Skip to content

Lua API Reference

xAstroBoy edited this page Apr 14, 2026 · 2 revisions

Lua API Reference

This is the complete API reference for Quest UE4 Modloader's Lua scripting environment.

For the full detailed reference, see docs/LUA_API.md

Table of Contents

  1. Logging
  2. Object Finding
  3. UObject Methods
  4. ProcessEvent Hooks
  5. Native Hooks
  6. Memory Read/Write
  7. Timers & Delayed Actions
  8. Structs (LuaUStruct)
  9. TArray
  10. Enums
  11. Widget Creation
  12. Config & File I/O
  13. Cross-Mod Communication
  14. Bridge Commands

1. Logging

Log("Info message")
LogWarn("Warning message")
LogError("Error message")
print("Debug", 42, true, obj) -- Auto-formats all typesNotify("Title", "Body") -- In-game notification

2. Object Finding

-- Most commonly used:localobj=FindFirstOf("ClassName") -- First live instancelocalall=FindAllOf("ClassName") -- All live instances (table)-- Advanced:localcls=FindClass("ClassName") -- UClass objectlocalobj=FindObject("ShortName") -- By short namelocalobj=StaticFindObject("FullPath") -- By full pathlocalobj=LoadAsset("/Game/Path/Asset") -- Load from PAKlocalworld=GetWorldContext() -- Current UWorld

3. UObject Methods

Every UObject returned by the API has these methods:

obj:IsValid() -- Is this object still alive?obj:GetName() -- Short name (e.g., "PlayerController_0")obj:GetFullName() -- Full pathobj:GetClass() -- UClass objectobj:GetClassName() -- Class name string-- Property access (reflection)obj:Get("PropName") -- Read propertyobj:Set("PropName", v) -- Write propertyobj.PropName-- Shorthand readobj.PropName=v-- Shorthand write-- Function callsobj:Call("FuncName", arg1, arg2, ...)
obj:FuncName(arg1, arg2, ...) -- Shorthand-- Type checkingUObject_IsA(obj, "ClassName") -- Inheritance check

4. ProcessEvent Hooks

-- Pre-hook: fires BEFORE original. Return "BLOCK" to prevent it.RegisterPreHook("/Script/Game.Class:Function", function(self, func, parms)
localobj=self:get()
return"BLOCK" -- Optional: skip originalend)
-- Post-hook: fires AFTER original.RegisterPostHook("/Script/Game.Class:Function", function(self, func, parms)
localobj=self:get()
WriteU8(parms, 0) -- Modify return valueend)
-- Combined (returns IDs for removal)localpreId, postId=RegisterHook("Class:Func", function(self, parms) end)
UnregisterHook("Class:Func", preId, postId)

Hook Paths

Function paths follow UE4's naming:

  • Blueprint: /Game/Blueprints/Path/BP.BP_C:FunctionName
  • Native: /Script/ModuleName.ClassName:FunctionName

5. Native Hooks

-- Hook by C++ symbol nameRegisterNativeHook("_ZN9SomeClass4FuncEv", "fp",
function(thisPtr) end, -- Pre-hookfunction(thisPtr, retval) end-- Post-hook
)
-- Hook by addresslocalbase=GetLibBase()
RegisterNativeHookAt(Offset(base, 0x1234), "vpp",
function(a1, a2) return"BLOCK" end,
nil
)
-- Call native functionlocalresult=CallNativeBySymbol("_ZSymbol", "ip", ptr)
localresult=CallNative(addr, "fp", ptr)

Signature format: First char = return type, rest = arg types. v=void, i=int32, u=uint32, b=bool, p=pointer, f=float, d=double, l=int64

6. Memory Read/Write

⚠️ Only use for byte/instruction patching. For UObject properties, use Get/Set.

