Changed bonus exp/sp calculations.

This commit is contained in:
MobiusDev 2018-04-11 07:18:25 +00:00
parent 765ca8f160
commit f96eacc903
26 changed files with 549 additions and 502 deletions

View File

@ -473,6 +473,10 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
// Calculate the difference of level between this attacker (player or servitor owner) and the L2Attackable
// mob = 24, atk = 10, diff = -14 (full xp)
// mob = 24, atk = 28, diff = 4 (some xp)
// mob = 24, atk = 50, diff = 26 (no xp)
final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
double exp = expSp[0]; double exp = expSp[0];
double sp = expSp[1]; double sp = expSp[1];
@ -1356,67 +1360,70 @@ public class L2Attackable extends L2Npc
*/ */
private double[] 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 = charLevel - getLevel();
double xp = Math.max(0, (getExpReward() * damage) / totalDamage); double xp = 0;
double sp = Math.max(0, (getSpReward() * damage) / totalDamage); double sp = 0;
if ((levelDiff < 11) && (levelDiff > -11))
{
xp = Math.max(0, (getExpReward() * damage) / totalDamage);
sp = Math.max(0, (getSpReward() * damage) / totalDamage);
if ((charLevel > 84) && (levelDiff <= -3))
{
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
case 0: case -3:
case 1:
case 2:
{
mul = 1.;
break;
}
case 3:
{ {
mul = 0.97; mul = 0.97;
break; break;
} }
case 4: case -4:
{ {
mul = 0.67; mul = 0.67;
break; break;
} }
case 5: case -5:
{ {
mul = 0.42; mul = 0.42;
break; break;
} }
case 6: case -6:
{ {
mul = 0.25; mul = 0.25;
break; break;
} }
case 7: case -7:
{ {
mul = 0.15; mul = 0.15;
break; break;
} }
case 8: case -8:
{ {
mul = 0.09; mul = 0.09;
break; break;
} }
case 9: case -9:
{ {
mul = 0.05; mul = 0.05;
break; break;
} }
case 10: case -10:
{ {
mul = 0.03; mul = 0.03;
break; break;
} }
default: default:
{ {
mul = 0.; mul = 1.;
break; break;
} }
} }
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
}
}
return new double[] return new double[]
{ {

View File

@ -469,6 +469,10 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
// Calculate the difference of level between this attacker (player or servitor owner) and the L2Attackable
// mob = 24, atk = 10, diff = -14 (full xp)
// mob = 24, atk = 28, diff = 4 (some xp)
// mob = 24, atk = 50, diff = 26 (no xp)
final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
double exp = expSp[0]; double exp = expSp[0];
double sp = expSp[1]; double sp = expSp[1];
@ -1302,67 +1306,70 @@ public class L2Attackable extends L2Npc
*/ */
private double[] 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 = charLevel - getLevel();
double xp = Math.max(0, (getExpReward() * damage) / totalDamage); double xp = 0;
double sp = Math.max(0, (getSpReward() * damage) / totalDamage); double sp = 0;
if ((levelDiff < 11) && (levelDiff > -11))
{
xp = Math.max(0, (getExpReward() * damage) / totalDamage);
sp = Math.max(0, (getSpReward() * damage) / totalDamage);
if ((charLevel > 84) && (levelDiff <= -3))
{
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
case 0: case -3:
case 1:
case 2:
{
mul = 1.;
break;
}
case 3:
{ {
mul = 0.97; mul = 0.97;
break; break;
} }
case 4: case -4:
{ {
mul = 0.67; mul = 0.67;
break; break;
} }
case 5: case -5:
{ {
mul = 0.42; mul = 0.42;
break; break;
} }
case 6: case -6:
{ {
mul = 0.25; mul = 0.25;
break; break;
} }
case 7: case -7:
{ {
mul = 0.15; mul = 0.15;
break; break;
} }
case 8: case -8:
{ {
mul = 0.09; mul = 0.09;
break; break;
} }
case 9: case -9:
{ {
mul = 0.05; mul = 0.05;
break; break;
} }
case 10: case -10:
{ {
mul = 0.03; mul = 0.03;
break; break;
} }
default: default:
{ {
mul = 0.; mul = 1.;
break; break;
} }
} }
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
}
}
return new double[] return new double[]
{ {

View File

@ -469,6 +469,10 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
// Calculate the difference of level between this attacker (player or servitor owner) and the L2Attackable
// mob = 24, atk = 10, diff = -14 (full xp)
// mob = 24, atk = 28, diff = 4 (some xp)
// mob = 24, atk = 50, diff = 26 (no xp)
final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
double exp = expSp[0]; double exp = expSp[0];
double sp = expSp[1]; double sp = expSp[1];
@ -1302,67 +1306,70 @@ public class L2Attackable extends L2Npc
*/ */
private double[] 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 = charLevel - getLevel();
double xp = Math.max(0, (getExpReward() * damage) / totalDamage); double xp = 0;
double sp = Math.max(0, (getSpReward() * damage) / totalDamage); double sp = 0;
if ((levelDiff < 11) && (levelDiff > -11))
{
xp = Math.max(0, (getExpReward() * damage) / totalDamage);
sp = Math.max(0, (getSpReward() * damage) / totalDamage);
if ((charLevel > 84) && (levelDiff <= -3))
{
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
case 0: case -3:
case 1:
case 2:
{
mul = 1.;
break;
}
case 3:
{ {
mul = 0.97; mul = 0.97;
break; break;
} }
case 4: case -4:
{ {
mul = 0.67; mul = 0.67;
break; break;
} }
case 5: case -5:
{ {
mul = 0.42; mul = 0.42;
break; break;
} }
case 6: case -6:
{ {
mul = 0.25; mul = 0.25;
break; break;
} }
case 7: case -7:
{ {
mul = 0.15; mul = 0.15;
break; break;
} }
case 8: case -8:
{ {
mul = 0.09; mul = 0.09;
break; break;
} }
case 9: case -9:
{ {
mul = 0.05; mul = 0.05;
break; break;
} }
case 10: case -10:
{ {
mul = 0.03; mul = 0.03;
break; break;
} }
default: default:
{ {
mul = 0.; mul = 1.;
break; break;
} }
} }
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
}
}
return new double[] return new double[]
{ {

View File

@ -469,6 +469,10 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
// Calculate the difference of level between this attacker (player or servitor owner) and the L2Attackable
// mob = 24, atk = 10, diff = -14 (full xp)
// mob = 24, atk = 28, diff = 4 (some xp)
// mob = 24, atk = 50, diff = 26 (no xp)
final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
double exp = expSp[0]; double exp = expSp[0];
double sp = expSp[1]; double sp = expSp[1];
@ -1302,67 +1306,70 @@ public class L2Attackable extends L2Npc
*/ */
private double[] 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 = charLevel - getLevel();
double xp = Math.max(0, (getExpReward() * damage) / totalDamage); double xp = 0;
double sp = Math.max(0, (getSpReward() * damage) / totalDamage); double sp = 0;
if ((levelDiff < 11) && (levelDiff > -11))
{
xp = Math.max(0, (getExpReward() * damage) / totalDamage);
sp = Math.max(0, (getSpReward() * damage) / totalDamage);
if ((charLevel > 84) && (levelDiff <= -3))
{
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
case 0: case -3:
case 1:
case 2:
{
mul = 1.;
break;
}
case 3:
{ {
mul = 0.97; mul = 0.97;
break; break;
} }
case 4: case -4:
{ {
mul = 0.67; mul = 0.67;
break; break;
} }
case 5: case -5:
{ {
mul = 0.42; mul = 0.42;
break; break;
} }
case 6: case -6:
{ {
mul = 0.25; mul = 0.25;
break; break;
} }
case 7: case -7:
{ {
mul = 0.15; mul = 0.15;
break; break;
} }
case 8: case -8:
{ {
mul = 0.09; mul = 0.09;
break; break;
} }
case 9: case -9:
{ {
mul = 0.05; mul = 0.05;
break; break;
} }
case 10: case -10:
{ {
mul = 0.03; mul = 0.03;
break; break;
} }
default: default:
{ {
mul = 0.; mul = 1.;
break; break;
} }
} }
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
}
}
return new double[] return new double[]
{ {

View File

@ -1,8 +1,8 @@
CREATE TABLE IF NOT EXISTS `character_subclasses` ( CREATE TABLE IF NOT EXISTS `character_subclasses` (
`charId` INT UNSIGNED NOT NULL DEFAULT 0, `charId` INT UNSIGNED NOT NULL DEFAULT 0,
`class_id` int(2) NOT NULL DEFAULT 0, `class_id` int(2) NOT NULL DEFAULT 0,
`exp` decimal(20,0) NOT NULL DEFAULT 0, `exp` bigint(20) NOT NULL DEFAULT 0,
`sp` decimal(11,0) NOT NULL DEFAULT 0, `sp` bigint(10) NOT NULL DEFAULT 0,
`level` int(2) NOT NULL DEFAULT 40, `level` int(2) NOT NULL DEFAULT 40,
`class_index` int(1) NOT NULL DEFAULT 0, `class_index` int(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`charId`,`class_id`) PRIMARY KEY (`charId`,`class_id`)

View File

@ -19,7 +19,7 @@ CREATE TABLE IF NOT EXISTS `characters` (
`z` MEDIUMINT DEFAULT NULL, `z` MEDIUMINT DEFAULT NULL,
`exp` BIGINT UNSIGNED DEFAULT 0, `exp` BIGINT UNSIGNED DEFAULT 0,
`expBeforeDeath` BIGINT UNSIGNED DEFAULT 0, `expBeforeDeath` BIGINT UNSIGNED DEFAULT 0,
`sp` INT UNSIGNED NOT NULL DEFAULT 0, `sp` BIGINT(10) UNSIGNED NOT NULL DEFAULT 0,
`karma` INT UNSIGNED DEFAULT NULL, `karma` INT UNSIGNED DEFAULT NULL,
`fame` MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, `fame` MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
`pvpkills` SMALLINT UNSIGNED DEFAULT NULL, `pvpkills` SMALLINT UNSIGNED DEFAULT NULL,

View File

@ -345,6 +345,11 @@ MaxEvasion = 250
MinAbnormalStateSuccessRate = 10 MinAbnormalStateSuccessRate = 10
MaxAbnormalStateSuccessRate = 90 MaxAbnormalStateSuccessRate = 90
# Maximum amount of SP a character can posses.
# Current retail limit is 50 billion, use -1 to set it to unlimited.
# Default: 50000000000
MaxSp = 50000000000
# Maximum number of allowed subclasses for every player. # Maximum number of allowed subclasses for every player.
# Default: 3 # Default: 3
MaxSubclass = 3 MaxSubclass = 3
@ -789,17 +794,6 @@ FreeTeleporting = False
# Default: 7 # Default: 7
DeleteCharAfterDays = 7 DeleteCharAfterDays = 7
# Alternative Xp/Sp rewards, if not 0, then calculated as 2^((mob.level-player.level) / coef). Coef are the 2 numbers set below.
# A few examples for "AltGameExponentXp = 5." and "AltGameExponentSp = 3.":
# diff = 0 (player and mob has the same level), XP bonus rate = 1, SP bonus rate = 1
# diff = 3 (mob is 3 levels above), XP bonus rate = 1.52, SP bonus rate = 2
# diff = 5 (mob is 5 levels above), XP bonus rate = 2, SP bonus rate = 3.17
# diff = -8 (mob is 8 levels below), XP bonus rate = 0.4, SP bonus rate = 0.16
# Default: 0, 0
AltGameExponentXp = 0
AltGameExponentSp = 0
# PARTY XP DISTRIBUTION # PARTY XP DISTRIBUTION
# With "auto method" member is cut from Exp/SP distribution when his share is lower than party bonus acquired for him (30% for 2 member party). # With "auto method" member is cut from Exp/SP distribution when his share is lower than party bonus acquired for him (30% for 2 member party).
# In that case he will not receive any Exp/SP from party and is not counted for party bonus. # In that case he will not receive any Exp/SP from party and is not counted for party bonus.

View File

@ -192,6 +192,7 @@ public final class Config
public static int MAX_EVASION; public static int MAX_EVASION;
public static int MIN_ABNORMAL_STATE_SUCCESS_RATE; public static int MIN_ABNORMAL_STATE_SUCCESS_RATE;
public static int MAX_ABNORMAL_STATE_SUCCESS_RATE; public static int MAX_ABNORMAL_STATE_SUCCESS_RATE;
public static long MAX_SP;
public static byte MAX_SUBCLASS; public static byte MAX_SUBCLASS;
public static byte BASE_SUBCLASS_LEVEL; public static byte BASE_SUBCLASS_LEVEL;
public static byte MAX_SUBCLASS_LEVEL; public static byte MAX_SUBCLASS_LEVEL;
@ -269,8 +270,6 @@ public final class Config
public static int MAX_PETITIONS_PENDING; public static int MAX_PETITIONS_PENDING;
public static boolean FREE_TELEPORTING; public static boolean FREE_TELEPORTING;
public static int DELETE_DAYS; public static int DELETE_DAYS;
public static float ALT_GAME_EXPONENT_XP;
public static float ALT_GAME_EXPONENT_SP;
public static String PARTY_XP_CUTOFF_METHOD; public static String PARTY_XP_CUTOFF_METHOD;
public static double PARTY_XP_CUTOFF_PERCENT; public static double PARTY_XP_CUTOFF_PERCENT;
public static int PARTY_XP_CUTOFF_LEVEL; public static int PARTY_XP_CUTOFF_LEVEL;
@ -1641,6 +1640,7 @@ public final class Config
MAX_EVASION = Character.getInt("MaxEvasion", 250); MAX_EVASION = Character.getInt("MaxEvasion", 250);
MIN_ABNORMAL_STATE_SUCCESS_RATE = Character.getInt("MinAbnormalStateSuccessRate", 10); MIN_ABNORMAL_STATE_SUCCESS_RATE = Character.getInt("MinAbnormalStateSuccessRate", 10);
MAX_ABNORMAL_STATE_SUCCESS_RATE = Character.getInt("MaxAbnormalStateSuccessRate", 90); MAX_ABNORMAL_STATE_SUCCESS_RATE = Character.getInt("MaxAbnormalStateSuccessRate", 90);
MAX_SP = Character.getLong("MaxSp", 50000000000L) >= 0 ? Character.getLong("MaxSp", 50000000000L) : Long.MAX_VALUE;
MAX_SUBCLASS = Character.getByte("MaxSubclass", (byte) 3); MAX_SUBCLASS = Character.getByte("MaxSubclass", (byte) 3);
BASE_SUBCLASS_LEVEL = Character.getByte("BaseSubclassLevel", (byte) 40); BASE_SUBCLASS_LEVEL = Character.getByte("BaseSubclassLevel", (byte) 40);
MAX_SUBCLASS_LEVEL = Character.getByte("MaxSubclassLevel", (byte) 80); MAX_SUBCLASS_LEVEL = Character.getByte("MaxSubclassLevel", (byte) 80);
@ -1804,8 +1804,6 @@ public final class Config
MAX_PETITIONS_PENDING = Character.getInt("MaxPetitionsPending", 25); MAX_PETITIONS_PENDING = Character.getInt("MaxPetitionsPending", 25);
FREE_TELEPORTING = Character.getBoolean("FreeTeleporting", false); FREE_TELEPORTING = Character.getBoolean("FreeTeleporting", false);
DELETE_DAYS = Character.getInt("DeleteCharAfterDays", 7); DELETE_DAYS = Character.getInt("DeleteCharAfterDays", 7);
ALT_GAME_EXPONENT_XP = Character.getFloat("AltGameExponentXp", 0);
ALT_GAME_EXPONENT_SP = Character.getFloat("AltGameExponentSp", 0);
PARTY_XP_CUTOFF_METHOD = Character.getString("PartyXpCutoffMethod", "highfive"); PARTY_XP_CUTOFF_METHOD = Character.getString("PartyXpCutoffMethod", "highfive");
PARTY_XP_CUTOFF_PERCENT = Character.getDouble("PartyXpCutoffPercent", 3); PARTY_XP_CUTOFF_PERCENT = Character.getDouble("PartyXpCutoffPercent", 3);
PARTY_XP_CUTOFF_LEVEL = Character.getInt("PartyXpCutoffLevel", 20); PARTY_XP_CUTOFF_LEVEL = Character.getInt("PartyXpCutoffLevel", 20);

View File

@ -2702,7 +2702,7 @@ public class L2Clan implements IIdentifiable, INamable
// the player should know that he has less sp now :p // the player should know that he has less sp now :p
final StatusUpdate su = new StatusUpdate(player); final StatusUpdate su = new StatusUpdate(player);
su.addAttribute(StatusUpdate.SP, player.getSp()); su.addAttribute(StatusUpdate.SP, (int) player.getSp());
player.sendPacket(su); player.sendPacket(su);
player.sendPacket(new ItemList(player, false)); player.sendPacket(new ItemList(player, false));

View File

@ -741,7 +741,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);
@ -774,8 +774,8 @@ 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.calcStat(Stats.EXPSP_RATE, xpReward * preCalculation, null, null)); double addexp = Math.round(member.calcStat(Stats.EXPSP_RATE, xpReward * preCalculation, null, null));
final int addsp = (int) member.calcStat(Stats.EXPSP_RATE, spReward * preCalculation, null, null); final double addsp = member.calcStat(Stats.EXPSP_RATE, spReward * preCalculation, null, null);
addexp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, addexp, addsp, useVitalityRate); addexp = calculateExpSpPartyCutoff(member.getActingPlayer(), topLvl, addexp, addsp, useVitalityRate);
if (addexp > 0) if (addexp > 0)
@ -790,10 +790,10 @@ public class L2Party extends AbstractPlayerGroup
} }
} }
private final 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;

