Фреймворки на коде
Раскладки и листы
Нарисуйте лист с помощью фрейма, привяжите его к своим полям и свяжите его кнопки с действиями.
Файл фрейма
Фрейм это JSON-файл в layouts/. Фреймворк указывает его в frames. Это лист Keeper.
"dataContract": {
"requiredBindings": [
{ "binding": "element.attributes.name", "expectedType": "string" },
{ "binding": "element.attributes.hp", "expectedType": "number" },
{ "binding": "element.attributes.max_hp", "expectedType": "number" }
],
"optionalBindings": [],
"actions": [
{ "name": "hurt", "functionRef": "hurt" },
{ "name": "heal", "functionRef": "heal" }
],
"regions": []
},- Строки 11-15 requiredBindings перечисляет каждое поле, которое использует текст, с его типом.
- Строки 17-20 Псевдонимы действий: имя, которое используют кнопки, и идентификатор действия, которое оно вызывает.
layouts/keeper.json
{
"version": "1.0",
"metadata": {
"name": "Keeper sheet",
"bindingMode": "bound",
"frameworkRef": "keeper",
"context": "BLADE",
"template": "standard-blade"
},
"dataContract": {
"requiredBindings": [
{ "binding": "element.attributes.name", "expectedType": "string" },
{ "binding": "element.attributes.hp", "expectedType": "number" },
{ "binding": "element.attributes.max_hp", "expectedType": "number" }
],
"optionalBindings": [],
"actions": [
{ "name": "hurt", "functionRef": "hurt" },
{ "name": "heal", "functionRef": "heal" }
],
"regions": []
},
"layout": {
"kind": "container",
"children": [
{ "kind": "text", "text": "{{element.attributes.name}}" },
{
"kind": "text",
"text": "HP: {{element.attributes.hp}} / {{element.attributes.max_hp}}"
},
{ "kind": "button", "label": "Take damage", "actionRef": "hurt" },
{ "kind": "button", "label": "Heal", "actionRef": "heal" }
]
}
}| Часть | Что содержит |
|---|---|
| version | Версия формата фрейма. Используйте 1.0 или 2.0 для фрейма, который рисует список. |
| metadata | Название, bindingMode со значением bound и frameworkRef, то есть идентификатор фреймворка, которому принадлежит фрейм. Поля context и template оставьте как в примере. |
| dataContract | Поля, которые читает фрейм, и действия, которые могут вызывать его кнопки. |
| layout | Дерево узлов. В примере используются узлы container, text и button. |
Контейнер принимает настройки раскладки в объекте layout рядом с kind. Текстовый узел принимает настройки стиля, например fontSize и fontWeight. Во фрейме нет кода, обработчиков событий и сырого HTML.
"kind": "container",
"layout": { "direction": "column", "gap": 12, "padding": 16 },
"children": [- Строка 25 Вид узла.
- Строка 26 Настройки раскладки: direction, gap и padding.
- Строка 27 Узлы внутри контейнера.
Привязки
Текст показывает хранимое значение через {{element.attributes.field}}. Перечислите каждое используемое поле в requiredBindings с его типом. Привязка к несуществующему полю отклоняется.
{
"kind": "text",
"text": "HP: {{element.attributes.hp}} / {{element.attributes.mana}}"
}FRAME_BINDING_UNKNOWN: element.attributes.manaКнопки и действия
В dataContract перечислены псевдонимы действий. У каждого псевдонима есть имя и functionRef, то есть идентификатор действия того же фреймворка. Кнопка называет псевдоним в actionRef.
"layout": {
"kind": "container",
"children": [
{ "kind": "text", "text": "{{element.attributes.name}}" },
{
"kind": "text",
"text": "HP: {{element.attributes.hp}} / {{element.attributes.max_hp}}"
},
{ "kind": "button", "label": "Take damage", "actionRef": "hurt" },
{ "kind": "button", "label": "Heal", "actionRef": "heal" }
]
}- Строки 26-30 Узлы Text показывают поля в двойных фигурных скобках.
- Строки 31-32 Кнопки называют в actionRef псевдоним из dataContract.actions.
{ "kind": "button", "label": "Take damage", "actionRef": "mend" }ACTION_MISSING: Action "mend" not found in framework's actionFunctions/ledgerFunctionsКубики в тексте
Запишите бросок кубиков внутри текста, например [[1d20+{{element.attributes.guard}}]]. Игрок бросает обычными кубиками Fabled. Привязанное число должно быть объявленным полем и входить в requiredBindings.
"text": "Defend: [[1d20+{{element.attributes.guard}}]]"- Строка 39 Аннотация кубиков стоит в двойных квадратных скобках. Поле должно быть в requiredBindings.
Как бросок попадает в действие
Аннотация кубиков показывает значок кубиков. Когда игрок нажимает на него, Fabled бросает кубики и показывает результат в журнале бросков стола и в чате. Бросок ничего не пишет в журнал и не заполняет входное значение действия. Вход с ключом roll, напротив, бросает сервер, как описано ниже.
Кнопка тоже не может хранить значение или бросок. Когда игрок нажимает кнопку действия с входными данными, Fabled открывает диалог и спрашивает каждое значение. Поэтому шаги такие: бросьте кубики, прочитайте число, нажмите кнопку действия и введите число.
Напишите эти шаги на листе, чтобы игроки их знали. Правило должно проверять число, потому что диалог его не ограничивает.
Чтобы Fabled бросал за игрока, дайте входу действия ключ roll, как показано на странице схем Framework. Тогда диалог показывает кнопку «Бросить» вместо поля. Сервер бросает кубики, а диалог вписывает сумму в поле, которое игрок не может изменить. Игрок может бросить снова, и новая сумма заменит прежнюю.
Бросок тратится один раз. Когда действие выполняется, оно берёт бросок, сохранённый сервером, поэтому число нельзя ни ввести вручную, ни использовать дважды. Новый бросок аннулирует прежние неиспользованные броски этого входа. Бросок привязан к кампании, в которой он сделан, и истекает через 15 минут. После этого игрок бросает снова.
Бросок попадает в журнал стола для определённой аудитории. Если действие не называет получателей, он идёт аудитории бросков игрока, то есть по тому же параметру, что и его другие броски кубиков. «Все» означает публичный бросок, «только он» означает шёпот самому себе, а «он и ГМы» означает шёпот самому себе и ГМам.
Действие может опубликовать строку с результатом в журнале стола с помощью шаблона log. Раздел «Строка журнала действия» на странице «Схемы фреймворков» показывает, как. Бросок на листе публикует только свой собственный бросок костей. Строки журнала внедряются постепенно и пока могут быть доступны не в каждой игре.
Один фрейм для каждого фреймворка
У каждого фреймворка свои фреймы. У дочернего Lamp своя карточка, привязанная к полям Lamp.

