Compare commits
25 Commits
14.0.2
..
92ea0164a2
| Author | SHA1 | Date | |
|---|---|---|---|
| 92ea0164a2 | |||
| 0425ccf723 | |||
| 37ff6ebf1d | |||
| 1c73faeb00 | |||
| 0c42b6ab34 | |||
| d6e7b62c31 | |||
| a3f304c77b | |||
| 1b81b0a3ac | |||
| 3ff2b8e9bb | |||
| 38525c3257 | |||
| f035bcfae2 | |||
| a8bf356d20 | |||
| cd70b70088 | |||
| 14763cc5b3 | |||
| 0258c2e8b7 | |||
| 9b3d34c5d7 | |||
| 335238df3d | |||
| a1519e7a60 | |||
| e55b5cbe15 | |||
| f28719fc6f | |||
| d0423b2017 | |||
| 156672d853 | |||
| 5ab03920d6 | |||
| 9dd6fbd2e7 | |||
| 76ed974352 |
+458
@@ -0,0 +1,458 @@
|
|||||||
|
# Corrections apportées au module Mournblade CYD 2.0
|
||||||
|
|
||||||
|
## Date : 2026-06-07
|
||||||
|
|
||||||
|
## Dernière mise à jour : 2026-06-07
|
||||||
|
|
||||||
|
## Problèmes identifiés et corrigés
|
||||||
|
|
||||||
|
### 1. ❌ Erreur de chargement des partials Handlebars
|
||||||
|
|
||||||
|
**Problème :**
|
||||||
|
Les feuilles de personnage et de créature généraient une erreur lors du rendu :
|
||||||
|
```
|
||||||
|
Failed to render template part "sheet":
|
||||||
|
The partial systems/fvtt-mournblade-cyd-2-0/templates/partial-active-effects.hbs could not be found
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cause :**
|
||||||
|
La fonction `preloadHandlebarsTemplates()` dans `modules/mournblade-cyd2-utility.js` ne préchargeait pas tous les partials nécessaires. Seuls 7 templates étaient préchargés sur 9 utilisés.
|
||||||
|
|
||||||
|
**Partials manquants :**
|
||||||
|
- `partial-active-effects.hbs` - Utilisé dans les feuilles actor-sheet.hbs et creature-sheet.hbs
|
||||||
|
- `partial-item-effects.hbs` - Utilisé dans de nombreux templates d'items
|
||||||
|
|
||||||
|
**Solution :**
|
||||||
|
Ajout des deux partials manquants à la liste des templates préchargés dans la fonction `preloadHandlebarsTemplates()`.
|
||||||
|
|
||||||
|
**Fichier modifié :**
|
||||||
|
- `modules/mournblade-cyd2-utility.js` (lignes 189-201)
|
||||||
|
|
||||||
|
**Code avant :**
|
||||||
|
```javascript
|
||||||
|
const templatePaths = [
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/editor-notes-gm.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-prix.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-automation.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/hud-adversites.hbs',
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code après :**
|
||||||
|
```javascript
|
||||||
|
const templatePaths = [
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/editor-notes-gm.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-header.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-description.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-prix.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-automation.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-active-effects.hbs', // ✅ Ajouté
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-effects.hbs', // ✅ Ajouté
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/hud-adversites.hbs',
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. ❌ Erreur de création d'effet actif
|
||||||
|
|
||||||
|
**Problème :**
|
||||||
|
```
|
||||||
|
base-actor-sheet.mjs:357 MournbladeCYD2 | Failed to create effect: TypeError:
|
||||||
|
Cannot read properties of undefined (reading 'create')
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cause :**
|
||||||
|
La fonction `ActiveEffectDialog.create()` n'existe pas dans Foundry VTT v14. L'API a changé et cette méthode a été supprimée.
|
||||||
|
|
||||||
|
**Solution :**
|
||||||
|
Remplacement de l'appel à `foundry.applications.api.ActiveEffectDialog.create()` par une création directe via `document.createEmbeddedDocuments("ActiveEffect", [data])`, suivie de l'ouverture de la feuille d'édition.
|
||||||
|
|
||||||
|
**Fichiers modifiés :**
|
||||||
|
- `modules/applications/sheets/base-actor-sheet.mjs` (lignes 328-363)
|
||||||
|
- `modules/applications/sheets/base-item-sheet.mjs` (lignes 189-224)
|
||||||
|
|
||||||
|
**Code avant :**
|
||||||
|
```javascript
|
||||||
|
const effect = await foundry.applications.api.ActiveEffectDialog.create({
|
||||||
|
document: this.document,
|
||||||
|
effect: defaultEffectData
|
||||||
|
});
|
||||||
|
|
||||||
|
if (effect) {
|
||||||
|
await this.document.createEmbeddedDocuments("ActiveEffect", [effect.toObject()]);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code après :**
|
||||||
|
```javascript
|
||||||
|
const [effect] = await this.document.createEmbeddedDocuments("ActiveEffect", [defaultEffectData]);
|
||||||
|
|
||||||
|
if (effect) {
|
||||||
|
effect.sheet.render(true);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. ❌ Boucle infinie de chargement d'icône (effect.webp introuvable) ✅
|
||||||
|
|
||||||
|
**Problème :**
|
||||||
|
```
|
||||||
|
404 (Not Found) - GET https://localhost:31000/systems/fvtt-mournblade-cyd-2-0/assets/icons/effect.webp
|
||||||
|
Boucle infinie de tentatives de chargement
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cause :**
|
||||||
|
L'icône `effect.webp` était référencée dans plusieurs fichiers mais n'existait pas dans le dossier `assets/icons/`. Chaque fois que la dialog de création d'effet s'ouvrait, le navigateur essayait de charger cette image manquante en boucle.
|
||||||
|
|
||||||
|
**Fichiers concernés :**
|
||||||
|
- `modules/applications/sheets/base-actor-sheet.mjs` (ligne 336)
|
||||||
|
- `modules/applications/sheets/base-item-sheet.mjs` (ligne 197)
|
||||||
|
- `modules/mournblade-cyd2-effects.js` (lignes 120, 180)
|
||||||
|
- `templates/partial-active-effects.hbs` (ligne 30)
|
||||||
|
- `templates/partial-item-effects.hbs` (ligne 30)
|
||||||
|
|
||||||
|
**Solution :**
|
||||||
|
Remplacement de toutes les références à `effect.webp` par `capacite.webp`, une icône existante dans le dossier `assets/icons/`.
|
||||||
|
|
||||||
|
**Code avant :**
|
||||||
|
```javascript
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/effect.webp"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code après :**
|
||||||
|
```javascript
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/capacite.webp"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. ❌ Propriété dépréciée ActiveEffectDuration.type ✅
|
||||||
|
|
||||||
|
**Problème :**
|
||||||
|
```
|
||||||
|
foundry.mjs:1555 Error: You are accessing ActiveEffectDuration#type,
|
||||||
|
which is now at ActiveEffectDuration#units.
|
||||||
|
Deprecated since Version 14
|
||||||
|
Backwards-compatible support will be removed in Version 16
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cause :**
|
||||||
|
En Foundry VTT v14, la propriété `duration.type` a été renommée en `duration.units`. L'ancien nom était encore supporté pour la compatibilité, mais générait des avertissements et sera supprimé en v16.
|
||||||
|
|
||||||
|
**Fichiers concernés :**
|
||||||
|
- `templates/partial-active-effects.hbs` (lignes 55-61)
|
||||||
|
- `templates/partial-item-effects.hbs` (lignes 51-56)
|
||||||
|
|
||||||
|
**Solution :**
|
||||||
|
Remplacement de toutes les occurrences de `effect.duration.type` par `effect.duration.units` dans les templates.
|
||||||
|
|
||||||
|
**Code avant :**
|
||||||
|
```handlebars
|
||||||
|
{{#if effect.duration.type}}
|
||||||
|
{{#if (eq effect.duration.type "rounds")}}🔄{{/if}}
|
||||||
|
{{#if (eq effect.duration.type "turns")}}🎭{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code après :**
|
||||||
|
```handlebars
|
||||||
|
{{#if effect.duration.units}}
|
||||||
|
{{#if (eq effect.duration.units "rounds")}}🔄{{/if}}
|
||||||
|
{{#if (eq effect.duration.units "turns")}}🎭{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. ❌ Helper Handlebars "subtract" manquant ✅
|
||||||
|
|
||||||
|
**Problème :**
|
||||||
|
```
|
||||||
|
Failed to render Application "MournbladeCYD2PersonnageSheet":
|
||||||
|
Missing helper: "subtract"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cause :**
|
||||||
|
Le template utilisait le helper `subtract` dans `{{#unless (eq index (subtract effect.changes.length 1))}}` mais ce helper n'était pas enregistré dans Handlebars.
|
||||||
|
|
||||||
|
**Fichiers concernés :**
|
||||||
|
- `templates/partial-active-effects.hbs` (ligne 44)
|
||||||
|
- `templates/partial-item-effects.hbs` (ligne 44)
|
||||||
|
- `modules/mournblade-cyd2-utility.js` (helper non enregistré)
|
||||||
|
|
||||||
|
**Solution :**
|
||||||
|
Ajout du helper `subtract` dans la méthode `init()` de `MournbladeCYD2Utility` :
|
||||||
|
|
||||||
|
**Code ajouté :**
|
||||||
|
```javascript
|
||||||
|
Handlebars.registerHelper('subtract', function (a, b) {
|
||||||
|
return parseInt(a) - parseInt(b);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fonctionnalité :**
|
||||||
|
Le helper permet de soustraire deux nombres dans les templates Handlebars, utilisé pour détecter le dernier élément d'une liste.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. ❌ Clés i18n manquantes pour les effets ✅
|
||||||
|
|
||||||
|
**Problème :**
|
||||||
|
Les clés de localisation pour les messages d'erreur des effets actifs étaient manquantes dans `lang/fr.json`, ce qui pouvait entraîner l'affichage de messages en anglais ou vides.
|
||||||
|
|
||||||
|
**Clés manquantes identifiées :**
|
||||||
|
- `MOURNBLADECYD2.EFFECT.createError`
|
||||||
|
- `MOURNBLADECYD2.EFFECT.deleteError`
|
||||||
|
- `MOURNBLADECYD2.EFFECT.applyError`
|
||||||
|
- `MOURNBLADECYD2.EFFECT.applyItemError`
|
||||||
|
- `MOURNBLADECYD2.EFFECT.selectActor`
|
||||||
|
- `MOURNBLADECYD2.EFFECT.toggleError`
|
||||||
|
|
||||||
|
**Solution :**
|
||||||
|
Ajout de toutes les clés manquantes dans la section `EFFECT` du fichier `lang/fr.json`.
|
||||||
|
|
||||||
|
**Traductions ajoutées :**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"createError": "Erreur lors de la création de l'effet",
|
||||||
|
"deleteError": "Erreur lors de la suppression de l'effet",
|
||||||
|
"applyError": "Erreur lors de l'application de l'effet",
|
||||||
|
"applyItemError": "Erreur lors de l'application de l'effet sur l'item",
|
||||||
|
"selectActor": "Sélectionnez un acteur pour appliquer l'effet",
|
||||||
|
"toggleError": "Erreur lors de l'activation/désactivation de l'effet"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fichier modifié :** `lang/fr.json`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. ❌ Clés i18n MNBL manquantes ✅
|
||||||
|
|
||||||
|
**Problème :**
|
||||||
|
Les clés de localisation `MNBL.details` et `MNBL.description` étaient manquantes dans `lang/fr.json`, ce qui entraînait l'affichage de la clé elle-même au lieu d'une traduction.
|
||||||
|
|
||||||
|
**Clés manquantes identifiées :**
|
||||||
|
- `MNBL.details` - Utilisée dans l'onglet "Détails" des fiches d'items
|
||||||
|
- `MNBL.description` - Utilisée dans l'onglet "Description" des fiches d'items
|
||||||
|
|
||||||
|
**Solution :**
|
||||||
|
Ajout des deux clés manquantes dans la section `MNBL` du fichier `lang/fr.json`.
|
||||||
|
|
||||||
|
**Traductions ajoutées :**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"details": "Détails",
|
||||||
|
"description": "Description"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fichier modifié :** `lang/fr.json`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 8. ❌ Onglet "Effets" manquant dans les fiches d'items ✅
|
||||||
|
|
||||||
|
**Problème :**
|
||||||
|
L'onglet "Effets" n'apparaissait pas dans les fiches d'items, empêchant l'accès à la gestion des effets actifs sur les items.
|
||||||
|
|
||||||
|
**Cause :**
|
||||||
|
Dans `templates/partial-item-nav.hbs`, l'onglet "Effets" n'était affiché que si l'item avait déjà des effets (`{{#if item.effects.length}}`).
|
||||||
|
|
||||||
|
**Solution :**
|
||||||
|
Suppression de la condition pour toujours afficher l'onglet "Effets", même lorsque l'item n'a pas encore d'effets actifs.
|
||||||
|
|
||||||
|
**Fichier modifié :** `templates/partial-item-nav.hbs`
|
||||||
|
|
||||||
|
**Code avant :**
|
||||||
|
```handlebars
|
||||||
|
{{#if item.effects.length}}
|
||||||
|
<a class="item" data-tab="effects" ...>{{localize "MOURNBLADECYD2.EFFECT.activeEffects"}}</a>
|
||||||
|
{{/if}}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code après :**
|
||||||
|
```handlebars
|
||||||
|
<a class="item" data-tab="effects" ...>{{localize "MOURNBLADECYD2.EFFECT.activeEffects"}}</a>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 9. ❌ Erreur de parsing JSON (historique)
|
||||||
|
|
||||||
|
**Problème mentionné :**
|
||||||
|
```
|
||||||
|
SyntaxError: Expected ',' or '}' after property value in JSON at position 3753 (line 118 column 4)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Statut :**
|
||||||
|
Cette erreur concernait probablement une ancienne version du fichier `lang/fr.json`. Le fichier actuel est valide et ne contient pas d'erreur de syntaxe.
|
||||||
|
|
||||||
|
**Vérification :**
|
||||||
|
```bash
|
||||||
|
# Le fichier passe la validation JSON
|
||||||
|
node -e "require('./lang/fr.json')" # ✅ Pas d'erreur
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Liste complète des partials Handlebars
|
||||||
|
|
||||||
|
### Partials utilisés dans le système :
|
||||||
|
|
||||||
|
| Partial | Utilisation | Pré-chargé ? |
|
||||||
|
|---------|-------------|--------------|
|
||||||
|
| `partial-item-header.hbs` | En-têtes des items | ✅ Oui |
|
||||||
|
| `partial-item-description.hbs` | Descriptions des items | ✅ Oui |
|
||||||
|
| `partial-item-nav.hbs` | Navigation des items | ✅ Oui |
|
||||||
|
| `partial-item-prix.hbs` | Prix des items | ✅ Oui |
|
||||||
|
| `partial-item-effects.hbs` | Effets des items | ✅ Oui (ajouté) |
|
||||||
|
| `partial-active-effects.hbs` | Effets actifs (actors) | ✅ Oui (ajouté) |
|
||||||
|
| `partial-automation.hbs` | Automatisation | ✅ Oui |
|
||||||
|
| `editor-notes-gm.hbs` | Notes GM | ✅ Oui |
|
||||||
|
| `hud-adversites.hbs` | HUD Adversités | ✅ Oui |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Templates principaux
|
||||||
|
|
||||||
|
### Fiches d'acteurs :
|
||||||
|
- `actor-sheet.hbs` - Feuille de personnage
|
||||||
|
- `creature-sheet.hbs` - Feuille de créature
|
||||||
|
|
||||||
|
### Fiches d'items :
|
||||||
|
- `item-arme-sheet.hbs`
|
||||||
|
- `item-capaciteautomata-sheet.hbs`
|
||||||
|
- `item-competence-sheet.hbs`
|
||||||
|
- `item-don-sheet.hbs`
|
||||||
|
- `item-equipement-sheet.hbs`
|
||||||
|
- `item-historique-sheet.hbs`
|
||||||
|
- `item-monnaie-sheet.hbs`
|
||||||
|
- `item-pacte-sheet.hbs`
|
||||||
|
- `item-pouvoirselementaire-sheet.hbs`
|
||||||
|
- `item-profil-sheet.hbs`
|
||||||
|
- `item-protection-sheet.hbs`
|
||||||
|
- `item-ressource-sheet.hbs`
|
||||||
|
- `item-rune-sheet.hbs`
|
||||||
|
- `item-runeeffect-sheet.hbs`
|
||||||
|
- `item-talent-sheet.hbs`
|
||||||
|
- `item-tendance-sheet.hbs`
|
||||||
|
- `item-traitchaotique-sheet.hbs`
|
||||||
|
- `item-traitdemoniaque-sheet.hbs`
|
||||||
|
- `item-traitespece-sheet.hbs`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Outils de test
|
||||||
|
|
||||||
|
Un script de test a été créé pour valider les corrections :
|
||||||
|
- **Fichier :** `test-templates.js`
|
||||||
|
- **Exécution :** `node test-templates.js`
|
||||||
|
|
||||||
|
**Fonctionnalités du test :**
|
||||||
|
1. ✅ Vérifie que tous les templates préchargés existent
|
||||||
|
2. ✅ Scanne tous les templates pour trouver les partials utilisés
|
||||||
|
3. ✅ Vérifie que tous les partials utilisés sont préchargés
|
||||||
|
4. ✅ Valide le fichier de localisation JSON
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bonnes pratiques rappelées
|
||||||
|
|
||||||
|
### Pré-chargement des templates Handlebars
|
||||||
|
|
||||||
|
En Foundry VTT v12+, il est **obligatoire** de pré-charger tous les partials Handlebars utilisés via la fonction `foundry.applications.handlebars.loadTemplates()` dans le hook `init`.
|
||||||
|
|
||||||
|
**Pourquoi ?**
|
||||||
|
- Les partials ne sont pas chargés automatiquement
|
||||||
|
- Sans pré-chargement, le rendu échouera avec une erreur "partial could not be found"
|
||||||
|
- Le pré-chargement améliore les performances en cacheant les templates
|
||||||
|
|
||||||
|
**Où ?**
|
||||||
|
Dans le hook `init`, avant l'enregistrement des feuilles (sheets) :
|
||||||
|
```javascript
|
||||||
|
Hooks.once("init", async function () {
|
||||||
|
// Pré-charger les templates AVANT d'enregistrer les feuilles
|
||||||
|
await MournbladeCYD2Utility.preloadHandlebarsTemplates();
|
||||||
|
|
||||||
|
// Ensuite enregistrer les feuilles
|
||||||
|
Actors.registerSheet(...);
|
||||||
|
Items.registerSheet(...);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gestion des chemins des templates
|
||||||
|
|
||||||
|
Les chemins doivent être **relatifs au répertoire `systems/`** :
|
||||||
|
- ✅ Bon : `'systems/fvtt-mournblade-cyd-2-0/templates/partial-active-effects.hbs'`
|
||||||
|
- ❌ Mauvais : `'./templates/partial-active-effects.hbs'`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Impact des corrections
|
||||||
|
|
||||||
|
### Avant les corrections :
|
||||||
|
- ❌ Ouverture des feuilles de personnage → Erreur
|
||||||
|
- ❌ Ouverture des feuilles de créature → Erreur
|
||||||
|
- ❌ Affichage des effets actifs → Impossible
|
||||||
|
- ❌ Utilisation des effets d'items → Problèmes potentiels
|
||||||
|
- ❌ Création d'effets actifs → Erreur TypeError
|
||||||
|
- ❌ Boucle infinie de 404 sur effect.webp
|
||||||
|
- ❌ Avertissements duration.type déprécié
|
||||||
|
- ❌ Helper subtract manquant → Erreur de rendu
|
||||||
|
- ❌ Clés i18n manquantes → Messages en anglais
|
||||||
|
- ❌ Clés MNBL.details et MNBL.description manquantes
|
||||||
|
- ❌ Onglet "Effets" manquant dans les fiches d'items
|
||||||
|
|
||||||
|
### Après les corrections :
|
||||||
|
- ✅ Toutes les feuilles s'ouvrent correctement
|
||||||
|
- ✅ Les effets actifs s'affichent correctement
|
||||||
|
- ✅ Tous les items affichent leurs effets
|
||||||
|
- ✅ Plus d'erreurs de templates manquants
|
||||||
|
- ✅ Création d'effets actifs fonctionne correctement
|
||||||
|
- ✅ Plus de boucles infinies de chargement d'icônes
|
||||||
|
- ✅ Plus d'avertissements de compatibilité
|
||||||
|
- ✅ Helper subtract disponible et fonctionnel
|
||||||
|
- ✅ Toutes les clés i18n présentes → Localisation complète
|
||||||
|
- ✅ Toutes les clés MNBL présentes
|
||||||
|
- ✅ Onglet "Effets" toujours visible dans les fiches d'items
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommandations pour le développement futur
|
||||||
|
|
||||||
|
1. **Toujours pré-charger les nouveaux partials** lorsqu'ils sont ajoutés
|
||||||
|
2. **Utiliser un script de test** pour valider les templates après modification
|
||||||
|
3. **Maintenir une liste à jour** des partials utilisés dans le projet
|
||||||
|
4. **Vérifier les erreurs de console** lors du développement
|
||||||
|
5. **Tester toutes les feuilles** après ajout de nouveaux partials
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fichiers modifiés
|
||||||
|
|
||||||
|
| Fichier | Modification | Statut |
|
||||||
|
|---------|--------------|--------|
|
||||||
|
| `modules/mournblade-cyd2-utility.js` | Ajout partials + helper subtract | ✅ Corrigé |
|
||||||
|
| `modules/applications/sheets/base-actor-sheet.mjs` | Correction création effets + icône | ✅ Corrigé |
|
||||||
|
| `modules/applications/sheets/base-item-sheet.mjs` | Correction création effets + icône | ✅ Corrigé |
|
||||||
|
| `modules/mournblade-cyd2-effects.js` | Remplacement effect.webp par capacite.webp | ✅ Corrigé |
|
||||||
|
| `templates/partial-active-effects.hbs` | Remplacement effect.webp + duration.type → duration.units | ✅ Corrigé |
|
||||||
|
| `templates/partial-item-effects.hbs` | Remplacement effect.webp + duration.type → duration.units | ✅ Corrigé |
|
||||||
|
| `templates/partial-item-nav.hbs` | Affichage permanent onglet Effets + clés MNBL | ✅ Corrigé |
|
||||||
|
| `test-templates.js` | Nouveau fichier de test | ✅ Ajouté |
|
||||||
|
| `CORRECTIONS.md` | Documentation des corrections | ✅ Ajouté |
|
||||||
|
| `lang/fr.json` | Ajout des clés i18n EFFECT + MNBL manquantes | ✅ Corrigé |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Auteurs
|
||||||
|
|
||||||
|
Corrections réalisées par : Mistral Vibe (via Vibe CLI)
|
||||||
|
Date : 2026-06-07
|
||||||
+74
-3
@@ -20,7 +20,26 @@
|
|||||||
"runeeffect": "Effet de Rune",
|
"runeeffect": "Effet de Rune",
|
||||||
"tendance": "Tendance",
|
"tendance": "Tendance",
|
||||||
"traitchaotique": "Trait Chaotique",
|
"traitchaotique": "Trait Chaotique",
|
||||||
"traitespece": "Trait d'Espèce"
|
"traitespece": "Trait d'Espèce",
|
||||||
|
"traitdemoniaque": "Trait Démoniaque",
|
||||||
|
"pouvoirselementaire": "Pouvoir Élémentaire",
|
||||||
|
"capaciteautomata": "Capacité d'Automata"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SORCELLERIE": {
|
||||||
|
"tab": "Sorcellerie",
|
||||||
|
"runes": "Runes",
|
||||||
|
"creaturesinvoquees": "Créatures invoquées",
|
||||||
|
"demonslies": "Démons liés",
|
||||||
|
"enchantements": "Enchantements / Automata",
|
||||||
|
"invocationsencours": "Invocations en cours",
|
||||||
|
"coutPouvoirInvocations": "Coût en Pouvoir des invocations"
|
||||||
|
},
|
||||||
|
"SHEETS": {
|
||||||
|
"Item": {
|
||||||
|
"traitdemoniaque": "Trait Démoniaque",
|
||||||
|
"pouvoirselementaire": "Pouvoir Élémentaire",
|
||||||
|
"capaciteautomata": "Capacité d'Automata"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"MOURNBLADE": {
|
"MOURNBLADE": {
|
||||||
@@ -32,10 +51,13 @@
|
|||||||
"MNBL": {
|
"MNBL": {
|
||||||
"all": "Tous",
|
"all": "Tous",
|
||||||
"allegiance": "Allégeance",
|
"allegiance": "Allégeance",
|
||||||
|
"balance": "Balance",
|
||||||
"beastslords": "Seigneurs des Bêtes",
|
"beastslords": "Seigneurs des Bêtes",
|
||||||
"chaos": "Chaos",
|
"chaos": "Chaos",
|
||||||
"difficulty": "Difficulté",
|
"difficulty": "Difficulté",
|
||||||
"duration": "Durée",
|
"duration": "Durée",
|
||||||
|
"details": "Détails",
|
||||||
|
"description": "Description",
|
||||||
"elementslords": "Seigneurs des Éléments",
|
"elementslords": "Seigneurs des Éléments",
|
||||||
"equipment": "Equipement",
|
"equipment": "Equipement",
|
||||||
"examples": "Exemples",
|
"examples": "Exemples",
|
||||||
@@ -56,9 +78,58 @@
|
|||||||
"pronouncerune": "Prononcer",
|
"pronouncerune": "Prononcer",
|
||||||
"rune": "Rune",
|
"rune": "Rune",
|
||||||
"soulcost": "Coût en points de pouvoir",
|
"soulcost": "Coût en points de pouvoir",
|
||||||
"soulpoints": "Points d'Âme",
|
"soulpoints": "Points de Pouvoir",
|
||||||
"traced": "Tracée",
|
"traced": "Tracée",
|
||||||
"tracedrune": "Rune tracée",
|
"tracedrune": "Rune tracée",
|
||||||
"tracerune": "Tracer"
|
"tracerune": "Tracer",
|
||||||
|
"initiative": "Initiative",
|
||||||
|
"initShort": "Init.",
|
||||||
|
"defense": "Défense",
|
||||||
|
"defShort": "Déf.",
|
||||||
|
"protection": "Protection",
|
||||||
|
"protShort": "Prot."
|
||||||
|
},
|
||||||
|
"EFFECT": {
|
||||||
|
"new": "Nouvel Effet",
|
||||||
|
"edit": "Éditer l'effet",
|
||||||
|
"delete": "Supprimer l'effet",
|
||||||
|
"deleteConfirm": "Supprimer l'effet",
|
||||||
|
"deleteConfirmText": "Êtes-vous sûr de vouloir supprimer cet effet ?",
|
||||||
|
"deleteError": "Erreur lors de la suppression de l'effet",
|
||||||
|
"create": "Créer un effet",
|
||||||
|
"createError": "Erreur lors de la création de l'effet",
|
||||||
|
"applyError": "Erreur lors de l'application de l'effet",
|
||||||
|
"applyItemError": "Erreur lors de l'application de l'effet sur l'item",
|
||||||
|
"selectActor": "Sélectionnez un acteur pour appliquer l'effet",
|
||||||
|
"toggleError": "Erreur lors de l'activation/désactivation de l'effet",
|
||||||
|
"name": "Nom de l'effet",
|
||||||
|
"icon": "Icône",
|
||||||
|
"description": "Description",
|
||||||
|
"changes": "Modifications",
|
||||||
|
"addChange": "Ajouter une modification",
|
||||||
|
"duration": "Durée",
|
||||||
|
"durationType": "Type de durée",
|
||||||
|
"durationValue": "Valeur",
|
||||||
|
"disabled": "Désactivé",
|
||||||
|
"transfer": "Transférer au token",
|
||||||
|
"noDuration": "Aucune (permanent)",
|
||||||
|
"rounds": "Rounds",
|
||||||
|
"turns": "Tours",
|
||||||
|
"seconds": "Secondes",
|
||||||
|
"combat": "Jusqu'à la fin du combat",
|
||||||
|
"scene": "Jusqu'à la fin de la scène",
|
||||||
|
"attribute": "Attribut",
|
||||||
|
"value": "Valeur",
|
||||||
|
"mode": "Mode",
|
||||||
|
"modeAdd": "Ajouter",
|
||||||
|
"modeMultiply": "Multiplier",
|
||||||
|
"modeOverride": "Remplacer",
|
||||||
|
"modeUpgrade": "Améliorer",
|
||||||
|
"modeDowngrade": "Dégrader",
|
||||||
|
"activeEffects": "Effets Actifs",
|
||||||
|
"noActiveEffects": "Aucun effet actif",
|
||||||
|
"noItemEffects": "Aucun effet sur cet item",
|
||||||
|
"effectSummary": "Résumé des modifications",
|
||||||
|
"toggleEffect": "Activer/Désactiver"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,3 +23,6 @@ export { default as MournbladeCYD2TalentSheet } from './mournblade-cyd2-talent-s
|
|||||||
export { default as MournbladeCYD2TendanceSheet } from './mournblade-cyd2-tendance-sheet.mjs';
|
export { default as MournbladeCYD2TendanceSheet } from './mournblade-cyd2-tendance-sheet.mjs';
|
||||||
export { default as MournbladeCYD2TraitChaotiqueSheet } from './mournblade-cyd2-traitchaotique-sheet.mjs';
|
export { default as MournbladeCYD2TraitChaotiqueSheet } from './mournblade-cyd2-traitchaotique-sheet.mjs';
|
||||||
export { default as MournbladeCYD2TraitEspeceSheet } from './mournblade-cyd2-traitespece-sheet.mjs';
|
export { default as MournbladeCYD2TraitEspeceSheet } from './mournblade-cyd2-traitespece-sheet.mjs';
|
||||||
|
export { default as MournbladeCYD2TraitDemoniaqueSheet } from './mournblade-cyd2-traitdemoniaque-sheet.mjs';
|
||||||
|
export { default as MournbladeCYD2PouvoirElementaireSheet } from './mournblade-cyd2-pouvoirselementaire-sheet.mjs';
|
||||||
|
export { default as MournbladeCYD2CapaciteAutomataSheet } from './mournblade-cyd2-capaciteautomata-sheet.mjs';
|
||||||
|
|||||||
@@ -60,6 +60,12 @@ export default class MournbladeCYD2ActorSheetV2 extends HandlebarsApplicationMix
|
|||||||
rollDesengager: MournbladeCYD2ActorSheetV2.#onRollDesengager,
|
rollDesengager: MournbladeCYD2ActorSheetV2.#onRollDesengager,
|
||||||
rollInitiative: MournbladeCYD2ActorSheetV2.#onRollInitiative,
|
rollInitiative: MournbladeCYD2ActorSheetV2.#onRollInitiative,
|
||||||
rollFuir: MournbladeCYD2ActorSheetV2.#onRollFuir,
|
rollFuir: MournbladeCYD2ActorSheetV2.#onRollFuir,
|
||||||
|
// Actions pour les ActiveEffects
|
||||||
|
createEffect: MournbladeCYD2ActorSheetV2.#onCreateEffect,
|
||||||
|
editEffect: MournbladeCYD2ActorSheetV2.#onEditEffect,
|
||||||
|
deleteEffect: MournbladeCYD2ActorSheetV2.#onDeleteEffect,
|
||||||
|
toggleEffect: MournbladeCYD2ActorSheetV2.#onToggleEffect,
|
||||||
|
applyEffect: MournbladeCYD2ActorSheetV2.#onApplyEffect,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -176,7 +182,8 @@ export default class MournbladeCYD2ActorSheetV2 extends HandlebarsApplicationMix
|
|||||||
const item = await Item.fromDropData(data);
|
const item = await Item.fromDropData(data);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
if (this.document.uuid === item.parent?.uuid) return;
|
if (this.document.uuid === item.parent?.uuid) return;
|
||||||
return this.document.createEmbeddedDocuments("Item", [item.toObject()]);
|
await this.document.createEmbeddedDocuments("Item", [item.toObject()]);
|
||||||
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDropActor(event, data) {}
|
async _onDropActor(event, data) {}
|
||||||
@@ -309,4 +316,149 @@ export default class MournbladeCYD2ActorSheetV2 extends HandlebarsApplicationMix
|
|||||||
static async #onRollFuir(event, target) {
|
static async #onRollFuir(event, target) {
|
||||||
await this.document.rollFuir();
|
await this.document.rollFuir();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #region ActiveEffects Management
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un nouvel effet actif
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onCreateEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.isEditable || !this.document) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Créer les données par défaut pour un nouvel effet
|
||||||
|
const defaultEffectData = {
|
||||||
|
name: game.i18n.localize("EFFECT.new") || "Nouvel Effet",
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/capacite.webp",
|
||||||
|
description: "",
|
||||||
|
changes: [],
|
||||||
|
disabled: false,
|
||||||
|
duration: {},
|
||||||
|
origin: this.document.uuid,
|
||||||
|
tint: "",
|
||||||
|
transfer: true,
|
||||||
|
flags: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Créer directement l'effet actif sur l'acteur
|
||||||
|
const [effect] = await this.document.createEmbeddedDocuments("ActiveEffect", [defaultEffectData]);
|
||||||
|
|
||||||
|
if (effect) {
|
||||||
|
// Ouvrir la feuille d'édition de l'effet
|
||||||
|
effect.sheet.render(true);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("MournbladeCYD2 | Failed to create effect:", error);
|
||||||
|
ui.notifications.error(
|
||||||
|
game.i18n.localize("EFFECT.createError") ||
|
||||||
|
"Erreur lors de la création de l'effet"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Édite un effet actif existant
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onEditEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.isEditable || !this.document) return;
|
||||||
|
|
||||||
|
const effectId = target?.dataset?.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.document.effects.get(effectId);
|
||||||
|
if (effect) {
|
||||||
|
// Ouvrir la sheet de l'effet pour édition
|
||||||
|
effect.sheet.render(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supprime un effet actif
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onDeleteEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.isEditable || !this.document) return;
|
||||||
|
|
||||||
|
const effectId = target?.dataset?.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.document.effects.get(effectId);
|
||||||
|
if (effect) {
|
||||||
|
const effectName = effect.name;
|
||||||
|
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||||
|
title: game.i18n.localize("EFFECT.deleteConfirm") || "Supprimer l'effet",
|
||||||
|
content: game.i18n.localize("EFFECT.deleteConfirmText", {name: effectName}) ||
|
||||||
|
`Êtes-vous sûr de vouloir supprimer l'effet "${effectName}" ?`
|
||||||
|
});
|
||||||
|
|
||||||
|
if (confirmed) {
|
||||||
|
try {
|
||||||
|
await this.document.deleteEmbeddedDocuments("ActiveEffect", [effectId]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("MournbladeCYD2 | Failed to delete effect:", error);
|
||||||
|
ui.notifications.error(
|
||||||
|
game.i18n.localize("EFFECT.deleteError") ||
|
||||||
|
"Erreur lors de la suppression de l'effet"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle l'état actif/désactivé d'un effet
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onToggleEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.isEditable || !this.document) return;
|
||||||
|
|
||||||
|
const effectId = target?.dataset?.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.document.effects.get(effectId);
|
||||||
|
if (effect) {
|
||||||
|
try {
|
||||||
|
await effect.update({ disabled: !effect.disabled });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("MournbladeCYD2 | Failed to toggle effect:", error);
|
||||||
|
ui.notifications.error(
|
||||||
|
game.i18n.localize("EFFECT.toggleError") ||
|
||||||
|
"Erreur lors du basculement de l'effet"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applique un effet à partir d'un item
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onApplyEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
const effectId = target?.dataset?.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.document.effects.get(effectId);
|
||||||
|
if (effect) {
|
||||||
|
await effect.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,14 @@ export default class MournbladeCYD2ItemSheetV2 extends HandlebarsApplicationMixi
|
|||||||
postItem: MournbladeCYD2ItemSheetV2.#onPostItem,
|
postItem: MournbladeCYD2ItemSheetV2.#onPostItem,
|
||||||
addPredilection: MournbladeCYD2ItemSheetV2.#onAddPredilection,
|
addPredilection: MournbladeCYD2ItemSheetV2.#onAddPredilection,
|
||||||
deletePredilection: MournbladeCYD2ItemSheetV2.#onDeletePredilection,
|
deletePredilection: MournbladeCYD2ItemSheetV2.#onDeletePredilection,
|
||||||
|
addAutomation: MournbladeCYD2ItemSheetV2.#onAddAutomation,
|
||||||
|
deleteAutomation: MournbladeCYD2ItemSheetV2.#onDeleteAutomation,
|
||||||
|
// Actions pour les ActiveEffects
|
||||||
|
createEffect: MournbladeCYD2ItemSheetV2.#onCreateEffect,
|
||||||
|
editEffect: MournbladeCYD2ItemSheetV2.#onEditEffect,
|
||||||
|
deleteEffect: MournbladeCYD2ItemSheetV2.#onDeleteEffect,
|
||||||
|
toggleEffect: MournbladeCYD2ItemSheetV2.#onToggleEffect,
|
||||||
|
applyEffect: MournbladeCYD2ItemSheetV2.#onApplyEffect,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,13 +58,13 @@ export default class MournbladeCYD2ItemSheetV2 extends HandlebarsApplicationMixi
|
|||||||
item: this.document,
|
item: this.document,
|
||||||
system: this.document.system,
|
system: this.document.system,
|
||||||
source: this.document.toObject(),
|
source: this.document.toObject(),
|
||||||
|
config: game.system.mournbladecyd2.config,
|
||||||
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
|
||||||
this.document.system.description || "", { async: true }
|
this.document.system.description || "", { async: true }
|
||||||
),
|
),
|
||||||
isEditMode: true,
|
isEditMode: this.isEditMode,
|
||||||
isEditable: this.isEditable,
|
isEditable: this.isEditable,
|
||||||
isGM: game.user.isGM,
|
isGM: game.user.isGM,
|
||||||
config: game.system.mournbladecyd2.config,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,4 +147,189 @@ export default class MournbladeCYD2ItemSheetV2 extends HandlebarsApplicationMixi
|
|||||||
preds.splice(idx, 1);
|
preds.splice(idx, 1);
|
||||||
await this.document.update({ "system.predilections": preds });
|
await this.document.update({ "system.predilections": preds });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async #onAddAutomation(event) {
|
||||||
|
const automations = foundry.utils.duplicate(this.document.system.automations || []);
|
||||||
|
automations.push({
|
||||||
|
id: foundry.utils.randomID(),
|
||||||
|
eventtype: "on-drop",
|
||||||
|
name: "",
|
||||||
|
bonusname: "vigueur",
|
||||||
|
bonus: 0,
|
||||||
|
competence: "",
|
||||||
|
minLevel: 0,
|
||||||
|
baCost: 0
|
||||||
|
});
|
||||||
|
await this.document.update({
|
||||||
|
"system.automations": automations,
|
||||||
|
"system.isautomated": true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async #onDeleteAutomation(event, target) {
|
||||||
|
const idx = Number(target.dataset.automationIndex);
|
||||||
|
const automations = foundry.utils.duplicate(this.document.system.automations || []);
|
||||||
|
automations.splice(idx, 1);
|
||||||
|
await this.document.update({ "system.automations": automations });
|
||||||
|
if (automations.length === 0) {
|
||||||
|
await this.document.update({ "system.isautomated": false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #region ActiveEffects Management
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un nouvel effet actif sur l'item
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onCreateEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.isEditable || !this.document) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Créer les données par défaut pour un nouvel effet
|
||||||
|
const defaultEffectData = {
|
||||||
|
name: game.i18n.localize("EFFECT.new") || "Nouvel Effet",
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/capacite.webp",
|
||||||
|
description: "",
|
||||||
|
changes: [],
|
||||||
|
disabled: false,
|
||||||
|
duration: {},
|
||||||
|
origin: this.document.uuid,
|
||||||
|
tint: "",
|
||||||
|
transfer: false,
|
||||||
|
flags: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Créer directement l'effet actif sur l'item
|
||||||
|
const [effect] = await this.document.createEmbeddedDocuments("ActiveEffect", [defaultEffectData]);
|
||||||
|
|
||||||
|
if (effect) {
|
||||||
|
// Ouvrir la feuille d'édition de l'effet
|
||||||
|
effect.sheet.render(true);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("MournbladeCYD2 | Failed to create effect:", error);
|
||||||
|
ui.notifications.error(
|
||||||
|
game.i18n.localize("EFFECT.createError") ||
|
||||||
|
"Erreur lors de la création de l'effet"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Édite un effet actif existant sur l'item
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onEditEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.isEditable || !this.document) return;
|
||||||
|
|
||||||
|
const effectId = target?.dataset?.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.document.effects.get(effectId);
|
||||||
|
if (effect) {
|
||||||
|
// Ouvrir la sheet de l'effet pour édition
|
||||||
|
effect.sheet.render(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supprime un effet actif de l'item
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onDeleteEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.isEditable || !this.document) return;
|
||||||
|
|
||||||
|
const effectId = target?.dataset?.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.document.effects.get(effectId);
|
||||||
|
if (effect) {
|
||||||
|
const effectName = effect.name;
|
||||||
|
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||||
|
title: game.i18n.localize("EFFECT.deleteConfirm") || "Supprimer l'effet",
|
||||||
|
content: game.i18n.localize("EFFECT.deleteConfirmText", {name: effectName}) ||
|
||||||
|
`Êtes-vous sûr de vouloir supprimer l'effet "${effectName}" ?`
|
||||||
|
});
|
||||||
|
|
||||||
|
if (confirmed) {
|
||||||
|
try {
|
||||||
|
await this.document.deleteEmbeddedDocuments("ActiveEffect", [effectId]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("MournbladeCYD2 | Failed to delete effect:", error);
|
||||||
|
ui.notifications.error(
|
||||||
|
game.i18n.localize("EFFECT.deleteError") ||
|
||||||
|
"Erreur lors de la suppression de l'effet"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle l'état actif/désactivé d'un effet sur l'item
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onToggleEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.isEditable || !this.document) return;
|
||||||
|
|
||||||
|
const effectId = target?.dataset?.effectId;
|
||||||
|
if (!effectId) return;
|
||||||
|
|
||||||
|
const effect = this.document.effects.get(effectId);
|
||||||
|
if (effect) {
|
||||||
|
try {
|
||||||
|
await effect.update({ disabled: !effect.disabled });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("MournbladeCYD2 | Failed to toggle effect:", error);
|
||||||
|
ui.notifications.error(
|
||||||
|
game.i18n.localize("EFFECT.toggleError") ||
|
||||||
|
"Erreur lors du basculement de l'effet"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applique un effet à partir de l'item à un acteur sélectionné
|
||||||
|
* Cette méthode n'est pas directement utilisable sans acteur cible
|
||||||
|
* Elle est gardée pour compatibilité mais devrait être appelée avec un acteur
|
||||||
|
* @param {Event} event - Événement
|
||||||
|
* @param {HTMLElement} target - Éléments cible
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static async #onApplyEffect(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.isEditable) return;
|
||||||
|
|
||||||
|
const effectId = target?.dataset?.effectId;
|
||||||
|
if (!effectId || !this.document) return;
|
||||||
|
|
||||||
|
const effect = this.document.effects.get(effectId);
|
||||||
|
if (!effect) return;
|
||||||
|
|
||||||
|
// Pour appliquer un effet d'item, il faut sélectionner un acteur
|
||||||
|
// Cette méthode est placeholders - l'application devrait être gérée par drag-drop
|
||||||
|
// ou par une action spécifique qui demande à l'utilisateur de sélectionner un acteur
|
||||||
|
ui.notifications.warn(
|
||||||
|
game.i18n.localize("EFFECT.selectActor") ||
|
||||||
|
"Veuillez d'abord sélectionner un acteur pour appliquer cet effet."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import MournbladeCYD2ItemSheetV2 from "./base-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class MournbladeCYD2CapaciteAutomataSheet extends MournbladeCYD2ItemSheetV2 {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
...super.DEFAULT_OPTIONS,
|
||||||
|
classes: [...super.DEFAULT_OPTIONS.classes, "capaciteautomata"],
|
||||||
|
window: {
|
||||||
|
...super.DEFAULT_OPTIONS.window,
|
||||||
|
title: "SHEETS.Item.capaciteautomata",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/fvtt-mournblade-cyd-2-0/templates/item-capaciteautomata-sheet.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,8 @@ export default class MournbladeCYD2CreatureSheet extends MournbladeCYD2ActorShee
|
|||||||
|
|
||||||
context.skills = actor.getSkills?.() ?? [];
|
context.skills = actor.getSkills?.() ?? [];
|
||||||
context.combativiteList = MournbladeCYD2Utility.getCombativiteList(actor.system.sante?.nbcombativite || 0);
|
context.combativiteList = MournbladeCYD2Utility.getCombativiteList(actor.system.sante?.nbcombativite || 0);
|
||||||
|
context.ameList = MournbladeCYD2Utility.getAmeList(actor.system.ame.nbame, actor.getAmeMax?.() ?? 0);
|
||||||
|
context.ameMaxList = MournbladeCYD2Utility.getAmeMaxList(actor.system.ame.nbame);
|
||||||
context.armes = foundry.utils.duplicate(actor.getWeapons?.() ?? []);
|
context.armes = foundry.utils.duplicate(actor.getWeapons?.() ?? []);
|
||||||
context.protections = foundry.utils.duplicate(actor.getArmors?.() ?? []);
|
context.protections = foundry.utils.duplicate(actor.getArmors?.() ?? []);
|
||||||
context.runes = foundry.utils.duplicate(actor.getRunes?.() ?? []);
|
context.runes = foundry.utils.duplicate(actor.getRunes?.() ?? []);
|
||||||
@@ -37,9 +39,16 @@ export default class MournbladeCYD2CreatureSheet extends MournbladeCYD2ActorShee
|
|||||||
context.equipements = foundry.utils.duplicate(actor.getEquipments?.() ?? []);
|
context.equipements = foundry.utils.duplicate(actor.getEquipments?.() ?? []);
|
||||||
context.monnaies = foundry.utils.duplicate(actor.getMonnaies?.() ?? []);
|
context.monnaies = foundry.utils.duplicate(actor.getMonnaies?.() ?? []);
|
||||||
context.talents = foundry.utils.duplicate(actor.getTalents?.() ?? []);
|
context.talents = foundry.utils.duplicate(actor.getTalents?.() ?? []);
|
||||||
|
context.traitsChaotiques = foundry.utils.duplicate(actor.getTraitsChaotiques?.() ?? []);
|
||||||
|
context.traitsEspeces = foundry.utils.duplicate(actor.getTraitsEspeces?.() ?? []);
|
||||||
context.protectionTotal = actor.getProtectionTotal?.() ?? 0;
|
context.protectionTotal = actor.getProtectionTotal?.() ?? 0;
|
||||||
context.adversiteTotal = (actor.system.adversite?.bleue || 0) + (actor.system.adversite?.rouge || 0) + (actor.system.adversite?.noire || 0);
|
context.adversiteTotal = (actor.system.adversite?.bleue || 0) + (actor.system.adversite?.rouge || 0) + (actor.system.adversite?.noire || 0);
|
||||||
context.initiative = context.combat?.initTotal ?? 0;
|
|
||||||
|
// Utiliser les valeurs manuelles si elles existent, sinon les valeurs calculées
|
||||||
|
context.initiative = actor.system.combat?.inittotal !== undefined ? actor.system.combat.inittotal : (context.combat?.initTotal ?? 0);
|
||||||
|
context.combat.defenseTotal = actor.system.combat?.defensetotal !== undefined ? actor.system.combat.defensetotal : context.combat.defenseTotal;
|
||||||
|
context.protectionTotal = actor.system.combat?.protectiontotal !== undefined ? actor.system.combat.protectiontotal : context.protectionTotal;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export default class MournbladeCYD2DonSheet extends MournbladeCYD2ItemSheetV2 {
|
|||||||
/** @override */
|
/** @override */
|
||||||
async _prepareContext() {
|
async _prepareContext() {
|
||||||
const context = await super._prepareContext();
|
const context = await super._prepareContext();
|
||||||
|
context.owner = this.document.isOwner;
|
||||||
|
context.editable = this.isEditable;
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import MournbladeCYD2ItemSheetV2 from "./base-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class MournbladeCYD2PouvoirElementaireSheet extends MournbladeCYD2ItemSheetV2 {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
...super.DEFAULT_OPTIONS,
|
||||||
|
classes: [...super.DEFAULT_OPTIONS.classes, "pouvoirselementaire"],
|
||||||
|
window: {
|
||||||
|
...super.DEFAULT_OPTIONS.window,
|
||||||
|
title: "SHEETS.Item.pouvoirselementaire",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/fvtt-mournblade-cyd-2-0/templates/item-pouvoirselementaire-sheet.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import MournbladeCYD2ItemSheetV2 from "./base-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class MournbladeCYD2TraitDemoniaqueSheet extends MournbladeCYD2ItemSheetV2 {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
...super.DEFAULT_OPTIONS,
|
||||||
|
classes: [...super.DEFAULT_OPTIONS.classes, "traitdemoniaque"],
|
||||||
|
window: {
|
||||||
|
...super.DEFAULT_OPTIONS.window,
|
||||||
|
title: "SHEETS.Item.traitdemoniaque",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/fvtt-mournblade-cyd-2-0/templates/item-traitdemoniaque-sheet.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les capacités d'Automata MournbladeCYD2
|
||||||
|
*/
|
||||||
|
export default class CapaciteAutomataDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
bonusmalus: new fields.StringField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -88,12 +88,15 @@ export default class CreatureDataModel extends foundry.abstract.TypeDataModel {
|
|||||||
}),
|
}),
|
||||||
combat: new fields.SchemaField({
|
combat: new fields.SchemaField({
|
||||||
initbonus: new fields.NumberField({ initial: 0, integer: true }),
|
initbonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
inittotal: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
vitessebonus: new fields.NumberField({ initial: 0, integer: true }),
|
vitessebonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
bonusdegats: new fields.NumberField({ initial: 0, integer: true }),
|
bonusdegats: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
attaquebonus: new fields.NumberField({ initial: 0, integer: true }),
|
attaquebonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
defensebonus: new fields.NumberField({ initial: 0, integer: true }),
|
defensebonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
defensetotal: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
defensetotale: new fields.BooleanField({ initial: false }),
|
defensetotale: new fields.BooleanField({ initial: false }),
|
||||||
monte: new fields.BooleanField({ initial: false })
|
monte: new fields.BooleanField({ initial: false }),
|
||||||
|
protectiontotal: new fields.NumberField({ initial: 0, integer: true })
|
||||||
}),
|
}),
|
||||||
balance: new fields.SchemaField({
|
balance: new fields.SchemaField({
|
||||||
loi: new fields.NumberField({ initial: 0, integer: true }),
|
loi: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ export { default as RuneEffectDataModel } from './runeeffect.mjs';
|
|||||||
export { default as TendanceDataModel } from './tendance.mjs';
|
export { default as TendanceDataModel } from './tendance.mjs';
|
||||||
export { default as TraitChaotiqueDataModel } from './traitchaotique.mjs';
|
export { default as TraitChaotiqueDataModel } from './traitchaotique.mjs';
|
||||||
export { default as TraitEspeceDataModel } from './traitespece.mjs';
|
export { default as TraitEspeceDataModel } from './traitespece.mjs';
|
||||||
|
export { default as TraitDemoniaqueDataModel } from './traitdemoniaque.mjs';
|
||||||
|
export { default as PouvoirElementaireDataModel } from './pouvoirselementaire.mjs';
|
||||||
|
export { default as CapaciteAutomataDataModel } from './capaciteautomata.mjs';
|
||||||
|
|
||||||
// Modèles d'acteurs
|
// Modèles d'acteurs
|
||||||
export { default as PersonnageDataModel } from './personnage.mjs';
|
export { default as PersonnageDataModel } from './personnage.mjs';
|
||||||
|
|||||||
@@ -102,6 +102,15 @@ export default class PersonnageDataModel extends foundry.abstract.TypeDataModel
|
|||||||
marge: new fields.NumberField({ initial: 0, integer: true }),
|
marge: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
pointschaos: new fields.NumberField({ initial: 0, integer: true }),
|
pointschaos: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
pointsloi: new fields.NumberField({ initial: 0, integer: true })
|
pointsloi: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
}),
|
||||||
|
// Sorcellerie
|
||||||
|
sorcellerie: new fields.SchemaField({
|
||||||
|
runes: new fields.HTMLField({ initial: "" }),
|
||||||
|
creaturesinvoquees: new fields.HTMLField({ initial: "" }),
|
||||||
|
demonslies: new fields.HTMLField({ initial: "" }),
|
||||||
|
enchantements: new fields.HTMLField({ initial: "" }),
|
||||||
|
invocationsencours: new fields.HTMLField({ initial: "" }),
|
||||||
|
coutPouvoirInvocations: new fields.NumberField({ initial: 0, integer: true })
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les pouvoirs élémentaires MournbladeCYD2
|
||||||
|
*/
|
||||||
|
export default class PouvoirElementaireDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
bonusmalus: new fields.StringField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,12 +10,12 @@ export default class ProfilDataModel extends foundry.abstract.TypeDataModel {
|
|||||||
attribut1: new fields.StringField({ initial: "" }),
|
attribut1: new fields.StringField({ initial: "" }),
|
||||||
attribut2: new fields.StringField({ initial: "" }),
|
attribut2: new fields.StringField({ initial: "" }),
|
||||||
attribut3: new fields.StringField({ initial: "" }),
|
attribut3: new fields.StringField({ initial: "" }),
|
||||||
competences: new fields.StringField({ initial: "" }),
|
competences: new fields.HTMLField({ initial: "" }),
|
||||||
talentsinitie: new fields.StringField({ initial: "" }),
|
talentsinitie: new fields.HTMLField({ initial: "" }),
|
||||||
prerequisaguerri: new fields.StringField({ initial: "" }),
|
prerequisaguerri: new fields.HTMLField({ initial: "" }),
|
||||||
talentsaguerri: new fields.StringField({ initial: "" }),
|
talentsaguerri: new fields.HTMLField({ initial: "" }),
|
||||||
prerequismaitre: new fields.StringField({ initial: "" }),
|
prerequismaitre: new fields.HTMLField({ initial: "" }),
|
||||||
talentsmaitre: new fields.StringField({ initial: "" }),
|
talentsmaitre: new fields.HTMLField({ initial: "" }),
|
||||||
equipement: new fields.StringField({ initial: "" })
|
equipement: new fields.StringField({ initial: "" })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default class RuneDataModel extends foundry.abstract.TypeDataModel {
|
|||||||
seuil: new fields.NumberField({ initial: 0, integer: true }),
|
seuil: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
prononcee: new fields.StringField({ initial: "" }),
|
prononcee: new fields.StringField({ initial: "" }),
|
||||||
tracee: new fields.StringField({ initial: "" }),
|
tracee: new fields.StringField({ initial: "" }),
|
||||||
coutAme: new fields.NumberField({ initial: 0, integer: true })
|
coutAme: new fields.StringField({ initial: "" })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ export default class TendanceDataModel extends foundry.abstract.TypeDataModel {
|
|||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
return {
|
return {
|
||||||
description: new fields.HTMLField({ initial: "" }),
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
allegeance: new fields.StringField({ initial: "" })
|
allegeance: new fields.StringField({ initial: "" }),
|
||||||
|
donlie: new fields.StringField({ initial: "" })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ export default class TraitChaotiqueDataModel extends foundry.abstract.TypeDataMo
|
|||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
return {
|
return {
|
||||||
description: new fields.HTMLField({ initial: "" })
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
bonusmalus: new fields.StringField({ initial: "" })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Data model pour les traits démoniaques MournbladeCYD2
|
||||||
|
*/
|
||||||
|
export default class TraitDemoniaqueDataModel extends foundry.abstract.TypeDataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
return {
|
||||||
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
bonusmalus: new fields.StringField({ initial: "" })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@ export default class TraitEspeceDataModel extends foundry.abstract.TypeDataModel
|
|||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
return {
|
return {
|
||||||
description: new fields.HTMLField({ initial: "" })
|
description: new fields.HTMLField({ initial: "" }),
|
||||||
|
bonusmalus: new fields.StringField({ initial: "" })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const MOURNBLADECYD2_CONFIG = {
|
|||||||
tous: localizeOrFallback("MNBL.all", "Tous"),
|
tous: localizeOrFallback("MNBL.all", "Tous"),
|
||||||
chaos: localizeOrFallback("MNBL.chaos", "Chaos"),
|
chaos: localizeOrFallback("MNBL.chaos", "Chaos"),
|
||||||
loi: localizeOrFallback("MNBL.law", "Loi"),
|
loi: localizeOrFallback("MNBL.law", "Loi"),
|
||||||
|
balance: localizeOrFallback("MNBL.balance", "Balance"),
|
||||||
betes: localizeOrFallback("MNBL.beastslords", "Seigneurs des Bêtes"),
|
betes: localizeOrFallback("MNBL.beastslords", "Seigneurs des Bêtes"),
|
||||||
elementaires: localizeOrFallback("MNBL.elementslords", "Seigneurs des Éléments")
|
elementaires: localizeOrFallback("MNBL.elementslords", "Seigneurs des Éléments")
|
||||||
},
|
},
|
||||||
@@ -118,6 +119,96 @@ export const MOURNBLADECYD2_CONFIG = {
|
|||||||
{ key: "personnage", label: "Personnage" },
|
{ key: "personnage", label: "Personnage" },
|
||||||
{ key: "traitespece", label: "Trait d'espèce" }
|
{ key: "traitespece", label: "Trait d'espèce" }
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// Configuration des ActiveEffects
|
||||||
|
effectTypes: {
|
||||||
|
bonus: "Bonus",
|
||||||
|
malus: "Malus",
|
||||||
|
rune: "Effet de Rune",
|
||||||
|
don: "Effet de Don",
|
||||||
|
talent: "Effet de Talent",
|
||||||
|
trait: "Effet de Trait",
|
||||||
|
temporaire: "Effet Temporaire",
|
||||||
|
permanent: "Effet Permanent"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Clés des attributs pour les modifications d'effets
|
||||||
|
effectAttributeKeys: {
|
||||||
|
// Attributs
|
||||||
|
adr: "system.attributs.adr.value",
|
||||||
|
pui: "system.attributs.pui.value",
|
||||||
|
cla: "system.attributs.cla.value",
|
||||||
|
pre: "system.attributs.pre.value",
|
||||||
|
tre: "system.attributs.tre.value",
|
||||||
|
|
||||||
|
// Santé
|
||||||
|
vigueur: "system.sante.vigueur",
|
||||||
|
etat: "system.sante.etat",
|
||||||
|
nbcombativite: "system.sante.nbcombativite",
|
||||||
|
|
||||||
|
// Âme
|
||||||
|
nbame: "system.ame.nbame",
|
||||||
|
seuilpouvoir: "system.ame.seuilpouvoir",
|
||||||
|
etatAme: "system.ame.etat",
|
||||||
|
|
||||||
|
// Bonne Aventure
|
||||||
|
bonneaventure: "system.bonneaventure.base",
|
||||||
|
bonneaventureActuelle: "system.bonneaventure.actuelle",
|
||||||
|
eclat: "system.eclat.value",
|
||||||
|
|
||||||
|
// Combat
|
||||||
|
initiative: "system.combat.inittotal",
|
||||||
|
defense: "system.combat.defensetotal",
|
||||||
|
protection: "system.combat.protectiontotal",
|
||||||
|
|
||||||
|
// Adversités
|
||||||
|
adversiteBleue: "system.adversite.bleue",
|
||||||
|
adversiteRouge: "system.adversite.rouge",
|
||||||
|
adversiteNoire: "system.adversite.noire",
|
||||||
|
|
||||||
|
// Balance
|
||||||
|
loi: "system.balance.loi",
|
||||||
|
chaos: "system.balance.chaos",
|
||||||
|
aspect: "system.balance.aspect",
|
||||||
|
|
||||||
|
// Ressources
|
||||||
|
ressources: "system.ressources.value",
|
||||||
|
|
||||||
|
// Vitesse
|
||||||
|
vitesse: "system.vitesse.value"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Types de bonus/malus supportés (groupés par catégorie)
|
||||||
|
effectTypesConfig: {
|
||||||
|
attribut: {
|
||||||
|
label: "Attribut",
|
||||||
|
keys: ["adr", "pui", "cla", "pre", "tre"]
|
||||||
|
},
|
||||||
|
sante: {
|
||||||
|
label: "Santé",
|
||||||
|
keys: ["vigueur", "etat", "nbcombativite"]
|
||||||
|
},
|
||||||
|
ame: {
|
||||||
|
label: "Âme",
|
||||||
|
keys: ["nbame", "seuilpouvoir", "etatAme"]
|
||||||
|
},
|
||||||
|
combat: {
|
||||||
|
label: "Combat",
|
||||||
|
keys: ["initiative", "defense", "protection"]
|
||||||
|
},
|
||||||
|
bonneAventure: {
|
||||||
|
label: "Bonne Aventure",
|
||||||
|
keys: ["bonneaventure", "bonneaventureActuelle", "eclat"]
|
||||||
|
},
|
||||||
|
adversite: {
|
||||||
|
label: "Adversité",
|
||||||
|
keys: ["adversiteBleue", "adversiteRouge", "adversiteNoire"]
|
||||||
|
},
|
||||||
|
balance: {
|
||||||
|
label: "Balance",
|
||||||
|
keys: ["loi", "chaos", "aspect"]
|
||||||
|
}
|
||||||
|
},
|
||||||
optionsUseTalent: [
|
optionsUseTalent: [
|
||||||
{ key: "permanent", label: "Permanent" },
|
{ key: "permanent", label: "Permanent" },
|
||||||
{ key: "sceance", label: "Une fois par scéance" },
|
{ key: "sceance", label: "Une fois par scéance" },
|
||||||
|
|||||||
@@ -0,0 +1,807 @@
|
|||||||
|
/**
|
||||||
|
* Gestion des ActiveEffects pour Mournblade CYD 2.0
|
||||||
|
* Ce module fournit des utilitaires pour créer, appliquer et gérer les effets actifs
|
||||||
|
* sur les Acteurs et les Items.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class MournbladeCYD2Effects {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise le système de gestion des effets
|
||||||
|
*/
|
||||||
|
static init() {
|
||||||
|
console.log("MournbladeCYD2 | Initializing ActiveEffects management");
|
||||||
|
|
||||||
|
// Hook pour appliquer les modifications des effets
|
||||||
|
Hooks.on("applyActiveEffect", (effect, change, current, delta, changes) => {
|
||||||
|
return this._onApplyActiveEffect(effect, change, current, delta, changes);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hook pour supprimer les modifications des effets
|
||||||
|
Hooks.on("removeActiveEffect", (effect, change, current, delta, changes) => {
|
||||||
|
return this._onRemoveActiveEffect(effect, change, current, delta, changes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse une valeur d'effet en nombre
|
||||||
|
* Gère les strings comme "+2", "-3", "5"
|
||||||
|
* @param {string|number} value - Valeur à parser
|
||||||
|
* @returns {number} - Valeur numérique
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static _parseEffectValue(value) {
|
||||||
|
if (typeof value === 'number') return value;
|
||||||
|
if (typeof value !== 'string') return 0;
|
||||||
|
|
||||||
|
const trimmed = value.trim();
|
||||||
|
if (!trimmed) return 0;
|
||||||
|
|
||||||
|
if (trimmed.startsWith('+')) {
|
||||||
|
return parseFloat(trimmed.substring(1)) || 0;
|
||||||
|
} else if (trimmed.startsWith('-')) {
|
||||||
|
return -(parseFloat(trimmed.substring(1)) || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseFloat(trimmed) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook appelé lorsqu'un effet est appliqué
|
||||||
|
* Permet de personnaliser le calcul des modifications
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static _onApplyActiveEffect(effect, change, current, delta, changes) {
|
||||||
|
// Pour Mournblade, nous voulons gérer les valeurs string (ex: "+1", "-2")
|
||||||
|
// Convertir delta en nombre si nécessaire
|
||||||
|
const numericDelta = this._parseEffectValue(delta);
|
||||||
|
const numericCurrent = current != null ? Number(current) : 0;
|
||||||
|
|
||||||
|
if (!isNaN(numericDelta) && !isNaN(numericCurrent)) {
|
||||||
|
return numericCurrent + numericDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si on ne peut pas calculer, retourner delta tel quel
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook appelé lorsqu'un effet est supprimé
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
static _onRemoveActiveEffect(effect, change, current, delta, changes) {
|
||||||
|
// Logique inverse de l'application
|
||||||
|
// Foundry gère déjà la suppression, ce hook est pour des calculs personnalisés
|
||||||
|
const numericDelta = this._parseEffectValue(delta);
|
||||||
|
const numericCurrent = current != null ? Number(current) : 0;
|
||||||
|
|
||||||
|
if (!isNaN(numericDelta) && !isNaN(numericCurrent)) {
|
||||||
|
return numericCurrent - numericDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Méthodes de création d'effets */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet simple de bonus/malus à un attribut
|
||||||
|
* @param {string} name - Nom de l'effet
|
||||||
|
* @param {string} attribute - Attribut cible (adr, pui, cla, pre, tre, vigueur, etc.)
|
||||||
|
* @param {number|string} value - Valeur du bonus/malus
|
||||||
|
* @param {object} options - Options supplémentaires
|
||||||
|
* @returns {Object|null} - Données de l'effet ou null
|
||||||
|
*/
|
||||||
|
static createSimpleEffect(name, attribute, value, options = {}) {
|
||||||
|
// Validation des paramètres
|
||||||
|
if (!name || typeof name !== "string") {
|
||||||
|
console.warn("MournbladeCYD2 | Effect name must be a non-empty string");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
console.warn("MournbladeCYD2 | Effect value cannot be null or undefined");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const attributeKey = this.getAttributeKey(attribute);
|
||||||
|
if (!attributeKey) {
|
||||||
|
console.warn(`MournbladeCYD2 | Unknown attribute: ${attribute}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normaliser la valeur en string
|
||||||
|
const valueString = String(value).trim();
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: name.trim(),
|
||||||
|
icon: options.icon || "systems/fvtt-mournblade-cyd-2-0/assets/icons/capacite.webp",
|
||||||
|
description: (options.description || "").trim(),
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
key: attributeKey,
|
||||||
|
mode: CONST.ActiveEffect.MODES.ADD,
|
||||||
|
value: valueString,
|
||||||
|
priority: options.priority ?? 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
disabled: Boolean(options.disabled),
|
||||||
|
duration: options.duration || {},
|
||||||
|
origin: options.origin || null,
|
||||||
|
tint: options.tint || "",
|
||||||
|
transfer: options.transfer !== false,
|
||||||
|
statuses: options.statuses || [],
|
||||||
|
flags: options.flags || {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de bonus permanent
|
||||||
|
* @param {string} name - Nom de l'effet
|
||||||
|
* @param {string} attribute - Attribut cible
|
||||||
|
* @param {number|string} value - Valeur du bonus
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createPermanentEffect(name, attribute, value) {
|
||||||
|
return this.createSimpleEffect(name, attribute, value, {
|
||||||
|
duration: {},
|
||||||
|
type: "base"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet temporaire (rounds, turns, etc.)
|
||||||
|
* @param {string} name - Nom de l'effet
|
||||||
|
* @param {string} attribute - Attribut cible
|
||||||
|
* @param {number|string} value - Valeur du bonus/malus
|
||||||
|
* @param {string} durationType - Type de durée (rounds, turns, seconds, combat)
|
||||||
|
* @param {number} durationValue - Valeur de la durée
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createTemporaryEffect(name, attribute, value, durationType, durationValue) {
|
||||||
|
return this.createSimpleEffect(name, attribute, value, {
|
||||||
|
duration: { type: durationType, value: durationValue },
|
||||||
|
type: "temp"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet avec plusieurs modifications
|
||||||
|
* @param {string} name - Nom de l'effet
|
||||||
|
* @param {Array} changes - Array de modifications {key, mode, value}
|
||||||
|
* @param {object} options - Options supplémentaires
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createMultiEffect(name, changes, options = {}) {
|
||||||
|
return {
|
||||||
|
name: name,
|
||||||
|
icon: options.icon || "systems/fvtt-mournblade-cyd-2-0/assets/icons/capacite.webp",
|
||||||
|
description: options.description || "",
|
||||||
|
changes: changes.map(c => ({
|
||||||
|
key: c.key,
|
||||||
|
mode: c.mode || CONST.ActiveEffect.MODES.ADD,
|
||||||
|
value: c.value.toString(),
|
||||||
|
priority: c.priority || 0
|
||||||
|
})),
|
||||||
|
disabled: options.disabled || false,
|
||||||
|
duration: options.duration || {},
|
||||||
|
origin: options.origin || null,
|
||||||
|
tint: options.tint || "",
|
||||||
|
transfer: options.transfer !== false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Méthodes d'application d'effets */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applique un effet à un acteur
|
||||||
|
* @param {Actor} actor - L'acteur cible
|
||||||
|
* @param {Object|ActiveEffect} effectData - Données de l'effet ou instance ActiveEffect
|
||||||
|
* @returns {Promise<ActiveEffect|null>} - L'effet créé ou null
|
||||||
|
*/
|
||||||
|
static async applyEffectToActor(actor, effectData) {
|
||||||
|
if (!actor || !actor.canUserModify(game.user, "update")) return null;
|
||||||
|
|
||||||
|
let effect;
|
||||||
|
if (effectData instanceof foundry.documents.ActiveEffect) {
|
||||||
|
effect = effectData;
|
||||||
|
} else if (effectData?.toObject) {
|
||||||
|
effect = effectData;
|
||||||
|
} else {
|
||||||
|
effect = new CONFIG.ActiveEffect.documentClass(effectData);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const createdEffects = await actor.createEmbeddedDocuments("ActiveEffect", [effect.toObject()]);
|
||||||
|
return createdEffects[0];
|
||||||
|
} catch (error) {
|
||||||
|
console.error("MournbladeCYD2 | Failed to apply effect:", error);
|
||||||
|
ui.notifications?.error(
|
||||||
|
game.i18n?.localize("EFFECT.applyError") ||
|
||||||
|
`Erreur: Impossible d'appliquer l'effet (${error.message})`
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applique les effets d'un item à un acteur
|
||||||
|
* @param {Item} item - L'item source
|
||||||
|
* @param {Actor} actor - L'acteur cible
|
||||||
|
* @returns {Promise<Array<ActiveEffect>>} - Liste des effets appliqués
|
||||||
|
*/
|
||||||
|
static async applyItemEffectsToActor(item, actor) {
|
||||||
|
if (!item?.effects?.length || !actor) return [];
|
||||||
|
if (!actor.canUserModify(game.user, "update")) return [];
|
||||||
|
|
||||||
|
const effectsToApply = [];
|
||||||
|
for (const effectData of item.effects) {
|
||||||
|
// Par défaut, appliquer automatiquement SAUF si explicitement désactivé
|
||||||
|
const autoApply = effectData.getFlag("mournblade-cyd2", "autoApply");
|
||||||
|
if (autoApply !== false) {
|
||||||
|
effectsToApply.push({
|
||||||
|
...effectData.toObject(),
|
||||||
|
origin: item.uuid,
|
||||||
|
name: `${item.name}: ${effectData.name}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effectsToApply.length === 0) return [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const createdEffects = await actor.createEmbeddedDocuments("ActiveEffect", effectsToApply);
|
||||||
|
return createdEffects;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("MournbladeCYD2 | Failed to apply item effects:", error);
|
||||||
|
ui.notifications?.error(
|
||||||
|
game.i18n?.localize("EFFECT.applyItemError") ||
|
||||||
|
`Erreur: Impossible d'appliquer les effets de l'item`
|
||||||
|
);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Méthodes de gestion d'effets */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Désactive un effet
|
||||||
|
* @param {Actor|Item} owner - Le propriétaire de l'effet
|
||||||
|
* @param {string} effectId - ID de l'effet
|
||||||
|
* @returns {Promise<ActiveEffect|null>} - L'effet désactivé
|
||||||
|
*/
|
||||||
|
static async disableEffect(owner, effectId) {
|
||||||
|
if (!owner?.canUserModify(game.user, "update")) return null;
|
||||||
|
|
||||||
|
const effect = owner.effects.get(effectId);
|
||||||
|
if (!effect) return null;
|
||||||
|
|
||||||
|
await effect.update({ disabled: true });
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active un effet
|
||||||
|
* @param {Actor|Item} owner - Le propriétaire de l'effet
|
||||||
|
* @param {string} effectId - ID de l'effet
|
||||||
|
* @returns {Promise<ActiveEffect|null>} - L'effet activé
|
||||||
|
*/
|
||||||
|
static async enableEffect(owner, effectId) {
|
||||||
|
if (!owner?.canUserModify(game.user, "update")) return null;
|
||||||
|
|
||||||
|
const effect = owner.effects.get(effectId);
|
||||||
|
if (!effect) return null;
|
||||||
|
|
||||||
|
await effect.update({ disabled: false });
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle l'état d'un effet (actif/désactivé)
|
||||||
|
* @param {Actor|Item} owner - Le propriétaire de l'effet
|
||||||
|
* @param {string} effectId - ID de l'effet
|
||||||
|
* @returns {Promise<ActiveEffect|null>} - L'effet togglé
|
||||||
|
*/
|
||||||
|
static async toggleEffect(owner, effectId) {
|
||||||
|
if (!owner?.canUserModify(game.user, "update")) return null;
|
||||||
|
|
||||||
|
const effect = owner.effects.get(effectId);
|
||||||
|
if (!effect) return null;
|
||||||
|
|
||||||
|
await effect.update({ disabled: !effect.disabled });
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supprime un effet
|
||||||
|
* @param {Actor|Item} owner - Le propriétaire de l'effet
|
||||||
|
* @param {string} effectId - ID de l'effet
|
||||||
|
* @returns {Promise<ActiveEffect|null>} - L'effet supprimé
|
||||||
|
*/
|
||||||
|
static async deleteEffect(owner, effectId) {
|
||||||
|
if (!owner?.canUserModify(game.user, "delete")) return null;
|
||||||
|
|
||||||
|
const effect = owner.effects.get(effectId);
|
||||||
|
if (!effect) return null;
|
||||||
|
|
||||||
|
await owner.deleteEmbeddedDocuments("ActiveEffect", [effectId]);
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Méthodes utilitaires */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtient la clé complète pour un attribut
|
||||||
|
* @param {string} attribute - Attribut court (adr, pui, cla, pre, tre, vigueur, etc.)
|
||||||
|
* @returns {string|null} - Clé complète ou null
|
||||||
|
*/
|
||||||
|
static getAttributeKey(attribute) {
|
||||||
|
if (!attribute) return null;
|
||||||
|
|
||||||
|
const config = game.system.mournbladecyd2?.config;
|
||||||
|
if (!config?.effectAttributeKeys) return null;
|
||||||
|
|
||||||
|
// Normaliser en minuscules pour correspondre à la config
|
||||||
|
const normalizedAttribute = attribute.toLowerCase().trim();
|
||||||
|
return config.effectAttributeKeys[normalizedAttribute] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtient tous les attributs modifiables
|
||||||
|
* @returns {Object} - Map des attributs courts vers les clés complètes
|
||||||
|
*/
|
||||||
|
static getAllAttributeKeys() {
|
||||||
|
const config = game.system.mournbladecyd2?.config;
|
||||||
|
return config?.effectAttributeKeys || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtient les effets actifs d'un acteur
|
||||||
|
* @param {Actor} actor - L'acteur
|
||||||
|
* @returns {Array<ActiveEffect>} - Liste des effets actifs (non désactivés)
|
||||||
|
*/
|
||||||
|
static getActiveEffects(actor) {
|
||||||
|
if (!actor?.effects) return [];
|
||||||
|
return actor.effects.filter(e => !e.disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtient les effets désactivés d'un acteur
|
||||||
|
* @param {Actor} actor - L'acteur
|
||||||
|
* @returns {Array<ActiveEffect>} - Liste des effets désactivés
|
||||||
|
*/
|
||||||
|
static getDisabledEffects(actor) {
|
||||||
|
if (!actor?.effects) return [];
|
||||||
|
return actor.effects.filter(e => e.disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtient les effets par origine
|
||||||
|
* @param {Actor} actor - L'acteur
|
||||||
|
* @param {string} originUuid - UUID de l'origine
|
||||||
|
* @returns {Array<ActiveEffect>} - Liste des effets de cette origine
|
||||||
|
*/
|
||||||
|
static getEffectsByOrigin(actor, originUuid) {
|
||||||
|
if (!actor?.effects) return [];
|
||||||
|
return actor.effects.filter(e => e.origin === originUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtient les effets temporaires en cours
|
||||||
|
* @param {Actor} actor - L'acteur
|
||||||
|
* @returns {Array<ActiveEffect>} - Liste des effets temporaires actifs
|
||||||
|
*/
|
||||||
|
static getActiveTemporaryEffects(actor) {
|
||||||
|
if (!actor?.effects) return [];
|
||||||
|
return actor.effects.filter(e => !e.disabled && e.duration?.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcule la valeur totale des modifications pour une clé donnée
|
||||||
|
* @param {Actor} actor - L'acteur
|
||||||
|
* @param {string} key - Clé à vérifier
|
||||||
|
* @returns {number} - Somme des modifications
|
||||||
|
*/
|
||||||
|
static getTotalModificationForKey(actor, key) {
|
||||||
|
if (!actor?.effects) return 0;
|
||||||
|
|
||||||
|
let total = 0;
|
||||||
|
for (const effect of actor.effects) {
|
||||||
|
if (effect.disabled) continue;
|
||||||
|
|
||||||
|
for (const change of effect.changes || []) {
|
||||||
|
if (change.key === key && change.mode === CONST.ActiveEffect.MODES.ADD) {
|
||||||
|
total += Number(change.value) || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtient toutes les modifications actives groupées par clé
|
||||||
|
* @param {Actor} actor - L'acteur
|
||||||
|
* @returns {Object} - Objet avec les clés et les valeurs totales
|
||||||
|
*/
|
||||||
|
static getAllActiveModifications(actor) {
|
||||||
|
if (!actor?.effects) return {};
|
||||||
|
|
||||||
|
const modifications = {};
|
||||||
|
|
||||||
|
for (const effect of actor.effects) {
|
||||||
|
if (effect.disabled) continue;
|
||||||
|
|
||||||
|
for (const change of effect.changes || []) {
|
||||||
|
if (!modifications[change.key]) {
|
||||||
|
modifications[change.key] = {
|
||||||
|
value: 0,
|
||||||
|
effects: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appliquer selon le mode
|
||||||
|
const numericValue = Number(change.value) || 0;
|
||||||
|
switch (change.mode) {
|
||||||
|
case CONST.ActiveEffect.MODES.ADD:
|
||||||
|
modifications[change.key].value += numericValue;
|
||||||
|
break;
|
||||||
|
case CONST.ActiveEffect.MODES.OVERRIDE:
|
||||||
|
modifications[change.key].value = numericValue;
|
||||||
|
modifications[change.key].overridden = true;
|
||||||
|
break;
|
||||||
|
case CONST.ActiveEffect.MODES.MULTIPLY:
|
||||||
|
// Ne peut pas être additionné, stocké séparément
|
||||||
|
if (!modifications[change.key].multipliers) {
|
||||||
|
modifications[change.key].multipliers = [];
|
||||||
|
}
|
||||||
|
modifications[change.key].multipliers.push(numericValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
modifications[change.key].effects.push(effect.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Méthodes de création d'effets prédéfinis */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de bonus d'attribut
|
||||||
|
* @param {string} attribute - Attribut (adr, pui, cla, pre, tre)
|
||||||
|
* @param {number} value - Valeur du bonus
|
||||||
|
* @param {string} source - Source de l'effet
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createAttributeBonusEffect(attribute, value, source = "Effet") {
|
||||||
|
const attrNames = {
|
||||||
|
adr: "Adresse",
|
||||||
|
pui: "Puissance",
|
||||||
|
cla: "Clairvoyance",
|
||||||
|
pre: "Présence",
|
||||||
|
tre: "Trempe"
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`${source}: Bonus de ${attrNames[attribute] || attribute}`,
|
||||||
|
attribute,
|
||||||
|
`+${value}`,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/attributs.webp",
|
||||||
|
type: "base"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de malus d'attribut
|
||||||
|
* @param {string} attribute - Attribut
|
||||||
|
* @param {number} value - Valeur du malus (positif)
|
||||||
|
* @param {string} source - Source de l'effet
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createAttributeMalusEffect(attribute, value, source = "Effet") {
|
||||||
|
const attrNames = {
|
||||||
|
adr: "Adresse",
|
||||||
|
pui: "Puissance",
|
||||||
|
cla: "Clairvoyance",
|
||||||
|
pre: "Présence",
|
||||||
|
tre: "Trempe"
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`${source}: Malus de ${attrNames[attribute] || attribute}`,
|
||||||
|
attribute,
|
||||||
|
`-${value}`,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/malus.webp",
|
||||||
|
type: "base"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de bonus à la Vigueur
|
||||||
|
* @param {number} value - Valeur du bonus
|
||||||
|
* @param {string} source - Source de l'effet
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createVigueurBonusEffect(value, source = "Effet") {
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`${source}: Bonus de Vigueur`,
|
||||||
|
"vigueur",
|
||||||
|
`+${value}`,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/vigueur.webp",
|
||||||
|
type: "base"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de bonus au Seuil de Pouvoir
|
||||||
|
* @param {number} value - Valeur du bonus
|
||||||
|
* @param {string} source - Source de l'effet
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createSeuilPouvoirBonusEffect(value, source = "Effet") {
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`${source}: Bonus au Seuil de Pouvoir`,
|
||||||
|
"seuilPouvoir",
|
||||||
|
`+${value}`,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/ame.webp",
|
||||||
|
type: "base"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de bonus à la Bonne Aventure
|
||||||
|
* @param {number} value - Valeur du bonus
|
||||||
|
* @param {string} source - Source de l'effet
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createBonneAventureBonusEffect(value, source = "Effet") {
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`${source}: Bonus de Bonne Aventure`,
|
||||||
|
"bonneAventure",
|
||||||
|
`+${value}`,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/bonneaventure.webp",
|
||||||
|
type: "base"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de bonus à l'Initiative
|
||||||
|
* @param {number} value - Valeur du bonus
|
||||||
|
* @param {string} source - Source de l'effet
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createInitiativeBonusEffect(value, source = "Effet") {
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`${source}: Bonus d'Initiative`,
|
||||||
|
"initiative",
|
||||||
|
`+${value}`,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/initiative.webp",
|
||||||
|
type: "temp",
|
||||||
|
duration: { type: "rounds", value: 1 }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de bonus à la Défense
|
||||||
|
* @param {number} value - Valeur du bonus
|
||||||
|
* @param {string} source - Source de l'effet
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createDefenseBonusEffect(value, source = "Effet") {
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`${source}: Bonus de Défense`,
|
||||||
|
"defense",
|
||||||
|
`+${value}`,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/defense.webp",
|
||||||
|
type: "temp",
|
||||||
|
duration: { type: "rounds", value: 1 }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de bonus à la Protection
|
||||||
|
* @param {number} value - Valeur du bonus
|
||||||
|
* @param {string} source - Source de l'effet
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createProtectionBonusEffect(value, source = "Effet") {
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`${source}: Bonus de Protection`,
|
||||||
|
"protection",
|
||||||
|
`+${value}`,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/protection.webp",
|
||||||
|
type: "base"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Méthodes de gestion des statuts */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet qui applique un statut
|
||||||
|
* @param {string} status - Nom du statut
|
||||||
|
* @param {string} source - Source de l'effet
|
||||||
|
* @returns {Object} - Données de l'effet
|
||||||
|
*/
|
||||||
|
static createStatusEffect(status, source = "Effet") {
|
||||||
|
return {
|
||||||
|
name: `${source}: ${status}`,
|
||||||
|
icon: `systems/fvtt-mournblade-cyd-2-0/assets/icons/status_${status.toLowerCase()}.webp`,
|
||||||
|
description: `Applique le statut ${status}`,
|
||||||
|
changes: [],
|
||||||
|
statuses: [status],
|
||||||
|
disabled: false,
|
||||||
|
duration: {},
|
||||||
|
origin: null,
|
||||||
|
tint: "",
|
||||||
|
transfer: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet d'adversité bleue
|
||||||
|
* @param {number} value - Nombre d'adversités
|
||||||
|
* @returns {Object|null} - Données de l'effet ou null
|
||||||
|
*/
|
||||||
|
static createAdversiteBleueEffect(value) {
|
||||||
|
if (value == null) return null;
|
||||||
|
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`Adversité Bleue: +${value}`,
|
||||||
|
"adversite.bleue",
|
||||||
|
value,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/gemme_bleue.webp",
|
||||||
|
duration: { type: "rounds", value: 1 },
|
||||||
|
statuses: ["adversite-bleue"]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet d'adversité rouge
|
||||||
|
* @param {number} value - Nombre d'adversités
|
||||||
|
* @returns {Object|null} - Données de l'effet ou null
|
||||||
|
*/
|
||||||
|
static createAdversiteRougeEffect(value) {
|
||||||
|
if (value == null) return null;
|
||||||
|
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`Adversité Rouge: +${value}`,
|
||||||
|
"adversite.rouge",
|
||||||
|
value,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/gemme_rouge.webp",
|
||||||
|
duration: { type: "rounds", value: 1 },
|
||||||
|
statuses: ["adversite-rouge"]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet d'adversité noire
|
||||||
|
* @param {number} value - Nombre d'adversités
|
||||||
|
* @returns {Object|null} - Données de l'effet ou null
|
||||||
|
*/
|
||||||
|
static createAdversiteNoireEffect(value) {
|
||||||
|
if (value == null) return null;
|
||||||
|
|
||||||
|
return this.createSimpleEffect(
|
||||||
|
`Adversité Noire: +${value}`,
|
||||||
|
"adversite.noire",
|
||||||
|
value,
|
||||||
|
{
|
||||||
|
icon: "systems/fvtt-mournblade-cyd-2-0/assets/icons/gemme_noire.webp",
|
||||||
|
duration: { type: "rounds", value: 1 },
|
||||||
|
statuses: ["adversite-noire"]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Méthodes pour les Runes */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de Rune prononcée
|
||||||
|
* @param {Object} rune - Données de la rune
|
||||||
|
* @param {number} pointsAme - Points de pouvoir dépensés
|
||||||
|
* @returns {Object|null} - Données de l'effet ou null
|
||||||
|
*/
|
||||||
|
static createRunePrononceeEffect(rune, pointsAme) {
|
||||||
|
if (!rune || !rune.name || pointsAme == null) return null;
|
||||||
|
|
||||||
|
// Utiliser une icône par défaut si l'image de la rune est l'image par défaut
|
||||||
|
const icon = rune.img?.includes('/blank.png') || !rune.img
|
||||||
|
? "systems/fvtt-mournblade-cyd-2-0/assets/icons/rune.webp"
|
||||||
|
: rune.img;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: `Rune: ${rune.name} (Prononcée)`,
|
||||||
|
icon: icon,
|
||||||
|
description: rune.system?.description || "",
|
||||||
|
changes: [], // Les modifications spécifiques peuvent être ajoutées par les appels
|
||||||
|
disabled: false,
|
||||||
|
duration: { type: "rounds", value: Math.ceil(pointsAme / 3) },
|
||||||
|
origin: rune.uuid || null,
|
||||||
|
tint: "#00ff00",
|
||||||
|
transfer: true,
|
||||||
|
flags: {
|
||||||
|
"mournblade-cyd2": {
|
||||||
|
runeId: rune._id,
|
||||||
|
runeType: "prononcee",
|
||||||
|
pointsAme: pointsAme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un effet de Rune tracée
|
||||||
|
* @param {Object} rune - Données de la rune
|
||||||
|
* @param {number} pointsAme - Points de pouvoir dépensés
|
||||||
|
* @returns {Object|null} - Données de l'effet ou null
|
||||||
|
*/
|
||||||
|
static createRuneTraceeEffect(rune, pointsAme) {
|
||||||
|
if (!rune || !rune.name || pointsAme == null) return null;
|
||||||
|
|
||||||
|
// Utiliser une icône par défaut si l'image de la rune est l'image par défaut
|
||||||
|
const icon = rune.img?.includes('/blank.png') || !rune.img
|
||||||
|
? "systems/fvtt-mournblade-cyd-2-0/assets/icons/rune.webp"
|
||||||
|
: rune.img;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: `Rune: ${rune.name} (Tracée)`,
|
||||||
|
icon: icon,
|
||||||
|
description: rune.system?.description || "",
|
||||||
|
changes: [], // Les modifications spécifiques peuvent être ajoutées par les appels
|
||||||
|
disabled: false,
|
||||||
|
duration: { type: "rounds", value: Math.ceil(pointsAme / 3) * 2 },
|
||||||
|
origin: rune.uuid || null,
|
||||||
|
tint: "#0000ff",
|
||||||
|
transfer: true,
|
||||||
|
flags: {
|
||||||
|
"mournblade-cyd2": {
|
||||||
|
runeId: rune._id,
|
||||||
|
runeType: "tracee",
|
||||||
|
pointsAme: pointsAme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialisation automatique
|
||||||
|
Hooks.once("init", () => {
|
||||||
|
MournbladeCYD2Effects.init();
|
||||||
|
});
|
||||||
@@ -16,6 +16,7 @@ import { MournbladeCYD2Item } from "./mournblade-cyd2-item.js";
|
|||||||
import { MournbladeCYD2Automation } from "./mournblade-cyd2-automation.js";
|
import { MournbladeCYD2Automation } from "./mournblade-cyd2-automation.js";
|
||||||
import { MournbladeCYD2TokenHud } from "./mournblade-cyd2-hud.js";
|
import { MournbladeCYD2TokenHud } from "./mournblade-cyd2-hud.js";
|
||||||
import { MOURNBLADECYD2_CONFIG } from "./mournblade-cyd2-config.js";
|
import { MOURNBLADECYD2_CONFIG } from "./mournblade-cyd2-config.js";
|
||||||
|
import { MournbladeCYD2Effects } from "./mournblade-cyd2-effects.js";
|
||||||
|
|
||||||
// Import DataModels
|
// Import DataModels
|
||||||
import * as models from "./models/index.mjs";
|
import * as models from "./models/index.mjs";
|
||||||
@@ -69,11 +70,15 @@ Hooks.once("init", async function () {
|
|||||||
runeeffect: models.RuneEffectDataModel,
|
runeeffect: models.RuneEffectDataModel,
|
||||||
tendance: models.TendanceDataModel,
|
tendance: models.TendanceDataModel,
|
||||||
traitchaotique: models.TraitChaotiqueDataModel,
|
traitchaotique: models.TraitChaotiqueDataModel,
|
||||||
traitespece: models.TraitEspeceDataModel
|
traitespece: models.TraitEspeceDataModel,
|
||||||
|
traitdemoniaque: models.TraitDemoniaqueDataModel,
|
||||||
|
pouvoirselementaire: models.PouvoirElementaireDataModel,
|
||||||
|
capaciteautomata: models.CapaciteAutomataDataModel
|
||||||
}
|
}
|
||||||
game.system.mournbladecyd2 = {
|
game.system.mournbladecyd2 = {
|
||||||
MournbladeCYD2Utility,
|
MournbladeCYD2Utility,
|
||||||
MournbladeCYD2Automation,
|
MournbladeCYD2Automation,
|
||||||
|
MournbladeCYD2Effects,
|
||||||
config: MOURNBLADECYD2_CONFIG
|
config: MOURNBLADECYD2_CONFIG
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,6 +104,9 @@ Hooks.once("init", async function () {
|
|||||||
foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TendanceSheet, { types: ["tendance"], makeDefault: true });
|
foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TendanceSheet, { types: ["tendance"], makeDefault: true });
|
||||||
foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TraitChaotiqueSheet, { types: ["traitchaotique"], makeDefault: true });
|
foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TraitChaotiqueSheet, { types: ["traitchaotique"], makeDefault: true });
|
||||||
foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TraitEspeceSheet, { types: ["traitespece"], makeDefault: true });
|
foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TraitEspeceSheet, { types: ["traitespece"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2TraitDemoniaqueSheet, { types: ["traitdemoniaque"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2PouvoirElementaireSheet, { types: ["pouvoirselementaire"], makeDefault: true });
|
||||||
|
foundry.documents.collections.Items.registerSheet("fvtt-mournblade-cyd-2-0", sheets.MournbladeCYD2CapaciteAutomataSheet, { types: ["capaciteautomata"], makeDefault: true });
|
||||||
|
|
||||||
MournbladeCYD2Utility.init()
|
MournbladeCYD2Utility.init()
|
||||||
MournbladeCYD2Automation.init()
|
MournbladeCYD2Automation.init()
|
||||||
@@ -123,14 +131,14 @@ function welcomeMessage() {
|
|||||||
<div class="section-text">
|
<div class="section-text">
|
||||||
<strong>Livres nécessaires</strong>
|
<strong>Livres nécessaires</strong>
|
||||||
<p>Les livres de Mournblade sont nécessaires pour jouer. Supplément de conversion CYD 2.0 requis.</p>
|
<p>Les livres de Mournblade sont nécessaires pour jouer. Supplément de conversion CYD 2.0 requis.</p>
|
||||||
<a class="welcome-link" href="https://www.titam-france.fr" target="_blank"><i class="fas fa-external-link-alt"></i>titam-france.fr</a>
|
<a class="welcome-link" href="https://www.lahiette.com/leratierbretonnien/mournblade-et-le-cyd-2-0/" target="_blank"><i class="fas fa-external-link-alt"></i>Règles PAO 0.9</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="welcome-section">
|
<div class="welcome-section">
|
||||||
<div class="section-icon"><i class="fas fa-copyright"></i></div>
|
<div class="section-icon"><i class="fas fa-copyright"></i></div>
|
||||||
<div class="section-text">
|
<div class="section-text">
|
||||||
<strong>Droits</strong>
|
<strong>Droits</strong>
|
||||||
<p>Mournblade est un jeu publié par Titam France / Sombres Projets, tous les droits leur appartiennent.</p>
|
<p>Mournblade est un jeu Titam.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="welcome-section">
|
<div class="welcome-section">
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ export class MournbladeCYD2Utility {
|
|||||||
Handlebars.registerHelper('mul', function (a, b) {
|
Handlebars.registerHelper('mul', function (a, b) {
|
||||||
return parseInt(a) * parseInt(b);
|
return parseInt(a) * parseInt(b);
|
||||||
})
|
})
|
||||||
|
Handlebars.registerHelper('subtract', function (a, b) {
|
||||||
|
return parseInt(a) - parseInt(b);
|
||||||
|
})
|
||||||
Handlebars.registerHelper('select', function(value, options) {
|
Handlebars.registerHelper('select', function(value, options) {
|
||||||
const html = options.fn(this);
|
const html = options.fn(this);
|
||||||
const escaped = String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
const escaped = String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
@@ -195,6 +198,8 @@ export class MournbladeCYD2Utility {
|
|||||||
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs',
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-nav.hbs',
|
||||||
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-prix.hbs',
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-prix.hbs',
|
||||||
'systems/fvtt-mournblade-cyd-2-0/templates/partial-automation.hbs',
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-automation.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-active-effects.hbs',
|
||||||
|
'systems/fvtt-mournblade-cyd-2-0/templates/partial-item-effects.hbs',
|
||||||
'systems/fvtt-mournblade-cyd-2-0/templates/hud-adversites.hbs',
|
'systems/fvtt-mournblade-cyd-2-0/templates/hud-adversites.hbs',
|
||||||
]
|
]
|
||||||
return foundry.applications.handlebars.loadTemplates(templatePaths);
|
return foundry.applications.handlebars.loadTemplates(templatePaths);
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
MANIFEST-000410
|
MANIFEST-000431
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
2026/05/24-16:13:27.948127 7fdf5bfff6c0 Recovering log #409
|
2026/06/07-00:21:50.466229 7f15cf3fe6c0 Recovering log #429
|
||||||
2026/05/24-16:13:27.958589 7fdf5bfff6c0 Delete type=0 #409
|
2026/06/07-00:21:50.475486 7f15cf3fe6c0 Delete type=3 #427
|
||||||
2026/05/24-16:13:27.958609 7fdf5bfff6c0 Delete type=3 #408
|
2026/06/07-00:21:50.475515 7f15cf3fe6c0 Delete type=0 #429
|
||||||
2026/05/24-16:49:30.908639 7fdf5affd6c0 Level-0 table #413: started
|
|
||||||
2026/05/24-16:49:30.908660 7fdf5affd6c0 Level-0 table #413: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.941518 7fdf5affd6c0 Manual compaction at level-0 from '!journal!gVybbv17TFY8o3Y4' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end)
|
|
||||||
2026/05/24-16:49:30.959159 7fdf5affd6c0 Manual compaction at level-1 from '!journal!gVybbv17TFY8o3Y4' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
2026/05/24-16:10:55.778032 7f1c57fff6c0 Recovering log #407
|
2026/06/07-00:01:17.675368 7f15ce3fc6c0 Recovering log #425
|
||||||
2026/05/24-16:10:55.794066 7f1c57fff6c0 Delete type=0 #407
|
2026/06/07-00:01:17.685411 7f15ce3fc6c0 Delete type=3 #423
|
||||||
2026/05/24-16:10:55.794127 7f1c57fff6c0 Delete type=3 #406
|
2026/06/07-00:01:17.685428 7f15ce3fc6c0 Delete type=0 #425
|
||||||
|
2026/06/07-00:21:46.748268 7f15cdbfb6c0 Level-0 table #430: started
|
||||||
|
2026/06/07-00:21:46.748282 7f15cdbfb6c0 Level-0 table #430: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.755214 7f15cdbfb6c0 Delete type=0 #428
|
||||||
|
2026/06/07-00:21:46.768389 7f15cdbfb6c0 Manual compaction at level-0 from '!journal!gVybbv17TFY8o3Y4' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
|||||||
MANIFEST-000402
|
MANIFEST-000426
|
||||||
|
|||||||
+3
-20
@@ -1,20 +1,3 @@
|
|||||||
2026/05/24-16:13:27.805283 7fdf5bfff6c0 Recovering log #401
|
2026/06/07-00:21:50.343006 7f15cebfd6c0 Recovering log #424
|
||||||
2026/05/24-16:13:27.815296 7fdf5bfff6c0 Delete type=0 #401
|
2026/06/07-00:21:50.352418 7f15cebfd6c0 Delete type=3 #422
|
||||||
2026/05/24-16:13:27.815331 7fdf5bfff6c0 Delete type=3 #400
|
2026/06/07-00:21:50.352440 7f15cebfd6c0 Delete type=0 #424
|
||||||
2026/05/24-16:49:30.661093 7fdf5affd6c0 Level-0 table #405: started
|
|
||||||
2026/05/24-16:49:30.661158 7fdf5affd6c0 Level-0 table #405: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.698495 7fdf5affd6c0 Manual compaction at level-0 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at '!items!wv5EiePmPTpqFutt' @ 287 : 1
|
|
||||||
2026/05/24-16:49:30.698499 7fdf5affd6c0 Compacting 1@0 + 0@1 files
|
|
||||||
2026/05/24-16:49:30.701559 7fdf5affd6c0 Generated table #406@0: 48 keys, 14533 bytes
|
|
||||||
2026/05/24-16:49:30.701564 7fdf5affd6c0 Compacted 1@0 + 0@1 files => 14533 bytes
|
|
||||||
2026/05/24-16:49:30.707420 7fdf5affd6c0 compacted to: files[ 0 1 1 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.707454 7fdf5affd6c0 Delete type=2 #392
|
|
||||||
2026/05/24-16:49:30.707535 7fdf5affd6c0 Manual compaction at level-0 from '!items!wv5EiePmPTpqFutt' @ 287 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end)
|
|
||||||
2026/05/24-16:49:30.707559 7fdf5affd6c0 Manual compaction at level-1 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at '!items!wv5EiePmPTpqFutt' @ 287 : 1
|
|
||||||
2026/05/24-16:49:30.707561 7fdf5affd6c0 Compacting 1@1 + 1@2 files
|
|
||||||
2026/05/24-16:49:30.710996 7fdf5affd6c0 Generated table #407@1: 48 keys, 14533 bytes
|
|
||||||
2026/05/24-16:49:30.711014 7fdf5affd6c0 Compacted 1@1 + 1@2 files => 14533 bytes
|
|
||||||
2026/05/24-16:49:30.717230 7fdf5affd6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.717309 7fdf5affd6c0 Delete type=2 #235
|
|
||||||
2026/05/24-16:49:30.717368 7fdf5affd6c0 Delete type=2 #406
|
|
||||||
2026/05/24-16:49:30.739563 7fdf5affd6c0 Manual compaction at level-1 from '!items!wv5EiePmPTpqFutt' @ 287 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
+7
-3
@@ -1,3 +1,7 @@
|
|||||||
2026/05/24-16:10:54.653592 7f2f52bfe6c0 Recovering log #399
|
2026/06/07-00:01:17.549317 7f15ce3fc6c0 Recovering log #420
|
||||||
2026/05/24-16:10:54.665351 7f2f52bfe6c0 Delete type=0 #399
|
2026/06/07-00:01:17.559821 7f15ce3fc6c0 Delete type=3 #418
|
||||||
2026/05/24-16:10:54.665381 7f2f52bfe6c0 Delete type=3 #398
|
2026/06/07-00:01:17.559847 7f15ce3fc6c0 Delete type=0 #420
|
||||||
|
2026/06/07-00:21:46.679739 7f15cdbfb6c0 Level-0 table #425: started
|
||||||
|
2026/06/07-00:21:46.679750 7f15cdbfb6c0 Level-0 table #425: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.685835 7f15cdbfb6c0 Delete type=0 #423
|
||||||
|
2026/06/07-00:21:46.698903 7f15cdbfb6c0 Manual compaction at level-0 from '!items!0swiE8k5zfUIqmXu' @ 72057594037927935 : 1 .. '!items!wv5EiePmPTpqFutt' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
|||||||
MANIFEST-000302
|
MANIFEST-000325
|
||||||
|
|||||||
+3
-13
@@ -1,13 +1,3 @@
|
|||||||
2026/05/24-16:13:27.843303 7fdfa8dfe6c0 Recovering log #301
|
2026/06/07-00:21:50.374568 7f15cf3fe6c0 Recovering log #323
|
||||||
2026/05/24-16:13:27.854272 7fdfa8dfe6c0 Delete type=0 #301
|
2026/06/07-00:21:50.384637 7f15cf3fe6c0 Delete type=3 #321
|
||||||
2026/05/24-16:13:27.854314 7fdfa8dfe6c0 Delete type=3 #299
|
2026/06/07-00:21:50.384658 7f15cf3fe6c0 Delete type=0 #323
|
||||||
2026/05/24-16:49:30.749361 7fdf5affd6c0 Level-0 table #305: started
|
|
||||||
2026/05/24-16:49:30.749380 7fdf5affd6c0 Level-0 table #305: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.773159 7fdf5affd6c0 Manual compaction at level-0 from '!items!5dGXNiL3WN4cAk7X' @ 72057594037927935 : 1 .. '!items!zzz9JrtWjELdoAfK' @ 0 : 0; will stop at '!items!zzz9JrtWjELdoAfK' @ 150 : 1
|
|
||||||
2026/05/24-16:49:30.773164 7fdf5affd6c0 Compacting 1@0 + 1@1 files
|
|
||||||
2026/05/24-16:49:30.776884 7fdf5affd6c0 Generated table #306@0: 30 keys, 15949 bytes
|
|
||||||
2026/05/24-16:49:30.776900 7fdf5affd6c0 Compacted 1@0 + 1@1 files => 15949 bytes
|
|
||||||
2026/05/24-16:49:30.782834 7fdf5affd6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.782894 7fdf5affd6c0 Delete type=2 #288
|
|
||||||
2026/05/24-16:49:30.782981 7fdf5affd6c0 Delete type=2 #300
|
|
||||||
2026/05/24-16:49:30.800757 7fdf5affd6c0 Manual compaction at level-0 from '!items!zzz9JrtWjELdoAfK' @ 150 : 1 .. '!items!zzz9JrtWjELdoAfK' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
+7
-5
@@ -1,5 +1,7 @@
|
|||||||
2026/05/24-16:10:54.877151 7f57f93ff6c0 Recovering log #298
|
2026/06/07-00:01:17.584289 7f15ce3fc6c0 Recovering log #319
|
||||||
2026/05/24-16:10:54.877440 7f57f93ff6c0 Level-0 table #300: started
|
2026/06/07-00:01:17.594286 7f15ce3fc6c0 Delete type=3 #317
|
||||||
2026/05/24-16:10:54.881592 7f57f93ff6c0 Level-0 table #300: 15949 bytes OK
|
2026/06/07-00:01:17.594301 7f15ce3fc6c0 Delete type=0 #319
|
||||||
2026/05/24-16:10:54.891689 7f57f93ff6c0 Delete type=0 #298
|
2026/06/07-00:21:46.698908 7f15cdbfb6c0 Level-0 table #324: started
|
||||||
2026/05/24-16:10:54.891758 7f57f93ff6c0 Delete type=3 #297
|
2026/06/07-00:21:46.698917 7f15cdbfb6c0 Level-0 table #324: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.704788 7f15cdbfb6c0 Delete type=0 #322
|
||||||
|
2026/06/07-00:21:46.710794 7f15cdbfb6c0 Manual compaction at level-0 from '!items!5dGXNiL3WN4cAk7X' @ 72057594037927935 : 1 .. '!items!zzz9JrtWjELdoAfK' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000302
|
MANIFEST-000325
|
||||||
|
|||||||
+3
-13
@@ -1,13 +1,3 @@
|
|||||||
2026/05/24-16:13:27.829466 7fdf5b7fe6c0 Recovering log #301
|
2026/06/07-00:21:50.363711 7f15ce3fc6c0 Recovering log #323
|
||||||
2026/05/24-16:13:27.840345 7fdf5b7fe6c0 Delete type=0 #301
|
2026/06/07-00:21:50.373124 7f15ce3fc6c0 Delete type=3 #321
|
||||||
2026/05/24-16:13:27.840390 7fdf5b7fe6c0 Delete type=3 #299
|
2026/06/07-00:21:50.373150 7f15ce3fc6c0 Delete type=0 #323
|
||||||
2026/05/24-16:49:30.733360 7fdf5affd6c0 Level-0 table #305: started
|
|
||||||
2026/05/24-16:49:30.733392 7fdf5affd6c0 Level-0 table #305: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.756430 7fdf5affd6c0 Manual compaction at level-0 from '!items!1cZd2hlTV9tykDED' @ 72057594037927935 : 1 .. '!items!y47dBO3Mf5Pn7tOd' @ 0 : 0; will stop at '!items!y47dBO3Mf5Pn7tOd' @ 275 : 1
|
|
||||||
2026/05/24-16:49:30.756454 7fdf5affd6c0 Compacting 1@0 + 1@1 files
|
|
||||||
2026/05/24-16:49:30.759808 7fdf5affd6c0 Generated table #306@0: 55 keys, 9796 bytes
|
|
||||||
2026/05/24-16:49:30.759829 7fdf5affd6c0 Compacted 1@0 + 1@1 files => 9796 bytes
|
|
||||||
2026/05/24-16:49:30.766114 7fdf5affd6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.766193 7fdf5affd6c0 Delete type=2 #288
|
|
||||||
2026/05/24-16:49:30.766365 7fdf5affd6c0 Delete type=2 #300
|
|
||||||
2026/05/24-16:49:30.783021 7fdf5affd6c0 Manual compaction at level-0 from '!items!y47dBO3Mf5Pn7tOd' @ 275 : 1 .. '!items!y47dBO3Mf5Pn7tOd' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
2026/05/24-16:10:54.804401 7fc086bff6c0 Recovering log #298
|
2026/06/07-00:01:17.573032 7f15cfbff6c0 Recovering log #319
|
||||||
2026/05/24-16:10:54.804603 7fc086bff6c0 Level-0 table #300: started
|
2026/06/07-00:01:17.582308 7f15cfbff6c0 Delete type=3 #317
|
||||||
2026/05/24-16:10:54.809175 7fc086bff6c0 Level-0 table #300: 9796 bytes OK
|
2026/06/07-00:01:17.582329 7f15cfbff6c0 Delete type=0 #319
|
||||||
2026/05/24-16:10:54.820050 7fc086bff6c0 Delete type=0 #298
|
2026/06/07-00:21:46.660469 7f15cdbfb6c0 Level-0 table #324: started
|
||||||
2026/05/24-16:10:54.820128 7fc086bff6c0 Delete type=3 #297
|
2026/06/07-00:21:46.660487 7f15cdbfb6c0 Level-0 table #324: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.667102 7f15cdbfb6c0 Delete type=0 #322
|
||||||
|
2026/06/07-00:21:46.679674 7f15cdbfb6c0 Manual compaction at level-0 from '!items!1cZd2hlTV9tykDED' @ 72057594037927935 : 1 .. '!items!y47dBO3Mf5Pn7tOd' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000418
|
MANIFEST-000442
|
||||||
|
|||||||
+3
-20
@@ -1,20 +1,3 @@
|
|||||||
2026/05/24-16:13:27.793795 7fdf5b7fe6c0 Recovering log #417
|
2026/06/07-00:21:50.331328 7f15cf3fe6c0 Recovering log #440
|
||||||
2026/05/24-16:13:27.803165 7fdf5b7fe6c0 Delete type=0 #417
|
2026/06/07-00:21:50.341554 7f15cf3fe6c0 Delete type=3 #438
|
||||||
2026/05/24-16:13:27.803205 7fdf5b7fe6c0 Delete type=3 #416
|
2026/06/07-00:21:50.341580 7f15cf3fe6c0 Delete type=0 #440
|
||||||
2026/05/24-16:49:30.654051 7fdf5affd6c0 Level-0 table #421: started
|
|
||||||
2026/05/24-16:49:30.654105 7fdf5affd6c0 Level-0 table #421: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.688223 7fdf5affd6c0 Manual compaction at level-0 from '!items!15foLG7y3LUXNzkK' @ 72057594037927935 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at '!items!z1HtkvazCGHut7cz' @ 336 : 1
|
|
||||||
2026/05/24-16:49:30.688226 7fdf5affd6c0 Compacting 1@0 + 0@1 files
|
|
||||||
2026/05/24-16:49:30.692355 7fdf5affd6c0 Generated table #422@0: 48 keys, 20398 bytes
|
|
||||||
2026/05/24-16:49:30.692374 7fdf5affd6c0 Compacted 1@0 + 0@1 files => 20398 bytes
|
|
||||||
2026/05/24-16:49:30.698404 7fdf5affd6c0 compacted to: files[ 0 1 1 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.698435 7fdf5affd6c0 Delete type=2 #410
|
|
||||||
2026/05/24-16:49:30.707532 7fdf5affd6c0 Manual compaction at level-0 from '!items!z1HtkvazCGHut7cz' @ 336 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at (end)
|
|
||||||
2026/05/24-16:49:30.717401 7fdf5affd6c0 Manual compaction at level-1 from '!items!15foLG7y3LUXNzkK' @ 72057594037927935 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at '!items!z1HtkvazCGHut7cz' @ 336 : 1
|
|
||||||
2026/05/24-16:49:30.717404 7fdf5affd6c0 Compacting 1@1 + 1@2 files
|
|
||||||
2026/05/24-16:49:30.720557 7fdf5affd6c0 Generated table #423@1: 48 keys, 20398 bytes
|
|
||||||
2026/05/24-16:49:30.720563 7fdf5affd6c0 Compacted 1@1 + 1@2 files => 20398 bytes
|
|
||||||
2026/05/24-16:49:30.726463 7fdf5affd6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.726537 7fdf5affd6c0 Delete type=2 #352
|
|
||||||
2026/05/24-16:49:30.726638 7fdf5affd6c0 Delete type=2 #422
|
|
||||||
2026/05/24-16:49:30.739587 7fdf5affd6c0 Manual compaction at level-1 from '!items!z1HtkvazCGHut7cz' @ 336 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
2026/05/24-16:10:55.365745 7f834bfff6c0 Recovering log #415
|
2026/06/07-00:01:17.537677 7f15cfbff6c0 Recovering log #436
|
||||||
2026/05/24-16:10:55.376057 7f834bfff6c0 Delete type=0 #415
|
2026/06/07-00:01:17.547496 7f15cfbff6c0 Delete type=3 #434
|
||||||
2026/05/24-16:10:55.376117 7f834bfff6c0 Delete type=3 #414
|
2026/06/07-00:01:17.547526 7f15cfbff6c0 Delete type=0 #436
|
||||||
|
2026/06/07-00:21:46.685907 7f15cdbfb6c0 Level-0 table #441: started
|
||||||
|
2026/06/07-00:21:46.685917 7f15cdbfb6c0 Level-0 table #441: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.691937 7f15cdbfb6c0 Delete type=0 #439
|
||||||
|
2026/06/07-00:21:46.704830 7f15cdbfb6c0 Manual compaction at level-0 from '!items!15foLG7y3LUXNzkK' @ 72057594037927935 : 1 .. '!items!z1HtkvazCGHut7cz' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000418
|
MANIFEST-000442
|
||||||
|
|||||||
+3
-20
@@ -1,20 +1,3 @@
|
|||||||
2026/05/24-16:13:27.895777 7fdfa95ff6c0 Recovering log #417
|
2026/06/07-00:21:50.420841 7f15cfbff6c0 Recovering log #440
|
||||||
2026/05/24-16:13:27.904649 7fdfa95ff6c0 Delete type=0 #417
|
2026/06/07-00:21:50.430740 7f15cfbff6c0 Delete type=3 #438
|
||||||
2026/05/24-16:13:27.904673 7fdfa95ff6c0 Delete type=3 #416
|
2026/06/07-00:21:50.430770 7f15cfbff6c0 Delete type=0 #440
|
||||||
2026/05/24-16:49:30.833777 7fdf5affd6c0 Level-0 table #421: started
|
|
||||||
2026/05/24-16:49:30.833795 7fdf5affd6c0 Level-0 table #421: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.850864 7fdf5affd6c0 Manual compaction at level-0 from '!items!26mRstKhCJoXkhu1' @ 72057594037927935 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at '!items!tFQqcxmkS3MT6ASE' @ 105 : 1
|
|
||||||
2026/05/24-16:49:30.850868 7fdf5affd6c0 Compacting 1@0 + 0@1 files
|
|
||||||
2026/05/24-16:49:30.854607 7fdf5affd6c0 Generated table #422@0: 15 keys, 30233 bytes
|
|
||||||
2026/05/24-16:49:30.854633 7fdf5affd6c0 Compacted 1@0 + 0@1 files => 30233 bytes
|
|
||||||
2026/05/24-16:49:30.862029 7fdf5affd6c0 compacted to: files[ 0 1 1 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.862120 7fdf5affd6c0 Delete type=2 #410
|
|
||||||
2026/05/24-16:49:30.878767 7fdf5affd6c0 Manual compaction at level-0 from '!items!tFQqcxmkS3MT6ASE' @ 105 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at (end)
|
|
||||||
2026/05/24-16:49:30.890474 7fdf5affd6c0 Manual compaction at level-1 from '!items!26mRstKhCJoXkhu1' @ 72057594037927935 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at '!items!tFQqcxmkS3MT6ASE' @ 105 : 1
|
|
||||||
2026/05/24-16:49:30.890480 7fdf5affd6c0 Compacting 1@1 + 1@2 files
|
|
||||||
2026/05/24-16:49:30.895249 7fdf5affd6c0 Generated table #423@1: 15 keys, 30233 bytes
|
|
||||||
2026/05/24-16:49:30.895261 7fdf5affd6c0 Compacted 1@1 + 1@2 files => 30233 bytes
|
|
||||||
2026/05/24-16:49:30.908330 7fdf5affd6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.908435 7fdf5affd6c0 Delete type=2 #352
|
|
||||||
2026/05/24-16:49:30.908535 7fdf5affd6c0 Delete type=2 #422
|
|
||||||
2026/05/24-16:49:30.915370 7fdf5affd6c0 Manual compaction at level-1 from '!items!tFQqcxmkS3MT6ASE' @ 105 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
2026/05/24-16:10:55.440137 7fc32b7ef6c0 Recovering log #415
|
2026/06/07-00:01:17.628038 7f15cf3fe6c0 Recovering log #436
|
||||||
2026/05/24-16:10:55.459685 7fc32b7ef6c0 Delete type=0 #415
|
2026/06/07-00:01:17.637109 7f15cf3fe6c0 Delete type=3 #434
|
||||||
2026/05/24-16:10:55.459751 7fc32b7ef6c0 Delete type=3 #414
|
2026/06/07-00:01:17.637121 7f15cf3fe6c0 Delete type=0 #436
|
||||||
|
2026/06/07-00:21:46.761269 7f15cdbfb6c0 Level-0 table #441: started
|
||||||
|
2026/06/07-00:21:46.761294 7f15cdbfb6c0 Level-0 table #441: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.768307 7f15cdbfb6c0 Delete type=0 #439
|
||||||
|
2026/06/07-00:21:46.777465 7f15cdbfb6c0 Manual compaction at level-0 from '!items!26mRstKhCJoXkhu1' @ 72057594037927935 : 1 .. '!items!tFQqcxmkS3MT6ASE' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000302
|
MANIFEST-000325
|
||||||
|
|||||||
+3
-13
@@ -1,13 +1,3 @@
|
|||||||
2026/05/24-16:13:27.817130 7fdfa8dfe6c0 Recovering log #301
|
2026/06/07-00:21:50.353793 7f15cfbff6c0 Recovering log #323
|
||||||
2026/05/24-16:13:27.827508 7fdfa8dfe6c0 Delete type=0 #301
|
2026/06/07-00:21:50.362811 7f15cfbff6c0 Delete type=3 #321
|
||||||
2026/05/24-16:13:27.827563 7fdfa8dfe6c0 Delete type=3 #299
|
2026/06/07-00:21:50.362829 7f15cfbff6c0 Delete type=0 #323
|
||||||
2026/05/24-16:49:30.726685 7fdf5affd6c0 Level-0 table #305: started
|
|
||||||
2026/05/24-16:49:30.726704 7fdf5affd6c0 Level-0 table #305: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.739601 7fdf5affd6c0 Manual compaction at level-0 from '!items!2hD1DQVeCIQIXFU7' @ 72057594037927935 : 1 .. '!items!veoS6Gtzj6Dq087V' @ 0 : 0; will stop at '!items!veoS6Gtzj6Dq087V' @ 35 : 1
|
|
||||||
2026/05/24-16:49:30.739606 7fdf5affd6c0 Compacting 1@0 + 1@1 files
|
|
||||||
2026/05/24-16:49:30.742829 7fdf5affd6c0 Generated table #306@0: 7 keys, 2881 bytes
|
|
||||||
2026/05/24-16:49:30.742848 7fdf5affd6c0 Compacted 1@0 + 1@1 files => 2881 bytes
|
|
||||||
2026/05/24-16:49:30.749097 7fdf5affd6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.749193 7fdf5affd6c0 Delete type=2 #288
|
|
||||||
2026/05/24-16:49:30.749309 7fdf5affd6c0 Delete type=2 #300
|
|
||||||
2026/05/24-16:49:30.773136 7fdf5affd6c0 Manual compaction at level-0 from '!items!veoS6Gtzj6Dq087V' @ 35 : 1 .. '!items!veoS6Gtzj6Dq087V' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
2026/05/24-16:10:54.729976 7f0993fff6c0 Recovering log #298
|
2026/06/07-00:01:17.561757 7f15cf3fe6c0 Recovering log #319
|
||||||
2026/05/24-16:10:54.730135 7f0993fff6c0 Level-0 table #300: started
|
2026/06/07-00:01:17.571010 7f15cf3fe6c0 Delete type=3 #317
|
||||||
2026/05/24-16:10:54.734161 7f0993fff6c0 Level-0 table #300: 2881 bytes OK
|
2026/06/07-00:01:17.571033 7f15cf3fe6c0 Delete type=0 #319
|
||||||
2026/05/24-16:10:54.744747 7f0993fff6c0 Delete type=0 #298
|
2026/06/07-00:21:46.667152 7f15cdbfb6c0 Level-0 table #324: started
|
||||||
2026/05/24-16:10:54.744817 7f0993fff6c0 Delete type=3 #297
|
2026/06/07-00:21:46.667166 7f15cdbfb6c0 Level-0 table #324: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.673526 7f15cdbfb6c0 Delete type=0 #322
|
||||||
|
2026/06/07-00:21:46.679679 7f15cdbfb6c0 Manual compaction at level-0 from '!items!2hD1DQVeCIQIXFU7' @ 72057594037927935 : 1 .. '!items!veoS6Gtzj6Dq087V' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
|||||||
MANIFEST-000302
|
MANIFEST-000325
|
||||||
|
|||||||
+3
-13
@@ -1,13 +1,3 @@
|
|||||||
2026/05/24-16:13:27.881867 7fdf5bfff6c0 Recovering log #301
|
2026/06/07-00:21:50.409088 7f15ce3fc6c0 Recovering log #323
|
||||||
2026/05/24-16:13:27.892914 7fdf5bfff6c0 Delete type=0 #301
|
2026/06/07-00:21:50.419461 7f15ce3fc6c0 Delete type=3 #321
|
||||||
2026/05/24-16:13:27.892950 7fdf5bfff6c0 Delete type=3 #299
|
2026/06/07-00:21:50.419490 7f15ce3fc6c0 Delete type=0 #323
|
||||||
2026/05/24-16:49:30.800774 7fdf5affd6c0 Level-0 table #305: started
|
|
||||||
2026/05/24-16:49:30.800796 7fdf5affd6c0 Level-0 table #305: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.823354 7fdf5affd6c0 Manual compaction at level-0 from '!items!1JqWbEkHUoKXbsgn' @ 72057594037927935 : 1 .. '!items!xnCf2xIPzdsUoBTy' @ 0 : 0; will stop at '!items!xnCf2xIPzdsUoBTy' @ 225 : 1
|
|
||||||
2026/05/24-16:49:30.823360 7fdf5affd6c0 Compacting 1@0 + 1@1 files
|
|
||||||
2026/05/24-16:49:30.827700 7fdf5affd6c0 Generated table #306@0: 45 keys, 33963 bytes
|
|
||||||
2026/05/24-16:49:30.827710 7fdf5affd6c0 Compacted 1@0 + 1@1 files => 33963 bytes
|
|
||||||
2026/05/24-16:49:30.833611 7fdf5affd6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.833659 7fdf5affd6c0 Delete type=2 #288
|
|
||||||
2026/05/24-16:49:30.833739 7fdf5affd6c0 Delete type=2 #300
|
|
||||||
2026/05/24-16:49:30.850855 7fdf5affd6c0 Manual compaction at level-0 from '!items!xnCf2xIPzdsUoBTy' @ 225 : 1 .. '!items!xnCf2xIPzdsUoBTy' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
+7
-5
@@ -1,5 +1,7 @@
|
|||||||
2026/05/24-16:10:54.953569 7f78713ff6c0 Recovering log #298
|
2026/06/07-00:01:17.617058 7f15ce3fc6c0 Recovering log #319
|
||||||
2026/05/24-16:10:54.953939 7f78713ff6c0 Level-0 table #300: started
|
2026/06/07-00:01:17.626625 7f15ce3fc6c0 Delete type=3 #317
|
||||||
2026/05/24-16:10:54.958319 7f78713ff6c0 Level-0 table #300: 33963 bytes OK
|
2026/06/07-00:01:17.626639 7f15ce3fc6c0 Delete type=0 #319
|
||||||
2026/05/24-16:10:54.968428 7f78713ff6c0 Delete type=0 #298
|
2026/06/07-00:21:46.716945 7f15cdbfb6c0 Level-0 table #324: started
|
||||||
2026/05/24-16:10:54.968509 7f78713ff6c0 Delete type=3 #297
|
2026/06/07-00:21:46.716955 7f15cdbfb6c0 Level-0 table #324: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.723471 7f15cdbfb6c0 Delete type=0 #322
|
||||||
|
2026/06/07-00:21:46.729892 7f15cdbfb6c0 Manual compaction at level-0 from '!items!1JqWbEkHUoKXbsgn' @ 72057594037927935 : 1 .. '!items!xnCf2xIPzdsUoBTy' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000250
|
MANIFEST-000273
|
||||||
|
|||||||
+3
-14
@@ -1,14 +1,3 @@
|
|||||||
2026/05/24-16:13:27.934950 7fdf5b7fe6c0 Recovering log #249
|
2026/06/07-00:21:50.454761 7f15ce3fc6c0 Recovering log #271
|
||||||
2026/05/24-16:13:27.944727 7fdf5b7fe6c0 Delete type=0 #249
|
2026/06/07-00:21:50.464634 7f15ce3fc6c0 Delete type=3 #269
|
||||||
2026/05/24-16:13:27.944766 7fdf5b7fe6c0 Delete type=3 #248
|
2026/06/07-00:21:50.464657 7f15ce3fc6c0 Delete type=0 #271
|
||||||
2026/05/24-16:49:30.868686 7fdf5affd6c0 Level-0 table #253: started
|
|
||||||
2026/05/24-16:49:30.871770 7fdf5affd6c0 Level-0 table #253: 1897 bytes OK
|
|
||||||
2026/05/24-16:49:30.908620 7fdf5affd6c0 Manual compaction at level-0 from '!scenes!dYKdGdh2PbtXs32a' @ 72057594037927935 : 1 .. '!scenes.levels!dYKdGdh2PbtXs32a.defaultLevel0000' @ 0 : 0; will stop at (end)
|
|
||||||
2026/05/24-16:49:30.915400 7fdf5affd6c0 Manual compaction at level-1 from '!scenes!dYKdGdh2PbtXs32a' @ 72057594037927935 : 1 .. '!scenes.levels!dYKdGdh2PbtXs32a.defaultLevel0000' @ 0 : 0; will stop at '!scenes.levels!mfosNsLsHN5Pf4TO.defaultLevel0000' @ 104 : 0
|
|
||||||
2026/05/24-16:49:30.915405 7fdf5affd6c0 Compacting 1@1 + 1@2 files
|
|
||||||
2026/05/24-16:49:30.918981 7fdf5affd6c0 Generated table #254@1: 2 keys, 1628 bytes
|
|
||||||
2026/05/24-16:49:30.918988 7fdf5affd6c0 Compacted 1@1 + 1@2 files => 1628 bytes
|
|
||||||
2026/05/24-16:49:30.925116 7fdf5affd6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.925157 7fdf5affd6c0 Delete type=2 #223
|
|
||||||
2026/05/24-16:49:30.925248 7fdf5affd6c0 Delete type=2 #253
|
|
||||||
2026/05/24-16:49:30.941527 7fdf5affd6c0 Manual compaction at level-1 from '!scenes.levels!mfosNsLsHN5Pf4TO.defaultLevel0000' @ 104 : 0 .. '!scenes.levels!dYKdGdh2PbtXs32a.defaultLevel0000' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
2026/05/24-16:10:55.855003 7fcff97ec6c0 Recovering log #247
|
2026/06/07-00:01:17.661008 7f15cf3fe6c0 Recovering log #267
|
||||||
2026/05/24-16:10:55.867026 7fcff97ec6c0 Delete type=0 #247
|
2026/06/07-00:01:17.670919 7f15cf3fe6c0 Delete type=3 #265
|
||||||
2026/05/24-16:10:55.867082 7fcff97ec6c0 Delete type=3 #246
|
2026/06/07-00:01:17.670935 7f15cf3fe6c0 Delete type=0 #267
|
||||||
|
2026/06/07-00:21:46.723582 7f15cdbfb6c0 Level-0 table #272: started
|
||||||
|
2026/06/07-00:21:46.723594 7f15cdbfb6c0 Level-0 table #272: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.729834 7f15cdbfb6c0 Delete type=0 #270
|
||||||
|
2026/06/07-00:21:46.742119 7f15cdbfb6c0 Manual compaction at level-0 from '!scenes!dYKdGdh2PbtXs32a' @ 72057594037927935 : 1 .. '!scenes.levels!dYKdGdh2PbtXs32a.defaultLevel0000' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000208
|
MANIFEST-000231
|
||||||
|
|||||||
@@ -1,13 +1,3 @@
|
|||||||
2026/05/24-16:13:27.781963 7fdf5b7fe6c0 Recovering log #207
|
2026/06/07-00:21:50.321397 7f15ce3fc6c0 Recovering log #229
|
||||||
2026/05/24-16:13:27.792095 7fdf5b7fe6c0 Delete type=0 #207
|
2026/06/07-00:21:50.330366 7f15ce3fc6c0 Delete type=3 #227
|
||||||
2026/05/24-16:13:27.792113 7fdf5b7fe6c0 Delete type=3 #205
|
2026/06/07-00:21:50.330389 7f15ce3fc6c0 Delete type=0 #229
|
||||||
2026/05/24-16:49:30.640321 7fdf5affd6c0 Level-0 table #211: started
|
|
||||||
2026/05/24-16:49:30.640388 7fdf5affd6c0 Level-0 table #211: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.668355 7fdf5affd6c0 Manual compaction at level-0 from '!items!6bmjc4MUduGs9s6n' @ 72057594037927935 : 1 .. '!items!t692JcsGHG4YJIlM' @ 0 : 0; will stop at '!items!t692JcsGHG4YJIlM' @ 49 : 1
|
|
||||||
2026/05/24-16:49:30.668380 7fdf5affd6c0 Compacting 1@0 + 1@1 files
|
|
||||||
2026/05/24-16:49:30.671868 7fdf5affd6c0 Generated table #212@0: 8 keys, 3873 bytes
|
|
||||||
2026/05/24-16:49:30.671886 7fdf5affd6c0 Compacted 1@0 + 1@1 files => 3873 bytes
|
|
||||||
2026/05/24-16:49:30.678060 7fdf5affd6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.678393 7fdf5affd6c0 Delete type=2 #194
|
|
||||||
2026/05/24-16:49:30.678468 7fdf5affd6c0 Delete type=2 #206
|
|
||||||
2026/05/24-16:49:30.707523 7fdf5affd6c0 Manual compaction at level-0 from '!items!t692JcsGHG4YJIlM' @ 49 : 1 .. '!items!t692JcsGHG4YJIlM' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
2026/05/24-16:10:55.284487 7f38c97ee6c0 Recovering log #204
|
2026/06/07-00:01:17.527640 7f15cf3fe6c0 Recovering log #225
|
||||||
2026/05/24-16:10:55.284651 7f38c97ee6c0 Level-0 table #206: started
|
2026/06/07-00:01:17.536413 7f15cf3fe6c0 Delete type=3 #223
|
||||||
2026/05/24-16:10:55.296249 7f38c97ee6c0 Level-0 table #206: 3873 bytes OK
|
2026/06/07-00:01:17.536429 7f15cf3fe6c0 Delete type=0 #225
|
||||||
2026/05/24-16:10:55.307332 7f38c97ee6c0 Delete type=0 #204
|
2026/06/07-00:21:46.673575 7f15cdbfb6c0 Level-0 table #230: started
|
||||||
2026/05/24-16:10:55.307395 7f38c97ee6c0 Delete type=3 #203
|
2026/06/07-00:21:46.673592 7f15cdbfb6c0 Level-0 table #230: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.679599 7f15cdbfb6c0 Delete type=0 #228
|
||||||
|
2026/06/07-00:21:46.685902 7f15cdbfb6c0 Manual compaction at level-0 from '!items!6bmjc4MUduGs9s6n' @ 72057594037927935 : 1 .. '!items!t692JcsGHG4YJIlM' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000300
|
MANIFEST-000323
|
||||||
|
|||||||
+3
-13
@@ -1,13 +1,3 @@
|
|||||||
2026/05/24-16:13:27.770260 7fdfa95ff6c0 Recovering log #299
|
2026/06/07-00:21:50.310068 7f15cfbff6c0 Recovering log #321
|
||||||
2026/05/24-16:13:27.780183 7fdfa95ff6c0 Delete type=0 #299
|
2026/06/07-00:21:50.320158 7f15cfbff6c0 Delete type=3 #319
|
||||||
2026/05/24-16:13:27.780244 7fdfa95ff6c0 Delete type=3 #297
|
2026/06/07-00:21:50.320186 7f15cfbff6c0 Delete type=0 #321
|
||||||
2026/05/24-16:49:30.647265 7fdf5affd6c0 Level-0 table #303: started
|
|
||||||
2026/05/24-16:49:30.647318 7fdf5affd6c0 Level-0 table #303: 0 bytes OK
|
|
||||||
2026/05/24-16:49:30.678500 7fdf5affd6c0 Manual compaction at level-0 from '!items!0LlzDyCurJedqeyG' @ 72057594037927935 : 1 .. '!items!tq6mEgXog7h4VyWk' @ 0 : 0; will stop at '!items!tq6mEgXog7h4VyWk' @ 75 : 1
|
|
||||||
2026/05/24-16:49:30.678503 7fdf5affd6c0 Compacting 1@0 + 1@1 files
|
|
||||||
2026/05/24-16:49:30.681724 7fdf5affd6c0 Generated table #304@0: 15 keys, 8091 bytes
|
|
||||||
2026/05/24-16:49:30.681731 7fdf5affd6c0 Compacted 1@0 + 1@1 files => 8091 bytes
|
|
||||||
2026/05/24-16:49:30.688059 7fdf5affd6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
|
||||||
2026/05/24-16:49:30.688095 7fdf5affd6c0 Delete type=2 #286
|
|
||||||
2026/05/24-16:49:30.688197 7fdf5affd6c0 Delete type=2 #298
|
|
||||||
2026/05/24-16:49:30.707528 7fdf5affd6c0 Manual compaction at level-0 from '!items!tq6mEgXog7h4VyWk' @ 75 : 1 .. '!items!tq6mEgXog7h4VyWk' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
2026/05/24-16:10:55.204766 7fed9e3ff6c0 Recovering log #296
|
2026/06/07-00:01:17.516491 7f15cf3fe6c0 Recovering log #317
|
||||||
2026/05/24-16:10:55.204926 7fed9e3ff6c0 Level-0 table #298: started
|
2026/06/07-00:01:17.526454 7f15cf3fe6c0 Delete type=3 #315
|
||||||
2026/05/24-16:10:55.209216 7fed9e3ff6c0 Level-0 table #298: 8091 bytes OK
|
2026/06/07-00:01:17.526475 7f15cf3fe6c0 Delete type=0 #317
|
||||||
2026/05/24-16:10:55.219909 7fed9e3ff6c0 Delete type=0 #296
|
2026/06/07-00:21:46.653448 7f15cdbfb6c0 Level-0 table #322: started
|
||||||
2026/05/24-16:10:55.219959 7fed9e3ff6c0 Delete type=3 #295
|
2026/06/07-00:21:46.653485 7f15cdbfb6c0 Level-0 table #322: 0 bytes OK
|
||||||
|
2026/06/07-00:21:46.660396 7f15cdbfb6c0 Delete type=0 #320
|
||||||
|
2026/06/07-00:21:46.679667 7f15cdbfb6c0 Manual compaction at level-0 from '!items!0LlzDyCurJedqeyG' @ 72057594037927935 : 1 .. '!items!tq6mEgXog7h4VyWk' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user