NarraLeaf

state

读取、写入并观察当前游玩进程的故事变量

app.game.state 触及作者在 Studio 中声明的故事变量——场景局部变量、存档变量和持久变量。把一次游玩进程读出来,和把它重写掉,是完全不同的两件事,所以它们是两项能力:

{
  "contributes": {
    "runtimeCapabilities": ["state.read", "state.write"]
  }
}

state.read 授予 getonChangestate.write 额外授予 set——并且隐含 state.read,所以你只声明 write 时,Studio 会替你补上读的那一半

方法

方法签名需要
get<T>(scope, key: string) => T | nullstate.read
onChange(listener: (change) => void) => RuntimePluginCleanupstate.read
set(scope, key: string, value: unknown) => voidstate.write

getset同步的——变量表就在内存里。没有 state.writeset 会从对象上彻底消失,所以如果你的插件在两种声明下都能运行,请写成 app.game.state.set?.(...)

作用域

作用域生命周期
"scene"当前场景。场景结束即消失
"saved"本次游玩进程。会写入存档槽位,并从中恢复
"persistent"玩家本人,跨越每一次游玩进程。开新游戏也不会丢
const count = app.game.state?.get<number>("saved", "timesAsked") ?? 0;
app.game.state?.set?.("saved", "timesAsked", count + 1);

观察变化

type RuntimePluginStateChange = {
    scope: "scene" | "saved" | "persistent";
    key: string;
    previous: unknown;
    next: unknown;
};

const stop = app.game.state?.onChange(change => {
    if (change.scope === "persistent" && change.key === "trueEndingSeen" && change.next === true) {
        // 解锁点什么
    }
});

onChange 对来自故事、来自其他插件,以及来自你自己 set 的写入都会触发。它返回一个清理函数

持久变量是被精确观察的——变化与写入在同一帧抵达。场景变量和存档变量则是在故事可能写过它们的那些时点(一次动作变更、一句台词结束、场景挂载或卸载、存档被恢复,以及你自己的 set)与快照比对得出的,而且只在确实有人监听时才比对。实际用起来你能看到每一次变化;不能依赖的是场景或存档变化在一帧之内被报告的确切时刻

这不是插件 store

state作者的数据:他们在 Studio 中声明并接进故事里的变量。app.game.store你插件的数据,在自己的命名空间里,对故事不可见。用 state 参与作者的剧本;用 store 记住属于你自己的东西

本页目录