소스 검색

- Implemented use of ers for skill_unit_groups to reduce memory usage. NEEDS TESTING

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@5991 54d463be-8e91-2dee-dedb-b68131a5f0ec
skotlex 19 년 전
부모
커밋
0ef81c9d08
8개의 변경된 파일104개의 추가작업 그리고 89개의 파일을 삭제
  1. 3 0
      Changelog-Trunk.txt
  2. 2 2
      src/map/battle.c
  3. 1 0
      src/map/map.c
  4. 1 1
      src/map/map.h
  5. 1 1
      src/map/pc.c
  6. 92 81
      src/map/skill.c
  7. 2 2
      src/map/skill.h
  8. 2 2
      src/map/status.c

+ 3 - 0
Changelog-Trunk.txt

@@ -4,6 +4,9 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2006/04/11
+	* Implemented use of ers for skill_unit_groups to reduce memory usage.
+	* Note that it's NOT TESTED yet. Use with caution, at least some obvious
+	  bugs are expected to be found... [Skotlex]
 	* Modified battle_check_range to do a path-check on distances less than 2
 	  (rather than 3) to avoid being able to hit through walls. [Skotlex]
 	* Modified unit_walktoxy_sub to always move at least one cell when a large

+ 2 - 2
src/map/battle.c

@@ -223,7 +223,7 @@ int battle_damage(struct block_list *src,struct block_list *target,int damage, i
 			sc->data[SC_GRAVITATION].val3 == BCT_SELF) {
 			struct skill_unit_group *sg = (struct skill_unit_group *)sc->data[SC_GRAVITATION].val4;
 			if (sg) {
-				skill_delunitgroup(sg);
+				skill_delunitgroup(target,sg);
 				sc->data[SC_GRAVITATION].val4 = 0;
 				status_change_end(target, SC_GRAVITATION, -1);
 			}
@@ -404,7 +404,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 			struct skill_unit_group *group = (struct skill_unit_group *)sc->data[SC_SAFETYWALL].val3;
 			if (group) {
 				if (--group->val2<=0)
-					skill_delunitgroup(group);
+					skill_delunitgroup(NULL,group);
 				return 0;
 			} else {
 				status_change_end(bl,SC_SAFETYWALL,-1);

+ 1 - 0
src/map/map.c

@@ -3659,6 +3659,7 @@ void do_final(void) {
 	do_final_pet();
 	do_final_mob();
 	do_final_msg();
+	do_final_skill();
 	do_final_unit();
 	if(use_irc)
 		do_final_irc();

+ 1 - 1
src/map/map.h

@@ -349,7 +349,7 @@ struct unit_data {
 	struct block_list *bl;
 	struct walkpath_data walkpath;
 	struct skill_timerskill skilltimerskill[MAX_SKILLTIMERSKILL];
-	struct skill_unit_group skillunit[MAX_SKILLUNITGROUP];
+	struct skill_unit_group *skillunit[MAX_SKILLUNITGROUP];
 	struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET];
 	short attacktarget_lv;
 	short to_x,to_y;

+ 1 - 1
src/map/pc.c

@@ -4679,7 +4679,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 	{	//Remove Gospel [Skotlex]
 		struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc.data[SC_GOSPEL].val3;
 		if (sg)
-			skill_delunitgroup(sg);
+			skill_delunitgroup(&sd->bl, sg);
 	}
 	clif_clearchar_area(&sd->bl,1);
 

+ 92 - 81
src/map/skill.c

@@ -12,6 +12,7 @@
 #include "../common/malloc.h"
 #include "../common/showmsg.h"
 #include "../common/grfio.h"
+#include "../common/ers.h"
 
 #include "skill.h"
 #include "map.h"
@@ -35,7 +36,6 @@
 //Guild Skills are shifted to these to make them stick into the skill array.
 #define GD_SKILLRANGEMIN 900
 #define GD_SKILLRANGEMAX GD_SKILLRANGEMIN+MAX_GUILDSKILL
-#define swap(x,y) { int t; t = x; x = y; y = t; }
 
 int skill_names_id[MAX_SKILL_DB];
 const struct skill_name_db skill_names[] = {
@@ -610,6 +610,8 @@ const struct skill_name_db skill_names[] = {
 static const int dirx[8]={0,-1,-1,-1,0,1,1,1};
 static const int diry[8]={1,1,0,-1,-1,-1,0,1};
 
+
+static struct eri *skill_unit_ers = NULL; //For handling skill_unit's [Skotlex]
 /* ƒXƒLƒ‹ƒf?ƒ^ƒx?ƒX */
 struct skill_db skill_db[MAX_SKILL_DB];
 
@@ -5803,8 +5805,8 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data )
 			(maxcount = skill_get_maxcount(ud->skillid)) > 0
 		  ) {
 			int i;
-			for(i=0;i<MAX_SKILLUNITGROUP && maxcount;i++) {
-				if(ud->skillunit[i].alive_count > 0 && ud->skillunit[i].skill_id == ud->skillid)
+			for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i] && maxcount;i++) {
+				if(ud->skillunit[i]->skill_id == ud->skillid)
 					maxcount--;
 			}
 			if(!maxcount)
@@ -6229,8 +6231,8 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
 			p[3] = &sd->status.memo_point[2];
 
 			if((maxcount = skill_get_maxcount(skill_num)) > 0) {
-				for(i=0;i<MAX_SKILLUNITGROUP && maxcount;i++) {
-					if(sd->ud.skillunit[i].alive_count > 0 && sd->ud.skillunit[i].skill_id == skill_num)
+				for(i=0;i<MAX_SKILLUNITGROUP && sd->ud.skillunit[i] && maxcount;i++) {
+					if(sd->ud.skillunit[i]->skill_id == skill_num)
 						maxcount--;
 				}
 				if(!maxcount) {
@@ -6598,7 +6600,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
 	struct skill_unit_group *sg;
 	struct block_list *ss;
 	struct status_change *sc;
-	int type;
+	int type,skillid;
 
 	nullpo_retr(0, src);
 	nullpo_retr(0, bl);
@@ -6622,7 +6624,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
 		return 0; //Hidden characters are inmune to AoE skills except Heaven's Drive. [Skotlex]
 	
 	type = SkillStatusChangeTable[sg->skill_id];
-
+	skillid = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still.
 	switch (sg->unit_id) {
 	case UNT_SAFETYWALL:
 		//TODO: Find a more reliable way to handle the link to sg, this could cause dangling pointers. [Skotlex]
@@ -6637,7 +6639,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
 				&& sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) {
 				if (pc_setpos(sd,sg->val3,sg->val2>>16,sg->val2&0xffff,3) == 0) {
 					if (--sg->val1<=0 || sg->src_id == bl->id)
-						skill_delunitgroup(sg);
+						skill_delunitgroup(NULL, sg);
 				}
 			}
 		} else if(battle_config.mob_warpportal && bl->type != BL_PET)
@@ -6686,12 +6688,12 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
 		if (sc && sc->data[type].timer==-1)
 			sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
 		break;
-
+/* Basilica does not knocks back...
 	case UNT_BASILICA:
 		if (!(status_get_mode(bl)&MD_BOSS) && battle_check_target(&src->bl,bl,BCT_ENEMY)>0)
 			skill_blown(&src->bl,bl,1);
 		break;
-
+*/
 	case UNT_FOGWALL:
 		if (sc && sc->data[type].timer==-1)
 		{
@@ -6713,7 +6715,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
 		break;
 	}	
 
-	return sg->skill_id;
+	return skillid;
 }
 
 /*==========================================
@@ -6728,7 +6730,7 @@ int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsign
 	int splash_count=0;
 	struct status_change *tsc, *sc;
 	struct skill_unit_group_tickset *ts;
-	int type;
+	int type, skillid;
 	int diff=0;
 
 	nullpo_retr(0, src);
@@ -6743,6 +6745,7 @@ int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsign
 	sc = status_get_sc(ss); //For magic power. 
 	tsc = status_get_sc(bl);
 	type = SkillStatusChangeTable[sg->skill_id];
+	skillid = sg->skill_id;
 
 	if (sg->interval == -1) {
 		switch (sg->unit_id) {
@@ -6765,7 +6768,7 @@ int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsign
 		ts->tick = tick+sg->interval;
 		
 		// GX‚Í?d‚È‚Á‚Ä‚¢‚½‚ç3HIT‚µ‚È‚¢
-		if ((sg->skill_id==CR_GRANDCROSS || sg->skill_id==NPC_GRANDDARKNESS) && !battle_config.gx_allhit)
+		if ((skillid==CR_GRANDCROSS || skillid==NPC_GRANDDARKNESS) && !battle_config.gx_allhit)
 			ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y,0)-1);
 	}
 	//Temporarily set magic power to have it take effect. [Skotlex]
@@ -6817,7 +6820,7 @@ int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsign
 					sg->val1--;	// ?V‹K‚É“ü‚Á‚½ƒ†ƒjƒbƒg‚¾‚¯ƒJƒEƒ“ƒg
 			}
 			if (sg->val1 <= 0)
-				skill_delunitgroup(sg);
+				skill_delunitgroup(NULL,sg);
 			break;
 		}
 
@@ -6835,8 +6838,8 @@ int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsign
 		break;
 
 	case UNT_FIREPILLAR_WAITING:
-		skill_delunit(src);
 		skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1);
+		skill_delunit(src);
 		break;
 
 	case UNT_FIREPILLAR_ACTIVE:
@@ -7066,13 +7069,13 @@ int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsign
 			int target = md->target_id;
 			if (ss->type == BL_PC)
 				md->target_id = ss->id;
-			mobskill_use(md, tick, MSC_SKILLUSED|(sg->skill_id << 16));
+			mobskill_use(md, tick, MSC_SKILLUSED|(skillid << 16));
 			md->target_id = target;
 		} else
-			mobskill_use(md, tick, MSC_SKILLUSED|(sg->skill_id << 16));
+			mobskill_use(md, tick, MSC_SKILLUSED|(skillid << 16));
 	}
 
-	return sg->skill_id;
+	return skillid;
 }
 /*==========================================
  * ƒXƒLƒ‹ƒ†ƒjƒbƒg‚©‚ç—£?‚·‚é(‚à‚µ‚­‚Í‚µ‚Ä‚¢‚é)?ê?‡
@@ -7321,7 +7324,7 @@ int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,
 	nullpo_retr(0, sg=src->group);
 
 	if (skill_get_inf2(sg->skill_id)&INF2_TRAP && damage > 0)
-		skill_delunitgroup(sg);
+		skill_delunitgroup(NULL,sg);
 	else 
 	switch(sg->unit_id){
 	case UNT_ICEWALL:
@@ -8926,14 +8929,14 @@ int skill_clear_element_field(struct block_list *bl)
 	nullpo_retr(0, bl);
 	if (!ud) return 0;
 	
-	for (i=0;i<MAX_SKILLUNITGROUP;i++) {
-		switch (ud->skillunit[i].skill_id) {
+	for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) {
+		switch (ud->skillunit[i]->skill_id) {
 			case SA_DELUGE:
 			case SA_VOLCANO:
 			case SA_VIOLENTGALE:
 			case SA_LANDPROTECTOR:
 			case NJ_SUITON:
-				skill_delunitgroup(&ud->skillunit[i]);
+				skill_delunitgroup(bl, ud->skillunit[i]);
 		}
 	}
 	return 1;
@@ -8950,14 +8953,14 @@ struct skill_unit_group *skill_locate_element_field(struct block_list *bl)
 	nullpo_retr(0, bl);
 	if (!ud) return NULL;
 
-	for (i=0;i<MAX_SKILLUNITGROUP;i++) {
-		switch (ud->skillunit[i].skill_id) {
+	for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) {
+		switch (ud->skillunit[i]->skill_id) {
 			case SA_DELUGE:
 			case SA_VOLCANO:
 			case SA_VIOLENTGALE:
 			case SA_LANDPROTECTOR:
 			case NJ_SUITON:
-				return &ud->skillunit[i];
+				return ud->skillunit[i];
 		}
 	}
 	return NULL;
@@ -9058,7 +9061,7 @@ int skill_ganbatein(struct block_list *bl, va_list ap )
 	
 	if (unit->group->skill_id == SA_LANDPROTECTOR)
 		skill_delunit(unit);
-	else skill_delunitgroup(unit->group);
+	else skill_delunitgroup(NULL, unit->group);
 
 	return 1;
 }
@@ -9246,7 +9249,7 @@ void skill_stop_dancing(struct block_list *src)
 	}
 
 	if (group)
-		skill_delunitgroup(group);
+		skill_delunitgroup(NULL, group);
 		
 	if (dsd)
 	{
@@ -9348,7 +9351,7 @@ int skill_delunit(struct skill_unit *unit)
 	unit->alive=0;
 	map_delobjectnofree(unit->bl.id);
 	if(--group->alive_count==0)
-		skill_delunitgroup(group);
+		skill_delunitgroup(NULL, group);
 
 	return 0;
 }
@@ -9369,30 +9372,23 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src,
 	nullpo_retr(NULL, src);
 	nullpo_retr(NULL, ud);
 	
-	if(ud->skillunit){
-		for(i=0;i<MAX_SKILLUNITGROUP;i++)	/* ‹ó‚¢‚Ä‚¢‚é‚à‚Ì??õ */
-			if(ud->skillunit[i].group_id==0){
-				group=&ud->skillunit[i];
-				break;
-			}
-
-		if(group==NULL){	/* ‹ó‚¢‚ĂȂ¢‚̂Ō¢‚à‚Ì??õ */
-			int j=0;
-			unsigned maxdiff=0,x,tick=gettick();
-			for(i=0;i<MAX_SKILLUNITGROUP;i++)
-				if((x=DIFF_TICK(tick,ud->skillunit[i].tick))>maxdiff){
-					maxdiff=x;
-					j=i;
-				}
-			skill_delunitgroup(&ud->skillunit[j]);
-			group=&ud->skillunit[j];
-		}
-	}
-
-	if(group==NULL){
-		ShowFatalError("skill_initunitgroup: error unit group !\n");
-		exit(1);
-	}
+	for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i]; i++);
+	
+	if(i == MAX_SKILLUNITGROUP) {
+		int j=0;
+		unsigned maxdiff=0,x,tick=gettick();
+		for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++)
+			if((x=DIFF_TICK(tick,ud->skillunit[i]->tick))>maxdiff){
+				maxdiff=x;
+				j=i;
+			}
+		skill_delunitgroup(src, ud->skillunit[j]);
+		//Since elements must have shifted, we use the last slot.
+		i = MAX_SKILLUNITGROUP-1;
+	}
+	if (!ud->skillunit[i])
+		ud->skillunit[i] = ers_alloc(skill_unit_ers, struct skill_unit_group);
+	group=ud->skillunit[i];
 
 	group->src_id=src->id;
 	group->party_id=status_get_party_id(src);
