diff --git a/db/re/item_db.txt b/db/re/item_db.txt index f1e23e71f6..4b8a0d0bba 100644 --- a/db/re/item_db.txt +++ b/db/re/item_db.txt @@ -6270,9 +6270,9 @@ 12256,PRO_Gift_Box,PRO Gift Box,2,0,,10,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{} 12257,Cold_Medicine,Cold Medicine,0,20,,100,,,,,0xFFFFFFFF,63,2,,,50,,,{ percentheal 25,25; },{},{} 12258,Bombring_Box,Bomb Poring Box,2,0,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ if(strcharinfo(3)=="job3_rang02") { monster "this",-1,-1,"--ja--",1904,1,""; } },{},{} -12259,Miracle_Medicine,Miracle Tonic,2,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ getexp 3000000,1500000; },{},{} +12259,Miracle_Medicine,Miracle Tonic,2,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ BaseExp += 3000000; JobExp += 1500000; },{},{} 12260,Cool_Summer_Outfit,Cool Summer Outfit,2,0,,100,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_SUMMER,600000,0; },{},{} -12261,Secret_Medicine,Leap of Fantasy,2,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ getexp 2000000,1000000; },{},{} +12261,Secret_Medicine,Leap of Fantasy,2,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ BaseExp += 2000000; JobExp += 1000000; },{},{} 12262,Inspector_Certificate_,Authoritative Badge,2,0,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_SPEEDUP0,540000,25; },{},{} 12263,Comp_Battle_Manual,Field Manual,2,2,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_EXPBOOST,1800000,50; },{},{} 12264,Comp_Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_ITEMBOOST,1800000,200; },{},{} diff --git a/src/map/clif.c b/src/map/clif.c index d42ff2c88a..0521ea0574 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -16697,7 +16697,7 @@ void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, b WFIFOL(fd,2) = sd->bl.id; WFIFOL(fd,6) = (int)umin(exp, INT_MAX) * (lost ? -1 : 1); WFIFOW(fd,10) = type; - WFIFOW(fd,12) = quest?1:0;// Normal exp is shown in yellow, quest exp is shown in purple. + WFIFOW(fd,12) = (quest && type != SP_JOBEXP) ? 1 : 0; // NOTE: Somehow JobEXP always in yellow color WFIFOSET(fd,packet_len(0x7f6)); } diff --git a/src/map/pc.c b/src/map/pc.c index eed61e1ad3..13c07d6a97 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1296,6 +1296,16 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ sd->bonus_script.head = NULL; sd->bonus_script.count = 0; + // Check EXP overflow, since in previous revision EXP on Max Level can be more than 'official' Max EXP + if (pc_is_maxbaselv(sd) && sd->status.base_exp > MAX_LEVEL_BASE_EXP) { + sd->status.base_exp = MAX_LEVEL_BASE_EXP; + clif_updatestatus(sd, SP_BASEEXP); + } + if (pc_is_maxjoblv(sd) && sd->status.job_exp > MAX_LEVEL_JOB_EXP) { + sd->status.job_exp = MAX_LEVEL_JOB_EXP; + clif_updatestatus(sd, SP_JOBEXP); + } + // Request all registries (auth is considered completed whence they arrive) intif_request_registry(sd,7); return true; @@ -6394,13 +6404,19 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi bonus += ( sd->sc.data[SC_EXPBOOST]->val1 / battle_config.vip_bm_increase ); } - *base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * (bonus + vip_bonus_base)/100., 1, UINT_MAX); + if (*base_exp) { + unsigned int exp = (unsigned int)(*base_exp + (double)*base_exp * (bonus + vip_bonus_base)/100.); + *base_exp = cap_value(exp, 1, UINT_MAX); + } // Give JEXPBOOST for quests even if src is NULL. if (&sd->sc && sd->sc.data[SC_JEXPBOOST]) bonus += sd->sc.data[SC_JEXPBOOST]->val1; - *job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * (bonus + vip_bonus_job)/100., 1, UINT_MAX); + if (*job_exp) { + unsigned int exp = (unsigned int)(*job_exp + (double)*job_exp * (bonus + vip_bonus_job)/100.); + *job_exp = cap_value(exp, 1, UINT_MAX); + } return; } @@ -6437,7 +6453,6 @@ void pc_gainexp_disp(struct map_session_data *sd, unsigned int base_exp, unsigne **/ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, bool quest) { - float nextbp = 0, nextjp = 0; unsigned int nextb = 0, nextj = 0; uint8 flag = 0; ///< 1: Base EXP given, 2: Job EXP given, 4: Max Base level, 8: Max Job Level @@ -6452,15 +6467,15 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int if(sd->status.guild_id>0) base_exp-=guild_payexp(sd,base_exp); + flag = ((base_exp) ? 1 : 0) | + ((job_exp) ? 2 : 0) | + ((pc_is_maxbaselv(sd)) ? 4 : 0) | + ((pc_is_maxjoblv(sd)) ? 8 : 0); + pc_calcexp(sd, &base_exp, &job_exp, src); nextb = pc_nextbaseexp(sd); nextj = pc_nextjobexp(sd); - - flag = ((base_exp) ? 1 : 0) | - ((job_exp) ? 2 : 0) | - (pc_is_maxbaselv(sd) ? 4 : 0) | - (pc_is_maxjoblv(sd) ? 8 : 0); if (flag&4){ if( sd->status.base_exp >= MAX_LEVEL_BASE_EXP ) @@ -6475,25 +6490,18 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int job_exp = MAX_LEVEL_JOB_EXP - sd->status.job_exp; } - if ((base_exp || job_exp) && (sd->state.showexp || battle_config.max_exp_gain_rate)){ - if (nextb > 0) - nextbp = (float) base_exp / (float) nextb; - if (nextj > 0) - nextjp = (float) job_exp / (float) nextj; - - if(battle_config.max_exp_gain_rate) { - if (nextbp > battle_config.max_exp_gain_rate/1000.) { - //Note that this value should never be greater than the original - //base_exp, therefore no overflow checks are needed. [Skotlex] + if (battle_config.max_exp_gain_rate && (base_exp || job_exp)) { + //Note that this value should never be greater than the original + //therefore no overflow checks are needed. [Skotlex] + if (nextb > 0) { + float nextbp = (float) base_exp / (float) nextb; + if (nextbp > battle_config.max_exp_gain_rate/1000.) base_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextb); - if (sd->state.showexp) - nextbp = (float) base_exp / (float) nextb; - } - if (nextjp > battle_config.max_exp_gain_rate/1000.) { + } + if (nextj > 0) { + float nextjp = (float) job_exp / (float) nextj; + if (nextjp > battle_config.max_exp_gain_rate/1000.) job_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextj); - if (sd->state.showexp) - nextjp = (float) job_exp / (float) nextj; - } } } @@ -7923,23 +7931,55 @@ bool pc_setparam(struct map_session_data *sd,int type,int val) sd->status.zeny = cap_value(val, 0, MAX_ZENY); break; case SP_BASEEXP: - if(pc_nextbaseexp(sd) > 0) { - if( pc_is_maxbaselv(sd) ) - sd->status.base_exp = u32min(val,MAX_LEVEL_BASE_EXP); - else - sd->status.base_exp = val; - if (!pc_checkbaselevelup(sd)) - clif_updatestatus(sd, SP_BASEEXP); + { + unsigned int exp = sd->status.base_exp; + unsigned int next = pc_nextbaseexp(sd); + bool isLost = false; + bool isMax = false; + + val = cap_value(val, 0, INT_MAX); + sd->status.base_exp = val; + + if ((unsigned int)val < exp) { // Lost + exp -= val; + isLost = true; + } + else { // Gained + if ((isMax = pc_is_maxbaselv(sd)) && sd->status.base_exp >= MAX_LEVEL_BASE_EXP) + exp = 0; + else + exp = val-exp; + pc_checkbaselevelup(sd); + } + clif_displayexp(sd, isMax ? 0 : exp, SP_BASEEXP, false, isLost); + if (sd->state.showexp) + pc_gainexp_disp(sd, exp, next, 0, pc_nextjobexp(sd), isLost); } break; case SP_JOBEXP: - if(pc_nextjobexp(sd) > 0) { - if( pc_is_maxjoblv(sd) ) - sd->status.job_exp = u32min(val,MAX_LEVEL_JOB_EXP); - else - sd->status.job_exp = val; - if (!pc_checkjoblevelup(sd)) - clif_updatestatus(sd, SP_JOBEXP); + { + unsigned int exp = sd->status.job_exp; + unsigned int next = pc_nextjobexp(sd); + bool isLost = false; + bool isMax = false; + + val = cap_value(val, 0, INT_MAX); + sd->status.job_exp = val; + + if ((unsigned int)val < exp) { // Lost + exp -= val; + isLost = true; + } + else { // Gained + if ((isMax = pc_is_maxjoblv(sd)) && sd->status.job_exp >= MAX_LEVEL_JOB_EXP) + exp = 0; + else + exp = val-exp; + pc_checkjoblevelup(sd); + } + clif_displayexp(sd, isMax ? 0 : exp, SP_JOBEXP, false, isLost); + if (sd->state.showexp) + pc_gainexp_disp(sd, 0, pc_nextbaseexp(sd), exp, next, isLost); } break; case SP_SEX: diff --git a/src/map/pc.h b/src/map/pc.h index 1ed2069cfd..d145fa1584 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -1008,7 +1008,7 @@ bool pc_is_maxbaselv(struct map_session_data *sd); bool pc_is_maxjoblv(struct map_session_data *sd); int pc_checkbaselevelup(struct map_session_data *sd); int pc_checkjoblevelup(struct map_session_data *sd); -int pc_gainexp(struct map_session_data*,struct block_list*,unsigned int,unsigned int, bool); +int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, bool quest); void pc_gainexp_disp(struct map_session_data *sd, unsigned int base_exp, unsigned int next_base_exp, unsigned int job_exp, unsigned int next_job_exp, bool lost); unsigned int pc_nextbaseexp(struct map_session_data *sd); unsigned int pc_nextjobexp(struct map_session_data *sd);