Compare commits
	
		
			31 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 03366fdf26 | |||
| 14f324360d | |||
| d60c9f1b28 | |||
| cf514470fd | |||
| b09b095897 | |||
| d81965155c | |||
| 9fa8a2e6f3 | |||
| da7f87fd45 | |||
| 6aba92900c | |||
| 4939e5564e | |||
| 40be65a94e | |||
| 633638a9ab | |||
| 88a3464eed | |||
| 921e470498 | |||
| 0009876a6d | |||
| 54785f0c3a | |||
| df76c4bd78 | |||
| 5f3c678195 | |||
| 89bbe63340 | |||
| 149990e352 | |||
| 3e355784c7 | |||
| b92055d5dd | |||
| 220f8142f5 | |||
| a8bb00ad0b | |||
| 78e30b5503 | |||
| 069fef4720 | |||
| e32a7d7540 | |||
| 0773493851 | |||
| da982678b7 | |||
| c1066d70f6 | |||
| 5085ba5b54 | 
							
								
								
									
										44
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								changelog.md
									
									
									
									
									
								
							@@ -1,5 +1,40 @@
 | 
			
		||||
# 12.0
 | 
			
		||||
 | 
			
		||||
## 12.0.44 - 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
 | 
			
		||||
 | 
			
		||||
- 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
 | 
			
		||||
 | 
			
		||||
## 12.0.38 - Les prévisions d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- Correction de modifications de personnages qui ne s'affichaient pas:
 | 
			
		||||
  - changements d'endurance/vie/fatigue, transformé, ...
 | 
			
		||||
- Migration des compétences "Ecriture" en "Écriture" dans les tâches, livres, oeuvres et méditations
 | 
			
		||||
@@ -9,12 +44,14 @@
 | 
			
		||||
  - utilisation de l'extension hbs pour tous les fichiers handlebars
 | 
			
		||||
 | 
			
		||||
## 12.0.37 - Les enchantements d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- les potions ont un état, seules les potions liquides sont enchantables
 | 
			
		||||
- 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
 | 
			
		||||
- on peut enchanter des gemmes exactement comme des potions
 | 
			
		||||
 | 
			
		||||
## 12.0.36 - L'alchimie d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- Nouveautés
 | 
			
		||||
  - ajout d'un bouton pour enchanter les potions
 | 
			
		||||
  - standardisation des boutons d'actions sur les items
 | 
			
		||||
@@ -29,9 +66,11 @@
 | 
			
		||||
  - Corrections de descriptions pour proposer les jet de dés
 | 
			
		||||
 | 
			
		||||
## 12.0.35 - La Solution d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- Fix problème d'initialisation des feuilles d'items
 | 
			
		||||
 | 
			
		||||
## 12.0.34 - la tête d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- support de liens "jets de dés"
 | 
			
		||||
  - 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:
 | 
			
		||||
@@ -46,21 +85,26 @@
 | 
			
		||||
- gestion des blocs secrets dans les descriptions
 | 
			
		||||
 | 
			
		||||
## 12.0.33 - la vieillesse d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- retour de l'expérience pour les joueurs
 | 
			
		||||
- suppression du message "Pas de caractéristique" sur les jets d'odorat-goût
 | 
			
		||||
 | 
			
		||||
## 12.0.32 - les rêveries d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- Ajout des Items Race pour gérer les ajustements liés aux races
 | 
			
		||||
 | 
			
		||||
## 12.0.31 - le mausolée d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- Correction: les automatisation de combat jouer-MJ fonctionnentde nouveau
 | 
			
		||||
 | 
			
		||||
## 12.0.30 - le cauchemar d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- calcul automatique du niveau des entités selon leur rêve
 | 
			
		||||
- 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)
 | 
			
		||||
 | 
			
		||||
## 12.0.29 - L'indexation d'Astrobazzarh
 | 
			
		||||
 | 
			
		||||
