diff --git a/conf/battle/monster.conf b/conf/battle/monster.conf
index 5102c3a875..cfbecf2266 100644
--- a/conf/battle/monster.conf
+++ b/conf/battle/monster.conf
@@ -29,9 +29,7 @@ monster_max_aspd: 199
 // 0x004: If not set, mobs that can change target only do so when melee attacked
 //        (distance player/mob < 3), otherwise mobs may change target and chase 
 //        ranged attackers. This flag also overrides the 'provoke' target.
-// 0x008: If set, when a mob loses track of their target, they stop walking
-//        immediately. Otherwise, they continue to their last target tile. When
-//        set mobs also scatter as soon as they lose their target. Use this mode
+// 0x008: When set, mobs scatter as soon as they lose their target. Use this mode
 //        to make it much harder to mob-train by hiding and collecting them on a
 //        single spot (ie: GrimTooth training)
 // 0x010: If set, mob skills defined for friends will also trigger on themselves.
@@ -52,6 +50,17 @@ monster_max_aspd: 199
 // Example: 0x140 -> Chase players through warps + use skills in random order.
 monster_ai: 0
 
+// How often should a monster rethink its chase?
+// 0: Every 100ms (MIN_MOBTHINKTIME)
+// 1: Every cell moved (official)
+// 2: Every 2 cells moved
+// 3: Every 3 cells moved (previous setting)
+// x: Every x cells moved
+// Regardless of this setting, a monster will always rethink its chase if it has 
+// reached its target. Increase this value if you want to make monsters continue
+// moving after they lost their target (hide, loot picked, etc.).
+monster_chase_refresh: 1
+
 // Should mobs be able to be warped (add as needed)?
 // 0: Disable.
 // 1: Enable mob-warping when standing on NPC-warps
diff --git a/src/map/battle.c b/src/map/battle.c
index 58449aeb0f..407000657f 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -7666,6 +7666,7 @@ static const struct _battle_data {
 	{ "berserk_cancels_buffs",              &battle_config.berserk_cancels_buffs,           0,      0,      1,              },
 	{ "debuff_on_logout",                   &battle_config.debuff_on_logout,                1|2,    0,      1|2,            },
 	{ "monster_ai",                         &battle_config.mob_ai,                          0x000,  0x000,  0x77F,          },
+	{ "monster_chase_refresh",              &battle_config.mob_chase_refresh,               1,      0,      30,             },
 	{ "hom_setting",                        &battle_config.hom_setting,                     0xFFFF, 0x0000, 0xFFFF,         },
 	{ "dynamic_mobs",                       &battle_config.dynamic_mobs,                    1,      0,      1,              },
 	{ "mob_remove_damaged",                 &battle_config.mob_remove_damaged,              1,      0,      1,              },
diff --git a/src/map/battle.h b/src/map/battle.h
index c792c91348..2329d40510 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -402,6 +402,7 @@ extern struct Battle_Config
 	int berserk_cancels_buffs; // [Aru]
 	int debuff_on_logout; // Removes a few "official" negative Scs on logout. [Skotlex]
 	int mob_ai; //Configures various mob_ai settings to make them smarter or dumber(official). [Skotlex]
+	int mob_chase_refresh; //How often a monster should refresh its chase [Playtester]
 	int hom_setting; //Configures various homunc settings which make them behave unlike normal characters.. [Skotlex]
 	int dynamic_mobs; // Dynamic Mobs [Wizputer] - battle_athena flag implemented by [random]
 	int mob_remove_damaged; // Dynamic Mobs - Remove mobs even if damaged [Wizputer]
diff --git a/src/map/mob.c b/src/map/mob.c
index fd0c726bc8..a92f1e85e7 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -1316,8 +1316,7 @@ int mob_unlocktarget(struct mob_data *md, unsigned int tick)
 		break;
 	default:
 		mob_stop_attack(md);
-		if (battle_config.mob_ai&0x8)
-			mob_stop_walking(md,1); //Immediately stop chasing.
+		mob_stop_walking(md,1); //Stop chasing.
 		md->state.skillstate = MSS_IDLE;
 		md->next_walktime=tick+rnd()%3000+3000;
 		break;
@@ -1423,9 +1422,6 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 	if (md->ud.skilltimer != INVALID_TIMER)
 		return false;
 
-	if(md->ud.walktimer != INVALID_TIMER && md->ud.walkpath.path_pos <= 3)
-		return false;
-
 	// Abnormalities
 	if(( md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE )
 	   || md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {//Should reset targets.
@@ -1451,10 +1447,12 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 				tbl->type == BL_PC &&
 				((((TBL_PC*)tbl)->state.gangsterparadise && !(mode&MD_BOSS)) ||
 				((TBL_PC*)tbl)->invincible_timer != INVALID_TIMER)
-		)) {	//Unlock current target.
+		)) {	//No valid target
 			if (mob_warpchase(md, tbl))
 				return true; //Chasing this target.
-			mob_unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Imediately do random walk.
+			if(md->ud.walktimer != INVALID_TIMER && md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh)
+				return true; //Walk at least "mob_chase_refresh" cells before dropping the target
+			mob_unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Immediately do random walk.
 			tbl = NULL;
 		}
 	}
