diff options
Diffstat (limited to 'src/map/itemdb.c')
-rw-r--r-- | src/map/itemdb.c | 389 |
1 files changed, 271 insertions, 118 deletions
diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 6428bade5..27adc387b 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -342,81 +342,202 @@ const char* itemdb_typename(int type) return "Unknown Type"; } -/*========================================== - * Converts the jobid from the format in itemdb - * to the format used by the map server. [Skotlex] - *------------------------------------------*/ -void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask) + /** + * Converts the JobID to the format used by map-server to check item + * restriction as per job. + * + * @param bclass Pointer to the variable containing the new format + * @param job_id Variable containing JobID + * @param enable Boolean value which (un)set the restriction. + * + * @author Dastgir + */ +void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable) { + uint64 mask[3] = { 0 }; int i; + nullpo_retv(bclass); - bclass[0]= bclass[1]= bclass[2]= 0; + + switch(job_id) { + // Base Classes + case JOB_NOVICE: + case JOB_SUPER_NOVICE: + mask[0] = 1ULL << MAPID_NOVICE; + mask[1] = 1ULL << MAPID_NOVICE; + break; + case JOB_SWORDMAN: + case JOB_MAGE: + case JOB_ARCHER: + case JOB_ACOLYTE: + case JOB_MERCHANT: + case JOB_THIEF: + mask[0] = 1ULL << (MAPID_NOVICE+job_id); + break; + // 2-1 Classes + case JOB_KNIGHT: + mask[1] = 1ULL << MAPID_SWORDMAN; + break; + case JOB_PRIEST: + mask[1] = 1ULL << MAPID_ACOLYTE; + break; + case JOB_WIZARD: + mask[1] = 1ULL << MAPID_MAGE; + break; + case JOB_BLACKSMITH: + mask[1] = 1ULL << MAPID_MERCHANT; + break; + case JOB_HUNTER: + mask[1] = 1ULL << MAPID_ARCHER; + break; + case JOB_ASSASSIN: + mask[1] = 1ULL << MAPID_THIEF; + break; + // 2-2 Classes + case JOB_CRUSADER: + mask[2] = 1ULL << MAPID_SWORDMAN; + break; + case JOB_MONK: + mask[2] = 1ULL << MAPID_ACOLYTE; + break; + case JOB_SAGE: + mask[2] = 1ULL << MAPID_MAGE; + break; + case JOB_ALCHEMIST: + mask[2] = 1ULL << MAPID_MERCHANT; + break; + case JOB_BARD: + mask[2] = 1ULL << MAPID_ARCHER; + break; + case JOB_ROGUE: + mask[2] = 1ULL << MAPID_THIEF; + break; + // Extended Classes + case JOB_TAEKWON: + mask[0] = 1ULL << MAPID_TAEKWON; + break; + case JOB_STAR_GLADIATOR: + mask[1] = 1ULL << MAPID_TAEKWON; + break; + case JOB_SOUL_LINKER: + mask[2] = 1ULL << MAPID_TAEKWON; + break; + case JOB_GUNSLINGER: + mask[0] = 1ULL << MAPID_GUNSLINGER; + mask[1] = 1ULL << MAPID_GUNSLINGER; + break; + case JOB_NINJA: + mask[0] = 1ULL << MAPID_NINJA; + mask[1] = 1ULL << MAPID_NINJA; + break; + case JOB_KAGEROU: + case JOB_OBORO: + mask[1] = 1ULL << MAPID_NINJA; + break; + case JOB_REBELLION: + mask[1] = 1ULL << MAPID_GUNSLINGER; + break; + // Other Classes + case JOB_GANGSI: //Bongun/Munak + mask[0] = 1ULL << MAPID_GANGSI; + break; + case JOB_DEATH_KNIGHT: + mask[1] = 1ULL << MAPID_GANGSI; + break; + case JOB_DARK_COLLECTOR: + mask[2] = 1ULL << MAPID_GANGSI; + break; + } + + for (i = 0; i < ARRAYLENGTH(mask); i++) { + if (mask[i] == 0) + continue; + if (enable) + bclass[i] |= mask[i]; + else + bclass[i] &= ~mask[i]; + } +} + +/** + * Converts the JobMask to the format used by map-server to check item + * restriction as per job. + * + * @param bclass Pointer to the variable containing the new format. + * @param jobmask Variable containing JobMask. + */ +void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask) +{ + int i; + nullpo_retv(bclass); + bclass[0] = bclass[1] = bclass[2] = 0; //Base classes - if (jobmask & 1<<JOB_NOVICE) { + if (jobmask & 1ULL<<JOB_NOVICE) { //Both Novice/Super-Novice are counted with the same ID - bclass[0] |= 1<<MAPID_NOVICE; - bclass[1] |= 1<<MAPID_NOVICE; + bclass[0] |= 1ULL<<MAPID_NOVICE; + bclass[1] |= 1ULL<<MAPID_NOVICE; } - for (i = JOB_NOVICE+1; i <= JOB_THIEF; i++) - { - if (jobmask & 1<<i) - bclass[0] |= 1<<(MAPID_NOVICE+i); + for (i = JOB_NOVICE+1; i <= JOB_THIEF; i++) { + if (jobmask & 1ULL<<i) + bclass[0] |= 1ULL<<(MAPID_NOVICE+i); } //2-1 classes - if (jobmask & 1<<JOB_KNIGHT) - bclass[1] |= 1<<MAPID_SWORDMAN; - if (jobmask & 1<<JOB_PRIEST) - bclass[1] |= 1<<MAPID_ACOLYTE; - if (jobmask & 1<<JOB_WIZARD) - bclass[1] |= 1<<MAPID_MAGE; - if (jobmask & 1<<JOB_BLACKSMITH) - bclass[1] |= 1<<MAPID_MERCHANT; - if (jobmask & 1<<JOB_HUNTER) - bclass[1] |= 1<<MAPID_ARCHER; - if (jobmask & 1<<JOB_ASSASSIN) - bclass[1] |= 1<<MAPID_THIEF; + if (jobmask & 1ULL<<JOB_KNIGHT) + bclass[1] |= 1ULL<<MAPID_SWORDMAN; + if (jobmask & 1ULL<<JOB_PRIEST) + bclass[1] |= 1ULL<<MAPID_ACOLYTE; + if (jobmask & 1ULL<<JOB_WIZARD) + bclass[1] |= 1ULL<<MAPID_MAGE; + if (jobmask & 1ULL<<JOB_BLACKSMITH) + bclass[1] |= 1ULL<<MAPID_MERCHANT; + if (jobmask & 1ULL<<JOB_HUNTER) + bclass[1] |= 1ULL<<MAPID_ARCHER; + if (jobmask & 1ULL<<JOB_ASSASSIN) + bclass[1] |= 1ULL<<MAPID_THIEF; //2-2 classes - if (jobmask & 1<<JOB_CRUSADER) - bclass[2] |= 1<<MAPID_SWORDMAN; - if (jobmask & 1<<JOB_MONK) - bclass[2] |= 1<<MAPID_ACOLYTE; - if (jobmask & 1<<JOB_SAGE) - bclass[2] |= 1<<MAPID_MAGE; - if (jobmask & 1<<JOB_ALCHEMIST) - bclass[2] |= 1<<MAPID_MERCHANT; - if (jobmask & 1<<JOB_BARD) - bclass[2] |= 1<<MAPID_ARCHER; + if (jobmask & 1ULL<<JOB_CRUSADER) + bclass[2] |= 1ULL<<MAPID_SWORDMAN; + if (jobmask & 1ULL<<JOB_MONK) + bclass[2] |= 1ULL<<MAPID_ACOLYTE; + if (jobmask & 1ULL<<JOB_SAGE) + bclass[2] |= 1ULL<<MAPID_MAGE; + if (jobmask & 1ULL<<JOB_ALCHEMIST) + bclass[2] |= 1ULL<<MAPID_MERCHANT; + if (jobmask & 1ULL<<JOB_BARD) + bclass[2] |= 1ULL<<MAPID_ARCHER; #if 0 // Bard/Dancer share the same slot now. - if (jobmask & 1<<JOB_DANCER) - bclass[2] |= 1<<MAPID_ARCHER; + if (jobmask & 1ULL<<JOB_DANCER) + bclass[2] |= 1ULL<<MAPID_ARCHER; #endif // 0 - if (jobmask & 1<<JOB_ROGUE) - bclass[2] |= 1<<MAPID_THIEF; + if (jobmask & 1ULL<<JOB_ROGUE) + bclass[2] |= 1ULL<<MAPID_THIEF; //Special classes that don't fit above. - if (jobmask & 1<<21) //Taekwon boy - bclass[0] |= 1<<MAPID_TAEKWON; - if (jobmask & 1<<22) //Star Gladiator - bclass[1] |= 1<<MAPID_TAEKWON; - if (jobmask & 1<<23) //Soul Linker - bclass[2] |= 1<<MAPID_TAEKWON; - if (jobmask & 1<<JOB_GUNSLINGER) - {//Rebellion job can equip Gunslinger equips. [Rytech] - bclass[0] |= 1<<MAPID_GUNSLINGER; - bclass[1] |= 1<<MAPID_GUNSLINGER; - } - if (jobmask & 1<<JOB_NINJA) - {bclass[0] |= 1<<MAPID_NINJA; - bclass[1] |= 1<<MAPID_NINJA;}//Kagerou/Oboro jobs can equip Ninja equips. [Rytech] - if (jobmask & 1<<26) //Bongun/Munak - bclass[0] |= 1<<MAPID_GANGSI; - if (jobmask & 1<<27) //Death Knight - bclass[1] |= 1<<MAPID_GANGSI; - if (jobmask & 1<<28) //Dark Collector - bclass[2] |= 1<<MAPID_GANGSI; - if (jobmask & 1<<29) //Kagerou / Oboro - bclass[1] |= 1<<MAPID_NINJA; - if (jobmask & 1<<30) //Rebellion - bclass[1] |= 1<<MAPID_GUNSLINGER; + if (jobmask & 1ULL<<21) //Taekwon boy + bclass[0] |= 1ULL<<MAPID_TAEKWON; + if (jobmask & 1ULL<<22) //Star Gladiator + bclass[1] |= 1ULL<<MAPID_TAEKWON; + if (jobmask & 1ULL<<23) //Soul Linker + bclass[2] |= 1ULL<<MAPID_TAEKWON; + if (jobmask & 1ULL<<JOB_GUNSLINGER) { + //Rebellion job can equip Gunslinger equips. [Rytech] + bclass[0] |= 1ULL<<MAPID_GUNSLINGER; + bclass[1] |= 1ULL<<MAPID_GUNSLINGER; + } + if (jobmask & 1ULL<<JOB_NINJA) { + //Kagerou/Oboro jobs can equip Ninja equips. [Rytech] + bclass[0] |= 1ULL<<MAPID_NINJA; + bclass[1] |= 1ULL<<MAPID_NINJA; + } + if (jobmask & 1ULL<<26) //Bongun/Munak + bclass[0] |= 1ULL<<MAPID_GANGSI; + if (jobmask & 1ULL<<27) //Death Knight + bclass[1] |= 1ULL<<MAPID_GANGSI; + if (jobmask & 1ULL<<28) //Dark Collector + bclass[2] |= 1ULL<<MAPID_GANGSI; + if (jobmask & 1ULL<<29) //Kagerou / Oboro + bclass[1] |= 1ULL<<MAPID_NINJA; + if (jobmask & 1ULL<<30) //Rebellion + bclass[1] |= 1ULL<<MAPID_GUNSLINGER; } void create_dummy_data(void) @@ -637,8 +758,8 @@ int itemdb_isidentified2(struct item_data *data) { } void itemdb_read_groups(void) { - config_t item_group_conf; - config_setting_t *itg = NULL, *it = NULL; + struct config_t item_group_conf; + struct config_setting_t *itg = NULL, *it = NULL; #ifdef RENEWAL const char *config_filename = "db/re/item_group.conf"; // FIXME hardcoded name #else @@ -648,10 +769,8 @@ void itemdb_read_groups(void) { int i = 0, count = 0, c; unsigned int *gsize = NULL; - if (libconfig->read_file(&item_group_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&item_group_conf, config_filename)) return; - } gsize = aMalloc( libconfig->setting_length(item_group_conf.root) * sizeof(unsigned int) ); @@ -929,8 +1048,8 @@ bool itemdb_read_cached_packages(const char *config_filename) { return true; } void itemdb_read_packages(void) { - config_t item_packages_conf; - config_setting_t *itg = NULL, *it = NULL, *t = NULL; + struct config_t item_packages_conf; + struct config_setting_t *itg = NULL, *it = NULL, *t = NULL; #ifdef RENEWAL const char *config_filename = "db/re/item_packages.conf"; // FIXME hardcoded name #else @@ -946,10 +1065,8 @@ void itemdb_read_packages(void) { return; } - if (libconfig->read_file(&item_packages_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&item_packages_conf, config_filename)) return; - } must = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) ); random = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) ); @@ -1161,8 +1278,8 @@ void itemdb_read_packages(void) { } void itemdb_read_chains(void) { - config_t item_chain_conf; - config_setting_t *itc = NULL; + struct config_t item_chain_conf; + struct config_setting_t *itc = NULL; #ifdef RENEWAL const char *config_filename = "db/re/item_chain.conf"; // FIXME hardcoded name #else @@ -1170,10 +1287,8 @@ void itemdb_read_chains(void) { #endif int i = 0, count = 0; - if (libconfig->read_file(&item_chain_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&item_chain_conf, config_filename)) return; - } CREATE(itemdb->chains, struct item_chain, libconfig->setting_length(item_chain_conf.root)); itemdb->chain_count = (unsigned short)libconfig->setting_length(item_chain_conf.root); @@ -1186,7 +1301,7 @@ void itemdb_read_chains(void) { struct item_chain_entry *prev = NULL; const char *name = config_setting_name(itc); int c = 0; - config_setting_t *entry = NULL; + struct config_setting_t *entry = NULL; script->set_constant2(name, i-1, false, false); itemdb->chains[count].qty = (unsigned short)libconfig->setting_length(itc); @@ -1286,7 +1401,7 @@ void itemdb_read_combos(void) if (!strchr(p,',')) { /* is there even a single column? */ - ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, filepath); + ShowError("itemdb_read_combos: Insufficient columns in line %u of \"%s\", skipping.\n", lines, filepath); continue; } @@ -1300,13 +1415,13 @@ void itemdb_read_combos(void) p++; if (str[1][0] != '{') { - ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, filepath); + ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %u of \"%s\", skipping.\n", lines, filepath); continue; } /* no ending key anywhere (missing \}\) */ if ( str[1][strlen(str[1])-1] != '}' ) { - ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, filepath); + ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %u of \"%s\", skipping.\n", lines, filepath); continue; } else { int items[MAX_ITEMS_PER_COMBO]; @@ -1314,14 +1429,14 @@ void itemdb_read_combos(void) struct item_combo *combo = NULL; if((retcount = itemdb->combo_split_atoi(str[0], items)) < 2) { - ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, filepath); + ShowError("itemdb_read_combos: line %u of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, filepath); continue; } /* validate */ for(v = 0; v < retcount; v++) { if( !itemdb->exists(items[v]) ) { - ShowError("itemdb_read_combos: line %d of \"%s\" contains unknown item ID %d, skipping.\n", lines, filepath,items[v]); + ShowError("itemdb_read_combos: line %u of \"%s\" contains unknown item ID %d, skipping.\n", lines, filepath, items[v]); break; } } @@ -1385,17 +1500,17 @@ int itemdb_gendercheck(struct item_data *id) * This function is called after preparing the item entry data, and it takes * care of inserting it and cleaning up any remainders of the previous one. * - * @param *entry Pointer to the new item_data entry. Ownership is NOT taken, - * but the content is modified to reflect the validation. - * @param n Ordinal number of the entry, to be displayed in case of - * validation errors. - * @param *source Source of the entry (table or file name), to be displayed in - * case of validation errors. + * @param entry Pointer to the new item_data entry. Ownership is NOT taken, + * but the content is modified to reflect the validation. + * @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 Nameid of the validated entry, or 0 in case of failure. * - * Note: This is safe to call if the new entry is a copy of the old one (i.e. - * item_db2 inheritance), as it will make sure not to free any scripts still in - * use in the new entry. + * Note: This is safe to call if the new entry is a shallow copy of the old one + * (i.e. item_db2 inheritance), as it will make sure not to free any scripts + * still in use by the new entry. */ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { struct item_data *item; @@ -1462,7 +1577,7 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { if (entry->flag.trade_restriction > ITR_ALL) { ShowWarning("itemdb_validate_entry: Invalid trade restriction flag 0x%x for item %d (%s) in '%s', defaulting to none.\n", - entry->flag.trade_restriction, entry->nameid, entry->jname, source); + (unsigned int)entry->flag.trade_restriction, entry->nameid, entry->jname, source); entry->flag.trade_restriction = ITR_NONE; } @@ -1535,27 +1650,53 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { return item->nameid; } -void itemdb_readdb_additional_fields(int itemid, config_setting_t *it, int n, const char *source) +void itemdb_readdb_additional_fields(int itemid, struct config_setting_t *it, int n, const char *source) { // do nothing. plugins can do own work } /** + * Processes job names and changes it into mapid format. + * + * @param id item_data entry. + * @param t 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). + */ +void itemdb_readdb_job_sub(struct item_data *id, struct config_setting_t *t) +{ + int idx = 0; + struct config_setting_t *it = NULL; + id->class_base[0] = id->class_base[1] = id->class_base[2] = 0; + while ((it = libconfig->setting_get_elem(t, idx++)) != NULL) { + const char *job_name = config_setting_name(it); + int job_id; + + if (strcmp(job_name, "All") == 0) { + itemdb->jobmask2mapid(id->class_base, UINT64_MAX); + } else if ((job_id = pc->check_job_name(job_name)) == -1) { + ShowWarning("itemdb_readdb_job_sub: unknown job name '%s'!\n", job_name); + } else { + itemdb->jobid2mapid(id->class_base, job_id, libconfig->setting_get_bool(it)); + } + } +} + +/** * Processes one itemdb entry from the libconfig backend, loading and inserting * it into the item database. * - * @param *it 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. + * @param it 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 Nameid of the validated entry, or 0 in case of failure. */ -int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) { +int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *source) { struct item_data id = { 0 }; - config_setting_t *t = NULL; + struct config_setting_t *t = NULL; const char *str = NULL; int i32 = 0; bool inherit = false; @@ -1627,7 +1768,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) } else { // Use old entry as default struct item_data *old_entry = itemdb->load(id.nameid); - memcpy(&id, old_entry, sizeof(struct item_data)); + memcpy(&id, old_entry, sizeof(id)); } } @@ -1681,10 +1822,15 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if( itemdb->lookup_const(it, "Slots", &i32) && i32 >= 0 ) id.slot = i32; - if( itemdb->lookup_const(it, "Job", &i32) ) // This is an unsigned value, do not check for >= 0 - itemdb->jobid2mapid(id.class_base, (unsigned int)i32); - else if( !inherit ) - itemdb->jobid2mapid(id.class_base, UINT_MAX); + if ((t = libconfig->setting_get_member(it, "Job")) != NULL) { + if (config_setting_is_group(t)) { + itemdb->readdb_job_sub(&id, t); + } else if (itemdb->lookup_const(it, "Job", &i32) && i32 >= 0) { + itemdb->jobmask2mapid(id.class_base, i32); + } + } else if (!inherit) { + itemdb->jobmask2mapid(id.class_base, UINT64_MAX); + } if( itemdb->lookup_const(it, "Upper", &i32) && i32 >= 0 ) id.class_upper = (unsigned int)i32; @@ -1736,7 +1882,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if ( (t = libconfig->setting_get_member(it, "Trade")) ) { if (config_setting_is_group(t)) { - config_setting_t *tt = NULL; + struct config_setting_t *tt = NULL; if ((tt = libconfig->setting_get_member(t, "override"))) { id.gm_lv_trade_override = libconfig->setting_get_int(tt); @@ -1802,7 +1948,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if ((t = libconfig->setting_get_member(it, "Nouse"))) { if (config_setting_is_group(t)) { - config_setting_t *nt = NULL; + struct config_setting_t *nt = NULL; if ((nt = libconfig->setting_get_member(t, "override"))) { id.item_usage.override = libconfig->setting_get_int(nt); @@ -1850,7 +1996,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) return itemdb->validate_entry(&id, n, source); } -bool itemdb_lookup_const(const config_setting_t *it, const char *name, int *value) +bool itemdb_lookup_const(const struct config_setting_t *it, const char *name, int *value) { nullpo_retr(false, name); nullpo_retr(false, value); @@ -1874,24 +2020,29 @@ bool itemdb_lookup_const(const config_setting_t *it, const char *name, int *valu * Reads from a libconfig-formatted itemdb file and inserts the found entries into the * item database, overwriting duplicate ones (i.e. item_db2 overriding item_db.) * - * @param *filename File name, relative to the database path. + * @param filename File name, relative to the database path. * @return The number of found entries. */ int itemdb_readdb_libconfig(const char *filename) { bool duplicate[MAX_ITEMDB]; - config_t item_db_conf; - config_setting_t *itdb, *it; + struct config_t item_db_conf; + struct config_setting_t *itdb, *it; char filepath[256]; int i = 0, count = 0; nullpo_ret(filename); + sprintf(filepath, "%s/%s", map->db_path, filename); - memset(&duplicate,0,sizeof(duplicate)); - if( libconfig->read_file(&item_db_conf, filepath) || !(itdb = libconfig->setting_get_member(item_db_conf.root, "item_db")) ) { + if (!libconfig->load_file(&item_db_conf, filepath)) + return 0; + + if ((itdb = libconfig->setting_get_member(item_db_conf.root, "item_db")) == NULL) { ShowError("can't read %s\n", filepath); return 0; } + memset(&duplicate,0,sizeof(duplicate)); + while( (it = libconfig->setting_get_elem(itdb,i++)) ) { int nameid = itemdb->readdb_libconfig_sub(it, i-1, filename); @@ -2227,6 +2378,7 @@ void itemdb_defaults(void) { itemdb->searchname_array_sub = itemdb_searchname_array_sub; itemdb->searchrandomid = itemdb_searchrandomid; itemdb->typename = itemdb_typename; + itemdb->jobmask2mapid = itemdb_jobmask2mapid; itemdb->jobid2mapid = itemdb_jobid2mapid; itemdb->create_dummy_data = create_dummy_data; itemdb->create_item_data = create_item_data; @@ -2251,6 +2403,7 @@ void itemdb_defaults(void) { itemdb->gendercheck = itemdb_gendercheck; itemdb->validate_entry = itemdb_validate_entry; itemdb->readdb_additional_fields = itemdb_readdb_additional_fields; + itemdb->readdb_job_sub = itemdb_readdb_job_sub; itemdb->readdb_libconfig_sub = itemdb_readdb_libconfig_sub; itemdb->readdb_libconfig = itemdb_readdb_libconfig; itemdb->unique_id = itemdb_unique_id; |