Compare commits

...

22 Commits

Author SHA1 Message Date
cc4cbbc771 Merge pull request 'cherry-pick v12.0.50 vers v13' (#761) from VincentVk/foundryvtt-reve-de-dragon:v13 into v13
Reviewed-on: #761
2025-05-04 19:16:52 +02:00
0850789ed7 Fix fatigue à la descente des TMR
La modification d'un activeEffect déclenche un render, qui
utilise les valeurs courante de l'actor.

Du coup, si l'update de l'actor est fait après:
- le render en cours utilise les anciennes valeurs
- comme un render est en cours, le nouveau render est ignoré

En faisant les changements d'active effect après ceux de l'actor,
l'affichage se fait correctement.,
2025-05-04 18:37:03 +02:00
7a6ccac7fa Merge pull request 'Fix: sommeil avec double rêve' (#758) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #758
2025-05-04 18:36:54 +02:00
ed64d823ac Merge pull request '12.0.49 - La deuxième lame d'Astrobazzarh' (#757) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #757
2025-05-04 18:36:36 +02:00
3162264afa Merge pull request '12.0.48 - La chèvre d'Astrobazzarh' (#756) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #756
2025-05-04 18:36:28 +02:00
e53eda5b42 Correction sur les mise à jour en cascade + correction sur le force rendering après un changement de competence 2025-05-04 18:36:19 +02:00
47a7564a1c Correction sur les mise à jour en cascade + correction sur le force rendering après un changement de competence 2025-05-04 18:36:08 +02:00
f7a6fee51d 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-05-04 18:35:59 +02:00
0b3f08ef29 correction des raffraîchissement lors du sommeil
On peut de nouveau dormir plusieurs heures

# Conflicts:
#	changelog.md
2025-05-04 18:35:43 +02:00
8df9c8ddf5 Gestion armes naturelles sur defense 2025-05-04 18:35:10 +02:00
4cbe652a91 Renommage révéler/masquer le demi-rêve
# Conflicts:
#	changelog.md
2025-05-04 18:34:58 +02:00
3eb1179c40 Fix: difficulté des médiations
La difficulté des méditations n'augmente plus en cas de réussite
et d'échec normal

# Conflicts:
#	changelog.md
2025-05-04 18:33:35 +02:00
cf185844af Correction sur heures de repos
# Conflicts:
#	module/actor.js
2025-05-04 18:32:21 +02:00
250b936fae Fix erreurs sorts variables
- correction de la sélection de la voie de draconique pour
  sort à voie variable
- en cas de sort avec un coût en rêve numérique, ce n'est pas variable
2025-05-04 18:31:05 +02:00
cd8268f569 Fix possessions 2025-05-04 18:30:49 +02:00
c04e0cec78 Fix récupération sommeil
Les différents updates pouvaient ne pas être visibles lors du sommeil

En forçant un render 20ms après la fin des actions qui impliquent un
sommeil, les mises à jour sont correctes
2025-05-04 18:30:35 +02:00
1d5fe1af71 Corrections automatisations combat
Visiblement des changements sur les callbacks n'avaient pas
été finalisés
2025-05-04 18:27:56 +02:00
e96a627c37 Fix item names 2025-03-04 21:31:51 +01:00
06c3d2f80a Add command to run debug server 2025-02-11 21:29:58 +01:00
d07f5a41e7 Version 13.0.0 on branch 2025-02-10 00:32:52 +01:00
856d038dc9 Start experiment style for monnaie sheet 2025-02-09 22:51:33 +01:00
791593ad38 Fix: jet de caractéristique/difficulté
Les jets avec difficulté ne fonctionnaient plus à cause des armes
 à 1 main / à 2 mains
2025-02-09 22:51:33 +01:00
31 changed files with 3067 additions and 2922 deletions

View File

@ -1,4 +1,52 @@
# 12.0
## 12.0.50 - Le sommeil d'Astrobazzarh
- Le don de double rêve n'interrompt plus le sommeil toutes les heures
- la perte de fatigue à la descente des TMR est visible immédiatement
## 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
- Renommage du Bouton pour révéler/masquer le demi-rêve
## 12.0.44 - Les errements d'Astrobazzarh, suite
- on peut de nouveau dormir et se réveiller reposé
- les possessions utilisent maintenant correctement le rêve actuel
- les sorts variables ne causent plus de soucis de voie pour le lancement de sorts
- les acteurs ayant un sort avec un coût de rêve entier ne sont plus considérés
comme pouvant avoir un rêve variable
## 12.0.42 - Les errements d'Astrobazzarh
- Correction de différentes automatisations de combat incorrectes
- Correction des jets `@roll[vue/-2]` qui tentaient de chercher une compétence -2 (à cause des armes à 1/2 mains)
## 12.0.41 - La loupe d'Astrobazzarh
- On peut de nouveau effectuer des tirages cachés
- Le stress transformé est bien diminué lorsqu'on met le stress dans une compétence

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +1,13 @@
:root {
/* =================== 1. ACTOR SHEET FONT STYLES =========== */
--window-header-title-font-family: CaslonAntique;
--window-header-title-font-size: 1.6rem;
--window-header-title-font-weight: normal;
--window-header-title-color: #f5f5f5;
--major-button-font-family: CaslonAntique;
--major-button-font-size: 1.4rem;
--major-button-font-weight: normal;
--major-button-color: #dadada;
--tab-header-font-family: CaslonAntique;
--tab-header-font-size: 1.2rem;
--tab-header-font-weight: 700;
--tab-header-color: #403f3e;
--tab-header-color-active: #4a0404;
--actor-input-font-family: CaslonAntique;
--actor-input-font-size: 1.2rem;
--actor-input-font-weight: 500;
--actor-input-color: black;
--actor-label-font-family: CaslonAntique;
--actor-label-font-size: 1.2rem;
--actor-label-font-weight: 700;
--actor-label-color: #464331c4;
/* =================== 2. DEBUGGING HIGHLIGHTERS ============ */
--debug-background-color-red: #ff000054;
--debug-background-color-blue: #1d00ff54;
--debug-background-color-green: #54ff0054;
// --debug-background-color-red: #ff000054;
// --debug-background-color-blue: #1d00ff54;
// --debug-background-color-green: #54ff0054;
--debug-box-shadow-red: inset 0 0 2px red;
--debug-box-shadow-blue: inset 0 0 2px blue;
--debug-box-shadow-green: inset 0 0 2px green;
// --debug-box-shadow-red: inset 0 0 2px red;
// --debug-box-shadow-blue: inset 0 0 2px blue;
// --debug-box-shadow-green: inset 0 0 2px green;
/* =================== 3. some constants ============ */
--color-controls:rgba(0, 0, 0, 0.9);

View File

@ -28,3 +28,57 @@
font-weight: normal;
font-style: normal;
}
:root {
/* =================== 1. ACTOR SHEET FONT STYLES =========== */
--window-header-title-font-family: CaslonAntique;
--window-header-title-font-size: 1.6rem;
--window-header-title-font-weight: normal;
--window-header-title-color: #f5f5f5;
--major-button-font-family: CaslonAntique;
--major-button-font-size: 1.4rem;
--major-button-font-weight: normal;
--major-button-color: #dadada;
--tab-header-font-family: CaslonAntique;
--tab-header-font-size: 1.2rem;
--tab-header-font-weight: 700;
--tab-header-color: #403f3e;
--tab-header-color-active: #4a0404;
--actor-input-font-family: CaslonAntique;
--actor-input-font-size: 1.2rem;
--actor-input-font-weight: 500;
--actor-input-color: black;
--actor-label-font-family: CaslonAntique;
--actor-label-font-size: 1.2rem;
--actor-label-font-weight: 700;
--actor-label-color: #464331c4;
}
/* Global styles & Font */
.window-app {
font-family: CaslonAntique;
text-align: justify;
font-size: 1rem;
letter-spacing: 1px;
}
/* Fonts */
.sheet header.sheet-header h1 input,
.window-app .window-header,
#actors .directory-list,
#navigation #scene-list .scene.nav-item {
font-family: "GoudyAcc"
}
/* For title, sidebar character and scene */
.sheet nav.sheet-tabs,
.window-app input,
.sheet header.sheet-header .header-compteurs,
.sheet header.sheet-header .flex-group-center.flex-fatigue,
select, button, .item-checkbox, #sidebar, #players, #navigation #nav-toggle {
font-family: "CaslonAntique"; /* For sheet parts; For nav and title */
}

