forked from public/foundryvtt-reve-de-dragon
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:
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user