Vincent Vandemeulebrouck
582df7e290
Les messages dans les TMRs sont envoyés au GM Simplification des messages de tchat liés à un actor: on peut utiliser les Owners (car les GMs sont owner). Au lieu de passer le name de l'Actor (qui peut être incorrect si deux actors ont le même, mais pas les mêmes propriétaires), on passe directement l'actor pour déterminer mles destinataires de messages
1152 lines
39 KiB
JavaScript
1152 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 { ITEM_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 initSettings() {
|
|
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: ChatUtility.getGMs() });
|
|
}
|
|
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 = foundry.utils.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 && !game.user.isGM) {
|
|
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.lancerUnSort());
|
|
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();
|
|
}
|
|
|
|
lancerUnSort() {
|
|
if (this.subdialog) {
|
|
return this.forceTMRContinueAction();
|
|
}
|
|
return this.actor.rollUnSort(this._getCoordActor());
|
|
}
|
|
|
|
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()
|
|
this.bringSubDialogToTop();
|
|
}
|
|
}
|
|
|
|
bringSubDialogToTop() {
|
|
if (this.subdialog?.bringToTop && this.subdialog?.element[0]) {
|
|
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');
|
|
this.bringSubDialogToTop();
|
|
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[ITEM_TYPES.sortreserve];
|
|
}
|
|
|
|
getSortsReserve(coord) {
|
|
return this.actor.itemTypes[ITEM_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.getRencontresTMR();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
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[ITEM_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.deleteRencontreTMRAtPosition()
|
|
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.deleteRencontreTMRAtPosition()
|
|
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 = foundry.utils.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.deleteRencontreTMRAtPosition()
|
|
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.getOwners(this.actor),
|
|
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({
|
|
user: game.user.id,
|
|
content: message,
|
|
whisper: ChatUtility.getGMs()
|
|
});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_tellToUserAndGM(message) {
|
|
ChatMessage.create({
|
|
user: game.user.id,
|
|
content: message,
|
|
whisper: ChatUtility.getUserAndGMs()
|
|
})
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
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: foundry.utils.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.getOwners(this.actor),
|
|
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: ChatUtility.getOwners(this.actor)
|
|
});
|
|
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: ChatUtility.getOwners(this.actor)
|
|
});
|
|
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: ChatUtility.getOwners(this.actor)
|
|
});
|
|
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: foundry.utils.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.getOwners(this.actor),
|
|
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)) {
|
|
ChatMessage.create({
|
|
content: 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 }
|
|
}),
|
|
whisper: ChatUtility.getOwners(this.actor)
|
|
})
|
|
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: ChatUtility.getOwners(this.actor)
|
|
});
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
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.getOwners(this.actor),
|
|
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);
|
|
}
|
|
}
|
|
}
|