diff --git a/module/actor.js b/module/actor.js index 892266d8..47d9f374 100644 --- a/module/actor.js +++ b/module/actor.js @@ -34,6 +34,7 @@ import { DialogItemAchat } from "./dialog-item-achat.js"; import { RdDItem } from "./item.js"; import { RdDPossession } from "./rdd-possession.js"; import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; +import { RdDConfirm } from "./rdd-confirm.js"; const POSSESSION_SANS_DRACONIC = { img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp', @@ -1157,7 +1158,8 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ /** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */ async nettoyerConteneurs() { - RdDUtility.confirmer({ + RdDConfirm.confirmer({ + settingConfirmer: "confirmation-vider", content: `

Etes vous certain de vouloir vider tous les conteneurs ?

`, title: 'Vider les conteneurs', buttonLabel: 'Vider', @@ -3178,7 +3180,17 @@ export class RdDActor extends Actor { 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 } + RdDConfirm.confirmer({ + bypass: mode == 'visu', + settingConfirmer: "confirmation-tmr", + content: `

Voulez vous monter dans les TMR en mode ${mode}?

`, + title: 'Confirmer la montée dans les TMR', + buttonLabel: 'Monter dans les TMR', + onAction: async () => await this._doDisplayTMR(mode) + }); + } + async _doDisplayTMR(mode) { let isRapide = mode == "rapide"; if (mode != "visu") { let minReveValue = (isRapide && !EffetsDraconiques.isDeplacementAccelere(this) ? 3 : 2) + this.countMonteeLaborieuse(); diff --git a/module/item.js b/module/item.js index 35204f2f..48da84f1 100644 --- a/module/item.js +++ b/module/item.js @@ -18,6 +18,10 @@ const typesObjetsEquipement = [ "potion", ] const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"] +const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve"] +const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"] +const typesObjetsEffet = ["possession", "poison", "maladie"] +const typesObjetsCompetence = ["competence", "compcreature"] const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc densité 3.5 (~2.3 à 4, parfois plus) -- https://www.juwelo.fr/guide-des-pierres/faits-et-chiffres/ @@ -74,16 +78,37 @@ export class RdDItem extends Item { } isCompetence() { - return this.type == 'competence'; + return typesObjetsCompetence.includes(this.type) } - isEquipement() { return typesObjetsEquipement.includes(this.type) } + isOeuvre() { + return typesObjetsOeuvres.includes(this.type) + } + isDraconique() { + return typesObjetsDraconiques.includes(this.type) + } + isEffet() { + return typesObjetsEffet.includes(this.type) + } + isConnaissance() { + return typesObjetsConnaissance.includes(this.type) + } isConteneur() { return this.type == 'conteneur'; } + getItemGroup() { + if (this.isEquipement()) return "equipement"; + if (this.isOeuvre()) return "oeuvre"; + if (this.isDraconique()) return "draconique"; + if (this.isConnaissance()) return "connaissance"; + if (this.isEffet()) return "effet"; + if (this.isCompetence()) return "competence"; + return "autres"; + } + isConteneurNonVide() { return this.isConteneur() && (this.system.contenu?.length ?? 0) > 0; } diff --git a/module/rdd-confirm.js b/module/rdd-confirm.js new file mode 100644 index 00000000..86980b49 --- /dev/null +++ b/module/rdd-confirm.js @@ -0,0 +1,55 @@ +import { ReglesOptionelles } from "./regles-optionelles.js"; + +export class RdDConfirm { + /* -------------------------------------------- */ + static confirmer(options, autresActions) { + options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionelles.isUsing(options.settingConfirmer)); + if (options.bypass) { + options.onAction(); + } + else { + let buttons = { + "action": RdDConfirm._createButtonAction(options), + "cancel": RdDConfirm._createButtonCancel() + }; + if (options.settingConfirmer) { + buttons = mergeObject(RdDConfirm._createButtonActionSave(options), buttons); + } + if (autresActions) { + buttons = mergeObject(autresActions, buttons); + } + const dialogDetails = { + title: options.title, + content: options.content, + default: "cancel", + buttons: buttons + }; + new Dialog(dialogDetails, { width: 200 * Object.keys(buttons) }).render(true); + } + } + + static _createButtonCancel() { + return { icon: '', label: "Annuler" }; + } + + static _createButtonAction(options) { + return { + icon: '', + label: options.buttonLabel, + callback: () => options.onAction() + }; + } + + static _createButtonActionSave(options) { + return { + "actionSave": { + icon: '', + label: options.buttonLabel + "
(Ne plus demander)", + callback: () => { + ReglesOptionelles.set(options.settingConfirmer, false); + options.onAction(); + } + } + }; + } +} \ No newline at end of file diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 61a8c2a9..997e5c33 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -12,6 +12,7 @@ import { RdDItem } from "./item.js"; import { Monnaie } from "./item-monnaie.js"; import { RdDPossession } from "./rdd-possession.js"; import { RdDNameGen } from "./rdd-namegen.js"; +import { RdDConfirm } from "./rdd-confirm.js"; /* -------------------------------------------- */ // This table starts at 0 -> niveau -10 @@ -262,7 +263,7 @@ export class RdDUtility { Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord)); Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord)); Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1))); - Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option) ); + Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option)); Handlebars.registerHelper('filtreTriCompetences', competences => competences.filter(it => it.system.isVisible) .sort((a, b) => { @@ -855,36 +856,14 @@ export class RdDUtility { return chatData; } - /* -------------------------------------------- */ - static confirmer(options) { - const d = new Dialog({ - title: options.title, - content: options.content, - buttons: { - action: { - icon: '', - label: options.buttonLabel, - callback: () => { - options.onAction(); - } - }, - cancel: { - icon: '', - label: "Annuler" - } - }, - default: "cancel" - }); - d.render(true); - } - /* -------------------------------------------- */ static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete) { - RdDUtility.confirmer({ - content: `

Etes vous certain de vouloir supprimer le lien vers le véhicule/monture/suivant : ${subActor.name} ?

`, + RdDConfirm.confirmer({ + settingConfirmer: "confirmation-supprimer-lien-acteur", + content: `

Etes vous certain de vouloir supprimer le lien vers ${subActor.name} ?

`, title: 'Confirmer la suppression', buttonLabel: 'Supprimer le lien', - onAction: () => { + onAction: () => { console.log('Delete : ', subActor.id); sheet.actor.removeSubacteur(subActor.id); RdDUtility.slideOnDelete(sheet, htmlToDelete); @@ -899,47 +878,41 @@ export class RdDUtility { ui.notifications.warn("Suppression des monnaies de base impossible"); return; } - - let msgTxt = '

Etes vous certain de vouloir supprimer cet objet ?'; - let buttons = { - delete: { - icon: '', - label: "Supprimer l'objet", - callback: () => { - console.log('Delete : ', itemId); - sheet.actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false }); - RdDUtility.slideOnDelete(sheet, htmlToDelete); - } - }, - cancel: { - icon: '', - label: "Annuler" + + const confirmationSuppression = { + settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(), + content: `

Etes vous certain de vouloir supprimer: ${item.name}?

`, + title: `Supprimer ${item.name}`, + buttonLabel: "Supprimer", + onAction: () => { + console.log('Delete : ', itemId); + sheet.actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false }); + RdDUtility.slideOnDelete(sheet, htmlToDelete); } + }; + if (item.isConteneurNonVide()) { + confirmationSuppression.content += `

Ce conteneur n'est pas vide. Que voulez vous supprimer?

`; + confirmationSuppression.settingConfirmer = undefined; + RdDConfirm.confirmer(confirmationSuppression, + { + 'deleteall': { + icon: '', + label: "Supprimer conteneur et contenu", + callback: () => { + console.log("Delete : ", itemId); + sheet.actor.deleteAllConteneur(itemId, { renderSheet: false }); + RdDUtility.slideOnDelete(sheet, htmlToDelete); + } + } + }); } - if (item.type == 'conteneur' && item.system.contenu.length > 0) { - msgTxt += "
Ce conteneur n'est pas vide. Choisissez l'option de suppression"; - buttons['deleteall'] = { - icon: '', - label: "Supprimer le conteneur et tout son contenu", - callback: () => { - console.log("Delete : ", itemId); - sheet.actor.deleteAllConteneur(itemId, { renderSheet: false }); - RdDUtility.slideOnDelete(sheet, htmlToDelete); - } - } + else { + RdDConfirm.confirmer(confirmationSuppression) } - msgTxt += "

"; - let d = new Dialog({ - title: "Confirmer la suppression", - content: msgTxt, - buttons: buttons, - default: "cancel" - }); - d.render(true); } static slideOnDelete(sheet, htmlToDelete) { - return htmlToDelete.slideUp(200, () => sheet.render(false)); + return htmlToDelete.slideUp(200, () => sheet.render(false)); } /* -------------------------------------------- */ diff --git a/module/regles-optionelles.js b/module/regles-optionelles.js index 2cb29580..7dbb72b8 100644 --- a/module/regles-optionelles.js +++ b/module/regles-optionelles.js @@ -11,11 +11,22 @@ const listeReglesOptionelles = [ { name: 'degat-minimum-malus-libre-simple', group: 'Règles de combat', descr: "Le malus libre d'attaque remplace une des valeurs de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, si 1 résultat est inférieur à 4, alors il devient 4.", default: false }, { name: 'degat-minimum-malus-libre', group: 'Règles de combat', descr: "Le malus libre d'attaque remplace une valeur de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, tout résultat inférieur à 4 devient 4.", default: false }, { name: 'degat-ajout-malus-libre', group: 'Règles de combat', descr: "Le malus libre d'attaque s'ajoute au jet d'encaissement et aux autres bonus. Exemple : la difficulté libre de l'attaquant est de -4. Le jet d'encaissement est effectué à 2d10+4, plus les bonus de situation et d'armes.", default: false }, - { name: 'astrologie', group: 'Règles générales', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels", default: true }, - { name: 'afficher-prix-joueurs', group: 'Règles générales', descr: "Afficher le prix de l'équipement des joueurs", default: true, uniquementJoueur: true}, - { name: 'appliquer-fatigue', group: 'Règles générales', descr: "Appliquer les règles de fatigue", default: true }, + { name: 'astrologie', group: 'Règles générales', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels"}, + { name: 'afficher-prix-joueurs', group: 'Règles générales', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true}, + { name: 'appliquer-fatigue', group: 'Règles générales', descr: "Appliquer les règles de fatigue"}, { name: 'afficher-colonnes-reussite', group: 'Règles générales', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false }, + { name: 'confirmation-tmr', group: 'Confirmations', descr: "Confirmer pour monter dans les TMR", scope: "client"}, + { name: 'confirmation-vider', group: 'Confirmations', descr: "Confirmer pour vider l'équipement", scope: "client"}, + { name: 'confirmation-supprimer-lien-acteur', group: 'Confirmations', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"}, + { name: 'confirmation-supprimer-equipement', group: 'Confirmations', descr: "Confirmer la suppression des équipements", scope: "client"}, + { name: 'confirmation-supprimer-oeuvre', group: 'Confirmations', descr: "Confirmer la suppression des oeuvres", scope: "client"}, + { name: 'confirmation-supprimer-connaissance', group: 'Confirmations', descr: "Confirmer la suppression des connaissances", scope: "client"}, + { name: 'confirmation-supprimer-draconique', group: 'Confirmations', descr: "Confirmer la suppression des queues, souffles, têtes", scope: "client"}, + { name: 'confirmation-supprimer-effet', group: 'Confirmations', descr: "Confirmer la suppression des effets (maladie, poisons, possessions)", scope: "client"}, + { name: 'confirmation-supprimer-competence', group: 'Confirmations', descr: "Confirmer la suppression des compétences", scope: "client"}, + { name: 'confirmation-supprimer-autres', group: 'Confirmations', descr: "Confirmer la suppression des autres types d'Objets", scope: "client"}, ]; + const uniquementJoueur = listeReglesOptionelles.filter(it => it.uniquementJoueur).map(it=>it.name); export class ReglesOptionelles extends FormApplication { @@ -23,7 +34,7 @@ export class ReglesOptionelles extends FormApplication { for (const regle of listeReglesOptionelles) { const name = regle.name; const id = ReglesOptionelles._getIdRegle(name); - game.settings.register(SYSTEM_RDD, id, { name: id, scope: "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean }); + game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean }); } game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", { @@ -31,8 +42,7 @@ export class ReglesOptionelles extends FormApplication { label: "Choix des règles optionelles", hint: "Ouvre la fenêtre de sélection des règles optionelles", icon: "fas fa-bars", - type: ReglesOptionelles, - restricted: true + type: ReglesOptionelles }); } @@ -50,7 +60,7 @@ export class ReglesOptionelles extends FormApplication { id: "optional-settings", template: "systems/foundryvtt-reve-de-dragon/templates/regles-optionelles.html", height: 600, - width: 350, + width: 450, minimizable: false, closeOnSubmit: true, title: "Règles optionnelles" @@ -60,7 +70,7 @@ export class ReglesOptionelles extends FormApplication { getData() { let formData = super.getData(); - const regles = listeReglesOptionelles.map(it => { + const regles = listeReglesOptionelles.filter(it => game.user.isGM || it.scope == "client").map(it => { it = duplicate(it); it.id = ReglesOptionelles._getIdRegle(it.name); it.active = ReglesOptionelles.isUsing(it.name); @@ -78,6 +88,14 @@ export class ReglesOptionelles extends FormApplication { return game.settings.get(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name)); } + static isSet(name) { + return ReglesOptionelles.isUsing(name); + } + + static set(name, value) { + return game.settings.set(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name), value ? true: false); + } + activateListeners(html) { html.find(".select-option").click((event) => { if (event.currentTarget.attributes.name) {