ClientCast - A Client-based, Idiosyncratic Hitbox System!

Hi! just a note - I’ve changed my GitHub username, which broke existing links to e.g. the wiki & API pages. The links are just pyseph.github.io/ClientCast now, and have since already been updated on this DevForum thread.

how would you perform a hitbox backtrack

Any idea how I would use this module actually on the client. Trying to use some hitboxes only on the client side, not worried about cheating as this game is singleplayer.

Trying to set the hitbox to the one in the viewmodel, but cant do it as it errors when the module is ran on the client.

(I’ve tried using Swordphins module for this too but it doesn’t work right and I really would rather use it because its never maintained and is super inconsistent)

This module is meant to automate client-server communication; it should still be used from the server. It does run the hitboxes on the client, however that is behind-the-scenes and not controllable by the player.

If you want to run hitboxes completely on the client, you should create your own module for this - as it’s just stopping/starting raycasts from an object.

Hallo Pyseph, I’ve got a question.

When you use ClientCast.new() and store it in a variable, that would be the only one variable to cast the player’s weapon. Then store it in a server table so the player can access it. You would do this for each players’ weapons.

Do you recommend a better or much optimal way of doing this?

Danke in advance!

2 Likes

It is better to re-use the same caster object for the same weapon as it lessens the data needed to be sent to the client.

1 Like

Hi, may I ask what is the usage of MeleeWeaponModule?
I assume this code runs when you ask the server to start the cast. Why there is a need to cache the CollidedConnections? Also, why are you disconnecting it before connecting? Do I need to disconnect the event after each collision is fired? Thank you in advance.

1 Like

Hello Pyseph, thank you for making ClientCast. I would like to ask if you will ever add support for ShapeCasting in the future.

Idk why we need that. RayCast is cheaper and for swords this module is great. For big hammer instead of making shapecast you can use more attachments.
Also, more attachements cheaper than shapecast. Depends on number of attachments. You can simply use more attachments or recode it yourself but it will expensive I think. It doesn’t cause high ping do it being client sided but clients will have more memory usage(that is what I think)

If I play animations for an NPC locally, will clientcast raycast around those animations if I call it on server?

i would like to know if im doing this correctly
whenever i pull out the sword the debug shows, isn’t it suppose to happen when caster start?
oh wait its only the serverside debug not client

here’s my code for a sword
i dont think i am doing things correctly

server script

local Players = game:GetService("Players")

local ServerStorage = game:GetService("ServerStorage")
local ClientCast = require(ServerStorage.ClientCast)

local tool = script.Parent
local handle = tool.Handle

local event = tool.Attack

local caster = nil

local hitList = {}

local function attack(player, attacking)
	if not caster then return end
	caster:Stop() --disconnects previous attack
	if not attacking then
		return
	end
	print('swing')
	
	table.clear(hitList)
	caster:Start()
end

event.OnServerEvent:Connect(attack)

tool.Equipped:Connect(function()
	local character = tool.Parent
	local player = Players:GetPlayerFromCharacter(character)

	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {character}
	params.FilterType = Enum.RaycastFilterType.Exclude
	caster = ClientCast.new(handle, params)
	caster:SetOwner(player)
	
	table.clear(hitList)
	
	caster.HumanoidCollided:Connect(function(RaycastResult, HitHumanoid)
		if table.find(hitList, HitHumanoid) then return end
		table.insert(hitList, HitHumanoid)
		HitHumanoid:TakeDamage(10)
		print('Ow!')
	end)
end)

tool.Unequipped:Connect(function()
	if caster then caster:Stop() caster = nil end
end)

client

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")

local swingAnimation = Instance.new("Animation")
swingAnimation.AnimationId ="rbxassetid://17323900082"

local swingAnimationTrack = animator:LoadAnimation(swingAnimation)

local tool = script.Parent
local event = tool.Attack

swingAnimationTrack:GetMarkerReachedSignal("HitStart"):Connect(function()
	event:FireServer(true)
end)

swingAnimationTrack:GetMarkerReachedSignal("HitStop"):Connect(function()
	event:FireServer(false)
end)

swingAnimationTrack.Stopped:Connect(function()
	event:FireServer(false)
end)

tool.Activated:Connect(function()
	print('click')
	swingAnimationTrack:Play()
end)

That error is probably occurring because the remote data from the client is arriving on the server after the server code already :Destroy()ed the caster. This is a bug as the remote data should be disregarded, but a recommendation is to only create one caster per character, and instead use :Start and :Stop methods.

1 Like

Just want to know, why are we just not using Touched Event?

One question how do I change the debug lines (so turn them on/off) for only one client so like one client can see them and the other cant?

Touched event is a lot slower. And it will show different results depending on NetworkOwner

Not sure what im doing wrong but the ClientCast Debug Trails are not showing when I try to turn the setting on anymore

ClientCastModule Settings:

local Settings = {
	AttachmentName = "DmgPoint", -- The name of the attachment that this network will raycast from
	DebugAttachmentName = "DebugDmgPoint", -- The name of the debug trail attachment

	FunctionDebug = false,
	DebugMode = true, -- DebugMode visualizes the rays, from last to current position
	DebugColor = Color3.new(1, 0, 0), -- The color of the visualized ray
	DebugLifetime = 1, -- Lifetime of the visualized trail
	AutoSetup = true, -- Automatically creates a LocalScript and a RemoteEvent to establish a connection to the server, from the client.
}

ServerScript:

local RaySettings = RaycastParams.new()
RaySettings.FilterType = Enum.RaycastFilterType.Exclude
RaySettings.IgnoreWater = true
RaySettings.FilterDescendantsInstances = {character}
		
local ClientRay = HitboxController.new(character, RaySettings)
ClientRay:SetOwner(player)
ClientRay:Start()

Local Script:

serverRemote:FireServer(character, action)

And this is extremely bizarre because the debug trails use to appear before but now they don’t show up after I updated the module. I also recommend converting the module to a package incase there is an update that could potentially require developers to reiterate over the whole code.

Also recommend fleshing out the API and possibly a tutorial with more use cases because Im starting to find that RayCastHitbox may be more useful/flexible to use

Hello! I am unable to reproduce the issue with debug rays not appearing. Here is my test file:
Place1.rbxl (68.7 KB)

Could you expand on what functionality you believe is missing?

Oh my bad I had fixed the bug yesterday, in an older version I was able to use the client cast module on the client (yes i know not what it was intended for, but its functionality was perfect for what I was trying to achieve). Ended up converting everything to work with the server.

1 Like

Hey, I wanted to make you aware of a really strange bug I’ve found in my game. For some reason, this bug ReplicatedStorage.Modules.ClientCast:152 attempt to index nil with 'Disabled' just randomly appeared. My development team and I have not touched the inside of the ClientCast module and I have even tried deleting the ClientCast version we had and adding the latest version to the game and it still gives the same error.

This error is occuring more than 400M+ times in my game so I would appreciate it if you could please help me figure this out.

Hello! This is a very unusual error to have. Could you provide the relevant code? Also, could you try making a minimal place file that reproduces this?

1 Like