* Official EXP-Giving Script

* Fixed #980.
  * Job Quest EXP always be shown in yellow color.
  * Miracle Tonic (12259) and Leap of Fantasy (12261) give fixed EXP through `pc_setparam` that ignore EXP item bonuses and exp rates. Not as Quest EXP from `getexp` script.
  * If given EXP is 0 by `getexp`, it won't be notified in client EXP log.
  * If given EXP for base/job that reach max level, client will be notified as 0 EXP gained.
* Follow up 20588abcd83fab53f9e52deafc08bfcddfe1658a
  * Some clean up on `pc_gainexp`.

Signed-off-by: Cydh Ramdh <cydh@pservero.com>
This commit is contained in:
Cydh Ramdh 2016-03-08 18:03:59 +07:00
parent 71cdcb3a0a
commit 9ebf59c37b
4 changed files with 83 additions and 43 deletions

View File

@ -6270,9 +6270,9 @@
12256,PRO_Gift_Box,PRO Gift Box,2,0,,10,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{} 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; },{},{} 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,""; } },{},{} 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; },{},{} 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; },{},{} 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; },{},{} 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; },{},{} 12264,Comp_Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_ITEMBOOST,1800000,200; },{},{}

View File

@ -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,2) = sd->bl.id;
WFIFOL(fd,6) = (int)umin(exp, INT_MAX) * (lost ? -1 : 1); WFIFOL(fd,6) = (int)umin(exp, INT_MAX) * (lost ? -1 : 1);
WFIFOW(fd,10) = type; 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)); WFIFOSET(fd,packet_len(0x7f6));
} }

View File

@ -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.head = NULL;
sd->bonus_script.count = 0; 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) // Request all registries (auth is considered completed whence they arrive)
intif_request_registry(sd,7); intif_request_registry(sd,7);
return true; 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 ); 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. // Give JEXPBOOST for quests even if src is NULL.
if (&sd->sc && sd->sc.data[SC_JEXPBOOST]) if (&sd->sc && sd->sc.data[SC_JEXPBOOST])
bonus += sd->sc.data[SC_JEXPBOOST]->val1; 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; 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) 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; 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 uint8 flag = 0; ///< 1: Base EXP given, 2: Job EXP given, 4: Max Base level, 8: Max Job Level
@ -6452,16 +6467,16 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
if(sd->status.guild_id>0) if(sd->status.guild_id>0)
base_exp-=guild_payexp(sd,base_exp); 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); pc_calcexp(sd, &base_exp, &job_exp, src);
nextb = pc_nextbaseexp(sd); nextb = pc_nextbaseexp(sd);
nextj = pc_nextjobexp(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 (flag&4){
if( sd->status.base_exp >= MAX_LEVEL_BASE_EXP ) if( sd->status.base_exp >= MAX_LEVEL_BASE_EXP )
base_exp = 0; base_exp = 0;
@ -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; 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 (battle_config.max_exp_gain_rate && (base_exp || job_exp)) {
if (nextb > 0) //Note that this value should never be greater than the original
nextbp = (float) base_exp / (float) nextb; //therefore no overflow checks are needed. [Skotlex]
if (nextj > 0) if (nextb > 0) {
nextjp = (float) job_exp / (float) nextj; float nextbp = (float) base_exp / (float) nextb;
if (nextbp > battle_config.max_exp_gain_rate/1000.)
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]
base_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextb); base_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextb);
if (sd->state.showexp) }
nextbp = (float) base_exp / (float) nextb; if (nextj > 0) {
} float nextjp = (float) job_exp / (float) nextj;
if (nextjp > battle_config.max_exp_gain_rate/1000.) { if (nextjp > battle_config.max_exp_gain_rate/1000.)
job_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextj); 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); sd->status.zeny = cap_value(val, 0, MAX_ZENY);
break; break;
case SP_BASEEXP: case SP_BASEEXP:
if(pc_nextbaseexp(sd) > 0) { {
if( pc_is_maxbaselv(sd) ) unsigned int exp = sd->status.base_exp;
sd->status.base_exp = u32min(val,MAX_LEVEL_BASE_EXP); unsigned int next = pc_nextbaseexp(sd);
else bool isLost = false;
sd->status.base_exp = val; bool isMax = false;
if (!pc_checkbaselevelup(sd))
clif_updatestatus(sd, SP_BASEEXP); 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; break;
case SP_JOBEXP: case SP_JOBEXP:
if(pc_nextjobexp(sd) > 0) { {
if( pc_is_maxjoblv(sd) ) unsigned int exp = sd->status.job_exp;
sd->status.job_exp = u32min(val,MAX_LEVEL_JOB_EXP); unsigned int next = pc_nextjobexp(sd);
else bool isLost = false;
sd->status.job_exp = val; bool isMax = false;
if (!pc_checkjoblevelup(sd))
clif_updatestatus(sd, SP_JOBEXP); 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; break;
case SP_SEX: case SP_SEX:

View File

@ -1008,7 +1008,7 @@ bool pc_is_maxbaselv(struct map_session_data *sd);
bool pc_is_maxjoblv(struct map_session_data *sd); bool pc_is_maxjoblv(struct map_session_data *sd);
int pc_checkbaselevelup(struct map_session_data *sd); int pc_checkbaselevelup(struct map_session_data *sd);
int pc_checkjoblevelup(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); 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_nextbaseexp(struct map_session_data *sd);
unsigned int pc_nextjobexp(struct map_session_data *sd); unsigned int pc_nextjobexp(struct map_session_data *sd);