IdaJS
    Preparing search index...

    Type Alias CoroutineFunction

    CoroutineFunction: (...args: any[]) => Generator<any, any, any>

    Type definition for a coroutine generator function (used to run Move scripts of the objects).

    Coroutines are modern replacement for the LBA move scripts. They are designed to control the sequence of object actions.

    Every coroutine runs its commands one by one until finished or stopped.

    The coroutines run as asynchronous, multiple step functions, and can be paused and resumed. Also the coroutines persist their execution state and restore automatically during save/load.

    Type Declaration

      • (...args: any[]): Generator<any, any, any>
      • Parameters

        • ...args: any[]

        Returns Generator<any, any, any>

    Coroutine Limitations:

    Coroutines functions have the following limitations in order to function correctly:

    • No outside dynamic state can be used: Coroutine cannot use or depend on any dynamically changing state outside of the coroutine (no closured variables), except variables passed through the arguments of the coroutine function.

      • That means that any loops and conditions within the coroutine cannot use any external variables or call other functions (unless those functions are fully immutable, or do side effects only through specially allowed coroutine mechanisms (see do... functions below)).
    • Deterministic execution flow: When running with the same arguments, the coroutine should always result in the exact same sequence of the yield commands. No outside state should ever change the order or flow of the yield actions within the coroutine.

    • Serializable arguments: Coroutine arguments must be serializable to JSON, in order to be saved / loaded correctly, so they need to be of simple types.

    • yield side effects only: Any action, that causes side-effect, should be called as yield <coroutineCommand>(...).

      • Currently supported coroutine commands are: doMove (low level track script command), doReduce, doAction, doGameStore, doSceneStore.
      • Exception of this rule: technically you can run something within the coroutine that doesn't start with yield (arbitrary code), but it must be a fully idempotent action, because it will re-run again when coroutine is loaded from a save game state, even if the last position in the coroutine is already after this line.
    • Supports infinite loops: Once entered infinite loop, there should be no way to exit it, except terminating the coroutine. If your loop has break statement, it's not a truly infinite loop.

      • In the case you use a truly infinite loop, call yield doReduce() as a first command in its scope. It will make sure the coroutine saved position doesn't grow infinitely.
      • It's not recommended to create complex coroutines with several or nested infinite loops. However, if this is the case, you have to pass different key to each doReduce, so they save the state separately: yield doReduce(1), yield doReduce("mainLoop"), and so on.

    // Simple coroutine with arguments
    function* myCoroutine(arg1, arg2) {
    yield doMove(ida.Move.TM_SAMPLE, arg1);
    yield doMove(ida.Move.TM_BACKGROUND, arg2);
    // ...
    }
    // Coroutine with infinite loop: going infinitely between 2 points
    function* infinitePatrol() {
    while (true) {
    yield doReduce(); // Used at start of truly infinite loops to reduce position counter growth
    yield doMove(ida.Move.TM_GOTO_POINT, 1);
    yield doMove(ida.Move.TM_GOTO_POINT, 2);
    }
    }