Noticias:

No tienes permiso para ver los enlaces. Para poder verlos Registrate o Conectate.

Menú Principal

Premium Account system

Iniciado por Swarlog, Ago 03, 2025, 01:37 AM

Tema anterior - Siguiente tema

Swarlog

CitarCORE:

### Eclipse Workspace Patch 1.0
#P L2J_Server
diff --git dist/game/config/Custom.properties dist/game/config/Custom.properties
new file mode 100644
index 0000000..d32f5c6
--- /dev/null
+++ dist/game/config/Custom.properties
@@ -0,0 +1,33 @@
+# ---------------------------------------------------------------------------
+# Premium System (VIP)
+# ---------------------------------------------------------------------------
+# -Admins can manage subscriptions from main admin menu.
+# -Players can use .premium to view account related info.
+# -Caution: Premium rates multiply existing server rates.
+
+# Enable premium system.
+# Default: False
+EnablePremiumSystem = False
+
+# Xp rate for premium players.
+PremiumRateXp = 2
+
+# Sp rate for premium players.
+PremiumRateSp = 2
+
+# Drop chance for premium players.
+PremiumDeathDropChanceMultiplier = 2
+
+# Drop amount for premium players.
+PremiumDeathDropAmountMultiplier = 1
+
+# Spoil chance for premium players.
+PremiumCorpseDropChanceMultiplier = 2
+
+# Spoil amount for premium players.
+PremiumCorpseDropAmountMultiplier = 1
+
+# List of items affected by custom drop rate by id, used now for Adena rate too.
+# Usage: itemId1,multiplier1;itemId2,multiplier2;...
+PremiumDropChanceMultiplierByItemId = 57,2
+PremiumDropAmountMultiplierByItemId = 57,1
\ No newline at end of file
diff --git java/com/l2jserver/Config.java java/com/l2jserver/Config.java
index 796d027..0c68e8e 100644
--- java/com/l2jserver/Config.java
+++ java/com/l2jserver/Config.java
@@ -107,6 +107,7 @@
 	public static final String EMAIL_CONFIG_FILE = "./config/Email.properties";
 	public static final String CH_SIEGE_FILE = "./config/ConquerableHallSiege.properties";
 	public static final String GEODATA_FILE = "./config/GeoData.properties";
+	public static final String CUSTOM_FILE = "./config/Custom.properties";
 	// --------------------------------------------------
 	// L2J Variable Definitions
 	// --------------------------------------------------
@@ -416,6 +417,19 @@
 	public static int CLAN_LEVEL_11_REQUIREMENT;
 	public static boolean ALLOW_WYVERN_ALWAYS;
 	public static boolean ALLOW_WYVERN_DURING_SIEGE;
+	
+	// --------------------------------------------------
+	// Premium Account Settings
+	// --------------------------------------------------
+	public static boolean PREMIUM_SYSTEM_ENABLED;
+	public static float PREMIUM_RATE_XP;
+	public static float PREMIUM_RATE_SP;
+	public static float PREMIUM_RATE_DEATH_DROP_AMOUNT_MULTIPLIER;
+	public static float PREMIUM_RATE_CORPSE_DROP_AMOUNT_MULTIPLIER;
+	public static float PREMIUM_RATE_DEATH_DROP_CHANCE_MULTIPLIER;
+	public static float PREMIUM_RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
+	public static Map<Integer, Float> PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER;
+	public static Map<Integer, Float> PREMIUM_RATE_DROP_CHANCE_MULTIPLIER;
 	
 	// --------------------------------------------------
 	// General Settings
@@ -2496,6 +2510,71 @@
 			}
 			L2JMOD_ALLOW_CHANGE_PASSWORD = L2JModSettings.getBoolean("AllowChangePassword", false);
 			
+			// Load Custom Properties file (if exists)
+			final PropertiesParser CustomSettings = new PropertiesParser(CUSTOM_FILE);
+			PREMIUM_SYSTEM_ENABLED = CustomSettings.getBoolean("EnablePremiumSystem", false);
+			PREMIUM_RATE_XP = CustomSettings.getFloat("PremiumRateXp", 2);
+			PREMIUM_RATE_SP = CustomSettings.getFloat("PremiumRateSp", 2);
+			PREMIUM_RATE_DEATH_DROP_AMOUNT_MULTIPLIER = CustomSettings.getFloat("PremiumDeathDropAmountMultiplier", 1);
+			PREMIUM_RATE_CORPSE_DROP_AMOUNT_MULTIPLIER = CustomSettings.getFloat("PremiumCorpseDropAmountMultiplier", 1);
+			PREMIUM_RATE_DEATH_DROP_CHANCE_MULTIPLIER = CustomSettings.getFloat("PremiumDeathDropChanceMultiplier", 1);
+			PREMIUM_RATE_CORPSE_DROP_CHANCE_MULTIPLIER = CustomSettings.getFloat("PremiumCorpseDropChanceMultiplier", 1);
+			String[] premiumdropAmountMultiplier = CustomSettings.getString("PremiumDropAmountMultiplierByItemId", "").split(";");
+			PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER = new HashMap<>(premiumdropAmountMultiplier.length);
+			if (!premiumdropAmountMultiplier[0].isEmpty())
+			{
+				for (String item : premiumdropAmountMultiplier)
+				{
+					String[] itemSplit = item.split(",");
+					if (itemSplit.length != 2)
+					{
+						_log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumRateDropItemsById \"", item, "\""));
+					}
+					else
+					{
+						try
+						{
+							PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
+						}
+						catch (NumberFormatException nfe)
+						{
+							if (!item.isEmpty())
+							{
+								_log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumRateDropItemsById \"", item, "\""));
+							}
+						}
+					}
+				}
+			}
+			
+			String[] premiumdropChanceMultiplier = CustomSettings.getString("PremiumDropChanceMultiplierByItemId", "").split(";");
+			PREMIUM_RATE_DROP_CHANCE_MULTIPLIER = new HashMap<>(premiumdropChanceMultiplier.length);
+			if (!dropChanceMultiplier[0].isEmpty())
+			{
+				for (String item : premiumdropChanceMultiplier)
+				{
+					String[] itemSplit = item.split(",");
+					if (itemSplit.length != 2)
+					{
+						_log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumRateDropItemsById \"", item, "\""));
+					}
+					else
+					{
+						try
+						{
+							PREMIUM_RATE_DROP_CHANCE_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
+						}
+						catch (NumberFormatException nfe)
+						{
+							if (!item.isEmpty())
+							{
+								_log.warning(StringUtil.concat("Config.load(): invalid config property -> PremiumRateDropItemsById \"", item, "\""));
+							}
+						}
+					}
+				}
+			}
+			
 			// Load PvP L2Properties file (if exists)
 			final PropertiesParser PVPSettings = new PropertiesParser(PVP_CONFIG_FILE);
 			
