# Vermine 2047 — Copilot Instructions ## Build & Development Requires Node.js v16.15.1 (see `.nvmrc`). ```bash npm run watch # Watch SCSS + templates, proxy Foundry at localhost:30000 (requires Foundry running) npm run buildStyle # Compile SCSS once to css/vermine2047.css npm run pullYAMLtoLDB # Build LevelDB compendium packs from src/packs/ YAML → packs/ npm run pushLDBtoYAML # Extract LevelDB packs to editable YAML in src/packs/ npx eslint module/ # Lint JavaScript (ESLint configured in .eslintrc.js) ``` There are no automated tests. Use `npm run watch` during development — browser-sync proxies Foundry over HTTPS and live-reloads SCSS, `.hbs`, and `.html` templates on change. `system.json` declares `hotReload` for `.css`, `.scss`, `.hbs`, and `.json` extensions, so Foundry auto-refreshes those assets client-side when the dev server is running. ## Architecture This is a **FoundryVTT game system** (`system.json` → system ID `vermine2047`), compatible with Foundry v11–v14. It implements the French post-apocalyptic TTRPG **Vermine 2047**. **Entry point**: `module/vermine2047.mjs` — loaded as an ES module. On the `init` hook it registers custom document classes, sheet classes, combat classes, Handlebars helpers, settings, hooks, and preloads templates. **Actor types** (4): `character`, `npc`, `group`, `creature` **Item types** (12): `item`, `weapon`, `defense`, `vehicle`, `ability`, `specialty`, `background`, `trauma`, `evolution`, `rumor`, `target`, `rite` **Key source files** (`module/system/`): | File | Role | |---|---| | `config.mjs` | All game constants (`CONFIG.VERMINE`) — abilities, skills, totems, threat/role/pattern levels, traits, damage types | | `roll.mjs` | `VermineUtils` class — d10 dice pool system with success counting, totem mechanics, rerolls, Dice So Nice integration | | `dice3d.mjs` | Dice So Nice 3D dice configuration (appearance, colors, themes for totem/standard dice) | | `fight.mjs` | Confrontation system (`VermineFight`), plus `VermineCombat`, `VermineCombatant`, `VermineCombatTracker` | | `group-link.mjs` | `GroupLink` — bidirectional sync of members/encounters between group actors and character/NPC actors via Foundry hooks | | `hooks.mjs` | All Foundry hook registrations (chat messages, hotbar drop, combat, preCreate, Dice So Nice) | | `settings.mjs` | System settings (game mode: survie/cauchemar/apocalypse) | | `handlebars-manager.mjs` | Template preloading paths + all Handlebars helpers (level config lookups, math, conditionals) | | `effects.mjs` | Active effect management | | `dialogs/rollDialog.mjs` | Advanced roll dialog (ability/skill selection, difficulty, totems, specialties, assist/pool bonuses) | | `applications.mjs` | `TotemPicker` and `TraitSelector` applications (still AppV1) | | `applications/sheets/` | ApplicationV2 sheet classes: `base-actor-sheet.mjs`, `base-item-sheet.mjs` + 4 actor + 12 item sheets | **Data model**: Defined via Foundry DataModels (`module/models/`) extending `foundry.abstract.TypeDataModel`. Type-specific derived data is computed in each DataModel's `prepareDerivedData()`. The legacy `template.json` has been removed in favor of `system.json` → `documentTypes`. **Sheet inheritance**: ApplicationV2 (`HandlebarsApplicationMixin(ActorSheetV2)`/`ItemSheetV2`) in `module/applications/sheets/`. `VermineBaseActorSheet` → `VermineCharacterSheetV2`, etc. Sheets expose `CONFIG.VERMINE` as `context.config` in template data. Each sheet is split into parts via `static PARTS`; tab navigation uses Core's `templates/generic/tab-navigation.hbs`. **Data preparation**: `VermineActor.prepareDerivedData()` delegates to the type-specific DataModel. Each DataModel implements its own `prepareDerivedData()` with type-specific computation logic. **Global access**: On `init`, `game.vermine2047` is populated with `{ VermineActor, VermineItem, VermineUtils, VermineCombat, GroupLink }` for easy access in macros and scripts. **Compendium packs**: Stored in `packs/` as LevelDB databases. Edit source data in `src/packs/` as YAML, then `npm run pullYAMLtoLDB` to build. The CI release workflow runs this automatically. ## Key Conventions - **All `.mjs` files**: ES module syntax only. Foundry globals (`game`, `Hooks`, `CONFIG`, `Actor`, `Item`, `ChatMessage`, `Roll`, `Handlebars`, `renderTemplate`, `foundry`, `ui`, `Canvas`, `Dialog`) are available but declared as readonly globals in `.eslintrc.js`. - **ESLint conventions**: 2-space indent, single quotes, semicolons required, `===` equality (except `== null`). Constants named with `VERMINE_` prefix are exempt from camelCase. Max 1 class per file, 500 lines per file, 100 lines per function, 5 levels of nesting max. No `console.log` calls — use `ui.notifications`. - **Code language**: Source code and comments are in French. UI strings in `lang/fr.json` and `lang/en.json`. Use `game.i18n.localize()` for all user-visible text. - **Template naming**: Actor sheets use ApplicationV2 part templates in `templates/actor/appv2/{type}-{part}.hbs` (e.g. `character-main.hbs`, `npc-characteristics.hbs`). Item sheets at `templates/item/item-{type}-sheet.html`. Chat card templates at `templates/item/chatCards/{type}.hbs`. Legacy templates in `templates/actor/` subdirectories are preserved for dialog/chat use. - **Dice system**: d10 pools with success counting (result ≥ difficulty). Totem dice (human/adapted) count double on success. Formula syntax: `{N}d10cs>={threshold}[label]`. Totem dice: `(1d10cs>={threshold}[totem_label]*2)`. - **CSS**: SCSS sources in `scss/` compile to `css/vermine2047.css`. Entry point: `vermine2047.scss` which imports partials: `_app.scss`, `_flex.scss`, `dialog.scss`, `item-sheet.scss`, `itemCards.scss`, `roll.scss`, `special-applications.scss`, `special-inputs.scss`, `style.scss`, `base_work.scss`. Add new SCSS partials as `_component.scss`, import in `vermine2047.scss`. - **Data tools**: The `pushLDBtoYAML` / `pullYAMLtoLDB` scripts use `@foundryvtt/foundryvtt-cli` to convert between LevelDB packs and editable YAML. When adding pack content, edit YAML in `src/packs/` then rebuild. - **Actor updates**: Use `actor.update({...})` with dot-notation paths (e.g., `'system.adaptation.totems.human.value'`). The `GroupLink` hooks system automatically syncs group memberships on actor changes. - **New template partials**: Must be listed in `preloadHandlebarsTemplates()` in `handlebars-manager.mjs` for pre-compilation. - **Full architecture documentation**: See `docs/technical/ARCHITECTURE.md`.