Versus Airlines Developer Docs
Quick examples for building scripts with the Versus UI library. This page covers the main UI elements, saved flags, helper utilities, theme tools, and the new VersusAI Pathing card.
-
New feature
VersusAI Pathing
Adds the special VersusAI consent card to the top of a script. It lets users choose AI movement instead of teleport-style farming, while still giving your script a normal flag to check.
VersusAI is a custom pathing system made by @dev_cammy. It does not use Roblox
PathfindingService. Routes come from VersusAI's own sandbox, map snapshots, learned route memory, and movement data so the character can move more like an actual player.local main = ui:CreateSection("Main") main:createButton({ Name = "VersusAI Pathing", VersusAI = true, flagName = "UseVersusAI", Callback = function(enabled) if enabled then print("VersusAI allowed - use learned routes first") else print("VersusAI disabled - use normal movement") end end, })Custom route engineNo Roblox PathfindingServiceSupports learned farm routesBest placed at the top of MainUse
Library.Flags["UseVersusAI"]inside your farms to decide whether to ask the backend for learned nodes or fall back to your old movement method. -
Load the Library
Loads the current Versus UI library from the server. Put this near the top of your script before creating any windows or sections.
-- Load the Library local Library = loadstring(game:HttpGet("https://versusairlines.top/scripts/NewLibrary.lua"))()Loads from the live library URLIncludes messages, bug reports, themes, and saved flags -
Open the UI
Creates the main window and returns the controller used to add tabs, sections, and elements. This also creates the floating open/close button.
local ui = Library:Setup({ Location = game.CoreGui, -- parent for the ScreenGui OpenCloseLocation = "Top Center" -- "Top Left" | "Top Center" | "Top Right" -- "Middle Left" | "Middle Right" -- "Bottom Left" | "Bottom Center" | "Bottom Right" })Tip: Set
OpenCloseLocationif you want the floating button somewhere specific. The listed positions are supported. -
Starter snapshot
Base Script Template
This is my script layout: services first, library setup, anti-afk-kick, helper functions, then the documentation marker where game-specific features start.
Keep shared helpers above the marker and build the actual script below it. That makes future edits cleaner and helps avoid mixing setup code with feature code.
Plus it just means that I'll only need to cut out the stuff above the anti-afk when putting the script in the loader.
local client = game:GetService("Players").LocalPlayer local request = (syn and syn.request) or (http and http.request) or http_request; -- Essential services local TweenService = game:GetService("TweenService") local HttpService = game:GetService("HttpService") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local LightingService = game:GetService("Lighting") local VirtualUser = game:GetService("VirtualUser") local CoreGui = game:GetService("CoreGui") local ReplicatedStorage = game:GetService("ReplicatedStorage") local MarketplaceService = game:GetService("MarketplaceService") local CollectionService = game:GetService("CollectionService") local Players = game:GetService("Players") local PathfindingService = game:GetService("PathfindingService") local Workspace = game:GetService("Workspace") local Camera = Workspace.Camera -- Load UI print("Loading Library...") local Library = loadstring(game:HttpGet("https://versusairlines.top/scripts/NewLibrary.lua"))() local Setup = Library:Setup({ Location = CoreGui, OpenCloseLocation = "Top Center" -- Top Right, Bottom Left, Center Left, Etc }) -- Prevent player from being idled out client.Idled:Connect(function() VirtualUser:Button2Down(Vector2.new(0, 0), Workspace.CurrentCamera.CFrame) wait(1) VirtualUser:Button2Up(Vector2.new(0, 0), Workspace.CurrentCamera.CFrame) end) ----------------------------------------------------------------- local function interval(tag, flag, delayTime, callback) Library:CleanupConnectionsByTag(tag) if not Library.Flags[flag] then return end local last = 0 local conn = RunService.Heartbeat:Connect(function() if not Library.Flags[flag] then Library:CleanupConnectionsByTag(tag) return end local now = os.clock() if now - last >= delayTime then last = now pcall(callback) end end) Library:TrackConnection(conn, tag) end local function notify(title, desc, style) -- "info" | "warning" | "danger" Library:createDisplayMessage(title, desc, { { text = "OK" }, }, style or "info") end local function prettyPrint(data, indent) indent = indent or 0 local prefix = string.rep(" ", indent) if type(data) ~= "table" then print(prefix .. tostring(data)) return end for k, v in pairs(data) do if type(v) == "table" then print(prefix .. tostring(k) .. " = {") prettyPrint(v, indent + 1) print(prefix .. "}") else print(prefix .. tostring(k) .. " = " .. tostring(v)) end end end ----------------------------------------------------------------- https://versusairlines.top/developers.html local Main = Setup:CreateSection("Versus")Standard servicesLibrary setupAnti-idleinterval helpernotify helperFor a normal release script, add your sections, labels, toggles, dropdowns, and buttons after the
https://versusairlines.top/developers.htmlmarker. -
Add a Section
Adds a section to the left side of the UI. Any elements created from that section will show in the main content area.
local versus = ui:CreateSection("Versus") local airlines = ui:CreateSection("Airlines") -
Label
Adds text to the UI. Use it for headings, dividers, notes, or small explanations between features. The special style gives it a cleaner Discord-like heading look.
versus:createLabel({ Name = "hello world", Special = true, -- renders like __***hello world***__ }) -- You can now use :Set to change the title of a label! -- granular control versus:createLabel({ Name = "Centered + rich", TransparentBackground = true, Center = true, Bold = true, Underline = true, Italic = true, }) -- or pass your own RichText versus:createLabel({ Name = "ignored when Markup set", Markup = "hello world", }) -
Button
Clickable action. Use it for one-off actions, or pass
VersusAI = trueto show the special Versus AI Pathing card.versus:createButton({ Name = "Vague Button", Description = "Needs 'Normal Toggle' active to respond.", Callback = function() if Library.Flags["Jimbo"] then print("Hello!!") else warn("Error: 'Normal Toggle' is off.") end end, }) -
Toggle
A saved on/off switch. The value is stored in
Library.Flags, so loops and other features can check it whenever they need to.versus:createToggle({ Name = "Normal Toggle", Flag = false, flagName = "Jimbo", Callback = function(v) print("Toggle:", v) end, }) -
Slider
Lets the user pick a number between a minimum and maximum value. Useful for speed, delays, distances, amounts, and other tunable settings.
versus:createSlider({ Name = "Speed", Description = "WalkSpeed (1‑100)", flagName = "Speed", value = 50 -- Default value minValue = 1, maxValue = 100, Callback = function(v) game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = v end, }) -
Input Box
Lets the user type a custom value. The value saves when they press Enter, making it useful for numbers, player names, IDs, or raw settings.
versus:createInputBox({ Name = "Jump Height", flagName = "Jump", Flag = 50, Callback = function(v) game.Players.LocalPlayer.Character.Humanoid.JumpHeight = tonumber(v) end, }) -
Dropdown
Shows a selectable list. It can be single-select or multi-select, and the returned object can refresh the list without rebuilding the whole UI.
local dd = versus:createDropdown({ Name = "Crew", flagName = "CrewDrop", Flag = {"Samantha"}, List = {"Samantha","Emma","Daisy","Timmy"}, multi = true, Callback = print, }) -- later: dd:updateList({"Ava","Olivia","Mia"}) -
Info and Warning Icons
Most elements can show small info or warning icons on the right. Use
Descriptionfor extra details andWarningwhen a feature needs a clear heads-up.versus:createToggle({ Name = "God Mode", flagName = "GodMode", Description = "Makes you invincible (client‑side).", Warning = function() return "Server anticheat may kick you." end, WarnIf = function() return true end, -- return false to show a disabled icon })Info and warning popups use the same message box style as createDisplayMessage.
-
Display Message
Shows a clean popup message. Use it for confirmations, warnings, changelogs, errors, or anything that needs more attention than a small label.
Library:createDisplayMessage("Heads up", "Something changed behind the scenes.", { { text = "OK", color = Color3.fromRGB(82,171,255) }, { text = "More", color = Color3.fromRGB(120,120,120), callback=function() print("more") end }, }, "info" ) -
Bug Report Prompt
Opens the built-in bug report form. It sends the report to the server and can include the user's save/theme files when supported.
Library:PromptBugReport() -- opens the modalBackspace/Esc to closeIncludes key + summary + descriptionCan attach saves.json & theme JSONs -
Themes and Customizer
Apply a preset theme or open the customizer so users can edit colors and save their own themes.
ui:UpdateUI("Dark Mode") -- apply any preset: "Light Mode", "Dark Mode", "Halloween", etc. Library:OpenCustomizer() -- launch the interactive customizer -- Saved theme helpers: Library:SaveCurrentThemeAs("My Cool Theme") Library:OverwriteSavedTheme("My Cool Theme")Note: Special labels keep their transparent background & hidden stroke when themes change.
Presets: Light/Dark + 20+ curated setsSaves toVersus Airlines 2.0/themes.jsonYour themes inVersus Airlines 2.0/my_themes.json -
Window Button and Side Icons
The library creates a floating button for opening and closing the UI. The left icon bar includes quick tools for folders, saves, bug reports, and themes.
- Folder: Opens the Versus folder (copies path if open fails)
- Trash: Deletes the current game’s save (with confirm)
- Bug: Opens the bug reporter
- Customize: Opens the theme customizer
-- Visibility flag for your loops: if Library.isClosed then -- UI is currently visible endThe
isClosedfield is a boolean you can read; it reflects the current main window visibility. -
Saved Flags
Element values are kept inside
Library.Flags. When the executor supports files, those values are saved per game so users keep their settings.print(Library.Flags) -- read everything print(Library.Flags["Jimbo"]) -- read one flagFolder:Versus Airlines 2.0/Save file:saves.json(per‑placeId) -
Connections and Cleanup
Track Roblox event connections by tag so toggles can cleanly stop their loops and listeners when disabled.
Library:CleanupConnectionsByTag("AutoFarm") Library:TrackConnection(RunService.RenderStepped:Connect(function() end), "AutoFarm") -
Sounds
Small click and pop sounds for UI feedback. They are off by default, so only enable them if the script needs sound feedback.
Library.DisableSounds = false Library:PlaySound("Click") -- also: "Pop" -
Template: Toggle Loop
A safe pattern for features that need to run while a toggle is enabled. It cleans up the old connection before starting a new one.
versus:createToggle({ Name = "Normal Toggle", Flag = false, flagName = "Jimbo", Callback = function(enabled) Library:CleanupConnectionsByTag("AutoJimbo") if enabled then local conn = RunService.RenderStepped:Connect(function() if not Library.Flags["Jimbo"] then return end print("'Normal Toggle' flag is enabled!") end) Library:TrackConnection(conn,"AutoJimbo") end end, }) -
Template: Timed Heartbeat
Use this for slower repeating work, such as claiming rewards, checking shops, refreshing targets, or running anything that does not need every frame.
versus:createToggle({ Name = "Jimbo With Waiting", Flag = false, flagName = "waitJimbo", Callback = function(enabled) Library:CleanupConnectionsByTag("AutowaitJimbo") if enabled then local last = 0 local conn = RunService.Heartbeat:Connect(function() if not Library.Flags["waitJimbo"] then return end if tick() - last >= 2 then print("Jimbo tick!") last = tick() end end) Library:TrackConnection(conn,"AutowaitJimbo") end end, }) -
Template: Refreshing Dropdown
Keeps a dropdown updated while the game changes. This example refreshes whenever players join or leave.
local dd = versus:createDropdown({ Name = "Players", flagName = "PlayerDrop", List = {}, }) local function refresh() local names = {} for _,plr in ipairs(game.Players:GetPlayers()) do table.insert(names,plr.Name) end dd:updateList(names) end refresh() Library:TrackConnection(game.Players.PlayerAdded:Connect(refresh),"PlayersDD") Library:TrackConnection(game.Players.PlayerRemoving:Connect(refresh),"PlayersDD")