diff --git java/com/l2jserver/gameserver/GameServer.java java/com/l2jserver/gameserver/GameServer.java
index 25de90c..d82feaf 100644
--- java/com/l2jserver/gameserver/GameServer.java
+++ java/com/l2jserver/gameserver/GameServer.java
@@ -112,6 +112,7 @@
 import com.l2jserver.gameserver.instancemanager.MapRegionManager;
 import com.l2jserver.gameserver.instancemanager.MercTicketManager;
 import com.l2jserver.gameserver.instancemanager.PetitionManager;
+import com.l2jserver.gameserver.instancemanager.PremiumManager;
 import com.l2jserver.gameserver.instancemanager.PunishmentManager;
 import com.l2jserver.gameserver.instancemanager.QuestManager;
 import com.l2jserver.gameserver.instancemanager.RaidBossPointsManager;
@@ -243,6 +244,11 @@
 		RaidBossPointsManager.getInstance();
 		PetDataTable.getInstance();
 		CharSummonTable.getInstance().init();
+		if (Config.PREMIUM_SYSTEM_ENABLED)
+		{
+			_log.info("PremiumManager: Premium system is enabled.");
+			PremiumManager.getInstance();
+		}
 		
 		printSection("Clans");
 		ClanTable.getInstance();
diff --git java/com/l2jserver/gameserver/instancemanager/PremiumManager.java java/com/l2jserver/gameserver/instancemanager/PremiumManager.java
new file mode 100644
index 0000000..3815641
--- /dev/null
+++ java/com/l2jserver/gameserver/instancemanager/PremiumManager.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2004-2015 L2J Server
+ * 
+ * This file is part of L2J Server.
+ * 
+ * L2J Server 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.
+ * 
+ * L2J Server 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.instancemanager;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Calendar;
+
+import com.l2jserver.Config;
+import com.l2jserver.L2DatabaseFactory;
+import com.l2jserver.gameserver.model.L2World;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+
+public class PremiumManager
+{
+	private long endDate = 0;
+	
+	public long getPremiumEndDate(String accountName)
+	{
+		try (Connection con = L2DatabaseFactory.getInstance().getConnection())
+		{
+			PreparedStatement statement = con.prepareStatement("SELECT premium_service,enddate FROM account_premium WHERE account_name=?");
+			statement.setString(1, accountName);
+			ResultSet rset = statement.executeQuery();
+			while (rset.next())
+			{
+				if (Config.PREMIUM_SYSTEM_ENABLED)
+				{
+					endDate = rset.getLong("enddate");
+					if (endDate <= System.currentTimeMillis())
+					{
+						endDate = 0;
+						removePremiumStatus(accountName);
+					}
+				}
+			}
+			statement.close();
+		}
+		catch (Exception e)
+		{
+		}
+		
+		return endDate;
+	}
+	
+	public void updatePremiumData(int months, String accountName)
+	{
+		long remainingTime = getPremiumEndDate(accountName);
+		if (remainingTime > 0)
+		{
+			remainingTime -= System.currentTimeMillis();
+		}
+		
+		try (Connection con = L2DatabaseFactory.getInstance().getConnection())
+		{
+			Calendar endDate = Calendar.getInstance();
+			endDate.setTimeInMillis(System.currentTimeMillis() + remainingTime);
+			endDate.set(Calendar.SECOND, 0);
+			endDate.add(Calendar.MONTH, months);
+			
+			PreparedStatement statement = con.prepareStatement("UPDATE account_premium SET premium_service=?,enddate=? WHERE account_name=?");
+			statement.setInt(1, 1);
+			statement.setLong(2, endDate.getTimeInMillis());
+			statement.setString(3, accountName);
+			statement.execute();
+			statement.close();
+		}
+		catch (SQLException e)
+		{
+		}
+		
+		for (L2PcInstance player : L2World.getInstance().getPlayers())
+		{
+			if (player.getAccountNamePlayer().equalsIgnoreCase(accountName))
+			{
+				player.setPremiumStatus(getPremiumEndDate(accountName) > 0 ? true : false);
+			}
+		}
+	}
+	
+	public void removePremiumStatus(String accountName)
+	{
+		// TODO: Add check if account exists. XD
+		try (Connection con = L2DatabaseFactory.getInstance().getConnection())
+		{
+			PreparedStatement statement = con.prepareStatement("INSERT INTO account_premium (account_name,premium_service,enddate) values(?,?,?) ON DUPLICATE KEY UPDATE premium_service = ?, enddate = ?");
+			statement.setString(1, accountName);
+			statement.setInt(2, 0);
+			statement.setLong(3, 0);
+			statement.setInt(4, 0);
+			statement.setLong(5, 0);
+			statement.execute();
+			statement.close();
+		}
+		catch (SQLException e)
+		{
+		}
+		
+		for (L2PcInstance player : L2World.getInstance().getPlayers())
+		{
+			if (player.getAccountNamePlayer().equalsIgnoreCase(accountName))
+			{
+				player.setPremiumStatus(false);
+			}
+		}
+	}
+	
+	public static final PremiumManager getInstance()
+	{
+		return SingletonHolder._instance;
+	}
+	
+	private static class SingletonHolder
+	{
+		protected static final PremiumManager _instance = new PremiumManager();
+	}
+}
\ No newline at end of file
diff --git java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
index 8762730..c13a577 100644
--- java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
+++ java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
@@ -108,6 +108,7 @@
 import com.l2jserver.gameserver.instancemanager.HandysBlockCheckerManager;
 import com.l2jserver.gameserver.instancemanager.InstanceManager;
 import com.l2jserver.gameserver.instancemanager.ItemsOnGroundManager;
