• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!
  • 2026 staff recruitment is open! Check it out and consider applying!

[EXPLORATON] PVPE Threshold

Michael Orsino

Premium User
Premium User
Support Team
Joined
Nov 15, 2007
Messages
864
Solutions
10
Reaction score
451
Location
Western Australia
From what I have seen the majority of people, including myself, do not know how the pvpe threshold system works. So let us explore it, or perhaps someone can offer a full explanation on the system.

Here is the default config.lua extract of the pvpe threshold.
-- Experience from players
-- NOTE: min~Threshold* set to 0 will disable the minimum threshold:
-- player will gain experience from every lower leveled player.
-- max~Threshold* set to 0 will disable the maximum threshold:
-- player will gain experience from every higher leveled player.
minLevelThresholdForKilledPlayer = 0.9
maxLevelThresholdForKilledPlayer = 1.1

Focusing on the default values (0.9 and 1.1)

I look at them as percentage representations, where 1=100%(of the players level). This would suggest that "minLevelThresholdForKillerPlayer = 0.9" would mean that if the victim was within 90% of the killers level, they would gain exp. (level 100 killer, minimum victim level 90.)
Furthering this concept "maxLevelThresholdForKillerPlayer = 1.1" would suggest that if the victim is within 110% of the killers level, they would gain exp. (level 100 killer, maximum victim level 110)

If this concept is correct, then there are some confusions and some conclusions that can be drawn.
- minLevelThresholdForKilledPlayer = 0
"set to 0 will disable the minimum threshold"
Disables the minimum threshold, all players will gain EXP for killing all players lower, irrelevant of level.
OR
- minLevelThresholdForKillerPlayer = 0
Working on percentages. playerlevel x 0 = 0. Players cannot gain EXP from any player lower than them.
AND
- maxLevelThresholdForKilledPlayer = 0
"set to 0 will disable the minimum threshold"
Disables the maximum threshold, all players will gain EXP from all players higher than them, irrelevant of level.
OR
- maxLevelThresholdForKilledPlayer = 0
Working on percentages, playerlevel x 0 = 0. Players cannot gain EXP from any player higher than them.



Many people have expressed confusion at the 'explanatory' text accompanying the threshold in the config.lua, as you can probably see by the possible understandings and misconceptions that can be reached by reading them evident in the conclusions I have attempted to draw.

Ultimately, I do not know how exactly the threshold works.
I propose that a better explanation be offered. ESPECIALLY because in the CONFIG_HELP, there is no explanation at all! Only the default values.

Can anyone explain the system completely? Anyone read it differently?
Anyone managed to simply work out "what works"?

I probably sound like an idiot, but hey. I have seen countless people get angry at people asking about the system, angrily posting the information commented in config.lua as though the user hasnt already read it. Good work, guys. And I said I sound like an idiot, imagine how you look.
 
Code:
double Player::getGainedExperience(Creature* attacker) const
{
	if(!skillLoss)
		return 0;

	double rate = g_config.getDouble(ConfigManager::RATE_PVP_EXPERIENCE);
	if(rate <= 0)
		return 0;

	Player* attackerPlayer = attacker->getPlayer();
	if(!attackerPlayer || attackerPlayer == this)
		return 0;

[B][COLOR="Red"]	double attackerLevel = (double)attackerPlayer->getLevel(), min = g_config.getDouble(
		ConfigManager::EFP_MIN_THRESHOLD), max = g_config.getDouble(ConfigManager::EFP_MAX_THRESHOLD);
	if((min > 0 && level < (uint32_t)std::floor(attackerLevel * min)) || (max > 0 &&
		level > (uint32_t)std::floor(attackerLevel * max)))
		return 0;[/COLOR][/B]

	/*
		Formula
		a = attackers level * 0.9
		b = victims level
		c = victims experience

		result = (1 - (a / b)) * 0.05 * c
		Not affected by special multipliers(!)
	*/
	uint32_t a = (uint32_t)std::floor(attackerLevel * 0.9), b = level;
	uint64_t c = getExperience();
	return (double)std::max((uint64_t)0, (uint64_t)std::floor(getDamageRatio(attacker)
		* std::max((double)0, ((double)(1 - (((double)a / b))))) * 0.05 * c)) * rate;
}
Edit, hope it's easier to understand:
Code:
attackerLevel = getLevel(attackerPlayer)
min = minLevelThresholdForKilledPlayer
max = maxLevelThresholdForKilledPlayer

