diff --git a/module/apps/rdd-import-stats.js b/module/apps/rdd-import-stats.js index c7fb0ab9..1fa1b325 100644 --- a/module/apps/rdd-import-stats.js +++ b/module/apps/rdd-import-stats.js @@ -17,12 +17,20 @@ const XREGEXP_COMP_CREATURE = WHITESPACES + "(?\\d+)" // Skill parser depending on the type of actor const compParser = { - //personnage: "(\\D+)*" + WHITESPACES + NUMERIC_VALUE, - personnage: WHITESPACES + NUMERIC_VALUE, + personnage: "(\\s+\\((?[^\\)]+)\\))?(,\\s*\\p{Letter}+)*(\\s+(?avec armure))?" + WHITESPACES + NUMERIC_VALUE, creature: XREGEXP_COMP_CREATURE, entite: XREGEXP_COMP_CREATURE } +const MANIEMENTS = { + 'de lancer': (weapon) => { return { name: weapon.system.lancer, categorie: 'lancer' } }, + 'de jet': (weapon) => { return { name: weapon.system.lancer, categorie: 'lancer' } }, + 'à une main': (weapon) => { return { name: weapon.system.competence, categorie: 'melee' } }, + 'à deux main': (weapon) => { return { name: weapon.system.competence.replace("à 1 main", "à 2 main"), categorie: 'melee' } }, + 'mêlée': (weapon) => { return { name: weapon.system.competence, categorie: 'melee' } }, +} +const XREGEXP_WEAPON_MANIEMENT = "(?(" + Misc.join(Object.keys(MANIEMENTS), '|') + "))" + const XREGEXP_SORT_VOIE = "(?[OHNT](\\/[OHNT])*)" const XREGEXP_SORT_NAME = "(?[^\\(]+)" const XREGEXP_SORT_CASE = "\\((?([A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+|[A-M]\\d{1,2})+)\\)"; @@ -134,6 +142,9 @@ export class RdDStatBlockParser { // Now start carac let actorData = foundry.utils.deepClone(game.model.Actor[type]); + let items = []; + + actorData.flags = { hautRevant: false, malusArmure: 0 } for (let key in actorData.carac) { let caracDef = actorData.carac[key]; // Parse the stat string for each caracteristic @@ -152,77 +163,18 @@ export class RdDStatBlockParser { RdDStatBlockParser.parseEntite(statString, actorData) break } - - let items = []; - // Get skills from compendium - const competences = await SystemCompendiums.getCompetences(type); - //console.log("Competences : ", competences); - for (let comp of competences) { - let compNameToSearch = RdDStatBlockParser.fixCompName(comp.name) - let compMatch = XRegExp.exec(statString, XRegExp(compNameToSearch + compParser[type], 'giu')); - if (compMatch) { - comp = comp.toObject() - comp.system.niveau = Number(compMatch.value); - if (type == "creature" || type == "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 (type == "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); - } - } - } - } - if (type == "personnage") { // 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); - } - } + await RdDStatBlockParser.parseArmors(statString, actorData, items); + } + // Get skills from compendium + await RdDStatBlockParser.parseCompetences(type, statString, actorData, items); + + + if (type == "personnage") { + // Now process weapons + await RdDStatBlockParser.parseWeapons(statString, items); await RdDStatBlockParser.parseHautReve(statString, actorData, items); RdDStatBlockParser.parsePersonnage(statString, actorData); @@ -230,6 +182,7 @@ export class RdDStatBlockParser { const name = RdDStatBlockParser.extractName(type, statString); + actorData.flags = undefined console.log(actorData); let newActor = await RdDBaseActorReve.create({ name, type, system: actorData, items }); @@ -238,6 +191,92 @@ export class RdDStatBlockParser { await newActor?.sheet.render(true) } + static async parseCompetences(type, statString, actorData, items) { + const competences = await SystemCompendiums.getCompetences(type); + //console.log("Competences : ", competences); + for (let comp of competences) { + let compNameToSearch = RdDStatBlockParser.fixCompName(comp.name); + let compMatch = XRegExp.exec(statString, XRegExp("\\s" + compNameToSearch + compParser[type], 'giu')); + if (compMatch) { + comp = comp.toObject() + comp.system.niveau = Number(compMatch.value) + if (compMatch.malus) { + comp.system.niveau = Number(compMatch.value) - actorData.flags.malusArmure + } + if (comp.system.categorie == 'draconic' && comp.system.niveau > -11) { + actorData.flags.hautRevant = true + } + if (type == "creature" || type == "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 (type == "personnage") { + comp = comp.toObject(); + items.push(comp); + } + } + } + + static async parseArmors(statString, actorData, items) { + 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 + actorData.flags.malusArmure = armor.system.malus + items.push(armor) + break + } + } + } + + static async parseWeapons(statString, items) { + 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 nomArmeManiement = XRegExp.exec(weapon.name, XRegExp(".*" + XREGEXP_WEAPON_MANIEMENT)); + if (nomArmeManiement) { + continue // ignore les objets 'Dague de jet" ou "dague mêlée" + } + let weapMatch = XRegExp.exec(statString, XRegExp(weapon.name + + "(\\s*" + XREGEXP_WEAPON_MANIEMENT + ")?" + + "\\s+(?\\+\\d+)", 'giu')); + if (weapMatch) { + weapon = weapon.toObject(); + weapon.system.equipe = 'true'; + items.push(weapon); + + const niveau = Number(weapMatch.value); + // now process the skill + if (weapMatch?.maniement) { + RdDStatBlockParser.setNiveauCompetenceArme(items, MANIEMENTS[weapMatch.maniement](weapon), niveau) + } + else { + RdDStatBlockParser.setNiveauCompetenceArme(items, { name: weapon.system.competence, categorie: 'melee' }, niveau) + RdDStatBlockParser.setNiveauCompetenceArme(items, { name: weapon.system.tir, categorie: 'tir' }, niveau) + RdDStatBlockParser.setNiveauCompetenceArme(items, { name: weapon.system.lancer, categorie: 'lancer' }, niveau) + } + } + } + } + + static setNiveauCompetenceArme(items, competence, niveau) { + if (competence != "") { + const item = items.find(i => i.system.categorie == competence.categorie && Grammar.equalsInsensitive(i.name, competence.name)) + if (item) { + item.system.niveau = niveau + } + } + } + static async setValeursActuelles(newActor, statString) { const updates = { } @@ -264,7 +303,6 @@ export class RdDStatBlockParser { } 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")); @@ -276,7 +314,7 @@ export class RdDStatBlockParser { const sortName = Grammar.toLowerCaseNoAccent(matchSort.name).trim().replace("’", "'"); let sort = sorts.find(s => Grammar.toLowerCaseNoAccent(s.name) == sortName) if (sort) { - hautRevant = true; + actorData.flags.hautRevant = true sort = sort.toObject(); if (matchSort.bonus && matchSort.bonuscase) { sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}`; @@ -288,7 +326,7 @@ export class RdDStatBlockParser { } }); - if (hautRevant) { + if (actorData.flags.hautRevant) { const donHR = await RdDItemTete.teteDonDeHautReve(); if (donHR) { items.push(donHR.toObject());