Gun Ammo Amount Problem

So I have this ui that displays the amout of Ammo the gun has. But it is swiching from the amount and the total amount it is supposed to have. I know the problem, the Ammo Amount setting is swiching from the amount of ammo left and 6 (max ammo). But I dont know why, I checked using prints and the reload is not going off or anyuthing, But it prints the ammo swiching from the amount of ammo left and 6?

Here is the script that changes the ammo, (its in server script serivce.)

local TweenService = game:GetService("TweenService")
Debris = game:GetService("Debris")

function TagHumanoid(humanoid, player)
	local Creator_Tag = Instance.new("ObjectValue")
	Creator_Tag.Name = "creator"
	Creator_Tag.Value = player
	Debris:AddItem(Creator_Tag, 2)
	Creator_Tag.Parent = humanoid
end

function UntagHumanoid(humanoid)
	for i, v in pairs(humanoid:GetChildren()) do
		if v:IsA("ObjectValue") and v.Name == "creator" then
			v:Destroy()
		end
	end
end


game.ReplicatedStorage.GunRemote.OnServerEvent:Connect(function(player, origin,direction, Settings, GunToo, reload, mousepos)
	if reload == true then
		wait(Settings.ReloadTime.Value)
		Settings.CurrentAmmo.Value = Settings.MagSize.Value
		print("True")
		return
	end
	if GunToo:IsA("Tool") and GunToo:FindFirstChild("GunSystem") and GunToo.Parent == player.Character or player.Backpack then
		if Settings.CurrentAmmo.Value > 0 then
			Settings.CurrentAmmo.Value = Settings.CurrentAmmo.Value - 1
			GunToo.Handle.ShotEffect:Play()
			-- raycast params
			local raycastParams = RaycastParams.new()
			raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
			raycastParams.FilterDescendantsInstances = {player.Character, GunToo}
			raycastParams.IgnoreWater = true
			local result2 = workspace:Raycast(origin,direction*Settings.Distance.Value, raycastParams)
			if result2 then
				local beam = Instance.new("Part", workspace)
				beam.BrickColor = BrickColor.new("White")
				beam.FormFactor = "Custom"
				beam.Material = "Neon"
				beam.Transparency = 0.7
				beam.Anchored = true
				beam.Locked = true
				beam.CanCollide = false

				local distance = (GunToo.FirePart.CFrame.p - mousepos).magnitude
				beam.Size = Vector3.new(0.1, 0.1, distance)
				beam.CFrame = CFrame.new(GunToo.FirePart.CFrame.p, mousepos) * CFrame.new(0, 0, -distance / 2)
				wait(0.05)
				beam:Destroy()
				local part = result2.Instance
				local humanoid = part.Parent:FindFirstChild("Humanoid") or part.Parent.Parent:FindFirstChild("Humanoid")
				
				if humanoid then
					if part.Name == "Head" then
						player.folder.lastkilled.Value = humanoid.Parent.Name
						humanoid:TakeDamage(Settings.Damage.Value * 2)
						game.ReplicatedStorage.Killed:FireClient(player)
						UntagHumanoid(humanoid)
						player.folder.killstreak.Value += 1
						TagHumanoid(humanoid, player)
					elseif part.Name == "UpperTorso" or part.Name == "Torso" or part.Name == "HumanoidRootPart" then
						player.folder.lastkilled.Value = humanoid.Parent.Name
						humanoid:TakeDamage(Settings.Damage.Value * 1.3)
						game.ReplicatedStorage.Killed:FireClient(player)
						UntagHumanoid(humanoid)
						player.folder.killstreak.Value += 1
						TagHumanoid(humanoid, player)
					else
						player.folder.lastkilled.Value = humanoid.Parent.Name
						humanoid:TakeDamage(Settings.Damage.Value)
						game.ReplicatedStorage.Killed:FireClient(player)
						UntagHumanoid(humanoid)
						player.folder.killstreak.Value += 1
						TagHumanoid(humanoid, player)
					end
				end
			end
		else
			GunToo.Handle.Empty:Play()
		end
	else
		player:Kick("A suspicious action was found, are you trying to use cheats?")
	end

end)

Here is video:

4 Likes

do ammo -= 1, not ammo = ammo - 1

anyway, since this is a UI related issue, can you send the script that handles the UI?
i don’t necessarily think server-side has anything to do with this problem

thanks but it still has the problem. Also it is not a UI problem, the ui is just displaying the value. I have a # value that is constantly changing, which is the problem.

1 Like

and if you print the ammo value?

