Aller au contenu principal

Frameworks de code

Listes de contenu

Laissez un personnage gagner du contenu en jouant : déclarez une liste, changez-la avec des actions et montrez-la sur la fiche.

Ce qu'est une liste

Une liste contient du contenu qu'un personnage gagne en jouant, comme un sac de bibelots. Le contenu est un autre Framework, et ses préréglages sont les entrées. Une liste vit dans le registre et n'est pas un champ du constructeur. Seules les actions la changent.

OptionSignification
labelLe nom de la liste.
ofL'id du Framework de contenu.
maxLe nombre d'entrées que la liste contient, de 1 à 128.
cardLe Cadre qui dessine une entrée sous forme de carte. Ce doit être un Cadre du Framework de contenu.
summaryJusqu'à 4 champs de l'entrée à montrer sur sa ligne.
effects, caps, distinctByDes entrées qui changent des modificateurs, et leurs limites. Voir Réserves et modificateurs.

Les listes de lignes, qui ajoutent des cellules à chaque ligne, existent et ne sont pas encore couvertes.

Déclarer une liste

Ajoutez la liste au Framework qui la possède. Le Framework de contenu contient les entrées sous forme de préréglages. Le tutoriel Faire grandir Lantern construit le Framework Trinket étape par étape.

schemas/keeper.json
  "lists": {
    "pack": {
      "label": "Pack",
      "of": "trinket",
      "max": 2,
      "card": "trinket-card",
      "summary": ["weight"]
    }
  }
  1. Ligne 45 Le Framework de contenu dont les préréglages sont les entrées.
  2. Ligne 46 La liste contient au plus ce nombre d'entrées.
  3. Ligne 47 Le Cadre qui dessine une entrée.
  4. Ligne 48 Les champs à montrer sur la ligne d'une entrée. Un champ de résumé a besoin d'un domaine fermé : des options, un minimum et un maximum, ou vrai et faux.

Ajouter et retirer

Une liste ne change que par des actions. Prenez l'entrée comme entrée ContentRef et appelez list.add avec une offre.

rules/pack-trinket.ts
export function pack_trinket(self: ElementRef, trinket: ContentRef): void {
  list.add(self, "pack", trinket, offer.where({ weight: { lte: 3 } }));
}
  1. Ligne 1 L'entrée que le joueur choisit.
  2. Ligne 2 list.add vérifie d'abord l'offre. Cette offre autorise les entrées de poids 3 ou moins.

Retirez une entrée avec list.remove.

rules/unpack-trinket.ts
export function unpack_trinket(self: ElementRef, trinket: ContentRef): void {
  list.remove(self, "pack", trinket);
}
  1. Ligne 2 Retire l'entrée choisie. C'est refusé si la liste ne la contient pas.

Quand un joueur utilise le bouton, Fabled lui demande de choisir l'une des entrées que l'offre autorise. Utilisez list.count pour arrêter un ajout avec une règle à vous, comme le montre la page Écrire des règles.

Offres

offer.where prend des conditions sur les champs de l'entrée. Vous écrivez les conditions comme des littéraux, donc une offre ne peut pas lire le personnage. Pour dépendre du personnage, testez-le avec if avant list.add.

OpérateurSignificationExemple
eqLe champ est égal à la valeur.{"slot":{"eq":"Ring"}}
neLe champ n'est pas égal à la valeur.{"slot":{"ne":"Ring"}}
gteLe nombre est au moins égal à la valeur.{"weight":{"gte":2}}
lteLe nombre est au plus égal à la valeur.{"weight":{"lte":3}}
inLe champ est égal à l'une des valeurs. Jusqu'à 64 valeurs.{"slot":{"in":["Ring","Cloak"]}}
hasLe champ est un texte séparé par des virgules qui contient l'une des valeurs.{"tags":{"has":["fire"]}}

Chaque condition d'une offre doit être vraie, et une offre nomme 6 champs au plus. Un champ que l'entrée n'a pas ne correspond jamais.

La montrer sur la fiche

Un Cadre qui montre une liste utilise la version 2.0. Déclarez une région dans le dataContract, puis dessinez-la. Une région peut aussi donner jusqu'à 4 boutons à chaque entrée, chacun lançant une action sur cette entrée.

layouts/keeper.json
      {
        "kind": "region",
        "id": "pack_list",
        "listBinding": "{{element.lists.pack}}",
        "emptyText": "Your pack is empty.",
        "itemActions": [{ "actionRef": "unpack_trinket", "label": "Unpack" }]
      }
  1. Ligne 46 Montré tant que la liste est vide.
  2. Ligne 47 Un bouton sur chaque entrée. L'action ne doit prendre que l'entrée.

Testez-la

Testez chaque refus que l'offre et la taille peuvent donner. Les étapes ci-dessous ajoutent, refusent de trois façons, retirent, puis refusent un retrait.

scenarios/pack.json
{
  "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"] }
}
  1. Lignes 19-24 Acceptée : la corde est ajoutée.
  2. Lignes 25-31 Refusée : le sac contient déjà la corde.
  3. Lignes 32-38 Refusée : l'offre n'autorise pas l'enclume.
  4. Lignes 47-53 Refusée : le sac contient 2 entrées, ce qui est son maximum.
  5. Lignes 54-61 Retirée : la corde quitte le sac.
  6. Lignes 62-68 Refusée : la corde n'est plus dans le sac.
  7. Ligne 70 Le sac finit avec la bougie seulement.

Un scénario peut aussi commencer avec une liste qui contient déjà des entrées. Nommez-les dans lists, par id de préréglage, et vérifiez-les avec expectedLists.

scenarios/seeded.json
{
  "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"] }
}
  1. Ligne 18 La liste avec laquelle l'Élément commence.
  2. Ligne 19 La liste après le scénario.

SAME_NAME et LIST_CAP viennent des limites d'une liste qui applique des effets. La page Réserves et modificateurs les prouve.