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:
@ -5,7 +5,6 @@
|
||||
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { RdDItemArme } from "./item-arme.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
526
module/actor.js
526
module/actor.js
File diff suppressed because it is too large
Load Diff
@ -1,41 +0,0 @@
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItem {
|
||||
|
||||
static isQueueDragon(item) {
|
||||
return item.type == 'queue' || item.type == 'ombre';
|
||||
}
|
||||
|
||||
static isSouffleDragon(item) {
|
||||
return item.type == 'souffle';
|
||||
}
|
||||
|
||||
static isHRPontImpraticable(item) {
|
||||
return RdDItem.isSouffleDragon(item) && item.name.toLowerCase().includes(' des ponts');
|
||||
}
|
||||
|
||||
static isHRDoubleResistanceFleuve(item) {
|
||||
return RdDItem.isSouffleDragon(item) && item.name.toLowerCase().includes('résistance du fleuve')
|
||||
}
|
||||
static isHRPeage(item) {
|
||||
return RdDItem.isSouffleDragon(item) && item.name.toLowerCase().includes('péage')
|
||||
}
|
||||
|
||||
static isHRMauvaiseRencontreEnPerspective(item) {
|
||||
return (RdDItem.isQueueDragon(item) || RdDItem.isSouffleDragon(item)) && item.name.toLowerCase().includes('mauvaise rencontre')
|
||||
}
|
||||
|
||||
static isHRInertieDraconique(item) {
|
||||
return RdDItem.isQueueDragon(item) && item.name.toLowerCase().includes('inertie draconique')
|
||||
}
|
||||
|
||||
static isCaseTMR(item) {
|
||||
return item.type == 'casetmr';
|
||||
}
|
||||
|
||||
static isHRCaseInnondee(item) {
|
||||
return RdDItem.isCaseTMR(item) && item.data.specific == 'debordement';
|
||||
}
|
||||
|
||||
}
|
@ -49,7 +49,8 @@ const poesieHautReve = [
|
||||
},
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
extrait: `Ainsi se cuccèdent les Jours et les Ages. Les jours des Dragons sont les Ages des Hommes`
|
||||
extrait: `Ainsi se cuccèdent les Jours et les Ages.
|
||||
<br>Les jours des Dragons sont les Ages des Hommes.`
|
||||
},
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
|
@ -22,12 +22,13 @@ export class RdDCommands {
|
||||
const rddCommands = new RdDCommands();
|
||||
rddCommands.registerCommand({ path: ["/aide"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
|
||||
rddCommands.registerCommand({ path: ["/help"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
|
||||
rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(), descr: "Tire une Queue de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(), descr: "Tire une Ombre de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(), descr: "Tire une Tête de Dragon pour Hauts Revants" });
|
||||
rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(), descr: "Tire une Tête de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle(), descr: " Tire un Souffle de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot(), descr: "Tire une carte du Tarot Draconique" });
|
||||
rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(true), descr: "Tire une Queue de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(true), descr: "Tire une Ombre de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(true), descr: "Tire une Tête de Dragon pour Hauts Revants" });
|
||||
rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(true), descr: "Tire une Tête de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle(true), descr: " Tire un Souffle de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence(true), descr: "Tire une compétence au hasard" });
|
||||
rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot(true), descr: "Tire une carte du Tarot Draconique" });
|
||||
rddCommands.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
|
||||
|
||||
rddCommands.registerCommand({
|
||||
@ -237,7 +238,7 @@ export class RdDCommands {
|
||||
getTMRAleatoire(msg, params) {
|
||||
if (params.length < 2) {
|
||||
let type = params[0];
|
||||
const tmr = TMRUtility.getTMRAleatoire(type);
|
||||
const tmr = TMRUtility.getTMRAleatoire(it => it.type == type);
|
||||
RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`);
|
||||
}
|
||||
else {
|
||||
|
@ -1,17 +1,15 @@
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/**
|
||||
* Mapping des types d'Item/Actor vers le nom d'affichage.
|
||||
* Par défaut, on prend le type avec la première lettre
|
||||
* majuscule, pas besoin d'ajouter tous les types.
|
||||
*/
|
||||
const typeDisplayName = {
|
||||
"objet": "Objet",
|
||||
"arme": "Arme",
|
||||
"armure": "Armure",
|
||||
"conteneur": "Conteneur",
|
||||
"competence": "Compétence",
|
||||
"sort": "Sort",
|
||||
"herbe": "Plante",
|
||||
"ingredient": "Ingrédient",
|
||||
"livre": "Livre",
|
||||
"potion": "Potion",
|
||||
"munition": "Munition",
|
||||
"queue": "Queue de dragon",
|
||||
"ombre": "Ombre de Thanatos",
|
||||
"souffle": "Souffle de Dragon",
|
||||
@ -20,20 +18,16 @@ const typeDisplayName = {
|
||||
"rencontresTMR": "Rencontre des TMR",
|
||||
"competencecreature": "Compétence de créature",
|
||||
"nombreastral": "Nombre astral",
|
||||
"casetmr": "Case des TMR",
|
||||
"casetmr": "Effet sur TMR",
|
||||
"recettealchimique": "Recette alchimique",
|
||||
"recettecuisine": "Recette de cuisine",
|
||||
"tarot": "Carte de tarot draconique",
|
||||
"tache": "Tâche",
|
||||
"meditation": "Méditation",
|
||||
"monnaie": "Monnaie",
|
||||
"musique": "Morceau de musique",
|
||||
"chant": "Chanson",
|
||||
"danse": "Danse",
|
||||
"jeu": "Jeu",
|
||||
"personnage": "Personnage",
|
||||
"creature": "Créature",
|
||||
"entite": "Entité de cauchemar",
|
||||
"entite": "Entité",
|
||||
"vehicule": "Véhicule"
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js";
|
||||
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||
import { RdDHotbar } from "./rdd-hotbar-drop.js"
|
||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
@ -234,6 +235,7 @@ Hooks.once("init", async function () {
|
||||
RdDActor.init();
|
||||
RddCompendiumOrganiser.init();
|
||||
ReglesOptionelles.init();
|
||||
EffetsDraconiques.init()
|
||||
TMRUtility.init();
|
||||
TMRRencontres.init();
|
||||
RdDHotbar.initDropbar();
|
||||
|
@ -179,12 +179,6 @@ export class RdDRoll extends Dialog {
|
||||
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#ptreve-variable').change((event) => {
|
||||
let ptreve = Misc.toInt(event.currentTarget.value);
|
||||
this.rollData.selectedSort.data.ptreve_reel = ptreve; // Update the selectedCarac
|
||||
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#coupsNonMortels').change((event) => {
|
||||
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
||||
this.updateRollResult();
|
||||
|
@ -34,6 +34,11 @@ export class RdDRollTables {
|
||||
return drawnItemRef.text;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async getCompetence(toChat = false) {
|
||||
return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async getSouffle(toChat = false) {
|
||||
return await RdDRollTables.drawItemFromRollTable("Souffles de Dragon", toChat);
|
||||
|
@ -1,24 +1,31 @@
|
||||
/**
|
||||
* Extend the base Dialog entity by defining a custom window to perform spell.
|
||||
* @extends {Dialog}
|
||||
*/
|
||||
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
import { tmrConstants } from "./tmr-utility.js";
|
||||
import { TMRUtility, tmrConstants } from "./tmr-utility.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDTMRRencontreDialog } from "./rdd-tmr-rencontre-dialog.js";
|
||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { RdDRoll } from "./rdd-roll.js";
|
||||
import { Poetique } from "./poetique.js";
|
||||
|
||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
import { PixiTMR } from "./tmr/pixi-tmr.js";
|
||||
import { Draconique } from "./tmr/draconique.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDTMRDialog extends Dialog {
|
||||
|
||||
static async create(html, actor, tmrData) {
|
||||
|
||||
if (tmrData.mode != 'visu') {
|
||||
// Notification au MJ
|
||||
ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatMessage.getWhisperRecipients("GM") });
|
||||
}
|
||||
|
||||
return new RdDTMRDialog(html, actor, tmrData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, actor, tmrData, mode) {
|
||||
constructor(html, actor, tmrData) {
|
||||
const dialogConf = {
|
||||
title: "Terres Médianes de Rêve",
|
||||
content: html,
|
||||
@ -38,19 +45,145 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.tmrdata = duplicate(tmrData);
|
||||
this.actor = actor;
|
||||
this.actor.tmrApp = this; // reference this app in the actor structure
|
||||
this.viewOnly = mode == "visu"
|
||||
this.viewOnly = tmrData.mode == "visu"
|
||||
this.fatigueParCase = this.viewOnly ? 0 : this.actor.getTMRFatigue();
|
||||
this.cumulFatigue = 0;
|
||||
this.rencontresExistantes = duplicate(this.actor.data.data.reve.rencontre.list);
|
||||
this.sortReserves = duplicate(this.actor.data.data.reve.reserve.list);
|
||||
this.casesSpeciales = this.actor.data.items.filter(item => item.type == 'casetmr');
|
||||
this.loadRencontres();
|
||||
this.loadSortsReserve();
|
||||
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item));
|
||||
this.allTokens = [];
|
||||
this.rencontreState = 'aucune';
|
||||
this.pixiApp = new PIXI.Application({ width: 720, height: 860 });
|
||||
|
||||
this.pixiTMR = new PixiTMR(this, this.pixiApp);
|
||||
|
||||
this.callbacksOnAnimate = [];
|
||||
if (!this.viewOnly) {
|
||||
this.actor.setStatusDemiReve(true);
|
||||
this._tellToGM(this.actor.name + " monte dans les terres médianes (" + mode + ")");
|
||||
this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
|
||||
}
|
||||
// load the texture we need
|
||||
this.pixiTMR.load((loader, resources) => this.createPixiSprites());
|
||||
}
|
||||
|
||||
loadSortsReserve() {
|
||||
this.sortsReserves = duplicate(this.actor.data.data.reve.reserve.list);
|
||||
}
|
||||
|
||||
loadRencontres() {
|
||||
this.rencontresExistantes = duplicate(this.actor.getTMRRencontres()).list;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
createPixiSprites() {
|
||||
EffetsDraconiques.carteTmr._createSprite(this.pixiTMR);
|
||||
|
||||
this.updateTokens();
|
||||
|
||||
this.demiReve = this._tokenDemiReve();
|
||||
this._updateDemiReve();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_createTokens() {
|
||||
let tokens = this._getTokensCasesTmr()
|
||||
.concat(this._getTokensRencontres())
|
||||
.concat(this._getTokensSortsReserve());
|
||||
|
||||
for (let t of tokens) {
|
||||
this._trackToken(t);
|
||||
}
|
||||
}
|
||||
|
||||
updateTokens() {
|
||||
this._removeTokens(t => true);
|
||||
this.loadRencontres();
|
||||
this.loadSortsReserve();
|
||||
this._createTokens();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getTokensCasesTmr() {
|
||||
return this.casesSpeciales.map(c => this._tokenCaseSpeciale(c)).filter(token => token);
|
||||
}
|
||||
_getTokensRencontres() {
|
||||
return this.rencontresExistantes.map(it => this._tokenRencontre(it));
|
||||
}
|
||||
_getTokensSortsReserve() {
|
||||
return this.sortsReserves.map(it => this._tokenSortEnReserve(it));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tokenRencontre(rencontre) {
|
||||
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
|
||||
}
|
||||
_tokenCaseSpeciale(caseSpeciale) {
|
||||
const draconique = Draconique.get(caseSpeciale.data.specific);
|
||||
return draconique?.token(this.pixiTMR, caseSpeciale, () => caseSpeciale.data.coord);
|
||||
}
|
||||
_tokenSortEnReserve(sortEnReserve) {
|
||||
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord);
|
||||
}
|
||||
_tokenDemiReve() {
|
||||
return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => this.actor.data.data.reve.tmrpos.coord);
|
||||
}
|
||||
|
||||
_updateDemiReve() {
|
||||
this._setTokenPosition(this.demiReve);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
document.getElementById("tmrrow1").insertCell(1).append(this.pixiApp.view);
|
||||
|
||||
if (this.viewOnly) {
|
||||
html.find('#lancer-sort').remove();
|
||||
}
|
||||
else {
|
||||
// Roll Sort
|
||||
html.find('#lancer-sort').click((event) => {
|
||||
this.actor.rollUnSort(this.actor.data.data.reve.tmrpos.coord);
|
||||
});
|
||||
}
|
||||
if (this.viewOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Gestion du cout de montée en points de rêve
|
||||
let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1)
|
||||
- this.actor.countMonteeLaborieuse();
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
await this.actor.reveActuelIncDec(reveCout);
|
||||
|
||||
// Le reste...
|
||||
this.updateValuesDisplay();
|
||||
let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord);
|
||||
await this.manageRencontre(tmr, () => {
|
||||
this.postRencontre(tmr);
|
||||
this.actor.displayTMRQueueSouffleInformation();
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateValuesDisplay() {
|
||||
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
||||
ptsreve.innerHTML = this.actor.data.data.reve.reve.value;
|
||||
|
||||
let tmrpos = document.getElementById("tmr-pos");
|
||||
let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord);
|
||||
tmrpos.innerHTML = this.actor.data.data.reve.tmrpos.coord + " (" + tmr.label + ")";
|
||||
|
||||
let etat = document.getElementById("tmr-etatgeneral-value");
|
||||
etat.innerHTML = this.actor.getEtatGeneral();
|
||||
|
||||
let refoulement = document.getElementById("tmr-refoulement-value");
|
||||
refoulement.innerHTML = this.actor.data.data.reve.refoulement.value;
|
||||
|
||||
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
||||
//console.log("Refresh : ", this.actor.data.data.sante.fatigue.value);
|
||||
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.data.data.sante.fatigue.value, this.actor.data.data.sante.endurance.max).html() + "</table>";
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -63,51 +196,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
displaySortReserve() {
|
||||
console.debug("displaySortReserve", this.sortReserves);
|
||||
for (let sort of this.sortReserves) {
|
||||
this._trackToken(this._tokenSortEnReserve(sort));
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
displaySpecificCase() {
|
||||
for (let caseSpeciale of this.casesSpeciales) {
|
||||
console.log("SPEC CASE ", caseSpeciale);
|
||||
if (caseSpeciale.data.specific == 'trounoir') {
|
||||
this._trackToken(this._tokenTrouNoir(caseSpeciale.data.coord));
|
||||
} else if (caseSpeciale.data.specific == 'attache') {
|
||||
this._trackToken(this._tokenTerreAttache(caseSpeciale.data.coord));
|
||||
} else if (caseSpeciale.data.specific == 'debordement') {
|
||||
this._trackToken(this._tokenDebordement(caseSpeciale.data.coord));
|
||||
} else if (caseSpeciale.data.specific == 'maitrisee') {
|
||||
this._trackToken(this._tokenMaitrisee(caseSpeciale.data.coord));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
displayPreviousRencontres() {
|
||||
console.debug("displayPreviousRencontres", this.rencontresExistantes);
|
||||
for (let rencontre of this.rencontresExistantes) {
|
||||
this._trackToken(this._tokenRencontre(rencontre));
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updatePreviousRencontres() {
|
||||
this._removeTokens(t => t.rencontre != undefined);
|
||||
this.rencontresExistantes = duplicate(this.actor.data.data.reve.rencontre.list);
|
||||
this.displayPreviousRencontres();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateSortReserve() {
|
||||
this._removeTokens(t => t.sort != undefined);
|
||||
this.sortReserves = duplicate(this.actor.data.data.reve.reserve.list);
|
||||
this.displaySortReserve();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async derober() {
|
||||
@ -121,7 +209,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
this._tellToGM(this.actor.name + " a refoulé : " + this.currentRencontre.name);
|
||||
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
|
||||
await this.actor.ajouterRefoulement(this.currentRencontre.refoulement ?? 1);
|
||||
this.updatePreviousRencontres();
|
||||
this.updateTokens();
|
||||
console.log("-> refouler", this.currentRencontre)
|
||||
this.updateValuesDisplay();
|
||||
this.nettoyerRencontre();
|
||||
@ -131,7 +219,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
async ignorerRencontre() {
|
||||
this._tellToGM(this.actor.name + " a ignoré : " + this.currentRencontre.name);
|
||||
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
|
||||
this.updatePreviousRencontres();
|
||||
this.updateTokens();
|
||||
this.updateValuesDisplay();
|
||||
this.nettoyerRencontre();
|
||||
}
|
||||
@ -166,7 +254,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
async choisirCaseType(type) {
|
||||
const locList = TMRUtility.getListCoordTMR(type);
|
||||
const locList = TMRUtility.filterTMR(it => it.type == type).map(it => it.coord);
|
||||
this.colorierZoneRencontre(locList);
|
||||
}
|
||||
|
||||
@ -200,9 +288,9 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async maitriser() {
|
||||
async maitriserRencontre() {
|
||||
this.actor.deleteTMRRencontreAtPosition();
|
||||
this.updatePreviousRencontres();
|
||||
this.updateTokens();
|
||||
|
||||
let rencontreData = {
|
||||
actor: this.actor,
|
||||
@ -218,6 +306,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this._tentativeMaitrise(rencontreData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _tentativeMaitrise(rencontreData) {
|
||||
console.log("-> matriser", rencontreData);
|
||||
|
||||
@ -227,7 +316,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
RollDataAjustements.calcul(rencontreData, this.actor);
|
||||
|
||||
rencontreData.rolled = await RdDResolutionTable.roll(rencontreData.reve, RollDataAjustements.sum(rencontreData.ajustements));
|
||||
|
||||
let postProcess = await TMRRencontres.gererRencontre(this, rencontreData);
|
||||
|
||||
ChatMessage.create({
|
||||
@ -257,6 +345,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_deleteTmrMessages(actor, nbRounds = -1) {
|
||||
setTimeout(() => {
|
||||
if (nbRounds < 0) {
|
||||
@ -307,60 +396,41 @@ export class RdDTMRDialog extends Dialog {
|
||||
if (rencontre) {
|
||||
return rencontre;
|
||||
}
|
||||
// TODO: dialog pour remplacer la rencontre par un présent
|
||||
//if (this.casesSpeciales.find(c => EffetsDraconiques.isPresentCite(c, tmr.coord))) {
|
||||
|
||||
|
||||
let myRoll = new Roll("1d7").evaluate().total;
|
||||
if (TMRUtility.isForceRencontre() || myRoll== 7) {
|
||||
if (TMRUtility.isForceRencontre() || myRoll == 7) {
|
||||
return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
|
||||
}
|
||||
this._tellToUser(myRoll + ": Pas de rencontre en " + tmr.label + " (" + tmr.coord + ")");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rencontreTMRRoll(tmr, isMauvaise = false) {
|
||||
let rencontre = TMRUtility.utiliseForceRencontre() ??
|
||||
isMauvaise ? await TMRRencontres.getMauvaiseRencontre()
|
||||
: await TMRRencontres.getRencontreAleatoire(tmr.type);
|
||||
(isMauvaise
|
||||
? await TMRRencontres.getMauvaiseRencontre()
|
||||
: await TMRRencontres.getRencontreAleatoire(tmr.type));
|
||||
rencontre.coord = tmr.coord;
|
||||
rencontre.date = game.system.rdd.calendrier.getDateFromIndex();
|
||||
rencontre.heure = game.system.rdd.calendrier.getCurrentHeure();
|
||||
return rencontre;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateValuesDisplay() {
|
||||
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
||||
ptsreve.innerHTML = this.actor.data.data.reve.reve.value;
|
||||
|
||||
let tmrpos = document.getElementById("tmr-pos");
|
||||
let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord);
|
||||
tmrpos.innerHTML = this.actor.data.data.reve.tmrpos.coord + " (" + tmr.label + ")";
|
||||
|
||||
let etat = document.getElementById("tmr-etatgeneral-value");
|
||||
etat.innerHTML = this.actor.getEtatGeneral();
|
||||
|
||||
let refoulement = document.getElementById("tmr-refoulement-value");
|
||||
refoulement.innerHTML = this.actor.data.data.reve.refoulement.value;
|
||||
|
||||
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
||||
//console.log("Refresh : ", this.actor.data.data.sante.fatigue.value);
|
||||
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.data.data.sante.fatigue.value, this.actor.data.data.sante.endurance.max).html() + "</table>";
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async manageCaseSpeciale(tmr) {
|
||||
for (let caseTMR of this.casesSpeciales) {
|
||||
if (caseTMR.data.coord == tmr.coord) { // Match !
|
||||
if (caseTMR.data.specific == 'trounoir') {
|
||||
let newTMR = TMRUtility.getTMRAleatoire();
|
||||
let tmrPos = duplicate(this.actor.data.data.reve.tmrpos);
|
||||
tmrPos.coord = newTMR.coord;
|
||||
await this.actor.update({ "data.reve.tmrpos": tmrPos });
|
||||
ChatMessage.create({
|
||||
content: "Vous êtes rentré sur un Trou Noir : ré-insertion aléatoire.",
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
});
|
||||
}
|
||||
}
|
||||
if (this.casesSpeciales.find(c => EffetsDraconiques.isCaseTrouNoir(c, tmr.coord))) {
|
||||
let newTMR = TMRUtility.getTMRAleatoire();
|
||||
let tmrPos = duplicate(this.actor.data.data.reve.tmrpos);
|
||||
tmrPos.coord = newTMR.coord;
|
||||
await this.actor.update({ "data.reve.tmrpos": tmrPos });
|
||||
ChatMessage.create({
|
||||
content: "Vous êtes rentré sur un Trou Noir : ré-insertion aléatoire.",
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,7 +446,8 @@ export class RdDTMRDialog extends Dialog {
|
||||
tmr: tmr,
|
||||
canClose: false,
|
||||
diffLibre: -7,
|
||||
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } }
|
||||
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
|
||||
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
|
||||
}
|
||||
rollData.competence.data.defaut_carac = 'reve-actuel';
|
||||
|
||||
@ -384,80 +455,125 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _rollMaitriseCaseHumide(rollData) {
|
||||
await this._maitriserTMR(rollData, r => this._resultatMaitriseCaseHumide(r));
|
||||
}
|
||||
|
||||
async _resultatMaitriseCaseHumide(rollData) {
|
||||
if (rollData.rolled.isETotal) {
|
||||
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
||||
}
|
||||
this.toclose = rollData.rolled.isEchec;
|
||||
if (rollData.rolled.isSuccess && !rollData.previous && EffetsDraconiques.isDoubleResistanceFleuve(this.actor)) {
|
||||
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
|
||||
await this._rollMaitriseCaseHumide(rollData);
|
||||
return;
|
||||
}
|
||||
rollData.poesie = Poetique.getExtrait();
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
|
||||
});
|
||||
if (rollData.rolled.isEchec) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isCaseHumide(tmr) {
|
||||
if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) {
|
||||
return undefined;
|
||||
}
|
||||
if (this.isCaseMaitrisee(tmr.coord)) {
|
||||
ChatMessage.create({
|
||||
content: tmr.label + ": cette case humide est déja maitrisée grâce à votre Tête <strong>Quête des Eaux</strong>",
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
});
|
||||
return false;
|
||||
return undefined;
|
||||
}
|
||||
if (this.actor.isCaseHumideAdditionelle(tmr)) {
|
||||
return true;
|
||||
}
|
||||
return tmr.type == "lac" || tmr.type == "fleuve" || tmr.type == "marais";
|
||||
return -7;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isCaseMaitrisee(coordTMR) {
|
||||
return this.casesSpeciales.find(it => it.data.coord = coordTMR && it.data.specific == 'maitrisee');
|
||||
isCaseHumideAdditionelle(tmr) {
|
||||
if (tmr.type == 'pont' && EffetsDraconiques.isPontImpraticable(this.actor)) {
|
||||
ChatMessage.create({
|
||||
content: tmr.label + ": Vous êtes sous le coup d'une Impraticabilité des Ponts : ce pont doit être maîtrisé comme une case humide.",
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (this.isCaseInondee(tmr.coord)) {
|
||||
ChatMessage.create({
|
||||
content: tmr.label + ": cette case est inondée, elle doit être maîtrisée comme une case humide.",
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async _rollMaitriseCaseHumide(rollData) {
|
||||
this.minimize(); // Hide
|
||||
const dialog = await RdDRoll.create(this.actor, rollData,
|
||||
{
|
||||
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-tmr-humide.html',
|
||||
options:{ height: 350 },
|
||||
close: html => { this.maximize(); } // Re-display TMR
|
||||
},
|
||||
{
|
||||
name: 'maitrise',
|
||||
label: 'Maîtriser le fleuve',
|
||||
callbacks: [
|
||||
this.actor.createCallbackExperience(),
|
||||
{ action: r => this._maitriseCaseHumide(r) }
|
||||
]
|
||||
/* -------------------------------------------- */
|
||||
async conquerirCiteFermee(tmr) {
|
||||
if (this.viewOnly || this.currentRencontre) {
|
||||
return;
|
||||
}
|
||||
const citeFermee = this.isCiteFermee(tmr.coord);
|
||||
if (citeFermee) {
|
||||
let rollData = {
|
||||
actor: this.actor,
|
||||
competence: duplicate(this.actor.getBestDraconic()),
|
||||
tmr: tmr,
|
||||
canClose: false,
|
||||
diffLibre: -9,
|
||||
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
|
||||
maitrise: { verbe: 'conquérir', action: 'Conquérir la cité' }
|
||||
}
|
||||
);
|
||||
dialog.render(true);
|
||||
}
|
||||
rollData.competence.data.defaut_carac = 'reve-actuel';
|
||||
|
||||
async _maitriseCaseHumide(rollData) {
|
||||
await this._maitriserTMR(rollData, r => this._resultatConqueteCiteFermee(r));
|
||||
}
|
||||
}
|
||||
async _resultatConqueteCiteFermee(rollData) {
|
||||
if (rollData.rolled.isETotal) {
|
||||
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
||||
}
|
||||
this.toclose = rollData.rolled.isEchec;
|
||||
if (rollData.rolled.isSuccess) {
|
||||
if (!rollData.previous && this.actor.isDoubleResistanceFleuve()) {
|
||||
ChatMessage.create({
|
||||
content: `Double résistance du fleuve: `,
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name)
|
||||
});
|
||||
rollData.previous = [rollData.rolled];
|
||||
await this._rollMaitriseCaseHumide(rollData);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rollData.poesie = Poetique.getExtrait();
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-fleuve-tmr.html`, rollData)
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
|
||||
});
|
||||
if (rollData.rolled.isEchec) {
|
||||
this.close();
|
||||
}
|
||||
|
||||
else {
|
||||
const citeFermee = this.actor.data.items.find(it => EffetsDraconiques.isCiteFermee(it, rollData.tmr.coord));
|
||||
this.actor.deleteOwnedItem(citeFermee._id);
|
||||
this._removeTokens(t => t.coordTMR() == citeFermee.data.coord && t.caseSpeciale?._id == citeFermee._id);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isReserveExtensible(coordTMR) {
|
||||
for (let caseTMR of this.casesSpeciales) {
|
||||
if (caseTMR.data.specific == 'reserve_extensible' && caseTMR.data.coord == coordTMR)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
async _maitriserTMR(rollData, callbackMaitrise) {
|
||||
this.minimize(); // Hide
|
||||
const dialog = await RdDRoll.create(this.actor, rollData,
|
||||
{
|
||||
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
|
||||
options: { height: 350 },
|
||||
close: html => { this.maximize(); } // Re-display TMR
|
||||
},
|
||||
{
|
||||
name: rollData.maitrise.verbe, label: rollData.maitrise.action,
|
||||
callbacks: [
|
||||
this.actor.createCallbackExperience(),
|
||||
{ action: callbackMaitrise }
|
||||
]
|
||||
}
|
||||
);
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -466,9 +582,9 @@ export class RdDTMRDialog extends Dialog {
|
||||
return;
|
||||
}
|
||||
|
||||
let sortReserveList = TMRUtility.getSortReserveList(this.sortReserves, coordTMR);
|
||||
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR);
|
||||
if (sortReserveList.length > 0) {
|
||||
if (this.actor.isReserveEnSecurite() || this.isReserveExtensible(coordTMR)) {
|
||||
if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coordTMR)) {
|
||||
let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête <strong>Reserve en Sécurité</strong> ou <strong>Réserve Exensible</strong>, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher : <ul>";
|
||||
for (let sortReserve of sortReserveList) {
|
||||
msg += "<li><a class='chat-card-button' id='sort-reserve' data-actor-id='" + this.actor._id + "' data-tmr-coord='" + coordTMR + "' data-sort-id='" + sortReserve.sort._id + "'>" + sortReserve.sort.name + "</a></li>";
|
||||
@ -483,9 +599,10 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
lancerSortEnReserve(coordTMR, sortId) {
|
||||
let sortReserveList = TMRUtility.getSortReserveList(this.sortReserves, coordTMR);
|
||||
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR);
|
||||
let sortReserve = sortReserveList.find(sortReserve => sortReserve.sort._id == sortId);
|
||||
//console.log("SORT RESA", sortReserveList, coordTMR, sortId, sortReserve);
|
||||
if (sortReserve) {
|
||||
@ -535,24 +652,34 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isTerreAttache(coordTMR) {
|
||||
for (let caseTMR of this.casesSpeciales) {
|
||||
if (caseTMR.data.specific == 'attache' && caseTMR.data.coord == coordTMR) { // Match !
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
isCaseInondee(coord) {
|
||||
return this.casesSpeciales.find(c => EffetsDraconiques.isCaseInondee(c, coord));
|
||||
}
|
||||
|
||||
isCiteFermee(coord) {
|
||||
return this.casesSpeciales.find(c => EffetsDraconiques.isCiteFermee(c, coord));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
checkConnaissanceFleuve(currentTMR, nextTMR) {
|
||||
if (this.actor.isConnaissanceFleuve()) {
|
||||
//console.log(currentTMR, nextTMR );
|
||||
if (TMRUtility.getTMR(currentTMR).type == 'fleuve' && TMRUtility.getTMR(nextTMR).type == 'fleuve') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
isTerreAttache(coord) {
|
||||
return this.casesSpeciales.find(c => EffetsDraconiques.isTerreAttache(c, coord));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isCaseMaitrisee(coord) {
|
||||
return this.casesSpeciales.find(c => EffetsDraconiques.isCaseMaitrisee(c, coord));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isReserveExtensible(coord) {
|
||||
return this.casesSpeciales.find(c => EffetsDraconiques.isReserveExtensible(c, coord));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isConnaissanceFleuve(currentTMR, nextTMR) {
|
||||
return TMRUtility.getTMR(currentTMR).type == 'fleuve' &&
|
||||
TMRUtility.getTMR(nextTMR).type == 'fleuve' &&
|
||||
EffetsDraconiques.isConnaissanceFleuve(this.actor);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -562,7 +689,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
let origEvent = event.data.originalEvent;
|
||||
let tmrObject = event.target.tmrObject;
|
||||
let tmrObject = this;
|
||||
|
||||
let eventPos = RdDTMRDialog._computeEventPos(origEvent);
|
||||
await tmrObject._onClickTMRPos(eventPos); // Vérifier l'état des compteurs reve/fatigue/vie
|
||||
@ -579,7 +706,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
// Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter)
|
||||
let deplacementType = 'erreur';
|
||||
if (this.rencontreState == 'aucune') { // Pas de recontre en post-processing, donc deplacement normal
|
||||
if (!RdDTMRDialog._horsDePortee(currentPos, eventPos) || this.isTerreAttache(targetCoordTMR) || this.checkConnaissanceFleuve(currentCoordTMR, targetCoordTMR)) {
|
||||
if (this.isTerreAttache(targetCoordTMR) || this.isConnaissanceFleuve(currentCoordTMR, targetCoordTMR) || !RdDTMRDialog._horsDePortee(currentPos, eventPos)) {
|
||||
deplacementType = 'normal';
|
||||
}
|
||||
} else {
|
||||
@ -644,6 +771,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
async postRencontre(tmr) {
|
||||
await this.manageCaseHumide(tmr);
|
||||
await this.conquerirCiteFermee(tmr);
|
||||
await this.declencheSortEnReserve(tmr.coord);
|
||||
await this.actor.checkSoufflePeage(tmr);
|
||||
}
|
||||
@ -658,76 +786,11 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this.actor.updateCoordTMR(coordTMR);
|
||||
this._updateDemiReve();
|
||||
let tmr = TMRUtility.getTMR(coordTMR);
|
||||
this.manageCaseHumide(tmr);
|
||||
await this.manageCaseHumide(tmr);
|
||||
await this.conquerirCiteFermee(tmr);
|
||||
await this.declencheSortEnReserve(tmr.coord);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
var row = document.getElementById("tmrrow1");
|
||||
var cell1 = row.insertCell(1);
|
||||
cell1.append(this.pixiApp.view);
|
||||
|
||||
if (this.viewOnly) {
|
||||
html.find('#lancer-sort').remove();
|
||||
}
|
||||
else {
|
||||
// Roll Sort
|
||||
html.find('#lancer-sort').click((event) => {
|
||||
this.actor.rollUnSort(this.actor.data.data.reve.tmrpos.coord);
|
||||
});
|
||||
}
|
||||
|
||||
// load the texture we need
|
||||
await this.pixiApp.loader
|
||||
.add('tmr', 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmp_main_r1.webp')
|
||||
.add('demi-reve', "icons/svg/sun.svg")
|
||||
.load((loader, resources) => {
|
||||
|
||||
// This creates a texture from a TMR image
|
||||
const mytmr = new PIXI.Sprite(resources.tmr.texture);
|
||||
// Setup the position of the TMR
|
||||
mytmr.x = 0;
|
||||
mytmr.y = 0;
|
||||
mytmr.width = 720;
|
||||
mytmr.height = 860;
|
||||
// Rotate around the center
|
||||
mytmr.anchor.x = 0;
|
||||
mytmr.anchor.y = 0;
|
||||
mytmr.interactive = true;
|
||||
mytmr.buttonMode = true;
|
||||
mytmr.tmrObject = this;
|
||||
if (!this.viewOnly) {
|
||||
mytmr.on('pointerdown', this.onClickTMR);
|
||||
}
|
||||
this.pixiApp.stage.addChild(mytmr);
|
||||
|
||||
this._addDemiReve();
|
||||
this.displayPreviousRencontres();
|
||||
this.displaySortReserve();
|
||||
this.displaySpecificCase();
|
||||
});
|
||||
|
||||
if (this.viewOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Gestion du cout de montée en points de rêve
|
||||
let reveCout = (this.tmrdata.isRapide && !this.actor.checkTeteDeplacementAccelere()) ? -2 : -1;
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
reveCout -= this.actor.checkMonteeLaborieuse();
|
||||
await this.actor.reveActuelIncDec(reveCout);
|
||||
// Le reste...
|
||||
this.updateValuesDisplay();
|
||||
let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord);
|
||||
await this.manageRencontre(tmr, () => {
|
||||
this.postRencontre(tmr);
|
||||
this.actor.displayTMRQueueSouffleInformation();
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _computeEventPos(origEvent) {
|
||||
let canvasRect = origEvent.target.getBoundingClientRect();
|
||||
@ -747,125 +810,16 @@ export class RdDTMRDialog extends Dialog {
|
||||
|| (target.y == 0 && target.y < origin.y && target.x != origin.x && origin.x % 2 == 1);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tokenRencontre(rencontre) {
|
||||
let sprite = new PIXI.Graphics();
|
||||
sprite.beginFill(0x767610, 0.6);
|
||||
sprite.drawCircle(0, 0, 6);
|
||||
sprite.endFill();
|
||||
sprite.decallage = {
|
||||
x: (tmrConstants.cellw / 2) - 16,
|
||||
y: 16 - (tmrConstants.cellh / 2)
|
||||
};
|
||||
return { sprite: sprite, rencontre: rencontre, coordTMR: () => rencontre.coord };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tokenTrouNoir(coord) {
|
||||
let sprite = new PIXI.Graphics();
|
||||
sprite.beginFill(0x050505, 0.8);
|
||||
sprite.drawCircle(0, 0, (tmrConstants.cellw / 2) - 2);
|
||||
sprite.endFill();
|
||||
sprite.decallage = {
|
||||
x: 0,
|
||||
y: 2
|
||||
}
|
||||
return { sprite: sprite, coordTMR: () => coord }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tokenDebordement(coord) {
|
||||
let sprite = new PIXI.Graphics();
|
||||
sprite.beginFill(0x0101FE, 0.3);
|
||||
sprite.drawCircle(0, 0, (tmrConstants.cellw / 2) - 2);
|
||||
sprite.endFill();
|
||||
sprite.decallage = {
|
||||
x: 0,
|
||||
y: 2
|
||||
}
|
||||
return { sprite: sprite, coordTMR: () => coord }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tokenMaitrisee(coord) {
|
||||
let sprite = new PIXI.Graphics();
|
||||
sprite.beginFill(0x1010F0, 0.8);
|
||||
sprite.drawCircle(0, 0, 6);
|
||||
sprite.endFill();
|
||||
sprite.decallage = {
|
||||
x: 16 - (tmrConstants.cellw / 2),
|
||||
y: 16 - (tmrConstants.cellh / 2)
|
||||
}
|
||||
return { sprite: sprite, coordTMR: () => coord }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tokenTerreAttache(coord) {
|
||||
let sprite = new PIXI.Graphics();
|
||||
sprite.beginFill(0x10F010, 0.8);
|
||||
sprite.drawCircle(0, 0, 6);
|
||||
sprite.endFill();
|
||||
sprite.decallage = {
|
||||
x: 16 - (tmrConstants.cellw / 2),
|
||||
y: 16 - (tmrConstants.cellh / 2)
|
||||
}
|
||||
return { sprite: sprite, coordTMR: () => coord }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tokenSortEnReserve(sort) {
|
||||
let sprite = new PIXI.Graphics();
|
||||
sprite.beginFill(0x101010, 0.8);
|
||||
sprite.drawCircle(0, 0, 6);
|
||||
sprite.endFill();
|
||||
sprite.decallage = {
|
||||
x: 16 - (tmrConstants.cellw / 2),
|
||||
y: 16 - (tmrConstants.cellh / 2)
|
||||
}
|
||||
return { sprite: sprite, sort: sort, coordTMR: () => sort.coord }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tokenDemiReve() {
|
||||
let texture = PIXI.utils.TextureCache['demi-reve'];
|
||||
let sprite = new PIXI.Sprite(texture);
|
||||
sprite.width = tmrConstants.cellw * 0.7;
|
||||
sprite.height = tmrConstants.cellh * 0.7;
|
||||
sprite.anchor.set(0.5);
|
||||
sprite.tint = 0x00FFEE;
|
||||
return { sprite: sprite, actor: this.actor, coordTMR: () => this.actor.data.data.reve.tmrpos.coord }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_addDemiReve() {
|
||||
this.demiReve = this._tokenDemiReve();
|
||||
this._setTokenPosition(this.demiReve);
|
||||
this.pixiApp.stage.addChild(this.demiReve.sprite);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_updateDemiReve() {
|
||||
this._setTokenPosition(this.demiReve);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** Retourne les coordonnées x, h, w, h du rectangle d'une case donnée */
|
||||
_getCaseRectangleCoord(coord) {
|
||||
let coordXY = TMRUtility.convertToCellPos(coord);
|
||||
let decallagePairImpair = (coordXY.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
let x = tmrConstants.gridx + (coordXY.x * tmrConstants.cellw) - (tmrConstants.cellw / 2);
|
||||
let y = tmrConstants.gridy + (coordXY.y * tmrConstants.cellh) - (tmrConstants.cellh / 2) + decallagePairImpair;
|
||||
return { x: x, y: y, w: tmrConstants.cellw, h: tmrConstants.cellh }
|
||||
return this.pixiTMR.getCaseRectangle(TMRUtility.convertToCellPos(coord));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_setTokenPosition(token) {
|
||||
let coordXY = TMRUtility.convertToCellPos(token.coordTMR());
|
||||
let decallagePairImpair = (coordXY.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
let dx = (token.sprite.decallage == undefined) ? 0 : token.sprite.decallage.x;
|
||||
let dy = (token.sprite.decallage == undefined) ? 0 : token.sprite.decallage.y;
|
||||
token.sprite.x = tmrConstants.gridx + (coordXY.x * tmrConstants.cellw) + dx;
|
||||
token.sprite.y = tmrConstants.gridy + (coordXY.y * tmrConstants.cellh) + dy + decallagePairImpair;
|
||||
this.pixiTMR.setPosition(token.sprite, TMRUtility.convertToCellPos(token.coordTMR()));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -878,10 +832,9 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_trackToken(token) {
|
||||
this.allTokens.push(token)
|
||||
this.allTokens.push(token);
|
||||
this._setTokenPosition(token);
|
||||
this.pixiApp.stage.addChild(token.sprite);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@ export class RdDTMRRencontreDialog extends Dialog {
|
||||
buttons: {
|
||||
derober: { icon: '<i class="fas fa-check"></i>', label: "Se dérober", callback: () => { this.onButtonFuir(() => tmrApp.derober()); } },
|
||||
refouler: { icon: '<i class="fas fa-check"></i>', label: "Refouler", callback: () => this.onButtonAction(() => tmrApp.refouler()) },
|
||||
maitiser: { icon: '<i class="fas fa-check"></i>', label: "Maîtriser", callback: () => this.onButtonAction(() => tmrApp.maitriser()) }
|
||||
maitiser: { icon: '<i class="fas fa-check"></i>', label: "Maîtriser", callback: () => this.onButtonAction(() => tmrApp.maitriserRencontre()) }
|
||||
},
|
||||
default: "derober"
|
||||
};
|
||||
|
@ -112,8 +112,8 @@ export const referenceAjustements = {
|
||||
getDescr: (rollData, actor) => RdDBonus.find(actor.getSurprise()).descr
|
||||
},
|
||||
bonusCase: {
|
||||
isUsed: (rollData, actor) => rollData.selectedSort && rollData.coord,
|
||||
getDescr: (rollData, actor) => rollData.selectedSort && rollData.coord ? `Bonus de case: ${RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.coord)}%` : ''
|
||||
isUsed: (rollData, actor) => rollData.selectedSort && rollData.tmr.coord,
|
||||
getDescr: (rollData, actor) => rollData.selectedSort && rollData.tmr.coord ? `Bonus de case: ${RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.tmr.coord)}%` : ''
|
||||
},
|
||||
rencontreTMR: {
|
||||
isVisible: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
|
||||
|
@ -86,7 +86,7 @@ const typeRencontres = {
|
||||
changeur: {
|
||||
msgSucces: (data) => `Le ${data.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[data.tmr.type].name} de votre choix en échange de sa liberté.`,
|
||||
msgEchec: (data) => {
|
||||
data.newTMR = TMRUtility.getTMRAleatoire(data.tmr.type);
|
||||
data.newTMR = TMRUtility.getTMRAleatoire(it => it.type = data.tmr.type);
|
||||
return `Le ${data.rencontre.name} vous embobine avec des promesses, et vous transporte en ${data.newTMR.label} sans attendre votre avis.`;
|
||||
},
|
||||
postSucces: (tmrDialog, data) => {
|
||||
@ -230,7 +230,7 @@ const typeRencontres = {
|
||||
msgSucces: (data) => `A tout seigneur, tout honneur, vous faites face à un ${data.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${data.rencontre.force} points de rêve`,
|
||||
msgEchec: (data) => `A tout seigneur, tout honneur, vous faites face à un ${data.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${data.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`,
|
||||
postSucces: (tmrDialog, data) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, data),
|
||||
postEchec: (tmrDialog, data) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, data),
|
||||
postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, data),
|
||||
poesieSucces: {
|
||||
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||
extrait: `Le monde est Rêve de Dragons, mais nous ne savons
|
||||
@ -475,11 +475,11 @@ export class TMRRencontres {
|
||||
if (data.rolled.isPart) {
|
||||
await data.actor.appliquerExperience(data.rolled, 'reve', data.competence);
|
||||
}
|
||||
await data.actor.resultCombattreReveDeDragon(data.rolled);
|
||||
await data.actor.resultCombatReveDeDragon(data);
|
||||
}
|
||||
|
||||
static async onPostEchecReveDeDragon(tmrDialog, data) {
|
||||
await data.actor.resultCombattreReveDeDragon(data.rolled);
|
||||
await data.actor.resultCombatReveDeDragon(data);
|
||||
tmrDialog.close();
|
||||
}
|
||||
}
|
||||
|
@ -227,68 +227,6 @@ export const TMRType = {
|
||||
desolation: { name: "désolation", genre: "f" }
|
||||
}
|
||||
|
||||
export const poesieHautReve = [
|
||||
{
|
||||
reference: 'Le Ratier Bretonien',
|
||||
extrait: `Le courant du Fleuve
|
||||
<br>Te domine et te Porte
|
||||
<br>Avant que tu te moeuves
|
||||
<br>Combat le, ou il t'emporte`
|
||||
},
|
||||
{
|
||||
reference: 'Incompatibilité, Charles Beaudelaire',
|
||||
extrait: `Et lorsque par hasard une nuée errante
|
||||
<br>Assombrit dans son vol le lac silencieux,
|
||||
<br>On croirait voir la robe ou l'ombre transparente
|
||||
<br>D'un esprit qui voyage et passe dans les cieux.`
|
||||
},
|
||||
{
|
||||
reference: 'Au fleuve de Loire, Joachim du Bellay',
|
||||
extrait: `Ô de qui la vive course
|
||||
<br>Prend sa bienheureuse source,
|
||||
<br>D’une argentine fontaine,
|
||||
<br>Qui d’une fuite lointaine,
|
||||
<br>Te rends au sein fluctueux
|
||||
<br>De l’Océan monstrueux`
|
||||
},
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
extrait: `Et l'on peut savoir qui est le maître d'Oniros, c'est le Fleuve de l'Oubli.
|
||||
Et l'on sait qui est le créateur du Fleuve de l'Oubli, c'est Hypnos et Narcos.
|
||||
Mais l'on ne sait pas qui est le maître du Fleuve de l'Oubli,
|
||||
sinon peut-être lui-même, ou peut-être Thanatos` },
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
extrait: `Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure
|
||||
Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir.
|
||||
Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli`
|
||||
},
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
extrait: `Narcos engendre le fils dont il est la mère à l'heure du Vaisseau,
|
||||
car Oniros s'embarque pour redescendre le Fleuve
|
||||
vers son père Hypnos sur la Voie de l'Oubli`
|
||||
},
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
extrait: `Hypnos engendre le fils dont il est la mère à l'heure du Serpent, car
|
||||
tel les serpents, Oniros commence à remonter le Fleuve
|
||||
sur le Voie du Souvenir vers son père Narcos`
|
||||
},
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
extrait: `Ainsi se cuccèdent les Jours et les Ages. Les jours des Dragons sont les Ages des Hommes`
|
||||
},
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
extrait: `Ainsi parlent les sages:
|
||||
«Les Dragons sont créateurs de leurs rêves, mais ils ne sont pas créateurs d'Oniros
|
||||
Les Dragons ne sont pas les maîtres de leurs rêvezs, car ils ne sont pas maîtres d'Oniros.
|
||||
Nul ne sait qui est le créateur des Dragons, ni qui est leur maître.
|
||||
Mais l'on peut supposer qui est le maître du Rêve des Dragons, c'est Oniros»`
|
||||
},
|
||||
]
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const caseSpecificModes = ["attache", "trounoir", "debordement", "reserve_extensible", "maitrisee"];
|
||||
|
||||
@ -309,9 +247,36 @@ export const tmrConstants = {
|
||||
cellw: 55,
|
||||
cellh: 55,
|
||||
gridx: 28,
|
||||
gridy: 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 },
|
||||
}
|
||||
|
||||
// couleurs
|
||||
export const tmrColors = {
|
||||
sort: 0xFF8800,
|
||||
tetes: 0xA000FF,
|
||||
souffle: 0x804040,
|
||||
trounoir: 0x401060,
|
||||
demireve: 0x00FFEE,
|
||||
rencontre: 0xFF0000,
|
||||
casehumide: 0x1050F0,
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -355,6 +320,9 @@ export class TMRUtility {
|
||||
static getTMR(coordTMR) {
|
||||
return TMRMapping[coordTMR];
|
||||
}
|
||||
static isCaseHumide(tmr) {
|
||||
return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** Some debug functions */
|
||||
@ -416,12 +384,16 @@ export class TMRUtility {
|
||||
return TMRType[terrain].list;
|
||||
}
|
||||
|
||||
static getListCoordTMR(terrain) {
|
||||
return this.getListTMR(terrain).map(it => it.coord);
|
||||
static filterTMR(filter) {
|
||||
return Object.values(TMRMapping).filter(filter);
|
||||
}
|
||||
|
||||
static getTMRAleatoire(terrain = undefined) {
|
||||
let list = terrain ? TMRUtility.getListTMR(terrain) : Object.values(TMRMapping);
|
||||
static filterTMRCoord(filter) {
|
||||
return TMRUtility.filterTMR(filter).map(it => it.coord);
|
||||
}
|
||||
|
||||
static getTMRAleatoire(filter = undefined) {
|
||||
let list = TMRUtility.filterTMR(filter);
|
||||
let index = new Roll("1d" + list.length).evaluate().total - 1;
|
||||
return list[index];
|
||||
}
|
||||
|
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