From 7906f0a3ff3742bb519b19b0cadbca9db0d35b32 Mon Sep 17 00:00:00 2001 From: Playtester Date: Sat, 5 Mar 2016 18:02:22 +0100 Subject: [PATCH] Line of Sight System updated (fixes #937, fixes #994) * You can now target walls with ground skills * Updated path check to not check the last cell * Unit skills will now place units depending on line of sight to the caster rather than the cast center * Implemented a new algorithm that retrieves all units in an area that are in line of sight with the area center * Arrow Shower, Dragon Breath, Cold Slower, Wind Cutter and Arms Cannon now use the new algorithm (Arrow Shower is no longer a unit skill) * Nodamage skills will no longer fail when the target walked around a corner * The following damage skills will no longer damage through walls: Raging Thrust, Tornado Kick, Splash Attack, Venom Splasher, Fireball, Meteor Assault, Desperado, Spread Attack, Pulse Strike, Hell's Judgment, Vampire Gift, Magnum Break, Sightrasher, Frost Nova, Explosion, Self Destruction, Firing Trap, Icebound Trap, Cluster Bomb, Claymore, Fire Pillar --- db/pre-re/skill_db.txt | 2 +- db/pre-re/skill_unit_db.txt | 6 ++-- db/re/skill_db.txt | 6 ++-- db/re/skill_unit_db.txt | 6 ++-- src/map/map.c | 70 +++++++++++++++++++++++++++++++++++++ src/map/map.h | 3 +- src/map/path.c | 2 +- src/map/skill.c | 68 ++++++++++++++++++++++------------- src/map/unit.c | 7 ---- 9 files changed, 125 insertions(+), 45 deletions(-) diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt index 67c98a5e77..5e39d3bafe 100644 --- a/db/pre-re/skill_db.txt +++ b/db/pre-re/skill_db.txt @@ -48,7 +48,7 @@ // 14 attack type (none, weapon, magic, misc) // 15 Blowcount (amount of tiles skill knockbacks) // 16 inf3 (skill information 3): -// 0x00001 - skill ignores land protector (e.g. arrow shower) +// 0x00001 - skill ignores land protector // 0x00002 - skill that doesn't end camouflage // 0x00004 - usable skills while hiding // 0x00008 - skill that can be use while in dancing state diff --git a/db/pre-re/skill_unit_db.txt b/db/pre-re/skill_unit_db.txt index 8d0a9d9c9d..ec83ae701f 100644 --- a/db/pre-re/skill_unit_db.txt +++ b/db/pre-re/skill_unit_db.txt @@ -36,7 +36,6 @@ 21,0x86, , 0, 2:2:2:2:2:2:2:2:2:2:3,1000,enemy, 0x010 //MG_THUNDERSTORM 25,0x85, , 1, 0, -1,all, 0x6003 //AL_PNEUMA 27,0x81,0x80, 0, 0, -1,all, 0x00E //AL_WARP - 47,0x86, , 0, 2,1000,enemy, 0x080 //AC_SHOWER 70,0x83, , -1, 1,1000,all, 0x018 //PR_SANCTUARY 79,0x84, , -1, 1,3000,enemy, 0x8018 //PR_MAGNUS 80,0x87,0x88, 0, 1,2000,enemy, 0x4006 //WZ_FIREPILLAR @@ -84,7 +83,7 @@ 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, 300,enemy, 0x000 //NPC_DARKGRANDCROSS +339,0x86, , -1, 0, 300,enemy, 0x000 //NPC_GRANDDARKNESS 362,0xb4, , 2, 0, 300,all, 0x2000 //HP_BASILICA 369,0xb3, , -1, 0,10000,all, 0x008 //PA_GOSPEL 395,0xb5, , 4, 0, -1,all, 0x200 //CG_MOONLIT @@ -95,7 +94,7 @@ 428,0x86, , 0, 1, 100,enemy, 0x000 //SG_SUN_WARM 429,0x86, , 0, 1, 100,enemy, 0x000 //SG_MOON_WARM 430,0x86, , 0, 1, 100,enemy, 0x000 //SG_STAR_WARM -484,0xb8, , 2, 0,1000,enemy, 0x8808 //HW_GRAVITATION +484,0xb8, , 2, 0,1000,enemy, 0x8818 //HW_GRAVITATION 488,0xb9, , 3, 0, -1,all, 0x200 //CG_HERMODE 516,0x86, , 3, 0, 100,enemy, 0x000 //GS_DESPERADO 521,0xbe, , 0, 1,1000,enemy, 0x000 //GS_GROUNDDRIFT @@ -182,7 +181,6 @@ 8041,0xf6, , 1:1:2:2:3, 0,2000,enemy, 0x01A //MH_LAVA_SLIDE 8043,0xf7, , 1, 0,-1,all, 0x2018 //MH_VOLCANIC_ASH -8208,0x86, , 0, 2,1000,enemy, 0x080 //MA_SHOWER 8209,0x90, , 0, 1,1000,enemy, 0x006 //MA_SKIDTRAP 8210,0x93, , 0, 0,1000,enemy, 0x006 //MA_LANDMINE 8211,0x95, , 0, 1,1000,enemy, 0x006 //MA_SANDMAN diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt index 082706c9a5..82bd5fad5b 100644 --- a/db/re/skill_db.txt +++ b/db/re/skill_db.txt @@ -48,7 +48,7 @@ // 14 attack type (none, weapon, magic, misc) // 15 Blowcount (amount of tiles skill knockbacks) // 16 inf3 (skill information 3): -// 0x00001 - skill ignores land protector (e.g. arrow shower) +// 0x00001 - skill ignores land protector // 0x00002 - skill that doesn't end camouflage // 0x00004 - usable skills while hiding // 0x00008 - skill that can be use while in dancing state @@ -131,7 +131,7 @@ 44,0,0,0,0,0,0,10,0,no,0,0,0,none,0,0x0, AC_VULTURE,Vulture's Eye 45,0,6,4,0,0x3,3,10,1,no,0,0,0,weapon,0,0x0, AC_CONCENTRATION,Improve Concentration 46,-9,8,1,-1,0,0,10,2,no,0,0,0,weapon,0,0x80, AC_DOUBLE,Double Strafe -47,-9,6,2,-1,0x2,2,10,1,no,0,0x40000,0,weapon,2,0x81, AC_SHOWER,Arrow Shower +47,-9,6,2,-1,0x2,1:1:1:1:1:2:2:2:2:2,10,1,no,0,0x40000,0,weapon,2,0x81, AC_SHOWER,Arrow Shower //**** // Thief @@ -1382,7 +1382,7 @@ 8205,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,0,0x0, MS_REFLECTSHIELD,Shield_Reflect 8206,0,6,4,0,0x1,0,1,1,no,0,0,0,weapon,0,0x0, MS_BERSERK,Frenzy 8207,-9,8,1,-1,0,0,10,2,no,0,0,0,weapon,0,0x80, MA_DOUBLE,Double_Strafe -8208,-9,6,2,-1,0x2,2,10,1,no,0,0x40000,0,weapon,2,0x81, MA_SHOWER,Arrow_Shower +8208,-9,6,2,-1,0x2,1:1:1:1:1:2:2:2:2:2,10,1,no,0,0x40000,0,weapon,2,0x81, MA_SHOWER,Arrow_Shower 8209,3,6,2,0,0x1,0,5,1,no,0,0x80,0,misc,6:7:8:9:10,0x3000, MA_SKIDTRAP,Skid_Trap 8210,3,6,2,2,0xC0,0,5,1,no,0,0x80,0,misc,0,0x3800, MA_LANDMINE,Land_Mine 8211,3,6,2,0,0x3,2,5,1,no,0,0x80,0,misc,0,0x3000, MA_SANDMAN,Sandman diff --git a/db/re/skill_unit_db.txt b/db/re/skill_unit_db.txt index 91bdc85364..30dbe76ed6 100644 --- a/db/re/skill_unit_db.txt +++ b/db/re/skill_unit_db.txt @@ -36,7 +36,6 @@ 21,0x86, , 0, 2:2:2:2:2:2:2:2:2:2:3,1000,enemy, 0x010 //MG_THUNDERSTORM 25,0x85, , 1, 0, -1,all, 0x6003 //AL_PNEUMA 27,0x81,0x80, 0, 0, -1,all, 0x00E //AL_WARP - 47,0x86, , 0, 1:1:1:1:1:2:2:2:2:2,1000,enemy, 0x080 //AC_SHOWER 70,0x83, , -1, 1,1000,all, 0x018 //PR_SANCTUARY 79,0x84, , -1, 1,3000,enemy, 0x8018 //PR_MAGNUS 80,0x87,0x88, 0, 1,2000,enemy, 0x4006 //WZ_FIREPILLAR @@ -84,7 +83,7 @@ 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, 300,enemy, 0x000 //NPC_DARKGRANDCROSS +339,0x86, , -1, 0, 300,enemy, 0x000 //NPC_GRANDDARKNESS 362,0xb4, , 2, 0, 300,all, 0x2000 //HP_BASILICA 369,0xb3, , -1, 0,10000,all, 0x008 //PA_GOSPEL 395,0xb5, , 4, 0, -1,all, 0x200 //CG_MOONLIT @@ -95,7 +94,7 @@ 428,0x86, , 0, 1, 100,enemy, 0x000 //SG_SUN_WARM 429,0x86, , 0, 1, 100,enemy, 0x000 //SG_MOON_WARM 430,0x86, , 0, 1, 100,enemy, 0x000 //SG_STAR_WARM -484,0xb8, , 2, 0, 500,enemy, 0x8808 //HW_GRAVITATION +484,0xb8, , 2, 0, 500,enemy, 0x8818 //HW_GRAVITATION 488,0xb9, , 3, 0, -1,all, 0x200 //CG_HERMODE 516,0x86, , 3, 0, 100,enemy, 0x000 //GS_DESPERADO 521,0xbe, , 0, 1,1000,enemy, 0x000 //GS_GROUNDDRIFT @@ -183,7 +182,6 @@ 8041,0xf6, , 1:1:2:2:3, 0,2000,enemy, 0x01A //MH_LAVA_SLIDE 8043,0xf7, , 1, 0,-1,all, 0x2018 //MH_VOLCANIC_ASH -8208,0x86, , 0, 2,1000,enemy, 0x080 //MA_SHOWER 8209,0x90, , 0, 1,1000,enemy, 0x8006 //MA_SKIDTRAP 8210,0x93, , 0, 0,1000,enemy, 0x8006 //MA_LANDMINE 8211,0x95, , 0, 1,1000,enemy, 0x8006 //MA_SANDMAN diff --git a/src/map/map.c b/src/map/map.c index a8d5ebe6d3..986b22469d 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -742,6 +742,76 @@ int map_foreachinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0 bl_list_count = blockcount; return returnCount; //[Skotlex] } + +/*========================================== [Playtester] +* Same as foreachinarea, but there must be a shoot-able range between area center and target. +* @param m: ID of map +* @param x0: West end of area +* @param y0: South end of area +* @param x1: East end of area +* @param y1: North end of area +* @param type: Type of bl to search for +*------------------------------------------*/ +int map_foreachinshootarea(int(*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...) +{ + int bx, by, cx, cy; + int returnCount = 0; //total sum of returned values of func() + struct block_list *bl; + int blockcount = bl_list_count, i; + va_list ap; + + if (m < 0 || m >= map_num) + return 0; + + if (x1 < x0) + swap(x0, x1); + if (y1 < y0) + swap(y0, y1); + + x0 = i16max(x0, 0); + y0 = i16max(y0, 0); + x1 = i16min(x1, map[m].xs - 1); + y1 = i16min(y1, map[m].ys - 1); + + cx = x0 + (x1 - x0) / 2; + cy = y0 + (y1 - y0) / 2; + + if (type&~BL_MOB) + for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) + for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) + for (bl = map[m].block[bx + by * map[m].bxs]; bl != NULL; bl = bl->next) + if (bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 + && path_search_long(NULL, m, cx, cy, bl->x, bl->y, CELL_CHKWALL) + && bl_list_count < BL_LIST_MAX) + bl_list[bl_list_count++] = bl; + + if (type&BL_MOB) + for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) + for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) + for (bl = map[m].block_mob[bx + by * map[m].bxs]; bl != NULL; bl = bl->next) + if (bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 + && path_search_long(NULL, m, cx, cy, bl->x, bl->y, CELL_CHKWALL) + && bl_list_count < BL_LIST_MAX) + bl_list[bl_list_count++] = bl; + + if (bl_list_count >= BL_LIST_MAX) + ShowWarning("map_foreachinarea: block count too many!\n"); + + map_freeblock_lock(); + + for (i = blockcount; i < bl_list_count; i++) + if (bl_list[i]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasn't queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[i], ap); + va_end(ap); + } + + map_freeblock_unlock(); + + bl_list_count = blockcount; + return returnCount; +} + /*========================================== * Adapted from forcountinarea for an easier invocation. [pakpil] *------------------------------------------*/ diff --git a/src/map/map.h b/src/map/map.h index 5a43f222a3..cc331ffeb5 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -822,7 +822,8 @@ int map_delblock(struct block_list* bl); int map_moveblock(struct block_list *, int, int, unsigned int); int map_foreachinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int type, ...); int map_foreachinshootrange(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int type, ...); -int map_foreachinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...); +int map_foreachinarea(int(*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...); +int map_foreachinshootarea(int(*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...); int map_forcountinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int count, int type, ...); int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, ...); int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, ...); diff --git a/src/map/path.c b/src/map/path.c index 238bdc28f0..b653da9d52 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -172,7 +172,7 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16 spd->y[spd->len] = y0; spd->len++; } - if (map_getcellp(md,x0,y0,cell)) + if ((x0 != x1 || y0 != y1) && map_getcellp(md,x0,y0,cell)) return false; } diff --git a/src/map/skill.c b/src/map/skill.c index 26a4bf8c43..9892ad0345 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2887,16 +2887,16 @@ void skill_attack_blow(struct block_list *src, struct block_list *dsrc, struct b if(!battle_config.stormgust_knockback) dir = rnd()%8; break; - case WL_CRIMSONROCK: - dir = map_calc_dir(target,skill_area_temp[4],skill_area_temp[5]); - break; case MC_CARTREVOLUTION: if (battle_config.cart_revo_knockback) dir = 6; // Official servers push target to the West break; case AC_SHOWER: - if (!battle_config.arrow_shower_knockback) + case WL_CRIMSONROCK: + if (!battle_config.arrow_shower_knockback && skill_id == AC_SHOWER) dir = map_calc_dir(target, src->x, src->y); + else + dir = map_calc_dir(target, skill_area_temp[4], skill_area_temp[5]); break; } @@ -4427,7 +4427,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case MO_COMBOFINISH: if (!(flag&1) && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) { //Becomes a splash attack when Soul Linked. - map_foreachinrange(skill_area_sub, bl, + map_foreachinshootrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv),splash_target(src), src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id); @@ -4438,7 +4438,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case TK_STORMKICK: // Taekwon kicks [Dralnu] clif_skill_nodamage(src,bl,skill_id,skill_lv,1); skill_area_temp[1] = 0; - map_foreachinrange(skill_attack_area, src, + map_foreachinshootrange(skill_attack_area, src, skill_get_splash(skill_id, skill_lv), splash_target(src), BF_WEAPON, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY); break; @@ -4708,7 +4708,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint skill_area_temp[0] = map_foreachinrange(skill_area_sub, bl, (skill_id == AS_SPLASHER)?1:skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill_area_sub_count); // recursive invocation of skill_castend_damage_id() with flag|1 - if (battle_config.skill_wall_check && skill_id == RA_ARROWSTORM) + if (battle_config.skill_wall_check && skill_id != NPC_EARTHQUAKE) map_foreachinshootrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), starget, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); else map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), starget, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); @@ -6293,7 +6293,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case SM_MAGNUM: case MS_MAGNUM: skill_area_temp[1] = 0; - map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_SKILL|BL_CHAR, + map_foreachinshootrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_SKILL|BL_CHAR, src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id); clif_skill_nodamage (src,src,skill_id,skill_lv,1); // Initiate 20% of your damage becomes fire element. @@ -6804,7 +6804,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui //Passive side of the attack. status_change_end(src, SC_SIGHT, INVALID_TIMER); clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub,src, + map_foreachinshootrange(skill_area_sub,src, skill_get_splash(skill_id, skill_lv),BL_CHAR|BL_SKILL, src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_ANIMATION|1, skill_castend_damage_id); @@ -6813,7 +6813,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case WZ_FROSTNOVA: clif_skill_nodamage(src,bl,skill_id,skill_lv,1); skill_area_temp[1] = 0; - map_foreachinrange(skill_attack_area, src, + map_foreachinshootrange(skill_attack_area, src, skill_get_splash(skill_id, skill_lv), splash_target(src), BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY); break; @@ -6826,7 +6826,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui BCT_ENEMY:BCT_ALL; clif_skill_nodamage(src, src, skill_id, -1, 1); map_delblock(src); //Required to prevent chain-self-destructions hitting back. - map_foreachinrange(skill_area_sub, bl, + map_foreachinshootrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|i, skill_castend_damage_id); @@ -10984,7 +10984,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) break; } #ifdef OFFICIAL_WALKPATH - if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) ) + if(skill_get_casttype(ud->skill_id) != CAST_NODAMAGE && !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL)) { if (sd) { clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); @@ -11358,7 +11358,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case BS_HAMMERFALL: i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea (skill_area_sub, + map_foreachinarea(skill_area_sub, src->m, x-i, y-i, x+i, y+i, BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|2, skill_castend_nodamage_id); @@ -11434,8 +11434,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case WE_CALLPARTNER: case WE_CALLPARENT: case WE_CALLBABY: - case AC_SHOWER: //Ground-placed skill implementation. - case MA_SHOWER: case SA_LANDPROTECTOR: case BD_LULLABY: case BD_RICHMANKIM: @@ -11768,13 +11766,18 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case RK_WINDCUTTER: clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + case AC_SHOWER: + case MA_SHOWER: case NC_COLDSLOWER: case NC_ARMSCANNON: case RK_DRAGONBREATH: case RK_DRAGONBREATH_WATER: + // Cast center might be relevant later (e.g. for knockback direction) + skill_area_temp[4] = x; + skill_area_temp[5] = y; i = skill_get_splash(skill_id,skill_lv); if (battle_config.skill_wall_check) - map_foreachinshootrange(skill_area_sub,src,skill_get_splash(skill_id, skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + map_foreachinshootarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); else map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); break; @@ -12744,8 +12747,8 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_ 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 && unit_flag&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) ) - continue; // no path between cell and center of casting. + if( battle_config.skill_wall_check && unit_flag&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,src->x,src->y,CELL_CHKWALL) ) + continue; // no path between cell and caster switch( skill_id ) { // HP for Skill unit that can be damaged, see also skill_unit_ondamaged @@ -13445,18 +13448,23 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns case UNT_FREEZINGTRAP: case UNT_FIREPILLAR_ACTIVE: case UNT_CLAYMORETRAP: + { + int bl_flag = sg->bl_flag; if (tsc && tsc->data[SC__MANHOLE]) break; if (sg->unit_id == UNT_FIRINGTRAP || sg->unit_id == UNT_ICEBOUNDTRAP || sg->unit_id == UNT_CLAYMORETRAP) - map_foreachinrange(skill_trap_splash, &unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &unit->bl, tick); + bl_flag = bl_flag|BL_SKILL|~BCT_SELF; + if(battle_config.skill_wall_check && !(skill_get_nk(skill_id)&NK_NO_DAMAGE)) + map_foreachinshootrange(skill_trap_splash, &unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), bl_flag, &unit->bl, tick); else - map_foreachinrange(skill_trap_splash, &unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &unit->bl, tick); + map_foreachinrange(skill_trap_splash, &unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), bl_flag, &unit->bl, tick); if (sg->unit_id != UNT_FIREPILLAR_ACTIVE) clif_changetraplook(&unit->bl,(sg->unit_id == UNT_LANDMINE ? UNT_FIREPILLAR_ACTIVE : UNT_USED_TRAPS)); sg->limit = DIFF_TICK(tick, sg->tick) + (sg->unit_id == UNT_CLUSTERBOMB || sg->unit_id == UNT_ICEBOUNDTRAP ? 1000 : 0) + // Cluster Bomb/Icebound has 1s to disappear once activated. (sg->unit_id == UNT_FIRINGTRAP ? 0 : 1500); // Firing Trap gets removed immediately once activated. sg->unit_id = UNT_USED_TRAPS; // Change ID so it does not invoke a for each in area again. + } break; case UNT_TALKIEBOX: @@ -16796,10 +16804,16 @@ int skill_detonator(struct block_list *bl, va_list ap) case UNT_CLAYMORETRAP: case UNT_FIRINGTRAP: case UNT_ICEBOUNDTRAP: - map_foreachinrange(skill_trap_splash,bl,skill_get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag|BL_SKILL|~BCT_SELF,bl,unit->group->tick); + if (battle_config.skill_wall_check) + map_foreachinshootrange(skill_trap_splash,bl,skill_get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag|BL_SKILL|~BCT_SELF,bl,unit->group->tick); + else + map_foreachinrange(skill_trap_splash,bl,skill_get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag|BL_SKILL|~BCT_SELF,bl,unit->group->tick); break; default: - map_foreachinrange(skill_trap_splash,bl,skill_get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag,bl,unit->group->tick); + if(battle_config.skill_wall_check && !(skill_get_nk(unit->group->skill_id)&NK_NO_DAMAGE)) + map_foreachinshootrange(skill_trap_splash,bl,skill_get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag,bl,unit->group->tick); + else + map_foreachinrange(skill_trap_splash,bl,skill_get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag,bl,unit->group->tick); break; } clif_changetraplook(bl, UNT_USED_TRAPS); @@ -19337,7 +19351,10 @@ static int skill_destroy_trap(struct block_list *bl, va_list ap) case UNT_CLAYMORETRAP: case UNT_FIRINGTRAP: case UNT_ICEBOUNDTRAP: - map_foreachinrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &su->bl,tick); + if(battle_config.skill_wall_check) + map_foreachinshootrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &su->bl,tick); + else + map_foreachinrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &su->bl,tick); break; case UNT_LANDMINE: case UNT_BLASTMINE: @@ -19346,7 +19363,10 @@ static int skill_destroy_trap(struct block_list *bl, va_list ap) case UNT_FLASHER: case UNT_FREEZINGTRAP: case UNT_CLUSTERBOMB: - map_foreachinrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick); + if (battle_config.skill_wall_check && !(skill_get_nk(sg->skill_id)&NK_NO_DAMAGE)) + map_foreachinshootrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick); + else + map_foreachinrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick); break; } // Traps aren't recovered. diff --git a/src/map/unit.c b/src/map/unit.c index f579ed62d4..4c722a046e 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1986,13 +1986,6 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui return 0; } - 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_id,USESKILL_FAIL_LEVEL,0); - - return 0; - } - // Check range and obstacle bl.type = BL_NUL; bl.m = src->m;