@Marios2 gave me a sprinting script, which I slightly modified to this..

local stamina = game.Workspace.Config:WaitForChild("Stamina")
local maxStamina = game.Workspace.Config:WaitForChild("MaxStamina")
local sprint = false

function onSprint(_,state)
	if state == Enum.UserInputState.Begin then
		if stamina.Value < 3 then return end
		sprint = true
		stamina.Value = stamina.Value - 3
		game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 32
		repeat
			if stamina.Value > 0 then
				stamina.Value = stamina.Value - 1
			end
			wait(0.15)
		until (sprint == false or stamina.Value == 0)
	else
                sprint = false
		game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 16
		repeat
			wait(0.25)
			if stamina.Value < maxStamina.Value then
				stamina.Value = stamina.Value + 1
			end
		until (sprint == true or stamina.Value >= maxStamina.Value)
		if stamina.Value > maxStamina.Value then stamina.Value = maxStamina.Value end
	end
end

game:GetService("ContextActionService"):BindAction("Sprint", onSprint, false, Enum.KeyCode.LeftShift)

My problem here is that a GUI I made (uses the same IntValues for stamina and maxStamina) doesn't update. I checked the IntValues in Studio and they do update

local text = script.Parent:WaitForChild("HealthText")
local frame = script.Parent:WaitForChild("ColorFrame")
local config = game.Workspace:WaitForChild("Config")
local stamina = config:WaitForChild("Stamina")
local maxStamina = config:WaitForChild("MaxStamina")

text.Text = ""..stamina.value.." / "..maxStamina.value

stamina.Changed:connect(function()
	frame:TweenSize(UDim2.new(stamina.value/maxStamina.value,0,1,0),"Out","Quad",0.5)
	text.Text = ""..math.floor(stamina.value).." / "..maxStamina.value
	if stamina.value == 0 then
		frame:TweenSize(UDim2.new(0,0,1,0),"Out","Quad",0.5)
		text.Text = "0 / "..maxStamina.value
	end
end)

Thanks in advance, jakei181