Browse Source

* Added a safeguard to skill_get_unit_layout() against incorrectly defined layout ids (will give weird results but won't crash at least)
* Fixed Firewall/Icewall being oriented backwards (no real difference though...)
* Removed some junk Landprotector/Graffiti code; Graffiti doesn't get placed randomly anymore
* Icewall can now be cast on yourself... but for some reason, the cell on yourself immediately expires!
* Merged together functions clif_set0192() and clif_changemapcell()
- also removed its "send to whole map" mode which is just plain wrong (although aegis actually does use it to 'inform' caster about changes)

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11175 54d463be-8e91-2dee-dedb-b68131a5f0ec

ultramage 17 years ago
parent
commit
892f36f0b7
6 changed files with 170 additions and 159 deletions
  1. 10 0
      Changelog-Trunk.txt
  2. 31 38
      src/map/clif.c
  3. 1 1
      src/map/clif.h
  4. 2 2
      src/map/map.c
  5. 98 104
      src/map/skill.c
  6. 28 14
      src/map/skill.h

+ 10 - 0
Changelog-Trunk.txt

@@ -4,6 +4,16 @@ 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.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
 2007/09/10
 2007/09/10
+	* Added a safeguard to skill_get_unit_layout() against incorrectly
+	  defined layout ids (will give weird results but won't crash at least)
+	* Fixed Firewall/Icewall being oriented backwards (no real difference..)
+	* Removed some junk Landprotector/Graffiti code
+	- Graffiti doesn't get placed randomly anymore
+	* Icewall can now be cast on yourself
+	- TODO: for some reason, the cell on yourself immediately expires...
+	* Merged together functions clif_set0192() and clif_changemapcell()
+	- also removed its "send to whole map" mode which is just plain wrong
+	  (although aegis actually does use it to 'inform' caster about changes)
 	* Added config option to adjust exp gained by 'getexp' [ultramage]
 	* Added config option to adjust exp gained by 'getexp' [ultramage]
 2007/09/09
 2007/09/09
 	* Removed bonus bAddEffWhenHitShort as it is unneeded and unused.
 	* Removed bonus bAddEffWhenHitShort as it is unneeded and unused.

+ 31 - 38
src/map/clif.c

@@ -640,7 +640,7 @@ int clif_clearflooritem(struct flooritem_data *fitem, int fd)
 		clif_send(buf, packet_len(0xa1), &fitem->bl, AREA);
 		clif_send(buf, packet_len(0xa1), &fitem->bl, AREA);
 	} else {
 	} else {
 		WFIFOHEAD(fd,packet_len(0xa1));
 		WFIFOHEAD(fd,packet_len(0xa1));
-		memcpy(WFIFOP(fd,0), buf, 6);
+		memcpy(WFIFOP(fd,0), buf, packet_len(0xa1));
 		WFIFOSET(fd,packet_len(0xa1));
 		WFIFOSET(fd,packet_len(0xa1));
 	}
 	}
 
 
@@ -1184,20 +1184,6 @@ static void clif_spiritball_single(int fd, struct map_session_data *sd)
 	WFIFOSET(fd, packet_len(0x1e1));
 	WFIFOSET(fd, packet_len(0x1e1));
 }
 }
 
 
-/*==========================================
- *
- *------------------------------------------*/
-static void clif_set0192(int fd, int m, int x, int y, int type)
-{
-	WFIFOHEAD(fd,packet_len(0x192));
-	WFIFOW(fd,0) = 0x192;
-	WFIFOW(fd,2) = x;
-	WFIFOW(fd,4) = y;
-	WFIFOW(fd,6) = type;
-	mapindex_getmapname_ext(map[m].name, (char*)WFIFOP(fd,8));
-	WFIFOSET(fd,packet_len(0x192));
-}
-
 // new and improved weather display [Valaris]
 // new and improved weather display [Valaris]
 static void clif_weather_sub(int fd, int id, int type)
 static void clif_weather_sub(int fd, int id, int type)
 {
 {
@@ -3905,6 +3891,33 @@ void clif_standing(struct block_list* bl)
 	}
 	}
 }
 }
 
 
+/*==========================================
+ *
+ *------------------------------------------*/
+void clif_changemapcell(int fd, short m, short x, short y, int type)
+{
+	unsigned char buf[32];
+
+	WBUFW(buf,0) = 0x192;
+	WBUFW(buf,2) = x;
+	WBUFW(buf,4) = y;
+	WBUFW(buf,6) = type;
+	mapindex_getmapname_ext(map[m].name,(char*)WBUFP(buf,8));
+
+	if (fd == 0) {
+		struct block_list bl;
+		bl.type = BL_NUL;
+		bl.m = m;
+		bl.x = x;
+		bl.y = y;
+		clif_send(buf,packet_len(0x192),&bl,AREA);
+	} else {
+		WFIFOHEAD(fd,packet_len(0x192));
+		memcpy(WFIFOP(fd,0), buf, packet_len(0x192));
+		WFIFOSET(fd,packet_len(0x192));
+	}
+}
+
 /*==========================================
 /*==========================================
  *
  *
  *------------------------------------------*/
  *------------------------------------------*/
