summaryrefslogtreecommitdiff
path: root/src/map/itemdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/itemdb.c')
-rw-r--r--src/map/itemdb.c1112
1 files changed, 817 insertions, 295 deletions
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index c59f627cc..2b8200c06 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
#include "map/map.h"
#include "map/mob.h" // MAX_MOB_DB
#include "map/pc.h" // W_MUSICAL, W_WHIP
+#include "map/refine.h"
#include "map/script.h" // item script processing
#include "common/HPM.h"
#include "common/conf.h"
@@ -41,7 +42,7 @@
#include <stdlib.h>
#include <string.h>
-struct itemdb_interface itemdb_s;
+static struct itemdb_interface itemdb_s;
struct itemdb_interface *itemdb;
/**
@@ -49,7 +50,7 @@ struct itemdb_interface *itemdb;
* name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
* @see DBApply
*/
-int itemdb_searchname_sub(union DBKey key, struct DBData *data, va_list ap)
+static int itemdb_searchname_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct item_data *item = DB->data2ptr(data), **dst, **dst2;
char *str;
@@ -78,7 +79,8 @@ int itemdb_searchname_sub(union DBKey key, struct DBData *data, va_list ap)
/*==========================================
* Return item data from item name. (lookup)
*------------------------------------------*/
-struct item_data* itemdb_searchname(const char *str) {
+static struct item_data *itemdb_searchname(const char *str)
+{
struct item_data* item;
struct item_data* item2=NULL;
int i;
@@ -105,83 +107,118 @@ struct item_data* itemdb_searchname(const char *str) {
return item?item:item2;
}
/* name to item data */
-struct item_data* itemdb_name2id(const char *str) {
+static struct item_data *itemdb_name2id(const char *str)
+{
return strdb_get(itemdb->names,str);
}
/**
* @see DBMatcher
*/
-int itemdb_searchname_array_sub(union DBKey key, struct DBData data, va_list ap)
+static int itemdb_searchname_array_sub(union DBKey key, struct DBData data, va_list ap)
{
- struct item_data *item = DB->data2ptr(&data);
- char *str;
- str=va_arg(ap,char *);
+ struct item_data *itd = DB->data2ptr(&data);
+ const char *str = va_arg(ap, const char *);
+ enum item_name_search_flag flag = va_arg(ap, enum item_name_search_flag);
+
nullpo_ret(str);
- if (item == &itemdb->dummy)
+
+ if (itd == &itemdb->dummy)
return 1; //Invalid item.
- if(stristr(item->jname,str))
- return 0;
- if(battle_config.case_sensitive_aegisnames && strstr(item->name,str))
- return 0;
- if(!battle_config.case_sensitive_aegisnames && stristr(item->name,str))
+
+ if (
+ (flag == IT_SEARCH_NAME_PARTIAL
+ && (stristr(itd->jname, str) != NULL
+ || (battle_config.case_sensitive_aegisnames && strstr(itd->name, str))
+ || (!battle_config.case_sensitive_aegisnames && stristr(itd->name, str))
+ ))
+ || (flag == IT_SEARCH_NAME_EXACT
+ && (strcmp(itd->jname, str) == 0
+ || (battle_config.case_sensitive_aegisnames && strcmp(itd->name, str) == 0)
+ || (!battle_config.case_sensitive_aegisnames && strcasecmp(itd->name, str) == 0)
+ ))
+ ) {
+
return 0;
- return strcmpi(item->jname,str);
+ } else {
+ return 1;
+ }
}
-/*==========================================
- * Founds up to N matches. Returns number of matches [Skotlex]
- * search flag :
- * 0 - approximate match
- * 1 - exact match
- *------------------------------------------*/
-int itemdb_searchname_array(struct item_data** data, int size, const char *str, int flag) {
- struct item_data* item;
- int i;
- int count=0;
-
+/**
+ * Finds up to passed size matches
+ * @param data array of struct item_data for returning the results in
+ * @param size size of the array
+ * @param str string used in this search
+ * @param flag search mode refer to enum item_name_search_flag for possible values
+ * @return returns all found matches in the database which could be bigger than size
+ **/
+static int itemdb_searchname_array(struct item_data **data, const int size, const char *str, enum item_name_search_flag flag)
+{
nullpo_ret(data);
nullpo_ret(str);
- // Search in the array
- for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i )
- {
- item = itemdb->array[i];
- if( item == NULL )
+ Assert_ret(flag >= IT_SEARCH_NAME_PARTIAL && flag < IT_SEARCH_NAME_MAX);
+ Assert_ret(size > 0);
+
+ int
+ results_count = 0,
+ length = 0;
+
+ // Search in array
+ for (int i = 0; i < ARRAYLENGTH(itemdb->array); ++i) {
+ struct item_data *itd = itemdb->array[i];
+
+ if (itd == NULL)
continue;
- if(
- (!flag
- && (stristr(item->jname,str)
- || (battle_config.case_sensitive_aegisnames && strstr(item->name,str))
- || (!battle_config.case_sensitive_aegisnames && stristr(item->name,str))
- ))
- || (flag
- && (strcmp(item->jname,str) == 0
- || (battle_config.case_sensitive_aegisnames && strcmp(item->name,str) == 0)
- || (!battle_config.case_sensitive_aegisnames && strcasecmp(item->name,str) == 0)
- ))
- ) {
- if( count < size )
- data[count] = item;
- ++count;
+ if (
+ (flag == IT_SEARCH_NAME_PARTIAL
+ && (stristr(itd->jname, str) != NULL
+ || (battle_config.case_sensitive_aegisnames && strstr(itd->name, str))
+ || (!battle_config.case_sensitive_aegisnames && stristr(itd->name, str))
+ ))
+ || (flag == IT_SEARCH_NAME_EXACT
+ && (strcmp(itd->jname, str) == 0
+ || (battle_config.case_sensitive_aegisnames && strcmp(itd->name, str) == 0)
+ || (!battle_config.case_sensitive_aegisnames && strcasecmp(itd->name, str) == 0)
+ ))
+ ) {
+ if (length < size) {
+ data[length] = itd;
+ ++length;
+ }
+
+ ++results_count;
}
}
- // search in the db
- if( count < size )
- {
- struct DBData *db_data[MAX_SEARCH];
- int db_count = 0;
- size -= count;
- db_count = itemdb->other->getall(itemdb->other, (struct DBData**)&db_data, size, itemdb->searchname_array_sub, str);
- for (i = 0; i < db_count; i++)
- data[count++] = DB->data2ptr(db_data[i]);
- count += db_count;
+ // Search in dbmap
+ int dbmap_size = size - length;
+ if (dbmap_size > 0) {
+ struct DBData **dbmap_data = NULL;
+ int dbmap_count = 0;
+ CREATE(dbmap_data, struct DBData *, dbmap_size);
+
+ dbmap_count = itemdb->other->getall(itemdb->other, dbmap_data, dbmap_size, itemdb->searchname_array_sub, str, flag);
+ dbmap_size = min(dbmap_count, dbmap_size);
+
+ for (int i = 0; i < dbmap_size; ++i) {
+ data[length] = DB->data2ptr(dbmap_data[i]);
+ ++length;
+ }
+
+ results_count += dbmap_count;
+ aFree(dbmap_data);
+ } else { // We got all matches we can return, so we only need to count now.
+ results_count += itemdb->other->getall(itemdb->other, NULL, 0, itemdb->searchname_array_sub, str, flag);
}
- return count;
+
+ return results_count;
}
+
/* [Ind/Hercules] */
-int itemdb_chain_item(unsigned short chain_id, int *rate) {
+static int itemdb_chain_item(unsigned short chain_id, int *rate)
+{
struct item_chain_entry *entry;
if( chain_id >= itemdb->chain_count ) {
@@ -199,7 +236,8 @@ int itemdb_chain_item(unsigned short chain_id, int *rate) {
return entry->id;
}
/* [Ind/Hercules] */
-void itemdb_package_item(struct map_session_data *sd, struct item_package *package) {
+static void itemdb_package_item(struct map_session_data *sd, struct item_package *package)
+{
int i = 0, get_count, j, flag;
nullpo_retv(sd);
@@ -287,7 +325,8 @@ void itemdb_package_item(struct map_session_data *sd, struct item_package *packa
/*==========================================
* Return a random item id from group. (takes into account % chance giving/tot group)
*------------------------------------------*/
-int itemdb_searchrandomid(struct item_group *group) {
+static int itemdb_searchrandomid(struct item_group *group)
+{
nullpo_retr(UNKNOWN_ITEM_ID, group);
if (group->qty)
@@ -296,7 +335,8 @@ int itemdb_searchrandomid(struct item_group *group) {
ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group->id);
return UNKNOWN_ITEM_ID;
}
-bool itemdb_in_group(struct item_group *group, int nameid) {
+static bool itemdb_in_group(struct item_group *group, int nameid)
+{
int i;
nullpo_retr(false, group);
@@ -309,7 +349,7 @@ bool itemdb_in_group(struct item_group *group, int nameid) {
/// Searches for the item_data.
/// Returns the item_data or NULL if it does not exist.
-struct item_data* itemdb_exists(int nameid)
+static struct item_data *itemdb_exists(int nameid)
{
struct item_data* item;
@@ -321,9 +361,19 @@ struct item_data* itemdb_exists(int nameid)
return item;
}
+/**
+ * Searches for the item_option data.
+ * @param option_index as the index of the item option (client side).
+ * @return pointer to struct itemdb_option data or NULL.
+ */
+static struct itemdb_option *itemdb_option_exists(int idx)
+{
+ return (struct itemdb_option *)idb_get(itemdb->options, idx);
+}
+
/// Returns human readable name for given item type.
/// @param type Type id to retrieve name for ( IT_* ).
-const char* itemdb_typename(int type)
+static const char *itemdb_typename(int type)
{
switch(type)
{
@@ -342,7 +392,7 @@ const char* itemdb_typename(int type)
return "Unknown Type";
}
- /**
+/**
* Converts the JobID to the format used by map-server to check item
* restriction as per job.
*
@@ -352,14 +402,14 @@ const char* itemdb_typename(int type)
*
* @author Dastgir
*/
-void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable)
+static void itemdb_jobid2mapid(uint64 *bclass, int job_class, bool enable)
{
uint64 mask[3] = { 0 };
int i;
nullpo_retv(bclass);
- switch(job_id) {
+ switch (job_class) {
// Base Classes
case JOB_NOVICE:
case JOB_SUPER_NOVICE:
@@ -367,12 +417,22 @@ void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable)
mask[1] = 1ULL << MAPID_NOVICE;
break;
case JOB_SWORDMAN:
+ mask[0] = 1ULL << MAPID_SWORDMAN;
+ break;
case JOB_MAGE:
+ mask[0] = 1ULL << MAPID_MAGE;
+ break;
case JOB_ARCHER:
+ mask[0] = 1ULL << MAPID_ARCHER;
+ break;
case JOB_ACOLYTE:
+ mask[0] = 1ULL << MAPID_ACOLYTE;
+ break;
case JOB_MERCHANT:
+ mask[0] = 1ULL << MAPID_MERCHANT;
+ break;
case JOB_THIEF:
- mask[0] = 1ULL << (MAPID_NOVICE+job_id);
+ mask[0] = 1ULL << MAPID_THIEF;
break;
// 2-1 Classes
case JOB_KNIGHT:
@@ -437,6 +497,9 @@ void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable)
case JOB_REBELLION:
mask[1] = 1ULL << MAPID_GUNSLINGER;
break;
+ case JOB_SUMMONER:
+ mask[0] = 1ULL << MAPID_SUMMONER;
+ break;
// Other Classes
case JOB_GANGSI: //Bongun/Munak
mask[0] = 1ULL << MAPID_GANGSI;
@@ -466,9 +529,8 @@ void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable)
* @param bclass Pointer to the variable containing the new format.
* @param jobmask Variable containing JobMask.
*/
-void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask)
+static void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask)
{
- int i;
nullpo_retv(bclass);
bclass[0] = bclass[1] = bclass[2] = 0;
//Base classes
@@ -477,10 +539,18 @@ void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask)
bclass[0] |= 1ULL<<MAPID_NOVICE;
bclass[1] |= 1ULL<<MAPID_NOVICE;
}
- for (i = JOB_NOVICE+1; i <= JOB_THIEF; i++) {
- if (jobmask & 1ULL<<i)
- bclass[0] |= 1ULL<<(MAPID_NOVICE+i);
- }
+ if (jobmask & 1ULL<<JOB_SWORDMAN)
+ bclass[0] |= 1ULL<<MAPID_SWORDMAN;
+ if (jobmask & 1ULL<<JOB_MAGE)
+ bclass[0] |= 1ULL<<MAPID_MAGE;
+ if (jobmask & 1ULL<<JOB_ARCHER)
+ bclass[0] |= 1ULL<<MAPID_ARCHER;
+ if (jobmask & 1ULL<<JOB_ACOLYTE)
+ bclass[0] |= 1ULL<<MAPID_ACOLYTE;
+ if (jobmask & 1ULL<<JOB_MERCHANT)
+ bclass[0] |= 1ULL<<MAPID_MERCHANT;
+ if (jobmask & 1ULL<<JOB_THIEF)
+ bclass[0] |= 1ULL<<MAPID_THIEF;
//2-1 classes
if (jobmask & 1ULL<<JOB_KNIGHT)
bclass[1] |= 1ULL<<MAPID_SWORDMAN;
@@ -538,9 +608,11 @@ void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask)
bclass[1] |= 1ULL<<MAPID_NINJA;
if (jobmask & 1ULL<<30) //Rebellion
bclass[1] |= 1ULL<<MAPID_GUNSLINGER;
+ if (jobmask & 1ULL<<31) //Summoner
+ bclass[0] |= 1ULL<<MAPID_SUMMONER;
}
-void create_dummy_data(void)
+static void create_dummy_data(void)
{
memset(&itemdb->dummy, 0, sizeof(struct item_data));
itemdb->dummy.nameid=500;
@@ -552,7 +624,7 @@ void create_dummy_data(void)
itemdb->dummy.view_id=UNKNOWN_ITEM_ID;
}
-struct item_data* create_item_data(int nameid)
+static struct item_data *create_item_data(int nameid)
{
struct item_data *id;
CREATE(id, struct item_data, 1);
@@ -565,7 +637,8 @@ struct item_data* create_item_data(int nameid)
/*==========================================
* Loads (and creates if not found) an item from the db.
*------------------------------------------*/
-struct item_data* itemdb_load(int nameid) {
+static struct item_data *itemdb_load(int nameid)
+{
struct item_data *id;
if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb->array) )
@@ -588,7 +661,7 @@ struct item_data* itemdb_load(int nameid) {
/*==========================================
* Loads an item from the db. If not found, it will return the dummy item.
*------------------------------------------*/
-struct item_data* itemdb_search(int nameid)
+static struct item_data *itemdb_search(int nameid)
{
struct item_data* id;
if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb->array) )
@@ -608,7 +681,7 @@ struct item_data* itemdb_search(int nameid)
/*==========================================
* Returns if given item is a player-equippable piece.
*------------------------------------------*/
-int itemdb_isequip(int nameid)
+static int itemdb_isequip(int nameid)
{
int type=itemdb_type(nameid);
switch (type) {
@@ -624,7 +697,8 @@ int itemdb_isequip(int nameid)
/*==========================================
* Alternate version of itemdb_isequip
*------------------------------------------*/
-int itemdb_isequip2(struct item_data *data) {
+static int itemdb_isequip2(struct item_data *data)
+{
nullpo_ret(data);
switch(data->type) {
case IT_WEAPON:
@@ -639,7 +713,7 @@ int itemdb_isequip2(struct item_data *data) {
/*==========================================
* Returns if given item's type is stackable.
*------------------------------------------*/
-int itemdb_isstackable(int nameid)
+static int itemdb_isstackable(int nameid)
{
int type=itemdb_type(nameid);
switch(type) {
@@ -656,7 +730,7 @@ int itemdb_isstackable(int nameid)
/*==========================================
* Alternate version of itemdb_isstackable
*------------------------------------------*/
-int itemdb_isstackable2(struct item_data *data)
+static int itemdb_isstackable2(struct item_data *data)
{
nullpo_ret(data);
switch(data->type) {
@@ -673,43 +747,52 @@ int itemdb_isstackable2(struct item_data *data)
/*==========================================
* Trade Restriction functions [Skotlex]
*------------------------------------------*/
-int itemdb_isdropable_sub(struct item_data *item, int gmlv, int unused) {
+static int itemdb_isdropable_sub(struct item_data *item, int gmlv, int unused)
+{
return (item && (!(item->flag.trade_restriction&ITR_NODROP) || gmlv >= item->gm_lv_trade_override));
}
-int itemdb_cantrade_sub(struct item_data* item, int gmlv, int gmlv2) {
+static int itemdb_cantrade_sub(struct item_data *item, int gmlv, int gmlv2)
+{
return (item && (!(item->flag.trade_restriction&ITR_NOTRADE) || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
}
-int itemdb_canpartnertrade_sub(struct item_data* item, int gmlv, int gmlv2) {
+static int itemdb_canpartnertrade_sub(struct item_data *item, int gmlv, int gmlv2)
+{
return (item && (item->flag.trade_restriction&ITR_PARTNEROVERRIDE || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
}
-int itemdb_cansell_sub(struct item_data* item, int gmlv, int unused) {
+static int itemdb_cansell_sub(struct item_data *item, int gmlv, int unused)
+{
return (item && (!(item->flag.trade_restriction&ITR_NOSELLTONPC) || gmlv >= item->gm_lv_trade_override));
}
-int itemdb_cancartstore_sub(struct item_data* item, int gmlv, int unused) {
+static int itemdb_cancartstore_sub(struct item_data *item, int gmlv, int unused)
+{
return (item && (!(item->flag.trade_restriction&ITR_NOCART) || gmlv >= item->gm_lv_trade_override));
}
-int itemdb_canstore_sub(struct item_data* item, int gmlv, int unused) {
+static int itemdb_canstore_sub(struct item_data *item, int gmlv, int unused)
+{
return (item && (!(item->flag.trade_restriction&ITR_NOSTORAGE) || gmlv >= item->gm_lv_trade_override));
}
-int itemdb_canguildstore_sub(struct item_data* item, int gmlv, int unused) {
+static int itemdb_canguildstore_sub(struct item_data *item, int gmlv, int unused)
+{
return (item && (!(item->flag.trade_restriction&ITR_NOGSTORAGE) || gmlv >= item->gm_lv_trade_override));
}
-int itemdb_canmail_sub(struct item_data* item, int gmlv, int unused) {
+static int itemdb_canmail_sub(struct item_data *item, int gmlv, int unused)
+{
return (item && (!(item->flag.trade_restriction&ITR_NOMAIL) || gmlv >= item->gm_lv_trade_override));
}
-int itemdb_canauction_sub(struct item_data* item, int gmlv, int unused) {
+static int itemdb_canauction_sub(struct item_data *item, int gmlv, int unused)
+{
return (item && (!(item->flag.trade_restriction&ITR_NOAUCTION) || gmlv >= item->gm_lv_trade_override));
}
-int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(struct item_data*, int, int))
+static int itemdb_isrestricted(struct item *item, int gmlv, int gmlv2, int (*func)(struct item_data*, int, int))
{
struct item_data* item_data;
int i;
@@ -733,7 +816,8 @@ int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(stru
/*==========================================
* Specifies if item-type should drop unidentified.
*------------------------------------------*/
-int itemdb_isidentified(int nameid) {
+static int itemdb_isidentified(int nameid)
+{
int type=itemdb_type(nameid);
switch (type) {
case IT_WEAPON:
@@ -745,7 +829,8 @@ int itemdb_isidentified(int nameid) {
}
}
/* same as itemdb_isidentified but without a lookup */
-int itemdb_isidentified2(struct item_data *data) {
+static int itemdb_isidentified2(struct item_data *data)
+{
nullpo_ret(data);
switch (data->type) {
case IT_WEAPON:
@@ -757,14 +842,12 @@ int itemdb_isidentified2(struct item_data *data) {
}
}
-void itemdb_read_groups(void) {
+static void itemdb_read_groups(void)
+{
struct config_t item_group_conf;
struct config_setting_t *itg = NULL, *it = NULL;
-#ifdef RENEWAL
- const char *config_filename = "db/re/item_group.conf"; // FIXME hardcoded name
-#else
- const char *config_filename = "db/pre-re/item_group.conf"; // FIXME hardcoded name
-#endif
+ char config_filename[256];
+ libconfig->format_db_path(DBPATH"item_group.conf", config_filename, sizeof(config_filename));
const char *itname;
int i = 0, count = 0, c;
unsigned int *gsize = NULL;
@@ -810,7 +893,7 @@ void itemdb_read_groups(void) {
itemdb->groups[count].id = data->nameid;
itemdb->groups[count].qty = gsize[ count ];
- CREATE(itemdb->groups[count].nameid, unsigned short, gsize[ count ] + 1);
+ CREATE(itemdb->groups[count].nameid, int, gsize[count] + 1);
c = 0;
while( (it = libconfig->setting_get_elem(itg,c++)) ) {
int repeat = 1;
@@ -820,7 +903,7 @@ void itemdb_read_groups(void) {
} else
itname = libconfig->setting_get_string_elem(itg,c - 1);
- if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) {
+ if (itname[0] == 'I' && itname[1] == 'D' && strlen(itname) <= 12) {
if( !( data = itemdb->exists(atoi(itname+2)) ) )
ShowWarning("itemdb_read_groups: unknown item ID '%d' in group '%s'!\n",atoi(itname+2),config_setting_name(itg));
} else if( !( data = itemdb->name2id(itname) ) )
@@ -845,7 +928,8 @@ void itemdb_read_groups(void) {
}
/* [Ind/Hercules] - HCache for Packages */
-void itemdb_write_cached_packages(const char *config_filename) {
+static void itemdb_write_cached_packages(const char *config_filename)
+{
FILE *file;
unsigned short pcount = itemdb->package_count;
unsigned short i;
@@ -859,7 +943,8 @@ void itemdb_write_cached_packages(const char *config_filename) {
hwrite(&pcount,sizeof(pcount),1,file);
for(i = 0; i < pcount; i++) {
- unsigned short id = itemdb->packages[i].id, random_qty = itemdb->packages[i].random_qty, must_qty = itemdb->packages[i].must_qty;
+ int id = itemdb->packages[i].id;
+ unsigned short random_qty = itemdb->packages[i].random_qty, must_qty = itemdb->packages[i].must_qty;
unsigned short c;
//into a package, first 2 bytes = id.
hwrite(&id,sizeof(id),1,file);
@@ -916,7 +1001,9 @@ void itemdb_write_cached_packages(const char *config_filename) {
return;
}
-bool itemdb_read_cached_packages(const char *config_filename) {
+
+static bool itemdb_read_cached_packages(const char *config_filename)
+{
FILE *file;
unsigned short pcount = 0;
unsigned short i;
@@ -933,12 +1020,13 @@ bool itemdb_read_cached_packages(const char *config_filename) {
itemdb->package_count = pcount;
for( i = 0; i < pcount; i++ ) {
- unsigned short id = 0, random_qty = 0, must_qty = 0;
+ int id = 0;
+ unsigned short random_qty = 0, must_qty = 0;
struct item_data *pdata;
struct item_package *package = &itemdb->packages[i];
unsigned short c;
- //into a package, first 2 bytes = id.
+ //into a package, first 4 bytes = id.
hread(&id,sizeof(id),1,file);
//next 2 bytes = must count
hread(&must_qty,sizeof(must_qty),1,file);
@@ -961,10 +1049,11 @@ bool itemdb_read_cached_packages(const char *config_filename) {
//now we loop into must
for(c = 0; c < package->must_qty; c++) {
struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c];
- unsigned short mid = 0, qty = 0, hours = 0;
+ int mid = 0;
+ unsigned short qty = 0, hours = 0;
unsigned char announce = 0, named = 0, force_serial = 0;
struct item_data *data;
- //first 2 byte = item id
+ //first 4 byte = item id
hread(&mid,sizeof(mid),1,file);
//next 2 byte = qty
hread(&qty,sizeof(qty),1,file);
@@ -1004,7 +1093,8 @@ bool itemdb_read_cached_packages(const char *config_filename) {
//now we loop into the group's list
for(h = 0; h < group_qty; h++) {
struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h];
- unsigned short mid = 0, qty = 0, hours = 0, rate = 0;
+ int mid = 0;
+ unsigned short qty = 0, hours = 0, rate = 0;
unsigned char announce = 0, named = 0, force_serial = 0;
struct item_data *data;
@@ -1047,14 +1137,12 @@ bool itemdb_read_cached_packages(const char *config_filename) {
return true;
}
-void itemdb_read_packages(void) {
+static void itemdb_read_packages(void)
+{
struct config_t item_packages_conf;
struct config_setting_t *itg = NULL, *it = NULL, *t = NULL;
-#ifdef RENEWAL
- const char *config_filename = "db/re/item_packages.conf"; // FIXME hardcoded name
-#else
- const char *config_filename = "db/pre-re/item_packages.conf"; // FIXME hardcoded name
-#endif
+ char config_filename[256];
+ libconfig->format_db_path(DBPATH"item_packages.conf", config_filename, sizeof(config_filename));
const char *itname;
int i = 0, count = 0, c = 0, highest_gcount = 0;
unsigned int *must = NULL, *random = NULL, *rgroup = NULL, **rgroups = NULL;
@@ -1179,7 +1267,7 @@ void itemdb_read_packages(void) {
itname = config_setting_name(it);
- if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) {
+ if (itname[0] == 'I' && itname[1] == 'D' && strlen(itname) <= 12) {
if( !( data = itemdb->exists(atoi(itname+2)) ) )
ShowWarning("itemdb_read_packages: unknown item ID '%d' in package '%s'!\n",atoi(itname+2),config_setting_name(itg));
} else if( !( data = itemdb->name2id(itname) ) )
@@ -1277,14 +1365,132 @@ void itemdb_read_packages(void) {
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename);
}
-void itemdb_read_chains(void) {
+/**
+ * Processes any (plugin-defined) additional fields for a itemdb_options entry.
+ *
+ * @param[in,out] entry The destination ito entry, already initialized
+ * (item_opt.index, status.mode are expected to be already set).
+ * @param[in] t The libconfig entry.
+ * @param[in] source Source of the entry (file name), to be displayed in
+ * case of validation errors.
+ */
+static void itemdb_readdb_options_additional_fields(struct itemdb_option *ito, struct config_setting_t *t, const char *source)
+{
+ // do nothing. plugins can do their own work
+}
+
+/**
+ * Reads the Item Options configuration file.
+ */
+static void itemdb_read_options(void)
+{
+ struct config_t item_options_db;
+ struct config_setting_t *ito = NULL, *conf = NULL;
+ int index = 0, count = 0;
+ char filepath[256];
+ libconfig->format_db_path("item_options.conf", filepath, sizeof(filepath));
+ VECTOR_DECL(int) duplicate_id;
+
+ if (!libconfig->load_file(&item_options_db, filepath))
+ return;
+
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = filepath;
+#endif // ENABLE_CASE_CHECK
+
+ if ((ito=libconfig->setting_get_member(item_options_db.root, "item_options_db")) == NULL) {
+ ShowError("itemdb_read_options: '%s' could not be loaded.\n", filepath);
+ libconfig->destroy(&item_options_db);
+ return;
+ }
+
+ VECTOR_INIT(duplicate_id);
+
+ VECTOR_ENSURE(duplicate_id, libconfig->setting_length(ito), 1);
+
+ while ((conf = libconfig->setting_get_elem(ito, index++))) {
+ struct itemdb_option t_opt = { 0 }, *s_opt = NULL;
+ const char *str = NULL;
+ int i = 0;
+
+ /* Id Lookup */
+ if (!libconfig->setting_lookup_int16(conf, "Id", &t_opt.index) || t_opt.index <= 0) {
+ ShowError("itemdb_read_options: Invalid Option Id provided for entry %d in '%s', skipping...\n", t_opt.index, filepath);
+ continue;
+ }
+
+ /* Checking for duplicate entries. */
+ ARR_FIND(0, VECTOR_LENGTH(duplicate_id), i, VECTOR_INDEX(duplicate_id, i) == t_opt.index);
+
+ if (i != VECTOR_LENGTH(duplicate_id)) {
+ ShowError("itemdb_read_options: Duplicate entry for Option Id %d in '%s', skipping...\n", t_opt.index, filepath);
+ continue;
+ }
+
+ VECTOR_PUSH(duplicate_id, t_opt.index);
+
+ /* Name Lookup */
+ if (!libconfig->setting_lookup_string(conf, "Name", &str)) {
+ ShowError("itemdb_read_options: Invalid Option Name '%s' provided for Id %d in '%s', skipping...\n", str, t_opt.index, filepath);
+ continue;
+ }
+
+ /* check for illegal characters in the constant. */
+ {
+ const char *c = str;
+
+ while (ISALNUM(*c) || *c == '_')
+ ++c;
+
+ if (*c != '\0') {
+ ShowError("itemdb_read_options: Invalid characters in Option Name '%s' for Id %d in '%s', skipping...\n", str, t_opt.index, filepath);
+ continue;
+ }
+ }
+
+ /* Set name as a script constant with index as value. */
+ script->set_constant2(str, t_opt.index, false, false);
+
+ /* Script Code Lookup */
+ if (!libconfig->setting_lookup_string(conf, "Script", &str)) {
+ ShowError("itemdb_read_options: Script code not found for entry %s (Id: %d) in '%s', skipping...\n", str, t_opt.index, filepath);
+ continue;
+ }
+
+ /* Set Script */
+ t_opt.script = *str ? script->parse(str, filepath, t_opt.index, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
+ /* Additional fields through plugins */
+ itemdb->readdb_options_additional_fields(&t_opt, ito, filepath);
+
+ /* Allocate memory and copy contents */
+ CREATE(s_opt, struct itemdb_option, 1);
+
+ *s_opt = t_opt;
+
+ /* Store ptr in the database */
+ idb_put(itemdb->options, t_opt.index, s_opt);
+
+ count++;
+ }
+
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = NULL;
+#endif // ENABLE_CASE_CHECK
+
+ libconfig->destroy(&item_options_db);
+
+ VECTOR_CLEAR(duplicate_id);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+}
+
+static void itemdb_read_chains(void)
+{
struct config_t item_chain_conf;
struct config_setting_t *itc = NULL;
-#ifdef RENEWAL
- const char *config_filename = "db/re/item_chain.conf"; // FIXME hardcoded name
-#else
- const char *config_filename = "db/pre-re/item_chain.conf"; // FIXME hardcoded name
-#endif
+ char config_filename[256];
+ libconfig->format_db_path(DBPATH"item_chain.conf", config_filename, sizeof(config_filename));
int i = 0, count = 0;
if (!libconfig->load_file(&item_chain_conf, config_filename))
@@ -1310,7 +1516,7 @@ void itemdb_read_chains(void) {
while( (entry = libconfig->setting_get_elem(itc,c++)) ) {
const char *itname = config_setting_name(entry);
- if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) {
+ if (itname[0] == 'I' && itname[1] == 'D' && strlen(itname) <= 12) {
if( !( data = itemdb->exists(atoi(itname+2)) ) )
ShowWarning("itemdb_read_chains: unknown item ID '%d' in chain '%s'!\n",atoi(itname+2),name);
} else if( !( data = itemdb->name2id(itname) ) )
@@ -1341,155 +1547,127 @@ void itemdb_read_chains(void) {
else
itemdb->chain_cache[ECC_ORE] = i;
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename);
-}
-
-/**
- * @return: amount of retrieved entries.
- **/
-int itemdb_combo_split_atoi (char *str, int *val) {
- int i;
-
- nullpo_ret(val);
-
- for (i=0; i<MAX_ITEMS_PER_COMBO; i++) {
- if (!str) break;
-
- val[i] = atoi(str);
- str = strchr(str,':');
- if (str)
- *str++=0;
- }
+ if (!script->get_constant("ITMCHAIN_SIEGFRIED", &i))
+ ShowWarning("itemdb_read_chains: failed to find 'ITMCHAIN_SIEGFRIED' chain to link to cache!\n");
+ else
+ itemdb->chain_cache[ECC_SIEGFRIED] = i;
- if( i == 0 ) //No data found.
- return 0;
+ if (!script->get_constant("ITMCHAIN_NEO_INSURANCE", &i))
+ ShowWarning("itemdb_read_chains: failed to find 'ITMCHAIN_NEO_INSURANCE' chain to link to cache!\n");
+ else
+ itemdb->chain_cache[ECC_NEO_INSURANCE] = i;
- return i;
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename);
}
-/**
- * <combo{:combo{:combo:{..}}}>,<{ script }>
- **/
-void itemdb_read_combos(void)
+
+static bool itemdb_read_combodb_libconfig(void)
{
- uint32 lines = 0, count = 0;
- char line[1024];
+ struct config_t combo_conf;
char filepath[256];
- FILE* fp;
-
- sprintf(filepath, "%s/%s", map->db_path, DBPATH"item_combo_db.txt");
+ safesnprintf(filepath, sizeof(filepath), "%s/%s/%s", map->db_path, DBPATH, "item_combo_db.conf");
- if ((fp = fopen(filepath, "r")) == NULL) {
- ShowError("itemdb_read_combos: File not found \"%s\".\n", filepath);
- return;
+ if (libconfig->load_file(&combo_conf, filepath) == CONFIG_FALSE) {
+ ShowError("itemdb_read_combodb_libconfig: can't read %s\n", filepath);
+ return false;
}
- // process rows one by one
- while(fgets(line, sizeof(line), fp)) {
- char *str[2], *p;
-
- lines++;
-
- if (line[0] == '/' && line[1] == '/')
- continue;
+ struct config_setting_t *combo_db = NULL;
+ if ((combo_db = libconfig->setting_get_member(combo_conf.root, "combo_db")) == NULL) {
+ ShowError("itemdb_read_combodb_libconfig: can't read %s\n", filepath);
+ return false;
+ }
- memset(str, 0, sizeof(str));
+ int i = 0;
+ int count = 0;
+ struct config_setting_t *it = NULL;
- p = line;
- p = trim(p);
- if (*p == '\0')
- continue;// empty line
+ while ((it = libconfig->setting_get_elem(combo_db, i++)) != NULL) {
+ if (itemdb->read_combodb_libconfig_sub(it, i - 1, filepath))
+ ++count;
+ }
- if (!strchr(p,',')) {
- /* is there even a single column? */
- ShowError("itemdb_read_combos: Insufficient columns in line %u of \"%s\", skipping.\n", lines, filepath);
- continue;
- }
+ libconfig->destroy(&combo_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+ return true;
+}
- str[0] = p;
- p = strchr(p,',');
- *p = '\0';
- p++;
+static bool itemdb_read_combodb_libconfig_sub(struct config_setting_t *it, int idx, const char *source)
+{
+ nullpo_retr(false, it);
+ nullpo_retr(false, source);
- str[1] = p;
- p = strchr(p,',');
- p++;
+ struct config_setting_t *t = NULL;
- if (str[1][0] != '{') {
- ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %u of \"%s\", skipping.\n", lines, filepath);
- continue;
- }
+ if ((t = libconfig->setting_get_member(it, "Items")) == NULL) {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: invalid item list for combo (%d), in (%s), skipping..\n", idx, source);
+ return false;
+ }
- /* no ending key anywhere (missing \}\) */
- if ( str[1][strlen(str[1])-1] != '}' ) {
- ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %u of \"%s\", skipping.\n", lines, filepath);
- continue;
- } else {
- int items[MAX_ITEMS_PER_COMBO];
- int v = 0, retcount = 0;
- struct item_combo *combo = NULL;
+ if (!config_setting_is_array(t)) {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: the combo (%d) item list must be an array, in (%s), skipping..\n", idx, source);
+ return false;
+ }
- if((retcount = itemdb->combo_split_atoi(str[0], items)) < 2) {
- ShowError("itemdb_read_combos: line %u of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, filepath);
- continue;
- }
+ int len = libconfig->setting_length(t);
+ if (len > MAX_ITEMS_PER_COMBO) {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: the size of combo (%d) item list is too big (%d, max = %d), in (%s), skipping..\n", idx, len, MAX_ITEMS_PER_COMBO, source);
+ return false;
+ }
- /* validate */
- for(v = 0; v < retcount; v++) {
- if( !itemdb->exists(items[v]) ) {
- ShowError("itemdb_read_combos: line %u of \"%s\" contains unknown item ID %d, skipping.\n", lines, filepath, items[v]);
- break;
- }
- }
- /* failed at some item */
- if( v < retcount )
- continue;
+ struct item_combo *combo = NULL;
+ RECREATE(itemdb->combos, struct item_combo *, ++itemdb->combo_count);
+ CREATE(combo, struct item_combo, 1);
- RECREATE(itemdb->combos, struct item_combo*, ++itemdb->combo_count);
+ combo->id = itemdb->combo_count - 1;
+ combo->count = len;
- CREATE(combo, struct item_combo, 1);
+ for (int i = 0; i < len; i++) {
+ struct item_data *item = NULL;
+ const char *name = libconfig->setting_get_string_elem(t, i);
- combo->count = retcount;
- combo->script = script->parse(str[1], filepath, lines, 0, NULL);
- combo->id = itemdb->combo_count - 1;
- /* populate ->nameid field */
- for( v = 0; v < retcount; v++ ) {
- combo->nameid[v] = items[v];
- }
+ if ((item = itemdb->name2id(name)) == NULL) {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: unknown item '%s', in (%s), skipping..\n", name, source);
+ --itemdb->combo_count;
+ aFree(combo);
+ return false;
+ }
+ combo->nameid[i] = item->nameid;
+ }
- itemdb->combos[itemdb->combo_count - 1] = combo;
+ const char *str = NULL;
+ if (libconfig->setting_lookup_string(it, "Script", &str) == CONFIG_TRUE) {
+ combo->script = *str ? script->parse(str, source, -idx, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ } else {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: invalid script for combo (%d) in (%s), skipping..\n", idx, source);
+ --itemdb->combo_count;
+ aFree(combo);
+ return false;
+ }
- /* populate the items to refer to this combo */
- for( v = 0; v < retcount; v++ ) {
- struct item_data * it;
- int index;
+ itemdb->combos[combo->id] = combo;
- it = itemdb->exists(items[v]);
- index = it->combos_count;
- RECREATE(it->combos, struct item_combo*, ++it->combos_count);
- it->combos[index] = combo;
- }
- }
- count++;
+ /* populate the items to refer to this combo */
+ for (int i = 0; i < len; i++) {
+ struct item_data *item = itemdb->exists(combo->nameid[i]);
+ RECREATE(item->combos, struct item_combo *, ++item->combos_count);
+ item->combos[item->combos_count - 1] = combo;
}
- fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"item_combo_db"CL_RESET"'.\n", count);
-
- return;
+ return true;
}
/*======================================
* Applies gender restrictions according to settings. [Skotlex]
*======================================*/
-int itemdb_gendercheck(struct item_data *id)
+static int itemdb_gendercheck(struct item_data *id)
{
nullpo_ret(id);
if (id->nameid == WEDDING_RING_M) //Grom Ring
return 1;
if (id->nameid == WEDDING_RING_F) //Bride Ring
return 0;
- if (id->look == W_MUSICAL && id->type == IT_WEAPON) //Musical instruments are always male-only
+ if (id->subtype == W_MUSICAL && id->type == IT_WEAPON) //Musical instruments are always male-only
return 1;
- if (id->look == W_WHIP && id->type == IT_WEAPON) //Whips are always female-only
+ if (id->subtype == W_WHIP && id->type == IT_WEAPON) //Whips are always female-only
return 0;
return (battle_config.ignore_items_gender) ? 2 : id->sex;
@@ -1512,14 +1690,20 @@ int itemdb_gendercheck(struct item_data *id)
* (i.e. item_db2 inheritance), as it will make sure not to free any scripts
* still in use by the new entry.
*/
-int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
+static int itemdb_validate_entry(struct item_data *entry, int n, const char *source)
+{
struct item_data *item;
nullpo_ret(entry);
nullpo_ret(source);
- if( entry->nameid <= 0 || entry->nameid >= MAX_ITEMDB ) {
- ShowWarning("itemdb_validate_entry: Invalid item ID %d in entry %d of '%s', allowed values 0 < ID < %d (MAX_ITEMDB), skipping.\n",
- entry->nameid, n, source, MAX_ITEMDB);
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ if (entry->nameid <= 0 || entry->nameid > MAX_ITEM_ID) {
+#else
+ if (entry->nameid <= 0) {
+#endif
+ // item id wrong for any packet versions
+ ShowWarning("itemdb_validate_entry: Invalid item ID %d in entry %d of '%s', allowed values 0 < ID < %d (MAX_ITEM_ID), skipping.\n",
+ entry->nameid, n, source, MAX_ITEM_ID);
if (entry->script) {
script->free_code(entry->script);
entry->script = NULL;
@@ -1532,7 +1716,54 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
script->free_code(entry->unequip_script);
entry->unequip_script = NULL;
}
+ if (entry->rental_start_script != NULL) {
+ script->free_code(entry->rental_start_script);
+ entry->rental_start_script = NULL;
+ }
+ if (entry->rental_end_script != NULL) {
+ script->free_code(entry->rental_end_script);
+ entry->rental_end_script = NULL;
+ }
return 0;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ }
+#else
+ } else if (entry->nameid > MAX_ITEM_ID) {
+ // item id too big for packet version before item id in 4 bytes
+ entry->view_id = UNKNOWN_ITEM_ID;
+ }
+#endif
+
+ {
+ const char *c = entry->name;
+ while (ISALNUM(*c) || *c == '_')
+ ++c;
+
+ if (*c != '\0') {
+ ShowWarning("itemdb_validate_entry: Invalid characters in the AegisName '%s' for item %d in '%s'. Skipping.\n",
+ entry->name, entry->nameid, source);
+ if (entry->script) {
+ script->free_code(entry->script);
+ entry->script = NULL;
+ }
+ if (entry->equip_script) {
+ script->free_code(entry->equip_script);
+ entry->equip_script = NULL;
+ }
+ if (entry->unequip_script) {
+ script->free_code(entry->unequip_script);
+ entry->unequip_script = NULL;
+ }
+ if (entry->rental_start_script != NULL) {
+ script->free_code(entry->rental_start_script);
+ entry->rental_start_script = NULL;
+ }
+ if (entry->rental_end_script != NULL) {
+ script->free_code(entry->rental_end_script);
+ entry->rental_end_script = NULL;
+ }
+ return 0;
+ }
}
if( entry->type < 0 || entry->type == IT_UNKNOWN || entry->type == IT_UNKNOWN2
@@ -1613,10 +1844,14 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
memset(&entry->stack, '\0', sizeof(entry->stack));
}
- if (entry->type == IT_WEAPON && (entry->look < 0 || entry->look >= MAX_SINGLE_WEAPON_TYPE)) {
- ShowWarning("itemdb_validate_entry: Invalid View for weapon items. View value %d for item %d (%s) in '%s', defaulting to 1.\n",
- entry->look, entry->nameid, entry->jname, source);
- entry->look = 1;
+ if (entry->type == IT_WEAPON && (entry->subtype <= 0 || entry->subtype >= MAX_SINGLE_WEAPON_TYPE)) {
+ ShowWarning("itemdb_validate_entry: Invalid View for weapon items. View value %d for item %d (%s) in '%s', defaulting to W_DAGGER.\n",
+ entry->subtype, entry->nameid, entry->jname, source);
+ entry->subtype = W_DAGGER;
+ } else if (entry->type == IT_AMMO && (entry->subtype <= 0 || entry->subtype >= MAX_AMMO_TYPE)) {
+ ShowWarning("itemdb_validate_entry: Invalid View for ammunition items. View value %d for item %d (%s) in '%s', defaulting to A_ARROW.\n",
+ entry->subtype, entry->nameid, entry->jname, source);
+ entry->subtype = A_ARROW;
}
entry->wlv = cap_value(entry->wlv, REFINE_TYPE_ARMOR, REFINE_TYPE_MAX);
@@ -1629,6 +1864,9 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
if( entry->type != IT_ARMOR && entry->type != IT_WEAPON && !entry->flag.no_refine )
entry->flag.no_refine = 1;
+ if (entry->type != IT_ARMOR && entry->type != IT_WEAPON && !entry->flag.no_options)
+ entry->flag.no_options = 1;
+
if (entry->flag.available != 1) {
entry->flag.available = 1;
entry->view_id = 0;
@@ -1651,14 +1889,21 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
script->free_code(item->unequip_script);
item->unequip_script = NULL;
}
-
+ if (item->rental_start_script != NULL && item->rental_start_script != entry->rental_start_script) { // Don't free if it's inheriting the same script
+ script->free_code(item->rental_start_script);
+ item->rental_start_script = NULL;
+ }
+ if (item->rental_end_script != NULL && item->rental_end_script != entry->rental_end_script) { // Don't free if it's inheriting the same script
+ script->free_code(item->rental_end_script);
+ item->rental_end_script = NULL;
+ }
*item = *entry;
return item->nameid;
}
-void itemdb_readdb_additional_fields(int itemid, struct config_setting_t *it, int n, const char *source)
+static void itemdb_readdb_additional_fields(int itemid, struct config_setting_t *it, int n, const char *source)
{
- // do nothing. plugins can do own work
+ // do nothing. plugins can do own work
}
/**
@@ -1668,7 +1913,7 @@ void itemdb_readdb_additional_fields(int itemid, struct config_setting_t *it, in
* @param t Libconfig setting entry. It is expected to be valid and it won't
* be freed (it is care of the caller to do so if necessary).
*/
-void itemdb_readdb_job_sub(struct item_data *id, struct config_setting_t *t)
+static void itemdb_readdb_job_sub(struct item_data *id, struct config_setting_t *t)
{
int idx = 0;
struct config_setting_t *it = NULL;
@@ -1707,7 +1952,8 @@ void itemdb_readdb_job_sub(struct item_data *id, struct config_setting_t *t)
* validation errors.
* @return Nameid of the validated entry, or 0 in case of failure.
*/
-int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *source) {
+static int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *source)
+{
struct item_data id = { 0 };
struct config_setting_t *t = NULL;
const char *str = NULL;
@@ -1766,13 +2012,15 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
* ">
* OnEquipScript: <" OnEquip Script ">
* OnUnequipScript: <" OnUnequip Script ">
+ * OnRentalStartScript: <" on renting script ">
+ * OnRentalEndScript: <" on renting end script ">
* Inherit: inherit or override
*/
if( !itemdb->lookup_const(it, "Id", &i32) ) {
ShowWarning("itemdb_readdb_libconfig_sub: Invalid or missing id in \"%s\", entry #%d, skipping.\n", source, n);
return 0;
}
- id.nameid = (uint16)i32;
+ id.nameid = i32;
if( (t = libconfig->setting_get_member(it, "Inherit")) && (inherit = libconfig->setting_get_bool(t)) ) {
if( !itemdb->exists(id.nameid) ) {
@@ -1808,6 +2056,14 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
else if( !inherit )
id.type = IT_ETC;
+ if (itemdb->lookup_const(it, "Subtype", &i32) && i32 >= 0) {
+ if (id.type == IT_WEAPON || id.type == IT_AMMO)
+ id.subtype = i32;
+ else
+ ShowWarning("itemdb_readdb_libconfig_sub: Field 'Subtype' is only allowed for IT_WEAPON or IT_AMMO (Item #%d: %s). Ignoring.\n",
+ id.nameid, id.name);
+ }
+
if( itemdb->lookup_const(it, "Buy", &i32) )
id.value_buy = i32;
else if( !inherit )
@@ -1847,7 +2103,7 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
itemdb->jobmask2mapid(id.class_base, UINT64_MAX);
}
- if( itemdb->lookup_const(it, "Upper", &i32) && i32 >= 0 )
+ if (itemdb->lookup_const_mask(it, "Upper", &i32) && i32 >= 0)
id.class_upper = (unsigned int)i32;
else if( !inherit )
id.class_upper = ITEMUPPER_ALL;
@@ -1857,7 +2113,7 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
else if( !inherit )
id.sex = 2;
- if( itemdb->lookup_const(it, "Loc", &i32) && i32 >= 0 )
+ if (itemdb->lookup_const_mask(it, "Loc", &i32) && i32 >= 0)
id.equip = i32;
if( itemdb->lookup_const(it, "WeaponLv", &i32) && i32 >= 0 )
@@ -1877,8 +2133,32 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
if( (t = libconfig->setting_get_member(it, "Refine")) )
id.flag.no_refine = libconfig->setting_get_bool(t) ? 0 : 1;
- if( itemdb->lookup_const(it, "View", &i32) && i32 >= 0 )
- id.look = i32;
+ if ((t = libconfig->setting_get_member(it, "DisableOptions")))
+ id.flag.no_options = libconfig->setting_get_bool(t) ? 1 : 0;
+
+ if ((t = libconfig->setting_get_member(it, "ShowDropEffect")))
+ id.flag.showdropeffect = libconfig->setting_get_bool(t) ? 1 : 0;
+
+ if (itemdb->lookup_const(it, "DropEffectMode", &i32) && i32 >= 0)
+ id.dropeffectmode = i32;
+
+ if (itemdb->lookup_const(it, "ViewSprite", &i32) && i32 >= 0)
+ id.view_sprite = i32;
+
+ if (itemdb->lookup_const(it, "View", &i32) && i32 >= 0) { // TODO: Remove (Deprecated - 2016-09-04 [Haru])
+ if ((id.type == IT_WEAPON || id.type == IT_AMMO) && id.subtype == 0) {
+ ShowWarning("itemdb_readdb_libconfig_sub: The 'View' field is deprecated. Please rename it to 'Subtype' (or 'ViewSprite'). (Item #%d: %s)\n",
+ id.nameid, id.name);
+ id.subtype = i32;
+ } else if ((id.type != IT_WEAPON && id.type != IT_AMMO) && id.view_sprite == 0) {
+ ShowWarning("itemdb_readdb_libconfig_sub: The 'View' field is deprecated. Please rename it to 'ViewSprite' (or 'Subtype'). (Item #%d: %s)\n",
+ id.nameid, id.name);
+ id.view_sprite = i32;
+ } else {
+ ShowWarning("itemdb_readdb_libconfig_sub: The 'View' field is deprecated. Please rename it to 'Subtype' or 'ViewSprite'. (Item #%d: %s)\n",
+ id.nameid, id.name);
+ }
+ }
if( (t = libconfig->setting_get_member(it, "BindOnEquip")) )
id.flag.bindonequip = libconfig->setting_get_bool(t) ? 1 : 0;
@@ -1892,6 +2172,9 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
if ((t = libconfig->setting_get_member(it, "KeepAfterUse")))
id.flag.keepafteruse = libconfig->setting_get_bool(t) ? 1 : 0;
+ if ((t = libconfig->setting_get_member(it, "DropAnnounce")))
+ id.flag.drop_announce = libconfig->setting_get_bool(t) ? 1 : 0;
+
if (itemdb->lookup_const(it, "Delay", &i32) && i32 >= 0)
id.delay = i32;
@@ -2008,26 +2291,87 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
if( libconfig->setting_lookup_string(it, "OnUnequipScript", &str) )
id.unequip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ if (libconfig->setting_lookup_string(it, "OnRentalStartScript", &str) != CONFIG_FALSE)
+ id.rental_start_script = (*str != '\0') ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
+ if (libconfig->setting_lookup_string(it, "OnRentalEndScript", &str) != CONFIG_FALSE)
+ id.rental_end_script = (*str != '\0') ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
return itemdb->validate_entry(&id, n, source);
}
-bool itemdb_lookup_const(const struct config_setting_t *it, const char *name, int *value)
+static bool itemdb_lookup_const(const struct config_setting_t *it, const char *name, int *value)
{
+ const char *str = NULL;
+
nullpo_retr(false, name);
nullpo_retr(false, value);
- if (libconfig->setting_lookup_int(it, name, value))
- {
+
+ if (libconfig->setting_lookup_int(it, name, value)) {
return true;
}
- else
- {
+
+ if (libconfig->setting_lookup_string(it, name, &str)) {
+ if (*str && script->get_constant(str, value))
+ return true;
+ }
+
+ return false;
+}
+
+static bool itemdb_lookup_const_mask(const struct config_setting_t *it, const char *name, int *value)
+{
+ const struct config_setting_t *t = NULL;
+
+ nullpo_retr(false, it);
+ nullpo_retr(false, name);
+ nullpo_retr(false, value);
+
+ if ((t = libconfig->setting_get_member(it, name)) == NULL) {
+ return false;
+ }
+
+ if (config_setting_is_scalar(t)) {
const char *str = NULL;
- if (libconfig->setting_lookup_string(it, name, &str))
- {
- if (*str && script->get_constant(str, value))
+
+ if (config_setting_is_number(t)) {
+ *value = libconfig->setting_get_int(t);
+ return true;
+ }
+
+ if ((str = libconfig->setting_get_string(t)) != NULL) {
+ int i32 = -1;
+ if (script->get_constant(str, &i32) && i32 >= 0) {
+ *value = i32;
return true;
+ }
+ }
+
+ return false;
+ }
+
+ if (config_setting_is_aggregate(t) && libconfig->setting_length(t) >= 1) {
+ const struct config_setting_t *elem = NULL;
+ int i = 0;
+
+ *value = 0;
+
+ while ((elem = libconfig->setting_get_elem(t, i++)) != NULL) {
+ const char *str = libconfig->setting_get_string(elem);
+ int i32 = -1;
+
+ if (str == NULL)
+ return false;
+
+ if (!script->get_constant(str, &i32) || i32 < 0)
+ return false;
+
+ *value |= i32;
}
+
+ return true;
}
+
return false;
}
@@ -2038,8 +2382,10 @@ bool itemdb_lookup_const(const struct config_setting_t *it, const char *name, in
* @param filename File name, relative to the database path.
* @return The number of found entries.
*/
-int itemdb_readdb_libconfig(const char *filename) {
+static int itemdb_readdb_libconfig(const char *filename)
+{
bool duplicate[MAX_ITEMDB];
+ struct DBMap *duplicate_db;
struct config_t item_db_conf;
struct config_setting_t *itdb, *it;
char filepath[256];
@@ -2047,7 +2393,7 @@ int itemdb_readdb_libconfig(const char *filename) {
nullpo_ret(filename);
- sprintf(filepath, "%s/%s", map->db_path, filename);
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
if (!libconfig->load_file(&item_db_conf, filepath))
return 0;
@@ -2056,43 +2402,149 @@ int itemdb_readdb_libconfig(const char *filename) {
return 0;
}
+ // TODO add duplicates check for itemdb->other
memset(&duplicate,0,sizeof(duplicate));
+ duplicate_db = idb_alloc(DB_OPT_BASE);
while( (it = libconfig->setting_get_elem(itdb,i++)) ) {
int nameid = itemdb->readdb_libconfig_sub(it, i-1, filename);
- if (nameid <= 0 || nameid >= MAX_ITEMDB)
+ if (nameid <= 0 || nameid > MAX_ITEM_ID)
continue;
itemdb->readdb_additional_fields(nameid, it, i - 1, filename);
count++;
- if( duplicate[nameid] ) {
- ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n",
- filename, nameid, itemdb_name(nameid), itemdb_jname(nameid));
- } else
- duplicate[nameid] = true;
+ if (nameid < MAX_ITEMDB) {
+ if (duplicate[nameid]) {
+ ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n",
+ filename, nameid, itemdb_name(nameid), itemdb_jname(nameid));
+ } else {
+ duplicate[nameid] = true;
+ }
+ } else {
+ if (idb_exists(duplicate_db, nameid)) {
+ ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n",
+ filename, nameid, itemdb_name(nameid), itemdb_jname(nameid));
+ } else {
+ idb_iput(duplicate_db, nameid, true);
+ }
+ }
}
+ db_destroy(duplicate_db);
libconfig->destroy(&item_db_conf);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename);
-
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
return count;
}
/*==========================================
-* Unique item ID function
-* Only one operation by once
-*------------------------------------------*/
-uint64 itemdb_unique_id(struct map_session_data *sd) {
+ * Unique item ID function
+ * Only one operation by once
+ *------------------------------------------*/
+static uint64 itemdb_unique_id(struct map_session_data *sd)
+{
nullpo_ret(sd);
return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++;
}
+static bool itemdb_read_libconfig_lapineddukddak(void)
+{
+ struct config_t item_lapineddukddak;
+ struct config_setting_t *it = NULL;
+ char filepath[256];
+
+ int i = 0;
+ int count = 0;
+
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, DBPATH"item_lapineddukddak.conf");
+ if (libconfig->load_file(&item_lapineddukddak, filepath) == CONFIG_FALSE)
+ return false;
+
+ while ((it = libconfig->setting_get_elem(item_lapineddukddak.root, i++)) != NULL) {
+ if (itemdb->read_libconfig_lapineddukddak_sub(it, filepath))
+ ++count;
+ }
+
+ libconfig->destroy(&item_lapineddukddak);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+ return true;
+}
+
+static bool itemdb_read_libconfig_lapineddukddak_sub(struct config_setting_t *it, const char *source)
+{
+ nullpo_retr(false, it);
+ nullpo_retr(false, source);
+
+ struct item_data *data = NULL;
+ const char *name = config_setting_name(it);
+ const char *str = NULL;
+ int i32 = 0;
+
+ if ((data = itemdb->name2id(name)) == NULL) {
+ ShowWarning("itemdb_read_libconfig_lapineddukddak_sub: unknown item '%s', skipping..\n", name);
+ return false;
+ }
+
+ data->lapineddukddak = aCalloc(1, sizeof(struct item_lapineddukddak));
+ if (libconfig->setting_lookup_int(it, "NeedCount", &i32) == CONFIG_TRUE)
+ data->lapineddukddak->NeedCount = (int16)i32;
+
+ if (libconfig->setting_lookup_int(it, "NeedRefineMin", &i32) == CONFIG_TRUE)
+ data->lapineddukddak->NeedRefineMin = (int8)i32;
+
+ if (libconfig->setting_lookup_int(it, "NeedRefineMax", &i32) == CONFIG_TRUE)
+ data->lapineddukddak->NeedRefineMax = (int8)i32;
+
+ struct config_setting_t *sources = libconfig->setting_get_member(it, "SourceItems");
+ itemdb->read_libconfig_lapineddukddak_sub_sources(sources, data);
+
+ if (libconfig->setting_lookup_string(it, "Script", &str) == CONFIG_TRUE)
+ data->lapineddukddak->script = *str ? script->parse(str, source, -data->nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ return true;
+}
+
+static bool itemdb_read_libconfig_lapineddukddak_sub_sources(struct config_setting_t *sources, struct item_data *data)
+{
+ nullpo_retr(false, data);
+ nullpo_retr(false, data->lapineddukddak);
+
+ int i = 0;
+ struct config_setting_t *entry = NULL;
+
+ if (sources == NULL || !config_setting_is_group(sources))
+ return false;
+
+ VECTOR_INIT(data->lapineddukddak->SourceItems);
+ while ((entry = libconfig->setting_get_elem(sources, i++)) != NULL) {
+ struct item_data *edata = NULL;
+ struct itemlist_entry item = { 0 };
+ const char *name = config_setting_name(entry);
+ int i32 = 0;
+
+ if ((edata = itemdb->name2id(name)) == NULL) {
+ ShowWarning("itemdb_read_libconfig_lapineddukddak_sub: unknown item '%s', skipping..\n", name);
+ continue;
+ }
+ item.id = edata->nameid;
+
+ if ((i32 = libconfig->setting_get_int(entry)) == CONFIG_TRUE && (i32 <= 0 || i32 > MAX_AMOUNT)) {
+ ShowWarning("itemdb_read_libconfig_lapineddukddak_sub: invalid amount (%d) for source item '%s', skipping..\n", i32, name);
+ continue;
+ }
+ item.amount = i32;
+
+ VECTOR_ENSURE(data->lapineddukddak->SourceItems, 1, 1);
+ VECTOR_PUSH(data->lapineddukddak->SourceItems, item);
+ }
+ return true;
+}
+
/**
* Reads all item-related databases.
*/
-void itemdb_read(bool minimal) {
+static void itemdb_read(bool minimal)
+{
int i;
struct DBData prev;
@@ -2103,6 +2555,7 @@ void itemdb_read(bool minimal) {
for (i = 0; i < ARRAYLENGTH(filename); i++)
itemdb->readdb_libconfig(filename[i]);
+ // TODO check duplicate names also in itemdb->other
for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) {
if( itemdb->array[i] ) {
if( itemdb->names->put(itemdb->names,DB->str2key(itemdb->array[i]->name),DB->ptr2data(itemdb->array[i]),&prev) ) {
@@ -2112,20 +2565,44 @@ void itemdb_read(bool minimal) {
}
}
+ itemdb->other->foreach(itemdb->other, itemdb->addname_sub);
+
+ itemdb->read_options();
+
if (minimal)
return;
- itemdb->read_combos();
+ itemdb->name_constants();
+
+ itemdb->read_combodb_libconfig();
itemdb->read_groups();
itemdb->read_chains();
itemdb->read_packages();
+ itemdb->read_libconfig_lapineddukddak();
+}
+
+/**
+ * Add item name with high id into map
+ * @see DBApply
+ */
+static int itemdb_addname_sub(union DBKey key, struct DBData *data, va_list ap)
+{
+ struct item_data *item = DB->data2ptr(data);
+ struct DBData prev;
+ if (itemdb->names->put(itemdb->names, DB->str2key(item->name), DB->ptr2data(item), &prev)) {
+ struct item_data *oldItem = DB->data2ptr(&prev);
+ ShowError("itemdb_read: duplicate AegisName '%s' in item ID %d and %d\n", item->name, item->nameid, oldItem->nameid);
+ }
+
+ return 0;
}
/**
* retrieves item_combo data by combo id
**/
-struct item_combo * itemdb_id2combo( unsigned short id ) {
+static struct item_combo *itemdb_id2combo(int id)
+{
if( id > itemdb->combo_count )
return NULL;
return itemdb->combos[id];
@@ -2134,7 +2611,7 @@ struct item_combo * itemdb_id2combo( unsigned short id ) {
/**
* check is item have usable type
**/
-bool itemdb_is_item_usable(struct item_data *item)
+static bool itemdb_is_item_usable(struct item_data *item)
{
nullpo_retr(false, item);
return item->type == IT_HEALING || item->type == IT_USABLE || item->type == IT_CASH;
@@ -2145,7 +2622,7 @@ bool itemdb_is_item_usable(struct item_data *item)
*------------------------------------------*/
/// Destroys the item_data.
-void destroy_item_data(struct item_data* self, int free_self)
+static void destroy_item_data(struct item_data *self, int free_self)
{
if( self == NULL )
return;
@@ -2156,8 +2633,18 @@ void destroy_item_data(struct item_data* self, int free_self)
script->free_code(self->equip_script);
if( self->unequip_script )
script->free_code(self->unequip_script);
+ if (self->rental_start_script != NULL)
+ script->free_code(self->rental_start_script);
+ if (self->rental_end_script != NULL)
+ script->free_code(self->rental_end_script);
if( self->combos )
aFree(self->combos);
+ if (self->lapineddukddak != NULL) {
+ if (self->lapineddukddak->script != NULL)
+ script->free_code(self->lapineddukddak->script);
+ VECTOR_CLEAR(self->lapineddukddak->SourceItems);
+ aFree(self->lapineddukddak);
+ }
HPM->data_store_destroy(&self->hdata);
#if defined(DEBUG)
// trash item
@@ -2171,7 +2658,7 @@ void destroy_item_data(struct item_data* self, int free_self)
/**
* @see DBApply
*/
-int itemdb_final_sub(union DBKey key, struct DBData *data, va_list ap)
+static int itemdb_final_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct item_data *id = DB->data2ptr(data);
@@ -2180,7 +2667,19 @@ int itemdb_final_sub(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
-void itemdb_clear(bool total) {
+
+static int itemdb_options_final_sub(union DBKey key, struct DBData *data, va_list ap)
+{
+ struct itemdb_option *ito = DB->data2ptr(data);
+
+ if (ito->script != NULL)
+ script->free_code(ito->script);
+
+ return 0;
+}
+
+static void itemdb_clear(bool total)
+{
int i;
// clear the previous itemdb data
for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) {
@@ -2243,13 +2742,15 @@ void itemdb_clear(bool total) {
return;
itemdb->other->clear(itemdb->other, itemdb->final_sub);
+ itemdb->options->clear(itemdb->options, itemdb->options_final_sub);
memset(itemdb->array, 0, sizeof(itemdb->array));
db_clear(itemdb->names);
}
-void itemdb_reload(void) {
+static void itemdb_reload(void)
+{
struct s_mapiterator* iter;
struct map_session_data* sd;
@@ -2293,21 +2794,25 @@ void itemdb_reload(void) {
for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays
pc->setinventorydata(sd);
- if( battle_config.item_check )
- sd->state.itemcheck = 1;
+
+ if (battle->bc->item_check != PCCHECKITEM_NONE) // Check and flag items for inspection.
+ sd->itemcheck = (enum pc_checkitem_types) battle->bc->item_check;
+
/* clear combo bonuses */
- if( sd->combo_count ) {
+ if (sd->combo_count) {
aFree(sd->combos);
sd->combos = NULL;
sd->combo_count = 0;
if( pc->load_combo(sd) > 0 )
status_calc_pc(sd,SCO_FORCE);
}
+
+ // Check for and delete unavailable/disabled items.
pc->checkitem(sd);
}
mapit->free(iter);
}
-void itemdb_name_constants(void)
+static void itemdb_name_constants(void)
{
struct DBIterator *iter = db_iterator(itemdb->names);
struct item_data *data;
@@ -2323,17 +2828,22 @@ void itemdb_name_constants(void)
dbi_destroy(iter);
}
-void do_final_itemdb(void) {
+static void do_final_itemdb(void)
+{
itemdb->clear(true);
itemdb->other->destroy(itemdb->other, itemdb->final_sub);
+ itemdb->options->destroy(itemdb->options, itemdb->options_final_sub);
itemdb->destroy_item_data(&itemdb->dummy, 0);
db_destroy(itemdb->names);
+ VECTOR_CLEAR(clif->attendance_data);
}
-void do_init_itemdb(bool minimal) {
+static void do_init_itemdb(bool minimal)
+{
memset(itemdb->array, 0, sizeof(itemdb->array));
itemdb->other = idb_alloc(DB_OPT_BASE);
+ itemdb->options = idb_alloc(DB_OPT_RELEASE_DATA);
itemdb->names = strdb_alloc(DB_OPT_BASE,ITEM_NAME_LENGTH);
itemdb->create_dummy_data(); //Dummy data item.
itemdb->read(minimal);
@@ -2346,8 +2856,11 @@ void do_init_itemdb(bool minimal) {
/** it failed? we disable it **/
if (battle_config.feature_roulette == 1 && !clif->parse_roulette_db())
battle_config.feature_roulette = 0;
+ VECTOR_INIT(clif->attendance_data);
+ clif->pAttendanceDB();
}
-void itemdb_defaults(void) {
+void itemdb_defaults(void)
+{
itemdb = &itemdb_s;
itemdb->init = do_init_itemdb;
@@ -2376,6 +2889,7 @@ void itemdb_defaults(void) {
itemdb->read_groups = itemdb_read_groups;
itemdb->read_chains = itemdb_read_chains;
itemdb->read_packages = itemdb_read_packages;
+ itemdb->read_options = itemdb_read_options;
/* */
itemdb->write_cached_packages = itemdb_write_cached_packages;
itemdb->read_cached_packages = itemdb_read_cached_packages;
@@ -2386,6 +2900,7 @@ void itemdb_defaults(void) {
itemdb->load = itemdb_load;
itemdb->search = itemdb_search;
itemdb->exists = itemdb_exists;
+ itemdb->option_exists = itemdb_option_exists;
itemdb->in_group = itemdb_in_group;
itemdb->group_item = itemdb_searchrandomid;
itemdb->chain_item = itemdb_chain_item;
@@ -2414,10 +2929,11 @@ void itemdb_defaults(void) {
itemdb->isrestricted = itemdb_isrestricted;
itemdb->isidentified = itemdb_isidentified;
itemdb->isidentified2 = itemdb_isidentified2;
- itemdb->combo_split_atoi = itemdb_combo_split_atoi;
- itemdb->read_combos = itemdb_read_combos;
+ itemdb->read_combodb_libconfig = itemdb_read_combodb_libconfig;
+ itemdb->read_combodb_libconfig_sub = itemdb_read_combodb_libconfig_sub;
itemdb->gendercheck = itemdb_gendercheck;
itemdb->validate_entry = itemdb_validate_entry;
+ itemdb->readdb_options_additional_fields = itemdb_readdb_options_additional_fields;
itemdb->readdb_additional_fields = itemdb_readdb_additional_fields;
itemdb->readdb_job_sub = itemdb_readdb_job_sub;
itemdb->readdb_libconfig_sub = itemdb_readdb_libconfig_sub;
@@ -2426,8 +2942,14 @@ void itemdb_defaults(void) {
itemdb->read = itemdb_read;
itemdb->destroy_item_data = destroy_item_data;
itemdb->final_sub = itemdb_final_sub;
+ itemdb->options_final_sub = itemdb_options_final_sub;
itemdb->clear = itemdb_clear;
itemdb->id2combo = itemdb_id2combo;
itemdb->is_item_usable = itemdb_is_item_usable;
itemdb->lookup_const = itemdb_lookup_const;
+ itemdb->lookup_const_mask = itemdb_lookup_const_mask;
+ itemdb->addname_sub = itemdb_addname_sub;
+ itemdb->read_libconfig_lapineddukddak = itemdb_read_libconfig_lapineddukddak;
+ itemdb->read_libconfig_lapineddukddak_sub = itemdb_read_libconfig_lapineddukddak_sub;
+ itemdb->read_libconfig_lapineddukddak_sub_sources = itemdb_read_libconfig_lapineddukddak_sub_sources;
}