Compare commits

...

18 Commits
12.0.45 ... v11

Author SHA1 Message Date
29931fdcb5 Merge pull request 'Fix: sommeil avec double rêve' (#758) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #758
2025-04-30 14:01:03 +02:00
ec24e4a7e7 Fix: sommeil avec double rêve 2025-04-27 17:51:50 +02:00
d1adf3f6c4 Merge pull request '12.0.49 - La deuxième lame d'Astrobazzarh' (#757) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 1m20s
Reviewed-on: #757
2025-04-24 16:46:35 +02:00
8eb1387be4 attaques à distance sans difficulté libre 2025-04-24 00:58:42 +02:00
85378d74e3 Fix parade des vieux boucliers 2025-04-24 00:43:32 +02:00
9471420d38 Fix défenses particulières 2025-04-23 22:01:29 +02:00
6e456ca92c Merge pull request '12.0.48 - La chèvre d'Astrobazzarh' (#756) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 2m2s
Reviewed-on: #756
2025-04-23 11:50:59 +02:00
482256c218 L'armure du Bandersnatch 2025-04-22 20:42:43 +02:00
fa1c4ff221 Correction: particulières sur carac dérivées 2025-04-22 20:42:21 +02:00
b777271657 Echec à la mise en réserve
Un échec au lancement de sort brise la concentration, la mise en
réserve présuppose le lancement du sort.
2025-04-22 20:41:49 +02:00
d06a55b615 Amélioration message lancement sort en réserve 2025-04-22 20:41:35 +02:00
adfbc11eb8 Consistance chèvre
La consistance chèvre est supportée (caractères accentués)
2025-04-22 20:41:31 +02:00
9dd905134b Correction sur les mise à jour en cascade + correction sur le force rendering après un changement de competence
All checks were successful
Release Creation / build (release) Successful in 2m25s
2025-04-06 23:15:10 +02:00
f32b6af7b6 Correction sur les mise à jour en cascade + correction sur le force rendering après un changement de competence 2025-04-06 23:13:59 +02:00
9b8a600e22 Merge pull request '## 12.0.46 - Le double demi d'Astrobazzarh' (#755) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 1m25s
Reviewed-on: #755
2025-03-18 20:48:20 +01:00
25db7e0712 Amélioration des fermetures de TMR
- un seul message lors de la fermeture au MJ et joueur
- le déclenchement de sort en réserve
2025-03-18 01:56:26 +01:00
776d4ce9ec correction des raffraîchissement lors du sommeil
On peut de nouveau dormir plusieurs heures
2025-03-18 01:50:00 +01:00
1de0806e37 Fix changelog 2025-03-16 00:20:48 +01:00
12 changed files with 225 additions and 166 deletions

View File

@ -1,6 +1,34 @@
# 12.0 # 12.0
## 12.0.50 - Le sommeil d'Astrobazzarh
- Le don de double rêve n'interrompt plus le sommeil toutes les heures
## 12.0.44 - Les errements d'Astrobazzarh, encore ## 12.0.49 - La deuxième lame d'Astrobazzarh
- Corrections
- les défenses particulières sont correctement affichées
- les vieux boucliers (sans catégorie de parade car créés il y a longtemps) peuvent parer...
- Les attaques à distance n'ont pas de difficulté libre
## 12.0.48 - La chèvre d'Astrobazzarh
- le Bandersnatch a une protection de 10
- la consistance chèvre est maintenant possible dans les recettes
alchimiques (et toutes les consistances avec accents)
- un échec au lancement d'un sort pour le mettre en réserve brise
la concentration du haut-rêvant
- Correction: les réussites particulières fonctionnent avec les caractéristiques dérivées
## 12.0.47
- Correction sur les mise à jour en cascade -
- Correction sur le force rendering après un changement de competence
## 12.0.46 - Le double demi d'Astrobazzarh
- correction des raffraîchissement lors du sommeil qui empêchait de dormir
plusieurs heures
- Si la fatigue n'est pas utilisée, les rounds dans les TMR font perdre de l'endurance (au lieu d'en gagner)
- les TMRs se ferment correctement quand la fatigue maximale est dépassée
- le message de lancement de sort en réserve donne la description du sort
- suppression de double-messages lors de la fermeture des TMR
## 12.0.45 - Les errements d'Astrobazzarh, encore
- La difficulté des méditations n'augmente plus en cas de réussite et d'échec normal - La difficulté des méditations n'augmente plus en cas de réussite et d'échec normal
- Renommage du Bouton pour révéler/masquer le demi-rêve - Renommage du Bouton pour révéler/masquer le demi-rêve

View File

@ -279,28 +279,32 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async dormirChateauDormant() { async dormirChateauDormant() {
if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil.nouveaujour) { if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil.nouveaujour) {
await this.$dormirChateauDormant();
setTimeout(() => this.sheet.render(), 20)
}
}
async $dormirChateauDormant() {
const message = { const message = {
whisper: ChatUtility.getOwners(this), whisper: ChatUtility.getOwners(this),
content: "" content: ""
}; };
await this._recuperationSante(message) await this._recuperationSante(message);
await this._recupereMoralChateauDormant(message) await this._recupereMoralChateauDormant(message);
await this._recupereChance() await this._recupereChance();
await this.transformerStress() await this.transformerStress();
await this.retourSeuilDeReve(message) await this.retourSeuilDeReve(message);
await this.setBonusPotionSoin(0) await this.setBonusPotionSoin(0);
await this.retourSust(message) await this.retourSust(message);
await this.$perteReveEnchantementsChateauDormants() await this.$perteReveEnchantementsChateauDormants();
await this.$suppressionLancementsSort() await this.$suppressionLancementsSort();
await RdDCoeur.applyCoeurChateauDormant(this, message) await RdDCoeur.applyCoeurChateauDormant(this, message);
if (message.content != "") { if (message.content != "") {
message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`; message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`;
ChatMessage.create(message); ChatMessage.create(message);
} }
await this.resetInfoSommeil(); await this.resetInfoSommeil();
setTimeout(() => this.sheet.render(), 20)
}
} }
async resetInfoSommeil() { async resetInfoSommeil() {
@ -457,12 +461,10 @@ export class RdDActor extends RdDBaseActorSang {
ChatMessage.create(message); ChatMessage.create(message);
} }
if (options.chateauDormant) { if (options.chateauDormant) {
await this.dormirChateauDormant(); await this.$dormirChateauDormant();
} }
else {
setTimeout(() => this.sheet.render(), 20) setTimeout(() => this.sheet.render(), 20)
} }
}
async reveilReveDeDragon(message, heures) { async reveilReveDeDragon(message, heures) {
const restant = Math.max(this.system.sommeil?.heures - heures, 0) const restant = Math.max(this.system.sommeil?.heures - heures, 0)
@ -482,7 +484,7 @@ export class RdDActor extends RdDBaseActorSang {
await this.$recupererFatigue(message); await this.$recupererFatigue(message);
await this.$jetRecuperationReve(dormi, message); await this.$jetRecuperationReve(dormi, message);
if (dormi.etat == 'dort' && EffetsDraconiques.isDonDoubleReve(this)) { if (dormi.etat == 'dort' && EffetsDraconiques.isDonDoubleReve(this)) {
dormi.etat = await this.$jetRecuperationReve(dormi, message); await this.$jetRecuperationReve(dormi, message);
} }
} }
} }
@ -541,7 +543,6 @@ export class RdDActor extends RdDBaseActorSang {
max = Math.floor(max / 2); max = Math.floor(max / 2);
} }
const manquant = max - this.system.sante.endurance.value; const manquant = max - this.system.sante.endurance.value;
if (manquant > 0) { if (manquant > 0) {
await this.santeIncDec("endurance", manquant); await this.santeIncDec("endurance", manquant);
message.content += `Vous récuperez ${manquant} points d'endurance. `; message.content += `Vous récuperez ${manquant} points d'endurance. `;
@ -558,7 +559,6 @@ export class RdDActor extends RdDBaseActorSang {
} }
fatigue = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue)) fatigue = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue))
await this.update({ 'system.sante.fatigue.value': fatigue }); await this.update({ 'system.sante.fatigue.value': fatigue });
await new Promise(resolve => setTimeout(resolve, 200));
if (fatigue == 0) { if (fatigue == 0) {
message.content += "Vous êtes complêtement reposé. "; message.content += "Vous êtes complêtement reposé. ";
} }
@ -668,19 +668,23 @@ export class RdDActor extends RdDBaseActorSang {
if (!RdDItemRace.checkRacialMax(this, caracName, to)) { if (!RdDItemRace.checkRacialMax(this, caracName, to)) {
return return
} }
let updates = {};
if (caracName == LIST_CARAC_PERSONNAGE.reve.code) { if (caracName == LIST_CARAC_PERSONNAGE.reve.code) {
if (to > Misc.toInt(this.system.reve.seuil.value)) { if (to > Misc.toInt(this.system.reve.seuil.value)) {
this.setPointsDeSeuil(to); updates[`system.reve.seuil.value`] = to; // SFA : Direct and packed changes
//this.setPointsDeSeuil(to);
} }
} }
if (caracName == LIST_CARAC_PERSONNAGE.chance.code) { if (caracName == LIST_CARAC_PERSONNAGE.chance.code) {
if (to > Misc.toInt(this.system.compteurs.chance.value)) { if (to > Misc.toInt(this.system.compteurs.chance.value)) {
this.setPointsDeChance(to); updates[`system.compteurs.chance.value`] = to; // SFA : Direct and packed changes
//this.setPointsDeChance(to);
} }
} }
let selectedCarac = this.findCaracByName(caracName); let selectedCarac = this.findCaracByName(caracName);
const from = selectedCarac.value const from = selectedCarac.value
await this.update({ [`system.carac.${caracName}.value`]: to }); updates[`system.carac.${caracName}.value`] = to;
await this.update(updates);
await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName); await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName);
} }
@ -784,7 +788,7 @@ export class RdDActor extends RdDBaseActorSang {
const toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie, competence.getCategories()); const toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie, competence.getCategories());
this.notifyCompetencesTronc(competence, toNiveau); this.notifyCompetencesTronc(competence, toNiveau);
const fromNiveau = competence.system.niveau; const fromNiveau = competence.system.niveau;
await competence.update({ 'system.niveau': toNiveau }, { render: false }) await competence.update({ 'system.niveau': toNiveau }, { render: true })
await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name, true); await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name, true);
} }
} }
@ -1048,20 +1052,10 @@ export class RdDActor extends RdDBaseActorSang {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async deleteRencontreTMRAtPosition() {
const rencontreIds = this.itemTypes[ITEM_TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id)
if (rencontreIds.length > 0) {
await this.deleteEmbeddedDocuments('Item', rencontreIds)
}
}
getRencontreTMREnAttente() { getRencontreTMREnAttente() {
return this.itemTypes[ITEM_TYPES.rencontre].find(this.filterRencontreTMRDemiReve())
}
filterRencontreTMRDemiReve() {
const position = this.getDemiReve() const position = this.getDemiReve()
return it => it.system.coord == position return this.itemTypes[ITEM_TYPES.rencontre].find(it => it.system.coord == position)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -1771,7 +1765,7 @@ export class RdDActor extends RdDBaseActorSang {
if (reveActuel == 0) { // 0 points de reve if (reveActuel == 0) { // 0 points de reve
ChatMessage.create({ content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" }); ChatMessage.create({ content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" });
} }
if (!rollData.isSortReserve) { if (!rollData.isSortReserve || !rolled.isSuccess) {
this.tmrApp?.close(); this.tmrApp?.close();
} }
} }

View File

@ -39,7 +39,12 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return 0; return 0;
} }
getFatigueRestante() { return this.getFatigueMax() - this.getFatigueActuelle() } isCumulFatigueCauseSommeil(cumulFatigue){
return ReglesOptionnelles.isUsing("appliquer-fatigue")
? (this.getFatigueRestante() <= cumulFatigue)
: (this.getEnduranceActuelle() <= cumulFatigue)
}
getFatigueRestante() {return this.getFatigueMax() - this.getFatigueActuelle() }
getFatigueMin() { return this.system.sante.endurance.max - this.system.sante.endurance.value } getFatigueMin() { return this.system.sante.endurance.max - this.system.sante.endurance.value }
malusFatigue() { malusFatigue() {

View File

@ -5,7 +5,7 @@ import { RdDUtility } from "../../rdd-utility.js";
import { RdDAlchimie } from "../../rdd-alchimie.js"; import { RdDAlchimie } from "../../rdd-alchimie.js";
import { TextRollManager } from "./text-roll-formatter.js"; import { TextRollManager } from "./text-roll-formatter.js";
const REGEX_ALCHIMIE_TERMES = "(?<termes>(\\w|-)+)" const REGEX_ALCHIMIE_TERMES = "(?<termes>([-A-Za-zÀ-ÖØ-öø-ÿ ])+)"
const REGEX_ALCHIMIE_MANIP = "(?<manip>(couleur|consistance))" const REGEX_ALCHIMIE_MANIP = "(?<manip>(couleur|consistance))"
const XREGEXP_ROLL_ALCHIMIE = XRegExp("@roll\\[" + REGEX_ALCHIMIE_MANIP + "\\s+" + REGEX_ALCHIMIE_TERMES + "\\]", 'giu') const XREGEXP_ROLL_ALCHIMIE = XRegExp("@roll\\[" + REGEX_ALCHIMIE_MANIP + "\\s+" + REGEX_ALCHIMIE_TERMES + "\\]", 'giu')
const XREGEXP_ROLL_ALCHIMIE_MANIP = XRegExp("@" + REGEX_ALCHIMIE_MANIP + "\\{" + REGEX_ALCHIMIE_TERMES + "\\}", 'giu') const XREGEXP_ROLL_ALCHIMIE_MANIP = XRegExp("@" + REGEX_ALCHIMIE_MANIP + "\\{" + REGEX_ALCHIMIE_TERMES + "\\}", 'giu')

View File

@ -120,7 +120,7 @@ export class RdDItemArme extends Item {
static defenseArmeParade(armeAttaque, armeParade) { static defenseArmeParade(armeAttaque, armeParade) {
const defCategory = RdDItemArme.getCategorieParade(armeParade) const defCategory = RdDItemArme.getCategorieParade(armeParade)
if (defCategory == 'bouclier') { if (defCategory == 'boucliers') {
return 'norm' return 'norm'
} }
if (armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/)) { if (armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/)) {

View File

@ -55,6 +55,10 @@ export class RdDItemRace extends RdDItem {
isMax(actor, code, value = undefined) { isMax(actor, code, value = undefined) {
const path = RdDCarac.carac(code)?.path const path = RdDCarac.carac(code)?.path
if (path == undefined) {
// cas des caractéristiques dérivées, pas de max
return false
}
if (value == undefined) { if (value == undefined) {
value = path ? foundry.utils.getProperty(actor, path) : 0 value = path ? foundry.utils.getProperty(actor, path) : 0
} }

View File

@ -1047,11 +1047,12 @@ export class RdDCombat {
async _onParade(defenderRoll) { async _onParade(defenderRoll) {
if (RdDCombat.isParticuliere(defenderRoll)) {
return await this._onParadeParticuliere(defenderRoll)
}
if (RdDCombat.isReussite(defenderRoll)) { if (RdDCombat.isReussite(defenderRoll)) {
return await this._onParadeNormale(defenderRoll) await this._onParadeNormale(defenderRoll)
if (RdDCombat.isParticuliere(defenderRoll)) {
await this._onParadeParticuliere(defenderRoll)
}
return
} }
await this._onParadeEchec(defenderRoll) await this._onParadeEchec(defenderRoll)
} }
@ -1135,11 +1136,12 @@ export class RdDCombat {
} }
async _onEsquive(defenderRoll) { async _onEsquive(defenderRoll) {
if (RdDCombat.isParticuliere(defenderRoll)) {
return await this._onEsquiveParticuliere(defenderRoll)
}
if (RdDCombat.isReussite(defenderRoll)) { if (RdDCombat.isReussite(defenderRoll)) {
return await this._onEsquiveNormale(defenderRoll) await this._onEsquiveNormale(defenderRoll)
if (RdDCombat.isParticuliere(defenderRoll)) {
await this._onEsquiveParticuliere(defenderRoll)
}
return
} }
return await this._onEsquiveEchec(defenderRoll) return await this._onEsquiveEchec(defenderRoll)
} }

View File

@ -15,7 +15,6 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { RdDDice } from "./rdd-dice.js"; import { RdDDice } from "./rdd-dice.js";
import { STATUSES } from "./settings/status-effects.js"; import { STATUSES } from "./settings/status-effects.js";
import { RdDRencontre } from "./item/rencontre.js"; import { RdDRencontre } from "./item/rencontre.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { ITEM_TYPES } from "./constants.js"; import { ITEM_TYPES } from "./constants.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
@ -83,7 +82,7 @@ export class RdDTMRDialog extends Dialog {
this.subdialog = undefined this.subdialog = undefined
this.displaySize = undefined this.displaySize = undefined
if (!this.viewOnly && !game.user.isGM) { if (!this.viewOnly && !game.user.isGM) {
this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); this.$tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
} }
this.callbacksOnAnimate = []; this.callbacksOnAnimate = [];
const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def); const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def);
@ -139,7 +138,7 @@ export class RdDTMRDialog extends Dialog {
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
// Le reste... // Le reste...
this.updateValuesDisplay(); this.$updateValuesDisplay();
} }
lancerUnSort() { lancerUnSort() {
@ -190,7 +189,7 @@ export class RdDTMRDialog extends Dialog {
forceTMRContinueAction() { forceTMRContinueAction() {
ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR'); ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR');
this.bringSubDialogToTop(); this.bringSubDialogToTop();
return; return false
} }
setTMRPendingAction(dialog) { setTMRPendingAction(dialog) {
@ -297,7 +296,7 @@ export class RdDTMRDialog extends Dialog {
const coordOrig = this._getCoordActor(); const coordOrig = this._getCoordActor();
const coordTarget = TMRUtility.deplacement(coordOrig, move); const coordTarget = TMRUtility.deplacement(coordOrig, move);
await this._deplacerDemiReve(coordTarget, 'normal'); await this._deplacerDemiReve(coordTarget, 'normal');
this.checkQuitterTMR(); await this.$checkQuitterTMR();
} }
calculCoutMonteeTMR() { calculCoutMonteeTMR() {
@ -305,7 +304,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateValuesDisplay() { async $updateValuesDisplay() {
if (this.viewOnly || !this.rendered) { if (this.viewOnly || !this.rendered) {
return; return;
} }
@ -336,22 +335,30 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async close() { async close() {
await this.$forceClose(this.actor.name + " a quitté les terres médianes")
}
async $forceClose(message) {
if (this.subdialog) { if (this.subdialog) {
return this.forceTMRContinueAction() this.forceTMRContinueAction()
return false
} }
this.descenteTMR = true; this.descenteTMR = true;
if (this.actor.tmrApp) { if (this.actor.tmrApp) {
this.actor.tmrApp = undefined; // Cleanup reference this.actor.tmrApp = undefined; // Cleanup reference
if (!this.viewOnly) { if (!this.viewOnly) {
await this.actor.setEffect(STATUSES.StatusDemiReve, false) await this.actor.setEffect(STATUSES.StatusDemiReve, false);
this._tellToGM(this.actor.name + " a quitté les terres médianes"); this.$tellToUserAndGM(message)
} }
await this.actor.santeIncDec((ReglesOptionnelles.isUsing("appliquer-fatigue") ? "fatigue" : "endurance"), const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue");
this.cumulFatigue) await this.actor.santeIncDec(
appliquerFatigue ? "fatigue" : "endurance",
(appliquerFatigue ? 1 : -1) * this.cumulFatigue);
} }
await super.close(); this.pixiTMR.close();
this.pixiTMR.close()
this.pixiTMR = undefined this.pixiTMR = undefined
await super.close();
return true
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -363,48 +370,53 @@ export class RdDTMRDialog extends Dialog {
} }
switch (action) { switch (action) {
case 'derober': case 'derober':
await this.derober(); await this.$derober()
this.restoreTMRAfterAction(); this.restoreTMRAfterAction()
return; return
case 'refouler': case 'refouler':
await this.refouler(); await this.$refouler()
break; break
case 'maitriser': case 'maitriser':
await this.maitriserRencontre(); await this.$maitriserRencontre()
break; break
case 'ignorer': case 'ignorer':
await this.ignorerRencontre(); await this.$ignorerRencontre()
break; break
} }
await this.postRencontre(tmr); await this.postRencontre(tmr);
this.restoreTMRAfterAction(); this.restoreTMRAfterAction();
} }
async derober() { async $derober() {
if (this.currentRencontre) {
console.log("-> derober", this.currentRencontre); console.log("-> derober", this.currentRencontre);
await this.actor.addTMRRencontre(this.currentRencontre); await this.actor.addTMRRencontre(this.currentRencontre);
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR."); this.$forceClose(`${this.actor.name} s'est dérobé face à la rencontre ${this.currentRencontre.name}, et quitte les TMR.`)
this.close(); }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async refouler() { async $refouler() {
if (this.currentRencontre) {
console.log("-> refouler", this.currentRencontre); 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.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`);
await this.actor.deleteRencontreTMRAtPosition() await this.$deleteRencontreTMRAtPosition()
this.updateTokens(); this.updateTokens();
this.updateValuesDisplay(); this.$updateValuesDisplay();
this.nettoyerRencontre(); this.$nettoyerRencontre();
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async ignorerRencontre() { async $ignorerRencontre() {
if (this.currentRencontre) {
console.log("-> ignorer", this.currentRencontre); console.log("-> ignorer", this.currentRencontre);
this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); this.$tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
await this.actor.deleteRencontreTMRAtPosition() await this.$deleteRencontreTMRAtPosition()
this.updateTokens(); this.updateTokens();
this.updateValuesDisplay(); this.$updateValuesDisplay();
this.nettoyerRencontre(); this.$nettoyerRencontre();
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -421,41 +433,29 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
checkQuitterTMR() { async $checkQuitterTMR() {
if (this.actor.isDead()) { const reason = this.actor.isDead()
this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !"); ? "est mort"
this.close(); : this.actor.isCumulFatigueCauseSommeil(this.cumulFatigue)
return true; ? "s'écroule de fatigue"
: (this.actor.getReveActuel() == 0)
? "tombe à 0 Points de Rêve"
: undefined
if (reason) {
if (!this.actor.isDead()) {
await this.$refouler()
} }
this.$forceClose(`${this.actor.name} ${reason} et quitte les Terres médianes !`)
if (ReglesOptionnelles.isUsing("appliquer-fatigue") return true
? (this.actor.getFatigueRestante() <= this.cumulFatigue)
: (this.actor.getEnduranceActuelle() <= this.cumulFatigue)
) {
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
this.quitterLesTMRInconscient();
return true;
} }
return false
if (this.actor.getReveActuel() == 0) {
this._tellToGM("Vos Points de Rêve sont à 0 : vous quittez les Terres médianes !");
this.quitterLesTMRInconscient();
return true;
}
return false;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async quitterLesTMRInconscient() { async $maitriserRencontre() {
await this.refouler();
this.close();
}
/* -------------------------------------------- */
async maitriserRencontre() {
console.log("-> maitriser", this.currentRencontre); console.log("-> maitriser", this.currentRencontre);
await this.actor.deleteRencontreTMRAtPosition() await this.$deleteRencontreTMRAtPosition();
this.updateTokens(); this.updateTokens();
let rencontreData = { let rencontreData = {
@ -470,11 +470,21 @@ export class RdDTMRDialog extends Dialog {
tmr: TMRUtility.getTMR(this._getCoordActor()) tmr: TMRUtility.getTMR(this._getCoordActor())
} }
await this._tentativeMaitrise(rencontreData); await this.$tentativeMaitrise(rencontreData);
}
async $deleteRencontreTMRAtPosition() {
const position = this.actor.getDemiReve()
const rencontreIds = this.actor.itemTypes[ITEM_TYPES.rencontre]
.filter(it => it.system.coord == position)
.map(it => it.id)
if (rencontreIds.length > 0) {
await this.actor.deleteEmbeddedDocuments('Item', rencontreIds)
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _tentativeMaitrise(rencData) { async $tentativeMaitrise(rencData) {
this.rencontreState = 'normal'; this.rencontreState = 'normal';
rencData.reve = this.actor.getReveActuel(); rencData.reve = this.actor.getReveActuel();
@ -483,7 +493,7 @@ export class RdDTMRDialog extends Dialog {
RollDataAjustements.calcul(rencData, this.actor); RollDataAjustements.calcul(rencData, this.actor);
rencData.rolled = rencData.presentCite rencData.rolled = rencData.presentCite
? this._rollPresentCite(rencData) ? this.$rollPresentCite(rencData)
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements)); : await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
const result = rencData.rolled.isSuccess const result = rencData.rolled.isSuccess
@ -493,38 +503,41 @@ export class RdDTMRDialog extends Dialog {
await RdDRencontre.appliquer(result.effets, this, rencData); await RdDRencontre.appliquer(result.effets, this, rencData);
rencData.poesie = { extrait: result.poesie, reference: result.reference }; rencData.poesie = { extrait: result.poesie, reference: result.reference };
rencData.message = this.formatMessageRencontre(rencData, result.message); rencData.message = this.$formatMessageRencontre(rencData, result.message);
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor), whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData)
}); });
this.updateValuesDisplay(); this.$updateValuesDisplay();
if (this.checkQuitterTMR()) { if (await this.$checkQuitterTMR()) {
return; return;
} }
if (this.rencontreState == 'persistant') { if (this.rencontreState == 'persistant') {
this._nouvelleTentativeMaitrise(rencData); this.$nouvelleTentativeMaitrise(rencData);
} }
else if (!this.isRencontreDeplacement()) { else if (!this.isRencontreDeplacement()) {
this.nettoyerRencontre(); this.$nettoyerRencontre();
} }
} }
_nouvelleTentativeMaitrise(rencData) { $nouvelleTentativeMaitrise(rencData) {
setTimeout(() => { setTimeout(() => {
// TODO: remplacer par une boucle while(this.currentRencontre) ? /**
* TODO: remplacer par une boucle while(this.currentRencontre) ?
* ajouter un moyen d'attendre la saisie de l'utilisateur (jet obligatoire)?
*/
rencData.nbRounds++; rencData.nbRounds++;
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
} }
this._tentativeMaitrise(rencData); this.$tentativeMaitrise(rencData);
this._deleteTmrMessages(rencData.actor, rencData.nbRounds); this.$deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000); }, 2000);
} }
formatMessageRencontre(rencData, template) { $formatMessageRencontre(rencData, template) {
let messageDuree = '' let messageDuree = ''
if (rencData.nbRounds > 1) { if (rencData.nbRounds > 1) {
if (rencData.rolled.isSuccess) { if (rencData.rolled.isSuccess) {
@ -543,7 +556,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_rollPresentCite(rencData) { $rollPresentCite(rencData) {
let rolled = RdDResolutionTable.computeChances(rencData.reve, 0); let rolled = RdDResolutionTable.computeChances(rencData.reve, 0);
foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score }); foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score });
RdDResolutionTable.succesRequis(rolled); RdDResolutionTable.succesRequis(rolled);
@ -551,7 +564,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_deleteTmrMessages(actor, nbRounds = -1) { $deleteTmrMessages(actor, nbRounds = -1) {
setTimeout(() => { setTimeout(() => {
if (nbRounds < 0) { if (nbRounds < 0) {
ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}"`); ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}"`);
@ -570,7 +583,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_tellToGM(message) { $tellToGM(message) {
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
content: message, content: message,
@ -579,7 +592,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_tellToUserAndGM(message) { $tellToUserAndGM(message) {
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
content: message, content: message,
@ -601,7 +614,7 @@ export class RdDTMRDialog extends Dialog {
if (this.currentRencontre) { if (this.currentRencontre) {
if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)) { if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)) {
// rencontre en attente suite à dérobade // rencontre en attente suite à dérobade
await this.maitriserRencontre(); await this.$maitriserRencontre();
} }
else { else {
const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr); const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr);
@ -648,7 +661,7 @@ export class RdDTMRDialog extends Dialog {
tmr: tmr, tmr: tmr,
presentCite: presentCite presentCite: presentCite
}; };
await this._tentativeMaitrise(rencontreData); await this.$tentativeMaitrise(rencontreData);
this.postRencontre(tmr); this.postRencontre(tmr);
} }
@ -727,7 +740,7 @@ export class RdDTMRDialog extends Dialog {
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData)
}); });
if (rollData.rolled.isEchec) { if (rollData.rolled.isEchec) {
await this.close(); await this.$forceClose(`n'a pas maîtrisé la case ${rollData.tmr.label} et quitte les terres médianes`)
} }
await this.souffleSiEchecTotal(rollData); await this.souffleSiEchecTotal(rollData);
} }
@ -782,7 +795,7 @@ export class RdDTMRDialog extends Dialog {
onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
onConqueteEchec: r => { onConqueteEchec: r => {
this.souffleSiEchecTotal(rollData); this.souffleSiEchecTotal(rollData);
this.close() this.$forceClose(`${this.actor.name} n'a pas maîtrisé la ${tmr.label}, et quitte les TMR.`)
}, },
canClose: false canClose: false
}); });
@ -797,7 +810,7 @@ export class RdDTMRDialog extends Dialog {
onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
onConqueteEchec: r => { onConqueteEchec: r => {
this.souffleSiEchecTotal(rollData); this.souffleSiEchecTotal(rollData);
this.close() this.$forceClose(`${this.actor.name} n'a pas purifié la ${tmr.label}, et quitte les TMR.`)
}, },
canClose: false canClose: false
}); });
@ -811,7 +824,7 @@ export class RdDTMRDialog extends Dialog {
difficulte: -7, difficulte: -7,
action: 'Conquérir', action: 'Conquérir',
onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
onConqueteEchec: r => this.close(), onConqueteEchec: r => this.$forceClose(`${this.actor.name} n'a pas conquis la case ${tmr.label}, et quitte les TMR.`),
canClose: false canClose: false
}); });
} }
@ -922,19 +935,15 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async processSortReserve(sortReserve) { async processSortReserve(sortReserve) {
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]); await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
console.log("declencheSortEnReserve", sortReserve); console.log("declencheSortEnReserve", sortReserve)
const heureCible = RdDTimestamp.definition(sortReserve.system.heurecible).label; const sort = sortReserve.system.sortid ? this.actor.items.get(sortReserve.system.sortid) : undefined
this._tellToUserAndGM(`Vous avez déclenché const message = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-lancement-sortreserve.hbs`,
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"} { sortReserve, sort })
en réserve <strong>${sortReserve.name}</strong> await this.$forceClose(message)
avec ${sortReserve.system.ptreve} points de Rêve
en ${sortReserve.system.coord} (${TMRUtility.getTMRLabel(sortReserve.system.coord)}).
L'heure ciblée est ${heureCible}`);
this.close();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
nettoyerRencontre() { $nettoyerRencontre() {
// Suppression des dessins des zones possibles // Suppression des dessins des zones possibles
this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic)) this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic))
// Nettoyage de la structureet de l'état // Nettoyage de la structureet de l'état
@ -1021,7 +1030,7 @@ export class RdDTMRDialog extends Dialog {
console.log("STATUS :", this.rencontreState, this.currentRencontre); console.log("STATUS :", this.rencontreState, this.currentRencontre);
} }
this.checkQuitterTMR(); await this.$checkQuitterTMR();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -1054,13 +1063,13 @@ export class RdDTMRDialog extends Dialog {
*/ */
this.notifierResonanceSigneDraconique(targetCoord); this.notifierResonanceSigneDraconique(targetCoord);
await this.actor.rollUnSort(targetCoord); await this.actor.rollUnSort(targetCoord);
this.nettoyerRencontre(); this.$nettoyerRencontre();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
externalRefresh() { externalRefresh() {
this.createPixiSprites(); this.createPixiSprites();
this.updateValuesDisplay(); this.$updateValuesDisplay();
this.updateTokens(); this.updateTokens();
console.log("TMR REFRESHED !!!"); console.log("TMR REFRESHED !!!");
} }
@ -1071,7 +1080,7 @@ export class RdDTMRDialog extends Dialog {
return this.forceTMRContinueAction() return this.forceTMRContinueAction()
} }
if (this.currentRencontre != 'normal') { if (this.currentRencontre != 'normal') {
this.nettoyerRencontre(); this.$nettoyerRencontre();
} }
let tmr = TMRUtility.getTMR(targetCoord); let tmr = TMRUtility.getTMR(targetCoord);
// Gestion cases spéciales type Trou noir, etc // Gestion cases spéciales type Trou noir, etc
@ -1083,7 +1092,7 @@ export class RdDTMRDialog extends Dialog {
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
} }
this.updateValuesDisplay(); this.$updateValuesDisplay();
this.actor.notifyRefreshTMR(); this.actor.notifyRefreshTMR();
if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/...

