diff --git a/changelog/snippets/fix.6630.md b/changelog/snippets/fix.6630.md new file mode 100644 index 0000000000..00384cf6c6 --- /dev/null +++ b/changelog/snippets/fix.6630.md @@ -0,0 +1 @@ +- (#6630) Fix ACUs spawned on the right side of the map not facing towards the middle of the map. diff --git a/lua/sim/Unit.lua b/lua/sim/Unit.lua index 94503d4e40..19d0e04f0a 100644 --- a/lua/sim/Unit.lua +++ b/lua/sim/Unit.lua @@ -2262,8 +2262,8 @@ Unit = ClassUnit(moho.unit_methods, IntelComponent, VeterancyComponent, DebugUni ---@param self Unit ---@param tpos Vector RotateTowards = function(self, tpos) - local pos = self:GetPosition() - local dx, dz = tpos[1] - pos[1], tpos[3] - pos[3] + local pX, _, pZ = self:GetPositionXYZ() + local dx, dz = tpos[1] - pX, tpos[3] - pZ self:SetOrientation(utilities.QuatFromXZDirection(dx, dz), true) end, diff --git a/lua/utilities.lua b/lua/utilities.lua index 0b33e22d8e..539fffe778 100644 --- a/lua/utilities.lua +++ b/lua/utilities.lua @@ -487,13 +487,32 @@ end ---@param dz number ---@return Quaternion function QuatFromXZDirection(dx, dz) - -- ang = atan2(dx, dz) -- `dz` is adjacent - -- {0, sin(ang/2), 0, cos(ang/2)} + -- division by zero case + if dx == 0 and dz == 0 then + return UnsafeQuaternion(0, 0, 0, 1) + end + + -- q = (0, sin(ang/2), 0, cos(ang/2)) -- definition of our y-axis rotation quaternion we want to get for angle `ang` + + -- sin(ang/2) = +/-sqrt((1-cos(ang))/2) -- half angle formula for sin. +/- is sign of sin(ang/2) + -- = +/-sqrt( 0.5 - cos(ang)/2 ) + -- = +/-sqrt( 0.5 - a/2h ) -- cos(ang) = adjacent/hypotenuse + -- similar is repeated for cos(ang/2) + local hypot = MathSqrt(dx*dx + dz*dz) - -- use the half-angle formulas local halfCosA = dz / (2 * hypot) local sinHalfA = MathSqrt(0.5 - halfCosA) local cosHalfA = MathSqrt(0.5 + halfCosA) + + -- Resolve the +/- part of our result: + -- sign of sin(ang/2) is + for ang in (0, 2pi) + -- sign of cos(ang/2) is + for ang in (0, pi) and - for ang in (pi, 2pi) + -- ang in (pi, 2pi) is when dx is negative, so negate cosHalfA in that case + + if dx < 0 then + return UnsafeQuaternion(0, sinHalfA, 0, -cosHalfA) + end + return UnsafeQuaternion(0, sinHalfA, 0, cosHalfA) end