1137 lines
39 KiB
JavaScript
1137 lines
39 KiB
JavaScript
import { SHOW_DICE, SYSTEM_RDD } from "./constants.js";
|
|
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
|
import { RdDUtility } from "./rdd-utility.js";
|
|
import { TMRUtility } from "./tmr-utility.js";
|
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
|
import { RdDTMRRencontreDialog } from "./rdd-tmr-rencontre-dialog.js";
|
|
import { ChatUtility } from "./chat-utility.js";
|
|
import { RdDRoll } from "./rdd-roll.js";
|
|
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 { HtmlUtility } from "./html-utility.js";
|
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
|
import { RdDDice } from "./rdd-dice.js";
|
|
import { STATUSES } from "./settings/status-effects.js";
|
|
import { RdDRencontre } from "./item/rencontre.js";
|
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
|
import { TYPES } from "./item.js";
|
|
import { Misc } from "./misc.js";
|
|
|
|
const TMR_DISPLAY_SIZE = {
|
|
code: 'tmr-display-size',
|
|
range: {
|
|
min: 32,
|
|
max: 128,
|
|
step: 8,
|
|
},
|
|
def: 64,
|
|
clamp: (size, inc = 0) => Math.max(TMR_DISPLAY_SIZE.range.min, Math.min(size + (inc * TMR_DISPLAY_SIZE.range.step), TMR_DISPLAY_SIZE.range.max)),
|
|
get: () => TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def),
|
|
set: (size) => game.settings.set(SYSTEM_RDD, TMR_DISPLAY_SIZE.code, TMR_DISPLAY_SIZE.clamp(size)),
|
|
};
|
|
|
|
/* -------------------------------------------- */
|
|
export class RdDTMRDialog extends Dialog {
|
|
static async init() {
|
|
game.settings.register(SYSTEM_RDD, TMR_DISPLAY_SIZE.code, {
|
|
name: 'Taille des cases des TMR',
|
|
hint: "Taille en pixel des cases des TMR (réglable directement dans la fenêtre des TMR)",
|
|
scope: "client",
|
|
config: true,
|
|
default: TMR_DISPLAY_SIZE.def,
|
|
type: Number,
|
|
range: TMR_DISPLAY_SIZE.range
|
|
})
|
|
}
|
|
|
|
static async create(actor, tmrData) {
|
|
await PixiTMR.init()
|
|
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', tmrData);
|
|
if (tmrData.mode != 'visu' && !game.user.isGM) {
|
|
ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatMessage.getWhisperRecipients("GM") });
|
|
}
|
|
return new RdDTMRDialog(html, actor, tmrData)
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
constructor(html, actor, tmrData) {
|
|
const dialogConf = {
|
|
title: "Terres Médianes de Rêve",
|
|
content: html,
|
|
buttons: {}
|
|
}
|
|
const dialogOptions = {
|
|
classes: ["tmrdialog"],
|
|
width: 'fit-content',
|
|
height: 'fit-content',
|
|
'max-height': 1024,
|
|
'z-index': 40
|
|
}
|
|
super(dialogConf, dialogOptions);
|
|
this.tmrdata = duplicate(tmrData);
|
|
this.actor = actor;
|
|
this.actor.tmrApp = this; // reference this app in the actor structure
|
|
this.viewOnly = tmrData.mode == "visu"
|
|
this.fatigueParCase = this.viewOnly ? 0 : this.actor.getCoutFatigueTMR();
|
|
this.cumulFatigue = 0;
|
|
this.loadRencontres();
|
|
this.loadCasesSpeciales();
|
|
this.allTokens = [];
|
|
this.rencontreState = 'aucune';
|
|
this.subdialog = undefined
|
|
this.displaySize = undefined
|
|
if (!this.viewOnly) {
|
|
this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
|
|
}
|
|
this.callbacksOnAnimate = [];
|
|
const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def);
|
|
this.pixiTMR = new PixiTMR(this, displaySize);
|
|
this.resizePixiTMR(displaySize)
|
|
}
|
|
|
|
resizePixiTMR(displaySize) {
|
|
if (displaySize != this.displaySize) {
|
|
this.displaySize = displaySize
|
|
this.pixiTMR.resizeTMR(displaySize);
|
|
this._removeTokens()
|
|
this.allTokens = []
|
|
this.createPixiSprites()
|
|
this.pixiTMR.loadAnimations();
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async activateListeners(html) {
|
|
super.activateListeners(html);
|
|
this.html = html;
|
|
|
|
// this.activateTMRSize()
|
|
this.addTMRMap()
|
|
this.html.find('div.tmr-size a.tmr-size-zoom-minus*').click(event => {
|
|
this.$changeTMRSize(-1)
|
|
});
|
|
this.html.find('div.tmr-size a.tmr-size-zoom-plus*').click(event => {
|
|
this.$changeTMRSize(1)
|
|
});
|
|
|
|
|
|
if (this.viewOnly) {
|
|
this.html.find('.lancer-sort').remove();
|
|
this.html.find('.lire-signe-draconique').remove();
|
|
return;
|
|
}
|
|
|
|
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue"));
|
|
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getCoordActor()));
|
|
|
|
this.html.find('form.tmr-dialog *').click(event => this.subdialog?.bringToTop());
|
|
|
|
// Roll Sort
|
|
this.html.find('.lancer-sort').click(event => this.actor.rollUnSort(this._getCoordActor()));
|
|
this.html.find('.lire-signe-draconique').click(event => this.actor.rollLireSigneDraconique(this._getCoordActor()));
|
|
|
|
this.html.find('img.tmr-move').click(event => this.deplacementTMR(this.html.find(event.currentTarget)?.data('move')));
|
|
|
|
// Gestion du cout de montée en points de rêve
|
|
await this.actor.reveActuelIncDec(this.calculCoutMonteeTMR());
|
|
this.cumulFatigue += this.fatigueParCase;
|
|
|
|
// Le reste...
|
|
this.updateValuesDisplay();
|
|
}
|
|
|
|
async onDeplacement() {
|
|
await this.manageRencontre(TMRUtility.getTMR(this._getCoordActor()));
|
|
}
|
|
|
|
addTMRMap() {
|
|
const tmrCell = document.getElementsByClassName("tmr-map")[0];
|
|
tmrCell.childNodes.forEach(node => tmrCell.removeChild(node))
|
|
tmrCell.append(this.pixiTMR.view);
|
|
}
|
|
|
|
$changeTMRSize(inc) {
|
|
let displaySize = TMR_DISPLAY_SIZE.clamp(this.displaySize, inc)
|
|
if (displaySize != this.displaySize) {
|
|
game.settings.set(SYSTEM_RDD, TMR_DISPLAY_SIZE.code, TMR_DISPLAY_SIZE.clamp(displaySize))
|
|
this.resizePixiTMR(displaySize)
|
|
this.render()
|
|
}
|
|
}
|
|
|
|
async forceTMRDisplay() {
|
|
if (this.rendered) {
|
|
this.bringToTop()
|
|
if (this.subdialog?.bringToTop) {
|
|
this.subdialog.bringToTop();
|
|
}
|
|
}
|
|
}
|
|
|
|
async restoreTMRAfterAction() {
|
|
this.subdialog = undefined
|
|
await this.maximize();
|
|
this.bringToTop();
|
|
}
|
|
|
|
forceTMRContinueAction() {
|
|
ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR');
|
|
if (this.subdialog?.bringToTop) {
|
|
this.subdialog.bringToTop();
|
|
}
|
|
return;
|
|
}
|
|
|
|
setTMRPendingAction(dialog) {
|
|
this.subdialog = dialog
|
|
this.forceTMRDisplay()
|
|
}
|
|
|
|
isDemiReveCache() {
|
|
return !game.user.isGM && this.actor.isTMRCache();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
loadCasesSpeciales() {
|
|
this.casesSpeciales = this.actor.items.filter(item => Draconique.isCaseTMR(item));
|
|
}
|
|
|
|
get sortsReserve() {
|
|
return this.actor.itemTypes[TYPES.sortreserve];
|
|
}
|
|
|
|
getSortsReserve(coord) {
|
|
return this.actor.itemTypes[TYPES.sortreserve].filter(// Reserve sur une case fleuve ou normale
|
|
TMRUtility.getTMR(coord).type == 'fleuve'
|
|
? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve'
|
|
: it => it.system.coord == coord
|
|
);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
loadRencontres() {
|
|
this.rencontresExistantes = this.actor.getTMRRencontres();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
createPixiSprites() {
|
|
this.pixiTMR.setup()
|
|
this.updateTokens()
|
|
this.forceDemiRevePositionView()
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_createTokens() {
|
|
if (!this.isDemiReveCache()) {
|
|
this.demiReve = this._tokenDemiReve();
|
|
this._trackToken(this.demiReve);
|
|
}
|
|
this._getTokensCasesTmr().forEach(t => this._trackToken(t))
|
|
this._getTokensRencontres().forEach(t => this._trackToken(t))
|
|
this._getTokensSortsReserve().forEach(t => this._trackToken(t))
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
updateTokens() {
|
|
this._removeTokens(t => true);
|
|
this.loadRencontres();
|
|
this.loadCasesSpeciales();
|
|
this._createTokens();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
removeToken(tmr, casetmr) {
|
|
this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id);
|
|
this.updateTokens()
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_getTokensCasesTmr() {
|
|
return Misc.concat(this.casesSpeciales.map(caseSpeciale =>
|
|
Draconique.get(caseSpeciale.system.specific)?.token(this.pixiTMR, caseSpeciale, () => caseSpeciale.system.coord)
|
|
))
|
|
}
|
|
|
|
_getTokensRencontres() {
|
|
return Misc.concat(this.rencontresExistantes.map(rencontre =>
|
|
EffetsDraconiques.rencontre.tokens(this.pixiTMR, rencontre, () => rencontre.system.coord)
|
|
))
|
|
}
|
|
|
|
_getTokensSortsReserve() {
|
|
const sortsReserve = this.actor.itemTypes[TYPES.sortreserve];
|
|
return Misc.concat(sortsReserve.map(sortReserve =>
|
|
EffetsDraconiques.sortReserve.tokens(this.pixiTMR, sortReserve, () => sortReserve.system.coord)))
|
|
}
|
|
|
|
_tokenDemiReve() {
|
|
return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => this.actor.system.reve.tmrpos.coord);
|
|
}
|
|
|
|
forceDemiRevePositionView() {
|
|
this.notifierResonanceSigneDraconique(this._getCoordActor());
|
|
this._trackToken(this.demiReve);
|
|
}
|
|
|
|
_getCoordActor() {
|
|
return this.actor.system.reve.tmrpos.coord;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async deplacementTMR(move) {
|
|
if (this.subdialog) {
|
|
return this.forceTMRContinueAction();
|
|
}
|
|
|
|
const coordOrig = this._getCoordActor();
|
|
const coordTarget = TMRUtility.deplacement(coordOrig, move);
|
|
await this._deplacerDemiReve(coordTarget, 'normal');
|
|
this.checkQuitterTMR();
|
|
}
|
|
|
|
calculCoutMonteeTMR() {
|
|
return ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async updateValuesDisplay() {
|
|
if (this.viewOnly || !this.rendered) {
|
|
return;
|
|
}
|
|
const coord = this._getCoordActor();
|
|
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
|
|
|
|
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
|
ptsreve.innerHTML = this.actor.system.reve.reve.value;
|
|
|
|
let tmrpos = document.getElementById("tmr-pos");
|
|
if (this.isDemiReveCache()) {
|
|
tmrpos.innerHTML = `?? ( ${TMRUtility.getTMRType(coord)})`;
|
|
} else {
|
|
tmrpos.innerHTML = `${coord} ( ${TMRUtility.getTMRLabel(coord)})`;
|
|
}
|
|
|
|
let etat = document.getElementById("tmr-etatgeneral-value");
|
|
etat.innerHTML = this.actor.getEtatGeneral();
|
|
|
|
let refoulement = document.getElementById("tmr-refoulement-value");
|
|
refoulement.innerHTML = this.actor.system.reve.refoulement.value;
|
|
|
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
|
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
|
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.system.sante.fatigue.value, this.actor.system.sante.endurance.max).html() + "</table>";
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async close() {
|
|
if (this.subdialog) {
|
|
return this.forceTMRContinueAction()
|
|
}
|
|
this.descenteTMR = true;
|
|
if (this.actor.tmrApp) {
|
|
this.actor.tmrApp = undefined; // Cleanup reference
|
|
if (!this.viewOnly) {
|
|
await this.actor.setEffect(STATUSES.StatusDemiReve, false)
|
|
this._tellToGM(this.actor.name + " a quitté les terres médianes");
|
|
}
|
|
await this.actor.santeIncDec((ReglesOptionnelles.isUsing("appliquer-fatigue") ? "fatigue" : "endurance"),
|
|
this.cumulFatigue)
|
|
}
|
|
await super.close();
|
|
this.pixiTMR.close()
|
|
this.pixiTMR = undefined
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async onActionRencontre(action, tmr, rencontre) {
|
|
if (!this.currentRencontre) {
|
|
ui.notifications.warn("#612 Rencontre perdue, récupération en cours. Vous pouvez contacter l'équipe avec les logs pour aider à résoudre ce problème")
|
|
console.error("#612 Rencontre perdue", action, tmr, rencontre, this);
|
|
this.currentRencontre = rencontre;
|
|
}
|
|
switch (action) {
|
|
case 'derober':
|
|
await this.derober();
|
|
this.restoreTMRAfterAction();
|
|
return;
|
|
case 'refouler':
|
|
await this.refouler();
|
|
break;
|
|
case 'maitriser':
|
|
await this.maitriserRencontre();
|
|
break;
|
|
case 'ignorer':
|
|
await this.ignorerRencontre();
|
|
break;
|
|
}
|
|
await this.postRencontre(tmr);
|
|
this.restoreTMRAfterAction();
|
|
}
|
|
|
|
async derober() {
|
|
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() {
|
|
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();
|
|
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();
|
|
this.updateValuesDisplay();
|
|
this.nettoyerRencontre();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
// garder la trace de l'état en cours
|
|
setRencontreState(state, listCoordTMR) {
|
|
this.rencontreState = state;
|
|
this.$marquerCasesTMR(listCoordTMR ?? []);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
$marquerCasesTMR(listCoordTMR) {
|
|
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location
|
|
this.currentRencontre.graphics = listCoordTMR.map(coordTMR => this.pixiTMR.addMarkTMR(coordTMR))
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
checkQuitterTMR() {
|
|
if (this.actor.isDead()) {
|
|
this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !");
|
|
this.close();
|
|
return true;
|
|
}
|
|
|
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue")
|
|
? (this.actor.getFatigueRestante() <= this.cumulFatigue)
|
|
: (this.actor.getEnduranceActuelle() <= this.cumulFatigue)
|
|
) {
|
|
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
|
|
this.quitterLesTMRInconscient();
|
|
return true;
|
|
}
|
|
|
|
if (this.actor.getReveActuel() == 0) {
|
|
this._tellToGM("Vos Points de Rêve sont à 0 : vous quittez les Terres médianes !");
|
|
this.quitterLesTMRInconscient();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async quitterLesTMRInconscient() {
|
|
await this.refouler();
|
|
this.close();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async maitriserRencontre() {
|
|
console.log("-> maitriser", this.currentRencontre);
|
|
|
|
await this.actor.deleteTMRRencontreAtPosition();
|
|
this.updateTokens();
|
|
|
|
let rencontreData = {
|
|
actor: this.actor,
|
|
alias: this.actor.name,
|
|
reveDepart: this.actor.getReveActuel(),
|
|
competence: this.actor.getBestDraconic(),
|
|
rencontre: this.currentRencontre,
|
|
nbRounds: 1,
|
|
canClose: false,
|
|
selectedCarac: { label: "reve-actuel" },
|
|
tmr: TMRUtility.getTMR(this._getCoordActor())
|
|
}
|
|
|
|
await this._tentativeMaitrise(rencontreData);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async _tentativeMaitrise(rencData) {
|
|
this.rencontreState = 'normal';
|
|
|
|
rencData.reve = this.actor.getReveActuel();
|
|
rencData.etat = this.actor.getEtatGeneral();
|
|
|
|
RollDataAjustements.calcul(rencData, this.actor);
|
|
|
|
rencData.rolled = rencData.presentCite
|
|
? this._rollPresentCite(rencData)
|
|
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
|
|
|
|
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)
|
|
});
|
|
|
|
this.updateValuesDisplay();
|
|
if (this.checkQuitterTMR()) {
|
|
return;
|
|
}
|
|
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 (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
|
this.cumulFatigue += this.fatigueParCase;
|
|
}
|
|
this._tentativeMaitrise(rencData);
|
|
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
|
|
}, 2000);
|
|
}
|
|
|
|
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(rencData) {
|
|
let rolled = RdDResolutionTable.computeChances(rencData.reve, 0);
|
|
foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score });
|
|
RdDResolutionTable.succesRequis(rolled);
|
|
return rolled;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_deleteTmrMessages(actor, nbRounds = -1) {
|
|
setTimeout(() => {
|
|
if (nbRounds < 0) {
|
|
ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}"`);
|
|
}
|
|
else {
|
|
for (let i = 1; i < nbRounds; i++) {
|
|
ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}" data-rencontre-round="${i}">`);
|
|
}
|
|
}
|
|
}, 500);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_tellToUser(message) {
|
|
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] });
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_tellToGM(message) {
|
|
ChatMessage.create({ content: message, user: game.user.id, whisper: ChatMessage.getWhisperRecipients("GM") });
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_tellToUserAndGM(message) {
|
|
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id].concat(ChatMessage.getWhisperRecipients("GM")) });
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async manageRencontre(tmr) {
|
|
if (this.viewOnly) {
|
|
return;
|
|
}
|
|
this.descenteTMR = false;
|
|
this.currentRencontre = undefined;
|
|
if (await this._presentCite(tmr)) {
|
|
return;
|
|
}
|
|
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 {
|
|
const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr);
|
|
await dialog.render(true);
|
|
this.setTMRPendingAction(dialog);
|
|
}
|
|
}
|
|
else {
|
|
this.postRencontre(tmr);
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async _presentCite(tmr) {
|
|
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
|
|
if (presentCite) {
|
|
const caseData = presentCite;
|
|
const dialog = await EffetsDraconiques.presentCites.choisirUnPresent(caseData, present => {
|
|
this._utiliserPresentCite(presentCite, present, tmr)
|
|
this.restoreTMRAfterAction();
|
|
});
|
|
this.setTMRPendingAction(dialog);
|
|
}
|
|
return presentCite;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
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);
|
|
|
|
// simuler une rencontre
|
|
let rencontreData = {
|
|
actor: this.actor,
|
|
alias: this.actor.name,
|
|
reveDepart: this.actor.getReveActuel(),
|
|
competence: this.actor.getBestDraconic(),
|
|
rencontre: this.currentRencontre,
|
|
tmr: tmr,
|
|
presentCite: presentCite
|
|
};
|
|
await this._tentativeMaitrise(rencontreData);
|
|
this.postRencontre(tmr);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async _jetDeRencontre(tmr) {
|
|
let rencontre = this.lookupRencontreExistente(tmr);
|
|
if (rencontre) {
|
|
return game.system.rdd.rencontresTMR.calculRencontre(rencontre, tmr);
|
|
}
|
|
const coordTMR = (this.isDemiReveCache()
|
|
? TMRUtility.getTMRType(tmr.coord) + " ??"
|
|
: tmr.label + " (" + tmr.coord + ")");
|
|
|
|
this.setTMRPendingAction({ bringToTop: () => { } })
|
|
const myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
|
|
this.restoreTMRAfterAction()
|
|
if (myRoll == 7) {
|
|
this._tellToUser(myRoll + ": Rencontre en " + coordTMR);
|
|
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
|
|
} else {
|
|
this._tellToUser(myRoll + ": Pas de rencontre en " + coordTMR);
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
lookupRencontreExistente(tmr) {
|
|
return this.rencontresExistantes.find(it => it.system.coord == tmr.coord)
|
|
?? this.rencontresExistantes.find(it => it.system.coord == "");
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async manageTmrInnaccessible(tmr) {
|
|
if (!tmr) {
|
|
return await this.actor.reinsertionAleatoire('Sortie de carte');
|
|
}
|
|
const caseTmrInnaccessible = this.casesSpeciales.find(c => EffetsDraconiques.isInnaccessible(c, tmr.coord));
|
|
if (caseTmrInnaccessible) {
|
|
return await this.actor.reinsertionAleatoire(caseTmrInnaccessible.name);
|
|
}
|
|
return tmr;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async manageCaseHumide(tmr) {
|
|
if (this.isCaseHumide(tmr)) {
|
|
let rollData = {
|
|
actor: this.actor,
|
|
competence: duplicate(this.actor.getBestDraconic()),
|
|
tmr: tmr,
|
|
canClose: false,
|
|
diffLibre: -7,
|
|
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
|
|
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
|
|
}
|
|
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined,
|
|
rollData.competence.system.defaut_carac = 'reve-actuel';
|
|
await this._rollMaitriseCaseHumide(rollData);
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async _rollMaitriseCaseHumide(rollData) {
|
|
await this._maitriserTMR(rollData, r => this._resultatMaitriseCaseHumide(r));
|
|
}
|
|
|
|
async _resultatMaitriseCaseHumide(rollData) {
|
|
if (rollData.rolled.isSuccess && rollData.double) {
|
|
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
|
|
rollData.double = undefined;
|
|
await this._rollMaitriseCaseHumide(rollData);
|
|
return;
|
|
}
|
|
rollData.poesie = await Poetique.getExtrait();
|
|
ChatMessage.create({
|
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
|
|
});
|
|
if (rollData.rolled.isEchec) {
|
|
await this.close();
|
|
}
|
|
await this.souffleSiEchecTotal(rollData);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async souffleSiEchecTotal(rollData) {
|
|
if (rollData.rolled.isETotal) {
|
|
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
isCaseHumide(tmr) {
|
|
if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) {
|
|
return false;
|
|
}
|
|
if (this.isCaseMaitrisee(tmr.coord)) {
|
|
ChatMessage.create({
|
|
content: tmr.label + ": cette case humide est déja maitrisée grâce à votre Tête <strong>Quête des Eaux</strong>",
|
|
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
|
});
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
isCaseHumideAdditionelle(tmr) {
|
|
if (tmr.type == 'pont' && EffetsDraconiques.isPontImpraticable(this.actor)) {
|
|
ChatMessage.create({
|
|
content: tmr.label + ": Vous êtes sous le coup d'une Impraticabilité des Ponts : ce pont doit être maîtrisé comme une case humide.",
|
|
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
|
});
|
|
return true;
|
|
}
|
|
if (this.isCaseInondee(tmr.coord)) {
|
|
ChatMessage.create({
|
|
content: tmr.label + ": cette case est inondée, elle doit être maîtrisée comme une case humide.",
|
|
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
|
});
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async conquerirCiteFermee(tmr) {
|
|
if (EffetsDraconiques.fermetureCites.find(this.casesSpeciales, tmr.coord)) {
|
|
await this._conquerir(tmr, {
|
|
difficulte: -9,
|
|
action: 'Conquérir la cité',
|
|
onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
|
|
onConqueteEchec: r => {
|
|
this.souffleSiEchecTotal(rollData);
|
|
this.close()
|
|
},
|
|
canClose: false
|
|
});
|
|
}
|
|
}
|
|
/* -------------------------------------------- */
|
|
async purifierPeriple(tmr) {
|
|
if (EffetsDraconiques.periple.find(this.casesSpeciales, tmr.coord)) {
|
|
await this._conquerir(tmr, {
|
|
difficulte: EffetsDraconiques.periple.getDifficulte(tmr),
|
|
action: 'Purifier ' + TMRUtility.getTMRDescr(tmr.coord),
|
|
onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
|
|
onConqueteEchec: r => {
|
|
this.souffleSiEchecTotal(rollData);
|
|
this.close()
|
|
},
|
|
canClose: false
|
|
});
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async conquerirTMR(tmr) {
|
|
if (EffetsDraconiques.conquete.find(this.casesSpeciales, tmr.coord)) {
|
|
await this._conquerir(tmr, {
|
|
difficulte: -7,
|
|
action: 'Conquérir',
|
|
onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
|
|
onConqueteEchec: r => this.close(),
|
|
canClose: false
|
|
});
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async _conquerir(tmr, options) {
|
|
let rollData = {
|
|
actor: this.actor,
|
|
competence: duplicate(this.actor.getBestDraconic()),
|
|
tmr: tmr,
|
|
canClose: options.canClose ?? false,
|
|
diffLibre: options.difficulte ?? -7,
|
|
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
|
|
maitrise: { verbe: 'conquérir', action: options.action }
|
|
};
|
|
rollData.competence.system.defaut_carac = 'reve-actuel';
|
|
|
|
await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options));
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async _onResultatConquerir(rollData, options) {
|
|
if (rollData.rolled.isETotal) {
|
|
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
|
}
|
|
rollData.poesie = await Poetique.getExtrait();
|
|
ChatMessage.create({
|
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
|
|
});
|
|
if (rollData.rolled.isEchec) {
|
|
options.onConqueteEchec(rollData, options.effetDraconique);
|
|
}
|
|
else {
|
|
await options.onConqueteReussie(rollData, options.effetDraconique);
|
|
this.updateTokens();
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async _maitriserTMR(rollData, callbackMaitrise) {
|
|
rollData.isTMRCache = rollData.actor.isTMRCache();
|
|
const dialog = await RdDRoll.create(this.actor, rollData,
|
|
{
|
|
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
|
|
},
|
|
{
|
|
name: rollData.maitrise.verbe, label: rollData.maitrise.action,
|
|
callbacks: [
|
|
this.actor.createCallbackExperience(),
|
|
{ action: r => { this.restoreTMRAfterAction() } },
|
|
{ action: callbackMaitrise }
|
|
]
|
|
}
|
|
);
|
|
dialog.render(true);
|
|
this.setTMRPendingAction(dialog);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async validerVisite(tmr) {
|
|
await EffetsDraconiques.pelerinage.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
|
|
await EffetsDraconiques.urgenceDraconique.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
|
|
}
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
async declencheSortEnReserve(coord) {
|
|
const sorts = this.getSortsReserve(coord);
|
|
if (sorts.length > 0) {
|
|
if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
|
|
ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
|
|
return;
|
|
}
|
|
const reserveSecurite = EffetsDraconiques.isReserveEnSecurite(this.actor);
|
|
const reserveExtensible = this.isReserveExtensible(coord);
|
|
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) && (reserveSecurite || reserveExtensible)) {
|
|
const msg = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-demande-declencher-sort.hbs`, {
|
|
actor: this.actor,
|
|
sorts: sorts,
|
|
coord: coord,
|
|
tete: { reserveSecurite: reserveSecurite, reserveExtensible: reserveExtensible }
|
|
})
|
|
ChatMessage.create({
|
|
content: msg,
|
|
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
|
});
|
|
return;
|
|
}
|
|
await this.processSortReserve(sorts[0]);
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
lancerSortEnReserve(coord, sortId) {
|
|
let sorts = this.getSortsReserve(coord);
|
|
let sort = sorts.find(it => it.id == sortId);
|
|
if (sort) {
|
|
this.processSortReserve(sort);
|
|
} else {
|
|
ChatMessage.create({
|
|
content:
|
|
"Une erreur est survenue : impossible de récupérer le sort en réserve demandé.",
|
|
whisper: ChatMessage.getWhisperRecipients(game.user.name),
|
|
});
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async processSortReserve(sortReserve) {
|
|
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
|
|
console.log("declencheSortEnReserve", sortReserve);
|
|
const heureCible = RdDTimestamp.definition(sortReserve.system.heurecible).label;
|
|
this._tellToUserAndGM(`Vous avez déclenché
|
|
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"}
|
|
en réserve <strong>${sortReserve.name}</strong>
|
|
avec ${sortReserve.system.ptreve} points de Rêve
|
|
en ${sortReserve.system.coord} (${TMRUtility.getTMRLabel(sortReserve.system.coord)}).
|
|
L'heure ciblée est ${heureCible}`);
|
|
this.close();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
nettoyerRencontre() {
|
|
// Suppression des dessins des zones possibles
|
|
this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic))
|
|
// Nettoyage de la structureet de l'état
|
|
this.currentRencontre = undefined;
|
|
this.rencontreState = 'aucune';
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
isCaseInondee(coord) {
|
|
return EffetsDraconiques.debordement.find(this.casesSpeciales, coord);
|
|
}
|
|
|
|
isCiteFermee(coord) {
|
|
return EffetsDraconiques.fermetureCites.find(this.casesSpeciales, coord);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
isTerreAttache(coord) {
|
|
return EffetsDraconiques.terreAttache.find(this.casesSpeciales, coord);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
isCaseMaitrisee(coord) {
|
|
return EffetsDraconiques.queteEaux.find(this.casesSpeciales, coord);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
isReserveExtensible(coord) {
|
|
return EffetsDraconiques.reserveExtensible.find(this.casesSpeciales, coord);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
isConnaissanceFleuve(tmrApp, nextTMR) {
|
|
return TMRUtility.getTMR(tmrApp).type == 'fleuve' &&
|
|
TMRUtility.getTMR(nextTMR).type == 'fleuve' &&
|
|
EffetsDraconiques.isConnaissanceFleuve(this.actor);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async onClickTMR(event) {
|
|
if (this.viewOnly) {
|
|
return;
|
|
}
|
|
if (this.subdialog) {
|
|
return this.forceTMRContinueAction()
|
|
}
|
|
const currentCoord = this._getCoordActor()
|
|
const currentOddq = TMRUtility.coordTMRToOddq(currentCoord)
|
|
const targetOddq = this.pixiTMR.computeEventOddq(event)
|
|
const targetCoord = TMRUtility.oddqToCoordTMR(targetOddq)
|
|
|
|
// Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter)
|
|
const typeDeplacement = this._calculDeplacement(targetCoord, currentCoord, currentOddq, targetOddq);
|
|
|
|
if (this.isDemiReveCache()) {
|
|
if (this.isTerreAttache(targetCoord)
|
|
|| this.isConnaissanceFleuve(currentCoord, targetCoord)
|
|
|| typeDeplacement == 'changeur') {
|
|
// déplacement possible
|
|
await this.actor.setTMRVisible(true);
|
|
this.demiReve = this._tokenDemiReve();
|
|
this._trackToken(this.demiReve);
|
|
}
|
|
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.
|
|
`);
|
|
return;
|
|
}
|
|
}
|
|
|
|
switch (typeDeplacement) {
|
|
case 'normal':
|
|
case 'changeur':
|
|
case 'passeur':
|
|
await this._deplacerDemiReve(targetCoord, typeDeplacement);
|
|
break;
|
|
case 'messager':
|
|
await this._messagerDemiReve(targetCoord);
|
|
break;
|
|
default:
|
|
ui.notifications.error("Vous ne pouvez 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();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_calculDeplacement(targetCoord, currentCoord, fromOddq, toOddq) {
|
|
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) {
|
|
/*
|
|
TODO:
|
|
Si la case a un sort en réserve, lancer ce sort.
|
|
Si la case est le demi-rêve, ne pas lancer de sort.
|
|
Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre
|
|
si on essaie de lancer un sort (ou bloquer le lancer de sort)
|
|
*/
|
|
this.notifierResonanceSigneDraconique(targetCoord);
|
|
await this.actor.rollUnSort(targetCoord);
|
|
this.nettoyerRencontre();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
externalRefresh() {
|
|
this.createPixiSprites();
|
|
this.updateValuesDisplay();
|
|
this.updateTokens();
|
|
console.log("TMR REFRESHED !!!");
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async _deplacerDemiReve(targetCoord, deplacementType) {
|
|
if (this.subdialog) {
|
|
return this.forceTMRContinueAction()
|
|
}
|
|
if (this.currentRencontre != 'normal') {
|
|
this.nettoyerRencontre();
|
|
}
|
|
let tmr = TMRUtility.getTMR(targetCoord);
|
|
// Gestion cases spéciales type Trou noir, etc
|
|
tmr = await this.manageTmrInnaccessible(tmr);
|
|
|
|
await this.actor.updateCoordTMR(tmr.coord);
|
|
|
|
this.forceDemiRevePositionView();
|
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
|
this.cumulFatigue += this.fatigueParCase;
|
|
}
|
|
this.updateValuesDisplay();
|
|
this.actor.notifyRefreshTMR();
|
|
|
|
if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/...
|
|
await this.manageRencontre(tmr);
|
|
}
|
|
else {
|
|
await this.postRencontre(tmr);
|
|
}
|
|
}
|
|
|
|
async notifierResonanceSigneDraconique(coord) {
|
|
if (!this.viewOnly && this.actor.isResonanceSigneDraconique(coord)) {
|
|
ChatMessage.create({
|
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-resonance.html`, { alias: this.actor.name, typeTMR: TMRUtility.getTMRType(coord) })
|
|
});
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async postRencontre(tmr) {
|
|
if (!(this.viewOnly || this.currentRencontre)) {
|
|
// TODO: vérifier que la méthode s'arrête en cas de non-maîtrise
|
|
if (!this.descenteTMR) await this.manageCaseHumide(tmr);
|
|
if (!this.descenteTMR) await this.conquerirCiteFermee(tmr);
|
|
if (!this.descenteTMR) await this.purifierPeriple(tmr);
|
|
if (!this.descenteTMR) await this.conquerirTMR(tmr);
|
|
if (!this.descenteTMR) await this.validerVisite(tmr);
|
|
if (!this.descenteTMR) await this.declencheSortEnReserve(tmr.coord);
|
|
if (!this.descenteTMR) await this.actor.checkSoufflePeage(tmr);
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async positionnerDemiReve(coord) {
|
|
if (this.subdialog) {
|
|
return this.forceTMRContinueAction()
|
|
}
|
|
|
|
await this.actor.updateCoordTMR(coord);
|
|
this.forceDemiRevePositionView();
|
|
let tmr = TMRUtility.getTMR(coord);
|
|
await this.postRencontre(tmr);
|
|
return tmr;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_removeTokens(filter = it => true) {
|
|
this.allTokens.filter(filter).forEach(token => this.pixiTMR.removeToken(token))
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_trackToken(token) {
|
|
if (!token) {
|
|
return
|
|
}
|
|
if (this.demiReve === token && this.isDemiReveCache()) {
|
|
return;
|
|
}
|
|
this.pixiTMR.positionToken(token);
|
|
if (!this.allTokens.includes(token)) {
|
|
this.allTokens.push(token);
|
|
}
|
|
}
|
|
}
|