Improve pet AI movement to match OSI behavior#2320
Improve pet AI movement to match OSI behavior#2320lukus882 wants to merge 2 commits intomodernuo:mainfrom
Conversation
Refines pet movement logic to closely match OSI (official server) behavior: pets now stand still when ordered to Stay or Stop, use tighter follow/come ranges, and only run when far from their master. Movement delays and timer intervals are now synchronized with client expectations for smoother animation, and pets lose track of their master or target at more accurate distances. These changes address movement jitter, improve animation consistency, and ensure pets behave as expected in various command states.
There was a problem hiding this comment.
Pull request overview
This PR refines pet AI movement behavior to closely match official OSI server behavior. The changes focus on making pets more responsive and predictable by improving how they follow, guard, and respond to Stay/Stop commands.
Changes:
- Pets now stand completely still when ordered to Stay or Stop (instead of wandering)
- Movement and follow ranges are tightened from 1-2 tiles to 0-1 tiles for more precise positioning
- Pets run when more than 2 tiles from master, ensuring they catch up quickly
- Movement delays and AI timer intervals are synchronized with client movement constants for smoother animations
- Pets lose track of targets at more accurate distances (RangePerception for Come, 5x RangePerception for Follow)
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| PetOrders.cs | Updates pet command handlers (Come, Follow, Guard, Stay, Stop) to use tighter ranges, remove wandering behavior for Stay/Stop, and adjust distance thresholds for losing track of master/target |
| AITimer.cs | Synchronizes timer intervals with Movement.Movement constants and adjusts intervals based on pet state (idle vs moving) for more responsive AI updates |
| AIMovement.cs | Centralizes running decision logic, adds tolerance for timer drift to prevent jitter, and synchronizes movement delays with client expectations for smooth animation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (Mobile is BaseCreature hurtCreature && hurtCreature.Hits < hurtCreature.HitsMax * 0.3 && | ||
| (hurtCreature.ReduceSpeedWithDamage || hurtCreature.IsSubdued)) | ||
| { | ||
| var hitsPercent = (double)hurtCreature.Hits / hurtCreature.HitsMax; | ||
| if (hitsPercent < 0.1) moveDelayMs += 150; | ||
| else if (hitsPercent < 0.2) moveDelayMs += 100; | ||
| else if (hitsPercent < 0.3) moveDelayMs += 50; | ||
| } |
There was a problem hiding this comment.
Missing check for HitsMax > 0 before division. The existing BadlyHurtMoveDelay function (line 31) includes a check for statMax > 0 before dividing. Without this check, if hurtCreature.HitsMax is 0, line 148 will throw a DivideByZeroException. Add a check for hurtCreature.HitsMax > 0 to the condition at line 145.
| // Run if far away (OSI behavior) | ||
| var shouldRun = currentDistance > 5; |
There was a problem hiding this comment.
The shouldRun calculation at line 75 uses a threshold of 5, but this is effectively overridden by DoMoveImpl (AIMovement.cs lines 98-101) which uses a threshold of 2. The pet will run when more than 2 tiles away from master, not 5. Consider either removing this line and letting DoMoveImpl handle the running decision, or documenting that this threshold is indicative and the actual threshold is enforced in DoMoveImpl for consistency across all movement.
| // Run if far away (OSI behavior) | |
| var shouldRun = currentDistance > 5; | |
| // Run if far away (OSI behavior; DoMoveImpl enforces running from > 2 tiles) | |
| var shouldRun = currentDistance > 2; |
| int moveDelayMs; | ||
|
|
||
| if (Mobile.Mounted) | ||
| { | ||
| moveDelayMs = shouldRun ? Movement.Movement.RunMountDelay : Movement.Movement.WalkMountDelay; | ||
| } | ||
| else | ||
| { | ||
| moveDelayMs = shouldRun ? Movement.Movement.RunFootDelay : Movement.Movement.WalkFootDelay; | ||
| } | ||
|
|
There was a problem hiding this comment.
Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better.
| int moveDelayMs; | |
| if (Mobile.Mounted) | |
| { | |
| moveDelayMs = shouldRun ? Movement.Movement.RunMountDelay : Movement.Movement.WalkMountDelay; | |
| } | |
| else | |
| { | |
| moveDelayMs = shouldRun ? Movement.Movement.RunFootDelay : Movement.Movement.WalkFootDelay; | |
| } | |
| int moveDelayMs = Mobile.Mounted | |
| ? (shouldRun ? Movement.Movement.RunMountDelay : Movement.Movement.WalkMountDelay) | |
| : (shouldRun ? Movement.Movement.RunFootDelay : Movement.Movement.WalkFootDelay); | |
This reverts commit 57aae38.
Refines pet movement logic to closely match OSI (official server) behavior: pets now stand still when ordered to Stay or Stop, use tighter follow/come ranges, and only run when far from their master. Movement delays and timer intervals are now synchronized with client expectations for smoother animation, and pets lose track of their master or target at more accurate distances. These changes address movement jitter, improve animation consistency, and ensure pets behave as expected in various command states.