Clone
5
Lua API
pavetr edited this page 2026-09-02 17:18:44 +00:00

GM Fatal lua executor can run the common Garry's mod clientside or menuside lua code. But also it includes some custom methods.

Reference for Garry's mod Lua API

How to enable custom Lua API?

Click on the corresponding checkbox in Lua tab and join the server (or reconnect if you was on server):

Menu screenshot

  • What should I choose? The menu or client?
    • The menu state API is undetectable for gmod servers but it's very limited. Client state has rich functional but it can be easily detected (and server owner can do anything with the clientside-loaded functions - for example, create 9999 tabs in your cheat menu using custom API function)
  • Can I enable menu and clientside API together?
    • Yes

Lua API is separated on Free and Premium (which can be used only in Premium version)

Free Methods

ZXCModule-compatible functions (that means you can make local zxcmodule = fatal and run script with these functions):

fatal.get_view_angles() -> Angle

fatal.set_view_angles(Angle ang)

fatal.get_local_player() -> number

fatal.client_cmd_unrestricted(string command)

fatal.get_cur_time() -> number

fatal.set_cur_time(number val)

fatal.get_frame_time() -> number

fatal.set_frame_time(number val)

fatal.get_real_time() -> number

fatal.set_real_time(number val)

fatal.get_frame_count() -> number

fatal.set_frame_count(number val)

fatal.get_abs_frame_time() -> number

fatal.set_abs_frame_time(number val)

fatal.get_interpolation_amount() -> number

fatal.set_interpolation_amount(number val)

fatal.get_last_command_ack() -> number

fatal.set_last_command_ack(number val)

fatal.get_last_outgoing_command() -> number

fatal.set_last_outgoing_command(number val)

fatal.get_choked_commands() -> number

fatal.set_choked_commands(number val)

fatal.get_previous_tick() -> number

fatal.convar_set_value(string name, number val) -> bool

fatal.convar_set_flags(string name, number flags) -> bool

fatal.set_command_number(number num)

fatal.set_command_tick(number tick)

fatal.get_typing() -> bool

fatal.set_typing(bool typing)

fatal.get_random_seed() -> number

fatal.set_random_seed(number seed)

fatal.md5_pseudo_random(number seed) -> number

fatal.find_command_number(number target_seed) -> number, number

fatal.get_net_address() -> string

fatal.get_net_time() -> number

fatal.get_net_time_connected() -> number

fatal.get_out_sequence_nr() -> number

fatal.set_out_sequence_nr(number val)

fatal.get_in_sequence_nr() -> number

fatal.set_in_sequence_nr(number val)

fatal.get_out_sequence_nr_ack() -> number

fatal.set_out_sequence_nr_ack(number val)

fatal.get_out_reliable_state() -> number

fatal.set_out_reliable_state(number val)

fatal.get_in_reliable_state() -> number

fatal.set_in_reliable_state(number val)

fatal.get_net_choked_packets() -> number

fatal.set_net_choked_packets(number val)

fatal.get_latency(number flow) -> number

fatal.get_clipboard_text() -> string

fatal.exclude_from_capture(bool exclude)

fatal.invalidate_bone_cache(number entity_index)

fatal.push_special(number type) -> table

Premium Methods

fatal.being_screengrabbed() -> bool

This method returns if your screen is being screengrabbed by Admin or screenshoted.

Example

