How should I do this?

I’m using Raycast Hitbox 4.01 for my sword, the cooldown for the sword is an attribute, and the animation needs to be completed to strike again. The issue with it is that to save memory I want to use the function HitStop() which stops the hitbox from working after the animation is played. The issue with this is that the animation is played on the client so I can’t track if it is completed or not.

How should I go about doing this?

Local Script

local player = game.Players.LocalPlayer
local tool = script.Parent

local remoteEvent = tool:WaitForChild("HitDetection")

local char = player.Character
local humanoid = char:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")

local slashAnimation1 = Instance.new("Animation")
slashAnimation1.AnimationId = "rbxassetid://15699217139"

local slashAnimation2 = Instance.new("Animation")
slashAnimation2.AnimationId = "rbxassetid://15699432438"

local cooldown = false
local swingSpeed = tool:GetAttribute("swingSpeed")

tool.Activated:Connect(function()
	if not cooldown then
		cooldown = true
		
		local randomAttack = math.random(1, 2)
		
		local anim
		if randomAttack == 1 then -- slash1
			anim = animator:LoadAnimation(slashAnimation1)
			anim:Play()
			
			remoteEvent:FireServer(randomAttack)
		elseif randomAttack == 2 then
			anim = animator:LoadAnimation(slashAnimation2)
			anim:Play()

			remoteEvent:FireServer(randomAttack)
		end
		
		anim.Stopped:Wait()
		task.wait(swingSpeed)

		cooldown = false
	end
end)

Server Script

local tool = script.Parent
local handle = tool:WaitForChild("Handle")
local char = tool.Parent

local remoteEvent = tool:WaitForChild("HitDetection")
local replicatedStorage = game:GetService("ReplicatedStorage")
local raycastHitboxModule = require(replicatedStorage:WaitForChild("RaycastHitboxV4"))

local hitBox = raycastHitboxModule.new(handle)
hitBox.RaycastParams = RaycastParams.new()
hitBox.RaycastParams.FilterDescendantsInstances = {char}
hitBox.RaycastParams.FilterType = Enum.RaycastFilterType.Exclude

local damage = 17
local lungeDamage = 30

local connection
remoteEvent.OnServerEvent:Connect(function(player, attackType)
	hitBox:HitStart()
	
	char = tool.Parent
	hitBox.RaycastParams = RaycastParams.new()
	hitBox.RaycastParams.FilterDescendantsInstances = {char}
	hitBox.RaycastParams.FilterType = Enum.RaycastFilterType.Exclude
	
	connection = hitBox.OnHit:Connect(function(hit, humanoid)
		print(attackType)
		if attackType == 1 then
			humanoid:TakeDamage(damage)
		elseif attackType == 2 then
			humanoid:TakeDamage(damage)
		end
		
		hitBox:HitStop()
	end)
end)
2 Likes

First of all, why would you even need to control hitbox via server?
And second, use remote to stop hitbox

Erm, because I don’t want it to be exploitable?

So use two remotes? Are you sure there is no other alternatives? I don’t want to take up to much memory.

I highly suggest detecting hits on the client and then verifying the hit on the server to prevent exploits. If your hitbox is on the server, landing hits will feel laggy and inaccurate.

1 Like

Everything is exploitable. Don’t try to make your “anti-exploit” thing perfect, it’ll just do more problems on the player side.
You can use 1 remote and just send different information, like remote:FireServer(“Stop”) or remote:FireServer(“Start”) and then remote.OnServerEvent(player, hitboxState) if hitboxState == “Start” then hitbox:HitStart() and etc. you get it

2 Likes

How should I do this with the current model I have?

Alright, so I called the function on the client instead of the server but I keep getting this error.

  07:56:55.900  Workspace.Swords.Linked Sword.Functionality:20: attempt to call missing method 'Connect' of table  -  Server - Functionality:20
  07:56:55.900  Stack Begin  -  Studio
  07:56:55.900  Script 'Workspace.Swords.Linked Sword.Functionality', Line 20  -  Studio - Functionality:20
  07:56:55.900  Stack End  -  Studio

