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<ARRAYLENGTH(atkmods);i++)
for(j=0;j<MAX_WEAPON_TYPE;j++)
atkmods[i][j]=100;
-
// refine_db.txt
for(i=0;i<ARRAYLENGTH(refine_info);i++)
{
@@ -11482,17 +11518,17 @@
}
// read databases
- //
-
-
+ // path,filename,separator,mincol,maxcol,maxrow,func_parsor
#ifdef RENEWAL_ASPD
- sv_readdb(db_path, "re/job_db1.txt", ',', 6+MAX_WEAPON_TYPE, 6+MAX_WEAPON_TYPE, -1, &status_readdb_job1);
+ sv_readdb(db_path, "re/job_db1.txt",',',6+MAX_WEAPON_TYPE,6+MAX_WEAPON_TYPE,-1,&status_readdb_job1);
#else
- sv_readdb(db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, &status_readdb_job1);
+ sv_readdb(db_path, "pre-re/job_db1.txt",',',5+MAX_WEAPON_TYPE,5+MAX_WEAPON_TYPE,-1,&status_readdb_job1);
#endif
- sv_readdb(db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2);
- sv_readdb(db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix);
+ sv_readdb(db_path, "job_db2.txt",',',1,1+MAX_LEVEL,1,&status_readdb_job2);
+ sv_readdb(db_path, "size_fix.txt",',',MAX_WEAPON_TYPE,MAX_WEAPON_TYPE,ARRAYLENGTH(atkmods),&status_readdb_sizefix);
sv_readdb(db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine);
+ sv_readdb(db_path, DBPATH"job_maxhp_db.txt", ',', 3, -1, 1, &status_readdb_maxhp);
+ sv_readdb(db_path, DBPATH"job_maxsp_db.txt", ',', 3, -1, 1, &status_readdb_maxsp);
return 0;
}
@@ -11508,7 +11544,6 @@
initChangeTables();
initDummyData();
status_readdb();
- status_calc_sigma();
natural_heal_prev_tick = gettick();
sc_data_ers = ers_new(sizeof(struct status_change_entry),"status.c::sc_data_ers",ERS_OPT_NONE);
add_timer_interval(natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status_natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL)