From 5792e828135d119f3a449823f0fd3ed51199223a Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 21:34:28 +0200 Subject: [PATCH 01/21] added character import --- src/module/Actors/dsa-actor.mjs | 10 + src/module/character/character.mjs | 119 ++++++-- src/module/character/example-character.xml | 93 ++++++- src/module/xml-import/xml-import.mjs | 301 +++++++++++++++++++++ 4 files changed, 490 insertions(+), 33 deletions(-) create mode 100644 src/module/xml-import/xml-import.mjs diff --git a/src/module/Actors/dsa-actor.mjs b/src/module/Actors/dsa-actor.mjs index da6bcce9..2ddd9ad9 100644 --- a/src/module/Actors/dsa-actor.mjs +++ b/src/module/Actors/dsa-actor.mjs @@ -1,3 +1,13 @@ export class DsaActor extends Actor { + import() { + let input = document.createElement('input') + input.type = 'file' + input.accept = '.xml' + input.onchange = e => { + importCharacter(this.id, e.target.files[0]) + } + input.click() + } + } \ No newline at end of file diff --git a/src/module/character/character.mjs b/src/module/character/character.mjs index a483d6d7..906a1c1a 100644 --- a/src/module/character/character.mjs +++ b/src/module/character/character.mjs @@ -10,7 +10,7 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { meta: new SchemaField({ spezies: new StringField(), kultur: new StringField(), - profession: new StringField(), + professions: new ArrayField(new StringField()), geschlecht: new StringField(), haarfarbe: new StringField(), groesse: new NumberField({ required: true, integer: false }), @@ -18,41 +18,112 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { geburtstag: new StringField(), alter: new NumberField({ required: true, integer: true }), gewicht: new NumberField({ required: true, integer: true }), + aussehen: new ArrayField(new StringField()), + familie: new ArrayField(new StringField()), + titel: new StringField(), + stand: new StringField(), }), attribute: new SchemaField({ - mu: new NumberField({ required: true, integer: true }), - kl: new NumberField({ required: true, integer: true }), - in: new NumberField({ required: true, integer: true }), - ch: new NumberField({ required: true, integer: true }), - ff: new NumberField({ required: true, integer: true }), - ge: new NumberField({ required: true, integer: true }), - ko: new NumberField({ required: true, integer: true }), - kk: new NumberField({ required: true, integer: true }), - mr: new NumberField({ required: true, integer: true }), - lep: new NumberField({ required: true, integer: true }), - aup: new NumberField({ required: true, integer: true }), - asp: new NumberField({ required: false, integer: true }), - kap: new NumberField({ required: false, integer: true }), - at: new NumberField({ required: true, integer: true }), - pa: new NumberField({ required: true, integer: true }), - fk: new NumberField({ required: true, integer: true }), - ini: new NumberField({ required: true, integer: true }), - so: new NumberField({ required: true, integer: true }), + mu: new SchemaField({ + start: new NumberField({ required: true, integer: true }), + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + kl: new SchemaField({ + start: new NumberField({ required: true, integer: true }), + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + in: new SchemaField({ + start: new NumberField({ required: true, integer: true }), + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + ch: new SchemaField({ + start: new NumberField({ required: true, integer: true }), + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + ff: new SchemaField({ + start: new NumberField({ required: true, integer: true }), + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + ge: new SchemaField({ + start: new NumberField({ required: true, integer: true }), + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + ko: new SchemaField({ + start: new NumberField({ required: true, integer: true }), + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + kk: new SchemaField({ + start: new NumberField({ required: true, integer: true }), + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + mr: new SchemaField({ + mod: new NumberField({ required: true, integer: true }), + }), + lep: new SchemaField({ + mod: new NumberField({ required: true, integer: true }), + }), + aup: new SchemaField({ + mod: new NumberField({ required: true, integer: true }), + }), + asp: new SchemaField({ + mod: new NumberField({ required: true, integer: true }), + }), + kap: new SchemaField({ + mod: new NumberField({ required: true, integer: true }), + }), + at: new SchemaField({ + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + pa: new SchemaField({ + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + fk: new SchemaField({ + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + ini: new SchemaField({ + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), + so: new SchemaField({ + start: new NumberField({ required: true, integer: true }), + aktuell: new NumberField({ required: true, integer: true }), + mod: new NumberField({ required: true, integer: true }), + }), gilde: new StringField(), }), + vornachteile: new ArrayField(new SchemaField({ + name: new SchemaField(), + value: new NumberField(), + })), + sonderfertigkeiten: new ArrayField(new SchemaField({ + name: new SchemaField(), + auswahlen: new ArrayField(new StringField()), + })), talente: new ArrayField(new SchemaField({ name: new StringField(), taw: new NumberField({required: true, integer: true }), - kategorie: new StringField(), probe: new StringField(), + be: new NumberField({required: false, integer: true }), + komplexitaet: new NumberField({required: false, integer: true }), })), zauber: new ArrayField(new SchemaField({ name: new StringField(), rep: new StringField(), - merkmale: new ArrayField(new StringField()), hauszauber: new BooleanField(), zfw: new NumberField({ required: true, integer: true }), - quelle: new StringField(), + anmerkungen: new StringField(), + komplexitaet: new NumberField({required: true, integer: true }), })), liturgien: new ArrayField(new SchemaField({ name: new StringField(), @@ -62,6 +133,10 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { at: new NumberField({ required: true, integer: true }), pa: new NumberField({ required: true, integer: true }), })), + notizen: new ArrayField(new SchemaField({ + key: new StringField(), + notiz: new StringField(), + })) } } diff --git a/src/module/character/example-character.xml b/src/module/character/example-character.xml index 01738fc7..f636eace 100644 --- a/src/module/character/example-character.xml +++ b/src/module/character/example-character.xml @@ -1,6 +1,6 @@ - + @@ -13,15 +13,17 @@ - + + string="Akademie der Magischen Rüstung zu Gareth " tarnidentitaet="Depp vom Dienst"> - + @@ -73,6 +75,13 @@ + + + + + + + @@ -90,6 +99,13 @@ + + + + + + + @@ -257,6 +273,59 @@ text="Sonderfertigkeit hinzugefügt" time="1758728180962" version="HS 5.5.3"/> + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -320,8 +389,9 @@ value="6"/> - - + + + @@ -506,6 +576,7 @@ + @@ -542,10 +613,10 @@ - D/lXw741ikWhJ+dIE/eCcUgT5vw= + a1RMsniSGUvFk5vUM6faRb5HF7M= - Yo5RyWxO8N8Z0ReQlPhESaEjbpFUFTANob25mAXlFTH0eCBano63WQ== + IoH2tMVRNhVL5zF5VrhsiYRdosA0GopNsJMf4tFpYVi5yPW6RhGqNQ== diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs new file mode 100644 index 00000000..cdb093b1 --- /dev/null +++ b/src/module/xml-import/xml-import.mjs @@ -0,0 +1,301 @@ +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 + */ +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(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 + 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; +} + +/** + * 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.error = 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` +} + +/** + * 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(rawJson) { + let json = {} + with (rawJson.held) { + json.name = name + json.meta = {} + json.meta.spezies = basis.rasse.string + json.meta.kultur = basis.kultur.string + let professions = [] + for (ausbildung in basis.ausbildungen) { + if (ausbildung.tarnidentitaet) { + professions = [ausbildung.tarnidentitaet] + break; + } + let ausbildungString = ausbildung.string + professions.push(ausbildungString) + } + json.meta.profession = professions + json.geschlecht = basis.geschlecht.name + json.haarfarbe = basis.rasse.aussehen.haarfarbe + json.groesse = basis.rasse.groesse.value + json.augenfarbe = basis.rasse.aussehen.augenfarbe + json.geburtstag = calculateBirthdate(basis.rasse.aussehen) + json.alter = basis.rasse.aussehen.alter + json.gewicht = basis.rasse.groesse.gewicht + json.aussehen = [ + basis.rasse.aussehen.aussehentext0, + basis.rasse.aussehen.aussehentext1, + basis.rasse.aussehen.aussehentext2, + basis.rasse.aussehen.aussehentext3, + ] + json.familie = [ + basis.rasse.aussehen.familietext0, + basis.rasse.aussehen.familietext1, + basis.rasse.aussehen.familietext2, + basis.rasse.aussehen.familietext3, + basis.rasse.aussehen.familietext4, + basis.rasse.aussehen.familietext5, + ] + json.titel = basis.rasse.aussehen.titel + json.stand = basis.rasse.aussehen.stand + json.attribute = {} + json.attribute.mu = getAttributeJson(eigenschaften, "Mut") + json.attribute.kl = getAttributeJson(eigenschaften, "Klugheit") + json.attribute.in = getAttributeJson(eigenschaften, "Intuition") + json.attribute.ch = getAttributeJson(eigenschaften, "Charisma") + json.attribute.ff = getAttributeJson(eigenschaften, "Fingerfertigkeit") + json.attribute.ge = getAttributeJson(eigenschaften, "Gewandtheit") + json.attribute.ko = getAttributeJson(eigenschaften, "Konstitution") + json.attribute.kk = getAttributeJson(eigenschaften, "Körperkraft") + json.attribute.mr = { + mod: filterAttribute(eigenschaften ,"Magieresistenz").mod + } + json.attribute.lep = { + mod: filterAttribute(eigenschaften ,"Lebensenergie").mod + } + json.attribute.aup = { + mod: filterAttribute(eigenschaften ,"Ausdauer").mod + } + json.attribute.asp = { + mod: filterAttribute(eigenschaften ,"Astralenergie").mod + } + json.attribute.kap = { + mod: filterAttribute(eigenschaften ,"Karmaenergie").mod + } + let attribute = filterAttribute(eigenschaften ,"Karmaenergie") + json.attribute.at = { + mod: attribute.mod, + aktuell: attribute.value + } + attribute = filterAttribute(eigenschaften ,"at") + json.attribute.pa = { + mod: attribute.mod, + aktuell: attribute.value + } + attribute = filterAttribute(eigenschaften ,"pa") + json.attribute.at = { + mod: attribute.mod, + aktuell: attribute.value + } + attribute = filterAttribute(eigenschaften ,"fk") + json.attribute.fk = { + mod: attribute.mod, + aktuell: attribute.value + } + attribute = filterAttribute(eigenschaften ,"ini") + json.attribute.ini = { + mod: attribute.mod, + aktuell: attribute.value + } + json.attribute.so = getAttributeJson(eigenschaften, "Sozialstatus") + let specialAbilities = [] + let liturgies = [] + for (specialAbility in sf) { + 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 (field in fields) { + if (field !== "name") { + let choices = specialAbility[field] + if (choices.hasOwnProperty("name")) { + specialAbilityJson.auswahlen.push(choices.name) + } else { + for (choice in choices) { + specialAbilityJson.auswahlen.push(choice.value) + } + } + } + } + } + specialAbilities.push(specialAbilityJson) + } + } + json.sonderfertigkeiten = specialAbilities + json.liturgien = liturgies + let talents = [] + for (talent in talentliste) { + talents.push({ + name: talent.name, + taw: talent.value, + probe: talent.probe.trim(), + be: talent.be, + komplexitaet: talent.k, + }) + } + json.talente = talents + let spells = [] + for (spell in zauberliste) { + spells.push({ + name: spell.name, + rep: spell.repraesentation, + hauszauber: spell.hauszauber === "true", + zfw: spell.value, + anmerkungen: spell.zauberkommentar, + komplexitaet: spell.k, + }) + } + json.zauber = spells + let combatValues = [] + for (combatValue in kampfwerte) { + combatValues.push({ + name: combatValue.name, + at: combatValue.attacke.value, + pa: combatValue.parade.value, + }) + } + json.kampfwerte = combatValues + let notes = [] + for (note in kommentare) { + if (note.hasOwnProperty("key")) { + notes.push({ + key: note.key, + notiz: note.kommentar, + }) + } + } + json.notizen = notes + } + + return 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) +} \ No newline at end of file -- 2.43.0 From 2a6a590891557ab00c1c6cfcb8c7e5bace7148c0 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 21:40:50 +0200 Subject: [PATCH 02/21] removed function for testing purposes --- src/module/Actors/dsa-actor.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/module/Actors/dsa-actor.mjs b/src/module/Actors/dsa-actor.mjs index 2ddd9ad9..265c0352 100644 --- a/src/module/Actors/dsa-actor.mjs +++ b/src/module/Actors/dsa-actor.mjs @@ -1,13 +1,14 @@ export class DsaActor extends Actor { - import() { + /*import() { let input = document.createElement('input') input.type = 'file' input.accept = '.xml' input.onchange = e => { importCharacter(this.id, e.target.files[0]) + document.removeChild(input) } input.click() - } + }*/ } \ No newline at end of file -- 2.43.0 From 6848e58cf9ccefa7b3e06c6b340c4af216606729 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 21:45:52 +0200 Subject: [PATCH 03/21] reimplemented function since it didn't cause the error --- src/module/Actors/dsa-actor.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/module/Actors/dsa-actor.mjs b/src/module/Actors/dsa-actor.mjs index 265c0352..b1927e98 100644 --- a/src/module/Actors/dsa-actor.mjs +++ b/src/module/Actors/dsa-actor.mjs @@ -1,6 +1,6 @@ export class DsaActor extends Actor { - /*import() { + import() { let input = document.createElement('input') input.type = 'file' input.accept = '.xml' @@ -9,6 +9,6 @@ export class DsaActor extends Actor { document.removeChild(input) } input.click() - }*/ + } } \ No newline at end of file -- 2.43.0 From d68f757d634a1a8d5cfd2ce246f6b28cad6eb6c8 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 22:10:03 +0200 Subject: [PATCH 04/21] fixed two Field Errors --- src/module/character/character.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/module/character/character.mjs b/src/module/character/character.mjs index 906a1c1a..8436c4de 100644 --- a/src/module/character/character.mjs +++ b/src/module/character/character.mjs @@ -103,11 +103,11 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { gilde: new StringField(), }), vornachteile: new ArrayField(new SchemaField({ - name: new SchemaField(), + name: new StringField(), value: new NumberField(), })), sonderfertigkeiten: new ArrayField(new SchemaField({ - name: new SchemaField(), + name: new StringField(), auswahlen: new ArrayField(new StringField()), })), talente: new ArrayField(new SchemaField({ -- 2.43.0 From b8fa37532ce91856f3330b30d0e2e9f30590cff4 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 22:21:08 +0200 Subject: [PATCH 05/21] export and import function for importing characters --- src/module/Actors/dsa-actor.mjs | 2 + src/module/xml-import/xml-import.mjs | 311 +++++++++++++-------------- 2 files changed, 157 insertions(+), 156 deletions(-) diff --git a/src/module/Actors/dsa-actor.mjs b/src/module/Actors/dsa-actor.mjs index b1927e98..05c3f174 100644 --- a/src/module/Actors/dsa-actor.mjs +++ b/src/module/Actors/dsa-actor.mjs @@ -1,3 +1,5 @@ +import { importCharacter } from '../xml-import/xml-import.mjs' + export class DsaActor extends Actor { import() { diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs index cdb093b1..52b5b403 100644 --- a/src/module/xml-import/xml-import.mjs +++ b/src/module/xml-import/xml-import.mjs @@ -20,7 +20,7 @@ let months = [ * @param actorId the actor-id of the character * @param file the file from which the character should be imported */ -async function importCharacter(actorId, file) { +export async function importCharacter(actorId, file) { let actor = game.actors.get(actorId) let xmlString = await parseFileToString(file) let domParser = new DOMParser() @@ -108,169 +108,168 @@ function calculateBirthdate(json) { */ function mapRawJson(rawJson) { let json = {} - with (rawJson.held) { - json.name = name - json.meta = {} - json.meta.spezies = basis.rasse.string - json.meta.kultur = basis.kultur.string - let professions = [] - for (ausbildung in basis.ausbildungen) { - if (ausbildung.tarnidentitaet) { - professions = [ausbildung.tarnidentitaet] - break; + let held = rawJson.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 ausbildung in held.basis.ausbildungen) { + if (ausbildung.tarnidentitaet) { + professions = [ausbildung.tarnidentitaet] + break; + } + let ausbildungString = ausbildung.string + professions.push(ausbildungString) + } + json.meta.profession = professions + json.geschlecht = held.basis.geschlecht.name + json.haarfarbe = held.basis.rasse.aussehen.haarfarbe + json.groesse = held.basis.rasse.groesse.value + json.augenfarbe = held.basis.rasse.aussehen.augenfarbe + json.geburtstag = calculateBirthdate(held.basis.rasse.aussehen) + json.alter = held.basis.rasse.aussehen.alter + json.gewicht = held.basis.rasse.groesse.gewicht + json.aussehen = [ + held.basis.rasse.aussehen.aussehentext0, + held.basis.rasse.aussehen.aussehentext1, + held.basis.rasse.aussehen.aussehentext2, + held.basis.rasse.aussehen.aussehentext3, + ] + json.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.titel = held.basis.rasse.aussehen.titel + json.stand = held.basis.rasse.aussehen.stand + json.attribute = {} + json.attribute.mu = getAttributeJson(held.eigenschaften, "Mut") + json.attribute.kl = getAttributeJson(held.eigenschaften, "Klugheit") + json.attribute.in = getAttributeJson(held.eigenschaften, "Intuition") + json.attribute.ch = getAttributeJson(held.eigenschaften, "Charisma") + json.attribute.ff = getAttributeJson(held.eigenschaften, "Fingerfertigkeit") + json.attribute.ge = getAttributeJson(held.eigenschaften, "Gewandtheit") + json.attribute.ko = getAttributeJson(held.eigenschaften, "Konstitution") + json.attribute.kk = getAttributeJson(held.eigenschaften, "Körperkraft") + json.attribute.mr = { + mod: filterAttribute(held.eigenschaften ,"Magieresistenz").mod + } + json.attribute.lep = { + mod: filterAttribute(held.eigenschaften ,"Lebensenergie").mod + } + json.attribute.aup = { + mod: filterAttribute(held.eigenschaften ,"Ausdauer").mod + } + json.attribute.asp = { + mod: filterAttribute(held.eigenschaften ,"Astralenergie").mod + } + json.attribute.kap = { + mod: filterAttribute(held.eigenschaften ,"Karmaenergie").mod + } + let attribute = filterAttribute(held.eigenschaften ,"Karmaenergie") + json.attribute.at = { + mod: attribute.mod, + aktuell: attribute.value + } + attribute = filterAttribute(held.eigenschaften ,"at") + json.attribute.pa = { + mod: attribute.mod, + aktuell: attribute.value + } + attribute = filterAttribute(held.eigenschaften ,"pa") + json.attribute.at = { + mod: attribute.mod, + aktuell: attribute.value + } + attribute = filterAttribute(held.eigenschaften ,"fk") + json.attribute.fk = { + mod: attribute.mod, + aktuell: attribute.value + } + attribute = filterAttribute(held.eigenschaften ,"ini") + json.attribute.ini = { + mod: attribute.mod, + aktuell: attribute.value + } + json.attribute.so = getAttributeJson(held.eigenschaften, "Sozialstatus") + let specialAbilities = [] + let liturgies = [] + for (let specialAbility in held.sf) { + if (specialAbility.name.startsWith("Liturgie:")) { + liturgies.push({ + name: specialAbility.name.replace("Liturgie:", "").trim(), + }) + } else { + let specialAbilityJson= { + name: specialAbility.name, + auswahlen: [] } - let ausbildungString = ausbildung.string - professions.push(ausbildungString) - } - json.meta.profession = professions - json.geschlecht = basis.geschlecht.name - json.haarfarbe = basis.rasse.aussehen.haarfarbe - json.groesse = basis.rasse.groesse.value - json.augenfarbe = basis.rasse.aussehen.augenfarbe - json.geburtstag = calculateBirthdate(basis.rasse.aussehen) - json.alter = basis.rasse.aussehen.alter - json.gewicht = basis.rasse.groesse.gewicht - json.aussehen = [ - basis.rasse.aussehen.aussehentext0, - basis.rasse.aussehen.aussehentext1, - basis.rasse.aussehen.aussehentext2, - basis.rasse.aussehen.aussehentext3, - ] - json.familie = [ - basis.rasse.aussehen.familietext0, - basis.rasse.aussehen.familietext1, - basis.rasse.aussehen.familietext2, - basis.rasse.aussehen.familietext3, - basis.rasse.aussehen.familietext4, - basis.rasse.aussehen.familietext5, - ] - json.titel = basis.rasse.aussehen.titel - json.stand = basis.rasse.aussehen.stand - json.attribute = {} - json.attribute.mu = getAttributeJson(eigenschaften, "Mut") - json.attribute.kl = getAttributeJson(eigenschaften, "Klugheit") - json.attribute.in = getAttributeJson(eigenschaften, "Intuition") - json.attribute.ch = getAttributeJson(eigenschaften, "Charisma") - json.attribute.ff = getAttributeJson(eigenschaften, "Fingerfertigkeit") - json.attribute.ge = getAttributeJson(eigenschaften, "Gewandtheit") - json.attribute.ko = getAttributeJson(eigenschaften, "Konstitution") - json.attribute.kk = getAttributeJson(eigenschaften, "Körperkraft") - json.attribute.mr = { - mod: filterAttribute(eigenschaften ,"Magieresistenz").mod - } - json.attribute.lep = { - mod: filterAttribute(eigenschaften ,"Lebensenergie").mod - } - json.attribute.aup = { - mod: filterAttribute(eigenschaften ,"Ausdauer").mod - } - json.attribute.asp = { - mod: filterAttribute(eigenschaften ,"Astralenergie").mod - } - json.attribute.kap = { - mod: filterAttribute(eigenschaften ,"Karmaenergie").mod - } - let attribute = filterAttribute(eigenschaften ,"Karmaenergie") - json.attribute.at = { - mod: attribute.mod, - aktuell: attribute.value - } - attribute = filterAttribute(eigenschaften ,"at") - json.attribute.pa = { - mod: attribute.mod, - aktuell: attribute.value - } - attribute = filterAttribute(eigenschaften ,"pa") - json.attribute.at = { - mod: attribute.mod, - aktuell: attribute.value - } - attribute = filterAttribute(eigenschaften ,"fk") - json.attribute.fk = { - mod: attribute.mod, - aktuell: attribute.value - } - attribute = filterAttribute(eigenschaften ,"ini") - json.attribute.ini = { - mod: attribute.mod, - aktuell: attribute.value - } - json.attribute.so = getAttributeJson(eigenschaften, "Sozialstatus") - let specialAbilities = [] - let liturgies = [] - for (specialAbility in sf) { - 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 (field in fields) { - if (field !== "name") { - let choices = specialAbility[field] - if (choices.hasOwnProperty("name")) { - specialAbilityJson.auswahlen.push(choices.name) - } else { - for (choice in choices) { - specialAbilityJson.auswahlen.push(choice.value) - } + let fields = Object.keys(specialAbility) + if (fields.length > 1) { + for (let field in fields) { + if (field !== "name") { + let choices = specialAbility[field] + if (choices.hasOwnProperty("name")) { + specialAbilityJson.auswahlen.push(choices.name) + } else { + for (let choice in choices) { + specialAbilityJson.auswahlen.push(choice.value) } } } } - specialAbilities.push(specialAbilityJson) } + specialAbilities.push(specialAbilityJson) } - json.sonderfertigkeiten = specialAbilities - json.liturgien = liturgies - let talents = [] - for (talent in talentliste) { - talents.push({ - name: talent.name, - taw: talent.value, - probe: talent.probe.trim(), - be: talent.be, - komplexitaet: talent.k, - }) - } - json.talente = talents - let spells = [] - for (spell in zauberliste) { - spells.push({ - name: spell.name, - rep: spell.repraesentation, - hauszauber: spell.hauszauber === "true", - zfw: spell.value, - anmerkungen: spell.zauberkommentar, - komplexitaet: spell.k, - }) - } - json.zauber = spells - let combatValues = [] - for (combatValue in kampfwerte) { - combatValues.push({ - name: combatValue.name, - at: combatValue.attacke.value, - pa: combatValue.parade.value, - }) - } - json.kampfwerte = combatValues - let notes = [] - for (note in kommentare) { - if (note.hasOwnProperty("key")) { - notes.push({ - key: note.key, - notiz: note.kommentar, - }) - } - } - json.notizen = notes } + json.sonderfertigkeiten = specialAbilities + json.liturgien = liturgies + let talents = [] + for (let talent in held.talentliste) { + talents.push({ + name: talent.name, + taw: talent.value, + probe: talent.probe.trim(), + be: talent.be, + komplexitaet: talent.k, + }) + } + json.talente = talents + let spells = [] + for (let spell in held.zauberliste) { + spells.push({ + name: spell.name, + rep: spell.repraesentation, + hauszauber: spell.hauszauber === "true", + zfw: spell.value, + anmerkungen: spell.zauberkommentar, + komplexitaet: spell.k, + }) + } + json.zauber = spells + let combatValues = [] + for (let combatValue in held.kampfwerte) { + combatValues.push({ + name: combatValue.name, + at: combatValue.attacke.value, + pa: combatValue.parade.value, + }) + } + json.kampfwerte = combatValues + let notes = [] + for (let note in held.kommentare) { + if (note.hasOwnProperty("key")) { + notes.push({ + key: note.key, + notiz: note.kommentar, + }) + } + } + json.notizen = notes return json } -- 2.43.0 From 6ad1474f87633a164c597f2eddb9f4da785d3a7d Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 22:27:36 +0200 Subject: [PATCH 06/21] bugfixes --- src/module/Actors/dsa-actor.mjs | 1 - src/module/xml-import/xml-import.mjs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/module/Actors/dsa-actor.mjs b/src/module/Actors/dsa-actor.mjs index 05c3f174..0cf90572 100644 --- a/src/module/Actors/dsa-actor.mjs +++ b/src/module/Actors/dsa-actor.mjs @@ -8,7 +8,6 @@ export class DsaActor extends Actor { input.accept = '.xml' input.onchange = e => { importCharacter(this.id, e.target.files[0]) - document.removeChild(input) } input.click() } diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs index 52b5b403..ee5023ab 100644 --- a/src/module/xml-import/xml-import.mjs +++ b/src/module/xml-import/xml-import.mjs @@ -82,7 +82,7 @@ async function parseFileToString(file) { reader.onload = event => { resolve(event.target.result) } - reader.error = event => { + reader.onerror = event => { reject(event) } }) -- 2.43.0 From 4c4e2d1f236cffcde18a0535afb76d44c63b66f5 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 22:55:29 +0200 Subject: [PATCH 07/21] bugfixes --- src/module/xml-import/xml-import.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs index ee5023ab..f88ab7ae 100644 --- a/src/module/xml-import/xml-import.mjs +++ b/src/module/xml-import/xml-import.mjs @@ -43,7 +43,7 @@ function getJsonFromXML(dom) { // initializing object to be returned. let jsonResult = {}; - let attributes = dom.attributes + let attributes = dom.attributes ? dom.attributes : [] for (let attribute of attributes) { jsonResult[attribute.name] = attribute.value } @@ -108,7 +108,7 @@ function calculateBirthdate(json) { */ function mapRawJson(rawJson) { let json = {} - let held = rawJson.held; + let held = rawJson.helden.held; json.name = held.name json.meta = {} json.meta.spezies = held.basis.rasse.string -- 2.43.0 From 9e7428d58994d872dd5cde97bbc848a7c9a081ce Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 23:13:38 +0200 Subject: [PATCH 08/21] fixed json array problem --- src/module/xml-import/xml-import.mjs | 51 ++++++++++++++-------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs index f88ab7ae..f203eb16 100644 --- a/src/module/xml-import/xml-import.mjs +++ b/src/module/xml-import/xml-import.mjs @@ -114,7 +114,7 @@ function mapRawJson(rawJson) { json.meta.spezies = held.basis.rasse.string json.meta.kultur = held.basis.kultur.string let professions = [] - for (let ausbildung in held.basis.ausbildungen) { + for (let ausbildung in held.basis.ausbildungen.ausbildung) { if (ausbildung.tarnidentitaet) { professions = [ausbildung.tarnidentitaet] break; @@ -146,59 +146,60 @@ function mapRawJson(rawJson) { ] json.titel = held.basis.rasse.aussehen.titel json.stand = held.basis.rasse.aussehen.stand + let attributes = held.eigenschaften.eigenschaft json.attribute = {} - json.attribute.mu = getAttributeJson(held.eigenschaften, "Mut") - json.attribute.kl = getAttributeJson(held.eigenschaften, "Klugheit") - json.attribute.in = getAttributeJson(held.eigenschaften, "Intuition") - json.attribute.ch = getAttributeJson(held.eigenschaften, "Charisma") - json.attribute.ff = getAttributeJson(held.eigenschaften, "Fingerfertigkeit") - json.attribute.ge = getAttributeJson(held.eigenschaften, "Gewandtheit") - json.attribute.ko = getAttributeJson(held.eigenschaften, "Konstitution") - json.attribute.kk = getAttributeJson(held.eigenschaften, "Körperkraft") + 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.attribute.mr = { - mod: filterAttribute(held.eigenschaften ,"Magieresistenz").mod + mod: filterAttribute(attributes,"Magieresistenz").mod } json.attribute.lep = { - mod: filterAttribute(held.eigenschaften ,"Lebensenergie").mod + mod: filterAttribute(attributes,"Lebensenergie").mod } json.attribute.aup = { - mod: filterAttribute(held.eigenschaften ,"Ausdauer").mod + mod: filterAttribute(attributes,"Ausdauer").mod } json.attribute.asp = { - mod: filterAttribute(held.eigenschaften ,"Astralenergie").mod + mod: filterAttribute(attributes,"Astralenergie").mod } json.attribute.kap = { - mod: filterAttribute(held.eigenschaften ,"Karmaenergie").mod + mod: filterAttribute(attributes,"Karmaenergie").mod } - let attribute = filterAttribute(held.eigenschaften ,"Karmaenergie") + let attribute = filterAttribute(attributes,"Karmaenergie") json.attribute.at = { mod: attribute.mod, aktuell: attribute.value } - attribute = filterAttribute(held.eigenschaften ,"at") + attribute = filterAttribute(attributes,"at") json.attribute.pa = { mod: attribute.mod, aktuell: attribute.value } - attribute = filterAttribute(held.eigenschaften ,"pa") + attribute = filterAttribute(attributes,"pa") json.attribute.at = { mod: attribute.mod, aktuell: attribute.value } - attribute = filterAttribute(held.eigenschaften ,"fk") + attribute = filterAttribute(attributes,"fk") json.attribute.fk = { mod: attribute.mod, aktuell: attribute.value } - attribute = filterAttribute(held.eigenschaften ,"ini") + attribute = filterAttribute(attributes,"ini") json.attribute.ini = { mod: attribute.mod, aktuell: attribute.value } - json.attribute.so = getAttributeJson(held.eigenschaften, "Sozialstatus") + json.attribute.so = getAttributeJson(attributes, "Sozialstatus") let specialAbilities = [] let liturgies = [] - for (let specialAbility in held.sf) { + for (let specialAbility in held.sf.sonderfertigkeit) { if (specialAbility.name.startsWith("Liturgie:")) { liturgies.push({ name: specialAbility.name.replace("Liturgie:", "").trim(), @@ -216,7 +217,7 @@ function mapRawJson(rawJson) { if (choices.hasOwnProperty("name")) { specialAbilityJson.auswahlen.push(choices.name) } else { - for (let choice in choices) { + for (let choice in choices.wahl) { specialAbilityJson.auswahlen.push(choice.value) } } @@ -229,7 +230,7 @@ function mapRawJson(rawJson) { json.sonderfertigkeiten = specialAbilities json.liturgien = liturgies let talents = [] - for (let talent in held.talentliste) { + for (let talent in held.talentliste.talent) { talents.push({ name: talent.name, taw: talent.value, @@ -240,7 +241,7 @@ function mapRawJson(rawJson) { } json.talente = talents let spells = [] - for (let spell in held.zauberliste) { + for (let spell in held.zauberliste.zauber) { spells.push({ name: spell.name, rep: spell.repraesentation, @@ -252,7 +253,7 @@ function mapRawJson(rawJson) { } json.zauber = spells let combatValues = [] - for (let combatValue in held.kampfwerte) { + for (let combatValue in held.kampf.kampfwerte) { combatValues.push({ name: combatValue.name, at: combatValue.attacke.value, -- 2.43.0 From fc83a83de9d261650fe5c242b64c059c96d87960 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 23:26:05 +0200 Subject: [PATCH 09/21] fixed another array problem --- src/module/xml-import/xml-import.mjs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs index f203eb16..b150bcb1 100644 --- a/src/module/xml-import/xml-import.mjs +++ b/src/module/xml-import/xml-import.mjs @@ -114,13 +114,14 @@ function mapRawJson(rawJson) { json.meta.spezies = held.basis.rasse.string json.meta.kultur = held.basis.kultur.string let professions = [] - for (let ausbildung in held.basis.ausbildungen.ausbildung) { - if (ausbildung.tarnidentitaet) { - professions = [ausbildung.tarnidentitaet] + for (let profession in held.basis.ausbildungen.ausbildung) { + profession = held.basis.ausbildungen.ausbildung[profession] + if (profession.tarnidentitaet) { + professions = [profession.tarnidentitaet] break; } - let ausbildungString = ausbildung.string - professions.push(ausbildungString) + let professionString = profession.string + professions.push(professionString) } json.meta.profession = professions json.geschlecht = held.basis.geschlecht.name @@ -200,6 +201,7 @@ function mapRawJson(rawJson) { 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(), @@ -212,12 +214,14 @@ function mapRawJson(rawJson) { 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) } } @@ -231,6 +235,7 @@ function mapRawJson(rawJson) { json.liturgien = liturgies let talents = [] for (let talent in held.talentliste.talent) { + talent = held.talentliste.talent[talent] talents.push({ name: talent.name, taw: talent.value, @@ -242,6 +247,7 @@ function mapRawJson(rawJson) { json.talente = talents let spells = [] for (let spell in held.zauberliste.zauber) { + spell = held.zauberliste.zauber[spell] spells.push({ name: spell.name, rep: spell.repraesentation, @@ -254,6 +260,7 @@ function mapRawJson(rawJson) { json.zauber = spells let combatValues = [] for (let combatValue in held.kampf.kampfwerte) { + combatValue = held.kampf.kampfwerte[combatValue] combatValues.push({ name: combatValue.name, at: combatValue.attacke.value, @@ -263,6 +270,7 @@ function mapRawJson(rawJson) { json.kampfwerte = combatValues let notes = [] for (let note in held.kommentare) { + note = held.kommentare[note] if (note.hasOwnProperty("key")) { notes.push({ key: note.key, -- 2.43.0 From e94219b26b7e06a5d7b0bb22270b01409ab7817c Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 23:31:38 +0200 Subject: [PATCH 10/21] added custom entry to import --- src/main.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main.mjs b/src/main.mjs index 6cdd43a4..4a79ba9e 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -11,4 +11,16 @@ Hooks.once("init", () => { }; console.log("DSA 4.1 is ready for development!") +}) + +Hooks.on("getActorDirectoryEntryContext", (menuItems) => { + menuItems.push({ + name: "Import from XML", + icon: '', + callback: (li) => { + const actorId = li.data("document-id") + const actor = game.actors.get(actorId) + actor.import() + } + }) }) \ No newline at end of file -- 2.43.0 From 89860e8e981a94ce4a70748ada7d742559969cde Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 23:36:44 +0200 Subject: [PATCH 11/21] added custom entry to import --- src/main.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.mjs b/src/main.mjs index 4a79ba9e..6523a83f 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -13,7 +13,7 @@ Hooks.once("init", () => { console.log("DSA 4.1 is ready for development!") }) -Hooks.on("getActorDirectoryEntryContext", (menuItems) => { +Hooks.on("getActorContextOptions", (menuItems) => { menuItems.push({ name: "Import from XML", icon: '', -- 2.43.0 From e1911cdd4718387099a5b061f360351717dd8d49 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 23:38:15 +0200 Subject: [PATCH 12/21] fixed a bug with the sidebar entry --- src/main.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.mjs b/src/main.mjs index 6523a83f..214312c3 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -13,7 +13,7 @@ Hooks.once("init", () => { console.log("DSA 4.1 is ready for development!") }) -Hooks.on("getActorContextOptions", (menuItems) => { +Hooks.on("getActorContextOptions", (application, menuItems) => { menuItems.push({ name: "Import from XML", icon: '', -- 2.43.0 From 646c9c6d16f3d92f79b85191412ef4293cd256dc Mon Sep 17 00:00:00 2001 From: Jendrik Date: Thu, 25 Sep 2025 23:40:32 +0200 Subject: [PATCH 13/21] fixed a bug with the sidebar entry --- src/main.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.mjs b/src/main.mjs index 214312c3..49557c2a 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -18,7 +18,7 @@ Hooks.on("getActorContextOptions", (application, menuItems) => { name: "Import from XML", icon: '', callback: (li) => { - const actorId = li.data("document-id") + const actorId = li.getAttribute("data-entry-id") const actor = game.actors.get(actorId) actor.import() } -- 2.43.0 From 41de33cef35035f05d97d6bbc9cac2195e189180 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Fri, 26 Sep 2025 00:20:00 +0200 Subject: [PATCH 14/21] ironed out last bugs --- src/main.mjs | 12 ----- src/module/character/character.mjs | 6 +-- src/module/xml-import/xml-import.mjs | 73 ++++++++++++++++++++-------- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/main.mjs b/src/main.mjs index 49557c2a..6cdd43a4 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -11,16 +11,4 @@ Hooks.once("init", () => { }; console.log("DSA 4.1 is ready for development!") -}) - -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() - } - }) }) \ No newline at end of file diff --git a/src/module/character/character.mjs b/src/module/character/character.mjs index 8436c4de..5d4370bb 100644 --- a/src/module/character/character.mjs +++ b/src/module/character/character.mjs @@ -104,7 +104,7 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { }), vornachteile: new ArrayField(new SchemaField({ name: new StringField(), - value: new NumberField(), + wert: new NumberField({ required: false, integer: true }), })), sonderfertigkeiten: new ArrayField(new SchemaField({ name: new StringField(), @@ -114,7 +114,7 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { name: new StringField(), taw: new NumberField({required: true, integer: true }), probe: new StringField(), - be: new NumberField({required: false, integer: true }), + be: new StringField({required: false }), komplexitaet: new NumberField({required: false, integer: true }), })), zauber: new ArrayField(new SchemaField({ @@ -123,7 +123,7 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { hauszauber: new BooleanField(), zfw: new NumberField({ required: true, integer: true }), anmerkungen: new StringField(), - komplexitaet: new NumberField({required: true, integer: true }), + komplexitaet: new StringField({required: true }), })), liturgien: new ArrayField(new SchemaField({ name: new StringField(), diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs index b150bcb1..71b31be7 100644 --- a/src/module/xml-import/xml-import.mjs +++ b/src/module/xml-import/xml-import.mjs @@ -123,21 +123,21 @@ function mapRawJson(rawJson) { let professionString = profession.string professions.push(professionString) } - json.meta.profession = professions - json.geschlecht = held.basis.geschlecht.name - json.haarfarbe = held.basis.rasse.aussehen.haarfarbe - json.groesse = held.basis.rasse.groesse.value - json.augenfarbe = held.basis.rasse.aussehen.augenfarbe - json.geburtstag = calculateBirthdate(held.basis.rasse.aussehen) - json.alter = held.basis.rasse.aussehen.alter - json.gewicht = held.basis.rasse.groesse.gewicht - json.aussehen = [ + 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.familie = [ + json.meta.familie = [ held.basis.rasse.aussehen.familietext0, held.basis.rasse.aussehen.familietext1, held.basis.rasse.aussehen.familietext2, @@ -145,10 +145,13 @@ function mapRawJson(rawJson) { held.basis.rasse.aussehen.familietext4, held.basis.rasse.aussehen.familietext5, ] - json.titel = held.basis.rasse.aussehen.titel - json.stand = held.basis.rasse.aussehen.stand + 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") @@ -198,6 +201,18 @@ function mapRawJson(rawJson) { aktuell: attribute.value } json.attribute.so = getAttributeJson(attributes, "Sozialstatus") + let benefits = [] + for (let benefit in held.vt.vorteil) { + benefit = held.vt.vorteil[benefit] + let benefitJson = { + name: benefit.name, + } + if (benefit.value !== undefined) { + benefitJson.wert = benefit.value + } + benefits.push(benefitJson) + } + json.vornachteile = benefits let specialAbilities = [] let liturgies = [] for (let specialAbility in held.sf.sonderfertigkeit) { @@ -236,13 +251,18 @@ function mapRawJson(rawJson) { let talents = [] for (let talent in held.talentliste.talent) { talent = held.talentliste.talent[talent] - talents.push({ + let talentJson = { name: talent.name, taw: talent.value, probe: talent.probe.trim(), - be: talent.be, - komplexitaet: talent.k, - }) + } + if (talent.be !== undefined) { + talentJson.be = talent.be + } + if (talent.k !== undefined) { + talentJson.komplexitaet = parseInt(talent.k) + } + talents.push(talentJson) } json.talente = talents let spells = [] @@ -280,7 +300,10 @@ function mapRawJson(rawJson) { } json.notizen = notes - return json + return { + name: held.name, + system: json, + } } /** @@ -305,5 +328,17 @@ function getAttributeJson(attributes, name) { * @returns {{}} the json of the desired attribute */ function filterAttribute(attributes, name) { - return attributes.filter(attribute => attribute.name === name) -} \ No newline at end of file + 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() + } + }) +}) \ No newline at end of file -- 2.43.0 From b896af479e49b1f2965271aae541565bebc34e62 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Fri, 26 Sep 2025 09:59:35 +0200 Subject: [PATCH 15/21] added a (really really) rudimentary character Sheet --- src/main.mjs | 6 ++++++ src/module/Sheet/CharacterSheet.mjs | 20 ++++++++++++++++++++ src/templates/sheets/character-sheet.hbs | 10 ++++++++++ 3 files changed, 36 insertions(+) create mode 100644 src/module/Sheet/CharacterSheet.mjs create mode 100644 src/templates/sheets/character-sheet.hbs diff --git a/src/main.mjs b/src/main.mjs index 6cdd43a4..bf674013 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -1,5 +1,6 @@ import {PlayerCharacterDataModel} from "./module/character/character.mjs"; import {DsaActor} from "./module/Actors/dsa-actor.mjs"; +import {CharacterSheet} from "./module/Sheet/CharacterSheet.mjs"; Hooks.once("init", () => { // Configure custom Document implementations. @@ -10,5 +11,10 @@ Hooks.once("init", () => { character: PlayerCharacterDataModel, }; + foundry.documents.collections.Actors.registerSheet("dsa41.character", CharacterSheet, { + types: ["character"], + makeDefault: true + }); + console.log("DSA 4.1 is ready for development!") }) \ No newline at end of file diff --git a/src/module/Sheet/CharacterSheet.mjs b/src/module/Sheet/CharacterSheet.mjs new file mode 100644 index 00000000..5cbe3047 --- /dev/null +++ b/src/module/Sheet/CharacterSheet.mjs @@ -0,0 +1,20 @@ +/** + * Extend the basic ActorSheet with some very simple modifications + * @extends {ActorSheet} + */ +export class CharacterSheet extends ActorSheet { + + /** @override */ + static get defaultOptions() { + return foundry.utils.mergeObject(super.defaultOptions, { + template: "systems/DSA_4-1/templates/sheets/character-sheet.hbs", + width: 600, + height: 600, + }); + } + +} + +Handlebars.registerHelper("formatCharacter", function(actor) { + return JSON.stringify(actor, null, 4); +}); \ No newline at end of file diff --git a/src/templates/sheets/character-sheet.hbs b/src/templates/sheets/character-sheet.hbs new file mode 100644 index 00000000..ea1316a9 --- /dev/null +++ b/src/templates/sheets/character-sheet.hbs @@ -0,0 +1,10 @@ +
+
+
+

{{actor.name}}

+
+
+
+ +
+
\ No newline at end of file -- 2.43.0 From eb73822ba54442a695c16b9de929318dfe6132f2 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Sat, 27 Sep 2025 19:58:45 +0200 Subject: [PATCH 16/21] merged main in branch --- src/main.mjs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main.mjs b/src/main.mjs index 08346bee..d2048696 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -1,11 +1,9 @@ -import { PlayerCharacterDataModel } from "./module/character/character.mjs"; -import { SkillSheet } from "./module/sheets/skillSheet.mjs"; -import { SpellSheet } from "./module/sheets/spellSheet.mjs"; -import { SkillDataModel } from "./module/data/skill.mjs"; -import { SpellDataModel } from "./module/data/spell.mjs"; -import { Character } from "./module/documents/character.mjs"; -import {PlayerCharacterDataModel} from "./module/character/character.mjs"; -import {DsaActor} from "./module/Actors/dsa-actor.mjs"; +import {SkillSheet} from "./module/sheets/skillSheet.mjs"; +import {SpellSheet} from "./module/sheets/spellSheet.mjs"; +import {SkillDataModel} from "./module/data/skill.mjs"; +import {SpellDataModel} from "./module/data/spell.mjs"; +import {Character} from "./module/documents/character.mjs"; +import {PlayerCharacterDataModel} from "./module/data/character.mjs"; import {CharacterSheet} from "./module/Sheet/CharacterSheet.mjs"; Hooks.once("init", () => { -- 2.43.0 From b21ba191d8c223e27df0c9a779a96fa9021d84fc Mon Sep 17 00:00:00 2001 From: Jendrik Date: Sat, 27 Sep 2025 23:18:17 +0200 Subject: [PATCH 17/21] re-added import of characters --- src/module/documents/character.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/module/documents/character.mjs b/src/module/documents/character.mjs index ebc67b42..0beea18e 100644 --- a/src/module/documents/character.mjs +++ b/src/module/documents/character.mjs @@ -1,4 +1,16 @@ +import {importCharacter} from "../xml-import/xml-import.mjs"; + export class Character extends Actor { + + import() { + let input = document.createElement('input') + input.type = 'file' + input.accept = '.xml' + input.onchange = e => { + importCharacter(this.id, e.target.files[0]) + } + input.click() + } /** * Augment the basic Item data model with additional dynamic data. */ -- 2.43.0 From 5167d5e042f56b22738df409aab4a0f2ce7281b6 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Sun, 28 Sep 2025 12:13:57 +0200 Subject: [PATCH 18/21] import talents --- src/module/data/character.mjs | 16 ++++++++++------ src/module/xml-import/xml-import.mjs | 27 ++++++++++++--------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/module/data/character.mjs b/src/module/data/character.mjs index 560c4d1d..cb02a0c7 100644 --- a/src/module/data/character.mjs +++ b/src/module/data/character.mjs @@ -1,8 +1,5 @@ -import {SkillDataModel} from "./skill.mjs"; -import {SpellDataModel} from "./spell.mjs"; - const { - SchemaField, NumberField, StringField, ArrayField, BooleanField, ForeignDocumentField + SchemaField, NumberField, StringField, ArrayField, ForeignDocumentField } = foundry.data.fields; export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { @@ -114,8 +111,15 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { auswahlen: new ArrayField(new StringField()), })), - talente: new ArrayField ( new ForeignDocumentField(Item) ), - zauber: new ArrayField ( new ForeignDocumentField(Item) ), + talente: new ArrayField(new SchemaField({ + talent: new ForeignDocumentField(Item), + taw: new NumberField({integer: true, required: true}), + }) + ), + zauber: new ArrayField(new SchemaField({ + talent: new ForeignDocumentField(Item), + zfw: new NumberField({integer: true, required: true}), + })), liturgien: new ArrayField(new SchemaField({ name: new StringField(), })), diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs index 71b31be7..41488168 100644 --- a/src/module/xml-import/xml-import.mjs +++ b/src/module/xml-import/xml-import.mjs @@ -27,7 +27,8 @@ export async function importCharacter(actorId, file) { let dom = domParser.parseFromString(xmlString, 'application/xml') let rawJson = getJsonFromXML(dom) - let characterJson = mapRawJson(rawJson) + //for some reason this await is necessary, even if Webstorm thinks it is obsolete + let characterJson = await mapRawJson(rawJson) actor.update(characterJson) } @@ -106,7 +107,7 @@ function calculateBirthdate(json) { * @param rawJson the json parsed from the Helden-Software XML * @returns {{}} a json representation of the character */ -function mapRawJson(rawJson) { +async function mapRawJson(rawJson) { let json = {} let held = rawJson.helden.held; json.name = held.name @@ -251,22 +252,18 @@ function mapRawJson(rawJson) { let talents = [] for (let talent in held.talentliste.talent) { talent = held.talentliste.talent[talent] - let talentJson = { - name: talent.name, - taw: talent.value, - probe: talent.probe.trim(), + let talentItem = game.items.getName(talent.name) + if (talentItem) { + let talentJson = { + talent: talentItem, + taw: talent.value, + } + talents.push(talentJson) } - if (talent.be !== undefined) { - talentJson.be = talent.be - } - if (talent.k !== undefined) { - talentJson.komplexitaet = parseInt(talent.k) - } - talents.push(talentJson) } json.talente = talents let spells = [] - for (let spell in held.zauberliste.zauber) { + /*for (let spell in held.zauberliste.zauber) { spell = held.zauberliste.zauber[spell] spells.push({ name: spell.name, @@ -276,7 +273,7 @@ function mapRawJson(rawJson) { anmerkungen: spell.zauberkommentar, komplexitaet: spell.k, }) - } + }*/ json.zauber = spells let combatValues = [] for (let combatValue in held.kampf.kampfwerte) { -- 2.43.0 From 7038d2c5c0965d875fc538340fa75d191fc7cd83 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Sun, 28 Sep 2025 12:28:53 +0200 Subject: [PATCH 19/21] removed obsolete sheet --- src/module/Sheet/CharacterSheet.mjs | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 src/module/Sheet/CharacterSheet.mjs diff --git a/src/module/Sheet/CharacterSheet.mjs b/src/module/Sheet/CharacterSheet.mjs deleted file mode 100644 index 5cbe3047..00000000 --- a/src/module/Sheet/CharacterSheet.mjs +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Extend the basic ActorSheet with some very simple modifications - * @extends {ActorSheet} - */ -export class CharacterSheet extends ActorSheet { - - /** @override */ - static get defaultOptions() { - return foundry.utils.mergeObject(super.defaultOptions, { - template: "systems/DSA_4-1/templates/sheets/character-sheet.hbs", - width: 600, - height: 600, - }); - } - -} - -Handlebars.registerHelper("formatCharacter", function(actor) { - return JSON.stringify(actor, null, 4); -}); \ No newline at end of file -- 2.43.0 From f7593304009c5fd5571506b5887f8731e52ca4a5 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Sun, 28 Sep 2025 12:40:38 +0200 Subject: [PATCH 20/21] removed unnecessary async modifier --- src/module/xml-import/xml-import.mjs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs index 41488168..e7681a07 100644 --- a/src/module/xml-import/xml-import.mjs +++ b/src/module/xml-import/xml-import.mjs @@ -27,8 +27,7 @@ export async function importCharacter(actorId, file) { let dom = domParser.parseFromString(xmlString, 'application/xml') let rawJson = getJsonFromXML(dom) - //for some reason this await is necessary, even if Webstorm thinks it is obsolete - let characterJson = await mapRawJson(rawJson) + let characterJson = mapRawJson(rawJson) actor.update(characterJson) } @@ -107,7 +106,7 @@ function calculateBirthdate(json) { * @param rawJson the json parsed from the Helden-Software XML * @returns {{}} a json representation of the character */ -async function mapRawJson(rawJson) { +function mapRawJson(rawJson) { let json = {} let held = rawJson.helden.held; json.name = held.name -- 2.43.0 From 7e689105bdf436ca133a5eb486f6980525b3cd87 Mon Sep 17 00:00:00 2001 From: Jendrik Date: Sun, 28 Sep 2025 12:43:24 +0200 Subject: [PATCH 21/21] fixed characterSheet --- src/module/sheets/characterSheet.mjs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 44b29f88..a776bca3 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -38,42 +38,42 @@ export class CharacterSheet extends ActorSheet { { eigenschaft: "mu", name: "Mut", - wert: actorData.system.attribute.mu ?? 0, + wert: actorData.system.attribute.mu.aktuell ?? 0, }, { eigenschaft: "kl", name: "Klugheit", - wert: actorData.system.attribute.kl ?? 0, + wert: actorData.system.attribute.kl.aktuell ?? 0, }, { eigenschaft: "in", name: "Intuition", - wert: actorData.system.attribute.in ?? 0, + wert: actorData.system.attribute.in.aktuell ?? 0, }, { eigenschaft: "ch", name: "Charisma", - wert: actorData.system.attribute.ch ?? 0, + wert: actorData.system.attribute.ch.aktuell ?? 0, }, { eigenschaft: "ff", name: "Fingerfertigkeit", - wert: actorData.system.attribute.ff ?? 0, + wert: actorData.system.attribute.ff.aktuell ?? 0, }, { eigenschaft: "ge", name: "Geschicklichkeit", - wert: actorData.system.attribute.ge ?? 0, + wert: actorData.system.attribute.ge.aktuell ?? 0, }, { eigenschaft: "ko", name: "Konstitution", - wert: actorData.system.attribute.ko ?? 0, + wert: actorData.system.attribute.ko.aktuell ?? 0, }, { eigenschaft: "kk", name: "Körperkraft", - wert: actorData.system.attribute.kk ?? 0, + wert: actorData.system.attribute.kk.aktuell ?? 0, }, ]; -- 2.43.0