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.Capture
call
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
nil
if failed - Notes: This only supports getting the values of
int
,float
,bool
,color
,bind
andstring
. Gettingenum
values 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
,color
andstring
. Settingenum
andbind
values 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:
true
if the text was logged,false
if 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:
true
if the event was added,false
if it was not - Notes: Only works in the client state, returns
false
if 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:
true
if the event was removed,false
if it was not - Notes: Only works in the client state, returns
false
if 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,
nil
if 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_bytecode
ornil
if 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
nil
if 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 detours
example for what these names look like) - Returns: A c lua function or
nil
if not found. - Notes: Only works in the client state, returns
nil
if 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
true
if 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::
true
if the relationship was changed,false
otherwise.
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,false
otherwise.
oink.is_spectated()
- Checks if you are being spectated using the cheats spectator list.
- Returns::
true
if spectated,false
otherwise.
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 staticsound
string name
vector origin
float x
float y
float z
vector direction
float x
float y
float z
int soundsource
int speakerentity
float pitch
float vol
float 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)