Integre Dice Core e Dice View

Resolva regras no Core e apresente dados genéricos, sistemas e journals sem mudar os resultados.

Este artigo documenta a V2 publicada. Para a prévia atual com física, veja o guia V3. V3 ↗ Licenças ↗

O Core interpreta notação, sorteia e aplica regras. O View recebe faces físicas prontas. Mantenha o total, os modificadores e a explicação das regras na UI; o palco 3D mostra os dados, inclusive os descartados.

Rolagem genérica

import { rollRpgDice } from '@erpg/dicecore'
import { type DiceSides } from '@erpg/dice3dview/external'

const supported = new Set<number>([2, 4, 6, 8, 10, 12, 20, 100])
const roll = rollRpgDice('4d6kh3+2', { seed: 'atributo-42' })

const dice = roll.dice.flatMap(die => typeof die.sides === 'number' && supported.has(die.sides)
  ? [{
      id: die.id,
      sides: die.sides as DiceSides,
      value: die.value,
      discarded: !die.included
    }]
  : [])

if (dice.length) await viewer.display({ id: 'atributo-42', dice })
showTotal(roll.total)

viewer é uma instância criada como no começo rápido; showTotal representa a UI da sua aplicação. O filtro é necessário porque o Core aceita formatos sem geometria 3D nativa. O modificador +2 participa do total, mas não vira um dado. Para efeitos que mudam o valor sem corresponder a uma face física, como compound, prefira o journal em displayTimeline(). Experimente 4d6kh3+2.

Rolagens mistas

rollMixedDice() entrega uma lista achatada. O adaptador puro do View preserva ordem e faces físicas, aplica temas simbólicos por profileId e omite dados genéricos sem geometria por padrão.

import { rollMixedDice } from '@erpg/dicecore'
import { createMixedDisplayRequest } from '@erpg/dice3dview/adapters'

const mixed = rollMixedDice('2d20+5; v5(7,3,4); fate(4)', {
  seed: 'sessao-42'
})

await viewer.display(createMixedDisplayRequest({
  id: 'misto-42',
  seed: 'sessao-42',
  dice: mixed.dice,
  unsupportedDice: 'omit',
  mode: 'physics'
}))

Use unsupportedDice: 'error' quando omissões não forem aceitáveis. O adaptador usa physicalValue, depois rawValue e então value. Um d3 genérico é exibido como d6 com face 1–3; o dF genérico é omitido. Para Fate com faces 3D, use fate() na notação mista. Experimente a mistura.

Sistemas com perfis visuais

O adaptador createSystemDisplayRequest() valida profileId, lados e face. Use-o com a lista dice dos sistemas do Core:

import { rollVampireV5 } from '@erpg/dicecore'
import { createSystemDisplayRequest } from '@erpg/dice3dview/adapters'

const roll = rollVampireV5(
  { pool: 7, hunger: 3, difficulty: 4 },
  { seed: 'v5-42' }
)

await viewer.display(createSystemDisplayRequest({
  id: 'v5-42',
  dice: roll.dice
}))

Os perfis incluídos cobrem Vampiro V5, Assimilação, Fate e os dados de Esperança/Medo de Daggerheart. Em Assimilação, passe keptIds: selection.selectedIds após evaluateAssimilationSelection(); IDs sem seleção são exibidos como descartados. Veja a tabela de perfis.

Journal de eventos

Quando o Core fornece roll.events, displayTimeline() apresenta explosões, rerolls, descartes e classificações como etapas visuais. Passe apenas dados com geometria suportada e eventos correspondentes; não filtre eventos isoladamente se isso deixar referências para dados removidos.

const journalRoll = rollRpgDice('4d6kh3+2')
const result = await viewer.displayTimeline({
  id: 'journal-42',
  dice: journalRoll.dice.map(die => ({
    id: die.id,
    sides: die.sides as DiceSides
  })),
  events: journalRoll.events.filter(event => event.subject === 'die')
})

console.log(result.eventCount, result.phaseCount, result.degraded)

Esse exemplo pressupõe que todos os dados do journal usam lados aceitos pelo View. Leia Timeline semântica para contratos, orçamento e progresso.