Scripts & GC
getscripts
function getscripts(root: Instance?): { Instance }
Collects LocalScript / Script / ModuleScript under root, or DataModel if omitted. Capped — large places return a truncated list.
getscriptbytecode
function getscriptbytecode(script: Instance): string
Raw bytecode bytes as a Lua string, or "".
decompile
function decompile(script: Instance | string): string
Decompiles via in-process Fission (+ normalize for signed/RSB1). Prefer the explorer decompile button for big ModuleScripts — calling this from a hot script can hitch.
On failure returns a short comment string, not a Lua error.
getscripthash / getgamename
Not implemented (Matcha has these).
getsenv
function getsenv(script: Instance): table
Stub — always {}. External VM has no real script env.
scripts table
All of the functions above are also grouped under a scripts table, same behavior:
scripts.get(root: Instance?): { Instance } -- = getscripts
scripts.bytecode(script: Instance): string -- = getscriptbytecode
scripts.decompile(script: Instance | string): string -- = decompile
scripts.env(script: Instance): table -- = getsenv, stub {}
GC (game Luau heaps)
Scan Roblox Lua states from outside (not your script's tables). Two independent capabilities live under the same setgc/gc.set name — a real GC-control mode and a key/value write mode.
getgc() -- stats / info table
getgc(true) -- iterator of table proxies
findgc(key) -- iterator
findgc(key, value)
findgc(nil, value)
findgc({"A","B",...})-- one walk, map key -> array of proxies
getgc_info()
gcprobe()
getrawkeys(proxy)
Proxies: string-key __index; __newindex for existing number/bool keys only.
Heavy GC walks can hitch the cheat — keep samples small in tests.
setgc — GC control mode
setgc(opt: string, value: any?): any
opt is one of the classic lua_gc verbs, applied to the largest live game Luau state:
opt |
Effect |
|---|---|
"stop" |
disables the GC (sets threshold to -1) |
"restart" |
re-enables it |
"count" |
returns heap size in KB |
"isrunning" |
returns boolean |
"pause" / "setpause" |
get/set gcpause (0–1000) |
"stepmul" / "setstepmul" |
get/set gcstepmul (0–10000) |
"collect" / "step" |
always errors — "collect/step need ingame call", cannot be driven from outside the process |
setgc / gc.set — key/value write mode
setgc(key: string | {string}, value: number | boolean): number
gc.set(key, value): number
If the first argument is not one of the GC verbs above (or is a table), setgc scans every live table in every game Luau VM for a string key equal to key (or any key in the array form) whose current value has the same type as value (number or boolean — no strings), and overwrites it in place. Returns how many tables were touched.
setgc("ShootCooldown", 0) -- zero it everywhere it's found
gc.set("ShootCooldown", 0) -- identical, table form
gc.set({"FireRate", "Damage"}, 999)
This is a one-shot write — if the game's own code overwrites the field again next tick, the change does not stick. For that, use lockgc / gc.lock.
lockgc / gc.lock — persistent write
lockgc(key: string | {string}, value: number | boolean, interval_ms: number?): number
gc.lock(key, value, interval_ms?): number
Same key/value matching as setgc, but keeps re-writing the value from a background thread instead of writing once. Returns the initial hit count.
interval_ms(default 100, clamped 10–5000) sets how often the background thread re-applies all active locks — it's a shared interval, not per-lock.- The lock survives the end of the script that created it; it keeps running until explicitly removed or the cheat unloads.
- If a locked table stops matching (respawn, weapon switch, table got rebuilt), the lock detects the miss and rescans for tables with that key — but no more than once every 2 seconds, so it does not re-walk the whole heap on every tick.
- Locking the same key(s) again replaces the previous lock with the same tag instead of stacking.
lockgc("ShootCooldown", 0) -- keep it pinned at 0, default 100ms
gc.lock("Ammo", 999, 250) -- pin Ammo=999, re-apply every 250ms
gc.lock({"MinDamage", "MaxDamage"}, 9999)
unlockgc / gc.unlock
unlockgc(key: string?): number -- returns how many locks were removed
gc.unlock(key?): number
No argument removes all active locks; with a key (or the same comma-joined tag used for a multi-key lock) removes just that one.
gc.locks()
gc.locks(): { { key: string, value: number | boolean, hits: number } }
Lists currently active locks: the key/tag, the pinned value, and how many table nodes are currently being held.
gc table
All GC functions are also grouped under a gc table — same C functions, same behavior as the flat globals:
gc.set(key, value) -- = setgc
gc.get(...) -- = getgc
gc.find(...) -- = findgc
gc.info() -- = getgc_info
gc.lock(key, value, interval_ms?) -- = lockgc
gc.unlock(key?) -- = unlockgc
gc.locks() -- list active locks
gc.keys(proxy) -- = getrawkeys
gc.probe() -- = gcprobe
The legacy flat globals (setgc, getgc, getgc_info, findgc, gcprobe, getrawkeys, lockgc, unlockgc) are unchanged and keep working exactly as before — gc.* is an additional namespaced form, not a replacement.