+import com.l2jserver.gameserver.instancemanager.PremiumManager;
 import com.l2jserver.gameserver.instancemanager.PunishmentManager;
 import com.l2jserver.gameserver.instancemanager.QuestManager;
 import com.l2jserver.gameserver.instancemanager.SiegeManager;
@@ -354,6 +355,9 @@
 	private static final String UPDATE_CHARACTER = "UPDATE characters SET level=?,maxHp=?,curHp=?,maxCp=?,curCp=?,maxMp=?,curMp=?,face=?,hairStyle=?,hairColor=?,sex=?,heading=?,x=?,y=?,z=?,exp=?,expBeforeDeath=?,sp=?,karma=?,fame=?,pvpkills=?,pkkills=?,clanid=?,race=?,classid=?,deletetime=?,title=?,title_color=?,accesslevel=?,online=?,isin7sdungeon=?,clan_privs=?,wantspeace=?,base_class=?,onlinetime=?,newbie=?,nobless=?,power_grade=?,subpledge=?,lvl_joined_academy=?,apprentice=?,sponsor=?,clan_join_expiry_time=?,clan_create_expiry_time=?,char_name=?,death_penalty_level=?,bookmarkslot=?,vitality_points=?,language=? WHERE charId=?";
 	private static final String RESTORE_CHARACTER = "SELECT * FROM characters WHERE charId=?";
 	
+	// Character Premium System String Definitions:
+	private static final String RESTORE_PREMIUMSERVICE = "SELECT premium_service,enddate FROM account_premium WHERE account_name=?";
+	
 	// Character Teleport Bookmark:
 	private static final String INSERT_TP_BOOKMARK = "INSERT INTO character_tpbookmark (charId,Id,x,y,z,icon,tag,name) values (?,?,?,?,?,?,?,?)";
 	private static final String UPDATE_TP_BOOKMARK = "UPDATE character_tpbookmark SET icon=?,tag=?,name=? where charId=? AND Id=?";
@@ -554,6 +558,9 @@
 	
 	private boolean _noble = false;
 	private boolean _hero = false;
+	
+	/** Premium System */
+	private boolean _premiumStatus = false;
 	
 	/** The L2FolkInstance corresponding to the last Folk which one the player talked. */
 	private L2Npc _lastFolkNpc = null;
@@ -6774,6 +6781,7 @@
 					
 					player = new L2PcInstance(objectId, template, rset.getString("account_name"), app);
 					player.setName(rset.getString("char_name"));
+					restorePremiumSystemData(player, rset.getString("account_name"));
 					player._lastAccess = rset.getLong("lastAccess");
 					
 					player.getStat().setExp(rset.getLong("exp"));
@@ -13966,6 +13974,58 @@
 		return 0;
 	}
 	
+	public void setPremiumStatus(boolean premiumStatus)
+	{
+		_premiumStatus = premiumStatus;
+	}
+	
+	public boolean hasPremiumStatus()
+	{
+		return _premiumStatus;
+	}
+	
+	private static void restorePremiumSystemData(L2PcInstance player, String account)
+	{
+		boolean success = false;
+		try (Connection con = L2DatabaseFactory.getInstance().getConnection())
+		{
+			PreparedStatement statement = con.prepareStatement(RESTORE_PREMIUMSERVICE);
+			statement.setString(1, account);
+			ResultSet rset = statement.executeQuery();
+			while (rset.next())
+			{
+				success = true;
+				if (Config.PREMIUM_SYSTEM_ENABLED)
+				{
+					if (rset.getLong("enddate") <= System.currentTimeMillis())
+					{
+						PremiumManager.getInstance().removePremiumStatus(account);
+						player.setPremiumStatus(false);
+					}
+					else
+					{
+						player.setPremiumStatus(rset.getBoolean("premium_service"));
+					}
+				}
+				else
+				{
+					player.setPremiumStatus(false);
+				}
+			}
+			statement.close();
+		}
+		catch (Exception e)
+		{
+			_log.warning("Premium System: Could not restore premium system data for " + account + "." + e);
+			e.printStackTrace();
+		}
+		if (success == false)
+		{
+			PremiumManager.getInstance().removePremiumStatus(player.getAccountName());
+			player.setPremiumStatus(false);
+		}
+	}
+	
 	public void setLastPetitionGmName(String gmName)
 	{
 		_lastPetitionGmName = gmName;
diff --git java/com/l2jserver/gameserver/model/actor/stat/PcStat.java java/com/l2jserver/gameserver/model/actor/stat/PcStat.java
index 1f80731..1c4f46f 100644
--- java/com/l2jserver/gameserver/model/actor/stat/PcStat.java
+++ java/com/l2jserver/gameserver/model/actor/stat/PcStat.java
@@ -139,6 +139,12 @@
 		addToExp *= bonusExp;
 		addToSp *= bonusSp;
 		
+		if (activeChar.hasPremiumStatus())
+		{
+			addToExp *= Config.PREMIUM_RATE_XP;
+			addToSp *= Config.PREMIUM_RATE_SP;
+		}
+		
 		float ratioTakenByPlayer = 0;
 		
 		// if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now
diff --git java/com/l2jserver/gameserver/model/drops/CorpseDropItem.java java/com/l2jserver/gameserver/model/drops/CorpseDropItem.java
index a338f5a..d73f233 100644
--- java/com/l2jserver/gameserver/model/drops/CorpseDropItem.java
+++ java/com/l2jserver/gameserver/model/drops/CorpseDropItem.java
@@ -41,9 +41,9 @@
 	 * @see com.l2jserver.gameserver.model.drops.GeneralDropItem#getGlobalAmountMultiplier()
 	 */
 	@Override
-	protected double getGlobalAmountMultiplier()
+	protected double getGlobalAmountMultiplier(boolean isPremium)
 	{
-		return Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER;
+		return isPremium ? Config.PREMIUM_RATE_CORPSE_DROP_AMOUNT_MULTIPLIER * Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER : Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER;
 	}
 	
 	/*
@@ -51,8 +51,8 @@
 	 * @see com.l2jserver.gameserver.model.drops.GeneralDropItem#getGlobalChanceMultiplier()
 	 */
 	@Override
-	protected double getGlobalChanceMultiplier()
+	protected double getGlobalChanceMultiplier(boolean isPremium)
 	{
-		return Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
+		return isPremium ? Config.PREMIUM_RATE_CORPSE_DROP_CHANCE_MULTIPLIER * Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER : Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
 	}
 }
