Overview

Actions are what defines what any given statement in a script should do. When Monogatari reads a part of the script (a statement), it looks for an action that matches the statement and runs it.

Creating a Custom Action

The following code displays a simple example of an action that does something when applied (advancing through the game) and something else when reverted (rolling back through the game):

class MyAction extends Monogatari.Action {

    // Unique identifier for this action
    static id = 'MyAction';

    // Match statements starting with 'myaction'
    static matchString([action]) {
        return action === 'myaction';
    }

    constructor([myaction, ...args]) {
        super();
        this.args = args;
    }

    apply() {
        // Do something when the action is executed
        console.log('Action applied with args:', this.args);
        return Promise.resolve();
    }

    didApply() {
        // Return whether to advance automatically
        return Promise.resolve({ advance: true });
    }

    revert() {
        // Undo the action when rolling back
        console.log('Action reverted');
        return Promise.resolve();
    }

    didRevert() {
        return Promise.resolve({ advance: true, step: true });
    }
}

This action will match statements like:

'myaction'
'myaction something'
'myaction one two three'

Registering an Action

Once you have your action class, register it with Monogatari:

monogatari.registerAction(MyAction);

Static Properties

Property Type Description
id string Unique identifier for the action (required)
_experimental boolean Marks the action as experimental (default: false)
_configuration object Action-specific configuration storage
loadingOrder number Order for loading actions (default: 0). Higher values load first.
engine Monogatari Reference to the Monogatari engine (set automatically)

Instance Properties

Property Type Description
_statement string|object The original statement that matched this action
_cycle string Current cycle: 'Application' or 'Revert'
_extras object Additional context passed to the action
engine Monogatari Reference to the Monogatari engine

Matching Methods

Actions must implement at least one matching method to identify which statements they handle.

matchString

For string-based statements (most common):

static matchString([keyword, ...args]) {
    return keyword === 'myaction';
}

The statement is passed as an array of words split by spaces.

matchObject

For object-based statements (JSON):

static matchObject(statement) {
    return typeof statement.MyAction !== 'undefined';
}

Configuration

Actions can store and retrieve configuration:

// Set configuration
MyAction.configuration({
    defaultValue: 'something',
    options: { enabled: true }
});

// Get all configuration
const config = MyAction.configuration();

// Get specific property
const value = MyAction.configuration('defaultValue');

Complete Example

Here’s a more complete example of a custom action:

class NotifyAction extends Monogatari.Action {

    static id = 'Notify';

    static _configuration = {
        duration: 3000
    };

    // Setup runs once when the engine initializes
    static async setup() {
        // Initialize any state or history needed
        this.engine.history('notifications');
    }

    static matchString([action]) {
        return action === 'notify';
    }

    constructor([notify, ...message]) {
        super();
        this.message = message.join(' ');
    }

    async apply() {
        // Show notification
        const duration = NotifyAction.configuration('duration');
        
        // Create and show notification element
        const notification = document.createElement('div');
        notification.className = 'custom-notification';
        notification.textContent = this.message;
        document.body.appendChild(notification);
        
        // Auto-remove after duration
        setTimeout(() => notification.remove(), duration);
    }

    async didApply() {
        // Save to history for rollback support
        this.engine.history('notifications').push(this.message);
        return { advance: true };
    }

    async revert() {
        // Remove from history
        this.engine.history('notifications').pop();
    }

    async didRevert() {
        return { advance: true, step: true };
    }
}

// Register the action
monogatari.registerAction(NotifyAction);

Usage in script:

monogatari.script({
    'Start': [
        'notify Welcome to the game!',
        'notify This message will appear as a notification.',
        // ... rest of script
    ]
});
  • Life Cycle - Detailed explanation of action lifecycle methods
  • Components - Creating custom UI components