Przejdź do głównej treści

Frameworki kodowe

Schematy frameworków

Zadeklaruj dane wejściowe, akcje, wartości pochodne, ramki, treści i podrzędne frameworki dla jednego rodzaju elementu.

Plik frameworka

Każdy plik w schemas/ deklaruje jeden framework. Strony referencyjne rozbudowują postać Keeper z szybkiego startu. Ma teraz wybór Calling, wartość pochodną Guard, gotowy zestaw, sekcję i podrzędnego Lamp.

manifest/project.json
schemas/keeper.json
schemas/lamp.json
rules/keeper.ts
rules/lamp.ts
rules/hurt.ts
rules/heal.ts
rules/guard.ts
layouts/keeper.json
layouts/lamp.json
scenarios/new-keeper.json
scenarios/heal.json
scenarios/new-lamp.json

Pola podstawowe

PoleWymaganeZnaczenie
idTakUnikalne id frameworka. Używają go manifest i scenariusze.
nameTakWyświetlana nazwa.
elementTypeTakCo buduje: character dla postaci grywalnych, item dla przedmiotów, spell dla zaklęć. Można używać własnych typów.
constructorTakŚcieżka pliku reguł, który buduje nowy element.
inputsNieCo gracz wpisuje przy tworzeniu elementu. Każdy klucz odpowiada parametrowi konstruktora.
actionsNieRzeczy, które element może robić. Każda ma id, nazwę i plik reguł.
ledgerFunctionsNieWartości pochodne. Każda dotyczy zapisanego pola i ma plik reguł.
framesTakOd jednej do szesnastu ramek. Dokładnie jedna ma default ustawione na true.
sectionsNieGrupuje dane wejściowe w kroki kreatora tworzenia.
contentNieGotowe zestawy. Każdy ma id, nazwę i wartości danych wejściowych.
childFrameworksNieŁączy nazwę miejsca podrzędnego z innym frameworkiem tej samej gry.

W GRZE framework wejściowy w manifeście musi być postacią grywalną.

The entry framework must be a character constructor.

Dane wejściowe

Dana wejściowa dostosowuje jeden parametr konstruktora, a jej klucz musi odpowiadać nazwie parametru. Większość danych potrzebuje tylko etykiety. Pozostałe klucze zawężają to, co może wpisać gracz.

schemas/keeper.json
  "inputs": {
    "name": { "label": "Name" },
    "max_hp": {
      "label": "Maximum HP",
      "description": "How much damage a Keeper can take.",
      "defaultValue": 10,
      "min": 1,
      "max": 40
    },
    "calling": {
      "label": "Calling",
      "options": ["Guard", "Scout"],
      "defaultValue": "Guard"
    },
    "lamp": { "label": "Lamp", "defaultValue": "lamp", "hidden": true }
  },
  1. Wiersze 8-14 min i max ograniczają liczbę. Scenariusz lub preset poza granicami się nie powiedzie.
  2. Wiersze 15-19 options podaje stałą listę wyborów. Wartość domyślna musi być jedną z nich.
  3. Wiersz 20 Ukryte dane wejściowe przechowują wartość, której gracz nigdy nie widzi. Tutaj łączą podrzędny Lamp.
schemas/keeper.json
schemas/keeper.json
{
  "id": "keeper",
  "name": "Keeper",
  "elementType": "character",
  "constructor": "rules/keeper.ts",
  "inputs": {
    "name": { "label": "Name" },
    "max_hp": {
      "label": "Maximum HP",
      "description": "How much damage a Keeper can take.",
      "defaultValue": 10,
      "min": 1,
      "max": 40
    },
    "calling": {
      "label": "Calling",
      "options": ["Guard", "Scout"],
      "defaultValue": "Guard"
    },
    "lamp": { "label": "Lamp", "defaultValue": "lamp", "hidden": true }
  },
  "childFrameworks": { "lamp": "lamp" },
  "sections": [
    {
      "id": "basics",
      "title": "Basics",
      "inputs": ["name", "max_hp", "calling", "lamp"]
    }
  ],
  "actions": [
    { "id": "hurt", "name": "Take damage", "source": "rules/hurt.ts" },
    { "id": "heal", "name": "Heal", "source": "rules/heal.ts" }
  ],
  "ledgerFunctions": [
    {
      "id": "guard",
      "name": "Guard",
      "field": "guard",
      "source": "rules/guard.ts"
    }
  ],
  "frames": [
    { "id": "sheet", "source": "layouts/keeper.json", "default": true }
  ],
  "content": [
    {
      "id": "mira-scout",
      "name": "Mira the Scout",
      "parameters": {
        "name": "Mira",
        "max_hp": 8,
        "calling": "Scout",
        "lamp": "lamp"
      }
    }
  ]
}
KluczZnaczenie
labelTekst pokazywany graczowi.
descriptionTekst pomocy, do 1024 znaków.
defaultValueWartość używana, gdy gracz zostawi pole bez zmian.
optionsStała lista od 2 do 128 wyborów tekstowych, każdy do 128 znaków. Wartość domyślna musi być jednym z nich.
optionLabelsEtykiety opcji widoczne dla gracza. Zapisana wartość pozostaje opcją.
min, maxGranice liczby. min nie może przekraczać max.
minLength, maxLengthGranice długości tekstu.
requiredUstaw false, aby gracz mógł zostawić pole puste.
hiddenUkrywa dane wejściowe w kreatorze. Ukryte dane wejściowe wymagają defaultValue.
visibleWhenPokazuje dane wejściowe tylko wtedy, gdy spełniony jest warunek dotyczący innych danych.

