No tienes permiso para ver los enlaces. Para poder verlos Registrate o Conectate.
CitarCORE:
### Eclipse Workspace Patch 1.0
#P L2J_DataPack_BETA
Index: dist/game/data/scripts/handlers/MasterHandler.java
===================================================================
--- dist/game/data/scripts/handlers/MasterHandler.java (revision 10451)
+++ dist/game/data/scripts/handlers/MasterHandler.java (working copy)
@@ -270,6 +271,7 @@
import handlers.voicedcommandhandlers.Lang;
import handlers.voicedcommandhandlers.StatsVCmd;
import handlers.voicedcommandhandlers.Wedding;
+import handlers.voicedcommandhandlers.VisualArmor;
/**
* Master handler.
@@ -515,6 +518,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),
+ VisualArmor.class,
},
{
// Target Handlers
Index: dist/game/data/scripts/handlers/voicedcommandhandlers/VisualArmor.java
===================================================================
--- dist/game/data/scripts/handlers/voicedcommandhandlers/VisualArmor.java (revision 0)
+++ dist/game/data/scripts/handlers/voicedcommandhandlers/VisualArmor.java (working copy)
@@ -0,0 +1,71 @@
+/*
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package handlers.voicedcommandhandlers;
+
+import com.l2jserver.extensions.VisualArmorController;
+import com.l2jserver.gameserver.handler.IVoicedCommandHandler;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
+
+public class VisualArmor implements IVoicedCommandHandler
+{
+ private static final String[] VOICED_COMMANDS =
+ {
+ "dressme",
+ "dressMe",
+ "DressMe",
+ "cloakOn",
+ "cloakOff"
+ };
+
+ @Override
+ public boolean useVoicedCommand(String command, L2PcInstance activeChar, String params)
+ {
+ if (command.contains("cloakOn"))
+ {
+ activeChar.visualArmor.weaponLRHANDId = 0;
+ InventoryUpdate iu = new InventoryUpdate();
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ InventoryUpdate iu2 = new InventoryUpdate();
+ activeChar.sendPacket(iu2);
+ activeChar.broadcastUserInfo();
+ activeChar.sendMessage("Cloak enabled.");
+ }
+ else if (command.contains("cloakOff"))
+ {
+ activeChar.visualArmor.weaponLRHANDId = 1;
+ InventoryUpdate iu = new InventoryUpdate();
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ InventoryUpdate iu2 = new InventoryUpdate();
+ activeChar.sendPacket(iu2);
+ activeChar.broadcastUserInfo();
+ activeChar.sendMessage("Cloak disabled.");
+ }
+ else
+ {
+ VisualArmorController.dressMe(activeChar);
+ }
+
+ return true;
+ }
+
+ @Override
+ public String[] getVoicedCommandList()
+ {
+ return VOICED_COMMANDS;
+ }
+}
CitarDATA:
### Eclipse Workspace Patch 1.0
#P L2J_Server_BETA
Index: java/com/l2jserver/extensions/VisualArmorController.java
===================================================================
--- java/com/l2jserver/extensions/VisualArmorController.java (revision 0)
+++ java/com/l2jserver/extensions/VisualArmorController.java (working copy)
@@ -0,0 +1,422 @@
+/*
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.extensions;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import com.l2jserver.L2DatabaseFactory;
+import com.l2jserver.gameserver.datatables.ItemTable;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.itemcontainer.Inventory;
+import com.l2jserver.gameserver.model.items.L2Armor;
+import com.l2jserver.gameserver.model.items.L2Item;
+import com.l2jserver.gameserver.model.items.L2Weapon;
+import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jserver.gameserver.model.items.type.ArmorType;
+import com.l2jserver.gameserver.model.items.type.WeaponType;
+import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
+
+/**
+ * @author giorgakis
+ */
+public class VisualArmorController
+{
+ // As of freya there are 19 weapon types.
+ public static final int totalWeaponTypes = 19;
+
+ // As of freya there are 6 armor types.
+ public static final int totalArmorTypes = 6;
+
+ public static boolean[][] weaponMapping = new boolean[totalWeaponTypes][totalWeaponTypes];
+ public static boolean[][] armorMapping = new boolean[totalArmorTypes][totalArmorTypes];
+
+ public static void migrate()
+ {
+ System.out.println("[VisualArmor]:Migrating the database.");
+ Connection con = null;
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(VisualArmorModel.CREATE);
+ statement.execute();
+ statement.close();
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ con.close();
+ }
+ catch (Exception e)
+ {
+ }
+ }
+ }
+
+ public static void load()
+ {
+ migrate();
+ generateMappings();
+ }
+
+ /**
+ * All same type armors and same type weapons can get visual. All different types cannot get visual unless it is stated in here.
+ */
+ public static void generateMappings()
+ {
+ for (int i = 0; i < weaponMapping.length; i++)
+ {
+ for (int j = 0; j < weaponMapping.length; j++)
+ {
+ weaponMapping[i][j] = false;
+ }
+ }
+
+ for (int i = 0; i < armorMapping.length; i++)
+ {
+ for (int j = 0; j < armorMapping.length; j++)
+ {
+ armorMapping[i][j] = false;
+ }
+ }
+
+ callRules();
+
+ }
+
+ public static void callRules()
+ {
+ // Example: a Virtual sword can mount an Equipped blunt.
+ weaponMapping[WeaponType.SWORD.ordinal()][WeaponType.BLUNT.ordinal()] = true;
+
+ // Example: a Virtual blunt can mount an Equipped sword.
+ weaponMapping[WeaponType.BLUNT.ordinal()][WeaponType.SWORD.ordinal()] = true;
+
+ // weaponMapping[WeaponType.BIGSWORD.ordinal()][WeaponType.BIGBLUNT.ordinal()] = true;
+ // weaponMapping[WeaponType.BIGBLUNT.ordinal()][WeaponType.BIGSWORD.ordinal()] = true;
+
+ armorMapping[ArmorType.SIGIL.ordinal()][ArmorType.SHIELD.ordinal()] = true;
+ armorMapping[ArmorType.SHIELD.ordinal()][ArmorType.SIGIL.ordinal()] = true;
+
+ // armorMapping[L2ArmorType.HEAVY.ordinal()][L2ArmorType.LIGHT.ordinal()] = true;
+ // armorMapping[L2ArmorType.HEAVY.ordinal()][L2ArmorType.MAGIC.ordinal()] = true;
+
+ // armorMapping[L2ArmorType.LIGHT.ordinal()][L2ArmorType.HEAVY.ordinal()] = true;
+ // armorMapping[L2ArmorType.LIGHT.ordinal()][L2ArmorType.MAGIC.ordinal()] = true;
+
+ // armorMapping[L2ArmorType.MAGIC.ordinal()][L2ArmorType.LIGHT.ordinal()] = true;
+ // armorMapping[L2ArmorType.MAGIC.ordinal()][L2ArmorType.HEAVY.ordinal()] = true;
+ }
+
+ /**
+ * Checks if the weapon is the same type. If that is true then return the matching virtual id. Else check the mapping tables if any rule states that the two different weapon types should be matched.
+ * @param virtual
+ * @param equiped
+ * @param matchId
+ * @param noMatchId
+ * @return
+ */
+ public static int weaponMatching(WeaponType virtual, WeaponType equiped, int matchId, int noMatchId)
+ {
+ if (virtual == equiped)
+ {
+ return matchId;
+ }
+
+ if (weaponMapping[virtual.ordinal()][equiped.ordinal()] == true)
+ {
+ return matchId;
+ }
+
+ return noMatchId;
+ }
+
+ /**
+ * Checks if the armor is the same type. If that is true then return the matching virtual id. Else check the mapping tables if any rule states that the two different armor types should be matched.
+ * @param virtual
+ * @param equiped
+ * @param matchId
+ * @param noMatchId
+ * @return
+ */
+ public static int armorMatching(ArmorType virtual, ArmorType equiped, int matchId, int noMatchId)
+ {
+ if (virtual == equiped)
+ {
+ return matchId;
+ }
+
+ if (armorMapping[virtual.ordinal()][equiped.ordinal()] == true)
+ {
+ return matchId;
+ }
+
+ return noMatchId;
+ }
+
+ public static void setVirtualRhand(L2PcInstance actor)
+ {
+ actor.visualArmor.weaponRHANDId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_RHAND);
+ }
+
+ public static void setVirtualLhand(L2PcInstance actor)
+ {
+ actor.visualArmor.weaponLHANDId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LHAND);
+ }
+
+ public static void setVirtualGloves(L2PcInstance actor)
+ {
+ actor.visualArmor.glovesTextureId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_GLOVES);
+ }
+
+ public static void setVirtualBody(L2PcInstance actor)
+ {
+ actor.visualArmor.armorTextureId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CHEST);
+ }
+
+ public static void setVirtualPants(L2PcInstance actor)
+ {
+ int chestId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CHEST);
+ int pantsId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LEGS);
+
+ if ((chestId != 0) && (pantsId == 0))
+ {
+ actor.visualArmor.pantsTextureId = chestId;
+ }
+ else
+ {
+ actor.visualArmor.pantsTextureId = pantsId;
+ }
+ }
+
+ public static void setVirtualBoots(L2PcInstance actor)
+ {
+ actor.visualArmor.bootsTextureId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_FEET);
+ }
+
+ // TODO: Merge the armor getters in one function.
+ public static int getVirtualGloves(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_GLOVES);
+ if (equipedItem == null)
+ {
+ return 0;
+ }
+ // ClassCastException wont happen unless some jackass changes the values from the database.
+ L2Armor equipedGloves = (L2Armor) actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_GLOVES).getItem();
+ int equipedGlovesId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_GLOVES);
+
+ int glovesTextureId = actor.visualArmor.glovesTextureId;
+ L2Armor virtualGloves = (L2Armor) ItemTable.getInstance().getTemplate(glovesTextureId);
+
+ if (glovesTextureId != 0)
+ {
+ return armorMatching(virtualGloves.getItemType(), equipedGloves.getItemType(), glovesTextureId, equipedGlovesId);
+ }
+ else
+ {
+ return equipedGlovesId;
+ }
+ }
+
+ public static int getVirtualBody(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
+ if (equipedItem == null)
+ {
+ return 0;
+ }
+ // ClassCastException wont happen unless some jackass changes the values from the database.
+ L2Armor equipedChest = (L2Armor) actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST).getItem();
+ int equipedChestId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CHEST);
+
+ int chestTextureId = actor.visualArmor.armorTextureId;
+ L2Armor virtualChest = (L2Armor) ItemTable.getInstance().getTemplate(chestTextureId);
+
+ if (chestTextureId != 0)
+ {
+ return armorMatching(virtualChest.getItemType(), equipedChest.getItemType(), chestTextureId, equipedChestId);
+ }
+ else
+ {
+ return equipedChestId;
+ }
+ }
+
+ /**
+ * This is a brain fu**er handling the pants since they are also part of a fullbody armor.
+ * @param actor
+ * @return
+ */
+ public static int getVirtualPants(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEGS);
+
+ // Here comes the tricky part. If pants are null, then check for a fullbody armor.
+ if (equipedItem == null)
+ {
+ equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
+ }
+ if (equipedItem == null)
+ {
+ return 0;
+ }
+
+ int pantsTextureId = actor.visualArmor.pantsTextureId;
+
+ L2Armor equipedPants = (L2Armor) equipedItem.getItem();
+
+ if ((equipedPants.getBodyPart() != L2Item.SLOT_FULL_ARMOR) && (equipedPants.getBodyPart() != L2Item.SLOT_LEGS))
+ {
+ return 0;
+ }
+ int equipedPantsId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LEGS);
+
+ L2Armor virtualPants = (L2Armor) ItemTable.getInstance().getTemplate(pantsTextureId);
+
+ if (pantsTextureId != 0)
+ {
+ return armorMatching(virtualPants.getItemType(), equipedPants.getItemType(), pantsTextureId, equipedPantsId);
+ }
+ else
+ {
+ return equipedPantsId;
+ }
+ }
+
+ public static int getVirtualBoots(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_FEET);
+ if (equipedItem == null)
+ {
+ return 0;
+ }
+ // ClassCastException wont happen unless some jackass changes the values from the database.
+ L2Armor equipedBoots = (L2Armor) actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_FEET).getItem();
+ int equipedBootsId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_FEET);
+
+ int bootsTextureId = actor.visualArmor.bootsTextureId;
+ L2Armor virtualGloves = (L2Armor) ItemTable.getInstance().getTemplate(bootsTextureId);
+
+ if (bootsTextureId != 0)
+ {
+ return armorMatching(virtualGloves.getItemType(), equipedBoots.getItemType(), bootsTextureId, equipedBootsId);
+ }
+ else
+ {
+ return equipedBootsId;
+ }
+ }
+
+ public static int getLHAND(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ int equipedItemId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LHAND);
+
+ int weaponLHANDId = actor.visualArmor.weaponLHANDId;
+ L2Item virtualItem = ItemTable.getInstance().getTemplate(weaponLHANDId);
+
+ if ((equipedItem == null) || (weaponLHANDId == 0))
+ {
+ return equipedItemId;
+ }
+
+ // Only check same weapon types. Virtual replacement should not happen between armor/weapons.
+ if ((equipedItem.getItem() instanceof L2Weapon) && (virtualItem instanceof L2Weapon))
+ {
+ L2Weapon weapon = (L2Weapon) equipedItem.getItem();
+ L2Weapon virtualweapon = (L2Weapon) virtualItem;
+
+ return weaponMatching(virtualweapon.getItemType(), weapon.getItemType(), weaponLHANDId, equipedItemId);
+ }
+ else if ((equipedItem.getItem() instanceof L2Armor) && (virtualItem instanceof L2Armor))
+ {
+ L2Armor armor = (L2Armor) equipedItem.getItem();
+ L2Armor virtualarmor = (L2Armor) virtualItem;
+
+ return armorMatching(virtualarmor.getItemType(), armor.getItemType(), weaponLHANDId, equipedItemId);
+ }
+ return equipedItemId;
+ }
+
+ public static int getRHAND(L2PcInstance actor)
+ {
+ int weaponRHANDId = actor.visualArmor.weaponRHANDId;
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);
+ int equipedItemId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_RHAND);
+ L2Item virtualItem = ItemTable.getInstance().getTemplate(weaponRHANDId);
+
+ if ((equipedItem == null) || (weaponRHANDId == 0))
+ {
+ return equipedItemId;
+ }
+
+ // Only check same weapon types. Virtual replacement should not happen between armor/weapons.
+ if ((equipedItem.getItem() instanceof L2Weapon) && (virtualItem instanceof L2Weapon))
+ {
+ L2Weapon weapon = (L2Weapon) equipedItem.getItem();
+ L2Weapon virtualweapon = (L2Weapon) virtualItem;
+
+ return weaponMatching(virtualweapon.getItemType(), weapon.getItemType(), weaponRHANDId, equipedItemId);
+ }
+ else if ((equipedItem.getItem() instanceof L2Armor) && (virtualItem instanceof L2Armor))
+ {
+ L2Armor armor = (L2Armor) equipedItem.getItem();
+ L2Armor virtualarmor = (L2Armor) virtualItem;
+
+ return armorMatching(virtualarmor.getItemType(), armor.getItemType(), weaponRHANDId, equipedItemId);
+ }
+ return equipedItemId;
+
+ }
+
+ public static int getCloak(L2PcInstance actor)
+ {
+ if (actor.visualArmor.weaponLRHANDId == 1)
+ {
+ return 0;
+ }
+ else
+ {
+ return actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CLOAK);
+ }
+
+ }
+
+ public static void dressMe(L2PcInstance activeChar)
+ {
+ setVirtualBody(activeChar);
+ setVirtualGloves(activeChar);
+ setVirtualPants(activeChar);
+ setVirtualBoots(activeChar);
+ setVirtualLhand(activeChar);
+ setVirtualRhand(activeChar);
+
+ InventoryUpdate iu = new InventoryUpdate();
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ InventoryUpdate iu2 = new InventoryUpdate();
+ activeChar.sendPacket(iu2);
+ activeChar.broadcastUserInfo();
+ activeChar.sendMessage("You changed clothes.");
+ activeChar.visualArmor.updateVisualArmor();
+ }
+}
Index: java/com/l2jserver/extensions/VisualArmorController.java
===================================================================
--- java/com/l2jserver/extensions/VisualArmorController.java (revision 0)
+++ java/com/l2jserver/extensions/VisualArmorController.java (working copy)
@@ -0,0 +1,422 @@
+/*
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.extensions;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import com.l2jserver.L2DatabaseFactory;
+import com.l2jserver.gameserver.datatables.ItemTable;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.itemcontainer.Inventory;
+import com.l2jserver.gameserver.model.items.L2Armor;
+import com.l2jserver.gameserver.model.items.L2Item;
+import com.l2jserver.gameserver.model.items.L2Weapon;
+import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jserver.gameserver.model.items.type.ArmorType;
+import com.l2jserver.gameserver.model.items.type.WeaponType;
+import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
+
+/**
+ * @author giorgakis
+ */
+public class VisualArmorController
+{
+ // As of freya there are 19 weapon types.
+ public static final int totalWeaponTypes = 19;
+
+ // As of freya there are 6 armor types.
+ public static final int totalArmorTypes = 6;
+
+ public static boolean[][] weaponMapping = new boolean[totalWeaponTypes][totalWeaponTypes];
+ public static boolean[][] armorMapping = new boolean[totalArmorTypes][totalArmorTypes];
+
+ public static void migrate()
+ {
+ System.out.println("[VisualArmor]:Migrating the database.");
+ Connection con = null;
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(VisualArmorModel.CREATE);
+ statement.execute();
+ statement.close();
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ con.close();
+ }
+ catch (Exception e)
+ {
+ }
+ }
+ }
+
+ public static void load()
+ {
+ migrate();
+ generateMappings();
+ }
+
+ /**
+ * All same type armors and same type weapons can get visual. All different types cannot get visual unless it is stated in here.
+ */
+ public static void generateMappings()
+ {
+ for (int i = 0; i < weaponMapping.length; i++)
+ {
+ for (int j = 0; j < weaponMapping.length; j++)
+ {
+ weaponMapping[i][j] = false;
+ }
+ }
+
+ for (int i = 0; i < armorMapping.length; i++)
+ {
+ for (int j = 0; j < armorMapping.length; j++)
+ {
+ armorMapping[i][j] = false;
+ }
+ }
+
+ callRules();
+
+ }
+
+ public static void callRules()
+ {
+ // Example: a Virtual sword can mount an Equipped blunt.
+ weaponMapping[WeaponType.SWORD.ordinal()][WeaponType.BLUNT.ordinal()] = true;
+
+ // Example: a Virtual blunt can mount an Equipped sword.
+ weaponMapping[WeaponType.BLUNT.ordinal()][WeaponType.SWORD.ordinal()] = true;
+
+ // weaponMapping[WeaponType.BIGSWORD.ordinal()][WeaponType.BIGBLUNT.ordinal()] = true;
+ // weaponMapping[WeaponType.BIGBLUNT.ordinal()][WeaponType.BIGSWORD.ordinal()] = true;
+
+ armorMapping[ArmorType.SIGIL.ordinal()][ArmorType.SHIELD.ordinal()] = true;
+ armorMapping[ArmorType.SHIELD.ordinal()][ArmorType.SIGIL.ordinal()] = true;
+
+ // armorMapping[L2ArmorType.HEAVY.ordinal()][L2ArmorType.LIGHT.ordinal()] = true;
+ // armorMapping[L2ArmorType.HEAVY.ordinal()][L2ArmorType.MAGIC.ordinal()] = true;
+
+ // armorMapping[L2ArmorType.LIGHT.ordinal()][L2ArmorType.HEAVY.ordinal()] = true;
+ // armorMapping[L2ArmorType.LIGHT.ordinal()][L2ArmorType.MAGIC.ordinal()] = true;
+
+ // armorMapping[L2ArmorType.MAGIC.ordinal()][L2ArmorType.LIGHT.ordinal()] = true;
+ // armorMapping[L2ArmorType.MAGIC.ordinal()][L2ArmorType.HEAVY.ordinal()] = true;
+ }
+
+ /**
+ * Checks if the weapon is the same type. If that is true then return the matching virtual id. Else check the mapping tables if any rule states that the two different weapon types should be matched.
+ * @param virtual
+ * @param equiped
+ * @param matchId
+ * @param noMatchId
+ * @return
+ */
+ public static int weaponMatching(WeaponType virtual, WeaponType equiped, int matchId, int noMatchId)
+ {
+ if (virtual == equiped)
+ {
+ return matchId;
+ }
+
+ if (weaponMapping[virtual.ordinal()][equiped.ordinal()] == true)
+ {
+ return matchId;
+ }
+
+ return noMatchId;
+ }
+
+ /**
+ * Checks if the armor is the same type. If that is true then return the matching virtual id. Else check the mapping tables if any rule states that the two different armor types should be matched.
+ * @param virtual
+ * @param equiped
+ * @param matchId
+ * @param noMatchId
+ * @return
+ */
+ public static int armorMatching(ArmorType virtual, ArmorType equiped, int matchId, int noMatchId)
+ {
+ if (virtual == equiped)
+ {
+ return matchId;
+ }
+
+ if (armorMapping[virtual.ordinal()][equiped.ordinal()] == true)
+ {
+ return matchId;
+ }
+
+ return noMatchId;
+ }
+
+ public static void setVirtualRhand(L2PcInstance actor)
+ {
+ actor.visualArmor.weaponRHANDId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_RHAND);
+ }
+
+ public static void setVirtualLhand(L2PcInstance actor)
+ {
+ actor.visualArmor.weaponLHANDId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LHAND);
+ }
+
+ public static void setVirtualGloves(L2PcInstance actor)
+ {
+ actor.visualArmor.glovesTextureId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_GLOVES);
+ }
+
+ public static void setVirtualBody(L2PcInstance actor)
+ {
+ actor.visualArmor.armorTextureId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CHEST);
+ }
+
+ public static void setVirtualPants(L2PcInstance actor)
+ {
+ int chestId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CHEST);
+ int pantsId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LEGS);
+
+ if ((chestId != 0) && (pantsId == 0))
+ {
+ actor.visualArmor.pantsTextureId = chestId;
+ }
+ else
+ {
+ actor.visualArmor.pantsTextureId = pantsId;
+ }
+ }
+
+ public static void setVirtualBoots(L2PcInstance actor)
+ {
+ actor.visualArmor.bootsTextureId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_FEET);
+ }
+
+ // TODO: Merge the armor getters in one function.
+ public static int getVirtualGloves(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_GLOVES);
+ if (equipedItem == null)
+ {
+ return 0;
+ }
+ // ClassCastException wont happen unless some jackass changes the values from the database.
+ L2Armor equipedGloves = (L2Armor) actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_GLOVES).getItem();
+ int equipedGlovesId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_GLOVES);
+
+ int glovesTextureId = actor.visualArmor.glovesTextureId;
+ L2Armor virtualGloves = (L2Armor) ItemTable.getInstance().getTemplate(glovesTextureId);
+
+ if (glovesTextureId != 0)
+ {
+ return armorMatching(virtualGloves.getItemType(), equipedGloves.getItemType(), glovesTextureId, equipedGlovesId);
+ }
+ else
+ {
+ return equipedGlovesId;
+ }
+ }
+
+ public static int getVirtualBody(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
+ if (equipedItem == null)
+ {
+ return 0;
+ }
+ // ClassCastException wont happen unless some jackass changes the values from the database.
+ L2Armor equipedChest = (L2Armor) actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST).getItem();
+ int equipedChestId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CHEST);
+
+ int chestTextureId = actor.visualArmor.armorTextureId;
+ L2Armor virtualChest = (L2Armor) ItemTable.getInstance().getTemplate(chestTextureId);
+
+ if (chestTextureId != 0)
+ {
+ return armorMatching(virtualChest.getItemType(), equipedChest.getItemType(), chestTextureId, equipedChestId);
+ }
+ else
+ {
+ return equipedChestId;
+ }
+ }
+
+ /**
+ * This is a brain fu**er handling the pants since they are also part of a fullbody armor.
+ * @param actor
+ * @return
+ */
+ public static int getVirtualPants(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LEGS);
+
+ // Here comes the tricky part. If pants are null, then check for a fullbody armor.
+ if (equipedItem == null)
+ {
+ equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_CHEST);
+ }
+ if (equipedItem == null)
+ {
+ return 0;
+ }
+
+ int pantsTextureId = actor.visualArmor.pantsTextureId;
+
+ L2Armor equipedPants = (L2Armor) equipedItem.getItem();
+
+ if ((equipedPants.getBodyPart() != L2Item.SLOT_FULL_ARMOR) && (equipedPants.getBodyPart() != L2Item.SLOT_LEGS))
+ {
+ return 0;
+ }
+ int equipedPantsId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LEGS);
+
+ L2Armor virtualPants = (L2Armor) ItemTable.getInstance().getTemplate(pantsTextureId);
+
+ if (pantsTextureId != 0)
+ {
+ return armorMatching(virtualPants.getItemType(), equipedPants.getItemType(), pantsTextureId, equipedPantsId);
+ }
+ else
+ {
+ return equipedPantsId;
+ }
+ }
+
+ public static int getVirtualBoots(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_FEET);
+ if (equipedItem == null)
+ {
+ return 0;
+ }
+ // ClassCastException wont happen unless some jackass changes the values from the database.
+ L2Armor equipedBoots = (L2Armor) actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_FEET).getItem();
+ int equipedBootsId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_FEET);
+
+ int bootsTextureId = actor.visualArmor.bootsTextureId;
+ L2Armor virtualGloves = (L2Armor) ItemTable.getInstance().getTemplate(bootsTextureId);
+
+ if (bootsTextureId != 0)
+ {
+ return armorMatching(virtualGloves.getItemType(), equipedBoots.getItemType(), bootsTextureId, equipedBootsId);
+ }
+ else
+ {
+ return equipedBootsId;
+ }
+ }
+
+ public static int getLHAND(L2PcInstance actor)
+ {
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ int equipedItemId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LHAND);
+
+ int weaponLHANDId = actor.visualArmor.weaponLHANDId;
+ L2Item virtualItem = ItemTable.getInstance().getTemplate(weaponLHANDId);
+
+ if ((equipedItem == null) || (weaponLHANDId == 0))
+ {
+ return equipedItemId;
+ }
+
+ // Only check same weapon types. Virtual replacement should not happen between armor/weapons.
+ if ((equipedItem.getItem() instanceof L2Weapon) && (virtualItem instanceof L2Weapon))
+ {
+ L2Weapon weapon = (L2Weapon) equipedItem.getItem();
+ L2Weapon virtualweapon = (L2Weapon) virtualItem;
+
+ return weaponMatching(virtualweapon.getItemType(), weapon.getItemType(), weaponLHANDId, equipedItemId);
+ }
+ else if ((equipedItem.getItem() instanceof L2Armor) && (virtualItem instanceof L2Armor))
+ {
+ L2Armor armor = (L2Armor) equipedItem.getItem();
+ L2Armor virtualarmor = (L2Armor) virtualItem;
+
+ return armorMatching(virtualarmor.getItemType(), armor.getItemType(), weaponLHANDId, equipedItemId);
+ }
+ return equipedItemId;
+ }
+
+ public static int getRHAND(L2PcInstance actor)
+ {
+ int weaponRHANDId = actor.visualArmor.weaponRHANDId;
+ L2ItemInstance equipedItem = actor.getInventory().getPaperdollItem(Inventory.PAPERDOLL_RHAND);
+ int equipedItemId = actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_RHAND);
+ L2Item virtualItem = ItemTable.getInstance().getTemplate(weaponRHANDId);
+
+ if ((equipedItem == null) || (weaponRHANDId == 0))
+ {
+ return equipedItemId;
+ }
+
+ // Only check same weapon types. Virtual replacement should not happen between armor/weapons.
+ if ((equipedItem.getItem() instanceof L2Weapon) && (virtualItem instanceof L2Weapon))
+ {
+ L2Weapon weapon = (L2Weapon) equipedItem.getItem();
+ L2Weapon virtualweapon = (L2Weapon) virtualItem;
+
+ return weaponMatching(virtualweapon.getItemType(), weapon.getItemType(), weaponRHANDId, equipedItemId);
+ }
+ else if ((equipedItem.getItem() instanceof L2Armor) && (virtualItem instanceof L2Armor))
+ {
+ L2Armor armor = (L2Armor) equipedItem.getItem();
+ L2Armor virtualarmor = (L2Armor) virtualItem;
+
+ return armorMatching(virtualarmor.getItemType(), armor.getItemType(), weaponRHANDId, equipedItemId);
+ }
+ return equipedItemId;
+
+ }
+
+ public static int getCloak(L2PcInstance actor)
+ {
+ if (actor.visualArmor.weaponLRHANDId == 1)
+ {
+ return 0;
+ }
+ else
+ {
+ return actor.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CLOAK);
+ }
+
+ }
+
+ public static void dressMe(L2PcInstance activeChar)
+ {
+ setVirtualBody(activeChar);
+ setVirtualGloves(activeChar);
+ setVirtualPants(activeChar);
+ setVirtualBoots(activeChar);
+ setVirtualLhand(activeChar);
+ setVirtualRhand(activeChar);
+
+ InventoryUpdate iu = new InventoryUpdate();
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ InventoryUpdate iu2 = new InventoryUpdate();
+ activeChar.sendPacket(iu2);
+ activeChar.broadcastUserInfo();
+ activeChar.sendMessage("You changed clothes.");
+ activeChar.visualArmor.updateVisualArmor();
+ }
+}
Index: java/com/l2jserver/extensions/VisualArmorModel.java
===================================================================
--- java/com/l2jserver/extensions/VisualArmorModel.java (revision 0)
+++ java/com/l2jserver/extensions/VisualArmorModel.java (working copy)
@@ -0,0 +1,171 @@
+/*
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.extensions;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import com.l2jserver.L2DatabaseFactory;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
+
+/**
+ * @author Issle
+ *
+ */
+public class VisualArmorModel
+{
+ private static final String RESTORE_VISUAL_ARMOR = "SELECT GlovesId,ChestId,BootsId,PantsId,LeftHandId,RightHandId,DoubleHandId FROM visual_armor WHERE CharId=?";
+ private static final String UPDATE_VISUAL_ARMOR = "UPDATE visual_armor SET GlovesId=?,ChestId=?,BootsId=?,PantsId=?,LeftHandId=?,RightHandId=?,DoubleHandId=? WHERE CharId=?";
+ private static final String CREATE_VISUAL_ARMOR = "INSERT INTO visual_armor (CharId,GlovesId,ChestId,BootsId,PantsId,LeftHandId,RightHandId,DoubleHandId) values (?,?,?,?,?,?,?,?)";
+
+ public static final String CREATE =
+ "CREATE TABLE IF NOT EXISTS `visual_armor` (" +
+ "`CharId` int(11) NOT NULL," +
+ "`GlovesId` int(11) NOT NULL DEFAULT '0'," +
+ "`BootsId` int(11) NOT NULL DEFAULT '0'," +
+ "`ChestId` int(11) NOT NULL DEFAULT '0'," +
+ "`PantsId` int(11) NOT NULL DEFAULT '0'," +
+ "`LeftHandId` int(11) NOT NULL DEFAULT '0'," +
+ "`RightHandId` int(11) NOT NULL DEFAULT '0'," +
+ "`DoubleHandId` int(11) NOT NULL DEFAULT '0',PRIMARY KEY (`CharId`))";
+
+ public static final String DROP =
+ "DROP TABLE 'visual_armor'";
+
+ public int glovesTextureId=0;
+ public int armorTextureId=0;
+ public int pantsTextureId=0;
+ public int bootsTextureId=0;
+ public int weaponLHANDId=0;
+ public int weaponRHANDId=0;
+ public int weaponLRHANDId=0;
+ public int ownerId;
+
+
+ public void updateVisualArmor()
+ {
+ Connection con = null;
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(UPDATE_VISUAL_ARMOR);
+ statement.setInt(1, glovesTextureId);
+ statement.setInt(2, armorTextureId);
+ statement.setInt(3, bootsTextureId);
+ statement.setInt(4, pantsTextureId);
+ statement.setInt(5, weaponLHANDId);
+ statement.setInt(6, weaponRHANDId);
+ statement.setInt(7, weaponLRHANDId);
+ statement.setInt(8, ownerId);
+ statement.execute();
+ statement.close();
+
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ try { con.close(); } catch (Exception e) {}
+ }
+ }
+
+ public VisualArmorModel(L2PcInstance activeChar)
+ {
+ ownerId = activeChar.getObjectId();
+ Connection con = null;
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+
+ PreparedStatement statement = con.prepareStatement(RESTORE_VISUAL_ARMOR);
+ statement.setInt(1, ownerId);
+ ResultSet rset = statement.executeQuery();
+ boolean got = false;
+ while(rset.next())
+ {
+ glovesTextureId = rset.getInt("GlovesId");
+ armorTextureId = rset.getInt("ChestId");
+ pantsTextureId = rset.getInt("PantsId");
+ bootsTextureId = rset.getInt("BootsId");
+ weaponLHANDId = rset.getInt("LeftHandId");
+ weaponRHANDId = rset.getInt("RightHandId");
+ weaponLRHANDId = rset.getInt("DoubleHandId");
+ got = true;
+
+ }
+
+ rset.close();
+ statement.close();
+
+ if(got == false)
+ {
+ createVisualArmor();
+ }
+
+ InventoryUpdate iu = new InventoryUpdate();
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ InventoryUpdate iu2 = new InventoryUpdate();
+ activeChar.sendPacket(iu2);
+ activeChar.broadcastUserInfo();
+ activeChar.sendMessage("You changed clothes.");
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ try { con.close(); } catch (Exception e) {}
+ }
+ }
+
+ public void createVisualArmor() throws SQLException
+ {
+ Connection con = null;
+
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(CREATE_VISUAL_ARMOR);
+
+ statement.setInt(1, ownerId);
+ statement.setInt(2, 0);
+ statement.setInt(3, 0);
+ statement.setInt(4, 0);
+ statement.setInt(5, 0);
+ statement.setInt(6, 0);
+ statement.setInt(7, 0);
+ statement.setInt(8, 0);
+
+ statement.executeUpdate();
+ statement.close();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ try { con.close(); } catch (Exception e) {}
+ }
+ }
+
+}
+
Index: java/com/l2jserver/gameserver/GameServer.java
===================================================================
--- java/com/l2jserver/gameserver/GameServer.java (revision 6657)
+++ java/com/l2jserver/gameserver/GameServer.java (working copy)
@@ -37,6 +37,7 @@
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.Server;
import com.l2jserver.UPnPService;
+import com.l2jserver.extensions.VisualArmorController;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.datatables.AdminTable;
import com.l2jserver.gameserver.datatables.ArmorSetsData;
@@ -328,6 +331,7 @@
BoatManager.getInstance();
AirShipManager.getInstance();
GraciaSeedsManager.getInstance();
+ VisualArmorController.load();
CastleManager.getInstance().activateInstances();
FortManager.getInstance().activateInstances();
Index: java/com/l2jserver/gameserver/network/serverpackets/CharInfo.java
===================================================================
--- java/com/l2jserver/gameserver/network/serverpackets/CharInfo.java (revision 6657)
+++ java/com/l2jserver/gameserver/network/serverpackets/CharInfo.java (working copy)
@@ -19,6 +19,7 @@
package com.l2jserver.gameserver.network.serverpackets;
import com.l2jserver.Config;
+import com.l2jserver.extensions.VisualArmorController;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.instancemanager.CursedWeaponsManager;
import com.l2jserver.gameserver.model.PcCondOverride;
@@ -210,7 +211,32 @@
for (int slot : getPaperdollOrder())
{
- writeD(_activeChar.getInventory().getPaperdollItemDisplayId(slot));
+ switch (slot)
+ {
+ case 5:
+ writeD(VisualArmorController.getRHAND(_activeChar));
+ break;
+ case 6:
+ writeD(VisualArmorController.getVirtualBody(_activeChar));
+ break;
+ case 7:
+ writeD(VisualArmorController.getLHAND(_activeChar));
+ break;
+ case 10:
+ writeD(VisualArmorController.getVirtualGloves(_activeChar));
+ break;
+ case 11:
+ writeD(VisualArmorController.getVirtualPants(_activeChar));
+ break;
+ case 12:
+ writeD(VisualArmorController.getVirtualBoots(_activeChar));
+ break;
+ case 23:
+ writeD(VisualArmorController.getCloak(_activeChar));
+ break;
+ default:
+ writeD(_activeChar.getInventory().getPaperdollItemDisplayId(slot));
+ }
}
for (int slot : getPaperdollOrder())
Index: java/com/l2jserver/gameserver/network/serverpackets/UserInfo.java
===================================================================
--- java/com/l2jserver/gameserver/network/serverpackets/UserInfo.java (revision 6657)
+++ java/com/l2jserver/gameserver/network/serverpackets/UserInfo.java (working copy)
@@ -19,6 +19,7 @@
package com.l2jserver.gameserver.network.serverpackets;
import com.l2jserver.Config;
+import com.l2jserver.extensions.VisualArmorController;
import com.l2jserver.gameserver.datatables.ExperienceTable;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.instancemanager.CursedWeaponsManager;
@@ -123,7 +124,32 @@
for (int slot : getPaperdollOrder())
{
- writeD(_activeChar.getInventory().getPaperdollItemDisplayId(slot));
+ switch (slot)
+ {
+ case 5:
+ writeD(VisualArmorController.getRHAND(_activeChar));
+ break;
+ case 6:
+ writeD(VisualArmorController.getVirtualBody(_activeChar));
+ break;
+ case 7:
+ writeD(VisualArmorController.getLHAND(_activeChar));
+ break;
+ case 10:
+ writeD(VisualArmorController.getVirtualGloves(_activeChar));
+ break;
+ case 11:
+ writeD(VisualArmorController.getVirtualPants(_activeChar));
+ break;
+ case 12:
+ writeD(VisualArmorController.getVirtualBoots(_activeChar));
+ break;
+ case 23:
+ writeD(VisualArmorController.getCloak(_activeChar));
+ break;
+ default:
+ writeD(_activeChar.getInventory().getPaperdollItemDisplayId(slot));
+ }
}
for (int slot : getPaperdollOrder())
Index: java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
===================================================================
--- java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java (revision 6657)
+++ java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java (working copy)
@@ -51,6 +51,7 @@
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
+import com.l2jserver.extensions.VisualArmorModel;
import com.l2jserver.gameserver.Announcements;
import com.l2jserver.gameserver.GameTimeController;
import com.l2jserver.gameserver.GeoData;
@@ -342,6 +343,7 @@
*/
public final class L2PcInstance extends L2Playable
{
+ public VisualArmorModel visualArmor;
// Character Skill SQL String Definitions:
private static final String RESTORE_SKILLS_FOR_CHAR = "SELECT skill_id,skill_level FROM character_skills WHERE charId=? AND class_index=?";
private static final String ADD_NEW_SKILL = "INSERT INTO character_skills (charId,skill_id,skill_level,class_index) VALUES (?,?,?,?)";
@@ -1133,6 +1138,7 @@
_radar = new L2Radar(this);
startVitalityTask();
+ visualArmor = new VisualArmorModel(this);
}
@Override
Index: java/com/l2jserver/extensions/VisualArmorModel.java
===================================================================
--- java/com/l2jserver/extensions/VisualArmorModel.java (revision 0)
+++ java/com/l2jserver/extensions/VisualArmorModel.java (working copy)
@@ -0,0 +1,171 @@
+/*
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.l2jserver.extensions;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import com.l2jserver.L2DatabaseFactory;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
+
+/**
+ * @author Issle
+ *
+ */
+public class VisualArmorModel
+{
+ private static final String RESTORE_VISUAL_ARMOR = "SELECT GlovesId,ChestId,BootsId,PantsId,LeftHandId,RightHandId,DoubleHandId FROM visual_armor WHERE CharId=?";
+ private static final String UPDATE_VISUAL_ARMOR = "UPDATE visual_armor SET GlovesId=?,ChestId=?,BootsId=?,PantsId=?,LeftHandId=?,RightHandId=?,DoubleHandId=? WHERE CharId=?";
+ private static final String CREATE_VISUAL_ARMOR = "INSERT INTO visual_armor (CharId,GlovesId,ChestId,BootsId,PantsId,LeftHandId,RightHandId,DoubleHandId) values (?,?,?,?,?,?,?,?)";
+
+ public static final String CREATE =
+ "CREATE TABLE IF NOT EXISTS `visual_armor` (" +
+ "`CharId` int(11) NOT NULL," +
+ "`GlovesId` int(11) NOT NULL DEFAULT '0'," +
+ "`BootsId` int(11) NOT NULL DEFAULT '0'," +
+ "`ChestId` int(11) NOT NULL DEFAULT '0'," +
+ "`PantsId` int(11) NOT NULL DEFAULT '0'," +
+ "`LeftHandId` int(11) NOT NULL DEFAULT '0'," +
+ "`RightHandId` int(11) NOT NULL DEFAULT '0'," +
+ "`DoubleHandId` int(11) NOT NULL DEFAULT '0',PRIMARY KEY (`CharId`))";
+
+ public static final String DROP =
+ "DROP TABLE 'visual_armor'";
+
+ public int glovesTextureId=0;
+ public int armorTextureId=0;
+ public int pantsTextureId=0;
+ public int bootsTextureId=0;
+ public int weaponLHANDId=0;
+ public int weaponRHANDId=0;
+ public int weaponLRHANDId=0;
+ public int ownerId;
+
+
+ public void updateVisualArmor()
+ {
+ Connection con = null;
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(UPDATE_VISUAL_ARMOR);
+ statement.setInt(1, glovesTextureId);
+ statement.setInt(2, armorTextureId);
+ statement.setInt(3, bootsTextureId);
+ statement.setInt(4, pantsTextureId);
+ statement.setInt(5, weaponLHANDId);
+ statement.setInt(6, weaponRHANDId);
+ statement.setInt(7, weaponLRHANDId);
+ statement.setInt(8, ownerId);
+ statement.execute();
+ statement.close();
+
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ try { con.close(); } catch (Exception e) {}
+ }
+ }
+
+ public VisualArmorModel(L2PcInstance activeChar)
+ {
+ ownerId = activeChar.getObjectId();
+ Connection con = null;
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+
+ PreparedStatement statement = con.prepareStatement(RESTORE_VISUAL_ARMOR);
+ statement.setInt(1, ownerId);
+ ResultSet rset = statement.executeQuery();
+ boolean got = false;
+ while(rset.next())
+ {
+ glovesTextureId = rset.getInt("GlovesId");
+ armorTextureId = rset.getInt("ChestId");
+ pantsTextureId = rset.getInt("PantsId");
+ bootsTextureId = rset.getInt("BootsId");
+ weaponLHANDId = rset.getInt("LeftHandId");
+ weaponRHANDId = rset.getInt("RightHandId");
+ weaponLRHANDId = rset.getInt("DoubleHandId");
+ got = true;
+
+ }
+
+ rset.close();
+ statement.close();
+
+ if(got == false)
+ {
+ createVisualArmor();
+ }
+
+ InventoryUpdate iu = new InventoryUpdate();
+ activeChar.sendPacket(iu);
+ activeChar.broadcastUserInfo();
+ InventoryUpdate iu2 = new InventoryUpdate();
+ activeChar.sendPacket(iu2);
+ activeChar.broadcastUserInfo();
+ activeChar.sendMessage("You changed clothes.");
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ try { con.close(); } catch (Exception e) {}
+ }
+ }
+
+ public void createVisualArmor() throws SQLException
+ {
+ Connection con = null;
+
+ try
+ {
+ con = L2DatabaseFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(CREATE_VISUAL_ARMOR);
+
+ statement.setInt(1, ownerId);
+ statement.setInt(2, 0);
+ statement.setInt(3, 0);
+ statement.setInt(4, 0);
+ statement.setInt(5, 0);
+ statement.setInt(6, 0);
+ statement.setInt(7, 0);
+ statement.setInt(8, 0);
+
+ statement.executeUpdate();
+ statement.close();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ try { con.close(); } catch (Exception e) {}
+ }
+ }
+
+}
+
CitarINFO:
--- a/L2J_Server/java/com/l2jserver/gameserver/model/drops/CorpseDropItem.java
+++ b/L2J_Server/java/com/l2jserver/gameserver/model/drops/CorpseDropItem.java
@@ -20,6 +20,7 @@
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.actor.L2Character;
+import com.l2jserver.gameserver.model.stats.Stats;
/**
*
@@ -64,6 +65,6 @@
@Override
public double getChance(L2Character victim, L2Character killer)
{
- return super.getChance(victim, killer) * Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
+ return super.getChance(victim, killer) * Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER * ((killer.calcStat(Stats.BONUS_SPOIL, 0, null, null) / 100) + 1);
}
}
-------------------------------------------------------------------------------------------------------------------------------------
--- a/L2J_Server/java/com/l2jserver/gameserver/model/drops/DeathDropItem.java
+++ b/L2J_Server/java/com/l2jserver/gameserver/model/drops/DeathDropItem.java
@@ -20,6 +20,7 @@
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.actor.L2Character;
+import com.l2jserver.gameserver.model.stats.Stats;
/**
*
@@ -64,6 +65,6 @@
@Override
public double getChance(L2Character victim, L2Character killer)
{
- return super.getChance(victim, killer) * Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER;
+ return super.getChance(victim, killer) * Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER * ((killer.calcStat(Stats.BONUS_DROP, 0, null, null) / 100) + 1);
}
}
--------------------------------------------------------------------------------------------------------------------------------
--- a/L2J_Server/java/com/l2jserver/gameserver/model/drops/GroupedCorpseDropItem.java
+++ b/L2J_Server/java/com/l2jserver/gameserver/model/drops/GroupedCorpseDropItem.java
@@ -20,6 +20,7 @@
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.actor.L2Character;
+import com.l2jserver.gameserver.model.stats.Stats;
/**
* @author Nos
@@ -41,6 +42,6 @@
@Override
public double getChance(L2Character victim, L2Character killer)
{
- return super.getChance(victim, killer) * Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER;
+ return super.getChance(victim, killer) * Config.RATE_CORPSE_DROP_CHANCE_MULTIPLIER * ((killer.calcStat(Stats.BONUS_SPOIL, 0, null, null) / 100) + 1);
}
}
---------------------------------------------------------------------------------------------------------------------------------
--- a/L2J_Server/java/com/l2jserver/gameserver/model/drops/GroupedDeathDropItem.java
+++ b/L2J_Server/java/com/l2jserver/gameserver/model/drops/GroupedDeathDropItem.java
@@ -20,6 +20,7 @@
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.actor.L2Character;
+import com.l2jserver.gameserver.model.stats.Stats;
/**
*
@@ -41,6 +42,6 @@
@Override
public double getChance(L2Character victim, L2Character killer)
{
- return super.getChance(victim, killer) * Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER;
+ return super.getChance(victim, killer) * Config.RATE_DEATH_DROP_CHANCE_MULTIPLIER * ((killer.calcStat(Stats.BONUS_DROP, 0, null, null) / 100) + 1);
}
}
--------------------------------------------------------------------------------------------------------------------------------------
--- a/L2J_Server/java/com/l2jserver/gameserver/model/stats/Stats.java
+++ b/L2J_Server/java/com/l2jserver/gameserver/model/stats/Stats.java
@@ -87,6 +87,8 @@
EXPSP_RATE("rExp"),
BONUS_EXP("bonusExp"),
BONUS_SP("bonusSp"),
+ BONUS_DROP("bonusDrop"), // bonus drop
+ BONUS_SPOIL("bonusSpoil"), // bonus spoil
ATTACK_CANCEL("cancel"),
// ACCURACY & RANGE
--- /dev/null
+++ b/L2J_DataPack/dist/game/data/stats/skills/custom/rune.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/skills.xsd">
+ <skill id="30000" levels="2" name="Rune of Drop">
+ <!-- Confirmed CT2.5 -->
+ <table name="#bonusDrop"> 30 50 </table>
+ <table name="#icons"> br_cashtex.skill.br_cash_rune_of_exp_buff_3 br_cashtex.skill.br_cash_rune_of_exp_buff_5 </table>
+ <set name="icon" val="#icons" />
+ <set name="magicLvl" val="1" />
+ <set name="operateType" val="P" />
+ <set name="targetType" val="SELF" />
+ <for>
+ <effect name="Buff">
+ <add order="0x40" stat="bonusDrop" val="#bonusDrop" />
+ </effect>
+ </for>
+ </skill>
+ <skill id="30001" levels="2" name="Rune of Spoil">
+ <!-- Confirmed CT2.5 -->
+ <table name="#bonusSpoil"> 30 50 </table>
+ <table name="#icons"> br_cashtex.skill.br_cash_rune_of_exp_buff_3 br_cashtex.skill.br_cash_rune_of_exp_buff_5 </table>
+ <set name="icon" val="#icons" />
+ <set name="magicLvl" val="1" />
+ <set name="operateType" val="P" />
+ <set name="targetType" val="SELF" />
+ <for>
+ <effect name="Buff">
+ <add order="0x40" stat="bonusSpoil" val="#bonusSpoil" />
+ </effect>
+ </for>
+ </skill>
+</list>
\ No newline at end of file
-----------------------------------------------------------------------------------------------------------------------------
--- /dev/null
+++ b/L2J_DataPack/dist/game/data/stats/items/custom/rune.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/items.xsd">
+ <item id="30000" type="EtcItem" name="Rune of Drop 50% - 7 days limited period">
+ <set name="icon" val="br_cashtex.item.br_cash_rune_of_exp_i00" />
+ <set name="etcitem_type" val="RUNE" />
+ <set name="immediate_effect" val="true" />
+ <set name="material" val="PAPER" />
+ <set name="weight" val="120" />
+ <set name="is_tradable" val="false" />
+ <set name="is_dropable" val="false" />
+ <set name="is_sellable" val="false" />
+ <set name="is_premium" val="true" />
+ <set name="handler" val="ItemSkills" />
+ <set name="item_skill" val="30000-2" />
+ <set name="time" val="10080" />
+ </item>
+ <item id="30001" type="EtcItem" name="Rune of Spoil 50% - 7 days limited period">
+ <set name="icon" val="br_cashtex.item.br_cash_rune_of_exp_i00" />
+ <set name="etcitem_type" val="RUNE" />
+ <set name="immediate_effect" val="true" />
+ <set name="material" val="PAPER" />
+ <set name="weight" val="120" />
+ <set name="is_tradable" val="false" />
+ <set name="is_dropable" val="false" />
+ <set name="is_sellable" val="false" />
+ <set name="is_premium" val="true" />
+ <set name="handler" val="ItemSkills" />
+ <set name="item_skill" val="30001-2" />
+ <set name="time" val="10080" />
+ </item>
+</list>
30000 Rune of Drop 50% 7-day limited period a,Ancient characters which endow mysterious ability if stored in the inventory. It increases acquired Drop by 50%. The remaining period decreases even during log-off state. Cannot be exchanged or dropped.\0 -1 0 0 a, 0 0 a, 0 0 0 0 0 0 0 0 0 0 a, 1
30001 Rune of Spoil 50% 7-day limited period a,Ancient characters which endow mysterious ability if stored in the inventory. It increases acquired Spoil by 50%. The remaining period decreases even during log-off state. Cannot be exchanged or dropped.\0 -1 0 0 a, 0 0 a, 0 0 0 0 0 0 0 0 0 0 a, 1
2 30000 0 0 0 0 0 0 0 0 0 0 1 0 0 br_cashtex.item.br_cash_rune_of_exp_i00 -1 120 18 0 9BBEAD0 0 1 1 1 0 33 0
2 30001 0 0 0 0 0 0 0 0 0 0 1 0 0 br_cashtex.item.br_cash_rune_of_exp_i00 -1 120 18 0 9BBEAD0 0 1 1 1 0 33 0
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
/*
* 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.custom;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.events.Containers;
import com.l2jserver.gameserver.model.events.EventType;
import com.l2jserver.gameserver.model.events.impl.character.player.inventory.OnPlayerItemAdd;
import com.l2jserver.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
/**
* @author Zealar
*/
public class AutoAdenaBar
{
public AutoAdenaBar()
{
Containers.Players().addListener(new ConsumerEventListener(Containers.Players(), EventType.ON_PLAYER_ITEM_ADD, (OnPlayerItemAdd event) -> OnPlayerItemAdd(event), this));
}
/**
* @param event
* @return
*/
private Object OnPlayerItemAdd(OnPlayerItemAdd event)
{
L2PcInstance player = event.getActiveChar();
L2ItemInstance item = event.getItem();
if (item.getId() != 57)
{
return null;
}
if (player.getAdena() > 1100000000)
{
player.getInventory().reduceAdena("goldbar", 1000000000, player, null);
player.getInventory().addItem("goldbar", 3470, 1, player, null);
}
return null;
}
}
// Custom Handlers
AutoAdenaBar.class,
### Eclipse Workspace Patch 1.0
#P L2J_Server
Index: dist/game/config/L2JMods.properties
===================================================================
--- dist/game/config/L2JMods.properties (revision 6353)
+++ dist/game/config/L2JMods.properties (working copy)
@@ -3,6 +3,24 @@
# Be warned that there may be no support for these mods beyond the original author's assistance.
# ---------------------------------------------------------------------------
+# Subclass Acu by fissban
+# ---------------------------------------------------------------------------
+
+# Aqui activamos el sistema de subclass Acu
+# default false
+AcumulativeSkills = false
+
+# Aqui activamos para que solo se acumulen los skills pasivos
+AcumulativeSkillsPasive = False
+
+# Aqui activamos por si solo queremos q cierto skills no se acumulen, como por ejemplo los
+# skills de 3ra y bien los pasivos de armas y armaduras
+DontAcumulativeSkills = False
+
+# Aqui definimos los skills q no se acumularan
+DontAcumulativeSkillsId = 351;349
+
+# ---------------------------------------------------------------------------
# Champion mobs - Turn random mobs into Champions
# ---------------------------------------------------------------------------
Index: java/com/l2jserver/Config.java
===================================================================
--- java/com/l2jserver/Config.java (revision 6353)
+++ java/com/l2jserver/Config.java (working copy)
@@ -103,6 +103,11 @@
public static final String SECURITY_CONFIG_FILE = "./config/Security.properties";
public static final String EMAIL_CONFIG_FILE = "./config/Email.properties";
public static final String CH_SIEGE_FILE = "./config/ConquerableHallSiege.properties";
+
+ public static boolean ACUMULATIVE_SUBCLASS_SKILLS;
+ public static boolean ACUMULATIVE_SUBCLASS_PASIVE;
+ public static boolean ACUMULATIVE_SUBCLASS_DONT_SKILLS;
+ public static String[] ACUMULATIVE_SUBCLASS_DONT_SKILLS_ID;
// --------------------------------------------------
// L2J Variable Definitions
// --------------------------------------------------
@@ -2429,6 +2434,10 @@
_log.log(Level.SEVERE, "Error while loading L2JMod settings!", e);
}
+ ACUMULATIVE_SUBCLASS_SKILLS = Boolean.parseBoolean(L2JModSettings.getProperty("AcumulativeSkills", "false"));
+ ACUMULATIVE_SUBCLASS_PASIVE = Boolean.parseBoolean(L2JModSettings.getProperty("AcumulativeSkillsPasive", "false"));
+ ACUMULATIVE_SUBCLASS_DONT_SKILLS = Boolean.parseBoolean(L2JModSettings.getProperty("DontAcumulativeSkills", "true"));
+ ACUMULATIVE_SUBCLASS_DONT_SKILLS_ID = String.valueOf(L2JModSettings.getProperty("DontAcumulativeSkillsId", "351")).split(";");
L2JMOD_CHAMPION_ENABLE = Boolean.parseBoolean(L2JModSettings.getProperty("ChampionEnable", "false"));
L2JMOD_CHAMPION_PASSIVE = Boolean.parseBoolean(L2JModSettings.getProperty("ChampionPassive", "false"));
L2JMOD_CHAMPION_FREQUENCY = Integer.parseInt(L2JModSettings.getProperty("ChampionFrequency", "0"));
Index: java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java
===================================================================
--- java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java (revision 6511)
+++ java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java (working copy)
@@ -310,6 +310,8 @@
*/
public final class L2PcInstance extends L2Playable
{
+ // SubAcu by fissban
+ private static final String ACUMULATE_SKILLS_FOR_CHAR_SUB = "SELECT skill_id,skill_level,class_index FROM character_skills WHERE charId=? ORDER BY skill_id,skill_level ASC";
// Character Skill SQL String Definitions:
private static final String RESTORE_SKILLS_FOR_CHAR = "SELECT skill_id,skill_level FROM character_skills WHERE charId=? AND class_index=?";
private static final String ADD_NEW_SKILL = "INSERT INTO character_skills (charId,skill_id,skill_level,class_index) VALUES (?,?,?,?)";
@@ -8560,50 +8562,129 @@
*/
private void restoreSkills()
{
- try (Connection con = L2DatabaseFactory.getInstance().getConnection();
- PreparedStatement statement = con.prepareStatement(RESTORE_SKILLS_FOR_CHAR))
+ if (Config.ACUMULATIVE_SUBCLASS_SKILLS)
{
- // Retrieve all skills of this L2PcInstance from the database
- statement.setInt(1, getObjectId());
- statement.setInt(2, getClassIndex());
- final ResultSet rset = statement.executeQuery();
-
- // Go though the recordset of this SQL query
- while (rset.next())
+ try (Connection con = L2DatabaseFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(ACUMULATE_SKILLS_FOR_CHAR_SUB))
{
- final int id = rset.getInt("skill_id");
- final int level = rset.getInt("skill_level");
-
- // Create a L2Skill object for each record
- final L2Skill skill = SkillTable.getInstance().getInfo(id, level);
-
- if (skill == null)
+ statement.setInt(1, getObjectId());
+ // statement.setInt(2, getClassIndex());
+ try (ResultSet rset = statement.executeQuery())
{
- _log.warning("Skipped null skill Id: " + id + " Level: " + level + " while restoring player skills for playerObjId: " + getObjectId());
- continue;
+
+ // Go though the recordset of this SQL query
+ while (rset.next())
+ {
+ final int id = rset.getInt("skill_id");
+ final int level = rset.getInt("skill_level");
+ final int class_index = rset.getInt("class_index");
+
+ // Create a L2Skill object for each record
+ final L2Skill skill = SkillTable.getInstance().getInfo(id, level);
+
+ if (skill == null)
+ {
+ _log.warning("Skipped null skill Id: " + id + " Level: " + level + " while restoring player skills for playerObjId: " + getObjectId());
+ continue;
+ }
+
+ if (getClassIndex() != class_index)
+ {
+ // solo acumulamos activos.
+ if (Config.ACUMULATIVE_SUBCLASS_PASIVE && skill.isPassive())
+ {
+ continue;
+ }
+
+ // no acumulamos algunos skills especificos.
+ if (Config.ACUMULATIVE_SUBCLASS_SKILLS)
+ {
+ for (String skillId : Config.ACUMULATIVE_SUBCLASS_DONT_SKILLS_ID)
+ {
+ try
+ {
+ if (Integer.getInteger(skillId) == id)
+ {
+ continue;
+ }
+ }
+ catch (Exception e)
+ {
+ _log.warning("los skills usados en DontAcumulativeSkillsId no esta bien escrito ¬¬");
+ }
+ }
+ }
+ }
+
+ // Add the L2Skill object to the L2Character _skills and its Func objects to the calculator set of the L2Character
+ addSkill(skill);
+
+ if (Config.SKILL_CHECK_ENABLE && (!canOverrideCond(PcCondOverride.SKILL_CONDITIONS) || Config.SKILL_CHECK_GM))
+ {
+ if (!SkillTreesData.getInstance().isSkillAllowed(this, skill))
+ {
+ Util.handleIllegalPlayerAction(this, "Player " + getName() + " has invalid skill " + skill.getName() + " (" + skill.getId() + "/" + skill.getLevel() + "), class:" + ClassListData.getInstance().getClass(getClassId()).getClassName(), 1);
+ if (Config.SKILL_CHECK_REMOVE)
+ {
+ removeSkill(skill);
+ }
+ }
+ }
+ }
}
-
- // Add the L2Skill object to the L2Character _skills and its Func objects to the calculator set of the L2Character
- addSkill(skill);
-
- if (Config.SKILL_CHECK_ENABLE && (!canOverrideCond(PcCondOverride.SKILL_CONDITIONS) || Config.SKILL_CHECK_GM))
+ }
+ catch (Exception e)
+ {
+ _log.log(Level.WARNING, "Could not restore character " + this + " skills: " + e.getMessage(), e);
+ }
+ }
+ else
+ {
+ try (Connection con = L2DatabaseFactory.getInstance().getConnection();
+ PreparedStatement statement = con.prepareStatement(RESTORE_SKILLS_FOR_CHAR))
+ {
+ // Retrieve all skills of this L2PcInstance from the database
+ statement.setInt(1, getObjectId());
+ statement.setInt(2, getClassIndex());
+ try (ResultSet rset = statement.executeQuery())
{
- if (!SkillTreesData.getInstance().isSkillAllowed(this, skill))
+ // Go though the recordset of this SQL query
+ while (rset.next())
{
- Util.handleIllegalPlayerAction(this, "Player " + getName() + " has invalid skill " + skill.getName() + " (" + skill.getId() + "/" + skill.getLevel() + "), class:" + ClassListData.getInstance().getClass(getClassId()).getClassName(), 1);
- if (Config.SKILL_CHECK_REMOVE)
+ final int id = rset.getInt("skill_id");
+ final int level = rset.getInt("skill_level");
+
+ // Create a L2Skill object for each record
+ final L2Skill skill = SkillTable.getInstance().getInfo(id, level);
+
+ if (skill == null)
{
- removeSkill(skill);
+ _log.warning("Skipped null skill Id: " + id + " Level: " + level + " while restoring player skills for playerObjId: " + getObjectId());
+ continue;
}
+
+ // Add the L2Skill object to the L2Character _skills and its Func objects to the calculator set of the L2Character
+ addSkill(skill);
+
+ if (Config.SKILL_CHECK_ENABLE && (!canOverrideCond(PcCondOverride.SKILL_CONDITIONS) || Config.SKILL_CHECK_GM))
+ {
+ if (!SkillTreesData.getInstance().isSkillAllowed(this, skill))
+ {
+ Util.handleIllegalPlayerAction(this, "Player " + getName() + " has invalid skill " + skill.getName() + " (" + skill.getId() + "/" + skill.getLevel() + "), class:" + ClassListData.getInstance().getClass(getClassId()).getClassName(), 1);
+ if (Config.SKILL_CHECK_REMOVE)
+ {
+ removeSkill(skill);
+ }
+ }
+ }
}
}
}
- rset.close();
+ catch (Exception e)
+ {
+ _log.log(Level.WARNING, "Could not restore character " + this + " skills: " + e.getMessage(), e);
+ }
}
- catch (Exception e)
- {
- _log.log(Level.WARNING, "Could not restore character " + this + " skills: " + e.getMessage(), e);
- }
}
/**
Hopzone.java
-------------------------------------------------------------------------------------------------
package com.l2jserver.gameserver.votereward;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import static com.l2jserver.gameserver.config.Configuration.voteSystem;
/**
* Hopzone Vote System.
* @author CIAurelius
*/
public class Hopzone extends VoteSystem
{
public Hopzone(int votesDiff, boolean allowReport, int boxes, Map<Integer, Integer> rewards, int checkMins)
{
super(votesDiff, allowReport, boxes, rewards, checkMins);
}
public void run()
{
reward();
}
public int getVotes()
{
int votes = 1;
try
{
URLConnection con = new URL(voteSystem().hopzoneServerLink()).openConnection();
con.addRequestProperty("User-Agent", "Mozilla/5.0");
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = br.readLine()) != null)
{
if (line.contains("Total Votes"))
{
String inputLine = line.split(">")[2].replace("</span", "");
votes = Integer.parseInt(inputLine);
}
}
br.close();
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Error while getting server vote count from " + getSiteName() + ".");
}
return votes;
}
public String getSiteName()
{
return "[Hopzone]";
}
}
Topzone.java
-------------------------------------------------------------------------------------------------
package com.l2jserver.gameserver.votereward;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import static com.l2jserver.gameserver.config.Configuration.voteSystem;
/**
* Topzone Vote System.
* @author CIAurelius
*/
public class Topzone extends VoteSystem
{
public Topzone(int votesDiff, boolean allowReport, int boxes, Map<Integer, Integer> rewards, int checkMins)
{
super(votesDiff, allowReport, boxes, rewards, checkMins);
}
public void run()
{
reward();
}
public int getVotes()
{
int votes = -1;
try
{
URLConnection con = new URL(voteSystem().topzoneServerLink()).openConnection();
con.addRequestProperty("User-Agent", "Mozilla/5.0");
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
StringBuilder builder = new StringBuilder();
if ((line = br.readLine()) != null)
{
if (line.contains("fa fa-fw fa-lg fa-thumbs-up"))
{
String inputLine = line.split("fa fa-fw fa-lg fa-thumbs-up")[1].replace("\"></i>", "");
for (int i = 0; i < inputLine.length(); i++) {
char c = inputLine.charAt(i);
if (c == '<') {
break;
}
builder.append(c);
}
votes = Integer.parseInt(builder.toString());
}
}
br.close();
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Error while getting server vote count from " + getSiteName() + ".");
}
return votes;
}
public String getSiteName()
{
return "[Topzone]";
}
}
VoteSystem.java
-------------------------------------------------------------------------------------------------
package com.l2jserver.gameserver.votereward;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import static com.l2jserver.gameserver.config.Configuration.voteSystem;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
import com.l2jserver.gameserver.util.Broadcast;
/**
* Vote System.
* @author CIAurelius
*/
public abstract class VoteSystem implements Runnable
{
private static List<VoteSystem> voteSystems = new ArrayList<>();
private static Logger _log = Logger.getLogger(VoteSystem.class.getName());
protected int votesDiff;
protected boolean allowReport;
protected int boxes;
protected Map<Integer, Integer> rewards;
protected int checkMins;
protected int lastVotes = 0;
private final Map<String, Integer> playerIps = new HashMap<>();
public static void initializeHopzone()
{
if (voteSystem().hopzoneVoteReward())
{
_log.info("Hopzone: Loaded.");
voteSystems.add(new Hopzone(voteSystem().hopzoneVotesDifference(), voteSystem().hopzoneGameServerReport(), voteSystem().hopzoneDualBoxesAllowed(), voteSystem().hopzoneReward(), voteSystem().hopzoneRewardCheckTime()));
}
}
public static void initializeTopzone()
{
if (voteSystem().topzoneVoteReward())
{
_log.info("Topzone: Loaded.");
voteSystems.add(new Topzone(voteSystem().topzoneVotesDifference(), voteSystem().topzoneGameServerReport(), voteSystem().topzoneDualBoxesAllowed(), voteSystem().topzoneReward(), voteSystem().topzoneRewardCheckTime()));
}
}
public static VoteSystem getVoteSystem(String name)
{
for (VoteSystem vs : voteSystems)
{
if (vs.getSiteName().equals(name))
{
return vs;
}
}
return null;
}
public VoteSystem(int votesDiff, boolean allowReport, int boxes, Map<Integer, Integer> rewards, int checkMins)
{
this.votesDiff = votesDiff;
this.allowReport = allowReport;
this.boxes = boxes;
this.rewards = rewards;
this.checkMins = checkMins;
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(this, checkMins * 1000 * 60, checkMins * 1000 * 60);
}
protected void reward()
{
int currentVotes = getVotes();
if (currentVotes == -1)
{
System.out.println("There was a problem on getting server votes.");
return;
}
if (this.lastVotes == 0)
{
this.lastVotes = currentVotes;
announce(getSiteName() + ": Current vote count is " + currentVotes + ".");
announce(getSiteName() + ": We need " + ((this.lastVotes + this.votesDiff) - currentVotes) + " vote(s) for reward.");
if (this.allowReport)
{
System.out.println("Server votes on " + getSiteName() + ": " + currentVotes);
System.out.println("Votes needed for reward: " + ((this.lastVotes + this.votesDiff) - currentVotes));
}
return;
}
if (currentVotes >= (this.lastVotes + this.votesDiff))
{
Collection<L2PcInstance> pls = L2World.getInstance().getPlayers();
if (this.allowReport)
{
System.out.println("Server votes on " + getSiteName() + ": " + currentVotes);
System.out.println("Votes needed for next reward: " + ((currentVotes + this.votesDiff) - currentVotes));
}
announce(getSiteName() + ": Everyone has been rewarded.");
announce(getSiteName() + ": Current vote count is " + currentVotes + ".");
announce(getSiteName() + ": We need " + this.votesDiff + " vote(s) for next reward.");
for (L2PcInstance p : pls)
{
if ((p.getClient() != null) && (!p.getClient().isDetached()))
{
boolean canReward = false;
String pIp = p.getClient().getConnection().getInetAddress().getHostAddress();
int count;
if (this.playerIps.containsKey(pIp))
{
count = this.playerIps.get(pIp).intValue();
if (count < this.boxes)
{
this.playerIps.remove(pIp);
this.playerIps.put(pIp, Integer.valueOf(count + 1));
canReward = true;
}
}
else
{
canReward = true;
this.playerIps.put(pIp, Integer.valueOf(1));
}
if (canReward)
{
for (int i : rewards.keySet())
{
p.addItem("Vote reward.", i, this.rewards.get(Integer.valueOf(i)).intValue(), p, true);
}
}
else
{
p.sendMessage("Already " + this.boxes + " character(s) of your ip have been rewarded, so this character won't be rewarded.");
}
}
}
this.playerIps.clear();
this.lastVotes = currentVotes;
}
else
{
if (this.allowReport)
{
System.out.println("Server votes on " + getSiteName() + ": " + currentVotes);
System.out.println("Votes needed for next reward: " + ((this.lastVotes + this.votesDiff) - currentVotes));
}
announce(getSiteName() + ": Current vote count is " + currentVotes + ".");
announce(getSiteName() + ": We need " + ((this.lastVotes + this.votesDiff) - currentVotes) + " vote(s) for reward.");
}
}
private static void announce(String msg)
{
CreatureSay cs = new CreatureSay(0, 18, "", msg);
Broadcast.toAllOnlinePlayers(cs);
}
public abstract int getVotes();
public abstract String getSiteName();
}
Configuration.java
-------------------------------------------------------------------------------------------------
private static final VoteSystemConfiguration voteSystem = ConfigFactory.create(VoteSystemConfiguration.class);
public static VoteSystemConfiguration voteSystem() {
return voteSystem;
}
VoteSystemConfiguration.java
-------------------------------------------------------------------------------------------------
package com.l2jserver.gameserver.config;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.aeonbits.owner.Config.HotReloadType.ASYNC;
import static org.aeonbits.owner.Config.LoadType.MERGE;
import java.util.Map;
import org.aeonbits.owner.Reloadable;
import org.aeonbits.owner.Config.HotReload;
import org.aeonbits.owner.Config.LoadPolicy;
import org.aeonbits.owner.Config.Sources;
import com.l2jserver.gameserver.config.converter.MapIntegerIntegerConverter;
/**
* Vote System Configuration.
* @author CIAurelius
*/
@Sources({
"file:${L2J_HOME}/custom/game/config/votesystem.properties",
"file:./config/votesystem.properties",
"classpath:config/votesystem.properties"
})
@LoadPolicy(MERGE)
@HotReload(value = 5, unit = MINUTES, type = ASYNC)
public interface VoteSystemConfiguration extends Reloadable
{
@Key("HopzoneVotesDifference")
Integer hopzoneVotesDifference();
@Key("TopzoneVotesDifference")
Integer topzoneVotesDifference();
@Key("HopzoneRewardCheckTime")
Integer hopzoneRewardCheckTime();
@Key("TopzoneRewardCheckTime")
Integer topzoneRewardCheckTime();
@Key("HopzoneDualboxesAllowed")
Integer hopzoneDualBoxesAllowed();
@Key("TopzoneDualboxesAllowed")
Integer topzoneDualBoxesAllowed();
@Key("HopzoneReward")
@ConverterClass(MapIntegerIntegerConverter.class)
Map<Integer, Integer> hopzoneReward();
@Key("TopzoneReward")
@ConverterClass(MapIntegerIntegerConverter.class)
Map<Integer, Integer> topzoneReward();
@Key("HopzoneServerLink")
String hopzoneServerLink();
@Key("AllowHopzoneVoteReward")
Boolean hopzoneVoteReward();
@Key("TopzoneServerLink")
String topzoneServerLink();
@Key("AllowTopzoneVoteReward")
Boolean topzoneVoteReward();
@Key("AllowHopzoneGameServerReport")
Boolean hopzoneGameServerReport();
@Key("AllowTopzoneGameServerReport")
Boolean topzoneGameServerReport();
}
GameServer.java
-------------------------------------------------------------------------------------------------
import static com.l2jserver.gameserver.config.Configuration.voteSystem;
printSection("Customs");
if ((voteSystem().hopzoneVoteReward()) && (voteSystem().topzoneVoteReward())){
VoteSystem.initializeHopzone();
VoteSystem.initializeTopzone();
}
else if (voteSystem().hopzoneVoteReward()){
VoteSystem.initializeHopzone();
}
else if (voteSystem().topzoneVoteReward()){
VoteSystem.initializeTopzone();
}
VoteReward.properties
-------------------------------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# L2JVoteReward - non-retail-like systems that have been integrated into the L2J project.
# Be warned that there may be no support for these custom beyond the original author's assistance.
# ---------------------------------------------------------------------------
# Vote Reward System
# ---------------------------------------------------------------------------
# Vote reward for Hopzone.
AllowHopzoneVoteReward = True
# e.g. VoteHtmlPatch = https://l2.hopzone.net/lineage2/details/93067/L2-DAMAGE.html
# Vote reward server link. (IMPORTANT!!!! Always add .html at the end of the link)
HopzoneServerLink = https://l2.hopzone.net/lineage2/details/93067/L2-DAMAGE.html
# Votes for next reward needed.
HopzoneVotesDifference = 10
# Minutes between rewards.
# Eg. You put 5 it checks every 5 minutes for reward.
HopzoneRewardCheckTime = 5
# Reward(s).
HopzoneReward = 3481,5;
# Topzone reward max dual boxes reward.
# For example if you put 2 and someone has 3 boxes open 2 will be rewarded.
HopzoneDualboxesAllowed = 1
# Game server console report.
# If set to true, game server console will get a report of
# current vote count, votes needed for next reward and votes needed for first page.
AllowHopzoneGameServerReport = True
# Vote reward for Topzone.
AllowTopzoneVoteReward = True
# e.g. VoteHtmlPatch = http://l2topzone.com/tv.php?id=6084.html
# Vote reward server link. (IMPORTANT!!!! Always add .html at the end of the link)
TopzoneServerLink = http://l2topzone.com/tv.php?id=6084.html
# Votes for next reward needed.
TopzoneVotesDifference = 10
# Minutes between rewards.
# Eg. You put 7 it checks every 7 minutes for reward.
TopzoneRewardCheckTime = 7
# Reward(s).
TopzoneReward = 3481,5;
# Topzone reward max dual boxes reward.
# For example if you put 2 and someone has 3 boxes open 2 will be rewarded.
TopzoneDualboxesAllowed = 1
# Game server console report.
# If set to true, game server console will get a report of
# current vote count, votes needed for next reward and votes needed for first page.
AllowTopzoneGameServerReport = True
+ VoteSystem.initializeHopzone();
+ VoteSystem.initializeTopzone();