diff --git a/changelog.md b/changelog.md index 115544fb..9558701f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,18 @@ -# v11.0 +# v11.2 +## v11.2.0 - Les Terres médianes d'Akarlikarlikar +- Les TMRs sont redimensionables +- Nouveaux graphismes plus lisibles dans les TMRs +- Nouveau code couleur des icônes dans les TMR: + - noir: case innaccessible + - rouge: empêche l'usage du haut-rêve + - vert: bonus de tête de dragon permanent + - bleu: la case doit être vaincue + - blanc: effet temporaire (sort en réserve, présent des cités) +- Fix: les déplacements aléatoires prennent bien compte des colonnes paires/impaires +- Fix: Le Tricollet prend deux "L" +- Fix: Les jets d'encaissement forcés par le gardien à un résultat inférieur à 11 ne peuvent plus donner un deuxième d10 négatif + +# v11.1 ## v11.1.6 - Les dissections de Werther de Zloth - Fix: on peut de nouveau donner des compétences aux créatures - Fix: le délai de guérison d'une blessure rétrogradée est correctement appliqué @@ -53,6 +67,7 @@ - certaines macros ne marchaient pas pour les créatures/entités/véhicules/commerces - en cas de charge, les particulières sont toujours en force (p125) +# v11.0 ## v11.0.28 - les fractures de Khrachtchoum - La gravité de la blessure est affichée dans le résumé de l'encaissement - Lors du changement d'acteur pendant le round diff --git a/icons/tmr/attache.svg b/icons/tmr/attache.svg new file mode 100644 index 00000000..40dbd506 --- /dev/null +++ b/icons/tmr/attache.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/conquete.svg b/icons/tmr/conquete.svg new file mode 100644 index 00000000..f5065afa --- /dev/null +++ b/icons/tmr/conquete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/debordement.svg b/icons/tmr/debordement.svg new file mode 100644 index 00000000..d544562c --- /dev/null +++ b/icons/tmr/debordement.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/demi-reve.svg b/icons/tmr/demi-reve.svg new file mode 100644 index 00000000..7b6ab0eb --- /dev/null +++ b/icons/tmr/demi-reve.svg @@ -0,0 +1,124 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/tmr/desorientation.svg b/icons/tmr/desorientation.svg new file mode 100644 index 00000000..7e4c3fb9 --- /dev/null +++ b/icons/tmr/desorientation.svg @@ -0,0 +1,55 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/icons/tmr/fermeture.svg b/icons/tmr/fermeture.svg new file mode 100644 index 00000000..e3d70c97 --- /dev/null +++ b/icons/tmr/fermeture.svg @@ -0,0 +1,190 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/tmr/gift.webp b/icons/tmr/gift.webp deleted file mode 100644 index 7173e6e5..00000000 Binary files a/icons/tmr/gift.webp and /dev/null differ diff --git a/icons/tmr/maitrisee.svg b/icons/tmr/maitrisee.svg new file mode 100644 index 00000000..fa2a5d9d --- /dev/null +++ b/icons/tmr/maitrisee.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/pelerin.webp b/icons/tmr/pelerin.webp deleted file mode 100644 index 687e7429..00000000 Binary files a/icons/tmr/pelerin.webp and /dev/null differ diff --git a/icons/tmr/pelerinage.svg b/icons/tmr/pelerinage.svg new file mode 100644 index 00000000..371af982 --- /dev/null +++ b/icons/tmr/pelerinage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/periple.svg b/icons/tmr/periple.svg new file mode 100644 index 00000000..7b287467 --- /dev/null +++ b/icons/tmr/periple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/present.svg b/icons/tmr/present.svg new file mode 100644 index 00000000..6589cfd7 --- /dev/null +++ b/icons/tmr/present.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/rencontre.svg b/icons/tmr/rencontre.svg new file mode 100644 index 00000000..fcf0c57e --- /dev/null +++ b/icons/tmr/rencontre.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/reserve.svg b/icons/tmr/reserve.svg new file mode 100644 index 00000000..6cefe4c0 --- /dev/null +++ b/icons/tmr/reserve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/scroll.webp b/icons/tmr/scroll.webp deleted file mode 100644 index 43fd2f1f..00000000 Binary files a/icons/tmr/scroll.webp and /dev/null differ diff --git a/icons/tmr/sort-reserve.svg b/icons/tmr/sort-reserve.svg new file mode 100644 index 00000000..6a1b87c3 --- /dev/null +++ b/icons/tmr/sort-reserve.svg @@ -0,0 +1,132 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/tmr/treasure-chest.webp b/icons/tmr/treasure-chest.webp deleted file mode 100644 index ff4675ab..00000000 Binary files a/icons/tmr/treasure-chest.webp and /dev/null differ diff --git a/icons/tmr/trounoir.svg b/icons/tmr/trounoir.svg new file mode 100644 index 00000000..7a5f018e --- /dev/null +++ b/icons/tmr/trounoir.svg @@ -0,0 +1,126 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/tmr/urgence.svg b/icons/tmr/urgence.svg new file mode 100644 index 00000000..cb683bfd --- /dev/null +++ b/icons/tmr/urgence.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/tmr/wave.webp b/icons/tmr/wave.webp deleted file mode 100644 index 09c6a8b0..00000000 Binary files a/icons/tmr/wave.webp and /dev/null differ diff --git a/module/actor.js b/module/actor.js index 53556495..25c55eb7 100644 --- a/module/actor.js +++ b/module/actor.js @@ -2476,7 +2476,8 @@ export class RdDActor extends RdDBaseActorSang { } this.tmrApp = await RdDTMRDialog.create(this, tmrFormData); - this.tmrApp.render(true); + await this.tmrApp.render(true); + await this.tmrApp.onDeplacement() } /* -------------------------------------------- */ diff --git a/module/rdd-dice.js b/module/rdd-dice.js index 7dd9fa22..e9f9dcc2 100644 --- a/module/rdd-dice.js +++ b/module/rdd-dice.js @@ -164,7 +164,7 @@ export class RdDDice { if (options.showDice == HIDE_DICE || !game.modules.get("dice-so-nice")?.active || !game.dice3d) { return; } - + let { whisper, blind } = RdDDice._getWhisperBlind(options); if (options.forceDiceResult?.total) { let terms = await RdDDice._getForcedTerms(options); @@ -197,48 +197,25 @@ export class RdDDice { function terms1d100(total) { const unites = total % 10; const dizaines = Math.floor(total / 10); - return [{ - resultLabel: dizaines * 10, - d100Result: total, - result: dizaines, - type: "d100", - vectors: [], - options: {} - }, - { - resultLabel: unites, - d100Result: total, - result: unites, - type: "d10", - vectors: [], - options: {} - }]; + return [ + { type: "d100", result: dizaines, resultLabel: dizaines * 10, vectors: [], options: {}, d100Result: total }, + { type: "d10", result: unites, resultLabel: unites, vectors: [], options: {}, d100Result: total } + ]; } async function terms2d10(total) { - if (total>20 || total<2) { return undefined } - let first = await RdDDice.d10(); - let second = Math.min(total-first, 10); - first = Math.max(first, total-second); - return [{ - resultLabel:first, - result: first, - type: "d10", - vectors: [], - options: {} - }, - { - resultLabel: second, - result: second, - type: "d10", - vectors: [], - options: {} - }]; + if (total > 20 || total < 2) { return undefined } + const first = await RdDDice.fakeD10(Math.min(10, total - 1)); + const second = total - first; + return [ + { type: "d10", result: first, resultLabel: first, vectors: [], options: {} }, + { type: "d10", result: second, resultLabel: second, vectors: [], options: {} } + ]; } } - static async d10() { - let roll = new Roll('1d10'); + static async fakeD10(faces) { + let roll = new Roll(`1d${faces}`); await roll.evaluate({ async: true }); return roll.total; } diff --git a/module/rdd-main.js b/module/rdd-main.js index 0d4d0175..6996872a 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -63,6 +63,7 @@ import { AppAstrologie } from "./sommeil/app-astrologie.js"; import { RdDItemArmure } from "./item/armure.js"; import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-darkness.js"; import { RdDCreature } from "./actor/creature.js"; +import { RdDTMRDialog } from "./rdd-tmr-dialog.js"; /** * RdD system @@ -201,6 +202,7 @@ export class SystemReveDeDragon { RdDCompendiumOrganiser.init(); EffetsDraconiques.init() TMRUtility.init(); + await RdDTMRDialog.init() RdDHotbar.initDropbar(); RdDPossession.init(); TMRRencontres.init(); diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 4bec890c..773dc6c9 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -1,4 +1,4 @@ -import { SHOW_DICE } from "./constants.js"; +import { SHOW_DICE, SYSTEM_RDD } from "./constants.js"; import { RollDataAjustements } from "./rolldata-ajustements.js"; import { RdDUtility } from "./rdd-utility.js"; import { TMRUtility } from "./tmr-utility.js"; @@ -18,18 +18,40 @@ import { RdDRencontre } from "./item/rencontre.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { TYPES } from "./item.js"; -/* -------------------------------------------- */ +const TMR_DISPLAY_SIZE = { + code: 'tmr-display-size', + range: { + min: 32, + max: 128, + step: 8, + }, + def: 64, + clamp: (size, inc = 0) => Math.max(TMR_DISPLAY_SIZE.range.min, Math.min(size + (inc * TMR_DISPLAY_SIZE.range.step), TMR_DISPLAY_SIZE.range.max)), + get: () => TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def), + set: (size) => game.settings.set(SYSTEM_RDD, TMR_DISPLAY_SIZE.code, TMR_DISPLAY_SIZE.clamp(size)), +}; +/* -------------------------------------------- */ export class RdDTMRDialog extends Dialog { + static async init() { + game.settings.register(SYSTEM_RDD, TMR_DISPLAY_SIZE.code, { + name: 'Taille des cases des TMR', + hint: "Taille en pixel des cases des TMR (réglable directement dans la fenêtre des TMR)", + scope: "client", + config: true, + default: TMR_DISPLAY_SIZE.def, + type: Number, + range: TMR_DISPLAY_SIZE.range + }) + await PixiTMR.init() + } static async create(actor, tmrData) { let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', tmrData); - if (tmrData.mode != 'visu') { - // Notification au MJ + if (tmrData.mode != 'visu' && !game.user.isGM) { ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatMessage.getWhisperRecipients("GM") }); } - return new RdDTMRDialog(html, actor, tmrData); } @@ -38,21 +60,16 @@ export class RdDTMRDialog extends Dialog { const dialogConf = { title: "Terres Médianes de Rêve", content: html, - buttons: { - closeButton: { - label: "Fermer", callback: html => this.close() - } - }, - default: "closeButton" + buttons: {} } - const dialogOptions = { classes: ["tmrdialog"], - width: 920, maxheight: 1024, height: 'fit-content', + width: 'fit-content', + height: 'fit-content', + 'max-height': 1024, 'z-index': 40 } super(dialogConf, dialogOptions); - this.tmrdata = duplicate(tmrData); this.actor = actor; this.actor.tmrApp = this; // reference this app in the actor structure @@ -63,25 +80,97 @@ export class RdDTMRDialog extends Dialog { this.loadCasesSpeciales(); this.allTokens = []; this.rencontreState = 'aucune'; - this.pixiTMR = new PixiTMR(this); - this.subdialog = undefined - - this.callbacksOnAnimate = []; + this.displaySize = undefined if (!this.viewOnly) { this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); } + this.callbacksOnAnimate = []; + this.resizePixiTMR( + TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def) + ) + } - // load the texture we need - this.pixiTMR.load((loader, resources) => this.createPixiSprites()); + resizePixiTMR(displaySize) { + if (displaySize != this.displaySize) { + if (!this.pixiTMR) { + this.pixiTMR = new PixiTMR(this, displaySize); + } + this.displaySize = displaySize + this.pixiTMR.resizeTMR(displaySize); + this._removeTokens() + this.allTokens = [] + this.createPixiSprites() + this.pixiTMR.loadAnimations(); + } + } + + /* -------------------------------------------- */ + async activateListeners(html) { + super.activateListeners(html); + this.html = html; + + // this.activateTMRSize() + this.addTMRMap() + this.html.find('div.tmr-size a.tmr-size-zoom-minus*').click(event => { + this.$changeTMRSize(-1) + }); + this.html.find('div.tmr-size a.tmr-size-zoom-plus*').click(event => { + this.$changeTMRSize(1) + }); + + + if (this.viewOnly) { + this.html.find('.lancer-sort').remove(); + this.html.find('.lire-signe-draconique').remove(); + return; + } + + HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue")); + HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getCoordActor())); + + this.html.find('form.tmr-dialog *').click(event => this.subdialog?.bringToTop()); + + // Roll Sort + this.html.find('.lancer-sort').click(event => this.actor.rollUnSort(this._getCoordActor())); + this.html.find('.lire-signe-draconique').click(event => this.actor.rollLireSigneDraconique(this._getCoordActor())); + + this.html.find('img.tmr-move').click(event => this.deplacementTMR(this.html.find(event.currentTarget)?.data('move'))); + + // Gestion du cout de montée en points de rêve + await this.actor.reveActuelIncDec(this.calculCoutMonteeTMR()); + this.cumulFatigue += this.fatigueParCase; + + // Le reste... + this.updateValuesDisplay(); + } + + async onDeplacement() { + await this.manageRencontre(TMRUtility.getTMR(this._getCoordActor())); + } + + addTMRMap() { + const tmrCell = document.getElementsByClassName("tmr-map")[0]; + tmrCell.childNodes.forEach(node => tmrCell.removeChild(node)) + tmrCell.append(this.pixiTMR.view); + } + + $changeTMRSize(inc) { + let displaySize = TMR_DISPLAY_SIZE.clamp(this.displaySize, inc) + if (displaySize != this.displaySize) { + game.settings.set(SYSTEM_RDD, TMR_DISPLAY_SIZE.code, TMR_DISPLAY_SIZE.clamp(displaySize)) + this.resizePixiTMR(displaySize) + this.render() + } } async forceTMRDisplay() { - this.bringToTop(); - if (this.subdialog) { + this.bringToTop() + if (this.subdialog?.bringToTop) { this.subdialog.bringToTop(); } } + async restoreTMRAfterAction() { this.subdialog = undefined await this.maximize(); @@ -90,15 +179,15 @@ export class RdDTMRDialog extends Dialog { forceTMRContinueAction() { ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR'); - this.subdialog.bringToTop(); + if (this.subdialog?.bringToTop) { + this.subdialog.bringToTop(); + } return; } setTMRPendingAction(dialog) { this.subdialog = dialog - if (dialog instanceof Application) { - dialog.bringToTop(); - } + this.forceTMRDisplay() } isDemiReveCache() { @@ -130,8 +219,8 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ createPixiSprites() { this.pixiTMR.setup() - this.updateTokens(); - this.forceDemiRevePositionView(); + this.updateTokens() + this.forceDemiRevePositionView() } /* -------------------------------------------- */ @@ -188,78 +277,28 @@ export class RdDTMRDialog extends Dialog { } forceDemiRevePositionView() { - this.notifierResonanceSigneDraconique(this._getActorCoord()); + this.notifierResonanceSigneDraconique(this._getCoordActor()); this._trackToken(this.demiReve); } - _getActorCoord() { + _getCoordActor() { return this.actor.system.reve.tmrpos.coord; } /* -------------------------------------------- */ - async moveFromKey(move) { + async deplacementTMR(move) { if (this.subdialog) { return this.forceTMRContinueAction(); } - let oddq = TMRUtility.coordTMRToOddq(this._getActorCoord()); - - if (move == 'top') oddq.row -= 1; - if (move == 'bottom') oddq.row += 1; - if (move.includes('left')) oddq.col -= 1; - if (move.includes('right')) oddq.col += 1; - if (oddq.col % 2 == 1) { - if (move == 'top-left') oddq.row -= 1; - if (move == 'top-right') oddq.row -= 1; - } else { - if (move == 'bottom-left') oddq.row += 1; - if (move == 'bottom-right') oddq.row += 1; - } - - let targetCoord = TMRUtility.oddqToCoordTMR(oddq); - await this._deplacerDemiReve(targetCoord, 'normal'); + const coordOrig = this._getCoordActor(); + const coordTarget = TMRUtility.deplacement(coordOrig, move); + await this._deplacerDemiReve(coordTarget, 'normal'); this.checkQuitterTMR(); } - /* -------------------------------------------- */ - async activateListeners(html) { - super.activateListeners(html); - this.html = html; - - document.getElementsByClassName("tmr-row") - .item(0) - .insertCell(0) - .append(this.pixiTMR.view); - - if (this.viewOnly) { - this.html.find('.lancer-sort').remove(); - this.html.find('.lire-signe-draconique').remove(); - return; - } - - HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue")); - HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord())); - - this.html.find('tr.tmr-row *').click(event => this.subdialog?.bringToTop()); - - // Roll Sort - this.html.find('.lancer-sort').click(event => this.actor.rollUnSort(this._getActorCoord())); - this.html.find('.lire-signe-draconique').click(event => this.actor.rollLireSigneDraconique(this._getActorCoord())); - this.html.find('#dir-top').click(event=> this.moveFromKey("top")); - this.html.find('#dir-top-left').click(event=> this.moveFromKey("top-left")); - this.html.find('#dir-top-right').click(event=> this.moveFromKey("top-right")); - this.html.find('#dir-bottom-left').click(event=> this.moveFromKey("bottom-left")); - this.html.find('#dir-bottom-right').click(event=> this.moveFromKey("bottom-right")); - this.html.find('#dir-bottom').click(event=> this.moveFromKey("bottom")); - - // Gestion du cout de montée en points de rêve - let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse(); - await this.actor.reveActuelIncDec(reveCout); - this.cumulFatigue += this.fatigueParCase; - // Le reste... - this.updateValuesDisplay(); - let tmr = TMRUtility.getTMR(this._getActorCoord()); - await this.manageRencontre(tmr); + calculCoutMonteeTMR() { + return ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse(); } /* -------------------------------------------- */ @@ -267,7 +306,7 @@ export class RdDTMRDialog extends Dialog { if (!this.rendered) { return; } - const coord = this._getActorCoord(); + const coord = this._getCoordActor(); HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord)); @@ -295,11 +334,13 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ async close() { + if (this.subdialog) { return this.forceTMRContinueAction() } - + this.descenteTMR = true; + this.pixiTMR.close() if (this.actor.tmrApp) { this.actor.tmrApp = undefined; // Cleanup reference if (!this.viewOnly) { @@ -425,7 +466,7 @@ export class RdDTMRDialog extends Dialog { nbRounds: 1, canClose: false, selectedCarac: { label: "reve-actuel" }, - tmr: TMRUtility.getTMR(this._getActorCoord()) + tmr: TMRUtility.getTMR(this._getCoordActor()) } await this._tentativeMaitrise(rencontreData); @@ -608,19 +649,18 @@ export class RdDTMRDialog extends Dialog { if (rencontre) { return game.system.rdd.rencontresTMR.calculRencontre(rencontre, tmr); } - let locTMR = (this.isDemiReveCache() + const coordTMR = (this.isDemiReveCache() ? TMRUtility.getTMRType(tmr.coord) + " ??" : tmr.label + " (" + tmr.coord + ")"); - const fakeDialogRencontre = { bringToTop: () => { } }; - this.setTMRPendingAction(fakeDialogRencontre) - let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE }); + this.setTMRPendingAction({ bringToTop: () => { } }) + const myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE }); this.restoreTMRAfterAction() if (myRoll == 7) { - this._tellToUser(myRoll + ": Rencontre en " + locTMR); + this._tellToUser(myRoll + ": Rencontre en " + coordTMR); return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre()) } else { - this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR); + this._tellToUser(myRoll + ": Pas de rencontre en " + coordTMR); return undefined; } } @@ -934,19 +974,18 @@ export class RdDTMRDialog extends Dialog { if (this.subdialog) { return this.forceTMRContinueAction() } - let clickOddq = TMRUtility.computeEventOddq(event); - let currentOddq = TMRUtility.coordTMRToOddq(this._getActorCoord()); - - let targetCoord = TMRUtility.oddqToCoordTMR(clickOddq); - let currentCoord = TMRUtility.oddqToCoordTMR(currentOddq); + const currentCoord = this._getCoordActor() + const currentOddq = TMRUtility.coordTMRToOddq(currentCoord) + const targetOddq = this.pixiTMR.computeEventOddq(event) + const targetCoord = TMRUtility.oddqToCoordTMR(targetOddq) // Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter) - let deplacementType = this._calculDeplacement(targetCoord, currentCoord, currentOddq, clickOddq); + const typeDeplacement = this._calculDeplacement(targetCoord, currentCoord, currentOddq, targetOddq); if (this.isDemiReveCache()) { if (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) - || deplacementType == 'changeur') { + || typeDeplacement == 'changeur') { // déplacement possible await this.actor.setTMRVisible(true); this.demiReve = this._tokenDemiReve(); @@ -961,11 +1000,11 @@ export class RdDTMRDialog extends Dialog { } } - switch (deplacementType) { + switch (typeDeplacement) { case 'normal': case 'changeur': case 'passeur': - await this._deplacerDemiReve(targetCoord, deplacementType); + await this._deplacerDemiReve(targetCoord, typeDeplacement); break; case 'messager': await this._messagerDemiReve(targetCoord); @@ -1085,7 +1124,7 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - _removeTokens(filter) { + _removeTokens(filter = it => true) { this.allTokens.filter(filter).forEach(token => this.pixiTMR.removeToken(token)) } diff --git a/module/tmr-constants.js b/module/tmr-constants.js index b5a448d3..f0691c19 100644 --- a/module/tmr-constants.js +++ b/module/tmr-constants.js @@ -1,27 +1,64 @@ -/* -------------------------------------------- */ -export const tmrConstants = { - col1_y: 30, - col2_y: 55, - cellw: 55, - cellh: 55, - gridx: 28, - gridy: 28, - // tailles - third: 18, - half: 27.5, - twoThird: 36, - full: 55, - // decallages - center: { x: 0, y: 0 }, - top: { x: 0, y: -11.5 }, - topLeft: { x: -11.5, y: -11.5 }, - left: { x: -11.5, y: 0 }, - bottomLeft: { x: -11.5, y: 11.5 }, - bottom: { x: 0, y: 11.5 }, - bottomRight: { x: 11.5, y: 11.5 }, - right: { x: 11.5, y: 0 }, - topRight: { x: 11.5, y: -11.5 }, +export class TMRConstants { + constructor({ size = 64 }) { + // tailles + this.size = size + this.half = this.size / 2 + this.quarter = this.size / 4 + this.third = this.size / 3 + this.twoThird = this.size * 2 / 3 + this.full = this.size + // positions + this.col1_y = this.half + this.col2_y = this.size + this.cellw = this.size + this.cellh = this.size + this.gridx = this.half + this.gridy = this.half + // decallages + this.center = { x: 0, y: 0 } + this.top = { x: 0, y: -this.quarter } + this.topLeft = { x: -this.quarter, y: -this.quarter } + this.left = { x: -this.quarter, y: 0 } + this.bottomLeft = { x: -this.quarter, y: this.quarter } + this.bottom = { x: 0, y: this.quarter } + this.bottomRight = { x: this.quarter, y: this.quarter } + this.right = { x: this.quarter, y: 0 } + this.topRight = { x: this.quarter, y: -this.quarter } + this.marginx = 1 + this.marginy = 1 + } + + decallage(x, y) { + return { + x: x * this.third, + y: y * this.third + } + } + + computeEventPosition(event) { + if (!event.nativeEvent.target.getBoundingClientRect) { + return { x: 0, y: 0 } + } + const canvasRect = event.nativeEvent.target.getBoundingClientRect(); + return { + x: event.nativeEvent.clientX - canvasRect.left, + y: event.nativeEvent.clientY - canvasRect.top + } + } + + computeEventOddq(event) { + var { x, y } = this.computeEventPosition(event); + return this.computeOddq(x, y); + } + + + computeOddq(x, y) { + const col = Math.floor(x / this.cellw) + const decallageColonne = col % 2 == 0 ? this.col1_y : this.col2_y + const row = Math.floor((y - decallageColonne) / this.cellh) + return { col, row, x, y } + } } // couleurs @@ -35,13 +72,15 @@ export const tmrColors = { rencontre: 0xFF0000, casehumide: 0x1050F0, } + export const tmrTokenZIndex = { - sort: 40, - tetes: 20, casehumide: 10, - conquete: 30, + tetes: 20, + sort: 30, + conquete: 40, rencontre: 50, trounoir: 60, demireve: 70, tooltip: 100, } + diff --git a/module/tmr-utility.js b/module/tmr-utility.js index 32522a11..c7aa21d7 100644 --- a/module/tmr-utility.js +++ b/module/tmr-utility.js @@ -1,7 +1,6 @@ import { Misc } from "./misc.js"; import { Grammar } from "./grammar.js"; import { RdDDice } from "./rdd-dice.js"; -import { tmrConstants } from "./tmr-constants.js"; /* -------------------------------------------- */ const TMRMapping = { @@ -228,16 +227,28 @@ export const TMRType = { } /* -------------------------------------------- */ -const tmrRandomMovePatten = - [{ name: 'top', col: 0, row: -1 }, - { name: 'topright', col: 1, row: -1 }, - { name: 'botright', col: 1, row: 1 }, - { name: 'bot', col: 0, row: 1 }, - { name: 'botleft', col: -1, row: 1 }, - { name: 'topleft', col: -1, row: -1 } - ] +const TMR_MOVE = { + "top": { even: { row: -1, col: 0 }, odd: { row: -1, col: 0 }, }, + "topleft": { even: { row: -1, col: -1 }, odd: { row: 0, col: -1 }, }, + "topright": { even: { row: -1, col: 1 }, odd: { row: 0, col: 1 }, }, + "bottomleft": { even: { row: 0, col: -1 }, odd: { row: 1, col: -1 }, }, + "bottomright": { even: { row: 0, col: 1 }, odd: { row: 1, col: 1 }, }, + "bottom": { even: { row: 1, col: 0 }, odd: { row: 1, col: 0 }, }, +} -/* -------------------------------------------- */ +/* -------------------------------------------- + * Pour comprendre les conversions entre coordonnées + * - "TMR" A1, ... M15 + * - oddq: {col, row} + * - axial: { q, r ) + * + * Un site intéressant: https://www.redblobgames.com/grids/hexagons/#distances + * + * Pour être concis, le code TMR lettre(colonne)-ligne correspond à une grille hexagonale en coordonnées "odd-q" + * (lettre => col, ligne => row). + * + * Pour les calculs de distance, les coordonnées axiales sont beaucoup plus pratiques. + */ export class TMRUtility { static init() { for (let coord in TMRMapping) { @@ -313,17 +324,33 @@ export class TMRUtility { } /* -------------------------------------------- */ - static async getDirectionPattern() { - return await RdDDice.rollOneOf(tmrRandomMovePatten); + static deplacement(coordOrig, moveName) { + const tmrMove = TMR_MOVE[moveName]; + if (! tmrMove) { + ui.notifications.error(`Le déplacement dans les TMR '${moveName}' est inconnu`) + return coordOrig + } + const fromOddq = TMRUtility.coordTMRToOddq(coordOrig); + const move = TMRUtility.getOddqMove(tmrMove, fromOddq); + const toOddq = TMRUtility.addOddq(fromOddq, move); + return TMRUtility.oddqToCoordTMR(toOddq); + } + + static getOddqMove(tmrMove, oddq) { + return oddq.col % 2 == 1 ? tmrMove.odd : tmrMove.even; + } + + static async getDirectionPattern(oddq) { + const tmrMove = await RdDDice.rollOneOf(Object.values(TMR_MOVE)); + return TMRUtility.getOddqMove(tmrMove, oddq); } /* -------------------------------------------- */ static async deplaceTMRAleatoire(actor, coord) { - const currentOddq = TMRUtility.coordTMRToOddq(coord); - const direction = await TMRUtility.getDirectionPattern(); - currentOddq.col = currentOddq.col + direction.col; - currentOddq.row = currentOddq.row + direction.row; - if (this.isOddqInTMR(currentOddq)) { // Sortie de carte ! Ré-insertion aléatoire + const oddq = TMRUtility.coordTMRToOddq(coord); + const direction = await TMRUtility.getDirectionPattern(oddq); + const currentOddq = TMRUtility.addOddq(oddq, direction) + if (TMRUtility.isOddqInTMR(currentOddq)) { // Sortie de carte ! Ré-insertion aléatoire return TMRUtility.getTMR(TMRUtility.oddqToCoordTMR(currentOddq)); } else { return await actor.reinsertionAleatoire('Sortie de carte'); @@ -360,15 +387,15 @@ export class TMRUtility { * */ static getTMRPortee(coord, portee) { - let centerOddq = this.coordTMRToOddq(coord); + let centerOddq = TMRUtility.coordTMRToOddq(coord); let caseList = []; for (let dcol = -portee; dcol <= portee; dcol++) { // rows for (let drow = -portee; drow <= portee; drow++) { // columns const currentOddq = { col: centerOddq.col + dcol, row: centerOddq.row + drow }; - if (this.isOddqInTMR(currentOddq)) { - let dist = this.distanceOddq(centerOddq, currentOddq); + if (TMRUtility.isOddqInTMR(currentOddq)) { + let dist = TMRUtility.distanceOddq(centerOddq, currentOddq); if (dist <= portee) { - caseList.push(this.oddqToCoordTMR(currentOddq)); // Inside the area + caseList.push(TMRUtility.oddqToCoordTMR(currentOddq)); // Inside the area } } } @@ -376,40 +403,6 @@ export class TMRUtility { return caseList; } - // /* -------------------------------------------- */ - static computeEventPosition(event) { - if (!event.nativeEvent.target.getBoundingClientRect) { - return { x: 0, y: 0 } - } - const canvasRect = event.nativeEvent.target.getBoundingClientRect(); - return { - x: event.nativeEvent.clientX - canvasRect.left, - y: event.nativeEvent.clientY - canvasRect.top - }; - } - - /* -------------------------------------------- */ - static computeEventOddq(event) { - var { x, y } = TMRUtility.computeEventPosition(event); - return TMRUtility.computeOddq(x, y); - } - - static computeOddq(x, y) { - const col = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12] - const decallageColonne = col % 2 == 0 ? tmrConstants.col1_y : tmrConstants.col2_y; - const row = Math.floor((y - decallageColonne) / tmrConstants.cellh); // [From 0 -> 14] - return { col, row }; - } - - static computeEventCoord(event) { - const oddq = TMRUtility.computeEventOddq(event); - return TMRUtility.oddqToCoordTMR(oddq); - } - - /* -------------------------------------------- */ - // https://www.redblobgames.com/grids/hexagons/#distances - // TMR Letter-row correspond to "odd-q" grid (letter => col, numeric => row ) - /* -------------------------------------------- */ static coordTMRToOddq(coordTMR) { let col = coordTMR.charCodeAt(0) - 65; @@ -432,17 +425,13 @@ export class TMRUtility { row >= 0 && (row + col % 2 <= 14) ); - // if (x >= 0 && x < 13 && y >= 0 && y < 14) return true; - // if (x >= 0 && x < 13 && x % 2 == 0 && y == 14) return true; - // return false; } - /* -------------------------------------------- */ static distanceCoordTMR(coord1, coord2) { - let oddq1 = this.coordTMRToOddq(coord1); - let oddq2 = this.coordTMRToOddq(coord2); - return this.distanceOddq(oddq1, oddq2); + let oddq1 = TMRUtility.coordTMRToOddq(coord1); + let oddq2 = TMRUtility.coordTMRToOddq(coord2); + return TMRUtility.distanceOddq(oddq1, oddq2); } /* -------------------------------------------- */ @@ -450,13 +439,13 @@ export class TMRUtility { const axial1 = TMRUtility.oddqToAxial(oddq1); const axial2 = TMRUtility.oddqToAxial(oddq2); return TMRUtility.distanceAxial(axial1, axial2); + } - // const dx = oddq2.col - oddq1.col; - // const dy = oddq2.row - oddq1.row; - // const abs_dx = Math.abs(dx); - // const abs_dy = Math.abs(dy); - // const distance = Math.sign(dx) == Math.sign(dy) ? Math.max(abs_dx, abs_dy) : (abs_dx + abs_dy); - // return distance; + static addOddq(move, oddq) { + return { + row: oddq.row + move.row, + col: oddq.col + move.col + } } static oddqToAxial(pos) { @@ -480,20 +469,4 @@ export class TMRUtility { }; } - // function axial_to_cube(hex): - // var q = hex.q - // var r = hex.r - // var s = -q - r - // return Cube(q, r, s) - // } - - - // /* -------------------------------------------- */ - // static computeRealPictureCoordinates(coordOddq) { - // let decallagePairImpair = (coordOddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; - // return { - // x: tmrConstants.gridx + (coordOddq.col * tmrConstants.cellw), - // y: tmrConstants.gridy + (coordOddq.row * tmrConstants.cellh) + decallagePairImpair - // } - // } } \ No newline at end of file diff --git a/module/tmr/animation.js b/module/tmr/animation.js new file mode 100644 index 00000000..9b8312e9 --- /dev/null +++ b/module/tmr/animation.js @@ -0,0 +1,107 @@ +// pixiTMR.animate(pixiApp => pixiApp.ticker.add((delta) => { +// if (!sprite.waveAnimation) { +// sprite.waveAnimation = { +// originx: sprite.x, +// movex: 0, +// step: 0.03 +// } +// } +// else { +// if (Math.abs(sprite.waveAnimation.movex) > 2) { +// sprite.waveAnimation.step = -sprite.waveAnimation.step +// } +// sprite.waveAnimation.movex += sprite.waveAnimation.step; +// } +// sprite.x = sprite.waveAnimation.originx + sprite.waveAnimation.movex +// })); + +// return pixiTMR.square(this.code(), +// { +// zIndex: tmrTokenZIndex.trounoir, +// tint: tmrColors.trounoir, +// alpha: 1, +// taille: () => pixiTMR.sizes.full, +// decallage: { +// x: -pixiTMR.sizes.half, +// y: -pixiTMR.sizes.half +// } +// }) + +export class TMRAnimations { + + static withAnimation(sprite, pixiTMR, ...animations) { + if (animations.length > 0) { + animations.forEach(animation => + pixiTMR.animate(pixiApp => pixiApp.ticker.add(delta => animation(sprite, delta))) + ) + } + return sprite + } + + static rotation(options = { frequence: () => 1, angle: () => 1 }) { + return (sprite, delta) => { + if (!sprite.tmrConfig) { + sprite.tmrConfig = { nextTick: 0 } + } + sprite.tmrConfig.nextTick -= delta + if (sprite.tmrConfig.nextTick <= 0) { + sprite.tmrConfig.nextTick = options.frequence(delta) + sprite.angle += options.angle(delta) + } + } + } + + static changeZoom(range = { min: 0.8, max: 1.2, step: 0.005 }) { + return (sprite, delta) => { + if (!sprite.tmrConfig) { + sprite.tmrConfig = TMRAnimations.startRange(range) + } + sprite.tmrConfig.current += (sprite.tmrConfig.step * delta) + if (sprite.tmrConfig.current < sprite.tmrConfig.min) { + sprite.tmrConfig.step = Math.abs(sprite.tmrConfig.step) + } + else if (sprite.tmrConfig.current > sprite.tmrConfig.max) { + sprite.tmrConfig.step = -Math.abs(sprite.tmrConfig.step) + + } + const taille = sprite.tmrConfig.current * sprite.taille() + sprite.width = taille + sprite.height = taille + } + } + + static verticalAxis(options = { step: 1 }) { + return (sprite, delta) => { + if (!sprite.tmrConfig) { + sprite.tmrConfig = this.startRange({ + min: -Math.PI / 2, + max: Math.PI / 2, + step: options.step * Math.PI / 180, + }) + } + sprite.tmrConfig.current += (sprite.tmrConfig.step * delta) + sprite.width = Math.cos(sprite.tmrConfig.current) * sprite.taille() + } + } + + static startRange(range) { + range.current = TMRAnimations.randomInSegment(range) + const min = range.min + if (min > range.max) { + range.min = range.max + range.max = min + } + return range + } + + static outOfRange(range) { + return range.current < range.min || range.current > range.max + } + + static randomInSegment(range) { + const min = range.min + const max = range.max + const step = range.step + return min + (Math.floor(Math.random() / step) * step) * (max - min) + } +} diff --git a/module/tmr/augmentation-seuil.js b/module/tmr/augmentation-seuil.js index bf2c487f..3b715d46 100644 --- a/module/tmr/augmentation-seuil.js +++ b/module/tmr/augmentation-seuil.js @@ -4,10 +4,6 @@ import { Misc } from "../misc.js"; export class AugmentationSeuil extends Draconique { - constructor() { - super(); - } - type() { return 'tete' } match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('augmentation du seuil de reve'); } manualMessage() { return false } diff --git a/module/tmr/carte-tmr.js b/module/tmr/carte-tmr.js index dfdec720..b73822b2 100644 --- a/module/tmr/carte-tmr.js +++ b/module/tmr/carte-tmr.js @@ -20,10 +20,10 @@ export class CarteTmr extends Draconique { const img = PixiTMR.getImgFromCode(this.code()) const sprite = new PIXI.Sprite(PIXI.utils.TextureCache[img]); // Setup the position of the TMR - sprite.x = 0; - sprite.y = 0; - sprite.width = 722; - sprite.height = 860; + sprite.x = pixiTMR.pixiApp.screen.x; + sprite.y = pixiTMR.pixiApp.screen.y; + sprite.width = pixiTMR.pixiApp.screen.width; + sprite.height = pixiTMR.pixiApp.screen.height; // Rotate around the center sprite.anchor.set(0); sprite.buttonMode = true; @@ -31,9 +31,5 @@ export class CarteTmr extends Draconique { return sprite; } - computeTooltip(coordTMR) { - const tmr = TMRUtility.getTMR(coordTMR) - return tmr? TMRUtility.getTMRLabel(coordTMR) : ''; - } } diff --git a/module/tmr/conquete.js b/module/tmr/conquete.js index 43d53763..16ae3c1a 100644 --- a/module/tmr/conquete.js +++ b/module/tmr/conquete.js @@ -1,40 +1,38 @@ import { Grammar } from "../grammar.js"; import { RdDDice } from "../rdd-dice.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; - +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; +import { TMRAnimations } from "./animation.js"; export class Conquete extends Draconique { - constructor() { - super(); - } - type() { return 'queue' } match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('conquete'); } manualMessage() { return false } async onActorCreateOwned(actor, item) { await this._creerConquete(actor, item); } code() { return 'conquete' } - tooltip(linkData) { return `${this.tmrLabel(linkData)}: doit être conquis` } - img() { return 'icons/svg/combat.svg' } + tooltip(linkData) { return `Doit être conquis` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/conquete.svg' } createSprite(pixiTMR) { - return pixiTMR.sprite(this.code(), - { + return TMRAnimations.withAnimation( + pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.conquete, - color: tmrColors.queues, - taille: tmrConstants.full, - decallage: { x: 2, y: 0 } - }); + decallage: pixiTMR.sizes.decallage(0, 0), + taille: () => pixiTMR.sizes.half, + }), + pixiTMR, + TMRAnimations.changeZoom() + ) } async _creerConquete(actor, queue) { let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord); let possibles = TMRUtility.filterTMR(tmr => !TMRUtility.isCaseHumide(tmr) && !existants.includes(tmr.coord)); let conquete = await RdDDice.rollOneOf(possibles); - await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue.id); + await this.createCaseTmr(actor, 'Conquête', conquete, queue.id); } async onActorDeleteCaseTmr(actor, casetmr) { diff --git a/module/tmr/debordement.js b/module/tmr/debordement.js index 5c452ac2..0cbdfd61 100644 --- a/module/tmr/debordement.js +++ b/module/tmr/debordement.js @@ -1,34 +1,30 @@ import { Grammar } from "../grammar.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class Debordement extends Draconique { - constructor() { - super(); - } - type() { return 'souffle' } match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('debordement'); } manualMessage() { return false } async onActorCreateOwned(actor, souffle) { const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord); const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord))); - await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr, souffle.id); + await this.createCaseTmr(actor, 'Debordement', tmr, souffle.id); } code() { return 'debordement' } - tooltip(linkData) { return `Débordement en ${this.tmrLabel(linkData)}` } - img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/wave.webp' } + tooltip(linkData) { return `Débordement` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/debordement.svg' } createSprite(pixiTMR) { - return pixiTMR.sprite(this.code(), { + const sprite = pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.casehumide, - alpha: 0.6, - taille: tmrConstants.full, - decallage: tmrConstants.center - }); + decallage: pixiTMR.sizes.decallage(0, 2/3), + taille: () => pixiTMR.sizes.half, + }) + return sprite; } } diff --git a/module/tmr/demi-reve.js b/module/tmr/demi-reve.js index 0fa0e8f5..b0a10393 100644 --- a/module/tmr/demi-reve.js +++ b/module/tmr/demi-reve.js @@ -1,12 +1,8 @@ -import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class DemiReve extends Draconique { - constructor() { - super(); - } - type() { return '' } match(item) { return false; } manualMessage() { return false } @@ -18,9 +14,9 @@ export class DemiReve extends Draconique { createSprite(pixiTMR) { const sprite = pixiTMR.sprite(this.code(), { - color: tmrColors.demireve, + tint: tmrColors.demireve, zIndex: tmrTokenZIndex.demireve, - taille: (tmrConstants.full * 0.7) + taille: () => pixiTMR.sizes.twoThird }); pixiTMR.animate(pixiApp => pixiApp.ticker.add((delta) => sprite.rotation -= 0.01 * delta)); return sprite; diff --git a/module/tmr/desorientation.js b/module/tmr/desorientation.js index 927578fd..5de7aa74 100644 --- a/module/tmr/desorientation.js +++ b/module/tmr/desorientation.js @@ -1,14 +1,12 @@ import { Grammar } from "../grammar.js"; import { Misc } from "../misc.js"; import { RdDDice } from "../rdd-dice.js"; -import { TMRUtility, TMRType} from "../tmr-utility.js"; -import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; +import { TMRUtility, TMRType } from "../tmr-utility.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; +import { TMRAnimations } from "./animation.js"; export class Desorientation extends Draconique { - constructor() { - super(); - } type() { return 'souffle' } match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('desorientation'); } @@ -28,24 +26,27 @@ export class Desorientation extends Draconique { code() { return 'desorientation' } tooltip(linkData) { return `Désorientation, cette case n'existe plus !` } - img() { return 'icons/svg/explosion.svg' } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/desorientation.svg' } createSprite(pixiTMR) { - return pixiTMR.sprite(this.code(), - { + return TMRAnimations.withAnimation( + pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.trounoir, - color: tmrColors.trounoir, - alpha: 1, - taille: tmrConstants.full, - decallage: { x: 2, y: 2 }, - }); + taille: () => pixiTMR.sizes.full, + }), + pixiTMR, + TMRAnimations.rotation({ + frequence: delta => 2^(2 + Math.random() * 12) * 70, + angle: delta => (Math.floor(Math.random() * 2) - 1) * 30 + }) + ) } async _creerCasesTmr(actor, type, souffle) { const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.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); + await this.createCaseTmr(actor, 'Désorientation', tmr, souffle.id); } } diff --git a/module/tmr/draconique.js b/module/tmr/draconique.js index 7095321a..88f75f17 100644 --- a/module/tmr/draconique.js +++ b/module/tmr/draconique.js @@ -9,14 +9,15 @@ const registeredEffects = [ * Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR */ export class Draconique { + static init() { + } + static isCaseTMR(item) { return item.type == TYPES.casetmr; } static isQueueDragon(item) { return item.isQueueDragon(); } static isSouffleDragon(item) { return item.type == TYPES.souffle; } static isTeteDragon(item) { return item.type == TYPES.tete; } static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); } - tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.system.coord); } - static register(draconique) { registeredEffects[draconique.code()] = draconique; if (draconique.img()) { @@ -33,6 +34,8 @@ export class Draconique { return registeredEffects[code]; } + tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.system.coord); } + /** * @param item un Item quelconque * @returns true si l'item correspond @@ -96,32 +99,13 @@ export class Draconique { return token; } - /** - * methode en charge de recalculer le tooltip lorsque la souris bouge - * @param {*} event evenement contenant les coordonnées - * @param {*} sprite sprite pour laquelle calculer le tooltip - */ - computeTooltip(event, sprite) { - if (sprite.isOver) { - const oddq = TMRUtility.computeEventOddq(event); - const coord = TMRUtility.oddqToCoordTMR(oddq); - const tmr = TMRUtility.getTMR(coord) - if (tmr){ - const label = TMRUtility.getTMRLabel(coord); - const text = this.tooltip(this.linkData); - return text ? `${coord}: ${label}\n${text}` : `${coord}: ${label}` - } - } - return ''; - } - /** * 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. */ createSprite(pixiTMR) { if (this.img()) { - return pixiTMR.sprite(this.code()); + return pixiTMR.sprite(this.code()) } else { return pixiTMR.circle() @@ -143,7 +127,9 @@ export class Draconique { async createCaseTmr(actor, label, tmr, sourceId = undefined) { const casetmrData = { - name: label, type: 'casetmr', img: this.img(), + name: label, + type: 'casetmr', + img: this.img(), system: { coord: tmr.coord, specific: this.code(), sourceid: sourceId } }; await actor.createEmbeddedDocuments('Item', [casetmrData]); diff --git a/module/tmr/effets-draconiques.js b/module/tmr/effets-draconiques.js index 3bc8cfc6..42e45b2f 100644 --- a/module/tmr/effets-draconiques.js +++ b/module/tmr/effets-draconiques.js @@ -20,9 +20,9 @@ import { Grammar } from "../grammar.js"; import { AugmentationSeuil } from "./augmentation-seuil.js"; import { TYPES } from "../item.js"; - export class EffetsDraconiques { static carteTmr = new CarteTmr(); + static demiReve = new DemiReve(); static rencontre = new Rencontre(); static sortReserve = new SortReserve(); @@ -39,10 +39,13 @@ export class EffetsDraconiques { static pelerinage = new Pelerinage(); static periple = new Periple(); static urgenceDraconique = new UrgenceDraconique(); + static augmentationSeuil = new AugmentationSeuil(); static init() { + Draconique.init(); Draconique.register(EffetsDraconiques.carteTmr); + // icône TMR Draconique.register(EffetsDraconiques.demiReve); Draconique.register(EffetsDraconiques.rencontre); Draconique.register(EffetsDraconiques.sortReserve); @@ -59,6 +62,7 @@ export class EffetsDraconiques { Draconique.register(EffetsDraconiques.pelerinage); Draconique.register(EffetsDraconiques.periple); Draconique.register(EffetsDraconiques.urgenceDraconique); + // effets sans icône TMR Draconique.register(EffetsDraconiques.augmentationSeuil) } @@ -184,5 +188,4 @@ export class EffetsDraconiques { return EffetsDraconiques.soufflesDragon(actor, 'péage').length > 0; } - } \ No newline at end of file diff --git a/module/tmr/fermeture-cites.js b/module/tmr/fermeture-cites.js index 48cd4e6a..69793bee 100644 --- a/module/tmr/fermeture-cites.js +++ b/module/tmr/fermeture-cites.js @@ -1,39 +1,32 @@ import { Grammar } from "../grammar.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class FermetureCites extends Draconique { - constructor() { - super(); - } - type() { return 'souffle' } match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('fermeture des cites'); } manualMessage() { return false } async onActorCreateOwned(actor, souffle) { await this._fermerLesCites(actor, souffle); } code() { return 'fermeture' } - tooltip(linkData) { return `La ${this.tmrLabel(linkData)} est fermée` } - img() { return 'icons/svg/door-closed.svg' } + tooltip(linkData) { return `Cité fermée` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/fermeture.svg' } createSprite(pixiTMR) { - return pixiTMR.sprite(this.code(), - { - zIndex: tmrTokenZIndex.conquete, - color: tmrColors.souffle, - alpha: 0.9, - taille: tmrConstants.full, - decallage: { x: 2, y: 0 } - }); + return pixiTMR.sprite(this.code(), { + zIndex: tmrTokenZIndex.conquete, + decallage: pixiTMR.sizes.decallage(0, 0), + taille: () => pixiTMR.sizes.full + }) } async _fermerLesCites(actor, souffle) { let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord); let ouvertes = TMRUtility.filterTMR(it => it.type == 'cite' && !existants.includes(it.coord)); for (let tmr of ouvertes) { - await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr, souffle.id); + await this.createCaseTmr(actor, 'Fermeture', tmr, souffle.id); } } } diff --git a/module/tmr/pelerinage.js b/module/tmr/pelerinage.js index e7b8dc30..298978b4 100644 --- a/module/tmr/pelerinage.js +++ b/module/tmr/pelerinage.js @@ -1,37 +1,36 @@ import { Grammar } from "../grammar.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; +import { TMRAnimations } from "./animation.js"; export class Pelerinage extends Draconique { - constructor() { - super(); - } - type() { return 'queue' } match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('pelerinage'); } manualMessage() { return false } - async onActorCreateOwned(actor, queue) { + async onActorCreateOwned(actor, queue) { let tmr = await TMRUtility.getTMRAleatoire(); - await this.createCaseTmr(actor, 'Pèlerinage: ' + tmr.label, tmr, queue.id); + await this.createCaseTmr(actor, 'Pèlerinage', tmr, queue.id); } - - + code() { return 'pelerinage' } - tooltip(linkData) { return `Votre pèlerinage en ${this.tmrLabel(linkData)}` } - img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/pelerin.webp' } - + tooltip(linkData) { return `Lieu de pèlerinage` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/pelerinage.svg' } + createSprite(pixiTMR) { - return pixiTMR.sprite(this.code(), { - zIndex: tmrTokenZIndex.conquete, - alpha: 1, - taille: tmrConstants.full, - decallage: tmrConstants.center - }); + return TMRAnimations.withAnimation( + pixiTMR.sprite(this.code(), { + zIndex: tmrTokenZIndex.conquete, + decallage: pixiTMR.sizes.decallage(0, 0), + taille: () => pixiTMR.sizes.half, + }), + pixiTMR, + TMRAnimations.changeZoom() + ) } - + async onActorDeleteCaseTmr(actor, casetmr) { await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]); } diff --git a/module/tmr/periple.js b/module/tmr/periple.js index 326e16e4..7ab316e0 100644 --- a/module/tmr/periple.js +++ b/module/tmr/periple.js @@ -1,15 +1,12 @@ import { Grammar } from "../grammar.js"; import { RdDDice } from "../rdd-dice.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; +import { TMRAnimations } from "./animation.js"; export class Periple extends Draconique { - constructor() { - super(); - } - type() { return 'souffle' } match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('periple'); } manualMessage() { return false } @@ -18,22 +15,25 @@ export class Periple extends Draconique { let terrain = (await RdDDice.rollTotal("1d2")) == 1 ? 'sanctuaire' : 'necropole'; let tmrs = TMRUtility.getListTMR(terrain); for (let tmr of tmrs) { - await this.createCaseTmr(actor, 'Périple: ' + tmr.label, tmr, souffle.id); + await this.createCaseTmr(actor, 'Périple', tmr, souffle.id); } } code() { return 'periple' } - tooltip(linkData) { return `Votre Périple passe par ${this.tmrLabel(linkData)}` } - img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/pelerin.webp' } + tooltip(linkData) { return `Etape de périple` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/periple.svg' } createSprite(pixiTMR) { - return pixiTMR.sprite(this.code(), { - zIndex: tmrTokenZIndex.conquete, - alpha: 1, - taille: tmrConstants.full, - decallage: tmrConstants.center - }); + return TMRAnimations.withAnimation( + pixiTMR.sprite(this.code(), { + zIndex: tmrTokenZIndex.conquete, + decallage: pixiTMR.sizes.decallage(0, 0), + taille: () => pixiTMR.sizes.half + }), + pixiTMR, + TMRAnimations.changeZoom() + ) } getDifficulte(tmr) { switch (tmr.type) { diff --git a/module/tmr/pixi-tmr.js b/module/tmr/pixi-tmr.js index 1f5f3cd0..2d078bc8 100644 --- a/module/tmr/pixi-tmr.js +++ b/module/tmr/pixi-tmr.js @@ -1,35 +1,61 @@ +import { SYSTEM_RDD } from "../constants.js"; import { Misc } from "../misc.js"; -import { RdDTMRDialog } from "../rdd-tmr-dialog.js"; -import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; +import { TMRConstants, tmrTokenZIndex } from "../tmr-constants.js"; import { TMRUtility } from "../tmr-utility.js"; import { EffetsDraconiques } from "./effets-draconiques.js"; -export const tooltipStyle = new PIXI.TextStyle({ - fontFamily: 'CaslonAntique', - fontSize: 18, - fill: '#FFFFFF', - stroke: '#000000', - strokeThickness: 3 -}); - - export class PixiTMR { - static textures = [] - constructor(tmrDialog) { + static getImgFromCode(code) { + return PixiTMR.textures[code] + } + + static register(name, img) { + PixiTMR.textures[name] = img; + } + static async init() { + await Promise.all( + Object.values(PixiTMR.textures) + .filter(img => img != undefined) + .map(async img => PIXI.Sprite.from(await PIXI.Assets.load(img))) + ) + } + + constructor(tmrDialog, displaySize) { this.tmrDialog = tmrDialog; - this.callbacksOnAnimate = []; - - this.pixiApp = new PIXI.Application({ width: 720, height: 860 }); + this.sizes = new TMRConstants({ size: displaySize }) + this.pixiApp = new PIXI.Application(PixiTMR.computeTMRSize(this.sizes)); this.pixiApp.eventMode = 'static'; this.pixiApp.stage.sortableChildren = true; - this.tooltip = new PIXI.Text('', tooltipStyle); + + this.tooltipStyle = new PIXI.TextStyle({ + fontFamily: 'CaslonAntique', + fontSize: 16, + fill: '#FFFFFF', + stroke: '#000000', + strokeThickness: 4 + }); + + this.tooltip = new PIXI.Text('', this.tooltipStyle); this.tooltip.zIndex = 1000 this.pixiApp.stage.addChild(this.tooltip); + } + close() { + this.pixiApp.ticker.stop(); + } + static computeTMRSize(sizeConstants) { + return { width: sizeConstants.cellw * 13 + sizeConstants.marginx, height: sizeConstants.cellh / 2 + sizeConstants.cellh * 15 + sizeConstants.marginy } + } + + resizeTMR(displaySize) { + this.sizes = new TMRConstants({ size: displaySize }) + const appSize = PixiTMR.computeTMRSize(this.sizes) + this.pixiApp.renderer.resize(appSize.width, appSize.height) + this.tooltipStyle.fontSize = Math.max(this.sizes.size / 4, 16) } get view() { @@ -48,24 +74,11 @@ export class PixiTMR { .on('pointerout', event => this.onHideTooltip(event)); } - async load(onLoad = (loader, resources) => { }) { - // WIP - Deprecated since v7 : let loader = new PIXI.Loader(); - for (const [name, img] of Object.entries(PixiTMR.textures)) { - const texture = await PIXI.Assets.load(img); - let image = PIXI.Sprite.from(texture); - } - onLoad(); + async loadAnimations() { for (let onAnimate of this.callbacksOnAnimate) { onAnimate(); } - } - - static getImgFromCode(code) { - return PixiTMR.textures[code] - } - - static register(name, img) { - PixiTMR.textures[name] = img; + this.pixiApp.ticker.start(); } animate(animation = pixiApp => { }) { @@ -90,33 +103,48 @@ export class PixiTMR { sprite(code, options = {}) { let img = PixiTMR.getImgFromCode(code) - const texture = PIXI.utils.TextureCache[img]; + const texture = PIXI.utils.TextureCache[img] if (!texture) { console.error("Texture manquante", code, PIXI.utils.TextureCache) return; } let sprite = new PIXI.Sprite(texture); - sprite.width = options.taille ?? tmrConstants.half; - sprite.height = options.taille ?? tmrConstants.half; - sprite.anchor.set(0.5); - if (options.color) { - sprite.tint = options.color; + sprite.taille = options.taille ?? (() => this.sizes.half) + + sprite.width = sprite.taille() + sprite.height = sprite.taille() + sprite.anchor.set(0.5) + if (options.tint) { + sprite.tint = options.tint } - sprite.zIndex = options.zIndex ?? tmrTokenZIndex.casehumide + 1; - sprite.alpha = options.alpha ?? 0.75; - sprite.decallage = options.decallage ?? tmrConstants.center; - this.pixiApp.stage.addChild(sprite); - return sprite; + sprite.zIndex = options.zIndex ?? tmrTokenZIndex.casehumide + 1 + sprite.alpha = options.alpha ?? 1 + sprite.decallage = options.decallage ?? this.sizes.center + this.pixiApp.stage.addChild(sprite) + return sprite } circle(code, options = {}) { + let sprite = new PIXI.Graphics() + sprite.taille = options.taille ?? (() => this.sizes.half) + sprite.decallage = options.decallage ?? this.sizes.topLeft + sprite.beginFill(options.tint, options.opacity) + sprite.drawCircle(0, 0, sprite.taille()) + sprite.endFill() + this.pixiApp.stage.addChild(sprite) + return sprite + } + + square(code, options = {}) { let sprite = new PIXI.Graphics(); - sprite.beginFill(options.color, options.opacity); - sprite.drawCircle(0, 0, (options.taille ?? 12) / 2); - sprite.endFill(); - sprite.decallage = options.decallage ?? tmrConstants.topLeft; - this.pixiApp.stage.addChild(sprite); - return sprite; + sprite.taille = options.taille ?? (() => this.sizes.half) + sprite.decallage = options.decallage ?? this.sizes.topLeft + sprite.beginFill(options.tint, options.opacity) + const size = sprite.taille(); + sprite.drawRect(0, 0, size, size) + sprite.endFill() + this.pixiApp.stage.addChild(sprite) + return sprite } onClickBackground(event) { @@ -131,7 +159,7 @@ export class PixiTMR { this.tooltip.text = this.computeTooltip(event); } } - + onShowTooltip(event) { if (!this.carteTMR.isOver) { this.setTooltipPosition(event); @@ -149,25 +177,27 @@ export class PixiTMR { } computeTooltip(event) { - const oddq = TMRUtility.computeEventOddq(event); + const oddq = this.sizes.computeEventOddq(event); const coordTMR = TMRUtility.oddqToCoordTMR(oddq); const tmr = TMRUtility.getTMR(coordTMR) if (tmr) { - const labelTMR = TMRUtility.getTMRLabel(coordTMR); + const tmrTooltip = `${coordTMR}: ${TMRUtility.getTMRLabel(coordTMR)}`; const tokenTooltips = this.tmrDialog.allTokens .filter(token => token.coordTMR() == coordTMR) .map(token => token.tooltip); - const tmrTooltip = `${coordTMR}: ${labelTMR}`; return [tmrTooltip, ...tokenTooltips].reduce(Misc.joining('\n')) } } - setTooltipPosition(event) { - var { x, y } = TMRUtility.computeEventPosition(event); - const oddq = TMRUtility.computeOddq(x, y); + computeEventOddq(event) { + return this.sizes.computeEventOddq(event) + } - this.tooltip.x = x + (oddq.col > 8 ? -3 * tmrConstants.full : tmrConstants.half); - this.tooltip.y = y + (oddq.row > 10 ? -tmrConstants.half : tmrConstants.half); + setTooltipPosition(event) { + const oddq = this.sizes.computeEventOddq(event); + + this.tooltip.x = oddq.x + (oddq.col > 7 ? -3 * this.sizes.full : this.sizes.quarter); + this.tooltip.y = oddq.y + (oddq.row > 10 ? -this.sizes.size : 0); } positionToken(token) { @@ -175,11 +205,11 @@ export class PixiTMR { const sprite = token.sprite; const oddq = TMRUtility.coordTMRToOddq(token.coordTMR()); - const decallagePairImpair = (oddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; - const dx = (sprite.decallage == undefined) ? 0 : sprite.decallage.x; - const dy = (sprite.decallage == undefined) ? 0 : sprite.decallage.y; - sprite.x = tmrConstants.gridx + (oddq.col * tmrConstants.cellw) + dx; - sprite.y = tmrConstants.gridy + (oddq.row * tmrConstants.cellh) + dy + decallagePairImpair; + const decallagePairImpair = (oddq.col % 2 == 0) ? this.sizes.col1_y : this.sizes.col2_y; + const dx = sprite.decallage?.x ?? 0 + const dy = sprite.decallage?.y ?? 0 + sprite.x = this.sizes.gridx + (oddq.col * this.sizes.cellw) + dx; + sprite.y = this.sizes.gridy + (oddq.row * this.sizes.cellh) + dy + decallagePairImpair; } } @@ -190,10 +220,9 @@ export class PixiTMR { } getCaseRectangle(oddq) { - let decallagePairImpair = (oddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; - let x = tmrConstants.gridx + (oddq.col * tmrConstants.cellw) - (tmrConstants.cellw / 2); - let y = tmrConstants.gridy + (oddq.row * tmrConstants.cellh) - (tmrConstants.cellh / 2) + decallagePairImpair; - return { x: x, y: y, w: tmrConstants.cellw, h: tmrConstants.cellh }; + const decallagePairImpair = (oddq.col % 2 == 0) ? this.sizes.col1_y : this.sizes.col2_y; + const x = this.sizes.gridx + (oddq.col * this.sizes.cellw) - (this.sizes.cellw / 2); + const y = this.sizes.gridy + (oddq.row * this.sizes.cellh) - (this.sizes.cellh / 2) + decallagePairImpair; + return { x, y, w: this.sizes.cellw, h: this.sizes.cellh }; } - } \ No newline at end of file diff --git a/module/tmr/pont-impraticable.js b/module/tmr/pont-impraticable.js index 7728cee1..98d14871 100644 --- a/module/tmr/pont-impraticable.js +++ b/module/tmr/pont-impraticable.js @@ -1,35 +1,30 @@ import { Grammar } from "../grammar.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class PontImpraticable extends Draconique { - constructor() { - super(); - } - type() { return 'souffle' } match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('impraticabilite des ponts'); } async onActorCreateOwned(actor, souffle) { const ponts = TMRUtility.getListTMR('pont'); for (let tmr of ponts) { - await this.createCaseTmr(actor, 'Pont impraticable: ' + tmr.label, tmr, souffle.id); + await this.createCaseTmr(actor, 'Pont impraticable', tmr, souffle.id); } } code() { return 'pont-impraticable' } - tooltip(linkData) { return `${this.tmrLabel(linkData)} impraticable` } - img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/wave.webp' } + tooltip(linkData) { return `Pont impraticable` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/debordement.svg' } createSprite(pixiTMR) { return pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.casehumide, - alpha: 0.6, - taille: tmrConstants.full, - decallage: tmrConstants.center + decallage: pixiTMR.sizes.decallage(0, 2/3), + taille: () => pixiTMR.sizes.half, }); } diff --git a/module/tmr/present-cites.js b/module/tmr/present-cites.js index d6bfb4d6..c3eade99 100644 --- a/module/tmr/present-cites.js +++ b/module/tmr/present-cites.js @@ -1,31 +1,26 @@ import { ChatUtility } from "../chat-utility.js"; import { Grammar } from "../grammar.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class PresentCites extends Draconique { - constructor() { - super(); - } - type() { return 'tete' } match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('present des cites'); } manualMessage() { return false } async onActorCreateOwned(actor, tete) { await this._ajouterPresents(actor, tete); } code() { return 'present-cites' } - tooltip(linkData) { return `La ${this.tmrLabel(linkData)} a un présent` } - img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/gift.webp' } + tooltip(linkData) { return `La cité a un présent` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/present.svg' } createSprite(pixiTMR) { return pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.tetes, - alpha: 0.9, - taille: tmrConstants.third, - decallage: tmrConstants.topRight + decallage: pixiTMR.sizes.decallage(-1, -1), + taille: () => pixiTMR.sizes.third }); } @@ -40,7 +35,7 @@ export class PresentCites extends Draconique { else { let cites = TMRUtility.filterTMR(it => it.type == 'cite'); for (let tmr of cites) { - await this.createCaseTmr(actor, 'Présent: ' + tmr.label, tmr, tete.id); + await this.createCaseTmr(actor, 'Présent', tmr, tete.id); } } } diff --git a/module/tmr/quete-eaux.js b/module/tmr/quete-eaux.js index ae5b979b..fc8f6252 100644 --- a/module/tmr/quete-eaux.js +++ b/module/tmr/quete-eaux.js @@ -1,28 +1,26 @@ import { Grammar } from "../grammar.js"; -import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; +import { TMRUtility } from "../tmr-utility.js"; import { Draconique } from "./draconique.js"; export class QueteEaux extends Draconique { - constructor() { - super(); - } type() { return 'tete' } match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes("quete des eaux"); } - manualMessage() { return "Vous devrez re-configurer votre Quête des Eaux une fois un lac ou marais vaincu" } + manualMessage() { return "Vous devrez re-configurer votre Nouvelle Quête des Eaux une fois un lac ou marais vaincu" } async onActorCreateOwned(actor, tete) { - await this.createCaseTmr(actor, "Quête des eaux à déterminer", { coord: 'A0' }, tete.id); + await this.createCaseTmr(actor, "Nouvelle Quête des Eaux", { coord: 'A0' }, tete.id); } code() { return 'maitrisee' } - tooltip(linkData) { return `Quête des eaux, le ${this.tmrLabel(linkData)} est maîtrisé` } - img() { return 'icons/svg/bridge.svg' } + tooltip(linkData) { return `Quête des eaux, ${TMRUtility.getTMRType(linkData.system.coord)} maîtrisé` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/maitrisee.svg' } createSprite(pixiTMR) { return pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.casehumide + 1, - color: tmrColors.tetes, - decallage: tmrConstants.topRight + decallage: pixiTMR.sizes.decallage(0, -2 / 3), + taille: () => pixiTMR.sizes.half }); } } diff --git a/module/tmr/rencontre.js b/module/tmr/rencontre.js index 7d38e017..d8d2d47e 100644 --- a/module/tmr/rencontre.js +++ b/module/tmr/rencontre.js @@ -1,12 +1,8 @@ -import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class Rencontre extends Draconique { - constructor() { - super(); - } - type() { return '' } match(item) { return false; } manualMessage() { return false } @@ -14,14 +10,13 @@ export class Rencontre extends Draconique { code() { return 'rencontre' } tooltip(rencontre) { return `${rencontre.name} de force ${rencontre.system.force}` } - img() { return 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp' } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/rencontre.svg' } createSprite(pixiTMR) { return pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.rencontre, - color: tmrColors.rencontre, - taille: tmrConstants.full, - decallage: { x: 2, y: 2 } - }); + decallage: pixiTMR.sizes.decallage(0, 0), + taille: () => pixiTMR.sizes.twoThird, + }) } } diff --git a/module/tmr/reserve-extensible.js b/module/tmr/reserve-extensible.js index ce0d8dab..9da18dbb 100644 --- a/module/tmr/reserve-extensible.js +++ b/module/tmr/reserve-extensible.js @@ -1,16 +1,13 @@ import { Grammar } from "../grammar.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class ReserveExtensible extends Draconique { - constructor() { - super(); - } type() { return 'tete' } match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes("reserve extensible"); } - manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" } + manualMessage() { return "Vous pouvez re-configurer votre Nouvelle Réserve extensible" } async onActorCreateOwned(actor, tete) { const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord); const selectedTMR = await TMRUtility.getTMRAleatoire(tmr => !(tmr.type == 'fleuve' || existants.includes(tmr.coord))); @@ -18,14 +15,15 @@ export class ReserveExtensible extends Draconique { } code() { return 'reserve_extensible' } - tooltip(linkData) { return `Réserve extensible en ${this.tmrLabel(linkData)} !` } - img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/treasure-chest.webp' } + tooltip(linkData) { return `Réserve extensible` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/reserve.svg' } createSprite(pixiTMR) { return pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.tetes, - alpha: 0.7, - decallage: tmrConstants.left + decallage: pixiTMR.sizes.decallage(-1, 1), + taille: () => pixiTMR.sizes.third + }); } diff --git a/module/tmr/sort-reserve.js b/module/tmr/sort-reserve.js index 767e32df..7f4bec3e 100644 --- a/module/tmr/sort-reserve.js +++ b/module/tmr/sort-reserve.js @@ -1,12 +1,8 @@ -import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class SortReserve extends Draconique { - constructor() { - super(); - } - type() { return '' } match(item) { return false; } manualMessage() { return false } @@ -14,13 +10,13 @@ export class SortReserve extends Draconique { code() { return 'sortreserve' } tooltip(sort) { return `${sort.name}, r${sort.system.ptreve}` } - img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/scroll.webp' } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/sort-reserve.svg' } createSprite(pixiTMR) { return pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.sort, - alpha: 0.5, - decallage: tmrConstants.right + decallage: pixiTMR.sizes.decallage(-1, 0), + taille: () => pixiTMR.sizes.third, }); } } diff --git a/module/tmr/terre-attache.js b/module/tmr/terre-attache.js index 6ef5cf38..39b54eae 100644 --- a/module/tmr/terre-attache.js +++ b/module/tmr/terre-attache.js @@ -1,29 +1,26 @@ import { Grammar } from "../grammar.js"; -import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class TerreAttache extends Draconique { - constructor() { - super(); - } type() { return 'tete' } match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes("terre d'attache"); } - manualMessage() { return "Vous pouvez re-configurer votre Terre d'Attache" } + manualMessage() { return "Vous pouvez re-configurer votre Nouvelle Terre d'attache" } async onActorCreateOwned(actor, tete) { - await this.createCaseTmr(actor, "Terre d'attache à déterminer", { coord: 'A0' }, tete.id); + await this.createCaseTmr(actor, "Nouvelle Terre d'attache", { coord: 'A0' }, tete.id); } code() { return 'attache' } - tooltip(linkData) { return `Terre d'attache en ${this.tmrLabel(linkData)} !` } - img() { return 'icons/svg/anchor.svg' } + tooltip(linkData) { return `Terre d'attache` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/attache.svg' } createSprite(pixiTMR) { return pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.tetes, - color: tmrColors.tetes, - decallage: tmrConstants.topLeft + decallage: pixiTMR.sizes.decallage(-1, -1), + taille: () => pixiTMR.sizes.third }); } diff --git a/module/tmr/trou-noir.js b/module/tmr/trou-noir.js index 23b995aa..557bf33c 100644 --- a/module/tmr/trou-noir.js +++ b/module/tmr/trou-noir.js @@ -1,12 +1,9 @@ import { Grammar } from "../grammar.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; export class TrouNoir extends Draconique { - constructor() { - super(); - } type() { return 'souffle' } match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('trou noir'); } @@ -15,21 +12,19 @@ export class TrouNoir extends Draconique { async onActorCreateOwned(actor, souffle) { const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord); const selectedTMR = await TMRUtility.getTMRAleatoire(tmr => !(TMRUtility.isCaseHumide(tmr) || existants.includes(tmr.coord))); - await this.createCaseTmr(actor, 'Trou noir: ' + selectedTMR.label, selectedTMR, souffle.id); + await this.createCaseTmr(actor, 'Trou noir', selectedTMR, souffle.id); } code() { return 'trounoir' } - tooltip(linkData) { return `Trou noir en ${this.tmrLabel(linkData)} !` } - img() { return 'icons/svg/explosion.svg' } + tooltip(linkData) { return `Trou noir` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/trounoir.svg' } createSprite(pixiTMR) { return pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.trounoir, - color: tmrColors.trounoir, - alpha: 1, taille: - tmrConstants.full, - decallage: { x: 2, y: 2 }, + decallage: pixiTMR.sizes.decallage(0, 0), + taille: () => pixiTMR.sizes.full, }); } diff --git a/module/tmr/urgence-draconique.js b/module/tmr/urgence-draconique.js index fda4fa19..03a6f94b 100644 --- a/module/tmr/urgence-draconique.js +++ b/module/tmr/urgence-draconique.js @@ -3,8 +3,10 @@ import { Grammar } from "../grammar.js"; import { Misc } from "../misc.js"; import { RdDRollTables } from "../rdd-rolltables.js"; import { TMRUtility } from "../tmr-utility.js"; -import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js"; +import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; +import { TYPES } from "../item.js"; +import { TMRAnimations } from "./animation.js"; export class UrgenceDraconique extends Draconique { @@ -27,7 +29,7 @@ export class UrgenceDraconique extends Draconique { const demiReve = actor.getDemiReve(); coordSortsReserve.sort(Misc.ascending(t => TMRUtility.distanceCoordTMR(t, demiReve))); const tmr = TMRUtility.getTMR(coordSortsReserve[0]); - await this.createCaseTmr(actor, 'Urgence draconique: ' + tmr.label, tmr, queue.id); + await this.createCaseTmr(actor, 'Urgence draconique', tmr, queue.id); } } @@ -36,16 +38,18 @@ export class UrgenceDraconique extends Draconique { } code() { return 'urgence' } - tooltip(linkData) { return `Urgence draconique!` } - img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/pelerin.webp' } + tooltip(linkData) { return `Urgence draconique` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/urgence.svg' } createSprite(pixiTMR) { - return pixiTMR.sprite(this.code(), - { + return TMRAnimations.withAnimation( + pixiTMR.sprite(this.code(), { zIndex: tmrTokenZIndex.conquete, - color: tmrColors.queues, - taille: tmrConstants.full, - decallage: { x: 2, y: 0 } - }); + decallage: pixiTMR.sizes.decallage(0, 0), + taille: () => pixiTMR.sizes.half, + }), + pixiTMR, + TMRAnimations.changeZoom() + ) } } diff --git a/packs/faune-flore-mineraux.db b/packs/faune-flore-mineraux.db index f75c5f4c..b42eb60e 100644 --- a/packs/faune-flore-mineraux.db +++ b/packs/faune-flore-mineraux.db @@ -12,7 +12,7 @@ {"name":"Lièvre","type":"faune","img":"systems/foundryvtt-reve-de-dragon/icons/faune/lapin.webp","system":{"description":"

