Hello! I’ve birthed this absolutely terrible mother of spaghetti code of a module, used for ragdolling rigs. When a player ragdolls and unragdolls quickly, they regain control but their torso moves and their limbs flop around in a sort of limbo state between walking and ragdolling.
I’ve tried some things to no avail, so how can I add a cooldown/debounce to my code?
local module = {}
local Players = game:GetService("Players")
local Debris = game:GetService("Debris")
local PhysicsService = game:GetService("PhysicsService")
local ragParts = script.RagdollParts:GetChildren()
local ImpactSFX = script.ImpactSFX
local sounds = script.Sounds:GetChildren()
local slip = script.Slip
local defaultMinZoomDistance = game.StarterPlayer.CameraMinZoomDistance
local function playSound(part, s, vol)
local sound = s:Clone()
sound.Parent = part
sound.Volume = vol or 0.5
sound:Play()
task.wait(0.1)
Debris:AddItem(sound, sound.TimeLength + 0.1)
end
local function playRandomSound(char)
local sound = sounds[math.random(1, #sounds)]
local head = char and char:FindFirstChild("Head")
if not head or not sound then return end
playSound(head, slip)
playSound(head, sound, 0.2)
end
local function createCollider(limb : BasePart)
if limb.Name == "HumanoidRootPart" then return end
local collider = Instance.new("Part")
collider.CFrame = limb.CFrame
collider.Massless = true
collider.Size = limb.Size * 0.5
collider.Transparency = 1
local weld = Instance.new("WeldConstraint")
weld.Part0 = collider
weld.Part1 = limb
weld.Parent = collider
collider:AddTag("Collider")
collider.Name = limb.Name .. " Collider"
collider.Parent = limb.Parent
return collider
end
function module:Setup(char : Model, isPlayer)
if not char.Humanoid then return end
local humanoid = char:FindFirstChild("Humanoid")
assert(humanoid, "Can only set-up ragdoll on R6 humanoid rigs")
assert(humanoid.RigType == Enum.HumanoidRigType.R6, "Can only set-up ragdoll on R6 humanoid rigs")
assert(humanoid.RootPart ~= nil, "No RootPart was found in the provided rig")
assert(char:FindFirstChild("HumanoidRootPart"), "No HumanoidRootPart was found in the provided rig")
if not isPlayer then
for _, v: BasePart in ipairs(char:GetDescendants()) do
if v:IsA("BasePart") then
v:SetNetworkOwner(nil)
end
end
end
-- Setup ragdoll
char.Head.Size = Vector3.new(1, 1, 1)
humanoid.BreakJointsOnDeath = false
humanoid.RequiresNeck = true
local clones = {}
for _, v in ipairs(ragParts) do
clones[v.Name] = v:Clone()
end
local folder1 = Instance.new("Folder")
folder1.Name = "RagdollConstraints"
for _, v in pairs(clones) do
if v:IsA("Attachment") then
v.Parent = char[v:GetAttribute("Parent")]
elseif v:IsA("BallSocketConstraint") then
v.Attachment0 = clones[v:GetAttribute("0")]
v.Attachment1 = clones[v:GetAttribute("1")]
v.Parent = folder1
end
end
folder1.Parent = char
local folder2 = Instance.new("Folder")
folder2.Name = "Motors"
local value
for _, v in ipairs(char.Torso:GetChildren()) do
if v:IsA("Motor6D") then
value = Instance.new("ObjectValue")
value.Value = v
value.Parent = folder2
end
end
folder2.Parent = folder1
-- Ragdoll trigger
local trigger = Instance.new("BoolValue")
trigger.Name = "RagdollTrigger"
trigger.Parent = char
trigger.Changed:Connect(function(bool)
if bool then
module:Ragdoll(char)
else
module:Unragdoll(char)
end
end)
humanoid.Died:Once(function()
trigger.Value = true
end)
end
function module:Ragdoll(char: Model)
if not char.Humanoid then return end
char.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, false)
char.Humanoid.AutoRotate = false
local player = Players:GetPlayerFromCharacter(char)
if player then
player.CameraMinZoomDistance = player.CameraMaxZoomDistance
playRandomSound(char)
end
char:AddTag("CanGrab")
for _, v in ipairs(char.RagdollConstraints.Motors:GetChildren()) do
v.Value.Enabled = false
end
for _, v in ipairs(char:GetChildren()) do
if v:IsA("BasePart") then
v.CollisionGroup = "Ragdoll"
--createCollider(v)
end
end
local hrp = char:FindFirstChild("HumanoidRootPart")
local rootJoint = hrp:FindFirstChildOfClass("Motor6D")
if rootJoint then
task.spawn(function()
rootJoint.Enabled = false
task.wait()
rootJoint.Enabled = true
end)
end
local newSFX = ImpactSFX:Clone()
newSFX.Parent = char
newSFX.Enabled = true
hrp:ApplyAngularImpulse(Vector3.new(-120, 0, 0))
end
function module:Unragdoll(char: Model)
if not char.Humanoid then return end
char.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, true)
local player = Players:GetPlayerFromCharacter(char)
if player then
player.CameraMinZoomDistance = defaultMinZoomDistance
end
char:RemoveTag("CanGrab")
for _, v in ipairs(char.RagdollConstraints.Motors:GetChildren()) do
v.Value.Enabled = true
end
for _, v in ipairs(char:GetChildren()) do
if v:IsA("BasePart") then
v.CollisionGroup = player and "Players" or "Default"
--[[if v:HasTag("Collider") then
v:Destroy()
end]]--
end
end
local foundSFX = char:FindFirstChild("ImpactSFX")
if foundSFX then
foundSFX:Destroy()
end
char.Humanoid.AutoRotate = true
end
return module
