Help on an In-Game NohBoard Script

Recently I’ve been trying to make a custom in-game NohBoard in one of my games. I was able to program one with the W, A, S, D, and space keys with the help of a few other people on the forum, but as soon as I started adding shift lock a ton of things started going wrong.

The issue I’m having is that it seems the W, A, S, D, and space keys all do the thing I intended the shift lock key to do, and vice versa. Another huge problem I’ve noticed is that if you press any other key that isnt those 7 (those 5 keys plus left and right shift), you get a massive lagspike out of nowhere.

Here is a video of the issue I’m having (I didn’t record the lagging issue, but it’s pretty self explanitory:

External Media

Notice how when I tap the W, A, S, D, or space keys the gui only disappears once you tap it again (which was intended for the shift keys), and when you tap shift the gui disappears when you let go of the key (was was intended for the other 5 keys). All of the keys also seem to only activate the shift gui, not the other 5 guis I’ve made… strange.

Here is the code for anyone who wants to look into it:

local run = game:GetService("RunService")
local players = game:GetService("Players")
local player = players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local userInput = game:GetService("UserInputService")
local character = player.Character or player.CharacterAdded:Wait()
local head = character:WaitForChild("Head")
local camera = workspace.CurrentCamera

local keycodeToGui = {
	[Enum.KeyCode.W] = playerGui:WaitForChild("NohboardW"),
	[Enum.KeyCode.A] = playerGui:WaitForChild("NohboardA"),
	[Enum.KeyCode.S] = playerGui:WaitForChild("NohboardS"),
	[Enum.KeyCode.D] = playerGui:WaitForChild("NohboardD"),
	[Enum.KeyCode.Space] = playerGui:WaitForChild("NohboardSpace"),
	[Enum.KeyCode.LeftShift] = playerGui:WaitForChild("NohboardShift"),
	[Enum.KeyCode.RightShift] = playerGui:WaitForChild("NohboardShift")
}

-- we can loop through a table and set all of them to false
-- save the copy and paste
for _, ui in keycodeToGui do
	ui.Enabled = false 
end

run.RenderStepped:Connect(function()
	
	local distance = (head.Position - camera.CFrame.Position).Magnitude
	local debounce = false
	
	local function checkKeys()
		
		userInput.InputBegan:Connect(function(input)
			if keycodeToGui[input.KeyCode] then -- check if the key exists
				if Enum.KeyCode.LeftShift or Enum.KeyCode.RightShift then -- is the player pressing either of the shift keys?
					if distance > 0.55 then 
						if debounce == false then -- not in first person and turns on shift lock, turns on gui
							playerGui.NohboardShift.Enabled = true
							debounce = true
						else -- not in first person and turns off shift lock, turns off gui
							playerGui.NohboardShift.Enabled = false
							debounce = false
						end
					end	
				else -- if not, enable the other keys from the table above
					keycodeToGui[input.KeyCode].Enabled = true -- set the respective gui to be enabled
				end
			end	
		end)
		
		if distance < 0.55 then -- constantly checking: is the player in first person? if yes, turn off the shift lock gui
			playerGui.NohboardShift.Enabled = false
		else
			if debounce == true then
				playerGui.NohboardShift.Enabled = true -- if the player is in shiftlock, zoomed to first person, and zooms back out, turn the gui on again
			end
		end
		
		userInput.InputEnded:Connect(function(input)
			if keycodeToGui[input.KeyCode] ~= Enum.KeyCode.LeftShift or Enum.KeyCode.RightShift then
				keycodeToGui[input.KeyCode].Enabled = false
			end
		end)
	end
	
	checkKeys()
end)

Please keep in mind that I’m fairly new to scripting, so if this makes you want to rip your eyeballs out I wouldn’t blame you :joy:
Any and all help is appreciated!

1 Like

Remove the RenderStepped connection

The RenderStepped function is there to detect whether or not the player is in first person. Is there a way to detect this inside of the other function?

yes remove the checkKeys() function from the renderStep and have the distance variables scope be for the whole file so define it outside the renderStep and update it inside. Or also you can just check the distance when the player uses a key which is a lot better because you’re only checking it when you need it instead of all the time

Sorry for the late response, but do you mean something like this?

local distance = (head.Position - camera.CFrame.Position).Magnitude
local debounce = false

run.RenderStepped:Connect(function()
	userInput.InputBegan:Connect(function(input)
		if keycodeToGui[input.KeyCode] then -- check if the key exists
			if Enum.KeyCode.LeftShift or Enum.KeyCode.RightShift then -- is the player pressing either of the shift keys?
				if distance > 0.55 then 
					if debounce == false then -- not in first person and turns on shift lock, turns on gui
						playerGui.NohboardShift.Enabled = true
						debounce = true
					else -- not in first person and turns off shift lock, turns off gui
						playerGui.NohboardShift.Enabled = false
						debounce = false
					end
				end	
			else -- if not, enable the other keys from the table above
				keycodeToGui[input.KeyCode].Enabled = true -- set the respective gui to be enabled
			end
		end	
	end)
		
	if distance < 0.55 then -- constantly checking: is the player in first person? if yes, turn off the shift lock gui
		playerGui.NohboardShift.Enabled = false
	else
		if debounce == true then
			playerGui.NohboardShift.Enabled = true -- if the player is in shiftlock, zoomed to first person, and zooms back out, turn the gui on again
		end
	end
		
	userInput.InputEnded:Connect(function(input)
		if keycodeToGui[input.KeyCode] ~= Enum.KeyCode.LeftShift or Enum.KeyCode.RightShift then
			keycodeToGui[input.KeyCode].Enabled = false
		end
	end)
end)

It unfortunately doesn’t make it any better and I still end up with the same issues I came in with :sob:

Like this:

local run = game:GetService("RunService")
local players = game:GetService("Players")
local player = players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local userInput = game:GetService("UserInputService")
local character = player.Character or player.CharacterAdded:Wait()
local head = character:WaitForChild("Head")
local camera = workspace.CurrentCamera

local keycodeToGui = {
	[Enum.KeyCode.W] = playerGui:WaitForChild("NohboardW"),
	[Enum.KeyCode.A] = playerGui:WaitForChild("NohboardA"),
	[Enum.KeyCode.S] = playerGui:WaitForChild("NohboardS"),
	[Enum.KeyCode.D] = playerGui:WaitForChild("NohboardD"),
	[Enum.KeyCode.Space] = playerGui:WaitForChild("NohboardSpace"),
	[Enum.KeyCode.LeftShift] = playerGui:WaitForChild("NohboardShift"),
	[Enum.KeyCode.RightShift] = playerGui:WaitForChild("NohboardShift")
}

-- we can loop through a table and set all of them to false
-- save the copy and paste
for _, ui in keycodeToGui do
	ui.Enabled = false 
end

local distance
run.RenderStepped:Connect(function()
	distance = (head.Position - camera.CFrame.Position).Magnitude

	if distance < 0.55 then -- constantly checking: is the player in first person? if yes, turn off the shift lock gui
		playerGui.NohboardShift.Enabled = false
	else
		if debounce == true then
			playerGui.NohboardShift.Enabled = true -- if the player is in shiftlock, zoomed to first person, and zooms back out, turn the gui on again
		end
	end
end)

local function checkKeys()
	userInput.InputBegan:Connect(function(input)
		if keycodeToGui[input.KeyCode] then -- check if the key exists
			if Enum.KeyCode.LeftShift or Enum.KeyCode.RightShift then -- is the player pressing either of the shift keys?
				if distance > 0.55 then 
					if debounce == false then -- not in first person and turns on shift lock, turns on gui
						playerGui.NohboardShift.Enabled = true
						debounce = true
					else -- not in first person and turns off shift lock, turns off gui
						playerGui.NohboardShift.Enabled = false
						debounce = false
					end
				end	
			else -- if not, enable the other keys from the table above
				keycodeToGui[input.KeyCode].Enabled = true -- set the respective gui to be enabled
			end
		end	
	end)
	
	userInput.InputEnded:Connect(function(input)
		if keycodeToGui[input.KeyCode] ~= Enum.KeyCode.LeftShift or Enum.KeyCode.RightShift then
			keycodeToGui[input.KeyCode].Enabled = false
		end
	end)
end

checkKeys()

Ok yeah this worked, thanks! That’s one of the problems done.

The function I made is definitely wrong and I think it has something to do with this line here:

if Enum.KeyCode.LeftShift or Enum.KeyCode.RightShift then

I chose to write it like this because I didn’t know how to directly call from a table. Is there a way to do this?

Could you specify a little more?

if you wanted to get the value of Enum.KeyCode.LeftShift then you could just do

keycodeToGui[Enum.KeyCode.LeftShift]

but if you wanted to search through a table for a specific value you could use a for loop like

for i,v in pairs(keycodeToGui) do
	print(i) -- keycodes
	print(v)-- playergui connected to the keycode
end

Hmm… I’m trying to specify if the player is pressing the shift keys. This is because I’m using a completely different gui system for them. I didn’t want them to turn on when you press the key and turn off when you let go of it, I wanted a toggle system that also depended on whether or not you were in first person which I sort of made in the script. The issue is that all 7 keys are going to the same gui, and I’m not sure why. Before I added the shift lock gui, every key corresponded to its gui.

As you can see here, I’m basically trying to say “If you’re pressing a key from the table and its left or right shift, use this toggle system. If not, use the other corresponding guis”

if keycodeToGui[input.KeyCode] then -- check if the key exists
			if Enum.KeyCode.LeftShift or Enum.KeyCode.RightShift then -- is the player pressing either of the shift keys?
				if distance > 0.55 then 
					if debounce == false then -- not in first person and turns on shift lock, turns on gui
						playerGui.NohboardShift.Enabled = true
						debounce = true
					else -- not in first person and turns off shift lock, turns off gui
						playerGui.NohboardShift.Enabled = false
						debounce = false
					end
				end	
			else -- if not, enable the other keys from the table above
				keycodeToGui[input.KeyCode].Enabled = true -- set the respective gui to be enabled
			end
		end	

I’m fairly confident it’s bugging out here.