game.Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
while true do
local lastHRP = char.HumanoidRootPart.Position
task.wait(2)
if (char.HumanoidRootPart.Position - lastHRP).Magnitude > 20 then
char:PivotTo(CFrame.new(lastHRP))
end
end
end)
end)
anyway, I wanted smooth weapons and this is what i will use in the future, thanks
If a connected client were to have several connected casters at once, a raycast event from the client would fire all active casters on the server which are owned by that client. Oopsā¦
How would i activate raycasts for separate parts? For example, have the left fist activate itās raycasts only, then on the second time the player clicks the right fist activates.
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?
Screenshots:
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)
Iāve been trying to use this for a few hours, and got a bug.
Whenever I first join the game, hitboxes are fine, but when I respawn and try to hit someone, the first hit registers, but then it just breaks and there are no errors, or it just registers a few hits.
Hey, sorry for the late response. Whatās happening is that to make sure the :SetOwner command is replicated to the client, :SetOwner is actually wrapped in task.spawn, which then yields for a maximum of 0.1 seconds. This is to make sure that by the time the SetOwner command is sent to the client, the client already has a Caster object created.
If you want the casterās object to be set to player the moment itās created, use the third argument of ClientCast.new directly:
EDIT: Due to how I structured the code, it should actually be fine to remove the yields in theory. I will update the module to remove the yields, which should fix your issue without having to do anything besides updating the module.
Please verify that this is indeed an issue with the ClientCast module, and not your code. ClientCast never indexes the Character property in any of itās code, meaning itās extremely unlikely for the bug to be tied to ClientCast itself.
Iām not sure what the issue might be, but I recommend creating a separate studio place, and try reproducing the bug with as few lines of code as possible. Itāll become much easier to identify the problem from there.
figured a lot out but now im running into a separate issue.
I realised that if my character stays in the same position after being hit, none of the other hits register. I troubleshooted a lot and it turns out that this is a problem with client cast itself.
ClientCast only raycasts, it has no debounces, cooldowns, and the like. I really donāt think ClientCast is the issue here, but if youāre sure that it is, please provide a file which reproduces your issue in as few lines as possible.
Small script that uses a tool to use clientcast. It works fine at first, but whenever I respawn, it stops working at all. This is a simple script and it should still be working even after respawning if im not wrong, I donāt think I used something the wrong way
local clientCast = require(game.ReplicatedStorage.ClientCast)
local hitbox = clientCast.new(script.Parent.Handle, RaycastParams.new(), script.Parent.Parent.Parent)
local alreadyHit = false
hitbox.Collided:Connect(function(params)
if alreadyHit then return end
if params.Instance.Parent:FindFirstChild("Humanoid") then
alreadyHit = true
params.Instance.Parent:FindFirstChild("Humanoid"):TakeDamage(10)
end
end)
local inCD = false
function attack()
if inCD then return end
inCD = true
task.spawn(function()
wait(1)
alreadyHit = false
inCD = false
end)
hitbox:Start()
spawn(function()
wait(.5)
hitbox:Stop()
end)
end
script.Parent.Activated:Connect(function()
attack()
end)
Interesting catch! This seems to be a mix of buggy behavior between both ClientCast and Roblox itself - since the server canāt access Player.PlayerScripts, it parents the ClientHandler LocalScript into PlayerGui to run the code, and then ClientHandler reparents itself into Player.PlayerScripts. The deprecated StarterGui.ResetPlayerGuiOnSpawn conflicts with this though, and purges any children that were parented into PlayerGui at any point in time, even if they were later reparented.
Iāll try finding a better workaround for this, but for now, you can fix this by running game:GetService("StarterGui").ResetPlayerGuiOnSpawn = false in the command bar. Sorry for the inconvenience!
All good, Iām not sure how to fix it so I will wait for you to push a fix. I msut use resetplayerguionspawn because I have important guis that need to be resetted when respawned. Nice one on noticing the bug so fast haha
Hey! The issue should now be fixed on GitHub, though Iām reworking ClientCast a bit to support Rojo, along with adding a brand new documentation API so I wonāt update the devforum thread for a bit.
You can get the newest update here for now: https://github.com/PysephWasntAvailable/ClientCast
(cc. @Downrest, your issue should also be fixed now)