ClientCast - A Client-based, Idiosyncratic Hitbox System!

Update 1.10.0

  • Completely remade the documentation API with the help of Moonwave! You can find the new documentation site at ClientCast.
  • Fixed an issue with ClientHandler localscript being destroyed when StarterGui.ResetPlayerGuiOnSpawn = false. (cc. @XarkDev)
  • methods such as GetOwner now no longer internally yield, and instantly return the associated values. (cc. @Downrest)
  • Added support for rojo and non-studio workflows, categorizing scripts into their appropriate folders.
  • Automated releases, such that the code will now automatically pack itself into a .rbxm file and be added into Releases upon a commit.
  • Changed to version to follow SemVer semantic versioning.
5 Likes

Hello there!

First, I would like to commend all that youā€™ve done in regard to the provision of this system to the community, and it is the best material Iā€™ve found on this forum!

I just have an issue pertaining to the hitbox, which is attached to a humanoid in a model of mine. Essentially, I have a range of DmgPoint attachments within a hitbox part, but Iā€™m struggling to prevent self-inflicted damage while also enabling damage to those who collide with the attachments thereof. I was hoping you would be able to solve this problem!

Below is the hitbox Iā€™m referring to


local ClientCast = require(game.ServerStorage.ClientCast)

for i = -2.5, 2.5, 0.1 do -- Creating new attachments called "DmgPoint" within the -2.5 and 2.5 range every 0.1 stud on the Y-axis
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(0, i, 0) 
end

for j = -2.5, 2.5, 0.1 do
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(1, j, 0) -- Note the changes to the attachment positions (X = 1)
end

for k = -2.5, 2.5, 0.1 do
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(-1, k, 0)
end

for l = -2.5, 2.5, 0.1 do
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(-2, l, 0)
end

for m = -2.5, 2.5, 0.1 do
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(2, m, 0)
end

for n = -2.5, 2.5, 0.1 do
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(0, n, -0.5)
end

for o = -2.5, 2.5, 0.1 do
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(-1, o, -0.5)
end

for p = -2.5, 2.5, 0.1 do
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(-2, p, -0.5)
end

for q = -2.5, 2.5, 0.1 do
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(1, q, -0.5)
end

for r = -2.5, 2.5, 0.1 do
	local Attachment = Instance.new("Attachment", game.Workspace.MALWARE.CorruptionAura)
	Attachment.Name = "DmgPoint"
	Attachment.Position = Vector3.new(2, r, -0.5)
end

local Caster = ClientCast.new(game.Workspace.MALWARE.CorruptionAura, RaycastParams.new()) -- Creates new clientcaster

local Debounce = {}

local MALWARE = script.Parent.Parent

Caster.HumanoidCollided:Connect(function(Result, HitHumanoid)
	
	if Debounce[HitHumanoid] then return end
	
	Debounce[HitHumanoid] = true
	
	local Hit = Result.Instance.Parent
	if Hit ~= "MALWARE" then -- Here is the area of focus ... how ensure damage to any humanoid, while also preventing MALWARE's humanoid from being damaged? 
	
	HitHumanoid:TakeDamage(20)
	
	wait(0.33)
	
		Debounce[HitHumanoid] = false
	end
end)

Caster:Start()

Iā€™ve tried scrolling through this hefty discussion, and I havenā€™t seen anything pertaining to ā€œ3D hitbox cubesā€.

Thank you :smiley:

Hey, ClientCast does not actually offer any debounces by itself to keep maximum customizability in mind. Youā€™d have to check if the hit humanoid originated from the player who used it, and ignore the hit if so.

EDIT: it seems like youā€™re aware of this, but donā€™t know how to go about it. You donā€™t seem to be using this for players (at least, no Owner is defined), so you can instead do:

local DamagingMob = workspace.MALWARE

Caster.HumanoidCollided:Connect(function(Result, HitHumanoid)
    if HitHumanoid:IsDescendantOf(DamagingMob) then
        return
    end

    -- rest of your code
end)
2 Likes

Hey, thanks for making this @PysephDEV. Would I be able to get this to work with native animations?