@@ -3948,7 +3961,7 @@ int clif_getareachar_skillunit(struct map_session_data *sd,struct skill_unit *un
 		WFIFOL(fd, 2)=unit->bl.id;
 		WFIFOL(fd, 2)=unit->bl.id;
 		WFIFOL(fd, 6)=unit->group->src_id;
 		WFIFOL(fd, 6)=unit->group->src_id;
 		WFIFOW(fd,10)=unit->bl.x;
 		WFIFOW(fd,10)=unit->bl.x;
-		WFIFOW(fd,12)=unit->bl.y; // might be typo? [Lance]
+		WFIFOW(fd,12)=unit->bl.y;
 		WFIFOB(fd,14)=unit->group->unit_id;
 		WFIFOB(fd,14)=unit->group->unit_id;
 		WFIFOB(fd,15)=1;
 		WFIFOB(fd,15)=1;
 		WFIFOB(fd,16)=1;
 		WFIFOB(fd,16)=1;
@@ -3973,7 +3986,7 @@ int clif_getareachar_skillunit(struct map_session_data *sd,struct skill_unit *un
 	WFIFOSET(fd,packet_len(0x11f));
 	WFIFOSET(fd,packet_len(0x11f));
 
 
 	if(unit->group->skill_id == WZ_ICEWALL)
 	if(unit->group->skill_id == WZ_ICEWALL)
-		clif_set0192(fd,unit->bl.m,unit->bl.x,unit->bl.y,5);
+		clif_changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,5);
 	return 0;
 	return 0;
 /* Previous implementation guess of packet 0x1c9, who can understand what all those fields are for? [Skotlex]
 /* Previous implementation guess of packet 0x1c9, who can understand what all those fields are for? [Skotlex]
 	WFIFOHEAD(fd,packet_len(0x1c9));
 	WFIFOHEAD(fd,packet_len(0x1c9));
@@ -4034,7 +4047,7 @@ int clif_clearchar_skillunit(struct skill_unit *unit,int fd)
 	WFIFOL(fd, 2)=unit->bl.id;
 	WFIFOL(fd, 2)=unit->bl.id;
 	WFIFOSET(fd,packet_len(0x120));
 	WFIFOSET(fd,packet_len(0x120));
 	if(unit->group && unit->group->skill_id == WZ_ICEWALL)
 	if(unit->group && unit->group->skill_id == WZ_ICEWALL)
-		clif_set0192(fd,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2);
+		clif_changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -6354,26 +6367,6 @@ int clif_bladestop(struct block_list *src,struct block_list *dst,
 	return 0;
 	return 0;
 }
 }
 
 
-/*==========================================
- *
- *------------------------------------------*/
-void clif_changemapcell(short m, short x, short y, int cell_type, int type)
-{
-	struct block_list bl;
-	unsigned char buf[32];
-
-	bl.type = BL_NUL;
-	bl.m = m;
-	bl.x = x;
-	bl.y = y;
-	WBUFW(buf,0) = 0x192;
-	WBUFW(buf,2) = x;
-	WBUFW(buf,4) = y;
-	WBUFW(buf,6) = cell_type;
-	mapindex_getmapname_ext(map[m].name,(char*)WBUFP(buf,8));
-	clif_send(buf,packet_len(0x192),&bl,(!type)?AREA:ALL_SAMEMAP);
-}
-
 /*==========================================
 /*==========================================
  * MVPƒGƒtƒFƒNƒg
  * MVPƒGƒtƒFƒNƒg
  *------------------------------------------*/
  *------------------------------------------*/

+ 1 - 1
src/map/clif.h

@@ -229,7 +229,7 @@ int clif_marionette(struct block_list *src, struct block_list *target);
 int clif_spiritball(struct map_session_data *sd);
 int clif_spiritball(struct map_session_data *sd);
 int clif_combo_delay(struct block_list *src,int wait);
 int clif_combo_delay(struct block_list *src,int wait);
 int clif_bladestop(struct block_list *src,struct block_list *dst,int bool_);
 int clif_bladestop(struct block_list *src,struct block_list *dst,int bool_);
-void clif_changemapcell(short m, short x, short y, int cell_type, int type);
+void clif_changemapcell(int fd, short m, short x, short y, int type);
 
 
 int clif_status_load(struct block_list *bl,int type, int flag);
 int clif_status_load(struct block_list *bl,int type, int flag);
 int clif_status_change(struct block_list *bl,int type,int flag);
 int clif_status_change(struct block_list *bl,int type,int flag);

+ 2 - 2
src/map/map.c

@@ -2150,8 +2150,8 @@ int map_calc_dir(struct block_list* src, int x, int y)
 	dy = y-src->y;
 	dy = y-src->y;
 	if( dx == 0 && dy == 0 )
 	if( dx == 0 && dy == 0 )
 	{	// both are standing on the same spot
 	{	// both are standing on the same spot
-		//dir = 6; // aegis-style, causes knockback to the left
-		dir = unit_getdir(src); // athena-style, causes knockback opposite to src's current direction
+		//dir = 6; // aegis-style, makes knockback default to the left
+		dir = unit_getdir(src); // athena-style, makes knockback default to behind 'src'
 	}
 	}
 	else if( dx >= 0 && dy >=0 )
 	else if( dx >= 0 && dy >=0 )
 	{	// upper-right
 	{	// upper-right

+ 98 - 104
src/map/skill.c

@@ -6,6 +6,7 @@
 #include "../common/nullpo.h"
 #include "../common/nullpo.h"
 #include "../common/malloc.h"
 #include "../common/malloc.h"
 #include "../common/showmsg.h"
 #include "../common/showmsg.h"
+#include "../common/strlib.h"
 #include "../common/ers.h"
 #include "../common/ers.h"
 
 
 #include "skill.h"
 #include "skill.h"
@@ -14,7 +15,7 @@
 #include "pc.h"
 #include "pc.h"
 #include "status.h"
 #include "status.h"
 #include "pet.h"
 #include "pet.h"
-#include "mercenary.h"	//[orn]
+#include "mercenary.h"
 #include "mob.h"
 #include "mob.h"
 #include "npc.h"
 #include "npc.h"
 #include "battle.h"
 #include "battle.h"
@@ -666,6 +667,10 @@ struct skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB];
 struct skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
 struct skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
 struct skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
 struct skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
 
 
+struct skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT];
+int firewall_unit_pos;
+int icewall_unit_pos;
+
 // macros to check for out of bounds errors [celest]
 // macros to check for out of bounds errors [celest]
 // i: Skill ID, l: Skill Level, var: Value to return after checking
 // i: Skill ID, l: Skill Level, var: Value to return after checking
 // for values that don't require level just put a one (putting 0 will trigger return 0; instead
 // for values that don't require level just put a one (putting 0 will trigger return 0; instead
@@ -986,30 +991,28 @@ int skillnotok_hom (int skillid, struct homun_data *hd)
 	return skillnotok(skillid, hd->master);
 	return skillnotok(skillid, hd->master);
 }
 }
 
 
