public void levelUp() {
        if (getLevel() >= maxLevel) {
            return;
        }

        if (getExp() > getNeededExp() || getExp() < 0) { //Nagative exp fix
            setExp(getNeededExp());
        }

        remainingAp += 5;
        int maxhp = stats.getMaxHp();
        int maxmp = stats.getMaxMp();

        if (GameConstants.isBeginnerJob(job)) { // Beginner
            maxhp += Randomizer.rand(12, 16);
            maxmp += Randomizer.rand(10, 12);
        } else if (job >= 3100 && job <= 3112) { // Warrior
            maxhp += Randomizer.rand(48, 52);
        } else if ((job >= 100 && job <= 132) || (job >= 1100 && job <= 1111)) { // Warrior
            maxhp += Randomizer.rand(48, 52);
            maxmp += Randomizer.rand(4, 6);
        } else if ((job >= 200 && job <= 232) || (job >= 1200 && job <= 1211)) { // Magician
            maxhp += Randomizer.rand(10, 14);
            maxmp += Randomizer.rand(48, 52);
        } else if (job >= 3200 && job <= 3212) { //battle mages get their own little neat thing
            maxhp += Randomizer.rand(20, 24);
            maxmp += Randomizer.rand(42, 44);
        } else if ((job >= 300 && job <= 322) || (job >= 400 && job <= 434) || (job >= 1300 && job <= 1311) || (job >= 1400 && job <= 1411) || (job >= 3300 && job <= 3312) || (job >= 2300 && job <= 2312)) { // Bowman, Thief, Wind Breaker and Night Walker
            maxhp += Randomizer.rand(20, 24);
            maxmp += Randomizer.rand(14, 16);
        } else if ((job >= 510 && job <= 512) || (job >= 1510 && job <= 1512)) { // Pirate
            maxhp += Randomizer.rand(37, 41);
            maxmp += Randomizer.rand(18, 22);
        } else if ((job >= 500 && job <= 532) || (job >= 3500 && job <= 3512) || job == 1500) { // Pirate
            maxhp += Randomizer.rand(20, 24);
            maxmp += Randomizer.rand(18, 22);
        } else if (job >= 2100 && job <= 2112) { // Aran
            maxhp += Randomizer.rand(50, 52);
            maxmp += Randomizer.rand(4, 6);
        } else if (job >= 2200 && job <= 2218) { // Evan
            maxhp += Randomizer.rand(12, 16);
            maxmp += Randomizer.rand(50, 52);
        } else if (job >= 5100 && job <= 5112) { // Evan
            maxhp += Randomizer.rand(48, 52);
            maxmp += Randomizer.rand(4, 6);
        } else { // GameMaster
            maxhp += Randomizer.rand(50, 100);//its already there lol
            maxmp += Randomizer.rand(50, 100);
        }
        maxmp += stats.getTotalInt() / 10;

        exp -= getNeededExp();
        level += 1;
        addLevelSkills();
        if (GameConstants.isKOC(job) && level < 120 && level > 10) {
            exp += getNeededExp() / 10;
        }
        maxhp = Math.min(500000, Math.abs(maxhp));
        maxmp = Math.min(500000, Math.abs(maxmp));
        if (GameConstants.isDemonSlayer(job)) { //TODO: use shield instead of df per job
            maxmp = GameConstants.getMPByJob(job);
        } else if (GameConstants.isZero(job)) {
            maxmp = 100;
        }
        final Map<MapleStat, Long> statup = new EnumMap<>(MapleStat.class);

        statup.put(MapleStat.MAXHP, (long) maxhp);
        statup.put(MapleStat.MAXMP, (long) maxmp);
        statup.put(MapleStat.HP, (long) maxhp);
        statup.put(MapleStat.MP, (long) maxmp);
        statup.put(MapleStat.EXP, exp);
        statup.put(MapleStat.LEVEL, (long) level);
        updateSingleStat(MapleStat.AVAILABLESP, 0);

        if (level <= 10) {
            stats.str += remainingAp;
            remainingAp = 0;

            statup.put(MapleStat.STR, (long) stats.getStr());
        }
        if (LoginInformationProvider.isExtendedSpJob(job)) {
            if (GameConstants.isZero(job) && level >= 100) {
                remainingSp[0] += 3; //alpha gets 3sp
                remainingSp[1] += 3; //beta gets 3sp
            } else {
                if (level >= 11) {
                    remainingSp[GameConstants.getSkillBook(job, level)] += 3;
                }
            }
        } else if (level >= 11) {
            remainingSp[GameConstants.getSkillBook(job, 0)] += 3;
        }

        statup.put(MapleStat.AVAILABLEAP, (long) remainingAp);
        statup.put(MapleStat.AVAILABLESP, (long) remainingSp[GameConstants.getSkillBook(job, level)]);
        obtainHyperSP();
        stats.setInfo(maxhp, maxmp, maxhp, maxmp);
        client.getSession().write(CWvsContext.updatePlayerStats(statup, this));
        map.broadcastMessage(this, EffectPacket.showForeignEffect(getId(), 0), false);
        characterCard.recalcLocalStats(this);
        stats.recalcLocalStats(this);
        silentPartyUpdate();
        guildUpdate();
        familyUpdate();
        autoJob();
        if (GameConstants.isZero(job)) {
            checkZeroWeapon();
            checkZeroTranscendent();
        }
        if (level == 250) {
            setExp(0);
            StringBuilder sb = new StringBuilder();
            sb.append("[Congrats] ");
            addMedalString(client.getPlayer(), sb);
            sb.append(getName()).append(" has reached Level ").append(level).append("! Congratule ");
            addMedalString(client.getPlayer(), sb);
            sb.append(getName()).append(" on such an amazing achievement!");
            World.Broadcast.broadcastMessage(CField.getGameMessage(sb.toString(), (short) 10));
        }
        //if (map.getForceMove() > 0 && map.getForceMove() <= getLevel()) {
        //    changeMap(map.getReturnMap(), map.getReturnMap().getPortal(0));
        //    dropMessage(-1, "You have been expelled from the map.");
        //}
        //checkCustomReward(level);
    }