Rap Ability Test Script (Delta Mobile) – Autoplay: Auto Notes, Skip Mines 10 4 No Key

Rap Ability Test Script (Delta Mobile) – Autoplay: Auto Notes, Skip Mines

Rap Ability Test 0.22 · Roblox
Play
No key Mobile friendly Working · Nov 4
Report

Description

Rap Ability Autoplay is a Rap Ability Test 0.22 script you can run in Delta on Android, iOS or PC. It includes enable autoplay, skip mines, long notes and more. It is open source and uses the WindUI menu. Created by SarahHenderson. No key.

Key Features

  • Autoplay: hits notes with press and release
  • Skip mines and damage notes
  • Long note (sustain) support
  • Auto-detects your keybinds
  • Press and release offset settings
  • Player side override

Rap Ability Test 0.22 is a 4-key rhythm battle with daily and weekly leaderboards and Cheddar rewards. SarahHenderson’s Rap Ability Test script plays the chart for you through the same input path the game uses for real key presses. It also keeps your timing a little imperfect on purpose.

Tabs in the WindUI window

Autoplay

Enable Autoplay and Skip mines / damage notes. Long notes are held for their full tail and released at the end.

Timing

Press Offset (−100 to 100 ms), Release Offset for long-note tails (−100 to 200 ms), Press Leeway, and a Reset Timing button. The script notes these shifts don’t affect detection. They just fix early or late hits, like a tail that reads “Fresh −X ms”.

Keys

Your four lane keys are read from the game’s Settings → Controls. Edit them here if you rebind after launching.

Advanced

The humanizer: press and release jitter, clamps, Miss Chance and Bad/Good Chance (0–5%), plus a Player Side override for 1v1 lanes.

About the shadowban warning

The creator says the default humanizer values are user-tested to pass the game’s shadowban. A shadowbanned account can’t earn Cheddar or post leaderboard scores. If you drag a slider under the safe threshold, a “Risky setting” alert pops up. Leave the defaults alone unless you’re on an alt.

Loading

No key is needed. The code box holds the readable source, which pulls the WindUI library from a GitHub mirror (ofkotov/lib). Execute it (Delta is the headline executor, and the page also tests Arceus X, Fluxus, Codex and PC ones), then toggle the menu with the Delete key. Your executor has to support VirtualInputManager and debug upvalues for the note hits to work.

FAQ

Does it play on mobile? The page is marked mobile-friendly, and the game advertises strong mobile support. Use the window’s buttons, since there’s no Delete key on a phone.

Why do I sometimes get a Bad? That’s the humanizer doing its job. The small Bad chance is part of what keeps runs looking human.

Chart tip: if long notes keep finishing early, nudge Release Offset up in small steps instead of touching the jitter sliders. It only moves the tail release, so you fix the timing without going near the risky zone.

Tested With
DeltaCodexArceus XFluxusPC executors
Script CodeRap Ability Autoplay (SarahHenderson)
--[[
    Rap Ability Test — Autoplay

    Toggle the menu with the Delete key.
]]--

------------------------------------------------------------
-- 0) Cleanup previous instance(s)
------------------------------------------------------------
do
    local function killState(g)
        if type(g) ~= "table" then return end
        pcall(function() g.heartbeat:Disconnect() end)
        pcall(function() g.spoof:Disconnect() end)
        pcall(function() g.window:Destroy() end)
        pcall(function() g.window:Close() end)
        if g.players then
            for _, p in pairs(g.players) do
                if type(p) == "table" and not p.Ghost then p.Bot = nil end
            end
        end
    end
    killState(_G.__RAT_AUTOPLAY); _G.__RAT_AUTOPLAY = nil
    killState(_G.__FF_AUTOPLAY);  _G.__FF_AUTOPLAY  = nil
    if _G.__AUTOPLAY_CONN       then pcall(function() _G.__AUTOPLAY_CONN:Disconnect() end);       _G.__AUTOPLAY_CONN       = nil end
    if _G.__AUTOPLAY_SPOOF_CONN then pcall(function() _G.__AUTOPLAY_SPOOF_CONN:Disconnect() end); _G.__AUTOPLAY_SPOOF_CONN = nil end
    pcall(game:GetService("RunService").UnbindFromRenderStep,
          game:GetService("RunService"), "__AUTOPLAY_RENDER")
end

------------------------------------------------------------
-- 1) Services / module
------------------------------------------------------------
local RS         = game:GetService("ReplicatedStorage")
local Players    = game:GetService("Players")
local RunService = game:GetService("RunService")
local VIM        = game:GetService("VirtualInputManager")

