local Players = game:GetService("Players") local RunService = game:GetService("RunService") local player = Players.LocalPlayer -- ================= SETTINGS ================= local CHARACTER_TILT_ANGLE = math.rad(45.5) local VEHICLE_TILT_ANGLE = math.rad(25) local FIRST_PERSON_SMOOTHNESS = 100 local THIRD_PERSON_SMOOTHNESS = 16 local BLOCKED_SMOOTHNESS = 4 local VEHICLE_SMOOTHNESS = 8 local MIN_DIR_MAGNITUDE = 0.01 local VEHICLE_TORQUE = 80000 local FIRST_PERSON_DISTANCE_THRESHOLD = 2 local BLOCK_VELOCITY_MULTIPLIER = 6 -- ============================================ local function isFirstPerson(character) local camera = workspace.CurrentCamera local head = character:FindFirstChild("Head") if camera and head then local dist = (camera.CFrame.Position - head.Position).Magnitude return dist < FIRST_PERSON_DISTANCE_THRESHOLD end return false end local function setupCharacter(character) local humanoid = character:WaitForChild("Humanoid") local hrp = character:WaitForChild("HumanoidRootPart") humanoid.AutoRotate = false -- Cleanup cũ for _,v in pairs(hrp:GetChildren()) do if v.Name == "LeanAttachment" or v.Name == "LeanAlign" or v.Name == "VehicleLeanAttachment" or v.Name == "VehicleLeanAlign" then v:Destroy() end end -- ================= CHARACTER ALIGN ================= local attachment = Instance.new("Attachment") attachment.Name = "LeanAttachment" attachment.Parent = hrp local align = Instance.new("AlignOrientation") align.Name = "LeanAlign" align.Mode = Enum.OrientationAlignmentMode.OneAttachment align.Attachment0 = attachment align.RigidityEnabled = true align.Responsiveness = 2000 align.MaxTorque = Vector3.new(1e6,1e6,1e6) align.Parent = hrp -- ================= VEHICLE ================= local vehicleAlign local vehicleAttachment local seatPart local isSeated = false local currentVehicleAngle = 0 local currentCharCF = hrp.CFrame local function setupVehicle(seat) seatPart = seat isSeated = true if vehicleAlign then vehicleAlign:Destroy() end if vehicleAttachment then vehicleAttachment:Destroy() end vehicleAttachment = Instance.new("Attachment") vehicleAttachment.Name = "VehicleLeanAttachment" vehicleAttachment.Parent = seatPart vehicleAlign = Instance.new("AlignOrientation") vehicleAlign.Name = "VehicleLeanAlign" vehicleAlign.Mode = Enum.OrientationAlignmentMode.OneAttachment vehicleAlign.Attachment0 = vehicleAttachment vehicleAlign.PrimaryAxisOnly = true vehicleAlign.PrimaryAxis = Vector3.new(1,0,0) vehicleAlign.RigidityEnabled = false vehicleAlign.Responsiveness = 40 vehicleAlign.MaxTorque = Vector3.new(VEHICLE_TORQUE,0,0) vehicleAlign.Parent = seatPart currentVehicleAngle = 0 end local function cleanupVehicle() isSeated = false seatPart = nil currentVehicleAngle = 0 if vehicleAlign then vehicleAlign:Destroy() vehicleAlign = nil end if vehicleAttachment then vehicleAttachment:Destroy() vehicleAttachment = nil end end humanoid.Seated:Connect(function(active, seat) if active and seat and seat:IsA("VehicleSeat") then setupVehicle(seat) else cleanupVehicle() end end) ----------------------------------------------------- RunService.RenderStepped:Connect(function(dt) if not character.Parent then return end -- ================= VEHICLE MODE ================= if isSeated and seatPart and vehicleAlign and seatPart.Parent then align.Enabled = false currentVehicleAngle = currentVehicleAngle + (VEHICLE_TILT_ANGLE - currentVehicleAngle) * math.clamp(dt * VEHICLE_SMOOTHNESS,0,1) vehicleAlign.CFrame = CFrame.Angles(currentVehicleAngle,0,0) return end -- ================= CHARACTER MODE ================= align.Enabled = true local camera = workspace.CurrentCamera local moveInput = humanoid.MoveDirection local moveDir = nil if camera then if isFirstPerson(character) then local camLook = camera.CFrame.LookVector local flatCam = Vector3.new(camLook.X,0,camLook.Z) if flatCam.Magnitude > 0 then moveDir = flatCam.Unit end else if moveInput.Magnitude > MIN_DIR_MAGNITUDE then moveDir = moveInput end end end -- ===== PHÁT HIỆN BỊ CẢN (giống engine) ===== local realVelocity = hrp.AssemblyLinearVelocity local flatVelocity = Vector3.new(realVelocity.X,0,realVelocity.Z) local isBlocked = false if moveInput.Magnitude > MIN_DIR_MAGNITUDE then if flatVelocity.Magnitude < moveInput.Magnitude * BLOCK_VELOCITY_MULTIPLIER then isBlocked = true end end local targetCF = currentCharCF if moveDir then local lookCF = CFrame.lookAt( hrp.Position, hrp.Position + Vector3.new(moveDir.X,0,moveDir.Z) ) targetCF = lookCF * CFrame.Angles(CHARACTER_TILT_ANGLE,0,0) end -- ===== SMOOTHNESS LOGIC ===== local smoothness if isBlocked then smoothness = BLOCKED_SMOOTHNESS else smoothness = isFirstPerson(character) and FIRST_PERSON_SMOOTHNESS or THIRD_PERSON_SMOOTHNESS end currentCharCF = currentCharCF:Lerp( targetCF, math.clamp(dt * smoothness,0,1) ) align.CFrame = currentCharCF end) end -- Setup local character = player.Character or player.CharacterAdded:Wait() setupCharacter(character) player.CharacterAdded:Connect(setupCharacter)