Pular para o conteúdo

JavaScript na ficha

Quando os atributos no HTML não bastam (uma conta, um botão especial, uma regra do seu sistema), o JavaScript entra. Tudo passa pelo objeto RPGDesk, que o rpgdesk.js cria. A lista completa das funções está em A API do rpgdesk.js.

RPGDesk.connect().then(({ doc, me, item, room, kind, language, test }) => {
// tudo o que usa o documento começa aqui
});

RPGDesk.connect() espera a conexão com o RPG Desk (ou com o modo de teste) e devolve o contexto:

Campo O que é
doc o documento da ficha (veja abaixo)
me quem está vendo: { id, nick, role, isOwner }. role é 'gm', 'player' ou 'spectator'
item a ficha: { id, name, type, ownerId }
room a mesa: { id, name, system }
kind 'sheet' (ficha) ou 'table' (tabela da sala)
language 'pt' ou 'en', a língua do RPG Desk de quem está vendo
test true no modo de teste, fora do RPG Desk
plugin { id, version } do seu plugin

Pode chamar RPGDesk.connect() quantas vezes quiser: é sempre a mesma conexão. Depois de conectado, RPGDesk.context e RPGDesk.doc também dão o contexto e o documento.

doc.get('nome'); // 'Aria'
doc.get('pv'); // { atual: 18, max: 22 } (um grupo vira objeto)
doc.get('nao_existe'); // undefined
await doc.set('nivel', 4); // grava um campo
await doc.set('pv', { atual: 10, max: 12 }); // grava campo a campo (o que não veio fica)
await doc.set('anotacoes', null); // apaga
await doc.update({ 'pv.atual': 3, 'pv.max': 10 }); // vários de uma vez
  • Os valores são textos, números, verdadeiro/falso ou objetos com eles. Listas se gravam pela API de listas (veja abaixo).
  • set e update devolvem uma promessa: a gravação vai ao RPG Desk, que confere a permissão e devolve a mudança em milissegundos.
  • doc.batch(() => { … }) junta várias gravações num lote só, aplicado inteiro ou recusado inteiro.
  • doc.canWrite('pv.atual') diz se a pessoa pode escrever ali.

Uma gravação sem permissão (um jogador escrevendo na ficha de outro) é recusada. Para saber:

doc.on('rejected', (mensagem) => RPGDesk.ui.toast(mensagem, 'error'));
const parar = doc.watch('pv', (pv, { local }) => {
barra.style.width = `${(pv.atual / pv.max) * 100}%`;
}, { now: true });
  • O watch avisa a cada mudança no caminho, ou em qualquer campo dentro dele, venha de quem vier.
  • { now: true } chama a função já, com o valor de agora.
  • local diz se a mudança saiu deste navegador.
  • O watch devolve a função que para de avisar.

Um valor que sai de outros (o modificador de um atributo, a carga total) se calcula com doc.compute:

const mod = (valor) => Math.floor(((Number(valor) || 10) - 10) / 2);
doc.compute('mod_forca', ['forca'], mod);
doc.compute('defesa', ['destreza', 'armadura'], (des, arm) => 10 + mod(des) + (Number(arm) || 0));

doc.compute(alvo, [fontes], função) grava o alvo quando uma fonte muda. Mostre o resultado com data-text ou use nas rolagens (data-roll="1d20 + {mod_forca}").

const inv = doc.list('inventario');
inv.items(); // [{ id: 'i1…', nome: 'Corda', qtd: 1 }, …]
inv.length; // 1
const id = inv.add({ nome: 'Tocha', qtd: 3 }); // no fim; inv.add(valor, 0) põe no começo
await inv.item(id).set('qtd', 2);
await inv.move(id, 0); // muda a posição
await inv.remove(id);
inv.watch((itens) => totalEl.textContent = itens.length, { now: true });
  • Cada item tem um id próprio, que o add devolve na hora.
  • inv.item(id) tem get, set, watch e remove, com os caminhos relativos ao item.
  • Os caminhos também podem ser listas: ['inventario', '#' + id, 'qtd'] é o campo qtd do item id.
RPGDesk.on('players', (jogadores) => { /* entrou ou saiu alguém */ });
RPGDesk.on('me', (me) => { /* o meu papel mudou */ });
RPGDesk.on('language', (lingua) => { /* 'pt' ou 'en' */ });
RPGDesk.on('theme', (cores) => { /* as cores do tema mudaram */ });
RPGDesk.on('library', (itens) => { /* a biblioteca mudou */ });

RPGDesk.on devolve a função que para de ouvir.

Use language para trocar os textos:

const TEXTOS = { pt: { rolar: 'Rolar' }, en: { rolar: 'Roll' } };
RPGDesk.connect().then(({ language }) => {
for (const b of document.querySelectorAll('[data-roll]')) b.textContent = TEXTOS[language].rolar;
});

O nome do plugin e o título da ficha, no manifesto, também aceitam as duas línguas: "title": { "pt": "Personagem", "en": "Character" }. Veja O manifesto.

Um erro no seu código não derruba a mesa: a ficha mostra um aviso com o número de Erros da página, e o painel tem Copiar erros. No modo de teste, os erros aparecem no Registro. Veja Testar e desenvolver.