local StaminaManager = require(script.Parent:WaitForChild("StaminaModule"))

local defaultSpeed = 16
local sprintSpeed = 22
local normalFov = 70
local sprintFov = 80
local crouchFov = 65
local crouchSpeed = 8
local staminaDrainRate = 17
local Settings = {
	Lifetime = 0.15,
	DashVelocity = 55,
	Cooldown = 3,
	DashStaminaCost = 20,
}

local Services = setmetatable({}, {
	__index = function(Self, Index)
		local NewService = game:GetService(Index)
		if NewService then
			Self[Index] = NewService
		end
		return NewService
	end
})

local UserInputService = Services.UserInputService
local TweenService = Services.TweenService
local RunService = Services.RunService
local Players = Services.Players
local ReplicatedStorage = Services.ReplicatedStorage

local sprintKey = Enum.KeyCode.LeftShift
local crouchKey = Enum.KeyCode.C
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local Camera = workspace.CurrentCamera
local healthBar = Player.PlayerGui:WaitForChild("StaminaAndHealthBar"):WaitForChild("Frame"):WaitForChild("HealthBar"):WaitForChild("Bar")
local staminaBar = Player.PlayerGui:WaitForChild("StaminaAndHealthBar"):WaitForChild("Frame"):WaitForChild("StaminaBar"):WaitForChild("Bar")
local sprintAnim = ReplicatedStorage:WaitForChild("Animations"):WaitForChild("Player"):WaitForChild("SprintAnim")
local animTrack = Humanoid:LoadAnimation(sprintAnim)
local movementKeys = {Enum.KeyCode.W, Enum.KeyCode.A, Enum.KeyCode.S, Enum.KeyCode.D}
local movementKeysPressed = {}
local shiftPressed, sprinting, isCrouching, isMoving, isSliding = false, false, false, false, false

local Animations = {
	Forward = Humanoid:LoadAnimation(ReplicatedStorage:WaitForChild("Animations"):WaitForChild("Player"):WaitForChild("FrontDash")),
	Backward = Humanoid:LoadAnimation(ReplicatedStorage:WaitForChild("Animations"):WaitForChild("Player"):WaitForChild("BackDash")),
	Left = Humanoid:LoadAnimation(ReplicatedStorage:WaitForChild("Animations"):WaitForChild("Player"):WaitForChild("LeftDash")),
	Right = Humanoid:LoadAnimation(ReplicatedStorage:WaitForChild("Animations"):WaitForChild("Player"):WaitForChild("RightDash")),
}
local BV = Instance.new("BodyVelocity")

local function tweenFov(duration, fov)
	local tween = TweenService:Create(Camera, TweenInfo.new(duration, Enum.EasingStyle.Quad), { FieldOfView = fov })
	tween:Play()
	tween.Completed:Wait()
	tween:Destroy()
end

local function tweenStaminaBar()
	local stamina = StaminaManager.GetStamina()
	local tween = TweenService:Create(staminaBar, TweenInfo.new(0.25, Enum.EasingStyle.Quad), { Size = UDim2.new(stamina / StaminaManager.maxStamina, 0, 1, 0) })
	tween:Play()
end

local function startSprinting()
	if not sprinting and StaminaManager.GetStamina() > 0 and not isCrouching then
		sprinting = true
		StaminaManager.ReduceStamina(staminaDrainRate * RunService.RenderStepped:Wait())
		Humanoid.WalkSpeed = sprintSpeed
		if Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall then
			animTrack:Play()
		end
		tweenFov(0.25, sprintFov)
		tweenStaminaBar()
	end
end

local function stopSprinting()
	if sprinting then
		sprinting = false
		Humanoid.WalkSpeed = defaultSpeed
		animTrack:Stop()
		tweenFov(0.25, normalFov)
		tweenStaminaBar()
	end
end

local function crouch()
	if not isCrouching and not sprinting then
		if animTrack.IsPlaying then animTrack:Stop() end
		isCrouching, Humanoid.WalkSpeed = true, crouchSpeed
		tweenFov(0.25, crouchFov)
	end
end