-struct skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT];
-int firewall_unit_pos;
-int icewall_unit_pos;
-
-struct skill_unit_layout *skill_get_unit_layout (int skillid, int skilllv, struct block_list *src, int x, int y)
+struct skill_unit_layout* skill_get_unit_layout (int skillid, int skilllv, struct block_list* src, int x, int y)
 {	
 {	
 	int pos = skill_get_unit_layout_type(skillid,skilllv);
 	int pos = skill_get_unit_layout_type(skillid,skilllv);
 	int dir;
 	int dir;
 
 
-	if (pos != -1)
+	if (pos < -1 || pos >= MAX_SKILL_UNIT_LAYOUT) {
+		ShowError("skill_get_unit_layout: unsupported layout type %d for skill %d (level %d)\n", pos, skillid, skilllv);
+		pos = cap_value(pos, 0, MAX_SQUARE_LAYOUT); // cap to nearest square layout
+	}
+
+	if (pos != -1) // simple single-definition layout
 		return &skill_unit_layout[pos];
 		return &skill_unit_layout[pos];
 
 
-	if (src->x == x && src->y == y)
-		dir = 2;
-	else
-		dir = map_calc_dir(src,x,y);
+	dir = (src->x == x && src->y == y) ? 6 : map_calc_dir(src,x,y); // 6 - default aegis direction
 
 
 	if (skillid == MG_FIREWALL)
 	if (skillid == MG_FIREWALL)
 		return &skill_unit_layout [firewall_unit_pos + dir];
 		return &skill_unit_layout [firewall_unit_pos + dir];
 	else if (skillid == WZ_ICEWALL)
 	else if (skillid == WZ_ICEWALL)
 		return &skill_unit_layout [icewall_unit_pos + dir];
 		return &skill_unit_layout [icewall_unit_pos + dir];
 
 
-	ShowError("Unknown unit layout for skill %d, %d\n",skillid,skilllv);
-	return &skill_unit_layout[0];
+	ShowError("skill_get_unit_layout: unknown unit layout for skill %d (level %d)\n", skillid, skilllv);
+	return &skill_unit_layout[0]; // default 1x1 layout
 }
 }
 
 
 /*==========================================
 /*==========================================
@@ -2341,8 +2344,7 @@ static int skill_check_unit_range (struct block_list *bl, int x, int y, int skil
 	}
 	}
 
 
 	range += layout_type;
 	range += layout_type;
-	return map_foreachinarea(skill_check_unit_range_sub,bl->m,
-			x-range,y-range,x+range,y+range,BL_SKILL,skillid);
+	return map_foreachinarea(skill_check_unit_range_sub,bl->m,x-range,y-range,x+range,y+range,BL_SKILL,skillid);
 }
 }
 
 
 static int skill_check_unit_range2_sub (struct block_list *bl, va_list ap)
 static int skill_check_unit_range2_sub (struct block_list *bl, va_list ap)
@@ -5959,21 +5961,22 @@ int skill_castend_pos (int tid, unsigned int tick, int id, int data)
 
 
 	ud->skilltimer=-1;
 	ud->skilltimer=-1;
 	do {
 	do {
-		if(status_isdead(src)) break;
+		if(status_isdead(src))
+			break;
 
 
-		if (!(battle_config.skill_reiteration && src->type&battle_config.skill_reiteration) &&
+		if( !(src->type&battle_config.skill_reiteration) &&
 			skill_get_unit_flag(ud->skillid)&UF_NOREITERATION &&
 			skill_get_unit_flag(ud->skillid)&UF_NOREITERATION &&
 			skill_check_unit_range(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv)
 			skill_check_unit_range(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv)
-		)
+		  ) 
 			break;
 			break;
 
 
-		if (battle_config.skill_nofootset && src->type&battle_config.skill_nofootset &&
+		if( src->type&battle_config.skill_nofootset &&
 			skill_get_unit_flag(ud->skillid)&UF_NOFOOTSET &&
 			skill_get_unit_flag(ud->skillid)&UF_NOFOOTSET &&
 			skill_check_unit_range2(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv)
 			skill_check_unit_range2(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv)
-		)
+		  )
 			break;
 			break;
 		
 		
-		if(battle_config.land_skill_limit && src->type&battle_config.land_skill_limit &&
+		if( src->type&battle_config.land_skill_limit &&
 			(maxcount = skill_get_maxcount(ud->skillid, ud->skilllv)) > 0
 			(maxcount = skill_get_maxcount(ud->skillid, ud->skilllv)) > 0
 		  ) {
 		  ) {
 			int i;
 			int i;
@@ -5981,7 +5984,7 @@ int skill_castend_pos (int tid, unsigned int tick, int id, int data)
 				if(ud->skillunit[i]->skill_id == ud->skillid)
 				if(ud->skillunit[i]->skill_id == ud->skillid)
 					maxcount--;
 					maxcount--;
 			}
 			}
-			if(!maxcount)
+			if( maxcount == 0 )
 				break;
 				break;
 		}
 		}
 
 
@@ -6647,7 +6650,6 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid,
 {
 {
 	struct skill_unit_group *group;
 	struct skill_unit_group *group;
 	int i,limit,val1=0,val2=0,val3=0;
 	int i,limit,val1=0,val2=0,val3=0;
-	int count=0;
 	int target,interval,range,unit_flag;
 	int target,interval,range,unit_flag;
 	struct skill_unit_layout *layout;
 	struct skill_unit_layout *layout;
 	struct map_session_data *sd;
 	struct map_session_data *sd;
@@ -6737,13 +6739,6 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid,
 		break;
 		break;
 
 
 	case SA_LANDPROTECTOR:
 	case SA_LANDPROTECTOR:
-		{
-			int aoe_diameter;	// -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
-			val1=skilllv*15+10;
-			aoe_diameter=skilllv+skilllv%2+5;
-			count=aoe_diameter*aoe_diameter;	// -- this will not function if changed to ^2 (moonsoul)
-		}
-	//No break because we also have to check if we use gemstones. [Skotlex]
 	case SA_VOLCANO:
 	case SA_VOLCANO:
 	case SA_DELUGE:
 	case SA_DELUGE:
 	case SA_VIOLENTGALE:
 	case SA_VIOLENTGALE:
@@ -6845,9 +6840,6 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid,
 		val1 = 55 + skilllv*5;	//Elemental Resistance
 		val1 = 55 + skilllv*5;	//Elemental Resistance
 		val2 = skilllv*10;	//Status ailment resistance
 		val2 = skilllv*10;	//Status ailment resistance
 		break;
 		break;
-	case RG_GRAFFITI:			/* Graffiti */
-		count=1;	// Leave this at 1 [Valaris]
-		break;
 	case WE_CALLPARTNER:
 	case WE_CALLPARTNER:
 		if (sd) val1 = sd->status.partner_id;
 		if (sd) val1 = sd->status.partner_id;
 		break;
 		break;
