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 is not yet supported. 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 only supports setting the values of
int,float,bool,colorandstring. Settingenumandbindvalues is not yet supported.
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, name, color) - 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.
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:
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)