From 9c7d90d307b014a21e9739bc0bf97bea21ee6446 Mon Sep 17 00:00:00 2001 From: zarmstrong Date: Mon, 7 Mar 2022 11:59:00 -0700 Subject: [PATCH] update module.json for 0.9.0 --- module.json | 2 +- pathbuilder-import-min.js | 69 +-------------------------------------- pathbuilder-import.js | 2 +- 3 files changed, 3 insertions(+), 70 deletions(-) diff --git a/module.json b/module.json index cc2ca31..287f102 100644 --- a/module.json +++ b/module.json @@ -14,7 +14,7 @@ "license": "MIT", "url": "https://github.com/zarmstrong/foundry-pathbuilder2e-import", "manifest": "https://raw.githubusercontent.com/zarmstrong/foundry-pathbuilder2e-import/master/module.json", - "download": "https://github.com/zarmstrong/foundry-pathbuilder2e-import/releases/download/foundry-pathbuilder2e-import-0.7.5/foundry-pathbuilder2e-import-0.7.5.zip", + "download": "https://github.com/zarmstrong/foundry-pathbuilder2e-import/releases/download/foundry-pathbuilder2e-import-0.9.0/foundry-pathbuilder2e-import-0.9.0.zip", "changelog": "https://github.com/zarmstrong/foundry-pathbuilder2e-import/blob/master/CHANGELOG.md", "bugs": "https://github.com/zarmstrong/herovau.lt-foundry/issues", "flags": { diff --git a/pathbuilder-import-min.js b/pathbuilder-import-min.js index 87de9d5..0851b52 100644 --- a/pathbuilder-import-min.js +++ b/pathbuilder-import-min.js @@ -1,68 +1 @@ -var fbpiDebug=!1;const fpbi="0.7.5",reportDomain="https://www.pf2player.com/",pbcolor1="color: #7bf542",pbcolor2="color: #d8eb34",pbcolor3="color: #ffffff",pbcolor4="color: #cccccc",pbcolor5="color: #ff0000";var buildID,pcAlign,applyChanges=!1,finishedFeats=!1,finishedActions=!1,finishedClassFeatures=!1,finishedAncestryFeatures=!1,finishedEquipment=!1,finishedSpells=!1,addFeats=!1,addEquipment=!1,addMoney=!1,addSpellcasters=!1,deleteAll=!1,heroVaultExport=!1,reportMissedItems=!1,allItems=[],jsonBuild=[],addedItems=[],pbButton=!0,focusPool=0,focusWarning=0;async function doHVExport(hero,act){game.modules.get("herovaultfoundry")?.api?.exportToHVFromPBHLO(hero,act)}async function beginPathbuilderImport(targetActor,isHV=!1){finishedSpells=finishedEquipment=finishedAncestryFeatures=finishedClassFeatures=finishedActions=finishedFeats=applyChanges=!1,allItems=[];let heroVault=isHV?'

':"";new Dialog({title:"Pathbuilder Import",content:` -
-

It is strongly advised to import to a blank PC and not overwrite an existing PC.

-
-

Step 1: Refresh this browser page!

-

Step 2: Export your character from Pathbuilder 2e via the app menu

-

Step 3: Enter the 6 digit user ID number from the pathbuilder export dialog below

-
-

Please note - items which cannot be matched to the Foundry database will not be imported!

-

All inventory items will be removed upon import. The option to turn this off will return in the future. If you need to keep items, I recommend creating a new PC, importing via Pathbuilder to the new PC, then dragging inventory items from old PC to new PC.

-
-
-
- -

- -
- -

- - -

- ${heroVault} -
-
- Enter your pathbuilder user ID number
-
-
- -
-
-
-

- - `,buttons:{yes:{icon:"",label:"Import",callback:()=>applyChanges=!0},no:{icon:"",label:"Cancel"}},default:"yes",close:html=>{applyChanges&&(isNormalInteger(buildID=html.find('[id="textBoxBuildID"]')[0].value)?(addFeats=html.find('[name="checkBoxFeats"]')[0].checked,addEquipment=html.find('[name="checkBoxEquipment"]')[0].checked,addMoney=html.find('[name="checkBoxMoney"]')[0].checked,addSpellcasters=html.find('[name="checkBoxSpells"]')[0].checked,deleteAll=!0,isHV&&(heroVaultExport=html.find('[name="checkBoxHVExport"]')[0].checked),fbpiDebug&&console.log("%cPathbuilder2e Import | %cGot heroVaultExport:"+heroVaultExport,pbcolor1,pbcolor4),fetchPathbuilderBuild(targetActor,buildID)):ui.notifications.warn("Build ID must be a positive integer!"))}}).render(!0)}function isNormalInteger(str){var n=Math.floor(Number(str));return n!==1/0&&String(n)===str&&0<=n}function fetchPathbuilderBuild(targetActor,buildID){var xmlhttp=new XMLHttpRequest;xmlhttp.onreadystatechange=function(){var responseJSON;4==this.readyState&&200==this.status&&(responseJSON=JSON.parse(this.responseText),fbpiDebug&&console.log(responseJSON),responseJSON.success?(jsonBuild=responseJSON.build,checkCharacterIsCorrect(targetActor,responseJSON.build)):ui.notifications.warn("Unable to find a character with this build id!"))},xmlhttp.open("GET","https://www.pathbuilder2e.com/json.php?id="+buildID,!0),xmlhttp.send()}function checkCharacterIsCorrect(targetActor,jsonBuild){let correctCharacter=!1;new Dialog({title:jsonBuild.name,content:` -
Importing `+jsonBuild.name+", level "+jsonBuild.level+`


- `,buttons:{yes:{icon:"",label:"Proceed",callback:()=>correctCharacter=!0},no:{icon:"",label:"Cancel"}},default:"yes",close:html=>{correctCharacter&&(ui.notifications.info("Please be patient while "+jsonBuild.name+" is imported."),ui.notifications.info("The import can take up to 1 minute on slower systems."),importCharacter(targetActor,jsonBuild))}}).render(!0)}function shouldBeManuallyDeleted(i){return("feat"!=i.data.type||"ancestryfeature"!=i.data.data.featType.value)&&("spell"!=i.data.type&&"spellcastingEntry"!=i.data.type)}async function importCharacter(targetActor,jsonBuild){if(deleteAll){fbpiDebug&&console.log("%cPathbuilder2e Import | %cDeleting all items",pbcolor1,pbcolor4);await targetActor.deleteEmbeddedDocuments("Item",["123"],{deleteAll:!0})}else if(addMoney){fbpiDebug&&console.log("%cPathbuilder2e Import | %cDeleting money",pbcolor1,pbcolor4);let items=targetActor.data.items.filter(i=>"Platinum Pieces"===i.name||"Gold Pieces"===i.name||"Silver Pieces"===i.name||"Copper Pieces"===i.name);var conEven=items.map(i=>i.id);await targetActor.deleteEmbeddedDocuments("Item",conEven)}let arrayFeats=jsonBuild.feats,arrayEquipment=jsonBuild.equipment,arrayWeapons=jsonBuild.weapons,arrayArmor=jsonBuild.armor,arraySpecials=jsonBuild.specials;var arrayLores=jsonBuild.lores,backpackData=[];jsonBuild.proficiencies.castingArcane,jsonBuild.proficiencies.castingDivine,jsonBuild.proficiencies.castingOccult,jsonBuild.proficiencies.castingPrimal;for(ref in pcAlign=jsonBuild.alignment,jsonBuild.languages)jsonBuild.languages.hasOwnProperty(ref)&&(jsonBuild.languages[ref]=jsonBuild.languages[ref].toLowerCase());for(ref in arrayEquipment)arrayEquipment[ref][0]=mapItemToFoundryName(arrayEquipment[ref][0]);for(ref in fbpiDebug&&console.log("%cPathbuilder2e Import | %c Working on arraySpecials: "+arraySpecials,pbcolor1,pbcolor4),arraySpecials)fbpiDebug&&console.log("%cPathbuilder2e Import | %c Checking arraySpecials[ref]: "+arraySpecials[ref],pbcolor1,pbcolor4),void 0!==arraySpecials[ref][0]&&(arraySpecials[ref]=mapSpecialToFoundryName(arraySpecials[ref]));for(ref in fbpiDebug&&console.log("%cPathbuilder2e Import | %c Finished arraySpecials: "+arraySpecials,pbcolor1,pbcolor4),fbpiDebug&&console.log("%cPathbuilder2e Import | %c Working on arrayFeats: "+arrayFeats,pbcolor1,pbcolor4),arrayFeats)fbpiDebug&&console.log("%cPathbuilder2e Import | %c Checking arrayFeats[ref][0]: "+arrayFeats[ref][0],pbcolor1,pbcolor4),void 0!==arrayFeats[ref][0]&&(arrayFeats[ref][0]=mapSpecialToFoundryName(arrayFeats[ref][0]));fbpiDebug&&console.log("%cPathbuilder2e Import | %c Finished arrayFeats: "+arrayFeats,pbcolor1,pbcolor4),[arraySpecials,arrayFeats,backpackData]=findSpecialThings(arraySpecials,arrayFeats,backpackData);var senses=[];for(ref in arraySpecials)arraySpecials.hasOwnProperty(ref)&&("Low-Light Vision"==arraySpecials[ref]?senses.push({exceptions:"",label:"Low-Light Vision",type:"lowLightVision",value:""}):"Darkvision"==arraySpecials[ref]&&senses.push({exceptions:"",label:"Darkvision",type:"darkvision",value:""}));conEven=(jsonBuild.abilities.con%2==0?jsonBuild.abilities.con:jsonBuild.abilities.con-1)-10;let conBonus=0;conBonus=0=item.data.data.items[classFeatureItem].level&&(newFeature={id:item.data.data.items[classFeatureItem].id,pack:item.data.data.items[classFeatureItem].pack,name:item.data.data.items[classFeatureItem].name},classFeatures.push(newFeature))}}if(targetActor.data.data.details.ancestry!=jsonBuild.ancestry)for(const item of await game.packs.get("pf2e.ancestries").getDocuments())item.data.data.slug!=getSlug(jsonBuild.ancestry)&&item.data.data.slug!=getSlugNoQuote(jsonBuild.ancestry)||allItems.push(item.data);let blacklist=[jsonBuild.heritage,"Great Fortitude","Divine Spellcasting","Divine Ally (Blade)","Divine Ally (Shield)","Divine Ally (Steed)","Divine Smite (Antipaladin)","Divine Smite (Paladin)","Divine Smite (Desecrator)","Divine Smite (Liberator)","Divine Smite (Redeemer)","Divine Smite (Tyrant)","Exalt (Antipaladin)","Exalt (Paladin)","Exalt (Desecrator)","Exalt (Redeemer)","Exalt (Liberator)","Exalt (Tyrant)","Intimidation","Axe","Sword","Water","Sword Cane","Battle Axe","Bane","Air","Occultism","Performance","Alchemy","Nature","Red","Shark","Green","Divine","Sun","Fire","Might","Mace","Bronze","Spirit","Zeal","Battledancer","Light Armor Expertise","Religion","Polearm","Longsword","Moon","","","","","","","","","","","","","","","Hammer","Athletics","Deception","Society","Occultism","Arcane","Simple Weapon Expertise","Defensive Robes","Magical Fortitude","Occult","Acrobatics","Medicine","Diplomacy","Might","Reflex","Evasion","Vigilant Senses","Iron Will","Lightning Reflexes","Alertness","Shield Block","Anathema","Druidic Language","Weapon Expertise","Armor Expertise","Armor Mastery","Darkvision","Stealth","Divine","Shield","Survival","Arcana","Will","Fortitude","Signature Spells","Low-Light Vision","Powerful Fist","Mystic Strikes","Incredible Movement","Claws","Wild Empathy","Aquatic Adaptation","Resolve","Expert Spellcaster","Master Spellcaster","Legendary Spellcaster","Weapon Specialization","Mighty Rage","Deny Advantage","Critical Brutality","Juggernaut","Medium Armor Expertise","Weapon Specialization (Barbarian)","Greater Weapon Specialization","Diplomacy","Improved Evasion","Weapon Mastery","Incredible Senses"];for(const cf in classFeatures)blacklist.push(classFeatures[cf].name);arraySpecials=arraySpecials.filter(val=>!blacklist.includes(val)),jsonBuild.specials=uniq(arraySpecials),addFeats?(finishedClassFeatures=finishedAncestryFeatures=!0,await addFeatItems(targetActor,arrayFeats),await addFeatItems(targetActor,arraySpecials),await addActionItems(targetActor,arraySpecials),await addAncestryFeatureItems(targetActor,arraySpecials),await addClassFeatureItems(targetActor,arraySpecials,classFeatures),await addClassFeatureItems(targetActor,backpackData,classFeatures)):(finishedClassFeatures=finishedActions=finishedAncestryFeatures=finishedFeats=!0,checkAllFinishedAndCreate(targetActor)),blacklist=["Bracers of Armor","","","","",""];for(const cf in allItems)blacklist.push(allItems[cf].name);if(allItems=allItems.filter(function(a){return!this[a._id]&&(this[a._id]=!0)},Object.create(null)),addEquipment){let pack=game.packs.get("pf2e.equipment-srd"),content=await game.packs.get("pf2e.equipment-srd").getDocuments();backpackData=await pack.getDocuments("3lgwjrFEsQVKzhh7");let backpackInstance=[],arrayKit=[];hasAdventurersPack(arrayEquipment)&&(backpackInstance=await targetActor.createEmbeddedDocuments("Item",backpackData),arrayKit.push(["bedroll",1]),arrayKit.push(["chalk",10]),arrayKit.push(["flint-and-steel",1]),arrayKit.push(["rope",1]),arrayKit.push(["rations",14]),arrayKit.push(["torch",5]),arrayKit.push(["waterskin",1]));for(const action of content.filter(item=>equipmentIsRequired(item,arrayEquipment,arrayWeapons,arrayArmor,arrayKit,addMoney))){for(var ref in arrayEquipment)if(fbpiDebug&&console.log("%cPathbuilder2e Import | %c arrayEquipment[ref]: "+arrayEquipment[ref],pbcolor1,pbcolor4),arrayEquipment.hasOwnProperty(ref)){var itemName=arrayEquipment[ref][0];if(isNameMatch(itemName,action.data.data.slug)&&needsNewInstanceofItem(targetActor,arrayEquipment[ref][0])){var itemAmount=arrayEquipment[ref][1];arrayEquipment[ref].added=!0;const clonedData=JSON.parse(JSON.stringify(action.data));"kit"!=clonedData.type&&(clonedData.data.quantity.value=itemAmount,allItems.push(clonedData))}}for(var ref in arrayKit)if(arrayKit.hasOwnProperty(ref))if(arrayKit[ref][0]===action.data.data.slug&&needsNewInstanceofItem(targetActor,itemName)){itemAmount=arrayKit[ref][1];const clonedData=JSON.parse(JSON.stringify(action.data));clonedData.data.quantity.value=itemAmount,clonedData.data.containerId.value=backpackInstance.id,allItems.push(clonedData)}for(var ref in arrayWeapons)if(arrayWeapons.hasOwnProperty(ref)){var material,weaponDetails=arrayWeapons[ref];if(isNameMatch(weaponDetails.name,action.data.data.slug)&&needsNewInstanceofItem(targetActor,weaponDetails.name)){weaponDetails.added=!0;const clonedData=JSON.parse(JSON.stringify(action.data));clonedData.data.quantity.value=weaponDetails.qty,clonedData.data.damage.die=weaponDetails.die,clonedData.data.potencyRune.value=weaponDetails.pot,clonedData.data.strikingRune.value=weaponDetails.str,weaponDetails.runes[0]&&(clonedData.data.propertyRune1.value=camelCase(weaponDetails.runes[0])),weaponDetails.runes[1]&&(clonedData.data.propertyRune2.value=camelCase(weaponDetails.runes[1])),weaponDetails.runes[2]&&(clonedData.data.propertyRune3.value=camelCase(weaponDetails.runes[2])),weaponDetails.runes[3]&&(clonedData.data.propertyRune4.value=camelCase(weaponDetails.runes[3])),weaponDetails.mat&&(material=weaponDetails.mat.split(" (")[0],clonedData.data.preciousMaterial.value=camelCase(material),clonedData.data.preciousMaterialGrade.value=getMaterialGrade(weaponDetails.mat)),weaponDetails.display&&(clonedData.name=weaponDetails.display),allItems.push(clonedData)}}for(var ref in arrayArmor)if(arrayArmor.hasOwnProperty(ref)){var armorDetails=arrayArmor[ref];if(fbpiDebug&&console.log("%cPathbuilder2e Import | %c armorDetails.name: "+armorDetails.name,pbcolor1,pbcolor4),isNameMatch(armorDetails.name,action.data.data.slug)&&needsNewInstanceofItem(targetActor,armorDetails.name)){armorDetails.added=!0;const clonedData=JSON.parse(JSON.stringify(action.data));if(notBracersOfArmor(armorDetails.name)){if(clonedData.data.quantity.value=armorDetails.qty,clonedData.data.category=armorDetails.prof,clonedData.data.potencyRune.value=armorDetails.pot,clonedData.data.resiliencyRune.value=armorDetails.res,armorDetails.worn?clonedData.data.equipped.value=!0:clonedData.data.equipped.value=!1,armorDetails.runes[0]&&(clonedData.data.propertyRune1.value=camelCase(armorDetails.runes[0])),armorDetails.runes[1]&&(clonedData.data.propertyRune2.value=camelCase(armorDetails.runes[1])),armorDetails.runes[2]&&(clonedData.data.propertyRune3.value=camelCase(armorDetails.runes[2])),armorDetails.runes[3]&&(clonedData.data.propertyRune4.value=camelCase(armorDetails.runes[3])),armorDetails.mat){let material=armorDetails.mat.split(" (")[0];clonedData.data.preciousMaterial.value=camelCase(material),clonedData.data.preciousMaterialGrade.value=getMaterialGrade(armorDetails.mat)}armorDetails.display&&(clonedData.name=armorDetails.display)}allItems.push(clonedData)}}if(addMoney)if("platinum-pieces"===action.data.data.slug){const clonedData=JSON.parse(JSON.stringify(action.data));clonedData.data.quantity.value=jsonBuild.money.pp,allItems.push(clonedData)}else if("gold-pieces"===action.data.data.slug){const clonedData=JSON.parse(JSON.stringify(action.data));clonedData.data.quantity.value=jsonBuild.money.gp,allItems.push(clonedData)}else if("silver-pieces"===action.data.data.slug){const clonedData=JSON.parse(JSON.stringify(action.data));clonedData.data.quantity.value=jsonBuild.money.sp,allItems.push(clonedData)}else if("copper-pieces"===action.data.data.slug){const clonedData=JSON.parse(JSON.stringify(action.data));clonedData.data.quantity.value=jsonBuild.money.cp,allItems.push(clonedData)}}finishedEquipment=!0,checkAllFinishedAndCreate(targetActor)}else finishedEquipment=!0,checkAllFinishedAndCreate(targetActor);addSpellcasters?setSpellcasters(targetActor,jsonBuild.spellCasters):(finishedSpells=!0,checkAllFinishedAndCreate(targetActor)),addLores(targetActor,arrayLores)}function getExistingAncestrySlug(targetActor){for(var item in targetActor.data.items)if(targetActor.data.items.hasOwnProperty(item)){item=targetActor.data.items[item];if("ancestry"==item.type)return item.data.slug}return null}function notBracersOfArmor(name){return!name.toLowerCase().includes("bracers of armor")}function camelCase(str){return str.replace(/(?:^\w|[A-Z]|\b\w)/g,function(word,index){return 0==index?word.toLowerCase():word.toUpperCase()}).replace(/\s+/g,"")}function getMaterialGrade(material){return material.toLowerCase().includes("high-grade")?"high":material.toLowerCase().includes("standard-grade")?"standard":"low"}function makeid(length){for(var result="",characters="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",charactersLength=characters.length,i=0;ifeatIsRequired(item,arrayFeats)))for(var ref in arrayFeats)if(fbpiDebug&&console.log("%cPathbuilder2e Import | %c Looking at feat: "+arrayFeats[ref],pbcolor1,pbcolor4),arrayFeats.hasOwnProperty(ref)){var pathbuilderFeatItem=arrayFeats[ref],itemName=pathbuilderFeatItem[0],itemExtra=pathbuilderFeatItem[1];if(isNameMatch(itemName,action.data.data.slug)&&needsNewInstanceofFeat(targetActor,itemName,itemExtra)){var location,displayName=itemName;addedItems.push(itemName),null!=itemExtra&&(displayName+=" ("+itemExtra+")");const clonedData=JSON.parse(JSON.stringify(action.data));clonedData.name=displayName;try{pathbuilderFeatItem[2]&&pathbuilderFeatItem[3]&&(location=getFoundryFeatLocation(pathbuilderFeatItem[2],pathbuilderFeatItem[3]),usedLocations.includes(location)||(clonedData.data.location=location,usedLocations.push(location)))}catch(err){console.log(err)}clonedData._id=makeid(16),allItems.push(clonedData)}}content=await game.packs.get("pf2e.ancestryfeatures").getDocuments();for(const action of content.filter(item=>featIsRequired(item,arrayFeats)))for(var ref in arrayFeats)if(arrayFeats.hasOwnProperty(ref)){let pathbuilderFeatItem=arrayFeats[ref];itemName=pathbuilderFeatItem[0],itemExtra=pathbuilderFeatItem[1];if(isNameMatch(itemName,action.data.data.slug)&&needsNewInstanceofFeat(targetActor,itemName,itemExtra)){displayName=itemName;addedItems.push(itemName),null!=itemExtra&&(displayName+=" ("+itemExtra+")");const clonedData=JSON.parse(JSON.stringify(action.data));clonedData.name=displayName;try{if(pathbuilderFeatItem[2]&&pathbuilderFeatItem[3]){let location=getFoundryFeatLocation(pathbuilderFeatItem[2],pathbuilderFeatItem[3]);usedLocations.includes(location)||(clonedData.data.location=location,usedLocations.push(location))}}catch(err){console.log(err)}allItems.push(clonedData)}}finishedFeats=!0,checkAllFinishedAndCreate(targetActor)}function isNameMatch(pathbuilderItemName,foundryItemSlug){return getSlug(pathbuilderItemName)==foundryItemSlug||(getSlugNoQuote(pathbuilderItemName)==foundryItemSlug||(getSlug(getClassAdjustedSpecialNameLowerCase(pathbuilderItemName))==foundryItemSlug||(getSlug(getAncestryAdjustedSpecialNameLowerCase(pathbuilderItemName))==foundryItemSlug||getSlug(getHeritageAdjustedSpecialNameLowerCase(pathbuilderItemName))==foundryItemSlug)))}async function addActionItems(targetActor,arraySpecials){let content=await game.packs.get("pf2e.actionspf2e").getDocuments();for(const action of content.filter(item=>specialIsRequired(item,arraySpecials)))for(var itemName in arraySpecials)!arraySpecials.hasOwnProperty(itemName)||isNameMatch(itemName=arraySpecials[itemName],action.data.data.slug)&&needsNewInstanceofItem(targetActor,itemName)&&(addedItems.push(itemName),allItems.push(action.data));finishedActions=!0,checkAllFinishedAndCreate(targetActor)}async function addAncestryFeatureItems(targetActor,arraySpecials){let content=await game.packs.get("pf2e.ancestryfeatures").getDocuments();for(const action of content.filter(item=>specialIsRequired(item,arraySpecials)))for(var itemName in arraySpecials)!arraySpecials.hasOwnProperty(itemName)||isNameMatch(itemName=arraySpecials[itemName],action.data.data.slug)&&needsNewInstanceofItem(targetActor,itemName)&&(addedItems.push(itemName),allItems.push(action.data));finishedAncestryFeatures=!0,checkAllFinishedAndCreate(targetActor)}async function addAncestryFeatureFeatItems(targetActor,arraySpecials){let content=await game.packs.get("pf2e.ancestryfeatures").getDocuments();for(const action of content.filter(item=>specialIsRequired(item,arraySpecials)))for(var itemName in arraySpecials)!arraySpecials.hasOwnProperty(itemName)||isNameMatch(itemName=arraySpecials[itemName],action.data.data.slug)&&needsNewInstanceofItem(targetActor,itemName)&&(addedItems.push(itemName),allItems.push(action.data));finishedAncestryFeatureFeats=!0,checkAllFinishedAndCreate(targetActor)}async function addClassFeatureItems(targetActor,arraySpecials,arrayCF){let content=await game.packs.get("pf2e.classfeatures").getDocuments();for(const action of content.filter(item=>specialIsRequired(item,arraySpecials)))for(var ref in arraySpecials)arraySpecials.hasOwnProperty(ref)&&isNameMatch(itemName=arraySpecials[ref],action.data.data.slug)&&needsNewInstanceofItem(targetActor,itemName)&&(addedItems.push(itemName),allItems.push(action.data));let classFeatures=arrayCF.map(a=>a.name);for(const action of content.filter(item=>specialIsRequired(item,classFeatures)))for(var ref in classFeatures){var itemName;isNameMatch(itemName=classFeatures[ref],action.data.data.slug)&&needsNewInstanceofItem(targetActor,itemName)&&(addedItems.push(itemName),allItems.push(action.data))}finishedClassFeatures=!0,checkAllFinishedAndCreate(targetActor)}function hasAdventurersPack(arrayEquipment){for(var ref in arrayEquipment)if(arrayEquipment.hasOwnProperty(ref))if("Adventurer's Pack"===arrayEquipment[ref][0])return arrayEquipment[ref].added=!0;return!1}function isSpecialsPack(packName){return"actionspf2e"===packName||"ancestryfeatures"===packName||"classfeatures"===packName}function featIsRequired(item,arrayFeats){for(var featDetails in arrayFeats)if(arrayFeats.hasOwnProperty(featDetails)){if(getSlug(arrayFeats[featDetails][0])==item.data.data.slug)return!0;if(getSlugNoQuote(arrayFeats[featDetails][0])==item.data.data.slug)return!0;if(getSlug(getClassAdjustedSpecialNameLowerCase(arrayFeats[featDetails][0]))==item.data.data.slug)return!0;if(getSlug(getAncestryAdjustedSpecialNameLowerCase(arrayFeats[featDetails][0]))==item.data.data.slug)return!0;if(getSlug(getHeritageAdjustedSpecialNameLowerCase(arrayFeats[featDetails][0]))==item.data.data.slug)return!0}return!1}function specialIsRequired(item,arraySpecials){for(var ref in arraySpecials)if(arraySpecials.hasOwnProperty(ref)){if(getSlug(arraySpecials[ref])==item.data.data.slug||getSlugNoQuote(arraySpecials[ref])==item.data.data.slug)return!0;if(getSlug(getClassAdjustedSpecialNameLowerCase(arraySpecials[ref]))==item.data.data.slug||getSlugNoQuote(getClassAdjustedSpecialNameLowerCase(arraySpecials[ref]))==item.data.data.slug)return!0;if(getSlug(getAncestryAdjustedSpecialNameLowerCase(arraySpecials[ref]))==item.data.data.slug||getSlugNoQuote(getAncestryAdjustedSpecialNameLowerCase(arraySpecials[ref]))==item.data.data.slug)return!0;if(getSlug(getHeritageAdjustedSpecialNameLowerCase(arraySpecials[ref]))==item.data.data.slug||getSlugNoQuote(getHeritageAdjustedSpecialNameLowerCase(arraySpecials[ref]))==item.data.data.slug)return!0}return!1}function equipmentIsRequired(item,arrayEquipment,arrayWeapons,arrayArmor,arrayKit,addMoney){for(var ref in arrayEquipment)if(arrayEquipment.hasOwnProperty(ref)){if(getSlug(arrayEquipment[ref][0])===item.data.data.slug)return!0;if(getSlugNoQuote(arrayEquipment[ref][0])===item.data.data.slug)return!0}for(var ref in arrayWeapons)if(arrayWeapons.hasOwnProperty(ref)){if(getSlug(arrayWeapons[ref].name)===item.data.data.slug)return!0;if(getSlugNoQuote(arrayWeapons[ref].name)===item.data.data.slug)return!0}for(var ref in arrayArmor)if(arrayArmor.hasOwnProperty(ref)){if(arrayArmor[ref].name=mapItemToFoundryName(arrayArmor[ref].name),getSlug(arrayArmor[ref].name)===item.data.data.slug)return!0;if(getSlugNoQuote(arrayArmor[ref].name)===item.data.data.slug)return!0}for(var ref in arrayKit)if(arrayKit.hasOwnProperty(ref)&&arrayKit[ref][0]===item.data.data.slug)return!0;return!(!addMoney||"platinum-pieces"!==item.data.data.slug&&"gold-pieces"!==item.data.data.slug&&"silver-pieces"!==item.data.data.slug&&"copper-pieces"!==item.data.data.slug)}function getClassAdjustedSpecialNameLowerCase(specialName){return(specialName+" ("+jsonBuild.class+")").toLowerCase()}function getAncestryAdjustedSpecialNameLowerCase(specialName){return(specialName+" ("+jsonBuild.ancestry+")").toLowerCase()}function getHeritageAdjustedSpecialNameLowerCase(specialName){return(specialName+" ("+jsonBuild.heritage+")").toLowerCase()}function needsNewInstanceofFeat(targetActor,itemName,itemExtra){for(const existingItem of targetActor.data.items){var displayName=itemName;if(null!=itemExtra&&(displayName+=" ("+itemExtra+")"),existingItem.data.name===displayName)return!1}return!0}function needsNewInstanceofItem(targetActor,itemName){for(var ref in targetActor.data.items)if(targetActor.data.items.hasOwnProperty(ref)&&targetActor.data.items[ref].name===itemName)return!1;return!0}function getSizeValue(size){switch(size){case 0:return"tiny";case 1:return"sm";case 3:return"lg"}return"med"}async function setSpellcasters(targetActor,arraySpellcasters){fbpiDebug&&console.log("%cPathbuilder2e Import | %cDeleting all spells",pbcolor1,pbcolor4);let items=targetActor.data.items.filter(i=>"spell"===i.type);var spellListObject,deletions=items.map(i=>i.id);await targetActor.deleteEmbeddedDocuments("Item",deletions);items=targetActor.data.items.filter(i=>"spellcastingEntry"===i.type),deletions=items.map(i=>i.id),await targetActor.deleteEmbeddedDocuments("Item",deletions);let requiredSpells=[];for(ref in arraySpellcasters)if(arraySpellcasters.hasOwnProperty(ref)){let spellCaster=arraySpellcasters[ref];for(var ref in focusPool+=spellCaster.focusPoints,"focus"==spellCaster.magicTradition?(focusWarning=1,spellCaster.instance=await addSpecificCasterAndSpells(targetActor,spellCaster,"divine",spellCaster.magicTradition)):spellCaster.instance=await addSpecificCasterAndSpells(targetActor,spellCaster,spellCaster.magicTradition,spellCaster.spellcastingType),spellCaster.spells)spellCaster.spells.hasOwnProperty(ref)&&(spellListObject=spellCaster.spells[ref],requiredSpells=requiredSpells.concat(spellListObject.list))}game.packs.filter(pack=>"spells-srd"===pack.metadata.name).forEach(async pack=>{const content=await pack.getDocuments();for(const action of content.filter(item=>spellIsRequired(item,requiredSpells)))arraySpellcasters.forEach(spellCaster=>{for(var ref in spellCaster.spells)if(spellCaster.spells.hasOwnProperty(ref)){let spellListObject=spellCaster.spells[ref];for(var ref in spellListObject.list)if(spellListObject.list.hasOwnProperty(ref)&&(getSlug(spellListObject.list[ref])==action.data.data.slug||getSlugNoQuote(spellListObject.list[ref])==action.data.data.slug)){const clonedData=JSON.parse(JSON.stringify(action.data));clonedData.data.location.value=spellCaster.instance[0].id,0==spellListObject.spellLevel?clonedData.data.level.value=1:clonedData.data.level.value=spellListObject.spellLevel,allItems.push(clonedData);break}}});finishedSpells=!0,checkAllFinishedAndCreate(targetActor)})}function spellIsRequired(item,arraySpells){for(var ref in arraySpells)if(arraySpells.hasOwnProperty(ref)&&getSlug(arraySpells[ref])==item.data.data.slug)return!0;return!1}async function addSpecificCasterAndSpells(targetActor,spellCaster,data,spellCasterInstance){data={ability:{value:spellCaster.ability},proficiency:{value:spellCaster.proficiency/2},spelldc:{item:0},tradition:{value:data},prepared:{value:spellCasterInstance,flexible:!1},slots:{slot0:{max:spellCaster.perDay[0],prepared:[],value:spellCaster.perDay[0]},slot1:{max:spellCaster.perDay[1],prepared:[],value:spellCaster.perDay[1]},slot2:{max:spellCaster.perDay[2],prepared:[],value:spellCaster.perDay[2]},slot3:{max:spellCaster.perDay[3],prepared:[],value:spellCaster.perDay[3]},slot4:{max:spellCaster.perDay[4],prepared:[],value:spellCaster.perDay[4]},slot5:{max:spellCaster.perDay[5],prepared:[],value:spellCaster.perDay[5]},slot6:{max:spellCaster.perDay[6],prepared:[],value:spellCaster.perDay[6]},slot7:{max:spellCaster.perDay[7],prepared:[],value:spellCaster.perDay[7]},slot8:{max:spellCaster.perDay[8],prepared:[],value:spellCaster.perDay[8]},slot9:{max:spellCaster.perDay[9],prepared:[],value:spellCaster.perDay[9]},slot10:{max:spellCaster.perDay[10],prepared:[],value:spellCaster.perDay[10]}},showUnpreparedSpells:{value:!0}},spellCasterInstance=[],data={name:spellCaster.name,type:"spellcastingEntry",data:data};spellCasterInstance.push(data);spellCasterInstance=await targetActor.createEmbeddedDocuments("Item",spellCasterInstance);return fbpiDebug&&console.log(spellCasterInstance),spellCasterInstance}async function addLores(targetActor,arrayLores){const arrayLoreData=[];for(var ref in arrayLores)if(arrayLores.hasOwnProperty(ref)){var update,loreName=arrayLores[ref][0],loreProf=arrayLores[ref][1];if(needsNewInstanceOfLore(targetActor,loreName))arrayLoreData.push({name:loreName,type:"lore",data:{proficient:{value:loreProf/2},featType:"",mod:{value:0},item:{value:0}}});else for(var ref in targetActor.data.items)targetActor.data.items.hasOwnProperty(ref)&&targetActor.data.items[ref].name===loreName&&(update={id:targetActor.data.items[ref].id,"data.proficient.value":loreProf/2},targetActor.updateEmbeddedEntity("Item",update))}0The following items could not be added. They may have already have been added in a previous import or cannot be matched to a foundry item. You may be able to find them with a manual search.

    ";if(addEquipment)for(var ref in jsonBuild.equipment)jsonBuild.equipment.hasOwnProperty(ref)&&((item=jsonBuild.equipment[ref]).added||(notAddedCount++,warning+="
  • Equipment: "+item[0]+"
  • ",warningList+="Equipment: "+item[0]+"|",fbpiDebug&&console.log("%cPathbuilder2e Import | %cdid not add "+item[0],pbcolor1,pbcolor4)));if(addFeats){for(var ref in jsonBuild.feats)jsonBuild.feats.hasOwnProperty(ref)&&(item=jsonBuild.feats[ref],addedItems.includes(item[0])||(notAddedCount++,warning+="
  • Feat: "+item[0]+"
  • ",warningList+="Feat: "+item[0]+"|",fbpiDebug&&console.log("%cPathbuilder2e Import | %cdid not add "+item[0],pbcolor1,pbcolor4)));for(var ref in targetActor.update({"flags.exportSource.world":game.world.id,"flags.exportSource.system":game.system.id,"flags.exportSource.systemVersion":game.system.data.version,"flags.exportSource.coreVersion":game.data.version,"flags.pathbuilderID.value":buildID}),targetActor.update({"data.resources.focus.max":focusPool,"data.resources.focus.value":focusPool}),targetActor.update({"data.attributes.hp.value":1234}),jsonBuild.specials)jsonBuild.specials.hasOwnProperty(ref)&&(item=jsonBuild.specials[ref],addedItems.includes(item)||(notAddedCount++,warning+="
  • Special: "+item+"
  • ",warningList+="Special: "+item+"|",fbpiDebug&&console.log("%cPathbuilder2e Import | %cdid not add "+item,pbcolor1,pbcolor4)))}warning+="

",0You have focus spells and Pathbuilder does not export the tradition of focus spells. This importer automatically sets their tradition to divine. If this is incorrect, edit the focus spells entry to fix it.
":warning="You have focus spells and Pathbuilder does not export the tradition of focus spells. This importer automatically sets their tradition to divine. If this is incorrect, edit the focus spells entry to fix it.
",notAddedCount++),reportMissedItems&&reportWarnings(warningList),0",label:"Finished"}},default:"yes",close:html=>{var heroJSON;heroVaultExport&&(heroJSON=JSON.stringify(targetActor.data),fbpiDebug&&console.log(heroJSON),doHVExport(heroJSON,targetActor))}}).render(!0)):(ui.notifications.info("Import completed successfully."),heroVaultExport&&(heroJSON=JSON.stringify(targetActor.data),fbpiDebug&&console.log(heroJSON),doHVExport(heroJSON,targetActor)))}}function reportWarnings(warnings){var systemVersion=game.system.data.version,coreVersion=game.data.version,xmlhttp=new XMLHttpRequest;xmlhttp.open("POST",reportDomain+"/pbreport.php",!0),xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"),xmlhttp.send("buildID="+buildID+"&warnings="+encodeURIComponent(warnings)+"&systemVersion="+encodeURIComponent(systemVersion)+"&coreVersion="+encodeURIComponent(coreVersion)+"&fpbi="+encodeURIComponent(fpbi))}function getSlug(itemName){return itemName.toString().toLowerCase().replace(/[^a-z0-9]+/gi," ").trim().replace(/\s+|-{2,}/g,"-")}function getSlugNoQuote(itemName){return itemName.toString().toLowerCase().replace(/[\']+/gi,"").replace(/[^a-z0-9]+/gi," ").trim().replace(/\s+|-{2,}/g,"-")}function mapItemToFoundryName(itemName){fbpiDebug&&console.log("%cPathbuilder2e Import | %c Checking map for '"+itemName+"'",pbcolor1,pbcolor4);const changeNames=[{name:"Chain",newname:"Chain (10 feet)"},{name:"Oil",newname:"Oil (1 pint)"},{name:"Bracelets of Dashing",newname:"Bracelet of Dashing"},{name:"Fingerprinting Kit",newname:"Fingerprint Kit"},{name:"Greater Unmemorable Mantle",newname:"Unmemorable Mantle (Greater)"},{name:"Major Unmemorable Mantle",newname:"Unmemorable Mantle (Major)"},{name:"Ladder",newname:"Ladder (10-foot)"},{name:"Mezmerizing Opal",newname:"Mesmerizing Opal"},{name:"Explorer's Clothing",newname:"Clothing (Explorer's)"},{name:"Flaming Star (Greater)",newname:"Greater Flaming Star"},{name:"Potion of Lesser Darkvision",newname:"Darkvision Elixir (Lesser)"},{name:"Bottled Sunlight",newname:"Formulated Sunlight"},{name:"Magazine (Repeating Hand Crossbow)",newname:"Magazine with 5 Bolts"},{name:"Astrolabe (Standard)",newname:"Standard Astrolabe"},{name:"Greater Cloak of Repute",newname:"Cloak of Repute (Greater)"},{name:"Skinitch Salve",newname:"Skinstitch Salve"},{name:"Flawless Scale",newname:"Abadar's Flawless Scale"},{name:"Construct Key",newname:"Cordelia's Construct Key"},{name:"Construct Key (Greater)",newname:"Cordelia's Greater Construct Key"},{name:"Lesser Swapping Stone",newname:"Lesser Bonmuan Swapping Stone"},{name:"Major Swapping Stone",newname:"Major Bonmuan Swapping Stone"},{name:"Moderate Swapping Stone",newname:"Moderate Bonmuan Swapping Stone"},{name:"Greater Swapping Stone",newname:"Greater Bonmuan Swapping Stone"},{name:"Heartstone",newname:"Skarja's Heartstone"},{name:"",newname:""},{name:"",newname:""},{name:"",newname:""},{name:"",newname:""},{name:"",newname:""}];var newNameIdx=changeNames.findIndex(function(item){return item.name==itemName});return-1{if(val.includes("Domain: "))return val});return search.forEach(domainName=>{domainName=domainName.split(" ")[1];featsArray.push({0:"Deity's Domain",1:domainName})}),[specialArr=specialArr.filter(val=>{if(!val.includes("Domain: "))return val}),featsArray,specialClassFeatures]}function uniq(a){return Array.from(new Set(a))}Hooks.on("herovaultfoundryReady",api=>{fbpiDebug&&console.log("%cPathbuilder2e Import | %cDisabling pathbuilder button since herovault is loaded",pbcolor1,pbcolor4),pbButton=!1}),Hooks.on("renderActorSheet",async function(obj,html){const actor=obj.actor;if("character"===actor.data.type&&0!=actor.canUserModify(game.user,"update")&&pbButton){let element=html.find(".window-header .window-title");if(1==element.length){let button=$('Import from Pathbuilder 2e');button.on("click",()=>beginPathbuilderImport(obj.object)),element.after(button)}}}),Hooks.on("init",()=>{game.modules.get("pathbuilder2e-import").api={beginPathbuilderImport:beginPathbuilderImport},Hooks.callAll("pathbuilder2eimportReady",game.modules.get("pathbuilder2e-import").api)}),Hooks.on("ready",function(){console.log("%cPathbuilder2e Import | %cinitializing",pbcolor1,pbcolor4),game.settings.register("pathbuilder2e-import","reportMissedItems",{name:"Report missed items?",hint:"Having this checked will send me the error report generated during an import. Please keep this enabled so that I can continue to improve the module. It sends the following data: pathbuilder character ID and error messages presented post-import.",scope:"client",config:!0,type:Boolean,default:!0,onChange:value=>reportMissedItems=value}),game.settings.register("pathbuilder2e-import","debugEnabled",{name:"Enable debug mode",hint:"Debug output will be written to the js console.",scope:"client",config:!0,type:Boolean,default:!1,onChange:value=>fbpiDebug=value}),reportMissedItems=game.settings.get("pathbuilder2e-import","reportMissedItems"),fbpiDebug=game.settings.get("pathbuilder2e-import","debugEnabled")});export{beginPathbuilderImport}; \ No newline at end of file +var fbpiDebug=!1;const fpbi="0.9.0",reportDomain="https://www.pf2player.com/",pbcolor1="color: #7bf542",pbcolor2="color: #d8eb34",pbcolor3="color: #ffffff",pbcolor4="color: #cccccc",pbcolor5="color: #ff0000";ui.notifications.error("Pathbuilder Importer is NOT COMPATABLE with Foundry VTT 9.x at this time and has been disabled."),ui.notifications.error("Do not try to install an earlier version. It will not work."),ui.notifications.error("Admin/GM, please disable this module to prevent this message from appearing again."); \ No newline at end of file diff --git a/pathbuilder-import.js b/pathbuilder-import.js index 21b8ad7..5e31b5f 100644 --- a/pathbuilder-import.js +++ b/pathbuilder-import.js @@ -1,5 +1,5 @@ var fbpiDebug = false; -const fpbi = "0.7.5"; +const fpbi = "0.9.0"; const reportDomain = "https://www.pf2player.com/"; const pbcolor1 = "color: #7bf542"; //bright green