summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/itemdb.c194
-rw-r--r--src/map/itemdb.h10
-rw-r--r--src/map/pc.c38
3 files changed, 207 insertions, 35 deletions
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index f7b2da7cb..2acb18714 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -735,6 +735,133 @@ static bool itemdb_read_buyingstore(char* fields[], int columns, int current)
return true;
}
+/**
+ * @return: amount of retrieved entries.
+ **/
+int itemdb_combo_split_atoi (char *str, int *val) {
+ int i;
+
+ for (i=0; i<MAX_ITEMS_PER_COMBO; i++) {
+ if (!str) break;
+
+ val[i] = atoi(str);
+
+ str = strchr(str,':');
+
+ if (str)
+ *str++=0;
+ }
+
+ if( i == 0 ) //No data found.
+ return 0;
+
+ return i;
+}
+/**
+ * <combo{:combo{:combo:{..}}}>,<{ script }>
+ **/
+void itemdb_read_combos(DBMap* item_combo_db) {
+ uint32 lines = 0, count = 0;
+ char line[1024];
+
+ char path[256];
+ FILE* fp;
+
+ sprintf(path, "%s/%s", db_path, DBPATH"item_combo_db.txt");
+
+ if ((fp = fopen(path, "r")) == NULL) {
+ ShowError("itemdb_read_combos: File not found \"%s\".\n", path);
+ return;
+ }
+
+ // process rows one by one
+ while(fgets(line, sizeof(line), fp)) {
+ char *str[2], *p;
+
+ lines++;
+
+ if (line[0] == '/' && line[1] == '/')
+ continue;
+
+ memset(str, 0, sizeof(str));
+
+ p = line;
+ while (ISSPACE(*p))
+ ++p;
+
+ if (*p == '\0')
+ continue;// empty line
+
+ if (!strchr(p,','))
+ {
+ /* is there even a single column? */
+ ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, path);
+ continue;
+ }
+
+ str[0] = p;
+ p = strchr(p,',');
+ *p = '\0';
+ p++;
+
+ str[1] = p;
+ p = strchr(p,',');
+ p++;
+
+ if (str[1][0] != '{') {
+ ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
+ continue;
+ }
+
+ /* no ending key anywhere (missing \}\) */
+ if ((p = strstr(p + 1, "}")) == NULL ) {
+ ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
+ continue;
+ } else {
+ int items[MAX_ITEMS_PER_COMBO];
+ int v = 0, retcount = 0;
+ struct item_combo * ic = NULL;
+ char combo_out[2048];
+ int len = 0, slen = 0;
+ bool exists = false;
+
+ if((retcount = itemdb_combo_split_atoi(str[0], items)) < 2) {
+ ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, path);
+ continue;
+ }
+
+ if ((ic = idb_get(item_combo_db, items[0])) != NULL) {
+ slen = strlen(ic->script);
+ exists = true;
+ } else {
+ CREATE(ic, struct item_combo, 1);
+ }
+
+ len += sprintf(combo_out + len, "if(isequipped(");
+
+ /* we skip the first for its not a required check */
+ for(v = 1; v < retcount; v++) {
+ len += sprintf(combo_out + len, "%d,", items[v]);
+ }
+
+ len += sprintf(combo_out + len - 1, "))%s", str[1]);
+
+ safestrncpy(ic->script + (slen?slen-1:0), combo_out, len);
+
+ if (!exists)
+ idb_put(item_combo_db, items[0], ic);
+ }
+
+ count++;
+ }
+
+ fclose(fp);
+
+ ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"item_combo_db"CL_RESET"'.\n", count);
+
+ return;
+}
+
/*======================================
@@ -785,7 +912,7 @@ void itemdb_re_split_atoi(char *str, int *atk, int *matk) {
/*==========================================
* processes one itemdb entry
*------------------------------------------*/
-static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt)
+static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt, char *comboScript)
{
/*
+----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
@@ -899,8 +1026,26 @@ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scr
id->unequip_script = NULL;
}
- if (*str[19])
- id->script = parse_script(str[19], source, line, scriptopt);
+ if (*str[19]) {
+ char *scriptCode = str[19];
+
+ if ( comboScript ) {
+ char *script1 = str[19];
+
+ while (*script1++ != '{');
+
+ scriptCode = (char *)aMalloc(strlen(script1) + strlen(comboScript) + 2); // +2 = {\0
+ sprintf(scriptCode, "{%s%s", comboScript, script1);
+ }
+
+ id->script = parse_script(scriptCode, source, line, scriptopt);
+
+ if( comboScript )
+ aFree(scriptCode);
+
+ } else if ( comboScript )
+ id->script = parse_script(comboScript, source, line, scriptopt);
+
if (*str[20])
id->equip_script = parse_script(str[20], source, line, scriptopt);
if (*str[21])
@@ -919,9 +1064,11 @@ static int itemdb_readdb(void)
"item_db2.txt" };
int fi;
+ DBMap* item_combo_db = idb_alloc(DB_OPT_RELEASE_DATA);
+
+ itemdb_read_combos(item_combo_db);
- for( fi = 0; fi < ARRAYLENGTH(filename); ++fi )
- {
+ for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) {
uint32 lines = 0, count = 0;
char line[1024];
@@ -930,8 +1077,7 @@ static int itemdb_readdb(void)
sprintf(path, "%s/%s", db_path, filename[fi]);
fp = fopen(path, "r");
- if( fp == NULL )
- {
+ if( fp == NULL ) {
ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path);
continue;
}
@@ -941,7 +1087,8 @@ static int itemdb_readdb(void)
{
char *str[32], *p;
int i;
-
+ struct item_combo *ic = NULL;
+ char *script2 = NULL;
lines++;
if(line[0] == '/' && line[1] == '/')
continue;
@@ -1015,9 +1162,16 @@ static int itemdb_readdb(void)
continue;
}
- if (!itemdb_parse_dbrow(str, path, lines, 0))
+ if ((ic = idb_get(item_combo_db, atoi(str[0])))) {
+ script2 = ic->script;
+ }
+
+ if (!itemdb_parse_dbrow(str, path, lines, 0, script2))
continue;
+ if( script2 != NULL )
+ idb_remove(item_combo_db,atoi(str[0]));
+
count++;
}
@@ -1026,6 +1180,13 @@ static int itemdb_readdb(void)
ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename[fi]);
}
+ if( db_size(item_combo_db) ) {
+ /* non-processed entries */
+ ShowWarning("item_combo_db: There are %d unused entries in the file (combo(s) with non-available item IDs)\n",db_size(item_combo_db));
+ }
+
+ db_destroy(item_combo_db);
+
return 0;
}
@@ -1065,7 +1226,7 @@ static int itemdb_read_sqldb(void)
if( str[i] == NULL ) str[i] = dummy; // get rid of NULL columns
}
- if (!itemdb_parse_dbrow(str, item_db_name[fi], lines, SCRIPT_IGNORE_EXTERNAL_BRACKETS))
+ if (!itemdb_parse_dbrow(str, item_db_name[fi], lines, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL))
continue;
++count;
}
@@ -1082,8 +1243,8 @@ static int itemdb_read_sqldb(void)
/*====================================
* read all item-related databases
*------------------------------------*/
-static void itemdb_read(void)
-{
+static void itemdb_read(void) {
+
if (db_use_sqldbs)
itemdb_read_sqldb();
else
@@ -1095,7 +1256,7 @@ static void itemdb_read(void)
sv_readdb(db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade);
sv_readdb(db_path, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay);
sv_readdb(db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack);
- sv_readdb(db_path, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore);
+ sv_readdb(db_path, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore);
}
/*==========================================
@@ -1151,7 +1312,7 @@ void itemdb_reload(void)
itemdb_other->clear(itemdb_other, itemdb_final_sub);
memset(itemdb_array, 0, sizeof(itemdb_array));
-
+
// read new data
itemdb_read();
@@ -1205,10 +1366,9 @@ void do_final_itemdb(void)
destroy_item_data(&dummy_item, 0);
}
-int do_init_itemdb(void)
-{
+int do_init_itemdb(void) {
memset(itemdb_array, 0, sizeof(itemdb_array));
- itemdb_other = idb_alloc(DB_OPT_BASE);
+ itemdb_other = idb_alloc(DB_OPT_BASE);
create_dummy_data(); //Dummy data item.
itemdb_read();
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index a19ac45e0..f84330522 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -4,8 +4,9 @@
#ifndef _ITEMDB_H_
#define _ITEMDB_H_
+#include "../common/db.h"
#include "../common/mmo.h" // ITEM_NAME_LENGTH
-#include "map.h" //REMODE
+#include "map.h"
// 32k array entries in array (the rest goes to the db)
#define MAX_ITEMDB 0x8000
@@ -17,6 +18,9 @@
#define MAX_SEARCH 5 //Designed for search functions, species max number of matches to display.
+/* maximum amount of items a combo may require */
+#define MAX_ITEMS_PER_COMBO 6
+
enum item_itemid {
ITEMID_EMPERIUM = 714,
ITEMID_YELLOW_GEMSTONE = 715,
@@ -141,6 +145,10 @@ struct item_group {
int qty; //Counts amount of items in the group.
};
+struct item_combo {
+ char script[2048]; /* combo script */
+};
+
struct item_data* itemdb_searchname(const char *name);
int itemdb_searchname_array(struct item_data** data, int size, const char *str);
struct item_data* itemdb_load(int nameid);
diff --git a/src/map/pc.c b/src/map/pc.c
index e1ba324b1..6c15adce6 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -999,7 +999,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
if (!(battle_config.display_skill_fail&2))
sd->state.showdelay = 1;
-
+
pc_setinventorydata(sd);
pc_setequipindex(sd);
@@ -8012,14 +8012,15 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
run_script(id->equip_script,0,sd->bl.id,fake_nd->bl.id);
if(itemdb_isspecial(sd->status.inventory[n].card[0]))
; //No cards
- else
- for(i=0;i<id->slot; i++)
- {
- if (!sd->status.inventory[n].card[i])
- continue;
- data = itemdb_exists(sd->status.inventory[n].card[i]);
- if (data && data->equip_script)
- run_script(data->equip_script,0,sd->bl.id,fake_nd->bl.id);
+ else {
+ for( i = 0; i < id->slot; i++ ) {
+ if (!sd->status.inventory[n].card[i])
+ continue;
+ if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
+ if( data->equip_script )
+ run_script(data->equip_script,0,sd->bl.id,fake_nd->bl.id);
+ }
+ }
}
}
return 0;
@@ -8140,14 +8141,17 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
run_script(sd->inventory_data[n]->unequip_script,0,sd->bl.id,fake_nd->bl.id);
if(itemdb_isspecial(sd->status.inventory[n].card[0]))
; //No cards
- else
- for(i=0;i<sd->inventory_data[n]->slot; i++)
- {
- if (!sd->status.inventory[n].card[i])
- continue;
- data = itemdb_exists(sd->status.inventory[n].card[i]);
- if (data && data->unequip_script)
- run_script(data->unequip_script,0,sd->bl.id,fake_nd->bl.id);
+ else {
+ for( i = 0; i < sd->inventory_data[n]->slot; i++ ) {
+ if (!sd->status.inventory[n].card[i])
+ continue;
+
+ if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
+ if( data->unequip_script )
+ run_script(data->unequip_script,0,sd->bl.id,fake_nd->bl.id);
+ }
+
+ }
}
}