12.0.26 - Astrobazzarh le Haut-rêvant #728
@@ -1,4 +1,10 @@
 | 
			
		||||
# 12.0
 | 
			
		||||
## 12.0.26 - Astrobazzarh le Haut-rêvant
 | 
			
		||||
- bouton pour le don de haut-rêve en un clic
 | 
			
		||||
- les compétences de draconic ne sont plus précédées de "Voie de"
 | 
			
		||||
  - migration des compétences & compendiums
 | 
			
		||||
- Correction feuille simplifiée qui ne s'affichait pas en ccas de sort variable
 | 
			
		||||
 | 
			
		||||
## 12.0.24 - Les ajustements d'Astrobazzarh
 | 
			
		||||
- amélioration
 | 
			
		||||
  - meilleure gestion des noms des voies de draconic
 | 
			
		||||
 
 | 
			
		||||
@@ -214,6 +214,8 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
 | 
			
		||||
      });
 | 
			
		||||
      // Boutons spéciaux MJs
 | 
			
		||||
      this.html.find('.forcer-tmr-aleatoire').click(async event => this.actor.reinsertionAleatoire("Action MJ"))
 | 
			
		||||
      this.html.find('.don-de-haut-reve').click(async event => this.actor.addDonDeHautReve())
 | 
			
		||||
      
 | 
			
		||||
      this.html.find('.afficher-tmr').click(async event => this.actor.changeTMRVisible())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,8 @@ import { RdDCoeur } from "./coeur/rdd-coeur.js";
 | 
			
		||||
import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js";
 | 
			
		||||
import { RdDItemArme } from "./item-arme.js";
 | 
			
		||||
import { RdDCombatManager } from "./rdd-combat.js";
 | 
			
		||||
import { RdDItemTete } from "./item/tete.js";
 | 
			
		||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
 | 
			
		||||
 | 
			
		||||
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
 | 
			
		||||
 | 
			
		||||