local PlayerModule = require(RS:WaitForChild("Game"):WaitForChild("PlayerModule"))
local Trigger      = PlayerModule.Trigger
local Tick         = PlayerModule.Tick

------------------------------------------------------------
-- 2) Localised globals (hot-path micro-opt)
------------------------------------------------------------
local mathMax, mathSqrt, mathLog, mathCos, mathPi =
    math.max, math.sqrt, math.log, math.cos, math.pi
local taskDefer = task.defer
local pcallF    = pcall
local debugGU   = debug.getupvalue

------------------------------------------------------------
-- 3) Upvalue accessors
------------------------------------------------------------
local function getUp(fn, idx)
    local ok, val = pcallF(debugGU, fn, idx)
    if ok then return val end
    return nil
end

local function getPlayers()     return getUp(Trigger, 3) end
local function getCurrentTime() return getUp(Tick, 3) or 0 end
local function getInputOffset() return getUp(Tick, 14) or 0 end

------------------------------------------------------------
-- 4) Danger thresholds (GUI warnings only)
--    Below these values is the territory where the server's anti-cheat has
--    been observed to shadow-ban accounts. They are advisory; the engine
--    still applies whatever value you set.
------------------------------------------------------------
local DANGER = {
    pressJitterMs   = 3,
    releaseJitterMs = 3,
    badChance       = 0.4,
}

------------------------------------------------------------
-- 5) Settings (mutable from GUI)
--    Defaults are the user's tested-safe humanizer values.
------------------------------------------------------------
local settings = {
    enabled              = true,

    pressOffsetMs        = 0,
    releaseOffsetMs      = 0,
    pressLeewayMs        = 5,

    pressJitterMs        = 5,
    pressJitterClampMs   = 5,
    releaseJitterMs      = 5,
    releaseJitterClampMs = 5,
    missChance           = 0.0,
    badChance            = 0.7,

    sendVirtualInput     = true,
    bindKey              = { "A", "S", "K", "L" },

    hideBotplayLabel     = true,
    skipMines            = true,
    sideOverride         = 0,
}

------------------------------------------------------------
-- 6) Auto-detect bound keys from in-game preferences
------------------------------------------------------------
local function pickKeyboardKey(bind)
    if type(bind) ~= "table" then return nil end
    local fallback
    for _, v in pairs(bind) do
        local name
        if type(v) == "string" then name = v
        elseif typeof(v) == "EnumItem" then name = v.Name end
        if name then
            local up = name:upper()
            if Enum.KeyCode[up] then
                if up ~= "LEFT" and up ~= "RIGHT" and up ~= "UP" and up ~= "DOWN" then
                    return up
                end
                fallback = fallback or up
            end
        end
    end
    return fallback
end

do
    local plr = Players.LocalPlayer
    local getPref = plr and plr:FindFirstChild("GetPref")
    if getPref then
        local ok, binds = pcallF(function() return getPref:Invoke("Binds") end)
        if ok and type(binds) == "table" then
            local laneNames = { "Left", "Down", "Up", "Right" }
            for i, n in ipairs(laneNames) do
                local k = pickKeyboardKey(binds[n])
                if k then settings.bindKey[i] = k end
            end
        end
    end
end

------------------------------------------------------------
-- 7) RNG / Gauss (Box-Muller)
------------------------------------------------------------
local rng = Random.new(tick() * 1e3)

local function gauss()
    local u1 = mathMax(rng:NextNumber(), 1e-7)
    return mathSqrt(-2 * mathLog(u1)) * mathCos(2 * mathPi * rng:NextNumber())
end

local function jitterMs(sigma, clampMag)
    if sigma <= 0 then return 0 end
    local v = gauss() * sigma
    if v < -clampMag then return -clampMag end
    if v >  clampMag then return  clampMag end
    return v
end

------------------------------------------------------------
-- 7b) Mint-type lookup
--     Each mint module has a Type field:
--       0 = "must hit" pickup. Missing it kills or heavily damages you
--           (Cheddar, MustHit, Power, Bait, Coin64, KennyCheddar, Bullet…).
--           ➜ ALWAYS hit at perfect timing, bypass humanizer miss/bad chance.
--       1 = special note like Tap/Hopo                — normal humanizer
--       2 = damaging on hit (Mine, Hurt Note…)        — SKIP
--       3 = damaging on hit (Kill, Axe, Knife, Nuke…) — SKIP
------------------------------------------------------------
local mintIsDamaging = {}
local mintIsMustHit  = {}
do
    local mints = RS:FindFirstChild("Game") and RS.Game:FindFirstChild("Mints")
    if mints then
        for _, m in ipairs(mints:GetChildren()) do
            local ok, mod = pcall(require, m)
            if ok and type(mod) == "table" then
                local t = mod.Type
                if t == 2 or t == 3 then
                    mintIsDamaging[m.Name] = true
                elseif t == 0 then
                    mintIsMustHit[m.Name] = true
                end
            end
        end
    end
