* 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,,,,,,{},{},{}
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; },{},{}

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,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));
}

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.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:

View File

@ -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);