1 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
2 // For more information, see LICENCE in the main folder
4 #include "../common/nullpo.h"
5 #include "../common/malloc.h"
6 #include "../common/random.h"
7 #include "../common/showmsg.h"
8 #include "../common/strlib.h"
9 #include "../common/utils.h"
11 #include "battle.h" // struct battle_config
17 static DBMap *itemdb; /// Item DB
18 static DBMap *itemdb_combo; /// Item Combo DB
19 static DBMap *itemdb_group; /// Item Group DB
20 static DBMap *itemdb_randomopt; /// Random option DB
21 static DBMap *itemdb_randomopt_group; /// Random option group DB
23 struct item_data *dummy_item; /// This is the default dummy item used for non-existant items. [Skotlex]
25 struct s_roulette_db rd;
28 * Check if combo exists
30 * @return NULL if not exist, or struct item_combo*
32 struct item_combo *itemdb_combo_exists(unsigned short combo_id) {
33 return (struct item_combo *)uidb_get(itemdb_combo, combo_id);
37 * Check if item group exists
39 * @return NULL if not exist, or s_item_group_db *
41 struct s_item_group_db *itemdb_group_exists(unsigned short group_id) {
42 return (struct s_item_group_db *)uidb_get(itemdb_group, group_id);
46 * Check if an item exists in a group
47 * @param nameid: Item to check for in group
48 * @return True if item is in group, else false
50 bool itemdb_group_item_exists(unsigned short group_id, unsigned short nameid)
52 struct s_item_group_db *group = (struct s_item_group_db *)uidb_get(itemdb_group, group_id);
58 for (i = 0; i < MAX_ITEMGROUP_RANDGROUP; i++) {
59 for (j = 0; j < group->random[i].data_qty; j++)
60 if (group->random[i].data[j].nameid == nameid)
67 * Search for item name
68 * name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
71 static int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap)
73 struct item_data *item = (struct item_data *)db_data2ptr(data), **dst, **dst2;
75 str = va_arg(ap,char *);
76 dst = va_arg(ap,struct item_data **);
77 dst2 = va_arg(ap,struct item_data **);
79 //Absolute priority to Aegis code name.
80 if (strcmpi(item->name,str) == 0)
83 //Second priority to Client displayed name.
84 if (strcmpi(item->jname,str) == 0)
89 /*==========================================
90 * Return item data from item name. (lookup)
91 * @param str Item Name
93 *------------------------------------------*/
94 struct item_data* itemdb_searchname(const char *str)
96 struct item_data *item = NULL, * item2 = NULL;
98 itemdb->foreach(itemdb,itemdb_searchname_sub,str,&item,&item2);
99 return item ? item : item2;
105 static int itemdb_searchname_array_sub(DBKey key, DBData data, va_list ap)
107 struct item_data *item = (struct item_data *)db_data2ptr(&data);
108 char *str = va_arg(ap,char *);
110 if (stristr(item->jname,str))
112 if (stristr(item->name,str))
114 return strcmpi(item->jname,str);
117 /*==========================================
118 * Founds up to N matches. Returns number of matches [Skotlex]
122 * @return Number of matches item
123 *------------------------------------------*/
124 int itemdb_searchname_array(struct item_data** data, int size, const char *str)
126 DBData *db_data[MAX_SEARCH];
127 int i, count = 0, db_count;
129 db_count = itemdb->getall(itemdb, (DBData**)&db_data, size, itemdb_searchname_array_sub, str);
130 for (i = 0; i < db_count && count < size; i++)
131 data[count++] = (struct item_data*)db_data2ptr(db_data[i]);
137 * Return a random group entry from Item Group
139 * @param sub_group: 0 is 'must' item group, random groups start from 1 to MAX_ITEMGROUP_RANDGROUP+1
140 * @return Item group entry or NULL on fail
142 struct s_item_group_entry *itemdb_get_randgroupitem(uint16 group_id, uint8 sub_group) {
143 struct s_item_group_db *group = (struct s_item_group_db *) uidb_get(itemdb_group, group_id);
144 struct s_item_group_entry *list = NULL;
148 ShowError("itemdb_get_randgroupitem: Invalid group id %d\n", group_id);
151 if (sub_group > MAX_ITEMGROUP_RANDGROUP+1) {
152 ShowError("itemdb_get_randgroupitem: Invalid sub_group %d\n", sub_group);
155 if (sub_group == 0) {
157 qty = group->must_qty;
160 list = group->random[sub_group-1].data;
161 qty = group->random[sub_group-1].data_qty;
164 ShowError("itemdb_get_randgroupitem: No item entries for group id %d and sub group %d\n", group_id, sub_group);
167 return &list[rnd()%qty];
171 * Return a random Item ID from from Item Group
173 * @param sub_group: 0 is 'must' item group, random groups start from 1 to MAX_ITEMGROUP_RANDGROUP+1
174 * @return Item ID or UNKNOWN_ITEM_ID on fail
176 unsigned short itemdb_searchrandomid(uint16 group_id, uint8 sub_group) {
177 struct s_item_group_entry *entry = itemdb_get_randgroupitem(group_id, sub_group);
178 return entry ? entry->nameid : UNKNOWN_ITEM_ID;
182 * Gives item(s) to the player based on item group
183 * @param sd: Player that obtains item from item group
184 * @param group_id: The group ID of item that obtained by player
185 * @param *group: struct s_item_group from itemgroup_db[group_id].random[idx] or itemgroup_db[group_id].must[sub_group][idx]
187 static void itemdb_pc_get_itemgroup_sub(struct map_session_data *sd, struct s_item_group_entry *data) {
188 uint16 i, get_amt = 0;
193 memset(&tmp, 0, sizeof(tmp));
195 tmp.nameid = data->nameid;
196 tmp.bound = data->bound;
198 tmp.expire_time = (data->duration) ? (unsigned int)(time(NULL) + data->duration*60) : 0;
200 tmp.card[0] = itemdb_isequip(data->nameid) ? CARD0_FORGE : CARD0_CREATE;
202 tmp.card[2] = GetWord(sd->status.char_id, 0);
203 tmp.card[3] = GetWord(sd->status.char_id, 1);
206 if (!itemdb_isstackable(data->nameid))
209 get_amt = data->amount;
211 // Do loop for non-stackable item
212 for (i = 0; i < data->amount; i += get_amt) {
214 tmp.unique_id = data->GUID ? pc_generate_unique_id(sd) : 0; // Generate GUID
215 if ((flag = pc_additem(sd, &tmp, get_amt, LOG_TYPE_SCRIPT))) {
216 clif_additem(sd, 0, 0, flag);
217 if (pc_candrop(sd, &tmp))
218 map_addflooritem(&tmp, tmp.amount, sd->bl.m, sd->bl.x,sd->bl.y, 0, 0, 0, 0, 0);
220 else if (!flag && data->isAnnounced)
221 intif_broadcast_obtain_special_item(sd, data->nameid, sd->itemid, ITEMOBTAIN_TYPE_BOXITEM);
226 * Find item(s) that will be obtained by player based on Item Group
227 * @param group_id: The group ID that will be gained by player
228 * @param nameid: The item that trigger this item group
229 * @return val: 0:success, 1:no sd, 2:invalid item group
231 char itemdb_pc_get_itemgroup(uint16 group_id, struct map_session_data *sd) {
233 struct s_item_group_db *group;
237 if (!(group = (struct s_item_group_db *) uidb_get(itemdb_group, group_id))) {
238 ShowError("itemdb_pc_get_itemgroup: Invalid group id '%d' specified.\n",group_id);
242 // Get the 'must' item(s)
243 if (group->must_qty) {
244 for (i = 0; i < group->must_qty; i++)
246 itemdb_pc_get_itemgroup_sub(sd,&group->must[i]);
249 // Get the 'random' item each random group
250 for (i = 0; i < MAX_ITEMGROUP_RANDGROUP; i++) {
252 if (!(&group->random[i]) || !group->random[i].data_qty) //Skip empty random group
254 rand = rnd()%group->random[i].data_qty;
255 if (!(&group->random[i].data[rand]) || !group->random[i].data[rand].nameid)
257 itemdb_pc_get_itemgroup_sub(sd,&group->random[i].data[rand]);
263 /** Searches for the item_data. Use this to check if item exists or not.
265 * @return *item_data if item is exist, or NULL if not
267 struct item_data* itemdb_exists(unsigned short nameid) {
268 return ((struct item_data*)uidb_get(itemdb,nameid));
271 /// Returns name type of ammunition [Cydh]
272 const char *itemdb_typename_ammo (enum e_item_ammo ammo) {
274 case AMMO_ARROW: return "Arrow";
275 case AMMO_THROWABLE_DAGGER: return "Throwable Dagger";
276 case AMMO_BULLET: return "Bullet";
277 case AMMO_SHELL: return "Shell";
278 case AMMO_GRENADE: return "Grenade";
279 case AMMO_SHURIKEN: return "Shuriken";
280 case AMMO_KUNAI: return "Kunai";
281 case AMMO_CANNONBALL: return "Cannonball";
282 case AMMO_THROWABLE_ITEM: return "Throwable Item/Sling Item";
287 /// Returns human readable name for given item type.
288 /// @param type Type id to retrieve name for ( IT_* ).
289 const char* itemdb_typename(enum item_types type)
293 case IT_HEALING: return "Potion/Food";
294 case IT_USABLE: return "Usable";
295 case IT_ETC: return "Etc.";
296 case IT_WEAPON: return "Weapon";
297 case IT_ARMOR: return "Armor";
298 case IT_CARD: return "Card";
299 case IT_PETEGG: return "Pet Egg";
300 case IT_PETARMOR: return "Pet Accessory";
301 case IT_AMMO: return "Arrow/Ammunition";
302 case IT_DELAYCONSUME: return "Delay-Consume Usable";
303 case IT_SHADOWGEAR: return "Shadow Equipment";
304 case IT_CASH: return "Cash Usable";
306 return "Unknown Type";
310 * Converts the jobmask from the format in itemdb to the format used by the map server.
311 * @param bclass: Pointer to store itemdb format
312 * @param jobmask: Job Mask to convert
315 static void itemdb_jobid2mapid(uint64 *bclass, uint64 jobmask)
319 bclass[0] = bclass[1] = bclass[2] = 0;
322 if (jobmask & 1ULL<<JOB_NOVICE) {
323 //Both Novice/Super-Novice are counted with the same ID
324 bclass[0] |= 1ULL<<MAPID_NOVICE;
325 bclass[1] |= 1ULL<<MAPID_NOVICE;
327 for (i = JOB_NOVICE + 1; i <= JOB_THIEF; i++) {
328 if (jobmask & 1ULL <<i)
329 bclass[0] |= 1ULL<<(MAPID_NOVICE + i);
332 if (jobmask & 1ULL<<JOB_KNIGHT)
333 bclass[1] |= 1ULL<<MAPID_SWORDMAN;
334 if (jobmask & 1ULL<<JOB_PRIEST)
335 bclass[1] |= 1ULL<<MAPID_ACOLYTE;
336 if (jobmask & 1ULL<<JOB_WIZARD)
337 bclass[1] |= 1ULL<<MAPID_MAGE;
338 if (jobmask & 1ULL<<JOB_BLACKSMITH)
339 bclass[1] |= 1ULL<<MAPID_MERCHANT;
340 if (jobmask & 1ULL<<JOB_HUNTER)
341 bclass[1] |= 1ULL<<MAPID_ARCHER;
342 if (jobmask & 1ULL<<JOB_ASSASSIN)
343 bclass[1] |= 1ULL<<MAPID_THIEF;
345 if (jobmask & 1ULL<<JOB_CRUSADER)
346 bclass[2] |= 1ULL<<MAPID_SWORDMAN;
347 if (jobmask & 1ULL<<JOB_MONK)
348 bclass[2] |= 1ULL<<MAPID_ACOLYTE;
349 if (jobmask & 1ULL<<JOB_SAGE)
350 bclass[2] |= 1ULL<<MAPID_MAGE;
351 if (jobmask & 1ULL<<JOB_ALCHEMIST)
352 bclass[2] |= 1ULL<<MAPID_MERCHANT;
353 if (jobmask & 1ULL<<JOB_BARD)
354 bclass[2] |= 1ULL<<MAPID_ARCHER;
355 // Bard/Dancer share the same slot now.
356 // if (jobmask & 1ULL<<JOB_DANCER)
357 // bclass[2] |= 1ULL<<MAPID_ARCHER;
358 if (jobmask & 1ULL<<JOB_ROGUE)
359 bclass[2] |= 1ULL<<MAPID_THIEF;
360 //Special classes that don't fit above.
361 if (jobmask & 1ULL<<21) //Taekwon
362 bclass[0] |= 1ULL<<MAPID_TAEKWON;
363 if (jobmask & 1ULL<<22) //Star Gladiator
364 bclass[1] |= 1ULL<<MAPID_TAEKWON;
365 if (jobmask & 1ULL<<23) //Soul Linker
366 bclass[2] |= 1ULL<<MAPID_TAEKWON;
367 if (jobmask & 1ULL<<JOB_GUNSLINGER) { // Rebellion job can equip Gunslinger equips.
368 bclass[0] |= 1ULL<<MAPID_GUNSLINGER;
369 bclass[1] |= 1ULL<<MAPID_GUNSLINGER;
371 if (jobmask & 1ULL<<JOB_NINJA) { //Kagerou/Oboro jobs can equip Ninja equips. [Rytech]
372 bclass[0] |= 1ULL<<MAPID_NINJA;
373 bclass[1] |= 1ULL<<MAPID_NINJA;
375 if (jobmask & 1ULL<<26) //Bongun/Munak
376 bclass[0] |= 1ULL<<MAPID_GANGSI;
377 if (jobmask & 1ULL<<27) //Death Knight
378 bclass[1] |= 1ULL<<MAPID_GANGSI;
379 if (jobmask & 1ULL<<28) //Dark Collector
380 bclass[2] |= 1ULL<<MAPID_GANGSI;
381 if (jobmask & 1ULL<<29) //Kagerou / Oboro
382 bclass[1] |= 1ULL<<MAPID_NINJA;
383 if (jobmask & 1ULL<<30) //Rebellion
384 bclass[1] |= 1ULL<<MAPID_GUNSLINGER;
385 if (jobmask & 1ULL<<31) //Summoner
386 bclass[0] |= 1ULL<<MAPID_SUMMONER;
390 * Create dummy item_data as dummy_item and dummy item group entry as dummy_itemgroup
392 static void itemdb_create_dummy(void) {
393 CREATE(dummy_item, struct item_data, 1);
395 memset(dummy_item, 0, sizeof(struct item_data));
396 dummy_item->nameid = 500;
397 dummy_item->weight = 1;
398 dummy_item->value_sell = 1;
399 dummy_item->type = IT_ETC; //Etc item
400 safestrncpy(dummy_item->name, "UNKNOWN_ITEM", sizeof(dummy_item->name));
401 safestrncpy(dummy_item->jname, "Unknown Item", sizeof(dummy_item->jname));
402 dummy_item->view_id = UNKNOWN_ITEM_ID;
406 * Create new item data
409 static struct item_data *itemdb_create_item(unsigned short nameid) {
410 struct item_data *id;
411 CREATE(id, struct item_data, 1);
412 memset(id, 0, sizeof(struct item_data));
414 id->type = IT_ETC; //Etc item
415 uidb_put(itemdb, nameid, id);
419 /*==========================================
420 * Loads an item from the db. If not found, it will return the dummy item.
422 * @return *item_data or *dummy_item if item not found
423 *------------------------------------------*/
424 struct item_data* itemdb_search(unsigned short nameid) {
425 struct item_data* id = NULL;
426 if (nameid == dummy_item->nameid)
428 else if (!(id = (struct item_data*)uidb_get(itemdb, nameid))) {
429 ShowWarning("itemdb_search: Item ID %hu does not exists in the item_db. Using dummy data.\n", nameid);
435 /** Checks if item is equip type or not
436 * @param id Item data
437 * @return True if item is equip, false otherwise
439 bool itemdb_isequip2(struct item_data *id) {
452 /** Checks if item is stackable or not
453 * @param id Item data
454 * @return True if item is stackable, false otherwise
456 bool itemdb_isstackable2(struct item_data *id)
472 /*==========================================
473 * Trade Restriction functions [Skotlex]
474 *------------------------------------------*/
475 bool itemdb_isdropable_sub(struct item_data *item, int gmlv, int unused) {
476 return (item && (!(item->flag.trade_restriction&1) || gmlv >= item->gm_lv_trade_override));
479 bool itemdb_cantrade_sub(struct item_data* item, int gmlv, int gmlv2) {
480 return (item && (!(item->flag.trade_restriction&2) || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
483 bool itemdb_canpartnertrade_sub(struct item_data* item, int gmlv, int gmlv2) {
484 return (item && (item->flag.trade_restriction&4 || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
487 bool itemdb_cansell_sub(struct item_data* item, int gmlv, int unused) {
488 return (item && (!(item->flag.trade_restriction&8) || gmlv >= item->gm_lv_trade_override));
491 bool itemdb_cancartstore_sub(struct item_data* item, int gmlv, int unused) {
492 return (item && (!(item->flag.trade_restriction&16) || gmlv >= item->gm_lv_trade_override));
495 bool itemdb_canstore_sub(struct item_data* item, int gmlv, int unused) {
496 return (item && (!(item->flag.trade_restriction&32) || gmlv >= item->gm_lv_trade_override));
499 bool itemdb_canguildstore_sub(struct item_data* item, int gmlv, int unused) {
500 return (item && (!(item->flag.trade_restriction&64) || gmlv >= item->gm_lv_trade_override));
503 bool itemdb_canmail_sub(struct item_data* item, int gmlv, int unused) {
504 return (item && (!(item->flag.trade_restriction&128) || gmlv >= item->gm_lv_trade_override));
507 bool itemdb_canauction_sub(struct item_data* item, int gmlv, int unused) {
508 return (item && (!(item->flag.trade_restriction&256) || gmlv >= item->gm_lv_trade_override));
511 bool itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, bool (*func)(struct item_data*, int, int))
513 struct item_data* item_data = itemdb_search(item->nameid);
516 if (!func(item_data, gmlv, gmlv2))
519 if(item_data->slot == 0 || itemdb_isspecial(item->card[0]))
522 for(i = 0; i < item_data->slot; i++) {
523 if (!item->card[i]) continue;
524 if (!func(itemdb_search(item->card[i]), gmlv, gmlv2))
530 /** Specifies if item-type should drop unidentified.
531 * @param nameid ID of item
533 char itemdb_isidentified(unsigned short nameid) {
534 int type=itemdb_type(nameid);
546 /** Search by name for the override flags available items (Give item another sprite)
547 * Structure: <nameid>,<sprite>
549 static bool itemdb_read_itemavail(char* str[], int columns, int current) {
550 unsigned short nameid, sprite;
551 struct item_data *id;
553 nameid = atoi(str[0]);
555 if( ( id = itemdb_exists(nameid) ) == NULL )
557 ShowWarning("itemdb_read_itemavail: Invalid item id %hu.\n", nameid);
561 sprite = atoi(str[1]);
565 id->flag.available = 1;
566 id->view_id = sprite;
570 id->flag.available = 0;
576 static int itemdb_group_free(DBKey key, DBData *data, va_list ap);
577 static int itemdb_group_free2(DBKey key, DBData *data);
579 static bool itemdb_read_group(char* str[], int columns, int current) {
581 unsigned int j, prob = 1;
582 uint8 rand_group = 1;
583 struct s_item_group_random *random = NULL;
584 struct s_item_group_db *group = NULL;
585 struct s_item_group_entry entry;
587 memset(&entry, 0, sizeof(entry));
589 entry.bound = BOUND_NONE;
591 str[0] = trim(str[0]);
592 if( ISDIGIT(str[0][0]) ){
593 group_id = atoi(str[0]);
595 // Try to parse group id as constant
596 script_get_constant(str[0], &group_id);
599 // Check the group id
601 ShowWarning( "itemdb_read_group: Invalid group ID '%s'\n", str[0] );
606 if( strcmpi( str[1], "clear" ) == 0 ){
609 if( itemdb_group->remove( itemdb_group, db_ui2key(group_id), &data ) ){
610 itemdb_group_free2(db_ui2key(group_id), &data);
611 ShowNotice( "itemdb_read_group: Item Group '%s' has been cleared.\n", str[0] );
614 ShowWarning( "itemdb_read_group: Item Group '%s' has not been cleared, because it did not exist.\n", str[0] );
619 // Checking sub group
623 rand_group = atoi(str[4]);
625 if( rand_group < 0 || rand_group > MAX_ITEMGROUP_RANDGROUP ){
626 ShowWarning( "itemdb_read_group: Invalid sub group '%d' for group '%s'\n", rand_group, str[0] );
633 if( rand_group != 0 && prob < 1 ){
634 ShowWarning( "itemdb_read_group: Random item must have a probability. Group '%s'\n", str[0] );
639 str[1] = trim(str[1]);
641 // Check if the item can be found by id
642 if( ( entry.nameid = atoi(str[1]) ) <= 0 || !itemdb_exists( entry.nameid ) ){
643 // Otherwise look it up by name
644 struct item_data *id = itemdb_searchname(str[1]);
647 // Found the item with a name lookup
648 entry.nameid = id->nameid;
650 ShowWarning( "itemdb_read_group: Non-existant item '%s'\n", str[1] );
655 if( columns > 3 ) entry.amount = cap_value(atoi(str[3]),1,MAX_AMOUNT);
656 if( columns > 5 ) entry.isAnnounced= atoi(str[5]);
657 if( columns > 6 ) entry.duration = cap_value(atoi(str[6]),0,UINT16_MAX);
658 if( columns > 7 ) entry.GUID = atoi(str[7]);
659 if( columns > 8 ) entry.bound = cap_value(atoi(str[8]),BOUND_NONE,BOUND_MAX-1);
660 if( columns > 9 ) entry.isNamed = atoi(str[9]);
662 if (!(group = (struct s_item_group_db *) uidb_get(itemdb_group, group_id))) {
663 CREATE(group, struct s_item_group_db, 1);
664 group->id = group_id;
665 uidb_put(itemdb_group, group->id, group);
668 // Must item (rand_group == 0), place it here
670 RECREATE(group->must, struct s_item_group_entry, group->must_qty+1);
671 group->must[group->must_qty++] = entry;
673 // If 'must' item isn't set as random item, skip the next process
682 random = &group->random[rand_group];
684 RECREATE(random->data, struct s_item_group_entry, random->data_qty+prob);
686 // Put the entry to its rand_group
687 for (j = random->data_qty; j < random->data_qty+prob; j++)
688 random->data[j] = entry;
690 random->data_qty += prob;
694 /** Read item forbidden by mapflag (can't equip item)
695 * Structure: <nameid>,<mode>
697 static bool itemdb_read_noequip(char* str[], int columns, int current) {
698 unsigned short nameid;
700 struct item_data *id;
702 nameid = atoi(str[0]);
705 if( ( id = itemdb_exists(nameid) ) == NULL )
707 ShowWarning("itemdb_read_noequip: Invalid item id %hu.\n", nameid);
712 id->flag.no_equip |= flag;
714 id->flag.no_equip &= ~abs(flag);
719 /** Reads item trade restrictions [Skotlex]
720 * Structure: <nameid>,<mask>,<gm level>
722 static bool itemdb_read_itemtrade(char* str[], int columns, int current) {
723 unsigned short nameid, flag, gmlv;
724 struct item_data *id;
726 nameid = atoi(str[0]);
728 if( ( id = itemdb_exists(nameid) ) == NULL )
730 //ShowWarning("itemdb_read_itemtrade: Invalid item id %d.\n", nameid);
732 // FIXME: item_trade.txt contains items, which are commented in item database.
739 if( flag > 511 ) {//Check range
740 ShowWarning("itemdb_read_itemtrade: Invalid trading mask %hu for item id %hu.\n", flag, nameid);
745 ShowWarning("itemdb_read_itemtrade: Invalid override GM level %hu for item id %hu.\n", gmlv, nameid);
749 id->flag.trade_restriction = flag;
750 id->gm_lv_trade_override = gmlv;
755 /** Reads item delay amounts [Paradox924X]
756 * Structure: <nameid>,<delay>{,<delay sc group>}
758 static bool itemdb_read_itemdelay(char* str[], int columns, int current) {
759 unsigned short nameid;
761 struct item_data *id;
763 nameid = atoi(str[0]);
765 if( ( id = itemdb_exists(nameid) ) == NULL )
767 ShowWarning("itemdb_read_itemdelay: Invalid item id %hu.\n", nameid);
771 delay = atoi(str[1]);
775 ShowWarning("itemdb_read_itemdelay: Invalid delay %d for item id %hu.\n", delay, nameid);
782 id->delay_sc = SC_NONE;
783 else if( ISDIGIT(str[2][0]) )
784 id->delay_sc = atoi(str[2]);
785 else{ // Try read sc group id from const db
788 if( !script_get_constant(trim(str[2]), &constant) ){
789 ShowWarning("itemdb_read_itemdelay: Invalid sc group \"%s\" for item id %hu.\n", str[2], nameid);
793 id->delay_sc = (short)constant;
799 /** Reads item stacking restrictions
800 * Structure: <item id>,<stack limit amount>,<type>
802 static bool itemdb_read_stack(char* fields[], int columns, int current) {
803 unsigned short nameid, amount;
805 struct item_data* id;
807 nameid = (unsigned short)strtoul(fields[0], NULL, 10);
809 if( ( id = itemdb_exists(nameid) ) == NULL )
811 ShowWarning("itemdb_read_stack: Unknown item id '%hu'.\n", nameid);
815 if( !itemdb_isstackable2(id) )
817 ShowWarning("itemdb_read_stack: Item id '%hu' is not stackable.\n", nameid);
821 amount = (unsigned short)strtoul(fields[1], NULL, 10);
822 type = strtoul(fields[2], NULL, 10);
829 id->stack.amount = amount;
830 id->stack.inventory = (type&1)!=0;
831 id->stack.cart = (type&2)!=0;
832 id->stack.storage = (type&4)!=0;
833 id->stack.guildstorage = (type&8)!=0;
838 /** Reads items allowed to be sold in buying stores
841 static bool itemdb_read_buyingstore(char* fields[], int columns, int current) {
842 unsigned short nameid;
843 struct item_data* id;
845 nameid = atoi(fields[0]);
847 if( ( id = itemdb_exists(nameid) ) == NULL )
849 ShowWarning("itemdb_read_buyingstore: Invalid item id %hu.\n", nameid);
853 if( !itemdb_isstackable2(id) )
855 ShowWarning("itemdb_read_buyingstore: Non-stackable item id %hu cannot be enabled for buying store.\n", nameid);
859 id->flag.buyingstore = true;
864 /** Item usage restriction (item_nouse.txt)
865 * <nameid>,<flag>,<override>
867 static bool itemdb_read_nouse(char* fields[], int columns, int current) {
868 unsigned short nameid, flag, override;
869 struct item_data* id;
871 nameid = atoi(fields[0]);
873 if( ( id = itemdb_exists(nameid) ) == NULL ) {
874 ShowWarning("itemdb_read_nouse: Invalid item id %hu.\n", nameid);
878 flag = atoi(fields[1]);
879 override = atoi(fields[2]);
881 id->item_usage.flag = flag;
882 id->item_usage.override = override;
889 * &1 - As dead branch item
890 * &2 - As item container
891 * &4 - GUID item, cannot be stacked even same or stackable item
893 static bool itemdb_read_flag(char* fields[], int columns, int current) {
894 unsigned short nameid = atoi(fields[0]);
897 struct item_data *id;
899 if (!(id = itemdb_exists(nameid))) {
900 ShowError("itemdb_read_flag: Invalid item item with id %hu\n", nameid);
904 flag = abs(atoi(fields[1]));
905 set = atoi(fields[1]) > 0;
907 if (flag&1) id->flag.dead_branch = set ? 1 : 0;
908 if (flag&2) id->flag.group = set ? 1 : 0;
909 if (flag&4 && itemdb_isstackable2(id)) id->flag.guid = set ? 1 : 0;
910 if (flag&8) id->flag.bindOnEquip = true;
911 if (flag&16) id->flag.broadcast = 1;
912 if (flag&32) id->flag.delay_consume = 2;
918 * @return: amount of retrieved entries.
920 static int itemdb_combo_split_atoi (char *str, int *val) {
923 for (i=0; i<MAX_ITEMS_PER_COMBO; i++) {
928 str = strchr(str,':');
934 if( i == 0 ) //No data found.
941 * <combo{:combo{:combo:{..}}}>,<{ script }>
943 static void itemdb_read_combos(const char* basedir, bool silent) {
944 uint32 lines = 0, count = 0;
950 sprintf(path, "%s/%s", basedir, "item_combo_db.txt");
952 if ((fp = fopen(path, "r")) == NULL) {
953 if(silent==0) ShowError("itemdb_read_combos: File not found \"%s\".\n", path);
957 // process rows one by one
958 while(fgets(line, sizeof(line), fp)) {
963 if (line[0] == '/' && line[1] == '/')
966 memset(str, 0, sizeof(str));
973 continue;// empty line
977 /* is there even a single column? */
978 ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, path);
991 if (str[1][0] != '{') {
992 ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
995 /* no ending key anywhere (missing \}\) */
996 if ( str[1][strlen(str[1])-1] != '}' ) {
997 ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
1000 int items[MAX_ITEMS_PER_COMBO];
1001 int v = 0, retcount = 0;
1002 struct item_data * id = NULL;
1004 if((retcount = itemdb_combo_split_atoi(str[0], items)) < 2) {
1005 ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, path);
1009 for(v = 0; v < retcount; v++) {
1010 if( !itemdb_exists(items[v]) ) {
1011 ShowError("itemdb_read_combos: line %d of \"%s\" contains unknown item ID %d, skipping.\n", lines, path,items[v]);
1015 /* failed at some item */
1018 id = itemdb_exists(items[0]);
1019 idx = id->combos_count;
1020 /* first entry, create */
1021 if( id->combos == NULL ) {
1022 CREATE(id->combos, struct item_combo*, 1);
1023 id->combos_count = 1;
1025 RECREATE(id->combos, struct item_combo*, ++id->combos_count);
1027 CREATE(id->combos[idx],struct item_combo,1);
1028 id->combos[idx]->nameid = (unsigned short*)aMalloc( retcount * sizeof(unsigned short) );
1029 id->combos[idx]->count = retcount;
1030 id->combos[idx]->script = parse_script(str[1], path, lines, 0);
1031 id->combos[idx]->id = count;
1032 id->combos[idx]->isRef = false;
1033 /* populate ->nameid field */
1034 for( v = 0; v < retcount; v++ ) {
1035 id->combos[idx]->nameid[v] = items[v];
1038 /* populate the children to refer to this combo */
1039 for( v = 1; v < retcount; v++ ) {
1040 struct item_data * it;
1042 it = itemdb_exists(items[v]);
1043 index = it->combos_count;
1044 if( it->combos == NULL ) {
1045 CREATE(it->combos, struct item_combo*, 1);
1046 it->combos_count = 1;
1048 RECREATE(it->combos, struct item_combo*, ++it->combos_count);
1050 CREATE(it->combos[index],struct item_combo,1);
1051 /* we copy previously alloc'd pointers and just set it to reference */
1052 memcpy(it->combos[index],id->combos[idx],sizeof(struct item_combo));
1053 /* we flag this way to ensure we don't double-dealloc same data */
1054 it->combos[index]->isRef = true;
1056 uidb_put(itemdb_combo,id->combos[idx]->id,id->combos[idx]);
1062 ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",count,path);
1068 * Process Roulette items
1070 bool itemdb_parse_roulette_db(void)
1075 // retrieve all rows from the item database
1076 if (SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", roulette_table)) {
1077 Sql_ShowDebug(mmysql_handle);
1081 for (i = 0; i < MAX_ROULETTE_LEVEL; i++)
1084 for (i = 0; i < MAX_ROULETTE_LEVEL; i++) {
1085 int k, limit = MAX_ROULETTE_COLUMNS - i;
1087 for (k = 0; k < limit && SQL_SUCCESS == Sql_NextRow(mmysql_handle); k++) {
1089 unsigned short item_id, amount;
1092 Sql_GetData(mmysql_handle, 1, &data, NULL); level = atoi(data);
1093 Sql_GetData(mmysql_handle, 2, &data, NULL); item_id = atoi(data);
1094 Sql_GetData(mmysql_handle, 3, &data, NULL); amount = atoi(data);
1095 Sql_GetData(mmysql_handle, 4, &data, NULL); flag = atoi(data);
1097 if (!itemdb_exists(item_id)) {
1098 ShowWarning("itemdb_parse_roulette_db: Unknown item ID '%hu' in level '%d'\n", item_id, level);
1102 ShowWarning("itemdb_parse_roulette_db: Unsupported amount '%hu' for item ID '%hu' in level '%d'\n", amount, item_id, level);
1105 if (flag < 0 || flag > 1) {
1106 ShowWarning("itemdb_parse_roulette_db: Unsupported flag '%d' for item ID '%hu' in level '%d'\n", flag, item_id, level);
1111 RECREATE(rd.nameid[i], unsigned short, ++rd.items[i]);
1112 RECREATE(rd.qty[i], unsigned short, rd.items[i]);
1113 RECREATE(rd.flag[i], int, rd.items[i]);
1115 rd.nameid[i][j] = item_id;
1116 rd.qty[i][j] = amount;
1117 rd.flag[i][j] = flag;
1123 // free the query result
1124 Sql_FreeResult(mmysql_handle);
1126 for (i = 0; i < MAX_ROULETTE_LEVEL; i++) {
1127 int limit = MAX_ROULETTE_COLUMNS - i;
1129 if (rd.items[i] == limit)
1132 if (rd.items[i] > limit) {
1133 ShowWarning("itemdb_parse_roulette_db: level %d has %d items, only %d supported, capping...\n", i + 1, rd.items[i], limit);
1134 rd.items[i] = limit;
1138 /** this scenario = rd.items[i] < limit **/
1139 ShowWarning("itemdb_parse_roulette_db: Level %d has %d items, %d are required. Filling with Apples...\n", i + 1, rd.items[i], limit);
1141 rd.items[i] = limit;
1142 RECREATE(rd.nameid[i], unsigned short, rd.items[i]);
1143 RECREATE(rd.qty[i], unsigned short, rd.items[i]);
1144 RECREATE(rd.flag[i], int, rd.items[i]);
1146 for (j = 0; j < MAX_ROULETTE_COLUMNS - i; j++) {
1150 rd.nameid[i][j] = ITEMID_APPLE;
1156 ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, roulette_table);
1162 * Free Roulette items
1164 static void itemdb_roulette_free(void) {
1167 for (i = 0; i < MAX_ROULETTE_LEVEL; i++) {
1169 aFree(rd.nameid[i]);
1174 rd.nameid[i] = NULL;
1181 /*======================================
1182 * Applies gender restrictions according to settings. [Skotlex]
1183 *======================================*/
1184 static char itemdb_gendercheck(struct item_data *id)
1186 if (id->nameid == WEDDING_RING_M) //Grom Ring
1188 if (id->nameid == WEDDING_RING_F) //Bride Ring
1190 if (id->look == W_MUSICAL && id->type == IT_WEAPON) //Musical instruments are always male-only
1192 if (id->look == W_WHIP && id->type == IT_WEAPON) //Whips are always female-only
1195 return (battle_config.ignore_items_gender) ? 2 : id->sex;
1200 * For backwards compatibility, in Renewal mode, MATK from weapons comes from the atk slot
1201 * We use a ':' delimiter which, if not found, assumes the weapon does not provide any matk.
1203 static void itemdb_re_split_atoi(char *str, int *val1, int *val2) {
1206 for (i=0; i<2; i++) {
1209 str = strchr(str,':');
1215 return;//no data found
1217 if( i == 1 ) {//Single Value
1222 //We assume we have 2 values.
1229 * Processes one itemdb entry
1231 static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt) {
1233 +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
1234 | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
1235 +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
1236 | 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 |
1237 +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
1239 unsigned short nameid;
1240 struct item_data* id;
1242 if( atoi(str[0]) <= 0 || atoi(str[0]) >= MAX_ITEMID || atoi(str[0]) == dummy_item->nameid )
1244 ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", atoi(str[0]), line, source);
1247 nameid = atoi(str[0]);
1249 //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View
1250 if (!(id = itemdb_exists(nameid)))
1251 id = itemdb_create_item(nameid);
1253 safestrncpy(id->name, str[1], sizeof(id->name));
1254 safestrncpy(id->jname, str[2], sizeof(id->jname));
1256 id->type = atoi(str[3]);
1258 if( id->type < 0 || id->type == IT_UNKNOWN || id->type == IT_UNKNOWN2 || ( id->type > IT_SHADOWGEAR && id->type < IT_CASH ) || id->type >= IT_MAX )
1259 {// catch invalid item types
1260 ShowWarning("itemdb_parse_dbrow: Invalid item type %d for item %hu. IT_ETC will be used.\n", id->type, nameid);
1264 if (id->type == IT_DELAYCONSUME)
1265 { //Items that are consumed only after target confirmation
1266 id->type = IT_USABLE;
1267 id->flag.delay_consume = 1;
1268 } else //In case of an itemdb reload and the item type changed.
1269 id->flag.delay_consume = 0;
1271 //When a particular price is not given, we should base it off the other one
1272 //(it is important to make a distinction between 'no price' and 0z)
1274 id->value_buy = atoi(str[4]);
1276 id->value_buy = atoi(str[5]) * 2;
1279 id->value_sell = atoi(str[5]);
1281 id->value_sell = id->value_buy / 2;
1283 if ( !str[4][0] && !str[5][0])
1285 ShowWarning("itemdb_parse_dbrow: No buying/selling price defined for item %hu (%s), using 20/10z\n", nameid, id->jname);
1287 id->value_sell = 10;
1290 if (id->value_buy/124. < id->value_sell/75.)
1291 ShowWarning("itemdb_parse_dbrow: Buying/Selling [%d/%d] price of item %hu (%s) allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n",
1292 id->value_buy, id->value_sell, nameid, id->jname);
1294 id->weight = atoi(str[6]);
1296 itemdb_re_split_atoi(str[7],&id->atk,&id->matk);
1298 id->atk = atoi(str[7]);
1300 id->def = atoi(str[8]);
1301 id->range = atoi(str[9]);
1302 id->slot = atoi(str[10]);
1304 if (id->slot > MAX_SLOTS)
1306 ShowWarning("itemdb_parse_dbrow: Item %hu (%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);
1307 id->slot = MAX_SLOTS;
1310 itemdb_jobid2mapid(id->class_base, (uint64)strtoull(str[11],NULL,0));
1311 id->class_upper = atoi(str[12]);
1312 id->sex = atoi(str[13]);
1313 id->equip = atoi(str[14]);
1315 if (!id->equip && itemdb_isequip2(id))
1317 ShowWarning("Item %hu (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname);
1321 if( id->type != IT_SHADOWGEAR && id->equip&EQP_SHADOW_GEAR )
1323 ShowWarning("Item %hu (%s) have invalid equipment slot! Making it an etc item.\n", nameid, id->jname);
1327 id->wlv = cap_value(atoi(str[15]), REFINE_TYPE_ARMOR, REFINE_TYPE_MAX);
1328 itemdb_re_split_atoi(str[16],&id->elv,&id->elvmax);
1329 id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this
1330 id->look = atoi(str[18]);
1332 id->flag.available = 1;
1334 id->sex = itemdb_gendercheck(id); //Apply gender filtering.
1337 script_free_code(id->script);
1340 if (id->equip_script) {
1341 script_free_code(id->equip_script);
1342 id->equip_script = NULL;
1344 if (id->unequip_script) {
1345 script_free_code(id->unequip_script);
1346 id->unequip_script = NULL;
1350 id->script = parse_script(str[19], source, line, scriptopt);
1352 id->equip_script = parse_script(str[20], source, line, scriptopt);
1354 id->unequip_script = parse_script(str[21], source, line, scriptopt);
1357 id->nameid = nameid;
1358 uidb_put(itemdb, nameid, id);
1364 * Read item from item db
1365 * item_db2 overwriting item_db
1367 static int itemdb_readdb(void){
1368 const char* filename[] = {
1369 DBPATH"item_db.txt",
1370 DBIMPORT"/item_db.txt"
1375 for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) {
1376 uint32 lines = 0, count = 0;
1382 sprintf(path, "%s/%s", db_path, filename[fi]);
1383 fp = fopen(path, "r");
1385 ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path);
1389 // process rows one by one
1390 while(fgets(line, sizeof(line), fp))
1395 if(line[0] == '/' && line[1] == '/')
1397 memset(str, 0, sizeof(str));
1400 while( ISSPACE(*p) )
1403 continue;// empty line
1404 for( i = 0; i < 19; ++i )
1409 break;// comma not found
1416 ShowError("itemdb_readdb: Insufficient columns in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
1423 ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
1427 p = strstr(p+1,"},");
1430 ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
1439 ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
1443 p = strstr(p+1,"},");
1446 ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
1452 // OnUnequip_Script (last column)
1455 ShowError("itemdb_readdb: Invalid format (OnUnequip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
1460 if ( str[21][strlen(str[21])-2] != '}' ) {
1461 /* lets count to ensure it's not something silly e.g. a extra space at line ending */
1462 int v, lcurly = 0, rcurly = 0;
1464 for( v = 0; v < strlen(str[21]); v++ ) {
1465 if( str[21][v] == '{' )
1467 else if ( str[21][v] == '}' )
1471 if( lcurly != rcurly ) {
1472 ShowError("itemdb_readdb: Mismatching curly braces in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
1477 if (!itemdb_parse_dbrow(str, path, lines, 0))
1485 ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, path);
1492 * Read item_db table
1494 static int itemdb_read_sqldb(void) {
1496 const char* item_db_name[] = {
1502 for( fi = 0; fi < ARRAYLENGTH(item_db_name); ++fi ) {
1503 uint32 lines = 0, count = 0;
1505 // retrieve all rows from the item database
1506 if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", item_db_name[fi]) ) {
1507 Sql_ShowDebug(mmysql_handle);
1511 // process rows one by one
1512 while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) {// wrap the result into a TXT-compatible format
1517 for( i = 0; i < 22; ++i ) {
1518 Sql_GetData(mmysql_handle, i, &str[i], NULL);
1519 if( str[i] == NULL )
1520 str[i] = dummy; // get rid of NULL columns
1523 if (!itemdb_parse_dbrow(str, item_db_name[fi], lines, SCRIPT_IGNORE_EXTERNAL_BRACKETS))
1528 // free the query result
1529 Sql_FreeResult(mmysql_handle);
1531 ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, item_db_name[fi]);
1537 /** Check if the item is restricted by item_noequip.txt
1538 * @param id Item that will be checked
1540 * @return true: can't be used; false: can be used
1542 bool itemdb_isNoEquip(struct item_data *id, uint16 m) {
1543 if (!id->flag.no_equip)
1545 if ((!map_flag_vs2(m) && id->flag.no_equip&1) || // Normal
1546 (map[m].flag.pvp && id->flag.no_equip&2) || // PVP
1547 (map_flag_gvg2_no_te(m) && id->flag.no_equip&4) || // GVG
1548 (map[m].flag.battleground && id->flag.no_equip&8) || // Battleground
1549 (map_flag_gvg2_te(m) && id->flag.no_equip&16) || // WOE:TE
1550 (map[m].flag.restricted && id->flag.no_equip&(8*map[m].zone)) // Zone restriction
1557 * Check if item is available in spellbook_db or not
1559 * @return True if item is spellbook; False if not
1561 bool itemdb_is_spellbook2(unsigned short nameid) {
1563 if (!nameid || !itemdb_exists(nameid) || !skill_spellbook_count)
1565 ARR_FIND(0, MAX_SKILL_SPELLBOOK_DB, i, skill_spellbook_db[i].nameid == nameid);
1566 return i == MAX_SKILL_SPELLBOOK_DB ? false : true;
1570 * Retrieves random option data
1572 struct s_random_opt_data* itemdb_randomopt_exists(short id) {
1573 return ((struct s_random_opt_data*)uidb_get(itemdb_randomopt, id));
1579 static bool itemdb_read_randomopt(const char* basedir, bool silent) {
1580 uint32 lines = 0, count = 0;
1586 sprintf(path, "%s/%s", basedir, "item_randomopt_db.txt");
1588 if ((fp = fopen(path, "r")) == NULL) {
1589 if (silent == 0) ShowError("itemdb_read_randomopt: File not found \"%s\".\n", path);
1593 while (fgets(line, sizeof(line), fp)) {
1598 if (line[0] == '/' && line[1] == '/') // Ignore comments
1601 memset(str, 0, sizeof(str));
1608 continue;// empty line
1610 if (!strchr(p, ','))
1612 ShowError("itemdb_read_randomopt: Insufficient columns in line %d of \"%s\", skipping.\n", lines, path);
1623 if (str[1][0] != '{') {
1624 ShowError("itemdb_read_randomopt(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
1627 /* no ending key anywhere (missing \}\) */
1628 if (str[1][strlen(str[1]) - 1] != '}') {
1629 ShowError("itemdb_read_randomopt(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
1634 struct s_random_opt_data *data;
1635 struct script_code *code;
1637 str[0] = trim(str[0]);
1638 if (ISDIGIT(str[0][0])) {
1642 script_get_constant(str[0], &id);
1646 ShowError("itemdb_read_randomopt: Invalid Random Option ID '%s' in line %d of \"%s\", skipping.\n", str[0], lines, path);
1650 if ((data = itemdb_randomopt_exists(id)) == NULL) {
1651 CREATE(data, struct s_random_opt_data, 1);
1652 uidb_put(itemdb_randomopt, id, data);
1655 if ((code = parse_script(str[1], path, lines, 0)) == NULL) {
1656 ShowWarning("itemdb_read_randomopt: Invalid script on option ID #%d.\n", id);
1660 script_free_code(data->script);
1661 data->script = NULL;
1663 data->script = code;
1669 ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, path);
1675 * Clear Item Random Option Group from memory
1678 static int itemdb_randomopt_group_free(DBKey key, DBData *data, va_list ap) {
1679 struct s_random_opt_group *g = (struct s_random_opt_group *)db_data2ptr(data);
1690 * Get Item Random Option Group from itemdb_randomopt_group MapDB
1691 * @param id Random Option Group
1692 * @return Random Option Group data or NULL if not found
1695 struct s_random_opt_group *itemdb_randomopt_group_exists(int id) {
1696 return (struct s_random_opt_group *)uidb_get(itemdb_randomopt_group, id);
1700 * Read Item Random Option Group from db file
1703 static bool itemdb_read_randomopt_group(char* str[], int columns, int current) {
1705 unsigned short rate = (unsigned short)strtoul(str[1], NULL, 10);
1706 struct s_random_opt_group *g = NULL;
1708 if (!script_get_constant(str[0], &id)) {
1709 ShowError("itemdb_read_randomopt_group: Invalid ID for Random Option Group '%s'.\n", str[0]);
1713 if ((columns-2)%3 != 0) {
1714 ShowError("itemdb_read_randomopt_group: Invalid column entries '%d'.\n", columns);
1718 if (!(g = (struct s_random_opt_group *)uidb_get(itemdb_randomopt_group, id))) {
1719 CREATE(g, struct s_random_opt_group, 1);
1723 uidb_put(itemdb_randomopt_group, g->id, g);
1726 RECREATE(g->entries, struct s_random_opt_group_entry, g->total + rate);
1728 for (i = g->total; i < (g->total + rate); i++) {
1730 memset(&g->entries[i].option, 0, sizeof(g->entries[i].option));
1731 for (j = 0, k = 2; k < columns && j < MAX_ITEM_RDM_OPT; k+=3) {
1733 if (!script_get_constant(str[k], &randid) || !itemdb_randomopt_exists(randid)) {
1734 ShowError("itemdb_read_randomopt_group: Invalid random group id '%s' in column %d!\n", str[k], k+1);
1737 g->entries[i].option[j].id = randid;
1738 g->entries[i].option[j].value = (short)strtoul(str[k+1], NULL, 10);
1739 g->entries[i].option[j].param = (char)strtoul(str[k+2], NULL, 10);
1748 * Read all item-related databases
1750 static void itemdb_read(void) {
1752 const char* dbsubpath[] = {
1758 itemdb_read_sqldb();
1762 for(i=0; i<ARRAYLENGTH(dbsubpath); i++){
1763 uint8 n1 = (uint8)(strlen(db_path)+strlen(dbsubpath[i])+1);
1764 uint8 n2 = (uint8)(strlen(db_path)+strlen(DBPATH)+strlen(dbsubpath[i])+1);
1765 char* dbsubpath1 = (char*)aMalloc(n1+1);
1766 char* dbsubpath2 = (char*)aMalloc(n2+1);
1770 safesnprintf(dbsubpath1,n1,"%s%s",db_path,dbsubpath[i]);
1771 safesnprintf(dbsubpath2,n2,"%s/%s%s",db_path,DBPATH,dbsubpath[i]);
1774 safesnprintf(dbsubpath1,n1,"%s%s",db_path,dbsubpath[i]);
1775 safesnprintf(dbsubpath2,n1,"%s%s",db_path,dbsubpath[i]);
1778 sv_readdb(dbsubpath1, "item_avail.txt", ',', 2, 2, -1, &itemdb_read_itemavail, i);
1779 sv_readdb(dbsubpath2, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack, i);
1780 sv_readdb(dbsubpath1, "item_nouse.txt", ',', 3, 3, -1, &itemdb_read_nouse, i);
1781 sv_readdb(dbsubpath2, "item_group_db.txt", ',', 2, 10, -1, &itemdb_read_group, i);
1782 sv_readdb(dbsubpath2, "item_bluebox.txt", ',', 2, 10, -1, &itemdb_read_group, i);
1783 sv_readdb(dbsubpath2, "item_violetbox.txt", ',', 2, 10, -1, &itemdb_read_group, i);
1784 sv_readdb(dbsubpath2, "item_cardalbum.txt", ',', 2, 10, -1, &itemdb_read_group, i);
1785 sv_readdb(dbsubpath1, "item_findingore.txt", ',', 2, 10, -1, &itemdb_read_group, i);
1786 sv_readdb(dbsubpath2, "item_giftbox.txt", ',', 2, 10, -1, &itemdb_read_group, i);
1787 sv_readdb(dbsubpath2, "item_misc.txt", ',', 2, 10, -1, &itemdb_read_group, i);
1789 sv_readdb(dbsubpath2, "item_package.txt", ',', 2, 10, -1, &itemdb_read_group, i);
1791 itemdb_read_combos(dbsubpath2,i); //TODO change this to sv_read ? id#script ?
1792 itemdb_read_randomopt(dbsubpath2, i);
1793 sv_readdb(dbsubpath2, "item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip, i);
1794 sv_readdb(dbsubpath2, "item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade, i);
1795 sv_readdb(dbsubpath2, "item_delay.txt", ',', 2, 3, -1, &itemdb_read_itemdelay, i);
1796 sv_readdb(dbsubpath2, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore, i);
1797 sv_readdb(dbsubpath2, "item_flag.txt", ',', 2, 2, -1, &itemdb_read_flag, i);
1798 sv_readdb(dbsubpath2, "item_randomopt_group.txt", ',', 5, 2+5*MAX_ITEM_RDM_OPT, -1, &itemdb_read_randomopt_group, i);
1804 /*==========================================
1805 * Initialize / Finalize
1806 *------------------------------------------*/
1809 * Destroys the item_data.
1811 static void destroy_item_data(struct item_data* self) {
1816 script_free_code(self->script);
1817 if( self->equip_script )
1818 script_free_code(self->equip_script);
1819 if( self->unequip_script )
1820 script_free_code(self->unequip_script);
1821 if( self->combos_count ) {
1823 for( i = 0; i < self->combos_count; i++ ) {
1824 if( !self->combos[i]->isRef ) {
1825 aFree(self->combos[i]->nameid);
1826 if (self->combos[i]->script)
1827 script_free_code(self->combos[i]->script);
1829 aFree(self->combos[i]);
1831 aFree(self->combos);
1835 memset(self, 0xDD, sizeof(struct item_data));
1844 static int itemdb_final_sub(DBKey key, DBData *data, va_list ap)
1846 struct item_data *id = (struct item_data *)db_data2ptr(data);
1848 destroy_item_data(id);
1853 * In some OSs, like Raspbian, we aren't allowed to pass 0 in va_list.
1854 * So, itemdb_group_free2 is useful in some cases.
1855 * NB : We keeping that funciton cause that signature is needed for some iterator..
1857 static int itemdb_group_free(DBKey key, DBData *data, va_list ap) {
1858 return itemdb_group_free2(key,data);
1862 * Adaptation of itemdb_group_free. This function enables to compile rAthena on Raspbian OS.
1864 static inline int itemdb_group_free2(DBKey key, DBData *data) {
1865 struct s_item_group_db *group = (struct s_item_group_db *)db_data2ptr(data);
1869 if (group->must_qty)
1871 group->must_qty = 0;
1872 for (j = 0; j < MAX_ITEMGROUP_RANDGROUP; j++) {
1873 if (!group->random[j].data_qty || !(&group->random[j]))
1875 aFree(group->random[j].data);
1876 group->random[j].data_qty = 0;
1882 static int itemdb_randomopt_free(DBKey key, DBData *data, va_list ap) {
1883 struct s_random_opt_data *opt = (struct s_random_opt_data *)db_data2ptr(data);
1887 script_free_code(opt->script);
1894 * Re-link monster drop data with item data
1895 * Fixes the need of a @reloadmobdb after a @reloaditemdb
1898 void itemdb_reload_itemmob_data(void) {
1901 for( i = 0; i < MAX_MOB_DB; i++ ) {
1902 struct mob_db *entry = mob_db(i);
1905 for(d = 0; d < MAX_MOB_DROP_TOTAL; d++) {
1906 struct item_data *id;
1907 if( !entry->dropitem[d].nameid )
1909 id = itemdb_search(entry->dropitem[d].nameid);
1911 for (k = 0; k < MAX_SEARCH; k++) {
1912 if (id->mob[k].chance <= entry->dropitem[d].p)
1916 if (k == MAX_SEARCH)
1919 if (id->mob[k].id != i)
1920 memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0]));
1921 id->mob[k].chance = entry->dropitem[d].p;
1930 void itemdb_reload(void) {
1931 struct s_mapiterator* iter;
1932 struct map_session_data* sd;
1934 itemdb_group->clear(itemdb_group, itemdb_group_free);
1935 itemdb_randomopt->clear(itemdb_randomopt, itemdb_randomopt_free);
1936 itemdb_randomopt_group->clear(itemdb_randomopt_group, itemdb_randomopt_group_free);
1937 itemdb->clear(itemdb, itemdb_final_sub);
1938 db_clear(itemdb_combo);
1939 if (battle_config.feature_roulette)
1940 itemdb_roulette_free();
1944 cashshop_reloaddb();
1946 if (battle_config.feature_roulette)
1947 itemdb_parse_roulette_db();
1949 itemdb_reload_itemmob_data();
1951 // readjust itemdb pointer cache for each player
1952 iter = mapit_geteachpc();
1953 for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) ) {
1954 memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays
1955 pc_setinventorydata(sd);
1956 pc_check_available_item(sd, ITMCHK_ALL); // Check for invalid(ated) items.
1957 /* clear combo bonuses */
1958 if( sd->combos.count ) {
1959 aFree(sd->combos.bonus);
1960 aFree(sd->combos.id);
1961 aFree(sd->combos.pos);
1962 sd->combos.bonus = NULL;
1963 sd->combos.id = NULL;
1964 sd->combos.pos = NULL;
1965 sd->combos.count = 0;
1966 if( pc_load_combo(sd) > 0 )
1967 status_calc_pc(sd, SCO_FORCE);
1975 * Finalizing Item DB
1977 void do_final_itemdb(void) {
1978 db_destroy(itemdb_combo);
1979 itemdb_group->destroy(itemdb_group, itemdb_group_free);
1980 itemdb_randomopt->destroy(itemdb_randomopt, itemdb_randomopt_free);
1981 itemdb_randomopt_group->destroy(itemdb_randomopt_group, itemdb_randomopt_group_free);
1982 itemdb->destroy(itemdb, itemdb_final_sub);
1983 destroy_item_data(dummy_item);
1984 if (battle_config.feature_roulette)
1985 itemdb_roulette_free();
1989 * Initializing Item DB
1991 void do_init_itemdb(void) {
1992 itemdb = uidb_alloc(DB_OPT_BASE);
1993 itemdb_combo = uidb_alloc(DB_OPT_BASE);
1994 itemdb_group = uidb_alloc(DB_OPT_BASE);
1995 itemdb_randomopt = uidb_alloc(DB_OPT_BASE);
1996 itemdb_randomopt_group = uidb_alloc(DB_OPT_BASE);
1997 itemdb_create_dummy();
2000 if (battle_config.feature_roulette)
2001 itemdb_parse_roulette_db();