Sprinting System Penalty when Carrying Items

Hey everyone,

I’m trying to create an item encumberment system for the player as they try to carry artillery shells. This involves a penalty to the player’s WalkSpeed and they cannot sprint. This WalkSpeed penalty restricts the player’s movement to a value of 2.

My current sprint system (shift to sprint) has the player going at a WalkSpeed of 8 at walking pace and a speed of 12 when running. This script also operates outside of this obtainment quest.

However, the system I have currently does not work as it features three prominent bugs/unusual scenarios:

  1. The player picks up a shell → Player’s speed is 2 → Player attempts to sprint, increasing the value by 4 (the player’s speed is now 6) → When the player lets go of the sprint button, the player’s WalkSpeed is 8, and further sprint attempts result in the WalkSpeed increasing to 12.

  2. Player picks up a shell → Player doesn’t attempt to sprint → places the shell into the trolley → Player’s WalkSpeed remains at 2 → If the player decides to sprint, their WalkSpeed is 10, before resetting to 8 when they let go.

  3. Player picks up a second shell (regardless of whether they followed the 1st or 2nd outcomes) → WalkSpeed is 0 but can be fixed by repeatedly attempting to sprint.

Here are some videos to demonstrate this issue:

Local Script for Sprinting:

local Players = game:GetService("Players")
local ContextActionService = game:GetService("ContextActionService")

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CannotSprintEvent = ReplicatedStorage:FindFirstChild("CannotSprint")
local CanSprintEvent = ReplicatedStorage:FindFirstChild("CanSprint")

local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

repeat wait() until Character:FindFirstChild("Humanoid")

local Humanoid = Character.Humanoid

local function HandleSprint(StartSprint)
	CannotSprintEvent.OnClientEvent:Connect(function()
		warn("Exhausted/Restricted Movement; Cannot Sprint")
		Humanoid.WalkSpeed = 8
	end)

	CanSprintEvent.OnClientEvent:Connect(function()
		print("Free Movement; Can Sprint")
		if StartSprint == true then
			Humanoid.WalkSpeed += 4
		else
			Humanoid.WalkSpeed = 8
		end
	end)

	-- When neither CannotSprint nor CanSprint event is fired, sprinting is default
	if StartSprint == true then
		Humanoid.WalkSpeed += 4
	else
		Humanoid.WalkSpeed = 8
	end
end

local function HandleInput(Action, InputState, InputObject)
	if Action == "Sprint" then
		local StartSprint = false
		if InputState == Enum.UserInputState.Begin then
			StartSprint = true
		end
		HandleSprint(StartSprint)
	end
end

local function AwaitInput()
	ContextActionService:BindAction("Sprint", HandleInput, true, Enum.KeyCode.LeftShift, Enum.KeyCode.ButtonX)
	ContextActionService:SetTitle("Sprint", "Sprint")
end

AwaitInput()

Server Script (Detecting Carry Status)

local ArtilleryShellPallet = script.Parent.Parent
local Shells = ArtilleryShellPallet.Shells
local TopLayerShells = Shells.TopLayer

local Clicker = script.Parent.ClickDetector

local ServerStorage = game:GetService("ServerStorage")
local TrolleyFull = ServerStorage.TrolleyFull

local Full = false

TrolleyFull.Event:Connect(function()
	Full = true -- Set the Full variable to true when the event is called
	if Full then
		Clicker:Destroy() -- Delete the click detector if Full is true
	end
end)

Clicker.MouseClick:Connect(function(Player)

	if Player then

		local TurretShells = Player:FindFirstChild("TurretShells")
		if not TurretShells then
			TurretShells = Instance.new("IntValue")
			TurretShells.Name = "TurretShells"
			TurretShells.Parent = Player
		end

		if TurretShells.Value == 0 and not Full then -- Check if the player already has a shell and the Full variable is false
			TurretShells.Value += 1
			print("Shells after increment:", TurretShells.Value)

			local ReplicatedStorage = game:GetService("ReplicatedStorage")
			local ShellCountNum = ReplicatedStorage.Values.ShellCountNum

			ShellCountNum.Value += 1

			local Humanoid = Player.Character and Player.Character:FindFirstChildOfClass("Humanoid")
			if Humanoid then
				Humanoid.WalkSpeed -= 6 -- Reduce the player's walkspeed by 6
			end

			if TopLayerShells then
				local ShellAmmo = TopLayerShells:GetChildren()

				if #ShellAmmo > 0 then
					local RandomIndex = math.random(1, #ShellAmmo)
					local RandomPart = ShellAmmo[RandomIndex]

					RandomPart:Destroy()
				end
			end

		else
			warn("You already have a shell or the trolley is full!")
		end

	end

end)