Skip to main content

utility

Time, randomness, mouse, clipboard, screen projection. 15 canonical functions.

Functions15 (45 with aliases)
Verified live13 of 15 (GetFingerprint and TeleportToPlace are partial)
Required event contextnone
Side effectsMoveMouse, SetClipboard, TeleportToPlace mutate global state. LoadImage allocates a texture handle each call.

Aliases. Every function on this page exists in three forms: utility.GetTickCount (canonical), utility.getTickCount (camelCase), utility.get_tick_count (snake_case). All three call the same C function. See Overview / Naming convention.

Quick reference

FunctionSignatureNotesStatus
RandomInt(a: int, b: int) → intinclusive [a, b]verified
RandomFloat(a: number, b: number) → numberinclusive [a, b]verified
GetTickCount() → intmilliseconds since cheat startupverified
GetDeltaTime() → numberseconds since previous frameverified
GetSystemTime() → {year, month, day, hour, minute, second, weekday}local time, weekday 0=Sun..6=Satverified
GetTimestamp() → intunix seconds (UTC)verified
GetFingerprint() → stringempty in this buildpartial
GetMousePos() → {[1] = x, [2] = y}one array-table, not multi-returnverified
MoveMouse(dx: int, dy: int)relative offset, NOT pixel-perfect (Windows ptr accel applies)verified
GetMenuState() → booltrue when cheat menu is openverified
WorldToScreen(v3: Vector3) → screenX: number, screenY: number, onScreen: boolonScreen = projection valid, not screen-boundsverified
GetClipboard() → stringUTF-8, empty for non-text contentverified
SetClipboard(s: string)overwrites system clipboardverified
LoadImage(data: string) → numberPNG/JPG bytes, allocates new texture id every callverified
TeleportToPlace(jobId: string)join Roblox server by Job ID, can trigger network teleportpartial

RandomInt

utility.RandomInt(a: int, b: int) → int

Returns a random integer in the inclusive range [a, b]. Pass a <= b. Distribution is uniform.

Verified live: RandomInt(1, 100) returned 69, then 38 on consecutive calls.

local roll = utility.RandomInt(1, 100)
print(roll)

RandomFloat

utility.RandomFloat(a: number, b: number) → number

Returns a random float in the range [a, b]. Pass a <= b. Negative ranges are fine: RandomFloat(-1, 1) works.

Verified live: RandomFloat(0, 1) returned 0.26634337488978, then 0.48977073860767.

local jitter = utility.RandomFloat(-0.5, 0.5)

GetTickCount

utility.GetTickCount() → int

Returns the cheat-side tick counter in milliseconds. Monotonically increasing.

Verified live value: 99868805 (about 27 hours since cheat startup).

Use it for timing throttles, cooldowns, frame deltas:

local last = 0
cheat.register("onUpdate", function()
local now = utility.GetTickCount()
if now - last < 500 then return end
last = now
print("fires every 500 ms")
end)

GetDeltaTime

utility.GetDeltaTime() → number

Time in seconds since the previous frame.

Verified live value: 0.0045325998216867 (about 220 FPS).

cheat.register("onPaint", function()
local fps = 1 / math.max(utility.GetDeltaTime(), 0.0001)
draw.TextOutlined(string.format("FPS: %.0f", fps), 10, 10,
Color3.fromRGB(255, 255, 255), "Verdana")
end)

GetSystemTime

utility.GetSystemTime(){ year, month, day, hour, minute, second, weekday }

Returns local system time as a table. All fields are integers.

weekday follows the C tm_wday convention: 0 = Sunday, 1 = Monday, ... 6 = Saturday. Verified live: April 25 2026 was a Saturday and the call returned weekday = 6.

Verified live output:

{ year=2026, month=4, day=25, hour=18, minute=24, second=32, weekday=6 }
local t = utility.GetSystemTime()
local stamp = string.format("%04d-%02d-%02d %02d:%02d:%02d",
t.year, t.month, t.day, t.hour, t.minute, t.second)
print(stamp)

GetTimestamp

utility.GetTimestamp() → int

Unix timestamp in seconds since 1970-01-01 UTC.

Verified live value: 1777159472 (April 2026).

