I grabbed a free model "shift to run" script to play around with for a small little project. I'm trying to make it take stamina away from the player, but all it does is take the stamina and then nothing else. Any ideas on what I'm doing wrong?
local mouse = game.Players.LocalPlayer:GetMouse() local running = false function getTool() for _, kid in ipairs(script.Parent:GetChildren()) do if kid.className == "Tool" then return kid end end return nil end mouse.KeyDown:connect(function (key) key = string.lower(key) if string.byte(key) == 48 and game.Players.LocalPlayer.Levelss.Vampire.Value == 0 then running = true while true do wait() if running == true then game.Players.LocalPlayer.Levelss.Stamina.Value = game.Players.LocalPlayer.Levelss.Stamina.Value - 5 end end local keyConnection = mouse.KeyUp:connect(function (key) if string.byte(key) == 48 then running = false end end) for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (70+(i*2)) wait() end game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = game.Players.LocalPlayer.Character.Humanoid.WalkSpeed + 7 repeat wait () until running == false keyConnection:disconnect() game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = game.Players.LocalPlayer.Character.Humanoid.WalkSpeed - 7 for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (80-(i*2)) wait() end end end) mouse.KeyDown:connect(function (key) key = string.lower(key) if string.byte(key) == 48 and game.Players.LocalPlayer.Levelss.Vampire.Value == 1 then running = true while true do wait() if running == true then game.Players.LocalPlayer.Levelss.Stamina.Value = game.Players.LocalPlayer.Levelss.Stamina.Value - 5 end end local keyConnection = mouse.KeyUp:connect(function (key) if string.byte(key) == 48 then running = false end end) for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (70+(i*2)) wait() end game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = game.Players.LocalPlayer.Character.Humanoid.WalkSpeed + 15 repeat wait () until running == false keyConnection:disconnect() game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = game.Players.LocalPlayer.Character.Humanoid.WalkSpeed - 15 for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (80-(i*2)) wait() end end end)
Before getting to the actual problems, there are a couple of things fundamentally wrong with this. I'll list and address them in order, I suppose:
game.Players.LocalPlayer
; you should create variables for stuff you're using a lot.Mouse.KeyDown
, which is deprecated. You should use UserInputService
or ContextActionService
instead.The script is also just rather messy, in general. So, let's tackle them in order.
The first part should be simple to fix; it looks like the only differences are the check of Vampire.Value
and the number which is added. So, knowing this, we should be able to merge the two functions rather easily.
I also pointed out that you should use a variable for game.Players.LocalPlayer
, so let's add that in as well.
local player = game:GetService("Players").LocalPlayer; local mouse = player:GetMouse() local running = false function getTool() for _, kid in ipairs(script.Parent:GetChildren()) do if kid.className == "Tool" then return kid end end return nil end mouse.KeyDown:Connect(function(key) key = string.lower(key) if string.byte(key) ~= 48 then return end; local delta; if player.Levelss.Vampire.Value == 0 then --// You may be better off using a BoolValue here. delta = 7; else delta = 15; end; running = true while true do wait() if running == true then player.Levelss.Stamina.Value = player.Levelss.Stamina.Value - 5 end end local keyConnection = mouse.KeyUp:connect(function (key) if string.byte(key) == 48 then running = false end end) for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (70+(i*2)) wait() end player.Character.Humanoid.WalkSpeed = player.Character.Humanoid.WalkSpeed + delta --// Using the delta value, which was set earlier. repeat wait () until running == false keyConnection:disconnect() player.Character.Humanoid.WalkSpeed = player.Character.Humanoid.WalkSpeed - delta for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (80-(i*2)) wait() end end)
Okay, that wasn't too bad. Now that the script is a bit more straightforward, we can deal with the other issues. As I said before, Mouse.KeyDown
is deprecated (Mouse.KeyUp
, as well). Personally, I prefer UserInputService
, although ContextActionService
has its perks and is more useful in certain contexts. In this case, however, I'm going to use UserInputService
.
UserInputService
methods may look a bit different from Mouse.KeyDown
, but they're really quite straightforward.
local player = game:GetService("Players").LocalPlayer; local UIS = game:GetService("UserInputService"); local running = false function getTool() for _, kid in ipairs(script.Parent:GetChildren()) do if kid.ClassName == "Tool" then return kid end --// Not super related, but `className` is deprecated. Use `ClassName` instead. end return nil end UIS.InputBegan:Connect(function(input, gameProcessedEvent) if gameProcessedEvent then return end; --// If it was pressed on top of a GUI, return. local key = input.KeyCode; if key ~= Enum.KeyCode.RightShift then return end; local delta; if player.Levelss.Vampire.Value == 0 then --// You may be better off using a BoolValue here. delta = 7; else delta = 15; end; running = true while true do wait() if running == true then player.Levelss.Stamina.Value = player.Levelss.Stamina.Value - 5 end end local keyConnection = UIS.InputEnded:Connect(function(input, gpe) if input.KeyCode == Enum.KeyCode.RightShift then running = false end end) for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (70+(i*2)) wait() end player.Character.Humanoid.WalkSpeed = player.Character.Humanoid.WalkSpeed + delta --// Using the delta value, which was set earlier. repeat wait () until running == false keyConnection:disconnect() player.Character.Humanoid.WalkSpeed = player.Character.Humanoid.WalkSpeed - delta for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (80-(i*2)) wait() end end)
Alright, that conversion is out of the way. Now we can get to the real issues!
For this bit, I'll focus on a few smaller sections of the code. The first, and most prominent error would probably be the infinite loop you've got going on:
while true do wait() if running == true then player.Levelss.Stamina.Value = player.Levelss.Stamina.Value - 5 end end
You may be thinking, "But that isn't infinite, it only runs if running
is true!"
The thing is, not only does the loop itself keep going even if running
is no longer true, running
will never not be true, because the event connection directly beneath the loop never runs. I'll get to that in a bit.
The two big flaws here are messed-up order of execution (as I just pointed out) and lack of a loop condition.
As for the loop condition, you could break the loop like this:
while true do wait() if running == true then player.Levelss.Stamina.Value = player.Levelss.Stamina.Value - 5 else break end end
And it works, sure. But why do that when you can just as easily, and a bit more cleanly, do this?
while running do wait() player.Levelss.Stamina.Value = player.Levelss.Stamina.Value - 5 end
Alright, now we've set up the loop condition. The bigger issue here would be the order of execution. Right now, this section of code looks like this:
running = true while running do wait() player.Levelss.Stamina.Value = player.Levelss.Stamina.Value - 5 end local keyConnection = UIS.InputEnded:Connect(function(input, gpe) if input.KeyCode == Enum.KeyCode.RightShift then running = false end end) for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (70+(i*2)) wait() end player.Character.Humanoid.WalkSpeed = player.Character.Humanoid.WalkSpeed + delta - --// More stuff...
The logic is all over the place. It might seem to make sense when looking at the script, but let's describe the first two things happening, in order.
running
is true, decrease the stamina value.running
to false when shift is released.This already doesn't seem right. How is it going to get to the second step if it's still looping in the first step!?
Short answer: it can't. And it can't reach any of the code in the function below that point, either.
But we already know it doesn't work, so how do we fix it? Easy, just change what the problem was: the order of execution. If you need the event to be connected before the loop starts, you should, well.. do it before the loop. Same with the WalkSpeed change, and the camera effects.
local player = game:GetService("Players").LocalPlayer; local UIS = game:GetService("UserInputService"); local running = false function getTool() for _, kid in ipairs(script.Parent:GetChildren()) do if kid.ClassName == "Tool" then return kid end --// Not super related, but `className` is deprecated. Use `ClassName` instead. end return nil end UIS.InputBegan:Connect(function(input, gameProcessedEvent) if gameProcessedEvent then return end; --// If it was pressed on top of a GUI, return. local key = input.KeyCode; if key ~= Enum.KeyCode.RightShift then return end; local delta; if player.Levelss.Vampire.Value == 0 then --// You may be better off using a BoolValue here. delta = 7; else delta = 15; end; local keyConnection = UIS.InputEnded:Connect(function(input, gpe) if input.KeyCode == Enum.KeyCode.RightShift then running = false end end) for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (70+(i*2)) wait() end player.Character.Humanoid.WalkSpeed = player.Character.Humanoid.WalkSpeed + delta running = true while running do wait() player.Levelss.Stamina.Value = player.Levelss.Stamina.Value - 5 end --// repeat wait () until running == false -> This line is useless, and can be removed. keyConnection:Disconnect() --// `disconnect` is deprecated, use `Disconnect` instead. player.Character.Humanoid.WalkSpeed = player.Character.Humanoid.WalkSpeed - delta for i = 1,5 do game.Workspace.CurrentCamera.FieldOfView = (80-(i*2)) wait() end end)
Really, that's about it for the real script-breaking problems. You can improve upon the code in a few ways, such as:
IsA()
rather then ClassName
.BoolValue
for Vampire
, as I noted in the code.running
as a debounce (if running then return end
) at the start of the function, so it can't be triggered while it's already happening.But, for the most part, it should be good.
Hope this helped, and hope you learned some stuff.
Read more about InputObjects, KeyCodes, and ContextActionService.