Why won't this work?

Hey everyone, I made a script for running which i wanted to be active only when the player presses down W,A and D without S also being pressed. The running works wonders without this bonus part but I can’t find a solution to what I want to achieve
This is my script

Script
local sprintSpeed = 41

local sprintFov = 80
local normalFov = 70

local sprintKey = Enum.KeyCode.LeftControl

local userInputService = game:GetService("UserInputService")
local tweenService = game:GetService("TweenService")
local runService = game:GetService("RunService")

local replicatedStorage = game:GetService("ReplicatedStorage")
local playersService = game:GetService("Players")

local player = playersService.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local defaultSpeed = humanoid.WalkSpeed

local camera = workspace.CurrentCamera

local sprintAnim = script:WaitForChild("SprintAnim")
local animTrack = humanoid:LoadAnimation(sprintAnim)

-- STATES
local sprinting = false

local function tweenFov(duration, fov)

	local tween = tweenService:Create(camera, TweenInfo.new(duration, Enum.EasingStyle.Quad), {FieldOfView = fov})
	tween:Play()

	spawn(function()
		tween.Completed:Wait()
		tween:Destroy()
	end)

end

userInputService.InputBegan:Connect(function(input, processed)
	if input.KeyCode == sprintKey and not processed then
		if not sprinting then
			
			sprinting = true
			defaultSpeed = humanoid.WalkSpeed
			
			if humanoid.MoveDirection.Magnitude > 0 then
				tweenFov(0.2, sprintFov)
				if not animTrack.IsPlaying then
					animTrack:Play()
				end
				humanoid.WalkSpeed = sprintSpeed
			end
		end
	end
end)

userInputService.InputEnded:Connect(function(input)
	if input.KeyCode == sprintKey then
		sprinting = false

		if animTrack.IsPlaying then
			animTrack:Stop()
		end

		humanoid.WalkSpeed = defaultSpeed

		tweenFov(0.2, normalFov)
	end
end)

if sprinting == true then
	userInputService.InputBegan:Connect(function(input)
		if input.KeyCode == Enum.KeyCode.S then
			sprinting = false
		
		end
	end)
end

And this is the section that I added for this feature:

if sprinting == true then
	userInputService.InputBegan:Connect(function(input)
		if input.KeyCode == Enum.KeyCode.S then
			sprinting = false
		
		end
	end)
end
2 Likes

By the time the code reaches this section sprinting is still false. This would never work

1 Like

So do I put this inside the input began?

Because the sprinting condition is outside the Inputbegan, the script only reads it once. So whether you make sprinting true or false, the script won’t be able to determine that.
So that’s part of the problem. Just arrange it like this.

userInputService.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.S and sprinting then
		sprinting = false
	end)
end
1 Like

The thing is that it doesn’t work, which bugs me because in theory it should.

You’re connecting inputbegan, but only if spirinting is true. What you’d actually need is inputbegan on it’s own, which checks if sprinting. Not the other way around.

1 Like

Is it possible that the problem might be because of some conflict between your two InputBegan functions? Try printing something inside of those functions, usually you’ll be able to determine there if it’s working as you intend it to be.

1 Like

You need to debug your code. One way would be to add print() statements, so you can track which code runs and which doesn’t.

Expanding on Primotivos’,

userInputService.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.S then
		print("S down")
		if sprinting then
			sprinting = false
			print("Sprinting = false")
		end	
	end
end)

You should do this throughout the whole script

I added a print in the first input began for the running mechanism and it worked, but it didn’t when I pressed S

I got “S is down” but not “sprinting = false”

That’s because you’re not actually connecting the inputBegan.

Roblox walks through your code top to bottom, once.
If you write print(123), it’ll print it once.
If you want to do it a few times, you have to encapsulate it into a loop.
If you want to do it whenever X happens, you have to connect the X event to it.

Right now, you check == sprinting? Which is false, by default, and Roblox only goes over it once!
If you determine it’s false, you don’t continue connecting the input. And thus you never connect the input.

  • Are we sprinting? If yes, connect input
    No, we are not sprinting.
  • OK, do not connect input

Well, then clearly sprinting is false.

so would i have to use a loop to see if sprinting is true?

No, because you are connecting it to an event. Think of it like this:

  • We can run code
  • We can run code X times, or never ending but with X seconds inbetween
  • We can run code every time X happens

In this case, every time the player presses S, is an event (so the third variant). When that event happens you can check if sprinting, because that’s the only time it’s relevant. You don’t need to check X seconds

The function as I wrote it down should be fine. Your problem lays wherever you change sprinting to true