Lua Api

There is a basic lua api you can use to control cheat behavior from lua

Color representation

Colors are represented the same way as they are in the cheat internally. A color is an unsigned 32 bit integer, the format of the color is 0xAABBGGRR (example: 0xff0000ff is red)

oink.in_screenshot() - Checks if a screenshot is being taken

oink.config_get(key) - Gets a config value

oink.config_set(key, value) - Sets a config value

oink.log(color, text) - Logs text to top left of the screen

oink.event_listen(event, handler_name, handler) - Adds an event handler

oink.event_remove(event, handler_name) - Removes an event handler

oink.lua_to_c_function(func) - Converts a lua function to a C lua function

oink.username() - Returns the current username

oink.dump_bytecode(function) - Gets a functions bytecode

oink.load_bytecode(bytecode) - Loads a function from bytecode

oink.get_original(name) - Gets the original copy of any given lua c function

Events

Below is a list of events to be used with oink.event_listen and oink.event_remove

Example Scripts

Screengrab proof rendering

local function screenshot_proof_visuals()
    -- draw something
    surface.SetDrawColor(0, 0, 0, 128)
    surface.DrawRect(50, 50, 128, 128)
end

oink.event_remove("view_render_post", "Api Example")
oink.event_listen("view_render_post", "Api Example", function()
    -- dont render if we are in a screenshot
    if oink.in_screenshot() then
        return
    end

    -- setup a render context and draw
    cam.Start2D()
    screenshot_proof_visuals()
    cam.End2D()
end)

Log whenever nospread is turned on

-- gets if nospread is on
local function is_nospread_on()
    return oink.config_get("misc.no_spread")
end

-- get the initial state of nospread
local state = is_nospread_on()

-- execute every frame
hook.Remove("Think", "Api Example")
hook.Add("Think", "Api Example", function()
    -- gets current state of nospread
    local new_state = is_nospread_on()

    -- if it was off, and now its on then log
    if not state and new_state then
        local enemy_color = oink.config_get("esp.enemy_override_color")

        oink.log(0xff0000ff, "[api example] red alert!")
        oink.log(0xff00ff00, "[api example] green alert!")
        oink.log(0xffff0000, "[api example] blue alert!")
        oink.log(enemy_color, "[api example] same as enemy color!")
    end

    -- update the state
    state = new_state
end)

Syncs player esp colors

local function sync_settings(settings)
    local value = nil

    for _, setting in pairs(settings) do
        if value == nil then
            value = oink.config_get(setting)
        end

        oink.config_set(setting, value)
    end
end

sync_settings({
    "esp.players.player.box.visible",
    "esp.players.player.name.visible",
    "esp.players.player.weapon.visible",
    "esp.players.player.usergroup.visible",
    "esp.players.player.distance.visible",
    "esp.players.player.team.visible",
})

sync_settings({
    "esp.players.player.box.hidden",
    "esp.players.player.name.hidden",
    "esp.players.player.weapon.hidden",
    "esp.players.player.usergroup.hidden",
    "esp.players.player.distance.hidden",
    "esp.players.player.team.hidden",
})

Pre autorun c function detouring

-- NOTE: THIS SCRIPT MUST BE RUN IN PRE STARTUP AUTORUN
-- NOTE: THIS SCRIPT MUST BE RUN IN PRE STARTUP AUTORUN
-- NOTE: THIS SCRIPT MUST BE RUN IN PRE STARTUP AUTORUN
-- NOTE: THIS SCRIPT MUST BE RUN IN PRE STARTUP AUTORUN
-- NOTE: THIS SCRIPT MUST BE RUN IN PRE STARTUP AUTORUN
-- NOTE: THIS SCRIPT MUST BE RUN IN PRE STARTUP AUTORUN

-- WHY THIS WORKS: by running in pre autorun, we have access to the globals before anything else does so we can modify
-- the table without anyone being able to fetch an original copy, then by masking our hooked function as a lua c function
-- using the oink api, it makes it impossible to tell that its not a function that gmod declared leading to a very good detour

local _file_Time = file.Time

file.Time = oink.lua_to_c_function(function(path, game_path)
    if game_path == "oinking" then
        return 123456
    end

    return _file_Time(path, game_path)
end)

print("lua c detour demo!")
print("original: " .. tostring(_file_Time))
print("new: " .. tostring(file.Time))

Bytecode loading and unloading

-- saves the function below to bytecode
local bytecode = oink.dump_bytecode(function()
    print("hello, this function is dumped and saved from bytecode")
end)

-- prints the bytecode
print("example bytecode: " .. tostring(bytecode))

-- loads the bytecode
local loaded = oink.load_bytecode(bytecode)
loaded()

Calling original versions of functions to avoid detours

local _LocalPlayer = oink.get_original("_G.LocalPlayer")
local _Player_SteamID64 = oink.get_original("_R.Player.SteamID64")
local _chat_AddText = oink.get_original("_G.chat.AddText")

local lp = _LocalPlayer()
local sid = _Player_SteamID64(lp)
_chat_AddText("your steamid64 is " .. tostring(sid))