itemdb.c 27 KB

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