end

------------------------------------------------------------
-- 8) Virtual input
------------------------------------------------------------
local function keyCodeForLane(laneIdx)
    if not settings.sendVirtualInput then return nil end
    local name = settings.bindKey[laneIdx]
    if not name or name == "" then return nil end
    return Enum.KeyCode[name:upper()]
end

local function vimPress(lane)
    local kc = keyCodeForLane(lane)
    if kc then pcallF(VIM.SendKeyEvent, VIM, true, kc, false, game) end
end

local function vimRelease(lane)
    local kc = keyCodeForLane(lane)
    if kc then pcallF(VIM.SendKeyEvent, VIM, false, kc, false, game) end
end

------------------------------------------------------------
-- 9) Engine state
------------------------------------------------------------
local pressedNotes    = setmetatable({}, { __mode = "k" })
local heldSustains    = {}
local plannedDecision = setmetatable({}, { __mode = "k" })

local function clearState()
    pressedNotes    = setmetatable({}, { __mode = "k" })
    plannedDecision = setmetatable({}, { __mode = "k" })
    heldSustains    = {}
end

local function findLocalPlayerSlot(players)
    local ov = settings.sideOverride
    if ov == 1 or ov == 2 then
        local p = players[ov]
        if type(p) == "table" and p.Strums then return ov, p end
    end
    for k, p in pairs(players) do
        if type(p) == "table" and p.Strums and p.Controller ~= nil and not p.Ghost then
            return k, p
        end
    end
    for k, p in pairs(players) do
        if type(p) == "table" and p.Strums and not p.Ghost then
            return k, p
        end
    end
    return nil, nil
end

local function planFor(note)
    local plan = plannedDecision[note]
    if plan then return plan end

    plan = { jitter = 0, releaseJ = 0, miss = false, bad = false, mine = false }

    -- Damaging mints (Mine / Hurt Note / Kill / Nuke …) — skip entirely.
    if settings.skipMines and note.mint and mintIsDamaging[note.mint] then
        plan.mine = true
        plannedDecision[note] = plan
        return plan
    end

    -- "Must-hit" / golden mints (Cheddar / MustHit / KennyCheddar / Bait …) —
    -- missing them is a guaranteed loss, so always hit them at perfect timing,
    -- bypassing humanizer miss/bad rolls and jitter.
    if note.mint and mintIsMustHit[note.mint] then
        plannedDecision[note] = plan
        return plan
    end

    plan.jitter   = jitterMs(settings.pressJitterMs,   settings.pressJitterClampMs)
    plan.releaseJ = jitterMs(settings.releaseJitterMs, settings.releaseJitterClampMs)

    if not (note.len and note.len > 0) then
        local mc, bc = settings.missChance, settings.badChance
        if mc > 0 or bc > 0 then
            local r = rng:NextNumber() * 100
            if r < mc then
                plan.miss = true
            elseif r < mc + bc then
                local sign = (rng:NextNumber() < 0.5) and -1 or 1
                plan.jitter = sign * (80 + rng:NextNumber() * 50)
                plan.bad = true
            end
        end
    end

    plannedDecision[note] = plan
    return plan
end

-- Tracks whether the previous tick had a valid player slot so we can release
-- any keys/sustains that were still down when the song ends.
local hadPlayer    = false
local lastSideIdx  = nil

local function releaseAllPressed()
    for laneIdx = 1, 4 do
        if heldSustains[laneIdx] then
            if lastSideIdx then
                pcallF(Trigger, PlayerModule, lastSideIdx, laneIdx, false, true)
            end
            heldSustains[laneIdx] = nil
        end
        -- Always tell the OS the key is up — VirtualInputManager doesn't
        -- auto-release when the game session ends, so a sustained key would
        -- otherwise stay logically pressed (causing menu navigation, etc.).
        vimRelease(laneIdx)
    end
end

