package com.gmail.nossr50.util.experience; import java.io.File; import java.util.HashMap; import java.util.Map; import org.bukkit.configuration.file.YamlConfiguration; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.datatypes.experience.FormulaType; import com.gmail.nossr50.datatypes.skills.SkillType; 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 FormulaType previousFormula; public FormulaManager() { loadFormula(); } /** * Get the formula type that was used before converting * * @return previously used formula type */ public FormulaType getPreviousFormulaType() { return previousFormula; } /** * Set the formula type that was used before converting * * @param previousFormulaType The {@link FormulaType} previously used */ public void setPreviousFormulaType(FormulaType previousFormulaType) { this.previousFormula = previousFormulaType; } /** * Calculate the total amount of experience earned based on * the amount of levels and experience, using the previously * used formula type. * * @param skillLevel Amount of levels * @param skillXPLevel Amount of experience * @return The total amount of experience */ public int calculateTotalExperience(int skillLevel, int skillXPLevel) { int totalXP = 0; for (int level = 0; level < skillLevel; level++) { totalXP += getCachedXpToLevel(level, previousFormula); } totalXP += skillXPLevel; return totalXP; } /** * Calculate how many levels a player should have using * the new formula type. * * @param skillType skill where new levels and experience are calculated for * @param experience total amount of experience * @param formulaType The new {@link FormulaType} * @return the amount of levels and experience */ public int[] calculateNewLevel(SkillType skillType, int experience, FormulaType formulaType) { int newLevel = 0; int remainder = 0; int maxLevel = Config.getInstance().getLevelCap(skillType); while (experience > 0 && newLevel < maxLevel) { int experienceToNextLevel = getCachedXpToLevel(newLevel, formulaType); if (experience - experienceToNextLevel < 0) { remainder = experience; break; } newLevel++; experience -= experienceToNextLevel; } return new int[]{ newLevel, remainder }; } /** * Get the cached amount of experience needed to reach the next level, * if cache doesn't contain the given value it is calculated and added * to the cached data. * * @param level level to check * @param formulaType The {@link FormulaType} used * @return amount of experience needed to reach next level */ public int getCachedXpToLevel(int level, FormulaType formulaType) { int experience; 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); switch (formulaType) { case LINEAR: if (!experienceNeededLinear.containsKey(level)) { experience = (int) Math.floor(base + level * multiplier); experienceNeededLinear.put(level, experience); } return experienceNeededLinear.get(level); case EXPONENTIAL: if (!experienceNeededExponential.containsKey(level)) { experience = (int) Math.floor(multiplier * Math.pow(level, exponent) + base); experienceNeededExponential.put(level, experience); } return experienceNeededExponential.get(level); default: return 0; } } /** * Load formula file. */ public void loadFormula() { if (!formulaFile.exists()) { previousFormula = FormulaType.UNKNOWN; return; } previousFormula = FormulaType.getFormulaType(YamlConfiguration.loadConfiguration(formulaFile).getString("Previous_Formula", "UNKNOWN")); } /** * Save formula file. */ public void saveFormula() { mcMMO.p.debug("Saving previous XP formula type..."); YamlConfiguration formulasFile = new YamlConfiguration(); formulasFile.set("Previous_Formula", previousFormula.toString()); try { formulasFile.save(formulaFile); } catch (Exception e) { e.printStackTrace(); } } }