@@ -6894,8 +6886,7 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid,
 		}
 		}
 	}
 	}
 
 
-	nullpo_retr(NULL, group=skill_initunitgroup(src,(count > 0 ? count : layout->count),
-		skillid,skilllv,skill_get_unit_id(skillid,flag&1)+subunt, limit, interval));
+	nullpo_retr(NULL, group=skill_initunitgroup(src,layout->count,skillid,skilllv,skill_get_unit_id(skillid,flag&1)+subunt, limit, interval));
 	group->val1=val1;
 	group->val1=val1;
 	group->val2=val2;
 	group->val2=val2;
 	group->val3=val3;
 	group->val3=val3;
@@ -6903,47 +6894,39 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid,
 	group->bl_flag= skill_get_unit_bl_target(skillid);
 	group->bl_flag= skill_get_unit_bl_target(skillid);
 	group->state.into_abyss = (sc && sc->data[SC_INTOABYSS].timer != -1); //Store into abyss state, to know it shouldn't give traps back. [Skotlex]
 	group->state.into_abyss = (sc && sc->data[SC_INTOABYSS].timer != -1); //Store into abyss state, to know it shouldn't give traps back. [Skotlex]
 	group->state.magic_power = (flag&2 || (sc && sc->data[SC_MAGICPOWER].timer != -1)); //Store the magic power flag. [Skotlex]
 	group->state.magic_power = (flag&2 || (sc && sc->data[SC_MAGICPOWER].timer != -1)); //Store the magic power flag. [Skotlex]
