I have a Toggle-able Sprint Script as well as a Toggle-able Crouch Script and, annoyingly, they will overlap. I’ve tried multiple solutions, each with failure so I’m looking for help. I want it so that the Sprint Script can’t be activated when crouching and also stops sprinting when activated.
Both of these are Local Scripts in StarterCharacterScripts.
Crouch Script:
-- Services and References --
local plr = game.Players.LocalPlayer
local Character = plr.Character or plr.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local UIS = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local Camera = workspace.CurrentCamera
-- Variables and Initialization --
local Crouching = script:WaitForChild("IsCrouching").Value
Crouching = false
local CrouchAnim = Humanoid:LoadAnimation(script:WaitForChild("Crouching"))
local CrouchSound = script.Crouch
local GetUpSound = script.GetUp
local WalkingSound = script.Walking
local originalSpeed = Humanoid.WalkSpeed
local originalMinCameraDistance = plr.CameraMinZoomDistance
local originalMaxCameraDistance = plr.CameraMaxZoomDistance
local notMoving = true
local isOnGround = true
local freefallTimer = 0
-- Changeable --
local CrouchButton = Enum.KeyCode.LeftControl -- Change this to the key you want for Crouching
local newSpeed = 12 -- Speed you want while Crouching
local DefaultFieldOfView = 70 -- Default FOV
local CrouchFieldOfView = 60 -- Crouching FOV
local MinCameraDistance = 0.5 -- Minimum camera distance you want while Crouching
local MaxCameraDistance = 10 -- Maximum camera distance you want while Crouching
local maxFreefallDuration = 0.35 -- Max Freefall duration before getting up
Camera.FieldOfView = DefaultFieldOfView
-- Crouch Function --
local function Crouch()
if Crouching == false and isOnGround == true and script.CrouchEnabled.Value == true then
Crouching = true
CrouchAnim:Play()
CrouchSound:Play()
WalkingSound:Play()
Humanoid.WalkSpeed = newSpeed
plr.CameraMinZoomDistance = MinCameraDistance
plr.CameraMaxZoomDistance = MaxCameraDistance
Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
local FOVgoal1 = { FieldOfView = CrouchFieldOfView }
local FOVinfo1 = TweenInfo.new(0.5)
local FOVtween1 = TweenService:Create(Camera, FOVinfo1, FOVgoal1)
FOVtween1:Play()
local CAMgoal1 = { CameraOffset = Vector3.new(0, -1, 0) }
local CAMinfo1 = TweenInfo.new(
0.3,
Enum.EasingStyle.Back,
Enum.EasingDirection.Out,
0,
false,
0
)
local CAMtween1 = TweenService:Create(Humanoid, CAMinfo1, CAMgoal1)
CAMtween1:Play()
end
end
-- Obstruction Check Function --
local function IsntObstructed()
local head = Character:FindFirstChild("Head")
if head then
local rayStart = head.Position
local rayDirection = head.CFrame.UpVector * 1.5
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {Character}
local raycastResult = workspace:Raycast(rayStart, rayDirection, raycastParams)
return raycastResult ~= nil
end
return false
end
-- Can Uncrouch Function --
local function CanUncrouch()
return not IsntObstructed()
end
-- Stop Crouch Function --
local function Stop()
if CanUncrouch() then
if Crouching == true then
Crouching = false
CrouchAnim:Stop()
GetUpSound:Play()
WalkingSound:Stop()
Humanoid.WalkSpeed = originalSpeed
plr.CameraMinZoomDistance = originalMinCameraDistance
plr.CameraMaxZoomDistance = originalMaxCameraDistance
Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
local FOVgoal2 = { FieldOfView = DefaultFieldOfView }
local FOVinfo2 = TweenInfo.new(1)
local FOVtween2 = TweenService:Create(Camera, FOVinfo2, FOVgoal2)
FOVtween2:Play()
local CAMgoal2 = { CameraOffset = Vector3.new(0, 0, 0) }
local CAMinfo2 = TweenInfo.new(
0.3,
Enum.EasingStyle.Back,
Enum.EasingDirection.Out,
0,
false,
0
)
local CAMtween2 = TweenService:Create(Humanoid, CAMinfo2, CAMgoal2)
CAMtween2:Play()
end
end
end
-- Input Handling --
UIS.InputBegan:Connect(function(input, isTyping)
if isTyping then return end
if input.KeyCode == CrouchButton then
if Crouching == false then
Crouch()
elseif Crouching == true then
Stop()
end
end
end)
-- Heartbeat Logic --
RunService.Heartbeat:Connect(function()
notMoving = Humanoid.MoveDirection.Magnitude == 0
if notMoving and Crouching == true then
CrouchAnim:AdjustSpeed(0)
WalkingSound.PlaybackSpeed = 0
end
if notMoving == false and Crouching == true then
CrouchAnim:AdjustSpeed(1)
WalkingSound.PlaybackSpeed = 1.5
end
if Crouching == true and Humanoid:GetState() == Enum.HumanoidStateType.Physics or Humanoid:GetState() == Enum.HumanoidStateType.Seated or Humanoid:GetState() == Enum.HumanoidStateType.Swimming or Humanoid:GetState() == Enum.HumanoidStateType.Climbing or Humanoid:GetState() == Enum.HumanoidStateType.Dead or Humanoid:GetState() == Enum.HumanoidStateType.Landed then
Stop()
end
if Crouching == true and script.CrouchEnabled.Value == false then
Stop()
end
isOnGround = Humanoid.FloorMaterial ~= Enum.Material.Air
if isOnGround == false and Crouching == true then
freefallTimer = freefallTimer + RunService.Heartbeat:Wait()
if freefallTimer >= maxFreefallDuration then
Stop()
end
else
freefallTimer = 0
end
end)
Sprint Script:
-- Getting Services and Setting Up Sprint Animation --
local userInputService = game:GetService("UserInputService")
local players = game:GetService("Players")
-- Getting Local Player and Character --
local player = players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local hum = char:WaitForChild("Humanoid")
local animator = hum:WaitForChild("Animator")
-- Setting Up Animation --
local animation = Instance.new("Animation")
animation.AnimationId = "rbxassetid://82671911689586"
local track = animator:LoadAnimation(animation)
track.Priority = Enum.AnimationPriority.Movement
-- Constants --
local RUN_KEYCODE = Enum.KeyCode.LeftShift
local RUN_SPEED = 36
local WALK_SPEED = 16
-- State Variables --
local isSprinting = false
local isMoving = false
local isInAir = false
-- Function to Handle Floor Material Changes --
local function floorMaterialChanged()
if hum.FloorMaterial == Enum.Material.Air then
isInAir = true
track:Stop()
else
isInAir = false
if isSprinting and isMoving and not track.IsPlaying then
track:Play()
end
end
end
-- Function to Update Animation Based on State --
local function updateAnimation()
if isSprinting and isMoving then
hum.WalkSpeed = RUN_SPEED
if not track.IsPlaying then
track:Play()
end
else
hum.WalkSpeed = WALK_SPEED
track:Stop()
end
end
-- Function to Handle User Input --
local function inputBegan(input, processed)
if processed then return end
if input.KeyCode == RUN_KEYCODE then
if not isSprinting and char:GetAttribute("Swimming") then
return
end
isSprinting = not isSprinting
updateAnimation()
end
end
-- Function to Handle Movement Direction Changes --
local function moveDirectionChanged()
isMoving = hum.MoveDirection.Magnitude > 0
if not isInAir then
updateAnimation()
end
end
-- Connect Events --
userInputService.InputBegan:Connect(inputBegan)
hum:GetPropertyChangedSignal("MoveDirection"):Connect(moveDirectionChanged)
hum:GetPropertyChangedSignal("FloorMaterial"):Connect(floorMaterialChanged)
Thank you!