Need feedback for my combat system code

[Code review request] Need feedback for my combat system code

Hi everyone,
I’m new to game development and working on the Combat System. I would greatly appreciate it if experienced developers could review my code and give feedback. Your insights will help me improve and learn best practices.

Best regards,
thanhgamer091206

Ragdoll module:

Game Link:

Local script:

-- [[ services ]] --
local players = game:GetService('Players')
local userinput_service = game:GetService('UserInputService')
local replicated_storage = game:GetService('ReplicatedStorage')
local runservice = game:GetService('RunService')

-- [[ varibles ]] --
local tool = script.Parent
local remote_event = script.Parent:WaitForChild('RemoteEvent')
local local_player = players.LocalPlayer
local character = local_player.Character or local_player.CharacterAdded:Wait()
local animations = replicated_storage:WaitForChild('animations')

local boolean = false
local attacking = false
local action = ''
local combo = 0
local combo_timer = tick()

-- [[ functions ]] --
local function check(character, propertise)
	for _, v in pairs(propertise) do
		if character:FindFirstChild(v) then
			return true
		end
	end

	return false
end

-- [[ main ]] --
tool.Equipped:Connect(function()
	boolean = true
	remote_event:FireServer('equip', true)
end)

tool.Unequipped:Connect(function()
	boolean = false
	remote_event:FireServer('equip', false)
end)

local delay_test = tick()
userinput_service.InputBegan:Connect(function(input, is_typing)
	if is_typing or boolean == false or attacking == true or check(character, {'action', 'stun', 'block'}) then return end
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		print(tick() - delay_test)
		if tick() - combo_timer >= 2 then
			combo = 0
		end
		
		if combo >= 5 then
			combo = 0
		end
		
		action = 'm1'
		combo += 1
		combo_timer = tick()
		
		remote_event:FireServer('m1', combo)
	end
	
	if input.KeyCode == Enum.KeyCode.F then
		remote_event:FireServer('block', true)
	end
end)

userinput_service.InputEnded:Connect(function(input, is_typing)
	if is_typing or boolean == false or attacking == true then return end
	
	if input.KeyCode == Enum.KeyCode.F then
		remote_event:FireServer('block', false)
	end
end)

remote_event.OnClientEvent:Connect(function(command, ...)
	if command == 'attack' then
		if attacking == true then return end
		action = 'm1'
		attacking = true
		local animation_name = select(1, ...)
		local track = character.Humanoid:LoadAnimation(animations:FindFirstChild(animation_name))
		track:Play()
		track:AdjustSpeed(1.25)
		track.Stopped:Once(function()
			track:Destroy()
		end)
		wait(.5)
		attacking = false
		action = ''
	end
	
	if command == 'block' then
		action = 'block'
		local track = character.Humanoid:LoadAnimation(animations:FindFirstChild('block'))
		track:Play()
		
		while character:FindFirstChild('block') do
			wait()
		end
		
		track:Stop()
		track:Destroy()
		action = ''
	end
end)

runservice.RenderStepped:Connect(function()
	local speedrun = 18
	local jump = 50
	
	if action == 'm1' then
		speedrun = 8
		jump = 0
	end
	
	if action == 'block' then
		speedrun = 8
	end
	
	character.Humanoid.WalkSpeed = math.max(0, speedrun)
	character.Humanoid.JumpHeight = math.max(0, jump)
end)

Script in tool:

-- [[ services ]] --
local server_storage = game:GetService('ServerStorage')
local replicated_storage = game:GetService('ReplicatedStorage')

-- [[ varibles ]] --
local remote_event = script.Parent:WaitForChild('RemoteEvent')
local hitbox_module = require(server_storage:WaitForChild('hitbox_module'))
local bindable_event = replicated_storage:WaitForChild('Damage')
local effect_event = replicated_storage:WaitForChild('effect')

local boolean = false
local cache = {}

-- [[ functions ]] --
local function check(character, propertise)
	for _, v in pairs(propertise) do
		if character:FindFirstChild(v) then
			return true
		end
	end
	
	return false
