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.jsonPola podstawowe
| Pole | Wymagane | Znaczenie |
|---|---|---|
| id | Tak | Unikalne id frameworka. Używają go manifest i scenariusze. |
| name | Tak | Wyświetlana nazwa. |
| elementType | Tak | Co buduje: character dla postaci grywalnych, item dla przedmiotów, spell dla zaklęć. Można używać własnych typów. |
| constructor | Tak | Ścieżka pliku reguł, który buduje nowy element. |
| inputs | Nie | Co gracz wpisuje przy tworzeniu elementu. Każdy klucz odpowiada parametrowi konstruktora. |
| actions | Nie | Rzeczy, które element może robić. Każda ma id, nazwę i plik reguł. |
| ledgerFunctions | Nie | Wartości pochodne. Każda dotyczy zapisanego pola i ma plik reguł. |
| frames | Tak | Od jednej do szesnastu ramek. Dokładnie jedna ma default ustawione na true. |
| sections | Nie | Grupuje dane wejściowe w kroki kreatora tworzenia. |
| content | Nie | Gotowe zestawy. Każdy ma id, nazwę i wartości danych wejściowych. |
| childFrameworks | Nie | Łą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.
"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 }
},- Wiersze 8-14 min i max ograniczają liczbę. Scenariusz lub preset poza granicami się nie powiedzie.
- Wiersze 15-19 options podaje stałą listę wyborów. Wartość domyślna musi być jedną z nich.
- Wiersz 20 Ukryte dane wejściowe przechowują wartość, której gracz nigdy nie widzi. Tutaj łączą podrzędny Lamp.
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"
}
}
]
}| Klucz | Znaczenie |
|---|---|
| label | Tekst pokazywany graczowi. |
| description | Tekst pomocy, do 1024 znaków. |
| defaultValue | Wartość używana, gdy gracz zostawi pole bez zmian. |
| options | Stała lista od 2 do 128 wyborów tekstowych, każdy do 128 znaków. Wartość domyślna musi być jednym z nich. |
| optionLabels | Etykiety opcji widoczne dla gracza. Zapisana wartość pozostaje opcją. |
| min, max | Granice liczby. min nie może przekraczać max. |
| minLength, maxLength | Granice długości tekstu. |
| required | Ustaw false, aby gracz mógł zostawić pole puste. |
| hidden | Ukrywa dane wejściowe w kreatorze. Ukryte dane wejściowe wymagają defaultValue. |
| visibleWhen | Pokazuje 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.
"ledgerFunctions": [
{
"id": "guard",
"name": "Guard",
"field": "guard",
"source": "rules/guard.ts"
}
],- Wiersze 36-39 id i name identyfikują funkcję, field to zapisana wartość, którą funkcja wylicza, a source to jej plik reguł.
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);
}- Wiersze 1-3 Funkcja pomocnicza. Nie ma export, a funkcja ledgera wywołuje ją po nazwie.
- Wiersz 5 Funkcja ledgera dostaje swoją bieżącą wartość i element.
- Wiersz 6 Odczytuj zapisane wartości przez element.var.
- 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 contractDane 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.
{
"id": "check_lore",
"name": "Lore check",
"source": "rules/check-lore.ts",
"inputs": { "roll": { "label": "Roll", "min": 1, "max": 100 } }
}- 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.
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);
}
}- Wiersz 1 Rzut to dane wejściowe, które wpisuje gracz.
- Wiersz 2 Zignoruj liczbę z ułamkiem. Granice wejścia już utrzymują ją między 1 a 100.
- 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.
"content": [
{
"id": "mira-scout",
"name": "Mira the Scout",
"parameters": {
"name": "Mira",
"max_hp": 8,
"calling": "Scout",
"lamp": "lamp"
}
}
]- Wiersze 47-48 Preset ma id i name.
- 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.
"sections": [
{
"id": "basics",
"title": "Basics",
"inputs": ["name", "max_hp", "calling", "lamp"]
}
],- 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.
"childFrameworks": { "lamp": "lamp" },- Wiersz 22 Przypisuje miejsce podrzędne lamp do frameworka o id lamp.
{
"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 }]
}- Wiersze 6-9 Dane wejściowe elementu podrzędnego. Element podrzędny też potrzebuje name.
- 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.
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 } } },
};
}- Wiersz 5 lamp to FrameworkRef. Platforma zamienia id frameworka z danych wejściowych na taki obiekt.
- Wiersze 6-9 Typ zwracany wymienia zapisane wartości i miejsca podrzędne.
- Wiersz 11 Wartości początkowe Keepera.
- 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
| Pole | Cel |
|---|---|
| lists | Treści, które postać zdobywa w trakcie gry. |
| contentChoices | Punkty wyboru, w których gracz wybiera jeden wpis frameworka treści. |
| slots | Selektory powtarzalnych wyborów. |
| pools | Wspólne pule, z których czerpią liczbowe dane wejściowe. |
| modifiers | Liczby, które platforma wylicza z efektów treści. |
| effects | Jak framework treści nazywa modyfikator i wartość. |
| levelling | Przesuwanie postaci o jeden poziom w górę lub w dół po utworzeniu. |
| rebuild | Co przebudowa robi ze stanem gry, na przykład przy zmianie poziomu. |
| combat | Role, które czytają narzędzia bojowe stołu. |
| catalogue | Rekordy treści trzymane poza źródłem i dodawane partiami. |
| tables | Wspólne tabele danych. |
| playReads | Wartości pochodne, które stół czyta z zapisanych atrybutów. |
| rulesAttacks | Ataki, które ma każda postać. |
| optionsFrom | Bierze opcje danych wejściowych z innego źródła. |
| rich, richText | Oznacza dane wejściowe tekstowe jako tekst sformatowany. |

