diff options
Diffstat (limited to 'src/map/pc.c')
-rw-r--r-- | src/map/pc.c | 154 |
1 files changed, 96 insertions, 58 deletions
diff --git a/src/map/pc.c b/src/map/pc.c index a4a32545b..d5d359557 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1560,7 +1560,7 @@ int pc_calc_skillpoint(struct map_session_data* sd) { nullpo_ret(sd); - for (i = 1; i < MAX_SKILL; i++) { + for (i = 1; i < MAX_SKILL_DB; i++) { int skill_lv = pc->checkskill2(sd,i); if (skill_lv > 0) { inf2 = skill->dbs->db[i].inf2; @@ -1596,7 +1596,7 @@ int pc_calc_skilltree(struct map_session_data *sd) } classidx = pc->class2idx(class); - for( i = 0; i < MAX_SKILL; i++ ) { + for (i = 0; i < MAX_SKILL_DB; i++) { if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these sd->status.skill[i].id = 0; //First clear skills. /* permanent skills that must be re-checked */ @@ -1613,7 +1613,7 @@ int pc_calc_skilltree(struct map_session_data *sd) } } - for( i = 0; i < MAX_SKILL; i++ ) { + for (i = 0; i < MAX_SKILL_DB; i++) { if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) { // Restore original level of skills after deleting earned skills. sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; @@ -1622,18 +1622,25 @@ int pc_calc_skilltree(struct map_session_data *sd) if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill->dbs->db[i].nameid >= DC_HUMMING && skill->dbs->db[i].nameid <= DC_SERVICEFORYOU ) { //Enable Bard/Dancer spirit linked skills. - if( sd->status.sex ) - { //Link dancer skills to bard. - // i can be < 8? - if( sd->status.skill[i-8].lv < 10 ) + if (sd->status.sex) { + // Link dancer skills to bard. + if (i < 8) { + Assert_report(i >= 8); + continue; + } + if (sd->status.skill[i-8].lv < 10) continue; sd->status.skill[i].id = skill->dbs->db[i].nameid; sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill - } else { //Link bard skills to dancer. - if( sd->status.skill[i].lv < 10 ) + } else { + // Link bard skills to dancer. + if (i < 8) { + Assert_report(i >= 8); + continue; + } + if (sd->status.skill[i].lv < 10) continue; - // i can be < 8? sd->status.skill[i-8].id = skill->dbs->db[i-8].nameid; sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill @@ -1642,7 +1649,7 @@ int pc_calc_skilltree(struct map_session_data *sd) } if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) { - for( i = 0; i < MAX_SKILL; i++ ) { + for (i = 0; i < MAX_SKILL_DB; i++) { switch(skill->dbs->db[i].nameid) { /** * Dummy skills must be added here otherwise they'll be displayed in the, @@ -1836,7 +1843,7 @@ int pc_clean_skilltree(struct map_session_data *sd) { int i; nullpo_ret(sd); - for (i = 0; i < MAX_SKILL; i++){ + for (i = 0; i < MAX_SKILL_DB; i++) { if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) { sd->status.skill[i].id = 0; sd->status.skill[i].lv = 0; @@ -4143,7 +4150,7 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4 *------------------------------------------*/ int pc_skill(struct map_session_data *sd, int id, int level, int flag) { - uint16 index = 0; + int index = 0; nullpo_ret(sd); if (!(index = skill->get_index(id))) { @@ -5869,7 +5876,7 @@ int pc_memo(struct map_session_data* sd, int pos) { * Return player sd skill_lv learned for given skill *------------------------------------------*/ int pc_checkskill(struct map_session_data *sd,uint16 skill_id) { - uint16 index = 0; + int index = 0; if(sd == NULL) return 0; if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) { struct guild *g; @@ -5888,8 +5895,9 @@ int pc_checkskill(struct map_session_data *sd,uint16 skill_id) { return 0; } int pc_checkskill2(struct map_session_data *sd,uint16 index) { - if(sd == NULL) return 0; - if(index >= ARRAYLENGTH(sd->status.skill) ) { + if (sd == NULL) + return 0; + if (index >= MAX_SKILL_DB) { ShowError("pc_checkskill: Invalid skill index %d (char_id=%d).\n", index, sd->status.char_id); return 0; } @@ -6698,8 +6706,9 @@ int pc_follow(struct map_session_data *sd,int target_id) { return 0; } -int pc_checkbaselevelup(struct map_session_data *sd) { - unsigned int next = pc->nextbaseexp(sd); +int pc_checkbaselevelup(struct map_session_data *sd) +{ + uint64 next = pc->nextbaseexp(sd); nullpo_ret(sd); if (!next || sd->status.base_exp < next) @@ -6763,7 +6772,7 @@ void pc_baselevelchanged(struct map_session_data *sd) { int pc_checkjoblevelup(struct map_session_data *sd) { - unsigned int next = pc->nextjobexp(sd); + uint64 next = pc->nextjobexp(sd); nullpo_ret(sd); if(!next || sd->status.job_exp < next) @@ -6796,7 +6805,7 @@ int pc_checkjoblevelup(struct map_session_data *sd) /** * Alters EXP based on self bonuses that do not get shared with the party **/ -void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src) { +void pc_calcexp(struct map_session_data *sd, uint64 *base_exp, uint64 *job_exp, struct block_list *src) { int buff_ratio = 0, buff_job_ratio = 0, race_ratio = 0, pk_ratio = 0; int64 jexp, bexp; @@ -6861,8 +6870,8 @@ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned in bexp += apply_percentrate64(bexp, buff_ratio, 100); jexp += apply_percentrate64(jexp, buff_ratio + buff_job_ratio, 100); - *job_exp = (unsigned int)cap_value(jexp, 1, UINT_MAX); - *base_exp = (unsigned int)cap_value(bexp, 1, UINT_MAX); + *job_exp = cap_value(jexp, 1, UINT64_MAX); + *base_exp = cap_value(bexp, 1, UINT64_MAX); } /** @@ -6871,9 +6880,10 @@ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned in * @param is_quest Used to let client know that the EXP was from a quest (clif->displayexp) PACKETVER >= 20091027 * @retval true success **/ -bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp,unsigned int job_exp,bool is_quest) { - float nextbp=0, nextjp=0; - unsigned int nextb=0, nextj=0; +bool pc_gainexp(struct map_session_data *sd, struct block_list *src, uint64 base_exp, uint64 job_exp, bool is_quest) +{ + float nextbp = 0, nextjp = 0; + uint64 nextb = 0, nextj = 0; nullpo_ret(sd); if (sd->bl.prev == NULL || pc_isdead(sd)) @@ -6889,7 +6899,7 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in pc->calcexp(sd, &base_exp, &job_exp, src); if (sd->status.guild_id > 0) - base_exp -= guild->payexp(sd,base_exp); + base_exp -= guild->payexp(sd, base_exp); nextb = pc->nextbaseexp(sd); nextj = pc->nextjobexp(sd); @@ -6900,16 +6910,16 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in if (nextj > 0) nextjp = (float) job_exp / (float) nextj; - if(battle_config.max_exp_gain_rate) { + 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 = (uint64)(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.) { - job_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextj); + job_exp = (uint64)(battle_config.max_exp_gain_rate / 1000. * nextj); if (sd->state.showexp) nextjp = (float) job_exp / (float) nextj; } @@ -6919,23 +6929,23 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in // 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] if (base_exp) { - nextb = nextb?UINT_MAX:pc->thisbaseexp(sd); - if(sd->status.base_exp > nextb - base_exp) + nextb = nextb ? UINT64_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); - clif->updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd, SP_BASEEXP); } if (job_exp) { - nextj = nextj?UINT_MAX:pc->thisjobexp(sd); - if(sd->status.job_exp > nextj - job_exp) + nextj = nextj ? UINT64_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); - clif->updatestatus(sd,SP_JOBEXP); + clif->updatestatus(sd, SP_JOBEXP); } #if PACKETVER >= 20091027 @@ -6948,7 +6958,8 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in 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); + "Experience Gained Base:%"PRIu64" (%.2f%%) Job:%"PRIu64" (%.2f%%)", + base_exp, nextbp * (float)100, job_exp, nextjp * (float)100); clif_disp_onlyself(sd, output); } @@ -6973,7 +6984,7 @@ int pc_maxjoblv(const struct map_session_data *sd) *------------------------------------------*/ //Base exp needed for next level. -unsigned int pc_nextbaseexp(const struct map_session_data *sd) +uint64 pc_nextbaseexp(const struct map_session_data *sd) { nullpo_ret(sd); @@ -6984,7 +6995,7 @@ unsigned int pc_nextbaseexp(const struct map_session_data *sd) } //Base exp needed for this level. -unsigned int pc_thisbaseexp(const struct map_session_data *sd) +uint64 pc_thisbaseexp(const struct map_session_data *sd) { if (sd->status.base_level > pc->maxbaselv(sd) || sd->status.base_level <= 1) return 0; @@ -7000,7 +7011,7 @@ unsigned int pc_thisbaseexp(const struct map_session_data *sd) *------------------------------------------*/ //Job exp needed for next level. -unsigned int pc_nextjobexp(const struct map_session_data *sd) +uint64 pc_nextjobexp(const struct map_session_data *sd) { nullpo_ret(sd); @@ -7010,7 +7021,7 @@ unsigned int pc_nextjobexp(const struct map_session_data *sd) } //Job exp needed for this level. -unsigned int pc_thisjobexp(const struct map_session_data *sd) +uint64 pc_thisjobexp(const struct map_session_data *sd) { if (sd->status.job_level > pc->maxjoblv(sd) || sd->status.job_level <= 1) return 0; @@ -7226,7 +7237,7 @@ int pc_statusup2(struct map_session_data* sd, int type, int val) * Skill point allocation *------------------------------------------*/ int pc_skillup(struct map_session_data *sd,uint16 skill_id) { - uint16 index = 0; + int index = 0; nullpo_ret(sd); if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL ) { @@ -7283,7 +7294,7 @@ int pc_allskillup(struct map_session_data *sd) nullpo_ret(sd); - for(i=0;i<MAX_SKILL;i++){ + for (i = 0; i < MAX_SKILL_DB; i++) { if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) { sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; @@ -7294,7 +7305,7 @@ int pc_allskillup(struct map_session_data *sd) if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { //Get ALL skills except npc/guild ones. [Skotlex] //and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage] - for(i=0;i<MAX_SKILL;i++){ + for (i = 0; i < MAX_SKILL_DB; i++) { switch( skill->dbs->db[i].nameid ) { case SG_DEVIL: case MO_TRIPLEATTACK: @@ -7534,9 +7545,7 @@ int pc_resetskill(struct map_session_data* sd, int flag) status_change_end(&sd->bl, SC_SPRITEMABLE, INVALID_TIMER); } - for( i = 1; i < MAX_SKILL; i++ ) { - // FIXME: We're looping on i = [1..MAX_SKILL-1] (which makes sense as index for sd->status.skill[]) but then we're using the - // same i to access skill->dbs->db[], and especially to check skill_ischangesex(). This is wrong. + for (i = 1; i < MAX_SKILL_DB; i++) { uint16 skill_id = 0; int lv = sd->status.skill[i].lv; if (lv < 1) continue; @@ -7958,7 +7967,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { // activate Steel body if a super novice dies at 99+% exp [celest] if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag) { - unsigned int next = pc->nextbaseexp(sd); + uint64 next = pc->nextbaseexp(sd); if( next == 0 ) next = pc->thisbaseexp(sd); if (get_percentage64(sd->status.base_exp, next) >= 99) { sd->state.snovice_dead_flag = 1; @@ -8329,7 +8338,7 @@ int pc_setparam(struct map_session_data *sd, int type, int64 val) if (val >= sd->status.job_level) { if (val > pc->maxjoblv(sd)) val = pc->maxjoblv(sd); - sd->status.skill_point += val - sd->status.job_level; + sd->status.skill_point += (int)val - sd->status.job_level; clif->updatestatus(sd, SP_SKILLPOINT); } sd->status.job_level = (int32)val; @@ -8410,28 +8419,28 @@ int pc_setparam(struct map_session_data *sd, int type, int64 val) } break; case SP_STR: - sd->status.str = cap_value(val, 1, pc_maxparameter(sd)); + sd->status.str = cap_value((int)val, 1, pc_maxparameter(sd)); break; case SP_AGI: - sd->status.agi = cap_value(val, 1, pc_maxparameter(sd)); + sd->status.agi = cap_value((int)val, 1, pc_maxparameter(sd)); break; case SP_VIT: - sd->status.vit = cap_value(val, 1, pc_maxparameter(sd)); + sd->status.vit = cap_value((int)val, 1, pc_maxparameter(sd)); break; case SP_INT: - sd->status.int_ = cap_value(val, 1, pc_maxparameter(sd)); + sd->status.int_ = cap_value((int)val, 1, pc_maxparameter(sd)); break; case SP_DEX: - sd->status.dex = cap_value(val, 1, pc_maxparameter(sd)); + sd->status.dex = cap_value((int)val, 1, pc_maxparameter(sd)); break; case SP_LUK: - sd->status.luk = cap_value(val, 1, pc_maxparameter(sd)); + sd->status.luk = cap_value((int)val, 1, pc_maxparameter(sd)); break; case SP_KARMA: - sd->status.karma = val; + sd->status.karma = (int)val; break; case SP_MANNER: - sd->status.manner = val; + sd->status.manner = (int)val; if( val < 0 ) sc_start(NULL, &sd->bl, SC_NOCHAT, 100, 0, 0); else { @@ -10988,6 +10997,35 @@ int pc_split_atoui(char* str, unsigned int* val, char sep, int max) return i; } +int pc_split_atoui64(char* str, uint64* val, char sep, int max) +{ + static int warning=0; + int i,j; + nullpo_ret(val); + for (i=0; i<max; i++) { + double f; + if (!str) break; + f = atof(str); + if (f < 0) + val[i] = 0; + else if (f > UINT64_MAX) { + val[i] = UINT64_MAX; + if (!warning) { + warning = 1; + ShowWarning("pc_readdb (exp.txt): Required exp per level is capped to %"PRIu64"\n", UINT64_MAX); + } + } else + val[i] = (uint64)f; + str = strchr(str,sep); + if (str) + *str++=0; + } + //Zero up the remaining. + for(j=i; j < max; j++) + val[j] = 0; + return i; +} + /** * Parses the skill tree config file. * @@ -11295,7 +11333,7 @@ int pc_readdb(void) { count++; job = jobs[0] = pc->class2idx(job_id); //We send one less and then one more because the last entry in the exp array should hold 0. - pc->max_level[job][type] = pc_split_atoui(split[3], pc->exp_table[job][type],',',maxlv-1)+1; + pc->max_level[job][type] = pc_split_atoui64(split[3], pc->exp_table[job][type], ',', maxlv - 1) + 1; //Reverse check in case the array has a bunch of trailing zeros... [Skotlex] //The reasoning behind the -2 is this... if the max level is 5, then the array //should look like this: @@ -11932,7 +11970,7 @@ bool pc_process_chat_message(struct map_session_data *sd, const char *message) */ void pc_check_supernovice_call(struct map_session_data *sd, const char *message) { - unsigned int next = pc->nextbaseexp(sd); + uint64 next = pc->nextbaseexp(sd); int percent = 0; nullpo_retv(sd); |