end
-- [[ main ]] --
remote_event.OnServerEvent:Connect(function(player, command, ...)	
	local character = player.Character
	if command == 'equip' then
		local is_equip = select(1, ...)
		if type(is_equip) ~= 'boolean' then player:Kick('WTF ??') end
		boolean = is_equip
	else
		if boolean == false then player:Kick('SPOOF ?') end
		if boolean == true and not character:FindFirstChildWhichIsA('Tool') then player:Kick('SPOOF ?') end
	end
	
	if command == 'm1' then
		if check(character, {'action', 'stun', 'block'}) then return end
		local combo = select(1, ...)
		
		remote_event:FireClient(player, 'attack', 'hit'..combo)
		wait(0.25)
		
		hitbox_module.validate_hit(character, Vector3.new(5, 5, 3), CFrame.new(0, 0, -4), {
			damage = 1.25,
			type = 'classic',
			combo = combo
		})
		
		if combo == 5 then
			local flag = Instance.new('BoolValue')
			flag.Parent = character
			flag.Name = 'action'
			game.Debris:AddItem(flag, .75)
		end
	end
	
	if command == 'block' then
		if check(character, {'action', 'stun'}) then return end	
		local is_blocking = select(1, ...)
		if type(is_blocking) ~= 'boolean' then player:Kick('WTF ??') end

		if is_blocking == true then
			local flag = Instance.new('IntValue')
			flag.Parent = player.Character
			flag.Name = 'block'
			flag.Value = 5
			
			remote_event:FireClient(player, 'block', is_blocking)
		else
			if character:FindFirstChild('block') then
				character:FindFirstChild('block'):Destroy()
			end
		end
	end
end)

Server script:

-- [[ services ]] --
local replicated_storage = game:GetService('ReplicatedStorage')
local server_storage = game:GetService('ServerStorage')
local player_service = game:GetService('Players')

-- [[ varibles ]] --
local bindable_event = replicated_storage:WaitForChild('Damage')
local effect_event = replicated_storage:WaitForChild('effect')
local ragdoll_module = require(script.Parent.R6Ragdoll.ModuleScript)

-- [[ main ]] --
player_service.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		repeat
			character.Parent = workspace.characters
			wait()
		until character.Parent == workspace.characters
	end)
	
	player.CharacterRemoving:Connect(function(character)
		character:Destroy()
	end)
end)

player_service.PlayerRemoving:Connect(function(player)
	player:Destroy()
end)

workspace.characters.ChildAdded:Connect(function(obj)
	ragdoll_module:Setup(obj)
end)

bindable_event.Event:Connect(function(player_character, target_character, humanoid, propertise)
	local player = player_service:GetPlayerFromCharacter(target_character)
	if humanoid ~= target_character.Humanoid then
		player:Kick('SPOOF ???')
	end
	
	if target_character:FindFirstChild('ragdoll') then
		return
	end
	
	if propertise.block and propertise.block.Value > 0 then
		effect_event:FireAllClients('m1', 'block', target_character, propertise)
		propertise.block.Value -= 1
		if propertise.block.Value == 0 then
			propertise.block:Destroy()
		else
			return
		end
	end
	
	local stun_flag = Instance.new('BodyGyro')
	stun_flag.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
	stun_flag.CFrame = target_character.HumanoidRootPart.CFrame
	stun_flag.Name = 'stun'
	stun_flag.Parent = target_character.HumanoidRootPart
	game.Debris:AddItem(stun_flag, 0.25)
	
	if propertise.combo >= 5 then
		stun_flag:Destroy()
		
		local ragdoll_flag = Instance.new('BoolValue')
		ragdoll_flag.Name = 'ragdoll'
		ragdoll_flag.Parent = target_character
		game.Debris:AddItem(ragdoll_flag, 2)
		
		local body_vec = Instance.new('BodyVelocity')
		body_vec.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
		body_vec.Velocity = player_character.HumanoidRootPart.CFrame.LookVector * 40
		body_vec.Parent = target_character.HumanoidRootPart
		game.Debris:AddItem(body_vec, 0.1)
		
		target_character.RagdollTrigger.Value = true
		delay(2, function()
			target_character.RagdollTrigger.Value = false
		end)
	end
	
	effect_event:FireAllClients('m1', 'hit', target_character, propertise)
	humanoid:TakeDamage(propertise.damage)
end)

for _, v in pairs(workspace.characters:GetChildren()) do
	ragdoll_module:Setup(v)
end