diff options
Diffstat (limited to 'src/map/status.c')
-rw-r--r-- | src/map/status.c | 165 |
1 files changed, 134 insertions, 31 deletions
diff --git a/src/map/status.c b/src/map/status.c index 3ba80e531..7a7a4f415 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -28,13 +28,14 @@ #include "map/vending.h" #include "common/cbasetypes.h" #include "common/ers.h" -#include "common/malloc.h" +#include "common/memmgr.h" #include "common/nullpo.h" #include "common/random.h" #include "common/showmsg.h" #include "common/strlib.h" #include "common/timer.h" #include "common/utils.h" +#include "common/conf.h" #include <math.h> #include <memory.h> @@ -8960,6 +8961,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t { int hp = status_get_hp(bl), sp = status_get_sp(bl), lv = 5; + if (sp < 1) sp = 1; + if (hp < 1) hp = 1; + if( rnd()%100 > (25 + 10 * val1) - status_get_int(bl) / 2) return 0; @@ -12263,38 +12267,136 @@ bool status_readdb_sizefix(char* fields[], int columns, int current) return true; } -bool status_readdb_refine(char* fields[], int columns, int current) +/** + * Processes a refine_db.conf entry. + * + * @param *r Libconfig setting entry. It is expected to be valid and it + * won't be freed (it is care of the caller to do so if + * necessary) + * @param n Ordinal number of the entry, to be displayed in case of + * validation errors. + * @param *source Source of the entry (file name), to be displayed in case of + * validation errors. + * @return # of the validated entry, or 0 in case of failure. + */ +int status_readdb_refine_libconfig_sub(config_setting_t *r, const char *name, const char *source) { - int i, bonus_per_level, random_bonus, random_bonus_start_level; - - current = atoi(fields[0]); - - if (current < 0 || current >= REFINE_TYPE_MAX) - return false; - - bonus_per_level = atoi(fields[1]); - random_bonus_start_level = atoi(fields[2]); - random_bonus = atoi(fields[3]); - - for(i = 0; i < MAX_REFINE; i++) - { - char* delim; - - if (!(delim = strchr(fields[4+i], ':'))) - return false; - - *delim = '\0'; - - status->dbs->refine_info[current].chance[i] = atoi(fields[4+i]); + config_setting_t *rate = NULL; + int type = REFINE_TYPE_ARMOR, bonus_per_level = 0, rnd_bonus_v = 0, rnd_bonus_lv = 0; + char lv[4]; + nullpo_ret(r); + nullpo_ret(name); + nullpo_ret(source); + + if (strncmp(name, "Armors", 6) == 0) { + type = REFINE_TYPE_ARMOR; + } else if (strncmp(name, "WeaponLevel", 11) != 0 || !strspn(&name[strlen(name)-1], "0123456789") || (type = atoi(strncpy(lv, name+11, 2))) == REFINE_TYPE_ARMOR) { + ShowError("status_readdb_refine_libconfig_sub: Invalid key name for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + if (type < REFINE_TYPE_ARMOR || type >= REFINE_TYPE_MAX) { + ShowError("status_readdb_refine_libconfig_sub: Out of range level for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + if (!libconfig->setting_lookup_int(r, "StatsPerLevel", &bonus_per_level)) { + ShowWarning("status_readdb_refine_libconfig_sub: Missing StatsPerLevel for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + if (!libconfig->setting_lookup_int(r, "RandomBonusStartLevel", &rnd_bonus_lv)) { + ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusStartLevel for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + if (!libconfig->setting_lookup_int(r, "RandomBonusValue", &rnd_bonus_v)) { + ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusValue for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } - if (i >= random_bonus_start_level - 1) - status->dbs->refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2); + if ((rate=libconfig->setting_get_member(r, "Rates")) != NULL && config_setting_is_group(rate)) { + config_setting_t *t = NULL; + bool duplicate[MAX_REFINE]; + int bonus[MAX_REFINE], rnd_bonus[MAX_REFINE], chance[MAX_REFINE]; + int i; + memset(&duplicate, 0, sizeof(duplicate)); + memset(&bonus, 0, sizeof(bonus)); + memset(&rnd_bonus, 0, sizeof(rnd_bonus)); + + for (i = 0; i < MAX_REFINE; i++) { + chance[i] = 100; + } + i = 0; + while ((t = libconfig->setting_get_elem(rate,i++)) != NULL && config_setting_is_group(t)) { + int level = 0, i32; + char *rlvl = config_setting_name(t); + memset(&lv, 0, sizeof(lv)); + if (!strspn(&rlvl[strlen(rlvl)-1], "0123456789") || (level = atoi(strncpy(lv, rlvl+2, 3))) <= 0) { + ShowError("status_readdb_refine_libconfig_sub: Invalid refine level format '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source); + continue; + } + if (level <= 0 || level > MAX_REFINE) { + ShowError("status_readdb_refine_libconfig_sub: Out of range refine level '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source); + continue; + } + level--; + if (duplicate[level]) { + ShowWarning("status_readdb_refine_libconfig_sub: duplicate rate '%s' for entry %s in \"%s\", overwriting previous entry...\n", rlvl, name, source); + } else { + duplicate[level] = true; + } + if (libconfig->setting_lookup_int(t, "Chance", &i32)) + chance[level] = i32; + else + chance[level] = 100; + if (libconfig->setting_lookup_int(t, "Bonus", &i32)) + bonus[level] += i32; + if (level >= rnd_bonus_lv - 1) + rnd_bonus[level] = rnd_bonus_v * (level - rnd_bonus_lv + 2); + } + for (i = 0; i < MAX_REFINE; i++) { + status->dbs->refine_info[type].chance[i] = chance[i]; + status->dbs->refine_info[type].randombonus_max[i] = rnd_bonus[i]; + bonus[i] += bonus_per_level + (i > 0 ? bonus[i-1] : 0); + status->dbs->refine_info[type].bonus[i] = bonus[i]; + } + } else { + ShowWarning("status_readdb_refine_libconfig_sub: Missing refine rates for entry '%s' in \"%s\", skipping.\n", name, source); + return 0; + } + return type+1; +} - status->dbs->refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1); - if (i > 0) - status->dbs->refine_info[current].bonus[i] += status->dbs->refine_info[current].bonus[i-1]; +/** + * Reads from a libconfig-formatted refine_db.conf file. + * + * @param *filename File name, relative to the database path. + * @return The number of found entries. + */ +int status_readdb_refine_libconfig(const char *filename) { + bool duplicate[REFINE_TYPE_MAX]; + config_t refine_db_conf; + config_setting_t *r; + char filepath[256]; + int i = 0, count = 0,type = 0; + + sprintf(filepath, "%s/%s", map->db_path, filename); + memset(&duplicate,0,sizeof(duplicate)); + if( libconfig->read_file(&refine_db_conf, filepath) ) { + ShowError("can't read %s\n", filepath); + return 0; } - return true; + + while((r = libconfig->setting_get_elem(refine_db_conf.root,i++))) { + char *name = config_setting_name(r); + if((type=status->readdb_refine_libconfig_sub(r, name, filename))) { + if( duplicate[type-1] ) { + ShowWarning("status_readdb_refine_libconfig: duplicate entry for %s in \"%s\", overwriting previous entry...\n", name, filename); + } else duplicate[type-1] = true; + count++; + } + } + libconfig->destroy(&refine_db_conf); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename); + + return count; } bool status_readdb_scconfig(char* fields[], int columns, int current) { @@ -12357,7 +12459,7 @@ int status_readdb(void) // sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2); sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix); - sv->readdb(map->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(status->dbs->refine_info), status->readdb_refine); + status->readdb_refine_libconfig(DBPATH"refine_db.conf"); sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig); status->read_job_db(); @@ -12532,7 +12634,8 @@ void status_defaults(void) { status->natural_heal_timer = status_natural_heal_timer; status->readdb_job2 = status_readdb_job2; status->readdb_sizefix = status_readdb_sizefix; - status->readdb_refine = status_readdb_refine; + status->readdb_refine_libconfig = status_readdb_refine_libconfig; + status->readdb_refine_libconfig_sub = status_readdb_refine_libconfig_sub; status->readdb_scconfig = status_readdb_scconfig; status->read_job_db = status_read_job_db; status->read_job_db_sub = status_read_job_db_sub; |