Hey people,
I’m working on a game right now, sorta like a classic-esque roblox FPS, but I’m having an issue with my gun system.
If you pay attention to the HUD on the bottom right, you’ll see that when reloading the gun with a higher maxAmmo
will override the gun with a lower maxAmmo
after reloading. I have been at this for over an hour, and not even ChatGPT can help me.
My first thought was that I was setting the module’s ammo to my local ammo when I equipped the gun after reloading, but it wasn’t that. I added a check to detect whether or not it was the first time equipping the gun to prevent this, but it didn’t work, or wasn’t the issue.
I don’t know what’s wrong and can’t really provide a lot of context, but I think the issue is on line’s 68-77 in my tool’s local script, inside the onEquip()
function when I initialize all the values.
Suspected Section
-- Initialize gun stats (could be loaded from some config per gun)
gunStats.maxAmmo = 8
if setAmmo then
ammo = gunStats.maxAmmo
setAmmo = false
end
gunStats.ammo = ammo
gunStats.damage = 45
gunStats.firerate = 13
gunStats.isSecondary = true
gunStats.isAutomatic = false
local
local tool = script.Parent
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local camera = workspace.CurrentCamera
local replicatedStorage = game:GetService("ReplicatedStorage")
local userInputService = game:GetService("UserInputService")
local arms = workspace:WaitForChild("arms")
local shootEvent = replicatedStorage:WaitForChild("shootEvent")
local stateProperties = require(replicatedStorage:WaitForChild("stateProperties"))
local flashEffect = replicatedStorage:WaitForChild("gunFlash")
local gunStats = stateProperties.gunStats
local setAmmo = true
local mouseDown = false
local canShoot = true
local ammo = 0
local tracks = {}
local gunModel = nil
local animator = nil
local function stopAllAnimations()
for _, animation in pairs(tracks) do
animation:Stop()
end
end
local function doRecoil(recoil, recoverySpeed)
local rotationOffset = CFrame.Angles(math.rad(recoil), 0, 0)
camera.CFrame *= rotationOffset
for i = 1, recoil do
task.wait(recoverySpeed / recoil)
camera.CFrame *= CFrame.Angles(math.rad(-1), 0, 0)
end
end
local function onEquip()
-- Clear previous states if any
stopAllAnimations()
mouseDown = false
canShoot = true
-- Get animations from tool each time equipped
local animations = tool:WaitForChild("animations")
-- Set gunName based on tool name or a value (you might want to store it in a StringValue inside the tool)
local gunName = tool.Name
local gunModels = replicatedStorage:WaitForChild("gunModels")
gunModel = gunModels:WaitForChild(gunName):Clone()
gunModel.Parent = arms
arms.head.grip.Part1 = gunModel.base
arms.head.grip.C1 = CFrame.Angles(0, math.rad(180), 0)
-- Setup animator fresh each equip
animator = arms:WaitForChild("AnimationController"):WaitForChild("Animator")
-- Load animations fresh each equip
tracks = {
equip = animator:LoadAnimation(animations.equip),
hold = animator:LoadAnimation(animations.hold),
shoot = animator:LoadAnimation(animations.shoot),
reload = animator:LoadAnimation(animations:WaitForChild("reload"))
}
-- Initialize gun stats (could be loaded from some config per gun)
gunStats.maxAmmo = 8
if setAmmo then
ammo = gunStats.maxAmmo
setAmmo = false
end
gunStats.ammo = ammo
gunStats.damage = 45
gunStats.firerate = 13
gunStats.isSecondary = true
gunStats.isAutomatic = false
stateProperties.equipped = true
stopAllAnimations()
tracks.equip:Play()
task.wait(tracks.equip.Length)
if stateProperties.equipped then
tracks.hold:Play()
end
end
local function onDequip()
stateProperties.equipped = false
if gunModel then
gunModel.Parent = replicatedStorage
arms.head.grip.Part1 = nil
end
stopAllAnimations()
mouseDown = false
end
local function flash()
local flashClone = flashEffect:Clone()
flashClone.Parent = gunModel.shootPart
flashClone:Emit(4)
end
local function onActivate()
local gunStats = stateProperties.gunStats
if not gunStats.isAutomatic then
if canShoot and ammo > 0 then
canShoot = false
shootEvent:FireServer(gunModel.base.Position, gunModel.shootPart.CFrame.LookVector * 500, gunStats.damage)
ammo = ammo - 1
gunStats.ammo = ammo
flash()
doRecoil(5, 0.3)
task.wait(1 / gunStats.firerate)
canShoot = true
end
end
end
tool.Equipped:Connect(onEquip)
tool.Unequipped:Connect(onDequip)
tool.Activated:Connect(onActivate)
mouse.Button1Down:Connect(function()
mouseDown = true
local gunStats = stateProperties.gunStats
if gunStats.isAutomatic then
while mouseDown do
if stateProperties.equipped and not stateProperties.reloading and not stateProperties.sprinting and canShoot and ammo > 0 then
canShoot = false
shootEvent:FireServer(gunModel.base.Position, gunModel.shootPart.CFrame.LookVector * 500, gunStats.damage)
ammo = ammo - 1
gunStats.ammo = ammo
flash()
doRecoil(5, 0.3)
end
task.wait(1 / gunStats.firerate)
canShoot = true
end
end
end)
mouse.Button1Up:Connect(function()
mouseDown = false
end)
userInputService.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.R then
local gunStats = stateProperties.gunStats
if stateProperties.equipped and ammo < gunStats.maxAmmo and not stateProperties.reloading and not stateProperties.sprinting and not stateProperties.aiming then
tool.reload.TimePosition = 0
tool.reload:Play()
stateProperties.reloading = true
game:GetService("StarterGui"):SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
tracks.reload:Play()
task.wait(tracks.reload.Length)
tracks.reload:Stop()
ammo = gunStats.maxAmmo
gunStats.ammo = ammo
stateProperties.reloading = false
game:GetService("StarterGui"):SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, true)
end
end
end)
Here’s the moduleScript I store the value’s in.
stateProperties
local stateProperties = {
equipped = false,
aiming = false,
sprinting = false,
reloading = false,
gunStats = {
ammo = 0,
maxAmmo = 0,
damage = 0,
isSecondary = false,
isAutomatic = false,
firerate = 0
}
}
return stateProperties
Any help would be extremely appreciated. If any more details are necessary, I’ll provide them.