Wartość domyślna spoza opcji zostanie odrzucona.

{
  "calling": {
    "label": "Calling",
    "options": ["Guard", "Scout"],
    "defaultValue": "Mage"
  }
}
Default for calling must be one of its options ("Guard", "Scout").

Scenariusze i zestawy też muszą mieścić się w granicach.

Parameter max_hp 99 is not between 1 and 40.

Ukryte dane wejściowe bez wartości domyślnej kończą się błędem:

Input name is hidden, so it must declare a defaultValue.

Akcje i funkcje ledgera

Każda akcja ma id, nazwę i plik źródłowy. Każda funkcja ledgera ma to samo, plus pole. Pole to zapisana wartość, którą funkcja wylicza, i musi być polem skalarnym zwracanym przez konstruktor. Funkcja ledgera czyta wartości i zwraca wartość pochodną. Nigdy nie zapisuje.

schemas/keeper.json
  "ledgerFunctions": [
    {
      "id": "guard",
      "name": "Guard",
      "field": "guard",
      "source": "rules/guard.ts"
    }
  ],
  1. Wiersze 36-39 id i name identyfikują funkcję, field to zapisana wartość, którą funkcja wylicza, a source to jej plik reguł.
rules/guard.ts
function base_guard(calling: string): number {
  return calling === "Guard" ? 3 : 1;
}

export function guard(currentValue: number, self: ElementRef): number {
  const calling: string = element.var(self, "calling") as string;
  return base_guard(calling);
}
  1. Wiersze 1-3 Funkcja pomocnicza. Nie ma export, a funkcja ledgera wywołuje ją po nazwie.
  2. Wiersz 5 Funkcja ledgera dostaje swoją bieżącą wartość i element.
  3. Wiersz 6 Odczytuj zapisane wartości przez element.var.
  4. Wiersz 7 Zwróć wyliczoną wartość.
Ledger function must target an existing scalar field.

Id muszą być unikalne w obrębie Frameworka. Akcje i funkcje ledgera dzielą jeden zestaw id.

Duplicate semantic identity or source path.

Dwie funkcje ledgera mogą dzielić jeden plik źródłowy. Akcja i funkcja ledgera nie mogą:

action source does not match its owner contract

Dane wejściowe akcji

Wejścia akcji to parametry jej funkcji. Sygnatura je deklaruje, a schemat może dodać wpis dla każdego z nich. Każde wejście to liczba, tekst lub wartość prawda/fałsz.

Gracz jest pytany o każde wejście w oknie dialogowym, gdy użyje przycisku. Okno nazywa wejście nazwą jego parametru, chyba że wpis nadaje mu etykietę. Wpis może też podać opis i wartość domyślną. Wejście liczbowe może mieć minimum i maksimum. Wejście tekstowe może mieć listę opcji lub opcje z tabeli. Okno pokazuje to wszystko, a serwer odrzuca wartość spoza granic lub opcji. Przycisk nie może przekazać wartości. Nazwij każdy parametr tak, żeby gracz mógł go przeczytać: roll, a nie r.