View File

@ -447,11 +447,9 @@ public class L2Attackable extends L2Npc
// mob = 24, atk = 10, diff = -14 (full xp) // mob = 24, atk = 10, diff = -14 (full xp)
// mob = 24, atk = 28, diff = 4 (some xp) // mob = 24, atk = 28, diff = 4 (some xp)
// mob = 24, atk = 50, diff = 26 (no xp) // mob = 24, atk = 50, diff = 26 (no xp)
final int levelDiff = attacker.getLevel() - getLevel(); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
double exp = expSp[0];
final int[] expSp = calculateExpAndSp(levelDiff, damage, totalDamage); double sp = expSp[1];
long exp = expSp[0];
int sp = expSp[1];
if (Config.CHAMPION_ENABLE && isChampion()) if (Config.CHAMPION_ENABLE && isChampion())
{ {
@ -487,7 +485,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
@ -551,16 +549,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 the level difference between Party and L2Attackable
final int levelDiff = partyLvl - getLevel();
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
final int[] expSp = calculateExpAndSp(levelDiff, 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())
{ {
@ -1282,61 +1277,86 @@ public class L2Attackable extends L2Npc
/** /**
* Calculate the Experience and SP to distribute to attacker (L2PcInstance, L2ServitorInstance or L2Party) of the L2Attackable. * Calculate the Experience and SP to distribute to attacker (L2PcInstance, L2ServitorInstance or L2Party) of the L2Attackable.
* @param diff The difference of level between attacker (L2PcInstance, L2ServitorInstance or L2Party) and the L2Attackable * @param charLevel The killer level
* @param damage The damages given by the attacker (L2PcInstance, L2ServitorInstance or L2Party) * @param damage The damages given by the attacker (L2PcInstance, L2ServitorInstance or L2Party)
* @param totalDamage The total damage done * @param totalDamage The total damage done
* @return * @return
*/ */
private int[] calculateExpAndSp(int diff, int damage, long totalDamage) private double[] calculateExpAndSp(int charLevel, int damage, long totalDamage)
{ {
double xp; final int levelDiff = charLevel - getLevel();
double sp; double xp = 0;
double sp = 0;
if (diff < -5) if ((levelDiff < 11) && (levelDiff > -11))
{ {
diff = -5; // makes possible to use ALT_GAME_EXPONENT configuration xp = Math.max(0, (getExpReward() * damage) / totalDamage);
sp = Math.max(0, (getSpReward() * damage) / totalDamage);
if ((charLevel > 84) && (levelDiff <= -3))
{
double mul;
switch (levelDiff)
{
case -3:
{
mul = 0.97;
break;
}
case -4:
{
mul = 0.67;
break;
}
case -5:
{
mul = 0.42;
break;
}
case -6:
{
mul = 0.25;
break;
}
case -7:
{
mul = 0.15;
break;
}
case -8:
{
mul = 0.09;
break;
}
case -9:
{
mul = 0.05;
break;
}
case -10:
{
mul = 0.03;
break;
}
default:
{
mul = 1.;
break;
}
}
xp *= mul;
sp *= mul;
}
} }
xp = ((double) getExpReward() * damage) / totalDamage; return new double[]
if (Config.ALT_GAME_EXPONENT_XP != 0)
{ {
xp *= Math.pow(2., -diff / Config.ALT_GAME_EXPONENT_XP); xp,
} sp
sp = ((double) getSpReward() * damage) / totalDamage;
if (Config.ALT_GAME_EXPONENT_SP != 0)
{
sp *= Math.pow(2., -diff / Config.ALT_GAME_EXPONENT_SP);
}
if ((Config.ALT_GAME_EXPONENT_XP == 0) && (Config.ALT_GAME_EXPONENT_SP == 0))
{
if (diff > 5) // formula revised May 07
{
final double pow = Math.pow((double) 5 / 6, diff - 5);
xp = xp * pow;
sp = sp * pow;
}
if (xp <= 0)
{
xp = 0;
sp = 0;
}
else if (sp <= 0)
{
sp = 0;
}
}
final int[] tmp =
{
(int) xp,
(int) sp
}; };
return tmp;
} }
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());
@ -1349,11 +1369,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 ammount of exp points to be added to the player's normal exp reward
final long bonusOverhit = Math.round(overhitExp);
return bonusOverhit;
} }
/** /**

View File

@ -4554,7 +4554,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
* @param addToExp * @param addToExp
* @param addToSp * @param addToSp
*/ */
public void addExpAndSp(long addToExp, int addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
// Dummy method (overridden by players and pets) // Dummy method (overridden by players and pets)
} }

