Merge branch 'regles-optionelles' into 'v1.3'

Regles optionelles

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!135
This commit is contained in:
Leratier Bretonnien 2021-01-27 09:27:14 +00:00
commit e138ff0e13
14 changed files with 141 additions and 140 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -1,4 +1,3 @@
import { Misc } from "./misc.js";
/**
* Extend the base Dialog entity by defining a custom window to perform roll.

View File

@ -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.

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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();
});
/* -------------------------------------------- */

View File

@ -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")
}
}
}

View File

@ -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();
}
}

View File

@ -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()
},

View File

@ -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];

View File

@ -1,28 +0,0 @@
<form autocomplete="off" onsubmit="event.preventDefault();">
<ul>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-recul" {{#if recul}}checked{{/if}}/>
<label>Appliquer le recul en cas de particulière en force ou de charge</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-resistanceArmeParade" {{#if resistanceArmeParade}}checked{{/if}}/>
<label>Faire le jet de résistance des armes lors de parades pouvant les endommager</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-deteriorationArmure" {{#if deteriorationArmure}}checked{{/if}}/>
<label>Tenir compte de la détérioration des armures</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-defenseurDesarme" {{#if defenseurDesarme}}checked{{/if}}/>
<label>Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-categorieParade" {{#if categorieParade}}checked{{/if}}/>
<label>Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-tripleSignificative" {{#if tripleSignificative}}checked{{/if}}/>
<label>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</label>
</li>
</ul>
</form>

View File

@ -0,0 +1,21 @@
<form autocomplete="off" onsubmit="event.preventDefault();">
<h3>Règles de combat</h3>
<ul>
{{#each regles as |regle key|}}
{{#if (eq regle.group 'combat')}}
<li>
<input class="select-option" type="checkbox" name="{{regle.id}}" {{#if regle.active}}checked{{/if}}/>
<label>{{regle.descr}}</label>
</li>
{{/if}}
{{/each}}
<h3>Autres règles</h3>
{{#each regles as |regle key|}}
{{#if (eq regle.group 'generale')}}
<li>
<input class="select-option" type="checkbox" name="{{regle.id}}" {{#if regle.active}}checked{{/if}}/>
<label>{{regle.descr}}</label>
</li>
{{/if}}
{{/each}}
</form>