Project Mammut Wiki
Project Mammut is currently in open beta. The UI is being updated a lot during this time, and you may run into bugs. If you'd like to help develop the engine or suggest features, come find us on Bluesky or Discord.

Script Types

Written 31 Oct 2026 · Updated 13 Nov 2026 · Requires Mammut 0.9.17+

The script editor knows the type of everything your scene script can use. This page explains where those types come from, and how to type your own values in TypeScript scripts.

this.dom

this.dom holds the scene's root (this.dom.root) and one entry for each node that has Referenceable ticked, named by the node's id. Scene, animator, particles, 3D scene and Spine nodes always get an entry.

Each entry is typed as the element the node becomes in the game:

Node Type
Image HTMLImageElement (a HTMLDivElement when it's nine-sliced, tiled or has children)
Button HTMLButtonElement
Video HTMLVideoElement
Slider, Text Input HTMLInputElement (a HTMLTextAreaElement for multi-line text input)
Checkbox HTMLLabelElement
Particles, 3D Scene HTMLCanvasElement
Everything else HTMLDivElement

Every element also has the engine's helpers:

  • hide(), show(), isHidden() and toggleVisibility()
  • disableEvents() and enableEvents()
  • getState(), and setState(name), which you can await until the state's animation finishes

Animator nodes add play(), pause(), resume(), stop() and restart(). Particle nodes add start(), stop(), pause(), resume() and burst(count).

In the editor's types this combination is called MammutElement. You can use that name yourself, for example MammutElement or MammutElement<HTMLImageElement>.

If a node is missing from this.dom., tick Referenceable on it.

this.vars

this.vars holds the variables from the scene's Scene Variables list in the inspector:

Variable type Type
String string
Number number
Bool boolean
File string (the file's path)

In TypeScript, using a name that isn't in the list is an error, so typos are caught. If you need a value that isn't a scene variable, you have two options:

  1. Add it to Scene Variables. It then has a type, a default value, and can be set per instance when the scene is used inside another scene.
  2. Make it a member of your script (see below).

Your own script members

Anything you declare at the top level of a scene script becomes part of this, with its type worked out from its starting value:

speakingCharacterId: "",
retries: 0,

onStart() {
  this.speakingCharacterId = "alice";
  this.retries++;
},

When the starting value doesn't show the full type, add one with as:

markers: [] as { el: MammutElement; char: string | null }[],
currentTimer: null as number | null,

onStart() {
  // this.dom is only ready from onStart, so fill in values that use it here
  this.markers = [
    { el: this.dom.character_marker_1, char: null },
    { el: this.dom.character_marker_2, char: null },
  ];
},

Your own methods are members too, so you can pass them straight to Register. Passing this as the last argument makes your scene this inside the handler and removes the handler when the scene exits, so there's nothing to store or unregister:

onStart() {
  Revealer.Register("SetCharacter", this.onSetCharacter, this);
},

onSetCharacter(event: RevealerEvent) {
  const key = event.args[0];
},

Don't use arrow functions as members (handler: () => this.doThing(),). At that level this isn't the scene, so they break when they run.

Names from your project

Some engine functions take names from your project, and the editor suggests them inside the quotes:

Where Suggests
SceneManager.SwitchScene(", GetScene, LoadScene, AttachScene Your scenes
AudioManager.PlayMusic(" Files in audio/music
AudioManager.PlaySFX(" Files in audio/sfx
AudioManager.PlayAmbient(" Files in audio/ambient
AudioManager.PlayVoice(" Files in audio/voice
Store.Get(", Store.Set(" Your project variables
Revealer.StartRevealChapterByID(" Your chapters

Any other string is still accepted, so names you build in code work too.

The Revealer

When the Narrative module is turned on, the Revealer is fully typed:

  • Revealer.Register(" suggests the built-in events (NodeStart, NodeEnd, OptionsReady, SetCharacter and more). Any [ActionName] tag name works as well.
  • Handlers receive a RevealerEvent with args, kwargs, and on some events options or char.
  • RevealNode() and the StartRevealChapter... functions give back a controller with promise, skip(), stop(), pause() and resume().

Adding your own types

Scene scripts can't declare types themselves, but Project Scripts can, and every scene can use them. A .d.ts file in your project is the tidiest place:

// assets/scripts/types.d.ts
interface CharacterMarker {
  el: MammutElement;
  char: string | null;
}
// In a scene script
markers: [] as CharacterMarker[],

A .d.ts file can also add properties to every scene element, by extending MammutElementHelpers:

// assets/scripts/types.d.ts
interface MammutElementHelpers {
  /** Which character this element shows. */
  charId?: string | null;
}

After that, this.dom.character_marker_1.charId = "alice"; is typed in every scene.