if (min > 0 and level < (attackerLevel * min)) or (max > 0 and level > (attackerLevel * max))
	return 0 -- killer(s) won't get any exp
 
Last edited:
So by my understanding of that, if the kill satisfies one of the following two statements, then the player will gain EXP. correct?

if the minimum threshold is greater than 0 and the attackers level is less than the attackers level multiplied by the minimum threshold THEN THE ATTACKER WILL GAIN EXP

if the maximum threshold is greater than 0 and the attackers level is greater than the attackers level multiplied by the maximum threshold THEN THE ATTACKER WILL GAIN EXP

The current explanation in the config.lua is fairly unhelpful.

Edit: think I understood the original fine, didnt bother reading the amended version
Edit2: If these statements are satisfied, will the attacker(s) gain, or not gain exp?
 
So by my understanding of that, if the kill satisfies one of the following two statements, then the player will gain EXP. correct?
Other way around, return 0 means that killers won't get any exp.

if the minimum threshold is greater than 0 and the attackers level is less than the attackers level multiplied by the minimum threshold THEN THE ATTACKER WILL GAIN EXP

if the maximum threshold is greater than 0 and the attackers level is greater than the attackers level multiplied by the maximum threshold THEN THE ATTACKER WILL GAIN EXP
Hey um, no.
level is victim's level, and attackerLevel is level of the killer/attacker.
 
Nope, didnt find my error. Sigh. bed time.

Ahh okay. So let us summerize.

Supposing that the minimum threshold IS greater than 0
If the victims level is less than the attackers level multiplied by the minimum threshold, the player will not gain

EXP.

If the victims level is greater than the attackers level multiplied by the maximum threshold, the player will not gain

EXP.

EXAMPLE: Level 120 KILLS level 100.
minLevelThresholdForKilledPlayer = 0.9
maxLevelThresholdForKilledPlayer = 1.1

if 100 < (120x0.9) then no exp gained
120x0.9=108. therefore 100<108 therefore NO EXP GAINED
meaning that in this example, 108 is the lowest level a level 120 can kill and still gain exp



For people that want a system where ALL players gain EXP from killing ALL players, what should we do?

EXAMPLE: level 200 KILLS level 8.
minLevelThresholdForKilledPlayer = 0
maxLevelThresholdForKilledPlayer = 0

if 8 < (200x0) then no exp gained
200x0=0 therefore 8>0 therefore EXP GAINED

EXAMPLE: level 8 kills level 200.
200 > (8x0) then no exp gained
8x0=0 therefore 200>0 therefore NO EXP GAINED

By this, I conclude that setting the minimum to 0 does in fact make high level characters benefit from killing any lower leveled

character, HOWEVER setting the maximum to 0 will not do the same, it will not 'disable' the maximum threshold, at least not in the

same sense/understanding that using 0 for the minimum does.
My brain is now thoroughly confused and tired, cannot continue.

What threshold values should a user input if he or she wishes for all players to gain exp from all players irrelevant of level?
minLevelThresholdForKilledPlayer = 0
maxLevelThresholdForKilledPlayer = ?

mind just flipped again, i must have done something wrong somewhere up higher. Or totally missed or misread something.

Care to explain in words, for mine and everyone else's benefit how it works? I had hoped to work it out myself with your help but

apparently I am too tired, brain is really struggling to work around the simple maths at this hour
 
You're not the only one with this problem, I suggest removing the bold red part from my first post (in player.cpp)
 
Will do, thank you very much.
It is pretty annoying that there is no real explanation of this anywhere from what I have seen.
As far as I know you are the first person to actually explain it this far.

I wonder if better threshold rules could be written.
 
For what it's worth it, I may have found the source of this problem.
Looking at this code:
Code:
double attackerLevel = (double)attackerPlayer->getLevel(), min = g_config.getDouble(
ConfigManager::EFP_MIN_THRESHOLD), max = g_config.getDouble(ConfigManager::EFP_MAX_THRESHOLD);
if((min > 0 && level < (uint32_t)std::floor(attackerLevel * min)) || (max > 0 &&
level > (uint32_t)std::floor(attackerLevel * max)))
return 0;[/COLOR][/B]

/*
Formula
a = attackers level * 0.9
b = victims level
c = victims experience

result = (1 - (a / b)) * 0.05 * c
Not affected by special multipliers(!)
*/
uint32_t a = (uint32_t)std::floor(attackerLevel * 0.9), b = level;
uint64_t c = getExperience();
return (double)std::max((uint64_t)0, (uint64_t)std::floor(getDamageRatio(attacker)
* std::max((double)0, ((double)(1 - (((double)a / b))))) * 0.05 * c)) * rate;
}

