How to Force Enable Shift-Lock (Without changing the PlayerModule)

i changed the script to this and the mouse is broken, when I disable it, it wont release the mouse

local plr = game:GetService("Players").LocalPlayer
local mouse = plr:GetMouse()
local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local rotation = Instance.new("BodyGyro") 
local Root = plr.Character.HumanoidRootPart
rotation.P = 1000000 
rotation.Parent = hum.RootPart 
local conn 

function shiftLock(value,active) 
	if active then
		hum.CameraOffset = Vector3.new(value,0.5,0) 
		rotation.MaxTorque = Vector3.new(0, math.huge, 0) 
		conn = game:GetService("RunService").RenderStepped:Connect(function()
			rotation.CFrame = mouse.Origin
			game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
		end) 
	else
		hum.CameraOffset = Vector3.new(0,0,0) 
		rotation.MaxTorque = Vector3.new(0, 0, 0) 
		if conn then conn:Disconnect() end 
	end
end

game.ReplicatedStorage.Shiftlock.OnClientEvent:Connect(shiftLock)	

i fixed it myself the script is very helpfull ty

1 Like

I’ve an odd problem, where I’ve set the character to R6, but after I implemented this script, and tested it, it’s now an R15 character. What’s going on?

This script does not change any character parts.

Did you change the character from the Avatar editor? Or game settings?

If from avatar editor, try from the game settings.

Game Settings → Avatar → Avatar Type → R6

1 Like

Man, your code format…

But hey, no offense, I can fix that

Nice anyway!

local plr = nil
local mouse = nil
local char = nil
local hum = nil
local rotation = nil
local conn

local UIS = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local Tween1
local Tween2

local data = script.Parent:WaitForChild("Configuration")

local autoshooting = false
local cooldown = false

function shiftLock(shifttype)
	if conn then conn:Disconnect() end
	
	if shifttype ==  "Idle" then
		Tween2:Cancel()
		Tween1:Cancel()
		task.wait()
		Tween1:Play()
		rotation.MaxTorque = Vector3.new(0, 0, 0)
			
		conn = game:GetService("RunService").RenderStepped:Connect(function()
			game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
		end)
	elseif shifttype == "Shoot" then
		Tween1:Cancel()
		Tween2:Cancel()
		task.wait()
		Tween2:Play()
		rotation.MaxTorque = Vector3.new(0, math.huge, 0)
		
		conn = game:GetService("RunService").RenderStepped:Connect(function()
			rotation.CFrame = mouse.Origin
			game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
		end)
	else
		task.wait()
		Tween2:Cancel()
		Tween1:Cancel()
		task.wait()
		Tween1:Play()
		rotation.MaxTorque = Vector3.new(0, 0, 0)
		game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.Default
		
		if conn then conn:Disconnect() end
	end
end

script.Parent.Equipped:Connect(function()
	UIS.MouseIconEnabled = false
	char = script.Parent.Parent
	plr = game.Players:GetPlayerFromCharacter(char)
	hum = char.Humanoid
	mouse = plr:GetMouse()
	rotation = Instance.new("BodyGyro")
	rotation.P = 1000000
	rotation.Parent = hum.RootPart
	
	if Tween1 then
		Tween1:Cancel()
	end

	if Tween2 then
		Tween2:Cancel()
	end

	Tween1 = TweenService:Create(hum,TweenInfo.new(0.3),{CameraOffset = Vector3.new(0,0,0)})
	Tween2 = TweenService:Create(hum,TweenInfo.new(0.3),{CameraOffset = Vector3.new(5,0.5,0)})
	
	shiftLock("Idle")
end)

script.Parent.Unequipped:Connect(function()
	UIS.MouseIconEnabled = true
	task.wait()
	shiftLock()
	
	plr = nil
	mouse = nil
	char = nil
	hum = nil
	rotation:Destroy()
	rotation = nil
	
	if conn then conn:Disconnect() end
end)

local status = false

UIS.InputBegan:Connect(function(Input,System)
	if System or script.Parent.Parent:IsA("Backpack") then return end
	
	if Input.KeyCode == Enum.KeyCode.Q then
		if status then
			shiftLock("Idle")
			script.Parent.ShootEnable:FireServer(false)
		else
			shiftLock("Shoot")
			script.Parent.ShootEnable:FireServer(true)
		end
		
		status = not status
	elseif Input.UserInputType == Enum.UserInputType.MouseButton2 then
		shiftLock("Shoot")
		script.Parent.ShootEnable:FireServer(true)
		
	elseif Input.UserInputType == Enum.UserInputType.MouseButton1 then
		if data.Auto.Value and not cooldown then
			autoshooting = true
			
			repeat
				script.Parent.Shoot:FireServer(plr:GetMouse().Hit.Position)
				task.wait(data.Firerate.Value)
			until not autoshooting
			
			cooldown = true
			task.wait(data.Firerate.Value)
			cooldown = false
		else
			if not cooldown then
				script.Parent.Shoot:FireServer(plr:GetMouse().Hit.Position)
				cooldown = true
				task.wait(data.Firerate.Value)
				cooldown = false
			end
		end
	elseif Input.KeyCode == Enum.KeyCode.R then
		script.Parent.Reload:FireServer()
	end
end)

UIS.InputEnded:Connect(function(Input,System)
	if System or script.Parent.Parent:IsA("Backpack") then return end

	if Input.UserInputType == Enum.UserInputType.MouseButton2 then
		shiftLock("Idle")
		status = false
		script.Parent.ShootEnable:FireServer(false)
		
	elseif Input.UserInputType == Enum.UserInputType.MouseButton1 then
		autoshooting = false
	end
end)

My mouse got locked on the center sometimes, any reason?

1 Like

Yes, but you can disable it :slightly_smiling_face:

