So again, I’ve needed this for one of my recent games but I also believe it’d be helpful to other people with similar goals. This module allows you to set whether or not a user’s shift lock is enabled, one of the main reasons I made this was so I could have a mobile shift lock option.
Before I go onto usage and other stuff, I’d like to credit people who contributed to it’s creation.
To use the system, all you need to do is insert the model and reparent the ‘PlayerScriptsLoader’ that comes with it to ‘StarterPlayerScripts’ and change the configurations to your likings.
In the main script there’s a configuration named ‘ShiftlockAttributeName’ and whatever you set it to is what will enable / disable shift lock for the client.
You can enable shift lock when installed and the ‘ShiftlockAttributeName’ is set to ‘Shiftlock’ with something like:
If you’re too lazy to do all the installation steps you can run this code in the command bar to do that job for you.
-- Author: @Jumpathy
-- Usage: Installing EzShiftlock through the command bar
local start = tick()
local model = game:GetObjects("rbxassetid://8285701600")[1]
local init = model:WaitForChild("EzShiftlock")
local plugin = PluginManager():CreatePlugin()
init.Parent = game:GetService("ServerScriptService")
init:WaitForChild("PlayerScriptsLoader").Parent = game:GetService("StarterPlayer").StarterPlayerScripts
game:GetService("Selection"):Set({init})
plugin:OpenScript(init)
warn(("[Installed in %s]"):format(tick() - start))
Use-cases:
Mobile shift lock support
Extra shift lock keys
Needing to change shift lock in general
Some other weird reason
Polls
Would you use this?
Yes
No
0voters
How helpful would this be to you if you did use it?
1
2
3
4
5
6
7
8
9
10
0voters
Notes
Best of all? You never need to fork the Camera module because I’m just that cool (jk thank you EgoMoose for fixing that Roblox update) but yea! You don’t need to change any code and you can just get started easily!
I’m aware this post is a bit vague, but there’s not a whole lot else than what’s outlined to it. I hope this can be helpful to the people who are needing something like this.
If you have any problems with the system or need help don’t hesitate to PM me or leave a reply!
EDIT: Fetch MouseLockController from the CameraModule at the top of the PlayerScriptsLoader script
local cameraModule = require(playerModule:WaitForChild("CameraModule"))
local MouseLockController = require(playerModule.CameraModule:WaitForChild("MouseLockController"))
Then tack this onto the end of the script, and it should work on mobile
---------------
-- Add in detection for TouchEnabled, as this is
-- how the CameraModule decides not to instantiate
-- a mouselockcontroller.
if (userInput.TouchEnabled) then
cameraModule.activeMouseLockController = MouseLockController.new()
local toggleEvent = cameraModule.activeMouseLockController:GetBindableToggleEvent()
if toggleEvent then
toggleEvent:Connect(function()
cameraModule:OnMouseLockToggled()
end)
end
userInput:GetPropertyChangedSignal("MouseBehavior"):Connect(function()
-- in testing scenarios on studio, locking the mouse on mobile prevents user input.
-- if this has any impact on functionality in your game, remove it
userInput.MouseBehavior = Enum.MouseBehavior.Default
end)
end
I don’t know if this is just a me problem but I made it in my game that pressing V enables third person and automatically sets the attribute to True, and when pressed again it sets the player to first person and disables the attribute. However, when another player does this and I try to enable third person, third person is enabled but shift lock is not (until I disable first person, and then reenable it again).
Code in LocalScript under StarterGui:
local uis = game:GetService("UserInputService")
local player = game:GetService("Players").LocalPlayer
local playergui = script.Parent.Parent
local mobilebutton = playergui:WaitForChild("MobileStuff"):WaitForChild("Frame").ToggleView
local human = player.Character:WaitForChild("Humanoid")
local teams = game:GetService("Teams")
local firstperson = true
function togglecamera()
if player.CameraMode == Enum.CameraMode.LockFirstPerson then
firstperson = false
if player.Team == teams.Monsters then
player.CameraMaxZoomDistance = 15
player.CameraMinZoomDistance = 10
elseif player.Team == teams.Players then
player.CameraMaxZoomDistance = 5
player.CameraMinZoomDistance = 5
end
player.CameraMode = Enum.CameraMode.Classic
player:SetAttribute("Shiftlock",true)
else
firstperson = true
player.CameraMinZoomDistance = .5
player.CameraMaxZoomDistance = .5
player.CameraMode = Enum.CameraMode.LockFirstPerson
player:SetAttribute("Shiftlock",false)
end
end
function resetcamera()
if not firstperson then togglecamera() end
end
uis.InputBegan:Connect(function(input,gameProcessedEvent)
if not gameProcessedEvent and human.Health > 0 and player.Team ~= teams.Idle and playergui:WaitForChild("A_Title").Enabled == false then
if input.KeyCode == Enum.KeyCode.V then
togglecamera()
end
end
end)
mobilebutton.MouseButton1Down:Connect(function()
if human.Health > 0 then togglecamera() end
end)
player.CharacterAdded:Connect(function()
resetcamera()
end)
human.Died:Connect(function()
resetcamera()
end)
player.CharacterRemoving:Connect(function()
resetcamera()
end)
TL;DR for me, another playing enabling Shiftlock via the attribute system makes it so the next player does not go into Shiftlock when it is supposed to. Any idea for why this might be?
Haven’t been able to replicate this in my testing, but the whole system is subject to randomly not working at moments from what I’ve experienced and I haven’t remedied that, either cuz I can’t narrow down the fail cases. Hopefully eventually roblox will just expose a better mouse lock control method in the PlayerModule, I don’t see why it’s not more accessible.
If this approach cannot do what you’re trying to do, there is a workaround, albeit hacky and maybe not the most stable. It works for now and never seems to fail.
Use UserInputService’s MouseBehavior property in conjunction with an update function and hook it to one of the events that runs after the core camera script updates (like RenderStepped), and offset by your desired CFrame from the Camera’s CFrame.
example:
local CameraDisplacement = Spring.new(Vector3.new(), 16, 1)
function toggleMouseLock(bool)
if bool then
CameraDisplacement.Target = Vector3.new(-5,0,0)
else
CameraDisplacement.Target = Vector3.new(0,0,0)
end
end
function update()
local displacementPos = CameraDisplacement.Position
workspace.CurrentCamera.CFrame = workspace.CurrentCamera.CFrame
*CFrame.new(displacementPos.X,displacementPos.Y,displacementPos.Z)
end
game:GetService("RunService").RenderStepped:Connect(update)
you’d probably want to expose this in a module
EDIT: note that this will not impact the core camera’s PopperCam detection, so your offset is capable of clipping into walls. Pretty sure you can fix this by requiring and calling PopperCam AGAIN in your update function, which I will choose not to do lol