* Fixed some memleaks because of bonus_script and sd->combos.pair

* Updated 'doc/item_db.txt' following bd2503e

Signed-off-by: Cahyadi Ramadhan Togihon <house.bad@gmail.com>
This commit is contained in:
Cahyadi Ramadhan Togihon 2013-11-17 00:32:00 +07:00
parent fca76baad8
commit f17a385f86
7 changed files with 74 additions and 82 deletions

View File

@ -35,6 +35,7 @@ Type:
10 Ammo (Arrows/Bullets/etc) 10 Ammo (Arrows/Bullets/etc)
11 Usable with delayed consumption (item is lost from inventory 11 Usable with delayed consumption (item is lost from inventory
after selecting a target, for use with skills and pet lures) after selecting a target, for use with skills and pet lures)
12 Shadow Equipment
18 Another delayed consume that requires user confirmation before 18 Another delayed consume that requires user confirmation before
using item. using item.
@ -132,17 +133,17 @@ Loc: Equipment's placement. Values are (hexadecimal):
2^6 064 = Footgear 2^6 064 = Footgear
2^3 008 = Accessory 1 2^3 008 = Accessory 1
2^7 128 = Accessory 2 2^7 128 = Accessory 2
2^10 1024 = Costume Top Headgear 2^10 1024 = Costume Top Headgear
2^11 2048 = Costume Mid Headgear 2^11 2048 = Costume Mid Headgear
2^12 4096 = Costume Low Headgear 2^12 4096 = Costume Low Headgear
2^13 8192 = Costume Garment/Robe 2^13 8192 = Costume Garment/Robe
2^15 32768 = Ammo 2^15 32768 = Ammo
2^16 65536 = Shadow Armor 2^16 65536 = Shadow Armor
2^17 131072 = Shadow Weapon 2^17 131072 = Shadow Weapon
2^18 262144 = Shadow Shield 2^18 262144 = Shadow Shield
2^18 524288 = Shadow Shoes 2^18 524288 = Shadow Shoes
2^20 1048576 = Shadow Accessory 2 2^20 1048576 = Shadow Accessory 2
2^21 2097152 = Shadow Accessory 1 2^21 2097152 = Shadow Accessory 1
--------------------------------------- ---------------------------------------

View File

@ -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)); 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); delete_timer(sd->bonus_script[i].tid,pc_bonus_script_timer);
pc_bonus_script_remove(sd,i);
count++; count++;
} }

View File

