Standard level scaling now mirrors RetroMode in a true 1:10 parity

This commit is contained in:
nossr50
2019-05-27 17:37:54 -07:00
parent 33dd34931c
commit 50e4e971d9
7 changed files with 130 additions and 37 deletions

View File

@ -15,8 +15,10 @@ public class FormulaManager {
private static File formulaFile = new File(mcMMO.getFlatFileDirectory() + "formula.yml");
// Experience needed to reach a level, cached values to improve conversion speed
private final Map<Integer, Integer> experienceNeededLinear = new HashMap<Integer, Integer>();
private final Map<Integer, Integer> experienceNeededExponential = new HashMap<Integer, Integer>();
private Map<Integer, Integer> experienceNeededRetroLinear;
private Map<Integer, Integer> experienceNeededStandardLinear;
private Map<Integer, Integer> experienceNeededRetroExponential;
private Map<Integer, Integer> experienceNeededStandardExponential;
private FormulaType previousFormula;
@ -26,9 +28,20 @@ public class FormulaManager {
public FormulaManager() {
/* Setting for Classic Mode (Scales a lot of stuff up by * 10) */
retroModeEnabled = Config.getInstance().getIsRetroMode();
initExperienceNeededMaps();
loadFormula();
}
/**
* Initialize maps used for XP to next level
*/
private void initExperienceNeededMaps() {
experienceNeededRetroLinear = new HashMap<>();
experienceNeededRetroExponential = new HashMap<>();
experienceNeededStandardLinear = new HashMap<>();
experienceNeededStandardExponential = new HashMap<>();
}
/**
* Get the formula type that was used before converting
*
@ -60,7 +73,7 @@ public class FormulaManager {
int totalXP = 0;
for (int level = 0; level < skillLevel; level++) {
totalXP += getCachedXpToLevel(level, previousFormula);
totalXP += getXPtoNextLevel(level, previousFormula);
}
totalXP += skillXPLevel;
@ -83,7 +96,7 @@ public class FormulaManager {
int maxLevel = Config.getInstance().getLevelCap(primarySkillType);
while (experience > 0 && newLevel < maxLevel) {
int experienceToNextLevel = getCachedXpToLevel(newLevel, formulaType);
int experienceToNextLevel = getXPtoNextLevel(newLevel, formulaType);
if (experience - experienceToNextLevel < 0) {
remainder = experience;
@ -106,42 +119,97 @@ public class FormulaManager {
* @param formulaType The {@link FormulaType} used
* @return amount of experience needed to reach next level
*/
public int getCachedXpToLevel(int level, FormulaType formulaType) {
int experience;
public int getXPtoNextLevel(int level, FormulaType formulaType) {
/**
* Retro mode XP requirements are the default requirements
* Standard mode XP requirements are multiplied by a factor of 10
*/
int xpNeededMultiplier = retroModeEnabled ? 1 : 10;
//TODO: When the heck is Unknown used?
if (formulaType == FormulaType.UNKNOWN) {
formulaType = FormulaType.LINEAR;
}
return processXPToNextLevel(level, formulaType);
}
/**
* Gets the value of XP needed for the next level based on the level Scaling, the level, and the formula type
* @param level target level
* @param formulaType target formulaType
*/
private int processXPToNextLevel(int level, FormulaType formulaType) {
if(mcMMO.isRetroModeEnabled())
{
return processXPRetroToNextLevel(level, formulaType);
} else {
return processStandardXPToNextLevel(level, formulaType);
}
}
/**
* Calculate the XP needed for the next level for the linear formula for Standard scaling (1-100)
* @param level target level
* @return raw xp needed to reach the next level
*/
private int processStandardXPToNextLevel(int level, FormulaType formulaType) {
Map<Integer, Integer> experienceMapRef = formulaType == FormulaType.LINEAR ? experienceNeededStandardLinear : experienceNeededStandardExponential;
if(!experienceMapRef.containsKey(level)) {
int experienceSum = 0;
int retroIndex = (level * 10) + 1;
//Sum the range of levels in Retro that this Standard level would represent
for(int x = retroIndex; x < (retroIndex + 10); x++) {
//calculateXPNeeded doesn't cache results so we use that instead of invoking the Retro XP methods to avoid memory bloat
experienceSum += calculateXPNeeded(x, formulaType);
}
experienceMapRef.put(level, experienceSum);
}
return experienceMapRef.get(level);
}
/**
* Calculates the XP to next level for Retro Mode scaling
* Results are cached to reduce needless operations
* @param level target level
* @param formulaType target formula type
* @return raw xp needed to reach the next level based on formula type
*/
private int processXPRetroToNextLevel(int level, FormulaType formulaType) {
Map<Integer, Integer> experienceMapRef = formulaType == FormulaType.LINEAR ? experienceNeededRetroLinear : experienceNeededRetroExponential;
if (!experienceMapRef.containsKey(level)) {
int experience = calculateXPNeeded(level, FormulaType.LINEAR);
experienceMapRef.put(level, experience);
}
return experienceMapRef.get(level);
}
/**
* Does the actual math to get the XP needed for a level in RetroMode scaling
* Standard uses a sum of RetroMode XP needed levels for its own thing, so it uses this too
* @param level target level
* @param formulaType target formulatype
* @return the raw XP needed for the next level based on formula type
*/
private int calculateXPNeeded(int level, FormulaType formulaType) {
int base = ExperienceConfig.getInstance().getBase(formulaType);
double multiplier = ExperienceConfig.getInstance().getMultiplier(formulaType);
double exponent = ExperienceConfig.getInstance().getExponent(formulaType);
switch (formulaType) {
switch(formulaType) {
case LINEAR:
if (!experienceNeededLinear.containsKey(level)) {
experience = (int) Math.floor( xpNeededMultiplier * (base + level * multiplier));
experienceNeededLinear.put(level, experience);
}
return experienceNeededLinear.get(level);
return (int) Math.floor(base + level * multiplier);
case EXPONENTIAL:
if (!experienceNeededExponential.containsKey(level)) {
experience = (int) Math.floor( xpNeededMultiplier * (multiplier * Math.pow(level, exponent) + base));
experienceNeededExponential.put(level, experience);
}
return experienceNeededExponential.get(level);
double exponent = ExperienceConfig.getInstance().getExponent(formulaType);
return (int) Math.floor(multiplier * Math.pow(level, exponent) + base);
default:
return 0;
//TODO: Should never be called
mcMMO.p.getLogger().severe("Invalid formula specified for calculation, defaulting to Linear");
return calculateXPNeeded(level, FormulaType.LINEAR);
}
}