It is apparent that with min = 0; max = 0 then the first condition will never be satisfied thus return 0 doesn't happen.
Nonetheless with both min and max set to 0 at config.lua when killing a LOWER LEVELLED CHARACTER with a HIGHER LEVEL CHARACTER, you get NO EXP.
Writing everything as to be read by as simple humans (no C++ psychos)
Code:
return max(0, floor(getDamageRatio(attacker) * max(0, ( (1 - (( a / b ))))) * 0.05 * c)) * rate

    CASE I) if a/b > 1 then a >> b
 
    CASE II) if a/b < 1 then a > b (little diff) or a < b -- Remember a = attlevel * 0.9 so at attlevel > level with little distance then a < b could happen potentially.
 
    CASE I:
    if a/b > 1 then 1 - (n > 1) => n < 0
 
    => return max(0, floor(getDamageRatio(attacker) * max(0, n < 0) * 0.05 * c)) * rate
    => return max(0, floor(getDamageRatio(attacker) * 0 * 0.05 * c)) * rate
    => return max(0, floor(0)) * rate
    => return max(0, 0) * rate => return 0 * rate => return 0
 
    CASE II:
    if a/b < 1 then 1 - (n < 1) => n > 0
 
    => return max(0, floor(getDamageRatio(attacker) * max(0, n > 0) * 0.05 * c)) * rate
    => return max(0, floor(getDamageRatio(attacker) * n>0 * 0.05 * c)) * rate -- Remember c >> 0 for high levels.
    => return max(0, floor(getDamageRatio(attacker) * n >> 0)) * rate
    => return max(0, floor(n >> 0)) * rate
    => return max(0, n >> 0) * rate => return n >> 0 * rate => return n >> 0

I've done a little calculation and the high-level character - low-level character difference (with a/b positive for 1st case) is 3.~ times MORE (and it should increase non-linear). The system works fine and the gap increases if the distance between the level increases due to c (experience from the dead).
The fix should be to get advantage to the low-level character something like:
Code:
if((1 - (a/b)) < 0) {
    return (double)std::max((uint64_t)0, (uint64_t)std::floor(getDamageRatio(attacker) * std::max((double)0, ((double)(-(1 - (((double)a / b)))))) * 0.05 * c)) * rate;
} else {
    return (double)std::max((uint64_t)0, (uint64_t)std::floor(getDamageRatio(attacker) * std::max((double)0, ((double)(1 - (((double)a / b))))) * 0.05 * c)) * rate;
}

Well if anyone got it and could test it out it would be great, I'll think I will test it myself aswell.. The problem seems to coincide with what happens in-game so I guess it is correct. Also I'm not sure this couples with RL tibia (heck I don't even know if high level gets exp when killing low levels? I guess they do..).

PS: Sorry for bumping such an old topic, I was running into this problem and found this thread, maybe there are others with the same problem as I do.
PS2: This should be solveable by LUA much easily I guess.
PS3: Here thought case:
Supposed case ONE

a/b > 1

attackerLevel = 435
level = 302

a = 391.5
b = 302
c = 450025100

return std::max(0, std::floor(getDamageRatio(attacker) * std::max(0, 1-a/b) *0.05*c))*rate

max(0, 1-(1.29635761589404))*0.05*450025100
0*0.05*450025100 => Here if |1-(1.3~)| => 0.3 positive giving aprox. result = 6750300 that is aprox. (case2 result/4~)
which is expectable since a is higher level.

result = 0

return std::max(0, std::floor(getDamageRatio(attacker) * 0)) * rate

return std::max(0, std:floor(0)) => return 0 * rate => return 0


Supposed case TWO

a/b < 1

attackerLevel = 302
level = 435

a = 271.8
b = 435
c = 1.~

max(0, 1-(271.8/435)) * 0.05 * 1.~

max(0, 1-(0.6248275862088966))*0.05*1.~
0.3751724137911034 * 0.05 * 1,353,081,800

result = 25381948.24814055

return std::max(0, getDamageRatio(attacker)) * std::max(0, 25381948.24814055)
return (getDamageRatio(attacker) * 25381948.24814055)*rate => return (n >> 0) * rate => return n >> 0

EDIT: Well this IS HOW IT IS SUPPOSED TO WORK! The only problem is the misconception at config.lua but the formula is SPOT ON, perfect.
 
Last edited:

Similar threads

Back
Top