ルールセットのレイヤー、翻訳、移行
このページでは、プレイヤーがあるゲームでオンにするバリエーションを用意する方法、ルールセットのテキストを翻訳する方法、シートが変わったときに保存済みの値を新しいIDへ移す方法を説明します。ルールセットの作者向けのページです。始める前に、Game Modeのルールセットを作成するを読んでください。
レイヤー: ルールセット自身のバリエーション
レイヤーはLow magic、Hard winter、より過酷な難易度など、ゲーム作成時にプレイヤーがオンにする名前付きのルールセット変種です。ルールセットファイル内の任意のlayers配列に置くため、一緒に移動し、使用したゲームから失われることはありません。ウィザードではルールセットの下にトグルとして表示し、ルールセット自身と同じく、そのゲームの存続中は選択を固定します。
"layers": [
{
"id": "hard_winter",
"label": "Hard winter",
"summary": "Cold, hunger and short days. Everything is harder.",
"conflicts": ["mud_season"],
"gm": {
"guidance": "Hard winter is on. Let a failed check cost warmth, food or daylight as well as progress.",
"worldGuidance": "Hard winter is on. Build a world of closed roads, thin stores and rationed settlements."
},
"fields": [{ "id": "calling", "removeValues": ["Sailor"], "default": "Hauler" }],
"difficultyLadder": [{ "label": "Easy", "dc": 7 }],
"catalogs": [{ "id": "knacks", "hide": { "filter": "grit", "above": 0 } }]
},
{
"id": "mud_season",
"label": "Mud season",
"summary": "Thaw, flooded roads and slow going."
}
]レイヤーにできること。 リストは固定されており、各効果は何かを絞り込むか、文章を追加します。
gm.guidanceはgm.checkGuidanceへ、作者自身の文章と先行するレイヤーの後に追加します。gm.worldGuidanceも同様にgm.worldGuidanceへ追加します。fieldsはenumフィールドから値を除きます。removeValuesはフィールドがすでに持つ値を指定し、少なくとも1つを残す必要があります。フィールドのdefaultも除く場合、レイヤーは残る値を代わりのdefaultに指定します。difficultyLadderは独自の解決方式と同じ形で難易度表を置き換えます。dice-sumなら{label, dc}、dice-poolなら{label, successes, target?}です。元の表とまったく同じ検証を受けます。複数の有効なレイヤーが宣言した場合は、最後のものが優先されます。catalogsはシートエディターの選択画面から項目を隠します。各ルールはカタログに宣言したfiltersの1つと、ちょうど1つの比較を指定します。numberフィルターならaboveかbelow、textやtagsならequalsかnotInです。そのフィルターをまったく設定していない項目は隠しません。currenciesは硬貨を除きます。removeUnitsは個々の硬貨を、removeFamiliesは系統全体を指定します。系統の最小硬貨は系統ごとにしか除けないため、残る系統はすべて支払いとお釣りが可能です。レイヤーの有効中、除かれた硬貨は誰も得たり、支払いに使ったり、選んだり、落としたりせず、財布の行にも表示しません。その硬貨で示す価格は、残る硬貨のうちちょうど払える最大のもので、同じ価値として示します。GravewatchのThe long nightはcrownを除くため、3 crownsのWatch pistolは15 shillingsです。系統全体がなくなったアイテムには価格がありません。itemsは、ものが売られる場所と出る戦利品を変えますが、存在するものは変えません。market.removeSellersは市場から売り手を除きます(常に少なくとも1人は残ります。売り手のいない市場では誰でもすべてを売れるため、2つのレイヤーの組み合わせであっても、売り手がいなくなる除外は行いません)。market.unsoldは、市場自身と同じ形式のフィルターで、すべての売り手から商品を除きます(市場のunsoldに追加します)。lootTablesは、すでにある戦利品表をIDで指定し、同じ形の表に置き換えるため、それを指定するすべてのクリーチャー、脅威の段階、売り手のstockでは、置き換えた表でダイスを振ります。複数の有効なレイヤーが同じ表を置き換える場合、最後のものが優先されます。売り物から除かれたアイテムも引き続きアイテムです。持ち運び、使用、戦利品としての発見、Game Masterからの配布ができ、売り手のstockの表でも引き続き出ることがあります。
"items": {
"market": { "removeSellers": ["magic_dealer", "scribe"], "unsold": [{ "tag": "magical" }] },
"lootTables": [{ "id": "treasure_low", "label": "Pocket treasure", "entries": [{ "coins": "sp", "weight": 1, "count": "4d6" }] }]
}レイヤーにできないこと。 列挙値、フィールド、スキル、プール、休息、売り手、戦利品表の追加、解決方式の変更、ライブ状態や戦闘数値の変更、モデル呼び出しの追加はできません。レイヤーが_追加した_値は、シートを読むほかのすべての処理には未知となるため、値は除く方向だけです。このリストを超える変更は、ルールセット自身の変更か、別のルールセットになります。
競合。 conflictsは同時に有効にできないレイヤーを指定します。組の片方だけに書けば十分です。ウィザードは相手のトグルを無効にし、保存済みの選択になぜか両方がある場合は、後で宣言された方を削除します。そのため、同じ2つの選択からは常に同じルールが得られます。
除外された値をすでに持つシートは、その値を保ちます。 キャラクターを書き換えるものはありません。エディターはその値を選択肢として出さなくなり、すでに持つキャラクターにはそのまま表示します。新しいゲームでレイヤーをオフにすれば、再び選べます。隠したカタログ項目も同じです。選択画面からは消えますが、プレイヤーがすでに選んだ行はシートに残ります。レイヤーが除いた硬貨をすでに持っている場合は、袋に残ります。
制限。 ルールセットごとに12レイヤー、各レイヤーのガイダンスは2つの文字列を合わせて4000文字です。layersまたは基本のgm.worldGuidanceを宣言するパッケージ化されたルールセットにはCapability API 1.25が、硬貨を除くレイヤーを持つものには1.64が、itemsを変更するレイヤーを持つものには1.813が必要です。インポートするルールセットは読み取るEngineが検証するため、この宣言は不要です。
他者が書くレイヤー(自分が書いていないルールセット向けのLow Magicレイヤーを独立したファイルで配布するもの)は、今後の追加事項です。現在は、所属するルールセットの中で配布します。
翻訳
翻訳(Capability API 1.811)。ルールセットの表示文字列を別の言語に訳したものは、言語ごとに用意し、Engine自身の言語パックと同じく、その言語コードで名前を付けます(ru、pt-BR、zh-Hans)。公式エージェントカタログでは、それぞれがルールセットのファイルと並ぶ言語パックです(後述)。共有するルールセットパッケージファイルでは、代わりに内部に含めることもできます。ruleset.jsonと並べて言語ごとにlocales/<language>.jsonを置き、ほかのファイルと同じようにマニフェストに列挙します。どちらの場合も、それぞれがrulesetセクションを持つパッケージのローカライズカタログです。各キーはルールセットまたはそのカタログの表示文字列を英語のまま一字一句変えずに記したもので、値はその文字列をファイルの言語に訳したものです。
{
"_meta": { "locale": "ru", "direction": "ltr" },
"package": { "name": "5e (SRD 5.1)" },
"ruleset": { "Prone": "Лежащий", "Fire Bolt": "Огненный снаряд", "Goblin": "Гоблин" }
}_meta.localeはファイル名が示す言語でなければならず、ファイルには$schema、_meta、package、ruleset以外を含めず、値はすべてテキストにします。空のままの文字列は未翻訳で、英語で表示されます。rulesetセクションがないファイル(パッケージ自身の英語の紹介文であるlocales/en.json)は何も翻訳しません。翻訳は表示専用です。ルール、シートのコマンド、Game Masterに伝えられる内容はすべて、引き続き英語を読み取ります。戦闘画面(名前、状態、アクション、呪文、ログ、行動順)では、ルールセットの翻訳に文字列があればプレイヤーの言語で表示し、なければ英語で表示します。まずその言語自体のファイル、次にその基になる言語のファイル(pt-BRならpt)を参照します。「Goblin 2」は「Goblin」の翻訳にその番号を付けて表示します。翻訳を含むパッケージファイルにはCapability API 1.811が必要です。インポートすると、Engineに設定されている言語(またはその基になる言語)の翻訳だけを保持し、残りは破棄します。別の言語でルールセットを読むには、Engineの言語を切り替えてファイルを再度インポートしてください。保持されている翻訳が置き換わります。翻訳はバージョンに含まれないため、修正した翻訳を含む同じバージョンを再度インポートした場合も翻訳が置き換わり、翻訳のないファイルをインポートした場合は保持されている翻訳が残ります。
カタログのルールセットは、そのファイル内にlocales/<language>.jsonを含めません(含むものはダウンロード前に拒否されます)。その翻訳は言語パックです(Capability API 1.811)。言語ごとにJSONファイル<id>-<version>.<language>.jsonを用意し、<id>-<version>.ruleset.jsonと並べて公開します。内容はlocales/<language>.jsonとまったく同じです(_meta.localeはファイル名が示す言語で、rulesetセクションを持ちます)。カタログのエントリーは、artifactと並べてそれらを列挙します。
"locales": {
"ru": {
"url": "https://raw.githubusercontent.com/Pasta-Devs/Marinara-Agents/main/artifacts/ember-roads-1.0.0.ru.json",
"sha256": "<64 hex>",
"bytes": 812345,
"name": "Угольные дороги",
"description": "<the store card's description in Russian>"
}
}各パックは、成果物のURLと同じ形式のhttps URLで、バージョンと言語に応じた名前を付け、sha256とサイズ(8 MBまで)を持ちます。ルールセットが列挙できるパックは、40個までで、enは決して含めず(英語はルールセット自体です)、マニフェストにはCapability API 1.811を宣言します。nameとdescriptionはその言語でのストアカードの名前と説明なので、パックを取得しなくても、カードはEngineの言語で読めます。インストール時にはルールセットのファイルを取得し、続いてEngineに設定されている言語(またはその基になる言語)のパックだけを取得し、サイズ、チェックサム、言語を検証して、インストールしたバージョンとともに保持します。Engineの言語が変わると(およびその言語でページを開くたびに)、新しい言語のパックを列挙しているインストール済みの各カタログルールセットがそのパックを取得し、古い言語のパックは削除されます。パックを取得できない場合(オフライン、列挙されていない、カタログに列挙されたファイルと異なる場合)、ルールセットは英語のままになります。次のインストールまたは言語変更時に再試行します。アップデート時にはロールバック用に以前のバージョンを保持しますが、そのパックは保持しません。ロールバック後、次の言語変更時に、カタログが引き続きそのバージョンのパックを列挙していれば、再度取得します。
値を新しいIDへ移す: sheet.migrations
追加するだけなら何も要りません。新しい構成が値を別の場所へ移す場合(名前を変えたフィールド、クラスごとのレベルに分かれる1つのレベル、ダイスごとに分かれる1つのヒット・ダイスのプール)、その方法をsheet.migrations(Capability API 1.77)で示してください。そうすれば、古い構成で作ったすべてのキャラクターが、ライブラリー、ゲーム、古いセーブ、分岐、チェックポイント、インポートしたカードで、その数値を保ちます。
"migrations": [
{
"from": 3,
"steps": [
{ "rename": "field", "from": "xp", "to": "experience" },
{
"route": "level",
"by": "class",
"cases": [
{ "words": ["fighter"], "to": "level_fighter" },
{ "words": ["wizard"], "to": "level_wizard" }
],
"else": "level_other",
"default": 1
},
{
"routeLive": "pool",
"from": "hit_dice",
"cases": ["hit_dice_d6", "hit_dice_d8", "hit_dice_d10", "hit_dice_d12"],
"else": "hit_dice_d8"
}
]
}
]- 各項目は、保存されたシートをバージョン
fromからfrom + 1へ移し、そのバージョン以前に保存されたすべてのシートに対して順に実行されます。一度公開した項目は決して削除しないでください。ずっと前に保存されたシートには引き続き必要です。追加するだけのバージョンには何も要りません。 rename(ability、skill、save、field): 値を新しいIDにコピーします。スキルやセーヴはボーナスも一緒に移します。名前の変更は、前の項目の名前の変更を引き継いだり、後のrouteが送り先にするフィールドに供給したりできます。インポートは、その連鎖を終点までたどります。route: 一つのフィールドの値を、別のフィールドの文章が指定するフィールドへ送ります。大文字と小文字を区別せず、byの文章にケースの語が単語全体として現れ(単語をつなぐのは英字だけなので、「Fighter3」はfighterを指定します)、ちょうど一つのケースが一致すれば、そのケースが採用されます。一致がないか複数ある場合(「Fighter 3 / Wizard 2」は、尋ねずに一つの数値を分けられません)はelseへ送ります。defaultは、値を保存したことのないシートの代わりの値です。byは、シートが持つフィールドか、以前の構成で名前を変えて移したフィールドです。送り先は数値またはテキストのフィールドで、デフォルトがないか、デフォルトが0または空でなければなりません。値はそのうちの一つに入り、ほかはすべてデフォルトのままなので、それ以外のデフォルトは誰も与えていないレベルとして読まれてしまいます。後の名前の変更が移す送り先は、そこまでたどります。routeLive(ライブステートのpoolかtrack): 保存された値を、移行後のシートが示すcasesの一つ(最大値が正(0より大きい)のプール、シートが隠していないトラック)へ送り、なければelseへ送ります。値の送り先のトラックは、すべて負傷トラック(印を運びます)か、すべて普通のトラック(数値を運びます)です。setColumn(Capability API 1.794):{ "setColumn": { "list": "attacks", "where": { "name": ["Dagger", "Rapier"], "ability": ["str", "dex"] }, "column": "ability", "to": "finesse" } }は、whereの各列がそれぞれ列挙された値のいずれかを持つリストのすべての行について、指定した列の値を設定します(テキストは大文字と小文字の違いと前後の空白を無視して照合し、数値は完全一致で照合します)。武器の能力値の選択肢ができる前に作られた攻撃の行など、ルールセットが適切に扱えるようになる前に作られた行を修正するために使ってください。指定するリストとすべての列は、シート上に存在しなければなりません。- ほかのビルドのステップはすべてコピーします。古い値は元の場所に残るため、ルールセットの古いバージョンは引き続き以前と同じようにシートを読めます。ステップが送り先にすでにある値を上書きすることはありません。上書きするのは
setColumnだけです。 - インポートは、
sheet.version以上の項目、同じバージョンからの二つの項目、シートが持たないIDに書き込むステップ、二回列挙したケース、シートがまだ持つIDから読むrenameやrouteLiveを拒否します(移したIDは二度と使われないため、それらのステップは安全に再実行できます)。 - シートは読むたびに移行され、新しい構成は次の編集で保存されます。ライブステートには独自のバージョンがないため、
routeLiveは読むたびに実行されます。古いキーは捨てられ、その値は新しいキーがまだない間だけ移るため、その後消費したり休息で回復したりした値が上書きされることはありません。どこへ移ったかは、アップデート後の最初の書き込みで決まります。後で修正したシート(手で移したクラスのレベル)が再び移されることはありません。新しいバージョンが届いた時点で進行中の戦闘は、これまでどおり最後まで続きます。