forked from GitHub-Mirrors/foundry-sw5e
Merge pull request #190 from unrealkakeman89/character-importer-updates
Character importer updates
This commit is contained in:
commit
20f47110cd
1 changed files with 187 additions and 87 deletions
|
@ -1,52 +1,47 @@
|
||||||
export default class CharacterImporter {
|
export default class CharacterImporter {
|
||||||
|
|
||||||
// transform JSON from sw5e.com to Foundry friendly format
|
// transform JSON from sw5e.com to Foundry friendly format
|
||||||
// and insert new actor
|
// and insert new actor
|
||||||
static async transform(rawCharacter){
|
static async transform(rawCharacter) {
|
||||||
const sourceCharacter = JSON.parse(rawCharacter);
|
const sourceCharacter = JSON.parse(rawCharacter); //source character
|
||||||
|
|
||||||
const details = {
|
const details = {
|
||||||
species: sourceCharacter.attribs.find(e => e.name == "race").current,
|
species: sourceCharacter.attribs.find((e) => e.name == "race").current,
|
||||||
background: sourceCharacter.attribs.find(e => e.name == "background").current,
|
background: sourceCharacter.attribs.find((e) => e.name == "background").current,
|
||||||
alignment: sourceCharacter.attribs.find(e => e.name == "alignment").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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ac = {
|
const hp = {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == "ac").current
|
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 = {
|
const abilities = {
|
||||||
str: {
|
str: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == "strength").current,
|
value: sourceCharacter.attribs.find((e) => e.name == "strength").current,
|
||||||
proficient: sourceCharacter.attribs.find(e => e.name == 'strength_save_prof').current ? 1 : 0
|
proficient: sourceCharacter.attribs.find((e) => e.name == "strength_save_prof").current ? 1 : 0
|
||||||
},
|
},
|
||||||
dex: {
|
dex: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == "dexterity").current,
|
value: sourceCharacter.attribs.find((e) => e.name == "dexterity").current,
|
||||||
proficient: sourceCharacter.attribs.find(e => e.name == 'dexterity_save_prof').current ? 1 : 0
|
proficient: sourceCharacter.attribs.find((e) => e.name == "dexterity_save_prof").current ? 1 : 0
|
||||||
},
|
},
|
||||||
con: {
|
con: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == "constitution").current,
|
value: sourceCharacter.attribs.find((e) => e.name == "constitution").current,
|
||||||
proficient: sourceCharacter.attribs.find(e => e.name == 'constitution_save_prof').current ? 1 : 0
|
proficient: sourceCharacter.attribs.find((e) => e.name == "constitution_save_prof").current ? 1 : 0
|
||||||
},
|
},
|
||||||
int: {
|
int: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == "intelligence").current,
|
value: sourceCharacter.attribs.find((e) => e.name == "intelligence").current,
|
||||||
proficient: sourceCharacter.attribs.find(e => e.name == 'intelligence_save_prof').current ? 1 : 0
|
proficient: sourceCharacter.attribs.find((e) => e.name == "intelligence_save_prof").current ? 1 : 0
|
||||||
},
|
},
|
||||||
wis: {
|
wis: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == "wisdom").current,
|
value: sourceCharacter.attribs.find((e) => e.name == "wisdom").current,
|
||||||
proficient: sourceCharacter.attribs.find(e => e.name == 'wisdom_save_prof').current ? 1 : 0
|
proficient: sourceCharacter.attribs.find((e) => e.name == "wisdom_save_prof").current ? 1 : 0
|
||||||
},
|
},
|
||||||
cha: {
|
cha: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == "charisma").current,
|
value: sourceCharacter.attribs.find((e) => e.name == "charisma").current,
|
||||||
proficient: sourceCharacter.attribs.find(e => e.name == 'charisma_save_prof').current ? 1 : 0
|
proficient: sourceCharacter.attribs.find((e) => e.name == "charisma_save_prof").current ? 1 : 0
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ----------------------------------------------------------------- */
|
/* ----------------------------------------------------------------- */
|
||||||
|
@ -60,58 +55,58 @@ export default class CharacterImporter {
|
||||||
/* ----------------------------------------------------------------- */
|
/* ----------------------------------------------------------------- */
|
||||||
const skills = {
|
const skills = {
|
||||||
acr: {
|
acr: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'acrobatics_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "acrobatics_type").current
|
||||||
},
|
},
|
||||||
ani: {
|
ani: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'animal_handling_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "animal_handling_type").current
|
||||||
},
|
},
|
||||||
ath: {
|
ath: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'athletics_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "athletics_type").current
|
||||||
},
|
},
|
||||||
dec: {
|
dec: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'deception_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "deception_type").current
|
||||||
},
|
},
|
||||||
ins: {
|
ins: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'insight_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "insight_type").current
|
||||||
},
|
},
|
||||||
inv: {
|
inv: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'investigation_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "investigation_type").current
|
||||||
},
|
},
|
||||||
itm: {
|
itm: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'intimidation_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "intimidation_type").current
|
||||||
},
|
},
|
||||||
lor: {
|
lor: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'lore_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "lore_type").current
|
||||||
},
|
},
|
||||||
med: {
|
med: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'medicine_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "medicine_type").current
|
||||||
},
|
},
|
||||||
nat: {
|
nat: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'nature_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "nature_type").current
|
||||||
},
|
},
|
||||||
per: {
|
per: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'persuasion_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "persuasion_type").current
|
||||||
},
|
},
|
||||||
pil: {
|
pil: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'piloting_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "piloting_type").current
|
||||||
},
|
},
|
||||||
prc: {
|
prc: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'perception_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "perception_type").current
|
||||||
},
|
},
|
||||||
prf: {
|
prf: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'performance_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "performance_type").current
|
||||||
},
|
},
|
||||||
slt: {
|
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: {
|
ste: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'stealth_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "stealth_type").current
|
||||||
},
|
},
|
||||||
sur: {
|
sur: {
|
||||||
value: sourceCharacter.attribs.find(e => e.name == 'survival_type').current
|
value: sourceCharacter.attribs.find((e) => e.name == "survival_type").current
|
||||||
},
|
},
|
||||||
tec: {
|
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: {
|
data: {
|
||||||
abilities: abilities,
|
abilities: abilities,
|
||||||
details: details,
|
details: details,
|
||||||
|
skills: skills,
|
||||||
attributes: {
|
attributes: {
|
||||||
ac: ac,
|
|
||||||
hp: hp
|
hp: hp
|
||||||
},
|
}
|
||||||
skills: skills
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -135,98 +129,204 @@ export default class CharacterImporter {
|
||||||
|
|
||||||
// Parse all classes and add them to already created actor.
|
// Parse all classes and add them to already created actor.
|
||||||
// "class" is a reserved word, therefore I use profession where I can.
|
// "class" is a reserved word, therefore I use profession where I can.
|
||||||
static async addProfessions(sourceCharacter, actor){
|
static async addProfessions(sourceCharacter, actor) {
|
||||||
|
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
// parse all class and multiclassX items
|
// parse all class and multiclassX items
|
||||||
// couldn't get Array.filter to work here for some reason
|
// couldn't get Array.filter to work here for some reason
|
||||||
// result = array of objects. each object is a separate class
|
// result = array of objects. each object is a separate class
|
||||||
sourceCharacter.attribs.forEach( (e) => {
|
sourceCharacter.attribs.forEach((e) => {
|
||||||
if ( CharacterImporter.classOrMulticlass(e.name) ){
|
if (CharacterImporter.classOrMulticlass(e.name)) {
|
||||||
var t = {
|
var t = {
|
||||||
profession: CharacterImporter.capitalize(e.current),
|
profession: CharacterImporter.capitalize(e.current),
|
||||||
type: CharacterImporter.baseOrMulti(e.name),
|
type: CharacterImporter.baseOrMulti(e.name),
|
||||||
level: CharacterImporter.getLevel(e, sourceCharacter)
|
level: CharacterImporter.getLevel(e, sourceCharacter)
|
||||||
}
|
};
|
||||||
result.push(t);
|
result.push(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// pull classes directly from system compendium and add them to current actor
|
// pull classes directly from system compendium and add them to current actor
|
||||||
const professionsPack = await game.packs.get('sw5e.classes').getContent();
|
const professionsPack = await game.packs.get("sw5e.classes").getContent();
|
||||||
result.forEach( (prof) => {
|
result.forEach((prof) => {
|
||||||
let assignedProfession = professionsPack.find( o => o.name === prof.profession );
|
let assignedProfession = professionsPack.find((o) => o.name === prof.profession);
|
||||||
assignedProfession.data.data.levels = prof.level;
|
assignedProfession.data.data.levels = prof.level;
|
||||||
actor.createEmbeddedEntity("OwnedItem", assignedProfession.data, { displaySheet: false });
|
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){
|
static async addClasses(profession, level, actor) {
|
||||||
return name === 'class' || (name.includes('multiclass') && name.length <= 12);
|
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){
|
static classOrMulticlass(name) {
|
||||||
if (name === 'class'){
|
return name === "class" || (name.includes("multiclass") && name.length <= 12);
|
||||||
return 'base_class';
|
}
|
||||||
|
|
||||||
|
static baseOrMulti(name) {
|
||||||
|
if (name === "class") {
|
||||||
|
return "base_class";
|
||||||
} else {
|
} else {
|
||||||
return 'multi_class';
|
return "multi_class";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static getLevel(item, sourceCharacter){
|
static getLevel(item, sourceCharacter) {
|
||||||
if (item.name === 'class'){
|
if (item.name === "class") {
|
||||||
let result = sourceCharacter.attribs.find( e => e.name === 'base_level' ).current;
|
let result = sourceCharacter.attribs.find((e) => e.name === "base_level").current;
|
||||||
return parseInt(result);
|
return parseInt(result);
|
||||||
} else {
|
} 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);
|
return parseInt(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static capitalize(str){
|
static capitalize(str) {
|
||||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
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 header = $("#actors").find("header.directory-header");
|
||||||
const search = $("#actors").children().find("div.header-search");
|
const search = $("#actors").children().find("div.header-search");
|
||||||
const newImportButtonDiv = $("#actors").children().find("div.header-actions").clone();
|
const newImportButtonDiv = $("#actors").children().find("div.header-actions").clone();
|
||||||
const newSearch = search.clone();
|
const newSearch = search.clone();
|
||||||
search.remove();
|
search.remove();
|
||||||
newImportButtonDiv.attr('id', 'character-sheet-import');
|
newImportButtonDiv.attr("id", "character-sheet-import");
|
||||||
header.append(newImportButtonDiv);
|
header.append(newImportButtonDiv);
|
||||||
newImportButtonDiv.children("button").remove();
|
newImportButtonDiv.children("button").remove();
|
||||||
newImportButtonDiv.append("<button class='create-entity' id='cs-import-button'><i class='fas fa-upload'></i> Import Character</button>");
|
newImportButtonDiv.append(
|
||||||
|
"<button class='create-entity' id='cs-import-button'><i class='fas fa-upload'></i> Import Character</button>"
|
||||||
|
);
|
||||||
newSearch.appendTo(header);
|
newSearch.appendTo(header);
|
||||||
|
|
||||||
let characterImportButton = $("#cs-import-button");
|
let characterImportButton = $("#cs-import-button");
|
||||||
characterImportButton.click(ev => {
|
characterImportButton.click(() => {
|
||||||
let content = '<h1>Saved Character JSON Import</h1> '
|
let content =
|
||||||
+ '<label for="character-json">Paste character JSON here:</label> '
|
"<h1>Saved Character JSON Import</h1> " +
|
||||||
+ '</br>'
|
'<label for="character-json">Paste character JSON here:</label> ' +
|
||||||
+ '<textarea id="character-json" name="character-json" rows="10" cols="50"></textarea>';
|
"</br>" +
|
||||||
|
'<textarea id="character-json" name="character-json" rows="10" cols="50"></textarea>';
|
||||||
let importDialog = new Dialog({
|
let importDialog = new Dialog({
|
||||||
title: "Import Character from SW5e.com",
|
title: "Import Character from SW5e.com",
|
||||||
content: content,
|
content: content,
|
||||||
buttons: {
|
buttons: {
|
||||||
"Import": {
|
Import: {
|
||||||
icon: '<i class="fas fa-file-import"></i>',
|
icon: '<i class="fas fa-file-import"></i>',
|
||||||
label: "Import Character",
|
label: "Import Character",
|
||||||
callback: (e) => {
|
callback: () => {
|
||||||
let characterData = $('#character-json').val();
|
let characterData = $("#character-json").val();
|
||||||
console.log('Parsing Character JSON');
|
console.log("Parsing Character JSON");
|
||||||
CharacterImporter.transform(characterData);
|
CharacterImporter.transform(characterData);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Cancel": {
|
Cancel: {
|
||||||
icon: '<i class="fas fa-times-circle"></i>',
|
icon: '<i class="fas fa-times-circle"></i>',
|
||||||
label: "Cancel",
|
label: "Cancel",
|
||||||
callback: () => {},
|
callback: () => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
importDialog.render(true);
|
importDialog.render(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue