diff --git a/module/apps/rdd-import-stats.js b/module/apps/rdd-import-stats.js index 0f938010..894f594f 100644 --- a/module/apps/rdd-import-stats.js +++ b/module/apps/rdd-import-stats.js @@ -6,6 +6,370 @@ import { Grammar } from "../grammar.js"; import { Misc } from "../misc.js"; import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.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+)?" + ")?" + +// Skill parser depending on the type of actor +const compParser = { + personnage: "(\\D+)*" + WHITESPACES + NUMERIC_VALUE, + creature: XREGEXP_COMP_CREATURE, + entite: XREGEXP_COMP_CREATURE +} + +const XREGEXP_SORT_VOIE = "[OHNT\\/]+" +const XREGEXP_SORT_CASE = "\\((?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\)"; + +const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE + + WHITESPACES + XREGEXP_NAME + + WHITESPACES + XREGEXP_SORT_CASE + + WHITESPACES + "R(?([\\-\\d]+|(\\w|\\s)+))" + + WHITESPACES + "r(?(\\d+(\\+)?|\\s\\w+))" + + "(" + WHITESPACES + "\\+(?\\d+)\\s?%" + WHITESPACES + "en" + WHITESPACES + "(?[A-M]\\d{1,2})" + ")?" + + ")" + + +// Main class for parsing a stat block +export class RdDStatBlockParser { + + static openInputDialog() { + let dialog = new Dialog({ + title: "Import de stats de PNJ/Créatures", + content: ` +
+

Coller le texte de la stat ici