hook.Add("HUDPaint","my_cool_custom_esp",function()
	if not fatal.being_screengrabbed() then
    	draw.SimpleText("This text is not visible on screengrab apps", "DermaLarge", ScrW()/2, ScrH()/2, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
	end
end)

How it looks as user (you):
User view

And when admin takes screenshot:
Admin view

fatal.run_on_client(code: string)

This method allows you to run the code from menuside on client

Example

if not MENU_DLL then
	fatal.notify("Please run in menustate (click on RMB)")
	return
end
RunString("print('Hi on menu!')")
fatal.run_on_client("print('Hi on client!')")

fatal.config_get(key: string) -> any

fatal.config_set(key: string, value: any)

fatal.menu_tab(name: string) -> number

fatal.menu_checkbox(tab: number, label: string, id: string)

fatal.menu_slider_float(tab: number, label: string, id: string, min: number, max: number)

fatal.menu_slider_int(tab: number, label: string, id: string, min: number, max: number)

fatal.menu_combo(tab: number, label: string, id: string, items: table | ...string)

fatal.menu_color(tab: number, label: string, id: string)

fatal.menu_button(tab: number, label: string, id: string)

fatal.menu_text(tab: number, label: string, id: string, default_value: string = "")

fatal.menu_label(tab: number, text: string, id: string = "")

fatal.menu_separator(tab: number)

fatal.notify(message: string)

Example

-- Making a tab "My Script"
local tab = fatal.menu_tab("My Script")

-- Add some elements
fatal.menu_separator(tab)
fatal.menu_checkbox(tab, "Enable aimbot", "enable_aimbot")
fatal.menu_checkbox(tab, "Silent aim", "silent_aim")
fatal.menu_slider_float(tab, "FOV", "aim_fov", 0, 180)
fatal.menu_slider_float(tab, "Smooth", "aim_smooth", 0, 30)
fatal.menu_slider_int(tab, "Backtrack ticks", "bt_ticks", 0, 12)
fatal.menu_combo(tab, "Target selection", "target_mode", {
    "Crosshair",
    "Distance",
    "Lowest Health",
    "FOV"
})
-- Also can be used but not recommended
-- fatal.menu_combo(tab, "Target selection", "target_mode", "Crosshair", "Distance", "Lowest Health", "FOV")
fatal.menu_color(tab, "ESP Color", "esp_color")
fatal.menu_separator(tab)
fatal.menu_label(tab, "This is just a text")
fatal.menu_text(tab, "Custom Message", "custom_msg", "Hello World")
fatal.menu_button(tab, "Print message", "btn_print")
fatal.menu_button(tab, "Reset config", "btn_reset")

-- Load saved fields
local saved_fov = fatal.config_get("aim_fov")
if saved_fov then
    -- field is loaded from config
end

-- Main cycle - reading values
hook.Add("Think", "my_script_loop", function()
    local enabled = fatal.config_get("enable_aimbot")
    if not enabled then return end

    local fov = fatal.config_get("aim_fov") or 0
    local smooth = fatal.config_get("aim_smooth") or 0
    local ticks = fatal.config_get("bt_ticks") or 0

    -- Saving config values
    fatal.config_set("aim_fov", fov)
    fatal.config_set("aim_smooth", smooth)
    fatal.config_set("bt_ticks", ticks)
end)

-- Handler for button "Print message"
hook.Add("Think", "btn_print_handler", function()
    if fatal.config_get("btn_print") then -- Guarantee that button click will be handled once
        local msg = fatal.config_get("custom_msg") or "no message"
        print(msg)
    end
end)

-- Handler for button "Reset config"
hook.Add("Think", "btn_reset_handler", function()
    if fatal.config_get("btn_reset") then
        fatal.config_set("enable_aimbot", false)
        fatal.config_set("silent_aim", false)
        fatal.config_set("aim_fov", 0)
        fatal.config_set("aim_smooth", 0)
        fatal.config_set("bt_ticks", 0)
        fatal.config_set("custom_msg", "")
    end
end)

-- Notification on load
fatal.notify("My Script loaded successfully!")

-- Creating some tabs (to test scroll with mouse wheel)
tab = fatal.menu_tab("My Script 1")
tab = fatal.menu_tab("My Script 2")
tab = fatal.menu_tab("My Script 3")

How it looks in game:
User view

fatal.draw.line(x1, y1, x2, y2, r, g, b, a, [thickness])

fatal.draw.rect(x, y, w, h, r, g, b, a)

fatal.draw.rect_filled(x, y, w, h, r, g, b, a)

fatal.draw.circle(cx, cy, radius, r, g, b, a, [thickness])

fatal.draw.circle_filled(cx, cy, radius, r, g, b, a)

fatal.draw.text(x, y, text, r, g, b, a)

fatal.draw.clear()

Example

hook.Remove("Think", "fatal_demo_draw")
hook.Add("Think", "fatal_demo_draw", function()
local t = RealTime()

-- Line: x1, y1, x2, y2, r, g, b, a [, thickness]
fatal.draw.line(100, 100, 500, 300, 1, 0, 0, 1, 2)

-- Running line
local x = 100 + (t * 60 % 400)
fatal.draw.line(x, 180, x + 80, 180, 0, 1, 0, 0.8, 1)

-- Rect outline: x, y, w, h, r, g, b, a
fatal.draw.rect(200, 220, 150, 80, 1, 1, 1, 1)

-- Rect fill
fatal.draw.rect_filled(420, 60, 90, 30, 0.2, 0.6, 1, 0.5)

-- Circle outline: cx, cy, radius, r, g, b, a [, thickness]
fatal.draw.circle(650, 300, 40, 1, 1, 0, 1, 2)

-- Circle fill
fatal.draw.circle_filled(720, 200, 15, 0, 1, 0, 0.6)

-- Text: x, y, text, r, g, b, a
fatal.draw.text(100, 260, "fatal.draw works", 1, 1, 1, 1)

-- Manually clear buffer (not necessary - it clears by itself)
-- fatal.draw.clear()
end)

How it looks in game (it's unscreengrabable because draws in overlay):
User view