When I was working on my gun system, it worked just fine in studio. Upon testing it in a real server, however, it would create extreme server lag (the ping would go from 50 to 400). Could someone please tell me how I could optimize my code? (I would prefer if most of it could stay server-side as to prevent cheaters and to keep it simple, but if this isn’t an option, any advice is helpful.)
Server script:
local tool = script.Parent.Parent
local handle = tool.Handle
local equipped = false
local player
local character
local humanoid
--
local Range = script.Parent.Range.Value
local Damage = script.Parent.Damage.Value
local Pellets = script.Parent.PelletsPerShot.Value
local Spread = script.Parent.Spread.Value
local Type = script.Parent.Type
local cooldownTime = script.Parent.CooldownTime
local reloadTime = script.Parent.ReloadTime
local onCooldown = false
local origin = tool.Origin
local flash = origin.MuzzleFlash
local check = 0
local Reloading
local ClipAmmo = script.Parent.ClipAmmo --ammo thats in your clip currently
local MaxClip = script.Parent.MaxClip --the most amount of ammo you can have in your clip at one time
local Reserve = script.Parent.ReserveAmmo --the ammo in your pockets
local MaxReserve = script.Parent.MaxReserve ----the most amount of ammo you can have in your pockets at one time
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.IgnoreWater = true
local CSI = game:GetService("ServerStorage"):FindFirstChild("CurrentSessionInformation")
tool.Equipped:Connect(function()
equipped = true
character = script.Parent.Parent.Parent
humanoid = character:FindFirstChild("Humanoid")
player = game.Players:GetPlayerFromCharacter(character)
raycastParams.FilterDescendantsInstances = {character, tool, tool.Handle}
end)
tool.Unequipped:Connect(function()
equipped = true
end)
function TagHumanoid(enemyHum, player)
local creator_tag = Instance.new("ObjectValue")
creator_tag.Value = player
creator_tag.Name = "creator"
creator_tag.Parent = enemyHum
task.wait(0.25)
UntagHumanoid(enemyHum)
end
function UntagHumanoid(humanoid)
if humanoid ~= nil then
local tag = humanoid:findFirstChild("creator")
if tag ~= nil then
tag.Parent = nil
end
end
end
function FX()
flash.Enabled = true
task.wait(0.1)
flash.Enabled = false
end
local TipStep = false
function Reload(player)
if Reserve.Value ~= 0 then
Reloading = true
print("Reloading... (" .. player.Name .. ")")
handle.Reload:Play()
wait(reloadTime.Value)
print("Finished reloading! (" .. player.Name .. ")")
local Difference = (ClipAmmo.Value - MaxClip.Value)
ClipAmmo.Value = math.clamp(MaxClip.Value, 0, Reserve.Value)
Reserve.Value += Difference
if Reserve.Value < 0 then
Reserve.Value = 0
end
Reloading = false
else
if not TipStep then
TipStep = true
handle.DryFire:Play()
task.wait(0.25)
TipStep = false
end
end
end
function FireBullet(raycastResult)
if raycastResult then
local hitPart, hitPosition = unpack({raycastResult.Instance, raycastResult.Position})
local hashum = hitPart.Parent:FindFirstChild("Humanoid")
if hashum then
local enemyHum = hitPart.Parent.Humanoid
if hitPart.Name == ("Head") then
enemyHum:TakeDamage(Damage * 4)
else
enemyHum:TakeDamage(Damage)
end
handle.HitPlayer:Play()
local TagCoro = coroutine.create(TagHumanoid)
coroutine.resume(TagCoro, enemyHum, player)
----------------------------------------
elseif hitPart.Parent:IsA("Accessory") or hitPart.Parent:IsA("Hat") then --if you hit a hat (used for helmets to make them only deal bodyshot damage)
local enemyHum = hitPart.Parent.Parent:FindFirstChild("Humanoid")
if hitPart.Parent.Name ~= ("Shield") then
if hitPart.Parent.Name == ("Vest") or hitPart.Parent.Name == ("Armor") then
enemyHum:TakeDamage(Damage)
game.ServerStorage.ServerEventsGame.DestroyInfoPasser:Fire(hitPart) --send request to get % chance to destroy object
else
if CSI.IsLoud.Value == false then
enemyHum:TakeDamage(Damage * 4)
else
enemyHum:TakeDamage(Damage * 2)
game.ServerStorage.ServerEventsGame.DestroyInfoPasser:Fire(hitPart) --send request to get % chance to destroy object
end
end
handle.HitPlayer:Play()
local TagCoro = coroutine.create(TagHumanoid)
coroutine.resume(TagCoro, enemyHum, player)
end
----------------------------------------
elseif hitPart.Name == ("Glass") then
game.ServerStorage.ServerEventsGame.DestroyInfoPasser:Fire(hitPart) --send request to break glass
----------------------------------------
else --if you missed
handle.HitWorld:Play()
end
end
end
script.Parent.Shoot.OnServerEvent:Connect(function(Player, MousePos, OriginPos)
if not onCooldown and character:FindFirstChild("Humanoid").Health ~= 0 then
if ClipAmmo.Value ~= 0 and not Reloading then
onCooldown = true
ClipAmmo.Value = ClipAmmo.Value - 1
if check == 0 then
humanoid:LoadAnimation(script.Parent.Anim01):Play()
check = 1
elseif check == 1 then
humanoid:LoadAnimation(script.Parent.Anim02):Play()
check = 0
end
handle.Fire:Play()
local FXCoro = coroutine.create(FX)
coroutine.resume(FXCoro)
local Direction = (MousePos - OriginPos).Unit * Range
if Type.Value ~= ("Shotgun") then
local raycastResult = workspace:Raycast(OriginPos, Direction, raycastParams)
FireBullet(raycastResult)
else
for i = 1, Pellets do
local random = Random.new()
local NewDirection = ((MousePos + Vector3.new(random:NextNumber(-Spread, Spread), random:NextNumber(-Spread, Spread), random:NextNumber(-Spread, Spread))) - OriginPos).Unit * Range
local raycastResult = workspace:Raycast(OriginPos, NewDirection, raycastParams)
FireBullet(raycastResult)
end
end
task.wait(cooldownTime.Value)
onCooldown = false
else
if not Reloading then
Reload(player)
end
end
end
end)
script.Parent.Reload.OnServerEvent:Connect(function(Player)
if not Reloading and ClipAmmo.Value ~= MaxClip.Value then
Reload(player)
end
end)
print("Gun system ready! (" .. tool.Name .. ")")
LocalScript:
local player = game.Players.LocalPlayer
repeat wait(1) until player.Character
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local Mouse = player:GetMouse()
local UIS = game:GetService("UserInputService")
local Anim = script.Parent.Idle
local IdleAnim = humanoid:LoadAnimation(Anim)
local Equipped = false
local tool = script.Parent.Parent
local origin = script.Parent.Parent:WaitForChild("Origin")
local range = script.Parent.Range.Value
local damage = script.Parent.Damage.Value
local cooldownTime = script.Parent.CooldownTime.Value
local check = 0
local serverReady = true
local Firing
local ReloadConnection
tool.Equipped:Connect(function()
Equipped = true
ReloadConnection = UIS.InputBegan:connect(function(input)
if input.KeyCode == Enum.KeyCode.R then
script.Parent.Reload:FireServer()
end
end)
IdleAnim:Play()
end)
tool.Unequipped:Connect(function()
Equipped = false
Firing = false
ReloadConnection:Disconnect()
IdleAnim:Stop()
end)
local AllowedToStep = true
script.Parent.Parent.Activated:Connect(function()
Firing = true
while Firing do
if AllowedToStep then
AllowedToStep = false
local MousePosition = Mouse.Hit.p
local OriginPosition = origin.Position
script.Parent.Shoot:FireServer(MousePosition, OriginPosition)
task.wait(cooldownTime)
AllowedToStep = true
end
task.wait(0.02)
end
end)
script.Parent.Parent.Deactivated:Connect(function()
Firing = false
end)
Any help would be much appreciated!