Howdy,

Recently I’ve been interested in refactoring my game from static attack animation cycles to a dynamic cursor influenced system. When you move your cursor, it takes your mouse delta X & Y and adds it to a Vector2 until it reaches a specific magnitude value. In practice, easy to replicate angles such as left and right (-90, 90 respectively) are incredibly easy to replicate and will rarely “jitter,” while other angles such as the cleave in the diagram below are extremely hard to hit. The current system I have works generally, but sometimes the angle solver doesn’t get a precise enough angle, and will snap to an incorrect position.

My current code takes the dot product of the total delta, checks if it’s negative or positive, converts it to an angle and then tweens the cursor. Is there a more efficient, precise way to calculate this sort of angle? Any ideas or examples would be appreciated

```
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
-- this stuff will be in item modules, accessible to client
local attacks = {
[90] = "MiddleSweepRight";
[-90] = "MiddleSweepLeft";
[180] = "Cleave";
[45] = "45Test"
}
local attackAngles = {
90,-90,180,45
}
-- local player stuff
UserInputService.MouseIconEnabled = false
UserInputService.MouseDeltaSensitivity = .25
local previousPosition = Vector2.new(0, 0)
local angleTween = nil
local function roundNearestTable(inputTable, inputNumber:number)
table.sort(inputTable, function(Left, Right) return math.abs(inputNumber - Left) < math.abs(inputNumber - Right) end)
return inputTable[1]
end
local function averageOfNumbers(inputTable)
local total = 0
for _, value in pairs(inputTable) do total += value end return total/#inputTable
end
local function averageOfVectors(inputTable)
local total = Vector2.new(0,0)
for _, value in pairs(inputTable) do total += value end return total/#inputTable
end
local function totalOfVectors(inputTable)
local total = Vector2.new(0,0)
for _, value in pairs(inputTable) do total += value end return total
end
local function round(num, mult)
return math.floor(num / mult + 0.5) * mult
end
local MINIMUM_DISTANCE = 1
local MAXIMUM_DISTANCE = 10
local ROUND_ANGLE_DEGREE = 45
local MINIMUM_TIME_CHANGE = .25
local storeDelta = Vector2.new(0,0)
local lastChangedTime = 0
local lastAngle = 0
UserInputService.InputChanged:Connect(function(input:InputObject)
if input.UserInputType == Enum.UserInputType.MouseMovement then
local absSize = script.Parent.AbsoluteSize
local xAxisRatio = absSize.Y/absSize.X
local yAxisRatio = absSize.X/absSize.Y
-- Get delta change position
local changePosition = Vector2.new(input.Delta.X, input.Delta.Y)
storeDelta += changePosition
if storeDelta.Magnitude >= MAXIMUM_DISTANCE then
-- Calculate dot product and angle
local verticalDot = storeDelta.Unit:Dot(Vector2.new(0,-1))
local mouseAngle = round(math.deg(math.acos(verticalDot)),ROUND_ANGLE_DEGREE)
if storeDelta.X < 0 then mouseAngle *= -1 end
storeDelta = Vector2.new(0,0)
local foundIndex = roundNearestTable(attackAngles, mouseAngle)
if angleTween and angleTween.PlaybackState == Enum.PlaybackState.Playing then
angleTween:Pause()
end
if attacks[foundIndex] then
local angleTween = TweenService:Create(script.Parent.ImageLabel,TweenInfo.new(0.1,Enum.EasingStyle.Sine,Enum.EasingDirection.Out),{Rotation = foundIndex})
angleTween:Play()
end
end
end
end)
```

Thanks in advance.