local ts = utility.GetTimestamp()
file.append("events.log", ts .. " script_loaded\n")

GetFingerprint

utility.GetFingerprint() → string

Hardware fingerprint hash. Intended to be a stable per-machine identifier for licensing or per-machine config files.

Verified to return empty string in this build

Three consecutive calls all returned "" (length 0). Treat the return as potentially empty and have a fallback.

local fp = utility.GetFingerprint()
if fp == nil or fp == "" then
fp = "unknown-" .. tostring(utility.GetTimestamp())
end
print("HWID:", fp)

GetMousePos

utility.GetMousePos()table { [1] = x, [2] = y }

Current mouse position in screen pixels. Origin is top-left, X grows right, Y grows down.

Returns one array-like table, not multi-return

The function returns a single table whose only keys are integers 1 and 2. Access via mp[1] and mp[2]. There is no mp.X / mp.Y shortcut, and the table does not spread into local x, y = ... (you would get the table in x and nil in y).

Verified live: returned {[1]=862, [2]=679} while the cursor was at (862, 679).

cheat.register("onPaint", function()
local mp = utility.GetMousePos()
local x, y = mp[1], mp[2]
draw.Circle(x, y, 6, Color3.fromRGB(255, 255, 0), 1, 12, 1)
end)

MoveMouse

utility.MoveMouse(dx: int, dy: int)

Moves the mouse by a relative offset (not absolute screen coordinates). Positive dx moves right, positive dy moves down (same axes as GetMousePos). Used internally by silent-aim and triggerbot logic.

utility.MoveMouse(5, -3)
The argument is NOT in raw screen pixels

Verified live: starting at (972, 717), calling MoveMouse(30, 0) moved the cursor to (1010, 717), that is +38 px, not +30. Calling MoveMouse(0, 25) produced +47 px vertical movement. The offset is passed through Windows pointer ballistics (mouse acceleration), which applies a non-linear multiplier based on speed and the current OS sensitivity setting.

Consequences:

  • A naive "move +N then move -N" round-trip does not return the cursor to the original position. The verify probe ended with a (-22, 0) drift after a +30 / -30 pair.
  • For aimbot or smooth-aim use cases, you have to either calibrate the multiplier per machine, or call MoveMouse repeatedly in tiny steps (1-3 units) where the ballistic curve is closer to linear.
  • For unit-tests of cursor movement, prefer comparing the direction of the delta, not the magnitude.
Side effect

Actually moves the system cursor. Never call from onPaint. Use onUpdate with rate limiting via the GetTickCount throttle pattern.


GetMenuState

utility.GetMenuState() → bool

Returns true if the Serotonin menu is currently open (cursor visible). Use it to suppress aim or movement when the user is interacting with the cheat.

Verified live: returned true while menu was open.

cheat.register("onUpdate", function()
if utility.GetMenuState() then return end
end)

WorldToScreen

utility.WorldToScreen(v3: Vector3) → screenX, screenY, onScreen: bool

Projects a world-space Vector3 to 2D screen coordinates. Returns three values: screenX, screenY, and a bool.

Verified live with Vector3.new(0, 10, 0):

screenX  = 1201.9686279297
screenY = 410.52291870117
onScreen = true
select("#", utility.WorldToScreen(v3)) == 3

Argument validation (verified):

CallResult
WorldToScreen()"bad argument #1 to '?' (__vector3_meta expected, got no value)"
WorldToScreen(nil)"bad argument #1 to '?' (__vector3_meta expected, got nil)"
WorldToScreen({0,10,0})"bad argument #1 to '?' (__vector3_meta expected, got table)" (must be a Vector3 userdata, not a plain table)
What onScreen actually means

onScreen is true when the projection is mathematically valid (the point is in front of the camera). It is not a screen-rectangle bounds check, a probe with Vector3.new(-99999, 50, -99999) still returned true. If you need real on-screen check, additionally test 0 <= screenX <= window_w and 0 <= screenY <= window_h using cheat.GetWindowSize().

