Pārlūkot izejas kodu

* Follow up 51074a0: Remove ugly fixed array size! It increases memory usage too much!
* A little optimization on skill_db for skill requirement

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>

Cydh Ramdh 11 gadi atpakaļ
vecāks
revīzija
5143c4c36f
4 mainītis faili ar 186 papildinājumiem un 109 dzēšanām
  1. 82 44
      src/map/itemdb.c
  2. 19 15
      src/map/itemdb.h
  3. 76 41
      src/map/skill.c
  4. 9 9
      src/map/skill.h

+ 82 - 44
src/map/itemdb.c

@@ -160,8 +160,8 @@ unsigned short itemdb_searchrandomid(int group_id, uint8 sub_group)
 		ShowError("itemdb_searchrandomid: Invalid sub_group %d\n", sub_group+1);
 		return UNKNOWN_ITEM_ID;
 	}
-	if (itemgroup_db[group_id].random_qty[sub_group])
-		return itemgroup_db[group_id].random[sub_group][rnd()%itemgroup_db[group_id].random_qty[sub_group]].nameid;
+	if (&itemgroup_db[group_id].random[sub_group] && itemgroup_db[group_id].random[sub_group].data_qty)
+		return itemgroup_db[group_id].random[sub_group].data[rand()%itemgroup_db[group_id].random[sub_group].data_qty].nameid;
 
 	ShowError("itemdb_searchrandomid: No item entries for group id %d and sub group %d\n", group_id, sub_group+1);
 	return UNKNOWN_ITEM_ID;
@@ -187,9 +187,11 @@ uint16 itemdb_get_randgroupitem_count(uint16 group_id, uint8 sub_group, uint16 n
 		ShowError("itemdb_get_randgroupitem_count: Invalid sub_group id %d\n", group_id+1);
 		return amt;
 	}
-	ARR_FIND(0,itemgroup_db[group_id].random_qty[sub_group],i,itemgroup_db[group_id].random[sub_group][i].nameid == nameid);
-	if (i < MAX_ITEMGROUP_RAND)
-		amt = itemgroup_db[group_id].random[sub_group][i].amount;
+	if (!(&itemgroup_db[group_id].random[sub_group]) || !itemgroup_db[group_id].random[sub_group].data_qty)
+		return amt;
+	ARR_FIND(0,itemgroup_db[group_id].random[sub_group].data_qty,i,itemgroup_db[group_id].random[sub_group].data[i].nameid == nameid);
+	if (i < itemgroup_db[group_id].random[sub_group].data_qty)
+		amt = itemgroup_db[group_id].random[sub_group].data[i].amount;
 	return amt;
 }
 
@@ -251,23 +253,23 @@ char itemdb_pc_get_itemgroup(uint16 group_id, struct map_session_data *sd) {
 	}
 	
 	//Get the 'must' item(s)
