Browse Source

Cleaned up and corrected some more land skill code:
* removed redundant skill_ganbatein() function
* Added flag UF_PATHCHECK from jAthena which affects whether a skill's cells will be affected by the surrounding terrain. Adjusted existing flags so that they closely match jA's (for easier comparisons).
* Fixed code that allowed placing of skill unit cells on 'gaps'.
* Fixed code that prevented successful casting of land skills on 'gaps' (officially it's possbile, even though they will not deploy entirely).

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

ultramage 17 years ago
parent
commit
5767cc5285
6 changed files with 112 additions and 122 deletions
  1. 9 0
      Changelog-Trunk.txt
  2. 2 0
      db/Changelog.txt
  3. 32 31
      db/skill_unit_db.txt
  4. 55 78
      src/map/skill.c
  5. 12 11
      src/map/skill.h
  6. 2 2
      src/map/unit.c

+ 9 - 0
Changelog-Trunk.txt

@@ -3,6 +3,15 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
+2008/03/09
+	* Cleaned up and corrected some more land skill code [ultramage]
+	- removed redundant skill_ganbatein() function
+	- Added flag UF_PATHCHECK from jAthena which affects whether a skill's
+	  cells will be affected by the surrounding terrain. Adjusted existing
+	  flags so that they closely match jA's (for easier comparisons).
+	- Fixed code that allowed placing of skill unit cells on 'gaps'.
+	- Fixed code that prevented successful casting of land skills on 'gaps'
+	  (officially it's possbile, even though they will not deploy entirely).
 2008/03/07
 	* Script induced status changes can now be reduced by stats/cards (but
 	  only trigger rate is reduced, not duration).

+ 2 - 0
db/Changelog.txt

@@ -43,6 +43,8 @@
 	2385 Recuvative_Armor		Should trigger HP/SP return with magical kills as well.
 
 =======================
+2008/03/09
+	* Added UF_PATHCHECK to skill_unit_db.txt, re-numbered flags [ultramage]
 2008/03/08
 	* Added a missing ; in item 5384's script. (bugreport: 1115) [Paradox924X]
 2008/03/04

+ 32 - 31
db/skill_unit_db.txt

@@ -7,13 +7,14 @@
 //      0x002(UF_NOREITERRATION)	Spell cannot be stacked
 //      0x004(UF_NOFOOTSET)		Spell cannot be cast near/on targets
 //      0x008(UF_NOOVERLAP)		Spell effects do not overlap
-//      0x010(UF_NOPC)		Spell cannot affect players.
-//      0x020(UF_NOMOB)		Spell cannot affect mobs.
+//      0x010(UF_PATHCHECK)	Only cells with a shootable path will be placed
+//      0x020(UF_NOPC)		Spell cannot affect players.
+//      0x040(UF_NOMOB)		Spell cannot affect mobs.
 //      0x080(UF_SKILL)		Spell CAN affect skills.
 //      0x100(UF_DANCE)		Dance skill
 //      0x200(UF_ENSEMBLE)	Ensemble skill
 //      0x400(UF_SONG)		Song skill
-//      0x800(UF_DUALMODE) Spell has effects both at an interval and when you step in/out
+//      0x800(UF_DUALMODE)	Spell has effects both at an interval and when you step in/out
 // 	Example: 0x006 = 0x002+0x004 -> Cannot be stacked nor cast near targets
 //
 // Notes:
@@ -24,20 +25,20 @@
 //
 
  12,0x7e,    ,  0, 0,  -1,all,   0x003	//MG_SAFETYWALL
- 18,0x7f,    , -1, 0,  20,enemy, 0x008	//MG_FIREWALL
- 21,0x86,    ,  0, 2,1000,enemy, 0x008	//MG_THUNDERSTORM
+ 18,0x7f,    , -1, 0,  20,enemy, 0x018	//MG_FIREWALL
+ 21,0x86,    ,  0, 2,1000,enemy, 0x018	//MG_THUNDERSTORM
  25,0x85,    ,  1, 0,  -1,all,   0x003	//AL_PNEUMA
  27,0x81,0x80,  0, 0,  -1,all,   0x006	//AL_WARP
  47,0x86,    ,  0, 2,1000,enemy, 0x080	//AC_SHOWER
- 70,0x83,    , -1, 1,1000,all,   0x008	//PR_SANCTUARY
- 79,0x84,    , -1, 1,3000,enemy, 0x008	//PR_MAGNUS
+ 70,0x83,    , -1, 1,1000,all,   0x018	//PR_SANCTUARY
+ 79,0x84,    , -1, 1,3000,enemy, 0x018	//PR_MAGNUS
  80,0x87,0x88,  0, 1,2000,enemy, 0x006	//WZ_FIREPILLAR
- 83,0x86,    ,  0, 3,1000,enemy, 0x000	//WZ_METEOR
- 85,0x86,    ,  0, 6:6:6:6:6:6:6:6:6:6:8,1250,enemy,0x008	//WZ_VERMILION
- 87,0x8d,    , -1, 0,  -1,all,   0x000	//WZ_ICEWALL
- 89,0x86,    ,  0, 5, 450,enemy, 0x008	//WZ_STORMGUST
- 91,0x86,    ,  0, 2,1000,enemy, 0x000	//WZ_HEAVENDRIVE
- 92,0x8e,    ,  2, 0,  -1,enemy, 0x000	//WZ_QUAGMIRE
+ 83,0x86,    ,  0, 3,1000,enemy, 0x010	//WZ_METEOR
+ 85,0x86,    ,  0, 6:6:6:6:6:6:6:6:6:6:8,1250,enemy,0x018	//WZ_VERMILION
+ 87,0x8d,    , -1, 0,  -1,all,   0x010	//WZ_ICEWALL
+ 89,0x86,    ,  0, 5, 450,enemy, 0x018	//WZ_STORMGUST
+ 91,0x86,    ,  0, 2,1000,enemy, 0x010	//WZ_HEAVENDRIVE
+ 92,0x8e,    ,  2, 0,  -1,enemy, 0x010	//WZ_QUAGMIRE
 115,0x90,    ,  0, 1,1000,enemy, 0x006	//HT_SKIDTRAP
 116,0x93,    ,  0, 0,1000,enemy, 0x006	//HT_LANDMINE
 117,0x91,    ,  0, 1,1000,enemy, 0x006	//HT_ANKLESNARE
@@ -51,29 +52,29 @@
 140,0x92,    , -1, 0,1000,enemy, 0x000	//AS_VENOMDUST
 220,0xb0,    ,  0, 0,  -1,all,   0x002	//RG_GRAFFITI
 229,0xb1,    ,  0, 1,1000,enemy, 0x006	//AM_DEMONSTRATION
-254,0x86,    , -1, 0, 400,enemy, 0x000	//CR_GRANDCROSS
-285,0x9a,    ,  3, 0,  -1,all,   0x000	//SA_VOLCANO
-286,0x9b,    ,  3, 0,  -1,all,   0x000	//SA_DELUGE
-287,0x9c,    ,  3, 0,  -1,all,   0x000	//SA_VIOLENTGALE
-288,0x9d,    ,  3:3:4:4:5,0, -1,all,   0x000	//SA_LANDPROTECTOR
+254,0x86,    , -1, 0, 400,enemy, 0x010	//CR_GRANDCROSS
+285,0x9a,    ,  3, 0,  -1,all,   0x010	//SA_VOLCANO
+286,0x9b,    ,  3, 0,  -1,all,   0x010	//SA_DELUGE
+287,0x9c,    ,  3, 0,  -1,all,   0x010	//SA_VIOLENTGALE
+288,0x9d,    ,  3:3:4:4:5,0, -1,all,   0x010	//SA_LANDPROTECTOR
 306,0x9e,    ,  4, 0,6000,all,   0x200	//BD_LULLABY
-307,0x9f,    ,  4, 0,  -1,enemy, 0x210	//BD_RICHMANKIM
+307,0x9f,    ,  4, 0,  -1,enemy, 0x220	//BD_RICHMANKIM
 308,0xa0,    ,  4, 0,  -1,enemy, 0x200	//BD_ETERNALCHAOS
 309,0xa1,    ,  4, 0,  -1,party, 0x200	//BD_DRUMBATTLEFIELD
 310,0xa2,    ,  4, 0,  -1,party, 0x200	//BD_RINGNIBELUNGEN
 311,0xa3,    ,  4, 0,  -1,all,   0x200	//BD_ROKISWEIL
-312,0xa4,    ,  4, 0,  -1,party, 0x220	//BD_INTOABYSS
+312,0xa4,    ,  4, 0,  -1,party, 0x240	//BD_INTOABYSS
 313,0xa5,    ,  4, 0,  -1,party, 0x200	//BD_SIEGFRIED
 317,0xa6,    ,  3, 0,3000,enemy, 0x400	//BA_DISSONANCE
-319,0xa7,    ,  3, 0,  -1,all,   0x420	//BA_WHISTLE
-320,0xa8,    ,  3, 0,  -1,all,   0x420	//BA_ASSASSINCROSS
-321,0xa9,    ,  3, 0,  -1,all,   0x420	//BA_POEMBRAGI
-322,0xaa,    ,  3, 0,6000,all,   0xC20	//BA_APPLEIDUN
+319,0xa7,    ,  3, 0,  -1,all,   0x440	//BA_WHISTLE
+320,0xa8,    ,  3, 0,  -1,all,   0x440	//BA_ASSASSINCROSS
+321,0xa9,    ,  3, 0,  -1,all,   0x440	//BA_POEMBRAGI
+322,0xaa,    ,  3, 0,6000,all,   0xC40	//BA_APPLEIDUN
 325,0xab,    ,  3, 0,3000,enemy, 0x100	//DC_UGLYDANCE
-327,0xac,    ,  3, 0,  -1,all,   0x120	//DC_HUMMING
+327,0xac,    ,  3, 0,  -1,all,   0x140	//DC_HUMMING
 328,0xad,    ,  3, 0,  -1,enemy, 0x100	//DC_DONTFORGETME
-329,0xae,    ,  3, 0,  -1,all,   0x120	//DC_FORTUNEKISS
-330,0xaf,    ,  3, 0,  -1,all,   0x120	//DC_SERVICEFORYOU
+329,0xae,    ,  3, 0,  -1,all,   0x140	//DC_FORTUNEKISS
+330,0xaf,    ,  3, 0,  -1,all,   0x140	//DC_SERVICEFORYOU
 336,0xb2,    ,  0,-1,  -1,noone, 0x000	//WE_CALLPARTNER
 339,0x86,    , -1, 0, 400,enemy, 0x000	//NPC_DARKGRANDCROSS
 362,0xb4,    ,  0, 3,  -1,all,   0x000	//HP_BASILICA
@@ -90,7 +91,7 @@
 488,0xb9,    ,  3, 0,  -1,all,   0x200	//CG_HERMODE
 516,0xba,    ,  3, 0, 100,enemy, 0x000	//GS_DESPERADO
 521,0xbe,    ,  0, 1,1000,enemy, 0x000	//GS_GROUNDDRIFT
-527,0xbc,    , -1, 0,2000,enemy, 0x000	//NJ_TATAMIGAESHI
-535,0xbd,    , -1, 0,  20,enemy, 0x008	//NJ_KAENSIN
-538,0xbb,    ,  1:1:1:2:2:2:3:3:3:4,0,-1,all,0x000	//NJ_SUITON
-670,0xc7,    ,  5, 1,1000,all,   0x008	//NPC_EVILLAND
+527,0xbc,    , -1, 0,2000,enemy, 0x010	//NJ_TATAMIGAESHI
+535,0xbd,    , -1, 0,  20,enemy, 0x018	//NJ_KAENSIN
+538,0xbb,    ,  1:1:1:2:2:2:3:3:3:4,0,-1,all,0x010	//NJ_SUITON
+670,0xc7,    ,  5, 1,1000,all,   0x018	//NPC_EVILLAND

+ 55 - 78
src/map/skill.c

@@ -161,9 +161,8 @@ int skill_attack_area(struct block_list *bl,va_list ap);
 struct skill_unit_group *skill_locate_element_field(struct block_list *bl); // [Skotlex]
 int skill_graffitiremover(struct block_list *bl, va_list ap); // [Valaris]
 int skill_greed(struct block_list *bl, va_list ap);
-int skill_cell_overlap(struct block_list *bl, va_list ap);
-int skill_ganbatein(struct block_list *bl, va_list ap);
-int skill_trap_splash(struct block_list *bl, va_list ap);
+static int skill_cell_overlap(struct block_list *bl, va_list ap);
+static int skill_trap_splash(struct block_list *bl, va_list ap);
 struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg,int tick);
 static int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick);
 static int skill_unit_onleft(int skill_id, struct block_list *bl,unsigned int tick);