diff --git java/com/l2jserver/gameserver/model/drops/DeathDropItem.java java/com/l2jserver/gameserver/model/drops/DeathDropItem.java
index 5ffee75..c85a9e8 100644
--- java/com/l2jserver/gameserver/model/drops/DeathDropItem.java
+++ java/com/l2jserver/gameserver/model/drops/DeathDropItem.java
@@ -41,9 +41,9 @@
 	 * @see com.l2jserver.gameserver.model.drops.GeneralDropItem#getGlobalAmountMultiplier()
 	 */
 	@Override
-	protected double getGlobalAmountMultiplier()
+	protected double getGlobalAmountMultiplier(boolean isPremium)
 	{
-		return Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER;
+		return isPremium ? Config.PREMIUM_RATE_DEATH_DROP_AMOUNT_MULTIPLIER * Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER : Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER;
 	}
 	
 	/*
@@ -51,8 +51,8 @@
 	 * @see com.l2jserver.gameserver.model.drops.GeneralDropItem#getGlobalChanceMultiplier()
 	 */
 	@Override
-	protected double getGlobalChanceMultiplier()
+	protected double getGlobalChanceMultiplier(boolean isPremium)
 	{
-		return Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER;
+		return isPremium ? Config.PREMIUM_RATE_DEATH_DROP_CHANCE_MULTIPLIER * Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER : Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER;
 	}
 }
diff --git java/com/l2jserver/gameserver/model/drops/GeneralDropItem.java java/com/l2jserver/gameserver/model/drops/GeneralDropItem.java
index 34638ce..5e837e0 100644
--- java/com/l2jserver/gameserver/model/drops/GeneralDropItem.java
+++ java/com/l2jserver/gameserver/model/drops/GeneralDropItem.java
@@ -54,12 +54,12 @@
 		_chance = chance;
 	}
 	
-	protected double getGlobalChanceMultiplier()
+	protected double getGlobalChanceMultiplier(boolean isPremium)
 	{
 		return 1.;
 	}
 	
-	protected double getGlobalAmountMultiplier()
+	protected double getGlobalAmountMultiplier(boolean isPremium)
 	{
 		return 1.;
 	}
@@ -69,7 +69,29 @@
 		double multiplier = 1;
 		
 		// individual drop amount
-		Float individualDropAmountMultiplier = Config.RATE_DROP_AMOUNT_MULTIPLIER.get(getItemId());
+		Float individualDropAmountMultiplier = null;
+		if (killer.getActingPlayer().hasPremiumStatus())
+		{
+			final Float normalMultiplier = Config.RATE_DROP_AMOUNT_MULTIPLIER.get(getItemId());
+			final Float premiumMultiplier = Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(getItemId());
+			if ((normalMultiplier != null) && (premiumMultiplier != null))
+			{
+				individualDropAmountMultiplier = normalMultiplier * premiumMultiplier;
+			}
+			else if (normalMultiplier != null)
+			{
+				individualDropAmountMultiplier = normalMultiplier;
+			}
+			else if (premiumMultiplier != null)
+			{
+				individualDropAmountMultiplier = premiumMultiplier;
+			}
+		}
+		else
+		{
+			individualDropAmountMultiplier = Config.RATE_DROP_AMOUNT_MULTIPLIER.get(getItemId());
+		}
+		
 		if (individualDropAmountMultiplier != null)
 		{
 			// individual amount list multiplier
@@ -87,7 +109,7 @@
 			else
 			{
 				// drop type specific amount multiplier
-				multiplier *= getGlobalAmountMultiplier();
+				multiplier *= getGlobalAmountMultiplier(killer.getActingPlayer().hasPremiumStatus());
 			}
 		}
 		
@@ -169,7 +191,29 @@
 		double multiplier = 1;
 		
 		// individual drop chance
-		Float individualDropChanceMultiplier = Config.RATE_DROP_CHANCE_MULTIPLIER.get(getItemId());
+		Float individualDropChanceMultiplier = null;
+		if (killer.getActingPlayer().hasPremiumStatus())
+		{
+			final Float normalMultiplier = Config.RATE_DROP_CHANCE_MULTIPLIER.get(getItemId());
+			final Float premiumMultiplier = Config.PREMIUM_RATE_DROP_CHANCE_MULTIPLIER.get(getItemId());
+			if ((normalMultiplier != null) && (premiumMultiplier != null))
+			{
+				individualDropChanceMultiplier = normalMultiplier * premiumMultiplier;
+			}
+			else if (normalMultiplier != null)
+			{
+				individualDropChanceMultiplier = normalMultiplier;
+			}
+			else if (premiumMultiplier != null)
+			{
+				individualDropChanceMultiplier = premiumMultiplier;
+			}
+		}
+		else
+		{
+				individualDropChanceMultiplier = Config.RATE_DROP_CHANCE_MULTIPLIER.get(getItemId());
+		}
+		
 		if (individualDropChanceMultiplier != null)
 		{
 			multiplier *= individualDropChanceMultiplier;
@@ -183,7 +227,7 @@
 			}
 			else
 			{
-				multiplier *= getGlobalChanceMultiplier();
+				multiplier *= getGlobalChanceMultiplier(killer.getActingPlayer().hasPremiumStatus());
 			}
 		}
 		
