How do I make an exploiter-proof custom health system?

I want the player to have a death animation and sequence when they die, however, when the humanoid’s health property reaches 0, it kills the player and they respawn within seconds, so I can’t really make the death sequence work with that. My solution is to make an IntValue in every character to work as their health value, and to fire a RemoteEvent to decrease the value by a certain amount when the player is hit by another player. From my understanding, exploiters can simply fire that RemoteEvent whenever and pass any player as an argument and kill them. How can I make this more secure?

2 Likes

You can add a debounce on the server so the exploiter can’t fire the event repeatedly. For example:

local debounce = false
RemoteEvent:OnServerEvent:Connect(function()
if debounce == false then
--minus health
debounce = true
wait(0.5)
debounce = false
end
end)

I should have mentioned that the RemoteEvent has two arguments, one being the player taking damage, and the other is the amount of damage. I’m not sure a debounce would help with this, considering potential exploiters could fire the RemoteEvent once and pass the damage argument as 100 and instantly kill someone.

1 Like

Greetings, I don’t suggest you using a remote to edit the health, you could however disable the automatic player respawn so that you can implement a fully serverside script that creates joints on arms and legs to keep te body intact and to play the animation and then simply respawn the player by using :LoadCharacter()

I’ve heard that reviving the player like that can cause some problems like messing up the camera and movement. Any other suggestions?

Umh, It doesn’t, :LoadCharacter() is the same thing that roblox uses to respawn the character.

This system should not be handled by the client whatsoever and should be handled entirely by the server otherwise you’ll never be able to fully secure it and your game will have some glaring issues with health. You could also just use the Players.RespawnTime and Players.CharacterAutoLoads property to edit the amount of time before a respawn or if the player respawns automatically (and if you don’t want them to respawn automatically you can handle it yourself with Player:LoadCharacter() as stated above.)

Generally though, this type of thing should not be managed by the client whatsoever and the client should not have any say in changing these values otherwise it’s incredibly easy to abuse and exploit to create infinite health scripts or other things of the such.

1 Like

How would I make it work on the server?

Start by creating a server script called “Health” (to replace the regular one) inside StarterCharacterScripts within StarterPlayer.
You can utilize a .Changed event on the intvalue to handle death and other such things. Here’s a quick little example:

local int = --the intvalue
local max = --positive number describing the maximum health of the character, could also be an intvalue or numbervalue to allow for more flexibility
local char = script.Parent --character will be parent when game starts if in startercharacterscripts
local hum = --the humanoid
int.Changed:connect(function()
	if hum.Health <= 0 then int.Value = 0 return end --if humanoid is already dead, set value to zero and stop current reaction to change by returning
	int.Value = math.clamp(int.Value,0,max) --keep value within 0 and max, prevent it from going negative or above the maximum value
	if int.Value <= 0 then 
		char:BreakJoints() --or hum.Health = 0
		return --if the value is zero or negative, kill the character and stop the current response
	end
end)

May be a bit inefficient although I’m not sure. Try to learn from this rather than just copying it down and being done with it.

You can also take a look at the base server script containing the code for the Humanoid’s health regeneration for this as a neat little example of how you could create health regeneration with this value.

-- Gradually regenerates the Humanoid's Health over time.

local REGEN_RATE = 1/100 -- Regenerate this fraction of MaxHealth per second.
local REGEN_STEP = 1 -- Wait this long between each regeneration step.

--------------------------------------------------------------------------------

local Character = script.Parent
local Humanoid = Character:WaitForChild'Humanoid'

--------------------------------------------------------------------------------

while true do
	while Humanoid.Health < Humanoid.MaxHealth do
		local dt = wait(REGEN_STEP)
		local dh = dt*REGEN_RATE*Humanoid.MaxHealth
		Humanoid.Health = math.min(Humanoid.Health + dh, Humanoid.MaxHealth)
	end
	Humanoid.HealthChanged:Wait()
end
1 Like

Thanks! How should I change the IntValue, though?

Why are you trusting the client to handle any damaging anyway?

There is no way you can’t control damage on the server and you absolutely should make the switch.

You can change the IntValue by referencing the .Value property of the object.

1 Like