local owner = game:GetService("Players").LocalPlayer local rs = game:GetService("RunService").RenderStepped local hb = game:GetService("RunService").Heartbeat local camera = workspace.Camera local input = game:GetService("UserInputService") local debris = game:GetService("Debris") local mouse = owner:GetMouse() -- Movement variables local move = Vector3.new() local velocity = Vector3.new() local velocity2 = Vector3.new() local human = nil local speed = 16 local charge = 0 local ptick = tick() local ltick = tick() local sprint = false local grounded = false local moving = false local firstperson = false local ignores = {} local lastjump = tick() local lastnoise = tick() local hurting = false local damage = true local chp = 100 local isR15 = false -- Physics objects local rotvel = Instance.new("BodyAngularVelocity") rotvel.MaxTorque = rotvel.MaxTorque * 90 local force = Instance.new("BodyVelocity") force.MaxForce = Vector3.new(force.MaxForce.X, 0, force.MaxForce.Z) * 40 local leftgrab = Instance.new("BallSocketConstraint") local rightgrab = Instance.new("BallSocketConstraint") local leftarm, rightarm = nil, nil -- Storage local colliders = {} local ballsockets = {} local ps = {} local sounds = {} local ss = 1 -- Sound IDs local kactus = {"3932504231", "3932505023", "3932506183", "3932506625", "4306980885"} local noises = {'5450183076', '5450183948', '5450184712', '5450212479', '5450213341'} local slaps = {"3848124871", "3848125583", "3848126035", "3929466751"} local snaps = {"704141469", "5645905885"} -- Monkey sounds local monkeysounds = Instance.new("Sound") monkeysounds.SoundId = "rbxassetid://5987858580" monkeysounds.Volume = 5 monkeysounds.RollOffMode = Enum.RollOffMode.InverseTapered monkeysounds.RollOffMinDistance = 30 monkeysounds.RollOffMaxDistance = 50 -- Create sound pool for i = 1, 5 do local sound = Instance.new("Sound") sound.PlayOnRemove = true sounds[#sounds + 1] = sound end -- R6/R15 Detection local function detectRigType(character) if character:FindFirstChild("UpperTorso") then return "R15" elseif character:FindFirstChild("Torso") then return "R6" end return nil end -- Get appropriate body parts based on rig type local function getBodyParts(character, rigType) local parts = {} if rigType == "R15" then parts.LeftArm = character:FindFirstChild("LeftHand") parts.RightArm = character:FindFirstChild("RightHand") parts.LeftLeg = character:FindFirstChild("LeftFoot") parts.RightLeg = character:FindFirstChild("RightFoot") parts.Torso = character:FindFirstChild("UpperTorso") parts.LowerTorso = character:FindFirstChild("LowerTorso") parts.Head = character:FindFirstChild("Head") else -- R6 parts.LeftArm = character:FindFirstChild("Left Arm") parts.RightArm = character:FindFirstChild("Right Arm") parts.LeftLeg = character:FindFirstChild("Left Leg") parts.RightLeg = character:FindFirstChild("Right Leg") parts.Torso = character:FindFirstChild("Torso") parts.Head = character:FindFirstChild("Head") end return parts end -- Utility Functions function Destroyed(x) if x.Parent then return false end local _, result = pcall(function() x.Parent = x end) return result:match("locked") and true or false end function lerp(a, b, t) return a + (b - a) * t end function playsound(id, parent, volume, pitch) local sound = sounds[ss] sound.SoundId = "rbxassetid://" .. id sound.Volume = volume or 1 sound.Pitch = pitch or math.random(95, 105) / 100 sound.Parent = parent sound.RollOffMode = Enum.RollOffMode.InverseTapered sound.RollOffMinDistance = 30 sound.RollOffMaxDistance = 50 sound.Parent = nil ss = ss + 1 if ss > #sounds then ss = 1 end end function hashuman(v) local model = v:FindFirstAncestorOfClass("Model") if model and model:FindFirstChildOfClass("Humanoid") then return model:FindFirstChildOfClass("Humanoid") end return false end -- Swait function for precise timing local Swait, Artificial = (function() local a = 0 local b = 0 local c = 1 / 60 local d = Instance.new("BindableEvent", script) local function ArtificalStuff(e) b = b + e while a < b do a = a + c d:Fire() end end hb:Connect(ArtificalStuff) return function(f) f = tonumber(f) if type(f) ~= "number" then f = 1 end for g = 1, f do d.Event:Wait() end end, d end)() -- Health damage function function ouch() if not hurting then hurting = true local parts = {} if human.Health > 0 then if human.Health < chp then for i, v in pairs(owner.Character:GetDescendants()) do if v:IsA("Decal") or v:IsA("BasePart") or v:IsA("Texture") then parts[#parts + 1] = {v, v.Transparency} end end coroutine.wrap(function() local rand = {6.57, 18.79} if not monkeysounds or Destroyed(monkeysounds) then monkeysounds = monkeysounds:Clone() end monkeysounds.Parent = human.RootPart monkeysounds:Play() monkeysounds.TimePosition = rand[math.random(1, #rand)] monkeysounds.Pitch = math.random(90, 110) / 100 Swait((60 * 0.35) / monkeysounds.Pitch) monkeysounds:Stop() end)() chp = human.Health for i = 1, 12 do for i, v in pairs(parts) do v[1].Transparency = 1 end Swait(60 * 0.05) for i, v in pairs(parts) do v[1].Transparency = v[2] end Swait(60 * 0.05) end end hurting = false else playsound("12222152", human.RootPart, 2, 0.8) end else if human.Health < chp then human.Health = chp end end chp = human.Health end -- Grab functions function grab(part, ballsocket, pos) if not part or Destroyed(part) then return end local att0, att1 = ballsocket.Attachment0, ballsocket.Attachment1 if not att0 or Destroyed(att0) then att0 = Instance.new("Attachment") att0.Position = Vector3.new(0, -ballsocket.Parent.Size.Y / 2, 0) ballsocket.Attachment0 = att0 end if not att1 or Destroyed(att1) then att1 = Instance.new("Attachment") ballsocket.Attachment1 = att1 end att1.CFrame = part.CFrame:inverse() * CFrame.new(pos) att1.Parent = part att0.Parent = ballsocket.Parent local h = hashuman(part) if h and h.RootPart and h.RootPart:IsDescendantOf(workspace) and not h.RootPart:IsGrounded() then h.RootPart:SetNetworkOwner(owner) end end function letgo(part, ballsocket) if not part or Destroyed(part) then return end local att0, att1 = ballsocket.Attachment0, ballsocket.Attachment1 if att1 and not Destroyed(att1) then att1.Parent = nil end local h = hashuman(part) if h and h.RootPart and h.RootPart:IsDescendantOf(workspace) and not h.RootPart:IsGrounded() then local plr for i, v in pairs(game.Players:GetPlayers()) do if v.Character and h.Parent == v.Character then plr = v end end if plr then h.RootPart:SetNetworkOwner(plr) end end end -- Touch damage function touched(part) local debounce = false part.Touched:Connect(function(p) if not debounce and human and human.RootPart and human.RootPart.RotVelocity.magnitude >= 12 and part.Velocity.magnitude >= 8 and not p:IsDescendantOf(owner.Character) then local humanoid = hashuman(p) local impact = (p.Velocity - human.RootPart.Velocity).magnitude if impact / 120 >= 1.25 and math.random(1, 2) == 1 then playsound(snaps[math.random(1, #snaps)], human.RootPart, impact / 50, math.random(80, 110) / 100) human:TakeDamage(impact / 200) end if humanoid and damage then debounce = true if impact > 50 and math.random(1, 2) == 1 then humanoid:TakeDamage(impact / 25) playsound(slaps[math.random(1, #slaps)], human.RootPart, impact / 7, math.random(90, 110) / 100) if math.random(1, 3) == 1 then humanoid.Sit = true else local tool = humanoid.Parent:FindFirstChildOfClass("Tool") if tool and humanoid.RootPart and tool:FindFirstChild("Handle") then humanoid:UnequipTools() tool.Parent = workspace tool.Handle.CFrame = tool.Handle.CFrame + humanoid.RootPart.CFrame.LookVector * (tool.Handle.Size.magnitude + 1) end end end local bvel = Instance.new("BodyVelocity") bvel.MaxForce = Vector3.new(math.huge, math.huge, math.huge) bvel.Velocity = part.Velocity / 1.4 bvel.Parent = p debris:AddItem(bvel, 0.125) p.RotVelocity = part.RotVelocity task.wait(0.1) debounce = false end end end) end -- Movement functions function jump() if not human or not human.RootPart then return end local new = Instance.new("BodyVelocity", human.RootPart) new.MaxForce = new.MaxForce * 200 new.Velocity = Vector3.new(0, 1000 * human.RootPart.Size.Y, 0) debris:AddItem(new, 0.075) if grounded then lastjump = tick() local pitch = math.random(90, 100) / 100 playsound("12222200", human.RootPart, 3, pitch) end end function launch() if not human or not human.RootPart then return end local pitch = math.random(90, 100) / 200 playsound("12222200", human.RootPart, 3, pitch) local new = Instance.new("BodyVelocity", human.RootPart) new.MaxForce = Vector3.new(math.huge, math.huge, math.huge) new.Velocity = (camera.CFrame.LookVector + Vector3.new(0, 0.3, 0)) * charge velocity2 += new.Velocity debris:AddItem(new, 0.1) end -- R15-specific joint angle limits local R15JointLimits = { -- Head ["Neck"] = { UpperAngle = 45, TwistLowerAngle = -60, TwistUpperAngle = 60 }, -- Arms ["LeftShoulder"] = { UpperAngle = 90, TwistLowerAngle = -90, TwistUpperAngle = 90 }, ["RightShoulder"] = { UpperAngle = 90, TwistLowerAngle = -90, TwistUpperAngle = 90 }, ["LeftElbow"] = { UpperAngle = 90, TwistLowerAngle = -5, TwistUpperAngle = 5 }, ["RightElbow"] = { UpperAngle = 90, TwistLowerAngle = -5, TwistUpperAngle = 5 }, ["LeftWrist"] = { UpperAngle = 30, TwistLowerAngle = -30, TwistUpperAngle = 30 }, ["RightWrist"] = { UpperAngle = 30, TwistLowerAngle = -30, TwistUpperAngle = 30 }, -- Legs ["LeftHip"] = { UpperAngle = 90, TwistLowerAngle = -45, TwistUpperAngle = 45 }, ["RightHip"] = { UpperAngle = 90, TwistLowerAngle = -45, TwistUpperAngle = 45 }, ["LeftKnee"] = { UpperAngle = 90, TwistLowerAngle = -5, TwistUpperAngle = 5 }, ["RightKnee"] = { UpperAngle = 90, TwistLowerAngle = -5, TwistUpperAngle = 5 }, ["LeftAnkle"] = { UpperAngle = 30, TwistLowerAngle = -20, TwistUpperAngle = 20 }, ["RightAnkle"] = { UpperAngle = 30, TwistLowerAngle = -20, TwistUpperAngle = 20 } } -- Ragdoll function with R15 support and proper torso function ragdoll(model, h) local rigType = detectRigType(model) isR15 = (rigType == "R15") for i, v in pairs(model:GetDescendants()) do if v:IsA("Motor6D") then if v.Part1 and v.Part0 and v.Part0 ~= h.RootPart then local bsc = Instance.new("BallSocketConstraint") local c = Instance.new("Part") local cw = Instance.new("Weld") local att0, att1 = Instance.new("Attachment"), Instance.new("Attachment") c.Size = v.Part1.Size / 2 c.Massless = true c.Transparency = 1 c.CanCollide = false c.Name = "Collider" cw.Part0 = v.Part1 cw.Part1 = c cw.Parent = c colliders[#colliders + 1] = { c, cw, v.Part1, v.Part0, v.C0, v.C1, Name = v.Name } c.Parent = v.Part1 att0.Parent = v.Part0 att1.Parent = v.Part1 att0.CFrame, att1.CFrame = v.C0, v.C1 bsc.Attachment0 = att0 bsc.Attachment1 = att1 bsc.LimitsEnabled = true bsc.TwistLimitsEnabled = true -- Apply specific limits for R15 joints if isR15 and R15JointLimits[v.Name] then local limits = R15JointLimits[v.Name] bsc.UpperAngle = limits.UpperAngle bsc.TwistLowerAngle = limits.TwistLowerAngle bsc.TwistUpperAngle = limits.TwistUpperAngle else -- Default limits for R6 or unlisted joints bsc.TwistLowerAngle = -90 bsc.TwistUpperAngle = 90 bsc.UpperAngle = 60 end bsc.Parent = v.Part1 v.Enabled = false -- Adjusted physics for R15 (lighter parts) if isR15 then v.Part1.CustomPhysicalProperties = PhysicalProperties.new(50, 0.3, 0.5, 1, 1) else v.Part1.CustomPhysicalProperties = PhysicalProperties.new(100, 0.3, 0.5, 1, 1) end -- Don't add touch to torso parts or head local torsoNames = {"Torso", "UpperTorso", "LowerTorso", "Head"} local isTorso = false for _, name in ipairs(torsoNames) do if v.Part1.Name == name then isTorso = true break end end if not isTorso then touched(v.Part1) end end end end end -- Input handling input.InputBegan:Connect(function(k, p) if not p then if k.KeyCode == Enum.KeyCode.R then if human and human.RootPart then owner.Character:MoveTo(human.RootPart.Position) if tick() - ptick <= 0.3 then -- Reconnect/reset human.RootPart.Anchored = true human.RootPart.CFrame = CFrame.new(0, 10, 0) for i, v in pairs(owner.Character:GetChildren()) do if v:IsA("BasePart") then v.Anchored = true v.CFrame = human.RootPart.CFrame v.Velocity = Vector3.new() v.RotVelocity = Vector3.new() v.Anchored = false end end human.RootPart.Anchored = false end ptick = tick() end elseif k.KeyCode == Enum.KeyCode.F then firstperson = not firstperson elseif k.KeyCode == Enum.KeyCode.LeftControl then damage = not damage print("Damage mode:", damage) end end end) input.InputEnded:Connect(function(k, p) if not p then if k.KeyCode == Enum.KeyCode.T then if grounded then launch() end end end end) -- Mouse controls mouse.Button1Down:Connect(function() if not human or not human.RootPart then return end if mouse.Target and mouse.Target.Name ~= "Baseplate" and mouse.Target.Name ~= "Base" and (mouse.Hit.Position - human.RootPart.Position).magnitude <= 24 then local dif = mouse.Hit.p - human.RootPart.Position local part, pos = workspace:FindPartOnRayWithWhitelist(Ray.new(human.RootPart.Position, dif.Unit * 24), {mouse.Target}) if not pos then pos = mouse.Hit.p end if (pos - human.RootPart.Position).magnitude >= 30 then return end leftgrab.Parent = leftarm playsound("160432334", leftarm, 0.5) grab(mouse.Target, leftgrab, pos or mouse.Hit.p) end end) mouse.Button2Down:Connect(function() if not human or not human.RootPart then return end if mouse.Target and mouse.Target.Name ~= "Baseplate" and mouse.Target.Name ~= "Base" and (mouse.Hit.Position - human.RootPart.Position).magnitude <= 24 then local dif = mouse.Hit.p - human.RootPart.Position local part, pos = workspace:FindPartOnRayWithWhitelist(Ray.new(human.RootPart.Position, dif.Unit * 24), {mouse.Target}) if not pos then pos = mouse.Hit.p end if (pos - human.RootPart.Position).magnitude >= 30 then return end rightgrab.Parent = rightarm playsound("160432334", rightarm, 0.5) grab(mouse.Target, rightgrab, pos or mouse.Hit.p) end end) mouse.Button1Up:Connect(function() if leftgrab.Attachment1 and leftgrab.Attachment1.Parent then letgo(leftgrab.Attachment1.Parent, leftgrab) end leftgrab.Parent = nil end) mouse.Button2Up:Connect(function() if rightgrab.Attachment1 and rightgrab.Attachment1.Parent then letgo(rightgrab.Attachment1.Parent, rightgrab) end rightgrab.Parent = nil end) -- Character setup function load() colliders = {} ballsockets = {} ps = {} repeat task.wait() until owner.Character repeat human = owner.Character:FindFirstChildOfClass("Humanoid") task.wait() until human repeat task.wait() until human.RootPart -- Detect rig type local rigType = detectRigType(owner.Character) isR15 = (rigType == "R15") print("Rig Type Detected:", rigType) -- Set physical properties for i, v in pairs(owner.Character:GetChildren()) do if v:IsA("BasePart") then v.CustomPhysicalProperties = PhysicalProperties.new(Enum.Material.Metal) end end ragdoll(owner.Character, human) hurting = false chp = human.Health human.HealthChanged:Connect(ouch) -- Get appropriate limbs based on rig type local bodyParts = getBodyParts(owner.Character, rigType) leftarm = bodyParts.LeftArm rightarm = bodyParts.RightArm ignores = {owner.Character} end owner.CharacterAdded:Connect(load) if owner.Character then load() end -- Main loop while rs:wait() do if owner.Character then human = owner.Character:FindFirstChildOfClass("Humanoid") end camera = workspace:FindFirstChildOfClass("Camera") if not rotvel or Destroyed(rotvel) then rotvel = rotvel:Clone() end if not force or Destroyed(force) then force = force:Clone() end if human and camera and human.RootPart and owner.Character and owner.Character:FindFirstChild("Head") then -- Camera handling if firstperson then camera.CFrame = owner.Character.Head.CFrame owner.CameraMaxZoomDistance = 0 else owner.CameraMaxZoomDistance = 999 end -- Charge mechanic if input:IsKeyDown(Enum.KeyCode.T) then charge = lerp(charge, 240, 0.05) else charge = lerp(charge, 0, 0.1) end -- Character settings - DISABLE PlatformStand to prevent levitation human.PlatformStand = false human.AutoRotate = false human.CameraOffset = Vector3.new(0, (-human.RootPart.Size.Y / 2) - owner.Character.Head.Size.Y / 2, 0) -- Ground detection local part, pos = workspace:FindPartOnRayWithIgnoreList( Ray.new(human.RootPart.Position, Vector3.new(0, -human.RootPart.Size.Y * 1.25, 0)), ignores ) local wasGrounded = grounded if part and part.CanCollide then grounded = true else if part then table.insert(ignores, part) end grounded = false end -- Landing effects if not wasGrounded and grounded then for i = 1, 3 do playsound(noises[math.random(1, #noises)], human.RootPart, human.RootPart.Velocity.magnitude / 24, (math.random(85, 95) / 100)) end if human.RootPart.Velocity.Y <= -40 then playsound("4057626616", human.RootPart, 4, math.random(95, 105) / 100) if human.RootPart.Velocity.Y <= -160 then playsound("535681058", human.RootPart, 4, math.random(95, 105) / 100) human:TakeDamage(math.abs(human.RootPart.Velocity.Y / 5)) elseif human.RootPart.Velocity.Y <= -80 then human:TakeDamage(math.abs(human.RootPart.Velocity.Y / 5)) end end end -- Jump if input:IsKeyDown(Enum.KeyCode.Space) and grounded then jump() end -- Sprint sprint = input:IsKeyDown(Enum.KeyCode.LeftShift) if sprint then speed = 20 * 4 if moving then camera.FieldOfView = lerp(camera.FieldOfView, 80 + (charge / 6), 0.175) else camera.FieldOfView = lerp(camera.FieldOfView, 70 + (charge / 6), 0.175) end else camera.FieldOfView = lerp(camera.FieldOfView, 70 + (charge / 6), 0.25) speed = 15 end -- Movement velocity2 = velocity2:lerp(Vector3.new(), 0.25) velocity = Vector3.new(human.MoveDirection.X, 0, human.MoveDirection.Z) + velocity2 moving = velocity.magnitude >= 0.5 -- Apply forces force.Velocity = (velocity * 1.5) * human.RootPart.RotVelocity.magnitude rotvel.AngularVelocity = (Vector3.new(human.MoveDirection.Z, 0, -human.MoveDirection.X) * speed) if velocity.magnitude <= speed / 100 then rotvel.Parent = nil force.Parent = nil else rotvel.Parent = human.RootPart force.Parent = human.RootPart end -- Footstep sounds if grounded and moving and tick() - lastnoise >= 5 / human.RootPart.Velocity.magnitude and human.RootPart.RotVelocity.magnitude >= 4 then lastnoise = tick() playsound(noises[math.random(1, #noises)], human.RootPart, human.RootPart.Velocity.magnitude / 64, math.random(110, 120) / 100) end -- Maintain colliders for i, v in pairs(colliders) do if not v[1] or Destroyed(v[1]) then v[1] = v[1]:Clone() v[1].Parent = v[3] else v[1].Size = v[3].Size / 2 v[1].Massless = true v[1].Transparency = 1 v[1].CanCollide = false end if not v[2] or Destroyed(v[2]) then v[2] = v[2]:Clone() v[2].Parent = v[1] v[2].Part1 = v[1] v[2].Part0 = v[3] else v[2].Parent = v[1] v[2].Part1 = v[1] v[2].Part0 = v[3] v[2].C0, v[2].C1 = CFrame.new(), CFrame.new() v[2].Enabled = true end end -- ForceField for invincibility during hurt local ff = owner.Character:FindFirstChildOfClass("ForceField") if hurting and not ff then Instance.new("ForceField", owner.Character).Visible = false elseif not hurting and ff then ff:Destroy() end -- Other settings human.BreakJointsOnDeath = false if human.RootPart and not human.RootPart:IsGrounded() and human.RootPart.Parent then human.RootPart:SetNetworkOwner(owner) end -- Ensure RootJoint exists local root = owner.Character:FindFirstChild("HumanoidRootPart") local torso = owner.Character:FindFirstChild("Torso") or owner.Character:FindFirstChild("UpperTorso") if root and torso and not root:FindFirstChild("RootJoint") and not root:FindFirstChild("Root") then local weld = Instance.new("Weld", root) weld.Name = isR15 and "Root" or "RootJoint" weld.Part0 = root weld.Part1 = torso end -- Health regen human.Health += 0.25 end end