* Refactor pc_setparam for SP_BASEEXP and SP_JOBEXP.

* Added script command `getexp2` for safety usage of `set BaseExp,n;` and `set JobExp,n` usages.
* Cleanup exp lost functionto `pc_lostexp`.

Signed-off-by: Cydh Ramdh <cydh@pservero.com>
This commit is contained in:
Cydh Ramdh 2016-03-20 12:31:44 +07:00
parent 9ebf59c37b
commit 09b2ea06ee
9 changed files with 114 additions and 102 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,,,,,,{ BaseExp += 3000000; JobExp += 1500000; },{},{}
12259,Miracle_Medicine,Miracle Tonic,2,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ getexp2(3000000,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,,,,,,{ BaseExp += 2000000; JobExp += 1000000; },{},{}
12261,Secret_Medicine,Leap of Fantasy,2,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ getexp2(2000000,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

@ -4185,25 +4185,26 @@ the character will also have their skills reset upon 'changecharsex'.
---------------------------------------
*getexp <base xp>,<job xp>{,<char_id>};
*getexp <base_exp>,<job_exp>{,<char_id>};
This command will give the invoking character a specified number of base and job
experience points. Can be used as a quest reward. Negative values won't work.
experience points. Used for a quest reward. Negative values won't work.
The EXP values are adjustted by 'quest_exp_rate' config value, VIP bonus, Guild
Tax and EXP boost items such Battle Manual, Bubble Gum, or items that have
SC_EXPBOOST or SC_ITEMBOOST.
getexp 10000,5000;
You can also use the "set" command with the constants defined in 'db/const.txt':
---------------------------------------
// These 2 combined has the same effect as the above command
set BaseExp,BaseExp+10000;
set JobExp,JobExp+5000;
*getexp2 <base_exp>,<job_exp>{,<char_id>};
You can also reduce the amount of experience points:
This command is safety version of 'set' command for BaseExp and JobExp. If using
'set' while the BaseExp or JobExp value is more than 2,147,483,647 (INT_MAX) will
causing overflow error.
set BaseExp,BaseExp-10000;
Note that 'getexp' is now subject to the 'quest_exp_rate' config option, which
adjusts the gained value. If you want to bypass this, use the 'set' method.
Unlike 'getexp', this command ignores the adjustment factors!
---------------------------------------

View File

@ -2410,7 +2410,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
job_exp = (unsigned int)cap_value(apply_rate(job_exp, rate), 1, UINT_MAX);
}
#endif
pc_gainexp(tmpsd[i], &md->bl, base_exp, job_exp, false);
pc_gainexp(tmpsd[i], &md->bl, base_exp, job_exp, 0);
}
}
if(zeny) // zeny from mobs [Valaris]
@ -2606,7 +2606,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
clif_mvp_effect(mvp_sd);
clif_mvp_exp(mvp_sd,mexp);
pc_gainexp(mvp_sd, &md->bl, mexp,0, false);
pc_gainexp(mvp_sd, &md->bl, mexp,0, 0);
log_mvp[1] = mexp;
if( !(map[m].flag.nomvploot || type&1) ) {

View File

@ -1817,7 +1817,7 @@ uint8 npc_buylist(struct map_session_data* sd, uint16 n, struct s_npc_buy_list *
z = z * (double)skill * (double)battle_config.shop_exp/10000.;
if( z < 1 )
z = 1;
pc_gainexp(sd,NULL,0,(int)z, false);
pc_gainexp(sd,NULL,0,(int)z, 0);
}
}
@ -1974,7 +1974,7 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list
z = z * (double)skill * (double)battle_config.shop_exp/10000.;
if( z < 1 )
z = 1;
pc_gainexp(sd, NULL, 0, (int)z, false);
pc_gainexp(sd, NULL, 0, (int)z, 0);
}
}

View File

@ -1077,7 +1077,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
}
#endif
pc_gainexp(sd[i], src, base_exp, job_exp, false);
pc_gainexp(sd[i], src, base_exp, job_exp, 0);
if (zeny) // zeny from mobs [Valaris]
pc_getzeny(sd[i],zeny,LOG_TYPE_PICKDROP_MONSTER,NULL);

View File

