The title is pretty self explanatory. I’m creating a system that allows a player to choose between different attacks depending on which way the cursor is moving. Not unlike blood & iron or other games in the same category.
This is an abstract overview of how I’ve tried to implement such a system so far:
When new mouse movement is detected*
-Get mouse position (relative to the frame)
-wait a few frames
-Compare original mouse position to current
-Perform some arithmetic
-Depending on previous arithmetic it can be determined which direction the mouse was moving in.
This system works fine with the mouse in free view, but it breaks in shiftlock (for obvious reasons being that the mouse position is locked to the center of the screen)
I’ve thought of using CFrames and the Mouse.hit property, this would work with the up/down since that would present in the same results no matter the direction the player is facing in, but how would I get the XPosition? I’ve currently thinking of trying to get the direction of the HumanoidRootPart’s look vector and comparing that to the look vector a few frames previously but at this moment I’m not sure how to achieve that.
Sorry that I am responding to this a bit late (3 days), but the way I have figured out to the problem of not being able to detect mouse movement in shift lock. My solution is to check if the mouse is locked, and if it is locked, then it will capture camera rotation, wait a frame, then capture the camera rotation again and compare the current rotation to the previously captured rotation, then work from there. This will also work when the player is holding RMB in 3rd person or in first person. here’s the code.
local player = game:GetService("Players").LocalPlayer
local UIS = game:GetService("UserInputService")
local runService = game:GetService("RunService")
local camera = workspace.CurrentCamera
local mouse = player:GetMouse()
local function mouseIconFunction()
if UIS.MouseBehavior == Enum.MouseBehavior.LockCurrentPosition or UIS.MouseBehavior == Enum.MouseBehavior.LockCenter then
local startingCamY,startingCamX = camera.CFrame:ToOrientation()
wait(runService.Heartbeat)
--Feel free to adjust time between first capturing cam rotation and next time checking cam rotation.
local currentCamY,currentCamX = camera.CFrame:ToOrientation()
local xDifference = currentCamX - startingCamX
local yDifference = currentCamY - startingCamY
if math.abs(xDifference) >= math.abs(yDifference) then
if math.abs(xDifference) < 0.023 then
--In mouse deadzone
return
end
if xDifference < 0 then
print("looking right, mouse locked")
--Add your code
else
print("looking left, mouse locked")
--Add your code
end
else
if math.abs(yDifference) < 0.023 then
--In mouse deadzone
return
end
if yDifference > 0 then
print("looking up, mouse locked")
--Add your code
else
print("looking down, mouse locked")
--Add your code
end
end
else
--Add your current code to check the direction the mouse is heading in here, it will be only ran when the mouse is unlocked/player is in 3rd person and not holding RMB.
end
end
local functionCallDebounce = false
UIS.InputChanged:Connect(function(input,gameProcessed)
if functionCallDebounce or gameProcessed then
return
end
functionCallDebounce = true
if input.UserInputType == Enum.UserInputType.MouseMovement then
mouseIconFunction()
end
for i = 1,3 do
wait(runService.Heartbeat)
end
functionCallDebounce = false
end)
If you need for me to explain anything else or something isn’t working, then feel free to ask me. I hope this has helped you.
Dude this is awesome, thanks so much. I wish you hadn’t written out the code so I’d be forced to figure it out myself but nevertheless I changed a lot of things. xD
I did eventually get this mechanic to work by using cframes and the look vector of the torso and some acos math to get the angle from the CFrame’s look vectors.
With nothing more being said your system is far more elegant.
NOTES/CHANGES TO YOUR CODE
-Using your code unchanged it will print both Left/Right and Up/Down, this is undesired because I need to pick out of the 4 directions. Nothing a lil math.abs comparison between the two difference can’t fix.
-Another undesired behavior of your code is at the 180/-180 inflection point. This was fixed with a little bit of math trickery to determine if an inflection point occurred and then determine what the direction is by comparing which is negative.
local tool = script.Parent
local cam = game.Workspace.CurrentCamera
local P = game:GetService("Players")
local p = P.LocalPlayer
local mouse = p:GetMouse()
local UIS = game:GetService("UserInputService")
local RS = game:GetService("RunService")
local startCamY, startCamX = cam.CFrame:ToOrientation()
local startMouseY, startMouseX = mouse.y, mouse.x
local MOUSEDEADZONE = 0.023
local inputChangeDebounce = false
local function mouseDirection()
wait(RS.Heartbeat)
wait(RS.Heartbeat)
if UIS.MouseBehavior == Enum.MouseBehavior.LockCenter then --detects if shiftlock enabled
local curCamY, curCamX = cam.CFrame:ToOrientation()
local XDiff = curCamX - startCamX
local YDiff = curCamY - startCamY
if math.abs(curCamX + -1 * startCamX) > math.abs(curCamX) and math.abs(curCamX) > math.rad(170) then --detects rear inflection point
if curCamX > 0 and startCamX < 0 then
print("Right Locked")
else
print("Left Locked")
end
else
if math.abs(YDiff) > math.abs(XDiff) then --runs up/down detection depending on which difference is greater
if math.abs(YDiff) < MOUSEDEADZONE then
if YDiff < 0 then
print("Up Locked")
else
print("Down Locked")
end
end
else
if math.abs(XDiff) > MOUSEDEADZONE then
if XDiff < 0 then
print("Right Locked")
else
print("Left Locked")
end
end
end
end
else -- if shift locked not enabled check mouse position
local curMouseY, curMouseX = mouse.y, mouse.x
local xDiff = curMouseX - startMouseX
local yDiff = curMouseY - startMouseY
if math.abs(yDiff) > math.abs(xDiff) then
if yDiff < 0 then
print("Up MouseNotLocked")
else
print("Down MouseNotLocked")
end
else
if xDiff > 0 then
print("Right MouseNotLocked")
else
print("Left MouseNotLocked")
end
end
end
startCamY, startCamX = cam.CFrame:ToOrientation()
startMouseY, startMouseX = mouse.y, mouse.x
end
UIS.InputChanged:Connect(function(input,gameProcessed)
if inputChangeDebounce == false then
inputChangeDebounce = true
mouseDirection()
inputChangeDebounce = false
end
end)
Thanks again for taking the time to write out the code! I’ll mark yours as the solution, since it is.
One last question though; What is the point of the purpose of gameProcessed? What does it represent?
Not really sure, now thinking back it is redundant in this case so you can just remove it, but gameProcessed means if the player is in a built in Roblox GUI, like the escape key
menu screen, but since this script isn’t dealing with registering key presses then it doesn’t really serve a purpose as the player mouse would already be unlocked if they’re in the menu screen. Once again, I’m happy that you found this useful and that I was able to help you!