-	//Store if this skill needs to consume ammo.
-	group->state.ammo_consume = (sd && sd->state.arrow_atk && skillid != GS_GROUNDDRIFT);
+	group->state.ammo_consume = (sd && sd->state.arrow_atk && skillid != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo.
 	group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet
 	group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet
 
 
   	//if tick is greater than current, do not invoke onplace function just yet. [Skotlex]
   	//if tick is greater than current, do not invoke onplace function just yet. [Skotlex]
 	if (DIFF_TICK(group->tick, gettick()) > 100)
 	if (DIFF_TICK(group->tick, gettick()) > 100)
 		active_flag = 0;
 		active_flag = 0;
 
 
-	if(skillid==HT_TALKIEBOX ||
-	   skillid==RG_GRAFFITI){
+	if(skillid==HT_TALKIEBOX || skillid==RG_GRAFFITI){
 		group->valstr=(char *) aMalloc(MESSAGE_SIZE*sizeof(char));
 		group->valstr=(char *) aMalloc(MESSAGE_SIZE*sizeof(char));
 		if (sd)
 		if (sd)
-			memcpy(group->valstr,sd->message,MESSAGE_SIZE);
+			safestrncpy(group->valstr, sd->message, MESSAGE_SIZE);
 		else //Eh... we have to write something here... even though mobs shouldn't use this. [Skotlex]
 		else //Eh... we have to write something here... even though mobs shouldn't use this. [Skotlex]
-			strcpy(group->valstr, "Boo!");
+			safestrncpy(group->valstr, "Boo!", MESSAGE_SIZE);
 	}
 	}
 
 
 	//Why redefine local variables when the ones of the function can be reused? [Skotlex]
 	//Why redefine local variables when the ones of the function can be reused? [Skotlex]
 	val1=skilllv;
 	val1=skilllv;
 	val2=0;
 	val2=0;
 	limit=group->limit;
 	limit=group->limit;
-	count=group->unit_count;
-	for(i=0;i<count;i++){
+	for(i=0;i<layout->count;i++)
+	{
 		struct skill_unit *unit;
 		struct skill_unit *unit;
 		int ux,uy,alive=1;
 		int ux,uy,alive=1;
 		ux = x + layout->dx[i];
 		ux = x + layout->dx[i];
 		uy = y + layout->dy[i];
 		uy = y + layout->dy[i];
+
 		switch (skillid) {
 		switch (skillid) {
 		case MG_FIREWALL:
 		case MG_FIREWALL:
 		case NJ_KAENSIN:
 		case NJ_KAENSIN:
 			val2=group->val2;
 			val2=group->val2;
 			break;
 			break;
 		case WZ_ICEWALL:
 		case WZ_ICEWALL:
-			if(skilllv <= 1)
-				val1 = 500;
-			else
-				val1 = 200 + 200*skilllv;
-			break;
-		case RG_GRAFFITI:	/* Graffiti [Valaris] */
-			ux+=(i%5-2);
-			uy+=(i/5-2);
+			val1 = (skilllv <= 1) ? 500 : 200 + 200*skilllv;
 			break;
 			break;
 		case GS_DESPERADO:
 		case GS_DESPERADO:
 			val1 = abs(layout->dx[i]);
 			val1 = abs(layout->dx[i]);
@@ -6968,25 +6951,19 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid,
 		if(alive && map_getcell(src->m,ux,uy,CELL_CHKWALL))
 		if(alive && map_getcell(src->m,ux,uy,CELL_CHKWALL))
 			alive = 0;
 			alive = 0;
 		
 		
-		if (alive && battle_config.skill_wall_check) {
-			//Check if there's a path between cell and center of casting.
-			if (!path_search_long(NULL,src->m,ux,uy,x,y))
-				alive = 0;
-		}
+		if(alive && battle_config.skill_wall_check && !path_search_long(NULL,src->m,ux,uy,x,y))
+			alive = 0; //no path between cell and center of casting.
 					
 					
 		if(alive && skillid == WZ_ICEWALL) {
 		if(alive && skillid == WZ_ICEWALL) {
-			if(src->x == x && src->y==y) // Ice Wall not allowed on self [DracoRPG]
-				alive=0;
-			else {
-				val2=map_getcell(src->m,ux,uy,CELL_GETTYPE);
-				if(val2==5 || val2==1)
+				int celltype = map_getcell(src->m,ux,uy,CELL_GETTYPE);
+				if(celltype==5 || celltype==1)
 					alive=0;
 					alive=0;
 				else
 				else
-					clif_changemapcell(src->m,ux,uy,5,0);
-			}
+					clif_changemapcell(0,src->m,ux,uy,5);
 		}
 		}
 
 
 		if(alive){
 		if(alive){
+			//FIXME: why not calculate val1/val2 in here? [ultramage]
 			nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy,val1,val2));
 			nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy,val1,val2));
 			unit->limit=limit;
 			unit->limit=limit;
 			unit->range=range;
 			unit->range=range;
@@ -7681,8 +7658,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
 		case BD_ROKISWEIL:
 		case BD_ROKISWEIL:
 		case BD_INTOABYSS:
 		case BD_INTOABYSS:
 		case BD_SIEGFRIED:
 		case BD_SIEGFRIED:
-			if(sc && sc->data[SC_DANCING].timer != -1 &&
-				(sc->data[SC_DANCING].val1&0xFFFF) == skill_id)
+			if(sc && sc->data[SC_DANCING].timer != -1 && (sc->data[SC_DANCING].val1&0xFFFF) == skill_id)
 			{	//Check if you just stepped out of your ensemble skill to cancel dancing. [Skotlex]
 			{	//Check if you just stepped out of your ensemble skill to cancel dancing. [Skotlex]
 				//We don't check for SC_LONGING because someone could always have knocked you back and out of the song/dance.
 				//We don't check for SC_LONGING because someone could always have knocked you back and out of the song/dance.
 				//FIXME: This code is not perfect, it doesn't checks for the real ensemble's owner,
 				//FIXME: This code is not perfect, it doesn't checks for the real ensemble's owner,
@@ -7735,12 +7711,12 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
 				}
 				}
 			}
 			}
 			break;
 			break;
-	case UNT_GOSPEL:
-		if (sc && sc->data[type].timer != -1 && sc->data[type].val4 == BCT_ALL) //End item-no-use Gospel Effect. [Skotlex]
-			status_change_end(bl, type, -1);
-		break;
-
+		case UNT_GOSPEL:
+			if (sc && sc->data[type].timer != -1 && sc->data[type].val4 == BCT_ALL) //End item-no-use Gospel Effect. [Skotlex]
+				status_change_end(bl, type, -1);
+			break;
 	}
 	}