File diff suppressed because it is too large Load Diff

10
less/item/monnaie.less Normal file
View File

@ -0,0 +1,10 @@
.application.sheet.fvtt-rdd {
.sheet-common();
section.window-content{
padding: 0rem;
section header.sheet-header {
.sheet-header();
}
}
}

32
less/sheets.less Normal file
View File

@ -0,0 +1,32 @@
.sheet-common() {
.window-content{
font-family: CaslonAntique;
text-align: justify;
font-size: 1rem;
letter-spacing: 1px;
font-size: calc(var(--font-size-standard) * 1);
color: var(--color-dark-1);
background: var(--background-image-base) no-repeat;
background-size: 100% 100%;
}
}
.sheet-header() {
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
color: rgba(255, 255, 255, 1);
:is(
input[type="text"],
input[type="number"],
input[type="password"],
input[type="datetime-local"],
input[type="date"],
input[type="time"]) {
color: rgba(255, 255, 255, 0.75);
background: rgba(255, 255, 255, 0.1);
border: 0 none;
margin-bottom: 0.2rem;
}
}

View File

@ -243,7 +243,7 @@ export class RdDActor extends RdDBaseActorSang {
}
await this.resetInfoSommeil()
ChatMessage.create(message);
this.sheet.render(true);
setTimeout(() => this.sheet.render(), 20)
}
async _recuperationSante(message) {
@ -279,30 +279,34 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async dormirChateauDormant() {
if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil.nouveaujour) {
const message = {
whisper: ChatUtility.getOwners(this),
content: ""
};
await this._recuperationSante(message)
await this._recupereMoralChateauDormant(message)
await this._recupereChance()
await this.transformerStress()
await this.retourSeuilDeReve(message)
await this.setBonusPotionSoin(0)
await this.retourSust(message)
await this.$perteReveEnchantementsChateauDormants()
await this.$suppressionLancementsSort()
await RdDCoeur.applyCoeurChateauDormant(this, message)
if (message.content != "") {
message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`;
ChatMessage.create(message);
}
await this.resetInfoSommeil();
this.sheet.render(true);
await this.$dormirChateauDormant();
setTimeout(() => this.sheet.render(), 20)
}
}
async $dormirChateauDormant() {
const message = {
whisper: ChatUtility.getOwners(this),
content: ""
};
await this._recuperationSante(message);
await this._recupereMoralChateauDormant(message);
await this._recupereChance();
await this.transformerStress();
await this.retourSeuilDeReve(message);
await this.setBonusPotionSoin(0);
await this.retourSust(message);
await this.$perteReveEnchantementsChateauDormants();
await this.$suppressionLancementsSort();
await RdDCoeur.applyCoeurChateauDormant(this, message);
if (message.content != "") {
message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`;
ChatMessage.create(message);
}
await this.resetInfoSommeil();
}
async resetInfoSommeil() {
await this.update({
'system.sommeil': {
@ -442,10 +446,9 @@ export class RdDActor extends RdDBaseActorSang {
message.content += 'Vous ne trouvez pas le sommeil';
}
else {
let jetsReve = [];
let dormi = await this.dormirDesHeures(jetsReve, message, heures, options);
if (jetsReve.length > 0) {
message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '0 (réveil)' : it).reduce(Misc.joining("+"))} Points de rêve. `;
let dormi = await this.$dormirDesHeures(message, heures, options);
if (dormi.jetsReve.length > 0) {
message.content += `Vous récupérez ${dormi.jetsReve.map(it => it < 0 ? '0 (réveil)' : it).reduce(Misc.joining("+"))} Points de rêve. `;
}
if (dormi.etat == 'eveil') {
await this.reveilReveDeDragon(message, dormi.heures);
@ -458,11 +461,9 @@ export class RdDActor extends RdDBaseActorSang {
ChatMessage.create(message);
}
if (options.chateauDormant) {
await this.dormirChateauDormant();
}
else {
this.sheet.render(true);
await this.$dormirChateauDormant();
}
setTimeout(() => this.sheet.render(), 20)
}
async reveilReveDeDragon(message, heures) {
@ -472,18 +473,18 @@ export class RdDActor extends RdDBaseActorSang {
}
}
async dormirDesHeures(jetsReve, message, heures, options) {
const dormi = { heures: 0, etat: 'dort' };
async $dormirDesHeures(message, heures, options) {
const dormi = { heures: 0, etat: 'dort', jetsReve: [] };
for (; dormi.heures < heures && dormi.etat == 'dort'; dormi.heures++) {
await this._recupererEthylisme(message);
await this.$recupererEthylisme(message);
if (options.grisReve) {
await this.recupererFatigue(message);
await this.$recupererFatigue(message);
}
else if (!this.system.sommeil?.insomnie) {
await this.recupererFatigue(message);
dormi.etat = await this.jetRecuperationReve(jetsReve, message);
await this.$recupererFatigue(message);
await this.$jetRecuperationReve(dormi, message);
if (dormi.etat == 'dort' && EffetsDraconiques.isDonDoubleReve(this)) {
dormi.etat = await this.jetRecuperationReve(jetsReve, message);
await this.$jetRecuperationReve(dormi, message);
}
}
}
@ -491,35 +492,36 @@ export class RdDActor extends RdDBaseActorSang {
}
/* -------------------------------------------- */
async jetRecuperationReve(jetsReve, message) {
async $jetRecuperationReve(dormi, message) {
if (this.getReveActuel() < this.system.reve.seuil.value) {
let reve = await RdDDice.rollTotal("1dr");
const reve = await RdDDice.rollTotal("1dr")
if (reve >= 7) {
// Rêve de Dragon !
message.content += `Vous faites un <strong>Rêve de Dragon</strong> de ${reve} Points de rêve qui vous réveille! `;
await this.combattreReveDeDragon(reve);
jetsReve.push(-1);
return 'eveil';
dormi.jetsReve.push(-1);
dormi.etat = 'eveil'
return
}
else {
if (!ReglesOptionnelles.isUsing("recuperation-reve")) {
ChatMessage.create({
whisper: ChatUtility.getOwners(this),
content: `Pas de récupération de rêve (${reve} points ignorés)`
});
jetsReve.push(0);
})
dormi.jetsReve.push(0)
}
else {
await this.reveActuelIncDec(reve);
jetsReve.push(reve);
await this.reveActuelIncDec(reve)
dormi.jetsReve.push(reve)
}
}
}
return 'dort';
dormi.etat = 'dort'
}
/* -------------------------------------------- */
async _recupererEthylisme(message) {
async $recupererEthylisme(message) {
if (!ReglesOptionnelles.isUsing("recuperation-ethylisme")) { return; }
let value = Math.min(Number.parseInt(this.system.compteurs.ethylisme.value) + 1, 1);
if (value <= 0) {
@ -541,7 +543,6 @@ export class RdDActor extends RdDBaseActorSang {
max = Math.floor(max / 2);
}
const manquant = max - this.system.sante.endurance.value;
if (manquant > 0) {
await this.santeIncDec("endurance", manquant);
message.content += `Vous récuperez ${manquant} points d'endurance. `;
@ -549,15 +550,15 @@ export class RdDActor extends RdDBaseActorSang {
}
/* -------------------------------------------- */
async recupererFatigue(message) {
async $recupererFatigue(message) {
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
let fatigue = this.system.sante.fatigue.value;
const fatigueMin = this.getFatigueMin();
let fatigue = this.system.sante.fatigue.value
const fatigueMin = this.getFatigueMin()
if (fatigue <= fatigueMin) {
return;
return
}
fatigue = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue));
await this.update({ "system.sante.fatigue.value": fatigue });
fatigue = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue))
await this.update({ 'system.sante.fatigue.value': fatigue });
if (fatigue == 0) {
message.content += "Vous êtes complêtement reposé. ";
}
@ -667,19 +668,23 @@ export class RdDActor extends RdDBaseActorSang {
if (!RdDItemRace.checkRacialMax(this, caracName, to)) {
return
}
let updates = {};
if (caracName == LIST_CARAC_PERSONNAGE.reve.code) {
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 (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);
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);
}
@ -783,7 +788,7 @@ export class RdDActor extends RdDBaseActorSang {
const toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie, competence.getCategories());
this.notifyCompetencesTronc(competence, toNiveau);
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);
}
}
@ -1047,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() {
return this.itemTypes[ITEM_TYPES.rencontre].find(this.filterRencontreTMRDemiReve())
}
filterRencontreTMRDemiReve() {
const position = this.getDemiReve()
return it => it.system.coord == position
return this.itemTypes[ITEM_TYPES.rencontre].find(it => it.system.coord == position)
}
/* -------------------------------------------- */
@ -1770,7 +1765,7 @@ export class RdDActor extends RdDBaseActorSang {
if (reveActuel == 0) { // 0 points de reve
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();
}
}
@ -2116,7 +2111,6 @@ export class RdDActor extends RdDBaseActorSang {
label: "Jet de méditation",
callbacks: [
this.createCallbackExperience(),
{ condition: r => r.rolled.isEPart, action: r => this._meditationEPart(r) },
{ action: r => this._meditationResult(r) }
]
});
@ -2125,21 +2119,16 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async _meditationResult(meditationRoll) {
this.santeIncDec("fatigue", 2);
if (meditationRoll.rolled.isSuccess) {
await this.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditationRoll.meditation, meditationRoll.rolled)]);
}
if (meditationRoll.rolled.isEPart){
await this.updateEmbeddedDocuments('Item', [{ _id: meditationRoll.meditation._id, 'system.malus': meditationRoll.meditation.system.malus - 1 }]);
}
await this.santeIncDec("fatigue", 2);
await RdDRollResult.displayRollData(meditationRoll, this.name, 'chat-resultat-meditation.hbs');
}
/* -------------------------------------------- */
_meditationEPart(meditationRoll) {
this.updateEmbeddedDocuments('Item', [{ _id: meditationRoll.meditation._id, 'system.malus': meditationRoll.meditation.system.malus - 1 }]);
}
/* -------------------------------------------- */
_getSignesDraconiques(coord) {
const type = TMRUtility.getTMRType(coord);
@ -2643,12 +2632,13 @@ export class RdDActor extends RdDBaseActorSang {
}
/* -------------------------------------------- */
async incDecItemUse(itemId, inc = 1) {
const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse');
let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {};
itemUse[itemId] = (itemUse[itemId] ?? 0) + inc;
await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse);
console.log("ITEM USE INC", inc, itemUse);
async incDecItemUse(itemId, shouldIncrease = true) {
if (shouldIncrease) {
const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse');
let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {};
itemUse[itemId] = (itemUse[itemId] ?? 0) + 1;
await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse);
}
}
/* -------------------------------------------- */

