Docs · For modders
Getting started: install V3X and write your first plugin in 10 minutes
Install the loader, build the template plugin and run it, in about 10 minutes.
Copied from docs/getting-started.md in the V3X repository, file dated 2026-11-13.
V3X loads your compiled C/C++ code into victoria3.exe, so you can hook and patch engine
functions directly. This guide installs the loader, builds the template plugin, and runs it.
Read safety.md before you change game state.
Single player only. Native code is not part of the multiplayer checksum, so other players would be out of sync. Back up your saves.
1. Requirements (2 minutes)
- Victoria 3 on Windows x64 (the plugins in this repo were reverse-engineered on 1.15.1; other builds may make some plugins refuse to load, which is the intended fail-closed behaviour).
- Python 3.8+ and the zig compiler from pip:
pip install ziglang. No Visual Studio needed. Any x64 Windows C compiler works (MSVC, clang, mingw); zig is the tested one. - For the reverse-engineering tools:
pip install pefile capstone(see reverse-engineering.md). - A shell: Git Bash for
build.sh, or cmd/PowerShell for the Python build script.
2. Install the loader (2 minutes)
Put (or clone) this repository as a folder inside the game folder, next to binaries/:
<Steam>/steamapps/common/Victoria 3/
binaries/victoria3.exe
v3x/ <- this repository
Then build and install:
cd "<Steam>/steamapps/common/Victoria 3/v3x"
./build.sh install # builds build/version.dll + build/plugins/*.dll, copies them into ../binaries
This puts binaries/version.dll (the loader) and binaries/v3x/plugins/*.dll in place. Start
the game normally (Steam or the launcher). A “V3X console” window opens next to it; the log is
binaries/v3x/v3x.log.
- Not all bundled plugins are for everyone. Disable one without deleting it in
binaries/v3x/v3x.ini:
The key is the DLL file name without[plugins] alloc_tracker = 0 lazy_mesh = 0.dll(case-insensitive);0,off,noorfalseskip it, a missing key means enabled. Thepluginsconsole command lists skipped plugins asdisabled (v3x.ini [plugins]). Themod_menuplugin edits this section from the main menu. - No console window:
console=0inbinaries/v3x/v3x.ini, or the env varV3X_NO_CONSOLE=1. - Disable V3X for one run: env var
V3X_DISABLE=1. - Uninstall: delete
binaries/version.dllandbinaries/v3x/. Steam “Verify files” does not remove version.dll (it is not a game file).
3. Build the template plugin (3 minutes)
python sdk/build_plugin.py templates/plugin_template --test
This builds build/plugins/my_plugin.dll, then builds and runs the offline test
templates/plugin_template/test_my_plugin.c. The test maps ../binaries/victoria3.exe
read-only (nothing in it runs) and checks that the plugin’s anchor finds its target:
[my_plugin] anchor game_tick at exe+0x1465690 ok
OK : anchors resolve on ...victoria3.exe
OK : plugin loads and installs exactly 1 hook
4 checks, 0 failed
ALL OK
If the anchor fails on your game build, the plugin would refuse to install anything. That is the point: see safety.md.
4. Run it (2 minutes)
python sdk/build_plugin.py templates/plugin_template --install
Start the game, load a save, unpause for a few days, and type into the V3X console (the numbers below are illustrative; the template has not been run in the game as part of this repo’s tests):
> plugins
my_plugin 0.1.0 my_plugin.dll loaded at 00007FF...
template: counts and times game ticks -- your name
> mytick
my_plugin: 412 ticks, avg 9312 us, max 61044 us
5. Read the template (1 minute)
templates/plugin_template/my_plugin.c is about 100 lines:
#include "v3x_sdk.h"
V3X_PLUGIN_MANIFEST("my_plugin", "0.1.0", "your name", "template: counts and times game ticks",
"release/1.15*");
V3xAnchor my_plugin_anchors[] = {
{"game_tick", "Processing Tick: ", "48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24", V3X_ANCHOR_ALL_SAME},
};
static void tick_pre(V3X_HookCall *c) { /* store a start time in c->scratch[0] */ }
static void tick_post(V3X_HookCall *c) { /* count, time; c->ret is the return value */ }
V3X_EXPORT int v3x_plugin_load(const V3X_API *a)
{
api = a;
if (!V3X_HAS(api, hook_safe)) return 1; /* loader too old */
if (my_plugin_resolve(api) != 0) return 1; /* anchor failed: install nothing */
return api->hook_safe(my_plugin_anchors[0].result, tick_pre, tick_post, NULL) ? 1 : 0;
}
V3X_PLUGIN_MANIFESTexports name, version, author, description and the supported game builds. Thepluginscommand shows them; a build mismatch is logged as a WARNING.- The anchor finds the function that references the log string
"Processing Tick: "and checks its first bytes. Nothing is hardcoded. api->hook_safeinstalls a generic pass-through thunk: you never write a detour with a guessed prototype.presees every argument (c->args[],c->xmm[]),postsees the return value.
Next steps
| you want to | read |
|---|---|
| know every API function and on which thread it may be called | api-reference.md |
| not crash the game | safety.md |
| find engine functions | reverse-engineering.md, engine-map.md |
| see what the bundled plugins do | plugins.md |
| understand a crash | troubleshooting.md |
| common questions | faq.md |