@ -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] 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 * Search for item name
* name = item alias, so we should find items aliases first. if not found then look for "jname" (full 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 */ /* we flag this way to ensure we don't double-dealloc same data */
it->combos[index]->isRef = true; it->combos[index]->isRef = true;
} }
idb_put(itemdb_combo,id->combos[idx]->id,id->combos[idx]);
} }
count++; count++;
} }
@ -1380,7 +1385,7 @@ static void itemdb_read(void) {
*------------------------------------------*/ *------------------------------------------*/
/// Destroys the item_data. /// 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 ) if( self == NULL )
return; return;
@ -1419,7 +1424,7 @@ static int itemdb_final_sub(DBKey key, DBData *data, va_list ap)
struct item_data *id = db_data2ptr(data); struct item_data *id = db_data2ptr(data);
if( id != &dummy_item ) if( id != &dummy_item )
destroy_item_data(id, 1); destroy_item_data(id, true);
return 0; return 0;
} }
@ -1434,9 +1439,10 @@ void itemdb_reload(void)
// clear the previous itemdb data // clear the previous itemdb data
for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
if( 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); itemdb_other->clear(itemdb_other, itemdb_final_sub);
db_clear(itemdb_combo);
memset(itemdb_array, 0, sizeof(itemdb_array)); memset(itemdb_array, 0, sizeof(itemdb_array));
@ -1499,15 +1505,17 @@ void do_final_itemdb(void)
for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
if( 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); 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) { int do_init_itemdb(void) {
memset(itemdb_array, 0, sizeof(itemdb_array)); memset(itemdb_array, 0, sizeof(itemdb_array));
itemdb_other = idb_alloc(DB_OPT_BASE); itemdb_other = idb_alloc(DB_OPT_BASE);
itemdb_combo = idb_alloc(DB_OPT_BASE);
create_dummy_data(); //Dummy data item. create_dummy_data(); //Dummy data item.
itemdb_read(); itemdb_read();

View File

@ -242,6 +242,8 @@ int itemdb_isstackable2(struct item_data *);
uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID
bool itemdb_isNoEquip(struct item_data *id, uint16 m); bool itemdb_isNoEquip(struct item_data *id, uint16 m);
DBMap * itemdb_get_combodb();
void itemdb_reload(void); void itemdb_reload(void);
void do_final_itemdb(void); void do_final_itemdb(void);

View File

@ -8462,15 +8462,18 @@ int pc_cleareventtimer(struct map_session_data *sd)
} }
return 0; 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 i, j, k, z;
int index, idx, success = 0; int index, idx, success = 0;
for( i = 0; i < data->combos_count; i++ ) { for( i = 0; i < data->combos_count; i++ ) {
struct s_combo_pair *pair;
uint8 pair_idx = 0;
/* ensure this isn't a duplicate combo */ /* ensure this isn't a duplicate combo */
if( sd->combos.bonus != NULL ) { if( sd->combos.bonus != NULL ) {
int x; int x;
@ -8481,7 +8484,6 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
continue; continue;
} }
CREATE(pair,struct s_combo_pair,1);
for( j = 0; j < data->combos[i]->count; j++ ) { for( j = 0; j < data->combos[i]->count; j++ ) {
int id = data->combos[i]->nameid[j]; int id = data->combos[i]->nameid[j];
bool found = false; 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 ( itemdb_type(id) != IT_CARD ) {
if ( sd->inventory_data[index]->nameid != id ) if ( sd->inventory_data[index]->nameid != id )
continue; continue;
found = true; found = true;
pair->nameid[pair_idx] = id;
pair_idx ++;
break; break;
} else { //Cards } else { //Cards
if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0]) ) if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0]) )
continue; continue;
for (z = 0; z < sd->inventory_data[index]->slot; z++) { for (z = 0; z < sd->inventory_data[index]->slot; z++) {
if (sd->status.inventory[index].card[z] != id) if (sd->status.inventory[index].card[z] != id)
continue; continue;
// We have found a match
found = true; found = true;
pair->nameid[pair_idx] = id;
pair_idx ++;
break; break;
} }
} }
} }
if( !found ) if( !found )
break;/* we haven't found all the ids for this combo, so we can return */ 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 */ /* 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 ) if( j < data->combos[i]->count )
continue; continue;
/* we got here, means all items in the combo are matching */ /* we got here, means all items in the combo are matching */
idx = sd->combos.count; idx = sd->combos.count;
if( sd->combos.bonus == NULL ) { if( sd->combos.bonus == NULL ) {
CREATE(sd->combos.bonus, struct script_code *, 1); CREATE(sd->combos.bonus, struct script_code *, 1);
CREATE(sd->combos.id, unsigned short, 1); CREATE(sd->combos.id, unsigned short, 1);
sd->combos.count = 1; sd->combos.count = 1;
CREATE(sd->combos.pair, struct s_combo_pair *, 1);
} else { } else {
RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count); RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count);
RECREATE(sd->combos.id, unsigned short, 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 */ /* we simply copy the pointer */
sd->combos.bonus[idx] = data->combos[i]->script; sd->combos.bonus[idx] = data->combos[i]->script;
/* save this combo's id */ /* save this combo's id */
sd->combos.id[idx] = data->combos[i]->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++; success++;
} }
return 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 pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
int i, retval = 0; 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.bonus[x] = NULL;
sd->combos.id[x] = 0; sd->combos.id[x] = 0;
sd->combos.pair[x] = NULL;
retval++; retval++;
/* move next value to empty slot */ /* 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 ) { if( cursor != j ) {
sd->combos.bonus[cursor] = sd->combos.bonus[j]; sd->combos.bonus[cursor] = sd->combos.bonus[j];
sd->combos.id[cursor] = sd->combos.id[j]; sd->combos.id[cursor] = sd->combos.id[j];
sd->combos.pair[cursor] = sd->combos.pair[j];
} }
cursor++; cursor++;
} }
@ -8596,16 +8583,20 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
if( (sd->combos.count = cursor) == 0 ) { if( (sd->combos.count = cursor) == 0 ) {
aFree(sd->combos.bonus); aFree(sd->combos.bonus);
aFree(sd->combos.id); aFree(sd->combos.id);
aFree(sd->combos.pair);
sd->combos.bonus = NULL; sd->combos.bonus = NULL;
sd->combos.id = 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; /* we also can return at this point for we have no more combos to check */
} }
} }
return retval; 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 pc_load_combo(struct map_session_data *sd) {
int i, ret = 0; int i, ret = 0;
for( i = 0; i < EQI_MAX; i++ ) { 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; 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. pos = pc_equippoint(sd,n); //With a few exceptions, item should go in all specified slots.
if(battle_config.battle_log) 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; iflag = sd->npc_item_flag;
/* check for combos (MUST be before status_calc_pc) */ /* check for combos (MUST be before status_calc_pc) */
if ( id ) { if( id->combos_count )
if( id->combos_count ) pc_checkcombo(sd,id);
pc_checkcombo(sd,id); if(itemdb_isspecial(sd->status.inventory[n].card[0]))
if(itemdb_isspecial(sd->status.inventory[n].card[0])) ; //No cards
; //No cards else {
else { for( i = 0; i < id->slot; i++ ) {
for( i = 0; i < id->slot; i++ ) { struct item_data *data;
struct item_data *data; if (!sd->status.inventory[n].card[i])
if (!sd->status.inventory[n].card[i]) continue;
continue; if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { if( data->combos_count )
if( data->combos_count ) pc_checkcombo(sd,data);
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) if (!sd || i >= MAX_PC_BONUS_SCRIPT)
return; 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,0,sizeof(sd->bonus_script[i].script));
memset(sd->bonus_script[i].script_str,'\0',sizeof(sd->bonus_script[i].script_str)); memset(sd->bonus_script[i].script_str,'\0',sizeof(sd->bonus_script[i].script_str));
sd->bonus_script[i].tick = 0; sd->bonus_script[i].tick = 0;

View File

@ -24,7 +24,7 @@
#define MAX_PC_SKILL_REQUIRE 5 #define MAX_PC_SKILL_REQUIRE 5
#define MAX_PC_FEELHATE 3 #define MAX_PC_FEELHATE 3
#define DAMAGELOG_SIZE_PC 100 // Any idea for this value? #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 //Update this max as necessary. 55 is the value needed for Super Baby currently
//Raised to 84 since Expanded Super Novice needs it. //Raised to 84 since Expanded Super Novice needs it.
@ -133,13 +133,6 @@ enum npc_timeout_type {
NPCT_WAIT = 2, NPCT_WAIT = 2,
}; };
/*
* Combo's items
*/
struct s_combo_pair {
uint16 nameid[MAX_ITEMS_PER_COMBO];
};
struct map_session_data { struct map_session_data {
struct block_list bl; struct block_list bl;
struct unit_data ud; struct unit_data ud;
@ -527,7 +520,6 @@ struct map_session_data {
struct script_code **bonus;/* the script */ struct script_code **bonus;/* the script */
unsigned short *id;/* array of combo ids */ unsigned short *id;/* array of combo ids */
unsigned char count; unsigned char count;
struct s_combo_pair **pair;
} combos; } combos;
/** /**

View File

@ -2704,27 +2704,24 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
// We've got combos to process and check // We've got combos to process and check
if( sd->combos.count ) { if( sd->combos.count ) {
DBMap *combo_db = itemdb_get_combodb();
for (i = 0; i < sd->combos.count; i++) { for (i = 0; i < sd->combos.count; i++) {
uint8 j; uint8 j = 0;
bool no_run = false; 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]) if (!sd->combos.bonus[i])
continue; continue;
// Check combo items // Check combo items
CREATE(ids,struct s_combo_pair,1); while (j < combo->count) {
memcpy(ids, &sd->combos.pair[i], sizeof(ids)); struct item_data *id = itemdb_exists(combo->nameid[j]);
for (j = 0; j < MAX_ITEMS_PER_COMBO; j++) { // Don't run the script if at least one of combo's pair has restriction
uint16 nameid = ids->nameid[j]; if (id && !pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(id, sd->bl.m)) {
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)) {
no_run = true; no_run = true;
break; break;
} }
j++;
} }
aFree(ids);
if (no_run) if (no_run)
continue; continue;
run_script(sd->combos.bonus[i],0,sd->bl.id,0); run_script(sd->combos.bonus[i],0,sd->bl.id,0);