local function autoplayTick()
    if not settings.enabled then return end

    local players = getPlayers()
    if not players then
        if hadPlayer then
            releaseAllPressed()
            hadPlayer = false
        end
        return
    end

    local sideIdx, p = findLocalPlayerSlot(players)
    if not p then
        if hadPlayer then
            releaseAllPressed()
            hadPlayer = false
        end
        return
    end
    hadPlayer   = true
    lastSideIdx = sideIdx
    if p.BlockPlay or p.Killed then return end

    local hitTime    = getCurrentTime() - getInputOffset()
    local pressOff   = settings.pressOffsetMs
    local releaseOff = settings.releaseOffsetMs
    local leeway     = settings.pressLeewayMs
    local strums     = p.Strums

    for laneIdx = 1, #strums do
        local strum = strums[laneIdx]

        -- Sustain release
        local heldNote = heldSustains[laneIdx]
        if heldNote then
            local plan = plannedDecision[heldNote] or planFor(heldNote)
            local releaseAt = heldNote.t + (heldNote.len or 0) + releaseOff + plan.releaseJ
            if heldNote.removed or hitTime >= releaseAt then
                pcallF(Trigger, PlayerModule, sideIdx, laneIdx, false, true)
                vimRelease(laneIdx)
                heldSustains[laneIdx] = nil
            end
        end

        -- Press
        local closestIdx = strum.Closest
        local notes      = strum.Notes
        local note       = closestIdx and notes and notes[closestIdx]
        if note and not pressedNotes[note] then
            local plan = planFor(note)
            if not plan.mine then
                if plan.miss then
                    pressedNotes[note] = true
                else
                    local target = note.t + pressOff + plan.jitter
                    if hitTime - target >= -leeway then
                        pressedNotes[note] = true
                        vimPress(laneIdx)
                        pcallF(Trigger, PlayerModule, sideIdx, laneIdx, true, true)
                        if note.len and note.len > 0 then
                            heldSustains[laneIdx] = note
                        else
                            local capturedLane = laneIdx
                            taskDefer(function()
                                pcallF(Trigger, PlayerModule, sideIdx, capturedLane, false, true)
                                vimRelease(capturedLane)
                            end)
                        end
                    end
                end
            end
        end
    end
end

------------------------------------------------------------
-- 10) Botplay label spoof — cached + throttled
------------------------------------------------------------
local botplayLabel  = nil
local lastSpoofTime = 0

local function refreshBotplayLabel()
    botplayLabel = nil
    local plr = Players.LocalPlayer
    local pg  = plr and plr:FindFirstChildOfClass("PlayerGui")
    if not pg then return end
    local hud = pg:FindFirstChild("GameHUD")
    if not hud then return end
    for _, d in ipairs(hud:GetDescendants()) do
        if d.Name == "Botplay" and d:IsA("GuiObject") then
            botplayLabel = d
            return
        end
    end
end

local function spoofBotplayLabel()
    if not settings.hideBotplayLabel then return end
    local now = os.clock()
    if now - lastSpoofTime < 0.5 then return end
    lastSpoofTime = now
    if not botplayLabel or not botplayLabel.Parent then
        refreshBotplayLabel()
    end
    if botplayLabel and botplayLabel.Visible then
        botplayLabel.Visible = false
    end
end

------------------------------------------------------------
-- 11) WindUI GUI
------------------------------------------------------------
local WindUI
do
    local ok, lib = pcallF(function()
        return loadstring(game:HttpGet(
            "https://raw.githubusercontent.com/ofkotov/lib/refs/heads/main/123"))()
    end)
    if not ok or not lib then
        warn("[RAT Autoplay] WindUI failed to load: " .. tostring(lib))
        return
    end
    WindUI = lib
end

local Window = WindUI:CreateWindow({
    Title  = "Rap Ability Autoplay",
    Icon   = "music",
    Author = "by claude opus vibecodus",
    Folder = "RAT_Autoplay",
    Size   = UDim2.fromOffset(440, 380),
    Theme  = "Rose",
    User   = { Enabled = false },
    SideBarWidth     = 150,
    ScrollBarEnabled = true,
})

Window:EditOpenButton({
    Title           = "Autoplay",
    Icon            = "music",
    CornerRadius    = UDim.new(0, 16),
    StrokeThickness = 2,
    Color           = ColorSequence.new(Color3.fromHex("ff6b9d"), Color3.fromHex("c850c0")),
    OnlyMobile      = false,
    Enabled         = true,
    Draggable       = true,
})
Window:SetToggleKey(Enum.KeyCode.Delete)

