Hello, I’m making a melee system using Raycast Hitbox Module from TeamSwordphin.
Right now, My script is handling the cooldown in the local script with no actual sanity check in server.
I thought it would be vulnerable to exploit, So i wanted to make a server check for a cooldown.
If i completely handle cooldown on server, Player would be able to play animation in any condition, Which i don’t want it to be.
I want idea of what kind of method should i use to implement it.
Local Script:
local raycastHitbox = require(game.ReplicatedStorage:WaitForChild("RaycastHitboxV4"))
local tool = script.Parent
local handle = tool:WaitForChild("Handle")
local player = game.Players.LocalPlayer
local char = player.Character
if not char or not char.Parent then
char = player.CharacterAdded:Wait()
end
local hum = char:WaitForChild("Humanoid")
local remoteEvent = tool:WaitForChild("RemoteEvent")
local cdTime = 1
local lastUseTime = 0
local step = 1
local hitbox
local hitWait
local swingSFX = handle:WaitForChild("Swing")
local equipSFX = handle:WaitForChild("Equip")
local idleAnim = hum:LoadAnimation(script:WaitForChild("Idle"))
local attack1Anim = hum:LoadAnimation(script:WaitForChild("Attack1"))
local attack2Anim = hum:LoadAnimation(script:WaitForChild("Attack2"))
local equipAnim = hum:LoadAnimation(script:WaitForChild("Equip"))
tool.Activated:Connect(function()
if hum.Health > 0 and not equipAnim.IsPlaying then
local currentTime = os.clock()
if currentTime - lastUseTime >= cdTime then
lastUseTime = currentTime
if step == 1 then
attack1Anim:Play()
step = 2
elseif step == 2 then
attack2Anim:Play()
step = 1
end
swingSFX:Play()
local params = RaycastParams.new()
params.FilterDescendantsInstances = {char}
params.FilterType = Enum.RaycastFilterType.Exclude
hitbox = raycastHitbox.new(handle)
hitbox.RaycastParams = params
hitbox.OnHit:Connect(function(hit, victimHum)
remoteEvent:FireServer(hit, victimHum)
end)
hitbox:HitStart()
hitWait = task.delay(0.5, function()
hitbox:HitStop()
end)
end
end
end)
tool.Equipped:Connect(function()
idleAnim:Play()
equipAnim:Play()
equipSFX:Play()
end)
tool.Unequipped:Connect(function()
if hitbox then
hitbox:HitStop()
if hitWait then
task.cancel(hitWait)
end
end
swingSFX:Stop()
equipSFX:Stop()
if idleAnim then
idleAnim:Stop()
end
if attack1Anim then
attack1Anim:Stop()
end
if attack2Anim then
attack2Anim:Stop()
end
if equipAnim then
equipAnim:Stop()
end
end)
Server Script:
local debris = game:GetService("Debris")
local serverscriptservice = game:GetService("ServerScriptService")
local replicatedstorage = game:GetService("ReplicatedStorage")
local tool = script.Parent
local handle = tool.Handle
local remoteEvent = tool.RemoteEvent
local hitSFX = handle.Hit
local config = {
Damage = 57,
MagnitudeRange = 15,
}
remoteEvent.OnServerEvent:Connect(function(player, hit, victimHum)
local char = player.Character or player.CharacterAdded:Wait()
local hum = char.Humanoid
local victimChar = victimHum.Parent
if victimHum.Health > 0 then
local magnitude = (char.HumanoidRootPart.Position - victimChar.HumanoidRootPart.Position).Magnitude
if magnitude <= config.MagnitudeRange then
victimHum:TakeDamage(config.Damage)
hitSFX:Play()
if not victimHum:FindFirstChild("creator") then
local creator = Instance.new("ObjectValue")
creator.Name = "creator"
creator.Value = player
debris:AddItem(creator,5)
creator.Parent = victimHum
end
local bloodEffect = replicatedstorage.Miscs.BloodEffect.Blood:Clone()
if char:FindFirstChild("Torso") then
bloodEffect.Parent = victimChar.Torso
else
bloodEffect.Parent = victimChar.UpperTorso
end
debris:AddItem(bloodEffect, 0.5)
else
warn("Too far to give damage.")
end
end
end)