cheat.register("onPaint", function()
local lp = entity.GetLocalPlayer()
if not lp then return end
local pos = lp:GetBonePosition("HumanoidRootPart")
if not pos then return end
local x, y, onScreen = utility.WorldToScreen(pos)
if onScreen then
draw.TextOutlined("ME", x, y, Color3.fromRGB(0, 255, 0), "Verdana")
end
end)

GetClipboard

utility.GetClipboard() → string

Returns the current system clipboard as a UTF-8 string. Empty string if the clipboard is empty or holds non-text content (image, file, binary). No length cap was observed.

Verified live: returned a 159-character string containing the previously copied Lua snippet.

local text = utility.GetClipboard()
print("clipboard length:", #text)

SetClipboard

utility.SetClipboard(s: string)

Replaces the system clipboard with the given string. Returns nothing.

Verified live with a full round-trip: write "serotonin-test-1777160880", immediate GetClipboard() returned the exact same string, then restoring the original 232-char value also worked. No latency longer than the next frame was needed.

local lp = entity.GetLocalPlayer()
if lp then
utility.SetClipboard("UserId: " .. tostring(lp.UserId))
end
Side effect

Overwrites whatever the user had copied. If you need to be polite, save the previous clipboard with GetClipboard and restore it afterwards.


LoadImage

utility.LoadImage(data: string) → number

Loads raw image bytes (PNG / JPG) and returns a numeric texture id usable by draw.Image. Pair with file.read for an asset pipeline.

Verified live with a 21816-byte PNG: returned id 1 on first call, 2 on second call. Each call allocates a new texture handle, the function does not deduplicate. Load once at startup and reuse the id, do not reload every frame or you will leak texture memory.

Bad input is safely rejected through pcall:

  • garbage string returns error "Failed to load texture from memory. HRESULT: 0x?"
  • non-string argument returns error "bad argument #1 to '?' (string expected)"
  • no native crash observed
local data = file.read("logo.png")
if data then
local tex = utility.LoadImage(data)
cheat.register("onPaint", function()
draw.Image(tex, 20, 20, 64, 64, Color3.new(1, 1, 1), 1)
end)
end

The file goes in C:\Serotonin\files\ (the script sandbox). Forward slashes in the path.

local data = file.read("logo.png")
if data then
local tex = utility.LoadImage(data)
cheat.register("onPaint", function()
draw.Image(tex, 20, 20, 64, 64, Color3.new(1, 1, 1), 1)
end)
end

The file goes in C:\Serotonin\files\ (the script sandbox). Forward slashes in the path.


TeleportToPlace

utility.TeleportToPlace(jobId: string)

Joins a specific Roblox server (game instance) by its Job ID, the UUID identifier of an active server within the current game. This is not a "switch to a different game" call, the place stays the same.

Real signature was recovered from the runtime error message: calling with nil, bool, or table returns:

bad argument #1 to '?' (string Job ID expected)

Number arguments are accepted too (auto-coerced to string). String arguments do not raise at the call site, but if the Job ID is invalid the cheat can still initiate a teleport attempt that the Roblox client then rejects, which can disconnect you from the current server.

Use it to follow a friend into their private server or rejoin the same instance after a disconnect:

local job_id = "place-it-here-when-you-have-a-real-job-id"
utility.TeleportToPlace(job_id)

A Job ID looks like df93c2e8-7c18-4f3a-9d1e-9b8a5b2f4e3c (standard UUID).

Network side effect

Even with an invalid Job ID, the cheat may initiate a teleport request that the Roblox server rejects mid-flight. This can crash the cheat or kick you from the current server. Never call TeleportToPlace with random or guessed strings, only with a real Job ID you obtained from game.GetService("Players").LocalPlayer or a friend's profile.


Patterns

Frame-rate counter

See GetDeltaTime.

Throttled action (every N ms)

See GetTickCount.

Save state per machine

local fp = utility.GetFingerprint()
if fp == nil or fp == "" then fp = "anon" end
local path = "config_" .. string.sub(fp, 1, 8) .. ".json"
file.write(path, '{"theme":"dark"}')

Skip logic when menu open

cheat.register("onUpdate", function()
if utility.GetMenuState() then return end
end)

Read mouse position correctly

local mp = utility.GetMousePos()
local mx, my = mp[1], mp[2]