Bläddra i källkod

* Follow up 7cd82d0
-- Changed itemdb_array (array) to itemdb (DBMap)
-- Removed itemdb_other (DBMap)
-- Changed MAX_ITEMDB to MAX_ITEMID, by default limit is USHRT_MAX (65,535)
-- Changed item_drop_ratio_db (array) to mob_item_drop_ratio (DBMap)
-- Now all item datas stored in itemdb (DBMap) and mob item ratio datas in mob_item_drop_ratio (DBMap)

PS: I just realized that db/import/mob_item_ratio.txt doesn't work, because it loaded after mob_db.txt (another thing to do)
Signed-off-by: Cydh Ramdh <house.bad@gmail.com>

Cydh Ramdh 11 år sedan
förälder
incheckning
6c5d4a730f

+ 1 - 1
conf/msg_conf/map_msg.conf

@@ -92,7 +92,7 @@
 75: War of Emperium is currently not in progress.
 76: All skills have been added to your skill tree.
 77: The reference result of '%s' (name: id):
-78: %s: %d
+78: - %s: %d
 79: It is %d affair above.
 80: Give the display name or monster name/id please.
 81: Your GM level doesn't authorize you to perform this action on the specified player.

+ 1 - 1
conf/msg_conf/map_msg_idn.conf

@@ -92,7 +92,7 @@
 75: War of Emperium saat ini tidak sedang berjalan.
 76: Semua skill telah ditambahkan ke skill tree.
 77: Hasil referensi dari '%s' (nama: id):
-78: %s: %d
+78: - %s: %d
 79: Terdapat %d hal di atas.
 80: Harap berikan nama tampilan atau nama/id monster.
 81: Level GM kamu tidak diizinkan untuk untuk melakukan aksi ini pada pemain tertentu.

+ 1 - 2
db/import-tmpl/mob_item_ratio.txt

@@ -2,7 +2,7 @@
 // Overrides for global item_rate* values from conf/battle/drops.conf
 //
 // Structure of Database:
-// ItemID,Ratio{,MonsterID}
+// ItemID,Ratio{,MonsterID1,...,MonsterID10}
 //
 // Result:
 // ItemID base drop rates defined in mob_db will not get multiplied
@@ -28,4 +28,3 @@
 //   for different monsters, override drop rate with Ratio=100 and edit
 //   base drop rates in mob_db.
 // - This file is reloaded by @reloadmobdb.
-

+ 1 - 1
db/mob_item_ratio.txt

@@ -2,7 +2,7 @@
 // Overrides for global item_rate* values from conf/battle/drops.conf
 //
 // Structure of Database:
-// ItemID,Ratio{,MonsterID}
+// ItemID,Ratio{,MonsterID1,...,MonsterID10}
 //
 // Result:
 // ItemID base drop rates defined in mob_db will not get multiplied

+ 88 - 170
src/map/itemdb.c

@@ -18,12 +18,11 @@
 #include <stdlib.h>
 #include <string.h>
 
-static struct item_data* itemdb_array[MAX_ITEMDB];
-struct item_data dummy_item; //This is the default dummy item used for non-existant items. [Skotlex]
+struct item_data *dummy_item; /// This is the default dummy item used for non-existant items. [Skotlex]
 
-static DBMap* itemdb_other;// unsigned short nameid -> struct item_data*
-static DBMap *itemdb_combo;
-static DBMap *itemdb_group;
+static DBMap* itemdb; /// Item DB
+static DBMap *itemdb_combo; /// Item Combo DB
+static DBMap *itemdb_group; /// Item Group DB
 
 DBMap * itemdb_get_combodb(){
 	return itemdb_combo;
@@ -42,50 +41,37 @@ static int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap)
 {
 	struct item_data *item = db_data2ptr(data), **dst, **dst2;
 	char *str;
-	str=va_arg(ap,char *);
-	dst=va_arg(ap,struct item_data **);
-	dst2=va_arg(ap,struct item_data **);
-	if(item == &dummy_item) return 0;
+	str = va_arg(ap,char *);
+	dst = va_arg(ap,struct item_data **);
+	dst2 = va_arg(ap,struct item_data **);
+	if (item == dummy_item)
+		return 0;
 
 	//Absolute priority to Aegis code name.
-	if (*dst != NULL) return 0;
-	if( strcmpi(item->name,str)==0 )
-		*dst=item;
+	if (*dst != NULL)
+		return 0;
+	if (strcmpi(item->name,str) == 0)
+		*dst = item;
 
 	//Second priority to Client displayed name.
 	if (*dst2 != NULL) return 0;
-	if( strcmpi(item->jname,str)==0 )
-		*dst2=item;
+	if (strcmpi(item->jname,str) == 0)
+		*dst2 = item;
 	return 0;
 }
 
 /*==========================================
  * Return item data from item name. (lookup)
+ * @param str Item Name
+ * @return item data
  *------------------------------------------*/
 struct item_data* itemdb_searchname(const char *str)
 {
-	struct item_data* item;
-	struct item_data* item2=NULL;
-	int i;
-
-	for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
-	{
-		item = itemdb_array[i];
-		if( item == NULL )
-			continue;
-
-		// Absolute priority to Aegis code name.
-		if( strcasecmp(item->name,str) == 0 )
-			return item;
-
-		//Second priority to Client displayed name.
-		if( strcasecmp(item->jname,str) == 0 )
-			item2 = item;
-	}
+	struct item_data* item = NULL;
+	struct item_data* item2 = NULL;
 
-	item = NULL;
-	itemdb_other->foreach(itemdb_other,itemdb_searchname_sub,str,&item,&item2);
-	return item?item:item2;
+	itemdb->foreach(itemdb,itemdb_searchname_sub,str,&item,&item2);
+	return item ? item : item2;
 }
 
 /**
@@ -95,51 +81,32 @@ static int itemdb_searchname_array_sub(DBKey key, DBData data, va_list ap)
 {
 	struct item_data *item = db_data2ptr(&data);
 	char *str;
-	str=va_arg(ap,char *);
-	if (item == &dummy_item)
+	str = va_arg(ap,char *);
+	if (item == dummy_item)
 		return 1; //Invalid item.
-	if(stristr(item->jname,str))
+	if (stristr(item->jname,str))
 		return 0;
-	if(stristr(item->name,str))
+	if (stristr(item->name,str))
 		return 0;
 	return strcmpi(item->jname,str);
 }
 
 /*==========================================
  * Founds up to N matches. Returns number of matches [Skotlex]
+ * @param *data
+ * @param size
+ * @param str
+ * @return Number of matches item
  *------------------------------------------*/
 int itemdb_searchname_array(struct item_data** data, int size, const char *str)
 {
-	struct item_data* item;
-	int i;
-	int count=0;
+	DBData *db_data[MAX_SEARCH];
+	int i, count = 0, db_count;
 
-	// Search in the array
-	for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
-	{
-		item = itemdb_array[i];
-		if( item == NULL )
-			continue;
+	db_count = itemdb->getall(itemdb, (DBData**)&db_data, size, itemdb_searchname_array_sub, str);
+	for (i = 0; i < db_count && count < size; i++)
+		data[count++] = db_data2ptr(db_data[i]);
 
-		if( stristr(item->jname,str) || stristr(item->name,str) )
-		{
-			if( count < size )
-				data[count] = item;
-			++count;
-		}
-	}
-
-	// search in the db
-	if( count < size )
-	{
-		DBData *db_data[MAX_SEARCH];
-		int db_count = 0;
-		size -= count;
-		db_count = itemdb_other->getall(itemdb_other, (DBData**)&db_data, size, itemdb_searchname_array_sub, str);
-		for (i = 0; i < db_count; i++)
-			data[count++] = db_data2ptr(db_data[i]);
-		count += db_count;
-	}
 	return count;
 }
 
@@ -280,18 +247,12 @@ char itemdb_pc_get_itemgroup(uint16 group_id, struct map_session_data *sd) {
 	return 0;
 }
 
