View Issue Details

IDProjectCategoryView StatusLast Update
0006701The Dark ModAIpublic19.04.2026 12:54
ReporterArcturus Assigned Tostgatilov  
PrioritynormalSeveritymajorReproducibilityalways
Status resolvedResolutionfixed 
Product VersionTDM 2.14 
Target VersionTDM 2.15Fixed in VersionTDM 2.15 
Summary0006701: Broken AI with vsync off, uncap FPS on and high FPS
DescriptionCharacter animations get restarted (walking, running) when AI makes a turn. It looks bad and causes NPCs to stop a lot, too:
https://youtu.be/bq8uZ2vFDVk?si=wOmq_xidHwP0YXy8

The bug is more than cosmetic. It affects pathfinding. I noticed in test/horse.map that a horse can't find path nodes with those settings. Turning v-sync on, or lowering FPS fixes it:
https://youtu.be/_UItEYdgU5A?si=AOfh4_6l5ZfR6JPA
Steps To ReproduceTurn vertical sync off, uncap FPS on and set high max FPS values (around 100 and above).
Additional InformationOriginally reported here:
* https://forums.thedarkmod.com/index.php?/topic/23142-npcs-swaying-from-side-to-side-while-turning-procedural-animation/#findComment-507688
TagsAI, animation, framerate, graphics, vsync

Activities

stgatilov

stgatilov

18.04.2026 20:18

administrator   ~0017262

r11281. Fixed FPS-dependent movement estimates in MovementSubsystem::CheckBlocked.

Origin and frame index were recorded in 32-entry ring buffer, so that we could compute velocity using them.
I have no idea why there are 32 entries, since the code only every references the last 2 frames =) but OK.

The velocity is computed as (Orig[i+1] - Orig[i]) / (Frame[i+1] - Frame[i]), and it basically "movement per frame".
It is then compared with hardcoded constants like 0.1 and 0.3 to check if AI movement has stalled due to some kind of block.
If this is true, then AI starts some kind of evasion manoeuvre.
The problem is that the velocity is FPS-dependent, and on high FPS is falls unexpectedly low.
As the result, slowly moving AI becomes blocked constantly, and just circles around trying to evade nothing.

Instead of tracking frame numbers, now we track gameplay time.
We compute velocity as (Orig[i+1] - Orig[i]) / (Time[i+1] - Time[i]) * 16, which is basically "movement per 16 ms of time".
This should be the same velocity that is there in 60 FPS move / capped FPS, so the thresholds which used to work back then should work fine now.

Also I refactored the velocity computation.
There are two methods: velocity by last two moment in history, and velocity by curent state and last moment in history.
I unified these two methods and replaced the code in CheckBlocked with a call to GetPrevTraveled.
The horses move find for me now, even with 300 and 1000 FPS.
Normal missions seems to work fine too.

Issue History

Date Modified Username Field Change
14.04.2026 08:47 Arcturus New Issue
14.04.2026 08:47 Arcturus Tag Attached: AI
14.04.2026 08:47 Arcturus Tag Attached: animation
14.04.2026 08:47 Arcturus Tag Attached: framerate
14.04.2026 08:47 Arcturus Tag Attached: graphics
14.04.2026 08:47 Arcturus Tag Attached: vsync
18.04.2026 20:18 stgatilov Note Added: 0017262
18.04.2026 20:18 stgatilov Assigned To => stgatilov
18.04.2026 20:18 stgatilov Status new => resolved
18.04.2026 20:18 stgatilov Resolution open => fixed
18.04.2026 20:18 stgatilov Fixed in Version => TDM 2.15
18.04.2026 20:19 stgatilov Target Version => TDM 2.15
19.04.2026 12:54 stgatilov Additional Information Updated