diff --git a/module/actor-sheet.js b/module/actor-sheet.js index b41baf20..19254bb0 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -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()) } diff --git a/module/actor.js b/module/actor.js index badb3492..ccd83847 100644 --- a/module/actor.js +++ b/module/actor.js @@ -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'] @@ -87,7 +89,7 @@ export class RdDActor extends RdDBaseActorSang { } $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" : ""; } @@ -989,6 +991,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) { diff --git a/module/apps/rdd-import-stats.js b/module/apps/rdd-import-stats.js index 894f594f..bf6c23bc 100644 --- a/module/apps/rdd-import-stats.js +++ b/module/apps/rdd-import-stats.js @@ -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 = "(?" + NUMERIC + ")" -const XREGEXP_NAME = "(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)" const XREGEXP_COMP_CREATURE = WHITESPACES + "(?\\d+)" + WHITESPACES + NUMERIC_VALUE + "(" + WHITESPACES + "(?\\d+)?\\s+?(?[\\+\\-]?\\d+)?" + ")?" @@ -23,10 +23,11 @@ const compParser = { } const XREGEXP_SORT_VOIE = "[OHNT\\/]+" +const XREGEXP_SORT_NAME = "(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-']+)" const XREGEXP_SORT_CASE = "\\((?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\)"; const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE - + WHITESPACES + XREGEXP_NAME + + WHITESPACES + XREGEXP_SORT_NAME + WHITESPACES + XREGEXP_SORT_CASE + WHITESPACES + "R(?([\\-\\d]+|(\\w|\\s)+))" + WHITESPACES + "r(?(\\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,82 +214,89 @@ 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")) + + if (type == "personnage") { + // Attemp to detect spell + await RdDStatBlockParser.parseHautReve(statString, items); + + RdDStatBlockParser.parsePersonnage(statString, actorData); + } + + let name = RdDStatBlockParser.extractName(type, statString); + + let newActor = RdDBaseActorReve.create({ name, type: type, system: actorData, items }); + + // DUmp.... + console.log(actorData); + } + + static async parseHautReve(statString, items) { + 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'), function (matchSort, i) { - let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name)) + let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name)); 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); } }); 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é(?e?) à", 'giu')); - actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin' + static parsePersonnage(statString, actorData) { + let feminin = XRegExp.exec(statString, XRegExp("né(?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*(?[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu')); - actorData.heure = this.getHeureKey(heure?.value || "Vaisseau"); + // Get hour name : heure du XXXXX + let heure = XRegExp.exec(statString, XRegExp("heure (du|de la|des|de l\')\\s*(?[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu')); + actorData.heure = this.getHeureKey(heure?.value || "Vaisseau"); - // Get age - let age = XRegExp.exec(statString, XRegExp("(?\\d+) ans", 'giu')); - if (age?.value) { - actorData.age = Number(age.value); - } - // Get height - let taille = XRegExp.exec(statString, XRegExp("(?\\d+m\\d+)", 'giu')); - if (taille?.value) { - actorData.taille = taille.value; - } - // Get weight - let poids = XRegExp.exec(statString, XRegExp("(?\\d+) kg", 'giu')); - if (poids?.value) { - actorData.poids = poids.value; - } - // Get cheveux - let cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu')); - if (cheveux?.value) { - actorData.cheveux = cheveux.value; - } - // Get yeux - let yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu')); - if (yeux?.value) { - actorData.yeux = yeux.value; - } - - // Get beauty - let beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?\\d+)", 'giu')); - if (beaute?.value) { - actorData.beaute = Number(beaute.value); - } + // Get age + let age = XRegExp.exec(statString, XRegExp("(?\\d+) ans", 'giu')); + if (age?.value) { + actorData.age = Number(age.value); + } + // Get height + let taille = XRegExp.exec(statString, XRegExp("(?\\d+m\\d+)", 'giu')); + if (taille?.value) { + actorData.taille = taille.value; + } + // Get weight + let poids = XRegExp.exec(statString, XRegExp("(?\\d+) kg", 'giu')); + if (poids?.value) { + actorData.poids = poids.value; + } + // Get cheveux + let cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu')); + if (cheveux?.value) { + actorData.cheveux = cheveux.value; + } + // Get yeux + let yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu')); + if (yeux?.value) { + actorData.yeux = yeux.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); + // Get beauty + let beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?\\d+)", 'giu')); + if (beaute?.value) { + actorData.beaute = Number(beaute.value); + } } static parseCreature(statString, actorData) { @@ -350,24 +358,17 @@ 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("(?[\\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("(?[\\p{Letter}\\s\\d]+),", 'giu')); - if (!name?.value) { - name = XRegExp.exec(statString, XRegExp("(?.+)\\s+taille", 'giu')); - } - return Misc.upperFirst(name?.value || "Importé"); - } - - static extractNameCreature(statString) { const name = XRegExp.exec(statString, XRegExp("(?.+)\\s+taille", 'giu')); return Misc.upperFirst(name?.value || "Importé"); } + } /************************************************************************************/ diff --git a/module/item/tete.js b/module/item/tete.js new file mode 100644 index 00000000..f16598cb --- /dev/null +++ b/module/item/tete.js @@ -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 + } +} diff --git a/module/rdd-main.js b/module/rdd-main.js index 5b857b87..64f78328 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -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, diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 59bc9809..01dd562e 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -145,8 +145,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', diff --git a/module/settings/system-compendiums.js b/module/settings/system-compendiums.js index 663b3c5a..fba598ff 100644 --- a/module/settings/system-compendiums.js +++ b/module/settings/system-compendiums.js @@ -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) { diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 58bf0955..9e772304 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -129,11 +129,10 @@
{{#if system.attributs.hautrevant.value}}

Haut rêvant

- {{> "systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.hbs"}} {{else}}

Vous n'avez pas le don de haut-rêve

-

Attribuer la Tête de Dragon 'Don de Haut Rêve' pour rendre le personnage Haut-Rêvant.

- {{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs"}} {{/if}}

diff --git a/templates/actor/haut-revant.html b/templates/actor/haut-revant.hbs similarity index 99% rename from templates/actor/haut-revant.html rename to templates/actor/haut-revant.hbs index 604fca15..74d59386 100644 --- a/templates/actor/haut-revant.html +++ b/templates/actor/haut-revant.hbs @@ -26,7 +26,7 @@ {{/if}} -{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html"}} +{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.html"}} diff --git a/templates/actor/non-haut-revant.hbs b/templates/actor/non-haut-revant.hbs new file mode 100644 index 00000000..c91ed10b --- /dev/null +++ b/templates/actor/non-haut-revant.hbs @@ -0,0 +1,41 @@ +{{#if (not system.attributs.hautrevant.value)}} +

Attribuer la Tête de Dragon + {{#if options.isGM}} + Don de Haut Rêve + {{else}} + 'Don de Haut Rêve' + {{/if}} + pour rendre le personnage Haut-Rêvant.

+{{/if}} +
  • + Seuil de Rêve : + + {{#if options.isGM}} + + {{else}} + {{system.reve.seuil.value}} + {{/if}} + +
  • +
  • + Refoulement : + + {{#if options.isGM}} + + {{else}} + {{system.reve.refoulement.value}} + {{/if}} + +
  • +{{#if system.reve.reve.thanatosused}} +
  • + La prochaine queue est une Ombre + + + +
  • +{{/if}} +
    +{{> "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"}} diff --git a/templates/actor/non-haut-revant.html b/templates/actor/non-haut-revant.html deleted file mode 100644 index 333cf48a..00000000 --- a/templates/actor/non-haut-revant.html +++ /dev/null @@ -1,34 +0,0 @@ -
      -
    • - Seuil de Rêve : - - {{#if options.isGM}} - - {{else}} - {{system.reve.seuil.value}} - {{/if}} - -
    • -
    • - Refoulement : - - {{#if options.isGM}} - - {{else}} - {{system.reve.refoulement.value}} - {{/if}} - -
    • - {{#if system.reve.reve.thanatosused}} -
    • - La prochaine queue est une Ombre - - - -
    • - {{/if}} -
    -
    -{{> "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"}}