package net.scapeemulator.game.model.player.skills; import java.util.ArrayList; import java.util.List; public final class SkillSet { public static final double MAXIMUM_EXPERIENCE = 200000000; private int hpRegenCounter; private int regenCounter; private static int getLevelFromExperience(double xp) { int points = 0; int output = 0; for (int level = 1; level <= 99; level++) { points += Math.floor(level + 300.0 * Math.pow(2.0, level / 7.0)); output = points / 4; if ((output - 1) >= xp) return level; } return 99; } private final int[] curLevel = new int[24]; private final int[] level = new int[curLevel.length]; private final double[] exp = new double[curLevel.length]; private final List<SkillListener> listeners = new ArrayList<>(); private int combatLevel; public SkillSet() { for (int i = 0; i < curLevel.length; i++) { curLevel[i] = 1; level[i] = 1; exp[i] = 0; } curLevel[Skill.HITPOINTS] = 10; level[Skill.HITPOINTS] = 10; exp[Skill.HITPOINTS] = 1154; calculateCombatLevel(); } public void addListener(SkillListener listener) { listeners.add(listener); } public void removeListener(SkillListener listener) { listeners.remove(listener); } public void removeListeners() { listeners.clear(); } public int size() { return curLevel.length; } public int getCurrentLevel(int skill) { return curLevel[skill]; } public void setCurrentLevel(int skill, int curLvl) { if (curLevel[skill] == curLvl) { return; } curLvl = curLvl < 0 ? 0 : curLvl; curLevel[skill] = curLvl; for (SkillListener listener : listeners) listener.skillChanged(this, skill); } public int getLevel(int skill) { return level[skill]; } public double getExperience(int skill) { return exp[skill]; } public void setExperience(int skill, double experience) { exp[skill] = experience; level[skill] = getLevelFromExperience(exp[skill]); calculateCombatLevel(); } private double xpRate(int skill, double xp) { return xp * 3.0; } /** * Grants experience to the player modified by the XP rate. * * @param skill skill id to grant experience to * @param xp amount of experience to grant */ public void addExperience(int skill, double xp) { addExperience(skill, xp, true); } /** * Grants experience to the player. * * @param skill skill id to grant experience to * @param xp amount of experience to grant * @param modify whether or not the experience should be modifed for the xp rate */ public void addExperience(int skill, double xp, boolean modify) { if (xp <= 0) { return; } xp = xpRate(skill, xp); int oldLevel = level[skill]; int oldCB = combatLevel; exp[skill] = Math.min(exp[skill] + xp, MAXIMUM_EXPERIENCE); level[skill] = getLevelFromExperience(exp[skill]); calculateCombatLevel(); int delta = level[skill] - oldLevel; curLevel[skill] += delta; for (SkillListener listener : listeners) { listener.skillChanged(this, skill); } if (delta > 0) { for (SkillListener listener : listeners) { listener.skillLevelledUp(this, delta, skill); } } if (combatLevel > oldCB) { for (SkillListener listener : listeners) { listener.combatLevelledUp(this, combatLevel); } } } public void refresh() { for (int skill = 0; skill < curLevel.length; skill++) { for (SkillListener listener : listeners) listener.skillChanged(this, skill); } } public void restoreStats() { for (int skill = 0; skill < curLevel.length; skill++) { curLevel[skill] = level[skill]; for (SkillListener listener : listeners) listener.skillChanged(this, skill); } } public int getCombatLevel() { return combatLevel; } public void calculateCombatLevel() { int defence = level[Skill.DEFENCE]; int hitpoints = level[Skill.HITPOINTS]; int prayer = level[Skill.PRAYER]; int attack = level[Skill.ATTACK]; int strength = level[Skill.STRENGTH]; int magic = level[Skill.MAGIC]; int ranged = level[Skill.RANGED]; int summoning = level[Skill.SUMMONING]; double base = 1.3 * Math.max(Math.max(attack + strength, 1.5 * magic), 1.5 * ranged); combatLevel = (int) Math.floor((defence + hitpoints + Math.floor(prayer / 2.0) + Math.floor(summoning / 2.0) + base) / 4.0); } public int getTotalLevel() { int total = 0; for (int skill = 0; skill < curLevel.length; skill++) { total += level[skill]; } return total; } public void tick(int hpRegen, int skillRegen) { if (curLevel[Skill.HITPOINTS] < level[Skill.HITPOINTS]) { hpRegenCounter += hpRegen; if (hpRegenCounter >= 100) { hpRegenCounter = 0; curLevel[Skill.HITPOINTS] = curLevel[Skill.HITPOINTS] + 1; for (SkillListener listener : listeners) { listener.skillChanged(this, Skill.HITPOINTS); } } } regenCounter += skillRegen; if (regenCounter >= 100) { regenCounter = 0; for (int skill = 0; skill < curLevel.length; skill++) { if (skill == Skill.HITPOINTS || skill == Skill.PRAYER) { continue; } if (curLevel[skill] != level[skill]) { if (curLevel[skill] < level[skill]) { curLevel[skill] = curLevel[skill] + 1; } else { curLevel[skill] = curLevel[skill] - 1; } for (SkillListener listener : listeners) { listener.skillChanged(this, skill); } } } } } }