swade-fr-content/modules/sw-statblock-parser.js

117 lines
7.6 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const actorText = "OISEAU-TONNERRE\nCe sont les gardiens des Terres de chasse.Ils sont pra - tiquement aussi omniscients que tu pourrais lêtre sans être le Créateur lui - même.Quatre grands oiseaux - ton - nerre anciens habitent quelque part dans le monde des esprits, mais on ne peut jamais les rencontrer, à moins quils ne le veuillent.Les caractéristiques disponibles ici sappliquent aux oiseaux - tonnerre plus jeunes qui volent haut dans le ciel des Terres de chasse.Ces créatures ont lapparence dimmenses et puissants oiseaux de proie, dune majesté absolument terrifiante.Et pourtant, ces gardiens sont lunique raison qui a empêché les mani - tous de prendre le contrôle total du monde des esprits.Les oiseaux - tonnerre ont tendance à être lunatiques et imprévisibles.\nAllure: 8(dé de course d10) Charisme: 0 Trempe: 2\n" +
"TRAITS\n" +
"Agi Âme For Int Vig d10 d8 d10 d6 d8 Compétences : Combat d10, Discrétion d8, Équi- tation d10, Intimidation d8, Pistage d8, Survie d6, Tir d10, Tripes d8. Handicaps : Serment des Anciennes Traditions (Majeur), Têtu. Atouts : Blocage, Esprit totem (variable), Véloce.\nDÉFENSE Parade Résistance 8 7 CAPACITÉS SPÉCIALES Arcane : Chamanisme, Médecine tribale d10, PP 25. Don (étoile filante) : au début dun combat, peut dépen- ser 1 Jeton pour augmenter la portée de ses Atouts de Commandement jusquà la fin du combat. Blanc : +Âme ; rouge : +Âme × 2 ; bleu : +Âme × 3. Esprit totem (chouette) : le coût en PP du pouvoir Ter- reur est divisé par 2 si Relance de Médecine tribale. Esquive : inflige -1 aux attaques à distance. Inspiration : +2 pour annuler Secoué pour les alliés dans un rayon de 5 cases. Leader naturel : peut donner des Jetons aux alliés dans un rayon de 5 cases. Tête froide : agit sur la meilleure de deux cartes dInitiative. Volonté de fer : Intimidation +2, Sarcasme +2, y résister +2.\nACTIONS\nArmure : Médecine tribale d10, PP 2, T, Durée 3 (1/rd), +2 en Armure, -4 avec une Relance. Arc : Tir d10, 2d6, 12/24/48, CdT 1, Munitions 1, 20 flèches. Augmentation/Diminution de Trait : Médecine tri- bale d10, PP 2, Int, Durée 3 (1/rd), +/-1 au type de dé dans un Trait (+/-2 en cas de Relance). Bâton de coup de Crazy Horse : voir p. 66. Pioche un Je- ton la première fois quil touche un adversaire dange- reux, Marque le coup (nécessite Attaque pour toucher, que sur adversaire armé, conscient et dangereux, une seule fois, sans dégâts). Couteau : Combat d12, d10+d4, PA 1. Déflexion: Médecine tribale d10, PP 2, T, Durée 3 (1/rd), -2 pour toucher le sujet, -4 avec une Relance. Frappe : Médecine tribale d10, PP 2, T, Durée 3 (1 / Round), +2 de dégâts sur une arme, +4 avec Relance. Frénésie suprême : peut faire une attaque en Combat supplémentaire. Guérison : Médecine tribale d10, PP 3, T, Durée Inst., soigne une Blessure vieille de moins d1 h. Masse de guerre à lame : Combat d12, d10+d8, PA 2, Parade -1, Maniement à deux mains. Poigne ferme : ignore la pénalité de Plateforme instable. Terreur : Médecine tribale d10, PP 2, Int × 2, Durée Inst., jet de Tripes pour cibles dans GG (-2 si Relance), Ex- tras paniqués, Jokers tirent sur la Table de Terreur. Tireur délite : Tir +2 si pas de mouvement (Visée).Visée : Médecine tribale d10, PP 1, T, Durée 3 (1/rd), pé- nalité dattaque ciblée réduite de 1 (2 sur Relance).\nÉQUIPEMENT Sac médecine, cheval.";
const __attrMapping = {agility: 0, spirit: 1, smarts: 3, vigor:4, strength: 2 }
export class SWDELUXStatBlockParser {
constructor() {
this.parsingTable = {
attributs: { regex: /TRAITS\s*(.*?)\s*Comp/, value: "", attributs: {}, elements: [] },
competences: { regex: /Compétences\s*:\s*(.*?).\s+Handicaps/, value: "", elements: [] },
atouts: { regex: /Atouts\s*:\s*(.*?).\s*DÉFENSE/, value: "", elements: [] },
handicaps: { regex: /Handicaps\s*:\s*(.*?).\s+Atouts/, value: "", elements: [] },
defense: { regex: /nDÉFENSE\s*Parade\s*Résistance\s+(\d+)\s+(\d+)/, parade: 0, resistance: 0 },
capacites: { regex: /CAPACITÉS SPÉCIALES\s*(.*?)\s*ACTIONS|ÉQUIPEMENT|$/, value: "", elements: [] },
actions: { regex: /ACTIONS\s*(.*?)\s*ÉQUIPEMENT|$/, value: "", elements: [] },
equipement: { regex: /ÉQUIPEMENT\s*(.*)$/, value: "", elements: [] }
}
console.log("MODEL", this.model)
}
async parse(actorText) {
let parsingTable = this.parsingTable; // Shortcut
// Cleanup phase and format stat block
let splitted = actorText.split("Allure");
let charDesc = splitted[0]
let statBlock = "Allure : " + splitted[1]
let charName = charDesc.split("\n")[0]
statBlock = statBlock.replace(/\n/g, ' ');
statBlock = statBlock.replace(/- /g, '');
// Add missing section headers, needed to easily parse the stat block
if (!statBlock.includes('CAPACITÉS SPÉCIALES')) {
statBlock += "\nCAPACITÉS SPÉCIALES : ";
}
if (!statBlock.includes('ACTIONS')) {
statBlock += "\nACTIONS : ";
}
if (!statBlock.includes('ÉQUIPEMENT')) {
statBlock += "\nÉQUIPEMENT : ";
}
for (let key in parsingTable) {
let parseData = parsingTable[key]
parseData.key = key;
let match = parseData.regex.exec(statBlock)
//console.log("MATCH", key, match);
if (match && match[1]) {
if (key == "attributs") {
const diceSide = match[1].match(/\d+/g);
parseData.traitMatch = diceSide
console.log("TRAITMATCH", parseData.traitMatch);
}
if (parseData.value == "") {
parseData.value = match[1]
}
if (key == "competences") {
// Utiliser une expression régulière pour extraire chaque compétence et sa valeur de dé
const regex = /([\w\séèàÉ'()-]+)\s+(d\d+)\s*,\s*/g;
let skillDef;
while ((skillDef = regex.exec(match[1])) !== null) {
const skill = skillDef[1].trim();
const value = skillDef[2];
parseData.elements.push({ name: skill, dice: value });
}
console.log("SKILLS", parseData.skills);
}
if (key == "atouts" || key == "handicaps") {
const regex = /([\w\séèàÉ'()-]+)\s*,\s*/g;
let elemDef;
while ((elemDef = regex.exec(match[1])) !== null) {
const name = elemDef[1].trim();
parseData.elements.push({ name });
}
}
if (key == "capacites" || key == "actions") {
const regex = /([\w\séèàÉ'()-]+)\s*:\s*([\w\séèàÉ\d,'()-]+)\s*./g;
let elemDef;
while ((elemDef = regex.exec(match[1])) !== null) {
const name = elemDef[1].trim();
const text = elemDef[2].trim();
parseData.elements.push({ name, text });
}
}
if (key == "equipement") {
const regex = /([\w\séèàÉ$\d'()-]+)\s*[,|.]\s*/g;
let elemDef;
while ((elemDef = regex.exec(match[1])) !== null) {
const name = elemDef[1].trim();
parseData.elements.push({ name });
}
}
if (key == "defense") {
parseData.parade = match[1];
parseData.resistance = match[2];
}
console.log("PARSED", parseData);
}
}
let actor = await Actor.create({name: charName || "PNJ importé", type: "npc", items: []})
let updates = {}
for (let key in __attrMapping) {
let index = __attrMapping[key]
updates[`system.attributes.${key}.die.sides`] = Number(this.parsingTable["attributs"].traitMatch[index])
}
actor.update( updates )
console.log("ACTOR", actor, updates);
}
}