{"$schema":"https://rpg.pizza/ruleset-v1","format":"rpg.pizza/ruleset","id":"example","name":{"en":"rpg.pizza Example","es":"Ejemplo de rpg.pizza","pt":"Exemplo do rpg.pizza"},"version":"2.0.0","languages":["en","es","pt"],"authors":["rpg.pizza"],"description":{"en":"A tiny original fantasy system that shows most of the engine features. Use it as a reference to write your own rules.","es":"Un pequeño sistema de fantasía original que muestra la mayoría de las funciones del motor. Úsalo como referencia para escribir tus reglas.","pt":"Um pequeno sistema de fantasia original que mostra a maioria dos recursos da engine. Use-o como referência para escrever suas regras."},"scripts":[{"name":"helpers.lua","source":"-- rpg.pizza example system: shared helpers.\n-- Scripts run in the order listed in ruleset.json, in one global scope, so helpers defined here are\n-- visible to main.lua. Schema and API reference: https://rpg.pizza/ruleset-v1\n\n-- A translatable text: one string per language listed in ruleset.json (the first one is the main language).\nfunction T(en, es, pt) return { en = en, es = es, pt = pt } end\n\n-- Joins texts and plain values into one translatable text: J(T(\"Level \", \"Nivel \", \"Nível \"), 3) -> \"Level 3\" / ...\nfunction J(...)\n  local out = { en = \"\", es = \"\", pt = \"\" }\n  for _, part in ipairs({ ... }) do\n    for lang in pairs(out) do\n      out[lang] = out[lang] .. (type(part) == \"table\" and (part[lang] or part.en) or tostring(part))\n    end\n  end\n  return out\nend\n\nATTRIBUTES = {\n  { id = \"str\", name = T(\"Strength\", \"Fuerza\", \"Força\"), short = \"STR\" },\n  { id = \"dex\", name = T(\"Dexterity\", \"Destreza\", \"Destreza\"), short = \"DEX\" },\n  { id = \"con\", name = T(\"Constitution\", \"Constitución\", \"Constituição\"), short = \"CON\" },\n  { id = \"int\", name = T(\"Intelligence\", \"Inteligencia\", \"Inteligência\"), short = \"INT\" },\n}\n\n-- Point buy: what each base value costs (8 to 15, 15 points in total).\nPOINT_COST = { [8] = -2, [9] = -1, [10] = 0, [11] = 1, [12] = 2, [13] = 3, [14] = 5, [15] = 7 }\n\n-- The attribute modifier: (value - 10) / 2, rounded down.\nfunction modifier(c, attr) return (c:get(\"attr:\" .. attr) - 10) // 2 end\n\nfunction contains(list, value)\n  for _, x in ipairs(list or {}) do if x == value then return true end end\n  return false\nend\n\n-- Money is stored in gold pieces (decimals for silver); this is how it is shown: 1234.5 -> \"1,234.5 gp\".\nfunction gold(n)\n  local whole = math.floor(math.abs(n))\n  local cents = math.floor((math.abs(n) - whole) * 10 + 0.5)\n  local text = tostring(whole):reverse():gsub(\"(%d%d%d)\", \"%1,\"):reverse():gsub(\"^,\", \"\")\n  if cents > 0 then text = text .. \".\" .. cents end\n  return (n < 0 and \"-\" or \"\") .. text .. \" gp\"\nend\n\nfunction kg(n) return (string.format(\"%.1f\", n):gsub(\"%.0$\", \"\")) .. \" kg\" end\n\n-- A dice expression plus a flat bonus: (\"1d20\", 3) -> \"1d20+3\".\nfunction with_bonus(dice, bonus)\n  if bonus == 0 then return dice end\n  return dice .. (bonus > 0 and \"+\" or \"-\") .. math.abs(bonus)\nend\n"},{"name":"main.lua","source":"-- rpg.pizza example system: a tiny original fantasy game that shows most of the engine features.\n-- Read it top to bottom: every block says which feature it demonstrates. API reference and the JSON\n-- schema of this file: https://rpg.pizza/ruleset-v1\n--\n-- build(c) runs on every change with a fresh character `c`. It declares the sheet in display order and\n-- reads the player's inputs from the values the element functions return. Keep it pure and fast.\n\nlocal XP_FOR_LEVEL = function(n) return 1000 * n * (n - 1) // 2 end -- 0, 1000, 3000, 6000...\n\nfunction build(c)\n  -- Sections: fixed order, titles in three languages, an icon (see x-icons in the schema) and a\n  -- tooltip on the title (hint).\n  c:sections({\n    { id = \"character\", title = T(\"Character\", \"Personaje\", \"Personagem\"), icon = \"user\", columns = 3 },\n    { id = \"attributes\", title = T(\"Attributes\", \"Atributos\", \"Atributos\"), icon = \"activity\", columns = 4,\n      hint = T(\"Modifier = (value − 10) ÷ 2, rounded down.\", \"Modificador = (valor − 10) ÷ 2, redondeado hacia abajo.\",\n        \"Modificador = (valor − 10) ÷ 2, arredondado para baixo.\") },\n    { id = \"combat\", title = T(\"Combat\", \"Combate\", \"Combate\"), icon = \"swords\", columns = 3 },\n    { id = \"skills\", title = T(\"Skills\", \"Habilidades\", \"Perícias\"), icon = \"target\", columns = 3 },\n    { id = \"levels\", title = T(\"Levels\", \"Niveles\", \"Níveis\"), icon = \"arrow-up\" },\n    { id = \"features\", title = T(\"Features\", \"Rasgos\", \"Habilidades\"), icon = \"sparkles\" },\n    { id = \"spells\", title = T(\"Spells\", \"Hechizos\", \"Magias\"), icon = \"magic\" },\n    { id = \"gear\", title = T(\"Gear\", \"Equipo\", \"Equipamento\"), icon = \"backpack\", columns = 2 },\n    { id = \"notes\", title = T(\"Notes\", \"Notas\", \"Notas\"), icon = \"book-open\" },\n  })\n  c.vars.trained = {}\n\n  ------------------------------------------------------------------ Character\n  c:section(\"character\")\n  -- A choice from a catalog: the sheet stores only the id; the item comes from catalogs/ancestries.json.\n  local ancestry = c:choose({ id = \"ancestry\", label = T(\"Ancestry\", \"Ascendencia\", \"Ancestralidade\"), from = \"ancestries\" })\n  local background = c:choose({ id = \"background\", label = T(\"Background\", \"Trasfondo\", \"Antecedente\"), from = \"backgrounds\" })\n  -- A number typed by the player (starts at 0; min shows a warning when violated).\n  local xp = c:number({ id = \"xp\", label = T(\"Experience (XP)\", \"Experiencia (PX)\", \"Experiência (XP)\"), default = 0, min = 0 })\n\n  ------------------------------------------------------------------ Levels\n  -- The level list with a \"Level up\" button. Multiclass is just picking another class.\n  local levels = c:levels({ id = \"levels\", label = T(\"Levels\", \"Niveles\", \"Níveis\"), from = \"classes\", max = 10, section = \"levels\" })\n  if c.level > 0 and c.level < 10 then\n    local next_xp = XP_FOR_LEVEL(c.level + 1)\n    c:show({ label = T(\"Next level\", \"Siguiente nivel\", \"Próximo nível\"), value = next_xp .. \" XP\", section = \"character\" })\n    if xp >= next_xp then c:info(T(\"Enough XP to level up!\", \"¡PX suficiente para subir de nivel!\", \"XP suficiente para subir de nível!\")) end\n  end\n\n  -- A stored roll (c:roll): pending until the player rolls it; the dice and total are kept.\n  local omen = c:roll({ id = \"omen\", label = T(\"Birth omen\", \"Presagio de nacimiento\", \"Presságio de nascimento\"), dice = \"1d6\",\n    section = \"character\", description = T(\"Roll once. 6: you start with a lucky charm (+1 on one test per day).\",\n      \"Tira una vez. 6: empiezas con un amuleto de la suerte (+1 en una prueba por día).\",\n      \"Role uma vez. 6: você começa com um amuleto da sorte (+1 em um teste por dia).\") })\n\n  ------------------------------------------------------------------ Attributes\n  c:section(\"attributes\")\n  local method = c:choose({ id = \"attributes:method\", label = T(\"Attribute method\", \"Método de atributos\", \"Método de atributos\"),\n    options = {\n      { id = \"points\", name = T(\"Point buy (15 points)\", \"Compra de puntos (15 puntos)\", \"Compra por pontos (15 pontos)\"),\n        description = T(\"Bases from 8 to 15; the cost table is in the points bar tooltip.\", \"Bases de 8 a 15.\", \"Bases de 8 a 15.\") },\n      { id = \"roll\", name = T(\"Roll (4d6, drop the lowest)\", \"Tirada (4d6, descarta el menor)\", \"Rolagem (4d6, descarta o menor)\") },\n    }, optional = true, wide = true })\n  local point_buy = method and method.id == \"points\"\n  for _, a in ipairs(ATTRIBUTES) do\n    -- A computed value with a typed base (input). With point buy, each base spends from a budget.\n    c:stat({ id = \"attr:\" .. a.id, label = a.name, secondary = \"mod:\" .. a.id, roll = \"1d20\", rollAdd = \"mod:\" .. a.id,\n      input = { id = \"base:\" .. a.id, label = T(\"base\", \"base\", \"base\"), default = 10, min = point_buy and 8 or 3, max = point_buy and 15 or 18,\n        budget = point_buy and \"points\" or nil, cost = function(v) return POINT_COST[v] or 0 end } })\n  end\n  if point_buy then\n    -- A budget shown as a bar where it is declared; going over warns.\n    c:budget({ id = \"points\", label = T(\"Attribute points\", \"Puntos de atributo\", \"Pontos de atributo\"), total = 15, show = true,\n      description = \"| 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |\\n|---|---|---|---|---|---|---|---|\\n| –2 | –1 | 0 | 1 | 2 | 3 | 5 | 7 |\" })\n  elseif method and method.id == \"roll\" then\n    -- Numbers with a roll button: rolling fills the field, and the player may still edit it.\n    local rolled = {}\n    for i = 1, 4 do\n      local v = c:number({ id = \"attributes:roll:\" .. i, label = J(T(\"Roll \", \"Tirada \", \"Rolagem \"), i), roll = \"4d6kh3\",\n        required = true, min = 3, max = 18 })\n      if v then rolled[#rolled + 1] = v end\n    end\n    if #rolled == 4 then\n      table.sort(rolled, function(x, y) return x > y end)\n      c:info(J(T(\"Assign the rolled values to the bases: \", \"Asigna los valores a las bases: \", \"Distribua os valores nas bases: \"),\n        table.concat(rolled, \", \")), \"attributes:method\")\n    end\n  end\n  -- Ancestry bonuses are parts of the computed values: the breakdown shows \"Dwarf +2\".\n  if ancestry then\n    for attr, n in pairs(ancestry.bonus or {}) do c:add(\"attr:\" .. attr, n, ancestry.name) end\n    if ancestry.versatile then\n      local pick = c:choose({ id = \"ancestry:attribute\", label = T(\"Versatile: +1 attribute\", \"Versátil: +1 atributo\", \"Versátil: +1 atributo\"),\n        options = ATTRIBUTES })\n      if pick then c:add(\"attr:\" .. pick.id, 1, T(\"Versatile\", \"Versátil\", \"Versátil\")) end\n    end\n  end\n  for _, a in ipairs(ATTRIBUTES) do\n    c:stat({ id = \"mod:\" .. a.id, hidden = true })\n    c:add(\"mod:\" .. a.id, modifier(c, a.id), a.name)\n  end\n\n  ------------------------------------------------------------------ Classes, features and talents\n  c:stat({ id = \"hp\", hidden = true })\n  c:stat({ id = \"mp\", hidden = true })\n  for _, n in ipairs(levels) do\n    local class = n.class\n    -- The level heading, with a tooltip.\n    c:heading(J(T(\"Level \", \"Nivel \", \"Nível \"), n.index, \" · \", class.name, \" \", n.classLevel),\n      { section = \"levels\", description = class.description })\n    local hp = n.index == 1 and class.hp or class.hpPerLevel\n    c:add(\"hp\", math.max(1, hp + modifier(c, \"con\")), J(T(\"Level \", \"Nivel \", \"Nível \"), n.index))\n    c:add(\"mp\", class.mp, class.name)\n    if class.caster then c:add(\"mp\", math.max(0, modifier(c, class.caster)), T(\"Spellcasting\", \"Conjuración\", \"Conjuração\")) end\n\n    -- Class features gained at this class level: cards with buttons (mods). A mod with `target` spends a resource.\n    for _, f in ipairs(cat(\"features\")) do\n      if f.class == class.id and f.level == n.classLevel then\n        local mods = {}\n        if f.mp then mods[#mods + 1] = { label = \"MP\", value = \"-\" .. f.mp, target = \"mp\" } end\n        if f.id == \"sneak-attack\" then\n          local dice = (c.classLevels.rogue + 1) // 2\n          mods[#mods + 1] = { label = T(\"damage\", \"daño\", \"dano\"), value = \"+\" .. dice .. \"d6\" }\n        end\n        c:feature({ item = f, source = class.name, section = \"features\", mods = mods })\n        c.vars[f.id] = true\n      end\n    end\n  end\n\n  -- Talents: one every two levels, in a single choice (so `replaces` works: Mighty Blow removes Power Attack).\n  -- `stack` lets a repeatable talent be picked again; `requires` explains every unmet requirement.\n  local talent_count = c.level // 2\n  if talent_count > 0 then\n    local picks = c.values[\"talents\"]\n    local talents = c:choose({ id = \"talents\", label = J(T(\"Talents\", \"Talentos\", \"Talentos\"), \" (\", talent_count, \")\"), from = \"talents\",\n      count = talent_count, stack = true, section = \"levels\",\n      requires = function(t)\n        local reasons = {}\n        local r = t.requires or {}\n        if r.str and c:get(\"attr:str\") < r.str then reasons[#reasons + 1] = J(T(\"Requires: Strength \", \"Requiere: Fuerza \", \"Requer: Força \"), r.str) end\n        if r.level and c.level < r.level then reasons[#reasons + 1] = J(T(\"Requires: level \", \"Requiere: nivel \", \"Requer: nível \"), r.level) end\n        if r.class and (c.classLevels[r.class] or 0) == 0 then reasons[#reasons + 1] = T(\"Requires: mage\", \"Requiere: mago\", \"Requer: mago\") end\n        for _, other in ipairs(r.talents or {}) do\n          if not contains(type(picks) == \"table\" and picks or {}, other) then\n            reasons[#reasons + 1] = T(\"Requires: Power Attack\", \"Requiere: Ataque poderoso\", \"Requer: Ataque Poderoso\")\n          end\n        end\n        local times = 0\n        for _, x in ipairs(type(picks) == \"table\" and picks or {}) do if x == t.id then times = times + 1 end end\n        if times > 1 and not t.repeatable then reasons[#reasons + 1] = T(\"Only once\", \"Solo una vez\", \"Só uma vez\") end\n        return #reasons == 0, reasons\n      end })\n    local seen = {}\n    for _, t in ipairs(talents) do\n      if t.id == \"toughness\" then c:add(\"hp\", 3, t.name) end\n      if t.id == \"keen-eye\" then c:add(\"skill:perception\", 2, t.name) end\n      if t.id == \"spell-reserve\" then c:add(\"mp\", 2 * (c.classLevels.mage or 0), t.name) end\n      if not seen[t.id] then c:feature({ item = t, source = T(\"Talent\", \"Talento\", \"Talento\"), section = \"features\" }) end\n      seen[t.id] = true\n    end\n  end\n  if ancestry then c:feature({ item = ancestry, source = T(\"Ancestry\", \"Ascendencia\", \"Ancestralidade\"), section = \"features\" }) end\n\n  ------------------------------------------------------------------ Skills\n  -- Trained skills: fixed ones are registered in the pool with c:take, so choices of the same pool show\n  -- them as taken; the others are choices limited to a list.\n  local first = levels[1] and levels[1].class\n  if first then\n    for _, id in ipairs(first.skills.fixed) do c:take(\"skills\", id); c.vars.trained[id] = true end\n    local chosen = c:choose({ id = \"skills:class\", label = J(T(\"Class skills\", \"Habilidades de clase\", \"Perícias da classe\"), \" (\", first.skills.choose, \")\"),\n      from = \"skills\", count = first.skills.choose, multiple = true, pool = \"skills\", section = \"skills\",\n      filter = function(s) return contains(first.skills.from, s.id) end })\n    for _, s in ipairs(chosen) do c.vars.trained[s.id] = true end\n  end\n  if background then c:take(\"skills\", background.skill); c.vars.trained[background.skill] = true end\n  if ancestry and ancestry.versatile then\n    local extra = c:choose({ id = \"skills:versatile\", label = T(\"Versatile: extra skill\", \"Versátil: habilidad extra\", \"Versátil: perícia extra\"),\n      from = \"skills\", pool = \"skills\", section = \"skills\" })\n    if extra then c.vars.trained[extra.id] = true end\n  end\n\n  ------------------------------------------------------------------ Gear (before combat: armor affects Defense)\n  c:section(\"gear\")\n  -- Starting money: a number with a roll button, then multiplied. The player can type another value.\n  local starting = c:number({ id = \"gold:start\", label = T(\"Starting gold (3d6 × 10)\", \"Oro inicial (3d6 × 10)\", \"Ouro inicial (3d6 × 10)\"),\n    roll = \"3d6\", required = c.level >= 1, min = 0 })\n  c:stat({ id = \"gold\", hidden = true })\n  if starting then c:add(\"gold\", starting * 10, T(\"Starting gold\", \"Oro inicial\", \"Ouro inicial\")) end\n  if c.level > 1 then c:add(\"gold\", 100 * (c.level - 1), T(\"Higher level\", \"Nivel superior\", \"Nível acima do 1º\")) end\n  -- Budgets: money (hard: options that don't fit are flagged) and weight (soft: only warns).\n  local offset = c.values[\"gold:offset\"]\n  c:budget({ id = \"gold\", label = T(\"Gold\", \"Oro\", \"Ouro\"), format = gold, total = c:raw(\"gold\") + (type(offset) == \"number\" and offset or 0) })\n  local carry = 3 * c:get(\"attr:str\")\n  local proficient_heavy = c.vars.heavy or (c.classLevels.warrior or 0) > 0\n  local price = function(i) return i.price or 0 end\n  local weight = function(i) return i.weight or 0 end\n\n  local armor = c:choose({ id = \"gear:armor\", label = T(\"Armor\", \"Armadura\", \"Armadura\"), from = \"gear\", optional = true,\n    filter = function(i) return i.kind == \"armor\" end,\n    requires = function(i) return i.armor ~= \"heavy\" or proficient_heavy, T(\"Not proficient: –5 on Dexterity and Strength skills\", \"Sin competencia: –5 en habilidades de Destreza y Fuerza\", \"Sem proficiência: –5 em perícias de Destreza e Força\") end,\n    budgets = { { id = \"gold\", cost = price }, { id = \"weight\", cost = weight } } })\n  local shield = c:choose({ id = \"gear:shield\", label = T(\"Shield\", \"Escudo\", \"Escudo\"), from = \"gear\", optional = true,\n    filter = function(i) return i.kind == \"shield\" end,\n    requires = function() return proficient_heavy, T(\"Not proficient\", \"Sin competencia\", \"Sem proficiência\") end,\n    budgets = { { id = \"gold\", cost = price }, { id = \"weight\", cost = weight } } })\n\n  -- Granted items: the background gives them for free; they leave by themselves if the background changes.\n  local granted_weapons, granted_items = {}, {}\n  for _, g in ipairs(background and background.items or {}) do\n    local item = g.id and cat(\"gear\", g.id)\n    local entry = { id = g.id, name = g.name, qty = g.qty, source = background.name }\n    if item and item.kind == \"weapon\" then granted_weapons[#granted_weapons + 1] = entry else granted_items[#granted_items + 1] = entry end\n  end\n  local weapons = c:choose({ id = \"gear:weapons\", label = T(\"Weapons\", \"Armas\", \"Armas\"), from = \"gear\", count = 5, multiple = true,\n    optional = true, wide = true, granted = granted_weapons,\n    filter = function(i) return i.kind == \"weapon\" end,\n    -- Categories in the picker: a name and an order (simple weapons first).\n    group = function(i)\n      if i.category == \"martial\" then return T(\"Martial weapons\", \"Armas marciales\", \"Armas marciais\"), 2 end\n      return T(\"Simple weapons\", \"Armas sencillas\", \"Armas simples\"), 1\n    end,\n    requires = function(i) return i.category ~= \"martial\" or (c.classLevels.warrior or 0) > 0, T(\"Not proficient: –4 on attacks\", \"Sin competencia: –4 en ataques\", \"Sem proficiência: –4 nos ataques\") end,\n    budgets = { { id = \"gold\", cost = price }, { id = \"weight\", cost = weight, granted = true } } })\n  -- An inventory with quantities (stack) and per-item state (charges, notes), read back with c:state.\n  local items = c:choose({ id = \"gear:items\", label = T(\"Items\", \"Objetos\", \"Itens\"), from = \"gear\", stack = true, optional = true, wide = true,\n    granted = granted_items,\n    filter = function(i) return i.kind == \"item\" end,\n    state = {\n      { id = \"charges\", label = T(\"Charges\", \"Cargas\", \"Cargas\"), type = \"number\" },\n      { id = \"note\", label = T(\"Note\", \"Nota\", \"Anotação\"), type = \"text\" },\n    },\n    budgets = { { id = \"gold\", cost = price }, { id = \"weight\", cost = weight, granted = true } } })\n  for _, i in ipairs(items) do\n    if i.charges then\n      local left = c:state(\"gear:items\", i).charges\n      if left == nil then c:info(J(i.name, \": \", i.charges, T(\" charges (click the item to track them).\", \" cargas (haz clic en el objeto para anotarlas).\", \" cargas (clique no item para anotar).\")), \"gear:items\")\n      elseif left <= 0 then c:issue(\"gear:items\", i.id, T(\"No charges left\", \"Sin cargas\", \"Sem cargas\")) end\n    end\n  end\n  -- The money left: an editable value. The player types the current amount; the difference is kept apart.\n  c:add(\"gold\", -c:spent(\"gold\"), T(\"Purchases\", \"Compras\", \"Compras\"))\n  c:stat({ id = \"gold\", label = T(\"Gold\", \"Oro\", \"Ouro\"), format = gold, editable = true,\n    description = T(\"Purchases are already subtracted. Type your current gold when you spend or find money.\",\n      \"Las compras ya están descontadas. Escribe tu oro actual cuando gastes o encuentres dinero.\",\n      \"As compras já estão descontadas. Digite seu ouro atual quando gastar ou achar dinheiro.\") })\n  c:budget({ id = \"weight\", label = T(\"Load\", \"Carga\", \"Carga\"), total = carry, format = kg, soft = true, show = true, warn = false,\n    description = T(\"Up to 3 × Strength kg. Above that: –3m speed.\", \"Hasta 3 × Fuerza kg. Por encima: –3m de velocidad.\",\n      \"Até 3 × Força kg. Acima disso: –3m de deslocamento.\") })\n  local overloaded = c:spent(\"weight\") > carry\n  if overloaded then c:warn(T(\"Overloaded: –3m speed.\", \"Sobrecargado: –3m de velocidad.\", \"Sobrecarregado: –3m de deslocamento.\"), \"weight\") end\n\n  ------------------------------------------------------------------ Combat\n  c:section(\"combat\")\n  -- Resources: maximum from the computed value with the same id; the current value is stored apart.\n  c:resource({ id = \"hp\", label = T(\"Hit Points\", \"Puntos de Vida\", \"Pontos de Vida\") })\n  c:resource({ id = \"mp\", label = T(\"Mana Points\", \"Puntos de Maná\", \"Pontos de Mana\"), min = 0 })\n  -- Actions that change resources (with undo on the page). The icon comes from the schema's list.\n  c:actions({ id = \"rest\", label = T(\"Rest\", \"Descansar\", \"Descansar\"), icon = \"moon\", wide = true, options = {\n    { id = \"short\", label = T(\"Short rest\", \"Descanso corto\", \"Descanso curto\"),\n      description = T(\"One hour: recover half your level in HP and MP.\", \"Una hora: recupera la mitad de tu nivel en PV y PM.\", \"Uma hora: recupere metade do nível em PV e PM.\"),\n      changes = { hp = math.max(1, c.level // 2), mp = math.max(1, c.level // 2) } },\n    { id = \"long\", label = T(\"Long rest\", \"Descanso largo\", \"Descanso longo\"),\n      description = T(\"A night of sleep: recover everything.\", \"Una noche de sueño: recupera todo.\", \"Uma noite de sono: recupere tudo.\"),\n      changes = { hp = \"full\", mp = \"full\" } },\n  } })\n\n  -- Conditions: a multiple choice whose items carry numeric effects.\n  local conditions = c:choose({ id = \"conditions\", label = T(\"Conditions\", \"Condiciones\", \"Condições\"), from = \"conditions\", count = 3,\n    multiple = true, optional = true, wide = true })\n  local cond = { skills = 0, attack = 0, defense = 0, physical = 0 }\n  for _, x in ipairs(conditions) do\n    -- Same effects don't stack: keep the worst of each kind.\n    for k in pairs(cond) do if x[k] and x[k] < cond[k] then cond[k] = x[k] end end\n  end\n\n  -- Defense: 10 + Dexterity (not with heavy armor) + armor + shield. Each part shows in the breakdown.\n  c:stat({ id = \"defense\", label = T(\"Defense\", \"Defensa\", \"Defesa\"), base = 10,\n    description = T(\"10 + Dexterity + armor + shield.\", \"10 + Destreza + armadura + escudo.\", \"10 + Destreza + armadura + escudo.\") })\n  local heavy = armor and armor.armor == \"heavy\"\n  if not heavy then c:add(\"defense\", modifier(c, \"dex\"), T(\"Dexterity\", \"Destreza\", \"Destreza\")) end\n  if armor then c:add(\"defense\", armor.defense, armor.name) end\n  if shield then c:add(\"defense\", shield.defense, shield.name) end\n  if c.vars.evasion and not heavy then c:add(\"defense\", 2, T(\"Evasion\", \"Evasión\", \"Evasão\")) end\n  c:add(\"defense\", cond.defense, T(\"Conditions\", \"Condiciones\", \"Condições\"))\n\n  c:stat({ id = \"speed\", label = T(\"Speed (m)\", \"Velocidad (m)\", \"Deslocamento (m)\"), base = 9 })\n  if overloaded then c:add(\"speed\", -3, T(\"Overloaded\", \"Sobrecargado\", \"Sobrecarregado\")) end\n  if ancestry and ancestry.senses then c:show({ label = T(\"Senses\", \"Sentidos\", \"Sentidos\"), value = ancestry.senses }) end\n  if ancestry and ancestry.poisonResistance then\n    c:show({ label = T(\"Resistances\", \"Resistencias\", \"Resistências\"), value = J(T(\"poison \", \"veneno \", \"veneno \"), ancestry.poisonResistance) })\n  end\n\n  -- One line per weapon with roll buttons (attack, damage and critical). The roller adds advantage etc.\n  local mastery = c.vars[\"weapon-mastery\"] and 1 or 0\n  for _, w in ipairs(weapons) do\n    local dex = w.finesse or w.ranged\n    local attr = dex and \"dex\" or \"str\"\n    local attack = c.level // 2 + modifier(c, attr) + mastery + cond.attack\n    if w.category == \"martial\" and (c.classLevels.warrior or 0) == 0 then attack = attack - 4 end\n    local bonus = (w.ranged and 0 or modifier(c, \"str\")) + mastery\n    local crit_dice = w.damage:gsub(\"^(%d+)d\", function(n) return tostring(tonumber(n) * w.multiplier) .. \"d\" end)\n    c:show({ label = w.name, wide = true,\n      value = J(T(\"Attack \", \"Ataque \", \"Ataque \"), with_bonus(\"\", attack), \" · \", with_bonus(w.damage, bonus),\n        \" · \", (w.critical < 20 and (w.critical .. \"/\") or \"\"), \"×\", w.multiplier),\n      rolls = {\n        { label = T(\"Attack\", \"Ataque\", \"Ataque\"), dice = with_bonus(\"1d20\", attack) },\n        { label = T(\"Damage\", \"Daño\", \"Dano\"), dice = with_bonus(w.damage, bonus) },\n        { label = T(\"Critical\", \"Crítico\", \"Crítico\"), dice = with_bonus(crit_dice, bonus) },\n      } })\n  end\n  -- A toggle the player switches during play; when on, it offers a +1d4 button for the roller.\n  local inspired = c:toggle({ id = \"inspired\", label = T(\"Inspired\", \"Inspirado\", \"Inspirado\") })\n  if inspired then\n    c:show({ label = T(\"Inspiration\", \"Inspiración\", \"Inspiração\"), value = \"+1d4\",\n      mods = { { label = T(\"any test\", \"cualquier prueba\", \"qualquer teste\"), value = \"+1d4\" } } })\n  end\n  if omen == 6 then c:info(T(\"Lucky charm: +1 on one test per day.\", \"Amuleto: +1 en una prueba por día.\", \"Amuleto: +1 em um teste por dia.\"), \"omen\") end\n\n  ------------------------------------------------------------------ Skills (values)\n  c:section(\"skills\")\n  for _, s in ipairs(cat(\"skills\")) do\n    local id = \"skill:\" .. s.id\n    c:add(id, c.level // 2, T(\"Half level\", \"Mitad del nivel\", \"Metade do nível\"))\n    c:add(id, modifier(c, s.attribute), cat(\"skills\", s.id).attribute:upper())\n    if c.vars.trained[s.id] then c:add(id, 2, T(\"Trained\", \"Entrenada\", \"Treinada\")) end\n    if s.armorPenalty and armor and armor.penalty ~= 0 then c:add(id, armor.penalty, armor.name) end\n    if armor and armor.armor == \"heavy\" and not proficient_heavy and (s.attribute == \"dex\" or s.attribute == \"str\") then\n      c:add(id, -5, T(\"Not proficient\", \"Sin competencia\", \"Sem proficiência\"))\n    end\n    if ancestry and ancestry.skillBonus and ancestry.skillBonus[s.id] then c:add(id, ancestry.skillBonus[s.id], ancestry.name) end\n    local physical = (s.attribute == \"str\" or s.attribute == \"con\") and cond.physical or 0\n    c:add(id, math.min(cond.skills, physical), T(\"Conditions\", \"Condiciones\", \"Condições\"))\n    -- tag (key attribute), marked (trained dot), roll button, and a warning for trained-only skills.\n    c:stat({ id = id, label = s.name, format = \"bonus\", tag = s.attribute:upper(), marked = c.vars.trained[s.id] == true,\n      markHint = c.vars.trained[s.id] and T(\"Trained: +2\", \"Entrenada: +2\", \"Treinada: +2\") or T(\"Untrained\", \"Sin entrenar\", \"Não treinada\"),\n      roll = \"1d20\", description = s.description })\n    if s.trainedOnly and not c.vars.trained[s.id] then\n      c:info(T(\"Only trained characters can use it.\", \"Solo personajes entrenados.\", \"Só personagens treinados podem usar.\"), id)\n    end\n  end\n\n  ------------------------------------------------------------------ Spells\n  local mage = c.classLevels.mage or 0\n  if mage > 0 then\n    local circle = mage >= 5 and 2 or 1\n    local spells = c:choose({ id = \"spells\", label = J(T(\"Known spells\", \"Hechizos conocidos\", \"Magias conhecidas\"), \" (\", mage + 1, \")\"),\n      from = \"spells\", count = mage + 1, multiple = true, section = \"spells\",\n      group = function(s) return J(T(\"Circle \", \"Círculo \", \"Círculo \"), s.circle), s.circle end,\n      filter = function(s) return s.circle <= circle end })\n    for _, s in ipairs(spells) do\n      -- A variable MP button: the player chooses how much to spend (augments), up to the level.\n      local mods = { { label = \"MP\", value = \"-\" .. s.cost, target = \"mp\", variable = true, max = math.max(s.cost, c.level) } }\n      for _, m in ipairs(s.mods or {}) do mods[#mods + 1] = m end\n      c:feature({ item = s, name = J(s.name, \" (\", s.circle, \")\"), source = s.sustained and T(\"sustained\", \"sostenido\", \"sustentada\") or nil,\n        section = \"spells\", mods = mods })\n    end\n    -- format can be a function: the page shows its text.\n    c:stat({ id = \"spell-dc\", label = T(\"Spell DC\", \"CD de hechizos\", \"CD das magias\"), base = 10, section = \"spells\" })\n    c:add(\"spell-dc\", c.level // 2, T(\"Half level\", \"Mitad del nivel\", \"Metade do nível\"))\n    c:add(\"spell-dc\", modifier(c, \"int\"), T(\"Intelligence\", \"Inteligencia\", \"Inteligência\"))\n  end\n\n  ------------------------------------------------------------------ Notes\n  c:text({ id = \"backstory\", label = T(\"Backstory\", \"Historia\", \"História\"), long = true, section = \"notes\" })\n  -- A free-form list with suggestions from a catalog (for things that are not in the catalogs).\n  c:list({ id = \"contacts\", label = T(\"Contacts\", \"Contactos\", \"Contatos\"), section = \"notes\", columns = {\n    { id = \"name\", label = T(\"Name\", \"Nombre\", \"Nome\") },\n    { id = \"where\", label = T(\"Where\", \"Dónde\", \"Onde\") },\n  } })\n\n  ------------------------------------------------------------------ Sheet-level messages\n  if not ancestry then c:info(T(\"Start by choosing an ancestry and leveling up to 1st level.\",\n    \"Empieza eligiendo una ascendencia y subiendo al 1er nivel.\", \"Comece escolhendo a ancestralidade e subindo para o 1º nível.\")) end\n  if c.level > 0 and c:get(\"hp\") <= 0 then c:warn(T(\"No hit points: check Constitution.\", \"Sin puntos de vida: revisa Constitución.\",\n    \"Sem pontos de vida: confira Constituição.\")) end\nend\n"}],"catalogs":{"ancestries":[{"id":"human","name":{"en":"Human","es":"Humano","pt":"Humano"},"description":{"en":"Adaptable and ambitious.\n\n> **Versatile:** +1 to one attribute and one extra trained skill.","es":"Adaptable y ambicioso.\n\n> **Versátil:** +1 en un atributo y una habilidad entrenada extra.","pt":"Adaptável e ambicioso.\n\n> **Versátil:** +1 em um atributo e uma perícia treinada extra."},"versatile":true},{"id":"dwarf","name":{"en":"Dwarf","es":"Enano","pt":"Anão"},"description":{"en":"Stout folk of stone halls.\n\n> **Constitution +2.** Darkvision. Resistance to poison 5.","es":"Pueblo robusto de salones de piedra.\n\n> **Constitución +2.** Visión en la oscuridad. Resistencia a veneno 5.","pt":"Povo robusto de salões de pedra.\n\n> **Constituição +2.** Visão no escuro. Resistência a veneno 5."},"bonus":{"con":2},"senses":{"en":"darkvision","es":"visión en la oscuridad","pt":"visão no escuro"},"poisonResistance":5},{"id":"elf","name":{"en":"Elf","es":"Elfo","pt":"Elfo"},"description":{"en":"Graceful and keen-eyed.\n\n> **Dexterity +2.** +2 in Perception.","es":"Grácil y de vista aguda.\n\n> **Destreza +2.** +2 en Percepción.","pt":"Gracioso e de olhar aguçado.\n\n> **Destreza +2.** +2 em Percepção."},"bonus":{"dex":2},"skillBonus":{"perception":2}}],"backgrounds":[{"id":"soldier","name":{"en":"Soldier","es":"Soldado","pt":"Soldado"},"description":{"en":"You served in an army.\n\n> **Skill:** Athletics. **Items:** a spear, a uniform.","es":"Serviste en un ejército.\n\n> **Habilidad:** Atletismo. **Objetos:** una lanza, un uniforme.","pt":"Você serviu num exército.\n\n> **Perícia:** Atletismo. **Itens:** uma lança, um uniforme."},"skill":"athletics","items":[{"id":"spear"},{"name":{"en":"Uniform","es":"Uniforme","pt":"Uniforme"}}]},{"id":"scholar","name":{"en":"Scholar","es":"Erudito","pt":"Estudioso"},"description":{"en":"You studied in a great library.\n\n> **Skill:** Lore. **Items:** a book, ink and a quill.","es":"Estudiaste en una gran biblioteca.\n\n> **Habilidad:** Saber. **Objetos:** un libro, tinta y una pluma.","pt":"Você estudou numa grande biblioteca.\n\n> **Perícia:** Conhecimento. **Itens:** um livro, tinta e pena."},"skill":"lore","items":[{"name":{"en":"Book","es":"Libro","pt":"Livro"}},{"name":{"en":"Ink and quill","es":"Tinta y pluma","pt":"Tinta e pena"}}]},{"id":"wanderer","name":{"en":"Wanderer","es":"Vagabundo","pt":"Andarilho"},"description":{"en":"The road is your home.\n\n> **Skill:** Survival. **Items:** a bedroll, rope, 3 rations.","es":"El camino es tu hogar.\n\n> **Habilidad:** Supervivencia. **Objetos:** un saco de dormir, cuerda, 3 raciones.","pt":"A estrada é a sua casa.\n\n> **Perícia:** Sobrevivência. **Itens:** saco de dormir, corda, 3 rações."},"skill":"survival","items":[{"id":"bedroll"},{"id":"rope"},{"id":"ration","qty":3}]}],"classes":[{"id":"warrior","name":{"en":"Warrior","es":"Guerrero","pt":"Guerreiro"},"description":{"en":"Master of weapons and armor.\n\n> **HP:** 12 + Con at 1st level, 4 + Con per level. **MP:** 2 per level.\n> **Skills:** Athletics and 1 more. **Proficiency:** heavy armor and shields.","es":"Maestro de armas y armaduras.\n\n> **PV:** 12 + Con en el 1er nivel, 4 + Con por nivel. **PM:** 2 por nivel.\n> **Habilidades:** Atletismo y 1 más. **Competencia:** armaduras pesadas y escudos.","pt":"Mestre das armas e armaduras.\n\n> **PV:** 12 + Con no 1º nível, 4 + Con por nível. **PM:** 2 por nível.\n> **Perícias:** Atletismo e mais 1. **Proficiência:** armaduras pesadas e escudos."},"hp":12,"hpPerLevel":4,"mp":2,"skills":{"fixed":["athletics"],"choose":1,"from":["perception","survival","persuasion"]},"heavyArmor":true},{"id":"rogue","name":{"en":"Rogue","es":"Pícaro","pt":"Ladino"},"description":{"en":"Quick, sneaky and lucky.\n\n> **HP:** 8 + Con at 1st level, 3 + Con per level. **MP:** 3 per level.\n> **Skills:** Stealth and 2 more.","es":"Rápido, sigiloso y afortunado.\n\n> **PV:** 8 + Con en el 1er nivel, 3 + Con por nivel. **PM:** 3 por nivel.\n> **Habilidades:** Sigilo y 2 más.","pt":"Rápido, furtivo e sortudo.\n\n> **PV:** 8 + Con no 1º nível, 3 + Con por nível. **PM:** 3 por nível.\n> **Perícias:** Furtividade e mais 2."},"hp":8,"hpPerLevel":3,"mp":3,"skills":{"fixed":["stealth"],"choose":2,"from":["athletics","perception","lore","survival","persuasion"]}},{"id":"mage","name":{"en":"Mage","es":"Mago","pt":"Mago"},"description":{"en":"Scholar of arcane spells.\n\n> **HP:** 6 + Con at 1st level, 2 + Con per level. **MP:** 5 + Int per level.\n> **Skills:** Lore and 1 more. **Spells:** 2 at 1st level, +1 per level; circle 2 from 5th level.","es":"Erudito de los hechizos arcanos.\n\n> **PV:** 6 + Con en el 1er nivel, 2 + Con por nivel. **PM:** 5 + Int por nivel.\n> **Habilidades:** Saber y 1 más. **Hechizos:** 2 en el 1er nivel, +1 por nivel; círculo 2 desde el 5º nivel.","pt":"Estudioso das magias arcanas.\n\n> **PV:** 6 + Con no 1º nível, 2 + Con por nível. **PM:** 5 + Int por nível.\n> **Perícias:** Conhecimento e mais 1. **Magias:** 2 no 1º nível, +1 por nível; 2º círculo a partir do 5º nível."},"hp":6,"hpPerLevel":2,"mp":5,"caster":"int","skills":{"fixed":["lore"],"choose":1,"from":["perception","persuasion"]}}],"conditions":[{"id":"frightened","name":{"en":"Frightened","es":"Asustado","pt":"Amedrontado"},"description":{"en":"–2 on all skill tests and attacks.","es":"–2 en todas las pruebas y ataques.","pt":"–2 em todos os testes de perícia e ataques."},"skills":-2,"attack":-2},{"id":"prone","name":{"en":"Prone","es":"Derribado","pt":"Caído"},"description":{"en":"–4 on melee attacks and –2 Defense.","es":"–4 en ataques cuerpo a cuerpo y –2 a la Defensa.","pt":"–4 em ataques corpo a corpo e –2 na Defesa."},"attack":-4,"defense":-2},{"id":"poisoned","name":{"en":"Poisoned","es":"Envenenado","pt":"Envenenado"},"description":{"en":"–2 on Constitution and Strength skills.","es":"–2 en habilidades de Constitución y Fuerza.","pt":"–2 em perícias de Constituição e Força."},"physical":-2}],"features":[{"id":"second-wind","class":"warrior","level":1,"icon":"heart-pulse","name":{"en":"Second Wind","es":"Segundo aliento","pt":"Fôlego Extra"},"description":{"en":"Once per scene, spend 2 MP to recover 1d10 + level HP.","es":"Una vez por escena, gasta 2 PM para recuperar 1d10 + nivel PV.","pt":"Uma vez por cena, gaste 2 PM para recuperar 1d10 + nível PV."},"mp":2},{"id":"weapon-mastery","class":"warrior","level":3,"icon":"swords","name":{"en":"Weapon Mastery","es":"Maestría con armas","pt":"Maestria em Armas"},"description":{"en":"+1 on attack and damage rolls with weapons.","es":"+1 en tiradas de ataque y daño con armas.","pt":"+1 nas rolagens de ataque e dano com armas."},"attackBonus":1},{"id":"sneak-attack","class":"rogue","level":1,"icon":"crosshair","name":{"en":"Sneak Attack","es":"Ataque furtivo","pt":"Ataque Furtivo"},"description":{"en":"When the target is flanked or unaware, deal extra damage: 1d6, +1d6 every two levels.","es":"Cuando el objetivo está flanqueado o desprevenido, causas daño extra: 1d6, +1d6 cada dos niveles.","pt":"Quando o alvo está flanqueado ou desprevenido, cause dano extra: 1d6, +1d6 a cada dois níveis."}},{"id":"evasion","class":"rogue","level":3,"icon":"wind","name":{"en":"Evasion","es":"Evasión","pt":"Evasão"},"description":{"en":"+2 Defense when not wearing heavy armor.","es":"+2 a la Defensa sin armadura pesada.","pt":"+2 na Defesa sem armadura pesada."}},{"id":"arcane-focus","class":"mage","level":1,"icon":"magic","name":{"en":"Arcane Focus","es":"Foco arcano","pt":"Foco Arcano"},"description":{"en":"Your spells use Intelligence. Spell DC: 10 + half level + Int.","es":"Tus hechizos usan Inteligencia. CD de hechizos: 10 + mitad del nivel + Int.","pt":"Suas magias usam Inteligência. CD das magias: 10 + metade do nível + Int."}}],"gear":[{"id":"dagger","kind":"weapon","category":"simple","name":{"en":"Dagger","es":"Daga","pt":"Adaga"},"price":2,"weight":0.5,"damage":"1d4","critical":19,"multiplier":2,"finesse":true,"description":{"en":"Light and easy to hide. Uses Dexterity on attacks.","es":"Ligera y fácil de esconder. Usa Destreza en ataques.","pt":"Leve e fácil de esconder. Usa Destreza nos ataques."}},{"id":"spear","kind":"weapon","category":"simple","name":{"en":"Spear","es":"Lanza","pt":"Lança"},"price":2,"weight":1.5,"damage":"1d6","critical":20,"multiplier":3,"description":{"en":"A simple pole with a sharp tip.","es":"Un asta simple con punta afilada.","pt":"Uma haste simples com ponta afiada."}},{"id":"longsword","kind":"weapon","category":"martial","name":{"en":"Longsword","es":"Espada larga","pt":"Espada Longa"},"price":15,"weight":2,"damage":"1d8","critical":19,"multiplier":2,"description":{"en":"The classic knight's blade.","es":"La clásica hoja del caballero.","pt":"A clássica lâmina do cavaleiro."}},{"id":"greataxe","kind":"weapon","category":"martial","name":{"en":"Greataxe","es":"Gran hacha","pt":"Machado Grande"},"price":20,"weight":4,"damage":"1d12","critical":20,"multiplier":3,"description":{"en":"Two-handed and brutal.","es":"A dos manos y brutal.","pt":"De duas mãos e brutal."}},{"id":"shortbow","kind":"weapon","category":"simple","ranged":true,"name":{"en":"Shortbow","es":"Arco corto","pt":"Arco Curto"},"price":25,"weight":1,"damage":"1d6","critical":20,"multiplier":3,"description":{"en":"Ranged. Uses Dexterity on attacks.","es":"A distancia. Usa Destreza en ataques.","pt":"À distância. Usa Destreza nos ataques."}},{"id":"leather","kind":"armor","armor":"light","name":{"en":"Leather Armor","es":"Armadura de cuero","pt":"Armadura de Couro"},"price":10,"weight":5,"defense":2,"penalty":0,"description":{"en":"Light armor.","es":"Armadura ligera.","pt":"Armadura leve."}},{"id":"chainmail","kind":"armor","armor":"heavy","name":{"en":"Chainmail","es":"Cota de malla","pt":"Cota de Malha"},"price":60,"weight":15,"defense":5,"penalty":-2,"description":{"en":"Heavy armor: no Dexterity on Defense and –2 on Stealth. Requires proficiency.","es":"Armadura pesada: sin Destreza en la Defensa y –2 en Sigilo. Requiere competencia.","pt":"Armadura pesada: sem Destreza na Defesa e –2 em Furtividade. Exige proficiência."}},{"id":"shield","kind":"shield","name":{"en":"Shield","es":"Escudo","pt":"Escudo"},"price":10,"weight":3,"defense":2,"description":{"en":"+2 Defense. Requires proficiency.","es":"+2 a la Defensa. Requiere competencia.","pt":"+2 na Defesa. Exige proficiência."}},{"id":"rope","kind":"item","name":{"en":"Rope (10m)","es":"Cuerda (10m)","pt":"Corda (10m)"},"price":1,"weight":1,"description":{"en":"Strong hemp rope.","es":"Cuerda resistente de cáñamo.","pt":"Corda resistente de cânhamo."}},{"id":"bedroll","kind":"item","name":{"en":"Bedroll","es":"Saco de dormir","pt":"Saco de Dormir"},"price":1,"weight":2.5,"description":{"en":"Sleep in the open without a bad rest.","es":"Duerme a la intemperie sin mal descanso.","pt":"Durma ao relento sem descanso ruim."}},{"id":"torch","kind":"item","name":{"en":"Torch","es":"Antorcha","pt":"Tocha"},"price":0.1,"weight":0.5,"description":{"en":"Burns for one hour.","es":"Arde durante una hora.","pt":"Queima por uma hora."}},{"id":"ration","kind":"item","name":{"en":"Ration","es":"Ración","pt":"Ração"},"price":0.5,"weight":0.5,"description":{"en":"Food for one day.","es":"Comida para un día.","pt":"Comida para um dia."}},{"id":"healing-potion","kind":"item","magic":true,"name":{"en":"Healing Potion","es":"Poción de curación","pt":"Poção de Cura"},"price":50,"weight":0.5,"description":{"en":"Drink to recover 2d8+2 HP.","es":"Bébela para recuperar 2d8+2 PV.","pt":"Beba para recuperar 2d8+2 PV."}},{"id":"wand-of-sparks","kind":"item","magic":true,"charges":10,"name":{"en":"Wand of Sparks","es":"Varita de chispas","pt":"Varinha de Faíscas"},"price":200,"weight":0.5,"description":{"en":"Spend a charge to cast Magic Missile. 10 charges.","es":"Gasta una carga para lanzar Proyectil mágico. 10 cargas.","pt":"Gaste uma carga para lançar Míssil Mágico. 10 cargas."}}],"skills":[{"id":"athletics","name":{"en":"Athletics","es":"Atletismo","pt":"Atletismo"},"attribute":"str","description":{"en":"Climb, swim, jump and push.","es":"Trepar, nadar, saltar y empujar.","pt":"Escalar, nadar, saltar e empurrar."}},{"id":"stealth","name":{"en":"Stealth","es":"Sigilo","pt":"Furtividade"},"attribute":"dex","armorPenalty":true,"description":{"en":"Move unseen and unheard.","es":"Moverse sin ser visto ni oído.","pt":"Mover-se sem ser visto nem ouvido."}},{"id":"perception","name":{"en":"Perception","es":"Percepción","pt":"Percepção"},"attribute":"int","description":{"en":"Notice hidden things and danger.","es":"Notar cosas ocultas y peligros.","pt":"Notar coisas escondidas e perigos."}},{"id":"lore","name":{"en":"Lore","es":"Saber","pt":"Conhecimento"},"attribute":"int","trainedOnly":true,"description":{"en":"History, magic and legends. Only trained characters can use it.","es":"Historia, magia y leyendas. Solo personajes entrenados pueden usarla.","pt":"História, magia e lendas. Só personagens treinados podem usar."}},{"id":"survival","name":{"en":"Survival","es":"Supervivencia","pt":"Sobrevivência"},"attribute":"con","description":{"en":"Track, forage and endure the wild.","es":"Rastrear, buscar comida y resistir en la naturaleza.","pt":"Rastrear, coletar comida e resistir na natureza."}},{"id":"persuasion","name":{"en":"Persuasion","es":"Persuasión","pt":"Persuasão"},"attribute":"int","description":{"en":"Convince, negotiate and charm.","es":"Convencer, negociar y encantar.","pt":"Convencer, negociar e encantar."}}],"spells":[{"id":"magic-missile","circle":1,"cost":1,"name":{"en":"Magic Missile","es":"Proyectil mágico","pt":"Míssil Mágico"},"description":{"en":"Range medium. Deals 1d4+1 force damage, never misses.\n\n**Augment:** +1 MP for one more missile.","es":"Alcance medio. Causa 1d4+1 de daño de fuerza, nunca falla.\n\n**Mejora:** +1 PM por un proyectil más.","pt":"Alcance médio. Causa 1d4+1 de dano de força, nunca erra.\n\n**Aprimoramento:** +1 PM para mais um míssil."},"mods":[{"label":{"en":"damage","es":"daño","pt":"dano"},"value":"+1d4+1"}]},{"id":"shield","circle":1,"cost":1,"name":{"en":"Shield","es":"Escudo","pt":"Escudo Arcano"},"description":{"en":"Reaction. +4 Defense until your next turn.","es":"Reacción. +4 a la Defensa hasta tu próximo turno.","pt":"Reação. +4 na Defesa até o seu próximo turno."},"mods":[{"label":{"en":"Defense","es":"Defensa","pt":"Defesa"},"value":"+4"}]},{"id":"light","circle":1,"cost":1,"name":{"en":"Light","es":"Luz","pt":"Luz"},"description":{"en":"An object shines like a torch for one scene.","es":"Un objeto brilla como una antorcha durante una escena.","pt":"Um objeto brilha como uma tocha por uma cena."}},{"id":"sleep","circle":1,"cost":1,"sustained":true,"name":{"en":"Sleep","es":"Sueño","pt":"Sono"},"description":{"en":"Sustained. Creatures in a small area fall asleep (Will negates).","es":"Sostenido. Las criaturas en un área pequeña se duermen (Voluntad anula).","pt":"Sustentada. Criaturas numa área pequena adormecem (Vontade anula)."}},{"id":"fireball","circle":2,"cost":3,"name":{"en":"Fireball","es":"Bola de fuego","pt":"Bola de Fogo"},"description":{"en":"Range long. 6d6 fire damage in a 6m radius (Reflex halves).\n\n**Augment:** +1 MP for +1d6.","es":"Alcance largo. 6d6 de daño de fuego en un radio de 6m (Reflejos reduce a la mitad).\n\n**Mejora:** +1 PM por +1d6.","pt":"Alcance longo. 6d6 de dano de fogo num raio de 6m (Reflexos reduz à metade).\n\n**Aprimoramento:** +1 PM para +1d6."}},{"id":"invisibility","circle":2,"cost":3,"sustained":true,"name":{"en":"Invisibility","es":"Invisibilidad","pt":"Invisibilidade"},"description":{"en":"Sustained. A creature becomes invisible until it attacks.","es":"Sostenido. Una criatura se vuelve invisible hasta que ataca.","pt":"Sustentada. Uma criatura fica invisível até atacar."}}],"talents":[{"id":"toughness","name":{"en":"Toughness","es":"Dureza","pt":"Vigor"},"description":{"en":"+3 HP. You can take this talent many times.","es":"+3 PV. Puedes elegir este talento varias veces.","pt":"+3 PV. Você pode escolher este talento várias vezes."},"repeatable":true,"icon":"heart"},{"id":"keen-eye","name":{"en":"Keen Eye","es":"Ojo agudo","pt":"Olhar Atento"},"description":{"en":"+2 in Perception.","es":"+2 en Percepción.","pt":"+2 em Percepção."},"icon":"eye"},{"id":"power-attack","name":{"en":"Power Attack","es":"Ataque poderoso","pt":"Ataque Poderoso"},"description":{"en":"Before attacking, take –2 on the attack for +4 damage.","es":"Antes de atacar, recibe –2 al ataque para +4 de daño.","pt":"Antes de atacar, sofra –2 no ataque para +4 no dano."},"requires":{"str":13},"mods":[{"label":{"en":"attack","es":"ataque","pt":"ataque"},"value":"-2"},{"label":{"en":"damage","es":"daño","pt":"dano"},"value":"+4"}],"icon":"axe"},{"id":"mighty-blow","name":{"en":"Mighty Blow","es":"Golpe devastador","pt":"Golpe Devastador"},"description":{"en":"Improved Power Attack: –2 on the attack for +8 damage. It replaces Power Attack.","es":"Ataque poderoso mejorado: –2 al ataque para +8 de daño. Reemplaza a Ataque poderoso.","pt":"Ataque Poderoso aprimorado: –2 no ataque para +8 no dano. Substitui Ataque Poderoso."},"requires":{"str":15,"talents":["power-attack"],"level":4},"replaces":"power-attack","mods":[{"label":{"en":"attack","es":"ataque","pt":"ataque"},"value":"-2"},{"label":{"en":"damage","es":"daño","pt":"dano"},"value":"+8"}],"icon":"hammer"},{"id":"spell-reserve","name":{"en":"Spell Reserve","es":"Reserva arcana","pt":"Reserva Arcana"},"description":{"en":"+2 MP per mage level.","es":"+2 PM por nivel de mago.","pt":"+2 PM por nível de mago."},"requires":{"class":"mage"},"icon":"sparkles"},{"id":"lucky","name":{"en":"Lucky","es":"Afortunado","pt":"Sortudo"},"description":{"en":"Once per day, roll a test twice and keep the best (use Advantage in the dice roller).","es":"Una vez al día, tira una prueba dos veces y quédate con el mejor (usa Ventaja en el lanzador).","pt":"Uma vez por dia, role um teste duas vezes e fique com o melhor (use Vantagem no rolador)."},"icon":"star"}]}}