From a5c4303012d2b3e88a12fa4bb427c2e6d315deb9 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Tue, 30 Dec 2025 00:14:36 +0100 Subject: [PATCH] =?UTF-8?q?Les=20conteneurs=20ouverts=20sont=20mis=20?= =?UTF-8?q?=C3=A0=20jour?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/actions/ouvrir.svg | 1 + changelog.md | 1 + module/actor/base-actor-sang.js | 4 +- module/actor/base-actor.js | 23 +++++---- module/item.js | 11 +++- module/item/item-actions.js | 65 +++++++++++++++--------- module/rdd-sheet-utility.js | 2 +- module/rdd-utility.js | 1 + templates/actor/item-action-controls.hbs | 2 +- 9 files changed, 68 insertions(+), 42 deletions(-) create mode 100644 assets/actions/ouvrir.svg diff --git a/assets/actions/ouvrir.svg b/assets/actions/ouvrir.svg new file mode 100644 index 00000000..201ece1d --- /dev/null +++ b/assets/actions/ouvrir.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/changelog.md b/changelog.md index 8810392c..22475a16 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,7 @@ ## 13.0.27 - Les lunettes d'Illysis - Les heures ne sont plus affichées en doublon sur les messages +- Les conteneurs ouverts sont mis à jour si leur contenu change ## 13.0.26 - La ménagerie d'Illysis diff --git a/module/actor/base-actor-sang.js b/module/actor/base-actor-sang.js index 99f93960..83091b09 100644 --- a/module/actor/base-actor-sang.js +++ b/module/actor/base-actor-sang.js @@ -255,9 +255,9 @@ export class RdDBaseActorSang extends RdDBaseActorReve { await super.onCreateItem(item, options, id) } - async onUpdateItem(item, options, id) { + async onUpdateItem(item, updates, options, id) { await this.changeItemEffects(item); - await super.onUpdateItem(item, options, id) + await super.onUpdateItem(item, updates, options, id) } async onDeleteItem(item, options, id) { diff --git a/module/actor/base-actor.js b/module/actor/base-actor.js index 2113c8a1..5a315b69 100644 --- a/module/actor/base-actor.js +++ b/module/actor/base-actor.js @@ -50,7 +50,7 @@ export class RdDBaseActor extends Actor { Handlebars.registerHelper('actor-isFeminin', actor => actor.isFeminin()) Hooks.on("preUpdateItem", (item, change, options, id) => Misc.documentIfResponsible(item.parent)?.onPreUpdateItem(item, change, options, id)) Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id)) - Hooks.on("updateItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onUpdateItem(item, options, id)) + Hooks.on("updateItem", (item, updates, options, id) => Misc.documentIfResponsible(item.parent)?.onUpdateItem(item, updates, options, id)) Hooks.on("deleteItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onDeleteItem(item, options, id)) Hooks.on("updateActor", (actor, change, options, actorId) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId)) } @@ -330,7 +330,9 @@ export class RdDBaseActor extends Actor { async onCreateItem(item, options, id) { } - async onUpdateItem(item, options, id) { + async onUpdateItem(item, updates, options, id) { + const conteneur = item.findConteneur() + conteneur?.render(options.render) } async onDeleteItem(item, options, id) { @@ -339,9 +341,8 @@ export class RdDBaseActor extends Actor { } } - async _removeItemFromConteneur(item) { - const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) + const updates = this.findConteneur(item) .map(conteneur => { const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id) return { _id: conteneur.id, 'system.contenu': nouveauContenu } @@ -371,7 +372,7 @@ export class RdDBaseActor extends Actor { /* -------------------------------------------- */ async cleanupConteneurs() { if (Misc.isOwnerPlayer(this)) { - let updates = this.itemTypes['conteneur'] + let updates = this.itemTypes[ITEM_TYPES.conteneur] .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) } }); if (updates.length > 0) { @@ -382,7 +383,7 @@ export class RdDBaseActor extends Actor { /* -------------------------------------------- */ getFortune() { - return Monnaie.getFortune(this.itemTypes['monnaie']); + return Monnaie.getFortune(this.itemTypes[ITEM_TYPES.monnaie]); } /* -------------------------------------------- */ @@ -663,7 +664,7 @@ export class RdDBaseActor extends Actor { if (srcId != destId && itemId != destId) { // déplacement de l'objet const src = this.getItem(srcId); const dest = this.getItem(destId); - const cible = this.getContenantOrParent(dest); + const cible = this.findConteneurOrParent(dest); const [empilable, message] = item.isInventaireEmpilable(dest); if (empilable) { await dest.empiler(item) @@ -685,15 +686,15 @@ export class RdDBaseActor extends Actor { return result; } - getContenantOrParent(dest) { + findConteneurOrParent(dest) { if (!dest || dest.isConteneur()) { return dest; } - return this.getContenant(dest); + return this.findConteneur(dest) } - getContenant(item) { - return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id)); + findConteneur(item) { + return this.itemTypes[ITEM_TYPES.conteneur].find(it => it.system.contenu.includes(item.id)); } diff --git a/module/item.js b/module/item.js index d769b779..4a3ac55c 100644 --- a/module/item.js +++ b/module/item.js @@ -81,13 +81,13 @@ export const defaultItemImg = { souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp", tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp", tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp", - monnaie:"systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp", + monnaie: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp", munition: "systems/foundryvtt-reve-de-dragon/icons/objets/fleche.webp" } /* -------------------------------------------- */ export class RdDItem extends Item { - + static get defaultIcon() { return undefined; } @@ -185,6 +185,13 @@ export class RdDItem extends Item { isCompetencePersonnage() { return this.type == ITEM_TYPES.competence } isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature } isConteneur() { return this.type == ITEM_TYPES.conteneur } + findConteneur() { + if (this.isInventaire('all') && this.parent) { + return this.parent.findConteneur(this) + } + return undefined + } + isMonnaie() { return this.type == ITEM_TYPES.monnaie } isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; } isService() { return this.type == ITEM_TYPES.service } diff --git a/module/item/item-actions.js b/module/item/item-actions.js index fe4f96af..f6f8e818 100644 --- a/module/item/item-actions.js +++ b/module/item/item-actions.js @@ -1,4 +1,4 @@ -import { ACTOR_TYPES } from "../constants.js" +import { ACTOR_TYPES, ITEM_TYPES } from "../constants.js" import { Misc } from "../misc.js" import { RdDSheetUtility } from "../rdd-sheet-utility.js" import { RdDUtility } from "../rdd-utility.js" @@ -11,33 +11,35 @@ import { RdDUtility } from "../rdd-utility.js" const _SPACEHOLDER = { placeholder: true } const _VENDRE = { - code: 'item-vendre', label: 'Vendre ou donner', icon: it => 'fa-solid fa-comments-dollar', + code: 'item-vendre', label: 'Vendre ou donner', icon: 'fa-solid fa-comments-dollar', filter: it => Misc.toInt(it.system.quantite) > 0 || it.parent?.type == ACTOR_TYPES.commerce, action: (item, actor) => item.proposerVente() } const _ACHETER = { - code: 'item-acheter', label: 'Acheter', icon: it => 'fa-regular fa-coins', + code: 'item-acheter', label: 'Acheter', icon: 'fa-regular fa-coins', filter: it => it.parent?.type == ACTOR_TYPES.commerce, allowLimited: true, action: (item, actor) => actor.vente(item) } const _MONTRER = { - code: 'item-montrer', label: 'Montrer', icon: it => 'fa-solid fa-comment', + code: 'item-montrer', label: 'Montrer', icon: 'fa-solid fa-comment', allowLimited: true, action: (item, actor) => item.postItemToChat() } const _SPLIT = { - code: 'item-split', label: 'Séparer le goupe', icon: it => 'fa-solid fa-unlink', + code: 'item-split', label: 'Séparer le goupe', icon: 'fa-solid fa-unlink', filter: it => Misc.toInt(it.system.quantite) > 1 && it.parent?.type != ACTOR_TYPES.commerce, action: (item, actor) => RdDSheetUtility.splitItem(item, actor) } const _EDIT = { - code: 'item-edit', label: 'Editer', icon: it => 'fa-solid fa-edit', + code: 'item-edit', label: it => it.type == ITEM_TYPES.conteneur ? 'Ouvrir' : 'Editer', + icon: 'fa-solid fa-edit', action: (item, actor) => item.sheet.render(true) } + const _DELETE = { - code: 'item-delete', label: 'Supprimer', icon: it => 'fa-solid fa-trash', + code: 'item-delete', label: 'Supprimer', icon: 'fa-solid fa-trash', optionsFilter: options => options.isOwner, action: (item, actor) => RdDUtility.confirmActorItemDelete(item, actor) } @@ -49,48 +51,48 @@ const _EQUIPER = { const _CUISINER = { code: 'item-cuisiner', label: 'Cuisiner', - img: it => 'systems/foundryvtt-reve-de-dragon/assets/actions/cuisine.svg', - // icon: it => 'fa-solid fa-spoon', + img: 'systems/foundryvtt-reve-de-dragon/assets/actions/cuisine.svg', filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0, action: (item, actor) => actor.preparerNourriture(item) } const _MANGER_CRU = { - code: 'item-manger-cru', label: 'Manger cru', icon: it => 'fa-solid fa-drumstick-bite', + code: 'item-manger-cru', label: 'Manger cru', icon: 'fa-solid fa-drumstick-bite', filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0, action: (item, actor) => actor.mangerNourriture(item) } const _MANGER = { - code: 'item-manger', label: 'Manger', icon: it => 'fa-solid fa-utensils', + code: 'item-manger', label: 'Manger', icon: 'fa-solid fa-utensils', filter: it => !(it.system.boisson), action: (item, actor) => actor.mangerNourriture(item) } const _BOIRE = { - code: 'item-boire', label: 'Boire', icon: it => 'fa-solid fa-glass-water', + code: 'item-boire', label: 'Boire', icon: 'fa-solid fa-glass-water', filter: it => it.system.boisson, action: (item, actor) => actor.mangerNourriture(item) } const _DECOCTION = { - code: 'item-decoction', label: 'Décoction', icon: it => 'fa-solid fa-flask-vial', + code: 'item-decoction', label: 'Décoction', icon: 'fa-solid fa-flask-vial', action: (item, actor) => actor.fabriquerDecoctionHerbe(item) } + const _OUVRIR = { - code: 'item-edit', label: 'Ouvrir', icon: it => 'fa-solid fa-eye', + code: 'item-edit', label: 'Ouvrir', + img: 'systems/foundryvtt-reve-de-dragon/assets/actions/ouvrir.svg', action: (item, actor) => item.sheet.render(true) } - const _LIRE = { - code: 'item-lire', label: 'Lire', icon: it => 'fa-solid fa-book-open', + code: 'item-lire', label: 'Lire', icon: 'fa-solid fa-book-open', action: (item, actor) => actor.actionLire(item) } const _REFOULER = { - code: 'item-refouler', label: 'Refouler', icon: it => 'fa-solid fa-burst', + code: 'item-refouler', label: 'Refouler', icon: 'fa-solid fa-burst', filter: it => it.system.refoulement > 0, action: (item, actor) => actor.actionRefoulement(item) } const _SORT_RESERVE = { - code: 'item-sortreserve-add', label: 'Ajouter en réserve', icon: it => 'fa-solid fa-sparkles', + code: 'item-sortreserve-add', label: 'Ajouter en réserve', icon: 'fa-solid fa-sparkles', filter: it => game.user.isGM && !it.system.isrituel, action: (item, actor) => actor.addSortReserve(item) } @@ -121,20 +123,33 @@ export class ItemAction { && (!action.optionsFilter || action.optionsFilter(options)) } - - static img(action, item) { - if (action.placeholder){ + static label(action, item) { + if (action.placeholder) { return "" } - if (action?.img) { - return `` + return ItemAction.getParam(action.label, item) + } + + static img(action, item) { + if (action.placeholder) { + return "" } - if (action?.icon) { - return `` + + const img = ItemAction.getParam(action.img, item) + if (img) { + return `` + } + const icon = ItemAction.getParam(action.icon, item) + if (icon) { + return `` } return action.label } + static getParam(p, item) { + return typeof (p) == 'function' ? p(item) : p + } + static async onActionItem(event, actor, options) { const code = $(event.currentTarget).data('code') const item = RdDSheetUtility.getItem(event, actor) diff --git a/module/rdd-sheet-utility.js b/module/rdd-sheet-utility.js index bf6fc289..910fae5d 100644 --- a/module/rdd-sheet-utility.js +++ b/module/rdd-sheet-utility.js @@ -93,7 +93,7 @@ export class RdDSheetUtility { static async renderItemBranch(actor, item) { while (item) { await item.sheet?.render() - item = actor.getContenant(item) + item = actor.findConteneur(item) } } } \ No newline at end of file diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 6f818763..265f73e8 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -348,6 +348,7 @@ export class RdDUtility { // Items Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field)); Handlebars.registerHelper('item-action-applies', (action, item, options) => ItemAction.applies(action, item, options)) + Handlebars.registerHelper('item-action-label', (action, item) => new Handlebars.SafeString(ItemAction.label(action, item))) Handlebars.registerHelper('item-action-img', (action, item) => new Handlebars.SafeString(ItemAction.img(action, item))) Handlebars.registerHelper('item-name', (item) => item.nameDisplay) diff --git a/templates/actor/item-action-controls.hbs b/templates/actor/item-action-controls.hbs index 8ef4ef05..ad1a0422 100644 --- a/templates/actor/item-action-controls.hbs +++ b/templates/actor/item-action-controls.hbs @@ -2,7 +2,7 @@ {{#each item.actions as |action|}} {{#if action.placeholder}}  {{else if (item-action-applies action ../item ../options)}} - + {{item-action-img action ../item}} {{/if}}