@ -6448,31 +6448,35 @@ void pc_gainexp_disp(struct map_session_data *sd, unsigned int base_exp, unsigne
* @param src EXP source
* @param base_exp Base EXP gained
* @param base_exp Job EXP gained
* @param quest True if EXP from quest, false otherwise.
* @param exp_flag 1: Quest EXP; 2: Param Exp (Ignore Guild EXP tax, EXP adjustments)
* @return
**/
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(struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, uint8 exp_flag)
{
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
nullpo_ret(sd);
nullpo_retv(sd);
if(sd->bl.prev == NULL || pc_isdead(sd))
return 0;
return;
if(!battle_config.pvp_exp && map[sd->bl.m].flag.pvp) // [MouseJstr]
return 0; // no exp on pvp maps
if (!(exp_flag&2)) {
if (!battle_config.pvp_exp && map[sd->bl.m].flag.pvp) // [MouseJstr]
return; // no exp on pvp maps
if(sd->status.guild_id>0)
base_exp-=guild_payexp(sd,base_exp);
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);
if (!(exp_flag&2))
pc_calcexp(sd, &base_exp, &job_exp, src);
nextb = pc_nextbaseexp(sd);
nextj = pc_nextjobexp(sd);
@ -6490,7 +6494,7 @@ 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 (battle_config.max_exp_gain_rate && (base_exp || job_exp)) {
if (!(exp_flag&2) && 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) {
@ -6526,14 +6530,40 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
}
if (flag&1)
clif_displayexp(sd, (flag&4) ? 0 : base_exp, SP_BASEEXP, quest, false);
clif_displayexp(sd, (flag&4) ? 0 : base_exp, SP_BASEEXP, exp_flag&1, false);
if (flag&2)
clif_displayexp(sd, (flag&8) ? 0 : job_exp, SP_JOBEXP, quest, false);
clif_displayexp(sd, (flag&8) ? 0 : job_exp, SP_JOBEXP, exp_flag&1, false);
if (sd->state.showexp)
pc_gainexp_disp(sd, base_exp, nextb, job_exp, nextj, false);
}
return 1;
/**
* Lost Base/Job EXP from a player
* @param sd Player
* @param base_exp Base EXP lost
* @param job_exp Job EXP lost
**/
void pc_lostexp(struct map_session_data *sd, unsigned int base_exp, unsigned int job_exp) {
nullpo_retv(sd);
if (base_exp) {
base_exp = u32min(sd->status.base_exp, base_exp);
sd->status.base_exp -= base_exp;
clif_displayexp(sd, base_exp, SP_BASEEXP, false, true);
clif_updatestatus(sd, SP_BASEEXP);
}
if (job_exp) {
job_exp = u32min(sd->status.job_exp, job_exp);
sd->status.job_exp -= job_exp;
clif_displayexp(sd, job_exp, SP_JOBEXP, false, true);
clif_updatestatus(sd, SP_JOBEXP);
}
if (sd->state.showexp)
pc_gainexp_disp(sd, base_exp, pc_nextbaseexp(sd), job_exp, pc_nextjobexp(sd), true);
}
/**
@ -7586,9 +7616,6 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty *= 2;
base_penalty = u32min(sd->status.base_exp, base_penalty);
sd->status.base_exp -= base_penalty;
clif_displayexp(sd, base_penalty, SP_BASEEXP, false, true);
clif_updatestatus(sd,SP_BASEEXP);
}
}
else
@ -7603,16 +7630,13 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
if (battle_config.pk_mode && src && src->type==BL_PC)
job_penalty *= 2;
job_penalty = u32min(sd->status.job_exp, job_penalty);
sd->status.job_exp -= job_penalty;
clif_displayexp(sd, job_penalty, SP_JOBEXP, false, true);
clif_updatestatus(sd,SP_JOBEXP);
}
}
else
job_penalty = 0;
if (sd->state.showexp && (base_penalty || job_penalty))
pc_gainexp_disp(sd, base_penalty, pc_nextbaseexp(sd), job_penalty, pc_nextjobexp(sd), true);
if (base_penalty || job_penalty)
pc_lostexp(sd, base_penalty, job_penalty);
if( zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) {
zeny_penalty = (uint32)( sd->status.zeny * ( zeny_penalty / 10000. ) );
@ -7932,56 +7956,22 @@ bool pc_setparam(struct map_session_data *sd,int type,int val)
break;
case 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);
if ((unsigned int)val < sd->status.base_exp) // Lost
pc_lostexp(sd, sd->status.base_exp - val, 0);
else // Gained
pc_gainexp(sd, NULL, val - sd->status.base_exp, 0, 2);
}
break;
return true;
case 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);
if ((unsigned int)val < sd->status.job_exp) // Lost
pc_lostexp(sd, 0, sd->status.job_exp - val);
else // Gained
pc_gainexp(sd, NULL, 0, val - sd->status.job_exp, 2);
}
break;
return true;
case SP_SEX:
sd->status.sex = val ? SEX_MALE : SEX_FEMALE;
break;

View File

@ -1008,8 +1008,9 @@ 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 *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, bool quest);
void pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, uint8 exp_flag);
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_lostexp(struct map_session_data *sd, unsigned int base_exp, unsigned int job_exp);
unsigned int pc_nextbaseexp(struct map_session_data *sd);
unsigned int pc_nextjobexp(struct map_session_data *sd);
int pc_gets_status_point(int);

View File

@ -9641,7 +9641,7 @@ BUILDIN_FUNC(getexp)
if (job)
job = (int) cap_value(job * bonus, 0, INT_MAX);
pc_gainexp(sd, NULL, base, job, true);
pc_gainexp(sd, NULL, base, job, 1);
return SCRIPT_CMD_SUCCESS;
}
@ -21082,6 +21082,35 @@ BUILDIN_FUNC(navigateto){
#endif
}
/**
* Safety Base/Job EXP addition than using `set BaseExp,n;` or `set JobExp,n;`
* Unlike `getexp` that affected by some adjustments.
* getexp2 <base_exp>,<job_exp>{,<char_id>};
* @author [Cydh]
**/
BUILDIN_FUNC(getexp2) {
TBL_PC *sd = NULL;
int base_exp = script_getnum(st, 2);
int job_exp = script_getnum(st, 3);
if (!script_charid2sd(4, sd))
return SCRIPT_CMD_FAILURE;
if (base_exp == 0 && job_exp == 0)
return SCRIPT_CMD_SUCCESS;
if (base_exp > 0)
pc_gainexp(sd, NULL, base_exp, 0, 2);
else if (base_exp < 0)
pc_lostexp(sd, base_exp * -1, 0);
if (job_exp > 0)
pc_gainexp(sd, NULL, 0, job_exp, 2);
else if (job_exp < 0)
pc_lostexp(sd, 0, job_exp * -1);
return SCRIPT_CMD_SUCCESS;
}
#include "../custom/script.inc"
// declarations that were supposed to be exported from npc_chat.c
@ -21649,6 +21678,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(setquestinfo_job,"ii*"),
BUILDIN_DEF(opendressroom,"i?"),
BUILDIN_DEF(navigateto,"s???????"),
BUILDIN_DEF(getexp2,"ii?"),
#include "../custom/script_def.inc"

View File

@ -5908,7 +5908,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100;
if (heal_get_jobexp <= 0)
heal_get_jobexp = 1;
pc_gainexp (sd, bl, 0, heal_get_jobexp, false);
pc_gainexp (sd, bl, 0, heal_get_jobexp, 0);
}
}
break;
@ -5931,12 +5931,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
skill_area_temp[0] = battle_config.exp_cost_redemptio_limit - skill_area_temp[0]; // The actual penalty...
if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty && battle_config.exp_cost_redemptio) { //Apply penalty
//If total penalty is 1% => reduced 0.2% penalty per each revived player
unsigned int base_penalty = u32min(sd->status.base_exp, (pc_nextbaseexp(sd) * skill_area_temp[0] * battle_config.exp_cost_redemptio / battle_config.exp_cost_redemptio_limit) / 100);
sd->status.base_exp -= base_penalty;
clif_displayexp(sd, base_penalty, SP_BASEEXP, false, true);
clif_updatestatus(sd,SP_BASEEXP);
if (sd->state.showexp)
pc_gainexp_disp(sd, base_penalty, pc_nextbaseexp(sd), 0, pc_nextjobexp(sd), true);
pc_lostexp(sd, u32min(sd->status.base_exp, (pc_nextbaseexp(sd) * skill_area_temp[0] * battle_config.exp_cost_redemptio / battle_config.exp_cost_redemptio_limit) / 100), 0);
}
status_set_hp(src, 1, 0);
status_set_sp(src, 0, 0);
@ -5987,7 +5982,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (jexp < 1) jexp = 1;
}
if(exp > 0 || jexp > 0)
pc_gainexp (sd, bl, exp, jexp, false);
pc_gainexp (sd, bl, exp, jexp, 0);
}
}
}
@ -6106,7 +6101,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case SA_LEVELUP:
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd, NULL, pc_nextbaseexp(sd) * 10 / 100, 0, false);
if (sd && pc_nextbaseexp(sd))
pc_gainexp(sd, NULL, pc_nextbaseexp(sd) * 10 / 100, 0, 0);
break;
case SA_INSTANTDEATH:
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
@ -9648,14 +9644,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case LG_INSPIRATION:
if( sd && !map[sd->bl.m].flag.noexppenalty && battle_config.exp_cost_inspiration ) {
unsigned int base_penalty = u32min(sd->status.base_exp, pc_nextbaseexp(sd) * battle_config.exp_cost_inspiration / 100); // 1% penalty.
sd->status.base_exp -= base_penalty;
clif_displayexp(sd, base_penalty, SP_BASEEXP, false, true);
clif_updatestatus(sd,SP_BASEEXP);
if (sd->state.showexp)
pc_gainexp_disp(sd, base_penalty, pc_nextbaseexp(sd), 0, pc_nextjobexp(sd), true);
}
if( sd && !map[sd->bl.m].flag.noexppenalty && battle_config.exp_cost_inspiration )
pc_lostexp(sd, u32min(sd->status.base_exp, pc_nextbaseexp(sd) * battle_config.exp_cost_inspiration / 100), 0); // 1% penalty.
clif_skill_nodamage(bl,src,skill_id,skill_lv, sc_start(src,bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)));
break;
case SR_CURSEDCIRCLE: