private void giveExpToCharacter(final MapleCharacter attacker, int exp, final boolean highestDamage, final int numExpSharers, byte pty, final byte Class_Bonus_EXP_PERCENT, final byte Premium_Bonus_EXP_PERCENT, final int lastskillID) {
        if (highestDamage) {
            if (eventInstance != null) {
                eventInstance.monsterKilled(attacker, this);
            } else {
                final EventInstanceManager em = attacker.getEventInstance();
                if (em != null) {
                    em.monsterKilled(attacker, this);
                }
            }
            highestDamageChar = attacker.getId();
        }
        if (exp > 0) {
            final MonsterStatusEffect ms = stati.get(MonsterStatus.SHOWDOWN);
            if (ms != null) {
                exp += (int) (exp * (ms.getX() / 100.0));
            }
            final Integer holySymbol = attacker.getBuffedValue(MapleBuffStat.HOLY_SYMBOL);
            if (holySymbol != null) {
                exp *= 1.0 + (holySymbol.doubleValue() / 100.0);
            }
            if (attacker.hasDisease(MapleDisease.CURSE)) {
                exp /= 2;
            }
            for (int item = 5211000; item < 5211100; item++) {
                if (attacker.haveItem(item)) {
                    exp *= 2.0;
                }
            }
            if (EventConstants.DoubleTime) {
                exp *= 2.0;
            }
            exp *= attacker.getEXPMod();
            exp *= attacker.getStat().expBuff / 100.0;
            if (GameConstants.isTutorialMap(attacker.getMapId())) {
                exp *= 1;
            } else {
                int ch_exp = ChannelServer.getInstance(map.getChannel()).getExpRate(attacker.getWorld());
                exp *= GameConstants.getExpRate(attacker.getJob(), ch_exp);
            }

//            exp = (int) Math.min(Integer.MAX_VALUE, exp * attacker.getEXPMod() * attacker.getStat().expBuff / 100.0 * (GameConstants.isTutorialMap(attacker.getMapId()) ? 1 : GameConstants.getExpRate(attacker.getJob(), ChannelServer.getInstance(map.getChannel()).getExpRate(attacker.getWorld()))));
            //do this last just incase someone has a 2x exp card and its set to max value
            int Class_Bonus_EXP = 0;
            if (Class_Bonus_EXP_PERCENT > 0) {
                Class_Bonus_EXP = (int) ((exp / 100.0) * Class_Bonus_EXP_PERCENT);
            }
            int Premium_Bonus_EXP = 0;
            if (Premium_Bonus_EXP_PERCENT > 0) {
                Premium_Bonus_EXP = (int) ((exp / 100.0) * Premium_Bonus_EXP_PERCENT);
            }
            int Equipment_Bonus_EXP = (int) ((exp / 100.0) * attacker.getStat().equipmentBonusExp);
            if (attacker.getStat().equippedFairy > 0 && attacker.getFairyExp() > 0) {
                Equipment_Bonus_EXP += (int) ((exp / 100.0) * attacker.getFairyExp());
            }
            attacker.getTrait(MapleTraitType.charisma).addExp(stats.getCharismaEXP(), attacker);
            MapleParty party = attacker.getParty();
            if (party != null) {
                int minlevel = 250;
                int maxlevel = 0;
                for (MaplePartyCharacter mpc : party.getMembers()) {
                    if (mpc.getLevel() < minlevel) {
                        minlevel = mpc.getLevel();
                    }
                    if (mpc.getLevel() > maxlevel) {
                        maxlevel = mpc.getLevel();
                    }
                }
                if (maxlevel - minlevel > 40) {
                    pty = 0;
                }
            }
            attacker.gainExpMonster(exp, true, highestDamage, pty, Class_Bonus_EXP, Equipment_Bonus_EXP, Premium_Bonus_EXP, stats.isPartyBonus(), stats.getPartyBonusRate());
        }
        attacker.mobKilled(getId(), lastskillID);
    }