View File

@ -2668,7 +2668,7 @@ public final class L2PcInstance extends L2Playable
/** /**
* @return the SP amount of the L2PcInstance. * @return the SP amount of the L2PcInstance.
*/ */
public int getSp() public long getSp()
{ {
return getStat().getSp(); return getStat().getSp();
} }
@ -2677,7 +2677,7 @@ public final class L2PcInstance extends L2Playable
* Set the SP amount of the L2PcInstance. * Set the SP amount of the L2PcInstance.
* @param sp * @param sp
*/ */
public void setSp(int sp) public void setSp(long sp)
{ {
if (sp < 0) if (sp < 0)
{ {
@ -6647,7 +6647,7 @@ public final class L2PcInstance extends L2Playable
ps.setInt(13, getAppearance().getHairColor()); ps.setInt(13, getAppearance().getHairColor());
ps.setInt(14, getAppearance().getSex() ? 1 : 0); ps.setInt(14, getAppearance().getSex() ? 1 : 0);
ps.setLong(15, getExp()); ps.setLong(15, getExp());
ps.setInt(16, getSp()); ps.setLong(16, getSp());
ps.setInt(17, getKarma()); ps.setInt(17, getKarma());
ps.setInt(18, getFame()); ps.setInt(18, getFame());
ps.setInt(19, getPvpKills()); ps.setInt(19, getPvpKills());
@ -7246,7 +7246,7 @@ public final class L2PcInstance extends L2Playable
// Get the exp, level, and sp of base class to store in base table // Get the exp, level, and sp of base class to store in base table
final long exp = getStat().getBaseExp(); final long exp = getStat().getBaseExp();
final int level = getStat().getBaseLevel(); final int level = getStat().getBaseLevel();
final int sp = getStat().getBaseSp(); final long sp = getStat().getBaseSp();
try (Connection con = DatabaseFactory.getInstance().getConnection(); try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(UPDATE_CHARACTER)) PreparedStatement ps = con.prepareStatement(UPDATE_CHARACTER))
{ {
@ -7267,7 +7267,7 @@ public final class L2PcInstance extends L2Playable
ps.setInt(15, _observerMode ? _lastLoc.getZ() : getZ()); ps.setInt(15, _observerMode ? _lastLoc.getZ() : getZ());
ps.setLong(16, exp); ps.setLong(16, exp);
ps.setLong(17, getExpBeforeDeath()); ps.setLong(17, getExpBeforeDeath());
ps.setInt(18, sp); ps.setLong(18, sp);
ps.setInt(19, getKarma()); ps.setInt(19, getKarma());
ps.setInt(20, getFame()); ps.setInt(20, getFame());
ps.setInt(21, getPvpKills()); ps.setInt(21, getPvpKills());
@ -7341,7 +7341,7 @@ public final class L2PcInstance extends L2Playable
for (SubClass subClass : getSubClasses().values()) for (SubClass subClass : getSubClasses().values())
{ {
ps.setLong(1, subClass.getExp()); ps.setLong(1, subClass.getExp());
ps.setInt(2, subClass.getSp()); ps.setLong(2, subClass.getSp());
ps.setInt(3, subClass.getLevel()); ps.setInt(3, subClass.getLevel());
ps.setInt(4, subClass.getClassId()); ps.setInt(4, subClass.getClassId());
ps.setInt(5, getObjectId()); ps.setInt(5, getObjectId());
@ -10026,7 +10026,7 @@ public final class L2PcInstance extends L2Playable
ps.setInt(1, getObjectId()); ps.setInt(1, getObjectId());
ps.setInt(2, newClass.getClassId()); ps.setInt(2, newClass.getClassId());
ps.setLong(3, newClass.getExp()); ps.setLong(3, newClass.getExp());
ps.setInt(4, newClass.getSp()); ps.setLong(4, newClass.getSp());
ps.setInt(5, newClass.getLevel()); ps.setInt(5, newClass.getLevel());
ps.setInt(6, newClass.getClassIndex()); // <-- Added ps.setInt(6, newClass.getClassIndex()); // <-- Added
ps.execute(); ps.execute();
@ -10830,22 +10830,22 @@ public final class L2PcInstance extends L2Playable
} }
@Override @Override
public void addExpAndSp(long addToExp, int addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
getStat().addExpAndSp(addToExp, addToSp, false); getStat().addExpAndSp(addToExp, addToSp, false);
} }
public void addExpAndSp(long addToExp, int addToSp, boolean useVitality) public void addExpAndSp(double addToExp, double addToSp, boolean useVitality)
{ {
getStat().addExpAndSp(addToExp, addToSp, useVitality); getStat().addExpAndSp(addToExp, addToSp, useVitality);
} }
public void removeExpAndSp(long removeExp, int removeSp) public void removeExpAndSp(long removeExp, long removeSp)
{ {
getStat().removeExpAndSp(removeExp, removeSp, true); getStat().removeExpAndSp(removeExp, removeSp, true);
} }
public void removeExpAndSp(long removeExp, int removeSp, boolean sendMessage) public void removeExpAndSp(long removeExp, long removeSp, boolean sendMessage)
{ {
getStat().removeExpAndSp(removeExp, removeSp, sendMessage); getStat().removeExpAndSp(removeExp, removeSp, sendMessage);
} }

View File

@ -934,7 +934,7 @@ public class L2PetInstance extends L2Summon
ps.setDouble(3, getStatus().getCurrentHp()); ps.setDouble(3, getStatus().getCurrentHp());
ps.setDouble(4, getStatus().getCurrentMp()); ps.setDouble(4, getStatus().getCurrentMp());
ps.setLong(5, getStat().getExp()); ps.setLong(5, getStat().getExp());
ps.setInt(6, getStat().getSp()); ps.setLong(6, getStat().getSp());
ps.setInt(7, getCurrentFed()); ps.setInt(7, getCurrentFed());
ps.setInt(8, getOwner().getObjectId()); ps.setInt(8, getOwner().getObjectId());
ps.setString(9, String.valueOf(_restoreSummon)); // True restores pet on login ps.setString(9, String.valueOf(_restoreSummon)); // True restores pet on login
@ -1154,7 +1154,7 @@ public class L2PetInstance extends L2Summon
} }
@Override @Override
public void addExpAndSp(long addToExp, int addToSp) public void addExpAndSp(double addToExp, double addToSp)
{ {
if (getId() == 12564) if (getId() == 12564)
{ {

View File

@ -37,7 +37,7 @@ public class CharStat
private final L2Character _activeChar; private final L2Character _activeChar;
private long _exp = 0; private long _exp = 0;
private int _sp = 0; private long _sp = 0;
private byte _level = 1; private byte _level = 1;
private final float[] _attackTraits = new float[TraitType.values().length]; private final float[] _attackTraits = new float[TraitType.values().length];
private final int[] _attackTraitsCount = new int[TraitType.values().length]; private final int[] _attackTraitsCount = new int[TraitType.values().length];
@ -592,12 +592,12 @@ public class CharStat
return (int) calcStat(Stats.SHIELD_DEFENCE, 0); return (int) calcStat(Stats.SHIELD_DEFENCE, 0);
} }
public int getSp() public long getSp()
{ {
return _sp; return _sp;
} }
public void setSp(int value) public void setSp(long value)
{ {
_sp = value; _sp = value;
} }

View File

@ -113,7 +113,7 @@ public class PcStat extends PlayableStat
return true; return true;
} }
public boolean addExpAndSp(long addToExp, int addToSp, boolean useBonuses) public boolean addExpAndSp(double addToExp, double addToSp, boolean useBonuses)
{ {
final L2PcInstance activeChar = getActiveChar(); final L2PcInstance activeChar = getActiveChar();
@ -130,8 +130,8 @@ public class PcStat extends PlayableStat
addToSp *= Config.PREMIUM_RATE_SP; addToSp *= Config.PREMIUM_RATE_SP;
} }
final long baseExp = addToExp; final double baseExp = addToExp;
final int baseSp = addToSp; final double baseSp = addToSp;
double bonusExp = 1.; double bonusExp = 1.;
double bonusSp = 1.; double bonusSp = 1.;
@ -161,7 +161,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
if (activeChar.hasPet() && Util.checkIfInShortRange(Config.ALT_PARTY_RANGE, activeChar, activeChar.getSummon(), false)) if (activeChar.hasPet() && Util.checkIfInShortRange(Config.ALT_PARTY_RANGE, activeChar, activeChar.getSummon(), false))
@ -178,55 +178,45 @@ 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;
}
if ((addToExp == 0) && (addToSp == 0))
{
return false;
}
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.addInt(addToSp); sm.addLong(finalSp);
} }
else if ((addToSp == 0) && (addToExp != 0)) else if (expAdded && !spAdded)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_EXPERIENCE); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_EXPERIENCE);
sm.addLong(addToExp); sm.addLong(finalExp);
} }
else else
{ {
if ((addToExp - baseExp) > 0) if ((addToExp - baseExp) > 0)
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_EXP_BONUS_S2_AND_S3_SP_BONUS_S4); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_ACQUIRED_S1_EXP_BONUS_S2_AND_S3_SP_BONUS_S4);
sm.addLong(addToExp); sm.addLong(finalExp);
sm.addLong(addToExp - baseExp); sm.addLong(Math.round(addToExp - baseExp));
sm.addInt(addToSp); sm.addLong(finalSp);
sm.addInt(addToSp - baseSp); sm.addLong(Math.round(addToSp - baseSp));
} }
else else
{ {
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_EXPERIENCE_AND_S2_SP); sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1_EXPERIENCE_AND_S2_SP);
sm.addLong(addToExp); sm.addLong((long) addToExp);
sm.addInt(addToSp); sm.addLong((long) addToSp);
} }
} }
activeChar.sendPacket(sm); activeChar.sendPacket(sm);
@ -234,12 +224,12 @@ public class PcStat extends PlayableStat
} }
@Override @Override
public boolean removeExpAndSp(long addToExp, int addToSp) public boolean removeExpAndSp(long addToExp, long addToSp)
{ {
return removeExpAndSp(addToExp, addToSp, true); return removeExpAndSp(addToExp, addToSp, true);
} }
public boolean removeExpAndSp(long addToExp, int addToSp, boolean sendMessage) public boolean removeExpAndSp(long addToExp, long addToSp, boolean sendMessage)
{ {
final int level = getLevel(); final int level = getLevel();
if (!super.removeExpAndSp(addToExp, addToSp)) if (!super.removeExpAndSp(addToExp, addToSp))
@ -254,7 +244,7 @@ public class PcStat extends PlayableStat
sm.addLong(addToExp); sm.addLong(addToExp);
getActiveChar().sendPacket(sm); getActiveChar().sendPacket(sm);
sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_SP_HAS_DECREASED_BY_S1); sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_SP_HAS_DECREASED_BY_S1);
sm.addInt(addToSp); sm.addLong(addToSp);
getActiveChar().sendPacket(sm); getActiveChar().sendPacket(sm);
if (getLevel() < level) if (getLevel() < level)
{ {
@ -349,7 +339,7 @@ public class PcStat extends PlayableStat
} }
@Override @Override
public boolean addSp(int value) public boolean addSp(long value)
{ {
if (!super.addSp(value)) if (!super.addSp(value))
{ {
@ -357,7 +347,7 @@ public class PcStat extends PlayableStat
} }
final StatusUpdate su = new StatusUpdate(getActiveChar()); final StatusUpdate su = new StatusUpdate(getActiveChar());
su.addAttribute(StatusUpdate.SP, getSp()); su.addAttribute(StatusUpdate.SP, (int) getSp());
getActiveChar().sendPacket(su); getActiveChar().sendPacket(su);
return true; return true;
@ -562,7 +552,7 @@ public class PcStat extends PlayableStat
} }
@Override @Override
public final int getSp() public final long getSp()
{ {
if (getActiveChar().isSubClassActive()) if (getActiveChar().isSubClassActive())
{ {
@ -572,13 +562,13 @@ public class PcStat extends PlayableStat
return super.getSp(); return super.getSp();
} }
public final int getBaseSp() public final long getBaseSp()
{ {
return super.getSp(); return super.getSp();
} }
@Override @Override
public final void setSp(int value) public final void setSp(long value)
{ {
if (getActiveChar().isSubClassActive()) if (getActiveChar().isSubClassActive())
{ {
@ -907,7 +897,10 @@ public class PcStat extends PlayableStat
// Check for abnormal bonuses // Check for abnormal bonuses
bonus = Math.max(bonus, 1); bonus = Math.max(bonus, 1);
if (Config.MAX_BONUS_EXP > 0)
{
bonus = Math.min(bonus, Config.MAX_BONUS_EXP); bonus = Math.min(bonus, Config.MAX_BONUS_EXP);
}
return bonus; return bonus;
} }
@ -951,7 +944,10 @@ public class PcStat extends PlayableStat
// Check for abnormal bonuses // Check for abnormal bonuses
bonus = Math.max(bonus, 1); bonus = Math.max(bonus, 1);
if (Config.MAX_BONUS_SP > 0)
{
bonus = Math.min(bonus, Config.MAX_BONUS_SP); bonus = Math.min(bonus, Config.MAX_BONUS_SP);
}
return bonus; return bonus;
} }

View File

@ -48,15 +48,16 @@ public class PetStat extends SummonStat
return true; return true;
} }
public boolean addExpAndSp(long addToExp, int 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_EXPERIENCE_POINTS); final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PET_GAINED_S1_EXPERIENCE_POINTS);
sm.addLong(addToExp); sm.addLong(finalExp);
getActiveChar().updateAndBroadcastStatus(1); getActiveChar().updateAndBroadcastStatus(1);
getActiveChar().sendPacket(sm); getActiveChar().sendPacket(sm);
return true; return true;

