diff --git a/.gitignore b/.gitignore
index 9c14ae61..f47effc4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
.vscode/settings.json
.idea
-todo.txt
todo.md
/.vscode
+/ignored/
diff --git a/lang/fr.json b/lang/fr.json
index 3201992b..465f180a 100644
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -15,7 +15,8 @@
"TypeNombreastral": "Nombre astral",
"TypeTarot": "Carte de tarot",
"TypeCasetmr": "TMR spéciale",
- "TypeRencontrestmr": "Rencontre TMR",
+ "TypeRencontre": "Rencontre TMR",
+ "TypeRencontrestmr": "Rencontre TMR (ancien)",
"TypeMunition": "Munition",
"TypeMonnaie": "Monnaie",
"TypeHerbe": "Herbe ou plante",
diff --git a/module/actor-creature-sheet.js b/module/actor-creature-sheet.js
index fbced05f..acfd115f 100644
--- a/module/actor-creature-sheet.js
+++ b/module/actor-creature-sheet.js
@@ -1,14 +1,9 @@
+import { RdDActorSheet } from "./actor-sheet.js";
/**
* Extend the basic ActorSheet with some very simple modifications
* @extends {ActorSheet}
*/
-
-import { RdDUtility } from "./rdd-utility.js";
-import { RdDActorSheet } from "./actor-sheet.js";
-import { RdDCarac } from "./rdd-carac.js";
-
-/* -------------------------------------------- */
export class RdDActorCreatureSheet extends RdDActorSheet {
/** @override */
@@ -19,7 +14,7 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
width: 640,
height: 720,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
- dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }]
+ dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
});
}
diff --git a/module/actor-entite-sheet.js b/module/actor-entite-sheet.js
index 4ab81798..42577475 100644
--- a/module/actor-entite-sheet.js
+++ b/module/actor-entite-sheet.js
@@ -1,6 +1,4 @@
import { RdDActorSheet } from "./actor-sheet.js";
-import { HtmlUtility } from "./html-utility.js";
-import { RdDUtility } from "./rdd-utility.js";
export class RdDActorEntiteSheet extends RdDActorSheet {
@@ -12,7 +10,7 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
width: 640,
height: 720,
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac"}],
- dragDrop: [{dragSelector: ".item-list .item", dropSelector: null}]
+ dragDrop: [{dragSelector: ".item-list .item", dropSelector: undefined}]
});
}
diff --git a/module/actor-sheet.js b/module/actor-sheet.js
index 9aed24be..6b103ad2 100644
--- a/module/actor-sheet.js
+++ b/module/actor-sheet.js
@@ -1,8 +1,3 @@
-/**
- * Extend the basic ActorSheet with some very simple modifications
- * @extends {ActorSheet}
- */
-
import { RdDUtility } from "./rdd-utility.js";
import { HtmlUtility } from "./html-utility.js";
import { RdDItemArme } from "./item-arme.js";
@@ -12,12 +7,16 @@ import { Misc } from "./misc.js";
import { RdDCombatManager } from "./rdd-combat.js";
import { RdDCarac } from "./rdd-carac.js";
import { DialogSplitItem } from "./dialog-split-item.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { DialogRepos } from "./dialog-repos.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
-import { STATUSES } from "./status-effects.js";
+import { STATUSES } from "./settings/status-effects.js";
/* -------------------------------------------- */
+/**
+ * Extend the basic ActorSheet with some very simple modifications
+ * @extends {ActorSheet}
+ */
export class RdDActorSheet extends ActorSheet {
/** @override */
@@ -28,7 +27,7 @@ export class RdDActorSheet extends ActorSheet {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html",
width: 640,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
- dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
+ dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
showCompNiveauBase: false,
vueDetaillee: false
});
@@ -102,7 +101,6 @@ export class RdDActorSheet extends ActorSheet {
formData.hautreve = {
isDemiReve: this.actor.getEffect(STATUSES.StatusDemiReve),
- rencontres: duplicate(formData.system.reve.rencontre.list),
cacheTMR: this.actor.isTMRCache()
}
@@ -171,9 +169,6 @@ export class RdDActorSheet extends ActorSheet {
const item = RdDSheetUtility.getItem(event, this.actor);
item.sheet.render(true);
});
- html.find('.rencontre-delete').click(async event => {
- this.actor.deleteTMRRencontre(RdDSheetUtility.getItemId(event));
- });
html.find('.item-delete').click(async event => {
const li = RdDSheetUtility.getEventElement(event);
const item = this.actor.getObjet(li.data("item-id"));
diff --git a/module/actor-vehicule-sheet.js b/module/actor-vehicule-sheet.js
index aa7df7c3..2729f2af 100644
--- a/module/actor-vehicule-sheet.js
+++ b/module/actor-vehicule-sheet.js
@@ -1,5 +1,4 @@
import { RdDUtility } from "./rdd-utility.js";
-import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { RdDActorSheet } from "./actor-sheet.js";
/* -------------------------------------------- */
@@ -15,7 +14,7 @@ export class RdDActorVehiculeSheet extends RdDActorSheet {
width: 640,
height: 720,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
- dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }]
+ dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
});
}
diff --git a/module/actor.js b/module/actor.js
index 6d41ab33..5d6b291b 100644
--- a/module/actor.js
+++ b/module/actor.js
@@ -17,12 +17,11 @@ import { RdDAudio } from "./rdd-audio.js";
import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemArme } from "./item-arme.js";
import { RdDAlchimie } from "./rdd-alchimie.js";
-import { STATUSES, StatusEffects } from "./status-effects.js";
+import { STATUSES, StatusEffects } from "./settings/status-effects.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { TMRRencontres } from "./tmr-rencontres.js";
-import { Poetique } from "./poetique.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { Draconique } from "./tmr/draconique.js";
import { RdDCarac } from "./rdd-carac.js";
@@ -36,6 +35,7 @@ import { RdDPossession } from "./rdd-possession.js";
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { RdDConfirm } from "./rdd-confirm.js";
import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js";
+import { RdDRencontre } from "./item-rencontre.js";
const POSSESSION_SANS_DRACONIC = {
img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
@@ -56,6 +56,7 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
static init() {
Hooks.on("preUpdateItem", (item, change, options, id) => RdDActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id));
+ // TODO: replace with pre-hooks?
Hooks.on("createItem", (item, options, id) => RdDActor.getParentActor(item)?.onCreateItem(item, options, id));
Hooks.on("deleteItem", (item, options, id) => RdDActor.getParentActor(item)?.onDeleteItem(item, options, id));
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId));
@@ -756,25 +757,24 @@ export class RdDActor extends Actor {
actor: this,
competence: duplicate(this.getDraconicOuPossession()),
canClose: false,
- rencontre: duplicate(TMRRencontres.getRencontre('rdd')),
+ rencontre: await TMRRencontres.getReveDeDragon(force),
tmr: true,
use: { libre: false, conditions: false },
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.getReveActuel() } }
}
- rollData.rencontre.force = force;
rollData.competence.system.defaut_carac = 'reve-actuel';
const dialog = await RdDRoll.create(this, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-reve-de-dragon.html',
- options: { height: 400 }
+ options: { height: 'fit-content' }
},
{
name: 'maitrise',
label: 'Maîtriser le Rêve de Dragon',
callbacks: [
- this.createCallbackExperience(),
- { action: async r => this.resultCombatReveDeDragon(r) }
+ { action: async r =>
+ this.resultCombatReveDeDragon(r) }
]
}
);
@@ -783,27 +783,11 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async resultCombatReveDeDragon(rollData) {
- rollData.queues = [];
- if (rollData.rolled.isEchec) {
- rollData.queues.push(await this.ajouterQueue());
- }
- if (rollData.rolled.isETotal) {
- rollData.queues.push(await this.ajouterQueue());
- }
- if (rollData.rolled.isSuccess) {
- await this.updatePointDeSeuil();
- await this.reveActuelIncDec(rollData.rencontre.force);
- }
- if (rollData.rolled.isPart) {
- // TODO: un dialogue pour demander le type de tête?
- rollData.tete = true;
- }
- rollData.poesie = await Poetique.getExtrait();
+ const result = rollData.rolled.isSuccess
+ ? rollData.rencontre.system.succes
+ : rollData.rencontre.system.echec;
- ChatMessage.create({
- whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
- content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, rollData)
- });
+ RdDRencontre.appliquer(result.effets, {}, rollData)
}
/* -------------------------------------------- */
@@ -1540,42 +1524,27 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
getTMRRencontres() {
- return this.system.reve.rencontre.list;
+ return this.itemTypes['rencontre'];
}
/* -------------------------------------------- */
async deleteTMRRencontreAtPosition() {
- let rencontres = this.getTMRRencontres();
- let newRencontres = rencontres.filter(it => it.coord != this.getDemiReve());
- if (newRencontres.length != rencontres.length) {
- await this.update({ "system.reve.rencontre.list": newRencontres });
+ const demiReve = this.getDemiReve()
+ let rencontreIds = this.items.filter(it => it.type == 'rencontre' && it.system.coord == demiReve).map(it => it.id);
+ if (rencontreIds.length>0) {
+ await this.deleteEmbeddedDocuments('Item', rencontreIds);
}
}
/* -------------------------------------------- */
async addTMRRencontre(currentRencontre) {
- let rencontres = this.getTMRRencontres();
- let newRencontres = rencontres.filter(it => it.coord != this.getDemiReve());
- if (newRencontres.length == rencontres.length) {
- newRencontres.push(currentRencontre);
- await this.update({ "system.reve.rencontre.list": newRencontres });
- }
- }
-
- /* -------------------------------------------- */
- async deleteTMRRencontre(rencontreKey) {
- let list = duplicate(this.system.reve.rencontre.list);
- let newList = [];
- for (let i = 0; i < list.length; i++) {
- if (i != rencontreKey)
- newList.push(list[i]);
- }
- await this.update({ "system.reve.rencontre.list": newList });
+ const toCreate = currentRencontre.toObject();
+ console.log('actor.addTMRRencontre(', toCreate,')');
+ this.createEmbeddedDocuments('Item', [toCreate]);
}
/* -------------------------------------------- */
async updateCoordTMR(coord) {
- //console.log("UPDATE TMR", coord);
await this.update({ "system.reve.tmrpos.coord": coord });
}
@@ -1586,11 +1555,13 @@ export class RdDActor extends Actor {
}
/* -------------------------------------------- */
- async updatePointDeSeuil(value = 1) {
+ async regainPointDeSeuil() {
const seuil = Misc.toInt(this.system.reve.seuil.value);
- const reve = Misc.toInt(this.system.carac.reve.value);
- if (seuil < reve) {
- await this.setPointsDeSeuil(Math.min(seuil + value, reve));
+ const seuilMax = Misc.toInt(this.system.carac.reve.value)
+ + 2 * EffetsDraconiques.countAugmentationSeuil(this);
+
+ if (seuil < seuilMax) {
+ await this.setPointsDeSeuil(Math.min(seuil + 1, seuilMax));
}
}
@@ -2382,7 +2353,7 @@ export class RdDActor extends Actor {
}
/* -------------------------------------------- */
- isRencontreSpeciale() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective'
+ isMauvaiseRencontre() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective'
let addMsg = "";
let rencSpecial = EffetsDraconiques.mauvaiseRencontre(this);
if (rencSpecial) {
@@ -3824,7 +3795,7 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
_buildActorLinksList(links, actorTransformation = it => RdDActor._buildActorData(it)) {
return links.map(link => game.actors.get(link.id))
- .filter(it => it != null)
+ .filter(it => it != undefined)
.map(actorTransformation);
}
diff --git a/module/dialog-chronologie.js b/module/dialog-chronologie.js
index 7b780d1b..0e84e358 100644
--- a/module/dialog-chronologie.js
+++ b/module/dialog-chronologie.js
@@ -6,7 +6,7 @@ const LATEST_USED_JOURNAL_ID = "chronologie-dernier-journal";
export class DialogChronologie extends Dialog {
- static onInit() {
+ static init() {
game.settings.register(SYSTEM_RDD, LATEST_USED_JOURNAL_ID, {
name: "Dernier article de journal utilisé pour enregistrer la chronologie",
scope: "client",
diff --git a/module/effets-rencontres.js b/module/effets-rencontres.js
new file mode 100644
index 00000000..37599d15
--- /dev/null
+++ b/module/effets-rencontres.js
@@ -0,0 +1,137 @@
+import { ChatUtility } from "./chat-utility.js";
+import { Poetique } from "./poetique.js";
+import { RdDDice } from "./rdd-dice.js";
+import { TMRUtility } from "./tmr-utility.js";
+
+export class EffetsRencontre {
+
+ static messager = async (dialog, context) => {
+ dialog.setRencontreState('messager', TMRUtility.getTMRPortee(context.tmr.coord, context.rencontre.system.force));
+ }
+
+ static passeur = async (dialog, context) => {
+ dialog.setRencontreState('passeur', TMRUtility.getTMRPortee(context.tmr.coord, context.rencontre.system.force));
+ }
+
+ static teleportation_typecase = async (dialog, context) => {
+ dialog.setRencontreState('changeur', TMRUtility.getCasesType(context.tmr.type));
+ }
+
+ static rencontre_persistante = async (dialog, context) => {
+ dialog.setRencontreState('persistant', []);
+ }
+
+ static reve_plus_force = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, context.rencontre.system.force) }
+ static reve_plus_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, 1) }
+ static reve_moins_force = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -context.rencontre.system.force) }
+ static reve_moins_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -1) }
+ static $reve_plus = async (actor, valeur) => { await actor.reveActuelIncDec(valeur) }
+
+ static vie_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
+ static vie_moins_force = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -context.rencontre.system.force) }
+ static $vie_plus = async (actor, valeur) => { await actor.santeIncDec("vie", valeur) }
+
+ static moral_plus_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, 1) }
+ static moral_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
+ static $moral_plus = async (actor, valeur) => { await actor.moralIncDec(valeur) }
+
+ static end_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
+ static end_moins_force = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -context.rencontre.system.force) }
+ static $end_plus = async (actor, valeur) => { await actor.santeIncDec("endurance", valeur) }
+
+ static fatigue_plus_1 = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, 1) }
+ static fatigue_plus_force = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, context.rencontre.system.force) }
+ static fatigue_moins_1 = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, -1) }
+ static fatigue_moins_force = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, -context.rencontre.system.force) }
+ static $fatigue_plus = async (actor, valeur) => { await actor.santeIncDec("fatigue", valeur) }
+
+ static perte_chance = async (dialog, context) => {
+ const perte = context.rolled.isETotal ? context.rencontre.system.force : 1;
+ await context.actor.chanceActuelleIncDec("fatigue", -perte);
+ }
+
+ static xp_sort_force = async (dialog, context) => {
+ let competence = context.competence;
+ if (competence) {
+ const xpSort = Misc.toInt(competence.system.xp_sort) + context.rencontre.system.force;
+ await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': xpSort }]);
+ await this.updateExperienceLog("XP Sort", xpSort, `Rencontre d'un ${context.rencontre.name} en TMR`);
+ }
+ }
+
+ static stress_plus_1 = async (dialog, context) => {
+ await context.actor.addCompteurValue('stress', 1, `Rencontre d'un ${context.rencontre.name} en TMR`);
+ }
+
+ static reinsertion = async (dialog, context) => {
+ await EffetsRencontre.$reinsertion(dialog, context.actor, it => true)
+ }
+
+ static teleportation_aleatoire_typecase = async (dialog, context) => {
+ await EffetsRencontre.$reinsertion(dialog, context.actor, it => it.type == context.tmr.type && it.coord != context.tmr.coord)
+ }
+
+ static demireve_rompu = async (dialog, context) => {
+ dialog.close()
+ }
+
+ static sort_aleatoire = async (dialog, context) => {
+ context.sortReserve = await RdDDice.rollOneOf(context.actor.itemTypes['sortreserve']);
+ if (context.sortReserve) {
+ context.newTMR = TMRUtility.getTMR(context.sortReserve.system.coord);
+ await dialog.positionnerDemiReve(context.newTMR.coord);
+ await dialog.processSortReserve(context.sortReserve);
+ dialog.close();
+ }
+ else {
+ await EffetsRencontre.$reinsertion(dialog, context.actor, it => true);
+ }
+ }
+
+ static deplacement_aleatoire = async (dialog, context) => {
+ const oldCoord = context.actor.system.reve.tmrpos.coord;
+ const newTmr = await TMRUtility.deplaceTMRAleatoire(context.actor, oldCoord);
+ await dialog.positionnerDemiReve(newTmr.coord)
+ }
+
+ static rdd_part_tete = async (dialog, context) => {
+ mergeObject(context, {
+ tete: context.rolled.isPart,
+ poesie: await Poetique.getExtrait()
+ })
+ ChatMessage.create({
+ whisper: ChatUtility.getWhisperRecipientsAndGMs(context.actor.name),
+ content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, context)
+ });
+ }
+
+ static rdd_echec_queue = async (dialog, context) => {
+ mergeObject(context, {
+ queues: [await context.actor.ajouterQueue()],
+ poesie: await Poetique.getExtrait()
+ })
+ if (context.rolled.isETotal) {
+ context.queues.push(await context.actor.ajouterQueue());
+ }
+
+ ChatMessage.create({
+ whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
+ content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, context)
+ });
+ }
+
+ static experience_particuliere = async (dialog, context) => {
+ await context.actor.appliquerAjoutExperience(context)
+ }
+
+ static regain_seuil = async (dialog, context) => {
+ await context.actor.regainPointDeSeuil()
+ }
+
+ static async $reinsertion(dialog, actor, filter) {
+ const newTMR = await TMRUtility.getTMRAleatoire(filter);
+ await actor.forcerPositionTMRInconnue(newTMR);
+ await dialog.positionnerDemiReve(newTMR.coord);
+ }
+
+}
diff --git a/module/item-rencontre-sheet.js b/module/item-rencontre-sheet.js
new file mode 100644
index 00000000..baaf5d8d
--- /dev/null
+++ b/module/item-rencontre-sheet.js
@@ -0,0 +1,108 @@
+import { RdDRencontre } from "./item-rencontre.js";
+
+/**
+ * Item sheet pour configurer les rencontres
+ * @extends {ItemSheet}
+ */
+export class RdDRencontreItemSheet extends ItemSheet {
+
+ /** @override */
+ static get defaultOptions() {
+ return mergeObject(super.defaultOptions, {
+ classes: ["rdd", "sheet", "item"],
+ template: "systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html",
+ width: 500,
+ height: 500,
+ tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }]
+ });
+ }
+
+ /* -------------------------------------------- */
+ _getHeaderButtons() {
+ let buttons = super._getHeaderButtons();
+ buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => this.item.postItem() });
+ return buttons;
+ }
+
+ /* -------------------------------------------- */
+ /** @override */
+ setPosition(options = {}) {
+ const position = super.setPosition(options);
+ const sheetHeader = this.element.find(".sheet-header");
+ const sheetBody = this.element.find(".sheet-body");
+ sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
+ return position;
+ }
+
+
+ /* -------------------------------------------- */
+ async getData() {
+ const formData = duplicate(this.item);
+ mergeObject(formData, {
+ title: formData.name,
+ isGM: game.user.isGM,
+ owner: this.actor?.isOwner,
+ isOwned: this.actor ? true : false,
+ actorId: this.actor?.id,
+ editable: this.isEditable,
+ cssClass: this.isEditable ? "editable" : "locked",
+ effets: {
+ succes: {
+ liste: RdDRencontre.getEffetsSucces(),
+ select: RdDRencontre.mapEffets(this.item.system.succes.effets)
+ },
+ echec: {
+ liste: RdDRencontre.getEffetsEchec(),
+ select: RdDRencontre.mapEffets(this.item.system.echec.effets)
+ }
+ }
+ });
+ return formData;
+ }
+
+ /* -------------------------------------------- */
+ /** @override */
+ activateListeners(html) {
+ super.activateListeners(html);
+ if (!this.options.editable) return;
+ html.find("a.effet-add").click(event => this.onAddEffet(event));
+ html.find("a.effet-delete").click(event => this.onDeleteEffet(event));
+ }
+
+ async onAddEffet(event) {
+ const resultat = $(event.currentTarget)?.data("effet-resultat");
+ const keyEffets = `system.${resultat}.effets`;
+
+ const code = $(event.currentTarget)?.data("effet-code");
+ const liste = RdDRencontre.getListeEffets(this.item, resultat);
+ liste.push(code);
+
+ await this._updateEffetsRencontre(keyEffets, liste);
+ }
+
+ async onDeleteEffet(event) {
+ const resultat = $(event.currentTarget)?.data("effet-resultat");
+ const keyEffets = `system.${resultat}.effets`;
+
+ const pos = $(event.currentTarget)?.data("effet-pos");
+ const liste = RdDRencontre.getListeEffets(this.item, resultat);
+ liste.splice(pos, 1);
+
+ await this._updateEffetsRencontre(keyEffets, liste);
+ }
+
+ async _updateEffetsRencontre(key, liste) {
+ const updates = {};
+ updates[key] = liste;
+ this.item.update(updates);
+ }
+
+ get template() {
+ /* -------------------------------------------- */
+ return `systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html`;
+ }
+
+ get title() {
+ return `Rencontre: ${this.object.name}`;
+ }
+}
diff --git a/module/item-rencontre.js b/module/item-rencontre.js
new file mode 100644
index 00000000..519b5129
--- /dev/null
+++ b/module/item-rencontre.js
@@ -0,0 +1,71 @@
+import { EffetsRencontre } from "./effets-rencontres.js";
+
+const tableEffets = [
+ { code: "messager", resultat: "succes", description: "Envoie un message à (force) cases", method: EffetsRencontre.messager },
+ { code: "passeur", resultat: "succes", description: "Déplacer le demi-rêve à (force) cases", method: EffetsRencontre.passeur},
+ { code: "reve+f", resultat: "succes", description: "Gain de (force) points de rêve" , method: EffetsRencontre.reve_plus_force},
+ { code: "teleport", resultat: "succes", description: "Déplacer le demi-rêve (même type)", method: EffetsRencontre.teleportation_typecase },
+ { code: "part+tete", resultat: "succes", description: "Tête de dragon sur réussite particulière", method: EffetsRencontre.rdd_part_tete },
+ { code: "part+xp", resultat: "succes", description: "Expérience sur réussite particulière", method: EffetsRencontre.experience_particuliere },
+ { code: "seuil", resultat: "succes", description: "Récupération de seuil de rêve", method: EffetsRencontre.regain_seuil },
+
+ { code: "reve-1", resultat: "echec", description: "Perte de 1 point de rêve", method: EffetsRencontre.reve_moins_1 },
+ { code: "reve-f", resultat: "echec", description: "Perte de (force) points de rêve", method: EffetsRencontre.reve_moins_force },
+ { code: "vie-1", resultat: "echec", description: "Perte de 1 point de vie", method: EffetsRencontre.vie_moins_1 },
+ { code: "reinsere", resultat: "echec", description: "Réinsertion aléatoire", method: EffetsRencontre.reinsertion },
+ { code: "persistant", resultat: "echec", description: "Bloque le demi-rêve", method: EffetsRencontre.rencontre_persistante },
+ { code: "teleport-aleatoire", resultat: "echec", description: "Déplacement aléatoire (même type)", method: EffetsRencontre.teleportation_aleatoire_typecase },
+ { code: "aleatoire", resultat: "echec", description: "Déplacement aléatoire", method: EffetsRencontre.deplacement_aleatoire },
+ { code: "sort-aleatoire", resultat: "echec", description: "Déclenche un sort en réserve aléatoire", method: EffetsRencontre.sort_aleatoire },
+ { code: "rompu", resultat: "echec", description: "Demi-rêve interrompu", method: EffetsRencontre.demireve_rompu },
+ { code: "echec-queue", resultat: "echec", description: "Queue(s) de dragon sur échec", method: EffetsRencontre.rdd_echec_queue },
+
+ { code: "reve+1", resultat: "succes", description: "Gain de 1 point de rêve", method: EffetsRencontre.reve_plus_1 },
+ { code: "vie-f", resultat: "echec", description: "Perte de (force) points de vie", method: EffetsRencontre.vie_moins_force },
+ { code: "moral+1", resultat: "succes", description: "Gain de 1 point de moral", method: EffetsRencontre.moral_plus_1 },
+ { code: "moral-1", resultat: "echec", description: "Perte de 1 point de moral", method: EffetsRencontre.moral_moins_1 },
+ { code: "xpsort+f", resultat: "succes", description: "Gain de (force) xp sort", method: EffetsRencontre.xp_sort_force },
+ { code: "endurance-1", resultat: "echec", description: "Perte de 1 point d'endurance", method: EffetsRencontre.end_moins_1 },
+ { code: "endurance-f", resultat: "echec", description: "Perte de (force) points d'endurance", method: EffetsRencontre.end_moins_force },
+ { code: "fatigue+1", resultat: "echec", description: "Coup de fatigue de 1 point", method: EffetsRencontre.fatigue_plus_1},
+ { code: "fatigue+f", resultat: "echec", description: "Coup de fatigue de 1 (force) points", method: EffetsRencontre.fatigue_plus_force },
+ { code: "fatigue-1", resultat: "succes", description: "Récupération de 1 point de fatigue", method: EffetsRencontre.fatigue_moins_1},
+ { code: "fatigue-f", resultat: "succes", description: "Récupération de 1 (force) points de fatigue", method: EffetsRencontre.fatigue_moins_force },
+ { code: "perte-chance", resultat: "echec", description: "Perte de chance actuelle", method: EffetsRencontre.perte_chance },
+ { code: "stress+1", resultat: "succes", description: "Gain de 1 point de stress", method: EffetsRencontre.stress_plus_1 },
+ // { code: "epart-souffle", resultat: "echec", description: "Souffle de dragon sur échec particulier" },
+];
+
+export class RdDRencontre {
+
+ static getEffetsSucces() { return RdDRencontre.getEffets("succes"); }
+ static getEffetsEchec() { return RdDRencontre.getEffets("echec"); }
+ static getEffets(resultat) {
+ return tableEffets.filter(e => resultat == e.resultat);
+ }
+
+ static mapEffets(liste) {
+ return liste.map(it => RdDRencontre.getEffet(it));
+ }
+
+ static getListeEffets(item, reussite) {
+ if (reussite == 'echec') {
+ return [...item.system.echec.effets];
+ }
+ if (reussite == 'succes') {
+ return [...item.system.succes.effets];
+ }
+ return [];
+ }
+
+ static getEffet(code) {
+ return tableEffets.find(it => code == it.code)
+ }
+
+ static async appliquer(codes, tmrDialog, rencData) {
+ for(const effet of RdDRencontre.mapEffets(codes)){
+ await effet.method(tmrDialog, rencData);
+ }
+ }
+
+}
diff --git a/module/item-sheet.js b/module/item-sheet.js
index 4c23b1ba..59c68d95 100644
--- a/module/item-sheet.js
+++ b/module/item-sheet.js
@@ -4,9 +4,8 @@ import { RdDAlchimie } from "./rdd-alchimie.js";
import { RdDItemCompetence } from "./item-competence.js";
import { RdDHerbes } from "./rdd-herbes.js";
import { RdDGemme } from "./rdd-gemme.js";
-import { Misc } from "./misc.js";
import { HtmlUtility } from "./html-utility.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { SYSTEM_RDD } from "./constants.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
@@ -67,8 +66,6 @@ export class RdDItemSheet extends ItemSheet {
img: this.item.img,
name: this.item.name,
system: this.item.system,
- // TODO: v10 remove
- data: this.item.system,
isGM: game.user.isGM,
actorId: this.actor?.id,
owner: this.item.isOwner,
diff --git a/module/item-signedraconique-sheet.js b/module/item-signedraconique-sheet.js
index 3e013f4b..f3c33fdd 100644
--- a/module/item-signedraconique-sheet.js
+++ b/module/item-signedraconique-sheet.js
@@ -1,7 +1,6 @@
import { SYSTEM_RDD } from "./constants.js";
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
-import { Misc } from "./misc.js";
-import { TMRType, TMRUtility } from "./tmr-utility.js";
+import { TMRUtility } from "./tmr-utility.js";
/**
* Item sheet pour signes draconiques
diff --git a/module/item.js b/module/item.js
index 0652d11c..9f2396fe 100644
--- a/module/item.js
+++ b/module/item.js
@@ -18,7 +18,7 @@ const typesObjetsEquipement = [
"potion",
]
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
-const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve"]
+const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"]
const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
const typesObjetsEffet = ["possession", "poison", "maladie"]
const typesObjetsCompetence = ["competence", "competencecreature"]
@@ -38,6 +38,7 @@ export const defaultItemImg = {
ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp",
livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp",
potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp",
+ rencontre: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp",
queue: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
ombre: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
@@ -301,8 +302,7 @@ export class RdDItem extends Item {
async postItem(modeOverride) {
console.log(this);
let chatData = duplicate(this);
- const properties = this.getProprietes();
- chatData["properties"] = properties
+ chatData["properties"] = this.getProprietes();
if (this.actor) {
chatData.actor = { id: this.actor.id };
}
@@ -325,254 +325,218 @@ export class RdDItem extends Item {
/* -------------------------------------------- */
_objetChatData() {
- const tplData = this.system
- let properties = [].concat(
- RdDItem.propertyIfDefined('Résistance', tplData.resistance, tplData.resistance),
- RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
- RdDItem.propertyIfDefined('Encombrement', tplData.encombrement),
+ return [].concat(
+ RdDItem.propertyIfDefined('Résistance', this.system.resistance, this.system.resistance),
+ RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite),
+ RdDItem.propertyIfDefined('Encombrement', this.system.encombrement),
);
- return properties;
}
/* -------------------------------------------- */
_nourritureboissonChatData() {
- const tplData = this.system
- let properties = [].concat(
- RdDItem.propertyIfDefined('Sustentation', tplData.sust, tplData.sust > 0),
- RdDItem.propertyIfDefined('Désaltère', tplData.desaltere, tplData.boisson),
- RdDItem.propertyIfDefined('Force alcool', tplData.force, tplData.boisson && tplData.alcoolise),
- RdDItem.propertyIfDefined('Exotisme', tplData.exotisme, tplData.exotisme < 0),
- RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
- RdDItem.propertyIfDefined('Encombrement', tplData.encombrement),
+ return [].concat(
+ RdDItem.propertyIfDefined('Sustentation', this.system.sust, this.system.sust > 0),
+ RdDItem.propertyIfDefined('Désaltère', this.system.desaltere, this.system.boisson),
+ RdDItem.propertyIfDefined('Force alcool', this.system.force, this.system.boisson && this.system.alcoolise),
+ RdDItem.propertyIfDefined('Exotisme', this.system.exotisme, this.system.exotisme < 0),
+ RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite),
+ RdDItem.propertyIfDefined('Encombrement', this.system.encombrement),
);
- return properties;
}
/* -------------------------------------------- */
_armeChatData() {
- const tplData = this.system
- let properties = [
- `Compétence: ${tplData.competence}`,
- `Dommages: ${tplData.dommages}`,
- `Force minimum: ${tplData.force}`,
- `Resistance: ${tplData.resistance}`,
- `Encombrement: ${tplData.encombrement}`
+ return [
+ `Compétence: ${this.system.competence}`,
+ `Dommages: ${this.system.dommages}`,
+ `Force minimum: ${this.system.force}`,
+ `Resistance: ${this.system.resistance}`,
+ `Encombrement: ${this.system.encombrement}`
]
- return properties;
}
/* -------------------------------------------- */
_conteneurChatData() {
- const tplData = this.system
- let properties = [
- `Capacité: ${tplData.capacite} Enc.`,
- `Encombrement: ${tplData.encombrement}`
+ return [
+ `Capacité: ${this.system.capacite} Enc.`,
+ `Encombrement: ${this.system.encombrement}`
]
- return properties;
}
/* -------------------------------------------- */
_munitionChatData() {
- const tplData = this.system
- let properties = [
- `Encombrement: ${tplData.encombrement}`
+ return [
+ `Encombrement: ${this.system.encombrement}`
]
- return properties;
}
/* -------------------------------------------- */
_armureChatData() {
- const tplData = this.system
- let properties = [
- `Protection: ${tplData.protection}`,
- `Détérioration: ${tplData.deterioration}`,
- `Malus armure: ${tplData.malus}`,
- `Encombrement: ${tplData.encombrement}`
+ return [
+ `Protection: ${this.system.protection}`,
+ `Détérioration: ${this.system.deterioration}`,
+ `Malus armure: ${this.system.malus}`,
+ `Encombrement: ${this.system.encombrement}`
]
- return properties;
}
/* -------------------------------------------- */
_competenceChatData() {
- const tplData = this.system
- let properties = [
- `Catégorie: ${tplData.categorie}`,
- `Niveau: ${tplData.niveau}`,
- `Caractéristique par défaut: ${tplData.carac_defaut}`,
- `XP: ${tplData.xp}`
+ return [
+ `Catégorie: ${this.system.categorie}`,
+ `Niveau: ${this.system.niveau}`,
+ `Caractéristique par défaut: ${this.system.carac_defaut}`,
+ `XP: ${this.system.xp}`
]
- return properties;
}
/* -------------------------------------------- */
_competencecreatureChatData() {
- const tplData = this.system
- let properties = [
- `Catégorie: ${tplData.categorie}`,
- `Niveau: ${tplData.niveau}`,
- `Caractéristique: ${tplData.carac_value}`,
- `XP: ${tplData.xp}`
+ return [
+ `Catégorie: ${this.system.categorie}`,
+ `Niveau: ${this.system.niveau}`,
+ `Caractéristique: ${this.system.carac_value}`,
+ `XP: ${this.system.xp}`
]
- return properties;
}
/* -------------------------------------------- */
_sortChatData() {
- const tplData = this.system
- let properties = [
- `Draconic: ${tplData.draconic}`,
- `Difficulté: ${tplData.difficulte}`,
- `Case TMR: ${tplData.caseTMR}`,
- `Points de Rêve: ${tplData.ptreve}`
+ return [
+ `Draconic: ${this.system.draconic}`,
+ `Difficulté: ${this.system.difficulte}`,
+ `Case TMR: ${this.system.caseTMR}`,
+ `Points de Rêve: ${this.system.ptreve}`
]
- return properties;
}
/* -------------------------------------------- */
_herbeChatData() {
- const tplData = this.system
- let properties = [
- `Milieu: ${tplData.milieu}`,
- `Rareté: ${tplData.rarete}`,
- `Catégorie: ${tplData.categorie}`,
+ return [
+ `Milieu: ${this.system.milieu}`,
+ `Rareté: ${this.system.rarete}`,
+ `Catégorie: ${this.system.categorie}`,
]
- return properties;
}
/* -------------------------------------------- */
_ingredientChatData() {
- const tplData = this.system
- let properties = [
- `Milieu: ${tplData.milieu}`,
- `Rareté: ${tplData.rarete}`,
- `Catégorie: ${tplData.categorie}`,
+ return [
+ `Milieu: ${this.system.milieu}`,
+ `Rareté: ${this.system.rarete}`,
+ `Catégorie: ${this.system.categorie}`,
]
- return properties;
}
/* -------------------------------------------- */
_tacheChatData() {
- const tplData = this.system
- let properties = [
- `Caractéristique: ${tplData.carac}`,
- `Compétence: ${tplData.competence}`,
- `Périodicité: ${tplData.periodicite}`,
- `Fatigue: ${tplData.fatigue}`,
- `Difficulté: ${tplData.difficulte}`
+ return [
+ `Caractéristique: ${this.system.carac}`,
+ `Compétence: ${this.system.competence}`,
+ `Périodicité: ${this.system.periodicite}`,
+ `Fatigue: ${this.system.fatigue}`,
+ `Difficulté: ${this.system.difficulte}`
].concat([
- tplData.cacher_points_de_tache ? [] :`Points de Tâche: ${tplData.points_de_tache}`
+ this.system.cacher_points_de_tache ? [] :`Points de Tâche: ${this.system.points_de_tache}`
]).concat([
- `Points de Tâche atteints: ${tplData.points_de_tache_courant}`]
+ `Points de Tâche atteints: ${this.system.points_de_tache_courant}`]
);
- return properties;
}
/* -------------------------------------------- */
_livreChatData() {
- const tplData = this.system
- let properties = [
- `Compétence: ${tplData.competence}`,
- `Auteur: ${tplData.auteur}`,
- `Difficulté: ${tplData.difficulte}`,
- `Points de Tâche: ${tplData.points_de_tache}`,
- `Encombrement: ${tplData.encombrement}`
+ return [
+ `Compétence: ${this.system.competence}`,
+ `Auteur: ${this.system.auteur}`,
+ `Difficulté: ${this.system.difficulte}`,
+ `Points de Tâche: ${this.system.points_de_tache}`,
+ `Encombrement: ${this.system.encombrement}`
]
- return properties;
}
/* -------------------------------------------- */
_potionChatData() {
- const tplData = this.system
- let properties = [
- `Rareté: ${tplData.rarete}`,
- `Catégorie: ${tplData.categorie}`,
- `Encombrement: ${tplData.encombrement}`,
+ return [
+ `Rareté: ${this.system.rarete}`,
+ `Catégorie: ${this.system.categorie}`,
+ `Encombrement: ${this.system.encombrement}`,
]
- return properties;
}
/* -------------------------------------------- */
_queueChatData() {
- const tplData = this.system
- let properties = [
- `Refoulement: ${tplData.refoulement}`
+ return [
+ `Refoulement: ${this.system.refoulement}`
]
- return properties;
}
/* -------------------------------------------- */
_ombreChatData() {
- const tplData = this.system
- let properties = [
- `Refoulement: ${tplData.refoulement}`
+ return [
+ `Refoulement: ${this.system.refoulement}`
]
- return properties;
}
/* -------------------------------------------- */
_souffleChatData() {
- const tplData = this.system
- let properties = [];
- return properties;
+ return [];
}
/* -------------------------------------------- */
_teteChatData() {
- const tplData = this.system
- let properties = [];
- return properties;
+ return [];
}
/* -------------------------------------------- */
_tarotChatData() {
- const tplData = this.system
- let properties = [
- `Concept: ${tplData.concept}`,
- `Aspect: ${tplData.aspect}`,
+ return [
+ `Concept: ${this.system.concept}`,
+ `Aspect: ${this.system.aspect}`,
]
- return properties;
}
/* -------------------------------------------- */
_nombreastralChatData() {
- const tplData = this.system
- let properties = [
- `Valeur: ${tplData.value}`,
- `Jour: ${tplData.jourlabel}`,
+ return [
+ `Valeur: ${this.system.value}`,
+ `Jour: ${this.system.jourlabel}`,
]
- return properties;
}
/* -------------------------------------------- */
_monnaieChatData() {
- const tplData = this.system
- let properties = [
- `Valeur en Deniers: ${tplData.valeur_deniers}`,
- `Encombrement: ${tplData.encombrement}`
+ return [
+ `Valeur en Deniers: ${this.system.valeur_deniers}`,
+ `Encombrement: ${this.system.encombrement}`
]
- return properties;
}
/* -------------------------------------------- */
_meditationChatData() {
- const tplData = this.system
- let properties = [
- `Thème: ${tplData.theme}`,
- `Compétence: ${tplData.competence}`,
- `Support: ${tplData.support}`,
- `Heure: ${tplData.heure}`,
- `Purification: ${tplData.purification}`,
- `Vêture: ${tplData.veture}`,
- `Comportement: ${tplData.comportement}`,
- `Case TMR: ${tplData.tmr}`
+ return [
+ `Thème: ${this.system.theme}`,
+ `Compétence: ${this.system.competence}`,
+ `Support: ${this.system.support}`,
+ `Heure: ${this.system.heure}`,
+ `Purification: ${this.system.purification}`,
+ `Vêture: ${this.system.veture}`,
+ `Comportement: ${this.system.comportement}`,
+ `Case TMR: ${this.system.tmr}`
+ ]
+ }
+ /* -------------------------------------------- */
+ _rencontreChatData() {
+ if (this.system.coord) {
+ return [
+ `Force: ${this.system.force}`,
+ `Coordonnées: ${this.system.coord}`,
+ ]
+ }
+ return [
+ `Force: ${this.system.force}`,
+ `Refoulement: ${this.system.refoulement}`,
+ `Présent de cités: ${this.system.presentCite}`,
]
- return properties;
}
/* -------------------------------------------- */
_casetmrChatData() {
- const tplData = this.system
- let properties = [
- `Coordonnée: ${tplData.coord}`,
- `Spécificité: ${tplData.specific}`
+ return [
+ `Coordonnée: ${this.system.coord}`,
+ `Spécificité: ${this.system.specific}`
]
- return properties;
}
/* -------------------------------------------- */
_maladieChatData() {
- const tplData = this.system
- let properties
- if (tplData.identifie) {
- properties = [
- `Malignité: ${tplData.malignite}`,
- `Périodicité: ${tplData.periodicite}`,
- `Dommages: ${tplData.dommages}`
+ if (!this.system.identifie) {
+ return [`Inconnue`]
+ }
+ let properties = [
+ `Malignité: ${this.system.malignite}`,
+ `Périodicité: ${this.system.periodicite}`,
+ `Dommages: ${this.system.dommages}`
]
- if (tplData.remedesconnus) {
- properties.push(`Remedes: ${tplData.remedes}`)
- }
- } else {
- properties = [
- `Inconnue`]
+ if (this.system.remedesconnus) {
+ properties.push(`Remedes: ${this.system.remedes}`)
}
return properties;
}
@@ -584,15 +548,13 @@ export class RdDItem extends Item {
/* -------------------------------------------- */
_gemmeChatData() {
- const tplData = this.system
- let properties = [
- `Pureté: ${tplData.purete}`,
- `Taille: ${tplData.taille}`,
- `Inertie: ${tplData.inertie}`,
- `Enchantabilité: ${tplData.enchantabilite}`,
- `Prix: ${tplData.cout}`,
+ return [
+ `Pureté: ${this.system.purete}`,
+ `Taille: ${this.system.taille}`,
+ `Inertie: ${this.system.inertie}`,
+ `Enchantabilité: ${this.system.enchantabilite}`,
+ `Prix: ${this.system.cout}`,
]
- return properties;
}
diff --git a/module/migrations.js b/module/migrations.js
index 9e3fd2f2..f04c9e43 100644
--- a/module/migrations.js
+++ b/module/migrations.js
@@ -43,7 +43,7 @@ class _10_0_16_MigrationSortsReserve extends Migration {
await actor.createEmbeddedDocuments("Item", sortsReserve, {
renderSheet: false,
});
- await actor.update({ 'system.reve.reserve.list': [] })
+ await actor.update({ 'system.reve.reserve': undefined })
});
}
diff --git a/module/rdd-calendrier.js b/module/rdd-calendrier.js
index 1377b26d..b5221454 100644
--- a/module/rdd-calendrier.js
+++ b/module/rdd-calendrier.js
@@ -86,14 +86,14 @@ export class RdDCalendrier extends Application {
getCalendrier(index) {
index = index ?? this.getCurrentDayIndex();
- const moisRdD = Math.floor(index / RDD_JOUR_PAR_MOIS) % RDD_MOIS_PAR_AN;
+ const mois = Math.floor(index / RDD_JOUR_PAR_MOIS) % RDD_MOIS_PAR_AN;
return {
heureRdD: 0, // Index dans heuresList / heuresDef[x].heure
minutesRelative: 0,
indexJour: index,
annee: Math.floor(index / (RDD_JOUR_PAR_MOIS * RDD_MOIS_PAR_AN)),
- moisRdD: RdDCalendrier.getDefSigne(moisRdD),
- moisLabel: RdDCalendrier.getDefSigne(moisRdD).label,
+ moisRdD: RdDCalendrier.getDefSigne(mois),
+ moisLabel: RdDCalendrier.getDefSigne(mois).label,
jour: (index % RDD_JOUR_PAR_MOIS) // Le calendrier stocke le jour en 0-27, mais en 1-28 à l'affichage
}
}
@@ -138,7 +138,7 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */
getDateFromIndex(index) {
const dateRdD = this.getCalendrier(index);
- return (dateRdD.jour + 1) + ' ' + RdDCalendrier.getDefSigne(dateRdD.moisRdD).label;
+ return (dateRdD.jour + 1) + ' ' + dateRdD.moisLabel;
}
/* -------------------------------------------- */
@@ -458,7 +458,7 @@ export class RdDCalendrier extends Application {
function check() {
let elmnt = document.getElementById("calendar-time-container");
if (elmnt) {
- elmnt.style.bottom = null;
+ elmnt.style.bottom = undefined;
let xPos = (pos.left) > window.innerWidth ? window.innerWidth - 200 : pos.left;
let yPos = (pos.top) > window.innerHeight - 20 ? window.innerHeight - 100 : pos.top;
elmnt.style.top = (yPos) + "px";
@@ -615,16 +615,16 @@ export class RdDCalendrier extends Application {
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
- elmnt.style.bottom = null
+ elmnt.style.bottom = undefined
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
- elmnt.onmousedown = null;
- document.onmouseup = null;
- document.onmousemove = null;
+ elmnt.onmousedown = undefined;
+ document.onmouseup = undefined;
+ document.onmousemove = undefined;
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth - 200 : (elmnt.offsetLeft - pos1);
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight - 20 ? window.innerHeight - 100 : (elmnt.offsetTop - pos2)
xPos = xPos < 0 ? 0 : xPos;
diff --git a/module/rdd-combat.js b/module/rdd-combat.js
index af430b59..518b5d4f 100644
--- a/module/rdd-combat.js
+++ b/module/rdd-combat.js
@@ -9,8 +9,8 @@ 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";
-import { STATUSES } from "./status-effects.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
+import { STATUSES } from "./settings/status-effects.js";
/* -------------------------------------------- */
const premierRoundInit = [
@@ -121,7 +121,7 @@ export class RdDCombatManager extends Combat {
{
speaker: {
scene: canvas.scene._id,
- actor: combatant.actor ? combatant.actor._id : null,
+ actor: combatant.actor?._id,
token: combatant.token._id,
alias: combatant.token.name,
sound: CONFIG.sounds.dice,
@@ -498,7 +498,7 @@ export class RdDCombat {
let defender = canvas.tokens.get(msg.defenderTokenId).actor;
if (Misc.isOwnerPlayerOrUniqueConnectedGM()) {
let attackerRoll = msg.attackerRoll;
- let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : null;
+ let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined;
defender.encaisserDommages(attackerRoll, attacker);
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
diff --git a/module/rdd-compendium-organiser.js b/module/rdd-compendium-organiser.js
index 23cac6c7..e8b11b4e 100644
--- a/module/rdd-compendium-organiser.js
+++ b/module/rdd-compendium-organiser.js
@@ -29,13 +29,14 @@ export class RddCompendiumOrganiser {
static getEntityTypeLabel(entity) {
const documentName = entity?.documentName
- const type = entity?.type
+ const type = entity?.type
if (documentName === 'Actor' || documentName === 'Item') {
const label = CONFIG[documentName]?.typeLabels?.[type] ?? type;
- return game.i18n.has(label) ? game.i18n.localize(label) : t;
+ if (game.i18n.has(label)) {
+ return game.i18n.localize(label);
+ }
}
return type;
}
-
}
\ No newline at end of file
diff --git a/module/rdd-confirm.js b/module/rdd-confirm.js
index e406b877..6fe5579d 100644
--- a/module/rdd-confirm.js
+++ b/module/rdd-confirm.js
@@ -1,5 +1,5 @@
import { Grammar } from "./grammar.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
export class RdDConfirm {
/* -------------------------------------------- */
diff --git a/module/rdd-dice.js b/module/rdd-dice.js
index cba20726..dbc62e2b 100644
--- a/module/rdd-dice.js
+++ b/module/rdd-dice.js
@@ -241,7 +241,7 @@ export class RdDDice {
}
static _getWhisperBlind(options) {
- let whisper = null;
+ let whisper = undefined;
let blind = false;
let rollMode = options.rollMode ?? game.settings.get("core", "rollMode");
switch (rollMode) {
diff --git a/module/rdd-main.js b/module/rdd-main.js
index 12331097..86a15f4d 100644
--- a/module/rdd-main.js
+++ b/module/rdd-main.js
@@ -23,9 +23,9 @@ import { RdDTokenHud } from "./rdd-token-hud.js";
import { RdDCommands } from "./rdd-commands.js";
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
import { ChatUtility } from "./chat-utility.js";
-import { StatusEffects } from "./status-effects.js";
+import { StatusEffects } from "./settings/status-effects.js";
import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { TMRRencontres } from "./tmr-rencontres.js";
import { RdDHotbar } from "./rdd-hotbar-drop.js"
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
@@ -37,6 +37,8 @@ import { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.js";
import { Misc } from "./misc.js";
import { Migrations } from './migrations.js';
import { DialogChronologie } from "./dialog-chronologie.js";
+import { SystemCompendiums } from "./settings/system-compendiums.js";
+import { RdDRencontreItemSheet } from "./item-rencontre-sheet.js";
/* -------------------------------------------- */
/* Foundry VTT Initialization */
@@ -143,8 +145,6 @@ Hooks.once("init", async function () {
default: "aucun"
});
- DialogChronologie.onInit();
-
/* -------------------------------------------- */
// Set an initiative formula for the system
CONFIG.Combat.initiative = {
@@ -189,14 +189,27 @@ Hooks.once("init", async function () {
types: ["signedraconique"],
makeDefault: true
});
+ Items.registerSheet(SYSTEM_RDD, RdDRencontreItemSheet, {
+ label: "Rencontre",
+ types: ["rencontre"],
+ makeDefault: true
+ });
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
- types: ["arme", "armure", "objet", "arme", "armure", "conteneur", "competence", "sort", "herbe", "ingredient", "livre", "potion", "munition", "rencontresTMR", "queue", "ombre", "souffle",
- "tete", "competencecreature", "tarot", "monnaie", "nombreastral", "tache", "meditation", "casetmr", "recettealchimique", "gemme",
- "musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre", "nourritureboisson", "possession", "sortreserve"], makeDefault: true
+ types: [
+ "competence", "competencecreature",
+ "recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
+ "objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition",
+ "monnaie", "nourritureboisson", "gemme",
+ "meditation", "rencontresTMR", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
+ "nombreastral", "tache", "maladie", "poison", "possession",
+ "tarot"
+ ], makeDefault: true
});
CONFIG.Combat.documentClass = RdDCombatManager;
// préparation des différents modules
+ SystemCompendiums.init();
+ DialogChronologie.init();
ReglesOptionelles.init();
RdDUtility.init();
RdDDice.init();
@@ -208,7 +221,6 @@ Hooks.once("init", async function () {
RddCompendiumOrganiser.init();
EffetsDraconiques.init()
TMRUtility.init();
- TMRRencontres.init();
RdDHotbar.initDropbar();
RdDPossession.init();
});
diff --git a/module/rdd-resolution-table.js b/module/rdd-resolution-table.js
index 37eac10a..c6d67bf3 100644
--- a/module/rdd-resolution-table.js
+++ b/module/rdd-resolution-table.js
@@ -1,7 +1,7 @@
import { ChatUtility } from "./chat-utility.js";
import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
/**
* difficultés au delà de -10
@@ -54,7 +54,7 @@ export class RdDResolutionTable {
/* -------------------------------------------- */
static explain(rolled) {
let message = "
Jet : " + rolled.roll + " sur " + rolled.score + "% ";
- if (rolled.caracValue != null && rolled.finalLevel != null) {
+ if (rolled.caracValue != undefined && rolled.finalLevel != undefined) {
message += (rolled.diviseurSignificative > 1 ? `(1/${rolled.diviseurSignificative} de ` : "(")
+ rolled.caracValue + " à " + Misc.toSignedString(rolled.finalLevel) + ") ";
}
@@ -116,7 +116,7 @@ export class RdDResolutionTable {
static _updateChancesFactor(chances, diviseur) {
if (chances.level > -11 && diviseur && diviseur > 1) {
let newScore = Math.floor(chances.score / diviseur);
- mergeObject(chances, this._computeCell(null, newScore), { overwrite: true });
+ mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true });
}
}
@@ -124,7 +124,7 @@ export class RdDResolutionTable {
static _updateChancesWithBonus(chances, bonus, finalLevel) {
if (bonus && finalLevel>-11) {
let newScore = Number(chances.score) + bonus;
- mergeObject(chances, this._computeCell(null, newScore), { overwrite: true });
+ mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true });
}
}
diff --git a/module/rdd-roll.js b/module/rdd-roll.js
index fece5d69..efbe8c50 100644
--- a/module/rdd-roll.js
+++ b/module/rdd-roll.js
@@ -6,7 +6,7 @@ import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js";
import { RdDCarac } from "./rdd-carac.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
/**
* Extend the base Dialog entity to select roll parameters
diff --git a/module/rdd-rolltables.js b/module/rdd-rolltables.js
index 9ba058c5..8db91cf5 100644
--- a/module/rdd-rolltables.js
+++ b/module/rdd-rolltables.js
@@ -1,3 +1,5 @@
+import { SystemCompendiums } from "./settings/system-compendiums.js";
+
export class RdDRollTables {
/* -------------------------------------------- */
@@ -14,7 +16,7 @@ export class RdDRollTables {
}
static async getSystemTable(tableName) {
- const pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses");
+ const pack = SystemCompendiums.getPack("tables-diverses");
const index = await pack.getIndex();
const entry = index.find(e => e.name === tableName);
return await pack.getDocument(entry._id);
@@ -24,8 +26,7 @@ export class RdDRollTables {
static async drawItemFromRollTable(tableName, toChat = false) {
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
const pack = game.packs.get(drawResult.documentCollection)
- let doc = await pack.getDocument(drawResult.documentId)
- return doc
+ return await pack.getDocument(drawResult.documentId)
}
/* -------------------------------------------- */
diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js
index 5a65cc89..e5fa7516 100644
--- a/module/rdd-tmr-dialog.js
+++ b/module/rdd-tmr-dialog.js
@@ -1,3 +1,4 @@
+import { SHOW_DICE } from "./constants.js";
import { RollDataAjustements } from "./rolldata-ajustements.js";
import { RdDUtility } from "./rdd-utility.js";
import { TMRUtility } from "./tmr-utility.js";
@@ -11,11 +12,12 @@ import { Poetique } from "./poetique.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { PixiTMR } from "./tmr/pixi-tmr.js";
import { Draconique } from "./tmr/draconique.js";
-import { Misc } from "./misc.js";
import { HtmlUtility } from "./html-utility.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { RdDDice } from "./rdd-dice.js";
-import { STATUSES } from "./status-effects.js";
+import { STATUSES } from "./settings/status-effects.js";
+import { RdDRencontre } from "./item-rencontre.js";
+
/* -------------------------------------------- */
export class RdDTMRDialog extends Dialog {
@@ -89,7 +91,7 @@ export class RdDTMRDialog extends Dialog {
TMRUtility.getTMR(coord).type == 'fleuve'
? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve'
: it => it.system.coord == coord
- );
+ );
}
/* -------------------------------------------- */
@@ -146,7 +148,7 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
_tokenRencontre(rencontre) {
- return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
+ return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.system.coord);
}
_tokenCaseSpeciale(casetmr) {
const caseData = casetmr;
@@ -248,7 +250,7 @@ export class RdDTMRDialog extends Dialog {
let tmrpos = document.getElementById("tmr-pos");
if (this.isDemiReveCache()) {
- tmrpos.innerHTML = `?? ( ${ TMRUtility.getTMRType(coord)})`;
+ tmrpos.innerHTML = `?? ( ${TMRUtility.getTMRType(coord)})`;
} else {
tmrpos.innerHTML = `${coord} ( ${TMRUtility.getTMRLabel(coord)})`;
}
@@ -280,25 +282,44 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
+ async onActionRencontre(action, tmr) {
+ switch (action) {
+ case 'derober':
+ await this.derober();
+ return;
+ case 'refouler':
+ await this.refouler();
+ break;
+ case 'maitriser':
+ await this.maitriserRencontre();
+ break;
+ case 'ignorer':
+ await this.ignorerRencontre();
+ break;
+ }
+ await this.postRencontre(tmr);
+ }
+
async derober() {
- await this.actor.addTMRRencontre(this.currentRencontre);
console.log("-> derober", this.currentRencontre);
+ await this.actor.addTMRRencontre(this.currentRencontre);
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR.");
this.close();
}
/* -------------------------------------------- */
async refouler() {
- await this.actor.ajouterRefoulement(this.currentRencontre.refoulement ?? 1, `une rencontre ${this.currentRencontre.name}`);
+ console.log("-> refouler", this.currentRencontre);
+ await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
this.updateTokens();
- console.log("-> refouler", this.currentRencontre)
this.updateValuesDisplay();
this.nettoyerRencontre();
}
/* -------------------------------------------- */
async ignorerRencontre() {
+ console.log("-> ignorer", this.currentRencontre);
this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
this.updateTokens();
@@ -307,7 +328,14 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
- colorierZoneRencontre(listCoordTMR) {
+ // garder la trace de l'état en cours
+ setRencontreState(state, listCoordTMR) {
+ this.rencontreState = state;
+ this.$marquerCasesTMR(listCoordTMR ?? []);
+ }
+
+ /* -------------------------------------------- */
+ $marquerCasesTMR(listCoordTMR) {
this.currentRencontre.graphics = []; // Keep track of rectangles to delete it
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location
for (let coordTMR of listCoordTMR) {
@@ -323,23 +351,6 @@ export class RdDTMRDialog extends Dialog {
}
}
- /* -------------------------------------------- */
- // garder la trace de l'état en cours
- setStateRencontre(state) {
- this.rencontreState = state;
- }
-
- /* -------------------------------------------- */
- async choisirCasePortee(coord, portee) {
- // Récupère la liste des cases à portées
- this.colorierZoneRencontre(TMRUtility.getTMRPortee(coord, portee));
- }
-
- /* -------------------------------------------- */
- async choisirCaseType(type) {
- this.colorierZoneRencontre(TMRUtility.filterTMR(it => it.type == type).map(it => it.coord));
- }
-
/* -------------------------------------------- */
checkQuitterTMR() {
@@ -364,15 +375,15 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async quitterLesTMRInconscient() {
- if (this.currentRencontre?.isPersistant) {
- await this.refouler();
- }
+ await this.refouler();
this.close();
}
/* -------------------------------------------- */
async maitriserRencontre() {
- this.actor.deleteTMRRencontreAtPosition();
+ console.log("-> maitriser", this.currentRencontre);
+
+ await this.actor.deleteTMRRencontreAtPosition();
this.updateTokens();
let rencontreData = {
@@ -383,7 +394,7 @@ export class RdDTMRDialog extends Dialog {
rencontre: this.currentRencontre,
nbRounds: 1,
canClose: false,
- selectedCarac: {label: "reve-actuel"},
+ selectedCarac: { label: "reve-actuel" },
tmr: TMRUtility.getTMR(this._getActorCoord())
}
@@ -392,8 +403,6 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async _tentativeMaitrise(rencData) {
- console.log("-> matriser", rencData);
-
rencData.reve = this.actor.getReveActuel();
rencData.etat = this.actor.getEtatGeneral();
@@ -403,41 +412,67 @@ export class RdDTMRDialog extends Dialog {
? this._rollPresentCite(rencData)
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
- let postProcess = await TMRRencontres.gererRencontre(this, rencData);
+ const result = rencData.rolled.isSuccess
+ ? rencData.rencontre.system.succes
+ : rencData.rencontre.system.echec;
+
+ await RdDRencontre.appliquer(result.effets, this, rencData);
+
+ rencData.poesie = { extrait: result.poesie, reference: result.reference };
+ rencData.message = this.formatMessageRencontre(rencData, result.message);
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData)
});
- if (postProcess) {
- /** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */
- await postProcess(this, rencData);
- }
- else {
- this.currentRencontre = undefined;
- }
-
this.updateValuesDisplay();
if (this.checkQuitterTMR()) {
return;
}
- else if (rencData.rolled.isEchec && rencData.rencontre.isPersistant) {
- setTimeout(() => {
- rencData.nbRounds++;
- if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
- this.cumulFatigue += this.fatigueParCase;
- }
- this._tentativeMaitrise(rencData);
- this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
- }, 2000);
+ if (this.rencontreState == 'persistant') {
+ this._nouvelleTentativeMaitrise(rencData);
+ }
+ else if (!this.isRencontreDeplacement()) {
+ this.nettoyerRencontre();
+ }
+ }
+
+ _nouvelleTentativeMaitrise(rencData) {
+ setTimeout(() => {
+ // TODO: remplacer par une boucle while(this.currentRencontre) ?
+ rencData.nbRounds++;
+ if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
+ this.cumulFatigue += this.fatigueParCase;
+ }
+ this._tentativeMaitrise(rencData);
+ this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
+ }, 2000);
+ this.rencontreState == 'normal';
+ }
+
+ formatMessageRencontre(rencData, template) {
+ let messageDuree = ''
+ if (rencData.nbRounds > 1) {
+ if (rencData.rolled.isSuccess) {
+ messageDuree = ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
+ }
+ else {
+ messageDuree = ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
+ }
+ }
+ try {
+ const compiled = Handlebars.compile(template);
+ return compiled(rencData) + messageDuree ;
+ } catch (error) {
+ return template + messageDuree ;
}
}
/* -------------------------------------------- */
- _rollPresentCite(rencontreData) {
- let rolled = RdDResolutionTable.computeChances(rencontreData.reve, 0);
- mergeObject(rolled, { caracValue: rencontreData.reve, finalLevel: 0, roll: rolled.score });
+ _rollPresentCite(rencData) {
+ let rolled = RdDResolutionTable.computeChances(rencData.reve, 0);
+ mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score });
RdDResolutionTable.succesRequis(rolled);
return rolled;
}
@@ -481,15 +516,16 @@ export class RdDTMRDialog extends Dialog {
if (this._presentCite(tmr)) {
return;
}
- let rencontre = await this._jetDeRencontre(tmr);
-
- if (rencontre) { // Manages it
- if (rencontre.rencontre) rencontre = rencontre.rencontre; // Manage stored rencontres
- console.log("manageRencontre", rencontre);
- this.currentRencontre = duplicate(rencontre);
-
- let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, () => this.postRencontre(tmr));
- dialog.render(true);
+ this.currentRencontre = await this._jetDeRencontre(tmr);
+ if (this.currentRencontre) {
+ if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)){
+ // rencontre en attente suite à dérobade
+ await this.maitriserRencontre();
+ }
+ else {
+ let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, tmr);
+ dialog.render(true);
+ }
}
else {
this.postRencontre(tmr);
@@ -502,15 +538,18 @@ export class RdDTMRDialog extends Dialog {
if (presentCite) {
this.minimize();
const caseData = presentCite;
- EffetsDraconiques.presentCites.choisirUnPresent(caseData, (type => this._utiliserPresentCite(presentCite, type, tmr)));
+ EffetsDraconiques.presentCites.choisirUnPresent(caseData, (present => this._utiliserPresentCite(presentCite, present, tmr)));
}
return presentCite;
}
/* -------------------------------------------- */
- async _utiliserPresentCite(presentCite, typeRencontre, tmr) {
- this.currentRencontre = TMRRencontres.getRencontre(typeRencontre);
- await TMRRencontres.evaluerForceRencontre(this.currentRencontre);
+ async _utiliserPresentCite(presentCite, present, tmr) {
+ this.currentRencontre = present.clone({
+ 'system.force': await RdDDice.rollTotal(present.system.formule),
+ 'system.coord': tmr.coord
+ }, {save: false});
+
await EffetsDraconiques.presentCites.ouvrirLePresent(this.actor, presentCite);
this.removeToken(tmr, presentCite);
@@ -532,33 +571,26 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async _jetDeRencontre(tmr) {
- let rencontre = this.rencontresExistantes.find(prev => prev.coord == tmr.coord);
+ let rencontre = this.lookupRencontreExistente(tmr);
if (rencontre) {
- return rencontre;
+ return TMRRencontres.calculRencontre(rencontre, tmr);
}
let locTMR = (this.isDemiReveCache()
- ? Misc.upperFirst(tmr.type) + " ??"
+ ? TMRUtility.getTMRType(tmr.coord) + " ??"
: tmr.label + " (" + tmr.coord + ")");
- let myRoll = await RdDDice.rollTotal("1dt");
- if (TMRUtility.isForceRencontre() || myRoll == 7) {
+ let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
+ if (myRoll == 7) {
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
- return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
+ return await TMRRencontres.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
} else {
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
}
}
- /* -------------------------------------------- */
- async rencontreTMRRoll(tmr, isMauvaise = false) {
- let rencontre = TMRUtility.utiliseForceRencontre() ??
- (isMauvaise
- ? await TMRRencontres.getMauvaiseRencontre()
- : await TMRRencontres.getRencontreAleatoire(tmr.type));
- rencontre.coord = tmr.coord;
- rencontre.date = game.system.rdd.calendrier.getDateFromIndex();
- rencontre.heure = game.system.rdd.calendrier.getCurrentHeure();
- return rencontre;
+ lookupRencontreExistente(tmr) {
+ return this.rencontresExistantes.find(it => it.system.coord == tmr.coord)
+ ?? this.rencontresExistantes.find(it => it.system.coord == "");
}
/* -------------------------------------------- */
@@ -586,7 +618,7 @@ export class RdDTMRDialog extends Dialog {
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
}
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined,
- rollData.competence.system.defaut_carac = 'reve-actuel';
+ rollData.competence.system.defaut_carac = 'reve-actuel';
await this._rollMaitriseCaseHumide(rollData);
}
}
@@ -877,16 +909,14 @@ export class RdDTMRDialog extends Dialog {
if (this.isDemiReveCache()) {
if (this.isTerreAttache(targetCoord)
- || this.isConnaissanceFleuve(currentCoord, targetCoord)
- || deplacementType == 'changeur')
- {
+ || this.isConnaissanceFleuve(currentCoord, targetCoord)
+ || deplacementType == 'changeur') {
// déplacement possible
await this.actor.setTMRVisible(true);
this.demiReve = this._tokenDemiReve();
this._trackToken(this.demiReve);
}
- else
- {
+ else {
ui.notifications.error(`Vous ne connaissez plus votre position dans les TMR.
Vous devez utiliser les boutons de direction pour vous déplacer.
Une fois que vous aurez retrouvé votre demi-rêve, demandez au gardien de vérifier et rendre les TMR visibles.
@@ -895,20 +925,18 @@ export class RdDTMRDialog extends Dialog {
}
}
- switch (deplacementType){
+ switch (deplacementType) {
case 'normal':
+ case 'changeur':
+ case 'passeur':
await this._deplacerDemiReve(targetCoord, deplacementType);
break;
case 'messager':
await this._messagerDemiReve(targetCoord);
break;
- case 'changeur':
- case 'passeur':
- await this._deplacerDemiReve(targetCoord, deplacementType);
- break;
default:
- ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
- console.log("STATUS :", this.rencontreState, this.currentRencontre);
+ ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
+ console.log("STATUS :", this.rencontreState, this.currentRencontre);
}
this.checkQuitterTMR();
@@ -916,19 +944,23 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
_calculDeplacement(targetCoord, currentCoord, fromOddq, toOddq) {
-
- const isInArea = this.rencontreState == 'aucune'
- ? (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1)
- : this.currentRencontre?.locList?.find(coord => coord == targetCoord) ?? false
- if (isInArea) {
- switch (this.rencontreState) {
- case 'aucune': return 'normal';
- case 'passeur': case 'changeur': case 'messager': return this.rencontreState;
+ if (this.isRencontreDeplacement()) {
+ if (this.currentRencontre?.locList?.find(coord => coord == targetCoord)) {
+ return this.rencontreState;
+ }
+ }
+ else {
+ if (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1) {
+ return 'normal'
}
}
return 'erreur';
}
+ isRencontreDeplacement() {
+ return ['passeur', 'changeur', 'messager'].includes(this.rencontreState);
+ }
+
/* -------------------------------------------- */
async _messagerDemiReve(targetCoord) {
/*
diff --git a/module/rdd-tmr-rencontre-dialog.js b/module/rdd-tmr-rencontre-dialog.js
index ac21f161..72c65558 100644
--- a/module/rdd-tmr-rencontre-dialog.js
+++ b/module/rdd-tmr-rencontre-dialog.js
@@ -2,20 +2,22 @@
export class RdDTMRRencontreDialog extends Dialog {
/* -------------------------------------------- */
- constructor(tmrApp, rencontre, postRencontre) {
+ constructor(tmrApp, rencontre, tmr) {
const dialogConf = {
title: "Rencontre en TMR!",
- content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.force + "
",
+ content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.system.force + "
",
buttons: {
- derober: { icon: '', label: "Se dérober", callback: () => { this.onButtonFuir(() => tmrApp.derober()); } },
- refouler: { icon: '', label: "Refouler", callback: () => this.onButtonAction(() => tmrApp.refouler()) },
- maitiser: { icon: '', label: "Maîtriser", callback: () => this.onButtonAction(() => tmrApp.maitriserRencontre()) }
+ derober: { icon: '', label: "Se dérober", callback: () => this.onButtonAction('derober') },
+ maitiser: { icon: '', label: "Maîtriser", callback: () => this.onButtonAction('maitriser') }
},
default: "derober"
- };
- if (rencontre.ignorer) {
- dialogConf.buttons.ignorer = { icon: '', label: "Ignorer", callback: () => this.onButtonAction(() => tmrApp.ignorerRencontre()) }
- };
+ }
+ if ((rencontre.system.refoulement ?? 0) == 0) {
+ dialogConf.buttons.ignorer = { icon: '', label: "Ignorer", callback: () => this.onButtonAction('ignorer') }
+ }
+ else {
+ dialogConf.buttons.refouler = { icon: '', label: "Refouler", callback: () => this.onButtonAction('refouler') }
+ }
const dialogOptions = {
classes: ["tmrrencdialog"],
@@ -25,23 +27,16 @@ export class RdDTMRRencontreDialog extends Dialog {
super(dialogConf, dialogOptions);
this.toClose = false;
- this.rencontreData = duplicate(rencontre);
- this.postRencontre = postRencontre;
+ this.tmr = tmr;
this.tmrApp = tmrApp;
this.tmrApp.minimize();
}
async onButtonAction(action) {
this.toClose = true;
- await action();
- this.postRencontre();
+ this.tmrApp.onActionRencontre(action, this.tmr)
}
- async onButtonFuir(action) {
- this.toClose = true;
- await action();
- }
-
/* -------------------------------------------- */
close() {
if (this.toClose) {
diff --git a/module/rdd-utility.js b/module/rdd-utility.js
index c427fad6..afb589a8 100644
--- a/module/rdd-utility.js
+++ b/module/rdd-utility.js
@@ -6,14 +6,13 @@ import { Misc } from "./misc.js";
import { Grammar } from "./grammar.js";
import { TMRUtility } from "./tmr-utility.js";
import { DialogItemAchat } from "./dialog-item-achat.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { RdDDice } from "./rdd-dice.js";
import { RdDItem } from "./item.js";
import { Monnaie } from "./item-monnaie.js";
import { RdDPossession } from "./rdd-possession.js";
import { RdDNameGen } from "./rdd-namegen.js";
import { RdDConfirm } from "./rdd-confirm.js";
-import { RdDActor } from "./actor.js";
import { RdDCalendrier } from "./rdd-calendrier.js";
/* -------------------------------------------- */
@@ -182,6 +181,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html',
+ 'systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-rencontresTMR-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-souffle-sheet.html',
@@ -280,6 +280,7 @@ export class RdDUtility {
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord));
+ Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
Handlebars.registerHelper('signeHeure', (key, heure) => RdDCalendrier.getSigneAs(key, heure));
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
@@ -415,6 +416,7 @@ export class RdDUtility {
RdDUtility.filterEquipementParType(formData, itemTypes);
formData.sorts = this.arrayOrEmpty(itemTypes['sort']);
+ formData.rencontres = this.arrayOrEmpty(itemTypes['rencontre']);
formData.casestmr = this.arrayOrEmpty(itemTypes['casetmr']);
formData.signesdraconiques = this.arrayOrEmpty(itemTypes['signedraconique']);
formData.queues = this.arrayOrEmpty(itemTypes['queue']);
diff --git a/module/rolldata-ajustements.js b/module/rolldata-ajustements.js
index 4631e7cc..2807065a 100644
--- a/module/rolldata-ajustements.js
+++ b/module/rolldata-ajustements.js
@@ -6,7 +6,7 @@ import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js";
import { RdDCarac } from "./rdd-carac.js";
import { RdDUtility } from "./rdd-utility.js";
-import { ReglesOptionelles } from "./regles-optionelles.js";
+import { ReglesOptionelles } from "./settings/regles-optionelles.js";
/**
* tous les ajustements pouvant s'appliquer.
@@ -120,7 +120,7 @@ export const referenceAjustements = {
isVisible: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
getLabel: (rollData, actor) => rollData.rencontre?.name,
- getValue: (rollData, actor) => - (rollData.rencontre?.force ?? 0)
+ getValue: (rollData, actor) => - (rollData.rencontre?.system.force ?? 0)
},
ethylismeAlcool: {
isVisible: (rollData, actor) => rollData.nbDoses != undefined,
diff --git a/module/regles-optionelles.js b/module/settings/regles-optionelles.js
similarity index 96%
rename from module/regles-optionelles.js
rename to module/settings/regles-optionelles.js
index eceda14c..d9094180 100644
--- a/module/regles-optionelles.js
+++ b/module/settings/regles-optionelles.js
@@ -1,5 +1,5 @@
-import { SYSTEM_RDD } from "./constants.js";
-import { Misc } from "./misc.js";
+import { SYSTEM_RDD } from "../constants.js";
+import { Misc } from "../misc.js";
const listeReglesOptionelles = [
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
@@ -43,7 +43,7 @@ export class ReglesOptionelles extends FormApplication {
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
name: "Choisir les règles optionelles",
- label: "Choix des règles optionelles",
+ label: "Règles optionelles",
hint: "Ouvre la fenêtre de sélection des règles optionelles",
icon: "fas fa-bars",
type: ReglesOptionelles
@@ -61,8 +61,8 @@ export class ReglesOptionelles extends FormApplication {
static get defaultOptions() {
const options = super.defaultOptions;
mergeObject(options, {
- id: "optional-settings",
- template: "systems/foundryvtt-reve-de-dragon/templates/regles-optionelles.html",
+ id: "regles-optionelles",
+ template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionelles.html",
height: 600,
width: 450,
minimizable: false,
diff --git a/module/status-effects.js b/module/settings/status-effects.js
similarity index 89%
rename from module/status-effects.js
rename to module/settings/status-effects.js
index 488c0e54..6c2146f6 100644
--- a/module/status-effects.js
+++ b/module/settings/status-effects.js
@@ -1,4 +1,4 @@
-import { SYSTEM_RDD } from "./constants.js";
+import { SYSTEM_RDD } from "../constants.js";
export const STATUSES = {
StatusStunned : 'stun',
@@ -32,7 +32,7 @@ const demiReveStatusEffect = rddStatusEffects.find(it => it.id == STATUSES.Statu
const statusDemiSurprise = [STATUSES.StatusStunned, STATUSES.StatusProne, STATUSES.StatusRestrained];
const statusSurpriseTotale = [STATUSES.StatusUnconscious, STATUSES.StatusBlind, STATUSES.StatusComma];
-export class StatusEffects {
+export class StatusEffects extends FormApplication {
static onReady() {
const rddStatusIds = rddStatusEffects.map(it => it.id);
rddStatusEffects.forEach(it => it.flags = { core: { statusId: it.id } });
@@ -50,7 +50,7 @@ export class StatusEffects {
label: "Choix des effets",
hint: "Ouvre la fenêtre de sélection des effets/status appliqués aux acteurs",
icon: "fas fa-bars",
- type: StatusEffectsSettings,
+ type: StatusEffects,
restricted: true
});
@@ -69,13 +69,12 @@ export class StatusEffects {
}
static _getUseStatusEffects() {
- const setting = game.settings.get(SYSTEM_RDD, "use-status-effects");
- return setting ? setting.split(',') : [];
+ return game.settings.get(SYSTEM_RDD, "use-status-effects")?.split(',') ?? [];
}
static _setUseStatusEffects(statusIds) {
if (game.user.isGM) {
- game.settings.set(SYSTEM_RDD, "use-status-effects", StatusEffects._toSetting(statusIds));
+ game.settings.set(SYSTEM_RDD, "use-status-effects", statusIds.join());
}
for (let effect of CONFIG.RDD.allEffects) {
@@ -84,10 +83,6 @@ export class StatusEffects {
CONFIG.statusEffects = CONFIG.RDD.allEffects.filter(it => it.active);
}
- static _toSetting(statusIds) {
- return statusIds.join();
- }
-
static status(statusId) {
return rddStatusEffects.find(it => it.flags?.core?.statusId == statusId);
}
@@ -95,9 +90,7 @@ export class StatusEffects {
static demiReve() {
return demiReveStatusEffect;
}
-}
-class StatusEffectsSettings extends FormApplication {
constructor(...args) {
super(...args);
}
@@ -105,8 +98,8 @@ class StatusEffectsSettings extends FormApplication {
static get defaultOptions() {
const options = super.defaultOptions;
mergeObject(options, {
- id: "status-effects-settings",
- template: "systems/foundryvtt-reve-de-dragon/templates/status-effects-settings.html",
+ id: "status-effects",
+ template: "systems/foundryvtt-reve-de-dragon/templates/settings/status-effects.html",
height: "800",
width: 350,
minimizable: false,
diff --git a/module/settings/system-compendiums.js b/module/settings/system-compendiums.js
new file mode 100644
index 00000000..21bdbe9d
--- /dev/null
+++ b/module/settings/system-compendiums.js
@@ -0,0 +1,124 @@
+import { SYSTEM_RDD } from "../constants.js";
+
+const COMPENDIUM_SETTING_PREFIX = 'compendium-';
+
+const CONFIGURABLE_COMPENDIUMS = {
+ 'tables-diverses': { label: "Tables aléatoires", type: "RollTable" },
+ 'competences': { label: "Compétences", type: "Item" },
+ 'queues-de-dragon': { label: "Queues de dragon", type: "Item" },
+ 'ombres-de-thanatos': { label: "Ombres de Thanatos", type: "Item" },
+ 'souffles-de-dragon': { label: "Souffles de Dragon", type: "Item" },
+ 'tarot-draconique': { label: "Tarots draconiques", type: "Item" },
+ 'rencontres': { label: "Rencontres dans les TMR", type: "Item" },
+ 'tetes-de-dragon-pour-haut-revants': { label: "Têtes de dragons (haut-rêvant)", type: "Item" },
+ 'tetes-de-dragon-pour-tous-personnages': { label: "Têtes de dragons (tous)", type: "Item" },
+}
+
+export class SystemCompendiums extends FormApplication {
+ static init() {
+ Object.keys(CONFIGURABLE_COMPENDIUMS).forEach(compendium => {
+ const definition = CONFIGURABLE_COMPENDIUMS[compendium];
+ mergeObject(definition, {
+ compendium: compendium,
+ default: SystemCompendiums._getDefaultCompendium(compendium),
+ setting: SystemCompendiums._getSettingCompendium(compendium)
+ });
+
+ game.settings.register(SYSTEM_RDD, definition.setting, {
+ name: definition.label,
+ default: definition.default,
+ scope: "world",
+ config: false,
+ type: String
+ });
+ });
+
+ game.settings.registerMenu(SYSTEM_RDD, "compendium-settings", {
+ name: "Choisir les compendiums système",
+ label: "Compendiums système",
+ hint: "Ouvre la fenêtre de sélection des compendiums système",
+ icon: "fas fa-bars",
+ type: SystemCompendiums
+ })
+ }
+
+ static getPack(compendium) {
+ return game.packs.get(SystemCompendiums.getCompendium(compendium));
+ }
+
+ static async getContent(compendium, docType) {
+ const pack = SystemCompendiums.getPack(compendium);
+ if (pack.metadata.type == docType) {
+ return await pack.getDocuments();
+ }
+ return [];
+ }
+
+ static async getItems(compendium) {
+ return await SystemCompendiums.getContent(compendium, 'Item')
+ }
+
+ static async getDefaultItems(compendium) {
+ const pack = game.packs.get(SystemCompendiums._getDefaultCompendium(compendium));
+ if (pack.metadata.type == 'Item') {
+ return await pack.getDocuments();
+ }
+ return [];
+ }
+
+ static getCompendium(compendium) {
+ const setting = CONFIGURABLE_COMPENDIUMS[compendium]?.setting;
+ return setting ? game.settings.get(SYSTEM_RDD, setting) : SystemCompendiums._getDefaultCompendium(compendium);
+ }
+
+ static _getSettingCompendium(compendium) {
+ return COMPENDIUM_SETTING_PREFIX + compendium;
+ }
+
+ static _getDefaultCompendium(compendium) {
+ return `${SYSTEM_RDD}.${compendium}`;
+ }
+
+ constructor(...args) {
+ super(...args);
+ }
+
+ static get defaultOptions() {
+ const options = super.defaultOptions;
+ mergeObject(options, {
+ id: "system-compendiums",
+ template: "systems/foundryvtt-reve-de-dragon/templates/settings/system-compendiums.html",
+ height: 'fit-content',
+ width: 600,
+ minimizable: false,
+ closeOnSubmit: true,
+ title: "Compendiums système"
+ });
+ return options;
+ }
+
+ getData() {
+ const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS)
+ .map(it => mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) }));
+ const availableCompendiums = game.packs.map(pack => { return {
+ name: pack.collection,
+ path: pack.collection.replace('.', " / "),
+ type: pack.metadata.type
+ } });
+ return mergeObject(super.getData(), {
+ systemCompendiums: systemCompendiums,
+ availableCompendiums: availableCompendiums
+ });
+ }
+
+ activateListeners(html) {
+ html.find("select.system-compendium-setting").change((event) => {
+ const compendium = $(event.currentTarget).data('compendium')
+ const value = $(event.currentTarget).val();
+ const systemCompendium = CONFIGURABLE_COMPENDIUMS[compendium];
+
+ game.settings.set(SYSTEM_RDD, systemCompendium.setting, value);
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js
index 2f9d099e..14f94dc2 100644
--- a/module/tmr-rencontres.js
+++ b/module/tmr-rencontres.js
@@ -1,500 +1,142 @@
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
+import { SystemCompendiums } from "./settings/system-compendiums.js";
import { TMRUtility } from "./tmr-utility.js";
-import { TMRType } from "./tmr-utility.js";
-
-/* -------------------------------------------- */
-const typeRencontres = {
-
- messager: {
- msgSucces: async (rencData) => {
- if (rencData.actor.isTMRCache()){
- return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort, mais vous ne savez pas où vous êtes.`;
- }
- return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`;
- },
- msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`,
- postSucces: async (tmrDialog, rencData) => {
- tmrDialog.setStateRencontre(rencData.rencontre.type);
- tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
- },
- poesieSucces: {
- reference: "La chevelure, Charles Baudelaire",
- extrait: `J'irai là-bas où l'arbre et l'homme, pleins de sève,
-
Se pâment longuement sous l'ardeur des climats ;
-
Fortes tresses, soyez la houle qui m'enlève !`
- },
- poesieEchec: {
- reference: "Rêve de Dragon, Denis Gerfaud",
- extrait: `En réalité, tous les éléments du rêve des Dragons expriment
- le Draconic : chaque pierre, chaque fleur, chaque goutte d'eau,
- chaque nuage est porteur d'un message dans la langue des Dragons`}
- },
-
- passeur: {
- msgSucces: async (rencData) => {
- if (rencData.actor.isTMRCache()){
- return `Le ${rencData.rencontre.name} vous propose de vous transporter, mais vous ne savez pas où vous êtes.`;
- }
- return `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.tmr.label}.`;
- },
- msgEchec: async (rencData)=> `Le prix que demande le ${rencData.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`,
- postSucces: async (tmrDialog, rencData) => {
- tmrDialog.setStateRencontre(rencData.rencontre.type);
- tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
- },
- poesieSucces: {
- reference: "Femmes damnées (2), Charles Baudelaire",
- extrait: `Comme je descendais des Fleuves impassibles,
-
Je ne me sentis plus guidé par les haleurs :
-
Des Peaux-Rouges criards les avaient pris pour cibles,
-
Les ayant cloués nus aux poteaux de couleurs.`},
- poesieEchec: {
- reference: "Le bateau ivre, Arthur Rimbaud",
- extrait: `Loin des peuples vivants, errantes, condamnées,
-
A travers les déserts courez comme les loups ;
-
Faites votre destin, âmes désordonnées,
-
Et fuyez l'infini que vous portez en vous !`}
- },
-
- fleur: {
- msgSucces: async (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`,
- msgEchec: async (rencData)=> `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`,
- postSucces: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force),
- poesieSucces: {
- reference: "L'Ennemi, Charles Baudelaire",
- extrait: `Et qui sait si les fleurs nouvelles que je rêve
-
Trouveront dans ce sol lavé comme une grève
-
Le mystique aliment qui ferait leur vigueur ?`},
- poesieEchec: {
- reference: "Une charogne, Charles Baudelaire",
- extrait: `Et le ciel regardait la carcasse superbe
-
Comme une fleur s'épanouir.
-
La puanteur était si forte, que sur l'herbe
-
Vous crûtes vous évanouir.`},
- },
-
- mangeur: {
- msgSucces: async (rencData) => `Le ${rencData.rencontre.name} claque de sa machoire dans le vide avant de fuir.`,
- msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} croque votre Rêve ! Il emporte ${rencData.rencontre.force} de vos points de rêve actuels`,
- postEchec: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force),
- poesieSucces: {
- reference: "Conseil, Victor Hugo",
- extrait: `Rois ! la bure est souvent jalouse du velours.
-
Le peuple a froid l'hiver, le peuple a faim toujours.
-
Rendez-lui son sort plus facile.
-
Le peuple souvent porte un bien rude collier.
-
Ouvrez l'école aux fils, aux pères l'atelier,
-
À tous vos bras, auguste asile !`},
- poesieEchec: {
- reference: "El Desdichado, Gérard de Nerval",
- extrait: `Suis-je Amour ou Phébus ?... Lusignan ou Biron ?
-
Mon front est rouge encor du baiser de la Reine ;
-
J'ai rêvé dans la Grotte où nage la sirène...`}
- },
-
- changeur: {
- msgSucces: async (rencData) => `Le ${rencData.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[rencData.tmr.type].name} de votre choix en échange de sa liberté.`,
- msgEchec: async (rencData) => `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte sur une autre ${TMRType[rencData.tmr.type].name} sans attendre votre avis.`,
- postSucces: async (tmrDialog, rencData) => {
- tmrDialog.setStateRencontre(rencData.rencontre.type);
- tmrDialog.choisirCaseType(rencData.tmr.type);
- },
- postEchec: async (tmrDialog, rencData) => {
- const newTMR = await TMRUtility.getTMRAleatoire(it => it.type == rencData.tmr.type && it.coord != rencData.tmr.coord);
- await tmrDialog.actor.forcerPositionTMRInconnue(newTMR);
- tmrDialog.positionnerDemiReve(newTMR.coord);
- },
- poesieSucces: {
- reference: "Caligula - IIIème chant, Gérard de Nerval",
- extrait: `Allez, que le caprice emporte
-
Chaque âme selon son désir,
-
Et que, close après vous, la porte
-
Ne se rouvre plus qu'au plaisir.`},
- poesieEchec: {
- reference: "Rêve de Dragon, Denis Gerfaud",
- extrait: `Les sages ont encore coutume de dire :
-
« Mais comment les Dragons peuvent-ils
- être influencés par une créature qui, tout
- bien considéré, n'existe pas vraiment pour eux,
- qui n'est que le fantasme de leur activité nocturne ? »`}
- },
-
- briseur: {
- msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`,
- msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`,
- postEchec: async (tmrDialog, rencData) => tmrDialog.close(),
- poesieSucces: {
- reference: "Rêve de Dragon, Denis Gerfaud",
- extrait: `La légende affirme que ce sont les Gnomes qui furent
- les premiers haut-rêvants. En observant les pierres précieuses,
- les gemmes qui sont les larmes de joie des Dragons, ils parvinrent à
- en comprendre la langue. Et l'ayant comprise, ils purent s'en servir
- pour influencer le cours du rêve`},
- poesieEchec: {
- reference: "Quand le rêve se brise, Cypora Sebagh",
- extrait: `Quand le rêve se brise,
-
Dans la plainte du jour,
-
Ma mémoire devient grise
-
Et sombre, tour à tour,
-
Dans le puits du silence
-
Et de la solitude ;
-
Elle reprend son errance
-
Parmi la multitude.`}
- },
-
- reflet: {
- msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'estompe dans l'oubli.`,
- msgEchec: async (rencData)=> `Vous êtes submergé par un ${rencData.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`,
- poesieSucces: {
- reference: "Une charogne, Charles Baudelaire",
- extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve,
-
Une ébauche lente à venir
-
Sur la toile oubliée, et que l'artiste achève
-
Seulement par le souvenir.`},
- poesieEchec: {
- reference: "La chevelure, Charles Baudelaire",
- extrait: `Longtemps ! toujours ! ma main dans ta crinière lourde
-
Sèmera le rubis, la perle et le saphir,
-
Afin qu'à mon désir tu ne sois jamais sourde !
-
N'es-tu pas l'oasis où je rêve, et la gourde
-
Où je hume à longs traits le vin du souvenir`}
- },
-
- passeurfou: {
- msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`,
- msgEchec: async (rencData)=> TMRRencontres.msgEchecPasseurFou(rencData),
- postEchec: async (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData),
- poesieSucces: {
- reference: "Un Fou et un Sage, Jean de La Fontaine",
- extrait: `Certain Fou poursuivait à coups de pierre un Sage.
-
Le Sage se retourne et lui dit : Mon ami,
-
C'est fort bien fait à toi ; reçois cet écu-ci :
-
Tu fatigues assez pour gagner davantage.`},
- poesieEchec: {
- reference: "Guitare, Victor Hugo",
- extrait: `Je la voyais passer de ma demeure,
-
Et c'était tout.
-
Mais à présent je m'ennuie à toute heure,
-
Plein de dégoût,
-
Rêveur oisif, l'âme dans la campagne,
-
La dague au clou ... –
-
Le vent qui vient à travers la montagne
-
M'a rendu fou !`}
- },
-
- tbblanc: {
- msgSucces: async (rencData) => `Le ${rencData.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`,
- msgEchec: async (rencData)=> `Le souffle du ${rencData.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`,
- postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1),
- poesieSucces: {
- reference: "Rêve de Dragon, Denis Gerfaud",
- extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement
- des temps, le commencement des rêves. Durant cette période plus mythique
- que réellement historique, les Dragons aimaient à se rêver eux-mêmes.`},
- poesieEchec: {
- reference: "Les Djinns, Victor Hugo",
- extrait: `C'est l'essaim des Djinns qui passe,
-
Et tourbillonne en sifflant !
-
Les ifs, que leur vol fracasse,
-
Craquent comme un pin brûlant.`},
- },
-
- tbnoir: {
- msgSucces: async (rencData) => `Le ${rencData.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`,
- msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`,
- postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 2),
- poesieSucces: {
- reference: "Rêve de Dragon, Denis Gerfaud",
- extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les
- Gnomes s'enfoncèrent profondément sous les montagnes et la magie passa aux
- mains des Humains qui en usèrent et abusèrent, se croyant devenus les maîtres du monde`},
- poesieEchec: {
- reference: "Lily, Pierre Perret",
- extrait: `Elle aurait pas cru sans le voir
-
Que la couleur du désespoir
-
Là-bas aussi ce fût le noir.`},
- },
-
- tbrouge: {
- msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`,
- msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`,
- postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData),
- poesieSucces: {
- reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet",
- extrait: `Qu'est-ce de votre vie ? un tourbillon rouant
-
De fumière à flot gris, parmi l'air se jouant,
-
Qui passe plus soudain que foudre meurtrière.`},
- poesieEchec: {
- reference: "Les Djinns, poème Victor Hugo",
- extrait: `Cris de l'enfer! voix qui hurle et qui pleure !
-
L'horrible essaim, poussé par l'aquilon,
-
Sans doute, ô ciel ! s'abat sur ma demeure.
-
Le mur fléchit sous le noir bataillon.
-
La maison crie et chancelle penchée,
-
Et l'on dirait que, du sol arrachée,
-
Ainsi qu'il chasse une feuille séchée,
-
Le vent la roule avec leur tourbillon !`},
- },
-
- rdd: {
- msgSucces: async (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${rencData.rencontre.force} points de rêve`,
- msgEchec: async (rencData)=> `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${rencData.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`,
- postSucces: async (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData),
- postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData),
- poesieSucces: {
- reference: "Rêve de Dragon, Denis Gerfaud",
- extrait: `Le monde est Rêve de Dragons, mais nous ne savons
-
ni leur apparence ni qui sont les dragons.
-
En dépit de l'iconographie qui les clame
-
immenses créatures ailées crachant des flammes`},
- poesieEchec: {
- reference: "El Desdichado, Gérard de Nerval",
- extrait: `Je suis le Ténébreux, – le Veuf, – l'Inconsolé,
-
Le Prince d'Aquitaine à la Tour abolie :
-
Ma seule Etoile est morte, – et mon luth constellé
-
Porte le Soleil noir de la Mélancolie.`}
- },
-}
-
-/* -------------------------------------------- */
-const mauvaisesRencontres = [
- { 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: "reflet+4", name: "Reflet d'ancien Rêve", type: "reflet", 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: "tbnoir+4", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8+4", refoulement: 2, isPersistant: true, isMauvaise: true },
- { code: "passfou", name: "Passeur fou", type: "passeurfou", genre: "m", force: "2d8", refoulement: 2, isMauvaise: true },
- { code: "tbrouge", name: "Tourbillon rouge", type: "tbrouge", genre: "m", force: "2d8", refoulement: 3, isPersistant: true, isMauvaise: true }
-]
-
-/* -------------------------------------------- */
-const rencontresStandard = [
- { code: "messager", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d4", ignorer: true },
- { code: "passeur", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d4", ignorer: true },
- { code: "fleur", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "1d6", ignorer: true },
- { code: "mangeur", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6" },
- { code: "changeur", name: "Changeur de Rêve", type: "changeur", genre: "m", force: "2d6" },
- { code: "briseur", name: "Briseur de Rêve", type: "briseur", genre: "m", force: "2d6", quitterTMR: true },
- { code: "reflet", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6", isPersistant: true },
- { code: "tbblanc", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6", isPersistant: true },
- { code: "tbnoir", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8", isPersistant: true },
- { code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1dr + 7", refoulement: 2, quitterTMR: true }
-];
-
-const rencontresPresentCite = [
- { code: "messager2d6", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d6", ignorer: true },
- { code: "passeur2d6", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d6", ignorer: true },
- { code: "fleur2d6", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "2d6", ignorer: true }
-]
-const rencontresAll = [].concat(rencontresStandard).concat(mauvaisesRencontres).concat(rencontresPresentCite);
-
-const tableRencontres = {
- 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: '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: '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: '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: '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: '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: '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: '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: '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: '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: '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: '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: '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: '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] }]
-}
/* -------------------------------------------- */
export class TMRRencontres {
- static gestionRencontre = {}
-
- /* -------------------------------------------- */
- static init() {
- for (let type in typeRencontres) {
- TMRRencontres.register(type, typeRencontres[type]);
- }
- }
-
- /* -------------------------------------------- */
- static register(type, rencontre) {
- TMRRencontres.gestionRencontre[type] = rencontre;
- }
/* -------------------------------------------- */
/**
* Retourne une recontre en fonction de la case et du tirage
* @param {*} terrain
- * @param {*} roll
+ * @param {*} forcedRoll
*/
- static async rollRencontre(terrain, roll = undefined) {
+ static async rollRencontre(terrain, forcedRoll) {
+ // TODO: recherche parmi les types de terrains + mauvaise, rejet si plusieurs choix
+ const codeTerrain = Grammar.toLowerCaseNoAccent(terrain);
if (!terrain) {
- ChatMessage.create({ content: "Un type de case doit être indiqué (par exemple sanctuaire, desert ou cité)" });
+ ChatMessage.create({
+ user: game.user.id,
+ whisper: [game.user.id],
+ content: "Un type de case doit être indiqué (par exemple sanctuaire, desert ou cité)"
+ });
return false;
}
- if (!roll || roll <= 0 || roll > 100) {
- roll = await RdDDice.rollTotal("1d100");
+
+ if (forcedRoll && (forcedRoll <= 0 || forcedRoll > 100)) {
+ forcedRoll = undefined;
}
- let rencontre = await TMRRencontres.getRencontreAleatoire(terrain, roll);
+
+ const table = await TMRRencontres.$buildTableRencontre(codeTerrain);
+ const [selected, roll] = await TMRRencontres.$selectRencontre(codeTerrain, table, forcedRoll);
+ const rencontre = await TMRRencontres.createRencontre(selected.rencontre);
+ TMRRencontres.$chatRolledRencontre(rencontre, terrain, table, roll, true);
+ return false;
+ }
+
+ /* -------------------------------------------- */
+ static async $buildTableRencontre(codeTerrain) {
+ let max = 0;
+ const items = await SystemCompendiums.getItems('rencontres');
+ const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
+ const rencontres = items.filter(it => it.type == 'rencontre')
+ .filter(filtreMauvaise)
+ .filter(it => it.system.frequence[codeTerrain] > 0)
+ .sort(Misc.ascending(it => it.system.ordreTri))
+ .map(it => {
+ const frequence = it.system.frequence[codeTerrain];
+ max += frequence;
+ return { rencontre: it, min: max - frequence + 1, max: max,frequence: frequence };
+ });
+ return rencontres;
+ }
+
+ /* -------------------------------------------- */
+ static async $selectRencontre(terrain, table, roll = undefined) {
+ const total = table.map(it => it.frequence).reduce(Misc.sum(), 0);
+ if (total == 0){
+ ui.notifications.warn(`Pas de rencontres définies pour ${terrain}`);
+ return undefined;
+ }
+ if (roll != undefined && (roll > total || roll <= 0)) {
+ ui.notifications.warn(`Jet de rencontre ${roll} en dehors de la table [1..${total}], le jet est relancé`);
+ roll = undefined;
+ }
+ if (!roll) {
+ roll = await RdDDice.rollTotal(`1d${total}`);
+ }
+ return [table.find(it => it.min <= roll && roll <= it.max), roll];
+ }
+
+ /* -------------------------------------------- */
+ static async createRencontre(rencontre, tmr = undefined) {
+ return rencontre.clone({
+ 'system.force': await RdDDice.rollTotal(rencontre.system.formule),
+ 'system.coord': tmr?.coord,
+ 'system.date': game.system.rdd.calendrier.getDateFromIndex(),
+ 'system.heure': game.system.rdd.calendrier.getCurrentHeure()
+ }, {save: false});
+ }
+
+ static async calculRencontre(rencontre, tmr = undefined) {
+ if (rencontre.system.coord == ""){
+ rencontre.system.coord = tmr?.coord;
+ }
+ if (rencontre.system.force == 0){
+ rencontre.system.force = await RdDDice.rollTotal(rencontre.system.formule);
+ }
+ if (rencontre.system.date == "" ) {
+ rencontre.system.date = game.system.rdd.calendrier.getDateFromIndex();
+ }
+ if (rencontre.system.heure == "") {
+ rencontre.system.heure = game.system.rdd.calendrier.getCurrentHeure();
+ }
+ return rencontre;
+ }
+
+ /* -------------------------------------------- */
+ static $chatRolledRencontre(rencontre, terrain, table, roll = 0, displayTable=false){
+ const total = table.map(it => it.frequence).reduce(Misc.sum(), 0);
+ const namesPercent = displayTable ?
+ table.map(it => `
${it.rencontre.name} : ${it.frequence}${total == 100 ? '%' : ''} (${it.min} - ${it.max})`).reduce((a, b) => a + b, '
Tirer la prochaine rencontre dans les TMR sur la @Compendium[foundryvtt-reve-de-dragon.tables-diverses.66ye0OOxBO9LEjdd]{Table spéciale de rencontres}
","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[]} +{"_id":"0jrEZ62Q2Jz4kBGf","name":"Mauvaise rencontre en perspective","type":"queue","flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"La prochaine rencontre dans les TMR sera tirée de la @Compendium[foundryvtt-reve-de-dragon.tables-diverses.66ye0OOxBO9LEjdd]{Table spéciale de rencontres}
","descriptionmj":"","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":null,"modifiedTime":1668033514731,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"0uc2pMIGL03Hq2Hn","name":"Idée fixe : Anorexie. Ne rien avaler, ni solide, ni liquide, pas même une potion","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","data":{"description":"Prend effet immédiatement et dure jusqu'à la fin de l'heure du Château Dormant du lendemain.
Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.
Si elle entre en contradiction avec une autre queue, retirer.
","descriptionmj":"","refoulement":1,"duree":"","restant":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"rYShh2P1DNavdoBD":3},"flags":{}} {"_id":"1gGVlZM0UyifL6RK","name":"Souvenir obsessionnel de l'archétype","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"Les prochains points d’expérience dus au stress doivent être mis dans une compétence déterminée aléatoirement par la table de @Compendium[foundryvtt-reve-de-dragon.tables-diverses.E0WLgjn6LA9WsvKJ]{Détermination aléatoire de compétence}.
","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[]} {"_id":"1l59lWbtvYp74OTb","name":"Désir lancinant : Briser un objet de verre","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","data":{"description":"Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.
Les points d'expérience dus au stress ne sont pas affectés.
Comme je descendais des Fleuves impassibles,
Je ne me sentis plus guidé par les haleurs :
Des Peaux-Rouges criards les avaient pris pour cibles,
Les ayant cloués nus aux poteaux de couleurs.
Loin des peuples vivants, errantes, condamnées,
A travers les déserts courez comme les loups ;
Faites votre destin, âmes désordonnées,
Et fuyez l'infini que vous portez en vous !
J'irai là-bas où l'arbre et l'homme, pleins de sève,
Se pâment longuement sous l'ardeur des climats ;
Fortes tresses, soyez la houle qui m'enlève !
En réalité, tous les éléments du rêve des Dragons expriment
le Draconic : chaque pierre, chaque fleur, chaque goutte d'eau,
chaque nuage est porteur d'un message dans la langue des Dragons
La légende affirme que ce sont les Gnomes qui furent les premiers haut-rêvants. En observant les pierres précieuses, les gemmes qui sont les larmes de joie des Dragons, ils parvinrent à en comprendre la langue. Et l'ayant comprise, ils purent s'en servir pour influencer le cours du rêve.
","reference":"Rêve de Dragon, Denis Gerfaud"},"echec":{"effets":["rompu"],"message":"Le {{rencontre.name}} vous déconcentre au point de briser votre demi-rêve.","poesie":"Quand le rêve se brise,
Dans la plainte du jour,
Ma mémoire devient grise
Et sombre, tour à tour,
Dans le puits du silence
Et de la solitude ;
Elle reprend son errance
Parmi la multitude.
Les formes s'effaçaient et n'étaient plus qu'un rêve,
Une ébauche lente à venir
Sur la toile oubliée, et que l'artiste achève
Seulement par le souvenir.
Longtemps ! toujours ! ma main dans ta crinière lourde
Sèmera le rubis, la perle et le saphir,
Afin qu'à mon désir tu ne sois jamais sourde !
N'es-tu pas l'oasis où je rêve, et la gourde
Où je hume à longs traits le vin du souvenir
Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les Gnomes s'enfoncèrent profondément sous les montagnes et la magie passa aux mains des Humains qui en usèrent et abusèrent, se croyant devenus les maîtres du monde
","reference":"Rêve de Dragon, Denis Gerfaud"},"echec":{"effets":["reve-1","reve-1","aleatoire","aleatoire","persistant"],"message":"Le {{rencontre.name}} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.","poesie":"Elle aurait pas cru sans le voir
Que la couleur du désespoir
Là-bas aussi ce fût le noir.
Les formes s'effaçaient et n'étaient plus qu'un rêve,
Une ébauche lente à venir
Sur la toile oubliée, et que l'artiste achève
Seulement par le souvenir.
Longtemps ! toujours ! ma main dans ta crinière lourde
Sèmera le rubis, la perle et le saphir,
Afin qu'à mon désir tu ne sois jamais sourde !
N'es-tu pas l'oasis où je rêve, et la gourde
Où je hume à longs traits le vin du souvenir
Allez, que le caprice emporte
Chaque âme selon son désir,
Et que, close après vous, la porte
Ne se rouvre plus qu'au plaisir.
Les sages ont encore coutume de dire :
« Mais comment les Dragons peuvent-ils être influencés par une créature qui, tout bien considéré, n'existe pas vraiment pour eux, qui n'est que le fantasme de leur activité nocturne ? »
Le monde est Rêve de Dragons, mais nous ne savons
Ni leur apparence ni qui sont les dragons.
En dépit de l'iconographie qui les clame
Immenses créatures ailées crachant des flammes
Je suis le Ténébreux, – le Veuf, – l'Inconsolé,
Le Prince d'Aquitaine à la Tour abolie :
Ma seule Etoile est morte, – et mon luth constellé
Porte le Soleil noir de la Mélancolie.
Certain Fou poursuivait à coups de pierre un Sage.
Le Sage se retourne et lui dit : Mon ami,
C'est fort bien fait à toi ; reçois cet écu-ci :
Tu fatigues assez pour gagner davantage.
Je la voyais passer de ma demeure,
Et c'était tout.
Mais à présent je m'ennuie à toute heure,
Plein de dégoût,
Rêveur oisif, l'âme dans la campagne,
La dague au clou ... –
Le vent qui vient à travers la montagne
M'a rendu fou !
Rois ! la bure est souvent jalouse du velours.
Le peuple a froid l'hiver, le peuple a faim toujours.
Rendez-lui son sort plus facile.
Le peuple souvent porte un bien rude collier.
Ouvrez l'école aux fils, aux pères l'atelier,
À tous vos bras, auguste asile !
Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les Gnomes s'enfoncèrent profondément sous les montagnes et la magie passa aux mains des Humains qui en usèrent et abusèrent, se croyant devenus les maîtres du monde
","reference":"Rêve de Dragon, Denis Gerfaud"},"echec":{"effets":["reve-1","reve-1","aleatoire","aleatoire","persistant"],"message":"Le {{rencontre.name}} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.","poesie":"Elle aurait pas cru sans le voir
Que la couleur du désespoir
Là-bas aussi ce fût le noir.
Et qui sait si les fleurs nouvelles que je rêve
Trouveront dans ce sol lavé comme une grève
Le mystique aliment qui ferait leur vigueur ?
Et le ciel regardait la carcasse superbe
Comme une fleur s'épanouir.
La puanteur était si forte, que sur l'herbe
Vous crûtes vous évanouir.
Qu'est-ce de votre vie ? un tourbillon rouant
De fumière à flot gris, parmi l'air se jouant,
Qui passe plus soudain que foudre meurtrière.
Cris de l'enfer! voix qui hurle et qui pleure !
L'horrible essaim, poussé par l'aquilon,
Sans doute, ô ciel ! s'abat sur ma demeure.
Le mur fléchit sous le noir bataillon.
La maison crie et chancelle penchée,
Et l'on dirait que, du sol arrachée,
Ainsi qu'il chasse une feuille séchée,
Le vent la roule avec leur tourbillon !
Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement
des temps, le commencement des rêves. Durant cette période plus mythique
que réellement historique, les Dragons aimaient à se rêver eux-mêmes.
C'est l'essaim des Djinns qui passe,
Et tourbillonne en sifflant !
Les ifs, que leur vol fracasse,
Craquent comme un pin brûlant.
Rois ! la bure est souvent jalouse du velours.
Le peuple a froid l'hiver, le peuple a faim toujours.
Rendez-lui son sort plus facile.
Le peuple souvent porte un bien rude collier.
Ouvrez l'école aux fils, aux pères l'atelier,
À tous vos bras, auguste asile !
Rois ! la bure est souvent jalouse du velours.
Le peuple a froid l'hiver, le peuple a faim toujours.
Rendez-lui son sort plus facile.
Le peuple souvent porte un bien rude collier.
Ouvrez l'école aux fils, aux pères l'atelier,
À tous vos bras, auguste asile !
Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement
des temps, le commencement des rêves. Durant cette période plus mythique
que réellement historique, les Dragons aimaient à se rêver eux-mêmes.
C'est l'essaim des Djinns qui passe,
Et tourbillonne en sifflant !
Les ifs, que leur vol fracasse,
Craquent comme un pin brûlant.