The MWOn12 SDK is how you write mods for Most Wanted under MWOn12. It has seven parts, and you can use any of them without the others.
| Part | What it is |
|---|---|
| Plugins | A DLL that MWOn12 loads and hands the live Direct3D 12 device to, once per frame, with the back buffer ready to draw on. A C ABI, C++ helpers, a static library and samples. |
| ASI mods | The format most existing Most Wanted mods ship in. MWOn12 loads them before the game initialises, and they can still get the device every frame. |
| Hooking | Hook the game's own functions, patch memory, scan for byte patterns: gameplay, physics and AI, everything that never touches Direct3D. |
| Shader kit | Replace the game's shaders with your own HLSL. No code and no compiler: edit a text file and restart. |
| Graphics | See every draw and pipeline as the frame is built, drop draws, swap shaders at runtime, and read the buffers behind a draw, through VanGFX. |
| MWSDK | The game itself rather than its rendering: verified addresses, typed object views, live attributes, and the file formats. |
| User interface | VanGUI, built in, with the descriptor heap, the window hook and the backend lifecycles handled for you. |
A plugin
A plugin is a 32-bit DLL in MWOn12\Plugins\ that exports one function. With the C++ helpers:
#include <mwon12/plugin.hpp>
#include <mwon12/overlay.hpp>
class MyPlugin final : public mwon12::Plugin {
public:
const char* Name() const override { return "MyPlugin"; }
void OnDeviceCreated(const MWOn12_DeviceInfo& d) override {
m_ui.Init(static_cast<ID3D12Device*>(d.device),
static_cast<DXGI_FORMAT>(d.backBufferFormat), d.frameCount);
}
void OnPresent(const MWOn12_Frame& f) override {
m_ui.Begin(f);
m_ui.Rect(20, 20, 120, 10, 0xFF4040FF); // x, y, w, h, 0xRRGGBBAA
m_ui.Submit(static_cast<ID3D12GraphicsCommandList*>(f.commandList));
}
void OnDeviceDestroyed() override { m_ui.Shutdown(); }
private:
mwon12::Overlay m_ui;
};
MWON12_PLUGIN(MyPlugin)
An ASI mod can join the same plugin system: MWOn12 exports MWOn12_RegisterPlugin, and <mwon12/asi.hpp> wraps it in one macro. Registration waits for the render thread, so callbacks always arrive there and never at the same time. The difference between an ASI and a plugin is when your code first runs, not what it's allowed to do.
Samples and tutorials
Five samples each exercise one part of the SDK:
FrameStatswrites the frame rate to the log and draws nothing. Build it first: if its lines appear, your install is right.HelloOverlaydraws a frame-rate bar over the game.GameHookshooks, patches and scans.VanGfxProbecounts draws and pipeline states.GameSdkreads the live vehicle list through MWSDK.
Four tutorials build small, finished mods, each a standalone .asi: a full-screen colour grade with an F12 menu, stopping the police from spawning, a top-speed boost on a key press, and culling draws live from a menu.
Building
Build.bat
Visual Studio 2022 with the C++ workload. No DirectX SDK, no network, no package manager. It's C++23, because VanHooks and VanGFX are built on std::expected, and everything is x86, because speed.exe is 32-bit: CMake stops the build rather than let you produce a 64-bit plugin that loads into nothing.
Linking the whole SDK costs a plugin nothing it doesn't use. A static library only contributes the code you reference, so FrameStats.dll is 114,176 bytes and imports only KERNEL32.dll whether one dependency is linked or all four.