View File

@ -119,7 +119,7 @@ public class PlayableStat extends CharStat
return true; return true;
} }
public boolean removeExpAndSp(long removeExp, int removeSp) public boolean removeExpAndSp(long removeExp, long removeSp)
{ {
boolean expRemoved = false; boolean expRemoved = false;
boolean spRemoved = false; boolean spRemoved = false;
@ -175,31 +175,31 @@ public class PlayableStat extends CharStat
return true; return true;
} }
public boolean addSp(int value) public boolean addSp(long value)
{ {
if (value < 0) if (value < 0)
{ {
_log.warning("wrong usage"); _log.warning("wrong usage");
return false; return false;
} }
final int currentSp = getSp(); final long currentSp = getSp();
if (currentSp == Integer.MAX_VALUE) if (currentSp >= Config.MAX_SP)
{ {
return false; return false;
} }
if (currentSp > (Integer.MAX_VALUE - value)) if (currentSp > (Config.MAX_SP - value))
{ {
value = Integer.MAX_VALUE - currentSp; value = Config.MAX_SP - currentSp;
} }
setSp(currentSp + value); setSp(currentSp + value);
return true; return true;
} }
public boolean removeSp(int value) public boolean removeSp(long value)
{ {
final int currentSp = getSp(); final long currentSp = getSp();
if (currentSp < value) if (currentSp < value)
{ {
value = currentSp; value = currentSp;

View File

@ -30,7 +30,7 @@ public final class SubClass
private PlayerClass _class; private PlayerClass _class;
private long _exp = ExperienceData.getInstance().getExpForLevel(Config.BASE_SUBCLASS_LEVEL); private long _exp = ExperienceData.getInstance().getExpForLevel(Config.BASE_SUBCLASS_LEVEL);
private int _sp = 0; private long _sp = 0;
private byte _level = Config.BASE_SUBCLASS_LEVEL; private byte _level = Config.BASE_SUBCLASS_LEVEL;
private int _classIndex = 1; private int _classIndex = 1;
@ -71,7 +71,7 @@ public final class SubClass
return _exp; return _exp;
} }
public int getSp() public long getSp()
{ {
return _sp; return _sp;
} }
@ -105,7 +105,7 @@ public final class SubClass
_exp = expValue; _exp = expValue;
} }
public void setSp(int spValue) public void setSp(long spValue)
{ {
_sp = spValue; _sp = spValue;
} }