schemas/keeper.json
    {
      "id": "check_lore",
      "name": "Lore check",
      "source": "rules/check-lore.ts",
      "inputs": { "roll": { "label": "Roll", "min": 1, "max": 100 } }
    }
  1. Wiersz 24 Wpis wejścia rzutu. Okno pokazuje etykietę, a serwer wymusza minimum i maksimum.

Minimum i maksimum nie zatrzymają liczby z ułamkiem. Jeśli reguła potrzebuje liczby całkowitej, sprawdza to sama, a krok scenariusza to dowodzi. Krok scenariusza spoza granic jest odrzucany.

rules/check-lore.ts
export function check_lore(self: ElementRef, roll: number): void {
  if (math.floor(roll) === roll) {
    const lore: number = element.var(self, "lore") as number;
    ledger.set(self, "last_target", lore);
    ledger.set(self, "last_roll", roll);
  }
}
  1. Wiersz 1 Rzut to dane wejściowe, które wpisuje gracz.
  2. Wiersz 2 Zignoruj liczbę z ułamkiem. Granice wejścia już utrzymują ją między 1 a 100.
  3. Wiersze 4-5 Zapisz cel i rzut.

Dane wejściowe tekstowe mogą zamiast tego oferować listę wyborów z tabeli podręcznika. Strona Tabele podręcznika pokazuje, jak.

Wejście tekstowe może zamiast tego wybrać po nazwie jedno z zapisanych pól Frameworka, za pomocą listy fields. Strona Pisanie reguł pokazuje akcję, która z tego korzysta.

Dane wejściowe liczbowe mogą poprosić serwer o rzut. Dodaj klucz roll z jednym wyrażeniem kości, takim jak "roll": "1d100" lub "roll": "2d6+1". Okno pokazuje wtedy przycisk Rzuć zamiast pola, w którym gracz wpisuje liczbę. Serwer rzuca, a okno pokazuje sumę, której gracz nie może zmienić. Rzucić można tylko parametr liczbowy. Kompilator odrzuca roll razem z defaultValue oraz wyrażenie kości, którego serwer nie przyjmuje.

Rzucane dane wejściowe zużywają się raz: akcja bierze rzut, gdy się wykonuje, a nowy rzut unieważnia wcześniejsze niezużyte rzuty tych danych. Rzut jest powiązany ze swoją kampanią i wygasa po 15 minutach. Strona Układy i karty pokazuje, co widzi stół.

Wiersz dziennika akcji

Akcja może opublikować wiersz z wynikiem w dzienniku stołu. Dodaj szablon dziennika do wpisu akcji w schemacie, na przykład "log": "{name} takes {amount} damage, defense {defense}". Serwer wypełnia każdy symbol zastępczy {name} jako zwykły tekst po zapisaniu akcji. Przeglądarka nigdy nie wysyła tego wiersza.

Symbol zastępczy może wskazywać wejście akcji albo pole liczbowe, tekstowe lub prawda/fałsz tego samego Frameworka. Kompilator odrzuca ukryte wejście, pole zdrowia (hp, current_hp, hit_points, temp_hp, current_health, max_health, hitPoints oraz pola zdrowia i stanów bloku walki), nazwę, która nie istnieje, szablon dłuższy niż 200 znaków, więcej niż 16 symboli zastępczych, pojedynczy nawias klamrowy i znak sterujący. Gdy wejście i pole mają tę samą nazwę, wygrywa wejście. Wartości pochodzą z chwili po akcji, więc pole zapisane przez akcję pokazuje nową wartość. Pole obliczane nie jest przeliczane ponownie, więc pokazuje wartość sprzed akcji.

Gracz, który działa swoją postacią, widzi wiersz w tym samym gronie, co jego rzuty kośćmi: wszyscy, tylko on albo on i MG. We wszystkich innych przypadkach, także gdy MG działa dowolną postacią, wiersz trafia tylko do członków kampanii, którzy mogą odczytać tę postać. Jeśli grono to wszyscy, ale któryś członek nie może odczytać postaci, wiersz idzie jako prywatna wiadomość do tych, którzy mogą. Stół pokazuje wiersz z etykietą Gra, żeby nikt nie wziął go za wiadomość gracza.

Zestawy treści

Zestaw to nazwany zbiór wartości danych wejściowych, na przykład gotowa postać. Fabled sprawdza każdy zestaw jak scenariusz, więc każda wartość musi pasować do swojej danej. Gra może mieć do 512 zestawów na framework.