View File

@ -318,6 +318,7 @@ export class RdDUtility {
// gestion des dates et heures // gestion des dates et heures
Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) }); Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) });
Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) }); Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) });
Handlebars.registerHelper('timestamp-definition', (heure) => RdDTimestamp.definition(heure))
Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier()); Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier());
Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree()); Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode()); Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());

View File

@ -196,7 +196,7 @@ system:
derivee: false derivee: false
protection: protection:
type: number type: number
value: 2 value: 10
label: Protection label: Protection
derivee: false derivee: false
compteurs: compteurs:

View File

@ -0,0 +1,13 @@
<img class="chat-icon" src="{{sortReserve.img}}" data-tooltip="{{sortReserve.name}}"/>
<h4>Déclenchement de sort: {{sortReserve.name}}</h4>
<br> Vous avez déclenché {{#if sortReserve.system.echectotal}}<strong>l'échec total</strong>{{else}}le sort{{/if}}
en réserve en {{sortReserve.system.coord}} ({{caseTmr-label sortReserve.system.coord}}).
<br>Ce sort a {{sortReserve.system.ptreve}} points de Rêve
<br>L'heure ciblée est {{#if sortReserve.system.heurecible}}
{{timestamp-imgSigneHeure sortReserve.system.heurecible}} {{sortReserve.system.heurecible}}
{{else}}indéterminée{{/if}}
{{#if sort}}
<div class="poesie-extrait poesie-overflow">
{{{sort.system.description}}}
</div>
{{/if}}

View File

@ -70,7 +70,10 @@
</div> </div>
<div class="flex-group-left"> <div class="flex-group-left">
{{#if attackerRoll}} {{#if (or attackerRoll
(and sourceToken (eq competence.system.categorie 'tir'))
(and sourceToken (eq competence.system.categorie 'lancer'))
)}}
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.hbs"}} {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.hbs"}}
{{else}} {{else}}
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.hbs"}} {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.hbs"}}