View File

@ -499,7 +499,7 @@ public final class RequestAcquireSkill implements IClientIncomingPacket
{ {
player.setSp(player.getSp() - levelUpSp); player.setSp(player.getSp() - levelUpSp);
final StatusUpdate su = new StatusUpdate(player); final StatusUpdate su = new StatusUpdate(player);
su.addAttribute(StatusUpdate.SP, player.getSp()); su.addAttribute(StatusUpdate.SP, (int) player.getSp());
player.sendPacket(su); player.sendPacket(su);
} }
return true; return true;

View File

@ -57,7 +57,7 @@ public class CharSelected implements IClientOutgoingPacket
packet.writeF(_activeChar.getCurrentHp()); packet.writeF(_activeChar.getCurrentHp());
packet.writeF(_activeChar.getCurrentMp()); packet.writeF(_activeChar.getCurrentMp());
packet.writeD(_activeChar.getSp()); packet.writeD((int) _activeChar.getSp());
packet.writeQ(_activeChar.getExp()); packet.writeQ(_activeChar.getExp());
packet.writeD(_activeChar.getLevel()); packet.writeD(_activeChar.getLevel());
packet.writeD(_activeChar.getKarma()); // thx evill33t packet.writeD(_activeChar.getKarma()); // thx evill33t