@@ -1626,25 +1624,25 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 		mob_unlocktarget (md,tick);
 		return true;
 	}
+
 	//Attempt to attack.
 	//At this point we know the target is attackable, we just gotta check if the range matches.
-	if (md->ud.target == tbl->id && md->ud.attacktimer != INVALID_TIMER) //Already locked.
-		return true;
-
 	if (battle_check_range (&md->bl, tbl, md->status.rhw.range))
 	{	//Target within range, engage
+		if (md->ud.target != tbl->id || md->ud.attacktimer == INVALID_TIMER) 
+		{ //Only attack if no more attack delay left
+			if(tbl->type == BL_PC)
+				mob_log_damage(md, tbl, 0); //Log interaction (counts as 'attacker' for the exp bonus)
 
-		if(tbl->type == BL_PC)
-			mob_log_damage(md, tbl, 0); //Log interaction (counts as 'attacker' for the exp bonus)
-
-		if( !(mode&MD_RANDOMTARGET) )
-			unit_attack(&md->bl,tbl->id,1);
-		else { // Attack once and find a new random target
-			int search_size = (view_range < md->status.rhw.range) ? view_range : md->status.rhw.range;
-			unit_attack(&md->bl, tbl->id, 0);
-			if ((tbl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), search_size))) {
-				md->target_id = tbl->id;
-				md->min_chase = md->db->range3;
+			if( !(mode&MD_RANDOMTARGET) )
+				unit_attack(&md->bl,tbl->id,1);
+			else { // Attack once and find a new random target
+				int search_size = (view_range < md->status.rhw.range) ? view_range : md->status.rhw.range;
+				unit_attack(&md->bl, tbl->id, 0);
+				if ((tbl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), search_size))) {
+					md->target_id = tbl->id;
+					md->min_chase = md->db->range3;
+				}
 			}
 		}
 		return true;
@@ -1653,17 +1651,23 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 	//Out of range...
 	if (!(mode&MD_CANMOVE))
 	{	//Can't chase. Attempt an idle skill before unlocking.
-		md->state.skillstate = MSS_IDLE;
-		if (!mobskill_use(md, tick, -1))
-			mob_unlocktarget(md,tick);
+		if (md->ud.target != tbl->id || md->ud.attacktimer == INVALID_TIMER) 
+		{ //Only use skill if no more attack delay left
+			md->state.skillstate = MSS_IDLE;
+			if (!mobskill_use(md, tick, -1))
+				mob_unlocktarget(md,tick);
+		}
 		return true;
 	}
 
 	if (!can_move)
 	{	//Stuck. Attempt an idle skill
-		md->state.skillstate = MSS_IDLE;
-		if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL))
-			mobskill_use(md, tick, -1);
+		if (md->ud.target != tbl->id || md->ud.attacktimer == INVALID_TIMER) 
+		{ //Only use skill if no more attack delay left
+			md->state.skillstate = MSS_IDLE;
+			if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL))
+				mobskill_use(md, tick, -1);
+		}
 		return true;
 	}
 
@@ -1674,6 +1678,10 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
 	)) //Current target tile is still within attack range.
 		return true;
 
+	//Only update target cell after having moved at least "mob_chase_refresh" cells
+	if(md->ud.walktimer != INVALID_TIMER && md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh)
+		return true;
+
 	//Follow up if possible.
 	if(!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) ||
 		!unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2))