Getting started
Installation
A scripted mod needs two things the plain game does not have: the Lua runtime next to the hook, and a
Scripts folder inside the mod with a main.lua in it.
The runtime#
The hook does not link Lua. It loads lua51.dll at start-up from its own folder, the one that holds
dinput8.dll and SDL3.dll. The file is LuaJIT 2.1, built for x86 from the
v2.1 branch, and is about 640 KB. The JIT is enabled and scripts have access to jit and
ffi.
If you need to build the runtime yourself, the following commands produce it:
git clone --depth 1 --branch v2.1 https://github.com/LuaJIT/LuaJIT.git
cd LuaJIT/src && mingw32-make BUILDMODE=dynamic CC=gcc
Without the file nothing happens: the log reports it in one line and the game runs as if no mod had scripts.
The DLL is not loaded at all when no mod has a Scripts\main.lua, so a Mods folder of asset-only
mods costs nothing.
The Mods folder#
Mods are placed under Mods next to the game, one folder each. The Assets folder is
the asset override system (loose files that shadow the same paths inside the game's archives) and is optional.
A file under Assets also replaces the file of the same path in the game's Data folder,
so Assets\Movies\BootUp\Intro.bik plays in place of the game's intro movie.
The Scripts folder is what this documentation covers.
<game>\Mods\
└── MyMod\
├── Assets\ loose files shadowing the archives (optional)
├── Scripts\
│ ├── main.lua runs once at start-up, registers handlers
│ └── util.lua require("util") finds it
└── ModInfo.ini
main.lua runs when the game starts, before the window exists. Any other file in
Scripts can be loaded with require by its file name. The mod's name, as
ss.mod.name reports it, is the name of the folder.
ModInfo.ini#
The mod's description. The sample mods ship with the following:
[Mod]
Name=Magnet
Version=1.0
Author=sshook samples
Description=The level's props slowly gravitate towards the player's car.Folders and zips#
A mod can be a folder or a zip with the same layout inside it (Mods\MyMod.zip with
Scripts\main.lua at its root). Both load the same way, in the order the start-up scan finds them.
The one visible difference is where saved data goes: a folder mod writes
Mods\MyMod\save.lua, a zipped mod writes Mods\MyMod.zip.save.lua next to the archive,
as the archive itself is never written to.
Checking it works#
Start the game with a main.lua that calls ss.log("hello"). The line
sshook: lua: [MyMod] hello appears in the debug output before the window is up;
How to: Testing a mod explains where to watch for it. A
main.lua that fails to compile or run is reported there as well, with the file and line, and that
mod receives nothing for the rest of the run.