-	for (i = 0; i < itemgroup_db[group_id].must_qty; i++) {
-		if (&itemgroup_db[group_id].must[i] && itemdb_exists(itemgroup_db[group_id].must[i].nameid))
-			itemdb_pc_get_itemgroup_sub(sd,group_id,&itemgroup_db[group_id].must[i]);
-	}
+	if (itemgroup_db[group_id].must_qty)
+		for (i = 0; i < itemgroup_db[group_id].must_qty; i++)
+			if (&itemgroup_db[group_id].must[i] && itemdb_exists(itemgroup_db[group_id].must[i].nameid))
+				itemdb_pc_get_itemgroup_sub(sd,group_id,&itemgroup_db[group_id].must[i]);
 
 	//Get the 'random' item each random group
 	for (i = 0; i < MAX_ITEMGROUP_RANDGROUP; i++) {
 		uint16 rand;
-		if (!itemgroup_db[group_id].random_qty[i]) //Skip empty random group
+		if (!(&itemgroup_db[group_id].random[i]) || !itemgroup_db[group_id].random[i].data_qty) //Skip empty random group
 			continue;
-		rand = rnd()%itemgroup_db[group_id].random_qty[i];
+		rand = rnd()%itemgroup_db[group_id].random[i].data_qty;
 		//Woops, why is the data empty? Every check should be done when load the item group! So this is bad day for the player :P
-		if (!&itemgroup_db[group_id].random[i][rand] || !itemgroup_db[group_id].random[i][rand].nameid) {
+		if (!&itemgroup_db[group_id].random[i].data[rand] || !itemgroup_db[group_id].random[i].data[rand].nameid) {
 			continue;
 		}
-		if (itemdb_exists(itemgroup_db[group_id].random[i][rand].nameid))
-			itemdb_pc_get_itemgroup_sub(sd,group_id,&itemgroup_db[group_id].random[i][rand]);
+		if (itemdb_exists(itemgroup_db[group_id].random[i].data[rand].nameid))
+			itemdb_pc_get_itemgroup_sub(sd,group_id,&itemgroup_db[group_id].random[i].data[rand]);
 	}
 
 	return 0;
@@ -282,8 +284,8 @@ int itemdb_group_bonus(struct map_session_data* sd, int itemid)
 	for (i=0; i < MAX_ITEMGROUP; i++) {
 		if (!sd->itemgrouphealrate[i])
 			continue;
-		ARR_FIND( 0, itemgroup_db[i].random_qty[0], j, itemgroup_db[i].random[0][j].nameid == itemid );
-		if( j < itemgroup_db[i].random_qty[0] )
+		ARR_FIND(0,itemgroup_db[i].random[0].data_qty,j,itemgroup_db[i].random[0].data[j].nameid == itemid );
+		if( j < itemgroup_db[i].random[0].data_qty )
 			bonus += sd->itemgrouphealrate[i];
 	}
 	return bonus;
@@ -659,9 +661,10 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
 	
 	while (fgets(line,sizeof(line),fp)) {
 		uint16 nameid;
-		int j, group_id, prob = 1, amt = 1, group = 1, announced = 0, dur = 0, named = 0, bound = 0;
+		int j, group_id, prob = 1, amt = 1, rand_group = 1, announced = 0, dur = 0, named = 0, bound = 0;
 		char *str[3], *p, w1[1024], w2[1024];
 		bool found = false;
+		struct s_item_group_random *random;
 
 		ln++;
 		if (line[0] == '/' && line[1] == '/')
@@ -678,7 +681,7 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
 		for (j = 0, p = line; j < 3 && p;j++) {
 			str[j] = p;
 			if (j == 2)
-				sscanf(str[j],"%d,%d,%d,%d,%d,%d,%d",&prob,&amt,&group,&announced,&dur,&named,&bound);
+				sscanf(str[j],"%d,%d,%d,%d,%d,%d,%d",&prob,&amt,&rand_group,&announced,&dur,&named,&bound);
 			p = strchr(p,',');
 			if (p) *p++=0;
 		}
@@ -691,7 +694,8 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
 		}
 
 		//Checking group_id
-		if (atoi(str[0]))
+		trim(str[0]);
+		if (ISDIGIT(str[0][0]))
 			group_id = atoi(str[0]);
 		else //Try reads group id by const
 			script_get_constant(trim(str[0]),&group_id);
@@ -701,13 +705,14 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
 		}
 
 		//Checking sub group