View File

@ -68,7 +68,7 @@ public class GMViewCharacterInfo implements IClientOutgoingPacket
packet.writeD((int) _activeChar.getCurrentHp()); packet.writeD((int) _activeChar.getCurrentHp());
packet.writeD(_activeChar.getMaxMp()); packet.writeD(_activeChar.getMaxMp());
packet.writeD((int) _activeChar.getCurrentMp()); packet.writeD((int) _activeChar.getCurrentMp());
packet.writeD(_activeChar.getSp()); packet.writeD((int) _activeChar.getSp());
packet.writeD(_activeChar.getCurrentLoad()); packet.writeD(_activeChar.getCurrentLoad());
packet.writeD(_activeChar.getMaxLoad()); packet.writeD(_activeChar.getMaxLoad());
packet.writeD(_activeChar.getPkKills()); packet.writeD(_activeChar.getPkKills());

View File

@ -127,7 +127,7 @@ public class PetInfo implements IClientOutgoingPacket
packet.writeD(_maxHp);// max hp packet.writeD(_maxHp);// max hp
packet.writeD((int) _summon.getCurrentMp());// current mp packet.writeD((int) _summon.getCurrentMp());// current mp
packet.writeD(_maxMp);// max mp packet.writeD(_maxMp);// max mp
packet.writeD(_summon.getStat().getSp()); // sp packet.writeD((int) _summon.getStat().getSp()); // sp
packet.writeD(_summon.getLevel());// lvl packet.writeD(_summon.getLevel());// lvl
packet.writeQ(_summon.getStat().getExp()); packet.writeQ(_summon.getStat().getExp());

