// $Id: itemdb.c,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $ #include #include #include #include "../common/db.hpp" #include "../common/grfio.hpp" #include "../common/nullpo.hpp" #include "map.hpp" #include "battle.hpp" #include "itemdb.hpp" #include "script.hpp" #include "pc.hpp" #include "../common/socket.hpp" #include "../common/mt_rand.hpp" #ifdef MEMWATCH #include "memwatch.hpp" #endif #define MAX_RANDITEM 2000 // ** ITEMDB_OVERRIDE_NAME_VERBOSE ** // 定義すると、itemdb.txtとgrfで名前が異なる場合、表示します. //#define ITEMDB_OVERRIDE_NAME_VERBOSE 1 static struct dbt *item_db; static struct random_item_data blue_box[MAX_RANDITEM], violet_box[MAX_RANDITEM], card_album[MAX_RANDITEM], gift_box[MAX_RANDITEM], scroll[MAX_RANDITEM]; static int blue_box_count = 0, violet_box_count = 0, card_album_count = 0, gift_box_count = 0, scroll_count = 0; static int blue_box_default = 0, violet_box_default = 0, card_album_default = 0, gift_box_default = 0, scroll_default = 0; // Function declarations static void itemdb_read (void); static int itemdb_readdb (void); static int itemdb_read_randomitem (void); static int itemdb_read_itemavail (void); static int itemdb_read_itemnametable (void); static int itemdb_read_noequip (void); /*========================================== * 名前で検索用 *------------------------------------------ */ // name = item alias, so we should find items aliases first. if not found then look for "jname" (full name) static void itemdb_searchname_sub (db_key_t key, db_val_t data, va_list ap) { struct item_data *item = (struct item_data *) data, **dst; char *str; str = va_arg (ap, char *); dst = va_arg (ap, struct item_data **); // if( strcasecmp(item->name,str)==0 || strcmp(item->jname,str)==0 || // memcmp(item->name,str,24)==0 || memcmp(item->jname,str,24)==0 ) if (strcasecmp (item->name, str) == 0) //by lupus *dst = item; } /*========================================== * 名前で検索用 *------------------------------------------ */ static int itemdb_searchjname_sub (void *key, void *data, va_list ap) { struct item_data *item = (struct item_data *) data, **dst; char *str; str = va_arg (ap, char *); dst = va_arg (ap, struct item_data **); if (strcasecmp (item->jname, str) == 0) *dst = item; return 0; } /*========================================== * 名前で検索 *------------------------------------------ */ struct item_data *itemdb_searchname (const char *str) { struct item_data *item = NULL; numdb_foreach (item_db, itemdb_searchname_sub, str, &item); return item; } /*========================================== * 箱系アイテム検索 *------------------------------------------ */ int itemdb_searchrandomid (int flags) { int nameid = 0, i, index, count; struct random_item_data *list = NULL; struct { int nameid, count; struct random_item_data *list; } data[] = { { 0, 0, NULL}, { blue_box_default, blue_box_count, blue_box}, { violet_box_default, violet_box_count, violet_box}, { card_album_default, card_album_count, card_album}, { gift_box_default, gift_box_count, gift_box}, { scroll_default, scroll_count, scroll},}; if (flags >= 1 && flags <= 5) { nameid = data[flags].nameid; count = data[flags].count; list = data[flags].list; if (count > 0) { for (i = 0; i < 1000; i++) { index = MRAND (count); if (MRAND (1000000) < list[index].per) { nameid = list[index].nameid; break; } } } } return nameid; } /*========================================== * DBの存在確認 *------------------------------------------ */ struct item_data *itemdb_exists (int nameid) { return (struct item_data *)numdb_search (item_db, nameid); } /*========================================== * DBの検索 *------------------------------------------ */ struct item_data *itemdb_search (int nameid) { struct item_data *id = (struct item_data *)numdb_search (item_db, nameid); if (id) return id; id = (struct item_data *) calloc (1, sizeof (struct item_data)); numdb_insert (item_db, nameid, id); id->nameid = nameid; id->value_buy = 10; id->value_sell = id->value_buy / 2; id->weight = 10; id->sex = 2; id->elv = 0; id->flag.available = 0; id->flag.value_notdc = 0; //一応・・・ id->flag.value_notoc = 0; id->flag.no_equip = 0; id->view_id = 0; if (nameid > 500 && nameid < 600) id->type = 0; //heal item else if (nameid > 600 && nameid < 700) id->type = 2; //use item else if ((nameid > 700 && nameid < 1100) || (nameid > 7000 && nameid < 8000)) id->type = 3; //correction else if (nameid >= 1750 && nameid < 1771) id->type = 10; //arrow else if (nameid > 1100 && nameid < 2000) id->type = 4; //weapon else if ((nameid > 2100 && nameid < 3000) || (nameid > 5000 && nameid < 6000)) id->type = 5; //armor else if (nameid > 4000 && nameid < 5000) id->type = 6; //card return id; } /*========================================== * *------------------------------------------ */ int itemdb_isequip (int nameid) { int type = itemdb_type (nameid); if (type == 0 || type == 2 || type == 3 || type == 6 || type == 10) return 0; return 1; } /*========================================== * *------------------------------------------ */ int itemdb_isequip2 (struct item_data *data) { if (data) { int type = data->type; if (type == 0 || type == 2 || type == 3 || type == 6 || type == 10) return 0; else return 1; } return 0; } /*========================================== * *------------------------------------------ */ int itemdb_isequip3 (int nameid) { int type = itemdb_type (nameid); if (type == 4 || type == 5 || type == 8) return 1; return 0; } /*========================================== * 捨てられるアイテムは1、そうでないアイテムは0 *------------------------------------------ */ int itemdb_isdropable (int nameid) { //結婚指輪は捨てられない switch (nameid) { case 2634: //結婚指輪 case 2635: //結婚指輪 return 0; } return 1; } // // 初期化 // /*========================================== * *------------------------------------------ */ static int itemdb_read_itemslottable (void) { char *buf, *p; size_t s; buf = (char *)grfio_reads ("data\\itemslottable.txt", &s); if (buf == NULL) return -1; buf[s] = 0; for (p = buf; p - buf < s;) { int nameid, equip; sscanf (p, "%d#%d#", &nameid, &equip); itemdb_search (nameid)->equip = equip; p = strchr (p, 10); if (!p) break; p++; p = strchr (p, 10); if (!p) break; p++; } free (buf); return 0; } /*========================================== * アイテムデータベースの読み込み *------------------------------------------ */ static int itemdb_readdb (void) { FILE *fp; char line[1024]; int ln = 0, lines = 0; int nameid, j; char *str[32], *p, *np; struct item_data *id; int i = 0; const char *filename[] = { "db/item_db.txt", "db/item_db2.txt" }; for (i = 0; i < 2; i++) { fp = fopen_ (filename[i], "r"); if (fp == NULL) { if (i > 0) continue; printf ("can't read %s\n", filename[i]); exit (1); } lines = 0; while (fgets (line, 1020, fp)) { lines++; if (line[0] == '/' && line[1] == '/') continue; memset (str, 0, sizeof (str)); for (j = 0, np = p = line; j < 17 && p; j++) { while (*p == '\t' || *p == ' ') p++; str[j] = p; p = strchr (p, ','); if (p) { *p++ = 0; np = p; } } if (str[0] == NULL) continue; nameid = atoi (str[0]); if (nameid <= 0 || nameid >= 20000) continue; ln++; //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Gender,Loc,wLV,eLV,View id = itemdb_search (nameid); memcpy (id->name, str[1], 24); memcpy (id->jname, str[2], 24); id->type = atoi (str[3]); id->value_buy = atoi (str[4]); id->value_sell = atoi (str[5]); if (id->value_buy == 0 && id->value_sell == 0) { } else if (id->value_buy == 0) { id->value_buy = id->value_sell * 2; } else if (id->value_sell == 0) { id->value_sell = id->value_buy / 2; } id->weight = atoi (str[6]); id->atk = atoi (str[7]); id->def = atoi (str[8]); id->range = atoi (str[9]); id->magic_bonus = atoi (str[10]); id->slot = atoi (str[11]); id->sex = atoi (str[12]); id->equip = atoi (str[13]); id->wlv = atoi (str[14]); id->elv = atoi (str[15]); id->look = atoi (str[16]); id->flag.available = 1; id->flag.value_notdc = 0; id->flag.value_notoc = 0; id->view_id = 0; id->use_script = NULL; id->equip_script = NULL; if ((p = strchr (np, '{')) == NULL) continue; id->use_script = parse_script (p, lines); if ((p = strchr (p + 1, '{')) == NULL) continue; id->equip_script = parse_script (p, lines); } fclose_ (fp); printf ("read %s done (count=%d)\n", filename[i], ln); } return 0; } // Removed item_value_db, don't re-add! /*========================================== * ランダムアイテム出現データの読み込み *------------------------------------------ */ static int itemdb_read_randomitem (void) { FILE *fp; char line[1024]; int ln = 0; int nameid, i, j; char *str[10], *p; const struct { char filename[64]; struct random_item_data *pdata; int *pcount, *pdefault; } data[] = { { "db/item_bluebox.txt", blue_box, &blue_box_count, &blue_box_default}, { "db/item_violetbox.txt", violet_box, &violet_box_count, &violet_box_default}, { "db/item_cardalbum.txt", card_album, &card_album_count, &card_album_default}, { "db/item_giftbox.txt", gift_box, &gift_box_count, &gift_box_default}, { "db/item_scroll.txt", scroll, &scroll_count, &scroll_default},}; for (i = 0; i < sizeof (data) / sizeof (data[0]); i++) { struct random_item_data *pd = data[i].pdata; int *pc = data[i].pcount; int *pdefault = data[i].pdefault; const char *fn = data[i].filename; *pdefault = 0; if ((fp = fopen_ (fn, "r")) == NULL) { printf ("can't read %s\n", fn); continue; } while (fgets (line, 1020, fp)) { if (line[0] == '/' && line[1] == '/') continue; memset (str, 0, sizeof (str)); for (j = 0, p = line; j < 3 && p; j++) { str[j] = p; p = strchr (p, ','); if (p) *p++ = 0; } if (str[0] == NULL) continue; nameid = atoi (str[0]); if (nameid < 0 || nameid >= 20000) continue; if (nameid == 0) { if (str[2]) *pdefault = atoi (str[2]); continue; } if (str[2]) { pd[*pc].nameid = nameid; pd[(*pc)++].per = atoi (str[2]); } if (ln >= MAX_RANDITEM) break; ln++; } fclose_ (fp); printf ("read %s done (count=%d)\n", fn, *pc); } return 0; } /*========================================== * アイテム使用可能フラグのオーバーライド *------------------------------------------ */ static int itemdb_read_itemavail (void) { FILE *fp; char line[1024]; int ln = 0; int nameid, j, k; char *str[10], *p; if ((fp = fopen_ ("db/item_avail.txt", "r")) == NULL) { printf ("can't read db/item_avail.txt\n"); return -1; } while (fgets (line, 1020, fp)) { struct item_data *id; if (line[0] == '/' && line[1] == '/') continue; memset (str, 0, sizeof (str)); for (j = 0, p = line; j < 2 && p; j++) { str[j] = p; p = strchr (p, ','); if (p) *p++ = 0; } if (str[0] == NULL) continue; nameid = atoi (str[0]); if (nameid < 0 || nameid >= 20000 || !(id = itemdb_exists (nameid))) continue; k = atoi (str[1]); if (k > 0) { id->flag.available = 1; id->view_id = k; } else id->flag.available = 0; ln++; } fclose_ (fp); printf ("read db/item_avail.txt done (count=%d)\n", ln); return 0; } /*========================================== * アイテムの名前テーブルを読み込む *------------------------------------------ */ static int itemdb_read_itemnametable (void) { char *buf, *p; size_t s; buf = (char *)grfio_reads ("data\\idnum2itemdisplaynametable.txt", &s); if (buf == NULL) return -1; buf[s] = 0; for (p = buf; p - buf < s;) { int nameid; char buf2[64]; if (sscanf (p, "%d#%[^#]#", &nameid, buf2) == 2) { #ifdef ITEMDB_OVERRIDE_NAME_VERBOSE if (itemdb_exists (nameid) && strncmp (itemdb_search (nameid)->jname, buf2, 24) != 0) { printf ("[override] %d %s => %s\n", nameid, itemdb_search (nameid)->jname, buf2); } #endif memcpy (itemdb_search (nameid)->jname, buf2, 24); } p = strchr (p, 10); if (!p) break; p++; } free (buf); printf ("read data\\idnum2itemdisplaynametable.txt done.\n"); return 0; } /*========================================== * カードイラストのリソース名前テーブルを読み込む *------------------------------------------ */ static int itemdb_read_cardillustnametable (void) { char *buf, *p; size_t s; buf = (char *)grfio_reads ("data\\num2cardillustnametable.txt", &s); if (buf == NULL) return -1; buf[s] = 0; for (p = buf; p - buf < s;) { int nameid; char buf2[64]; if (sscanf (p, "%d#%[^#]#", &nameid, buf2) == 2) { strcat (buf2, ".bmp"); memcpy (itemdb_search (nameid)->cardillustname, buf2, 64); // printf("%d %s\n",nameid,itemdb_search(nameid)->cardillustname); } p = strchr (p, 10); if (!p) break; p++; } free (buf); printf ("read data\\num2cardillustnametable.txt done.\n"); return 0; } /*========================================== * 装備制限ファイル読み出し *------------------------------------------ */ static int itemdb_read_noequip (void) { FILE *fp; char line[1024]; int ln = 0; int nameid, j; char *str[32], *p; struct item_data *id; if ((fp = fopen_ ("db/item_noequip.txt", "r")) == NULL) { printf ("can't read db/item_noequip.txt\n"); return -1; } while (fgets (line, 1020, fp)) { if (line[0] == '/' && line[1] == '/') continue; memset (str, 0, sizeof (str)); for (j = 0, p = line; j < 2 && p; j++) { str[j] = p; p = strchr (p, ','); if (p) *p++ = 0; } if (str[0] == NULL) continue; nameid = atoi (str[0]); if (nameid <= 0 || nameid >= 20000 || !(id = itemdb_exists (nameid))) continue; id->flag.no_equip = atoi (str[1]); ln++; } fclose_ (fp); printf ("read db/item_noequip.txt done (count=%d)\n", ln); return 0; } /*========================================== * *------------------------------------------ */ static void itemdb_final (db_key_t key, db_val_t data, va_list ap) { struct item_data *id; nullpo_retv (id = (struct item_data *)data); if (id->use_script) free (const_cast(id->use_script)); if (id->equip_script) free (const_cast(id->equip_script)); free (id); } void itemdb_reload (void) { /* * * * itemdb_read(); * */ do_init_itemdb (); } /*========================================== * *------------------------------------------ */ void do_final_itemdb (void) { if (item_db) { numdb_final (item_db, itemdb_final); item_db = NULL; } } /* static FILE *dfp; static int itemdebug(void *key,void *data,va_list ap){ // struct item_data *id=(struct item_data *)data; fprintf(dfp,"%6d",(int)key); return 0; } void itemdebugtxt() { dfp=fopen_("itemdebug.txt","wt"); numdb_foreach(item_db,itemdebug); fclose_(dfp); } */ /*==================================== * Removed item_value_db, don't re-add *------------------------------------ */ static void itemdb_read (void) { itemdb_read_itemslottable (); itemdb_readdb (); itemdb_read_randomitem (); itemdb_read_itemavail (); itemdb_read_noequip (); itemdb_read_cardillustnametable (); if (!battle_config.item_name_override_grffile) itemdb_read_itemnametable (); } /*========================================== * *------------------------------------------ */ int do_init_itemdb (void) { item_db = numdb_init (); itemdb_read (); return 0; }