ModernUO/Projects/UOContent/Mobiles
Kamron Batman 346228fa69
fix(ai): pet order/home refactor — stop & post-combat behavior (#2459)
## Summary

Fixes two related pet-behavior bugs and the underlying design flaw behind both:

1. **Post-combat erratic** — after a pet killed its `all kill` target it milled around erratically at the kill site (or failed to return to the master) until the player issued `all follow`/`all stop`.
2. **`all stop` returns home** — a pet with a non-zero `Home` walked back toward that location on `all stop` (on ML; on non-ML the old `DoOrderStop` was a no-op, so the sighting there came from a residual `Stay`).

### Root cause

`ControlOrder` and the wild-creature `Home` field were overloaded to express several distinct ideas, mutated/read inconsistently across order transitions:

- `Home` doubled as the controlled-pet "stay anchor" (`HandleStayOrder` set `Home = Location`) but nothing cleared it when the pet left the staying state; `HandleStopOrder` was the only handler that never touched it.
- `DoOrderStop` had dropped RunUO's `Home = Location` re-anchor, so on ML it walked to a stale anchor.
- The post-combat fallback was a fragile `_lastPetOrder` hack in `DoOrderNone` that re-anchored a resumed `Stay` at the corpse.
- Controlled idle-wander bypassed the `CheckIdle()` rest gate that every non-controlled creature uses, so idling pets jittered every AI tick.

## Approach

Separate three concepts that were tangled together:

- **`ControlOrder`** — the active order (may be transient: Come/Attack/Drop).
- **Persistent command** (`PersistentOrder` ∈ `{None, Stay, Follow, Guard}`) — the standing directive a pet falls back to when a transient order completes. Runtime-only (not serialized; reset to `None` on load) and **derived from master proximity on login** (near → Follow, far → Stay).
- **Anchor** (`Home`) — a pure function of the persistent command, set only when that command changes (never on transient transitions or fallback-resume), so it can't go stale.

### Behavior

- **Stop** is resolved immediately from what the pet was doing: Attack/Come → resume the persistent command; Follow/Guard → cancel to idle where it stands; Stay → stay put.
- **Stay** holds its post (returns only if displaced, e.g. after a fight) — no shuffle.
- **Idle** (`None`) is a gentle wander routed through `CheckMove/CanMoveNow/CheckIdle`, so idling pets take the same 15–25s rest periods as other creatures, on both ML and non-ML.
- **Post-combat** the pet resumes its persistent command (a staying pet returns to its original post, not the corpse).
- **Release** without a spawner anchors where the pet stands instead of pathing to a stale anchor.

This restores the RunUO-intended behavior (verified against the RunUO reference) while fixing the ModernUO regressions.

## Tests

New `PetOrderTests` (13 deterministic xUnit tests) cover: anchor lifecycle, the full Stop truth table, report 1 (post-combat return to post), report 2 (no stale-anchor walk-home), frozen-Stay/gated-idle wiring, release fix, derive-on-login, and a non-ML spot-check. The subjective wander *feel* is covered by a manual-QA checklist in the implementation plan.

## Notes

- Engine project (`Projects/Server`) untouched; the one `BaseCreature.cs` change is the `ControlOrder` setter passing the previous order to `OnCurrentOrderChanged`.
- `DoOrderCome` keeps auto-converting to `Stay` on arrival, which under the new model cleanly means "come and hold near me."
- Commits in this PR are temporarily **unsigned** (the signing agent's passphrase cache expired mid-session); happy to re-sign / amend on request.
2026-06-07 01:22:43 -07:00
..
Abilities fix: Adds guard for monster ability recursion (#2363) 2026-03-12 19:26:49 -07:00
AI fix(ai): pet order/home refactor — stop & post-combat behavior (#2459) 2026-06-07 01:22:43 -07:00
Animals chore: Fixes variable types for possible performance issues (#2172) 2025-05-01 21:54:41 -07:00
Familiars fix: Fixes container enumeration not recycling pooled arrays (#2341) 2026-02-17 09:54:32 -08:00
Guards feat: Adjusts fame and karma system with era gates for OSI accuracy (#2389) 2026-04-25 11:19:57 -07:00
Healers feat: Adds Mobile.Murderer virtual property, consolidates kill-threshold checks (#2355) 2026-03-06 08:36:41 -08:00
Hireables chore: Use var everywhere (#2294) 2025-12-27 16:47:28 -08:00
Monsters perf(messages): restructure format-string call sites (#2437) 2026-05-03 18:29:11 -07:00
Special feat: Adds Mobile.Murderer virtual property, consolidates kill-threshold checks (#2355) 2026-03-06 08:36:41 -08:00
Townfolk perf: Migrate NPC and Skill UI gumps to DynamicGump/StaticGump (#2414) 2026-04-25 19:51:42 -07:00
Vendors perf: Migrate vendor management gumps to DynamicGump/StaticGump (#2431) 2026-05-03 10:19:12 -07:00
BaseCreature.cs fix(ai): pet order/home refactor — stop & post-combat behavior (#2459) 2026-06-07 01:22:43 -07:00
NPCSpeeds.cs feat: Overhauls AI (Speech/Movement) (#2232) 2025-07-18 22:39:57 -07:00
PlayerMobile.cs feat: add young_player_system feature flag to disable Young player system (#2445) 2026-05-05 20:09:49 -07:00
VirtualMountItem.cs fix: Fixes mount stamina, adds Pub46+ Ethereal stamina (#1716) 2024-04-05 21:05:16 -07:00