* 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)
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
---------------------------------------

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

View File

@ -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);

View File

@ -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;

View File

@ -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;
/**

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
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);