Saltar al contenido principal

Code frameworks

Receta: tirar contra una habilidad

Comprueba una tirada porcentual contra el valor de una habilidad e indica una banda de éxito.

Objetivo

Deja que un jugador tire un d100 contra una habilidad Lore y vea una banda: Flawless, Strong, Pass o Miss. Una tirada más baja es mejor.

Cómo entra la tirada

Las reglas no pueden tirar dados. El jugador tira en la hoja y escribe el número en una acción. La regla valida el número y lo escribe. El ciclo de juego tiene cuatro pasos.

  1. Haz clic en la insignia del dado

    La hoja muestra Roll: [[1d100]]. Un clic tira un d100.

  2. Lee la tirada en el registro

    El resultado aparece en el registro de dados de la mesa y en el chat. Aún no se escribe nada en el personaje.

  3. Ejecuta la acción y escribe la tirada

    Usa el botón Lore check. Fabled pide la tirada en un cuadro de diálogo. Escribe el número del registro.

  4. La banda se actualiza

    La regla escribe la tirada y el objetivo. La función del ledger deriva la banda, y la hoja la muestra.

El cambio

Añade al esquema una entrada Lore, la acción y la función del ledger. Una entrada del constructor puede tener límites.

schemas/keeper.json
    "lore": {
      "label": "Lore",
      "description": "The percentile a Lore check must roll under.",
      "defaultValue": 40,
      "min": 1,
      "max": 99
    }
  1. Líneas 13-14 Estos límites se aplican cuando se crea un personaje. No se aplican a la tirada.
schemas/keeper.json
    {
      "id": "check_lore",
      "name": "Lore check",
      "source": "rules/check-lore.ts",
      "inputs": { "roll": { "label": "Roll", "min": 1, "max": 100 } }
    }
  1. Líneas 21-23 La acción de prueba de Lore y su archivo de reglas.
  2. Línea 24 La entrada Roll: una etiqueta y unos límites. El diálogo los muestra y el servidor los exige.
schemas/keeper.json
  "ledgerFunctions": [
    {
      "id": "last_band",
      "name": "Last band",
      "field": "last_band",
      "source": "rules/band.ts"
    }
  ]
  1. Líneas 32-35 La función del ledger deriva last_band de los dos campos que escribe la acción.

El constructor devuelve los campos nuevos con marcadores. La función del ledger reemplaza last_band cuando se crea el Elemento.

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. Líneas 10-12 Los campos que escribe la acción y lee la función del ledger.
  2. Líneas 19-21 Valores iniciales: aún no hay tirada.

Los límites de la entrada mantienen la tirada entre 1 y 100. La acción ignora un número con decimales y, si no, escribe la tirada y el objetivo.

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. Línea 1 La tirada es una entrada que escribe el jugador.
  2. Línea 2 Ignora un número con decimales. Los límites de la entrada ya lo mantienen entre 1 y 100.
  3. Líneas 4-5 Escribe el objetivo y la tirada. La franja se deduce de ellos.

Una función del ledger los convierte en una franja. Cualquier habilidad puede usarla, porque todas las acciones de habilidad escriben los mismos dos campos.

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. Líneas 2-3 Lee los dos campos que escribió la acción.
  2. Líneas 4-6 Si aún no hay tirada, indícalo.
  3. Líneas 7-15 Una tirada más baja es mejor. Cada franja es una parte del objetivo.
  4. Línea 16 Por encima del objetivo es un fallo.

Para otra habilidad, copia check-lore.ts y cambia el nombre de la función y el campo de la llamada element.var. Cada habilidad necesita su propia acción, porque el nombre del campo se escribe en el código.

Muestra los dados, la franja y un botón en la hoja. Enumera la franja en requiredBindings y la acción en los alias.

layouts/keeper.json
      { "binding": "element.attributes.last_band", "expectedType": "string" }
  1. Línea 15 La franja es texto.
layouts/keeper.json
      { "name": "check_lore", "functionRef": "check_lore" }
  1. Línea 21 El alias que usa el botón.
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. Línea 35 La insignia de dados. Un clic tira y muestra el resultado en el registro de dados.
  2. Líneas 36-39 La franja que derivó la función del ledger.
  3. Línea 40 El botón que abre el cuadro de diálogo de la tirada.

Pruébalo

Prueba cada banda y una tirada fuera del rango. Cada paso enumera las dos escrituras. expectedValuesAfter comprueba la banda después de la acción.

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. Línea 17 El número que escribió el jugador.
  2. Líneas 18-21 Las dos escrituras, en orden.
  3. Línea 22 La banda derivada después de la acción.

El último paso es una tirada de 40,5. No escribe nada, así que la protección contra decimales queda demostrada. Una tirada de 500 no puede ser un paso: queda fuera de los límites de la entrada y el escenario se rechaza.

scenarios/lore.json
    {
      "action": "check_lore",
      "parameters": { "roll": 40.5 },
      "expectedWrites": [],
      "expectedValuesAfter": { "last_band": "Miss" }
    }
  1. Línea 53 Un número con decimales.
  2. Línea 54 Sin escrituras.
  3. Línea 55 La banda queda como la dejó el paso anterior.

Enumera el archivo de escenario en el manifiesto. Añade los campos nuevos a los valores esperados de los otros escenarios.

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. Línea 12 El nuevo archivo de escenario.

Siguiente