Fixes script commands unitwalkto/unitwalk (#7007)
* Fixes #5340. * Resolves an issue where monsters may tend to lose their target if they are too slow and the destination is too far when using script commands unitwalkto/unitwalk. * Allow script command unitstopwalk to remove the state tracking for script commands unitwalk/unitwalkto. * Print a warning to the console if a unit is forced to walk again and hasn't yet reached its initial destination. Thanks to @NeutralDev and @Lemongrass3110!
This commit is contained in:
parent
2bb79d0200
commit
aad3a70bbc
@ -8270,6 +8270,8 @@ values (can be combined using the pipe operator):
|
||||
USW_MOVE_FULL_CELL = Enable moving to the next cell when unit was already half-way there (may cause on-touch/place side-effects, such as a scripted map change).
|
||||
USW_FORCE_STOP = Force stop moving.
|
||||
|
||||
This command will also remove the state tracking used for 'unitwalk' and 'unitwalkto'.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*unittalk <GID>,"<text>"{,flag};
|
||||
|
@ -1687,6 +1687,10 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
|
||||
if(md->bl.prev == nullptr || md->status.hp == 0)
|
||||
return false;
|
||||
|
||||
// Monsters force-walked by script commands should not be searching for targets.
|
||||
if (md->ud.state.force_walk)
|
||||
return false;
|
||||
|
||||
if (DIFF_TICK(tick, md->last_thinktime) < MIN_MOBTHINKTIME)
|
||||
return false;
|
||||
|
||||
@ -2005,6 +2009,10 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
|
||||
if(md->bl.prev == NULL)
|
||||
return 0;
|
||||
|
||||
// Monsters force-walked by script commands should not be searching for targets.
|
||||
if (md->ud.state.force_walk)
|
||||
return false;
|
||||
|
||||
t_tick tick = va_arg(args,t_tick);
|
||||
|
||||
if (battle_config.mob_ai&0x20 && map_getmapdata(md->bl.m)->users>0)
|
||||
|
@ -19310,6 +19310,13 @@ BUILDIN_FUNC(unitwalk)
|
||||
|
||||
ud = unit_bl2ud(bl);
|
||||
|
||||
// Unit was already forced to walk.
|
||||
if (ud != nullptr && ud->state.force_walk) {
|
||||
script_pushint(st, 0);
|
||||
ShowWarning("buildin_%s: Unit has already been forced to walk and not reached it's destination yet.\n", cmd);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (bl->type == BL_NPC) {
|
||||
if (!((TBL_NPC*)bl)->status.hp)
|
||||
status_calc_npc(((TBL_NPC*)bl), SCO_FIRST);
|
||||
@ -19321,8 +19328,11 @@ BUILDIN_FUNC(unitwalk)
|
||||
int x = script_getnum(st,3);
|
||||
int y = script_getnum(st,4);
|
||||
|
||||
if (script_pushint(st, unit_can_reach_pos(bl,x,y,0)))
|
||||
if (script_pushint(st, unit_can_reach_pos(bl,x,y,0))) {
|
||||
if (ud != nullptr)
|
||||
ud->state.force_walk = true;
|
||||
add_timer(gettick()+50, unit_delay_walktoxy_timer, bl->id, (x<<16)|(y&0xFFFF)); // Need timer to avoid mismatches
|
||||
}
|
||||
} else {
|
||||
struct block_list* tbl = map_id2bl(script_getnum(st,3));
|
||||
|
||||
@ -19330,8 +19340,11 @@ BUILDIN_FUNC(unitwalk)
|
||||
ShowError("buildin_unitwalk: Bad target destination.\n");
|
||||
script_pushint(st, 0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
} else if (script_pushint(st, unit_can_reach_bl(bl, tbl, distance_bl(bl, tbl)+1, 0, NULL, NULL)))
|
||||
} else if (script_pushint(st, unit_can_reach_bl(bl, tbl, distance_bl(bl, tbl)+1, 0, NULL, NULL))) {
|
||||
if (ud != nullptr)
|
||||
ud->state.force_walk = true;
|
||||
add_timer(gettick()+50, unit_delay_walktobl_timer, bl->id, tbl->id); // Need timer to avoid mismatches
|
||||
}
|
||||
off = 4;
|
||||
}
|
||||
|
||||
@ -19477,10 +19490,21 @@ BUILDIN_FUNC(unitstopwalk)
|
||||
if (script_hasdata(st, 3))
|
||||
flag = script_getnum(st, 3);
|
||||
|
||||
if(script_rid2bl(2,bl))
|
||||
unit_stop_walking(bl, flag);
|
||||
if(script_rid2bl(2,bl)) {
|
||||
unit_data *ud = unit_bl2ud(bl);
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
if (ud != nullptr)
|
||||
ud->state.force_walk = false;
|
||||
|
||||
if (unit_stop_walking(bl, flag) == 0 && flag != USW_FORCE_STOP) {
|
||||
ShowWarning("buildin_unitstopwalk: Unable to find unit or unit is not walking.\n");
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
} else {
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -435,7 +435,7 @@ static TIMER_FUNC(unit_walktoxy_timer)
|
||||
|
||||
//Monsters can only leave icewalls to the west and south
|
||||
//But if movement fails more than icewall_walk_block times, they can ignore this rule
|
||||
if(md && md->walktoxy_fail_count < icewall_walk_block && map_getcell(bl->m,x,y,CELL_CHKICEWALL) && (dx > 0 || dy > 0)) {
|
||||
if(md && !ud->state.force_walk && md->walktoxy_fail_count < icewall_walk_block && map_getcell(bl->m,x,y,CELL_CHKICEWALL) && (dx > 0 || dy > 0)) {
|
||||
//Needs to be done here so that rudeattack skills are invoked
|
||||
md->walktoxy_fail_count++;
|
||||
clif_fixpos(bl);
|
||||
@ -472,6 +472,8 @@ static TIMER_FUNC(unit_walktoxy_timer)
|
||||
}
|
||||
#endif
|
||||
|
||||
ud->state.force_walk = false;
|
||||
|
||||
if (ud->walk_done_event[0]){
|
||||
char walk_done_event[EVENT_NAME_LENGTH];
|
||||
|
||||
@ -526,7 +528,7 @@ static TIMER_FUNC(unit_walktoxy_timer)
|
||||
md->min_chase--;
|
||||
// Walk skills are triggered regardless of target due to the idle-walk mob state.
|
||||
// But avoid triggering on stop-walk calls.
|
||||
if(tid != INVALID_TIMER &&
|
||||
if(!ud->state.force_walk && tid != INVALID_TIMER &&
|
||||
!(ud->walk_count%WALK_SKILL_INTERVAL) &&
|
||||
map[bl->m].users > 0 &&
|
||||
mobskill_use(md, tick, -1)) {
|
||||
|
@ -58,6 +58,7 @@ struct unit_data {
|
||||
unsigned blockedmove : 1;
|
||||
unsigned blockedskill : 1;
|
||||
unsigned ignore_cell_stack_limit : 1;
|
||||
bool force_walk; ///< Used with script commands unitwalk/unitwalkto. Disables monster idle and random walk.
|
||||
} state;
|
||||
char walk_done_event[EVENT_NAME_LENGTH];
|
||||
char title[NAME_LENGTH];
|
||||
|
Loading…
x
Reference in New Issue
Block a user