Message pour maîtrise Fleuve de l'Oubli

This commit is contained in:
Vincent Vandemeulebrouck 2021-02-06 21:53:25 +01:00
parent 4b88efa999
commit 863fc65844
11 changed files with 551 additions and 431 deletions

View File

@ -18,6 +18,23 @@ export class Grammar {
} }
static toLowerCaseNoAccent(words) { static toLowerCaseNoAccent(words) {
return words?.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") ?? words; return words?.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") ?? words;
}
static articleDetermine(genre) {
switch (genre?.toLowerCase()) {
case 'f': case 'feminin': return 'la';
case 'p': case 'pluriel': return 'les';
default:
case 'm': case 'masculin': return 'le';
}
}
static articleIndétermine(genre) {
switch (genre?.toLowerCase()) {
case 'f': case 'feminin': return 'une';
case 'p': case 'pluriel': return 'des';
case 'n': case 'neutre': return 'du'
default:
case 'm': case 'masculin': return 'un';
}
} }
} }

View File

@ -68,13 +68,13 @@ export class RdDItemSort extends Item {
let list = []; let list = [];
let caseCheck = {}; let caseCheck = {};
for(let i=0; i<formData.bonusValue.length; i++) { for(let i=0; i<formData.bonusValue.length; i++) {
let caseTMR = formData.caseValue[i] || 'A1'; let coord = formData.caseValue[i] || 'A1';
caseTMR = caseTMR.toUpperCase(); coord = coord.toUpperCase();
if ( TMRUtility.verifyTMRCoord( caseTMR ) ) { // Sanity check if ( TMRUtility.verifyTMRCoord( coord ) ) { // Sanity check
let bonus = formData.bonusValue[i] || 0; let bonus = formData.bonusValue[i] || 0;
if ( bonus > 0 && caseCheck[caseTMR] == undefined ) { if ( bonus > 0 && caseCheck[coord] == undefined ) {
caseCheck[caseTMR] = bonus; caseCheck[coord] = bonus;
list.push( caseTMR+":"+bonus ); list.push( coord+":"+bonus );
} }
} }
} }
@ -86,21 +86,21 @@ export class RdDItemSort extends Item {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static incrementBonusCase( actor, sort, coordTMR ) { static incrementBonusCase( actor, sort, coord ) {
let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false); let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false);
//console.log("ITEMSORT", sort, bonusCaseList); //console.log("ITEMSORT", sort, bonusCaseList);
let found = false; let found = false;
let StringList = []; let StringList = [];
for( let bc of bonusCaseList) { for( let bc of bonusCaseList) {
if (bc.case == coordTMR) { // Case existante if (bc.case == coord) { // Case existante
found = true; found = true;
bc.bonus = Number(bc.bonus) + 1; bc.bonus = Number(bc.bonus) + 1;
} }
StringList.push( bc.case+':'+bc.bonus ); StringList.push( bc.case+':'+bc.bonus );
} }
if ( !found) { //Nouvelle case, bonus de 1 if ( !found) { //Nouvelle case, bonus de 1
StringList.push(coordTMR+':1'); StringList.push(coord+':1');
} }
// Sauvegarde/update // Sauvegarde/update
@ -110,10 +110,10 @@ export class RdDItemSort extends Item {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getCaseBonus( sort, coordTMR) { static getCaseBonus( sort, coord) {
let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false); let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false);
for( let bc of bonusCaseList) { for( let bc of bonusCaseList) {
if (bc.case == coordTMR) { // Case existante if (bc.case == coord) { // Case existante
return Number(bc.bonus); return Number(bc.bonus);
} }
} }

View File

