Compare commits

...

32 Commits
v13 ... v11

Author SHA1 Message Date
27882be340 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-03-24 23:25:53 +01:00
c62de40620 Consistance chèvre
La consistance chèvre est supportée (caractères accentués)
2025-03-24 23:24:09 +01:00
6dcf8ddee9 Amélioration message lancement sort en réserve 2025-03-19 02:06:47 +01:00
9b8a600e22 Merge pull request '## 12.0.46 - Le double demi d'Astrobazzarh' (#755) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#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
03366fdf26 Gestion armes naturelles sur defense 2025-03-15 22:04:37 +01:00
14f324360d Merge pull request 'Fix: difficulté des médiations' (#754) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#754
2025-03-15 20:32:20 +01:00
d60c9f1b28 Renommage révéler/masquer le demi-rêve 2025-03-15 17:18:41 +01:00
cf514470fd Fix: difficulté des médiations
La difficulté des méditations n'augmente plus en cas de réussite
et d'échec normal
2025-03-15 17:17:29 +01:00
b09b095897 Formatage changelog 2025-03-05 08:26:37 +01:00
d81965155c Correction sur heures de repos 2025-03-05 08:25:00 +01:00
9fa8a2e6f3 Merge pull request '12.0.44 - Les errements d'Astrobazzarh, suite' (#753) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#753
2025-03-05 08:24:13 +01:00
da7f87fd45 Changelog 12.0.44 2025-03-04 23:06:39 +01:00
6aba92900c 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-03-04 23:01:04 +01:00
4939e5564e Fix possessions 2025-03-04 22:46:28 +01:00
40be65a94e Merge pull request 'v11 - sommeil' (#752) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#752
2025-03-04 22:11:00 +01:00
633638a9ab Fix récupération sommeil
Les différentsq 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-03-04 22:04:52 +01:00
88a3464eed Add command to run debug server 2025-03-04 21:32:21 +01:00
921e470498 Petit fixes de synchro + essai pour corriger message XP + roll 2025-02-27 22:53:06 +01:00
0009876a6d Merge pull request '12.0.42' (#751) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#751
2025-02-10 07:58:31 +01:00
54785f0c3a Version 12.0.42 2025-02-10 01:54:25 +01:00
df76c4bd78 Corrections automatisations combat
Visiblement des changements sur les callbacks n'avaient pas
été finalisés
2025-02-10 01:54:25 +01:00
5f3c678195 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:06 +01:00
89bbe63340 Merge pull request 'La loupe d'Astrobazzar' (#748) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#748
2025-02-09 00:30:52 +01:00
149990e352 Correction: diminution stress transformé 2025-02-07 21:29:50 +01:00
3e355784c7 Message d'expérience en sort
Adaptation du message d'xp en sort au renommage des voies draconiques
2025-02-07 20:47:20 +01:00
b92055d5dd Commande /tirer cachée
Pour les messages sans actor, la méthode getOwners ne marchait
pas. En cas d'absence d'acteur, les gmroll doivent être pour le
joueur courant et les MJs
2025-02-07 20:47:20 +01:00
220f8142f5 Merge pull request 'v11 Fix choix particulière' (#746) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#746
2025-02-06 10:42:25 +01:00
a8bb00ad0b Fix choix particulière 2025-02-05 22:56:24 +01:00
78e30b5503 Correction message min/max de race 2025-02-02 00:06:38 +01:00
26 changed files with 385 additions and 298 deletions

View File

@ -1,9 +1,54 @@
# 12.0 # 12.0
## 12.0.47 - La chèvre d'Astrobazzarh
- 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
## 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
## 12.0.40 - Les mains d'Astrobazzarh
- correction des attaques particulières en combat
- correction de message sur les min/max liés aux modificateurs de races (s'applique uniquement sur la taille)
## 12.0.39 - Les mains d'Astrobazzarh ## 12.0.39 - Les mains d'Astrobazzarh
- les armes à 1 ou 2 mains fonctionnent dans les liens de jets de dés - les armes à 1 ou 2 mains fonctionnent dans les liens de jets de dés
- commande `/jet` pour poster une demande de jet de dés - commande `/jet` pour poster une demande de jet de dés
## 12.0.38 - Les prévisions d'Astrobazzarh ## 12.0.38 - Les prévisions d'Astrobazzarh
- Correction de modifications de personnages qui ne s'affichaient pas: - Correction de modifications de personnages qui ne s'affichaient pas:
- changements d'endurance/vie/fatigue, transformé, ... - changements d'endurance/vie/fatigue, transformé, ...
- Migration des compétences "Ecriture" en "Écriture" dans les tâches, livres, oeuvres et méditations - Migration des compétences "Ecriture" en "Écriture" dans les tâches, livres, oeuvres et méditations
@ -13,12 +58,14 @@
- utilisation de l'extension hbs pour tous les fichiers handlebars - utilisation de l'extension hbs pour tous les fichiers handlebars
## 12.0.37 - Les enchantements d'Astrobazzarh ## 12.0.37 - Les enchantements d'Astrobazzarh
- les potions ont un état, seules les potions liquides sont enchantables - les potions ont un état, seules les potions liquides sont enchantables
- les lancements de sorts du jour sont conservés jusqu'à chateau dormant - les lancements de sorts du jour sont conservés jusqu'à chateau dormant
- lorsqu'un joueur souhaite enchanter une potion, les sorts d'enchantements/purification/permanence doivent avoir été lancés auparavant - lorsqu'un joueur souhaite enchanter une potion, les sorts d'enchantements/purification/permanence doivent avoir été lancés auparavant
- on peut enchanter des gemmes exactement comme des potions - on peut enchanter des gemmes exactement comme des potions
## 12.0.36 - L'alchimie d'Astrobazzarh ## 12.0.36 - L'alchimie d'Astrobazzarh
- Nouveautés - Nouveautés
- ajout d'un bouton pour enchanter les potions - ajout d'un bouton pour enchanter les potions
- standardisation des boutons d'actions sur les items - standardisation des boutons d'actions sur les items
@ -33,9 +80,11 @@
- Corrections de descriptions pour proposer les jet de dés - Corrections de descriptions pour proposer les jet de dés
## 12.0.35 - La Solution d'Astrobazzarh ## 12.0.35 - La Solution d'Astrobazzarh
- Fix problème d'initialisation des feuilles d'items - Fix problème d'initialisation des feuilles d'items
## 12.0.34 - la tête d'Astrobazzarh ## 12.0.34 - la tête d'Astrobazzarh
- support de liens "jets de dés" - support de liens "jets de dés"
- on peut ajouter des liens "jet de dés" dans les journaux, descriptions, notes, maladresses, ... - on peut ajouter des liens "jet de dés" dans les journaux, descriptions, notes, maladresses, ...
- avec la syntaxe `@roll[...]` on peut ajouter le lien vers: - avec la syntaxe `@roll[...]` on peut ajouter le lien vers:
@ -50,21 +99,26 @@
- gestion des blocs secrets dans les descriptions - gestion des blocs secrets dans les descriptions
## 12.0.33 - la vieillesse d'Astrobazzarh ## 12.0.33 - la vieillesse d'Astrobazzarh
- retour de l'expérience pour les joueurs - retour de l'expérience pour les joueurs
- suppression du message "Pas de caractéristique" sur les jets d'odorat-goût - suppression du message "Pas de caractéristique" sur les jets d'odorat-goût
## 12.0.32 - les rêveries d'Astrobazzarh ## 12.0.32 - les rêveries d'Astrobazzarh
- Ajout des Items Race pour gérer les ajustements liés aux races - Ajout des Items Race pour gérer les ajustements liés aux races
## 12.0.31 - le mausolée d'Astrobazzarh ## 12.0.31 - le mausolée d'Astrobazzarh
- Correction: les automatisation de combat jouer-MJ fonctionnentde nouveau - Correction: les automatisation de combat jouer-MJ fonctionnentde nouveau
## 12.0.30 - le cauchemar d'Astrobazzarh ## 12.0.30 - le cauchemar d'Astrobazzarh
- calcul automatique du niveau des entités selon leur rêve - calcul automatique du niveau des entités selon leur rêve
- la description des créatures venimeuses contient un lien vers leur venin - la description des créatures venimeuses contient un lien vers leur venin
- Correction: les messages de combats ne marchaient plus (Changement combiné Foundry + rêve de Dragon) - Correction: les messages de combats ne marchaient plus (Changement combiné Foundry + rêve de Dragon)
## 12.0.29 - L'indexation d'Astrobazzarh ## 12.0.29 - L'indexation d'Astrobazzarh
- les liens dans la descriptions des sorts pointent vers les sorts du compendium - les liens dans la descriptions des sorts pointent vers les sorts du compendium
- la description du chrasme contient le lien vers son venin plutôt qu'un tableau - la description du chrasme contient le lien vers son venin plutôt qu'un tableau

View File

@ -237,7 +237,11 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
this.html.find('.carac-xp-augmenter').click(async event => await this.actor.updateCaracXPAuto(event.currentTarget.name.replace("augmenter.", ""))) this.html.find('.carac-xp-augmenter').click(async event => await this.actor.updateCaracXPAuto(event.currentTarget.name.replace("augmenter.", "")))
this.html.find('.competence-xp-augmenter').click(async event => await this.actor.updateCompetenceXPAuto(RdDSheetUtility.getItemId(event))) this.html.find('.competence-xp-augmenter').click(async event => await this.actor.updateCompetenceXPAuto(RdDSheetUtility.getItemId(event)))
this.html.find('.competence-stress-augmenter').click(async event => await this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event))) this.html.find('.competence-stress-augmenter').click(async event =>{
await this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event))
this.render(true)
}
)
if (this.options.vueDetaillee) { if (this.options.vueDetaillee) {
// On carac change // On carac change

View File

@ -243,7 +243,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
await this.resetInfoSommeil() await this.resetInfoSommeil()
ChatMessage.create(message); ChatMessage.create(message);
this.sheet.render(true); setTimeout(() => this.sheet.render(), 20)
} }
async _recuperationSante(message) { async _recuperationSante(message) {
@ -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();
this.sheet.render(true);
}
} }
async resetInfoSommeil() { async resetInfoSommeil() {
@ -442,10 +446,9 @@ export class RdDActor extends RdDBaseActorSang {
message.content += 'Vous ne trouvez pas le sommeil'; message.content += 'Vous ne trouvez pas le sommeil';
} }
else { else {
let jetsReve = []; let dormi = await this.$dormirDesHeures(message, heures, options);
let dormi = await this.dormirDesHeures(jetsReve, message, heures, options); if (dormi.jetsReve.length > 0) {
if (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. `;
message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '0 (réveil)' : it).reduce(Misc.joining("+"))} Points de rêve. `;
} }
if (dormi.etat == 'eveil') { if (dormi.etat == 'eveil') {
await this.reveilReveDeDragon(message, dormi.heures); await this.reveilReveDeDragon(message, dormi.heures);
@ -458,11 +461,9 @@ export class RdDActor extends RdDBaseActorSang {
ChatMessage.create(message); ChatMessage.create(message);
} }
if (options.chateauDormant) { if (options.chateauDormant) {
await this.dormirChateauDormant(); await this.$dormirChateauDormant();
}
else {
this.sheet.render(true);
} }
setTimeout(() => this.sheet.render(), 20)
} }
async reveilReveDeDragon(message, heures) { async reveilReveDeDragon(message, heures) {
@ -472,18 +473,18 @@ export class RdDActor extends RdDBaseActorSang {
} }
} }
async dormirDesHeures(jetsReve, message, heures, options) { async $dormirDesHeures(message, heures, options) {
const dormi = { heures: 0, etat: 'dort' }; const dormi = { heures: 0, etat: 'dort', jetsReve: [] };
for (; dormi.heures < heures && dormi.etat == 'dort'; dormi.heures++) { for (; dormi.heures < heures && dormi.etat == 'dort'; dormi.heures++) {
await this._recupererEthylisme(message); await this.$recupererEthylisme(message);
if (options.grisReve) { if (options.grisReve) {
await this.recupererFatigue(message); await this.$recupererFatigue(message);
} }
else if (!this.system.sommeil?.insomnie) { else if (!this.system.sommeil?.insomnie) {
await this.recupererFatigue(message); await this.$recupererFatigue(message);
dormi.etat = await this.jetRecuperationReve(jetsReve, 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(jetsReve, message); dormi.etat = 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) { if (this.getReveActuel() < this.system.reve.seuil.value) {
let reve = await RdDDice.rollTotal("1dr"); const reve = await RdDDice.rollTotal("1dr")
if (reve >= 7) { if (reve >= 7) {
// Rêve de Dragon ! // 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! `; 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); await this.combattreReveDeDragon(reve);
jetsReve.push(-1); dormi.jetsReve.push(-1);
return 'eveil'; dormi.etat = 'eveil'
return
} }
else { else {
if (!ReglesOptionnelles.isUsing("recuperation-reve")) { if (!ReglesOptionnelles.isUsing("recuperation-reve")) {
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(this), whisper: ChatUtility.getOwners(this),
content: `Pas de récupération de rêve (${reve} points ignorés)` content: `Pas de récupération de rêve (${reve} points ignorés)`
}); })
jetsReve.push(0); dormi.jetsReve.push(0)
} }
else { else {
await this.reveActuelIncDec(reve); await this.reveActuelIncDec(reve)
jetsReve.push(reve); dormi.jetsReve.push(reve)
} }
} }
} }
return 'dort'; dormi.etat = 'dort'
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _recupererEthylisme(message) { async $recupererEthylisme(message) {
if (!ReglesOptionnelles.isUsing("recuperation-ethylisme")) { return; } if (!ReglesOptionnelles.isUsing("recuperation-ethylisme")) { return; }
let value = Math.min(Number.parseInt(this.system.compteurs.ethylisme.value) + 1, 1); let value = Math.min(Number.parseInt(this.system.compteurs.ethylisme.value) + 1, 1);
if (value <= 0) { if (value <= 0) {
@ -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. `;
@ -549,15 +550,15 @@ export class RdDActor extends RdDBaseActorSang {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async recupererFatigue(message) { async $recupererFatigue(message) {
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
let fatigue = this.system.sante.fatigue.value; let fatigue = this.system.sante.fatigue.value
const fatigueMin = this.getFatigueMin(); const fatigueMin = this.getFatigueMin()
if (fatigue <= fatigueMin) { if (fatigue <= fatigueMin) {
return; return
} }
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 });
if (fatigue == 0) { if (fatigue == 0) {
message.content += "Vous êtes complêtement reposé. "; message.content += "Vous êtes complêtement reposé. ";
} }
@ -736,7 +737,7 @@ export class RdDActor extends RdDBaseActorSang {
await competence.update({ await competence.update({
"system.xp": toXp, "system.xp": toXp,
"system.niveau": toNiveau, "system.niveau": toNiveau,
}); }, { render: false })
await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name); await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name);
await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name); await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name);
} }
@ -767,7 +768,7 @@ export class RdDActor extends RdDBaseActorSang {
await competence.update({ await competence.update({
"system.xp": newXp, "system.xp": newXp,
"system.niveau": toNiveau, "system.niveau": toNiveau,
}); }, { render: false })
const toXpStress = Math.max(0, fromXpStress - xpUtilise); const toXpStress = Math.max(0, fromXpStress - xpUtilise);
await this.update({ "system.compteurs.experience.value": toXpStress }); await this.update({ "system.compteurs.experience.value": toXpStress });
@ -783,7 +784,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 }); await competence.update({ 'system.niveau': toNiveau }, { render: false })
await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name, true); await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name, true);
} }
} }
@ -808,7 +809,7 @@ export class RdDActor extends RdDBaseActorSang {
if (isNaN(toXp) || typeof (toXp) != 'number') toXp = 0; if (isNaN(toXp) || typeof (toXp) != 'number') toXp = 0;
const fromXp = competence.system.xp; const fromXp = competence.system.xp;
this.checkCompetenceXP(idOrName, toXp); this.checkCompetenceXP(idOrName, toXp);
await competence.update({ 'system.xp': toXp }); await competence.update({ 'system.xp': toXp }, { render: false })
await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name, true); await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name, true);
if (toXp > fromXp) { if (toXp > fromXp) {
RdDUtility.checkThanatosXP(competence) RdDUtility.checkThanatosXP(competence)
@ -822,7 +823,7 @@ export class RdDActor extends RdDBaseActorSang {
if (competence) { if (competence) {
if (isNaN(toXpSort) || typeof (toXpSort) != 'number') toXpSort = 0; if (isNaN(toXpSort) || typeof (toXpSort) != 'number') toXpSort = 0;
const fromXpSort = competence.system.xp_sort; const fromXpSort = competence.system.xp_sort;
await competence.update({ 'system.xp_sort': toXpSort }); await competence.update({ 'system.xp_sort': toXpSort }, { render: false })
await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, competence.name, true); await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, competence.name, true);
if (toXpSort > fromXpSort) { if (toXpSort > fromXpSort) {
RdDUtility.checkThanatosXP(competence) RdDUtility.checkThanatosXP(competence)
@ -834,7 +835,7 @@ export class RdDActor extends RdDBaseActorSang {
async updateCompetenceArchetype(idOrName, compValue) { async updateCompetenceArchetype(idOrName, compValue) {
let competence = this.getCompetence(idOrName) let competence = this.getCompetence(idOrName)
if (competence) { if (competence) {
await competence.update({ 'system.niveau_archetype': Math.max(compValue ?? 0, 0) }); await competence.update({ 'system.niveau_archetype': Math.max(compValue ?? 0, 0) })
} }
} }
@ -1047,20 +1048,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)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -1770,7 +1761,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();
} }
} }
@ -1800,8 +1791,10 @@ export class RdDActor extends RdDBaseActorSang {
}; };
RollDataAjustements.calcul(rollData, this); RollDataAjustements.calcul(rollData, this);
await RdDResolutionTable.rollData(rollData); await RdDResolutionTable.rollData(rollData);
this.gererExperience(rollData);
await RdDRollResult.displayRollData(rollData, this) await RdDRollResult.displayRollData(rollData, this)
this.gererExperience(rollData);
return rollData.rolled; return rollData.rolled;
} }
@ -2116,7 +2109,6 @@ export class RdDActor extends RdDBaseActorSang {
label: "Jet de méditation", label: "Jet de méditation",
callbacks: [ callbacks: [
this.createCallbackExperience(), this.createCallbackExperience(),
{ condition: r => r.rolled.isEPart, action: r => this._meditationEPart(r) },
{ action: r => this._meditationResult(r) } { action: r => this._meditationResult(r) }
] ]
}); });
@ -2125,21 +2117,16 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _meditationResult(meditationRoll) { async _meditationResult(meditationRoll) {
this.santeIncDec("fatigue", 2);
if (meditationRoll.rolled.isSuccess) { if (meditationRoll.rolled.isSuccess) {
await this.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditationRoll.meditation, meditationRoll.rolled)]); 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'); 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) { _getSignesDraconiques(coord) {
const type = TMRUtility.getTMRType(coord); const type = TMRUtility.getTMRType(coord);
@ -2527,7 +2514,6 @@ export class RdDActor extends RdDBaseActorSang {
}) })
} }
const blessure = this.getItem(blessureId, 'blessure') const blessure = this.getItem(blessureId, 'blessure')
console.log('TODO update blessure', this, blessureId, rollData, rollData.tache);
if (blessure && !blessure.system.premierssoins.done) { if (blessure && !blessure.system.premierssoins.done) {
const tache = rollData.tache; const tache = rollData.tache;
if (rollData.rolled.isETotal) { if (rollData.rolled.isETotal) {
@ -2644,12 +2630,13 @@ export class RdDActor extends RdDBaseActorSang {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async incDecItemUse(itemId, inc = 1) { async incDecItemUse(itemId, shouldIncrease = true) {
if (shouldIncrease) {
const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse'); const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse');
let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {}; let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {};
itemUse[itemId] = (itemUse[itemId] ?? 0) + inc; itemUse[itemId] = (itemUse[itemId] ?? 0) + 1;
await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse); await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse);
console.log("ITEM USE INC", inc, itemUse); }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

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

View File

@ -39,6 +39,11 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return 0; return 0;
} }
isCumulFatigueCauseSommeil(cumulFatigue){
return ReglesOptionnelles.isUsing("appliquer-fatigue")
? (this.getFatigueRestante() <= cumulFatigue)
: (this.getEnduranceActuelle() <= cumulFatigue)
}
getFatigueRestante() {return this.getFatigueMax() - this.getFatigueActuelle() } 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 }

View File

@ -244,16 +244,19 @@ export class RdDBaseActor extends Actor {
async onUpdateActor(update, options, actorId) { } async onUpdateActor(update, options, actorId) { }
async onDeleteItem(item, options, id) { async onDeleteItem(item, options, id) {
if (item.isInventaire()) { if (item.isInventaire()) {
this._removeItemFromConteneur(item) await this._removeItemFromConteneur(item)
} }
} }
_removeItemFromConteneur(item) { async _removeItemFromConteneur(item) {
this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id))
.forEach(conteneur => { .map(conteneur => {
const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id); const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id)
conteneur.update({ 'system.contenu': nouveauContenu }); return { _id: conteneur.id, 'system.contenu': nouveauContenu }
}); })
if (updates.length > 0) {
await this.updateEmbeddedDocuments('Item', updates)
}
} }
async onTimeChanging(oldTimestamp, newTimestamp) { async onTimeChanging(oldTimestamp, newTimestamp) {
@ -744,7 +747,7 @@ export class RdDBaseActor extends Actor {
async jetDeMoral() { this.actionImpossible("jet de moral") } async jetDeMoral() { this.actionImpossible("jet de moral") }
async resetItemUse() { } async resetItemUse() { }
async incDecItemUse(itemId, inc = 1) { } async incDecItemUse(itemId, shouldIncrease = true) { }
getItemUse(itemId) { return 0; } getItemUse(itemId) { return 0; }
async finDeRound(options = { terminer: false }) { } async finDeRound(options = { terminer: false }) { }

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

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

View File

@ -62,7 +62,6 @@ export class ChatUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static removeMessages(socketData) { static removeMessages(socketData) {
if (Misc.isFirstConnectedGM()) { if (Misc.isFirstConnectedGM()) {
ChatUtility.onRemoveMessages(socketData); ChatUtility.onRemoveMessages(socketData);
@ -97,7 +96,7 @@ export class ChatUtility {
} }
break break
case "gmroll": case "gmroll":
messageData.whisper = ChatUtility.getOwners(actor) messageData.whisper = actor ? ChatUtility.getOwners(actor) : ChatUtility.getUserAndGMs()
break break
case "selfroll": case "selfroll":
messageData.whisper = [game.user] messageData.whisper = [game.user]
@ -108,7 +107,7 @@ export class ChatUtility {
} }
static getOwners(document) { static getOwners(document) {
return game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user]
} }
static getUserAndGMs() { static getUserAndGMs() {

View File

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

View File

@ -56,6 +56,10 @@ export class RdDItemSort extends Item {
return voies.map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie)) 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) { static getOrdreCode(code) {
return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?') return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?')
} }
@ -92,7 +96,7 @@ export class RdDItemSort extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCoutVariable(sort) { 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

@ -19,11 +19,13 @@ export class RdDItemRace extends RdDItem {
return false return false
} }
} }
if (code == LIST_CARAC_PERSONNAGE.taille.code) {
const carac = RdDCarac.carac(code) const carac = RdDCarac.carac(code)
if (race.isMax(actor, code, value - 1)) { if (race.isMax(actor, code, value - 1)) {
ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`) ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`)
return false return false
} }
}
return true return true
} }
@ -59,7 +61,8 @@ export class RdDItemRace extends RdDItem {
if (code == LIST_CARAC_PERSONNAGE.force.code) { if (code == LIST_CARAC_PERSONNAGE.force.code) {
return value >= this.getForceMax(actor) return value >= this.getForceMax(actor)
} }
const max = foundry.utils.getProperty(this, path) ?? -1 const pathMax = path.replace(".value", ".max");
const max = foundry.utils.getProperty(this, pathMax) ?? -1
return (max > 0 && value >= max) return (max > 0 && value >= max)
} }

View File

@ -265,7 +265,7 @@ export class Misc {
const subset = elements.filter(options.preFilter) const subset = elements.filter(options.preFilter)
.filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value)) .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value))
.sort(Misc.ascending(it => options.mapper(it))) .sort(Misc.ascending(it => options.mapper(it)))
if (subset.length == 0) { if (subset.length == 0 && options?.onMessage) {
options.onMessage(`Pas de ${options.description} correspondant à ${value}`); options.onMessage(`Pas de ${options.description} correspondant à ${value}`);
} }
return subset; return subset;

View File

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

View File

@ -104,8 +104,8 @@ export class RdDPossession {
rollData.selectedCarac = carac.reve rollData.selectedCarac = carac.reve
} }
else { else {
rollData.selectedCarac = rollingActor.system.carac.reve
rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } } rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } }
rollData.selectedCarac = rollData.forceCarac['reve-actuel']
rollData.competence.system.defaut_carac = '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 { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js"; import { RdDDice } from "./rdd-dice.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";

View File

@ -279,7 +279,7 @@ export class RdDRoll extends Dialog {
async setSelectedSort(sort) { async setSelectedSort(sort) {
this.rollData.selectedSort = sort; // Update the selectedCarac 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.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord);
this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7); this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7);
RdDItemSort.setCoutReveReel(sort); RdDItemSort.setCoutReveReel(sort);

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

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

View File

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

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> <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>
<span> <span>
<a class="chat-card-button afficher-tmr" <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>
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>
</span> </span>
</li> </li>
{{/if}} {{/if}}

View File

@ -1,15 +1,18 @@
<div> <div>
<ul class="item-list"> <ul class="item-list">
<li class="item flexrow"> <li class="flexrow">
<label class="derivee-label" for="system.compteurs.experience.value">Stress transformé</label> <label class="derivee-label" for="system.compteurs.experience.value">Stress transformé</label>
{{#if options.vueDetaillee}} {{#if options.vueDetaillee}}
<input class="derivee-value" type="number" name="system.compteurs.experience.value" value="{{system.compteurs.experience.value}}" data-dtype="number" size="3"/> <input class="resource-content"
type="text" data-dtype="Number" size="3"
name="system.compteurs.experience.value"
value="{{system.compteurs.experience.value}}"/>
{{else}} {{else}}
<label name="system.compteurs.experience.value">{{system.compteurs.experience.value}}</label> <label name="system.compteurs.experience.value">{{system.compteurs.experience.value}}</label>
{{/if}} {{/if}}
</li> </li>
{{#if options.vueDetaillee}} {{#if options.vueDetaillee}}
<li class="item flexrow"> <li class="flexrow">
<span class="generic-label">Total XP compétences</span> <span class="generic-label">Total XP compétences</span>
<span class="competence-value">{{calc.competenceXPTotal}}</span> <span class="competence-value">{{calc.competenceXPTotal}}</span>
</li> </li>

View File

@ -2,19 +2,22 @@
<h4 class="rdd-roll-part">{{alias}} réussit une attaque particulière!</strong></h4> <h4 class="rdd-roll-part">{{alias}} réussit une attaque particulière!</strong></h4>
{{#if isForce}} {{#if isForce}}
<br> <br>
<a class="chat-card-button particuliere-attaque" data-mode="force" data-attackerId="{{attackerId}}"> <a class="chat-card-button particuliere-attaque" data-mode="force" data-attackerId="{{attackerId}}"
data-defenderTokenId="{{defenderToken.id}}" data-attackerTokenId="{{attackerToken.id}}">
Attaquer en Force Attaquer en Force
</a> </a>
{{/if}} {{/if}}
{{#if isRapide}} {{#if isRapide}}
<br> <br>
<a class="chat-card-button particuliere-attaque" data-mode="rapidite" data-attackerId="{{attackerId}}"> <a class="chat-card-button particuliere-attaque" data-mode="rapidite" data-attackerId="{{attackerId}}"
data-defenderTokenId="{{defenderToken.id}}" data-attackerTokenId="{{attackerToken.id}}">
Attaquer en Rapidité Attaquer en Rapidité
</a> </a>
{{/if}} {{/if}}
{{#if isFinesse}} {{#if isFinesse}}
<br> <br>
<a class="chat-card-button particuliere-attaque" data-mode="finesse" data-attackerId="{{attackerId}}"> <a class="chat-card-button particuliere-attaque" data-mode="finesse" data-attackerId="{{attackerId}}"
data-defenderTokenId="{{defenderToken.id}}" data-attackerTokenId="{{attackerToken.id}}">
Attaquer en Finesse Attaquer en Finesse
</a> </a>
{{/if}} {{/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

@ -4,7 +4,7 @@
<hr> <hr>
<div> <div>
{{#if rolled.isSuccess}} {{#if rolled.isSuccess}}
{{alias}} a gagné {{xpSort}} points d'expérience en sorts dans la {{competence.name}}. {{alias}} a gagné {{xpSort}} points d'expérience en sorts en {{competence.name}}.
{{else}} {{else}}
{{alias}} n'a pas pu interpréter le signe draconique. {{alias}} n'a pas pu interpréter le signe draconique.
{{/if}} {{/if}}