Améliorations des tmr
* fermeture des cités * utilisations d'icônes pour les cases spéciales, rencontres, sorts en réserve * séparation pixi/actions TMR / définition des cases spéciales fixes divers: * #153 lancer de sort si draconic utilise compétence autre que rêve * #152: table de résolution doublée sur cht points de rêve * /table n'affichait plus les résultats suite à chgt sur souffles/queues
This commit is contained in:
20
module/tmr/carte-tmr.js
Normal file
20
module/tmr/carte-tmr.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class CarteTmr extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return '' }
|
||||
match(item) { return false; }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, item) { }
|
||||
|
||||
code() { return 'tmr' }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmp_main_r1.webp' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.carteTmr(this.code());
|
||||
}
|
||||
}
|
31
module/tmr/debordement.js
Normal file
31
module/tmr/debordement.js
Normal file
@ -0,0 +1,31 @@
|
||||
import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class Debordement extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return 'souffle' }
|
||||
match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase().includes('trou noir'); }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
|
||||
|
||||
code() { return 'debordement' }
|
||||
tooltip(linkData) { return `Débordement en ${TMRUtility.getTMR(linkData.data.coord).label}` }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(),
|
||||
{
|
||||
color: tmrColors.casehumide, alpha: 0.5, taille: tmrConstants.twoThird, decallage: tmrConstants.bottom
|
||||
});
|
||||
}
|
||||
|
||||
async _creerCaseTmr(actor) {
|
||||
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
const tmr = TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord)));
|
||||
await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr);
|
||||
}
|
||||
}
|
27
module/tmr/demi-reve.js
Normal file
27
module/tmr/demi-reve.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { tmrColors, tmrConstants } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class DemiReve extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return '' }
|
||||
match(item) { return false; }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, item) { }
|
||||
|
||||
code() { return 'demi-reve' }
|
||||
tooltip(linkData) { return `Demi-rêve` }
|
||||
img() { return 'icons/svg/sun.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
const sprite = pixiTMR.sprite(this.code(), {
|
||||
color: tmrColors.demireve,
|
||||
taille: (tmrConstants.full * 0.7)
|
||||
});
|
||||
pixiTMR.animate(pixiApp => pixiApp.ticker.add((delta) => sprite.rotation -= 0.01 * delta));
|
||||
return sprite;
|
||||
}
|
||||
}
|
118
module/tmr/draconique.js
Normal file
118
module/tmr/draconique.js
Normal file
@ -0,0 +1,118 @@
|
||||
import { PixiTMR } from "./pixi-tmr.js";
|
||||
|
||||
const registeredEffects = [
|
||||
]
|
||||
|
||||
/**
|
||||
* Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR
|
||||
*/
|
||||
export class Draconique
|
||||
{
|
||||
static isCaseTMR(element) { return element.type == 'casetmr'; }
|
||||
static isQueueDragon(element) { return element.type == 'queue' || element.type == 'ombre'; }
|
||||
static isSouffleDragon(element) { return element.type == 'souffle'; }
|
||||
static isTeteDragon(element) { return element.type == 'tete'; }
|
||||
static isQueueSouffle(it) { return Draconique.isQueueDragon(it) || Draconique.isSouffleDragon(it); }
|
||||
|
||||
static register(draconique) {
|
||||
registeredEffects[draconique.code()] = draconique;
|
||||
if (draconique.img()) {
|
||||
PixiTMR.register(draconique.code(), draconique.img())
|
||||
}
|
||||
return draconique;
|
||||
}
|
||||
|
||||
static all() {
|
||||
return Object.values(registeredEffects);
|
||||
}
|
||||
static get(code) {
|
||||
return registeredEffects[code];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param item un Item quelconque
|
||||
* @returns true si l'item correspond
|
||||
*/
|
||||
match(item) {
|
||||
return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item) || Draconique.isTeteDragon(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns un message à afficher si la draconique doit être gérée manuellement.
|
||||
*/
|
||||
manualMessage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode responsable de gérer une draconique (par exemple, ajouter des casetmr pour la fermeture des cités).
|
||||
* @param actor auquel la draconique est ajoutée
|
||||
*/
|
||||
async onActorCreateOwned(actor) {
|
||||
return false;
|
||||
}
|
||||
async onActorDeleteOwned(actor) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @return le code interne utilisé pour les casetmr correpondant
|
||||
*/
|
||||
code() { return undefined }
|
||||
|
||||
/**
|
||||
* @param {*} linkData données associées au token pixi (une casetmr, un sort en réserve, une rencontre en attente)
|
||||
* @returns un tooltip à afficher au dessus du token
|
||||
*/
|
||||
tooltip(linkData) { return undefined }
|
||||
|
||||
/**
|
||||
* @param {*} img l'url du fichier image à utiliser pour le token. Si indéfini (et si createSprite n'est pas surchargé),
|
||||
* un disque est utilisé.
|
||||
*/
|
||||
img() { return undefined }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
token(pixiTMR, linkData, coordTMR, type = undefined) {
|
||||
const token = {
|
||||
sprite: this._createSprite(pixiTMR),
|
||||
coordTMR: coordTMR
|
||||
};
|
||||
token[type ?? this.code()] = linkData;
|
||||
pixiTMR.addTooltip(token.sprite, this.tooltip(linkData));
|
||||
return token;
|
||||
|
||||
return sprite;
|
||||
}
|
||||
/**
|
||||
* factory d'élément graphique PIXI correpsondant à l'objet draconique
|
||||
* @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks.
|
||||
*/
|
||||
_createSprite(pixiTMR) {
|
||||
if (this.img()) {
|
||||
return pixiTMR.sprite(this.code());
|
||||
}
|
||||
else{
|
||||
return pixiTMR.circle()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} it un item à tester
|
||||
* @param {*} coord les coordonnées d'une case. Si undefined toute case du type correspondra,
|
||||
*/
|
||||
isCase(it, coord = undefined) {
|
||||
return Draconique.isCaseTMR(it) && it.data.specific == this.code() && (coord ? it.data.coord == coord : true);
|
||||
}
|
||||
|
||||
async createCaseTmr(actor, label, tmr) {
|
||||
await actor.createOwnedItem({
|
||||
name: label, type: 'casetmr', img: this.img(), _id: randomID(16),
|
||||
data: { coord: tmr.coord, specific: this.code() }
|
||||
});
|
||||
}
|
||||
|
||||
}
|
152
module/tmr/effets-draconiques.js
Normal file
152
module/tmr/effets-draconiques.js
Normal file
@ -0,0 +1,152 @@
|
||||
import { Debordement } from "./debordement.js";
|
||||
import { FermetureCites } from "./fermeture-cites.js";
|
||||
import { QueteEaux } from "./quete-eaux.js";
|
||||
import { TerreAttache } from "./terre-attache.js";
|
||||
import { ReserveExtensible } from "./reserve-extensible.js";
|
||||
import { DemiReve } from "./demi-reve.js";
|
||||
import { TrouNoir } from "./trou-noir.js";
|
||||
import { Rencontre } from "./rencontre.js";
|
||||
import { SortReserve } from "./sort-reserve.js";
|
||||
import { CarteTmr } from "./carte-tmr.js";
|
||||
import { PontImpraticable } from "./pont-impraticable.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
import { PresentCites } from "./present-cites.js";
|
||||
|
||||
|
||||
|
||||
export class EffetsDraconiques {
|
||||
static carteTmr = new CarteTmr();
|
||||
static demiReve = new DemiReve();
|
||||
static rencontre = new Rencontre();
|
||||
static sortReserve = new SortReserve();
|
||||
static debordement = new Debordement();
|
||||
static presentCites = new PresentCites();
|
||||
static fermetureCites = new FermetureCites();
|
||||
static queteEaux = new QueteEaux();
|
||||
static reserveExtensible = new ReserveExtensible();
|
||||
static terreAttache = new TerreAttache();
|
||||
static trouNoir = new TrouNoir();
|
||||
static pontImpraticable = new PontImpraticable();
|
||||
|
||||
static init() {
|
||||
Draconique.register(EffetsDraconiques.carteTmr);
|
||||
Draconique.register(EffetsDraconiques.demiReve);
|
||||
Draconique.register(EffetsDraconiques.rencontre);
|
||||
Draconique.register(EffetsDraconiques.sortReserve);
|
||||
Draconique.register(EffetsDraconiques.debordement);
|
||||
Draconique.register(EffetsDraconiques.fermetureCites);
|
||||
Draconique.register(EffetsDraconiques.queteEaux);
|
||||
Draconique.register(EffetsDraconiques.reserveExtensible);
|
||||
Draconique.register(EffetsDraconiques.terreAttache);
|
||||
Draconique.register(EffetsDraconiques.trouNoir);
|
||||
Draconique.register(EffetsDraconiques.pontImpraticable);
|
||||
Draconique.register(EffetsDraconiques.presentCites);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCaseInondee(caseTMR, coord) {
|
||||
return EffetsDraconiques.debordement.isCase(caseTMR, coord) || EffetsDraconiques.pontImpraticable.isCase(caseTMR, coord);
|
||||
}
|
||||
|
||||
static isCaseTrouNoir(caseTMR, coord) {
|
||||
return EffetsDraconiques.trouNoir.isCase(caseTMR, coord);
|
||||
}
|
||||
|
||||
static isReserveExtensible(caseTMR, coord) {
|
||||
return EffetsDraconiques.reserveExtensible.isCase(caseTMR, coord);
|
||||
}
|
||||
|
||||
static isTerreAttache(caseTMR, coord) {
|
||||
return EffetsDraconiques.terreAttache.isCase(caseTMR, coord);
|
||||
}
|
||||
|
||||
static isCiteFermee(caseTMR, coord) {
|
||||
return EffetsDraconiques.fermetureCites.isCase(caseTMR, coord);
|
||||
}
|
||||
|
||||
static isPresentCite(caseTMR, coord) {
|
||||
return EffetsDraconiques.presentCites.isCase(caseTMR, coord);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isMauvaiseRencontre(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('mauvaise rencontre'));
|
||||
}
|
||||
|
||||
static isMonteeLaborieuse(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('montée laborieuse'));
|
||||
}
|
||||
|
||||
static isFermetureCite(element) {
|
||||
/* -------------------------------------------- */
|
||||
return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.fermetureCites.match(it));
|
||||
}
|
||||
|
||||
static isPontImpraticable(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.pontImpraticable.match(it));
|
||||
}
|
||||
|
||||
static isDoubleResistanceFleuve(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase().includes('résistance du fleuve'));
|
||||
}
|
||||
|
||||
static isPeage(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase().includes('péage'));
|
||||
}
|
||||
|
||||
static isPeriple(element) {
|
||||
// TODO
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && ir.name.toLowerCase() == 'périple');
|
||||
}
|
||||
|
||||
static isDesorientation(element) {
|
||||
// TODO
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase() == 'désorientation');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isConquete(element) {
|
||||
// TODO
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'conquête');
|
||||
}
|
||||
|
||||
static isPelerinage(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'pélerinage');
|
||||
}
|
||||
|
||||
static countInertieDraconique(element) {
|
||||
return EffetsDraconiques.count(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase().includes('inertie draconique'));
|
||||
}
|
||||
|
||||
static isUrgenceDraconique(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'urgence draconique');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isDonDoubleReve(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name == 'Don de double-rêve');
|
||||
}
|
||||
|
||||
static isConnaissanceFleuve(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes('connaissance du fleuve'));
|
||||
}
|
||||
|
||||
static isReserveEnSecurite(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes(' en sécurité'));
|
||||
}
|
||||
|
||||
static isDeplacementAccelere(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes(' déplacement accéléré'));
|
||||
}
|
||||
|
||||
static isMatching(element, matcher) {
|
||||
return EffetsDraconiques.toItems(element).find(matcher);
|
||||
}
|
||||
static count(element, matcher) {
|
||||
return EffetsDraconiques.toItems(element).filter(matcher).length;
|
||||
}
|
||||
|
||||
static toItems(element) {
|
||||
return (element?.entity === 'Actor') ? element.data.items : (element?.entity === 'Item') ? [element] : [];
|
||||
}
|
||||
|
||||
}
|
33
module/tmr/fermeture-cites.js
Normal file
33
module/tmr/fermeture-cites.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class FermetureCites extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return 'souffle' }
|
||||
match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase() == 'fermeture des cités'; }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, item) { await this._fermerLesCites(actor); }
|
||||
|
||||
code() { return 'fermeture' }
|
||||
tooltip(linkData) { return `La ${TMRUtility.getTMR(linkData.data.coord).label} est fermée` }
|
||||
img() { return 'icons/svg/door-closed.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(),
|
||||
{
|
||||
color: tmrColors.souffle, alpha: 0.9, taille: tmrConstants.full, decallage: { x: 2, y: 0 }
|
||||
});
|
||||
}
|
||||
|
||||
async _fermerLesCites(actor) {
|
||||
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.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);
|
||||
}
|
||||
}
|
||||
}
|
148
module/tmr/pixi-tmr.js
Normal file
148
module/tmr/pixi-tmr.js
Normal file
@ -0,0 +1,148 @@
|
||||
import { tmrConstants } from "../tmr-utility.js";
|
||||
|
||||
const tooltipStyle = new PIXI.TextStyle({
|
||||
fontFamily: 'CaslonAntique',
|
||||
fontSize: 18,
|
||||
fill: '#FFFFFF',
|
||||
stroke: '#000000',
|
||||
strokeThickness: 3
|
||||
});
|
||||
|
||||
|
||||
export class PixiTMR {
|
||||
|
||||
static textures = []
|
||||
|
||||
constructor(tmrObject, pixiApp) {
|
||||
this.tmrObject = tmrObject;
|
||||
this.pixiApp = pixiApp ?? tmrObject.pixiApp;
|
||||
this.callbacksOnAnimate = [];
|
||||
}
|
||||
|
||||
load(onLoad = (loader, resources) => {}) {
|
||||
let loader = this.pixiApp.loader;
|
||||
for (const [name, img] of Object.entries(PixiTMR.textures)) {
|
||||
loader = loader.add(name, img);
|
||||
}
|
||||
loader.load((loader, resources) => {
|
||||
onLoad(loader, resources);
|
||||
for (let onAnimate of this.callbacksOnAnimate) {
|
||||
onAnimate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static register(name, img) {
|
||||
PixiTMR.textures[name] = img;
|
||||
}
|
||||
|
||||
animate(animation = pixiApp=>{})
|
||||
{
|
||||
this.callbacksOnAnimate.push(() => animation(this.pixiApp));
|
||||
}
|
||||
|
||||
carteTmr(code) {
|
||||
const carteTmr = new PIXI.Sprite(PIXI.utils.TextureCache[code]);
|
||||
// Setup the position of the TMR
|
||||
carteTmr.x = 0;
|
||||
carteTmr.y = 0;
|
||||
carteTmr.width = 720;
|
||||
carteTmr.height = 860;
|
||||
// Rotate around the center
|
||||
carteTmr.anchor.set(0);
|
||||
carteTmr.interactive = true;
|
||||
carteTmr.buttonMode = true;
|
||||
carteTmr.tmrObject = this;
|
||||
// atténue les couleurs des TMRs
|
||||
const tmrColorFilter = new PIXI.filters.ColorMatrixFilter();
|
||||
tmrColorFilter.contrast(1);
|
||||
tmrColorFilter.brightness(0.2);
|
||||
tmrColorFilter.saturate(-0.5);
|
||||
carteTmr.filters = [tmrColorFilter];
|
||||
if (!this.tmrObject.viewOnly) {
|
||||
carteTmr.on('pointerdown', event => this.onClickBackground(event));
|
||||
}
|
||||
this.pixiApp.stage.addChild(carteTmr);
|
||||
return carteTmr;
|
||||
}
|
||||
|
||||
sprite(code, options = {}) {
|
||||
const texture = PIXI.utils.TextureCache[code];
|
||||
if (!texture) {
|
||||
console.error("Texture manquante", code)
|
||||
return;
|
||||
}
|
||||
let sprite = new PIXI.Sprite(texture);
|
||||
sprite.width = options.taille ?? tmrConstants.half;
|
||||
sprite.height = options.taille ?? tmrConstants.half;
|
||||
sprite.anchor.set(0.5);
|
||||
sprite.tint = options.color ?? 0x000000;
|
||||
sprite.alpha = options.alpha ?? 0.75;
|
||||
sprite.decallage = options.decallage ?? tmrConstants.center;
|
||||
this.pixiApp.stage.addChild(sprite);
|
||||
return sprite;
|
||||
}
|
||||
|
||||
circle(name, 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;
|
||||
}
|
||||
|
||||
addTooltip(sprite, text) {
|
||||
if (text) {
|
||||
sprite.tooltip = new PIXI.Text(text, tooltipStyle);
|
||||
sprite.isOver = false;
|
||||
sprite.interactive = true;
|
||||
sprite.on('pointerdown', event => this.onClickBackground(event))
|
||||
.on('pointerover', () => this.onShowTooltip(sprite))
|
||||
.on('pointerout', () => this.onHideTooltip(sprite));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onClickBackground(event) {
|
||||
this.tmrObject.onClickTMR(event)
|
||||
}
|
||||
|
||||
onShowTooltip(sprite) {
|
||||
if (sprite.tooltip) {
|
||||
|
||||
if (!sprite.isOver) {
|
||||
sprite.tooltip.x = sprite.x;
|
||||
sprite.tooltip.y = sprite.y;
|
||||
this.pixiApp.stage.addChild(sprite.tooltip);
|
||||
}
|
||||
sprite.isOver = true;
|
||||
}
|
||||
}
|
||||
|
||||
onHideTooltip(sprite) {
|
||||
if (sprite.tooltip) {
|
||||
if (sprite.isOver) {
|
||||
this.pixiApp.stage.removeChild(sprite.tooltip);
|
||||
}
|
||||
sprite.isOver = false;
|
||||
}
|
||||
}
|
||||
|
||||
setPosition( sprite, pos) {
|
||||
let decallagePairImpair = (pos.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
let dx = (sprite.decallage == undefined) ? 0 : sprite.decallage.x;
|
||||
let dy = (sprite.decallage == undefined) ? 0 : sprite.decallage.y;
|
||||
sprite.x = tmrConstants.gridx + (pos.x * tmrConstants.cellw) + dx;
|
||||
sprite.y = tmrConstants.gridy + (pos.y * tmrConstants.cellh) + dy + decallagePairImpair;
|
||||
}
|
||||
|
||||
getCaseRectangle(pos) {
|
||||
let decallagePairImpair = (pos.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
let x = tmrConstants.gridx + (pos.x * tmrConstants.cellw) - (tmrConstants.cellw / 2);
|
||||
let y = tmrConstants.gridy + (pos.y * tmrConstants.cellh) - (tmrConstants.cellh / 2) + decallagePairImpair;
|
||||
return { x: x, y: y, w: tmrConstants.cellw, h: tmrConstants.cellh };
|
||||
}
|
||||
|
||||
}
|
40
module/tmr/pont-impraticable.js
Normal file
40
module/tmr/pont-impraticable.js
Normal file
@ -0,0 +1,40 @@
|
||||
import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class PontImpraticable extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return 'souffle' }
|
||||
match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase().includes('impraticabilité des ponts'); }
|
||||
|
||||
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
|
||||
async onActorDeleteOwned(actor, item) { await this._supprimerCaseTmr(actor); }
|
||||
|
||||
code() { return 'pont-impraticable' }
|
||||
tooltip(linkData) { return `${TMRUtility.getTMR(linkData.data.coord).label} impraticable` }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(),
|
||||
{
|
||||
color: tmrColors.casehumide, alpha: 0.5, taille: tmrConstants.twoThird, decallage: tmrConstants.bottom
|
||||
});
|
||||
}
|
||||
|
||||
async _creerCaseTmr(actor) {
|
||||
const ponts = TMRUtility.getListTMR('pont');
|
||||
for (let tmr of ponts) {
|
||||
await this.createCaseTmr(actor, 'Pont impraticable: ' + tmr.label, tmr);
|
||||
}
|
||||
}
|
||||
|
||||
async _supprimerCaseTmr(actor) {
|
||||
const existants = actor.data.items.filter(it => this.isCase(it));
|
||||
for (let caseTMR of existants) {
|
||||
await actor.deleteOwnedItem(caseTMR._id);
|
||||
}
|
||||
}
|
||||
}
|
42
module/tmr/present-cites.js
Normal file
42
module/tmr/present-cites.js
Normal file
@ -0,0 +1,42 @@
|
||||
import { ChatUtility } from "../chat-utility.js";
|
||||
import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class PresentCites extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return 'tete' }
|
||||
match(item) { return Draconique.isTeteDragon(item) && item.name.toLowerCase() == 'présent des cités'; }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, item) { await this._ajouterPresents(actor); }
|
||||
|
||||
code() { return 'present-cites' }
|
||||
tooltip(linkData) { return `La ${TMRUtility.getTMR(linkData.data.coord).label} a un présent` }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/gift.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(),
|
||||
{
|
||||
color: tmrColors.tetes, alpha: 0.7, taille: tmrConstants.third, decallage:tmrConstants.topRight
|
||||
});
|
||||
}
|
||||
|
||||
async _ajouterPresents(actor) {
|
||||
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
if (existants.length >0 ) {
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user),
|
||||
content: "Vous avez encore des présents dans des cités, vous devrez tirer une autre tête pour remplacer celle ci!"
|
||||
})
|
||||
}
|
||||
else{
|
||||
let cites = TMRUtility.filterTMR(it => it.type == 'cite');
|
||||
for (let tmr of cites) {
|
||||
await this.createCaseTmr(actor, 'Présent: ' + tmr.label, tmr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
module/tmr/quete-eaux.js
Normal file
25
module/tmr/quete-eaux.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { tmrColors, tmrConstants, 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) && item.name.toLowerCase().includes("quête des eaux"); }
|
||||
manualMessage() { return "Vous devrez re-configurer votre Quête des Eaux une fois un lac ou marais vaincu" }
|
||||
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
|
||||
|
||||
code() { return 'maitrisee' }
|
||||
tooltip(linkData) { return `Quête des eaux, le ${TMRUtility.getTMR(linkData.data.coord).label} est maîtrisé` }
|
||||
img() { return 'icons/svg/bridge.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(), { color: tmrColors.tetes, decallage: tmrConstants.topRight });
|
||||
}
|
||||
|
||||
async _creerCaseTmr(actor) {
|
||||
await this.createCaseTmr(actor, "Quête des eaux à déterminer", {coord:'A0'});
|
||||
}
|
||||
}
|
22
module/tmr/rencontre.js
Normal file
22
module/tmr/rencontre.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { tmrColors, tmrConstants } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class Rencontre extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return '' }
|
||||
match(item) { return false; }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, item) { }
|
||||
|
||||
code() { return 'rencontre' }
|
||||
tooltip(linkData) { return `${linkData.name} de force ${linkData.force}` }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(), { color: tmrColors.rencontre, taille: tmrConstants.full, decallage: { x: 2, y: 2 } });
|
||||
}
|
||||
}
|
28
module/tmr/reserve-extensible.js
Normal file
28
module/tmr/reserve-extensible.js
Normal file
@ -0,0 +1,28 @@
|
||||
import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class ReserveExtensible extends Draconique {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return 'tete' }
|
||||
match(item) { return Draconique.isTeteDragon(item) && item.name.toLowerCase().includes("réserve extensible"); }
|
||||
manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" }
|
||||
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
|
||||
|
||||
code() { return 'reserve_extensible' }
|
||||
tooltip(linkData) { return `Réserve extensible en ${TMRUtility.getTMR(linkData.data.coord).label} !` }
|
||||
img() { return 'icons/svg/chest.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(), { color: tmrColors.tetes, decallage: tmrConstants.left});
|
||||
}
|
||||
|
||||
async _creerCaseTmr(actor) {
|
||||
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
const tmr = TMRUtility.getTMRAleatoire(it => !(it.type == 'fleuve' || existants.includes(it.coord)));
|
||||
await this.createCaseTmr(actor, "Nouvelle Réserve extensible", tmr);
|
||||
}
|
||||
|
||||
}
|
22
module/tmr/sort-reserve.js
Normal file
22
module/tmr/sort-reserve.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { tmrColors, tmrConstants } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class SortReserve extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return '' }
|
||||
match(item) { return false; }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, item) { }
|
||||
|
||||
code() { return 'sort' }
|
||||
tooltip(linkData) { return `${linkData.name}, r${linkData.data.ptreve_reel}` }
|
||||
img() { return 'icons/svg/book.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(), { color: tmrColors.sort, decallage: tmrConstants.right });
|
||||
}
|
||||
}
|
25
module/tmr/terre-attache.js
Normal file
25
module/tmr/terre-attache.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class TerreAttache extends Draconique {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return 'tete' }
|
||||
match(item) { return Draconique.isTeteDragon(item) && item.name.toLowerCase().includes("terre d'attache"); }
|
||||
manualMessage() { return "Vous pouvez re-configurer votre Terre d'Attache" }
|
||||
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
|
||||
|
||||
code() { return 'attache' }
|
||||
tooltip(linkData) { return `Terre d'attache en ${TMRUtility.getTMR(linkData.data.coord).label} !` }
|
||||
img() { return 'icons/svg/anchor.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(), { color: tmrColors.tetes, decallage: tmrConstants.topLeft });
|
||||
}
|
||||
|
||||
async _creerCaseTmr(actor) {
|
||||
await this.createCaseTmr(actor, "Terre d'attache à déterminer", {coord:'A0'});
|
||||
}
|
||||
}
|
30
module/tmr/trou-noir.js
Normal file
30
module/tmr/trou-noir.js
Normal file
@ -0,0 +1,30 @@
|
||||
import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class TrouNoir extends Draconique {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return 'souffle' }
|
||||
match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase().includes('trou noir'); }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
|
||||
|
||||
code() { return 'trounoir' }
|
||||
tooltip(linkData) { return `Trou noir en ${TMRUtility.getTMR(linkData.data.coord).label} !` }
|
||||
img() { return 'icons/svg/explosion.svg' }
|
||||
|
||||
_createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(),
|
||||
{
|
||||
color: tmrColors.trounoir, alpha: 1, taille: tmrConstants.full, decallage: { x: 2, y: 2 },
|
||||
});
|
||||
}
|
||||
|
||||
async _creerCaseTmr(actor) {
|
||||
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
const tmr = TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord)));
|
||||
await this.createCaseTmr(actor, 'Trou noir: ' + tmr.label, tmr);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user