ReadU8(addr) /WriteU8(addr, val) -- 8-bitReadU16(addr) /WriteU16(addr, val) -- 16-bitReadU32(addr) /WriteU32(addr, val) -- 32-bitReadU64(addr) /WriteU64(addr, val) -- 64-bitReadS32(addr) /WriteS32(addr, val) -- Signed 32-bitReadFloat(addr) /WriteFloat(addr, v) -- Float-- Address helperslocalbase=GetLibBase() -- Game library baselocalsym=FindSymbol("name") -- dlsym resolvelocalsym=Resolve("name") -- Full resolution chainlocalpat=FindPattern("FF 43 ?? ??") -- Byte pattern scanlocalptr=Offset(base, 0x1000) -- Pointer arithmeticIsNull(ptr) -- NULL checkIsValidPtr(ptr) -- Mapped check

7. Timers & Delayed Actions

-- One-shot timerlocalh=ExecuteWithDelay(5000, function() end)
-- Next tickExecuteAsync(function() end)
-- Repeating timerlocalh=LoopAsync(2000, function() end)
-- Game thread variants (safe for UObject modification)ExecuteInGameThread(function() end)
ExecuteInGameThreadWithDelay(1000, function() end)
LoopInGameThread(2000, function() end)
-- Frame-based timersExecuteWithDelayFrames(60, function() end)
LoopAsyncFrames(1, function() end) -- Every frame-- CancelCancelDelayedAction(h)
IsDelayedActionValid(h)

8. Structs

Struct properties (FVector, FRotator, IntPoint, etc.) are returned as LuaUStruct userdata:

localpos=actor:Get("Position") -- LuaUStruct-- Field accesspos.X-- Read fieldpos.X=100-- Write field (writes to live memory)-- Set from tableactor:Set("Position", {X=100, Y=200, Z=300})
-- Pass struct to Call()actor:Call("SetActorLocation", {X=100, Y=200, Z=300})
-- Methodspos:GetTypeName() -- "FVector"pos:GetSize() -- Struct size in bytespos:Clone() -- Independent copypos:CopyFrom({X=1}) -- Copy from tablepos:GetFields() -- {X="float", Y="float", Z="float"}tostring(pos) -- "UStruct(FVector: X=100, Y=200, Z=300)"

9. TArray

TArray properties are returned as userdata with 1-based indexing:

localarr=obj:Get("SomeArray")
arr[1] -- First element (1-indexed!)arr[3] =newValue-- Write element#arr-- Lengtharr:GetArrayNum() -- Element countarr:IsEmpty() -- True if emptyarr:ForEach(function(i, elem)
Log(i..": " ..tostring(elem))
returnfalse-- Return true to breakend)
arr:Add(value) -- Append elementarr:Clear() -- Remove all

10. Enums

-- Global enum table (auto-populated from reflection)Enums.ECollisionChannel-- {ECC_WorldStatic=0, ...}Enums.DebugMenuType-- {NewEnumerator5=0, ...}-- Lookuplocalue=FindEnum("EnumName")
localt=GetEnumTable("EnumName") -- {Name=Value, ...}localnames=GetEnumNames() -- All enum names-- Extend (runtime, adds to UEnum metadata)AppendEnumValue("EnumName", "NewValue", 99)

11. Widget Creation

localwidget=CreateWidget("TextBlock")
localvbox=CreateWidget("VerticalBox")
localcustom=CreateWidget("MyWidget_C")
-- With owning playerlocalpc=FindFirstOf("PlayerController")
localw=CreateWidget("TextBlock", pc)

12. Config & File I/O

-- ModConfig (JSON, persistent)ModConfig.Save("ModName", {key="value", num=42})
localcfg=ModConfig.Load("ModName")
localpath=ModConfig.GetPath("ModName")
-- Raw file I/Olocaltext=ReadTextFile("/path/to/file")
WriteTextFile("/path/to/file", "content")
FileExists("/path/to/file")
-- Mod pathsGetModDir() -- This mod's directoryGetDataDir() -- Shared data directory

13. Cross-Mod Communication

-- SharedAPI table (shared across all mods)SharedAPI.MyMod= { DoSomething=function() end }
-- Shared variablesSetSharedVariable("key", value)
localv=GetSharedVariable("key")

14. Bridge Commands

RegisterBridgeCommand("my_command", function(args)
return { status="ok", data=42 }
end)

Test: python tools/deploy.py consolemy_command

Clone this wiki locally