Developer Events Hooks Guide
Hands-on subscribing, emitting, and naming. Concepts: Core Events. Catalog: Hooks Reference.
Subscribe (Lua)
Section titled “Subscribe (Lua)”local token = greg.on("greg.Audio.AudioManager.SetEffectsVolume", function(payload) greg.ui.log_info("Volume changed!")end)
greg.once("greg.PLAYER.CoinChanged", function(payload) ... end)greg.off(token) -- unsubscribe early; otherwise auto-removed at shutdown/reloadPayload shape (via PayloadToTable): { hook_name, timestamp, cancelable, cancelled, data } — read args from payload.data.
Emit your own (mod-to-mod)
Section titled “Emit your own (mod-to-mod)”greg.fire("my_mod.job_done", { result = "ok", count = 3 })greg.on("my_mod.job_done", function(payload) local n = payload.data["count"]end)Use your mod ID as prefix (my_mod.*) to avoid collisions. Document your custom events in your README.
Discover hooks
Section titled “Discover hooks”greg.hooks.groups() -- all 22 groupsgreg.hooks.audio.list() -- hook IDs in Audiogreg.hooks.networking.list()Per-group sugar (generated by LuaHookBindingGenerator from game_hooks.json):
greg.hooks.<group>.on_<snake_case_method>(callback)-- e.g. greg.hooks.audio.on_set_effects_volume(fn)-- full ID form: "greg.Audio.AudioManager.SetEffectsVolume"Subscribe (C#)
Section titled “Subscribe (C#)”[GregHook("greg.PLAYER.CoinChanged")]public void OnCoins(EventPayload payload) { … }
// or manually (inside a GregMod: tracked, IDisposable):IDisposable sub = On("greg.Group.Event", payload => { /* ... */ });// dispose in OnUnload (or DisposeSubscriptions for all at once)Native lifecycle hooks (gregNativeEventHooks): SystemGameLoaded / SystemGameSaved, GameLoaded / GameSaved, Money / Xp / ReputationChanged, Day / MonthEnded. Numeric IDs 1001–4001 (EventIds, GetByEventId) appear in examples/ — prefer string IDs in new code.
Naming + versioning your events
Section titled “Naming + versioning your events”- Full game-hook ID:
greg.{Group}.{Class}.{Method}(matchesgame_hooks.jsonrows 1:1). - Curated mod-level names:
greg.{Domain}.{Event}(greg.PLAYER.CoinChanged,greg.RACK.*,greg.SYSTEM.ButtonCheckOut). - Your own:
<modId>.<snake_event>with a stable payload table; never rename a shipped event — add a new one. - Cancelable semantics: only set
cancelledwhere the dispatcher marks the hook cancelable; document it.
Debugging hooks
Section titled “Debugging hooks”- Confirm
game_hooks.jsonsits next togregCore.dll(“No hooks found” = misplaced file). - Check
[DynamicPatcher]lines in the loader log — installed vs failed patches. - Subscribe minimally in the F12 REPL first, then move working code into
main.lua. - Suspect a game update? Re-dump + regenerate (
tools/GameApiGenerator,Generate-GregHooksFromIl2CppDump.ps1), thenscripts/validate_contracts.py.