@@ -5808,9 +5807,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 
 	case HW_GANBANTEIN:
 		if (rand()%100 < 80) {
+			int dummy = 1;
 			clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
 			i = skill_get_splash(skillid, skilllv);
-			map_foreachinarea (skill_ganbatein, src->m, x-i, y-i, x+i, y+i, BL_SKILL);
+			map_foreachinarea(skill_cell_overlap, src->m, x-i, y-i, x+i, y+i, BL_SKILL, HW_GANBANTEIN, &dummy, src);
 		} else {
 			if (sd) clif_skill_fail(sd,skillid,0,0);
 			return 1;
@@ -6203,9 +6203,6 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 			&& (src->type&battle_config.vs_traps_bctall))
 			target = BCT_ALL;
 		break;
-	case NJ_SUITON:
-		skill_clear_group(src,1);
-		break;
 	case HT_SHOCKWAVE:
 		val1=skilllv*15+10;
 	case HT_SANDMAN:
@@ -6340,6 +6337,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 		skill_clear_group(src, 1); //Delete previous Kaensins/Suitons
 		val2 = (skilllv+1)/2 + 4;
 		break;
+	case NJ_SUITON:
+		skill_clear_group(src, 1);
+		break;
 
 	case GS_GROUNDDRIFT:
 		{
@@ -6392,17 +6392,20 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 			safestrncpy(group->valstr, "Boo!", MESSAGE_SIZE);
 	}
 