diff --git java/com/l2jserver/gameserver/model/drops/GroupedCorpseDropItem.java java/com/l2jserver/gameserver/model/drops/GroupedCorpseDropItem.java
index 9e8df87..fe23b6b 100644
--- java/com/l2jserver/gameserver/model/drops/GroupedCorpseDropItem.java
+++ java/com/l2jserver/gameserver/model/drops/GroupedCorpseDropItem.java
@@ -38,8 +38,8 @@
 	 * @see com.l2jserver.gameserver.model.drops.GroupedGeneralDropItem#getGlobalChanceMultiplier()
 	 */
 	@Override
-	protected double getGlobalChanceMultiplier()
+	protected double getGlobalChanceMultiplier(boolean isPremium)
 	{
-		return Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
+		return isPremium ? Config.PREMIUM_RATE_CORPSE_DROP_CHANCE_MULTIPLIER * Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER : Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
 	}
 }
diff --git java/com/l2jserver/gameserver/model/drops/GroupedDeathDropItem.java java/com/l2jserver/gameserver/model/drops/GroupedDeathDropItem.java
index cb7f4bb..728f276 100644
--- java/com/l2jserver/gameserver/model/drops/GroupedDeathDropItem.java
+++ java/com/l2jserver/gameserver/model/drops/GroupedDeathDropItem.java
@@ -38,8 +38,8 @@
 	 * @see com.l2jserver.gameserver.model.drops.GroupedGeneralDropItem#getGlobalChanceMultiplier()
 	 */
 	@Override
-	protected double getGlobalChanceMultiplier()
+	protected double getGlobalChanceMultiplier(boolean isPremium)
 	{
-		return Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER;
+		return isPremium ? Config.PREMIUM_RATE_DEATH_DROP_CHANCE_MULTIPLIER * Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER : Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER;
 	}
 }
diff --git java/com/l2jserver/gameserver/model/drops/GroupedGeneralDropItem.java java/com/l2jserver/gameserver/model/drops/GroupedGeneralDropItem.java
index 79e9f78..044e85f 100644
--- java/com/l2jserver/gameserver/model/drops/GroupedGeneralDropItem.java
+++ java/com/l2jserver/gameserver/model/drops/GroupedGeneralDropItem.java
@@ -48,7 +48,7 @@
 		_chance = chance;
 	}
 	
-	protected double getGlobalChanceMultiplier()
+	protected double getGlobalChanceMultiplier(boolean isPremium)
 	{
 		return 1.;
 	}
@@ -75,7 +75,7 @@
 			final L2Item item = ItemTable.getInstance().getTemplate(gdi.getItemId());
 			if ((item == null) || !item.hasExImmediateEffect())
 			{
-				return getChance() * getGlobalChanceMultiplier();
+				return getChance() * getGlobalChanceMultiplier(killer.getActingPlayer().hasPremiumStatus());
 			}
 		}
 		
diff --git java/com/l2jserver/gameserver/model/itemcontainer/ItemContainer.java java/com/l2jserver/gameserver/model/itemcontainer/ItemContainer.java
index d4f7fcb..7a5632c 100644
--- java/com/l2jserver/gameserver/model/itemcontainer/ItemContainer.java
+++ java/com/l2jserver/gameserver/model/itemcontainer/ItemContainer.java
@@ -239,6 +239,10 @@
 			
 			// Updates database
 			float adenaRate = Config.RATE_DROP_AMOUNT_MULTIPLIER.getOrDefault(Inventory.ADENA_ID, 1f);