Server

local connection
remoteEvent.OnServerEvent:Connect(function(player, attackType, hitBox)
	char = tool.Parent
	hitBox.RaycastParams = RaycastParams.new()
	hitBox.RaycastParams.FilterDescendantsInstances = {char}
	hitBox.RaycastParams.FilterType = Enum.RaycastFilterType.Exclude
	
	connection = hitBox.OnHit:Connect(function(hit, humanoid)
		if attackType == 1 then
			humanoid:TakeDamage(damage)
		elseif attackType == 2 then
			humanoid:TakeDamage(damage)
		end
		
		hitBox:HitStop()
	end)
end)

Client

local replicatedStorage = game:GetService("ReplicatedStorage")
local raycastHitboxModule = require(replicatedStorage:WaitForChild("RaycastHitboxV4"))

local hitBox = raycastHitboxModule.new(handle)
hitBox.RaycastParams = RaycastParams.new()
hitBox.RaycastParams.FilterDescendantsInstances = {char}
hitBox.RaycastParams.FilterType = Enum.RaycastFilterType.Exclude

tool.Activated:Connect(function()
	if not cooldown then
		cooldown = true
		
		local randomAttack = math.random(1, 2)
		
		local anim
		if randomAttack == 1 then -- slash1
			hitBox:HitStart()
			
			anim = animator:LoadAnimation(slashAnimation1)
			anim:Play()
			
			remoteEvent:FireServer(randomAttack, hitBox)
		elseif randomAttack == 2 then
			hitBox:HitStart()
			
			anim = animator:LoadAnimation(slashAnimation2)
			anim:Play()

			remoteEvent:FireServer(randomAttack, hitBox)
		end
		
		anim.Stopped:Wait()
		task.wait(swingSpeed)

		cooldown = false
	end
end)

Why are you trying to send required module by client to server???

If you know how the module works, that’s the only way I can explain it, also I’m not sending “the module” to the server I’m sending the hitbox to the server. I’m managing it on the client but after I fire the remote event the server actually manages hit calculations.

You are totally sending a module function that is required on the client. Maybe you should try learning modules and remotes a bit more? Otherwise my help is gonna be worthless.

If you want lagless normal hitbox, control it on client side.
If you want less exploitable hitbox, control it on the client side and check the distance between hit and part it hit.
If you want crappy laggy but non exploitable hitbox, control it on the server side.

In your script i see that you’re for some reason trying to control your hitbox on client and server side at the same time, tell me for what?

2 Likes

If you still want to continue using RaycastHitbox, I suggest you remove any calling signal for RaycastHitbox as it is server-sided, as for your problem what I did was:

  1. Play the animation and hitbox start (server only)
  2. Validate if the player has the weapon equipped (precautionary check)
  3. If the animation has stopped (a special wait, then disable hitbox by firing a RemoteEvent)
1 Like

So would this give the client full control over the hitbox system? If it does give them any control, I didn’t realize this before but thanks for letting me know.

Instead of doing that, should I require it in the server script, use a remote function to start the hitbox on the client, and then on the server check if the hitbox detected any character model?

My goal was to have the hitbox on the client so that it wouldn’t cause a lot of server lag, then I would detect if it was hit on the server.

This is what I was attempting to go for but I’m not really sure how to execute it properly

What’s a calling signal?

So both should be activated on the server?

Ah sorry my wording is not clear, I was just saying any reference to RaycastHitbox on the client even a signal should be removed as it’s only server-sided.

No what I mean here is that you play the animation on the client and fire an event that triggers hitbox start signal on the server, after the animation has stopped by using AnimationTrack.Stopped:Wait(), simply fire an event that disables this by using the hit stop signal.

Hopefully that clears my confusing words.

1 Like

That was much easier to digest! Though… the last time I tried controlling it on the server the hitbox visualized was a bit off from the attachments on the sword.

Is there any way I can solve this issue? The game may be laggy at times anyway due to you exploding a lot of parts in different maps.

bumping this because I still haven’t found a solution…