-	//Why redefine local variables when the ones of the function can be reused? [Skotlex]
-	val1=skilllv;
-	val2=0;
-	limit=group->limit;
-	for(i=0;i<layout->count;i++)
+	for( i = 0; i < layout->count; i++ )
 	{
 		struct skill_unit *unit;
-		short ux,uy;
-		int alive=1;
-		ux = x + layout->dx[i];
-		uy = y + layout->dy[i];
+		int ux = x + layout->dx[i];
+		int uy = y + layout->dy[i];
+		int val1 = skilllv;
+		int val2 = 0;
+		int limit = group->limit;
+		int alive = 1;
+
+		if( !group->state.song_dance && !map_getcell(src->m,ux,uy,CELL_CHKREACH) )
+			continue; // don't place skill units on walls (except for songs/dances/encores)
+		if( battle_config.skill_wall_check && skill_get_unit_flag(skillid)&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) )
+			continue; // no path between cell and center of casting.
 
 		switch (skillid) {
 		case MG_FIREWALL:
@@ -6429,35 +6432,25 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 				val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance
 			break;
 		}
-		if(range<=0)
+
+		if( range <= 0 )
 			map_foreachincell(skill_cell_overlap,src->m,ux,uy,BL_SKILL,skillid,&alive, src);
-		
-		//Song/dances/encores are displayed even over pits/walls.
-		if( alive && map_getcell(src->m,ux,uy,CELL_CHKWALL) && !group->state.song_dance )
-			alive = 0;
-		
-		if( alive && battle_config.skill_wall_check && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) )
-			alive = 0; //no path between cell and center of casting.
-					
-		if( alive && skillid == WZ_ICEWALL && !map_getcell(src->m,ux,uy,CELL_CHKREACH) )
-			alive = 0;
-
-		if(alive){
-			//FIXME: why not calculate val1/val2 in here? [ultramage]
-			nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy,val1,val2));
-			unit->limit=limit;
-			unit->range=range;
-
-			if (skillid == PF_FOGWALL && alive == 2)
-			{	//Double duration of cells on top of Deluge/Suiton
-				unit->limit *= 2;
-				group->limit = unit->limit;
-			}
-		
-			// execute on all targets standing on this cell
-			if (range==0 && active_flag)
-				map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1);
+		if( !alive )
+			continue;
+
+		nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy,val1,val2));
+		unit->limit=limit;
+		unit->range=range;
+
+		if (skillid == PF_FOGWALL && alive == 2)
+		{	//Double duration of cells on top of Deluge/Suiton
+			unit->limit *= 2;
+			group->limit = unit->limit;
 		}
