Modding overview
Phoenix Engine is built around two ways of modding, and tries to make both pleasant:
| Softmodding | Hardmodding | |
|---|---|---|
| What | a folder in mods/ | a fork of the engine |
| Language | Lua / Luau, Python, HScript, JSON | Haxe |
| Needs a compiler | no | yes |
| Can replace assets | yes | yes |
| Can change engine behaviour | through the scripting API | anything |
| Distribution | zip the folder | ship a build |
Most mods only need softmodding. The scripting API exposes 275 Lua functions and
170 Python functions, and standalone HScript gets the engine classes directly, plus reflective getProperty/setProperty access to almost any
field in the engine.
Compatibility
Phoenix keeps the Psych Engine / JS Engine mod contract, so existing mods generally load unchanged: the same folder layout, the same callback names, the same chart format (including Psych 1.0 charts). Phoenix additions are strictly additive — Python scripting, extra callbacks, extra events.
What a build supports
Scripting is compile-time gated. -DMODDING_LEVEL=0 disables both Lua and Python, and
=1 keeps Lua but drops Python. HScript is controlled separately by HSCRIPT_ALLOWED, so
it stays available at every modding level on targets that support it:
| Build | MODS_ALLOWED | Lua | Python | HScript |
|---|---|---|---|---|
| Desktop (default) | ✓ | ✓ | ✓ | ✓ |
| Mobile (default) | ✓ | ✓ | ✓ | ✓ |
-DMODDING_LEVEL=1 | ✓ | ✓ | ✗ | ✓ |
-DMODDING_LEVEL=0 | ✓ | ✗ | ✗ | ✓ |
| HTML5 / Flash / AIR | ✗ | ✗ | ✗ | web only |
Getting started
- Create the folder —
mods/MyMod/with the subfolders you need. See Mod folder structure. - Enable it — add
MyMod|1tomodsList.txt, or toggle it in the in-game Mods menu. - Add content — charts in
data/, audio insongs/, art inimages/, characters incharacters/, weeks inweeks/. - Add behaviour — a
.lua,.pyor.hx/.hscriptscript inscripts/(global) ordata/<song>/(per song). Start fromdocs/TemplateScript.lua/docs/TemplateScript.py/docs/TemplateScript.hx. - Test — run the game, watch the on-screen debug text for script errors.
-- mods/MyMod/scripts/hello.lua
function onCreatePost()
debugPrint('Hello from MyMod!')
end
function onBeatHit()
if curBeat % 4 == 0 then
cameraShake('camGame', 0.005, 0.1)
end
end
# mods/MyMod/scripts/hello.py
def onCreatePost():
debugPrint('Hello from MyMod!')
def onBeatHit():
if curBeat % 4 == 0:
cameraShake('camGame', 0.005, 0.1)
The bundled example
mods/bf-clicker/ is a shipped example mod written in Python:
mods/bf-clicker/
├── data/bf-clicker/bf-clicker.json # chart (normal)
├── data/bf-clicker/bf-clicker-easy.json
├── data/bf-clicker/bf-clicker-hard.json
├── data/bf-clicker/bf-clicker.py # the song script
├── songs/bf-clicker/Inst.ogg
└── weeks/bf-clicker-week.json
example_mods/ also contains modTemplate.zip and a script template.
Where to go next
| Page | Contents |
|---|---|
| Mod folder structure | every folder the engine looks for, pack.json, load order |
| Lua scripting | how scripts are loaded, globals, patterns |
| Lua API reference | all 275 functions, generated from the engine |
| Python scripting | the Hython runtime and its differences |
| Python API reference | all 170 functions |
| HScript | standalone .hx/.hscript mods, plus running Haxe from a Lua script |
| Script hooks | every callback the engine fires |
| Custom events & notetypes | chart-driven scripting |
| Transparent window | see-through window, alpha and click-through |