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!
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)