ClientCast - A Client-based, Idiosyncratic Hitbox System!

Hey there!

So I’ve been using your module to make a sword system. Works pretty nice, however I noticed one thing.

Whenever I try to set the owner of the sword and do Caster:GetOwner(), it prints out nil? And using Caster:GetPing() prints out 0.

Did I mess something up?

image


Screenshots:

image

image

image


Client:

local RS = game:GetService("ReplicatedStorage")
local PS = game:GetService("Players")

local player = PS.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()

player.CharacterAppearanceLoaded:Wait()

local hum = char:FindFirstChildWhichIsA("Humanoid")
local animator = hum:FindFirstChildWhichIsA("Animator")
local tool = script.Parent
local blade = tool:WaitForChild("Blade")
local equip = blade:WaitForChild("Equip")
local request = RS.Sword.Events.Request
local validate = RS.Sword.Events.Validate
local idleAnim = nil
local animation = {
	attack = {
		9503532906,
		9503922539,
		9504030319
	},
	idle = 9504150874,
}

local function LoadAnimation(id, priority)
	local anim = Instance.new("Animation") do
		anim.AnimationId = "rbxassetid://" .. id
	end
	
	local load = animator:LoadAnimation(anim) do
		load.Priority = priority
		load:Play()
	end
	
	return load
end

tool.Equipped:Connect(function()
	equip:Play()
	idleAnim = LoadAnimation(animation.idle, Enum.AnimationPriority.Idle)
end)

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

tool.Activated:Connect(function()
	request:FireServer(tool)
end)

request.OnClientEvent:Connect(function()
	LoadAnimation(animation.attack[math.random(1, #animation.attack)], Enum.AnimationPriority.Action)
end)

Server:

local RS = game:GetService("ReplicatedStorage")

local caster = require(RS.Sword.ClientCast)
local request = RS.Sword.Events.Request
local validate = RS.Sword.Events.Validate
local stat = {
	Sword1 = {Damage = 10}
}
local debounce = {}

local function IsHitboxValid(hitPos: Vector3, swordPos: Vector3): boolean
	local mag = (hitPos - swordPos).Magnitude

	if mag > 8 then
		return false
	else
		return true
	end
end

local function CalculateHitbox(player, blade)
	if not player or not blade then
		return
	end

	local sword = caster.new(blade, RaycastParams.new())
	local char = player.Character or player.CharacterAdded:Wait()
	local debounce = {}

	sword.HumanoidCollided:Connect(function(ray, hum)
		local instance = ray.Instance
		
		if instance:IsDescendantOf(char) or instance:IsDescendantOf(blade.Parent) or IsHitboxValid(ray.Position, sword.Object.Position) == false then
			return
		end 
		
		local info = stat[blade.Parent.Name]
		local hit = blade:FindFirstChild("Hit")
		
		if debounce[hum] then
			return
		end

		debounce[hum] = true

		hit:Play()
		hum:TakeDamage(info.Damage)
	end)

	task.spawn(function()
		warn("old: ", sword:GetOwner())
		sword:SetOwner(player)
		warn("new: ", sword:GetOwner())
		warn("ping: ", sword:GetPing())
		sword:Start()
		task.wait(1)
		sword:Destroy()
	end)
end

request.OnServerEvent:Connect(function(player: Player, tool: Tool)
	if debounce[player] or not tool:FindFirstChild("Blade") then
		return
	end

	local blade = tool:FindFirstChild("Blade")

	debounce[player] = true
	
	request:FireClient(player)
	CalculateHitbox(player, blade)

	task.wait(2)
	debounce[player] = false
end)