Améliorations des tmr

* fermeture des cités
* utilisations d'icônes pour les cases spéciales, rencontres, sorts
en réserve
* séparation pixi/actions TMR / définition des cases spéciales

fixes divers:
* #153 lancer de sort si draconic utilise compétence autre que rêve
* #152: table de résolution doublée sur cht points de rêve
* /table n'affichait plus les résultats suite à chgt sur souffles/queues
This commit is contained in:
Vincent Vandemeulebrouck
2021-02-11 02:48:27 +01:00
parent d25e25e6fd
commit b226e5c09a
36 changed files with 1631 additions and 774 deletions

View File

@ -1,24 +1,31 @@
/**
* Extend the base Dialog entity by defining a custom window to perform spell.
* @extends {Dialog}
*/
import { RollDataAjustements } from "./rolldata-ajustements.js";
import { RdDUtility } from "./rdd-utility.js";
import { TMRUtility } from "./tmr-utility.js";
import { tmrConstants } from "./tmr-utility.js";
import { TMRUtility, tmrConstants } from "./tmr-utility.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
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";
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";
/* -------------------------------------------- */
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, mode) {
constructor(html, actor, tmrData) {
const dialogConf = {
title: "Terres Médianes de Rêve",
content: html,
@ -38,19 +45,145 @@ export class RdDTMRDialog extends Dialog {
this.tmrdata = duplicate(tmrData);
this.actor = actor;
this.actor.tmrApp = this; // reference this app in the actor structure
this.viewOnly = mode == "visu"
this.viewOnly = tmrData.mode == "visu"
this.fatigueParCase = this.viewOnly ? 0 : this.actor.getTMRFatigue();
this.cumulFatigue = 0;
this.rencontresExistantes = duplicate(this.actor.data.data.reve.rencontre.list);
this.sortReserves = duplicate(this.actor.data.data.reve.reserve.list);
this.casesSpeciales = this.actor.data.items.filter(item => item.type == 'casetmr');
this.loadRencontres();
this.loadSortsReserve();
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item));
this.allTokens = [];
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 (" + mode + ")");
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;
}
/* -------------------------------------------- */
createPixiSprites() {
EffetsDraconiques.carteTmr._createSprite(this.pixiTMR);
this.updateTokens();
this.demiReve = this._tokenDemiReve();
this._updateDemiReve();
}
/* -------------------------------------------- */
_createTokens() {
let tokens = this._getTokensCasesTmr()
.concat(this._getTokensRencontres())
.concat(this._getTokensSortsReserve());
for (let t of tokens) {
this._trackToken(t);
}
}
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();
}
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();
});
}
/* -------------------------------------------- */
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>";
}
/* -------------------------------------------- */
@ -63,51 +196,6 @@ export class RdDTMRDialog extends Dialog {
}
}
/* -------------------------------------------- */
displaySortReserve() {
console.debug("displaySortReserve", this.sortReserves);
for (let sort of this.sortReserves) {
this._trackToken(this._tokenSortEnReserve(sort));
}
}
/* -------------------------------------------- */
displaySpecificCase() {
for (let caseSpeciale of this.casesSpeciales) {
console.log("SPEC CASE ", caseSpeciale);
if (caseSpeciale.data.specific == 'trounoir') {
this._trackToken(this._tokenTrouNoir(caseSpeciale.data.coord));
} else if (caseSpeciale.data.specific == 'attache') {
this._trackToken(this._tokenTerreAttache(caseSpeciale.data.coord));
} else if (caseSpeciale.data.specific == 'debordement') {
this._trackToken(this._tokenDebordement(caseSpeciale.data.coord));
} else if (caseSpeciale.data.specific == 'maitrisee') {
this._trackToken(this._tokenMaitrisee(caseSpeciale.data.coord));
}
}
}
/* -------------------------------------------- */
displayPreviousRencontres() {
console.debug("displayPreviousRencontres", this.rencontresExistantes);
for (let rencontre of this.rencontresExistantes) {
this._trackToken(this._tokenRencontre(rencontre));
}
}
/* -------------------------------------------- */
updatePreviousRencontres() {
this._removeTokens(t => t.rencontre != undefined);
this.rencontresExistantes = duplicate(this.actor.data.data.reve.rencontre.list);
this.displayPreviousRencontres();
}
/* -------------------------------------------- */
updateSortReserve() {
this._removeTokens(t => t.sort != undefined);
this.sortReserves = duplicate(this.actor.data.data.reve.reserve.list);
this.displaySortReserve();
}
/* -------------------------------------------- */
async derober() {
@ -121,7 +209,7 @@ export class RdDTMRDialog extends Dialog {
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.updatePreviousRencontres();
this.updateTokens();
console.log("-> refouler", this.currentRencontre)
this.updateValuesDisplay();
this.nettoyerRencontre();
@ -131,7 +219,7 @@ export class RdDTMRDialog extends Dialog {
async ignorerRencontre() {
this._tellToGM(this.actor.name + " a ignoré : " + this.currentRencontre.name);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
this.updatePreviousRencontres();
this.updateTokens();
this.updateValuesDisplay();
this.nettoyerRencontre();
}
@ -166,7 +254,7 @@ export class RdDTMRDialog extends Dialog {
}
async choisirCaseType(type) {
const locList = TMRUtility.getListCoordTMR(type);
const locList = TMRUtility.filterTMR(it => it.type == type).map(it => it.coord);
this.colorierZoneRencontre(locList);
}
@ -200,9 +288,9 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
async maitriser() {
async maitriserRencontre() {
this.actor.deleteTMRRencontreAtPosition();
this.updatePreviousRencontres();
this.updateTokens();
let rencontreData = {
actor: this.actor,
@ -218,6 +306,7 @@ export class RdDTMRDialog extends Dialog {
await this._tentativeMaitrise(rencontreData);
}
/* -------------------------------------------- */
async _tentativeMaitrise(rencontreData) {
console.log("-> matriser", rencontreData);
@ -227,7 +316,6 @@ export class RdDTMRDialog extends Dialog {
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({
@ -257,6 +345,7 @@ export class RdDTMRDialog extends Dialog {
}
}
/* -------------------------------------------- */
_deleteTmrMessages(actor, nbRounds = -1) {
setTimeout(() => {
if (nbRounds < 0) {
@ -307,60 +396,41 @@ export class RdDTMRDialog extends Dialog {
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) {
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);
(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;
}
/* -------------------------------------------- */
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>";
}
/* -------------------------------------------- */
async manageCaseSpeciale(tmr) {
for (let caseTMR of this.casesSpeciales) {
if (caseTMR.data.coord == tmr.coord) { // Match !
if (caseTMR.data.specific == 'trounoir') {
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)
});
}
}
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)
});
}
}
@ -376,7 +446,8 @@ export class RdDTMRDialog extends Dialog {
tmr: tmr,
canClose: false,
diffLibre: -7,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } }
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
}
rollData.competence.data.defaut_carac = 'reve-actuel';
@ -384,80 +455,125 @@ export class RdDTMRDialog extends Dialog {
}
}
/* -------------------------------------------- */
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.previous && EffetsDraconiques.isDoubleResistanceFleuve(this.actor)) {
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
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 false;
return undefined;
}
if (this.actor.isCaseHumideAdditionelle(tmr)) {
return true;
}
return tmr.type == "lac" || tmr.type == "fleuve" || tmr.type == "marais";
return -7;
}
/* -------------------------------------------- */
isCaseMaitrisee(coordTMR) {
return this.casesSpeciales.find(it => it.data.coord = coordTMR && it.data.specific == 'maitrisee');
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 _rollMaitriseCaseHumide(rollData) {
this.minimize(); // Hide
const dialog = await RdDRoll.create(this.actor, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-tmr-humide.html',
options:{ height: 350 },
close: html => { this.maximize(); } // Re-display TMR
},
{
name: 'maitrise',
label: 'Maîtriser le fleuve',
callbacks: [
this.actor.createCallbackExperience(),
{ action: r => this._maitriseCaseHumide(r) }
]
/* -------------------------------------------- */
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é' }
}
);
dialog.render(true);
}
rollData.competence.data.defaut_carac = 'reve-actuel';
async _maitriseCaseHumide(rollData) {
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;
if (rollData.rolled.isSuccess) {
if (!rollData.previous && this.actor.isDoubleResistanceFleuve()) {
ChatMessage.create({
content: `Double résistance du fleuve: `,
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name)
});
rollData.previous = [rollData.rolled];
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-fleuve-tmr.html`, rollData)
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);
}
}
/* -------------------------------------------- */
isReserveExtensible(coordTMR) {
for (let caseTMR of this.casesSpeciales) {
if (caseTMR.data.specific == 'reserve_extensible' && caseTMR.data.coord == coordTMR)
return true;
}
return false;
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);
}
/* -------------------------------------------- */
@ -466,9 +582,9 @@ export class RdDTMRDialog extends Dialog {
return;
}
let sortReserveList = TMRUtility.getSortReserveList(this.sortReserves, coordTMR);
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR);
if (sortReserveList.length > 0) {
if (this.actor.isReserveEnSecurite() || this.isReserveExtensible(coordTMR)) {
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>";
@ -483,9 +599,10 @@ export class RdDTMRDialog extends Dialog {
}
}
}
/* -------------------------------------------- */
lancerSortEnReserve(coordTMR, sortId) {
let sortReserveList = TMRUtility.getSortReserveList(this.sortReserves, coordTMR);
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR);
let sortReserve = sortReserveList.find(sortReserve => sortReserve.sort._id == sortId);
//console.log("SORT RESA", sortReserveList, coordTMR, sortId, sortReserve);
if (sortReserve) {
@ -535,24 +652,34 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
isTerreAttache(coordTMR) {
for (let caseTMR of this.casesSpeciales) {
if (caseTMR.data.specific == 'attache' && caseTMR.data.coord == coordTMR) { // Match !
return true;
}
}
return false;
isCaseInondee(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isCaseInondee(c, coord));
}
isCiteFermee(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isCiteFermee(c, coord));
}
/* -------------------------------------------- */
checkConnaissanceFleuve(currentTMR, nextTMR) {
if (this.actor.isConnaissanceFleuve()) {
//console.log(currentTMR, nextTMR );
if (TMRUtility.getTMR(currentTMR).type == 'fleuve' && TMRUtility.getTMR(nextTMR).type == 'fleuve') {
return true;
}
}
return false;
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);
}
/* -------------------------------------------- */
@ -562,7 +689,7 @@ export class RdDTMRDialog extends Dialog {
}
let origEvent = event.data.originalEvent;
let tmrObject = event.target.tmrObject;
let tmrObject = this;
let eventPos = RdDTMRDialog._computeEventPos(origEvent);
await tmrObject._onClickTMRPos(eventPos); // Vérifier l'état des compteurs reve/fatigue/vie
@ -579,7 +706,7 @@ export class RdDTMRDialog extends Dialog {
// Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter)
let deplacementType = 'erreur';
if (this.rencontreState == 'aucune') { // Pas de recontre en post-processing, donc deplacement normal
if (!RdDTMRDialog._horsDePortee(currentPos, eventPos) || this.isTerreAttache(targetCoordTMR) || this.checkConnaissanceFleuve(currentCoordTMR, targetCoordTMR)) {
if (this.isTerreAttache(targetCoordTMR) || this.isConnaissanceFleuve(currentCoordTMR, targetCoordTMR) || !RdDTMRDialog._horsDePortee(currentPos, eventPos)) {
deplacementType = 'normal';
}
} else {
@ -644,6 +771,7 @@ export class RdDTMRDialog extends Dialog {
async postRencontre(tmr) {
await this.manageCaseHumide(tmr);
await this.conquerirCiteFermee(tmr);
await this.declencheSortEnReserve(tmr.coord);
await this.actor.checkSoufflePeage(tmr);
}
@ -658,76 +786,11 @@ export class RdDTMRDialog extends Dialog {
await this.actor.updateCoordTMR(coordTMR);
this._updateDemiReve();
let tmr = TMRUtility.getTMR(coordTMR);
this.manageCaseHumide(tmr);
await this.manageCaseHumide(tmr);
await this.conquerirCiteFermee(tmr);
await this.declencheSortEnReserve(tmr.coord);
}
/* -------------------------------------------- */
async activateListeners(html) {
super.activateListeners(html);
var row = document.getElementById("tmrrow1");
var cell1 = row.insertCell(1);
cell1.append(this.pixiApp.view);
if (this.viewOnly) {
html.find('#lancer-sort').remove();
}
else {
// Roll Sort
html.find('#lancer-sort').click((event) => {
this.actor.rollUnSort(this.actor.data.data.reve.tmrpos.coord);
});
}
// load the texture we need
await this.pixiApp.loader
.add('tmr', 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmp_main_r1.webp')
.add('demi-reve', "icons/svg/sun.svg")
.load((loader, resources) => {
// This creates a texture from a TMR image
const mytmr = new PIXI.Sprite(resources.tmr.texture);
// Setup the position of the TMR
mytmr.x = 0;
mytmr.y = 0;
mytmr.width = 720;
mytmr.height = 860;
// Rotate around the center
mytmr.anchor.x = 0;
mytmr.anchor.y = 0;
mytmr.interactive = true;
mytmr.buttonMode = true;
mytmr.tmrObject = this;
if (!this.viewOnly) {
mytmr.on('pointerdown', this.onClickTMR);
}
this.pixiApp.stage.addChild(mytmr);
this._addDemiReve();
this.displayPreviousRencontres();
this.displaySortReserve();
this.displaySpecificCase();
});
if (this.viewOnly) {
return;
}
// Gestion du cout de montée en points de rêve
let reveCout = (this.tmrdata.isRapide && !this.actor.checkTeteDeplacementAccelere()) ? -2 : -1;
this.cumulFatigue += this.fatigueParCase;
reveCout -= this.actor.checkMonteeLaborieuse();
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();
});
}
/* -------------------------------------------- */
static _computeEventPos(origEvent) {
let canvasRect = origEvent.target.getBoundingClientRect();
@ -747,125 +810,16 @@ export class RdDTMRDialog extends Dialog {
|| (target.y == 0 && target.y < origin.y && target.x != origin.x && origin.x % 2 == 1);
}
/* -------------------------------------------- */
_tokenRencontre(rencontre) {
let sprite = new PIXI.Graphics();
sprite.beginFill(0x767610, 0.6);
sprite.drawCircle(0, 0, 6);
sprite.endFill();
sprite.decallage = {
x: (tmrConstants.cellw / 2) - 16,
y: 16 - (tmrConstants.cellh / 2)
};
return { sprite: sprite, rencontre: rencontre, coordTMR: () => rencontre.coord };
}
/* -------------------------------------------- */
_tokenTrouNoir(coord) {
let sprite = new PIXI.Graphics();
sprite.beginFill(0x050505, 0.8);
sprite.drawCircle(0, 0, (tmrConstants.cellw / 2) - 2);
sprite.endFill();
sprite.decallage = {
x: 0,
y: 2
}
return { sprite: sprite, coordTMR: () => coord }
}
/* -------------------------------------------- */
_tokenDebordement(coord) {
let sprite = new PIXI.Graphics();
sprite.beginFill(0x0101FE, 0.3);
sprite.drawCircle(0, 0, (tmrConstants.cellw / 2) - 2);
sprite.endFill();
sprite.decallage = {
x: 0,
y: 2
}
return { sprite: sprite, coordTMR: () => coord }
}
/* -------------------------------------------- */
_tokenMaitrisee(coord) {
let sprite = new PIXI.Graphics();
sprite.beginFill(0x1010F0, 0.8);
sprite.drawCircle(0, 0, 6);
sprite.endFill();
sprite.decallage = {
x: 16 - (tmrConstants.cellw / 2),
y: 16 - (tmrConstants.cellh / 2)
}
return { sprite: sprite, coordTMR: () => coord }
}
/* -------------------------------------------- */
_tokenTerreAttache(coord) {
let sprite = new PIXI.Graphics();
sprite.beginFill(0x10F010, 0.8);
sprite.drawCircle(0, 0, 6);
sprite.endFill();
sprite.decallage = {
x: 16 - (tmrConstants.cellw / 2),
y: 16 - (tmrConstants.cellh / 2)
}
return { sprite: sprite, coordTMR: () => coord }
}
/* -------------------------------------------- */
_tokenSortEnReserve(sort) {
let sprite = new PIXI.Graphics();
sprite.beginFill(0x101010, 0.8);
sprite.drawCircle(0, 0, 6);
sprite.endFill();
sprite.decallage = {
x: 16 - (tmrConstants.cellw / 2),
y: 16 - (tmrConstants.cellh / 2)
}
return { sprite: sprite, sort: sort, coordTMR: () => sort.coord }
}
/* -------------------------------------------- */
_tokenDemiReve() {
let texture = PIXI.utils.TextureCache['demi-reve'];
let sprite = new PIXI.Sprite(texture);
sprite.width = tmrConstants.cellw * 0.7;
sprite.height = tmrConstants.cellh * 0.7;
sprite.anchor.set(0.5);
sprite.tint = 0x00FFEE;
return { sprite: sprite, actor: this.actor, coordTMR: () => this.actor.data.data.reve.tmrpos.coord }
}
/* -------------------------------------------- */
_addDemiReve() {
this.demiReve = this._tokenDemiReve();
this._setTokenPosition(this.demiReve);
this.pixiApp.stage.addChild(this.demiReve.sprite);
}
/* -------------------------------------------- */
_updateDemiReve() {
this._setTokenPosition(this.demiReve);
}
/* -------------------------------------------- */
/** Retourne les coordonnées x, h, w, h du rectangle d'une case donnée */
_getCaseRectangleCoord(coord) {
let coordXY = TMRUtility.convertToCellPos(coord);
let decallagePairImpair = (coordXY.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
let x = tmrConstants.gridx + (coordXY.x * tmrConstants.cellw) - (tmrConstants.cellw / 2);
let y = tmrConstants.gridy + (coordXY.y * tmrConstants.cellh) - (tmrConstants.cellh / 2) + decallagePairImpair;
return { x: x, y: y, w: tmrConstants.cellw, h: tmrConstants.cellh }
return this.pixiTMR.getCaseRectangle(TMRUtility.convertToCellPos(coord));
}
/* -------------------------------------------- */
_setTokenPosition(token) {
let coordXY = TMRUtility.convertToCellPos(token.coordTMR());
let decallagePairImpair = (coordXY.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
let dx = (token.sprite.decallage == undefined) ? 0 : token.sprite.decallage.x;
let dy = (token.sprite.decallage == undefined) ? 0 : token.sprite.decallage.y;
token.sprite.x = tmrConstants.gridx + (coordXY.x * tmrConstants.cellw) + dx;
token.sprite.y = tmrConstants.gridy + (coordXY.y * tmrConstants.cellh) + dy + decallagePairImpair;
this.pixiTMR.setPosition(token.sprite, TMRUtility.convertToCellPos(token.coordTMR()));
}
/* -------------------------------------------- */
@ -878,10 +832,9 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
_trackToken(token) {
this.allTokens.push(token)
this.allTokens.push(token);
this._setTokenPosition(token);
this.pixiApp.stage.addChild(token.sprite);
}
}