TotalAmmo deducts 2 even though its supposed to only take 1 away

In my script the reload function is glitching a little bit. whenever it reloads its supposed to just take 1 away from totalammo but it takes 2 away. Im guessing its because for some reason the reload function is fired twice but i cant figure out where or how to prevent this.

Here is the full script (important code after the shoot() function)

local body = script.Tank.Value.BodyKit
local tool = script.Parent
local event = game.ReplicatedStorage.TankSystem.RemoteEvents.TankTurretRotation
local TurretUnion = script.Tank.Value.BodyKit.Turret.PrimaryPart
local fireShell = event.Parent.FireShell
local debris = game:GetService("Debris")

local config = script.Tank.Value.Seat.Configuration

local ammoLeft = config.AmmoLeft
local totalAmmo = config.TotalAmmo
local reloading = false

local turret = script.Tank.Value.BodyKit.Turret  -- Assuming turret is a model with PrimaryPart set
local startPart = script.Tank.Value.BodyKit.Turret.FirePart
local muzzlePart = script.Tank.Value.BodyKit.Turret.MuzzlePart
local barrelPart = script.Tank.Value.BodyKit.Turret.BarrelPart

local function Shoot(mousePosition)
	if not turret.PrimaryPart then
		warn("Turret does not have a PrimaryPart set!")
		return
	end

	local turretPosition = startPart.Position
	local turretDirection = turret.PrimaryPart.CFrame.LookVector

	local camera = game.Workspace.CurrentCamera
	local mouseDirection = (mousePosition - camera.CFrame.Position).Unit
	local angle = math.asin(mouseDirection.Y)
	local upDownDirection = Vector3.new(turretDirection.X, math.sin(angle), turretDirection.Z).Unit

	local targetPosition = turretPosition + upDownDirection * 1000

	-- Raycast to simulate the shell's trajectory
	local ray = Ray.new(turretPosition, (targetPosition - turretPosition).unit * 1000)
	local rayResult = game.Workspace:Raycast(ray.Origin, ray.Direction)

	-- Fire sound
	local fireSound = Instance.new("Sound")
	fireSound.SoundId = "rbxassetid://8213064126"
	fireSound.Volume = 0.75
	fireSound.Parent = barrelPart
	fireSound:Play()
	fireSound.Ended:Connect(function()
		fireSound:Destroy()
	end)

	-- Explosion effect
	local function createExplosionAtImpact(hitPosition)
		local explosion = Instance.new("Explosion")
		explosion.Position = hitPosition
		explosion.BlastRadius = 100
		explosion.BlastPressure = 0  -- Increased explosion impact
		explosion.ExplosionType = Enum.ExplosionType.NoCraters
		explosion.Parent = game.Workspace
	end

	-- If the ray hits something, create explosion at the hit position
	if rayResult then
		local distance = (rayResult.Position - turretPosition).Magnitude

		-- You can change this value to control how long the delay is
		local delayTime = distance / 350  -- Example: 1 second per 100 studs of distance

		-- Wait for the delay time before creating the explosion
		delay(delayTime, function()
			createExplosionAtImpact(rayResult.Position)
		end)
	end
end

local function reload()
	-- Prevent reloading if already in the process or if there's ammo left
	if reloading or ammoLeft.Value >= 1 or totalAmmo.Value <= 0 then
		return
	end

	reloading = true
	local reloadSound = Instance.new("Sound")
	reloadSound.SoundId = "rbxassetid://2721754456"
	reloadSound.Volume = 0.75
	reloadSound.Parent = barrelPart
	reloadSound:Play()

	wait(3)  -- Wait for reload time

	-- Only reload if totalAmmo is available
	if totalAmmo.Value > 0 then
		ammoLeft.Value = 1  -- Refill one ammo
		totalAmmo.Value = totalAmmo.Value - 1  -- Decrease totalAmmo by 1
	end

	reloading = false
end

event.Parent.FireShell.OnServerEvent:Connect(function(plr, mouseHitPosition)
	if ammoLeft.Value > 0 and not reloading then
		ammoLeft.Value = ammoLeft.Value - 1
		Shoot(mouseHitPosition)
	end
end)

ammoLeft:GetPropertyChangedSignal("Value"):Connect(function()
	if ammoLeft.Value <= 0 and totalAmmo.Value >= 1 and not reloading then
		reload()
	end
end)

-- Function to calculate C0 from the world CFrame
local function worldCFrameToC0ObjectSpace(motor6DJoint, worldCFrame)
	local part1CF = motor6DJoint.Part1.CFrame
	local c1Store = motor6DJoint.C1
	local c0Store = motor6DJoint.C0
	local relativeToPart1 = c0Store * c1Store:Inverse() * part1CF:Inverse() * worldCFrame * c1Store
	relativeToPart1 -= relativeToPart1.Position
	local goalC0CFrame = relativeToPart1 + c0Store.Position
	return goalC0CFrame
end

local rotationSpeed = 0.05

event.OnServerEvent:Connect(function(plr, mousePosition)
	local lookPos = Vector3.new(mousePosition.X, TurretUnion.CFrame.Position.Y, mousePosition.Z)
	local goalCF = CFrame.lookAt(TurretUnion.CFrame.Position, lookPos)

	local currentCF = TurretUnion.Motor6D.C0
	local newCF = worldCFrameToC0ObjectSpace(TurretUnion.Motor6D, goalCF)
	TurretUnion.Motor6D.C0 = currentCF:Lerp(newCF, rotationSpeed)
end)

Wrap setting the reloading value to false in a task.delay. it could be that as it is a race condition when you update the value of ammo left it gets picked up by the detecting function however by the time this happens, reloading has been set to false

1 Like