@ -4,12 +4,14 @@
*/ */
import { RollDataAjustements } from "./rolldata-ajustements.js"; import { RollDataAjustements } from "./rolldata-ajustements.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { TMRUtility } from "./tmr-utility.js"; import { poesieCaseHumide, TMRUtility } from "./tmr-utility.js";
import { tmrConstants } from "./tmr-utility.js"; import { tmrConstants } from "./tmr-utility.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDTMRRencontreDialog } from "./rdd-tmr-rencontre-dialog.js"; import { RdDTMRRencontreDialog } from "./rdd-tmr-rencontre-dialog.js";
import { TMRRencontres } from "./tmr-rencontres.js"; import { TMRRencontres } from "./tmr-rencontres.js";
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import { RdDRoll } from "./rdd-roll.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDTMRDialog extends Dialog { export class RdDTMRDialog extends Dialog {
@ -70,16 +72,16 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
displaySpecificCase() { displaySpecificCase() {
for (let caseTMR of this.casesSpeciales) { for (let caseSpeciale of this.casesSpeciales) {
console.log("SPEC CASE ", caseTMR); console.log("SPEC CASE ", caseSpeciale);
if (caseTMR.data.specific == 'trounoir') { if (caseSpeciale.data.specific == 'trounoir') {
this._trackToken(this._tokenTrouNoir(caseTMR.data.coord)); this._trackToken(this._tokenTrouNoir(caseSpeciale.data.coord));
} else if (caseTMR.data.specific == 'attache') { } else if (caseSpeciale.data.specific == 'attache') {
this._trackToken(this._tokenTerreAttache(caseTMR.data.coord)); this._trackToken(this._tokenTerreAttache(caseSpeciale.data.coord));
} else if (caseTMR.data.specific == 'debordement') { } else if (caseSpeciale.data.specific == 'debordement') {
this._trackToken(this._tokenDebordement(caseTMR.data.coord)); this._trackToken(this._tokenDebordement(caseSpeciale.data.coord));
} else if (caseTMR.data.specific == 'maitrisee') { } else if (caseSpeciale.data.specific == 'maitrisee') {
this._trackToken(this._tokenMaitrisee(caseTMR.data.coord)); this._trackToken(this._tokenMaitrisee(caseSpeciale.data.coord));
} }
} }
} }
@ -208,6 +210,7 @@ export class RdDTMRDialog extends Dialog {
competence: this.actor.getBestDraconic(), competence: this.actor.getBestDraconic(),
rencontre: this.currentRencontre, rencontre: this.currentRencontre,
nbRounds: 1, nbRounds: 1,
canClose: false,
tmr: TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord) tmr: TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord)
} }
@ -299,19 +302,25 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _jetDeRencontre(tmr) { async _jetDeRencontre(tmr) {
if (TMRUtility.isForceRencontre()) {
return await TMRUtility.rencontreTMRRoll(tmr.coord, tmr);
}
let rencontre = this.rencontresExistantes.find(prev => prev.coord == tmr.coord); let rencontre = this.rencontresExistantes.find(prev => prev.coord == tmr.coord);
if (rencontre) { if (rencontre) {
return rencontre; return rencontre;
} }
let myRoll = new Roll("1d7").evaluate(); let myRoll = new Roll("1d7").evaluate().total;
if (myRoll.total == 7) { if (TMRUtility.isForceRencontre() || myRoll== 7) {
let isMauvaise = this.actor.isRencontreSpeciale(); return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
return await TMRUtility.rencontreTMRRoll(tmr.coord, tmr, isMauvaise);
} }
this._tellToUser(myRoll.total + ": Pas de rencontre en " + tmr.label + " (" + tmr.coord + ")"); this._tellToUser(myRoll + ": Pas de rencontre en " + tmr.label + " (" + tmr.coord + ")");
}
/* -------------------------------------------- */
async rencontreTMRRoll(tmr, isMauvaise = false) {
let rencontre = TMRUtility.utiliseForceRencontre() ??
isMauvaise ? await TMRRencontres.getMauvaiseRencontre()
: await TMRRencontres.getRencontreAleatoire(tmr.type);
rencontre.coord = tmr.coord;
return rencontre;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -352,79 +361,27 @@ export class RdDTMRDialog extends Dialog {
} }
} }
/* -------------------------------------------- */
isCaseMaitrisee(coordTMR) {
return this.casesSpeciales.find(it => it.data.coord = coordTMR && it.data.specific == 'maitrisee');
}
/* -------------------------------------------- */
manageCaseHumideResult() {
if (this.toclose)
this.close();
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async manageCaseHumide(tmr) { async manageCaseHumide(tmr) {
if (this.viewOnly || this.currentRencontre) { if (this.viewOnly || this.currentRencontre) {
return; return;
} }
if (this.isCaseHumide(tmr)) { if (this.isCaseHumide(tmr)) {
// TODO: permettre de choisir la voie de draconic? let rollData = {
let draconic = this.actor.getBestDraconic(); actor: this.actor,
competence: duplicate(this.actor.getBestDraconic()),
tmr: tmr,
canClose: false,
diffLibre: -7,
forceCarac: { "reveactuel": { label: "Rêve Actuel", value: this.actor.getReveActuel() } }
}
rollData.competence.data.defaut_carac = "reveactuel";
let carac = this.actor.getReveActuel(); await this._rollMaitriseCaseHumide(rollData);
const etatGeneral = this.actor.getEtatGeneral();
let difficulte = draconic.data.niveau - 7;
let rolled = await RdDResolutionTable.roll(carac, difficulte);
// Gestion du souffle Double Résistance du Fleuve
if (this.actor.isDoubleResistanceFleuve()) {
let rolled2 = await RdDResolutionTable.roll(carac, difficulte);
if (rolled2.isEchec)
rolled = rolled;
}
console.log("manageCaseHumide >>", rolled);
let explication = "";
let msg2MJ = "";
this.toclose = rolled.isEchec;
if (rolled.isEchec) {
explication += "Vous êtes entré sur une case humide, et vous avez <strong>raté</strong> votre maîtrise ! Vous <strong>quittez les Terres Médianes</strong> !"
msg2MJ += game.user.name + " est rentré sur une case humides : Echec !";
}
else {
explication += "Vous êtes entré sur une case humide, et vous avez <strong>réussi</strong> votre maîtrise !"
msg2MJ += game.user.name + " est rentré sur une case humides : Réussite !";
}
explication += "<br><strong>Test : Rêve actuel / " + draconic.name + " / " + tmr.type + "</strong>"
+ RdDResolutionTable.explain(rolled);
if (rolled.isETotal) {
let souffle = await this.actor.ajouterSouffle({ chat: false });
explication += "<br>Vous avez fait un Echec Total. Vous subissez un Souffle de Dragon : " + souffle.name;
msg2MJ += "<br>Et a reçu un Souffle de Dragon : " + souffle.name;
}
if (rolled.isPart) {
explication += "<br>Vous avez fait une Réussite Particulière";
this.actor._appliquerAjoutExperience({ rolled: rolled, selectedCarac: { label: 'reve' }, competence: draconic.name })
msg2MJ += "<br>Et a fait une réussite particulière";
}
// Notification au MJ
ChatMessage.create({ content: msg2MJ, whisper: ChatMessage.getWhisperRecipients("GM") });
// Et au joueur (ca pourrait être un message de tchat d'ailleurs)
let humideDiag = new Dialog({
title: "Case humide",
content: explication,
buttons: {
choice: { icon: '<i class="fas fa-check"></i>', label: "Fermer", callback: () => this.manageCaseHumideResult() }
}
}
);
humideDiag.render(true);
} }
} }
/* -------------------------------------------- */
isCaseHumide(tmr) { isCaseHumide(tmr) {
if (this.isCaseMaitrisee(tmr.coord)) { if (this.isCaseMaitrisee(tmr.coord)) {
ChatMessage.create({ ChatMessage.create({
@ -439,6 +396,60 @@ export class RdDTMRDialog extends Dialog {
return tmr.type == "lac" || tmr.type == "fleuve" || tmr.type == "marais"; return tmr.type == "lac" || tmr.type == "fleuve" || tmr.type == "marais";
} }
/* -------------------------------------------- */
isCaseMaitrisee(coordTMR) {
return this.casesSpeciales.find(it => it.data.coord = coordTMR && it.data.specific == 'maitrisee');
}
async _rollMaitriseCaseHumide(rollData) {
this.minimize(); // Hide
const dialog = await RdDRoll.create(this.actor, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-tmr-humide.html',
options:{ height: 350 },
close: html => { this.maximize(); } // Re-display TMR
},
{
name: 'maitrise',
label: 'Maîtriser le fleuve',
callbacks: [
this.actor.createCallbackExperience(),
{ action: r => this._maitriseCaseHumide(r) }
]
}
);
dialog.render(true);
}
async _maitriseCaseHumide(rollData) {
if (rollData.rolled.isETotal) {
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
}
this.toclose = rollData.rolled.isEchec;
if (rollData.rolled.isSuccess) {
if (!rollData.previous && this.actor.isDoubleResistanceFleuve()) {
ChatMessage.create({
content: `Double résistance du fleuve: `,
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name)
});
rollData.previous = [rollData.rolled];
await this._rollMaitriseCaseHumide(rollData);
return;
}
}
rollData.poesie = poesieCaseHumide[new Roll("1d" + poesieCaseHumide.length).evaluate().total - 1];
const whisperTo = ChatUtility.getWhisperRecipientsAndGMs(game.user.name);
const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-fleuve-tmr.html`, rollData);
ChatMessage.create({
whisper: whisperTo,
content: content
});
if (rollData.rolled.isEchec) {
this.close();
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
isReserveExtensible(coordTMR) { isReserveExtensible(coordTMR) {
for (let caseTMR of this.casesSpeciales) { for (let caseTMR of this.casesSpeciales) {
@ -625,7 +636,7 @@ export class RdDTMRDialog extends Dialog {
if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/...
await this.manageRencontre(tmr, () => this.postRencontre(tmr)); await this.manageRencontre(tmr, () => this.postRencontre(tmr));
} }
else{ else {
await this.postRencontre(tmr); await this.postRencontre(tmr);
} }
} }

View File

@ -8,6 +8,7 @@ import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { RdDItemArme } from "./item-arme.js"; import { RdDItemArme } from "./item-arme.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { Grammar } from "./grammar.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const categorieCompetences = { const categorieCompetences = {
@ -96,7 +97,6 @@ function _buildAllSegmentsFatigue(max) {
ligneFatigue[caseIncrementee + 6]++; ligneFatigue[caseIncrementee + 6]++;
ligneFatigue.fatigueMax = 2 * (i + 1); ligneFatigue.fatigueMax = 2 * (i + 1);
fatigue[i + 1] = ligneFatigue; fatigue[i + 1] = ligneFatigue;
} }
return fatigue; return fatigue;
} }
@ -253,13 +253,10 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html' 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html'
]; ];
Handlebars.registerHelper('upperFirst', function (str) { Handlebars.registerHelper('upperFirst', str=> Misc.upperFirst(str ?? 'Null'));
return Misc.upperFirst(str ?? 'null') Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? 'NULL' );
}) Handlebars.registerHelper('le', str => Grammar.articleDetermine(str) );
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str) );
Handlebars.registerHelper('upper', function (str) {
return str?.toUpperCase() ?? 'NULL'
})
return loadTemplates(templatePaths); return loadTemplates(templatePaths);
} }

View File

@ -248,44 +248,44 @@ const typeRencontres = {
/* -------------------------------------------- */ /* -------------------------------------------- */
const mauvaisesRencontres = [ const mauvaisesRencontres = [
{ code: "mangeur1d6", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6", refoulement: 2, isMauvaise: true }, { code: "mangeur", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6", refoulement: 2, isMauvaise: true },
{ code: "mangeur2d6", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "2d6", refoulement: 2, isMauvaise: true }, { code: "mangeur2d6", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "2d6", refoulement: 2, isMauvaise: true },
{ code: "reflet2d6+4", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true }, { code: "reflet+4", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true },
{ code: "tbblanc2d6+4", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true }, { code: "tbblanc+4", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true },
{ code: "tbnoir2d8+4", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8+4", refoulement: 2, isPersistant: true, isMauvaise: true }, { code: "tbnoir+4", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8+4", refoulement: 2, isPersistant: true, isMauvaise: true },
{ code: "passfou2d8", name: "Passeur fou", type: "passeurfou", genre: "m", force: "2d8", refoulement: 2, isMauvaise: true }, { code: "passfou2d8", name: "Passeur fou", type: "passeurfou", genre: "m", force: "2d8", refoulement: 2, isMauvaise: true },
{ code: "tbrouge2d8", name: "Tourbillon rouge", type: "tbrouge", genre: "m", force: "2d8", refoulement: 3, isPersistant: true, isMauvaise: true } { code: "tbrouge2d8", name: "Tourbillon rouge", type: "tbrouge", genre: "m", force: "2d8", refoulement: 3, isPersistant: true, isMauvaise: true }
] ]
/* -------------------------------------------- */ /* -------------------------------------------- */
const rencontresStandard = [ const rencontresStandard = [
{ code: "messager2d4", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d4", ignorer: true }, { code: "messager", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d4", ignorer: true },
{ code: "passeur2d4", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d4", ignorer: true }, { code: "passeur", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d4", ignorer: true },
{ code: "fleur1d6", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "1d6", ignorer: true }, { code: "fleur", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "1d6", ignorer: true },
{ code: "mangeur1d6", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6" }, { code: "mangeur", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6" },
{ code: "changeur2d6", name: "Changeur de Rêve", type: "changeur", genre: "m", force: "2d6" }, { code: "changeur", name: "Changeur de Rêve", type: "changeur", genre: "m", force: "2d6" },
{ code: "briseur2d6", name: "Briseur de Rêve", type: "briseur", genre: "m", force: "2d6", quitterTMR: true }, { code: "briseur", name: "Briseur de Rêve", type: "briseur", genre: "m", force: "2d6", quitterTMR: true },
{ code: "reflet1d6", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6", isPersistant: true }, { code: "reflet", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6", isPersistant: true },
{ code: "tbblanc2d6", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6", isPersistant: true }, { code: "tbblanc", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6", isPersistant: true },
{ code: "tbnoir2d8", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8", isPersistant: true }, { code: "tbnoir", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8", isPersistant: true },
{ code: "rdd1ddr+7", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1ddr + 7", refoulement: 2, quitterTMR: true } { code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1ddr + 7", refoulement: 2, quitterTMR: true }
]; ];
const tableRencontres = { const tableRencontres = {
cite: [{ code: 'messager2d4', range: [1, 25] }, { code: 'passeur2d4', range: [26, 50] }, { code: 'fleur1d6', range: [51, 65] }, { code: 'mangeur1d6', range: [66, 70] }, { code: 'changeur2d6', range: [71, 80] }, { code: 'briseur2d6', range: [81, 85] }, { code: 'reflet2d6', range: [86, 90] }, { code: 'tbblanc2d6', range: [91, 94] }, { code: 'tbnoir2d8', range: [95, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], cite: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }],
sanctuaire: [{ code: 'messager2d4', range: [1, 25] }, { code: 'passeur2d4', range: [26, 50] }, { code: 'fleur1d6', range: [51, 65] }, { code: 'mangeur1d6', range: [66, 70] }, { code: 'changeur2d6', range: [71, 80] }, { code: 'briseur2d6', range: [81, 85] }, { code: 'reflet2d6', range: [86, 90] }, { code: 'tbblanc2d6', range: [91, 94] }, { code: 'tbnoir2d8', range: [95, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], sanctuaire: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }],
plaines: [{ code: 'messager2d4', range: [1, 20] }, { code: 'passeur2d4', range: [21, 40] }, { code: 'fleur1d6', range: [41, 55] }, { code: 'mangeur1d6', range: [56, 60] }, { code: 'changeur2d6', range: [61, 75] }, { code: 'briseur2d6', range: [76, 82] }, { code: 'reflet2d6', range: [83, 88] }, { code: 'tbblanc2d6', range: [89, 93] }, { code: 'tbnoir2d8', range: [94, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], plaines: [{ code: 'messager', range: [1, 20] }, { code: 'passeur', range: [21, 40] }, { code: 'fleur', range: [41, 55] }, { code: 'mangeur', range: [56, 60] }, { code: 'changeur', range: [61, 75] }, { code: 'briseur', range: [76, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
pont: [{ code: 'messager2d4', range: [1, 20] }, { code: 'passeur2d4', range: [21, 40] }, { code: 'fleur1d6', range: [41, 55] }, { code: 'mangeur1d6', range: [56, 60] }, { code: 'changeur2d6', range: [61, 75] }, { code: 'briseur2d6', range: [76, 82] }, { code: 'reflet2d6', range: [83, 88] }, { code: 'tbblanc2d6', range: [89, 93] }, { code: 'tbnoir2d8', range: [94, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], pont: [{ code: 'messager', range: [1, 20] }, { code: 'passeur', range: [21, 40] }, { code: 'fleur', range: [41, 55] }, { code: 'mangeur', range: [56, 60] }, { code: 'changeur', range: [61, 75] }, { code: 'briseur', range: [76, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
collines: [{ code: 'messager2d4', range: [1, 15] }, { code: 'passeur2d4', range: [16, 30] }, { code: 'fleur1d6', range: [31, 42] }, { code: 'mangeur1d6', range: [43, 54] }, { code: 'changeur2d6', range: [55, 69] }, { code: 'briseur2d6', range: [70, 82] }, { code: 'reflet2d6', range: [83, 88] }, { code: 'tbblanc2d6', range: [89, 93] }, { code: 'tbnoir2d8', range: [94, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], collines: [{ code: 'messager', range: [1, 15] }, { code: 'passeur', range: [16, 30] }, { code: 'fleur', range: [31, 42] }, { code: 'mangeur', range: [43, 54] }, { code: 'changeur', range: [55, 69] }, { code: 'briseur', range: [70, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
foret: [{ code: 'messager2d4', range: [1, 15] }, { code: 'passeur2d4', range: [16, 30] }, { code: 'fleur1d6', range: [31, 42] }, { code: 'mangeur1d6', range: [43, 54] }, { code: 'changeur2d6', range: [55, 69] }, { code: 'briseur2d6', range: [70, 82] }, { code: 'reflet2d6', range: [83, 88] }, { code: 'tbblanc2d6', range: [89, 93] }, { code: 'tbnoir2d8', range: [94, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], foret: [{ code: 'messager', range: [1, 15] }, { code: 'passeur', range: [16, 30] }, { code: 'fleur', range: [31, 42] }, { code: 'mangeur', range: [43, 54] }, { code: 'changeur', range: [55, 69] }, { code: 'briseur', range: [70, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
monts: [{ code: 'messager2d4', range: [1, 10] }, { code: 'passeur2d4', range: [11, 20] }, { code: 'fleur1d6', range: [21, 26] }, { code: 'mangeur1d6', range: [27, 44] }, { code: 'changeur2d6', range: [45, 59] }, { code: 'briseur2d6', range: [60, 75] }, { code: 'reflet2d6', range: [76, 85] }, { code: 'tbblanc2d6', range: [86, 92] }, { code: 'tbnoir2d8', range: [93, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], monts: [{ code: 'messager', range: [1, 10] }, { code: 'passeur', range: [11, 20] }, { code: 'fleur', range: [21, 26] }, { code: 'mangeur', range: [27, 44] }, { code: 'changeur', range: [45, 59] }, { code: 'briseur', range: [60, 75] }, { code: 'reflet', range: [76, 85] }, { code: 'tbblanc', range: [86, 92] }, { code: 'tbnoir', range: [93, 97] }, { code: 'rdd', range: [98, 100] }],
desert: [{ code: 'messager2d4', range: [1, 10] }, { code: 'passeur2d4', range: [11, 20] }, { code: 'fleur1d6', range: [21, 26] }, { code: 'mangeur1d6', range: [27, 44] }, { code: 'changeur2d6', range: [45, 59] }, { code: 'briseur2d6', range: [60, 75] }, { code: 'reflet2d6', range: [76, 85] }, { code: 'tbblanc2d6', range: [86, 92] }, { code: 'tbnoir2d8', range: [93, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], desert: [{ code: 'messager', range: [1, 10] }, { code: 'passeur', range: [11, 20] }, { code: 'fleur', range: [21, 26] }, { code: 'mangeur', range: [27, 44] }, { code: 'changeur', range: [45, 59] }, { code: 'briseur', range: [60, 75] }, { code: 'reflet', range: [76, 85] }, { code: 'tbblanc', range: [86, 92] }, { code: 'tbnoir', range: [93, 97] }, { code: 'rdd', range: [98, 100] }],
fleuve: [{ code: 'messager2d4', range: [1, 5] }, { code: 'passeur2d4', range: [6, 10] }, { code: 'fleur1d6', range: [11, 13] }, { code: 'mangeur1d6', range: [14, 37] }, { code: 'changeur2d6', range: [38, 49] }, { code: 'briseur2d6', range: [50, 65] }, { code: 'reflet2d6', range: [66, 79] }, { code: 'tbblanc2d6', range: [80, 89] }, { code: 'tbnoir2d8', range: [90, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], fleuve: [{ code: 'messager', range: [1, 5] }, { code: 'passeur', range: [6, 10] }, { code: 'fleur', range: [11, 13] }, { code: 'mangeur', range: [14, 37] }, { code: 'changeur', range: [38, 49] }, { code: 'briseur', range: [50, 65] }, { code: 'reflet', range: [66, 79] }, { code: 'tbblanc', range: [80, 89] }, { code: 'tbnoir', range: [90, 97] }, { code: 'rdd', range: [98, 100] }],
lac: [{ code: 'messager2d4', range: [1, 5] }, { code: 'passeur2d4', range: [6, 10] }, { code: 'fleur1d6', range: [11, 13] }, { code: 'mangeur1d6', range: [14, 37] }, { code: 'changeur2d6', range: [38, 49] }, { code: 'briseur2d6', range: [50, 65] }, { code: 'reflet2d6', range: [66, 79] }, { code: 'tbblanc2d6', range: [80, 89] }, { code: 'tbnoir2d8', range: [90, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], lac: [{ code: 'messager', range: [1, 5] }, { code: 'passeur', range: [6, 10] }, { code: 'fleur', range: [11, 13] }, { code: 'mangeur', range: [14, 37] }, { code: 'changeur', range: [38, 49] }, { code: 'briseur', range: [50, 65] }, { code: 'reflet', range: [66, 79] }, { code: 'tbblanc', range: [80, 89] }, { code: 'tbnoir', range: [90, 97] }, { code: 'rdd', range: [98, 100] }],
marais: [{ code: 'messager2d4', range: [1, 2] }, { code: 'passeur2d4', range: [3, 4] }, { code: 'fleur1d6', range: [5, 5] }, { code: 'mangeur1d6', range: [6, 29] }, { code: 'changeur2d6', range: [30, 39] }, { code: 'briseur2d6', range: [40, 60] }, { code: 'reflet2d6', range: [61, 75] }, { code: 'tbblanc2d6', range: [76, 86] }, { code: 'tbnoir2d8', range: [87, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], marais: [{ code: 'messager', range: [1, 2] }, { code: 'passeur', range: [3, 4] }, { code: 'fleur', range: [5, 5] }, { code: 'mangeur', range: [6, 29] }, { code: 'changeur', range: [30, 39] }, { code: 'briseur', range: [40, 60] }, { code: 'reflet', range: [61, 75] }, { code: 'tbblanc', range: [76, 86] }, { code: 'tbnoir', range: [87, 97] }, { code: 'rdd', range: [98, 100] }],
gouffre: [{ code: 'messager2d4', range: [1, 2] }, { code: 'passeur2d4', range: [3, 4] }, { code: 'fleur1d6', range: [5, 5] }, { code: 'mangeur1d6', range: [6, 29] }, { code: 'changeur2d6', range: [30, 39] }, { code: 'briseur2d6', range: [40, 60] }, { code: 'reflet2d6', range: [61, 75] }, { code: 'tbblanc2d6', range: [76, 86] }, { code: 'tbnoir2d8', range: [87, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], gouffre: [{ code: 'messager', range: [1, 2] }, { code: 'passeur', range: [3, 4] }, { code: 'fleur', range: [5, 5] }, { code: 'mangeur', range: [6, 29] }, { code: 'changeur', range: [30, 39] }, { code: 'briseur', range: [40, 60] }, { code: 'reflet', range: [61, 75] }, { code: 'tbblanc', range: [76, 86] }, { code: 'tbnoir', range: [87, 97] }, { code: 'rdd', range: [98, 100] }],
necropole: [{ code: 'mangeur1d6', range: [1, 20] }, { code: 'changeur2d6', range: [21, 30] }, { code: 'briseur2d6', range: [31, 50] }, { code: 'reflet2d6', range: [51, 65] }, { code: 'tbblanc2d6', range: [66, 80] }, { code: 'tbnoir2d8', range: [81, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], necropole: [{ code: 'mangeur', range: [1, 20] }, { code: 'changeur', range: [21, 30] }, { code: 'briseur', range: [31, 50] }, { code: 'reflet', range: [51, 65] }, { code: 'tbblanc', range: [66, 80] }, { code: 'tbnoir', range: [81, 97] }, { code: 'rdd', range: [98, 100] }],
desolation: [{ code: 'mangeur1d6', range: [1, 20] }, { code: 'changeur2d6', range: [21, 30] }, { code: 'briseur2d6', range: [31, 50] }, { code: 'reflet2d6', range: [51, 65] }, { code: 'tbblanc2d6', range: [66, 80] }, { code: 'tbnoir2d8', range: [81, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }] desolation: [{ code: 'mangeur', range: [1, 20] }, { code: 'changeur', range: [21, 30] }, { code: 'briseur', range: [31, 50] }, { code: 'reflet', range: [51, 65] }, { code: 'tbblanc', range: [66, 80] }, { code: 'tbnoir', range: [81, 97] }, { code: 'rdd', range: [98, 100] }]
} }
@ -378,7 +378,8 @@ export class TMRRencontres {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async evaluerForceRencontre(rencontre) { static async evaluerForceRencontre(rencontre) {
if (TMRRencontres.isReveDeDragon(rencontre)) { if (TMRRencontres.isReveDeDragon(rencontre)) {
rencontre.force = await DeDraconique.ddr("selfroll").total + 7; const ddr = await DeDraconique.ddr("selfroll")
rencontre.force = 7 + ddr.total;
} }
else { else {
rencontre.force = new Roll(rencontre.force).evaluate().total; rencontre.force = new Roll(rencontre.force).evaluate().total;

View File

@ -4,241 +4,303 @@ import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const TMRMapping = { const TMRMapping = {
A1: { type: "cite", label: "Cité Vide"}, A1: { type: "cite", label: "Cité Vide" },
B1: { type: "plaines", label: "Plaines dAssorh"}, B1: { type: "plaines", label: "Plaines dAssorh" },
C1: { type: "necropole", label: "Nécropole de Kroak"}, C1: { type: "necropole", label: "Nécropole de Kroak" },
D1: { type: "fleuve", label: "Fleuve"}, D1: { type: "fleuve", label: "Fleuve de l'Oubli" },
E1: { type: "monts", label: "Monts de Kanaï"}, E1: { type: "monts", label: "Monts de Kanaï" },
F1: { type: "cite", label: "Cité Glauque"}, F1: { type: "cite", label: "Cité Glauque" },
G1: { type: "desolation", label: "Désolation de Demain"}, G1: { type: "desolation", label: "Désolation de Demain" },
H1: { type: "lac", label: "Lac dAnticalme"}, H1: { type: "lac", label: "Lac dAnticalme" },
I1: { type: "plaines", label: "Plaines Grises"}, I1: { type: "plaines", label: "Plaines Grises" },
J1: { type: "monts", label: "Monts Fainéants"}, J1: { type: "monts", label: "Monts Fainéants" },
K1: { type: "cite", label: "Cité dOnkause"}, K1: { type: "cite", label: "Cité dOnkause" },
L1: { type: "fleuve", label: "Fleuve"}, L1: { type: "fleuve", label: "Fleuve de l'Oubli" },
M1: { type: "cite", label: "Cité Jalouse"}, M1: { type: "cite", label: "Cité Jalouse" },
A2: { type: "desert", label: "Désert de Mieux"},
B2: { type: "collines", label: "Collines de Dawell"},
C2: { type: "marais", label: "Marais Glignants"},
D2: { type: "cite", label: "Cité de Frost"},
E2: { type: "plaines", label: "Plaines de Fiask"},
F2: { type: "lac", label: "Lac de Misère"},
G2: { type: "marais", label: "Marais Nuisants"},
H2: { type: "collines", label: "Collines de Parta"},
I2: { type: "foret", label: "Forêt Fade"},
J2: { type: "desert", label: "Désert de Poly"},
K2: { type: "foret", label: "Forêt Tamée"},
L2: { type: "fleuve", label: "Fleuve"},
M2: { type: "necropole", label: "Nécropole de Logos"},
A3: { type: "desolation", label: "Désolation de Demain"}, A2: { type: "desert", label: "Désert de Mieux" },
B3: { type: "plaines", label: "Plaines de Rubéga"}, B2: { type: "collines", label: "Collines de Dawell" },
C3: { type: "fleuve", label: "Fleuve"}, C2: { type: "marais", label: "Marais Glignants" },
D3: { type: "gouffre", label: "Gouffre dOki"}, D2: { type: "cite", label: "Cité de Frost" },
E3: { type: "foret", label: "Forêt dEstoubh"}, E2: { type: "plaines", label: "Plaines de Fiask" },
F3: { type: "fleuve", label: "Fleuve"}, F2: { type: "lac", label: "Lac de Misère" },
G3: { type: "gouffre", label: "Gouffre de Sun"}, G2: { type: "marais", label: "Marais Nuisants" },
H3: { type: "foret", label: "Forêt de Ganna"}, H2: { type: "collines", label: "Collines de Parta" },
I3: { type: "monts", label: "Monts Grinçants"}, I2: { type: "foret", label: "Forêt Fade" },
J3: { type: "cite", label: "Cité Venin"}, J2: { type: "desert", label: "Désert de Poly" },
K3: { type: "plaines", label: "Plaines de Dois"}, K2: { type: "foret", label: "Forêt Tamée" },
L3: { type: "lac", label: "Lac Laineux"}, L2: { type: "fleuve", label: "Fleuve de l'Oubli" },
M3: { type: "monts", label: "Monts de Vdah"}, M2: { type: "necropole", label: "Nécropole de Logos" },
A4: { type: "foret", label: "Forêt de Falconax"}, A3: { type: "desolation", label: "Désolation de Demain" },
B4: { type: "monts", label: "Monts Crâneurs"}, B3: { type: "plaines", label: "Plaines de Rubéga" },
C4: { type: "pont", label: "Pont de Giolii"}, C3: { type: "fleuve", label: "Fleuve de l'Oubli" },
D4: { type: "lac", label: "Lac de Foam"}, D3: { type: "gouffre", label: "Gouffre dOki" },
E4: { type: "plaines", label: "Plaines dOrti"}, E3: { type: "foret", label: "Forêt dEstoubh" },
F4: { type: "fleuve", label: "Fleuve"}, F3: { type: "fleuve", label: "Fleuve de l'Oubli" },
G4: { type: "sanctuaire", label: "Sanctuaire Blanc"}, G3: { type: "gouffre", label: "Gouffre de Sun" },
H4: { type: "plaines", label: "Plaines de Psark"}, H3: { type: "foret", label: "Forêt de Ganna" },
I4: { type: "plaines", label: "Plaines de Xiax"}, I3: { type: "monts", label: "Monts Grinçants" },
J4: { type: "collines", label: "Collines dEncre"}, J3: { type: "cite", label: "Cité Venin" },
K4: { type: "pont", label: "Pont de Fah"}, K3: { type: "plaines", label: "Plaines de Dois" },
L4: { type: "sanctuaire", label: "Sanctuaire Mauve"}, L3: { type: "lac", label: "Lac Laineux" },
M4: { type: "gouffre", label: "Gouffre Grisant"}, M3: { type: "monts", label: "Monts de Vdah" },
A5: { type: "plaines", label: "Plaines de Trilkh"}, A4: { type: "foret", label: "Forêt de Falconax" },
B5: { type: "collines", label: "Collines de Tanegy"}, B4: { type: "monts", label: "Monts Crâneurs" },
C5: { type: "marais", label: "Marais Flouants"}, C4: { type: "pont", label: "Pont de Giolii" },
D5: { type: "fleuve", label: "Fleuve"}, D4: { type: "lac", label: "Lac de Foam" },
E5: { type: "monts", label: "Monts Brûlants"}, E4: { type: "plaines", label: "Plaines dOrti" },
F5: { type: "cite", label: "Cité de Panople"}, F4: { type: "fleuve", label: "Fleuve de l'Oubli" },
G5: { type: "pont", label: "Pont dIk"}, G4: { type: "sanctuaire", label: "Sanctuaire Blanc" },
H5: { type: "desert", label: "Désert de Krane"}, H4: { type: "plaines", label: "Plaines de Psark" },
I5: { type: "desolation", label: "Désolation de Demain"}, I4: { type: "plaines", label: "Plaines de Xiax" },
J5: { type: "marais", label: "Marais de Jab"}, J4: { type: "collines", label: "Collines dEncre" },
K5: { type: "fleuve", label: "Fleuve"}, K4: { type: "pont", label: "Pont de Fah" },
L5: { type: "collines", label: "Collines Suaves"}, L4: { type: "sanctuaire", label: "Sanctuaire Mauve" },
M5: { type: "cite", label: "Cité Rimarde"}, M4: { type: "gouffre", label: "Gouffre Grisant" },
A6: { type: "necropole", label: "Nécropole de Zniak"}, A5: { type: "plaines", label: "Plaines de Trilkh" },
B6: { type: "foret", label: "Forêt de Bust"}, B5: { type: "collines", label: "Collines de Tanegy" },
C6: { type: "cite", label: "Cité Pavois"}, C5: { type: "marais", label: "Marais Flouants" },
D6: { type: "fleuve", label: "Fleuve"}, D5: { type: "fleuve", label: "Fleuve de l'Oubli" },
E6: { type: "sanctuaire", label: "Sanctuaire de Plaine"}, E5: { type: "monts", label: "Monts Brûlants" },
F6: { type: "fleuve", label: "Fleuve"}, F5: { type: "cite", label: "Cité de Panople" },
G6: { type: "marais", label: "Marais Glutants"}, G5: { type: "pont", label: "Pont dIk" },
H6: { type: "monts", label: "Monts Gurdes"}, H5: { type: "desert", label: "Désert de Krane" },
I6: { type: "necropole", label: "Nécropole de Xotar"}, I5: { type: "desolation", label: "Désolation de Demain" },
J6: { type: "lac", label: "Lac dIaupe"}, J5: { type: "marais", label: "Marais de Jab" },
K6: { type: "desolation", label: "Désolation de Demain"}, K5: { type: "fleuve", label: "Fleuve de l'Oubli" },
L6: { type: "foret", label: "Forêt Gueuse"}, L5: { type: "collines", label: "Collines Suaves" },
M6: { type: "desolation", label: "Désolation de Demain"}, M5: { type: "cite", label: "Cité Rimarde" },
A7: { type: "plaines", label: "Plaines de lArc"}, A6: { type: "necropole", label: "Nécropole de Zniak" },
B7: { type: "marais", label: "Marais Bluants"}, B6: { type: "foret", label: "Forêt de Bust" },
C7: { type: "fleuve", label: "Fleuve"}, C6: { type: "cite", label: "Cité Pavois" },
D7: { type: "plaines", label: "Plaines dA!a"}, D6: { type: "fleuve", label: "Fleuve de l'Oubli" },
E7: { type: "foret", label: "Forêt de Glusks"}, E6: { type: "sanctuaire", label: "Sanctuaire de Plaine" },
F7: { type: "fleuve", label: "Fleuve"}, F6: { type: "fleuve", label: "Fleuve de l'Oubli" },
G7: { type: "cite", label: "Cité de Terwa"}, G6: { type: "marais", label: "Marais Glutants" },
H7: { type: "gouffre", label: "Gouffre de Kapfa"}, H6: { type: "monts", label: "Monts Gurdes" },
I7: { type: "plaines", label: "Plaines de Troo"}, I6: { type: "necropole", label: "Nécropole de Xotar" },
J7: { type: "fleuve", label: "Fleuve"}, J6: { type: "lac", label: "Lac dIaupe" },
K7: { type: "cite", label: "Cité de Kolix"}, K6: { type: "desolation", label: "Désolation de Demain" },
L7: { type: "gouffre", label: "Gouffre dEpisophe"}, L6: { type: "foret", label: "Forêt Gueuse" },
M7: { type: "desert", label: "Désert de Lave"}, M6: { type: "desolation", label: "Désolation de Demain" },
A8: { type: "gouffre", label: "Gouffre de Shok"}, A7: { type: "plaines", label: "Plaines de lArc" },
B8: { type: "fleuve", label: "Fleuve"}, B7: { type: "marais", label: "Marais Bluants" },
C8: { type: "foret", label: "Forêt Turmide"}, C7: { type: "fleuve", label: "Fleuve de l'Oubli" },
D8: { type: "cite", label: "Cité dOlak"}, D7: { type: "plaines", label: "Plaines dA!a" },
E8: { type: "plaines", label: "Plaines dIolise"}, E7: { type: "foret", label: "Forêt de Glusks" },
F8: { type: "lac", label: "Lac des Chats"}, F7: { type: "fleuve", label: "Fleuve de l'Oubli" },
G8: { type: "plaines", label: "Plaines Sans Joie"}, G7: { type: "cite", label: "Cité de Terwa" },
H8: { type: "foret", label: "Forêt dOurf"}, H7: { type: "gouffre", label: "Gouffre de Kapfa" },
I8: { type: "fleuve", label: "Fleuve"}, I7: { type: "plaines", label: "Plaines de Troo" },
J8: { type: "monts", label: "Monts Barask"}, J7: { type: "fleuve", label: "Fleuve de l'Oubli" },
K8: { type: "desert", label: "Désert de Fumée"}, K7: { type: "cite", label: "Cité de Kolix" },
L8: { type: "monts", label: "Monts Tavelés"}, L7: { type: "gouffre", label: "Gouffre dEpisophe" },
M8: { type: "plaines", label: "Plaines Lavées"}, M7: { type: "desert", label: "Désert de Lave" },
A9: { type: "collines", label: "Collines de Korrex"}, A8: { type: "gouffre", label: "Gouffre de Shok" },
B9: { type: "lac", label: "Lac de Lucre"}, B8: { type: "fleuve", label: "Fleuve de l'Oubli" },
C9: { type: "monts", label: "Monts Tuméfiés"}, C8: { type: "foret", label: "Forêt Turmide" },
D9: { type: "pont", label: "Pont dOrx"}, D8: { type: "cite", label: "Cité dOlak" },
E9: { type: "fleuve", label: "Fleuve"}, E8: { type: "plaines", label: "Plaines dIolise" },
F9: { type: "plaines", label: "Plaines de Foe"}, F8: { type: "lac", label: "Lac des Chats" },
G9: { type: "desolation", label: "Désolation de Demain"}, G8: { type: "plaines", label: "Plaines Sans Joie" },
H9: { type: "collines", label: "Collines de Noirseul"}, H8: { type: "foret", label: "Forêt dOurf" },
I9: { type: "fleuve", label: "Fleuve"}, I8: { type: "fleuve", label: "Fleuve de l'Oubli" },
J9: { type: "marais", label: "Marais Gronchants"}, J8: { type: "monts", label: "Monts Barask" },
K9: { type: "sanctuaire", label: "Sanctuaire Noir"}, K8: { type: "desert", label: "Désert de Fumée" },
L9: { type: "collines", label: "Collines Cornues"}, L8: { type: "monts", label: "Monts Tavelés" },
M9: { type: "necropole", label: "Nécropole de Zonar"}, M8: { type: "plaines", label: "Plaines Lavées" },
A10: { type: "sanctuaire", label: "Sanctuaire dOlis"}, A9: { type: "collines", label: "Collines de Korrex" },
B10: { type: "monts", label: "Monts Salés"}, B9: { type: "lac", label: "Lac de Lucre" },
C10: { type: "marais", label: "Marais de Dom"}, C9: { type: "monts", label: "Monts Tuméfiés" },
D10: { type: "fleuve", label: "Fleuve"}, D9: { type: "pont", label: "Pont dOrx" },
E10: { type: "gouffre", label: "Gouffre de Junk"}, E9: { type: "fleuve", label: "Fleuve de l'Oubli" },
F10: { type: "marais", label: "Marais Zultants"}, F9: { type: "plaines", label: "Plaines de Foe" },
G10: { type: "cite", label: "Cité de Sergal"}, G9: { type: "desolation", label: "Désolation de Demain" },
H10: { type: "plaines", label: "Plaines Noires"}, H9: { type: "collines", label: "Collines de Noirseul" },
I10: { type: "lac", label: "Lac Wanito"}, I9: { type: "fleuve", label: "Fleuve de l'Oubli" },
J10: { type: "fleuve", label: "Fleuve"}, J9: { type: "marais", label: "Marais Gronchants" },
K10: { type: "plaines", label: "Plaines Jaunes"}, K9: { type: "sanctuaire", label: "Sanctuaire Noir" },
L10: { type: "desert", label: "Désert de Nicrop"}, L9: { type: "collines", label: "Collines Cornues" },
M10: { type: "foret", label: "Forêt de Jajou"}, M9: { type: "necropole", label: "Nécropole de Zonar" },
A11: { type: "desolation", label: "Désolation de Demain"}, A10: { type: "sanctuaire", label: "Sanctuaire dOlis" },
B11: { type: "cite", label: "Cité de Brilz"}, B10: { type: "monts", label: "Monts Salés" },
C11: { type: "pont", label: "Pont de Roï"}, C10: { type: "marais", label: "Marais de Dom" },
D11: { type: "desolation", label: "Désolation de Demain"}, D10: { type: "fleuve", label: "Fleuve de l'Oubli" },
E11: { type: "lac", label: "Lac de Glinster"}, E10: { type: "gouffre", label: "Gouffre de Junk" },
F11: { type: "cite", label: "Cité de Noape"}, F10: { type: "marais", label: "Marais Zultants" },
G11: { type: "fleuve", label: "Fleuve"}, G10: { type: "cite", label: "Cité de Sergal" },
H11: { type: "fleuve", label: "Fleuve"}, H10: { type: "plaines", label: "Plaines Noires" },
I11: { type: "pont", label: "Pont de Yalm"}, I10: { type: "lac", label: "Lac Wanito" },
J11: { type: "plaines", label: "Plaines de Miltiar"}, J10: { type: "fleuve", label: "Fleuve de l'Oubli" },
K11: { type: "cite", label: "Cité Tonnerre"}, K10: { type: "plaines", label: "Plaines Jaunes" },
L11: { type: "collines", label: "Collines de Kol"}, L10: { type: "desert", label: "Désert de Nicrop" },
M11: { type: "cite", label: "Cité Crapaud"}, M10: { type: "foret", label: "Forêt de Jajou" },
A12: { type: "plaines", label: "Plaines Sages"}, A11: { type: "desolation", label: "Désolation de Demain" },
B12: { type: "fleuve", label: "Fleuve"}, B11: { type: "cite", label: "Cité de Brilz" },
C12: { type: "lac", label: "Lac de Fricassa"}, C11: { type: "pont", label: "Pont de Roï" },
D12: { type: "collines", label: "Collines dHuaï"}, D11: { type: "desolation", label: "Désolation de Demain" },
E12: { type: "monts", label: "Monts Ajourés"}, E11: { type: "lac", label: "Lac de Glinster" },
F12: { type: "necropole", label: "Nécropole de Troat"}, F11: { type: "cite", label: "Cité de Noape" },
G12: { type: "plaines", label: "Plaines de Lufmil"}, G11: { type: "fleuve", label: "Fleuve de l'Oubli" },
H12: { type: "collines", label: "Collines de Tooth"}, H11: { type: "fleuve", label: "Fleuve de l'Oubli" },
I12: { type: "gouffre", label: "Gouffre Abimeux"}, I11: { type: "pont", label: "Pont de Yalm" },
J12: { type: "cite", label: "Cité Folle"}, J11: { type: "plaines", label: "Plaines de Miltiar" },
K12: { type: "desolation", label: "Désolation de Demain"}, K11: { type: "cite", label: "Cité Tonnerre" },
L12: { type: "plaines", label: "Plaines Venteuses"}, L11: { type: "collines", label: "Collines de Kol" },
M12: { type: "collines", label: "Collines Révulsantes"}, M11: { type: "cite", label: "Cité Crapaud" },
A13: { type: "fleuve", label: "Fleuve"}, A12: { type: "plaines", label: "Plaines Sages" },
B13: { type: "gouffre", label: "Gouffre des Litiges"}, B12: { type: "fleuve", label: "Fleuve de l'Oubli" },
C13: { type: "desert", label: "Désert de Neige"}, C12: { type: "lac", label: "Lac de Fricassa" },
D13: { type: "cite", label: "Cité Sordide"}, D12: { type: "collines", label: "Collines dHuaï" },
E13: { type: "plaines", label: "Plaines de Xnez"}, E12: { type: "monts", label: "Monts Ajourés" },
F13: { type: "foret", label: "Forêt des Cris"}, F12: { type: "necropole", label: "Nécropole de Troat" },
G13: { type: "plaines", label: "Plaines Calcaires"}, G12: { type: "plaines", label: "Plaines de Lufmil" },
H13: { type: "desolation", label: "Désolation de Demain"}, H12: { type: "collines", label: "Collines de Tooth" },
I13: { type: "monts", label: "Monts Bigleux"}, I12: { type: "gouffre", label: "Gouffre Abimeux" },
J13: { type: "gouffre", label: "Gouffre de Gromph"}, J12: { type: "cite", label: "Cité Folle" },
K13: { type: "foret", label: "Forêt de Kluth"}, K12: { type: "desolation", label: "Désolation de Demain" },
L13: { type: "monts", label: "Monts Dormants"}, L12: { type: "plaines", label: "Plaines Venteuses" },
M13: { type: "plaines", label: "Plaines dAnjou"}, M12: { type: "collines", label: "Collines Révulsantes" },
A14: { type: "collines", label: "Collines de Stolis"}, A13: { type: "fleuve", label: "Fleuve de l'Oubli" },
B14: { type: "necropole", label: "Nécropole de Gorlo"}, B13: { type: "gouffre", label: "Gouffre des Litiges" },
C14: { type: "foret", label: "Forêt de Bissam"}, C13: { type: "desert", label: "Désert de Neige" },
D14: { type: "sanctuaire", label: "Sanctuaire Plat"}, D13: { type: "cite", label: "Cité Sordide" },
E14: { type: "monts", label: "Monts de Quath"}, E13: { type: "plaines", label: "Plaines de Xnez" },
F14: { type: "plaines", label: "Plaines Brisées"}, F13: { type: "foret", label: "Forêt des Cris" },
G14: { type: "desert", label: "Désert de Sek"}, G13: { type: "plaines", label: "Plaines Calcaires" },
H14: { type: "plaines", label: "Plaines Blanches"}, H13: { type: "desolation", label: "Désolation de Demain" },
I14: { type: "cite", label: "Cité Destituée"}, I13: { type: "monts", label: "Monts Bigleux" },
J14: { type: "desert", label: "Désert de Sank"}, J13: { type: "gouffre", label: "Gouffre de Gromph" },
K14: { type: "necropole", label: "Nécropole dAntinéar"}, K13: { type: "foret", label: "Forêt de Kluth" },
L14: { type: "plaines", label: "Plaines de Jislith"}, L13: { type: "monts", label: "Monts Dormants" },
M14: { type: "desolation", label: "Désolation de Demain"}, M13: { type: "plaines", label: "Plaines dAnjou" },
A15: { type: "cite", label: "Cité de Mielh"}, A14: { type: "collines", label: "Collines de Stolis" },
C15: { type: "plaines", label: "Plaines de Toué"}, B14: { type: "necropole", label: "Nécropole de Gorlo" },
E15: { type: "foret", label: "Forêt des Furies"}, C14: { type: "foret", label: "Forêt de Bissam" },
G15: { type: "plaines", label: "Plaines des Soupirs"}, D14: { type: "sanctuaire", label: "Sanctuaire Plat" },
I15: { type: "monts", label: "Monts des Dragées"}, E14: { type: "monts", label: "Monts de Quath" },
K15: { type: "collines", label: "Collines Pourpres"}, F14: { type: "plaines", label: "Plaines Brisées" },
M15: { type: "cite", label: "Cité de Klana"} G14: { type: "desert", label: "Désert de Sek" },
} H14: { type: "plaines", label: "Plaines Blanches" },
I14: { type: "cite", label: "Cité Destituée" },
J14: { type: "desert", label: "Désert de Sank" },
K14: { type: "necropole", label: "Nécropole dAntinéar" },
L14: { type: "plaines", label: "Plaines de Jislith" },
M14: { type: "desolation", label: "Désolation de Demain" },
export const TMRType = { A15: { type: "cite", label: "Cité de Mielh" },
cite: {name:"cité"}, C15: { type: "plaines", label: "Plaines de Toué" },
sanctuaire: {name:"sanctuaire"}, E15: { type: "foret", label: "Forêt des Furies" },
plaines: {name:"plaines"}, G15: { type: "plaines", label: "Plaines des Soupirs" },
pont: {name:"pont"}, I15: { type: "monts", label: "Monts des Dragées" },
collines: {name:"collines"}, K15: { type: "collines", label: "Collines Pourpres" },
foret: {name:"forêt"}, M15: { type: "cite", label: "Cité de Klana" }
monts: {name:"monts"},
desert: {name:"désert"},
fleuve: {name:"fleuve"},
lac: {name:"lac"},
marais: {name:"marais"},
gouffre: {name:"gouffre"},
necropole: {name:"nécropole"},
desolation: {name:"désolation"}
} }
/* -------------------------------------------- */ export const TMRType = {
const caseSpecificModes = [ "attache", "trounoir", "debordement", "reserve_extensible", "maitrisee" ]; cite: { name: "cité", genre: "f" },
sanctuaire: { name: "sanctuaire" },
plaines: { name: "plaines", genre: "p" },
pont: { name: "pont", genre: "m" },
collines: { name: "collines", genre: "p" },
foret: { name: "forêt", genre: "f" },
monts: { name: "monts", genre: "p" },
desert: { name: "désert", genre: "m" },
fleuve: { name: "fleuve", genre: "m" },
lac: { name: "lac", genre: "m" },
marais: { name: "marais", genre: "m" },
gouffre: { name: "gouffre", genre: "m" },
necropole: { name: "nécropole", genre: "f" },
desolation: { name: "désolation", genre: "f" }
}
export const poesieCaseHumide = [
{
reference: 'Le Ratier Bretonien',
extrait: `Le courant du Fleuve
<br>Te domine et te Porte
<br>Avant que tu te moeuves
<br>Combat le, ou il t'emporte`
},
{
reference: 'Incompatibilité, Charles Beaudelaire',
extrait: `Et lorsque par hasard une nuée errante
<br>Assombrit dans son vol le lac silencieux,
<br>On croirait voir la robe ou l'ombre transparente
<br>D'un esprit qui voyage et passe dans les cieux.`
},
{
reference: 'Au fleuve de Loire, Joachim du Bellay',
extrait: `Ô de qui la vive course
<br>Prend sa bienheureuse source,
<br>Dune argentine fontaine,
<br>Qui dune fuite lointaine,
<br>Te rends au sein fluctueux
<br>De lOcéan monstrueux`
},
{
reference: 'Denis Gerfaud',
extrait: `Et l'on peut savoir qui est le maître d'Oniros, c'est le Fleuve de l'Oubli.
Et l'on sait qui est le créateur du Fleuve de l'Oubli, c'est Hypnos et Narcos.
Mais l'on ne sait pas qui est le maître du Fleuve de l'Oubli,
sinon peut-être lui-même, ou peut-être Thanatos` },
{
reference: 'Denis Gerfaud',
extrait: `Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure
Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir.
Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli`
},
{
reference: 'Denis Gerfaud',
extrait: `Narcos engendre le fils dont il est la mère à l'heure du Vaisseau,
car Oniros s'embarque pour redescendre le Fleuve
vers son père Hypnos sur la Voie de l'Oubli`
},
{
reference: 'Denis Gerfaud',
extrait: `Hypnos engendre le fils dont il est la mère à l'heure du Serpent, car
tel les serpents, Oniros commence à remonter le Fleuve
sur le Voie du Souvenir vers son père Narcos`
},
{
reference: 'Denis Gerfaud',
extrait: `Ainsi se cuccèdent les Jours et les Ages. Les jours des Dragons sont les Ages des Hommes`
},
{
reference: 'Denis Gerfaud',
extrait: `Ainsi parlent les sages:
&laquo;Les Dragons sont créateurs de leurs rêves, mais ils ne sont pas créateurs d'Oniros
Les Dragons ne sont pas les maîtres de leurs rêvezs, car ils ne sont pas maîtres d'Oniros.
Nul ne sait qui est le créateur des Dragons, ni qui est leur maître.
Mais l'on peut supposer qui est le maître du Rêve des Dragons, c'est Oniros&raquo;`
},
]
/* -------------------------------------------- */ /* -------------------------------------------- */
const tmrRandomMovePatten = const caseSpecificModes = ["attache", "trounoir", "debordement", "reserve_extensible", "maitrisee"];
[ { name: 'top', x: 0, y: -1 },
{ name: 'topright', x: 1, y: -1 }, /* -------------------------------------------- */
{ name: 'botright', x: 1, y: 1 }, const tmrRandomMovePatten =
{ name: 'bot', x: 0, y: 1 }, [{ name: 'top', x: 0, y: -1 },
{ name: 'botleft', x: -1, y: 1 }, { name: 'topright', x: 1, y: -1 },
{ name: 'topleft', x: -1, y: -1 } { name: 'botright', x: 1, y: 1 },
] { name: 'bot', x: 0, y: 1 },
{ name: 'botleft', x: -1, y: 1 },
{ name: 'topleft', x: -1, y: -1 }
]
/* -------------------------------------------- */ /* -------------------------------------------- */
export const tmrConstants = { export const tmrConstants = {
@ -253,7 +315,7 @@ export const tmrConstants = {
/* -------------------------------------------- */ /* -------------------------------------------- */
/* -------------------------------------------- */ /* -------------------------------------------- */
export class TMRUtility { export class TMRUtility {
static init() { static init() {
for (let coord in TMRMapping) { for (let coord in TMRMapping) {
TMRMapping[coord].coord = coord; TMRMapping[coord].coord = coord;
@ -265,64 +327,68 @@ export class TMRUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static convertToTMRCoord( pos ) static convertToTMRCoord(pos) {
{ let letterX = String.fromCharCode(65 + (pos.x));
let letterX = String.fromCharCode(65+ (pos.x)); return letterX + (pos.y + 1)
return letterX + (pos.y +1)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static verifyTMRCoord( coord ) { static verifyTMRCoord(coord) {
let TMRregexp = new RegExp(/([A-M])(\d+)/g); let TMRregexp = new RegExp(/([A-M])(\d+)/g);
let res = TMRregexp.exec( coord ); let res = TMRregexp.exec(coord);
if (res && res[1] && res[2]) { if (res && res[1] && res[2]) {
if (res[2] > 0 && res[2] < 16) { if (res[2] > 0 && res[2] < 16) {
return true; return true;
} }
} }
return false; return false;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static convertToCellPos( coordTMR ) static convertToCellPos(coordTMR) {
{
let x = coordTMR.charCodeAt(0) - 65; let x = coordTMR.charCodeAt(0) - 65;
let y = coordTMR.substr(1) - 1; let y = coordTMR.substr(1) - 1;
return {x: x, y: y} return { x: x, y: y }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getTMR( coordTMR) static getTMR(coordTMR) {
{
return TMRMapping[coordTMR]; return TMRMapping[coordTMR];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Some debug functions */ /** Some debug functions */
static async setForceRencontre( index, force = undefined ) { static async setForceRencontre(index, force = undefined) {
this.prochaineRencontre = TMRRencontres.getRencontre( index ); this.prochaineRencontre = TMRRencontres.getRencontre(index);
if (this.prochaineRencontre ) { if (this.prochaineRencontre) {
if (force) { if (force) {
this.prochaineRencontre.force = force; this.prochaineRencontre.force = force;
} }
else{ else {
await TMRRencontres.evaluerForceRencontre(this.prochaineRencontre) await TMRRencontres.evaluerForceRencontre(this.prochaineRencontre)
} }
console.log("La prochaine rencontre sera:", this.prochaineRencontre.name, " force:", this.prochaineRencontre.force); console.log("La prochaine rencontre sera:", this.prochaineRencontre.name, " force:", this.prochaineRencontre.force);
} }
else { else {
ui.notifications.warn("Pas de prochaine rencontre valide pour "+index); ui.notifications.warn("Pas de prochaine rencontre valide pour " + index);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isForceRencontre() { static isForceRencontre() {
return this.prochaineRencontre return this.prochaineRencontre;
}
/* -------------------------------------------- */
static utiliseForceRencontre() {
const rencontre = this.prochaineRencontre;
this.prochaineRencontre = undefined;
return rencontre;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getDirectionPattern() { static getDirectionPattern() {
let roll = new Roll("1d"+tmrRandomMovePatten.length).evaluate().total; let roll = new Roll("1d" + tmrRandomMovePatten.length).evaluate().total;
return tmrRandomMovePatten[roll -1]; return tmrRandomMovePatten[roll - 1];
} }
static deplaceTMRAleatoire(coord) { static deplaceTMRAleatoire(coord) {
@ -330,12 +396,12 @@ export class TMRUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static deplaceTMRSelonPattern( coord, direction, nTime ) { static deplaceTMRSelonPattern(coord, direction, nTime) {
for (let i=0; i <nTime; i++) { for (let i = 0; i < nTime; i++) {
let currentPosXY = TMRUtility.convertToCellPos(coord); let currentPosXY = TMRUtility.convertToCellPos(coord);
currentPosXY.x = currentPosXY.x + direction.x; currentPosXY.x = currentPosXY.x + direction.x;
currentPosXY.y = currentPosXY.y + direction.y; currentPosXY.y = currentPosXY.y + direction.y;
if ( this._checkTMRCoord(currentPosXY.x, currentPosXY.y) ) { // Sortie de carte ! Ré-insertion aléatoire if (this._checkTMRCoord(currentPosXY.x, currentPosXY.y)) { // Sortie de carte ! Ré-insertion aléatoire
coord = TMRUtility.convertToTMRCoord(currentPosXY); coord = TMRUtility.convertToTMRCoord(currentPosXY);
} else { } else {
coord = this.getTMRAleatoire().coord; coord = this.getTMRAleatoire().coord;
@ -345,65 +411,47 @@ export class TMRUtility {
return coord; return coord;
} }
/* -------------------------------------------- */
static async rencontreTMRRoll( coordTMR, cellDescr, isMauvaise = false )
{
let rencontre;
if ( this.prochaineRencontre ) {
rencontre = this.prochaineRencontre;
rencontre.coord = coordTMR;
this.prochaineRencontre = undefined;
}
else if ( isMauvaise ) {
rencontre = await TMRRencontres.getMauvaiseRencontre();
} else {
rencontre = await TMRRencontres.getRencontreAleatoire(cellDescr.type);
}
rencontre.coord = coordTMR;
return rencontre;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getListTMR(terrain) { static getListTMR(terrain) {
return TMRType[terrain].list; return TMRType[terrain].list;
} }
static getListCoordTMR(terrain) { static getListCoordTMR(terrain) {
return this.getListTMR(terrain).map(it=>it.coord); return this.getListTMR(terrain).map(it => it.coord);
} }
static getTMRAleatoire(terrain = undefined) { static getTMRAleatoire(terrain = undefined) {
let list = terrain ? TMRUtility.getListTMR(terrain) : Object.values(TMRMapping); let list = terrain ? TMRUtility.getListTMR(terrain) : Object.values(TMRMapping);
let index = new Roll("1d" + list.length).evaluate().total - 1; let index = new Roll("1d" + list.length).evaluate().total - 1;
return list[index]; return list[index];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _checkTMRCoord( x, y ) { static _checkTMRCoord(x, y) {
if (x >= 0 && x < 13 && y >= 0 && y < 14 ) return true; if (x >= 0 && x < 13 && y >= 0 && y < 14) return true;
if (x >= 0 && x < 13 && x%2 == 0 && y == 14 ) return true; if (x >= 0 && x < 13 && x % 2 == 0 && y == 14) return true;
return false; return false;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeRealPictureCoordinates( coordXY, tmrConstants ) { static computeRealPictureCoordinates(coordXY, tmrConstants) {
let decallagePairImpair = (coordXY.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; let decallagePairImpair = (coordXY.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
return { return {
x: tmrConstants.gridx + (coordXY.x * tmrConstants.cellw), x: tmrConstants.gridx + (coordXY.x * tmrConstants.cellw),
y: tmrConstants.gridy + (coordXY.y * tmrConstants.cellh) + decallagePairImpair y: tmrConstants.gridy + (coordXY.y * tmrConstants.cellh) + decallagePairImpair
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getSortReserveList( reserveList, coordTMR ) { static getSortReserveList(reserveList, coordTMR) {
// TODO : Gérer les têtes spéciales réserve! // TODO : Gérer les têtes spéciales réserve!
let sortReserveList let sortReserveList
let tmrDescr = this.getTMR(coordTMR); let tmrDescr = this.getTMR(coordTMR);
//console.log("Sort réserve : ", tmrDescr); //console.log("Sort réserve : ", tmrDescr);
if ( tmrDescr.type == 'fleuve') { // Gestion de la reserve en Fleuve if (tmrDescr.type == 'fleuve') { // Gestion de la reserve en Fleuve
sortReserveList = reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve' ); sortReserveList = reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve');
} else { // Reserve sur un case "normale" } else { // Reserve sur un case "normale"
sortReserveList = reserveList.filter(it => it.coord == coordTMR); sortReserveList = reserveList.filter(it => it.coord == coordTMR);
} }
//console.log("Sort réserve : ", tmrDescr, sortReserve, reserveList); //console.log("Sort réserve : ", tmrDescr, sortReserve, reserveList);
return sortReserveList; return sortReserveList;
@ -417,18 +465,18 @@ export class TMRUtility {
return TMRUtility.getTMRArea(centerCoord, portee, tmrConstants); return TMRUtility.getTMRArea(centerCoord, portee, tmrConstants);
} }
static getTMRArea( centerCoord, distance, tmrConstants ) { static getTMRArea(centerCoord, distance, tmrConstants) {
let centerPos = this.convertToCellPos( centerCoord ); let centerPos = this.convertToCellPos(centerCoord);
let posPic = this.computeRealPictureCoordinates( centerPos, tmrConstants ); let posPic = this.computeRealPictureCoordinates(centerPos, tmrConstants);
let caseList = []; let caseList = [];
for (let dx=-distance; dx<=distance; dx++ ) { // Loop thru lines for (let dx = -distance; dx <= distance; dx++) { // Loop thru lines
for (let dy=-distance; dy<=distance; dy++ ) { // Loop thru lines for (let dy = -distance; dy <= distance; dy++) { // Loop thru lines
const currentPos = { x: centerPos.x+dx, y: centerPos.y+dy }; const currentPos = { x: centerPos.x + dx, y: centerPos.y + dy };
if ( this._checkTMRCoord(currentPos.x, currentPos.y) ) { // Coordinate is valie if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Coordinate is valie
let posPicNow = this.computeRealPictureCoordinates( currentPos, tmrConstants ); let posPicNow = this.computeRealPictureCoordinates(currentPos, tmrConstants);
let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x,2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw; let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x, 2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw;
if ( dist < distance+0.5) { if (dist < distance + 0.5) {
caseList.push( this.convertToTMRCoord(currentPos) ); // Inside the area caseList.push(this.convertToTMRCoord(currentPos)); // Inside the area
} }
} }
} }

View File

@ -0,0 +1,30 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{competence.name}}"/>
<h4 data-categorie="tmr" data-actor-id="{{actor._id}}">
{{alias}} tente de maîtriser {{le tmr.genre}} {{tmr.label}} ({{tmr.coord}})
</h4>
{{#if previous}}
{{#each previous as |rolled key|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<br>Double résistance du fleuve!
{{/each}}
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
<span>
{{#if rolled.isSuccess}}
Vous avez maîtrisé {{le tmr.genre}} {{#if (eq tmr.type 'fleuve')}}Fleuve de l'Oubli{{else}}{{tmr.label}}{{/if}} !
{{else}}
Vous ne parvenez pas à surmonter {{le tmr.genre}} {{#if (eq tmr.type 'fleuve')}}Fleuve de l'Oubli{{else}}{{tmr.label}}{{/if}}.
Vous <strong>quittez les Terres Médianes</strong> !
{{#if souffle}}
<br>De plus, votre échec total vous fait subir un Souffle de Dragon : {{souffle.name}}
{{/if}}
{{/if}}
</span>
{{#if poesie}}
<hr>
<span class="poesie-extrait">
{{{poesie.extrait}}}
<p class="poesie-reference">{{poesie.reference}}</p>
</span>
{{/if}}

View File

@ -0,0 +1,28 @@
<form class="skill-roll-dialog">
<div class="form-group">
<label for="categorie">{{tmr.label}} ({{tmr.coord}})</label>
<label for="categorie">Rêve actuel à {{diffLibre}}</label>
<span>
<label for="categorie">Conditions</label>
<select name="diffConditions" id="diffConditions" data-dtype="number">
{{#select diffConditions}}
{{#each ajustementsConditions as |key|}}
<option value={{key}}>{{numberFormat key decimals=0 sign=true}}</option>
{{/each}}
{{/select}}
</select>
</span>
</div>
{{>"systems/foundryvtt-reve-de-dragon/templates/dialog-roll-surenc.html"}}
<div id="tableAjustements">
</div>
<div id="tableResolution">
</div>
<div id="tableProbaReussite">
</div>
</form>
<script>
</script>

View File

@ -50,20 +50,7 @@
<label for="xp">Case TMR</label> <label for="xp">Case TMR</label>
<select name="data.tmr" id="tmr" data-dtype="String"> <select name="data.tmr" id="tmr" data-dtype="String">
{{#select item.data.tmr}} {{#select item.data.tmr}}
<option value="cite">Cité</option> {{>"systems/foundryvtt-reve-de-dragon/templates/sort-tmr.html"}}
<option value="collines">Collines</option>
<option value="desert">Désert</option>
<option value="desolation">Désolation</option>
<option value="fleuve">Fleuve</option>
<option value="foret">Forêt</option>
<option value="gouffre">Gouffre</option>
<option value="lac">Lac</option>
<option value="marais">Marais</option>
<option value="monts">Monts</option>
<option value="necropole">Nécropole</option>
<option value="plaines">Plaines</option>
<option value="pont">Pont</option>
<option value="sanctuaire">Sanctuaire</option>
{{/select}} {{/select}}
</select> </select>
</div> </div>

View File

@ -21,6 +21,7 @@
<select name="data.caseTMR" id="caseTMR" data-dtype="String"> <select name="data.caseTMR" id="caseTMR" data-dtype="String">
{{#select item.data.caseTMR}} {{#select item.data.caseTMR}}
{{>"systems/foundryvtt-reve-de-dragon/templates/sort-tmr.html"}} {{>"systems/foundryvtt-reve-de-dragon/templates/sort-tmr.html"}}
<option value="special">Case spéciale TMR (saisie ci-dessous)</option>
{{/select}} {{/select}}
</select> </select>
</div> </div>

View File

@ -2,7 +2,7 @@
<option value="collines">Collines</option> <option value="collines">Collines</option>
<option value="desert">Désert</option> <option value="desert">Désert</option>
<option value="desolation">Désolation</option> <option value="desolation">Désolation</option>
<option value="fleuve">Fleuve</option> <option value="fleuve">Fleuve de l'Oubli</option>
<option value="foret">Forêt</option> <option value="foret">Forêt</option>
<option value="gouffre">Gouffre</option> <option value="gouffre">Gouffre</option>
<option value="lac">Lac</option> <option value="lac">Lac</option>
@ -12,4 +12,4 @@
<option value="plaines">Plaines</option> <option value="plaines">Plaines</option>
<option value="pont">Pont</option> <option value="pont">Pont</option>
<option value="sanctuaire">Sanctuaire</option> <option value="sanctuaire">Sanctuaire</option>
<option value="special">Case spéciale TMR (saisie ci-dessous)</option>