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
This commit is contained in:
Playtester 2016-03-05 18:02:22 +01:00
parent fb4cf3e5e3
commit 7906f0a3ff
9 changed files with 125 additions and 45 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]
*------------------------------------------*/

View File

@ -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, ...);

View File

@ -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;
}

View File

@ -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.

View File

@ -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;