From 9fd7db2ccff3f24bfe79a35308b1e4f9fc9ee0a4 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Fri, 5 Feb 2021 01:38:40 +0100 Subject: [PATCH] Fixes nombreux sur tmr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rencontre sur case humide ne causait pas de maîtrise - détermination de la liste des tmrs par type à l'init (classify) - tirages aléatoire par type de tmr dans les commandes - amélioration de messages (nom de case) - fix expérience case humide - correction gestion des débordement - montées très laborieuses multiples - renommages et extraits méthodes - distinction de pos (x, y) vs coord (A1) --- module/actor-sheet.js | 5 +- module/actor-vehicule-sheet.js | 3 +- module/actor.js | 36 +++-- module/item-competencecreature.js | 2 +- module/item.js | 26 +--- module/misc.js | 20 ++- module/rdd-commands.js | 60 +++++--- module/rdd-tmr-dialog.js | 239 +++++++++++++++-------------- module/rdd-tmr-rencontre-dialog.js | 32 ++-- module/tmr-rencontres.js | 2 +- module/tmr-utility.js | 103 +++++-------- 11 files changed, 282 insertions(+), 246 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 6c7314f0..ef20bd34 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -9,6 +9,7 @@ import { RdDItem } from "./item.js"; import { RdDItemArme } from "./item-arme.js"; import { RdDItemCompetence } from "./item-competence.js"; import { RdDBonus } from "./rdd-bonus.js"; +import { Misc } from "./misc.js"; /* -------------------------------------------- */ export class RdDActorSheet extends ActorSheet { @@ -38,11 +39,11 @@ export class RdDActorSheet extends ActorSheet { data.data.showCompNiveauBase = this.options.showCompNiveauBase; data.data.montrerArchetype = this.options.montrerArchetype; - data.itemsByType = RdDItem.buildItemsClassification(data.items); + data.itemsByType = Misc.classify(data.items); // Competence per category data.data.competenceXPTotal = 0; - data.competenceByCategory = RdDItem.classify( + data.competenceByCategory = Misc.classify( data.itemsByType.competence, item => item.data.categorie, item => { diff --git a/module/actor-vehicule-sheet.js b/module/actor-vehicule-sheet.js index b9136a2b..0a2c90d7 100644 --- a/module/actor-vehicule-sheet.js +++ b/module/actor-vehicule-sheet.js @@ -6,6 +6,7 @@ import { RdDUtility } from "./rdd-utility.js"; import { HtmlUtility } from "./html-utility.js"; import { RdDItem } from "./item.js"; +import { Misc } from "./misc.js"; /* -------------------------------------------- */ export class RdDActorVehiculeSheet extends ActorSheet { @@ -36,7 +37,7 @@ export class RdDActorVehiculeSheet extends ActorSheet { getData() { let data = super.getData(); - data.itemsByType = RdDItem.buildItemsClassification(data.items); + data.itemsByType = Misc.classify(data.items); RdDUtility.filterItemsPerTypeForSheet(data); RdDUtility.buildArbreDeConteneur(this, data); diff --git a/module/actor.js b/module/actor.js index a22e56bf..fadb6bbb 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1,5 +1,5 @@ import { RdDUtility } from "./rdd-utility.js"; -import { TMRUtility } from "./tmr-utility.js"; +import { TMRType, TMRUtility } from "./tmr-utility.js"; import { RdDRollDialogEthylisme } from "./rdd-roll-ethylisme.js"; import { RdDRoll } from "./rdd-roll.js"; import { RdDTMRDialog } from "./rdd-tmr-dialog.js"; @@ -21,6 +21,7 @@ import { RdDAlchimie } from "./rdd-alchimie.js"; import { StatusEffects } from "./status-effects.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { ReglesOptionelles } from "./regles-optionelles.js"; +import { RdDItem } from "./item.js"; /* -------------------------------------------- */ @@ -1837,22 +1838,25 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - checkIsAdditionnalHumide(cellDescr, coordTMR) { - let pontHumide = this.data.items.find(item => item.type == 'souffle' && item.name.toLowerCase().includes(' des ponts')); - if (pontHumide && cellDescr.type == 'pont') { + isCaseHumideAdditionelle(tmr) { + if (tmr.type == 'pont' && this.data.items.find(it => RdDItem.isSoufflePontImpraticable(it))) { ChatMessage.create({ - content: "Vous êtes sous le coup d'une Impraticabilité des Ponts : ils doivent être maîtrisés comme des cases humides.", + 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; } // Débordement ? - let debordementList = this.data.items.filter(item => item.type == 'casetmr' && item.data.specific == 'debordement'); - for (let caseTMR of debordementList) { - if (caseTMR.data.coord == coordTMR) - return true; + let isTmrInondee = this.data.items.filter(it => RdDItem.isCaseTMR(it)) + .filter(it => it.data.coord == tmr.coord) + .find(it => RdDItem.isCaseInnondee(it)); + if (isTmrInondee) { + 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; } @@ -2398,14 +2402,14 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - checkMonteeLaborieuse() { // Return +1 si la queue Montée Laborieuse est présente, 0 sinon - let monteLaborieuse = this.data.items.find(item => (item.type == 'queue' || item.type == 'souffle') && item.name.toLowerCase().includes('montée laborieuse')); - if (monteLaborieuse) { + checkMonteeLaborieuse() { // Return +1 par queue/ombre/souffle Montée Laborieuse présente + let countMonteLaborieuse = this.data.items.filter(item => (item.type == 'queue' || item.type == 'ombre' || item.type == 'souffle') && item.name.toLowerCase().includes('montée laborieuse')).length; + if (countMonteLaborieuse) { ChatMessage.create({ - content: "Vous êtes sous le coup d'une Montée Laborieuse : vos montées en TMR coûtent 1 Point de Rêve de plus.", + content: `Vous êtes sous le coup d'une Montée Laborieuse : vos montées en TMR coûtent ${countMonteLaborieuse} Point de Rêve de plus.`, whisper: ChatMessage.getWhisperRecipients(game.user.name) }); - return 1; + return countMonteLaborieuse; } return 0; } @@ -2414,7 +2418,7 @@ export class RdDActor extends Actor { refreshTMRView( tmrData ) { console.log("REFRESH !!!!"); if ( this.currentTMR ) { - this.currentTMR.forceDemiRevePositionView(tmrData.tmrPos); + this.currentTMR.forceDemiRevePositionView(); } } diff --git a/module/item-competencecreature.js b/module/item-competencecreature.js index 524d5829..67896acb 100644 --- a/module/item-competencecreature.js +++ b/module/item-competencecreature.js @@ -29,7 +29,7 @@ export class RdDItemCompetenceCreature extends Item { }); return arme; } - console.error("RdDItem.toArme(", item, ") : impossible de transformer l'Item en arme"); + console.error("RdDItemCompetenceCreature.toArme(", item, ") : impossible de transformer l'Item en arme"); return undefined; } diff --git a/module/item.js b/module/item.js index 46ad7721..988d3ecf 100644 --- a/module/item.js +++ b/module/item.js @@ -1,28 +1,18 @@ +import { Misc } from "./misc.js"; /* -------------------------------------------- */ export class RdDItem { - /* -------------------------------------------- */ - static buildItemsClassification(items) { - return RdDItem.classify(items, it => it.type) + static isSoufflePontImpraticable(item) { + return item.type == 'souffle' && item.name.toLowerCase().includes(' des ponts'); } - static classify(items, classifier = it => it.type, transform = it => it) { - let itemsBy = {}; - RdDItem.classifyInto(itemsBy, items, classifier, transform); - return itemsBy; + static isCaseInnondee(item) { + return RdDItem.isCaseTMR(item) && item.data.specific == 'debordement'; } - static classifyInto(itemsBy, items, classifier = it => it.type, transform = it => it) { - for (const item of items) { - const classification = classifier(item); - let list = itemsBy[classification]; - if (!list) { - list = []; - itemsBy[classification] = list; - } - list.push(transform(item)); - } - } + static isCaseTMR(item) { + return item.type == 'casetmr'; + } } \ No newline at end of file diff --git a/module/misc.js b/module/misc.js index 6b754e23..50566a09 100644 --- a/module/misc.js +++ b/module/misc.js @@ -1,5 +1,4 @@ - /** * This class is intended as a placeholder for utility methods unrelated * to actual classes of the game system or of FoundryVTT @@ -41,4 +40,23 @@ export class Misc { default: return '1/' + diviseur; } } + + static classify(items, classifier = it => it.type, transform = it => it) { + let itemsBy = {}; + Misc.classifyInto(itemsBy, items, classifier, transform); + return itemsBy; + } + + static classifyInto(itemsBy, items, classifier = it => it.type, transform = it => it) { + for (const item of items) { + const classification = classifier(item); + let list = itemsBy[classification]; + if (!list) { + list = []; + itemsBy[classification] = list; + } + list.push(transform(item)); + } + } + } \ No newline at end of file diff --git a/module/rdd-commands.js b/module/rdd-commands.js index f4bbcb47..f58eaec9 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -9,7 +9,7 @@ import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js"; import { RdDRollTables } from "./rdd-rolltables.js"; import { RdDUtility } from "./rdd-utility.js"; import { TMRRencontres } from "./tmr-rencontres.js"; -import { TMRUtility } from "./tmr-utility.js"; +import { TMRType, TMRUtility } from "./tmr-utility.js"; const rddRollNumeric = /(\d+)\s*([\+\-]?\d+)?\s*(s)?/; @@ -21,20 +21,23 @@ export class RdDCommands { const rddCommands = new RdDCommands(); rddCommands.registerCommand({ path: ["/aide"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" }); rddCommands.registerCommand({ path: ["/help"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" }); - rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(true), descr: "Tire une Queue de Dragon" }); - rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(true), descr: "Tire une Ombre de Dragon" }); - rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(true), descr: "Tire une Tête de Dragon pour Hauts Revants" }); - rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(true), descr: "Tire une Tête de Dragon" }); - rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle(true), descr: " Tire un Souffle de Dragon" }); - rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot(true), descr: "Tire une carte du Tarot Draconique" }); + rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(), descr: "Tire une Queue de Dragon" }); + rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(), descr: "Tire une Ombre de Dragon" }); + rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(), descr: "Tire une Tête de Dragon pour Hauts Revants" }); + rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(), descr: "Tire une Tête de Dragon" }); + rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle(), descr: " Tire un Souffle de Dragon" }); + rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot(), descr: "Tire une carte du Tarot Draconique" }); - rddCommands.registerCommand({ path: ["/tmra"], func: (content, msg, params) => TMRUtility.getTMRAleatoire(), descr: "Tire une case aléatoire des Terres médianes" }); + rddCommands.registerCommand({ + path: ["/tmra"], func: (content, msg, params) => rddCommands.getTMRAleatoire(msg, params), + descr: `Tire une case aléatoire des Terres médianes +
/tmra forêt détermine une 'forêt' aléatoire +
/tmra détermine une case aléatoire dans toutes les TMR` }); rddCommands.registerCommand({ path: ["/tmrr"], func: (content, msg, params) => rddCommands.getRencontreTMR(params), - descr: ` - Exemple: /tmrr foret lance un d100 et détermine la rencontre correspondante en 'forêt' - Exemple: /tmrr forêt 47 détermine la rencontre en 'forêt' pour un jet de dé de 47 - ` + descr: `Détermine une rencontre dans un type de case +
/tmrr foret lance un d100 et détermine la rencontre correspondante en 'forêt' +
/tmrr forêt 47 détermine la rencontre en 'forêt' pour un jet de dé de 47` }); rddCommands.registerCommand({ @@ -53,27 +56,24 @@ export class RdDCommands { rddCommands.registerCommand({ path: ["/rdd"], func: (content, msg, params) => rddCommands.rollRdd(msg, params), descr: `Effectue un jet de dés dans la table de résolution. Exemples: -
/rdd ouvre la table de résolution -
/rdd 10 3 effectue un jet 10 à +3 -
/rdd 10 +2 effectue un jet 10 à +2 -
/rdd 15 -2 effectue un jet 15 à -2 -
/rdd 15 0 s effectue un jet 15 à 0, avec significative requise - ` +
/rdd ouvre la table de résolution +
/rdd 10 3 effectue un jet 10 à +3 +
/rdd 10 +2 effectue un jet 10 à +2 +
/rdd 15 -2 effectue un jet 15 à -2 +
/rdd 15 0 s effectue un jet 15 à 0, avec significative requise` }); rddCommands.registerCommand({ path: ["/ddr"], func: (content, msg, params) => rddCommands.rollDeDraconique(msg), descr: "Lance un Dé Draconique" }); rddCommands.registerCommand({ path: ["/payer"], func: (content, msg, params) => RdDUtility.afficherDemandePayer(params[0], params[1]), descr: `Permet de payer un montant. Exemples: -
/payer 5s 10d permet d'envoyer un message pour payer 5 sols et 10 deniers -
/payer 10d permet d'envoyer un message pour payer 10 deniers - ` +
/payer 5s 10d permet d'envoyer un message pour payer 5 sols et 10 deniers +
/payer 10d permet d'envoyer un message pour payer 10 deniers` }); rddCommands.registerCommand({ path: ["/astro"], func: (content, msg, params) => RdDUtility.afficherHeuresChanceMalchance(params[0]), descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples: -
/astro Lyre - ` +
/astro Lyre` }); game.system.rdd.commands = rddCommands; } @@ -185,7 +185,7 @@ export class RdDCommands { /* -------------------------------------------- */ async getRencontreTMR(params) { - if (params.length == 1 || params.length ==2) { + if (params.length == 1 || params.length == 2) { return TMRRencontres.rollRencontre(params[0], params[1]) } else { @@ -232,6 +232,18 @@ export class RdDCommands { RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr.total}`); } + getTMRAleatoire(msg, params) { + if (params.length < 2) { + let type = params[0]; + const tmr = TMRUtility.getTMRAleatoire(type); + RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`); + } + else { + return false; + } + } + + /* -------------------------------------------- */ getCoutXpComp(msg, params) { if (params && (params.length == 1 || params.length == 2)) { diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 61b9059e..9745a5f6 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -200,7 +200,6 @@ export class RdDTMRDialog extends Dialog { this.actor.deleteTMRRencontreAtPosition(); this.updatePreviousRencontres(); - let rencontreData = { actor: this.actor, alias: this.actor.name, @@ -248,20 +247,22 @@ export class RdDTMRDialog extends Dialog { rencontreData.nbRounds++; this.nbFatigue += 1; this._tentativeMaitrise(rencontreData); - setTimeout(() => this._deleteTmrMessages(rencontreData.actor, rencontreData.nbRounds), 500); + this._deleteTmrMessages(rencontreData.actor, rencontreData.nbRounds); }, 2000); } } _deleteTmrMessages(actor, nbRounds = -1) { - if (nbRounds < 0) { - ChatUtility.removeChatMessageContaining(`

`); + setTimeout(() => { + if (nbRounds < 0) { + ChatUtility.removeChatMessageContaining(`

`); + } + } + }, 500); } /* -------------------------------------------- */ @@ -275,38 +276,38 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async manageRencontre(coordTMR, cellDescr) { + async manageRencontre(tmr, postRencontre) { if (this.viewOnly) { return; } this.currentRencontre = undefined; - let rencontre = await this._jetDeRencontre(coordTMR, cellDescr); + let rencontre = await this._jetDeRencontre(tmr); if (rencontre) { // Manages it if (rencontre.rencontre) rencontre = rencontre.rencontre; // Manage stored rencontres console.log("manageRencontre", rencontre); this.currentRencontre = duplicate(rencontre); - let dialog = new RdDTMRRencontreDialog("", this, this.currentRencontre); + let dialog = new RdDTMRRencontreDialog("", this, this.currentRencontre, postRencontre); dialog.render(true); } } /* -------------------------------------------- */ - async _jetDeRencontre(coordTMR, cellDescr) { + async _jetDeRencontre(tmr) { if (TMRUtility.isForceRencontre()) { - return await TMRUtility.rencontreTMRRoll(coordTMR, cellDescr); + return await TMRUtility.rencontreTMRRoll(tmr.coord, tmr); } - let rencontre = this.rencontresExistantes.find(prev => prev.coord == coordTMR); + let rencontre = this.rencontresExistantes.find(prev => prev.coord == tmr.coord); if (rencontre) { return rencontre; } let myRoll = new Roll("1d7").evaluate(); if (myRoll.total == 7) { let isMauvaise = this.actor.isRencontreSpeciale(); - return await TMRUtility.rencontreTMRRoll(coordTMR, cellDescr, isMauvaise); + return await TMRUtility.rencontreTMRRoll(tmr.coord, tmr, isMauvaise); } - this._tellToUser(myRoll.total + ": Pas de rencontre en " + cellDescr.label + " (" + coordTMR + ")"); + this._tellToUser(myRoll.total + ": Pas de rencontre en " + tmr.label + " (" + tmr.coord + ")"); } /* -------------------------------------------- */ @@ -330,13 +331,13 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async manageCaseSpeciale(cellDescr, coordTMR) { + async manageCaseSpeciale(tmr) { for (let caseTMR of this.casesSpeciales) { - if (caseTMR.data.coord == coordTMR) { // Match ! + 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; + 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.", @@ -349,12 +350,7 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ isCaseMaitrisee(coordTMR) { - for (let caseTMR of this.casesSpeciales) { - if (caseTMR.data.coord == coordTMR && caseTMR.data.specific == 'maitrisee') { - return true; - } - } - return false; + return this.casesSpeciales.find(it => it.data.coord = coordTMR && it.data.specific == 'maitrisee'); } /* -------------------------------------------- */ @@ -364,19 +360,11 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async manageCaseHumide(cellDescr, coordTMR) { + async manageCaseHumide(tmr) { if (this.viewOnly || this.currentRencontre) { return; } - let isHumide = this.actor.checkIsAdditionnalHumide(cellDescr, coordTMR); - if (cellDescr.type == "lac" || cellDescr.type == "fleuve" || cellDescr.type == "marais" || isHumide) { - if (this.isCaseMaitrisee(coordTMR)) { - ChatMessage.create({ - content: "Cette case humide est déja maitrisée grâce à votre Tête Quête des Eaux", - whisper: ChatMessage.getWhisperRecipients(game.user.name) - }); - return; - } + if (this.isCaseHumide(tmr)) { // TODO: permettre de choisir la voie de draconic? let draconic = this.actor.getBestDraconic(); @@ -404,7 +392,7 @@ export class RdDTMRDialog extends Dialog { explication += "Vous êtes entré sur une case humide, et vous avez réussi votre maîtrise !" msg2MJ += game.user.name + " est rentré sur une case humides : Réussite !"; } - explication += "
Test : Rêve actuel / " + draconic.name + " / " + cellDescr.type + "" + explication += "
Test : Rêve actuel / " + draconic.name + " / " + tmr.type + "" + RdDResolutionTable.explain(rolled); if (rolled.isETotal) { @@ -414,7 +402,7 @@ export class RdDTMRDialog extends Dialog { } if (rolled.isPart) { explication += "
Vous avez fait une Réussite Particulière"; - this.actor._appliquerAjoutExperience({ rolled: rolled, seletedCarac: { label: 'reve' }, competence: draconic.name }) + this.actor._appliquerAjoutExperience({ rolled: rolled, selectedCarac: { label: 'reve' }, competence: draconic.name }) msg2MJ += "
Et a fait une réussite particulière"; } @@ -432,6 +420,21 @@ export class RdDTMRDialog extends Dialog { humideDiag.render(true); } } + + isCaseHumide(tmr) { + if (this.isCaseMaitrisee(tmr.coord)) { + ChatMessage.create({ + content: tmr.label + ": cette case humide est déja maitrisée grâce à votre Tête Quête des Eaux", + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); + return false; + } + if (this.actor.isCaseHumideAdditionelle(tmr)) { + return true; + } + return tmr.type == "lac" || tmr.type == "fleuve" || tmr.type == "marais"; + } + /* -------------------------------------------- */ isReserveExtensible(coordTMR) { for (let caseTMR of this.casesSpeciales) { @@ -537,60 +540,38 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async deplacerDemiReve(event) { + async onClickTMR(event) { if (this.viewOnly) { return; } let origEvent = event.data.originalEvent; - let myself = event.target.tmrObject; + let tmrObject = event.target.tmrObject; - let eventCoord = RdDTMRDialog._computeEventCoord(origEvent); - let cellx = eventCoord.cellx; - let celly = eventCoord.celly; - console.log("deplacerDemiReve >>>>", cellx, celly); - let currentPos = TMRUtility.convertToCellCoord(myself.actor.data.data.reve.tmrpos.coord); - let coordTMR = TMRUtility.convertToTMRCoord(cellx, celly); - let currentTMR = TMRUtility.convertToTMRCoord(currentPos.x, currentPos.y); + 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 targetCoordTMR = TMRUtility.convertToTMRCoord(eventPos); + let currentCoordTMR = TMRUtility.convertToTMRCoord(currentPos); // Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter) let deplacementType = 'erreur'; - if (myself.rencontreState == 'aucune') { // Pas de recontre en post-processing, donc deplacement normal - if (!RdDTMRDialog._horsDePortee(currentPos, cellx, celly) || myself.isTerreAttache(coordTMR) || myself.checkConnaissanceFleuve(currentTMR, coordTMR)) { + 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)) { deplacementType = 'normal'; } } else { - deplacementType = myself.processClickPostRencontre(coordTMR); + deplacementType = this.processClickPostRencontre(targetCoordTMR); } // Si le deplacement est valide if (deplacementType == 'normal' || deplacementType == 'saut') { - if (myself.currentRencontre != 'normal') - myself.nettoyerRencontre(); - let cellDescr = TMRUtility.getTMR(coordTMR); - - await myself.manageCaseSpeciale(cellDescr, coordTMR); // Gestion cases spéciales type Trou noir, etc - - console.log("deplacerDemiReve: TMR column is", coordTMR, cellx, celly, cellDescr, this); - - let tmrPos = duplicate(myself.actor.data.data.reve.tmrpos); - tmrPos.coord = coordTMR; - await myself.actor.update({ "data.reve.tmrpos": tmrPos }); - myself._updateDemiReve(myself); - myself.nbFatigue += 1; - myself.updateValuesDisplay(); - game.socket.emit("system.foundryvtt-reve-de-dragon", { - msg: "msg_tmr_move", data: { - actorId: myself.actor.data._id, - tmrPos: tmrPos - } - }); - - if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... - await myself.manageRencontre(coordTMR, cellDescr); - } - await myself.manageCaseHumide(cellDescr, coordTMR); - await myself.declencheSortEnReserve(coordTMR); - await myself.actor.checkSoufflePeage(cellDescr); + await this._deplacerDemiReve(targetCoordTMR, deplacementType); } else if (deplacementType == 'messager') { // Dans ce cas, ouverture du lancement de sort sur la case visée /* @@ -598,29 +579,71 @@ export class RdDTMRDialog extends Dialog { Si la case est le demi-rêve, ne pas lancer de sort. Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre si on essaie de lancer un sort (ou bloquer le lancer de sort) */ - await myself.actor.rollUnSort(coordTMR); - myself.nettoyerRencontre(); + await this._messagerDemiReve(targetCoordTMR); } 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 :", myself.rencontreState, myself.currentRencontre); + console.log("STATUS :", this.rencontreState, this.currentRencontre); } - myself.checkQuitterTMR(); // Vérifier l'état des compteurs reve/fatigue/vie + 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(); + this.nbFatigue += 1; + this.updateValuesDisplay(); + game.socket.emit("system.foundryvtt-reve-de-dragon", { + msg: "msg_tmr_move", data: { + actorId: this.actor.data._id, + tmrPos: tmrPos + } + }); + + if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... + await this.manageRencontre(tmr, () => this.postRencontre(tmr)); + } + else{ + await this.postRencontre(tmr); + } + } + + async postRencontre(tmr) { + await this.manageCaseHumide(tmr); + await this.declencheSortEnReserve(tmr.coord); + await this.actor.checkSoufflePeage(tmr); } /* -------------------------------------------- */ async forceDemiRevePositionView(coordTMR) { - this._updateDemiReve(this); + this._updateDemiReve(); } /* -------------------------------------------- */ async forceDemiRevePosition(coordTMR) { await this.actor.updateCoordTMR(coordTMR); - this._updateDemiReve(this); - let cellDescr = TMRUtility.getTMR(coordTMR); - this.manageCaseHumide(cellDescr, coordTMR); - await this.declencheSortEnReserve(coordTMR); + this._updateDemiReve(); + let tmr = TMRUtility.getTMR(coordTMR); + this.manageCaseHumide(tmr); + await this.declencheSortEnReserve(tmr.coord); } /* -------------------------------------------- */ @@ -661,7 +684,7 @@ export class RdDTMRDialog extends Dialog { mytmr.buttonMode = true; mytmr.tmrObject = this; if (!this.viewOnly) { - mytmr.on('pointerdown', this.deplacerDemiReve); + mytmr.on('pointerdown', this.onClickTMR); } this.pixiApp.stage.addChild(mytmr); @@ -676,42 +699,36 @@ export class RdDTMRDialog extends Dialog { } // Gestion du cout de montée en points de rêve - let reveCout = -1; - if (this.actor.checkTeteDeplacementAccelere()) { - reveCout = -1; - } else { - reveCout = (this.tmrdata.isRapide) ? -2 : -1; - } + let reveCout = (this.tmrdata.isRapide && !this.actor.checkTeteDeplacementAccelere()) ? -2 : -1; reveCout -= this.actor.checkMonteeLaborieuse(); await this.actor.reveActuelIncDec(reveCout); // Le reste... this.updateValuesDisplay(); - let coordTMR = this.actor.data.data.reve.tmrpos.coord; - let cellDescr = TMRUtility.getTMR(coordTMR); - await this.manageRencontre(coordTMR, cellDescr); - this.manageCaseHumide(cellDescr, coordTMR); - // Mise à jour du nb de cases de Fatigue - this.nbFatigue = this.actor.getTMRFatigue(); - this.actor.displayTMRQueueSouffleInformation(); + let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord); + await this.manageRencontre(tmr, () => { + this.postRencontre(tmr); + this.nbFatigue = this.actor.getTMRFatigue(); + this.actor.displayTMRQueueSouffleInformation(); + }); } /* -------------------------------------------- */ - static _computeEventCoord(origEvent) { + 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 { cellx, celly }; + return { x: cellx, y: celly }; } /* -------------------------------------------- */ - static _horsDePortee(pos, cellx, celly) { - return Math.abs(cellx - pos.x) > 1 - || Math.abs(celly - pos.y) > 1 - || (pos.y == 0 && celly > pos.y && cellx != pos.x && pos.x % 2 == 0) - || (celly == 0 && celly < pos.y && cellx != pos.x && pos.x % 2 == 1); + 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); } /* -------------------------------------------- */ @@ -811,14 +828,14 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - _updateDemiReve(myself) { - myself._setTokenPosition(myself.demiReve); + _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.convertToCellCoord(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; @@ -827,7 +844,7 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ _setTokenPosition(token) { - let coordXY = TMRUtility.convertToCellCoord(token.coordTMR()); + 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; diff --git a/module/rdd-tmr-rencontre-dialog.js b/module/rdd-tmr-rencontre-dialog.js index 5b432fda..dfa9ffb3 100644 --- a/module/rdd-tmr-rencontre-dialog.js +++ b/module/rdd-tmr-rencontre-dialog.js @@ -1,22 +1,22 @@ /* -------------------------------------------- */ export class RdDTMRRencontreDialog extends Dialog { - + /* -------------------------------------------- */ - constructor(html, tmrApp, rencontre) { + constructor(html, tmrApp, rencontre, postRencontre) { const dialogConf = { title: "Rencontre en TMR!", content: "Vous recontrez un " + rencontre.name + " de force " + rencontre.force + "
", buttons: { - derober: { icon: '', label: "Se dérober", callback: () => { this.toClose = true; this.tmrApp.derober() } }, - refouler: { icon: '', label: "Refouler", callback: () => { this.toClose = true; this.tmrApp.refouler() } }, - maitiser: { icon: '', label: "Maîtriser", callback: () => { this.toClose = true; this.tmrApp.maitriser() } } + derober: { icon: '', label: "Se dérober", callback: () => { this.onButtonFuir(() => tmrApp.derober()); } }, + refouler: { icon: '', label: "Refouler", callback: () => this.onButtonAction(() => tmrApp.refouler()) }, + maitiser: { icon: '', label: "Maîtriser", callback: () => this.onButtonAction(() => tmrApp.maitriser()) } }, default: "derober" - } + }; if (rencontre.ignorer) { - dialogConf.buttons.ignorer = { icon: '', label: "Ignorer", callback: () => { this.toClose = true; this.tmrApp.ignorerRencontre() }}; - } - + dialogConf.buttons.ignorer = { icon: '', label: "Ignorer", callback: () => this.onButtonAction(() => tmrApp.ignorerRencontre()) } + }; + const dialogOptions = { classes: ["tmrrencdialog"], width: 320, height: 240, @@ -26,13 +26,25 @@ export class RdDTMRRencontreDialog extends Dialog { this.toClose = false; this.rencontreData = duplicate(rencontre); + this.postRencontre = postRencontre; this.tmrApp = tmrApp; this.tmrApp.minimize(); } + + async onButtonAction(action) { + this.toClose = true; + await action(); + this.postRencontre(); + } + onButtonFuir(action) { + this.toClose = true; + await action(); + } + /* -------------------------------------------- */ close() { - if ( this.toClose ) { + if (this.toClose) { this.tmrApp.maximize(); return super.close(); } diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js index da24a414..cab3a844 100644 --- a/module/tmr-rencontres.js +++ b/module/tmr-rencontres.js @@ -84,7 +84,7 @@ const typeRencontres = { }, changeur: { - msgSucces: (data) => `Le ${data.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[data.tmr.type]} de votre choix en échange de sa liberté.`, + msgSucces: (data) => `Le ${data.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[data.tmr.type].name} de votre choix en échange de sa liberté.`, msgEchec: (data) => { data.newTMR = TMRUtility.getTMRAleatoire(data.tmr.type); return `Le ${data.rencontre.name} vous embobine avec des promesses, et vous transporte en ${data.newTMR.label} sans attendre votre avis.`; diff --git a/module/tmr-utility.js b/module/tmr-utility.js index b423edc8..4cedfaa7 100644 --- a/module/tmr-utility.js +++ b/module/tmr-utility.js @@ -1,6 +1,7 @@ import { DeDraconique } from "./de-draconique.js"; import { TMRRencontres } from "./tmr-rencontres.js"; import { Grammar } from "./grammar.js"; +import { Misc } from "./misc.js"; /* -------------------------------------------- */ const TMRMapping = { @@ -210,20 +211,20 @@ const TMRMapping = { } export const TMRType = { - cite: "cité", - sanctuaire: "sanctuaire", - plaines: "plaines", - pont: "pont", - collines: "collines", - foret: "forêt", - monts: "monts", - desert: "désert", - fleuve: "fleuve", - lac: "lac", - marais: "marais", - gouffre: "gouffre", - necropole: "nécropole", - desolation: "désolation" + cite: {name:"cité"}, + sanctuaire: {name:"sanctuaire"}, + plaines: {name:"plaines"}, + pont: {name:"pont"}, + collines: {name:"collines"}, + foret: {name:"forêt"}, + monts: {name:"monts"}, + desert: {name:"désert"}, + fleuve: {name:"fleuve"}, + lac: {name:"lac"}, + marais: {name:"marais"}, + gouffre: {name:"gouffre"}, + necropole: {name:"nécropole"}, + desolation: {name:"désolation"} } /* -------------------------------------------- */ @@ -257,14 +258,17 @@ export class TMRUtility { for (let coord in TMRMapping) { TMRMapping[coord].coord = coord; } + let tmrByType = Misc.classify(Object.values(TMRMapping)); + for (const [type, list] of Object.entries(tmrByType)) { + TMRType[type].list = list; + } } /* -------------------------------------------- */ - static convertToTMRCoord( x, y ) + static convertToTMRCoord( pos ) { - y = y + 1 - let letterX = String.fromCharCode(65+x); - return letterX+y + let letterX = String.fromCharCode(65+ (pos.x)); + return letterX + (pos.y +1) } /* -------------------------------------------- */ @@ -280,7 +284,7 @@ export class TMRUtility { } /* -------------------------------------------- */ - static convertToCellCoord( coordTMR ) + static convertToCellPos( coordTMR ) { let x = coordTMR.charCodeAt(0) - 65; let y = coordTMR.substr(1) - 1; @@ -328,13 +332,13 @@ export class TMRUtility { /* -------------------------------------------- */ static deplaceTMRSelonPattern( coord, direction, nTime ) { for (let i=0; i it.coord); } - /* -------------------------------------------- */ - static getTMRAleatoire(terrain=undefined) - { - if (terrain) { - let list = TMRUtility.getListTMR(terrain); - let index = new Roll("1d" + list.length).evaluate().total - 1; - return list[index]; - } - let num = new Roll("1d15").roll().total; - let letter, letterValue; - if ( num == 15) { - letterValue = new Roll( "1d7").roll().total; - letter = String.fromCharCode( 65 + ((parseInt(letterValue)-1)*2) ); - } else { - letterValue = new Roll( "1d13 + 64" ).roll().total; - letter = String.fromCharCode( letterValue ); - } - let caseIndex = letter+num; - ChatMessage.create( { content: "Case aléatoire : " + letter+num + " - " + TMRMapping[caseIndex].label , - whisper: ChatMessage.getWhisperRecipients("GM") } ); - return caseIndex; + static getTMRAleatoire(terrain = undefined) { + let list = terrain ? TMRUtility.getListTMR(terrain) : Object.values(TMRMapping); + let index = new Roll("1d" + list.length).evaluate().total - 1; + return list[index]; } /* -------------------------------------------- */ @@ -432,22 +413,22 @@ export class TMRUtility { /** Returns a list of case inside a given distance * */ - static getTMRPortee(coord, portee) { - return TMRUtility.getTMRArea(coord, portee, tmrConstants); + static getTMRPortee(centerCoord, portee) { + return TMRUtility.getTMRArea(centerCoord, portee, tmrConstants); } - static getTMRArea( coord, distance, tmrConstants ) { - let pos = this.convertToCellCoord( coord ); - let posPic = this.computeRealPictureCoordinates( pos, tmrConstants ); + static getTMRArea( centerCoord, distance, tmrConstants ) { + let centerPos = this.convertToCellPos( centerCoord ); + let posPic = this.computeRealPictureCoordinates( centerPos, tmrConstants ); let caseList = []; - for (let x=pos.x-distance; x<=pos.x+distance; x++ ) { // Loop thru lines - for (let y=pos.y-distance; y<=pos.y+distance; y++ ) { // Loop thru lines - //console.log("Parsing position", x, y); - if ( this._checkTMRCoord(x, y) ) { // Coordinate is valie - let posPicNow = this.computeRealPictureCoordinates( {x: x, y: y}, tmrConstants ); + for (let dx=-distance; dx<=distance; dx++ ) { // Loop thru lines + for (let dy=-distance; dy<=distance; dy++ ) { // Loop thru lines + const currentPos = { x: centerPos.x+dx, y: centerPos.y+dy }; + if ( this._checkTMRCoord(currentPos.x, currentPos.y) ) { // Coordinate is valie + let posPicNow = this.computeRealPictureCoordinates( currentPos, tmrConstants ); let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x,2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw; if ( dist < distance+0.5) { - caseList.push( this.convertToTMRCoord(x, y) ); // Inside the area + caseList.push( this.convertToTMRCoord(currentPos) ); // Inside the area } } }