Custom Shift Lock Module - [New]

:wave: Hey! I have noticed that many programmers have been wishing for a way to apply shift lock easily.
So, I have created a simple Custom Shift Lock Module. The module’s API is straightforward and simple, here is an example of how you would use it:

local shiftLock = (require(script.Parent:WaitForChild("ShiftLock")))
local userInputService = (game:GetService("UserInputService"));

function input_Began(input, gpe)
	if (gpe) then return end;
	if (input.KeyCode == Enum.KeyCode.LeftShift) then
		shiftLock:Lock(not shiftLock:IsLocked())
	end;
end;

userInputService.InputBegan:Connect(input_Began)
-- Roblox's shift lock behavior, you press Left Shift, and it locks / unlocks dependent on the current state.

:gear: There are also custom settings which you can apply at the beginning of the module:

local shiftLock = {
	-- Settings (i.e Customizations):
	Settings = {
		CameraOffsetX = (2);
		CameraOffsetY = (1.75);
		MouseIconOnToggle = ("");
		CameraOffsetLerpSpeed = (3);
		CharacterFacingLerpSpeed = (3);
	}
}

:page_facing_up: Current API document:

--[[
    ShiftLock:Lock(boolean) --> Locks/Unlocks the shift lock, returns: {nil}
    ShiftLock:IsLocked() --> Returns {boolean}
--]]

:fist: Grab the module here, you don’t have to credit me:

:stop_sign: IMPORTANT NOTE: Place the module in StarterGui, to avoid any bugs.

Make sure to recommend for new settings i.e new APIs, any idea is good!
:stop_sign: Note: I apologize if any issues occur with the module. I have not updated it in a long time, and it is not currently something I am working on.

57 Likes

:stop_sign: Found out a major bug I didn’t notice while testing, I am working to fix it.

:green_circle: After some work that has been done, the bug has been fixed, and model is now copy-open again.

11 Likes

This is a crazy good module I love this! Thank you! One suggestion, Allow the player to offset the camera for example in settings maybe add a setting call xoffset and another for yoffset. Just a little thing that will help other people get a better camera.

3 Likes

Thanks for the suggestion, and I apologize for the very-late response.
I will consider adding the feature that you suggested, as I do see it being useful :+1: :pray:
Edit: I have just tested and added this feature, thanks for your suggestion!

2 Likes

kinda looks buggy when you move your camera fast https://gyazo.com/a639071dd895abb35c03e09542efa026

1 Like

I don’t really think that there is a possible solution for this issue, I will try looking into it.
And again, I apologize for the delay of my response.

1 Like

The module seems to break when :LoadCharacter() occurs. You can replicate this by doing :LoadCharacter() on said Player when this module is in effect.

2 Likes

I wasn’t really active at the time that this comment was written, but now I’m active, I managed to fix that issue. If bugs will be reported now, I will most likely solve them the time they are reported. Really big apologies for this inactivity.

umm your module still broken because when the player is respawned because the local character = characteradded:wait() took so long

Edit: here’s my fixed version of the code:

-- Fixed by zBrick20 (@thebrickplanetboy)
local function WaitForChildOfClass(Parent, ClassName)
	while not Parent:FindFirstChildOfClass(ClassName) do 
		Parent.ChildAdded:Wait() 
	end
	return Parent:FindFirstChildOfClass(ClassName)
end

local Players = game:GetService("Players")
local Player = Players.LocalPlayer

if not Player then
	Players:GetPropertyChangedSignal("LocalPlayer"):Wait()
	Player = Players.LocalPlayer
end

local Mouse = Player:GetMouse()
local Camera = workspace.CurrentCamera

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

local Character = Player.Character or Player.CharacterAdded:Wait()
local ShiftLockController = {}
ShiftLockController.__index = ShiftLockController

