# Advanced label features (/start/labels-advanced)





This section covers advanced <DynamicLink href="/start/labels">label</DynamicLink> features. These are not required to create a basic game, but can help you build more complex and interactive experiences.

<Accordions>
  <Accordion title="onloadinglabel" id="onloadinglabel">
    `onLoadingLabel` is a function executed in `onStepStart` if the `step` index is 0, and also when the user loads a save file.

    When a save file is loaded, all `onLoadingLabel` functions of the `narration.openedLabels` (the current `label` and all `labels` in the stack) are executed.

    This is useful, for example, to ensure all images used in the `label` are cached before the `label` starts.

    You can set this function by passing it to the `onLoadingLabel` property in the `label` options. This function has the following parameters:

    * `stepIndex`: The index of the `step` being executed
    * `label`: The `label` being executed

    ```ts title="content/labels/start.label.ts"
    const startLabel = newLabel(
        "start",
        [
            async () => {
                await showImage("image1", "path/to/image1.png");
                await showImage("image2", "path/to/image2.png");
            },
        ],
        {
            onLoadingLabel: async (stepIndex, label) => {
                // [!code focus]
                await Assets.load("path/to/image1.png"); // [!code focus]
                await Assets.load("path/to/image2.png"); // [!code focus]
            }, // [!code focus]
        },
    );
    ```

    You can also use `Game.onLoadingLabel` to intercept the loading of all `labels` globally.

    ```ts
    import { Game } from "@drincs/pixi-vn";

    Game.onLoadingLabel((_stepId, label) => {
        // [!code focus]
        Assets.backgroundLoadBundle(label.id); // [!code focus]
    }); // [!code focus]
    ```
  </Accordion>

  <Accordion title="onstepstart" id="onstepstart">
    `onStepStart` is a function executed before each `step` of a `label`. Set it via the `onStepStart` property in the `label` options. This function has the following parameters:

    * `stepIndex`: The index of the `step` being executed
    * `label`: The `label` containing the `step`

    ```ts title="content/labels/start.label.ts"
    const startLabel = newLabel(
        "start",
        [
            () => {
                narration.dialogue = "Step 1";
            },
            () => {
                narration.dialogue = "Step 2";
            },
        ],
        {
            onStepStart: (stepIndex, label) => {
                // [!code focus]
                console.log(`Step ${stepIndex} started`); // [!code focus]
            }, // [!code focus]
        },
    );
    ```

    You can also use `Game.onStepStart` to intercept the start of any `step` in any `label`.

    ```ts
    import { Game } from "@drincs/pixi-vn";

    Game.onStepStart((stepIndex, label) => {
        // [!code focus]
        console.log(`Step ${stepIndex} started`); // [!code focus]
    }); // [!code focus]
    ```
  </Accordion>

  <Accordion title="onstepend" id="onstepend">
    `onStepEnd` is a function executed after each `step` of a `label`. Set it via the `onStepEnd` property in the `label` options. This function has the following parameters:

    * `stepIndex`: The index of the `step` that ended
    * `label`: The `label` containing the `step`

    ```ts title="content/labels/start.label.ts"
    const startLabel = newLabel(
        "start",
        [
            () => {
                narration.dialogue = "Step 1";
            },
            () => {
                narration.dialogue = "Step 2";
            },
        ],
        {
            onStepEnd: (stepIndex, label) => {
                // [!code focus]
                console.log(`Step ${stepIndex} ended`); // [!code focus]
            }, // [!code focus]
        },
    );
    ```

    You can also use `Game.onStepEnd` to intercept the end of any `step` in any `label`.

    ```ts
    import { Game } from "@drincs/pixi-vn";

    Game.onStepEnd((stepIndex, label) => {
        // [!code focus]
        console.log(`Step ${stepIndex} ended`); // [!code focus]
    }); // [!code focus]
    ```
  </Accordion>

  <Accordion title="dynamic_step_list" id="dynamic-step-list">
    When creating a new `label`, you can pass a function that returns the `steps` for that `label`. This allows you to change the `step` list dynamically based on a condition.

    ```ts title="content/labels/start.label.ts"
    import { storage, narration, newLabel } from "@drincs/pixi-vn";

    export const startLabel = newLabel("start", () => {
        let condition = storage.getFlag("condition");
        if (condition) {
            return [
                () => {
                    narration.dialogue = "Step 2";
                },
                () => {
                    narration.dialogue = "Restart";
                },
            ];
        } else {
            return [
                () => {
                    narration.dialogue = "Step 1";
                },
                async (props, { labelId }) => {
                    storage.setFlag("condition", true);
                    return await narration.jump(labelId, props);
                },
            ];
        }
    });
    ```

    <ReturningDifferentStepLists />
  </Accordion>
</Accordions>
