Quellcode durchsuchen

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

Cahyadi Ramadhan Togihon vor 11 Jahren
Ursprung
Commit
f17a385f86
7 geänderte Dateien mit 74 neuen und 82 gelöschten Zeilen
  1. 11 10
      doc/item_db.txt
  2. 1 0
      src/map/chrif.c
  3. 15 7
      src/map/itemdb.c
  4. 2 0
      src/map/itemdb.h
  5. 35 44
      src/map/pc.c
  6. 1 9
      src/map/pc.h
  7. 9 12
      src/map/status.c

+ 11 - 10
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
 
 ---------------------------------------
 

+ 1 - 0
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++;
 	}
 

+ 15 - 7
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();
 

+ 2 - 0
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);

+ 35 - 44
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;

+ 1 - 9
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;
 
 	/**

+ 9 - 12
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);