local function notify(opts)
    pcallF(function() WindUI:Notify(opts) end)
end

local function makeSlider(tab, opts)
    local function fire(v)
        opts.Callback(v)
        if opts.DangerBelow and v < opts.DangerBelow then
            notify({
                Title    = "Risky setting",
                Content  = (opts.Title or "value") .. " = " .. tostring(v) ..
                           " is below the safe threshold (" .. tostring(opts.DangerBelow) ..
                           "). This may trigger the anti-cheat and shadow-ban your account.",
                Icon     = "alert-triangle",
                Duration = 5,
            })
        end
    end
    if tab.Slider then
        return tab:Slider({
            Title    = opts.Title,
            Icon     = opts.Icon,
            Value    = { Min = opts.Min, Max = opts.Max, Default = opts.Default },
            Step     = opts.Step or 1,
            Callback = fire,
        })
    end
    return tab:Input({
        Title       = opts.Title .. " (" .. tostring(opts.Min) .. ".." .. tostring(opts.Max) .. ")",
        Value       = tostring(opts.Default),
        InputIcon   = opts.Icon or "hash",
        Placeholder = "number",
        Callback    = function(text)
            local n = tonumber(text)
            if not n then return end
            if opts.Min and n < opts.Min then n = opts.Min end
            if opts.Max and n > opts.Max then n = opts.Max end
            fire(n)
        end,
    })
end

------------------------------------------------------------
-- MAIN TAB
------------------------------------------------------------
local MainTab = Window:Tab({ Title = "Autoplay", Icon = "play", Desc = "Main controls" })

MainTab:Paragraph({
    Title = "Rap Ability Autoplay",
    Desc  = "Auto-hits every note through the same code path the game uses for real keypresses. A light humanizer (gaussian timing jitter + tiny Bad chance) keeps your runs under the detection so Cheddar and lb plays keeps coming.",
    Image = "music",
    Color = "HotPink",
})

MainTab:Paragraph({
    Title = "Notes",
    Desc  = "Defaults settings are pre-tuned and confirmed safe. If you want to tweak them, the Advanced tab exposes everything — values inside the safe stay undetected; the GUI only warns you if you drop into the risky zone.",
    Image = "info",
    Color = "HotPink",
})

MainTab:Toggle({
    Title   = "Enable Autoplay",
    Icon    = "power",
    Default = settings.enabled,
    Callback = function(v)
        settings.enabled = v
        if not v then
            releaseAllPressed()
            clearState()
            hadPlayer = false
        end
    end,
})

MainTab:Toggle({
    Title   = "Skip mines / damage notes",
    Icon    = "bomb",
    Default = settings.skipMines,
    Callback = function(v) settings.skipMines = v end,
})

------------------------------------------------------------
-- TIMING TAB
------------------------------------------------------------
local TimingTab = Window:Tab({ Title = "Timing", Icon = "timer", Desc = "Press / Release offsets" })

TimingTab:Paragraph({
    Title = "Press / Release offsets",
    Desc  = "Constant timing shifts (ms). These do NOT affect anti-cheat — they just nudge everything. Useful when long-note tails read Fresh -X ms (raise Release Offset by +X).",
    Image = "info",
    Color = "HotPink",
})

makeSlider(TimingTab, { Title = "Press Offset",             Icon = "arrow-down", Min = -100, Max = 100, Default = settings.pressOffsetMs,   Step = 1, Callback = function(v) settings.pressOffsetMs   = v end })
makeSlider(TimingTab, { Title = "Release Offset (LN tail)", Icon = "arrow-up",   Min = -100, Max = 200, Default = settings.releaseOffsetMs, Step = 1, Callback = function(v) settings.releaseOffsetMs = v end })
makeSlider(TimingTab, { Title = "Press Leeway",             Icon = "clock",      Min = 0,    Max = 30,  Default = settings.pressLeewayMs,   Step = 1, Callback = function(v) settings.pressLeewayMs   = v end })

TimingTab:Button({
    Title = "Reset Timing",
    Icon  = "rotate-ccw",
    Callback = function()
        settings.pressOffsetMs   = 0
        settings.releaseOffsetMs = 0
        settings.pressLeewayMs   = 5
        notify({ Title = "Timing reset", Content = "Offsets back to 0", Icon = "check", Duration = 2 })
    end,
})

------------------------------------------------------------
-- KEYS TAB
------------------------------------------------------------
local KeysTab = Window:Tab({ Title = "Keys", Icon = "keyboard", Desc = "Bind keys for virtual input" })

