|
@@ -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;
|
|
|
}
|
|
|
|
|
|
- int base = ExperienceConfig.getInstance().getBase(formulaType);
|
|
|
- double multiplier = ExperienceConfig.getInstance().getMultiplier(formulaType);
|
|
|
- double exponent = ExperienceConfig.getInstance().getExponent(formulaType);
|
|
|
+ return processXPToNextLevel(level, formulaType);
|
|
|
+ }
|
|
|
|
|
|
- switch (formulaType) {
|
|
|
- case LINEAR:
|
|
|
- if (!experienceNeededLinear.containsKey(level)) {
|
|
|
- experience = (int) Math.floor( xpNeededMultiplier * (base + level * multiplier));
|
|
|
- experienceNeededLinear.put(level, experience);
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return experienceNeededLinear.get(level);
|
|
|
+ /**
|
|
|
+ * 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;
|
|
|
|
|
|
- case EXPONENTIAL:
|
|
|
- if (!experienceNeededExponential.containsKey(level)) {
|
|
|
- experience = (int) Math.floor( xpNeededMultiplier * (multiplier * Math.pow(level, exponent) + base));
|
|
|
- experienceNeededExponential.put(level, experience);
|
|
|
- }
|
|
|
+ if(!experienceMapRef.containsKey(level)) {
|
|
|
+ int experienceSum = 0;
|
|
|
+ int retroIndex = (level * 10) + 1;
|
|
|
|
|
|
- return experienceNeededExponential.get(level);
|
|
|
+ //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);
|
|
|
+
|
|
|
+ switch(formulaType) {
|
|
|
+ case LINEAR:
|
|
|
+ return (int) Math.floor(base + level * multiplier);
|
|
|
+ case EXPONENTIAL:
|
|
|
+ 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);
|
|
|
}
|
|
|
}
|
|
|
|