repackages xml-import into class and adds configuration dialog to it
parent
53c5c7b53a
commit
1c9d4a1f1f
16
src/main.mjs
16
src/main.mjs
|
|
@ -27,6 +27,8 @@ import {CultureDataModel} from "./module/data/culture.mjs";
|
||||||
import {CultureSheet} from "./module/sheets/CultureSheet.mjs";
|
import {CultureSheet} from "./module/sheets/CultureSheet.mjs";
|
||||||
import {SpeciesSheet} from "./module/sheets/SpeciesSheet.mjs";
|
import {SpeciesSheet} from "./module/sheets/SpeciesSheet.mjs";
|
||||||
import {ProfessionSheet} from "./module/sheets/ProfessionSheet.mjs";
|
import {ProfessionSheet} from "./module/sheets/ProfessionSheet.mjs";
|
||||||
|
import {XmlImport} from "./module/xml-import/xml-import.mjs";
|
||||||
|
import {XmlImportDialog} from "./module/dialog/xmlImportDialog.mjs";
|
||||||
|
|
||||||
async function preloadHandlebarsTemplates() {
|
async function preloadHandlebarsTemplates() {
|
||||||
return foundry.applications.handlebars.loadTemplates([
|
return foundry.applications.handlebars.loadTemplates([
|
||||||
|
|
@ -219,6 +221,20 @@ Hooks.once("ready", async function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
new XmlImportDialog(actor).render(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
async function createTalentMacro(data, slot) {
|
async function createTalentMacro(data, slot) {
|
||||||
console.log(data, slot)
|
console.log(data, slot)
|
||||||
if (data.type !== "Item") return;
|
if (data.type !== "Item") return;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
import {XmlImport} from "../xml-import/xml-import.mjs";
|
||||||
|
|
||||||
|
const {ApplicationV2, HandlebarsApplicationMixin} = foundry.applications.api
|
||||||
|
|
||||||
|
export class XmlImportDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
|
|
||||||
|
static DEFAULT_OPTIONS = {
|
||||||
|
classes: ['dsa41', 'dialog', 'xmlimport'],
|
||||||
|
tag: "form",
|
||||||
|
position: {
|
||||||
|
width: 320,
|
||||||
|
height: 478
|
||||||
|
},
|
||||||
|
window: {
|
||||||
|
resizable: false,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
submitOnChange: false,
|
||||||
|
closeOnSubmit: true,
|
||||||
|
handler: XmlImportDialog.#onSubmitForm
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
static PARTS = {
|
||||||
|
form: {
|
||||||
|
template: 'systems/DSA_4-1/templates/dialog/xml-import.hbs',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Actor}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_actor = null
|
||||||
|
/**
|
||||||
|
* @type {XmlImport}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_xmlImport = null
|
||||||
|
|
||||||
|
constructor(actor) {
|
||||||
|
super();
|
||||||
|
this._actor = actor
|
||||||
|
this._xmlImport = new XmlImport()
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #onSubmitForm(event, form, formData) {
|
||||||
|
event.preventDefault()
|
||||||
|
console.log("lets go", formData.object)
|
||||||
|
|
||||||
|
const options = {}
|
||||||
|
|
||||||
|
formData.object.importOption.forEach(p => {
|
||||||
|
options[p] = true
|
||||||
|
})
|
||||||
|
|
||||||
|
const file = form.querySelector('input[type="file"]').files[0]
|
||||||
|
|
||||||
|
try {
|
||||||
|
form.querySelector('button[type="submit"]').setAttribute("disabled", true)
|
||||||
|
await this._xmlImport.importCharacter(this._actor._id, file, options)
|
||||||
|
form.querySelector('button[type="submit"]').setAttribute("disabled", false)
|
||||||
|
return true
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
form.querySelector('button[type="submit"]').setAttribute("disabled", false)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_configureRenderOptions(options) {
|
||||||
|
super._configureRenderOptions(options)
|
||||||
|
options.window.title = `${this._actor.name} importieren`
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
async _prepareContext(options) {
|
||||||
|
const context = await super._prepareContext(options)
|
||||||
|
context.options = XmlImport.getOptions()
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
_onRender(context, options) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import {importCharacter} from "../xml-import/xml-import.mjs";
|
|
||||||
import {LiturgyData} from "../data/miracle/liturgydata.mjs";
|
import {LiturgyData} from "../data/miracle/liturgydata.mjs";
|
||||||
import {Zonenruestung, Zonenwunde, Wunde} from "../data/Trefferzone.js";
|
import {Zonenruestung, Zonenwunde, Wunde} from "../data/Trefferzone.js";
|
||||||
import {PlayerCharacterDataModel} from "../data/character.mjs";
|
import {PlayerCharacterDataModel} from "../data/character.mjs";
|
||||||
|
|
||||||
export class Character extends Actor {
|
export class Character extends Actor {
|
||||||
|
|
||||||
|
/**
|
||||||
import() {
|
import() {
|
||||||
let input = document.createElement('input')
|
let input = document.createElement('input')
|
||||||
input.type = 'file'
|
input.type = 'file'
|
||||||
|
|
@ -13,7 +13,7 @@ export class Character extends Actor {
|
||||||
importCharacter(this.id, e.target.files[0])
|
importCharacter(this.id, e.target.files[0])
|
||||||
}
|
}
|
||||||
input.click()
|
input.click()
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @override
|
* @override
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ import {Profession} from "../documents/profession.mjs";
|
||||||
import {Culture} from "../documents/culture.mjs";
|
import {Culture} from "../documents/culture.mjs";
|
||||||
import {Species} from "../documents/species.mjs";
|
import {Species} from "../documents/species.mjs";
|
||||||
|
|
||||||
let months = [
|
export class XmlImport {
|
||||||
|
#months = [
|
||||||
"Praios",
|
"Praios",
|
||||||
"Rondra",
|
"Rondra",
|
||||||
"Efferd",
|
"Efferd",
|
||||||
|
|
@ -22,9 +23,11 @@ let months = [
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef ImportOptions
|
* @typedef ImportOptions
|
||||||
|
* @property {Boolean} skipMeta
|
||||||
* @property {Boolean} skipSpecies
|
* @property {Boolean} skipSpecies
|
||||||
* @property {Boolean} skipCulture
|
* @property {Boolean} skipCulture
|
||||||
* @property {Boolean} skipProfessions
|
* @property {Boolean} skipProfessions
|
||||||
|
* @property {Boolean} skipAttributes
|
||||||
* @property {Boolean} skipAdvantages
|
* @property {Boolean} skipAdvantages
|
||||||
* @property {Boolean} skipSpecialAbilities
|
* @property {Boolean} skipSpecialAbilities
|
||||||
* @property {Boolean} skipEquipment
|
* @property {Boolean} skipEquipment
|
||||||
|
|
@ -33,25 +36,44 @@ let months = [
|
||||||
* @property {Boolean} skipSkills
|
* @property {Boolean} skipSkills
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
static getOptions() {
|
||||||
|
return {
|
||||||
|
skipMeta: "Meta",
|
||||||
|
skipSpecies: "Rasse",
|
||||||
|
skipCulture: "Kultur",
|
||||||
|
skipProfessions: "Professionen",
|
||||||
|
skipAttribution: "Eigenschaften",
|
||||||
|
skipAdvantages: "Vor und Nachteile",
|
||||||
|
skipSpecialAbilities: "Sonderfertigkeiten",
|
||||||
|
skipEquipment: "Inventar",
|
||||||
|
skipSpells: "Zauber",
|
||||||
|
skipLiturgies: "Liturgien",
|
||||||
|
skipSkills: "Talente"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports a character from a file created in the tool Helden-Software
|
* Imports a character from a file created in the tool Helden-Software
|
||||||
* @param actorId the actor-id of the character
|
* @param actorId the actor-id of the character
|
||||||
* @param file the file from which the character should be imported
|
* @param file the file from which the character should be imported
|
||||||
* @param {ImportOptions?} options the set of item types the import should skip
|
* @param {ImportOptions?} options the set of item types the import should skip
|
||||||
*/
|
*/
|
||||||
export async function importCharacter(actorId, file, options = undefined) {
|
async importCharacter(actorId, file, options = undefined) {
|
||||||
let actor = game.actors.get(actorId)
|
let actor = game.actors.get(actorId)
|
||||||
let xmlString = await parseFileToString(file)
|
console.log("starting import with following options", options)
|
||||||
|
let xmlString = await this.#parseFileToString(file)
|
||||||
let domParser = new DOMParser()
|
let domParser = new DOMParser()
|
||||||
let dom = domParser.parseFromString(xmlString, 'application/xml')
|
let dom = domParser.parseFromString(xmlString, 'application/xml')
|
||||||
|
|
||||||
let rawJson = getJsonFromXML(dom)
|
let rawJson = this.#getJsonFromXML(dom)
|
||||||
|
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {
|
options = {
|
||||||
|
skipMeta: false,
|
||||||
skipSpecies: false,
|
skipSpecies: false,
|
||||||
skipCulture: false,
|
skipCulture: false,
|
||||||
skipProfessions: false,
|
skipProfessions: false,
|
||||||
|
skipAttributes: false,
|
||||||
skipAdvantages: false,
|
skipAdvantages: false,
|
||||||
skipSpecialAbilities: false,
|
skipSpecialAbilities: false,
|
||||||
skipEquipment: false,
|
skipEquipment: false,
|
||||||
|
|
@ -61,17 +83,18 @@ export async function importCharacter(actorId, file, options = undefined) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let characterJson = mapRawJson(actor, rawJson, options)
|
let characterJson = this.#mapRawJson(actor, rawJson, options)
|
||||||
|
|
||||||
actor.update(characterJson)
|
actor.update(characterJson)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param dom the XML-Dom from which the json should be extracted
|
* @param dom the XML-Dom from which the json should be extracted
|
||||||
* @returns {{}} the json parsed from the xml
|
* @returns {{}} the json parsed from the xml
|
||||||
*/
|
*/
|
||||||
function getJsonFromXML(dom) {
|
#getJsonFromXML(dom) {
|
||||||
let children = [...dom.children];
|
let children = [...dom.children];
|
||||||
|
|
||||||
// initializing object to be returned.
|
// initializing object to be returned.
|
||||||
|
|
@ -91,12 +114,12 @@ function getJsonFromXML(dom) {
|
||||||
// if child is array, save the values as array, else as strings.
|
// if child is array, save the values as array, else as strings.
|
||||||
if (childIsArray) {
|
if (childIsArray) {
|
||||||
if (jsonResult[child.nodeName] === undefined) {
|
if (jsonResult[child.nodeName] === undefined) {
|
||||||
jsonResult[child.nodeName] = [getJsonFromXML(child)];
|
jsonResult[child.nodeName] = [this.#getJsonFromXML(child)];
|
||||||
} else {
|
} else {
|
||||||
jsonResult[child.nodeName].push(getJsonFromXML(child));
|
jsonResult[child.nodeName].push(this.#getJsonFromXML(child));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
jsonResult[child.nodeName] = getJsonFromXML(child);
|
jsonResult[child.nodeName] = this.#getJsonFromXML(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +132,7 @@ function getJsonFromXML(dom) {
|
||||||
* @param file the file with the desired content
|
* @param file the file with the desired content
|
||||||
* @returns {Promise<String>} a promise that returns the string contents of the file
|
* @returns {Promise<String>} a promise that returns the string contents of the file
|
||||||
*/
|
*/
|
||||||
async function parseFileToString(file) {
|
async #parseFileToString(file) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let reader = new FileReader()
|
let reader = new FileReader()
|
||||||
reader.readAsText(file, "utf-8")
|
reader.readAsText(file, "utf-8")
|
||||||
|
|
@ -122,21 +145,196 @@ async function parseFileToString(file) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Calculates a Birthdate String in the Calendar of Bosparans Fall
|
*Calculates a Birthdate String in the Calendar of Bosparans Fall
|
||||||
* @param json json with the day, the month and the year of the birthday
|
* @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"
|
* @returns {string} a string in the format of "DD.MMMM.YYYY BF"
|
||||||
*/
|
*/
|
||||||
function calculateBirthdate(json) {
|
#calculateBirthdate(json) {
|
||||||
let day = json.gbtag
|
let day = json.gbtag
|
||||||
let month = months[parseInt(json.gbmonat) - 1]
|
let month = this.#months[parseInt(json.gbmonat) - 1]
|
||||||
let year = json.gbjahr
|
let year = json.gbjahr
|
||||||
|
|
||||||
return `${day}. ${month} ${year} BF`
|
return `${day}. ${month} ${year} BF`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function addSkillFromCompendiumByNameToActor(talentName, taw, actor, combatStatistics, attributes) {
|
/**
|
||||||
|
* parses a json into a fitting character-json
|
||||||
|
* @param {Character} actor
|
||||||
|
* @param rawJson the json parsed from the Helden-Software XML
|
||||||
|
* @param {ImportOptions} options
|
||||||
|
* @returns {{}} a json representation of the character
|
||||||
|
*/
|
||||||
|
#mapRawJson(actor, rawJson, options) {
|
||||||
|
let json = {}
|
||||||
|
let held = rawJson.helden.held;
|
||||||
|
json.name = held.name
|
||||||
|
json.meta = {}
|
||||||
|
if (!options.skipSpecies) this.#mapSpezies(actor, held.basis.rasse) // as string includes the demonymized form
|
||||||
|
if (!options.skipCulture) this.#mapKultur(actor, held.basis.kultur) // as string includes the demonymized form
|
||||||
|
if (!options.skipProfessions) this.#mapProfessions(actor, held.basis.ausbildungen.ausbildung)
|
||||||
|
if (!options.skipMeta) {
|
||||||
|
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 = this.#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].join('\n')
|
||||||
|
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].join('\n')
|
||||||
|
json.meta.titel = held.basis.rasse.aussehen.titel
|
||||||
|
json.meta.stand = held.basis.rasse.aussehen.stand
|
||||||
|
}
|
||||||
|
let attributes = held.eigenschaften.eigenschaft
|
||||||
|
json.attribute = {}
|
||||||
|
if (!options.skipAttributes) {
|
||||||
|
if (held.basis.gilde) {
|
||||||
|
json.attribute.gilde = held.basis.gilde.name
|
||||||
|
}
|
||||||
|
json.attribute.mu = this.#getAttributeJson(attributes, "Mut")
|
||||||
|
json.attribute.kl = this.#getAttributeJson(attributes, "Klugheit")
|
||||||
|
json.attribute.in = this.#getAttributeJson(attributes, "Intuition")
|
||||||
|
json.attribute.ch = this.#getAttributeJson(attributes, "Charisma")
|
||||||
|
json.attribute.ff = this.#getAttributeJson(attributes, "Fingerfertigkeit")
|
||||||
|
json.attribute.ge = this.#getAttributeJson(attributes, "Gewandtheit")
|
||||||
|
json.attribute.ko = this.#getAttributeJson(attributes, "Konstitution")
|
||||||
|
json.attribute.kk = this.#getAttributeJson(attributes, "Körperkraft")
|
||||||
|
json.mr = {
|
||||||
|
mod: this.#filterAttribute(attributes, "Magieresistenz").mod
|
||||||
|
}
|
||||||
|
json.lep = {
|
||||||
|
mod: this.#filterAttribute(attributes, "Lebensenergie").mod
|
||||||
|
}
|
||||||
|
json.aup = {
|
||||||
|
mod: this.#filterAttribute(attributes, "Ausdauer").mod
|
||||||
|
}
|
||||||
|
json.asp = {
|
||||||
|
mod: this.#filterAttribute(attributes, "Astralenergie").mod
|
||||||
|
}
|
||||||
|
json.kap = {
|
||||||
|
mod: this.#filterAttribute(attributes, "Karmaenergie").mod
|
||||||
|
}
|
||||||
|
let attribute = this.#filterAttribute(attributes, "ini")
|
||||||
|
json.ini = {
|
||||||
|
mod: attribute.mod,
|
||||||
|
aktuell: attribute.value
|
||||||
|
}
|
||||||
|
json.attribute.so = this.#getAttributeJson(attributes, "Sozialstatus")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.skipAdvantages) this.#mapAdvantages(actor, held)
|
||||||
|
let specialAbilities = []
|
||||||
|
let liturgies = []
|
||||||
|
for (let specialAbility in held.sf.sonderfertigkeit) {
|
||||||
|
specialAbility = held.sf.sonderfertigkeit[specialAbility]
|
||||||
|
if (specialAbility.name.startsWith("Liturgie:")) {
|
||||||
|
if (!options.skipLiturgies) {
|
||||||
|
liturgies.push({
|
||||||
|
name: specialAbility.name.replace("Liturgie:", "").trim(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!options.skipSpecialAbilities) {
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if (!options.skipSkills) this.#mapSkills(actor, held, combatValues)
|
||||||
|
if (!options.skipSpells) this.#mapSpells(actor, held)
|
||||||
|
if (!options.skipLiturgies) this.#mapLiturgies(actor, liturgies)
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
#getAttributeJson(attributes, name) {
|
||||||
|
let attribute = this.#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
|
||||||
|
*/
|
||||||
|
#filterAttribute(attributes, name) {
|
||||||
|
return attributes.filter(attribute => attribute.name === name)[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
async #addSkillFromCompendiumByNameToActor(talentName, taw, actor, combatStatistics, attributes) {
|
||||||
const compendiumOfSkills = game.packs.get('DSA_4-1.talente');
|
const compendiumOfSkills = game.packs.get('DSA_4-1.talente');
|
||||||
const talentId = compendiumOfSkills.index.find(skill => skill.name === talentName)
|
const talentId = compendiumOfSkills.index.find(skill => skill.name === talentName)
|
||||||
if (talentId) {
|
if (talentId) {
|
||||||
|
|
@ -166,7 +364,7 @@ async function addSkillFromCompendiumByNameToActor(talentName, taw, actor, comba
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addAdvantageFromCompendiumByNameToActor(advantageName, advantageValue, actor) {
|
async #addAdvantageFromCompendiumByNameToActor(advantageName, advantageValue, actor) {
|
||||||
const compendiumOfAdvantages = game.packs.get('DSA_4-1.Advantage');
|
const compendiumOfAdvantages = game.packs.get('DSA_4-1.Advantage');
|
||||||
const advantageId = compendiumOfAdvantages.index.find(skill => skill.name === advantageName)
|
const advantageId = compendiumOfAdvantages.index.find(skill => skill.name === advantageName)
|
||||||
if (advantageId) {
|
if (advantageId) {
|
||||||
|
|
@ -182,8 +380,7 @@ async function addAdvantageFromCompendiumByNameToActor(advantageName, advantageV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addSpellsFromCompendiumByNameToActor(spellName, zfw, representation, hauszauber, actor) {
|
async #addSpellsFromCompendiumByNameToActor(spellName, zfw, representation, hauszauber, actor) {
|
||||||
|
|
||||||
const compendiumOfSpells = game.packs.get('DSA_4-1.spells');
|
const compendiumOfSpells = game.packs.get('DSA_4-1.spells');
|
||||||
const SCREAMING_NAME = spellName.toUpperCase()
|
const SCREAMING_NAME = spellName.toUpperCase()
|
||||||
const spellId = compendiumOfSpells.index.find(spell => spell.name === SCREAMING_NAME)
|
const spellId = compendiumOfSpells.index.find(spell => spell.name === SCREAMING_NAME)
|
||||||
|
|
@ -200,7 +397,7 @@ async function addSpellsFromCompendiumByNameToActor(spellName, zfw, representati
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addLiturgiesFromCompendiumByNameToActor(liturgyName, actor) {
|
async #addLiturgiesFromCompendiumByNameToActor(liturgyName, actor) {
|
||||||
const compendiumOfLiturgies = game.packs.get('DSA_4-1.liturgien');
|
const compendiumOfLiturgies = game.packs.get('DSA_4-1.liturgien');
|
||||||
const liturgyId = compendiumOfLiturgies.index.find(liturgy => {
|
const liturgyId = compendiumOfLiturgies.index.find(liturgy => {
|
||||||
return liturgy.name === LiturgyData.lookupAlias(liturgyName.split(" (")[0])
|
return liturgy.name === LiturgyData.lookupAlias(liturgyName.split(" (")[0])
|
||||||
|
|
@ -217,7 +414,7 @@ async function addLiturgiesFromCompendiumByNameToActor(liturgyName, actor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapSkills(actor, held, kampfwerte) {
|
#mapSkills(actor, held, kampfwerte) {
|
||||||
if (actor.itemTypes["Skill"].length > 0) {
|
if (actor.itemTypes["Skill"].length > 0) {
|
||||||
actor.itemTypes["Skill"].forEach(s => {
|
actor.itemTypes["Skill"].forEach(s => {
|
||||||
actor.items.get(s._id).delete()
|
actor.items.get(s._id).delete()
|
||||||
|
|
@ -248,12 +445,12 @@ function mapSkills(actor, held, kampfwerte) {
|
||||||
} else {
|
} else {
|
||||||
// proceed
|
// proceed
|
||||||
const eigenschaften = held.eigenschaften.eigenschaft
|
const eigenschaften = held.eigenschaften.eigenschaft
|
||||||
addSkillFromCompendiumByNameToActor(talent.name, talent.value, actor, kampfwerte, eigenschaften)
|
this.#addSkillFromCompendiumByNameToActor(talent.name, talent.value, actor, kampfwerte, eigenschaften)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapAdvantages(actor, held) {
|
#mapAdvantages(actor, held) {
|
||||||
if (actor.itemTypes["Advantage"].length > 0) {
|
if (actor.itemTypes["Advantage"].length > 0) {
|
||||||
actor.itemTypes["Advantage"].forEach(a => {
|
actor.itemTypes["Advantage"].forEach(a => {
|
||||||
actor.items.get(a._id).delete()
|
actor.items.get(a._id).delete()
|
||||||
|
|
@ -261,11 +458,11 @@ function mapAdvantages(actor, held) {
|
||||||
}
|
}
|
||||||
for (let advantage in held.vt.vorteil) {
|
for (let advantage in held.vt.vorteil) {
|
||||||
advantage = held.vt.vorteil[advantage]
|
advantage = held.vt.vorteil[advantage]
|
||||||
addAdvantageFromCompendiumByNameToActor(advantage.name, advantage.value, actor)
|
this.#addAdvantageFromCompendiumByNameToActor(advantage.name, advantage.value, actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapSpells(actor, held) {
|
#mapSpells(actor, held) {
|
||||||
if (actor.itemTypes["Spell"].length > 0) {
|
if (actor.itemTypes["Spell"].length > 0) {
|
||||||
actor.itemTypes["Spell"].forEach(s => {
|
actor.itemTypes["Spell"].forEach(s => {
|
||||||
actor.items.get(s._id).delete()
|
actor.items.get(s._id).delete()
|
||||||
|
|
@ -273,11 +470,11 @@ function mapSpells(actor, held) {
|
||||||
}
|
}
|
||||||
for (let spell in held.zauberliste.zauber) {
|
for (let spell in held.zauberliste.zauber) {
|
||||||
spell = held.zauberliste.zauber[spell]
|
spell = held.zauberliste.zauber[spell]
|
||||||
addSpellsFromCompendiumByNameToActor(spell.name, spell.value, spell.repraesentation, spell.hauszauber === "true", actor)
|
this.#addSpellsFromCompendiumByNameToActor(spell.name, spell.value, spell.repraesentation, spell.hauszauber === "true", actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapLiturgies(actor, liturgies) {
|
#mapLiturgies(actor, liturgies) {
|
||||||
if (actor.itemTypes["Liturgy"].length > 0) {
|
if (actor.itemTypes["Liturgy"].length > 0) {
|
||||||
actor.itemTypes["Liturgy"].forEach(l => {
|
actor.itemTypes["Liturgy"].forEach(l => {
|
||||||
actor.items.get(l._id).delete()
|
actor.items.get(l._id).delete()
|
||||||
|
|
@ -285,11 +482,11 @@ function mapLiturgies(actor, liturgies) {
|
||||||
}
|
}
|
||||||
for (let liturgy in liturgies) {
|
for (let liturgy in liturgies) {
|
||||||
liturgy = liturgies[liturgy]
|
liturgy = liturgies[liturgy]
|
||||||
addLiturgiesFromCompendiumByNameToActor(liturgy.name, actor)
|
this.#addLiturgiesFromCompendiumByNameToActor(liturgy.name, actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function mapProfessions(actor, professions) {
|
async #mapProfessions(actor, professions) {
|
||||||
if (actor.itemTypes["Profession"].length > 0) {
|
if (actor.itemTypes["Profession"].length > 0) {
|
||||||
actor.itemTypes["Profession"].forEach(p => {
|
actor.itemTypes["Profession"].forEach(p => {
|
||||||
actor.items.get(p._id).delete()
|
actor.items.get(p._id).delete()
|
||||||
|
|
@ -311,10 +508,9 @@ async function mapProfessions(actor, professions) {
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
// actor.update({"system.meta.professions": professions})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function mapSpezies(actor, spezies) {
|
async #mapSpezies(actor, spezies) {
|
||||||
if (actor.itemTypes["Species"].length > 0) {
|
if (actor.itemTypes["Species"].length > 0) {
|
||||||
actor.itemTypes["Species"].forEach(s => {
|
actor.itemTypes["Species"].forEach(s => {
|
||||||
actor.items.get(s._id).delete()
|
actor.items.get(s._id).delete()
|
||||||
|
|
@ -346,7 +542,7 @@ async function mapSpezies(actor, spezies) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function mapKultur(actor, kultur) {
|
async #mapKultur(actor, kultur) {
|
||||||
if (actor.itemTypes["Culture"].length > 0) {
|
if (actor.itemTypes["Culture"].length > 0) {
|
||||||
actor.itemTypes["Culture"].forEach(c => {
|
actor.itemTypes["Culture"].forEach(c => {
|
||||||
actor.items.get(c._id).delete()
|
actor.items.get(c._id).delete()
|
||||||
|
|
@ -379,180 +575,4 @@ async function mapKultur(actor, kultur) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* parses a json into a fitting character-json
|
|
||||||
* @param {Character} actor
|
|
||||||
* @param rawJson the json parsed from the Helden-Software XML
|
|
||||||
* @param {ImportOptions} options
|
|
||||||
* @returns {{}} a json representation of the character
|
|
||||||
*/
|
|
||||||
function mapRawJson(actor, rawJson, options) {
|
|
||||||
let json = {}
|
|
||||||
let held = rawJson.helden.held;
|
|
||||||
json.name = held.name
|
|
||||||
json.meta = {}
|
|
||||||
if (!options.skipSpecies) mapSpezies(actor, held.basis.rasse) // as string includes the demonymized form
|
|
||||||
if (!options.skipCulture) mapKultur(actor, held.basis.kultur) // as string includes the demonymized form
|
|
||||||
if (!options.skipProfessions) mapProfessions(actor, held.basis.ausbildungen.ausbildung)
|
|
||||||
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].join('\n')
|
|
||||||
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].join('\n')
|
|
||||||
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")
|
|
||||||
if (!options.skipAdvantages) 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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
if (!options.skipSkills) mapSkills(actor, held, combatValues)
|
|
||||||
if (!options.skipSpells) mapSpells(actor, held)
|
|
||||||
if (!options.skipLiturgies) mapLiturgies(actor, liturgies)
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
.application.dsa41.dialog.xmlimport {
|
||||||
|
|
||||||
|
section.window-content {
|
||||||
|
|
||||||
|
section {
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: 32px 1fr 32px;
|
||||||
|
gap: 8px 0;
|
||||||
|
grid-template-areas: "file" "options" "actions";
|
||||||
|
|
||||||
|
.file-input {
|
||||||
|
grid-area: file;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
flex: 0;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
grid-area: options;
|
||||||
|
border-left: 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-right: 0;
|
||||||
|
|
||||||
|
legend {
|
||||||
|
padding: 0 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
|
||||||
|
label {
|
||||||
|
|
||||||
|
height: 21px;
|
||||||
|
|
||||||
|
input {
|
||||||
|
line-height: 21px;
|
||||||
|
height: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
line-height: 21px;
|
||||||
|
height: 21px;
|
||||||
|
vertical-align: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
grid-area: actions;
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,4 +23,5 @@
|
||||||
@use "organisms/culture-sheet";
|
@use "organisms/culture-sheet";
|
||||||
@use "organisms/species-sheet";
|
@use "organisms/species-sheet";
|
||||||
@use "organisms/profession-sheet";
|
@use "organisms/profession-sheet";
|
||||||
|
@use "organisms/xml-import-dialog";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<section>
|
||||||
|
|
||||||
|
<div class="file-input">
|
||||||
|
<label for="file"><span>Quelldatei</span></label><input id="file" type="file" name="file" accept=".xml">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Folgendes <strong>nicht</strong> importieren</legend>
|
||||||
|
|
||||||
|
|
||||||
|
{{#each options}}
|
||||||
|
<div><label><input type="checkbox" name="importOption" value="{{@key}}"><span>{{this}}</span></label>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<button type="submit"><i class="fas fa-upload"></i>Import starten</button>
|
||||||
|
|
||||||
|
</section>
|
||||||
Loading…
Reference in New Issue