-/// Searches for the item_data.
-/// Returns the item_data or NULL if it does not exist.
-struct item_data* itemdb_exists(unsigned short nameid)
-{
-	struct item_data* item;
-
-	if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
-		return itemdb_array[nameid];
-	item = (struct item_data*)idb_get(itemdb_other,nameid);
-	if( item == &dummy_item )
-		return NULL;// dummy data, doesn't exist
-	return item;
+/** Searches for the item_data. Use this to check if item exists or not.
+* @param nameid
+* @return *item_data if item is exist, or NULL if not
+*/
+struct item_data* itemdb_exists(unsigned short nameid) {
+	return ((struct item_data*)idb_get(itemdb,nameid));
 }
 
 /// Returns name type of ammunition [Cydh]
@@ -405,70 +366,34 @@ static void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask)
 		bclass[1] |= 1<<MAPID_GUNSLINGER;
 }
 
+/**
+* Create dummy item data
+*/
 static void create_dummy_data(void)
 {
-	memset(&dummy_item, 0, sizeof(struct item_data));
-	dummy_item.nameid=500;
-	dummy_item.weight=1;
-	dummy_item.value_sell=1;
-	dummy_item.type=IT_ETC; //Etc item
-	safestrncpy(dummy_item.name,"UNKNOWN_ITEM",sizeof(dummy_item.name));
-	safestrncpy(dummy_item.jname,"UNKNOWN_ITEM",sizeof(dummy_item.jname));
-	dummy_item.view_id=UNKNOWN_ITEM_ID;
-}
-
-static struct item_data* create_item_data(unsigned short nameid)
-{
-	struct item_data *id;
-	CREATE(id, struct item_data, 1);
-	id->nameid = nameid;
-	id->weight = 1;
-	id->type = IT_ETC;
-	return id;
-}
-
-/*==========================================
- * Loads (and creates if not found) an item from the db.
- *------------------------------------------*/
-struct item_data* itemdb_load(unsigned short nameid)
-{
-	struct item_data *id;
-
-	if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
-	{
-		id = itemdb_array[nameid];
-		if( id == NULL || id == &dummy_item )
-			id = itemdb_array[nameid] = create_item_data(nameid);
-		return id;
-	}
-
-	id = (struct item_data*)idb_get(itemdb_other, nameid);
-	if( id == NULL || id == &dummy_item )
-	{
-		id = create_item_data(nameid);
-		idb_put(itemdb_other, nameid, id);
-	}
-	return id;
+	CREATE(dummy_item, struct item_data, 1);
+
+	memset(dummy_item, 0, sizeof(struct item_data));
+	dummy_item->nameid = 500;
+	dummy_item->weight = 1;
+	dummy_item->value_sell = 1;
+	dummy_item->type = IT_ETC; //Etc item
+	safestrncpy(dummy_item->name, "UNKNOWN_ITEM", sizeof(dummy_item->name));
+	safestrncpy(dummy_item->jname, "Unknown Item", sizeof(dummy_item->jname));
+	dummy_item->view_id = UNKNOWN_ITEM_ID;
 }
 
 /*==========================================
  * Loads an item from the db. If not found, it will return the dummy item.
+ * @param nameid
+ * @return *item_data or *dummy_item if item not found
  *------------------------------------------*/
