* 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>
This commit is contained in:
Cydh Ramdh 2014-06-20 19:13:45 +07:00
parent 0fca530278
commit 6c5d4a730f
8 changed files with 128 additions and 211 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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;
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<<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;
}
CREATE(dummy_item, struct item_data, 1);
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;
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.

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}