Como criar um pacote de sistema original completo
Um ZIP instalável com fichas de ator/token funcionais, tipos de item, iniciativa armazenada e três packs originais.
O que o ZIP único do sistema entrega
Monte Complete Example Expedition no Gravewright 0.3.0. É um sistema original funcional: substituições completas de fichas de personagem/NPC em actor.sheet e token.sheet, vigor persistido, tipos de item gear/spell, iniciativa nativa e três packs de compêndio. Não exige módulo instalado separadamente nem complemento de regras no servidor. É um sistema pequeno de ensino, não a implementação completa de um RPG publicado.
O código da ficha reutiliza o pacote de sistema editável, e o JSON original deriva de compêndios de sistema instalados. O guia mostra todos os arquivos funcionais para começar com pasta vazia. O pacote é GPL-3.0-only; os avisos MIT da coleção original derivada permanecem intactos.
1. Crie a pasta e entenda o contrato
Baixar ZIP-fonte completo do sistema
complete-expedition/
manifest.json
main.mjs
styles.css
compendiums/expedition.json
LICENSE.txt
MIT-COMPENDIUM.txt
THIRD_PARTY_NOTICES.txt
README.mdCrie complete-expedition e a subpasta compendiums. Salve os arquivos exatos da seção 5 em UTF-8. Copie LICENSE.txt sem alterações do ZIP. Não substitua essa licença GPL pelo aviso MIT separado. Não exige build npm, app Python nem alteração no host.
O ID example.complete-expedition também é o systemId de cada entrada do catálogo. character e npc correspondem a system.actorTypes; gear e spell correspondem a system.itemTypes. content.compendiums aponta para o arquivo JSON físico. Os tipos instalados permitidos são actor_pack, item_pack e spell_pack; o pack de magia segue a importação de itens, sem acrescentar regras de magia ao core.
2. Empacote, instale e crie a campanha
Na pasta dos fontes, use um Python existente e liste explicitamente os arquivos. Em POSIX, substitua python por python3 ou pelo caminho do ambiente do host. Mantenha o ZIP de saída fora da pasta dos fontes.
Set-Location -LiteralPath ./complete-expedition
python -m json.tool manifest.json
python -m json.tool compendiums/expedition.json
python -m zipfile -c ../complete-expedition-source.zip manifest.json main.mjs styles.css compendiums/expedition.json LICENSE.txt MIT-COMPENDIUM.txt THIRD_PARTY_NOTICES.txt README.md
python -m zipfile -l ../complete-expedition-source.zipComo dono, abra Inside → Sistemas → Instalar sistema → Instalar de ZIP, revise e selecione complete-expedition-source.zip e clique Instalar. Use Sistemas porque o manifesto declara system. O envio local exige confiança explícita, mas não assinatura remota.
Crie campanha descartável e escolha Complete Example Expedition como sistema. Entre como mestre e confira a versão exata 1.0.0 em Gravewright → Extensions → Table modules. Instalar sistema não troca campanhas existentes automaticamente.
Em Atores, crie Character e NPC e abra as duas fichas. O formulário real Example Expedition sheet deve mostrar Stamina, Save e Reload server value. Os controles da janela continuam fornecidos pelo host.
3. Importe e edite o conteúdo original
Abra Compêndios. Em Complete Expedition Library, confira Scouts, Equipment e Signals. Como mestre, leia e importe Harbor Scout, Signal Rope e Blue Glow. Os corpos pertencem a este sistema; a API devolve esses documentos da coleção, sem envelope inventado que exija kind. A importação cria cópias na campanha somente quando solicitada. Reabrir a campanha não importa duplicatas sozinho.
Abra Harbor Scout importado. Seus dados começam com stamina 8, role Watch keeper e combat.initiative 3. Mude Stamina para 17, clique Save, feche e reabra. O valor deve continuar 17; role e combat devem permanecer. A ficha copia os dados existentes e altera somente stamina, enviando version e sheetVersion da mesma leitura. Teste outra sessão com versão antiga; o formulário recarrega no conflito e pede revisão em vez de forçar a gravação.
Crie tokens vinculados e independentes do ator importado. O vinculado grava no ator. O independente usa snapshot, tokenId e sheetVersion próprios. Alterar seu vigor não pode mudar o ator original. Com jogador somente leitura, edição e gravação ficam bloqueadas; confirme que tentativa direta também é rejeitada pelo servidor.
Equipamento e magia são dados originais de item, não automação de regras. O pacote reutiliza a interface de itens do host e não substitui item.sheet por editor incompleto. Um editor completo do pacote pode ser acrescentado depois com o exemplo de superfície de item, após conferir a API alvo.
4. Role iniciativa com o modificador armazenado
Abra uma cena, adicione Harbor Scout ou seu token à iniciativa nativa e use Roll initiative / Rolar iniciativa. O pacote fornece 1d20+@combat.initiative; o ator importado rola 1d20+3, de 4 a 23. O core resolve o caminho numérico do ator ou snapshot e avalia a expressão nativa. Nenhum cálculo específico deriva esse modificador de outro atributo.
Um ator criado do zero não recebe dados do catálogo automaticamente. Sem combat.initiative, o caminho vale 0 e ele rola 1d20. O formulário mostra stamina 10 como valor inicial de interface até salvar. A ficha não expõe edição da iniciativa; para acrescentá-la, implemente campo, validação e gravação com revisões neste pacote. manualInput number descreve iniciativa manual numérica quando aplicável; a fórmula configurada seleciona o modo de rolagem nativo. Não exige provedor externo.
5. Arquivos completos do pacote
manifest.json
{
"id": "example.complete-expedition",
"name": "Complete Example Expedition",
"version": "1.0.0",
"sdk": {
"requires": ">=1.0.0 <2.0.0",
"tested": "1.0.0"
},
"description": "One original system with editable actor/token sheets, initiative and three installed content packs.",
"author": "Gravewright documentation examples",
"license": "GPL-3.0-only",
"entry": "main.mjs",
"system": {
"actorTypes": [
{
"id": "character",
"label": "Character"
},
{
"id": "npc",
"label": "NPC"
}
],
"itemTypes": [
{
"id": "gear",
"label": "Gear"
},
{
"id": "spell",
"label": "Spell"
}
],
"combat": {
"formula": "1d20+@combat.initiative",
"manualInput": "number",
"showRoll": true
}
},
"content": {
"compendiums": [
"compendiums/expedition.json"
]
}
}main.mjs
export default {
start({styles}) { styles.use('styles.css'); },
register({register}) {
const sheet={
mode:'replace',types:['character','npc'],
async mount({root,context,api,signal,onDispose}) {
const doc=root.ownerDocument;
const form=doc.createElement('form');form.className='example-panel';
form.setAttribute('aria-label','Example Expedition sheet');
const title=doc.createElement('h2');
const label=doc.createElement('label');label.textContent='Stamina (0–100)';
const input=doc.createElement('input');input.type='number';input.min='0';input.max='100';
label.append(input);
const saveButton=doc.createElement('button');saveButton.type='submit';saveButton.textContent='Save';
const reloadButton=doc.createElement('button');reloadButton.type='button';reloadButton.textContent='Reload server value';
input.disabled=true;saveButton.disabled=true;reloadButton.disabled=true;
const status=doc.createElement('p');status.setAttribute('role','status');
form.append(title,label,saveButton,reloadButton,status);root.append(form);
let current,dirty=false,pending;
const token=context.tokenId ? {tokenId:context.tokenId} : {};
async function load() {
input.disabled=true;saveButton.disabled=true;reloadButton.disabled=true;
try {
const sheet=await api.actors.sheet(context.actorId,token,{signal});
if(signal.aborted) return;
current=sheet;title.textContent=sheet.name;
input.value=String(sheet.data.stamina ?? 10);
input.disabled=!sheet.canEdit;saveButton.disabled=!sheet.canEdit;
dirty=false;
} finally { if(!signal.aborted) reloadButton.disabled=false; }
}
function save() {
if(pending) return pending;
if(!dirty || !current?.canEdit) return Promise.resolve();
const stamina=Number(input.value);
if(input.value.trim()==='' || !Number.isInteger(stamina) || stamina<0 || stamina>100) {
status.textContent='Enter an integer from 0 to 100.';
return Promise.reject(new Error('Invalid stamina'));
}
const payload={actorId:context.actorId,name:current.name,version:current.version,
sheetVersion:current.sheetVersion,data:{...current.data,stamina},
...(current.tokenId ? {tokenId:current.tokenId} : {})};
const requestId=crypto.randomUUID();
input.disabled=true;saveButton.disabled=true;reloadButton.disabled=true;
pending=(async()=>{
try {
await api.actors.saveSheet(payload,{requestId,signal});
if(signal.aborted) return;
await load();status.textContent='Saved.';
} catch(error) {
if(!signal.aborted) {
if(error.code==='conflict') {
await load();
status.textContent='Conflict: server value loaded. Review it before editing again.';
} else status.textContent=error.code || 'Save failed. Reload before retrying.';
}
throw error;
} finally {
pending=undefined;
if(!signal.aborted){input.disabled=!current?.canEdit;saveButton.disabled=!current?.canEdit;reloadButton.disabled=false;}
}
})();
return pending;
}
input.addEventListener('input',()=>{dirty=true;},{signal});
form.addEventListener('submit',event=>{event.preventDefault();void save().catch(()=>{});},{signal});
reloadButton.addEventListener('click',()=>{
void load().then(()=>{if(!signal.aborted)status.textContent='Server value loaded.';})
.catch(error=>{if(!signal.aborted)status.textContent=error.code||'unavailable';});
},{signal});
root.closest('.gw-window')?.addEventListener('gravewright:sheet-flush',event=>{
if(pending || dirty) event.detail.waitUntil(save());
},{signal});
onDispose(()=>form.remove());
await load();
}
};
register('actor.sheet',sheet);
register('token.sheet',sheet);
},
stop() {}
};styles.css
.gw-module-root[data-module-id="example.complete-expedition"] .example-panel { box-sizing: border-box; padding: var(--space-4); color: var(--text); background: var(--surface); font: 14px/1.5 system-ui, sans-serif; }
.gw-module-root[data-module-id="example.complete-expedition"] .example-panel h2 { font-size: 18px; margin: var(--space-0) var(--space-0) var(--space-3); }
.gw-module-root[data-module-id="example.complete-expedition"] .example-panel label { display: block; margin-bottom: var(--space-3); }
.gw-module-root[data-module-id="example.complete-expedition"] .example-panel input { display: block; max-width: 100%; box-sizing: border-box; }
.gw-module-root[data-module-id="example.complete-expedition"] .example-panel :is(input,button) { font: inherit; color: inherit; background: var(--surface); padding: var(--space-2); margin: var(--space-1) var(--space-2) var(--space-1) var(--space-0); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.gw-module-root[data-module-id="example.complete-expedition"] .example-panel :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gw-module-root[data-module-id="example.complete-expedition"] .example-panel [role=status] { overflow-wrap: anywhere; }compendiums/expedition.json
{
"name": "Complete Expedition Library",
"packs": [
{
"id": "scouts",
"label": "Scouts",
"type": "actor_pack",
"entries": [
{
"id": "harbor-scout",
"name": "Harbor Scout",
"type": "character",
"systemId": "example.complete-expedition",
"data": {
"stamina": 8,
"role": "Watch keeper",
"combat": {
"initiative": 3
}
}
}
]
},
{
"id": "equipment",
"label": "Equipment",
"type": "item_pack",
"entries": [
{
"id": "signal-rope",
"name": "Signal Rope",
"type": "gear",
"systemId": "example.complete-expedition",
"data": {
"length": 12,
"description": "An original training rope with blue knots."
}
}
]
},
{
"id": "signals",
"label": "Signals",
"type": "spell_pack",
"entries": [
{
"id": "blue-glow",
"name": "Blue Glow",
"type": "spell",
"systemId": "example.complete-expedition",
"data": {
"color": "blue",
"duration": 1,
"description": "An original fictional signal, with no host automation."
}
}
]
}
]
}MIT-COMPENDIUM.txt
MIT License
Copyright (c) 2026 Gravewright contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.THIRD_PARTY_NOTICES.txt
Complete Example Expedition notices
main.mjs derives from the Gravewright documentation Example Expedition sheet.
The system package and this derivative sheet are GPL-3.0-only. The complete GPL
license is in LICENSE.txt. Preserve source availability and applicable notices.
compendiums/expedition.json derives from the original Beacon Expedition Library
example in tutorial-compendiums.mjs. Its original content was published under
the MIT License, Copyright (c) 2026 Gravewright contributors. The full original
MIT notice is preserved in MIT-COMPENDIUM.txt. Changes here update systemId and
the collection name and add the original numeric combat.initiative example.
No rulebook, proprietary catalog, licensed game branding or external artwork is
included. Gear and spell entries are original fictional data, without automated
game rules. English interface labels remain those of the demonstrated sheet.README.md
# Complete Example Expedition
Target: Gravewright 0.3.0, SDK 1.x. Package ID: example.complete-expedition.
This single system ZIP provides working actor/token sheet replacements, character
and NPC actor types, gear and spell item types, native initiative configuration,
and actor_pack/item_pack/spell_pack content in compendiums/expedition.json.
As owner, review and install through Systems, Install system, Install from ZIP.
Create a disposable campaign with Complete Example Expedition as its system.
As GM, open Compendiums and import Harbor Scout, Signal Rope and Blue Glow.
The imported actor has stamina 8 and combat.initiative 3. Open its sheet, save
Stamina 17, close and reopen. Add it or a token to a scene's initiative tracker
and roll initiative: 1d20+3 yields 4 to 23. A new empty character has no stored
initiative modifier, so the native resolver uses zero. The displayed stamina
default of 10 is only a form default until saved. No derived game rules run.
Linked token sheets share actor data; independent tokens use their snapshots.
Item/spell content imports through native items; this package does not provide
a custom item editor, spell rules or equipment automation. Languages use the
separate installation-wide language-package workflow, not system.locales.
For changes, increment version, build a new ZIP, install it and explicitly select
the new release. Never replace installed bytes. Imported documents remain copies.
See THIRD_PARTY_NOTICES.txt, MIT-COMPENDIUM.txt and LICENSE.txt before reuse.LICENSE.txt
Copie a GNU GPL versão 3 completa e sem alterações incluída no ZIP. O aviso MIT separado dos fontes JSON está reproduzido em MIT-COMPENDIUM.txt acima e deve permanecer com a coleção derivada.
6. Confira atualização, idioma e desativação
Mantenha ID do sistema e IDs dos packs/entradas estáveis. Para alterar, aumente version para 1.0.1, gere o ZIP, instale em Sistemas e selecione a release exata da campanha. Teste personagens antigos, os dois modos de token, vigor salvo e iniciativa. Documentos importados são cópias e não são reescritos pelo catálogo atualizado. Não edite arquivos instalados nem troque bytes na mesma versão.
Idioma usa pacote global e preferência por conta; não acrescente locales ao manifesto do sistema. Siga separadamente o tutorial de idioma. Feche durante gravação, teste rascunhos inválidos e antigos, desative ou troque o sistema somente em campanha descartável e confira liberação de recursos e documentos preservados. Sem ficha compatível ativa, documentos podem ficar sem editor útil até reativar; desativação não migra dados.
Como usar a IA para ampliar este sistema completo
Amplie o pacote completo example.complete-expedition no Gravewright 0.3.0 com [uma regra ou campo original]. Preserve fichas funcionais de ator/token, tipos de item, fórmula 1d20+@combat.initiative, packs de ator/item/magia e systemId correto. Diferencie modificador armazenado de automação derivada. Mantenha pacote único e avisos GPL/MIT. Entregue arquivos alterados, versões exatas, comandos de ZIP e testes de criar/importar/editar/salvar/reabrir/tokens/iniciativa. Não invente APIs, crie Server Rules separado nem distribua regras/catálogos proprietários.