So after my post about asking for scripting advice, I’ve teamed up with one of my friend for a small prototype project and we’ve created a lot of very interesting thing. Although, there is one particular problem that we can’t seem to understand, as the output says nothing of it…
Now, what’s happening here is that the ammo in the gun is behaving very weirdly… Every time I re-equip the gun and fire, it consumes an additional ammo for every re-equip. We’ve been scrambling for a bit and have yet to find out about what caused this issue to occur as we can’t properly find any posts about it, yet.
We need help identifying the cause of this issue and to make the gun work properly.
(The Discord ping sound is from the video background, sorry about that…)
This is the coding inside of the gun’s model, named MainScript.
local maxAmmo = 10
local ammo = maxAmmo
local reloading = false
local plr = game.Players.LocalPlayer
local plrgui = plr:WaitForChild("PlayerGui")
local text = plrgui:WaitForChild("Ammo"):FindFirstChild("AmmoCount")
script.Parent.Equipped:Connect(function(Mouse)
-- reloading
local function reload()
script.Parent.ReloadAudio:Play()
reloading = true
wait(1.5)
-- reload time
ammo = maxAmmo
reloading = false
end
-- shooting
script.Parent.Activated:Connect(function()
-- checks if there's ammo to shoot/First Condition Check
if ammo > 0 and not reloading then
ammo = ammo - 1
script.Parent.ShootingAudio:Play()
-- first humanoid hit takes damage
if Mouse.Target.Parent:FindFirstChild("Humanoid") then
script.Parent.DealDamage:FireServer(Mouse.Target.Parent, 25)
end
-- if there's no ammo, auto reload/Second Condition Check
elseif reloading == false then
reload()
script.Parent.ShootingAudio:Stop()
end
-- ammo display
while wait() do
text.Text = (ammo).." / "..maxAmmo
end
end)
-- Reload Input, Check if not reloading
local input = game:GetService("UserInputService")
input.InputBegan:Connect(function(Key)
if Key.KeyCode == Enum.KeyCode.R and reloading == false and ammo ~= maxAmmo then
reload()
end
end)
end)
-- Let's break this script down so you understand everything that is happening here!
--- Services ---
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
--[[
It's recommended to use the full names' of services, so it's easier to understand what it is.
Example:
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
...
]]
--- Variables ---
local maxAmmo = 10
local reloading = false
local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")
local AmmoCount = PlayerGui:WaitForChild("Ammo"):FindFirstChild("AmmoCount")
local weapon = script.Parent
local mouse = LocalPlayer:GetMouse()
--[[
Remember to also use the full name of the variable, so it's easier to understand what it is.
Don't go around and do "plr". You can simply use tab, and it will autocomplete the variable name.
No one is stopping you from using a few bytes less of memory, though.
Just keep the variable names simple and easy to understand.
]]
local ammo = Instance.new("IntValue")
ammo.Name = "Ammo"
ammo.Value = maxAmmo
ammo.Parent = weapon
-- We can use an IntValue for this, you'll see why later.
--- Functions ---
local function reloadWeapon()
if reloading then return end
-- If the weapon is already reloading, then we don't want to reload it again.
reloading = true
weapon.ReloadAudio:Play()
task.delay(1.5, function()
-- task.delay() is a better alternative to wait().
ammo.Value = maxAmmo
reloading = false
end)
end
local function shootWeapon()
if reloading then return end
ammo.Value -= 1
weapon.ShootingAudio:Play()
if not mouse.Target then return end
-- If the weapon is not hitting anything, then we don't want to do anything.
local humanoid = mouse.Target.Parent:FindFirstChild("Humanoid")
if humanoid then
-- If the weapon is hitting a humanoid, then we want to deal damage to it.
weapon.DealDamage:FireServer(humanoid.Parent, 25)
end
end
local function weaponEquipped()
local reloadConnection = UserInputService.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.R and ammo.Value < maxAmmo then
-- There's no need to check if the weapon is reloading, because we already do that in the reloadWeapon() function.
reloadWeapon()
end
end)
local shootConnection = weapon.Activated:Connect(shootWeapon)
local disconnect
disconnect = weapon.Unequipped:Connect(function()
reloadConnection:Disconnect()
shootConnection:Disconnect()
disconnect:Disconnect()
end)
end
weapon.Equipped:Connect(weaponEquipped)
ammo:GetPropertyChangedSignal("Value"):Connect(function()
AmmoCount.Text = ammo.Value .." / ".. maxAmmo
if ammo.Value == 0 then
reloadWeapon()
end
--[[
We can use GetPropertyChangedSignal() to check if the ammo value has changed.
If the ammo value has changed, then we want to update the ammo count.
If the ammo value is 0, then we want to reload the weapon
]]
end)
Also, here’s a few recommendations:
Don’t put connections inside other connections, especially if you’re not disconnecting them! This causes a memory leak.
Use task.wait() instead of wait(). Wait is (probably) deprecated, much slower and yields the entire script.
The script is working absolutely perfect! I appreciate your thorough help and advices from the last post and this one. Thank you for your quick respond and helpful work.