Skip to content

Script bindings: Script flow

Verified against: SLUS_212.15 (NTSC-U, SHA1 e9cb2cc49aa046b9e494313dce2f5038ed17b2f4).

Bindings for running scripts, scheduled calls, callbacks and message handlers: 18 in all. Conventions, the other categories and how to read an entry are on the masterlist.

Binding Returns Scripts Boot Mission 1 Evidence
doFile - 39 yes no confirmed (code)
doInclude - 0 no no confirmed (code)
FlushScheduledFuncs - 134 yes yes confirmed (code)
gc - 18 yes yes confirmed (code)
preLoadFile - 61 yes yes confirmed (code)
RegisterUpdate - 0 no no confirmed (code)
ScheduleFunc - 204 yes yes confirmed (code)
ScheduleFuncArg1 - 89 yes yes confirmed (code)
SetAllClearCallBack - 2 no no confirmed (code)
SetArmiesMultiplayerCallback - 0 no no inferred
SetCheatCallback - 1 yes no confirmed (code)
SetGeneralCarMsgHandler - 10 no no confirmed (code)
SetHatCallBack - 2 no no confirmed (code)
SetMsgHandler - 195 yes yes confirmed (code)
SetMsgHandlerEx - 43 yes yes confirmed (code)
SetMultiplayerCallback - 6 yes no confirmed (code)
SetObjZoneMsgHandler - 5 no no confirmed (code)
SetStartGameCallback - 116 no yes confirmed (code)

doFile

doFile(name)
# Argument Read as Meaning
1 name string Script name without extension, such as config_easy.

Returns nothing.

Runs name .. ".lua" from the WAD synchronously in the current Lua state (script system slot +0x34).

Notes. A PC-style path under the current level's folder is built when 0x001458c0 returns 0, which it never does in this build.

  • Evidence: confirmed (code) at 0x003579a0; detail: traced
  • Wrapper 0x0036d648 (registered by RegisterBindings); calls 0x003579a0
  • Used by 39 of 467 script chunks (80 references); boot to menu: yes; mission 1: no; result used: no
  • Later in the story: 15 of 28 levels, first level87 (mission 3)
  • Coney: implemented

doInclude

doInclude(name)
# Argument Read as Meaning
1 name string Script name without extension.

Returns nothing.

The same as doFile (the same callee, 0x003579a0). No shipped script calls it.

  • Evidence: confirmed (code) at 0x003579a0; detail: brief
  • Wrapper 0x0036d678 (registered by RegisterBindings); calls 0x003579a0
  • Used by no script on the disc
  • Coney: not implemented

FlushScheduledFuncs

FlushScheduledFuncs(callback)
# Argument Read as Meaning
1 callback string Name of the function whose pending calls to cancel; nil cancels every pending call.

Returns nothing.

Cancels scheduled calls (slot +0xac).

  • Evidence: confirmed (code) at 0x00386450; detail: traced
  • Wrapper 0x0036d848 (registered by RegisterBindings); calls 0x00386450
  • Used by 134 of 467 script chunks (358 references); boot to menu: yes; mission 1: yes; result used: no
  • Later in the story: 23 of 28 levels, first level80 (mission 2)
  • Coney: implemented

gc

gc()

No arguments.

Returns nothing.

Runs a Lua garbage collection now and pushes the next forced collection 2 s away (script system slot +0x1c).

  • Evidence: confirmed (code) at 0x00386370; detail: traced
  • Wrapper 0x0036d700 (registered by RegisterBindings); calls 0x00386370
  • Used by 18 of 467 script chunks (56 references); boot to menu: yes; mission 1: yes; result used: no
  • Later in the story: 7 of 28 levels, first level95 (the hub)
  • Coney: implemented

preLoadFile

