From 7a92ee85efad96e621df27e589ce104dedaf51e0 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 17 Sep 2022 22:36:43 +0200 Subject: [PATCH] Nettoyage des status effects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Recherche et suppression toujours par flags.core.statusId * l'ajout d'un status depuis le token est maintenant équivallent à l'ajout par le code * Correction des demi-surprises * Correction du Demi-rêve (qui ne disparaissait pas) * fix de la selection dans la configuration système --- module/actor-sheet.js | 14 ++-- module/actor.js | 72 +++++++------------ module/rdd-combat.js | 3 +- module/rdd-tmr-dialog.js | 13 ++-- module/status-effects.js | 81 +++++++++++++--------- templates/actor-sheet-effects-partial.html | 2 +- templates/status-effects-settings.html | 2 +- 7 files changed, 93 insertions(+), 94 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 69224370..ba5c6099 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -15,7 +15,7 @@ import { DialogSplitItem } from "./dialog-split-item.js"; import { ReglesOptionelles } from "./regles-optionelles.js"; import { DialogRepos } from "./dialog-repos.js"; import { RdDSheetUtility } from "./rdd-sheet-utility.js"; -import { TMRUtility } from "./tmr-utility.js"; +import { STATUSES } from "./status-effects.js"; /* -------------------------------------------- */ export class RdDActorSheet extends ActorSheet { @@ -100,7 +100,7 @@ export class RdDActorSheet extends ActorSheet { formData.difficultesLibres = CONFIG.RDD.difficultesLibres; formData.hautreve = { - isDemiReve: this.actor.getEffectByLabel("Demi-rêve"), + isDemiReve: this.actor.getEffect(STATUSES.StatusDemiReve), rencontres: duplicate(formData.system.reve.rencontre.list), casesTmr: formData.itemsByType.casetmr, cacheTMR: this.actor.isTMRCache() @@ -361,11 +361,15 @@ export class RdDActorSheet extends ActorSheet { await DialogRepos.create(this.actor); }); html.find('.delete-active-effect').click(async event => { - let id = $(event.currentTarget).parents(".active-effect").data('id'); - this.actor.enleverActiveEffectById(id); + if (game.user.isGM) { + let effect = $(event.currentTarget).parents(".active-effect").data('effect'); + this.actor.removeEffect(effect); + } }); html.find('.enlever-tous-effets').click(async event => { - this.actor.enleverTousLesEffets(); + if (game.user.isGM) { + this.actor.enleverTousLesEffets(); + } }); html.find('.conteneur-name a').click(async event => { RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event)); diff --git a/module/actor.js b/module/actor.js index 8ef268f7..33a3055a 100644 --- a/module/actor.js +++ b/module/actor.js @@ -17,7 +17,7 @@ import { RdDAudio } from "./rdd-audio.js"; import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemArme } from "./item-arme.js"; import { RdDAlchimie } from "./rdd-alchimie.js"; -import { StatusEffects } from "./status-effects.js"; +import { STATUSES, StatusEffects } from "./status-effects.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemSigneDraconique } from "./item-signedraconique.js"; import { ReglesOptionelles } from "./regles-optionelles.js"; @@ -52,8 +52,6 @@ const POSSESSION_SANS_DRACONIC = { export class RdDActor extends Actor { /* -------------------------------------------- */ static init() { - Hooks.on("deleteActiveEffect", (effect, options, userId) => RdDActor.getParentActor(effect)?.onDeleteActiveEffect(effect, options)); - Hooks.on("preUpdateItem", (item, change, options, id) => RdDActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id)); Hooks.on("createItem", (item, options, id) => RdDActor.getParentActor(item)?.onCreateItem(item, options, id)); Hooks.on("deleteItem", (item, options, id) => RdDActor.getParentActor(item)?.onDeleteItem(item, options, id)); @@ -420,7 +418,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ getSurprise(isCombat = undefined) { - let niveauSurprise = this.getActiveEffects() + let niveauSurprise = this.getEffects() .map(effect => StatusEffects.valeurSurprise(effect, isCombat)) .reduce(Misc.sum(), 0); if (niveauSurprise > 1) { @@ -1587,12 +1585,12 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ getSonne() { - return this.getEffectByLabel("EFFECT.StatusStunned"); + return this.getEffect(STATUSES.StatusStunned); } /* -------------------------------------------- */ async finDeRound(options = { terminer: false }) { - for (let effect of this.getActiveEffects()) { + for (let effect of this.getEffects()) { if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) { if (effect.system.origin) { await effect.update({ 'disabled': true }); @@ -1621,7 +1619,7 @@ export class RdDActor extends Actor { ui.notifications.info("Le personnage est hors combat, il ne reste donc pas sonné"); return; } - await this.setStatusEffect("EFFECT.StatusStunned", sonne); + await this.setEffect(STATUSES.StatusStunned, sonne); } /* -------------------------------------------- */ @@ -1774,7 +1772,7 @@ export class RdDActor extends Actor { } await this.update({ "system.sante": sante }) if (this.isDead()) { - await this.setStatusEffect("EFFECT.StatusComma", true); + await this.setEffect(STATUSES.StatusComma, true); } return result; } @@ -3158,8 +3156,7 @@ export class RdDActor extends Actor { ui.notifications.warn("Vous êtes déja dans les TMR...."); return } - let demiReve = this.getActiveEffects(it => it.label == "Demi-rêve"); - if (mode != 'visu' && demiReve.length > 0) { + if (mode != 'visu' && this.getEffect(STATUSES.StatusDemiReve)) { ui.notifications.warn("Le joueur ou le MJ est déja dans les Terres Médianes avec ce personnage ! Visualisation uniquement"); mode = "visu"; // bascule le mode en visu automatiquement } @@ -3174,7 +3171,7 @@ export class RdDActor extends Actor { }); return; } - await this.setStatusEffect("EFFECT.StatusDemiReve", true); + await this.setEffect(STATUSES.StatusDemiReve, true); } const fatigue = this.system.sante.fatigue.value; @@ -3464,7 +3461,7 @@ export class RdDActor extends Actor { count--; } else { // TODO: status effect dead - this.setStatusEffect("EFFECT.StatusComma", true); + this.setEffect(STATUSES.StatusComma, true); ChatMessage.create({ content: `charge ${this.name} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !` @@ -4099,61 +4096,44 @@ export class RdDActor extends Actor { async onUpdateActor(update, options, actorId) { const updatedEndurance = update?.system?.sante?.endurance if (updatedEndurance && options.diff) { - await this.setStatusEffect("EFFECT.StatusUnconscious", updatedEndurance.value == 0) + await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0) } } /* -------------------------------------------- */ - async onDeleteActiveEffect(effect, options) { - switch (effect.label) { - case 'EFFECT.StatusStunned': - return; - } + getEffects() { + return this.getEmbeddedCollection("ActiveEffect"); } /* -------------------------------------------- */ - getActiveEffects(matching = it => true) { - return Array.from(this.getEmbeddedCollection("ActiveEffect").values()).filter(it => matching(it)); + getEffect(statusId) { + return this.getEmbeddedCollection("ActiveEffect").find(it => it.flags?.core?.statusId == statusId); } /* -------------------------------------------- */ - getEffectByLabel(label) { - return this.getActiveEffects().find(it => it.system?.label == label); - } - - /* -------------------------------------------- */ - getEffectById(id) { - return this.getActiveEffects().find(it => it.id == id); - } - - /* -------------------------------------------- */ - async setStatusEffect(label, status, updates = {}) { + async setEffect(statusId, status) { if (this.isEntite() || this.type == 'vehicule') { return; } - console.log("setStatusEffect", label, status, updates) - const existing = this.getEffectByLabel(label); - if (existing) { - existing.delete(); - } - if (status) { - const statusEffect = mergeObject(duplicate(StatusEffects.status(label)), updates); - await this.createEmbeddedDocuments("ActiveEffect", [statusEffect]); + console.log("setEffect", statusId, status) + await this.removeEffect(statusId); + const effect = StatusEffects.status(statusId); + if (effect) { + await this.createEmbeddedDocuments("ActiveEffect", [effect]); } } - enleverActiveEffectById(id) { - if (game.user.isGM) { - const existing = this.getEffectById(id); - if (existing) { - existing.delete(); - } + async removeEffect(statusId) { + const effect = this.getEffect(statusId); + if (effect) { + await this.deleteEmbeddedDocuments('ActiveEffect', [effect.id]); } } + /* -------------------------------------------- */ enleverTousLesEffets() { if (game.user.isGM) { - this.deleteEmbeddedDocuments('ActiveEffect', this.getActiveEffects().map(it => it.id)); + this.deleteEmbeddedDocuments('ActiveEffect', this.getEffects().map(it => it.id)); } } diff --git a/module/rdd-combat.js b/module/rdd-combat.js index fee00988..30456d43 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -10,6 +10,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDRoll } from "./rdd-roll.js"; import { RdDRollTables } from "./rdd-rolltables.js"; import { ReglesOptionelles } from "./regles-optionelles.js"; +import { STATUSES } from "./status-effects.js"; /* -------------------------------------------- */ const premierRoundInit = [ @@ -1185,7 +1186,7 @@ export class RdDCombat { defenderRoll.show.recul = 'encaisse'; } else if (rollRecul.rolled.isETotal || this._isReculCauseChute(impact)) { defenderRoll.show.recul = 'chute'; - await this.defender.setStatusEffect("EFFECT.StatusProne", true); + await this.defender.setEffect(STATUSES.StatusProne, true); } else { defenderRoll.show.recul = 'recul'; diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index f7e07f83..8bd2ce34 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -1,4 +1,3 @@ -import { SYSTEM_SOCKET_ID } from "./constants.js"; import { RollDataAjustements } from "./rolldata-ajustements.js"; import { RdDUtility } from "./rdd-utility.js"; import { TMRUtility } from "./tmr-utility.js"; @@ -16,6 +15,7 @@ import { Misc } from "./misc.js"; import { HtmlUtility } from "./html-utility.js"; import { ReglesOptionelles } from "./regles-optionelles.js"; import { RdDDice } from "./rdd-dice.js"; +import { STATUSES } from "./status-effects.js"; /* -------------------------------------------- */ export class RdDTMRDialog extends Dialog { @@ -277,15 +277,16 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - close() { - if ( this.actor.tmrApp ) { + async close() { + if (this.actor.tmrApp) { this.actor.tmrApp = undefined; // Cleanup reference - if ( !this.viewOnly ) { - this.actor.setStatusEffect("EFFECT.StatusDemiReve", false); + if (!this.viewOnly) { + await this.actor.setEffect(STATUSES.StatusDemiReve, false) this._tellToGM(this.actor.name + " a quitté les terres médianes"); } - this.actor.santeIncDec("fatigue", this.cumulFatigue).then(super.close()); // moving 1 cell costs 1 fatigue + await this.actor.santeIncDec("fatigue", this.cumulFatigue) } + await super.close(); // moving 1 cell costs 1 fatigue } /* -------------------------------------------- */ diff --git a/module/status-effects.js b/module/status-effects.js index c0f8c863..488c0e54 100644 --- a/module/status-effects.js +++ b/module/status-effects.js @@ -1,26 +1,41 @@ import { SYSTEM_RDD } from "./constants.js"; -const rddStatusEffects = [ - { rdd: true, id: 'stun', label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 }, - { rdd: true, id: 'bleeding', label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' }, - { rdd: true, id: 'prone', label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' }, - { rdd: true, id: 'grappling', tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }, - { rdd: true, id: 'grappled', tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }, - { rdd: true, id: 'restrain', label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' }, - { rdd: true, id: 'unconscious', label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' }, - { rdd: true, id: 'blind', label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' }, - { rdd: true, id: 'comma', label: 'EFFECT.StatusComma', icon: 'icons/svg/skull.svg' }, - { rdd: true, id: 'dead', label: 'EFFECT.StatusDead', icon: 'icons/svg/skull.svg' }, - { rdd: true, id: 'demi-reve', label: 'EFFECT.StatusDemiReve', icon: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd12.svg' } -]; -const demiReveStatusEffect = rddStatusEffects.find(it => it.label == 'EFFECT.StatusDemiReve'); +export const STATUSES = { + StatusStunned : 'stun', + StatusBleeding: 'bleeding', + StatusProne: 'prone', + StatusGrappling: 'grappling', + StatusGrappled: 'grappled', + StatusRestrained: 'restrain', + StatusUnconscious: 'unconscious', + StatusBlind: 'blind', + StatusComma: 'comma', + StatusDead: 'dead', + StatusDemiReve: 'demi-reve', +} -const statusDemiSurprise = new Set(['EFFECT.StatusStunned', 'EFFECT.StatusProne', 'EFFECT.StatusRestrain']); -const statusSurpriseTotale = new Set(['EFFECT.StatusUnconscious', 'EFFECT.StatusBlind', 'EFFECT.StatusComma']); +const rddStatusEffects = [ + { rdd: true, id: STATUSES.StatusStunned, label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 }, + { rdd: true, id: STATUSES.StatusBleeding, label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' }, + { rdd: true, id: STATUSES.StatusProne, label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' }, + { rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }, + { rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }, + { rdd: true, id: STATUSES.StatusRestrained, label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' }, + { rdd: true, id: STATUSES.StatusUnconscious, label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' }, + { rdd: true, id: STATUSES.StatusBlind, label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' }, + { rdd: true, id: STATUSES.StatusComma, label: 'EFFECT.StatusComma', icon: 'icons/svg/skull.svg' }, + { rdd: true, id: STATUSES.StatusDead, label: 'EFFECT.StatusDead', icon: 'icons/svg/skull.svg' }, + { rdd: true, id: STATUSES.StatusDemiReve, label: 'EFFECT.StatusDemiReve', icon: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd12.svg' } +]; +const demiReveStatusEffect = rddStatusEffects.find(it => it.id == STATUSES.StatusDemiReve); + +const statusDemiSurprise = [STATUSES.StatusStunned, STATUSES.StatusProne, STATUSES.StatusRestrained]; +const statusSurpriseTotale = [STATUSES.StatusUnconscious, STATUSES.StatusBlind, STATUSES.StatusComma]; export class StatusEffects { static onReady() { const rddStatusIds = rddStatusEffects.map(it => it.id); + rddStatusEffects.forEach(it => it.flags = { core: { statusId: it.id } }); const defaultStatusEffectIds = CONFIG.statusEffects.map(it => it.id); game.settings.register(SYSTEM_RDD, "use-status-effects", { name: "use-status-effects", @@ -47,40 +62,36 @@ export class StatusEffects { static valeurSurprise(effect, isCombat) { // const id = StatusEffects.statusId(effect); - if (statusSurpriseTotale.has(effect.label)) { + if (statusSurpriseTotale.includes(effect.flags?.core?.statusId)) { return 2; } - return statusDemiSurprise.has(effect.label) || (isCombat && effect.label == demiReveStatusEffect.label) ? 1 : 0; - } - - static setMandatoryRdd() { - CONFIG.statusEffects.filter(it => statusDemiSurprise.has(it.id) || statusSurpriseTotale.has(it.id)) - .forEach(it => it.rdd = true); + return statusDemiSurprise.includes(effect.flags?.core?.statusId) || (isCombat && effect.flags?.core?.statusId == STATUSES.StatusDemiReve) ? 1 : 0; } static _getUseStatusEffects() { const setting = game.settings.get(SYSTEM_RDD, "use-status-effects"); - return setting ? new Set(setting.split(',')) : new Set(); + return setting ? setting.split(',') : []; } - static _setUseStatusEffects(useStatusEffects) { + static _setUseStatusEffects(statusIds) { if (game.user.isGM) { - game.settings.set(SYSTEM_RDD, "use-status-effects", StatusEffects._toSetting(useStatusEffects)); + game.settings.set(SYSTEM_RDD, "use-status-effects", StatusEffects._toSetting(statusIds)); } for (let effect of CONFIG.RDD.allEffects) { - effect.active = effect.rdd || useStatusEffects.has(effect.id); + effect.active = effect.rdd || statusIds.includes(effect.flags?.core?.statusId); } CONFIG.statusEffects = CONFIG.RDD.allEffects.filter(it => it.active); } - static _toSetting(useStatusEffects) { - return Array.from(useStatusEffects).join(); + static _toSetting(statusIds) { + return statusIds.join(); } - static status(label) { - return rddStatusEffects.find(it => it.label == label) ?? { label: label }; + static status(statusId) { + return rddStatusEffects.find(it => it.flags?.core?.statusId == statusId); } + static demiReve() { return demiReveStatusEffect; } @@ -106,8 +117,10 @@ class StatusEffectsSettings extends FormApplication { } getData() { + const used = StatusEffects._getUseStatusEffects(); let formData = super.getData(); - formData.effects = CONFIG.RDD.allEffects; + formData.effects = duplicate(CONFIG.RDD.allEffects); + formData.effects.forEach(it => it.active = used.includes(it.id)) return formData; } @@ -118,10 +131,10 @@ class StatusEffectsSettings extends FormApplication { let selected = StatusEffects._getUseStatusEffects(); let isChecked = event.currentTarget.checked; if (isChecked) { - selected.add(id); + selected.push(id); } else { - selected.delete(id); + selected = selected.filter(it => it != id) } StatusEffects._setUseStatusEffects(selected); } diff --git a/templates/actor-sheet-effects-partial.html b/templates/actor-sheet-effects-partial.html index 3e4ada8f..67a93101 100644 --- a/templates/actor-sheet-effects-partial.html +++ b/templates/actor-sheet-effects-partial.html @@ -1,7 +1,7 @@ {{#if calc.surprise}}{{calc.surprise}}! {{/if}} {{#if effects}} {{#each effects as |effect key|}} - + {{localize effect.label}} {{/each}} diff --git a/templates/status-effects-settings.html b/templates/status-effects-settings.html index d1f0a757..68adcc96 100644 --- a/templates/status-effects-settings.html +++ b/templates/status-effects-settings.html @@ -7,7 +7,7 @@ {{else}} {{/if}} - {{ localize  effect.label}} + {{localize effect.label}} {{/each}}