[Skills] Configurable Exponential Decay Formula for Skill Up (#1887)

* [Skills] Exponential Decay Skill Up Formula

Added an exponential decay skill up formula option.
The current, linear, formula results in negative chances to skill up, which
have been mitigated via a multiplier and minimum of 1%

* [Skills]Configurable Exponential Decay Formala for Skill Up

What this fixes:
The existing formula for determining whether or not to skill up could result
in negative chances, and made an assumption around the number 252.
This would ultimately result in an override that would set the chance to 1.

My fix:
I created 2 new rules:
Character:SkillUpMaximumChancePercentage
Character:SkillUpMinimumChancePercentage

I changed the forumla to:
chance = ((max - min + skill_modification) * (.99^skill)) + min

This results in an exponential decay that starts at skill-modified maximum
and approaches minimum.

I decided that max-min+skill_modification should never be less than min
I also decided to continue to apply the Character:SkillUpModifier rule
post-calculation.  I do not really think this is necessary anymore, given
this new formula, but we can discuss removing it.
I chose 25 and 2 as default maximum and minimum based on feel.

Related method signature fix:

Client::mod_increase_skill_chance was changed to return a double and
accept a double as an input for chance.  This matches the actual data types
provided while calling the method and eliminates some type coersion and
resultant truncation.  Right now, this method doesn't do anything, but in the
future we could implement skill-specific training dummies that accelerate
skill ups.  I deduce that this is the purpose of this method call.

* [Skills]Configurable Exponential Decay Formula for Skill Up

What this fixes:
The existing formula for determining whether or not to skill up could result
in negative chances, and made an assumption around the number 252.
This would ultimately result in an override that would set the chance to 1.

My fix:
I created 2 new rules:
Character:SkillUpMaximumChancePercentage
Character:SkillUpMinimumChancePercentage

I changed the forumla to:
chance = ((max - min + skill_modification) * (.99^skill)) + min

This results in an exponential decay that starts at skill-modified maximum
and approaches minimum.

I decided that max-min+skill_modification should never be less than min
I also decided to continue to apply the Character:SkillUpModifier rule
post-calculation.  I do not really think this is necessary anymore, given
this new formula, but we can discuss removing it.
I chose 25 and 2 as default maximum and minimum based on feel.

Related method signature fix:

Client::mod_increase_skill_chance was changed to return a double and
accept a double as an input for chance.  This matches the actual data types
provided while calling the method and eliminates some type coersion and
resultant truncation.  Right now, this method doesn't do anything, but in the
future we could implement skill-specific training dummies that accelerate
skill ups.  I deduce that this is the purpose of this method call.

* fixup! [Skills]Configurable Exponential Decay Formula for Skill Up

* fixup! [Skills]Configurable Exponential Decay Formula for Skill Up
This commit is contained in:
mmcgarvey 2022-01-29 21:01:58 -05:00 committed by GitHub
parent 7749c626f0
commit 58d5983ef1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 14 deletions

View File

@ -174,6 +174,8 @@ RULE_INT(Character, ResurrectionSicknessSpellID, 756, "756 is Default Resurrecti
RULE_BOOL(Character, EnableBardMelody, true, "Enable Bard /melody by default, to disable change to false for a classic experience.")
RULE_BOOL(Character, EnableRangerAutoFire, true, "Enable Ranger /autofire by default, to disable change to false for a classic experience.")
RULE_BOOL(Character, EnableTGB, true, "Enable /tgb (Target Group Buff) by default, to disable change to false for a classic experience.")
RULE_INT(Character, SkillUpMaximumChancePercentage, 25, "Maximum chance to improve a combat skill, before skill-specific modifiers. This should be greater than SkillUpMinimumChancePercentage.")
RULE_INT(Character, SkillUpMinimumChancePercentage, 2, "Minimum chance to improve a combat skill, after skill-specific modifiers. This should be lesser than SkillUpMaximumChancePercentage.")
RULE_INT(Character, WarriorTrackingDistanceMultiplier, 0, "If you want warriors to be able to track, increase this above 0. 0 disables tracking packets.")
RULE_INT(Character, ClericTrackingDistanceMultiplier, 0, "If you want clerics to be able to track, increase this above 0. 0 disables tracking packets.")
RULE_INT(Character, PaladinTrackingDistanceMultiplier, 0, "If you want paladins to be able to track, increase this above 0. 0 disables tracking packets.")

View File

@ -2422,7 +2422,7 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who,
return false;
if (skillid > EQ::skills::HIGHEST_SKILL)
return false;
int skillval = GetRawSkill(skillid);
int skillval = GetRawSkill(skillid);
int maxskill = GetMaxSkillAfterSpecializationRules(skillid, MaxSkill(skillid));
std::string export_string = fmt::format(
"{} {}",
@ -2447,23 +2447,26 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who,
// Make sure we're not already at skill cap
if (skillval < maxskill)
{
// the higher your current skill level, the harder it is
int32 Chance = 10 + chancemodi + ((252 - skillval) / 20);
Chance = (Chance * RuleI(Character, SkillUpModifier) / 100);
Chance = mod_increase_skill_chance(Chance, against_who);
if(Chance < 1)
Chance = 1; // Make it always possible
double Chance = 0;
if (RuleI(Character, SkillUpMaximumChancePercentage) + chancemodi - RuleI(Character, SkillUpMinimumChancePercentage) <= RuleI(Character, SkillUpMinimumChancePercentage)) {
Chance = RuleI(Character, SkillUpMinimumChancePercentage);
}
else {
// f(x) = (max - min + modification) * .99^skillval + min
// This results in a exponential decay where as you skill up, you lose a slight chance to skill up, ranging from your modified maximum to approaching your minimum
// This result is increased by the existing SkillUpModifier rule
double working_chance = (((RuleI(Character, SkillUpMaximumChancePercentage) - RuleI(Character, SkillUpMinimumChancePercentage) + chancemodi) * (pow(0.99, skillval))) + RuleI(Character, SkillUpMinimumChancePercentage));
Chance = (working_chance * RuleI(Character, SkillUpModifier) / 100);
Chance = mod_increase_skill_chance(Chance, against_who);
}
if(zone->random.Real(0, 99) < Chance)
{
SetSkill(skillid, GetRawSkill(skillid) + 1);
LogSkills("Skill [{}] at value [{}] successfully gain with [{}]% chance (mod [{}])", skillid, skillval, Chance, chancemodi);
LogSkills("Skill [{}] at value [{}] successfully gain with [{}] chance (mod [{}])", skillid, skillval, Chance, chancemodi);
return true;
} else {
LogSkills("Skill [{}] at value [{}] failed to gain with [{}]% chance (mod [{}])", skillid, skillval, Chance, chancemodi);
LogSkills("Skill [{}] at value [{}] failed to gain with [{}] chance (mod [{}])", skillid, skillval, Chance, chancemodi);
}
} else {
LogSkills("Skill [{}] at value [{}] cannot increase due to maxmum [{}]", skillid, skillval, maxskill);

View File

@ -1566,7 +1566,7 @@ public:
int mod_client_damage(int damage, EQ::skills::SkillType skillinuse, int hand, const EQ::ItemInstance* weapon, Mob* other);
bool mod_client_message(char* message, uint8 chan_num);
bool mod_can_increase_skill(EQ::skills::SkillType skillid, Mob* against_who);
int16 mod_increase_skill_chance(int16 chance, Mob* against_who);
double mod_increase_skill_chance(double chance, Mob* against_who);
int mod_bindwound_percent(int max_percent, Mob* bindmob);
int mod_bindwound_hp(int bindhps, Mob* bindmob);
int mod_client_haste(int h);

View File

@ -61,7 +61,7 @@ bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); }
bool Client::mod_can_increase_skill(EQ::skills::SkillType skillid, Mob* against_who) { return(false); }
//chance of general skill increase, rolled against 0-99 where higher chance is better.
int16 Client::mod_increase_skill_chance(int16 chance, Mob* against_who) { return(chance); }
double Client::mod_increase_skill_chance(double chance, Mob* against_who) { return(chance); }
//Max percent of health you can bind wound starting with default value for class, item, and AA bonuses
int Client::mod_bindwound_percent(int max_percent, Mob* bindmob) { return(max_percent); }