Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd3c228b32 | ||
|
|
9b3eceb96b | ||
|
|
73b91285e3 | ||
|
|
1238460cc8 | ||
|
|
d590dfce7f | ||
|
|
332da735f8 | ||
|
|
4a6913a2ba | ||
|
|
3a55d8e912 | ||
|
|
7caeb0c918 | ||
|
|
188e7676fa | ||
|
|
bb56a3a809 | ||
|
|
ac2e2027a0 | ||
|
|
dca201c5e2 | ||
|
|
5db30ddeb3 | ||
|
|
3758d0ca85 | ||
|
|
d8cfd02807 | ||
|
|
9aca2c32ef | ||
|
|
882aa5fbcb | ||
|
|
1272cfdfd1 | ||
|
|
2348b2262b | ||
|
|
81cb3bb6bd | ||
|
|
e0e3d4f230 | ||
|
|
3afd111711 | ||
|
|
1c288b654a | ||
|
|
a5843888c0 | ||
|
|
7d9ebd601a | ||
|
|
25e3df1f5d | ||
|
|
84ce2f78d7 | ||
|
|
8fddbe698c | ||
|
|
d0a434fb0b | ||
|
|
27b232776c | ||
|
|
d06f1de433 | ||
|
|
54fc1e8e1a | ||
|
|
70092ffd8f | ||
|
|
36b33890db | ||
|
|
ec2bf050d4 | ||
|
|
00edfe8201 | ||
|
|
6fdb07a4e8 | ||
|
|
c4f9150fdb | ||
|
|
8400d88677 | ||
|
|
93a1478cba | ||
|
|
51b05d025a | ||
|
|
348536556a | ||
|
|
afabba430a | ||
|
|
3e63054b9d | ||
|
|
07997576cd | ||
|
|
d216e8fcf6 | ||
|
|
29cdcca1bb | ||
|
|
8c9c8f3345 | ||
|
|
8e748a1d94 | ||
|
|
7599db07ad | ||
|
|
1db733f379 | ||
|
|
07a48fb3cc | ||
|
|
f52575f413 | ||
|
|
5969009eb1 |
@@ -0,0 +1,28 @@
|
|||||||
|
# Session Summary: v13 Migration — DataModel + _id/duplicate Cleanup + template.json removal
|
||||||
|
|
||||||
|
## Done
|
||||||
|
|
||||||
|
### `duplicate()` → `deepClone()` (finding #10, 36 files)
|
||||||
|
`foundry.utils.duplicate()` → `foundry.utils.deepClone()` across the system. `deepClone` preserves Document prototypes where `duplicate` stripped them.
|
||||||
|
|
||||||
|
### `_id` → `id` on Documents (finding #11, finding #7, ~25 sites)
|
||||||
|
- 21 read accesses migrated during initial sweep
|
||||||
|
- Review sweep caught 3 more: `rdd-combat.js:148` (combatant._id), `rdd-combat.js:898` (esquive e._id), `rdd-tmr-dialog.js:261` (casetmr._id)
|
||||||
|
- Also fixed: `actor.js:1844` (selectedSort._id), `actor.js:2884` (herbeData._id), `base-actor.js:404` (conteneur c._id)
|
||||||
|
- Remaining `_id` references are on POJOs (`toObject()`/migration data) — correct.
|
||||||
|
|
||||||
|
### `_onClose` → `super._onClose()` (finding #9)
|
||||||
|
All dialog `_onClose` overrides now call `super._onClose()` for proper HandlebarsApplicationMixin cleanup.
|
||||||
|
|
||||||
|
### Actor DataModel Migration (3 phases)
|
||||||
|
- Phase 1: 5 DataModels in `module/models/` + helpers + `CONFIG.Actor.dataModels` registration
|
||||||
|
- Phase 2: `prepareActorData()` chain → DataModel `prepareDerivedData()` in each model
|
||||||
|
- Phase 3: template.json deletion, dead code cleanup
|
||||||
|
|
||||||
|
### `template.json` elimination (like `fvtt-hawkmoon-cyd`)
|
||||||
|
- `template.json` deleted. Foundry v13+ uses `documentTypes` in system.json.
|
||||||
|
- Added `documentTypes.Actor` (5 types) + `documentTypes.Item` (44 types) with `htmlFields`
|
||||||
|
- Fixed CI/CD files referencing template.json
|
||||||
|
|
||||||
|
## Still remaining (v14-blocking)
|
||||||
|
V1 Application/Dialog classes (24 `extends Dialog`, 6+ V1 sheets) cannot run in v14 — findings #1–#6.
|
||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
run: node ./tools/packCompendiumsToDist.mjs
|
run: node ./tools/packCompendiumsToDist.mjs
|
||||||
|
|
||||||
- name: Create ZIP file
|
- name: Create ZIP file
|
||||||
run: zip -r ./rddsystem.zip system.json template.json README.md LICENSE.txt assets/ css/ fonts/ icons lang/ module/ packs/ pic/ sounds/ styles/ templates/
|
run: zip -r ./rddsystem.zip system.json README.md LICENSE.txt assets/ css/ fonts/ icons lang/ module/ packs/ pic/ sounds/ styles/ templates/
|
||||||
|
|
||||||
- name: setup go
|
- name: setup go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
|
|||||||
@@ -13,3 +13,6 @@ todo.md
|
|||||||
/packs/*/LOG
|
/packs/*/LOG
|
||||||
/packs/*/LOCK
|
/packs/*/LOCK
|
||||||
.github/
|
.github/
|
||||||
|
*.bak
|
||||||
|
/AGENTS.md
|
||||||
|
/regles/
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ test:
|
|||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- python -mjson.tool 'system.json' > /dev/null
|
- python -mjson.tool 'system.json' > /dev/null
|
||||||
- python -mjson.tool 'template.json' > /dev/null
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
|
|||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
# TODO v14 — Compatibilité Foundry VTT
|
||||||
|
|
||||||
|
## ✅ Bloquant — terminé
|
||||||
|
|
||||||
|
### 1. ✅ Sheets acteur V1 → V2
|
||||||
|
- V1 déplacés vers `_deprecated/module/actor/` (10 fichiers `.js`)
|
||||||
|
- V2 dans `module/applications/sheets/` (fichiers `.mjs`)
|
||||||
|
|
||||||
|
### 2. ✅ Sheet journal V1 → V2
|
||||||
|
- `module/journal/journal-sheet.mjs` → `extends JournalEntryPageProseMirrorSheet`
|
||||||
|
- `_prepareContentContext` override → `RdDTextEditor.enrichHTML()`
|
||||||
|
- `_onRender` → roll-text/chat-roll-text click listeners
|
||||||
|
|
||||||
|
### 3. ✅ 24 classes `extends Dialog` → V2
|
||||||
|
- Toutes converties en `extends foundry.applications.api.DialogV2`
|
||||||
|
- `module/tirage/fenetre-recherche-tirage.js` — `FenetreRechercheTirage` migré V1 App → V2 ApplicationV2
|
||||||
|
- `module/sommeil/dialog-nouveau-repos-cd.js` — `new Dialog(...)` direct → `DialogV2.wait()`
|
||||||
|
|
||||||
|
### 4. ✅ 3 classes `extends Application` → V2
|
||||||
|
- `module/tirage/fenetre-recherche-tirage.js` — FAIT (ApplicationV2)
|
||||||
|
- `module/time/rdd-calendrier.js` (RdDCalendrier) — FAIT (ApplicationV2)
|
||||||
|
- `module/sommeil/app-astrologie.js` (AppAstrologie) — FAIT (ApplicationV2)
|
||||||
|
|
||||||
|
### 5. ✅ 1 classe `extends FormApplication` → V2
|
||||||
|
- `module/actor/random/app-personnage-aleatoire.js` — FAIT (ApplicationV2)
|
||||||
|
|
||||||
|
### 6. ✅ 7 appels `new Dialog({...})` directs → DialogV2
|
||||||
|
Tous convertis. +3 autres dans `module/applications/sheets/base-actor-sheet.mjs` & `personnage-sheet.mjs`.
|
||||||
|
|
||||||
|
## 🟠 Haute priorité
|
||||||
|
|
||||||
|
### 7. ✅ `_id` dans `updateEmbeddedDocuments` → utiliser `.id` — **FAIT** (10 occ. changées, 2 déjà OK, 1 string param)
|
||||||
|
|
||||||
|
### 8. ✅ `bringToFront()` sur apps V1 → adapter
|
||||||
|
Rétrocompatibilité V2 gère. Pas d'erreur constatée (les apps converties utilisent V2).
|
||||||
|
|
||||||
|
### 9. ✅ `_onClose()` sans `super._onClose()` → **FAIT**
|
||||||
|
- `module/dialog-gerer-potions.js:45-49`
|
||||||
|
- `module/dialog-gerer-ingredients.js:45-49`
|
||||||
|
- `module/dialog-gerer-herbes.js:47-51`
|
||||||
|
|
||||||
|
## 🟡 Priorité moyenne
|
||||||
|
|
||||||
|
### 10. ✅ `foundry.utils.duplicate()` → `deepClone()` — **FAIT** (36 fichiers)
|
||||||
|
|
||||||
|
### 11. ✅ `._id` en lecture → `.id` — **FAIT** (21 occ. changées, 11 conservées sur objets de données)
|
||||||
|
~45 occurrences : `item._id`, `actor._id`, `combatant._id`, `token._id`…
|
||||||
|
|
||||||
|
### 12. `render(true)` sur apps V2 → `render({force: true})`
|
||||||
|
Rétrocompatibilité V2 normalise booléen → pas prioritaire.
|
||||||
|
~60 occurrences dans module/ — nos fichiers convertis l'utilisent déjà.
|
||||||
|
|
||||||
|
### 13. ✅ Incohérence registration sheets
|
||||||
|
`module/applications/sheets/common-item-sheet.mjs` — `Items.registerSheet()` → `foundry.documents.collections.Items.registerSheet()`
|
||||||
|
|
||||||
|
## 🟢 Basse priorité / Info
|
||||||
|
|
||||||
|
### 14. ✅ `canvas` sans vérification `ready`
|
||||||
|
27 occurrences dans 11 fichiers sécurisées avec `?.`
|
||||||
|
|
||||||
|
### 15. ✅ `element[0]` jQuery
|
||||||
|
`module/tirage/fenetre-recherche-tirage.js:213` — déjà résolu par refacto antérieur
|
||||||
|
|
||||||
|
### 16. ✅ `_warnedAppV1 = true`
|
||||||
|
Supprimé de `rdd-calendrier.js`; restant dans `_deprecated/` ignoré
|
||||||
|
|
||||||
|
### 17. ✅ `system.json` — nom de langue
|
||||||
|
`"name": "English"` → `"Français"` pour ne pas tromper sur `lang/fr.json`
|
||||||
@@ -2,7 +2,7 @@ import { RdDUtility } from "./rdd-utility.js";
|
|||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { RdDBonus } from "./rdd-bonus.js";
|
import { RdDBonus } from "./rdd-bonus.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombat } from "./combat/rdd-combat.js";
|
||||||
import { CARACS, RdDCarac } from "./rdd-carac.js";
|
import { CARACS, RdDCarac } from "./rdd-carac.js";
|
||||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||||
@@ -13,7 +13,7 @@ import { ACTOR_TYPES, ITEM_TYPES } from "./constants.js";
|
|||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
import { RdDItemBlessure } from "./item/blessure.js";
|
import { RdDItemBlessure } from "./item/blessure.js";
|
||||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
import { RdDEmpoignade } from "./combat/rdd-empoignade.js";
|
||||||
import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js";
|
import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js";
|
||||||
import { RdDCoeur } from "./coeur/rdd-coeur.js";
|
import { RdDCoeur } from "./coeur/rdd-coeur.js";
|
||||||
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js";
|
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js";
|
||||||
@@ -126,7 +126,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
|||||||
.forEach(tache => {
|
.forEach(tache => {
|
||||||
if (tache.isTacheCommune()) {
|
if (tache.isTacheCommune()) {
|
||||||
const tacheCommune = tache.getTacheOuCommune()
|
const tacheCommune = tache.getTacheOuCommune()
|
||||||
tache.system = foundry.utils.duplicate(tacheCommune.system)
|
tache.system = foundry.utils.deepClone(tacheCommune.system)
|
||||||
tache.system.tacheCommuneId = tache.system.tacheCommuneId
|
tache.system.tacheCommuneId = tache.system.tacheCommuneId
|
||||||
}
|
}
|
||||||
return tache
|
return tache
|
||||||
@@ -214,7 +214,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
|||||||
this.html.find('.action-jeu').click(async event => await this.actor.rollJeu(RdDSheetUtility.getItemId(event)))
|
this.html.find('.action-jeu').click(async event => await this.actor.rollJeu(RdDSheetUtility.getItemId(event)))
|
||||||
this.html.find('.action-recettecuisine').click(async event => await this.actor.rollRecetteCuisine(RdDSheetUtility.getItemId(event)))
|
this.html.find('.action-recettecuisine').click(async event => await this.actor.rollRecetteCuisine(RdDSheetUtility.getItemId(event)))
|
||||||
|
|
||||||
this.html.find('.description-aleatoire').click(async event => new AppPersonnageAleatoire(this.actor).render(true))
|
this.html.find('.description-aleatoire').click(async event => new AppPersonnageAleatoire(this.actor).render({ force: true }))
|
||||||
|
|
||||||
this.html.find('.gerer-herbes').click(async event => {
|
this.html.find('.gerer-herbes').click(async event => {
|
||||||
const { DialogGererHerbes } = await import("./dialog-gerer-herbes.js")
|
const { DialogGererHerbes } = await import("./dialog-gerer-herbes.js")
|
||||||
@@ -265,7 +265,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
|||||||
this.html.find('.roll-init-arme').click(async event => {
|
this.html.find('.roll-init-arme').click(async event => {
|
||||||
let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id)
|
let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id)
|
||||||
if (combatant) {
|
if (combatant) {
|
||||||
RdDCombatManager.rollInitiativeAction(combatant._id, this._getActionCombat(event));
|
RdDCombat.rollInitiativeAction(combatant.id, this._getActionCombat(event));
|
||||||
} else {
|
} else {
|
||||||
ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat.");
|
ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat.");
|
||||||
}
|
}
|
||||||
@@ -323,6 +323,8 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
|||||||
this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral(MORAL.NEUTRE))
|
this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral(MORAL.NEUTRE))
|
||||||
this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral(MORAL.HEUREUX))
|
this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral(MORAL.HEUREUX))
|
||||||
this.html.find('.button-ethylisme').click(async event => await this.actor.jetEthylisme())
|
this.html.find('.button-ethylisme').click(async event => await this.actor.jetEthylisme())
|
||||||
|
this.html.find('.btn-sust-externe').click(async event => await this.actor.mangerExterne())
|
||||||
|
this.html.find('.btn-sust-rations').click(async event => await this.actor.mangerRations())
|
||||||
|
|
||||||
this.html.find('.ptreve-actuel-plus').click(async event => await this.actor.reveActuelIncDec(1))
|
this.html.find('.ptreve-actuel-plus').click(async event => await this.actor.reveActuelIncDec(1))
|
||||||
this.html.find('.ptreve-actuel-moins').click(async event => await this.actor.reveActuelIncDec(-1))
|
this.html.find('.ptreve-actuel-moins').click(async event => await this.actor.reveActuelIncDec(-1))
|
||||||
@@ -371,18 +373,13 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
|||||||
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
||||||
}
|
}
|
||||||
content += '</select>';
|
content += '</select>';
|
||||||
let dialog = new Dialog({
|
new foundry.applications.api.DialogV2({
|
||||||
title: "Créer une oeuvre",
|
title: "Créer une oeuvre",
|
||||||
content: content,
|
content,
|
||||||
buttons: {
|
buttons: [
|
||||||
create: {
|
{ label: "Créer l'oeuvre", action: "create", icon: "fa-solid fa-check", callback: () => this.actor.createItem($(".item-type").val()) }
|
||||||
icon: '<i class="fas fa-check"></i>',
|
]
|
||||||
label: "Créer l'oeuvre",
|
}).render({ force: true });
|
||||||
callback: () => this.actor.createItem($(".item-type").val())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
dialog.render(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -428,7 +425,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
|||||||
async _onSplitItem(item, split) {
|
async _onSplitItem(item, split) {
|
||||||
if (split >= 1 && split < item.system.quantite) {
|
if (split >= 1 && split < item.system.quantite) {
|
||||||
await item.diminuerQuantite(split);
|
await item.diminuerQuantite(split);
|
||||||
const splitItem = foundry.utils.duplicate(item);
|
const splitItem = foundry.utils.deepClone(item);
|
||||||
splitItem.system.quantite = split;
|
splitItem.system.quantite = split;
|
||||||
await this.actor.createEmbeddedDocuments('Item', [splitItem])
|
await this.actor.createEmbeddedDocuments('Item', [splitItem])
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,8 @@ import { RdDItem } from "../item.js";
|
|||||||
import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js";
|
import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js";
|
||||||
import { ItemAction } from "../item/item-actions.js";
|
import { ItemAction } from "../item/item-actions.js";
|
||||||
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
|
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
|
||||||
|
import { DialogVerifierIngredients } from "../dialog-verifier-ingredients.js";
|
||||||
|
import { DialogLancerRecette } from "../dialog-lancer-recette.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/**
|
/**
|
||||||
@@ -90,6 +92,8 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
|
|||||||
|
|
||||||
this.html.find('.actionItem').click(async event => await ItemAction.onActionItem(event, this.actor, this.options))
|
this.html.find('.actionItem').click(async event => await ItemAction.onActionItem(event, this.actor, this.options))
|
||||||
this.html.find('.item-edit').click(async event => await this.itemActionEdit(event))
|
this.html.find('.item-edit').click(async event => await this.itemActionEdit(event))
|
||||||
|
this.html.find('.item-verify-ingredients').click(async event => await this._onVerifyIngredients(event))
|
||||||
|
this.html.find('.item-lancer-recette').click(async event => await this._onLancerRecette(event))
|
||||||
this.html.find('.conteneur-name a').click(async event => {
|
this.html.find('.conteneur-name a').click(async event => {
|
||||||
RdDUtility.toggleAfficheContenu(this.getItemId(event))
|
RdDUtility.toggleAfficheContenu(this.getItemId(event))
|
||||||
this.render(true)
|
this.render(true)
|
||||||
@@ -137,35 +141,57 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const item = this.getItem(event)
|
const item = this.getItem(event)
|
||||||
if (!item?.isInventaire()) return
|
if (!item?.isInventaire()) return
|
||||||
new Dialog({
|
new foundry.applications.api.DialogV2({
|
||||||
title: `Quantité — ${item.name}`,
|
title: `Quantité — ${item.name}`,
|
||||||
content: `<p>Réduire la quantité de :</p>
|
content: `<p>Réduire la quantité de :</p>
|
||||||
<select class="qty-amount" style="width:100%">
|
<select class="qty-amount">
|
||||||
<option value="1">1</option>
|
<option value="1">1</option>
|
||||||
<option value="5">5</option>
|
<option value="5">5</option>
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
<option value="all">Tout jeter</option>
|
<option value="all">Tout jeter</option>
|
||||||
</select>`,
|
</select>`,
|
||||||
buttons: {
|
buttons: [
|
||||||
reduce: {
|
{ action: "reduce", label: "Retirer", icon: "fa-solid fa-minus", callback: (event, button, dialog) => {
|
||||||
icon: '<i class="fas fa-minus"></i>',
|
const amount = dialog.element.querySelector('.qty-amount').value
|
||||||
label: 'Retirer',
|
if (amount === 'all') {
|
||||||
callback: html => {
|
item.delete()
|
||||||
const amount = html.find('.qty-amount').val()
|
this.render({ force: true })
|
||||||
if (amount === 'all') {
|
} else {
|
||||||
item.delete()
|
item.update({ 'system.quantite': Math.max(0, item.system.quantite - parseInt(amount)) })
|
||||||
this.render(true)
|
|
||||||
} else {
|
|
||||||
item.update({ 'system.quantite': Math.max(0, item.system.quantite - parseInt(amount)) })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}
|
]
|
||||||
}).render(true)
|
}).render({ force: true })
|
||||||
})
|
})
|
||||||
|
|
||||||
this.html.find('.creer-un-objet').click(async event => await this.selectObjetTypeToCreate())
|
this.html.find('.creer-un-objet').click(async event => await this.selectObjetTypeToCreate())
|
||||||
this.html.find('.nettoyer-conteneurs').click(async event => await this.actor.nettoyerConteneurs())
|
this.html.find('.nettoyer-conteneurs').click(async event => await this.actor.nettoyerConteneurs())
|
||||||
|
this.html.find('.quick-add-ration').click(async event => {
|
||||||
|
const existante = this.actor.items.find(it => it.type === "nourritureboisson" && it.name === "Ration")
|
||||||
|
if (existante) {
|
||||||
|
await existante.update({ "system.quantite": Math.max(0, Number(existante.system.quantite) + 1) })
|
||||||
|
} else {
|
||||||
|
await this.actor.createEmbeddedDocuments('Item', [{
|
||||||
|
name: "Ration", type: "nourritureboisson",
|
||||||
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
|
||||||
|
system: { sust: 1, encombrement: 0.1, quantite: 1, cout: 0.1, boisson: false }
|
||||||
|
}], { renderSheet: false })
|
||||||
|
}
|
||||||
|
this.render(true)
|
||||||
|
})
|
||||||
|
this.html.find('.quick-add-eau').click(async event => {
|
||||||
|
const existante = this.actor.items.find(it => it.type === "nourritureboisson" && it.name === "Eau")
|
||||||
|
if (existante) {
|
||||||
|
await existante.update({ "system.quantite": Math.max(0, Number(existante.system.quantite) + 1) })
|
||||||
|
} else {
|
||||||
|
await this.actor.createEmbeddedDocuments('Item', [{
|
||||||
|
name: "Eau", type: "nourritureboisson",
|
||||||
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/outre.webp",
|
||||||
|
system: { desaltere: 1, encombrement: 0.1, quantite: 1, cout: 0.05, boisson: true }
|
||||||
|
}], { renderSheet: false })
|
||||||
|
}
|
||||||
|
this.render(true)
|
||||||
|
})
|
||||||
|
|
||||||
this.html.find('.vue-detaillee').click(async event => {
|
this.html.find('.vue-detaillee').click(async event => {
|
||||||
this.options.vueDetaillee = !this.options.vueDetaillee
|
this.options.vueDetaillee = !this.options.vueDetaillee
|
||||||
@@ -174,8 +200,29 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
itemActionEdit(event) {
|
itemActionEdit(event) {
|
||||||
const item = this.getItem(event);
|
const item = this.getItem(event)
|
||||||
return item?.sheet.render(true);
|
if (item) item.sheet.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async _onVerifyIngredients(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const item = this.getItem(event)
|
||||||
|
if (!item || item.type !== ITEM_TYPES.recettealchimique) return
|
||||||
|
DialogVerifierIngredients.create(item, this.actor)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async _onLancerRecette(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const item = this.getItem(event)
|
||||||
|
if (!item || item.type !== ITEM_TYPES.recettealchimique) return
|
||||||
|
const ingredients = Misc.safeJsonParse(item.system.ingredients, [])
|
||||||
|
if (!ingredients.length) {
|
||||||
|
ui.notifications.warn('Cette recette n\'a pas d\'ingrédients définis.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
DialogLancerRecette.create(item, this.actor)
|
||||||
}
|
}
|
||||||
|
|
||||||
_rechercherKeyup(event) {
|
_rechercherKeyup(event) {
|
||||||
@@ -262,18 +309,13 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
|
|||||||
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
||||||
}
|
}
|
||||||
content += '</select>';
|
content += '</select>';
|
||||||
let d = new Dialog({
|
new foundry.applications.api.DialogV2({
|
||||||
title: "Créer un équipement",
|
title: "Créer un équipement",
|
||||||
content: content,
|
content,
|
||||||
buttons: {
|
buttons: [
|
||||||
create: {
|
{ action: "create", label: "Créer l'objet", icon: "fa-solid fa-check", callback: () => this.actor.createItem($(".item-type").val()) }
|
||||||
icon: '<i class="fas fa-check"></i>',
|
]
|
||||||
label: "Créer l'objet",
|
}).render({ force: true });
|
||||||
callback: () => this.actor.createItem($(".item-type").val())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
d.render(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getTypesInventaire() {
|
getTypesInventaire() {
|
||||||
@@ -302,7 +344,7 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
|
|||||||
async _onSplitItem(item, split) {
|
async _onSplitItem(item, split) {
|
||||||
if (split >= 1 && split < item.system.quantite) {
|
if (split >= 1 && split < item.system.quantite) {
|
||||||
await item.diminuerQuantite(split);
|
await item.diminuerQuantite(split);
|
||||||
const splitItem = foundry.utils.duplicate(item);
|
const splitItem = foundry.utils.deepClone(item);
|
||||||
splitItem.system.quantite = split;
|
splitItem.system.quantite = split;
|
||||||
await this.actor.createEmbeddedDocuments('Item', [splitItem])
|
await this.actor.createEmbeddedDocuments('Item', [splitItem])
|
||||||
}
|
}
|
||||||
+104
@@ -1,5 +1,109 @@
|
|||||||
# 13.0
|
# 13.0
|
||||||
|
|
||||||
|
## 14.0.4 - Le sommeil de Tétragor
|
||||||
|
|
||||||
|
### Sommeil & Château Dormant (nouveau mode de repos)
|
||||||
|
|
||||||
|
- Insomnie (Queue de Dragon)
|
||||||
|
- bannière d'avertissement dans le dialogue de repos
|
||||||
|
- rafraîchissement du drapeau à l'ouverture du dialogue
|
||||||
|
- vérification en direct dans la boucle de sommeil : si l'insomnie surgit en
|
||||||
|
cours de nuit, la récupération de fatigue et de rêve est interrompue
|
||||||
|
- drapeau remis à jour dans les deux sens (levée possible)
|
||||||
|
- mention dans le dialogue Château Dormant
|
||||||
|
- Château Dormant automatique : déclenché quand l'heure de fin de nuit (11) est
|
||||||
|
réellement atteinte, au lieu de seulement après 12 heures de sommeil
|
||||||
|
- Reprise de nuit après un Rêve de Dragon
|
||||||
|
- la durée de sommeil est conservée
|
||||||
|
- les heures restantes sont proposées à la réouverture du dialogue avec une
|
||||||
|
bannière « Reprise de nuit »
|
||||||
|
- remise à zéro après une nuit complète
|
||||||
|
- don « double rêve » : second jet de récupération de rêve par heure (parité
|
||||||
|
ancien mode)
|
||||||
|
- garde anti-boucle infinie si l'insomnie apparaît pendant le sommeil
|
||||||
|
- info-bulle sur le réveil forcé
|
||||||
|
- perte de rêve des enchantements au Château Dormant : suppression du message en
|
||||||
|
double (whisper dédié), texte intégré au résumé ; la gemme renvoie son
|
||||||
|
nouveau total de points de rêve
|
||||||
|
|
||||||
|
### Commerces
|
||||||
|
|
||||||
|
- achat depuis un commerce en quantité illimitée : la quantité achetée est
|
||||||
|
correctement utilisée au lieu de celle du commerce
|
||||||
|
- fiche commerce : le champ Description utilise toute la largeur de la fiche
|
||||||
|
|
||||||
|
### Compétences
|
||||||
|
|
||||||
|
- ne plus créer d'item « Sans compétence » lors des migrations
|
||||||
|
|
||||||
|
## 14.0.3 - Les bases de Tétragor
|
||||||
|
|
||||||
|
- XP des compétences : les bases de catégorie peuvent être négatives
|
||||||
|
(base stockée en entier signé, migration 14.0.3)
|
||||||
|
- réorganisation des titres CSS
|
||||||
|
|
||||||
|
## 14.0.2 - Le grang ménage de Tétragor
|
||||||
|
|
||||||
|
### Migration Foundry V14
|
||||||
|
|
||||||
|
- Migration des classes restantes de V1 vers V2 (ApplicationV2)
|
||||||
|
- OptionsAvancees, StatusEffects, SystemCompendiums, ReglesOptionnelles,
|
||||||
|
DialogEncaissementTables
|
||||||
|
- DialogV2: formes imbriquées, boutons, styles et positionnement corrigés
|
||||||
|
- DialogV2 requiert au moins un bouton (boutons vides interdits en V14)
|
||||||
|
- templates avec wrapper à racine unique
|
||||||
|
- correction des éditeurs ProseMirror et des scrollbar sur les fiches d'acteur
|
||||||
|
- rollMode → messageMode, Token HUD, data-message-id
|
||||||
|
- champ age en StringField pour compat V14
|
||||||
|
- compat V14: _onFirstRender (HTMLElement.show) pour les jets de dés,
|
||||||
|
fermeture des dialogs TMR après lecture d'un signe draconique
|
||||||
|
- 10 fichiers .js V1 inutilisés déplacés vers _deprecated/
|
||||||
|
- scrollbar des applications V2 corrigées (LESS, plus de style inline)
|
||||||
|
- migration de toutes les directives CSS inline vers LESS
|
||||||
|
- titres des tables d'encaissement alternatives lisibles
|
||||||
|
- le dialog ne passe plus au premier plan lors du re-render (hook)
|
||||||
|
- refresh des dialogs herbes/potions/ingrédients après édition de fiche
|
||||||
|
- TODO-v14.md pour le suivi de la compatibilité V14
|
||||||
|
|
||||||
|
### Feuilles d'items
|
||||||
|
|
||||||
|
- migration des feuilles d'items vers V2 (models, apps, templates, less + common/mixins)
|
||||||
|
- ajout des sections environnement (inventaire) et temporel (blessure, maladie,
|
||||||
|
poison, rencontre, signe draconique) manquantes dans les sheets V2
|
||||||
|
|
||||||
|
### Sommeil & Château Dormant
|
||||||
|
|
||||||
|
- nouveau mode sommeil avec sélection des heures de repos
|
||||||
|
- dialogs Château Dormant intégrés, toolbar équipement
|
||||||
|
- message de statut MJ + journal de suivi stress/moral/événements par jour
|
||||||
|
- journal enrichi avec stress, perte d'enchantements, moral
|
||||||
|
- message stress journal: perte fixe de 1, reste X, conversion Y en xp
|
||||||
|
- boutons Repas externe et Rations harmonisés avec les cartouches de tchat
|
||||||
|
|
||||||
|
### Inventaire
|
||||||
|
|
||||||
|
- boutons +Ration/+Eau et cartouche de tchat compacte
|
||||||
|
- consommation des rations: assez d'unités pour remplir sustentation/eau en un
|
||||||
|
clic + alerte si vide
|
||||||
|
- ne plus afficher « rien à manger » quand les compteurs sont déjà pleins
|
||||||
|
|
||||||
|
### Règles & encaissement
|
||||||
|
|
||||||
|
- fusion des Règles customs dans Règles optionnelles (section Options alternatives)
|
||||||
|
- tables d'encaissement révisées optionnelles + dialog de consultation
|
||||||
|
|
||||||
|
### Divers
|
||||||
|
|
||||||
|
- regroupement des classes de combat
|
||||||
|
- fix assign dans les constructeurs
|
||||||
|
|
||||||
|
### Tests automatisés
|
||||||
|
|
||||||
|
- plan de test (227 cas, 33 sections) + scripts TC-01 à TC-07
|
||||||
|
- 22 scripts TC supplémentaires (TC-08 à TC-31) avec fonctions partagées
|
||||||
|
- orchestrateur run-all-tests.sh (sélection, exécution, rapport final)
|
||||||
|
- documentation du lancement des tests dans test/README.md
|
||||||
|
|
||||||
## 14.0.1 - Les imprécisions de Tétragor
|
## 14.0.1 - Les imprécisions de Tétragor
|
||||||
|
|
||||||
- correction de l'indicateur de remplissage des conteneurs
|
- correction de l'indicateur de remplissage des conteneurs
|
||||||
|
|||||||
+5312
-149
File diff suppressed because it is too large
Load Diff
+648
-134
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
|||||||
|
.arme-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.armure-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.blessure-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.casetmr-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.chant-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.competence-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.competencecreature-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.conteneur-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.danse-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.empoignade-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.extraitpoetique-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.faune-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.gemme-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.herbe-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.ingredient-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.jeu-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.livre-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.maladie-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.meditation-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -3,5 +3,6 @@
|
|||||||
|
|
||||||
.item-sheet-common();
|
.item-sheet-common();
|
||||||
.item-sheet-header();
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// Styles pour la feuille d'objet Monnaie
|
// Styles pour la feuille d'objet Munition
|
||||||
.munition-content {
|
.munition-content {
|
||||||
|
|
||||||
.item-sheet-common();
|
.item-sheet-common();
|
||||||
.item-sheet-header();
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.musique-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.nombreastral-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.nourritureboisson-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.objet-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.oeuvre-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.ombre-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.plante-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.poison-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.possession-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.potion-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.queue-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.race-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
.recettealchimique-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
|
||||||
|
.ingredient-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.recettecuisine-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.rencontre-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.service-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.signedraconique-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.sort-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.sortreserve-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.souffle-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.tache-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
// Styles pour la feuille d'objet Monnaie
|
// Styles pour la feuille d'objet Tarot
|
||||||
.tarot-content {
|
.tarot-content {
|
||||||
|
|
||||||
.item-sheet-common();
|
.item-sheet-common();
|
||||||
.item-sheet-header();
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.tete-content {
|
||||||
|
.item-sheet-common();
|
||||||
|
.item-sheet-header();
|
||||||
|
.item-sheet-scrollable-body();
|
||||||
|
}
|
||||||
+26
-4
@@ -74,9 +74,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-sheet-scrollable-body() {
|
||||||
|
max-height: 75vh;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
> section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.sheet-header {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.sheet-body {
|
||||||
|
overflow-y: auto;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.item-sheet-header() {
|
.item-sheet-header() {
|
||||||
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
|
|
||||||
color: rgba(255, 255, 255, 1);
|
color: rgba(255, 255, 255, 1);
|
||||||
|
.sheet-header {
|
||||||
|
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
|
||||||
|
}
|
||||||
.sheet-header-row {
|
.sheet-header-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -86,7 +108,7 @@
|
|||||||
font-family: CaslonAntique;
|
font-family: CaslonAntique;
|
||||||
font-size: 2.5rem;
|
font-size: 2.5rem;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: var(--window-header-title-color);
|
color: var(--window-header-title-color, #fff);
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
}
|
}
|
||||||
@@ -100,8 +122,8 @@
|
|||||||
input[type="date"],
|
input[type="date"],
|
||||||
input[type="time"]
|
input[type="time"]
|
||||||
) {
|
) {
|
||||||
color: rgba(255, 255, 255, 0.75);
|
color: #fff;
|
||||||
background: rgba(255, 255, 255, 0.1);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
border: 0 none;
|
border: 0 none;
|
||||||
margin-bottom: 0.2rem;
|
margin-bottom: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Supprimer tous les items du monde
|
||||||
|
// Coller ce code dans une macro Foundry (type script)
|
||||||
|
const count = game.items.size
|
||||||
|
if (!count) return ui.notifications.info("Aucun item dans le monde.")
|
||||||
|
|
||||||
|
const confirmed = await Dialog.confirm({
|
||||||
|
title: "Supprimer tous les items",
|
||||||
|
content: `<p>⚠️ <b>${count} items</b> vont être définitivement supprimés.</p>`,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!confirmed) return
|
||||||
|
|
||||||
|
await Item.deleteDocuments(game.items.map(i => i.id))
|
||||||
|
ui.notifications.info(`${count} items supprimés.`)
|
||||||
@@ -12,7 +12,7 @@ export class ChatVente {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const nbLots = chatMessage.getFlag(SYSTEM_RDD, NB_LOTS)
|
const nbLots = chatMessage.getFlag(SYSTEM_RDD, NB_LOTS)
|
||||||
const detail = foundry.utils.duplicate(chatMessage.getFlag(SYSTEM_RDD, DETAIL_VENTE))
|
const detail = foundry.utils.deepClone(chatMessage.getFlag(SYSTEM_RDD, DETAIL_VENTE))
|
||||||
if (!detail.item) {
|
if (!detail.item) {
|
||||||
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
|
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { renderTemplate } from "../constants.js";
|
import { renderTemplate } from "../constants.js"
|
||||||
import { Misc } from "../misc.js";
|
import { Misc } from "../misc.js"
|
||||||
import { RdDUtility } from "../rdd-utility.js";
|
import { RdDUtility } from "../rdd-utility.js"
|
||||||
import { ChatVente } from "./chat-vente.js";
|
import { ChatVente } from "./chat-vente.js"
|
||||||
|
|
||||||
export class DialogItemAchat extends Dialog {
|
|
||||||
|
|
||||||
|
export class DialogItemAchat extends foundry.applications.api.DialogV2 {
|
||||||
static preparerAchat(chatButton) {
|
static preparerAchat(chatButton) {
|
||||||
return ChatVente.getDetailAchatVente(RdDUtility.findChatMessageId(chatButton))
|
return ChatVente.getDetailAchatVente(RdDUtility.findChatMessageId(chatButton))
|
||||||
}
|
}
|
||||||
@@ -21,57 +20,64 @@ export class DialogItemAchat extends Dialog {
|
|||||||
choix: { seForcer: false, supprimerSiZero: true },
|
choix: { seForcer: false, supprimerSiZero: true },
|
||||||
prixLot,
|
prixLot,
|
||||||
isVente: prixLot > 0,
|
isVente: prixLot > 0,
|
||||||
isConsommable: item.type == 'nourritureboisson' && acheteur?.isPersonnage(),
|
isConsommable: item.type == "nourritureboisson" && acheteur?.isPersonnage(),
|
||||||
chatMessageIdVente
|
chatMessageIdVente
|
||||||
}
|
}
|
||||||
if (venteData.vendeur?.id == venteData.acheteur?.id) {
|
if (venteData.vendeur?.id == venteData.acheteur?.id) {
|
||||||
ui.notifications.info("Inutile de se vendre à soi-même")
|
ui.notifications.info("Inutile de se vendre à soi-même")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogItemAchat.changeNombreLots(venteData, 1)
|
DialogItemAchat.changeNombreLots(venteData, 1)
|
||||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.hbs`, venteData)
|
const content = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.hbs", venteData)
|
||||||
new DialogItemAchat(html, venteData).render(true)
|
new DialogItemAchat(content, venteData).render({ force: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
static changeNombreLots(venteData, nombreLots) {
|
static changeNombreLots(venteData, nombreLots) {
|
||||||
venteData.choix.nombreLots = nombreLots;
|
venteData.choix.nombreLots = nombreLots
|
||||||
venteData.prixTotal = (nombreLots * venteData.prixLot).toFixed(2);
|
venteData.prixTotal = (nombreLots * venteData.prixLot).toFixed(2)
|
||||||
if (venteData.isConsommable) {
|
if (venteData.isConsommable) {
|
||||||
const doses = nombreLots * venteData.tailleLot;
|
const doses = nombreLots * venteData.tailleLot
|
||||||
venteData.totalSust = Misc.keepDecimals(doses * (venteData.item.system.sust ?? 0), 2);
|
venteData.totalSust = Misc.keepDecimals(doses * (venteData.item.system.sust ?? 0), 2)
|
||||||
venteData.totalDesaltere = venteData.item.system.boisson
|
venteData.totalDesaltere = venteData.item.system.boisson
|
||||||
? Misc.keepDecimals(doses * (venteData.item.system.desaltere ?? 0), 2)
|
? Misc.keepDecimals(doses * (venteData.item.system.desaltere ?? 0), 2)
|
||||||
: 0;
|
: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(html, venteData) {
|
constructor(content, venteData) {
|
||||||
let options = { classes: ["dialogachat"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre"
|
||||||
|
const buttons = []
|
||||||
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
|
|
||||||
const buttons = {};
|
|
||||||
if (venteData.isConsommable) {
|
if (venteData.isConsommable) {
|
||||||
buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => this.onAchatConsommer() }
|
buttons.push({
|
||||||
|
label: venteData.item.system.boisson ? "Boire" : "Manger",
|
||||||
|
action: "consommer",
|
||||||
|
callback: () => this.onAchatConsommer()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
|
buttons.push({ label: actionAchat, action: actionAchat, callback: () => this.onAchat() })
|
||||||
buttons["decliner"] = { label: "Décliner", callback: it => { } };
|
buttons.push({ label: "Décliner", action: "decliner", callback: () => {} })
|
||||||
const acheteur = venteData.acheteur?.name ?? 'Un acheteur';
|
const acheteur = venteData.acheteur?.name ?? "Un acheteur"
|
||||||
const vendeur = venteData.vendeur?.name ?? 'Un vendeur';
|
const vendeur = venteData.vendeur?.name ?? "Un vendeur"
|
||||||
let conf = {
|
super({
|
||||||
title: `${acheteur} - ${actionAchat} à ${vendeur}`,
|
title: `${acheteur} - ${actionAchat} à ${vendeur}`,
|
||||||
content: html,
|
content,
|
||||||
default: actionAchat,
|
classes: ["dialogachat"],
|
||||||
buttons: buttons
|
position: { width: 400, height: 'fit-content' },
|
||||||
};
|
buttons
|
||||||
|
})
|
||||||
|
this.venteData = venteData
|
||||||
|
}
|
||||||
|
|
||||||
super(conf, options);
|
_onRender(context) {
|
||||||
this.venteData = venteData;
|
super._onRender(context)
|
||||||
|
this.element.querySelector(".nombreLots")?.addEventListener("change", event => this.setNombreLots(Number(event.currentTarget.value)))
|
||||||
|
this.element.querySelector(".se-forcer")?.addEventListener("change", event => this.setSeForcer(event))
|
||||||
}
|
}
|
||||||
|
|
||||||
async onAchat() {
|
async onAchat() {
|
||||||
await this.html.find(".nombreLots").change();
|
const el = this.element
|
||||||
(this.venteData.vendeur ?? this.venteData.acheteur).achatVente({
|
el.querySelector(".nombreLots")?.dispatchEvent(new Event("change"))
|
||||||
|
;(this.venteData.vendeur ?? this.venteData.acheteur).achatVente({
|
||||||
userId: game.user.id,
|
userId: game.user.id,
|
||||||
vendeurId: this.venteData.vendeur?.id,
|
vendeurId: this.venteData.vendeur?.id,
|
||||||
acheteurId: this.venteData.acheteur?.id,
|
acheteurId: this.venteData.acheteur?.id,
|
||||||
@@ -79,42 +85,34 @@ export class DialogItemAchat extends Dialog {
|
|||||||
chatMessageIdVente: this.venteData.chatMessageIdVente,
|
chatMessageIdVente: this.venteData.chatMessageIdVente,
|
||||||
choix: this.venteData.choix,
|
choix: this.venteData.choix,
|
||||||
vente: this.venteData
|
vente: this.venteData
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async onAchatConsommer() {
|
async onAchatConsommer() {
|
||||||
this.venteData.choix.consommer = true;
|
this.venteData.choix.consommer = true
|
||||||
await this.onAchat();
|
await this.onAchat()
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
this.html = html;
|
|
||||||
this.html.find(".nombreLots").change(event => this.setNombreLots(Number(event.currentTarget.value)));
|
|
||||||
this.html.find(".se-forcer").change(event => this.setSeForcer(event));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setSeForcer(event) {
|
setSeForcer(event) {
|
||||||
this.venteData.choix.seForcer = event.currentTarget.checked;
|
this.venteData.choix.seForcer = event.currentTarget.checked
|
||||||
}
|
}
|
||||||
|
|
||||||
setNombreLots(nbLots) {
|
setNombreLots(nbLots) {
|
||||||
|
|
||||||
if (!this.venteData.quantiteIllimite) {
|
if (!this.venteData.quantiteIllimite) {
|
||||||
if (!this.venteData.quantiteIllimite && nbLots > this.venteData.nbLots) {
|
if (nbLots > this.venteData.nbLots) {
|
||||||
ui.notifications.warn(`Seulement ${this.venteData.nbLots} lots disponibles, vous ne pouvez pas en prendre ${nbLots}`)
|
ui.notifications.warn(`Seulement ${this.venteData.nbLots} lots disponibles, vous ne pouvez pas en prendre ${nbLots}`)
|
||||||
}
|
}
|
||||||
nbLots = Math.min(nbLots, this.venteData.nbLots);
|
nbLots = Math.min(nbLots, this.venteData.nbLots)
|
||||||
}
|
}
|
||||||
|
DialogItemAchat.changeNombreLots(this.venteData, nbLots)
|
||||||
DialogItemAchat.changeNombreLots(this.venteData, nbLots);
|
const el = this.element
|
||||||
|
const nbl = el.querySelector(".nombreLots")
|
||||||
this.html.find(".nombreLots").val(nbLots);
|
if (nbl) nbl.value = nbLots
|
||||||
this.html.find(".prixTotal").text(this.venteData.prixTotal);
|
const pt = el.querySelector(".prixTotal")
|
||||||
this.html.find("span.total-sust").text(this.venteData.totalSust);
|
if (pt) pt.textContent = this.venteData.prixTotal
|
||||||
this.html.find("span.total-desaltere").text(this.venteData.totalDesaltere);
|
const sust = el.querySelector("span.total-sust")
|
||||||
|
if (sust) sust.textContent = this.venteData.totalSust
|
||||||
|
const des = el.querySelector("span.total-desaltere")
|
||||||
|
if (des) des.textContent = this.venteData.totalDesaltere
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import { renderTemplate } from "../constants.js";
|
import { renderTemplate } from "../constants.js"
|
||||||
import { HtmlUtility } from "../html-utility.js";
|
import { HtmlUtility } from "../html-utility.js";
|
||||||
import { RdDUtility } from "../rdd-utility.js";
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
import { ChatVente } from "./chat-vente.js";
|
import { ChatVente } from "./chat-vente.js";
|
||||||
|
|
||||||
export class DialogItemVente extends Dialog {
|
export class DialogItemVente extends foundry.applications.api.DialogV2 {
|
||||||
|
|
||||||
static async display({ item, quantiteMax = undefined }) {
|
static async display({ item, quantiteMax = undefined }) {
|
||||||
const quantite = quantiteMax ?? item.getQuantite() ?? 1;
|
const quantite = quantiteMax ?? item.getQuantite() ?? 1
|
||||||
const venteData = {
|
const venteData = {
|
||||||
item: item,
|
item,
|
||||||
alias: item.actor?.name ?? game.user.name,
|
alias: item.actor?.name ?? game.user.name,
|
||||||
vendeurId: item.actor?.id,
|
vendeurId: item.actor?.id,
|
||||||
prixOrigine: item.calculerPrixCommercant(),
|
prixOrigine: item.calculerPrixCommercant(),
|
||||||
@@ -19,93 +18,99 @@ export class DialogItemVente extends Dialog {
|
|||||||
maxLots: quantite,
|
maxLots: quantite,
|
||||||
quantiteMax: quantite,
|
quantiteMax: quantite,
|
||||||
quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !item.parent,
|
quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !item.parent,
|
||||||
isOwned: item.parent,
|
isOwned: item.parent,
|
||||||
}
|
}
|
||||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.hbs`, venteData);
|
const content = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.hbs", venteData)
|
||||||
return new DialogItemVente(venteData, html).render(true);
|
const dialog = new DialogItemVente(venteData, content)
|
||||||
|
dialog.render({ force: true })
|
||||||
|
return dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(venteData, html) {
|
constructor(venteData, content) {
|
||||||
let options = { classes: ["dialogvente"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
super({
|
||||||
|
|
||||||
let conf = {
|
|
||||||
title: "Proposer",
|
title: "Proposer",
|
||||||
content: html,
|
content,
|
||||||
default: "proposer",
|
classes: ["dialogvente"],
|
||||||
buttons: { "proposer": { label: "Proposer", callback: it => { this.onProposer(it); } } }
|
position: { width: 400, height: 'fit-content' },
|
||||||
};
|
buttons: [
|
||||||
|
{ label: "Proposer", action: "proposer", callback: () => this.onProposer() }
|
||||||
super(conf, options);
|
]
|
||||||
this.venteData = venteData;
|
})
|
||||||
|
this.venteData = venteData
|
||||||
}
|
}
|
||||||
|
|
||||||
activateListeners(html) {
|
_onRender(context) {
|
||||||
super.activateListeners(html);
|
super._onRender(context)
|
||||||
|
const el = this.element
|
||||||
this.html = html;
|
el.querySelector(".tailleLot")?.addEventListener("change", event => this.setTailleLot(Number(event.currentTarget.value)))
|
||||||
this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
|
el.querySelector(".nbLots")?.addEventListener("change", event => this.setNbLots(Number(event.currentTarget.value)))
|
||||||
this.html.find(".nbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
|
el.querySelector(".quantiteIllimite")?.addEventListener("change", event => this.setQuantiteIllimite(event.currentTarget.checked))
|
||||||
this.html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
|
el.querySelector(".prixLot")?.addEventListener("change", event => this.setPrixLot(Number(event.currentTarget.value)))
|
||||||
this.html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
|
this.setQuantiteIllimite(this.venteData.quantiteIllimite)
|
||||||
|
|
||||||
this.setQuantiteIllimite(this.venteData.quantiteIllimite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onProposer(it) {
|
async onProposer() {
|
||||||
this.updateVente(this.getChoixVente());
|
this.updateVente(this.getChoixVente())
|
||||||
|
this.venteData["properties"] = this.venteData.item.getProprietes()
|
||||||
this.venteData["properties"] = this.venteData.item.getProprietes();
|
|
||||||
if (this.venteData.isOwned) {
|
if (this.venteData.isOwned) {
|
||||||
if (this.venteData.nbLots * this.venteData.tailleLot > this.venteData.quantiteMax) {
|
if (this.venteData.nbLots * this.venteData.tailleLot > this.venteData.quantiteMax) {
|
||||||
ui.notifications.warn(`Vous avez ${this.venteData.quantiteMax} ${this.venteData.item.name}, ce n'est pas suffisant pour vendre ${this.venteData.nbLots} de ${this.venteData.tailleLot}`)
|
ui.notifications.warn(`Vous avez ${this.venteData.quantiteMax} ${this.venteData.item.name}, ce n'est pas suffisant pour vendre ${this.venteData.nbLots} de ${this.venteData.tailleLot}`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ChatVente.displayAchatVente(this.venteData)
|
await ChatVente.displayAchatVente(this.venteData)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVente(update) {
|
updateVente(update) {
|
||||||
foundry.utils.mergeObject(this.venteData, update);
|
foundry.utils.mergeObject(this.venteData, update)
|
||||||
}
|
}
|
||||||
|
|
||||||
getChoixVente() {
|
getChoixVente() {
|
||||||
|
const el = this.element
|
||||||
return {
|
return {
|
||||||
nbLots: Number(this.html.find(".nbLots").val()),
|
nbLots: Number(el.querySelector(".nbLots")?.value ?? 0),
|
||||||
tailleLot: Number(this.html.find(".tailleLot").val()),
|
tailleLot: Number(el.querySelector(".tailleLot")?.value ?? 0),
|
||||||
quantiteIllimite: this.html.find(".quantiteIllimite").is(':checked'),
|
quantiteIllimite: el.querySelector(".quantiteIllimite")?.checked ?? false,
|
||||||
prixLot: Number(this.html.find(".prixLot").val())
|
prixLot: Number(el.querySelector(".prixLot")?.value ?? 0)
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
setPrixLot(prixLot) {
|
setPrixLot(prixLot) {
|
||||||
this.venteData.prixLot = prixLot;
|
this.venteData.prixLot = prixLot
|
||||||
}
|
}
|
||||||
|
|
||||||
setTailleLot(tailleLot) {
|
setTailleLot(tailleLot) {
|
||||||
const maxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
|
const maxLots = Math.floor(this.venteData.quantiteMax / tailleLot)
|
||||||
this.updateVente({
|
this.updateVente({
|
||||||
tailleLot,
|
tailleLot,
|
||||||
nbLots: Math.min(maxLots, this.venteData.nbLots),
|
nbLots: Math.min(maxLots, this.venteData.nbLots),
|
||||||
maxLots: maxLots,
|
maxLots,
|
||||||
prixLot: (tailleLot * this.venteData.prixOrigine).toFixed(2)
|
prixLot: (tailleLot * this.venteData.prixOrigine).toFixed(2)
|
||||||
});
|
})
|
||||||
|
const el = this.element
|
||||||
this.html.find(".prixLot").val(this.venteData.prixLot);
|
const prix = el.querySelector(".prixLot")
|
||||||
this.html.find(".nbLots").val(this.venteData.nbLots);
|
if (prix) prix.value = this.venteData.prixLot
|
||||||
this.html.find(".nbLots").attr("max", this.venteData.maxLots)
|
const nb = el.querySelector(".nbLots")
|
||||||
|
if (nb) {
|
||||||
|
nb.value = this.venteData.nbLots
|
||||||
|
nb.setAttribute("max", this.venteData.maxLots)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setNbLots(nbLots) {
|
setNbLots(nbLots) {
|
||||||
this.updateVente({
|
this.updateVente({
|
||||||
nbLots: this.venteData.isOwned ? Math.max(0, Math.min(nbLots, this.venteData.maxLots)) : nbLots
|
nbLots: this.venteData.isOwned ? Math.max(0, Math.min(nbLots, this.venteData.maxLots)) : nbLots
|
||||||
})
|
})
|
||||||
this.html.find(".nbLots").val(this.venteData.nbLots);
|
const nb = this.element.querySelector(".nbLots")
|
||||||
|
if (nb) nb.value = this.venteData.nbLots
|
||||||
}
|
}
|
||||||
|
|
||||||
setQuantiteIllimite(checked) {
|
setQuantiteIllimite(checked) {
|
||||||
this.updateVente({ quantiteIllimite: checked })
|
this.updateVente({ quantiteIllimite: checked })
|
||||||
this.html.find(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles");
|
const el = this.element
|
||||||
HtmlUtility.showControlWhen(this.html.find(".nbLots"), !this.venteData.quantiteIllimite)
|
const label = el.querySelector(".label-quantiteIllimite")
|
||||||
|
if (label) label.textContent = checked ? "Illimités" : "disponibles"
|
||||||
|
const nb = el.querySelector(".nbLots")
|
||||||
|
if (nb) HtmlUtility.showControlWhen(nb, !checked)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+169
-88
@@ -18,14 +18,16 @@ import { CARACS, LIST_CARAC_PERSONNAGE, RdDCarac } from "./rdd-carac.js";
|
|||||||
import { DialogConsommer } from "./dialog-item-consommer.js";
|
import { DialogConsommer } from "./dialog-item-consommer.js";
|
||||||
import { DialogFabriquerPotion } from "./dialog-fabriquer-potion.js";
|
import { DialogFabriquerPotion } from "./dialog-fabriquer-potion.js";
|
||||||
import { RollDataAjustements } from "./rolldata-ajustements-v1.js";
|
import { RollDataAjustements } from "./rolldata-ajustements-v1.js";
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
import { RdDPossession } from "./combat/rdd-possession.js";
|
||||||
|
import { RdDPossessionV2 } from "./combat/rdd-possession-v2.mjs";
|
||||||
import { ACTOR_TYPES, renderTemplate, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { ACTOR_TYPES, renderTemplate, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { RdDConfirm } from "./rdd-confirm.js";
|
import { RdDConfirm } from "./rdd-confirm.js";
|
||||||
import { DialogRepos } from "./sommeil/dialog-repos.js";
|
import { DialogRepos } from "./sommeil/dialog-repos.js";
|
||||||
|
import { DialogNouveauRepos } from "./sommeil/dialog-nouveau-repos.js";
|
||||||
import { RdDBaseActor } from "./actor/base-actor.js";
|
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
import { AppAstrologie } from "./sommeil/app-astrologie.js";
|
import { AppAstrologie } from "./sommeil/app-astrologie.js";
|
||||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
import { RdDEmpoignade } from "./combat/rdd-empoignade.js";
|
||||||
import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js";
|
import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js";
|
||||||
import { ITEM_TYPES } from "./constants.js";
|
import { ITEM_TYPES } from "./constants.js";
|
||||||
import { RdDBaseActorSang } from "./actor/base-actor-sang.js";
|
import { RdDBaseActorSang } from "./actor/base-actor-sang.js";
|
||||||
@@ -34,7 +36,7 @@ import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js";
|
|||||||
|
|
||||||
import { ATTAQUE_TYPE, RdDItemArme } from "./item/arme.js";
|
import { ATTAQUE_TYPE, RdDItemArme } from "./item/arme.js";
|
||||||
import { RdDItemBlessure } from "./item/blessure.js";
|
import { RdDItemBlessure } from "./item/blessure.js";
|
||||||
import { RdDItemTete } from "./item/tete.js";
|
import { RdDItemTete } from "./documents/_module.mjs";
|
||||||
import { RdDItemSort } from "./item-sort.js";
|
import { RdDItemSort } from "./item-sort.js";
|
||||||
import { RdDItemRace } from "./item/race.js";
|
import { RdDItemRace } from "./item/race.js";
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
@@ -44,11 +46,10 @@ import { DialogSelect } from "./dialog-select.js";
|
|||||||
import { CATEGORIES_COMPETENCES, PAS_DE_DRACONIC, SANS_DRACONIC } from "./item/base-items.js";
|
import { CATEGORIES_COMPETENCES, PAS_DE_DRACONIC, SANS_DRACONIC } from "./item/base-items.js";
|
||||||
|
|
||||||
import { RdDRollResult } from "./rdd-roll-result.js";
|
import { RdDRollResult } from "./rdd-roll-result.js";
|
||||||
import { RdDInitiative } from "./initiative.mjs";
|
import { RdDInitiative } from "./combat/initiative.mjs";
|
||||||
import RollDialog from "./roll/roll-dialog.mjs";
|
import RollDialog from "./roll/roll-dialog.mjs";
|
||||||
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
|
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
|
||||||
import { ROLL_TYPE_COMP, ROLL_TYPE_CUISINE, ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_SORT, ROLL_TYPE_APPEL_CHANCE, ROLL_TYPE_TACHE } from "./roll/roll-constants.mjs";
|
import { ROLL_TYPE_COMP, ROLL_TYPE_CUISINE, ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_SORT, ROLL_TYPE_APPEL_CHANCE, ROLL_TYPE_TACHE } from "./roll/roll-constants.mjs";
|
||||||
import { RdDPossessionV2 } from "./rdd-possession-v2.mjs";
|
|
||||||
import { Apprecier, MORAL, SITUATION_MORAL } from "./moral/apprecier.mjs";
|
import { Apprecier, MORAL, SITUATION_MORAL } from "./moral/apprecier.mjs";
|
||||||
import { Distance } from "./combat/distance.mjs";
|
import { Distance } from "./combat/distance.mjs";
|
||||||
|
|
||||||
@@ -62,36 +63,6 @@ export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
|
|||||||
*/
|
*/
|
||||||
export class RdDActor extends RdDBaseActorSang {
|
export class RdDActor extends RdDBaseActorSang {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/**
|
|
||||||
* Prepare Character type specific data
|
|
||||||
*/
|
|
||||||
prepareActorData() {
|
|
||||||
|
|
||||||
RdDItemRace.applyRacialLimits(this)
|
|
||||||
|
|
||||||
this.system.carac.melee.value = Math.floor((this.getForce() + parseInt(this.system.carac.agilite.value)) / 2);
|
|
||||||
this.system.carac.tir.value = Math.floor((parseInt(this.system.carac.vue.value) + parseInt(this.system.carac.dexterite.value)) / 2);
|
|
||||||
this.system.carac.lancer.value = Math.floor((parseInt(this.system.carac.tir.value) + parseInt(this.system.carac.force.value)) / 2);
|
|
||||||
this.system.carac.derobee.value = Math.floor(parseInt(((21 - this.system.carac.taille.value)) + parseInt(this.system.carac.agilite.value)) / 2);
|
|
||||||
|
|
||||||
super.prepareActorData()
|
|
||||||
|
|
||||||
this.system.attributs.sconst.value = RdDCarac.calculSConst(this.getConstitution())
|
|
||||||
this.system.attributs.sust.value = RdDCarac.getCaracDerivee(this.getTaille()).sust
|
|
||||||
|
|
||||||
this.system.sante.fatigue.max = this.getFatigueMax()
|
|
||||||
this.system.sante.fatigue.value = Math.min(this.system.sante.fatigue.value, this.system.sante.fatigue.max);
|
|
||||||
|
|
||||||
//Compteurs
|
|
||||||
this.system.reve.reve.max = 3 * this.getReve()
|
|
||||||
this.system.compteurs.chance.max = this.getChance()
|
|
||||||
|
|
||||||
this.system.attributs.hautrevant.value = this.itemTypes[ITEM_TYPES.tete].find(it => RdDItemTete.isDonDeHautReve(it))
|
|
||||||
? "Haut rêvant"
|
|
||||||
: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
canReceive(item) {
|
canReceive(item) {
|
||||||
return ![ITEM_TYPES.competencecreature, ITEM_TYPES.tarot, ITEM_TYPES.service].includes(item.type)
|
return ![ITEM_TYPES.competencecreature, ITEM_TYPES.tarot, ITEM_TYPES.service].includes(item.type)
|
||||||
@@ -243,19 +214,26 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async $perteReveEnchantementsChateauDormants() {
|
async $perteReveEnchantementsChateauDormants(message = undefined) {
|
||||||
const toUpdate = this.items.filter(it => [ITEM_TYPES.potion, ITEM_TYPES.gemme].includes(it.type))
|
const toUpdate = this.items.filter(it => [ITEM_TYPES.potion, ITEM_TYPES.gemme].includes(it.type))
|
||||||
.map(it => it.perteReveChateauDormant())
|
.map(it => it.perteReveChateauDormant())
|
||||||
.filter(it => it != undefined)
|
.filter(it => it != undefined)
|
||||||
|
|
||||||
if (toUpdate.length > 0) {
|
if (toUpdate.length > 0) {
|
||||||
console.log('perte de rêve des enchantements', toUpdate)
|
console.log('perte de rêve des enchantements', toUpdate)
|
||||||
const messageUpdates = await Promise.all(
|
if (message) {
|
||||||
toUpdate.map(async it => await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-pertereve-enchantement-chateaudormant.hbs`, it)))
|
message.content += toUpdate
|
||||||
await ChatMessage.create({
|
.map(it => {
|
||||||
whisper: ChatUtility.getOwners(this),
|
const type = it.item.type === 'potion' ? 'potion' : 'gemme'
|
||||||
content: messageUpdates.reduce(Misc.joining('<br>'))
|
const nouveaupr = it.nouveaupr ?? it.item.system.pr
|
||||||
})
|
let texte = `La ${type} enchantée ${it.item.name} de ${it.alias} a perdu un Point de Rêve (nouveau total : ${nouveaupr}).`
|
||||||
|
if (type === 'potion' && nouveaupr === 0) {
|
||||||
|
texte += ` Sa potion étant désormais à 0 Point de Rêve, elle est inutilisable et peut être jetée.`
|
||||||
|
}
|
||||||
|
return texte
|
||||||
|
})
|
||||||
|
.reduce(Misc.joining(' ')) + ' '
|
||||||
|
}
|
||||||
await this.updateEmbeddedDocuments('Item', toUpdate.map(it => it.update));
|
await this.updateEmbeddedDocuments('Item', toUpdate.map(it => it.update));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,7 +274,11 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async repos() {
|
async repos() {
|
||||||
await DialogRepos.create(this);
|
if (ReglesOptionnelles.isUsing("nouveau-mode-repos")) {
|
||||||
|
await DialogNouveauRepos.create(this);
|
||||||
|
} else {
|
||||||
|
await DialogRepos.create(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -360,15 +342,16 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
whisper: ChatUtility.getOwners(this),
|
whisper: ChatUtility.getOwners(this),
|
||||||
content: ""
|
content: ""
|
||||||
}
|
}
|
||||||
|
const stressAvant = this.system.compteurs.stress.value
|
||||||
|
|
||||||
await this._recuperationSante(message)
|
await this._recuperationSante(message)
|
||||||
await this._recupereMoralChateauDormant(message)
|
await this._recupereMoralChateauDormant(message)
|
||||||
await this._recupereChance()
|
await this._recupereChance()
|
||||||
await this.transformerStress()
|
await this.transformerStress(message)
|
||||||
await this.retourSeuilDeReve(message)
|
await this.retourSeuilDeReve(message)
|
||||||
await this.setBonusPotionSoin(0)
|
await this.setBonusPotionSoin(0)
|
||||||
await this.retourSust(message)
|
await this.retourSust(message)
|
||||||
await this.$perteReveEnchantementsChateauDormants()
|
await this.$perteReveEnchantementsChateauDormants(message)
|
||||||
await this.$suppressionLancementsSort()
|
await this.$suppressionLancementsSort()
|
||||||
await RdDCoeur.applyCoeurChateauDormant(this, message)
|
await RdDCoeur.applyCoeurChateauDormant(this, message)
|
||||||
if (message.content != "") {
|
if (message.content != "") {
|
||||||
@@ -376,6 +359,35 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
await ChatMessage.create(message)
|
await ChatMessage.create(message)
|
||||||
}
|
}
|
||||||
await this.resetInfoSommeil()
|
await this.resetInfoSommeil()
|
||||||
|
|
||||||
|
const stressApres = this.system.compteurs.stress.value
|
||||||
|
const date = game.system.rdd.calendrier.dateCourante()
|
||||||
|
const recapMJ = `**${this.name}** — Château Dormant (${date})<br>Stress : ${stressAvant} → ${stressApres}`
|
||||||
|
await ChatUtility.tellToGM(message.content ? recapMJ + '<br>' + message.content : recapMJ)
|
||||||
|
|
||||||
|
const journalId = game.settings.get(SYSTEM_RDD, 'cd-suivi-journal')
|
||||||
|
if (journalId) {
|
||||||
|
const journalEntry = game.journal.get(journalId)
|
||||||
|
if (journalEntry?.canUserModify(game.user, 'update')) {
|
||||||
|
const timestamp = game.system.rdd.calendrier.getTimestamp()
|
||||||
|
const jour = timestamp.jour + 1
|
||||||
|
const mois = RdDTimestamp.definition(timestamp.mois).label
|
||||||
|
const annee = timestamp.annee
|
||||||
|
const section = `${jour} ${mois} ${annee}`
|
||||||
|
const log = `<p><b>${this.name}</b> — Stress ${stressAvant} → ${stressApres}</p>` + message.content
|
||||||
|
let page = journalEntry.pages.find(p => p.type == 'text' && Grammar.equalsInsensitive(p.name, section))
|
||||||
|
if (page) {
|
||||||
|
await page.update({ 'text.content': page.text.content + '\n' + log })
|
||||||
|
} else {
|
||||||
|
await journalEntry.createEmbeddedDocuments('JournalEntryPage', [new JournalEntryPage({
|
||||||
|
name: section,
|
||||||
|
type: 'text',
|
||||||
|
title: { show: true, level: 1 },
|
||||||
|
text: { content: log, format: 1 }
|
||||||
|
})])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async resetInfoSommeil() {
|
async resetInfoSommeil() {
|
||||||
@@ -391,9 +403,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setInfoSommeilInsomnie() {
|
async setInfoSommeilInsomnie() {
|
||||||
if (EffetsDraconiques.isSujetInsomnie(this)) {
|
await this.update({ 'system.sommeil.insomnie': EffetsDraconiques.isSujetInsomnie(this) });
|
||||||
await this.update({ 'system.sommeil.insomnie': true });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async setInfoSommeilMoral(situationMoral) {
|
async setInfoSommeilMoral(situationMoral) {
|
||||||
@@ -657,6 +667,69 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
return cumul;
|
return cumul;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async mangerExterne() {
|
||||||
|
const besoin = this.system.attributs.sust.value
|
||||||
|
await this.update({
|
||||||
|
'system.compteurs.sust.value': besoin,
|
||||||
|
'system.compteurs.eau.value': besoin
|
||||||
|
})
|
||||||
|
ChatUtility.tellToUserAndGM(`${this.name} a mangé et bu pour la journée (repas externe)`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async mangerRations() {
|
||||||
|
const besoin = this.system.attributs.sust.value
|
||||||
|
let restantSust = besoin - this.system.compteurs.sust.value
|
||||||
|
let restantEau = besoin - this.system.compteurs.eau.value
|
||||||
|
let totalSust = 0, totalEau = 0
|
||||||
|
let foundAny = false
|
||||||
|
|
||||||
|
if (restantSust <= 0 && restantEau <= 0) return
|
||||||
|
|
||||||
|
for (const item of this.items) {
|
||||||
|
if (item.type !== 'nourritureboisson') continue
|
||||||
|
|
||||||
|
const qty = item.system.quantite
|
||||||
|
if (!qty || qty <= 0) continue
|
||||||
|
const sustUnit = item.system.sust || 0
|
||||||
|
const eauUnit = item.system.desaltere || 0
|
||||||
|
if (sustUnit <= 0 && eauUnit <= 0) continue
|
||||||
|
|
||||||
|
foundAny = true
|
||||||
|
let unitNeeded = 0
|
||||||
|
if (restantSust > 0 && sustUnit > 0) {
|
||||||
|
unitNeeded = Math.max(unitNeeded, Math.ceil(restantSust / sustUnit))
|
||||||
|
}
|
||||||
|
if (restantEau > 0 && eauUnit > 0) {
|
||||||
|
unitNeeded = Math.max(unitNeeded, Math.ceil(restantEau / eauUnit))
|
||||||
|
}
|
||||||
|
const take = Math.min(unitNeeded, qty)
|
||||||
|
|
||||||
|
totalSust += Math.min(sustUnit * take, restantSust)
|
||||||
|
totalEau += Math.min(eauUnit * take, restantEau)
|
||||||
|
restantSust -= Math.min(sustUnit * take, restantSust)
|
||||||
|
restantEau -= Math.min(eauUnit * take, restantEau)
|
||||||
|
|
||||||
|
await item.diminuerQuantite(take)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundAny) {
|
||||||
|
ChatUtility.tellToUserAndGM(`${this.name} n'a rien à manger dans ses rations !`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalSust > 0) {
|
||||||
|
await this.update({ 'system.compteurs.sust.value': this.system.compteurs.sust.value + totalSust })
|
||||||
|
}
|
||||||
|
if (totalEau > 0) {
|
||||||
|
await this.update({ 'system.compteurs.eau.value': this.system.compteurs.eau.value + totalEau })
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatUtility.tellToUserAndGM(
|
||||||
|
`${this.name} a mangé ${totalSust}/${besoin} sust, bu ${totalEau}/${besoin} eau (rations)`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async retourSeuilDeReve(message) {
|
async retourSeuilDeReve(message) {
|
||||||
const seuil = this.system.reve.seuil.value;
|
const seuil = this.system.reve.seuil.value;
|
||||||
@@ -776,7 +849,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
let carac = this.findCaracByName(caracName);
|
let carac = this.findCaracByName(caracName);
|
||||||
if (carac) {
|
if (carac) {
|
||||||
carac = foundry.utils.duplicate(carac);
|
carac = foundry.utils.deepClone(carac);
|
||||||
const fromXp = Number(carac.xp);
|
const fromXp = Number(carac.xp);
|
||||||
const fromValue = Number(carac.value);
|
const fromValue = Number(carac.value);
|
||||||
let toXp = fromXp;
|
let toXp = fromXp;
|
||||||
@@ -916,7 +989,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
|
|
||||||
async deleteExperienceLog(from, count) {
|
async deleteExperienceLog(from, count) {
|
||||||
if (from >= 0 && count > 0) {
|
if (from >= 0 && count > 0) {
|
||||||
let expLog = foundry.utils.duplicate(this.system.experiencelog)
|
let expLog = foundry.utils.deepClone(this.system.experiencelog)
|
||||||
expLog.splice(from, count)
|
expLog.splice(from, count)
|
||||||
await this.update({ [`system.experiencelog`]: expLog })
|
await this.update({ [`system.experiencelog`]: expLog })
|
||||||
}
|
}
|
||||||
@@ -1046,7 +1119,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
notifyRefreshTMR() {
|
notifyRefreshTMR() {
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
msg: "msg_tmr_move", data: {
|
msg: "msg_tmr_move", data: {
|
||||||
actorId: this._id,
|
actorId: this.id,
|
||||||
tmrPos: this.system.reve.tmrpos
|
tmrPos: this.system.reve.tmrpos
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1256,7 +1329,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async mangerNourriture(item) {
|
async mangerNourriture(item) {
|
||||||
return (await DialogConsommer.create(this, item)).render(true);
|
return await DialogConsommer.create(this, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
async actionLire(item) {
|
async actionLire(item) {
|
||||||
@@ -1383,7 +1456,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async saouler(forceAlcool, alcool = undefined) {
|
async saouler(forceAlcool, alcool = undefined) {
|
||||||
let ethylisme = foundry.utils.duplicate(this.system.compteurs.ethylisme);
|
let ethylisme = foundry.utils.deepClone(this.system.compteurs.ethylisme);
|
||||||
|
|
||||||
const etat = this.getEtatGeneral({ ethylisme: true });
|
const etat = this.getEtatGeneral({ ethylisme: true });
|
||||||
const nbDoses = Number(this.system.compteurs.ethylisme.nb_doses || 0);
|
const nbDoses = Number(this.system.compteurs.ethylisme.nb_doses || 0);
|
||||||
@@ -1457,7 +1530,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async transformerStress() {
|
async transformerStress(message = undefined) {
|
||||||
if (!ReglesOptionnelles.isUsing("transformation-stress")) { return }
|
if (!ReglesOptionnelles.isUsing("transformation-stress")) { return }
|
||||||
const fromStress = Number(this.system.compteurs.stress.value);
|
const fromStress = Number(this.system.compteurs.stress.value);
|
||||||
if (this.system.sommeil?.insomnie || fromStress <= 0) {
|
if (this.system.sommeil?.insomnie || fromStress <= 0) {
|
||||||
@@ -1491,6 +1564,11 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-transformer-stress.hbs`, stressRollData)
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-transformer-stress.hbs`, stressRollData)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
const reste = Math.max(fromStress - stressRollData.perte - 1, 0)
|
||||||
|
message.content += `Transformation de ${stressRollData.stress} points de stress : perte fixe de 1, reste ${reste}, conversion de ${stressRollData.convertis} en expérience. `
|
||||||
|
}
|
||||||
|
|
||||||
const toStress = Math.max(fromStress - stressRollData.perte - 1, 0);
|
const toStress = Math.max(fromStress - stressRollData.perte - 1, 0);
|
||||||
const fromXpSress = Number(this.system.compteurs.experience.value);
|
const fromXpSress = Number(this.system.compteurs.experience.value);
|
||||||
const toXpStress = fromXpSress + Number(stressRollData.xp);
|
const toXpStress = fromXpSress + Number(stressRollData.xp);
|
||||||
@@ -1543,7 +1621,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
const niveauSuivant = Number(carac.value) + 1;
|
const niveauSuivant = Number(carac.value) + 1;
|
||||||
let xpNeeded = RdDCarac.getCaracNextXp(niveauSuivant);
|
let xpNeeded = RdDCarac.getCaracNextXp(niveauSuivant);
|
||||||
if (carac.xp >= xpNeeded) {
|
if (carac.xp >= xpNeeded) {
|
||||||
carac = foundry.utils.duplicate(carac);
|
carac = foundry.utils.deepClone(carac);
|
||||||
carac.value = niveauSuivant;
|
carac.value = niveauSuivant;
|
||||||
|
|
||||||
let checkXp = {
|
let checkXp = {
|
||||||
@@ -1570,10 +1648,10 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async ajoutExperience(rollData, hideChatMessage = 'show') {
|
async ajoutExperience(rollData, hideChatMessage = 'show') {
|
||||||
const rollMode = rollData.current?.rollmode?.key ?? game.settings.get("core", "rollMode")
|
const rollMode = rollData.current?.rollmode?.key ?? game.settings.get("core", "messageMode")
|
||||||
if (!rollData.rolled.isPart ||
|
if (!rollData.rolled.isPart ||
|
||||||
rollData.finalLevel >= 0 ||
|
rollData.finalLevel >= 0 ||
|
||||||
rollMode == 'selfroll' ||
|
rollMode == 'self' ||
|
||||||
!Misc.hasConnectedGM()) {
|
!Misc.hasConnectedGM()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1599,7 +1677,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async appliquerAppelMoral(rollData) {
|
async appliquerAppelMoral(rollData) {
|
||||||
if (!rollData.use.moral || game.settings.get("core", "rollMode") == 'selfroll') {
|
if (!rollData.use.moral || game.settings.get("core", "messageMode") == 'self') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (rollData.rolled.isEchec ||
|
if (rollData.rolled.isEchec ||
|
||||||
@@ -1641,14 +1719,14 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
return await this.rollUnSortV2();
|
return await this.rollUnSortV2();
|
||||||
}
|
}
|
||||||
// Duplication car les pts de reve sont modifiés dans le sort!
|
// Duplication car les pts de reve sont modifiés dans le sort!
|
||||||
let sorts = foundry.utils.duplicate(this.itemTypes[ITEM_TYPES.sort].filter(it => RdDItemSort.isSortOnCoord(it, coord)))
|
let sorts = foundry.utils.deepClone(this.itemTypes[ITEM_TYPES.sort].filter(it => RdDItemSort.isSortOnCoord(it, coord)))
|
||||||
if (sorts.length == 0) {
|
if (sorts.length == 0) {
|
||||||
ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
|
ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const draconicList = this.computeDraconicAndSortIndex(sorts)
|
const draconicList = this.computeDraconicAndSortIndex(sorts)
|
||||||
const reve = foundry.utils.duplicate(this.system.carac.reve)
|
const reve = foundry.utils.deepClone(this.system.carac.reve)
|
||||||
|
|
||||||
const dialog = await this.openRollDialog({
|
const dialog = await this.openRollDialog({
|
||||||
name: 'lancer-un-sort',
|
name: 'lancer-un-sort',
|
||||||
@@ -1765,7 +1843,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
console.log('lancement de sort', rollData.selectedSort)
|
console.log('lancement de sort', rollData.selectedSort)
|
||||||
const lancements = RdDItemSort.prepareSortAddLancement(rollData.selectedSort, rollData.selectedSort.system.ptreve_reel)
|
const lancements = RdDItemSort.prepareSortAddLancement(rollData.selectedSort, rollData.selectedSort.system.ptreve_reel)
|
||||||
await this.updateEmbeddedDocuments('Item',
|
await this.updateEmbeddedDocuments('Item',
|
||||||
[{ _id: rollData.selectedSort._id, 'system.lancements': lancements }]
|
[{ _id: rollData.selectedSort.id, 'system.lancements': lancements }]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1903,7 +1981,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
diffConditions: 0,
|
diffConditions: 0,
|
||||||
use: { libre: false, conditions: true },
|
use: { libre: false, conditions: true },
|
||||||
carac: {
|
carac: {
|
||||||
[tache.system.carac]: foundry.utils.duplicate(this.system.carac[tache.system.carac])
|
[tache.system.carac]: foundry.utils.deepClone(this.system.carac[tache.system.carac])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
callbacks: [{ action: r => this._tacheResult(r, options) }]
|
callbacks: [{ action: r => this._tacheResult(r, options) }]
|
||||||
@@ -1965,7 +2043,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
const artData = {
|
const artData = {
|
||||||
art: 'jeu', verbe: 'Jeu',
|
art: 'jeu', verbe: 'Jeu',
|
||||||
use: { libre: true, conditions: true, },
|
use: { libre: true, conditions: true, },
|
||||||
competence: foundry.utils.duplicate(this.getCompetence('jeu')),
|
competence: foundry.utils.deepClone(this.getCompetence('jeu')),
|
||||||
forceCarac: {}
|
forceCarac: {}
|
||||||
};
|
};
|
||||||
listCarac.forEach(c => artData.forceCarac[c] = this.system.carac[c]);
|
listCarac.forEach(c => artData.forceCarac[c] = this.system.carac[c]);
|
||||||
@@ -1977,7 +2055,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async rollMeditation(id) {
|
async rollMeditation(id) {
|
||||||
const meditation = foundry.utils.duplicate(this.getMeditation(id));
|
const meditation = foundry.utils.deepClone(this.getMeditation(id));
|
||||||
|
|
||||||
if (meditation && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
if (meditation && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||||
const rollData = {
|
const rollData = {
|
||||||
@@ -1988,7 +2066,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
return await RollDialog.create(rollData)
|
return await RollDialog.create(rollData)
|
||||||
}
|
}
|
||||||
|
|
||||||
const competence = foundry.utils.duplicate(this.getCompetence(meditation.system.competence));
|
const competence = foundry.utils.deepClone(this.getCompetence(meditation.system.competence));
|
||||||
competence.system.defaut_carac = "intellect"; // Meditation = toujours avec intellect
|
competence.system.defaut_carac = "intellect"; // Meditation = toujours avec intellect
|
||||||
let meditationData = {
|
let meditationData = {
|
||||||
competence: competence,
|
competence: competence,
|
||||||
@@ -2018,7 +2096,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
await this.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditationRoll.meditation, meditationRoll.rolled)]);
|
await this.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditationRoll.meditation, meditationRoll.rolled)]);
|
||||||
}
|
}
|
||||||
if (meditationRoll.rolled.isEPart) {
|
if (meditationRoll.rolled.isEPart) {
|
||||||
await this.updateEmbeddedDocuments('Item', [{ _id: meditationRoll.meditation._id, 'system.malus': meditationRoll.meditation.system.malus - 1 }]);
|
await this.updateEmbeddedDocuments('Item', [{ _id: meditationRoll.meditation.id, 'system.malus': meditationRoll.meditation.system.malus - 1 }]);
|
||||||
}
|
}
|
||||||
await this.santeIncDec("fatigue", 2);
|
await this.santeIncDec("fatigue", 2);
|
||||||
await RdDRollResult.displayRollData(meditationRoll, this.name, 'chat-resultat-meditation.hbs');
|
await RdDRollResult.displayRollData(meditationRoll, this.name, 'chat-resultat-meditation.hbs');
|
||||||
@@ -2050,7 +2128,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
let draconicList = this.getDraconics()
|
let draconicList = this.getDraconics()
|
||||||
.filter(it => it.system.niveau > -11)
|
.filter(it => it.system.niveau > -11)
|
||||||
.map(draconic => {
|
.map(draconic => {
|
||||||
let draconicLecture = foundry.utils.duplicate(draconic)
|
let draconicLecture = foundry.utils.deepClone(draconic)
|
||||||
draconicLecture.system.defaut_carac = "intellect"
|
draconicLecture.system.defaut_carac = "intellect"
|
||||||
return draconicLecture
|
return draconicLecture
|
||||||
});
|
});
|
||||||
@@ -2100,12 +2178,15 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
if (rollData.xpSort > 0) {
|
if (rollData.xpSort > 0) {
|
||||||
const fromXp = Number(compData.system.xp_sort);
|
const fromXp = Number(compData.system.xp_sort);
|
||||||
const toXp = fromXp + rollData.xpSort;
|
const toXp = fromXp + rollData.xpSort;
|
||||||
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': toXp }]);
|
await this.updateEmbeddedDocuments("Item", [{ _id: compData.id, 'system.xp_sort': toXp }]);
|
||||||
await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXp, toXp, `${rollData.competence.name} : signe draconique`);
|
await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXp, toXp, `${rollData.competence.name} : signe draconique`);
|
||||||
}
|
}
|
||||||
await this.deleteEmbeddedDocuments("Item", [rollData.signe._id]);
|
await this.deleteEmbeddedDocuments("Item", [rollData.signe.id]);
|
||||||
await RdDRollResult.displayRollData(rollData, this.name, 'chat-resultat-lecture-signedraconique.hbs');
|
await RdDRollResult.displayRollData(rollData, this.name, 'chat-resultat-lecture-signedraconique.hbs');
|
||||||
this.tmrApp.close();
|
if (this.tmrApp) {
|
||||||
|
this.tmrApp.subdialog = undefined; // débloque $forceClose qui refuse de fermer tant qu'un subdialog est actif
|
||||||
|
await this.tmrApp.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -2205,7 +2286,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
if (xpData.competence) {
|
if (xpData.competence) {
|
||||||
const from = Number(xpData.competence.system.xp);
|
const from = Number(xpData.competence.system.xp);
|
||||||
const to = from + xpData.xpCompetence;
|
const to = from + xpData.xpCompetence;
|
||||||
await this.updateEmbeddedDocuments('Item', [{ _id: xpData.competence._id, 'system.xp': to }]);
|
await this.updateEmbeddedDocuments('Item', [{ _id: xpData.competence.id, 'system.xp': to }]);
|
||||||
xpData.checkComp = await this.checkCompetenceXP(xpData.competence.name, undefined, false)
|
xpData.checkComp = await this.checkCompetenceXP(xpData.competence.name, undefined, false)
|
||||||
await ExperienceLog.add(this, XP_TOPIC.XP, from, to, xpData.competence.name);
|
await ExperienceLog.add(this, XP_TOPIC.XP, from, to, xpData.competence.name);
|
||||||
return [xpData]
|
return [xpData]
|
||||||
@@ -2216,7 +2297,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _xpCarac(xpData) {
|
async _xpCarac(xpData) {
|
||||||
if (xpData.xpCarac > 0) {
|
if (xpData.xpCarac > 0) {
|
||||||
const carac = foundry.utils.duplicate(this.system.carac)
|
const carac = foundry.utils.deepClone(this.system.carac)
|
||||||
const code = RdDBaseActor._findCaracNode(carac, xpData.caracName)
|
const code = RdDBaseActor._findCaracNode(carac, xpData.caracName)
|
||||||
const selectedCarac = carac[code]
|
const selectedCarac = carac[code]
|
||||||
if (this.isCaracMax(code)) {
|
if (this.isCaracMax(code)) {
|
||||||
@@ -2269,7 +2350,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async deleteNombresAstraux() {
|
async deleteNombresAstraux() {
|
||||||
const deletions = this.itemTypes['nombreastral'].map(it => it._id);
|
const deletions = this.itemTypes['nombreastral'].map(it => it.id);
|
||||||
await this.deleteEmbeddedDocuments("Item", deletions);
|
await this.deleteEmbeddedDocuments("Item", deletions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2294,7 +2375,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
if (calendrier) {
|
if (calendrier) {
|
||||||
const toDelete = this.itemTypes['nombreastral']
|
const toDelete = this.itemTypes['nombreastral']
|
||||||
.filter(it => calendrier.isAfterIndexDate(it.system.jourindex))
|
.filter(it => calendrier.isAfterIndexDate(it.system.jourindex))
|
||||||
.map(it => it._id);
|
.map(it => it.id);
|
||||||
await this.deleteEmbeddedDocuments("Item", toDelete);
|
await this.deleteEmbeddedDocuments("Item", toDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2513,7 +2594,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
async incDecItemUse(itemId, shouldIncrease = true) {
|
async incDecItemUse(itemId, shouldIncrease = true) {
|
||||||
if (shouldIncrease) {
|
if (shouldIncrease) {
|
||||||
const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse');
|
const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse');
|
||||||
let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {};
|
let itemUse = currentItemUse ? foundry.utils.deepClone(currentItemUse) : {};
|
||||||
itemUse[itemId] = (itemUse[itemId] ?? 0) + 1;
|
itemUse[itemId] = (itemUse[itemId] ?? 0) + 1;
|
||||||
await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse);
|
await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse);
|
||||||
}
|
}
|
||||||
@@ -2610,7 +2691,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setPointsCoeur(subActorId, coeurs, options = { immediat: false }) {
|
async setPointsCoeur(subActorId, coeurs, options = { immediat: false }) {
|
||||||
const newSuivants = foundry.utils.duplicate(this.system.subacteurs.suivants)
|
const newSuivants = foundry.utils.deepClone(this.system.subacteurs.suivants)
|
||||||
const amoureux = newSuivants.find(it => it.id == subActorId)
|
const amoureux = newSuivants.find(it => it.id == subActorId)
|
||||||
if (amoureux) {
|
if (amoureux) {
|
||||||
amoureux[options.immediat ? 'coeur' : 'prochainCoeur'] = coeurs
|
amoureux[options.immediat ? 'coeur' : 'prochainCoeur'] = coeurs
|
||||||
@@ -2654,7 +2735,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
if (!this.isAddSubActeurAllowed(subActor)) {
|
if (!this.isAddSubActeurAllowed(subActor)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const subActorOnlyId = { id: subActor._id };
|
const subActorOnlyId = { id: subActor.id };
|
||||||
if (subActor.type == 'vehicule') {
|
if (subActor.type == 'vehicule') {
|
||||||
this.pushSubActeur(subActorOnlyId, this.system.subacteurs.vehicules, `system.subacteurs.vehicules`, `Le véhicule ${subActor.name}`)
|
this.pushSubActeur(subActorOnlyId, this.system.subacteurs.vehicules, `system.subacteurs.vehicules`, `Le véhicule ${subActor.name}`)
|
||||||
} else if (subActor.type == 'creature') {
|
} else if (subActor.type == 'creature') {
|
||||||
@@ -2805,7 +2886,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.createEmbeddedDocuments('Item', [newPotion])
|
await this.createEmbeddedDocuments('Item', [newPotion])
|
||||||
await this.diminuerQuantiteObjet(herbeData._id, herbeData.nbBrins)
|
await this.diminuerQuantiteObjet(herbeData.id, herbeData.nbBrins)
|
||||||
|
|
||||||
await ChatMessage.create({
|
await ChatMessage.create({
|
||||||
whisper: ChatUtility.getOwners(this),
|
whisper: ChatUtility.getOwners(this),
|
||||||
@@ -2980,8 +3061,8 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
|
|
||||||
incarnation.name = 'Réincarnation de ' + incarnation.name
|
incarnation.name = 'Réincarnation de ' + incarnation.name
|
||||||
incarnation.system = {
|
incarnation.system = {
|
||||||
carac: foundry.utils.duplicate(this.system.carac),
|
carac: foundry.utils.deepClone(this.system.carac),
|
||||||
heure: RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key,
|
heure: RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "self", showDice: SHOW_DICE })).key,
|
||||||
age: 18,
|
age: 18,
|
||||||
biographie: '',
|
biographie: '',
|
||||||
notes: '',
|
notes: '',
|
||||||
@@ -3061,7 +3142,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const artData = { art: 'oeuvre', verbe: 'Interpréter' }
|
const artData = { art: 'oeuvre', verbe: 'Interpréter' }
|
||||||
const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art))
|
const oeuvre = foundry.utils.deepClone(this.findItemLike(id, artData.art))
|
||||||
await this._rollArtV1(artData, oeuvre.system.default_carac, oeuvre)
|
await this._rollArtV1(artData, oeuvre.system.default_carac, oeuvre)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3072,7 +3153,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const artData = { art: 'chant', verbe: 'Chanter' }
|
const artData = { art: 'chant', verbe: 'Chanter' }
|
||||||
const oeuvre = foundry.utils.duplicate(this.getChant(id))
|
const oeuvre = foundry.utils.deepClone(this.getChant(id))
|
||||||
await this._rollArtV1(artData, "ouie", oeuvre)
|
await this._rollArtV1(artData, "ouie", oeuvre)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3083,14 +3164,14 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} }
|
const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} }
|
||||||
const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art))
|
const oeuvre = foundry.utils.deepClone(this.findItemLike(id, artData.art))
|
||||||
let selectedCarac = this.getCompetence(oeuvre.system.competence)?.system.defaut_carac
|
let selectedCarac = this.getCompetence(oeuvre.system.competence)?.system.defaut_carac
|
||||||
if (oeuvre.system.apparence) {
|
if (oeuvre.system.apparence) {
|
||||||
artData.forceCarac['apparence'] = foundry.utils.duplicate(this.system.carac.apparence)
|
artData.forceCarac['apparence'] = foundry.utils.deepClone(this.system.carac.apparence)
|
||||||
selectedCarac = "apparence"
|
selectedCarac = "apparence"
|
||||||
}
|
}
|
||||||
if (oeuvre.system.agilite) {
|
if (oeuvre.system.agilite) {
|
||||||
artData.forceCarac['agilite'] = foundry.utils.duplicate(this.system.carac.agilite)
|
artData.forceCarac['agilite'] = foundry.utils.deepClone(this.system.carac.agilite)
|
||||||
selectedCarac = "agilite"
|
selectedCarac = "agilite"
|
||||||
}
|
}
|
||||||
await this._rollArtV1(artData, selectedCarac, oeuvre)
|
await this._rollArtV1(artData, selectedCarac, oeuvre)
|
||||||
@@ -3115,17 +3196,17 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
{
|
{
|
||||||
oeuvre: oeuvre,
|
oeuvre: oeuvre,
|
||||||
art: oeuvre.type,
|
art: oeuvre.type,
|
||||||
competence: foundry.utils.duplicate(this.getCompetence(artData.compName ?? oeuvre.system.competence ?? artData.art)),
|
competence: foundry.utils.deepClone(this.getCompetence(artData.compName ?? oeuvre.system.competence ?? artData.art)),
|
||||||
diffLibre: - oeuvre.system.niveau,
|
diffLibre: - oeuvre.system.niveau,
|
||||||
diffConditions: 0,
|
diffConditions: 0,
|
||||||
use: { libre: false, conditions: true, surenc: false },
|
use: { libre: false, conditions: true, surenc: false },
|
||||||
selectedCarac: foundry.utils.duplicate(this.system.carac[selected])
|
selectedCarac: foundry.utils.deepClone(this.system.carac[selected])
|
||||||
},
|
},
|
||||||
{ overwrite: false });
|
{ overwrite: false });
|
||||||
artData.competence.system.defaut_carac = selected;
|
artData.competence.system.defaut_carac = selected;
|
||||||
if (!artData.forceCarac) {
|
if (!artData.forceCarac) {
|
||||||
artData.forceCarac = {};
|
artData.forceCarac = {};
|
||||||
artData.forceCarac[selected] = foundry.utils.duplicate(this.system.carac[selected]);
|
artData.forceCarac[selected] = foundry.utils.deepClone(this.system.carac[selected]);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.openRollDialog({
|
await this.openRollDialog({
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
|||||||
import { RdDBaseActor } from "./base-actor.js";
|
import { RdDBaseActor } from "./base-actor.js";
|
||||||
import { ITEM_TYPES } from "../constants.js";
|
import { ITEM_TYPES } from "../constants.js";
|
||||||
import { StatusEffects, STATUSES } from "../settings/status-effects.js";
|
import { StatusEffects, STATUSES } from "../settings/status-effects.js";
|
||||||
import { Targets } from "../targets.js";
|
import { Targets } from "../combat/targets.js";
|
||||||
import { RdDConfirm } from "../rdd-confirm.js";
|
import { RdDConfirm } from "../rdd-confirm.js";
|
||||||
import { CARACS, RdDCarac } from "../rdd-carac.js";
|
import { CARACS, RdDCarac } from "../rdd-carac.js";
|
||||||
import { RdDRollResult } from "../rdd-roll-result.js";
|
import { RdDRollResult } from "../rdd-roll-result.js";
|
||||||
@@ -19,18 +19,19 @@ import { RdDItemCompetence } from "../item-competence.js";
|
|||||||
|
|
||||||
import { ChatUtility } from "../chat-utility.js";
|
import { ChatUtility } from "../chat-utility.js";
|
||||||
import { DialogValidationEncaissement } from "../dialog-validation-encaissement.js";
|
import { DialogValidationEncaissement } from "../dialog-validation-encaissement.js";
|
||||||
import { RdDCombat } from "../rdd-combat.js";
|
import { PasseArme } from "../combat/passe-arme.mjs";
|
||||||
import { RdDEmpoignade } from "../rdd-empoignade.js";
|
import { RdDEmpoignade } from "../combat/rdd-empoignade.js";
|
||||||
import { RdDPossession } from "../rdd-possession.js";
|
import { RdDPossession } from "../combat/rdd-possession.js";
|
||||||
|
import { RdDPossessionV2 } from "../combat/rdd-possession-v2.mjs";
|
||||||
|
|
||||||
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES, SANS_DRACONIC } from "../item/base-items.js";
|
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES, SANS_DRACONIC } from "../item/base-items.js";
|
||||||
import { RollDataAjustements } from "../rolldata-ajustements-v1.js";
|
import { RollDataAjustements } from "../rolldata-ajustements-v1.js";
|
||||||
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
|
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
|
||||||
import RollDialog from "../roll/roll-dialog.mjs";
|
import RollDialog from "../roll/roll-dialog.mjs";
|
||||||
import { DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP, ROLL_TYPE_REVE_RESISTANCE } from "../roll/roll-constants.mjs";
|
import { DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP, ROLL_TYPE_REVE_RESISTANCE } from "../roll/roll-constants.mjs";
|
||||||
import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
|
import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
|
||||||
import { RdDInitiative } from "../initiative.mjs";
|
import { RdDInitiative } from "../combat/initiative.mjs";
|
||||||
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
|
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
|
||||||
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Classe de base pour les acteurs disposant de rêve (donc, pas des objets)
|
* Classe de base pour les acteurs disposant de rêve (donc, pas des objets)
|
||||||
@@ -39,13 +40,6 @@ import { RdDPossessionV2 } from "../rdd-possession-v2.mjs";
|
|||||||
*/
|
*/
|
||||||
export class RdDBaseActorReve extends RdDBaseActor {
|
export class RdDBaseActorReve extends RdDBaseActor {
|
||||||
|
|
||||||
prepareActorData() {
|
|
||||||
super.prepareActorData()
|
|
||||||
this.system.attributs.plusdom.value = this.getBonusDegat()
|
|
||||||
this.system.sante.endurance.max = this.getEnduranceMax()
|
|
||||||
this.system.sante.endurance.value = Math.min(this.system.sante.endurance.value, this.system.sante.endurance.max)
|
|
||||||
}
|
|
||||||
|
|
||||||
getCarac() {
|
getCarac() {
|
||||||
const carac = super.getCarac()
|
const carac = super.getCarac()
|
||||||
foundry.utils.mergeObject(carac, this.getCaracReveActuel())
|
foundry.utils.mergeObject(carac, this.getCaracReveActuel())
|
||||||
@@ -369,7 +363,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
|||||||
selectedCarac: carac,
|
selectedCarac: carac,
|
||||||
competence: competence,
|
competence: competence,
|
||||||
diffLibre: diff ?? 0,
|
diffLibre: diff ?? 0,
|
||||||
current: { rollmode: { key: game.settings.get("core", "rollMode") } },
|
current: { rollmode: { key: game.settings.get("core", "messageMode") } },
|
||||||
show: { title: options?.title ?? '' }
|
show: { title: options?.title ?? '' }
|
||||||
}
|
}
|
||||||
RollDataAjustements.calcul(rollData, this);
|
RollDataAjustements.calcul(rollData, this);
|
||||||
@@ -531,7 +525,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
|||||||
RdDPossession.onAttaquePossession(target, this, competence)
|
RdDPossession.onAttaquePossession(target, this, competence)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme)
|
PasseArme.rddCombatTarget(target, this, token).attaque(competence, arme)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return
|
return
|
||||||
@@ -566,7 +560,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RdDCombat.rddCombatTarget(target, this, token).attaqueV2();
|
PasseArme.rddCombatTarget(target, this, token).attaqueV2();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -630,7 +624,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
|||||||
// TODO: vérifier si c'est possible, sinon simplifier
|
// TODO: vérifier si c'est possible, sinon simplifier
|
||||||
return RdDPossession.onAttaquePossession(target, this, comp);
|
return RdDPossession.onAttaquePossession(target, this, comp);
|
||||||
}
|
}
|
||||||
RdDCombat.rddCombatTarget(target, this, token).attaque(comp, arme, maniement)
|
PasseArme.rddCombatTarget(target, this, token).attaque(comp, arme, maniement)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,7 +690,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
|||||||
{ actor: this }))
|
{ actor: this }))
|
||||||
|
|
||||||
if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) {
|
if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) {
|
||||||
encaissement = foundry.utils.duplicate(encaissement)
|
encaissement = foundry.utils.deepClone(encaissement)
|
||||||
encaissement.isGM = true
|
encaissement.isGM = true
|
||||||
await ChatMessage.create({
|
await ChatMessage.create({
|
||||||
whisper: ChatUtility.getGMs(),
|
whisper: ChatUtility.getGMs(),
|
||||||
|
|||||||
@@ -25,13 +25,6 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
|||||||
return super._preUpdate(changed, options, user)
|
return super._preUpdate(changed, options, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareActorData() {
|
|
||||||
this.system.sante.vie.max = Math.ceil((this.getTaille() + this.getConstitution()) / 2)
|
|
||||||
this.system.sante.vie.value = Math.min(this.system.sante.vie.value, this.system.sante.vie.max)
|
|
||||||
super.prepareActorData()
|
|
||||||
this.system.attributs.encombrement.value = this.getEncombrementMax()
|
|
||||||
}
|
|
||||||
|
|
||||||
getCarac() {
|
getCarac() {
|
||||||
const carac = super.getCarac()
|
const carac = super.getCarac()
|
||||||
foundry.utils.mergeObject(carac, this.getCaracChanceActuelle())
|
foundry.utils.mergeObject(carac, this.getCaracChanceActuelle())
|
||||||
@@ -109,7 +102,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
async onAppliquerJetEncaissement(encaissement, attackerToken) {
|
async onAppliquerJetEncaissement(encaissement, attackerToken) {
|
||||||
const santeOrig = foundry.utils.duplicate(this.system.sante);
|
const santeOrig = foundry.utils.deepClone(this.system.sante);
|
||||||
const blessure = this.nouvelleBlessure(encaissement.gravite, {
|
const blessure = this.nouvelleBlessure(encaissement.gravite, {
|
||||||
localisation: encaissement.dmg?.loc.label ?? '',
|
localisation: encaissement.dmg?.loc.label ?? '',
|
||||||
origine: attackerToken?.name ?? ''
|
origine: attackerToken?.name ?? ''
|
||||||
@@ -124,7 +117,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
|||||||
await rollPerteEndurance.evaluate()
|
await rollPerteEndurance.evaluate()
|
||||||
blessure.system.endurance = rollPerteEndurance.total
|
blessure.system.endurance = rollPerteEndurance.total
|
||||||
}
|
}
|
||||||
const isCritique = blessure.system.gravite >= 6;
|
const isCritique = blessure.system.gravite >= 6 || encaissement._reduireEndAZero;
|
||||||
if (isCritique) {
|
if (isCritique) {
|
||||||
blessure.system.endurance = this.getEnduranceActuelle()
|
blessure.system.endurance = this.getEnduranceActuelle()
|
||||||
}
|
}
|
||||||
@@ -156,7 +149,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
|||||||
if (!this.system.sante[name]) {
|
if (!this.system.sante[name]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const sante = foundry.utils.duplicate(this.system.sante)
|
const sante = foundry.utils.deepClone(this.system.sante)
|
||||||
const compteur = sante[name]
|
const compteur = sante[name]
|
||||||
const result = { sonne: false }
|
const result = { sonne: false }
|
||||||
let perteEndurance = 0
|
let perteEndurance = 0
|
||||||
|
|||||||
+18
-18
@@ -91,7 +91,7 @@ export class RdDBaseActor extends Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getRealActor(actorId, tokenId) {
|
static getRealActor(actorId, tokenId) {
|
||||||
const actor = tokenId ? canvas.tokens.get(tokenId)?.actor : undefined
|
const actor = tokenId ? canvas?.tokens?.get(tokenId)?.actor : undefined
|
||||||
return actor ?? game.actors.get(actorId)
|
return actor ?? game.actors.get(actorId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ export class RdDBaseActor extends Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCarac() {
|
getCarac() {
|
||||||
return foundry.utils.duplicate(this.system.carac)
|
return foundry.utils.deepClone(this.system.carac)
|
||||||
}
|
}
|
||||||
|
|
||||||
findCaracByName(name) {
|
findCaracByName(name) {
|
||||||
@@ -220,16 +220,16 @@ export class RdDBaseActor extends Actor {
|
|||||||
await this.delayedRenderSheet('_preUpdate', changed, options)
|
await this.delayedRenderSheet('_preUpdate', changed, options)
|
||||||
return super._preUpdate(changed, options, user)
|
return super._preUpdate(changed, options, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
_onUpdate(changed, options, userId) {
|
_onUpdate(changed, options, userId) {
|
||||||
super._onUpdate(changed, options, userId)
|
super._onUpdate(changed, options, userId)
|
||||||
if (userId == game.user.id){
|
if (userId == game.user.id) {
|
||||||
this.delayedRenderSheet('_onUpdate', changed, options)
|
this.delayedRenderSheet('_onUpdate', changed, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async delayedRenderSheet(caller, data, options) {
|
async delayedRenderSheet(caller, data, options) {
|
||||||
this.refreshDelayCounter = (this.refreshDelayCounter ?? 0)+1
|
this.refreshDelayCounter = (this.refreshDelayCounter ?? 0) + 1
|
||||||
if (this.refreshDelayCounter == 1) {
|
if (this.refreshDelayCounter == 1) {
|
||||||
this.renderAfterDelay(this.refreshDelayCounter)
|
this.renderAfterDelay(this.refreshDelayCounter)
|
||||||
}
|
}
|
||||||
@@ -250,14 +250,11 @@ export class RdDBaseActor extends Actor {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
prepareData() {
|
prepareData() {
|
||||||
super.prepareData()
|
super.prepareData()
|
||||||
this.prepareActorData()
|
|
||||||
this.cleanupConteneurs()
|
this.cleanupConteneurs()
|
||||||
this.computeEtatGeneral()
|
this.computeEtatGeneral()
|
||||||
this.computeEncTotal()
|
this.computeEncTotal()
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareActorData() { }
|
|
||||||
|
|
||||||
async computeEtatGeneral() { }
|
async computeEtatGeneral() { }
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -383,8 +380,8 @@ export class RdDBaseActor extends Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onTimeChanging(oldTimestamp, newTimestamp) {
|
async onTimeChanging(oldTimestamp, newTimestamp) {
|
||||||
this.items.filter(it => it.isFinPeriode(oldTimestamp, newTimestamp))
|
await Promise.all(this.items.filter(it => it.isFinPeriode(oldTimestamp, newTimestamp))
|
||||||
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
|
.map(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async creerObjetParMJ(object) {
|
async creerObjetParMJ(object) {
|
||||||
@@ -404,7 +401,7 @@ export class RdDBaseActor extends Actor {
|
|||||||
if (Misc.isOwnerPlayer(this)) {
|
if (Misc.isOwnerPlayer(this)) {
|
||||||
let updates = this.itemTypes[ITEM_TYPES.conteneur]
|
let updates = this.itemTypes[ITEM_TYPES.conteneur]
|
||||||
.filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0)
|
.filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0)
|
||||||
.map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } });
|
.map(c => { return { _id: c.id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } });
|
||||||
if (updates.length > 0) {
|
if (updates.length > 0) {
|
||||||
await this.updateEmbeddedDocuments("Item", updates)
|
await this.updateEmbeddedDocuments("Item", updates)
|
||||||
}
|
}
|
||||||
@@ -545,7 +542,7 @@ export class RdDBaseActor extends Actor {
|
|||||||
if (cout > 0) {
|
if (cout > 0) {
|
||||||
RdDAudio.PlayContextAudio("argent");
|
RdDAudio.PlayContextAudio("argent");
|
||||||
}
|
}
|
||||||
const chatAchatItem = foundry.utils.duplicate(achat.vente);
|
const chatAchatItem = foundry.utils.deepClone(achat.vente);
|
||||||
chatAchatItem.quantiteTotal = quantite;
|
chatAchatItem.quantiteTotal = quantite;
|
||||||
await ChatMessage.create({
|
await ChatMessage.create({
|
||||||
user: achat.userId,
|
user: achat.userId,
|
||||||
@@ -631,17 +628,20 @@ export class RdDBaseActor extends Actor {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const isItemEmpilable = "quantite" in item.system;
|
|
||||||
const baseItem = {
|
const baseItem = {
|
||||||
|
id: undefined,
|
||||||
type: item.type,
|
type: item.type,
|
||||||
img: item.img,
|
img: item.img,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false })
|
system: foundry.utils.duplicate(item.system)
|
||||||
}
|
}
|
||||||
|
const createItemArray = "quantite" in item.system
|
||||||
|
? (it, qt) => { it.system.quantite = qt; return [it] }
|
||||||
|
: (it, qt) => Array.from({ length: qt }, (_, i) => it)
|
||||||
|
|
||||||
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
|
const newItems = createItemArray(baseItem, quantite)
|
||||||
const items = await this.createEmbeddedDocuments("Item", newItems);
|
const items = await this.createEmbeddedDocuments("Item", newItems)
|
||||||
return newItems.length > 0 ? items[0].id : undefined;
|
return items.length > 0 ? items[0].id : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -851,7 +851,7 @@ export class RdDBaseActor extends Actor {
|
|||||||
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
|
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
|
||||||
|
|
||||||
const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id))
|
const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id))
|
||||||
.map(it => foundry.utils.duplicate(it))
|
.map(it => foundry.utils.deepClone(it))
|
||||||
.map(it => { it.system.contenu = []; return it; });
|
.map(it => { it.system.contenu = []; return it; });
|
||||||
let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate);
|
let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate);
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ async function randomPoidsKg(taille) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function randomHeure() {
|
async function randomHeure() {
|
||||||
return RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key
|
return RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "self", showDice: SHOW_DICE })).key
|
||||||
}
|
}
|
||||||
|
|
||||||
const CONTROL_UNKNOWN = { name: 'unknown', path: '', getter: (act) => { undefined }, random: async act => undefined }
|
const CONTROL_UNKNOWN = { name: 'unknown', path: '', getter: (act) => { undefined }, random: async act => undefined }
|
||||||
@@ -79,7 +79,24 @@ const CONTROLS = [
|
|||||||
{ name: 'yeux', path: 'system.yeux', getter: act => act.system.yeux, random: async act => await randomFrom(TABLE_COULEURS_YEUX) },
|
{ name: 'yeux', path: 'system.yeux', getter: act => act.system.yeux, random: async act => await randomFrom(TABLE_COULEURS_YEUX) },
|
||||||
]
|
]
|
||||||
|
|
||||||
export class AppPersonnageAleatoire extends FormApplication {
|
const { HandlebarsApplicationMixin } = foundry.applications.api;
|
||||||
|
export class AppPersonnageAleatoire extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/foundryvtt-reve-de-dragon/templates/actor/random/app-personnage-aleatoire.hbs" }
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ['app-personnage-aleatoire'],
|
||||||
|
window: {
|
||||||
|
title: "Génération aléatoire",
|
||||||
|
controls: []
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
width: 600,
|
||||||
|
height: 600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static preloadHandlebars() {
|
static preloadHandlebars() {
|
||||||
foundry.applications.handlebars.loadTemplates([
|
foundry.applications.handlebars.loadTemplates([
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs',
|
||||||
@@ -87,18 +104,6 @@ export class AppPersonnageAleatoire extends FormApplication {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor/random/app-personnage-aleatoire.hbs",
|
|
||||||
title: "Génération aléatoire",
|
|
||||||
width: 'fit-content',
|
|
||||||
height: 'fit-content',
|
|
||||||
classes: ['app-personnage-aleatoire'],
|
|
||||||
popOut: true,
|
|
||||||
resizable: true
|
|
||||||
}, { inplace: false })
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(actor) {
|
constructor(actor) {
|
||||||
super({})
|
super({})
|
||||||
this.actor = actor
|
this.actor = actor
|
||||||
@@ -106,18 +111,18 @@ export class AppPersonnageAleatoire extends FormApplication {
|
|||||||
this.checked = Object.fromEntries(CONTROLS.map(it => [it.name, [0, '', undefined].includes(this.current[it.name])]))
|
this.checked = Object.fromEntries(CONTROLS.map(it => [it.name, [0, '', undefined].includes(this.current[it.name])]))
|
||||||
}
|
}
|
||||||
|
|
||||||
async getData(options) {
|
_prepareContext() {
|
||||||
return foundry.utils.mergeObject(await super.getData(options), {
|
return {
|
||||||
actor: this.actor,
|
actor: this.actor,
|
||||||
current: this.current,
|
current: this.current,
|
||||||
checked: this.checked,
|
checked: this.checked,
|
||||||
options: { isGM: game.user.isGM }
|
options: { isGM: game.user.isGM }
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activateListeners(html) {
|
_onRender(context, options) {
|
||||||
super.activateListeners(html)
|
super._onRender(context, options)
|
||||||
this.html = html
|
this.html = $(this.element)
|
||||||
this.html.find("input.current-value").change(async event => await this.onChange(event))
|
this.html.find("input.current-value").change(async event => await this.onChange(event))
|
||||||
this.html.find("a.random").click(async event => await this.onRandom(event))
|
this.html.find("a.random").click(async event => await this.onRandom(event))
|
||||||
this.html.find("a.reset").click(async event => await this.onReset(event))
|
this.html.find("a.reset").click(async event => await this.onReset(event))
|
||||||
@@ -132,8 +137,6 @@ export class AppPersonnageAleatoire extends FormApplication {
|
|||||||
this.html.find("button.button-apply").click(async event => await this.onApply())
|
this.html.find("button.button-apply").click(async event => await this.onApply())
|
||||||
}
|
}
|
||||||
|
|
||||||
async _updateObject(event, formData) { }
|
|
||||||
|
|
||||||
async onApply() {
|
async onApply() {
|
||||||
const updates = Object.fromEntries(
|
const updates = Object.fromEntries(
|
||||||
CONTROLS.filter(control => game.user.isGM || control.name != 'name')
|
CONTROLS.filter(control => game.user.isGM || control.name != 'name')
|
||||||
@@ -154,14 +157,14 @@ export class AppPersonnageAleatoire extends FormApplication {
|
|||||||
|
|
||||||
async onSexe(sexe) {
|
async onSexe(sexe) {
|
||||||
this.current['sexe'] = sexe
|
this.current['sexe'] = sexe
|
||||||
this.render()
|
this.render({ force: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
async onChange(event) {
|
async onChange(event) {
|
||||||
const name = this.getName(event.currentTarget)
|
const name = this.getName(event.currentTarget)
|
||||||
const control = this.getControl(name)
|
const control = this.getControl(name)
|
||||||
this.current[control.name] = event.currentTarget.value
|
this.current[control.name] = event.currentTarget.value
|
||||||
this.render()
|
this.render({ force: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -169,20 +172,20 @@ export class AppPersonnageAleatoire extends FormApplication {
|
|||||||
const name = this.getName(event.currentTarget)
|
const name = this.getName(event.currentTarget)
|
||||||
const control = this.getControl(name)
|
const control = this.getControl(name)
|
||||||
await this.randomControl(control)
|
await this.randomControl(control)
|
||||||
this.render()
|
this.render({ force: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
async onReset(event) {
|
async onReset(event) {
|
||||||
const name = this.getName(event.currentTarget)
|
const name = this.getName(event.currentTarget)
|
||||||
const control = this.getControl(name)
|
const control = this.getControl(name)
|
||||||
this.current[control.name] = control.getter(this.actor)
|
this.current[control.name] = control.getter(this.actor)
|
||||||
await this.render()
|
this.render({ force: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
async onCheckForRandom(event) {
|
async onCheckForRandom(event) {
|
||||||
const name = this.getName(event.currentTarget)
|
const name = this.getName(event.currentTarget)
|
||||||
this.checked[name] = event.currentTarget.checked
|
this.checked[name] = event.currentTarget.checked
|
||||||
this.render()
|
this.render({ force: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
async onRandomizeSelected() {
|
async onRandomizeSelected() {
|
||||||
@@ -191,11 +194,10 @@ export class AppPersonnageAleatoire extends FormApplication {
|
|||||||
.toArray()
|
.toArray()
|
||||||
.map(it => this.getControl(it.attributes['data-field-name'].value))
|
.map(it => this.getControl(it.attributes['data-field-name'].value))
|
||||||
await Promise.all(controls.map(it => this.randomControl(it)))
|
await Promise.all(controls.map(it => this.randomControl(it)))
|
||||||
this.render()
|
this.render({ force: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
async randomControl(control) {
|
async randomControl(control) {
|
||||||
this.current[control.name] = await control.random(this.current)
|
this.current[control.name] = await control.random(this.actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,52 @@
|
|||||||
export { default as RdDItemBaseSheet} from "./common-item-sheet.mjs"
|
export { RdDBaseActorSheetV2 } from "./base-actor-sheet.mjs"
|
||||||
export { default as RdDMonnaieSheet } from "./monnaie-sheet.mjs"
|
export { RdDCreatureSheetV2 } from "./creature-sheet.mjs"
|
||||||
export { default as RdDMunitionSheet } from "./munition-sheet.mjs"
|
export { RdDActorVehiculeSheetV2 } from "./vehicule-sheet.mjs"
|
||||||
export { default as RdDTarotSheet } from "./tarot-sheet.mjs"
|
export { RdDCommerceSheetV2 } from "./commerce-sheet.mjs"
|
||||||
|
export { RdDActorEntiteSheetV2 } from "./entite-sheet.mjs"
|
||||||
|
export { RdDActorSheetV2 } from "./personnage-sheet.mjs"
|
||||||
|
export { RdDActorExportSheetV2 } from "./export-encart-sheet.mjs"
|
||||||
|
export { default as RdDItemBaseSheet} from "./common-item-sheet.mjs"
|
||||||
|
export { default as RdDMonnaieSheet } from "./monnaie-sheet.mjs"
|
||||||
|
export { default as RdDMunitionSheet } from "./munition-sheet.mjs"
|
||||||
|
export { default as RdDTarotSheet } from "./tarot-sheet.mjs"
|
||||||
|
export { default as RdDTeteSheet } from "./tete-sheet.mjs"
|
||||||
|
export { default as RdDQueueSheet } from "./queue-sheet.mjs"
|
||||||
|
export { default as RdDSouffleSheet } from "./souffle-sheet.mjs"
|
||||||
|
export { default as RdDOmbreSheet } from "./ombre-sheet.mjs"
|
||||||
|
export { default as RdDChantSheet } from "./chant-sheet.mjs"
|
||||||
|
export { default as RdDMusiqueSheet } from "./musique-sheet.mjs"
|
||||||
|
export { default as RdDDanseSheet } from "./danse-sheet.mjs"
|
||||||
|
export { default as RdDJeuSheet } from "./jeu-sheet.mjs"
|
||||||
|
export { default as RdDRecetteAlchimiqueSheet } from "./recettealchimique-sheet.mjs"
|
||||||
|
export { default as RdDRecetteCuisineSheet } from "./recettecuisine-sheet.mjs"
|
||||||
|
export { default as RdDArmeSheet } from "./arme-sheet.mjs"
|
||||||
|
export { default as RdDArmureSheet } from "./armure-sheet.mjs"
|
||||||
|
export { default as RdDObjetSheet } from "./objet-sheet.mjs"
|
||||||
|
export { default as RdDConteneurSheet } from "./conteneur-sheet.mjs"
|
||||||
|
export { default as RdDNourritureBoissonSheet } from "./nourritureboisson-sheet.mjs"
|
||||||
|
export { default as RdDGemmeSheet } from "./gemme-sheet.mjs"
|
||||||
|
export { default as RdDServiceSheet } from "./service-sheet.mjs"
|
||||||
|
export { default as RdDTacheSheet } from "./tache-sheet.mjs"
|
||||||
|
export { default as RdDBlessureSheet } from "./blessure-sheet.mjs"
|
||||||
|
export { default as RdDMaladieSheet } from "./maladie-sheet.mjs"
|
||||||
|
export { default as RdDPoisonSheet } from "./poison-sheet.mjs"
|
||||||
|
export { default as RdDCompetenceSheet } from "./competence-sheet.mjs"
|
||||||
|
export { default as RdDCompetenceCreatureSheet } from "./competencecreature-sheet.mjs"
|
||||||
|
export { default as RdDPotionSheet } from "./potion-sheet.mjs"
|
||||||
|
export { default as RdDSigneDraconiqueSheet } from "./signedraconique-sheet.mjs"
|
||||||
|
export { default as RdDSortSheet } from "./sort-sheet.mjs"
|
||||||
|
export { default as RdDRaceSheet } from "./race-sheet.mjs"
|
||||||
|
export { default as RdDRencontreSheet } from "./rencontre-sheet.mjs"
|
||||||
|
export { default as RdDEmpoignadeSheet } from "./empoignade-sheet.mjs"
|
||||||
|
export { default as RdDPossessionSheet } from "./possession-sheet.mjs"
|
||||||
|
export { default as RdDLivreSheet } from "./livre-sheet.mjs"
|
||||||
|
export { default as RdDFauneSheet } from "./faune-sheet.mjs"
|
||||||
|
export { default as RdDHerbeSheet } from "./herbe-sheet.mjs"
|
||||||
|
export { default as RdDPlanteSheet } from "./plante-sheet.mjs"
|
||||||
|
export { default as RdDIngredientSheet } from "./ingredient-sheet.mjs"
|
||||||
|
export { default as RdDExtraitPoetiqueSheet } from "./extraitpoetique-sheet.mjs"
|
||||||
|
export { default as RdDNombreAstralSheet } from "./nombreastral-sheet.mjs"
|
||||||
|
export { default as RdDCaseTMRSheet } from "./casetmr-sheet.mjs"
|
||||||
|
export { default as RdDSortReserveSheet } from "./sortreserve-sheet.mjs"
|
||||||
|
export { default as RdDMeditationSheet } from "./meditation-sheet.mjs"
|
||||||
|
export { default as RdDOeuvreSheet } from "./oeuvre-sheet.mjs"
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES, ACTOR_TYPES } from "../../constants.js";
|
||||||
|
import { SystemCompendiums } from "../../settings/system-compendiums.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDArmeSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.arme; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE]; }
|
||||||
|
|
||||||
|
static MORTALITE_CHOICES = {
|
||||||
|
mortel: "Mortel",
|
||||||
|
"non-mortel": "Non mortel",
|
||||||
|
empoignade: "Empoignade",
|
||||||
|
}
|
||||||
|
|
||||||
|
static CATEGORIE_PARADE_CHOICES = {
|
||||||
|
"sans-armes": "Sans arme",
|
||||||
|
"armes-naturelles": "Armes naturelles",
|
||||||
|
hast: "Armes d'hast",
|
||||||
|
batons: "Bâtons",
|
||||||
|
boucliers: "Boucliers",
|
||||||
|
dagues: "Dagues",
|
||||||
|
"epees-courtes": "Epées courtes",
|
||||||
|
"epees-longues": "Epées longues",
|
||||||
|
"epees-lourdes": "Epées lourdes",
|
||||||
|
haches: "Haches",
|
||||||
|
lances: "Lances",
|
||||||
|
masses: "Masses",
|
||||||
|
}
|
||||||
|
|
||||||
|
static INIT_CHOICES = {
|
||||||
|
hast: "Armes Hast",
|
||||||
|
lance: "Lance",
|
||||||
|
baton: "Bâton",
|
||||||
|
doubledragonne: "Double Dragonne",
|
||||||
|
esparlongue: "Esparlongue",
|
||||||
|
epeedragonne: "Epée Dragonne",
|
||||||
|
epeebatarde: "Epée Bâtarde",
|
||||||
|
epeecyane: "Epée Cyane",
|
||||||
|
epeesorde: "Epée Sorde",
|
||||||
|
grandehache: "Grande Hache",
|
||||||
|
hachebataille: "Hache de Bataille",
|
||||||
|
epeegnome: "Epée Gnome",
|
||||||
|
masse: "Masse",
|
||||||
|
gourdin: "Gourdin",
|
||||||
|
fleau: "Fléaux",
|
||||||
|
dague: "Dague",
|
||||||
|
armenaturelle: "Armes Naturelles",
|
||||||
|
autre: "Autres",
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "arme"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["arme-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/arme.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const competences = (await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage))
|
||||||
|
.filter(it => it.isCompetenceArme())
|
||||||
|
const competenceMeleeChoices = {}
|
||||||
|
const competenceLancerChoices = {}
|
||||||
|
const competenceTirChoices = {}
|
||||||
|
competences.forEach(c => {
|
||||||
|
const label = c.name
|
||||||
|
switch (c.system.categorie) {
|
||||||
|
case 'melee': competenceMeleeChoices[label] = label; break
|
||||||
|
case 'lancer': competenceLancerChoices[label] = label; break
|
||||||
|
case 'tir': competenceTirChoices[label] = label; break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return Object.assign(
|
||||||
|
await super._prepareContext(),
|
||||||
|
{
|
||||||
|
competenceMeleeChoices,
|
||||||
|
competenceLancerChoices,
|
||||||
|
competenceTirChoices,
|
||||||
|
mortaliteChoices: RdDArmeSheet.MORTALITE_CHOICES,
|
||||||
|
categorieParadeChoices: RdDArmeSheet.CATEGORIE_PARADE_CHOICES,
|
||||||
|
initChoices: RdDArmeSheet.INIT_CHOICES,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDArmureSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.armure; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "armure"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["armure-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/armure.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,460 @@
|
|||||||
|
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||||
|
|
||||||
|
import { RdDUtility } from "../../rdd-utility.js"
|
||||||
|
import { Misc } from "../../misc.js"
|
||||||
|
import { DialogSplitItem } from "../../dialog-split-item.js"
|
||||||
|
import { RdDSheetUtility } from "../../rdd-sheet-utility.js"
|
||||||
|
import { Monnaie } from "../../item-monnaie.js"
|
||||||
|
import { ITEM_TYPES } from "../../constants.js"
|
||||||
|
import { RdDItem } from "../../item.js"
|
||||||
|
import { RdDTextEditor } from "../../apps/rdd-text-roll-editor.js"
|
||||||
|
import { ItemAction } from "../../item/item-actions.js"
|
||||||
|
import { DialogVerifierIngredients } from "../../dialog-verifier-ingredients.js"
|
||||||
|
import { DialogLancerRecette } from "../../dialog-lancer-recette.js"
|
||||||
|
import { ChatUtility } from "../../chat-utility.js"
|
||||||
|
import { RdDItemBlessure } from "../../item/blessure.js"
|
||||||
|
import { Grammar } from "../../grammar.js"
|
||||||
|
import { SYSTEM_RDD } from "../../constants.js"
|
||||||
|
|
||||||
|
export class RdDBaseActorSheetV2 extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
||||||
|
|
||||||
|
get actor() { return this.document }
|
||||||
|
|
||||||
|
// Was this.options.* — custom state
|
||||||
|
vueDetaillee = false
|
||||||
|
triEquipement = "name"
|
||||||
|
recherche = undefined
|
||||||
|
|
||||||
|
static TYPE = undefined
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ["rdd", "sheet", "actor"],
|
||||||
|
position: { width: 640 },
|
||||||
|
form: { submitOnChange: true, closeOnSubmit: false },
|
||||||
|
window: { resizable: true, controls: [] },
|
||||||
|
actions: {
|
||||||
|
postToChat: RdDBaseActorSheetV2._onPostToChat,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region Registration
|
||||||
|
|
||||||
|
static register() {
|
||||||
|
foundry.documents.collections.Actors.registerSheet(SYSTEM_RDD, this, {
|
||||||
|
types: [this.TYPE],
|
||||||
|
makeDefault: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static async registerAll(...sheetClasses) {
|
||||||
|
const handlebars = []
|
||||||
|
sheetClasses.forEach(sheetClass => {
|
||||||
|
if (sheetClass.PARTS) {
|
||||||
|
Object.values(sheetClass.PARTS).forEach(part => {
|
||||||
|
if (part.template) handlebars.push(part.template)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sheetClass.register()
|
||||||
|
})
|
||||||
|
await foundry.applications.handlebars.loadTemplates(Misc.distinct(handlebars))
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Data
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
Monnaie.validerMonnaies(this.actor)
|
||||||
|
this.actor.computeEtatGeneral()
|
||||||
|
|
||||||
|
this._sheetOptions = foundry.utils.mergeObject(
|
||||||
|
RdDSheetUtility.mergeDocumentRights({ ...this.options }, this.actor, this.isEditable),
|
||||||
|
{ vueDetaillee: this.vueDetaillee, triEquipement: this.triEquipement, recherche: this.recherche },
|
||||||
|
{ inplace: false }
|
||||||
|
)
|
||||||
|
const ctx = {
|
||||||
|
title: this.title,
|
||||||
|
id: this.actor.id,
|
||||||
|
type: this.actor.type,
|
||||||
|
img: this.actor.img,
|
||||||
|
name: this.actor.name,
|
||||||
|
system: this.actor.system,
|
||||||
|
systemFields: this.actor.system.schema.fields,
|
||||||
|
description: await RdDTextEditor.enrichHTML(this.actor.system.description, this.actor),
|
||||||
|
notesmj: await RdDTextEditor.enrichHTML(this.actor.system.notesmj, this.actor),
|
||||||
|
options: this._sheetOptions,
|
||||||
|
effects: this.actor.effects,
|
||||||
|
editable: this.isEditable,
|
||||||
|
cssClass: this.isEditable ? "editable" : "locked",
|
||||||
|
limited: this.actor.limited,
|
||||||
|
owner: this.actor.isOwner,
|
||||||
|
}
|
||||||
|
|
||||||
|
RdDUtility.filterItemsPerTypeForSheet(ctx, this.actor.itemTypes, this.triEquipement)
|
||||||
|
ctx.calc = {
|
||||||
|
fortune: Monnaie.toSolsDeniers(this.actor.getFortune()),
|
||||||
|
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
||||||
|
encTotal: this.actor.getEncTotal(),
|
||||||
|
}
|
||||||
|
|
||||||
|
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(ctx.conteneurs, ctx.inventaires)
|
||||||
|
this._appliquerRechercheObjets(ctx.conteneurs, ctx.inventaires)
|
||||||
|
ctx.conteneurs = RdDUtility.conteneursRacine(ctx.conteneurs)
|
||||||
|
ctx.competences.filter(it => it.type == ITEM_TYPES.competencecreature)
|
||||||
|
.forEach(it => it.isdommages = it.isDommages())
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
_appliquerRechercheObjets(conteneurs, inventaires) {
|
||||||
|
if (this.recherche?.text) {
|
||||||
|
const recherche = this.recherche
|
||||||
|
const allVisible = inventaires.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id)
|
||||||
|
let addVisible = conteneurs.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id)
|
||||||
|
do {
|
||||||
|
allVisible.push(...addVisible)
|
||||||
|
const parentsIds = conteneurs.filter(it => it.system.contenu.find(id => allVisible.includes(id))).map(it => it.id)
|
||||||
|
addVisible = parentsIds.filter(id => !allVisible.includes(id))
|
||||||
|
}
|
||||||
|
while (addVisible.length > 0)
|
||||||
|
inventaires.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
||||||
|
conteneurs.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inventaires.forEach(it => it.system.isHidden = false)
|
||||||
|
conteneurs.forEach(it => it.system.isHidden = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Rendering
|
||||||
|
|
||||||
|
async _renderFrame(options) {
|
||||||
|
const frame = await super._renderFrame(options)
|
||||||
|
return frame
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options)
|
||||||
|
this.html = $(this.element)
|
||||||
|
|
||||||
|
const nav = this.element.querySelector(".sheet-tabs")
|
||||||
|
if (nav) {
|
||||||
|
const tab = this.tabGroups?.primary || nav.querySelector("[data-tab]")?.dataset.tab
|
||||||
|
if (tab) this.changeTab(tab, "primary", { force: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
this.html.find(".actionItem").click(async event => await ItemAction.onActionItem(event, this.actor, this._sheetOptions))
|
||||||
|
this.html.find(".item-edit").click(async event => await this._onItemEdit(event))
|
||||||
|
this.html.find(".item-verify-ingredients").click(async event => await this._onVerifyIngredients(event))
|
||||||
|
this.html.find(".item-lancer-recette").click(async event => await this._onLancerRecette(event))
|
||||||
|
this.html.find(".conteneur-name a").click(async event => {
|
||||||
|
RdDUtility.toggleAfficheContenu(this._getItemId(event))
|
||||||
|
this.render({ force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
this.html.find(".actor-montrer").click(async event => await this.actor.postActorToChat())
|
||||||
|
|
||||||
|
this.html.find(".recherche")
|
||||||
|
.each((_index, field) => this._rechercheSelectArea(field))
|
||||||
|
.keyup(async event => this._rechercherKeyup(event))
|
||||||
|
.change(async event => this._rechercherKeyup(event))
|
||||||
|
|
||||||
|
this.html.find(".recherche").prop("disabled", false)
|
||||||
|
|
||||||
|
this.html.find(".item-list .item").dblclick(async event => {
|
||||||
|
const item = this._getItem(event)
|
||||||
|
if (item) item.sheet.render({ force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
this.html.find(".tri-equipement").change(event => {
|
||||||
|
this.triEquipement = event.currentTarget.value
|
||||||
|
this.render({ force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!this.isEditable) return
|
||||||
|
|
||||||
|
this.html.find(".item-equip-armure").click(async event => await this.actor.equiperObjet(this._getItem(event)))
|
||||||
|
this.html.find(".item-delete").click(async event => await RdDUtility.confirmActorItemDelete(this._getItem(event), this.actor))
|
||||||
|
this.html.find(".item-quantite-plus").click(async event => await this.actor.itemQuantiteIncDec(this._getItemId(event), 1))
|
||||||
|
this.html.find(".item-quantite-moins").click(async event => await this.actor.itemQuantiteIncDec(this._getItemId(event), -1))
|
||||||
|
this.html.find(".item-quantite").change(async event => {
|
||||||
|
const input = event.currentTarget
|
||||||
|
const item = this.actor.items.get(input.dataset.itemId)
|
||||||
|
if (item) {
|
||||||
|
const newQty = Math.max(0, parseInt(input.value) || 0)
|
||||||
|
await item.update({ "system.quantite": newQty })
|
||||||
|
if (newQty === 0) this.render({ force: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.html.find(".item-quantite").on("contextmenu", async event => {
|
||||||
|
event.preventDefault()
|
||||||
|
const item = this._getItem(event)
|
||||||
|
if (!item?.isInventaire()) return
|
||||||
|
new foundry.applications.api.DialogV2({
|
||||||
|
title: `Quantité — ${item.name}`,
|
||||||
|
content: `<p>Réduire la quantité de :</p>
|
||||||
|
<select class="qty-amount">
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="5">5</option>
|
||||||
|
<option value="10">10</option>
|
||||||
|
<option value="all">Tout jeter</option>
|
||||||
|
</select>`,
|
||||||
|
buttons: [
|
||||||
|
{ action: "reduce", label: "Retirer", icon: "fa-solid fa-minus", callback: (event, button, dialog) => {
|
||||||
|
const amount = dialog.element.querySelector(".qty-amount").value
|
||||||
|
if (amount === "all") {
|
||||||
|
item.delete()
|
||||||
|
this.render({ force: true })
|
||||||
|
} else {
|
||||||
|
item.update({ "system.quantite": Math.max(0, item.system.quantite - parseInt(amount)) })
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
],
|
||||||
|
}).render({ force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
this.html.find(".creer-un-objet").click(async event => await this._selectObjetTypeToCreate())
|
||||||
|
this.html.find(".nettoyer-conteneurs").click(async event => await this.actor.nettoyerConteneurs())
|
||||||
|
this.html.find(".quick-add-ration").click(async event => {
|
||||||
|
const existante = this.actor.items.find(it => it.type === "nourritureboisson" && it.name === "Ration")
|
||||||
|
if (existante) {
|
||||||
|
await existante.update({ "system.quantite": Math.max(0, Number(existante.system.quantite) + 1) })
|
||||||
|
} else {
|
||||||
|
await this.actor.createEmbeddedDocuments("Item", [{
|
||||||
|
name: "Ration", type: "nourritureboisson",
|
||||||
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
|
||||||
|
system: { sust: 1, encombrement: 0.1, quantite: 1, cout: 0.1, boisson: false },
|
||||||
|
}], { renderSheet: false })
|
||||||
|
}
|
||||||
|
this.render({ force: true })
|
||||||
|
})
|
||||||
|
this.html.find(".quick-add-eau").click(async event => {
|
||||||
|
const existante = this.actor.items.find(it => it.type === "nourritureboisson" && it.name === "Eau")
|
||||||
|
if (existante) {
|
||||||
|
await existante.update({ "system.quantite": Math.max(0, Number(existante.system.quantite) + 1) })
|
||||||
|
} else {
|
||||||
|
await this.actor.createEmbeddedDocuments("Item", [{
|
||||||
|
name: "Eau", type: "nourritureboisson",
|
||||||
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/outre.webp",
|
||||||
|
system: { desaltere: 1, encombrement: 0.1, quantite: 1, cout: 0.05, boisson: true },
|
||||||
|
}], { renderSheet: false })
|
||||||
|
}
|
||||||
|
this.render({ force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
this.html.find(".vue-detaillee").click(async event => {
|
||||||
|
this.vueDetaillee = !this.vueDetaillee
|
||||||
|
this.render({ force: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
// Revel listeners (was base-actor-reve-sheet.js)
|
||||||
|
this.html.find(".button-encaissement").click(async event => await this.actor.encaisser())
|
||||||
|
this.html.find(".roll-carac").click(async event => {
|
||||||
|
await this.actor.rollCarac(Grammar.toLowerCaseNoAccent(event.currentTarget.attributes["data-carac-name"].value))
|
||||||
|
})
|
||||||
|
this.html.find(".roll-competence").click(async event => await this.actor.rollCompetence(this._getItemId(event)))
|
||||||
|
this.html.find(".endurance-plus").click(async event => await this.actor.santeIncDec("endurance", 1))
|
||||||
|
this.html.find(".endurance-moins").click(async event => await this.actor.santeIncDec("endurance", -1))
|
||||||
|
|
||||||
|
if (game.user.isGM) {
|
||||||
|
this.html.find(".button-remise-a-neuf").click(async event => await this.actor.remiseANeuf())
|
||||||
|
this.html.find(".delete-active-effect").click(async event => await this.actor.removeEffect(this.html.find(event.currentTarget).parents(".active-effect").data("effect")))
|
||||||
|
this.html.find(".enlever-tous-effets").click(async event => await this.actor.removeEffects())
|
||||||
|
}
|
||||||
|
this.html.find(".competence-add").click(async event =>
|
||||||
|
await this.actor.createEmbeddedDocuments("Item", [{
|
||||||
|
type: ITEM_TYPES.competencecreature,
|
||||||
|
name: "Nouvelle competence",
|
||||||
|
img: "systems/foundryvtt-reve-de-dragon/icons/compcreature-serres.webp",
|
||||||
|
system: { carac_value: this.actor.getForce() },
|
||||||
|
}], { renderSheet: true })
|
||||||
|
)
|
||||||
|
this.html.find(".roll-text").click(async event => await RdDTextEditor.rollText(event, this.actor))
|
||||||
|
this.html.find(".chat-roll-text").click(async event => await RdDTextEditor.chatRollText(event))
|
||||||
|
|
||||||
|
if (this.vueDetaillee) {
|
||||||
|
this.html.find(".carac-value").change(async event => {
|
||||||
|
if (event.currentTarget.name.includes("carac.")) {
|
||||||
|
const caracName = event.currentTarget.name.replace("carac.", "")
|
||||||
|
await this.actor.updateCarac(caracName, parseInt(event.currentTarget.value))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.html.find(".competence-value").change(async event => {
|
||||||
|
const compName = event.currentTarget.attributes.compname.value
|
||||||
|
await this.actor.updateCompetence(compName, parseInt(event.currentTarget.value))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sang listeners (was base-actor-sang-sheet.js)
|
||||||
|
this.html.find(".creer-blessure-legere").click(async event => await RdDItemBlessure.createBlessure(this.actor, 2))
|
||||||
|
this.html.find(".creer-blessure-grave").click(async event => await RdDItemBlessure.createBlessure(this.actor, 4))
|
||||||
|
this.html.find(".creer-blessure-critique").click(async event => await RdDItemBlessure.createBlessure(this.actor, 6))
|
||||||
|
this.html.find(".subir-blessure-contusion").click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 0))
|
||||||
|
this.html.find(".subir-blessure-legere").click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 2))
|
||||||
|
this.html.find(".subir-blessure-grave").click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 4))
|
||||||
|
this.html.find(".subir-blessure-critique").click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 6))
|
||||||
|
this.html.find(".jet-vie").click(async event => await this.actor.jetDeVie())
|
||||||
|
this.html.find(".jet-endurance").click(async event => await this._jetEndurance())
|
||||||
|
this.html.find(".vie-plus").click(async event => await this.actor.santeIncDec("vie", 1))
|
||||||
|
this.html.find(".vie-moins").click(async event => await this.actor.santeIncDec("vie", -1))
|
||||||
|
}
|
||||||
|
|
||||||
|
async _jetEndurance() {
|
||||||
|
const endurance = this.actor.getEnduranceActuelle()
|
||||||
|
const result = await this.actor.jetEndurance(endurance)
|
||||||
|
await ChatMessage.create({
|
||||||
|
content: `Jet d'Endurance : ${result.jetEndurance} / ${endurance}
|
||||||
|
<br>${this.actor.name} a ${result.sonne ? "échoué" : "réussi"} son Jet d'Endurance ${result.sonne ? "et devient Sonné" : ""}`,
|
||||||
|
whisper: ChatUtility.getOwners(this.actor),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_rechercherKeyup(event) {
|
||||||
|
const currentTarget = event.currentTarget
|
||||||
|
const nouvelleRecherche = this._optionRecherche(currentTarget)
|
||||||
|
if (this.recherche?.text != nouvelleRecherche?.text) {
|
||||||
|
this.recherche = nouvelleRecherche
|
||||||
|
if (this._timerRecherche) clearTimeout(this._timerRecherche)
|
||||||
|
this._timerRecherche = setTimeout(() => {
|
||||||
|
this._timerRecherche = undefined
|
||||||
|
this.render({ force: true })
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_rechercheSelectArea(field) {
|
||||||
|
if (this.recherche) {
|
||||||
|
field.focus()
|
||||||
|
field.setSelectionRange(this.recherche.start, this.recherche.end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_optionRecherche(target) {
|
||||||
|
if (!target.value?.length) return undefined
|
||||||
|
return {
|
||||||
|
text: target.value,
|
||||||
|
start: target.selectionStart,
|
||||||
|
end: target.selectionEnd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Drop
|
||||||
|
|
||||||
|
async _onDropItem(event, item) {
|
||||||
|
const destItemId = this.html.find(event.target)?.closest(".item").attr("data-item-id")
|
||||||
|
const previousItemIds = new Set(this.actor.items.keys())
|
||||||
|
const dropParams = await RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, { uuid: item.uuid }, this.objetVersConteneur)
|
||||||
|
if (dropParams) {
|
||||||
|
const callSuper = await this.actor.processDropItem(dropParams)
|
||||||
|
if (callSuper) {
|
||||||
|
await super._onDropItem(event, item)
|
||||||
|
}
|
||||||
|
if (destItemId && dropParams.sourceActorId !== this.actor.id) {
|
||||||
|
const container = this.actor.items.get(destItemId)
|
||||||
|
if (container?.isConteneur()) {
|
||||||
|
const dropped = [...this.actor.items].find(i => !previousItemIds.has(i.id))
|
||||||
|
if (dropped && !this.actor.findConteneur(dropped)) {
|
||||||
|
await this.actor.ajouterDansConteneur(dropped, container, () => {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onDropActor(event, actor) {
|
||||||
|
this.actor.addSubActeur(actor)
|
||||||
|
await super._onDropActor(event, actor)
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Helpers
|
||||||
|
|
||||||
|
_getItemId(event) {
|
||||||
|
return RdDSheetUtility.getItemId(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
_getItem(event) {
|
||||||
|
return RdDSheetUtility.getItem(event, this.actor)
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onItemEdit(event) {
|
||||||
|
const item = this._getItem(event)
|
||||||
|
if (item) item.sheet.render({ force: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onVerifyIngredients(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const item = this._getItem(event)
|
||||||
|
if (!item || item.type !== ITEM_TYPES.recettealchimique) return
|
||||||
|
DialogVerifierIngredients.create(item, this.actor)
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onLancerRecette(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
const item = this._getItem(event)
|
||||||
|
if (!item || item.type !== ITEM_TYPES.recettealchimique) return
|
||||||
|
const ingredients = Misc.safeJsonParse(item.system.ingredients, [])
|
||||||
|
if (!ingredients.length) {
|
||||||
|
ui.notifications.warn("Cette recette n'a pas d'ingrédients définis.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
DialogLancerRecette.create(item, this.actor)
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Actions
|
||||||
|
|
||||||
|
static async _onPostToChat(event, target) {
|
||||||
|
await this.actor.postActorToChat()
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Item operations
|
||||||
|
|
||||||
|
async _selectObjetTypeToCreate() {
|
||||||
|
const types = this._getTypesInventaire().sort(Misc.ascending(type => Misc.typeName("Item", type)))
|
||||||
|
let content = `<span class="generic-label">Selectionnez le type d'équipement</span><select class="item-type">`
|
||||||
|
for (const typeName of types) {
|
||||||
|
content += `<option value="${typeName}">${Misc.typeName("Item", typeName)}</option>`
|
||||||
|
}
|
||||||
|
content += "</select>"
|
||||||
|
new foundry.applications.api.DialogV2({
|
||||||
|
title: "Créer un équipement",
|
||||||
|
content,
|
||||||
|
buttons: [
|
||||||
|
{ action: "create", label: "Créer l'objet", icon: "fa-solid fa-check", callback: () => this.actor.createItem($(".item-type").val()) },
|
||||||
|
],
|
||||||
|
}).render({ force: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
_getTypesInventaire() {
|
||||||
|
return RdDItem.getItemTypesInventaire()
|
||||||
|
}
|
||||||
|
|
||||||
|
async splitItem(item) {
|
||||||
|
const dialog = await DialogSplitItem.create(item, (it, split) => this._onSplitItem(it, split))
|
||||||
|
dialog.render({ force: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onSplitItem(item, split) {
|
||||||
|
if (split >= 1 && split < item.system.quantite) {
|
||||||
|
await item.diminuerQuantite(split)
|
||||||
|
const splitItem = foundry.utils.deepClone(item)
|
||||||
|
splitItem.system.quantite = split
|
||||||
|
await this.actor.createEmbeddedDocuments("Item", [splitItem])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vendre(item) {
|
||||||
|
item?.proposerVente(this.actor.getQuantiteDisponible(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDBlessureSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.blessure; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{ classes: ["fvtt-rdd", "item", "blessure"], position: { width: 448 }, window: { contentClasses: ["blessure-content"] } });
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/blessure.hbs" },
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDCaseTMRSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.casetmr; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "casetmr"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["casetmr-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/casetmr.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
import { CommonAppreciable } from "../../common/appreciable.mjs";
|
||||||
|
|
||||||
|
const TEMPLATE_APPRECIABLE = new CommonAppreciable();
|
||||||
|
|
||||||
|
export default class RdDChantSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.chant; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_APPRECIABLE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "chant"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["chant-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/chant.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { RdDBaseActorSheetV2 } from "./base-actor-sheet.mjs"
|
||||||
|
import { RdDItem } from "../../item.js"
|
||||||
|
import { ACTOR_TYPES } from "../../constants.js"
|
||||||
|
|
||||||
|
export class RdDCommerceSheetV2 extends RdDBaseActorSheetV2 {
|
||||||
|
|
||||||
|
static TYPE = ACTOR_TYPES.commerce
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({}, RdDBaseActorSheetV2.DEFAULT_OPTIONS, {
|
||||||
|
position: { width: 600, height: 720 },
|
||||||
|
})
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
form: { template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
get title() {
|
||||||
|
if (this.actor.token && this.actor.token !== this.actor.prototypeToken) {
|
||||||
|
return this.actor.token.name
|
||||||
|
}
|
||||||
|
return super.title
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const ctx = await super._prepareContext()
|
||||||
|
if (this.actor.token && this.actor.token !== this.actor.prototypeToken) {
|
||||||
|
foundry.utils.mergeObject(ctx, {
|
||||||
|
title: this.actor.token.name,
|
||||||
|
token: { img: this.actor.token.texture.src },
|
||||||
|
}, { overwrite: true })
|
||||||
|
}
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options)
|
||||||
|
if (!this.isEditable) return
|
||||||
|
|
||||||
|
this.html.find("input.item-quantite").change(async event => {
|
||||||
|
const newQuantite = Math.max(0, Number.parseInt(this.html.find(event.currentTarget).val()))
|
||||||
|
await this._getItem(event)?.update({ "system.quantite": newQuantite })
|
||||||
|
})
|
||||||
|
this.html.find("input.item-cout").change(async event => {
|
||||||
|
const newCout = Math.max(0, Number(this.html.find(event.currentTarget).val()))
|
||||||
|
await this._getItem(event)?.update({ "system.cout": newCout })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_getTypesInventaire() {
|
||||||
|
return RdDItem.getItemTypesInventaire("all")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ export default class RdDItemBaseSheet extends HandlebarsApplicationMixin(foundry
|
|||||||
|
|
||||||
static register(sheetClass) {
|
static register(sheetClass) {
|
||||||
const itemType = sheetClass.ITEM_TYPE
|
const itemType = sheetClass.ITEM_TYPE
|
||||||
Items.registerSheet(SYSTEM_RDD, sheetClass, {
|
foundry.documents.collections.Items.registerSheet(SYSTEM_RDD, sheetClass, {
|
||||||
label: Misc.typeName('Item', itemType),
|
label: Misc.typeName('Item', itemType),
|
||||||
types: [itemType],
|
types: [itemType],
|
||||||
makeDefault: true
|
makeDefault: true
|
||||||
@@ -63,13 +63,15 @@ export default class RdDItemBaseSheet extends HandlebarsApplicationMixin(foundry
|
|||||||
resizable: true,
|
resizable: true,
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
editImage: RdDItemBaseSheet.#onEditImage,
|
editImage: RdDItemBaseSheet._onEditImage,
|
||||||
|
postToChat: RdDItemBaseSheet._onPostToChat,
|
||||||
|
proposerVente: RdDItemBaseSheet._onProposerVente,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async _prepareContext() {
|
async _prepareContext() {
|
||||||
return {
|
const ctx = {
|
||||||
item: this.document,
|
item: this.document,
|
||||||
options: RdDSheetUtility.getOptions(this.document, this.isEditable),
|
options: RdDSheetUtility.getOptions(this.document, this.isEditable),
|
||||||
fields: this.document.schema.fields,
|
fields: this.document.schema.fields,
|
||||||
@@ -77,7 +79,12 @@ export default class RdDItemBaseSheet extends HandlebarsApplicationMixin(foundry
|
|||||||
system: this.document.system,
|
system: this.document.system,
|
||||||
source: this.document.toObject(),
|
source: this.document.toObject(),
|
||||||
isEditable: this.isEditable,
|
isEditable: this.isEditable,
|
||||||
|
canVendre: this.document.isInventaire?.() && this.document.isVideOuNonConteneur?.(),
|
||||||
}
|
}
|
||||||
|
for (const tpl of this.constructor.TEMPLATES) {
|
||||||
|
Object.assign(ctx, await tpl.prepareContext(this.document))
|
||||||
|
}
|
||||||
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// #region Actions
|
// #region Actions
|
||||||
@@ -91,7 +98,7 @@ export default class RdDItemBaseSheet extends HandlebarsApplicationMixin(foundry
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
static async #onEditImage(event, target) {
|
static async _onEditImage(event, target) {
|
||||||
const attr = target.dataset.edit
|
const attr = target.dataset.edit
|
||||||
const current = foundry.utils.getProperty(this.document, attr)
|
const current = foundry.utils.getProperty(this.document, attr)
|
||||||
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}
|
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}
|
||||||
@@ -107,5 +114,40 @@ export default class RdDItemBaseSheet extends HandlebarsApplicationMixin(foundry
|
|||||||
})
|
})
|
||||||
return fp.browse()
|
return fp.browse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async _onPostToChat(event, target) {
|
||||||
|
await this.document.postItemToChat()
|
||||||
|
}
|
||||||
|
|
||||||
|
static async _onProposerVente(event, target) {
|
||||||
|
await this.document.proposerVente(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _renderFrame(options) {
|
||||||
|
const frame = await super._renderFrame(options)
|
||||||
|
const header = frame.querySelector(".window-header")
|
||||||
|
if (header) {
|
||||||
|
const closeBtn = header.querySelector("button[data-action=close]")
|
||||||
|
const chatBtn = document.createElement("button")
|
||||||
|
chatBtn.type = "button"
|
||||||
|
chatBtn.className = "header-control icon fa-solid fa-comment"
|
||||||
|
chatBtn.dataset.action = "postToChat"
|
||||||
|
chatBtn.dataset.tooltip = "Poster dans le chat"
|
||||||
|
chatBtn.ariaLabel = "Poster dans le chat"
|
||||||
|
header.insertBefore(chatBtn, closeBtn)
|
||||||
|
if (this.document.isInventaire?.() && this.document.isVideOuNonConteneur?.()) {
|
||||||
|
const sellBtn = document.createElement("button")
|
||||||
|
sellBtn.type = "button"
|
||||||
|
sellBtn.className = "header-control icon fa-solid fa-comments-dollar"
|
||||||
|
sellBtn.dataset.action = "proposerVente"
|
||||||
|
sellBtn.dataset.tooltip = "Proposer à la vente"
|
||||||
|
sellBtn.ariaLabel = "Proposer à la vente"
|
||||||
|
header.insertBefore(sellBtn, chatBtn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return frame
|
||||||
|
}
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDCompetenceSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.competence; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{ classes: ["fvtt-rdd", "item", "competence"], position: { width: 448 }, window: { contentClasses: ["competence-content"] } });
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/competence.hbs" },
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDCompetenceCreatureSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.competencecreature; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{ classes: ["fvtt-rdd", "item", "competencecreature"], position: { width: 448 }, window: { contentClasses: ["competencecreature-content"] } });
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/competencecreature.hbs" },
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDConteneurSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.conteneur; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "conteneur"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["conteneur-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/conteneur.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
return Object.assign(
|
||||||
|
await super._prepareContext(),
|
||||||
|
{
|
||||||
|
actorId: this.document.parent?.id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { RdDBaseActorSheetV2 } from "./base-actor-sheet.mjs"
|
||||||
|
import { ACTOR_TYPES } from "../../constants.js"
|
||||||
|
|
||||||
|
export class RdDCreatureSheetV2 extends RdDBaseActorSheetV2 {
|
||||||
|
|
||||||
|
static TYPE = ACTOR_TYPES.creature
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({}, RdDBaseActorSheetV2.DEFAULT_OPTIONS, {
|
||||||
|
position: { width: 640, height: 720 },
|
||||||
|
})
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
form: { template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options)
|
||||||
|
if (!this.isEditable) return
|
||||||
|
|
||||||
|
this.html.find(".creature-carac").change(async event => {
|
||||||
|
const compName = event.currentTarget.attributes.compname.value
|
||||||
|
await this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value))
|
||||||
|
})
|
||||||
|
this.html.find(".creature-niveau").change(async event => {
|
||||||
|
const compName = event.currentTarget.attributes.compname.value
|
||||||
|
await this.actor.updateCreatureCompetence(compName, "niveau", parseInt(event.target.value))
|
||||||
|
})
|
||||||
|
this.html.find(".creature-dommages").change(async event => {
|
||||||
|
const compName = event.currentTarget.attributes.compname.value
|
||||||
|
await this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
import { CommonAppreciable } from "../../common/appreciable.mjs";
|
||||||
|
|
||||||
|
const TEMPLATE_APPRECIABLE = new CommonAppreciable();
|
||||||
|
|
||||||
|
export default class RdDDanseSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.danse; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_APPRECIABLE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "danse"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["danse-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/danse.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
return Object.assign(
|
||||||
|
await super._prepareContext(),
|
||||||
|
{
|
||||||
|
typeChoices: { recreative: "Récreative", soliste: "Soliste" },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDEmpoignadeSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.empoignade; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{ classes: ["fvtt-rdd", "item", "empoignade"], position: { width: 448 }, window: { contentClasses: ["empoignade-content"] } });
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/empoignade.hbs" },
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import { RdDBaseActorSheetV2 } from "./base-actor-sheet.mjs"
|
||||||
|
import { RdDSheetUtility } from "../../rdd-sheet-utility.js"
|
||||||
|
import { RdDUtility } from "../../rdd-utility.js"
|
||||||
|
import { DialogSelect } from "../../dialog-select.js"
|
||||||
|
import { ACTOR_TYPES } from "../../constants.js"
|
||||||
|
|
||||||
|
export class RdDActorEntiteSheetV2 extends RdDBaseActorSheetV2 {
|
||||||
|
|
||||||
|
static TYPE = ACTOR_TYPES.entite
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({}, RdDBaseActorSheetV2.DEFAULT_OPTIONS, {
|
||||||
|
position: { width: 640, height: 720 },
|
||||||
|
})
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
form: { template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const ctx = await super._prepareContext()
|
||||||
|
ctx.niveau = this.actor.getNiveau()
|
||||||
|
const { niveau: _, ...caracRest } = ctx.system.carac
|
||||||
|
ctx.system = { ...ctx.system, carac: caracRest }
|
||||||
|
ctx.resonances = this.actor.system.sante.resonnance.actors
|
||||||
|
.map(actorId => game.actors.get(actorId))
|
||||||
|
.filter(actor => actor != undefined)
|
||||||
|
.map(actor => ({ id: actor.id, name: actor.name, img: actor.img }))
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options)
|
||||||
|
if (!this.isEditable) return
|
||||||
|
|
||||||
|
this.html.find(".creature-carac").change(async event => {
|
||||||
|
const compName = event.currentTarget.attributes.compname.value
|
||||||
|
await this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value))
|
||||||
|
})
|
||||||
|
this.html.find(".creature-dommages").change(async event => {
|
||||||
|
const compName = event.currentTarget.attributes.compname.value
|
||||||
|
await this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value))
|
||||||
|
})
|
||||||
|
|
||||||
|
this.html.find(".resonance-add").click(async event =>
|
||||||
|
await DialogSelect.select({
|
||||||
|
label: "Choisir un acteur à accorder",
|
||||||
|
list: game.actors.filter(it => true),
|
||||||
|
},
|
||||||
|
it => this._resonanceAdd(it.id))
|
||||||
|
)
|
||||||
|
|
||||||
|
this.html.find(".resonance-delete").click(async event => {
|
||||||
|
const li = RdDSheetUtility.getEventElement(event)
|
||||||
|
const actorId = li.data("actor-id")
|
||||||
|
if (actorId) {
|
||||||
|
const actorResonance = game.actors.get(actorId)
|
||||||
|
RdDUtility.confirmSubActeurDelete(this, actorResonance, li, () => {
|
||||||
|
this._resonanceDelete(actorId)
|
||||||
|
RdDUtility.slideOnDelete(this, li)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onDropActor(event, dragData) {
|
||||||
|
const dropActor = fromUuidSync(dragData.uuid)
|
||||||
|
await this.actor.setEntiteReveAccordee(dropActor)
|
||||||
|
await super._onDropActor(event, dragData)
|
||||||
|
}
|
||||||
|
|
||||||
|
async _resonanceAdd(actorId) {
|
||||||
|
const newResonances = [...this.actor.system.sante.resonnance.actors, actorId]
|
||||||
|
await this.actor.update({ "system.sante.resonnance.actors": newResonances })
|
||||||
|
}
|
||||||
|
|
||||||
|
async _resonanceDelete(actorId) {
|
||||||
|
console.log("Delete : ", actorId)
|
||||||
|
const newResonances = this.actor.system.sante.resonnance.actors.filter(id => id !== actorId)
|
||||||
|
await this.actor.update({ "system.sante.resonnance.actors": newResonances }, { render: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
import { RdDActorSheetV2 } from "./personnage-sheet.mjs"
|
||||||
|
import { SYSTEM_RDD } from "../../constants.js"
|
||||||
|
import { Misc } from "../../misc.js"
|
||||||
|
import { EXPORT_CSV_SCRIPTARIUM, OptionsAvancees } from "../../settings/options-avancees.js"
|
||||||
|
import { ExportScriptarium } from "../../actor/export-scriptarium/export-scriptarium.js"
|
||||||
|
import { CATEGORIES_COMPETENCES_BASE, CATEGORIES_DRACONIC, Mapping } from "../../actor/export-scriptarium/mapping.js"
|
||||||
|
|
||||||
|
export class RdDActorExportSheetV2 extends RdDActorSheetV2 {
|
||||||
|
|
||||||
|
static TYPE = "personnage"
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({}, RdDActorSheetV2.DEFAULT_OPTIONS, {
|
||||||
|
position: { width: 550 },
|
||||||
|
})
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
form: { template: "systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/actor-encart-sheet.hbs" },
|
||||||
|
}
|
||||||
|
|
||||||
|
showCompNiveauBase = false
|
||||||
|
vueArchetype = false
|
||||||
|
|
||||||
|
static async init() {
|
||||||
|
await foundry.applications.handlebars.loadTemplates([
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme-titre.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/blessure.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/blessures.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-compteur.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee-compteur.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/competences.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/esquive.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/fatigue.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/protection.hbs",
|
||||||
|
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs",
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
static register() {
|
||||||
|
foundry.documents.collections.Actors.registerSheet(SYSTEM_RDD, this, {
|
||||||
|
types: ["personnage"],
|
||||||
|
makeDefault: false,
|
||||||
|
label: "Feuille simplifiée",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const ctx = await super._prepareContext()
|
||||||
|
ctx.context = Mapping.prepareContext(this.actor)
|
||||||
|
ctx.attaques = this.actor.listActionsAttaque()
|
||||||
|
ctx.export = this._getMappingValues(ctx.context, this.actor)
|
||||||
|
ctx.competences = this._getCompetences(CATEGORIES_COMPETENCES_BASE)
|
||||||
|
ctx.draconic = this._getCompetences(CATEGORIES_DRACONIC)
|
||||||
|
const legeres = this.actor.countBlessures(it => it.isLegere())
|
||||||
|
const graves = this.actor.countBlessures(it => it.isGrave())
|
||||||
|
const critiques = this.actor.countBlessures(it => it.isCritique())
|
||||||
|
ctx.etat = {
|
||||||
|
surenc: this.actor.computeMalusSurEncombrement(),
|
||||||
|
fatigue: {
|
||||||
|
value: this.actor.getFatigueActuelle(),
|
||||||
|
max: this.actor.getFatigueMax(),
|
||||||
|
malus: this.actor.malusFatigue(),
|
||||||
|
},
|
||||||
|
blessures: legeres + graves + critiques,
|
||||||
|
blessure: [legeres > 0, legeres > 1, legeres > 2, legeres > 3, legeres > 4, graves > 0, graves > 1, critiques > 0],
|
||||||
|
}
|
||||||
|
ctx.options.exportScriptarium = OptionsAvancees.isUsing(EXPORT_CSV_SCRIPTARIUM)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
_getMappingValues(context, actor) {
|
||||||
|
return Object.fromEntries(Mapping.getMapping().map(it => [it.column, {
|
||||||
|
colName: it.colName ?? it.column,
|
||||||
|
column: it.column,
|
||||||
|
rollClass: it.rollClass,
|
||||||
|
value: String(it.getter(actor, context)),
|
||||||
|
}]))
|
||||||
|
}
|
||||||
|
|
||||||
|
_getCompetences(categories) {
|
||||||
|
const competences = Mapping.getCompetencesCategorie(this.actor, categories)
|
||||||
|
if (competences.length == 0) return ""
|
||||||
|
const byCategories = Mapping.competencesByCategoriesByNiveau(competences, categories)
|
||||||
|
const listByCategories = Object.values(byCategories)
|
||||||
|
.map(it => it.competencesParNiveau)
|
||||||
|
.map(byNiveau => {
|
||||||
|
const niveaux = Object.keys(byNiveau).map(it => Number(it)).sort(Misc.ascending())
|
||||||
|
if (niveaux.length == 0) return undefined
|
||||||
|
const listCategorieByNiveau = niveaux.map(niveau => {
|
||||||
|
const list = byNiveau[niveau].sort(Misc.ascending(it => it.name))
|
||||||
|
return { niveau, list }
|
||||||
|
})
|
||||||
|
return Misc.concat(listCategorieByNiveau)
|
||||||
|
}).filter(it => it != undefined)
|
||||||
|
return Misc.concat(listByCategories)
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options)
|
||||||
|
|
||||||
|
this.html.find(".click-blessure-remove").click(async event =>
|
||||||
|
await this.actor.supprimerBlessure({
|
||||||
|
gravite: this.html.find(event.currentTarget).data("gravite"),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
this.html.find(".click-blessure-add").click(async event => {
|
||||||
|
const blessure = this.actor.nouvelleBlessure(this.html.find(event.currentTarget).data("gravite"))
|
||||||
|
await this.actor.createEmbeddedDocuments("Item", [blessure])
|
||||||
|
})
|
||||||
|
this.html.find(".button-export").click(async event => await
|
||||||
|
ExportScriptarium.INSTANCE.exportActors([this.actor],
|
||||||
|
`${this.actor.uuid}-${this.actor.name}`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDExtraitPoetiqueSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.extraitpoetique; }
|
||||||
|
static get TEMPLATES() { return []; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "extraitpoetique"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["extraitpoetique-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/extraitpoetique.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE, TEMPLATE_COMESTIBLE } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDFauneSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.faune; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE, TEMPLATE_COMESTIBLE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "faune"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["faune-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/faune.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import { RdDItemGemme } from "../../item/gemme.js";
|
||||||
|
import { RdDTimestamp } from "../../time/rdd-timestamp.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDGemmeSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.gemme; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "gemme"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["gemme-content"] },
|
||||||
|
actions: {
|
||||||
|
enchanter: RdDGemmeSheet.#onEnchanter,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/gemme.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const item = this.document
|
||||||
|
const enchantement = RdDTimestamp.splitIndexDate(item.system.prdate)
|
||||||
|
return Object.assign(
|
||||||
|
await super._prepareContext(),
|
||||||
|
{
|
||||||
|
gemmeTypeList: RdDItemGemme.getGemmeTypeOptionList(),
|
||||||
|
isEnchantementPossible: item.isEnchantementPossible,
|
||||||
|
dateActuelle: game.system.rdd.calendrier.dateCourante(),
|
||||||
|
enchantement,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onChangeForm(event, formData) {
|
||||||
|
const obj = formData?.object
|
||||||
|
if (!obj) return super._onChangeForm(event, formData)
|
||||||
|
|
||||||
|
if (event.target?.classList?.contains('date-enchantement')) {
|
||||||
|
const jour = Number(this.element?.querySelector('input.date-enchantement[name="enchantement.jour"]')?.value)
|
||||||
|
const moisEl = this.element?.querySelector('select.date-enchantement[name="enchantement.mois"]')
|
||||||
|
if (moisEl) {
|
||||||
|
const mois = RdDTimestamp.definition(moisEl.value)
|
||||||
|
const indexDate = game.system.rdd.calendrier.getIndexFromDate(jour, mois.heure)
|
||||||
|
obj['system.prdate'] = indexDate
|
||||||
|
delete obj['enchantement.jour']
|
||||||
|
delete obj['enchantement.mois']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super._onChangeForm(event, formData)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #onEnchanter(event, target) {
|
||||||
|
const { DialogEnchanter } = await import("../../enchantement/dialog-enchanter.js")
|
||||||
|
DialogEnchanter.enchanter(this.document)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE, TEMPLATE_COMESTIBLE } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDHerbeSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.herbe; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE, TEMPLATE_COMESTIBLE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "herbe"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["herbe-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/herbe.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const ctx = await super._prepareContext()
|
||||||
|
ctx.isBrut = this.document.getUtilisationCuisine() === 'brut'
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options)
|
||||||
|
|
||||||
|
this.element.querySelector('.preparer-nourriture')?.addEventListener('click', async () => {
|
||||||
|
const actor = this.document.parent
|
||||||
|
if (actor) await actor.preparerNourriture(this.document)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.element.querySelector('.manger-nourriture')?.addEventListener('click', async () => {
|
||||||
|
const actor = this.document.parent
|
||||||
|
if (actor) await actor.mangerNourriture(this.document)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE, TEMPLATE_COMESTIBLE } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDIngredientSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.ingredient; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE, TEMPLATE_COMESTIBLE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "ingredient"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["ingredient-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/ingredient.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
const ctx = await super._prepareContext()
|
||||||
|
ctx.isBrut = this.document.getUtilisationCuisine() === 'brut'
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options)
|
||||||
|
|
||||||
|
this.element.querySelector('.preparer-nourriture')?.addEventListener('click', async () => {
|
||||||
|
const actor = this.document.parent
|
||||||
|
if (actor) await actor.preparerNourriture(this.document)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.element.querySelector('.manger-nourriture')?.addEventListener('click', async () => {
|
||||||
|
const actor = this.document.parent
|
||||||
|
if (actor) await actor.mangerNourriture(this.document)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
import { CommonAppreciable } from "../../common/appreciable.mjs";
|
||||||
|
|
||||||
|
const TEMPLATE_APPRECIABLE = new CommonAppreciable();
|
||||||
|
|
||||||
|
export default class RdDJeuSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.jeu; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_APPRECIABLE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "jeu"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["jeu-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/jeu.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async _prepareContext() {
|
||||||
|
return Object.assign(
|
||||||
|
await super._prepareContext(),
|
||||||
|
{
|
||||||
|
typeChoices: { adressehasard: "Adresse/Hasard", de: "Dés", carte: "Cartes", reflexion: "Réflexion" },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDLivreSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.livre; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION, TEMPLATE_INVENTAIRE]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "livre"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["livre-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/livre.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDMaladieSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.maladie; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{ classes: ["fvtt-rdd", "item", "maladie"], position: { width: 448 }, window: { contentClasses: ["maladie-content"] } });
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: { template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/maladie.hbs" },
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { TEMPLATE_DESCRIPTION } from "../../common/_module.mjs";
|
||||||
|
import { ITEM_TYPES } from "../../constants.js";
|
||||||
|
import RdDItemBaseSheet from "./common-item-sheet.mjs";
|
||||||
|
|
||||||
|
export default class RdDMeditationSheet extends RdDItemBaseSheet {
|
||||||
|
static get ITEM_TYPE() { return ITEM_TYPES.meditation; }
|
||||||
|
static get TEMPLATES() { return [TEMPLATE_DESCRIPTION]; }
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = Object.assign({},
|
||||||
|
RdDItemBaseSheet.DEFAULT_OPTIONS,
|
||||||
|
{
|
||||||
|
classes: ["fvtt-rdd", "item", "meditation"],
|
||||||
|
position: { width: 448 },
|
||||||
|
window: { contentClasses: ["meditation-content"] },
|
||||||
|
});
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
main: {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sheets/item/meditation.hbs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -24,12 +24,4 @@ export default class RdDMonnaieSheet extends RdDItemBaseSheet {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
|
||||||
async _prepareContext() {
|
|
||||||
return Object.assign(
|
|
||||||
await super._prepareContext(),
|
|
||||||
await TEMPLATE_DESCRIPTION.prepareContext(this.document),
|
|
||||||
await TEMPLATE_INVENTAIRE.prepareContext(this.document)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -23,12 +23,4 @@ export default class RdDMunitionSheet extends RdDItemBaseSheet {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
|
||||||
async _prepareContext() {
|
|
||||||
return Object.assign(
|
|
||||||
await super._prepareContext(),
|
|
||||||
await TEMPLATE_DESCRIPTION.prepareContext(this.document),
|
|
||||||
await TEMPLATE_INVENTAIRE.prepareContext(this.document)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user