Przejdź do głównej treści

Frameworki kodowe

Przepis: rzut przeciw umiejętności

Sprawdź rzut procentowy względem wartości umiejętności i podaj przedział sukcesu.

Cel

Pozwól graczowi rzucić k100 przeciw umiejętności Lore i zobaczyć przedział: Flawless, Strong, Pass albo Miss. Niższy rzut jest lepszy.

Jak rzut trafia do gry

Reguły nie rzucają kośćmi. Gracz rzuca na karcie i wpisuje liczbę do akcji. Reguła sprawdza liczbę i ją zapisuje. Pętla gry ma cztery kroki.

  1. Kliknij znaczek kości

    Karta pokazuje Roll: [[1d100]]. Kliknięcie rzuca k100.

  2. Odczytaj rzut w dzienniku

    Wynik pojawia się w dzienniku kości stołu i na czacie. Postać nie ma jeszcze żadnego zapisu.

  3. Uruchom akcję i wpisz rzut

    Użyj przycisku Lore check. Fabled prosi o rzut w oknie dialogowym. Wpisz liczbę z dziennika.

  4. Pasmo się aktualizuje

    Reguła zapisuje rzut i cel. Funkcja ledgera wylicza pasmo, a karta je pokazuje.

Zmiana

Dodaj do schematu dane wejściowe Lore, akcję i funkcję ledgera. Dane wejściowe konstruktora mogą mieć ograniczenia.

schemas/keeper.json
    "lore": {
      "label": "Lore",
      "description": "The percentile a Lore check must roll under.",
      "defaultValue": 40,
      "min": 1,
      "max": 99
    }
  1. Wiersze 13-14 Te ograniczenia działają, gdy powstaje postać. Nie dotyczą rzutu.
schemas/keeper.json
    {
      "id": "check_lore",
      "name": "Lore check",
      "source": "rules/check-lore.ts",
      "inputs": { "roll": { "label": "Roll", "min": 1, "max": 100 } }
    }
  1. Wiersze 21-23 Akcja Lore check i jej plik reguł.
  2. Wiersz 24 Wejście Roll: etykieta i granice. Okno je pokazuje, a serwer je wymusza.
schemas/keeper.json
  "ledgerFunctions": [
    {
      "id": "last_band",
      "name": "Last band",
      "field": "last_band",
      "source": "rules/band.ts"
    }
  ]
  1. Wiersze 32-35 Funkcja ledgera wylicza last_band z dwóch pól, które zapisuje akcja.

Konstruktor zwraca nowe pola z wartościami zastępczymi. Funkcja ledgera zastępuje last_band, gdy element jest budowany.

rules/keeper.ts
export function construct(
  name: string,
  max_hp: number,
  lore: number,
): {
  name: string;
  max_hp: number;
  hp: number;
  lore: number;
  last_roll: number;
  last_target: number;
  last_band: string;
} {
  return {
    name: name,
    max_hp: max_hp,
    hp: max_hp,
    lore: lore,
    last_roll: 0,
    last_target: 0,
    last_band: "",
  };
}
  1. Wiersze 10-12 Pola, które zapisuje akcja i czyta funkcja ledgera.
  2. Wiersze 19-21 Wartości początkowe: jeszcze bez rzutu.

Granice wejścia utrzymują rzut między 1 a 100. Akcja ignoruje liczbę z ułamkiem, a w przeciwnym razie zapisuje rzut i cel.

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. Przedział wynika z nich.

Jedna funkcja ledgera zamienia je w przedział. Może jej użyć każda umiejętność, bo każda akcja umiejętności zapisuje te same dwa pola.

rules/band.ts
export function last_band(currentValue: string, self: ElementRef): string {
  const roll: number = element.var(self, "last_roll") as number;
  const target: number = element.var(self, "last_target") as number;
  if (roll === 0) {
    return "No roll yet";
  }
  if (roll <= math.floor(target / 5)) {
    return "Flawless";
  }
  if (roll <= math.floor(target / 2)) {
    return "Strong";
  }
  if (roll <= target) {
    return "Pass";
  }
  return "Miss";
}
  1. Wiersze 2-3 Odczytaj dwa pola zapisane przez akcję.
  2. Wiersze 4-6 Przed pierwszym rzutem powiedz o tym.
  3. Wiersze 7-15 Niższy rzut jest lepszy. Każdy przedział to część celu.
  4. Wiersz 16 Powyżej celu to pudło.

Dla innej umiejętności skopiuj check-lore.ts, zmień nazwę funkcji i pole w wywołaniu element.var. Każda umiejętność potrzebuje własnej akcji, bo nazwa pola jest zapisana wprost w kodzie.

Pokaż na karcie kości, przedział i przycisk. Wpisz przedział w requiredBindings, a akcję w aliasach.

layouts/keeper.json
      { "binding": "element.attributes.last_band", "expectedType": "string" }
  1. Wiersz 15 Przedział to tekst.
layouts/keeper.json
      { "name": "check_lore", "functionRef": "check_lore" }
  1. Wiersz 21 Alias, którego używa przycisk.
layouts/keeper.json
      { "kind": "text", "text": "Roll: [[1d100]]" },
      {
        "kind": "text",
        "text": "Last check: {{element.attributes.last_band}}"
      },
      { "kind": "button", "label": "Lore check", "actionRef": "check_lore" }
  1. Wiersz 35 Znaczek kości. Kliknięcie rzuca i pokazuje wynik w dzienniku rzutów.
  2. Wiersze 36-39 Przedział, który wyliczyła funkcja ledgera.
  3. Wiersz 40 Przycisk, który otwiera dialog dla rzutu.

Przetestuj to

Przetestuj każdy przedział oraz rzut spoza zakresu. Każdy krok wymienia dwa zapisy. expectedValuesAfter sprawdza przedział po akcji.

scenarios/lore.json
    {
      "action": "check_lore",
      "parameters": { "roll": 6 },
      "expectedWrites": [
        { "op": "ledger.set", "key": "last_target", "value": 40 },
        { "op": "ledger.set", "key": "last_roll", "value": 6 }
      ],
      "expectedValuesAfter": { "last_band": "Flawless" }
    },
  1. Wiersz 17 Liczba, którą wpisał gracz.
  2. Wiersze 18-21 Dwa zapisy, po kolei.
  3. Wiersz 22 Wyliczony przedział po akcji.

Ostatni krok to rzut 40,5. Nic nie zapisuje, więc zabezpieczenie przed ułamkami jest udowodnione. Rzut 500 nie może być krokiem: leży poza granicami wejścia, a scenariusz jest odrzucany.

scenarios/lore.json
    {
      "action": "check_lore",
      "parameters": { "roll": 40.5 },
      "expectedWrites": [],
      "expectedValuesAfter": { "last_band": "Miss" }
    }
  1. Wiersz 53 Liczba z ułamkiem.
  2. Wiersz 54 Brak zapisów.
  3. Wiersz 55 Przedział zostaje taki, jaki zostawił wcześniejszy krok.

Wpisz plik scenariusza w manifeście. Dodaj nowe pola do oczekiwanych wartości pozostałych scenariuszy.

manifest/project.json
{
  "formatVersion": "fabled.game-project/v1",
  "projectId": "game-your-game-id",
  "projectKind": "GAME",
  "compilerProfile": "native-game-v1",
  "name": "Lantern Keepers",
  "entryFramework": "keeper",
  "frameworks": ["schemas/keeper.json"],
  "scenarios": [
    "scenarios/new-keeper.json",
    "scenarios/heal.json",
    "scenarios/lore.json"
  ]
}
  1. Wiersz 12 Nowy plik scenariusza.

Dalej