I'm making a physics-based fighting game, where players can shove others and have falling deal damage. In it, I have a push ability where players press 'e' to play a short shoving animation, then any character in front of them that triggers the collision is ragdolled, then pushed away. It works great, except when used on players’ characters. If I shove an NPC, it flies away and ragdolls correctly. But if I shove a player, they ragdoll, but no actual 'shoving' occurs and they just flop there until recovery.
Parts of my shoving script shown below (excluding parts not relevant to this question, such as triggering and other variable handlers)
--COLLISION DETECTION (ONE OF THREE I HAVE FOR SEPARATE BODY PARTS)
script.Parent["Right Arm"].Touched:Connect(function(hit)
if hit.Parent ~= script.Parent then
if shoving == true then
shoving = false
--local directionVector = (hit.Parent.PrimaryPart.CFrame.p - script.Parent.HumanoidRootPart.Position).unit
local velocity = script.Parent.PrimaryPart.CFrame.LookVector * 100
--local velocity = directionVector * 100
ragdollTarg(hit.Parent)
hit.Parent.PrimaryPart.Velocity = velocity
end
end
end)
--This runs correctly.
function ragdollTarg(targ)
local plr = game.Players:GetPlayerFromCharacter(targ)
if plr ~= nil then
--targ is player
Module.Bot(targ)
game.ReplicatedStorage.pushHits:FireAllClients(plr,script.Parent)
--[[
targ.Humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
if not targ:FindFirstChild("Jointed") then Module.Joints(targ)end
Module.Ragdoll(targ)
]]
else
print("Targ is a bot.")
targ.Humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
if not targ:FindFirstChild("Jointed") then Module.Joints(targ)end
Module.Bot(targ)
end
end
The module functions I have for these is:
Module.Joints = function(c) --instantiate floppy attachments for ragdoll activation
c.Humanoid.BreakJointsOnDeath = false
c.Humanoid.RequiresNeck = false
local mark = Instance.new("IntValue",c)
mark.Name = "Jointed"
for _,v in pairs(c:GetDescendants()) do
if v:IsA("Motor6D")and Module.Check(v.Name)then
local b = Instance.new("BallSocketConstraint",v.Parent)
local a0,a1 = Instance.new("Attachment"),Instance.new("Attachment")
a0.Parent,a1.Parent = v.Part0,v.Part1
b.Attachment0,b.Attachment1 = a0,a1
a0.CFrame,a1.CFrame = v.c0,v.c1
b.LimitsEnabled = false
b.TwistLimitsEnabled = false
b.Enabled = false
elseif v:IsA'BasePart' then
PS:SetPartCollisionGroup(v,"A")
if v.Name == "HumanoidRootPart" then
PS:SetPartCollisionGroup(v,"B")
elseif v.Name=="Head"then
v.CanCollide = true
end
end
end
end
Module.Bot = function(bot)--USED FOR NPCs ONLY.
task.spawn(function()
local H = bot.Humanoid
if bot:FindFirstChild'HumanoidRootPart'and H.Health~=0 then
H:SetStateEnabled(Enum.HumanoidStateType.GettingUp,false)
H:ChangeState(Enum.HumanoidStateType.Ragdoll)
if H:GetState() == Enum.HumanoidStateType.Ragdoll then print("Ragdolled")
else
print("Not ragdolled")
end
for _,v in pairs(H:GetPlayingAnimationTracks())do v:Stop(0)end
bot.Animate.Disabled = true
for _,v in pairs(bot:GetDescendants()) do
if v:IsA'Motor6D'and Module.Check(v.Name) then
v.Enabled = false
elseif v:IsA'BallSocketConstraint' then
v.Enabled = true
end
end
task.wait(5)
bot.Animate.Disabled = false
H:SetStateEnabled(Enum.HumanoidStateType.GettingUp,true)
H:ChangeState(Enum.HumanoidStateType.GettingUp)
for _,v in pairs(bot:GetDescendants()) do
if v:IsA'Motor6D' then
v.Enabled = true
elseif v:IsA'BallSocketConstraint' then
v.Enabled = false
end
end
--[[else
bot.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp,false)
bot.Humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
for _,v in pairs(bot:GetDescendants()) do
if v:IsA'Motor6D'and Module.Check(v.Name)then
v.Enabled = false
elseif v:IsA'BallSocketConstraint' then
v.Enabled = true
elseif v.Name=="Head"then
local b = Instance.new("BodyVelocity",bot.Head)
b.Velocity = Vector3.new(math.random(-10,10),0,math.random(-10,10))
task.spawn(function()
wait(.1)
b:Destroy()
end)
end
end]]
end
end)
end
Module.Ragdoll = function(char,bool)--USED FOR PLAYERS ONLY
local plr = game.Players:GetPlayerFromCharacter(char)
if char.Humanoid.Health~=0 and ((char:FindFirstChild'LowerTorso'and not char.LowerTorso.Root.Enabled)or (char:FindFirstChild'Torso'and not char.Torso.Neck.Enabled)) and not bool then
RE:FireClient(plr,false)
for _,v in pairs(char:GetDescendants()) do
if v:IsA'Motor6D' then
v.Enabled = true
elseif v:IsA'BallSocketConstraint' then
v.Enabled = false
end
end
task.wait(5)
char.Animate.Disabled = false
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp,true)
char.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
for _,v in pairs(char:GetDescendants()) do
if v:IsA'Motor6D' then
v.Enabled = true
elseif v:IsA'BallSocketConstraint' then
v.Enabled = false
end
end
else
RE:FireClient(plr,true)
for _,v in pairs(char:GetDescendants()) do
if v:IsA'Motor6D'and Module.Check(v.Name)then
v.Enabled = false
elseif v:IsA'BallSocketConstraint' then
v.Enabled = true
elseif v.Name=="Head"then
local b = Instance.new("BodyVelocity",char.Head)
b.Velocity = Vector3.new(math.random(-10,10),0,math.random(-10,10))
task.spawn(function()
wait(.1)
b:Destroy()
end)
end
end
task.wait(5)
char.Animate.Disabled = false
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp,true)
char.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
for _,v in pairs(char:GetDescendants()) do
if v:IsA'Motor6D' then
v.Enabled = true
elseif v:IsA'BallSocketConstraint' then
v.Enabled = false
end
end
end
end
I’m guessing this has something to do with client-side interruption. I’m fairly new on the subject of client-server communication, so any help explaining would be greatly appreciated!

2 comments
Wow! Thank you so much! FYI: I didn't even know what to look up, so I was kinda lost.
It's fine!