function ShiftLockController.New(Settings)
	local self = {
		IsShiftLockToggled = false,
		Humanoid = WaitForChildOfClass(Character, "Humanoid"),
		RootPart = Character:WaitForChild("HumanoidRootPart", math.huge)
	}
	
	local function IsInFirstPerson()
		if (Camera.Focus.Position - Camera.CFrame.Position).Magnitude < 1 then
			return true
		else
			return false
		end
	end
	
	local function CharacterAdded(NewCharacter)
		self.Humanoid = WaitForChildOfClass(NewCharacter, "Humanoid")
		self.RootPart = NewCharacter:WaitForChild("HumanoidRootPart", math.huge)
	end
	
	local function InputChanged(Input, GameProcessed)
		if GameProcessed or not self.IsShiftLockToggled then return end
		if (self.Humanoid.Sit or self.Humanoid:GetState() == Enum.HumanoidStateType.Seated) and self.Humanoid:GetState() == Enum.HumanoidStateType.Swimming and self.Humanoid:GetState() == Enum.HumanoidStateType.Physics and self.Humanoid:GetState() == Enum.HumanoidStateType.Ragdoll and self.Humanoid:GetState() == Enum.HumanoidStateType.Dead then return end
		if Input.UserInputType == Enum.UserInputType.MouseMovement or Input.UserInputType == Enum.UserInputType.Touch or Input.UserInputType == Enum.UserInputType.Focus then
			Camera.CFrame = Camera.CFrame * CFrame.Angles((Input.Delta.X / Camera.ViewportSize.X) * UserInputService.MouseDeltaSensitivity, 0, 0) * CFrame.Angles(0, (Input.Delta.Y / Camera.ViewportSize.Y) * UserInputService.MouseDeltaSensitivity, 0)
		end
	end
	
	local function RenderStepped(DeltaTime)
		UserInputService.MouseBehavior = self.IsShiftLockToggled and Enum.MouseBehavior.LockCenter or UserInputService.MouseBehavior
		Mouse.Icon = self.IsShiftLockToggled and Settings.MouseIconOnToggle or ""

		if self.Humanoid and self.RootPart then
			self.Humanoid.AutoRotate = not self.IsShiftLockToggled
			self.Humanoid.CameraOffset = self.IsShiftLockToggled and not IsInFirstPerson() and self.Humanoid.CameraOffset:Lerp(Vector3.new(Settings.CameraOffsetX, Settings.CameraOffsetY), DeltaTime * 3 * Settings.CameraOffsetLerpSpeed) or self.Humanoid.CameraOffset:Lerp(Vector3.new(), DeltaTime * 3 * Settings.CameraOffsetLerpSpeed)
		end

		if self.IsShiftLockToggled then
			if (not self.Humanoid.Sit or self.Humanoid:GetState() ~= Enum.HumanoidStateType.Seated) and self.Humanoid:GetState() ~= Enum.HumanoidStateType.Swimming and self.Humanoid:GetState() ~= Enum.HumanoidStateType.Physics and self.Humanoid:GetState() ~= Enum.HumanoidStateType.Ragdoll and self.Humanoid:GetState() ~= Enum.HumanoidStateType.Dead then
				local X, Y, Z = Camera.CFrame:ToOrientation()
				self.RootPart.CFrame = self.RootPart.CFrame:Lerp(CFrame.new(self.RootPart.Position) * CFrame.Angles(0, Y, 0), DeltaTime * 5 * Settings.CharacterFacingLerpSpeed)
			end
		end
	end

	Player.CharacterAdded:Connect(CharacterAdded)
	RunService.RenderStepped:Connect(RenderStepped)
	UserInputService.InputChanged:Connect(InputChanged)
	return setmetatable(self, ShiftLockController)
end

function ShiftLockController:Lock(Boolean)
	assert(not (Boolean == nil), "Argument missing or is equal to nil.")
	assert(typeof(Boolean) == typeof(false), "Argument is not a valid boolean.")
	self.IsShiftLockToggled = Boolean
end

return ShiftLockController

Please submit a video previewing the issue that you are claiming.
Edit: No clue what you are asking, I am doing:

local character = (players.LocalPlayer.Character or players.LocalPlayer.CharacterAdded:Wait());

I resetted the humanoid and rootpart variables by using characteradded:

local function CharacterAdded(NewCharacter)
		self.Humanoid = WaitForChildOfClass(NewCharacter, "Humanoid")
		self.RootPart = NewCharacter:WaitForChild("HumanoidRootPart", math.huge)
	end

Player.CharacterAdded:Connect(CharacterAdded)

What issue did it solve, can you submit a video of the previous issue?

Previous issue:
robloxapp-20210929-2233073.wmv (2.7 MB)

(Can’t upload mp4 after recording with obs)

The system itself isn’t locking the mouse on it’s own, you have to call a method that the system provides to lock the mouse. Where did you place the ShiftLock module, where did you place the code that is activating the shift lock, and also send the code that is activating the shift lock.

I put it in Replicated Storage

Where is the code that activates the ShiftLock, and what’s it’s source code?
(Send it as a private Message, the thread is getting too long)

An option to not rotate the character would be nice

1 Like

Sorry for the incredible delay, I haven’t looked at this post for a while now.
You can do this directly through the code, by just removing the line that changes HumanoidRootPart.CFrame (don’t know where it is exactly).
When I will soon get on studio, I will add the requested feature, and edit this comment to update when I will have done that. Thanks for the suggestion and patience.
Edit: RotateCharacter is now a feature which you can disable/enable in the settings.

Hello, when i unshiftlock the cursor is still stuck in the middle of the screen, behaving like im holding right click.

Do you know how to fix this?