-- [[ Rscripts Risk Notice ]] -- This script is not verified by rscripts.net. Deal with caution. -- -- Stay safe: -- • Never log in on unofficial Roblox sites or lookalike domains. -- • Real Roblox links use roblox.com (check the .com ending). -- • Treat fake Roblox login / "claim reward" pages as phishing. -- [[ End Rscripts Risk Notice ]] local Players = game:GetService("Players") local Workspace = game:GetService("Workspace") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local player = Players.LocalPlayer local playerGui = player:WaitForChild("PlayerGui") -- Останавливаем предыдущую версию. local old = playerGui:FindFirstChild("P_RallyTest") if old then local event = old:FindFirstChild("Stop") if event and event:IsA("BindableEvent") then event:Fire() else old:Destroy() end end local gui = Instance.new("ScreenGui") gui.Name = "P_RallyTest" gui.ResetOnSpawn = false gui.Parent = playerGui local stopEvent = Instance.new("BindableEvent") stopEvent.Name = "Stop" stopEvent.Parent = gui local running = true local moving = false local generation = 0 local connections = {} local SPEED = 300 local MAX_GAP = 25 local MAX_DEVIATION = 12 local function connect(signal, callback) local connection = signal:Connect(callback) table.insert(connections, connection) return connection end local function make(className, parent, properties) local object = Instance.new(className) for key, value in pairs(properties) do object[key] = value end object.Parent = parent return object end local function button(parent, text, position, size) return make("TextButton", parent, { Position = position, Size = size, BackgroundColor3 = Color3.fromRGB(38, 38, 38), BorderSizePixel = 0, Text = text, TextColor3 = Color3.fromRGB(235, 235, 235), Font = Enum.Font.Gotham, TextSize = 14, TextWrapped = true }) end local main = make("Frame", gui, { Position = UDim2.fromOffset(12, 75), Size = UDim2.fromOffset(300, 220), BackgroundColor3 = Color3.fromRGB(18, 18, 18), BorderSizePixel = 0, Active = true }) local header = make("TextLabel", main, { Size = UDim2.new(1, -84, 0, 38), BackgroundColor3 = Color3.fromRGB(28, 28, 28), BorderSizePixel = 0, Text = " RALLY | МАРШРУТ", TextColor3 = Color3.fromRGB(235, 235, 235), Font = Enum.Font.GothamBold, TextSize = 14, TextXAlignment = Enum.TextXAlignment.Left, Active = true }) local minimize = button( main, "—", UDim2.new(1, -84, 0, 0), UDim2.fromOffset(42, 38) ) local close = button( main, "X", UDim2.new(1, -42, 0, 0), UDim2.fromOffset(42, 38) ) local onButton = button( main, "ВКЛ", UDim2.fromOffset(12, 48), UDim2.fromOffset(132, 38) ) local offButton = button( main, "ВЫКЛ", UDim2.fromOffset(156, 48), UDim2.fromOffset(132, 38) ) local info = make("TextLabel", main, { Position = UDim2.fromOffset(12, 94), Size = UDim2.new(1, -24, 0, 24), BackgroundTransparency = 1, Text = "Скорость: 300 studs/с | F6 — старт / стоп", TextColor3 = Color3.fromRGB(210, 210, 210), Font = Enum.Font.Gotham, TextSize = 12, TextWrapped = true }) local status = make("TextLabel", main, { Position = UDim2.fromOffset(12, 124), Size = UDim2.new(1, -24, 0, 84), BackgroundTransparency = 1, Text = "Сядь в машину на старте.\nRightShift — свернуть.", TextColor3 = Color3.fromRGB(170, 170, 170), Font = Enum.Font.Gotham, TextSize = 12, TextWrapped = true }) local reopen = button( gui, "RALLY", UDim2.fromOffset(12, 75), UDim2.fromOffset(76, 40) ) reopen.Visible = false local function updateButtons() onButton.BackgroundColor3 = moving and Color3.fromRGB(62, 62, 62) or Color3.fromRGB(38, 38, 38) offButton.BackgroundColor3 = not moving and Color3.fromRGB(62, 62, 62) or Color3.fromRGB(38, 38, 38) end local function setVisible(value) main.Visible = value reopen.Visible = not value end local function cancel(message) generation += 1 moving = false updateButtons() if running and message then status.Text = message end end local function getVehicle() local character = player.Character local humanoid = character and character:FindFirstChildOfClass("Humanoid") local seat = humanoid and humanoid.SeatPart local cars = Workspace:FindFirstChild("Cars") if not humanoid or humanoid.Health <= 0 or not seat or not cars then return nil end local car = seat while car and car.Parent ~= cars do car = car.Parent end if not car or not car:IsA("Model") or not seat:IsDescendantOf(car) then return nil end return car, seat, humanoid, character end local function findStage() local world = Workspace:FindFirstChild("World") if not world then return nil end for _, obj in ipairs(world:GetChildren()) do if obj.Name:lower():find("stage_", 1, true) and obj:FindFirstChild("Collision") then return obj end end return nil end local function getRoads(stage) local roads = {} local collision = stage and stage:FindFirstChild("Collision") if not collision then return roads end for _, obj in ipairs(collision:GetDescendants()) do if obj:IsA("BasePart") and obj.Name:lower() == "road" then table.insert(roads, obj) end end return roads end local function closestRoad(roads, position) local closest, distance for _, road in ipairs(roads) do local d = (road.Position - position).Magnitude if not distance or d < distance then closest = road distance = d end end return closest, distance end local function nextRoad(roads, current, direction, visited) local best, bestScore for _, candidate in ipairs(roads) do if candidate ~= current and not visited[candidate] and candidate.Parent then local delta = candidate.Position - current.Position local gap = delta.Magnitude if gap > 2 and gap <= MAX_GAP then local forward = delta.Unit:Dot(direction) if forward > 0.25 then local score = gap + (1 - forward) * 12 if not bestScore or score < bestScore then best = candidate bestScore = score end end end end end return best end -- Обнуляем скорость каждой отдельной физической сборки машины. local function stabilize(car) local assemblies = {} for _, obj in ipairs(car:GetDescendants()) do if obj:IsA("BasePart") and not obj.Anchored then local root = obj.AssemblyRootPart or obj if not assemblies[root] then assemblies[root] = true pcall(function() root.AssemblyLinearVelocity = Vector3.zero root.AssemblyAngularVelocity = Vector3.zero end) end end end end local function startRoute() if moving or not running then return end local car, seat, humanoid, character = getVehicle() if not car then status.Text = "Сядь в машину и начни заезд." return end local stage = findStage() if not stage then status.Text = "Этап с дорогой не найден." return end local roads = getRoads(stage) local current, distance = closestRoad(roads, seat.Position) if not current or distance > 25 then status.Text = "Дорога рядом с машиной не найдена." return end generation += 1 local token = generation moving = true updateButtons() local visited = {[current] = true} local direction = seat.CFrame.LookVector local heightOffset = seat.Position.Y - current.Position.Y local lastExpected = seat.Position local stageName = tostring(stage:GetAttribute("StageId") or stage.Name) local count = 0 status.Text = "Маршрут запущен. Скорость: 300 studs/с." task.spawn(function() while running and moving and generation == token do if player.Character ~= character or humanoid.Health <= 0 or humanoid.SeatPart ~= seat or not car.Parent or not seat.Parent or not stage.Parent or not current.Parent then cancel("Остановлено: машина, персонаж или трасса изменились.") return end roads = getRoads(stage) local nextPart = nextRoad(roads, current, direction, visited) if not nextPart then status.Text = "Продолжение не найдено. Жду загрузку 3 секунды..." local deadline = os.clock() + 3 while running and moving and generation == token and os.clock() < deadline do -- Удерживаем машину от разгона во время ожидания. if car.Parent then stabilize(car) end task.wait(0.5) if not current.Parent or not stage.Parent then break end roads = getRoads(stage) nextPart = nextRoad(roads, current, direction, visited) if nextPart then break end end end if not running or not moving or generation ~= token then return end if not nextPart or not nextPart.Parent or not current.Parent then cancel("Конец найденной дороги. Финиш не подтверждён.") return end local roadDelta = nextPart.Position - current.Position if roadDelta.Magnitude < 0.1 then cancel("Направление дороги не определено.") return end local nextDirection = roadDelta.Unit local targetPosition = nextPart.Position + Vector3.new(0, heightOffset, 0) local delta = targetPosition - seat.Position local horizontal = Vector3.new(delta.X, 0, delta.Z) if horizontal.Magnitude < 0.1 then cancel("Направление машины не определено.") return end local startSeat = seat.CFrame local targetSeat = CFrame.lookAt( targetPosition, targetPosition + horizontal.Unit ) local duration = math.max(delta.Magnitude / SPEED, 0.05) local started = os.clock() while true do if not running or not moving or generation ~= token then return end if player.Character ~= character or humanoid.Health <= 0 or humanoid.SeatPart ~= seat or not car.Parent or not seat.Parent or not nextPart.Parent then cancel("Остановлено: машина или дорога изменились.") return end if (seat.Position - lastExpected).Magnitude > MAX_DEVIATION then cancel("Остановлено: сильное отклонение или откат.") return end local alpha = math.min((os.clock() - started) / duration, 1) local desiredSeat = startSeat:Lerp(targetSeat, alpha) local ok, err = pcall(function() stabilize(car) local pivot = car:GetPivot() local desiredPivot = desiredSeat * seat.CFrame:Inverse() * pivot car:PivotTo(desiredPivot) stabilize(car) end) if not ok then cancel("Ошибка перемещения: " .. tostring(err)) return end lastExpected = desiredSeat.Position if alpha >= 1 then break end RunService.Heartbeat:Wait() end current = nextPart visited[current] = true direction = nextDirection count += 1 status.Text = string.format( "%s: пройдено сегментов %d.\nF6 — остановить.", stageName, count ) end end) end local function toggleRoute() if moving then cancel("Маршрут остановлен пользователем.") else startRoute() end end connect(onButton.Activated, startRoute) connect(offButton.Activated, function() if moving then cancel("Маршрут остановлен пользователем.") end end) connect(minimize.Activated, function() setVisible(false) end) connect(reopen.Activated, function() setVisible(true) end) connect(UserInputService.InputBegan, function(input) if UserInputService:GetFocusedTextBox() then return end if input.KeyCode == Enum.KeyCode.F6 then toggleRoute() elseif input.KeyCode == Enum.KeyCode.RightShift then setVisible(not main.Visible) end end) connect(player.CharacterRemoving, function() if moving then cancel("Остановлено: персонаж сменился.") end end) local dragInput local dragStart local startPosition connect(header.InputBegan, function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragInput = input dragStart = input.Position startPosition = main.Position end end) connect(UserInputService.InputChanged, function(input) if not dragInput then return end local mouseDrag = dragInput.UserInputType == Enum.UserInputType.MouseButton1 and input.UserInputType == Enum.UserInputType.MouseMovement if mouseDrag or input == dragInput then local delta = input.Position - dragStart main.Position = UDim2.new( startPosition.X.Scale, startPosition.X.Offset + delta.X, startPosition.Y.Scale, startPosition.Y.Offset + delta.Y ) end end) connect(UserInputService.InputEnded, function(input) if input == dragInput then dragInput = nil end end) local function stop() if not running then return end cancel() running = false for _, connection in ipairs(connections) do connection:Disconnect() end gui:Destroy() end connect(close.Activated, stop) connect(stopEvent.Event, stop) updateButtons()