# Tabelas da sala

> Páginas para a mesa toda, abertas como aba para todos: uma lista de NPCs, a iniciativa, um calendário. Como declarar, quem escreve e um exemplo comentado.

Página: https://docs.rpgdesk.com/fichas/tabelas/

Uma **tabela da sala** é uma página como a ficha, com duas diferenças:

- há **uma por mesa**, e ela fica aberta para todos, como uma aba;
- **só os mestres escrevem**; os jogadores veem.

Servem para o que é da mesa, não de um personagem: os NPCs da campanha, um calendário, o mapa de viagem, a reputação das facções.

## Declarar

No manifesto, troque `"sheets"` por `"tables"`:

```json
"tables": [{ "type": "com.seunome.sistema.npcs", "title": "NPCs" }]
```

Um arquivo `.html` único traz uma ficha **ou** uma tabela. Um [pacote](https://docs.rpgdesk.com/fichas/pacotes/) pode trazer as duas coisas, com um HTML para cada.

## Na mesa

1. Instale o plugin em **Configurações da mesa → Plugins**.
2. No grupo **Tabelas de…**, embaixo do plugin, clique em **Ativar**.
3. A tabela abre para todos como uma aba que não fica à vista, junto das outras tabelas (ou no último espaço usado): clique no nome dela para vê-la.

Desativar fecha a tabela para todos e guarda os dados: ativar de novo traz tudo como estava.

## No código

- `kind` é `'table'`, e `item.ownerId` é `null` (a tabela não tem dono).
- O `private` do manifesto não vale nas tabelas: esconda as partes com `doc.restrict` (veja [Partes privadas](https://docs.rpgdesk.com/fichas/partes-privadas/#nas-tabelas-docrestrict)).
- Os controles do mestre ficam com `data-role="gm"`: para os jogadores, os campos já ficam travados sozinhos, mas os botões de criar e apagar somem.
- Para mexer no cartão de um jogador, diga de quem: `RPGDesk.card.setBar(0, 7, 12, { userId })`, com o `id` de `await RPGDesk.room.players()`.

## Exemplo: a lista de NPCs

*Exemplo funcionando:* [NPCs da mesa](https://docs.rpgdesk.com/exemplos/tabela-npcs.html)

O exemplo é uma lista em que cada NPC tem nome, PV, iniciativa, notas e um botão de rolar a iniciativa, tudo com atributos no HTML. O JavaScript faz duas coisas:

```js
RPGDesk.connect().then(({ doc, me }) => {
  const npcs = doc.list('npcs');
  const vazio = document.getElementById('vazio');
  // "Nenhum NPC ainda." some quando a lista tem itens
  npcs.watch((itens) => { vazio.hidden = itens.length > 0; }, { now: true });
  if (me.role !== 'gm') return;
  // "Oculto dos jogadores": o NPC passa a ser só dos mestres
  const visto = new Map();
  npcs.watch((itens, { local }) => {
    for (const npc of itens) {
      const oculto = npc.oculto === true;
      if (visto.get(npc.id) === oculto) continue;
      visto.set(npc.id, oculto);
      if (local) doc.restrict(['npcs', '#' + npc.id], oculto ? 'gm' : null);
    }
  }, { now: true });
});
```

- Só o navegador do mestre que marcou a caixa (`local`) chama o `restrict`: os outros mestres com a tabela aberta não repetem o pedido.
- O NPC oculto some de verdade para os jogadores: o servidor nem manda.

> **Dica**
>
> No modo de teste, a tabela abre com o papel **Mestre**. Troque para **Outro jogador** na faixa para ver como os jogadores veem.
