diff --git a/module/characterImporter.js b/module/characterImporter.js index b87e50fc..65fa7f6a 100644 --- a/module/characterImporter.js +++ b/module/characterImporter.js @@ -1,52 +1,47 @@ export default class CharacterImporter { - // transform JSON from sw5e.com to Foundry friendly format // and insert new actor - static async transform(rawCharacter){ - const sourceCharacter = JSON.parse(rawCharacter); - + static async transform(rawCharacter) { + const sourceCharacter = JSON.parse(rawCharacter); //source character + const details = { - species: sourceCharacter.attribs.find(e => e.name == "race").current, - background: sourceCharacter.attribs.find(e => e.name == "background").current, - alignment: sourceCharacter.attribs.find(e => e.name == "alignment").current - } - - const hp = { - value: sourceCharacter.attribs.find(e => e.name == "hp").current, - min: 0, - max: sourceCharacter.attribs.find(e => e.name == "hp").current, - temp: sourceCharacter.attribs.find(e => e.name == "hp_temp").current + species: sourceCharacter.attribs.find((e) => e.name == "race").current, + background: sourceCharacter.attribs.find((e) => e.name == "background").current, + alignment: sourceCharacter.attribs.find((e) => e.name == "alignment").current }; - const ac = { - value: sourceCharacter.attribs.find(e => e.name == "ac").current + const hp = { + value: sourceCharacter.attribs.find((e) => e.name == "hp").current, + min: 0, + max: sourceCharacter.attribs.find((e) => e.name == "hp").current, + temp: sourceCharacter.attribs.find((e) => e.name == "hp_temp").current }; const abilities = { str: { - value: sourceCharacter.attribs.find(e => e.name == "strength").current, - proficient: sourceCharacter.attribs.find(e => e.name == 'strength_save_prof').current ? 1 : 0 + value: sourceCharacter.attribs.find((e) => e.name == "strength").current, + proficient: sourceCharacter.attribs.find((e) => e.name == "strength_save_prof").current ? 1 : 0 }, dex: { - value: sourceCharacter.attribs.find(e => e.name == "dexterity").current, - proficient: sourceCharacter.attribs.find(e => e.name == 'dexterity_save_prof').current ? 1 : 0 + value: sourceCharacter.attribs.find((e) => e.name == "dexterity").current, + proficient: sourceCharacter.attribs.find((e) => e.name == "dexterity_save_prof").current ? 1 : 0 }, con: { - value: sourceCharacter.attribs.find(e => e.name == "constitution").current, - proficient: sourceCharacter.attribs.find(e => e.name == 'constitution_save_prof').current ? 1 : 0 + value: sourceCharacter.attribs.find((e) => e.name == "constitution").current, + proficient: sourceCharacter.attribs.find((e) => e.name == "constitution_save_prof").current ? 1 : 0 }, int: { - value: sourceCharacter.attribs.find(e => e.name == "intelligence").current, - proficient: sourceCharacter.attribs.find(e => e.name == 'intelligence_save_prof').current ? 1 : 0 + value: sourceCharacter.attribs.find((e) => e.name == "intelligence").current, + proficient: sourceCharacter.attribs.find((e) => e.name == "intelligence_save_prof").current ? 1 : 0 }, wis: { - value: sourceCharacter.attribs.find(e => e.name == "wisdom").current, - proficient: sourceCharacter.attribs.find(e => e.name == 'wisdom_save_prof').current ? 1 : 0 + value: sourceCharacter.attribs.find((e) => e.name == "wisdom").current, + proficient: sourceCharacter.attribs.find((e) => e.name == "wisdom_save_prof").current ? 1 : 0 }, cha: { - value: sourceCharacter.attribs.find(e => e.name == "charisma").current, - proficient: sourceCharacter.attribs.find(e => e.name == 'charisma_save_prof').current ? 1 : 0 - }, + value: sourceCharacter.attribs.find((e) => e.name == "charisma").current, + proficient: sourceCharacter.attribs.find((e) => e.name == "charisma_save_prof").current ? 1 : 0 + } }; /* ----------------------------------------------------------------- */ @@ -60,58 +55,58 @@ export default class CharacterImporter { /* ----------------------------------------------------------------- */ const skills = { acr: { - value: sourceCharacter.attribs.find(e => e.name == 'acrobatics_type').current + value: sourceCharacter.attribs.find((e) => e.name == "acrobatics_type").current }, ani: { - value: sourceCharacter.attribs.find(e => e.name == 'animal_handling_type').current + value: sourceCharacter.attribs.find((e) => e.name == "animal_handling_type").current }, ath: { - value: sourceCharacter.attribs.find(e => e.name == 'athletics_type').current + value: sourceCharacter.attribs.find((e) => e.name == "athletics_type").current }, dec: { - value: sourceCharacter.attribs.find(e => e.name == 'deception_type').current + value: sourceCharacter.attribs.find((e) => e.name == "deception_type").current }, ins: { - value: sourceCharacter.attribs.find(e => e.name == 'insight_type').current + value: sourceCharacter.attribs.find((e) => e.name == "insight_type").current }, inv: { - value: sourceCharacter.attribs.find(e => e.name == 'investigation_type').current + value: sourceCharacter.attribs.find((e) => e.name == "investigation_type").current }, itm: { - value: sourceCharacter.attribs.find(e => e.name == 'intimidation_type').current + value: sourceCharacter.attribs.find((e) => e.name == "intimidation_type").current }, lor: { - value: sourceCharacter.attribs.find(e => e.name == 'lore_type').current + value: sourceCharacter.attribs.find((e) => e.name == "lore_type").current }, med: { - value: sourceCharacter.attribs.find(e => e.name == 'medicine_type').current + value: sourceCharacter.attribs.find((e) => e.name == "medicine_type").current }, nat: { - value: sourceCharacter.attribs.find(e => e.name == 'nature_type').current + value: sourceCharacter.attribs.find((e) => e.name == "nature_type").current }, per: { - value: sourceCharacter.attribs.find(e => e.name == 'persuasion_type').current + value: sourceCharacter.attribs.find((e) => e.name == "persuasion_type").current }, pil: { - value: sourceCharacter.attribs.find(e => e.name == 'piloting_type').current + value: sourceCharacter.attribs.find((e) => e.name == "piloting_type").current }, prc: { - value: sourceCharacter.attribs.find(e => e.name == 'perception_type').current + value: sourceCharacter.attribs.find((e) => e.name == "perception_type").current }, prf: { - value: sourceCharacter.attribs.find(e => e.name == 'performance_type').current + value: sourceCharacter.attribs.find((e) => e.name == "performance_type").current }, slt: { - value: sourceCharacter.attribs.find(e => e.name == 'sleight_of_hand_type').current + value: sourceCharacter.attribs.find((e) => e.name == "sleight_of_hand_type").current }, ste: { - value: sourceCharacter.attribs.find(e => e.name == 'stealth_type').current + value: sourceCharacter.attribs.find((e) => e.name == "stealth_type").current }, sur: { - value: sourceCharacter.attribs.find(e => e.name == 'survival_type').current + value: sourceCharacter.attribs.find((e) => e.name == "survival_type").current }, tec: { - value: sourceCharacter.attribs.find(e => e.name == 'technology_type').current + value: sourceCharacter.attribs.find((e) => e.name == "technology_type").current } }; @@ -121,11 +116,10 @@ export default class CharacterImporter { data: { abilities: abilities, details: details, + skills: skills, attributes: { - ac: ac, hp: hp - }, - skills: skills + } } }; @@ -135,98 +129,204 @@ export default class CharacterImporter { // Parse all classes and add them to already created actor. // "class" is a reserved word, therefore I use profession where I can. - static async addProfessions(sourceCharacter, actor){ - + static async addProfessions(sourceCharacter, actor) { let result = []; // parse all class and multiclassX items // couldn't get Array.filter to work here for some reason // result = array of objects. each object is a separate class - sourceCharacter.attribs.forEach( (e) => { - if ( CharacterImporter.classOrMulticlass(e.name) ){ + sourceCharacter.attribs.forEach((e) => { + if (CharacterImporter.classOrMulticlass(e.name)) { var t = { profession: CharacterImporter.capitalize(e.current), type: CharacterImporter.baseOrMulti(e.name), level: CharacterImporter.getLevel(e, sourceCharacter) - } + }; result.push(t); } }); // pull classes directly from system compendium and add them to current actor - const professionsPack = await game.packs.get('sw5e.classes').getContent(); - result.forEach( (prof) => { - let assignedProfession = professionsPack.find( o => o.name === prof.profession ); + const professionsPack = await game.packs.get("sw5e.classes").getContent(); + result.forEach((prof) => { + let assignedProfession = professionsPack.find((o) => o.name === prof.profession); assignedProfession.data.data.levels = prof.level; actor.createEmbeddedEntity("OwnedItem", assignedProfession.data, { displaySheet: false }); }); + + this.addSpecies(sourceCharacter.attribs.find((e) => e.name == "race").current, actor); + + this.addPowers( + sourceCharacter.attribs.filter((e) => e.name.search(/repeating_power.+_powername/g) != -1).map((e) => e.current), + actor + ); + + const discoveredItems = sourceCharacter.attribs.filter( + (e) => e.name.search(/repeating_inventory.+_itemname/g) != -1 + ); + const items = discoveredItems.map((item) => { + const id = item.name.match(/-\w{19}/g); + + return { + name: item.current, + quantity: sourceCharacter.attribs.find((e) => e.name === `repeating_inventory_${id}_itemcount`).current + }; + }); + + this.addItems(items, actor); } - static classOrMulticlass(name){ - return name === 'class' || (name.includes('multiclass') && name.length <= 12); + static async addClasses(profession, level, actor) { + let classes = await game.packs.get("sw5e.classes").getContent(); + let assignedClass = classes.find((c) => c.name === profession); + assignedClass.data.data.levels = level; + await actor.createEmbeddedEntity("OwnedItem", assignedClass.data, { displaySheet: false }); } - static baseOrMulti(name){ - if (name === 'class'){ - return 'base_class'; + static classOrMulticlass(name) { + return name === "class" || (name.includes("multiclass") && name.length <= 12); + } + + static baseOrMulti(name) { + if (name === "class") { + return "base_class"; } else { - return 'multi_class'; + return "multi_class"; } } - static getLevel(item, sourceCharacter){ - if (item.name === 'class'){ - let result = sourceCharacter.attribs.find( e => e.name === 'base_level' ).current; + static getLevel(item, sourceCharacter) { + if (item.name === "class") { + let result = sourceCharacter.attribs.find((e) => e.name === "base_level").current; return parseInt(result); } else { - let result = sourceCharacter.attribs.find( e => e.name === `${item.name}_lvl` ).current; + let result = sourceCharacter.attribs.find((e) => e.name === `${item.name}_lvl`).current; return parseInt(result); } } - static capitalize(str){ + static capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); } - static addImportButton(html){ + static async addSpecies(race, actor) { + const species = await game.packs.get("sw5e.species").getContent(); + const assignedSpecies = species.find((c) => c.name === race); + const activeEffects = assignedSpecies.data.effects[0].changes; + const actorData = { data: { abilities: { ...actor.data.data.abilities } } }; + + activeEffects.map((effect) => { + switch (effect.key) { + case "data.abilities.str.value": + actorData.data.abilities.str.value -= effect.value; + break; + + case "data.abilities.dex.value": + actorData.data.abilities.dex.value -= effect.value; + break; + + case "data.abilities.con.value": + actorData.data.abilities.con.value -= effect.value; + break; + + case "data.abilities.int.value": + actorData.data.abilities.int.value -= effect.value; + break; + + case "data.abilities.wis.value": + actorData.data.abilities.wis.value -= effect.value; + break; + + case "data.abilities.cha.value": + actorData.data.abilities.cha.value -= effect.value; + break; + + default: + break; + } + }); + + actor.update(actorData); + + await actor.createEmbeddedEntity("OwnedItem", assignedSpecies.data, { displaySheet: false }); + } + + static async addPowers(powers, actor) { + const forcePowers = await game.packs.get("sw5e.forcepowers").getContent(); + const techPowers = await game.packs.get("sw5e.techpowers").getContent(); + + for (const power of powers) { + const createdPower = forcePowers.find((c) => c.name === power) || techPowers.find((c) => c.name === power); + + if (createdPower) { + await actor.createEmbeddedEntity("OwnedItem", createdPower.data, { displaySheet: false }); + } + } + } + + static async addItems(items, actor) { + const weapons = await game.packs.get("sw5e.weapons").getContent(); + const armors = await game.packs.get("sw5e.armor").getContent(); + const adventuringGear = await game.packs.get("sw5e.adventuringgear").getContent(); + + for (const item of items) { + const createdItem = + weapons.find((c) => c.name.toLowerCase() === item.name.toLowerCase()) || + armors.find((c) => c.name.toLowerCase() === item.name.toLowerCase()) || + adventuringGear.find((c) => c.name.toLowerCase() === item.name.toLowerCase()); + + if (createdItem) { + if (item.quantity != 1) { + createdItem.data.data.quantity = item.quantity; + } + + await actor.createEmbeddedEntity("OwnedItem", createdItem.data, { displaySheet: false }); + } + } + } + + static addImportButton() { const header = $("#actors").find("header.directory-header"); const search = $("#actors").children().find("div.header-search"); const newImportButtonDiv = $("#actors").children().find("div.header-actions").clone(); const newSearch = search.clone(); search.remove(); - newImportButtonDiv.attr('id', 'character-sheet-import'); + newImportButtonDiv.attr("id", "character-sheet-import"); header.append(newImportButtonDiv); newImportButtonDiv.children("button").remove(); - newImportButtonDiv.append(""); + newImportButtonDiv.append( + "" + ); newSearch.appendTo(header); let characterImportButton = $("#cs-import-button"); - characterImportButton.click(ev => { - let content = '

Saved Character JSON Import

' - + ' ' - + '
' - + ''; + characterImportButton.click(() => { + let content = + "

Saved Character JSON Import

" + + ' ' + + "
" + + ''; let importDialog = new Dialog({ title: "Import Character from SW5e.com", content: content, buttons: { - "Import": { + Import: { icon: '', label: "Import Character", - callback: (e) => { - let characterData = $('#character-json').val(); - console.log('Parsing Character JSON'); + callback: () => { + let characterData = $("#character-json").val(); + console.log("Parsing Character JSON"); CharacterImporter.transform(characterData); - } + } }, - "Cancel": { + Cancel: { icon: '', label: "Cancel", - callback: () => {}, + callback: () => {} } } - }) + }); importDialog.render(true); }); - } -} \ No newline at end of file + } +}