pagefaultgames / pokerogue

A browser based Pokémon fangame heavily inspired by the roguelite genre.
https://pokerogue.net
GNU Affero General Public License v3.0
3.89k stars 1.56k forks source link

Rework Exp Balance implementation #1410

Open zizibaloob opened 1 month ago

zizibaloob commented 1 month ago

The Exp. Balance item is currently implemented in a way that leads to less than desirable outcomes. A summary of the current implementation follows.

Current Exp Balance implementation - Normal exp gains for each pokemon are calculated (including bonuses from lucky/golden eggs and pokerus) - The `splitExp` value is calculated: the total amount of exp gained by all party members divided by the number of party members that gained exp - The mean level (despite the name `medianLevel`) for all party members that gained exp is calculated - For each party member above the mean level, they receive between 80% (at 1 stack) and 0% (at 5 stacks) of the original experience they would have gained - For each party member at or below the mean level, they receive between 20% (at 1 stack) and 100% (at 5 stacks) of the `splitExp` value

At five stacks, this means that any pokemon above the mean level gets 0 exp, and any pokemon at or below the mean level gets an equal share of the entire exp pool. Among other things, this can mean:

Rather than basing everything around the mean party level, I suggest distributing the total exp pool in a weighted manner based on how far each party member is from the current level cap. This would mean that you never wind up in a situation where any pokemon receives zero exp, and make it so that you avoid massively over-allocating exp to a single party member in situations where they are near the level cap.

Pseudo-code overview of suggested algorithm if (expBalanceModifier) { totalExp = total exp gained by all participating members partyMembersDistanceToCap = array of amount of exp necessary for each party member to hit the level cap totalDistanceToCap = sum of all values in partyMembersDistanceToCap partyMemberRatios = array of partyMembersDistanceToCap[i] / totalDistanceToCap for each participating member { rebalancedExp = totalExp * partyMemberRatios[i] final exp granted = linear from [original exp value] to rebalancedExp, based on stack count } }

I have never written typescript code before, but I believe the following works as a drop-in replacement for the current Exp Balance implementation (in phases.ts):

Suggested real implementation if (expBalanceModifier) { let totalExp = 0; expPartyMembers.forEach((expPartyMember, epm) => { totalExp += partyMemberExp[epm]; }); let totalDistanceToCap = 0; const partyMemberDistanceToCap = []; expPartyMembers.forEach((expPartyMember, epm) => { const expToLevelCap = expPartyMember.getExpToLevelCap(); totalDistanceToCap += expToLevelCap; partyMemberDistanceToCap.push(expToLevelCap); }); const partyMemberExpRatios = []; expPartyMembers.forEach((expPartyMember, epm) => { partyMemberExpRatios.push(partyMemberDistanceToCap[epm] / totalDistanceToCap); }); expPartyMembers.forEach((_partyMember, pm) => { const rebalancedExp = Math.floor(totalExp * partyMemberExpRatios[pm]); partyMemberExp[pm] = Phaser.Math.Linear(partyMemberExp[pm], rebalancedExp, 0.2 * expBalanceModifier.getStackCount()); }); } This includes a new `getExpToLevelCap()` function, which would look like this (in `pokemon.ts`): getExpToLevelCap(): integer { const levelCapExp = getLevelTotalExp(this.scene.getMaxExpLevel(), this.species.growthRate); return levelCapExp - this.exp; }
wuzhaoqi1015 commented 1 month ago

Agree with this suggestion, but it has to be optimized, and the empirical calculation method can be turned into a parameter setting for the user to choose. Provide two modes of exp calculation: Traditional and new models (based on how far each party member is from the current level cap)

Xavion3 commented 3 weeks ago

EXP Balance are capped at 4 so you already can't get to a situation where a pokemon gets zero experience.

zizibaloob commented 3 weeks ago

The pull request that reduced the cap to 4 explicitly called out that they were looking for a better implementation:

The EXP Balance item is not currently functioning as a useful item. This reduces the item's Max Stack Count temporarily until a better solution can be found.

IMO, regardless of stack count, a proportional allocation is more useful than an even one.