diff --git a/module/actor-sheet.js b/module/actor-sheet.js
index 0ee4994f..6b103ad2 100644
--- a/module/actor-sheet.js
+++ b/module/actor-sheet.js
@@ -101,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()
}
@@ -170,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.js b/module/actor.js
index 37f90e46..b0e46eb0 100644
--- a/module/actor.js
+++ b/module/actor.js
@@ -36,6 +36,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',
@@ -757,25 +758,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) }
]
}
);
@@ -784,27 +784,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)
}
/* -------------------------------------------- */
@@ -1541,42 +1525,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 });
}
@@ -2383,7 +2352,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) {
@@ -3825,7 +3794,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/effets-rencontres.js b/module/effets-rencontres.js
new file mode 100644
index 00000000..a0697d74
--- /dev/null
+++ b/module/effets-rencontres.js
@@ -0,0 +1,111 @@
+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_f = 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_f = 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 vie_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
+
+
+ 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 $reve_plus = async (actor, valeur) => {
+ await actor.reveActuelIncDec(valeur);
+ }
+
+ static $vie_plus = async (actor, valeur) => {
+ await actor.santeIncDec("vie", valeur);
+ }
+
+ 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
index 46b2b54b..baaf5d8d 100644
--- a/module/item-rencontre-sheet.js
+++ b/module/item-rencontre-sheet.js
@@ -1,4 +1,3 @@
-import { SYSTEM_RDD } from "./constants.js";
import { RdDRencontre } from "./item-rencontre.js";
/**
diff --git a/module/item-rencontre.js b/module/item-rencontre.js
index 66454b34..0b07ddf7 100644
--- a/module/item-rencontre.js
+++ b/module/item-rencontre.js
@@ -1,52 +1,38 @@
-import { RdDRollTables } from "./rdd-rolltables.js";
+import { EffetsRencontre } from "./effets-rencontres.js";
const tableEffets = [
- { code: "messager", resultat: "succes", description: "Envoie un message à (force) cases" },
- { code: "passeur", resultat: "succes", description: "Déplacer le demi-rêve à (force) cases" },
- { code: "reve+f", resultat: "succes", description: "Gain de (force) points de rêve" },
- { code: "teleport", resultat: "succes", description: "Déplacer le demi-rêve (même type de case)" },
- { code: "part+tete", resultat: "succes", description: "Tête de dragon sur réussite particulière" },
- { code: "part+xp", resultat: "succes", description: "Expérience sur réussite particulière" },
+ { 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_f},
+ { 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" },
- { code: "reve-f", resultat: "echec", description: "Perte de (force) points de rêve" },
- { code: "vie-1", resultat: "echec", description: "Perte de 1 point de vie" },
- { code: "reinsere", resultat: "echec", description: "Réinsertion aléatoire" },
- { code: "declenhe", resultat: "echec", description: "Déclenche un sort aléatoire" },
- { code: "persistant", resultat: "echec", description: "Bloque le demi-rêve" },
- { code: "teleport-aleatoire", resultat: "echec", description: "Déplacement aléatoire (même type de case)" },
- { code: "aleatoire", resultat: "echec", description: "Déplacement aléatoire" },
- { code: "sort-aleatoire", resultat: "echec", description: "Déplacement pour déclencher un sort en réserve aléatoire" },
- { code: "rompu", resultat: "echec", description: "Demi-rêve interrompu" },
- { code: "echec-queue", resultat: "echec", description: "Queue de dragon sur échec" },
- { code: "etotal-queue", resultat: "echec", description: "Queue de dragon sur échec total" },
-
- { code: "moral+1", resultat: "succes", description: "Gain de 1 point de moral" },
- { code: "reve+1", resultat: "succes", description: "Gain de 1 point de rêve" },
- { code: "vie-f", resultat: "echec", description: "Perte de (force) point de vie" },
- { code: "endurance-1", resultat: "echec", description: "Perte de 1 point d'endurance" },
- { code: "endurance-f", resultat: "echec", description: "Perte de (force) point d'endurance" },
- { code: "fatigue-1", resultat: "echec", description: "Perte de 1 point de fatigue" },
- { code: "fatigue-f", resultat: "echec", description: "Perte de (force) point de fatigue" },
- { code: "moral-1", resultat: "echec", description: "Perte de 1 point de moral" },
- { code: "chance-1", resultat: "echec", description: "Perte de 1 point de chance actuelle" },
- { code: "chance-f", resultat: "echec", description: "Perte de (force) point de chance" },
- { code: "epart-queue", resultat: "echec", description: "Queue de dragon sur échec particulier" },
- { code: "etotal-souffle", resultat: "echec", description: "Souffle de dragon sur échec total" },
- { code: "epart-souffle", resultat: "echec", description: "Souffle de dragon sur échec particulier" },
+ { 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_f },
+ { 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 },
];
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 getEffetsSucces() { return RdDRencontre.getEffets("succes"); }
- static getEffetsEchec() { return RdDRencontre.getEffets("echec"); }
-
+
static mapEffets(liste) {
- return liste.map(it => tableEffets.find(e => it == e.code));
+ return liste.map(it => RdDRencontre.getEffet(it));
}
-
+
static getListeEffets(item, reussite) {
if (reussite == 'echec') {
return [...item.system.echec.effets];
@@ -57,4 +43,14 @@ export class RdDRencontre {
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/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 05459e94..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;
}
/* -------------------------------------------- */
diff --git a/module/rdd-main.js b/module/rdd-main.js
index 81a80311..86a15f4d 100644
--- a/module/rdd-main.js
+++ b/module/rdd-main.js
@@ -221,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-tmr-dialog.js b/module/rdd-tmr-dialog.js
index 893cabbb..80d129be 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 "./settings/regles-optionelles.js";
import { RdDDice } from "./rdd-dice.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() {
@@ -370,7 +381,9 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async maitriserRencontre() {
- this.actor.deleteTMRRencontreAtPosition();
+ console.log("-> maitriser", this.currentRencontre);
+
+ await this.actor.deleteTMRRencontreAtPosition();
this.updateTokens();
let rencontreData = {
@@ -381,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())
}
@@ -390,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();
@@ -401,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;
}
@@ -479,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);
@@ -500,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);
@@ -530,32 +571,27 @@ 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 });
+ console.warn('// TODO: remettre myRoll==7');
+ 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 = (isMauvaise
- ? await TMRRencontres.getMauvaiseRencontre()
- : await TMRRencontres.getRencontreAleatoire(tmr));
- 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 == "");
}
/* -------------------------------------------- */
@@ -583,7 +619,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);
}
}
@@ -874,16 +910,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.
@@ -892,20 +926,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();
@@ -913,19 +945,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/rolldata-ajustements.js b/module/rolldata-ajustements.js
index 7ba8b0b5..2807065a 100644
--- a/module/rolldata-ajustements.js
+++ b/module/rolldata-ajustements.js
@@ -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/settings/system-compendiums.js b/module/settings/system-compendiums.js
index 17474e3d..21bdbe9d 100644
--- a/module/settings/system-compendiums.js
+++ b/module/settings/system-compendiums.js
@@ -48,8 +48,7 @@ export class SystemCompendiums extends FormApplication {
static async getContent(compendium, docType) {
const pack = SystemCompendiums.getPack(compendium);
- if (pack.metadata.type == docType)
- {
+ if (pack.metadata.type == docType) {
return await pack.getDocuments();
}
return [];
@@ -59,6 +58,14 @@ export class SystemCompendiums extends FormApplication {
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);
diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js
index d8634310..14f94dc2 100644
--- a/module/tmr-rencontres.js
+++ b/module/tmr-rencontres.js
@@ -1,335 +1,22 @@
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 de ${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: "Le bateau ivre, Arthur Rimbaud",
- 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: "Femmes damnées (2), Charles Baudelaire",
- 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({
user: game.user.id,
@@ -338,170 +25,118 @@ export class TMRRencontres {
});
return false;
}
- TMRRencontres.selectRencontre(terrain);
- const codeTerrain = Grammar.toLowerCaseNoAccent(terrain);
-
- if (!roll || roll <= 0 || roll > 100) {
- roll = await RdDDice.rollTotal("1d100");
+
+ if (forcedRoll && (forcedRoll <= 0 || forcedRoll > 100)) {
+ forcedRoll = undefined;
}
+
+ 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});
+ }
- let rencontre = await TMRRencontres.getRencontreAleatoire({type: codeTerrain, coord:''}, roll);
+ 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, '