ModernUO/Projects/UOContent
Kamron Batman cff9fbda29
fix(ai): creatures pathfind around concave obstacles instead of oscillating (#2461)
## Summary

Creatures (pets following, monsters chasing, NPCs approaching) would **oscillate — "pace back and forth really fast"** at concave obstacles (reported at the Britain Inn L-desk: a pet at `(1493,1614,20)` never reaching its master at `(1494,1605,21)`) instead of routing around them.

**Root cause** (the A* pathfinder itself was correct): all goal-seeking funnels through `MoveTo` and `WalkMobileRange` → `MoveTowardsOrAwayFrom`, which step greedily via `DoMove(dir, badStateOk:true)`. `DoMove` returns `true` even when the direct step was blocked and the creature merely **auto-turned and sidestepped** (`MoveResult.SuccessAutoTurn`), and the caller then set `Path = null`, discarding the `PathFollower`. So at a concave obstacle a non-progressing sidestep was mistaken for progress and the creature never committed to a route. (AOS pet-follow runs at `CurrentSpeed = 0.1`, hence the "really fast" shuffle.)

## What changed

- **New centralized `BaseAI.ApproachTarget(target, run, range)` primitive.** A greedy step is committed only when it **fully succeeds (`MoveResult.Success`) and actually gets closer**; otherwise the creature commits to a **persistent `PathFollower`** that routes around the obstacle and is never discarded by a greedy step. The open-terrain fast path (one greedy step, no pathfinding) is preserved. `MoveTo`, `MoveTowardsOrAwayFrom`, and `MoveToWithCollisionAvoidance` all delegate to it — public signatures unchanged, so no AI-class call site changes.
- **Best-distance give-up + idle.** A creature that cannot reach a **stationary** in-range goal stops shuffling and idles after `ApproachGiveUpTicks` (40) ticks without lowering its closest-ever distance; a **moving** goal (active chase) never gives up. It resumes the moment the goal moves.
- **Pathfinder fix (required):** `BitmapAStarAlgorithm.IsBlockedByDynamic` now skips the dynamic mobile-block check **at the goal cell only** (`MoveImpl.Goal`). Previously A* returned `null` whenever the target mobile stood on the goal cell, so creatures could never pathfind *toward* another mobile — only toward empty ground. The follower stops within `range` short of it. Static/item blocking and all non-goal mobile blocking are unchanged.

## Tests

New AI-loop integration tests in `ApproachTargetTests.cs` drive the real `BaseAI` primitives against live Britain Inn map statics: exact-repro pet follow, open-terrain (asserts zero pathfinding), `MoveTo` chase (static + walking-away target), route-around-a-dynamic-wall, and walled-off give-up-and-idle.

- Pathfinding + AI subset: **52/52** pass.
- Full `UOContent.Tests`: **301/301** pass. (Note: the test host lingers on shutdown — a pre-existing infra quirk unrelated to this change; all tests complete and pass.)
- Full solution build: clean (0 warnings / 0 errors).

## Notes

- Branched off `main`; independent of the in-flight step-cache work.
- Out of scope (future work): proactive "SmartAI" look-ahead pathfinding so clever creatures plan a route before walking into the obstacle, rather than reacting after they hit it.

## Test Plan

- [X] In-game: order a pet to `follow`/`come` across the Britain Inn L-desk; confirm it routes around and reaches you instead of pacing.
- [X] Aggro a monster and kite it around a building/treeline; confirm it chases around obstacles.
- [X] Confirm open-terrain following/chasing feels unchanged (no extra latency).
- [X] Confirm a creature with a genuinely unreachable target idles rather than shuffling forever.
2026-06-06 10:20:52 -07:00
..
Accounting feat: add young_player_system feature flag to disable Young player system (#2445) 2026-05-05 20:09:49 -07:00
Assistants chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Commands perf(messages): mechanical interpolation cleanups (#2436) 2026-05-03 18:26:49 -07:00
Compression feat: Implements new robust/pluggable backup/archive system. (#2388) 2026-03-22 19:51:20 -07:00
Configuration fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
Console feat: Adds console commands (#1714) 2024-03-30 09:40:43 -07:00
Context Menus fix: Moves ContextMenu out of core, streamlines code, fixes bugs (#1873) 2024-07-20 21:33:23 -07:00
Engines fix(ai): creatures pathfind around concave obstacles instead of oscillating (#2461) 2026-06-06 10:20:52 -07:00
Gumps perf: Migrate RewardGump to DynamicGump (#2432) 2026-05-03 10:22:52 -07:00
Holiday Stuff perf: Migrate Veteran Reward gumps to DynamicGump/StaticGump (#2415) 2026-04-25 20:09:27 -07:00
Items fix: HouseRaffleStone timer cleanup (#2456) 2026-05-23 10:39:58 -07:00
Migrations feat: Adds rope teleporter for New Haven Mines (#2439) 2026-05-03 17:23:31 -07:00
Misc perf(messages): mechanical interpolation cleanups (#2436) 2026-05-03 18:26:49 -07:00
Mobiles fix(ai): creatures pathfind around concave obstacles instead of oscillating (#2461) 2026-06-06 10:20:52 -07:00
Multis perf: Migrate vendor management gumps to DynamicGump/StaticGump (#2431) 2026-05-03 10:19:12 -07:00
Network feat: Adds robust speed hack detection and movement throttling (#2266) 2026-03-07 11:44:37 -08:00
Regions fix: Fixes criminals having guards called on them (#2348) 2026-03-13 17:35:47 -07:00
Skills perf: Migrate NPC and Skill UI gumps to DynamicGump/StaticGump (#2414) 2026-04-25 19:51:42 -07:00
Special Systems feat: Add zero-alloc interpolation handler to ValueStringBuilder, replace all StringBuilder usage (#2387) 2026-03-22 14:23:44 -07:00
Spells feat: Adjusts fame and karma system with era gates for OSI accuracy (#2389) 2026-04-25 11:19:57 -07:00
Systems/JailSystem fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
Targets chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Text fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
Utilities chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
World Saves perf(messages): mechanical interpolation cleanups (#2436) 2026-05-03 18:26:49 -07:00
Module.cs fix: Fixes sending packets and sidesteps a major issue with stackalloc and PGO in .NET 8 (#1607) 2023-11-21 12:18:20 -08:00
UOContent.csproj feat(pathfinding): JSONL recorder + public bake helpers (#2449) 2026-05-06 13:06:28 -07:00