Index: src/map/status.c =================================================================== --- src/map/status.c (revision 17363) +++ src/map/status.c (working copy) @@ -49,10 +49,12 @@ }; static int max_weight_base[CLASS_COUNT]; -static int hp_coefficient[CLASS_COUNT]; -static int hp_coefficient2[CLASS_COUNT]; -static int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1]; -static int sp_coefficient[CLASS_COUNT]; +static struct { + int hp_table[MAX_LEVEL]; + int sp_table[MAX_LEVEL]; + int max_level; +} hpsp_info[CLASS_COUNT]; + #ifdef RENEWAL_ASPD static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; #else @@ -2239,39 +2241,11 @@ return 1; } -/// Helper function for status_base_pc_maxhp(), used to pre-calculate the hp_sigma_val[] array -static void status_calc_sigma(void) -{ - int i,j; - - for(i = 0; i < CLASS_COUNT; i++) - { - unsigned int k = 0; - hp_sigma_val[i][0] = hp_sigma_val[i][1] = 0; - for(j = 2; j <= MAX_LEVEL; j++) - { - k += (hp_coefficient[i]*j + 50) / 100; - hp_sigma_val[i][j] = k; - if (k >= INT_MAX) - break; //Overflow protection. [Skotlex] - } - for(; j <= MAX_LEVEL; j++) - hp_sigma_val[i][j] = INT_MAX; - } -} - -/// Calculates base MaxHP value according to class and base level -/// The recursive equation used to calculate level bonus is (using integer operations) -/// f(0) = 35 | f(x+1) = f(x) + A + (x + B)*C/D -/// which reduces to something close to -/// f(x) = 35 + x*(A + B*C/D) + sum(i=2..x){ i*C/D } +//Calculate maxHP from tables static unsigned int status_base_pc_maxhp(struct map_session_data* sd, struct status_data* status) { - uint64 val = pc_class2idx(sd->status.class_); - val = 35 + sd->status.base_level*(int64)hp_coefficient2[val]/100 + hp_sigma_val[val][sd->status.base_level]; + uint32 val = hpsp_info[pc_class2idx(sd->status.class_)].hp_table[sd->status.base_level-1]; - if((sd->class_&MAPID_UPPERMASK) == MAPID_NINJA || (sd->class_&MAPID_UPPERMASK) == MAPID_GUNSLINGER) - val += 100; //Since their HP can't be approximated well enough without this. if((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) val *= 3; //Triple max HP for top ranking Taekwons over level 90. if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99) @@ -2286,11 +2260,11 @@ return (unsigned int)val; } +//Calculate maxSP from tables static unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct status_data *status) { - uint64 val; + uint32 val = hpsp_info[pc_class2idx(sd->status.class_)].sp_table[sd->status.base_level-1]; - val = 10 + sd->status.base_level*(int64)sp_coefficient[pc_class2idx(sd->status.class_)]/100; val += val * status->int_/100; if (sd->class_&JOBL_UPPER) @@ -11341,15 +11315,8 @@ } -/*------------------------------------------ - * DB reading. - * job_db1.txt - weight, hp, sp, aspd - * job_db2.txt - job level stat bonuses - * size_fix.txt - size adjustment table for weapons - * refine_db.txt - refining data table - *------------------------------------------*/ -static bool status_readdb_job1(char* fields[], int columns, int current) -{// Job-specific values (weight, HP, SP, ASPD) +//Reading job_db1.txt line, (class,weight,aspd) +static bool status_readdb_job1(char* fields[], int columns, int current){ int idx, class_; unsigned int i; @@ -11363,20 +11330,18 @@ idx = pc_class2idx(class_); max_weight_base[idx] = atoi(fields[1]); - hp_coefficient[idx] = atoi(fields[2]); - hp_coefficient2[idx] = atoi(fields[3]); - sp_coefficient[idx] = atoi(fields[4]); #ifdef RENEWAL_ASPD for(i = 0; i <= MAX_WEAPON_TYPE; i++) #else for(i = 0; i < MAX_WEAPON_TYPE; i++) #endif { - aspd_base[idx][i] = atoi(fields[i+5]); + aspd_base[idx][i] = atoi(fields[i+2]); } return true; } +//Reading job_db2.txt line (class,JobLv1,JobLv2,JobLv3,...) static bool status_readdb_job2(char* fields[], int columns, int current) { int idx, class_, i; @@ -11397,6 +11362,78 @@ return true; } +//Reading job_maxhp.txt line +static bool status_readdb_maxhp(char* fields[], int columns, int current) +{ + int idx, i, maxlvl; + int job_id,job_count,jobs[CLASS_COUNT]; + + job_count = pc_split_atoi(fields[1],jobs,':',CLASS_COUNT); + if (job_count < 1) + return; + for (i = 1; i < job_count; i++) { + job_id = jobs[i]; + if(!pcdb_checkid(job_id)) + { + ShowWarning("status_readdb_maxhp: Invalid job class %d specified.\n", job_id); + return false; + } + idx = pc_class2idx(job_id); + + maxlvl = atoi(fields[0]); + if(maxlvl > MAX_LEVEL){ + ShowWarning("status_readdb_maxhp: Invalid maxlevel %d specified.\n", maxlvl); + return false; + } + if(hpsp_info[idx].max_level && hpsp_info[idx].max_level != maxlvl){ + ShowWarning("status_readdb_maxhp: maxlevel %d was already specified with different value %d.\n",maxlvl,hpsp_info[idx].max_level); + return false; + } + hpsp_info[idx].max_level = maxlvl; + for(i = 2; i < maxlvl; i++) + { + hpsp_info[idx].hp_table[i-1] = atoi(fields[i]); + } + } + return true; +} + +//Reading job_maxsp.txt line +static bool status_readdb_maxsp(char* fields[], int columns, int current) +{ + int idx, i, maxlvl; + int job_id,job_count,jobs[CLASS_COUNT]; + + job_count = pc_split_atoi(fields[1],jobs,':',CLASS_COUNT); + if (job_count < 1) + return; + for (i = 1; i < job_count; i++) { + job_id = jobs[i]; + if(!pcdb_checkid(job_id)) + { + ShowWarning("status_readdb_maxhp: Invalid job class %d specified.\n", job_id); + return false; + } + idx = pc_class2idx(job_id); + + maxlvl = atoi(fields[0]); + if(maxlvl > MAX_LEVEL){ + ShowWarning("status_readdb_maxhp: Invalid maxlevel %d specified.\n", maxlvl); + return false; + } + if(hpsp_info[idx].max_level && hpsp_info[idx].max_level != maxlvl){ + ShowWarning("status_readdb_maxhp: maxlevel %d was already specified with different value %d.\n",maxlvl,hpsp_info[idx].max_level); + return false; + } + hpsp_info[idx].max_level = maxlvl; + for(i = 2; i < maxlvl; i++) + { + hpsp_info[idx].sp_table[i-1] = atoi(fields[i]); + } + } + return true; +} + static bool status_readdb_sizefix(char* fields[], int columns, int current) { unsigned int i; @@ -11442,34 +11479,33 @@ return true; } -/* -* Read status db -* job1.txt -* job2.txt -* size_fixe.txt -* refine_db.txt -*/ + +/*------------------------------------------ + * DB reading. + * job_db1.txt - job weight, aspd + * job_db2.txt - job level stat bonuses + * job_maxhp_db.txt - job max hp + * job_maxsp_db.txt - job max sp + * size_fix.txt - size adjustment table for weapons + * refine_db.txt - refining data table + *------------------------------------------*/ int status_readdb(void) { int i, j; - // initialize databases to default // - // reset job_db1.txt data memset(max_weight_base, 0, sizeof(max_weight_base)); - memset(hp_coefficient, 0, sizeof(hp_coefficient)); - memset(hp_coefficient2, 0, sizeof(hp_coefficient2)); - memset(sp_coefficient, 0, sizeof(sp_coefficient)); memset(aspd_base, 0, sizeof(aspd_base)); // reset job_db2.txt data memset(job_bonus,0,sizeof(job_bonus)); // Job-specific stats bonus + // hp_sptable + memset(hpsp_info,0,sizeof(hpsp_info)); // size_fix.txt for(i=0;i