1
0
forked from 0ad/0ad

Fix units 'waltzing' in place in formation.

Following 847f3a9995,
Units in formation can get very small movement offsets, that nonetheless
require large rotations, and thus at least 2 turns to accomplish.
However, following 847f3a9995, PossiblyAtDestination fires() only after
the first rotation, so the unit ends up 'waltzing' in place.
Before that diff, the unit never even moved since PossiblyAtDestination
fired straight away.

This is also noticeable since IDLE formation re-order their members
since 71a61d5f50.

The fix here is to ignore rotation time for very small offsets, which
lets units accomplish the movement in one turn and fixes the issue.

Reported by: wowgetoffyourcellphone
Reviewed By: Freagarach
Tested By: langbart
Differential Revision: https://code.wildfiregames.com/D3518
This was SVN commit r24831.
This commit is contained in:
wraitii 2021-02-04 16:58:19 +00:00
parent 3ea0e0c903
commit 5d96346ac5

View File

@ -1072,7 +1072,11 @@ bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath&
target = CFixedVector2D(shortPath.m_Waypoints.back().x, shortPath.m_Waypoints.back().z);
CFixedVector2D offset = target - pos;
if (turnRate > zero && !offset.IsZero())
// Idle formations reorder their members to move to their offset, but numerical imprecisions can lead
// to small offsets every time. Units would then rotate in-place, looking odd.
// If the offset is small enough (epsilon is about 0.000015, so that's 0.0015 which is still irrelevant),
// simply don't turn.
if (turnRate > zero && offset.CompareLength(fixed::Epsilon() * 100) > 0)
{
fixed maxRotation = turnRate.Multiply(timeLeft);
fixed angleDiff = angle - atan2_approx(offset.X, offset.Y);