Correction sur combat des PNJs
All checks were successful
Release Creation / build (release) Successful in 51s

This commit is contained in:
2026-03-16 23:04:21 +01:00
parent 25b6e30aa8
commit 038aa37838
31 changed files with 1148 additions and 36 deletions

598
DEVELOPER_INSTRUCTIONS.md Normal file
View 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