I’m working on a gun right now and I’m currently wondering what the best way to handle fire-rate is? Ideally I wanna handle it on the server but I’m not sure how the client-side would work for that.
Here is an example of code, where you can use debounce on the server side:
local Players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local gunRange = 500
local HeadShotMulti = 2 -- Change on your discression
local Debounce = 0.3 -- Change for the amount of time inbetween shots
local DebounceTable= {}
Players.PlayerAdded:Connect(function(Player)
if not DebounceTable[Player] then
DebounceTable[Player] = false
end
end)
Players.PlayerRemoving:Connect(function(Player)
if DebounceTable[Player] then
DebounceTable[Player] = nil
end
end)
replicatedStorage.Shoot.OnServerEvent:Connect(function(Player, MousePosition, Target)
if not DebounceTable[Player] then
DebounceTable[Player] = true
local Gun = Player.Character:FindFirstChildOfClass("Tool")
if Gun == nil then return end
local Damage = Gun.Damage.Value
local Direction = (MousePosition- Gun.Handle.Position) * gunRange
local RayParams = RaycastParams.new()
RayParams.FilterDescendantsInstances = {Player.Character}
RayParams.FilterType = Enum.RaycastFilterType.Exclude
local Result = workspace:Raycast(Gun.Handle.Position, Direction, RayParams)
local Bullet = replicatedStorage.Bullet:Clone()
Bullet.CFrame = Gun.Handle.CFrame
Bullet.Parent = workspace
local BulletDuration = 0.3 * ((Direction/gunRange).Magnitude)/50
TweenService:Create(Bullet, TweenInfo.new(BulletDuration), {CFrame = CFrame.new(MousePosition)}):Play()
if not Target then
task.delay(BulletDuration, function()
Bullet:Destroy()
end)
else
task.delay(1, function()
Bullet:Destroy()
end)
end
task.delay(Debounce, function()
if DebounceTable[Player] then
DebounceTable[Player] = false
end
end)
if Result == nil then return end
local Humanoid = Result.Instance.Parent:FindFirstChild("Humanoid")
if Humanoid == nil then return end
task.wait(BulletDuration)
if Result.Instance.Name == "Head" then
Humanoid.Health -= Damage * HeadShotMulti
else
Humanoid.Health -= Damage
end
end
end)
Server would be your best bet when handling verification/validation such at this. You could measure the tick() and the tick() when the player shot. If it exceeds your RPM then you invalidate the shot, if it does not then you continue with your code.