U3Games
Games | Desarrollo & Soporte => L2 | Sección de Servidores => Lineage => L2 | Implementaciones => Mensaje iniciado por: Swarlog en Ago 03, 2025, 01:41 AM
CitarCORE:
diff --git a/dist/game/config/Premium.ini b/dist/game/config/Premium.ini
new file mode 100644
index 0000000..bf635ba
--- /dev/null
+++ b/dist/game/config/Premium.ini
@@ -0,0 +1,18 @@
+EnablePremiumSystem = True
+
+# Premium Exp Rates
+PremiumRateXp = 2
+
+# Premium SP Rates
+PremiumRateSp = 2
+
+# Premium Drop Chance Rates
+PremiumRateDropChance = 1
+
+# Premium Drop Amount Rates
+PremiumRateDropAmount = 2
+
+# List of items affected by premium drop rate by id, used now for Adena rate too.
+# Usage: itemId1,multiplier1;itemId2,multiplier2;...
+PremiumDropChanceMultiplierByItemId = 57,1
+PremiumDropAmountMultiplierByItemId = 57,2
diff --git a/src/main/java/com/l2jserver/Config.java b/src/main/java/com/l2jserver/Config.java
index cbc9f0b..a9824a0 100644
--- a/src/main/java/com/l2jserver/Config.java
+++ b/src/main/java/com/l2jserver/Config.java
@@ -108,6 +108,8 @@
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 PREMIUM_CONFIG_FILE = "./config/Premium.ini";
+
// --------------------------------------------------
// L2J Variable Definitions
// --------------------------------------------------
@@ -774,6 +780,18 @@
public static int L2JMOD_DUALBOX_CHECK_MAX_L2EVENT_PARTICIPANTS_PER_IP;
public static Map<Integer, Integer> L2JMOD_DUALBOX_CHECK_WHITELIST;
public static boolean L2JMOD_ALLOW_CHANGE_PASSWORD;
+
+ // --------------------------------------------------
+ // Premium Settings
+ // --------------------------------------------------
+ public static boolean PREMIUM_SYSTEM_ENABLED;
+ public static float PREMIUM_RATE_XP;
+ public static float PREMIUM_RATE_SP;
+ public static float PREMIUM_RATE_DROP_CHANCE;
+ public static float PREMIUM_RATE_DROP_AMOUNT;
+ public static Map<Integer, Float> PREMIUM_RATE_DROP_CHANCE_MULTIPLIER;
+ public static Map<Integer, Float> PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER;
+
// --------------------------------------------------
// NPC Settings
// --------------------------------------------------
@@ -2042,6 +2065,68 @@
DROP_ITEM_MAX_LEVEL_DIFFERENCE = NPC.getInt("DropItemMaxLevelDifference", 10);
DROP_ITEM_MIN_LEVEL_GAP_CHANCE = NPC.getDouble("DropItemMinLevelGapChance", 10);
+ // Premium
+ final PropertiesParser PremiumSettings = new PropertiesParser(PREMIUM_CONFIG_FILE);
+ PREMIUM_SYSTEM_ENABLED = PremiumSettings.getBoolean("EnablePremiumSystem", false);
+ PREMIUM_RATE_XP = PremiumSettings.getFloat("PremiumRateXp", 2);
+ PREMIUM_RATE_SP = PremiumSettings.getFloat("PremiumRateSp", 2);
+ PREMIUM_RATE_DROP_CHANCE = PremiumSettings.getFloat("PremiumRateDropChance", 1);
+ PREMIUM_RATE_DROP_AMOUNT = PremiumSettings.getFloat("PremiumRateDropAmount", 2);
+ String[] premiumDropChanceMultiplier = PremiumSettings.getString("PremiumDropChanceMultiplierByItemId", "").split(";");
+ PREMIUM_RATE_DROP_CHANCE_MULTIPLIER = new HashMap<>(premiumDropChanceMultiplier.length);
+ if (!premiumDropChanceMultiplier[0].isEmpty())
+ {
+ for (String item : premiumDropChanceMultiplier)
+ {
+ String[] itemSplit = item.split(",");
+ if (itemSplit.length != 2)
+ {
+ _log.warn(StringUtil.concat("Config.load(): invalid config property -> PremiumDropChanceMultiplierByItemId \"", item, "\""));
+ }
+ else
+ {
+ try
+ {
+ PREMIUM_RATE_DROP_CHANCE_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
+ }
+ catch (NumberFormatException nfe)
+ {
+ if (!item.isEmpty())
+ {
+ _log.warn(StringUtil.concat("Config.load(): invalid config property -> PremiumDropChanceMultiplierByItemId \"", item, "\""));
+ }
+ }
+ }
+ }
+ }
+ String[] premiumDropAmountMultiplier = PremiumSettings.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.warn(StringUtil.concat("Config.load(): invalid config property -> PremiumDropAmountMultiplierByItemId \"", item, "\""));
+ }
+ else
+ {
+ try
+ {
+ PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.put(Integer.valueOf(itemSplit[0]), Float.valueOf(itemSplit[1]));
+ }
+ catch (NumberFormatException nfe)
+ {
+ if (!item.isEmpty())
+ {
+ _log.warn(StringUtil.concat("Config.load(): invalid config property -> PremiumDropAmountMultiplierByItemId \"", item, "\""));
+ }
+ }
+ }
+ }
+ }
+
// Load Rates L2Properties file (if exists)
final PropertiesParser RatesSettings = new PropertiesParser(RATES_CONFIG_FILE);
diff --git a/src/main/java/com/l2jserver/gameserver/GameServer.java b/src/main/java/com/l2jserver/gameserver/GameServer.java
index c29f23e..2a7d04d 100644
--- a/src/main/java/com/l2jserver/gameserver/GameServer.java
+++ b/src/main/java/com/l2jserver/gameserver/GameServer.java
@@ -114,6 +115,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;
@@ -231,6 +234,12 @@
PetDataTable.getInstance();
CharSummonTable.getInstance().init();
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ _log.info("Premium System: Premium System is turned ON");
+ PremiumManager.getInstance();
+ }
+
printSection("Clans");
ClanTable.getInstance();
CHSiegeManager.getInstance();
diff --git a/src/main/java/com/l2jserver/gameserver/engines/DocumentParser.java b/src/main/java/com/l2jserver/gameserver/engines/DocumentParser.java
new file mode 100644
index 0000000..213d0e6
--- /dev/null
+++ b/src/main/java/com/l2jserver/gameserver/engines/DocumentParser.java
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2004-2014 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.engines;
+
+import java.io.File;
+import java.io.FileFilter;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXParseException;
+
+import com.l2jserver.Config;
+import com.l2jserver.util.file.filter.XMLFilter;
+
+/**
+ * Abstract class for XML parsers.<br>
+ * It's in <i>beta</i> state, so it's expected to change over time.
+ * @author Zoey76
+ */
+public abstract class DocumentParser
+{
+ protected final Logger _log = LoggerFactory.getLogger(getClass().getName());
+
+ private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
+ private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
+
+ private static final XMLFilter xmlFilter = new XMLFilter();
+
+ private File _currentFile;
+
+ private Document _currentDocument;
+
+ private FileFilter _currentFilter = null;
+
+ /**
+ * This method can be used to load/reload the data.<br>
+ * It's highly recommended to clear the data storage, either the list or map.
+ */
+ public abstract void load();
+
+ /**
+ * Wrapper for {@link #parseFile(File)} method.
+ * @param path the relative path to the datapack root of the XML file to parse.
+ */
+ protected void parseDatapackFile(String path)
+ {
+ parseFile(new File(Config.DATAPACK_ROOT, path));
+ }
+
+ /**
+ * Parses a single XML file.<br>
+ * If the file was successfully parsed, call {@link #parseDocument(Document)} for the parsed document.<br>
+ * <b>Validation is enforced.</b>
+ * @param f the XML file to parse.
+ */
+ protected void parseFile(File f)
+ {
+ if (!getCurrentFileFilter().accept(f))
+ {
+ _log.warn(getClass().getSimpleName() + ": Could not parse " + f.getName() + " is not a file or it doesn't exist!");
+ return;
+ }
+
+ final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(true);
+ dbf.setIgnoringComments(true);
+ _currentDocument = null;
+ _currentFile = f;
+ try
+ {
+ dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
+ final DocumentBuilder db = dbf.newDocumentBuilder();
+ db.setErrorHandler(new XMLErrorHandler());
+ _currentDocument = db.parse(f);
+ }
+ catch (Exception e)
+ {
+ _log.warn(getClass().getSimpleName() + ": Could not parse " + f.getName() + " file: " + e.getMessage());
+ return;
+ }
+ parseDocument();
+ }
+
+ /**
+ * Gets the current file.
+ * @return the current file
+ */
+ public File getCurrentFile()
+ {
+ return _currentFile;
+ }
+
+ /**
+ * Gets the current document.
+ * @return the current document
+ */
+ protected Document getCurrentDocument()
+ {
+ return _currentDocument;
+ }
+
+ /**
+ * Wrapper for {@link #parseDirectory(File, boolean)}.
+ * @param file the path to the directory where the XML files are.
+ * @return {@code false} if it fails to find the directory, {@code true} otherwise.
+ */
+ protected boolean parseDirectory(File file)
+ {
+ return parseDirectory(file, false);
+ }
+
+ /**
+ * Wrapper for {@link #parseDirectory(File, boolean)}.
+ * @param path the path to the directory where the XML files are.
+ * @return {@code false} if it fails to find the directory, {@code true} otherwise.
+ */
+ protected boolean parseDirectory(String path)
+ {
+ return parseDirectory(new File(path), false);
+ }
+
+ /**
+ * Wrapper for {@link #parseDirectory(File, boolean)}.
+ * @param path the path to the directory where the XML files are.
+ * @param recursive parses all sub folders if there is.
+ * @return {@code false} if it fails to find the directory, {@code true} otherwise.
+ */
+ protected boolean parseDirectory(String path, boolean recursive)
+ {
+ return parseDirectory(new File(path), recursive);
+ }
+
+ /**
+ * Loads all XML files from {@code path} and calls {@link #parseFile(File)} for each one of them.
+ * @param dir the directory object to scan.
+ * @param recursive parses all sub folders if there is.
+ * @return {@code false} if it fails to find the directory, {@code true} otherwise.
+ */
+ protected boolean parseDirectory(File dir, boolean recursive)
+ {
+ if (!dir.exists())
+ {
+ _log.warn(getClass().getSimpleName() + ": Folder " + dir.getAbsolutePath() + " doesn't exist!");
+ return false;
+ }
+
+ final File[] listOfFiles = dir.listFiles();
+ for (File f : listOfFiles)
+ {
+ if (recursive && f.isDirectory())
+ {
+ parseDirectory(f, recursive);
+ }
+ else if (getCurrentFileFilter().accept(f))
+ {
+ parseFile(f);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Wrapper for {@link #parseDirectory(File, boolean)}.
+ * @param path the path to the directory where the XML files are
+ * @param recursive parses all sub folders if there is
+ * @return {@code false} if it fails to find the directory, {@code true} otherwise
+ */
+ protected boolean parseDatapackDirectory(String path, boolean recursive)
+ {
+ return parseDirectory(new File(Config.DATAPACK_ROOT, path), recursive);
+ }
+
+ /**
+ * Overridable method that could parse a custom document.<br>
+ * @param doc the document to parse.
+ */
+ protected void parseDocument(Document doc)
+ {
+ // Do nothing, to be overridden in sub-classes.
+ }
+
+ /**
+ * Abstract method that when implemented will parse the current document.<br>
+ * Is expected to be call from {@link #parseFile(File)}.
+ */
+ protected abstract void parseDocument();
+
+ protected Boolean parseBoolean(Node node, Boolean defaultValue)
+ {
+ return node != null ? Boolean.valueOf(node.getNodeValue()) : defaultValue;
+ }
+
+ protected Boolean parseBoolean(Node node)
+ {
+ return parseBoolean(node, null);
+ }
+
+ protected Boolean parseBoolean(NamedNodeMap attrs, String name)
+ {
+ return parseBoolean(attrs.getNamedItem(name));
+ }
+
+ protected Boolean parseBoolean(NamedNodeMap attrs, String name, Boolean defaultValue)
+ {
+ return parseBoolean(attrs.getNamedItem(name), defaultValue);
+ }
+
+ protected Byte parseByte(Node node, Byte defaultValue)
+ {
+ return node != null ? Byte.valueOf(node.getNodeValue()) : defaultValue;
+ }
+
+ protected Byte parseByte(Node node)
+ {
+ return parseByte(node, null);
+ }
+
+ protected Byte parseByte(NamedNodeMap attrs, String name)
+ {
+ return parseByte(attrs.getNamedItem(name));
+ }
+
+ protected Byte parseByte(NamedNodeMap attrs, String name, Byte defaultValue)
+ {
+ return parseByte(attrs.getNamedItem(name), defaultValue);
+ }
+
+ protected Short parseShort(Node node, Short defaultValue)
+ {
+ return node != null ? Short.valueOf(node.getNodeValue()) : defaultValue;
+ }
+
+ protected Short parseShort(Node node)
+ {
+ return parseShort(node, null);
+ }
+
+ protected Short parseShort(NamedNodeMap attrs, String name)
+ {
+ return parseShort(attrs.getNamedItem(name));
+ }
+
+ protected Short parseShort(NamedNodeMap attrs, String name, Short defaultValue)
+ {
+ return parseShort(attrs.getNamedItem(name), defaultValue);
+ }
+
+ protected Integer parseInteger(Node node, Integer defaultValue)
+ {
+ return node != null ? Integer.valueOf(node.getNodeValue()) : defaultValue;
+ }
+
+ protected Integer parseInteger(Node node)
+ {
+ return parseInteger(node, null);
+ }
+
+ protected Integer parseInteger(NamedNodeMap attrs, String name)
+ {
+ return parseInteger(attrs.getNamedItem(name));
+ }
+
+ protected Integer parseInteger(NamedNodeMap attrs, String name, Integer defaultValue)
+ {
+ return parseInteger(attrs.getNamedItem(name), defaultValue);
+ }
+
+ protected Long parseLong(Node node, Long defaultValue)
+ {
+ return node != null ? Long.valueOf(node.getNodeValue()) : defaultValue;
+ }
+
+ protected Long parseLong(Node node)
+ {
+ return parseLong(node, null);
+ }
+
+ protected Long parseLong(NamedNodeMap attrs, String name)
+ {
+ return parseLong(attrs.getNamedItem(name));
+ }
+
+ protected Long parseLong(NamedNodeMap attrs, String name, Long defaultValue)
+ {
+ return parseLong(attrs.getNamedItem(name), defaultValue);
+ }
+
+ protected Float parseFloat(Node node, Float defaultValue)
+ {
+ return node != null ? Float.valueOf(node.getNodeValue()) : defaultValue;
+ }
+
+ protected Float parseFloat(Node node)
+ {
+ return parseFloat(node, null);
+ }
+
+ protected Float parseFloat(NamedNodeMap attrs, String name)
+ {
+ return parseFloat(attrs.getNamedItem(name));
+ }
+
+ protected Float parseFloat(NamedNodeMap attrs, String name, Float defaultValue)
+ {
+ return parseFloat(attrs.getNamedItem(name), defaultValue);
+ }
+
+ protected Double parseDouble(Node node, Double defaultValue)
+ {
+ return node != null ? Double.valueOf(node.getNodeValue()) : defaultValue;
+ }
+
+ protected Double parseDouble(Node node)
+ {
+ return parseDouble(node, null);
+ }
+
+ protected Double parseDouble(NamedNodeMap attrs, String name)
+ {
+ return parseDouble(attrs.getNamedItem(name));
+ }
+
+ protected Double parseDouble(NamedNodeMap attrs, String name, Double defaultValue)
+ {
+ return parseDouble(attrs.getNamedItem(name), defaultValue);
+ }
+
+ protected String parseString(Node node, String defaultValue)
+ {
+ return node != null ? node.getNodeValue() : defaultValue;
+ }
+
+ protected String parseString(Node node)
+ {
+ return parseString(node, null);
+ }
+
+ protected String parseString(NamedNodeMap attrs, String name)
+ {
+ return parseString(attrs.getNamedItem(name));
+ }
+
+ protected String parseString(NamedNodeMap attrs, String name, String defaultValue)
+ {
+ return parseString(attrs.getNamedItem(name), defaultValue);
+ }
+
+ protected <T extends Enum<T>> T parseEnum(Node node, Class<T> clazz, T defaultValue)
+ {
+ if (node == null)
+ {
+ return defaultValue;
+ }
+
+ try
+ {
+ return Enum.valueOf(clazz, node.getNodeValue());
+ }
+ catch (IllegalArgumentException e)
+ {
+ _log.warn("[" + getCurrentFile().getName() + "] Invalid value specified for node: " + node.getNodeName() + " specified value: " + node.getNodeValue() + " should be enum value of \"" + clazz.getSimpleName() + "\" using default value: " + defaultValue);
+ return defaultValue;
+ }
+ }
+
+ protected <T extends Enum<T>> T parseEnum(Node node, Class<T> clazz)
+ {
+ return parseEnum(node, clazz, null);
+ }
+
+ protected <T extends Enum<T>> T parseEnum(NamedNodeMap attrs, Class<T> clazz, String name)
+ {
+ return parseEnum(attrs.getNamedItem(name), clazz);
+ }
+
+ protected <T extends Enum<T>> T parseEnum(NamedNodeMap attrs, Class<T> clazz, String name, T defaultValue)
+ {
+ return parseEnum(attrs.getNamedItem(name), clazz, defaultValue);
+ }
+
+ public void setCurrentFileFilter(FileFilter filter)
+ {
+ _currentFilter = filter;
+ }
+
+ public FileFilter getCurrentFileFilter()
+ {
+ return _currentFilter != null ? _currentFilter : xmlFilter;
+ }
+
+ /**
+ * Simple XML error handler.
+ * @author Zoey76
+ */
+ protected class XMLErrorHandler implements ErrorHandler
+ {
+ @Override
+ public void warning(SAXParseException e) throws SAXParseException
+ {
+ throw e;
+ }
+
+ @Override
+ public void error(SAXParseException e) throws SAXParseException
+ {
+ throw e;
+ }
+
+ @Override
+ public void fatalError(SAXParseException e) throws SAXParseException
+ {
+ throw e;
+ }
+ }
+}
diff --git a/src/main/java/com/l2jserver/gameserver/instancemanager/PremiumManager.java b/src/main/java/com/l2jserver/gameserver/instancemanager/PremiumManager.java
new file mode 100644
index 0000000..6118e24
--- /dev/null
+++ b/src/main/java/com/l2jserver/gameserver/instancemanager/PremiumManager.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2004-2016 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.commons.database.pool.impl.ConnectionFactory;
+import com.l2jserver.gameserver.model.L2World;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+
+public class PremiumManager
+{
+ private long endDate = 0;
+
+ private static final String GETPREM = "SELECT premium_service,enddate FROM account_premium WHERE account_name=?";
+ private static final String UPDATEPREM = "UPDATE account_premium SET premium_service=?,enddate=? WHERE account_name=?";
+ private static final String REMOVEPREM = "INSERT INTO account_premium (account_name,premium_service,enddate) values(?,?,?) ON DUPLICATE KEY UPDATE premium_service = ?, enddate = ?";
+
+ public long getPremiumEndDate(String accountName)
+ {
+ try (Connection con = ConnectionFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(GETPREM))
+ {
+ 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 = ConnectionFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(UPDATEPREM))
+
+ {
+ Calendar endDate = Calendar.getInstance();
+ endDate.setTimeInMillis(System.currentTimeMillis() + remainingTime);
+ endDate.set(Calendar.SECOND, 0);
+ endDate.add(Calendar.MONTH, months);
+
+ 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 = ConnectionFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(REMOVEPREM))
+ {
+ 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 a/src/main/java/com/l2jserver/gameserver/model/L2World.java b/src/main/java/com/l2jserver/gameserver/model/L2World.java
index 4aa6c2e..7f94cf6 100644
--- a/src/main/java/com/l2jserver/gameserver/model/L2World.java
+++ b/src/main/java/com/l2jserver/gameserver/model/L2World.java
@@ -340,9 +340,10 @@
// Goes through all surrounding world region's creatures.
// And removes the object from their known lists.
- for (L2WorldRegion worldRegion : oldWorldRegion.getSurroundingRegions())
+ for (L2WorldRegion reg : oldWorldRegion.getSurroundingRegions())
{
- for (L2Object obj : worldRegion.getVisibleObjects().values())
+ final Collection<L2Object> vObj = reg.getVisibleObjects().values();
+ for (L2Object obj : vObj)
{
if (obj != null)
{
diff --git a/src/main/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java b/src/main/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
index f4151eb..595b92e 100644
--- a/src/main/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
+++ b/src/main/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
@@ -112,6 +112,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;
@@ -360,6 +362,8 @@
private static final String INSERT_CHARACTER = "INSERT INTO characters (account_name,charId,char_name,level,maxHp,curHp,maxCp,curCp,maxMp,curMp,face,hairStyle,hairColor,sex,exp,sp,karma,fame,pvpkills,pkkills,clanid,race,classid,deletetime,cancraft,title,title_color,accesslevel,online,isin7sdungeon,clan_privs,wantspeace,base_class,newbie,nobless,power_grade,createDate) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
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=?";
+
+ 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 (?,?,?,?,?,?,?,?)";
@@ -559,6 +568,8 @@
private boolean _noble = false;
private boolean _hero = false;
+
+ private boolean _premiumStatus = false;
/** The L2FolkInstance corresponding to the last Folk which one the player talked. */
private L2Npc _lastFolkNpc = null;
@@ -6769,6 +6788,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"));
@@ -13907,6 +13931,62 @@
_recoTwoHoursGiven = val;
}
+ public void setPremiumStatus(boolean premiumStatus)
+ {
+ _premiumStatus = premiumStatus;
+ }
+
+ public boolean hasPremiumStatus()
+ {
+ if (!Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ return _premiumStatus;
+ }
+
+ private static void restorePremiumSystemData(L2PcInstance player, String account)
+ {
+ boolean success = false;
+ try (Connection con = ConnectionFactory.getInstance().getConnection();
+ PreparedStatement ps = con.prepareStatement(RESTORE_PREMIUMSERVICE))
+ {
+ ps.setString(1, account);
+ ResultSet rs = ps.executeQuery();
+ while (rs.next())
+ {
+ success = true;
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (rs.getLong("enddate") <= System.currentTimeMillis())
+ {
+ PremiumManager.getInstance().removePremiumStatus(account);
+ player.setPremiumStatus(false);
+ }
+ else
+ {
+ player.setPremiumStatus(rs.getBoolean("premium_service"));
+ }
+ }
+ else
+ {
+ player.setPremiumStatus(false);
+ }
+ }
+ ps.close();
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Premium System: Could not restore premium system data for " + account + "." + e);
+ e.printStackTrace();
+ }
+ if (!success)
+ {
+ PremiumManager.getInstance().removePremiumStatus(player.getAccountName());
+ player.setPremiumStatus(false);
+ }
+ }
+
public int getRecomBonusTime()
{
if (_recoBonusTask != null)
@@ -14145,6 +14225,16 @@
}
/**
+ * Sets player level.
+ * @param lvl
+ */
+ public void setExpOfLevel(int lvl)
+ {
+ long exp = ExperienceData.getInstance().getExpForLevel(lvl);
+ setExp(exp);
+ }
+
+ /**
* Adds a event listener.
* @param listener
*/
diff --git a/src/main/java/com/l2jserver/gameserver/model/actor/stat/PcStat.java b/src/main/java/com/l2jserver/gameserver/model/actor/stat/PcStat.java
index 578a843..c91e788 100644
--- a/src/main/java/com/l2jserver/gameserver/model/actor/stat/PcStat.java
+++ b/src/main/java/com/l2jserver/gameserver/model/actor/stat/PcStat.java
@@ -137,9 +137,14 @@
bonusSp = getSpBonusMultiplier();
}
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 a/src/main/java/com/l2jserver/gameserver/model/drops/GeneralDropItem.java b/src/main/java/com/l2jserver/gameserver/model/drops/GeneralDropItem.java
index be83697..248f0a8 100644
--- a/src/main/java/com/l2jserver/gameserver/model/drops/GeneralDropItem.java
+++ b/src/main/java/com/l2jserver/gameserver/model/drops/GeneralDropItem.java
@@ -20,6 +20,7 @@
import java.util.List;
+import com.l2jserver.Config;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.drops.strategy.IAmountMultiplierStrategy;
import com.l2jserver.gameserver.model.drops.strategy.IChanceMultiplierStrategy;
@@ -146,10 +147,19 @@
/**
* Gets the min drop count modified by server rates
* @param victim the victim who drops the item
+ * @param killer
* @return the min modified by any rates.
*/
- public final long getMin(L2Character victim)
+ public final long getMin(L2Character victim, L2Character killer)
{
+ if (Config.PREMIUM_SYSTEM_ENABLED && killer.isPlayer() && killer.getActingPlayer().hasPremiumStatus())
+ {
+ if (Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(_itemId) != null)
+ {
+ return (long) (getMin() * getAmountMultiplier(victim) * Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(_itemId));
+ }
+ return (long) (getMin() * getAmountMultiplier(victim) * Config.PREMIUM_RATE_DROP_AMOUNT);
+ }
return (long) (getMin() * getAmountMultiplier(victim));
}
@@ -165,10 +175,19 @@
/**
* Gets the max drop count modified by server rates
* @param victim the victim who drops the item
+ * @param killer
* @return the max modified by any rates.
*/
- public final long getMax(L2Character victim)
+ public final long getMax(L2Character victim, L2Character killer)
{
+ if (Config.PREMIUM_SYSTEM_ENABLED && killer.isPlayer() && killer.getActingPlayer().hasPremiumStatus())
+ {
+ if (Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(_itemId) != null)
+ {
+ return (long) (getMax() * getAmountMultiplier(victim) * Config.PREMIUM_RATE_DROP_AMOUNT_MULTIPLIER.get(_itemId));
+ }
+ return (long) (getMax() * getAmountMultiplier(victim) * Config.PREMIUM_RATE_DROP_AMOUNT);
+ }
return (long) (getMax() * getAmountMultiplier(victim));
}
@@ -201,7 +220,15 @@
*/
public final double getChance(L2Character victim, L2Character killer)
{
- return (getKillerChanceModifier(victim, killer) * getChance(victim));
+ if (Config.PREMIUM_SYSTEM_ENABLED && killer.isPlayer() && killer.getActingPlayer().hasPremiumStatus())
+ {
+ if (Config.PREMIUM_RATE_DROP_CHANCE_MULTIPLIER.get(_itemId) != null)
+ {
+ return getKillerChanceModifier(victim, killer) * getChance(victim) * Config.PREMIUM_RATE_DROP_CHANCE_MULTIPLIER.get(_itemId);
+ }
+ return getKillerChanceModifier(victim, killer) * getChance(victim) * Config.PREMIUM_RATE_DROP_CHANCE;
+ }
+ return getKillerChanceModifier(victim, killer) * getChance(victim);
}
@Override
diff --git a/src/main/java/com/l2jserver/gameserver/model/drops/GroupedGeneralDropItem.java b/src/main/java/com/l2jserver/gameserver/model/drops/GroupedGeneralDropItem.java
index f248c5f..3d90419 100644
--- a/src/main/java/com/l2jserver/gameserver/model/drops/GroupedGeneralDropItem.java
+++ b/src/main/java/com/l2jserver/gameserver/model/drops/GroupedGeneralDropItem.java
@@ -214,14 +214,14 @@
double sumchance = 0;
for (GeneralDropItem item : getItems())
{
- sumchance += (item.getChance(victim) * getChance() * chanceModifier) / 100;
+ sumchance += (item.getChance(victim, killer) * getChance() * chanceModifier) / 100;
}
GroupedGeneralDropItem group = new GroupedGeneralDropItem(sumchance, getDropCalculationStrategy(), IKillerChanceModifierStrategy.NO_RULES, getPreciseStrategy()); // to discard further deep blue calculations
List<GeneralDropItem> items = new ArrayList<>();
for (GeneralDropItem item : getItems())
{
// the item is made almost "static"
- items.add(new GeneralDropItem(item.getItemId(), item.getMin(victim), item.getMax(victim), (item.getChance(victim) * getChance() * chanceModifier) / sumchance, IAmountMultiplierStrategy.STATIC, IChanceMultiplierStrategy.STATIC, getPreciseStrategy(), IKillerChanceModifierStrategy.NO_RULES, item.getDropCalculationStrategy()));
+ items.add(new GeneralDropItem(item.getItemId(), item.getMin(victim, killer), item.getMax(victim, killer), (item.getChance(victim, killer) * getChance() * chanceModifier) / sumchance, IAmountMultiplierStrategy.STATIC, IChanceMultiplierStrategy.STATIC, getPreciseStrategy(), IKillerChanceModifierStrategy.NO_RULES, item.getDropCalculationStrategy()));
}
group.setItems(items);
return group;
diff --git a/src/main/java/com/l2jserver/gameserver/model/drops/strategy/IDropCalculationStrategy.java b/src/main/java/com/l2jserver/gameserver/model/drops/strategy/IDropCalculationStrategy.java
index ad8c9ec..75dacdd 100644
--- a/src/main/java/com/l2jserver/gameserver/model/drops/strategy/IDropCalculationStrategy.java
+++ b/src/main/java/com/l2jserver/gameserver/model/drops/strategy/IDropCalculationStrategy.java
@@ -46,7 +46,7 @@
}
}
- return Collections.singletonList(new ItemHolder(item.getItemId(), Rnd.get(item.getMin(victim), item.getMax(victim)) * amountMultiply));
+ return Collections.singletonList(new ItemHolder(item.getItemId(), Rnd.get(item.getMin(victim, killer), item.getMax(victim, killer)) * amountMultiply));
}
return null;
diff --git a/src/main/java/com/l2jserver/gameserver/model/drops/strategy/IGroupedItemDropCalculationStrategy.java b/src/main/java/com/l2jserver/gameserver/model/drops/strategy/IGroupedItemDropCalculationStrategy.java
index 1d39b24..f02ed01 100644
--- a/src/main/java/com/l2jserver/gameserver/model/drops/strategy/IGroupedItemDropCalculationStrategy.java
+++ b/src/main/java/com/l2jserver/gameserver/model/drops/strategy/IGroupedItemDropCalculationStrategy.java
@@ -46,7 +46,8 @@
private GeneralDropItem getSingleItem(GroupedGeneralDropItem dropItem)
{
final GeneralDropItem item1 = dropItem.getItems().iterator().next();
- singleItemCache.putIfAbsent(dropItem, new GeneralDropItem(item1.getItemId(), item1.getMin(), item1.getMax(), (item1.getChance() * dropItem.getChance()) / 100, item1.getAmountStrategy(), item1.getChanceStrategy(), dropItem.getPreciseStrategy(), dropItem.getKillerChanceModifierStrategy(), item1.getDropCalculationStrategy()));
+ singleItemCache.putIfAbsent(dropItem, new GeneralDropItem(item1.getItemId(), item1.getMin(), item1.getMax(), (item1.getChance() * dropItem.getChance())
+ / 100, item1.getAmountStrategy(), item1.getChanceStrategy(), dropItem.getPreciseStrategy(), dropItem.getKillerChanceModifierStrategy(), item1.getDropCalculationStrategy()));
return singleItemCache.get(dropItem);
}
@@ -79,7 +80,7 @@
}
}
- return Collections.singletonList(new ItemHolder(item2.getItemId(), Rnd.get(item2.getMin(victim), item2.getMax(victim)) * amountMultiply));
+ return Collections.singletonList(new ItemHolder(item2.getItemId(), Rnd.get(item2.getMin(victim, killer), item2.getMax(victim, killer)) * amountMultiply));
}
}
}
diff --git a/src/main/java/com/l2jserver/gameserver/network/clientpackets/EnterWorld.java b/src/main/java/com/l2jserver/gameserver/network/clientpackets/EnterWorld.java
index 6d728ac..46ef637 100644
--- a/src/main/java/com/l2jserver/gameserver/network/clientpackets/EnterWorld.java
+++ b/src/main/java/com/l2jserver/gameserver/network/clientpackets/EnterWorld.java
@@ -65,9 +65,10 @@
import com.l2jserver.gameserver.network.serverpackets.Die;
import com.l2jserver.gameserver.network.serverpackets.EtcStatusUpdate;
import com.l2jserver.gameserver.network.serverpackets.ExBasicActionList;
+import com.l2jserver.gameserver.network.serverpackets.ExBrPremiumState;
import com.l2jserver.gameserver.network.serverpackets.ExGetBookMarkInfoPacket;
import com.l2jserver.gameserver.network.serverpackets.ExNevitAdventPointInfoPacket;
import com.l2jserver.gameserver.network.serverpackets.ExNevitAdventTimeChange;
import com.l2jserver.gameserver.network.serverpackets.ExNoticePostArrived;
import com.l2jserver.gameserver.network.serverpackets.ExNotifyPremiumItem;
import com.l2jserver.gameserver.network.serverpackets.ExShowContactList;
@@ -128,7 +127,7 @@
@Override
protected void runImpl()
{
- final L2PcInstance activeChar = getActiveChar();
+ final L2PcInstance activeChar = getClient().getActiveChar();
if (activeChar == null)
{
_log.warning("EnterWorld failed! activeChar returned 'null'.");
@@ -167,7 +166,15 @@
_log.warning("User already exists in Object ID map! User " + activeChar.getName() + " is a character clone.");
}
}
-
+ if (activeChar.hasPremiumStatus())
+ {
+ activeChar.sendMessage("Premium service activated");
+ activeChar.sendPacket(new ExBrPremiumState(activeChar.getObjectId(), 1));
+ }
+ else
+ {
+ activeChar.sendPacket(new ExBrPremiumState(activeChar.getObjectId(), 0));
+ }
// Apply special GM properties to the GM when entering
if (activeChar.isGM())
{
CitarDATA:
diff --git a/dist/game/config/adminCommands.xml b/dist/game/config/adminCommands.xml
index d4fe593..bb1bf3a 100644
--- a/dist/game/config/adminCommands.xml
+++ b/dist/game/config/adminCommands.xml
@@ -28,6 +28,14 @@
<admin command="admin_config_server" accessLevel="7" />
<admin command="admin_gmon" 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 ANNOUNCEMENTS -->
<admin command="admin_announce" accessLevel="7" />
<admin command="admin_announce_crit" accessLevel="7" />
diff --git a/dist/game/data/html/admin/premium_menu.htm b/dist/game/data/html/admin/premium_menu.htm
new file mode 100644
index 0000000..0cdfbff
--- /dev/null
+++ b/dist/game/data/html/admin/premium_menu.htm
@@ -0,0 +1,23 @@
+<html><title>L2JServer</title><body>
+<center>
+<table width=270>
+<tr>
+<td width=45><button value="Home" action="bypass admin_admin" width=45 height=21 back="L2UI_CT1.Button_DF_Down" fore="L2UI_CT1.Button_DF"></td>
+<td width=180><center>Premium Menu</center></td>
+<td width=45><button value="Return" action="bypass -h admin_admin6" width=45 height=21 back="L2UI_CT1.Button_DF_Down" fore="L2UI_CT1.Button_DF"></td>
+</tr>
+</table>
+<br>
+<font color="LEVEL">Please enter the account name</font><br>
+<edit var="acc_name" width=200>
+<br>
+<br><button value="Add 1 Mounth" action="bypass -h admin_premium_add1 $acc_name" width=200 height=30 back="L2UI_CT1.OlympiadWnd_DF_Reward_Down" fore="L2UI_CT1.OlympiadWnd_DF_Reward">
+<button value="Add 2 Mounth" action="bypass -h admin_premium_add2 $acc_name" width=200 height=30 back="L2UI_CT1.OlympiadWnd_DF_Reward_Down" fore="L2UI_CT1.OlympiadWnd_DF_Reward">
+<button value="Add 3 Mounth" action="bypass -h admin_premium_add3 $acc_name" width=200 height=30 back="L2UI_CT1.OlympiadWnd_DF_Reward_Down" fore="L2UI_CT1.OlympiadWnd_DF_Reward">
+<br>
+<button value="View Premium Status" action="bypass -h admin_premium_info $acc_name" width=200 height=30 back="L2UI_CT1.Button_DF_Down" fore="L2UI_CT1.Button_DF">
+<button value="Remove Premium Status" action="bypass -h admin_premium_remove $acc_name" width=200 height=30 back="L2UI_CT1.Button_DF_Down" fore="L2UI_CT1.Button_DF">
+<br>
+<font color="FF0000">Players can use the command .premium</font>
+</center>
+</body></html>
\ No newline at end of file
diff --git a/dist/game/data/scripts/handlers/MasterHandler.java b/dist/game/data/scripts/handlers/MasterHandler.java
index 6c7f2b9..4929a70 100644
--- a/dist/game/data/scripts/handlers/MasterHandler.java
+++ b/dist/game/data/scripts/handlers/MasterHandler.java
@@ -105,6 +105,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;
@@ -276,6 +277,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;
@@ -378,6 +380,7 @@
AdminPForge.class,
AdminPledge.class,
AdminPolymorph.class,
+ AdminPremium.class,
AdminPunishment.class,
AdminQuest.class,
AdminReload.class,
@@ -533,6 +536,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 a/dist/game/data/scripts/handlers/admincommandhandlers/AdminPremium.java b/dist/game/data/scripts/handlers/admincommandhandlers/AdminPremium.java
new file mode 100644
index 0000000..6d40059
--- /dev/null
+++ b/dist/game/data/scripts/handlers/admincommandhandlers/AdminPremium.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2004-2016 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.Config;
+import com.l2jserver.gameserver.cache.HtmCache;
+import com.l2jserver.gameserver.handler.IAdminCommandHandler;
+import com.l2jserver.gameserver.instancemanager.PremiumManager;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
+
+/**
+ * @author Mobius
+ */
+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("Please enter the account name.");
+ }
+ }
+ else if (command.startsWith("admin_premium_add2"))
+ {
+ try
+ {
+ String val = command.substring(19);
+ addPremiumStatus(activeChar, 2, val);
+ }
+ catch (StringIndexOutOfBoundsException e)
+ {
+ activeChar.sendMessage("Please enter the account name.");
+ }
+ }
+ else if (command.startsWith("admin_premium_add3"))
+ {
+ try
+ {
+ String val = command.substring(19);
+ addPremiumStatus(activeChar, 3, val);
+ }
+ catch (StringIndexOutOfBoundsException e)
+ {
+ activeChar.sendMessage("Please enter the account name.");
+ }
+ }
+ else if (command.startsWith("admin_premium_info"))
+ {
+ try
+ {
+ String val = command.substring(19);
+ viewPremiumInfo(activeChar, val);
+ }
+ catch (StringIndexOutOfBoundsException e)
+ {
+ activeChar.sendMessage("Please enter the account name.");
+ }
+ }
+ else if (command.startsWith("admin_premium_remove"))
+ {
+ try
+ {
+ String val = command.substring(21);
+ removePremium(activeChar, val);
+ }
+ catch (StringIndexOutOfBoundsException e)
+ {
+ activeChar.sendMessage("Please enter a valid account name.");
+ }
+ }
+
+ final NpcHtmlMessage html = new NpcHtmlMessage(0, 0);
+ html.setHtml(HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "html/admin/premium_menu.htm"));
+ activeChar.sendPacket(html);
+ return true;
+ }
+
+ private void addPremiumStatus(L2PcInstance admin, int months, String accountName)
+ {
+ if (!Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ admin.sendMessage("Premium system has been shutdown.");
+ return;
+ }
+
+ // 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 + " Premium Account, " + String.valueOf(format.format(endDate)) + " Expire.");
+ }
+
+ 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 + " Premium Account, " + String.valueOf(format.format(endDate)) + " Expire.");
+ }
+ else
+ {
+ admin.sendMessage("Account: " + accountName + " Not are Premium.");
+ }
+ }
+
+ private void removePremium(L2PcInstance admin, String accountName)
+ {
+ if (PremiumManager.getInstance().getPremiumEndDate(accountName) > 0)
+ {
+ PremiumManager.getInstance().removePremiumStatus(accountName);
+ admin.sendMessage("Account: " + accountName + " Premium Removed.");
+ }
+ else
+ {
+ admin.sendMessage("Account: " + accountName + " Not are Premium.");
+ }
+ }
+
+ @Override
+ public String[] getAdminCommandList()
+ {
+ return ADMIN_COMMANDS;
+ }
+}
\ No newline at end of file
diff --git a/dist/game/data/scripts/handlers/bypasshandlers/NpcViewMod.java b/dist/game/data/scripts/handlers/bypasshandlers/NpcViewMod.java
index 3e5144f..5950dc5 100644
--- a/dist/game/data/scripts/handlers/bypasshandlers/NpcViewMod.java
+++ b/dist/game/data/scripts/handlers/bypasshandlers/NpcViewMod.java
@@ -328,7 +328,7 @@
sb.append(item.getName());
sb.append("</font></td></tr><tr><td width=32></td><td width=259><table width=253 cellpadding=0 cellspacing=0>");
sb.append("<tr><td width=48 align=right valign=top><font color=\"LEVEL\">Amount:</font></td><td width=205 align=center>");
- MinMax minMax = getPreciseMinMax(normalized.getChance(), generalDropItem.getMin(npc), generalDropItem.getMax(npc), generalDropItem.isPreciseCalculated());
+ MinMax minMax = getPreciseMinMax(normalized.getChance(), generalDropItem.getMin(npc, activeChar), generalDropItem.getMax(npc, activeChar), generalDropItem.isPreciseCalculated());
final long min = minMax.min;
final long max = minMax.max;
if (min == max)
@@ -344,7 +344,7 @@
sb.append("</td></tr><tr><td width=48 align=right valign=top><font color=\"LEVEL\">Chance:</font></td>");
sb.append("<td width=205 align=center>");
- sb.append(chanceFormat.format(Math.min(generalDropItem.getChance(), 100)));
+ sb.append(chanceFormat.format(Math.min(generalDropItem.getChance(npc, activeChar), 100)));
sb.append("%</td></tr></table></td></tr><tr><td width=32></td><td width=259> </td></tr></table>");
height += 64;
@@ -407,7 +407,7 @@
sb.append("</font></td></tr><tr><td width=32></td><td width=300><table width=295 cellpadding=0 cellspacing=0>");
sb.append("<tr><td width=48 align=right valign=top><font color=\"LEVEL\">Amount:</font></td>");
sb.append("<td width=247 align=center>");
- MinMax minMax = getPreciseMinMax(dropItem.getChance(npc, activeChar), dropItem.getMin(npc), dropItem.getMax(npc), dropItem.isPreciseCalculated());
+ MinMax minMax = getPreciseMinMax(dropItem.getChance(npc, activeChar), dropItem.getMin(npc, activeChar), dropItem.getMax(npc, activeChar), dropItem.isPreciseCalculated());
final long min = minMax.min;
final long max = minMax.max;
diff --git a/dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java b/dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java
new file mode 100644
index 0000000..84034b9
--- /dev/null
+++ b/dist/game/data/scripts/handlers/voicedcommandhandlers/Premium.java
@@ -0,0 +1,101 @@
+/*
+ * 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><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.RATE_DEATH_DROP_CHANCE_MULTIPLIER * Config.PREMIUM_RATE_DROP_CHANCE) + "<br1></font></td></tr>");
+ html.append("<tr><td>Drop Amount: <font color=\"LEVEL\"> x" + (Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_DROP_AMOUNT) + "<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_DROP_CHANCE) + " <br1></font></td></tr>");
+ html.append("<tr><td>Drop Amount: <font color=\"LEVEL\">x" + (Config.RATE_DEATH_DROP_AMOUNT_MULTIPLIER * Config.PREMIUM_RATE_DROP_AMOUNT) + " <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 a/dist/sql/game/account_premium.sql b/dist/sql/game/account_premium.sql
new file mode 100644
index 0000000..ce5aa62
--- /dev/null
+++ b/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