コードフレームワーク
コンテンツのリスト
キャラクターがプレイ中にコンテンツを得られるようにします。リストを宣言し、アクションで変更し、シートに表示します。
リストとは
リストは、小物のパックのように、キャラクターがプレイ中に得るコンテンツを保持します。コンテンツは別のフレームワークで、そのプリセットがエントリです。リストはレジャーにあり、コンストラクタのフィールドではありません。変更できるのはアクションだけです。
| オプション | 意味 |
|---|---|
| label | リストの名前です。 |
| of | コンテンツのフレームワークの ID です。 |
| max | リストが持てるエントリ数です。1 から 128 までです。 |
| card | エントリをカードとして描くフレームです。コンテンツのフレームワークのフレームにします。 |
| summary | エントリの行に表示するフィールドです。最大 4 つです。 |
| effects, caps, distinctBy | 修正値を変えるエントリと、その上限です。「プールと修正値」を参照してください。 |
各行にセルを加える行リストもありますが、まだ説明していません。
リストを宣言する
リストを、それを持つフレームワークに追加します。コンテンツのフレームワークは、エントリをプリセットとして持ちます。「Lantern を育てる」のチュートリアルでは、Trinket フレームワークを順に作ります。
"lists": {
"pack": {
"label": "Pack",
"of": "trinket",
"max": 2,
"card": "trinket-card",
"summary": ["weight"]
}
}- 45 行目 プリセットがエントリになるコンテンツのフレームワークです。
- 46 行目 リストが持てるエントリは、最大でこの数です。
- 47 行目 エントリを描くフレームです。
- 48 行目 エントリの行に表示するフィールドです。summary のフィールドには、閉じた範囲が必要です。選択肢、最小値と最大値、または真偽値です。
追加と削除
リストはアクションでしか変わりません。エントリを ContentRef の入力として受け取り、オファーを付けて list.add を呼び出します。
export function pack_trinket(self: ElementRef, trinket: ContentRef): void {
list.add(self, "pack", trinket, offer.where({ weight: { lte: 3 } }));
}- 1 行目 プレイヤーが選ぶエントリです。
- 2 行目 list.add は最初にオファーを確認します。このオファーが許可するのは、weight が 3 以下のエントリです。
エントリは list.remove で削除します。
export function unpack_trinket(self: ElementRef, trinket: ContentRef): void {
list.remove(self, "pack", trinket);
}- 2 行目 選ばれたエントリを削除します。リストにそのエントリがなければ拒否されます。
プレイヤーがボタンを使うと、Fabled はオファーが許可するエントリから 1 つ選ぶよう求めます。独自のルールで追加を止めるには、「ルールの書き方」のページにあるように list.count を使います。
オファー
offer.where は、エントリのフィールドに対する条件を取ります。条件はリテラルで書くので、オファーはキャラクターを読めません。キャラクターに応じて変えたいときは、list.add の前に if で確認します。
| 演算子 | 意味 | 例 |
|---|---|---|
| eq | フィールドが値と等しい。 | {"slot":{"eq":"Ring"}} |
| ne | フィールドが値と等しくない。 | {"slot":{"ne":"Ring"}} |
| gte | 数値が値以上。 | {"weight":{"gte":2}} |
| lte | 数値が値以下。 | {"weight":{"lte":3}} |
| in | フィールドが値のどれかと等しい。値は最大 64 個です。 | {"slot":{"in":["Ring","Cloak"]}} |
| has | フィールドがカンマ区切りのテキストで、値のどれかを含む。 | {"tags":{"has":["fire"]}} |
オファーのすべての条件が成り立つ必要があり、オファーが指定できるフィールドは最大 6 つです。エントリにないフィールドは、決して一致しません。
シートに表示する
リストを表示するフレームはバージョン 2.0 を使います。dataContract でリージョンを宣言してから、描きます。リージョンは、各エントリに最大 4 つのボタンを付けることもでき、各ボタンはそのエントリに対してアクションを実行します。
{
"kind": "region",
"id": "pack_list",
"listBinding": "{{element.lists.pack}}",
"emptyText": "Your pack is empty.",
"itemActions": [{ "actionRef": "unpack_trinket", "label": "Unpack" }]
}- 46 行目 リストが空の間に表示されます。
- 47 行目 各エントリのボタンです。アクションが受け取る入力は、エントリだけにします。
テストする
オファーとサイズが返すすべての拒否をテストします。次のステップは、追加、3 通りの拒否、削除、削除の拒否を行います。
{
"id": "pack-trinkets",
"framework": "keeper",
"parameters": {
"name": "Mira",
"max_hp": 10,
"calling": "Guard",
"lamp": "lamp"
},
"expectedValues": {
"name": "Mira",
"max_hp": 10,
"hp": 10,
"calling": "Guard",
"guard": 3
},
"expectedChildren": { "lamp": { "name": "Lantern", "oil": 5 } },
"actions": [
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "rope" },
"expectedWrites": [{ "op": "list.add", "key": "pack", "value": "rope" }]
},
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "rope" },
"expectedRefusal": "ALREADY_IN_LIST",
"expectedWrites": []
},
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "anvil" },
"expectedRefusal": "NOT_OFFERED",
"expectedWrites": []
},
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "candle" },
"expectedWrites": [
{ "op": "list.add", "key": "pack", "value": "candle" }
]
},
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "bell" },
"expectedRefusal": "LIST_FULL",
"expectedWrites": []
},
{
"action": "unpack_trinket",
"parameters": {},
"choose": { "trinket": "rope" },
"expectedWrites": [
{ "op": "list.remove", "key": "pack", "value": "rope" }
]
},
{
"action": "unpack_trinket",
"parameters": {},
"choose": { "trinket": "rope" },
"expectedRefusal": "NOT_IN_LIST",
"expectedWrites": []
}
],
"expectedLists": { "pack": ["candle"] }
}- 19-24 行目 受け入れ: rope が追加されます。
- 25-31 行目 拒否: パックにはすでに rope があります。
- 32-38 行目 拒否: オファーは anvil を許可しません。
- 47-53 行目 拒否: パックは 2 つのエントリを持っていて、これが最大です。
- 54-61 行目 削除: rope がパックから出ます。
- 62-68 行目 拒否: rope はもうパックにありません。
- 70 行目 パックに残るのは candle だけです。
シナリオは、すでにエントリを持つリストから始めることもできます。lists にプリセット ID で指定し、expectedLists で確認します。
{
"id": "seeded-pack",
"framework": "keeper",
"parameters": {
"name": "Mira",
"max_hp": 10,
"calling": "Guard",
"lamp": "lamp"
},
"expectedValues": {
"name": "Mira",
"max_hp": 10,
"hp": 10,
"calling": "Guard",
"guard": 3
},
"expectedChildren": { "lamp": { "name": "Lantern", "oil": 5 } },
"lists": { "pack": ["rope"] },
"expectedLists": { "pack": ["rope"] }
}- 18 行目 エレメントが最初に持つリストです。
- 19 行目 シナリオ後のリストです。
SAME_NAME と LIST_CAP は、効果を適用するリストの上限から出ます。「プールと修正値」のページで確認します。