View File

@ -277,14 +277,9 @@ export class RdDBaseActorReve extends RdDBaseActor {
return dialog
}
createEmptyCallback() {
return {
condition: r => false,
action: r => { }
};
}
createCallbackExperience() { return this.createEmptyCallback(); }
createCallbackAppelAuMoral() { return this.createEmptyCallback(); }
createCallbackExperience() { return { action: r => { } } }
createCallbackAppelAuMoral() { return { action: r => { } } }
async _onCloseRollDialog(html) { }
async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) {

View File

@ -39,7 +39,12 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
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 }
malusFatigue() {

View File

@ -747,7 +747,7 @@ export class RdDBaseActor extends Actor {
async jetDeMoral() { this.actionImpossible("jet de moral") }
async resetItemUse() { }
async incDecItemUse(itemId, inc = 1) { }
async incDecItemUse(itemId, shouldIncrease = true) { }
getItemUse(itemId) { return 0; }
async finDeRound(options = { terminer: false }) { }

View File

@ -5,7 +5,7 @@ import { RdDUtility } from "../../rdd-utility.js";
import { RdDAlchimie } from "../../rdd-alchimie.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 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')

View File

@ -5,7 +5,7 @@ import { RdDUtility } from "../../rdd-utility.js";
import { TextRollManager } from "./text-roll-formatter.js";
const REGECP_CARAC = "(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)"
const REGEXP_COMP = "(\\/(?<competence>[A-Za-z0-9À-ÖØ-öø-ÿ -]+))?"
const REGEXP_COMP = "(\\/(?<competence>[A-Za-zÀ-ÖØ-öø-ÿ ]+([1-2]?[A-Za-zÀ-ÖØ-öø-ÿ ]+)?))?"
const REGEXP_DIFF = "(/(?<diff>[\\+\\-]?\\d+(d\\d+)?))?"
const REGEXP_ROLL_CARAC_COMP = REGECP_CARAC + REGEXP_COMP + REGEXP_DIFF
const XREGEXP_ROLL_CARAC_COMP = XRegExp("@roll\\[" + REGEXP_ROLL_CARAC_COMP + "\\]", 'giu')

View File

@ -1,2 +1,2 @@
export { default as RdDModelMonnaie } from "./monnaie.mjs"
export { default as RdDModelMunition } from "./munition.mjs"
export { default as RdDItemMonnaie } from "./monnaie.mjs"
export { default as RdDItemMunition } from "./munition.mjs"

View File

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

View File

@ -56,6 +56,10 @@ export class RdDItemSort extends Item {
return voies.map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie))
}
static getBestDraconicSort(competencesDraconic, sort) {
return RdDItemSort.getDraconicsSort(competencesDraconic, sort).sort(Misc.descending(it => it.system.niveau)).find(it=>true)
}
static getOrdreCode(code) {
return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?')
}
@ -92,7 +96,7 @@ export class RdDItemSort extends Item {
/* -------------------------------------------- */
static isCoutVariable(sort) {
return sort && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0);
return sort && !Number.isInteger(sort.system.ptreve) && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0);
}
/* -------------------------------------------- */

