Fixed looters getting stuck (#6958)
- Fixes #6939 - Looters will now use complex pathing to find a way to an item they can see - Monsters no longer stop when using NPC_EMOTION or NPC_EMOTION_ON - Added a security check to prevent endless loops when easy pathing is used (no longer used by default) Special thanks to @secretdataz.
This commit is contained in:
parent
20d9fa6cc7
commit
f5e75d28ec
@ -978,29 +978,14 @@ bool mob_is_chasing(int state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
* Reachability to a Specification ID existence place
|
* Checks if a monster can reach a target by walking
|
||||||
* state indicates type of 'seek' mob should do:
|
* Range: Maximum number of cells to be walked
|
||||||
* - MSS_LOOT: Looking for item, path must be easy.
|
|
||||||
* - MSS_RUSH: Chasing attacking player, path is complex
|
|
||||||
* - MSS_FOLLOW: Initiative/support seek, path is complex
|
|
||||||
*------------------------------------------*/
|
*------------------------------------------*/
|
||||||
int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state)
|
int mob_can_reach(struct mob_data *md,struct block_list *bl,int range)
|
||||||
{
|
{
|
||||||
int easy = 0;
|
|
||||||
|
|
||||||
nullpo_ret(md);
|
nullpo_ret(md);
|
||||||
nullpo_ret(bl);
|
nullpo_ret(bl);
|
||||||
switch (state) {
|
return unit_can_reach_bl(&md->bl, bl, range, 0, NULL, NULL);
|
||||||
case MSS_RUSH:
|
|
||||||
case MSS_FOLLOW:
|
|
||||||
easy = 0; //(battle_config.mob_ai&0x1?0:1);
|
|
||||||
break;
|
|
||||||
case MSS_LOOT:
|
|
||||||
default:
|
|
||||||
easy = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return unit_can_reach_bl(&md->bl, bl, range, easy, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
@ -1023,7 +1008,7 @@ int mob_linksearch(struct block_list *bl,va_list ap)
|
|||||||
&& !md->target_id)
|
&& !md->target_id)
|
||||||
{
|
{
|
||||||
md->last_linktime = tick;
|
md->last_linktime = tick;
|
||||||
if( mob_can_reach(md,target,md->db->range2, MSS_FOLLOW) ){ // Reachability judging
|
if( mob_can_reach(md,target,md->db->range2) ){ // Reachability judging
|
||||||
md->target_id = target->id;
|
md->target_id = target->id;
|
||||||
md->min_chase=md->db->range3;
|
md->min_chase=md->db->range3;
|
||||||
return 1;
|
return 1;
|
||||||
@ -1382,7 +1367,7 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
|
|||||||
target = va_arg(ap,struct block_list**);
|
target = va_arg(ap,struct block_list**);
|
||||||
|
|
||||||
dist = distance_bl(&md->bl, bl);
|
dist = distance_bl(&md->bl, bl);
|
||||||
if (mob_can_reach(md,bl,dist+1, MSS_LOOT) && (
|
if (mob_can_reach(md, bl, md->db->range3) && (
|
||||||
(*target) == nullptr ||
|
(*target) == nullptr ||
|
||||||
(battle_config.monster_loot_search_type && md->target_id > bl->id) ||
|
(battle_config.monster_loot_search_type && md->target_id > bl->id) ||
|
||||||
(!battle_config.monster_loot_search_type && !check_distance_bl(&md->bl, *target, dist)) // New target closer than previous one.
|
(!battle_config.monster_loot_search_type && !check_distance_bl(&md->bl, *target, dist)) // New target closer than previous one.
|
||||||
@ -1755,7 +1740,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
|
|||||||
|| md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target.
|
|| md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target.
|
||||||
|| md->walktoxy_fail_count > 0)
|
|| md->walktoxy_fail_count > 0)
|
||||||
)
|
)
|
||||||
|| !mob_can_reach(md, tbl, md->min_chase, MSS_RUSH)
|
|| !mob_can_reach(md, tbl, md->min_chase)
|
||||||
)
|
)
|
||||||
&& md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
|
&& md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
|
||||||
&& !mobskill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack
|
&& !mobskill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack
|
||||||
@ -1780,7 +1765,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
|
|||||||
|| md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target.
|
|| md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target.
|
||||||
|| md->walktoxy_fail_count > 0)
|
|| md->walktoxy_fail_count > 0)
|
||||||
)
|
)
|
||||||
|| !mob_can_reach(md, abl, dist+md->db->range3, MSS_RUSH)
|
|| !mob_can_reach(md, abl, dist+md->db->range3)
|
||||||
)
|
)
|
||||||
) )
|
) )
|
||||||
{ // Rude attacked
|
{ // Rude attacked
|
||||||
@ -1880,7 +1865,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
|
|||||||
if (!can_move) //Stuck. Wait before walking.
|
if (!can_move) //Stuck. Wait before walking.
|
||||||
return true;
|
return true;
|
||||||
md->state.skillstate = MSS_LOOT;
|
md->state.skillstate = MSS_LOOT;
|
||||||
if (!unit_walktobl(&md->bl, tbl, 0, 1))
|
if (!unit_walktobl(&md->bl, tbl, 0, 0))
|
||||||
mob_unlocktarget(md, tick); //Can't loot...
|
mob_unlocktarget(md, tick); //Can't loot...
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1978,7 +1963,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
|
|||||||
|
|
||||||
//Follow up if possible.
|
//Follow up if possible.
|
||||||
//Hint: Chase skills are handled in the walktobl routine
|
//Hint: Chase skills are handled in the walktobl routine
|
||||||
if(!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) ||
|
if(!mob_can_reach(md, tbl, md->min_chase) ||
|
||||||
!unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2))
|
!unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2))
|
||||||
mob_unlocktarget(md,tick);
|
mob_unlocktarget(md,tick);
|
||||||
|
|
||||||
|
@ -531,6 +531,7 @@ static TIMER_FUNC(unit_walktoxy_timer)
|
|||||||
map[bl->m].users > 0 &&
|
map[bl->m].users > 0 &&
|
||||||
mobskill_use(md, tick, -1)) {
|
mobskill_use(md, tick, -1)) {
|
||||||
if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)
|
if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)
|
||||||
|
&& ud->skill_id != NPC_EMOTION && ud->skill_id != NPC_EMOTION_ON //NPC_EMOTION doesn't make the monster stop
|
||||||
&& md->state.skillstate != MSS_WALK) //Walk skills are supposed to be used while walking
|
&& md->state.skillstate != MSS_WALK) //Walk skills are supposed to be used while walking
|
||||||
{ // Skill used, abort walking
|
{ // Skill used, abort walking
|
||||||
clif_fixpos(bl); // Fix position as walk has been cancelled.
|
clif_fixpos(bl); // Fix position as walk has been cancelled.
|
||||||
@ -855,6 +856,9 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, unsi
|
|||||||
//Should walk on the same cell as target (for looters)
|
//Should walk on the same cell as target (for looters)
|
||||||
ud->to_x = tbl->x;
|
ud->to_x = tbl->x;
|
||||||
ud->to_y = tbl->y;
|
ud->to_y = tbl->y;
|
||||||
|
//Because of the change of target position the easy walkpath could fail
|
||||||
|
//Note: Easy walking is no longer used by default, but we keep this to prevent endless loops [Playtester]
|
||||||
|
flag &= ~1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ud->state.walk_easy = flag&1;
|
ud->state.walk_easy = flag&1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user