🧠Examples

Examples:

Calling virtual functions

-- Get the interface address
local IVEngineClient = utils.find_interface("engine.dll", "VEngineClient014") or error("Engine client is invalid")

-- Cast to a pointer that can be dereferenced
local IVEngineClientPtr = ffi.cast("void***", IVEngineClient)

-- Dereference to get the vtable 
local IVEngineClientVtable = IVEngineClientPtr[0]

-- Get virtual function ptr
local ClientCmdPtr = IVEngineClientVtable[108]

-- Cast the address to the function type
local ClientCmd = ffi.cast(ffi.typeof("void(__thiscall*)(void*, const char*)"), ClientCmdPtr)

-- Call the virtual function with the interface ptr as the first argument
ClientCmd(IVEngineClientPtr, "say Hello from lua-ffi")

-------------------------------------------------
-- All of this can be compacted into one function
-------------------------------------------------

local function vtable_bind(interface, type, index)
    local this = ffi.cast("void***", interface)
    return function (...)
        return ffi.cast(ffi.typeof(type), this[0][index])(this, ...)
    end
end
--                                       Interface       Function type                            Virtual index
local ClientCmd_AltVersion = vtable_bind(IVEngineClient, "void(__thiscall*)(void*, const char*)", 108)

Watermark

-- Create a gui element
local CheckboxItem = gui.add_checkbox("Example Watermark", "Visuals>Misc>Various")

-- Get our font 
local Font = render.create_font("verdana.ttf", 14)

-- Set how many pixels of spacing we want 
local Spacing = {30, 30}
local Padding = {6, 2}
local WatermarkName = "Fatality.win"

-- Use the paint callback
function on_paint()
    -- Check if our checkbox is active (get_bool() == true) 
    -- If not then do nothing and return
    if not CheckboxItem:get_bool() then
        return
    end
    -- Get our screensize
    local ScreenSize = {render.get_screen_size()}
    -- Calculate the text size of the cheat name
    local TextSize = {render.get_text_size(Font, WatermarkName)}

    -- Calculate our text size with spacing
    local Size      = {TextSize[1] + (Padding[1] * 2), TextSize[2] + (Padding[2] * 2)}
    local Position  = {ScreenSize[1] - Size[1] - Spacing[1], Spacing[2]}

    -- Render background
    render.rect_filled(Position[1], Position[2], Position[1] + Size[1], Position[2] + Size[2], render.color(58, 36, 107, 255))
    render.rect(Position[1], Position[2], Position[1] + Size[1], Position[2] + Size[2], render.color(26, 22, 64, 200))

    -- Render our text
    render.text(Font, Position[1] + Padding[1], Position[2] + Size[2] / 2, WatermarkName, render.color("#FFFFFF"), render.align_left, render.align_center)
end

Accessing callbacks

-- define a function with the name of the callback you want to use
-- here i will use create_move

-- add any parameters that are passed into the callback (read the callbacks page to see what is passed in each callback)
-- for example events from their callbacks are accessed like this function on_item_pickup(event <- here)
function on_create_move(user_cmd)
    
    -- here you can access the data inside of the current user command (user_cmd datatype)
    user_cmd:get_buttons()
end

Last updated