1.16.5 How to Calculate Exp and Levels

Discussion in 'Spigot Plugin Development' started by filtastisch, Jun 10, 2021.

  1. Hey,
    im coding a plugin rn, where if you wanna teleport to some warps, it costs Exp.
    But now im struggeling how to calculate this. I want the further you are the more xp is consumed and when you teleport from another dimension at least 10 lvl plus the levels are consumed for the distance, but that doesn't work.

    Whatever i try, i always get either the message not enough xp, although I have given myself 1000 lvl, or only 0.001 lvl are used

    Code (Java):
       public boolean teleport(Player p) {
            double xp = p.getExp();
            float newXP = (float) (p.getExp() - this.getCost(p));
            if (xp > this.getCost(p)) {
                p.teleport(this.location);
                p.setExp(newXP);
                return true;
            }

            //for debug reason
            p.sendMessage(String.valueOf(newXP));
            return false;
        }

        public String costBetweenWorld(Player p){
            return String.valueOf(getCostBetweenWorlds(p));
        }

        public void remove(){
            all.remove(this);
        }

        /*Getter / Setter*/

        public double getCost(Player p) {
            ExperienceManager expM = new ExperienceManager(p);
            if (Objects.equals(this.location.getWorld(), p.getLocation().getWorld())) {
                return (p.getLocation().distance(this.location) / 2000);
            }
            return (getCostBetweenWorlds(p) / 5000);
        }

        public double getCostBetweenWorlds(Player p){
            double x1, x2, y1, y2, z1, z2;
            x1 = p.getLocation().getX();
            y1 = p.getLocation().getY();
            z1 = p.getLocation().getZ();
            x2 = location.getX();
            y2 = location.getY();
            z2 = location.getZ();


            return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + Math.pow(z1 - z2, 2));
        }
     
    #1 filtastisch, Jun 10, 2021
    Last edited: Jun 10, 2021
  2. SteelPhoenix

    Moderator

    Use the correct method. I doubt you want #getExp() here.
     
  3. wich then?
     
  4. SteelPhoenix

    Moderator

  5. Which method should they use instead? If getExp isn‘t the correct one to get Exp, which one do you think it is?
     
  6. SteelPhoenix

    Moderator

    Look at all exp related methods, read their documentation and pick the one that suits your needs. I do not know which one OP needs because I do not know what he is trying to do. I know that #getExp() returns the progress towards the next level as a fraction (i.e. range [0, 1)) which generally isn't that useful except for some niche applications.
     
    • Agree Agree x 1
  7. There unfortunately is no method to get the total XP, i think the API is very bad regarding this. The total amount of XP can only be calculated :/
     
  8. Code (Java):
    public int getTotalExperience() {
        int experience = 0;
        int level = player.getLevel();
        if(level >= 0 && level <= 15) {
            experience = (int) Math.ceil(Math.pow(level, 2) + (6 * level));
            int requiredExperience = 2 * level + 7;
            double currentExp = Double.parseDouble(Float.toString(player.getExp()));
            experience += Math.ceil(currentExp * requiredExperience);
            return experience;
        } else if(level > 15 && level <= 30) {
            experience = (int) Math.ceil((2.5 * Math.pow(level, 2) - (40.5 * level) + 360));
            int requiredExperience = 5 * level - 38;
            double currentExp = Double.parseDouble(Float.toString(player.getExp()));
            experience += Math.ceil(currentExp * requiredExperience);
            return experience;
        } else {
            experience = (int) Math.ceil(((4.5 * Math.pow(level, 2) - (162.5 * level) + 2220)));
            int requiredExperience = 9 * level - 158;
            double currentExp = Double.parseDouble(Float.toString(player.getExp()));
            experience += Math.ceil(currentExp * requiredExperience);
            return experience;
        }
    }

    public void setTotalExperience(int xp) {
        //Levels 0 through 15
        if(xp >= 0 && xp < 351) {
            //Calculate Everything
            int a = 1; int b = 6; int c = -xp;
            int level = (int) (-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a);
            int xpForLevel = (int) (Math.pow(level, 2) + (6 * level));
            int remainder = xp - xpForLevel;
            int experienceNeeded = (2 * level) + 7;
            float experience = (float) remainder / (float) experienceNeeded;
            experience = round(experience, 2);

            //Set Everything
            player.setLevel(level);
            player.setExp(experience);
            //Levels 16 through 30
        } else if(xp >= 352 && xp < 1507) {
            //Calculate Everything
            double a = 2.5; double b = -40.5; int c = -xp + 360;
            double dLevel = (-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a);
            int level = (int) Math.floor(dLevel);
            int xpForLevel = (int) (2.5 * Math.pow(level, 2) - (40.5 * level) + 360);
            int remainder = xp - xpForLevel;
            int experienceNeeded = (5 * level) - 38;
            float experience = (float) remainder / (float) experienceNeeded;
            experience = round(experience, 2);

            //Set Everything
            player.setLevel(level);
            player.setExp(experience);
            //Level 31 and greater
        } else {
            //Calculate Everything
            double a = 4.5; double b = -162.5; int c = -xp + 2220;
            double dLevel = (-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a);
            int level = (int) Math.floor(dLevel);
            int xpForLevel = (int) (4.5 * Math.pow(level, 2) - (162.5 * level) + 2220);
            int remainder = xp - xpForLevel;
            int experienceNeeded = (9 * level) - 158;
            float experience = (float) remainder / (float) experienceNeeded;
            experience = round(experience, 2);

            //Set Everything
            player.setLevel(level);
            player.setExp(experience);
        }
    }

    private float round(float d, int decimalPlace) {
        BigDecimal bd = new BigDecimal(Float.toString(d));
        bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_DOWN);
        return bd.floatValue();
    }