diff options
-rw-r--r-- | src/map/map.c | 6 | ||||
-rw-r--r-- | src/map/map.h | 7 | ||||
-rw-r--r-- | src/map/mob.c | 4 | ||||
-rw-r--r-- | src/map/skill.c | 103 |
4 files changed, 79 insertions, 41 deletions
diff --git a/src/map/map.c b/src/map/map.c index 8fe860995..dadc0e4e8 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -2493,13 +2493,13 @@ int map_getcellp(struct map_data* m,int x,int y,cell_chk cellchk) // base gat type checks case CELL_CHKWALL: return (!cell.walkable && !cell.shootable); - //return (map_cell2gat(cell) == 1); + case CELL_CHKWATER: return (cell.water); - //return (map_cell2gat(cell) == 3); + case CELL_CHKCLIFF: return (!cell.walkable && cell.shootable); - //return (map_cell2gat(cell) == 5); + // base cell type checks case CELL_CHKNPC: diff --git a/src/map/map.h b/src/map/map.h index ceddec555..be90b6644 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -540,6 +540,13 @@ struct map_data { int jexp; // map experience multiplicator int bexp; // map experience multiplicator int nocommand; //Blocks @/# commands for non-gms. [Skotlex] + /** + * Ice wall reference counter for bugreport:3574 + * - since there are a thounsand mobs out there in a lot of maps checking on, + * - every targetting for icewall on attack path would just be a waste, so, + * - this counter allows icewall checking be only run when there is a actual ice wall on the map + **/ + int icewall_num; // Instance Variables int instance_id; int instance_src_map; diff --git a/src/map/mob.c b/src/map/mob.c index c2270afb3..bdc661f58 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1016,7 +1016,9 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) dist = distance_bl(&md->bl, bl); if( ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) && - battle_check_range(&md->bl,bl,md->db->range2) + battle_check_range(&md->bl,bl,md->db->range2) && ( map[bl->m].icewall_num && ( + check_distance_bl(&md->bl, bl, status_get_range(&md->bl) ) || + path_search_long(NULL,bl->m,md->bl.x,md->bl.y,bl->x,bl->y,CELL_CHKICEWALL) ) ) ) { //Pick closest target? (*target) = bl; md->target_id=bl->id; diff --git a/src/map/skill.c b/src/map/skill.c index 87fcc6dde..2fe268eaa 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -9385,7 +9385,29 @@ static bool skill_dance_switch(struct skill_unit* unit, int flag) return true; } +/** + * Upon Ice Wall cast it checks all nearby mobs to find any who may be blocked by the IW + **/ +static int skill_icewall_block(struct block_list *bl,va_list ap) { + struct block_list *src; + struct mob_data *md = ((TBL_MOB*)bl); + + nullpo_ret(bl); + + src = va_arg(ap,struct block_list *); + + nullpo_ret(src); + nullpo_ret(md); + + if( md->target_id != src->id + || check_distance_bl(bl, src, status_get_range(bl) ) + || path_search_long(NULL,bl->m,bl->x,bl->y,src->x,src->y,CELL_CHKICEWALL) ) + return 0; + + mob_unlocktarget(md,gettick()); + return 0; +} /*========================================== * Initializes and sets a ground skill. * flag&1 is used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active) @@ -9796,9 +9818,15 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli return NULL; } - - if (skillid == NJ_TATAMIGAESHI) //Store number of tiles. - group->val1 = group->alive_count; + //success, unit created. + switch( skillid ) { + case WZ_ICEWALL: //Store number of tiles. + map_foreachinrange(skill_icewall_block, src, AREA_SIZE, BL_MOB, src); + break; + case NJ_TATAMIGAESHI: //Store number of tiles. + group->val1 = group->alive_count; + break; + } return group; } @@ -13234,6 +13262,7 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,5); clif_changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,5,AREA); skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,true); + map[unit->bl.m].icewall_num++; break; case SA_LANDPROTECTOR: skill_unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,true); @@ -13278,40 +13307,40 @@ int skill_delunit (struct skill_unit* unit) // perform ondelete actions switch (group->skill_id) { - case HT_ANKLESNARE: - { - struct block_list* target = map_id2bl(group->val2); - if( target ) - status_change_end(target, SC_ANKLE, INVALID_TIMER); - } - break; - case WZ_ICEWALL: - map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,unit->val2); - clif_changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug - skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false); - break; - case SA_LANDPROTECTOR: - skill_unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,false); - break; - case HP_BASILICA: - skill_unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,false); - break; - case RA_ELECTRICSHOCKER: { - struct block_list* target = map_id2bl(group->val2); - if( target ) - status_change_end(target, SC_ELECTRICSHOCKER, -1); - break; - } - case SC_MAELSTROM: - skill_unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,false); - break; - case SC_MANHOLE: // Note : Removing the unit don't remove the status (official info) - if( group->val2 ) { // Someone Traped - struct status_change *tsc = status_get_sc( map_id2bl(group->val2)); - if( tsc && tsc->data[SC__MANHOLE] ) - tsc->data[SC__MANHOLE]->val4 = 0; // Remove the Unit ID - } - break; + case HT_ANKLESNARE: { + struct block_list* target = map_id2bl(group->val2); + if( target ) + status_change_end(target, SC_ANKLE, INVALID_TIMER); + } + break; + case WZ_ICEWALL: + map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,unit->val2); + clif_changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug + skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false); + map[unit->bl.m].icewall_num--; + break; + case SA_LANDPROTECTOR: + skill_unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,false); + break; + case HP_BASILICA: + skill_unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,false); + break; + case RA_ELECTRICSHOCKER: { + struct block_list* target = map_id2bl(group->val2); + if( target ) + status_change_end(target, SC_ELECTRICSHOCKER, -1); + } + break; + case SC_MAELSTROM: + skill_unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,false); + break; + case SC_MANHOLE: // Note : Removing the unit don't remove the status (official info) + if( group->val2 ) { // Someone Traped + struct status_change *tsc = status_get_sc( map_id2bl(group->val2)); + if( tsc && tsc->data[SC__MANHOLE] ) + tsc->data[SC__MANHOLE]->val4 = 0; // Remove the Unit ID + } + break; } clif_skill_delunit(unit); |