Merge branch 'queues-souffles' into 'v1.3'

Queues souffles

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!150
This commit is contained in:
Leratier Bretonnien 2021-02-12 09:44:01 +00:00
commit 1c5d14a1fa
22 changed files with 410 additions and 211 deletions

View File

@ -1121,6 +1121,24 @@ export class RdDActor extends Actor {
return queue; return queue;
} }
/* -------------------------------------------- */
async reinsertionAleatoire(raison) {
ChatMessage.create({
content: `${raison} : ré-insertion aléatoire.`,
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name)
});
const innaccessible = this.buildTMRInnaccessible();
let tmr = TMRUtility.getTMRAleatoire(tmr => !innaccessible.includes(tmr.coord) );
this.updateCoordTMR(tmr.coord);
return tmr;
}
buildTMRInnaccessible() {
const tmrInnaccessibles = this.data.items.filter(it => Draconique.isCaseTMR(it) &&
EffetsDraconiques.isInnaccessible(it));
return tmrInnaccessibles.map(it => it.data.coord);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
displayTMRQueueSouffleInformation() { displayTMRQueueSouffleInformation() {
let messages = []; let messages = [];
@ -1137,9 +1155,6 @@ export class RdDActor extends Actor {
if (EffetsDraconiques.isPeriple(item)) { if (EffetsDraconiques.isPeriple(item)) {
messages.push("Vous souffrez du Souffle <strong>Périple</strong>. Vous devez gérer manuellement le détail du Périple.<br>" + item.data.description); messages.push("Vous souffrez du Souffle <strong>Périple</strong>. Vous devez gérer manuellement le détail du Périple.<br>" + item.data.description);
} }
if (EffetsDraconiques.isDesorientation(item)) {
messages.push("Vous souffrez du Souffle <strong>Désorientation</strong>. Vous devez gérer avec votre MJ les effets de ce souffle.<br>" + item.data.description);
}
} }
if (messages.length > 0) { if (messages.length > 0) {
@ -1796,6 +1811,10 @@ export class RdDActor extends Actor {
ui.notifications.info("Aucun sort disponible pour cette case !"); ui.notifications.info("Aucun sort disponible pour cette case !");
return; return;
} }
if (EffetsDraconiques.isConquete(this)) {
ui.notifications.error("Vous ne pouvez pas lancer de sort sous l'effet d'une conquête!");
return;
}
if (this.currentTMR) this.currentTMR.minimize(); // Hide if (this.currentTMR) this.currentTMR.minimize(); // Hide
let draconicList = this.filterDraconicList(sortList); let draconicList = this.filterDraconicList(sortList);
@ -2708,25 +2727,23 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async resetItemUse( ) { async resetItemUse( ) {
await this.setFlag('foundryvtt-reve-de-dragon', 'itemUse', null ); await this.unsetFlag('foundryvtt-reve-de-dragon', 'itemUse');
await this.setFlag('foundryvtt-reve-de-dragon', 'itemUse', {} ); await this.setFlag('foundryvtt-reve-de-dragon', 'itemUse', {} );
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async incItemUse( itemId ) { async incItemUse( itemId ) {
let itemUse = this.getFlag('foundryvtt-reve-de-dragon', 'itemUse'); let itemUse = duplicate(this.getFlag('foundryvtt-reve-de-dragon', 'itemUse') ?? {});
itemUse = (itemUse) ? duplicate(itemUse) : {}; itemUse[itemId] = (itemUse[itemId] ?? 0) + 1;
itemUse[itemId] = (itemUse[itemId]) ? itemUse[itemId] + 1 : 1;
await this.setFlag( 'foundryvtt-reve-de-dragon', 'itemUse', itemUse); await this.setFlag( 'foundryvtt-reve-de-dragon', 'itemUse', itemUse);
console.log("ITEM USE INC", itemUse); console.log("ITEM USE INC", itemUse);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getItemUse( itemId ) { getItemUse( itemId ) {
let itemUse = this.getFlag('foundryvtt-reve-de-dragon', 'itemUse'); let itemUse = this.getFlag('foundryvtt-reve-de-dragon', 'itemUse') ?? {};
itemUse = (itemUse) ? itemUse : {};
console.log("ITEM USE GET", itemUse); console.log("ITEM USE GET", itemUse);
return itemUse[itemId] ? itemUse[itemId] : 0; return itemUse[itemId] ?? 0;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -59,4 +59,12 @@ export class Misc {
} }
} }
static rollOneOf(array) {
return array[new Roll("1d" + array.length).evaluate().total - 1];
}
static distinct(array) {
return [...new Set(array)];
}
} }

View File

@ -1,3 +1,4 @@
import { Misc } from "./misc.js"
const poesieHautReve = [ const poesieHautReve = [
{ {
@ -64,7 +65,7 @@ const poesieHautReve = [
export class Poetique { export class Poetique {
static getExtrait(){ static getExtrait(){
return poesieHautReve[new Roll("1d" + poesieHautReve.length).evaluate().total - 1] return Misc.rollOneOf(poesieHautReve);
} }
} }

View File

@ -1,3 +1,4 @@
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
const words = [ 'pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', 'onse', 'iane', 'ane', 'zach', 'arri', 'ba', 'bo', 'bi', const words = [ 'pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', 'onse', 'iane', 'ane', 'zach', 'arri', 'ba', 'bo', 'bi',
@ -7,9 +8,7 @@ const words = [ 'pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i',
export class RdDNameGen { export class RdDNameGen {
static getName( msg, params ) { static getName( msg, params ) {
let max = words.length; let name = Misc.upperFirst( Misc.rollOneOf(words) + Misc.rollOneOf(words) )
let name = words[new Roll("1d"+max+" -1").roll().total];
name += words[new Roll("1d"+max+" -1").roll().total];
//console.log(name); //console.log(name);
ChatMessage.create( { content: `Nom : ${name}`, whisper: ChatMessage.getWhisperRecipients("GM") } ); ChatMessage.create( { content: `Nom : ${name}`, whisper: ChatMessage.getWhisperRecipients("GM") } );
} }

View File

@ -10,6 +10,7 @@ import { Poetique } from "./poetique.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js"; import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { PixiTMR } from "./tmr/pixi-tmr.js"; import { PixiTMR } from "./tmr/pixi-tmr.js";
import { Draconique } from "./tmr/draconique.js"; import { Draconique } from "./tmr/draconique.js";
import { Grammar } from "./grammar.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDTMRDialog extends Dialog { export class RdDTMRDialog extends Dialog {
@ -50,7 +51,7 @@ export class RdDTMRDialog extends Dialog {
this.cumulFatigue = 0; this.cumulFatigue = 0;
this.loadRencontres(); this.loadRencontres();
this.loadSortsReserve(); this.loadSortsReserve();
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item)); this.loadCasesSpeciales();
this.allTokens = []; this.allTokens = [];
this.rencontreState = 'aucune'; this.rencontreState = 'aucune';
this.pixiApp = new PIXI.Application({ width: 720, height: 860 }); this.pixiApp = new PIXI.Application({ width: 720, height: 860 });
@ -66,6 +67,10 @@ export class RdDTMRDialog extends Dialog {
this.pixiTMR.load((loader, resources) => this.createPixiSprites()); this.pixiTMR.load((loader, resources) => this.createPixiSprites());
} }
loadCasesSpeciales() {
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item));
}
loadSortsReserve() { loadSortsReserve() {
this.sortsReserves = duplicate(this.actor.data.data.reve.reserve.list); this.sortsReserves = duplicate(this.actor.data.data.reve.reserve.list);
} }
@ -99,6 +104,7 @@ export class RdDTMRDialog extends Dialog {
this._removeTokens(t => true); this._removeTokens(t => true);
this.loadRencontres(); this.loadRencontres();
this.loadSortsReserve(); this.loadSortsReserve();
this.loadCasesSpeciales();
this._createTokens(); this._createTokens();
} }
@ -396,8 +402,11 @@ export class RdDTMRDialog extends Dialog {
if (rencontre) { if (rencontre) {
return rencontre; return rencontre;
} }
// TODO: dialog pour remplacer la rencontre par un présent if (this.casesSpeciales.find(c => EffetsDraconiques.isPresentCite(c, tmr.coord))) {
//if (this.casesSpeciales.find(c => EffetsDraconiques.isPresentCite(c, tmr.coord))) {
// TODO: dialog pour remplacer la rencontre par un présent
}
let myRoll = new Roll("1d7").evaluate().total; let myRoll = new Roll("1d7").evaluate().total;
@ -415,30 +424,22 @@ export class RdDTMRDialog extends Dialog {
? await TMRRencontres.getMauvaiseRencontre() ? await TMRRencontres.getMauvaiseRencontre()
: await TMRRencontres.getRencontreAleatoire(tmr.type)); : await TMRRencontres.getRencontreAleatoire(tmr.type));
rencontre.coord = tmr.coord; rencontre.coord = tmr.coord;
rencontre.date = game.system.rdd.calendrier.getDateFromIndex(); rencontre.date = game.system.rdd.calendrier.getDateFromIndex();
rencontre.heure = game.system.rdd.calendrier.getCurrentHeure(); rencontre.heure = game.system.rdd.calendrier.getCurrentHeure();
return rencontre; return rencontre;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async manageCaseSpeciale(tmr) { async manageTmrInnaccessible(tmr) {
if (this.casesSpeciales.find(c => EffetsDraconiques.isCaseTrouNoir(c, tmr.coord))) { const caseTmrInnaccessible = this.casesSpeciales.find(c => EffetsDraconiques.isInnaccessible(c, tmr.coord));
let newTMR = TMRUtility.getTMRAleatoire(); if (caseTmrInnaccessible) {
let tmrPos = duplicate(this.actor.data.data.reve.tmrpos); return await this.actor.reinsertionAleatoire(caseTmrInnaccessible.name);
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)
});
} }
return tmr;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async manageCaseHumide(tmr) { async manageCaseHumide(tmr) {
if (this.viewOnly || this.currentRencontre) {
return;
}
if (this.isCaseHumide(tmr)) { if (this.isCaseHumide(tmr)) {
let rollData = { let rollData = {
actor: this.actor, actor: this.actor,
@ -449,8 +450,8 @@ export class RdDTMRDialog extends Dialog {
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' } maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
} }
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true: undefined,
rollData.competence.data.defaut_carac = 'reve-actuel'; rollData.competence.data.defaut_carac = 'reve-actuel';
await this._rollMaitriseCaseHumide(rollData); await this._rollMaitriseCaseHumide(rollData);
} }
} }
@ -465,8 +466,9 @@ export class RdDTMRDialog extends Dialog {
rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
} }
this.toclose = rollData.rolled.isEchec; this.toclose = rollData.rolled.isEchec;
if (rollData.rolled.isSuccess && !rollData.previous && EffetsDraconiques.isDoubleResistanceFleuve(this.actor)) { if (rollData.rolled.isSuccess && rollData.double) {
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements }; rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
rollData.double = undefined;
await this._rollMaitriseCaseHumide(rollData); await this._rollMaitriseCaseHumide(rollData);
return; return;
} }
@ -516,26 +518,52 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async conquerirCiteFermee(tmr) { async conquerirCiteFermee(tmr) {
if (this.viewOnly || this.currentRencontre) { if (EffetsDraconiques.fermetureCites.find(this.casesSpeciales, tmr.coord)) {
return; await this._conquerir(tmr, {
} difficulte: -9,
const citeFermee = this.isCiteFermee(tmr.coord); action: 'Conquérir la cité',
if (citeFermee) { onConqueteReussie: r => EffetsDraconiques.fermetureCites.onConquete(r.actor, tmr.coord),
let rollData = { onConqueteEchec: r => this.close(),
actor: this.actor, canClose: false
competence: duplicate(this.actor.getBestDraconic()), });
tmr: tmr,
canClose: false,
diffLibre: -9,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
maitrise: { verbe: 'conquérir', action: 'Conquérir la cité' }
}
rollData.competence.data.defaut_carac = 'reve-actuel';
await this._maitriserTMR(rollData, r => this._resultatConqueteCiteFermee(r));
} }
} }
async _resultatConqueteCiteFermee(rollData) {
removeToken(tmr, casetmr) {
this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id);
this.updateTokens()
}
/* -------------------------------------------- */
async conquerirTMR(tmr) {
if (EffetsDraconiques.conquete.find(this.casesSpeciales, tmr.coord)) {
await this._conquerir(tmr, {
difficulte: -7,
action: 'Conquérir',
onConqueteReussie: r => EffetsDraconiques.conquete.onConquete(r.actor, tmr.coord, (casetmr) => this.removeToken(tmr, casetmr)),
onConqueteEchec: r => {},
canClose: false
});
}
}
/* -------------------------------------------- */
async _conquerir(tmr, options) {
let rollData = {
actor: this.actor,
competence: duplicate(this.actor.getBestDraconic()),
tmr: tmr,
canClose: options.canClose ?? false,
diffLibre: options.difficulte ?? -7,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
maitrise: { verbe: 'conquérir', action: options.action }
};
rollData.competence.data.defaut_carac = 'reve-actuel';
await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options));
}
async _onResultatConquerir(rollData, options) {
if (rollData.rolled.isETotal) { if (rollData.rolled.isETotal) {
rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
} }
@ -547,12 +575,11 @@ export class RdDTMRDialog extends Dialog {
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
}); });
if (rollData.rolled.isEchec) { if (rollData.rolled.isEchec) {
this.close(); options.onConqueteEchec(rollData, options.effetDraconique);
} }
else { else {
const citeFermee = this.actor.data.items.find(it => EffetsDraconiques.isCiteFermee(it, rollData.tmr.coord)); await options.onConqueteReussie(rollData, options.effetDraconique);
this.actor.deleteOwnedItem(citeFermee._id); this.updateTokens();
this._removeTokens(t => t.coordTMR() == citeFermee.data.coord && t.caseSpeciale?._id == citeFermee._id);
} }
} }
@ -577,17 +604,18 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async declencheSortEnReserve(coordTMR) { async declencheSortEnReserve(coord) {
if (this.viewOnly) {
return;
}
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR); let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord);
if (sortReserveList.length > 0) { if (sortReserveList.length > 0) {
if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coordTMR)) { if (EffetsDraconiques.isConquete(this.actor)) {
ui.notifications.error("Vous ne pouvez pas déclencher de sort sous l'effet d'une conquête!");
return;
}
if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord)) {
let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête <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>"; 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) { 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>"; msg += "<li><a class='chat-card-button' id='sort-reserve' data-actor-id='" + this.actor._id + "' data-tmr-coord='" + coord + "' data-sort-id='" + sortReserve.sort._id + "'>" + sortReserve.sort.name + "</a></li>";
} }
msg += "</ol>"; msg += "</ol>";
ChatMessage.create({ ChatMessage.create({
@ -601,8 +629,8 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
lancerSortEnReserve(coordTMR, sortId) { lancerSortEnReserve(coord, sortId) {
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR); let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord);
let sortReserve = sortReserveList.find(sortReserve => sortReserve.sort._id == sortId); let sortReserve = sortReserveList.find(sortReserve => sortReserve.sort._id == sortId);
//console.log("SORT RESA", sortReserveList, coordTMR, sortId, sortReserve); //console.log("SORT RESA", sortReserveList, coordTMR, sortId, sortReserve);
if (sortReserve) { if (sortReserve) {
@ -620,10 +648,10 @@ export class RdDTMRDialog extends Dialog {
await this.actor.deleteSortReserve(sortReserve); await this.actor.deleteSortReserve(sortReserve);
this.updateSortReserve(); this.updateSortReserve();
console.log("declencheSortEnReserve", sortReserve) console.log("declencheSortEnReserve", sortReserve)
const declenchementSort = "Vous avez déclenché le sort <strong>" + sortReserve.sort.name this._tellToGM(`Vous avez déclenché le sort en réserve <strong> ${sortReserve.sort.name}</strong>
+ "</strong> en réserve en " + sortReserve.coord + " (" + TMRUtility.getTMR(sortReserve.coord).label avec ${sortReserve.sort.data.ptreve_reel} points de Rêve
+ ") avec " + sortReserve.sort.data.ptreve_reel + " points de Rêve"; en ${sortReserve.coord} (${TMRUtility.getTMRLabel(sortReserve.coord)})
this._tellToGM(declenchementSort); `);
this.close(); this.close();
} }
@ -639,40 +667,28 @@ export class RdDTMRDialog extends Dialog {
this.rencontreState = 'aucune'; // Et de l'état this.rencontreState = 'aucune'; // Et de l'état
} }
/* -------------------------------------------- */
processClickPostRencontre(coord) {
if (this.rencontreState == 'passeur' || this.rencontreState == 'messager' || this.rencontreState == 'changeur') {
console.log("Searching", this.currentRencontre.locList, coord);
let isInArea = this.currentRencontre.locList.find(locCoord => locCoord == coord);
if (isInArea) { // OK !
return (this.rencontreState == 'messager') ? 'messager' : 'saut';
}
}
return "erreur";
}
/* -------------------------------------------- */ /* -------------------------------------------- */
isCaseInondee(coord) { isCaseInondee(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isCaseInondee(c, coord)); return EffetsDraconiques.debordement.find(this.casesSpeciales, coord);
} }
isCiteFermee(coord) { isCiteFermee(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isCiteFermee(c, coord)); return EffetsDraconiques.fermetureCites.find(this.casesSpeciales, coord);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
isTerreAttache(coord) { isTerreAttache(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isTerreAttache(c, coord)); return EffetsDraconiques.terreAttache.find(this.casesSpeciales, coord);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
isCaseMaitrisee(coord) { isCaseMaitrisee(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isCaseMaitrisee(c, coord)); return EffetsDraconiques.queteEaux.find(this.casesSpeciales, coord);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
isReserveExtensible(coord) { isReserveExtensible(coord) {
return this.casesSpeciales.find(c => EffetsDraconiques.isReserveExtensible(c, coord)); return EffetsDraconiques.reserveExtensible.find(this.casesSpeciales, coord);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -700,40 +716,47 @@ export class RdDTMRDialog extends Dialog {
console.log("deplacerDemiReve >>>>", currentPos, eventPos); console.log("deplacerDemiReve >>>>", currentPos, eventPos);
let targetCoordTMR = TMRUtility.convertToTMRCoord(eventPos); let targetCoord = TMRUtility.convertToTMRCoord(eventPos);
let currentCoordTMR = TMRUtility.convertToTMRCoord(currentPos); let currentCoord = TMRUtility.convertToTMRCoord(currentPos);
// Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter) // Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter)
let deplacementType = 'erreur'; let deplacementType = this._calculDeplacement(targetCoord, currentCoord, currentPos, eventPos);
if (this.rencontreState == 'aucune') { // Pas de recontre en post-processing, donc deplacement normal
if (this.isTerreAttache(targetCoordTMR) || this.isConnaissanceFleuve(currentCoordTMR, targetCoordTMR) || !RdDTMRDialog._horsDePortee(currentPos, eventPos)) {
deplacementType = 'normal';
}
} else {
deplacementType = this.processClickPostRencontre(targetCoordTMR);
}
// Si le deplacement est valide // Si le deplacement est valide
if (deplacementType == 'normal' || deplacementType == 'saut') { if (deplacementType == 'normal' || deplacementType == 'saut') {
await this._deplacerDemiReve(targetCoordTMR, deplacementType); await this._deplacerDemiReve(targetCoord, deplacementType);
} else if (deplacementType == 'messager') { // Dans ce cas, ouverture du lancement de sort sur la case visée } else if (deplacementType == 'messager') { // Dans ce cas, ouverture du lancement de sort sur la case visée
/* await this._messagerDemiReve(targetCoord);
TODO: si la case a un sort en réserve, lancer ce sort.
Si la case est le demi-rêve, ne pas lancer de sort.
Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre si on essaie de lancer un sort (ou bloquer le lancer de sort)
*/
await this._messagerDemiReve(targetCoordTMR);
} else { } else {
ui.notifications.error("Vous ne pouvez vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre"); ui.notifications.error("Vous ne pouvez vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
console.log("STATUS :", this.rencontreState, this.currentRencontre); console.log("STATUS :", this.rencontreState, this.currentRencontre);
} }
this.checkQuitterTMR(); this.checkQuitterTMR();
} }
async _messagerDemiReve(targetCoordTMR) { /* -------------------------------------------- */
await this.actor.rollUnSort(targetCoordTMR); _calculDeplacement(targetCoord, currentCoord, currentPos, eventPos) {
let isInArea = this.rencontreState == 'aucune'
? this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || !RdDTMRDialog._horsDePortee(currentPos, eventPos)
: this.currentRencontre?.locList.find(coord => coord == targetCoord) ?? false
if (isInArea) {
switch (this.rencontreState) {
case 'aucune': return 'normal';
case 'messager': return 'messager';
case 'passeur': case 'changeur': return 'saut';
}
}
return 'erreur'
}
/* -------------------------------------------- */
async _messagerDemiReve(targetCoord) {
/*
TODO: si la case a un sort en réserve, lancer ce sort.
Si la case est le demi-rêve, ne pas lancer de sort.
Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre si on essaie de lancer un sort (ou bloquer le lancer de sort)
*/
await this.actor.rollUnSort(targetCoord);
this.nettoyerRencontre(); this.nettoyerRencontre();
} }
@ -742,14 +765,12 @@ export class RdDTMRDialog extends Dialog {
this.nettoyerRencontre(); this.nettoyerRencontre();
} }
let tmr = TMRUtility.getTMR(targetCoord); let tmr = TMRUtility.getTMR(targetCoord);
console.log("deplacerDemiReve", tmr, this);
// Gestion cases spéciales type Trou noir, etc
tmr = await this.manageTmrInnaccessible(tmr);
await this.manageCaseSpeciale(tmr); // Gestion cases spéciales type Trou noir, etc this.actor.updateCoordTMR(tmr.coord);
await this.actor.updateCoordTMR(tmr.coord);
console.log("deplacerDemiReve: TMR is", tmr, this);
let tmrPos = duplicate(this.actor.data.data.reve.tmrpos);
tmrPos.coord = targetCoord;
await this.actor.update({ "data.reve.tmrpos": tmrPos });
this._updateDemiReve(); this._updateDemiReve();
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
@ -757,7 +778,7 @@ export class RdDTMRDialog extends Dialog {
game.socket.emit("system.foundryvtt-reve-de-dragon", { game.socket.emit("system.foundryvtt-reve-de-dragon", {
msg: "msg_tmr_move", data: { msg: "msg_tmr_move", data: {
actorId: this.actor.data._id, actorId: this.actor.data._id,
tmrPos: tmrPos tmrPos: this.actor.data.data.reve.tmrpos
} }
}); });
@ -770,25 +791,31 @@ export class RdDTMRDialog extends Dialog {
} }
async postRencontre(tmr) { async postRencontre(tmr) {
await this.manageCaseHumide(tmr); if (!(this.viewOnly || this.currentRencontre)) {
await this.conquerirCiteFermee(tmr); await this.manageCaseHumide(tmr);
await this.declencheSortEnReserve(tmr.coord); await this.conquerirCiteFermee(tmr);
await this.actor.checkSoufflePeage(tmr); await this.conquerirTMR(tmr);
await this.declencheSortEnReserve(tmr.coord);
await this.actor.checkSoufflePeage(tmr);
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async forceDemiRevePositionView(coordTMR) { async forceDemiRevePositionView() {
this._updateDemiReve(); this._updateDemiReve();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async forceDemiRevePosition(coordTMR) { async forceDemiRevePosition(coord) {
await this.actor.updateCoordTMR(coordTMR); await this.actor.updateCoordTMR(coord);
this._updateDemiReve(); this._updateDemiReve();
let tmr = TMRUtility.getTMR(coordTMR); let tmr = TMRUtility.getTMR(coord);
await this.manageCaseHumide(tmr); if (!(this.viewOnly || this.currentRencontre)) {
await this.conquerirCiteFermee(tmr); await this.manageCaseHumide(tmr);
await this.declencheSortEnReserve(tmr.coord); await this.conquerirCiteFermee(tmr);
await this.declencheSortEnReserve(tmr.coord);
}
return tmr;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -1,5 +1,6 @@
import { DeDraconique } from "./de-draconique.js"; import { DeDraconique } from "./de-draconique.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
import { TMRType } from "./tmr-utility.js"; import { TMRType } from "./tmr-utility.js";
@ -271,6 +272,12 @@ const rencontresStandard = [
{ code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1ddr + 7", refoulement: 2, quitterTMR: true } { code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1ddr + 7", refoulement: 2, quitterTMR: true }
]; ];
const presentsCite = [
{ code: "messager2d6", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d6", ignorer: true },
{ code: "passeur2d6", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d6", ignorer: true },
{ code: "fleur2d6", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "2d6", ignorer: true }
]
const tableRencontres = { const tableRencontres = {
cite: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }], cite: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }],
sanctuaire: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }], sanctuaire: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }],
@ -367,10 +374,10 @@ export class TMRRencontres {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getMauvaiseRencontre(index = undefined) { static async getMauvaiseRencontre(index = undefined) {
if (index == undefined || index >= mauvaisesRencontres.length) { const rencontre = duplicate(
index = new Roll("1d" + mauvaisesRencontres.length).roll().total - 1; (index && index>=0 && index < mauvaisesRencontres.length)
} ? mauvaisesRencontres[index]
const rencontre = duplicate(mauvaisesRencontres[index]); : Misc.rollOneOf(mauvaisesRencontres));
await TMRRencontres.evaluerForceRencontre(rencontre); await TMRRencontres.evaluerForceRencontre(rencontre);
return rencontre; return rencontre;
} }
@ -428,8 +435,7 @@ export class TMRRencontres {
data.newTMR = TMRUtility.getTMR(data.sortReserve.coord); data.newTMR = TMRUtility.getTMR(data.sortReserve.coord);
} else { } else {
// Déplacement aléatoire de la force du Passeur Fou // Déplacement aléatoire de la force du Passeur Fou
const locList = TMRUtility.getTMRPortee(data.tmr.coord, data.rencontre.force); const newCoord = Misc.rollOneOf(TMRUtility.getTMRPortee(data.tmr.coord, data.rencontre.force));
const newCoord = locList[new Roll("1d" + locList.length).evaluate().total - 1];
data.newTMR = TMRUtility.getTMR(newCoord); data.newTMR = TMRUtility.getTMR(newCoord);
} }
if (data.sortReserve) { if (data.sortReserve) {
@ -466,7 +472,7 @@ export class TMRRencontres {
static async _toubillonner(tmrDialog, actor, cases) { static async _toubillonner(tmrDialog, actor, cases) {
let coord = actor.data.data.reve.tmrpos.coord; let coord = actor.data.data.reve.tmrpos.coord;
for (let i = 0; i < cases; i++) { for (let i = 0; i < cases; i++) {
coord = TMRUtility.deplaceTMRAleatoire(coord); coord = TMRUtility.deplaceTMRAleatoire(actor, coord).coord;
} }
await tmrDialog.forceDemiRevePosition(coord) await tmrDialog.forceDemiRevePosition(coord)
} }

View File

@ -1,6 +1,4 @@
import { DeDraconique } from "./de-draconique.js";
import { TMRRencontres } from "./tmr-rencontres.js"; import { TMRRencontres } from "./tmr-rencontres.js";
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -92,7 +90,7 @@ const TMRMapping = {
A7: { type: "plaines", label: "Plaines de lArc" }, A7: { type: "plaines", label: "Plaines de lArc" },
B7: { type: "marais", label: "Marais Bluants" }, B7: { type: "marais", label: "Marais Bluants" },
C7: { type: "fleuve", label: "Fleuve de l'Oubli" }, C7: { type: "fleuve", label: "Fleuve de l'Oubli" },
D7: { type: "plaines", label: "Plaines dA!a" }, D7: { type: "plaines", label: "Plaines dAffa" },
E7: { type: "foret", label: "Forêt de Glusks" }, E7: { type: "foret", label: "Forêt de Glusks" },
F7: { type: "fleuve", label: "Fleuve de l'Oubli" }, F7: { type: "fleuve", label: "Fleuve de l'Oubli" },
G7: { type: "cite", label: "Cité de Terwa" }, G7: { type: "cite", label: "Cité de Terwa" },
@ -270,6 +268,7 @@ export const tmrColors = {
sort: 0xFF8800, sort: 0xFF8800,
tetes: 0xA000FF, tetes: 0xA000FF,
souffle: 0x804040, souffle: 0x804040,
queues: 0xAA4040,
trounoir: 0x401060, trounoir: 0x401060,
demireve: 0x00FFEE, demireve: 0x00FFEE,
rencontre: 0xFF0000, rencontre: 0xFF0000,
@ -283,7 +282,9 @@ export const tmrColors = {
export class TMRUtility { export class TMRUtility {
static init() { static init() {
for (let coord in TMRMapping) { for (let coord in TMRMapping) {
TMRMapping[coord].coord = coord; const tmr = TMRMapping[coord];
tmr.coord = coord;
tmr.genre = TMRType[tmr.type].genre;
} }
let tmrByType = Misc.classify(Object.values(TMRMapping)); let tmrByType = Misc.classify(Object.values(TMRMapping));
for (const [type, list] of Object.entries(tmrByType)) { for (const [type, list] of Object.entries(tmrByType)) {
@ -317,9 +318,14 @@ export class TMRUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getTMR(coordTMR) { static getTMR(coord) {
return TMRMapping[coordTMR]; return TMRMapping[coord];
} }
static getTMRLabel(coord) {
return TMRMapping[coord]?.label ?? (coord+": case inconnue");
}
static isCaseHumide(tmr) { static isCaseHumide(tmr) {
return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais'; return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais';
} }
@ -355,24 +361,23 @@ export class TMRUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getDirectionPattern() { static getDirectionPattern() {
let roll = new Roll("1d" + tmrRandomMovePatten.length).evaluate().total; return Misc.rollOneOf(tmrRandomMovePatten);
return tmrRandomMovePatten[roll - 1];
} }
static deplaceTMRAleatoire(coord) { static deplaceTMRAleatoire(actor, coord) {
return TMRUtility.deplaceTMRSelonPattern(coord, TMRUtility.getDirectionPattern(), 1); return TMRUtility.deplaceTMRSelonPattern(actor, coord, TMRUtility.getDirectionPattern(), 1);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static deplaceTMRSelonPattern(coord, direction, nTime) { static async deplaceTMRSelonPattern(actor, coord, direction, nTime) {
for (let i = 0; i < nTime; i++) { for (let i = 0; i < nTime; i++) {
let currentPosXY = TMRUtility.convertToCellPos(coord); let currentPos = TMRUtility.convertToCellPos(coord);
currentPosXY.x = currentPosXY.x + direction.x; currentPos.x = currentPos.x + direction.x;
currentPosXY.y = currentPosXY.y + direction.y; currentPos.y = currentPos.y + direction.y;
if (this._checkTMRCoord(currentPosXY.x, currentPosXY.y)) { // Sortie de carte ! Ré-insertion aléatoire if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Sortie de carte ! Ré-insertion aléatoire
coord = TMRUtility.convertToTMRCoord(currentPosXY); coord = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos));
} else { } else {
coord = this.getTMRAleatoire().coord; coord = await actor.reinsertionAleatoire('Sortie de carte');
} }
console.log("Nouvelle case iteration !!!", i, coord); console.log("Nouvelle case iteration !!!", i, coord);
} }
@ -392,10 +397,8 @@ export class TMRUtility {
return TMRUtility.filterTMR(filter).map(it => it.coord); return TMRUtility.filterTMR(filter).map(it => it.coord);
} }
static getTMRAleatoire(filter = undefined) { static getTMRAleatoire(filter = it => true) {
let list = TMRUtility.filterTMR(filter); return Misc.rollOneOf(TMRUtility.filterTMR(filter))
let index = new Roll("1d" + list.length).evaluate().total - 1;
return list[index];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -415,39 +418,32 @@ export class TMRUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getSortReserveList(reserveList, coordTMR) { static getSortReserveList(reserveList, coord) {
// TODO : Gérer les têtes spéciales réserve! // TODO : Gérer les têtes spéciales réserve!
let sortReserveList let tmrDescr = this.getTMR(coord);
let tmrDescr = this.getTMR(coordTMR);
//console.log("Sort réserve : ", tmrDescr); //console.log("Sort réserve : ", tmrDescr);
if (tmrDescr.type == 'fleuve') { // Gestion de la reserve en Fleuve if (tmrDescr.type == 'fleuve') { // Gestion de la reserve en Fleuve
sortReserveList = reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve'); return reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve');
} else { // Reserve sur un case "normale"
sortReserveList = reserveList.filter(it => it.coord == coordTMR);
} }
//console.log("Sort réserve : ", tmrDescr, sortReserve, reserveList); // Reserve sur un case "normale"
return sortReserveList; return reserveList.filter(it => it.coord == coord);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Returns a list of case inside a given distance /** Returns a list of case inside a given distance
* *
*/ */
static getTMRPortee(centerCoord, portee) { static getTMRPortee(coord, portee) {
return TMRUtility.getTMRArea(centerCoord, portee, tmrConstants); let centerPos = this.convertToCellPos(coord);
}
static getTMRArea(centerCoord, distance, tmrConstants) {
let centerPos = this.convertToCellPos(centerCoord);
let posPic = this.computeRealPictureCoordinates(centerPos, tmrConstants); let posPic = this.computeRealPictureCoordinates(centerPos, tmrConstants);
let caseList = []; let caseList = [];
for (let dx = -distance; dx <= distance; dx++) { // Loop thru lines for (let dx = -portee; dx <= portee; dx++) { // Loop thru lines
for (let dy = -distance; dy <= distance; dy++) { // Loop thru lines for (let dy = -portee; dy <= portee; dy++) { // Loop thru lines
const currentPos = { x: centerPos.x + dx, y: centerPos.y + dy }; const currentPos = { x: centerPos.x + dx, y: centerPos.y + dy };
if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Coordinate is valie if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Coordinate is valie
let posPicNow = this.computeRealPictureCoordinates(currentPos, tmrConstants); let posPicNow = this.computeRealPictureCoordinates(currentPos, tmrConstants);
let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x, 2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw; let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x, 2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw;
if (dist < distance + 0.5) { if (dist < portee + 0.5) {
caseList.push(this.convertToTMRCoord(currentPos)); // Inside the area caseList.push(this.convertToTMRCoord(currentPos)); // Inside the area
} }
} }

41
module/tmr/conquete.js Normal file
View File

@ -0,0 +1,41 @@
import { Misc } from "../misc.js";
import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js";
import { Draconique } from "./draconique.js";
export class Conquete extends Draconique {
constructor() {
super();
}
type() { return 'queue' }
match(item) { return Draconique.isQueueDragon(item) && item.name.toLowerCase() == 'conquête'; }
manualMessage() { return false }
async onActorCreateOwned(actor, item) { await this._creerConquete(actor, item); }
code() { return 'conquete' }
tooltip(linkData) { return `La ${this.tmrLabel(linkData)} doit être conquise` }
img() { return 'icons/svg/combat.svg' }
_createSprite(pixiTMR) {
return pixiTMR.sprite(this.code(),
{
color: tmrColors.queues, taille: tmrConstants.full, decallage: { x: 2, y: 0 }
});
}
async _creerConquete(actor, queue) {
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
let possibles = TMRUtility.filterTMR(tmr => !TMRUtility.isCaseHumide(tmr) && !existants.includes(tmr.coord));
let conquete = Misc.rollOneOf(possibles);
await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue._id);
}
async onConquete(actor, coord) {
let existants = actor.data.items.filter(it => this.isCase(it, coord));
for (let casetmr of existants) {
await actor.deleteOwnedItem(casetmr._id);
await actor.deleteOwnedItem(casetmr.data.sourceid);
}
}
}

View File

@ -13,7 +13,7 @@ export class Debordement extends Draconique {
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
code() { return 'debordement' } code() { return 'debordement' }
tooltip(linkData) { return `Débordement en ${TMRUtility.getTMR(linkData.data.coord).label}` } tooltip(linkData) { return `Débordement en ${this.tmrLabel(linkData)}` }
img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' } img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' }
_createSprite(pixiTMR) { _createSprite(pixiTMR) {

View File

@ -0,0 +1,58 @@
import { Misc } from "../misc.js";
import { RollDataAjustements } from "../rolldata-ajustements.js";
import { tmrColors, tmrConstants, TMRType, TMRUtility } from "../tmr-utility.js";
import { Debordement } from "./debordement.js";
import { Draconique } from "./draconique.js";
export class Desorientation extends Draconique {
constructor() {
super();
}
type() { return 'souffle' }
match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase().includes('désorientation'); }
manualMessage() { return false }
async onActorCreateOwned(actor, souffle) {
const type = Misc.rollOneOf(this._typesPossibles(actor));
console.log("désorientation", type);
souffle.name += ": " + TMRType[type].name;
await this._creerCasesTmr(actor, type, souffle);
}
_typesPossibles(actor) {
const dejaDesorientes = Misc.distinct(actor.data.items.filter(it => this.isCase(it)).map(it => it.type));
return Object.keys(TMRType).filter(it => !dejaDesorientes.includes(it));
}
async onActorDeleteOwned(actor, souffle) {
await this._supprimerCasesTmr(actor, souffle);
}
code() { return 'desorientation' }
tooltip(linkData) { return `Désorientation, cette case n'existe plus !` }
img() { return 'icons/svg/explosion.svg' }
_createSprite(pixiTMR) {
return pixiTMR.sprite(this.code(),
{
color: tmrColors.trounoir, alpha: 1, taille: tmrConstants.full, decallage: { x: 2, y: 2 },
});
}
async _creerCasesTmr(actor, type, souffle) {
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
let tmrs = TMRUtility.filterTMR(it => it.type == type && !existants.includes(it.coord));
for (let tmr of tmrs) {
await this.createCaseTmr(actor, 'Désorientation: ' + tmr.label, tmr, souffle._id);
}
}
async _supprimerCasesTmr(actor, souffle) {
let caseTmrs = actor.data.items.filter(it => it.data.sourceId == souffle._id);
for (let casetmr of caseTmrs) {
await actor.deleteOwnedItem(casetmr._id);
}
}
}

View File

@ -1,3 +1,4 @@
import { TMRUtility } from "../tmr-utility.js";
import { PixiTMR } from "./pixi-tmr.js"; import { PixiTMR } from "./pixi-tmr.js";
const registeredEffects = [ const registeredEffects = [
@ -14,6 +15,8 @@ export class Draconique
static isTeteDragon(element) { return element.type == 'tete'; } static isTeteDragon(element) { return element.type == 'tete'; }
static isQueueSouffle(it) { return Draconique.isQueueDragon(it) || Draconique.isSouffleDragon(it); } static isQueueSouffle(it) { return Draconique.isQueueDragon(it) || Draconique.isSouffleDragon(it); }
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.data.coord); }
static register(draconique) { static register(draconique) {
registeredEffects[draconique.code()] = draconique; registeredEffects[draconique.code()] = draconique;
if (draconique.img()) { if (draconique.img()) {
@ -48,10 +51,10 @@ export class Draconique
* Méthode responsable de gérer une draconique (par exemple, ajouter des casetmr pour la fermeture des cités). * 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 * @param actor auquel la draconique est ajoutée
*/ */
async onActorCreateOwned(actor) { async onActorCreateOwned(actor, item) {
return false; return false;
} }
async onActorDeleteOwned(actor) { async onActorDeleteOwned(actor, item) {
return false; return false;
} }
/** /**
@ -108,10 +111,15 @@ export class Draconique
return Draconique.isCaseTMR(it) && it.data.specific == this.code() && (coord ? it.data.coord == coord : true); return Draconique.isCaseTMR(it) && it.data.specific == this.code() && (coord ? it.data.coord == coord : true);
} }
async createCaseTmr(actor, label, tmr) { find(list, coord = undefined) {
return list.find(c => this.isCase(c, coord));
}
async createCaseTmr(actor, label, tmr, sourceId=undefined) {
await actor.createOwnedItem({ await actor.createOwnedItem({
name: label, type: 'casetmr', img: this.img(), _id: randomID(16), name: label, type: 'casetmr', img: this.img(), _id: randomID(16),
data: { coord: tmr.coord, specific: this.code() } data: { coord: tmr.coord, specific: this.code(), sourceid:sourceId }
}); });
} }

View File

@ -11,6 +11,8 @@ import { CarteTmr } from "./carte-tmr.js";
import { PontImpraticable } from "./pont-impraticable.js"; import { PontImpraticable } from "./pont-impraticable.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
import { PresentCites } from "./present-cites.js"; import { PresentCites } from "./present-cites.js";
import { Desorientation } from "./desorientation.js";
import { Conquete } from "./conquete.js";
@ -27,6 +29,8 @@ export class EffetsDraconiques {
static terreAttache = new TerreAttache(); static terreAttache = new TerreAttache();
static trouNoir = new TrouNoir(); static trouNoir = new TrouNoir();
static pontImpraticable = new PontImpraticable(); static pontImpraticable = new PontImpraticable();
static desorientation = new Desorientation();
static conquete = new Conquete();
static init() { static init() {
Draconique.register(EffetsDraconiques.carteTmr); Draconique.register(EffetsDraconiques.carteTmr);
@ -41,13 +45,20 @@ export class EffetsDraconiques {
Draconique.register(EffetsDraconiques.trouNoir); Draconique.register(EffetsDraconiques.trouNoir);
Draconique.register(EffetsDraconiques.pontImpraticable); Draconique.register(EffetsDraconiques.pontImpraticable);
Draconique.register(EffetsDraconiques.presentCites); Draconique.register(EffetsDraconiques.presentCites);
Draconique.register(EffetsDraconiques.desorientation);
Draconique.register(EffetsDraconiques.conquete);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCaseInondee(caseTMR, coord) { static isCaseInondee(caseTMR, coord) {
return EffetsDraconiques.debordement.isCase(caseTMR, coord) || EffetsDraconiques.pontImpraticable.isCase(caseTMR, coord); return EffetsDraconiques.debordement.isCase(caseTMR, coord) ||
EffetsDraconiques.pontImpraticable.isCase(caseTMR, coord);
} }
static isInnaccessible(caseTMR, coord) {
return EffetsDraconiques.trouNoir.isCase(caseTMR, coord) ||
EffetsDraconiques.desorientation.isCase(caseTMR, coord);
}
static isCaseTrouNoir(caseTMR, coord) { static isCaseTrouNoir(caseTMR, coord) {
return EffetsDraconiques.trouNoir.isCase(caseTMR, coord); return EffetsDraconiques.trouNoir.isCase(caseTMR, coord);
} }
@ -76,8 +87,8 @@ export class EffetsDraconiques {
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('montée laborieuse')); return EffetsDraconiques.isMatching(element, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('montée laborieuse'));
} }
static isFermetureCite(element) {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isFermetureCite(element) {
return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.fermetureCites.match(it)); return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.fermetureCites.match(it));
} }
@ -99,14 +110,12 @@ export class EffetsDraconiques {
} }
static isDesorientation(element) { static isDesorientation(element) {
// TODO return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.desorientation.match(it)); // TODO
return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase() == 'désorientation');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isConquete(element) { static isConquete(element) {
// TODO return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.conquete.match(it));
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'conquête');
} }
static isPelerinage(element) { static isPelerinage(element) {

View File

@ -13,7 +13,7 @@ export class FermetureCites extends Draconique {
async onActorCreateOwned(actor, item) { await this._fermerLesCites(actor); } async onActorCreateOwned(actor, item) { await this._fermerLesCites(actor); }
code() { return 'fermeture' } code() { return 'fermeture' }
tooltip(linkData) { return `La ${TMRUtility.getTMR(linkData.data.coord).label} est fermée` } tooltip(linkData) { return `La ${this.tmrLabel(linkData)} est fermée` }
img() { return 'icons/svg/door-closed.svg' } img() { return 'icons/svg/door-closed.svg' }
_createSprite(pixiTMR) { _createSprite(pixiTMR) {
@ -30,4 +30,10 @@ export class FermetureCites extends Draconique {
await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr); await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr);
} }
} }
async onConquete(actor, coord) {
const citeFermee = actor.data.items.find(it => this.isCase(it, coord));
await this.actor.deleteOwnedItem(citeFermee._id);
}
} }

View File

@ -14,7 +14,7 @@ export class PontImpraticable extends Draconique {
async onActorDeleteOwned(actor, item) { await this._supprimerCaseTmr(actor); } async onActorDeleteOwned(actor, item) { await this._supprimerCaseTmr(actor); }
code() { return 'pont-impraticable' } code() { return 'pont-impraticable' }
tooltip(linkData) { return `${TMRUtility.getTMR(linkData.data.coord).label} impraticable` } tooltip(linkData) { return `${this.tmrLabel(linkData)} impraticable` }
img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' } img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' }
_createSprite(pixiTMR) { _createSprite(pixiTMR) {

View File

@ -14,29 +14,44 @@ export class PresentCites extends Draconique {
async onActorCreateOwned(actor, item) { await this._ajouterPresents(actor); } async onActorCreateOwned(actor, item) { await this._ajouterPresents(actor); }
code() { return 'present-cites' } code() { return 'present-cites' }
tooltip(linkData) { return `La ${TMRUtility.getTMR(linkData.data.coord).label} a un présent` } tooltip(linkData) { return `La ${this.tmrLabel(linkData)} a un présent` }
img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/gift.svg' } img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/gift.svg' }
_createSprite(pixiTMR) { _createSprite(pixiTMR) {
return pixiTMR.sprite(this.code(), return pixiTMR.sprite(this.code(),
{ {
color: tmrColors.tetes, alpha: 0.7, taille: tmrConstants.third, decallage:tmrConstants.topRight color: tmrColors.tetes, alpha: 0.7, taille: tmrConstants.third, decallage: tmrConstants.topRight
}); });
} }
async _ajouterPresents(actor) { async _ajouterPresents(actor) {
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
if (existants.length >0 ) { if (existants.length > 0) {
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user), whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: "Vous avez encore des présents dans des cités, vous devrez tirer une autre tête pour remplacer celle ci!" content: "Vous avez encore des présents dans des cités, vous devrez tirer une autre tête pour remplacer celle ci!"
}) })
} }
else{ else {
let cites = TMRUtility.filterTMR(it => it.type == 'cite'); let cites = TMRUtility.filterTMR(it => it.type == 'cite');
for (let tmr of cites) { for (let tmr of cites) {
await this.createCaseTmr(actor, 'Présent: ' + tmr.label, tmr); await this.createCaseTmr(actor, 'Présent: ' + tmr.label, tmr);
} }
} }
} }
async choisirUnPresent(casetmr) {
let d = new Dialog({
title: "Présent des cités",
content: `La ${casetmr.data.coord} vous offre un présent`,
buttons: {
fleur: {
icon: '<i class="fas fa-check"></i>',
label: "Fleur des rêves 2d6",
callback: () => this.creerObjet()
}
}
});
d.render(true);
}
} }

View File

@ -12,7 +12,7 @@ export class QueteEaux extends Draconique {
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
code() { return 'maitrisee' } code() { return 'maitrisee' }
tooltip(linkData) { return `Quête des eaux, le ${TMRUtility.getTMR(linkData.data.coord).label} est maîtrisé` } tooltip(linkData) { return `Quête des eaux, le ${this.tmrLabel(linkData)} est maîtrisé` }
img() { return 'icons/svg/bridge.svg' } img() { return 'icons/svg/bridge.svg' }
_createSprite(pixiTMR) { _createSprite(pixiTMR) {

View File

@ -12,7 +12,7 @@ export class ReserveExtensible extends Draconique {
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
code() { return 'reserve_extensible' } code() { return 'reserve_extensible' }
tooltip(linkData) { return `Réserve extensible en ${TMRUtility.getTMR(linkData.data.coord).label} !` } tooltip(linkData) { return `Réserve extensible en ${this.tmrLabel(linkData)} !` }
img() { return 'icons/svg/chest.svg' } img() { return 'icons/svg/chest.svg' }
_createSprite(pixiTMR) { _createSprite(pixiTMR) {

View File

@ -12,7 +12,7 @@ export class TerreAttache extends Draconique {
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
code() { return 'attache' } code() { return 'attache' }
tooltip(linkData) { return `Terre d'attache en ${TMRUtility.getTMR(linkData.data.coord).label} !` } tooltip(linkData) { return `Terre d'attache en ${this.tmrLabel(linkData)} !` }
img() { return 'icons/svg/anchor.svg' } img() { return 'icons/svg/anchor.svg' }
_createSprite(pixiTMR) { _createSprite(pixiTMR) {

View File

@ -12,7 +12,7 @@ export class TrouNoir extends Draconique {
async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); }
code() { return 'trounoir' } code() { return 'trounoir' }
tooltip(linkData) { return `Trou noir en ${TMRUtility.getTMR(linkData.data.coord).label} !` } tooltip(linkData) { return `Trou noir en ${this.tmrLabel(linkData)} !` }
img() { return 'icons/svg/explosion.svg' } img() { return 'icons/svg/explosion.svg' }
_createSprite(pixiTMR) { _createSprite(pixiTMR) {

View File

@ -6,7 +6,7 @@
"manifestPlusVersion": "1.0.0", "manifestPlusVersion": "1.0.0",
"minimumCoreVersion": "0.7.5", "minimumCoreVersion": "0.7.5",
"compatibleCoreVersion": "0.7.9", "compatibleCoreVersion": "0.7.9",
"templateVersion": 93, "templateVersion": 94,
"author": "LeRatierBretonnien", "author": "LeRatierBretonnien",
"authors": [ "authors": [
{ {

View File

@ -718,14 +718,20 @@
}, },
"queue": { "queue": {
"description": "", "description": "",
"refoulement": 0 "refoulement": 0,
}, "duree": "",
"restant" : 0
},
"ombre": { "ombre": {
"description": "", "description": "",
"refoulement": 2 "refoulement": 2,
"duree": "",
"restant" : 0
}, },
"souffle": { "souffle": {
"description": "" "description": "",
"duree": "",
"restant" : 0
}, },
"tete": { "tete": {
"description": "" "description": ""
@ -764,7 +770,8 @@
"type": "", "type": "",
"label": "", "label": "",
"specific": "", "specific": "",
"description": "" "description": "",
"sourceid":""
}, },
"recettealchimique": { "recettealchimique": {
"but": "", "but": "",

View File

@ -7,5 +7,6 @@
<option value="pont-impraticable">Pont impraticable</option> <option value="pont-impraticable">Pont impraticable</option>
<option value="desorientation">Désoriantation</option> <option value="desorientation">Désoriantation</option>
<option value="periple">Periple</option> <option value="periple">Periple</option>
<option value="conquete">Conquête</option>
<option value="pelerinage">Pèlerinage</option> <option value="pelerinage">Pèlerinage</option>
<option value="present-cites">Présents des cités</option> <option value="present-cites">Présents des cités</option>