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
- Returns: If the current frame has a screenshot or a
render.Capturecall
oink.config_get(key) - Gets a config value
- Param:
key: The config key that you want to get, a list of config keys is here - Returns: Value of the config entry or
nilif failed - Notes: This only supports getting the values of
int,float,bool,color,bindandstring. Gettingenumvalues returns the selected choice index, not the choice string itself. Getting the value of a bind returns if the bind is active.
oink.config_set(key, value) - Sets a config value
- Param:
key: The config key that you want to set, a list of config keys is here - Param:
value: Value that you want to set - Notes: This supports setting the values of
int,float,bool,color,string,enumandbind.enumvalues are set by the selected choice index, not by the choice string itself.bindvalues can only be set if thebindstate is set to toggle by the user, in which case sending a boolean type will set the toggle state.
oink.log(color, text) - Logs text to top left of the screen
- Param:
color: The color. - Param:
text: The text you want to log. - Returns:
trueif the text was logged,falseif it was not
oink.event_listen(event, handler_name, handler) - Adds an event handler
- Param:
event: The event. - Param:
text: The handlers name. - Param:
handler: A lua function to handle the event. - Returns:
trueif the event was added,falseif it was not - Notes: Only works in the client state, returns
falseif called from any other state.
oink.event_remove(event, handler_name) - Removes an event handler
- Param:
event: The event. - Param:
text: The handlers name. - Returns:
trueif the event was removed,falseif it was not - Notes: Only works in the client state, returns
falseif called from any other state.
oink.lua_to_c_function(func) - Converts a lua function to a C lua function
- Param:
function: The lua function. - Returns: A c lua function if successful,
nilif the call failed.
oink.username() - Returns the current username
- Returns: The current username.
oink.dump_bytecode(function[, strip]) - Gets a functions bytecode
- Param:
function: The lua function. - Param:
strip(optional): Whether or not to strip the bytecode to reduce it's size. - Returns: A string that can be given to
oink.load_bytecodeornilif failed.
oink.load_bytecode(bytecode) - Loads a function from bytecode
- Param:
bytecode: Bytecode of the function fromoink.dump_bytecode. - Returns: A lua function from the given bytecode or
nilif failed.
oink.get_original(name) - Gets the original copy of any given lua c function
- Param:
name: Name of the function (Refer to theCalling original versions of functions to avoid detoursexample for what these names look like) - Returns: A c lua function or
nilif not found. - Notes: Only works in the client state, returns
nilif called from any other state.
oink.change_in_game_name(name) - Changes your in game name.
- Param:
name: Your new in game name. - Returns: Nothing.
oink.ui_context(context) - Creates and sets your UI context.
- Param:
context: The name of the context. - Returns: Nothing.
oink.ui_slider(name, min, max, increment[, default]) - Creates a slider.
- Param:
name: The name of the slider. - Param:
min: The minimum value. - Param:
max: The maximum value. - Param:
increment: The increment of the slider. - Param:
default(optional): The default value of the slider. - Returns: Nothing.
oink.ui_button(name) - Creates a button.
- Param:
name: The name of the button. - Returns: Nothing.
oink.ui_checkbox(name[, default]) - Creates a checkbox.
- Param:
name: The name of the checkbox. - Param:
default(optional): The default value of the checkbox. - Returns: Nothing.
oink.ui_text(name) - Creates a text edit.
- Param:
name: The name of the text edit. - Returns: Nothing.
oink.ui_get(context, name) - Gets the value of a created UI element.
- Param:
context: The context the UI element is in. - Param:
name: The name of the element. - Returns: If checkbox returns value of the checkbox. If slider returns value of the slider. If button returns
trueif the button was clicked. If failed returnsnil.
oink.view_pos() - Returns the players view position.
- Return:
x: The x position. - Return:
y: The y position. - Return:
z: The z position.
oink.view_angles() - Returns the players view angles.
- Return:
x: The x position. - Return:
y: The y position. - Return:
z: The z position.
oink.view_forward() - Returns the players normalized forward direction.
- Return:
x: The x position. - Return:
y: The y position. - Return:
z: The z position.
oink.mark_player(steamid, relation) - Marks a player as a friend/enemy
- Param:
steamid: SteamID64 or SteamID of the target as a string. - Param:
relation:"friend","enemy"or"none". - Returns::
trueif the relationship was changed,falseotherwise.
oink.get_player_relationship(steamid) - Get a player's relationship status
- Param:
steamid: SteamID64 or SteamID of the target as a string. - Returns::
"friend","enemy"or"none"if the target was provided correctly,falseotherwise.
oink.is_spectated() - Checks if you are being spectated using the cheats spectator list.
- Returns::
trueif spectated,falseotherwise.
oink.register_custom_team(id, name, color) - Registers a team by hand.
- Param:
id: An internal id for the team, pick any number here. - Param:
name: Name of the team. - Param:
color: Color of the team.
oink.remove_custom_team(id) - Removes a team by hand.
- Param:
id: The internal id of the team.
oink.set_team_override(steamid, id) - Sets a team override
- Param:
steamid: SteamID64 or SteamID of the target as a string. - Param:
id: Id of the team. Set to -1 to remove override.
oink.set_esp_override(steamid, text, side, color) - Sets a custom esp element on a player.
- Param:
steamid: SteamID64 or SteamID of the target as a string. - Param:
text: Text - Param:
side: "left" "right" "top" "bottom" - Param:
color: Color
Events
Below is a list of events to be used with oink.event_listen and oink.event_remove
view_render_post: Happens after every other lua rendering callback has been called, useful for screengrab proof lua visuals.server_sound: Happens whenever the server sends us a serverside emitted sound.- Param:
table event_data:bool staticsoundstring namevector originfloat xfloat yfloat z
vector directionfloat xfloat yfloat z
int soundsourceint speakerentityfloat pitchfloat volfloat flags
- Param:
lua_execute: Happens whenever a script gets executed in the client state.- Param:
string filename - Param:
string code - Return:
bool blockorstring new_codeor nothing
- Param:
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))
Creating and using UI elements from lua
-- first create a context for our ui elements
oink.ui_context("My Application")
-- then create our UI elements
oink.ui_button("Button")
oink.ui_slider("Slider A", 0, 1000, 1)
oink.ui_slider("Slider B", -10, 10, 0.05)
-- some number
local number = 100
-- handle button presses
oink.event_remove("view_render_post", "oink_dupe_stealer")
oink.event_listen("view_render_post", "oink_dupe_stealer", function()
-- NOTE: this can be done in any hook, but its best if you do it in ones that are called every frame
if oink.ui_get("My Application", "Button") then
number = number + 1
local a = oink.ui_get("My Application", "Slider A")
local b = oink.ui_get("My Application", "Slider B")
oink.log(0xff0000ff, "[api example] " .. tostring(number) .. ": the values of the sliders are " .. tostring(a) .. " and " .. tostring(b))
end
end)
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))
Custom teams and esp elements
local target = 76561197960265728
oink.register_custom_team(1234567, "Skibidi toilet team (private)", 0xffffffff)
oink.remove_custom_team(1234567)
oink.set_team_override(target, 1234567)
oink.set_esp_override(target, "From ohio (left)", "left", 0xff0000ff)
oink.set_esp_override(target, "From ohio (right)", "right", 0xfffefeff)
oink.set_esp_override(target, "From ohio (top)", "top", 0xfffefeff)
oink.set_esp_override(target, "From ohio (bottom)", "bottom", 0xfffefeff)
Lua script modification
oink.event_remove("lua_execute", "Api Example")
oink.event_listen("lua_execute", "Api Example", function(file, code)
print("running file:", file, #code)
-- return false to block
return ("print('hello!')\n\n" .. code) -- to modify
-- returning nothing is fine as well
end)