diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/itemdb.c | 34 | ||||
-rw-r--r-- | src/map/itemdb.h | 24 | ||||
-rw-r--r-- | src/map/mob.c | 75 | ||||
-rw-r--r-- | src/map/mob.h | 8 |
4 files changed, 117 insertions, 24 deletions
diff --git a/src/map/itemdb.c b/src/map/itemdb.c index c04639693..04f25ae5b 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -1700,9 +1700,9 @@ static int itemdb_validate_entry(struct item_data *entry, int n, const char *sou nullpo_ret(entry); nullpo_ret(source); - if( entry->nameid <= 0 || entry->nameid >= MAX_ITEMDB ) { - ShowWarning("itemdb_validate_entry: Invalid item ID %d in entry %d of '%s', allowed values 0 < ID < %d (MAX_ITEMDB), skipping.\n", - entry->nameid, n, source, MAX_ITEMDB); + if (entry->nameid <= 0 || entry->nameid > MAX_ITEM_ID) { + ShowWarning("itemdb_validate_entry: Invalid item ID %d in entry %d of '%s', allowed values 0 < ID < %d (MAX_ITEM_ID), skipping.\n", + entry->nameid, n, source, MAX_ITEM_ID); if (entry->script) { script->free_code(entry->script); entry->script = NULL; @@ -2346,6 +2346,7 @@ static bool itemdb_lookup_const_mask(const struct config_setting_t *it, const ch static int itemdb_readdb_libconfig(const char *filename) { bool duplicate[MAX_ITEMDB]; + struct DBMap *duplicate_db; struct config_t item_db_conf; struct config_setting_t *itdb, *it; char filepath[256]; @@ -2362,26 +2363,38 @@ static int itemdb_readdb_libconfig(const char *filename) return 0; } + // TODO add duplicates check for itemdb->other memset(&duplicate,0,sizeof(duplicate)); + duplicate_db = idb_alloc(DB_OPT_BASE); while( (it = libconfig->setting_get_elem(itdb,i++)) ) { int nameid = itemdb->readdb_libconfig_sub(it, i-1, filename); - if (nameid <= 0 || nameid >= MAX_ITEMDB) + if (nameid <= 0 || nameid > MAX_ITEM_ID) continue; itemdb->readdb_additional_fields(nameid, it, i - 1, filename); count++; - if( duplicate[nameid] ) { - ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n", - filename, nameid, itemdb_name(nameid), itemdb_jname(nameid)); - } else - duplicate[nameid] = true; + if (nameid < MAX_ITEMDB) { + if (duplicate[nameid]) { + ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n", + filename, nameid, itemdb_name(nameid), itemdb_jname(nameid)); + } else { + duplicate[nameid] = true; + } + } else { + if (idb_exists(duplicate_db, nameid)) { + ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n", + filename, nameid, itemdb_name(nameid), itemdb_jname(nameid)); + } else { + idb_iput(duplicate_db, nameid, true); + } + } } + db_destroy(duplicate_db); libconfig->destroy(&item_db_conf); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename); - return count; } @@ -2411,6 +2424,7 @@ static void itemdb_read(bool minimal) for (i = 0; i < ARRAYLENGTH(filename); i++) itemdb->readdb_libconfig(filename[i]); + // TODO check duplicate names also in itemdb->other for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) { if( itemdb->array[i] ) { if( itemdb->names->put(itemdb->names,DB->str2key(itemdb->array[i]->name),DB->ptr2data(itemdb->array[i]),&prev) ) { diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 6cce715d3..d92940445 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -36,12 +36,23 @@ struct hplugin_data_store; #ifndef MAX_ITEMDB #define MAX_ITEMDB 0xFFFF #endif + +#ifndef MAX_ITEM_ID +#if PACKETVER_RE_NUM >= 20180704 +#define MAX_ITEM_ID 0x20000 +#else +#define MAX_ITEM_ID 0xFFFF +#endif +#endif + #ifndef MAX_ITEMDELAYS #define MAX_ITEMDELAYS 10 // The maximum number of item delays #endif + #ifndef MAX_SEARCH #define MAX_SEARCH 5 //Designed for search functions, species max number of matches to display. #endif + #ifndef MAX_ITEMS_PER_COMBO #define MAX_ITEMS_PER_COMBO 6 /* maximum amount of items a combo may require */ #endif @@ -58,6 +69,13 @@ struct hplugin_data_store; #define UNKNOWN_ITEM_ID 512 #endif +#if MAX_ITEM_ID < MAX_ITEMDB +#error "MAX_ITEM_ID must be bigger or same with MAX_ITEMDB" +#endif +#if MAX_ITEM_ID > 0xFFFF && PACKETVER_RE_NUM < 20180704 +#error "For clients before 20180704 RE, MAX_ITEM_ID must be smaller than 0x10000" +#endif + enum item_itemid { ITEMID_RED_POTION = 501, ITEMID_YELLOW_POTION = 503, @@ -409,13 +427,13 @@ struct item_combo { }; struct item_group { - unsigned short id; + int id; int *nameid; unsigned short qty; }; struct item_chain_entry { - unsigned short id; + int id; unsigned short rate; struct item_chain_entry *next; }; @@ -426,7 +444,7 @@ struct item_chain { }; struct item_package_rand_entry { - unsigned short id; + int id; unsigned short qty; unsigned short rate; unsigned short hours; diff --git a/src/map/mob.c b/src/map/mob.c index 403e3a2f2..0dbff9211 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -88,6 +88,7 @@ struct item_drop_ratio { int mob_id[MAX_ITEMRATIO_MOBS]; }; static struct item_drop_ratio *item_drop_ratio_db[MAX_ITEMDB]; +static struct DBMap *item_drop_ratio_other_db = NULL; static struct eri *item_drop_ers; //For loot drops delay structures. static struct eri *item_drop_list_ers; @@ -3791,6 +3792,28 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor return (unsigned int)cap_value(rate,rate_min,rate_max); } +static struct item_drop_ratio *mob_get_item_drop_ratio(int nameid) +{ + Assert_retr(NULL, nameid > 0); + if (nameid < ARRAYLENGTH(item_drop_ratio_db)) { + return item_drop_ratio_db[nameid]; + } else { + return (struct item_drop_ratio *)idb_get(item_drop_ratio_other_db, nameid); + } +} + +static void mob_set_item_drop_ratio(int nameid, struct item_drop_ratio *ratio) +{ + Assert_retv(nameid > 0); + if (nameid < ARRAYLENGTH(item_drop_ratio_db)) { + Assert_retv(item_drop_ratio_db[nameid] == NULL); + item_drop_ratio_db[nameid] = ratio; + } else { + Assert_retv(idb_get(item_drop_ratio_other_db, nameid) == NULL); + idb_put(item_drop_ratio_other_db, nameid, ratio); + } +} + /** * Check if global item drop rate is overridden for given item * in db/mob_item_ratio.txt @@ -3800,16 +3823,19 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor */ static void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust) { + struct item_drop_ratio *dropRatio; nullpo_retv(rate_adjust); - if( item_drop_ratio_db[nameid] ) { - if( item_drop_ratio_db[nameid]->mob_id[0] ) { // only for listed mobs + + dropRatio = mob->get_item_drop_ratio(nameid); + if (dropRatio) { + if (dropRatio->mob_id[0] ) { // only for listed mobs int i; - ARR_FIND(0, MAX_ITEMRATIO_MOBS, i, item_drop_ratio_db[nameid]->mob_id[i] == mob_id); - if(i < MAX_ITEMRATIO_MOBS) // found - *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio; + ARR_FIND(0, MAX_ITEMRATIO_MOBS, i, dropRatio->mob_id[i] == mob_id); + if (i < MAX_ITEMRATIO_MOBS) // found + *rate_adjust = dropRatio->drop_ratio; } else // for all mobs - *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio; + *rate_adjust = dropRatio->drop_ratio; } } @@ -5142,6 +5168,7 @@ static bool mob_readdb_race2(char *fields[], int columns, int current) static bool mob_readdb_itemratio(char *str[], int columns, int current) { int nameid, ratio, i; + struct item_drop_ratio *dropRatio; nullpo_retr(false, str); nameid = atoi(str[0]); @@ -5154,12 +5181,15 @@ static bool mob_readdb_itemratio(char *str[], int columns, int current) ratio = atoi(str[1]); - if(item_drop_ratio_db[nameid] == NULL) - item_drop_ratio_db[nameid] = (struct item_drop_ratio*)aCalloc(1, sizeof(struct item_drop_ratio)); + dropRatio = mob->get_item_drop_ratio(nameid); + if (dropRatio == NULL) { + dropRatio = (struct item_drop_ratio*)aCalloc(1, sizeof(struct item_drop_ratio)); + mob->set_item_drop_ratio(nameid, dropRatio); + } - item_drop_ratio_db[nameid]->drop_ratio = ratio; - for(i = 0; i < columns-2; i++) - item_drop_ratio_db[nameid]->mob_id[i] = atoi(str[i+2]); + dropRatio->drop_ratio = ratio; + for (i = 0; i < columns - 2; i++) + dropRatio->mob_id[i] = atoi(str[i + 2]); return true; } @@ -5183,6 +5213,19 @@ static void mob_load(bool minimal) sv->readdb(map->db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, mob->readdb_race2); } +/** + * @see DBApply + */ +static int mob_final_ratio_sub(union DBKey key, struct DBData *data, va_list ap) +{ + struct item_drop_ratio *ratio = DB->data2ptr(data); + + if (ratio) + aFree(ratio); + + return 0; +} + static void mob_reload(void) { int i; @@ -5201,6 +5244,7 @@ static void mob_reload(void) item_drop_ratio_db[i] = NULL; } } + mob->item_drop_ratio_other_db->clear(mob->item_drop_ratio_other_db, mob->final_ratio_sub); mob->load(false); } @@ -5291,6 +5335,8 @@ static int do_final_mob(void) item_drop_ratio_db[i] = NULL; } } + mob->item_drop_ratio_other_db->clear(mob->item_drop_ratio_other_db, mob->final_ratio_sub); + db_destroy(mob->item_drop_ratio_other_db); ers_destroy(item_drop_ers); ers_destroy(item_drop_list_ers); return 0; @@ -5334,6 +5380,10 @@ void mob_defaults(void) memcpy(mob->splendide, mob_splendide, sizeof(mob->splendide)); memcpy(mob->mora, mob_mora, sizeof(mob->mora)); + item_drop_ratio_other_db = idb_alloc(DB_OPT_BASE); + mob->item_drop_ratio_db = item_drop_ratio_db; + mob->item_drop_ratio_other_db = item_drop_ratio_other_db; + /* */ mob->reload = mob_reload; mob->init = do_init_mob; @@ -5438,6 +5488,9 @@ void mob_defaults(void) mob->readdb_race2 = mob_readdb_race2; mob->readdb_itemratio = mob_readdb_itemratio; mob->load = mob_load; + mob->get_item_drop_ratio = mob_get_item_drop_ratio; + mob->set_item_drop_ratio = mob_set_item_drop_ratio; + mob->final_ratio_sub = mob_final_ratio_sub; mob->clear_spawninfo = mob_clear_spawninfo; mob->destroy_mob_db = mob_destroy_mob_db; mob->skill_db_libconfig = mob_skill_db_libconfig; diff --git a/src/map/mob.h b/src/map/mob.h index 3ff3f213b..4cb3877ed 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -25,6 +25,7 @@ #include "map/status.h" // struct status_data, struct status_change #include "map/unit.h" // struct unit_data, view_data #include "common/hercules.h" +#include "common/db.h" #include "common/mmo.h" // struct item struct hplugin_data_store; @@ -72,6 +73,8 @@ struct hplugin_data_store; // Disable this to make monsters not do any path search when looking for a target (old behavior). #define ACTIVEPATHSEARCH +struct item_drop_ratio; + enum e_bosstype { BTYPE_NONE = 0, BTYPE_BOSS = 1, @@ -437,6 +440,8 @@ struct mob_interface { int manuk[8]; int splendide[5]; int mora[5]; + struct item_drop_ratio **item_drop_ratio_db; + struct DBMap *item_drop_ratio_other_db; /* */ int (*init) (bool mimimal); int (*final) (void); @@ -543,6 +548,9 @@ struct mob_interface { bool (*readdb_itemratio) (char *str[], int columns, int current); void (*load) (bool minimal); void (*clear_spawninfo) (void); + struct item_drop_ratio *(*get_item_drop_ratio) (int nameid); + void (*set_item_drop_ratio) (int nameid, struct item_drop_ratio *ratio); + int (*final_ratio_sub) (union DBKey key, struct DBData *data, va_list ap); void (*destroy_mob_db) (int index); bool (*skill_db_libconfig) (const char *filename, bool ignore_missing); bool (*skill_db_libconfig_sub) (struct config_setting_t *it, int n); |