View File

@ -110,7 +110,7 @@ public final class UserInfo implements IClientOutgoingPacket
packet.writeD((int) Math.round(_activeChar.getCurrentHp())); packet.writeD((int) Math.round(_activeChar.getCurrentHp()));
packet.writeD(_activeChar.getMaxMp()); packet.writeD(_activeChar.getMaxMp());
packet.writeD((int) Math.round(_activeChar.getCurrentMp())); packet.writeD((int) Math.round(_activeChar.getCurrentMp()));
packet.writeD(_activeChar.getSp()); packet.writeD((int) _activeChar.getSp());
packet.writeD(_activeChar.getCurrentLoad()); packet.writeD(_activeChar.getCurrentLoad());
packet.writeD(_activeChar.getMaxLoad()); packet.writeD(_activeChar.getMaxLoad());

View File

@ -469,6 +469,10 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
// Calculate the difference of level between this attacker (player or servitor owner) and the L2Attackable
// mob = 24, atk = 10, diff = -14 (full xp)
// mob = 24, atk = 28, diff = 4 (some xp)
// mob = 24, atk = 50, diff = 26 (no xp)
final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
double exp = expSp[0]; double exp = expSp[0];
double sp = expSp[1]; double sp = expSp[1];
@ -1302,67 +1306,70 @@ public class L2Attackable extends L2Npc
*/ */
private double[] 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 = charLevel - getLevel();
double xp = Math.max(0, (getExpReward() * damage) / totalDamage); double xp = 0;
double sp = Math.max(0, (getSpReward() * damage) / totalDamage); double sp = 0;
if ((levelDiff < 11) && (levelDiff > -11))
{
xp = Math.max(0, (getExpReward() * damage) / totalDamage);
sp = Math.max(0, (getSpReward() * damage) / totalDamage);
if ((charLevel > 84) && (levelDiff <= -3))
{
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
case 0: case -3:
case 1:
case 2:
{
mul = 1.;
break;
}
case 3:
{ {
mul = 0.97; mul = 0.97;
break; break;
} }
case 4: case -4:
{ {
mul = 0.67; mul = 0.67;
break; break;
} }
case 5: case -5:
{ {
mul = 0.42; mul = 0.42;
break; break;
} }
case 6: case -6:
{ {
mul = 0.25; mul = 0.25;
break; break;
} }
case 7: case -7:
{ {
mul = 0.15; mul = 0.15;
break; break;
} }
case 8: case -8:
{ {
mul = 0.09; mul = 0.09;
break; break;
} }
case 9: case -9:
{ {
mul = 0.05; mul = 0.05;
break; break;
} }
case 10: case -10:
{ {
mul = 0.03; mul = 0.03;
break; break;
} }
default: default:
{ {
mul = 0.; mul = 1.;
break; break;
} }
} }
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
}
}
return new double[] return new double[]
{ {

View File

@ -469,6 +469,10 @@ public class L2Attackable extends L2Npc
// Calculate Exp and SP rewards // Calculate Exp and SP rewards
if (isInSurroundingRegion(attacker)) if (isInSurroundingRegion(attacker))
{ {
// Calculate the difference of level between this attacker (player or servitor owner) and the L2Attackable
// mob = 24, atk = 10, diff = -14 (full xp)
// mob = 24, atk = 28, diff = 4 (some xp)
// mob = 24, atk = 50, diff = 26 (no xp)
final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage); final double[] expSp = calculateExpAndSp(attacker.getLevel(), damage, totalDamage);
double exp = expSp[0]; double exp = expSp[0];
double sp = expSp[1]; double sp = expSp[1];
@ -1302,67 +1306,70 @@ public class L2Attackable extends L2Npc
*/ */
private double[] 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 = charLevel - getLevel();
double xp = Math.max(0, (getExpReward() * damage) / totalDamage); double xp = 0;
double sp = Math.max(0, (getSpReward() * damage) / totalDamage); double sp = 0;
if ((levelDiff < 11) && (levelDiff > -11))
{
xp = Math.max(0, (getExpReward() * damage) / totalDamage);
sp = Math.max(0, (getSpReward() * damage) / totalDamage);
if ((charLevel > 84) && (levelDiff <= -3))
{
double mul; double mul;
switch (levelDiff) switch (levelDiff)
{ {
case 0: case -3:
case 1:
case 2:
{
mul = 1.;
break;
}
case 3:
{ {
mul = 0.97; mul = 0.97;
break; break;
} }
case 4: case -4:
{ {
mul = 0.67; mul = 0.67;
break; break;
} }
case 5: case -5:
{ {
mul = 0.42; mul = 0.42;
break; break;
} }
case 6: case -6:
{ {
mul = 0.25; mul = 0.25;
break; break;
} }
case 7: case -7:
{ {
mul = 0.15; mul = 0.15;
break; break;
} }
case 8: case -8:
{ {
mul = 0.09; mul = 0.09;
break; break;
} }
case 9: case -9:
{ {
mul = 0.05; mul = 0.05;
break; break;
} }
case 10: case -10:
{ {
mul = 0.03; mul = 0.03;
break; break;
} }
default: default:
{ {
mul = 0.; mul = 1.;
break; break;
} }
} }
xp *= mul; xp *= mul;
sp *= mul; sp *= mul;
}
}
return new double[] return new double[]
{ {