-		if (group > MAX_ITEMGROUP_RANDGROUP) {
-			ShowWarning("itemdb_read_itemgroup: Invalid sub group %d for group id %d in %s:%d\n", group, group_id, filename, ln);
+		if (rand_group > MAX_ITEMGROUP_RANDGROUP) {
+			ShowWarning("itemdb_read_itemgroup: Invalid sub group %d for group id %d in %s:%d\n", rand_group, group_id, filename, ln);
 			continue;
 		}
 
 		//Checking item
-		if ((nameid = atoi(str[1])) && itemdb_exists(nameid))
+		trim(str[1]);
+		if (ISDIGIT(str[1][0]) && itemdb_exists((nameid = atoi(str[1]))))
 			found = true;
 		else if (itemdb_searchname(str[1])) {
 			found = true;
@@ -718,20 +723,18 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
 			continue;
 		}
 
-		//Checking the capacity
-		if ((group && itemgroup_db[group_id].random_qty[group-1]+prob >= MAX_ITEMGROUP_RAND) ||
-			(!group && itemgroup_db[group_id].must_qty+1 >= MAX_ITEMGROUP_MUST))
-		{
-			ShowWarning("itemdb_read_itemgroup: Group id %d is overflow (%d entries) in %s:%d\n", group_id, (!group) ? MAX_ITEMGROUP_MUST : MAX_ITEMGROUP_RAND, filename, ln);
-			continue;
-		}
-
 		amt = cap_value(amt,1,MAX_AMOUNT);
 		dur = cap_value(dur,0,UINT16_MAX);
 		bound = cap_value(bound,0,4);
 
-		if (!group) {
+		//Must item, place it here
+		if (!rand_group) {
 			uint16 idx = itemgroup_db[group_id].must_qty;
+			if (!idx)
+				CREATE(itemgroup_db[group_id].must,struct s_item_group,1);
+			else
+				RECREATE(itemgroup_db[group_id].must,struct s_item_group,idx+1);
+
 			itemgroup_db[group_id].must[idx].nameid = nameid;
 			itemgroup_db[group_id].must[idx].amount = amt;
 			itemgroup_db[group_id].must[idx].isAnnounced = announced;
@@ -739,25 +742,34 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
 			itemgroup_db[group_id].must[idx].isNamed = named;
 			itemgroup_db[group_id].must[idx].bound = bound;
 			itemgroup_db[group_id].must_qty++;
-			group = 1;
+			rand_group = 1;
 		}
 		prob = max(prob,0);
+		//Must item didn't set as random item, skip next process
 		if (!prob) {
 			entries++;
 			continue;
 		}
-		group -= 1;
-		for (j = 0; j < prob; j++) {
-			uint16 idx;
-			idx = itemgroup_db[group_id].random_qty[group];
-			itemgroup_db[group_id].random[group][idx].nameid = nameid;
-			itemgroup_db[group_id].random[group][idx].amount = amt;
-			itemgroup_db[group_id].random[group][idx].isAnnounced = announced;
-			itemgroup_db[group_id].random[group][idx].duration = dur;
-			itemgroup_db[group_id].random[group][idx].isNamed = named;
-			itemgroup_db[group_id].random[group][idx].bound = bound;
-			itemgroup_db[group_id].random_qty[group]++;
+		rand_group -= 1;
+		random = &itemgroup_db[group_id].random[rand_group];
+
+		//Check, if the entry for this random group already created or not
+		if (!random->data_qty) {
+			CREATE(random->data,struct s_item_group,prob);
+			random->data_qty = 0;
+		}
+		else
+			RECREATE(random->data,struct s_item_group,random->data_qty+prob);
+		//Now put the entry to its rand_group
+		for (j = random->data_qty; j < random->data_qty+prob; j++) {
+			random->data[j].nameid = nameid;
+			random->data[j].amount = amt;
+			random->data[j].isAnnounced = announced;
+			random->data[j].duration = dur;
+			random->data[j].isNamed = named;
+			random->data[j].bound = bound;
 		}
+		random->data_qty += prob;
 		entries++;
 	}
 	fclose(fp);
@@ -1621,6 +1633,19 @@ void itemdb_reload(void)
 		if( itemdb_array[i] )
 			destroy_item_data(itemdb_array[i], true);
 
+	for (i = 0; i < MAX_ITEMGROUP; i++) {
+		uint8 j;
+		if (!(&itemgroup_db[i]))
+			continue;
+		if (itemgroup_db[i].must_qty)
+			aFree(itemgroup_db[i].must);
+		for (j = 0; j < MAX_ITEMGROUP_RANDGROUP; j++) {
+			if (!(&itemgroup_db[i].random[j]) || !itemgroup_db[i].random[j].data_qty)
+				continue;
+			aFree(itemgroup_db[i].random[j].data);
+		}
+	}
+
 	itemdb_other->clear(itemdb_other, itemdb_final_sub);
 	db_clear(itemdb_combo);
 
@@ -1687,6 +1712,19 @@ void do_final_itemdb(void)
 		if( itemdb_array[i] )
 			destroy_item_data(itemdb_array[i], true);
 
+	for (i = 0; i < MAX_ITEMGROUP; i++) {
+		uint8 j;
+		if (!(&itemgroup_db[i]))
+			continue;
+		if (itemgroup_db[i].must_qty)
+			aFree(itemgroup_db[i].must);
+		for (j = 0; j < MAX_ITEMGROUP_RANDGROUP; j++) {
+			if (!(&itemgroup_db[i].random[j]) || !itemgroup_db[i].random[j].data_qty)
+				continue;
+			aFree(itemgroup_db[i].random[j].data);
+		}
+	}
+
 	itemdb_other->destroy(itemdb_other, itemdb_final_sub);
 	destroy_item_data(&dummy_item, false);
 	db_destroy(itemdb_combo);
@@ -1697,7 +1735,7 @@ int do_init_itemdb(void) {
 	itemdb_other = idb_alloc(DB_OPT_BASE);
 	itemdb_combo = idb_alloc(DB_OPT_BASE);
 	create_dummy_data(); //Dummy data item.
+	
 	itemdb_read();
-
 	return 0;
 }

+ 19 - 15
src/map/itemdb.h

@@ -26,10 +26,8 @@
 #define IG_FINDINGORE 6
 #define IG_POTION 37
 
-#define MAX_ITEMGROUP 390 ///The max. item group count (increase this when needed).
+#define MAX_ITEMGROUP 390 ///The max. item group count (increase this when needed). TODO: Remove this limit and use dynamic allocaton
 
-#define MAX_ITEMGROUP_RAND 11000 ///Max item slots for random item group (increase this when needed).
-#define MAX_ITEMGROUP_MUST 15 ///Max item for 'must' item group (increase this when needed).
 #define MAX_ITEMGROUP_RANDGROUP 4	///Max group for random item (increase this when needed).
 
 #define CARD0_FORGE 0x00FF
@@ -310,6 +308,14 @@ enum e_item_job {
 	ITEMJ_THIRD_BABY  = 0x20,
 };
 
+struct item_combo {
+	struct script_code *script;
+	unsigned short *nameid;/* nameid array */
+	unsigned char count;
+	unsigned short id;/* id of this combo */
+	bool isRef;/* whether this struct is a reference or the master */
+};
+
 struct item_data {
 	uint16 nameid;
 	char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
@@ -373,7 +379,7 @@ struct item_data {
 	unsigned char combos_count;
 };
 
-/* Struct of item group */
+/* Struct of item group entry */
 struct s_item_group {
 	uint16 nameid, ///item id
 		duration; ///duration if item as rental item
@@ -383,19 +389,17 @@ struct s_item_group {
 	char bound; ///makes the item as bound item (according to bound type)
 };
 
-/* Struct of item group that will be used for db */
-struct s_item_group_db {
-	struct s_item_group must[MAX_ITEMGROUP_MUST];
-	struct s_item_group random[MAX_ITEMGROUP_RANDGROUP][MAX_ITEMGROUP_RAND]; ///NOTE: Is this good?
-	uint16 must_qty, random_qty[MAX_ITEMGROUP_RANDGROUP];
+/* Struct of random group */
+struct s_item_group_random {
+	struct s_item_group *data;
+	uint16 data_qty;
 };
 
-struct item_combo {
-	struct script_code *script;
-	unsigned short *nameid;/* nameid array */
-	unsigned char count;
-	unsigned short id;/* id of this combo */
-	bool isRef;/* whether this struct is a reference or the master */
+/* Struct of item group that will be used for db */
+struct s_item_group_db {
+	struct s_item_group *must;
+	uint16 must_qty;
+	struct s_item_group_random random[MAX_ITEMGROUP_RANDGROUP]; //! TODO: Move this fixed array to dynamic allocation!
 };
 
 struct item_data* itemdb_searchname(const char *name);

+ 76 - 41
src/map/skill.c

@@ -225,7 +225,7 @@ int skill_get_weapontype( uint16 skill_id )                 { skill_get (skill_d
 int skill_get_ammotype( uint16 skill_id )                   { skill_get (skill_db[skill_id].require.ammo, skill_id); }
 int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv )  { skill_get2 (skill_db[skill_id].require.ammo_qty[skill_lv-1], skill_id, skill_lv); }
 int skill_get_state( uint16 skill_id )                      { skill_get (skill_db[skill_id].require.state, skill_id); }
-int skill_get_status( uint16 skill_id, int idx )            { skill_get3 (skill_db[skill_id].require.status[idx], skill_id, idx); }
+//int skill_get_status( uint16 skill_id, int idx )            { skill_get3 (skill_db[skill_id].require.status[idx], skill_id, idx); }
 int skill_get_status_count( uint16 skill_id )               { skill_get (skill_db[skill_id].require.status_count, skill_id); }
 int skill_get_spiritball( uint16 skill_id, uint16 skill_lv ){ skill_get2 (skill_db[skill_id].require.spiritball[skill_lv-1], skill_id, skill_lv); }
 int skill_get_itemid( uint16 skill_id, int idx )            { skill_get3 (skill_db[skill_id].require.itemid[idx], skill_id, idx); }
@@ -14053,15 +14053,17 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
 	}
 
 	//check if equiped item
-	for (i = 0; i < MAX_SKILL_EQUIP_REQUIRE; i++) {
-		int reqeqit = require.eqItem[i];
-		if(!reqeqit) break; //no more required item get out of here
-		if (!pc_checkequip2(sd,reqeqit,EQI_ACC_L,EQI_MAX)) {
-			char output[128];
-			//clif_skill_fail(sd, skill_id, USESKILL_FAIL_NEED_EQUIPMENT, reqeqit);
-			sprintf(output,"need to put on [%d] in order to use.",reqeqit);
-			clif_colormes(sd,color_table[COLOR_RED],output);
-			return 0;
+	if (require.eqItem_count) {
+		for (i = 0; i < require.eqItem_count; i++) {
+			int reqeqit = require.eqItem[i];
+			if(!reqeqit) break; //no more required item get out of here
+			if (!pc_checkequip2(sd,reqeqit,EQI_ACC_L,EQI_MAX)) {
+				char output[128];
+				//clif_skill_fail(sd, skill_id, USESKILL_FAIL_NEED_EQUIPMENT, reqeqit);
+				sprintf(output,"need to put on [%d] in order to use.",reqeqit);
+				clif_colormes(sd,color_table[COLOR_RED],output);
+				return 0;
+			}
 		}
 	}
 
@@ -14453,10 +14455,9 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
 	}
 
 	req.status_count = skill_db[idx].require.status_count;
-	memset(req.status,SC_NONE,sizeof(req.status));
-	memcpy(req.status,skill_db[idx].require.status,sizeof(skill_db[idx].require.status));
-	memset(req.eqItem,0,sizeof(req.eqItem));
-	memcpy(req.eqItem,skill_db[idx].require.eqItem,sizeof(skill_db[idx].require.eqItem));
+	req.status = skill_db[idx].require.status;
+	req.eqItem_count = skill_db[idx].require.eqItem_count;
+	req.eqItem = skill_db[idx].require.eqItem;
 
 	for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ ) {
 		if( (skill_id == AM_POTIONPITCHER || skill_id == CR_SLIMPITCHER || skill_id == CR_CULTIVATION) && i != skill_lv%11 - 1 )
@@ -14643,10 +14644,10 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
 		if (req_opt&0x0040) req.weapon = 0;
 		if (req_opt&0x0080) { req.ammo = 0; req.ammo_qty = 0; }
 		if (req_opt&0x0100) req.state = ST_NONE;
-		if (req_opt&0x0200) memset(req.status,SC_NONE,sizeof(req.status));
+		if (req_opt&0x0200) req.status_count = 0;
 		if (req_opt&0x0400) req.spiritball = 0;
 		if (req_opt&0x0800) { memset(req.itemid,0,sizeof(req.itemid)); memset(req.amount,0,sizeof(req.amount)); }
-		if (req_opt&0x1000) memset(req.eqItem,0,sizeof(req.eqItem));
+		if (req_opt&0x1000) req.eqItem_count = 0;
 	}
 
 	return req;
@@ -18553,6 +18554,44 @@ static bool skill_parse_row_skilldb(char* split[], int columns, int current)
 	return true;
 }
 
+/** Split string to int or constanta value (const.txt)
+* @param *str: String input
+* @param *val: Temporary storage
+* @param *delim: Delimiter (for multiple value support)
+* @param useConst: 'true' uses const.txt as reference, 'false' uses atoi()
+* @param min: Min value of each const. Example: SC has min value SC_NONE (-1), so the value that less or equal won't be counted
+* @return count: Number of success
+*/
+uint8 skill_split2(char *str, int *val, const char *delim, bool useConst, short min) {
+	uint8 i = 0;
+	char *p = strtok(str,delim);
+
+	while (p != NULL) {
+		int n = -1;
+		if (useConst)
+			script_get_constant(trim(p),&n);
+		else
+			n = atoi(p);
+		if (n > min) {
+			val[i] = n;
+			i++;
+		}
+		p = strtok(NULL,delim);
+	}
+	return i;
+}
+
+/// Clear status data from skill requirement
+static void skill_destroy_requirement(void) {
+	uint16 i;
+	for (i = 0; i < MAX_SKILL; i++) {
+		if (skill_db[i].require.status_count)
+			aFree(skill_db[i].require.status);
+		if (skill_db[i].require.eqItem_count)
+			aFree(skill_db[i].require.eqItem);
+	}
+}
+
 /**
  * Read skill requirement from skill_require_db.txt
  **/
@@ -18618,42 +18657,36 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
 	else if( strcmpi(split[10],"elementalspirit")     == 0 ) skill_db[idx].require.state = ST_ELEMENTALSPIRIT;
 	else if( strcmpi(split[10],"peco")                == 0 ) skill_db[idx].require.state = ST_PECO;
 	else skill_db[idx].require.state = ST_NONE;	// Unknown or no state
-
+	
 	//Status requirements
-	memset(skill_db[idx].require.status,SC_NONE,sizeof(skill_db[idx].require.status));
-	skill_db[idx].require.status_count = 0;
-	p = strtok(split[11],":");
-	for( i = 0; i < MAX_SKILL_STATUS_REQUIRE && p != NULL; i++ ) {
-		int status = SC_NONE;
-		script_get_constant(trim(p),&status);
-		if (status > SC_NONE) {
-			skill_db[idx].require.status[skill_db[idx].require.status_count] = (enum sc_type)status;
-			skill_db[idx].require.status_count++;
+	trim(split[11]);
+	if (split[11][0] != '\0') {
+		int require[MAX_SKILL_STATUS_REQUIRE];
+		if ((skill_db[idx].require.status_count = skill_split2(split[11],require,":",true,SC_NONE))) {
+			skill_db[idx].require.status = aMalloc(skill_db[idx].require.status_count * sizeof(sc_type));
+			for (i = 0; i < skill_db[idx].require.status_count; i++)
+				skill_db[idx].require.status[i] = (sc_type)require[i];
 		}
-		p = strtok(NULL,":");
 	}
-
+	
 	skill_split_atoi(split[12],skill_db[idx].require.spiritball);
-
+	
 	for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ ) {
 		skill_db[idx].require.itemid[i] = atoi(split[13+ 2*i]);
 		skill_db[idx].require.amount[i] = atoi(split[14+ 2*i]);
 	}
 
-	//require equiped
-	memset(skill_db[idx].require.eqItem,0,sizeof(skill_db[idx].require.eqItem));
-	p = strtok(split[33],":");
-	for( i = 0; i < MAX_SKILL_EQUIP_REQUIRE && p != NULL; i++ ) {
-		int itid = atoi(p);
-		p = strtok(NULL,":"); //for easy continue don't read 'p' after this
-		if(itid <= 0) continue; //silent
-		if(itemdb_exists(itid)== NULL) {
-			ShowWarning("Invalid reqIt=%d specified for skillid=%d\n",itid,skill_id);
-			continue; //invalid id
+	//Equipped Item requirements.
+	//NOTE: We don't check the item is exist or not here
+	trim(split[33]);
+	if (split[33][0] != '\0') {
+		int require[MAX_SKILL_EQUIP_REQUIRE];
+		if ((skill_db[idx].require.eqItem_count = skill_split2(split[33],require,":",false,501))) {
+			skill_db[idx].require.eqItem = aMalloc(skill_db[idx].require.eqItem_count * sizeof(short));
+			for (i = 0; i < skill_db[idx].require.eqItem_count; i++)
+				skill_db[idx].require.eqItem[i] = require[i];
 		}
-		skill_db[idx].require.eqItem[i] = itid;
 	}
-
 	return true;
 }
 
@@ -19046,6 +19079,7 @@ static void skill_readdb(void) {
 void skill_reload (void) {
 	struct s_mapiterator *iter;
 	struct map_session_data *sd;
+	skill_destroy_requirement();
 	skill_readdb();
 	/* lets update all players skill tree : so that if any skill modes were changed they're properly updated */
 	iter = mapit_getallusers();
@@ -19083,6 +19117,7 @@ int do_init_skill (void)
 
 int do_final_skill(void)
 {
+	skill_destroy_requirement();
 	db_destroy(skilldb_name2id);
 	db_destroy(group_db);
 	db_destroy(skillunit_db);

+ 9 - 9
src/map/skill.h

@@ -119,10 +119,10 @@ struct skill_condition {
 		state,
 		spiritball,
 		itemid[MAX_SKILL_ITEM_REQUIRE],
-		amount[MAX_SKILL_ITEM_REQUIRE],
-		eqItem[MAX_SKILL_EQUIP_REQUIRE]; //max eq_item
-	uint8 status_count;
-	enum sc_type status[MAX_SKILL_STATUS_REQUIRE];
+		amount[MAX_SKILL_ITEM_REQUIRE];
+	short *eqItem;
+	enum sc_type *status;
+	uint8 status_count, eqItem_count;
 };
 
 struct s_skill_require {
@@ -138,10 +138,10 @@ struct s_skill_require {
 		state,
 		spiritball[MAX_SKILL_LEVEL],
 		itemid[MAX_SKILL_ITEM_REQUIRE],
-		amount[MAX_SKILL_ITEM_REQUIRE],
-		eqItem[MAX_SKILL_EQUIP_REQUIRE]; //max eq_item
-	uint8 status_count;
-	enum sc_type status[MAX_SKILL_STATUS_REQUIRE];
+		amount[MAX_SKILL_ITEM_REQUIRE];
+	short *eqItem;
+	enum sc_type *status;
+	uint8 status_count, eqItem_count;
 };
 
 /// Database skills
@@ -334,7 +334,7 @@ int skill_get_weapontype( uint16 skill_id );
 int skill_get_ammotype( uint16 skill_id );
 int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv );
 int skill_get_state(uint16 skill_id);
-int skill_get_status( uint16 skill_id, int idx );
+//int skill_get_status( uint16 skill_id, int idx );
 int skill_get_status_count( uint16 skill_id );
 int skill_get_spiritball( uint16 skill_id, uint16 skill_lv );
 int skill_get_itemid( uint16 skill_id, int idx );