Загрузка данных


local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local Settings = {
	FallSpeedToRagdoll = 90,  -- скорость падения для рагдола (примерно 20 стадов высоты)
	FallRagdollTime = 2.5,    -- сколько секунд лежишь после падения
	TestKey = Enum.KeyCode.X, -- тест рагдола
	TestRagdollTime = 3,
}

local player = Players.LocalPlayer
local character, humanoid, root
local ragdolled = false
local created = {}
local collideBackup = {}
local fallSpeed = 0
local token = 0

local function limitsFor(name)
	if name:find("Neck") then return 40, 30 end
	if name:find("Knee") or name:find("Elbow") then return 15, 5 end
	if name:find("Ankle") or name:find("Wrist") then return 25, 10 end
	return 65, 40
end

local function startRagdoll(duration)
	if ragdolled or not humanoid or not character then return end
	ragdolled = true
	token += 1
	local myToken = token
	character:SetAttribute("Ragdoll", true)
	humanoid.AutoRotate = false
	humanoid:ChangeState(Enum.HumanoidStateType.Physics)

	for _, d in ipairs(character:GetDescendants()) do
		if d:IsA("BasePart") and d ~= root and not d:FindFirstAncestorOfClass("Accessory") then
			collideBackup[d] = d.CanCollide
			d.CanCollide = true
		end
		if d:IsA("Motor6D") and d.Part0 and d.Part1 and d.Part0 ~= root then
			local a0 = Instance.new("Attachment")
			a0.CFrame = d.C0
			a0.Parent = d.Part0
			local a1 = Instance.new("Attachment")
			a1.CFrame = d.C1
			a1.Parent = d.Part1

			local ball = Instance.new("BallSocketConstraint")
			ball.Attachment0 = a0
			ball.Attachment1 = a1
			ball.LimitsEnabled = true
			ball.TwistLimitsEnabled = true
			local up, tw = limitsFor(d.Name)
			ball.UpperAngle = up
			ball.TwistLowerAngle = -tw
			ball.TwistUpperAngle = tw
			ball.Parent = d.Part0

			local nc = Instance.new("NoCollisionConstraint")
			nc.Part0 = d.Part0
			nc.Part1 = d.Part1
			nc.Parent = d.Part0

			d.Enabled = false
			table.insert(created, { d, a0, a1, ball, nc })
		end
	end

	if duration then
		task.delay(duration, function()
			if token ~= myToken or not ragdolled then return end
			if humanoid.Health <= 0 then return end
			for _, set in ipairs(created) do
				set[1].Enabled = true
				for i = 2, 5 do set[i]:Destroy() end
			end
			created = {}
			for part, value in pairs(collideBackup) do
				if part.Parent then part.CanCollide = value end
			end
			collideBackup = {}

			local pos = root.Position + Vector3.new(0, 3, 0)
			local look = root.CFrame.LookVector
			character:PivotTo(CFrame.new(pos, pos + Vector3.new(look.X, 0, look.Z)))
			humanoid.AutoRotate = true
			humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
			ragdolled = false
			character:SetAttribute("Ragdoll", false)
		end)
	end
end

local function setup(char)
	character = char
	humanoid = char:WaitForChild("Humanoid")
	root = char:WaitForChild("HumanoidRootPart")
	ragdolled = false
	created = {}
	collideBackup = {}
	fallSpeed = 0

	humanoid.Died:Connect(function()
		startRagdoll()
	end)

	humanoid.StateChanged:Connect(function(_, new)
		if new == Enum.HumanoidStateType.Landed then
			if fallSpeed >= Settings.FallSpeedToRagdoll then
				startRagdoll(Settings.FallRagdollTime)
			end
			fallSpeed = 0
		elseif new == Enum.HumanoidStateType.Running then
			fallSpeed = 0
		end
	end)
end

RunService.Heartbeat:Connect(function()
	if not root or ragdolled then return end
	local vy = root.AssemblyLinearVelocity.Y
	if vy < 0 then fallSpeed = math.max(fallSpeed, -vy) end
end)

UserInputService.InputBegan:Connect(function(input, processed)
	if processed then return end
	if input.KeyCode == Settings.TestKey then
		startRagdoll(Settings.TestRagdollTime)
	end
end)

player.CharacterAdded:Connect(setup)
if player.Character then setup(player.Character) end