+
 	return skill_id;
 	return skill_id;
 }
 }
 
 
@@ -7811,7 +7787,7 @@ int skill_unit_onlimit (struct skill_unit *src, unsigned int tick, int flag)
 		break;
 		break;
 
 
 	case UNT_ICEWALL:
 	case UNT_ICEWALL:
-		clif_changemapcell(src->bl.m,src->bl.x,src->bl.y,src->val2,1);
+		clif_changemapcell(0,src->bl.m,src->bl.x,src->bl.y,src->val2);
 		break;
 		break;
 	case UNT_CALLFAMILY:
 	case UNT_CALLFAMILY:
 		if (!flag)
 		if (!flag)
@@ -9904,11 +9880,13 @@ int skill_delunit (struct skill_unit *unit, int flag)
 		return 0;
 		return 0;
 	nullpo_retr(0, group=unit->group);
 	nullpo_retr(0, group=unit->group);
 
 
+	// invoke onlimit event
 	skill_unit_onlimit( unit,gettick(), flag);
 	skill_unit_onlimit( unit,gettick(), flag);
 
 
 	if (group->state.song_dance&0x1) //Restore dissonance effect.
 	if (group->state.song_dance&0x1) //Restore dissonance effect.
 		skill_dance_overlap(unit, 0);
 		skill_dance_overlap(unit, 0);
 
 
+	// invoke onout event
 	if (!unit->range) {
 	if (!unit->range) {
 		map_foreachincell(skill_unit_effect,unit->bl.m,
 		map_foreachincell(skill_unit_effect,unit->bl.m,
 			unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),4);
 			unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),4);
@@ -9946,10 +9924,11 @@ int skill_delunit (struct skill_unit *unit, int flag)
  *
  *
  *------------------------------------------*/
  *------------------------------------------*/
 static int skill_unit_group_newid = MAX_SKILL_DB;
 static int skill_unit_group_newid = MAX_SKILL_DB;
+
 struct skill_unit_group *skill_initunitgroup (struct block_list *src, int count, int skillid, int skilllv, int unit_id, int limit, int interval)
 struct skill_unit_group *skill_initunitgroup (struct block_list *src, int count, int skillid, int skilllv, int unit_id, int limit, int interval)
 {
 {
-	struct unit_data *ud = unit_bl2ud(src);
-	struct skill_unit_group *group=NULL;
+	struct unit_data* ud = unit_bl2ud( src );
+	struct skill_unit_group* group;
 	int i;
 	int i;
 
 
 	if(skilllv <= 0) return 0;
 	if(skilllv <= 0) return 0;
@@ -9957,9 +9936,11 @@ struct skill_unit_group *skill_initunitgroup (struct block_list *src, int count,
 	nullpo_retr(NULL, src);
 	nullpo_retr(NULL, src);
 	nullpo_retr(NULL, ud);
 	nullpo_retr(NULL, ud);
 	
 	
-	for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i]; i++);
-	
-	if(i == MAX_SKILLUNITGROUP) {
+	// find a free spot to store the new unit group
+	ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == NULL );
+	if(i == MAX_SKILLUNITGROUP)
+	{
+		// array is full, make room by discarding oldest group
 		int j=0;
 		int j=0;
 		unsigned maxdiff=0,x,tick=gettick();
 		unsigned maxdiff=0,x,tick=gettick();
 		for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++)
 		for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++)
