diff --git a/conf/msg_conf/map_msg.conf b/conf/msg_conf/map_msg.conf index ed1ee69b3a..a42925ea38 100644 --- a/conf/msg_conf/map_msg.conf +++ b/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. diff --git a/conf/msg_conf/map_msg_idn.conf b/conf/msg_conf/map_msg_idn.conf index 0cc846325f..7332aebbed 100644 --- a/conf/msg_conf/map_msg_idn.conf +++ b/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. diff --git a/db/import-tmpl/mob_item_ratio.txt b/db/import-tmpl/mob_item_ratio.txt index 8f8c4e52be..d085939c5b 100644 --- a/db/import-tmpl/mob_item_ratio.txt +++ b/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. - diff --git a/db/mob_item_ratio.txt b/db/mob_item_ratio.txt index 226460a86a..d085939c5b 100644 --- a/db/mob_item_ratio.txt +++ b/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 diff --git a/src/map/itemdb.c b/src/map/itemdb.c index b4578fbae3..8724b17709 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -18,12 +18,11 @@ #include #include -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; + struct item_data* item = NULL; + struct item_data* item2 = NULL; - 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; - } - - 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<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; + 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. diff --git a/src/map/itemdb.h b/src/map/itemdb.h index f2f41fbd1f..b9ad613ee1 100644 --- a/src/map/itemdb.h +++ b/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 diff --git a/src/map/log.c b/src/map/log.c index edac5802d1..3e2da2d85f 100644 --- a/src/map/log.c +++ b/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); } } diff --git a/src/map/mob.c b/src/map/mob.c index 070fe60e31..b3169b48de 100644 --- a/src/map/mob.c +++ b/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); }