+			if (actor.hasPremiumStatus() && Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.containsKey(Inventory.ADENA_ID))
+			{
+				adenaRate *= Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(Inventory.ADENA_ID);
+			}
 			if ((item.getId() == Inventory.ADENA_ID) && (count < (10000 * adenaRate)))
 			{
 				// Small adena changes won't be saved to database all the time
@@ -291,6 +295,10 @@
 			// Updates database
 			// If Adena drop rate is not present it will be x1.
 			float adenaRate = Config.RATE_DROP_AMOUNT_MULTIPLIER.getOrDefault(Inventory.ADENA_ID, 1f);
+			if (actor.hasPremiumStatus() && Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.containsKey(Inventory.ADENA_ID))
+			{
+				adenaRate *= Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(Inventory.ADENA_ID);
+			}
 			if ((itemId == Inventory.ADENA_ID) && (count < (10000 * adenaRate)))
 			{
 				// Small adena changes won't be saved to database all the time

CitarDATA:

### Eclipse Workspace Patch 1.0
#P L2J_DataPack
diff --git dist/game/config/adminCommands.xml dist/game/config/adminCommands.xml
index d4fe593..69f2c4a 100644
--- dist/game/config/adminCommands.xml
+++ dist/game/config/adminCommands.xml
@@ -420,6 +420,14 @@
 	<admin command="admin_untransform" accessLevel="7" />
 	<admin command="admin_transform_menu" accessLevel="7" />
 
+	<!-- PREMIUM SYSTEM -->
+	<admin command="admin_premium_menu" accessLevel="7" />
+	<admin command="admin_premium_add1" accessLevel="7" confirmDlg="true" />
+	<admin command="admin_premium_add2" accessLevel="7" confirmDlg="true" />
+	<admin command="admin_premium_add3" accessLevel="7" confirmDlg="true" />
+	<admin command="admin_premium_info" accessLevel="7" />
+	<admin command="admin_premium_remove" accessLevel="7" confirmDlg="true" />
+
 	<!-- ADMIN QUEST -->
 	<admin command="admin_quest_reload" accessLevel="7" />
 	<admin command="admin_script_load" accessLevel="7" />
diff --git dist/game/data/html/admin/main_menu.htm dist/game/data/html/admin/main_menu.htm
index 1807a16..714f9fc 100644
--- dist/game/data/html/admin/main_menu.htm
+++ dist/game/data/html/admin/main_menu.htm
@@ -28,6 +28,7 @@
 <td><button value="goSpawn" action="bypass -h admin_list_spawns $qbox 1" width=65 height=21 back="L2UI_CT1.Button_DF_Down" fore="L2UI_CT1.Button_DF"></td>
 </tr><tr>
 <td><button value="Scan" action="bypass -h admin_scan $qbox" width=65 height=21 back="L2UI_CT1.Button_DF_Down" fore="L2UI_CT1.Button_DF"></td>
+<td><button value="Premium" action="bypass -h admin_premium_menu" width=65 height=21 back="L2UI_CT1.Button_DF_Down" fore="L2UI_CT1.Button_DF"></td>
 </tr>
 </table>
 <br>
diff --git dist/game/data/html/admin/premium_menu.htm dist/game/data/html/admin/premium_menu.htm
new file mode 100644
index 0000000..ce256c6
--- /dev/null
+++ dist/game/data/html/admin/premium_menu.htm
@@ -0,0 +1,16 @@
+<html><title>Premium Service Menu</title><body>
+<center>
+<br>
+<font color="LEVEL">Premium Service Menu</font><br>
+<br>
+Enter Account Name:<br>
+<edit var="acc_name" width=200>
+<br>
+<button value="Add 1 month Premium" action="bypass -h admin_premium_add1 $acc_name" width=200 height=25 back="L2UI_ct1.button_df" fore="L2UI_ct1.button_df">
+<button value="Add 2 months Premium" action="bypass -h admin_premium_add2 $acc_name" width=200 height=25 back="L2UI_ct1.button_df" fore="L2UI_ct1.button_df">
+<button value="Add 3 months Premium" action="bypass -h admin_premium_add3 $acc_name" width=200 height=25 back="L2UI_ct1.button_df" fore="L2UI_ct1.button_df">
+<br>
+<button value="View Premium Info" action="bypass -h admin_premium_info $acc_name" width=200 height=25 back="L2UI_ct1.button_df" fore="L2UI_ct1.button_df">
+<button value="Remove Premium" action="bypass -h admin_premium_remove $acc_name" width=200 height=25 back="L2UI_ct1.button_df" fore="L2UI_ct1.button_df">
+</center>
+</body></html>
\ No newline at end of file
diff --git dist/game/data/scripts/handlers/MasterHandler.java dist/game/data/scripts/handlers/MasterHandler.java
index 38a3e91..70dbca6 100644
--- dist/game/data/scripts/handlers/MasterHandler.java
+++ dist/game/data/scripts/handlers/MasterHandler.java
@@ -83,6 +83,7 @@
 import handlers.admincommandhandlers.AdminPetition;
 import handlers.admincommandhandlers.AdminPledge;
 import handlers.admincommandhandlers.AdminPolymorph;
+import handlers.admincommandhandlers.AdminPremium;
 import handlers.admincommandhandlers.AdminPunishment;
 import handlers.admincommandhandlers.AdminQuest;
 import handlers.admincommandhandlers.AdminReload;
@@ -253,6 +254,7 @@
 import handlers.voicedcommandhandlers.ChatAdmin;
 import handlers.voicedcommandhandlers.Debug;
 import handlers.voicedcommandhandlers.Lang;
+import handlers.voicedcommandhandlers.Premium;
 import handlers.voicedcommandhandlers.StatsVCmd;
 import handlers.voicedcommandhandlers.Wedding;
 
@@ -377,6 +379,7 @@
 			AdminPForge.class,
 			AdminPledge.class,
 			AdminPolymorph.class,
+			AdminPremium.class,
 			AdminPunishment.class,
 			AdminQuest.class,
 			AdminReload.class,
@@ -532,6 +535,7 @@
 			(Config.L2JMOD_MULTILANG_ENABLE && Config.L2JMOD_MULTILANG_VOICED_ALLOW ? Lang.class : null),
 			(Config.L2JMOD_DEBUG_VOICE_COMMAND ? Debug.class : null),
 			(Config.L2JMOD_ALLOW_CHANGE_PASSWORD ? ChangePassword.class : null),
+			(Config.PREMIUM_SYSTEM_ENABLED ? Premium.class : null),
 		},
 		{
 			// Target Handlers
diff --git dist/game/data/scripts/handlers/admincommandhandlers/AdminPremium.java dist/game/data/scripts/handlers/admincommandhandlers/AdminPremium.java
new file mode 100644
index 0000000..8a0c1ce
--- /dev/null
+++ dist/game/data/scripts/handlers/admincommandhandlers/AdminPremium.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2004-2015 L2J DataPack
+ * 
+ * This file is part of L2J DataPack.
+ * 
+ * L2J DataPack 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.
+ * 
+ * L2J DataPack 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 handlers.admincommandhandlers;
+
+import java.text.SimpleDateFormat;
+
+import com.l2jserver.gameserver.handler.IAdminCommandHandler;
+import com.l2jserver.gameserver.instancemanager.PremiumManager;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+
+public class AdminPremium implements IAdminCommandHandler
+{
+	private static final String[] ADMIN_COMMANDS =
+	{
+		"admin_premium_menu",
+		"admin_premium_add1",
+		"admin_premium_add2",
+		"admin_premium_add3",
+		"admin_premium_info",
+		"admin_premium_remove"
+	};
+	
+	@Override
+	public boolean useAdminCommand(String command, L2PcInstance activeChar)
+	{
+		if (command.equals("admin_premium_menu"))
+		{
+			AdminHtml.showAdminHtml(activeChar, "premium_menu.htm");
+		}
+		else if (command.startsWith("admin_premium_add1"))
+		{
+			try
+			{
+				String val = command.substring(19);
+				addPremiumStatus(activeChar, 1, val);
+			}
+			catch (StringIndexOutOfBoundsException e)
+			{
+				activeChar.sendMessage("Error.");
+			}
+		}
+		else if (command.startsWith("admin_premium_add2"))
+		{
+			try
+			{
+				String val = command.substring(19);
+				addPremiumStatus(activeChar, 2, val);
+			}
+			catch (StringIndexOutOfBoundsException e)
+			{
+				activeChar.sendMessage("Error.");
+			}
+		}
+		else if (command.startsWith("admin_premium_add3"))
+		{
+			try
+			{
+				String val = command.substring(19);
+				addPremiumStatus(activeChar, 3, val);
+			}
+			catch (StringIndexOutOfBoundsException e)
+			{
+				activeChar.sendMessage("Error.");
+			}
+		}
+		else if (command.startsWith("admin_premium_info"))
+		{
+			try
+			{
+				String val = command.substring(19);
+				viewPremiumInfo(activeChar, val);
+			}
+			catch (StringIndexOutOfBoundsException e)
+			{
+				activeChar.sendMessage("Error.");
+			}
+		}
+		else if (command.startsWith("admin_premium_remove"))
+		{
+			try
+			{
+				String val = command.substring(21);
+				removePremium(activeChar, val);
+			}
+			catch (StringIndexOutOfBoundsException e)
+			{
+				activeChar.sendMessage("Error.");
+			}
+		}
+		return true;
+	}
+	
+	private void addPremiumStatus(L2PcInstance admin, int months, String accountName)
+	{
+		// TODO: Add check if account exists XD
+		PremiumManager.getInstance().updatePremiumData(months, accountName);
+		final SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm");
+		final long endDate = PremiumManager.getInstance().getPremiumEndDate(accountName);
+		admin.sendMessage("Account " + accountName + " will now have premium status until " + String.valueOf(format.format(endDate)) + ".");
+	}
+	
+	private void viewPremiumInfo(L2PcInstance admin, String accountName)
+	{
+		if (PremiumManager.getInstance().getPremiumEndDate(accountName) > 0)
+		{
+			final SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm");
+			final long endDate = PremiumManager.getInstance().getPremiumEndDate(accountName);
+			admin.sendMessage("Account " + accountName + " has premium status until " + String.valueOf(format.format(endDate)) + ".");
+		}
+		else
+		{
+			admin.sendMessage("Account " + accountName + " has no premium status.");
+		}
+	}
+	
+	private void removePremium(L2PcInstance admin, String accountName)
+	{
+		if (PremiumManager.getInstance().getPremiumEndDate(accountName) > 0)
+		{
+			PremiumManager.getInstance().removePremiumStatus(accountName);
+			admin.sendMessage("Account " + accountName + " has no longer premium status.");
+		}
+		else
+		{
+			admin.sendMessage("Account " + accountName + " has no premium status.");
+		}
+	}
+	
+	@Override
+	public String[] getAdminCommandList()
+	{
+		return ADMIN_COMMANDS;
+	}
+}
\ No newline at end of file
diff --git dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java
new file mode 100644
index 0000000..f5ae68d
--- /dev/null
+++ dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2004-2015 L2J DataPack
+ * 
+ * This file is part of L2J DataPack.
+ * 
+ * L2J DataPack 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.
+ * 
+ * L2J DataPack 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 handlers.voicedcommandhandlers;
+
+import java.text.SimpleDateFormat;
+
+import com.l2jserver.Config;
+import com.l2jserver.gameserver.handler.IVoicedCommandHandler;
+import com.l2jserver.gameserver.instancemanager.PremiumManager;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
+
+public class Premium implements IVoicedCommandHandler
+{
+	private static final String[] VOICED_COMMANDS =
+	{
+		"premium"
+	};
+	
+	@Override
+	public boolean useVoicedCommand(String command, L2PcInstance activeChar, String target)
+	{
+		if (command.startsWith("premium") && Config.PREMIUM_SYSTEM_ENABLED)
+		{
+			SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm");
+			long endDate = PremiumManager.getInstance().getPremiumEndDate(activeChar.getAccountName());
+			if (endDate == 0)
+			{
+				NpcHtmlMessage msg = new NpcHtmlMessage(5);
+				StringBuilder html = new StringBuilder("<html><body><title>Account Details</title><center>");
+				html.append("<table>");
+				html.append("<tr><td><center>Account Status: <font color=\"LEVEL\">Normal<br></font></td></tr>");
+				html.append("<tr><td>Rate XP: <font color=\"LEVEL\"> x" + Config.RATE_XP + "<br1></font></td></tr>");
+				html.append("<tr><td>Rate SP: <font color=\"LEVEL\"> x" + Config.RATE_SP + "<br1></font></td></tr>");
+				html.append("<tr><td>Drop Chance: <font color=\"LEVEL\"> x" + Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER + "<br1></font></td></tr><br>");
+				html.append("<tr><td>Drop Amount: <font color=\"LEVEL\"> x" + Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER + "<br1></font></td></tr><br>");
+				html.append("<tr><td>Spoil Chance: <font color=\"LEVEL\"> x" + Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER + "<br1></font></td></tr><br>");
+				html.append("<tr><td>Spoil Amount: <font color=\"LEVEL\"> x" + Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER + "<br><br></font></td></tr><br>");
+				html.append("<tr><td><center>Premium Info & Rules<br></td></tr>");
+				html.append("<tr><td>Rate XP: <font color=\"LEVEL\"> x" + (Config.RATE_XP * Config.PREMIUM_RATE_XP) + "<br1></font></td></tr>");
+				html.append("<tr><td>Rate SP: <font color=\"LEVEL\"> x" + (Config.RATE_SP * Config.PREMIUM_RATE_SP) + "<br1></font></td></tr>");
+				html.append("<tr><td>Drop Chance: <font color=\"LEVEL\"> x" + (Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER * Config.PREMIUM_RATE_DEATH_DROP_CHANCE_MULTIPLIER) + "<br1></font></td></tr>");
+				html.append("<tr><td>Drop Amount: <font color=\"LEVEL\"> x" + (Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_DEATH_DROP_AMOUNT_MULTIPLIER) + "<br1></font></td></tr>");
+				html.append("<tr><td>Spoil Chance: <font color=\"LEVEL\"> x" + (Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER * Config.PREMIUM_RATE_CORPSE_DROP_CHANCE_MULTIPLIER) + "<br1></font></td></tr>");
+				html.append("<tr><td>Spoil Amount: <font color=\"LEVEL\"> x" + (Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_CORPSE_DROP_AMOUNT_MULTIPLIER) + "<br1></font></td></tr>");
+				html.append("<tr><td> <font color=\"70FFCA\">1. Premium benefits CAN NOT BE TRANSFERED.<br1></font></td></tr>");
+				html.append("<tr><td> <font color=\"70FFCA\">2. Premium does not effect party members.<br1></font></td></tr>");
+				html.append("<tr><td> <font color=\"70FFCA\">3. Premium benefits effect ALL characters in same account.</font></td></tr>");
+				html.append("</table>");
+				html.append("</center></body></html>");
+				msg.setHtml(html.toString());
+				activeChar.sendPacket(msg);
+			}
+			else
+			{
+				NpcHtmlMessage msg = new NpcHtmlMessage(5);
+				StringBuilder html = new StringBuilder("<html><body><title>Premium Account Details</title><center>");
+				html.append("<table>");
+				html.append("<tr><td><center>Account Status: <font color=\"LEVEL\">Premium<br></font></td></tr>");
+				html.append("<tr><td>Rate XP: <font color=\"LEVEL\">x" + (Config.RATE_XP * Config.PREMIUM_RATE_XP) + " <br1></font></td></tr>");
+				html.append("<tr><td>Rate SP: <font color=\"LEVEL\">x" + (Config.RATE_SP * Config.PREMIUM_RATE_SP) + "  <br1></font></td></tr>");
+				html.append("<tr><td>Drop Chance: <font color=\"LEVEL\">x" + (Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER * Config.PREMIUM_RATE_DEATH_DROP_CHANCE_MULTIPLIER) + " <br1></font></td></tr>");
+				html.append("<tr><td>Drop Amount: <font color=\"LEVEL\">x" + (Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_DEATH_DROP_AMOUNT_MULTIPLIER) + " <br1></font></td></tr>");
+				html.append("<tr><td>Spoil Chance: <font color=\"LEVEL\">x" + (Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER * Config.PREMIUM_RATE_CORPSE_DROP_CHANCE_MULTIPLIER) + " <br1></font></td></tr>");
+				html.append("<tr><td>Spoil Amount: <font color=\"LEVEL\">x" + (Config.RATE_CORPSE_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_CORPSE_DROP_AMOUNT_MULTIPLIER) + " <br1></font></td></tr>");
+				html.append("<tr><td>Expires: <font color=\"00A5FF\">" + String.valueOf(format.format(endDate)) + "</font></td></tr>");
+				html.append("<tr><td>Current Date: <font color=\"70FFCA\">" + String.valueOf(format.format(System.currentTimeMillis())) + "<br><br></font></td></tr>");
+				html.append("<tr><td><center>Premium Info & Rules<br></center></td></tr>");
+				html.append("<tr><td><font color=\"70FFCA\">1. Premium accounts CAN NOT BE TRANSFERED.<br1></font></td></tr>");
+				html.append("<tr><td><font color=\"70FFCA\">2. Premium does not effect party members.<br1></font></td></tr>");
+				html.append("<tr><td><font color=\"70FFCA\">3. Premium account effects ALL characters in same account.<br><br><br></font></td></tr>");
+				html.append("<tr><td><center>Thank you for supporting our server.</td></tr>");
+				html.append("</table>");
+				html.append("</center></body></html>");
+				msg.setHtml(html.toString());
+				activeChar.sendPacket(msg);
+			}
+		}
+		else
+		{
+			return false;
+		}
+		return true;
+	}
+	
+	@Override
+	public String[] getVoicedCommandList()
+	{
+		return VOICED_COMMANDS;
+	}
+}
\ No newline at end of file
diff --git dist/sql/game/account_premium.sql dist/sql/game/account_premium.sql
new file mode 100644
index 0000000..ce5aa62
--- /dev/null
+++ dist/sql/game/account_premium.sql
@@ -0,0 +1,7 @@
+DROP TABLE IF EXISTS `account_premium`;
+CREATE TABLE `account_premium` (
+  `account_name` varchar(45) NOT NULL DEFAULT '',
+  `premium_service` int(1) NOT NULL DEFAULT '0',
+  `enddate` decimal(20,0) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`account_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
\ No newline at end of file
diff --git dist/tools/gs_cleanup.sql dist/tools/gs_cleanup.sql
index 7e29166..844a143 100644
--- dist/tools/gs_cleanup.sql
+++ dist/tools/gs_cleanup.sql
@@ -8,6 +8,7 @@
 
 DROP TABLE IF EXISTS 
 account_gsdata,
+account_premium,
 airships,
 auction,
 auction_bid,

Creditos: NetVirus , sam.jr , Annu.
Actualizado: PoRnosJH y maneco2