@@ -9971,30 +9952,35 @@ struct skill_unit_group *skill_initunitgroup (struct block_list *src, int count,
 		//Since elements must have shifted, we use the last slot.
 		//Since elements must have shifted, we use the last slot.
 		i = MAX_SKILLUNITGROUP-1;
 		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);
-	group->guild_id=status_get_guild_id(src);
-	group->group_id=skill_unit_group_newid++;
+	group             = ers_alloc(skill_unit_ers, struct skill_unit_group);
+	group->src_id     = src->id;
+	group->party_id   = status_get_party_id(src);
+	group->guild_id   = status_get_guild_id(src);
+	group->group_id   = skill_unit_group_newid++;
+	group->unit       = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
+	group->unit_count = count;
+	group->alive_count = 0;
+	group->val1       = 0;
+	group->val2       = 0;
+	group->val3       = 0;
+	group->skill_id   = skillid;
+	group->skill_lv   = skilllv;
+	group->unit_id    = unit_id;
+	group->map        = src->m;
+	group->limit      = limit;
+	group->interval   = interval;
+	group->tick       = gettick();
+	group->valstr     = NULL;
+
+	ud->skillunit[i] = group;
+
 	if(skill_unit_group_newid<=0)
 	if(skill_unit_group_newid<=0)
 		skill_unit_group_newid = MAX_SKILL_DB;
 		skill_unit_group_newid = MAX_SKILL_DB;
-	group->unit=(struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
-	group->unit_count=count;
-	group->alive_count=0;
-	group->val1=group->val2=group->val3=0;
-	group->skill_id=skillid;
-	group->skill_lv=skilllv;
-	group->unit_id=unit_id;
-	group->map=src->m;
-	group->limit=limit;
-	group->interval=interval;
-	group->tick=gettick();
+
 	if (skillid == PR_SANCTUARY) //Sanctuary starts healing +1500ms after casted. [Skotlex]
 	if (skillid == PR_SANCTUARY) //Sanctuary starts healing +1500ms after casted. [Skotlex]
 		group->tick += 1500;
 		group->tick += 1500;
-	group->valstr=NULL;
+
 	return group;
 	return group;
 }
 }
 
 
@@ -10060,16 +10046,18 @@ int skill_delunitgroup (struct block_list *src, struct skill_unit_group *group,
 	group->group_id=0;
 	group->group_id=0;
 	group->unit_count=0;
 	group->unit_count=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) {
+	// locate this group, swap with the last entry and delete it
+	ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == group );
+	ARR_FIND( i, MAX_SKILLUNITGROUP, j, ud->skillunit[j] == NULL ); j--;
+	if( i < MAX_SKILLUNITGROUP )
+	{
 		ud->skillunit[i] = ud->skillunit[j];
 		ud->skillunit[i] = ud->skillunit[j];
 		ud->skillunit[j] = NULL;
 		ud->skillunit[j] = NULL;
 		ers_free(skill_unit_ers, group);
 		ers_free(skill_unit_ers, group);
-	} else
+	}
+	else
 		ShowError("skill_delunitgroup: Group not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id);
 		ShowError("skill_delunitgroup: Group not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id);
+
 	return 1;
 	return 1;
 }
 }
 
 
@@ -10392,13 +10380,12 @@ int skill_unit_move (struct block_list *bl, unsigned int tick, int flag)
 		skill_unit_index=0;
 		skill_unit_index=0;
 	}
 	}
 		
 		
-	map_foreachincell(skill_unit_move_sub,
-			bl->m,bl->x,bl->y,BL_SKILL,bl,tick,flag);
+	map_foreachincell(skill_unit_move_sub,bl->m,bl->x,bl->y,BL_SKILL,bl,tick,flag);
 
 
 	if (flag&2 && flag&1)
 	if (flag&2 && flag&1)
 	{ //Onplace, check any skill units you have left.
 	{ //Onplace, check any skill units you have left.
 		int i;
 		int i;
-		for (i=0; i < (sizeof(skill_unit_temp)/sizeof(int)) && skill_unit_temp[i]; i++)
+		for (i=0; i < ARRAYLENGTH(skill_unit_temp) && skill_unit_temp[i]; i++)
 			skill_unit_onleft(skill_unit_temp[i], bl, tick);
 			skill_unit_onleft(skill_unit_temp[i], bl, tick);
 	}
 	}
 
 
@@ -11077,6 +11064,8 @@ void skill_init_unit_layout (void)
 	int i,j,size,pos = 0;
 	int i,j,size,pos = 0;
 
 
 	memset(skill_unit_layout,0,sizeof(skill_unit_layout));
 	memset(skill_unit_layout,0,sizeof(skill_unit_layout));
+
+	// standard square layouts go first
 	for (i=0; i<=MAX_SQUARE_LAYOUT; i++) {
 	for (i=0; i<=MAX_SQUARE_LAYOUT; i++) {
 		size = i*2+1;
 		size = i*2+1;
 		skill_unit_layout[i].count = size*size;
 		skill_unit_layout[i].count = size*size;
@@ -11085,6 +11074,8 @@ void skill_init_unit_layout (void)
 			skill_unit_layout[i].dy[j] = (j/size-i);
 			skill_unit_layout[i].dy[j] = (j/size-i);
 		}
 		}
 	}
 	}