@@ -9439,34 +9435,36 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src,
  * ƒXƒLƒ‹ƒ†ƒjƒbƒgƒOƒ‹?ƒv?í?œ
  *------------------------------------------
  */
-int skill_delunitgroup(struct skill_unit_group *group)
+int skill_delunitgroup(struct block_list *src, struct skill_unit_group *group)
 {
-	struct block_list *src;
-	int i;
+	struct unit_data *ud;
+	int i,j;
 
 	nullpo_retr(0, group);
 	if(group->unit_count<=0)
 		return 0;
 
-	src=map_id2bl(group->src_id);
-	//ƒ_ƒ“ƒXƒXƒLƒ‹‚̓_ƒ“ƒX?ó‘Ô‚ð‰ð?œ‚·‚é
-	if(src) {
-		if (skill_get_unit_flag(group->skill_id)&UF_DANCE)
+	if (!src) src=map_id2bl(group->src_id);
+	ud = unit_bl2ud(src);	
+	if(!src || !ud) {
+		ShowError("skill_delunitgroup: Group's source not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id);
+		return 0;	
+	}
+	if (skill_get_unit_flag(group->skill_id)&UF_DANCE)
+	{
+		struct status_change* sc = status_get_sc(src);
+		if (sc && sc->data[SC_DANCING].timer != -1)
 		{
-			struct status_change* sc = status_get_sc(src);
-			if (sc && sc->data[SC_DANCING].timer != -1)
-			{
-				sc->data[SC_DANCING].val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex]
-				status_change_end(src,SC_DANCING,-1);
-			}
+			sc->data[SC_DANCING].val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex]
+			status_change_end(src,SC_DANCING,-1);
 		}
+	}
 
-		if (group->unit_id == UNT_GOSPEL) { //Clear Gospel [Skotlex]
-			struct status_change *sc = status_get_sc(src);
-			if(sc && sc->data[SC_GOSPEL].timer != -1) {
-				sc->data[SC_GOSPEL].val3 = 0; //Remove reference to this group. [Skotlex]
-				status_change_end(src,SC_GOSPEL,-1);
-			}
+	if (group->unit_id == UNT_GOSPEL) { //Clear Gospel [Skotlex]
+		struct status_change *sc = status_get_sc(src);
+		if(sc && sc->data[SC_GOSPEL].timer != -1) {
+			sc->data[SC_GOSPEL].val3 = 0; //Remove reference to this group. [Skotlex]
+			status_change_end(src,SC_GOSPEL,-1);
 		}
 	}
 
@@ -9484,10 +9482,20 @@ int skill_delunitgroup(struct skill_unit_group *group)
 
 	map_freeblock((struct block_list*)group->unit);	/* aFree()‚̑ւí‚è */
 	group->unit=NULL;
-	group->src_id=0;
 	group->group_id=0;
 	group->unit_count=0;
-	return 0;
+
+	//Locate and clear this unit from the array.
+	for (i=0; i<MAX_SKILLUNITGROUP && ud->skillunit[i]!=group; i++);
+	for (j=i; j<MAX_SKILLUNITGROUP && ud->skillunit[j]; j++);
+	j--;
+	if (i<MAX_SKILLUNITGROUP) {
+		ud->skillunit[i] = ud->skillunit[j];
+		ud->skillunit[j] = NULL;
+		ers_free(skill_unit_ers, group);
+	} else
+		ShowError("skill_delunitgroup: Group not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id);
+	return 1;
 }
 
 /*==========================================
@@ -9497,16 +9505,11 @@ int skill_delunitgroup(struct skill_unit_group *group)
 int skill_clear_unitgroup(struct block_list *src)
 {
 	struct unit_data *ud = unit_bl2ud(src);
-	int i;
 
-	nullpo_retr(0, src);
 	nullpo_retr(0, ud);
 
-	if(!ud) return 0;
-
-	for(i=0;i<MAX_SKILLUNITGROUP;i++)
-		if(ud->skillunit[i].group_id>0 && ud->skillunit[i].src_id == src->id)
-			skill_delunitgroup(&ud->skillunit[i]);
+	while (ud->skillunit[0])
+		skill_delunitgroup(src, ud->skillunit[0]);
 	return 1;
 }
 
@@ -9744,6 +9747,7 @@ int skill_unit_move_sub( struct block_list *bl, va_list ap )
 	}
 	if (flag&4)
 		skill_unit_onleft(skill_id,target,tick);
+
 	return 1;
 }
 
@@ -11060,7 +11064,9 @@ void skill_reload(void)
 int do_init_skill(void)
 {
 	skill_readdb();
-
+	
+	skill_unit_ers = ers_new((uint32)sizeof(struct skill_unit_group));
+	
 	if (battle_config.skill_sp_override_grffile)
 		skill_read_skillspamount();
 
@@ -11074,3 +11080,8 @@ int do_init_skill(void)
 
 	return 0;
 }
+
+int do_final_skill(void) {
+	ers_destroy(skill_unit_ers);
+	return 0;
+}

+ 2 - 2
src/map/skill.h

@@ -130,7 +130,7 @@ struct skill_unit;
 struct skill_unit_group;
 
 int do_init_skill(void);
-
+int do_final_skill(void);
 
 //Returns the cast type of the skill: ground cast, castend damage, castend no damage
 enum { CAST_GROUND, CAST_DAMAGE, CAST_NODAMAGE };
@@ -187,7 +187,7 @@ struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,i
 int skill_delunit(struct skill_unit *unit);
 struct skill_unit_group *skill_initunitgroup(struct block_list *src,
 	int count,int skillid,int skilllv,int unit_id, int limit, int interval);
-int skill_delunitgroup(struct skill_unit_group *group);
+int skill_delunitgroup(struct block_list *src, struct skill_unit_group *group);
 int skill_clear_unitgroup(struct block_list *src);
 int skill_clear_element_field(struct block_list *bl);
 

+ 2 - 2
src/map/status.c

@@ -5021,7 +5021,7 @@ int status_change_end( struct block_list* bl , int type,int tid )
 					struct status_change *dsc;
 					if(sc->data[type].val2)
 					{
-						skill_delunitgroup((struct skill_unit_group *)sc->data[type].val2);
+						skill_delunitgroup(bl, (struct skill_unit_group *)sc->data[type].val2);
 						sc->data[type].val2 = 0;
 					}
 					if(sc->data[type].val4 && sc->data[type].val4 != BCT_SELF && (dsd=map_id2sd(sc->data[type].val4))){
@@ -5131,7 +5131,7 @@ int status_change_end( struct block_list* bl , int type,int tid )
 				else if (sc->data[type].val3) { //Clear the group.
 					struct skill_unit_group *group = (struct skill_unit_group *)sc->data[type].val3;
 					sc->data[type].val3 = 0;
-					skill_delunitgroup(group);
+					skill_delunitgroup(bl, group);
 				}
 				break;
 			case SC_HERMODE: