diff --git a/module/actor-sheet.js b/module/actor-sheet.js index ad72328e..f78ff592 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -315,7 +315,7 @@ export class RdDActorSheet extends ActorSheet { // Boutons spéciaux MJs html.find('.forcer-tmr-aleatoire').click(async event => { - this.actor.cacheTMRetMessage(); + this.actor.reinsertionAleatoire("Action MJ"); }); html.find('.afficher-tmr').click(async event => { this.actor.afficheTMRetMessage(); diff --git a/module/actor.js b/module/actor.js index 7bb90623..c2b41701 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1472,10 +1472,8 @@ export class RdDActor extends Actor { isTMRCache() { return this.data.data.reve.tmrpos.cache; } - /* -------------------------------------------- */ - async cacheTMRetMessage() { - await this.reinsertionAleatoire("Action MJ"); - await this.cacheTMR(); + + notifyRefreshTMR() { game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_tmr_move", data: { actorId: this.data._id, @@ -1487,27 +1485,27 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async afficheTMRetMessage() { await this.montreTMR(); - game.socket.emit(SYSTEM_SOCKET_ID, { - msg: "msg_tmr_move", data: { - actorId: this.data._id, - tmrPos: this.data.data.reve.tmrpos - } - }); + this.notifyRefreshTMR(); } /* -------------------------------------------- */ - async reinsertionAleatoire(raison) { + async reinsertionAleatoire(raison, accessible = tmr => true) { + const innaccessible = this.buildTMRInnaccessible(); + let tmr = await TMRUtility.getTMRAleatoire(tmr => accessible(tmr) && !innaccessible.includes(tmr.coord)); ChatMessage.create({ content: `${raison} : ré-insertion aléatoire.`, whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name) }); - const innaccessible = this.buildTMRInnaccessible(); - let tmr = await TMRUtility.getTMRAleatoire(tmr => !innaccessible.includes(tmr.coord)); - this.updateCoordTMR(tmr.coord); - this.cacheTMR(); + await this.forcerPositionTMRInconnue(tmr); return tmr; } + async forcerPositionTMRInconnue(tmr) { + await this.cacheTMR(); + await this.updateCoordTMR(tmr.coord); + this.notifyRefreshTMR(); + } + /* -------------------------------------------- */ buildTMRInnaccessible() { const tmrInnaccessibles = this.filterItemsData(it => Draconique.isCaseTMR(it) && @@ -2403,7 +2401,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async checkSoufflePeage(tmr) { - if ((tmr.type == 'pont' || tmr.type == 'cite') && EffetsDraconiques.isPeage(actor)) { + if ((tmr.type == 'pont' || tmr.type == 'cite') && EffetsDraconiques.isPeage(this)) { await this.reveActuelIncDec(-1); ChatMessage.create({ content: "Vous êtes sous le coup d'un Péage : l'entrée sur cette case vous a coûté 1 Point de Rêve (déduit automatiquement).", @@ -2568,7 +2566,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ conjurerPossession(possession) { - let draconic = this.getBestDraconic() + let draconic = this.getBestDraconic(); RdDPossession.managePossession(this, draconic, possession) } @@ -3153,9 +3151,9 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - refreshTMRView(tmrData) { + refreshTMRView() { if (this.currentTMR) { - this.currentTMR.externalRefresh(tmrData) + this.currentTMR.externalRefresh(); } } diff --git a/module/rdd-commands.js b/module/rdd-commands.js index 8793f306..fdddcb05 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -7,6 +7,7 @@ import { RdDItemCompetence } from "./item-competence.js"; import { Misc } from "./misc.js"; import { RdDCarac } from "./rdd-carac.js"; import { RdDDice } from "./rdd-dice.js"; +import { RdDMeteo } from "./rdd-meteo.js"; import { RdDNameGen } from "./rdd-namegen.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js"; @@ -34,6 +35,7 @@ export class RdDCommands { rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle(true), descr: " Tire un Souffle de Dragon" }); rddCommands.registerCommand({ path: ["/table", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence(true), descr: "Tire une compétence au hasard" }); rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot(true), descr: "Tire une carte du Tarot Draconique" }); + rddCommands.registerCommand({ path: ["/meteo"], func: (content, msg, params) => rddCommands.getMeteo(msg, params), descr: "Propose une météo marine" }); rddCommands.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" }); rddCommands.registerCommand({ @@ -398,5 +400,8 @@ export class RdDCommands { } return true; } + async getMeteo(msg, params) { + return await RdDMeteo.getMeteo(); + } } diff --git a/module/rdd-meteo.js b/module/rdd-meteo.js new file mode 100644 index 00000000..8dbff49c --- /dev/null +++ b/module/rdd-meteo.js @@ -0,0 +1,134 @@ + +const vents = [ + { min: 0, max: 0, valeur: 'Calme' }, + { min: 1, max: 1, valeur: 'Légère brise' }, + { min: 2, max: 2, valeur: 'Jolie brise' }, + { min: 3, max: 3, valeur: 'Bonne brise' }, + { min: 4, max: 4, valeur: 'Vent frais' }, + { min: 5, max: 5, valeur: 'Coup de vent' }, + { min: 6, max: 6, valeur: 'Fort coup de vent' }, + { min: 7, max: 9, valeur: 'Tempête' }, + { min: 10, max: 13, valeur: 'Violente tempête' }, + { min: 14, valeur: 'Ouragan' }, +] +const mers = [ + { min: 0, max: 0, valeur: 'Calme' }, + { min: 1, max: 1, valeur: 'Belle' }, + { min: 2, max: 2, valeur: 'Peu agitée' }, + { min: 3, max: 3, valeur: 'Agitée' }, + { min: 4, max: 4, valeur: 'Forte' }, + { min: 5, max: 6, valeur: 'Très forte' }, + { min: 7, max: 9, valeur: 'Grosse' }, + { min: 10, max: 13, valeur: 'Très grosse' }, + { min: 14, valeur: 'Énorme' }, +] + +const nuages = [ + { min: 0, max: 3, valeur: 'dégagé' }, + { min: 4, max: 6, valeur: 'passages nuageux' }, + { min: 7, max: 9, valeur: 'nuageux', }, + { min: 10, max: 10, valeur: 'brouillard' }, + { min: 11, max: 12, valeur: 'bruine' }, + { min: 13, valeur: 'très nuageux' }, +] + +const pluies = [ + { min: 0, max: 4, valeur: 'aucune' }, + { min: 5, max: 5, valeur: 'bruine, crachin, éparse' }, + { min: 6, max: 7, valeur: 'averses' }, + { min: 8, max: 10, valeur: 'pluvieux', }, + { min: 11, max: 13, valeur: 'forte pluie' }, + { min: 14, valeur: 'déluge' }, +] + +const temperatures = [ + { max: -14, valeur: 'glaciale' }, + { min: -13, max: -10, valeur: 'Très froide' }, + { min: -9, max: -7, valeur: 'froide' }, + { min: -6, max: -4, valeur: 'fraîche' }, + { min: -3, max: 3, valeur: 'de saison' }, + { min: 4, max: 6, valeur: 'élevée' }, + { min: 7, max: 9, valeur: 'chaude' }, + { min: 10, max: 13, valeur: 'torride' }, + { min: 14, valeur: 'caniculaire' }, +] + +export class RdDMeteo { + static async getForce() { + const roll = new Roll(`1dr`); + await roll.evaluate({ async: true }); + return roll.total; + } + + static async getPluie(nuage) { + return nuage <= 3 ? 0 : await RdDMeteo.getForce(); + } + + static async getTemperature() { + const degre = await RdDMeteo.getForce(); + const rollChaudFroid = new Roll('1d2'); + await rollChaudFroid.evaluate({ async: true }); + const chaudFroid = rollChaudFroid.total == 1; + return chaudFroid.total ? degre : -degre; + } + + static async getDirection(direction) { + const roll = new Roll(`1d16`); + await roll.evaluate({ async: true }); + switch (roll.total % 16) { + case 0: return 'Nord'; + case 1: return 'Nord Nord Est'; + case 2: return 'Nord Est'; + case 3: return 'Est Nord Est'; + case 4: return 'Est'; + case 5: return 'Est Sud Est'; + case 6: return 'Sud Est'; + case 7: return 'Sud Sud Est'; + case 8: return 'Sud'; + case 9: return 'Sud Sud Ouest'; + case 10: return 'Sud Ouest'; + case 11: return 'Ouest Sud Ouest'; + case 12: return 'Ouest'; + case 13: return 'Ouest Nord Ouest'; + case 14: return 'Nord Ouest'; + case 15: return 'Nord Nord Ouest'; + } + return undefined; + } + + static async getMeteo() { + const vent = await RdDMeteo.getForce(); + const mer = await RdDMeteo.getForce(); + const nuage = await RdDMeteo.getForce(); + const pluie = await RdDMeteo.getPluie(nuage); + const temperature = await RdDMeteo.getTemperature(); + const meteo = { + vent: { force: vent, direction: await RdDMeteo.getDirection(), }, + mer: { force: mer, direction: await RdDMeteo.getDirection(), }, + temperature: { force: temperature }, + nuage: { force: nuage, }, + pluie: { force: pluie }, + } + meteo.vent.description = RdDMeteo.vent(meteo.vent.force); + meteo.mer.description = RdDMeteo.mer(meteo.mer.force), + meteo.temperature.description = RdDMeteo.temperature(meteo.temperature.force); + meteo.nuage.description = RdDMeteo.nuage(meteo.nuage.force); + meteo.pluie.description = RdDMeteo.pluie(meteo.pluie.force); + + ChatMessage.create({ + content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-meteo.html', meteo), + whisper: ChatMessage.getWhisperRecipients('GM') + }); + } + + static description(liste, force, valeur = it => it.valeur) { + let select = liste.find(it => (it.min == undefined || it.min <= force) && (it.max == undefined || force <= it.max)); + return valeur(select ?? liste[0]); + } + + static vent(force) { return this.description(vents, force); } + static mer(force) { return this.description(mers, force); } + static nuage(force) { return this.description(nuages, force); } + static pluie(force) { return this.description(pluies, force); } + static temperature(force) { return this.description(temperatures, force); } +} \ No newline at end of file diff --git a/module/rdd-possession.js b/module/rdd-possession.js index 44a02423..ed5c88fa 100644 --- a/module/rdd-possession.js +++ b/module/rdd-possession.js @@ -139,18 +139,18 @@ export class RdDPossession { return; } - const defender = target.actor + const defender = target.actor; if ( !possession) { possession = this.searchPossessionFromEntite( attacker, defender) if ( !possession) { possession = await this.createPossession(attacker, defender) } } - possession = duplicate(possession) + possession = duplicate(possession); this.updateEtatPossession(possession) let rollData = { - competence: competence, + competence: competence.data.data.niveau >=0 ? competence : RdDPossession.competenceNonHautRevant(), possession: possession, possede: defender.name, possesseur: attacker.name, @@ -177,6 +177,19 @@ export class RdDPossession { dialog.render(true) } + static competenceNonHautRevant() { + return { + img: 'systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp', + name: 'non Haut-rêvant', + data: { + data: { + niveau: 0, + defaut_carac: "reve", + } + } + }; + } + /* -------------------------------------------- */ static async createPossession( attacker, defender ) { let possessionData = { diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 5185b0e2..f9acee4d 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -95,12 +95,15 @@ export class RdDTMRDialog extends Dialog { createPixiSprites() { EffetsDraconiques.carteTmr.createSprite(this.pixiTMR); this.updateTokens(); - this.demiReve = this._tokenDemiReve(); - this._updateDemiReve(); + this.forceDemiRevePositionView(); } - + /* -------------------------------------------- */ _createTokens() { + if (!this.isDemiReveCache()){ + this.demiReve = this._tokenDemiReve(); + this._trackToken(this.demiReve); + } let tokens = this._getTokensCasesTmr() .concat(this._getTokensRencontres()) .concat(this._getTokensSortsReserve()); @@ -154,9 +157,9 @@ export class RdDTMRDialog extends Dialog { return EffetsDraconiques.demiReve.token(this.pixiTMR, actorData, () => actorData.data.reve.tmrpos.coord); } - _updateDemiReve() { + forceDemiRevePositionView() { this.notifierResonanceSigneDraconique(this._getActorCoord()); - this._setTokenPosition(this.demiReve); + this._trackToken(this.demiReve); } _getActorCoord() { @@ -336,6 +339,10 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ async choisirCasePortee(coord, portee) { + if (this.actor.isTMRCache()) + { + return; + } // Récupère la liste des cases à portées let locList = TMRUtility.getTMRPortee(coord, portee); this.colorierZoneRencontre(locList); @@ -743,6 +750,7 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ async _maitriserTMR(rollData, callbackMaitrise) { this.minimize(); // Hide + rollData.isTMRCache = rollData.actor.isTMRCache(); const dialog = await RdDRoll.create(this.actor, rollData, { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html', @@ -874,49 +882,62 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ async _onClickTMRPos(clickOddq) { - if (this.isDemiReveCache()) { - ui.notifications.error(`Vous ne connaissez plus votre position dans les TMR. - Vous devez utiliser les boutons de direction pour vous déplacer. - Une fois que vous aurez retrouvé votre demi-rêve, demandez au gardien de vérifier et rendre les TMR visibles. - `); - return; - } - let currentOddq = TMRUtility.coordTMRToOddq(this._getActorCoord()); - - console.log("deplacerDemiReve >>>>", currentOddq, clickOddq); - let targetCoord = TMRUtility.oddqToCoordTMR(clickOddq); let currentCoord = TMRUtility.oddqToCoordTMR(currentOddq); - // Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter) let deplacementType = this._calculDeplacement(targetCoord, currentCoord, currentOddq, clickOddq); - // Si le deplacement est valide - if (deplacementType == 'normal' || deplacementType == 'saut') { - await this._deplacerDemiReve(targetCoord, deplacementType); - } else if (deplacementType == 'messager') { // Dans ce cas, ouverture du lancement de sort sur la case visée - await this._messagerDemiReve(targetCoord); - } else { - ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre"); - console.log("STATUS :", this.rencontreState, this.currentRencontre); + if (this.isDemiReveCache()) { + if (this.isTerreAttache(targetCoord) + || (this.isCaseHumide(currentCoord) && this.isCaseHumide(targetCoord)) + || deplacementType == 'changeur') + { + // déplacement possible + await this.actor.montreTMR(); + } + else + { + ui.notifications.error(`Vous ne connaissez plus votre position dans les TMR. + Vous devez utiliser les boutons de direction pour vous déplacer. + Une fois que vous aurez retrouvé votre demi-rêve, demandez au gardien de vérifier et rendre les TMR visibles. + `); + return; + } } + + switch (deplacementType){ + case 'normal': + await this._deplacerDemiReve(targetCoord, deplacementType); + break; + case 'messager': + await this._messagerDemiReve(targetCoord); + break; + case 'changeur': + case 'passeur': + await this._deplacerDemiReve(targetCoord, deplacementType); + break; + default: + ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre"); + console.log("STATUS :", this.rencontreState, this.currentRencontre); + } + this.checkQuitterTMR(); } /* -------------------------------------------- */ _calculDeplacement(targetCoord, currentCoord, fromOddq, toOddq) { + const isInArea = this.rencontreState == 'aucune' ? (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1) : this.currentRencontre?.locList.find(coord => coord == targetCoord) ?? false if (isInArea) { switch (this.rencontreState) { case 'aucune': return 'normal'; - case 'messager': return 'messager'; - case 'passeur': case 'changeur': return 'saut'; + case 'passeur': case 'changeur': case 'messager': return this.rencontreState; } } - return 'erreur' + return 'erreur'; } /* -------------------------------------------- */ @@ -932,9 +953,8 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - externalRefresh(tmrData) { + externalRefresh() { this.createPixiSprites(); - this.forceDemiRevePositionView(); this.updateValuesDisplay(); this.updateTokens(); console.log("TMR REFRESHED !!!"); @@ -946,23 +966,17 @@ export class RdDTMRDialog extends Dialog { this.nettoyerRencontre(); } let tmr = TMRUtility.getTMR(targetCoord); - //console.log("deplacerDemiReve", tmr, this); // Gestion cases spéciales type Trou noir, etc tmr = await this.manageTmrInnaccessible(tmr); await this.actor.updateCoordTMR(tmr.coord); - this._updateDemiReve(); + this.forceDemiRevePositionView(); if (ReglesOptionelles.isUsing("appliquer-fatigue")) { this.cumulFatigue += this.fatigueParCase; } this.updateValuesDisplay(); - game.socket.emit(SYSTEM_SOCKET_ID, { - msg: "msg_tmr_move", data: { - actorId: this.actor.data._id, - tmrPos: Misc.data(this.actor).data.reve.tmrpos - } - }); + this.actor.notifyRefreshTMR(); if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... await this.manageRencontre(tmr, () => this.postRencontre(tmr)); @@ -995,14 +1009,9 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async forceDemiRevePositionView() { - this._updateDemiReve(); - } - - /* -------------------------------------------- */ - async forceDemiRevePosition(coord) { + async positionnerDemiReve(coord) { await this.actor.updateCoordTMR(coord); - this._updateDemiReve(); + this.forceDemiRevePositionView(); let tmr = TMRUtility.getTMR(coord); await this.postRencontre(tmr); return tmr; @@ -1024,15 +1033,7 @@ export class RdDTMRDialog extends Dialog { _getCaseRectangleCoord(coord) { return this.pixiTMR.getCaseRectangle(TMRUtility.coordTMRToOddq(coord)); } - - /* -------------------------------------------- */ - _setTokenPosition(token) { - if (this.isDemiReveCache() && this.demiReve === token ) { - return; - } - this.pixiTMR.setPosition(token.sprite, TMRUtility.coordTMRToOddq(token.coordTMR())); - } - + /* -------------------------------------------- */ _removeTokens(filter) { const tokensToRemove = this.allTokens.filter(filter); @@ -1040,10 +1041,13 @@ export class RdDTMRDialog extends Dialog { this.pixiApp.stage.removeChild(token.sprite); } } - + /* -------------------------------------------- */ _trackToken(token) { + if (this.demiReve === token && this.isDemiReveCache()) { + return; + } + this.pixiTMR.setPosition(token.sprite, TMRUtility.coordTMRToOddq(token.coordTMR())); this.allTokens.push(token); - this._setTokenPosition(token); } } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 786ad9b1..7e5cd962 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -221,8 +221,10 @@ export class RdDUtility { ]; Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null')); + Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null')); Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? 'NULL'); Handlebars.registerHelper('le', str => Grammar.articleDetermine(str)); + Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str)); Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str)); Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args)); Handlebars.registerHelper('buildConteneur', (objet) => { return new Handlebars.SafeString(RdDUtility.buildConteneur(objet)); }); @@ -666,7 +668,7 @@ export class RdDUtility { case "msg_tmr_move": let actor = game.actors.get(sockmsg.data.actorId); if (actor.isOwner || game.user.isGM) { - actor.refreshTMRView(sockmsg.data.tmrPos); + actor.refreshTMRView(); } break; } @@ -681,7 +683,7 @@ export class RdDUtility { let coord = event.currentTarget.attributes['data-tmr-coord'].value; let actorId = event.currentTarget.attributes['data-actor-id'].value; let actor = game.actors.get(actorId); - actor.tmrApp.forceDemiRevePosition(coord); + actor.tmrApp.positionnerDemiReve(coord); }); // Gestion spécifique des sorts en réserve multiples (ie têtes) html.on("click", '#sort-reserve', event => { diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js index af2621ed..7f362978 100644 --- a/module/tmr-rencontres.js +++ b/module/tmr-rencontres.js @@ -8,9 +8,14 @@ import { TMRType } from "./tmr-utility.js"; const typeRencontres = { messager: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`, - msgEchec: (rencData) => `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`, - postSucces: (tmrDialog, rencData) => { + msgSucces: async (rencData) => { + if (rencData.actor.isTMRCache()){ + return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort, mais vous ne savez pas où vous êtes.`; + } + return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`; + }, + msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`, + postSucces: async (tmrDialog, rencData) => { tmrDialog.setStateRencontre(rencData.rencontre.type); tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force); }, @@ -28,9 +33,14 @@ const typeRencontres = { }, passeur: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.tmr.label}.`, - msgEchec: (rencData) => `Le prix que demande le ${rencData.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`, - postSucces: (tmrDialog, rencData) => { + msgSucces: async (rencData) => { + if (rencData.actor.isTMRCache()){ + return `Le ${rencData.rencontre.name} vous propose de vous transporter, mais vous ne savez pas où vous êtes.`; + } + return `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.tmr.label}.`; + }, + msgEchec: async (rencData)=> `Le prix que demande le ${rencData.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`, + postSucces: async (tmrDialog, rencData) => { tmrDialog.setStateRencontre(rencData.rencontre.type); tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force); }, @@ -49,9 +59,9 @@ const typeRencontres = { }, fleur: { - msgSucces: (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`, - msgEchec: (rencData) => `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`, - postSucces: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force), + msgSucces: async (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`, + msgEchec: async (rencData)=> `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`, + postSucces: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force), poesieSucces: { reference: "L'Ennemi, Charles Baudelaire", extrait: `Et qui sait si les fleurs nouvelles que je rêve @@ -66,9 +76,9 @@ const typeRencontres = { }, mangeur: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} claque de sa machoire dans le vide avant de fuir.`, - msgEchec: (rencData) => `Le ${rencData.rencontre.name} croque votre Rêve ! Il emporte ${rencData.rencontre.force} de vos points de rêve actuels`, - postEchec: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force), + msgSucces: async (rencData) => `Le ${rencData.rencontre.name} claque de sa machoire dans le vide avant de fuir.`, + msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} croque votre Rêve ! Il emporte ${rencData.rencontre.force} de vos points de rêve actuels`, + postEchec: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force), poesieSucces: { reference: "Conseil, Victor Hugo", extrait: `Rois ! la bure est souvent jalouse du velours. @@ -85,16 +95,17 @@ const typeRencontres = { }, changeur: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[rencData.tmr.type].name} de votre choix en échange de sa liberté.`, - msgEchec: (rencData) => { - rencData.newTMR = TMRUtility.getTMRAleatoire(it => it.type = rencData.tmr.type); - return `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte en ${rencData.newTMR.label} sans attendre votre avis.`; - }, - postSucces: (tmrDialog, rencData) => { + msgSucces: async (rencData) => `Le ${rencData.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[rencData.tmr.type].name} de votre choix en échange de sa liberté.`, + msgEchec: async (rencData) => `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte sur une autre ${TMRType[rencData.tmr.type].name} sans attendre votre avis.`, + postSucces: async (tmrDialog, rencData) => { tmrDialog.setStateRencontre(rencData.rencontre.type); tmrDialog.choisirCaseType(rencData.tmr.type); }, - postEchec: (tmrDialog, rencData) => tmrDialog.forceDemiRevePosition(rencData.newTMR.coord), + postEchec: async (tmrDialog, rencData) => { + const newTMR = await TMRUtility.getTMRAleatoire(it => it.type == rencData.tmr.type && it.coord != rencData.tmr.coord); + await tmrDialog.actor.forcerPositionTMRInconnue(newTMR); + tmrDialog.positionnerDemiReve(newTMR.coord); + }, poesieSucces: { reference: "Caligula - IIIème chant, Gérard de Nerval", extrait: `Allez, que le caprice emporte @@ -111,9 +122,9 @@ const typeRencontres = { }, briseur: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`, - msgEchec: (rencData) => `Le ${rencData.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`, - postEchec: (tmrDialog, rencData) => tmrDialog.close(), + msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`, + msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`, + postEchec: async (tmrDialog, rencData) => tmrDialog.close(), poesieSucces: { reference: "Rêve de Dragon, Denis Gerfaud", extrait: `La légende affirme que ce sont les Gnomes qui furent @@ -134,8 +145,8 @@ const typeRencontres = { }, reflet: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} s'estompe dans l'oubli.`, - msgEchec: (rencData) => `Vous êtes submergé par un ${rencData.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`, + msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'estompe dans l'oubli.`, + msgEchec: async (rencData)=> `Vous êtes submergé par un ${rencData.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`, poesieSucces: { reference: "Une charogne, Charles Baudelaire", extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve, @@ -152,9 +163,9 @@ const typeRencontres = { }, passeurfou: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`, - msgEchec: (rencData) => TMRRencontres.msgEchecPasseurFou(rencData), - postEchec: (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData), + msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`, + msgEchec: async (rencData)=> TMRRencontres.msgEchecPasseurFou(rencData), + postEchec: async (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData), poesieSucces: { reference: "Un Fou et un Sage, Jean de La Fontaine", extrait: `Certain Fou poursuivait à coups de pierre un Sage. @@ -174,9 +185,9 @@ const typeRencontres = { }, tbblanc: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`, - msgEchec: (rencData) => `Le souffle du ${rencData.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`, - postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1), + msgSucces: async (rencData) => `Le ${rencData.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`, + msgEchec: async (rencData)=> `Le souffle du ${rencData.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`, + postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1), poesieSucces: { reference: "Rêve de Dragon, Denis Gerfaud", extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement @@ -191,9 +202,9 @@ const typeRencontres = { }, tbnoir: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`, - msgEchec: (rencData) => `Le ${rencData.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`, - postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 2), + msgSucces: async (rencData) => `Le ${rencData.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`, + msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`, + postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 2), poesieSucces: { reference: "Rêve de Dragon, Denis Gerfaud", extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les @@ -207,9 +218,9 @@ const typeRencontres = { }, tbrouge: { - msgSucces: (rencData) => `Le ${rencData.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`, - msgEchec: (rencData) => `Le ${rencData.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`, - postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData), + msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`, + msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`, + postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData), poesieSucces: { reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet", extrait: `Qu'est-ce de votre vie ? un tourbillon rouant @@ -228,10 +239,10 @@ const typeRencontres = { }, rdd: { - msgSucces: (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${rencData.rencontre.force} points de rêve`, - msgEchec: (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${rencData.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`, - postSucces: (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData), - postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData), + msgSucces: async (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${rencData.rencontre.force} points de rêve`, + msgEchec: async (rencData)=> `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${rencData.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`, + postSucces: async (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData), + postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData), poesieSucces: { reference: "Rêve de Dragon, Denis Gerfaud", extrait: `Le monde est Rêve de Dragons, mais nous ne savons @@ -404,7 +415,7 @@ export class TMRRencontres { static async gererRencontre(tmrDialog, rencData) { let gestion = TMRRencontres.getGestionRencontre(rencData.rencontre.type); if (rencData.rolled.isSuccess) { - rencData.message = gestion.msgSucces(rencData); + rencData.message = await gestion.msgSucces(rencData); if (rencData.nbRounds > 1) { rencData.message += ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`; } @@ -412,7 +423,7 @@ export class TMRRencontres { return gestion.postSucces; } - rencData.message = gestion.msgEchec(rencData); + rencData.message = await gestion.msgEchec(rencData); if (rencData.nbRounds > 1) { rencData.message += ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`; } @@ -444,7 +455,7 @@ export class TMRRencontres { if (tmrData.sortReserve) { await tmrDialog.processSortReserve(tmrData.sortReserve); } - await tmrDialog.forceDemiRevePosition(tmrData.newTMR.coord); + await tmrDialog.positionnerDemiReve(tmrData.newTMR.coord); if (tmrData.sortReserve) { tmrDialog.close(); } @@ -469,7 +480,7 @@ export class TMRRencontres { for (let i = 0; i < cases; i++) { coord = await TMRUtility.deplaceTMRAleatoire(actor, coord).coord; } - await tmrDialog.forceDemiRevePosition(coord) + await tmrDialog.positionnerDemiReve(coord) } /* -------------------------------------------- */ diff --git a/module/tmr/draconique.js b/module/tmr/draconique.js index 9ca5848e..caeeecd9 100644 --- a/module/tmr/draconique.js +++ b/module/tmr/draconique.js @@ -94,9 +94,8 @@ export class Draconique { token[type ?? this.code()] = linkData; pixiTMR.addTooltip(token.sprite, this.tooltip(linkData)); return token; - - return sprite; } + /** * factory d'élément graphique PIXI correpsondant à l'objet draconique * @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks. diff --git a/templates/chat-resultat-maitrise-tmr.html b/templates/chat-resultat-maitrise-tmr.html index 97882ce8..dbabbbe1 100644 --- a/templates/chat-resultat-maitrise-tmr.html +++ b/templates/chat-resultat-maitrise-tmr.html @@ -1,6 +1,11 @@ {{competence.name}}

- {{alias}} tente de {{maitrise.verbe}} {{le tmr.genre}} {{tmr.label}} ({{tmr.coord}}) + {{alias}} tente de {{maitrise.verbe}} {{le tmr.genre}} + {{#if isTMRCache}} + {{caseTmr-type tmr.coord}} + {{else}} + {{tmr.label}} ({{tmr.coord}}) + {{/if}}

{{#if previous}} {{#with previous}} @@ -11,15 +16,20 @@ {{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
-{{#if rolled.isSuccess}} - {{alias}} parvient à {{maitrise.verbe}} {{le tmr.genre}} {{tmr.label}} ! + {{alias}} + {{#if rolled.isSuccess}}parvient à{{else}}échoue à{{/if}} + {{maitrise.verbe}} {{le tmr.genre}} + {{#if isTMRCache}} + {{caseTmr-type tmr.coord}} {{else}} - {{alias}} échoue à {{maitrise.verbe}} {{le tmr.genre}} {{tmr.label}}. - {{alias}} quitte les Terres Médianes ! - {{#if souffle}} -
De plus, son échec total lui fait subir un Souffle de Dragon : {{souffle.name}} + {{tmr.label}} ({{tmr.coord}}) + {{/if}}! + {{#if rolled.isEchec}} + {{alias}} quitte les Terres Médianes ! + {{#if souffle}} +
De plus, son échec total lui fait subir un Souffle de Dragon : {{souffle.name}} + {{/if}} {{/if}} -{{/if}}
{{#if poesie}}
diff --git a/templates/chat-resultat-meteo.html b/templates/chat-resultat-meteo.html new file mode 100644 index 00000000..96d7e4b8 --- /dev/null +++ b/templates/chat-resultat-meteo.html @@ -0,0 +1,9 @@ +Météo +

Météo aléatoire

+