Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 038aa37838 |
598
DEVELOPER_INSTRUCTIONS.md
Normal file
598
DEVELOPER_INSTRUCTIONS.md
Normal file
@@ -0,0 +1,598 @@
|
||||
# FoundryVTT Les Héritiers System - Developer Instructions
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**Les Héritiers** is an unofficial FoundryVTT system for the French RPG "Les Héritiers" (published by Titam France/Sombres Projets). The system implements a complete actor and item management framework with support for characters (personnage), NPCs (pnj), and 13 item types. Recent development includes a migration to Foundry v13+ with DataModels and AppV2 architecture.
|
||||
|
||||
**Repository**: https://www.uberwald.me/gitea/public/fvtt-les-heritiers
|
||||
**Current Version**: 13.0.7
|
||||
**Compatibility**: Foundry 13+
|
||||
**Language**: French (single language localization)
|
||||
|
||||
---
|
||||
|
||||
## 1. BUILD & DEVELOPMENT COMMANDS
|
||||
|
||||
### Build System
|
||||
- **Build Tool**: Gulp 4 with LESS compilation
|
||||
- **Package Manager**: npm
|
||||
|
||||
### Scripts (package.json)
|
||||
```json
|
||||
"build": "gulp build" # Compile LESS to CSS (primary task)
|
||||
"watch": "gulp watch" # Watch LESS files and rebuild on changes
|
||||
```
|
||||
|
||||
### Gulp Pipeline (gulpfile.js)
|
||||
The gulpfile defines three main tasks:
|
||||
|
||||
| Task | Source | Output | Features |
|
||||
|------|--------|--------|----------|
|
||||
| `styles` | `less/heritiers.less` | `styles/heritiers.css` | LESS→CSS compilation with source maps |
|
||||
| `watchFiles` | `less/**/*.less` | Watches recursively | Auto-rebuild on LESS file changes |
|
||||
| `build` | - | - | Runs `styles` (default export) |
|
||||
| `watch` | - | - | Runs `build` then `watchFiles` |
|
||||
|
||||
**Development Workflow**:
|
||||
```bash
|
||||
npm install # Install dependencies (gulp, gulp-less, gulp-sourcemaps)
|
||||
npm run build # One-time CSS compilation
|
||||
npm run watch # Development: continuous LESS watching
|
||||
```
|
||||
|
||||
**Key Files**:
|
||||
- `/package.json` - Minimal deps (only gulp toolchain)
|
||||
- `/gulpfile.js` - 36 lines defining LESS tasks
|
||||
- `/less/heritiers.less` - Entry point (imports `simple-converted.less`)
|
||||
- `/styles/heritiers.css` - Generated output + source maps
|
||||
|
||||
---
|
||||
|
||||
## 2. SYSTEM ARCHITECTURE
|
||||
|
||||
### 2.1 System Metadata (system.json)
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **id** | `fvtt-les-heritiers` |
|
||||
| **title** | Les Héritiers |
|
||||
| **version** | 13.0.7 |
|
||||
| **description** | Les Héritiers pour FoundryVTT (French) |
|
||||
| **authors** | Uberwald/LeRatierBretonnien, Prêtre |
|
||||
| **compatibility** | min: "13", verified: "13" |
|
||||
| **manifest** | Hosted on Uberwald Gitea |
|
||||
| **languages** | French only (fr.json) |
|
||||
| **license** | LICENCE.txt (proprietary) |
|
||||
| **grid** | 5m squares |
|
||||
|
||||
**Key Configuration Flags**:
|
||||
- `hotReload.extensions`: `css`, `html`, `hbs`, `json`
|
||||
- `hotReload.paths`: `styles`, `./`, `templates`, `lang/fr.json`
|
||||
- `primaryTokenAttribute`: `sante.vigueur` (health/vigor)
|
||||
- `secondaryTokenAttribute`: `bonneaventure.actuelle` (current good fortune)
|
||||
- **Socket Support**: Enabled (`socket: true`)
|
||||
|
||||
### 2.2 Data Model (template.json.backup)
|
||||
|
||||
The system defines a complex hierarchical data model with 2 Actor types and 14 Item types:
|
||||
|
||||
#### **Actor Types**
|
||||
|
||||
**1. `personnage` (Player Character)**
|
||||
- Templates: `biodata`, `core`
|
||||
- Key characteristics (8 attributes):
|
||||
- Physical: Agilité (agi), Constitution (con), Force (for), Précision (prec)
|
||||
- Mental: Esprit (esp), Perception (per), Prestance (pres), Sang-Froid (san)
|
||||
- Fields include biodata (name, appearance variants masked/unmasked, age, personality traits), ranks (Tricherie, Féerie, Masque, Héritage with scenario tracking), PV (health), combat skills
|
||||
- Profile-based competences (6 profiles + magic)
|
||||
|
||||
**2. `pnj` (NPC)**
|
||||
- Templates: `biodata`, `core`
|
||||
- Identical structure to `personnage` with simpler NPC-specific metadata
|
||||
|
||||
**Core Actor Data** (template.core):
|
||||
```
|
||||
caracteristiques: {
|
||||
agi, con, for, prec, esp, per, pres, san
|
||||
└─ label, labelnorm, abbrev, kind(physical|mental), value, rang, max
|
||||
}
|
||||
rang: {
|
||||
tricherie, feerie, masque, heritage (with scenarios subfield)
|
||||
}
|
||||
pv: { value, max, mod }
|
||||
competences: { aventurier, combattant, erudit, gentleman, roublard, savant }
|
||||
magie: { pointsame (value, max) }
|
||||
experience: { value, pourtricher }
|
||||
combat: {
|
||||
esquive, parade, resistancephysique, resistancepsychique, protection,
|
||||
effetssecondaires, dissimulation, initiative, corpsacorps, tir
|
||||
}
|
||||
```
|
||||
|
||||
#### **Item Types** (14 total)
|
||||
|
||||
| Item Type | Key Fields | Use Case |
|
||||
|-----------|-----------|----------|
|
||||
| `arme` (Weapon) | degats, precision, cadence, portee, dissimulation, armetype, rarete, prix | Combat equipment |
|
||||
| `protection` | points, malusagilite, protectiontype, effetsecondaire | Armor/shields |
|
||||
| `equipement` | rarete, quantite, prix | General gear |
|
||||
| `accessoire` | lieu (location code) | Small items |
|
||||
| `competence` | categorie, profil, niveau, specialites[], ismagie, nomniveau | Skills (6 profiles) |
|
||||
| `profil` | profiltype (majeur|mineur) | Character archetypes |
|
||||
| `contact` | contacttype (contact, allie, ennemi, interet) | NPC contacts |
|
||||
| `avantage` | description | Advantages (benefits) |
|
||||
| `desavantage` | description | Disadvantages (flaws) |
|
||||
| `capacitenaturelle` | pouvoirtype, activation, effet, portee, resistance, cibles, virulence | Natural abilities |
|
||||
| `pouvoir` | pouvoirtype, masquetype, niveau, istest, feeriemasque, carac, zoneffet, pointsusagecourant | Powers/spells |
|
||||
| `atoutfeerique` | description | Fairy/magical perks |
|
||||
| `fee` | feetype, avantages, desavantages, pouvoirsfeeriques*, atoutsfeeriques, competences, capacitenaturelles | Fairy character sheet |
|
||||
| `sort` (Spell) | niveau, rang, competence (Druidisme), carac1, carac2, duree, portee, ingredients, resistance | Magic spells |
|
||||
|
||||
**Item Templates**:
|
||||
- `base`: description (HTMLField)
|
||||
- `basequip`: rarete, quantite, prix, equipped (for equipable items)
|
||||
|
||||
### 2.3 Directory Structure
|
||||
|
||||
```
|
||||
modules/ # ES6 source code (12,273 LOC total)
|
||||
├── heritiers-main.js # Entry point: init, hook setup, document class config
|
||||
├── heritiers-actor.js # HeritiersActor class with creation hooks
|
||||
├── heritiers-item.js # HeritiersItem class
|
||||
├── heritiers-config.js # HERITIERS_CONFIG object (enums, constants)
|
||||
├── heritiers-commands.js # Chat command system
|
||||
├── heritiers-utility.js # Static utility class (dice, rolls, templates, socket)
|
||||
├── heritiers-combat.js # HeritiersCombat class
|
||||
├── xregexp-all.js # RegExp library
|
||||
├── models/
|
||||
│ ├── index.mjs # Exports all DataModels
|
||||
│ ├── personnage.mjs # PersonnageDataModel (complex, 12K+ lines)
|
||||
│ ├── pnj.mjs # PnjDataModel
|
||||
│ ├── arme.mjs # ArmeDataModel (updated Jan 21)
|
||||
│ ├── competence.mjs # CompetenceDataModel (updated Jan 21)
|
||||
│ ├── capacitenaturelle.mjs # Natural ability model (updated Jan 21)
|
||||
│ ├── pouvoir.mjs # PouvoirDataModel (updated Jan 21)
|
||||
│ ├── protection.mjs # ProtectionDataModel (updated Jan 21)
|
||||
│ ├── [11 more models] # accessoire, atoutfeerique, avantage, contact,
|
||||
│ │ # desavantage, equipement, fee, profil, sort
|
||||
│ └── base-item.mjs # Base item template
|
||||
├── applications/
|
||||
│ ├── sheets/
|
||||
│ │ ├── _module.mjs # Exports all sheet classes
|
||||
│ │ ├── base-actor-sheet.mjs # HeritiersActorSheet (HandlebarsApplicationMixin, AppV2)
|
||||
│ │ ├── base-item-sheet.mjs # HeritiersItemSheet base
|
||||
│ │ ├── personnage-sheet.mjs # Character sheet (specific)
|
||||
│ │ ├── pnj-sheet.mjs # NPC sheet (specific)
|
||||
│ │ └── [11 item sheets] # Type-specific sheets: arme, protection, competence, etc.
|
||||
│ └── heritiers-roll-dialog.mjs # Dialog for roll resolution
|
||||
```
|
||||
|
||||
#### **Key Module Details**:
|
||||
|
||||
**heritiers-main.js** (100+ lines):
|
||||
- Hooks.once("init") - Registers templates, combat, actor/item classes, DataModels
|
||||
- Registers AppV2 sheets for all actor and item types
|
||||
- Creates `game.system.lesheritiers` namespace with utilities, config, models, sheets
|
||||
- Socket message handling
|
||||
|
||||
**heritiers-config.js**:
|
||||
- `HERITIERS_CONFIG` object with ~40 enum dictionaries:
|
||||
- `caracList`: 8 characteristics with labels
|
||||
- `competenceProfil`: 6 profiles (aventurier, roublard, combattant, erudit, savant, gentleman) + magic
|
||||
- `baseTestPouvoir`, `resistancePouvoir`, `typePouvoir`
|
||||
- `seuilsDifficulte`: 30-level difficulty scale (5=Enfantine to 30=Divine)
|
||||
- `attaqueCible`: target localization (body part damage tracking)
|
||||
- Game-specific constants
|
||||
|
||||
**heritiers-utility.js** (60+ custom Handlebars helpers):
|
||||
- `rollDataStore`, `defenderStore` for roll tracking
|
||||
- Handlebars helpers: count, includes, upper, lower, upperFirst, notEmpty, mul, and, or, eq, isTest, etc.
|
||||
- `preloadHandlebarsTemplates()` - loads 27 template files
|
||||
- `chatListeners()` - click handlers for chat
|
||||
- `loadCompendium()` - loads packs dynamically
|
||||
- `onSocketMesssage()` - inter-client communication
|
||||
|
||||
**heritiers-actor.js**:
|
||||
- Custom creation logic: auto-adds useful skills from compendium for personnage type
|
||||
- Extends Foundry Actor class
|
||||
|
||||
**heritiers-item.js**:
|
||||
- Custom Item class with item-type-specific business logic
|
||||
|
||||
### 2.4 Templates Directory (27 Handlebars files)
|
||||
|
||||
Organized by purpose:
|
||||
|
||||
**Actor Sheets** (2 files):
|
||||
- `actor-sheet.hbs` - Personnage character sheet (complex form with tabs)
|
||||
- `actor-pnj-sheet.hbs` - NPC sheet (simplified)
|
||||
|
||||
**Item Sheets** (14 files):
|
||||
- `item-[type]-sheet.hbs` for each item type
|
||||
- E.g., `item-arme-sheet.hbs`, `item-competence-sheet.hbs`, `item-sort-sheet.hbs`
|
||||
|
||||
**Partials** (5 files):
|
||||
- `partial-actor-equipment.hbs` - Equipment list rendering
|
||||
- `partial-item-header.hbs` - Item sheet header (common)
|
||||
- `partial-item-nav.hbs` - Tabbed navigation
|
||||
- `partial-item-description.hbs` - Description editor
|
||||
- `partial-utile-skills.hbs` - Skill list filtering
|
||||
- `post-item.hbs` - Chat card for item description
|
||||
- `editor-notes-gm.hbs` - GM notes editor
|
||||
|
||||
**Chat Results** (3 files):
|
||||
- `chat-generic-result.hbs` - Generic roll result
|
||||
- `chat-cc-result.hbs` - Close combat result
|
||||
- `chat-assommer-result.hbs` - Stun attack result
|
||||
|
||||
**Dialogs** (1 file):
|
||||
- `roll-dialog-generic.hbs` - Roll dialog with modifiers
|
||||
|
||||
**Design Notes**:
|
||||
- Heavy use of Handlebars conditionals ({{#if}}, {{#each}})
|
||||
- Data-action attributes for action routing
|
||||
- Flexbox-based layout (`flexrow`, `flexcol` CSS classes)
|
||||
- Partial templates for reusability
|
||||
|
||||
### 2.5 Localization (lang/fr.json)
|
||||
|
||||
**Minimal localization** - only 24 lines:
|
||||
```json
|
||||
{
|
||||
"TYPES": {
|
||||
"Actor": {
|
||||
"personnage": "Personnage",
|
||||
"pnj": "PNJ"
|
||||
},
|
||||
"Item": {
|
||||
"accessoire": "Accessoire",
|
||||
"arme": "Arme",
|
||||
[12 more item types...]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Localization Strategy**:
|
||||
- Labels hardcoded in code/templates in French
|
||||
- No string keys for UI text outside TYPES
|
||||
- Template labels defined in DataModel schema (initial values)
|
||||
- Seeded localization keys in heritiers-config.js (no i18n lookup)
|
||||
|
||||
### 2.6 Styles (less/ and styles/)
|
||||
|
||||
**LESS Structure** (2 files):
|
||||
- `heritiers.less` (4 lines) - Entry point, imports converted template
|
||||
- `simple-converted.less` - Full stylesheet (converted from Bootstrap/template.css)
|
||||
|
||||
**Output**:
|
||||
- Compiled to `/styles/heritiers.css` (referenced in system.json)
|
||||
- Source maps generated (`.map` files)
|
||||
|
||||
**Styling Approach**:
|
||||
- Utility classes: `flexrow`, `flexcol`, `padd-right`, `status-small-label`
|
||||
- Color classes: `color-class-common`, etc.
|
||||
- Section classes: `background-sheet-header`
|
||||
- Responsive design via flexbox
|
||||
|
||||
### 2.7 Compendium Packs (packs/)
|
||||
|
||||
11 packs defined in system.json, stored as `.db` (LevelDB format):
|
||||
|
||||
| Pack Name | Type | Label | Folder | Contents |
|
||||
|-----------|------|-------|--------|----------|
|
||||
| `competences` | Item | Compétences | Creation | Skills |
|
||||
| `avantages` | Item | Avantages | Creation | Advantages |
|
||||
| `desavantages` | Item | Désavantages | Creation | Disadvantages |
|
||||
| `capacites` | Item | Capacités Naturelles | Creation | Natural abilities |
|
||||
| `atouts-feeriques` | Item | Atouts Féériques | Creation | Fairy perks |
|
||||
| `magie-sorts` | Item | Sorts | Creation | Spells (5 spell schools) |
|
||||
| `archetypes-fees` | Item | Fées | Creation | Fairy archetypes |
|
||||
| `pouvoirs` | Item | Pouvoirs | Creation | Powers |
|
||||
| `profils` | Item | Profils | Creation | Character profiles |
|
||||
| `armes-et-protection` | Item | Armes et Protections | Equipment | Weapons & armor |
|
||||
| `scenes` | Scene | Scènes | Root | Sample scenes |
|
||||
| `journaux` | JournalEntry | Journaux | Root | Game journal entries |
|
||||
|
||||
**Ownership Model** (PLAYER: OBSERVER, ASSISTANT: OWNER):
|
||||
- Players can observe (read) items in packs
|
||||
- Assistants have full control
|
||||
|
||||
**Source Data** (`srcdata/`):
|
||||
- 5 JSON files for spell normalization:
|
||||
- `sort_druidisme.json`, `sort_faeomancie.json`, `sort_magieduclan.json`, `sort_necromancie.json`, `sort_theurgie.json`
|
||||
- `normalize.py` - Python script to transform spell data to compendium format
|
||||
|
||||
---
|
||||
|
||||
## 3. KEY CONVENTIONS
|
||||
|
||||
### 3.1 Module/Class Structure
|
||||
|
||||
**Pattern**: ES6 Classes extending Foundry base classes
|
||||
- **Naming**: `Heritiers[Type]` (e.g., `HeritiersActor`, `HeritiersItem`, `HeritiersCombat`)
|
||||
- **Exports**: Named exports via `export class`/`export default`
|
||||
|
||||
**Example (heritiers-actor.js)**:
|
||||
```javascript
|
||||
export class HeritiersActor extends Actor {
|
||||
static async create(data, options) { ... }
|
||||
// Custom methods and hooks
|
||||
}
|
||||
```
|
||||
|
||||
**Example (models/personnage.mjs)**:
|
||||
```javascript
|
||||
export default class PersonnageDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
biodata: new fields.SchemaField({ ... }),
|
||||
// nested SchemaFields with detailed field definitions
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Sheet Pattern (AppV2 - Foundry v13+)**:
|
||||
```javascript
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
export default class HeritiersPersonnageSheet extends HandlebarsApplicationMixin(
|
||||
foundry.applications.sheets.ActorSheetV2
|
||||
) {
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["fvtt-les-heritiers", "sheet", "actor"],
|
||||
position: { width: 780, height: 840 },
|
||||
form: { submitOnChange: true, closeOnSubmit: false },
|
||||
actions: {
|
||||
editImage, toggleSheet, editItem, deleteItem,
|
||||
createItem, equipItem, rollCarac, ...
|
||||
}
|
||||
}
|
||||
// Static action handlers (#onEditImage, etc.)
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 Data Model Conventions
|
||||
|
||||
**Field Types** (foundry.data.fields.*):
|
||||
- `StringField` - Text values, default initial values
|
||||
- `HTMLField` - Rich-text fields (description, notes, etc.)
|
||||
- `NumberField` - Integers (integer: true), floats
|
||||
- `BooleanField` - Boolean flags
|
||||
- `ArrayField` - Lists (with element type)
|
||||
- `SchemaField` - Nested objects
|
||||
|
||||
**Naming Conventions**:
|
||||
- Snake_case for internal field names: `biodata`, `caracteristiques`, `pointsame`
|
||||
- Abbreviations for characteristics: `agi`, `con`, `for`, `prec`, `esp`, `per`, `pres`, `san`
|
||||
- French names for labels and UI: "Agilité", "Constitution", etc.
|
||||
|
||||
**Special Fields**:
|
||||
- `labelnorm` - Normalized label for lookups (lowercase, no accents)
|
||||
- `kind` - Classification (physical, mental, magical)
|
||||
- `initial` - Default value in schema definition
|
||||
|
||||
### 3.3 Handlebars Template Conventions
|
||||
|
||||
**File Naming**:
|
||||
- `actor-sheet.hbs` - Main sheet template (not item-specific)
|
||||
- `actor-[type]-sheet.hbs` - Type-specific actor sheet
|
||||
- `item-[type]-sheet.hbs` - Type-specific item sheet
|
||||
- `partial-[purpose].hbs` - Reusable component
|
||||
- `chat-[result-type].hbs` - Chat message template
|
||||
- `editor-[context].hbs` - Editor component
|
||||
|
||||
**Data Binding**:
|
||||
- Actor data: `{{system.field.subfield}}`, `{{actor.name}}`
|
||||
- Item data: `{{system.field}}`
|
||||
- Loops: `{{#each system.array as |item key|}}`
|
||||
- Conditionals: `{{#if condition}}...{{/if}}`
|
||||
|
||||
**Custom Helpers** (60+):
|
||||
- Comparison: `eq`, `ne`, `lt`, `gt`
|
||||
- Array: `includes`, `count`, `notEmpty`
|
||||
- String: `upper`, `lower`, `upperFirst`
|
||||
- Math: `mul`, `add`, `sub`, `and`, `or`
|
||||
- Game: `isTest` (checks test type)
|
||||
|
||||
**CSS Classes**:
|
||||
- Layout: `flexrow`, `flexcol`, `item`, `item-list`
|
||||
- Styling: `status-small-label`, `color-class-common`, `background-sheet-header`
|
||||
- Action: `data-action="actionName"` for click routing
|
||||
|
||||
### 3.4 Localization Key Naming
|
||||
|
||||
**Pattern**: `TYPES.Actor.[type]`, `TYPES.Item.[type]`
|
||||
|
||||
Current localization (lang/fr.json):
|
||||
```json
|
||||
"TYPES": {
|
||||
"Actor": {
|
||||
"personnage": "Personnage",
|
||||
"pnj": "PNJ"
|
||||
},
|
||||
"Item": {
|
||||
"accessoire": "Accessoire",
|
||||
"arme": "Arme",
|
||||
"atoutfeerique": "Atout féerique",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Strategy**:
|
||||
- **Type labels**: Centralized in TYPES
|
||||
- **Field labels**: Defined in DataModel schema as `initial` values
|
||||
- **Config labels**: In heritiers-config.js (caracList, competenceProfil, etc.)
|
||||
- **Template text**: Hardcoded in .hbs files (all French)
|
||||
|
||||
**No i18n System**: System is French-only; no game.i18n lookups used in code
|
||||
|
||||
### 3.5 Dice & Roll System
|
||||
|
||||
**Initiative Formula** (heritiers-config.js):
|
||||
```javascript
|
||||
CONFIG.Combat.initiative = {
|
||||
formula: "1d10",
|
||||
decimals: 1
|
||||
};
|
||||
```
|
||||
|
||||
**Roll Data Storage** (heritiers-utility.js):
|
||||
- `rollDataStore = {}` - Tracks active rolls by ID
|
||||
- `defenderStore = {}` - Tracks defenders for opposed rolls
|
||||
- Socket-based roll updates for multi-client scenarios
|
||||
|
||||
**Bonus/Malus**:
|
||||
- Range: -6 to +6 (signed integers)
|
||||
- Generated as: `Array.from({ length: 7 }, (v, k) => toString(k - 6))`
|
||||
|
||||
**Dice Mechanics**:
|
||||
- D8, D10, D12 support with face adjacency tables (unused in some contexts)
|
||||
- Example: `__facesAdjacentes` object maps die faces to adjacent faces
|
||||
|
||||
### 3.6 Socket Message Handling
|
||||
|
||||
**Game Socket** (configured in system.json):
|
||||
- Enabled via `"socket": true`
|
||||
- Message channel: `"system.fvtt-les-heritiers"`
|
||||
|
||||
**Message Flow** (heritiers-utility.js):
|
||||
```javascript
|
||||
game.socket.on("system.fvtt-les-heritiers", data => {
|
||||
HeritiersUtility.onSocketMesssage(data)
|
||||
})
|
||||
```
|
||||
|
||||
Used for:
|
||||
- Inter-client roll notifications
|
||||
- Multiplayer combat updates
|
||||
|
||||
### 3.7 Recent Migration Notes (v13.0.7)
|
||||
|
||||
**Latest Changes** (from git log):
|
||||
- Migrated from legacy v1 sheets to **AppV2** (HandlebarsApplicationMixin + ActorSheetV2)
|
||||
- Migrated to **DataModels** (foundry.abstract.TypeDataModel)
|
||||
- All sheets converted to `.mjs` (ES6 modules)
|
||||
- Specification & competence fixes (Jan 21)
|
||||
- Armor (protection) and weapon (arme) model refinements (Jan 21)
|
||||
|
||||
**Key Commit**: `4722fdf - Migration vers DataModels et appv2` (major architecture update)
|
||||
|
||||
---
|
||||
|
||||
## 4. EXISTING AI & DEVELOPER CONFIGURATIONS
|
||||
|
||||
### No Pre-Existing Configs Found
|
||||
|
||||
The following configuration files **do NOT exist** in the repository:
|
||||
- `.github/copilot-instructions.md` ❌
|
||||
- `CLAUDE.md` ❌
|
||||
- `.cursorrules` ❌
|
||||
- `AGENTS.md` ❌
|
||||
- `.windsurfrules` ❌
|
||||
- `CONVENTIONS.md` ❌
|
||||
- `CONTRIBUTING.md` ❌
|
||||
|
||||
Only **README.md** exists (29 lines):
|
||||
- Credits Titam France/Sombres Projets
|
||||
- Lists contributors: LeRatierBretonnien (dev), Prêtre (testing/data entry)
|
||||
- Notes official authorization
|
||||
- Links to books at titam-france.fr
|
||||
|
||||
---
|
||||
|
||||
## 5. DEVELOPMENT WORKFLOW
|
||||
|
||||
### 5.1 Setup
|
||||
|
||||
```bash
|
||||
cd /home/morr/work/foundryvtt/fvtt-les-heritiers
|
||||
npm install
|
||||
npm run watch
|
||||
```
|
||||
|
||||
### 5.2 File Organization When Adding Features
|
||||
|
||||
| Purpose | Location | Pattern |
|
||||
|---------|----------|---------|
|
||||
| New item type logic | `modules/heritiers-item.js` | Extend HeritiersItem |
|
||||
| New item data model | `modules/models/[type].mjs` | Extend TypeDataModel |
|
||||
| New item sheet | `modules/applications/sheets/[type]-sheet.mjs` | Extend HeritiersItemSheet |
|
||||
| New item template | `templates/item-[type]-sheet.hbs` | Handlebars + data-action |
|
||||
| New actor type | `modules/models/[type].mjs` | Extend TypeDataModel |
|
||||
| New actor sheet | `modules/applications/sheets/[type]-sheet.mjs` | Extend HeritiersActorSheet |
|
||||
| New chat message | `templates/chat-[result]-result.hbs` | HTML template |
|
||||
| Style updates | `less/heritiers.less` or new import | LESS → npm run build |
|
||||
| New config constants | `modules/heritiers-config.js` | Add to HERITIERS_CONFIG |
|
||||
| Game mechanics | `modules/heritiers-utility.js` or -commands.js | Static utilities or commands |
|
||||
|
||||
### 5.3 Registration Steps for New Item Type
|
||||
|
||||
1. **Update template.json.backup** - Add schema definition
|
||||
2. **Create DataModel** - `modules/models/[type].mjs`
|
||||
3. **Update heritiers-config.js** - Add enums if needed
|
||||
4. **Create Sheet** - `modules/applications/sheets/[type]-sheet.mjs`
|
||||
5. **Create Template** - `templates/item-[type]-sheet.hbs`
|
||||
6. **Update heritiers-main.js** - Register sheet class
|
||||
7. **Add to models/index.mjs** - Export DataModel
|
||||
8. **Add to applications/sheets/_module.mjs** - Export Sheet class
|
||||
9. **Update localization** - Add type to lang/fr.json TYPES.Item
|
||||
10. **Update system.json** - If exposing in UI
|
||||
|
||||
### 5.4 Debugging
|
||||
|
||||
- Check browser console for JS errors
|
||||
- Use Chrome DevTools on http://localhost:30000 (Foundry dev port)
|
||||
- Hot reload enabled for: `.css`, `.html`, `.hbs`, `.json` files (from system.json flags)
|
||||
- Git history available via `git log` or `git show <commit>`
|
||||
|
||||
---
|
||||
|
||||
## 6. KEY STATISTICS
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| **System ID** | fvtt-les-heritiers |
|
||||
| **Version** | 13.0.7 |
|
||||
| **Total Source LOC** | 12,273 lines |
|
||||
| **Actor Types** | 2 (personnage, pnj) |
|
||||
| **Item Types** | 14 (arme, protection, competence, etc.) |
|
||||
| **Compendium Packs** | 11 |
|
||||
| **Template Files** | 27 (.hbs) |
|
||||
| **Module Files** | 28 (.js/.mjs) |
|
||||
| **Model Files** | 16 (DataModels) |
|
||||
| **Sheet Files** | 14 (+ 1 base) |
|
||||
| **LESS Files** | 2 |
|
||||
| **Localization Files** | 1 (fr.json, 24 lines) |
|
||||
| **Dev Dependencies** | 3 (gulp, gulp-less, gulp-sourcemaps) |
|
||||
| **Characteristics** | 8 (agi, con, for, prec, esp, per, pres, san) |
|
||||
| **Competence Profiles** | 6 + magic (aventurier, roublard, combattant, erudit, savant, gentleman) |
|
||||
| **Difficulty Scale** | 30 levels (-1 to 30) |
|
||||
| **Last Commit** | "Correction sur calcul du rang" (recent) |
|
||||
|
||||
---
|
||||
|
||||
## 7. EXTERNAL RESOURCES
|
||||
|
||||
- **Official Publisher**: [Titam France / Sombres Projets](http://www.titam-france.fr)
|
||||
- **System Repository**: https://www.uberwald.me/gitea/public/fvtt-les-heritiers
|
||||
- **Foundry Documentation**: https://foundryvtt.com/articles/
|
||||
- **Foundry v13 API**: DataModels, AppV2 sheets (major changes in this version)
|
||||
|
||||
---
|
||||
|
||||
## 8. RECOMMENDATIONS FOR DEVELOPERS
|
||||
|
||||
1. **Use AppV2 Sheet API** for all new sheets (do not use legacy v1)
|
||||
2. **Define DataModels** for type data rather than inline templates
|
||||
3. **Keep French localization** in code/templates (minimal i18n setup)
|
||||
4. **Test with `npm run watch`** during development
|
||||
5. **Use socket messages** for multiplayer features
|
||||
6. **Follow naming conventions** (Heritiers[Type], snake_case for fields, French labels)
|
||||
7. **Document dice mechanics** when adding new rolls
|
||||
8. **Keep configuration constants** in heritiers-config.js
|
||||
9. **Use Handlebars helpers** rather than inline logic in templates
|
||||
10. **Register sheets in heritiers-main.js** and export from _module.mjs files
|
||||
|
||||
239
DOCUMENTATION_INDEX.md
Normal file
239
DOCUMENTATION_INDEX.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# Les Héritiers FoundryVTT System - Documentation Index
|
||||
|
||||
## 📖 Available Documentation
|
||||
|
||||
### 1. **QUICK_REFERENCE.md** ⭐ START HERE
|
||||
- **Length**: 250 lines
|
||||
- **Purpose**: Fast lookup and common task guide
|
||||
- **Best for**: Developers new to the system
|
||||
- **Contains**:
|
||||
- Quick start setup commands
|
||||
- System overview & statistics
|
||||
- Project structure diagram
|
||||
- Key classes and exports
|
||||
- Step-by-step: Adding a new item type
|
||||
- Common edits (characteristics, packs, rolls, UI)
|
||||
- Testing and git workflow
|
||||
- Useful commands
|
||||
|
||||
### 2. **DEVELOPER_INSTRUCTIONS.md** 📚 COMPREHENSIVE GUIDE
|
||||
- **Length**: 598 lines
|
||||
- **Purpose**: Complete architectural reference
|
||||
- **Best for**: Deep understanding and long-term development
|
||||
- **Contains**:
|
||||
- Executive summary
|
||||
- Build/dev commands (package.json, gulpfile.js)
|
||||
- System architecture (metadata, data model, directories)
|
||||
- Directory structure with file descriptions
|
||||
- Template organization & conventions
|
||||
- Localization strategy
|
||||
- Styling (LESS, CSS)
|
||||
- Compendium packs reference
|
||||
- Detailed conventions:
|
||||
- Module/class structure
|
||||
- Data model conventions
|
||||
- Handlebars template patterns
|
||||
- Localization key naming
|
||||
- Dice & roll system
|
||||
- Socket message handling
|
||||
- Recent migration notes (v13)
|
||||
- Development workflow (setup, file organization, registration steps)
|
||||
- Debugging tips
|
||||
- Key statistics
|
||||
- External resources
|
||||
- Developer recommendations
|
||||
|
||||
### 3. **README.md** (ORIGINAL)
|
||||
- **Length**: 29 lines
|
||||
- **Purpose**: Project overview and credits
|
||||
- **Contains**:
|
||||
- Project description (English & French)
|
||||
- Copyright & authorization notes
|
||||
- Developer credits
|
||||
|
||||
---
|
||||
|
||||
## 🎯 How to Use This Documentation
|
||||
|
||||
### For First-Time Setup (5-10 minutes)
|
||||
1. Read **QUICK_REFERENCE.md** → "Quick Start" section
|
||||
2. Run `npm install` and `npm run watch`
|
||||
3. Skim the "Project Structure" section
|
||||
|
||||
### For Adding a New Feature (30 minutes)
|
||||
1. Open **QUICK_REFERENCE.md** → "Adding a New Item Type" section
|
||||
2. Follow the numbered steps
|
||||
3. Reference **DEVELOPER_INSTRUCTIONS.md** for deeper understanding of each step
|
||||
4. Test with `npm run watch`
|
||||
|
||||
### For Understanding the System (1-2 hours)
|
||||
1. Start with **DEVELOPER_INSTRUCTIONS.md** → "Executive Summary"
|
||||
2. Read section 2: "System Architecture"
|
||||
3. Read section 3: "Key Conventions"
|
||||
4. Review section 5: "Development Workflow"
|
||||
|
||||
### For Debugging a Bug (varies)
|
||||
1. Check **QUICK_REFERENCE.md** → "Useful Commands" for search/analysis tools
|
||||
2. Reference **DEVELOPER_INSTRUCTIONS.md** → Section 3 for patterns
|
||||
3. Look at git history: `git log --oneline | head -20`
|
||||
4. Check browser console (DevTools) at `http://localhost:30000`
|
||||
|
||||
### For Making Common Edits (5-15 minutes each)
|
||||
Reference **QUICK_REFERENCE.md** → "Common Edits" section:
|
||||
- Adding a new characteristic
|
||||
- Adding a new compendium pack
|
||||
- Adding a new roll type
|
||||
- Changing UI layout
|
||||
|
||||
---
|
||||
|
||||
## 📊 Quick System Overview
|
||||
|
||||
| Aspect | Detail |
|
||||
|--------|--------|
|
||||
| **System ID** | `fvtt-les-heritiers` |
|
||||
| **Version** | 13.0.7 |
|
||||
| **Foundry** | v13+ (AppV2, DataModels) |
|
||||
| **Language** | French (monolingual) |
|
||||
| **Build Tool** | Gulp 4 + LESS |
|
||||
| **Code** | 12,273 LOC total |
|
||||
| **Actor Types** | 2 (personnage, pnj) |
|
||||
| **Item Types** | 14 types |
|
||||
| **Compendium Packs** | 11 LevelDB packs |
|
||||
| **Sheets** | 16 AppV2 sheets |
|
||||
| **Architecture** | ES6 modules, TypeDataModel |
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Repository Structure
|
||||
|
||||
```
|
||||
fvtt-les-heritiers/
|
||||
├── README.md # Original project readme
|
||||
├── QUICK_REFERENCE.md # ⭐ Start here (250 lines)
|
||||
├── DEVELOPER_INSTRUCTIONS.md # 📚 Deep dive (598 lines)
|
||||
├── DOCUMENTATION_INDEX.md # This file
|
||||
├── package.json # npm config (build commands)
|
||||
├── gulpfile.js # Gulp tasks (LESS → CSS)
|
||||
├── system.json # FoundryVTT manifest
|
||||
├── template.json.backup # Data schema reference
|
||||
├── LICENCE.txt # License
|
||||
├── modules/ # Source code (12,273 LOC)
|
||||
│ ├── heritiers-main.js # Foundry init & registration
|
||||
│ ├── heritiers-actor.js # HeritiersActor class
|
||||
│ ├── heritiers-item.js # HeritiersItem class
|
||||
│ ├── heritiers-config.js # Game constants (HERITIERS_CONFIG)
|
||||
│ ├── heritiers-utility.js # Static utilities & helpers
|
||||
│ ├── heritiers-commands.js # Chat commands
|
||||
│ ├── heritiers-combat.js # Combat handling
|
||||
│ ├── models/ # 16 TypeDataModels
|
||||
│ │ └── personnage.mjs, arme.mjs, competence.mjs, ...
|
||||
│ └── applications/sheets/ # 15 AppV2 Sheet classes
|
||||
│ └── personnage-sheet.mjs, arme-sheet.mjs, ...
|
||||
├── templates/ # 27 Handlebars templates
|
||||
│ ├── actor-sheet.hbs # Character sheet
|
||||
│ ├── actor-pnj-sheet.hbs # NPC sheet
|
||||
│ ├── item-[type]-sheet.hbs # Item sheets (14)
|
||||
│ ├── partial-*.hbs # Reusable components
|
||||
│ ├── chat-*-result.hbs # Chat templates
|
||||
│ └── editor-*.hbs # Editor components
|
||||
├── lang/
|
||||
│ └── fr.json # Localization (24 lines, minimal)
|
||||
├── less/
|
||||
│ ├── heritiers.less # Entry point
|
||||
│ └── simple-converted.less # Imported styles
|
||||
├── styles/
|
||||
│ ├── heritiers.css # Compiled output (generated)
|
||||
│ └── heritiers.css.map # Source map (generated)
|
||||
├── packs/ # 11 Compendium packs (LevelDB)
|
||||
├── srcdata/ # Source data for compilation
|
||||
├── assets/ # UI assets (images, etc.)
|
||||
└── .git/ # Git history available
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Common Tasks Quick Links
|
||||
|
||||
| Task | Guide | Time |
|
||||
|------|-------|------|
|
||||
| Initial setup | QUICK_REFERENCE.md → Quick Start | 5 min |
|
||||
| Add item type | QUICK_REFERENCE.md → Adding a New Item Type | 30 min |
|
||||
| Fix a bug | DEVELOPER_INSTRUCTIONS.md → Section 5 | 15-60 min |
|
||||
| Understand architecture | DEVELOPER_INSTRUCTIONS.md → Section 2 | 30 min |
|
||||
| Change UI layout | QUICK_REFERENCE.md → Change UI layout | 10 min |
|
||||
| Add characteristic | QUICK_REFERENCE.md → Add a new characteristic | 20 min |
|
||||
| Add new roll type | QUICK_REFERENCE.md → Add a new roll type | 25 min |
|
||||
| Debug an issue | QUICK_REFERENCE.md → Testing Changes | 10-30 min |
|
||||
|
||||
---
|
||||
|
||||
## 📝 Documentation Standards
|
||||
|
||||
All documentation follows these principles:
|
||||
|
||||
1. **Clarity**: Written for developers unfamiliar with the system
|
||||
2. **Completeness**: All information needed to perform tasks included
|
||||
3. **Accuracy**: Based on actual code analysis, not assumptions
|
||||
4. **Brevity**: Concise sections with clear headings
|
||||
5. **Examples**: Code snippets and patterns provided
|
||||
6. **Cross-references**: Links between guides for deeper understanding
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Keeping Documentation Updated
|
||||
|
||||
When making significant changes:
|
||||
|
||||
1. **Update QUICK_REFERENCE.md** if:
|
||||
- Adding/removing item types
|
||||
- Changing build commands
|
||||
- Adding/removing features
|
||||
- Changing conventions
|
||||
|
||||
2. **Update DEVELOPER_INSTRUCTIONS.md** if:
|
||||
- Major architecture changes
|
||||
- New development patterns established
|
||||
- New statistics to report
|
||||
- New sections needed
|
||||
|
||||
3. **Update git history** (automatic):
|
||||
- Commit messages explain changes
|
||||
- Reference these in DEVELOPER_INSTRUCTIONS.md
|
||||
|
||||
---
|
||||
|
||||
## 📞 Questions?
|
||||
|
||||
Refer to:
|
||||
- **FoundryVTT Docs**: https://foundryvtt.com/articles/
|
||||
- **Game Rules**: https://titam-france.fr
|
||||
- **Git History**: `git log --oneline` (see recent commits)
|
||||
- **Code Comments**: Most functions have JSDoc-style comments
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: March 16, 2025
|
||||
**Documentation Version**: 1.0
|
||||
**System Version**: 13.0.7
|
||||
|
||||
---
|
||||
|
||||
## 🎓 Learning Path
|
||||
|
||||
**Day 1**: Quick understanding
|
||||
1. Read QUICK_REFERENCE.md (20 min)
|
||||
2. Run setup commands (5 min)
|
||||
3. Explore directory structure (10 min)
|
||||
|
||||
**Week 1**: Basic development
|
||||
1. Read DEVELOPER_INSTRUCTIONS.md sections 1-3 (45 min)
|
||||
2. Add a simple new item type (1-2 hours)
|
||||
3. Fix a small bug (30 min - 1 hour)
|
||||
|
||||
**Week 2+**: Deep expertise
|
||||
1. Read full DEVELOPER_INSTRUCTIONS.md (1-2 hours)
|
||||
2. Add complex feature (3-6 hours)
|
||||
3. Understand DataModels & AppV2 sheets intimately
|
||||
4. Review git history for patterns (1-2 hours)
|
||||
|
||||
250
QUICK_REFERENCE.md
Normal file
250
QUICK_REFERENCE.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# Les Héritiers FoundryVTT System - Quick Reference
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
npm install # Install once
|
||||
npm run watch # Development watch (LESS → CSS)
|
||||
npm run build # Build once (production)
|
||||
```
|
||||
|
||||
## System at a Glance
|
||||
|
||||
| Item | Details |
|
||||
|------|---------|
|
||||
| **ID** | `fvtt-les-heritiers` |
|
||||
| **Version** | 13.0.7 |
|
||||
| **Foundry** | v13+ (AppV2, DataModels) |
|
||||
| **Language** | French only |
|
||||
| **Architecture** | ES6 modules, Foundry TypeDataModel |
|
||||
|
||||
## Core Actors (2 types)
|
||||
|
||||
- **`personnage`** - Player Character (full biodata + core mechanics)
|
||||
- **`pnj`** - NPC (same structure, simplified UI)
|
||||
|
||||
### Actor Data Structure
|
||||
- **Characteristics** (8): agi, con, for, prec, esp, per, pres, san
|
||||
- **Ranks** (4): tricherie, feerie, masque, heritage
|
||||
- **Combat**: esquive, parade, initiative, corpsacorps, tir, resistances
|
||||
- **Profiles** (6): aventurier, roublard, combattant, erudit, savant, gentleman + magic
|
||||
|
||||
## Core Items (14 types)
|
||||
|
||||
**Combat**: arme, protection
|
||||
**Equipment**: equipement, accessoire
|
||||
**Character Building**: competence, profil, contact, avantage, desavantage
|
||||
**Powers**: pouvoir, capacitenaturelle, atoutfeerique, fee
|
||||
**Magic**: sort
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
modules/
|
||||
├─ heritiers-main.js # Foundry init, hook setup
|
||||
├─ heritiers-actor.js # Actor class
|
||||
├─ heritiers-item.js # Item class
|
||||
├─ heritiers-config.js # HERITIERS_CONFIG (enums)
|
||||
├─ heritiers-utility.js # Static utilities, Handlebars helpers
|
||||
├─ heritiers-commands.js # Chat commands
|
||||
├─ heritiers-combat.js # Combat class
|
||||
├─ models/ # DataModels for each type
|
||||
│ └─ personnage.mjs, pnj.mjs, arme.mjs, ...
|
||||
└─ applications/sheets/ # AppV2 Sheets
|
||||
└─ personnage-sheet.mjs, arme-sheet.mjs, ...
|
||||
templates/ # 27 Handlebars templates
|
||||
lang/fr.json # Localization (minimal, type names only)
|
||||
less/heritiers.less # LESS compilation entry
|
||||
styles/heritiers.css # Compiled CSS (generated)
|
||||
packs/ # 11 LevelDB compendium packs
|
||||
system.json # Manifest
|
||||
template.json.backup # Data schema reference
|
||||
```
|
||||
|
||||
## Key Classes & Exports
|
||||
|
||||
### Actor Classes
|
||||
- **`HeritiersActor`** extends `Actor`
|
||||
- Custom creation: auto-adds utility skills for `personnage`
|
||||
- **PersonnageDataModel**, **PnjDataModel** extend `foundry.abstract.TypeDataModel`
|
||||
|
||||
### Item Classes
|
||||
- **`HeritiersItem`** extends `Item`
|
||||
- **14 DataModels**: ArmeDataModel, CompetenceDataModel, etc.
|
||||
|
||||
### Sheets (AppV2 - Foundry v13+)
|
||||
- **`HeritiersPersonnageSheet`**, **`HeritiersPnjSheet`** extend ActorSheetV2
|
||||
- **`HeritiersArmeSheet`**, **`HeritiersCompetenceSheet`**, etc. (14 item sheets)
|
||||
- All use `HandlebarsApplicationMixin`
|
||||
- Registered in `heritiers-main.js` with `foundry.documents.collections.[Actors|Items].registerSheet()`
|
||||
|
||||
## Adding a New Item Type
|
||||
|
||||
1. Add schema to `template.json.backup`
|
||||
2. Create `modules/models/[typename].mjs` (DataModel)
|
||||
3. Create `modules/applications/sheets/[typename]-sheet.mjs` (AppV2 Sheet)
|
||||
4. Create `templates/item-[typename]-sheet.hbs` (Handlebars template)
|
||||
5. Export from `modules/models/index.mjs`
|
||||
6. Export from `modules/applications/sheets/_module.mjs`
|
||||
7. Register in `heritiers-main.js` (+ other registrations)
|
||||
8. Add to `lang/fr.json` TYPES.Item
|
||||
9. Optionally: add config constants to `heritiers-config.js`
|
||||
|
||||
## Key Constants (heritiers-config.js)
|
||||
|
||||
```javascript
|
||||
HERITIERS_CONFIG = {
|
||||
caracList, // 8 characteristics
|
||||
competenceProfil, // 6 profiles + magic
|
||||
seuilsDifficulte, // 30-level difficulty scale
|
||||
baseTestPouvoir, // feerie, masque, autre
|
||||
resistancePouvoir, // physical/psychic active/passive
|
||||
typePouvoir, // actif, passif, metamorphose
|
||||
// ... 30+ more enums
|
||||
}
|
||||
```
|
||||
|
||||
## Handlebars Template Patterns
|
||||
|
||||
**File Naming**:
|
||||
- `actor-sheet.hbs` → Personnage sheet
|
||||
- `actor-pnj-sheet.hbs` → NPC sheet
|
||||
- `item-[type]-sheet.hbs` → Item sheet
|
||||
- `partial-*.hbs` → Reusable components
|
||||
- `chat-*-result.hbs` → Chat results
|
||||
- `editor-*.hbs` → Editor components
|
||||
|
||||
**Data Access**:
|
||||
```handlebars
|
||||
{{actor.name}} <!-- Actor name -->
|
||||
{{system.caracteristiques.agi.value}} <!-- Nested field -->
|
||||
{{#each system.items as |item key|}} <!-- Loops -->
|
||||
{{#if system.magie}} ... {{/if}} <!-- Conditionals -->
|
||||
{{eq kind "physical"}} <!-- Custom helper -->
|
||||
```
|
||||
|
||||
**Custom Helpers** (60+):
|
||||
- Comparison: `eq`, `ne`, `lt`, `gt`, `gte`, `lte`
|
||||
- String: `upper`, `lower`, `upperFirst`
|
||||
- Array: `includes`, `count`, `notEmpty`
|
||||
- Math: `mul`, `add`, `sub`, `and`, `or`
|
||||
|
||||
## Localization
|
||||
|
||||
**Single File**: `lang/fr.json`
|
||||
```json
|
||||
{
|
||||
"TYPES": {
|
||||
"Actor": { "personnage": "Personnage", "pnj": "PNJ" },
|
||||
"Item": { "arme": "Arme", "competence": "Compétence", ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Strategy**: Minimal i18n
|
||||
- Type labels in TYPES
|
||||
- Field labels in DataModel schema (French initial values)
|
||||
- Config constants in heritiers-config.js (French)
|
||||
- Template text hardcoded (French)
|
||||
|
||||
**No game.i18n calls** - all text is French-only
|
||||
|
||||
## Dice & Combat
|
||||
|
||||
- **Initiative**: 1d10 (decimal)
|
||||
- **Bonus/Malus**: -6 to +6
|
||||
- **Roll Storage**: `HeritiersUtility.rollDataStore` (socket-aware)
|
||||
- **Defender Tracking**: `HeritiersUtility.defenderStore`
|
||||
|
||||
## Socket Communication
|
||||
|
||||
**Channel**: `"system.fvtt-les-heritiers"`
|
||||
**Handler**: `HeritiersUtility.onSocketMesssage(data)`
|
||||
**Use Cases**: Roll updates, multi-client sync
|
||||
|
||||
## Recent Changes (v13.0.7)
|
||||
|
||||
- ✅ AppV2 sheet migration (from legacy v1)
|
||||
- ✅ DataModels adoption
|
||||
- ✅ ES6 modules (.mjs) throughout
|
||||
- ✅ Jan 21: arme, competence, capacitenaturelle, pouvoir, protection updates
|
||||
- ✅ Rank calculation fixes
|
||||
|
||||
## Common Edits
|
||||
|
||||
### Add a new characteristic?
|
||||
1. Update `template.json.backup` → `caracteristiques`
|
||||
2. Update `PersonnageDataModel` → `caracteristiques` SchemaField
|
||||
3. Update `HERITIERS_CONFIG.caracList`
|
||||
4. Update templates that reference characteristics
|
||||
|
||||
### Add a new compendium pack?
|
||||
1. Add to `system.json` → `packs` array
|
||||
2. Create directory in `packs/[packname]/`
|
||||
3. Add `.db` file via Foundry UI or scripts
|
||||
|
||||
### Add a new roll type?
|
||||
1. Add dialog template: `templates/roll-dialog-*.hbs`
|
||||
2. Add result template: `templates/chat-*-result.hbs`
|
||||
3. Add handler in `heritiers-utility.js` or `heritiers-commands.js`
|
||||
4. Emit via socket if multiplayer: `game.socket.emit("system.fvtt-les-heritiers", data)`
|
||||
|
||||
### Change UI layout?
|
||||
1. Edit `templates/actor-sheet.hbs` or `item-*.hbs`
|
||||
2. Update LESS: edit `less/heritiers.less`
|
||||
3. Run `npm run build` or watch with `npm run watch`
|
||||
4. CSS reloads automatically via hotReload
|
||||
|
||||
## Testing Changes
|
||||
|
||||
```bash
|
||||
npm run watch
|
||||
# Open FoundryVTT on http://localhost:30000
|
||||
# Open system's world
|
||||
# Make edits (files auto-reload)
|
||||
# Check browser console for errors
|
||||
# Test in UI
|
||||
```
|
||||
|
||||
## Git Workflow (Development)
|
||||
|
||||
```bash
|
||||
git status
|
||||
git add -A
|
||||
git commit -m "Description of change"
|
||||
git push
|
||||
# Check recent commits: git log --oneline
|
||||
```
|
||||
|
||||
## Useful Commands
|
||||
|
||||
```bash
|
||||
# Count lines of code
|
||||
wc -l modules/*.js modules/**/*.mjs
|
||||
|
||||
# Search for string in code
|
||||
grep -r "searchterm" modules/
|
||||
|
||||
# List all item types
|
||||
grep '"type":' packs/*/[file].db | head -20
|
||||
|
||||
# Check template syntax
|
||||
npm run build 2>&1 | grep error
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- **DEVELOPER_INSTRUCTIONS.md** - Comprehensive guide (this repo)
|
||||
- **README.md** - Project overview & credits
|
||||
- **system.json** - Manifest (metadata, packs, compatibility)
|
||||
- **template.json.backup** - Data schema reference
|
||||
- [FoundryVTT Docs](https://foundryvtt.com/articles/)
|
||||
- [Les Héritiers Books](https://titam-france.fr) - Game rules
|
||||
|
||||
## Notes
|
||||
|
||||
- All code is French (variable names in French, labels in French)
|
||||
- No English strings in UI
|
||||
- Single language system (French)
|
||||
- Heavy use of camelCase following Foundry conventions
|
||||
- AppV2 is the only supported sheet architecture (v13+)
|
||||
@@ -550,9 +550,9 @@
|
||||
}
|
||||
|
||||
.fvtt-les-heritiers .items-list .item {
|
||||
height: 30px;
|
||||
line-height: 24px;
|
||||
padding: 1px 0;
|
||||
height: 24px;
|
||||
line-height: 20px;
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #BBB;
|
||||
}
|
||||
|
||||
@@ -724,7 +724,7 @@
|
||||
/* AppV2 Actor Sheets - Tabs with scrolling */
|
||||
.fvtt-les-heritiers.actor .tab[data-tab] {
|
||||
display: none;
|
||||
padding: 0.5rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
overflow-y: auto;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
@@ -735,7 +735,7 @@
|
||||
|
||||
/* Redesigned skill category headers */
|
||||
.fvtt-les-heritiers.actor .sheet-box {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.fvtt-les-heritiers.actor .items-title-text {
|
||||
@@ -2336,35 +2336,35 @@
|
||||
}
|
||||
|
||||
.item-field-label-short {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 4rem;
|
||||
min-width: 4rem;
|
||||
}
|
||||
|
||||
.item-field-label-short-num {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 2rem;
|
||||
min-width: 2rem;
|
||||
}
|
||||
|
||||
.item-field-label-medium {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 6rem;
|
||||
min-width: 6rem;
|
||||
}
|
||||
|
||||
.item-field-label-long {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 8rem;
|
||||
min-width: 8rem;
|
||||
}
|
||||
|
||||
.item-field-label-long2 {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 14rem;
|
||||
min-width: 14rem;
|
||||
@@ -2376,7 +2376,7 @@
|
||||
}
|
||||
|
||||
.item-field-label-long3 {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 20rem;
|
||||
min-width: 20rem;
|
||||
|
||||
@@ -680,6 +680,14 @@ export class HeritiersActor extends Actor {
|
||||
this.update({ 'system.rang.tricherie': tricherie })
|
||||
return true
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
/* -------------------------------------------- */
|
||||
// Returns the combattant root competence formatted for rollData, used for PNJ attacks
|
||||
_getCombattantCompetence() {
|
||||
const combattant = this.system.competences.combattant
|
||||
return { name: combattant.label, system: { niveau: combattant.niveau } }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getPireCompetence(compName1, compName2) {
|
||||
let comp1 = this.items.find(it => it.name == compName1)
|
||||
@@ -856,13 +864,15 @@ export class HeritiersActor extends Actor {
|
||||
if (arme) {
|
||||
arme = foundry.utils.duplicate(arme)
|
||||
arme.system.isMelee = HeritiersUtility.isArmeMelee(arme)
|
||||
let competenceName = "Tir"
|
||||
let key = "prec"
|
||||
if (arme.system.isMelee) {
|
||||
competenceName = "Mêlée"
|
||||
key = "agi"
|
||||
let key = arme.system.isMelee ? "agi" : "prec"
|
||||
let rollData
|
||||
if (this.type == 'pnj') {
|
||||
rollData = this.getCommonRollData()
|
||||
rollData.competence = this._getCombattantCompetence()
|
||||
} else {
|
||||
let competenceName = arme.system.isMelee ? "Mêlée" : "Tir"
|
||||
rollData = this.getCommonRollData(undefined, competenceName)
|
||||
}
|
||||
let rollData = this.getCommonRollData(undefined, competenceName)
|
||||
rollData.carac = this.system.caracteristiques[key]
|
||||
rollData.caracKey = key
|
||||
rollData.arme = arme
|
||||
@@ -882,9 +892,14 @@ export class HeritiersActor extends Actor {
|
||||
let arme = this.items.get(armeId)
|
||||
if (arme) {
|
||||
let key = "for"
|
||||
let competenceName = "Mêlée"
|
||||
arme.system.isMelee = HeritiersUtility.isArmeMelee(arme)
|
||||
let rollData = this.getCommonRollData(undefined, competenceName)
|
||||
let rollData
|
||||
if (this.type == 'pnj') {
|
||||
rollData = this.getCommonRollData()
|
||||
rollData.competence = this._getCombattantCompetence()
|
||||
} else {
|
||||
rollData = this.getCommonRollData(undefined, "Mêlée")
|
||||
}
|
||||
rollData.carac = this.system.caracteristiques[key]
|
||||
rollData.caracKey = key
|
||||
rollData.arme = foundry.utils.duplicate(arme)
|
||||
@@ -901,8 +916,14 @@ export class HeritiersActor extends Actor {
|
||||
if (arme) {
|
||||
let key = "agi"
|
||||
arme.system.isMelee = HeritiersUtility.isArmeMelee(arme)
|
||||
let rollData
|
||||
if (this.type == 'pnj') {
|
||||
rollData = this.getCommonRollData()
|
||||
rollData.competence = this._getCombattantCompetence()
|
||||
} else {
|
||||
let pireCompetence = this.getPireCompetence("Mêlée", "Mouvement")
|
||||
let rollData = this.getCommonRollData(undefined, pireCompetence.name)
|
||||
rollData = this.getCommonRollData(undefined, pireCompetence.name)
|
||||
}
|
||||
rollData.carac = this.system.caracteristiques[key]
|
||||
rollData.caracKey = key
|
||||
rollData.arme = foundry.utils.duplicate(arme)
|
||||
@@ -917,9 +938,13 @@ export class HeritiersActor extends Actor {
|
||||
async rollAssomerArme(armeId) {
|
||||
let arme = this.items.get(armeId)
|
||||
if (arme) {
|
||||
let competenceName = "Mêlée"
|
||||
//arme.system.isMelee = HeritiersUtility.isArmeMelee(arme)
|
||||
let rollData = this.getCommonRollData(undefined, competenceName)
|
||||
let rollData
|
||||
if (this.type == 'pnj') {
|
||||
rollData = this.getCommonRollData()
|
||||
rollData.competence = this._getCombattantCompetence()
|
||||
} else {
|
||||
rollData = this.getCommonRollData(undefined, "Mêlée")
|
||||
}
|
||||
rollData.carac = this.system.caracteristiques["agi"]
|
||||
rollData.caracKey = "agi"
|
||||
rollData.arme = foundry.utils.duplicate(arme)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -465,9 +465,9 @@ table {
|
||||
font-weight: bold;
|
||||
}
|
||||
.fvtt-les-heritiers .items-list .item {
|
||||
height: 30px;
|
||||
line-height: 24px;
|
||||
padding: 1px 0;
|
||||
height: 24px;
|
||||
line-height: 20px;
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #BBB;
|
||||
}
|
||||
.fvtt-les-heritiers .items-list .item .item-image {
|
||||
@@ -614,7 +614,7 @@ nav.sheet-tabs .item:after {
|
||||
/* AppV2 Actor Sheets - Tabs with scrolling */
|
||||
.fvtt-les-heritiers.actor .tab[data-tab] {
|
||||
display: none;
|
||||
padding: 0.5rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
overflow-y: auto;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
@@ -623,7 +623,7 @@ nav.sheet-tabs .item:after {
|
||||
}
|
||||
/* Redesigned skill category headers */
|
||||
.fvtt-les-heritiers.actor .sheet-box {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
.fvtt-les-heritiers.actor .items-title-text {
|
||||
font-size: 0.95rem;
|
||||
@@ -2005,31 +2005,31 @@ h4.entry-name.document-name {
|
||||
min-width: 9rem;
|
||||
}
|
||||
.item-field-label-short {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 4rem;
|
||||
min-width: 4rem;
|
||||
}
|
||||
.item-field-label-short-num {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 2rem;
|
||||
min-width: 2rem;
|
||||
}
|
||||
.item-field-label-medium {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 6rem;
|
||||
min-width: 6rem;
|
||||
}
|
||||
.item-field-label-long {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 8rem;
|
||||
min-width: 8rem;
|
||||
}
|
||||
.item-field-label-long2 {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 14rem;
|
||||
min-width: 14rem;
|
||||
@@ -2039,7 +2039,7 @@ h4.entry-name.document-name {
|
||||
min-width: 16rem;
|
||||
}
|
||||
.item-field-label-long3 {
|
||||
padding-top: 6px;
|
||||
padding-top: 2px;
|
||||
flex-grow: 1;
|
||||
max-width: 20rem;
|
||||
min-width: 20rem;
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user