Network Ownership CanCollide on NPC's is screwed up

yo whats up devs! for awhile i’ve been trying to make a player-owned npc type system, so that the movement and crap like that is seamless. but when the npc ragdolls, and i set the “cancollide” to true, it doesn’t do crap and the limbs are all cancollide off. heres a video of what i mean:


and here’s the main parts of the main scripts:

“RagdollModule”

local module = {}

local remote = game.ReplicatedStorage.Events:WaitForChild("Ragdoll")
local dragEvent = game.ReplicatedStorage.Events:WaitForChild("Drag")

function module.NpcRagdoll(char : Model, velocity, sec : number) -- npcc
	local humanoid : Humanoid = char:WaitForChild("Humanoid")
	local torso : BasePart = char:WaitForChild("Torso")
	local rootPart : BasePart = char:WaitForChild("HumanoidRootPart")
	humanoid.BreakJointsOnDeath = false
	if humanoid:GetState() ~= Enum.HumanoidStateType.Physics and humanoid:GetState() ~= Enum.HumanoidStateType.PlatformStanding then
		for index, joint in pairs(char:GetDescendants()) do
			if joint:IsA("Motor6D") then
				humanoid:ChangeState(Enum.HumanoidStateType.Physics)
								
				if velocity then
					torso.AssemblyLinearVelocity = velocity * 20
					print('finished')
				end

				local attachmentCFrames = {
					["Neck"] = {CFrame.new(0, 1, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1), CFrame.new(0, -0.5, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1)},
					["Left Shoulder"] = {CFrame.new(-1.3, 0.75, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1), CFrame.new(0.2, 0.75, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1)},
					["Right Shoulder"] = {CFrame.new(1.3, 0.75, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CFrame.new(-0.2, 0.75, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1)},
					["Left Hip"] = {CFrame.new(-0.5, -1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1), CFrame.new(0, 1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)},
					["Right Hip"] = {CFrame.new(0.5, -1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1), CFrame.new(0, 1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)},
				}
				
				local socket = Instance.new("BallSocketConstraint")
				local a1, a2 = Instance.new("Attachment"), Instance.new("Attachment")

				socket.Parent = joint.Parent
				socket.Attachment0 = a1
				socket.Attachment1 = a2
				if joint.Name == "Neck" then
					a1.CFrame = CFrame.new(0, 1, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1)
					a2.CFrame = CFrame.new(0, -0.5, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1)
				end
				if joint.Name == "Right Shoulder" then
					a1.CFrame = CFrame.new(1.3, 0.75, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1)
					a2.CFrame = CFrame.new(-0.2, 0.75, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1)
				end
				if joint.Name == "Left Shoulder" then
					a1.CFrame = CFrame.new(-1.3, 0.75, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1)
					a2.CFrame = CFrame.new(0.2, 0.75, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1)
				end
				if joint.Name == "Right Hip" then
					a1.CFrame = CFrame.new(0.5, -1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)
					a2.CFrame = CFrame.new(0, 1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)
				end
				if joint.Name == "Left Hip" then
					a1.CFrame = CFrame.new(-0.5, -1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)
					a2.CFrame = CFrame.new(0, 1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)
				end
				
				socket.LimitsEnabled = true

				humanoid.PlatformStand = true

				socket.MaxFrictionTorque = 0
				socket.Restitution = 0
				socket.UpperAngle = 90
				socket.TwistLowerAngle = -45
				socket.TwistUpperAngle = 45

				-- Set realistic twist limits and attachment positions for arms, legs, and neck
				if joint.Name:lower():find("arm") then
					socket.TwistLimitsEnabled = true
					socket.TwistLowerAngle = 90
					socket.TwistUpperAngle = 90 -- Realistic twist limits for arms
				elseif joint.Name:lower():find("leg") then
					socket.TwistLimitsEnabled = true
					socket.TwistLowerAngle = 45
					socket.TwistUpperAngle = 45 -- Realistic twist limits for legs
				elseif joint.Name:lower():find("neck") then
					socket:Destroy()
					local hinge = Instance.new("HingeConstraint")
					hinge.Parent = joint.Parent
					hinge.Attachment0 = a1
					hinge.Attachment1 = a2
					hinge.LimitsEnabled = true
					hinge.LowerAngle = -30 -- Realistic lower angle limit for neck
					hinge.UpperAngle = 30  -- Realistic upper angle limit for neck
				end

				joint.Enabled = false
				a1.Parent = joint.Part0
				a2.Parent = joint.Part1
			end
		end
		local dragPrompt = Instance.new("ProximityPrompt")
		dragPrompt.Parent = torso
		dragPrompt.RequiresLineOfSight = false
		dragPrompt.HoldDuration = 0.1
		dragPrompt.Exclusivity = Enum.ProximityPromptExclusivity.AlwaysShow
		dragPrompt.Name = "DragPrompt"
		local disguisePrompt = Instance.new("ProximityPrompt")
		disguisePrompt.Parent = torso
		disguisePrompt.RequiresLineOfSight = false
		disguisePrompt.HoldDuration = 0.1
		disguisePrompt.KeyboardKeyCode = Enum.KeyCode.G
		disguisePrompt.UIOffset = Vector2.new(0,-80)
		disguisePrompt.Exclusivity = Enum.ProximityPromptExclusivity.AlwaysShow
		disguisePrompt.Name = "DisguisePrompt"
		
		disguisePrompt.Triggered:Connect(function(player)
			local pChar = player.Character
			local pRootPart = pChar:WaitForChild("HumanoidRootPart")
			local pTorso = pChar:WaitForChild("Torso")
			local pBodyColors = pChar:WaitForChild("Body Colors")
			local pShirt = pChar:FindFirstChild("Shirt")
			local pPants = pChar:FindFirstChild("Pants")
			
			local bodyColors = char:FindFirstChild("Body Colors")
			local shirt = char:FindFirstChild("Shirt")
			local pants = char:FindFirstChild("Pants")
			
			if shirt and pShirt and pants and pPants then
				pShirt.ShirtTemplate = shirt.ShirtTemplate
				pPants.PantsTemplate = pants.PantsTemplate
				
				shirt.ShirtTemplate = ""
				pants.PantsTemplate = ""
				
				bodyColors.RightLegColor = BrickColor.new("Bright blue")
				bodyColors.LeftLegColor = BrickColor.new("Bright blue")
				bodyColors.TorsoColor = BrickColor.new("White")
			elseif bodyColors then
				pShirt.ShirtTemplate = ""
				pPants.PantsTemplate = ""
				pBodyColors.RightLegColor = bodyColors.RightLegColor
				pBodyColors.LeftLegColor =  bodyColors.LeftLegColor
				pBodyColors.TorsoColor =  bodyColors.TorsoColor
							
				bodyColors.RightLegColor = BrickColor.new("Bright blue")
				bodyColors.LeftLegColor = BrickColor.new("Bright blue")
				bodyColors.TorsoColor = BrickColor.new("White")
			end
		end)
		
		dragPrompt.Triggered:Connect(function(player)			
			 local pChar = player.Character
			 local pRootPart = pChar:WaitForChild("HumanoidRootPart")
			 local pTorso = pChar:WaitForChild("Torso")
			 local pRightArm = pChar:WaitForChild("Right Arm")
			 local pLeftArm = pChar:WaitForChild("Left Arm")
			 local pRightGrip : Attachment = pRightArm:WaitForChild("RightGripAttachment")
			 local pLeftGrip : Attachment = pLeftArm:WaitForChild("LeftGripAttachment")
			 
			 local npcRightGrip : Attachment = char:WaitForChild("Right Arm"):WaitForChild("RightGripAttachment")
			 local npcLeftGrip : Attachment = char:WaitForChild("Left Arm"):WaitForChild("LeftGripAttachment")
			 
			 local rightDragSocket = Instance.new("BallSocketConstraint")
			 local leftDragSocket = Instance.new("BallSocketConstraint")
			 
			 local rightShoulder : Motor6D = torso:FindFirstChild("Right Shoulder")
			 local leftShoulder : Motor6D = torso:FindFirstChild("Left Shoulder")
			 			 
			 dragEvent:FireClient(player,char)
			end) 
		if sec then
			task.wait(sec)

			for index, joint in pairs(char:GetDescendants()) do
				if joint:IsA("Motor6D") then
					local socket = joint.Parent:FindFirstChild("BallSocketConstraint") or joint.Parent:FindFirstChild("HingeConstraint")
					local a1 = joint.Part0:FindFirstChild("Attachment")
					local a2 = joint.Part1:FindFirstChild("Attachment")
					socket.LimitsEnabled = true

					if socket:IsA("BallSocketConstraint") then
						socket.TwistLimitsEnabled = true
					end

					socket:Destroy()
					a1:Destroy()
					a2:Destroy()
					humanoid.PlatformStand = false
					humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
					joint.Enabled = true
				end
			end
		end
	end
end

return module

summary of this script: ragdolls the npc when called by a serverScript

“npcHandler”

local ContextProvider = game:GetService("ContentProvider")
local Players = game:GetService("Players")

local ownershipChangedEvent = game:GetService("ReplicatedStorage").Events:WaitForChild("OwnershipChanged")

local npcFolder = workspace:WaitForChild("NPCs")
local npcChildren = npcFolder:GetChildren()

local function getNearestPlayer(npc)
	local npcRootPart = npc:FindFirstChild("HumanoidRootPart")
	
	local closestPlayer = nil
	local closestDistance = math.huge
	
	for i,player in pairs(Players:GetPlayers()) do
		local playerChar = player.Character or player.CharacterAdded:Wait()
		local playerRootPart = playerChar:FindFirstChild("HumanoidRootPart")
		
		if playerChar and playerRootPart then
			local distance = (npcRootPart.Position - playerRootPart.Position).Magnitude
			if distance < closestDistance then
				closestDistance = distance
				closestPlayer = player
			end
		end

		return closestPlayer
	end
end

task.wait(3)

for i,npc in pairs(npcChildren) do
	local nearestPlayer = getNearestPlayer(npc)
	for i,part in pairs(npc:GetChildren()) do
		if part:IsA("Part") then
			part:SetNetworkOwner(nearestPlayer)
		end
	end
	ownershipChangedEvent:FireClient(nearestPlayer,npc)
end

summary of this script: sets the networkownership of the npc to the nearest player.

“ClientReplication”

ownershipChangedEvent.OnClientEvent:Connect(function(npc : Model)
	local humanoid : Humanoid = npc:FindFirstChild("Humanoid")
	humanoid.StateChanged:Connect(function(oldState,newState)
		if newState == Enum.HumanoidStateType.Physics then
			for i,part in pairs(npc:GetChildren()) do
				if part:IsA("BasePart") then
					part.CanCollide = true
				end
			end
		end
	end)
end)

summary of this script: gets called when the networkownership is set to the player, then when the state is changed to “physics” it’s supposed to set all parts of the npc’s cancollide to true, but it doesn’t. this is the main problem of all of this that i want to fix. of course on other remote events and stuff setting the cancollide works which i have absolutely no idea why. it makes me want to loose my shiz. (on the drag event setting the cancollide works just fine for some reason (in the modulescript, “RagdollModule”))

alright obviously this is a lot to ask for because most of the scripts are so thicc, thats why i added the summaries but anyway if you know anything about why this happens, please send a reply. please…

thanks for reading this post, and have an AWOSOME dae!

1 Like