Remplacement progressif rencontres

This commit is contained in:
Vincent Vandemeulebrouck
2022-11-07 00:04:43 +01:00
parent d20a6a1506
commit f659a7508a
21 changed files with 460 additions and 746 deletions

View File

@ -1,3 +1,4 @@
import { SHOW_DICE } from "./constants.js";
import { RollDataAjustements } from "./rolldata-ajustements.js";
import { RdDUtility } from "./rdd-utility.js";
import { TMRUtility } from "./tmr-utility.js";
@ -11,11 +12,12 @@ 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";
import { Misc } from "./misc.js";
import { HtmlUtility } from "./html-utility.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { RdDDice } from "./rdd-dice.js";
import { STATUSES } from "./settings/status-effects.js";
import { RdDRencontre } from "./item-rencontre.js";
/* -------------------------------------------- */
export class RdDTMRDialog extends Dialog {
@ -89,7 +91,7 @@ export class RdDTMRDialog extends Dialog {
TMRUtility.getTMR(coord).type == 'fleuve'
? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve'
: it => it.system.coord == coord
);
);
}
/* -------------------------------------------- */
@ -146,7 +148,7 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
_tokenRencontre(rencontre) {
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.system.coord);
}
_tokenCaseSpeciale(casetmr) {
const caseData = casetmr;
@ -248,7 +250,7 @@ export class RdDTMRDialog extends Dialog {
let tmrpos = document.getElementById("tmr-pos");
if (this.isDemiReveCache()) {
tmrpos.innerHTML = `?? ( ${ TMRUtility.getTMRType(coord)})`;
tmrpos.innerHTML = `?? ( ${TMRUtility.getTMRType(coord)})`;
} else {
tmrpos.innerHTML = `${coord} ( ${TMRUtility.getTMRLabel(coord)})`;
}
@ -280,25 +282,44 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
async onActionRencontre(action, tmr) {
switch (action) {
case 'derober':
await this.derober();
return;
case 'refouler':
await this.refouler();
break;
case 'maitriser':
await this.maitriserRencontre();
break;
case 'ignorer':
await this.ignorerRencontre();
break;
}
await this.postRencontre(tmr);
}
async derober() {
await this.actor.addTMRRencontre(this.currentRencontre);
console.log("-> derober", this.currentRencontre);
await this.actor.addTMRRencontre(this.currentRencontre);
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR.");
this.close();
}
/* -------------------------------------------- */
async refouler() {
await this.actor.ajouterRefoulement(this.currentRencontre.refoulement ?? 1, `une rencontre ${this.currentRencontre.name}`);
console.log("-> refouler", this.currentRencontre);
await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
this.updateTokens();
console.log("-> refouler", this.currentRencontre)
this.updateValuesDisplay();
this.nettoyerRencontre();
}
/* -------------------------------------------- */
async ignorerRencontre() {
console.log("-> ignorer", this.currentRencontre);
this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
this.updateTokens();
@ -307,7 +328,14 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
colorierZoneRencontre(listCoordTMR) {
// garder la trace de l'état en cours
setRencontreState(state, listCoordTMR) {
this.rencontreState = state;
this.$marquerCasesTMR(listCoordTMR ?? []);
}
/* -------------------------------------------- */
$marquerCasesTMR(listCoordTMR) {
this.currentRencontre.graphics = []; // Keep track of rectangles to delete it
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location
for (let coordTMR of listCoordTMR) {
@ -323,23 +351,6 @@ export class RdDTMRDialog extends Dialog {
}
}
/* -------------------------------------------- */
// garder la trace de l'état en cours
setStateRencontre(state) {
this.rencontreState = state;
}
/* -------------------------------------------- */
async choisirCasePortee(coord, portee) {
// Récupère la liste des cases à portées
this.colorierZoneRencontre(TMRUtility.getTMRPortee(coord, portee));
}
/* -------------------------------------------- */
async choisirCaseType(type) {
this.colorierZoneRencontre(TMRUtility.filterTMR(it => it.type == type).map(it => it.coord));
}
/* -------------------------------------------- */
checkQuitterTMR() {
@ -370,7 +381,9 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async maitriserRencontre() {
this.actor.deleteTMRRencontreAtPosition();
console.log("-> maitriser", this.currentRencontre);
await this.actor.deleteTMRRencontreAtPosition();
this.updateTokens();
let rencontreData = {
@ -381,7 +394,7 @@ export class RdDTMRDialog extends Dialog {
rencontre: this.currentRencontre,
nbRounds: 1,
canClose: false,
selectedCarac: {label: "reve-actuel"},
selectedCarac: { label: "reve-actuel" },
tmr: TMRUtility.getTMR(this._getActorCoord())
}
@ -390,8 +403,6 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async _tentativeMaitrise(rencData) {
console.log("-> matriser", rencData);
rencData.reve = this.actor.getReveActuel();
rencData.etat = this.actor.getEtatGeneral();
@ -401,41 +412,67 @@ export class RdDTMRDialog extends Dialog {
? this._rollPresentCite(rencData)
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
let postProcess = await TMRRencontres.gererRencontre(this, rencData);
const result = rencData.rolled.isSuccess
? rencData.rencontre.system.succes
: rencData.rencontre.system.echec;
await RdDRencontre.appliquer(result.effets, this, rencData);
rencData.poesie = { extrait: result.poesie, reference: result.reference };
rencData.message = this.formatMessageRencontre(rencData, result.message);
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData)
});
if (postProcess) {
/** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */
await postProcess(this, rencData);
}
else {
this.currentRencontre = undefined;
}
this.updateValuesDisplay();
if (this.checkQuitterTMR()) {
return;
}
else if (rencData.rolled.isEchec && rencData.rencontre.isPersistant) {
setTimeout(() => {
rencData.nbRounds++;
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase;
}
this._tentativeMaitrise(rencData);
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000);
if (this.rencontreState == 'persistant') {
this._nouvelleTentativeMaitrise(rencData);
}
else if (!this.isRencontreDeplacement()) {
this.nettoyerRencontre();
}
}
_nouvelleTentativeMaitrise(rencData) {
setTimeout(() => {
// TODO: remplacer par une boucle while(this.currentRencontre) ?
rencData.nbRounds++;
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase;
}
this._tentativeMaitrise(rencData);
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000);
this.rencontreState == 'normal';
}
formatMessageRencontre(rencData, template) {
let messageDuree = ''
if (rencData.nbRounds > 1) {
if (rencData.rolled.isSuccess) {
messageDuree = ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
}
else {
messageDuree = ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
}
}
try {
const compiled = Handlebars.compile(template);
return compiled(rencData) + messageDuree ;
} catch (error) {
return template + messageDuree ;
}
}
/* -------------------------------------------- */
_rollPresentCite(rencontreData) {
let rolled = RdDResolutionTable.computeChances(rencontreData.reve, 0);
mergeObject(rolled, { caracValue: rencontreData.reve, finalLevel: 0, roll: rolled.score });
_rollPresentCite(rencData) {
let rolled = RdDResolutionTable.computeChances(rencData.reve, 0);
mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score });
RdDResolutionTable.succesRequis(rolled);
return rolled;
}
@ -479,15 +516,16 @@ export class RdDTMRDialog extends Dialog {
if (this._presentCite(tmr)) {
return;
}
let rencontre = await this._jetDeRencontre(tmr);
if (rencontre) { // Manages it
if (rencontre.rencontre) rencontre = rencontre.rencontre; // Manage stored rencontres
console.log("manageRencontre", rencontre);
this.currentRencontre = duplicate(rencontre);
let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, () => this.postRencontre(tmr));
dialog.render(true);
this.currentRencontre = await this._jetDeRencontre(tmr);
if (this.currentRencontre) {
if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)){
// rencontre en attente suite à dérobade
await this.maitriserRencontre();
}
else {
let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, tmr);
dialog.render(true);
}
}
else {
this.postRencontre(tmr);
@ -500,15 +538,18 @@ export class RdDTMRDialog extends Dialog {
if (presentCite) {
this.minimize();
const caseData = presentCite;
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (type => this._utiliserPresentCite(presentCite, type, tmr)));
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (present => this._utiliserPresentCite(presentCite, present, tmr)));
}
return presentCite;
}
/* -------------------------------------------- */
async _utiliserPresentCite(presentCite, typeRencontre, tmr) {
this.currentRencontre = TMRRencontres.getRencontre(typeRencontre);
await TMRRencontres.evaluerForceRencontre(this.currentRencontre);
async _utiliserPresentCite(presentCite, present, tmr) {
this.currentRencontre = present.clone({
'system.force': await RdDDice.rollTotal(present.system.formule),
'system.coord': tmr.coord
}, {save: false});
await EffetsDraconiques.presentCites.ouvrirLePresent(this.actor, presentCite);
this.removeToken(tmr, presentCite);
@ -530,32 +571,27 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async _jetDeRencontre(tmr) {
let rencontre = this.rencontresExistantes.find(prev => prev.coord == tmr.coord);
let rencontre = this.lookupRencontreExistente(tmr);
if (rencontre) {
return rencontre;
return TMRRencontres.calculRencontre(rencontre, tmr);
}
let locTMR = (this.isDemiReveCache()
? Misc.upperFirst(tmr.type) + " ??"
? TMRUtility.getTMRType(tmr.coord) + " ??"
: tmr.label + " (" + tmr.coord + ")");
let myRoll = await RdDDice.rollTotal("1dt");
if (TMRUtility.isForceRencontre() || myRoll == 7) {
let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
console.warn('// TODO: remettre myRoll==7');
if (myRoll <= 7) {
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
return await TMRRencontres.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
} else {
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
}
}
/* -------------------------------------------- */
async rencontreTMRRoll(tmr, isMauvaise = false) {
let rencontre = (isMauvaise
? await TMRRencontres.getMauvaiseRencontre()
: await TMRRencontres.getRencontreAleatoire(tmr));
rencontre.coord = tmr.coord;
rencontre.date = game.system.rdd.calendrier.getDateFromIndex();
rencontre.heure = game.system.rdd.calendrier.getCurrentHeure();
return rencontre;
lookupRencontreExistente(tmr) {
return this.rencontresExistantes.find(it => it.system.coord == tmr.coord)
?? this.rencontresExistantes.find(it => it.system.coord == "");
}
/* -------------------------------------------- */
@ -583,7 +619,7 @@ export class RdDTMRDialog extends Dialog {
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
}
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined,
rollData.competence.system.defaut_carac = 'reve-actuel';
rollData.competence.system.defaut_carac = 'reve-actuel';
await this._rollMaitriseCaseHumide(rollData);
}
}
@ -874,16 +910,14 @@ export class RdDTMRDialog extends Dialog {
if (this.isDemiReveCache()) {
if (this.isTerreAttache(targetCoord)
|| this.isConnaissanceFleuve(currentCoord, targetCoord)
|| deplacementType == 'changeur')
{
|| this.isConnaissanceFleuve(currentCoord, targetCoord)
|| deplacementType == 'changeur') {
// déplacement possible
await this.actor.setTMRVisible(true);
this.demiReve = this._tokenDemiReve();
this._trackToken(this.demiReve);
}
else
{
else {
ui.notifications.error(`Vous ne connaissez plus votre position dans les TMR.
Vous devez utiliser les boutons de direction pour vous déplacer.
Une fois que vous aurez retrouvé votre demi-rêve, demandez au gardien de vérifier et rendre les TMR visibles.
@ -892,20 +926,18 @@ export class RdDTMRDialog extends Dialog {
}
}
switch (deplacementType){
switch (deplacementType) {
case 'normal':
case 'changeur':
case 'passeur':
await this._deplacerDemiReve(targetCoord, deplacementType);
break;
case 'messager':
await this._messagerDemiReve(targetCoord);
break;
case 'changeur':
case 'passeur':
await this._deplacerDemiReve(targetCoord, deplacementType);
break;
default:
ui.notifications.error("Vous ne pouvez pas 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);
ui.notifications.error("Vous ne pouvez pas 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);
}
this.checkQuitterTMR();
@ -913,19 +945,23 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
_calculDeplacement(targetCoord, currentCoord, fromOddq, toOddq) {
const isInArea = this.rencontreState == 'aucune'
? (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1)
: this.currentRencontre?.locList?.find(coord => coord == targetCoord) ?? false
if (isInArea) {
switch (this.rencontreState) {
case 'aucune': return 'normal';
case 'passeur': case 'changeur': case 'messager': return this.rencontreState;
if (this.isRencontreDeplacement()) {
if (this.currentRencontre?.locList?.find(coord => coord == targetCoord)) {
return this.rencontreState;
}
}
else {
if (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1) {
return 'normal'
}
}
return 'erreur';
}
isRencontreDeplacement() {
return ['passeur', 'changeur', 'messager'].includes(this.rencontreState);
}
/* -------------------------------------------- */
async _messagerDemiReve(targetCoord) {
/*