Configuration
Everything CU3ML reads and writes lives in the game's Mods/ directory —
two levels above the executable. Three files matter:
| File | Written by | Purpose |
|---|---|---|
cu3ml.toml |
loader / manager | Loader settings and per-mod enable state |
cu3ml.addrlist |
loader | Cached engine addresses for this exact .exe |
cu3ml.log |
loader | Log from the most recent launch |
cu3ml.toml
Written on first launch with defaults, and rewritten whenever something changes. Safe to hand-edit while the game is closed.
# CU3ML - crappy unreal engine 3 mod loader
# Written by the loader. Safe to edit while the game is closed.
[loader]
# embedded Lua VM and mod scripts (-nolua overrides this)
lua = true
# verbose Lua logging (-luaverbose overrides this)
lua_verbose = false
# open the manager on every launch, without -cu3ml-manager
manager_at_start = false
[mods]
# key = mod folder name inside this directory
"ExampleMod" = true
"SomeOtherMod" = false
[loader] accepts true/false, 1/0, yes/no, on/off; unknown keys are
logged as warnings and ignored.
[mods] keys are folder names, matched case-insensitively. On every
launch the loader rewrites this table to exactly the set of mod folders it
found: new folders are added as enabled, folders that no longer exist are
dropped. Editing a value to false keeps the mod on disk but excludes it
from content registration, replace patches, override discovery and Lua
startup scripts.
Command-line switches
Pass these to the game's executable (via a shortcut, launch options, or your
launcher of choice). Both -switch and /switch work, case-insensitively.
| Switch | Effect |
|---|---|
-cu3ml-manager |
Halt at the start of GEngineLoop::Init and open the manager |
-cu3ml-noaddrcache |
Ignore cu3ml.addrlist and force a full re-scan (the fresh results are still written back) |
-nolua |
Disable the Lua VM for this launch, overriding lua = true |
-luaverbose |
Log the result of every chunk the Lua host runs |
-lua=<path> |
Run an extra Lua script after all mod scripts. Repeatable |
Any other -switch on the command line is recorded and visible to scripts
via ue3.has_switch("switch").
cu3ml.addrlist
A flat key value text file of everything the resolver worked out by
disassembly — pointers stored as RVAs from the module base, scalars as
struct offsets and vtable slots.
# cu3ml address cache - generated automatically.
# Pointers are RVAs from the main module base; scalars are
# struct offsets / vtable slots. Delete this file (or pass
# -cu3ml-noaddrcache) to force a full re-scan.
cache.version 3
cache.bits 64
image.timestamp 0x...
image.size 0x...
image.checksum 0x...
image.entry 0x...
engine.EngineLoopInit 0x...
lua.Localize 0x...
The header pins the cache to one specific executable: cache format version,
pointer size, and the PE timestamp, size, checksum and entry point. If any
of those don't match, the whole file is discarded and the loader re-scans.
An RVA that falls outside the image is rejected rather than dereferenced,
and subsystems can call addr_cache::invalidate() at runtime — the Lua host
does this if hooks built from cached addresses fail to install.
Deleting the file is always safe; the next launch just takes longer.
cu3ml.log
Recreated on every launch (the previous run's log is not kept). It records the resolved layout, every discovered mod and override, each hook installation, and all output from scripts. It's the first thing to attach to a bug report — see FAQ.