Game Modeのストーリースクリプトの作成

ストーリースクリプトは、Game Modeのゲームの展開を方向付けます。パーティーがある場所に着いたときに再生されるシーン、条件が満たされたときにGame Masterへ依頼すること、プレイヤーがJournal(記録)で追う目標、Game Master自身が印を付けられる場面などです。ほかの人のために世界を作るなら、ストーリースクリプトを書いてください。ストーリーのある世界で遊ぶには、世界を作るを参照してください。

ストーリースクリプトはコードではなくデータです。中身は何も実行されません。Engineは対象の世界と照らし合わせてスクリプトを検査し、ターンごとに進行させ、合わないものはすべて拒否します。

始める前に、ストーリーを付ける世界と、その世界の場所IDと人物IDが必要です。ストーリーの保存にはゲームのAPIを使うため、JSONのリクエストを送ることに慣れている必要があります。ストーリーを試すを参照してください。

ストーリーの置き場所

ストーリーは1つの世界に属します。その世界の場所や人物を名指しするため、書かれた対象の世界(シード、概要、手動編集)と組み合わせたときにだけ意味を持ちます。

新しいゲームの設定では、ファイルやマップパックから読み込んだストーリーは、世界のシードと概要が変わらない限り保持されます。

構造

{
  "storyVersion": 1,
  "flags": [],
  "directions": [],
  "events": [],
  "cutscenes": [],
  "fights": [],
  "endings": [],
  "knowledge": []
}

動作する最小のストーリーは、フラグ1つとイベント1つでできています。次の例は、最初の返信でGame Masterにあることを伝えます。

{
  "storyVersion": 1,
  "flags": [{ "id": "met_guide", "kind": "bool", "initial": false }],
  "events": [
    {
      "id": "welcome",
      "when": { "on": "start" },
      "do": [{ "tell": "Open with a guide waiting at the gate." }, { "set": "met_guide", "value": true }]
    }
  ]
}

IDは小文字の英字、数字、_、-からなる1から40文字で、同じリストの中で一意である必要があります。1つのストーリーに入れられるのは、フラグ256個、指示64個、イベント256個、カットシーン64個、戦闘32個、エンディング16個、知識エントリー600個までです。ストーリー内のテキストには改行、角括弧、{{を含められません。タグに書き込む名前(グループ、背景)には二重引用符も含められません。こうして、ストーリーのどんな文言もGame Masterのタグになりすますことはできません。

フラグ

フラグは、ストーリーが保持する値です。"bool"(trueまたはfalse)か"number"のどちらかです。

{ "id": "trust", "kind": "number", "initial": 0, "gm": true, "note": "How far the town trusts the party" }
{
  "id": "favours",
  "kind": "number",
  "initial": 0,
  "quest": { "title": "Favours", "text": "Do the town three favours", "goal": 3 }
}

数値フラグにはminとmaxを指定できます。すべてのsetとaddは、Game Master自身のタグも含めてこの範囲内に収まります。そのため、いくつのイベントで加算しても、好感度を-10から10の間に保てます。initialもこの範囲内でなければなりません。

{ "id": "approval", "kind": "number", "initial": 0, "min": -10, "max": 10, "gm": true }

真偽値の目標は、フラグがtrueになると達成です。数値の目標は、goal(指定しない場合は1)に達すると達成で、goalを書いておくとJournalに進み具合が表示されます。"hidden": trueを指定した目標は、イベントで表示されるまでJournalに現れずに待機します。

クロック

数値フラグは、プレイヤーが埋まっていく様子を見守るクロックにもできます。2から12区画の円で、1ポイントごとに1区画が埋まります。ゲームのHUDとWorldタブに、タイトルと、すべて埋まると何が起きるかを表示します。

{
  "id": "reeve",
  "kind": "number",
  "initial": 0,
  "gm": true,
  "clock": { "title": "The Reeve's patience", "segments": 6, "full": "The Reeve sends his men." }
}

ほかの数値フラグと同じく、値を設定、加算し、条件で判定します。Game Masterには毎ターン、クロックが伝えられます。イベントでクロックが埋まったとき、またはGame Master自身のタグで埋まった次のターンに、何を起こすかが1回だけ伝えられます。"hidden": trueを持つクロックは、イベントがshowするまで見えません。

指示

指示は、Game Masterへの常時の指示で、条件が成り立っている間は有効です。

{ "id": "wary", "text": "The town is wary of strangers.", "if": [{ "flag": "trust", "is": "<", "value": 2 }] }

条件

{ "flag": "<id>", "is": "=" | "!=" | ">" | ">=" | "<" | "<=", "value": <value> }です。ifリストの条件はすべて成り立つ必要があります。真偽値のフラグは=か!=でしか比較できません。

{ "party": "<person id>", "is": "in" | "out" }は、その世界の人物が今パーティーと旅をしているかを判定します。ストーリーが加入させた仲間などが対象です。

{ "partySize": { "is": "=" | "!=" | ">" | ">=" | "<" | "<=", "value": <1 to 32> } }は、パーティーの人数を判定します。プレイヤーのキャラクターと同行中の仲間を数えますが、戦闘に参加しない仲間は除きます。Engineがパーティーの人数を把握している場合にだけ成り立ちます。

{ "any": [<condition>, <condition>, ...] }は、2から8個の条件のどれか1つが成り立てば成立します。2つのイベントを作る代わりに、1つのリストでどちらかの条件を表せます。

"if": [{ "any": [{ "flag": "won_granary", "is": "=", "value": true }, { "party": "p11-3", "is": "in" }] }]

知識

人物が自分自身、互い、舞台について知り、話す内容で、ストーリーの進行に応じて変わります。各エントリーは、次の条件を満たすターンに、話題になればその人物が話せる内容としてGame Masterへ伝えられます。

1ターンに伝えられるのは最大12個です。エントリーには優先順位が付きます。場面で名指しされた人物が最優先で、次に場面の言葉で取り込まれた人物なしのエントリー、最後に同行しているだけの仲間です。それぞれの中では人物ごとに順番に割り当てるので、話題の多い仲間がほかの仲間の枠をすべて使うことはありません。場面がどれほど混み合っていても、同行する仲間には12枠のうち2枠が必ず確保され、同じ方法で割り当てられます。

"knowledge": [
  { "id": "hob-self", "person": "p3-4", "text": "Hob was a miller's boy before the year stopped." },
  { "id": "hob-mill", "person": "p3-4", "if": [{ "flag": "act", "is": ">=", "value": 2 }],
    "text": "Since the second act, Hob is afraid of the mill." },
  { "id": "hob-bells", "person": "p3-4", "keys": ["bells"], "text": "Hob thinks the bells are a lie." },
  { "id": "wheel", "keys": ["mill", "millwheel"], "text": "The mill's wheel has not turned in a hundred autumns." }
]

スクリプトには最大600個のエントリーを入れられます。1ターンに伝えられるのはスクリプト順で最大12個なので、最も重要なものを先に置いてください。

イベント

イベントは起きる出来事です。トリガーが発動し、条件が成り立つと、アクションを実行します。

{
  "id": "gates",
  "when": { "on": "arrive", "place": "p11" },
  "if": [{ "flag": "banished", "is": "=", "value": false }],
  "do": [{ "cutscene": "gates" }, { "set": "arrived", "value": true }, { "show": "key" }]
}

イベントは1回だけ起きます。ただし"repeat": trueを指定した場合は繰り返します(start、turn、dayでは無視されます)。1ターンに起きるイベントは最大32個で、各イベントは1回までです。イベントはスクリプトに書かれた順に起きます。

トリガー(when.on)は次のとおりです。いずれもゲームが記録した内容から判定します。

トリガー発動するタイミング
startゲームの最初の返信で発動します。
turnセッションをまたいだゲーム全体で、Game Masterのturn番目の返信以降に発動します。
day世界の日付(Game Masterによる時間経過と移動で進みます)がday日目以降になると発動します。
arriveパーティーがplace(場所ID)またはその内側の場所にいる間に発動します。そこへ来た方法は、そこから開始した場合、オーバーワールドでの移動、町での訪問、Game Masterが名指しした場所のいずれかです。repeatを指定すると、別の場所から戻ってくるたびに再び発動します。
meet返信がperson(p11-3のような人物ID、手動で追加した人物ならp11-e1)をフルネームで名指しした時点で発動します。repeatを指定すると、その人物を名指しした返信ごとに再び発動します。名前の検出に使うのは、現在のセッションの返信だけです。
deed種類がdeedである、パーティーの行いを世界が記録した時点で発動します。placeを指定した場合は、その場所での行いに限ります。repeatを指定すると、行いを記録した返信ごとに再び発動します。
fight戦闘がoutcomeで終わったときに発動します。outcomeはvictory、defeat、fleeのいずれかです。fight(スクリプトの戦闘の1つ)を指定すると、その戦闘が指定の結果で終わったときにだけ発動します。対象は、Game Masterの直近の返信がストーリーのfightアクションかGame Master自身の発動で始めた戦闘です。
leaveパーティーがplace(場所ID)とその内側のすべての場所から出たときに発動します。直近の返信またはこのターンでの移動、訪問、Game Masterが名指しした場所、ストーリーのmoveが対象です。repeatを指定すると、出るたびに再び発動します。
broke戦闘でpropという名前の小道具が壊れたときに発動します。名前は大文字と小文字を区別せずに照合します。名指しできるのは、世界の戦場のいずれかに描かれた小道具だけです。
flags条件が成り立ったときに発動します。repeatを指定すると、条件が偽から真に変わるたびに再び発動します。
gmGame Masterが発動させたときだけ発動します(イベントに"gm": trueが必要です)。
restパーティーが休息した返信の後に発動します。Game Masterの返信で実行された[sheet: op="rest"]が対象で、restが指定するルールセットの休息(IDかラベル、例: long)に限るか、任意の休息を対象にできます。
travelパーティーがある場所から別の場所へ出発するターンに発動します。fromとtoが指定されている場合は、それぞれの内側から内側への移動に限ります。
idle何も起きない返信がturns回続いた後に発動します。ストーリーイベント、移動、戦闘のいずれもない場合です。
step移動がplaceのマスx、y(左上を0とする座標)を通ったときに発動します。placeは、集落の町(訪問時の経路で、扉から扉まで)か、手作業で作った場所のマップ(その上での移動)です。マスはパーティーが歩いて入れるものでなければなりません。町では広場からつながる地面で、ストーリーの展開で建物が建つ可能性のある空き区画は除きます。マップでは入口からつながる床です。生成されたマップには名指しできるマスがありません。repeatを指定すると、移動がそのマスを通るターンごとに再び発動します。

手動編集でstepイベントのマスがなくなる場合(そのマスに建物を置く、マップの床を壁にするなど)、その編集は保存時にイベントを名指しして拒否されます。

自身のシーンでその人物を名指しする繰り返しのmeetイベントや、自分が待っている行いを自ら行う繰り返しのdeedイベントは、毎ターン自分自身を発動させてしまうため、Engineはこれを拒否します。

アクション(do)は次のとおりです。

アクション内容
{ "set": "<flag>", "value": <value> }フラグを設定します。
{ "add": "<flag>", "amount": <number> }数値フラグに加算します。
{ "tell": "<text>" }このターンに1回、Game Masterに何かを依頼します。
{ "cutscene": "<id>" }カットシーンを再生します。
{ "show": "<flag>" }非表示のクエスト目標をJournalに表示します。
{ "world": { "deed": "<kind>", "group": "...", "with": "...", "place": "<place id>", "who": "..." } }世界に行いを記録します。Game Master自身による記録と同じように扱われます。
{ "give": { "item": "<catalog/entry or a name>", "count": 1, "who": "...", "summary": "..." } }アイテムを与えます。ゲームのルールセットのアイテムならIDで、それ以外は名前で指定し(summaryで内容を説明)、プレイヤーのバッグかwhoが指定するパーティーメンバーへ入れます。Game Master自身が与える場合と同じ処理なので、インベントリーのルールが適用されます。ルールセットにないIDは拒否され、その理由が返信に入ります。
{ "fight": "<fight id>" }スクリプトの戦闘の1つを始めます。Game Masterには戦闘へつなぐよう伝えられ、続く戦闘にはストーリーの敵が登場します。
{ "move": "<place id>" }移動した場合と同じように、パーティーを世界のある場所へ移します。これで発動するarriveイベントは同じターンに起きます。
{ "ending": "<ending id>" }スクリプトのエンディングの1つでゲームを終えます。シーンが再生され、Game Masterがエピローグで締めくくり、プレイヤーにはエンディングと、セッションを終える選択肢が表示されます。その後、ストーリーでは何も起きません。
{ "music": "<track id>" }または{ "music": null }その場所の音楽に代えてExperienceの曲を流します。別の指定が来るまで続き、nullでその場所の音楽へ戻します。曲はマップパックのmusicのいずれかでなければなりません。
{ "recruit": "<person id>" }Experienceの仲間の1人を、ゲームのルールセット用のシートとともにパーティーへ加入させます。Game Masterには加入を描写するよう伝えられます。
{ "dismiss": "<person id>" }仲間をパーティーから離脱させます。
{ "season": { "place": "<place id>", "to": "winter" } }日付にかかわらず、その場所と内側のすべての場所を指定の季節に固定します。placeを省略すると世界全体が対象です。"to": nullで、スクリプト自身のseasonsか日付による季節に戻します。
{ "sheet": { "condition": "<id>", "state": "on" }または{ "sheet": { "track": "<id>", "by": 1, "upTo": 3 } }パーティーの各メンバーにシートの状態を付けたり外したり("off")、各シートのトラックをupToまで動かしたりします。たとえばRime Edgeの、休息では癒えない寒さを、戦闘状態にcannot-heal-nonmagicalを持つ状態で表せます。Engine自身の発動では書き込む返信と一緒に適用し、Game Masterの発動では印を付けた次のターンに適用します。

どのアクションも独自のifを持てます。イベントがそのアクションへ進んだ時点で、先のアクションを実行した後の条件が成り立つ場合にだけ実行されます。そのため、1つのイベントで分岐できます。

"do": [
  { "add": "approval", "amount": 2 },
  { "tell": "Hob warms to the party.", "if": [{ "flag": "approval", "is": ">=", "value": 5 }] },
  { "tell": "Hob keeps his distance.", "if": [{ "flag": "approval", "is": "<", "value": 5 }] }
]

どのアクションが実行されたかは発動とともに記録されます。そのため、gmイベントのシーンと依頼内容は、Game Masterが印を付けた時点で実行されたとおりに、次のターンへ届きます。

仲間とは、パックの人物ファイルで仲間として指定された人物です(任意のエージェントパッケージのマップパックの人物を参照)。

同じターンに起こりうるrest、travel、idleイベントのうち、実際に起きるのは1つだけです。priorityが最も高いものが選ばれます(-100から100までの整数、省略時は0。同値ならスクリプトで先のもの)。仲間が焚き火で語る場面、道中で2人の仲間が口論する場面、静かな時間に仲間がプレイヤーを訪ねる場面などが重なることはありません。party条件を使うと、その仲間がパーティーと同行している間だけ場面が発生します。

環境の影響

ある場所にいることが、時間の経過とともにパーティーへ及ぼす影響です。たとえば、真昼の光が差す野原が、戦闘中の盤面の光ルールと同じように、戦闘外でも旅人を消耗させます。

"exposures": [
  { "id": "noonfield", "place": "e9", "label": "Noonfield's light", "hours": 1,
    "tracks": [{ "track": "exhaustion", "by": 1 }], "applies": ["sunstruck"],
    "if": [{ "flag": "darkness_carried", "is": "=", "value": false }],
    "tell": "The light presses on them; darkness would be a mercy." }
]

ゲームの時計に従います。ifが成り立ち、パーティーがplace(またはその内側)にいる最初のターンに始まり、後の各ターンには、そこで何回hours時間が経過したかを数えます。そのたびにEngineは各メンバーのtracksをbyずつ動かし、appliesの状態を付けます。Engine自身のシートコマンドは返信のコマンドと一緒に適用され、Game Masterにはtellで伝えます。場所を離れるかifが成り立たなくなると終了し、次回は最初から始まります。返信に1回だけ記録されます([story: exposure="<id>" ...])。

トラックには上限を指定できます。{ "track": "exhaustion", "by": 1, "upTo": 3 }は3を超えて増やさず、すでに超えている値も動かしません。環境の影響は全員に適用する代わりに、セーヴを求められます。戦闘盤面の光ルールのsaveと同じ形です。

"save": { "save": "con_save", "difficulty": 12, "against": { "conditions": ["noon_light"] } }

影響が発生するたびに、Engineは各メンバーのシートを使ってセーヴを振り、失敗したメンバーだけに、それぞれのシートコマンドでトラックと状態を適用します。againstはセーヴの対象を表します。その対象に限ったセーヴ修正は、戦闘中と同じく戦闘外でも適用されます。たとえば、オーバーレイの麦わら帽子に{ "to": "saves", "mode": "advantage", "against": { "conditions": ["noon_light"] } }があれば、着用者は有利になります。Game Masterには誰が成功し、誰が失敗したかを合計値とともに伝えます。

"sparedByShade": trueを指定すると、パーティーの誰かが灯して携える日陰が、ifが成り立たない場合と同じように影響を防ぎます。着用時または携帯時のlightに"shade": trueがあるアイテム(ショーケースのLantern of Dusk)が該当し、スイッチ付きならオンの間だけ有効です。灯すと影響が終了し、消すと最初から始まります。

Held Ground

ショーケースの谷のように、死を留める場所です。

"heldGround": [
  { "id": "valley", "place": "p0", "label": "The Held Autumn", "condition": "felled",
    "marks": [{ "track": "owing", "by": 1 }],
    "if": [{ "flag": "year_turned", "is": "=", "value": false }],
    "tell": "Nobody here has died in forty years." }
]

パーティーがplace(またはその内側。省略時は世界全体)にいてifが成り立つ間、そこで始まったルールセット戦闘はHeld Groundで戦います。体力が尽きた者は代わりに倒れ伏し、戦闘から外れます。容体は安定して瀕死にはならず、命を刈り取るものに倒された場合を除いて、後で再び立ち上がります。倒れ伏した者にはconditionが付き、それぞれのmarksのトラックが動きます(Owingの印)。最初に条件が成り立ったエントリーが適用されます。ストーリーはパーティーの出入りを記録し([story: held="<id>" ...]。離れたときは空のIDを記録します)、そのたびにGame Masterへtellで伝えます。有効な各ターンには、その意味をGame Masterへ再度伝えます。

この土地は死を解放することもできます。ショーケースでは年が巡るときです。releaseで、そのとき何を清算するかを指定します。

"release": { "felled": "die", "owing": { "track": "owing", "bonus": { "flag": "hymn_bonus" } } }

felledは、倒れ伏している者の行く末です。死亡する("die"、デフォルト)か、倒れてルールセット自身の規則で瀕死になり始める("down")かを指定します。owingはパーティーの各メンバーに、track(省略時はその土地が印を付ける最初のトラック)の印1つにつきルールセットの瀕死セーヴを1回振らせ、毎回bonusを加えます。ボーナスは数値か、解放時に読む数値フラグです。印が尽きるか成否が決まるまで続けます。印は消費され、3回の失敗で死亡します。そこでまだ続いているルールセット戦闘では、解放のきっかけとなる処理で解放されます。ifが読むストーリーの数値を消費するアイテムの使用、brokeイベントが応答する小道具の破壊、そしてそれらが発動させるフラグイベントが対象です。倒れ伏した者とOwingは、そのラウンドに戦闘自身の解放処理で清算されます。戦闘外では、それを記録するストーリーのターンに各メンバーのシートからOwingを振り、生死をGame Masterへ伝えます。そこで未完了のまま残された戦闘は、次の処理時に解放します。戦闘が清算したものを二重に振ることはありません。

季節

世界の季節は暦に従い、それぞれ90日です。ストーリーは日付にかかわらず、場所をある季節に固定できます。秋から進まない谷や、冬に閉ざされた丘などです。

"seasons": [{ "place": "p3", "season": "autumn" }, { "season": "summer" }]

それぞれ、その場所と内側のすべての場所を固定します。placeのないものは世界全体を固定します。最も近い固定された場所が季節を決めます。秋に固定された地域の中でも、冬に固定された村は冬です。seasonアクションで、プレイ中に固定する季節を変えたり、固定を解除したりできます。内側のすべてを対象とするover付きの固定は例外です。その範囲内のスクリプト自身の季節とほかの固定すべてより優先されます(このような固定が複数あれば最も外側を優先)。そのため、{ "season": { "to": "spring", "over": true } }で世界全体を一度に春へ変えられます。パーティーの現在地が固定されている場合、Game Masterにはその季節と固定されていることが伝えられ、天候もその季節に合わせて作られます。オーバーワールドの各セルは最も近い場所の季節で描かれ(タイルパックの<id>@<season>タイル)、町は自身の季節で描かれます。

世界の手描きの戦場にも季節を描けます。タイルの各行に対応するseasons行を用意し、タイルごとに文字か.を置き、seasonKeysで文字の意味を指定します({ "a": "autumn", "w": "winter" })。.のタイルは、戦闘が起きる場所の季節になります。戦闘のタイルはその季節で始まり、広がる霜の輪や通り過ぎる春の線のように、ラウンドのマップイベントで変えられます。

戦闘

ストーリーが設定する戦闘です。誰と戦うか、世界に描かれた盤面がある場合はどこで戦うかを決めます。

{
  "id": "granary",
  "name": "The Granary",
  "creatures": [
    { "creature": "creatures/scarecrow", "count": 3 },
    { "creature": "The Owed", "name": "The Owed" }
  ],
  "battlefield": "b2",
  "note": "The jars break when hit."
}

各クリーチャーはゲームのルールセットの図鑑のクリーチャーで、ID(catalog/entry)か名前で指定します。count体が登場し(複数なら番号付き)、nameがあれば戦闘中はその名前で呼ばれます。battlefieldは世界で手描きした盤面(b<n>)で、戦闘がどこで始まってもその盤面で戦います。なければ、ほかの戦闘と同じく開始した場所で戦います。noteは始まり方をGame Masterへ伝えます。ゲームのルールセットにないIDは拒否され、そのクリーチャーは戦闘から外され、拒否がログに記録されます。1体も残らなくても、ストーリーが設定した戦闘は指定の戦場で始まりますが、敵はGame Masterが選びます。

異なる人数のパーティーに合わせた戦闘も設定できます。パーティーは、プレイヤーのキャラクターと同行する仲間全員ですが、noncombatantの仲間は除きます。

"variants": [
  { "party": { "min": 3, "max": 4 }, "creatures": [{ "creature": "creatures/scarecrow", "count": 4 }] },
  { "party": 5, "creatures": [{ "creature": "creatures/scarecrow", "count": 5 }], "battlefield": "b3",
    "note": "The Owed wakes in the loft." }
]

partyがパーティーの人数に合うバリアントで戦います。そのバリアント自身のクリーチャーを使い、battlefieldとnoteがあればそれも使います(なければ戦闘の値を使います)。どのバリアントにも合わない人数のパーティーは、戦闘を元の記載どおりに戦います。同じ人数を2つのバリアントが対象にすることはできません。

戦闘やバリアントのクリーチャーエントリーは、その戦闘用にadjustできます。専用のクリーチャーを作らずに、ボスをパーティーに合わせて変えられます。"adjust": { "legendaryResistance": 2, "maxHp": 40 }は、そのLegendary Resistance(0なら削除)と体力を与えます。体力はブロックの値やダイスに代わる固定値です。Game Masterにはクリーチャーと一緒に伝えます。adjustのcallsは、クリーチャーのアクションが呼び出す相手を変えます。[{ "action": "shelves_lean", "creature": "creatures/wraith" }]のように、呼び出しアクションのIDか名前で指定します。levelsはパーティーがあるレベル以上に達したとき、これらの値を順に上書きします。例は"levels": [{ "from": 8, "calls": [{ "action": "shelves_lean", "creature": "creatures/wraith" }] }]です。パーティーのレベルは、所属するメンバーの最高レベルです。Experienceの仲間のシートがゲームのルールセット用に指定したレベルフィールドから読み取ります。指定がなければlevelsは読みません。partyは32人までの人数を指定できます。maxのない範囲({ "min": 7 }、Capability API 1.360)は、人数にかかわらずmin以上のすべてのパーティーを対象にします。Game Masterには、戦闘開始時と振り返りの後に、その戦闘が何人用かが伝えられます。

エンディング

{ "id": "kept", "title": "The Year Kept", "cutscene": "bells", "epilogue": "The valley stays held." }

cutsceneはスクリプトのシーンの1つで、エンディングが始まると再生されます。epilogueはGame Masterがゲームを締めくくる内容で、エンディングが表示されたときにプレイヤーも読みます。

カットシーン

カットシーンは、書かれたとおりにプレイヤーへ表示するか、Game Masterに語らせるかのどちらかです。

{
  "id": "gates",
  "kind": "pages",
  "background": "backgrounds:generated:town-gates",
  "pages": [
    { "text": "The gates creak open." },
    { "speaker": "p11-3", "expression": "happy", "text": "Welcome, travellers." },
    { "speaker": "player", "text": "We come in peace." }
  ]
}

pagesカットシーンは、Game Masterの返信の前にナレーションの中で1ページずつ再生されます。話者のないページはナレーションで、話者のあるページはその人物のせりふです。話者は世界での名前で表示され(playerならプレイヤーの名前)、Game Master自身の表情リストにあるexpressionを付けられます。backgroundは、ゲームにある背景か、backgrounds:generated:<words>です。後者は、画像生成がオンのときに背景を作らせます。Game Masterにはシーンが表示されたことが伝えられ、そこから続きを語ります。

ページにもifを指定できます。シーンの再生時に条件が成り立つページだけが表示されるため、キャンプのシーンで、同行している仲間にだけせりふを与えられます。

{ "speaker": "p11-3", "text": "Another night.", "if": [{ "party": "p11-3", "is": "in" }] }

すべてのページが条件で保留されたシーンは、何も表示しません。

{ "id": "dusk", "kind": "beats", "beats": ["Lamps are lit.", "A bell tolls."] }

beatsカットシーンは、そのターンにGame Masterが自分の言葉で、ビートごとに語ります。gmイベントのビートはイベントと一緒にGame Masterへ伝えられ、Game Masterはその場面に印を付ける返信の中でそれを語ります。そのため、gmイベントが使うbeatsのシーンは、Engineのイベントでも再生される場合であっても、最初からGame Masterに知られています。ビートは毎ターン伝えられるため、すべてのgmイベントのビートは合計16,000文字までに制限されます。

導入メッセージ

introは、ゲームの始まり方を設定します。GMの設定画面がどのゲームにも用意している選択肢と同じものです。

"intro": { "mode": "defined", "text": "The leaves have not fallen in Hollowmere for nine years.", "locked": true }

"defined"は、ゲームの最初のメッセージをtextそのものにします。Game Masterはそのメッセージを書かず、再生成しても同じテキストになります。"guided"は、Game Masterが書く冒頭を方向付けるだけです。最初の返信のときだけ読むガイダンスとして渡されます。textは1から8000文字で、改行を含められます(ストーリーの中で改行を含められるのはこのテキストだけです)。ただし{{は含められず、guidedのテキストには角括弧も含められません。lockedを指定すると、プレイヤーにはGMの設定画面で導入が表示され、変更できません。指定しない場合、導入は設定画面の欄に入力されるだけで、プレイヤーは変更したり消したりできます。最初の返信がすでに書かれているゲームや、パーティーを引き継いでいるゲームには、導入はありません。Experienceも、ほかのGM設定値と並べて導入を設定でき(contributions.gameSurface.setup.defaults.intro)、そちらを先に読みます。

ストーリーの進み方

毎ターン1回、Game Masterが返信する前に、Engineはストーリーがここまでに行ったことと、このターンにもたらされるもの(移動、訪問、戦闘の終了)を読み取り、イベントを起こします。起きたことはその返信の冒頭に書き込まれます。各イベントとそれが設定した値を記録するタグと、書かれたとおりに表示されたシーンです。ストーリーは返信から読み直されるため、スワイプや再生成をすると、その返信が行ったことは取り消されます。また、ゲームの途中でストーリーを変更しても、すでに起きたことが書き換えられることはありません。ストーリーはゲームの次のセッションにも引き継がれます。

Game Masterのタグ

毎ターン、Game Masterにはストーリーの値(プレイヤーには非表示)と有効な指示が伝えられます。スクリプトの残りの部分については、スクリプトがGame Masterに任せたものだけが伝えられます。つまり、gmイベント(そのnoteと、一緒に語るbeatsを含む)とgmフラグ、そしてそれらのイベントのうち今は印を付けられないもの(達成済み、または条件で保留されているもの)です。Game Masterは返信の中で次のように印を付けます。

gmイベントの贈り物、戦闘、移動は、そのタグと一緒に返信へ入ります。エンディングのシーンとエピローグは、次の返信の冒頭に入ります。

Engineは各タグにその場で応答し(イベントは1ターンに1回まで)、それ以外のものは理由を示して拒否します。ストーリーのないゲームでは、ストーリーのタグはすべて拒否されます。Game Masterが発動させたものは、すぐに効果を持ちます(フラグや行い)。そのシーンと依頼内容は次の返信の冒頭に現れます。ただしbeatsは例外です(その場面と一緒に語るよう依頼されているためです)。Game Masterはすでにその場面自体を語っているので、gmイベントのpagesは、その場面の後に続く内容として書いてください。

ストーリーを試す

  1. ストーリーの対象となる世界でゲームを始めます。
  2. PUT /api/game/:chatId/storyで、{ "story": { ... } }という本文を付けてストーリーを送ります。合わないストーリーは、すべての理由とともに拒否されます。
  3. 1ターン遊びます。ゲームのWorldタブにはストーリーが表示した目標とクロックが一覧で表示され、Game Masterのプロンプトには毎ターン、ストーリーの値と指示が含まれます。

保存したストーリーを読み取るには同じアドレスにGETを、削除するにはDELETEを使います。

Capability APIのバージョン別の機能

ストーリーの各機能には、最低限必要なCapability APIのバージョンがあります。