KeysTab:Paragraph({
    Title = "Bound keys",
    Desc  = "Auto-detected from your in-game settings (Settings -> Controls). Edit manually if you rebound them after launching the script.",
    Image = "keyboard",
    Color = "HotPink",
})

local laneLabels = { "Lane 1 (Left)", "Lane 2 (Down)", "Lane 3 (Up)", "Lane 4 (Right)" }
for i = 1, 4 do
    local laneIdx = i
    KeysTab:Input({
        Title       = laneLabels[i],
        Value       = settings.bindKey[i],
        InputIcon   = "keyboard",
        Placeholder = "Letter, e.g. A",
        Callback    = function(txt)
            if txt and #txt > 0 then settings.bindKey[laneIdx] = txt:upper() end
        end,
    })
end

------------------------------------------------------------
-- ADVANCED TAB
------------------------------------------------------------
local AdvTab = Window:Tab({ Title = "Advanced", Icon = "settings", Desc = "Humanizer knobs" })

AdvTab:Paragraph({
    Title = "Humanizer",
    Desc  = "Per-note timing variance plus a tiny chance of a Bad note. Defaults are user-tested and known to pass the shadowban (you are not abble to gain cheese or set your scores into leaderboard). Going lower than the defaults values may send you to shadowban",
    Image = "sliders-horizontal",
    Color = "HotPink",
})

makeSlider(AdvTab, { Title = "Press Jitter sigma (ms)",   Icon = "shuffle", Min = 0, Max = 20, Default = settings.pressJitterMs,        Step = 1,   DangerBelow = DANGER.pressJitterMs,   Callback = function(v) settings.pressJitterMs        = v end })
makeSlider(AdvTab, { Title = "Press Jitter Clamp (ms)",   Icon = "shuffle", Min = 1, Max = 30, Default = settings.pressJitterClampMs,   Step = 1,                                       Callback = function(v) settings.pressJitterClampMs   = v end })
makeSlider(AdvTab, { Title = "Release Jitter sigma (ms)", Icon = "shuffle", Min = 0, Max = 20, Default = settings.releaseJitterMs,      Step = 1,   DangerBelow = DANGER.releaseJitterMs, Callback = function(v) settings.releaseJitterMs      = v end })
makeSlider(AdvTab, { Title = "Release Clamp (ms)",        Icon = "shuffle", Min = 1, Max = 30, Default = settings.releaseJitterClampMs, Step = 1,                                       Callback = function(v) settings.releaseJitterClampMs = v end })
makeSlider(AdvTab, { Title = "Miss Chance (%)",           Icon = "x",       Min = 0, Max = 5,  Default = settings.missChance,           Step = 0.1,                                       Callback = function(v) settings.missChance           = v end })
makeSlider(AdvTab, { Title = "Bad/Good Chance (%)",       Icon = "minus",   Min = 0, Max = 5,  Default = settings.badChance,            Step = 0.1, DangerBelow = DANGER.badChance,       Callback = function(v) settings.badChance            = v end })

AdvTab:Dropdown({
    Title   = "Player Side override",
    Values  = { "Auto", "Side 1 (Left)", "Side 2 (Right)" },
    Multi   = false,
    Default = "Auto",
    Callback = function(v)
        if     v == "Side 1 (Left)"  then settings.sideOverride = 1
        elseif v == "Side 2 (Right)" then settings.sideOverride = 2
        else                              settings.sideOverride = 0 end
    end,
})

------------------------------------------------------------
-- 12) Hooks
------------------------------------------------------------
local heartbeatConn = RunService.Heartbeat:Connect(autoplayTick)
local spoofConn     = RunService.Heartbeat:Connect(spoofBotplayLabel)

_G.__RAT_AUTOPLAY = {
    heartbeat = heartbeatConn,
    spoof     = spoofConn,
    window    = Window,
    settings  = settings,
    players   = getPlayers(),
}

notify({
    Title    = "Rap Ability Autoplay",
    Content  = "Loaded. Keys: " ..
               table.concat(settings.bindKey, " ") ..
               ". Press Delete to toggle the menu.",
    Icon     = "music",
    Duration = 5,
})
Game pageRap Ability Test 0.22 · 1 script on this siteRoblox ›

More Rap Ability Test 0.22 scripts

See all
Get Delta Script first on GoogleAdd us as a preferred source to see our new scripts in your Google results.
Add Delta Script on Google

Leave a Reply

Your email address will not be published. Required fields are marked *