+ +
+ `, + buttons: { + ok: { + label: "OK", + callback: async (html) => { + let statBlock = html.find("#statBlock")[0].value; + await RdDStatBlockParser.parseStatBlock(statBlock); + dialog.close(); + } + }, + cancel: { + label: "Cancel" + } + } + }); + dialog.render(true); + } + + static fixWeirdPDF(statString) { + // Split the statString into lines + let lines = statString.split("\n"); + let newLines = []; + let index = 0; + let nextType = "string"; + // Loop through each line + for (let i = 0; i < lines.length; i++) { + // remove trailing spaces + lines[i] = lines[i].trim(); + // Is it text ? + if (lines[i].match(/^[a-zA-Zéêè\s]+/)) { + if (nextType == "string") { + newLines[index] = lines[i]; + nextType = "number"; + } else { + console.log("Wrong sequence string detected...", lines[i], nextType); + } + } + // Is it a number ? + if (lines[i].match(/^[\d\s]+/)) { + if (nextType == "number") { + newLines[index] = newLines[index] + lines[i]; + nextType = "string"; + index++; + } else { + console.log("Wrong sequence number detected...", lines[i], nextType); + } + } + } + } + + static getHeureKey(heure) { + for (let h of game.system.rdd.config.heuresRdD) { + if (h.label.toLowerCase() == heure.toLowerCase()) { + return h.value; + } + } + return "vaisseau"; + } + + static async parseStatBlock(statString, type = "npc") { + + //statString = statBlock03; + if (!statString) { + return; + } + + // Special function to fix strange/weird copy/paste from PDF readers + // Unused up to now : this.fixWeirdPDF(statString); + + // Replace all endline by space in the statString + statString = statString.replace(/\n/g, " "); + // Remove all multiple spaces + statString = statString.replace(/\s{2,}/g, " "); + // Remove all leading and trailing spaces + statString = statString.trim(); + + // TODO: check for entite + let actorType = RdDStatBlockParser.parseActorType(statString); + + // Now start carac + let actorData = foundry.utils.deepClone(game.model.Actor[actorType]); + for (let key in actorData.carac) { + let caracDef = actorData.carac[key]; + // Parse the stat string for each caracteristic + let carac = XRegExp.exec(statString, XRegExp(caracDef.label + "\\s+(?\\d+)", 'giu')); + if (carac?.value) { + actorData.carac[key].value = Number(carac.value); + } + } + + // If creature we need to setup additionnal fields + switch (actorType) { + case "creature": + RdDStatBlockParser.parseCreature(statString, actorData) + break + case "entite": + RdDStatBlockParser.parseEntite(statString, actorData) + break + } + + let items = []; + // Get skills from compendium + const competences = await SystemCompendiums.getCompetences(actorType); + //console.log("Competences : ", competences); + for (let comp of competences) { + let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[actorType], 'giu')); + if (compMatch) { + comp = comp.toObject() + comp.system.niveau = Number(compMatch.value); + if (actorType == "creature" || actorType == "entite") { + comp.system.carac_value = Number(compMatch.carac); + if (compMatch.dommages != undefined) { + comp.system.dommages = Number(compMatch.dommages); + comp.system.iscombat = true; + } + } + items.push(comp) + } + else if (actorType == "personnage") { + comp = comp.toObject() + items.push(comp) + } + } + + // Now process weapons + const weapons = await SystemCompendiums.getWorldOrCompendiumItems("arme", "equipement") + //console.log("Equipement : ", equipment); + // TODO: les noms d'armes peuvent avoir un suffixe (à une main, lancée) qui détermine la compétence correspondante + // TODO: une arme peut être spécifique ("fourche"), ajouter une compétence dans ces cas là? + for (let weapon of weapons) { + let weapMatch = XRegExp.exec(statString, XRegExp(weapon.name + "\\s+(?\\+\\d+)", 'giu')); + if (weapMatch) { + weapon = weapon.toObject() + weapon.system.equipe = 'true' + items.push(weapon) + // now process the skill + if (weapon.system?.competence != "") { + let wComp = items.find(i => Grammar.equalsInsensitive(i.name, weapon.system.competence)) + if (wComp) { + wComp.system.niveau = Number(weapMatch.value); + } + } + if (weapon.system?.tir != "") { + let wComp = items.find(i => Grammar.equalsInsensitive(i.name, weapon.system.tir)) + if (wComp) { + wComp.system.niveau = Number(weapMatch.value); + } + } + if (weapon.system?.lancer != "") { + let wComp = items.find(i => Grammar.equalsInsensitive(i.name, weapon.system.lancer)) + if (wComp) { + wComp.system.niveau = Number(weapMatch.value); + } + } + } + } + + // Now process armors + const armors = await SystemCompendiums.getWorldOrCompendiumItems("armure", "equipement") + for (let armor of armors) { + let matchArmor = XRegExp.exec(statString, XRegExp(armor.name, 'giu')); + if (matchArmor) { + armor = armor.toObject() + armor.system.equipe = true + items.push(armor); + } + } + + // 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'), + function (matchSort, i) { + let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name)) + if (sort) { + hautRevant = true + sort = sort.toObject(); + if (matchSort.bonus && matchSort.bonuscase) { + 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")) + 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' + + // 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); + } + } + + // 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+(?[\\+\\-]?\\d+)", 'giu')); + if (plusDom?.values) { + actorData.attributs.plusdom.value = Number(plusDom.value); + } + let protection = XRegExp.exec(statString, XRegExp("protection\\s+(?[\\-]?\\d+)", 'giu')); + if (protection?.value) { + actorData.attributs.protection.value = Number(protection.value); + } + let endurance = XRegExp.exec(statString, XRegExp("endurance\\s+(?\\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+(?\\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+(?[\\d\\/]+)", 'giu')); + if (vitesse?.value) { + actorData.attributs.vitesse.value = vitesse.value; + } + } + + static parseEntite(statString, actorData) { + let plusDom = XRegExp.exec(statString, XRegExp("\\+dom\\s+(?[\\+\\-]?\\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+(?\\d+)", 'giu')); + if (endurance?.value) { + actorData.sante.endurance.value = Number(endurance.value); + actorData.sante.endurance.max = Number(endurance.value); + actorData.definition.typeentite = ENTITE_INCARNE + } + let vitesse = XRegExp.exec(statString, XRegExp("vitesse\\s+(?[\\d\\/]+)", 'giu')); + if (vitesse?.value) { + actorData.attributs.vitesse.value = vitesse.value; + } + } + + static parseActorType(statString) { + let niveau = XRegExp.exec(statString, XRegExp("Niveau\\s+(?[\\+\\-]?\\d+)", 'giu')) + let perception = XRegExp.exec(statString, XRegExp("perception\\s+(?\\d+)", 'giu')) + if (perception?.value) { + return "creature" + } + if (niveau?.value) { + return "entite" + } + return "personnage" + } + + static extractName(actorType, statString) { + switch (actorType) { + case "personnage": return RdDStatBlockParser.extractNamePersonnage(statString); + case "creature": return RdDStatBlockParser.extractNameCreature(statString); + } + 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é"); + } +} + /************************************************************************************/ // Some internal test strings let statBlock01 = `+$16(/, baron de Sylvedire, né à l’heure du @@ -197,337 +561,4 @@ Discrétion Vigilance 13 +3 - ` -// Skill parser depending on the type of actor -const compParser = { - personnage: "(\\D+)*\\s+(?[\\+\\-]?\\d+)", - creature: "\\s+(?\\d+)\\s+(?[\\+\\-]?\\d+)\\s?(?\\d+)?\\s+?(?\\+\\d+)?" -}; - -// Main class for parsing a stat block -export class RdDStatBlockParser { - - static openInputDialog() { - let dialog = new Dialog({ - title: "Import de stats de PNJ/Créatures", - content: ` -
-

Coller le texte de la stat ici

- -
- `, - buttons: { - ok: { - label: "OK", - callback: async (html) => { - let statBlock = html.find("#statBlock")[0].value; - await RdDStatBlockParser.parseStatBlock(statBlock); - dialog.close(); - } - }, - cancel: { - label: "Cancel" - } - } - }); - dialog.render(true); - } - - static fixWeirdPDF(statString) { - // Split the statString into lines - let lines = statString.split("\n"); - let newLines = []; - let index = 0; - let nextType = "string"; - // Loop through each line - for (let i = 0; i < lines.length; i++) { - // remove trailing spaces - lines[i] = lines[i].trim(); - // Is it text ? - if (lines[i].match(/^[a-zA-Zéêè\s]+/)) { - if (nextType == "string") { - newLines[index] = lines[i]; - nextType = "number"; - } else { - console.log("Wrong sequence string detected...", lines[i], nextType); - } - } - // Is it a number ? - if (lines[i].match(/^[\d\s]+/)) { - if (nextType == "number") { - newLines[index] = newLines[index] + lines[i]; - nextType = "string"; - index++; - } else { - console.log("Wrong sequence number detected...", lines[i], nextType); - } - } - } - - } - - static getHeureKey(heure) { - for (let h of game.system.rdd.config.heuresRdD) { - if (h.label.toLowerCase() == heure.toLowerCase()) { - return h.value; - } - } - return "vaisseau"; - } - - static async parseStatBlock(statString, type = "npc") { - - //statString = statBlock03; - if (!statString) { - return; - } - - // Special function to fix strange/weird copy/paste from PDF readers - // Unused up to now : this.fixWeirdPDF(statString); - - // Replace all endline by space in the statString - statString = statString.replace(/\n/g, " "); - // Remove all multiple spaces - statString = statString.replace(/\s{2,}/g, " "); - // Remove all leading and trailing spaces - statString = statString.trim(); - - // TODO: check for entite - let actorType = RdDStatBlockParser.parseActorType(statString); - - // Now start carac - let actorData = foundry.utils.deepClone(game.model.Actor[actorType]); - for (let key in actorData.carac) { - let caracDef = actorData.carac[key]; - // Parse the stat string for each caracteristic - let carac = XRegExp.exec(statString, XRegExp(caracDef.label + "\\s+(?\\d+)", 'giu')); - if (carac?.value) { - actorData.carac[key].value = Number(carac.value); - } - } - - // If creature we need to setup additionnal fields - switch (actorType) { - case "creature": - RdDStatBlockParser.parseCreature(statString, actorData) - break - case "entite": - RdDStatBlockParser.parseEntite(statString, actorData) - break - } - - let items = []; - // Get skills from compendium - const competences = await SystemCompendiums.getCompetences(actorType); - //console.log("Competences : ", competences); - let allComp = competences.map(i => i.toObject()) - for (let comp of allComp) { - const compName = comp.name; - let skill = XRegExp.exec(Grammar.toLowerCaseNoAccent(statString), XRegExp(Grammar.toLowerCaseNoAccent(compName) + compParser[actorType], 'giu')); - if (skill) { - comp.system.niveau = Number(skill.value); - if (actorType == "creature") { - comp.system.carac_value = Number(skill.carac); - if (skill.init) { - comp.system.dommages = Number(skill.dommages); - comp.system.iscombat = true; - } - } - } - if (actorType == "personnage" || skill!= undefined){ - items.push(comp) - } - } - - // Now process weapons - const weapons = await SystemCompendiums.getWorldOrCompendiumItems("arme", "equipement") - //console.log("Equipement : ", equipment); - // TODO: les noms d'armes peuvent avoir un suffixe (à une main, lancée) qui détermine la compétence correspondante - // TODO: une arme peut être spécifique ("fourche"), ajouter une compétence dans ces cas là? - for (let w of weapons) { - let weapon = XRegExp.exec(statString, XRegExp(w.name + "\\s+(?\\+\\d+)", 'giu')); - if (weapon) { - w.system.equipe = 'true' - items.push(w.toObject()); - // now process the skill - if (w.system?.competence != "") { - let wComp = items.find(i => Grammar.equalsInsensitive(i.name, w.system.competence)) - if (wComp) { - wComp.system.niveau = Number(weapon.value); - } - } - if (w.system?.tir != "") { - let wComp = items.find(i => Grammar.equalsInsensitive(i.name, w.system.tir)) - if (wComp) { - wComp.system.niveau = Number(weapon.value); - } - } - if (w.system?.lancer != "") { - let wComp = items.find(i => Grammar.equalsInsensitive(i.name, w.system.lancer)) - if (wComp) { - wComp.system.niveau = Number(weapon.value); - } - } - } - } - - // Now process armors - const armors = await SystemCompendiums.getWorldOrCompendiumItems("armure", "equipement") - for (let a of armors) { - let armor = XRegExp.exec(statString, XRegExp(a.name, 'giu')); - if (armor) { - a.system.equipe = true - items.push(a.toObject()); - } - } - - // 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("[OHNT]\\s+(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\s+\\((?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\)\\s+R(?[\\-\\d]+)\\s+r(?\\d+)", 'giu'), - function (match, i) { - let sortCompendium = sorts.find(s => Grammar.equalsInsensitive(s.name, match.name)) - if (sortCompendium) { - hautRevant = true - let sort = sortCompendium.toObject(); - 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")) - if (donHR) { - items.push(donHR.toObject()); - } - } - - 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 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); - } - - // 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+(?[\\+\\-]?\\d+)", 'giu')); - if (plusDom?.values) { - actorData.attributs.plusdom.value = Number(plusDom.value); - } - let protection = XRegExp.exec(statString, XRegExp("protection\\s+(?[\\-]?\\d+)", 'giu')); - if (protection?.value) { - actorData.attributs.protection.value = Number(protection.value); - } - let endurance = XRegExp.exec(statString, XRegExp("endurance\\s+(?\\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+(?\\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+(?[\\d\\/]+)", 'giu')); - if (vitesse?.value) { - actorData.attributs.vitesse.value = vitesse.value; - } - } - - static parseEntite(statString, actorData) { - let plusDom = XRegExp.exec(statString, XRegExp("\\+dom\\s+(?[\\+\\-]?\\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+(?\\d+)", 'giu')); - if (endurance?.value) { - actorData.sante.endurance.value = Number(endurance.value); - actorData.sante.endurance.max = Number(endurance.value); - actorData.definition.typeentite = ENTITE_INCARNE - } - let vitesse = XRegExp.exec(statString, XRegExp("vitesse\\s+(?[\\d\\/]+)", 'giu')); - if (vitesse?.value) { - actorData.attributs.vitesse.value = vitesse.value; - } - } - - static parseActorType(statString) { - let niveau = XRegExp.exec(statString, XRegExp("Niveau\\s+(?[\\+\\-]?\\d+)", 'giu')) - let perception = XRegExp.exec(statString, XRegExp("perception\\s+(?\\d+)", 'giu')) - if (perception?.value) { - return "creature" - } - if (niveau?.value) { - return "entite" - } - return "personnage" - } - - static extractName(actorType, statString) { - switch (actorType) { - case "personnage": return RdDStatBlockParser.extractNamePersonnage(statString); - case "creature": return RdDStatBlockParser.extractNameCreature(statString); - } - 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-competencecreature.js b/module/item-competencecreature.js index 4fefb887..8648d8bd 100644 --- a/module/item-competencecreature.js +++ b/module/item-competencecreature.js @@ -81,7 +81,7 @@ export class RdDItemCompetenceCreature extends Item { static isParade(item) { if (item.type == ITEM_TYPES.competencecreature) { - return armeData.system.categorie_parade || armeData.system.isparade + return item.system.categorie_parade || item.system.isparade } return false } diff --git a/packs_src/competences-creatures/competencecreature_Esquive_eau_Qrg3ADB9LOhGthaO.yml b/packs_src/competences-creatures/competencecreature_Esquive_eau_Qrg3ADB9LOhGthaO.yml new file mode 100644 index 00000000..9700dddc --- /dev/null +++ b/packs_src/competences-creatures/competencecreature_Esquive_eau_Qrg3ADB9LOhGthaO.yml @@ -0,0 +1,35 @@ +name: Esquive eau +type: competencecreature +img: systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp +effects: [] +system: + description: '' + descriptionmj: '' + carac_value: 10 + niveau: 1 + default_diffLibre: 0 + categorie: generale + categorie_parade: '' + iscombat: false + isnaturelle: true + ispossession: false + dommages: 0 + mortalite: mortel + isparade: false +ownership: + default: 0 +folder: null +_stats: + compendiumSource: null + duplicateSource: null + coreVersion: '12.331' + systemId: foundryvtt-reve-de-dragon + systemVersion: 12.0.24 + createdTime: 1733182927319 + modifiedTime: 1733182927336 + lastModifiedBy: Hp9ImM4o9YRTSdfu +flags: {} +_id: Qrg3ADB9LOhGthaO +sort: 1300000 +_key: '!items!Qrg3ADB9LOhGthaO' + diff --git a/packs_src/competences-creatures/competencecreature_Esquive_sol_siPvW3hAMCJbrYvq.yml b/packs_src/competences-creatures/competencecreature_Esquive_sol_siPvW3hAMCJbrYvq.yml new file mode 100644 index 00000000..db5434fb --- /dev/null +++ b/packs_src/competences-creatures/competencecreature_Esquive_sol_siPvW3hAMCJbrYvq.yml @@ -0,0 +1,35 @@ +name: Esquive sol +type: competencecreature +img: systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp +effects: [] +system: + description: '' + descriptionmj: '' + carac_value: 10 + niveau: 1 + default_diffLibre: 0 + categorie: generale + categorie_parade: '' + iscombat: false + isnaturelle: true + ispossession: false + dommages: 0 + mortalite: mortel + isparade: false +ownership: + default: 0 +folder: null +_stats: + compendiumSource: null + duplicateSource: null + coreVersion: '12.331' + systemId: foundryvtt-reve-de-dragon + systemVersion: 12.0.24 + createdTime: 1733182930109 + modifiedTime: 1733182930109 + lastModifiedBy: Hp9ImM4o9YRTSdfu +flags: {} +_id: siPvW3hAMCJbrYvq +sort: 0 +_key: '!items!siPvW3hAMCJbrYvq' + diff --git a/packs_src/competences-creatures/competencecreature_Esquive_vol_3ScoGTkQ0VBOpaX6.yml b/packs_src/competences-creatures/competencecreature_Esquive_vol_3ScoGTkQ0VBOpaX6.yml new file mode 100644 index 00000000..971ad0a4 --- /dev/null +++ b/packs_src/competences-creatures/competencecreature_Esquive_vol_3ScoGTkQ0VBOpaX6.yml @@ -0,0 +1,35 @@ +name: Esquive vol +type: competencecreature +img: systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp +effects: [] +system: + description: '' + descriptionmj: '' + carac_value: 10 + niveau: 1 + default_diffLibre: 0 + categorie: generale + categorie_parade: '' + iscombat: false + isnaturelle: true + ispossession: false + dommages: 0 + mortalite: mortel + isparade: false +ownership: + default: 0 +folder: null +_stats: + compendiumSource: null + duplicateSource: null + coreVersion: '12.331' + systemId: foundryvtt-reve-de-dragon + systemVersion: 12.0.24 + createdTime: 1733182932133 + modifiedTime: 1733182932133 + lastModifiedBy: Hp9ImM4o9YRTSdfu +flags: {} +_id: 3ScoGTkQ0VBOpaX6 +sort: 0 +_key: '!items!3ScoGTkQ0VBOpaX6' +