Resurrection with payment.

Contributed by Index.
This commit is contained in:
MobiusDevelopment
2022-06-26 02:34:08 +00:00
parent 0500945790
commit 198be02ca5
24 changed files with 1345 additions and 9 deletions

View File

@@ -46,6 +46,74 @@ MpRegenMultiplier = 100
CpRegenMultiplier = 100 CpRegenMultiplier = 100
# ---------------------------------------------------------------------------
# Die recovery by payment
# ---------------------------------------------------------------------------
# Enable die recovery.
# Default: True
EnabledResurrectByPay = True
# Total number of free resurrections per day.
# Default: 2
MaxFreeResurrectionsByDay = 2
# Upper window resurrect item ID.
# Default: 91663 - L-Coin / MAKE CLIENT CHANGES!
FirstResurrectItemID = 91663
# List of for first case.
# level : times , count , restoration percent / times , count , percent;
# level : times , count , restoration percent / times , count , percent;
# the "\"indicates new line,
# NO FREE SPACES!
# Default: 60:3,1,100.0/4,2,100.0/5,3,100.0;\
# 75:3,1,100.0/4,3,100.0/5,4,100.0;\
# 79:3,2,100.0/4,5,100.0/5,10,100.0;\
# 81:3,5,100.0/4,10,100.0/5,15,100.0;\
# 84:3,15,100.0/4,20,100.0/5,25,100.0;\
# 86:3,20,100.0/4,40,100.0/5,80,100.0;\
# 88:3,25,100.0/4,50,100.0/5,100,100.0;\
# 90:3,25,100.0/4,50,100.0/5,100,100.0;
FirstResurrectList = 60:3,1,100.0/4,2,100.0/5,3,100.0;\
75:3,1,100.0/4,3,100.0/5,4,100.0;\
79:3,2,100.0/4,5,100.0/5,10,100.0;\
81:3,5,100.0/4,10,100.0/5,15,100.0;\
84:3,15,100.0/4,20,100.0/5,25,100.0;\
86:3,20,100.0/4,40,100.0/5,80,100.0;\
88:3,25,100.0/4,50,100.0/5,100,100.0;\
90:3,25,100.0/4,50,100.0/5,100,100.0;
# Lowest window resurrect item ID.
# Default: 57 - Adena / MAKE CLIENT CHANGES!
SecondResurrectItemID = 57
# List of for second case.
# level : times , count , restoration percent / times , count , percent;
# level : times , count , restoration percent / times , count , percent;
# the "\"indicates new line,
# NO FREE SPACES!
# Default:
# 60:3,5000,90.0/4,5000,80.0/5,5000,80.0/6,5000,70.0/7,5000,70.0/8,5000,60.0/9,5000,50.0;\
# 75:3,10000,90.0/4,10000,80.0/5,10000,80.0/6,10000,70.0/7,10000,70.0/8,10000,60.0/9,10000,50.0;\
# 79:3,20000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
# 81:3,30000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
# 84:3,60000,90.0/4,60000,80.0/5,60000,80.0/6,60000,70.0/7,60000,70.0/8,60000,60.0/9,60000,50.0;\
# 86:3,125000,90.0/4,125000,80.0/5,125000,80.0/6,125000,70.0/7,125000,70.0/8,125000,60.0/9,125000,50.0;\
# 88:3,240000,90.0/4,240000,80.0/5,240000,80.0/6,240000,70.0/7,240000,70.0/8,240000,60.0/9,240000,50.0;\
# 90:3,400000,90.0/4,400000,80.0/5,400000,80.0/6,400000,70.0/7,400000,70.0/8,400000,60.0/9,400000,50.0;
SecondResurrectList = 60:3,5000,90.0/4,5000,80.0/5,5000,80.0/6,5000,70.0/7,5000,70.0/8,5000,60.0/9,5000,50.0;\
75:3,10000,90.0/4,10000,80.0/5,10000,80.0/6,10000,70.0/7,10000,70.0/8,10000,60.0/9,10000,50.0;\
79:3,20000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
81:3,30000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
84:3,60000,90.0/4,60000,80.0/5,60000,80.0/6,60000,70.0/7,60000,70.0/8,60000,60.0/9,60000,50.0;\
86:3,125000,90.0/4,125000,80.0/5,125000,80.0/6,125000,70.0/7,125000,70.0/8,125000,60.0/9,125000,50.0;\
88:3,240000,90.0/4,240000,80.0/5,240000,80.0/6,240000,70.0/7,240000,70.0/8,240000,60.0/9,240000,50.0;\
90:3,400000,90.0/4,400000,80.0/5,400000,80.0/6,400000,70.0/7,400000,70.0/8,400000,60.0/9,400000,50.0;
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Skills & Effects # Skills & Effects
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@@ -44,6 +44,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -65,6 +66,7 @@ import org.l2jmobius.gameserver.enums.GeoType;
import org.l2jmobius.gameserver.enums.IllegalActionPunishmentType; import org.l2jmobius.gameserver.enums.IllegalActionPunishmentType;
import org.l2jmobius.gameserver.model.Location; import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.ResurrectByPaymentHolder;
import org.l2jmobius.gameserver.util.FloodProtectorConfig; import org.l2jmobius.gameserver.util.FloodProtectorConfig;
import org.l2jmobius.gameserver.util.Util; import org.l2jmobius.gameserver.util.Util;
@@ -890,6 +892,12 @@ public class Config
public static int MAX_CONNECTION_PER_IP; public static int MAX_CONNECTION_PER_IP;
public static boolean ENABLE_CMD_LINE_LOGIN; public static boolean ENABLE_CMD_LINE_LOGIN;
public static boolean ONLY_CMD_LINE_LOGIN; public static boolean ONLY_CMD_LINE_LOGIN;
public static boolean RESURRECT_BY_PAYMENT_ENABLED;
public static int RESURRECT_BY_PAYMENT_MAX_FREE_TIMES;
public static int RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM;
public static Map<Integer, Map<Integer, ResurrectByPaymentHolder>> RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES;
public static int RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM;
public static Map<Integer, Map<Integer, ResurrectByPaymentHolder>> RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES;
// Magic Lamp // Magic Lamp
public static boolean ENABLE_MAGIC_LAMP; public static boolean ENABLE_MAGIC_LAMP;
@@ -1654,6 +1662,93 @@ public class Config
HP_REGEN_MULTIPLIER = characterConfig.getDouble("HpRegenMultiplier", 100) / 100; HP_REGEN_MULTIPLIER = characterConfig.getDouble("HpRegenMultiplier", 100) / 100;
MP_REGEN_MULTIPLIER = characterConfig.getDouble("MpRegenMultiplier", 100) / 100; MP_REGEN_MULTIPLIER = characterConfig.getDouble("MpRegenMultiplier", 100) / 100;
CP_REGEN_MULTIPLIER = characterConfig.getDouble("CpRegenMultiplier", 100) / 100; CP_REGEN_MULTIPLIER = characterConfig.getDouble("CpRegenMultiplier", 100) / 100;
RESURRECT_BY_PAYMENT_ENABLED = characterConfig.getBoolean("EnabledResurrectByPay", true);
if (RESURRECT_BY_PAYMENT_ENABLED)
{
Map<Integer, ResurrectByPaymentHolder> RESURRECT_DATA = new TreeMap<>();
RESURRECT_BY_PAYMENT_MAX_FREE_TIMES = characterConfig.getInt("MaxFreeResurrectionsByDay", 0);
RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM = characterConfig.getInt("FirstResurrectItemID", 0);
final String[] firstPaymentSplit = characterConfig.getString("FirstResurrectList", "").split(";");
RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES = new TreeMap<>();
for (String timeData : firstPaymentSplit)
{
RESURRECT_DATA = new TreeMap<>();
final String[] timeSplit = timeData.split(":");
if (timeSplit.length != 2)
{
LOGGER.warning("[FirstResurrectList]: invalid config property -> Level data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
final String[] dataSplit = timeSplit[1].split("/");
for (String data : dataSplit)
{
while (data.contains(" "))
{
data = data.replace(" ", "");
}
final String[] values = data.split(",");
if (values.length < 3)
{
LOGGER.warning("[FirstResurrectList]: invalid config property -> Times data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
try
{
final int time = Integer.parseInt(values[0]);
final int count = Integer.parseInt(values[1]);
final double percent = Double.parseDouble(values[2]);
RESURRECT_DATA.put(time, new ResurrectByPaymentHolder(time, count, percent));
}
catch (Exception e)
{
LOGGER.warning("[FirstResurrectList]: invalid config property -> Times data cannot be parsed. Look on exception " + timeSplit[0]);
e.printStackTrace();
}
}
RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.put(Integer.parseInt(timeSplit[0]), RESURRECT_DATA);
}
final String[] secondPaymentSplit = characterConfig.getString("SecondResurrectList", "").split(";");
RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES = new TreeMap<>();
for (String timeData : secondPaymentSplit)
{
RESURRECT_DATA = new TreeMap<>();
final String[] timeSplit = timeData.split(":");
if (timeSplit.length != 2)
{
LOGGER.warning("[SecondResurrectList]: invalid config property -> Level data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
final String[] dataSplit = timeSplit[1].split("/");
for (String data : dataSplit)
{
while (data.contains(" "))
{
data = data.replace(" ", "");
}
final String[] values = data.split(",");
if (values.length < 3)
{
LOGGER.warning("[SecondResurrectList]: invalid config property -> Times data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
try
{
final int time = Integer.parseInt(values[0]);
final int count = Integer.parseInt(values[1]);
final double percent = Double.parseDouble(values[2]);
RESURRECT_DATA.put(time, new ResurrectByPaymentHolder(time, count, percent));
}
catch (Exception e)
{
LOGGER.warning("[SecondResurrectList]: invalid config property -> Times data cannot be parsed. Look on exception " + timeSplit[0]);
e.printStackTrace();
}
}
RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.put(Integer.parseInt(timeSplit[0]), RESURRECT_DATA);
}
RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM = characterConfig.getInt("SecondResurrectItemID", 0);
}
ENABLE_MODIFY_SKILL_DURATION = characterConfig.getBoolean("EnableModifySkillDuration", false); ENABLE_MODIFY_SKILL_DURATION = characterConfig.getBoolean("EnableModifySkillDuration", false);
if (ENABLE_MODIFY_SKILL_DURATION) if (ENABLE_MODIFY_SKILL_DURATION)
{ {

View File

@@ -140,6 +140,7 @@ public class DailyTaskManager
resetDailyMissionRewards(); resetDailyMissionRewards();
resetAttendanceRewards(); resetAttendanceRewards();
resetVip(); resetVip();
resetResurrectionByPayment();
} }
private void onSave() private void onSave()
@@ -667,6 +668,32 @@ public class DailyTaskManager
LOGGER.info("LimitShopData has been resetted."); LOGGER.info("LimitShopData has been resetted.");
} }
private void resetResurrectionByPayment()
{
// Update data for offline players.
try (Connection con = DatabaseFactory.getConnection())
{
try (PreparedStatement ps = con.prepareStatement("DELETE FROM character_variables WHERE var=?"))
{
ps.setString(1, PlayerVariables.RESURRECT_BY_PAYMENT_COUNT);
ps.execute();
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Could not reset payment resurrection count for players: " + e);
}
// Update data for online players.
for (Player player : World.getInstance().getPlayers())
{
player.getVariables().remove(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT);
player.getVariables().storeMe();
}
LOGGER.info("Daily payment resurrection count for player has been resetted.");
}
public static DailyTaskManager getInstance() public static DailyTaskManager getInstance()
{ {
return SingletonHolder.INSTANCE; return SingletonHolder.INSTANCE;

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.model.holders;
/**
* @author Index
*/
public class ResurrectByPaymentHolder
{
private final int _time;
private final int _amount;
private final double _resurrectPercent;
public ResurrectByPaymentHolder(int time, int amount, double percent)
{
_time = time;
_amount = amount;
_resurrectPercent = percent;
}
public int getTime()
{
return _time;
}
public int getAmount()
{
return _amount;
}
public double getResurrectPercent()
{
return _resurrectPercent;
}
}

View File

@@ -79,6 +79,7 @@ public class PlayerVariables extends AbstractVariables
public static final String STAT_INT = "STAT_INT"; public static final String STAT_INT = "STAT_INT";
public static final String STAT_WIT = "STAT_WIT"; public static final String STAT_WIT = "STAT_WIT";
public static final String STAT_MEN = "STAT_MEN"; public static final String STAT_MEN = "STAT_MEN";
public static final String RESURRECT_BY_PAYMENT_COUNT = "RESURRECT_BY_PAYMENT_COUNT";
public static final String CLAN_JOIN_TIME = "CLAN_JOIN_TIME"; public static final String CLAN_JOIN_TIME = "CLAN_JOIN_TIME";
private final int _objectId; private final int _objectId;

View File

@@ -16,6 +16,11 @@
*/ */
package org.l2jmobius.gameserver.network.clientpackets; package org.l2jmobius.gameserver.network.clientpackets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader; import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.threads.ThreadPool; import org.l2jmobius.commons.threads.ThreadPool;
import org.l2jmobius.gameserver.data.xml.ClanHallData; import org.l2jmobius.gameserver.data.xml.ClanHallData;
@@ -29,7 +34,9 @@ import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.EventType;
import org.l2jmobius.gameserver.model.events.listeners.AbstractEventListener; import org.l2jmobius.gameserver.model.events.listeners.AbstractEventListener;
import org.l2jmobius.gameserver.model.holders.ResurrectByPaymentHolder;
import org.l2jmobius.gameserver.model.instancezone.Instance; import org.l2jmobius.gameserver.model.instancezone.Instance;
import org.l2jmobius.gameserver.model.item.instance.Item;
import org.l2jmobius.gameserver.model.quest.Event; import org.l2jmobius.gameserver.model.quest.Event;
import org.l2jmobius.gameserver.model.residences.ClanHall; import org.l2jmobius.gameserver.model.residences.ClanHall;
import org.l2jmobius.gameserver.model.residences.ResidenceFunctionType; import org.l2jmobius.gameserver.model.residences.ResidenceFunctionType;
@@ -38,8 +45,11 @@ import org.l2jmobius.gameserver.model.siege.Castle.CastleFunction;
import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Fort;
import org.l2jmobius.gameserver.model.siege.Fort.FortFunction; import org.l2jmobius.gameserver.model.siege.Fort.FortFunction;
import org.l2jmobius.gameserver.model.skill.CommonSkill; import org.l2jmobius.gameserver.model.skill.CommonSkill;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
import org.l2jmobius.gameserver.network.GameClient; import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.PacketLogger; import org.l2jmobius.gameserver.network.PacketLogger;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/** /**
* @version $Revision: 1.7.2.3.2.6 $ $Date: 2005/03/27 15:29:30 $ * @version $Revision: 1.7.2.3.2.6 $ $Date: 2005/03/27 15:29:30 $
@@ -48,11 +58,18 @@ public class RequestRestartPoint implements IClientIncomingPacket
{ {
protected int _requestedPointType; protected int _requestedPointType;
protected boolean _continuation; protected boolean _continuation;
protected int _resItemID;
protected int _resCount;
@Override @Override
public boolean read(GameClient client, PacketReader packet) public boolean read(GameClient client, PacketReader packet)
{ {
_requestedPointType = packet.readD(); _requestedPointType = packet.readD();
if (packet.getReadableBytes() != 0)
{
_resItemID = packet.readD();
_resCount = packet.readD();
}
return true; return true;
} }
@@ -270,6 +287,80 @@ public class RequestRestartPoint implements IClientIncomingPacket
{ {
break; break;
} }
case 9:
{
if (Config.RESURRECT_BY_PAYMENT_ENABLED)
{
if (!player.isDead())
{
break;
}
final int originalValue = player.getVariables().getInt(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, 0);
if (originalValue < Config.RESURRECT_BY_PAYMENT_MAX_FREE_TIMES)
{
player.getVariables().set(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, originalValue + 1);
player.doRevive(100.0);
loc = MapRegionManager.getInstance().getTeleToLocation(player, TeleportWhereType.TOWN);
player.teleToLocation(loc, true, instance);
break;
}
final int firstID = Config.RESURRECT_BY_PAYMENT_ENABLED ? Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM : 91663;
final int secondID = Config.RESURRECT_BY_PAYMENT_ENABLED ? Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM : 57;
Map<Integer, Map<Integer, ResurrectByPaymentHolder>> resMAP = null;
Item item = null;
if (_resItemID == firstID)
{
resMAP = Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES;
item = player.getInventory().getItemByItemId(Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM);
}
else if (_resItemID == secondID)
{
resMAP = Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES;
item = player.getInventory().getItemByItemId(Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM);
}
if ((resMAP == null) || (item == null))
{
break;
}
final List<Integer> levelList = new ArrayList<>(resMAP.keySet());
for (int level : levelList)
{
if ((player.getLevel() >= level) && (levelList.lastIndexOf(level) != (levelList.size() - 1)))
{
continue;
}
int maxResTime;
try
{
maxResTime = resMAP.get(level).keySet().stream().max(Integer::compareTo).get();
}
catch (Exception e)
{
player.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
e.printStackTrace();
return;
}
final int getValue = maxResTime <= originalValue ? maxResTime : originalValue + 1;
final ResurrectByPaymentHolder rbph = resMAP.get(level).get(getValue);
if (item.getCount() < rbph.getAmount())
{
return;
}
player.getVariables().set(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, originalValue + 1);
player.destroyItem("item revive", item, rbph.getAmount(), player, true);
player.doRevive(rbph.getResurrectPercent());
loc = MapRegionManager.getInstance().getTeleToLocation(player, TeleportWhereType.TOWN);
player.teleToLocation(loc, true, instance);
break;
}
}
}
case 27: // to jail case 27: // to jail
{ {
if (!player.isJailed()) if (!player.isJailed())

View File

@@ -16,16 +16,23 @@
*/ */
package org.l2jmobius.gameserver.network.serverpackets; package org.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketWriter; import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.instancemanager.CastleManager;
import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.instancemanager.FortManager;
import org.l2jmobius.gameserver.model.SiegeClan; import org.l2jmobius.gameserver.model.SiegeClan;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.model.holders.ResurrectByPaymentHolder;
import org.l2jmobius.gameserver.model.siege.Castle; import org.l2jmobius.gameserver.model.siege.Castle;
import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Fort;
import org.l2jmobius.gameserver.model.skill.BuffInfo; import org.l2jmobius.gameserver.model.skill.BuffInfo;
import org.l2jmobius.gameserver.model.skill.CommonSkill; import org.l2jmobius.gameserver.model.skill.CommonSkill;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
import org.l2jmobius.gameserver.network.OutgoingPackets; import org.l2jmobius.gameserver.network.OutgoingPackets;
/** /**
@@ -37,6 +44,7 @@ public class Die implements IClientOutgoingPacket
private final boolean _isSweepable; private final boolean _isSweepable;
private int _flags = 0; private int _flags = 0;
private int _delayFeather = 0; private int _delayFeather = 0;
private Player _player;
public Die(Creature creature) public Die(Creature creature)
{ {
@@ -44,7 +52,8 @@ public class Die implements IClientOutgoingPacket
_isSweepable = creature.isAttackable() && creature.isSweepActive(); _isSweepable = creature.isAttackable() && creature.isSweepActive();
if (creature.isPlayer()) if (creature.isPlayer())
{ {
final Clan clan = creature.getActingPlayer().getClan(); _player = creature.getActingPlayer();
final Clan clan = _player.getClan();
boolean isInCastleDefense = false; boolean isInCastleDefense = false;
boolean isInFortDefense = false; boolean isInFortDefense = false;
SiegeClan siegeClan = null; SiegeClan siegeClan = null;
@@ -108,8 +117,113 @@ public class Die implements IClientOutgoingPacket
packet.writeD(_delayFeather); // Feather item time. packet.writeD(_delayFeather); // Feather item time.
packet.writeC(0); // Hide die animation. packet.writeC(0); // Hide die animation.
packet.writeD(0); packet.writeD(0);
packet.writeD(0); if ((_player != null) && Config.RESURRECT_BY_PAYMENT_ENABLED)
{
int resurrectTimes = _player.getVariables().getInt(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, 0) + 1;
int originalValue = resurrectTimes - 1;
if (originalValue < Config.RESURRECT_BY_PAYMENT_MAX_FREE_TIMES)
{
packet.writeD(Config.RESURRECT_BY_PAYMENT_MAX_FREE_TIMES - originalValue); // free round resurrection
packet.writeD(0); // Adena resurrection
packet.writeD(0); // Adena count%
packet.writeD(0); // L-Coin resurrection
packet.writeD(0); // L-Coin count%
}
else
{
packet.writeD(0);
getValues(_player, packet, originalValue);
}
}
else
{
packet.writeD(1); // free round resurrection
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
}
packet.writeD(0); packet.writeD(0);
return true; return true;
} }
private void getValues(Player player, PacketWriter packet, int originalValue)
{
if ((Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES == null) || (Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES == null))
{
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
return;
}
final List<Integer> levelListFirst = new ArrayList<>(Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.keySet());
final List<Integer> levelListSecond = new ArrayList<>(Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.keySet());
for (int level : levelListSecond)
{
if (Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.isEmpty())
{
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
break;
}
if ((player.getLevel() >= level) && (levelListSecond.lastIndexOf(level) != (levelListSecond.size() - 1)))
{
continue;
}
int maxResTime;
try
{
maxResTime = Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.get(level).keySet().stream().max(Integer::compareTo).get();
}
catch (Exception e)
{
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
return;
}
int getValue = maxResTime <= originalValue ? maxResTime : originalValue + 1;
ResurrectByPaymentHolder rbph = Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.get(level).get(getValue);
packet.writeD(rbph.getAmount()); // Adena resurrection
packet.writeD(Math.toIntExact(Math.round(rbph.getResurrectPercent()))); // Adena count%
break;
}
for (int level : levelListFirst)
{
if (Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.isEmpty())
{
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
break;
}
if ((player.getLevel() >= level) && (levelListFirst.lastIndexOf(level) != (levelListFirst.size() - 1)))
{
continue;
}
int maxResTime;
try
{
maxResTime = Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.get(level).keySet().stream().max(Integer::compareTo).get();
}
catch (Exception e)
{
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
return;
}
final int getValue = maxResTime <= originalValue ? maxResTime : originalValue + 1;
ResurrectByPaymentHolder rbph = Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.get(level).get(getValue);
packet.writeD(rbph.getAmount()); // L-Coin resurrection
packet.writeD(Math.toIntExact(Math.round(rbph.getResurrectPercent()))); // L-Coin count%
break;
}
}
} }

View File

@@ -131,7 +131,8 @@ Sylph: https://eu.4game.com/patchnotes/lineage2essence/281/
-Pledge donation system -Pledge donation system
Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/ Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/
-Client support -Resurrection with payment
-Frost Lord castle
Customs: Customs:
-Newbie Helper NPC location info -Newbie Helper NPC location info

View File

@@ -46,6 +46,74 @@ MpRegenMultiplier = 100
CpRegenMultiplier = 100 CpRegenMultiplier = 100
# ---------------------------------------------------------------------------
# Die recovery by payment
# ---------------------------------------------------------------------------
# Enable die recovery.
# Default: True
EnabledResurrectByPay = True
# Total number of free resurrections per day.
# Default: 2
MaxFreeResurrectionsByDay = 2
# Upper window resurrect item ID.
# Default: 91663 - L-Coin / MAKE CLIENT CHANGES!
FirstResurrectItemID = 91663
# List of for first case.
# level : times , count , restoration percent / times , count , percent;
# level : times , count , restoration percent / times , count , percent;
# the "\"indicates new line,
# NO FREE SPACES!
# Default: 60:3,1,100.0/4,2,100.0/5,3,100.0;\
# 75:3,1,100.0/4,3,100.0/5,4,100.0;\
# 79:3,2,100.0/4,5,100.0/5,10,100.0;\
# 81:3,5,100.0/4,10,100.0/5,15,100.0;\
# 84:3,15,100.0/4,20,100.0/5,25,100.0;\
# 86:3,20,100.0/4,40,100.0/5,80,100.0;\
# 88:3,25,100.0/4,50,100.0/5,100,100.0;\
# 90:3,25,100.0/4,50,100.0/5,100,100.0;
FirstResurrectList = 60:3,1,100.0/4,2,100.0/5,3,100.0;\
75:3,1,100.0/4,3,100.0/5,4,100.0;\
79:3,2,100.0/4,5,100.0/5,10,100.0;\
81:3,5,100.0/4,10,100.0/5,15,100.0;\
84:3,15,100.0/4,20,100.0/5,25,100.0;\
86:3,20,100.0/4,40,100.0/5,80,100.0;\
88:3,25,100.0/4,50,100.0/5,100,100.0;\
90:3,25,100.0/4,50,100.0/5,100,100.0;
# Lowest window resurrect item ID.
# Default: 57 - Adena / MAKE CLIENT CHANGES!
SecondResurrectItemID = 57
# List of for second case.
# level : times , count , restoration percent / times , count , percent;
# level : times , count , restoration percent / times , count , percent;
# the "\"indicates new line,
# NO FREE SPACES!
# Default:
# 60:3,5000,90.0/4,5000,80.0/5,5000,80.0/6,5000,70.0/7,5000,70.0/8,5000,60.0/9,5000,50.0;\
# 75:3,10000,90.0/4,10000,80.0/5,10000,80.0/6,10000,70.0/7,10000,70.0/8,10000,60.0/9,10000,50.0;\
# 79:3,20000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
# 81:3,30000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
# 84:3,60000,90.0/4,60000,80.0/5,60000,80.0/6,60000,70.0/7,60000,70.0/8,60000,60.0/9,60000,50.0;\
# 86:3,125000,90.0/4,125000,80.0/5,125000,80.0/6,125000,70.0/7,125000,70.0/8,125000,60.0/9,125000,50.0;\
# 88:3,240000,90.0/4,240000,80.0/5,240000,80.0/6,240000,70.0/7,240000,70.0/8,240000,60.0/9,240000,50.0;\
# 90:3,400000,90.0/4,400000,80.0/5,400000,80.0/6,400000,70.0/7,400000,70.0/8,400000,60.0/9,400000,50.0;
SecondResurrectList = 60:3,5000,90.0/4,5000,80.0/5,5000,80.0/6,5000,70.0/7,5000,70.0/8,5000,60.0/9,5000,50.0;\
75:3,10000,90.0/4,10000,80.0/5,10000,80.0/6,10000,70.0/7,10000,70.0/8,10000,60.0/9,10000,50.0;\
79:3,20000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
81:3,30000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
84:3,60000,90.0/4,60000,80.0/5,60000,80.0/6,60000,70.0/7,60000,70.0/8,60000,60.0/9,60000,50.0;\
86:3,125000,90.0/4,125000,80.0/5,125000,80.0/6,125000,70.0/7,125000,70.0/8,125000,60.0/9,125000,50.0;\
88:3,240000,90.0/4,240000,80.0/5,240000,80.0/6,240000,70.0/7,240000,70.0/8,240000,60.0/9,240000,50.0;\
90:3,400000,90.0/4,400000,80.0/5,400000,80.0/6,400000,70.0/7,400000,70.0/8,400000,60.0/9,400000,50.0;
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Skills & Effects # Skills & Effects
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@@ -44,6 +44,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -65,6 +66,7 @@ import org.l2jmobius.gameserver.enums.GeoType;
import org.l2jmobius.gameserver.enums.IllegalActionPunishmentType; import org.l2jmobius.gameserver.enums.IllegalActionPunishmentType;
import org.l2jmobius.gameserver.model.Location; import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.ResurrectByPaymentHolder;
import org.l2jmobius.gameserver.util.FloodProtectorConfig; import org.l2jmobius.gameserver.util.FloodProtectorConfig;
import org.l2jmobius.gameserver.util.Util; import org.l2jmobius.gameserver.util.Util;
@@ -891,6 +893,12 @@ public class Config
public static int MAX_CONNECTION_PER_IP; public static int MAX_CONNECTION_PER_IP;
public static boolean ENABLE_CMD_LINE_LOGIN; public static boolean ENABLE_CMD_LINE_LOGIN;
public static boolean ONLY_CMD_LINE_LOGIN; public static boolean ONLY_CMD_LINE_LOGIN;
public static boolean RESURRECT_BY_PAYMENT_ENABLED;
public static int RESURRECT_BY_PAYMENT_MAX_FREE_TIMES;
public static int RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM;
public static Map<Integer, Map<Integer, ResurrectByPaymentHolder>> RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES;
public static int RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM;
public static Map<Integer, Map<Integer, ResurrectByPaymentHolder>> RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES;
// Magic Lamp // Magic Lamp
public static boolean ENABLE_MAGIC_LAMP; public static boolean ENABLE_MAGIC_LAMP;
@@ -1661,6 +1669,93 @@ public class Config
HP_REGEN_MULTIPLIER = characterConfig.getDouble("HpRegenMultiplier", 100) / 100; HP_REGEN_MULTIPLIER = characterConfig.getDouble("HpRegenMultiplier", 100) / 100;
MP_REGEN_MULTIPLIER = characterConfig.getDouble("MpRegenMultiplier", 100) / 100; MP_REGEN_MULTIPLIER = characterConfig.getDouble("MpRegenMultiplier", 100) / 100;
CP_REGEN_MULTIPLIER = characterConfig.getDouble("CpRegenMultiplier", 100) / 100; CP_REGEN_MULTIPLIER = characterConfig.getDouble("CpRegenMultiplier", 100) / 100;
RESURRECT_BY_PAYMENT_ENABLED = characterConfig.getBoolean("EnabledResurrectByPay", true);
if (RESURRECT_BY_PAYMENT_ENABLED)
{
Map<Integer, ResurrectByPaymentHolder> RESURRECT_DATA = new TreeMap<>();
RESURRECT_BY_PAYMENT_MAX_FREE_TIMES = characterConfig.getInt("MaxFreeResurrectionsByDay", 0);
RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM = characterConfig.getInt("FirstResurrectItemID", 0);
final String[] firstPaymentSplit = characterConfig.getString("FirstResurrectList", "").split(";");
RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES = new TreeMap<>();
for (String timeData : firstPaymentSplit)
{
RESURRECT_DATA = new TreeMap<>();
final String[] timeSplit = timeData.split(":");
if (timeSplit.length != 2)
{
LOGGER.warning("[FirstResurrectList]: invalid config property -> Level data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
final String[] dataSplit = timeSplit[1].split("/");
for (String data : dataSplit)
{
while (data.contains(" "))
{
data = data.replace(" ", "");
}
final String[] values = data.split(",");
if (values.length < 3)
{
LOGGER.warning("[FirstResurrectList]: invalid config property -> Times data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
try
{
final int time = Integer.parseInt(values[0]);
final int count = Integer.parseInt(values[1]);
final double percent = Double.parseDouble(values[2]);
RESURRECT_DATA.put(time, new ResurrectByPaymentHolder(time, count, percent));
}
catch (Exception e)
{
LOGGER.warning("[FirstResurrectList]: invalid config property -> Times data cannot be parsed. Look on exception " + timeSplit[0]);
e.printStackTrace();
}
}
RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.put(Integer.parseInt(timeSplit[0]), RESURRECT_DATA);
}
final String[] secondPaymentSplit = characterConfig.getString("SecondResurrectList", "").split(";");
RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES = new TreeMap<>();
for (String timeData : secondPaymentSplit)
{
RESURRECT_DATA = new TreeMap<>();
final String[] timeSplit = timeData.split(":");
if (timeSplit.length != 2)
{
LOGGER.warning("[SecondResurrectList]: invalid config property -> Level data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
final String[] dataSplit = timeSplit[1].split("/");
for (String data : dataSplit)
{
while (data.contains(" "))
{
data = data.replace(" ", "");
}
final String[] values = data.split(",");
if (values.length < 3)
{
LOGGER.warning("[SecondResurrectList]: invalid config property -> Times data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
try
{
final int time = Integer.parseInt(values[0]);
final int count = Integer.parseInt(values[1]);
final double percent = Double.parseDouble(values[2]);
RESURRECT_DATA.put(time, new ResurrectByPaymentHolder(time, count, percent));
}
catch (Exception e)
{
LOGGER.warning("[SecondResurrectList]: invalid config property -> Times data cannot be parsed. Look on exception " + timeSplit[0]);
e.printStackTrace();
}
}
RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.put(Integer.parseInt(timeSplit[0]), RESURRECT_DATA);
}
RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM = characterConfig.getInt("SecondResurrectItemID", 0);
}
ENABLE_MODIFY_SKILL_DURATION = characterConfig.getBoolean("EnableModifySkillDuration", false); ENABLE_MODIFY_SKILL_DURATION = characterConfig.getBoolean("EnableModifySkillDuration", false);
if (ENABLE_MODIFY_SKILL_DURATION) if (ENABLE_MODIFY_SKILL_DURATION)
{ {

View File

@@ -141,6 +141,7 @@ public class DailyTaskManager
resetDailyMissionRewards(); resetDailyMissionRewards();
resetAttendanceRewards(); resetAttendanceRewards();
resetVip(); resetVip();
resetResurrectionByPayment();
} }
private void onSave() private void onSave()
@@ -668,6 +669,32 @@ public class DailyTaskManager
LOGGER.info("LimitShopData has been resetted."); LOGGER.info("LimitShopData has been resetted.");
} }
private void resetResurrectionByPayment()
{
// Update data for offline players.
try (Connection con = DatabaseFactory.getConnection())
{
try (PreparedStatement ps = con.prepareStatement("DELETE FROM character_variables WHERE var=?"))
{
ps.setString(1, PlayerVariables.RESURRECT_BY_PAYMENT_COUNT);
ps.execute();
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Could not reset payment resurrection count for players: " + e);
}
// Update data for online players.
for (Player player : World.getInstance().getPlayers())
{
player.getVariables().remove(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT);
player.getVariables().storeMe();
}
LOGGER.info("Daily payment resurrection count for player has been resetted.");
}
private void resetDailyHennaPattern() private void resetDailyHennaPattern()
{ {
// Update data for offline players. // Update data for offline players.

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.model.holders;
/**
* @author Index
*/
public class ResurrectByPaymentHolder
{
private final int _time;
private final int _amount;
private final double _resurrectPercent;
public ResurrectByPaymentHolder(int time, int amount, double percent)
{
_time = time;
_amount = amount;
_resurrectPercent = percent;
}
public int getTime()
{
return _time;
}
public int getAmount()
{
return _amount;
}
public double getResurrectPercent()
{
return _resurrectPercent;
}
}

View File

@@ -79,6 +79,7 @@ public class PlayerVariables extends AbstractVariables
public static final String STAT_INT = "STAT_INT"; public static final String STAT_INT = "STAT_INT";
public static final String STAT_WIT = "STAT_WIT"; public static final String STAT_WIT = "STAT_WIT";
public static final String STAT_MEN = "STAT_MEN"; public static final String STAT_MEN = "STAT_MEN";
public static final String RESURRECT_BY_PAYMENT_COUNT = "RESURRECT_BY_PAYMENT_COUNT";
public static final String CLAN_JOIN_TIME = "CLAN_JOIN_TIME"; public static final String CLAN_JOIN_TIME = "CLAN_JOIN_TIME";
public static final String HENNA1_DURATION = "HENNA1_DURATION"; public static final String HENNA1_DURATION = "HENNA1_DURATION";
public static final String HENNA2_DURATION = "HENNA2_DURATION"; public static final String HENNA2_DURATION = "HENNA2_DURATION";

View File

@@ -16,6 +16,11 @@
*/ */
package org.l2jmobius.gameserver.network.clientpackets; package org.l2jmobius.gameserver.network.clientpackets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader; import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.threads.ThreadPool; import org.l2jmobius.commons.threads.ThreadPool;
import org.l2jmobius.gameserver.data.xml.ClanHallData; import org.l2jmobius.gameserver.data.xml.ClanHallData;
@@ -29,7 +34,9 @@ import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.EventType;
import org.l2jmobius.gameserver.model.events.listeners.AbstractEventListener; import org.l2jmobius.gameserver.model.events.listeners.AbstractEventListener;
import org.l2jmobius.gameserver.model.holders.ResurrectByPaymentHolder;
import org.l2jmobius.gameserver.model.instancezone.Instance; import org.l2jmobius.gameserver.model.instancezone.Instance;
import org.l2jmobius.gameserver.model.item.instance.Item;
import org.l2jmobius.gameserver.model.quest.Event; import org.l2jmobius.gameserver.model.quest.Event;
import org.l2jmobius.gameserver.model.residences.ClanHall; import org.l2jmobius.gameserver.model.residences.ClanHall;
import org.l2jmobius.gameserver.model.residences.ResidenceFunctionType; import org.l2jmobius.gameserver.model.residences.ResidenceFunctionType;
@@ -38,8 +45,11 @@ import org.l2jmobius.gameserver.model.siege.Castle.CastleFunction;
import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Fort;
import org.l2jmobius.gameserver.model.siege.Fort.FortFunction; import org.l2jmobius.gameserver.model.siege.Fort.FortFunction;
import org.l2jmobius.gameserver.model.skill.CommonSkill; import org.l2jmobius.gameserver.model.skill.CommonSkill;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
import org.l2jmobius.gameserver.network.GameClient; import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.PacketLogger; import org.l2jmobius.gameserver.network.PacketLogger;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/** /**
* @version $Revision: 1.7.2.3.2.6 $ $Date: 2005/03/27 15:29:30 $ * @version $Revision: 1.7.2.3.2.6 $ $Date: 2005/03/27 15:29:30 $
@@ -48,11 +58,18 @@ public class RequestRestartPoint implements IClientIncomingPacket
{ {
protected int _requestedPointType; protected int _requestedPointType;
protected boolean _continuation; protected boolean _continuation;
protected int _resItemID;
protected int _resCount;
@Override @Override
public boolean read(GameClient client, PacketReader packet) public boolean read(GameClient client, PacketReader packet)
{ {
_requestedPointType = packet.readD(); _requestedPointType = packet.readD();
if (packet.getReadableBytes() != 0)
{
_resItemID = packet.readD();
_resCount = packet.readD();
}
return true; return true;
} }
@@ -270,6 +287,80 @@ public class RequestRestartPoint implements IClientIncomingPacket
{ {
break; break;
} }
case 9:
{
if (Config.RESURRECT_BY_PAYMENT_ENABLED)
{
if (!player.isDead())
{
break;
}
final int originalValue = player.getVariables().getInt(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, 0);
if (originalValue < Config.RESURRECT_BY_PAYMENT_MAX_FREE_TIMES)
{
player.getVariables().set(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, originalValue + 1);
player.doRevive(100.0);
loc = MapRegionManager.getInstance().getTeleToLocation(player, TeleportWhereType.TOWN);
player.teleToLocation(loc, true, instance);
break;
}
final int firstID = Config.RESURRECT_BY_PAYMENT_ENABLED ? Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM : 91663;
final int secondID = Config.RESURRECT_BY_PAYMENT_ENABLED ? Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM : 57;
Map<Integer, Map<Integer, ResurrectByPaymentHolder>> resMAP = null;
Item item = null;
if (_resItemID == firstID)
{
resMAP = Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES;
item = player.getInventory().getItemByItemId(Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM);
}
else if (_resItemID == secondID)
{
resMAP = Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES;
item = player.getInventory().getItemByItemId(Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM);
}
if ((resMAP == null) || (item == null))
{
break;
}
final List<Integer> levelList = new ArrayList<>(resMAP.keySet());
for (int level : levelList)
{
if ((player.getLevel() >= level) && (levelList.lastIndexOf(level) != (levelList.size() - 1)))
{
continue;
}
int maxResTime;
try
{
maxResTime = resMAP.get(level).keySet().stream().max(Integer::compareTo).get();
}
catch (Exception e)
{
player.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
e.printStackTrace();
return;
}
final int getValue = maxResTime <= originalValue ? maxResTime : originalValue + 1;
final ResurrectByPaymentHolder rbph = resMAP.get(level).get(getValue);
if (item.getCount() < rbph.getAmount())
{
return;
}
player.getVariables().set(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, originalValue + 1);
player.destroyItem("item revive", item, rbph.getAmount(), player, true);
player.doRevive(rbph.getResurrectPercent());
loc = MapRegionManager.getInstance().getTeleToLocation(player, TeleportWhereType.TOWN);
player.teleToLocation(loc, true, instance);
break;
}
}
}
case 27: // to jail case 27: // to jail
{ {
if (!player.isJailed()) if (!player.isJailed())

View File

@@ -16,16 +16,23 @@
*/ */
package org.l2jmobius.gameserver.network.serverpackets; package org.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketWriter; import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.instancemanager.CastleManager;
import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.instancemanager.FortManager;
import org.l2jmobius.gameserver.model.SiegeClan; import org.l2jmobius.gameserver.model.SiegeClan;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.model.holders.ResurrectByPaymentHolder;
import org.l2jmobius.gameserver.model.siege.Castle; import org.l2jmobius.gameserver.model.siege.Castle;
import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Fort;
import org.l2jmobius.gameserver.model.skill.BuffInfo; import org.l2jmobius.gameserver.model.skill.BuffInfo;
import org.l2jmobius.gameserver.model.skill.CommonSkill; import org.l2jmobius.gameserver.model.skill.CommonSkill;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
import org.l2jmobius.gameserver.network.OutgoingPackets; import org.l2jmobius.gameserver.network.OutgoingPackets;
/** /**
@@ -37,6 +44,7 @@ public class Die implements IClientOutgoingPacket
private final boolean _isSweepable; private final boolean _isSweepable;
private int _flags = 1; // To nearest village. private int _flags = 1; // To nearest village.
private int _delayFeather = 0; private int _delayFeather = 0;
private Player _player;
public Die(Creature creature) public Die(Creature creature)
{ {
@@ -44,7 +52,8 @@ public class Die implements IClientOutgoingPacket
_isSweepable = creature.isAttackable() && creature.isSweepActive(); _isSweepable = creature.isAttackable() && creature.isSweepActive();
if (creature.isPlayer()) if (creature.isPlayer())
{ {
final Clan clan = creature.getActingPlayer().getClan(); _player = creature.getActingPlayer();
final Clan clan = _player.getClan();
boolean isInCastleDefense = false; boolean isInCastleDefense = false;
boolean isInFortDefense = false; boolean isInFortDefense = false;
SiegeClan siegeClan = null; SiegeClan siegeClan = null;
@@ -108,8 +117,113 @@ public class Die implements IClientOutgoingPacket
packet.writeD(_delayFeather); // Feather item time. packet.writeD(_delayFeather); // Feather item time.
packet.writeC(0); // Hide die animation. packet.writeC(0); // Hide die animation.
packet.writeD(0); packet.writeD(0);
packet.writeD(0); if ((_player != null) && Config.RESURRECT_BY_PAYMENT_ENABLED)
{
int resurrectTimes = _player.getVariables().getInt(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, 0) + 1;
int originalValue = resurrectTimes - 1;
if (originalValue < Config.RESURRECT_BY_PAYMENT_MAX_FREE_TIMES)
{
packet.writeD(Config.RESURRECT_BY_PAYMENT_MAX_FREE_TIMES - originalValue); // free round resurrection
packet.writeD(0); // Adena resurrection
packet.writeD(0); // Adena count%
packet.writeD(0); // L-Coin resurrection
packet.writeD(0); // L-Coin count%
}
else
{
packet.writeD(0);
getValues(_player, packet, originalValue);
}
}
else
{
packet.writeD(1); // free round resurrection
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
}
packet.writeD(0); packet.writeD(0);
return true; return true;
} }
private void getValues(Player player, PacketWriter packet, int originalValue)
{
if ((Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES == null) || (Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES == null))
{
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
return;
}
final List<Integer> levelListFirst = new ArrayList<>(Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.keySet());
final List<Integer> levelListSecond = new ArrayList<>(Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.keySet());
for (int level : levelListSecond)
{
if (Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.isEmpty())
{
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
break;
}
if ((player.getLevel() >= level) && (levelListSecond.lastIndexOf(level) != (levelListSecond.size() - 1)))
{
continue;
}
int maxResTime;
try
{
maxResTime = Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.get(level).keySet().stream().max(Integer::compareTo).get();
}
catch (Exception e)
{
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
return;
}
int getValue = maxResTime <= originalValue ? maxResTime : originalValue + 1;
ResurrectByPaymentHolder rbph = Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.get(level).get(getValue);
packet.writeD(rbph.getAmount()); // Adena resurrection
packet.writeD(Math.toIntExact(Math.round(rbph.getResurrectPercent()))); // Adena count%
break;
}
for (int level : levelListFirst)
{
if (Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.isEmpty())
{
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
break;
}
if ((player.getLevel() >= level) && (levelListFirst.lastIndexOf(level) != (levelListFirst.size() - 1)))
{
continue;
}
int maxResTime;
try
{
maxResTime = Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.get(level).keySet().stream().max(Integer::compareTo).get();
}
catch (Exception e)
{
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
return;
}
final int getValue = maxResTime <= originalValue ? maxResTime : originalValue + 1;
ResurrectByPaymentHolder rbph = Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.get(level).get(getValue);
packet.writeD(rbph.getAmount()); // L-Coin resurrection
packet.writeD(Math.toIntExact(Math.round(rbph.getResurrectPercent()))); // L-Coin count%
break;
}
}
} }

View File

@@ -132,7 +132,7 @@ Sylph: https://eu.4game.com/patchnotes/lineage2essence/281/
-Hellbound spawns -Hellbound spawns
Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/ Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/
-Updated skill trees -Resurrection with payment
-Frost Lord castle -Frost Lord castle
Battle Chronicle: https://eu.4game.com/patchnotes/lineage2essence/353/ Battle Chronicle: https://eu.4game.com/patchnotes/lineage2essence/353/

View File

@@ -46,6 +46,74 @@ MpRegenMultiplier = 100
CpRegenMultiplier = 100 CpRegenMultiplier = 100
# ---------------------------------------------------------------------------
# Die recovery by payment
# ---------------------------------------------------------------------------
# Enable die recovery.
# Default: True
EnabledResurrectByPay = True
# Total number of free resurrections per day.
# Default: 2
MaxFreeResurrectionsByDay = 2
# Upper window resurrect item ID.
# Default: 91663 - L-Coin / MAKE CLIENT CHANGES!
FirstResurrectItemID = 91663
# List of for first case.
# level : times , count , restoration percent / times , count , percent;
# level : times , count , restoration percent / times , count , percent;
# the "\"indicates new line,
# NO FREE SPACES!
# Default: 60:3,1,100.0/4,2,100.0/5,3,100.0;\
# 75:3,1,100.0/4,3,100.0/5,4,100.0;\
# 79:3,2,100.0/4,5,100.0/5,10,100.0;\
# 81:3,5,100.0/4,10,100.0/5,15,100.0;\
# 84:3,15,100.0/4,20,100.0/5,25,100.0;\
# 86:3,20,100.0/4,40,100.0/5,80,100.0;\
# 88:3,25,100.0/4,50,100.0/5,100,100.0;\
# 90:3,25,100.0/4,50,100.0/5,100,100.0;
FirstResurrectList = 60:3,1,100.0/4,2,100.0/5,3,100.0;\
75:3,1,100.0/4,3,100.0/5,4,100.0;\
79:3,2,100.0/4,5,100.0/5,10,100.0;\
81:3,5,100.0/4,10,100.0/5,15,100.0;\
84:3,15,100.0/4,20,100.0/5,25,100.0;\
86:3,20,100.0/4,40,100.0/5,80,100.0;\
88:3,25,100.0/4,50,100.0/5,100,100.0;\
90:3,25,100.0/4,50,100.0/5,100,100.0;
# Lowest window resurrect item ID.
# Default: 57 - Adena / MAKE CLIENT CHANGES!
SecondResurrectItemID = 57
# List of for second case.
# level : times , count , restoration percent / times , count , percent;
# level : times , count , restoration percent / times , count , percent;
# the "\"indicates new line,
# NO FREE SPACES!
# Default:
# 60:3,5000,90.0/4,5000,80.0/5,5000,80.0/6,5000,70.0/7,5000,70.0/8,5000,60.0/9,5000,50.0;\
# 75:3,10000,90.0/4,10000,80.0/5,10000,80.0/6,10000,70.0/7,10000,70.0/8,10000,60.0/9,10000,50.0;\
# 79:3,20000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
# 81:3,30000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
# 84:3,60000,90.0/4,60000,80.0/5,60000,80.0/6,60000,70.0/7,60000,70.0/8,60000,60.0/9,60000,50.0;\
# 86:3,125000,90.0/4,125000,80.0/5,125000,80.0/6,125000,70.0/7,125000,70.0/8,125000,60.0/9,125000,50.0;\
# 88:3,240000,90.0/4,240000,80.0/5,240000,80.0/6,240000,70.0/7,240000,70.0/8,240000,60.0/9,240000,50.0;\
# 90:3,400000,90.0/4,400000,80.0/5,400000,80.0/6,400000,70.0/7,400000,70.0/8,400000,60.0/9,400000,50.0;
SecondResurrectList = 60:3,5000,90.0/4,5000,80.0/5,5000,80.0/6,5000,70.0/7,5000,70.0/8,5000,60.0/9,5000,50.0;\
75:3,10000,90.0/4,10000,80.0/5,10000,80.0/6,10000,70.0/7,10000,70.0/8,10000,60.0/9,10000,50.0;\
79:3,20000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
81:3,30000,90.0/4,20000,80.0/5,20000,80.0/6,20000,70.0/7,20000,70.0/8,20000,60.0/9,20000,50.0;\
84:3,60000,90.0/4,60000,80.0/5,60000,80.0/6,60000,70.0/7,60000,70.0/8,60000,60.0/9,60000,50.0;\
86:3,125000,90.0/4,125000,80.0/5,125000,80.0/6,125000,70.0/7,125000,70.0/8,125000,60.0/9,125000,50.0;\
88:3,240000,90.0/4,240000,80.0/5,240000,80.0/6,240000,70.0/7,240000,70.0/8,240000,60.0/9,240000,50.0;\
90:3,400000,90.0/4,400000,80.0/5,400000,80.0/6,400000,70.0/7,400000,70.0/8,400000,60.0/9,400000,50.0;
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Skills & Effects # Skills & Effects
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@@ -44,6 +44,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -65,6 +66,7 @@ import org.l2jmobius.gameserver.enums.GeoType;
import org.l2jmobius.gameserver.enums.IllegalActionPunishmentType; import org.l2jmobius.gameserver.enums.IllegalActionPunishmentType;
import org.l2jmobius.gameserver.model.Location; import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.holders.ResurrectByPaymentHolder;
import org.l2jmobius.gameserver.util.FloodProtectorConfig; import org.l2jmobius.gameserver.util.FloodProtectorConfig;
import org.l2jmobius.gameserver.util.Util; import org.l2jmobius.gameserver.util.Util;
@@ -891,6 +893,12 @@ public class Config
public static int MAX_CONNECTION_PER_IP; public static int MAX_CONNECTION_PER_IP;
public static boolean ENABLE_CMD_LINE_LOGIN; public static boolean ENABLE_CMD_LINE_LOGIN;
public static boolean ONLY_CMD_LINE_LOGIN; public static boolean ONLY_CMD_LINE_LOGIN;
public static boolean RESURRECT_BY_PAYMENT_ENABLED;
public static int RESURRECT_BY_PAYMENT_MAX_FREE_TIMES;
public static int RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM;
public static Map<Integer, Map<Integer, ResurrectByPaymentHolder>> RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES;
public static int RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM;
public static Map<Integer, Map<Integer, ResurrectByPaymentHolder>> RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES;
// Magic Lamp // Magic Lamp
public static boolean ENABLE_MAGIC_LAMP; public static boolean ENABLE_MAGIC_LAMP;
@@ -1661,6 +1669,93 @@ public class Config
HP_REGEN_MULTIPLIER = characterConfig.getDouble("HpRegenMultiplier", 100) / 100; HP_REGEN_MULTIPLIER = characterConfig.getDouble("HpRegenMultiplier", 100) / 100;
MP_REGEN_MULTIPLIER = characterConfig.getDouble("MpRegenMultiplier", 100) / 100; MP_REGEN_MULTIPLIER = characterConfig.getDouble("MpRegenMultiplier", 100) / 100;
CP_REGEN_MULTIPLIER = characterConfig.getDouble("CpRegenMultiplier", 100) / 100; CP_REGEN_MULTIPLIER = characterConfig.getDouble("CpRegenMultiplier", 100) / 100;
RESURRECT_BY_PAYMENT_ENABLED = characterConfig.getBoolean("EnabledResurrectByPay", true);
if (RESURRECT_BY_PAYMENT_ENABLED)
{
Map<Integer, ResurrectByPaymentHolder> RESURRECT_DATA = new TreeMap<>();
RESURRECT_BY_PAYMENT_MAX_FREE_TIMES = characterConfig.getInt("MaxFreeResurrectionsByDay", 0);
RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM = characterConfig.getInt("FirstResurrectItemID", 0);
final String[] firstPaymentSplit = characterConfig.getString("FirstResurrectList", "").split(";");
RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES = new TreeMap<>();
for (String timeData : firstPaymentSplit)
{
RESURRECT_DATA = new TreeMap<>();
final String[] timeSplit = timeData.split(":");
if (timeSplit.length != 2)
{
LOGGER.warning("[FirstResurrectList]: invalid config property -> Level data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
final String[] dataSplit = timeSplit[1].split("/");
for (String data : dataSplit)
{
while (data.contains(" "))
{
data = data.replace(" ", "");
}
final String[] values = data.split(",");
if (values.length < 3)
{
LOGGER.warning("[FirstResurrectList]: invalid config property -> Times data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
try
{
final int time = Integer.parseInt(values[0]);
final int count = Integer.parseInt(values[1]);
final double percent = Double.parseDouble(values[2]);
RESURRECT_DATA.put(time, new ResurrectByPaymentHolder(time, count, percent));
}
catch (Exception e)
{
LOGGER.warning("[FirstResurrectList]: invalid config property -> Times data cannot be parsed. Look on exception " + timeSplit[0]);
e.printStackTrace();
}
}
RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.put(Integer.parseInt(timeSplit[0]), RESURRECT_DATA);
}
final String[] secondPaymentSplit = characterConfig.getString("SecondResurrectList", "").split(";");
RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES = new TreeMap<>();
for (String timeData : secondPaymentSplit)
{
RESURRECT_DATA = new TreeMap<>();
final String[] timeSplit = timeData.split(":");
if (timeSplit.length != 2)
{
LOGGER.warning("[SecondResurrectList]: invalid config property -> Level data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
final String[] dataSplit = timeSplit[1].split("/");
for (String data : dataSplit)
{
while (data.contains(" "))
{
data = data.replace(" ", "");
}
final String[] values = data.split(",");
if (values.length < 3)
{
LOGGER.warning("[SecondResurrectList]: invalid config property -> Times data cannot be parsed. Looking like not exist " + timeSplit[0]);
continue;
}
try
{
final int time = Integer.parseInt(values[0]);
final int count = Integer.parseInt(values[1]);
final double percent = Double.parseDouble(values[2]);
RESURRECT_DATA.put(time, new ResurrectByPaymentHolder(time, count, percent));
}
catch (Exception e)
{
LOGGER.warning("[SecondResurrectList]: invalid config property -> Times data cannot be parsed. Look on exception " + timeSplit[0]);
e.printStackTrace();
}
}
RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.put(Integer.parseInt(timeSplit[0]), RESURRECT_DATA);
}
RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM = characterConfig.getInt("SecondResurrectItemID", 0);
}
ENABLE_MODIFY_SKILL_DURATION = characterConfig.getBoolean("EnableModifySkillDuration", false); ENABLE_MODIFY_SKILL_DURATION = characterConfig.getBoolean("EnableModifySkillDuration", false);
if (ENABLE_MODIFY_SKILL_DURATION) if (ENABLE_MODIFY_SKILL_DURATION)
{ {

View File

@@ -141,6 +141,7 @@ public class DailyTaskManager
resetDailyMissionRewards(); resetDailyMissionRewards();
resetAttendanceRewards(); resetAttendanceRewards();
resetVip(); resetVip();
resetResurrectionByPayment();
} }
private void onSave() private void onSave()
@@ -668,6 +669,32 @@ public class DailyTaskManager
LOGGER.info("LimitShopData has been resetted."); LOGGER.info("LimitShopData has been resetted.");
} }
private void resetResurrectionByPayment()
{
// Update data for offline players.
try (Connection con = DatabaseFactory.getConnection())
{
try (PreparedStatement ps = con.prepareStatement("DELETE FROM character_variables WHERE var=?"))
{
ps.setString(1, PlayerVariables.RESURRECT_BY_PAYMENT_COUNT);
ps.execute();
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Could not reset payment resurrection count for players: " + e);
}
// Update data for online players.
for (Player player : World.getInstance().getPlayers())
{
player.getVariables().remove(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT);
player.getVariables().storeMe();
}
LOGGER.info("Daily payment resurrection count for player has been resetted.");
}
private void resetDailyHennaPattern() private void resetDailyHennaPattern()
{ {
// Update data for offline players. // Update data for offline players.

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.model.holders;
/**
* @author Index
*/
public class ResurrectByPaymentHolder
{
private final int _time;
private final int _amount;
private final double _resurrectPercent;
public ResurrectByPaymentHolder(int time, int amount, double percent)
{
_time = time;
_amount = amount;
_resurrectPercent = percent;
}
public int getTime()
{
return _time;
}
public int getAmount()
{
return _amount;
}
public double getResurrectPercent()
{
return _resurrectPercent;
}
}

View File

@@ -80,6 +80,7 @@ public class PlayerVariables extends AbstractVariables
public static final String STAT_INT = "STAT_INT"; public static final String STAT_INT = "STAT_INT";
public static final String STAT_WIT = "STAT_WIT"; public static final String STAT_WIT = "STAT_WIT";
public static final String STAT_MEN = "STAT_MEN"; public static final String STAT_MEN = "STAT_MEN";
public static final String RESURRECT_BY_PAYMENT_COUNT = "RESURRECT_BY_PAYMENT_COUNT";
public static final String CLAN_JOIN_TIME = "CLAN_JOIN_TIME"; public static final String CLAN_JOIN_TIME = "CLAN_JOIN_TIME";
public static final String HENNA1_DURATION = "HENNA1_DURATION"; public static final String HENNA1_DURATION = "HENNA1_DURATION";
public static final String HENNA2_DURATION = "HENNA2_DURATION"; public static final String HENNA2_DURATION = "HENNA2_DURATION";

View File

@@ -16,6 +16,11 @@
*/ */
package org.l2jmobius.gameserver.network.clientpackets; package org.l2jmobius.gameserver.network.clientpackets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader; import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.threads.ThreadPool; import org.l2jmobius.commons.threads.ThreadPool;
import org.l2jmobius.gameserver.data.xml.ClanHallData; import org.l2jmobius.gameserver.data.xml.ClanHallData;
@@ -29,7 +34,9 @@ import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.EventType;
import org.l2jmobius.gameserver.model.events.listeners.AbstractEventListener; import org.l2jmobius.gameserver.model.events.listeners.AbstractEventListener;
import org.l2jmobius.gameserver.model.holders.ResurrectByPaymentHolder;
import org.l2jmobius.gameserver.model.instancezone.Instance; import org.l2jmobius.gameserver.model.instancezone.Instance;
import org.l2jmobius.gameserver.model.item.instance.Item;
import org.l2jmobius.gameserver.model.quest.Event; import org.l2jmobius.gameserver.model.quest.Event;
import org.l2jmobius.gameserver.model.residences.ClanHall; import org.l2jmobius.gameserver.model.residences.ClanHall;
import org.l2jmobius.gameserver.model.residences.ResidenceFunctionType; import org.l2jmobius.gameserver.model.residences.ResidenceFunctionType;
@@ -38,8 +45,11 @@ import org.l2jmobius.gameserver.model.siege.Castle.CastleFunction;
import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Fort;
import org.l2jmobius.gameserver.model.siege.Fort.FortFunction; import org.l2jmobius.gameserver.model.siege.Fort.FortFunction;
import org.l2jmobius.gameserver.model.skill.CommonSkill; import org.l2jmobius.gameserver.model.skill.CommonSkill;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
import org.l2jmobius.gameserver.network.GameClient; import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.PacketLogger; import org.l2jmobius.gameserver.network.PacketLogger;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/** /**
* @version $Revision: 1.7.2.3.2.6 $ $Date: 2005/03/27 15:29:30 $ * @version $Revision: 1.7.2.3.2.6 $ $Date: 2005/03/27 15:29:30 $
@@ -48,11 +58,18 @@ public class RequestRestartPoint implements IClientIncomingPacket
{ {
protected int _requestedPointType; protected int _requestedPointType;
protected boolean _continuation; protected boolean _continuation;
protected int _resItemID;
protected int _resCount;
@Override @Override
public boolean read(GameClient client, PacketReader packet) public boolean read(GameClient client, PacketReader packet)
{ {
_requestedPointType = packet.readD(); _requestedPointType = packet.readD();
if (packet.getReadableBytes() != 0)
{
_resItemID = packet.readD();
_resCount = packet.readD();
}
return true; return true;
} }
@@ -270,6 +287,80 @@ public class RequestRestartPoint implements IClientIncomingPacket
{ {
break; break;
} }
case 9:
{
if (Config.RESURRECT_BY_PAYMENT_ENABLED)
{
if (!player.isDead())
{
break;
}
final int originalValue = player.getVariables().getInt(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, 0);
if (originalValue < Config.RESURRECT_BY_PAYMENT_MAX_FREE_TIMES)
{
player.getVariables().set(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, originalValue + 1);
player.doRevive(100.0);
loc = MapRegionManager.getInstance().getTeleToLocation(player, TeleportWhereType.TOWN);
player.teleToLocation(loc, true, instance);
break;
}
final int firstID = Config.RESURRECT_BY_PAYMENT_ENABLED ? Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM : 91663;
final int secondID = Config.RESURRECT_BY_PAYMENT_ENABLED ? Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM : 57;
Map<Integer, Map<Integer, ResurrectByPaymentHolder>> resMAP = null;
Item item = null;
if (_resItemID == firstID)
{
resMAP = Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES;
item = player.getInventory().getItemByItemId(Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_ITEM);
}
else if (_resItemID == secondID)
{
resMAP = Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES;
item = player.getInventory().getItemByItemId(Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_ITEM);
}
if ((resMAP == null) || (item == null))
{
break;
}
final List<Integer> levelList = new ArrayList<>(resMAP.keySet());
for (int level : levelList)
{
if ((player.getLevel() >= level) && (levelList.lastIndexOf(level) != (levelList.size() - 1)))
{
continue;
}
int maxResTime;
try
{
maxResTime = resMAP.get(level).keySet().stream().max(Integer::compareTo).get();
}
catch (Exception e)
{
player.sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
e.printStackTrace();
return;
}
final int getValue = maxResTime <= originalValue ? maxResTime : originalValue + 1;
final ResurrectByPaymentHolder rbph = resMAP.get(level).get(getValue);
if (item.getCount() < rbph.getAmount())
{
return;
}
player.getVariables().set(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, originalValue + 1);
player.destroyItem("item revive", item, rbph.getAmount(), player, true);
player.doRevive(rbph.getResurrectPercent());
loc = MapRegionManager.getInstance().getTeleToLocation(player, TeleportWhereType.TOWN);
player.teleToLocation(loc, true, instance);
break;
}
}
}
case 27: // to jail case 27: // to jail
{ {
if (!player.isJailed()) if (!player.isJailed())

View File

@@ -16,16 +16,23 @@
*/ */
package org.l2jmobius.gameserver.network.serverpackets; package org.l2jmobius.gameserver.network.serverpackets;
import java.util.ArrayList;
import java.util.List;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketWriter; import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.instancemanager.CastleManager;
import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.instancemanager.FortManager;
import org.l2jmobius.gameserver.model.SiegeClan; import org.l2jmobius.gameserver.model.SiegeClan;
import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.clan.Clan; import org.l2jmobius.gameserver.model.clan.Clan;
import org.l2jmobius.gameserver.model.holders.ResurrectByPaymentHolder;
import org.l2jmobius.gameserver.model.siege.Castle; import org.l2jmobius.gameserver.model.siege.Castle;
import org.l2jmobius.gameserver.model.siege.Fort; import org.l2jmobius.gameserver.model.siege.Fort;
import org.l2jmobius.gameserver.model.skill.BuffInfo; import org.l2jmobius.gameserver.model.skill.BuffInfo;
import org.l2jmobius.gameserver.model.skill.CommonSkill; import org.l2jmobius.gameserver.model.skill.CommonSkill;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
import org.l2jmobius.gameserver.network.OutgoingPackets; import org.l2jmobius.gameserver.network.OutgoingPackets;
/** /**
@@ -37,6 +44,7 @@ public class Die implements IClientOutgoingPacket
private final boolean _isSweepable; private final boolean _isSweepable;
private int _flags = 1; // To nearest village. private int _flags = 1; // To nearest village.
private int _delayFeather = 0; private int _delayFeather = 0;
private Player _player;
public Die(Creature creature) public Die(Creature creature)
{ {
@@ -44,7 +52,8 @@ public class Die implements IClientOutgoingPacket
_isSweepable = creature.isAttackable() && creature.isSweepActive(); _isSweepable = creature.isAttackable() && creature.isSweepActive();
if (creature.isPlayer()) if (creature.isPlayer())
{ {
final Clan clan = creature.getActingPlayer().getClan(); _player = creature.getActingPlayer();
final Clan clan = _player.getClan();
boolean isInCastleDefense = false; boolean isInCastleDefense = false;
boolean isInFortDefense = false; boolean isInFortDefense = false;
SiegeClan siegeClan = null; SiegeClan siegeClan = null;
@@ -108,8 +117,113 @@ public class Die implements IClientOutgoingPacket
packet.writeD(_delayFeather); // Feather item time. packet.writeD(_delayFeather); // Feather item time.
packet.writeC(0); // Hide die animation. packet.writeC(0); // Hide die animation.
packet.writeD(0); packet.writeD(0);
packet.writeD(0); if ((_player != null) && Config.RESURRECT_BY_PAYMENT_ENABLED)
{
int resurrectTimes = _player.getVariables().getInt(PlayerVariables.RESURRECT_BY_PAYMENT_COUNT, 0) + 1;
int originalValue = resurrectTimes - 1;
if (originalValue < Config.RESURRECT_BY_PAYMENT_MAX_FREE_TIMES)
{
packet.writeD(Config.RESURRECT_BY_PAYMENT_MAX_FREE_TIMES - originalValue); // free round resurrection
packet.writeD(0); // Adena resurrection
packet.writeD(0); // Adena count%
packet.writeD(0); // L-Coin resurrection
packet.writeD(0); // L-Coin count%
}
else
{
packet.writeD(0);
getValues(_player, packet, originalValue);
}
}
else
{
packet.writeD(1); // free round resurrection
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
}
packet.writeD(0); packet.writeD(0);
return true; return true;
} }
private void getValues(Player player, PacketWriter packet, int originalValue)
{
if ((Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES == null) || (Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES == null))
{
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
return;
}
final List<Integer> levelListFirst = new ArrayList<>(Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.keySet());
final List<Integer> levelListSecond = new ArrayList<>(Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.keySet());
for (int level : levelListSecond)
{
if (Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.isEmpty())
{
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
break;
}
if ((player.getLevel() >= level) && (levelListSecond.lastIndexOf(level) != (levelListSecond.size() - 1)))
{
continue;
}
int maxResTime;
try
{
maxResTime = Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.get(level).keySet().stream().max(Integer::compareTo).get();
}
catch (Exception e)
{
packet.writeD(0); // Adena resurrection
packet.writeD(-1); // Adena count%
return;
}
int getValue = maxResTime <= originalValue ? maxResTime : originalValue + 1;
ResurrectByPaymentHolder rbph = Config.RESURRECT_BY_PAYMENT_SECOND_RESURRECT_VALUES.get(level).get(getValue);
packet.writeD(rbph.getAmount()); // Adena resurrection
packet.writeD(Math.toIntExact(Math.round(rbph.getResurrectPercent()))); // Adena count%
break;
}
for (int level : levelListFirst)
{
if (Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.isEmpty())
{
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
break;
}
if ((player.getLevel() >= level) && (levelListFirst.lastIndexOf(level) != (levelListFirst.size() - 1)))
{
continue;
}
int maxResTime;
try
{
maxResTime = Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.get(level).keySet().stream().max(Integer::compareTo).get();
}
catch (Exception e)
{
packet.writeD(0); // L-Coin resurrection
packet.writeD(-1); // L-Coin count%
return;
}
final int getValue = maxResTime <= originalValue ? maxResTime : originalValue + 1;
ResurrectByPaymentHolder rbph = Config.RESURRECT_BY_PAYMENT_FIRST_RESURRECT_VALUES.get(level).get(getValue);
packet.writeD(rbph.getAmount()); // L-Coin resurrection
packet.writeD(Math.toIntExact(Math.round(rbph.getResurrectPercent()))); // L-Coin count%
break;
}
}
} }

View File

@@ -132,7 +132,7 @@ Sylph: https://eu.4game.com/patchnotes/lineage2essence/281/
-Hellbound spawns -Hellbound spawns
Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/ Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/
-Updated skill trees -Resurrection with payment
-Frost Lord castle -Frost Lord castle
Battle Chronicle: https://eu.4game.com/patchnotes/lineage2essence/353/ Battle Chronicle: https://eu.4game.com/patchnotes/lineage2essence/353/