foundryvtt-reve-de-dragon/module/rdd-tmr-dialog.js

828 lines
30 KiB
JavaScript
Raw Normal View History

import { RollDataAjustements } from "./rolldata-ajustements.js";
2020-07-06 09:03:21 +02:00
import { RdDUtility } from "./rdd-utility.js";
import { TMRUtility, tmrConstants } from "./tmr-utility.js";
2020-11-12 16:35:51 +01:00
import { RdDResolutionTable } from "./rdd-resolution-table.js";
2020-11-29 18:21:34 +01:00
import { RdDTMRRencontreDialog } from "./rdd-tmr-rencontre-dialog.js";
import { TMRRencontres } from "./tmr-rencontres.js";
import { ChatUtility } from "./chat-utility.js";
import { RdDRoll } from "./rdd-roll.js";
2021-02-06 23:58:15 +01:00
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";
2020-11-18 23:49:05 +01:00
/* -------------------------------------------- */
2020-07-05 21:45:25 +02:00
export class RdDTMRDialog extends Dialog {
static async create(html, actor, tmrData) {
if (tmrData.mode != 'visu') {
// Notification au MJ
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",
2020-07-05 21:45:25 +02:00
content: html,
buttons: {
closeButton: { label: "Fermer", callback: html => this.close(html) }
},
default: "closeButton"
}
const dialogOptions = {
classes: ["tmrdialog"],
width: 920, height: 980,
'z-index': 20
}
2020-07-05 21:45:25 +02:00
super(dialogConf, dialogOptions);
this.tmrdata = duplicate(tmrData);
2020-07-14 22:19:29 +02:00
this.actor = actor;
2020-11-17 18:08:19 +01:00
this.actor.tmrApp = this; // reference this app in the actor structure
this.viewOnly = tmrData.mode == "visu"
2021-02-06 01:34:49 +01:00
this.fatigueParCase = this.viewOnly ? 0 : this.actor.getTMRFatigue();
this.cumulFatigue = 0;
this.loadRencontres();
this.loadSortsReserve();
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item));
2020-11-17 18:08:19 +01:00
this.allTokens = [];
2020-11-20 13:46:43 +01:00
this.rencontreState = 'aucune';
this.pixiApp = new PIXI.Application({ width: 720, height: 860 });
this.pixiTMR = new PixiTMR(this, this.pixiApp);
this.callbacksOnAnimate = [];
if (!this.viewOnly) {
this.actor.setStatusDemiReve(true);
this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
}
// load the texture we need
this.pixiTMR.load((loader, resources) => this.createPixiSprites());
}
loadSortsReserve() {
this.sortsReserves = duplicate(this.actor.data.data.reve.reserve.list);
}
loadRencontres() {
this.rencontresExistantes = duplicate(this.actor.getTMRRencontres()).list;
2020-07-14 22:19:29 +02:00
}
/* -------------------------------------------- */
createPixiSprites() {
EffetsDraconiques.carteTmr._createSprite(this.pixiTMR);
this.updateTokens();
this.demiReve = this._tokenDemiReve();
this._updateDemiReve();
2020-07-25 10:29:28 +02:00
}
/* -------------------------------------------- */
_createTokens() {
let tokens = this._getTokensCasesTmr()
.concat(this._getTokensRencontres())
.concat(this._getTokensSortsReserve());
for (let t of tokens) {
this._trackToken(t);
2020-07-26 18:44:03 +02:00
}
}
updateTokens() {
this._removeTokens(t => true);
this.loadRencontres();
this.loadSortsReserve();
this._createTokens();
}
/* -------------------------------------------- */
_getTokensCasesTmr() {
return this.casesSpeciales.map(c => this._tokenCaseSpeciale(c)).filter(token => token);
}
_getTokensRencontres() {
return this.rencontresExistantes.map(it => this._tokenRencontre(it));
}
_getTokensSortsReserve() {
return this.sortsReserves.map(it => this._tokenSortEnReserve(it));
}
/* -------------------------------------------- */
_tokenRencontre(rencontre) {
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
}
_tokenCaseSpeciale(caseSpeciale) {
const draconique = Draconique.get(caseSpeciale.data.specific);
return draconique?.token(this.pixiTMR, caseSpeciale, () => caseSpeciale.data.coord);
}
_tokenSortEnReserve(sortEnReserve) {
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord);
}
_tokenDemiReve() {
return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => this.actor.data.data.reve.tmrpos.coord);
}
_updateDemiReve() {
this._setTokenPosition(this.demiReve);
}
/* -------------------------------------------- */
async activateListeners(html) {
super.activateListeners(html);
document.getElementById("tmrrow1").insertCell(1).append(this.pixiApp.view);
if (this.viewOnly) {
html.find('#lancer-sort').remove();
2020-07-21 23:51:24 +02:00
}
else {
// Roll Sort
html.find('#lancer-sort').click((event) => {
this.actor.rollUnSort(this.actor.data.data.reve.tmrpos.coord);
});
}
if (this.viewOnly) {
return;
}
// Gestion du cout de montée en points de rêve
let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1)
- this.actor.countMonteeLaborieuse();
this.cumulFatigue += this.fatigueParCase;
await this.actor.reveActuelIncDec(reveCout);
// Le reste...
this.updateValuesDisplay();
let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord);
await this.manageRencontre(tmr, () => {
this.postRencontre(tmr);
this.actor.displayTMRQueueSouffleInformation();
});
2020-07-21 23:51:24 +02:00
}
/* -------------------------------------------- */
updateValuesDisplay() {
let ptsreve = document.getElementById("tmr-pointsreve-value");
ptsreve.innerHTML = this.actor.data.data.reve.reve.value;
let tmrpos = document.getElementById("tmr-pos");
let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord);
tmrpos.innerHTML = this.actor.data.data.reve.tmrpos.coord + " (" + tmr.label + ")";
let etat = document.getElementById("tmr-etatgeneral-value");
etat.innerHTML = this.actor.getEtatGeneral();
let refoulement = document.getElementById("tmr-refoulement-value");
refoulement.innerHTML = this.actor.data.data.reve.refoulement.value;
let fatigueItem = document.getElementById("tmr-fatigue-table");
//console.log("Refresh : ", this.actor.data.data.sante.fatigue.value);
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.data.data.sante.fatigue.value, this.actor.data.data.sante.endurance.max).html() + "</table>";
2020-07-21 23:51:24 +02:00
}
2020-07-26 18:44:03 +02:00
/* -------------------------------------------- */
close() {
this.actor.santeIncDec("fatigue", this.cumulFatigue).then(super.close()); // moving 1 cell costs 1 fatigue
this.actor.tmrApp = undefined; // Cleanup reference
this.actor.setStatusDemiReve(false);
if (!this.viewOnly) {
this._tellToGM(this.actor.name + " a quitté les terres médianes");
}
2020-07-26 18:44:03 +02:00
}
/* -------------------------------------------- */
2020-07-17 22:04:35 +02:00
async derober() {
await this.actor.addTMRRencontre(this.currentRencontre);
2020-07-17 22:04:35 +02:00
console.log("-> derober", this.currentRencontre);
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR.");
2020-07-21 23:51:24 +02:00
this.close();
2020-07-14 22:19:29 +02:00
}
/* -------------------------------------------- */
async refouler() {
this._tellToGM(this.actor.name + " a refoulé : " + this.currentRencontre.name);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
await this.actor.ajouterRefoulement(this.currentRencontre.refoulement ?? 1);
this.updateTokens();
2020-07-14 22:19:29 +02:00
console.log("-> refouler", this.currentRencontre)
2020-07-17 22:04:35 +02:00
this.updateValuesDisplay();
2020-11-20 13:46:43 +01:00
this.nettoyerRencontre();
2020-07-14 22:19:29 +02:00
}
2020-11-20 12:06:54 +01:00
/* -------------------------------------------- */
async ignorerRencontre() {
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();
}
/* -------------------------------------------- */
colorierZoneRencontre(locList) {
2020-11-20 12:06:54 +01:00
this.currentRencontre.graphics = []; // Keep track of rectangles to delete it
this.currentRencontre.locList = duplicate(locList); // And track of allowed location
for (let loc of locList) {
let rect = this._getCaseRectangleCoord(loc);
2020-11-20 12:06:54 +01:00
var rectDraw = new PIXI.Graphics();
rectDraw.beginFill(0xFFFF00, 0.3);
// set the line style to have a width of 5 and set the color to red
rectDraw.lineStyle(5, 0xFF0000);
// draw a rectangle
rectDraw.drawRect(rect.x, rect.y, rect.w, rect.h);
this.pixiApp.stage.addChild(rectDraw);
this.currentRencontre.graphics.push(rectDraw); // garder les objets pour gestion post-click
}
}
2020-11-21 14:30:00 +01:00
/* -------------------------------------------- */
// garder la trace de l'état en cours
setStateRencontre(state) {
this.rencontreState = state;
2020-11-21 14:30:00 +01:00
}
async choisirCasePortee(coord, portee) {
// Récupère la liste des cases à portées
let locList = TMRUtility.getTMRPortee(coord, portee);
this.colorierZoneRencontre(locList);
}
2020-11-21 08:27:28 +01:00
async choisirCaseType(type) {
const locList = TMRUtility.filterTMR(it => it.type == type).map(it => it.coord);
this.colorierZoneRencontre(locList);
2020-11-21 08:27:28 +01:00
}
2020-11-21 08:27:28 +01:00
/* -------------------------------------------- */
2020-11-21 23:24:00 +01:00
checkQuitterTMR() {
if (this.actor.isDead()) {
this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !");
2020-11-21 08:27:28 +01:00
this.close();
return true;
2020-11-21 08:27:28 +01:00
}
2021-02-06 01:34:49 +01:00
const resteAvantInconscience = this.actor.getFatigueMax() - this.actor.getFatigueActuelle() - this.cumulFatigue;
if (resteAvantInconscience <= 0) {
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
this.quitterLesTMRInconscient();
return true;
2020-11-21 08:27:28 +01:00
}
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() {
if (this.currentRencontre?.isPersistant) {
await this.refouler();
2020-11-21 08:27:28 +01:00
}
this.close();
2020-11-20 12:06:54 +01:00
}
/* -------------------------------------------- */
async maitriserRencontre() {
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,
tmr: TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord)
}
await this._tentativeMaitrise(rencontreData);
}
/* -------------------------------------------- */
async _tentativeMaitrise(rencontreData) {
console.log("-> matriser", rencontreData);
rencontreData.reve = this.actor.getReveActuel();
rencontreData.etat = this.actor.getEtatGeneral();
2020-11-20 12:06:54 +01:00
RollDataAjustements.calcul(rencontreData, this.actor);
rencontreData.rolled = await RdDResolutionTable.roll(rencontreData.reve, RollDataAjustements.sum(rencontreData.ajustements));
let postProcess = await TMRRencontres.gererRencontre(this, rencontreData);
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencontreData)
});
if (postProcess) {
/** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */
await postProcess(this, rencontreData);
}
else {
this.currentRencontre = undefined;
}
2020-11-20 12:06:54 +01:00
2020-07-17 22:04:35 +02:00
this.updateValuesDisplay();
if (this.checkQuitterTMR()) {
return;
}
else if (rencontreData.rolled.isEchec && rencontreData.rencontre.isPersistant) {
setTimeout(() => {
rencontreData.nbRounds++;
2021-02-06 01:34:49 +01:00
this.cumulFatigue += this.fatigueParCase;
this._tentativeMaitrise(rencontreData);
this._deleteTmrMessages(rencontreData.actor, rencontreData.nbRounds);
}, 2000);
}
}
/* -------------------------------------------- */
_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);
2020-07-14 22:19:29 +02:00
}
2020-11-12 23:35:29 +01:00
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
_tellToUser(message) {
ChatMessage.create({ content: message, user: game.user._id, whisper: [game.user._id] });
}
2020-11-18 23:49:05 +01:00
/* -------------------------------------------- */
_tellToGM(message) {
ChatMessage.create({ content: message, user: game.user._id, whisper: ChatMessage.getWhisperRecipients("GM") });
2020-11-18 23:49:05 +01:00
}
/* -------------------------------------------- */
async manageRencontre(tmr, postRencontre) {
2020-11-14 20:46:39 +01:00
if (this.viewOnly) {
return;
}
this.currentRencontre = undefined;
let rencontre = await this._jetDeRencontre(tmr);
2020-07-14 22:19:29 +02:00
if (rencontre) { // Manages it
2020-11-18 18:11:01 +01:00
if (rencontre.rencontre) rencontre = rencontre.rencontre; // Manage stored rencontres
console.log("manageRencontre", rencontre);
2020-07-21 23:51:24 +02:00
this.currentRencontre = duplicate(rencontre);
2020-11-16 04:01:36 +01:00
let dialog = new RdDTMRRencontreDialog("", this, this.currentRencontre, postRencontre);
2020-11-12 23:35:29 +01:00
dialog.render(true);
2020-07-14 22:19:29 +02:00
}
2021-02-06 02:29:58 +01:00
else {
postRencontre();
}
2020-07-14 22:19:29 +02:00
}
/* -------------------------------------------- */
async _jetDeRencontre(tmr) {
let rencontre = this.rencontresExistantes.find(prev => prev.coord == tmr.coord);
if (rencontre) {
return rencontre;
}
// TODO: dialog pour remplacer la rencontre par un présent
//if (this.casesSpeciales.find(c => EffetsDraconiques.isPresentCite(c, tmr.coord))) {
let myRoll = new Roll("1d7").evaluate().total;
if (TMRUtility.isForceRencontre() || myRoll == 7) {
return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
}
this._tellToUser(myRoll + ": Pas de rencontre en " + tmr.label + " (" + tmr.coord + ")");
}
/* -------------------------------------------- */
async rencontreTMRRoll(tmr, isMauvaise = false) {
let rencontre = TMRUtility.utiliseForceRencontre() ??
(isMauvaise
? await TMRRencontres.getMauvaiseRencontre()
: await TMRRencontres.getRencontreAleatoire(tmr.type));
rencontre.coord = tmr.coord;
rencontre.date = game.system.rdd.calendrier.getDateFromIndex();
rencontre.heure = game.system.rdd.calendrier.getCurrentHeure();
return rencontre;
}
/* -------------------------------------------- */
async manageCaseSpeciale(tmr) {
if (this.casesSpeciales.find(c => EffetsDraconiques.isCaseTrouNoir(c, tmr.coord))) {
let newTMR = TMRUtility.getTMRAleatoire();
let tmrPos = duplicate(this.actor.data.data.reve.tmrpos);
tmrPos.coord = newTMR.coord;
await this.actor.update({ "data.reve.tmrpos": tmrPos });
ChatMessage.create({
content: "Vous êtes rentré sur un Trou Noir : ré-insertion aléatoire.",
whisper: ChatMessage.getWhisperRecipients(game.user.name)
});
}
}
2020-11-12 16:35:51 +01:00
/* -------------------------------------------- */
async manageCaseHumide(tmr) {
if (this.viewOnly || this.currentRencontre) {
2020-11-14 20:46:39 +01:00
return;
}
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' }
2020-11-12 16:35:51 +01:00
}
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true: undefined,
2021-02-06 23:58:15 +01:00
rollData.competence.data.defaut_carac = 'reve-actuel';
await this._rollMaitriseCaseHumide(rollData);
2020-07-17 22:04:35 +02:00
}
}
/* -------------------------------------------- */
async _rollMaitriseCaseHumide(rollData) {
await this._maitriserTMR(rollData, r => this._resultatMaitriseCaseHumide(r));
}
async _resultatMaitriseCaseHumide(rollData) {
if (rollData.rolled.isETotal) {
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
}
this.toclose = rollData.rolled.isEchec;
if (rollData.rolled.isSuccess && rollData.double) {
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
rollData.double = undefined;
await this._rollMaitriseCaseHumide(rollData);
return;
}
rollData.poesie = 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) {
this.close();
}
}
/* -------------------------------------------- */
isCaseHumide(tmr) {
if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) {
return undefined;
}
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 undefined;
}
return -7;
}
/* -------------------------------------------- */
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 (this.viewOnly || this.currentRencontre) {
return;
}
const citeFermee = this.isCiteFermee(tmr.coord);
if (citeFermee) {
let rollData = {
actor: this.actor,
competence: duplicate(this.actor.getBestDraconic()),
tmr: tmr,
canClose: false,
diffLibre: -9,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
maitrise: { verbe: 'conquérir', action: 'Conquérir la cité' }
}
rollData.competence.data.defaut_carac = 'reve-actuel';
await this._maitriserTMR(rollData, r => this._resultatConqueteCiteFermee(r));
}
}
async _resultatConqueteCiteFermee(rollData) {
if (rollData.rolled.isETotal) {
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
}
this.toclose = rollData.rolled.isEchec;
2021-02-06 23:58:15 +01:00
rollData.poesie = Poetique.getExtrait();
ChatMessage.create({
2021-02-06 23:58:15 +01:00
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) {
this.close();
}
else {
const citeFermee = this.actor.data.items.find(it => EffetsDraconiques.isCiteFermee(it, rollData.tmr.coord));
this.actor.deleteOwnedItem(citeFermee._id);
this._removeTokens(t => t.coordTMR() == citeFermee.data.coord && t.caseSpeciale?._id == citeFermee._id);
}
}
/* -------------------------------------------- */
async _maitriserTMR(rollData, callbackMaitrise) {
this.minimize(); // Hide
const dialog = await RdDRoll.create(this.actor, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
options: { height: 350 },
close: html => { this.maximize(); } // Re-display TMR
},
{
name: rollData.maitrise.verbe, label: rollData.maitrise.action,
callbacks: [
this.actor.createCallbackExperience(),
{ action: callbackMaitrise }
]
}
);
dialog.render(true);
}
/* -------------------------------------------- */
async declencheSortEnReserve(coordTMR) {
2020-11-14 20:46:39 +01:00
if (this.viewOnly) {
return;
}
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR);
if (sortReserveList.length > 0) {
if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coordTMR)) {
let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête <strong>Reserve en Sécurité</strong> ou <strong>Réserve Exensible</strong>, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher : <ul>";
for (let sortReserve of sortReserveList) {
msg += "<li><a class='chat-card-button' id='sort-reserve' data-actor-id='" + this.actor._id + "' data-tmr-coord='" + coordTMR + "' data-sort-id='" + sortReserve.sort._id + "'>" + sortReserve.sort.name + "</a></li>";
}
msg += "</ol>";
ChatMessage.create({
content: msg,
whisper: ChatMessage.getWhisperRecipients(game.user.name)
});
} else {
await this.processSortReserve(sortReserveList[0]);
}
}
}
/* -------------------------------------------- */
lancerSortEnReserve(coord, sortId) {
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord);
let sortReserve = sortReserveList.find(sortReserve => sortReserve.sort._id == sortId);
//console.log("SORT RESA", sortReserveList, coordTMR, sortId, sortReserve);
if (sortReserve) {
this.processSortReserve(sortReserve);
} 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)
});
2020-07-26 18:44:03 +02:00
}
}
/* -------------------------------------------- */
async processSortReserve(sortReserve) {
await this.actor.deleteSortReserve(sortReserve);
this.updateSortReserve();
console.log("declencheSortEnReserve", sortReserve)
this._tellToGM(`Vous avez déclenché le sort en réserve <strong> ${sortReserve.sort.name}</strong>
avec ${sortReserve.sort.data.ptreve_reel} points de Rêve
en ${sortReserve.coord} (${TMRUtility.getTMRLabel(sortReserve.coord)})
`);
this.close();
}
2020-11-20 13:46:43 +01:00
/* -------------------------------------------- */
nettoyerRencontre() {
if (!this.currentRencontre) return; // Sanity check
if (this.currentRencontre.graphics) {
2020-11-20 13:46:43 +01:00
for (let drawRect of this.currentRencontre.graphics) { // Suppression des dessins des zones possibles
this.pixiApp.stage.removeChild(drawRect);
2020-11-20 13:46:43 +01:00
}
}
this.currentRencontre = undefined; // Nettoyage de la structure
this.rencontreState = 'aucune'; // Et de l'état
}
2020-11-20 12:06:54 +01:00
/* -------------------------------------------- */
processClickPostRencontre(coord) {
2020-11-21 08:27:28 +01:00
if (this.rencontreState == 'passeur' || this.rencontreState == 'messager' || this.rencontreState == 'changeur') {
2020-11-20 13:46:43 +01:00
console.log("Searching", this.currentRencontre.locList, coord);
let isInArea = this.currentRencontre.locList.find(locCoord => locCoord == coord);
if (isInArea) { // OK !
return (this.rencontreState == 'messager') ? 'messager' : 'saut';
}
}
return "erreur";
2020-11-20 12:06:54 +01:00
}
/* -------------------------------------------- */
isCaseInondee(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isCaseInondee(c, coord));
}
isCiteFermee(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isCiteFermee(c, coord));
}
/* -------------------------------------------- */
isTerreAttache(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isTerreAttache(c, coord));
}
/* -------------------------------------------- */
isCaseMaitrisee(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isCaseMaitrisee(c, coord));
}
/* -------------------------------------------- */
isReserveExtensible(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isReserveExtensible(c, coord));
}
/* -------------------------------------------- */
isConnaissanceFleuve(currentTMR, nextTMR) {
return TMRUtility.getTMR(currentTMR).type == 'fleuve' &&
TMRUtility.getTMR(nextTMR).type == 'fleuve' &&
EffetsDraconiques.isConnaissanceFleuve(this.actor);
}
/* -------------------------------------------- */
async onClickTMR(event) {
2020-11-14 20:46:39 +01:00
if (this.viewOnly) {
return;
}
2020-11-21 23:24:00 +01:00
2020-07-14 22:19:29 +02:00
let origEvent = event.data.originalEvent;
let tmrObject = this;
let eventPos = RdDTMRDialog._computeEventPos(origEvent);
await tmrObject._onClickTMRPos(eventPos); // Vérifier l'état des compteurs reve/fatigue/vie
}
async _onClickTMRPos(eventPos) {
let currentPos = TMRUtility.convertToCellPos(this.actor.data.data.reve.tmrpos.coord);
console.log("deplacerDemiReve >>>>", currentPos, eventPos);
let targetCoord = TMRUtility.convertToTMRCoord(eventPos);
let currentCoord = TMRUtility.convertToTMRCoord(currentPos);
2020-11-20 12:06:54 +01:00
// Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter)
let deplacementType = this._calculDeplacement(targetCoord, currentCoord, currentPos, eventPos);
2020-11-20 12:06:54 +01:00
// Si le deplacement est valide
if (deplacementType == 'normal' || deplacementType == 'saut') {
await this._deplacerDemiReve(targetCoord, deplacementType);
2020-11-20 13:46:43 +01:00
} else if (deplacementType == 'messager') { // Dans ce cas, ouverture du lancement de sort sur la case visée
await this._messagerDemiReve(targetCoord);
2020-11-20 12:06:54 +01:00
} else {
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();
}
async _messagerDemiReve(targetCoordTMR) {
await this.actor.rollUnSort(targetCoordTMR);
this.nettoyerRencontre();
}
async _deplacerDemiReve(targetCoord, deplacementType) {
if (this.currentRencontre != 'normal') {
this.nettoyerRencontre();
}
let tmr = TMRUtility.getTMR(targetCoord);
await this.manageCaseSpeciale(tmr); // Gestion cases spéciales type Trou noir, etc
console.log("deplacerDemiReve: TMR is", tmr, this);
let tmrPos = duplicate(this.actor.data.data.reve.tmrpos);
tmrPos.coord = targetCoord;
await this.actor.update({ "data.reve.tmrpos": tmrPos });
this._updateDemiReve();
2021-02-06 01:34:49 +01:00
this.cumulFatigue += this.fatigueParCase;
this.updateValuesDisplay();
game.socket.emit("system.foundryvtt-reve-de-dragon", {
msg: "msg_tmr_move", data: {
actorId: this.actor.data._id,
tmrPos: this.actor.data.data.reve.tmrpos
}
});
if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/...
await this.manageRencontre(tmr, () => this.postRencontre(tmr));
2020-07-14 22:19:29 +02:00
}
else {
await this.postRencontre(tmr);
}
}
2020-11-21 08:27:28 +01:00
async postRencontre(tmr) {
await this.manageCaseHumide(tmr);
await this.conquerirCiteFermee(tmr);
await this.declencheSortEnReserve(tmr.coord);
await this.actor.checkSoufflePeage(tmr);
2020-07-05 22:35:18 +02:00
}
/* -------------------------------------------- */
async forceDemiRevePositionView(coordTMR) {
this._updateDemiReve();
}
2020-11-17 18:08:19 +01:00
/* -------------------------------------------- */
async forceDemiRevePosition(coordTMR) {
2020-11-18 18:11:01 +01:00
await this.actor.updateCoordTMR(coordTMR);
this._updateDemiReve();
let tmr = TMRUtility.getTMR(coordTMR);
await this.manageCaseHumide(tmr);
await this.conquerirCiteFermee(tmr);
await this.declencheSortEnReserve(tmr.coord);
2020-11-17 18:08:19 +01:00
}
/* -------------------------------------------- */
static _computeEventPos(origEvent) {
let canvasRect = origEvent.target.getBoundingClientRect();
let x = origEvent.clientX - canvasRect.left;
let y = origEvent.clientY - canvasRect.top;
let cellx = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12]
y -= (cellx % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
let celly = Math.floor(y / tmrConstants.cellh); // [From 0 -> 14]
return { x: cellx, y: celly };
}
2020-11-17 18:08:19 +01:00
/* -------------------------------------------- */
static _horsDePortee(origin, target) {
return Math.abs(target.x - origin.x) > 1
|| Math.abs(target.y - origin.y) > 1
|| (origin.y == 0 && target.y > origin.y && target.x != origin.x && origin.x % 2 == 0)
|| (target.y == 0 && target.y < origin.y && target.x != origin.x && origin.x % 2 == 1);
}
2020-11-17 18:08:19 +01:00
/* -------------------------------------------- */
2020-11-20 12:06:54 +01:00
/** Retourne les coordonnées x, h, w, h du rectangle d'une case donnée */
_getCaseRectangleCoord(coord) {
return this.pixiTMR.getCaseRectangle(TMRUtility.convertToCellPos(coord));
2020-11-20 12:06:54 +01:00
}
/* -------------------------------------------- */
_setTokenPosition(token) {
this.pixiTMR.setPosition(token.sprite, TMRUtility.convertToCellPos(token.coordTMR()));
}
2020-11-17 18:08:19 +01:00
/* -------------------------------------------- */
_removeTokens(filter) {
const tokensToRemove = this.allTokens.filter(filter);
for (let token of tokensToRemove) {
this.pixiApp.stage.removeChild(token.sprite);
}
}
2020-11-17 18:08:19 +01:00
/* -------------------------------------------- */
_trackToken(token) {
this.allTokens.push(token);
this._setTokenPosition(token);
2020-07-05 21:45:25 +02:00
}
}