From 1cb4a7dbf5b4669ced747acecfbb14f077a787fd Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Fri, 12 Feb 2021 01:11:03 +0100 Subject: [PATCH 1/3] Small cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - extrait de méthode pour tirage dans un array - utilisation des operateur ?: / ?? --- module/actor.js | 12 ++++----- module/misc.js | 8 ++++++ module/poetique.js | 3 ++- module/rdd-namegen.js | 5 ++-- module/rdd-tmr-dialog.js | 47 +++++++++++++--------------------- module/tmr-rencontres.js | 18 ++++++------- module/tmr-utility.js | 55 ++++++++++++++++++++-------------------- 7 files changed, 70 insertions(+), 78 deletions(-) diff --git a/module/actor.js b/module/actor.js index ed4258c5..42ca2438 100644 --- a/module/actor.js +++ b/module/actor.js @@ -2708,25 +2708,23 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async resetItemUse( ) { - await this.setFlag('foundryvtt-reve-de-dragon', 'itemUse', null ); + await this.unsetFlag('foundryvtt-reve-de-dragon', 'itemUse'); await this.setFlag('foundryvtt-reve-de-dragon', 'itemUse', {} ); } /* -------------------------------------------- */ async incItemUse( itemId ) { - let itemUse = this.getFlag('foundryvtt-reve-de-dragon', 'itemUse'); - itemUse = (itemUse) ? duplicate(itemUse) : {}; - itemUse[itemId] = (itemUse[itemId]) ? itemUse[itemId] + 1 : 1; + let itemUse = duplicate(this.getFlag('foundryvtt-reve-de-dragon', 'itemUse') ?? {}); + itemUse[itemId] = (itemUse[itemId] ?? 0) + 1; await this.setFlag( 'foundryvtt-reve-de-dragon', 'itemUse', itemUse); console.log("ITEM USE INC", itemUse); } /* -------------------------------------------- */ getItemUse( itemId ) { - let itemUse = this.getFlag('foundryvtt-reve-de-dragon', 'itemUse'); - itemUse = (itemUse) ? itemUse : {}; + let itemUse = this.getFlag('foundryvtt-reve-de-dragon', 'itemUse') ?? {}; console.log("ITEM USE GET", itemUse); - return itemUse[itemId] ? itemUse[itemId] : 0; + return itemUse[itemId] ?? 0; } /* -------------------------------------------- */ diff --git a/module/misc.js b/module/misc.js index 50566a09..f1220c35 100644 --- a/module/misc.js +++ b/module/misc.js @@ -59,4 +59,12 @@ export class Misc { } } + static rollOneOf(array) { + return array[new Roll("1d" + array.length).evaluate().total - 1]; + } + + static distinct(array) { + return [...new Set(array)]; + } + } \ No newline at end of file diff --git a/module/poetique.js b/module/poetique.js index 67f0d387..58127bf8 100644 --- a/module/poetique.js +++ b/module/poetique.js @@ -1,3 +1,4 @@ +import { Misc } from "./misc.js" const poesieHautReve = [ { @@ -64,7 +65,7 @@ const poesieHautReve = [ export class Poetique { static getExtrait(){ - return poesieHautReve[new Roll("1d" + poesieHautReve.length).evaluate().total - 1] + return Misc.rollOneOf(poesieHautReve); } } \ No newline at end of file diff --git a/module/rdd-namegen.js b/module/rdd-namegen.js index dd59097f..a5e6d05c 100644 --- a/module/rdd-namegen.js +++ b/module/rdd-namegen.js @@ -1,3 +1,4 @@ +import { Grammar } from "./grammar.js"; import { Misc } from "./misc.js"; const words = [ 'pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', 'onse', 'iane', 'ane', 'zach', 'arri', 'ba', 'bo', 'bi', @@ -7,9 +8,7 @@ const words = [ 'pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', export class RdDNameGen { static getName( msg, params ) { - let max = words.length; - let name = words[new Roll("1d"+max+" -1").roll().total]; - name += words[new Roll("1d"+max+" -1").roll().total]; + let name = Misc.upperFirst( Misc.rollOneOf(words) + Misc.rollOneOf(words) ) //console.log(name); ChatMessage.create( { content: `Nom : ${name}`, whisper: ChatMessage.getWhisperRecipients("GM") } ); } diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index db874e8e..05bf2113 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -449,8 +449,8 @@ export class RdDTMRDialog extends Dialog { forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } }, maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' } } + rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true: undefined, rollData.competence.data.defaut_carac = 'reve-actuel'; - await this._rollMaitriseCaseHumide(rollData); } } @@ -465,8 +465,9 @@ export class RdDTMRDialog extends Dialog { rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); } this.toclose = rollData.rolled.isEchec; - if (rollData.rolled.isSuccess && !rollData.previous && EffetsDraconiques.isDoubleResistanceFleuve(this.actor)) { + if (rollData.rolled.isSuccess && rollData.double) { rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements }; + rollData.double = undefined; await this._rollMaitriseCaseHumide(rollData); return; } @@ -513,7 +514,7 @@ export class RdDTMRDialog extends Dialog { } return false; } - + /* -------------------------------------------- */ async conquerirCiteFermee(tmr) { if (this.viewOnly || this.currentRencontre) { @@ -601,8 +602,8 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - lancerSortEnReserve(coordTMR, sortId) { - let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR); + lancerSortEnReserve(coord, sortId) { + let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord); let sortReserve = sortReserveList.find(sortReserve => sortReserve.sort._id == sortId); //console.log("SORT RESA", sortReserveList, coordTMR, sortId, sortReserve); if (sortReserve) { @@ -620,10 +621,10 @@ export class RdDTMRDialog extends Dialog { await this.actor.deleteSortReserve(sortReserve); this.updateSortReserve(); console.log("declencheSortEnReserve", sortReserve) - const declenchementSort = "Vous avez déclenché le sort " + sortReserve.sort.name - + " en réserve en " + sortReserve.coord + " (" + TMRUtility.getTMR(sortReserve.coord).label - + ") avec " + sortReserve.sort.data.ptreve_reel + " points de Rêve"; - this._tellToGM(declenchementSort); + this._tellToGM(`Vous avez déclenché le sort en réserve ${sortReserve.sort.name} + avec ${sortReserve.sort.data.ptreve_reel} points de Rêve + en ${sortReserve.coord} (${TMRUtility.getTMRLabel(sortReserve.coord)}) + `); this.close(); } @@ -700,35 +701,21 @@ export class RdDTMRDialog extends Dialog { console.log("deplacerDemiReve >>>>", currentPos, eventPos); - let targetCoordTMR = TMRUtility.convertToTMRCoord(eventPos); - let currentCoordTMR = TMRUtility.convertToTMRCoord(currentPos); + let targetCoord = TMRUtility.convertToTMRCoord(eventPos); + let currentCoord = TMRUtility.convertToTMRCoord(currentPos); // 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 (this.isTerreAttache(targetCoordTMR) || this.isConnaissanceFleuve(currentCoordTMR, targetCoordTMR) || !RdDTMRDialog._horsDePortee(currentPos, eventPos)) { - deplacementType = 'normal'; - } - } else { - deplacementType = this.processClickPostRencontre(targetCoordTMR); - } + let deplacementType = this._calculDeplacement(targetCoord, currentCoord, currentPos, eventPos); + // Si le deplacement est valide if (deplacementType == 'normal' || deplacementType == 'saut') { - await this._deplacerDemiReve(targetCoordTMR, deplacementType); - + await this._deplacerDemiReve(targetCoord, deplacementType); } else if (deplacementType == 'messager') { // Dans ce cas, ouverture du lancement de sort sur la case visée - /* - TODO: si la case a un sort en réserve, lancer ce sort. - 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 this._messagerDemiReve(targetCoordTMR); - + await this._messagerDemiReve(targetCoord); } else { ui.notifications.error("Vous ne pouvez vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre"); console.log("STATUS :", this.rencontreState, this.currentRencontre); } - this.checkQuitterTMR(); } @@ -757,7 +744,7 @@ export class RdDTMRDialog extends Dialog { game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_tmr_move", data: { actorId: this.actor.data._id, - tmrPos: tmrPos + tmrPos: this.actor.data.data.reve.tmrpos } }); diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js index a3883396..2b6632ec 100644 --- a/module/tmr-rencontres.js +++ b/module/tmr-rencontres.js @@ -1,5 +1,6 @@ import { DeDraconique } from "./de-draconique.js"; import { Grammar } from "./grammar.js"; +import { Misc } from "./misc.js"; import { TMRUtility } from "./tmr-utility.js"; import { TMRType } from "./tmr-utility.js"; @@ -367,10 +368,10 @@ export class TMRRencontres { /* -------------------------------------------- */ static async getMauvaiseRencontre(index = undefined) { - if (index == undefined || index >= mauvaisesRencontres.length) { - index = new Roll("1d" + mauvaisesRencontres.length).roll().total - 1; - } - const rencontre = duplicate(mauvaisesRencontres[index]); + const rencontre = duplicate( + (index && index>=0 && index < mauvaisesRencontres.length) + ? mauvaisesRencontres[index] + : Misc.rollOneOf(mauvaisesRencontres)); await TMRRencontres.evaluerForceRencontre(rencontre); return rencontre; } @@ -408,15 +409,15 @@ export class TMRRencontres { data.message = gestion.msgSucces(data); if (data.nbRounds > 1) { data.message += ` Au total, vous avez passé ${data.nbRounds} rounds à vous battre!`; - } + } data.poesie = gestion.poesieSucces; return gestion.postSucces; } - + data.message = gestion.msgEchec(data); if (data.nbRounds > 1) { data.message += ` Vous avez passé ${data.nbRounds} rounds à lutter!`; - } + } data.poesie = gestion.poesieEchec; return gestion.postEchec; } @@ -428,8 +429,7 @@ export class TMRRencontres { data.newTMR = TMRUtility.getTMR(data.sortReserve.coord); } else { // Déplacement aléatoire de la force du Passeur Fou - const locList = TMRUtility.getTMRPortee(data.tmr.coord, data.rencontre.force); - const newCoord = locList[new Roll("1d" + locList.length).evaluate().total - 1]; + const newCoord = Misc.rollOneOf(TMRUtility.getTMRPortee(data.tmr.coord, data.rencontre.force)); data.newTMR = TMRUtility.getTMR(newCoord); } if (data.sortReserve) { diff --git a/module/tmr-utility.js b/module/tmr-utility.js index a2d2d013..523008e7 100644 --- a/module/tmr-utility.js +++ b/module/tmr-utility.js @@ -1,6 +1,4 @@ -import { DeDraconique } from "./de-draconique.js"; import { TMRRencontres } from "./tmr-rencontres.js"; -import { Grammar } from "./grammar.js"; import { Misc } from "./misc.js"; /* -------------------------------------------- */ @@ -270,6 +268,7 @@ export const tmrColors = { sort: 0xFF8800, tetes: 0xA000FF, souffle: 0x804040, + queues: 0xAA4040, trounoir: 0x401060, demireve: 0x00FFEE, rencontre: 0xFF0000, @@ -283,7 +282,9 @@ export const tmrColors = { export class TMRUtility { static init() { for (let coord in TMRMapping) { - TMRMapping[coord].coord = coord; + const tmr = TMRMapping[coord]; + tmr.coord = coord; + tmr.genre = TMRType[tmr.type].genre; } let tmrByType = Misc.classify(Object.values(TMRMapping)); for (const [type, list] of Object.entries(tmrByType)) { @@ -317,9 +318,14 @@ export class TMRUtility { } /* -------------------------------------------- */ - static getTMR(coordTMR) { - return TMRMapping[coordTMR]; + static getTMR(coord) { + return TMRMapping[coord]; } + + static getTMRLabel(coord) { + return TMRMapping[coord]?.label ?? (coord+": case inconnue"); + } + static isCaseHumide(tmr) { return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais'; } @@ -355,22 +361,21 @@ export class TMRUtility { /* -------------------------------------------- */ static getDirectionPattern() { - let roll = new Roll("1d" + tmrRandomMovePatten.length).evaluate().total; - return tmrRandomMovePatten[roll - 1]; + return Misc.rollOneOf(tmrRandomMovePatten); } - static deplaceTMRAleatoire(coord) { - return TMRUtility.deplaceTMRSelonPattern(coord, TMRUtility.getDirectionPattern(), 1); + static deplaceTMRAleatoire(actor, coord) { + return TMRUtility.deplaceTMRSelonPattern(actor, coord, TMRUtility.getDirectionPattern(), 1); } /* -------------------------------------------- */ - static deplaceTMRSelonPattern(coord, direction, nTime) { + static async deplaceTMRSelonPattern(actor, coord, direction, nTime) { for (let i = 0; i < nTime; i++) { - let currentPosXY = TMRUtility.convertToCellPos(coord); - currentPosXY.x = currentPosXY.x + direction.x; - currentPosXY.y = currentPosXY.y + direction.y; - if (this._checkTMRCoord(currentPosXY.x, currentPosXY.y)) { // Sortie de carte ! Ré-insertion aléatoire - coord = TMRUtility.convertToTMRCoord(currentPosXY); + let currentPos = TMRUtility.convertToCellPos(coord); + currentPos.x = currentPos.x + direction.x; + currentPos.y = currentPos.y + direction.y; + if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Sortie de carte ! Ré-insertion aléatoire + coord = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos)); } else { coord = this.getTMRAleatoire().coord; } @@ -392,10 +397,8 @@ export class TMRUtility { return TMRUtility.filterTMR(filter).map(it => it.coord); } - static getTMRAleatoire(filter = undefined) { - let list = TMRUtility.filterTMR(filter); - let index = new Roll("1d" + list.length).evaluate().total - 1; - return list[index]; + static getTMRAleatoire(filter = it => true) { + return Misc.rollOneOf(TMRUtility.filterTMR(filter)) } /* -------------------------------------------- */ @@ -433,21 +436,17 @@ export class TMRUtility { /** Returns a list of case inside a given distance * */ - static getTMRPortee(centerCoord, portee) { - return TMRUtility.getTMRArea(centerCoord, portee, tmrConstants); - } - - static getTMRArea(centerCoord, distance, tmrConstants) { - let centerPos = this.convertToCellPos(centerCoord); + static getTMRPortee(coord, portee) { + let centerPos = this.convertToCellPos(coord); let posPic = this.computeRealPictureCoordinates(centerPos, tmrConstants); let caseList = []; - for (let dx = -distance; dx <= distance; dx++) { // Loop thru lines - for (let dy = -distance; dy <= distance; dy++) { // Loop thru lines + for (let dx = -portee; dx <= portee; dx++) { // Loop thru lines + for (let dy = -portee; dy <= portee; 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) { + if (dist < portee + 0.5) { caseList.push(this.convertToTMRCoord(currentPos)); // Inside the area } } From 42bd63c999f511e0eea629d19db330c7c604c46c Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Fri, 12 Feb 2021 01:16:02 +0100 Subject: [PATCH 2/3] simplifications sur EffetsDraconiques MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ajout de methode tmrLabel pour les tooltips ajout de l'item en paramètre aux ajouts/suppressions ajout d'un 'sourceId' pour les casetmr liées à un souffle/queue/tête --- module/tmr/debordement.js | 2 +- module/tmr/draconique.js | 16 ++++++++++++---- module/tmr/effets-draconiques.js | 3 ++- module/tmr/fermeture-cites.js | 2 +- module/tmr/pont-impraticable.js | 2 +- module/tmr/present-cites.js | 10 +++++----- module/tmr/quete-eaux.js | 2 +- module/tmr/reserve-extensible.js | 2 +- module/tmr/terre-attache.js | 2 +- module/tmr/trou-noir.js | 2 +- template.json | 3 ++- 11 files changed, 28 insertions(+), 18 deletions(-) diff --git a/module/tmr/debordement.js b/module/tmr/debordement.js index c4c257b5..432f4b7f 100644 --- a/module/tmr/debordement.js +++ b/module/tmr/debordement.js @@ -13,7 +13,7 @@ export class Debordement extends Draconique { async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } code() { return 'debordement' } - tooltip(linkData) { return `Débordement en ${TMRUtility.getTMR(linkData.data.coord).label}` } + tooltip(linkData) { return `Débordement en ${this.tmrLabel(linkData)}` } img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' } _createSprite(pixiTMR) { diff --git a/module/tmr/draconique.js b/module/tmr/draconique.js index 0dacd3c3..aa566371 100644 --- a/module/tmr/draconique.js +++ b/module/tmr/draconique.js @@ -1,3 +1,4 @@ +import { TMRUtility } from "../tmr-utility.js"; import { PixiTMR } from "./pixi-tmr.js"; const registeredEffects = [ @@ -14,6 +15,8 @@ export class Draconique static isTeteDragon(element) { return element.type == 'tete'; } static isQueueSouffle(it) { return Draconique.isQueueDragon(it) || Draconique.isSouffleDragon(it); } + tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.data.coord); } + static register(draconique) { registeredEffects[draconique.code()] = draconique; if (draconique.img()) { @@ -48,10 +51,10 @@ export class Draconique * Méthode responsable de gérer une draconique (par exemple, ajouter des casetmr pour la fermeture des cités). * @param actor auquel la draconique est ajoutée */ - async onActorCreateOwned(actor) { + async onActorCreateOwned(actor, item) { return false; } - async onActorDeleteOwned(actor) { + async onActorDeleteOwned(actor, item) { return false; } /** @@ -108,10 +111,15 @@ export class Draconique return Draconique.isCaseTMR(it) && it.data.specific == this.code() && (coord ? it.data.coord == coord : true); } - async createCaseTmr(actor, label, tmr) { + find(list, coord = undefined) { + return list.find(c => this.isCase(c, coord)); + } + + + async createCaseTmr(actor, label, tmr, sourceId=undefined) { await actor.createOwnedItem({ name: label, type: 'casetmr', img: this.img(), _id: randomID(16), - data: { coord: tmr.coord, specific: this.code() } + data: { coord: tmr.coord, specific: this.code(), sourceid:sourceId } }); } diff --git a/module/tmr/effets-draconiques.js b/module/tmr/effets-draconiques.js index cec1edb3..b9745acb 100644 --- a/module/tmr/effets-draconiques.js +++ b/module/tmr/effets-draconiques.js @@ -45,7 +45,8 @@ export class EffetsDraconiques { /* -------------------------------------------- */ static isCaseInondee(caseTMR, coord) { - return EffetsDraconiques.debordement.isCase(caseTMR, coord) || EffetsDraconiques.pontImpraticable.isCase(caseTMR, coord); + return EffetsDraconiques.debordement.isCase(caseTMR, coord) || + EffetsDraconiques.pontImpraticable.isCase(caseTMR, coord); } static isCaseTrouNoir(caseTMR, coord) { diff --git a/module/tmr/fermeture-cites.js b/module/tmr/fermeture-cites.js index dc95bc37..0357c8ad 100644 --- a/module/tmr/fermeture-cites.js +++ b/module/tmr/fermeture-cites.js @@ -13,7 +13,7 @@ export class FermetureCites extends Draconique { async onActorCreateOwned(actor, item) { await this._fermerLesCites(actor); } code() { return 'fermeture' } - tooltip(linkData) { return `La ${TMRUtility.getTMR(linkData.data.coord).label} est fermée` } + tooltip(linkData) { return `La ${this.tmrLabel(linkData)} est fermée` } img() { return 'icons/svg/door-closed.svg' } _createSprite(pixiTMR) { diff --git a/module/tmr/pont-impraticable.js b/module/tmr/pont-impraticable.js index f9251742..1bd6ea94 100644 --- a/module/tmr/pont-impraticable.js +++ b/module/tmr/pont-impraticable.js @@ -14,7 +14,7 @@ export class PontImpraticable extends Draconique { async onActorDeleteOwned(actor, item) { await this._supprimerCaseTmr(actor); } code() { return 'pont-impraticable' } - tooltip(linkData) { return `${TMRUtility.getTMR(linkData.data.coord).label} impraticable` } + tooltip(linkData) { return `${this.tmrLabel(linkData)} impraticable` } img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' } _createSprite(pixiTMR) { diff --git a/module/tmr/present-cites.js b/module/tmr/present-cites.js index 105f7bba..4cb0135e 100644 --- a/module/tmr/present-cites.js +++ b/module/tmr/present-cites.js @@ -14,25 +14,25 @@ export class PresentCites extends Draconique { async onActorCreateOwned(actor, item) { await this._ajouterPresents(actor); } code() { return 'present-cites' } - tooltip(linkData) { return `La ${TMRUtility.getTMR(linkData.data.coord).label} a un présent` } + tooltip(linkData) { return `La ${this.tmrLabel(linkData)} a un présent` } img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/gift.svg' } _createSprite(pixiTMR) { return pixiTMR.sprite(this.code(), { - color: tmrColors.tetes, alpha: 0.7, taille: tmrConstants.third, decallage:tmrConstants.topRight + color: tmrColors.tetes, alpha: 0.7, taille: tmrConstants.third, decallage: tmrConstants.topRight }); } async _ajouterPresents(actor) { let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); - if (existants.length >0 ) { + if (existants.length > 0) { ChatMessage.create({ - whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user), + whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), content: "Vous avez encore des présents dans des cités, vous devrez tirer une autre tête pour remplacer celle ci!" }) } - else{ + else { let cites = TMRUtility.filterTMR(it => it.type == 'cite'); for (let tmr of cites) { await this.createCaseTmr(actor, 'Présent: ' + tmr.label, tmr); diff --git a/module/tmr/quete-eaux.js b/module/tmr/quete-eaux.js index 481502c9..c0a67c79 100644 --- a/module/tmr/quete-eaux.js +++ b/module/tmr/quete-eaux.js @@ -12,7 +12,7 @@ export class QueteEaux extends Draconique { async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } code() { return 'maitrisee' } - tooltip(linkData) { return `Quête des eaux, le ${TMRUtility.getTMR(linkData.data.coord).label} est maîtrisé` } + tooltip(linkData) { return `Quête des eaux, le ${this.tmrLabel(linkData)} est maîtrisé` } img() { return 'icons/svg/bridge.svg' } _createSprite(pixiTMR) { diff --git a/module/tmr/reserve-extensible.js b/module/tmr/reserve-extensible.js index 7fbce50f..47df6181 100644 --- a/module/tmr/reserve-extensible.js +++ b/module/tmr/reserve-extensible.js @@ -12,7 +12,7 @@ export class ReserveExtensible extends Draconique { async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } code() { return 'reserve_extensible' } - tooltip(linkData) { return `Réserve extensible en ${TMRUtility.getTMR(linkData.data.coord).label} !` } + tooltip(linkData) { return `Réserve extensible en ${this.tmrLabel(linkData)} !` } img() { return 'icons/svg/chest.svg' } _createSprite(pixiTMR) { diff --git a/module/tmr/terre-attache.js b/module/tmr/terre-attache.js index 34416fec..e5f913b1 100644 --- a/module/tmr/terre-attache.js +++ b/module/tmr/terre-attache.js @@ -12,7 +12,7 @@ export class TerreAttache extends Draconique { async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } code() { return 'attache' } - tooltip(linkData) { return `Terre d'attache en ${TMRUtility.getTMR(linkData.data.coord).label} !` } + tooltip(linkData) { return `Terre d'attache en ${this.tmrLabel(linkData)} !` } img() { return 'icons/svg/anchor.svg' } _createSprite(pixiTMR) { diff --git a/module/tmr/trou-noir.js b/module/tmr/trou-noir.js index 02637da1..79c97830 100644 --- a/module/tmr/trou-noir.js +++ b/module/tmr/trou-noir.js @@ -12,7 +12,7 @@ export class TrouNoir extends Draconique { async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } code() { return 'trounoir' } - tooltip(linkData) { return `Trou noir en ${TMRUtility.getTMR(linkData.data.coord).label} !` } + tooltip(linkData) { return `Trou noir en ${this.tmrLabel(linkData)} !` } img() { return 'icons/svg/explosion.svg' } _createSprite(pixiTMR) { diff --git a/template.json b/template.json index 17852e84..7f976010 100644 --- a/template.json +++ b/template.json @@ -764,7 +764,8 @@ "type": "", "label": "", "specific": "", - "description": "" + "description": "", + "sourceid":"" }, "recettealchimique": { "but": "", From 5328d2b690dcac263feb172281940187f904f5f7 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Fri, 12 Feb 2021 01:44:27 +0100 Subject: [PATCH 3/3] Gestion queues/souffles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - débordement - conquête --- module/actor.js | 25 +++- module/rdd-tmr-dialog.js | 212 ++++++++++++++++----------- module/tmr-rencontres.js | 10 +- module/tmr-utility.js | 17 +-- module/tmr/conquete.js | 41 ++++++ module/tmr/desorientation.js | 58 ++++++++ module/tmr/effets-draconiques.js | 26 ++-- module/tmr/fermeture-cites.js | 6 + module/tmr/present-cites.js | 15 ++ system.json | 2 +- template.json | 14 +- templates/casetmr-specific-list.html | 1 + 12 files changed, 312 insertions(+), 115 deletions(-) create mode 100644 module/tmr/conquete.js create mode 100644 module/tmr/desorientation.js diff --git a/module/actor.js b/module/actor.js index 42ca2438..6e993730 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1121,6 +1121,24 @@ export class RdDActor extends Actor { return queue; } + /* -------------------------------------------- */ + async reinsertionAleatoire(raison) { + ChatMessage.create({ + content: `${raison} : ré-insertion aléatoire.`, + whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name) + }); + const innaccessible = this.buildTMRInnaccessible(); + let tmr = TMRUtility.getTMRAleatoire(tmr => !innaccessible.includes(tmr.coord) ); + this.updateCoordTMR(tmr.coord); + return tmr; + } + + buildTMRInnaccessible() { + const tmrInnaccessibles = this.data.items.filter(it => Draconique.isCaseTMR(it) && + EffetsDraconiques.isInnaccessible(it)); + return tmrInnaccessibles.map(it => it.data.coord); + } + /* -------------------------------------------- */ displayTMRQueueSouffleInformation() { let messages = []; @@ -1137,9 +1155,6 @@ export class RdDActor extends Actor { if (EffetsDraconiques.isPeriple(item)) { messages.push("Vous souffrez du Souffle Périple. Vous devez gérer manuellement le détail du Périple.
" + item.data.description); } - if (EffetsDraconiques.isDesorientation(item)) { - messages.push("Vous souffrez du Souffle Désorientation. Vous devez gérer avec votre MJ les effets de ce souffle.
" + item.data.description); - } } if (messages.length > 0) { @@ -1796,6 +1811,10 @@ export class RdDActor extends Actor { ui.notifications.info("Aucun sort disponible pour cette case !"); return; } + if (EffetsDraconiques.isConquete(this)) { + ui.notifications.error("Vous ne pouvez pas lancer de sort sous l'effet d'une conquête!"); + return; + } if (this.currentTMR) this.currentTMR.minimize(); // Hide let draconicList = this.filterDraconicList(sortList); diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 05bf2113..823e8679 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -10,6 +10,7 @@ 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"; +import { Grammar } from "./grammar.js"; /* -------------------------------------------- */ export class RdDTMRDialog extends Dialog { @@ -50,7 +51,7 @@ export class RdDTMRDialog extends Dialog { this.cumulFatigue = 0; this.loadRencontres(); this.loadSortsReserve(); - this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item)); + this.loadCasesSpeciales(); this.allTokens = []; this.rencontreState = 'aucune'; this.pixiApp = new PIXI.Application({ width: 720, height: 860 }); @@ -66,6 +67,10 @@ export class RdDTMRDialog extends Dialog { this.pixiTMR.load((loader, resources) => this.createPixiSprites()); } + loadCasesSpeciales() { + this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item)); + } + loadSortsReserve() { this.sortsReserves = duplicate(this.actor.data.data.reve.reserve.list); } @@ -99,6 +104,7 @@ export class RdDTMRDialog extends Dialog { this._removeTokens(t => true); this.loadRencontres(); this.loadSortsReserve(); + this.loadCasesSpeciales(); this._createTokens(); } @@ -396,10 +402,13 @@ 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))) { - - + if (this.casesSpeciales.find(c => EffetsDraconiques.isPresentCite(c, tmr.coord))) { + + // TODO: dialog pour remplacer la rencontre par un présent + + } + + let myRoll = new Roll("1d7").evaluate().total; if (TMRUtility.isForceRencontre() || myRoll == 7) { return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale()); @@ -415,30 +424,22 @@ export class RdDTMRDialog extends Dialog { ? await TMRRencontres.getMauvaiseRencontre() : await TMRRencontres.getRencontreAleatoire(tmr.type)); rencontre.coord = tmr.coord; - rencontre.date = game.system.rdd.calendrier.getDateFromIndex(); + rencontre.date = game.system.rdd.calendrier.getDateFromIndex(); rencontre.heure = game.system.rdd.calendrier.getCurrentHeure(); return rencontre; } /* -------------------------------------------- */ - async manageCaseSpeciale(tmr) { - if (this.casesSpeciales.find(c => EffetsDraconiques.isCaseTrouNoir(c, tmr.coord))) { - let newTMR = TMRUtility.getTMRAleatoire(); - let tmrPos = duplicate(this.actor.data.data.reve.tmrpos); - tmrPos.coord = newTMR.coord; - await this.actor.update({ "data.reve.tmrpos": tmrPos }); - ChatMessage.create({ - content: "Vous êtes rentré sur un Trou Noir : ré-insertion aléatoire.", - whisper: ChatMessage.getWhisperRecipients(game.user.name) - }); + async manageTmrInnaccessible(tmr) { + const caseTmrInnaccessible = this.casesSpeciales.find(c => EffetsDraconiques.isInnaccessible(c, tmr.coord)); + if (caseTmrInnaccessible) { + return await this.actor.reinsertionAleatoire(caseTmrInnaccessible.name); } + return tmr; } /* -------------------------------------------- */ async manageCaseHumide(tmr) { - if (this.viewOnly || this.currentRencontre) { - return; - } if (this.isCaseHumide(tmr)) { let rollData = { actor: this.actor, @@ -517,26 +518,52 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ async conquerirCiteFermee(tmr) { - if (this.viewOnly || this.currentRencontre) { - return; - } - const citeFermee = this.isCiteFermee(tmr.coord); - if (citeFermee) { - let rollData = { - actor: this.actor, - competence: duplicate(this.actor.getBestDraconic()), - tmr: tmr, - canClose: false, - diffLibre: -9, - forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } }, - maitrise: { verbe: 'conquérir', action: 'Conquérir la cité' } - } - rollData.competence.data.defaut_carac = 'reve-actuel'; - - await this._maitriserTMR(rollData, r => this._resultatConqueteCiteFermee(r)); + if (EffetsDraconiques.fermetureCites.find(this.casesSpeciales, tmr.coord)) { + await this._conquerir(tmr, { + difficulte: -9, + action: 'Conquérir la cité', + onConqueteReussie: r => EffetsDraconiques.fermetureCites.onConquete(r.actor, tmr.coord), + onConqueteEchec: r => this.close(), + canClose: false + }); } } - async _resultatConqueteCiteFermee(rollData) { + + removeToken(tmr, casetmr) { + this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id); + this.updateTokens() + } + + /* -------------------------------------------- */ + async conquerirTMR(tmr) { + if (EffetsDraconiques.conquete.find(this.casesSpeciales, tmr.coord)) { + await this._conquerir(tmr, { + difficulte: -7, + action: 'Conquérir', + onConqueteReussie: r => EffetsDraconiques.conquete.onConquete(r.actor, tmr.coord, (casetmr) => this.removeToken(tmr, casetmr)), + onConqueteEchec: r => {}, + canClose: false + }); + } + } + + /* -------------------------------------------- */ + async _conquerir(tmr, options) { + let rollData = { + actor: this.actor, + competence: duplicate(this.actor.getBestDraconic()), + tmr: tmr, + canClose: options.canClose ?? false, + diffLibre: options.difficulte ?? -7, + forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } }, + maitrise: { verbe: 'conquérir', action: options.action } + }; + rollData.competence.data.defaut_carac = 'reve-actuel'; + + await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options)); + } + + async _onResultatConquerir(rollData, options) { if (rollData.rolled.isETotal) { rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); } @@ -548,12 +575,11 @@ export class RdDTMRDialog extends Dialog { content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData) }); if (rollData.rolled.isEchec) { - this.close(); + options.onConqueteEchec(rollData, options.effetDraconique); } 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); + await options.onConqueteReussie(rollData, options.effetDraconique); + this.updateTokens(); } } @@ -578,17 +604,18 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async declencheSortEnReserve(coordTMR) { - if (this.viewOnly) { - return; - } - - let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR); + async declencheSortEnReserve(coord) { + + let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord); if (sortReserveList.length > 0) { - if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coordTMR)) { + if (EffetsDraconiques.isConquete(this.actor)) { + ui.notifications.error("Vous ne pouvez pas déclencher de sort sous l'effet d'une conquête!"); + return; + } + if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord)) { let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête Reserve en Sécurité ou Réserve Exensible, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher :
    "; for (let sortReserve of sortReserveList) { - msg += "
  • " + sortReserve.sort.name + "
  • "; + msg += "
  • " + sortReserve.sort.name + "
  • "; } msg += ""; ChatMessage.create({ @@ -640,40 +667,28 @@ export class RdDTMRDialog extends Dialog { this.rencontreState = 'aucune'; // Et de l'état } - /* -------------------------------------------- */ - processClickPostRencontre(coord) { - if (this.rencontreState == 'passeur' || this.rencontreState == 'messager' || this.rencontreState == 'changeur') { - console.log("Searching", this.currentRencontre.locList, coord); - let isInArea = this.currentRencontre.locList.find(locCoord => locCoord == coord); - if (isInArea) { // OK ! - return (this.rencontreState == 'messager') ? 'messager' : 'saut'; - } - } - return "erreur"; - } - /* -------------------------------------------- */ isCaseInondee(coord) { - return this.casesSpeciales.find(c => EffetsDraconiques.isCaseInondee(c, coord)); + return EffetsDraconiques.debordement.find(this.casesSpeciales, coord); } isCiteFermee(coord) { - return this.casesSpeciales.find(c => EffetsDraconiques.isCiteFermee(c, coord)); + return EffetsDraconiques.fermetureCites.find(this.casesSpeciales, coord); } /* -------------------------------------------- */ isTerreAttache(coord) { - return this.casesSpeciales.find(c => EffetsDraconiques.isTerreAttache(c, coord)); + return EffetsDraconiques.terreAttache.find(this.casesSpeciales, coord); } /* -------------------------------------------- */ isCaseMaitrisee(coord) { - return this.casesSpeciales.find(c => EffetsDraconiques.isCaseMaitrisee(c, coord)); + return EffetsDraconiques.queteEaux.find(this.casesSpeciales, coord); } /* -------------------------------------------- */ isReserveExtensible(coord) { - return this.casesSpeciales.find(c => EffetsDraconiques.isReserveExtensible(c, coord)); + return EffetsDraconiques.reserveExtensible.find(this.casesSpeciales, coord); } /* -------------------------------------------- */ @@ -719,8 +734,29 @@ export class RdDTMRDialog extends Dialog { this.checkQuitterTMR(); } - async _messagerDemiReve(targetCoordTMR) { - await this.actor.rollUnSort(targetCoordTMR); + /* -------------------------------------------- */ + _calculDeplacement(targetCoord, currentCoord, currentPos, eventPos) { + let isInArea = this.rencontreState == 'aucune' + ? this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || !RdDTMRDialog._horsDePortee(currentPos, eventPos) + : 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'; + } + } + return 'erreur' + } + + /* -------------------------------------------- */ + async _messagerDemiReve(targetCoord) { + /* + TODO: si la case a un sort en réserve, lancer ce sort. + 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 this.actor.rollUnSort(targetCoord); this.nettoyerRencontre(); } @@ -729,14 +765,12 @@ 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.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.actor.updateCoordTMR(tmr.coord); + await this.actor.updateCoordTMR(tmr.coord); this._updateDemiReve(); this.cumulFatigue += this.fatigueParCase; @@ -757,25 +791,31 @@ 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); + if (!(this.viewOnly || this.currentRencontre)) { + await this.manageCaseHumide(tmr); + await this.conquerirCiteFermee(tmr); + await this.conquerirTMR(tmr); + await this.declencheSortEnReserve(tmr.coord); + await this.actor.checkSoufflePeage(tmr); + } } /* -------------------------------------------- */ - async forceDemiRevePositionView(coordTMR) { + async forceDemiRevePositionView() { this._updateDemiReve(); } /* -------------------------------------------- */ - async forceDemiRevePosition(coordTMR) { - await this.actor.updateCoordTMR(coordTMR); + async forceDemiRevePosition(coord) { + await this.actor.updateCoordTMR(coord); this._updateDemiReve(); - let tmr = TMRUtility.getTMR(coordTMR); - await this.manageCaseHumide(tmr); - await this.conquerirCiteFermee(tmr); - await this.declencheSortEnReserve(tmr.coord); + let tmr = TMRUtility.getTMR(coord); + if (!(this.viewOnly || this.currentRencontre)) { + await this.manageCaseHumide(tmr); + await this.conquerirCiteFermee(tmr); + await this.declencheSortEnReserve(tmr.coord); + } + return tmr; } /* -------------------------------------------- */ diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js index 2b6632ec..e22489c8 100644 --- a/module/tmr-rencontres.js +++ b/module/tmr-rencontres.js @@ -272,6 +272,12 @@ const rencontresStandard = [ { code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1ddr + 7", refoulement: 2, quitterTMR: true } ]; +const presentsCite = [ + { code: "messager2d6", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d6", ignorer: true }, + { code: "passeur2d6", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d6", ignorer: true }, + { code: "fleur2d6", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "2d6", ignorer: true } +] + const tableRencontres = { cite: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }], sanctuaire: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }], @@ -466,7 +472,7 @@ export class TMRRencontres { static async _toubillonner(tmrDialog, actor, cases) { let coord = actor.data.data.reve.tmrpos.coord; for (let i = 0; i < cases; i++) { - coord = TMRUtility.deplaceTMRAleatoire(coord); + coord = TMRUtility.deplaceTMRAleatoire(actor, coord).coord; } await tmrDialog.forceDemiRevePosition(coord) } @@ -477,7 +483,7 @@ export class TMRRencontres { } await data.actor.resultCombatReveDeDragon(data); } - + static async onPostEchecReveDeDragon(tmrDialog, data) { await data.actor.resultCombatReveDeDragon(data); tmrDialog.close(); diff --git a/module/tmr-utility.js b/module/tmr-utility.js index 523008e7..0da70a62 100644 --- a/module/tmr-utility.js +++ b/module/tmr-utility.js @@ -90,7 +90,7 @@ const TMRMapping = { A7: { type: "plaines", label: "Plaines de l’Arc" }, B7: { type: "marais", label: "Marais Bluants" }, C7: { type: "fleuve", label: "Fleuve de l'Oubli" }, - D7: { type: "plaines", label: "Plaines d’A!a" }, + D7: { type: "plaines", label: "Plaines d’Affa" }, E7: { type: "foret", label: "Forêt de Glusks" }, F7: { type: "fleuve", label: "Fleuve de l'Oubli" }, G7: { type: "cite", label: "Cité de Terwa" }, @@ -377,7 +377,7 @@ export class TMRUtility { if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Sortie de carte ! Ré-insertion aléatoire coord = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos)); } else { - coord = this.getTMRAleatoire().coord; + coord = await actor.reinsertionAleatoire('Sortie de carte'); } console.log("Nouvelle case iteration !!!", i, coord); } @@ -418,18 +418,15 @@ export class TMRUtility { } /* -------------------------------------------- */ - static getSortReserveList(reserveList, coordTMR) { + static getSortReserveList(reserveList, coord) { // TODO : Gérer les têtes spéciales réserve! - let sortReserveList - let tmrDescr = this.getTMR(coordTMR); + let tmrDescr = this.getTMR(coord); //console.log("Sort réserve : ", tmrDescr); if (tmrDescr.type == 'fleuve') { // Gestion de la reserve en Fleuve - sortReserveList = reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve'); - } else { // Reserve sur un case "normale" - sortReserveList = reserveList.filter(it => it.coord == coordTMR); + return reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve'); } - //console.log("Sort réserve : ", tmrDescr, sortReserve, reserveList); - return sortReserveList; + // Reserve sur un case "normale" + return reserveList.filter(it => it.coord == coord); } /* -------------------------------------------- */ diff --git a/module/tmr/conquete.js b/module/tmr/conquete.js new file mode 100644 index 00000000..fc3579b2 --- /dev/null +++ b/module/tmr/conquete.js @@ -0,0 +1,41 @@ +import { Misc } from "../misc.js"; +import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class Conquete extends Draconique { + + constructor() { + super(); + } + + type() { return 'queue' } + match(item) { return Draconique.isQueueDragon(item) && item.name.toLowerCase() == 'conquête'; } + manualMessage() { return false } + async onActorCreateOwned(actor, item) { await this._creerConquete(actor, item); } + + code() { return 'conquete' } + tooltip(linkData) { return `La ${this.tmrLabel(linkData)} doit être conquise` } + img() { return 'icons/svg/combat.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), + { + color: tmrColors.queues, taille: tmrConstants.full, decallage: { x: 2, y: 0 } + }); + } + + async _creerConquete(actor, queue) { + let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); + let possibles = TMRUtility.filterTMR(tmr => !TMRUtility.isCaseHumide(tmr) && !existants.includes(tmr.coord)); + let conquete = Misc.rollOneOf(possibles); + await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue._id); + } + + async onConquete(actor, coord) { + let existants = actor.data.items.filter(it => this.isCase(it, coord)); + for (let casetmr of existants) { + await actor.deleteOwnedItem(casetmr._id); + await actor.deleteOwnedItem(casetmr.data.sourceid); + } + } +} diff --git a/module/tmr/desorientation.js b/module/tmr/desorientation.js new file mode 100644 index 00000000..43fedf32 --- /dev/null +++ b/module/tmr/desorientation.js @@ -0,0 +1,58 @@ +import { Misc } from "../misc.js"; +import { RollDataAjustements } from "../rolldata-ajustements.js"; +import { tmrColors, tmrConstants, TMRType, TMRUtility } from "../tmr-utility.js"; +import { Debordement } from "./debordement.js"; +import { Draconique } from "./draconique.js"; + +export class Desorientation extends Draconique { + constructor() { + super(); + } + + type() { return 'souffle' } + match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase().includes('désorientation'); } + manualMessage() { return false } + + async onActorCreateOwned(actor, souffle) { + const type = Misc.rollOneOf(this._typesPossibles(actor)); + console.log("désorientation", type); + souffle.name += ": " + TMRType[type].name; + await this._creerCasesTmr(actor, type, souffle); + } + + _typesPossibles(actor) { + const dejaDesorientes = Misc.distinct(actor.data.items.filter(it => this.isCase(it)).map(it => it.type)); + return Object.keys(TMRType).filter(it => !dejaDesorientes.includes(it)); + } + + async onActorDeleteOwned(actor, souffle) { + await this._supprimerCasesTmr(actor, souffle); + } + + code() { return 'desorientation' } + tooltip(linkData) { return `Désorientation, cette case n'existe plus !` } + img() { return 'icons/svg/explosion.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), + { + color: tmrColors.trounoir, alpha: 1, taille: tmrConstants.full, decallage: { x: 2, y: 2 }, + }); + } + + async _creerCasesTmr(actor, type, souffle) { + const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); + let tmrs = TMRUtility.filterTMR(it => it.type == type && !existants.includes(it.coord)); + for (let tmr of tmrs) { + await this.createCaseTmr(actor, 'Désorientation: ' + tmr.label, tmr, souffle._id); + } + } + + async _supprimerCasesTmr(actor, souffle) { + let caseTmrs = actor.data.items.filter(it => it.data.sourceId == souffle._id); + for (let casetmr of caseTmrs) { + await actor.deleteOwnedItem(casetmr._id); + } + } + +} diff --git a/module/tmr/effets-draconiques.js b/module/tmr/effets-draconiques.js index b9745acb..656b0491 100644 --- a/module/tmr/effets-draconiques.js +++ b/module/tmr/effets-draconiques.js @@ -11,6 +11,8 @@ import { CarteTmr } from "./carte-tmr.js"; import { PontImpraticable } from "./pont-impraticable.js"; import { Draconique } from "./draconique.js"; import { PresentCites } from "./present-cites.js"; +import { Desorientation } from "./desorientation.js"; +import { Conquete } from "./conquete.js"; @@ -27,6 +29,8 @@ export class EffetsDraconiques { static terreAttache = new TerreAttache(); static trouNoir = new TrouNoir(); static pontImpraticable = new PontImpraticable(); + static desorientation = new Desorientation(); + static conquete = new Conquete(); static init() { Draconique.register(EffetsDraconiques.carteTmr); @@ -41,6 +45,8 @@ export class EffetsDraconiques { Draconique.register(EffetsDraconiques.trouNoir); Draconique.register(EffetsDraconiques.pontImpraticable); Draconique.register(EffetsDraconiques.presentCites); + Draconique.register(EffetsDraconiques.desorientation); + Draconique.register(EffetsDraconiques.conquete); } /* -------------------------------------------- */ @@ -48,19 +54,23 @@ export class EffetsDraconiques { return EffetsDraconiques.debordement.isCase(caseTMR, coord) || EffetsDraconiques.pontImpraticable.isCase(caseTMR, coord); } - + + static isInnaccessible(caseTMR, coord) { + return EffetsDraconiques.trouNoir.isCase(caseTMR, coord) || + EffetsDraconiques.desorientation.isCase(caseTMR, coord); + } static isCaseTrouNoir(caseTMR, coord) { return EffetsDraconiques.trouNoir.isCase(caseTMR, coord); } - + static isReserveExtensible(caseTMR, coord) { return EffetsDraconiques.reserveExtensible.isCase(caseTMR, coord); } - + static isTerreAttache(caseTMR, coord) { return EffetsDraconiques.terreAttache.isCase(caseTMR, coord); } - + static isCiteFermee(caseTMR, coord) { return EffetsDraconiques.fermetureCites.isCase(caseTMR, coord); } @@ -77,8 +87,8 @@ export class EffetsDraconiques { return EffetsDraconiques.isMatching(element, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('montée laborieuse')); } - static isFermetureCite(element) { /* -------------------------------------------- */ + static isFermetureCite(element) { return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.fermetureCites.match(it)); } @@ -100,14 +110,12 @@ export class EffetsDraconiques { } static isDesorientation(element) { - // TODO - return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase() == 'désorientation'); + return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.desorientation.match(it)); // TODO } /* -------------------------------------------- */ static isConquete(element) { - // TODO - return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'conquête'); + return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.conquete.match(it)); } static isPelerinage(element) { diff --git a/module/tmr/fermeture-cites.js b/module/tmr/fermeture-cites.js index 0357c8ad..29c0ef92 100644 --- a/module/tmr/fermeture-cites.js +++ b/module/tmr/fermeture-cites.js @@ -30,4 +30,10 @@ export class FermetureCites extends Draconique { await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr); } } + + async onConquete(actor, coord) { + const citeFermee = actor.data.items.find(it => this.isCase(it, coord)); + await this.actor.deleteOwnedItem(citeFermee._id); + } + } diff --git a/module/tmr/present-cites.js b/module/tmr/present-cites.js index 4cb0135e..84d13ba7 100644 --- a/module/tmr/present-cites.js +++ b/module/tmr/present-cites.js @@ -39,4 +39,19 @@ export class PresentCites extends Draconique { } } } + async choisirUnPresent(casetmr) { + let d = new Dialog({ + title: "Présent des cités", + content: `La ${casetmr.data.coord} vous offre un présent`, + buttons: { + fleur: { + icon: '', + label: "Fleur des rêves 2d6", + callback: () => this.creerObjet() + } + } + }); + d.render(true); + } + } diff --git a/system.json b/system.json index e1b9dfe4..25b90434 100644 --- a/system.json +++ b/system.json @@ -6,7 +6,7 @@ "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", - "templateVersion": 93, + "templateVersion": 94, "author": "LeRatierBretonnien", "authors": [ { diff --git a/template.json b/template.json index 7f976010..1fde5f9b 100644 --- a/template.json +++ b/template.json @@ -718,14 +718,20 @@ }, "queue": { "description": "", - "refoulement": 0 - }, + "refoulement": 0, + "duree": "", + "restant" : 0 + }, "ombre": { "description": "", - "refoulement": 2 + "refoulement": 2, + "duree": "", + "restant" : 0 }, "souffle": { - "description": "" + "description": "", + "duree": "", + "restant" : 0 }, "tete": { "description": "" diff --git a/templates/casetmr-specific-list.html b/templates/casetmr-specific-list.html index d69feec5..ccedfd1f 100644 --- a/templates/casetmr-specific-list.html +++ b/templates/casetmr-specific-list.html @@ -7,5 +7,6 @@ +