// $Id: itemdb.c,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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<ScriptCode *>(id->use_script));
if (id->equip_script)
free (const_cast<ScriptCode *>(id->equip_script));
free (id);
}
void itemdb_reload (void)
{
/*
*
* <empty item databases>
* 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;
}