+
+		// execute on all targets standing on this cell
+		if (range==0 && active_flag)
+			map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1);
 	}
 
 	if (!group->alive_count)
@@ -6488,7 +6481,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 /*==========================================
  * 
  *------------------------------------------*/
-int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned int tick)
+static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned int tick)
 {
 	struct skill_unit_group *sg;
 	struct block_list *ss;
@@ -7203,7 +7196,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
  * flag&1: Invoke onplace function (otherwise invoke onout)
  * flag&4: Invoke a onleft call (the unit might be scheduled for deletion)
  *------------------------------------------*/
-int skill_unit_effect (struct block_list* bl, va_list ap)
+static int skill_unit_effect (struct block_list* bl, va_list ap)
 {
 	struct skill_unit* unit = va_arg(ap,struct skill_unit*);
 	struct skill_unit_group* group = unit->group;
@@ -7373,6 +7366,7 @@ int skill_check_pc_partner (struct map_session_data *sd, short skill_id, short*
 				return c;
 		}
 	}
+
 	//Else: new search for partners.
 	c = 0;
 	memset (p_sd, 0, sizeof(p_sd));
@@ -8898,7 +8892,7 @@ int skill_greed (struct block_list *bl, va_list ap)
 /*==========================================
  *
  *------------------------------------------*/
-int skill_cell_overlap(struct block_list *bl, va_list ap)
+static int skill_cell_overlap(struct block_list *bl, va_list ap)
 {
 	int skillid;
 	int *alive;
@@ -8909,23 +8903,29 @@ int skill_cell_overlap(struct block_list *bl, va_list ap)
 	alive = va_arg(ap,int *);
 	src = va_arg(ap,struct block_list *);
 	unit = (struct skill_unit *)bl;
+
 	if (unit == NULL || unit->group == NULL || (*alive) == 0)
 		return 0;
 
 	switch (skillid)
 	{
 		case SA_LANDPROTECTOR:
-			if (unit->group->skill_id == SA_LANDPROTECTOR &&
-				battle_check_target(bl, src, BCT_ENEMY) > 0)
+			if( unit->group->skill_id == SA_LANDPROTECTOR &&
+				battle_check_target(bl, src, BCT_ENEMY) > 0 )
 			{	//Check for offensive Land Protector to delete both. [Skotlex]
 				(*alive) = 0;
 				skill_delunit(unit);
 				return 1;
 			}
-			//Delete the rest of types.
+			if( !(skill_get_inf2(unit->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) )
+			{	//It deletes everything except songs/dances and traps
+				skill_delunit(unit);
+				return 1;
+			}
+			break;
 		case HW_GANBANTEIN:
-			if(!(skill_get_inf2(unit->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)))
-			{	//It deletes everything except songs/dances
+			if( !(unit->group->state.song_dance&0x1) )
+			{// Don't touch song/dance.
 				skill_delunit(unit);
 				return 1;
 			}
@@ -8933,9 +8933,6 @@ int skill_cell_overlap(struct block_list *bl, va_list ap)
 		case SA_VOLCANO:
 		case SA_DELUGE:
 		case SA_VIOLENTGALE:
-// Suiton/Kaensin CAN super-impose on each another.
-//		case NJ_SUITON:
-//		case NJ_KAENSIN:
 // The official implementation makes them fail to appear when casted on top of ANYTHING
 // but I wonder if they didn't actually meant to fail when casted on top of each other?
 // hence, I leave the alternate implementation here, commented. [Skotlex]
@@ -8950,8 +8947,6 @@ int skill_cell_overlap(struct block_list *bl, va_list ap)
 				case SA_VOLCANO:
 				case SA_DELUGE:
 				case SA_VIOLENTGALE:
-//				case NJ_SUITON:
-//				case NJ_KAENSIN:
 					(*alive) = 0;
 					return 1;
 			}
@@ -8979,6 +8974,7 @@ int skill_cell_overlap(struct block_list *bl, va_list ap)
 			}
 			break;
 	}
+
 	if (unit->group->skill_id == SA_LANDPROTECTOR &&
 		!(skill_get_inf2(skillid)&(INF2_SONG_DANCE|INF2_TRAP)))
 	{	//It deletes everything except songs/dances/traps
@@ -8989,25 +8985,6 @@ int skill_cell_overlap(struct block_list *bl, va_list ap)
 	return 0;
 }
 
-/*==========================================
- * variation of skill_cell_overlap
- *------------------------------------------*/
-int skill_ganbatein (struct block_list *bl, va_list ap)
-{
-	struct skill_unit *unit;
-
-	nullpo_retr(0, bl);
-	nullpo_retr(0, ap);
-	if ((unit = (struct skill_unit *)bl) == NULL || unit->group == NULL)
-		return 0;
-
-	if (unit->group->state.song_dance&0x1)
-		return 0; //Don't touch song/dance.
-
-	skill_delunit(unit);
-	return 1;
-}
-
 /*==========================================
  * 
  *------------------------------------------*/
@@ -9032,7 +9009,7 @@ int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap)
 /*==========================================
  *
  *------------------------------------------*/
-int skill_trap_splash (struct block_list *bl, va_list ap)
+static int skill_trap_splash (struct block_list *bl, va_list ap)
 {
 	struct block_list *src;
 	int tick;
@@ -9547,7 +9524,7 @@ int skill_unit_timer_sub (struct block_list* bl, va_list ap)
 
 	// check for expiration
 	if( (DIFF_TICK(tick,group->tick) >= group->limit || DIFF_TICK(tick,group->tick) >= unit->limit) )
-	{	// stuff inlined from skill_unit_onlimit()
+	{// skill unit expired (inlined from skill_unit_onlimit())
 		switch( group->unit_id )
 		{
 			case UNT_BLASTMINE:
@@ -9628,7 +9605,7 @@ int skill_unit_timer_sub (struct block_list* bl, va_list ap)
 		}
 	}
 	else
-	{
+	{// skill unit is still active
 		switch( group->unit_id )
 		{
 			case UNT_ICEWALL:

+ 12 - 11
src/map/skill.h

@@ -100,17 +100,18 @@ struct s_skill_unit_layout {
 };
 
 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,	// If 'defunit_not_enemy' is set, the target is changed to 'friend'
+	UF_NOREITERATION = 0x0002,	// Spell cannot be stacked
+	UF_NOFOOTSET     = 0x0004,	// Spell cannot be cast near/on targets
+	UF_NOOVERLAP     = 0x0008,	// Spell effects do not overlap
+	UF_PATHCHECK     = 0x0010,	// Only cells with a shootable path will be placed
+	UF_NOPC          = 0x0020,	// May not target players
+	UF_NOMOB         = 0x0040,	// 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.
 };
 
 // アイテム作成デ?タベ?ス

+ 2 - 2
src/map/unit.c

@@ -1088,8 +1088,8 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh
 	if (!status_check_skilluse(src, NULL, skill_num, 0))
 		return 0;
 
-	if (map_getcell(src->m, skill_x, skill_y, CELL_CHKNOREACH))
-	{	//prevent casting ground targeted spells on non-walkable areas. [Skotlex] 
+	if( map_getcell(src->m, skill_x, skill_y, CELL_CHKWALL) )
+	{// can't cast ground targeted spells on wall cells
 		if (sd) clif_skill_fail(sd,skill_num,0,0);
 		return 0;
 	}