summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2018-07-17 02:57:06 +0300
committerAndrei Karas <akaras@inbox.ru>2018-07-19 21:53:40 +0300
commit2f80262667ece77ceb69de42b2cc4ce84aed6881 (patch)
tree326d86dae61a32bbd5a51ad9f2afdf2c91aba07a
parentb67565957203e5efae25b1a29d072c1b954ce394 (diff)
downloadhercules-2f80262667ece77ceb69de42b2cc4ce84aed6881.tar.gz
hercules-2f80262667ece77ceb69de42b2cc4ce84aed6881.tar.bz2
hercules-2f80262667ece77ceb69de42b2cc4ce84aed6881.tar.xz
hercules-2f80262667ece77ceb69de42b2cc4ce84aed6881.zip
Add new constant MAX_ITEM_ID for maximum allowed item id.
For clients older than 2018-07-04 Re maximum supported and enabled id is 65535 (0xffff). For newer clients miximum id is 2147483648. Enabled by default 131072 (0x20000)
-rw-r--r--src/map/itemdb.c34
-rw-r--r--src/map/itemdb.h24
-rw-r--r--src/map/mob.c75
-rw-r--r--src/map/mob.h8
4 files changed, 117 insertions, 24 deletions
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index c04639693..04f25ae5b 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -1700,9 +1700,9 @@ static int itemdb_validate_entry(struct item_data *entry, int n, const char *sou
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 (entry->nameid <= 0 || entry->nameid > MAX_ITEM_ID) {
+ 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;
@@ -2346,6 +2346,7 @@ static bool itemdb_lookup_const_mask(const struct config_setting_t *it, const ch
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];
@@ -2362,26 +2363,38 @@ static 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);
-
return count;
}
@@ -2411,6 +2424,7 @@ static 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) ) {
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 6cce715d3..d92940445 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -36,12 +36,23 @@ struct hplugin_data_store;
#ifndef MAX_ITEMDB
#define MAX_ITEMDB 0xFFFF
#endif
+
+#ifndef MAX_ITEM_ID
+#if PACKETVER_RE_NUM >= 20180704
+#define MAX_ITEM_ID 0x20000
+#else
+#define MAX_ITEM_ID 0xFFFF
+#endif
+#endif
+
#ifndef MAX_ITEMDELAYS
#define MAX_ITEMDELAYS 10 // The maximum number of item delays
#endif
+
#ifndef MAX_SEARCH
#define MAX_SEARCH 5 //Designed for search functions, species max number of matches to display.
#endif
+
#ifndef MAX_ITEMS_PER_COMBO
#define MAX_ITEMS_PER_COMBO 6 /* maximum amount of items a combo may require */
#endif
@@ -58,6 +69,13 @@ struct hplugin_data_store;
#define UNKNOWN_ITEM_ID 512
#endif
+#if MAX_ITEM_ID < MAX_ITEMDB
+#error "MAX_ITEM_ID must be bigger or same with MAX_ITEMDB"
+#endif
+#if MAX_ITEM_ID > 0xFFFF && PACKETVER_RE_NUM < 20180704
+#error "For clients before 20180704 RE, MAX_ITEM_ID must be smaller than 0x10000"
+#endif
+
enum item_itemid {
ITEMID_RED_POTION = 501,
ITEMID_YELLOW_POTION = 503,
@@ -409,13 +427,13 @@ struct item_combo {
};
struct item_group {
- unsigned short id;
+ int id;
int *nameid;
unsigned short qty;
};
struct item_chain_entry {
- unsigned short id;
+ int id;
unsigned short rate;
struct item_chain_entry *next;
};
@@ -426,7 +444,7 @@ struct item_chain {
};
struct item_package_rand_entry {
- unsigned short id;
+ int id;
unsigned short qty;
unsigned short rate;
unsigned short hours;
diff --git a/src/map/mob.c b/src/map/mob.c
index 403e3a2f2..0dbff9211 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -88,6 +88,7 @@ struct item_drop_ratio {
int mob_id[MAX_ITEMRATIO_MOBS];
};
static struct item_drop_ratio *item_drop_ratio_db[MAX_ITEMDB];
+static struct DBMap *item_drop_ratio_other_db = NULL;
static struct eri *item_drop_ers; //For loot drops delay structures.
static struct eri *item_drop_list_ers;
@@ -3791,6 +3792,28 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor
return (unsigned int)cap_value(rate,rate_min,rate_max);
}
+static struct item_drop_ratio *mob_get_item_drop_ratio(int nameid)
+{
+ Assert_retr(NULL, nameid > 0);
+ if (nameid < ARRAYLENGTH(item_drop_ratio_db)) {
+ return item_drop_ratio_db[nameid];
+ } else {
+ return (struct item_drop_ratio *)idb_get(item_drop_ratio_other_db, nameid);
+ }
+}
+
+static void mob_set_item_drop_ratio(int nameid, struct item_drop_ratio *ratio)
+{
+ Assert_retv(nameid > 0);
+ if (nameid < ARRAYLENGTH(item_drop_ratio_db)) {
+ Assert_retv(item_drop_ratio_db[nameid] == NULL);
+ item_drop_ratio_db[nameid] = ratio;
+ } else {
+ Assert_retv(idb_get(item_drop_ratio_other_db, nameid) == NULL);
+ idb_put(item_drop_ratio_other_db, nameid, ratio);
+ }
+}
+
/**
* Check if global item drop rate is overridden for given item
* in db/mob_item_ratio.txt
@@ -3800,16 +3823,19 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor
*/
static void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust)
{
+ struct item_drop_ratio *dropRatio;
nullpo_retv(rate_adjust);
- if( item_drop_ratio_db[nameid] ) {
- if( item_drop_ratio_db[nameid]->mob_id[0] ) { // only for listed mobs
+
+ dropRatio = mob->get_item_drop_ratio(nameid);
+ if (dropRatio) {
+ if (dropRatio->mob_id[0] ) { // only for listed mobs
int i;
- ARR_FIND(0, MAX_ITEMRATIO_MOBS, i, item_drop_ratio_db[nameid]->mob_id[i] == mob_id);
- if(i < MAX_ITEMRATIO_MOBS) // found
- *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio;
+ ARR_FIND(0, MAX_ITEMRATIO_MOBS, i, dropRatio->mob_id[i] == mob_id);
+ if (i < MAX_ITEMRATIO_MOBS) // found
+ *rate_adjust = dropRatio->drop_ratio;
}
else // for all mobs
- *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio;
+ *rate_adjust = dropRatio->drop_ratio;
}
}
@@ -5142,6 +5168,7 @@ static bool mob_readdb_race2(char *fields[], int columns, int current)
static bool mob_readdb_itemratio(char *str[], int columns, int current)
{
int nameid, ratio, i;
+ struct item_drop_ratio *dropRatio;
nullpo_retr(false, str);
nameid = atoi(str[0]);
@@ -5154,12 +5181,15 @@ static bool mob_readdb_itemratio(char *str[], int columns, int current)
ratio = atoi(str[1]);
- if(item_drop_ratio_db[nameid] == NULL)
- item_drop_ratio_db[nameid] = (struct item_drop_ratio*)aCalloc(1, sizeof(struct item_drop_ratio));
+ dropRatio = mob->get_item_drop_ratio(nameid);
+ if (dropRatio == NULL) {
+ dropRatio = (struct item_drop_ratio*)aCalloc(1, sizeof(struct item_drop_ratio));
+ mob->set_item_drop_ratio(nameid, dropRatio);
+ }
- item_drop_ratio_db[nameid]->drop_ratio = ratio;
- for(i = 0; i < columns-2; i++)
- item_drop_ratio_db[nameid]->mob_id[i] = atoi(str[i+2]);
+ dropRatio->drop_ratio = ratio;
+ for (i = 0; i < columns - 2; i++)
+ dropRatio->mob_id[i] = atoi(str[i + 2]);
return true;
}
@@ -5183,6 +5213,19 @@ static void mob_load(bool minimal)
sv->readdb(map->db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, mob->readdb_race2);
}
+/**
+ * @see DBApply
+ */
+static int mob_final_ratio_sub(union DBKey key, struct DBData *data, va_list ap)
+{
+ struct item_drop_ratio *ratio = DB->data2ptr(data);
+
+ if (ratio)
+ aFree(ratio);
+
+ return 0;
+}
+
static void mob_reload(void)
{
int i;
@@ -5201,6 +5244,7 @@ static void mob_reload(void)
item_drop_ratio_db[i] = NULL;
}
}
+ mob->item_drop_ratio_other_db->clear(mob->item_drop_ratio_other_db, mob->final_ratio_sub);
mob->load(false);
}
@@ -5291,6 +5335,8 @@ static int do_final_mob(void)
item_drop_ratio_db[i] = NULL;
}
}
+ mob->item_drop_ratio_other_db->clear(mob->item_drop_ratio_other_db, mob->final_ratio_sub);
+ db_destroy(mob->item_drop_ratio_other_db);
ers_destroy(item_drop_ers);
ers_destroy(item_drop_list_ers);
return 0;
@@ -5334,6 +5380,10 @@ void mob_defaults(void)
memcpy(mob->splendide, mob_splendide, sizeof(mob->splendide));
memcpy(mob->mora, mob_mora, sizeof(mob->mora));
+ item_drop_ratio_other_db = idb_alloc(DB_OPT_BASE);
+ mob->item_drop_ratio_db = item_drop_ratio_db;
+ mob->item_drop_ratio_other_db = item_drop_ratio_other_db;
+
/* */
mob->reload = mob_reload;
mob->init = do_init_mob;
@@ -5438,6 +5488,9 @@ void mob_defaults(void)
mob->readdb_race2 = mob_readdb_race2;
mob->readdb_itemratio = mob_readdb_itemratio;
mob->load = mob_load;
+ mob->get_item_drop_ratio = mob_get_item_drop_ratio;
+ mob->set_item_drop_ratio = mob_set_item_drop_ratio;
+ mob->final_ratio_sub = mob_final_ratio_sub;
mob->clear_spawninfo = mob_clear_spawninfo;
mob->destroy_mob_db = mob_destroy_mob_db;
mob->skill_db_libconfig = mob_skill_db_libconfig;
diff --git a/src/map/mob.h b/src/map/mob.h
index 3ff3f213b..4cb3877ed 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -25,6 +25,7 @@
#include "map/status.h" // struct status_data, struct status_change
#include "map/unit.h" // struct unit_data, view_data
#include "common/hercules.h"
+#include "common/db.h"
#include "common/mmo.h" // struct item
struct hplugin_data_store;
@@ -72,6 +73,8 @@ struct hplugin_data_store;
// Disable this to make monsters not do any path search when looking for a target (old behavior).
#define ACTIVEPATHSEARCH
+struct item_drop_ratio;
+
enum e_bosstype {
BTYPE_NONE = 0,
BTYPE_BOSS = 1,
@@ -437,6 +440,8 @@ struct mob_interface {
int manuk[8];
int splendide[5];
int mora[5];
+ struct item_drop_ratio **item_drop_ratio_db;
+ struct DBMap *item_drop_ratio_other_db;
/* */
int (*init) (bool mimimal);
int (*final) (void);
@@ -543,6 +548,9 @@ struct mob_interface {
bool (*readdb_itemratio) (char *str[], int columns, int current);
void (*load) (bool minimal);
void (*clear_spawninfo) (void);
+ struct item_drop_ratio *(*get_item_drop_ratio) (int nameid);
+ void (*set_item_drop_ratio) (int nameid, struct item_drop_ratio *ratio);
+ int (*final_ratio_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*destroy_mob_db) (int index);
bool (*skill_db_libconfig) (const char *filename, bool ignore_missing);
bool (*skill_db_libconfig_sub) (struct config_setting_t *it, int n);