Forum Mod Bakery Docs

Gag scripting documentation

Please login to contribute to the conversation.
I was going through some online storage earlier and stumbled across a document that I'd written during a "mostly offline/inactive" phase at some point in 2022. The document listed/explained the gag-related MFK script commands in TS:H&R, usable in either level setup script (level.mfk/leveli.mfk).

I thought I'd convert it (mostly unchanged) to a forum post and share here.

I don't remember sharing it much if at all (though I intended to), and I think part of why is that I considered its state unfinished/in need of more research/missing information/possibly containing some false or misunderstood information. After all, I only had a command list to begin with (from the "game.lua" script by Donut Team, I believe), and I had chosen to manually test the commands in-game and observe the effects. I'll keep that process/result warning noted here.


Method 1: Interior/exterior gag (a loose series of mostly optional commands, most flexible)

// Each gag can use as many of these commands as needed - "GagBegin" and "GagEnd" are the only required ones. These gags can exist anywhere.
GagBegin(A);
GagSetInterior(A);
GagSetCycle(A);
GagSetPosition(A,B,C);
GagSetRandom(A);
GagSetWeight(A);
GagSetSound(A);
GagSetSoundLoadDistances(A,B);
GagSetTrigger(A,B,C,D,E);
GagSetPersist(A);
GagSetCoins(A,B);
GagSetSparkle(A);
GagSetAnimCollision(A);
GagPlayFMV(A);
GagSetCameraShake(A,B,C);
GagSetIntro(A);
GagSetOutro(A);
GagSetLoadDistances(A,B);
GagCheckCollCards(A,B,C,D,E);
GagCheckMovie(A,B,C,D);
GagEnd();

GagBegin(A);
This gag exists, and any commands between this and GagEnd define things for this gag. Only required command besides GagEnd at most basic level.

A - Gag P3D file. Path rooted in “/art/nis/gags”.

GagSetInterior(A);
Define which interior (if any) the gag resides inside. By default the gag does not reside in any interior.

A - Interior’s internal name.

GagSetCycle(A);
Control gag repetition, after any given successful trigger/animation attempt. Defaults to A=”single”.

A - “single” (can be triggered once) OR “reset” (resets and can be re-triggered after each trigger, this appears to be generally broken for gags defined by GagSetTrigger to have a trigger type of “touch”) OR “cycle” (loops animation indefinitely, if not cancelled by GagSetOutro).

GagSetPosition(A,B,C);
Set the position of the gag. Defaults to A=”0”,B=”0”,C=”0”.

A - X position OR name of an existent/loaded (seems picky) Locator Type 2 to steal position coordinites from.
B - Y position (seemingly useless if A is set to a Locator Type 2).
C - Z position (seemingly useless if A is set to a Locator Type 2).

GagSetRandom(A);
Enable/disable randomising this gag and any other nearby gags with randomisation enabled, with the result that of those factored in, only one will spawn. Defaults to A=”0”.

A - “0” (randomisation disabled) OR “1” (randomisation enabled).

GagSetWeight(A);
Adjust the gag’s chance of spawning when randomisation is enabled. By default all gags have equal chance.

A - Weight value. Set to “0”, the gag cannot spawn.

GagSetSound(A);
Set a daSoundResourceData to play from any loaded SPT file upon triggering the gag (unless cancelled by GagPlayFMV). By default no daSoundResourceData is set.

A - Name of the daSoundResourceData.

GagSetSoundLoadDistances(A,B);
In theory, similar to GagSetLoadDistances, this can adjust the radius in which a player character triggers the loading of a sound file requested by the gag’s set daSoundResourceData. However, all vanilla gag daSoundResourceData scripts set “SetStreaming” to “true”, removing the need to load any sounds. Setting “SetStreaming” to “false” and adding this command does not seem to change anything or leave any evidence of action. Effect cannot be confirmed. By default this is not set.

A - Radius size. (?)
B - Radius size. (?)

GagSetTrigger(A,B,C,D,E);
Defines what trigger type the gag uses, where the trigger is placed, and the trigger’s size. By default there is no trigger.

A - “action” (the gag will trigger when the player presses ACTION as prompted whilst within the trigger radius) OR “touch” (the gag will trigger when the player is within the trigger radius).
B - X position OR name of an existent/loaded (seems picky) Locator Type 2 to steal position coordinites from.
C - Y position (seemingly useless if B is set to a Locator Type 2) OR radius size, in that event.
D - Z position (seemingly useless if C is set to/used as a radius size).
E - Radius size (seemingly useless if B is set to a Locator Type 2 and C is set to a radius size).