Lièvre. Plaine, 4 kg, 8 sust.

","descriptionmj":"","encombrement":2,"quantite":1,"qualite":0,"cout":0,"milieu":"Plaines","environnement":[{"milieu":"Plaines","rarete":"Frequente","frequence":18}],"sust":8,"exotisme":0,"categorie":"","actor":{"id":"","pack":"","name":""}},"effects":[],"flags":{"core":{"sourceId":"Item.LU5eutNQqwm52oOG"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.0","coreVersion":"10.291","createdTime":1670580597921,"modifiedTime":1673657676879,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"5rGi4IeFyxQwyOOq","folder":null,"sort":0,"ownership":{"default":0,"jtRmvSuwkwMmIMf0":3}} {"name":"Salsimir ventru","type":"plante","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.faune-flore-mineraux.66Rzf8phcEQRIShv"}},"img":"systems/foundryvtt-reve-de-dragon/icons/botanique/Salsimir%20ventru.webp","effects":[],"_id":"66Rzf8phcEQRIShv","system":{"description":"

À points jaunes ou à points rouges, le salsimir ventru se distingue par un pied large et renflé.

\n

Rare.

","descriptionmj":"","encombrement":0.1,"quantite":1,"qualite":4,"cout":0,"milieu":"Lieux sombres et humides","environnement":[{"milieu":"Forêts","rarete":"Rare","frequence":9},{"milieu":"Sous-sols","rarete":"Rarissime","frequence":3}],"sust":1,"exotisme":0,"niveau":4,"base":0,"categorie":"Cuisine","rarete":"Rare"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.0","coreVersion":"10.291","createdTime":1669734708517,"modifiedTime":1673792106248,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"name":"Sautille","type":"faune","img":"systems/foundryvtt-reve-de-dragon/icons/faune/oiseau.webp","system":{"description":"

Sautille. Rivage, 1 kg, 2 sust. Petit échassier voisin de la grue qui, au lieu de marcher tranquillement, passe son temps àsautiller sur ses longues pattes.

","descriptionmj":"","encombrement":0.5,"quantite":1,"qualite":0,"cout":0,"milieu":"Rivage","environnement":[{"milieu":"Cours d'eau","rarete":"Frequente","frequence":18}],"sust":2,"exotisme":0,"categorie":"","actor":{"id":"","pack":"","name":""}},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.faune-flore-mineraux.6bvChVkjsy5tsa4d"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.0","coreVersion":"10.291","createdTime":1670580597921,"modifiedTime":1673657676885,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"6bvChVkjsy5tsa4d","folder":null,"sort":0,"ownership":{"default":0,"jtRmvSuwkwMmIMf0":3}} -{"name":"Tricolet","type":"plante","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.faune-flore-mineraux.6gb2cjdPXI44ym8D"}},"img":"systems/foundryvtt-reve-de-dragon/icons/botanique/Tricollet.webp","effects":[],"_id":"6gb2cjdPXI44ym8D","system":{"description":"

Champignon à pied blanc, triple volve, et large chapeau vert à points bleus.

\n

Rare.

","descriptionmj":"","encombrement":0.1,"quantite":1,"qualite":4,"cout":0,"milieu":"Lieux sombres et humides","environnement":[{"milieu":"Forêts","rarete":"Rare","frequence":6},{"milieu":"Sous-sols","rarete":"Rarissime","frequence":3}],"sust":1,"exotisme":0,"niveau":4,"base":0,"categorie":"Cuisine","rarete":"Rare"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.0","coreVersion":"10.291","createdTime":1669734708518,"modifiedTime":1673792147727,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} +{"name":"Tricollet","type":"plante","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.faune-flore-mineraux.6gb2cjdPXI44ym8D"}},"img":"systems/foundryvtt-reve-de-dragon/icons/botanique/Tricollet.webp","effects":[],"_id":"6gb2cjdPXI44ym8D","system":{"description":"

Champignon à pied blanc, triple volve, et large chapeau vert à points bleus.

\n

Rare.

","descriptionmj":"","encombrement":0.1,"quantite":1,"qualite":4,"cout":0,"milieu":"Lieux sombres et humides","environnement":[{"milieu":"Forêts","rarete":"Rare","frequence":6},{"milieu":"Sous-sols","rarete":"Rarissime","frequence":3}],"sust":1,"exotisme":0,"niveau":4,"base":0,"categorie":"Cuisine","rarete":"Rare"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.0","coreVersion":"10.291","createdTime":1669734708518,"modifiedTime":1673792147727,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"name":"Lapin","type":"faune","img":"systems/foundryvtt-reve-de-dragon/icons/faune/lapin.webp","system":{"description":"

Lapin. Forêt, plaine, 2 kg, 5 sust.

","descriptionmj":"","encombrement":1,"quantite":1,"qualite":0,"cout":0,"milieu":"Forets, Plaines","environnement":[{"milieu":"Forêts","rarete":"Commune","frequence":54},{"milieu":"Plaines","rarete":"Commune","frequence":54}],"sust":5,"exotisme":0,"categorie":"","actor":{"id":"","pack":"","name":""}},"effects":[],"flags":{"core":{"sourceId":"Item.LU5eutNQqwm52oOG"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.0","coreVersion":"10.291","createdTime":1670580597921,"modifiedTime":1673657676879,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"6pDi7Pew5FZ3Ca1I","folder":null,"sort":0,"ownership":{"default":0,"jtRmvSuwkwMmIMf0":3}} {"name":"Salsimir à points verts","type":"plante","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.faune-flore-mineraux.7IV2V4ZotDEP2sLs"}},"img":"systems/foundryvtt-reve-de-dragon/icons/botanique/Salsimir%20%C3%A0%20points%20verts.webp","effects":[],"_id":"7IV2V4ZotDEP2sLs","system":{"description":"

Champignon semblable aux autres variétés de salsimir, hormis la couleur de ses points.

Pour l'empoisonnement, voir: @UUID[Compendium.foundryvtt-reve-de-dragon.maladies-et-poisons.Rx2nQjwaCa5s38Tm]{Salsimir à points verts}

Rare.

","descriptionmj":"","encombrement":0.1,"quantite":1,"qualite":0,"cout":0,"milieu":"Lieux sombres et humides","environnement":[{"milieu":"Forêts","rarete":"Rare","frequence":9},{"milieu":"Sous-sols","rarete":"Rarissime","frequence":3}],"sust":0,"exotisme":0,"niveau":null,"base":0,"categorie":"Poison","rarete":"Rare"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.0","coreVersion":"10.291","createdTime":1669734708518,"modifiedTime":1673792134571,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"name":"Tanemiel doré","type":"herbe","flags":{"core":{"sheetClass":"foundryvtt-reve-de-dragon.RdDItemSheet","sourceId":"Compendium.foundryvtt-reve-de-dragon.faune-flore-mineraux.7RgTRB47YPH74BwF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/botanique/Tanemiel%20dor%C3%A9.webp","effects":[],"_id":"7RgTRB47YPH74BwF","system":{"description":"

Herbe de soin.

\n

Variété de tanemiel aux feuilles luisantes de couleur ambrée.

\n

Rarissime.

\n

 

\n

Voir Les herbes de soin, p100.

","descriptionmj":"","encombrement":0,"quantite":1,"qualite":0,"cout":2,"milieu":"Forêts chaudes et humides","environnement":[{"milieu":"Forêts","rarete":"Rarissime","frequence":2}],"sust":0,"exotisme":0,"niveau":10,"base":0,"categorie":"Soin","rarete":"Rarissime"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.0","coreVersion":"10.291","createdTime":1669734708518,"modifiedTime":1673657676886,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} diff --git a/styles/img/ui/dir-bottom-left.svg b/styles/img/ui/dir-bottomleft.svg similarity index 100% rename from styles/img/ui/dir-bottom-left.svg rename to styles/img/ui/dir-bottomleft.svg diff --git a/styles/img/ui/dir-bottom-right.svg b/styles/img/ui/dir-bottomright.svg similarity index 100% rename from styles/img/ui/dir-bottom-right.svg rename to styles/img/ui/dir-bottomright.svg diff --git a/styles/img/ui/dir-top-left.svg b/styles/img/ui/dir-topleft.svg similarity index 100% rename from styles/img/ui/dir-top-left.svg rename to styles/img/ui/dir-topleft.svg diff --git a/styles/img/ui/dir-top-right.svg b/styles/img/ui/dir-topright.svg similarity index 100% rename from styles/img/ui/dir-top-right.svg rename to styles/img/ui/dir-topright.svg diff --git a/styles/simple.css b/styles/simple.css index 36e4b77f..a5f8122d 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -171,9 +171,6 @@ i:is(.fas, .far) { width: fit-content; } -.tmr-dialog table { - border: none; -} .system-foundryvtt-reve-de-dragon .sheet-header div.tmr-buttons { padding: 0; margin: 0; @@ -264,6 +261,39 @@ nav.sheet-tabs .item:after { border-right: 1px dashed rgba(52, 52, 52, 0.25); } +/* =================== Fenêtre TMR ============ */ +div.tmrdialog { + width: fit-content !important; + height: fit-content !important; + max-height: 1024px; +} +div.tmrdialog .window-content { + margin: 0; + padding: 0; + width: fit-content; + max-width: fit-content; + max-height: fit-content; +} +div.tmrdialog div.tmr-map { + width: fit-content; + height: fit-content; + max-height: 1024px; +} +div.tmrdialog div.tmr-actions{ + width: 12rem; + max-height: fit-content; +} +div.tmrdialog div.tmr-map { + width: min-content; + padding: 0; + font-size: 0; +} +div.tmrdialog div.tmr-actions { + vertical-align: top; + flex-basis: inherit; + flex: 'flex-shrink'; +} + /* =================== Autres ============ */ .tabs .item.active, diff --git a/system.json b/system.json index 59c30ff1..3930ad0a 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "11.1.6", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.1.6.zip", + "version": "v11.2.0", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-v11.2.0.zip", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "compatibility": { @@ -40,6 +40,19 @@ "flags": {} } ], + "flags": { + "hotReload": { + "extensions": [ + "css", + "hbs", + "html" + ], + "paths": [ + "styles/", + "templates/" + ] + } + }, "url": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/", "license": "LICENSE.txt", "esmodules": [ diff --git a/templates/dialog-tmr.html b/templates/dialog-tmr.html index 6ca5ed09..3b89000d 100644 --- a/templates/dialog-tmr.html +++ b/templates/dialog-tmr.html @@ -1,48 +1,60 @@ -
- - - - - -
+ +
+
+
+
+
+ © Scriptarium, 2023. +
Usage personnel et privé. +
+ {{#if (eq mode "visu")}} -
+

Visualisation!

{{else}} {{#if (and isGM hasPlayerOwner)}} -
+

Le gardien gére les TMR du joueur, le joueur ne peut pas monter dans les TMR!

{{/if}} -
- - - +
+ + +
-
- - - +
+ 0
-
+
+ + + +
+ -
+
-
+
-
+
0
-
- 0 -
-
+
0
-
+
0
@@ -50,8 +62,9 @@ {{{fatigue.html}}}
{{/if}} -
+
+
+ +