Aller au contenu principal

Frameworks de code

Dispositions et fiches

Dessinez une fiche avec un Cadre, liez-la à vos champs et reliez ses boutons aux actions.

Un fichier de Cadre

Un Cadre est un fichier JSON dans layouts/. Un Framework le liste dans frames. Voici la fiche du Keeper.

layouts/keeper.json
  "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": []
  },
  1. Lignes 11-15 requiredBindings liste chaque champ que le texte utilise, avec son type.
  2. Lignes 17-20 Alias d'action : un nom que les boutons utilisent, et l'id de l'action qu'il appelle.
layouts/keeper.json
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" }
    ]
  }
}
PartieCe qu'elle contient
versionLa version du format de Cadre. Utilisez 1.0, ou 2.0 pour un Cadre qui dessine une liste.
metadataLe nom, bindingMode bound, et frameworkRef, l'id du Framework auquel le Cadre appartient. Gardez context et template comme dans l'exemple.
dataContractLes champs que le Cadre lit et les actions que ses boutons peuvent appeler.
layoutUn arbre de nœuds. L'exemple utilise des nœuds container, text et button.

Un container accepte ses réglages de disposition dans un objet layout à côté de kind. Un nœud text accepte des réglages de style comme fontSize et fontWeight. Un Cadre ne contient ni code, ni gestionnaires d'événements, ni HTML brut.

layouts/keeper.json
    "kind": "container",
    "layout": { "direction": "column", "gap": 12, "padding": 16 },
    "children": [
  1. Ligne 25 Le type du nœud.
  2. Ligne 26 Les réglages de disposition : direction, gap et padding.
  3. Ligne 27 Les nœuds à l'intérieur du conteneur.

Liaisons

Le texte affiche une valeur stockée avec {{element.attributes.field}}. Listez chaque champ utilisé dans requiredBindings avec son type. Une liaison vers un champ qui n'existe pas est refusée.

{
  "kind": "text",
  "text": "HP: {{element.attributes.hp}} / {{element.attributes.mana}}"
}
FRAME_BINDING_UNKNOWN: element.attributes.mana

Boutons et actions

Le dataContract liste des alias d'action. Chaque alias a un nom et un functionRef, qui est un id d'action du même Framework. Un bouton nomme un alias dans actionRef.

layouts/keeper.json
  "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" }
    ]
  }
  1. Lignes 26-30 Les nœuds de texte affichent des champs entre doubles accolades.
  2. Lignes 31-32 Les boutons nomment dans actionRef un alias de dataContract.actions.
{ "kind": "button", "label": "Take damage", "actionRef": "mend" }
ACTION_MISSING: Action "mend" not found in framework's actionFunctions/ledgerFunctions

Dés dans le texte

Écrivez un jet de dés dans le texte, comme [[1d20+{{element.attributes.guard}}]]. Le joueur lance avec les commandes de dés habituelles de Fabled. Un nombre lié doit être un champ déclaré et figurer dans requiredBindings.

layouts/keeper.json
        "text": "Defend: [[1d20+{{element.attributes.guard}}]]"
  1. Ligne 39 Une annotation de dés se place entre doubles crochets. Le champ doit figurer dans requiredBindings.

Comment un jet atteint une action

Une annotation de dés affiche un badge de dés. Quand un joueur clique dessus, Fabled lance les dés et montre le résultat dans le journal des dés de la table et dans le chat. Le jet n'écrit pas dans le registre et ne remplit pas une entrée d'action. Une entrée avec la clé roll est au contraire lancée par le serveur, comme décrit plus bas.

Un bouton ne peut pas non plus contenir une valeur ou un jet. Quand un joueur utilise le bouton d'une action qui a des entrées, Fabled ouvre une boîte de dialogue et demande chaque entrée. Les étapes sont donc : lancer, lire le nombre, utiliser le bouton de l'action et saisir le nombre.

Écrivez ces étapes sur la fiche, pour que les joueurs les connaissent. La règle doit vérifier le nombre, car la boîte de dialogue ne le limite pas.

Pour que Fabled lance les dés à la place du joueur, donnez à l'entrée de l'action une clé roll, comme le montre la page des schémas de Framework. La boîte de dialogue affiche alors un bouton Lancer à la place d'un champ. Le serveur lance les dés et la boîte de dialogue remplit le total dans un champ que le joueur ne peut pas modifier. Le joueur peut relancer, et le nouveau total remplace l'ancien.

Un jet n'est dépensé qu'une fois. Quand l'action s'exécute, elle prend le jet conservé par le serveur : un nombre ne peut donc être ni saisi ni utilisé deux fois. Un nouveau jet annule les jets précédents non dépensés de cette entrée. Un jet est lié à la campagne où il a été fait et expire au bout de 15 minutes. Ensuite, le joueur relance.

Le jet est publié dans le journal de la table pour un public. Si l'action ne nomme aucun destinataire, il va au public de jets du joueur, le même réglage que ses autres jets de dés. Tout le monde donne un jet public, lui seul un murmure à lui-même, et lui et les MJ un murmure à lui-même et aux MJ.

Une action peut publier une ligne de résultat dans le journal de la table avec un modèle log. La section Ligne de journal d'une action de la page Schémas de Framework montre comment. Un jet sur la fiche ne publie que son propre jet de dés. Les lignes de journal sont en cours de déploiement et ne sont peut-être pas encore disponibles dans tous les jeux.

Un Cadre pour chaque Framework

Chaque Framework a ses propres Cadres. L'enfant Lamp a sa propre carte, liée aux champs de Lamp.

Suite