Merge branch 'master' of https://github.com/rathena/rathena
This commit is contained in:
commit
f5b6e9f7c4
@ -79,6 +79,12 @@ death_penalty_job: 100
|
||||
// NOTE: It is a percentage of their zeny, so 100 = 1%
|
||||
zeny_penalty: 0
|
||||
|
||||
// Will players on max base/job level lose the EXP on death?
|
||||
// 0: Never lose (default as in official).
|
||||
// 1: Lose Base EXP.
|
||||
// 2: Lose Job EXP.
|
||||
death_penalty_maxlv: 0
|
||||
|
||||
// Will display experience gained from killing a monster. (Note 1)
|
||||
disp_experience: no
|
||||
|
||||
@ -89,3 +95,14 @@ disp_zeny: no
|
||||
// If no, an equation will be used which preserves statpoints earned/lost
|
||||
// through external means (ie: stat point buyers/sellers)
|
||||
use_statpoint_table: yes
|
||||
|
||||
// EXP cost for cast PR_REDEMPTIO (Note 2)
|
||||
exp_cost_redemptio: 1
|
||||
|
||||
// How many player needed to makes PR_REDEMPTIO's EXP penalty become 0?
|
||||
// If by default, the 'exp_cost_redemptio' is 1 (1%) and every single player revived the penalty is reduced to 0.2%,
|
||||
// it means 'exp_cost_redemptio_limit' is 5.
|
||||
exp_cost_redemptio_limit: 5
|
||||
|
||||
// EXP cost for cast LG_INSPIRATION (Note 2)
|
||||
exp_cost_inspiration: 1
|
||||
|
@ -781,7 +781,11 @@
|
||||
739: Please enter a body style (usage: @bodystyle <body ID: %d-%d>).
|
||||
740: This job has no alternate body styles.
|
||||
|
||||
//741-899 free
|
||||
// @showexp
|
||||
741: Gained
|
||||
742: Lost
|
||||
743: Experience %s Base:%ld (%0.2f%%) Job:%ld (%0.2f%%)
|
||||
//744-899 free
|
||||
|
||||
//------------------------------------
|
||||
// More atcommands message
|
||||
@ -1358,8 +1362,8 @@
|
||||
1315: Available Flags:
|
||||
|
||||
// @showexp
|
||||
1316: Gained exp will not be shown.
|
||||
1317: Gained exp is now shown.
|
||||
1316: Gained/lost exp will not be shown.
|
||||
1317: Gained/lost exp is now shown.
|
||||
|
||||
// @showzeny
|
||||
1318: Gained zeny will not be shown.
|
||||
|
@ -2659,7 +2659,7 @@ void char_set_defaults(){
|
||||
charserv_config.start_point[0].map = mapindex_name2id(MAP_DEFAULT_NAME);
|
||||
charserv_config.start_point[0].x = MAP_DEFAULT_X;
|
||||
charserv_config.start_point[0].y = MAP_DEFAULT_Y;
|
||||
charserv_config.start_point_count = 0;
|
||||
charserv_config.start_point_count = 1;
|
||||
|
||||
charserv_config.start_items[0].nameid = 1201;
|
||||
charserv_config.start_items[0].amount = 1;
|
||||
@ -2697,12 +2697,14 @@ static void char_config_split_startpoint(char *w2_value)
|
||||
strcat(config_name, "start_point_pre");
|
||||
#endif
|
||||
|
||||
charserv_config.start_point_count = 0; // Reset to begin reading
|
||||
|
||||
fields = (char **)aMalloc(fields_length * sizeof(char *));
|
||||
if (fields == NULL)
|
||||
return; // Failed to allocate memory.
|
||||
lineitem = strtok(w2_value, ":");
|
||||
|
||||
while (lineitem != NULL) {
|
||||
while (lineitem != NULL && charserv_config.start_point_count < MAX_STARTPOINT) {
|
||||
int n = sv_split(lineitem, strlen(lineitem), 0, ',', fields, fields_length, SV_NOESCAPE_NOTERMINATE);
|
||||
|
||||
if (n + 1 < fields_length) {
|
||||
@ -2710,9 +2712,7 @@ static void char_config_split_startpoint(char *w2_value)
|
||||
lineitem = strtok(NULL, ":"); //next lineitem
|
||||
continue;
|
||||
}
|
||||
if (i > MAX_STARTPOINT)
|
||||
ShowDebug("%s: too many start points, only %d are allowed! Ignoring parameter %s...\n", config_name, MAX_STARTPOINT, lineitem);
|
||||
else {
|
||||
|
||||
charserv_config.start_point[i].map = mapindex_name2id(fields[1]);
|
||||
if (!charserv_config.start_point[i].map) {
|
||||
ShowError("Start point %s not found in map-index cache. Setting to default location.\n", charserv_config.start_point[i].map);
|
||||
@ -2724,7 +2724,7 @@ static void char_config_split_startpoint(char *w2_value)
|
||||
charserv_config.start_point[i].y = max(0, atoi(fields[3]));
|
||||
}
|
||||
charserv_config.start_point_count++;
|
||||
}
|
||||
|
||||
lineitem = strtok(NULL, ":"); //next lineitem
|
||||
i++;
|
||||
}
|
||||
@ -2749,7 +2749,7 @@ static void char_config_split_startitem(char *w2_value)
|
||||
return; // Failed to allocate memory.
|
||||
lineitem = strtok(w2_value, ":");
|
||||
|
||||
while (lineitem != NULL) {
|
||||
while (lineitem != NULL && i < MAX_STARTITEM) {
|
||||
int n = sv_split(lineitem, strlen(lineitem), 0, ',', fields, fields_length, SV_NOESCAPE_NOTERMINATE);
|
||||
|
||||
if (n + 1 < fields_length) {
|
||||
@ -2757,13 +2757,12 @@ static void char_config_split_startitem(char *w2_value)
|
||||
lineitem = strtok(NULL, ":"); //next lineitem
|
||||
continue;
|
||||
}
|
||||
if (i > MAX_STARTITEM)
|
||||
ShowDebug("%s: too many start items, only %d are allowed! Ignoring parameter %s...\n", config_name, MAX_STARTITEM, lineitem);
|
||||
else {
|
||||
|
||||
// TODO: Item ID verification
|
||||
charserv_config.start_items[i].nameid = max(0, atoi(fields[1]));
|
||||
charserv_config.start_items[i].amount = max(0, atoi(fields[2]));
|
||||
charserv_config.start_items[i].pos = max(0, atoi(fields[3]));
|
||||
}
|
||||
|
||||
lineitem = strtok(NULL, ":"); //next lineitem
|
||||
i++;
|
||||
}
|
||||
|
@ -8192,6 +8192,10 @@ static const struct _battle_data {
|
||||
{ "monster_eye_range_bonus", &battle_config.mob_eye_range_bonus, 0, 0, 10, },
|
||||
{ "monster_stuck_warning", &battle_config.mob_stuck_warning, 0, 0, 1, },
|
||||
{ "skill_eightpath_algorithm", &battle_config.skill_eightpath_algorithm, 1, 0, 1, },
|
||||
{ "death_penalty_maxlv", &battle_config.death_penalty_maxlv, 0, 0, 3, },
|
||||
{ "exp_cost_redemptio", &battle_config.exp_cost_redemptio, 1, 0, 100, },
|
||||
{ "exp_cost_redemptio_limit", &battle_config.exp_cost_redemptio_limit, 5, 0, MAX_PARTY, },
|
||||
{ "exp_cost_inspiration", &battle_config.exp_cost_inspiration, 1, 0, 100, },
|
||||
};
|
||||
|
||||
#ifndef STATS_OPT_OUT
|
||||
|
@ -601,6 +601,10 @@ extern struct Battle_Config
|
||||
int mob_eye_range_bonus; //Vulture's Eye and Snake's Eye range bonus
|
||||
int mob_stuck_warning; //Show warning if a monster is stuck too long
|
||||
int skill_eightpath_algorithm; //Official path algorithm
|
||||
int death_penalty_maxlv;
|
||||
int exp_cost_redemptio;
|
||||
int exp_cost_redemptio_limit;
|
||||
int exp_cost_inspiration;
|
||||
} battle_config;
|
||||
|
||||
void do_init_battle(void);
|
||||
|
@ -14041,7 +14041,6 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd)
|
||||
if( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE ) {
|
||||
unsigned int next = pc_nextbaseexp(sd);
|
||||
|
||||
if( next == 0 ) next = pc_thisbaseexp(sd);
|
||||
if( next ) {
|
||||
int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
|
||||
|
||||
@ -16653,14 +16652,21 @@ void clif_party_show_picker(struct map_session_data * sd, struct item * item_dat
|
||||
}
|
||||
|
||||
|
||||
/// Display gained exp (ZC_NOTIFY_EXP).
|
||||
/// 07f6 <account id>.L <amount>.L <var id>.W <exp type>.W
|
||||
/// var id:
|
||||
/// SP_BASEEXP, SP_JOBEXP
|
||||
/// exp type:
|
||||
/// 0 = normal exp gain/loss
|
||||
/// 1 = quest exp gain/loss
|
||||
void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest)
|
||||
/** Display gained exp (ZC_NOTIFY_EXP).
|
||||
* 07f6 <account id>.L <amount>.L <var id>.W <exp type>.W
|
||||
* amount: INT32_MIN ~ INT32_MAX
|
||||
* var id:
|
||||
* SP_BASEEXP, SP_JOBEXP
|
||||
* exp type:
|
||||
* 0 = normal exp gained/lost
|
||||
* 1 = quest exp gained/lost
|
||||
* @param sd Player
|
||||
* @param exp EXP value gained/loss
|
||||
* @param type SP_BASEEXP, SP_JOBEXP
|
||||
* @param quest False:Normal EXP; True:Quest EXP (displayed in purple color)
|
||||
* @param lost True:if lossing EXP
|
||||
*/
|
||||
void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest, bool lost)
|
||||
{
|
||||
int fd;
|
||||
|
||||
@ -16671,7 +16677,7 @@ void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, b
|
||||
WFIFOHEAD(fd, packet_len(0x7f6));
|
||||
WFIFOW(fd,0) = 0x7f6;
|
||||
WFIFOL(fd,2) = sd->bl.id;
|
||||
WFIFOL(fd,6) = exp;
|
||||
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.
|
||||
WFIFOSET(fd,packet_len(0x7f6));
|
||||
|
@ -816,7 +816,7 @@ void clif_quest_delete(struct map_session_data * sd, int quest_id);
|
||||
void clif_quest_update_status(struct map_session_data * sd, int quest_id, bool active);
|
||||
void clif_quest_update_objective(struct map_session_data * sd, struct quest * qd, int mobid);
|
||||
void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, short state, short color);
|
||||
void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest);
|
||||
void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest, bool lost);
|
||||
|
||||
int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type);
|
||||
void do_init_clif(void);
|
||||
|
192
src/map/pc.c
192
src/map/pc.c
@ -38,6 +38,8 @@
|
||||
int pc_split_atoui(char* str, unsigned int* val, char sep, int max);
|
||||
|
||||
#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval
|
||||
#define MAX_LEVEL_BASE_EXP 99999999 ///< Max Base EXP for player on Max Base Level
|
||||
#define MAX_LEVEL_JOB_EXP 999999999 ///< Max Job EXP for player on Max Job Level
|
||||
|
||||
static unsigned int statp[MAX_LEVEL+1];
|
||||
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
|
||||
@ -6236,7 +6238,7 @@ int pc_follow(struct map_session_data *sd,int target_id)
|
||||
int pc_checkbaselevelup(struct map_session_data *sd) {
|
||||
unsigned int next = pc_nextbaseexp(sd);
|
||||
|
||||
if (!next || sd->status.base_exp < next)
|
||||
if (!next || sd->status.base_exp < next || pc_is_maxbaselv(sd))
|
||||
return 0;
|
||||
|
||||
do {
|
||||
@ -6299,7 +6301,7 @@ int pc_checkjoblevelup(struct map_session_data *sd)
|
||||
unsigned int next = pc_nextjobexp(sd);
|
||||
|
||||
nullpo_ret(sd);
|
||||
if(!next || sd->status.job_exp < next)
|
||||
if(!next || sd->status.job_exp < next || pc_is_maxjoblv(sd))
|
||||
return 0;
|
||||
|
||||
do {
|
||||
@ -6361,6 +6363,7 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi
|
||||
#endif
|
||||
}
|
||||
|
||||
// Give EXPBOOST for quests even if src is NULL.
|
||||
if (&sd->sc && sd->sc.data[SC_EXPBOOST]) {
|
||||
bonus += sd->sc.data[SC_EXPBOOST]->val1;
|
||||
if( battle_config.vip_bm_increase && pc_isvip(sd) ) // Increase Battle Manual EXP rate for VIP.
|
||||
@ -6369,6 +6372,7 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi
|
||||
|
||||
*base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * (bonus + vip_bonus_base)/100., 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;
|
||||
|
||||
@ -6376,13 +6380,42 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi
|
||||
|
||||
return;
|
||||
}
|
||||
/*==========================================
|
||||
* Give x exp at sd player and calculate remaining exp for next lvl
|
||||
*------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Show EXP gained by player in percentage by @showexp
|
||||
* @param sd Player
|
||||
* @param base_exp Base EXP gained/loss
|
||||
* @param next_base_exp Base EXP needed for next base level
|
||||
* @param job_exp Job EXP gained/loss
|
||||
* @param next_job_exp Job EXP needed for next job level
|
||||
* @param lost True:EXP penalty, lose EXP
|
||||
**/
|
||||
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) {
|
||||
char output[CHAT_SIZE_MAX];
|
||||
|
||||
nullpo_retv(sd);
|
||||
|
||||
sprintf(output, msg_txt(sd,743), // Experience %s Base:%ld (%0.2f%%) Job:%ld (%0.2f%%)
|
||||
(lost) ? msg_txt(sd,742) : msg_txt(sd,741),
|
||||
(long)base_exp * (lost ? -1 : 1), (base_exp / (float)next_base_exp * 100 * (lost ? -1 : 1)),
|
||||
(long)job_exp * (lost ? -1 : 1), (job_exp / (float)next_job_exp * 100 * (lost ? -1 : 1)));
|
||||
clif_disp_onlyself(sd, output, strlen(output));
|
||||
}
|
||||
|
||||
/**
|
||||
* Give Base or Job EXP to player, then calculate remaining exp for next lvl
|
||||
* @param sd Player
|
||||
* @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.
|
||||
* @return
|
||||
**/
|
||||
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
|
||||
|
||||
nullpo_ret(sd);
|
||||
|
||||
@ -6395,12 +6428,22 @@ 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);
|
||||
|
||||
pc_calcexp(sd, &base_exp, &job_exp, src); // Give (J)EXPBOOST for quests even if src is NULL.
|
||||
pc_calcexp(sd, &base_exp, &job_exp, src);
|
||||
|
||||
nextb = pc_nextbaseexp(sd);
|
||||
nextj = pc_nextjobexp(sd);
|
||||
|
||||
if(sd->state.showexp || battle_config.max_exp_gain_rate){
|
||||
flag = ((base_exp) ? 1 : 0) |
|
||||
((job_exp) ? 2 : 0) |
|
||||
(pc_is_maxbaselv(sd) ? 4 : 0) |
|
||||
(pc_is_maxjoblv(sd) ? 8 : 0);
|
||||
|
||||
if (flag&4 && sd->status.base_exp >= MAX_LEVEL_BASE_EXP)
|
||||
base_exp = 0;
|
||||
if (flag&8 && sd->status.job_exp >= MAX_LEVEL_JOB_EXP)
|
||||
job_exp = 0;
|
||||
|
||||
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)
|
||||
@ -6422,94 +6465,103 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
|
||||
}
|
||||
}
|
||||
|
||||
//Cap exp to the level up requirement of the previous level when you are at max level, otherwise cap at UINT_MAX (this is required for some S. Novice bonuses). [Skotlex]
|
||||
// Give EXP for Base Level
|
||||
if (base_exp) {
|
||||
nextb = nextb?UINT_MAX:pc_thisbaseexp(sd);
|
||||
if(sd->status.base_exp > nextb - base_exp)
|
||||
sd->status.base_exp = nextb;
|
||||
else
|
||||
sd->status.base_exp += base_exp;
|
||||
pc_checkbaselevelup(sd);
|
||||
if (!pc_checkbaselevelup(sd))
|
||||
clif_updatestatus(sd,SP_BASEEXP);
|
||||
}
|
||||
|
||||
// Give EXP for Job Level
|
||||
if (job_exp) {
|
||||
nextj = nextj?UINT_MAX:pc_thisjobexp(sd);
|
||||
if(sd->status.job_exp > nextj - job_exp)
|
||||
sd->status.job_exp = nextj;
|
||||
else
|
||||
sd->status.job_exp += job_exp;
|
||||
pc_checkjoblevelup(sd);
|
||||
if (!pc_checkjoblevelup(sd))
|
||||
clif_updatestatus(sd,SP_JOBEXP);
|
||||
}
|
||||
|
||||
if(base_exp)
|
||||
clif_displayexp(sd, base_exp, SP_BASEEXP, quest);
|
||||
if(job_exp)
|
||||
clif_displayexp(sd, job_exp, SP_JOBEXP, quest);
|
||||
if(sd->state.showexp) {
|
||||
char output[256];
|
||||
sprintf(output,
|
||||
"Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
|
||||
clif_disp_onlyself(sd,output,strlen(output));
|
||||
}
|
||||
if (flag&1)
|
||||
clif_displayexp(sd, (flag&4) ? 0 : base_exp, SP_BASEEXP, quest, false);
|
||||
if (flag&2)
|
||||
clif_displayexp(sd, (flag&8) ? 0 : job_exp, SP_JOBEXP, quest, false);
|
||||
|
||||
if (sd->state.showexp)
|
||||
pc_gainexp_disp(sd, base_exp, nextb, job_exp, nextj, false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Returns max level for this character.
|
||||
*------------------------------------------*/
|
||||
/**
|
||||
* Returns max base level for this character.
|
||||
* @param sd Player
|
||||
* @return Max Base Level
|
||||
**/
|
||||
unsigned int pc_maxbaselv(struct map_session_data *sd){
|
||||
return job_info[pc_class2idx(sd->status.class_)].max_level[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns max job level for this character.
|
||||
* @param sd Player
|
||||
* @return Max Job Level
|
||||
**/
|
||||
unsigned int pc_maxjoblv(struct map_session_data *sd){
|
||||
return job_info[pc_class2idx(sd->status.class_)].max_level[1];
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* base level exp lookup.
|
||||
*------------------------------------------*/
|
||||
/**
|
||||
* Check if player is reached max base level
|
||||
* @param sd
|
||||
* @return True if reached max level
|
||||
**/
|
||||
bool pc_is_maxbaselv(struct map_session_data *sd) {
|
||||
nullpo_retr(false, sd);
|
||||
return (sd->status.base_level >= pc_maxbaselv(sd));
|
||||
}
|
||||
|
||||
//Base exp needed for next level.
|
||||
/**
|
||||
* Check if player is reached max base level
|
||||
* @param sd
|
||||
* @return True if reached max level
|
||||
**/
|
||||
bool pc_is_maxjoblv(struct map_session_data *sd) {
|
||||
nullpo_retr(false, sd);
|
||||
return (sd->status.job_level >= pc_maxjoblv(sd));
|
||||
}
|
||||
|
||||
/**
|
||||
* Base exp needed for player to level up.
|
||||
* @param sd
|
||||
* @return Base EXP needed for next base level
|
||||
**/
|
||||
unsigned int pc_nextbaseexp(struct map_session_data *sd){
|
||||
nullpo_ret(sd);
|
||||
if(sd->status.base_level>=pc_maxbaselv(sd) || sd->status.base_level==0)
|
||||
if (sd->status.base_level == 0) // Is this something that possible?
|
||||
return 0;
|
||||
if (pc_is_maxbaselv(sd))
|
||||
return MAX_LEVEL_BASE_EXP; // On max level, player's base EXP limit is 99,999,999
|
||||
return job_info[pc_class2idx(sd->status.class_)].exp_table[0][sd->status.base_level-1];
|
||||
}
|
||||
|
||||
//Base exp needed for this level.
|
||||
unsigned int pc_thisbaseexp(struct map_session_data *sd){
|
||||
if(sd->status.base_level>pc_maxbaselv(sd) || sd->status.base_level<=1)
|
||||
return 0;
|
||||
return job_info[pc_class2idx(sd->status.class_)].exp_table[0][sd->status.base_level-2];
|
||||
}
|
||||
|
||||
|
||||
/*==========================================
|
||||
* job level exp lookup
|
||||
* Return:
|
||||
* 0 = not found
|
||||
* x = exp for level
|
||||
*------------------------------------------*/
|
||||
|
||||
//Job exp needed for next level.
|
||||
/**
|
||||
* Job exp needed for player to level up.
|
||||
* @param sd
|
||||
* @return Job EXP needed for next job level
|
||||
**/
|
||||
unsigned int pc_nextjobexp(struct map_session_data *sd){
|
||||
nullpo_ret(sd);
|
||||
if(sd->status.job_level>=pc_maxjoblv(sd) || sd->status.job_level==0)
|
||||
if (sd->status.job_level == 0) // Is this something that possible?
|
||||
return 0;
|
||||
if (pc_is_maxjoblv(sd))
|
||||
return MAX_LEVEL_JOB_EXP; // On max level, player's job EXP limit is 999,999,999
|
||||
return job_info[pc_class2idx(sd->status.class_)].exp_table[1][sd->status.job_level-1];
|
||||
}
|
||||
|
||||
//Job exp needed for this level.
|
||||
unsigned int pc_thisjobexp(struct map_session_data *sd){
|
||||
if(sd->status.job_level>pc_maxjoblv(sd) || sd->status.job_level<=1)
|
||||
return 0;
|
||||
return job_info[pc_class2idx(sd->status.class_)].exp_table[1][sd->status.job_level-2];
|
||||
}
|
||||
|
||||
/// Returns the value of the specified stat.
|
||||
static int pc_getstat(struct map_session_data* sd, int type)
|
||||
{
|
||||
@ -7295,10 +7347,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
||||
// Activate Steel body if a super novice dies at 99+% exp [celest]
|
||||
// Super Novices have no kill or die functions attached when saved by their angel
|
||||
if (!sd->state.snovice_dead_flag && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
|
||||
unsigned int next = pc_nextbaseexp(sd);
|
||||
unsigned int exp = pc_nextbaseexp(sd);
|
||||
|
||||
if( next == 0 ) next = pc_thisbaseexp(sd);
|
||||
if( get_percentage(sd->status.base_exp,next) >= 99 ) {
|
||||
if( exp && get_percentage(sd->status.base_exp,exp) >= 99 ) {
|
||||
sd->state.snovice_dead_flag = 1;
|
||||
pc_setrestartvalue(sd,1);
|
||||
status_percent_heal(&sd->bl, 100, 100);
|
||||
@ -7486,20 +7537,24 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (base_penalty > 0) {
|
||||
if ((battle_config.death_penalty_maxlv&1 || !pc_is_maxbaselv(sd)) && base_penalty > 0) {
|
||||
switch (battle_config.death_penalty_type) {
|
||||
case 1: base_penalty = (uint32) ( pc_nextbaseexp(sd) * ( base_penalty / 10000. ) ); break;
|
||||
case 2: base_penalty = (uint32) ( sd->status.base_exp * ( base_penalty / 10000. ) ); break;
|
||||
}
|
||||
if (base_penalty > 0){ //recheck after altering to speedup
|
||||
if (base_penalty){ //recheck after altering to speedup
|
||||
if (battle_config.pk_mode && src && src->type==BL_PC)
|
||||
base_penalty *= 2;
|
||||
sd->status.base_exp -= u32min(sd->status.base_exp, base_penalty);
|
||||
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
|
||||
base_penalty = 0;
|
||||
|
||||
if(job_penalty > 0) {
|
||||
if ((battle_config.death_penalty_maxlv&2 || !pc_is_maxjoblv(sd)) && job_penalty > 0) {
|
||||
switch (battle_config.death_penalty_type) {
|
||||
case 1: job_penalty = (uint32) ( pc_nextjobexp(sd) * ( job_penalty / 10000. ) ); break;
|
||||
case 2: job_penalty = (uint32) ( sd->status.job_exp * ( job_penalty /10000. ) ); break;
|
||||
@ -7507,10 +7562,17 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
||||
if (job_penalty) {
|
||||
if (battle_config.pk_mode && src && src->type==BL_PC)
|
||||
job_penalty *= 2;
|
||||
sd->status.job_exp -= u32min(sd->status.job_exp, job_penalty);
|
||||
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( zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) {
|
||||
zeny_penalty = (uint32)( sd->status.zeny * ( zeny_penalty / 10000. ) );
|
||||
@ -7831,13 +7893,15 @@ bool pc_setparam(struct map_session_data *sd,int type,int val)
|
||||
case SP_BASEEXP:
|
||||
if(pc_nextbaseexp(sd) > 0) {
|
||||
sd->status.base_exp = val;
|
||||
pc_checkbaselevelup(sd);
|
||||
if (!pc_checkbaselevelup(sd))
|
||||
clif_updatestatus(sd, SP_BASEEXP);
|
||||
}
|
||||
break;
|
||||
case SP_JOBEXP:
|
||||
if(pc_nextjobexp(sd) > 0) {
|
||||
sd->status.job_exp = val;
|
||||
pc_checkjoblevelup(sd);
|
||||
if (!pc_checkjoblevelup(sd))
|
||||
clif_updatestatus(sd, SP_JOBEXP);
|
||||
}
|
||||
break;
|
||||
case SP_SEX:
|
||||
|
@ -1004,13 +1004,14 @@ int pc_stop_following(struct map_session_data*);
|
||||
|
||||
unsigned int pc_maxbaselv(struct map_session_data *sd);
|
||||
unsigned int pc_maxjoblv(struct map_session_data *sd);
|
||||
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);
|
||||
unsigned int pc_nextbaseexp(struct map_session_data *);
|
||||
unsigned int pc_thisbaseexp(struct map_session_data *);
|
||||
unsigned int pc_nextjobexp(struct map_session_data *);
|
||||
unsigned int pc_thisjobexp(struct map_session_data *);
|
||||
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);
|
||||
int pc_gets_status_point(int);
|
||||
int pc_need_status_point(struct map_session_data *,int,int);
|
||||
int pc_maxparameterincrease(struct map_session_data*,int);
|
||||
|
@ -5926,12 +5926,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
break;
|
||||
}
|
||||
skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty...
|
||||
if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty
|
||||
sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * skill_area_temp[0] * 2/1000); //0.2% penalty per each.
|
||||
sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * skill_area_temp[0] * 2/1000);
|
||||
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);
|
||||
clif_updatestatus(sd,SP_JOBEXP);
|
||||
if (sd->state.showexp)
|
||||
pc_gainexp_disp(sd, base_penalty, pc_nextbaseexp(sd), 0, pc_nextjobexp(sd), true);
|
||||
}
|
||||
status_set_hp(src, 1, 0);
|
||||
status_set_sp(src, 0, 0);
|
||||
@ -9636,14 +9639,15 @@ 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 && sd->status.base_level != MAX_LEVEL ) {
|
||||
sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * 1 / 100); // 1% penalty.
|
||||
sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * 1 / 100);
|
||||
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);
|
||||
clif_updatestatus(sd,SP_JOBEXP);
|
||||
if (sd->state.showexp)
|
||||
pc_gainexp_disp(sd, base_penalty, pc_nextbaseexp(sd), 0, pc_nextjobexp(sd), true);
|
||||
}
|
||||
clif_skill_nodamage(bl,src,skill_id,skill_lv,
|
||||
sc_start(src,bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)));
|
||||
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:
|
||||
if( flag&1 ) {
|
||||
@ -14761,10 +14765,18 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
|
||||
}
|
||||
break;
|
||||
case PR_REDEMPTIO:
|
||||
case LG_INSPIRATION:
|
||||
{
|
||||
int exp;
|
||||
if( ((exp = pc_nextbaseexp(sd)) > 0 && get_percentage(sd->status.base_exp, exp) < 1) ||
|
||||
((exp = pc_nextjobexp(sd)) > 0 && get_percentage(sd->status.job_exp, exp) < 1)) {
|
||||
unsigned int exp, exp_needp = 0;
|
||||
switch (skill_id) {
|
||||
case PR_REDEMPTIO:
|
||||
exp_needp = battle_config.exp_cost_redemptio;
|
||||
break;
|
||||
case LG_INSPIRATION:
|
||||
exp_needp = battle_config.exp_cost_inspiration;
|
||||
break;
|
||||
}
|
||||
if (exp_needp && ((exp = pc_nextbaseexp(sd)) > 0 && get_percentage(sd->status.base_exp, exp) < exp_needp)) {
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); //Not enough exp.
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user