import {LiturgyData} from "../data/miracle/liturgydata.mjs"; import {BlessingDataModel} from "../data/blessing.mjs"; import {Blessing} from "../documents/blessing.mjs"; let months = [ "Praios", "Rondra", "Efferd", "Travia", "Boron", "Hesinde", "Firun", "Tsa", "Phex", "Peraine", "Ingerimm", "Rahja", "Namenloser Tag" ] /** * Imports a character from a file created in the tool Helden-Software * @param actorId the actor-id of the character * @param file the file from which the character should be imported */ export async function importCharacter(actorId, file) { let actor = game.actors.get(actorId) let xmlString = await parseFileToString(file) let domParser = new DOMParser() let dom = domParser.parseFromString(xmlString, 'application/xml') let rawJson = getJsonFromXML(dom) let characterJson = mapRawJson(actor, rawJson) actor.update(characterJson) } /** * * @param dom the XML-Dom from which the json should be extracted * @returns {{}} the json parsed from the xml */ function getJsonFromXML(dom) { let children = [...dom.children]; // initializing object to be returned. let jsonResult = {}; let attributes = dom.attributes ? dom.attributes : [] for (let attribute of attributes) { jsonResult[attribute.name] = attribute.value } if (children.length) { for (let child of children) { // checking is child has siblings of same name. let childIsArray = children.filter(eachChild => eachChild.nodeName === child.nodeName).length > 1; // if child is array, save the values as array, else as strings. if (childIsArray) { if (jsonResult[child.nodeName] === undefined) { jsonResult[child.nodeName] = [getJsonFromXML(child)]; } else { jsonResult[child.nodeName].push(getJsonFromXML(child)); } } else { jsonResult[child.nodeName] = getJsonFromXML(child); } } } return jsonResult; } async function addSkillFromCompendiumByNameToActor(talentName, taw, actor) { const compendiumOfSkills = game.packs.get('DSA_4-1.talente'); const talentId = compendiumOfSkills.index.find(skill => skill.name === talentName) if (talentId) { const talent = await compendiumOfSkills.getDocument(talentId._id); try { const embeddedDocument = (await actor.createEmbeddedDocuments('Item', [talent]))[0] embeddedDocument.update({system: {taw: taw}}); } catch (error) { console.error(`${talentName} not found in items`, error) } } } async function addAdvantageFromCompendiumByNameToActor(advantageName, advantageValue, actor) { const compendiumOfAdvantages = game.packs.get('DSA_4-1.Advantage'); const advantageId = compendiumOfAdvantages.index.find(skill => skill.name === advantageName) if (advantageId) { const advantage = await compendiumOfAdvantages.getDocument(advantageId._id); try { const embeddedDocument = (await actor.createEmbeddedDocuments('Item', [advantage]))[0] embeddedDocument.update({system: {value: advantageValue}}); } catch (error) { console.error(`${advantageName} not found in items`, error) } } } async function addSpellsFromCompendiumByNameToActor(spellName, zfw, representation, hauszauber, actor) { const compendiumOfSpells = game.packs.get('DSA_4-1.spells'); const SCREAMING_NAME = spellName.toUpperCase() const spellId = compendiumOfSpells.index.find(spell => spell.name === SCREAMING_NAME) if (spellId) { const spell = await compendiumOfSpells.getDocument(spellId._id); try { const embeddedDocument = (await actor.createEmbeddedDocuments('Item', [spell]))[0] embeddedDocument.update({system: {zfw: zfw, hauszauber: hauszauber, repräsentation: representation}}); } catch (error) { console.error(`${spell} not found in items`, error) } } } async function addLiturgiesFromCompendiumByNameToActor(liturgyName, actor) { const compendiumOfLiturgies = game.packs.get('DSA_4-1.liturgien'); const liturgyId = compendiumOfLiturgies.index.find(liturgy => { return liturgy.name === LiturgyData.lookupAlias(liturgyName.split(" (")[0]) }) if (liturgyId) { const liturgy = await compendiumOfLiturgies.getDocument(liturgyId._id); try { await actor.createEmbeddedDocuments('Item', [liturgy]) } catch (error) { console.error(`${liturgy} not found in items`, error) } } } /** * gets the text content of a file * @param file the file with the desired content * @returns {Promise} a promise that returns the string contents of the file */ async function parseFileToString(file) { return new Promise((resolve, reject) => { let reader = new FileReader() reader.readAsText(file, "utf-8") reader.onload = event => { resolve(event.target.result) } reader.onerror = event => { reject(event) } }) } /** *Calculates a Birthdate String in the Calendar of Bosparans Fall * @param json json with the day, the month and the year of the birthday * @returns {string} a string in the format of "DD.MMMM.YYYY BF" */ function calculateBirthdate(json) { let day = json.gbtag let month = months[parseInt(json.gbmonat) - 1] let year = json.gbjahr return `${day}. ${month} ${year} BF` } function mapSkills(actor, held) { for (let talent in held.talentliste.talent) { talent = held.talentliste.talent[talent] // hook liturgy if (talent.name.startsWith("Liturgiekenntnis")) { actor.createEmbeddedDocuments('Item', [ new Blessing({ name: talent.name, type: "Blessing", system: { gottheit: new RegExp("\\((.+)\\)").exec(talent.name)[1], wert: talent.value } }) ]) } else { // proceed addSkillFromCompendiumByNameToActor(talent.name, talent.value, actor) } } } function mapAdvantages(actor, held) { for (let advantage in held.vt.vorteil) { advantage = held.vt.vorteil[advantage] addAdvantageFromCompendiumByNameToActor(advantage.name, advantage.value, actor) } } function mapSpells(actor, held) { for (let spell in held.zauberliste.zauber) { spell = held.zauberliste.zauber[spell] addSpellsFromCompendiumByNameToActor(spell.name, spell.value, spell.repraesentation, spell.hauszauber === "true", actor) } } function mapMiracles(actor, liturgies) { for (let liturgy in liturgies) { liturgy = liturgies[liturgy] addLiturgiesFromCompendiumByNameToActor(liturgy.name, actor) } } /** * parses a json into a fitting character-json * @param rawJson the json parsed from the Helden-Software XML * @returns {{}} a json representation of the character */ function mapRawJson(actor, rawJson) { let json = {} let held = rawJson.helden.held; json.name = held.name json.meta = {} json.meta.spezies = held.basis.rasse.string json.meta.kultur = held.basis.kultur.string let professions = [] for (let profession in held.basis.ausbildungen.ausbildung) { profession = held.basis.ausbildungen.ausbildung[profession] if (profession.tarnidentitaet) { professions = [profession.tarnidentitaet] break; } let professionString = profession.string professions.push(professionString) } json.meta.professions = professions json.meta.geschlecht = held.basis.geschlecht.name json.meta.haarfarbe = held.basis.rasse.aussehen.haarfarbe json.meta.groesse = held.basis.rasse.groesse.value json.meta.augenfarbe = held.basis.rasse.aussehen.augenfarbe json.meta.geburtstag = calculateBirthdate(held.basis.rasse.aussehen) json.meta.alter = held.basis.rasse.aussehen.alter json.meta.gewicht = held.basis.rasse.groesse.gewicht json.meta.aussehen = [ held.basis.rasse.aussehen.aussehentext0, held.basis.rasse.aussehen.aussehentext1, held.basis.rasse.aussehen.aussehentext2, held.basis.rasse.aussehen.aussehentext3, ] json.meta.familie = [ held.basis.rasse.aussehen.familietext0, held.basis.rasse.aussehen.familietext1, held.basis.rasse.aussehen.familietext2, held.basis.rasse.aussehen.familietext3, held.basis.rasse.aussehen.familietext4, held.basis.rasse.aussehen.familietext5, ] json.meta.titel = held.basis.rasse.aussehen.titel json.meta.stand = held.basis.rasse.aussehen.stand let attributes = held.eigenschaften.eigenschaft json.attribute = {} if (held.basis.gilde) { json.attribute.gilde = held.basis.gilde.name } json.attribute.mu = getAttributeJson(attributes, "Mut") json.attribute.kl = getAttributeJson(attributes, "Klugheit") json.attribute.in = getAttributeJson(attributes, "Intuition") json.attribute.ch = getAttributeJson(attributes, "Charisma") json.attribute.ff = getAttributeJson(attributes, "Fingerfertigkeit") json.attribute.ge = getAttributeJson(attributes, "Gewandtheit") json.attribute.ko = getAttributeJson(attributes, "Konstitution") json.attribute.kk = getAttributeJson(attributes, "Körperkraft") json.mr = { mod: filterAttribute(attributes, "Magieresistenz").mod } json.lep = { mod: filterAttribute(attributes, "Lebensenergie").mod } json.aup = { mod: filterAttribute(attributes, "Ausdauer").mod } json.asp = { mod: filterAttribute(attributes, "Astralenergie").mod } json.kap = { mod: filterAttribute(attributes, "Karmaenergie").mod } let attribute = filterAttribute(attributes, "Karmaenergie") attribute = filterAttribute(attributes, "ini") json.ini = { mod: attribute.mod, aktuell: attribute.value } json.attribute.so = getAttributeJson(attributes, "Sozialstatus") mapAdvantages(actor, held) let specialAbilities = [] let liturgies = [] for (let specialAbility in held.sf.sonderfertigkeit) { specialAbility = held.sf.sonderfertigkeit[specialAbility] if (specialAbility.name.startsWith("Liturgie:")) { liturgies.push({ name: specialAbility.name.replace("Liturgie:", "").trim(), }) } else { let specialAbilityJson = { name: specialAbility.name, auswahlen: [] } let fields = Object.keys(specialAbility) if (fields.length > 1) { for (let field in fields) { field = fields[field] if (field !== "name") { let choices = specialAbility[field] if (choices.hasOwnProperty("name")) { specialAbilityJson.auswahlen.push(choices.name) } else { for (let choice in choices.wahl) { choice = choices.wahl[choice] specialAbilityJson.auswahlen.push(choice.value) } } } } } specialAbilities.push(specialAbilityJson) } } json.sonderfertigkeiten = specialAbilities json.liturgien = liturgies mapSkills(actor, held) mapSpells(actor, held) mapMiracles(actor, liturgies) let combatValues = [] for (let combatValue in held.kampf.kampfwerte) { combatValue = held.kampf.kampfwerte[combatValue] combatValues.push({ name: combatValue.name, at: combatValue.attacke.value, pa: combatValue.parade.value, }) } json.kampfwerte = combatValues let notes = [] for (let note in held.kommentare) { note = held.kommentare[note] if (note.hasOwnProperty("key")) { notes.push({ key: note.key, notiz: note.kommentar, }) } } json.notizen = notes return { name: held.name, system: json, } } /** * * @param attributes an array with the attributes * @param name the name of the chosen attribute * @returns {{}} a representation of the chosen Attribute */ function getAttributeJson(attributes, name) { let attribute = filterAttribute(attributes, name) return { start: parseInt(attribute.startwert), aktuell: parseInt(attribute.value), mod: parseInt(attribute.mod), } } /** * filters a given attribute array based on the name of an attribute * @param attributes the attribute array * @param name the name of the desired attribute * @returns {{}} the json of the desired attribute */ function filterAttribute(attributes, name) { return attributes.filter(attribute => attribute.name === name)[0] } Hooks.on("getActorContextOptions", (application, menuItems) => { menuItems.push({ name: "Import from XML", icon: '', callback: (li) => { const actorId = li.getAttribute("data-entry-id") const actor = game.actors.get(actorId) actor.import() } }) })