How do I prevent this reserve ammo counter from going into the negatives?

I was working on a very simple weapon HUD and I ran into a problem where my reserve ammo counter kept going into the negatives if the player reloaded early. I quickly found a solution, which was making it so that the player can’t reload early, but I realized that this would probably get infuriating in-game. I’ve tried several things like checking if the Reserve <= 30 then to make the ammo’s value equal to the reserve’s value, and make the new reserve value 0. This is how I tried this:

if Reserve <= 30 then
Ammo = Reserve
AmmoCounter.Text = Reserve
ReserveAmmo.Text = 0
end

But this didn’t really seem to work, but at the same time I wasn’t sure if I was using it correctly.

Everything in the script is predefined, and the Ammo and Reserve values are stored in the script itself, not in an outside intvalue.

Here is the portion of my code that handles the ammocounter text.

  UserInputService.InputBegan:Connect(function(Input, gameFinished)
        if (not gameFinished) then
            if Input.KeyCode == Enum.KeyCode.R then
                character.Humanoid:LoadAnimation(script.Parent.reload):Play()
                if InfAmmo == false then
                    if Reserve ~= 0 then
                        if Reloading == false then
                            if Ammo ~= 30 then
                                Reloading = true
                                wait(ReloadingTime)
                                Reloading = false
                                Reserve = Reserve - (30 - Ammo)
                                Ammo = MaxAmmo
                                ReserveAmmo.Text = Reserve
                                AmmoCounter.Text = Ammo
                            end
                        end
                    end
                end
            end
        end
    end)
	
	while wait() do
		if buttononedown then
			while wait() do
				if Reloading == false then
					if Ammo ~= 0 then
						Ammo = Ammo - 1
						AmmoCounter.Text = Ammo
						ReserveAmmo.Text = Reserve
						script.Parent.rayCast:FireServer(script.Parent.Muzzle.Position, mouse.Hit.Position, script.Parent.Eject)
						shake()
						script.Parent.Flash.Light.Enabled = true
						RunService.Stepped:Wait()
						script.Parent.Flash.Light.Enabled = false
					else
						if InfAmmo == false then
							if Reserve ~= 0 then
								if Reloading == false then
									Reloading = true
									wait(ReloadingTime)
									Reloading = false
									Reserve = Reserve - (30-Ammo)
									Ammo = MaxAmmo
									ReserveAmmo.Text = Reserve
									AmmoCounter.Text = Ammo
								end
							end
						end
					end
				else
				end
				wait(0.03)
				if not buttononedown then
					break
				end
			end
		end
	end
end)

Where can I impliment what I need?

1 Like

Change

if Reserve ~= 0 then

to

if Reserve <= 0 then

Checks if reserve is less than zero.


Also,

		if not InfAmmo or Reserve <= 0 or Reloading then return end
		Reloading = true
		wait(ReloadingTime)
		Reloading = false
		Reserve = Reserve - (30-Ammo)
		Ammo = MaxAmmo
		ReserveAmmo.Text = Reserve
		AmmoCounter.Text = Ammo

Looks a little neater and easier to read.


Or you can try using math.clamp, explained in this Article

Well that just makes it so that you can’t reload early, which I already figured out.

I was trying to make a solution to make sure that no matter what, early reload or not, the reserve value always stays as a positive integar. I’ll now read the article about math.clamp, thanks for that and organizing my code a little

Hold on I have to edit it a bit. I didn’t do it clearly enough…

EDIT:

  UserInputService.InputBegan:Connect(function(Input, gameFinished)
	if gameFinished then return end
	if Input.KeyCode == Enum.KeyCode.R then
		character.Humanoid:LoadAnimation(script.Parent.reload):Play()
		if not InfAmmo or Reserve <= 0 or Reloading then return end
		if Ammo ~= 30 then
			Reloading = true
			wait(ReloadingTime)
			Reloading = false
			Reserve = Reserve - (30 - Ammo)
			Ammo = MaxAmmo
			ReserveAmmo.Text = Reserve
			AmmoCounter.Text = Ammo
		end
	end
	
	while wait() do
		if buttononedown then
			while wait() do
				if not Reloading then
					if Ammo ~= 0 then
						Ammo = Ammo - 1
						AmmoCounter.Text = Ammo
						ReserveAmmo.Text = Reserve
						script.Parent.rayCast:FireServer(script.Parent.Muzzle.Position, mouse.Hit.Position, script.Parent.Eject)
						shake()
						script.Parent.Flash.Light.Enabled = true
						RunService.Stepped:Wait()
						script.Parent.Flash.Light.Enabled = false
					else
						if not InfAmmo or Reserve <= 0 then return end
						Reloading = true
						wait(ReloadingTime)
						Reloading = false
						Reserve = Reserve - (30-Ammo)
						Ammo = MaxAmmo
						ReserveAmmo.Text = Reserve
						AmmoCounter.Text = Ammo
					end
				else
					wait(0.03)
					if not buttononedown then
						break
					end
				end
			end
		end
	end
end)

What was changed from your original reply?

I see

40004040404004040044p040404004

Putting Reserve = 0 was incorrect. That was an error on my behalf. You should probably put all of your code in functions. It makes it a little neater.

You can use math.max whenever you do subtraction on the ammo. Gets rid of the need for an if statement to check if the ammo falls below 0 and it will automatically choose the larger of the numbers you pass. In this case, 0 is greater than negative, so 0 would always get selected over negative.

Variable = math.max(Variable - 1, 0)

Simple test regarding this:

for i = 5, -5, -1 do
    -- Returns the maximum between passed numbers and prints
    print(math.max(0, i))
end

0 should be printed 6 times: once when the iteration first hits 0 and 5 other times to represent the negative numbers.

4 Likes

Thanks so much for this, I’ve never used that function of math before, and I looked at a few examples and articles on how it’s used, and I used math.min to fix my issue. Thanks for introducing me to this!

1 Like