foundry-dsa41-game/src/module/xml-import/xml-import.mjs

406 lines
13 KiB
JavaScript

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<String>} 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: '<i class="fas fa-file"></i>',
callback: (li) => {
const actorId = li.getAttribute("data-entry-id")
const actor = game.actors.get(actorId)
actor.import()
}
})
})