From ff4d9ac980318119e4293de7057a811dcf798d7d Mon Sep 17 00:00:00 2001 From: shennetsind Date: Wed, 11 Jul 2012 11:26:55 +0000 Subject: Implementing Kenpachi's design of item_combo_db.txt - Credits to Kenpachi and Masao for the db file edits. - Credits to GreenBox for the parsing - This commit might accidentally override a few item db entries, our db developers are expecting this and will work on the conflicting entries. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16393 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/itemdb.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++----- src/map/itemdb.h | 10 ++- src/map/pc.c | 38 ++++++----- 3 files changed, 207 insertions(+), 35 deletions(-) (limited to 'src') 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,<{ 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;islot; 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;iinventory_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); + } + + } } } -- cgit v1.2.3-70-g09d2