GagSetPersist(A);
Enable/disable gag persistence, meaning this gag will increase the level’s gag counter and level completion percentage, in addition to disabling coin rewardance and sparkle effect (if present) after being triggered once on a given game state/save file (if enabled). Defaults to A=”0”.

A - “0” (persistence disabled) OR “1” (persistence enabled).

GagSetCoins(A,B);
Set how many (if any) coins this gag rewards when triggered (only the first time per game state/save game if defined by GagSetPersist to be persistent) and when those coins are given. Defaults to no coins.

A - Number of coins given.
B - Delay (in seconds) after gag triggered before coins are given. Set to “-1”, the coins will be given after the animation finishes, unless the gag is defined to be cyclic by GagSetCycle or if GagSetOutro defines outro frames. Leaving this undefined disables coin rewardance.

GagSetSparkle(A);
Enable/disable a blue sparkle effect being rendered at the gag’s trigger (only the first time per game state/save file if defined by GagSetPersist to be persistent). By default there is no sparkle.

A - “0” (sparkle disabled) OR “1” (sparkle enabled).

GagSetAnimCollision(A);
Enable/disable collision changes in correspondence to animation. Defaults to A=”0”.

A - “0” (animation-based collision changes disabled) OR “1” (animation-based collision changes enabled).

GagPlayFMV(A);
Play a movie upon triggering the gag. This will cancel any daSoundResourceData which is also set to play via GagSetSound. By default no movie is played.

A - Movie RMV file. Path rooted in “/movies”.

GagSetCameraShake(A,B,C);
“Shake” the camera up and down rapidly upon triggering the gag. This effect can prematurely end upon a forced camera change or when entering a vehicle. By default there is no camera shake.

A - Delay (in seconds) after gag triggered before the shake begins.
B - Unknown. (?)
C - Duration (in seconds) of the shake. Set to “-1” for infinite.

GagSetIntro(A);
Loop the specified number of frames from the gag’s animation whilst the gag is loaded, until the gag is triggered. By default there are no intro frames.

A - Frame to stop looping at. Any frames prior to this will be looped.

GagSetOutro(A);
Loop the specified number of frames from the gag’s animation after the gag has been triggered and its animation has finished. By default there are no outro frames.

A - Frame to begin looping at. Any frames after this will be looped.

GagSetLoadDistances(A,B);
Adjust the radius in which a player character’s presence allows the gag’s P3D file to be loaded (relative to spawn point, likely the one defined by GagSetPosition). This is centred at an unknown point on the gag’s model. Unknown default.

A - Radius size. (?)
B - Radius size. (?)

GagCheckCollCards(A,B,C,D,E);
Check if the player has all 49 Collector Cards when the gag is triggered, and react. In the vanilla game, this command is linked to the setup of the Level 3 Bonus Movie and by default no gags use this. This command may rely on hardcoded or obscure features to properly function.

A - NPC name for conversations.
B - Player character name for conversations.
C - Conversation name for triggering the gag more than once, if without all 49 Collector Cards.
D - Conversation name for triggering the gag the first time.
E - Conversation name for triggering the gag with all 49 Collector Cards.

GagCheckMovie(A,B,C,D);
Check if the player has the Bonus Movie unlocked when the gag is triggered, and react. In the vanilla game, this command is linked to the setup of the Level 3 Bonus Movie and by default no gags use this. This command may rely on hardcoded or obscure features to properly function.

A - NPC name for conversation.
B - Player character name for conversations.
C - Movie file to play if Bonus Movie unlocked. Path rooted in “/movies”.
D - Conversation name for triggering the gag without Bonus Movie unlocked.

GagEnd();
Signals to the MFK loader that definition of this Gag has ended.

Method 2: Interior-only gag (one command per-gag, one other unknown command)

// Each gag gets one of the first command and is bound to an interior space. The second command's effect is unknown to me but I believe level-oriented.
AddGagBinding(A,B,C,D,E);
ClearGagBindings();

AddGagBinding(A,B,C,D,E);
Adds a gag to an interior that will be loaded/triggered as soon as the player is within the interior after entry. Multiple gags added to the same interior through the command cannot spawn at once, only one will be randomly selected to spawn on each entry.

A - Interior’s internal name.
B - Gag P3D file. Path rooted in “/art/nis/gags”.
C - “single” (animation plays once) OR “reset” (appears to be generally broken) OR “cycle” (loops animation indefinitely).
D - Weight value - adjust the gag’s chance of spawning. By default all gags have equal chance. Set to “0”, the gag cannot spawn.
E - Name of a daSoundResourceData to play from any loaded SPT file upon triggering the gag. By default no daSoundResourceData is set.

ClearGagBindings();
Effect unknown.