local function stand()
	if isCrouching then
		isCrouching, Humanoid.WalkSpeed = false, defaultSpeed
		tweenFov(0.25, normalFov)
	end
end

local function startSliding()
	print("SLIDE TIME")
end


Character.Humanoid:GetPropertyChangedSignal("Health"):Connect(function()
	healthBar.Size = UDim2.new(Character.Humanoid.Health / 100, 0, 1, 0)
end)

local function dash()
	local Now, DashCooldown = workspace:GetServerTimeNow(), Character:GetAttribute("DashCooldown") or 0
	if DashCooldown > Now or StaminaManager.GetStamina() < Settings.DashStaminaCost then return end

	Character:SetAttribute("DashCooldown", Now + Settings.Cooldown)
	StaminaManager.ReduceStamina(Settings.DashStaminaCost)

	local NewBV = BV:Clone()
	NewBV.MaxForce, NewBV.P = Vector3.new(1e5, 1e5, 1e5), 1250
	local Direction = Humanoid.MoveDirection.Magnitude > 0 and Humanoid.MoveDirection or HumanoidRootPart.CFrame.LookVector
	local RelativeDirection = (CFrame.lookAt(Camera.CFrame.LookVector, Camera.CFrame.LookVector + Direction)).LookVector
	local currentYVelocity = HumanoidRootPart.Velocity.Y / 2
	NewBV.Velocity = Vector3.new(RelativeDirection.X, 0, RelativeDirection.Z) * Settings.DashVelocity + Vector3.new(0, currentYVelocity, 0)
	NewBV.Parent = HumanoidRootPart

	for key, anim in pairs({[Enum.KeyCode.W] = "Forward", [Enum.KeyCode.A] = "Left", [Enum.KeyCode.S] = "Backward", [Enum.KeyCode.D] = "Right"}) do
		if UserInputService:IsKeyDown(key) then
			Animations[anim]:Play()
			break
		end
	end

	task.delay(Settings.Lifetime, function() NewBV:Destroy() end)
end

UserInputService.InputBegan:Connect(function(input, processed)
	if processed or Humanoid.Health == 0 then return end
	if input.KeyCode == sprintKey then
		shiftPressed = true
		if next(movementKeysPressed) ~= nil then
			startSprinting()
		end
	elseif table.find(movementKeys, input.KeyCode) then
		movementKeysPressed[input.KeyCode] = true
		if shiftPressed and StaminaManager.GetStamina() > 0 and not isCrouching then
			startSprinting()
		end
	elseif input.KeyCode == crouchKey then
		if sprinting and StaminaManager.GetStamina() > 0 and isCrouching then
			startSliding()
		else
			crouch()
		end
	elseif input.KeyCode == Enum.KeyCode.E then
		dash()
	end
end)


UserInputService.InputEnded:Connect(function(input)
    if Humanoid.Health == 0 then return end
    if input.KeyCode == sprintKey then
        shiftPressed = false
        stopSprinting()
    elseif table.find(movementKeys, input.KeyCode) then
        movementKeysPressed[input.KeyCode] = nil
        if next(movementKeysPressed) == nil then
            stopSprinting()
        end
    elseif input.KeyCode == crouchKey and not sprinting then
        stand()
    end
end)

RunService.RenderStepped:Connect(function(deltaTime)
    if sprinting and not StaminaManager.ReduceStamina(staminaDrainRate * deltaTime) then
        stopSprinting()
    end
    tweenStaminaBar()
end)

Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
    isMoving = Humanoid.MoveDirection.Magnitude > 0
end)

local playAnim = Humanoid:LoadAnimation(ReplicatedStorage:WaitForChild("Animations"):WaitForChild("Player"):WaitForChild("Land"))
Humanoid.StateChanged:Connect(function(oldState, newState)
    if newState == Enum.HumanoidStateType.Freefall then
        animTrack:Stop()
    elseif newState == Enum.HumanoidStateType.Landed then
        animTrack:Stop()
    	    playAnim:Play()
        playAnim.Stopped:Wait()
        if sprinting then
            animTrack:Play()
        end
    end
end)


problem 1: the health and stamina bar arent updating.
problem 2: startSliding() should fire when the player presses Shift and C, yet the function print doesnt happen.