diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/db_installer/sql/game/character_revenge_history.sql b/L2J_Mobius_Essence_5.2_FrostLord/dist/db_installer/sql/game/character_revenge_history.sql new file mode 100644 index 0000000000..5be9d849cf --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/db_installer/sql/game/character_revenge_history.sql @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS `character_revenge_history`; +CREATE TABLE IF NOT EXISTS `character_revenge_history` ( + `charId` int(10) UNSIGNED NOT NULL, + `type` int(10) NOT NULL, + `killer_name` VARCHAR(35), + `killer_clan` VARCHAR(45), + `killer_level` int UNSIGNED NOT NULL, + `killer_race` int NOT NULL DEFAULT 0, + `killer_class` int NOT NULL DEFAULT 0, + `victim_name` VARCHAR(35), + `victim_clan` VARCHAR(45), + `victim_level` int UNSIGNED NOT NULL, + `victim_race` int NOT NULL DEFAULT 0, + `victim_class` int NOT NULL DEFAULT 0, + `shared` TINYINT(1) NOT NULL DEFAULT 0, + `show_location_remaining` int NOT NULL DEFAULT 0, + `teleport_remaining` int NOT NULL DEFAULT 0, + `shared_teleport_remaining` int NOT NULL DEFAULT 0, + `kill_time` BIGINT(10) UNSIGNED NOT NULL, + `share_time` BIGINT(10) UNSIGNED NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/handlers/effecthandlers/Teleport.java b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/handlers/effecthandlers/Teleport.java index 673f0d4609..6f77938d03 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/handlers/effecthandlers/Teleport.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/handlers/effecthandlers/Teleport.java @@ -52,6 +52,9 @@ public class Teleport extends AbstractEffect @Override public void instant(Creature effector, Creature effected, Skill skill, Item item) { - effected.teleToLocation(_loc, true, null); + if ((_loc.getX() != 0) && (_loc.getY() != 0) && (_loc.getZ() != 0)) + { + effected.teleToLocation(_loc, true, null); + } } } diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/stats/skills/60000-60099.xml b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/stats/skills/60000-60099.xml index a70115c588..0f5d872bac 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/stats/skills/60000-60099.xml +++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/stats/skills/60000-60099.xml @@ -6,34 +6,35 @@ P 5000 - + icon.karma - 10 - P - 5 + A2 + SELF + SINGLE + 4 + 1 + -1 + true + true + false + true - -5 - -10 - -15 + -30 PER - -5 - -10 - -15 + -30 PER - -5 - -10 - -30 + -40 DIFF @@ -320,6 +321,9 @@ icon.skill0000 A1 2000 + + + diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/GameServer.java index 7d7fd2d72b..8ef7b8b7aa 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/GameServer.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/GameServer.java @@ -156,6 +156,7 @@ import org.l2jmobius.gameserver.instancemanager.PurgeRankingManager; import org.l2jmobius.gameserver.instancemanager.QuestManager; import org.l2jmobius.gameserver.instancemanager.RankManager; import org.l2jmobius.gameserver.instancemanager.RankingPowerManager; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; import org.l2jmobius.gameserver.instancemanager.SellBuffsManager; import org.l2jmobius.gameserver.instancemanager.ServerRestartManager; import org.l2jmobius.gameserver.instancemanager.SharedTeleportManager; @@ -314,6 +315,7 @@ public class GameServer AttendanceRewardData.getInstance(); MagicLampData.getInstance(); RandomCraftData.getInstance(); + RevengeHistoryManager.getInstance(); VipData.getInstance(); printSection("Characters"); diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/Shutdown.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/Shutdown.java index 8da5b7bc14..cc4be61e6a 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/Shutdown.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/Shutdown.java @@ -36,6 +36,7 @@ import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager; import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager; import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager; import org.l2jmobius.gameserver.instancemanager.QuestManager; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.olympiad.Hero; @@ -145,6 +146,16 @@ public class Shutdown extends Thread // ignore } + try + { + RevengeHistoryManager.getInstance().storeMe(); + LOGGER.info("Saved Revenge History(" + tc.getEstimatedTimeAndRestartCounter() + "ms)."); + } + catch (Throwable t) + { + // ignore + } + // ensure all services are stopped try diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/RevengeType.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/RevengeType.java new file mode 100644 index 0000000000..962e4f5fe6 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/RevengeType.java @@ -0,0 +1,27 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.enums; + +/** + * @author Mobius + */ +public enum RevengeType +{ + OWN_HELP_REQUEST, + REVENGE, + HELP_REQUEST; +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java index 547de579c3..8adc39fb95 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java @@ -147,6 +147,8 @@ public class DailyTaskManager { GlobalVariablesManager.getInstance().storeMe(); + RevengeHistoryManager.getInstance().storeMe(); + if (Olympiad.getInstance().inCompPeriod()) { Olympiad.getInstance().saveOlympiadStatus(); diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/IdManager.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/IdManager.java index 93bfd8b78c..96a825d4bc 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/IdManager.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/IdManager.java @@ -129,6 +129,7 @@ public class IdManager cleanCount += statement.executeUpdate("DELETE FROM character_offline_trade_items WHERE character_offline_trade_items.charId NOT IN (SELECT charId FROM characters);"); cleanCount += statement.executeUpdate("DELETE FROM character_tpbookmark WHERE character_tpbookmark.charId NOT IN (SELECT charId FROM characters);"); cleanCount += statement.executeUpdate("DELETE FROM character_variables WHERE character_variables.charId NOT IN (SELECT charId FROM characters);"); + cleanCount += statement.executeUpdate("DELETE FROM character_revenge_history WHERE character_revenge_history.charId NOT IN (SELECT charId FROM characters);"); cleanCount += statement.executeUpdate("DELETE FROM bot_reported_char_data WHERE bot_reported_char_data.botId NOT IN (SELECT charId FROM characters);"); // Clan diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/RankManager.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/RankManager.java index bfe1bccd8e..37b2440c44 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/RankManager.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/RankManager.java @@ -19,6 +19,9 @@ package org.l2jmobius.gameserver.instancemanager; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; @@ -31,6 +34,7 @@ import org.l2jmobius.gameserver.data.sql.ClanTable; import org.l2jmobius.gameserver.data.xml.PetDataTable; import org.l2jmobius.gameserver.model.PetData; import org.l2jmobius.gameserver.model.StatSet; +import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.olympiad.Hero; @@ -435,6 +439,28 @@ public class RankManager return 0; } + public Collection getTop50() + { + final List result = new LinkedList<>(); + for (int i = 1; i <= 50; i++) + { + final StatSet rank = _mainList.get(i); + if (rank == null) + { + break; + } + + final Player player = World.getInstance().getPlayer(rank.getInt("charId")); + if ((player == null) || (player.isOnlineInt() != 1)) + { + continue; + } + + result.add(player); + } + return result; + } + public static RankManager getInstance() { return SingletonHolder.INSTANCE; diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/RevengeHistoryManager.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/RevengeHistoryManager.java new file mode 100644 index 0000000000..13415a79a4 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/RevengeHistoryManager.java @@ -0,0 +1,480 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.instancemanager; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.logging.Logger; + +import org.l2jmobius.commons.database.DatabaseFactory; +import org.l2jmobius.gameserver.enums.RevengeType; +import org.l2jmobius.gameserver.model.StatSet; +import org.l2jmobius.gameserver.model.World; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.model.actor.Summon; +import org.l2jmobius.gameserver.model.holders.RevengeHistoryHolder; +import org.l2jmobius.gameserver.model.holders.SkillHolder; +import org.l2jmobius.gameserver.model.itemcontainer.Inventory; +import org.l2jmobius.gameserver.model.zone.ZoneId; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.serverpackets.revenge.ExPvpBookShareRevengeKillerLocation; +import org.l2jmobius.gameserver.network.serverpackets.revenge.ExPvpBookShareRevengeList; +import org.l2jmobius.gameserver.network.serverpackets.revenge.ExPvpBookShareRevengeNewRevengeInfo; + +/** + * @author Mobius + */ +public class RevengeHistoryManager +{ + private static final Logger LOGGER = Logger.getLogger(RevengeHistoryManager.class.getName()); + + private static final Map> REVENGE_HISTORY = new ConcurrentHashMap<>(); + private static final String DELETE_REVENGE_HISTORY = "TRUNCATE TABLE character_revenge_history"; + private static final String INSERT_REVENGE_HISTORY = "INSERT INTO character_revenge_history (charId, type, killer_name, killer_clan, killer_level, killer_race, killer_class, victim_name, victim_clan, victim_level, victim_race, victim_class, shared, show_location_remaining, teleport_remaining, shared_teleport_remaining, kill_time, share_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + private static final SkillHolder HIDE_SKILL = new SkillHolder(922, 1); + private static final long REVENGE_DURATION = 21600000; // Six hours. + private static final int[] LOCATION_PRICE = + { + 0, + 50000, + 100000, + 100000, + 200000 + }; + private static final int[] TELEPORT_PRICE = + { + 10, + 50, + 100, + 100, + 200 + }; + + protected RevengeHistoryManager() + { + try (Connection con = DatabaseFactory.getConnection(); + PreparedStatement ps = con.prepareStatement("SELECT * FROM character_revenge_history")) + { + ResultSet rs = ps.executeQuery(); + while (rs.next()) + { + final int charId = rs.getInt("charId"); + final List history = REVENGE_HISTORY.containsKey(charId) ? REVENGE_HISTORY.get(charId) : new CopyOnWriteArrayList<>(); + final StatSet killer = new StatSet(); + killer.set("name", rs.getString("killer_name")); + killer.set("clan", rs.getString("killer_clan")); + killer.set("level", rs.getInt("killer_level")); + killer.set("race", rs.getInt("killer_race")); + killer.set("class", rs.getInt("killer_class")); + final StatSet victim = new StatSet(); + victim.set("name", rs.getString("victim_name")); + victim.set("clan", rs.getString("victim_clan")); + victim.set("level", rs.getInt("victim_level")); + victim.set("race", rs.getInt("victim_race")); + victim.set("class", rs.getInt("victim_class")); + history.add(new RevengeHistoryHolder(killer, victim, RevengeType.values()[rs.getInt("type")], rs.getBoolean("shared"), rs.getInt("show_location_remaining"), rs.getInt("teleport_remaining"), rs.getInt("shared_teleport_remaining"), rs.getLong("kill_time"), rs.getLong("share_time"))); + REVENGE_HISTORY.put(charId, history); + } + } + catch (Exception e) + { + LOGGER.warning("Failed loading revenge history! " + e); + } + } + + public void storeMe() + { + for (Entry> entry : REVENGE_HISTORY.entrySet()) + { + final List history = entry.getValue(); + if (history != null) + { + final long currentTime = System.currentTimeMillis(); + final List removals = new ArrayList<>(); + for (RevengeHistoryHolder holder : history) + { + if (((holder.getKillTime() != 0) && ((holder.getKillTime() + REVENGE_DURATION) < currentTime)) || // + ((holder.getShareTime() != 0) && ((holder.getShareTime() + REVENGE_DURATION) < currentTime))) + { + removals.add(holder); + } + } + for (RevengeHistoryHolder holder : removals) + { + history.remove(holder); + } + } + } + + try (Connection con = DatabaseFactory.getConnection(); + PreparedStatement ps1 = con.prepareStatement(DELETE_REVENGE_HISTORY); + PreparedStatement ps2 = con.prepareStatement(INSERT_REVENGE_HISTORY)) + { + ps1.execute(); + + for (Entry> entry : REVENGE_HISTORY.entrySet()) + { + final List history = entry.getValue(); + if ((history == null) || history.isEmpty()) + { + continue; + } + + for (RevengeHistoryHolder holder : history) + { + ps2.clearParameters(); + ps2.setInt(1, entry.getKey()); + ps2.setInt(2, holder.getType().ordinal()); + ps2.setString(3, holder.getKillerName()); + ps2.setString(4, holder.getKillerClanName()); + ps2.setInt(5, holder.getKillerLevel()); + ps2.setInt(6, holder.getKillerRaceId()); + ps2.setInt(7, holder.getKillerClassId()); + ps2.setString(8, holder.getVictimName()); + ps2.setString(9, holder.getVictimClanName()); + ps2.setInt(10, holder.getVictimLevel()); + ps2.setInt(11, holder.getVictimRaceId()); + ps2.setInt(12, holder.getVictimClassId()); + ps2.setBoolean(13, holder.wasShared()); + ps2.setInt(14, holder.getShowLocationRemaining()); + ps2.setInt(15, holder.getTeleportRemaining()); + ps2.setInt(16, holder.getSharedTeleportRemaining()); + ps2.setLong(17, holder.getKillTime()); + ps2.setLong(18, holder.getShareTime()); + ps2.addBatch(); + } + } + ps2.executeBatch(); + } + catch (Exception e) + { + LOGGER.warning(getClass().getSimpleName() + " Error while saving revenge history. " + e); + } + } + + public void addNewKill(Player victim, Player killer) + { + try + { + boolean found = false; + final int victimObjectId = victim.getObjectId(); + final long currentTime = System.currentTimeMillis(); + final List removals = new ArrayList<>(); + final List history = REVENGE_HISTORY.containsKey(victimObjectId) ? REVENGE_HISTORY.get(victimObjectId) : new CopyOnWriteArrayList<>(); + for (RevengeHistoryHolder holder : history) + { + if (((holder.getKillTime() != 0) && ((holder.getKillTime() + REVENGE_DURATION) < currentTime)) || // + ((holder.getShareTime() != 0) && ((holder.getShareTime() + REVENGE_DURATION) < currentTime))) + { + removals.add(holder); + } + else if (holder.getKillerName().equals(killer.getName())) + { + found = true; + } + } + + history.removeAll(removals); + + if (!found) + { + history.add(new RevengeHistoryHolder(killer, victim, RevengeType.REVENGE)); + REVENGE_HISTORY.put(victimObjectId, history); + victim.sendPacket(new ExPvpBookShareRevengeNewRevengeInfo(victim.getName(), killer.getName(), RevengeType.REVENGE)); + victim.sendPacket(new ExPvpBookShareRevengeList(victim)); + } + } + catch (Exception e) + { + LOGGER.warning(getClass().getSimpleName() + ": Failed adding revenge history! " + e); + } + } + + public void locateKiller(Player player, String killerName) + { + final List history = REVENGE_HISTORY.get(player.getObjectId()); + if (history == null) + { + return; + } + + RevengeHistoryHolder revenge = null; + for (RevengeHistoryHolder holder : history) + { + if (holder.getKillerName().equals(killerName)) + { + revenge = holder; + break; + } + } + + if (revenge == null) + { + return; + } + + final Player killer = World.getInstance().getPlayer(killerName); + if ((killer == null) || !killer.isOnline()) + { + player.sendPacket(SystemMessageId.THE_ENEMY_IS_OFFLINE_AND_CANNOT_BE_FOUND_RIGHT_NOW); + return; + } + + if (killer.isInsideZone(ZoneId.PEACE) || killer.isInInstance() || killer.isInTimedHuntingZone() || killer.isInsideZone(ZoneId.SIEGE) // + || player.isDead() || player.isInInstance() || player.isInTimedHuntingZone() || player.isInsideZone(ZoneId.SIEGE)) + { + player.sendPacket(SystemMessageId.THE_CHARACTER_IS_IN_A_LOCATION_WHERE_IT_IS_IMPOSSIBLE_TO_USE_THIS_FUNCTION); + return; + } + + if (revenge.getShowLocationRemaining() > 0) + { + final int price = LOCATION_PRICE[Math.min(LOCATION_PRICE.length - revenge.getShowLocationRemaining(), LOCATION_PRICE.length - 1)]; + if (player.reduceAdena("Revenge find location", price, player, true)) + { + revenge.setShowLocationRemaining(revenge.getShowLocationRemaining() - 1); + player.sendPacket(new ExPvpBookShareRevengeKillerLocation(killer)); + player.sendPacket(new ExPvpBookShareRevengeList(player)); + } + } + } + + private boolean checkTeleportConditions(Player player, Player killer) + { + if ((killer == null) || !killer.isOnline()) + { + player.sendPacket(SystemMessageId.THE_ENEMY_IS_OFFLINE_AND_CANNOT_BE_FOUND_RIGHT_NOW); + return false; + } + if (killer.isTeleporting() || killer.isInsideZone(ZoneId.PEACE) || killer.isInInstance() || killer.isInTimedHuntingZone() || killer.isInsideZone(ZoneId.SIEGE) || killer.isInsideZone(ZoneId.NO_BOOKMARK)) + { + player.sendPacket(SystemMessageId.THE_CHARACTER_IS_IN_A_LOCATION_WHERE_IT_IS_IMPOSSIBLE_TO_USE_THIS_FUNCTION); + return false; + } + if (killer.isDead()) + { + player.sendPacket(SystemMessageId.THE_CHARACTER_IS_IN_A_LOCATION_WHERE_IT_IS_IMPOSSIBLE_TO_USE_THIS_FUNCTION); + return false; + } + + if (player.isInInstance() || player.isInTimedHuntingZone() || player.isInsideZone(ZoneId.SIEGE)) + { + player.sendPacket(SystemMessageId.THE_CHARACTER_IS_IN_A_LOCATION_WHERE_IT_IS_IMPOSSIBLE_TO_USE_THIS_FUNCTION); + return false; + } + if (player.isDead()) + { + player.sendPacket(SystemMessageId.YOU_CANNOT_USE_TELEPORT_WHILE_YOU_ARE_DEAD); + return false; + } + if (player.isInCombat() || player.isDisabled()) + { + player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_IN_COMBAT); + return false; + } + + return true; + } + + public void teleportToKiller(Player player, String killerName) + { + final List history = REVENGE_HISTORY.get(player.getObjectId()); + if (history == null) + { + return; + } + + RevengeHistoryHolder revenge = null; + for (RevengeHistoryHolder holder : history) + { + if (holder.getKillerName().equals(killerName)) + { + revenge = holder; + break; + } + } + + if (revenge == null) + { + return; + } + + if (revenge.wasShared()) + { + return; + } + + final Player killer = World.getInstance().getPlayer(killerName); + if (!checkTeleportConditions(player, killer)) + { + return; + } + + if (revenge.getTeleportRemaining() > 0) + { + final int price = TELEPORT_PRICE[Math.min(TELEPORT_PRICE.length - revenge.getTeleportRemaining(), TELEPORT_PRICE.length - 1)]; + if (player.destroyItemByItemId("Revenge Teleport", Inventory.LCOIN_ID, price, player, true)) + { + revenge.setTeleportRemaining(revenge.getTeleportRemaining() - 1); + HIDE_SKILL.getSkill().applyEffects(player, player); + for (Summon summon : player.getServitorsAndPets()) + { + HIDE_SKILL.getSkill().applyEffects(summon, summon); + } + player.teleToLocation(killer.getLocation()); + } + } + } + + public void teleportToSharedKiller(Player player, String victimName, String killerName) + { + if (player.getName().equals(killerName)) + { + return; + } + + final List history = REVENGE_HISTORY.get(player.getObjectId()); + if (history == null) + { + return; + } + + RevengeHistoryHolder revenge = null; + for (RevengeHistoryHolder holder : history) + { + if (holder.getVictimName().equals(victimName) && holder.getKillerName().equals(killerName)) + { + revenge = holder; + break; + } + } + + if (revenge == null) + { + return; + } + + if (!revenge.wasShared()) + { + return; + } + + final Player killer = World.getInstance().getPlayer(killerName); + if (!checkTeleportConditions(player, killer)) + { + return; + } + + if ((revenge.getSharedTeleportRemaining() > 0) && player.destroyItemByItemId("Revenge Teleport", Inventory.LCOIN_ID, 100, player, true)) + { + revenge.setSharedTeleportRemaining(revenge.getSharedTeleportRemaining() - 1); + HIDE_SKILL.getSkill().applyEffects(player, player); + for (Summon summon : player.getServitorsAndPets()) + { + HIDE_SKILL.getSkill().applyEffects(summon, summon); + } + player.teleToLocation(killer.getLocation()); + } + } + + public void requestHelp(Player player, Player killer, int type) + { + final List history = REVENGE_HISTORY.get(player.getObjectId()); + if (history == null) + { + return; + } + + RevengeHistoryHolder revenge = null; + for (RevengeHistoryHolder holder : history) + { + if (holder.getKillerName().equals(killer.getName())) + { + revenge = holder; + break; + } + } + + if (revenge == null) + { + return; + } + + if (revenge.wasShared()) + { + return; + } + + if (player.reduceAdena("Revenge request help", 100000, player, true)) + { + final long currentTime = System.currentTimeMillis(); + revenge.setShared(true); + revenge.setType(RevengeType.OWN_HELP_REQUEST); + revenge.setShareTime(currentTime); + + final Collection targets = type == 1 ? (player.getClan() == null ? Collections.emptyList() : player.getClan().getOnlineMembers(player.getObjectId())) : type == 2 ? RankManager.getInstance().getTop50() : Collections.emptyList(); + for (Player target : targets) + { + if (target == killer) + { + continue; + } + + final int targetObjectId = target.getObjectId(); + final List targetHistory = REVENGE_HISTORY.containsKey(targetObjectId) ? REVENGE_HISTORY.get(targetObjectId) : new CopyOnWriteArrayList<>(); + for (RevengeHistoryHolder temp : targetHistory) + { + if (temp.getVictimName().equals(player.getName()) && temp.getKillerName().equals(killer.getName()) && (temp != revenge)) + { + targetHistory.remove(temp); + break; + } + } + targetHistory.add(new RevengeHistoryHolder(killer, player, RevengeType.HELP_REQUEST, 1, revenge.getKillTime(), currentTime)); + REVENGE_HISTORY.put(targetObjectId, targetHistory); + + target.sendPacket(new ExPvpBookShareRevengeNewRevengeInfo(player.getName(), killer.getName(), RevengeType.HELP_REQUEST)); + target.sendPacket(new ExPvpBookShareRevengeList(target)); + } + } + player.sendPacket(new ExPvpBookShareRevengeList(player)); + } + + public Collection getHistory(Player player) + { + return REVENGE_HISTORY.get(player.getObjectId()); + } + + public static RevengeHistoryManager getInstance() + { + return SingletonHolder.INSTANCE; + } + + private static class SingletonHolder + { + protected static final RevengeHistoryManager INSTANCE = new RevengeHistoryManager(); + } +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Player.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Player.java index 9a17929089..1be5a6813d 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Player.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Player.java @@ -136,6 +136,7 @@ import org.l2jmobius.gameserver.instancemanager.MentorManager; import org.l2jmobius.gameserver.instancemanager.PunishmentManager; import org.l2jmobius.gameserver.instancemanager.QuestManager; import org.l2jmobius.gameserver.instancemanager.RecipeManager; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; import org.l2jmobius.gameserver.instancemanager.SellBuffsManager; import org.l2jmobius.gameserver.instancemanager.SiegeManager; import org.l2jmobius.gameserver.instancemanager.ZoneManager; @@ -534,6 +535,8 @@ public class Player extends Playable /** The PvP Flag state of the Player (0=White, 1=Purple) */ private byte _pvpFlag; + private int _einhasadOverseeingLevel = 0; + private final List _lastDamageTaken = new ArrayList<>(21); /** The Fame of this Player */ @@ -2173,6 +2176,67 @@ public class Player extends Playable sendPacket(new SystemMessage(SystemMessageId.YOUR_REPUTATION_HAS_BEEN_CHANGED_TO_S1).addInt(getReputation())); broadcastReputation(); + + applyKarmaPenalty(); + } + + public void applyKarmaPenalty() + { + final int expectedLevel; + if (getReputation() < -33840) + { + expectedLevel = 5; + } + else if (getReputation() < -30240) + { + expectedLevel = 4; + } + else if (getReputation() < -27000) + { + expectedLevel = 3; + } + else if (getReputation() < -18000) + { + expectedLevel = 2; + } + else if (getReputation() < 0) + { + expectedLevel = 1; + } + else + { + expectedLevel = 0; + } + + if (expectedLevel > 0) + { + if (_einhasadOverseeingLevel != expectedLevel) + { + getEffectList().stopSkillEffects(SkillFinishType.REMOVED, CommonSkill.EINHASAD_OVERSEEING.getId()); + SkillData.getInstance().getSkill(CommonSkill.EINHASAD_OVERSEEING.getId(), expectedLevel).applyEffects(this, this); + } + } + else + { + getEffectList().stopSkillEffects(SkillFinishType.REMOVED, CommonSkill.EINHASAD_OVERSEEING.getId()); + getServitors().values().forEach(s -> s.getEffectList().stopSkillEffects(SkillFinishType.REMOVED, CommonSkill.EINHASAD_OVERSEEING.getId())); + if (getPet() != null) + { + getPet().getEffectList().stopSkillEffects(SkillFinishType.REMOVED, CommonSkill.EINHASAD_OVERSEEING.getId()); + } + } + + _einhasadOverseeingLevel = expectedLevel; + } + + public int getEinhasadOverseeingLevel() + { + return _einhasadOverseeingLevel; + } + + public void setEinhasadOverseeingLevel(int level) + { + _einhasadOverseeingLevel = level; } public int getWeightPenalty() @@ -4897,6 +4961,11 @@ public class Player extends Playable setTotalDeaths(getTotalDeaths() + 1); + if (pk != this) + { + RevengeHistoryManager.getInstance().addNewKill(this, pk); + } + // pvp/pk item rewards if (!(Config.DISABLE_REWARDS_IN_INSTANCES && (getInstanceId() != 0)) && // !(Config.DISABLE_REWARDS_IN_PVP_ZONES && isInsideZone(ZoneId.PVP))) @@ -10343,6 +10412,8 @@ public class Player extends Playable DecayTaskManager.getInstance().cancel(this); } + applyKarmaPenalty(); + sendPacket(new EtcStatusUpdate(this)); _revivePet = false; _reviveRequested = 0; diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/RevengeHistoryHolder.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/RevengeHistoryHolder.java new file mode 100644 index 0000000000..af044bcebb --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/RevengeHistoryHolder.java @@ -0,0 +1,223 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.model.holders; + +import org.l2jmobius.gameserver.enums.RevengeType; +import org.l2jmobius.gameserver.model.StatSet; +import org.l2jmobius.gameserver.model.actor.Player; + +/** + * @author Mobius + */ +public class RevengeHistoryHolder +{ + private final String _killerName; + private final String _killerClanName; + private final int _killerLevel; + private final int _killerRaceId; + private final int _killerClassId; + private final long _killTime; + private final String _victimName; + private final String _victimClanName; + private final int _victimLevel; + private final int _victimRaceId; + private final int _victimClassId; + private RevengeType _type; + private boolean _wasShared; + private long _shareTime; + private int _showLocationRemaining; + private int _teleportRemaining; + private int _sharedTeleportRemaining; + + public RevengeHistoryHolder(Player killer, Player victim, RevengeType type) + { + _type = type; + _wasShared = false; + _killerName = killer.getName(); + _killerClanName = killer.getClan() == null ? "" : killer.getClan().getName(); + _killerLevel = killer.getLevel(); + _killerRaceId = killer.getRace().ordinal(); + _killerClassId = killer.getClassId().getId(); + _killTime = System.currentTimeMillis(); + _shareTime = 0; + _showLocationRemaining = 5; + _teleportRemaining = 5; + _sharedTeleportRemaining = 1; + _victimName = victim.getName(); + _victimClanName = victim.getClan() == null ? "" : victim.getClan().getName(); + _victimLevel = victim.getLevel(); + _victimRaceId = victim.getRace().ordinal(); + _victimClassId = victim.getClassId().getId(); + } + + public RevengeHistoryHolder(Player killer, Player victim, RevengeType type, int sharedTeleportRemaining, long killTime, long shareTime) + { + _type = type; + _wasShared = true; + _killerName = killer.getName(); + _killerClanName = killer.getClan() == null ? "" : killer.getClan().getName(); + _killerLevel = killer.getLevel(); + _killerRaceId = killer.getRace().ordinal(); + _killerClassId = killer.getClassId().getId(); + _killTime = killTime; + _shareTime = shareTime; + _showLocationRemaining = 0; + _teleportRemaining = 0; + _sharedTeleportRemaining = sharedTeleportRemaining; + _victimName = victim.getName(); + _victimClanName = victim.getClan() == null ? "" : victim.getClan().getName(); + _victimLevel = victim.getLevel(); + _victimRaceId = victim.getRace().ordinal(); + _victimClassId = victim.getClassId().getId(); + } + + public RevengeHistoryHolder(StatSet killer, StatSet victim, RevengeType type, boolean wasShared, int showLocationRemaining, int teleportRemaining, int sharedTeleportRemaining, long killTime, long shareTime) + { + _type = type; + _wasShared = wasShared; + _killerName = killer.getString("name"); + _killerClanName = killer.getString("clan"); + _killerLevel = killer.getInt("level"); + _killerRaceId = killer.getInt("race"); + _killerClassId = killer.getInt("class"); + _killTime = killTime; + _shareTime = shareTime; + _showLocationRemaining = showLocationRemaining; + _teleportRemaining = teleportRemaining; + _sharedTeleportRemaining = sharedTeleportRemaining; + _victimName = victim.getString("name"); + _victimClanName = victim.getString("clan"); + _victimLevel = victim.getInt("level"); + _victimRaceId = victim.getInt("race"); + _victimClassId = victim.getInt("class"); + } + + public RevengeType getType() + { + return _type; + } + + public void setType(RevengeType type) + { + _type = type; + } + + public boolean wasShared() + { + return _wasShared; + } + + public void setShared(boolean wasShared) + { + _wasShared = wasShared; + } + + public String getKillerName() + { + return _killerName; + } + + public String getKillerClanName() + { + return _killerClanName; + } + + public int getKillerLevel() + { + return _killerLevel; + } + + public int getKillerRaceId() + { + return _killerRaceId; + } + + public int getKillerClassId() + { + return _killerClassId; + } + + public long getKillTime() + { + return _killTime; + } + + public long getShareTime() + { + return _shareTime; + } + + public void setShareTime(long shareTime) + { + _shareTime = shareTime; + } + + public int getShowLocationRemaining() + { + return _showLocationRemaining; + } + + public void setShowLocationRemaining(int count) + { + _showLocationRemaining = count; + } + + public int getTeleportRemaining() + { + return _teleportRemaining; + } + + public void setTeleportRemaining(int count) + { + _teleportRemaining = count; + } + + public int getSharedTeleportRemaining() + { + return _sharedTeleportRemaining; + } + + public void setSharedTeleportRemaining(int count) + { + _sharedTeleportRemaining = count; + } + + public String getVictimName() + { + return _victimName; + } + + public String getVictimClanName() + { + return _victimClanName; + } + + public int getVictimLevel() + { + return _victimLevel; + } + + public int getVictimRaceId() + { + return _victimRaceId; + } + + public int getVictimClassId() + { + return _victimClassId; + } +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/skill/CommonSkill.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/skill/CommonSkill.java index 1243e35f39..8adfc24af9 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/skill/CommonSkill.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/skill/CommonSkill.java @@ -78,6 +78,7 @@ public enum CommonSkill MEN_INCREASE_BONUS_1(45196, 1), MEN_INCREASE_BONUS_2(45196, 2), MEN_INCREASE_BONUS_3(45196, 3), + EINHASAD_OVERSEEING(60002, 1), TELEPORT(60018, 1); private final SkillHolder _holder; diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/skill/SkillCaster.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/skill/SkillCaster.java index f870ade2b2..a16af95a50 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/skill/SkillCaster.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/skill/SkillCaster.java @@ -1168,6 +1168,12 @@ public class SkillCaster implements Runnable return false; } + // Einhasad Overseeing + if (skill.hasEffectType(EffectType.TELEPORT) && (player.getEinhasadOverseeingLevel() == 5)) + { + return false; + } + // Events. if (player.isOnEvent()) { diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java index 5b3e949d65..643f5f50a5 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java @@ -141,6 +141,11 @@ import org.l2jmobius.gameserver.network.clientpackets.ranking.RequestPvpRankingL import org.l2jmobius.gameserver.network.clientpackets.ranking.RequestPvpRankingMyInfo; import org.l2jmobius.gameserver.network.clientpackets.ranking.RequestRankingCharInfo; import org.l2jmobius.gameserver.network.clientpackets.ranking.RequestRankingCharRankers; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeKillerLocation; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeList; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeReqShareRevengeInfo; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeSharedTeleportToKiller; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeTeleportToKiller; import org.l2jmobius.gameserver.network.clientpackets.sayune.RequestFlyMove; import org.l2jmobius.gameserver.network.clientpackets.sayune.RequestFlyMoveStart; import org.l2jmobius.gameserver.network.clientpackets.settings.ExInteractModify; @@ -660,11 +665,11 @@ public enum ExIncomingPackets implements IIncomingPackets EX_COLLECTION_SUMMARY(0x1DF, null, ConnectionState.IN_GAME), EX_COLLECTION_REGISTER(0x1E0, RequestCollectionRegister::new, ConnectionState.IN_GAME), EX_COLLECTION_RECEIVE_REWARD(0x1E1, RequestCollectionReceiveReward::new, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_LIST(0x1E2, null, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_REQ_SHARE_REVENGEINFO(0x1E3, null, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_KILLER_LOCATION(0x1E4, null, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_TELEPORT_TO_KILLER(0x1E5, null, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_SHARED_TELEPORT_TO_KILLER(0x1E6, null, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_LIST(0x1E2, RequestExPvpBookShareRevengeList::new, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_REQ_SHARE_REVENGEINFO(0x1E3, RequestExPvpBookShareRevengeReqShareRevengeInfo::new, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_KILLER_LOCATION(0x1E4, RequestExPvpBookShareRevengeKillerLocation::new, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_TELEPORT_TO_KILLER(0x1E5, RequestExPvpBookShareRevengeTeleportToKiller::new, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_SHARED_TELEPORT_TO_KILLER(0x1E6, RequestExPvpBookShareRevengeSharedTeleportToKiller::new, ConnectionState.IN_GAME), EX_PENALTY_ITEM_LIST(0x1E7, null, ConnectionState.IN_GAME), EX_PENALTY_ITEM_RESTORE(0x1E8, null, ConnectionState.IN_GAME), EX_USER_WATCHER_TARGET_LIST(0x1E9, null, ConnectionState.IN_GAME), diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index 5816f830d2..8465de5b99 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -682,6 +682,8 @@ public class EnterWorld implements IClientIncomingPacket player.sendPacket(new ItemDeletionInfo()); + player.applyKarmaPenalty(); + // Activate first agathion when available. final Item agathion = player.getInventory().unEquipItemInBodySlot(ItemTemplate.SLOT_AGATHION); if (agathion != null) diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeKillerLocation.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeKillerLocation.java new file mode 100644 index 0000000000..ac5cd36b13 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeKillerLocation.java @@ -0,0 +1,51 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeKillerLocation implements IClientIncomingPacket +{ + private String _killerName; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + packet.readString(); // Victim name. + _killerName = packet.readString(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + RevengeHistoryManager.getInstance().locateKiller(player, _killerName); + } +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeList.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeList.java new file mode 100644 index 0000000000..257e28d67c --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeList.java @@ -0,0 +1,55 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; +import org.l2jmobius.gameserver.network.serverpackets.revenge.ExPvpBookShareRevengeList; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeList implements IClientIncomingPacket +{ + private int _objectId; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + _objectId = packet.readD(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + if (_objectId != player.getObjectId()) + { + return; + } + + player.sendPacket(new ExPvpBookShareRevengeList(player)); + } +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeReqShareRevengeInfo.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeReqShareRevengeInfo.java new file mode 100644 index 0000000000..21105f159c --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeReqShareRevengeInfo.java @@ -0,0 +1,71 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.World; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; +import org.l2jmobius.gameserver.network.serverpackets.SystemMessage; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeReqShareRevengeInfo implements IClientIncomingPacket +{ + private String _victimName; + private String _killerName; + private int _type; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + _victimName = packet.readString(); + _killerName = packet.readString(); + _type = packet.readD(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + if (!_victimName.equals(player.getName())) + { + return; + } + + final Player killer = World.getInstance().getPlayer(_killerName); + if ((killer == null) || !killer.isOnline()) + { + SystemMessage sm = new SystemMessage(SystemMessageId.S1_CURRENTLY_OFFLINE); + sm.addString(_killerName); + player.sendPacket(sm); + return; + } + + RevengeHistoryManager.getInstance().requestHelp(player, killer, _type); + } +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeSharedTeleportToKiller.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeSharedTeleportToKiller.java new file mode 100644 index 0000000000..ad1c3ce25f --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeSharedTeleportToKiller.java @@ -0,0 +1,52 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeSharedTeleportToKiller implements IClientIncomingPacket +{ + private String _victimName; + private String _killerName; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + _victimName = packet.readString(); + _killerName = packet.readString(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + RevengeHistoryManager.getInstance().teleportToSharedKiller(player, _victimName, _killerName); + } +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeTeleportToKiller.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeTeleportToKiller.java new file mode 100644 index 0000000000..3dc8ba3a86 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeTeleportToKiller.java @@ -0,0 +1,57 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeTeleportToKiller implements IClientIncomingPacket +{ + private String _victimName; + private String _killerName; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + _victimName = packet.readString(); + _killerName = packet.readString(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + if (!_victimName.equals(player.getName())) + { + return; + } + + RevengeHistoryManager.getInstance().teleportToKiller(player, _killerName); + } +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeKillerLocation.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeKillerLocation.java new file mode 100644 index 0000000000..40cd3d3505 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeKillerLocation.java @@ -0,0 +1,46 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.serverpackets.revenge; + +import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.OutgoingPackets; +import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; + +/** + * @author Mobius + */ +public class ExPvpBookShareRevengeKillerLocation implements IClientOutgoingPacket +{ + private final Player _player; + + public ExPvpBookShareRevengeKillerLocation(Player player) + { + _player = player; + } + + @Override + public boolean write(PacketWriter packet) + { + OutgoingPackets.EX_PVPBOOK_SHARE_REVENGE_KILLER_LOCATION.writeId(packet); + packet.writeString(_player.getName()); + packet.writeD(_player.getX()); + packet.writeD(_player.getY()); + packet.writeD(_player.getZ()); + return true; + } +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeList.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeList.java new file mode 100644 index 0000000000..c0836c2ec8 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeList.java @@ -0,0 +1,83 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.serverpackets.revenge; + +import java.util.Collection; + +import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.World; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.model.holders.RevengeHistoryHolder; +import org.l2jmobius.gameserver.network.OutgoingPackets; +import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; + +/** + * @author Mobius + */ +public class ExPvpBookShareRevengeList implements IClientOutgoingPacket +{ + private final Collection _history; + + public ExPvpBookShareRevengeList(Player player) + { + _history = RevengeHistoryManager.getInstance().getHistory(player); + } + + @Override + public boolean write(PacketWriter packet) + { + OutgoingPackets.EX_PVPBOOK_SHARE_REVENGE_LIST.writeId(packet); + if (_history == null) + { + packet.writeC(1); // CurrentPage + packet.writeC(1); // MaxPage + packet.writeD(0); + } + else + { + packet.writeC(1); // CurrentPage + packet.writeC(1); // MaxPage + packet.writeD(_history.size()); + for (RevengeHistoryHolder holder : _history) + { + packet.writeD(holder.getType().ordinal()); // ShareType (2 - help request, 1 - revenge, 0 - both) + packet.writeD((int) (holder.getKillTime() / 1000)); // KilledTime + packet.writeD(holder.getShowLocationRemaining()); // ShowKillerCount + packet.writeD(holder.getTeleportRemaining()); // TeleportKillerCount + packet.writeD(holder.getSharedTeleportRemaining()); // SharedTeleportKillerCount + packet.writeD(0); // KilledUserDBID + packet.writeString(holder.getVictimName()); // KilledUserName + packet.writeString(holder.getVictimClanName()); // KilledUserPledgeName + packet.writeD(holder.getVictimLevel()); // KilledUserLevel + packet.writeD(holder.getVictimRaceId()); // KilledUserRace + packet.writeD(holder.getVictimClassId()); // KilledUserClass + packet.writeD(0); // KillUserDBID + packet.writeString(holder.getKillerName()); // KillUserName + packet.writeString(holder.getKillerClanName()); // KillUserPledgeName + packet.writeD(holder.getKillerLevel()); // KillUserLevel + packet.writeD(holder.getKillerRaceId()); // KillUserRace + packet.writeD(holder.getKillerClassId()); // KillUserClass + Player killer = World.getInstance().getPlayer(holder.getKillerName()); + packet.writeD((killer != null) && killer.isOnline() ? 2 : 0); // KillUserOnline (2 - online, 0 - offline) + packet.writeD(0); // KillUserKarma + packet.writeD((int) (holder.getShareTime() / 1000)); // nSharedTime + } + } + return true; + } +} diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeNewRevengeInfo.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeNewRevengeInfo.java new file mode 100644 index 0000000000..28cb903401 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeNewRevengeInfo.java @@ -0,0 +1,49 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.serverpackets.revenge; + +import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.enums.RevengeType; +import org.l2jmobius.gameserver.network.OutgoingPackets; +import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; + +/** + * @author Mobius + */ +public class ExPvpBookShareRevengeNewRevengeInfo implements IClientOutgoingPacket +{ + private final String _victimName; + private final String _killerName; + private final RevengeType _type; + + public ExPvpBookShareRevengeNewRevengeInfo(String victimName, String killerName, RevengeType type) + { + _victimName = victimName; + _killerName = killerName; + _type = type; + } + + @Override + public boolean write(PacketWriter packet) + { + OutgoingPackets.EX_PVPBOOK_SHARE_REVENGE_NEW_REVENGEINFO.writeId(packet); + packet.writeD(_type.ordinal()); + packet.writeString(_victimName); + packet.writeString(_killerName); + return true; + } +} \ No newline at end of file diff --git a/L2J_Mobius_Essence_5.2_FrostLord/readme.txt b/L2J_Mobius_Essence_5.2_FrostLord/readme.txt index d885184bf2..d62bc0da4b 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/readme.txt +++ b/L2J_Mobius_Essence_5.2_FrostLord/readme.txt @@ -136,6 +136,7 @@ Sylph: https://eu.4game.com/patchnotes/lineage2essence/281/ Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/ -Resurrection with payment -Frost Lord castle +-Revenge system Customs: -Newbie Helper NPC location info diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/db_installer/sql/game/character_revenge_history.sql b/L2J_Mobius_Essence_6.2_Vanguard/dist/db_installer/sql/game/character_revenge_history.sql new file mode 100644 index 0000000000..5be9d849cf --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/db_installer/sql/game/character_revenge_history.sql @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS `character_revenge_history`; +CREATE TABLE IF NOT EXISTS `character_revenge_history` ( + `charId` int(10) UNSIGNED NOT NULL, + `type` int(10) NOT NULL, + `killer_name` VARCHAR(35), + `killer_clan` VARCHAR(45), + `killer_level` int UNSIGNED NOT NULL, + `killer_race` int NOT NULL DEFAULT 0, + `killer_class` int NOT NULL DEFAULT 0, + `victim_name` VARCHAR(35), + `victim_clan` VARCHAR(45), + `victim_level` int UNSIGNED NOT NULL, + `victim_race` int NOT NULL DEFAULT 0, + `victim_class` int NOT NULL DEFAULT 0, + `shared` TINYINT(1) NOT NULL DEFAULT 0, + `show_location_remaining` int NOT NULL DEFAULT 0, + `teleport_remaining` int NOT NULL DEFAULT 0, + `shared_teleport_remaining` int NOT NULL DEFAULT 0, + `kill_time` BIGINT(10) UNSIGNED NOT NULL, + `share_time` BIGINT(10) UNSIGNED NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/handlers/effecthandlers/Teleport.java b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/handlers/effecthandlers/Teleport.java index 673f0d4609..6f77938d03 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/handlers/effecthandlers/Teleport.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/handlers/effecthandlers/Teleport.java @@ -52,6 +52,9 @@ public class Teleport extends AbstractEffect @Override public void instant(Creature effector, Creature effected, Skill skill, Item item) { - effected.teleToLocation(_loc, true, null); + if ((_loc.getX() != 0) && (_loc.getY() != 0) && (_loc.getZ() != 0)) + { + effected.teleToLocation(_loc, true, null); + } } } diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/stats/skills/60000-60099.xml b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/stats/skills/60000-60099.xml index a70115c588..778a790e05 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/stats/skills/60000-60099.xml +++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/stats/skills/60000-60099.xml @@ -6,38 +6,19 @@ P 5000 - + icon.karma - 10 - P - 5 - - - - -5 - -10 - -15 - - PER - - - - -5 - -10 - -15 - - PER - - - - -5 - -10 - -30 - - DIFF - - + A2 + SELF + SINGLE + 4 + 1 + -1 + true + true + false + true @@ -320,6 +301,9 @@ icon.skill0000 A1 2000 + + + diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/GameServer.java index d3d4987cf4..d511b555fa 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/GameServer.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/GameServer.java @@ -159,6 +159,7 @@ import org.l2jmobius.gameserver.instancemanager.PurgeRankingManager; import org.l2jmobius.gameserver.instancemanager.QuestManager; import org.l2jmobius.gameserver.instancemanager.RankManager; import org.l2jmobius.gameserver.instancemanager.RankingPowerManager; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; import org.l2jmobius.gameserver.instancemanager.SellBuffsManager; import org.l2jmobius.gameserver.instancemanager.ServerRestartManager; import org.l2jmobius.gameserver.instancemanager.SharedTeleportManager; @@ -322,6 +323,7 @@ public class GameServer AttendanceRewardData.getInstance(); MagicLampData.getInstance(); RandomCraftData.getInstance(); + RevengeHistoryManager.getInstance(); VipData.getInstance(); printSection("Characters"); diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/Shutdown.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/Shutdown.java index b22ad02193..22f8e4af27 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/Shutdown.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/Shutdown.java @@ -36,6 +36,7 @@ import org.l2jmobius.gameserver.instancemanager.ItemAuctionManager; import org.l2jmobius.gameserver.instancemanager.ItemsOnGroundManager; import org.l2jmobius.gameserver.instancemanager.PrecautionaryRestartManager; import org.l2jmobius.gameserver.instancemanager.QuestManager; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.olympiad.Hero; @@ -145,6 +146,16 @@ public class Shutdown extends Thread // ignore } + try + { + RevengeHistoryManager.getInstance().storeMe(); + LOGGER.info("Saved Revenge History(" + tc.getEstimatedTimeAndRestartCounter() + "ms)."); + } + catch (Throwable t) + { + // ignore + } + // ensure all services are stopped try diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/RevengeType.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/RevengeType.java new file mode 100644 index 0000000000..962e4f5fe6 --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/RevengeType.java @@ -0,0 +1,27 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.enums; + +/** + * @author Mobius + */ +public enum RevengeType +{ + OWN_HELP_REQUEST, + REVENGE, + HELP_REQUEST; +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java index a68e644717..3d71f39fdf 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java @@ -148,6 +148,8 @@ public class DailyTaskManager { GlobalVariablesManager.getInstance().storeMe(); + RevengeHistoryManager.getInstance().storeMe(); + if (Config.WORLD_EXCHANGE_LAZY_UPDATE) { WorldExchangeManager.getInstance().storeMe(); diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/IdManager.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/IdManager.java index 93bfd8b78c..96a825d4bc 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/IdManager.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/IdManager.java @@ -129,6 +129,7 @@ public class IdManager cleanCount += statement.executeUpdate("DELETE FROM character_offline_trade_items WHERE character_offline_trade_items.charId NOT IN (SELECT charId FROM characters);"); cleanCount += statement.executeUpdate("DELETE FROM character_tpbookmark WHERE character_tpbookmark.charId NOT IN (SELECT charId FROM characters);"); cleanCount += statement.executeUpdate("DELETE FROM character_variables WHERE character_variables.charId NOT IN (SELECT charId FROM characters);"); + cleanCount += statement.executeUpdate("DELETE FROM character_revenge_history WHERE character_revenge_history.charId NOT IN (SELECT charId FROM characters);"); cleanCount += statement.executeUpdate("DELETE FROM bot_reported_char_data WHERE bot_reported_char_data.botId NOT IN (SELECT charId FROM characters);"); // Clan diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/RankManager.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/RankManager.java index bfe1bccd8e..37b2440c44 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/RankManager.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/RankManager.java @@ -19,6 +19,9 @@ package org.l2jmobius.gameserver.instancemanager; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; @@ -31,6 +34,7 @@ import org.l2jmobius.gameserver.data.sql.ClanTable; import org.l2jmobius.gameserver.data.xml.PetDataTable; import org.l2jmobius.gameserver.model.PetData; import org.l2jmobius.gameserver.model.StatSet; +import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.olympiad.Hero; @@ -435,6 +439,28 @@ public class RankManager return 0; } + public Collection getTop50() + { + final List result = new LinkedList<>(); + for (int i = 1; i <= 50; i++) + { + final StatSet rank = _mainList.get(i); + if (rank == null) + { + break; + } + + final Player player = World.getInstance().getPlayer(rank.getInt("charId")); + if ((player == null) || (player.isOnlineInt() != 1)) + { + continue; + } + + result.add(player); + } + return result; + } + public static RankManager getInstance() { return SingletonHolder.INSTANCE; diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/RevengeHistoryManager.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/RevengeHistoryManager.java new file mode 100644 index 0000000000..05d418fa3c --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/RevengeHistoryManager.java @@ -0,0 +1,480 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.instancemanager; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.logging.Logger; + +import org.l2jmobius.commons.database.DatabaseFactory; +import org.l2jmobius.gameserver.enums.RevengeType; +import org.l2jmobius.gameserver.model.StatSet; +import org.l2jmobius.gameserver.model.World; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.model.actor.Summon; +import org.l2jmobius.gameserver.model.holders.RevengeHistoryHolder; +import org.l2jmobius.gameserver.model.holders.SkillHolder; +import org.l2jmobius.gameserver.model.itemcontainer.Inventory; +import org.l2jmobius.gameserver.model.zone.ZoneId; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.serverpackets.revenge.ExPvpBookShareRevengeKillerLocation; +import org.l2jmobius.gameserver.network.serverpackets.revenge.ExPvpBookShareRevengeList; +import org.l2jmobius.gameserver.network.serverpackets.revenge.ExPvpBookShareRevengeNewRevengeInfo; + +/** + * @author Mobius + */ +public class RevengeHistoryManager +{ + private static final Logger LOGGER = Logger.getLogger(RevengeHistoryManager.class.getName()); + + private static final Map> REVENGE_HISTORY = new ConcurrentHashMap<>(); + private static final String DELETE_REVENGE_HISTORY = "TRUNCATE TABLE character_revenge_history"; + private static final String INSERT_REVENGE_HISTORY = "INSERT INTO character_revenge_history (charId, type, killer_name, killer_clan, killer_level, killer_race, killer_class, victim_name, victim_clan, victim_level, victim_race, victim_class, shared, show_location_remaining, teleport_remaining, shared_teleport_remaining, kill_time, share_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + private static final SkillHolder HIDE_SKILL = new SkillHolder(922, 1); + private static final long REVENGE_DURATION = 21600000; // Six hours. + private static final int[] LOCATION_PRICE = + { + 0, + 50000, + 100000, + 100000, + 200000 + }; + private static final int[] TELEPORT_PRICE = + { + 10, + 50, + 100, + 100, + 200 + }; + + protected RevengeHistoryManager() + { + try (Connection con = DatabaseFactory.getConnection(); + PreparedStatement ps = con.prepareStatement("SELECT * FROM character_revenge_history")) + { + ResultSet rs = ps.executeQuery(); + while (rs.next()) + { + final int charId = rs.getInt("charId"); + final List history = REVENGE_HISTORY.containsKey(charId) ? REVENGE_HISTORY.get(charId) : new CopyOnWriteArrayList<>(); + final StatSet killer = new StatSet(); + killer.set("name", rs.getString("killer_name")); + killer.set("clan", rs.getString("killer_clan")); + killer.set("level", rs.getInt("killer_level")); + killer.set("race", rs.getInt("killer_race")); + killer.set("class", rs.getInt("killer_class")); + final StatSet victim = new StatSet(); + victim.set("name", rs.getString("victim_name")); + victim.set("clan", rs.getString("victim_clan")); + victim.set("level", rs.getInt("victim_level")); + victim.set("race", rs.getInt("victim_race")); + victim.set("class", rs.getInt("victim_class")); + history.add(new RevengeHistoryHolder(killer, victim, RevengeType.values()[rs.getInt("type")], rs.getBoolean("shared"), rs.getInt("show_location_remaining"), rs.getInt("teleport_remaining"), rs.getInt("shared_teleport_remaining"), rs.getLong("kill_time"), rs.getLong("share_time"))); + REVENGE_HISTORY.put(charId, history); + } + } + catch (Exception e) + { + LOGGER.warning("Failed loading revenge history! " + e); + } + } + + public void storeMe() + { + for (Entry> entry : REVENGE_HISTORY.entrySet()) + { + final List history = entry.getValue(); + if (history != null) + { + final long currentTime = System.currentTimeMillis(); + final List removals = new ArrayList<>(); + for (RevengeHistoryHolder holder : history) + { + if (((holder.getKillTime() != 0) && ((holder.getKillTime() + REVENGE_DURATION) < currentTime)) || // + ((holder.getShareTime() != 0) && ((holder.getShareTime() + REVENGE_DURATION) < currentTime))) + { + removals.add(holder); + } + } + for (RevengeHistoryHolder holder : removals) + { + history.remove(holder); + } + } + } + + try (Connection con = DatabaseFactory.getConnection(); + PreparedStatement ps1 = con.prepareStatement(DELETE_REVENGE_HISTORY); + PreparedStatement ps2 = con.prepareStatement(INSERT_REVENGE_HISTORY)) + { + ps1.execute(); + + for (Entry> entry : REVENGE_HISTORY.entrySet()) + { + final List history = entry.getValue(); + if ((history == null) || history.isEmpty()) + { + continue; + } + + for (RevengeHistoryHolder holder : history) + { + ps2.clearParameters(); + ps2.setInt(1, entry.getKey()); + ps2.setInt(2, holder.getType().ordinal()); + ps2.setString(3, holder.getKillerName()); + ps2.setString(4, holder.getKillerClanName()); + ps2.setInt(5, holder.getKillerLevel()); + ps2.setInt(6, holder.getKillerRaceId()); + ps2.setInt(7, holder.getKillerClassId()); + ps2.setString(8, holder.getVictimName()); + ps2.setString(9, holder.getVictimClanName()); + ps2.setInt(10, holder.getVictimLevel()); + ps2.setInt(11, holder.getVictimRaceId()); + ps2.setInt(12, holder.getVictimClassId()); + ps2.setBoolean(13, holder.wasShared()); + ps2.setInt(14, holder.getShowLocationRemaining()); + ps2.setInt(15, holder.getTeleportRemaining()); + ps2.setInt(16, holder.getSharedTeleportRemaining()); + ps2.setLong(17, holder.getKillTime()); + ps2.setLong(18, holder.getShareTime()); + ps2.addBatch(); + } + } + ps2.executeBatch(); + } + catch (Exception e) + { + LOGGER.warning(getClass().getSimpleName() + " Error while saving revenge history. " + e); + } + } + + public void addNewKill(Player victim, Player killer) + { + try + { + boolean found = false; + final int victimObjectId = victim.getObjectId(); + final long currentTime = System.currentTimeMillis(); + final List removals = new ArrayList<>(); + final List history = REVENGE_HISTORY.containsKey(victimObjectId) ? REVENGE_HISTORY.get(victimObjectId) : new CopyOnWriteArrayList<>(); + for (RevengeHistoryHolder holder : history) + { + if (((holder.getKillTime() != 0) && ((holder.getKillTime() + REVENGE_DURATION) < currentTime)) || // + ((holder.getShareTime() != 0) && ((holder.getShareTime() + REVENGE_DURATION) < currentTime))) + { + removals.add(holder); + } + else if (holder.getKillerName().equals(killer.getName())) + { + found = true; + } + } + + history.removeAll(removals); + + if (!found) + { + history.add(new RevengeHistoryHolder(killer, victim, RevengeType.REVENGE)); + REVENGE_HISTORY.put(victimObjectId, history); + victim.sendPacket(new ExPvpBookShareRevengeNewRevengeInfo(victim.getName(), killer.getName(), RevengeType.REVENGE)); + victim.sendPacket(new ExPvpBookShareRevengeList(victim)); + } + } + catch (Exception e) + { + LOGGER.warning(getClass().getSimpleName() + ": Failed adding revenge history! " + e); + } + } + + public void locateKiller(Player player, String killerName) + { + final List history = REVENGE_HISTORY.get(player.getObjectId()); + if (history == null) + { + return; + } + + RevengeHistoryHolder revenge = null; + for (RevengeHistoryHolder holder : history) + { + if (holder.getKillerName().equals(killerName)) + { + revenge = holder; + break; + } + } + + if (revenge == null) + { + return; + } + + final Player killer = World.getInstance().getPlayer(killerName); + if ((killer == null) || !killer.isOnline()) + { + player.sendPacket(SystemMessageId.THE_ENEMY_IS_OFFLINE_AND_CANNOT_BE_FOUND_RIGHT_NOW); + return; + } + + if (killer.isInsideZone(ZoneId.PEACE) || killer.isInInstance() || killer.isInTimedHuntingZone() || killer.isInsideZone(ZoneId.SIEGE) // + || player.isDead() || player.isInInstance() || player.isInTimedHuntingZone() || player.isInsideZone(ZoneId.SIEGE)) + { + player.sendPacket(SystemMessageId.THE_CHARACTER_IS_IN_A_LOCATION_WHERE_IT_IS_IMPOSSIBLE_TO_USE_THIS_FUNCTION); + return; + } + + if (revenge.getShowLocationRemaining() > 0) + { + final int price = LOCATION_PRICE[Math.min(LOCATION_PRICE.length - revenge.getShowLocationRemaining(), LOCATION_PRICE.length - 1)]; + if (player.reduceAdena("Revenge find location", price, player, true)) + { + revenge.setShowLocationRemaining(revenge.getShowLocationRemaining() - 1); + player.sendPacket(new ExPvpBookShareRevengeKillerLocation(killer)); + player.sendPacket(new ExPvpBookShareRevengeList(player)); + } + } + } + + private boolean checkTeleportConditions(Player player, Player killer) + { + if ((killer == null) || !killer.isOnline()) + { + player.sendPacket(SystemMessageId.THE_ENEMY_IS_OFFLINE_AND_CANNOT_BE_FOUND_RIGHT_NOW); + return false; + } + if (killer.isTeleporting() || killer.isInsideZone(ZoneId.PEACE) || killer.isInInstance() || killer.isInTimedHuntingZone() || killer.isInsideZone(ZoneId.SIEGE) || killer.isInsideZone(ZoneId.NO_BOOKMARK)) + { + player.sendPacket(SystemMessageId.THE_CHARACTER_IS_IN_A_LOCATION_WHERE_IT_IS_IMPOSSIBLE_TO_USE_THIS_FUNCTION); + return false; + } + if (killer.isDead()) + { + player.sendPacket(SystemMessageId.THE_CHARACTER_IS_IN_A_LOCATION_WHERE_IT_IS_IMPOSSIBLE_TO_USE_THIS_FUNCTION); + return false; + } + + if (player.isInInstance() || player.isInTimedHuntingZone() || player.isInsideZone(ZoneId.SIEGE)) + { + player.sendPacket(SystemMessageId.THE_CHARACTER_IS_IN_A_LOCATION_WHERE_IT_IS_IMPOSSIBLE_TO_USE_THIS_FUNCTION); + return false; + } + if (player.isDead()) + { + player.sendPacket(SystemMessageId.YOU_CANNOT_USE_TELEPORT_WHILE_YOU_ARE_DEAD); + return false; + } + if (player.isInCombat() || player.isDisabled()) + { + player.sendPacket(SystemMessageId.YOU_CANNOT_TELEPORT_WHILE_IN_COMBAT_MODE); + return false; + } + + return true; + } + + public void teleportToKiller(Player player, String killerName) + { + final List history = REVENGE_HISTORY.get(player.getObjectId()); + if (history == null) + { + return; + } + + RevengeHistoryHolder revenge = null; + for (RevengeHistoryHolder holder : history) + { + if (holder.getKillerName().equals(killerName)) + { + revenge = holder; + break; + } + } + + if (revenge == null) + { + return; + } + + if (revenge.wasShared()) + { + return; + } + + final Player killer = World.getInstance().getPlayer(killerName); + if (!checkTeleportConditions(player, killer)) + { + return; + } + + if (revenge.getTeleportRemaining() > 0) + { + final int price = TELEPORT_PRICE[Math.min(TELEPORT_PRICE.length - revenge.getTeleportRemaining(), TELEPORT_PRICE.length - 1)]; + if (player.destroyItemByItemId("Revenge Teleport", Inventory.LCOIN_ID, price, player, true)) + { + revenge.setTeleportRemaining(revenge.getTeleportRemaining() - 1); + HIDE_SKILL.getSkill().applyEffects(player, player); + for (Summon summon : player.getServitorsAndPets()) + { + HIDE_SKILL.getSkill().applyEffects(summon, summon); + } + player.teleToLocation(killer.getLocation()); + } + } + } + + public void teleportToSharedKiller(Player player, String victimName, String killerName) + { + if (player.getName().equals(killerName)) + { + return; + } + + final List history = REVENGE_HISTORY.get(player.getObjectId()); + if (history == null) + { + return; + } + + RevengeHistoryHolder revenge = null; + for (RevengeHistoryHolder holder : history) + { + if (holder.getVictimName().equals(victimName) && holder.getKillerName().equals(killerName)) + { + revenge = holder; + break; + } + } + + if (revenge == null) + { + return; + } + + if (!revenge.wasShared()) + { + return; + } + + final Player killer = World.getInstance().getPlayer(killerName); + if (!checkTeleportConditions(player, killer)) + { + return; + } + + if ((revenge.getSharedTeleportRemaining() > 0) && player.destroyItemByItemId("Revenge Teleport", Inventory.LCOIN_ID, 100, player, true)) + { + revenge.setSharedTeleportRemaining(revenge.getSharedTeleportRemaining() - 1); + HIDE_SKILL.getSkill().applyEffects(player, player); + for (Summon summon : player.getServitorsAndPets()) + { + HIDE_SKILL.getSkill().applyEffects(summon, summon); + } + player.teleToLocation(killer.getLocation()); + } + } + + public void requestHelp(Player player, Player killer, int type) + { + final List history = REVENGE_HISTORY.get(player.getObjectId()); + if (history == null) + { + return; + } + + RevengeHistoryHolder revenge = null; + for (RevengeHistoryHolder holder : history) + { + if (holder.getKillerName().equals(killer.getName())) + { + revenge = holder; + break; + } + } + + if (revenge == null) + { + return; + } + + if (revenge.wasShared()) + { + return; + } + + if (player.reduceAdena("Revenge request help", 100000, player, true)) + { + final long currentTime = System.currentTimeMillis(); + revenge.setShared(true); + revenge.setType(RevengeType.OWN_HELP_REQUEST); + revenge.setShareTime(currentTime); + + final Collection targets = type == 1 ? (player.getClan() == null ? Collections.emptyList() : player.getClan().getOnlineMembers(player.getObjectId())) : type == 2 ? RankManager.getInstance().getTop50() : Collections.emptyList(); + for (Player target : targets) + { + if (target == killer) + { + continue; + } + + final int targetObjectId = target.getObjectId(); + final List targetHistory = REVENGE_HISTORY.containsKey(targetObjectId) ? REVENGE_HISTORY.get(targetObjectId) : new CopyOnWriteArrayList<>(); + for (RevengeHistoryHolder temp : targetHistory) + { + if (temp.getVictimName().equals(player.getName()) && temp.getKillerName().equals(killer.getName()) && (temp != revenge)) + { + targetHistory.remove(temp); + break; + } + } + targetHistory.add(new RevengeHistoryHolder(killer, player, RevengeType.HELP_REQUEST, 1, revenge.getKillTime(), currentTime)); + REVENGE_HISTORY.put(targetObjectId, targetHistory); + + target.sendPacket(new ExPvpBookShareRevengeNewRevengeInfo(player.getName(), killer.getName(), RevengeType.HELP_REQUEST)); + target.sendPacket(new ExPvpBookShareRevengeList(target)); + } + } + player.sendPacket(new ExPvpBookShareRevengeList(player)); + } + + public Collection getHistory(Player player) + { + return REVENGE_HISTORY.get(player.getObjectId()); + } + + public static RevengeHistoryManager getInstance() + { + return SingletonHolder.INSTANCE; + } + + private static class SingletonHolder + { + protected static final RevengeHistoryManager INSTANCE = new RevengeHistoryManager(); + } +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Player.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Player.java index 1a855cc06d..3d31023f44 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Player.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Player.java @@ -138,6 +138,7 @@ import org.l2jmobius.gameserver.instancemanager.MentorManager; import org.l2jmobius.gameserver.instancemanager.PunishmentManager; import org.l2jmobius.gameserver.instancemanager.QuestManager; import org.l2jmobius.gameserver.instancemanager.RecipeManager; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; import org.l2jmobius.gameserver.instancemanager.SellBuffsManager; import org.l2jmobius.gameserver.instancemanager.SiegeManager; import org.l2jmobius.gameserver.instancemanager.ZoneManager; @@ -542,6 +543,8 @@ public class Player extends Playable /** The PvP Flag state of the Player (0=White, 1=Purple) */ private byte _pvpFlag; + private int _einhasadOverseeingLevel = 0; + private final List _lastDamageTaken = new ArrayList<>(21); /** The Fame of this Player */ @@ -2198,6 +2201,87 @@ public class Player extends Playable sendPacket(new SystemMessage(SystemMessageId.YOUR_REPUTATION_HAS_BEEN_CHANGED_TO_S1).addInt(getReputation())); broadcastReputation(); + + applyKarmaPenalty(); + } + + public void applyKarmaPenalty() + { + final int expectedLevel; + if (getReputation() < -288000) + { + expectedLevel = 10; + } + else if (getReputation() < -216000) + { + expectedLevel = 9; + } + else if (getReputation() < -144000) + { + expectedLevel = 8; + } + else if (getReputation() < -72000) + { + expectedLevel = 7; + } + else if (getReputation() < -36000) + { + expectedLevel = 6; + } + else if (getReputation() < -33840) + { + expectedLevel = 5; + } + else if (getReputation() < -30240) + { + expectedLevel = 4; + } + else if (getReputation() < -27000) + { + expectedLevel = 3; + } + else if (getReputation() < -18000) + { + expectedLevel = 2; + } + else if (getReputation() < 0) + { + expectedLevel = 1; + } + else + { + expectedLevel = 0; + } + + if (expectedLevel > 0) + { + if (_einhasadOverseeingLevel != expectedLevel) + { + getEffectList().stopSkillEffects(SkillFinishType.REMOVED, CommonSkill.EINHASAD_OVERSEEING.getId()); + SkillData.getInstance().getSkill(CommonSkill.EINHASAD_OVERSEEING.getId(), expectedLevel).applyEffects(this, this); + } + } + else + { + getEffectList().stopSkillEffects(SkillFinishType.REMOVED, CommonSkill.EINHASAD_OVERSEEING.getId()); + getServitors().values().forEach(s -> s.getEffectList().stopSkillEffects(SkillFinishType.REMOVED, CommonSkill.EINHASAD_OVERSEEING.getId())); + if (getPet() != null) + { + getPet().getEffectList().stopSkillEffects(SkillFinishType.REMOVED, CommonSkill.EINHASAD_OVERSEEING.getId()); + } + } + + _einhasadOverseeingLevel = expectedLevel; + } + + public int getEinhasadOverseeingLevel() + { + return _einhasadOverseeingLevel; + } + + public void setEinhasadOverseeingLevel(int level) + { + _einhasadOverseeingLevel = level; } public int getWeightPenalty() @@ -4950,6 +5034,11 @@ public class Player extends Playable setTotalDeaths(getTotalDeaths() + 1); + if (pk != this) + { + RevengeHistoryManager.getInstance().addNewKill(this, pk); + } + // pvp/pk item rewards if (!(Config.DISABLE_REWARDS_IN_INSTANCES && (getInstanceId() != 0)) && // !(Config.DISABLE_REWARDS_IN_PVP_ZONES && isInsideZone(ZoneId.PVP))) @@ -8314,7 +8403,7 @@ public class Player extends Playable if ((hennaPoten != null) && (hennaPoten.getPotenId() > 0) && hennaPoten.isPotentialAvailable() && (hennaPoten.getActiveStep() > 0)) { final Skill hennaSkill = HennaPatternPotentialData.getInstance().getPotentialSkill(hennaPoten.getPotenId(), i, hennaPoten.getActiveStep()); - if (hennaSkill != null && (hennaSkill.getLevel() > getSkillLevel(hennaSkill.getId()))) + if ((hennaSkill != null) && (hennaSkill.getLevel() > getSkillLevel(hennaSkill.getId()))) { addSkill(hennaSkill, false); } @@ -10559,6 +10648,8 @@ public class Player extends Playable DecayTaskManager.getInstance().cancel(this); } + applyKarmaPenalty(); + sendPacket(new EtcStatusUpdate(this)); _revivePet = false; _reviveRequested = 0; diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java index ea4c9b6021..6098d996a3 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/stat/PlayerStat.java @@ -27,6 +27,7 @@ import org.l2jmobius.gameserver.model.Party; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.actor.Summon; import org.l2jmobius.gameserver.model.actor.instance.Pet; +import org.l2jmobius.gameserver.model.effects.EffectType; import org.l2jmobius.gameserver.model.events.EventDispatcher; import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLevelChanged; @@ -35,6 +36,7 @@ import org.l2jmobius.gameserver.model.holders.SubClassHolder; import org.l2jmobius.gameserver.model.item.instance.Item; import org.l2jmobius.gameserver.model.item.type.WeaponType; import org.l2jmobius.gameserver.model.skill.AbnormalType; +import org.l2jmobius.gameserver.model.skill.Skill; import org.l2jmobius.gameserver.model.stats.Formulas; import org.l2jmobius.gameserver.model.stats.Stat; import org.l2jmobius.gameserver.model.zone.ZoneId; @@ -725,6 +727,44 @@ public class PlayerStat extends PlayableStat return type == null ? 0 : getValue(type.getDefenseStat(), base); } + @Override + public int getReuseTime(Skill skill) + { + int addedReuse = 0; + if (skill.hasEffectType(EffectType.TELEPORT)) + { + switch (getActiveChar().getActingPlayer().getEinhasadOverseeingLevel()) + { + case 6: + { + addedReuse = 20000; + break; + } + case 7: + { + addedReuse = 30000; + break; + } + case 8: + { + addedReuse = 40000; + break; + } + case 9: + { + addedReuse = 50000; + break; + } + case 10: + { + addedReuse = 60000; + break; + } + } + } + return super.getReuseTime(skill) + addedReuse; + } + @Override public void recalculateStats(boolean broadcast) { diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/RevengeHistoryHolder.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/RevengeHistoryHolder.java new file mode 100644 index 0000000000..af044bcebb --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/RevengeHistoryHolder.java @@ -0,0 +1,223 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.model.holders; + +import org.l2jmobius.gameserver.enums.RevengeType; +import org.l2jmobius.gameserver.model.StatSet; +import org.l2jmobius.gameserver.model.actor.Player; + +/** + * @author Mobius + */ +public class RevengeHistoryHolder +{ + private final String _killerName; + private final String _killerClanName; + private final int _killerLevel; + private final int _killerRaceId; + private final int _killerClassId; + private final long _killTime; + private final String _victimName; + private final String _victimClanName; + private final int _victimLevel; + private final int _victimRaceId; + private final int _victimClassId; + private RevengeType _type; + private boolean _wasShared; + private long _shareTime; + private int _showLocationRemaining; + private int _teleportRemaining; + private int _sharedTeleportRemaining; + + public RevengeHistoryHolder(Player killer, Player victim, RevengeType type) + { + _type = type; + _wasShared = false; + _killerName = killer.getName(); + _killerClanName = killer.getClan() == null ? "" : killer.getClan().getName(); + _killerLevel = killer.getLevel(); + _killerRaceId = killer.getRace().ordinal(); + _killerClassId = killer.getClassId().getId(); + _killTime = System.currentTimeMillis(); + _shareTime = 0; + _showLocationRemaining = 5; + _teleportRemaining = 5; + _sharedTeleportRemaining = 1; + _victimName = victim.getName(); + _victimClanName = victim.getClan() == null ? "" : victim.getClan().getName(); + _victimLevel = victim.getLevel(); + _victimRaceId = victim.getRace().ordinal(); + _victimClassId = victim.getClassId().getId(); + } + + public RevengeHistoryHolder(Player killer, Player victim, RevengeType type, int sharedTeleportRemaining, long killTime, long shareTime) + { + _type = type; + _wasShared = true; + _killerName = killer.getName(); + _killerClanName = killer.getClan() == null ? "" : killer.getClan().getName(); + _killerLevel = killer.getLevel(); + _killerRaceId = killer.getRace().ordinal(); + _killerClassId = killer.getClassId().getId(); + _killTime = killTime; + _shareTime = shareTime; + _showLocationRemaining = 0; + _teleportRemaining = 0; + _sharedTeleportRemaining = sharedTeleportRemaining; + _victimName = victim.getName(); + _victimClanName = victim.getClan() == null ? "" : victim.getClan().getName(); + _victimLevel = victim.getLevel(); + _victimRaceId = victim.getRace().ordinal(); + _victimClassId = victim.getClassId().getId(); + } + + public RevengeHistoryHolder(StatSet killer, StatSet victim, RevengeType type, boolean wasShared, int showLocationRemaining, int teleportRemaining, int sharedTeleportRemaining, long killTime, long shareTime) + { + _type = type; + _wasShared = wasShared; + _killerName = killer.getString("name"); + _killerClanName = killer.getString("clan"); + _killerLevel = killer.getInt("level"); + _killerRaceId = killer.getInt("race"); + _killerClassId = killer.getInt("class"); + _killTime = killTime; + _shareTime = shareTime; + _showLocationRemaining = showLocationRemaining; + _teleportRemaining = teleportRemaining; + _sharedTeleportRemaining = sharedTeleportRemaining; + _victimName = victim.getString("name"); + _victimClanName = victim.getString("clan"); + _victimLevel = victim.getInt("level"); + _victimRaceId = victim.getInt("race"); + _victimClassId = victim.getInt("class"); + } + + public RevengeType getType() + { + return _type; + } + + public void setType(RevengeType type) + { + _type = type; + } + + public boolean wasShared() + { + return _wasShared; + } + + public void setShared(boolean wasShared) + { + _wasShared = wasShared; + } + + public String getKillerName() + { + return _killerName; + } + + public String getKillerClanName() + { + return _killerClanName; + } + + public int getKillerLevel() + { + return _killerLevel; + } + + public int getKillerRaceId() + { + return _killerRaceId; + } + + public int getKillerClassId() + { + return _killerClassId; + } + + public long getKillTime() + { + return _killTime; + } + + public long getShareTime() + { + return _shareTime; + } + + public void setShareTime(long shareTime) + { + _shareTime = shareTime; + } + + public int getShowLocationRemaining() + { + return _showLocationRemaining; + } + + public void setShowLocationRemaining(int count) + { + _showLocationRemaining = count; + } + + public int getTeleportRemaining() + { + return _teleportRemaining; + } + + public void setTeleportRemaining(int count) + { + _teleportRemaining = count; + } + + public int getSharedTeleportRemaining() + { + return _sharedTeleportRemaining; + } + + public void setSharedTeleportRemaining(int count) + { + _sharedTeleportRemaining = count; + } + + public String getVictimName() + { + return _victimName; + } + + public String getVictimClanName() + { + return _victimClanName; + } + + public int getVictimLevel() + { + return _victimLevel; + } + + public int getVictimRaceId() + { + return _victimRaceId; + } + + public int getVictimClassId() + { + return _victimClassId; + } +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/skill/CommonSkill.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/skill/CommonSkill.java index 1243e35f39..8adfc24af9 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/skill/CommonSkill.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/skill/CommonSkill.java @@ -78,6 +78,7 @@ public enum CommonSkill MEN_INCREASE_BONUS_1(45196, 1), MEN_INCREASE_BONUS_2(45196, 2), MEN_INCREASE_BONUS_3(45196, 3), + EINHASAD_OVERSEEING(60002, 1), TELEPORT(60018, 1); private final SkillHolder _holder; diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/skill/SkillCaster.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/skill/SkillCaster.java index b125fa3e5e..d7b2338655 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/skill/SkillCaster.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/skill/SkillCaster.java @@ -833,13 +833,46 @@ public class SkillCaster implements Runnable } else { + int addedTime = 0; + if (skill.hasEffectType(EffectType.TELEPORT) && creature.isPlayer()) + { + switch (creature.getActingPlayer().getEinhasadOverseeingLevel()) + { + case 6: + { + addedTime = 2000; + break; + } + case 7: + { + addedTime = 3000; + break; + } + case 8: + { + addedTime = 4000; + break; + } + case 9: + { + addedTime = 5000; + break; + } + case 10: + { + addedTime = 6000; + break; + } + } + } + if (castTime > -1) { - _hitTime = (int) Math.max((castTime / timeFactor) - cancelTime, 0); + _hitTime = (int) Math.max((castTime / timeFactor) - cancelTime, 0) + addedTime; } else { - _hitTime = (int) Math.max((skill.getHitTime() / timeFactor) - cancelTime, 0); + _hitTime = (int) Math.max((skill.getHitTime() / timeFactor) - cancelTime, 0) + addedTime; } _cancelTime = (int) cancelTime; } diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java index e998cd4d30..34988d2cb1 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java @@ -167,6 +167,11 @@ import org.l2jmobius.gameserver.network.clientpackets.ranking.RequestPvpRankingL import org.l2jmobius.gameserver.network.clientpackets.ranking.RequestPvpRankingMyInfo; import org.l2jmobius.gameserver.network.clientpackets.ranking.RequestRankingCharInfo; import org.l2jmobius.gameserver.network.clientpackets.ranking.RequestRankingCharRankers; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeKillerLocation; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeList; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeReqShareRevengeInfo; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeSharedTeleportToKiller; +import org.l2jmobius.gameserver.network.clientpackets.revenge.RequestExPvpBookShareRevengeTeleportToKiller; import org.l2jmobius.gameserver.network.clientpackets.sayune.RequestFlyMove; import org.l2jmobius.gameserver.network.clientpackets.sayune.RequestFlyMoveStart; import org.l2jmobius.gameserver.network.clientpackets.settings.ExInteractModify; @@ -696,11 +701,11 @@ public enum ExIncomingPackets implements IIncomingPackets EX_COLLECTION_SUMMARY(0x1DF, null, ConnectionState.IN_GAME), EX_COLLECTION_REGISTER(0x1E0, RequestCollectionRegister::new, ConnectionState.IN_GAME), EX_COLLECTION_RECEIVE_REWARD(0x1E1, RequestCollectionReceiveReward::new, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_LIST(0x1E2, null, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_REQ_SHARE_REVENGEINFO(0x1E3, null, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_KILLER_LOCATION(0x1E4, null, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_TELEPORT_TO_KILLER(0x1E5, null, ConnectionState.IN_GAME), - EX_PVPBOOK_SHARE_REVENGE_SHARED_TELEPORT_TO_KILLER(0x1E6, null, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_LIST(0x1E2, RequestExPvpBookShareRevengeList::new, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_REQ_SHARE_REVENGEINFO(0x1E3, RequestExPvpBookShareRevengeReqShareRevengeInfo::new, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_KILLER_LOCATION(0x1E4, RequestExPvpBookShareRevengeKillerLocation::new, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_TELEPORT_TO_KILLER(0x1E5, RequestExPvpBookShareRevengeTeleportToKiller::new, ConnectionState.IN_GAME), + EX_PVPBOOK_SHARE_REVENGE_SHARED_TELEPORT_TO_KILLER(0x1E6, RequestExPvpBookShareRevengeSharedTeleportToKiller::new, ConnectionState.IN_GAME), EX_PENALTY_ITEM_LIST(0x1E7, null, ConnectionState.IN_GAME), EX_PENALTY_ITEM_RESTORE(0x1E8, null, ConnectionState.IN_GAME), EX_USER_WATCHER_TARGET_LIST(0x1E9, null, ConnectionState.IN_GAME), diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index 5e9a348e4c..4712b9d80b 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -698,6 +698,8 @@ public class EnterWorld implements IClientIncomingPacket player.sendPacket(new ItemDeletionInfo()); + player.applyKarmaPenalty(); + // Activate first agathion when available. final Item agathion = player.getInventory().unEquipItemInBodySlot(ItemTemplate.SLOT_AGATHION); if (agathion != null) diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeKillerLocation.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeKillerLocation.java new file mode 100644 index 0000000000..396ec57454 --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeKillerLocation.java @@ -0,0 +1,51 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeKillerLocation implements IClientIncomingPacket +{ + private String _killerName; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + packet.readString(); // Victim name. + _killerName = packet.readString(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + RevengeHistoryManager.getInstance().locateKiller(player, _killerName); + } +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeList.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeList.java new file mode 100644 index 0000000000..2f48f2fec9 --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeList.java @@ -0,0 +1,55 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; +import org.l2jmobius.gameserver.network.serverpackets.revenge.ExPvpBookShareRevengeList; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeList implements IClientIncomingPacket +{ + private int _objectId; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + _objectId = packet.readD(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + if (_objectId != player.getObjectId()) + { + return; + } + + player.sendPacket(new ExPvpBookShareRevengeList(player)); + } +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeReqShareRevengeInfo.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeReqShareRevengeInfo.java new file mode 100644 index 0000000000..4c07408e07 --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeReqShareRevengeInfo.java @@ -0,0 +1,71 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.World; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; +import org.l2jmobius.gameserver.network.serverpackets.SystemMessage; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeReqShareRevengeInfo implements IClientIncomingPacket +{ + private String _victimName; + private String _killerName; + private int _type; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + _victimName = packet.readString(); + _killerName = packet.readString(); + _type = packet.readD(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + if (!_victimName.equals(player.getName())) + { + return; + } + + final Player killer = World.getInstance().getPlayer(_killerName); + if ((killer == null) || !killer.isOnline()) + { + SystemMessage sm = new SystemMessage(SystemMessageId.S1_CURRENTLY_OFFLINE); + sm.addString(_killerName); + player.sendPacket(sm); + return; + } + + RevengeHistoryManager.getInstance().requestHelp(player, killer, _type); + } +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeSharedTeleportToKiller.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeSharedTeleportToKiller.java new file mode 100644 index 0000000000..98986354e1 --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeSharedTeleportToKiller.java @@ -0,0 +1,52 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeSharedTeleportToKiller implements IClientIncomingPacket +{ + private String _victimName; + private String _killerName; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + _victimName = packet.readString(); + _killerName = packet.readString(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + RevengeHistoryManager.getInstance().teleportToSharedKiller(player, _victimName, _killerName); + } +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeTeleportToKiller.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeTeleportToKiller.java new file mode 100644 index 0000000000..212e01abb9 --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/revenge/RequestExPvpBookShareRevengeTeleportToKiller.java @@ -0,0 +1,57 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.clientpackets.revenge; + +import org.l2jmobius.commons.network.PacketReader; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket; + +/** + * @author Mobius + */ +public class RequestExPvpBookShareRevengeTeleportToKiller implements IClientIncomingPacket +{ + private String _victimName; + private String _killerName; + + @Override + public boolean read(GameClient client, PacketReader packet) + { + _victimName = packet.readString(); + _killerName = packet.readString(); + return true; + } + + @Override + public void run(GameClient client) + { + final Player player = client.getPlayer(); + if (player == null) + { + return; + } + + if (!_victimName.equals(player.getName())) + { + return; + } + + RevengeHistoryManager.getInstance().teleportToKiller(player, _killerName); + } +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeKillerLocation.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeKillerLocation.java new file mode 100644 index 0000000000..f6c9bd9791 --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeKillerLocation.java @@ -0,0 +1,46 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.serverpackets.revenge; + +import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.network.OutgoingPackets; +import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; + +/** + * @author Mobius + */ +public class ExPvpBookShareRevengeKillerLocation implements IClientOutgoingPacket +{ + private final Player _player; + + public ExPvpBookShareRevengeKillerLocation(Player player) + { + _player = player; + } + + @Override + public boolean write(PacketWriter packet) + { + OutgoingPackets.EX_PVPBOOK_SHARE_REVENGE_KILLER_LOCATION.writeId(packet); + packet.writeString(_player.getName()); + packet.writeD(_player.getX()); + packet.writeD(_player.getY()); + packet.writeD(_player.getZ()); + return true; + } +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeList.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeList.java new file mode 100644 index 0000000000..58615d42b0 --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeList.java @@ -0,0 +1,83 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.serverpackets.revenge; + +import java.util.Collection; + +import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.instancemanager.RevengeHistoryManager; +import org.l2jmobius.gameserver.model.World; +import org.l2jmobius.gameserver.model.actor.Player; +import org.l2jmobius.gameserver.model.holders.RevengeHistoryHolder; +import org.l2jmobius.gameserver.network.OutgoingPackets; +import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; + +/** + * @author Mobius + */ +public class ExPvpBookShareRevengeList implements IClientOutgoingPacket +{ + private final Collection _history; + + public ExPvpBookShareRevengeList(Player player) + { + _history = RevengeHistoryManager.getInstance().getHistory(player); + } + + @Override + public boolean write(PacketWriter packet) + { + OutgoingPackets.EX_PVPBOOK_SHARE_REVENGE_LIST.writeId(packet); + if (_history == null) + { + packet.writeC(1); // CurrentPage + packet.writeC(1); // MaxPage + packet.writeD(0); + } + else + { + packet.writeC(1); // CurrentPage + packet.writeC(1); // MaxPage + packet.writeD(_history.size()); + for (RevengeHistoryHolder holder : _history) + { + packet.writeD(holder.getType().ordinal()); // ShareType (2 - help request, 1 - revenge, 0 - both) + packet.writeD((int) (holder.getKillTime() / 1000)); // KilledTime + packet.writeD(holder.getShowLocationRemaining()); // ShowKillerCount + packet.writeD(holder.getTeleportRemaining()); // TeleportKillerCount + packet.writeD(holder.getSharedTeleportRemaining()); // SharedTeleportKillerCount + packet.writeD(0); // KilledUserDBID + packet.writeString(holder.getVictimName()); // KilledUserName + packet.writeString(holder.getVictimClanName()); // KilledUserPledgeName + packet.writeD(holder.getVictimLevel()); // KilledUserLevel + packet.writeD(holder.getVictimRaceId()); // KilledUserRace + packet.writeD(holder.getVictimClassId()); // KilledUserClass + packet.writeD(0); // KillUserDBID + packet.writeString(holder.getKillerName()); // KillUserName + packet.writeString(holder.getKillerClanName()); // KillUserPledgeName + packet.writeD(holder.getKillerLevel()); // KillUserLevel + packet.writeD(holder.getKillerRaceId()); // KillUserRace + packet.writeD(holder.getKillerClassId()); // KillUserClass + Player killer = World.getInstance().getPlayer(holder.getKillerName()); + packet.writeD((killer != null) && killer.isOnline() ? 2 : 0); // KillUserOnline (2 - online, 0 - offline) + packet.writeD(0); // KillUserKarma + packet.writeD((int) (holder.getShareTime() / 1000)); // nSharedTime + } + } + return true; + } +} diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeNewRevengeInfo.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeNewRevengeInfo.java new file mode 100644 index 0000000000..fa5336bfce --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/revenge/ExPvpBookShareRevengeNewRevengeInfo.java @@ -0,0 +1,49 @@ +/* + * This file is part of the L2J Mobius project. + * + * 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 org.l2jmobius.gameserver.network.serverpackets.revenge; + +import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.enums.RevengeType; +import org.l2jmobius.gameserver.network.OutgoingPackets; +import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; + +/** + * @author Mobius + */ +public class ExPvpBookShareRevengeNewRevengeInfo implements IClientOutgoingPacket +{ + private final String _victimName; + private final String _killerName; + private final RevengeType _type; + + public ExPvpBookShareRevengeNewRevengeInfo(String victimName, String killerName, RevengeType type) + { + _victimName = victimName; + _killerName = killerName; + _type = type; + } + + @Override + public boolean write(PacketWriter packet) + { + OutgoingPackets.EX_PVPBOOK_SHARE_REVENGE_NEW_REVENGEINFO.writeId(packet); + packet.writeD(_type.ordinal()); + packet.writeString(_victimName); + packet.writeString(_killerName); + return true; + } +} \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.2_Vanguard/readme.txt b/L2J_Mobius_Essence_6.2_Vanguard/readme.txt index 8721488638..5b04044732 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/readme.txt +++ b/L2J_Mobius_Essence_6.2_Vanguard/readme.txt @@ -137,6 +137,7 @@ Sylph: https://eu.4game.com/patchnotes/lineage2essence/281/ Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/ -Resurrection with payment -Frost Lord castle +-Revenge system Battle Chronicle: https://eu.4game.com/patchnotes/lineage2essence/353/ -New henna pattern potential system