beasty-visual-novel / scripting / generated-accessors.md

Generated accessors: VNVars and VNChars

VNVars and VNChars are C# files the editor generates from your project’s variables and characters. They turn a key typo from a silent wrong answer into a compile error.

The problem they solve

The variable store is keyed by string. VN.GetBool("met_maya") on a key you actually spelled met_Maya does not throw and does not warn: it returns the fallback, false. The condition never fires, the branch never runs, and you look for the bug in the graph.

VN.SetInt("money", 100);      // compiles whatever you type
int m = VN.GetInt("mony");    // 0. No error. No warning.

With the generated accessors, the same mistake does not build:

VNVars.Money = 100;
int m = VNVars.Mony;          // CS0117: 'VNVars' does not contain a definition for 'Mony'

What they look like

VNVars is a flat static class, one property per variable, typed from the variable’s declared value type:

public static class VNVars
{
    /// <summary>Variable [money] (Fixed/Int).</summary>
    public static int Money { get => VN.GetInt("money"); set => VN.SetInt("money", value); }
}

VNChars is a static class per character, one property per character variable:

public static class VNChars
{
    public static class Maya
    {
        public static int Affection { get => VN.GetCharInt("maya", "affection");
                                      set => VN.SetCharInt("maya", "affection", value); }
    }
}

The exact members depend on your project. Keys become PascalCase properties; the character id becomes the nested class name.

Regenerating

Menu itemRegenerates
Tools > Beasty VN > Codegen > Regenerate VNVars AccessorsVNVars — one property per variable
Tools > Beasty VN > Codegen > Regenerate VNChars AccessorsVNChars — one nested class per character

Regenerate after you add, rename or delete a variable, a character variable or a character. Nothing else changes them, and nothing warns you that they are stale — a renamed variable leaves an accessor pointing at a key that no longer exists, which reads the fallback exactly like a typo would.

Both files carry an <auto-generated> header. Do not edit them by hand: the next regeneration overwrites them. Both live in the Beasty.VN.Runtime assembly and namespace, so your game scripts see them with no extra reference.

Using them alongside the string API

They are a convenience over the same store, not a separate system. VNVars.Money compiles down to VN.GetInt("money"). Both paths hit the same VariableStore, so you can mix them freely:

using Beasty.VN.Runtime;

public static class Shop
{
    public static bool Buy(int price)
    {
        if (VNVars.Money < price) return false;

        VNVars.Money -= price;                      // typed
        VN.SetBool("bought_something", true);       // string-keyed, no accessor needed
        VNChars.Maya.Affection += 1;                // typed, character variable
        return true;
    }
}

Everything the VN API says applies unchanged, including the important part: these read the ACTIVE SESSION. Outside a running story every getter returns its fallback and every setter warns and does nothing. To read game state from FreeRoam, the main menu or your own mode, use VNGameController.Instance.SharedVariables, or one of the gameplay APIs, which already do.

A key you never declared in the editor has no accessor. Write it with the string API, or declare it — declaring it is what makes it visible to the condition picker, the validator and the save.

ItemIds

The Items tab generates the same kind of file for inventory ids: an ItemIds class of string constants, meant to be passed to Inventory.Item(...). Same rules — regenerate when your ids change, do not edit by hand. See Gameplay APIs.

See also