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!
It's because of Network Ownership. Check my answer here for the solution and check the documentation about it.
Remember, search (in either ScriptingHelpers or DevForum) your problem first before posting because there might be a similar problem posted long time ago and it is already solved.