diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 79880544..506278cd 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -177,6 +177,11 @@ export class RdDActorSheet extends ActorSheet { HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM); + html.find('#show-hide-competences').click((event) => { + this.options.showCompNiveauBase = !this.options.showCompNiveauBase; + this.render(true); + }); + // Everything below here is only needed if the sheet is editable if (!this.options.editable) return; @@ -396,10 +401,6 @@ export class RdDActorSheet extends ActorSheet { this.options.editCaracComp = !this.options.editCaracComp; this.render(true); }); - html.find('#show-hide-competences').click((event) => { - this.options.showCompNiveauBase = !this.options.showCompNiveauBase; - this.render(true); - }); html.find('#show-hide-archetype').click((event) => { this.options.montrerArchetype = !this.options.montrerArchetype; this.render(true); diff --git a/module/actor.js b/module/actor.js index fa0312b9..63d50001 100644 --- a/module/actor.js +++ b/module/actor.js @@ -12,7 +12,7 @@ import { ChatUtility } from "./chat-utility.js"; import { RdDItemSort } from "./item-sort.js"; import { Grammar } from "./grammar.js"; import { RdDEncaisser } from "./rdd-roll-encaisser.js"; -import { RdDCombat, RdDCombatSettings } from "./rdd-combat.js"; +import { RdDCombat } from "./rdd-combat.js"; import { DeDraconique } from "./de-draconique.js"; import { RdDAudio } from "./rdd-audio.js"; import { RdDItemCompetence } from "./item-competence.js"; @@ -20,6 +20,7 @@ import { RdDItemArme } from "./item-arme.js"; import { RdDAlchimie } from "./rdd-alchimie.js"; import { StatusEffects } from "./status-effects.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; +import { ReglesOptionelles } from "./regles-optionelles.js"; /* -------------------------------------------- */ @@ -2222,7 +2223,7 @@ export class RdDActor extends Actor { } _deteriorerArmure(item, dmg) { - if (!RdDCombatSettings.isUsingDeteriorationArmure()) { + if (!ReglesOptionelles.isUsing('deteriorationArmure')) { return; } let update = duplicate(item); diff --git a/module/grammar.js b/module/grammar.js index c840cd94..a5bb7472 100644 --- a/module/grammar.js +++ b/module/grammar.js @@ -12,7 +12,12 @@ export class Grammar { } return article + ' ' + word; } + static startsWithVoyel(word) { return word.match(/^[aeiouy]/i) } + + static toLowerCaseNoAccent(words) { + return words?.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") ?? words; + } } \ No newline at end of file diff --git a/module/rdd-astrologie-editeur.js b/module/rdd-astrologie-editeur.js index 7b539588..b09ff7c4 100644 --- a/module/rdd-astrologie-editeur.js +++ b/module/rdd-astrologie-editeur.js @@ -1,4 +1,3 @@ -import { Misc } from "./misc.js"; /** * Extend the base Dialog entity by defining a custom window to perform roll. diff --git a/module/rdd-astrologie-joueur.js b/module/rdd-astrologie-joueur.js index ab612adb..eccad906 100644 --- a/module/rdd-astrologie-joueur.js +++ b/module/rdd-astrologie-joueur.js @@ -1,7 +1,5 @@ import { RdDItemCompetence } from "./item-competence.js"; -import { Misc } from "./misc.js"; -import { RdDCalendrier } from "./rdd-calendrier.js"; -import { RdDUtility } from "./rdd-utility.js"; + /** * Extend the base Dialog entity by defining a custom window to perform roll. diff --git a/module/rdd-calendrier.js b/module/rdd-calendrier.js index b1a13ebd..18facb1e 100644 --- a/module/rdd-calendrier.js +++ b/module/rdd-calendrier.js @@ -4,6 +4,7 @@ import { RdDAstrologieEditeur } from "./rdd-astrologie-editeur.js"; import { HtmlUtility } from "./html-utility.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDUtility } from "./rdd-utility.js"; +import { Grammar } from "./grammar.js"; /* -------------------------------------------- */ const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/' @@ -274,8 +275,9 @@ export class RdDCalendrier extends Application { /* -------------------------------------------- */ getAjustementAstrologique(heureNaissance, name='inconnu') { - if (heureNaissance && heuresDef[heureNaissance]) { - let hn = heuresDef[heureNaissance].heure; + let heure = Grammar.toLowerCaseNoAccent(heureNaissance); + if (heure && heuresDef[heure]) { + let hn = heuresDef[heure].heure; let chiffreAstral = this.getCurrentNombreAstral(); let heureCourante = this.calendrier.heureRdD; let ecartChance = (hn + chiffreAstral - heureCourante)%12; diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 99fd9402..35af36ed 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -7,11 +7,11 @@ import { RdDBonus } from "./rdd-bonus.js"; 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"; export class RdDCombat { static init() { - RdDCombatSettings.onInit(); this.initStorePasseArmes(); Hooks.on("updateCombat", (combat, data) => { RdDCombat.onUpdateCombat(combat, data) }); Hooks.on("preDeleteCombat", (combat, options) => { RdDCombat.onPreDeleteCombat(combat, options); }); @@ -606,7 +606,7 @@ export class RdDCombat { competence: this.defender.getCompetence(compName), arme: armeParade, surprise: this.defender.getSurprise(true), - needParadeSignificative: RdDCombatSettings.isUsingCategorieParade() && RdDItemArme.needParadeSignificative(armeAttaque, armeParade), + needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(armeAttaque, armeParade), needResist: RdDItemArme.needArmeResist(armeAttaque, armeParade), carac: this.defender.data.data.carac, show: {} @@ -632,7 +632,7 @@ export class RdDCombat { if (RdDBonus.isDefenseAttaqueFinesse(defenderRoll)) { facteurSign *= 2; } - if (!RdDCombatSettings.isUsingTripleSignificative()) { + if (!ReglesOptionelles.isUsing('tripleSignificative')) { facteurSign = Math.min(facteurSign, 4); } return facteurSign; @@ -744,7 +744,7 @@ export class RdDCombat { /* -------------------------------------------- */ async computeDeteriorationArme(rollData) { - if (!RdDCombatSettings.isUsingResistanceArmeParade()) { + if (!ReglesOptionelles.isUsing('resistanceArmeParade')) { return; } const attackerRoll = rollData.attackerRoll; @@ -778,7 +778,7 @@ export class RdDCombat { } } // Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132) - if (RdDCombatSettings.isUsingDefenseurDesarme() && resistance > 0 && RdDItemArme.getCategorieParade(rollData.arme) != 'boucliers') { + if (ReglesOptionelles.isUsing('defenseurDesarme') && resistance > 0 && RdDItemArme.getCategorieParade(rollData.arme) != 'boucliers') { let desarme = await RdDResolutionTable.rollData({ caracValue: this.defender.getForce(), finalLevel: Misc.toInt(rollData.competence.data.niveau) - dmg, @@ -793,7 +793,7 @@ export class RdDCombat { /* -------------------------------------------- */ async computeRecul(defenderRoll) { // Calcul du recul (p. 132) const attackerRoll = defenderRoll.attackerRoll; - if (RdDCombatSettings.isUsingRecul() && this._isAttaqueCauseRecul(attackerRoll)) { + if (ReglesOptionelles.isUsing('recul') && this._isAttaqueCauseRecul(attackerRoll)) { const impact = this._computeImpactRecul(attackerRoll); const rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impact }); if (rollRecul.rolled.isSuccess) { @@ -916,91 +916,3 @@ export class RdDCombat { }); } } - -export class RdDCombatSettings extends FormApplication { - static onInit() { - game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-recul", { name: "rdd-combat-recul", scope: "world", config: false, default: true, type: Boolean }); - game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-resistanceArmeParade", { name: "rdd-combat-resistanceArmeParade", scope: "world", config: false, default: true, type: Boolean }); - game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-deteriorationArmure", { name: "rdd-combat-deteriorationArmure", scope: "world", config: false, default: true, type: Boolean }); - game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-defenseurDesarme", { name: "rdd-combat-defenseurDesarme", scope: "world", config: false, default: true, type: Boolean }); - game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-categorieParade", { name: "rdd-combat-categorieParade", scope: "world", config: false, default: true, type: Boolean }); - game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-tripleSignificative", { name: "rdd-combat-tripleSignificative", scope: "world", config: false, default: true, type: Boolean }); - - game.settings.registerMenu("foundryvtt-reve-de-dragon", "rdd-combat-options", { - name: "Choisir les options de combat", - label: "Choix des options de combat", - hint: "Ouvre la fenêtre de sélection des options de combats pour désactiver certaines règles", - icon: "fas fa-bars", - type: RdDCombatSettings, - restricted: true - }); - } - - constructor(...args) { - super(...args); - } - - static get defaultOptions() { - const options = super.defaultOptions; - mergeObject(options, { - id: "combat-settings", - template: "systems/foundryvtt-reve-de-dragon/templates/combat-settings.html", - height: 600, - width: 350, - minimizable: false, - closeOnSubmit: true, - title: "Options de combat" - }); - return options; - } - - getData() { - let data = super.getData(); - data.recul = RdDCombatSettings.isUsingRecul(); - data.resistanceArmeParade = RdDCombatSettings.isUsingResistanceArmeParade(); - data.deteriorationArmure = RdDCombatSettings.isUsingDeteriorationArmure(); - data.defenseurDesarme = RdDCombatSettings.isUsingDefenseurDesarme(); - data.categorieParade = RdDCombatSettings.isUsingCategorieParade(); - data.tripleSignificative = RdDCombatSettings.isUsingTripleSignificative(); - return data; - } - - static isUsingRecul() { - return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-recul"); - } - - static isUsingResistanceArmeParade() { - return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-resistanceArmeParade"); - } - - static isUsingDeteriorationArmure() { - return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-deteriorationArmure"); - } - - static isUsingDefenseurDesarme() { - return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-defenseurDesarme"); - } - - static isUsingCategorieParade() { - return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-categorieParade"); - } - - static isUsingTripleSignificative() { - return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-tripleSignificative"); - } - - activateListeners(html) { - html.find(".select-option").click((event) => { - if (event.currentTarget.attributes.name) { - let id = event.currentTarget.attributes.name.value; - let isChecked = event.currentTarget.checked; - game.settings.set("foundryvtt-reve-de-dragon", id, isChecked); - } - }); - } - - async _updateObject(event, formData) { - this.close(); - } -} - diff --git a/module/rdd-main.js b/module/rdd-main.js index d06d66ad..cb47fd2e 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -25,6 +25,7 @@ import { ChatUtility } from "./chat-utility.js"; import { RdDItemCompetence } from "./item-competence.js"; import { StatusEffects } from "./status-effects.js"; import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js"; +import { ReglesOptionelles } from "./regles-optionelles.js"; /* -------------------------------------------- */ /* Foundry VTT Initialization */ @@ -222,6 +223,7 @@ Hooks.once("init", async function () { RdDTokenHud.init(); RdDActor.init(); RddCompendiumOrganiser.init(); + ReglesOptionelles.init(); }); /* -------------------------------------------- */ diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 0e11e0bb..f3291c69 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -926,11 +926,16 @@ export class RdDUtility { /* -------------------------------------------- */ static afficherHeuresChanceMalchance( heureNaissance ) { - let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance.toLowerCase()); - ChatMessage.create( { - content: `Pour l'heure ${game.system.rdd.calendrier.getCurrentHeure()}, le modificateur de Chance/Malchance est de : ${ajustement}.`, - whisper: ChatMessage.getWhisperRecipients("MJ") + if (heureNaissance) { + let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance); + ChatMessage.create( { + content: `A l'heure ${game.system.rdd.calendrier.getCurrentHeure()}, le modificateur de Chance/Malchance pour l'heure de naissance ${heureNaissance} est de : ${ajustement}.`, + whisper: ChatMessage.getWhisperRecipients("MJ") } ); + } + else{ + ui.notifications.warn("Pas d'heure de naissance selectionnée") + } } } diff --git a/module/regles-optionelles.js b/module/regles-optionelles.js new file mode 100644 index 00000000..c300008e --- /dev/null +++ b/module/regles-optionelles.js @@ -0,0 +1,81 @@ + +const listeReglesOptionelles = [ + {name:'recul', group:'combat', descr:"Appliquer le recul en cas de particulière en force ou de charge"}, + {name:'resistanceArmeParade', group:'combat', descr:"Faire le jet de résistance des armes lors de parades pouvant les endommager"}, + {name:'deteriorationArmure', group:'combat', descr:"Tenir compte de la détérioration des armures"}, + {name:'defenseurDesarme', group:'combat', descr:"Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier"}, + {name:'categorieParade', group:'combat', descr:"Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes"}, + {name:'tripleSignificative', group:'combat', descr:"En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès"}, + {name:'astrologie', group:'generale', descr:"Appliquer les ajustements astrologiques aux jets de chance et aux rituels"} +]; + +export class ReglesOptionelles extends FormApplication { + static init() { + for (const regle of listeReglesOptionelles) { + const name = regle.name; + const id = ReglesOptionelles._getIdRegle(name); + game.settings.register("foundryvtt-reve-de-dragon", id, { name: id, scope: "world", config: false, default: regle.default??true, type: Boolean }); + } + + game.settings.registerMenu("foundryvtt-reve-de-dragon", "rdd-options-regles", { + name: "Choisir les règles optionelles", + 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 + }); + } + + constructor(...args) { + super(...args); + } + + static _getIdRegle(name) { + return `rdd-option-${name}`; + } + + static get defaultOptions() { + const options = super.defaultOptions; + mergeObject(options, { + id: "combat-settings", + template: "systems/foundryvtt-reve-de-dragon/templates/regles-optionelles.html", + height: 600, + width: 350, + minimizable: false, + closeOnSubmit: true, + title: "Options de combat" + }); + return options; + } + + getData() { + let data = super.getData(); + data.regles = listeReglesOptionelles.map(it => { + let r = duplicate(it); + r.id = ReglesOptionelles._getIdRegle(r.name); + r.active = ReglesOptionelles.isUsing(r.name); + return r; + }) + return data; + } + + static isUsing(name) { + return game.settings.get("foundryvtt-reve-de-dragon", ReglesOptionelles._getIdRegle(name)); + } + + activateListeners(html) { + html.find(".select-option").click((event) => { + if (event.currentTarget.attributes.name) { + let id = event.currentTarget.attributes.name.value; + let isChecked = event.currentTarget.checked; + game.settings.set("foundryvtt-reve-de-dragon", id, isChecked); + } + }); + } + + async _updateObject(event, formData) { + this.close(); + } +} + diff --git a/module/rolldata-ajustements.js b/module/rolldata-ajustements.js index 1929f7ef..e432fec1 100644 --- a/module/rolldata-ajustements.js +++ b/module/rolldata-ajustements.js @@ -5,6 +5,7 @@ import { RdDItemSort } from "./item-sort.js"; import { Misc } from "./misc.js"; import { RdDBonus } from "./rdd-bonus.js"; import { RdDCarac } from "./rdd-carac.js"; +import { ReglesOptionelles } from "./regles-optionelles.js"; /** * tous les ajustements pouvant s'appliquer. @@ -83,7 +84,7 @@ export const referenceAjustements = { getValue: (rollData, actor) => actor.getMoralTotal() }, astrologique: { - isUsed: (rollData, actor) => RdDBonus.isAjustementAstrologique(rollData), + isUsed: (rollData, actor) => ReglesOptionelles.isUsing("astrologie") && RdDBonus.isAjustementAstrologique(rollData), getLabel: (rollData, actor) => 'Astrologique', getValue: (rollData, actor) => actor.ajustementAstrologique() }, diff --git a/module/tmr-utility.js b/module/tmr-utility.js index ebde45cb..bef288ca 100644 --- a/module/tmr-utility.js +++ b/module/tmr-utility.js @@ -1,4 +1,5 @@ import { DeDraconique } from "./de-draconique.js"; +import { Grammar } from "./grammar.js"; /* -------------------------------------------- */ const TMRMapping = { @@ -383,7 +384,7 @@ export class TMRUtility { roll = new Roll("1d100").roll().total; console.log("rencontreTMRTypeCase", roll); } - typeTMR = typeTMR.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, ""); + typeTMR = Grammar.toLowerCaseNoAccent(typeTMR); for( let rencontre of rencontresTable) { console.log("TMR !!!", typeTMR, roll); let scoreDef = rencontre.data[typeTMR]; diff --git a/templates/combat-settings.html b/templates/combat-settings.html deleted file mode 100644 index 0da10f9d..00000000 --- a/templates/combat-settings.html +++ /dev/null @@ -1,28 +0,0 @@ -
- -
\ No newline at end of file diff --git a/templates/regles-optionelles.html b/templates/regles-optionelles.html new file mode 100644 index 00000000..47e97354 --- /dev/null +++ b/templates/regles-optionelles.html @@ -0,0 +1,21 @@ +
+

Règles de combat

+