itemdb.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "../common/nullpo.h"
  7. #include "../common/malloc.h"
  8. #include "../common/showmsg.h"
  9. #include "../common/grfio.h"
  10. #include "../common/strlib.h"
  11. #include "map.h"
  12. #include "battle.h"
  13. #include "itemdb.h"
  14. #include "script.h"
  15. #include "pc.h"
  16. // ** ITEMDB_OVERRIDE_NAME_VERBOSE **
  17. // 定義すると、itemdb.txtとgrfで名前が異なる場合、表示します.
  18. //#define ITEMDB_OVERRIDE_NAME_VERBOSE 1
  19. static struct dbt* item_db;
  20. static struct item_group itemgroup_db[MAX_ITEMGROUP];
  21. struct item_data *dummy_item=NULL; //This is the default dummy item used for non-existant items. [Skotlex]
  22. /*==========================================
  23. * 名前で検索用
  24. *------------------------------------------
  25. */
  26. // name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
  27. int itemdb_searchname_sub(DBKey key,void *data,va_list ap)
  28. {
  29. struct item_data *item=(struct item_data *)data,**dst;
  30. char *str;
  31. str=va_arg(ap,char *);
  32. dst=va_arg(ap,struct item_data **);
  33. if(item == dummy_item) return 0;
  34. if( strcmpi(item->name,str)==0 ) //by lupus
  35. *dst=item;
  36. return 0;
  37. }
  38. /*==========================================
  39. * 名前で検索用
  40. *------------------------------------------
  41. */
  42. int itemdb_searchjname_sub(int key,void *data,va_list ap)
  43. {
  44. struct item_data *item=(struct item_data *)data,**dst;
  45. char *str;
  46. str=va_arg(ap,char *);
  47. dst=va_arg(ap,struct item_data **);
  48. if( strcmpi(item->jname,str)==0 )
  49. *dst=item;
  50. return 0;
  51. }
  52. /*==========================================
  53. * 名前で検索
  54. *------------------------------------------
  55. */
  56. struct item_data* itemdb_searchname(const char *str)
  57. {
  58. struct item_data *item=NULL;
  59. item_db->foreach(item_db,itemdb_searchname_sub,str,&item);
  60. return item;
  61. }
  62. static int itemdb_searchname_array_sub(DBKey key,void * data,va_list ap)
  63. {
  64. struct item_data *item=(struct item_data *)data;
  65. char *str;
  66. str=va_arg(ap,char *);
  67. if (item == dummy_item)
  68. return 1; //Invalid item.
  69. if(stristr(item->jname,str))
  70. return 0;
  71. if(stristr(item->name,str))
  72. return 0;
  73. return strcmpi(item->jname,str);
  74. }
  75. /*==========================================
  76. * Founds up to N matches. Returns number of matches [Skotlex]
  77. *------------------------------------------
  78. */
  79. int itemdb_searchname_array(struct item_data** data, int size, const char *str)
  80. {
  81. return item_db->getall(item_db,(void**)data,size,itemdb_searchname_array_sub,str);
  82. }
  83. /*==========================================
  84. * 箱系アイテム検索
  85. *------------------------------------------
  86. */
  87. int itemdb_searchrandomid(int group)
  88. {
  89. if(group<1 || group>=MAX_ITEMGROUP) {
  90. if (battle_config.error_log)
  91. ShowError("itemdb_searchrandomid: Invalid group id %d\n", group);
  92. return 512; //Return apple?
  93. }
  94. if (itemgroup_db[group].qty)
  95. return itemgroup_db[group].nameid[rand()%itemgroup_db[group].qty];
  96. if (battle_config.error_log)
  97. ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group);
  98. return 512;
  99. }
  100. /*==========================================
  101. *
  102. *------------------------------------------
  103. */
  104. int itemdb_group (int nameid)
  105. {
  106. int i, j;
  107. for (i=0; i < MAX_ITEMGROUP; i++) {
  108. for (j=0; j < itemgroup_db[i].qty; j++) {
  109. if (itemgroup_db[i].id[j] == nameid)
  110. return i;
  111. }
  112. }
  113. return -1;
  114. }
  115. /*==========================================
  116. * DBの存在確認
  117. *------------------------------------------
  118. */
  119. struct item_data* itemdb_exists(int nameid)
  120. {
  121. struct item_data* id = idb_get(item_db,nameid);
  122. if (id == dummy_item) return NULL;
  123. return id;
  124. }
  125. /*==========================================
  126. * Converts the jobid from the format in itemdb
  127. * to the format used by the map server. [Skotlex]
  128. *------------------------------------------
  129. */
  130. static void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask)
  131. {
  132. int i;
  133. bclass[0]= bclass[1]= bclass[2]= 0;
  134. //Base classes
  135. if (jobmask & 1<<JOB_NOVICE)
  136. { //Both Novice/Super-Novice are counted with the same ID
  137. bclass[0] |= 1<<MAPID_NOVICE;
  138. bclass[1] |= 1<<MAPID_NOVICE;
  139. }
  140. for (i = JOB_NOVICE+1; i <= JOB_THIEF; i++)
  141. {
  142. if (jobmask & 1<<i)
  143. bclass[0] |= 1<<(MAPID_NOVICE+i);
  144. }
  145. //2-1 classes
  146. if (jobmask & 1<<JOB_KNIGHT)
  147. bclass[1] |= 1<<MAPID_SWORDMAN;
  148. if (jobmask & 1<<JOB_PRIEST)
  149. bclass[1] |= 1<<MAPID_ACOLYTE;
  150. if (jobmask & 1<<JOB_WIZARD)
  151. bclass[1] |= 1<<MAPID_MAGE;
  152. if (jobmask & 1<<JOB_BLACKSMITH)
  153. bclass[1] |= 1<<MAPID_MERCHANT;
  154. if (jobmask & 1<<JOB_HUNTER)
  155. bclass[1] |= 1<<MAPID_ARCHER;
  156. if (jobmask & 1<<JOB_ASSASSIN)
  157. bclass[1] |= 1<<MAPID_THIEF;
  158. //2-2 classes
  159. if (jobmask & 1<<JOB_CRUSADER)
  160. bclass[2] |= 1<<MAPID_SWORDMAN;
  161. if (jobmask & 1<<JOB_MONK)
  162. bclass[2] |= 1<<MAPID_ACOLYTE;
  163. if (jobmask & 1<<JOB_SAGE)
  164. bclass[2] |= 1<<MAPID_MAGE;
  165. if (jobmask & 1<<JOB_ALCHEMIST)
  166. bclass[2] |= 1<<MAPID_MERCHANT;
  167. if (jobmask & 1<<JOB_BARD)
  168. bclass[2] |= 1<<MAPID_ARCHER;
  169. if (jobmask & 1<<JOB_DANCER)
  170. bclass[2] |= 1<<MAPID_ARCHER;
  171. if (jobmask & 1<<JOB_ROGUE)
  172. bclass[2] |= 1<<MAPID_THIEF;
  173. //Special classes that don't fit above.
  174. if (jobmask & 1<<21) //Taekwon boy
  175. bclass[0] |= 1<<MAPID_TAEKWON;
  176. if (jobmask & 1<<22) //Star Gladiator
  177. bclass[1] |= 1<<MAPID_TAEKWON;
  178. if (jobmask & 1<<23) //Soul Linker
  179. bclass[2] |= 1<<MAPID_TAEKWON;
  180. if (jobmask & 1<<JOB_GUNSLINGER)
  181. bclass[0] |= 1<<MAPID_GUNSLINGER;
  182. if (jobmask & 1<<JOB_NINJA)
  183. bclass[0] |= 1<<MAPID_NINJA;
  184. }
  185. static void create_dummy_data(void) {
  186. if (dummy_item)
  187. aFree(dummy_item);
  188. dummy_item=(struct item_data *)aCalloc(1,sizeof(struct item_data));
  189. dummy_item->nameid=500;
  190. dummy_item->weight=1;
  191. dummy_item->type=3; //Etc item
  192. strncpy(dummy_item->name,"UNKNOWN_ITEM",ITEM_NAME_LENGTH-1);
  193. strncpy(dummy_item->jname,"UNKNOWN_ITEM",ITEM_NAME_LENGTH-1);
  194. dummy_item->view_id = 512; //Use apple sprite.
  195. }
  196. static void* create_item_data(DBKey key, va_list args) {
  197. struct item_data *id;
  198. id=(struct item_data *)aCalloc(1,sizeof(struct item_data));
  199. id->nameid = key.i;
  200. id->weight=1;
  201. id->type=3; //Etc item
  202. return id;
  203. }
  204. /*==========================================
  205. * Loads (and creates if not found) an item from the db.
  206. *------------------------------------------
  207. */
  208. struct item_data* itemdb_load(int nameid)
  209. {
  210. return idb_ensure(item_db,nameid,create_item_data);
  211. }
  212. static void* return_dummy_data(DBKey key, va_list args) {
  213. if (battle_config.error_log)
  214. ShowWarning("itemdb_search: Item ID %d does not exists in the item_db. Using dummy data.\n", key.i);
  215. return dummy_item;
  216. }
  217. /*==========================================
  218. * Loads an item from the db. If not found, it will return the dummy item.
  219. *------------------------------------------
  220. */
  221. struct item_data* itemdb_search(int nameid)
  222. {
  223. return idb_ensure(item_db,nameid,return_dummy_data);
  224. }
  225. /*==========================================
  226. *
  227. *------------------------------------------
  228. */
  229. int itemdb_isequip(int nameid)
  230. {
  231. int type=itemdb_type(nameid);
  232. if(type==0 || type==2 || type==3 || type==6 || type==10)
  233. return 0;
  234. return 1;
  235. }
  236. /*==========================================
  237. *
  238. *------------------------------------------
  239. */
  240. int itemdb_isequip2(struct item_data *data)
  241. {
  242. if(data) {
  243. int type=data->type;
  244. if(type==0 || type==2 || type==3 || type==6 || type==10)
  245. return 0;
  246. else
  247. return 1;
  248. }
  249. return 0;
  250. }
  251. /*==========================================
  252. * Trade Restriction functions [Skotlex]
  253. *------------------------------------------
  254. */
  255. int itemdb_isdropable(int nameid, int gmlv)
  256. {
  257. struct item_data* item = itemdb_exists(nameid);
  258. return (item && (!(item->flag.trade_restriction&1) || gmlv >= item->gm_lv_trade_override));
  259. }
  260. int itemdb_cantrade(int nameid, int gmlv, int gmlv2)
  261. {
  262. struct item_data* item = itemdb_exists(nameid);
  263. return (item && (!(item->flag.trade_restriction&2) || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
  264. }
  265. int itemdb_canpartnertrade(int nameid, int gmlv, int gmlv2)
  266. {
  267. struct item_data* item = itemdb_exists(nameid);
  268. return (item && (item->flag.trade_restriction&4 || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
  269. }
  270. int itemdb_cansell(int nameid, int gmlv)
  271. {
  272. struct item_data* item = itemdb_exists(nameid);
  273. return (item && (!(item->flag.trade_restriction&8) || gmlv >= item->gm_lv_trade_override));
  274. }
  275. int itemdb_cancartstore(int nameid, int gmlv)
  276. {
  277. struct item_data* item = itemdb_exists(nameid);
  278. return (item && (!(item->flag.trade_restriction&16) || gmlv >= item->gm_lv_trade_override));
  279. }
  280. int itemdb_canstore(int nameid, int gmlv)
  281. {
  282. struct item_data* item = itemdb_exists(nameid);
  283. return (item && (!(item->flag.trade_restriction&32) || gmlv >= item->gm_lv_trade_override));
  284. }
  285. int itemdb_canguildstore(int nameid, int gmlv)
  286. {
  287. struct item_data* item = itemdb_exists(nameid);
  288. return (item && (!(item->flag.trade_restriction&64) || gmlv >= item->gm_lv_trade_override));
  289. }
  290. /*==========================================
  291. *
  292. *------------------------------------------
  293. */
  294. int itemdb_isequip3(int nameid)
  295. {
  296. int type=itemdb_type(nameid);
  297. if(type==4 || type==5 || type == 8)
  298. return 1;
  299. return 0;
  300. }
  301. /*==========================================
  302. * アイテム使用可能フラグのオーバーライド
  303. *------------------------------------------
  304. */
  305. static int itemdb_read_itemavail (void)
  306. {
  307. FILE *fp;
  308. int nameid, j, k, ln = 0;
  309. char line[1024], *str[10], *p;
  310. struct item_data *id;
  311. sprintf(line, "%s/item_avail.txt", db_path);
  312. if ((fp = fopen(line,"r")) == NULL) {
  313. ShowError("can't read %s\n", line);
  314. return -1;
  315. }
  316. while (fgets(line, sizeof(line) - 1, fp)) {
  317. if (line[0] == '/' && line[1] == '/')
  318. continue;
  319. memset(str, 0, sizeof(str));
  320. for (j = 0, p = line; j < 2 && p; j++) {
  321. str[j] = p;
  322. p = strchr(p, ',');
  323. if(p) *p++ = 0;
  324. }
  325. if (j < 2 || str[0] == NULL ||
  326. (nameid = atoi(str[0])) < 0 || nameid >= 20000 || !(id = itemdb_exists(nameid)))
  327. continue;
  328. k = atoi(str[1]);
  329. if (k > 0) {
  330. id->flag.available = 1;
  331. id->view_id = k;
  332. } else
  333. id->flag.available = 0;
  334. ln++;
  335. }
  336. fclose(fp);
  337. ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, "item_avail.txt");
  338. return 0;
  339. }
  340. /*==========================================
  341. * read item group data
  342. *------------------------------------------
  343. */
  344. static void itemdb_read_itemgroup_sub(const char* filename)
  345. {
  346. FILE *fp;
  347. char line[1024];
  348. int ln=0;
  349. int groupid,j,k,nameid;
  350. char *str[3],*p;
  351. char w1[1024], w2[1024];
  352. if( (fp=fopen(filename,"r"))==NULL ){
  353. ShowError("can't read %s\n", line);
  354. return;
  355. }
  356. while(fgets(line,1020,fp)){
  357. ln++;
  358. if(line[0]=='/' && line[1]=='/')
  359. continue;
  360. if(strstr(line,"import")) {
  361. if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 &&
  362. strcmpi(w1, "import") == 0) {
  363. itemdb_read_itemgroup_sub(w2);
  364. continue;
  365. }
  366. }
  367. memset(str,0,sizeof(str));
  368. for(j=0,p=line;j<3 && p;j++){
  369. str[j]=p;
  370. p=strchr(p,',');
  371. if(p) *p++=0;
  372. }
  373. if(str[0]==NULL)
  374. continue;
  375. if (j<3)
  376. continue;
  377. groupid = atoi(str[0]);
  378. if (groupid < 0 || groupid >= MAX_ITEMGROUP) {
  379. ShowWarning("itemdb_read_itemgroup: Invalid group %d in %s:%d\n", groupid, filename, ln);
  380. continue;
  381. }
  382. nameid = atoi(str[1]);
  383. if (!itemdb_exists(nameid)) {
  384. ShowWarning("itemdb_read_itemgroup: Non-existant item %d in %s:%d\n", nameid, filename, ln);
  385. continue;
  386. }
  387. k = atoi(str[2]);
  388. if (itemgroup_db[groupid].qty+k > MAX_RANDITEM) {
  389. ShowWarning("itemdb_read_itemgroup: Group %d is full (%d entries) in %s:%d\n", groupid, MAX_RANDITEM, filename, ln);
  390. continue;
  391. }
  392. for(j=0;j<k;j++)
  393. itemgroup_db[groupid].nameid[itemgroup_db[groupid].qty++] = nameid;
  394. }
  395. fclose(fp);
  396. return;
  397. }
  398. static void itemdb_read_itemgroup(void)
  399. {
  400. char path[256];
  401. int i;
  402. const char* groups[] = {
  403. "Blue Box",
  404. "Violet Box",
  405. "Card Album",
  406. "Gift Box",
  407. "Scroll Box",
  408. "Finding Ore",
  409. "Cookie Bag",
  410. "Potion",
  411. "Herbs",
  412. "Fruits",
  413. "Meat",
  414. "Candy",
  415. "Juice",
  416. "Fish",
  417. "Boxes",
  418. "Gemstone",
  419. "Jellopy",
  420. "Ore",
  421. "Food",
  422. "Recovery",
  423. "Minerals",
  424. "Taming",
  425. "Scrolls",
  426. "Quivers",
  427. "Masks",
  428. "Accesory",
  429. "Jewels",
  430. "Gift Box",
  431. "Gift Box",
  432. "Gift Box",
  433. "Gift Box",
  434. "Egg Boy",
  435. "Egg Girl",
  436. "Gift Box"
  437. };
  438. memset(&itemgroup_db, 0, sizeof(itemgroup_db));
  439. snprintf(path, 255, "%s/item_group_db.txt", db_path);
  440. itemdb_read_itemgroup_sub(path);
  441. ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","item_group_db.txt");
  442. if (battle_config.etc_log) {
  443. for (i = 1; i < MAX_ITEMGROUP; i++)
  444. ShowInfo("Group %s: %d entries.\n", groups[i-1], itemgroup_db[i].qty);
  445. }
  446. return;
  447. }
  448. /*==========================================
  449. * アイテムの名前テーブルを読み込む
  450. *------------------------------------------
  451. */
  452. static int itemdb_read_itemnametable(void)
  453. {
  454. char *buf,*p;
  455. int s;
  456. buf=(char *) grfio_reads("data\\idnum2itemdisplaynametable.txt",&s);
  457. if(buf==NULL)
  458. return -1;
  459. buf[s]=0;
  460. for(p=buf;p-buf<s;){
  461. int nameid;
  462. char buf2[64]; //Why 64? What's this for, other than holding an item's name? [Skotlex]
  463. if( sscanf(p,"%d#%[^#]#",&nameid,buf2)==2 ){
  464. #ifdef ITEMDB_OVERRIDE_NAME_VERBOSE
  465. if( itemdb_exists(nameid) &&
  466. strncmp(itemdb_search(nameid)->jname,buf2,ITEM_NAME_LENGTH)!=0 ){
  467. ShowNotice("[override] %d %s => %s\n",nameid
  468. ,itemdb_search(nameid)->jname,buf2);
  469. }
  470. #endif
  471. strncpy(itemdb_search(nameid)->jname,buf2,ITEM_NAME_LENGTH-1);
  472. }
  473. p=strchr(p,10);
  474. if(!p) break;
  475. p++;
  476. }
  477. aFree(buf);
  478. ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\idnum2itemdisplaynametable.txt");
  479. return 0;
  480. }
  481. /*==========================================
  482. * カードイラストのリソース名前テーブルを読み込む
  483. *------------------------------------------
  484. */
  485. static int itemdb_read_cardillustnametable(void)
  486. {
  487. char *buf,*p;
  488. int s;
  489. buf=(char *) grfio_reads("data\\num2cardillustnametable.txt",&s);
  490. if(buf==NULL)
  491. return -1;
  492. buf[s]=0;
  493. for(p=buf;p-buf<s;){
  494. int nameid;
  495. char buf2[64];
  496. if( sscanf(p,"%d#%[^#]#",&nameid,buf2)==2 ){
  497. strcat(buf2,".bmp");
  498. memcpy(itemdb_search(nameid)->cardillustname,buf2,64);
  499. }
  500. p=strchr(p,10);
  501. if(!p) break;
  502. p++;
  503. }
  504. aFree(buf);
  505. ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\num2cardillustnametable.txt");
  506. return 0;
  507. }
  508. //
  509. // 初期化
  510. //
  511. /*==========================================
  512. *
  513. *------------------------------------------
  514. */
  515. static int itemdb_read_itemslottable(void)
  516. {
  517. char *buf, *p;
  518. int s;
  519. buf = (char *)grfio_reads("data\\itemslottable.txt", &s);
  520. if (buf == NULL)
  521. return -1;
  522. buf[s] = 0;
  523. for (p = buf; p - buf < s; ) {
  524. int nameid, equip;
  525. struct item_data* item;
  526. sscanf(p, "%d#%d#", &nameid, &equip);
  527. item = itemdb_search(nameid);
  528. if (item && itemdb_isequip2(item))
  529. item->equip = equip;
  530. p = strchr(p, 10);
  531. if(!p) break;
  532. p++;
  533. p=strchr(p, 10);
  534. if(!p) break;
  535. p++;
  536. }
  537. aFree(buf);
  538. ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\itemslottable.txt");
  539. return 0;
  540. }
  541. /*==========================================
  542. *
  543. *------------------------------------------
  544. */
  545. static int itemdb_read_itemslotcounttable(void)
  546. {
  547. char *buf, *p;
  548. int s;
  549. buf = (char *)grfio_reads("data\\itemslotcounttable.txt", &s);
  550. if (buf == NULL)
  551. return -1;
  552. buf[s] = 0;
  553. for (p = buf; p - buf < s;){
  554. int nameid, slot;
  555. sscanf(p, "%d#%d#", &nameid, &slot);
  556. if (slot > MAX_SLOTS)
  557. {
  558. ShowWarning("itemdb_read_itemslotcounttable: Item %d specifies %d slots, but the server only supports up to %d\n", nameid, slot, MAX_SLOTS);
  559. slot = MAX_SLOTS;
  560. }
  561. itemdb_slot(nameid) = slot;
  562. p = strchr(p,10);
  563. if(!p) break;
  564. p++;
  565. p = strchr(p,10);
  566. if(!p) break;
  567. p++;
  568. }
  569. aFree(buf);
  570. ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", "data\\itemslotcounttable.txt");
  571. return 0;
  572. }
  573. /*==========================================
  574. * 装備制限ファイル読み出し
  575. *------------------------------------------
  576. */
  577. static int itemdb_read_noequip(void)
  578. {
  579. FILE *fp;
  580. char line[1024];
  581. int ln=0;
  582. int nameid,j;
  583. char *str[32],*p;
  584. struct item_data *id;
  585. sprintf(line, "%s/item_noequip.txt", db_path);
  586. if( (fp=fopen(line,"r"))==NULL ){
  587. ShowError("can't read %s\n", line);
  588. return -1;
  589. }
  590. while(fgets(line,1020,fp)){
  591. if(line[0]=='/' && line[1]=='/')
  592. continue;
  593. memset(str,0,sizeof(str));
  594. for(j=0,p=line;j<2 && p;j++){
  595. str[j]=p;
  596. p=strchr(p,',');
  597. if(p) *p++=0;
  598. }
  599. if(str[0]==NULL)
  600. continue;
  601. nameid=atoi(str[0]);
  602. if(nameid<=0 || nameid>=20000 || !(id=itemdb_exists(nameid)))
  603. continue;
  604. id->flag.no_equip=atoi(str[1]);
  605. ln++;
  606. }
  607. fclose(fp);
  608. if (ln > 0) {
  609. ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"item_noequip.txt");
  610. }
  611. return 0;
  612. }
  613. /*==========================================
  614. * Reads item trade restrictions [Skotlex]
  615. *------------------------------------------
  616. */
  617. static int itemdb_read_itemtrade(void)
  618. {
  619. FILE *fp;
  620. int nameid, j, flag, gmlv, ln = 0;
  621. char line[1024], *str[10], *p;
  622. struct item_data *id;
  623. sprintf(line, "%s/item_trade.txt", db_path);
  624. if ((fp = fopen(line,"r")) == NULL) {
  625. ShowError("can't read %s\n", line);
  626. return -1;
  627. }
  628. while (fgets(line, sizeof(line) - 1, fp)) {
  629. if (line[0] == '/' && line[1] == '/')
  630. continue;
  631. memset(str, 0, sizeof(str));
  632. for (j = 0, p = line; j < 3 && p; j++) {
  633. str[j] = p;
  634. p = strchr(p, ',');
  635. if(p) *p++ = 0;
  636. }
  637. if (j < 3 || str[0] == NULL ||
  638. (nameid = atoi(str[0])) < 0 || nameid >= 20000 || !(id = itemdb_exists(nameid)))
  639. continue;
  640. flag = atoi(str[1]);
  641. gmlv = atoi(str[2]);
  642. if (flag > 0 && flag < 128 && gmlv > 0) { //Check range
  643. id->flag.trade_restriction = flag;
  644. id->gm_lv_trade_override = gmlv;
  645. ln++;
  646. }
  647. }
  648. fclose(fp);
  649. ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, "item_trade.txt");
  650. return 0;
  651. }
  652. /*======================================
  653. * Applies gender restrictions according to settings. [Skotlex]
  654. *======================================
  655. */
  656. static int itemdb_gendercheck(struct item_data *id)
  657. {
  658. if (id->nameid == WEDDING_RING_M) //Grom Ring
  659. return 1;
  660. if (id->nameid == WEDDING_RING_F) //Bride Ring
  661. return 0;
  662. if (id->look == 13 && id->type == 4) //Musical instruments are always male-only
  663. return 1;
  664. if (id->look == 14 && id->type == 4) //Whips are always female-only
  665. return 0;
  666. return (battle_config.ignore_items_gender?2:id->sex);
  667. }
  668. #ifndef TXT_ONLY
  669. /*======================================
  670. * SQL
  671. *===================================
  672. */
  673. static int itemdb_read_sqldb(void)
  674. {
  675. unsigned short nameid;
  676. struct item_data *id;
  677. char script[65535 + 2 + 1]; // Maximum length of MySQL TEXT type (65535) + 2 bytes for curly brackets + 1 byte for terminator
  678. char *item_db_name[] = { item_db_db, item_db2_db };
  679. long unsigned int ln = 0;
  680. int i;
  681. // ----------
  682. for (i = 0; i < 2; i++) {
  683. sprintf(tmp_sql, "SELECT * FROM `%s`", item_db_name[i]);
  684. // Execute the query; if the query execution succeeded...
  685. if (mysql_query(&mmysql_handle, tmp_sql) == 0) {
  686. sql_res = mysql_store_result(&mmysql_handle);
  687. // If the storage of the query result succeeded...
  688. if (sql_res) {
  689. // Parse each row in the query result into sql_row
  690. while ((sql_row = mysql_fetch_row(sql_res)))
  691. { /*Table structure is:
  692. 00 id
  693. 01 name_english
  694. 02 name_japanese
  695. 03 type
  696. 04 price_buy
  697. 05 price_sell
  698. 06 weight
  699. 07 attack
  700. 08 defence
  701. 09 range
  702. 10 slots
  703. 11 equip_jobs
  704. 12 equip_upper
  705. 13 equip_genders
  706. 14 equip_locations
  707. 15 weapon_level
  708. 16 equip_level
  709. 17 refineable
  710. 18 view
  711. 19 script
  712. 20 equip_script
  713. 21 unequip_script
  714. */
  715. nameid = atoi(sql_row[0]);
  716. // If the identifier is not within the valid range, process the next row
  717. if (nameid == 0 || nameid >= 20000)
  718. continue;
  719. ln++;
  720. // ----------
  721. id = itemdb_load(nameid);
  722. strncpy(id->name, sql_row[1], ITEM_NAME_LENGTH-1);
  723. strncpy(id->jname, sql_row[2], ITEM_NAME_LENGTH-1);
  724. id->type = atoi(sql_row[3]);
  725. if (id->type == 11)
  726. { //Items that are consumed upon target confirmation
  727. //(yggdrasil leaf, spells & pet lures) [Skotlex]
  728. id->type = 2;
  729. id->flag.delay_consume=1;
  730. }
  731. // If price_buy is not NULL and price_sell is not NULL...
  732. if ((sql_row[4] != NULL) && (sql_row[5] != NULL)) {
  733. id->value_buy = atoi(sql_row[4]);
  734. id->value_sell = atoi(sql_row[5]);
  735. }
  736. // If price_buy is not NULL and price_sell is NULL...
  737. else if ((sql_row[4] != NULL) && (sql_row[5] == NULL)) {
  738. id->value_buy = atoi(sql_row[4]);
  739. id->value_sell = atoi(sql_row[4]) / 2;
  740. }
  741. // If price_buy is NULL and price_sell is not NULL...
  742. else if ((sql_row[4] == NULL) && (sql_row[5] != NULL)) {
  743. id->value_buy = atoi(sql_row[5]) * 2;
  744. id->value_sell = atoi(sql_row[5]);
  745. }
  746. // If price_buy is NULL and price_sell is NULL...
  747. if ((sql_row[4] == NULL) && (sql_row[5] == NULL)) {
  748. id->value_buy = 0;
  749. id->value_sell = 0;
  750. }
  751. id->weight = atoi(sql_row[6]);
  752. id->atk = (sql_row[7] != NULL) ? atoi(sql_row[7]) : 0;
  753. id->def = (sql_row[8] != NULL) ? atoi(sql_row[8]) : 0;
  754. id->range = (sql_row[9] != NULL) ? atoi(sql_row[9]) : 0;
  755. id->slot = (sql_row[10] != NULL) ? atoi(sql_row[10]) : 0;
  756. if (id->slot > MAX_SLOTS)
  757. {
  758. ShowWarning("itemdb_read_sqldb: Item %d (%s) specifies %d slots, but the server only supports up to %d\n", nameid, id->jname, id->slot, MAX_SLOTS);
  759. id->slot = MAX_SLOTS;
  760. }
  761. itemdb_jobid2mapid(id->class_base, (sql_row[11] != NULL) ? (unsigned int)strtoul(sql_row[11], NULL, 0) : 0);
  762. id->class_upper= (sql_row[12] != NULL) ? atoi(sql_row[12]) : 0;
  763. id->sex = (sql_row[13] != NULL) ? atoi(sql_row[13]) : 0;
  764. id->equip = (sql_row[14] != NULL) ? atoi(sql_row[14]) : 0;
  765. id->wlv = (sql_row[15] != NULL) ? atoi(sql_row[15]) : 0;
  766. id->elv = (sql_row[16] != NULL) ? atoi(sql_row[16]) : 0;
  767. id->flag.no_refine = (sql_row[17] == NULL || atoi(sql_row[17]) == 1)?0:1;
  768. id->look = (sql_row[18] != NULL) ? atoi(sql_row[18]) : 0;
  769. id->view_id = 0;
  770. id->sex = itemdb_gendercheck(id); //Apply gender filtering.
  771. // ----------
  772. if (id->script)
  773. script_free_code(id->script);
  774. if (sql_row[19] != NULL) {
  775. if (sql_row[19][0] == '{')
  776. id->script = parse_script((unsigned char *) sql_row[19], 0);
  777. else {
  778. sprintf(script, "{%s}", sql_row[19]);
  779. id->script = parse_script((unsigned char *) script, 0);
  780. }
  781. } else id->script = NULL;
  782. if (id->equip_script)
  783. script_free_code(id->equip_script);
  784. if (sql_row[20] != NULL) {
  785. if (sql_row[20][0] == '{')
  786. id->equip_script = parse_script((unsigned char *) sql_row[20], 0);
  787. else {
  788. sprintf(script, "{%s}", sql_row[20]);
  789. id->equip_script = parse_script((unsigned char *) script, 0);
  790. }
  791. } else id->equip_script = NULL;
  792. if (id->unequip_script)
  793. script_free_code(id->unequip_script);
  794. if (sql_row[21] != NULL) {
  795. if (sql_row[21][0] == '{')
  796. id->unequip_script = parse_script((unsigned char *) sql_row[21], 0);
  797. else {
  798. sprintf(script, "{%s}", sql_row[21]);
  799. id->unequip_script = parse_script((unsigned char *) script, 0);
  800. }
  801. } else id->unequip_script = NULL;
  802. // ----------
  803. id->flag.available = 1;
  804. id->flag.value_notdc = 0;
  805. id->flag.value_notoc = 0;
  806. }
  807. ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, item_db_name[i]);
  808. ln = 0;
  809. } else {
  810. ShowSQL("DB error (%s) - %s\n",item_db_name[i], mysql_error(&mmysql_handle));
  811. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  812. }
  813. // Free the query result
  814. mysql_free_result(sql_res);
  815. } else {
  816. ShowSQL("DB error (%s) - %s\n",item_db_name[i], mysql_error(&mmysql_handle));
  817. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  818. }
  819. }
  820. return 0;
  821. }
  822. #endif /* not TXT_ONLY */
  823. /*==========================================
  824. * アイテムデータベースの読み込み
  825. *------------------------------------------
  826. */
  827. static int itemdb_readdb(void)
  828. {
  829. FILE *fp;
  830. char line[1024];
  831. int ln=0,lines=0;
  832. int nameid,j;
  833. char *str[32],*p,*np;
  834. struct item_data *id;
  835. int i=0;
  836. char *filename[]={ "item_db.txt","item_db2.txt" };
  837. for(i=0;i<2;i++){
  838. sprintf(line, "%s/%s", db_path, filename[i]);
  839. fp=fopen(line,"r");
  840. if(fp==NULL){
  841. if(i>0)
  842. continue;
  843. ShowFatalError("can't read %s\n",line);
  844. exit(1);
  845. }
  846. lines=0;
  847. while(fgets(line,1020,fp)){
  848. lines++;
  849. if(line[0]=='/' && line[1]=='/')
  850. continue;
  851. memset(str,0,sizeof(str));
  852. for(j=0,np=p=line;j<19 && p;j++){
  853. str[j]=p;
  854. p=strchr(p,',');
  855. if(p){ *p++=0; np=p; }
  856. }
  857. if(str[0]==NULL)
  858. continue;
  859. nameid=atoi(str[0]);
  860. if(nameid<=0 || nameid>=20000)
  861. continue;
  862. if (j < 19)
  863. { //Crash-fix on broken item lines. [Skotlex]
  864. ShowWarning("Reading %s: Insufficient fields for item with id %d, skipping.\n", filename[i], nameid);
  865. continue;
  866. }
  867. ln++;
  868. //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View
  869. id=itemdb_load(nameid);
  870. strncpy(id->name, str[1], ITEM_NAME_LENGTH-1);
  871. strncpy(id->jname, str[2], ITEM_NAME_LENGTH-1);
  872. id->type=atoi(str[3]);
  873. if (id->type == 11)
  874. { //Items that are consumed upon target confirmation
  875. //(yggdrasil leaf, spells & pet lures) [Skotlex]
  876. id->type = 2;
  877. id->flag.delay_consume=1;
  878. }
  879. {
  880. int buy = atoi(str[4]), sell = atoi(str[5]);
  881. // if buying price > selling price * 2 consider it valid and don't change it [celest]
  882. if (buy && sell && buy > sell*2){
  883. id->value_buy = buy;
  884. id->value_sell = sell;
  885. } else {
  886. // buy≠sell*2 は item_value_db.txt で指定してください。
  887. if (sell) { // sell値を優先とする
  888. id->value_buy = sell*2;
  889. id->value_sell = sell;
  890. } else {
  891. id->value_buy = buy;
  892. id->value_sell = buy/2;
  893. }
  894. }
  895. // check for bad prices that can possibly cause exploits
  896. if (id->value_buy*75/100 < id->value_sell*124/100) {
  897. ShowWarning ("Item %s [%d] buying:%d < selling:%d\n",
  898. id->name, id->nameid, id->value_buy*75/100, id->value_sell*124/100);
  899. }
  900. }
  901. id->weight=atoi(str[6]);
  902. id->atk=atoi(str[7]);
  903. id->def=atoi(str[8]);
  904. id->range=atoi(str[9]);
  905. id->slot=atoi(str[10]);
  906. if (id->slot > MAX_SLOTS)
  907. {
  908. ShowWarning("itemdb_readdb: Item %d (%s) specifies %d slots, but the server only supports up to %d\n", nameid, id->jname, id->slot, MAX_SLOTS);
  909. id->slot = MAX_SLOTS;
  910. }
  911. itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11],NULL,0));
  912. id->class_upper = atoi(str[12]);
  913. id->sex = atoi(str[13]);
  914. if(id->equip != atoi(str[14])){
  915. id->equip=atoi(str[14]);
  916. }
  917. id->wlv=atoi(str[15]);
  918. id->elv=atoi(str[16]);
  919. id->flag.no_refine = atoi(str[17])?0:1; //If the refine column is 1, no_refine is 0
  920. id->look=atoi(str[18]);
  921. id->flag.available=1;
  922. id->flag.value_notdc=0;
  923. id->flag.value_notoc=0;
  924. id->view_id=0;
  925. id->sex = itemdb_gendercheck(id); //Apply gender filtering.
  926. if (id->script) {
  927. script_free_code(id->script);
  928. id->script=NULL;
  929. }
  930. if (id->equip_script) {
  931. aFree(id->equip_script);
  932. id->equip_script=NULL;
  933. }
  934. if (id->unequip_script) {
  935. aFree(id->unequip_script);
  936. id->unequip_script=NULL;
  937. }
  938. if((p=strchr(np,'{'))==NULL)
  939. continue;
  940. str[19] = p; //Script
  941. np = strchr(p,'}');
  942. while (np && np[1] && np[1] != ',')
  943. np = strchr(np+1,'}'); //Jump close brackets until the next field is found.
  944. if (!np || !np[1]) {
  945. //Couldn't find the end of the script field.
  946. id->script = parse_script((unsigned char *) str[19],lines);
  947. continue;
  948. }
  949. np[1] = '\0'; //Set end of script
  950. id->script = parse_script((unsigned char *) str[19],lines);
  951. np+=2; //Skip to next field
  952. if(!np || (p=strchr(np,'{'))==NULL)
  953. continue;
  954. str[20] = p; //Equip Script
  955. np = strchr(p,'}');
  956. while (np && np[1] && np[1] != ',')
  957. np = strchr(np+1,'}'); //Jump close brackets until the next field is found.
  958. if (!np || !np[1]) {
  959. //Couldn't find the end of the script field.
  960. id->equip_script = parse_script((unsigned char *) str[20],lines);
  961. continue;
  962. }
  963. np[1] = '\0'; //Set end of script
  964. id->equip_script = parse_script((unsigned char *) str[20],lines);
  965. np+=2; //Skip comma, to next field
  966. if(!np || (p=strchr(np,'{'))==NULL)
  967. continue;
  968. //Unequip script, last column.
  969. id->unequip_script = parse_script((unsigned char *) p,lines);
  970. }
  971. fclose(fp);
  972. if (ln > 0) {
  973. ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]);
  974. }
  975. ln=0; // reset to 0
  976. }
  977. return 0;
  978. }
  979. /*====================================
  980. * Removed item_value_db, don't re-add
  981. *------------------------------------
  982. */
  983. static void itemdb_read(void)
  984. {
  985. #ifndef TXT_ONLY
  986. if (db_use_sqldbs)
  987. itemdb_read_sqldb();
  988. else
  989. #endif
  990. itemdb_readdb();
  991. itemdb_read_itemgroup();
  992. itemdb_read_itemavail();
  993. itemdb_read_noequip();
  994. itemdb_read_itemtrade();
  995. if (battle_config.cardillust_read_grffile)
  996. itemdb_read_cardillustnametable();
  997. if (battle_config.item_equip_override_grffile)
  998. itemdb_read_itemslottable();
  999. if (battle_config.item_slots_override_grffile)
  1000. itemdb_read_itemslotcounttable();
  1001. if (battle_config.item_name_override_grffile)
  1002. itemdb_read_itemnametable();
  1003. }
  1004. /*==========================================
  1005. * Initialize / Finalize
  1006. *------------------------------------------
  1007. */
  1008. static int itemdb_final_sub (DBKey key,void *data,va_list ap)
  1009. {
  1010. int flag;
  1011. struct item_data *id = (struct item_data *)data;
  1012. flag = va_arg(ap, int);
  1013. if (id->script)
  1014. {
  1015. script_free_code(id->script);
  1016. id->script = NULL;
  1017. }
  1018. if (id->equip_script)
  1019. {
  1020. script_free_code(id->equip_script);
  1021. id->equip_script = NULL;
  1022. }
  1023. if (id->unequip_script)
  1024. {
  1025. script_free_code(id->unequip_script);
  1026. id->unequip_script = NULL;
  1027. }
  1028. // Whether to clear the item data (exception: do not clear the dummy item data
  1029. if (flag && id != dummy_item)
  1030. aFree(id);
  1031. return 0;
  1032. }
  1033. void itemdb_reload(void)
  1034. {
  1035. // free up all item scripts first
  1036. item_db->foreach(item_db, itemdb_final_sub, 0);
  1037. itemdb_read();
  1038. }
  1039. void do_final_itemdb(void)
  1040. {
  1041. item_db->destroy(item_db, itemdb_final_sub, 1);
  1042. if (dummy_item) {
  1043. if (dummy_item->script)
  1044. script_free_code(dummy_item->script);
  1045. if (dummy_item->equip_script)
  1046. script_free_code(dummy_item->equip_script);
  1047. if (dummy_item->unequip_script)
  1048. script_free_code(dummy_item->unequip_script);
  1049. aFree(dummy_item);
  1050. dummy_item = NULL;
  1051. }
  1052. }
  1053. int do_init_itemdb(void)
  1054. {
  1055. item_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int));
  1056. create_dummy_data(); //Dummy data item.
  1057. itemdb_read();
  1058. return 0;
  1059. }