# 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

