itemdb.c 28 KB

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