Fixed gaining big amounts of exp on high rates.

This commit is contained in:
MobiusDev
2017-11-21 15:22:11 +00:00
parent 701a762570
commit b6d36e36be
60 changed files with 400 additions and 430 deletions
@@ -26,7 +26,7 @@ import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public final class PcCafePointsManager public final class PcCafePointsManager
{ {
public void givePcCafePoint(L2PcInstance player, long exp) public void givePcCafePoint(L2PcInstance player, double exp)
{ {
if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed()) if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed())
{ {
@@ -3109,7 +3109,7 @@ public class L2Clan implements IIdentifiable, INamable
* @param target * @param target
* @param value * @param value
*/ */
public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, long value) public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, double value)
{ {
// TODO: Figure out the retail formula // TODO: Figure out the retail formula
final int points = (int) value / 29600; final int points = (int) value / 29600;
@@ -834,7 +834,7 @@ public class L2Party extends AbstractPlayerGroup
* @param partyDmg * @param partyDmg
* @param target * @param target
*/ */
public void distributeXpAndSp(long xpReward, int spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target) public void distributeXpAndSp(double xpReward, double spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target)
{ {
final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl); final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl);
@@ -870,24 +870,24 @@ public class L2Party extends AbstractPlayerGroup
final double preCalculation = (sqLevel / sqLevelSum) * penalty; final double preCalculation = (sqLevel / sqLevelSum) * penalty;
// Add the XP/SP points to the requested party member // Add the XP/SP points to the requested party member
long addexp = Math.round(member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation)); double exp = member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation);
final int addsp = (int) member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation); double sp = member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation);
addexp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, addexp, addsp, target.useVitalityRate()); exp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, exp, sp, target.useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = member.getClan(); final L2Clan clan = member.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (target.useVitalityRate()) if (target.useVitalityRate())
{ {
finalExp *= member.getStat().getExpBonusMultiplier(); finalExp *= member.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(member, target, finalExp); clan.addHuntingPoints(member, target, finalExp);
} }
member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), addexp, target.isRaid()), true, false); member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), exp, target.isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(member, addexp); PcCafePointsManager.getInstance().givePcCafePoint(member, exp);
} }
} }
else else
@@ -897,10 +897,10 @@ public class L2Party extends AbstractPlayerGroup
} }
} }
private long calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, long addExp, int addSp, boolean vit) private double calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, double addExp, double addSp, boolean vit)
{ {
long xp = addExp; double xp = addExp;
int sp = addSp; double sp = addSp;
if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive")) if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive"))
{ {
int i = 0; int i = 0;
@@ -472,9 +472,9 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
final int[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -495,24 +495,24 @@ public class L2Attackable extends L2Npc
// Distribute the Exp and SP between the L2PcInstance and its L2Summon // Distribute the Exp and SP between the L2PcInstance and its L2Summon
if (!attacker.isDead()) if (!attacker.isDead())
{ {
final long addexp = Math.round(attacker.getStat().getValue(Stats.EXPSP_RATE, exp)); exp = attacker.getStat().getValue(Stats.EXPSP_RATE, exp);
final int addsp = (int) attacker.getStat().getValue(Stats.EXPSP_RATE, sp); sp = attacker.getStat().getValue(Stats.EXPSP_RATE, sp);
attacker.addExpAndSp(addexp, addsp, useVitalityRate()); attacker.addExpAndSp(exp, sp, useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = attacker.getClan(); final L2Clan clan = attacker.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (useVitalityRate()) if (useVitalityRate())
{ {
finalExp *= attacker.getStat().getExpBonusMultiplier(); finalExp *= attacker.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(attacker, this, finalExp); clan.addHuntingPoints(attacker, this, finalExp);
} }
attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), addexp, isRaid()), true, false); attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), exp, isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(attacker, addexp); PcCafePointsManager.getInstance().givePcCafePoint(attacker, exp);
} }
} }
} }
@@ -521,7 +521,7 @@ public class L2Attackable extends L2Npc
{ {
// share with party members // share with party members
int partyDmg = 0; int partyDmg = 0;
float partyMul = 1; double partyMul = 1;
int partyLvl = 0; int partyLvl = 0;
// Get all L2Character that can be rewarded in the party // Get all L2Character that can be rewarded in the party
@@ -580,13 +580,13 @@ public class L2Attackable extends L2Npc
// If the party didn't killed this L2Attackable alone // If the party didn't killed this L2Attackable alone
if (partyDmg < totalDamage) if (partyDmg < totalDamage)
{ {
partyMul = ((float) partyDmg / totalDamage); partyMul = ((double) partyDmg / totalDamage);
} }
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
final int[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage); final double[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -1308,11 +1308,11 @@ public class L2Attackable extends L2Npc
* @param totalDamage The total damage done * @param totalDamage The total damage done
* @return * @return
*/ */
private int[] calculateExpAndSp(int charLevel, int damage, long totalDamage) private double[] calculateExpAndSp(int charLevel, int damage, long totalDamage)
{ {
final int levelDiff = Math.abs(charLevel - getLevel()); final int levelDiff = Math.abs(charLevel - getLevel());
double xp = Math.max(0, ((double) getExpReward() * damage) / totalDamage); double xp = Math.max(0, (getExpReward() * damage) / totalDamage);
double sp = Math.max(0, ((double) getSpReward() * damage) / totalDamage); double sp = Math.max(0, (getSpReward() * damage) / totalDamage);
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
@@ -1372,14 +1372,14 @@ public class L2Attackable extends L2Npc
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
return new int[] return new double[]
{ {
(int) xp, xp,
(int) sp sp
}; };
} }
public long calculateOverhitExp(long normalExp) public double calculateOverhitExp(double exp)
{ {
// Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable // Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable
double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp()); double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp());
@@ -1392,10 +1392,7 @@ public class L2Attackable extends L2Npc
// Get the overhit exp bonus according to the above over-hit damage percentage // Get the overhit exp bonus according to the above over-hit damage percentage
// (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...) // (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...)
final double overhitExp = ((overhitPercentage / 100) * normalExp); return (overhitPercentage / 100) * exp;
// Return the rounded amount of exp points to be added to the player's normal exp reward
return Math.round(overhitExp);
} }
/** /**
@@ -1648,7 +1645,7 @@ public class L2Attackable extends L2Npc
/* /*
* Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp. * Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp.
*/ */
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
if ((getLevel() <= 0) || (getExpReward() <= 0)) if ((getLevel() <= 0) || (getExpReward() <= 0))
{ {
@@ -1658,11 +1655,11 @@ public class L2Attackable extends L2Npc
int points; int points;
if (level < 85) if (level < 85)
{ {
points = (int) ((exp / 1000) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / 1000) * Math.max(level - getLevel(), 1)), 1);
} }
else else
{ {
points = (int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)), 1);
} }
return -points; return -points;
@@ -3793,7 +3793,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
* @param addToExp * @param addToExp
* @param addToSp * @param addToSp
*/ */
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
// Dummy method (overridden by players and pets) // Dummy method (overridden by players and pets)
} }
@@ -54,7 +54,7 @@ public final class L2GrandBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -10400,12 +10400,12 @@ public final class L2PcInstance extends L2Playable
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
getStat().addExpAndSp(addToExp, addToSp, false); getStat().addExpAndSp(addToExp, addToSp, false);
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useVitality) public void addExpAndSp(double addToExp, double addToSp, boolean useVitality)
{ {
getStat().addExpAndSp(addToExp, addToSp, useVitality); getStat().addExpAndSp(addToExp, addToSp, useVitality);
} }
@@ -93,7 +93,7 @@ public class L2PetInstance extends L2Summon
private L2PetLevelData _leveldata; private L2PetLevelData _leveldata;
/** The Experience before the last Death Penalty */ /** The Experience before the last Death Penalty */
private long _expBeforeDeath = 0; private double _expBeforeDeath = 0;
private int _curWeightPenalty = 0; private int _curWeightPenalty = 0;
public final L2PetLevelData getPetLevelData() public final L2PetLevelData getPetLevelData()
@@ -1185,15 +1185,15 @@ public class L2PetInstance extends L2Summon
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
if (getId() == 12564) if (getId() == 12564) // TODO: Remove this stupid hardcode.
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.SINEATER_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.SINEATER_XP_RATE, addToSp);
} }
else else
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.PET_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.PET_XP_RATE, addToSp);
} }
} }
@@ -102,7 +102,7 @@ public class L2RaidBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -72,7 +72,7 @@ public class PcStat extends PlayableStat
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
// Allowed to gain exp? // Allowed to gain exp?
if (!getActiveChar().getAccessLevel().canGainExp()) if (!activeChar.getAccessLevel().canGainExp())
{ {
return false; return false;
} }
@@ -97,7 +97,7 @@ public class PcStat extends PlayableStat
return true; return true;
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useBonuses) public void addExpAndSp(double addToExp, double addToSp, boolean useBonuses)
{ {
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
@@ -107,8 +107,8 @@ public class PcStat extends PlayableStat
return; return;
} }
final long baseExp = addToExp; final double baseExp = addToExp;
final long baseSp = addToSp; final double baseSp = addToSp;
double bonusExp = 1.; double bonusExp = 1.;
double bonusSp = 1.; double bonusSp = 1.;
@@ -141,7 +141,7 @@ public class PcStat extends PlayableStat
addToExp *= bonusExp; addToExp *= bonusExp;
addToSp *= bonusSp; addToSp *= bonusSp;
float ratioTakenByPlayer = 0; double ratioTakenByPlayer = 0;
// if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now // if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now
final L2Summon sPet = activeChar.getPet(); final L2Summon sPet = activeChar.getPet();
@@ -159,42 +159,37 @@ public class PcStat extends PlayableStat
if (!pet.isDead()) if (!pet.isDead())
{ {
pet.addExpAndSp((long) (addToExp * (1 - ratioTakenByPlayer)), (int) (addToSp * (1 - ratioTakenByPlayer))); pet.addExpAndSp(addToExp * (1 - ratioTakenByPlayer), addToSp * (1 - ratioTakenByPlayer));
} }
// now adjust the max ratio to avoid the owner earning negative exp/sp // now adjust the max ratio to avoid the owner earning negative exp/sp
addToExp = (long) (addToExp * ratioTakenByPlayer); addToExp *= ratioTakenByPlayer;
addToSp = (int) (addToSp * ratioTakenByPlayer); addToSp *= ratioTakenByPlayer;
} }
if (!addExp(addToExp)) final long finalExp = Math.round(addToExp);
{ final long finalSp = Math.round(addToSp);
addToExp = 0; final boolean expAdded = addExp(finalExp);
} final boolean spAdded = addSp(finalSp);
if (!addSp(addToSp))
{
addToSp = 0;
}
SystemMessage sm = null; SystemMessage sm = null;
if ((addToExp == 0) && (addToSp != 0)) if (!expAdded && spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP);
sm.addLong(addToSp); sm.addLong(finalSp);
} }
else if ((addToSp == 0) && (addToExp != 0)) else if (expAdded && !spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
} }
else else
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4);
sm.addLong(addToExp); sm.addLong(finalExp);
sm.addLong(addToExp - baseExp); sm.addLong(Math.round(addToExp - baseExp));
sm.addLong(addToSp); sm.addLong(finalSp);
sm.addLong(addToSp - baseSp); sm.addLong(Math.round(addToSp - baseSp));
} }
activeChar.sendPacket(sm); activeChar.sendPacket(sm);
} }
@@ -307,6 +302,7 @@ public class PcStat extends PlayableStat
{ {
return false; return false;
} }
final UserInfo ui = new UserInfo(getActiveChar(), false); final UserInfo ui = new UserInfo(getActiveChar(), false);
ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP); ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP);
getActiveChar().sendPacket(ui); getActiveChar().sendPacket(ui);
@@ -41,15 +41,16 @@ public class PetStat extends SummonStat
return true; return true;
} }
public boolean addExpAndSp(long addToExp, long addToSp) public boolean addExpAndSp(double addToExp, double addToSp)
{ {
if (getActiveChar().isUncontrollable() || !addExp(addToExp)) final long finalExp = Math.round(addToExp);
if (getActiveChar().isUncontrollable() || !addExp(finalExp))
{ {
return false; return false;
} }
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP); SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
getActiveChar().updateAndBroadcastStatus(1); getActiveChar().updateAndBroadcastStatus(1);
getActiveChar().sendPacket(sm); getActiveChar().sendPacket(sm);
return true; return true;
@@ -1232,17 +1232,17 @@ public final class Formulas
/** /**
* Calculates karma lost upon death. * Calculates karma lost upon death.
* @param player * @param player
* @param exp * @param finalExp
* @return the amount of karma player has loosed. * @return the amount of karma player has loosed.
*/ */
public static int calculateKarmaLost(L2PcInstance player, long exp) public static int calculateKarmaLost(L2PcInstance player, double finalExp)
{ {
final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel()); final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel());
if (exp > 0) // Received exp if (finalExp > 0) // Received exp
{ {
exp /= Config.RATE_KARMA_LOST; finalExp /= Config.RATE_KARMA_LOST;
} }
return (int) ((Math.abs(exp) / karmaLooseMul) / 30); return (int) ((Math.abs(finalExp) / karmaLooseMul) / 30);
} }
/** /**
@@ -26,7 +26,7 @@ import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public final class PcCafePointsManager public final class PcCafePointsManager
{ {
public void givePcCafePoint(L2PcInstance player, long exp) public void givePcCafePoint(L2PcInstance player, double exp)
{ {
if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed()) if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed())
{ {
@@ -3110,7 +3110,7 @@ public class L2Clan implements IIdentifiable, INamable
* @param target * @param target
* @param value * @param value
*/ */
public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, long value) public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, double value)
{ {
// TODO: Figure out the retail formula // TODO: Figure out the retail formula
final int points = (int) value / 29600; final int points = (int) value / 29600;
@@ -834,7 +834,7 @@ public class L2Party extends AbstractPlayerGroup
* @param partyDmg * @param partyDmg
* @param target * @param target
*/ */
public void distributeXpAndSp(long xpReward, int spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target) public void distributeXpAndSp(double xpReward, double spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target)
{ {
final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl); final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl);
@@ -870,24 +870,24 @@ public class L2Party extends AbstractPlayerGroup
final double preCalculation = (sqLevel / sqLevelSum) * penalty; final double preCalculation = (sqLevel / sqLevelSum) * penalty;
// Add the XP/SP points to the requested party member // Add the XP/SP points to the requested party member
long addexp = Math.round(member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation)); double exp = member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation);
final int addsp = (int) member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation); double sp = member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation);
addexp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, addexp, addsp, target.useVitalityRate()); exp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, exp, sp, target.useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = member.getClan(); final L2Clan clan = member.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (target.useVitalityRate()) if (target.useVitalityRate())
{ {
finalExp *= member.getStat().getExpBonusMultiplier(); finalExp *= member.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(member, target, finalExp); clan.addHuntingPoints(member, target, finalExp);
} }
member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), addexp, target.isRaid()), true, false); member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), exp, target.isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(member, addexp); PcCafePointsManager.getInstance().givePcCafePoint(member, exp);
} }
} }
else else
@@ -897,10 +897,10 @@ public class L2Party extends AbstractPlayerGroup
} }
} }
private long calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, long addExp, int addSp, boolean vit) private double calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, double addExp, double addSp, boolean vit)
{ {
long xp = addExp; double xp = addExp;
int sp = addSp; double sp = addSp;
if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive")) if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive"))
{ {
int i = 0; int i = 0;
@@ -468,9 +468,9 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
final int[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -491,24 +491,24 @@ public class L2Attackable extends L2Npc
// Distribute the Exp and SP between the L2PcInstance and its L2Summon // Distribute the Exp and SP between the L2PcInstance and its L2Summon
if (!attacker.isDead()) if (!attacker.isDead())
{ {
final long addexp = Math.round(attacker.getStat().getValue(Stats.EXPSP_RATE, exp)); exp = attacker.getStat().getValue(Stats.EXPSP_RATE, exp);
final int addsp = (int) attacker.getStat().getValue(Stats.EXPSP_RATE, sp); sp = attacker.getStat().getValue(Stats.EXPSP_RATE, sp);
attacker.addExpAndSp(addexp, addsp, useVitalityRate()); attacker.addExpAndSp(exp, sp, useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = attacker.getClan(); final L2Clan clan = attacker.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (useVitalityRate()) if (useVitalityRate())
{ {
finalExp *= attacker.getStat().getExpBonusMultiplier(); finalExp *= attacker.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(attacker, this, finalExp); clan.addHuntingPoints(attacker, this, finalExp);
} }
attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), addexp, isRaid()), true, false); attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), exp, isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(attacker, addexp); PcCafePointsManager.getInstance().givePcCafePoint(attacker, exp);
} }
} }
} }
@@ -517,7 +517,7 @@ public class L2Attackable extends L2Npc
{ {
// share with party members // share with party members
int partyDmg = 0; int partyDmg = 0;
float partyMul = 1; double partyMul = 1;
int partyLvl = 0; int partyLvl = 0;
// Get all L2Character that can be rewarded in the party // Get all L2Character that can be rewarded in the party
@@ -576,13 +576,13 @@ public class L2Attackable extends L2Npc
// If the party didn't killed this L2Attackable alone // If the party didn't killed this L2Attackable alone
if (partyDmg < totalDamage) if (partyDmg < totalDamage)
{ {
partyMul = ((float) partyDmg / totalDamage); partyMul = ((double) partyDmg / totalDamage);
} }
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
final int[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage); final double[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -1254,11 +1254,11 @@ public class L2Attackable extends L2Npc
* @param totalDamage The total damage done * @param totalDamage The total damage done
* @return * @return
*/ */
private int[] calculateExpAndSp(int charLevel, int damage, long totalDamage) private double[] calculateExpAndSp(int charLevel, int damage, long totalDamage)
{ {
final int levelDiff = Math.abs(charLevel - getLevel()); final int levelDiff = Math.abs(charLevel - getLevel());
double xp = Math.max(0, ((double) getExpReward() * damage) / totalDamage); double xp = Math.max(0, (getExpReward() * damage) / totalDamage);
double sp = Math.max(0, ((double) getSpReward() * damage) / totalDamage); double sp = Math.max(0, (getSpReward() * damage) / totalDamage);
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
@@ -1318,14 +1318,14 @@ public class L2Attackable extends L2Npc
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
return new int[] return new double[]
{ {
(int) xp, xp,
(int) sp sp
}; };
} }
public long calculateOverhitExp(long normalExp) public double calculateOverhitExp(double exp)
{ {
// Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable // Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable
double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp()); double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp());
@@ -1338,10 +1338,7 @@ public class L2Attackable extends L2Npc
// Get the overhit exp bonus according to the above over-hit damage percentage // Get the overhit exp bonus according to the above over-hit damage percentage
// (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...) // (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...)
final double overhitExp = ((overhitPercentage / 100) * normalExp); return (overhitPercentage / 100) * exp;
// Return the rounded amount of exp points to be added to the player's normal exp reward
return Math.round(overhitExp);
} }
/** /**
@@ -1594,7 +1591,7 @@ public class L2Attackable extends L2Npc
/* /*
* Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp. * Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp.
*/ */
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
if ((getLevel() <= 0) || (getExpReward() <= 0)) if ((getLevel() <= 0) || (getExpReward() <= 0))
{ {
@@ -1604,11 +1601,11 @@ public class L2Attackable extends L2Npc
int points; int points;
if (level < 85) if (level < 85)
{ {
points = (int) ((exp / 1000) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / 1000) * Math.max(level - getLevel(), 1)), 1);
} }
else else
{ {
points = (int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)), 1);
} }
return -points; return -points;
@@ -3797,7 +3797,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
* @param addToExp * @param addToExp
* @param addToSp * @param addToSp
*/ */
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
// Dummy method (overridden by players and pets) // Dummy method (overridden by players and pets)
} }
@@ -54,7 +54,7 @@ public final class L2GrandBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -10401,12 +10401,12 @@ public final class L2PcInstance extends L2Playable
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
getStat().addExpAndSp(addToExp, addToSp, false); getStat().addExpAndSp(addToExp, addToSp, false);
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useVitality) public void addExpAndSp(double addToExp, double addToSp, boolean useVitality)
{ {
getStat().addExpAndSp(addToExp, addToSp, useVitality); getStat().addExpAndSp(addToExp, addToSp, useVitality);
} }
@@ -93,7 +93,7 @@ public class L2PetInstance extends L2Summon
private L2PetLevelData _leveldata; private L2PetLevelData _leveldata;
/** The Experience before the last Death Penalty */ /** The Experience before the last Death Penalty */
private long _expBeforeDeath = 0; private double _expBeforeDeath = 0;
private int _curWeightPenalty = 0; private int _curWeightPenalty = 0;
public final L2PetLevelData getPetLevelData() public final L2PetLevelData getPetLevelData()
@@ -1185,15 +1185,15 @@ public class L2PetInstance extends L2Summon
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
if (getId() == 12564) if (getId() == 12564) // TODO: Remove this stupid hardcode.
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.SINEATER_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.SINEATER_XP_RATE, addToSp);
} }
else else
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.PET_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.PET_XP_RATE, addToSp);
} }
} }
@@ -102,7 +102,7 @@ public class L2RaidBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -73,7 +73,7 @@ public class PcStat extends PlayableStat
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
// Allowed to gain exp? // Allowed to gain exp?
if (!getActiveChar().getAccessLevel().canGainExp()) if (!activeChar.getAccessLevel().canGainExp())
{ {
return false; return false;
} }
@@ -98,7 +98,7 @@ public class PcStat extends PlayableStat
return true; return true;
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useBonuses) public void addExpAndSp(double addToExp, double addToSp, boolean useBonuses)
{ {
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
@@ -108,8 +108,8 @@ public class PcStat extends PlayableStat
return; return;
} }
final long baseExp = addToExp; final double baseExp = addToExp;
final long baseSp = addToSp; final double baseSp = addToSp;
double bonusExp = 1.; double bonusExp = 1.;
double bonusSp = 1.; double bonusSp = 1.;
@@ -142,7 +142,7 @@ public class PcStat extends PlayableStat
addToExp *= bonusExp; addToExp *= bonusExp;
addToSp *= bonusSp; addToSp *= bonusSp;
float ratioTakenByPlayer = 0; double ratioTakenByPlayer = 0;
// if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now // if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now
final L2Summon sPet = activeChar.getPet(); final L2Summon sPet = activeChar.getPet();
@@ -160,42 +160,37 @@ public class PcStat extends PlayableStat
if (!pet.isDead()) if (!pet.isDead())
{ {
pet.addExpAndSp((long) (addToExp * (1 - ratioTakenByPlayer)), (int) (addToSp * (1 - ratioTakenByPlayer))); pet.addExpAndSp(addToExp * (1 - ratioTakenByPlayer), addToSp * (1 - ratioTakenByPlayer));
} }
// now adjust the max ratio to avoid the owner earning negative exp/sp // now adjust the max ratio to avoid the owner earning negative exp/sp
addToExp = (long) (addToExp * ratioTakenByPlayer); addToExp *= ratioTakenByPlayer;
addToSp = (int) (addToSp * ratioTakenByPlayer); addToSp *= ratioTakenByPlayer;
} }
if (!addExp(addToExp)) final long finalExp = Math.round(addToExp);
{ final long finalSp = Math.round(addToSp);
addToExp = 0; final boolean expAdded = addExp(finalExp);
} final boolean spAdded = addSp(finalSp);
if (!addSp(addToSp))
{
addToSp = 0;
}
SystemMessage sm = null; SystemMessage sm = null;
if ((addToExp == 0) && (addToSp != 0)) if (!expAdded && spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP);
sm.addLong(addToSp); sm.addLong(finalSp);
} }
else if ((addToSp == 0) && (addToExp != 0)) else if (expAdded && !spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
} }
else else
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4);
sm.addLong(addToExp); sm.addLong(finalExp);
sm.addLong(addToExp - baseExp); sm.addLong(Math.round(addToExp - baseExp));
sm.addLong(addToSp); sm.addLong(finalSp);
sm.addLong(addToSp - baseSp); sm.addLong(Math.round(addToSp - baseSp));
} }
activeChar.sendPacket(sm); activeChar.sendPacket(sm);
} }
@@ -309,6 +304,7 @@ public class PcStat extends PlayableStat
{ {
return false; return false;
} }
final UserInfo ui = new UserInfo(getActiveChar(), false); final UserInfo ui = new UserInfo(getActiveChar(), false);
ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP); ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP);
getActiveChar().sendPacket(ui); getActiveChar().sendPacket(ui);
@@ -41,15 +41,16 @@ public class PetStat extends SummonStat
return true; return true;
} }
public boolean addExpAndSp(long addToExp, long addToSp) public boolean addExpAndSp(double addToExp, double addToSp)
{ {
if (getActiveChar().isUncontrollable() || !addExp(addToExp)) final long finalExp = Math.round(addToExp);
if (getActiveChar().isUncontrollable() || !addExp(finalExp))
{ {
return false; return false;
} }
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP); SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
getActiveChar().updateAndBroadcastStatus(1); getActiveChar().updateAndBroadcastStatus(1);
getActiveChar().sendPacket(sm); getActiveChar().sendPacket(sm);
return true; return true;
@@ -1232,17 +1232,17 @@ public final class Formulas
/** /**
* Calculates karma lost upon death. * Calculates karma lost upon death.
* @param player * @param player
* @param exp * @param finalExp
* @return the amount of karma player has loosed. * @return the amount of karma player has loosed.
*/ */
public static int calculateKarmaLost(L2PcInstance player, long exp) public static int calculateKarmaLost(L2PcInstance player, double finalExp)
{ {
final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel()); final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel());
if (exp > 0) // Received exp if (finalExp > 0) // Received exp
{ {
exp /= Config.RATE_KARMA_LOST; finalExp /= Config.RATE_KARMA_LOST;
} }
return (int) ((Math.abs(exp) / karmaLooseMul) / 30); return (int) ((Math.abs(finalExp) / karmaLooseMul) / 30);
} }
/** /**
@@ -26,7 +26,7 @@ import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public final class PcCafePointsManager public final class PcCafePointsManager
{ {
public void givePcCafePoint(L2PcInstance player, long exp) public void givePcCafePoint(L2PcInstance player, double exp)
{ {
if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed()) if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed())
{ {
@@ -3110,7 +3110,7 @@ public class L2Clan implements IIdentifiable, INamable
* @param target * @param target
* @param value * @param value
*/ */
public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, long value) public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, double value)
{ {
// TODO: Figure out the retail formula // TODO: Figure out the retail formula
final int points = (int) value / 29600; final int points = (int) value / 29600;
@@ -834,7 +834,7 @@ public class L2Party extends AbstractPlayerGroup
* @param partyDmg * @param partyDmg
* @param target * @param target
*/ */
public void distributeXpAndSp(long xpReward, int spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target) public void distributeXpAndSp(double xpReward, double spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target)
{ {
final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl); final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl);
@@ -870,24 +870,24 @@ public class L2Party extends AbstractPlayerGroup
final double preCalculation = (sqLevel / sqLevelSum) * penalty; final double preCalculation = (sqLevel / sqLevelSum) * penalty;
// Add the XP/SP points to the requested party member // Add the XP/SP points to the requested party member
long addexp = Math.round(member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation)); double exp = member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation);
final int addsp = (int) member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation); double sp = member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation);
addexp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, addexp, addsp, target.useVitalityRate()); exp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, exp, sp, target.useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = member.getClan(); final L2Clan clan = member.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (target.useVitalityRate()) if (target.useVitalityRate())
{ {
finalExp *= member.getStat().getExpBonusMultiplier(); finalExp *= member.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(member, target, finalExp); clan.addHuntingPoints(member, target, finalExp);
} }
member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), addexp, target.isRaid()), true, false); member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), exp, target.isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(member, addexp); PcCafePointsManager.getInstance().givePcCafePoint(member, exp);
} }
} }
else else
@@ -897,10 +897,10 @@ public class L2Party extends AbstractPlayerGroup
} }
} }
private long calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, long addExp, int addSp, boolean vit) private double calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, double addExp, double addSp, boolean vit)
{ {
long xp = addExp; double xp = addExp;
int sp = addSp; double sp = addSp;
if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive")) if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive"))
{ {
int i = 0; int i = 0;
@@ -468,9 +468,9 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
final int[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -491,24 +491,24 @@ public class L2Attackable extends L2Npc
// Distribute the Exp and SP between the L2PcInstance and its L2Summon // Distribute the Exp and SP between the L2PcInstance and its L2Summon
if (!attacker.isDead()) if (!attacker.isDead())
{ {
final long addexp = Math.round(attacker.getStat().getValue(Stats.EXPSP_RATE, exp)); exp = attacker.getStat().getValue(Stats.EXPSP_RATE, exp);
final int addsp = (int) attacker.getStat().getValue(Stats.EXPSP_RATE, sp); sp = attacker.getStat().getValue(Stats.EXPSP_RATE, sp);
attacker.addExpAndSp(addexp, addsp, useVitalityRate()); attacker.addExpAndSp(exp, sp, useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = attacker.getClan(); final L2Clan clan = attacker.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (useVitalityRate()) if (useVitalityRate())
{ {
finalExp *= attacker.getStat().getExpBonusMultiplier(); finalExp *= attacker.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(attacker, this, finalExp); clan.addHuntingPoints(attacker, this, finalExp);
} }
attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), addexp, isRaid()), true, false); attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), exp, isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(attacker, addexp); PcCafePointsManager.getInstance().givePcCafePoint(attacker, exp);
} }
} }
} }
@@ -517,7 +517,7 @@ public class L2Attackable extends L2Npc
{ {
// share with party members // share with party members
int partyDmg = 0; int partyDmg = 0;
float partyMul = 1; double partyMul = 1;
int partyLvl = 0; int partyLvl = 0;
// Get all L2Character that can be rewarded in the party // Get all L2Character that can be rewarded in the party
@@ -576,13 +576,13 @@ public class L2Attackable extends L2Npc
// If the party didn't killed this L2Attackable alone // If the party didn't killed this L2Attackable alone
if (partyDmg < totalDamage) if (partyDmg < totalDamage)
{ {
partyMul = ((float) partyDmg / totalDamage); partyMul = ((double) partyDmg / totalDamage);
} }
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
final int[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage); final double[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -1254,11 +1254,11 @@ public class L2Attackable extends L2Npc
* @param totalDamage The total damage done * @param totalDamage The total damage done
* @return * @return
*/ */
private int[] calculateExpAndSp(int charLevel, int damage, long totalDamage) private double[] calculateExpAndSp(int charLevel, int damage, long totalDamage)
{ {
final int levelDiff = Math.abs(charLevel - getLevel()); final int levelDiff = Math.abs(charLevel - getLevel());
double xp = Math.max(0, ((double) getExpReward() * damage) / totalDamage); double xp = Math.max(0, (getExpReward() * damage) / totalDamage);
double sp = Math.max(0, ((double) getSpReward() * damage) / totalDamage); double sp = Math.max(0, (getSpReward() * damage) / totalDamage);
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
@@ -1318,14 +1318,14 @@ public class L2Attackable extends L2Npc
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
return new int[] return new double[]
{ {
(int) xp, xp,
(int) sp sp
}; };
} }
public long calculateOverhitExp(long normalExp) public double calculateOverhitExp(double exp)
{ {
// Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable // Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable
double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp()); double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp());
@@ -1338,10 +1338,7 @@ public class L2Attackable extends L2Npc
// Get the overhit exp bonus according to the above over-hit damage percentage // Get the overhit exp bonus according to the above over-hit damage percentage
// (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...) // (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...)
final double overhitExp = ((overhitPercentage / 100) * normalExp); return (overhitPercentage / 100) * exp;
// Return the rounded amount of exp points to be added to the player's normal exp reward
return Math.round(overhitExp);
} }
/** /**
@@ -1594,7 +1591,7 @@ public class L2Attackable extends L2Npc
/* /*
* Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp. * Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp.
*/ */
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
if ((getLevel() <= 0) || (getExpReward() <= 0)) if ((getLevel() <= 0) || (getExpReward() <= 0))
{ {
@@ -1604,11 +1601,11 @@ public class L2Attackable extends L2Npc
int points; int points;
if (level < 85) if (level < 85)
{ {
points = (int) ((exp / 1000) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / 1000) * Math.max(level - getLevel(), 1)), 1);
} }
else else
{ {
points = (int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)), 1);
} }
return -points; return -points;
@@ -3797,7 +3797,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
* @param addToExp * @param addToExp
* @param addToSp * @param addToSp
*/ */
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
// Dummy method (overridden by players and pets) // Dummy method (overridden by players and pets)
} }
@@ -54,7 +54,7 @@ public final class L2GrandBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -10411,12 +10411,12 @@ public final class L2PcInstance extends L2Playable
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
getStat().addExpAndSp(addToExp, addToSp, false); getStat().addExpAndSp(addToExp, addToSp, false);
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useVitality) public void addExpAndSp(double addToExp, double addToSp, boolean useVitality)
{ {
getStat().addExpAndSp(addToExp, addToSp, useVitality); getStat().addExpAndSp(addToExp, addToSp, useVitality);
} }
@@ -93,7 +93,7 @@ public class L2PetInstance extends L2Summon
private L2PetLevelData _leveldata; private L2PetLevelData _leveldata;
/** The Experience before the last Death Penalty */ /** The Experience before the last Death Penalty */
private long _expBeforeDeath = 0; private double _expBeforeDeath = 0;
private int _curWeightPenalty = 0; private int _curWeightPenalty = 0;
public final L2PetLevelData getPetLevelData() public final L2PetLevelData getPetLevelData()
@@ -1185,15 +1185,15 @@ public class L2PetInstance extends L2Summon
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
if (getId() == 12564) if (getId() == 12564) // TODO: Remove this stupid hardcode.
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.SINEATER_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.SINEATER_XP_RATE, addToSp);
} }
else else
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.PET_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.PET_XP_RATE, addToSp);
} }
} }
@@ -102,7 +102,7 @@ public class L2RaidBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -73,7 +73,7 @@ public class PcStat extends PlayableStat
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
// Allowed to gain exp? // Allowed to gain exp?
if (!getActiveChar().getAccessLevel().canGainExp()) if (!activeChar.getAccessLevel().canGainExp())
{ {
return false; return false;
} }
@@ -98,7 +98,7 @@ public class PcStat extends PlayableStat
return true; return true;
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useBonuses) public void addExpAndSp(double addToExp, double addToSp, boolean useBonuses)
{ {
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
@@ -108,8 +108,8 @@ public class PcStat extends PlayableStat
return; return;
} }
final long baseExp = addToExp; final double baseExp = addToExp;
final long baseSp = addToSp; final double baseSp = addToSp;
double bonusExp = 1.; double bonusExp = 1.;
double bonusSp = 1.; double bonusSp = 1.;
@@ -142,7 +142,7 @@ public class PcStat extends PlayableStat
addToExp *= bonusExp; addToExp *= bonusExp;
addToSp *= bonusSp; addToSp *= bonusSp;
float ratioTakenByPlayer = 0; double ratioTakenByPlayer = 0;
// if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now // if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now
final L2Summon sPet = activeChar.getPet(); final L2Summon sPet = activeChar.getPet();
@@ -160,42 +160,37 @@ public class PcStat extends PlayableStat
if (!pet.isDead()) if (!pet.isDead())
{ {
pet.addExpAndSp((long) (addToExp * (1 - ratioTakenByPlayer)), (int) (addToSp * (1 - ratioTakenByPlayer))); pet.addExpAndSp(addToExp * (1 - ratioTakenByPlayer), addToSp * (1 - ratioTakenByPlayer));
} }
// now adjust the max ratio to avoid the owner earning negative exp/sp // now adjust the max ratio to avoid the owner earning negative exp/sp
addToExp = (long) (addToExp * ratioTakenByPlayer); addToExp *= ratioTakenByPlayer;
addToSp = (int) (addToSp * ratioTakenByPlayer); addToSp *= ratioTakenByPlayer;
} }
if (!addExp(addToExp)) final long finalExp = Math.round(addToExp);
{ final long finalSp = Math.round(addToSp);
addToExp = 0; final boolean expAdded = addExp(finalExp);
} final boolean spAdded = addSp(finalSp);
if (!addSp(addToSp))
{
addToSp = 0;
}
SystemMessage sm = null; SystemMessage sm = null;
if ((addToExp == 0) && (addToSp != 0)) if (!expAdded && spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP);
sm.addLong(addToSp); sm.addLong(finalSp);
} }
else if ((addToSp == 0) && (addToExp != 0)) else if (expAdded && !spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
} }
else else
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4);
sm.addLong(addToExp); sm.addLong(finalExp);
sm.addLong(addToExp - baseExp); sm.addLong(Math.round(addToExp - baseExp));
sm.addLong(addToSp); sm.addLong(finalSp);
sm.addLong(addToSp - baseSp); sm.addLong(Math.round(addToSp - baseSp));
} }
activeChar.sendPacket(sm); activeChar.sendPacket(sm);
} }
@@ -309,6 +304,7 @@ public class PcStat extends PlayableStat
{ {
return false; return false;
} }
final UserInfo ui = new UserInfo(getActiveChar(), false); final UserInfo ui = new UserInfo(getActiveChar(), false);
ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP); ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP);
getActiveChar().sendPacket(ui); getActiveChar().sendPacket(ui);
@@ -41,15 +41,16 @@ public class PetStat extends SummonStat
return true; return true;
} }
public boolean addExpAndSp(long addToExp, long addToSp) public boolean addExpAndSp(double addToExp, double addToSp)
{ {
if (getActiveChar().isUncontrollable() || !addExp(addToExp)) final long finalExp = Math.round(addToExp);
if (getActiveChar().isUncontrollable() || !addExp(finalExp))
{ {
return false; return false;
} }
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP); SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
getActiveChar().updateAndBroadcastStatus(1); getActiveChar().updateAndBroadcastStatus(1);
getActiveChar().sendPacket(sm); getActiveChar().sendPacket(sm);
return true; return true;
@@ -1232,17 +1232,17 @@ public final class Formulas
/** /**
* Calculates karma lost upon death. * Calculates karma lost upon death.
* @param player * @param player
* @param exp * @param finalExp
* @return the amount of karma player has loosed. * @return the amount of karma player has loosed.
*/ */
public static int calculateKarmaLost(L2PcInstance player, long exp) public static int calculateKarmaLost(L2PcInstance player, double finalExp)
{ {
final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel()); final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel());
if (exp > 0) // Received exp if (finalExp > 0) // Received exp
{ {
exp /= Config.RATE_KARMA_LOST; finalExp /= Config.RATE_KARMA_LOST;
} }
return (int) ((Math.abs(exp) / karmaLooseMul) / 30); return (int) ((Math.abs(finalExp) / karmaLooseMul) / 30);
} }
/** /**
@@ -26,7 +26,7 @@ import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public final class PcCafePointsManager public final class PcCafePointsManager
{ {
public void givePcCafePoint(L2PcInstance player, long exp) public void givePcCafePoint(L2PcInstance player, double exp)
{ {
if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed()) if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed())
{ {
@@ -3110,7 +3110,7 @@ public class L2Clan implements IIdentifiable, INamable
* @param target * @param target
* @param value * @param value
*/ */
public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, long value) public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, double value)
{ {
// TODO: Figure out the retail formula // TODO: Figure out the retail formula
final int points = (int) value / 29600; final int points = (int) value / 29600;
@@ -834,7 +834,7 @@ public class L2Party extends AbstractPlayerGroup
* @param partyDmg * @param partyDmg
* @param target * @param target
*/ */
public void distributeXpAndSp(long xpReward, int spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target) public void distributeXpAndSp(double xpReward, double spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target)
{ {
final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl); final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl);
@@ -870,24 +870,24 @@ public class L2Party extends AbstractPlayerGroup
final double preCalculation = (sqLevel / sqLevelSum) * penalty; final double preCalculation = (sqLevel / sqLevelSum) * penalty;
// Add the XP/SP points to the requested party member // Add the XP/SP points to the requested party member
long addexp = Math.round(member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation)); double exp = member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation);
final int addsp = (int) member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation); double sp = member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation);
addexp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, addexp, addsp, target.useVitalityRate()); exp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, exp, sp, target.useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = member.getClan(); final L2Clan clan = member.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (target.useVitalityRate()) if (target.useVitalityRate())
{ {
finalExp *= member.getStat().getExpBonusMultiplier(); finalExp *= member.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(member, target, finalExp); clan.addHuntingPoints(member, target, finalExp);
} }
member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), addexp, target.isRaid()), true, false); member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), exp, target.isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(member, addexp); PcCafePointsManager.getInstance().givePcCafePoint(member, exp);
} }
} }
else else
@@ -897,10 +897,10 @@ public class L2Party extends AbstractPlayerGroup
} }
} }
private long calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, long addExp, int addSp, boolean vit) private double calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, double addExp, double addSp, boolean vit)
{ {
long xp = addExp; double xp = addExp;
int sp = addSp; double sp = addSp;
if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive")) if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive"))
{ {
int i = 0; int i = 0;
@@ -468,9 +468,9 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
final int[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -491,24 +491,24 @@ public class L2Attackable extends L2Npc
// Distribute the Exp and SP between the L2PcInstance and its L2Summon // Distribute the Exp and SP between the L2PcInstance and its L2Summon
if (!attacker.isDead()) if (!attacker.isDead())
{ {
final long addexp = Math.round(attacker.getStat().getValue(Stats.EXPSP_RATE, exp)); exp = attacker.getStat().getValue(Stats.EXPSP_RATE, exp);
final int addsp = (int) attacker.getStat().getValue(Stats.EXPSP_RATE, sp); sp = attacker.getStat().getValue(Stats.EXPSP_RATE, sp);
attacker.addExpAndSp(addexp, addsp, useVitalityRate()); attacker.addExpAndSp(exp, sp, useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = attacker.getClan(); final L2Clan clan = attacker.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (useVitalityRate()) if (useVitalityRate())
{ {
finalExp *= attacker.getStat().getExpBonusMultiplier(); finalExp *= attacker.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(attacker, this, finalExp); clan.addHuntingPoints(attacker, this, finalExp);
} }
attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), addexp, isRaid()), true, false); attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), exp, isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(attacker, addexp); PcCafePointsManager.getInstance().givePcCafePoint(attacker, exp);
} }
} }
} }
@@ -517,7 +517,7 @@ public class L2Attackable extends L2Npc
{ {
// share with party members // share with party members
int partyDmg = 0; int partyDmg = 0;
float partyMul = 1; double partyMul = 1;
int partyLvl = 0; int partyLvl = 0;
// Get all L2Character that can be rewarded in the party // Get all L2Character that can be rewarded in the party
@@ -576,13 +576,13 @@ public class L2Attackable extends L2Npc
// If the party didn't killed this L2Attackable alone // If the party didn't killed this L2Attackable alone
if (partyDmg < totalDamage) if (partyDmg < totalDamage)
{ {
partyMul = ((float) partyDmg / totalDamage); partyMul = ((double) partyDmg / totalDamage);
} }
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
final int[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage); final double[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -1254,11 +1254,11 @@ public class L2Attackable extends L2Npc
* @param totalDamage The total damage done * @param totalDamage The total damage done
* @return * @return
*/ */
private int[] calculateExpAndSp(int charLevel, int damage, long totalDamage) private double[] calculateExpAndSp(int charLevel, int damage, long totalDamage)
{ {
final int levelDiff = Math.abs(charLevel - getLevel()); final int levelDiff = Math.abs(charLevel - getLevel());
double xp = Math.max(0, ((double) getExpReward() * damage) / totalDamage); double xp = Math.max(0, (getExpReward() * damage) / totalDamage);
double sp = Math.max(0, ((double) getSpReward() * damage) / totalDamage); double sp = Math.max(0, (getSpReward() * damage) / totalDamage);
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
@@ -1318,14 +1318,14 @@ public class L2Attackable extends L2Npc
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
return new int[] return new double[]
{ {
(int) xp, xp,
(int) sp sp
}; };
} }
public long calculateOverhitExp(long normalExp) public double calculateOverhitExp(double exp)
{ {
// Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable // Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable
double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp()); double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp());
@@ -1338,10 +1338,7 @@ public class L2Attackable extends L2Npc
// Get the overhit exp bonus according to the above over-hit damage percentage // Get the overhit exp bonus according to the above over-hit damage percentage
// (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...) // (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...)
final double overhitExp = ((overhitPercentage / 100) * normalExp); return (overhitPercentage / 100) * exp;
// Return the rounded amount of exp points to be added to the player's normal exp reward
return Math.round(overhitExp);
} }
/** /**
@@ -1594,7 +1591,7 @@ public class L2Attackable extends L2Npc
/* /*
* Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp. * Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp.
*/ */
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
if ((getLevel() <= 0) || (getExpReward() <= 0)) if ((getLevel() <= 0) || (getExpReward() <= 0))
{ {
@@ -1604,11 +1601,11 @@ public class L2Attackable extends L2Npc
int points; int points;
if (level < 85) if (level < 85)
{ {
points = (int) ((exp / 1000) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / 1000) * Math.max(level - getLevel(), 1)), 1);
} }
else else
{ {
points = (int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)), 1);
} }
return -points; return -points;
@@ -3797,7 +3797,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
* @param addToExp * @param addToExp
* @param addToSp * @param addToSp
*/ */
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
// Dummy method (overridden by players and pets) // Dummy method (overridden by players and pets)
} }
@@ -54,7 +54,7 @@ public final class L2GrandBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -10410,12 +10410,12 @@ public final class L2PcInstance extends L2Playable
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
getStat().addExpAndSp(addToExp, addToSp, false); getStat().addExpAndSp(addToExp, addToSp, false);
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useVitality) public void addExpAndSp(double addToExp, double addToSp, boolean useVitality)
{ {
getStat().addExpAndSp(addToExp, addToSp, useVitality); getStat().addExpAndSp(addToExp, addToSp, useVitality);
} }
@@ -93,7 +93,7 @@ public class L2PetInstance extends L2Summon
private L2PetLevelData _leveldata; private L2PetLevelData _leveldata;
/** The Experience before the last Death Penalty */ /** The Experience before the last Death Penalty */
private long _expBeforeDeath = 0; private double _expBeforeDeath = 0;
private int _curWeightPenalty = 0; private int _curWeightPenalty = 0;
public final L2PetLevelData getPetLevelData() public final L2PetLevelData getPetLevelData()
@@ -1185,15 +1185,15 @@ public class L2PetInstance extends L2Summon
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
if (getId() == 12564) if (getId() == 12564) // TODO: Remove this stupid hardcode.
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.SINEATER_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.SINEATER_XP_RATE, addToSp);
} }
else else
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.PET_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.PET_XP_RATE, addToSp);
} }
} }
@@ -102,7 +102,7 @@ public class L2RaidBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -73,7 +73,7 @@ public class PcStat extends PlayableStat
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
// Allowed to gain exp? // Allowed to gain exp?
if (!getActiveChar().getAccessLevel().canGainExp()) if (!activeChar.getAccessLevel().canGainExp())
{ {
return false; return false;
} }
@@ -98,7 +98,7 @@ public class PcStat extends PlayableStat
return true; return true;
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useBonuses) public void addExpAndSp(double addToExp, double addToSp, boolean useBonuses)
{ {
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
@@ -108,8 +108,8 @@ public class PcStat extends PlayableStat
return; return;
} }
final long baseExp = addToExp; final double baseExp = addToExp;
final long baseSp = addToSp; final double baseSp = addToSp;
double bonusExp = 1.; double bonusExp = 1.;
double bonusSp = 1.; double bonusSp = 1.;
@@ -142,7 +142,7 @@ public class PcStat extends PlayableStat
addToExp *= bonusExp; addToExp *= bonusExp;
addToSp *= bonusSp; addToSp *= bonusSp;
float ratioTakenByPlayer = 0; double ratioTakenByPlayer = 0;
// if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now // if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now
final L2Summon sPet = activeChar.getPet(); final L2Summon sPet = activeChar.getPet();
@@ -160,42 +160,37 @@ public class PcStat extends PlayableStat
if (!pet.isDead()) if (!pet.isDead())
{ {
pet.addExpAndSp((long) (addToExp * (1 - ratioTakenByPlayer)), (int) (addToSp * (1 - ratioTakenByPlayer))); pet.addExpAndSp(addToExp * (1 - ratioTakenByPlayer), addToSp * (1 - ratioTakenByPlayer));
} }
// now adjust the max ratio to avoid the owner earning negative exp/sp // now adjust the max ratio to avoid the owner earning negative exp/sp
addToExp = (long) (addToExp * ratioTakenByPlayer); addToExp *= ratioTakenByPlayer;
addToSp = (int) (addToSp * ratioTakenByPlayer); addToSp *= ratioTakenByPlayer;
} }
if (!addExp(addToExp)) final long finalExp = Math.round(addToExp);
{ final long finalSp = Math.round(addToSp);
addToExp = 0; final boolean expAdded = addExp(finalExp);
} final boolean spAdded = addSp(finalSp);
if (!addSp(addToSp))
{
addToSp = 0;
}
SystemMessage sm = null; SystemMessage sm = null;
if ((addToExp == 0) && (addToSp != 0)) if (!expAdded && spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP);
sm.addLong(addToSp); sm.addLong(finalSp);
} }
else if ((addToSp == 0) && (addToExp != 0)) else if (expAdded && !spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
} }
else else
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4);
sm.addLong(addToExp); sm.addLong(finalExp);
sm.addLong(addToExp - baseExp); sm.addLong(Math.round(addToExp - baseExp));
sm.addLong(addToSp); sm.addLong(finalSp);
sm.addLong(addToSp - baseSp); sm.addLong(Math.round(addToSp - baseSp));
} }
activeChar.sendPacket(sm); activeChar.sendPacket(sm);
} }
@@ -309,6 +304,7 @@ public class PcStat extends PlayableStat
{ {
return false; return false;
} }
final UserInfo ui = new UserInfo(getActiveChar(), false); final UserInfo ui = new UserInfo(getActiveChar(), false);
ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP); ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP);
getActiveChar().sendPacket(ui); getActiveChar().sendPacket(ui);
@@ -41,15 +41,16 @@ public class PetStat extends SummonStat
return true; return true;
} }
public boolean addExpAndSp(long addToExp, long addToSp) public boolean addExpAndSp(double addToExp, double addToSp)
{ {
if (getActiveChar().isUncontrollable() || !addExp(addToExp)) final long finalExp = Math.round(addToExp);
if (getActiveChar().isUncontrollable() || !addExp(finalExp))
{ {
return false; return false;
} }
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP); SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
getActiveChar().updateAndBroadcastStatus(1); getActiveChar().updateAndBroadcastStatus(1);
getActiveChar().sendPacket(sm); getActiveChar().sendPacket(sm);
return true; return true;
@@ -1232,17 +1232,17 @@ public final class Formulas
/** /**
* Calculates karma lost upon death. * Calculates karma lost upon death.
* @param player * @param player
* @param exp * @param finalExp
* @return the amount of karma player has loosed. * @return the amount of karma player has loosed.
*/ */
public static int calculateKarmaLost(L2PcInstance player, long exp) public static int calculateKarmaLost(L2PcInstance player, double finalExp)
{ {
final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel()); final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel());
if (exp > 0) // Received exp if (finalExp > 0) // Received exp
{ {
exp /= Config.RATE_KARMA_LOST; finalExp /= Config.RATE_KARMA_LOST;
} }
return (int) ((Math.abs(exp) / karmaLooseMul) / 30); return (int) ((Math.abs(finalExp) / karmaLooseMul) / 30);
} }
/** /**
@@ -26,7 +26,7 @@ import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public final class PcCafePointsManager public final class PcCafePointsManager
{ {
public void givePcCafePoint(L2PcInstance player, long exp) public void givePcCafePoint(L2PcInstance player, double exp)
{ {
if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed()) if (!Config.PC_CAFE_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed())
{ {
@@ -3110,7 +3110,7 @@ public class L2Clan implements IIdentifiable, INamable
* @param target * @param target
* @param value * @param value
*/ */
public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, long value) public synchronized void addHuntingPoints(L2PcInstance activeChar, L2Npc target, double value)
{ {
// TODO: Figure out the retail formula // TODO: Figure out the retail formula
final int points = (int) value / 29600; final int points = (int) value / 29600;
@@ -834,7 +834,7 @@ public class L2Party extends AbstractPlayerGroup
* @param partyDmg * @param partyDmg
* @param target * @param target
*/ */
public void distributeXpAndSp(long xpReward, int spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target) public void distributeXpAndSp(double xpReward, double spReward, List<L2PcInstance> rewardedMembers, int topLvl, int partyDmg, L2Attackable target)
{ {
final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl); final List<L2PcInstance> validMembers = getValidMembers(rewardedMembers, topLvl);
@@ -870,24 +870,24 @@ public class L2Party extends AbstractPlayerGroup
final double preCalculation = (sqLevel / sqLevelSum) * penalty; final double preCalculation = (sqLevel / sqLevelSum) * penalty;
// Add the XP/SP points to the requested party member // Add the XP/SP points to the requested party member
long addexp = Math.round(member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation)); double exp = member.getStat().getValue(Stats.EXPSP_RATE, xpReward * preCalculation);
final int addsp = (int) member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation); double sp = member.getStat().getValue(Stats.EXPSP_RATE, spReward * preCalculation);
addexp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, addexp, addsp, target.useVitalityRate()); exp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, exp, sp, target.useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = member.getClan(); final L2Clan clan = member.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (target.useVitalityRate()) if (target.useVitalityRate())
{ {
finalExp *= member.getStat().getExpBonusMultiplier(); finalExp *= member.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(member, target, finalExp); clan.addHuntingPoints(member, target, finalExp);
} }
member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), addexp, target.isRaid()), true, false); member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), exp, target.isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(member, addexp); PcCafePointsManager.getInstance().givePcCafePoint(member, exp);
} }
} }
else else
@@ -897,10 +897,10 @@ public class L2Party extends AbstractPlayerGroup
} }
} }
private long calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, long addExp, int addSp, boolean vit) private double calculateExpSpPartyCutoff(L2PcInstance player, int topLvl, double addExp, double addSp, boolean vit)
{ {
long xp = addExp; double xp = addExp;
int sp = addSp; double sp = addSp;
if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive")) if (Config.PARTY_XP_CUTOFF_METHOD.equalsIgnoreCase("highfive"))
{ {
int i = 0; int i = 0;
@@ -468,9 +468,9 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
final int[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -491,24 +491,24 @@ public class L2Attackable extends L2Npc
// Distribute the Exp and SP between the L2PcInstance and its L2Summon // Distribute the Exp and SP between the L2PcInstance and its L2Summon
if (!attacker.isDead()) if (!attacker.isDead())
{ {
final long addexp = Math.round(attacker.getStat().getValue(Stats.EXPSP_RATE, exp)); exp = attacker.getStat().getValue(Stats.EXPSP_RATE, exp);
final int addsp = (int) attacker.getStat().getValue(Stats.EXPSP_RATE, sp); sp = attacker.getStat().getValue(Stats.EXPSP_RATE, sp);
attacker.addExpAndSp(addexp, addsp, useVitalityRate()); attacker.addExpAndSp(exp, sp, useVitalityRate());
if (addexp > 0) if (exp > 0)
{ {
final L2Clan clan = attacker.getClan(); final L2Clan clan = attacker.getClan();
if (clan != null) if (clan != null)
{ {
long finalExp = addexp; double finalExp = exp;
if (useVitalityRate()) if (useVitalityRate())
{ {
finalExp *= attacker.getStat().getExpBonusMultiplier(); finalExp *= attacker.getStat().getExpBonusMultiplier();
} }
clan.addHuntingPoints(attacker, this, finalExp); clan.addHuntingPoints(attacker, this, finalExp);
} }
attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), addexp, isRaid()), true, false); attacker.updateVitalityPoints(getVitalityPoints(attacker.getLevel(), exp, isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(attacker, addexp); PcCafePointsManager.getInstance().givePcCafePoint(attacker, exp);
} }
} }
} }
@@ -517,7 +517,7 @@ public class L2Attackable extends L2Npc
{ {
// share with party members // share with party members
int partyDmg = 0; int partyDmg = 0;
float partyMul = 1; double partyMul = 1;
int partyLvl = 0; int partyLvl = 0;
// Get all L2Character that can be rewarded in the party // Get all L2Character that can be rewarded in the party
@@ -576,13 +576,13 @@ public class L2Attackable extends L2Npc
// If the party didn't killed this L2Attackable alone // If the party didn't killed this L2Attackable alone
if (partyDmg < totalDamage) if (partyDmg < totalDamage)
{ {
partyMul = ((float) partyDmg / totalDamage); partyMul = ((double) partyDmg / totalDamage);
} }
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
final int[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage); final double[] expSp = calculateExpAndSp(partyLvl, partyDmg, totalDamage);
long exp = expSp[0]; double exp = expSp[0];
int sp = expSp[1]; double sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@@ -1254,11 +1254,11 @@ public class L2Attackable extends L2Npc
* @param totalDamage The total damage done * @param totalDamage The total damage done
* @return * @return
*/ */
private int[] calculateExpAndSp(int charLevel, int damage, long totalDamage) private double[] calculateExpAndSp(int charLevel, int damage, long totalDamage)
{ {
final int levelDiff = Math.abs(charLevel - getLevel()); final int levelDiff = Math.abs(charLevel - getLevel());
double xp = Math.max(0, ((double) getExpReward() * damage) / totalDamage); double xp = Math.max(0, (getExpReward() * damage) / totalDamage);
double sp = Math.max(0, ((double) getSpReward() * damage) / totalDamage); double sp = Math.max(0, (getSpReward() * damage) / totalDamage);
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
@@ -1318,14 +1318,14 @@ public class L2Attackable extends L2Npc
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
return new int[] return new double[]
{ {
(int) xp, xp,
(int) sp sp
}; };
} }
public long calculateOverhitExp(long normalExp) public double calculateOverhitExp(double exp)
{ {
// Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable // Get the percentage based on the total of extra (over-hit) damage done relative to the total (maximum) ammount of HP on the L2Attackable
double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp()); double overhitPercentage = ((getOverhitDamage() * 100) / getMaxHp());
@@ -1338,10 +1338,7 @@ public class L2Attackable extends L2Npc
// Get the overhit exp bonus according to the above over-hit damage percentage // Get the overhit exp bonus according to the above over-hit damage percentage
// (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...) // (1/1 basis - 13% of over-hit damage, 13% of extra exp is given, and so on...)
final double overhitExp = ((overhitPercentage / 100) * normalExp); return (overhitPercentage / 100) * exp;
// Return the rounded amount of exp points to be added to the player's normal exp reward
return Math.round(overhitExp);
} }
/** /**
@@ -1594,7 +1591,7 @@ public class L2Attackable extends L2Npc
/* /*
* Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp. * Return vitality points decrease (if positive) or increase (if negative) based on damage. Maximum for damage = maxHp.
*/ */
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
if ((getLevel() <= 0) || (getExpReward() <= 0)) if ((getLevel() <= 0) || (getExpReward() <= 0))
{ {
@@ -1604,11 +1601,11 @@ public class L2Attackable extends L2Npc
int points; int points;
if (level < 85) if (level < 85)
{ {
points = (int) ((exp / 1000) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / 1000) * Math.max(level - getLevel(), 1)), 1);
} }
else else
{ {
points = (int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)); points = Math.max((int) ((exp / (isBoss ? Config.VITALITY_CONSUME_BY_BOSS : Config.VITALITY_CONSUME_BY_MOB)) * Math.max(level - getLevel(), 1)), 1);
} }
return -points; return -points;
@@ -3797,7 +3797,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
* @param addToExp * @param addToExp
* @param addToSp * @param addToSp
*/ */
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
// Dummy method (overridden by players and pets) // Dummy method (overridden by players and pets)
} }
@@ -54,7 +54,7 @@ public final class L2GrandBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -10344,12 +10344,12 @@ public final class L2PcInstance extends L2Playable
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
getStat().addExpAndSp(addToExp, addToSp, false); getStat().addExpAndSp(addToExp, addToSp, false);
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useVitality) public void addExpAndSp(double addToExp, double addToSp, boolean useVitality)
{ {
getStat().addExpAndSp(addToExp, addToSp, useVitality); getStat().addExpAndSp(addToExp, addToSp, useVitality);
} }
@@ -93,7 +93,7 @@ public class L2PetInstance extends L2Summon
private L2PetLevelData _leveldata; private L2PetLevelData _leveldata;
/** The Experience before the last Death Penalty */ /** The Experience before the last Death Penalty */
private long _expBeforeDeath = 0; private double _expBeforeDeath = 0;
private int _curWeightPenalty = 0; private int _curWeightPenalty = 0;
public final L2PetLevelData getPetLevelData() public final L2PetLevelData getPetLevelData()
@@ -1185,15 +1185,15 @@ public class L2PetInstance extends L2Summon
} }
@Override @Override
public void addExpAndSp(long addToExp, long addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
if (getId() == 12564) if (getId() == 12564) // TODO: Remove this stupid hardcode.
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.SINEATER_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.SINEATER_XP_RATE, addToSp);
} }
else else
{ {
getStat().addExpAndSp(Math.round(addToExp * Config.PET_XP_RATE), addToSp); getStat().addExpAndSp(addToExp * Config.PET_XP_RATE, addToSp);
} }
} }
@@ -102,7 +102,7 @@ public class L2RaidBossInstance extends L2MonsterInstance
} }
@Override @Override
public int getVitalityPoints(int level, long exp, boolean isBoss) public int getVitalityPoints(int level, double exp, boolean isBoss)
{ {
return -super.getVitalityPoints(level, exp, isBoss); return -super.getVitalityPoints(level, exp, isBoss);
} }
@@ -73,7 +73,7 @@ public class PcStat extends PlayableStat
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
// Allowed to gain exp? // Allowed to gain exp?
if (!getActiveChar().getAccessLevel().canGainExp()) if (!activeChar.getAccessLevel().canGainExp())
{ {
return false; return false;
} }
@@ -98,7 +98,7 @@ public class PcStat extends PlayableStat
return true; return true;
} }
public void addExpAndSp(long addToExp, long addToSp, boolean useBonuses) public void addExpAndSp(double addToExp, double addToSp, boolean useBonuses)
{ {
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
@@ -108,8 +108,8 @@ public class PcStat extends PlayableStat
return; return;
} }
final long baseExp = addToExp; final double baseExp = addToExp;
final long baseSp = addToSp; final double baseSp = addToSp;
double bonusExp = 1.; double bonusExp = 1.;
double bonusSp = 1.; double bonusSp = 1.;
@@ -142,7 +142,7 @@ public class PcStat extends PlayableStat
addToExp *= bonusExp; addToExp *= bonusExp;
addToSp *= bonusSp; addToSp *= bonusSp;
float ratioTakenByPlayer = 0; double ratioTakenByPlayer = 0;
// if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now // if this player has a pet and it is in his range he takes from the owner's Exp, give the pet Exp now
final L2Summon sPet = activeChar.getPet(); final L2Summon sPet = activeChar.getPet();
@@ -160,42 +160,37 @@ public class PcStat extends PlayableStat
if (!pet.isDead()) if (!pet.isDead())
{ {
pet.addExpAndSp((long) (addToExp * (1 - ratioTakenByPlayer)), (int) (addToSp * (1 - ratioTakenByPlayer))); pet.addExpAndSp(addToExp * (1 - ratioTakenByPlayer), addToSp * (1 - ratioTakenByPlayer));
} }
// now adjust the max ratio to avoid the owner earning negative exp/sp // now adjust the max ratio to avoid the owner earning negative exp/sp
addToExp = (long) (addToExp * ratioTakenByPlayer); addToExp *= ratioTakenByPlayer;
addToSp = (int) (addToSp * ratioTakenByPlayer); addToSp *= ratioTakenByPlayer;
} }
if (!addExp(addToExp)) final long finalExp = Math.round(addToExp);
{ final long finalSp = Math.round(addToSp);
addToExp = 0; final boolean expAdded = addExp(finalExp);
} final boolean spAdded = addSp(finalSp);
if (!addSp(addToSp))
{
addToSp = 0;
}
SystemMessage sm = null; SystemMessage sm = null;
if ((addToExp == 0) && (addToSp != 0)) if (!expAdded && spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_SP);
sm.addLong(addToSp); sm.addLong(finalSp);
} }
else if ((addToSp == 0) && (addToExp != 0)) else if (expAdded && !spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
} }
else else
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_XP_BONUS_S2_AND_S3_SP_BONUS_S4);
sm.addLong(addToExp); sm.addLong(finalExp);
sm.addLong(addToExp - baseExp); sm.addLong(Math.round(addToExp - baseExp));
sm.addLong(addToSp); sm.addLong(finalSp);
sm.addLong(addToSp - baseSp); sm.addLong(Math.round(addToSp - baseSp));
} }
activeChar.sendPacket(sm); activeChar.sendPacket(sm);
} }
@@ -309,6 +304,7 @@ public class PcStat extends PlayableStat
{ {
return false; return false;
} }
final UserInfo ui = new UserInfo(getActiveChar(), false); final UserInfo ui = new UserInfo(getActiveChar(), false);
ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP); ui.addComponentType(UserInfoType.CURRENT_HPMPCP_EXP_SP);
getActiveChar().sendPacket(ui); getActiveChar().sendPacket(ui);
@@ -41,15 +41,16 @@ public class PetStat extends SummonStat
return true; return true;
} }
public boolean addExpAndSp(long addToExp, long addToSp) public boolean addExpAndSp(double addToExp, double addToSp)
{ {
if (getActiveChar().isUncontrollable() || !addExp(addToExp)) final long finalExp = Math.round(addToExp);
if (getActiveChar().isUncontrollable() || !addExp(finalExp))
{ {
return false; return false;
} }
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP); SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_XP);
sm.addLong(addToExp); sm.addLong(finalExp);
getActiveChar().updateAndBroadcastStatus(1); getActiveChar().updateAndBroadcastStatus(1);
getActiveChar().sendPacket(sm); getActiveChar().sendPacket(sm);
return true; return true;
@@ -1232,17 +1232,17 @@ public final class Formulas
/** /**
* Calculates karma lost upon death. * Calculates karma lost upon death.
* @param player * @param player
* @param exp * @param finalExp
* @return the amount of karma player has loosed. * @return the amount of karma player has loosed.
*/ */
public static int calculateKarmaLost(L2PcInstance player, long exp) public static int calculateKarmaLost(L2PcInstance player, double finalExp)
{ {
final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel()); final double karmaLooseMul = KarmaData.getInstance().getMultiplier(player.getLevel());
if (exp > 0) // Received exp if (finalExp > 0) // Received exp
{ {
exp /= Config.RATE_KARMA_LOST; finalExp /= Config.RATE_KARMA_LOST;
} }
return (int) ((Math.abs(exp) / karmaLooseMul) / 30); return (int) ((Math.abs(finalExp) / karmaLooseMul) / 30);
} }
/** /**