I have this custom rig with a sword that Iā€™m considering using this for, but Iā€™m cautious because I havenā€™t been able to get any type of hit detection to work with this rig yet.

iā€™m pretty sure you can just use .Touched instead of this

.Touched does not provide any information about where exactly the hit was, nor the surface normal at that hit point. Itā€™s also more inaccurate.

Animations update the WorldPosition property of Attachment objects just fine, so it should work in your scenario :slightly_smiling_face:

1 Like

Looks like animations only update Attachments if its a part being animated, as opposed to a bone. I had to make a new ā€œSwordā€ bone and connect the DmgPoint attachments to that with a RigidConstraint, but itā€™s working! Thanks!

.Touched is really innacurate and leads to a lot of problems.

only if you arenā€™t using it right

What do you mean by that, could you explain how to use it ā€œrightā€?

https://developer.roblox.com/en-us/api-reference/event/BasePart/Touched

1.11.0 & 1.12.0

  • Added an informative error for when the module is attempted to be required from the client
  • Added a yield for Player.PlayerGui to prevent issues when PlayerGui does not immediately replicate
  • Updated Testing.server.lua to set player Owner
  • Updated testing.project.json to work properly
  • Removed debug warning which was left out
2 Likes

Thatā€™s the API, not really sure how that proves your point?


.Touched relies of physics-based collisions which makes it unreliable, and why would you use .Touched when you have better options like WorldRoot:Raycast() and Region3 or OverlayParams? They are much more accurate, give you a lot more information about the hit, and WorldRoot:Raycast() is almost as fast as .Touched (slightly more expensive, but the pros greatly outweigh the cons).

1 Like

.Touched can be laggy and its not always accurate, not the best performant-wise either.

Iā€™m having some issues when it comes to making an NPC that swings a weapon in a loop. Now this issue seems to be pretty minor and Iā€™m not sure if it is something I should ignore or not but every time the NPC sword uses ClientCaster it prints this warning: ā–¶ No replication connection found - Server - ClientCast:344 though it doesnā€™t seem to affect anything. It just fills up the console and it might be causing an issue I donā€™t see. I am not setting an owner for the caster btw. Anybody know what to do about this?

Yeah, itā€™s a warning that was left there by accident which I removed since last update. Simply updating the module to the latest version should fix this!
This was because I originally only expected people to use ClientCast for Client<ā€“>Server communication, but itā€™s since been supported for just generic server/NPC hitboxes also :slightly_smiling_face:

Alright thanks. I was confused whether I shouldā€™ve been concerned about it or not.

Hi again!

Thereā€™s this really weird behavior that I cannot just wrap my head around.

So I made a viewmodel arm system, works great. How I do it is I basically just set the Motor6Dā€™s Part0 of both arms to the viewmodelā€™s torso and set the CFrame of the viewmodel to the cameraā€™s CFrame. Thus, making the arm move based on where the camera is looking.

Except the weird thing is, the sword works only whenever I am not in first person (basically, when the viewmodel is disabled).

I noticed is that whenever I switch to the server window and go back to the client, it gets fixed? And whenever I reset, the problem is back.

Another weird thing is that the issue gets fixed whenever I calculate the hitbox on the server (instead of setting the casterā€™s Owner to a player)

The welding process which makes the viewmodel work in the first place is definitely messing everything up, but Iā€™m not sure how I would go with fixing it.

Currently, I have two options: either just set the hitbox calculations to the server or actually fix the glitch.

If you can guide me onto how I can fix this issue I would really appreciate it. Thanks for reading!

zombietestgame.rbxl (139.8 KB)

Iā€™ll be honest, Iā€™ve no idea whatā€™s going on here :sweat_smile:
Iā€™m assuming this is a Roblox-related bug where parts welded to a part do not get updated properly. Besides switching client-server contexts, even selecting one of the DmgPoint attachments while in first-person makes hitboxes work again, so Iā€™m inclined to say this is an issue on Robloxā€™s end.
You should try uploading a live game and see how it performs there - maybe this is a Studio-specific issue?

1 Like