-struct item_data* itemdb_search(unsigned short nameid)
-{
-	struct item_data* id;
-	if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
-		id = itemdb_array[nameid];
-	else
-		id = (struct item_data*)idb_get(itemdb_other, nameid);
-
-	if( id == NULL )
-	{
-		ShowWarning("itemdb_search: Item ID %hu does not exists in the item_db. Using dummy data.\n", nameid);
-		id = &dummy_item;
-		dummy_item.nameid = nameid;
-	}
-	return id;
+struct item_data* itemdb_search(unsigned short nameid) {
+	struct item_data* id = (struct item_data*)idb_get(itemdb, nameid);
+	if (id)
+		return id;
+	ShowWarning("itemdb_search: Item ID %hu does not exists in the item_db. Using dummy data.\n", nameid);
+	return dummy_item;
 }
 
 /** Checks if item is equip type or not
@@ -692,11 +617,16 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
 
 		// Checking item
 		trim(str[1]);
-		if (ISDIGIT(str[1][0]) && itemdb_exists((nameid = atoi(str[1]))))
-			found = true;
-		else if (itemdb_searchname(str[1])) {
-			found = true;
-			nameid = itemdb_searchname(str[1])->nameid;
+		if (ISDIGIT(str[1][0])) {
+			if (itemdb_exists((nameid = atoi(str[1]))))
+				found = true;
+		}
+		else {
+			struct item_data *id = itemdb_searchname(str[1]);
+			if (id) {
+				nameid = id->nameid;
+				found = true;
+			}
 		}
 		if (!found) {
 			ShowWarning("itemdb_read_itemgroup: Non-existant item '%s' in %s:%d\n", str[1], filename, ln);
@@ -1190,15 +1120,17 @@ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scr
 	unsigned short nameid;
 	struct item_data* id;
 
-	nameid = atoi(str[0]);
-	if( nameid <= 0 )
+	if( atoi(str[0]) <= 0 || atoi(str[0]) >= MAX_ITEMID )
 	{
-		ShowWarning("itemdb_parse_dbrow: Invalid id %hu in line %d of \"%s\", skipping.\n", nameid, line, source);
+		ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", atoi(str[0]), line, source);
 		return false;
 	}
+	nameid = atoi(str[0]);
 
 	//ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View
-	id = itemdb_load(nameid);
+	if (!(id = itemdb_exists(nameid)))
+		CREATE(id, struct item_data, 1);
+
 	safestrncpy(id->name, str[1], sizeof(id->name));
 	safestrncpy(id->jname, str[2], sizeof(id->jname));
 
@@ -1306,6 +1238,10 @@ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scr
 	if (*str[21])
 		id->unequip_script = parse_script(str[21], source, line, scriptopt);
 
+	if (!id->nameid) {
+		id->nameid = nameid;
+		idb_put(itemdb, nameid, id);
+	}
 	return true;
 }
 
@@ -1609,7 +1545,7 @@ static void itemdb_read(void) {
 /**
 * Destroys the item_data.
 */
-static void destroy_item_data(struct item_data* self, bool free_self) {
+static void destroy_item_data(struct item_data* self) {
 	if( self == NULL )
 		return;
 	// free scripts
@@ -1636,8 +1572,7 @@ static void destroy_item_data(struct item_data* self, bool free_self) {
 	memset(self, 0xDD, sizeof(struct item_data));
 #endif
 	// free self
-	if( free_self )
-		aFree(self);
+	aFree(self);
 }
 
 /**
@@ -1647,9 +1582,7 @@ static int itemdb_final_sub(DBKey key, DBData *data, va_list ap)
 {
 	struct item_data *id = db_data2ptr(data);
 
-	if( id != &dummy_item )
-		destroy_item_data(id, true);
-
+	destroy_item_data(id);
 	return 0;
 }
 
@@ -1680,18 +1613,10 @@ void itemdb_reload(void) {
 
 	int i,d,k;
 
-	// clear the previous itemdb data
-	for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) {
-		if( itemdb_array[i] )
-			destroy_item_data(itemdb_array[i], true);
-	}
-
 	itemdb_group->clear(itemdb_group, itemdb_group_free);
-	itemdb_other->clear(itemdb_other, itemdb_final_sub);
+	itemdb->clear(itemdb, itemdb_final_sub);
 	db_clear(itemdb_combo);
 
-	memset(itemdb_array, 0, sizeof(itemdb_array));
-
 	// read new data
 	itemdb_read();
 	cashshop_reloaddb();
@@ -1749,15 +1674,9 @@ void itemdb_reload(void) {
 * Finalizing Item DB
 */
 void do_final_itemdb(void) {
-	int i;
-
-	for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
-		if( itemdb_array[i] )
-			destroy_item_data(itemdb_array[i], true);
-	
 	itemdb_group->destroy(itemdb_group, itemdb_group_free);
-	itemdb_other->destroy(itemdb_other, itemdb_final_sub);
-	destroy_item_data(&dummy_item, false);
+	itemdb->destroy(itemdb, itemdb_final_sub);
+	destroy_item_data(dummy_item);
 	db_destroy(itemdb_combo);
 }
 
@@ -1765,8 +1684,7 @@ void do_final_itemdb(void) {
 * Initializing Item DB
 */
 void do_init_itemdb(void) {
-	memset(itemdb_array, 0, sizeof(itemdb_array));
-	itemdb_other = idb_alloc(DB_OPT_BASE);
+	itemdb = idb_alloc(DB_OPT_BASE);
 	itemdb_combo = idb_alloc(DB_OPT_BASE);
 	itemdb_group = idb_alloc(DB_OPT_BASE);
 	create_dummy_data(); //Dummy data item.

+ 2 - 3
src/map/itemdb.h

@@ -8,8 +8,8 @@
 #include "../common/mmo.h" // ITEM_NAME_LENGTH
 #include "map.h"
 
-/// 65,535 entries in array (the rest goes to the db)
-#define MAX_ITEMDB 0x10000
+///Maximum allowed Item ID (range: 1 ~ 65,534)
+#define MAX_ITEMID USHRT_MAX
 ///Use apple for unknown items.
 #define UNKNOWN_ITEM_ID 512
 /// The maximum number of item delays
@@ -418,7 +418,6 @@ struct item_data {
 
 struct item_data* itemdb_searchname(const char *name);
 int itemdb_searchname_array(struct item_data** data, int size, const char *str);
-struct item_data* itemdb_load(unsigned short nameid);
 struct item_data* itemdb_search(unsigned short nameid);
 struct item_data* itemdb_exists(unsigned short nameid);
 #define itemdb_name(n) itemdb_search(n)->name

+ 1 - 1
src/map/log.c

@@ -319,7 +319,7 @@ void log_mvpdrop(struct map_session_data* sd, int monster_id, unsigned int* log_
 			return;
 		time(&curtime);
 		strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime));
-		fprintf(logfp,"%s - %s[%d:%d]\t%d\t%hu,%d\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1]);
+		fprintf(logfp,"%s - %s[%d:%d]\t%d\t%hu,%u\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, (unsigned short)log_mvp[0], log_mvp[1]);
 		fclose(logfp);
 	}
 }

+ 34 - 33
src/map/mob.c

@@ -67,11 +67,12 @@ struct mob_chat *mob_chat(short id) { if(id<=0 || id>MAX_MOB_CHAT || mob_chat_db
 
 //Dynamic item drop ratio database for per-item drop ratio modifiers overriding global drop ratios.
 #define MAX_ITEMRATIO_MOBS 10
-struct item_drop_ratio {
+struct s_mob_item_drop_ratio {
+	unsigned short nameid;
 	int drop_ratio;
-	int mob_id[MAX_ITEMRATIO_MOBS];
+	unsigned short mob_id[MAX_ITEMRATIO_MOBS];
 };
-static struct item_drop_ratio *item_drop_ratio_db[MAX_ITEMDB];
+static DBMap *mob_item_drop_ratio;
 
 static struct eri *item_drop_ers; //For loot drops delay structures.
 static struct eri *item_drop_list_ers;
@@ -1643,7 +1644,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 		else { // Attack once and find a new random target
 			int search_size = (view_range < md->status.rhw.range) ? view_range : md->status.rhw.range;
 			unit_attack(&md->bl, tbl->id, 0);
-			if (tbl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), search_size)) {
+			if ((tbl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), search_size))) {
 				md->target_id = tbl->id;
 				md->min_chase = md->db->range3;
 			}
@@ -3671,15 +3672,16 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor
  */
 static void item_dropratio_adjust(unsigned short nameid, int mob_id, int *rate_adjust)
 {
-	if( item_drop_ratio_db[nameid] ) {
-		if( item_drop_ratio_db[nameid]->mob_id[0] ) { // only for listed mobs
+	struct s_mob_item_drop_ratio *item_ratio = (struct s_mob_item_drop_ratio *)idb_get(mob_item_drop_ratio, nameid);
+	if( item_ratio) {
+		if( item_ratio->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, item_ratio->mob_id[i] == mob_id);
+			if( i < MAX_ITEMRATIO_MOBS ) // found
+				*rate_adjust = item_ratio->drop_ratio;
 		}
 		else // for all mobs
-			*rate_adjust = item_drop_ratio_db[nameid]->drop_ratio;
+			*rate_adjust = item_ratio->drop_ratio;
 	}
 }
 
@@ -4532,26 +4534,36 @@ static bool mob_readdb_itemratio(char* str[], int columns, int current)
 {
 	unsigned short nameid;
 	int ratio, i;
+	struct s_mob_item_drop_ratio *item_ratio;
 	nameid = atoi(str[0]);
 
-	if( itemdb_exists(nameid) == NULL )
-	{
+	if (itemdb_exists(nameid) == NULL) {
 		ShowWarning("itemdb_read_itemratio: Invalid item id %hu.\n", nameid);
 		return false;
 	}
 
 	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));
+	if (!(item_ratio = (struct s_mob_item_drop_ratio *)idb_get(mob_item_drop_ratio,nameid)))
+		CREATE(item_ratio, struct s_mob_item_drop_ratio, 1);
 
-	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]);
+	item_ratio->drop_ratio = ratio;
+	memset(item_ratio->mob_id, 0, sizeof(item_ratio->mob_id));
+	for (i = 0; i < columns-2; i++)
+		item_ratio->mob_id[i] = atoi(str[i+2]);
+
+	if (!item_ratio->nameid)
+		idb_put(mob_item_drop_ratio, nameid, item_ratio);
 
 	return true;
 }
 
+static int mob_item_drop_ratio_free(DBKey key, DBData *data, va_list ap) {
+	struct s_mob_item_drop_ratio *item_ratio = db_data2ptr(data);
+	aFree(item_ratio);
+	return 0;
+}
+
 /**
  * read all mob-related databases
  */
@@ -4602,19 +4614,15 @@ void mob_reload(void) {
 	int i;
 
 	//Mob skills need to be cleared before re-reading them. [Skotlex]
-	for (i = 0; i < MAX_MOB_DB; i++)
+	for (i = 0; i < MAX_MOB_DB; i++) {
 		if (mob_db_data[i]) {
 			memset(&mob_db_data[i]->skill,0,sizeof(mob_db_data[i]->skill));
 			mob_db_data[i]->maxskill=0;
 		}
+	}
 
 	// Clear item_drop_ratio_db
-	for (i = 0; i < MAX_ITEMDB; i++) {
-		if (item_drop_ratio_db[i]) {
-			aFree(item_drop_ratio_db[i]);
-			item_drop_ratio_db[i] = NULL;
-		}
-	}
+	mob_item_drop_ratio->clear(mob_item_drop_ratio, mob_item_drop_ratio_free);
 
 	mob_load();
 }
@@ -4636,7 +4644,7 @@ void do_init_mob(void){
 	mob_makedummymobdb(0); //The first time this is invoked, it creates the dummy mob
 	item_drop_ers = ers_new(sizeof(struct item_drop),"mob.c::item_drop_ers",ERS_OPT_NONE);
 	item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"mob.c::item_drop_list_ers",ERS_OPT_NONE);
-
+	mob_item_drop_ratio = idb_alloc(DB_OPT_BASE);
 	mob_load();
 
 	add_timer_func_list(mob_delayspawn,"mob_delayspawn");
@@ -4676,14 +4684,7 @@ void do_final_mob(void){
 			mob_chat_db[i] = NULL;
 		}
 	}
-	for (i = 0; i < MAX_ITEMDB; i++)
-	{
-		if (item_drop_ratio_db[i] != NULL)
-		{
-			aFree(item_drop_ratio_db[i]);
-			item_drop_ratio_db[i] = NULL;
-		}
-	}
+	mob_item_drop_ratio->destroy(mob_item_drop_ratio,mob_item_drop_ratio_free);
 	ers_destroy(item_drop_ers);
 	ers_destroy(item_drop_list_ers);
 }