So, everything is done on stage 3, the creation of the projectile and all that is done at stage 3, the first stage is simply the client telling the server “hey I want to shoot a bullet”, the second stage is where I want to put some sanity checks to see if the player is allowed to shoot.
Implement a server-sided debounce via attributes on the character/weapon, depends on the way your game is
if character:GetAttribute("ShootDebounce") then
return
end
character:SetAttribute("ShootDebounce", true)
-- // do the projectile logic
task.delay(0.1, character.SetAttribute, character, "ShootDebounce")
If there is a limited amount of ammo, implement the check on the server to prevent exploiters firing projectiles without any limits
-- Let's say the character has an attribute "Bullets" and it's set to 30
local bullets = character:GetAttribute("Bullets")
if bullets <= 0 then
return
end
character:SetAttribute("Bullets", bullets - 1)