View File

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

View File

@ -743,23 +743,13 @@ export class RdDCombat {
this.attacker.createCallbackExperience(),
this.attacker.createCallbackAppelAuMoral(),
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
{ action: r => this._increaseItemUse(r, arme) },
{ action: r => this._onAttaqueNormale(r) },
{ action: r => this._onAttaqueParticuliere(r) },
{ action: r => this._onAttaqueEchec(r) },
{ action: r => this._onAttaqueEchecTotal(r) },
{ action: async r => await this.attacker.incDecItemUse(arme._id, arme && !RdDCombat.isParticuliere(r)) },
{ action: r => this._onAttaque(r) },
]
});
dialog.render(true);
}
_increaseItemUse(rollData, arme) {
if (!arme || RdDCombat.isParticuliere(rollData)) {
return
}
this.attacker.incDecItemUse(arme._id)
}
/* -------------------------------------------- */
_prepareAttaque(competence, arme) {
let rollData = {
@ -790,11 +780,23 @@ export class RdDCombat {
return rollData;
}
async _onAttaque(attackerRoll) {
if (RdDCombat.isParticuliere(attackerRoll)) {
return await this._onAttaqueParticuliere(attackerRoll)
}
if (RdDCombat.isReussite(attackerRoll)) {
return await this._onAttaqueNormale(attackerRoll)
}
// if (RdDCombat.isParticuliere(attackerRoll) && attackerRoll.particuliere == undefined) {
// return
// }
if (RdDCombat.isEchecTotal(attackerRoll)) {
return await this._onAttaqueEchecTotal(attackerRoll)
}
return await this._onAttaqueEchec(attackerRoll)
}
/* -------------------------------------------- */
async _onAttaqueParticuliere(rollData) {
if (!RdDCombat.isParticuliere(rollData)) {
return
}
const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0;
// force toujours, sauf empoignade
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
@ -832,12 +834,6 @@ export class RdDCombat {
/* -------------------------------------------- */
async _onAttaqueNormale(attackerRoll) {
if (!RdDCombat.isReussite(attackerRoll)) {
return
}
if (RdDCombat.isParticuliere(attackerRoll) && attackerRoll.particuliere == undefined) {
return
}
console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll);
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite());
@ -954,9 +950,6 @@ export class RdDCombat {
/* -------------------------------------------- */
async _onAttaqueEchecTotal(attackerRoll) {
if (!RdDCombat.isEchecTotal(attackerRoll)) {
return
}
const choixEchecTotal = await ChatMessage.create({
whisper: ChatUtility.getOwners(this.attacker),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.hbs', {
@ -983,22 +976,16 @@ export class RdDCombat {
}
/* -------------------------------------------- */
async _onAttaqueEchec(rollData) {
if (!RdDCombat.isEchec(rollData)) {
return
}
console.log("RdDCombat.onAttaqueEchec >>>", rollData);
await RdDRollResult.displayRollData(rollData, this.attacker, 'chat-resultat-attaque.hbs');
async _onAttaqueEchec(attackerRoll) {
console.log("RdDCombat.onAttaqueEchec >>>", attackerRoll);
await RdDRollResult.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.hbs');
}
/* -------------------------------------------- */
async choixParticuliere(rollData, choix) {
console.log("RdDCombat.choixParticuliere >>>", rollData, choix);
if (choix != "rapidite") {
this.attacker.incDecItemUse(rollData.arme.id);
}
await this.attacker.incDecItemUse(rollData.arme.id, choix != "rapidite")
this.removeChatMessageActionsPasseArme(rollData.passeArme);
rollData.particuliere = choix;
@ -1026,10 +1013,8 @@ export class RdDCombat {
this.defender.createCallbackExperience(),
this.defender.createCallbackAppelAuMoral(),
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(armeParadeId) },
{ condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) },
{ condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) },
{ condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) },
{ action: async r => await this.defender.incDecItemUse(armeParadeId, !RdDCombat.isParticuliere(r)) },
{ action: r => this._onParade(r) },
]
});
dialog.render(true);
@ -1060,8 +1045,20 @@ export class RdDCombat {
return defenderRoll;
}
async _onParade(defenderRoll) {
if (RdDCombat.isReussite(defenderRoll)) {
await this._onParadeNormale(defenderRoll)
if (RdDCombat.isParticuliere(defenderRoll)) {
await this._onParadeParticuliere(defenderRoll)
}
return
}
await this._onParadeEchec(defenderRoll)
}
/* -------------------------------------------- */
_onParadeParticuliere(defenderRoll) {
async _onParadeParticuliere(defenderRoll) {
console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll);
if (!defenderRoll.attackerRoll.isPart) {
// TODO: attaquant doit jouer résistance et peut être désarmé p132
@ -1070,7 +1067,6 @@ export class RdDCombat {
this.defender)
}
}
/* -------------------------------------------- */
async _onParadeNormale(defenderRoll) {
console.log("RdDCombat._onParadeNormale >>>", defenderRoll);
@ -1109,11 +1105,9 @@ export class RdDCombat {
callbacks: [
this.defender.createCallbackExperience(),
this.defender.createCallbackAppelAuMoral(),
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(esquive._id) },
{ action: async r => await this.defender.incDecItemUse(esquive._id, !RdDCombat.isParticuliere(r)) },
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
{ condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) },
{ condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) },
{ condition: RdDCombat.isEchec, action: r => this._onEsquiveEchec(r) },
{ action: r => this._onEsquive(r) },
]
});
dialog.render(true);
@ -1141,9 +1135,19 @@ export class RdDCombat {
return rollData;
}
async _onEsquive(defenderRoll) {
if (RdDCombat.isReussite(defenderRoll)) {
await this._onEsquiveNormale(defenderRoll)
if (RdDCombat.isParticuliere(defenderRoll)) {
await this._onEsquiveParticuliere(defenderRoll)
}
return
}
return await this._onEsquiveEchec(defenderRoll)
}
/* -------------------------------------------- */
_onEsquiveParticuliere(rollData) {
console.log("RdDCombat._onEsquiveParticuliere >>>", rollData);
async _onEsquiveParticuliere(defenderRoll) {
console.log("RdDCombat._onEsquiveParticuliere >>>", defenderRoll);
ChatUtility.createChatWithRollMode(
{ content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" },
this.defender);

View File

@ -104,8 +104,8 @@ export class SystemReveDeDragon {
this.RdDHotbar = RdDHotbar
this.RdDStatBlockParser = RdDStatBlockParser
this.itemClasses = {
monnaie: items.RdDModelMonnaie,
munition: items.RdDModelMunition,
monnaie: items.RdDItemMonnaie,
munition: items.RdDItemMunition,
armure: RdDItemArmure,
blessure: RdDItemBlessure,
gemme: RdDItemGemme,

View File

@ -104,8 +104,8 @@ export class RdDPossession {
rollData.selectedCarac = carac.reve
}
else {
rollData.selectedCarac = rollingActor.system.carac.reve
rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } }
rollData.selectedCarac = rollData.forceCarac['reve-actuel']
rollData.competence.system.defaut_carac = 'reve-actuel'
}
}

View File

@ -1,4 +1,3 @@
import { ChatUtility } from "./chat-utility.js";
import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";

View File

@ -279,7 +279,7 @@ export class RdDRoll extends Dialog {
async setSelectedSort(sort) {
this.rollData.selectedSort = sort; // Update the selectedCarac
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.system.draconic);
this.rollData.competence = RdDItemSort.getBestDraconicSort(this.rollData.draconicList, sort)
this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord);
this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7);
RdDItemSort.setCoutReveReel(sort);

View File

@ -15,7 +15,6 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { RdDDice } from "./rdd-dice.js";
import { STATUSES } from "./settings/status-effects.js";
import { RdDRencontre } from "./item/rencontre.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { ITEM_TYPES } from "./constants.js";
import { Misc } from "./misc.js";
@ -83,7 +82,7 @@ export class RdDTMRDialog extends Dialog {
this.subdialog = undefined
this.displaySize = undefined
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 = [];
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;
// Le reste...
this.updateValuesDisplay();
this.$updateValuesDisplay();
}
lancerUnSort() {
@ -190,7 +189,7 @@ export class RdDTMRDialog extends Dialog {
forceTMRContinueAction() {
ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR');
this.bringSubDialogToTop();
return;
return false
}
setTMRPendingAction(dialog) {
@ -297,7 +296,7 @@ export class RdDTMRDialog extends Dialog {
const coordOrig = this._getCoordActor();
const coordTarget = TMRUtility.deplacement(coordOrig, move);
await this._deplacerDemiReve(coordTarget, 'normal');
this.checkQuitterTMR();
await this.$checkQuitterTMR();
}
calculCoutMonteeTMR() {
@ -305,7 +304,7 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
async updateValuesDisplay() {
async $updateValuesDisplay() {
if (this.viewOnly || !this.rendered) {
return;
}
@ -336,22 +335,31 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async close() {
await this.$forceClose(this.actor.name + " a quitté les terres médianes")
}
async $forceClose(message) {
if (this.subdialog) {
return this.forceTMRContinueAction()
this.forceTMRContinueAction()
return false
}
this.descenteTMR = true;
if (this.actor.tmrApp) {
this.actor.tmrApp = undefined; // Cleanup reference
this.actor.tmrApp = undefined // Cleanup reference
const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue")
await this.actor.santeIncDec(
appliquerFatigue ? "fatigue" : "endurance",
(appliquerFatigue ? 1 : -1) * this.cumulFatigue)
if (!this.viewOnly) {
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"),
this.cumulFatigue)
}
await super.close();
this.pixiTMR.close()
this.pixiTMR.close();
this.pixiTMR = undefined
await super.close();
return true
}
/* -------------------------------------------- */
@ -363,48 +371,53 @@ export class RdDTMRDialog extends Dialog {
}
switch (action) {
case 'derober':
await this.derober();
this.restoreTMRAfterAction();
return;
await this.$derober()
this.restoreTMRAfterAction()
return
case 'refouler':
await this.refouler();
break;
await this.$refouler()
break
case 'maitriser':
await this.maitriserRencontre();
break;
await this.$maitriserRencontre()
break
case 'ignorer':
await this.ignorerRencontre();
break;
await this.$ignorerRencontre()
break
}
await this.postRencontre(tmr);
this.restoreTMRAfterAction();
}
async derober() {
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 $derober() {
if (this.currentRencontre) {
console.log("-> derober", this.currentRencontre);
await this.actor.addTMRRencontre(this.currentRencontre);
this.$forceClose(`${this.actor.name} s'est dérobé face à la rencontre ${this.currentRencontre.name}, et quitte les TMR.`)
}
}
/* -------------------------------------------- */
async refouler() {
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.deleteRencontreTMRAtPosition()
this.updateTokens();
this.updateValuesDisplay();
this.nettoyerRencontre();
async $refouler() {
if (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.$deleteRencontreTMRAtPosition()
this.updateTokens();
this.$updateValuesDisplay();
this.$nettoyerRencontre();
}
}
/* -------------------------------------------- */
async ignorerRencontre() {
console.log("-> ignorer", this.currentRencontre);
this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens();
this.updateValuesDisplay();
this.nettoyerRencontre();
async $ignorerRencontre() {
if (this.currentRencontre) {
console.log("-> ignorer", this.currentRencontre);
this.$tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
await this.$deleteRencontreTMRAtPosition()
this.updateTokens();
this.$updateValuesDisplay();
this.$nettoyerRencontre();
}
}
/* -------------------------------------------- */
@ -421,41 +434,29 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
checkQuitterTMR() {
if (this.actor.isDead()) {
this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !");
this.close();
return true;
async $checkQuitterTMR() {
const reason = this.actor.isDead()
? "est mort"
: this.actor.isCumulFatigueCauseSommeil(this.cumulFatigue)
? "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 !`)
return true
}
if (ReglesOptionnelles.isUsing("appliquer-fatigue")
? (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;
}
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;
return false
}
/* -------------------------------------------- */
async quitterLesTMRInconscient() {
await this.refouler();
this.close();
}
/* -------------------------------------------- */
async maitriserRencontre() {
async $maitriserRencontre() {
console.log("-> maitriser", this.currentRencontre);
await this.actor.deleteRencontreTMRAtPosition()
await this.$deleteRencontreTMRAtPosition();
this.updateTokens();
let rencontreData = {
@ -470,11 +471,21 @@ export class RdDTMRDialog extends Dialog {
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';
rencData.reve = this.actor.getReveActuel();
@ -483,7 +494,7 @@ export class RdDTMRDialog extends Dialog {
RollDataAjustements.calcul(rencData, this.actor);
rencData.rolled = rencData.presentCite
? this._rollPresentCite(rencData)
? this.$rollPresentCite(rencData)
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
const result = rencData.rolled.isSuccess
@ -493,38 +504,41 @@ export class RdDTMRDialog extends Dialog {
await RdDRencontre.appliquer(result.effets, this, rencData);
rencData.poesie = { extrait: result.poesie, reference: result.reference };
rencData.message = this.formatMessageRencontre(rencData, result.message);
rencData.message = this.$formatMessageRencontre(rencData, result.message);
ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData)
});
this.updateValuesDisplay();
if (this.checkQuitterTMR()) {
this.$updateValuesDisplay();
if (await this.$checkQuitterTMR()) {
return;
}
if (this.rencontreState == 'persistant') {
this._nouvelleTentativeMaitrise(rencData);
this.$nouvelleTentativeMaitrise(rencData);
}
else if (!this.isRencontreDeplacement()) {
this.nettoyerRencontre();
this.$nettoyerRencontre();
}
}
_nouvelleTentativeMaitrise(rencData) {
$nouvelleTentativeMaitrise(rencData) {
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++;
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase;
}
this._tentativeMaitrise(rencData);
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
this.$tentativeMaitrise(rencData);
this.$deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000);
}
formatMessageRencontre(rencData, template) {
$formatMessageRencontre(rencData, template) {
let messageDuree = ''
if (rencData.nbRounds > 1) {
if (rencData.rolled.isSuccess) {
@ -543,7 +557,7 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
_rollPresentCite(rencData) {
$rollPresentCite(rencData) {
let rolled = RdDResolutionTable.computeChances(rencData.reve, 0);
foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score });
RdDResolutionTable.succesRequis(rolled);
@ -551,7 +565,7 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
_deleteTmrMessages(actor, nbRounds = -1) {
$deleteTmrMessages(actor, nbRounds = -1) {
setTimeout(() => {
if (nbRounds < 0) {
ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}"`);
@ -570,7 +584,7 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
_tellToGM(message) {
$tellToGM(message) {
ChatMessage.create({
user: game.user.id,
content: message,
@ -579,7 +593,7 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
_tellToUserAndGM(message) {
$tellToUserAndGM(message) {
ChatMessage.create({
user: game.user.id,
content: message,
@ -601,7 +615,7 @@ export class RdDTMRDialog extends Dialog {
if (this.currentRencontre) {
if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)) {
// rencontre en attente suite à dérobade
await this.maitriserRencontre();
await this.$maitriserRencontre();
}
else {
const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr);
@ -648,7 +662,7 @@ export class RdDTMRDialog extends Dialog {
tmr: tmr,
presentCite: presentCite
};
await this._tentativeMaitrise(rencontreData);
await this.$tentativeMaitrise(rencontreData);
this.postRencontre(tmr);
}
@ -727,7 +741,7 @@ export class RdDTMRDialog extends Dialog {
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData)
});
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);
}
@ -782,7 +796,7 @@ export class RdDTMRDialog extends Dialog {
onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
onConqueteEchec: r => {
this.souffleSiEchecTotal(rollData);
this.close()
this.$forceClose(`${this.actor.name} n'a pas maîtrisé la ${tmr.label}, et quitte les TMR.`)
},
canClose: false
});
@ -797,7 +811,7 @@ export class RdDTMRDialog extends Dialog {
onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
onConqueteEchec: r => {
this.souffleSiEchecTotal(rollData);
this.close()
this.$forceClose(`${this.actor.name} n'a pas purifié la ${tmr.label}, et quitte les TMR.`)
},
canClose: false
});
@ -811,7 +825,7 @@ export class RdDTMRDialog extends Dialog {
difficulte: -7,
action: 'Conquérir',
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
});
}
@ -922,19 +936,15 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async processSortReserve(sortReserve) {
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
console.log("declencheSortEnReserve", sortReserve);
const heureCible = RdDTimestamp.definition(sortReserve.system.heurecible).label;
this._tellToUserAndGM(`Vous avez déclenché
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"}
en réserve <strong>${sortReserve.name}</strong>
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();
console.log("declencheSortEnReserve", sortReserve)
const sort = sortReserve.system.sortid ? this.actor.items.get(sortReserve.system.sortid) : undefined
const message = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-lancement-sortreserve.hbs`,
{ sortReserve, sort })
await this.$forceClose(message)
}
/* -------------------------------------------- */
nettoyerRencontre() {
$nettoyerRencontre() {
// Suppression des dessins des zones possibles
this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic))
// Nettoyage de la structureet de l'état
@ -1021,7 +1031,7 @@ export class RdDTMRDialog extends Dialog {
console.log("STATUS :", this.rencontreState, this.currentRencontre);
}
this.checkQuitterTMR();
await this.$checkQuitterTMR();
}
/* -------------------------------------------- */
@ -1054,13 +1064,13 @@ export class RdDTMRDialog extends Dialog {
*/
this.notifierResonanceSigneDraconique(targetCoord);
await this.actor.rollUnSort(targetCoord);
this.nettoyerRencontre();
this.$nettoyerRencontre();
}
/* -------------------------------------------- */
externalRefresh() {
this.createPixiSprites();
this.updateValuesDisplay();
this.$updateValuesDisplay();
this.updateTokens();
console.log("TMR REFRESHED !!!");
}
@ -1071,7 +1081,7 @@ export class RdDTMRDialog extends Dialog {
return this.forceTMRContinueAction()
}
if (this.currentRencontre != 'normal') {
this.nettoyerRencontre();
this.$nettoyerRencontre();
}
let tmr = TMRUtility.getTMR(targetCoord);
// Gestion cases spéciales type Trou noir, etc
@ -1083,7 +1093,7 @@ export class RdDTMRDialog extends Dialog {
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase;
}
this.updateValuesDisplay();
this.$updateValuesDisplay();
this.actor.notifyRefreshTMR();
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
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-definition', (heure) => RdDTimestamp.definition(heure))
Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier());
Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());

View File

@ -8,6 +8,7 @@
"scripts": {
"build": "npx vite build",
"gulp": "gulp",
"run": "npx vite serve",
"packCompendiumsToDist": "node ./tools/packCompendiumsToDist.mjs",
"packCompendiumsToPublic": "node ./tools/packCompendiumsToPublic.mjs",
"unpackCompendiumsFromPublic": "node ./tools/unpackCompendiumsFromPublic.mjs"

View File

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

View File

@ -1,12 +1,12 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "12.0.38",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.38/rddsystem.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.38/system.json",
"version": "13.0.0",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/13.0.0/rddsystem.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/13.0.0/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": {
"minimum": "11",
"minimum": "12",
"verified": "12"
},
"description": "Rêve de Dragon RPG for FoundryVTT",

View File

@ -4,8 +4,7 @@
<a class="chat-card-button forcer-tmr-aleatoire" data-tooltip="Ré-insérer aléatoirement le demi-rêve, et masquer la position au joueur">Ré-insertion aléatoire</a>
</span>
<span>
<a class="chat-card-button afficher-tmr"
data-tooltip="{{#if hautreve.cacheTMR}}Montrer la position du demi-rêve au joueur{{else}}Cacher la position du demi-rêve au joueur{{/if}}">{{#if hautreve.cacheTMR}}Montrer les TMR{{else}}Cacher les TMR{{/if}}</a>
<a class="chat-card-button afficher-tmr" data-tooltip="{{#if hautreve.cacheTMR}}Révéler la position du demi-rêve au joueur{{else}}Cacher la position du demi-rêve au joueur{{/if}}">{{#if hautreve.cacheTMR}}Révéler le demi-rêve{{else}}Cacher le demi-rêve{{/if}}</a>
</span>
</li>
{{/if}}

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 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"}}
{{else}}
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.hbs"}}

View File

@ -3,3 +3,4 @@
{{>"systems/foundryvtt-reve-de-dragon/templates/sheets/item/common/template-inventaire.hbs"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/sheets/item/common/template-description.hbs"}}
</section>