@@ -53,41 +55,27 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
   * Prepare Character type specific data
 | 
			
		||||
   */
 | 
			
		||||
  prepareActorData() {
 | 
			
		||||
    this.$computeCaracDerivee()
 | 
			
		||||
    this.$computeIsHautRevant()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  $computeCaracDerivee() {
 | 
			
		||||
 | 
			
		||||
    this.system.carac.force.value = Math.min(this.system.carac.force.value, parseInt(this.system.carac.taille.value) + 4);
 | 
			
		||||
    this.system.carac.melee.value = Math.floor((parseInt(this.system.carac.force.value) + parseInt(this.system.carac.agilite.value)) / 2);
 | 
			
		||||
 | 
			
		||||
    this.system.carac.melee.value = Math.floor((this.getForce() + parseInt(this.system.carac.agilite.value)) / 2);
 | 
			
		||||
    this.system.carac.tir.value = Math.floor((parseInt(this.system.carac.vue.value) + parseInt(this.system.carac.dexterite.value)) / 2);
 | 
			
		||||
    this.system.carac.lancer.value = Math.floor((parseInt(this.system.carac.tir.value) + parseInt(this.system.carac.force.value)) / 2);
 | 
			
		||||
    this.system.carac.derobee.value = Math.floor(parseInt(((21 - this.system.carac.taille.value)) + parseInt(this.system.carac.agilite.value)) / 2);
 | 
			
		||||
 | 
			
		||||
    let bonusDomKey = Math.floor((parseInt(this.system.carac.force.value) + parseInt(this.system.carac.taille.value)) / 2);
 | 
			
		||||
    let tailleData = RdDCarac.getCaracDerivee(bonusDomKey);
 | 
			
		||||
    this.system.attributs.plusdom.value = tailleData.plusdom;
 | 
			
		||||
    this.system.attributs.encombrement.value = (parseInt(this.system.carac.force.value) + parseInt(this.system.carac.taille.value)) / 2;
 | 
			
		||||
    super.prepareActorData()
 | 
			
		||||
 | 
			
		||||
    this.system.attributs.sconst.value = RdDCarac.calculSConst(this.system.carac.constitution.value);
 | 
			
		||||
    this.system.attributs.sust.value = RdDCarac.getCaracDerivee(this.system.carac.taille.value).sust;
 | 
			
		||||
    this.system.sante.vie.max = Math.ceil((parseInt(this.system.carac.taille.value) + parseInt(this.system.carac.constitution.value)) / 2);
 | 
			
		||||
    this.system.attributs.sconst.value = RdDCarac.calculSConst(this.getConstitution())
 | 
			
		||||
    this.system.attributs.sust.value = RdDCarac.getCaracDerivee(this.getTaille()).sust
 | 
			
		||||
 | 
			
		||||
    this.system.sante.vie.value = Math.min(this.system.sante.vie.value, this.system.sante.vie.max)
 | 
			
		||||
    this.system.sante.endurance.max = Math.max(parseInt(this.system.carac.taille.value) + parseInt(this.system.carac.constitution.value), parseInt(this.system.sante.vie.max) + parseInt(this.system.carac.volonte.value));
 | 
			
		||||
    this.system.sante.endurance.value = Math.min(this.system.sante.endurance.value, this.system.sante.endurance.max);
 | 
			
		||||
    this.system.sante.fatigue.max = this.getFatigueMax();
 | 
			
		||||
    this.system.sante.fatigue.max = this.getFatigueMax()
 | 
			
		||||
    this.system.sante.fatigue.value = Math.min(this.system.sante.fatigue.value, this.system.sante.fatigue.max);
 | 
			
		||||
 | 
			
		||||
    //Compteurs
 | 
			
		||||
    this.system.reve.reve.max = this.system.carac.reve.value;
 | 
			
		||||
    this.system.compteurs.chance.max = this.system.carac.chance.value;
 | 
			
		||||
  }
 | 
			
		||||
    this.system.reve.reve.max = 3 * this.getReve()
 | 
			
		||||
    this.system.compteurs.chance.max = this.getChance()
 | 
			
		||||
 | 
			
		||||
  $computeIsHautRevant() {
 | 
			
		||||
    this.system.attributs.hautrevant.value = this.itemTypes['tete'].find(it => Grammar.equalsInsensitive(it.name, 'don de haut-reve'))
 | 
			
		||||
    this.system.attributs.hautrevant.value = this.itemTypes[ITEM_TYPES.tete].find(it => RdDItemTete.isDonDeHautReve(it))
 | 
			
		||||
      ? "Haut rêvant"
 | 
			
		||||
      : "";
 | 
			
		||||
  }
 | 
			
		||||
@@ -112,6 +100,8 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
  getChanceActuel() { return this.system.compteurs.chance?.value ?? 10 }
 | 
			
		||||
  getMoralTotal() { return this.system.compteurs.moral?.value ?? 0 }
 | 
			
		||||
 | 
			
		||||
  getEnduranceMax() { return Math.max(1, Math.max(this.getTaille() + this.getConstitution(), this.getVieMax() + this.getVolonte())) }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  getEtatGeneral(options = { ethylisme: false }) {
 | 
			
		||||
    const etatGeneral = this.system.compteurs.etat?.value ?? 0
 | 
			
		||||
@@ -989,6 +979,16 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async addDonDeHautReve() {
 | 
			
		||||
    if (!game.user.isGM || this.isHautRevant()) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    const donHR = await RdDItemTete.teteDonDeHautReve()
 | 
			
		||||
    if (donHR) {
 | 
			
		||||
      this.createEmbeddedDocuments('Item', [donHR.toObject()])
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async reinsertionAleatoire(raison, accessible = tmr => true) {
 | 
			
		||||
@@ -1083,9 +1083,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  getSConst() {
 | 
			
		||||
    return RdDCarac.calculSConst(this.system.carac.constitution.value)
 | 
			
		||||
  }
 | 
			
		||||
  getSConst() { return RdDCarac.calculSConst(this.getConstitution()) }
 | 
			
		||||
 | 
			
		||||
  async ajoutXpConstitution(xp) {
 | 
			
		||||
    await this.update({ "system.carac.constitution.xp": Misc.toInt(this.system.carac.constitution.xp) + xp });
 | 
			
		||||
@@ -1237,16 +1235,14 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false }, userId = undefined) {
 | 
			
		||||
    if (userId != undefined && userId != game.user.id) {
 | 
			
		||||
  async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false }) {
 | 
			
		||||
    if (!this.isOwner) {
 | 
			
		||||
      RdDBaseActor.remoteActorCall({
 | 
			
		||||
        tokenId: this.token?.id,
 | 
			
		||||
        actorId: this.id,
 | 
			
		||||
        method: 'consommerNourritureboisson',
 | 
			
		||||
        args: [itemId, choix, userId]
 | 
			
		||||
      },
 | 
			
		||||
        userId)
 | 
			
		||||
      return;
 | 
			
		||||
        method: 'consommerNourritureboisson', args: [itemId, choix]
 | 
			
		||||
      })
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    const item = this.getItem(itemId)
 | 
			
		||||
    if (!item.getUtilisationCuisine()) {
 | 
			
		||||
@@ -2521,7 +2517,11 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
 | 
			
		||||
  async onRollTachePremiersSoins(blessureId, rollData) {
 | 
			
		||||
    if (!this.isOwner) {
 | 
			
		||||
      return RdDBaseActor.remoteActorCall({ tokenId: this.token?.id, actorId: this.id, method: 'onRollTachePremiersSoins', args: [blessureId, rollData] });
 | 
			
		||||
      return RdDBaseActor.remoteActorCall({
 | 
			
		||||
        tokenId: this.token?.id,
 | 
			
		||||
        actorId: this.id,
 | 
			
		||||
        method: 'onRollTachePremiersSoins', args: [blessureId, rollData]
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    const blessure = this.getItem(blessureId, 'blessure')
 | 
			
		||||
    console.log('TODO update blessure', this, blessureId, rollData, rollData.tache);
 | 
			
		||||
@@ -2551,7 +2551,11 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
 | 
			
		||||
  async onRollSoinsComplets(blessureId, rollData) {
 | 
			
		||||
    if (!this.isOwner) {
 | 
			
		||||
      return RdDBaseActor.remoteActorCall({ tokenId: this.token?.id, actorId: this.id, method: 'onRollSoinsComplets', args: [blessureId, rollData] });
 | 
			
		||||
      return RdDBaseActor.remoteActorCall({
 | 
			
		||||
        tokenId: this.token?.id,
 | 
			
		||||
        actorId: this.id,
 | 
			
		||||
        method: 'onRollSoinsComplets', args: [blessureId, rollData]
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    const blessure = this.getItem(blessureId, 'blessure')
 | 
			
		||||
    if (blessure && blessure.system.premierssoins.done && !blessure.system.soinscomplets.done) {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ import { RdDCombat, RdDCombatManager } from "../rdd-combat.js";
 | 
			
		||||
import { RdDConfirm } from "../rdd-confirm.js";
 | 
			
		||||
import { ENTITE_INCARNE, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
 | 
			
		||||
import { RdDItemArme } from "../item-arme.js";
 | 
			
		||||
import { RdDCarac } from "../rdd-carac.js";
 | 
			
		||||
 | 
			
		||||
const POSSESSION_SANS_DRACONIC = {
 | 
			
		||||
  img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
 | 
			
		||||
@@ -36,6 +37,13 @@ const POSSESSION_SANS_DRACONIC = {
 | 
			
		||||
 */
 | 
			
		||||
export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
 | 
			
		||||
  prepareActorData() {
 | 
			
		||||
    super.prepareActorData()
 | 
			
		||||
    this.system.attributs.plusdom.value = this.getBonusDegat()
 | 
			
		||||
    this.system.sante.endurance.max = this.getEnduranceMax()
 | 
			
		||||
    this.system.sante.endurance.value = Math.min(this.system.sante.endurance.value, this.system.sante.endurance.max)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getCaracChanceActuelle() {
 | 
			
		||||
    return {
 | 
			
		||||
      label: 'Chance actuelle',
 | 
			
		||||
@@ -52,21 +60,26 @@ export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  getTaille() { return Misc.toInt(this.system.carac.taille?.value) }
 | 
			
		||||
  getConstitution() { return this.getReve() }
 | 
			
		||||
  getForce() { return this.getReve() }
 | 
			
		||||
  getAgilite() { return this.getForce() }
 | 
			
		||||
  getReve() { return Misc.toInt(this.system.carac.reve?.value) }
 | 
			
		||||
  getChance() { return this.getReve() }
 | 
			
		||||
 | 
			
		||||
  getReveActuel() { return this.getReve() }
 | 
			
		||||
  getChanceActuel() { return this.getChance() }
 | 
			
		||||
 | 
			
		||||
  getReve() { return Number(this.system.carac.reve?.value ?? 0) }
 | 
			
		||||
  getForce() { return this.getReve() }
 | 
			
		||||
  getTaille() { return Number(this.system.carac.taille?.value ?? 0) }
 | 
			
		||||
  getAgilite() { return this.getForce() }
 | 
			
		||||
  getChance() { return this.getReve() }
 | 
			
		||||
  getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) }
 | 
			
		||||
  getEncombrementMax() { return (this.getForce() + this.getTaille()) / 2 }
 | 
			
		||||
  getBonusDegat() { return RdDCarac.getCaracDerivee(this.getEncombrementMax()).plusdom }
 | 
			
		||||
 | 
			
		||||
  getMoralTotal() { return 0 }
 | 
			
		||||
  getBonusDegat() { return Number(this.system.attributs?.plusdom?.value ?? 0) }
 | 
			
		||||
  getProtectionNaturelle() { return Number(this.system.attributs?.protection?.value ?? 0) }
 | 
			
		||||
  getSConst() { return 0 }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  getEncombrementMax() { return 0 }
 | 
			
		||||
  isSurenc() { return false }
 | 
			
		||||
  computeMalusSurEncombrement() { return 0 }
 | 
			
		||||
 | 
			
		||||
@@ -445,8 +458,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
      RdDBaseActor.remoteActorCall({
 | 
			
		||||
        tokenId: this.token?.id,
 | 
			
		||||
        actorId: this.id,
 | 
			
		||||
        method: 'encaisserDommagesValidationGR',
 | 
			
		||||
        args: [rollData, armure, show, attackerToken, defenderToken]
 | 
			
		||||
        method: 'encaisserDommagesValidationGR', args: [rollData, armure, show, attackerToken, defenderToken]
 | 
			
		||||
      })
 | 
			
		||||
    } else {
 | 
			
		||||
      DialogValidationEncaissement.validerEncaissement(this, rollData, armure,
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import { RdDBaseActorReve } from "./base-actor-reve.js";
 | 
			
		||||
import { RdDDice } from "../rdd-dice.js";
 | 
			
		||||
import { RdDItemBlessure } from "../item/blessure.js";
 | 
			
		||||
import { ChatUtility } from "../chat-utility.js";
 | 
			
		||||
import { Misc } from "../misc.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Classe de base pour les acteurs qui peuvent subir des blessures
 | 
			
		||||
@@ -14,25 +15,32 @@ import { ChatUtility } from "../chat-utility.js";
 | 
			
		||||
 */
 | 
			
		||||
export class RdDBaseActorSang extends RdDBaseActorReve {
 | 
			
		||||
 | 
			
		||||
  prepareActorData() {
 | 
			
		||||
    this.system.sante.vie.max = Math.ceil((this.getTaille() + this.getConstitution()) / 2)
 | 
			
		||||
    this.system.sante.vie.value = Math.min(this.system.sante.vie.value, this.system.sante.vie.max)
 | 
			
		||||
    super.prepareActorData()
 | 
			
		||||
    this.system.attributs.encombrement.value = this.getEncombrementMax()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getForce() { return Number(this.system.carac.force?.value ?? 0) }
 | 
			
		||||
  getForce() { return Misc.toInt(this.system.carac.force?.value) }
 | 
			
		||||
  getConstitution() { return Misc.toInt(this.system.carac.constitution?.value) }
 | 
			
		||||
  getVolonte() { return Misc.toInt(this.system.carac.volonte?.value) }
 | 
			
		||||
 | 
			
		||||
  getBonusDegat() { return Number(this.system.attributs?.plusdom?.value ?? 0) }
 | 
			
		||||
  getProtectionNaturelle() { return Number(this.system.attributs?.protection?.value ?? 0) }
 | 
			
		||||
  getSConst() { return 0 }
 | 
			
		||||
  getVieMax() { return Misc.toInt(this.system.sante.vie?.max) }
 | 
			
		||||
  getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) }
 | 
			
		||||
  getFatigueMax() { return this.getEnduranceMax() * 2 }
 | 
			
		||||
 | 
			
		||||
  getEnduranceMax() { return Math.max(1, Math.min(this.system.sante.endurance.max, MAX_ENDURANCE_FATIGUE)) }
 | 
			
		||||
  getProtectionNaturelle() { return Misc.toInt(this.system.attributs?.protection?.value) }
 | 
			
		||||
 | 
			
		||||
  getFatigueActuelle() {
 | 
			
		||||
    if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
 | 
			
		||||
      return Math.max(0, Math.min(this.getFatigueMax(), this.system.sante.fatigue?.value ?? 0));
 | 
			
		||||
      return Math.max(0, Math.min(this.getFatigueMax(),  Misc.toInt(this.system.sante.fatigue?.value)))
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getFatigueRestante() { return this.getFatigueMax() - this.getFatigueActuelle() }
 | 
			
		||||
  getFatigueMin() { return this.system.sante.endurance.max - this.system.sante.endurance.value }
 | 
			
		||||
  getFatigueMax() { return this.getEnduranceMax() * 2 }
 | 
			
		||||
 | 
			
		||||
  malusFatigue() {
 | 
			
		||||
    if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
 | 
			
		||||
@@ -42,7 +50,6 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  getEncombrementMax() { return Number(this.system.attributs?.encombrement?.value ?? 0) }
 | 
			
		||||
  isSurenc() { return this.computeMalusSurEncombrement() < 0 }
 | 
			
		||||
 | 
			
		||||
  computeMalusSurEncombrement() {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
      .map(it => it[0])
 | 
			
		||||
      .find(it => it)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static $findCaracByName(carac, name) {
 | 
			
		||||
    const caracList = Object.entries(carac);
 | 
			
		||||
    let entry = Misc.findFirstLike(name, caracList, { mapper: it => it[0], description: 'caractéristique' });
 | 
			
		||||
@@ -26,6 +27,16 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
    }
 | 
			
		||||
    return entry && entry.length > 0 ? carac[entry[0]] : undefined;
 | 
			
		||||
  }
 | 
			
		||||
  static getDefaultValue(actorType, path) {
 | 
			
		||||
    if (path.includes('.')) {
 | 
			
		||||
      path = path.split('.')
 | 
			
		||||
    }
 | 
			
		||||
    let obj = game.model.Actor[actorType]
 | 
			
		||||
    for (let p of path) {
 | 
			
		||||
      obj = obj ? obj[p] : undefined
 | 
			
		||||
    }
 | 
			
		||||
    return obj
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static getDefaultImg(itemType) {
 | 
			
		||||
    return game.system.rdd.actorClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
 | 
			
		||||
@@ -45,28 +56,31 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static remoteActorCall(callData, userId = undefined) {
 | 
			
		||||
    userId = userId ?? Misc.firstConnectedGMId();
 | 
			
		||||
    if (userId == game.user.id) {
 | 
			
		||||
      RdDBaseActor.onRemoteActorCall(callData, userId);
 | 
			
		||||
      return false;
 | 
			
		||||
  static remoteActorCall(callData) {
 | 
			
		||||
    if (game.user.isGM) {
 | 
			
		||||
      RdDBaseActor.onRemoteActorCall(callData, game.user.id)
 | 
			
		||||
      return false
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_actor_call", data: callData, userId: userId });
 | 
			
		||||
      return true;
 | 
			
		||||
      game.socket.emit(SYSTEM_SOCKET_ID, {
 | 
			
		||||
        msg: "msg_remote_actor_call",
 | 
			
		||||
        data: callData,
 | 
			
		||||
        userId: Misc.firstConnectedGMId()
 | 
			
		||||
      })
 | 
			
		||||
      return true
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static onRemoteActorCall(callData, userId) {
 | 
			
		||||
    if (userId == game.user.id) {
 | 
			
		||||
    const actor = RdDBaseActor.getRealActor(callData?.actorId, callData?.tokenId);
 | 
			
		||||
      if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
 | 
			
		||||
    if (userId == game.user.id) {
 | 
			
		||||
      // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
 | 
			
		||||
      const args = callData.args;
 | 
			
		||||
      console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
 | 
			
		||||
      actor[callData.method](...args);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  static getRealActor(actorId, tokenId) {
 | 
			
		||||
    if (tokenId) {
 | 
			
		||||
@@ -178,7 +192,8 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
    this.computeEncTotal()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async prepareActorData() { }
 | 
			
		||||
  prepareActorData() { }
 | 
			
		||||
 | 
			
		||||
  async computeEtatGeneral() { }
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  findPlayer() {
 | 
			
		||||
@@ -210,6 +225,9 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
  getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
 | 
			
		||||
  getEncombrementMax() { return 0 }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async updateCarac(caracName, to) {
 | 
			
		||||
  }
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async onPreUpdateItem(item, change, options, id) { }
 | 
			
		||||
  async onCreateItem(item, options, id) { }
 | 
			
		||||
@@ -234,21 +252,20 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async creerObjetParMJ(object) {
 | 
			
		||||
    if (!Misc.isFirstConnectedGM()) {
 | 
			
		||||
    if (this.isOwner) {
 | 
			
		||||
      await this.createEmbeddedDocuments('Item', [object])
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    RdDBaseActor.remoteActorCall({
 | 
			
		||||
      tokenId: this.token?.id,
 | 
			
		||||
      actorId: this.id,
 | 
			
		||||
        method: 'creerObjetParMJ',
 | 
			
		||||
        args: [object]
 | 
			
		||||
      });
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    await this.createEmbeddedDocuments('Item', [object])
 | 
			
		||||
      method: 'creerObjetParMJ', args: [object]
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async cleanupConteneurs() {
 | 
			
		||||
    if (Misc.isOwnerPlayerOrUniqueConnectedGM(this)) {
 | 
			
		||||
    if (Misc.isOwnerPlayer(this)) {
 | 
			
		||||
      let updates = this.itemTypes['conteneur']
 | 
			
		||||
        .filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0)
 | 
			
		||||
        .map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } });
 | 
			
		||||
@@ -319,7 +336,7 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
      ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (fromActorId && !game.user.isGM) {
 | 
			
		||||
    if (fromActorId && !this.isOwner) {
 | 
			
		||||
      RdDBaseActor.remoteActorCall({
 | 
			
		||||
        userId: Misc.connectedGMOrUser(),
 | 
			
		||||
        tokenId: this.token?.id,
 | 
			
		||||
@@ -354,10 +371,9 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
    if (!Misc.isFirstConnectedGM()) {
 | 
			
		||||
      RdDBaseActor.remoteActorCall({
 | 
			
		||||
        actorId: achat.vendeurId ?? achat.acheteurId,
 | 
			
		||||
        method: 'achatVente',
 | 
			
		||||
        args: [achat]
 | 
			
		||||
        method: 'achatVente', args: [achat]
 | 
			
		||||
      });
 | 
			
		||||
      return;
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    const cout = Number(achat.prixTotal ?? 0);
 | 
			
		||||
    const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,9 +25,6 @@ export class RdDCommerce extends RdDBaseActor {
 | 
			
		||||
    }
 | 
			
		||||
    await super.depenserSols(cout)
 | 
			
		||||
  }
 | 
			
		||||
  async consommerNourritureboisson(itemId, choix, userId) { 
 | 
			
		||||
    // ne pas consommer pour un commerce
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async decrementerQuantiteItem(item, quantite) {
 | 
			
		||||
    if (this.system.illimite) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,4 @@
 | 
			
		||||
import { ENTITE_INCARNE } from "../constants.js";
 | 
			
		||||
import { ITEM_TYPES } from "../item.js";
 | 
			
		||||
import { STATUSES } from "../settings/status-effects.js";
 | 
			
		||||
import { RdDBaseActorSang } from "./base-actor-sang.js";
 | 
			
		||||
 | 
			
		||||
export class RdDCreature extends RdDBaseActorSang {
 | 
			
		||||
@@ -9,6 +7,7 @@ export class RdDCreature extends RdDBaseActorSang {
 | 
			
		||||
    return "systems/foundryvtt-reve-de-dragon/icons/creatures/bramart.svg";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getEnduranceMax() { return Math.max(1, this.getVieMax() + this.getConstitution()) }
 | 
			
		||||
  isCreature() { return true }
 | 
			
		||||
 | 
			
		||||
  canReceive(item) {
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ export class RdDEntite extends RdDBaseActorReve {
 | 
			
		||||
  getForce() { return this.getReve() }
 | 
			
		||||
  getAgilite() { return this.getReve() }
 | 
			
		||||
  getChance() { return this.getReve() }
 | 
			
		||||
  getEnduranceMax() { return Math.max(1, this.getTaille() + this.getReve()) }
 | 
			
		||||
 | 
			
		||||
  getDraconicOuPossession() {
 | 
			
		||||
    return this.itemTypes[ITEM_TYPES.competencecreature]
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ const MAPPING_BASE = [
 | 
			
		||||
  { column: "derobee", rollClass: 'roll-carac', colName: 'Dérobée', getter: (actor, context) => actor.system.carac.derobee.value },
 | 
			
		||||
  { column: "vie", getter: (actor, context) => actor.system.sante.vie.max },
 | 
			
		||||
  { column: "endurance", getter: (actor, context) => actor.system.sante.endurance.max },
 | 
			
		||||
  { column: "plusdom", colName: '+dom', getter: (actor, context) => actor.system.attributs.plusdom.value },
 | 
			
		||||
  { column: "plusdom", colName: '+dom', getter: (actor, context) => actor.getBonusDegat() },
 | 
			
		||||
  { column: "protectionnaturelle", colName: 'Protection naturelle', getter: (actor, context) => actor.system.attributs.protection.value > 0 ? actor.system.attributs.protection.value : '' },
 | 
			
		||||
  { column: "description", getter: (actor, context) => Mapping.getDescription(actor) },
 | 
			
		||||
  { column: "armure", getter: (actor, context) => Mapping.getArmure(actor, context) },
 | 
			
		||||
@@ -259,6 +259,9 @@ export class Mapping {
 | 
			
		||||
    const diff = 'R' + RdDItemSort.addSpaceToNonNumeric(sort.system.difficulte)
 | 
			
		||||
    return `${sort.name}${ptSeuil} (${caseTMR}) ${diff} ${coutReve}`
 | 
			
		||||
  }
 | 
			
		||||
  static toVar(caseSpeciale) {
 | 
			
		||||
    return Grammar.toLowerCaseNoAccent(caseSpeciale).startsWith('var') ? 'var' : caseSpeciale
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static bonusCase(sort) {
 | 
			
		||||
    const list = RdDItemSort.stringToBonuscases(sort.system.bonuscase).sort(Misc.descending(it => it.bonus))
 | 
			
		||||
 
 | 
			
		||||
@@ -5,12 +5,12 @@ import { RdDBaseActorReve } from "../actor/base-actor-reve.js";
 | 
			
		||||
import { Grammar } from "../grammar.js";
 | 
			
		||||
import { Misc } from "../misc.js";
 | 
			
		||||
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
 | 
			
		||||
import { RdDItemTete } from "../item/tete.js";
 | 
			
		||||
 | 
			
		||||
const WHITESPACES = "\\s+"
 | 
			
		||||
const NUMERIC = "[\\+\\-]?\\d+"
 | 
			
		||||
const NUMERIC_VALUE = "(?<value>" + NUMERIC + ")"
 | 
			
		||||
 | 
			
		||||
const XREGEXP_NAME = "(?<name>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)"
 | 
			
		||||
const XREGEXP_COMP_CREATURE = WHITESPACES + "(?<carac>\\d+)"
 | 
			
		||||
  + WHITESPACES + NUMERIC_VALUE
 | 
			
		||||
  + "(" + WHITESPACES + "(?<init>\\d+)?\\s+?(?<dommages>[\\+\\-]?\\d+)?" + ")?"
 | 
			
		||||
@@ -22,11 +22,12 @@ const compParser = {
 | 
			
		||||
  entite: XREGEXP_COMP_CREATURE
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const XREGEXP_SORT_VOIE = "[OHNT\\/]+"
 | 
			
		||||
const XREGEXP_SORT_CASE = "\\((?<case>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\)";
 | 
			
		||||
const XREGEXP_SORT_VOIE = "(?<voies>[OHNT](\\/[OHNT])*)"
 | 
			
		||||
const XREGEXP_SORT_NAME = "(?<name>[^\\(]+)"
 | 
			
		||||
const XREGEXP_SORT_CASE = "\\((?<case>([A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+|[A-M]\\d{1,2})+)\\)";
 | 
			
		||||
 | 
			
		||||
const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE
 | 
			
		||||
  + WHITESPACES + XREGEXP_NAME
 | 
			
		||||
  + WHITESPACES + XREGEXP_SORT_NAME
 | 
			
		||||
  + WHITESPACES + XREGEXP_SORT_CASE
 | 
			
		||||
  + WHITESPACES + "R(?<diff>([\\-\\d]+|(\\w|\\s)+))"
 | 
			
		||||
  + WHITESPACES + "r(?<reve>(\\d+(\\+)?|\\s\\w+))"
 | 
			
		||||
@@ -104,7 +105,7 @@ export class RdDStatBlockParser {
 | 
			
		||||
    return "vaisseau";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async parseStatBlock(statString, type = "npc") {
 | 
			
		||||
  static async parseStatBlock(statString) {
 | 
			
		||||
 | 
			
		||||
    //statString = statBlock03;
 | 
			
		||||
    if (!statString) {
 | 
			
		||||
@@ -122,10 +123,10 @@ export class RdDStatBlockParser {
 | 
			
		||||
    statString = statString.trim();
 | 
			
		||||
 | 
			
		||||
    // TODO: check for entite
 | 
			
		||||
    let actorType = RdDStatBlockParser.parseActorType(statString);
 | 
			
		||||
    let type = RdDStatBlockParser.parseActorType(statString);
 | 
			
		||||
 | 
			
		||||
    // Now start carac 
 | 
			
		||||
    let actorData = foundry.utils.deepClone(game.model.Actor[actorType]);
 | 
			
		||||
    let actorData = foundry.utils.deepClone(game.model.Actor[type]);
 | 
			
		||||
    for (let key in actorData.carac) {
 | 
			
		||||
      let caracDef = actorData.carac[key];
 | 
			
		||||
      // Parse the stat string for each caracteristic
 | 
			
		||||
@@ -136,7 +137,7 @@ export class RdDStatBlockParser {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If creature we need to setup additionnal fields 
 | 
			
		||||
    switch (actorType) {
 | 
			
		||||
    switch (type) {
 | 
			
		||||
      case "creature":
 | 
			
		||||
        RdDStatBlockParser.parseCreature(statString, actorData)
 | 
			
		||||
        break
 | 
			
		||||
@@ -147,14 +148,14 @@ export class RdDStatBlockParser {
 | 
			
		||||
 | 
			
		||||
    let items = [];
 | 
			
		||||
    // Get skills from compendium 
 | 
			
		||||
    const competences = await SystemCompendiums.getCompetences(actorType);
 | 
			
		||||
    const competences = await SystemCompendiums.getCompetences(type);
 | 
			
		||||
    //console.log("Competences : ", competences);
 | 
			
		||||
    for (let comp of competences) {
 | 
			
		||||
      let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[actorType], 'giu'));
 | 
			
		||||
      let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[type], 'giu'));
 | 
			
		||||
      if (compMatch) {
 | 
			
		||||
        comp = comp.toObject()
 | 
			
		||||
        comp.system.niveau = Number(compMatch.value);
 | 
			
		||||
        if (actorType == "creature" || actorType == "entite") {
 | 
			
		||||
        if (type == "creature" || type == "entite") {
 | 
			
		||||
          comp.system.carac_value = Number(compMatch.carac);
 | 
			
		||||
          if (compMatch.dommages != undefined) {
 | 
			
		||||
            comp.system.dommages = Number(compMatch.dommages);
 | 
			
		||||
@@ -163,7 +164,7 @@ export class RdDStatBlockParser {
 | 
			
		||||
        }
 | 
			
		||||
        items.push(comp)
 | 
			
		||||
      }
 | 
			
		||||
      else if (actorType == "personnage") {
 | 
			
		||||
      else if (type == "personnage") {
 | 
			
		||||
        comp = comp.toObject()
 | 
			
		||||
        items.push(comp)
 | 
			
		||||
      }
 | 
			
		||||
@@ -213,103 +214,133 @@ export class RdDStatBlockParser {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Attemp to detect spell
 | 
			
		||||
    let hautRevant = false
 | 
			
		||||
    let sorts = await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-oniros")
 | 
			
		||||
    sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-hypnos"))
 | 
			
		||||
    sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-narcos"))
 | 
			
		||||
    sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-thanatos"))
 | 
			
		||||
 | 
			
		||||
    XRegExp.forEach(statString, XRegExp(XREGEXP_SORT, 'giu'),
 | 
			
		||||
    if (type == "personnage") {
 | 
			
		||||
      await RdDStatBlockParser.parseHautReve(statString, actorData, items);
 | 
			
		||||
      RdDStatBlockParser.parsePersonnage(statString, actorData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let name = RdDStatBlockParser.extractName(type, statString);
 | 
			
		||||
 | 
			
		||||
    let newActor = await RdDBaseActorReve.create({ name, type: type, system: actorData, items });
 | 
			
		||||
    await newActor.remiseANeuf()
 | 
			
		||||
    await RdDStatBlockParser.setValActuelle(newActor, statString)
 | 
			
		||||
    // DUmp....
 | 
			
		||||
    console.log(actorData);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async setValActuelle(newActor, statString) {
 | 
			
		||||
    const updates = {
 | 
			
		||||
    }
 | 
			
		||||
    const endurance = XRegExp.exec(statString, XRegExp("endurance\\s+(?<value>\\d+)\\s+(\\(actuelle\\s*:\\s+(?<actuelle>\\d+)\\))?", 'giu'));
 | 
			
		||||
    if (endurance?.value) {
 | 
			
		||||
      if (newActor.getEnduranceMax() != endurance.value) {
 | 
			
		||||
        ui.notifications.warn(`Vérifier le calcul de l'endurance, calcul: ${newActor.getEnduranceMax()} / import: ${endurance.value}`)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (endurance?.actuelle) {
 | 
			
		||||
      updates['system.sante.endurance.value'] = Number(endurance?.actuelle)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const vie = XRegExp.exec(statString, XRegExp("vie\\s+(?<value>\\d+)\\s+(\\(actuelle\\s*:\\s+(?<actuelle>\\d+)\\))?", 'giu'));
 | 
			
		||||
    if (vie?.value) {
 | 
			
		||||
      if (newActor.getVieMax() != vie.value) {
 | 
			
		||||
        ui.notifications.warn(`Vérifier le calcul de la vie, calcul: ${newActor.getVieMax()} / import: ${vie.value}`)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (vie?.actuelle) {
 | 
			
		||||
      updates['system.sante.vie.value'] = Number(vie?.actuelle)
 | 
			
		||||
    }
 | 
			
		||||
    await newActor.update(updates)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async parseHautReve(statString, actorData, items) {
 | 
			
		||||
    let hautRevant = false;
 | 
			
		||||
    // Attemp to detect spell
 | 
			
		||||
    let sorts = await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-oniros");
 | 
			
		||||
    sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-hypnos"));
 | 
			
		||||
    sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-narcos"));
 | 
			
		||||
    sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-thanatos"));
 | 
			
		||||
 | 
			
		||||
    XRegExp.forEach(statString, XRegExp(XREGEXP_SORT, 'gu' /* keep case sensitive to match the spell draconic skill */),
 | 
			
		||||
      function (matchSort, i) {
 | 
			
		||||
        let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name))
 | 
			
		||||
        const sortName = Grammar.toLowerCaseNoAccent(matchSort.name).trim().replace("’", "'");
 | 
			
		||||
        let sort = sorts.find(s => Grammar.toLowerCaseNoAccent(s.name) == sortName)
 | 
			
		||||
        if (sort) {
 | 
			
		||||
          hautRevant = true
 | 
			
		||||
          hautRevant = true;
 | 
			
		||||
          sort = sort.toObject();
 | 
			
		||||
          if (matchSort.bonus && matchSort.bonuscase) {
 | 
			
		||||
            sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}`
 | 
			
		||||
            sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}`;
 | 
			
		||||
          }
 | 
			
		||||
          items.push(sort);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          ui.notifications.warn(`Impossible de trouver le sort ${matchSort.name} / ${sortName}`)
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    if (hautRevant) {
 | 
			
		||||
      let tetes = await SystemCompendiums.getWorldOrCompendiumItems("tete", "tetes-de-dragon-pour-tous-personnages")
 | 
			
		||||
      let donHR = tetes.find(t => Grammar.equalsInsensitive(t.name, "Don de Haut-Rêve"))
 | 
			
		||||
      const donHR = await RdDItemTete.teteDonDeHautReve();
 | 
			
		||||
      if (donHR) {
 | 
			
		||||
        items.push(donHR.toObject());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (actorType == "personnage") {
 | 
			
		||||
 | 
			
		||||
      let feminin = XRegExp.exec(statString, XRegExp("né(?<value>e?) à", 'giu'));
 | 
			
		||||
      actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin'
 | 
			
		||||
      const demiReve = XRegExp.exec(statString, XRegExp("Demi-rêve\\s+(?<value>[A-M]\\d{1,2})", 'giu'))
 | 
			
		||||
      actorData.reve.tmrpos.coord = demiReve?.value ?? 'A1'
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static parsePersonnage(statString, actorData) {
 | 
			
		||||
    actorData.reve.seuil.value = actorData.carac.reve.value
 | 
			
		||||
 | 
			
		||||
    const reveActuel = XRegExp.exec(statString, XRegExp("Rêve actuel\\s+(?<value>\\d+)", 'giu'))
 | 
			
		||||
    actorData.reve.reve.value = reveActuel?.value ? Number(reveActuel.value) : actorData.reve.seuil.value
 | 
			
		||||
 | 
			
		||||
    const feminin = XRegExp.exec(statString, XRegExp("né(?<value>e?) à", 'giu'));
 | 
			
		||||
    actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin';
 | 
			
		||||
 | 
			
		||||
    // Get hour name : heure du XXXXX
 | 
			
		||||
      let heure = XRegExp.exec(statString, XRegExp("heure (du|de la|des|de l\')\\s*(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu'));
 | 
			
		||||
    const heure = XRegExp.exec(statString, XRegExp("heure (du|de la|des|de l\')\\s*(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu'));
 | 
			
		||||
    actorData.heure = this.getHeureKey(heure?.value || "Vaisseau");
 | 
			
		||||
 | 
			
		||||
    // Get age
 | 
			
		||||
      let age = XRegExp.exec(statString, XRegExp("(?<value>\\d+) ans", 'giu'));
 | 
			
		||||
    const age = XRegExp.exec(statString, XRegExp("(?<value>\\d+) ans", 'giu'));
 | 
			
		||||
    if (age?.value) {
 | 
			
		||||
      actorData.age = Number(age.value);
 | 
			
		||||
    }
 | 
			
		||||
    // Get height
 | 
			
		||||
      let taille = XRegExp.exec(statString, XRegExp("(?<value>\\d+m\\d+)", 'giu'));
 | 
			
		||||
    const taille = XRegExp.exec(statString, XRegExp("(?<value>\\d+m\\d+)", 'giu'));
 | 
			
		||||
    if (taille?.value) {
 | 
			
		||||
      actorData.taille = taille.value;
 | 
			
		||||
    }
 | 
			
		||||
    // Get weight
 | 
			
		||||
      let poids = XRegExp.exec(statString, XRegExp("(?<value>\\d+) kg", 'giu'));
 | 
			
		||||
    const poids = XRegExp.exec(statString, XRegExp("(?<value>\\d+) kg", 'giu'));
 | 
			
		||||
    if (poids?.value) {
 | 
			
		||||
      actorData.poids = poids.value;
 | 
			
		||||
    }
 | 
			
		||||
    // Get cheveux
 | 
			
		||||
      let cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu'));
 | 
			
		||||
    const cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu'));
 | 
			
		||||
    if (cheveux?.value) {
 | 
			
		||||
      actorData.cheveux = cheveux.value;
 | 
			
		||||
    }
 | 
			
		||||
    // Get yeux
 | 
			
		||||
      let yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu'));
 | 
			
		||||
    const yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu'));
 | 
			
		||||
    if (yeux?.value) {
 | 
			
		||||
      actorData.yeux = yeux.value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get beauty
 | 
			
		||||
      let beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?<value>\\d+)", 'giu'));
 | 
			
		||||
    const beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?<value>\\d+)", 'giu'));
 | 
			
		||||
    if (beaute?.value) {
 | 
			
		||||
      actorData.beaute = Number(beaute.value);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    // Name is all string before ', né'
 | 
			
		||||
    let name = RdDStatBlockParser.extractName(actorType, statString);
 | 
			
		||||
 | 
			
		||||
    let newActor = RdDBaseActorReve.create({ name: name || "Importé", type: actorType, system: actorData, items: items });
 | 
			
		||||
 | 
			
		||||
    // DUmp....
 | 
			
		||||
    console.log(actorData);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static parseCreature(statString, actorData) {
 | 
			
		||||
    let plusDom = XRegExp.exec(statString, XRegExp("\\+dom\\s+(?<value>[\\+\\-]?\\d+)", 'giu'));
 | 
			
		||||
    if (plusDom?.values) {
 | 
			
		||||
      actorData.attributs.plusdom.value = Number(plusDom.value);
 | 
			
		||||
    }
 | 
			
		||||
    let protection = XRegExp.exec(statString, XRegExp("protection\\s+(?<value>[\\-]?\\d+)", 'giu'));
 | 
			
		||||
    if (protection?.value) {
 | 
			
		||||
      actorData.attributs.protection.value = Number(protection.value);
 | 
			
		||||
    }
 | 
			
		||||
    let endurance = XRegExp.exec(statString, XRegExp("endurance\\s+(?<value>\\d+)", 'giu'));
 | 
			
		||||
    if (endurance?.value) {
 | 
			
		||||
      actorData.sante.endurance.value = Number(endurance.value);
 | 
			
		||||
      actorData.sante.endurance.max = Number(endurance.value);
 | 
			
		||||
    }
 | 
			
		||||
    let vie = XRegExp.exec(statString, XRegExp("vie\\s+(?<value>\\d+)", 'giu'));
 | 
			
		||||
    if (vie.value) {
 | 
			
		||||
      actorData.sante.vie.value = Number(vie.value);
 | 
			
		||||
      actorData.sante.vie.max = Number(vie.value);
 | 
			
		||||
    }
 | 
			
		||||
    let vitesse = XRegExp.exec(statString, XRegExp("vitesse\\s+(?<value>[\\d\\/]+)", 'giu'));
 | 
			
		||||
    if (vitesse?.value) {
 | 
			
		||||
      actorData.attributs.vitesse.value = vitesse.value;
 | 
			
		||||
@@ -317,11 +348,6 @@ export class RdDStatBlockParser {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static parseEntite(statString, actorData) {
 | 
			
		||||
    let plusDom = XRegExp.exec(statString, XRegExp("\\+dom\\s+(?<value>[\\+\\-]?\\d+)", 'giu'));
 | 
			
		||||
    if (plusDom?.values) {
 | 
			
		||||
      actorData.attributs.plusdom.value = Number(plusDom.value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    actorData.definition.categorieentite = 'cauchemar'
 | 
			
		||||
    actorData.definition.typeentite = ENTITE_NONINCARNE
 | 
			
		||||
    let endurance = XRegExp.exec(statString, XRegExp("endurance\\s+(?<value>\\d+)", 'giu'));
 | 
			
		||||
@@ -350,24 +376,21 @@ export class RdDStatBlockParser {
 | 
			
		||||
 | 
			
		||||
  static extractName(actorType, statString) {
 | 
			
		||||
    switch (actorType) {
 | 
			
		||||
      case "personnage": return RdDStatBlockParser.extractNamePersonnage(statString);
 | 
			
		||||
      case "creature": return RdDStatBlockParser.extractNameCreature(statString);
 | 
			
		||||
      case "personnage":
 | 
			
		||||
        // Name is all string before first comma ','
 | 
			
		||||
        const namePersonnage = XRegExp.exec(statString, XRegExp("(?<value>[\\p{Letter}\\s\\d]+),", 'giu'));
 | 
			
		||||
        if (namePersonnage?.value) {
 | 
			
		||||
          return Misc.upperFirst(namePersonnage?.value);
 | 
			
		||||
        }
 | 
			
		||||
    return RdDStatBlockParser.extractNameCreature(statString);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  static extractNamePersonnage(statString) {
 | 
			
		||||
    let name = XRegExp.exec(statString, XRegExp("(?<value>[\\p{Letter}\\s\\d]+),", 'giu'));
 | 
			
		||||
    if (!name?.value) {
 | 
			
		||||
      name = XRegExp.exec(statString, XRegExp("(?<value>.+)\\s+taille", 'giu'));
 | 
			
		||||
    }
 | 
			
		||||
    return Misc.upperFirst(name?.value || "Importé");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static extractNameCreature(statString) {
 | 
			
		||||
    const name = XRegExp.exec(statString, XRegExp("(?<value>.+)\\s+taille", 'giu'));
 | 
			
		||||
    return Misc.upperFirst(name?.value || "Importé");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static warning(message) {
 | 
			
		||||
    ui.notifications.warn(message);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/************************************************************************************/
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								module/item/tete.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								module/item/tete.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
import { Grammar } from "../grammar.js"
 | 
			
		||||
import { ITEM_TYPES, RdDItem } from "../item.js"
 | 
			
		||||
import { SystemCompendiums } from "../settings/system-compendiums.js"
 | 
			
		||||
 | 
			
		||||
const DON_HAUT_REVE = "Don de Haut-Rêve"
 | 
			
		||||
 | 
			
		||||
export class RdDItemTete extends RdDItem {
 | 
			
		||||
 | 
			
		||||
  static get defaultIcon() {
 | 
			
		||||
    return "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static isDonDeHautReve(tete) {
 | 
			
		||||
    return tete.type == ITEM_TYPES.tete && Grammar.equalsInsensitive(tete.name, DON_HAUT_REVE)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async teteDonDeHautReve() {
 | 
			
		||||
    const tetes = await SystemCompendiums.getItems("tetes-de-dragon-pour-tous-personnages", ITEM_TYPES.tete)
 | 
			
		||||
    const tete = tetes.find(it => RdDItemTete.isDonDeHautReve(it))
 | 
			
		||||
    if (!tete) {
 | 
			
		||||
      ui.notifications.warn(`Impossible de trouver la tête "${DON_HAUT_REVE}", vérifiez le compendium de têtes pour tous personnages`)
 | 
			
		||||
    }
 | 
			
		||||
    return tete
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -137,7 +137,7 @@ class _10_0_21_VehiculeStructureResistanceMax extends Migration {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _10_0_33_MigrationNomsDraconic extends Migration {
 | 
			
		||||
  get code() { return "competences-creature-parade"; }
 | 
			
		||||
  get code() { return "competences-nom-draconic"; }
 | 
			
		||||
  get version() { return "10.0.33"; }
 | 
			
		||||
 | 
			
		||||
  migrationNomDraconic(ancien) {
 | 
			
		||||
@@ -530,15 +530,25 @@ class _11_2_20_MigrationAstrologie extends Migration {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _12_0_24_MigrationVoieSorts extends Migration {
 | 
			
		||||
class _12_0_26_MigrationVoieSorts extends Migration {
 | 
			
		||||
  get code() { return "migration-voies-sorts" }
 | 
			
		||||
  get version() { return "12.0.24" }
 | 
			
		||||
  get version() { return "12.0.26" }
 | 
			
		||||
 | 
			
		||||
  async migrate() {
 | 
			
		||||
    await this.applyItemsUpdates(items => items
 | 
			
		||||
      .filter(it => ITEM_TYPES.sort == it.type)
 | 
			
		||||
      .filter(it => [ITEM_TYPES.sort, ITEM_TYPES.sortreserve].includes(it.type))
 | 
			
		||||
      .map(it => this.migrateSort(it))
 | 
			
		||||
    )
 | 
			
		||||
    await this.applyItemsUpdates(items => items
 | 
			
		||||
      .filter(it => ITEM_TYPES.competence == it.type && it.system.categorie == 'draconic')
 | 
			
		||||
      .map(it => this.migrateDraconic(it))
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
  migrateDraconic(it) {
 | 
			
		||||
    return {
 | 
			
		||||
      _id: it.id,
 | 
			
		||||
      name: this.convertDraconic(it.name),
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  migrateSort(it) {
 | 
			
		||||
    return {
 | 
			
		||||
@@ -575,6 +585,7 @@ export class Migrations {
 | 
			
		||||
      new _10_7_19_CategorieCompetenceCreature(),
 | 
			
		||||
      new _10_7_19_PossessionsEntiteVictime(),
 | 
			
		||||
      new _11_2_20_MigrationAstrologie(),
 | 
			
		||||
      new _12_0_26_MigrationVoieSorts()
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -58,9 +58,6 @@ export class Misc {
 | 
			
		||||
   * @param {*} value value to convert to an integer using parseInt
 | 
			
		||||
   */
 | 
			
		||||
  static toInt(value) {
 | 
			
		||||
    if (value == undefined) {
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
    const parsed = parseInt(value);
 | 
			
		||||
    return isNaN(parsed) ? 0 : parsed;
 | 
			
		||||
  }
 | 
			
		||||
@@ -203,11 +200,7 @@ export class Misc {
 | 
			
		||||
    if (!document.testUserPermission){
 | 
			
		||||
      return false
 | 
			
		||||
    }
 | 
			
		||||
    return game.users.filter(u => document.testUserPermission(u, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)) == game.user
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static isOwnerPlayerOrUniqueConnectedGM(actor) {
 | 
			
		||||
    return Misc.isFirstOwnerPlayer(actor) ?? Misc.isFirstConnectedGM();
 | 
			
		||||
    return game.users.find(u => document.testUserPermission(u, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)) == game.user
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ export class RdDCarac {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static getCaracDerivee(value) {
 | 
			
		||||
    return TABLE_CARACTERISTIQUES_DERIVEES[Math.min(Math.max(Number(value), 1), 32)];
 | 
			
		||||
    return TABLE_CARACTERISTIQUES_DERIVEES[Math.min(Math.max(Math.floor(Number(value)), 1), 32)];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static computeTotal(carac, beaute = undefined) {
 | 
			
		||||
 
 | 
			
		||||
@@ -436,7 +436,7 @@ export class RdDCombat {
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static onMsgEncaisser(msg) {
 | 
			
		||||
    let defender = canvas.tokens.get(msg.defenderToken.id).actor;
 | 
			
		||||
    if (Misc.isOwnerPlayerOrUniqueConnectedGM(defender)) {
 | 
			
		||||
    if (Misc.isOwnerPlayer(defender)) {
 | 
			
		||||
      let attackerRoll = msg.attackerRoll;
 | 
			
		||||
      let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined;
 | 
			
		||||
      defender.encaisserDommages(attackerRoll, attacker, msg.attackerToken);
 | 
			
		||||
@@ -1251,7 +1251,7 @@ export class RdDCombat {
 | 
			
		||||
      this._onEchecTotal(defenderRoll);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Misc.isOwnerPlayerOrUniqueConnectedGM(this.defender)) {
 | 
			
		||||
    if (Misc.isOwnerPlayer(this.defender)) {
 | 
			
		||||
      attackerRoll.attackerId = this.attackerId;
 | 
			
		||||
      attackerRoll.defenderTokenId = this.defenderToken.id;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -70,6 +70,7 @@ import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.
 | 
			
		||||
import { RdDActorExportSheet } from "./actor/export-scriptarium/actor-encart-sheet.js"
 | 
			
		||||
import { RdDStatBlockParser } from "./apps/rdd-import-stats.js"
 | 
			
		||||
import { RdDItemSort } from "./item-sort.js"
 | 
			
		||||
import { RdDItemTete } from "./item/tete.js"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * RdD system
 | 
			
		||||
@@ -97,6 +98,7 @@ export class SystemReveDeDragon {
 | 
			
		||||
      ombre: RdDItemOmbre,
 | 
			
		||||
      poison: RdDItemPoison,
 | 
			
		||||
      queue: RdDItemQueue,
 | 
			
		||||
      tete: RdDItemTete,
 | 
			
		||||
      rencontre: RdDRencontre,
 | 
			
		||||
      service: RdDItemService,
 | 
			
		||||
      signedraconique: RdDItemSigneDraconique,
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ import { ExperienceLog } from "./actor/experience-log.js";
 | 
			
		||||
import { RdDCoeur } from "./coeur/rdd-coeur.js";
 | 
			
		||||
import { APP_ASTROLOGIE_REFRESH } from "./sommeil/app-astrologie.js";
 | 
			
		||||
import { RDD_CONFIG } from "./constants.js";
 | 
			
		||||
import { RdDBaseActor } from "./actor/base-actor.js";
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------- */
 | 
			
		||||
// This table starts at 0 -> niveau -10
 | 
			
		||||
@@ -145,8 +146,8 @@ export class RdDUtility {
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html',
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html',
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html',
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html',
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html',
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs',
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.hbs',
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html',
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queue.html',
 | 
			
		||||
      'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html',
 | 
			
		||||
@@ -288,6 +289,8 @@ export class RdDUtility {
 | 
			
		||||
    Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
 | 
			
		||||
    Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
 | 
			
		||||
 | 
			
		||||
    Handlebars.registerHelper('actor-default', (actorType, ...path) => RdDBaseActor.getDefaultValue(actorType, path.slice(0, -1)));
 | 
			
		||||
 | 
			
		||||
    Handlebars.registerHelper('array-includes', (array, value) => array.includes(value));
 | 
			
		||||
    Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
 | 
			
		||||
    Handlebars.registerHelper('isLastIndex', (index, list) => index + 1 >= list.length);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import { ChatUtility } from "../chat-utility.js";
 | 
			
		||||
import { HIDE_DICE, SYSTEM_RDD } from "../constants.js";
 | 
			
		||||
import { Grammar } from "../grammar.js";
 | 
			
		||||
import { RdDItem } from "../item.js";
 | 
			
		||||
import { Misc } from "../misc.js";
 | 
			
		||||
import { RdDDice } from "../rdd-dice.js";
 | 
			
		||||
@@ -84,15 +85,14 @@ export class SystemCompendiums extends FormApplication {
 | 
			
		||||
  static async getWorldOrCompendiumItems(itemType, compendium) {
 | 
			
		||||
    let items = game.items.filter(it => it.type == itemType)
 | 
			
		||||
    if (compendium) {
 | 
			
		||||
      const ids = items.map(it => it.id);
 | 
			
		||||
      const names = items.map(it => it.name.toLowerCase());
 | 
			
		||||
      const compendiumItems = await SystemCompendiums.getItems(compendium);
 | 
			
		||||
      items = items.concat(compendiumItems
 | 
			
		||||
        .filter(it => it.type == itemType)
 | 
			
		||||
      const ids = items.map(it => it.id)
 | 
			
		||||
      const names = items.map(it => Grammar.toLowerCaseNoAccent(it.name))
 | 
			
		||||
      const compendiumItems = await SystemCompendiums.getItems(compendium, itemType)
 | 
			
		||||
      return items.concat(compendiumItems
 | 
			
		||||
        .filter(it => !ids.includes(it.id))
 | 
			
		||||
        .filter(it => !names.includes(it.name.toLowerCase())));
 | 
			
		||||
        .filter(it => !names.includes(Grammar.equalsInsensitive(it.name))))
 | 
			
		||||
    }
 | 
			
		||||
    return items;
 | 
			
		||||
    return items
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async loadDocument(document) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
name: Voie d'Hypnos
 | 
			
		||||
name: Hypnos
 | 
			
		||||
type: competence
 | 
			
		||||
img: systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp
 | 
			
		||||
_id: bt2cR4aE6lIOeg4F
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
name: Voie de Narcos
 | 
			
		||||
name: Narcos
 | 
			
		||||
type: competence
 | 
			
		||||
img: systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp
 | 
			
		||||
_id: u1Peok1EYkBcVsmN
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
name: Voie d'Oniros
 | 
			
		||||
name: Oniros
 | 
			
		||||
type: competence
 | 
			
		||||
img: systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp
 | 
			
		||||
_id: nnR2UHelUaF8dxYn
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
name: Voie de Thanatos
 | 
			
		||||
name: Thanatos
 | 
			
		||||
type: competence
 | 
			
		||||
img: systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp
 | 
			
		||||
_id: dPlTQzvU3CEg5qKc
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "id": "foundryvtt-reve-de-dragon",
 | 
			
		||||
  "title": "Rêve de Dragon",
 | 
			
		||||
  "version": "12.0.24",
 | 
			
		||||
  "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.24/rddsystem.zip",
 | 
			
		||||
  "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download//12.0.24/system.json",
 | 
			
		||||
  "version": "12.0.26",
 | 
			
		||||
  "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.26/rddsystem.zip",
 | 
			
		||||
  "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.26/system.json",
 | 
			
		||||
  "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
 | 
			
		||||
  "compatibility": {
 | 
			
		||||
    "minimum": "11",
 | 
			
		||||
 
 | 
			
		||||
@@ -112,7 +112,7 @@
 | 
			
		||||
            "type": "string",
 | 
			
		||||
            "value": 0,
 | 
			
		||||
            "label": "Vitesse",
 | 
			
		||||
            "derivee": true
 | 
			
		||||
            "derivee": false
 | 
			
		||||
          },
 | 
			
		||||
          "protection": {
 | 
			
		||||
            "type": "number",
 | 
			
		||||
@@ -195,13 +195,13 @@
 | 
			
		||||
            "type": "string",
 | 
			
		||||
            "value": 0,
 | 
			
		||||
            "label": "Vitesse",
 | 
			
		||||
            "derivee": true
 | 
			
		||||
            "derivee": false
 | 
			
		||||
          },
 | 
			
		||||
          "encombrement": {
 | 
			
		||||
            "type": "number",
 | 
			
		||||
            "value": 0,
 | 
			
		||||
            "label": "Encombrement",
 | 
			
		||||
            "derivee": false
 | 
			
		||||
            "derivee": true
 | 
			
		||||
          },
 | 
			
		||||
          "protection": {
 | 
			
		||||
            "type": "number",
 | 
			
		||||
 
 | 
			
		||||
@@ -129,11 +129,10 @@
 | 
			
		||||
        <div>
 | 
			
		||||
          {{#if system.attributs.hautrevant.value}}
 | 
			
		||||
          <h3>Haut rêvant</h3>
 | 
			
		||||
          {{> "systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html"}}
 | 
			
		||||
          {{> "systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.hbs"}}
 | 
			
		||||
          {{else}}
 | 
			
		||||
          <h3>Vous n'avez pas le don de haut-rêve</h3>
 | 
			
		||||
          <p>Attribuer la Tête de Dragon 'Don de Haut Rêve' pour rendre le personnage Haut-Rêvant.</p>
 | 
			
		||||
          {{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html"}}
 | 
			
		||||
          {{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs"}}
 | 
			
		||||
          {{/if}}
 | 
			
		||||
          <br><br>
 | 
			
		||||
        </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,21 @@
 | 
			
		||||
<ol class="carac-list alterne-list">
 | 
			
		||||
  {{#each system.attributs as |attr key|}}
 | 
			
		||||
  {{#if (and (eq key 'plusdom') (eq @root.system.definition.typeentite 'nonincarne'))}}
 | 
			
		||||
  {{else}}
 | 
			
		||||
    <li class="caracteristique flexrow list-item" data-attribute="{{key}}">
 | 
			
		||||
      <span class="carac-label" name="system.attributs.{{key}}.label">{{attr.label}}</span>
 | 
			
		||||
      {{#if (actor-default @root.type 'attributs' key 'derivee')}}
 | 
			
		||||
      <input class="caracteristique streched" type="text" name="system.attributs.{{key}}.value" 
 | 
			
		||||
        {{#if (eq key 'plusdom')}}
 | 
			
		||||
        value="{{numberFormat attr.value decimals=0 sign=true}}"
 | 
			
		||||
        {{else}}
 | 
			
		||||
        value="{{attr.value}}"
 | 
			
		||||
        {{/if}}
 | 
			
		||||
        data-dtype="{{attr.type}}" disabled/>
 | 
			
		||||
      {{else}}
 | 
			
		||||
      <input class="caracteristique streched" type="text" name="system.attributs.{{key}}.value" value="{{attr.value}}" data-dtype="{{attr.type}}" {{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
 | 
			
		||||
      {{/if}}
 | 
			
		||||
    </li>
 | 
			
		||||
    {{/if}}
 | 
			
		||||
  {{/each}}
 | 
			
		||||
</ol>
 | 
			
		||||
 
 | 
			
		||||
@@ -11,10 +11,6 @@
 | 
			
		||||
      {{selectOptions (RDD_CONFIG 'typeEntite') selected=system.definition.typeentite}}
 | 
			
		||||
    </select>
 | 
			
		||||
  </li>
 | 
			
		||||
  {{#each system.attributs as |attr key|}}
 | 
			
		||||
  <li class="caracteristique flexrow list-item" data-attribute="{{key}}">
 | 
			
		||||
    <span class="carac-label" name="system.attributs.{{key}}.label">{{attr.label}} : </span>
 | 
			
		||||
    <input class="caracteristique streched" type="text" name="system.attributs.{{key}}.value" value="{{attr.value}}" data-dtype="{{attr.type}}" {{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
 | 
			
		||||
  </li>
 | 
			
		||||
  {{/each}}
 | 
			
		||||
</ol>
 | 
			
		||||
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.html"}}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,14 @@
 | 
			
		||||
<ul class="carac-list alterne-list">
 | 
			
		||||
  {{#each system.carac as |carac key|}}
 | 
			
		||||
  {{#if (and (eq key 'taille') (eq @root.system.definition.typeentite 'nonincarne'))}}
 | 
			
		||||
  {{else}}
 | 
			
		||||
    <li class="caracteristique flexrow list-item{{#if carac.isLevelUp}} xp-level-up{{/if}}" data-attribute="{{key}}">
 | 
			
		||||
      {{#if (eq key 'taille')}}
 | 
			
		||||
        <span class="carac-label" name="system.carac.{{key}}.label">{{carac.label}}</span>
 | 
			
		||||
        <input class="carac-value" type="text" name="system.carac.{{key}}.value" value="{{carac.value}}" data-dtype="{{carac.type}}" {{#unless @root.options.vueDetaillee}}disabled{{/unless}} />
 | 
			
		||||
        <label class="carac-xp"/>
 | 
			
		||||
      {{else}}
 | 
			
		||||
        {{#if carac.derivee}}
 | 
			
		||||
      {{#if (actor-default @root.type 'carac' key 'derivee')}}
 | 
			
		||||
        <span class="carac-label" name="system.carac.{{key}}.label"><a class="roll-carac" data-carac-name={{key}}>{{carac.label}}</a></span>
 | 
			
		||||
        <label class="competence-value">{{carac.value}}</label>
 | 
			
		||||
        <label class="carac-xp"/>
 | 
			
		||||
@@ -32,5 +34,6 @@
 | 
			
		||||
        {{/if}}
 | 
			
		||||
      {{/if}}
 | 
			
		||||
    </li>
 | 
			
		||||
    {{/if}}
 | 
			
		||||
  {{/each}}
 | 
			
		||||
</ul>
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
  {{/if}}
 | 
			
		||||
  </span> 
 | 
			
		||||
</li>
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html"}}
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs"}}
 | 
			
		||||
<hr>
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.html"}}
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.html"}}
 | 
			
		||||
@@ -5,9 +5,7 @@
 | 
			
		||||
        <a class="jet-vie" name="system.sante.vie.label" data-tooltip="Faire un jet de vie">Vie</a>
 | 
			
		||||
        <a class="vie-moins"><i class="fa-solid fa-square-minus"></i></a>
 | 
			
		||||
        <input class="resource-content" type="text" name="system.sante.vie.value" value="{{system.sante.vie.value}}" data-dtype="Number" />
 | 
			
		||||
        / {{#if @root.options.vueDetaillee}}
 | 
			
		||||
        <input class="resource-content" type="text" name="system.sante.vie.max" value="{{system.sante.vie.max}}" data-dtype="Number"/>
 | 
			
		||||
        {{else}}{{system.sante.vie.max}}{{/if}}
 | 
			
		||||
        / {{system.sante.vie.max}}
 | 
			
		||||
        <a class="vie-plus"><i class="fa-solid fa-square-plus"></i></a>
 | 
			
		||||
      </label>
 | 
			
		||||
    </li>
 | 
			
		||||
@@ -16,9 +14,7 @@
 | 
			
		||||
        <a class="jet-endurance" name="system.sante.endurance.label" data-tooltip="Faire un jet d'endurance pour ne pas être sonné">Endurance</a>
 | 
			
		||||
        <a class="endurance-moins"><i class="fa-solid fa-square-minus"></i></a>
 | 
			
		||||
        <input class="resource-content" type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number"/>
 | 
			
		||||
        / {{#if @root.options.vueDetaillee}}
 | 
			
		||||
        <input class="resource-content" type="text" name="system.sante.endurance.max" value="{{system.sante.endurance.max}}" data-dtype="Number"/>
 | 
			
		||||
        {{else}}{{system.sante.endurance.max}}{{/if}}
 | 
			
		||||
        / {{system.sante.endurance.max}}
 | 
			
		||||
        <a class="endurance-plus"><i class="fa-solid fa-square-plus"></i></a>
 | 
			
		||||
      </label>
 | 
			
		||||
    </li>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,7 @@
 | 
			
		||||
        Endurance
 | 
			
		||||
        <a class="endurance-moins"><i class="fa-solid fa-square-minus"></i></a>
 | 
			
		||||
        <input class="resource-content" type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number" />
 | 
			
		||||
        / {{#if @root.options.vueDetaillee}}
 | 
			
		||||
        <input class="resource-content" type="text" name="system.sante.endurance.max" value="{{system.sante.endurance.max}}" data-dtype="Number"/>
 | 
			
		||||
        {{else}}{{system.sante.endurance.max}}{{/if}}
 | 
			
		||||
        / {{system.sante.endurance.max}}
 | 
			
		||||
        <a class="endurance-plus"><i class="fa-solid fa-square-plus"></i></a>
 | 
			
		||||
      </label>
 | 
			
		||||
    </li>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								templates/actor/non-haut-revant.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								templates/actor/non-haut-revant.hbs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
{{#if (not system.attributs.hautrevant.value)}}
 | 
			
		||||
    <p>Attribuer la Tête de Dragon 
 | 
			
		||||
    {{#if options.isGM}}
 | 
			
		||||
      <a class="chat-card-button don-de-haut-reve" data-tooltip="Donner le don de haut-rêve">Don de Haut Rêve</a>
 | 
			
		||||
    {{else}}
 | 
			
		||||
      'Don de Haut Rêve'
 | 
			
		||||
    {{/if}}
 | 
			
		||||
    pour rendre le personnage Haut-Rêvant.</p>
 | 
			
		||||
{{/if}}
 | 
			
		||||
<li class="item flexrow">
 | 
			
		||||
  <span class="competence-label">Seuil de Rêve :</span>
 | 
			
		||||
  <span>
 | 
			
		||||
  {{#if options.isGM}}
 | 
			
		||||
    <input class="competence-value seuil-reve-value" type="text" name="system.reve.seuil.value" value="{{system.reve.seuil.value}}" data-dtype="Number"/>
 | 
			
		||||
  {{else}}
 | 
			
		||||
    {{system.reve.seuil.value}}
 | 
			
		||||
  {{/if}}
 | 
			
		||||
  </span>
 | 
			
		||||
</li>
 | 
			
		||||
<li class="item flexrow" >
 | 
			
		||||
  <span class="competence-label">Refoulement : </span>
 | 
			
		||||
  <span>
 | 
			
		||||
    {{#if options.isGM}}
 | 
			
		||||
    <input class="competence-value" type="text" name="system.reve.refoulement.value" value="{{system.reve.refoulement.value}}" data-dtype="Number"/>
 | 
			
		||||
    {{else}}
 | 
			
		||||
    {{system.reve.refoulement.value}}
 | 
			
		||||
    {{/if}}
 | 
			
		||||
  </span>
 | 
			
		||||
</li>
 | 
			
		||||
{{#if system.reve.reve.thanatosused}}
 | 
			
		||||
<li class="item flexrow" >
 | 
			
		||||
  <span class="competence-label">La prochaine queue est une Ombre</span>
 | 
			
		||||
  <span>
 | 
			
		||||
    <img class="sheet-competence-img" src="systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp"/>
 | 
			
		||||
  </span>
 | 
			
		||||
</li>
 | 
			
		||||
{{/if}}
 | 
			
		||||
<hr>
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html"}}
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html"}}
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html"}}
 | 
			
		||||
@@ -1,34 +0,0 @@
 | 
			
		||||
<ul class="item-list">
 | 
			
		||||
  <li class="item flexrow">
 | 
			
		||||
    <span class="competence-label">Seuil de Rêve :</span>
 | 
			
		||||
    <span>
 | 
			
		||||
    {{#if options.isGM}}
 | 
			
		||||
      <input class="competence-value seuil-reve-value" type="text" name="system.reve.seuil.value" value="{{system.reve.seuil.value}}" data-dtype="Number"/>
 | 
			
		||||
    {{else}}
 | 
			
		||||
      {{system.reve.seuil.value}}
 | 
			
		||||
    {{/if}}
 | 
			
		||||
    </span>
 | 
			
		||||
  </li>
 | 
			
		||||
  <li class="item flexrow" >
 | 
			
		||||
    <span class="competence-label">Refoulement : </span>
 | 
			
		||||
    <span>
 | 
			
		||||
      {{#if options.isGM}}
 | 
			
		||||
      <input class="competence-value" type="text" name="system.reve.refoulement.value" value="{{system.reve.refoulement.value}}" data-dtype="Number"/>
 | 
			
		||||
      {{else}}
 | 
			
		||||
      {{system.reve.refoulement.value}}
 | 
			
		||||
      {{/if}}
 | 
			
		||||
    </span>
 | 
			
		||||
  </li>
 | 
			
		||||
  {{#if system.reve.reve.thanatosused}}
 | 
			
		||||
  <li class="item flexrow" >
 | 
			
		||||
    <span class="competence-label">La prochaine queue est une Ombre</span>
 | 
			
		||||
    <span>
 | 
			
		||||
      <img class="sheet-competence-img" src="systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp"/>
 | 
			
		||||
    </span>
 | 
			
		||||
  </li>
 | 
			
		||||
  {{/if}}
 | 
			
		||||
</ul>
 | 
			
		||||
<hr>
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html"}}
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html"}}
 | 
			
		||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html"}}
 | 
			
		||||
		Reference in New Issue
	
	Block a user