Gestion queues/souffles

- débordement
- conquête
This commit is contained in:
Vincent Vandemeulebrouck 2021-02-12 01:44:27 +01:00
parent 42bd63c999
commit 5328d2b690
12 changed files with 312 additions and 115 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);

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,10 +402,13 @@ 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;
if (TMRUtility.isForceRencontre() || myRoll == 7) { if (TMRUtility.isForceRencontre() || myRoll == 7) {
return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale()); return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
@ -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,
@ -517,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 });
} }
@ -548,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);
} }
} }
@ -578,17 +604,18 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async declencheSortEnReserve(coordTMR) { async declencheSortEnReserve(coord) {
if (this.viewOnly) {
return; let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord);
}
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR);
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({
@ -640,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);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -719,8 +734,29 @@ export class RdDTMRDialog extends Dialog {
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();
} }
@ -729,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,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

@ -272,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] }],
@ -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)
} }
@ -477,7 +483,7 @@ export class TMRRencontres {
} }
await data.actor.resultCombatReveDeDragon(data); await data.actor.resultCombatReveDeDragon(data);
} }
static async onPostEchecReveDeDragon(tmrDialog, data) { static async onPostEchecReveDeDragon(tmrDialog, data) {
await data.actor.resultCombatReveDeDragon(data); await data.actor.resultCombatReveDeDragon(data);
tmrDialog.close(); tmrDialog.close();

View File

@ -90,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" },
@ -377,7 +377,7 @@ export class TMRUtility {
if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Sortie de carte ! Ré-insertion aléatoire if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Sortie de carte ! Ré-insertion aléatoire
coord = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos)); 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);
} }
@ -418,18 +418,15 @@ 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);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

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

@ -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

@ -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,6 +45,8 @@ 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);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -48,19 +54,23 @@ export class EffetsDraconiques {
return EffetsDraconiques.debordement.isCase(caseTMR, coord) || return EffetsDraconiques.debordement.isCase(caseTMR, coord) ||
EffetsDraconiques.pontImpraticable.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);
} }
static isReserveExtensible(caseTMR, coord) { static isReserveExtensible(caseTMR, coord) {
return EffetsDraconiques.reserveExtensible.isCase(caseTMR, coord); return EffetsDraconiques.reserveExtensible.isCase(caseTMR, coord);
} }
static isTerreAttache(caseTMR, coord) { static isTerreAttache(caseTMR, coord) {
return EffetsDraconiques.terreAttache.isCase(caseTMR, coord); return EffetsDraconiques.terreAttache.isCase(caseTMR, coord);
} }
static isCiteFermee(caseTMR, coord) { static isCiteFermee(caseTMR, coord) {
return EffetsDraconiques.fermetureCites.isCase(caseTMR, coord); return EffetsDraconiques.fermetureCites.isCase(caseTMR, coord);
} }
@ -77,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));
} }
@ -100,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

@ -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

@ -39,4 +39,19 @@ export class PresentCites extends Draconique {
} }
} }
} }
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

@ -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": ""

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>