preLoadFile(name, callback)
# Argument Read as Meaning
1 name string Script name without extension.
2 callback string Name of the Lua function to call once the script has loaded and run (for example a checkpoint's start function).

Returns nothing.

Requests name .. ".lua" from the file manager asynchronously; when it arrives it is run and then the callback is called. Level scripts load their checkpoint scripts this way.

Notes. The completion routine is 0x00356d00; that it calls the callback after running the file is inferred (scripting.md, open question).

  • Evidence: confirmed (code) at 0x00357a68; detail: traced
  • Wrapper 0x0036d6a8 (registered by RegisterBindings); calls 0x00357a68
  • Used by 61 of 467 script chunks (94 references); boot to menu: yes; mission 1: yes; result used: no
  • Later in the story: 28 of 28 levels, first level80 (mission 2)
  • Coney: implemented

RegisterUpdate

RegisterUpdate(callback)
# Argument Read as Meaning
1 callback string Name of a Lua function to call every frame with the frame time in milliseconds, or nil to stop.

Returns nothing.

Sets the script system's per-frame update function (slot +0xb4). No shipped script calls it.

  • Evidence: confirmed (code) at 0x003863a0; detail: brief
  • Wrapper 0x0036d720 (registered by RegisterBindings); calls 0x003863a0
  • Used by no script on the disc
  • Coney: not implemented

ScheduleFunc

ScheduleFunc(callback, delayMs)
# Argument Read as Meaning
1 callback string Name of the Lua function to call (dotted names allowed); looked up when it fires, so it can be redefined meanwhile.
2 delayMs number, truncated to an unsigned integer Delay in milliseconds on the game timer.

Returns nothing.

Calls a Lua function once, with no arguments, after a delay (script system slot +0x94). A name that no longer resolves to a function is dropped silently.

  • Evidence: confirmed (code) at 0x003863d8; detail: traced
  • Wrapper 0x0036d750 (registered by RegisterBindings); calls 0x003863d8
  • Used by 204 of 467 script chunks (1911 references); boot to menu: yes; mission 1: yes; result used: no
  • Later in the story: 28 of 28 levels, first level80 (mission 2)
  • Coney: implemented

ScheduleFuncArg1

ScheduleFuncArg1(callback, arg, delayMs)
# Argument Read as Meaning
1 callback string Name of the Lua function to call.
2 arg number, truncated to an unsigned integer The number passed to the function; converted to an unsigned 32-bit integer, so fractions are cut and negative values wrap.
3 delayMs number, truncated to an unsigned integer Delay in milliseconds on the game timer.

Returns nothing.

Calls a Lua function once with one number argument after a delay (slot +0x9c).

Notes. The argument order is (name, argument, delay): confirmed at 0x003572e8, which adds its last parameter to the game time; scripting.md's ScheduleFuncArg1(name, ms, n) has the two numbers the wrong way round.

  • Evidence: confirmed (code) at 0x00386410; detail: traced
  • Wrapper 0x0036d7b0 (registered by RegisterBindings); calls 0x00386410
  • Used by 89 of 467 script chunks (293 references); boot to menu: yes; mission 1: yes; result used: no
  • Later in the story: 23 of 28 levels, first level80 (mission 2)
  • Coney: implemented

SetAllClearCallBack

SetAllClearCallBack(callback)
# Argument Read as Meaning
1 callback string Lua function name (copied, at most 31 characters, to W_GameState + 0x2bc), or nil to clear it.

Returns nothing.

Sets the function called, with no arguments, when player 1's gang is in the clear: when its police wanted timer (gang +0x5e8) runs out with no crime in progress and the police turn neutral again (0x00169a20, which also tells the HUD and sets the last crime type to 0xe), or when its second timer (gang +0x5f0, set by GangRespond and GoalCallGang) runs out.

Notes. Setting a name also clears game state byte +0x2db (the byte before the name). The callback is only called if the name is a Lua function. Other readers of +0x2bc (0x0016cc60, Crime_UpdateLevel 0x0041c128) are not traced. Wanted timers: Crimes.

  • Evidence: confirmed (code) at 0x0041add0, 0x0041adf8, 0x001698f0, 0x00169a20; detail: traced
  • Wrapper 0x003705d0 (registered by RegisterBindings); calls 0x0041add0, 0x0041adf8 GameState_SetAllClearCallback, 0x001698f0 Gang_UpdateWanted, 0x00169a20 Gang_ClearWanted
  • Used by 2 of 467 script chunks (3 references); boot to menu: no; mission 1: no; result used: no
  • Later in the story: 1 of 28 levels, first level20 (flashback 4)
  • Coney: not implemented

SetArmiesMultiplayerCallback

SetArmiesMultiplayerCallback(callback)
# Argument Read as Meaning
1 callback string Lua function name, or nil.

Returns nothing.

Like SetMultiplayerCallback, for the Armies of the Night mode (stored by 0x0041b2c8). No shipped script calls it.

  • Evidence: inferred; detail: brief
  • Wrapper 0x00370660 (registered by RegisterBindings); calls 0x0041b280
  • Used by no script on the disc
  • Coney: not implemented

SetCheatCallback

SetCheatCallback(callback)
# Argument Read as Meaning
1 callback string Name of the Lua function to call when a cheat code is entered.

Returns nothing.

Interns and stores the cheat callback's name (0x0050ca98); global.lua sets it to its debug cheat handler.

Notes. What calls it and with which arguments is not traced.

  • Evidence: confirmed (code) at 0x00163e98; detail: traced
  • Wrapper 0x0036e488 (registered by RegisterBindings); calls 0x00163e98
  • Used by 1 of 467 script chunks (1 reference); boot to menu: yes; mission 1: no; result used: no
  • Coney: not implemented

SetGeneralCarMsgHandler

SetGeneralCarMsgHandler(message, callback)
# Argument Read as Meaning
1 message number, truncated to an integer Message number; every call passes 25 (0x19), the message a car sends itself when a hit damages it or it explodes.
2 callback string Name of the Lua function to call, or nil to remove it.

Returns nothing.

Registers one Lua callback for a message from any car: the car manager (0x00512c7c + 0x844) keeps the function's reference in its slot for that number (+0x18 + 4 × message). Message 0x19 calls it as (car, other, n, flag): once per part a hit damages (n = the part 1-25, other the human behind the hit, flag 1 when the hit broke the part), (car, human, -2, 1) when that hit leaves every breakable part broken, (car, thrower, -1, 0) when a molotov sets the car alight, and (car, NilHandle, -1, 1) when it explodes (Cars). It is the only way to hear a car: a car has no handler component, so SetMsgHandler on a car is never called.

Notes. The store is confirmed (code) at 0x0038e538; the reference comes from the script system's slot +0xcc. The car's message slot (vtable 0x00544c08 +0x44, 0x00389700) forwards every message to 0x0038ebf8, which calls the marshaller with the stored reference when the slot is set (Cars: explosion).

  • Evidence: confirmed (code) at 0x00386340, 0x0038e538; detail: traced
  • Wrapper 0x0036d2e8 (registered by RegisterBindings); calls 0x00386340 Script_SetGeneralCarMsgHandler, 0x0038e538 CarManager_SetMsgHandler
  • Used by 10 of 467 script chunks (20 references); boot to menu: no; mission 1: no; result used: no
  • Later in the story: 8 of 28 levels, first level34 (mission 4)
  • Coney: implemented

SetHatCallBack

SetHatCallBack(callback)
# Argument Read as Meaning
1 callback string Lua function name (copied, at most 31 characters, to W_GameState + 0x33c), or nil to clear it.

Returns nothing.

Sets the function called as f(humanHandle, hatHandle, typeName) whenever a human takes a hat: the human message handler (0x0024667c in Human_HandleMessage) stores the hat object's handle at human +0x364 and then calls it, with the hat's object type name. Not called while a scene plays (game state +0x410) or when either handle no longer resolves.

Notes. Fires for any human (thugs going for hats included), not only the player. Setting a name clears game state byte +0x35b. Cleared on every level load (0x00418c68). The message that leads there is not identified.

  • Evidence: confirmed (code) at 0x0041af20, 0x0041af48, 0x0041af80; detail: traced
  • Wrapper 0x00370600 (registered by RegisterBindings); calls 0x0041af20, 0x0041af48 GameState_SetHatCallback, 0x0041af80 GameState_CallHatCallback
  • Used by 2 of 467 script chunks (2 references); boot to menu: no; mission 1: no; result used: no
  • Later in the story: 1 of 28 levels, first level11 (flashback 5)
  • Coney: not implemented

SetMsgHandler

SetMsgHandler(object, message, callback)
# Argument Read as Meaning
1 object number, truncated to an unsigned integer Handle of the object or human whose messages to watch.
2 message number, truncated to an integer Message number, 0-25 (for example 3 when a human enters a volume box or trigger sphere, 4 when it leaves, 8 when an AI arrives at a flag, 18 for a death); 0 also clears the object's interaction prompt first, whatever the callback (see SetMsgHandlerEx; confirmed at runtime at the gym).
3 callback string Name of the Lua function to call (dotted names allowed), or nil to remove the handler.

Returns nothing.

Registers a Lua callback for a message an object receives: the interned name goes in slot message of the object's message-handler component (0x003860b8, made on demand). When the message arrives the callback gets arguments that depend on the number, usually the object itself and the other object involved (the table is in scripting.md#message-handlers). The most used binding in the scripts.

Notes. Messages reach Lua only while the level-end state (W_GameState + 0x14c) is 0, so no callback runs once a mission is won, failed or left (0x00384c38). The arguments per number are confirmed (code) at 0x00384ce0; the senders of 3, 4, 5 (volume boxes, trigger spheres) and 8 (flags) are confirmed, the meaning of the others is inferred from the scripts' handler names (references/script-events.md).

  • Evidence: confirmed (code) at 0x00386298; detail: traced
  • Wrapper 0x0036d1c8 (registered by RegisterBindings); calls 0x00386298
  • Used by 195 of 467 script chunks (3040 references); boot to menu: yes; mission 1: yes; result used: no
  • Later in the story: 28 of 28 levels, first level80 (mission 2)
  • Coney: implemented

SetMsgHandlerEx

SetMsgHandlerEx(object, message, callback, prompt, prompt2)
# Argument Read as Meaning
1 object number, truncated to an unsigned integer Handle of the object or human (a door, a bouncer, a tag).
2 message number, truncated to an integer Message number; 0 is the interaction (the scripts pass 0).
3 callback string Lua function name to call, or nil.
4 prompt string Text of the on-screen prompt shown when the player can interact (a string, often a GSTRING entry); nil or empty for none.
5 prompt2 string A second text, kept in the context record's +0x14 and shown in the hint box while the player can interact; given alone (prompt nil), it still makes the record.

Returns nothing.

Like SetMsgHandler but also gives the object an interaction prompt, the 'press to talk' text shown when the player is close; used for doors, bouncers and tags.

Notes. With message 0 and a callback, a non-empty prompt or a non-empty second text sets the object's prompt (vtable +0x124; with the prompt nil the record has no prompt and only the second text shows); a nil callback, or both texts nil or empty, clears it (+0x12c). On a world object the prompt is a kind-1 context record (1.1 m), which triangle hands to the message-0 callback (Scripts).

  • Evidence: confirmed (code) at 0x00386168; detail: traced
  • Wrapper 0x0036d348 (registered by RegisterBindings); calls 0x00386168
  • Used by 43 of 467 script chunks (212 references); boot to menu: yes; mission 1: yes; result used: no
  • Later in the story: 20 of 28 levels, first level87 (mission 3)
  • Coney: implemented

SetMultiplayerCallback

SetMultiplayerCallback(callback)
# Argument Read as Meaning
1 callback string Lua function name (at most 32 characters), or nil to clear.

Returns nothing.

Sets the function called when a second player joins (kept at W_GameState + 0x3a4); global.lua uses it to give the new player an inventory.

Notes. The store is confirmed; the trigger is inferred from the scripts' handler names.

  • Evidence: confirmed (code) at 0x0041b0f0; detail: traced
  • Wrapper 0x00370630 (registered by RegisterBindings); calls 0x0041b0f0
  • Used by 6 of 467 script chunks (7 references); boot to menu: yes; mission 1: no; result used: no
  • Later in the story: 5 of 28 levels, first level60 (Armies of the Night 1)
  • Coney: implemented

SetObjZoneMsgHandler

SetObjZoneMsgHandler(zone, message, callback)
# Argument Read as Meaning
1 zone number, truncated to an unsigned integer Object zone number 0-254 (Object zones); not range-checked.
2 message number, truncated to an integer Message number 0-25, as for SetMsgHandler (Script events); scripts use 1 (damaged) and 2 (broken). Not range-checked.
3 callback string Lua function name, interned; nil clears the slot.

Returns nothing.

Registers one Lua callback for a message on every world object of an object zone, in the object manager's table (255 zones of 26 slots, object manager +0x50 + zone * 0x68 + message * 4). Whenever a world object gets a message (0x00392520), the manager finds its spawn record, and when that record's zone has a callback for the message it is called like an object's own handler (same arguments, Scripts: message handlers); the object's own handlers run after it.

Notes. Only objects spawned from the level's spawn table belong to a zone. The table is cleared when the spawn table is reset (0x00398130). Out-of-range zone or message numbers write past the table.

  • Evidence: confirmed (code) at 0x00386308, 0x0039a7e0, 0x003982a0, 0x00392520; detail: traced
  • Wrapper 0x0036d258 (registered by RegisterBindings); calls 0x00386308, 0x0039a7e0 ObjZone_SetMsgHandler, 0x003982a0 ObjZone_DispatchMessage, 0x00392520
  • Used by 5 of 467 script chunks (34 references); boot to menu: no; mission 1: no; result used: no
  • Later in the story: 4 of 28 levels, first level93 (mission 10)
  • Coney: not implemented

SetStartGameCallback

SetStartGameCallback(callback)
# Argument Read as Meaning
1 callback string Name of the Lua function (at most 31 characters) that InitLevel calls when the level is ready; nil clears it.

Returns nothing.

Sets the function run once the level has finished loading (kept at 0x005e6d88).

  • Evidence: confirmed (code) at 0x0015fe50; detail: traced
  • Wrapper 0x0036df98 (registered by RegisterBindings); calls 0x0015fe50
  • Used by 116 of 467 script chunks (219 references); boot to menu: no; mission 1: yes; result used: no
  • Later in the story: 26 of 28 levels, first level87 (mission 3)
  • Coney: implemented