public void changeJob(short newJob) {
        try {
            cancelEffectFromBuffStat(MapleBuffStat.SHADOWPARTNER);
            this.job = newJob;
            updateSingleStat(MapleStat.JOB, newJob);

            if (!GameConstants.isBeginnerJob(newJob) && !GameConstants.isDualBladeNoSP(newJob) && !GameConstants.isZero(newJob) && !GameConstants.isBeastTamer(newJob) && !GameConstants.isGM(newJob)) {
                addJobSkills();
                if (GameConstants.isSeparatedSp(newJob)) {
                    if (GameConstants.isPhantom(job)) {
                        client.getSession().write(PhantomPacket.updateCardStack(0));
                        resetRunningStack();
                    }
                    int changeSp = (newJob == 2200 || newJob == 2210 || newJob == 2211 || newJob == 2213 ? 3 : 5);
                    if (GameConstants.isResistance(job) && newJob != 3100 && newJob != 3200 && newJob != 3300 && newJob != 3500 && newJob != 3600) {
                        changeSp = 3;
                    }
                    remainingSp[GameConstants.getSkillBook(newJob, 0)] += changeSp;
                    client.getSession().write(InfoPacket.getSPMsg((byte) changeSp, (short) newJob));
                } else {
                    remainingSp[GameConstants.getSkillBook(newJob, 0)]++;
                    if (newJob % 10 >= 2) {
                        remainingSp[GameConstants.getSkillBook(newJob, 0)] += 2;
                    }
                }
                if (newJob % 10 >= 1 && level >= 70) { //3rd job or higher. lucky for evans who get 80, 100, 120, 160 ap...
                    remainingAp += 5;
                    updateSingleStat(MapleStat.AVAILABLEAP, remainingAp);
                }
                if (!isGM()) {
                    resetStatsByJob(true);
                    if (!GameConstants.isEvan(newJob)) {
                        if (getLevel() > (newJob == 200 ? 8 : 10) && newJob % 100 == 0 && (newJob % 1000) / 100 > 0) { //first job
                            remainingSp[GameConstants.getSkillBook(newJob, 0)] += 3 * (getLevel() - (newJob == 200 ? 8 : 10));
                        }
                    } else if (newJob == 2200) {
                        MapleQuest.getInstance(22100).forceStart(this, 0, null);
                        MapleQuest.getInstance(22100).forceComplete(this, 0);
                        expandInventory((byte) 1, 4);
                        expandInventory((byte) 2, 4);
                        expandInventory((byte) 3, 4);
                        expandInventory((byte) 4, 4);
                        client.getSession().write(NPCPacket.getEvanTutorial("UI/tutorial/evan/14/0"));
                        dropMessage(5, "The baby Dragon hatched and appears to have something to tell you. Click the baby Dragon to start a conversation.");
                    }
                }
                if (newJob == 433) {
                    remainingSp[GameConstants.getSkillBook(newJob, 0)] -= 2;
                }
                updateSingleStat(MapleStat.AVAILABLESP, 0); // we don't care the value here
            }

            int maxhp = stats.getMaxHp(), maxmp = stats.getMaxMp();

            switch (job) {
                case 100: // Warrior
                case 1100: // Soul Master
                case 2100: // Aran
                case 3100:
                case 3200:
                case 4100:
                case 5100:
                case 6100:
                    maxhp += Randomizer.rand(200, 250);
                    break;
                case 3110:
                    maxhp += Randomizer.rand(300, 350);
                    break;
                case 200: // Magician
                case 2200: //evan
                case 2210: //evan
                case 2700:
                case 4200:
                    maxmp += Randomizer.rand(100, 150);
                    break;
                case 300: // Bowman
                case 400: // Thief
                case 500: // Pirate
                case 2300:
                case 3300:
                case 3500:
                case 3600:
                case 6500:
                    maxhp += Randomizer.rand(100, 150);
                    maxmp += Randomizer.rand(25, 50);
                    break;
                case 110: // Fighter
                case 120: // Page
                case 130: // Spearman
                case 1110: // Soul Master
                case 2110: // Aran
                case 3210:
                case 4110:
                case 5110:
                case 6110:
                    maxhp += Randomizer.rand(300, 350);
                    break;
                case 210: // FP
                case 220: // IL
                case 230: // Cleric
                    maxmp += Randomizer.rand(400, 450);
                    break;
                case 310: // Bowman
                case 320: // Crossbowman
                case 410: // Assasin
                case 420: // Bandit
                case 430: // Semi Dualer
                case 510:
                case 520:
                case 530:
                case 2310:
                case 1310: // Wind Breaker
                case 1410: // Night Walker
                case 3310:
                case 3510:
                    maxhp += Randomizer.rand(200, 250);
                    maxhp += Randomizer.rand(150, 200);
                    break;
                case 800: // Manager
                case 900: // GM
                case 910: // SuperGM
                    break; //No additions for now
            }
            if (maxhp >= 500000) {
                maxhp = 500000;
            }
            if (maxmp >= 500000) {
                maxmp = 500000;
            }
            if (GameConstants.isDemonSlayer(job)) {
                maxmp = GameConstants.getMPByJob(job);
            } else if (GameConstants.isZero(job)) {
                maxmp = 100;
            }
            stats.setInfo(maxhp, maxmp, maxhp, maxmp);
            Map<MapleStat, Long> statup = new EnumMap<>(MapleStat.class);
            statup.put(MapleStat.MAXHP, Long.valueOf(maxhp));
            statup.put(MapleStat.MAXMP, Long.valueOf(maxmp));
            statup.put(MapleStat.HP, Long.valueOf(maxhp));
            statup.put(MapleStat.MP, Long.valueOf(maxmp));
            characterCard.recalcLocalStats(this);
            stats.recalcLocalStats(this);
            client.getSession().write(CWvsContext.updatePlayerStats(statup, this));
            map.broadcastMessage(this, EffectPacket.showForeignEffect(getId(), 11), false);
            silentPartyUpdate();
            guildUpdate();
            familyUpdate();
            if (dragon != null) {
                map.broadcastMessage(CField.removeDragon(this.id));
                dragon = null;
            }
            if (haku != null) {
                haku = null;
            }
            baseSkills();
            if (newJob >= 2200 && newJob <= 2218) { //make new
                if (getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null) {
                    cancelBuffStats(MapleBuffStat.MONSTER_RIDING);
                }
                makeDragon();
            }
            if (((newJob >= 4200) && (newJob <= 4212)) || (newJob == 4002)) {
                if (getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null) {
                    cancelBuffStats(new MapleBuffStat[]{MapleBuffStat.MONSTER_RIDING});
                }
                makeHaku();
            }
            checkForceShield();
        } catch (Exception e) {
            FileoutputUtil.outputFileError(FileoutputUtil.ScriptEx_Log, e); //all jobs throw errors :(
        }
    }