summaryrefslogtreecommitdiff
path: root/src/map/pc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/pc.c')
-rw-r--r--src/map/pc.c154
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);