schemas/keeper.json
  "content": [
    {
      "id": "mira-scout",
      "name": "Mira the Scout",
      "parameters": {
        "name": "Mira",
        "max_hp": 8,
        "calling": "Scout",
        "lamp": "lamp"
      }
    }
  ]
  1. Wiersze 47-48 Preset ma id i name.
  2. Wiersze 49-54 Wartości danych wejściowych, które preset wypełnia. Muszą mieścić się w granicach danych wejściowych.

Sekcje

Sekcje grupują dane wejściowe w kroki kreatora tworzenia. Gdy framework deklaruje sekcje, każda dana wejściowa musi być na liście jednej z nich, także ukryte.

schemas/keeper.json
  "sections": [
    {
      "id": "basics",
      "title": "Basics",
      "inputs": ["name", "max_hp", "calling", "lamp"]
    }
  ],
  1. Wiersze 25-27 Sekcja ma id, title i dane wejściowe, które pokazuje. Każde dane wejściowe muszą być w jednej sekcji.
Input lamp is not assigned to any section.

Podrzędne frameworki

Podrzędny framework to część większego elementu, na przykład Lamp, którą nosi Keeper. Element podrzędny ma własny schemat, konstruktor, ramkę i scenariusz.

schemas/keeper.json
  "childFrameworks": { "lamp": "lamp" },
  1. Wiersz 22 Przypisuje miejsce podrzędne lamp do frameworka o id lamp.
schemas/lamp.json
{
  "id": "lamp",
  "name": "Lamp",
  "elementType": "item",
  "constructor": "rules/lamp.ts",
  "inputs": {
    "name": { "label": "Name" },
    "oil": { "label": "Oil", "defaultValue": 5 }
  },
  "frames": [{ "id": "card", "source": "layouts/lamp.json", "default": true }]
}
  1. Wiersze 6-9 Dane wejściowe elementu podrzędnego. Element podrzędny też potrzebuje name.
  2. Wiersz 10 Element podrzędny ma własną ramkę.

Element nadrzędny łączy nazwę miejsca z id frameworka w childFrameworks. Odwołanie przechowuje ukryta dana wejściowa. Konstruktor zwraca dane wejściowe elementu podrzędnego obok własnych wartości.

rules/keeper.ts
export function construct(
  name: string,
  max_hp: number,
  calling: string,
  lamp: FrameworkRef,
): {
  values: { name: string; max_hp: number; hp: number; calling: string; guard: number };
  children: { lamp: { framework: FrameworkRef; params: { name: string; oil: number } } };
} {
  return {
    values: { name: name, max_hp: max_hp, hp: max_hp, calling: calling, guard: 0 },
    children: { lamp: { framework: lamp, params: { name: "Lantern", oil: 5 } } },
  };
}
  1. Wiersz 5 lamp to FrameworkRef. Platforma zamienia id frameworka z danych wejściowych na taki obiekt.
  2. Wiersze 6-9 Typ zwracany wymienia zapisane wartości i miejsca podrzędne.
  3. Wiersz 11 Wartości początkowe Keepera.
  4. Wiersz 12 Miejsce podrzędne: który framework zbudować i jakie dane wejściowe mu przekazać.

Każdy framework, także podrzędny, musi zwracać nazwę.

must define the required 'name' value, normally as a string constructor field.

Miejsce wskazujące framework spoza gry kończy się błędem:

Invalid child Framework constraint: lamp.

Pola zaawansowane

PoleCel
listsTreści, które postać zdobywa w trakcie gry.
contentChoicesPunkty wyboru, w których gracz wybiera jeden wpis frameworka treści.
slotsSelektory powtarzalnych wyborów.
poolsWspólne pule, z których czerpią liczbowe dane wejściowe.
modifiersLiczby, które platforma wylicza z efektów treści.
effectsJak framework treści nazywa modyfikator i wartość.
levellingPrzesuwanie postaci o jeden poziom w górę lub w dół po utworzeniu.
rebuildCo przebudowa robi ze stanem gry, na przykład przy zmianie poziomu.
combatRole, które czytają narzędzia bojowe stołu.
catalogueRekordy treści trzymane poza źródłem i dodawane partiami.
tablesWspólne tabele danych.
playReadsWartości pochodne, które stół czyta z zapisanych atrybutów.
rulesAttacksAtaki, które ma każda postać.
optionsFromBierze opcje danych wejściowych z innego źródła.
rich, richTextOznacza dane wejściowe tekstowe jako tekst sformatowany.

Dalej