Its old one and quite complicated but hopefully you’ll understand:
Client script (punch/damage sender)
---declaration part
local replicatedStorage = game:GetService("ReplicatedStorage")
local player = game.Players.LocalPlayer
local part = script.Parent
local combo = player.PlayerScripts.Combat.Combo
local cooldown = false
---function part
part.Touched:Connect(function(partTouched)
---checks if touched part have a parent that is player
local isPlayer = false
for _, otherPlayer in pairs(game.Players:GetChildren()) do
if otherPlayer.Name ~= player.Name then
if partTouched.Parent.Name == otherPlayer.Name then
isPlayer = true
end
end
end
---checks if player is doing punch right now
if player.PlayerScripts.Combat.LeftPunch.Value == true then
---checks if it is player
if isPlayer == true then
---checks if humanoid is not dead
if partTouched.Parent.Humanoid.Health > 0 then
---cooldown so it would not spam the player (my animation took around 0.3 secs, thats why it is 0.3)
if cooldown == false then
cooldown = true
---fire event on the server
replicatedStorage.CombatFolder.LeftPunchSentToPlayer:FireServer(partTouched.Parent, partTouched)
wait(0.3)
cooldown = false
end
end
end
end
end)
Server side (sends info about sender to the receiver)
---declaration part
local replicatedStorage = game:GetService("ReplicatedStorage")
---function part
replicatedStorage.CombatFolder.LeftPunchSentToPlayer.OnServerEvent:Connect(function(sender, receiver, partTouched)
---finds player in game.Players
local player = game.Players:WaitForChild(receiver.Name)
---fire event on the receiver
replicatedStorage.CombatFolder.LeftPunchSentToPlayer:FireClient(player, sender, partTouched)
end)
Client script (punch/damage receiver)
---declaration part
local replicatedStorage = game:GetService("ReplicatedStorage")
---bool value stored inside script
local block = script.Block
---list of parts that will be taken as valid for blocking the damage (both R6 and R15 avatar type)
local blockParts = {
"LeftHand",
"LeftLowerArm",
"LeftUpperArm",
"Left Arm",
"RightHand",
"RightLowerArm",
"RightUpperArm",
"Right Arm"
}
---function part
replicatedStorage.CombatFolder.LeftPunchSentToPlayer.OnClientEvent:Connect(function(sender, partTouched)
---checks if player is blocking, and if hit part is valid within blockParts
local didBlockDamage = false
if block.Value == true then
for _, name in pairs(blockParts) do
if partTouched.Name == name then
didBlockDamage = true
end
end
end
---fire event on the server
replicatedStorage.CombatFolder.DamageReceived:FireServer(sender, didBlockDamage, partTouched)
end)
Server side (final part)
---declaration part
local replicatedStorage = game:GetService("ReplicatedStorage")
--||--Settings--||--
--Damage player will receive
local damage = 4
--Amount of damage that will get reduced while he is blocking, and he get hit into the arms
local block = 3
--||------------||--
replicatedStorage.CombatFolder.DamageReceived.OnServerEvent:Connect(function(receiver, sender, blocked, partTouched)
---sets final damage to the total damage set in settings
local finalDamage = damage
---if player was blocking, it will reduce final damage by block amount set in settings
if blocked == true then
finalDamage -= block
end
---declaring receiver humanoid
local receiverCharacter = receiver.Character
local humanoid = receiverCharacter:WaitForChild("Humanoid")
---reducing reveicer health by final damage amount
humanoid.Health -= finalDamage
end)
This is part of my older script, there are better ways to do it like instead of using part.touched, using :GetPartsInPart(), you can check more about how to use it here: How do I use getpartsinpart()?
If you have other questions let me know.