From b8abf962fd079bc3cad4498aa968f2318d1f5fde Mon Sep 17 00:00:00 2001 From: Michieru Date: Mon, 3 Nov 2014 11:46:22 +0100 Subject: * No cell stacking implemented (official version) - Split config cell_stack_limit into custom_cell_stack_limit (previous feature) and official_cell_stack_limit (see below) - Expanded map_count_oncell by a flag parameter, currently only one flag is supported: only count standing units (needed for official cell stack feature) - Added a new function map_closest_freecell that will return the closest free cell using the same order that official servers use - Monsters will now actively search for a free cell when starting to walk randomly and when unlocking target - When any unit finishes walking (regularly) and is not on a free cell, it will now actively search for a free cell - Step actions will be delayed until a suitable cell was found, they will even be executed when the player walked slightly out of attack range - Monsters will now stop instantly if their target is completely non-existent * This is mainly for looters that had their loot taken * Hide and most other situations still use the configuration setting monster_chase_refresh Mega Thanks to Playtester --- src/map/unit.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src/map/unit.c') diff --git a/src/map/unit.c b/src/map/unit.c index 34a9dcc24..f7b484e0c 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -197,7 +197,7 @@ int unit_step_timer(int tid, int64 tick, int id, intptr_t data) } if(ud->stepskill_id == 0) { //Execute normal attack - unit->attack(bl, tbl->id, ud->state.attack_continue); + unit->attack(bl, tbl->id, (ud->state.attack_continue) + 2); } else { //Execute non-ground skill unit->skilluse_id(bl, tbl->id, ud->stepskill_id, ud->stepskill_lv); @@ -439,6 +439,16 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { //Stopped walking. Update to_x and to_y to current location [Skotlex] ud->to_x = bl->x; ud->to_y = bl->y; + + if(map->count_oncell(bl->m, x, y, BL_CHAR|BL_NPC, 1) > battle_config.official_cell_stack_limit) { + //Walked on occupied cell, call unit_walktoxy again + if(ud->steptimer != INVALID_TIMER) { + //Execute step timer on next step instead + timer->delete(ud->steptimer, unit_step_timer); + ud->steptimer = INVALID_TIMER; + } + return unit->walktoxy(bl, x, y, 8); + } } return 0; } @@ -456,6 +466,7 @@ int unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { //&1 -> 1/0 = easy/hard //&2 -> force walking //&4 -> Delay walking if the reason you can't walk is the canwalk delay +//&8 -> Search for an unoccupied cell and cancel if none available int unit_walktoxy( struct block_list *bl, short x, short y, int flag) { struct unit_data* ud = NULL; @@ -468,6 +479,9 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag) if( ud == NULL) return 0; + if ((flag&8) && !map->closest_freecell(bl->m, &x, &y, BL_CHAR|BL_NPC, 1)) //This might change x and y + return 0; + if (!path->search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells return 0; @@ -654,7 +668,7 @@ bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type break; //if sprinting and there's a PC/Mob/NPC, block the path [Kevin] - if( map->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC) ) + if( map->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC, 0) ) break; to_x += dir_x; @@ -1792,6 +1806,7 @@ int unit_unattackable(struct block_list *bl) struct unit_data *ud = unit->bl2ud(bl); if (ud) { ud->state.attack_continue = 0; + ud->state.step_attack = 0; unit->set_target(ud, 0); } @@ -1838,7 +1853,8 @@ int unit_attack(struct block_list *src,int target_id,int continuous) { unit->unattackable(src); return 1; } - ud->state.attack_continue = continuous; + ud->state.attack_continue = (continuous&1)?1:0; + ud->state.step_attack = (continuous&2)?1:0; unit->set_target(ud, target_id); range = status_get_range(src); @@ -2064,7 +2080,8 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { sstatus = status->get_status_data(src); range = sstatus->rhw.range; - if( unit->is_walking(target) && (target->type == BL_PC || !map->getcell(target->m,target->x,target->y,CELL_CHKICEWALL)) ) + if( (unit_is_walking(target) || ud->state.step_attack) + && (target->type == BL_PC || !map->getcell(target->m,target->x,target->y,CELL_CHKICEWALL)) ) range++; // Extra range when chasing (does not apply to mobs locked in an icewall) if(sd && !check_distance_client_bl(src,target,range)) { -- cgit v1.2.3-60-g2f50