Like the original shiftlock, the mouse is locked in the center. So the mouse locking is on purpose, but you can easily disable it.


The shift lock icon :arrow_up:

If you want your character to face the mouse/camera without the centering, you can just remove all of these MouseBehavior lines.

1 Like

Hi stupid question but I can’t seem to figure it out,

How would I move the character by setting HumanoidRootPart CFrame directly?

I tried this but it makes the character completely glitch out:

rootPart.CFrame = CFrame.new(rootPart.CFrame.Position) * camera.CFrame.Rotation

I also tried taking out the X axis from the rotation but then it didn’t rotate at all

Thanks! I found this very helpful when making a horror game. Its very dark(as intended) but I needed the flashlight to stay in one spot so when people joined the game they could see. Very Helpful :+1:

Can confirm that the actual camera offset for shiftlock is 1.75, 0, 0 after looking through the scripts. Great system! But, now that bodygyro is deprecated, wouldn’t you need some replacements? I tried using align orientation but its jittery

Hey :slightly_smiling_face:.
As far as I know, BodyGyro is legacy, not deprecated. It still remains and is unlikely to be removed, though not further developed and not fully supported as well.

They are not going anywhere.
In this case, I find BodyGyro much simpler and straightforward to use.


Though theoretically, you're right about that the alternative should be used instead.

I might provide some further alternative methods to achieve this (Align orientation or CFraming). I planned to update this thread for a while now, but I’ve had no time.

1 Like

Hello, sorry for the late reply.

I’ll provide this alternative soon.

https://developer.roblox.com/en-us/api-reference/class/BodyGyro

Says here it’s indeed deprecated and is no longer legacy.

Hiya, you linked my post which was 3 years out of date - I updated it just now, but figure I echo things here: BodyMovers and their subclasses were deprecated in update 516 (March 1st, 2022). Like all deprecated stuff, they shouldn’t be used for new work, and as far as I know there’s no guarantee they’ll continue to work the way they do today, or at all.

The word legacy is a sort of softer classification of API members (and somewhat unofficial), as it doesn’t have a corresponding API dump tag. Stuff that you probably want to avoid due to age but isn’t yet depreciated is probably safe to consider legacy.

1 Like

Hello @batteryday , @SaturdayScandal and @Ozzypig .

Thank you for notifying me that BodyGyro has been deprecated.

I’ve come up with a solution based on CFrame.

I'll update the thread very soon, but for now, here's the alternative for you to use:
--Local script in StarterPlayerCharacter
--Variables:
local plr = game:GetService("Players").LocalPlayer
local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local root = hum.RootPart -- The HumanoidRootPart


--Toggle Function:
function shiftLock(active) --Toggle shift.lock function
	if active then
		hum.AutoRotate = false --Disable the automatic rotation since we set it.
		hum.CameraOffset = Vector3.new(1,0.5,0) -- I assume this is about the right camera offset.
		game:GetService("RunService"):BindToRenderStep("ShiftLock", Enum.RenderPriority.Character.Value, function()
			local _, y = workspace.CurrentCamera.CFrame.Rotation:ToEulerAnglesYXZ() --Get the angles of the camera
			root.CFrame = CFrame.new(root.Position) * CFrame.Angles(0,y,0) --Set the root part to the camera's rotation
			game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
		end) --Set the mouse to center every frame.
	else
		hum.CameraOffset = Vector3.new(0,0,0) --Move the camera back to normal.
		game:GetService("RunService"):UnbindFromRenderStep("ShiftLock") -- Allow mouse to move freely.
		hum.AutoRotate = true
	end
end
--Disable and Enable:
shiftLock(true) -- Toggle shift lock
print("Shift lock turned on!")

task.wait(15)
shiftLock(false) -- Toggle shift lock

Edit: The thread is now updated.

Hey, thanks for this script! However two things, the correct lock shift offset is Vector3.new(1.75,0,0) and you forget to set the MouseBehavior back to default. Other than that perfect! Thank you for the script

game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.Default
--Toggle Function:
function shiftLock(active) --Toggle shift.lock function
	if active then
		hum.AutoRotate = false --Disable the automatic rotation since we set it.
		hum.CameraOffset = Vector3.new(1.75,0,0) -- I assume this is about the right camera offset.
		game:GetService("RunService"):BindToRenderStep("ShiftLock", Enum.RenderPriority.Character.Value, function()
			local _, y = workspace.CurrentCamera.CFrame.Rotation:ToEulerAnglesYXZ() --Get the angles of the camera
			root.CFrame = CFrame.new(root.Position) * CFrame.Angles(0,y,0) --Set the root part to the camera's rotation
			game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
		end) --Set the mouse to center every frame.
	else
		hum.CameraOffset = Vector3.new(0,0,0) --Move the camera back to normal.
		game:GetService("RunService"):UnbindFromRenderStep("ShiftLock") -- Allow mouse to move freely.
		hum.AutoRotate = true
        game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.Default
	end
end
2 Likes

Hey, thank you for the accurate offset! I used an estimate since I did not know exactly what the real one was.

Actually, the MouseBehavior is constantly set to default, which is why I used RenderStepped :wink:.

Therefore when disconnecting the RenderStepped, the behavior will be set back, therefore there’s no need to do that manually.

Turns out you’re right. It used to be constantly set but now you have to set it back.

I updated it, thanks :slight_smile: !

No bother, I found the offset in the Roblox MouseLockController.

Interesting, I couldn’t get my mouse to unlock from centre without manually setting the MouseBehavior.

1 Like

This is really really really awesome!

Great tutorial, I accidentally solved a big problem in a game of mine.
One thing is, the character can (for some reason) only rotate half of the way around. Or at least for me.
If anyone else has this issue, using ToOrientation() seems to work fine.