diff options
-rw-r--r-- | Changelog-Trunk.txt | 9 | ||||
-rw-r--r-- | db/Changelog.txt | 2 | ||||
-rw-r--r-- | db/skill_unit_db.txt | 63 | ||||
-rw-r--r-- | src/map/skill.c | 133 | ||||
-rw-r--r-- | src/map/skill.h | 23 | ||||
-rw-r--r-- | src/map/unit.c | 4 |
6 files changed, 112 insertions, 122 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 9c5b82da3..cc6d66ded 100644 --- a/Changelog-Trunk.txt +++ b/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). diff --git a/db/Changelog.txt b/db/Changelog.txt index a0664ce3d..d7524d4ed 100644 --- a/db/Changelog.txt +++ b/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 diff --git a/db/skill_unit_db.txt b/db/skill_unit_db.txt index 83343bfaf..b882b7d58 100644 --- a/db/skill_unit_db.txt +++ b/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 diff --git a/src/map/skill.c b/src/map/skill.c index c80e46f57..c53aac4fe 100644 --- a/src/map/skill.c +++ b/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 @@ -8990,25 +8986,6 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) } /*========================================== - * 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; -} - -/*========================================== * *------------------------------------------*/ int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap) @@ -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: diff --git a/src/map/skill.h b/src/map/skill.h index 1a76e3417..73e1daf4f 100644 --- a/src/map/skill.h +++ b/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. }; // アイテム作成デ?タベ?ス diff --git a/src/map/unit.c b/src/map/unit.c index 164e84327..f379bcc4c 100644 --- a/src/map/unit.c +++ b/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; } |