even if,
the UI always displays 6 on gun equip until the gun gets fired, meaning the UI code has to be written incorrectly, since the server changes the ammo just fine

It changes from the current ammo and 6, which is the problem.

Here is the ui script:

while wait(0) do if state.autoShooting and state.equipped and Coroutine.Value == false and not isReloading then handleShot() end if game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD") then game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD").GunName.Text = script.Parent.Name game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD").CurrentAmmo.Text = Settings.CurrentAmmo.Value.."/"..Settings.MagSize.Value end end

it’s 3 back ticks ```

image

why the while loop?? why not just listen for changes to the int value via .Changed?
also PLEASE use variables you don’t have to do game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD") every single line

mbbbbbb i do uii, so i tried .Change and it just displays 0/0 nothing else, here is the code

while wait(0) do
	if state.autoShooting and state.equipped and Coroutine.Value == false and not isReloading then
		handleShot()
	end
	if game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD") then
		game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD").GunName.Text = script.Parent.Name
	end
end

Settings.CurrentAmmo.Changed:Connect(function()
	game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD").CurrentAmmo.Text = Settings.CurrentAmmo.Value.."/"..Settings.MagSize.Value
end)

bump


It seems like a block of code is changing the CurrentAmmo’s value back to 6, does your handleShot() function change its value?

thats a local script

but here is the handshot()

local function handleShot()
	if Settings.CurrentAmmo.Value <= 0 and isReloading == false then
		isReloading = true
		script.Parent.Handle.ReloadSound:Play()
		game.ReplicatedStorage.GunRemote:FireServer(nil, nil, Settings, script.Parent, true)
		wait(Settings.ReloadTime.Value + 0.2)
		isReloading = false
		return
	end
	if not Coroutine.Value and Settings.CurrentAmmo.Value > 0 and isReloading == false then
		Coroutine.Value = true
		curshots = 1
		local origin = script.Parent.FirePart.Position
		local direction = (player:GetMouse().Hit.Position - origin).Unit
		
		game.ReplicatedStorage.GunRemote:FireServer(origin, direction, Settings, script.Parent, false, player:GetMouse().Hit.Position)
		for _, effect in ipairs(script.Parent.Handle.Muzzle:GetChildren()) do
			if effect:IsA("ParticleEmitter") or effect:IsA("Light") then
				effect.Enabled = true
			end
		end
		for _, effect in ipairs(script.Parent.Handle.Muzzle:GetChildren()) do
			if effect:IsA("ParticleEmitter") or effect:IsA("Light") then
				effect.Enabled = false
			end
		end

		animations.shot:Play()
		local casing = game.ReplicatedStorage.Casing:Clone()
		casing.Parent = workspace
		casing.CanCollide = false
		casing.CFrame = script.Parent.Handle.CasingEject.WorldCFrame
		local bodyforce = Instance.new("BodyForce")
		bodyforce.Force = Vector3.new(script.Parent.Handle.CasingEject.WorldCFrame.LookVector.X * math.random(5,20), math.random(10,15), 0)
		bodyforce.Parent = casing
		casing.Orientation = casing.Orientation * math.random(5,10)
		casing.CanCollide = true
		bodyforce:Destroy()
		wait(Settings.Countdown.Value)
		Coroutine.Value = false
	end
end

Why are you setting the current ammo to Settings.CurrentAmmo? Realistically you should have the server update an attribute in the gun itself with the current ammo count, then on the client check if that value is changed, and if so then update the UI accordingly.

Most of your issues can be solved by using proper luau practices.

Use the features put in place by Roblox. Attributes within the gun handle will allow you to track and persist changes for that specific object, all changes to that attribute will replicate down to the client.

I am using a number in the gun and the server is upating it?

image

Are you able to either PM me the place file or post it here so I can look a little deeper into your issue?

Here are the 2 scripts:

Server script, inside server script service:

local TweenService = game:GetService("TweenService")
Debris = game:GetService("Debris")

function TagHumanoid(humanoid, player)
	local Creator_Tag = Instance.new("ObjectValue")
	Creator_Tag.Name = "creator"
	Creator_Tag.Value = player
	Debris:AddItem(Creator_Tag, 2)
	Creator_Tag.Parent = humanoid
end

function UntagHumanoid(humanoid)
	for i, v in pairs(humanoid:GetChildren()) do
		if v:IsA("ObjectValue") and v.Name == "creator" then
			v:Destroy()
		end
	end
end


game.ReplicatedStorage.GunRemote.OnServerEvent:Connect(function(player, origin,direction, Settings, GunToo, reload, mousepos)
	if reload == true then
		wait(Settings.ReloadTime.Value)
		Settings.CurrentAmmo.Value = Settings.MagSize.Value
		print("True")
		return
	end
	if GunToo:IsA("Tool") and GunToo:FindFirstChild("GunSystem") and GunToo.Parent == player.Character or player.Backpack then
		if Settings.CurrentAmmo.Value > 0 then
			Settings.CurrentAmmo.Value -= 1
			GunToo.Handle.ShotEffect:Play()
			-- raycast params
			local raycastParams = RaycastParams.new()
			raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
			raycastParams.FilterDescendantsInstances = {player.Character, GunToo}
			raycastParams.IgnoreWater = true
			local result2 = workspace:Raycast(origin,direction*Settings.Distance.Value, raycastParams)
			if result2 then
				local beam = Instance.new("Part", workspace)
				beam.BrickColor = BrickColor.new("White")
				beam.FormFactor = "Custom"
				beam.Material = "Neon"
				beam.Transparency = 0.7
				beam.Anchored = true
				beam.Locked = true
				beam.CanCollide = false

				local distance = (GunToo.FirePart.CFrame.p - mousepos).magnitude
				beam.Size = Vector3.new(0.1, 0.1, distance)
				beam.CFrame = CFrame.new(GunToo.FirePart.CFrame.p, mousepos) * CFrame.new(0, 0, -distance / 2)
				wait(0.05)
				beam:Destroy()
				local part = result2.Instance
				local humanoid = part.Parent:FindFirstChild("Humanoid") or part.Parent.Parent:FindFirstChild("Humanoid")
				
				if humanoid then
					if part.Name == "Head" then
						player.folder.lastkilled.Value = humanoid.Parent.Name
						humanoid:TakeDamage(Settings.Damage.Value * 2)
						game.ReplicatedStorage.Killed:FireClient(player)
						UntagHumanoid(humanoid)
						player.folder.killstreak.Value += 1
						TagHumanoid(humanoid, player)
					elseif part.Name == "UpperTorso" or part.Name == "Torso" or part.Name == "HumanoidRootPart" then
						player.folder.lastkilled.Value = humanoid.Parent.Name
						humanoid:TakeDamage(Settings.Damage.Value * 1.3)
						game.ReplicatedStorage.Killed:FireClient(player)
						UntagHumanoid(humanoid)
						player.folder.killstreak.Value += 1
						TagHumanoid(humanoid, player)
					else
						player.folder.lastkilled.Value = humanoid.Parent.Name
						humanoid:TakeDamage(Settings.Damage.Value)
						game.ReplicatedStorage.Killed:FireClient(player)
						UntagHumanoid(humanoid)
						player.folder.killstreak.Value += 1
						TagHumanoid(humanoid, player)
					end
				end
			end
		else
			GunToo.Handle.Empty:Play()
		end
	else
		player:Kick("A suspicious action was found, are you trying to use cheats?")
	end

end)

Local Script, inside the gun:

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")

-- Player and Character References
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local rootPart = character:WaitForChild("HumanoidRootPart")
local camera = workspace.CurrentCamera

-- Animations Setup
local animations = {
	idle = humanoid:LoadAnimation(script.Parent.Animations.Idle),
	shot = humanoid:LoadAnimation(script.Parent.Animations.Shot),
	reload = humanoid:LoadAnimation(script.Parent.Animations.Reload),
}

animations.idle.Priority = Enum.AnimationPriority.Idle
animations.shot.Priority = Enum.AnimationPriority.Action2
animations.reload.Priority = Enum.AnimationPriority.Action
animations.shot:AdjustSpeed(2)

-- States and Settings
local state = {
	equipped = false,
	autoShooting = false,
}

local Settings = script.Parent.Settings
local Coroutine = Settings.Coroutine
local isReloading = false;
local onfirstperson = false;
local gunHUD = script.Parent.GunHUD
local originalIcon = game:GetService("UserInputService").MouseIcon
-- Recoil Configuration
local RecoilPattern = {
	{3, 12, -1, 0.77, -0.1},
	{6, 12, -1, 0.77, 0.1},
	{8, 12, -1, 0.77, -0.1},
	{10, 12, -1, 0.77, 0.1},
}
local RecoilReset = 0.5

-- Variables
local curshots = 0
local lastclick = tick()
-- Utility Functions
local function lerp(a, b, t)
	return a * (1 - t) + (b * t)
end

local function createTween(instance, duration, properties)
	return TweenService:Create(
		instance,
		TweenInfo.new(duration, Enum.EasingStyle.Linear),
		properties
	):Play()
end

local function handleEquip()
	state.equipped = true
	animations.idle:Play()
	player:GetMouse().Icon = Settings.CrossHairID.Value
	local newHUD = gunHUD:Clone()
	newHUD.Parent = game.Players.LocalPlayer.PlayerGui
end

local function handleUnequip()
	player:GetMouse().Icon = originalIcon
	state.equipped = false
	state.autoShooting = false
	animations.idle:Stop()
	createTween(workspace.CurrentCamera, 0.3, {FieldOfView = 70})
	createTween(player.PlayerGui:FindFirstChild("GunHUD").Vignette, 0.3, {ImageTransparency = 1})
	if game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD") then
		game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD"):Destroy()
	end
end


local function handleShot()
	if Settings.CurrentAmmo.Value <= 0 and isReloading == false then
		isReloading = true
		script.Parent.Handle.ReloadSound:Play()
		game.ReplicatedStorage.GunRemote:FireServer(nil, nil, Settings, script.Parent, true)
		wait(Settings.ReloadTime.Value + 0.2)
		isReloading = false
		return
	end
	if not Coroutine.Value and Settings.CurrentAmmo.Value > 0 and isReloading == false then
		Coroutine.Value = true
		curshots = 1
		local origin = script.Parent.FirePart.Position
		local direction = (player:GetMouse().Hit.Position - origin).Unit
		
		game.ReplicatedStorage.GunRemote:FireServer(origin, direction, Settings, script.Parent, false, player:GetMouse().Hit.Position)
		for _, effect in ipairs(script.Parent.Handle.Muzzle:GetChildren()) do
			if effect:IsA("ParticleEmitter") or effect:IsA("Light") then
				effect.Enabled = true
			end
		end
		for _, effect in ipairs(script.Parent.Handle.Muzzle:GetChildren()) do
			if effect:IsA("ParticleEmitter") or effect:IsA("Light") then
				effect.Enabled = false
			end
		end

		animations.shot:Play()
		local casing = game.ReplicatedStorage.Casing:Clone()
		casing.Parent = workspace
		casing.CanCollide = false
		casing.CFrame = script.Parent.Handle.CasingEject.WorldCFrame
		local bodyforce = Instance.new("BodyForce")
		bodyforce.Force = Vector3.new(script.Parent.Handle.CasingEject.WorldCFrame.LookVector.X * math.random(5,20), math.random(10,15), 0)
		bodyforce.Parent = casing
		casing.Orientation = casing.Orientation * math.random(5,10)
		casing.CanCollide = true
		bodyforce:Destroy()
		wait(Settings.Countdown.Value)
		Coroutine.Value = false
	end
end


-- Event Connections
script.Parent.Equipped:Connect(handleEquip)
script.Parent.Unequipped:Connect(handleUnequip)
script.Parent.Activated:Connect(function()
	if not Settings.isAuto.Value then
		handleShot()
	end
end)

UserInputService.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		if Settings.isAuto.Value == true then
			state.autoShooting = true
		end
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		if Settings.isAuto.Value == true then
			state.autoShooting = false
		end		
	end
end)

while wait(0) do
	if state.autoShooting and state.equipped and Coroutine.Value == false and not isReloading then
		handleShot()
	end
	if game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD") then
		game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD").GunName.Text = script.Parent.Name
	end
end

Settings.CurrentAmmo.Changed:Connect(function()
	game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD").CurrentAmmo.Text = Settings.CurrentAmmo.Value.."/"..Settings.MagSize.Value
end)

You should put the whole loop inside the same scope where you set autoShooting to true, in the inputBegan event. Also make it conditional on autoShooting. When you do this, it will always refresh when pressing, instead of just running once. The whole loop will break once the code for inputEnded is triggered, setting autoShooting to false.
Something like this:

while autoShooting do
    handleShot()
    task.wait() — put some number of you want to wait for longer
end

Also, use task.wait() from now on.

thankyou but that did not help

here is also a video of me print(Settings.CurrentAmmo.Value)

you need to be able to narrow down the source of the problem even more. Where is Settings stored?

In the gun, I feel like I kinda i narrow down the source the problem is that the CurrentAmmo is swiching bettween the current ammo and 6

what does the explorer tree look like for settings?

[Edit] nvm don’t answer this. I see the previous post. I’ll edit my solution into this comment

[Edit] Try this:

Settings.CurrentAmmo.Changed:Connect(function(currValue)
	game.Players.LocalPlayer.PlayerGui:FindFirstChild("GunHUD").CurrentAmmo.Text = currValue.."/"..Settings.MagSize.Value
end)

it just displays 0/0, which is prob because we didd not set it to show anything BEFORE it changed