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

@ -649,11 +649,28 @@ public final class ExperienceAPI {
* @return the level of a given skill
*
* @throws InvalidSkillException if the given skill is not valid
* @deprecated Use getLevel(Player player, PrimarySkillType skillType) instead
*/
@Deprecated
public static int getLevel(Player player, String skillType) {
return getPlayer(player).getSkillLevel(getSkillType(skillType));
}
/**
* Get the level a player has in a specific skill.
* </br>
* This function is designed for API usage.
*
* @param player The player to get the level for
* @param skillType The skill to get the level for
* @return the level of a given skill
*
* @throws InvalidSkillException if the given skill is not valid
*/
public static int getLevel(Player player, PrimarySkillType skillType) {
return getPlayer(player).getSkillLevel(skillType);
}
/**
* Get the level an offline player has in a specific skill.
* </br>
@ -995,7 +1012,7 @@ public final class ExperienceAPI {
* @throws InvalidFormulaTypeException if the given formulaType is not valid
*/
public static int getXpNeededToLevel(int level) {
return mcMMO.getFormulaManager().getCachedXpToLevel(level, ExperienceConfig.getInstance().getFormulaType());
return mcMMO.getFormulaManager().getXPtoNextLevel(level, ExperienceConfig.getInstance().getFormulaType());
}
/**
@ -1009,7 +1026,7 @@ public final class ExperienceAPI {
* @throws InvalidFormulaTypeException if the given formulaType is not valid
*/
public static int getXpNeededToLevel(int level, String formulaType) {
return mcMMO.getFormulaManager().getCachedXpToLevel(level, getFormulaType(formulaType));
return mcMMO.getFormulaManager().getXPtoNextLevel(level, getFormulaType(formulaType));
}
/**

View File

@ -203,7 +203,7 @@ public class Party {
public int getXpToLevel() {
FormulaType formulaType = ExperienceConfig.getInstance().getFormulaType();
return (mcMMO.getFormulaManager().getCachedXpToLevel(level, formulaType)) * (getOnlineMembers().size() + Config.getInstance().getPartyXpCurveMultiplier());
return (mcMMO.getFormulaManager().getXPtoNextLevel(level, formulaType)) * (getOnlineMembers().size() + Config.getInstance().getPartyXpCurveMultiplier());
}
public String getXpToLevelPercentage() {

View File

@ -397,7 +397,7 @@ public class PlayerProfile {
int level = (ExperienceConfig.getInstance().getCumulativeCurveEnabled()) ? UserManager.getPlayer(playerName).getPowerLevel() : skills.get(primarySkillType);
FormulaType formulaType = ExperienceConfig.getInstance().getFormulaType();
return mcMMO.getFormulaManager().getCachedXpToLevel(level, formulaType);
return mcMMO.getFormulaManager().getXPtoNextLevel(level, formulaType);
}
private int getChildSkillLevel(PrimarySkillType primarySkillType) {

View File

@ -66,7 +66,7 @@ public enum PrimarySkillType {
ImmutableList.of(SubSkillType.WOODCUTTING_LEAF_BLOWER, SubSkillType.WOODCUTTING_TREE_FELLER, SubSkillType.WOODCUTTING_HARVEST_LUMBER));
private Class<? extends SkillManager> managerClass;
private Color runescapeColor;
private Color skillColor;
private SuperAbilityType ability;
private ToolType tool;
private List<SubSkillType> subSkillTypes;
@ -110,13 +110,13 @@ public enum PrimarySkillType {
NON_CHILD_SKILLS = ImmutableList.copyOf(nonChildSkills);
}
private PrimarySkillType(Class<? extends SkillManager> managerClass, Color runescapeColor, List<SubSkillType> subSkillTypes) {
this(managerClass, runescapeColor, null, null, subSkillTypes);
private PrimarySkillType(Class<? extends SkillManager> managerClass, Color skillColor, List<SubSkillType> subSkillTypes) {
this(managerClass, skillColor, null, null, subSkillTypes);
}
private PrimarySkillType(Class<? extends SkillManager> managerClass, Color runescapeColor, SuperAbilityType ability, ToolType tool, List<SubSkillType> subSkillTypes) {
private PrimarySkillType(Class<? extends SkillManager> managerClass, Color skillColor, SuperAbilityType ability, ToolType tool, List<SubSkillType> subSkillTypes) {
this.managerClass = managerClass;
this.runescapeColor = runescapeColor;
this.skillColor = skillColor;
this.ability = ability;
this.tool = tool;
this.subSkillTypes = subSkillTypes;
@ -243,7 +243,7 @@ public enum PrimarySkillType {
}
/* public void celebrateLevelUp(Player player) {
ParticleEffectUtils.fireworkParticleShower(player, runescapeColor);
ParticleEffectUtils.fireworkParticleShower(player, skillColor);
}*/
public boolean shouldProcess(Entity target) {

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);
}
}