Hello devs!
I am making an abilities system in my game where the player can equip three abilities (with keybinds F, G, and H) at a time. There is a bug right now where if you do an ability with keybind G for example, unequip the ability, and equip another ability (it will have keybind G), and actually press G, it will do the ability that you have equipped AND the one that you previously unequipped.
Here is my code right now.
ClientFunctions Script (StarterPlayerScripts):
local Players = game:GetService("Players")
local UI = {
Players.LocalPlayer.PlayerGui:WaitForChild("ShopUI"),
Players.LocalPlayer.PlayerGui:WaitForChild("InventoryUI"),
Players.LocalPlayer.PlayerGui:WaitForChild("AbilitiesUI"),
Players.LocalPlayer.PlayerGui:WaitForChild("VIPui"),
}
_G.HideAllUI = function(exception)
for i, gui in UI do
if gui.Name == exception then continue end
gui.Enabled = false
end
end
_G.UpdateAbilityKeybinds = function()
local player = game.Players.LocalPlayer
local equippedAbilities = player.EquippedAbilities:GetChildren()
local keybinds = { Enum.KeyCode.F, Enum.KeyCode.G, Enum.KeyCode.H } -- Default keybinds
local keyStringMap = {}
-- Clear existing keybinds
for _, abilityUI in pairs(player.PlayerGui.BottomBar.Frame:GetChildren()) do
if abilityUI:IsA("Frame") and abilityUI:FindFirstChild("Keystroke") then
abilityUI.Keystroke.Value = "Unknown" -- Reset to default value
end
end
-- Assign keybinds to equipped abilities
for i, ability in ipairs(equippedAbilities) do
if ability:IsA("StringValue") and ability.Name ~= "Keystroke" then
local key = keybinds[i] or Enum.KeyCode.Unknown
local keyString = key.Name
keyStringMap[ability.Name] = keyString
local abilityUI = player.PlayerGui.BottomBar.Frame:FindFirstChild(ability.Name)
if abilityUI and abilityUI:IsA("Frame") then
local keystrokeValue = abilityUI:FindFirstChild("Keystroke")
if keystrokeValue then
keystrokeValue.Value = keyString
end
end
end
end
return keyStringMap
end
Dash (StarterPlayerScripts → Abilities):
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UpgradeItems = require(ReplicatedStorage.Modules.UpgradeItems)
local player = game.Players.LocalPlayer
local DashAnimation = script:WaitForChild('Animation')
task.wait(2.1)
-- Settings
local velocity = 30000 -- dash speed
local debounce = false -- debounce, do not set to true
local cooldown = UpgradeItems.Dash.Cooldown
local duration = UpgradeItems.Dash.StartingTime
local currentAbilityConnection
-- Get the TextLabel
local textLabel = player:WaitForChild("PlayerGui"):WaitForChild("BottomBar"):WaitForChild("Frame"):WaitForChild("Dash"):WaitForChild("TextLabel")
local function updateKeyDisplay()
local keyStringMap = _G.UpdateAbilityKeybinds()
local keyString = keyStringMap["Dash"] or "Unknown"
local textLabel = player:WaitForChild("PlayerGui"):WaitForChild("BottomBar"):WaitForChild("Frame"):WaitForChild("Dash"):WaitForChild("TextLabel")
textLabel.Text = keyString
end
local function updateCooldownText(remainingTime)
textLabel.Text = string.format("%.1f", remainingTime)
end
local function Dash()
if not player.Abilities:FindFirstChild("Dash") then return end
local character = player.Character
if character and not debounce then
debounce = true
local humanoid = character.Humanoid
local HRP = character.HumanoidRootPart
local loadedAnimation = humanoid.Animator:LoadAnimation(DashAnimation)
local dashDirection = nil
local moveDirection = humanoid.MoveDirection
local lookVector = HRP.CFrame.LookVector
local minusVelocity = -velocity
local isOnGround = humanoid.FloorMaterial ~= Enum.Material.Air and humanoid.FloorMaterial ~= Enum.Material.Water
if isOnGround then
if moveDirection == Vector3.new(0,0,0) then
dashDirection = HRP.Position + Vector3.new(lookVector.X, 0, lookVector.Z)
else
dashDirection = HRP.Position + Vector3.new(moveDirection.X, 0, moveDirection.Z)
end
local bodyGyro = Instance.new("BodyGyro")
bodyGyro.Parent = HRP
bodyGyro.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
bodyGyro.D = 0
bodyGyro.P = 500000
bodyGyro.CFrame = CFrame.lookAt(HRP.Position, dashDirection)
script.DashSound:Play()
local trail = script.Trail:Clone()
trail.Attachment0 = HRP:WaitForChild("TrailAttachment0")
trail.Attachment1 = HRP:WaitForChild("TrailAttachment1")
trail.Parent = HRP
local attachment = Instance.new("Attachment")
attachment.Parent = HRP
local vectorForce = Instance.new("VectorForce")
vectorForce.Parent = HRP
vectorForce.Attachment0 = attachment
vectorForce.Force = Vector3.new(0, 0, minusVelocity)
loadedAnimation:Play()
humanoid.AutoRotate = false
wait(duration)
humanoid.AutoRotate = true
vectorForce:Destroy()
bodyGyro:Destroy()
attachment:Destroy()
trail:Destroy()
loadedAnimation:Stop()
end
-- Cooldown timer
local remainingCooldown = cooldown
while remainingCooldown > 0 do
updateCooldownText(remainingCooldown)
wait(0.1)
remainingCooldown = remainingCooldown - 0.1
end
updateKeyDisplay()
debounce = false
end
end
local function updateKey()
local keyStringMap = _G.UpdateAbilityKeybinds()
local keyString = keyStringMap["Dash"]
if keyString then
return Enum.KeyCode[keyString] or Enum.KeyCode.Unknown
else
return Enum.KeyCode.Unknown
end
end
local function connectInputToAbility(key)
if currentAbilityConnection then
currentAbilityConnection:Disconnect()
end
currentAbilityConnection = UserInputService.InputBegan:Connect(function(input, gameProcessed)
if not gameProcessed and input.KeyCode == key then
Dash()
end
end)
end
-- Initial Key Display
updateKeyDisplay()
local key = updateKey()
connectInputToAbility(key)
player.EquippedAbilities.ChildAdded:Connect(function()
key = updateKey()
updateKeyDisplay()
connectInputToAbility(key)
end)
player.EquippedAbilities.ChildRemoved:Connect(function()
key = updateKey()
updateKeyDisplay()
connectInputToAbility(key)
end)
player.PlayerGui.BottomBar.Frame.Dash.Activated:Connect(function()
Dash()
end)
High Jump (StarterPlayerScripts → Abilities):
local player = game.Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local UpgradeItems = require(ReplicatedStorage.Modules.UpgradeItems)
local jumpSettings = UpgradeItems["High Jump"]
local cooldown = jumpSettings.Cooldown
local duration = jumpSettings.StartingTime
local debounce = false
task.wait(2.1)
local currentAbilityConnection
local jumpButton = player:WaitForChild("PlayerGui"):WaitForChild("BottomBar"):WaitForChild("Frame"):WaitForChild("High Jump")
local textLabel = jumpButton:WaitForChild("TextLabel")
local function updateKeyDisplay()
local keyStringMap = _G.UpdateAbilityKeybinds()
local keyString = keyStringMap["High Jump"] or "Unknown"
local textLabel = player:WaitForChild("PlayerGui"):WaitForChild("BottomBar"):WaitForChild("Frame"):WaitForChild("High Jump"):WaitForChild("TextLabel")
textLabel.Text = keyString
end
local function updateCooldownText(remainingTime)
textLabel.Text = string.format("%.1f", remainingTime)
end
local function activateJump()
if not player.Abilities:FindFirstChild("High Jump") then return end
if not debounce then
debounce = true
local character = player.Character
if character then
ReplicatedStorage.PlayerJump:FireServer(character, true)
wait(duration)
ReplicatedStorage.PlayerJump:FireServer(character, false)
local remainingCooldown = cooldown
while remainingCooldown > 0 do
updateCooldownText(remainingCooldown)
wait(0.1)
remainingCooldown = remainingCooldown - 0.1
end
updateKeyDisplay()
debounce = false
end
end
end
local function updateKey()
local keyStringMap = _G.UpdateAbilityKeybinds()
local keyString = keyStringMap["High Jump"]
if keyString then
return Enum.KeyCode[keyString] or Enum.KeyCode.Unknown
else
return Enum.KeyCode.Unknown
end
end
local function connectInputToAbility(key)
if currentAbilityConnection then
currentAbilityConnection:Disconnect()
end
currentAbilityConnection = UserInputService.InputBegan:Connect(function(input, gameProcessed)
if not gameProcessed and input.KeyCode == key then
activateJump()
end
end)
end
-- Initial Key Display
updateKeyDisplay()
local key = updateKey()
connectInputToAbility(key)
player.EquippedAbilities.ChildAdded:Connect(function()
key = updateKey()
updateKeyDisplay()
connectInputToAbility(key)
end)
player.EquippedAbilities.ChildRemoved:Connect(function()
key = updateKey()
updateKeyDisplay()
connectInputToAbility(key)
end)
jumpButton.Activated:Connect(activateJump)
Invisibility (StarterPlayerScripts → Abilities):
local player = game.Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local UpgradeItems = require(ReplicatedStorage.Modules.UpgradeItems)
local jumpSettings = UpgradeItems["High Jump"]
local cooldown = jumpSettings.Cooldown
local duration = jumpSettings.StartingTime
local debounce = false
task.wait(2.1)
local currentAbilityConnection
local jumpButton = player:WaitForChild("PlayerGui"):WaitForChild("BottomBar"):WaitForChild("Frame"):WaitForChild("High Jump")
local textLabel = jumpButton:WaitForChild("TextLabel")
local function updateKeyDisplay()
local keyStringMap = _G.UpdateAbilityKeybinds()
local keyString = keyStringMap["High Jump"] or "Unknown"
local textLabel = player:WaitForChild("PlayerGui"):WaitForChild("BottomBar"):WaitForChild("Frame"):WaitForChild("High Jump"):WaitForChild("TextLabel")
textLabel.Text = keyString
end
local function updateCooldownText(remainingTime)
textLabel.Text = string.format("%.1f", remainingTime)
end
local function activateJump()
if not player.Abilities:FindFirstChild("High Jump") then return end
if not debounce then
debounce = true
local character = player.Character
if character then
ReplicatedStorage.PlayerJump:FireServer(character, true)
wait(duration)
ReplicatedStorage.PlayerJump:FireServer(character, false)
local remainingCooldown = cooldown
while remainingCooldown > 0 do
updateCooldownText(remainingCooldown)
wait(0.1)
remainingCooldown = remainingCooldown - 0.1
end
updateKeyDisplay()
debounce = false
end
end
end
local function updateKey()
local keyStringMap = _G.UpdateAbilityKeybinds()
local keyString = keyStringMap["High Jump"]
if keyString then
return Enum.KeyCode[keyString] or Enum.KeyCode.Unknown
else
return Enum.KeyCode.Unknown
end
end
local function connectInputToAbility(key)
if currentAbilityConnection then
currentAbilityConnection:Disconnect()
end
currentAbilityConnection = UserInputService.InputBegan:Connect(function(input, gameProcessed)
if not gameProcessed and input.KeyCode == key then
activateJump()
end
end)
end
-- Initial Key Display
updateKeyDisplay()
local key = updateKey()
connectInputToAbility(key)
player.EquippedAbilities.ChildAdded:Connect(function()
key = updateKey()
updateKeyDisplay()
connectInputToAbility(key)
end)
player.EquippedAbilities.ChildRemoved:Connect(function()
key = updateKey()
updateKeyDisplay()
connectInputToAbility(key)
end)
jumpButton.Activated:Connect(activateJump)
Shield (StarterPlayerScripts → Abilities):
local player = game.Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local UpgradeItems = require(ReplicatedStorage.Modules.UpgradeItems)
local shieldSettings = UpgradeItems["Shield"]
local cooldown = shieldSettings.Cooldown
local duration = shieldSettings.StartingTime
local debounce = false
task.wait(2.1)
local currentAbilityConnection
local shieldButton = player:WaitForChild("PlayerGui"):WaitForChild("BottomBar"):WaitForChild("Frame"):WaitForChild("Shield")
local textLabel = shieldButton:WaitForChild("TextLabel")
local function updateKeyDisplay()
local keyStringMap = _G.UpdateAbilityKeybinds()
local keyString = keyStringMap["Shield"] or "Unknown"
local textLabel = player:WaitForChild("PlayerGui"):WaitForChild("BottomBar"):WaitForChild("Frame"):WaitForChild("Shield"):WaitForChild("TextLabel")
textLabel.Text = keyString
end
local function updateCooldownText(remainingTime)
textLabel.Text = string.format("%.1f", remainingTime)
end
local function activateShield()
if not player.Abilities:FindFirstChild("Shield") then return end
if not debounce then
debounce = true
local character = player.Character
if character then
ReplicatedStorage.GiveShield:FireServer(character)
wait(duration)
ReplicatedStorage.DestroyShield:FireServer(character)
local remainingCooldown = cooldown
while remainingCooldown > 0 do
updateCooldownText(remainingCooldown)
wait(0.1)
remainingCooldown = remainingCooldown - 0.1
end
updateKeyDisplay()
debounce = false
end
end
end
local function updateKey()
local keyStringMap = _G.UpdateAbilityKeybinds()
local keyString = keyStringMap["Shield"]
if keyString then
return Enum.KeyCode[keyString] or Enum.KeyCode.Unknown
else
return Enum.KeyCode.Unknown
end
end
local function connectInputToAbility(key)
if currentAbilityConnection then
currentAbilityConnection:Disconnect()
end
currentAbilityConnection = UserInputService.InputBegan:Connect(function(input, gameProcessed)
if not gameProcessed and input.KeyCode == key then
activateShield()
end
end)
end
-- Initial Key Display
updateKeyDisplay()
local key = updateKey()
connectInputToAbility(key)
player.EquippedAbilities.ChildAdded:Connect(function()
key = updateKey()
updateKeyDisplay()
connectInputToAbility(key)
end)
player.EquippedAbilities.ChildRemoved:Connect(function()
key = updateKey()
updateKeyDisplay()
connectInputToAbility(key)
end)
shieldButton.Activated:Connect(activateShield)
If you need any more code snippets please ask!
Thanks
-DarkPurpleElixr