- 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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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('.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) {
 | 
			
		||||
      // On carac change
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										122
									
								
								module/actor.js
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								module/actor.js
									
									
									
									
									
								
							@@ -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) {
 | 
			
		||||
@@ -299,7 +299,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
        ChatMessage.create(message);
 | 
			
		||||
      }
 | 
			
		||||
      await this.resetInfoSommeil();
 | 
			
		||||
      this.sheet.render(true);
 | 
			
		||||
      setTimeout(() => this.sheet.render(), 20)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -442,10 +442,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);
 | 
			
		||||
@@ -461,7 +460,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
      await this.dormirChateauDormant();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      this.sheet.render(true);
 | 
			
		||||
      setTimeout(() => this.sheet.render(), 20)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -472,18 +471,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);
 | 
			
		||||
          dormi.etat = await this.$jetRecuperationReve(dormi, message);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -491,35 +490,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) {
 | 
			
		||||
@@ -549,15 +549,16 @@ 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 });
 | 
			
		||||
      await new Promise(resolve => setTimeout(resolve, 200)); 
 | 
			
		||||
      if (fatigue == 0) {
 | 
			
		||||
        message.content += "Vous êtes complêtement reposé. ";
 | 
			
		||||
      }
 | 
			
		||||
@@ -736,7 +737,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
      await competence.update({
 | 
			
		||||
        "system.xp": toXp,
 | 
			
		||||
        "system.niveau": toNiveau,
 | 
			
		||||
      });
 | 
			
		||||
      }, { render: false })
 | 
			
		||||
      await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, 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({
 | 
			
		||||
      "system.xp": newXp,
 | 
			
		||||
      "system.niveau": toNiveau,
 | 
			
		||||
    });
 | 
			
		||||
    }, { render: false })
 | 
			
		||||
    const toXpStress = Math.max(0, fromXpStress - xpUtilise);
 | 
			
		||||
    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());
 | 
			
		||||
      this.notifyCompetencesTronc(competence, toNiveau);
 | 
			
		||||
      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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -808,7 +809,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
      if (isNaN(toXp) || typeof (toXp) != 'number') toXp = 0;
 | 
			
		||||
      const fromXp = competence.system.xp;
 | 
			
		||||
      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);
 | 
			
		||||
      if (toXp > fromXp) {
 | 
			
		||||
        RdDUtility.checkThanatosXP(competence)
 | 
			
		||||
@@ -822,7 +823,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    if (competence) {
 | 
			
		||||
      if (isNaN(toXpSort) || typeof (toXpSort) != 'number') toXpSort = 0;
 | 
			
		||||
      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);
 | 
			
		||||
      if (toXpSort > fromXpSort) {
 | 
			
		||||
        RdDUtility.checkThanatosXP(competence)
 | 
			
		||||
@@ -834,7 +835,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
  async updateCompetenceArchetype(idOrName, compValue) {
 | 
			
		||||
    let competence = this.getCompetence(idOrName)
 | 
			
		||||
    if (competence) {
 | 
			
		||||
      await competence.update({ 'system.niveau_archetype': Math.max(compValue ?? 0, 0) });
 | 
			
		||||
      await competence.update({ 'system.niveau_archetype': Math.max(compValue ?? 0, 0) })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -1560,7 +1561,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    if (!rollData.rolled.isPart ||
 | 
			
		||||
      rollData.finalLevel >= 0 ||
 | 
			
		||||
      game.settings.get("core", "rollMode") == 'selfroll' ||
 | 
			
		||||
	  !Misc.hasConnectedGM()) {
 | 
			
		||||
      !Misc.hasConnectedGM()) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
 | 
			
		||||
@@ -1584,7 +1585,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async _appliquerAppelMoral(rollData) {
 | 
			
		||||
    if (!rollData.use.moral || game.settings.get("core", "rollMode") == 'selfroll'){
 | 
			
		||||
    if (!rollData.use.moral || game.settings.get("core", "rollMode") == 'selfroll') {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    if (rollData.rolled.isEchec ||
 | 
			
		||||
@@ -1800,17 +1801,16 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    };
 | 
			
		||||
    RollDataAjustements.calcul(rollData, this);
 | 
			
		||||
    await RdDResolutionTable.rollData(rollData);
 | 
			
		||||
    this._gererExperience(rollData);
 | 
			
		||||
    await RdDRollResult.displayRollData(rollData, this)
 | 
			
		||||
 | 
			
		||||
    this.gererExperience(rollData);
 | 
			
		||||
 | 
			
		||||
    return rollData.rolled;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  gererExperience(rollData) {
 | 
			
		||||
    const callback = this.createCallbackExperience();
 | 
			
		||||
    if (callback.condition(rollData)) {
 | 
			
		||||
      callback.action(rollData);
 | 
			
		||||
    }
 | 
			
		||||
    this.createCallbackExperience().action(rollData);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
@@ -1872,7 +1872,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
        competence: competence,
 | 
			
		||||
        show: { title: options?.title ?? '' }
 | 
			
		||||
      },
 | 
			
		||||
	  // TODO:
 | 
			
		||||
      // TODO:
 | 
			
		||||
      callbacks: [{ action: r => this.$onRollCompetence(r, options) }]
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
@@ -1885,7 +1885,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    compData.system.defaut_carac = tacheData.system.carac; // Patch !
 | 
			
		||||
 | 
			
		||||
    await this.openRollDialog({
 | 
			
		||||
          name: 'jet-competence',
 | 
			
		||||
      name: 'jet-competence',
 | 
			
		||||
      label: 'Jet de Tâche ' + tacheData.name,
 | 
			
		||||
      template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs',
 | 
			
		||||
      rollData: {
 | 
			
		||||
@@ -1948,9 +1948,9 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await this.openRollDialog({
 | 
			
		||||
          name: `jet-${artData.art}`,
 | 
			
		||||
      name: `jet-${artData.art}`,
 | 
			
		||||
      label: `${artData.verbe} ${oeuvre.name}`,
 | 
			
		||||
          template: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${oeuvre.type}.hbs`,
 | 
			
		||||
      template: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${oeuvre.type}.hbs`,
 | 
			
		||||
      rollData: artData,
 | 
			
		||||
      callbacks: [{ action: callbackAction }],
 | 
			
		||||
    })
 | 
			
		||||
@@ -2119,7 +2119,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) }
 | 
			
		||||
        ]
 | 
			
		||||
      });
 | 
			
		||||
@@ -2128,21 +2127,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);
 | 
			
		||||
@@ -2530,7 +2524,6 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    const blessure = this.getItem(blessureId, 'blessure')
 | 
			
		||||
    console.log('TODO update blessure', this, blessureId, rollData, rollData.tache);
 | 
			
		||||
    if (blessure && !blessure.system.premierssoins.done) {
 | 
			
		||||
      const tache = rollData.tache;
 | 
			
		||||
      if (rollData.rolled.isETotal) {
 | 
			
		||||
@@ -2647,12 +2640,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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
 
 | 
			
		||||
@@ -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: "" }) {
 | 
			
		||||
 
 | 
			
		||||
@@ -244,16 +244,19 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
  async onUpdateActor(update, options, actorId) { }
 | 
			
		||||
  async onDeleteItem(item, options, id) {
 | 
			
		||||
    if (item.isInventaire()) {
 | 
			
		||||
      this._removeItemFromConteneur(item)
 | 
			
		||||
      await this._removeItemFromConteneur(item)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _removeItemFromConteneur(item) {
 | 
			
		||||
    this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id))
 | 
			
		||||
      .forEach(conteneur => {
 | 
			
		||||
        const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id);
 | 
			
		||||
        conteneur.update({ 'system.contenu': nouveauContenu });
 | 
			
		||||
      });
 | 
			
		||||
  async _removeItemFromConteneur(item) {
 | 
			
		||||
    const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id))
 | 
			
		||||
      .map(conteneur => {
 | 
			
		||||
        const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id)
 | 
			
		||||
        return { _id: conteneur.id, 'system.contenu': nouveauContenu }
 | 
			
		||||
      })
 | 
			
		||||
    if (updates.length > 0) {
 | 
			
		||||
      await this.updateEmbeddedDocuments('Item', updates)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async onTimeChanging(oldTimestamp, newTimestamp) {
 | 
			
		||||
@@ -744,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 }) { }
 | 
			
		||||
 
 | 
			
		||||
@@ -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-zÀ-ÖØ-öø-ÿ\\s\\-]+))?"
 | 
			
		||||
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')
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,6 @@ export class ChatUtility {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
  static removeMessages(socketData) {
 | 
			
		||||
    if (Misc.isFirstConnectedGM()) {
 | 
			
		||||
      ChatUtility.onRemoveMessages(socketData);
 | 
			
		||||
@@ -97,7 +96,7 @@ export class ChatUtility {
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      case "gmroll":
 | 
			
		||||
        messageData.whisper = ChatUtility.getOwners(actor)
 | 
			
		||||
        messageData.whisper = actor ? ChatUtility.getOwners(actor) : ChatUtility.getUserAndGMs()
 | 
			
		||||
        break
 | 
			
		||||
      case "selfroll":
 | 
			
		||||
        messageData.whisper = [game.user]
 | 
			
		||||
@@ -108,7 +107,7 @@ export class ChatUtility {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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() {
 | 
			
		||||
@@ -199,7 +198,7 @@ export class ChatUtility {
 | 
			
		||||
  static async onCreateChatMessage(chatMessage, options, id) {
 | 
			
		||||
    if (chatMessage.isAuthor) {
 | 
			
		||||
      await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
 | 
			
		||||
      await chatMessage.update({ content: await RdDTextEditor.enrichHTML(chatMessage.content, undefined, {showLink:false}) })
 | 
			
		||||
      await chatMessage.update({ content: await RdDTextEditor.enrichHTML(chatMessage.content, undefined, { showLink: false }) })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -123,10 +123,10 @@ export class RdDItemArme extends Item {
 | 
			
		||||
    if (defCategory == 'bouclier') {
 | 
			
		||||
      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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
 
 | 
			
		||||
@@ -19,10 +19,12 @@ export class RdDItemRace extends RdDItem {
 | 
			
		||||
        return false
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    const carac = RdDCarac.carac(code)
 | 
			
		||||
    if (race.isMax(actor, code, value - 1)) {
 | 
			
		||||
      ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`)
 | 
			
		||||
      return false
 | 
			
		||||
    if (code == LIST_CARAC_PERSONNAGE.taille.code) {
 | 
			
		||||
      const carac = RdDCarac.carac(code)
 | 
			
		||||
      if (race.isMax(actor, code, value - 1)) {
 | 
			
		||||
        ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`)
 | 
			
		||||
        return false
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return true
 | 
			
		||||
  }
 | 
			
		||||
@@ -59,7 +61,8 @@ export class RdDItemRace extends RdDItem {
 | 
			
		||||
    if (code == LIST_CARAC_PERSONNAGE.force.code) {
 | 
			
		||||
      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)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,9 @@ const RARETE_FREQUENTE = { code: 'Frequente', label: 'Fréquente', frequence: 18
 | 
			
		||||
const RARETE_RARE = { code: 'Rare', label: 'Rare', frequence: 6, min: 3, max: 12 };
 | 
			
		||||
const RARETE_RARISSIME = { code: 'Rarissime', label: 'Rarissime', frequence: 2, min: 1, max: 4 };
 | 
			
		||||
const RARETE_INEXISTANT = { code: 'Inexistant', label: 'Inexistant', frequence: 0, min: 0, max: 0 };
 | 
			
		||||
const RARETE_EGALE = { code: 'eqal', label: 'Egal', frequence: 1, min: 1, max: 1 };
 | 
			
		||||
const RARETE_EGALE = { code: 'egal', label: 'Egal', frequence: 1, min: 1, max: 1 };
 | 
			
		||||
 | 
			
		||||
const RARETES = [
 | 
			
		||||
export const RARETES = [
 | 
			
		||||
  RARETE_COMMUNE,
 | 
			
		||||
  RARETE_FREQUENTE,
 | 
			
		||||
  RARETE_RARE,
 | 
			
		||||
 
 | 
			
		||||
@@ -238,7 +238,7 @@ export class Misc {
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static findFirstLike(value, elements, options = {}) {
 | 
			
		||||
    options = foundry.utils.mergeObject(DEFAULT_FIND_OPTIONS, options, { overwrite: true, inplace: false });
 | 
			
		||||
    const subset = this.findAllLike(value, elements, options);
 | 
			
		||||
    const subset = this.findAllLike(value, elements, options)
 | 
			
		||||
    if (subset.length == 0) {
 | 
			
		||||
      console.log(`Aucune ${options.description} pour ${value}`);
 | 
			
		||||
      return undefined
 | 
			
		||||
@@ -263,8 +263,9 @@ export class Misc {
 | 
			
		||||
    }
 | 
			
		||||
    value = Grammar.toLowerCaseNoAccent(value);
 | 
			
		||||
    const subset = elements.filter(options.preFilter)
 | 
			
		||||
      .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value));
 | 
			
		||||
    if (subset.length == 0) {
 | 
			
		||||
      .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value))
 | 
			
		||||
      .sort(Misc.ascending(it => options.mapper(it)))
 | 
			
		||||
    if (subset.length == 0 && options?.onMessage) {
 | 
			
		||||
      options.onMessage(`Pas de ${options.description} correspondant à ${value}`);
 | 
			
		||||
    }
 | 
			
		||||
    return subset;
 | 
			
		||||
 
 | 
			
		||||
@@ -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 = {
 | 
			
		||||
@@ -776,7 +766,7 @@ export class RdDCombat {
 | 
			
		||||
 | 
			
		||||
    if (this.attacker.isCreatureEntite()) {
 | 
			
		||||
      RdDItemCompetenceCreature.setRollDataCreature(rollData);
 | 
			
		||||
  }
 | 
			
		||||
    }
 | 
			
		||||
    else if (arme) {
 | 
			
		||||
      // Usual competence
 | 
			
		||||
      rollData.arme = RdDItemArme.armeUneOuDeuxMains(arme, RdDItemCompetence.isArmeUneMain(competence));
 | 
			
		||||
@@ -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,9 +834,6 @@ export class RdDCombat {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async _onAttaqueNormale(attackerRoll) {
 | 
			
		||||
    if (!RdDCombat.isReussite(attackerRoll) || RdDCombat.isParticuliere(attackerRoll)) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll);
 | 
			
		||||
 | 
			
		||||
    attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite());
 | 
			
		||||
@@ -849,7 +848,7 @@ export class RdDCombat {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this.target) {
 | 
			
		||||
    if (this.defender) {
 | 
			
		||||
      await this._sendMessageDefense(attackerRoll, defenderRoll);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -951,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', {
 | 
			
		||||
@@ -980,26 +976,20 @@ 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;
 | 
			
		||||
    await this._onAttaqueNormale(rollData);
 | 
			
		||||
    await this._onAttaqueNormale(rollData)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
@@ -1023,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);
 | 
			
		||||
@@ -1057,8 +1045,19 @@ export class RdDCombat {
 | 
			
		||||
    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);
 | 
			
		||||
    if (!defenderRoll.attackerRoll.isPart) {
 | 
			
		||||
      // TODO: attaquant doit jouer résistance et peut être désarmé p132
 | 
			
		||||
@@ -1067,7 +1066,6 @@ export class RdDCombat {
 | 
			
		||||
        this.defender)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async _onParadeNormale(defenderRoll) {
 | 
			
		||||
    console.log("RdDCombat._onParadeNormale >>>", defenderRoll);
 | 
			
		||||
@@ -1106,11 +1104,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);
 | 
			
		||||
@@ -1138,9 +1134,18 @@ export class RdDCombat {
 | 
			
		||||
    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) {
 | 
			
		||||
    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);
 | 
			
		||||
 
 | 
			
		||||
@@ -129,6 +129,16 @@ export class RdDCommands {
 | 
			
		||||
          <br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés
 | 
			
		||||
          `
 | 
			
		||||
    });
 | 
			
		||||
    this.registerCommand({
 | 
			
		||||
      path: ["/jet"], func: (content, msg, params) => this.askRollRdd(msg, params),
 | 
			
		||||
      descr: `Poste dans le tchat un jet de dés à effectuer. Exemples:
 | 
			
		||||
          <br><strong>/jet Vue Vigilance</strong> poste une demande de jet de VUE / Vigilance à 0
 | 
			
		||||
          <br><strong>/jet Vue</strong> poste une demande de jet de VUE à 0
 | 
			
		||||
          <br><strong>/jet Vue -2</strong> poste une demande de jet de VUE à -2
 | 
			
		||||
          <br><strong>/jet Vue Vigilance -2</strong> poste une demande de jet de VUE / Vigilance à -2
 | 
			
		||||
          <br><strong>/jet vol déser +2</strong> poste une demande de jet de VOLONTÉ / Survie en désert à +2
 | 
			
		||||
          `
 | 
			
		||||
    });
 | 
			
		||||
    this.registerCommand({ path: ["/ddr"], func: (content, msg, params) => this.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });
 | 
			
		||||
 | 
			
		||||
    this.registerCommand({
 | 
			
		||||
@@ -340,6 +350,25 @@ export class RdDCommands {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  async askRollRdd(msg, params) {
 | 
			
		||||
    if (params.length == 0) {
 | 
			
		||||
      return false
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      let length = params.length;
 | 
			
		||||
      let diff = Number(params[length - 1]);
 | 
			
		||||
      if (Number.isInteger(Number(diff))) {
 | 
			
		||||
        length--;
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        diff = 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const carac = params[0];
 | 
			
		||||
      const competence = length > 1 ? '/' + Misc.join(params.slice(1, length), ' ') : ''
 | 
			
		||||
      ChatMessage.create({ content: `@roll[${carac}${competence}/${diff}]` })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async rollRdDNumeric(msg, carac, diff, significative = false) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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'
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -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";
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "npx vite build",
 | 
			
		||||
    "run": "npx vite serve",
 | 
			
		||||
    "packCompendiumsToDist": "node ./tools/packCompendiumsToDist.mjs",
 | 
			
		||||
    "packCompendiumsToPublic": "node ./tools/packCompendiumsToPublic.mjs",
 | 
			
		||||
    "unpackCompendiumsFromPublic": "node ./tools/unpackCompendiumsFromPublic.mjs"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "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": "12.0.44",
 | 
			
		||||
  "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.44/system.json",
 | 
			
		||||
  "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
 | 
			
		||||
  "compatibility": {
 | 
			
		||||
    "minimum": "11",
 | 
			
		||||
 
 | 
			
		||||
@@ -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}}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,18 @@
 | 
			
		||||
<div>
 | 
			
		||||
  <ul class="item-list">
 | 
			
		||||
    <li class="item flexrow">
 | 
			
		||||
    <li class="flexrow">
 | 
			
		||||
      <label class="derivee-label" for="system.compteurs.experience.value">Stress transformé</label>
 | 
			
		||||
      {{#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}}
 | 
			
		||||
      <label name="system.compteurs.experience.value">{{system.compteurs.experience.value}}</label>
 | 
			
		||||
      {{/if}}
 | 
			
		||||
    </li>
 | 
			
		||||
    {{#if options.vueDetaillee}}
 | 
			
		||||
    <li class="item flexrow">
 | 
			
		||||
    <li class="flexrow">
 | 
			
		||||
      <span class="generic-label">Total XP compétences</span>
 | 
			
		||||
      <span class="competence-value">{{calc.competenceXPTotal}}</span>
 | 
			
		||||
    </li>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,19 +2,22 @@
 | 
			
		||||
  <h4 class="rdd-roll-part">{{alias}} réussit une attaque particulière!</strong></h4>
 | 
			
		||||
  {{#if isForce}}
 | 
			
		||||
  <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
 | 
			
		||||
  </a>
 | 
			
		||||
  {{/if}}
 | 
			
		||||
  {{#if isRapide}}
 | 
			
		||||
  <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é
 | 
			
		||||
  </a>
 | 
			
		||||
  {{/if}}
 | 
			
		||||
  {{#if isFinesse}}
 | 
			
		||||
  <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
 | 
			
		||||
  </a>
 | 
			
		||||
  {{/if}}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
<hr>
 | 
			
		||||
<div>
 | 
			
		||||
  {{#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}}
 | 
			
		||||
  {{alias}} n'a pas pu interpréter le signe draconique.
 | 
			
		||||
  {{/if}}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user