From f17a385f86581a9227c6ea455d670d46e61d6ef0 Mon Sep 17 00:00:00 2001 From: Cahyadi Ramadhan Togihon Date: Sun, 17 Nov 2013 00:32:00 +0700 Subject: [PATCH] * Fixed some memleaks because of bonus_script and sd->combos.pair * Updated 'doc/item_db.txt' following bd2503e Signed-off-by: Cahyadi Ramadhan Togihon --- doc/item_db.txt | 21 +++++++------ src/map/chrif.c | 1 + src/map/itemdb.c | 22 +++++++++----- src/map/itemdb.h | 2 ++ src/map/pc.c | 79 +++++++++++++++++++++--------------------------- src/map/pc.h | 10 +----- src/map/status.c | 21 ++++++------- 7 files changed, 74 insertions(+), 82 deletions(-) diff --git a/doc/item_db.txt b/doc/item_db.txt index 2609d6f643..0cc258383e 100644 --- a/doc/item_db.txt +++ b/doc/item_db.txt @@ -35,6 +35,7 @@ Type: 10 Ammo (Arrows/Bullets/etc) 11 Usable with delayed consumption (item is lost from inventory after selecting a target, for use with skills and pet lures) + 12 Shadow Equipment 18 Another delayed consume that requires user confirmation before using item. @@ -132,17 +133,17 @@ Loc: Equipment's placement. Values are (hexadecimal): 2^6 064 = Footgear 2^3 008 = Accessory 1 2^7 128 = Accessory 2 - 2^10 1024 = Costume Top Headgear - 2^11 2048 = Costume Mid Headgear - 2^12 4096 = Costume Low Headgear - 2^13 8192 = Costume Garment/Robe + 2^10 1024 = Costume Top Headgear + 2^11 2048 = Costume Mid Headgear + 2^12 4096 = Costume Low Headgear + 2^13 8192 = Costume Garment/Robe 2^15 32768 = Ammo - 2^16 65536 = Shadow Armor - 2^17 131072 = Shadow Weapon - 2^18 262144 = Shadow Shield - 2^18 524288 = Shadow Shoes - 2^20 1048576 = Shadow Accessory 2 - 2^21 2097152 = Shadow Accessory 1 + 2^16 65536 = Shadow Armor + 2^17 131072 = Shadow Weapon + 2^18 262144 = Shadow Shield + 2^18 524288 = Shadow Shoes + 2^20 1048576 = Shadow Accessory 2 + 2^21 2097152 = Shadow Accessory 1 --------------------------------------- diff --git a/src/map/chrif.c b/src/map/chrif.c index 054da49c84..933b5ce26b 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1760,6 +1760,7 @@ int chrif_save_bsdata(struct map_session_data *sd) { memcpy(WFIFOP(char_fd,10+count*sizeof(struct bonus_script_data)),&bs,sizeof(struct bonus_script_data)); delete_timer(sd->bonus_script[i].tid,pc_bonus_script_timer); + pc_bonus_script_remove(sd,i); count++; } diff --git a/src/map/itemdb.c b/src/map/itemdb.c index e56327ecfc..37539747a2 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -25,6 +25,12 @@ static struct item_group itemgroup_db[MAX_ITEMGROUP]; struct item_data dummy_item; //This is the default dummy item used for non-existant items. [Skotlex] +static DBMap *itemdb_combo; + +DBMap * itemdb_get_combodb(){ + return itemdb_combo; +} + /** * Search for item name * name = item alias, so we should find items aliases first. if not found then look for "jname" (full name) @@ -924,9 +930,8 @@ void itemdb_read_combos() { /* we flag this way to ensure we don't double-dealloc same data */ it->combos[index]->isRef = true; } - + idb_put(itemdb_combo,id->combos[idx]->id,id->combos[idx]); } - count++; } @@ -1380,7 +1385,7 @@ static void itemdb_read(void) { *------------------------------------------*/ /// Destroys the item_data. -static void destroy_item_data(struct item_data* self, int free_self) +static void destroy_item_data(struct item_data* self, bool free_self) { if( self == NULL ) return; @@ -1419,7 +1424,7 @@ static int itemdb_final_sub(DBKey key, DBData *data, va_list ap) struct item_data *id = db_data2ptr(data); if( id != &dummy_item ) - destroy_item_data(id, 1); + destroy_item_data(id, true); return 0; } @@ -1434,9 +1439,10 @@ void itemdb_reload(void) // clear the previous itemdb data for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) if( itemdb_array[i] ) - destroy_item_data(itemdb_array[i], 1); + destroy_item_data(itemdb_array[i], true); itemdb_other->clear(itemdb_other, itemdb_final_sub); + db_clear(itemdb_combo); memset(itemdb_array, 0, sizeof(itemdb_array)); @@ -1499,15 +1505,17 @@ void do_final_itemdb(void) for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) if( itemdb_array[i] ) - destroy_item_data(itemdb_array[i], 1); + destroy_item_data(itemdb_array[i], true); itemdb_other->destroy(itemdb_other, itemdb_final_sub); - destroy_item_data(&dummy_item, 0); + destroy_item_data(&dummy_item, false); + db_destroy(itemdb_combo); } int do_init_itemdb(void) { memset(itemdb_array, 0, sizeof(itemdb_array)); itemdb_other = idb_alloc(DB_OPT_BASE); + itemdb_combo = 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 6e33c4f032..395551c71e 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -242,6 +242,8 @@ int itemdb_isstackable2(struct item_data *); uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID bool itemdb_isNoEquip(struct item_data *id, uint16 m); +DBMap * itemdb_get_combodb(); + void itemdb_reload(void); void do_final_itemdb(void); diff --git a/src/map/pc.c b/src/map/pc.c index c4ba40bbca..b7f801c3f2 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -8462,15 +8462,18 @@ int pc_cleareventtimer(struct map_session_data *sd) } return 0; } -/* called when a item with combo is worn */ -int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { + +/** +* Called when an item with combo is worn +* @param *sd +* @param *data struct item_data +* @return success numbers of succeed combo +*/ +int pc_checkcombo(struct map_session_data *sd, struct item_data *data) { int i, j, k, z; int index, idx, success = 0; for( i = 0; i < data->combos_count; i++ ) { - struct s_combo_pair *pair; - uint8 pair_idx = 0; - /* ensure this isn't a duplicate combo */ if( sd->combos.bonus != NULL ) { int x; @@ -8481,7 +8484,6 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { continue; } - CREATE(pair,struct s_combo_pair,1); for( j = 0; j < data->combos[i]->count; j++ ) { int id = data->combos[i]->nameid[j]; bool found = false; @@ -8499,30 +8501,19 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { if ( itemdb_type(id) != IT_CARD ) { if ( sd->inventory_data[index]->nameid != id ) continue; - found = true; - pair->nameid[pair_idx] = id; - pair_idx ++; break; } else { //Cards if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0]) ) continue; - for (z = 0; z < sd->inventory_data[index]->slot; z++) { - if (sd->status.inventory[index].card[z] != id) continue; - - // We have found a match found = true; - pair->nameid[pair_idx] = id; - pair_idx ++; break; } } - } - if( !found ) break;/* we haven't found all the ids for this combo, so we can return */ } @@ -8530,33 +8521,31 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { /* means we broke out of the count loop w/o finding all ids, we can move to the next combo */ if( j < data->combos[i]->count ) continue; - /* we got here, means all items in the combo are matching */ idx = sd->combos.count; if( sd->combos.bonus == NULL ) { CREATE(sd->combos.bonus, struct script_code *, 1); CREATE(sd->combos.id, unsigned short, 1); sd->combos.count = 1; - CREATE(sd->combos.pair, struct s_combo_pair *, 1); } else { RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count); RECREATE(sd->combos.id, unsigned short, sd->combos.count); - RECREATE(sd->combos.pair, struct s_combo_pair *, sd->combos.count); } /* we simply copy the pointer */ sd->combos.bonus[idx] = data->combos[i]->script; /* save this combo's id */ sd->combos.id[idx] = data->combos[i]->id; - /* store the items id that trigger this combo */ - memcpy(&sd->combos.pair[idx], pair, sizeof(pair)); - aFree(pair); - success++; } return success; } -/* called when a item with combo is removed */ +/** +* Called when an item with combo is removed +* @param *sd +* @param *data struct item_data +* @return retval numbers of removed combo +*/ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { int i, retval = 0; @@ -8572,7 +8561,6 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { sd->combos.bonus[x] = NULL; sd->combos.id[x] = 0; - sd->combos.pair[x] = NULL; retval++; /* move next value to empty slot */ @@ -8583,7 +8571,6 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { if( cursor != j ) { sd->combos.bonus[cursor] = sd->combos.bonus[j]; sd->combos.id[cursor] = sd->combos.id[j]; - sd->combos.pair[cursor] = sd->combos.pair[j]; } cursor++; } @@ -8596,16 +8583,20 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { if( (sd->combos.count = cursor) == 0 ) { aFree(sd->combos.bonus); aFree(sd->combos.id); - aFree(sd->combos.pair); sd->combos.bonus = NULL; sd->combos.id = NULL; - sd->combos.pair = NULL; return retval; /* we also can return at this point for we have no more combos to check */ } } return retval; } + +/** +* Load combo data(s) of player +* @param *sd +* @return ret numbers of succeed combo +*/ int pc_load_combo(struct map_session_data *sd) { int i, ret = 0; for( i = 0; i < EQI_MAX; i++ ) { @@ -8659,7 +8650,8 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) return 0; } - id = sd->inventory_data[n]; + if (!(id = sd->inventory_data[n])) + return 0; pos = pc_equippoint(sd,n); //With a few exceptions, item should go in all specified slots. if(battle_config.battle_log) @@ -8800,20 +8792,18 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) iflag = sd->npc_item_flag; /* check for combos (MUST be before status_calc_pc) */ - if ( id ) { - if( id->combos_count ) - pc_checkcombo(sd,id); - if(itemdb_isspecial(sd->status.inventory[n].card[0])) - ; //No cards - else { - for( i = 0; i < id->slot; i++ ) { - struct item_data *data; - if (!sd->status.inventory[n].card[i]) - continue; - if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { - if( data->combos_count ) - pc_checkcombo(sd,data); - } + if( id->combos_count ) + pc_checkcombo(sd,id); + if(itemdb_isspecial(sd->status.inventory[n].card[0])) + ; //No cards + else { + for( i = 0; i < id->slot; i++ ) { + struct item_data *data; + if (!sd->status.inventory[n].card[i]) + continue; + if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { + if( data->combos_count ) + pc_checkcombo(sd,data); } } } @@ -10419,6 +10409,7 @@ void pc_bonus_script_remove(struct map_session_data *sd, uint8 i) { if (!sd || i >= MAX_PC_BONUS_SCRIPT) return; + script_free_code(sd->bonus_script[i].script); memset(&sd->bonus_script[i].script,0,sizeof(sd->bonus_script[i].script)); memset(sd->bonus_script[i].script_str,'\0',sizeof(sd->bonus_script[i].script_str)); sd->bonus_script[i].tick = 0; diff --git a/src/map/pc.h b/src/map/pc.h index bc0b6ba6a0..6e2693ebfb 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -24,7 +24,7 @@ #define MAX_PC_SKILL_REQUIRE 5 #define MAX_PC_FEELHATE 3 #define DAMAGELOG_SIZE_PC 100 // Any idea for this value? -#define MAX_PC_BONUS_SCRIPT 10 +#define MAX_PC_BONUS_SCRIPT 20 //Update this max as necessary. 55 is the value needed for Super Baby currently //Raised to 84 since Expanded Super Novice needs it. @@ -133,13 +133,6 @@ enum npc_timeout_type { NPCT_WAIT = 2, }; -/* - * Combo's items - */ -struct s_combo_pair { - uint16 nameid[MAX_ITEMS_PER_COMBO]; -}; - struct map_session_data { struct block_list bl; struct unit_data ud; @@ -527,7 +520,6 @@ struct map_session_data { struct script_code **bonus;/* the script */ unsigned short *id;/* array of combo ids */ unsigned char count; - struct s_combo_pair **pair; } combos; /** diff --git a/src/map/status.c b/src/map/status.c index 13832dafae..48925e57f7 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -2704,27 +2704,24 @@ int status_calc_pc_(struct map_session_data* sd, bool first) // We've got combos to process and check if( sd->combos.count ) { + DBMap *combo_db = itemdb_get_combodb(); for (i = 0; i < sd->combos.count; i++) { - uint8 j; + uint8 j = 0; bool no_run = false; - struct s_combo_pair *ids; + struct item_combo *combo = (struct item_combo *)idb_get(combo_db,sd->combos.id[i]); + if (!sd->combos.bonus[i]) continue; // Check combo items - CREATE(ids,struct s_combo_pair,1); - memcpy(ids, &sd->combos.pair[i], sizeof(ids)); - for (j = 0; j < MAX_ITEMS_PER_COMBO; j++) { - uint16 nameid = ids->nameid[j]; - struct item_data *id = NULL; - if (!nameid || !(id = itemdb_exists(nameid))) - continue; - // Don't run the script if the items has restriction - if (!pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(id, sd->bl.m)) { + while (j < combo->count) { + struct item_data *id = itemdb_exists(combo->nameid[j]); + // Don't run the script if at least one of combo's pair has restriction + if (id && !pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(id, sd->bl.m)) { no_run = true; break; } + j++; } - aFree(ids); if (no_run) continue; run_script(sd->combos.bonus[i],0,sd->bl.id,0);