From 25db7e0712d9ed0acd9806211ec013d24312c96c Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Tue, 18 Mar 2025 01:56:26 +0100 Subject: [PATCH] =?UTF-8?q?Am=C3=A9lioration=20des=20fermetures=20de=20TMR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - un seul message lors de la fermeture au MJ et joueur - le déclenchement de sort en réserve --- module/actor.js | 12 +- module/actor/base-actor-sang.js | 7 +- module/rdd-tmr-dialog.js | 225 ++++++++++++----------- module/rdd-utility.js | 1 + templates/chat-lancement-sortreserve.hbs | 15 ++ 5 files changed, 140 insertions(+), 120 deletions(-) create mode 100644 templates/chat-lancement-sortreserve.hbs diff --git a/module/actor.js b/module/actor.js index b5fc7302..1eed05f0 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1048,20 +1048,10 @@ export class RdDActor extends RdDBaseActorSang { } /* -------------------------------------------- */ - async deleteRencontreTMRAtPosition() { - const rencontreIds = this.itemTypes[ITEM_TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id) - if (rencontreIds.length > 0) { - await this.deleteEmbeddedDocuments('Item', rencontreIds) - } - } getRencontreTMREnAttente() { - return this.itemTypes[ITEM_TYPES.rencontre].find(this.filterRencontreTMRDemiReve()) - } - - filterRencontreTMRDemiReve() { const position = this.getDemiReve() - return it => it.system.coord == position + return this.itemTypes[ITEM_TYPES.rencontre].find(it => it.system.coord == position) } /* -------------------------------------------- */ diff --git a/module/actor/base-actor-sang.js b/module/actor/base-actor-sang.js index 5fe7895d..4a021a7f 100644 --- a/module/actor/base-actor-sang.js +++ b/module/actor/base-actor-sang.js @@ -39,7 +39,12 @@ export class RdDBaseActorSang extends RdDBaseActorReve { return 0; } - getFatigueRestante() { return this.getFatigueMax() - this.getFatigueActuelle() } + isCumulFatigueCauseSommeil(cumulFatigue){ + return ReglesOptionnelles.isUsing("appliquer-fatigue") + ? (this.getFatigueRestante() <= cumulFatigue) + : (this.getEnduranceActuelle() <= cumulFatigue) + } + getFatigueRestante() {return this.getFatigueMax() - this.getFatigueActuelle() } getFatigueMin() { return this.system.sante.endurance.max - this.system.sante.endurance.value } malusFatigue() { diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 7fa15384..af82d87c 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -15,7 +15,6 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { RdDDice } from "./rdd-dice.js"; import { STATUSES } from "./settings/status-effects.js"; import { RdDRencontre } from "./item/rencontre.js"; -import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { ITEM_TYPES } from "./constants.js"; import { Misc } from "./misc.js"; @@ -83,7 +82,7 @@ export class RdDTMRDialog extends Dialog { this.subdialog = undefined this.displaySize = undefined if (!this.viewOnly && !game.user.isGM) { - this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); + this.$tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); } this.callbacksOnAnimate = []; const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def); @@ -139,7 +138,7 @@ export class RdDTMRDialog extends Dialog { this.cumulFatigue += this.fatigueParCase; // Le reste... - this.updateValuesDisplay(); + this.$updateValuesDisplay(); } lancerUnSort() { @@ -190,7 +189,7 @@ export class RdDTMRDialog extends Dialog { forceTMRContinueAction() { ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR'); this.bringSubDialogToTop(); - return; + return false } setTMRPendingAction(dialog) { @@ -297,7 +296,7 @@ export class RdDTMRDialog extends Dialog { const coordOrig = this._getCoordActor(); const coordTarget = TMRUtility.deplacement(coordOrig, move); await this._deplacerDemiReve(coordTarget, 'normal'); - this.checkQuitterTMR(); + await this.$checkQuitterTMR(); } calculCoutMonteeTMR() { @@ -305,7 +304,7 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async updateValuesDisplay() { + async $updateValuesDisplay() { if (this.viewOnly || !this.rendered) { return; } @@ -336,22 +335,30 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ async close() { + await this.$forceClose(this.actor.name + " a quitté les terres médianes") + } + + async $forceClose(message) { if (this.subdialog) { - return this.forceTMRContinueAction() + this.forceTMRContinueAction() + return false } this.descenteTMR = true; if (this.actor.tmrApp) { this.actor.tmrApp = undefined; // Cleanup reference if (!this.viewOnly) { - await this.actor.setEffect(STATUSES.StatusDemiReve, false) - this._tellToGM(this.actor.name + " a quitté les terres médianes"); + await this.actor.setEffect(STATUSES.StatusDemiReve, false); + this.$tellToUserAndGM(message) } - await this.actor.santeIncDec((ReglesOptionnelles.isUsing("appliquer-fatigue") ? "fatigue" : "endurance"), - this.cumulFatigue) + const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue"); + await this.actor.santeIncDec( + appliquerFatigue ? "fatigue" : "endurance", + (appliquerFatigue ? 1 : -1) * this.cumulFatigue); } - await super.close(); - this.pixiTMR.close() + this.pixiTMR.close(); this.pixiTMR = undefined + await super.close(); + return true } /* -------------------------------------------- */ @@ -363,48 +370,53 @@ export class RdDTMRDialog extends Dialog { } switch (action) { case 'derober': - await this.derober(); - this.restoreTMRAfterAction(); - return; + await this.$derober() + this.restoreTMRAfterAction() + return case 'refouler': - await this.refouler(); - break; + await this.$refouler() + break case 'maitriser': - await this.maitriserRencontre(); - break; + await this.$maitriserRencontre() + break case 'ignorer': - await this.ignorerRencontre(); - break; + await this.$ignorerRencontre() + break } await this.postRencontre(tmr); this.restoreTMRAfterAction(); } - async derober() { - console.log("-> derober", this.currentRencontre); - await this.actor.addTMRRencontre(this.currentRencontre); - this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR."); - this.close(); + async $derober() { + if (this.currentRencontre) { + console.log("-> derober", this.currentRencontre); + await this.actor.addTMRRencontre(this.currentRencontre); + this.$forceClose(`${this.actor.name} s'est dérobé face à la rencontre ${this.currentRencontre.name}, et quitte les TMR.`) + } } /* -------------------------------------------- */ - async refouler() { - console.log("-> refouler", this.currentRencontre); - await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`); - await this.actor.deleteRencontreTMRAtPosition() - this.updateTokens(); - this.updateValuesDisplay(); - this.nettoyerRencontre(); + async $refouler() { + if (this.currentRencontre) { + console.log("-> refouler", this.currentRencontre); + await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`); + await this.$deleteRencontreTMRAtPosition() + this.updateTokens(); + this.$updateValuesDisplay(); + this.$nettoyerRencontre(); + } } /* -------------------------------------------- */ - async ignorerRencontre() { - console.log("-> ignorer", this.currentRencontre); - this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); - await this.actor.deleteRencontreTMRAtPosition() - this.updateTokens(); - this.updateValuesDisplay(); - this.nettoyerRencontre(); + async $ignorerRencontre() { + if (this.currentRencontre) { + console.log("-> ignorer", this.currentRencontre); + this.$tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); + await this.$deleteRencontreTMRAtPosition() + this.updateTokens(); + this.$updateValuesDisplay(); + this.$nettoyerRencontre(); + } } /* -------------------------------------------- */ @@ -421,41 +433,29 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - checkQuitterTMR() { - if (this.actor.isDead()) { - this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !"); - this.close(); - return true; + async $checkQuitterTMR() { + const reason = this.actor.isDead() + ? "est mort" + : this.actor.isCumulFatigueCauseSommeil(this.cumulFatigue) + ? "s'écroule de fatigue" + : (this.actor.getReveActuel() == 0) + ? "tombe à 0 Points de Rêve" + : undefined + if (reason) { + if (!this.actor.isDead()) { + await this.$refouler() + } + this.$forceClose(`${this.actor.name} ${reason} et quitte les Terres médianes !`) + return true } - - if (ReglesOptionnelles.isUsing("appliquer-fatigue") - ? (this.actor.getFatigueRestante() <= this.cumulFatigue) - : (this.actor.getEnduranceActuelle() <= this.cumulFatigue) - ) { - this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !"); - this.quitterLesTMRInconscient(); - return true; - } - - if (this.actor.getReveActuel() == 0) { - this._tellToGM("Vos Points de Rêve sont à 0 : vous quittez les Terres médianes !"); - this.quitterLesTMRInconscient(); - return true; - } - return false; + return false } /* -------------------------------------------- */ - async quitterLesTMRInconscient() { - await this.refouler(); - this.close(); - } - - /* -------------------------------------------- */ - async maitriserRencontre() { + async $maitriserRencontre() { console.log("-> maitriser", this.currentRencontre); - await this.actor.deleteRencontreTMRAtPosition() + await this.$deleteRencontreTMRAtPosition(); this.updateTokens(); let rencontreData = { @@ -470,11 +470,21 @@ export class RdDTMRDialog extends Dialog { tmr: TMRUtility.getTMR(this._getCoordActor()) } - await this._tentativeMaitrise(rencontreData); + await this.$tentativeMaitrise(rencontreData); + } + + async $deleteRencontreTMRAtPosition() { + const position = this.actor.getDemiReve() + const rencontreIds = this.actor.itemTypes[ITEM_TYPES.rencontre] + .filter(it => it.system.coord == position) + .map(it => it.id) + if (rencontreIds.length > 0) { + await this.actor.deleteEmbeddedDocuments('Item', rencontreIds) + } } /* -------------------------------------------- */ - async _tentativeMaitrise(rencData) { + async $tentativeMaitrise(rencData) { this.rencontreState = 'normal'; rencData.reve = this.actor.getReveActuel(); @@ -483,7 +493,7 @@ export class RdDTMRDialog extends Dialog { RollDataAjustements.calcul(rencData, this.actor); rencData.rolled = rencData.presentCite - ? this._rollPresentCite(rencData) + ? this.$rollPresentCite(rencData) : await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements)); const result = rencData.rolled.isSuccess @@ -493,38 +503,41 @@ export class RdDTMRDialog extends Dialog { await RdDRencontre.appliquer(result.effets, this, rencData); rencData.poesie = { extrait: result.poesie, reference: result.reference }; - rencData.message = this.formatMessageRencontre(rencData, result.message); + rencData.message = this.$formatMessageRencontre(rencData, result.message); ChatMessage.create({ whisper: ChatUtility.getOwners(this.actor), content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData) }); - this.updateValuesDisplay(); - if (this.checkQuitterTMR()) { + this.$updateValuesDisplay(); + if (await this.$checkQuitterTMR()) { return; } if (this.rencontreState == 'persistant') { - this._nouvelleTentativeMaitrise(rencData); + this.$nouvelleTentativeMaitrise(rencData); } else if (!this.isRencontreDeplacement()) { - this.nettoyerRencontre(); + this.$nettoyerRencontre(); } } - _nouvelleTentativeMaitrise(rencData) { + $nouvelleTentativeMaitrise(rencData) { setTimeout(() => { - // TODO: remplacer par une boucle while(this.currentRencontre) ? + /** + * TODO: remplacer par une boucle while(this.currentRencontre) ? + * ajouter un moyen d'attendre la saisie de l'utilisateur (jet obligatoire)? + */ rencData.nbRounds++; if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { this.cumulFatigue += this.fatigueParCase; } - this._tentativeMaitrise(rencData); - this._deleteTmrMessages(rencData.actor, rencData.nbRounds); + this.$tentativeMaitrise(rencData); + this.$deleteTmrMessages(rencData.actor, rencData.nbRounds); }, 2000); } - formatMessageRencontre(rencData, template) { + $formatMessageRencontre(rencData, template) { let messageDuree = '' if (rencData.nbRounds > 1) { if (rencData.rolled.isSuccess) { @@ -543,7 +556,7 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - _rollPresentCite(rencData) { + $rollPresentCite(rencData) { let rolled = RdDResolutionTable.computeChances(rencData.reve, 0); foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score }); RdDResolutionTable.succesRequis(rolled); @@ -551,7 +564,7 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - _deleteTmrMessages(actor, nbRounds = -1) { + $deleteTmrMessages(actor, nbRounds = -1) { setTimeout(() => { if (nbRounds < 0) { ChatUtility.removeChatMessageContaining(`

it.id == this.currentRencontre.id)) { // rencontre en attente suite à dérobade - await this.maitriserRencontre(); + await this.$maitriserRencontre(); } else { const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr); @@ -648,7 +661,7 @@ export class RdDTMRDialog extends Dialog { tmr: tmr, presentCite: presentCite }; - await this._tentativeMaitrise(rencontreData); + await this.$tentativeMaitrise(rencontreData); this.postRencontre(tmr); } @@ -727,7 +740,7 @@ export class RdDTMRDialog extends Dialog { content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData) }); if (rollData.rolled.isEchec) { - await this.close(); + await this.$forceClose(`n'a pas maîtrisé la case ${rollData.tmr.label} et quitte les terres médianes`) } await this.souffleSiEchecTotal(rollData); } @@ -782,7 +795,7 @@ export class RdDTMRDialog extends Dialog { onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), onConqueteEchec: r => { this.souffleSiEchecTotal(rollData); - this.close() + this.$forceClose(`${this.actor.name} n'a pas maîtrisé la ${tmr.label}, et quitte les TMR.`) }, canClose: false }); @@ -797,7 +810,7 @@ export class RdDTMRDialog extends Dialog { onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), onConqueteEchec: r => { this.souffleSiEchecTotal(rollData); - this.close() + this.$forceClose(`${this.actor.name} n'a pas purifié la ${tmr.label}, et quitte les TMR.`) }, canClose: false }); @@ -811,7 +824,7 @@ export class RdDTMRDialog extends Dialog { difficulte: -7, action: 'Conquérir', onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), - onConqueteEchec: r => this.close(), + onConqueteEchec: r => this.$forceClose(`${this.actor.name} n'a pas conquis la case ${tmr.label}, et quitte les TMR.`), canClose: false }); } @@ -922,19 +935,15 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ async processSortReserve(sortReserve) { await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]); - console.log("declencheSortEnReserve", sortReserve); - const heureCible = RdDTimestamp.definition(sortReserve.system.heurecible).label; - this._tellToUserAndGM(`Vous avez déclenché - ${sortReserve.system.echectotal ? "l'échec total!" : "le sort"} - en réserve ${sortReserve.name} - avec ${sortReserve.system.ptreve} points de Rêve - en ${sortReserve.system.coord} (${TMRUtility.getTMRLabel(sortReserve.system.coord)}). - L'heure ciblée est ${heureCible}`); - this.close(); + console.log("declencheSortEnReserve", sortReserve) + const sort = sortReserve.system.sortid ? this.actor.items.get(sortReserve.system.sortid) : undefined + const message = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-lancement-sortreserve.hbs`, + { sortReserve, sort }) + await this.$forceClose(message) } /* -------------------------------------------- */ - nettoyerRencontre() { + $nettoyerRencontre() { // Suppression des dessins des zones possibles this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic)) // Nettoyage de la structureet de l'état @@ -1021,7 +1030,7 @@ export class RdDTMRDialog extends Dialog { console.log("STATUS :", this.rencontreState, this.currentRencontre); } - this.checkQuitterTMR(); + await this.$checkQuitterTMR(); } /* -------------------------------------------- */ @@ -1054,13 +1063,13 @@ export class RdDTMRDialog extends Dialog { */ this.notifierResonanceSigneDraconique(targetCoord); await this.actor.rollUnSort(targetCoord); - this.nettoyerRencontre(); + this.$nettoyerRencontre(); } /* -------------------------------------------- */ externalRefresh() { this.createPixiSprites(); - this.updateValuesDisplay(); + this.$updateValuesDisplay(); this.updateTokens(); console.log("TMR REFRESHED !!!"); } @@ -1071,7 +1080,7 @@ export class RdDTMRDialog extends Dialog { return this.forceTMRContinueAction() } if (this.currentRencontre != 'normal') { - this.nettoyerRencontre(); + this.$nettoyerRencontre(); } let tmr = TMRUtility.getTMR(targetCoord); // Gestion cases spéciales type Trou noir, etc @@ -1083,7 +1092,7 @@ export class RdDTMRDialog extends Dialog { if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { this.cumulFatigue += this.fatigueParCase; } - this.updateValuesDisplay(); + this.$updateValuesDisplay(); this.actor.notifyRefreshTMR(); if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... diff --git a/module/rdd-utility.js b/module/rdd-utility.js index a15daf61..cced95a2 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -318,6 +318,7 @@ export class RdDUtility { // gestion des dates et heures Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) }); Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) }); + Handlebars.registerHelper('timestamp-definition', (heure) => RdDTimestamp.definition(heure)) Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier()); Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree()); Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode()); diff --git a/templates/chat-lancement-sortreserve.hbs b/templates/chat-lancement-sortreserve.hbs new file mode 100644 index 00000000..5589b338 --- /dev/null +++ b/templates/chat-lancement-sortreserve.hbs @@ -0,0 +1,15 @@ + +

Vous avez déclenché + {{#if sortReserve.system.echectotal}}l'échec total{{else}}le sort{{/if}} + en réserve +{{sortReserve.name}} + avec {{sortReserve.system.ptreve}} points de Rêve + en {{sortReserve.system.coord}} ({{caseTmr-label sortReserve.system.coord}}). + L'heure ciblée est {{sortReserve.system.heurecible}} + {{timestamp-imgSigneHeure sortReserve.system.heurecible}} +

+{{#if sort}} +
+ {{{sort.system.description}}} +
+{{/if}}