Réduction de l'espace des TMR
This commit is contained in:
@ -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()
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -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();
|
||||
|
@ -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,17 +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);
|
||||
}
|
||||
|
||||
@ -37,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
|
||||
@ -62,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();
|
||||
@ -89,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() {
|
||||
@ -129,8 +219,8 @@ export class RdDTMRDialog extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
createPixiSprites() {
|
||||
this.pixiTMR.setup()
|
||||
this.updateTokens();
|
||||
this.forceDemiRevePositionView();
|
||||
this.updateTokens()
|
||||
this.forceDemiRevePositionView()
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -207,43 +297,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
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._getCoordActor()));
|
||||
|
||||
this.html.find('tr.tmr-row *').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();
|
||||
let tmr = TMRUtility.getTMR(this._getCoordActor());
|
||||
await this.manageRencontre(tmr);
|
||||
}
|
||||
|
||||
calculCoutMonteeTMR() {
|
||||
return ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse();
|
||||
}
|
||||
@ -281,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) {
|
||||
@ -919,19 +974,18 @@ export class RdDTMRDialog extends Dialog {
|
||||
if (this.subdialog) {
|
||||
return this.forceTMRContinueAction()
|
||||
}
|
||||
let clickOddq = TMRUtility.computeEventOddq(event);
|
||||
let currentOddq = TMRUtility.coordTMRToOddq(this._getCoordActor());
|
||||
|
||||
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();
|
||||
@ -946,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);
|
||||
@ -1070,7 +1124,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_removeTokens(filter) {
|
||||
_removeTokens(filter = it => true) {
|
||||
this.allTokens.filter(filter).forEach(token => this.pixiTMR.removeToken(token))
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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 = {
|
||||
@ -237,8 +236,19 @@ const TMR_MOVE = {
|
||||
"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) {
|
||||
@ -340,7 +350,7 @@ export class TMRUtility {
|
||||
const oddq = TMRUtility.coordTMRToOddq(coord);
|
||||
const direction = await TMRUtility.getDirectionPattern(oddq);
|
||||
const currentOddq = TMRUtility.addOddq(oddq, direction)
|
||||
if (this.isOddqInTMR(currentOddq)) { // Sortie de carte ! Ré-insertion aléatoire
|
||||
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');
|
||||
@ -377,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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -393,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;
|
||||
@ -453,9 +429,9 @@ export class TMRUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
107
module/tmr/animation.js
Normal file
107
module/tmr/animation.js
Normal file
@ -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)
|
||||
}
|
||||
}
|
@ -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 }
|
||||
|
@ -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) : '';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 };
|
||||
}
|
||||
|
||||
}
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3,9 +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 {
|
||||
|
||||
@ -28,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user