### Eclipse Workspace Patch 1.0 #P aCis_gameserver Index: java/net/sf/l2j/gameserver/handler/AdminCommandHandler.java =================================================================== --- java/net/sf/l2j/gameserver/handler/AdminCommandHandler.java (revision 5) +++ java/net/sf/l2j/gameserver/handler/AdminCommandHandler.java (working copy) @@ -63,6 +63,7 @@ import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminSpawn; import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminTarget; import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminTeleport; +import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminVipStatus; import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminZone; public class AdminCommandHandler @@ -123,6 +124,7 @@ registerAdminCommandHandler(new AdminTarget()); registerAdminCommandHandler(new AdminTeleport()); registerAdminCommandHandler(new AdminZone()); + registerAdminCommandHandler(new AdminVipStatus()); } public void registerAdminCommandHandler(IAdminCommandHandler handler) Index: config/vip.properties =================================================================== --- config/vip.properties (nonexistent) +++ config/vip.properties (working copy) @@ -0,0 +1,25 @@ +# ================================================ +# VIP System +# ================================================ +# If True, player can got VIP Status by item. +VipItemEnabled = True + +# Id of VIP Item. +# Do not forget to add the item handler on xml/items 3481. +# +VipItemId = 3481 + +# Days of VIP. +VipDays = 10 + +# Set Exp/Sp/Drop. +VipExp/SpRates = 50 +VipAdenaDrop = 50 +VipSpoilRates = 50 +VipRaidDrop = 1 +VipDrop = 1 + +# Set Enchant Chance. +VipEnchantChanceArmor = 0.77 +VipEnchantChanceWeapon15Plus = 0.77 +VipEnchantChanceWeapon = 0.77 \ No newline at end of file Index: java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminVipStatus.java =================================================================== --- java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminVipStatus.java (nonexistent) +++ java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminVipStatus.java (working copy) @@ -0,0 +1,134 @@ +/* + * 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 . + */ +package net.sf.l2j.gameserver.handler.admincommandhandlers; + +import java.util.StringTokenizer; +import java.util.concurrent.TimeUnit; + +import net.sf.l2j.gameserver.handler.IAdminCommandHandler; +import net.sf.l2j.gameserver.model.World; +import net.sf.l2j.gameserver.model.actor.instance.Player; +import net.sf.l2j.gameserver.network.clientpackets.Say2; +import net.sf.l2j.gameserver.network.serverpackets.CreatureSay; +import net.sf.l2j.gameserver.network.serverpackets.SocialAction; +import net.sf.l2j.gameserver.taskmanager.VipTimeTaskManager; + +/** + * @author Baggos + */ +public class AdminVipStatus implements IAdminCommandHandler +{ + private static String[] _adminCommands = new String[] + { + "admin_vipon", + "admin_vipoff" + }; + + @Override + public boolean useAdminCommand(String command, Player activeChar) + { + StringTokenizer st = new StringTokenizer(command); + st.nextToken(); + String player = ""; + int time = 1; + Player target = null; + if (st.hasMoreTokens()) + { + player = st.nextToken(); + target = World.getInstance().getPlayer(player); + if (st.hasMoreTokens()) + { + try + { + time = Integer.parseInt(st.nextToken()); + } + catch (NumberFormatException nfe) + { + activeChar.sendMessage("Invalid number format used: " + nfe); + return false; + } + } + } + else if (activeChar.getTarget() != null && activeChar.getTarget() instanceof Player) + target = (Player) activeChar.getTarget(); + + if (command.startsWith("admin_vipon")) + { + if (target == null && player.equals("")) + { + activeChar.sendMessage("Usage: //vipon [days]"); + return false; + } + if (target != null) + { + AdminVipStatus.AddVipStatus(target, activeChar, time); + activeChar.sendMessage(target.getName() + " got VIP Status for " + time + " day(s)."); + } + } + else if (command.startsWith("admin_vipoff")) + { + if (target == null && player.equals("")) + { + activeChar.sendMessage("Usage: //removevip "); + return false; + } + if (target != null) + { + if (target.isVipStatus()) + { + AdminVipStatus.RemoveVipStatus(target); + activeChar.sendMessage(target.getName() + "'s VIP Status has been removed."); + } + else + activeChar.sendMessage("Player " +target.getName() + " is not an VIP."); + } + } + return true; + } + + public static void AddVipStatus(Player target, Player player, int time) + { + target.broadcastPacket(new SocialAction(target, 16)); + target.setVipStatus(true); + VipTimeTaskManager.getInstance().add(target); + long remainingTime = target.getMemos().getLong("TimeOfVip", 0); + if (remainingTime > 0) + { + target.getMemos().set("TimeOfVip", remainingTime + TimeUnit.DAYS.toMillis(time)); + target.sendPacket(new CreatureSay(0, Say2.HERO_VOICE, "VIP Manager", "Dear " + player.getName() + ", your VIP status has been extended by " + time + " day(s).")); + } + else + { + target.getMemos().set("TimeOfVip", System.currentTimeMillis() + TimeUnit.DAYS.toMillis(time)); + target.sendPacket(new CreatureSay(0, Say2.HERO_VOICE, "VIP Manager", "Dear " + player.getName() + ", you got VIP Status for " + time + " day(s).")); + target.broadcastUserInfo(); + } + } + + public static void RemoveVipStatus(Player target) + { + VipTimeTaskManager.getInstance().remove(target); + target.getMemos().set("TimeOfVip", 0); + target.setVipStatus(false); + target.broadcastPacket(new SocialAction(target, 13)); + target.broadcastUserInfo(); + } + + @Override + public String[] getAdminCommandList() + { + return _adminCommands; + } +} Index: java/net/sf/l2j/gameserver/taskmanager/VipTimeTaskManager.java =================================================================== --- java/net/sf/l2j/gameserver/taskmanager/VipTimeTaskManager.java (nonexistent) +++ java/net/sf/l2j/gameserver/taskmanager/VipTimeTaskManager.java (working copy) @@ -0,0 +1,75 @@ +/* + * 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 . + */ +package net.sf.l2j.gameserver.taskmanager; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import net.sf.l2j.commons.concurrent.ThreadPool; +import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminVipStatus; +import net.sf.l2j.gameserver.model.actor.instance.Player; + +/** + * @author Baggos + */ +public class VipTimeTaskManager implements Runnable +{ + private final Map _players = new ConcurrentHashMap<>(); + + protected VipTimeTaskManager() + { + // Run task each 10 second. + ThreadPool.scheduleAtFixedRate(this, 10000, 10000); + } + + public final void add(Player player) + { + _players.put(player, System.currentTimeMillis()); + } + + public final void remove(Player player) + { + _players.remove(player); + } + + @Override + public final void run() + { + if (_players.isEmpty()) + return; + + for (Map.Entry entry : _players.entrySet()) + { + final Player player = entry.getKey(); + + if (player.getMemos().getLong("TimeOfVip") < System.currentTimeMillis()) + { + AdminVipStatus.RemoveVipStatus(player); + remove(player); + } + } + } + + public static final VipTimeTaskManager getInstance() + { + return SingletonHolder._instance; + } + + private static class SingletonHolder + { + protected static final VipTimeTaskManager _instance = new VipTimeTaskManager(); + } +} Index: java/net/sf/l2j/Config.java =================================================================== --- java/net/sf/l2j/Config.java (revision 5) +++ java/net/sf/l2j/Config.java (working copy) @@ -49,10 +49,26 @@ public static final String LOGIN_CONFIGURATION_FILE = "./config/loginserver.properties"; public static final String NPCS_FILE = "./config/npcs.properties"; public static final String PLAYERS_FILE = "./config/players.properties"; + public static final String VIP_FILE = "./config/vip.properties"; public static final String SERVER_FILE = "./config/server.properties"; public static final String SIEGE_FILE = "./config/siege.properties"; public static final void loadGameServer() { _log.info("Loading gameserver configuration files."); // clans settings loadClans(); + // Vip settings + loadVip(); // -------------------------------------------------- + // VIP settings + // -------------------------------------------------- + public static boolean ENABLE_VIP_ITEM; + public static int VIP_ITEM_ID; + public static int VIP_DAYS; + public static int VIP_XP_SP_RATES; + public static int VIP_ADENA_RATES; + public static int VIP_SPOIL_RATES; + public static int VIP_RATE_DROP_ITEMS_BY_RAID; + public static int VIP_DROP_RATES; + public static double VIP_ENCHANT_CHANCE_ARMOR; + public static double VIP_ENCHANT_CHANCE_WEAPON_15PLUS; + public static double VIP_ENCHANT_CHANCE_WEAPON; + + // -------------------------------------------------- // Clans settings // -------------------------------------------------- @@ -687,6 +703,22 @@ MAX_MONSTER_ANIMATION = npcs.getProperty("MaxMonsterAnimation", 40); } /** * Loads player settings.
* Such as stats, inventory/warehouse, enchant, augmentation, karma, party, admin, petition, skill learn. */ + private static final void loadVip() + { + // VIP settings + ExProperties vip = initProperties(VIP_FILE); + ENABLE_VIP_ITEM = vip.getProperty("VipItemEnabled", true); + VIP_ITEM_ID = vip.getProperty("VipItemId", 3481); + VIP_DAYS = vip.getProperty("VipDays", 5); + + VIP_XP_SP_RATES = vip.getProperty("VipExp/SpRates", 1000); + VIP_ADENA_RATES = vip.getProperty("VipAdenaDrop", 1000); + VIP_SPOIL_RATES = vip.getProperty("VipSpoilRates", 1000); + VIP_RATE_DROP_ITEMS_BY_RAID = vip.getProperty("VipRaidDrop", 1); + VIP_DROP_RATES = vip.getProperty("VipDrop", 1); + + VIP_ENCHANT_CHANCE_ARMOR = vip.getProperty("VipEnchantChanceArmor", 0.77); + VIP_ENCHANT_CHANCE_WEAPON_15PLUS = vip.getProperty("VipEnchantChanceWeapon15Plus", 0.77); + VIP_ENCHANT_CHANCE_WEAPON = vip.getProperty("VipEnchantChanceWeapon", 0.77); + + + } + private static final void loadPlayers() { Index: java/net/sf/l2j/gameserver/network/clientpackets/RequestEnchantItem.java =================================================================== --- java/net/sf/l2j/gameserver/network/clientpackets/RequestEnchantItem.java (revision 5) +++ java/net/sf/l2j/gameserver/network/clientpackets/RequestEnchantItem.java (working copy) @@ -111,7 +111,7 @@ synchronized (item) { - double chance = scrollTemplate.getChance(item); + double chance = scrollTemplate.getChance(item, activeChar); // last validation check if (item.getOwnerId() != activeChar.getObjectId() || !isEnchantable(item) || chance < 0) Index: java/net/sf/l2j/gameserver/network/clientpackets/AbstractEnchantPacket.java =================================================================== --- java/net/sf/l2j/gameserver/network/clientpackets/AbstractEnchantPacket.java (revision 5) +++ java/net/sf/l2j/gameserver/network/clientpackets/AbstractEnchantPacket.java (working copy) @@ -18,6 +18,7 @@ import java.util.Map; import net.sf.l2j.Config; +import net.sf.l2j.gameserver.model.actor.instance.Player; import net.sf.l2j.gameserver.model.item.instance.ItemInstance; import net.sf.l2j.gameserver.model.item.kind.Item; import net.sf.l2j.gameserver.model.item.kind.Weapon; @@ -59,7 +60,6 @@ if (!_isWeapon || (Config.ENCHANT_MAX_WEAPON > 0 && enchantItem.getEnchantLevel() >= Config.ENCHANT_MAX_WEAPON)) return false; break; - case Item.TYPE2_SHIELD_ARMOR: case Item.TYPE2_ACCESSORY: if (_isWeapon || (Config.ENCHANT_MAX_ARMOR > 0 && enchantItem.getEnchantLevel() >= Config.ENCHANT_MAX_ARMOR)) @@ -107,9 +107,10 @@ *
  • full body armors has a chance of 1/1 for +4, 2/3 for +5, 1/3 for +6, ..., 1/17 for +20. If you've made a +20 armor, chance to make it +21 will be equal to zero (0%).
  • * * @param enchantItem : The item to enchant. + * @param player * @return the enchant chance under double format (0.7 / 0.35 / 0.44324...). */ - public final double getChance(ItemInstance enchantItem) + public final double getChance(ItemInstance enchantItem, Player player) { if (!isValid(enchantItem)) return -1; @@ -122,16 +123,20 @@ // Armor formula : 0.66^(current-2), chance is lower and lower for each enchant. if (enchantItem.isArmor()) - chance = Math.pow(Config.ENCHANT_CHANCE_ARMOR, (enchantItem.getEnchantLevel() - 2)); + if (player.isVipStatus()) + chance = Math.pow(Config.VIP_ENCHANT_CHANCE_ARMOR, (enchantItem.getEnchantLevel() - 2)); + else + chance = Math.pow(Config.ENCHANT_CHANCE_ARMOR, (enchantItem.getEnchantLevel() - 2)); // Weapon formula is 70% for fighter weapon, 40% for mage weapon. Special rates after +14. else if (enchantItem.isWeapon()) { + if (player.isVipStatus()) + chance = (enchantItem.getEnchantLevel() > 14) ? Config.VIP_ENCHANT_CHANCE_WEAPON_15PLUS : Config.VIP_ENCHANT_CHANCE_WEAPON; if (((Weapon) enchantItem.getItem()).isMagical()) chance = (enchantItem.getEnchantLevel() > 14) ? Config.ENCHANT_CHANCE_WEAPON_MAGIC_15PLUS : Config.ENCHANT_CHANCE_WEAPON_MAGIC; else chance = (enchantItem.getEnchantLevel() > 14) ? Config.ENCHANT_CHANCE_WEAPON_NONMAGIC_15PLUS : Config.ENCHANT_CHANCE_WEAPON_NONMAGIC; } - return chance; } } Index: java/net/sf/l2j/gameserver/handler/ItemHandler.java =================================================================== --- java/net/sf/l2j/gameserver/handler/ItemHandler.java (revision 5) +++ java/net/sf/l2j/gameserver/handler/ItemHandler.java (working copy) @@ -43,6 +43,7 @@ import net.sf.l2j.gameserver.handler.itemhandlers.SpecialXMas; import net.sf.l2j.gameserver.handler.itemhandlers.SpiritShot; import net.sf.l2j.gameserver.handler.itemhandlers.SummonItems; +import net.sf.l2j.gameserver.handler.itemhandlers.VipStatusItem; import net.sf.l2j.gameserver.model.item.kind.EtcItem; public class ItemHandler @@ -82,6 +83,7 @@ registerItemHandler(new SoulCrystals()); registerItemHandler(new SpiritShot()); registerItemHandler(new SummonItems()); + registerItemHandler(new VipStatusItem()); } public void registerItemHandler(IItemHandler handler) Index: java/net/sf/l2j/gameserver/model/actor/instance/Player.java =================================================================== --- java/net/sf/l2j/gameserver/model/actor/instance/Player.java (revision 5) +++ java/net/sf/l2j/gameserver/model/actor/instance/Player.java (working copy) @@ -239,6 +239,7 @@ import net.sf.l2j.gameserver.taskmanager.ItemsOnGroundTaskManager; import net.sf.l2j.gameserver.taskmanager.PvpFlagTaskManager; import net.sf.l2j.gameserver.taskmanager.ShadowItemTaskManager; +import net.sf.l2j.gameserver.taskmanager.VipTimeTaskManager; import net.sf.l2j.gameserver.taskmanager.WaterTaskManager; import net.sf.l2j.gameserver.templates.skills.L2EffectFlag; import net.sf.l2j.gameserver.templates.skills.L2EffectType; @@ -586,6 +587,7 @@ private volatile int _clientHeading; private int _mailPosition; + private boolean _isVipStatus; private static final int FALLING_VALIDATION_DELAY = 10000; private volatile long _fallingTimestamp = 0; @@ -4084,7 +4086,7 @@ for (L2Character character : getKnownList().getKnownType(L2Character.class)) if (character.getFusionSkill() != null && character.getFusionSkill().getTarget() == this) character.abortCast(); - + if (isInParty() && getParty().isInDimensionalRift()) getParty().getDimensionalRift().getDeadMemberList().add(this); @@ -4395,6 +4397,8 @@ PvpFlagTaskManager.getInstance().remove(this); GameTimeTaskManager.getInstance().remove(this); ShadowItemTaskManager.getInstance().remove(this); + if (isVipStatus()) + VipTimeTaskManager.getInstance().remove(this); } /** @@ -6890,7 +6894,7 @@ switch (sklTargetType) { - // Target the player if skill type is AURA, PARTY, CLAN or SELF + // Target the player if skill type is AURA, PARTY, CLAN or SELF case TARGET_AURA: case TARGET_FRONT_AURA: case TARGET_BEHIND_AURA: @@ -8150,7 +8154,7 @@ else for (L2Skill s : SkillTable.getNobleSkills()) super.removeSkill(s); // Just Remove skills without deleting from Sql - + _noble = val; sendSkillList(); @@ -8496,7 +8500,7 @@ for (L2Character character : getKnownList().getKnownType(L2Character.class)) if (character.getFusionSkill() != null && character.getFusionSkill().getTarget() == this) character.abortCast(); - + store(); _reuseTimeStamps.clear(); @@ -8631,6 +8635,8 @@ // Add to the GameTimeTask to keep inform about activity time. GameTimeTaskManager.getInstance().add(this); + if (isVipStatus()) + VipTimeTaskManager.getInstance().add(this); // Teleport player if the Seven Signs period isn't the good one, or if the player isn't in a cabal. if (isIn7sDungeon() && !isGM()) @@ -9113,7 +9119,7 @@ for (L2Character character : getKnownList().getKnownType(L2Character.class)) if (character.getFusionSkill() != null && character.getFusionSkill().getTarget() == this) character.abortCast(); - + // Stop signets & toggles effects. for (L2Effect effect : getAllEffects()) { @@ -9170,7 +9176,7 @@ // If the L2PcInstance is a GM, remove it from the GM List if (isGM()) GmListTable.getInstance().deleteGm(this); - + // Check if the L2PcInstance is in observer mode to set its position to its position // before entering in observer mode if (inObserverMode()) @@ -9285,13 +9291,13 @@ case 7809: // yellow for beginners case 8486: // prize-winning for beginners return 0; - + case 8485: // prize-winning luminous case 8506: // green luminous case 8509: // purple luminous case 8512: // yellow luminous return 2; - + default: return 1; } @@ -10198,6 +10204,16 @@ public final int getClientY() { return _clientY; } + public boolean isVipStatus() + { + return _isVipStatus; + } + + public void setVipStatus(boolean vip) + { + _isVipStatus = vip; + } + public final int getClientZ() { return _clientZ; } Index: java/net/sf/l2j/gameserver/handler/itemhandlers/VipStatusItem.java =================================================================== --- java/net/sf/l2j/gameserver/handler/itemhandlers/VipStatusItem.java (nonexistent) +++ java/net/sf/l2j/gameserver/handler/itemhandlers/VipStatusItem.java (working copy) @@ -0,0 +1,57 @@ +/* + * 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 . + */ +package net.sf.l2j.gameserver.handler.itemhandlers; + +import net.sf.l2j.Config; +import net.sf.l2j.gameserver.handler.IItemHandler; +import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminVipStatus; +import net.sf.l2j.gameserver.model.actor.Playable; +import net.sf.l2j.gameserver.model.actor.instance.Player; +import net.sf.l2j.gameserver.model.item.instance.ItemInstance; +import net.sf.l2j.gameserver.network.SystemMessageId; +import net.sf.l2j.gameserver.network.serverpackets.SocialAction; + +/** + * @author Baggos + */ +public class VipStatusItem implements IItemHandler +{ + @Override + public void useItem(Playable playable, ItemInstance item, boolean forceUse) + { + if (Config.ENABLE_VIP_ITEM) + { + if (!(playable instanceof Player)) + return; + + Player activeChar = (Player) playable; + if (activeChar.isVipStatus()) + activeChar.sendMessage("Your character has already VIP Status!"); + else if (activeChar.isInOlympiadMode()) + activeChar.sendPacket(SystemMessageId.YOU_ARE_NOT_AUTHORIZED_TO_DO_THAT); + else + { + AdminVipStatus.AddVipStatus(activeChar, activeChar, Config.VIP_DAYS); + activeChar.broadcastPacket(new SocialAction(activeChar, 16)); + playable.destroyItem("Consume", item.getObjectId(), 1, null, false); + } + } + } + + public int getItemIds() + { + return Config.VIP_ITEM_ID; + } +} Index: java/net/sf/l2j/gameserver/model/actor/Attackable.java =================================================================== --- java/net/sf/l2j/gameserver/model/actor/Attackable.java (revision 5) +++ java/net/sf/l2j/gameserver/model/actor/Attackable.java (working copy) @@ -340,6 +340,12 @@ sp *= Config.CHAMPION_REWARDS; } + if (attacker.isVipStatus()) + { + exp *= Config.VIP_XP_SP_RATES; + sp *= Config.VIP_XP_SP_RATES; + } + exp *= 1 - penalty; if (isOverhit() && _overhitAttacker != null && _overhitAttacker.getActingPlayer() != null && attacker == _overhitAttacker.getActingPlayer()) @@ -419,6 +425,12 @@ sp *= Config.CHAMPION_REWARDS; } + if (attacker.isVipStatus()) + { + exp *= Config.VIP_XP_SP_RATES; + sp *= Config.VIP_XP_SP_RATES; + } + exp *= partyMul; sp *= partyMul; @@ -793,11 +805,23 @@ // Applies Drop rates if (drop.getItemId() == 57) - dropChance *= Config.RATE_DROP_ADENA; + if (lastAttacker.isVipStatus()) + dropChance *= Config.VIP_ADENA_RATES; + else + dropChance *= Config.RATE_DROP_ADENA; else if (isSweep) - dropChance *= Config.RATE_DROP_SPOIL; + if (lastAttacker.isVipStatus()) + dropChance *= Config.VIP_SPOIL_RATES; + else + dropChance *= Config.RATE_DROP_SPOIL; else - dropChance *= isRaid() && !isRaidMinion() ? Config.RATE_DROP_ITEMS_BY_RAID : Config.RATE_DROP_ITEMS; + { + if (lastAttacker.isVipStatus()) + dropChance *= isRaid() && !isRaidMinion() ? Config.VIP_RATE_DROP_ITEMS_BY_RAID : Config.VIP_DROP_RATES; + else + dropChance *= isRaid() && !isRaidMinion() ? Config.RATE_DROP_ITEMS_BY_RAID : Config.RATE_DROP_ITEMS; + + } if (isChampion()) dropChance *= Config.CHAMPION_REWARDS; @@ -832,7 +856,7 @@ if (isChampion()) if (drop.getItemId() == 57 || (drop.getItemId() >= 6360 && drop.getItemId() <= 6362)) itemCount *= Config.CHAMPION_ADENAS_REWARDS; - + if (itemCount > 0) return new IntIntHolder(drop.getItemId(), itemCount); @@ -851,7 +875,7 @@ { if (categoryDrops == null) return null; - + // Get default drop chance for the category (that's the sum of chances for all items in the category) // keep track of the base category chance as it'll be used later, if an item is drop from the category. // for everything else, use the total "categoryDropChance" @@ -882,7 +906,7 @@ DropData drop = categoryDrops.dropOne(isRaid() && !isRaidMinion()); if (drop == null) return null; - + // Now decide the quantity to drop based on the rates and penalties. To get this value // simply divide the modified categoryDropChance by the base category chance. This // results in a chance that will dictate the drops amounts: for each amount over 100 @@ -897,7 +921,12 @@ double dropChance = drop.getChance(); if (drop.getItemId() == 57) - dropChance *= Config.RATE_DROP_ADENA; + if (lastAttacker.isVipStatus()) + dropChance *= Config.VIP_ADENA_RATES; + else + dropChance *= Config.RATE_DROP_ADENA; + else if (lastAttacker.isVipStatus()) + dropChance *= isRaid() && !isRaidMinion() ? Config.VIP_RATE_DROP_ITEMS_BY_RAID : Config.VIP_DROP_RATES; else dropChance *= isRaid() && !isRaidMinion() ? Config.RATE_DROP_ITEMS_BY_RAID : Config.RATE_DROP_ITEMS; @@ -933,7 +962,7 @@ if (isChampion()) if (drop.getItemId() == 57 || (drop.getItemId() >= 6360 && drop.getItemId() <= 6362)) itemCount *= Config.CHAMPION_ADENAS_REWARDS; - + if (itemCount > 0) return new IntIntHolder(drop.getItemId(), itemCount); } @@ -954,7 +983,7 @@ for (L2Character atkChar : _attackByList) if (atkChar.getLevel() > highestLevel) highestLevel = atkChar.getLevel(); - + // According to official data (Prima), deep blue mobs are 9 or more levels below players if (highestLevel - 9 >= getLevel()) return ((highestLevel - (getLevel() + 8)) * 9); @@ -1515,7 +1544,7 @@ // Over-hit damage percentages are limited to 25% max if (overhitPercentage > 25) overhitPercentage = 25; - + // Get the overhit exp bonus according to the above over-hit damage percentage // (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...) double overhitExp = ((overhitPercentage / 100) * normalExp); Index: java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java =================================================================== --- java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java (revision 5) +++ java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java (working copy) @@ -31,6 +31,7 @@ import net.sf.l2j.gameserver.model.L2Clan.SubPledge; import net.sf.l2j.gameserver.model.World; import net.sf.l2j.gameserver.model.actor.instance.Player; +import net.sf.l2j.gameserver.model.actor.instance.L2VipInstance; import net.sf.l2j.gameserver.model.base.Race; import net.sf.l2j.gameserver.model.entity.ClanHall; import net.sf.l2j.gameserver.model.entity.Couple; @@ -203,6 +204,10 @@ activeChar.sendPacket(ExMailArrived.STATIC_PACKET); } + // Vip Status onEnter + if (activeChar.getMemos().getLong("TimeOfVip", 0) > 0) + L2VipInstance.onEnterVipStatus(activeChar); + // Clan notice, if active. if (Config.ENABLE_COMMUNITY_BOARD && clan != null && clan.isNoticeEnabled()) { Index: java/net/sf/l2j/gameserver/model/actor/instance/L2VipInstance.java =================================================================== --- java/net/sf/l2j/gameserver/model/actor/instance/L2VipInstance.java (nonexistent) +++ java/net/sf/l2j/gameserver/model/actor/instance/L2VipInstance.java (working copy) @@ -0,0 +1,329 @@ +/* + * 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 . + */ +package net.sf.l2j.gameserver.model.actor.instance; + +import java.util.Calendar; +import java.util.StringTokenizer; + +import net.sf.l2j.commons.concurrent.ThreadPool; +import net.sf.l2j.gameserver.ai.CtrlIntention; +import net.sf.l2j.gameserver.datatables.SkillTable; +import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminVipStatus; +import net.sf.l2j.gameserver.instancemanager.CastleManager; +import net.sf.l2j.gameserver.model.World; +import net.sf.l2j.gameserver.model.actor.instance.Folk; +import net.sf.l2j.gameserver.model.base.Sex; +import net.sf.l2j.gameserver.model.actor.template.NpcTemplate; +import net.sf.l2j.gameserver.model.entity.Castle; +import net.sf.l2j.gameserver.network.SystemMessageId; +import net.sf.l2j.gameserver.network.serverpackets.ExShowScreenMessage; +import net.sf.l2j.gameserver.network.serverpackets.SiegeInfo; +import net.sf.l2j.gameserver.network.serverpackets.SocialAction; + +/** + * @author Baggos + */ +public class L2VipInstance extends Folk +{ + public L2VipInstance(int objectId, NpcTemplate template) + { + super(objectId, template); + } + + /** Type the count for clean pk */ + private final static int PK_CLEAN_COUNT = 50; + + @Override + public void onBypassFeedback(Player player, String command) + { + if (command.startsWith("vip")) + { + if (!player.isVipStatus()) + { + player.sendMessage("Sorry! Only VIP player can do this action."); + return; + } + StringTokenizer st = new StringTokenizer(command); + st.nextToken(); + try + { + String type = st.nextToken(); + switch (type) + { + case "Noblesse": + Nobless(player); + break; + case "ChangeSex": + Sex(player); + break; + case "CleanPk": + CleanPk(player); + break; + case "FullRec": + Rec(player); + break; + } + } + catch (Exception e) + { + } + } + + else if (command.startsWith("tp")) + { + if (!player.isVipStatus()) + { + player.sendMessage("Sorry! Only VIP player can do this action."); + return; + } + StringTokenizer st = new StringTokenizer(command); + st.nextToken(); + + String val = ""; + try + { + if (st.hasMoreTokens()) + { + val = st.nextToken(); + } + Player activeChar = World.getInstance().getPlayer(val); + teleportTo(val, player, activeChar); + } + catch (Exception e) + { + // Case if the player is not in the same party. + player.sendMessage("Incorrect target"); + } + } + + else if (command.startsWith("clantp")) + { + if (!player.isVipStatus()) + { + player.sendMessage("Sorry! Only VIP player can do this action."); + return; + } + StringTokenizer st = new StringTokenizer(command); + st.nextToken(); + + String clan = ""; + try + { + if (st.hasMoreTokens()) + { + clan = st.nextToken(); + } + Player activeChar = World.getInstance().getPlayer(clan); + teleportToClan(clan, player, activeChar); + } + catch (Exception e) + { + // Case if the player is not in the same clan. + player.sendMessage("Incorrect target"); + } + } + + else if (command.startsWith("siege")) + { + if (!player.isVipStatus()) + { + player.sendMessage("Sorry! Only VIP player can do this action."); + return; + } + StringTokenizer st = new StringTokenizer(command); + st.nextToken(); + try + { + String type = st.nextToken(); + int castleId = 0; + + if (type.startsWith("Gludio")) + castleId = 1; + else if (type.startsWith("Dion")) + castleId = 2; + else if (type.startsWith("Giran")) + castleId = 3; + else if (type.startsWith("Oren")) + castleId = 4; + else if (type.startsWith("Aden")) + castleId = 5; + else if (type.startsWith("Innadril")) + castleId = 6; + else if (type.startsWith("Goddard")) + castleId = 7; + else if (type.startsWith("Rune")) + castleId = 8; + else if (type.startsWith("Schuttgart")) + castleId = 9; + + Castle castle = CastleManager.getInstance().getCastleById(castleId); + + if (castle != null && castleId != 0) + player.sendPacket(new SiegeInfo(castle)); + } + catch (Exception e) + { + } + } + } + + public static void Nobless(Player player) + { + if (player.isNoble()) + { + player.sendMessage("You Are Already A Noblesse!."); + return; + } + player.broadcastPacket(new SocialAction(player, 16)); + player.setNoble(true, true); + player.sendMessage("You Are Now a Noble,You Are Granted With Noblesse Status , And Noblesse Skills."); + player.broadcastUserInfo(); + } + + public static void Sex(Player player) + { + player.getAppearance().setSex(player.getAppearance().getSex() == Sex.MALE ? Sex.FEMALE : Sex.MALE); + player.sendMessage("Your gender has been changed,You will be disconected in 3 Seconds!"); + player.broadcastUserInfo(); + player.decayMe(); + player.spawnMe(); + ThreadPool.schedule(() -> player.logout(false), 3000); + } + + public static void CleanPk(Player player) + { + if (player.getPkKills() < 50) + { + player.sendMessage("You do not have enough Pk kills for clean."); + return; + } + player.setPkKills(player.getPkKills() - PK_CLEAN_COUNT); + player.sendMessage("You have successfully clean " + PK_CLEAN_COUNT + " pks!"); + player.broadcastUserInfo(); + } + + public static void Rec(Player player) + { + if (player.getRecomHave() == 255) + { + player.sendMessage("You already have full recommends."); + return; + } + player.setRecomHave(255); + player.sendMessage("Added 255 recommends."); + player.getLastRecomUpdate(); + player.broadcastUserInfo(); + } + + public static void teleportTo(String val, Player activeChar, Player target) + { + if (target.getObjectId() == activeChar.getObjectId()) + activeChar.sendPacket(SystemMessageId.CANNOT_USE_ON_YOURSELF); + + // Check if the player is not in the same party + else if (!activeChar.getParty().getMembers().contains(target)) + return; + + // Simple checks to avoid exploits + else if (target.isInJail() || target.isInOlympiadMode() || target.isInDuel() || target.isFestivalParticipant() || (target.isInParty() && target.getParty().isInDimensionalRift()) || target.isInObserverMode()) + { + activeChar.sendMessage("Due to the current friend's status, the teleportation failed."); + return; + } + + else if (target.getClan() != null && CastleManager.getInstance().getCastleByOwner(target.getClan()) != null && CastleManager.getInstance().getCastleByOwner(target.getClan()).getSiege().isInProgress()) + { + activeChar.sendMessage("As your friend is in siege, you can't go to him/her."); + return; + } + else if (activeChar.getPvpFlag() > 0 || activeChar.getKarma() > 0) + { + activeChar.sendMessage("Go away! Flag or Pk player can not be teleported."); + return; + } + int x = target.getX(); + int y = target.getY(); + int z = target.getZ(); + + activeChar.getAI().setIntention(CtrlIntention.IDLE); + activeChar.doCast(SkillTable.getInstance().getInfo(2100, 1)); + activeChar.sendPacket(new ExShowScreenMessage("You will be teleported to " + target.getName() + " in 3 Seconds!", 3000, 2, true)); + ThreadPool.schedule(() -> activeChar.teleToLocation(x, y, z, 0), 3000); + activeChar.sendMessage("You have teleported to " + target.getName() + "."); + } + + public static void teleportToClan(String clan, Player activeChar, Player target) + { + if (target.getObjectId() == activeChar.getObjectId()) + activeChar.sendPacket(SystemMessageId.CANNOT_USE_ON_YOURSELF); + + // Check if the player is not in the same clan. + else if (!activeChar.getClan().isMember(target.getObjectId())) + return; + + // Simple checks to avoid exploits + else if (target.isInJail() || target.isInOlympiadMode() || target.isInDuel() || target.isFestivalParticipant() || (target.isInParty() && target.getParty().isInDimensionalRift()) || target.isInObserverMode()) + { + activeChar.sendMessage("Due to the current clan member's status, the teleportation failed."); + return; + } + + else if (target.getClan() != null && CastleManager.getInstance().getCastleByOwner(target.getClan()) != null && CastleManager.getInstance().getCastleByOwner(target.getClan()).getSiege().isInProgress()) + { + activeChar.sendMessage("As your clan member is in siege, you can't go to him/her."); + return; + } + else if (activeChar.getPvpFlag() > 0 || activeChar.getKarma() > 0) + { + activeChar.sendMessage("Go away! Flag or Pk player can not be teleported."); + return; + } + int x = target.getX(); + int y = target.getY(); + int z = target.getZ(); + + activeChar.getAI().setIntention(CtrlIntention.IDLE); + activeChar.doCast(SkillTable.getInstance().getInfo(2100, 1)); + activeChar.sendPacket(new ExShowScreenMessage("You will be teleported to " + target.getName() + " in 3 Seconds!", 3000, 2, true)); + ThreadPool.schedule(() -> activeChar.teleToLocation(x, y, z, 0), 3000); + activeChar.sendMessage("You have teleported to " + target.getName() + "."); + } + + // Contains to EnterWorld.java for VIP onEnter. + public static void onEnterVipStatus(Player activeChar) + { + long now = Calendar.getInstance().getTimeInMillis(); + long endDay = activeChar.getMemos().getLong("TimeOfVip"); + + if (now > endDay) + AdminVipStatus.RemoveVipStatus(activeChar); + else + { + activeChar.setVipStatus(true); + activeChar.broadcastUserInfo(); + } + } + + @Override + public String getHtmlPath(int npcId, int val) + { + String filename = ""; + + if (val == 0) + filename = "" + npcId; + else + filename = npcId + "-" + val; + + return "data/html/mods/vipNpc/" + filename + ".htm"; + } +} \ No newline at end of file #P aCis_datapack Index: data/xml/npcs/50000-50999.xml =================================================================== --- data/xml/npcs/50000-50999.xml (revision 5) +++ data/xml/npcs/50000-50999.xml (working copy) @@ -108,4 +108,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file Index: data/xml/admin_commands_rights.xml =================================================================== --- data/xml/admin_commands_rights.xml (revision 5) +++ data/xml/admin_commands_rights.xml (working copy) @@ -12,6 +12,10 @@ + + + + Index: data/html/mods/vipNpc/50009.htm =================================================================== Index: data/xml/items/3400-3499.xml =================================================================== --- data/xml/items/3400-3499.xml (revision 5) +++ data/xml/items/3400-3499.xml (working copy) @@ -595,6 +595,7 @@ + Index: data/html/mods/vipNpc/50009.htm =================================================================== --- data/html/mods/vipNpc/50009.htm (nonexistent) +++ data/html/mods/vipNpc/50009.htm (working copy) @@ -0,0 +1,83 @@ + + +Donate Manager + + +
    + + + + + + + +
    + +
    +
    +
    Vip Settings: +
    +
    +
    + + + + + + + +
    + +
    +
    +
    Siege Services: +
    +
    +
    + +
    +
    +Dear VIP player! +From here you can go to your party member +or you can also go to your clan member. +Try it! It is easy only with one click. +Conditions: + Olympiad, Duel, Events +Jail, Observer Mode, Siege +Flag for yourself, Karma for yourself. +
    + + + + + + + + +
    + + +
    Teleport to your party member: +
    +
    + + + + + + + + +
    + + +
    Teleport to your clan member: +
    +
    + \ No newline at end of file Index: data/xml/skills/2100-2199.xml =================================================================== --- data/xml/skills/2100-2199.xml (revision 5) +++ data/xml/skills/2100-2199.xml (working copy) @@ -1,8 +1,8 @@ - + - +