Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

How do I made a keybinded tool bar type thing that can be changed?

I didn't really know what to call this but here is what I mean. I have magic abilities, they are keybinded to F or G as of current. I want to make it so that Fireball = G but if I wanted to then I could change maybe Lightning Strike to G. This wouldn't be done by me either, I want it so that the players can do this themselves. This would save up keybinds and allow players to only have certain Spells equipped at one time, not all of them.

To sum it up, Player has Fireball and Lightning Strike spells (as an example), Player can customise which ability is keybinded to what button, max (let's say) 5 buttons. If they have 6 spells unlocked then only 5 can be on at one time each to the keybind of the player's choosing.

As of current, my spells are done with a local script checking for the keybind to be pressed if that player has the local script in their folder. This act will then use a Remote Event to activate the spell which is a server script.

If there's a YouTube tutorial that covers this then that would work too, thanks in advance!

1 answer

✓ Accepted answer

Apologies for the rather lengthy answer but hopefully it helps you understand how it might be implemented better than just some code. You can store the keybinds in a datastore, perhaps like this: {userid: {"F":=Lightning","G"="Fireball",...}}

This would look something like this:

local DataStoreService = game:GetService("DataStoreService")

local KeybindStore = DataStoreService:GetDataStore("KeybindDatastore")

local keybinds = {}

game.Players.PlayerAdded:Connect(function(player)
	local data = nil
	local success, data = pcall(function()
		return KeybindStore:GetAsync(player.UserId)
	end)
	if success then
		keybinds[player.UserId] = data
	end
	if data == nil then
		keybinds[player.UserId] = {"F" = "Lightning", "G" = "Fireball"}
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local success, errorMessage = pcall(function()
		KeybindStore:SetAsync(player.UserId, keybinds[player.UserId])
	end)
	if not success then
		print(errorMessage)
	end
end)

The result of this would be a the keybind settings being stored in the keybinds variable. This could be in a server script that also manages firing the abilities. One way of doing this would be to use a remote event. In my code, this would be a RemoteEvent in ReplicatedStorage called "AbilityRemote." Heres how that might look: Local Script in the player:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local abilityEvent = ReplicatedStorage:WaitForChild("AbilityRemote")
local UserInputService = game:GetService("UserInputService")

UserInputService.InputBegan:Connect(function(inputObject)
    if inputObject.UserInputType == Enum.UserInputType.Keyboard then -- check if input was from keyboard
		local value = inputObject.KeyCode.Value -- the value of the enum
		if value > 96 and value < 123 then -- letters are between 97 and 122
			key = string.char(value):upper() -- convert the enum to a string to pass to our function
			abilityEvent:FireServer(key)
		end
	end
end)

ServerScript:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local abilityEvent = ReplicatedStorage:WaitForChild("AbilityRemote")

local DataStoreService = game:GetService("DataStoreService")

local KeybindStore = DataStoreService:GetDataStore("KeybindDatastore")

local keybinds = {}

game.Players.PlayerAdded:Connect(function(player)
	local data = nil
	local success, data = pcall(function()
		return KeybindStore:GetAsync(player.UserId)
	end)
	if success then
		keybinds[player.UserId] = data --Get user data when a player joins and put it in the variable
	end
	if data == nil or data == {} then
		keybinds[player.UserId] = {"F" = "Lightning", "G" = "Fireball"} --If the data doesn't exist, create the default data. If you want to add more keybinds, you can add them to this table.
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local success, errorMessage = pcall(function()
		KeybindStore:SetAsync(player.UserId, keybinds[player.UserId]) --Save the player's keybinds when they leave.
	end)
	if not success then
		print(errorMessage)
	end
end)

local function doAbility(player, ability)
	if ability == "Fireball" then
		print("Fireball fired by",player)
		--write some code to deal with fireballs here
	elseif ability == "Lightning" then
		print("Lightning fired by",player)
		--write some code to deal with lightning here
	end
end

local function keyPressed(player, key)
	if keybinds[player.UserId][key] then
		doAbility(player, keybinds[player.UserId][key])
	end
end

abilityEvent.OnServerEvent:Connect(keyPressed)

Now, you can write code to change what keybinds correspond with which actions. How you implement this will depend on your game, but you can again use server events to change the keybinds, perhaps with a button. In my code, this would be handled by a RemoteEvent in ReplicatedStorage called "KeyRemote."

LocalScript in the player:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local abilityEvent = ReplicatedStorage:WaitForChild("AbilityRemote")
local keyEvent = ReplicatedStorage:WaitForChild("KeyRemote")
local UserInputService = game:GetService("UserInputService")

UserInputService.InputBegan:Connect(function(inputObject)
    if inputObject.UserInputType == Enum.UserInputType.Keyboard then -- check if input was from keyboard
		local value = inputObject.KeyCode.Value -- the value of the enum
		if value > 96 and value < 123 then -- letters are between 97 and 122
			key = string.char(value):upper() -- convert the enum to a string to pass to our function
			abilityEvent:FireServer(key)
		end
	end
end)

--Put this inside a button function, or another function
--key is the key that is being changed, and action is the new action to assign to it
keyEvent:FireServer(key, action)
--Example would be keyEvent:FireServer("F","Fireball")

ServerScript:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local abilityEvent = ReplicatedStorage:WaitForChild("AbilityRemote")
local keyEvent = ReplicatedStorage:WaitForChild("KeyRemote")

local DataStoreService = game:GetService("DataStoreService")

local KeybindStore = DataStoreService:GetDataStore("KeybindDatastore")

local keybinds = {}

game.Players.PlayerAdded:Connect(function(player)
	local data = nil
	local success, data = pcall(function()
		return KeybindStore:GetAsync(player.UserId)
	end)
	if success then
		keybinds[player.UserId] = data --Get user data when a player joins and put it in the variable
	end
	if data == nil or data == {} then
		keybinds[player.UserId] = {"F" = "Lightning", "G" = "Fireball"} --If the data doesn't exist, create the default data. If you want to add more keybinds, you can add them to this table.
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local success, errorMessage = pcall(function()
		KeybindStore:SetAsync(player.UserId, keybinds[player.UserId]) --Save the player's keybinds when they leave.
	end)
	if not success then
		print(errorMessage)
	end
end)

local function doAbility(player, ability)
	if ability == "Fireball" then
		print("Fireball fired by",player)
		--write some code to deal with fireballs here
	elseif ability == "Lightning" then
		print("Lightning fired by",player)
		--write some code to deal with lightning here
	end
end

local function keyPressed(player, key)
	if keybinds[player.UserId][key] then
		doAbility(player, keybinds[player.UserId][key])
	end
end

local function keyChanged(player, key, action)
	if keybinds[player.UserId][key] then
		keybinds[player.UserId][key] = action --set the key to the action
	end
end

abilityEvent.OnServerEvent:Connect(keyPressed)
keyEvent.OnServerEvent:Connect(keyChanged)

This discussion is preserved as it was. New answers, comments, and votes are closed.