+
+	// afterwards add special ones
 	pos = i;
 	pos = i;
 	for (i=0;i<MAX_SKILL_DB;i++) {
 	for (i=0;i<MAX_SKILL_DB;i++) {
 		if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1)
 		if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1)
@@ -11092,6 +11083,7 @@ void skill_init_unit_layout (void)
 		switch (i) {
 		switch (i) {
 			case MG_FIREWALL:
 			case MG_FIREWALL:
 			case WZ_ICEWALL:
 			case WZ_ICEWALL:
+				// these will be handled later
 				break;
 				break;
 			case PR_SANCTUARY:
 			case PR_SANCTUARY:
 			case NPC_EVILLAND:
 			case NPC_EVILLAND:
@@ -11234,6 +11226,8 @@ void skill_init_unit_layout (void)
 			skill_db[i].unit_layout_type[j] = pos;
 			skill_db[i].unit_layout_type[j] = pos;
 		pos++;
 		pos++;
 	}
 	}
+
+	// firewall and icewall have 8 layouts (direction-dependent)
 	firewall_unit_pos = pos;
 	firewall_unit_pos = pos;
 	for (i=0;i<8;i++) {
 	for (i=0;i<8;i++) {
 		if (i&1) {
 		if (i&1) {

+ 28 - 14
src/map/skill.h

@@ -98,17 +98,17 @@ struct skill_unit_layout {
 };
 };
 
 
 enum {
 enum {
-	UF_DEFNOTENEMY		= 0x0001,	// defnotenemy 設定でBCT_NOENEMYに切り替え
-	UF_NOREITERATION	= 0x0002,	// 重複置き禁止 
-	UF_NOFOOTSET		= 0x0004,	// 足元置き禁止
-	UF_NOOVERLAP		= 0x0008,	// ユニット効果が重複しない
-	UF_NOPC		= 0x0010,	//May not target players
-	UF_NOMOB		= 0x0020,	//May not target mobs
-	UF_SKILL		= 0x0080,	//May target skills
-	UF_DANCE			= 0x0100,	//Dance
-	UF_ENSEMBLE			= 0x0200,	//Duet
-	UF_SONG		= 0x0400,	//Song
-	UF_DUALMODE	= 0x0800,	//Spells should trigger both ontimer and onplace/onout/onleft effects.
+	UF_DEFNOTENEMY   = 0x0001,	// defnotenemy 設定でBCT_NOENEMYに切り替え
+	UF_NOREITERATION = 0x0002,	// 重複置き禁止 
+	UF_NOFOOTSET     = 0x0004,	// 足元置き禁止
+	UF_NOOVERLAP     = 0x0008,	// ユニット効果が重複しない
+	UF_NOPC          = 0x0010,	//May not target players
+	UF_NOMOB         = 0x0020,	//May not target mobs
+	UF_SKILL         = 0x0080,	//May target skills
+	UF_DANCE         = 0x0100,	//Dance
+	UF_ENSEMBLE      = 0x0200,	//Duet
+	UF_SONG          = 0x0400,	//Song
+	UF_DUALMODE      = 0x0800,	//Spells should trigger both ontimer and onplace/onout/onleft effects.
 };
 };
 
 
 // アイテム作成デ?タベ?ス
 // アイテム作成デ?タベ?ス
@@ -274,8 +274,20 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
 void skill_reload(void);
 void skill_reload(void);
 
 
 enum {
 enum {
-	ST_NONE,ST_HIDING,ST_CLOAKING,ST_HIDDEN,ST_RIDING,ST_FALCON,ST_CART,ST_SHIELD,ST_SIGHT,ST_EXPLOSIONSPIRITS,ST_CARTBOOST,
-	ST_RECOV_WEIGHT_RATE,ST_MOVE_ENABLE,ST_WATER,
+	ST_NONE,
+	ST_HIDING,
+	ST_CLOAKING,
+	ST_HIDDEN,
+	ST_RIDING,
+	ST_FALCON,
+	ST_CART,
+	ST_SHIELD,
+	ST_SIGHT,
+	ST_EXPLOSIONSPIRITS,
+	ST_CARTBOOST,
+	ST_RECOV_WEIGHT_RATE,
+	ST_MOVE_ENABLE,
+	ST_WATER,
 };
 };
 
 
 enum _skill {
 enum _skill {
@@ -933,7 +945,9 @@ enum {
 	UNT_ATTACK_SKILLS, //These show no effect on the client, therefore can be used for attack skills.
 	UNT_ATTACK_SKILLS, //These show no effect on the client, therefore can be used for attack skills.
 	UNT_FIREPILLAR_WAITING,
 	UNT_FIREPILLAR_WAITING,
 	UNT_FIREPILLAR_ACTIVE,
 	UNT_FIREPILLAR_ACTIVE,
-	//0x89, 0x8a, 0x8b
+	//0x89
+	//0x8a
+	//0x8b
 	UNT_USED_TRAPS = 0x8c,
 	UNT_USED_TRAPS = 0x8c,
 	UNT_ICEWALL,
 	UNT_ICEWALL,
 	UNT_QUAGMIRE,
 	UNT_QUAGMIRE,