Before anything, i’d like to say that i’ve been reading about exploiters for a few hours and i still haven’t found a foolproof solution to the problem. The general consensus seems to be that you shouldn’t trust your client at all, making the server do sanity checks whenever you get info from the client. With that in mind, i’ve attempted to create a simple script (with as little involvement with the client as possible) that makes the Player Character play a punch animation, and create a hitbox to detect hits, them damage anyone who might have been struck.
However i’ve run into a few roadblocks in the way, those being the fact that trying to do animations and hitboxes in the server isn’t really optimal, the animation are often late and the hitbox lags behind the character. So i’ve decided that i’d keep my original script, but change only those two parts to the client side.
I’m fully aware that i might having the wrong approach to the problem, so if you have a better suggestion, i’m willing to change.
--I removed most of the script that was irrelevant
local Cooldown
local CombatTool = script.Parent
local Player = CombatTool.Parent.Parent
local Character = Player.Character
local Animator = Character.Humanoid.Animator
-- Let's pretend the PlayerDamage is 10
local Damage = 10
local RayParams = RaycastParams.new()
RayParams.FilterDescendantsInstances = {Character}
RayParams.FilterType = Enum.RaycastFilterType.Blacklist
local Clicked = function()
if not Cooldown then
Cooldown = true
--Firing Remote Function that plays the animation in the client, it works as intended
AnimationClient:FireClient(Player,Animator,script.Animation)
--Another Remote Function that activates the Hitbox in the Client
RayHitBoxClient:FireClient(Player,Character.RightHand,1,RayParams,Damage)
wait(1)
Cooldown = false
end
end
CombatTool.Activated:Connect(Clicked)
-- Local script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Player = game:GetService("Players").LocalPlayer
-- I'm using Raycast Hitbox V4.01 for this, it works as intended
local RayHitbox = require(ReplicatedStorage.Modules.RaycastHitboxV4)
ReplicatedStorage.CheckHitbox.OnClientEvent:Connect(function(Part,Duration,Param,Damage)
local NewHitbox = RayHitBox.new(Part)
NewHitbox.RaycastParams = Param
NewHitbox.OnHit:Connect(function(Hit,Humanoid)
if Human then
-- I was thinking of Firing a remote event to the server, something like
ReplicatedStorage.DealDamage:FireServer(Hit,Humanoid,Damage)
end
end)
NewHitbox:HitStart()
wait(Duration)
NewHitbox:HitStop()
end)
-- Final Server Script
game:GetService("ReplicatedStorage").DealDamage.OnServerEvent:Connect(function(PLAYER,HIT,HUMAN,DAMAGE)
--Uh oh
end
-
This is the dreaded moment that i’ve been trying to avoid, so i have a few questions:
-
Can the client lie about the PLAYER parameter? Pretending to be another player? If they can, is there a way to check if they’re lying?
-
I’m already aware that the parameter HIT and HUMANOID are unreliable, but, if i have a correct PLAYER (As mentioned above, i dont know if i do) then i can get the Player.Character ( and by extension, the Humanoid ) and check the distance between HIT and the player character to check if it’s legit.
-
However i dont have a way to know that the variable DAMAGE is legit. Yes i could calculate the damage in the third script, instead of the first, but the problem is that the damage formula would probably look something like (BaseDamage * PlayerStat * Multipliers), which means i need to have the correct BaseDamage, which i can only get on the first script, since it’s the punching script.
Sorry for so many probably dumb questions but there is some stuff here i cant wrap my head around and i’d appreciate the help.