local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local HandcuffEvent = ReplicatedStorage:WaitForChild("RemoteEvent"):WaitForChild("Handcuff"):WaitForChild("HandcuffEvent") local CUFF_OFFSET = CFrame.new(0, 0, -2.5) local MAX_CUFF_DISTANCE = 10 local cuffedPlayers = {} local animationTracks = {} local function getRootPart(char) return char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("UpperTorso") or char:FindFirstChild("Torso") end local function cleanupCuff(suspectChar) local data = cuffedPlayers[suspectChar] if not data then return end if data.weld then data.weld:Destroy() end if data.prompts then for _, prompt in ipairs(data.prompts) do prompt:Destroy() end end if animationTracks[suspectChar] then animationTracks[suspectChar]:Stop() animationTracks[suspectChar]:Destroy() animationTracks[suspectChar] = nil end local humanoid = suspectChar:FindFirstChildOfClass("Humanoid") local rootPart = getRootPart(suspectChar) local player = Players:GetPlayerFromCharacter(suspectChar) if humanoid then humanoid.PlatformStand = false end if rootPart then rootPart.Massless = false end if player and rootPart then rootPart:SetNetworkOwner(player) end cuffedPlayers[suspectChar] = nil end local function updatePrompts(suspectChar, state) local data = cuffedPlayers[suspectChar] if not data then return end for _, prompt in ipairs(data.prompts) do prompt:Destroy() end data.prompts = {} local offsets = {Vector3.new(0,0,0), Vector3.new(0,0,0), Vector3.new(0,0,0)} local function createPrompt(action, key, index, callback) local attach = Instance.new("Attachment") attach.Position = offsets[index] attach.Parent = getRootPart(suspectChar) local prompt = Instance.new("ProximityPrompt") prompt.Name = "HandcuffPrompt" prompt.ObjectText = "Suspect" prompt.ActionText = action prompt.KeyboardKeyCode = key prompt.Style = Enum.ProximityPromptStyle.Custom prompt.RequiresLineOfSight = false prompt.MaxActivationDistance = 25 prompt.Parent = attach prompt.Exclusivity = Enum.ProximityPromptExclusivity.AlwaysShow prompt.Triggered:Connect(callback) table.insert(data.prompts, prompt) end if state == "grab" then createPrompt("Release", Enum.KeyCode.E, 1, function() cleanupCuff(suspectChar) end) createPrompt("Ungrab", Enum.KeyCode.F, 2, function() local root = getRootPart(suspectChar) if root then root.Massless = false local hum = suspectChar:FindFirstChildOfClass("Humanoid") if hum then hum.PlatformStand = false end end local d = cuffedPlayers[suspectChar] if d and d.weld then d.weld:Destroy() d.weld = nil end updatePrompts(suspectChar,"release") end) else createPrompt("Grab", Enum.KeyCode.F, 1, function() local root = getRootPart(suspectChar) local copRoot = getRootPart(data.copChar) if root and copRoot then root.Massless = true local hum = suspectChar:FindFirstChildOfClass("Humanoid") if hum then hum.PlatformStand = true end root.CFrame = copRoot.CFrame * CUFF_OFFSET local weld = Instance.new("WeldConstraint") weld.Part0 = copRoot weld.Part1 = root weld.Parent = copRoot data.weld = weld pcall(function() root:SetNetworkOwner(Players:GetPlayerFromCharacter(data.copChar)) end) end updatePrompts(suspectChar,"grab") end) createPrompt("Release", Enum.KeyCode.E, 2, function() cleanupCuff(suspectChar) end) end end HandcuffEvent.OnServerEvent:Connect(function(copPlayer, target) if not copPlayer or not target then return end local copChar = copPlayer.Character local suspectChar = target:IsA("Player") and target.Character or (target:IsA("Model") and target or nil) if not copChar or not suspectChar then return end if cuffedPlayers[suspectChar] then cleanupCuff(suspectChar) return end local copRoot = getRootPart(copChar) local suspectRoot = getRootPart(suspectChar) local suspectHumanoid = suspectChar:FindFirstChildOfClass("Humanoid") if not copRoot or not suspectRoot or not suspectHumanoid or suspectHumanoid:GetState() == Enum.HumanoidStateType.Dead then return end if (copRoot.Position - suspectRoot.Position).Magnitude > MAX_CUFF_DISTANCE then return end copRoot.Anchored = false suspectRoot.Anchored = false suspectHumanoid.PlatformStand = true suspectRoot.Massless = true suspectRoot.CFrame = copRoot.CFrame * CUFF_OFFSET local weld = Instance.new("WeldConstraint") weld.Part0 = copRoot weld.Part1 = suspectRoot weld.Parent = copRoot pcall(function() suspectRoot:SetNetworkOwner(copPlayer) end) local HandcuffAnimation = script:FindFirstChild("HandcuffAnimation") if HandcuffAnimation then local track = suspectHumanoid:LoadAnimation(HandcuffAnimation) track.Looped = true track.Priority = Enum.AnimationPriority.Action track:Play() animationTracks[suspectChar] = track end cuffedPlayers[suspectChar] = { copChar = copChar, weld = weld, prompts = {} } updatePrompts(suspectChar, "grab") end) Players.PlayerRemoving:Connect(function(player) local char = player.Character if char and cuffedPlayers[char] then cleanupCuff(char) end for suspectChar, data in pairs(cuffedPlayers) do if data.copChar == player.Character then cleanupCuff(suspectChar) end end end)