PF statblock importer

Discussion concerning lmarkus' campaign framework for D&D3.x and Pathfinder.

Moderators: Azhrei, dorpond, trevor, giliath, Gamerdude, jay, Mr.Ice, lmarkus001

Forum rules
Discussion regarding lmarkus001's framework only. Other posts deleted without notice! :)
User avatar
JamzTheMan
Great Wyrm
Posts: 1872
Joined: Mon May 10, 2010 12:59 pm
Location: Chicagoland
Contact:

Re: PF statblock importer

Post by JamzTheMan »

Full Bleed, I've been making changes to the StatBlock macro as well as I find issues generating creatures for my campaign and see you've ran into a few of the same things I have.

Lets share our work if you don't mind? :)

A couple things I've added to note are:

1. Fix bad characters (note, I've found non-ascii x's as well as emdash)
[H: statblock = replace(statblock, "\\xD7", "x")]
[H: statblock = replace(statblock, "\\u2013", "-")]
[H: statblock = replace(statblock, "Ecolo gy", "Ecology")]

2. Added Fast Healing & Regeneration

3. Perception from Statblock (vs skills section for simplicty to show on statsheet)

4. Hero Labs Friendly: I've made a few changes so it doesn't choke on reading StatBlocks from Hero Labs, mostly around the weapons area.

5. More changes/fixes around weapons. Still chokes on a few odd things. Still not 100% either.

6. Treasure Type: This goes with my Treasure Roll macro which uses standard Pathfinder core rules to generate random coin/gem values. (It does a basic job of breaking down total by copper/silver/gold/plat/gems as well.)

Note: I removed the input box for favor of cut/paste into GM text. That way I have a RAW semi formatted original stat block to refer back to for anything special or to rerun if needed. I heavily use the StatSheet as well and as we are F2F so I like the quick reference on hover.

I've also made changes to the Calculate XP macro if interested. It calculates XP and marks the token with a XP state and then saves the XP to the PC tokens. If the PC has enough XP to level, a LevelUp state is applied.

I note this as I use the StatBlock2Token macro of PC's (from Hero Labs) and needed to keep several properties from being erased like XP.

[spoiler=Statblock2Token]<!-- Statblock2Token v2.1
Jamz: Now paste formatted text into GM text (which stays formatted) and handles CR now.
Jamz: Added Fast-Healing, Regeneration, adjusted Weapons to be Hero Labs friendly

Changes: HD fixed, Resets token, Skills with space in the name except SleightOfHand
Macro takes a Pathfinder statblock as input and updates selected token with various stats.
Macro assumes pathfinder properties in the selected token.
Statblock format should mirror PF bestiary format.
Not handled: SQ, Spells
-->
[H: ids = getSelected()]
[H: abort(if(ids == "", 0, 1))]

<!-- Lets keep nice formated text in GMNotes and paste there first manually and then retrieve it from there
H: status=input("statblock|Insert statblock here|Enter statblock|TEXT|WIDTH=40")
H: abort(if(status < 1, 0, 1))
H: setGMNotes(statblock)
-->

[H: setPropertyType("Pathfinder")]

<!--Lets keep my custom Nerps properties if already populated-->
[H: Nerps_WikiTemp=getProperty("Nerps_Wiki")]
[H: Nerps_TreasureTemp=getProperty("Nerps_Treasure")]
[H: XPTemp=getProperty("XP")]
[H: NewXPTemp=getProperty("NewXP")]
[H: XPadvancmentPaceTemp=getProperty("XPadvancmentPace")]

[H: propnames = getPropertyNames()]
[H, foreach(propname,propnames),CODE:
{
[resetProperty(propname)]
}]

[H: setProperty("Nerps_Wiki", Nerps_WikiTemp)]
[H: setProperty("Nerps_Treasure", Nerps_TreasureTemp)]
[H: setProperty("XP", XPTemp)]
[H: setProperty("NewXP", NewXPTemp)]
[H: setProperty("XPadvancmentPace", XPadvancmentPaceTemp)]

[H: statblock = getGMNotes()]
[H: statblock = replace(statblock, "\\xD7", "x")]
[H: statblock = replace(statblock, "\\u2013", "-")]
[H: statblock = replace(statblock, "Ecolo gy", "Ecology")]

[H: setGMNotes(statblock)]
[H: statblockOrig = statblock]
[H: statblock = replace(statblock, "\\n", " ")]

[H: output="Token Updated:<br>"]
[H: id = strfind(statblock, "^(.+).*CR ")]
[H, IF(0<getFindCount(id)),CODE: {
[currentName = getName()]
[newName=trim(getGroup(id, 1, 1))]
[n1 = upper(currentName)]
[n2 = upper(newName)]
[if(n1 == n2): newName = currentName)]
[setName(newName)]
[Race = json.set(Race, "name", newName)]
[output=output+"Name: "+newName+", "]
}]

<!-- Setting ECL to CR from statblock. For CR 1/3 & 1/6 we will set it to .338 & .1625 so XP calcs correctly. -->
[H: id = strfind(statblockOrig, "(?<=[ |\\t]CR )([0-9]+)(/[0-9]+)?")]
[H, IF(0<getFindCount(id)),CODE:
{
[ECL=trim(getGroup(id, 1, 0))]
[output=output+"CR: "+ECL+", "]
[IF(ECL == "1/3"),CODE:{
[ECL=".338"]
}]
[IF(ECL == "1/6"),CODE:{
[ECL=".1625"]
}]
[Levels = setStrProp(Levels, "ECL", ECL)]
}]


<!-- Getting Perception. -->
[H: id = strfind(statblockOrig, "(?<=Perception )(.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[Perception=trim(getGroup(id, 1, 0))]
[output=output+"Perception: "+Perception+", "]
[Skills = setStrProp(Skills, "Perception", Perception)]
}]


[H: id = strfind(statblock, "(Fine|Diminutive|Tiny|Small|Medium|Large|Huge|Gargantuan|Colossal).([a-zA-Z]+\\s?[a-zA-Z]*?)\\s?(\\((.+)\\))?.?Init")]
[H, IF(0<getFindCount(id)),CODE:
{
[Size_txt=getGroup(id, 1, 1)]
[setSize(Size_txt)]
[sizeList = table( "SysVars", json.get( table( "SysVars", 0 ), "sizeList" ) ) ]
[sizeModList = "8,4,2,1,0,-1,-2,-4,-8"]
[Size=listFind(sizeList, Size_txt)]
[SizeM = listGet(sizeModList, Size)]
[type=upper(substring(getGroup(id, 1, 2),0,1))+substring(getGroup(id, 1, 2),1)]
[Race = json.set(Race, "type", type)]
[subtypes=getGroup(id, 1, 4)]
[output=output+"Size: "+Size_txt+", type: "+type+", subtypes: "+subtypes+"<br>"]
[subtypes="['"+replace(subtypes,", *","','")+"']"]
[Race = json.set(Race, "subtype",subtypes)]
}]

[H: id = strfind(statblock, "Init ([+-][0-9]+);")]
[H, IF(0<getFindCount(id)),CODE:
{
[InitMod=getGroup(id, 1, 1)]
[output=output+"Init: "+InitMod+", "]
}]

[H: id = strfind(statblock, "Senses ([lL]ow-?light|[dD]arkvision)")]
[H, IF(0<getFindCount(id)),CODE:
{
[sighttype=upper(substring(getGroup(id, 1, 1),0,1))+substring(getGroup(id, 1, 1),1)]
[sighttype=replace(sighttype, "-", "")]
[setSightType(sighttype)]
[setHasSight(1)]
[output=output+"Sighttype: "+sighttype+", "]
}]

[H: id = strfind(statblock, "Reach ([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[Reach=getGroup(id, 1, 1)]
[output=output+"Reach: "+Reach+", "]
}]

[H: id = strfind(statblock, "DR(.?[0-9]+)/(.+?)[;O]")]
[H, IF(0<getFindCount(id)),CODE:
{
[DR=getGroup(id, 1, 1)+"/"+getGroup(id, 1, 2))]
[output=output+"DR: "+DR+", "]
}]

[H: id = strfind(statblock, "Resist (\\w+) (\\d+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[resist = getGroup(id, 1, 1)+" "+getGroup(id, 1, 2))]
[DR=DR+" Resist "+resist]
[output=output+"Resist: "+resist+", "]
}]

[H: id = strfind(statblock, "SR ([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[SR=getGroup(id, 1, 1)]
[SpecialQual="SR "+SR]
[output=output+"SR: "+SR+", "]
}]

<!-- STATS BEGIN -->
[H: id = strfind(statblockOrig, "Str.+?([0-9]*).+?Dex ?([0-9]*).+?Con.?([0-9]*).+?Int.?([0-9]*).+?Wis.?([0-9]*).+?Cha.?([0-9]*)")]

[H, IF(0<getFindCount(id)), CODE:
{
[Strength=getGroup(id, 1, 1)]
[IF(Strength==""):Strength=10]
[Dexterity=getGroup(id, 1, 2)]
[IF(Dexterity==""):Dexterity=10]
[Constitution=getGroup(id, 1, 3)]
[IF(Constitution==""):Constitution=10]
[Intelligence=getGroup(id, 1, 4)]
[IF(Intelligence==""):Intelligence=10]
[Wisdom=getGroup(id, 1, 5)]
[IF(Wisdom==""):Wisdom=10]
[Charisma=getGroup(id, 1, 6)]
[IF(Charisma==""):Charisma=10]
[output=output+"Str: "+Strength+", Dex: "+Dexterity+", Con: "+Constitution+", Int: "+Intelligence+", Wis: "+Wisdom+", Cha: "+Charisma+"<br>"]
}]
<!-- STATS END -->

<!-- SAVES BEGIN -->
[H: id = strfind(statblock, "Fort (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[Fort=getGroup(id, 1, 1)-ConB]
[output=output+"Fort: "+fort+", "]
}]
[H: id = strfind(statblock, "Ref (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[Reflex=getGroup(id, 1, 1)-DexB]
[output=output+"Ref: "+reflex+", "]
}]

[H: id = strfind(statblock, "Will (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[Will=getGroup(id, 1, 1)-WisB]
[output=output+"Will: "+Will+"<br>"]
}]
<!-- SAVES END -->

[H: id = strfind(statblock, "hp ([0-9]+).+?([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[HP=getGroup(id, 1, 1)]
[HPmax=HP]
[HPavg=HP]
[HD=getGroup(id, 1, 2)]
[Level = max(1,HD)]
[output=output+"HP: "+HP+", HD: "+HD+"<br>"]
}]

[H: id = strfind(statblock, "(hp [0-9]+ )\\(([0-9]+d[0-9]+([+-][0-9]+)?(\\)))")]
[H, IF(0<getFindCount(id)),CODE:
{
[HitDice=getGroup(id, 1, 2)]
[HitDice=substring(HitDice,0, length(HitDice)-1)]
[output=output+"Hit Dice: "+HitDice+"<br>"]
}]

[H: id = strfind(statblock, "Base Atk.?(.?[0-9]+);")]
[H, IF(0<getFindCount(id)), CODE:
{
[BAB=getGroup(id, 1, 1)]
[output=output+"Base Atk: "+BAB+", "]
}]

[H: id = strfind(statblock, "CMB.?(.?[0-9]+);")]
[H, IF(0<getFindCount(id)), CODE:
{
[CMBMod=getGroup(id, 1, 1)]
[output=output+"CMB: "+CMBMod+", "]
}]

<!-- AC BEGIN -->
[H: id = strfind(statblock, "(.?[0-9]+) natural")]
[H, IF(0<getFindCount(id)): natural=getGroup(id, 1, 1); natural=0]
[H: ArmorClass = setStrProp(ArmorClass, "Natural", natural)]

[H: id = strfind(statblock, "(.?[0-9]+) armor")]
[H, IF(0<getFindCount(id)): armor=getGroup(id, 1, 1);armor=0]
[H: ArmorClass = setStrProp(ArmorClass, "Armor", armor)]

[H: id = strfind(statblock, "(.?[0-9]+) deflection")]
[H, IF(0<getFindCount(id)): deflect=getGroup(id, 1, 1); deflect=0]
[H: ArmorClass = setStrProp(ArmorClass, "Deflection", deflect)]

[H: id = strfind(statblock, "(.?[0-9]+) dodge")]
[H, IF(0<getFindCount(id)): dodge=getGroup(id, 1, 1); dodge=0]
[H: ArmorClass = setStrProp(ArmorClass, "Dodge", dodge)]

[H: id = strfind(statblock, "(.?[0-9]+) shield")]
[H, IF(0<getFindCount(id)): shield=getGroup(id, 1, 1); shield=0]
[H: ArmorClass = setStrProp(ArmorClass, "Shield", shield)]

[H: id = strfind(statblock, "AC ([0-9]+),")]
[H, IF(0<getFindCount(id)), CODE:
{
[AC=getGroup(id, 1, 1)]
[tch=AC-armor-shield]
[FF=AC-dodge-DexB]
[CMD=10+BAB+StrB+DexB-SizeM+dodge+deflect]
[CMDFF=CMD-DexB-dodge]
[AC=concat(AC,"/",tch,"/",FF,"/",CMD,"/",CMDFF)]
[output=output+"AC/tch/FF/CMD/CMDFF: "+AC+"<br>"]
}]
<!-- AC END -->


[H: id = strfind(statblock, "(Speed|Spd) ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
{
[spd=getGroup(id, 1, 2)]
[output=output+"Spd: "+spd]
[Speed = json.set(Speed, "base",spd)]
}]
[H: id = strfind(statblock, "fly ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
{
[spd=getGroup(id, 1, 1)]
[output=output+", Fly: "+spd]
[Speed = json.set(Speed, "fly",spd)]
}]
[H: id = strfind(statblock, "swim ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
{
[spd=getGroup(id, 1, 1)]
[output=output+", Swim: "+spd]
[Speed = json.set(Speed, "swim",spd)]
}]
[H: id = strfind(statblock, "burrow ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
{
[spd=getGroup(id, 1, 1)]
[output=output+", Burrow: "+spd]
[Speed = json.set(Speed, "burrow",spd)]
}]
[H: id = strfind(statblock, "climb ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
{
[spd=getGroup(id, 1, 1)]
[output=output+", Climb: "+spd]
[Speed = json.set(Speed, "climb",spd)]
}]
[H: output=output+"<br>"]

<!-- SKILLS BEGIN -->
[H: tSkillsJ ="[]"]
[H: output=output+"Skills: "]
[H, FOREACH(s, SkillsJ), CODE:
{
[skN = json.get(s, "name")]
[id=0]
[id = strfind(statblock, skN+"\\s(.?[0-9]+)")]
[H, IF(0<getFindCount(id)), CODE:
{
[skN = replace(skN, " ", "")] <!-- Remove spaces from skill name -->
[skStat = getStrProp(SkillStat, skN)]
[skVal = getGroup(id, 1, 1)]
[output=output+skN+" "+skVal+", "]
[s = json.set(s, "rank", skVal-eval(skStat))]
}]
[tSkillsJ = json.append(tSkillsJ,s)]
}]
[H: output=output+"<br>"]
[H: SkillsJ=tSkillsJ]
<!-- SKILLS END -->

<!-- FEATS BEGIN -->
[H: output=output+"Feats: "]
[H: id = strfind(statblock, "(Improved Initiative)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "ImprovedInitiative",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "ImprovedInitiative",0)]
}]
[H: id = strfind(statblock, "(Agile Maneuvers)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "AgileManeuvers",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "AgileManeuvers",0)]
}]
[H: id = strfind(statblock, "(Improved Bull Rush)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "ImprovedBullRush",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "ImprovedBullRush",0)]
}]
[H: id = strfind(statblock, "(Improved Disarm)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "ImprovedDisarm",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "ImprovedDisarm",0)]
}]
[H: id = strfind(statblock, "(Improved Grapple)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "ImprovedGrapple",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "ImprovedGrapple",0)]
}]
[H: id = strfind(statblock, "(Improved Overrun)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "ImprovedOverrun",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "ImprovedOverrun",0)]
}]
[H: id = strfind(statblock, "(Improved Sunder)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "ImprovedSunder",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "ImprovedSunder",0)]
}]
[H: id = strfind(statblock, "(Improved Trip)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "ImprovedTrip",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "ImprovedTrip",0)]
}]
[H: id = strfind(statblock, "(Improved Channeling)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "ImprovedChanneling",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "ImprovedChanneling",0)]
}]
[H: id = strfind(statblock, "(Two.?Weapon Fighting)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "TwoWeaponFighting",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "TwoWeaponFighting",0)]
}]
[H: id = strfind(statblock, "(Multi.?[aA]ttack)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "MultiAttack",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "MultiAttack",0)]
}]

[H: id = strfind(statblock, "(Power Attack)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "PowerAttack",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "PowerAttack",0)]
}]

[H: id = strfind(statblock, "(Weapon Finesse)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "WeaponFinesse",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "WeaponFinesse",0)]
}]
[H: id = strfind(statblock, "(Uncanny Dodge)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "UncannyDodge",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "UncannyDodge",0)]
}]
[H: id = strfind(statblock, "(Die.?[hH]ard)")]
[H, IF(0<getFindCount(id)), CODE:
{
[Feats=setStrProp(Feats, "DieHard",1)]
[H: output=output+getGroup(id, 1, 1)+", "]
};{
[Feats=setStrProp(Feats, "DieHard",0)]
}]
[H: output=output+"<br>"]
<!-- FEATS END -->

[H: id = strfind(statblockOrig, "Special Attacks (.+)")]
[H, IF(0<getFindCount(id)), CODE:
{
[SpecialATK=getGroup(id, 1, 1)]
[SpecialATK=trim(SpecialATK)]
[SpecialATK=substring(SpecialATK,0,min(length(SpecialATK),100))]
[output=output+"SA: "+SpecialATK+"<br>"]
};{
[SpecialATK=""]
}]

<!-- ATTACKS BEGIN -->
<!-- Insert empty weapon strings -->
[H: wpnstr=getPropertyDefault( "Weapon0" )]
[H, c(7,""),CODE:
{
[wpn="Weapon"+roll.count]
[eval(wpn + " = '" + wpnstr+ "'")]
}]

[H: atkno = 0]

<!-- MELEE -->
<!-- The '(?i)' makes the expression case-insensitive -->
[H: id = strfind(statblock, "Melee (.+?)(?i)(?=Tactic|Face|Space|Reach|Special|Ranged|Stat|Spell-Like Abilities|---)")]
[H, IF(0<getFindCount(id)), CODE:
{
[allmelee=getGroup(id, 1, 1)]
[setProperty("OriginalMeleeLine", allmelee)]
<!-- separate each attack option -->
[allmelee=stringToList(allmelee, "( or (Melee)?)|(Melee)",":")]
[atkno = listCount(allmelee, ":")]
}]
<!-- Loop through each attack option and divide into weapons -->
[H: wpnarray=""]
[H: wpnno=0]
[H, FOR(i,0,atkno,1), CODE:
{
[atkstr=listget(allmelee, i, ":")]
[atkstr=stringToList(atkstr, "(?<=\\)) and|(?<=\\)), ",":")]
[wpns = listCount(atkstr, ":")]

[FOR(j,0,wpns,1), CODE:
{
[WpnName = "Weapon" + wpnno]
[wpnarray=json.append(wpnarray, trim(listGet(atkstr,j,":")))]
[ x = eval(WpnName) ]
[IF(j>0):eval(WpnName + "= '" + replace(x,"Primary=\\d+", "Primary=2")+ "'")]

<!-- Set attack options after first to secondary attacks -->
[eval(WpnName + "= '" + replace(x,"OHLight=\\d+", "OHLight=2")+ "'")]

<!-- Default to not multiattack -->
[wpnno = wpnno +1]
}]
}]

<!-- RANGED -->
[H: atkno = 0]
[H: id = strfind(statblock, "Ranged (.+?)(?=Tac|Face|Space|Reach|Special|Ranged|STAT|Stat|Spell-Like Abilities|---)")]
[H, IF(0<getFindCount(id)), CODE:
{
[allranged=getGroup(id, 1, 1)]
[setProperty("OriginalRangedLine", allranged)]
<!-- separate each attack option -->
[allranged=stringToList(allranged, "(\\s?or (Ranged)?)|(Ranged)",":")]
[atkno = listCount(allranged, ":")]
}]
<!-- Loop through each attack option and divide into weapons -->
[H, FOR(i,0,atkno,1), CODE:
{
[atkstr=listget(allranged, i, ":")]
[atkstr=stringToList(atkstr, "(?<=\\)) and|(?<=\\)), ",":")]
[wpns = listCount(atkstr, ":")]
[FOR(j,0,wpns,1), CODE:
{
[WpnName = "Weapon" + wpnno]
[wpnarray=json.append(wpnarray, trim(listGet(atkstr,j,":")))]
[eval(WpnName + "= '" + setStrProp(eval(WpnName),"Ranged", 1)+ "'")]
[wpnno = wpnno +1]
}]
}]

<!-- extract info from each attack -->
[H: wpnno=0]
[H, FOREACH(atkstr, wpnarray), CODE: {
[atkstr=trim(atkstr)]
[id = strfind(atkstr, "([+-]\\d+)?(\\d+)?(.+(?= [\\+-]\\d+ \\()) ([+-]\\d+)[/+\\-0-9\\s]*?\\((.+)\\)")]
[regexptofindweaponname = ".+(?= (/?[\\+-]\\d+)+ \\()"]

[IF(0<getFindCount(id)), CODE:
{
[WpnName = "Weapon" + wpnno]
[eval(WpnName + "= '" + setStrProp(eval(WpnName),"Name", getGroup(id, 1, 3)) + "'")]

<!-- Quantity -->
[wquant = 1]
[wbonus = ""]
[IF(getGroup(id,1,1)==""): wquant = getGroup(id, 1, 2); wbonus="+ "+getGroup(id,1,1)]
[IF(getGroup(id,1,2)==""): wquant = 1]
[IF(1<wquant):eval(WpnName + "= '" + setStrProp(eval(WpnName),"Quantity", wquant)+ "'")]

<!-- Manufactored ? -->
[id2 = strfind(atkstr, "(slam|bite|claw|gore|hoof|tentacle|wing|pincer|tail|sting|talon)")]
[IF(0==getFindCount(id2)):eval(WpnName + "= '" + setStrProp(eval(WpnName),"Manufactured", 1)+ "'")]

<!-- Not a natural weapon -->
<!-- Attack bonus (assumes StrB for melee and DexB for ranged) -->
[watkbonus=getGroup(id, 1, 4)]
[Ranged=getStrProp(eval(WpnName),"Ranged")]
[IF(Ranged>0):watkbonus=watkbonus-BAB-DexB-SizeM;watkbonus=watkbonus-BAB-StrB-SizeM]
[eval(WpnName + "= '" + setStrProp(eval(WpnName),"AtkBonus", watkbonus)+ "'")]

<!-- CritMult-->
[wdam=getGroup(id, 1, 5)]
[CritMult=2]
[id2 = strfind(wdam, "/[xX](\\d)")]
[IF(0<getFindCount(id2)):CritMult=getGroup(id2, 1, 1)]
[eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritMult", CritMult)+ "'")]

<!-- CritRange-->
[CritRange=20]
[id2 = strfind(wdam, "/(1[0-9])")]
[IF(0<getFindCount(id2)):CritRange=getGroup(id2, 1, 1)]
[eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritRange", CritRange)+ "'")]

<!-- Damage -->
[Damage="0d4 plus" + wdam]
[id2 = strfind(wdam, "(\\dd\\d+)[^p]*(plus .+)?")]
[IF(0<getFindCount(id2)):Damage=getGroup(id2, 1, 1)+wbonus+" "+getGroup(id2, 1, 2)]
[Damage123=replace(Damage, " ", "")]
[eval(WpnName + "= '" + setStrProp(eval(WpnName),"Damage", Damage)+ "'")]

<!-- Two handed ? -->
<!-- Default to onehanded weapon -->
[eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 0)+ "'")]

[id2 = strfind(atkstr, "(?i)(longspear|quarterstaff| spear|falchion|glaive|greataxe|greatclub|greatsword|guisarme|halberd|lance|ranseur|scythe|spiked chain|elven curve blade|dire flail|two-bladed sword|urgrosh|hooked hammer)")]

[IF(0<getFindCount(id2)):eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 1)+ "'")]
}]
[wpnno = wpnno +1]
}]

[H: output = output + "Weapons: " + wpnarray+"<br>"]

<!--
Name=Slam ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=0 ; Ranged=0 ;
ATTACKS END -->

<!-- Getting treasure from Ecology section. -->
[H: id = strfind(statblockOrig, "(?i)(?<=Treasure )(None|Standard|Double|Triple|Incidental|NPC gear)")]
[H, IF(0<getFindCount(id)),CODE:
{
[TreasureType=getGroup(id, 1, 0)]
[output=output+"Treasure Type: "+TreasureType+"<br>"]
}]

<!-- Setting Fast Healing if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Fast Healing )([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[FastHealing=getGroup(id, 1, 0)]
[output=output+"Fast Healing: "+FastHealing+"<br>"]
}]

<!-- Setting Regeneration if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Regeneration )([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[Regeneration=getGroup(id, 1, 0)]
[output=output+"Regeneration: "+Regeneration+"<br>"]
}]

<!-- Setting Anti Regeneration damage type if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Regeneration )([0-9]+.+)")]
[H, IF(0<getFindCount(id)),CODE:
{
[AntiRegen=getGroup(id, 1, 0)]
[output=output+"Anti-Regen Damage Type: "+AntiRegen+"<br>"]
}]

<!-- Statblock from HeroLab -->
[H: id = strfind(statblockOrig, "(?i)(Hero Lab logo are Registered Trademarks)")]
[H, IF(0<getFindCount(id)),CODE:
{
[HeroLab=1]
[output=output+"Stat block generated from Hero Lab.<br>"]
}]

[R,S,G: output]

[H: HP = HPmax ]
[H: HPNonLethalDMG = 0]
[H: tToken = currentToken() ]
[H, MACRO( "[email protected]:libDnD35Pathfinder" ): "Token=" + tToken]
[H: setState("Prone", 0)]
[H: setState("Unconscious", 0)]
[H: setLayer("TOKEN") ][/spoiler]
-Jamz
____________________
Custom MapTool 1.4.x.x Fork: maptool.nerps.net
Custom TokenTool 2.0 Fork: tokentool.nerps.net
More information here: MapTool Nerps! Fork

User avatar
Full Bleed
Demigod
Posts: 4444
Joined: Sun Feb 25, 2007 11:53 am
Location: MD
Contact:

Re: PF statblock importer

Post by Full Bleed »

JamzTheMan wrote:Full Bleed, I've been making changes to the StatBlock macro as well as I find issues generating creatures for my campaign and see you've ran into a few of the same things I have.

Lets share our work if you don't mind? :)


Great stuff! Thanks for sharing.

I'm not sure I have much to reciprocate with... I've deviated so far from the original framework this was created for... and my macro has fallen into disrepair as my framework has grown. I'm just now trying to catch things up a bit and fix some niggling issues that have been hanging around (like the - issue.)

I love the idea of using the GM notes for the statblock location, though. I'll be looking to steal that for sure. ;)


Btw, without testing, does your replace statement fix the original dash/minus issue I was having? It would be better to do it with one line if possible.
Maptool is the Millennium Falcon of VTT's -- "She may not look like much, but she's got it where it counts."

User avatar
JamzTheMan
Great Wyrm
Posts: 1872
Joined: Mon May 10, 2010 12:59 pm
Location: Chicagoland
Contact:

Re: PF statblock importer

Post by JamzTheMan »

Full Bleed wrote:
JamzTheMan wrote:Full Bleed, I've been making changes to the StatBlock macro as well as I find issues generating creatures for my campaign and see you've ran into a few of the same things I have.

Lets share our work if you don't mind? :)


Great stuff! Thanks for sharing.

I'm not sure I have much to reciprocate with... I've deviated so far from the original framework this was created for... and my macro has fallen into disrepair as my framework has grown. I'm just now trying to catch things up a bit and fix some niggling issues that have been hanging around (like the - issue.)

I love the idea of using the GM notes for the statblock location, though. I'll be looking to steal that for sure. ;)


Btw, without testing, does your replace statement fix the original dash/minus issue I was having? It would be better to do it with one line if possible.


Yes, it fixes the emdash, it's just another code for it. I've been able to copy/paste from d20pfsrd and from the pdf's now without issue. And it's more or less permanent as those changes are stored back into the GM text.

And since you brought up the DR (it was a nagging issue I've been meaning to tackle) I went ahead and fixed/added it. I'm using the properties from the framework as valid DR/ER values to look for and store back (so just adding more to the property json is all that's needed if a new DR is found).

I also added Immunities and Defensive Abilities (but last one needs some work). I'm still not happy with the weapons, and been avoiding hacking up the original framework to fix it, how do you handle melee/ranged attacks?

Current macro seems to force using StrB for damage and doesn't like things like Wings +14 (2d6+3) where StrB == 6.

Here's the latest, done for the night :)
[spoiler=PF Statblblock2Token]

Code: Select all

<!-- Statblock2Token v2.2
Jamz: Now paste formatted text into GM text (which stays formatted) and handles CR now.
Jamz: Added Fast-Healing, Regeneration, adjusted Weapons to be Hero Labs friendly

Changes: HD fixed, Resets token, Skills with space in the name except SleightOfHand
Macro takes a Pathfinder statblock as input and updates selected token with various stats.
Macro assumes pathfinder properties in the selected token.
Statblock format should mirror PF bestiary format.
Not handled: SQ, Spells
-->
[H: ids = getSelected()]
[H: abort(if(ids == "", 0, 1))]

<!-- Lets keep nice formated text in GMNotes and paste there first manually and then retrieve it from there
   H: status=input("statblock|Insert statblock here|Enter statblock|TEXT|WIDTH=40")
   H: abort(if(status < 1, 0, 1))
   H: setGMNotes(statblock)
-->

[H: setPropertyType("Pathfinder")]

<!--Lets keep my custom Nerps properties if already populated-->
[H: Nerps_WikiTemp=getProperty("Nerps_Wiki")]
[H: Nerps_TreasureTemp=getProperty("Nerps_Treasure")]
[H: XPTemp=getProperty("XP")]
[H: NewXPTemp=getProperty("NewXP")]
[H: XPadvancmentPaceTemp=getProperty("XPadvancmentPace")]

[H: propnames = getPropertyNames()]
[H, foreach(propname,propnames),CODE:
  {
  [resetProperty(propname)]
  }]

[H: setProperty("Nerps_Wiki", Nerps_WikiTemp)]
[H: setProperty("Nerps_Treasure", Nerps_TreasureTemp)]
[H: setProperty("XP", XPTemp)]
[H: setProperty("NewXP", NewXPTemp)]
[H: setProperty("XPadvancmentPace", XPadvancmentPaceTemp)]

[H: statblock = getGMNotes()]
[H: statblock = replace(statblock, "\\xD7", "x")]
[H: statblock = replace(statblock, "\\u2013", "-")]
[H: statblock = replace(statblock, "&#151;", "-")]
[H: statblock = replace(statblock, "Ecolo gy", "Ecology")]

[H: setGMNotes(statblock)]
[H: statblockOrig = statblock]
[H: statblock = replace(statblock, "\\n", " ")]

[H: output="Token Updated:<br>"]
[H: id = strfind(statblock, "^(.+).*CR ")]
[H, IF(0<getFindCount(id)),CODE: {
  [currentName = getName()]
  [newName=trim(getGroup(id, 1, 1))]
  [n1 = upper(currentName)]
  [n2 = upper(newName)]
  [if(n1 == n2): newName = currentName)]
  [setName(newName)]
  [Race = json.set(Race, "name", newName)]
  [output=output+"Name: "+newName+", "]
}]

<!-- Setting ECL to CR from statblock. For CR 1/3 & 1/6 we will set it to .338 & .1625 so XP calcs correctly. -->
[H: id = strfind(statblockOrig, "(?<=[ |\\t]CR )([0-9]+)(/[0-9]+)?")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [ECL=trim(getGroup(id, 1, 0))]
  [output=output+"CR: "+ECL+", "]
  [IF(ECL == "1/3"),CODE:{
    [ECL=".338"]
  }]
  [IF(ECL == "1/6"),CODE:{
    [ECL=".1625"]
  }]
  [Levels = setStrProp(Levels, "ECL", ECL)]
  }]


<!-- Getting Perception. -->
[H: id = strfind(statblockOrig, "(?<=Perception )(.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Perception=trim(getGroup(id, 1, 0))]
  [output=output+"Perception: "+Perception+", "]
  [Skills = setStrProp(Skills, "Perception", Perception)]
  }]
 
 
[H: id = strfind(statblock, "(Fine|Diminutive|Tiny|Small|Medium|Large|Huge|Gargantuan|Colossal).([a-zA-Z]+\\s?[a-zA-Z]*?)\\s?(\\((.+)\\))?.?Init")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Size_txt=getGroup(id, 1, 1)]
  [setSize(Size_txt)]
  [sizeList = table( "SysVars", json.get( table( "SysVars", 0 ), "sizeList" ) ) ]
  [sizeModList = "8,4,2,1,0,-1,-2,-4,-8"]
  [Size=listFind(sizeList, Size_txt)]
  [SizeM = listGet(sizeModList, Size)]
  [type=upper(substring(getGroup(id, 1, 2),0,1))+substring(getGroup(id, 1, 2),1)]
  [Race =  json.set(Race, "type", type)]
  [subtypes=getGroup(id, 1, 4)]
  [output=output+"Size: "+Size_txt+", type: "+type+", subtypes: "+subtypes+"<br>"]
  [subtypes="['"+replace(subtypes,", *","','")+"']"]
  [Race =  json.set(Race, "subtype",subtypes)]
  }]

[H: id = strfind(statblock, "Init ([+-][0-9]+);")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [InitMod=getGroup(id, 1, 1)]
  [output=output+"Init: "+InitMod+", "]
  }]
 
[H: id = strfind(statblock, "Senses ([lL]ow-?light|[dD]arkvision)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [sighttype=upper(substring(getGroup(id, 1, 1),0,1))+substring(getGroup(id, 1, 1),1)]
  [sighttype=replace(sighttype, "-", "")]
  [setSightType(sighttype)]
  [setHasSight(1)]
  [output=output+"Sighttype: "+sighttype+", "]
  }]

[H: id = strfind(statblock, "Reach ([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Reach=getGroup(id, 1, 1)]
  [output=output+"Reach: "+Reach+", "]
  }]

<!-- Find Immunities. Sample: Immune acid, curse effects, flanking, mind-affecting effects, paralysis, poison, sleep -->
[h: resistSearch = ""]
[H: id = strfind(statblock, "\\bImmune \\b((\\w+-?,? ?)+)")]
[H, IF(0<getFindCount(id)),CODE: {
  [Immune = trim(getGroup(id, 1, 1)))]
  [output=output+"Immunities: "+Immune+", "]
}]

<!-- Find DR. Sample: 1/-, 2/adamantine, 3/good -->
[h: DRSearch = ""]
[H: id = strfind(statblock, "DR(.?[0-9]+)/(.+?)[;O]")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [DRSearch = getGroup(id, 1, 1)+"/"+getGroup(id, 1, 2))]
  [DRSearch = replace(DRSearch, "/-", "/All")]
  [DRSearch = replace(DRSearch, "(?i)/Cold Iron", "/ColdIron")]
  [DRSearch = replace(DRSearch, "(?i)/Chaotic", "/Chaos")]
  [DRSearch = replace(DRSearch, "(?i)/Lawful", "/Law")]
}]
 
<!-- Find Resistences. Sample: Resist acid 5, cold 5, electricity 5 -->
[h: resistSearch = ""]
[H: id = strfind(statblock, "(\\bResist \\b(\\w+ \\d+,? ?)+)")]
[H, IF(0<getFindCount(id)),CODE: {
  [resistSearch = trim(getGroup(id, 1, 1)))]
}]

<!-- Put DR & Resist values into JSON Property DRER -->
[H, FOREACH( reduceTypes, json.fields( DRER ) ), CODE: {
   [jRC = json.get( DRER, reduceTypes ) ]
   [prefixT = substring( reduceTypes, 0, 1 ) ]
   [FOREACH( reduceType, json.fields( jRC ) ), CODE: {
      [preValue = json.get( jRC, reduceType ) ]
    
     [reduceVal = 0]

     [resistFind = strfind(resistSearch, "(?i)("+reduceType+" )(\\d+)")]
     [IF(0<getFindCount(resistFind) && prefixT == "E"): reduceVal = getGroup(resistFind, 1, 2)]

     [drFind = strfind(DRSearch, "(?i)(\\d+)/("+reduceType+")")]
     [IF(0<getFindCount(drFind) && prefixT == "D"): reduceVal = getGroup(drFind, 1, 1)]
    
     [ chgValue = eval( "" + prefixT + reduceType + "=" + reduceVal ) ]
    
      [IF( reduceType != "Note" ): tmodV = json.get( DRERMod, if( reduceTypes == "Damage Reduction", "DR_", "ER_" ) + reduceType ) ]
      [IF( reduceType != "Note" ): tVal = max( chgValue, tmodV ); tVal = chgValue ]
     
     [IF( tVal != 0 && tVal != "" && prefixT == "D"): DR = listAppend( DR, tVal + if( reduceType == "Note", "", "/" + if( reduceType == "All", "-", reduceType ) ) ) ]
    
     [IF( tVal != 0 && tVal != "" && prefixT == "E"): DR = listAppend( DR, reduceType + if( reduceType == "Note", "", " (" + if( tVal == "999", "Immune", tVal ) + ")" ) ) ]
    
      [IF( reduceType == "Note" && chgValue == 0 ): chgValue = "" ]
      [IF( preValue != chgValue ):  output = output + reduceType + "= " + chgValue + " (" + preValue + "), "]
      [IF( preValue != chgValue ): jRC = json.set( jRC, reduceType, chgValue ) ]
   }]
   [setProperty( "DRER", json.set( DRER, reduceTypes, jRC ) ) ]
   [IF(DRSearch != "" || resistSearch != ""): output=output+"<br>"]
}]

[H: id = strfind(statblock, "SR ([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [SR=getGroup(id, 1, 1)]
  [SpecialQual="SR "+SR]
  [output=output+"SR: "+SR+", "]
  }]
 
<!-- Defensive Abilities Sample: channel resistance +2 -->
[H: id = strfind(statblock, "(?i)(?<=\\bDefensive Abilities\\b )(([a-zA-Z +-]+\\d?,? ?)+)")]
[H, IF(0<getFindCount(id)),CODE: {
  [SpecialDefense=getGroup(id, 1, 1)]
  [output=output+"Defensive Abilities: "+getFindCount(id)+", "]
}]

<!-- STATS BEGIN -->
[H: id = strfind(statblockOrig, "Str.+?([0-9]*).+?Dex ?([0-9]*).+?Con.?([0-9]*).+?Int.?([0-9]*).+?Wis.?([0-9]*).+?Cha.?([0-9]*)")]

[H, IF(0<getFindCount(id)), CODE:
  {
  [Strength=getGroup(id, 1, 1)]
  [IF(Strength==""):Strength=10]
  [Dexterity=getGroup(id, 1, 2)]
  [IF(Dexterity==""):Dexterity=10]
  [Constitution=getGroup(id, 1, 3)]
  [IF(Constitution==""):Constitution=10]
  [Intelligence=getGroup(id, 1, 4)]
  [IF(Intelligence==""):Intelligence=10]
  [Wisdom=getGroup(id, 1, 5)]
  [IF(Wisdom==""):Wisdom=10]
  [Charisma=getGroup(id, 1, 6)]
  [IF(Charisma==""):Charisma=10]
  [output=output+"Str: "+Strength+", Dex: "+Dexterity+", Con: "+Constitution+", Int: "+Intelligence+", Wis: "+Wisdom+", Cha: "+Charisma+"<br>"]
  }]
<!-- STATS END -->

<!-- SAVES BEGIN -->
[H: id = strfind(statblock, "Fort (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Fort=getGroup(id, 1, 1)-ConB]
  [output=output+"Fort: "+fort+", "]
  }]
[H: id = strfind(statblock, "Ref (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Reflex=getGroup(id, 1, 1)-DexB]
  [output=output+"Ref: "+reflex+", "]
  }]

[H: id = strfind(statblock, "Will (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Will=getGroup(id, 1, 1)-WisB]
  [output=output+"Will: "+Will+"<br>"]
  }]
<!-- SAVES END -->

[H: id = strfind(statblock, "hp ([0-9]+).+?([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [HP=getGroup(id, 1, 1)]
  [HPmax=HP]
  [HPavg=HP]
  [HD=getGroup(id, 1, 2)]
  [Level = max(1,HD)]
  [output=output+"HP: "+HP+", HD: "+HD+"<br>"]
  }]

[H: id = strfind(statblock, "(hp [0-9]+ )\\(([0-9]+d[0-9]+([+-][0-9]+)?(\\)))")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [HitDice=getGroup(id, 1, 2)]
  [HitDice=substring(HitDice,0, length(HitDice)-1)]
  [output=output+"Hit Dice: "+HitDice+"<br>"]
  }]
 
[H: id = strfind(statblock, "Base Atk.?(.?[0-9]+);")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [BAB=getGroup(id, 1, 1)]
  [output=output+"Base Atk: "+BAB+", "]
  }]
 
[H: id = strfind(statblock, "CMB.?(.?[0-9]+);")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [CMBMod=getGroup(id, 1, 1)]
  [output=output+"CMB: "+CMBMod+", "]
  }]

<!-- AC BEGIN -->
[H: id = strfind(statblock, "(.?[0-9]+) natural")]
[H, IF(0<getFindCount(id)): natural=getGroup(id, 1, 1); natural=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Natural", natural)]

[H: id = strfind(statblock, "(.?[0-9]+) armor")]
[H, IF(0<getFindCount(id)): armor=getGroup(id, 1, 1);armor=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Armor", armor)]

[H: id = strfind(statblock, "(.?[0-9]+) deflection")]
[H, IF(0<getFindCount(id)): deflect=getGroup(id, 1, 1); deflect=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Deflection", deflect)]

[H: id = strfind(statblock, "(.?[0-9]+) dodge")]
[H, IF(0<getFindCount(id)): dodge=getGroup(id, 1, 1); dodge=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Dodge", dodge)]

[H: id = strfind(statblock, "(.?[0-9]+) shield")]
[H, IF(0<getFindCount(id)): shield=getGroup(id, 1, 1); shield=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Shield", shield)]

[H: id = strfind(statblock, "AC ([0-9]+),")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [AC=getGroup(id, 1, 1)]
  [tch=AC-armor-shield]
  [FF=AC-dodge-DexB]
  [CMD=10+BAB+StrB+DexB-SizeM+dodge+deflect]
  [CMDFF=CMD-DexB-dodge]
  [AC=concat(AC,"/",tch,"/",FF,"/",CMD,"/",CMDFF)]
  [output=output+"AC/tch/FF/CMD/CMDFF: "+AC+"<br>"]
  }]
<!-- AC END -->


[H: id = strfind(statblock, "(Speed|Spd) ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 2)]
  [output=output+"Spd: "+spd]
  [Speed = json.set(Speed, "base",spd)]
  }]
[H: id = strfind(statblock, "fly ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Fly: "+spd]
  [Speed = json.set(Speed, "fly",spd)]
  }]
[H: id = strfind(statblock, "swim ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Swim: "+spd]
  [Speed = json.set(Speed, "swim",spd)]
  }]
[H: id = strfind(statblock, "burrow ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Burrow: "+spd]
  [Speed = json.set(Speed, "burrow",spd)]
  }]
[H: id = strfind(statblock, "climb ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Climb: "+spd]
  [Speed = json.set(Speed, "climb",spd)]
  }]
[H: output=output+"<br>"]

<!-- SKILLS BEGIN -->
[H: tSkillsJ ="[]"]
[H: output=output+"Skills: "]
[H, FOREACH(s, SkillsJ), CODE:
  {
  [skN = json.get(s, "name")]
  [id=0]
  [id = strfind(statblock, skN+"\\s(.?[0-9]+)")]
  [H, IF(0<getFindCount(id)), CODE:
    {
    [skN = replace(skN, " ", "")] <!-- Remove spaces from skill name -->
    [skStat = getStrProp(SkillStat, skN)]   
    [skVal = getGroup(id, 1, 1)]
    [output=output+skN+" "+skVal+", "]
    [s = json.set(s, "rank", skVal-eval(skStat))]   
    }]
  [tSkillsJ = json.append(tSkillsJ,s)]
  }]
[H: output=output+"<br>"]
[H: SkillsJ=tSkillsJ]
<!-- SKILLS END -->

<!-- FEATS BEGIN -->
[H: output=output+"Feats: "]
[H: id = strfind(statblock, "(Improved Initiative)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedInitiative",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedInitiative",0)]
  }]
[H: id = strfind(statblock, "(Agile Maneuvers)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "AgileManeuvers",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "AgileManeuvers",0)]
  }]
[H: id = strfind(statblock, "(Improved Bull Rush)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedBullRush",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedBullRush",0)]
  }]
[H: id = strfind(statblock, "(Improved Disarm)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedDisarm",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedDisarm",0)]
  }]
[H: id = strfind(statblock, "(Improved Grapple)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedGrapple",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedGrapple",0)]
  }]
[H: id = strfind(statblock, "(Improved Overrun)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedOverrun",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedOverrun",0)]
  }]
[H: id = strfind(statblock, "(Improved Sunder)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedSunder",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedSunder",0)]
  }]
[H: id = strfind(statblock, "(Improved Trip)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedTrip",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedTrip",0)]
  }]
[H: id = strfind(statblock, "(Improved Channeling)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedChanneling",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedChanneling",0)]
  }]
[H: id = strfind(statblock, "(Two.?Weapon Fighting)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "TwoWeaponFighting",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "TwoWeaponFighting",0)]
  }]
[H: id = strfind(statblock, "(Multi.?[aA]ttack)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "MultiAttack",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "MultiAttack",0)]
  }]
 
[H: id = strfind(statblock, "(Power Attack)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "PowerAttack",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "PowerAttack",0)]
  }]

[H: id = strfind(statblock, "(Weapon Finesse)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "WeaponFinesse",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "WeaponFinesse",0)]
  }]
[H: id = strfind(statblock, "(Uncanny Dodge)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "UncannyDodge",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "UncannyDodge",0)]
  }]
[H: id = strfind(statblock, "(Die.?[hH]ard)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "DieHard",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "DieHard",0)]
  }]
[H: output=output+"<br>"]
<!-- FEATS END -->

[H: id = strfind(statblockOrig, "Special Attacks (.+)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [SpecialATK=getGroup(id, 1, 1)]
  [SpecialATK=trim(SpecialATK)]
  [SpecialATK=substring(SpecialATK,0,min(length(SpecialATK),100))]
  [output=output+"SA: "+SpecialATK+"<br>"]
  };{
  [SpecialATK=""]
  }]

<!-- ATTACKS BEGIN -->
<!-- Insert empty weapon strings -->
[H: wpnstr=getPropertyDefault( "Weapon0" )]
[H, c(7,""),CODE:
  {
  [wpn="Weapon"+roll.count]
  [eval(wpn + " = '" + wpnstr+ "'")]
  }]

[H: atkno = 0]

<!-- MELEE -->
<!-- The '(?i)' makes the expression case-insensitive -->
[H: id = strfind(statblock, "Melee (.+?)(?i)(?=Tactic|Face|Space|Reach|Special|Ranged|Stat|Spell-Like Abilities|---)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [allmelee=getGroup(id, 1, 1)]
  [setProperty("OriginalMeleeLine", allmelee)]
  <!-- separate each attack option -->
  [allmelee=stringToList(allmelee, "( or (Melee)?)|(Melee)",":")]
  [atkno = listCount(allmelee, ":")]
  }]
 
<!-- Loop through each attack option and divide into weapons -->
[H: wpnarray=""]
[H: wpnno=0]
[H, FOR(i,0,atkno,1), CODE:
  {
  [atkstr=listget(allmelee, i, ":")]
  [atkstr=stringToList(atkstr, "(?<=\\)) and|(?<=\\)), ",":")]
  [wpns = listCount(atkstr, ":")]
 
  [FOR(j,0,wpns,1), CODE:
  {
    [WpnName = "Weapon" + wpnno]
    [wpnarray=json.append(wpnarray, trim(listGet(atkstr,j,":")))]
    [ x = eval(WpnName) ]
    [IF(j>0):eval(WpnName + "= '" + replace(x,"Primary=\\d+", "Primary=2")+ "'")]
   
    <!-- Set attack options after first to secondary attacks -->
    [eval(WpnName + "= '" + replace(x,"OHLight=\\d+", "OHLight=2")+ "'")]
   
   <!-- Default to not multiattack -->
    [wpnno = wpnno +1]
    }]
  }]
 
<!-- RANGED -->
[H: atkno = 0]
[H: id = strfind(statblock, "Ranged (.+?)(?=Tac|Face|Space|Reach|Special|Ranged|STAT|Stat|Spell-Like Abilities|---)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [allranged=getGroup(id, 1, 1)]
  [setProperty("OriginalRangedLine", allranged)]
  <!-- separate each attack option -->
  [allranged=stringToList(allranged, "(\\s?or (Ranged)?)|(Ranged)",":")]
  [atkno = listCount(allranged, ":")]
  }]
<!-- Loop through each attack option and divide into weapons -->
[H, FOR(i,0,atkno,1), CODE:
  {
  [atkstr=listget(allranged, i, ":")]
  [atkstr=stringToList(atkstr, "(?<=\\)) and|(?<=\\)), ",":")]
  [wpns = listCount(atkstr, ":")]
  [FOR(j,0,wpns,1), CODE:
    {
    [WpnName = "Weapon" + wpnno]
    [wpnarray=json.append(wpnarray, trim(listGet(atkstr,j,":")))]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Ranged", 1)+ "'")]
    [wpnno = wpnno +1]
    }]
  }]
 
<!-- extract info from each attack  -->
[H: wpnno=0]
[H, FOREACH(atkstr, wpnarray), CODE: {
  [atkstr=trim(atkstr)]
  [id = strfind(atkstr, "([+-]\\d+)?(\\d+)?(.+(?= [\\+-]\\d+ \\()) ([+-]\\d+)[/+\\-0-9\\s]*?\\((.+)\\)")]
  [regexptofindweaponname = ".+(?= (/?[\\+-]\\d+)+ \\()"]
 
  [IF(0<getFindCount(id)), CODE:
    {
    [WpnName = "Weapon" + wpnno]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Name", getGroup(id, 1, 3)) + "'")]
   
    <!-- Quantity -->
    [wquant = 1]
    [wbonus = ""]
    [IF(getGroup(id,1,1)==""): wquant = getGroup(id, 1, 2); wbonus="+ "+getGroup(id,1,1)]
    [IF(getGroup(id,1,2)==""): wquant = 1]
    [IF(1<wquant):eval(WpnName + "= '" + setStrProp(eval(WpnName),"Quantity", wquant)+ "'")]
   
   <!-- Manufactored ? -->
    [id2 = strfind(atkstr, "(slam|bite|claw|gore|hoof|tentacle|wing|pincer|tail|sting|talon)")]
    [IF(0==getFindCount(id2)):eval(WpnName + "= '" + setStrProp(eval(WpnName),"Manufactured", 1)+ "'")]
   
   <!-- Not a natural weapon -->
    <!-- Attack bonus (assumes StrB for melee and DexB for ranged) -->
    [watkbonus=getGroup(id, 1, 4)]
    [Ranged=getStrProp(eval(WpnName),"Ranged")]
    [IF(Ranged>0):watkbonus=watkbonus-BAB-DexB-SizeM;watkbonus=watkbonus-BAB-StrB-SizeM]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"AtkBonus", watkbonus)+ "'")]
   
   <!-- CritMult-->
    [wdam=getGroup(id, 1, 5)]
    [CritMult=2]
    [id2 = strfind(wdam, "/[xX](\\d)")]
    [IF(0<getFindCount(id2)):CritMult=getGroup(id2, 1, 1)]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritMult", CritMult)+ "'")]
   
   <!-- CritRange-->
    [CritRange=20]
    [id2 = strfind(wdam, "/(1[0-9])")]
    [IF(0<getFindCount(id2)):CritRange=getGroup(id2, 1, 1)]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritRange", CritRange)+ "'")]
   
   <!-- Damage -->
    [Damage="0d4 plus" + wdam]
    [id2 = strfind(wdam, "(\\dd\\d+)[^p]*(plus .+)?")]
    [IF(0<getFindCount(id2)):Damage=getGroup(id2, 1, 1)+wbonus+" "+getGroup(id2, 1, 2)]
   [Damage123=replace(Damage, " ", "")]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Damage", Damage)+ "'")]
   
   <!-- Two handed ? -->
    <!-- Default to onehanded weapon -->
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 0)+ "'")]

    [id2 = strfind(atkstr, "(?i)(longspear|quarterstaff| spear|falchion|glaive|greataxe|greatclub|greatsword|guisarme|halberd|lance|ranseur|scythe|spiked chain|elven curve blade|dire flail|two-bladed sword|urgrosh|hooked hammer)")]

    [IF(0<getFindCount(id2)):eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 1)+ "'")]
   
   <!-- If weapon damage == Str 1.5 then assume two handed -->
   [output=output+"DmgMax: "+getStrProp(eval(WpnName),"DmgMax")+"<br>"]
    }]
  [wpnno = wpnno +1]
  }]

[H: output = output + "Weapons: " + wpnarray+"<br>"]

<!--
Name=Slam ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=0 ; Ranged=0  ;
ATTACKS END -->

<!-- Getting treasure from Ecology section. -->
[H: id = strfind(statblockOrig, "(?i)(?<=Treasure )(None|Standard|Double|Triple|Incidental|NPC gear)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [TreasureType=getGroup(id, 1, 0)]
  [output=output+"Treasure Type: "+TreasureType+"<br>"]
  }]

<!-- Setting Fast Healing if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Fast Healing )([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [FastHealing=getGroup(id, 1, 0)]
  [output=output+"Fast Healing: "+FastHealing+"<br>"]
  }]
 
<!-- Setting Regeneration if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Regeneration )([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Regeneration=getGroup(id, 1, 0)]
  [output=output+"Regeneration: "+Regeneration+"<br>"]
  }]

<!-- Setting Anti Regeneration damage type if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Regeneration )([0-9]+.+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [AntiRegen=getGroup(id, 1, 0)]
  [output=output+"Anti-Regen Damage Type: "+AntiRegen+"<br>"]
  }]

<!-- Statblock from HeroLab -->
[H: id = strfind(statblockOrig, "(?i)(Hero Lab logo are Registered Trademarks)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [HeroLab=1]
  [output=output+"Stat block generated from Hero Lab.<br>"]
  }]
 
[R,S,G: output]

[H: HP = HPmax ]
[H: HPNonLethalDMG = 0]
[H: tToken = currentToken() ]
[H, MACRO( "[email protected]:libDnD35Pathfinder" ): "Token=" + tToken]
[H: setState("Prone", 0)]
[H: setState("Unconscious", 0)]
[H: setLayer("TOKEN") ]
[/spoiler]
-Jamz
____________________
Custom MapTool 1.4.x.x Fork: maptool.nerps.net
Custom TokenTool 2.0 Fork: tokentool.nerps.net
More information here: MapTool Nerps! Fork

neofax
Great Wyrm
Posts: 1694
Joined: Tue May 26, 2009 8:51 pm
Location: Philadelphia, PA
Contact:

Re: PF statblock importer

Post by neofax »

I get a error on Al-mi’raj.

Code: Select all

Illegal argument type java.lang.String, expecting java.math.BigDecimal
Image
Time-Zone information UTC -5

User avatar
JamzTheMan
Great Wyrm
Posts: 1872
Joined: Mon May 10, 2010 12:59 pm
Location: Chicagoland
Contact:

Re: PF statblock importer

Post by JamzTheMan »

neofax wrote:I get a error on Al-mi’raj.

Code: Select all

Illegal argument type java.lang.String, expecting java.math.BigDecimal


Just ran it through my macro and it works, but I've been working on it on/off today. You can try this one but it will require some token property changes, especially for Weapon0-9, adding DmgBonus. I'll post my current prop changes in another post (due to size limits).

[spoiler=Statblock2Token v2.2]

Code: Select all

<!-- Statblock2Token v2.1
Jamz: Now paste formatted text into GM text (which stays formatted) and handles CR now.
Jamz: Added Fast-Healing, Regeneration, adjusted Weapons to be Hero Labs friendly

Changes: HD fixed, Resets token, Skills with space in the name except SleightOfHand
Macro takes a Pathfinder statblock as input and updates selected token with various stats.
Macro assumes pathfinder properties in the selected token.
Statblock format should mirror PF bestiary format.
Not handled: SQ, Spells
-->
[H: ids = getSelected()]
[H: abort(if(ids == "", 0, 1))]

<!-- Lets keep nice formated text in GMNotes and paste there first manually and then retrieve it from there
   H: status=input("statblock|Insert statblock here|Enter statblock|TEXT|WIDTH=40")
   H: abort(if(status < 1, 0, 1))
   H: setGMNotes(statblock)
-->

[H: setPropertyType("Pathfinder")]

<!--Lets keep my custom Nerps properties if already populated-->
[H: Nerps_WikiTemp=getProperty("Nerps_Wiki")]
[H: Nerps_TreasureTemp=getProperty("Nerps_Treasure")]
[H: XPTemp=getProperty("XP")]
[H: NewXPTemp=getProperty("NewXP")]
[H: XPadvancmentPaceTemp=getProperty("XPadvancmentPace")]

[H: propnames = getPropertyNames()]
[H, foreach(propname,propnames),CODE:
  {
  [resetProperty(propname)]
  }]

[H: setProperty("Nerps_Wiki", Nerps_WikiTemp)]
[H: setProperty("Nerps_Treasure", Nerps_TreasureTemp)]
[H: setProperty("XP", XPTemp)]
[H: setProperty("NewXP", NewXPTemp)]
[H: setProperty("XPadvancmentPace", XPadvancmentPaceTemp)]

[H: statblock = getGMNotes()]
[H: statblock = replace(statblock, "\\xD7", "x")]
[H: statblock = replace(statblock, "\\u2013", "-")]
[H: statblock = replace(statblock, "&#151;", "-")]
[H: statblock = replace(statblock, "Ecolo gy", "Ecology")]

[H: setGMNotes(statblock)]
[H: statblockOrig = statblock]
[H: statblock = replace(statblock, "\\n", " ")]

[H: output="Token Updated:<br>"]
[H: id = strfind(statblock, "^(.+).*CR ")]
[H, IF(0<getFindCount(id)),CODE: {
  [currentName = getName()]
  [newName=trim(getGroup(id, 1, 1))]
  [n1 = upper(currentName)]
  [n2 = upper(newName)]
  [if(n1 == n2): newName = currentName)]
  [setName(newName)]
  [Race = json.set(Race, "name", newName)]
  [output=output+"Name: "+newName+", "]
}]

<!-- Setting ECL to CR from statblock. For CR 1/3 & 1/6 we will set it to .338 & .1625 so XP calcs correctly. -->
[H: id = strfind(statblockOrig, "(?<=[ |\\t]CR )([0-9]+)(/[0-9]+)?")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [ECL=trim(getGroup(id, 1, 0))]
  [output=output+"CR: "+ECL+", "]
  [IF(ECL == "1/3"),CODE:{
    [ECL=".338"]
  }]
  [IF(ECL == "1/6"),CODE:{
    [ECL=".1625"]
  }]
  [Levels = setStrProp(Levels, "ECL", ECL)]
  }]


<!-- Getting Perception. -->
[H: id = strfind(statblockOrig, "(?<=Perception )(.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Perception=trim(getGroup(id, 1, 0))]
  [output=output+"Perception: "+Perception+", "]
  [Skills = setStrProp(Skills, "Perception", Perception)]
  }]
 
 
[H: id = strfind(statblock, "(Fine|Diminutive|Tiny|Small|Medium|Large|Huge|Gargantuan|Colossal).([a-zA-Z]+\\s?[a-zA-Z]*?)\\s?(\\((.+)\\))?.?Init")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Size_txt=getGroup(id, 1, 1)]
  [setSize(Size_txt)]
  [sizeList = table( "SysVars", json.get( table( "SysVars", 0 ), "sizeList" ) ) ]
  [sizeModList = "8,4,2,1,0,-1,-2,-4,-8"]
  [Size=listFind(sizeList, Size_txt)]
  [SizeM = listGet(sizeModList, Size)]
  [type=upper(substring(getGroup(id, 1, 2),0,1))+substring(getGroup(id, 1, 2),1)]
  [Race =  json.set(Race, "type", type)]
  [subtypes=getGroup(id, 1, 4)]
  [output=output+"Size: "+Size_txt+", type: "+type+", subtypes: "+subtypes+"<br>"]
  [subtypes="['"+replace(subtypes,", *","','")+"']"]
  [Race =  json.set(Race, "subtype",subtypes)]
  }]

[H: id = strfind(statblock, "Init ([+-][0-9]+);")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [InitMod=getGroup(id, 1, 1)]
  [output=output+"Init: "+InitMod+", "]
  }]
 
[H: id = strfind(statblock, "Senses ([lL]ow-?light|[dD]arkvision)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [sighttype=upper(substring(getGroup(id, 1, 1),0,1))+substring(getGroup(id, 1, 1),1)]
  [sighttype=replace(sighttype, "-", "")]
  [setSightType(sighttype)]
  [setHasSight(1)]
  [output=output+"Sighttype: "+sighttype+", "]
  }]

[H: id = strfind(statblock, "Reach ([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Reach=getGroup(id, 1, 1)]
  [output=output+"Reach: "+Reach+", "]
  }]

<!-- Find Immunities. Sample: Immune acid, curse effects, flanking, mind-affecting effects, paralysis, poison, sleep -->
[h: resistSearch = ""]
[H: id = strfind(statblock, "\\bImmune \\b((\\w+-?,? ?)+)")]
[H, IF(0<getFindCount(id)),CODE: {
  [Immune = trim(getGroup(id, 1, 1)))]
  [output=output+"Immunities: "+Immune+", "]
}]

<!-- Find DR. Sample: 1/-, 2/adamantine, 3/good -->
[h: DRSearch = ""]
[H: id = strfind(statblock, "DR(.?[0-9]+)/(.+?)[;O]")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [DRSearch = getGroup(id, 1, 1)+"/"+getGroup(id, 1, 2))]
  [DRSearch = replace(DRSearch, "/-", "/All")]
  [DRSearch = replace(DRSearch, "(?i)/Cold Iron", "/ColdIron")]
  [DRSearch = replace(DRSearch, "(?i)/Chaotic", "/Chaos")]
  [DRSearch = replace(DRSearch, "(?i)/Lawful", "/Law")]
}]
 
<!-- Find Resistences. Sample: Resist acid 5, cold 5, electricity 5 -->
[h: resistSearch = ""]
[H: id = strfind(statblock, "(\\bResist \\b(\\w+ \\d+,? ?)+)")]
[H, IF(0<getFindCount(id)),CODE: {
  [resistSearch = trim(getGroup(id, 1, 1)))]
}]

<!-- Put DR & Resist values into JSON Property DRER -->
[H, FOREACH( reduceTypes, json.fields( DRER ) ), CODE: {
   [jRC = json.get( DRER, reduceTypes ) ]
   [prefixT = substring( reduceTypes, 0, 1 ) ]
   [FOREACH( reduceType, json.fields( jRC ) ), CODE: {
      [preValue = json.get( jRC, reduceType ) ]
    
     [reduceVal = 0]

     [resistFind = strfind(resistSearch, "(?i)("+reduceType+" )(\\d+)")]
     [IF(0<getFindCount(resistFind) && prefixT == "E"): reduceVal = getGroup(resistFind, 1, 2)]

     [drFind = strfind(DRSearch, "(?i)(\\d+)/("+reduceType+")")]
     [IF(0<getFindCount(drFind) && prefixT == "D"): reduceVal = getGroup(drFind, 1, 1)]
    
     [ chgValue = eval( "" + prefixT + reduceType + "=" + reduceVal ) ]
    
      [IF( reduceType != "Note" ): tmodV = json.get( DRERMod, if( reduceTypes == "Damage Reduction", "DR_", "ER_" ) + reduceType ) ]
      [IF( reduceType != "Note" ): tVal = max( chgValue, tmodV ); tVal = chgValue ]
     
     [IF( tVal != 0 && tVal != "" && prefixT == "D"): DR = listAppend( DR, tVal + if( reduceType == "Note", "", "/" + if( reduceType == "All", "-", reduceType ) ) ) ]
    
     [IF( tVal != 0 && tVal != "" && prefixT == "E"): DR = listAppend( DR, reduceType + if( reduceType == "Note", "", " (" + if( tVal == "999", "Immune", tVal ) + ")" ) ) ]
    
      [IF( reduceType == "Note" && chgValue == 0 ): chgValue = "" ]
      [IF( preValue != chgValue ):  output = output + reduceType + "= " + chgValue + " (" + preValue + "), "]
      [IF( preValue != chgValue ): jRC = json.set( jRC, reduceType, chgValue ) ]
   }]
   [setProperty( "DRER", json.set( DRER, reduceTypes, jRC ) ) ]
   [IF(DRSearch != "" || resistSearch != ""): output=output+"<br>"]
}]

[H: id = strfind(statblock, "SR ([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [SR=getGroup(id, 1, 1)]
  [SpecialQual="SR "+SR]
  [output=output+"SR: "+SR+", "]
  }]
 
<!-- Defensive Abilities Sample: Defensive Abilities incorporeal, channel resistance +2; -->
[H: id = strfind(statblockOrig, "(?i)(?<=\\bDefensive Abilities\\b )([a-zA-Z +-,]+\\d?)")]
[H, IF(0<getFindCount(id)),CODE: {
  [SpecialDefense=getGroup(id, 1, 1)]
  [output=output+"Defensive Abilities: "+getFindCount(id)+", "]
}]

<!-- STATS BEGIN -->
[H: id = strfind(statblockOrig, "Str.+?([0-9]*).+?Dex ?([0-9]*).+?Con.?([0-9]*).+?Int.?([0-9]*).+?Wis.?([0-9]*).+?Cha.?([0-9]*)")]

[H, IF(0<getFindCount(id)), CODE:
  {
  [Strength=getGroup(id, 1, 1)]
  [IF(Strength==""):Strength=10]
  [Dexterity=getGroup(id, 1, 2)]
  [IF(Dexterity==""):Dexterity=10]
  [Constitution=getGroup(id, 1, 3)]
  [IF(Constitution==""):Constitution=10]
  [Intelligence=getGroup(id, 1, 4)]
  [IF(Intelligence==""):Intelligence=10]
  [Wisdom=getGroup(id, 1, 5)]
  [IF(Wisdom==""):Wisdom=10]
  [Charisma=getGroup(id, 1, 6)]
  [IF(Charisma==""):Charisma=10]
  [output=output+"Str: "+Strength+", Dex: "+Dexterity+", Con: "+Constitution+", Int: "+Intelligence+", Wis: "+Wisdom+", Cha: "+Charisma+"<br>"]
  }]
<!-- STATS END -->

<!-- SAVES BEGIN -->
[H: id = strfind(statblock, "Fort (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Fort=getGroup(id, 1, 1)-ConB]
  [output=output+"Fort: "+fort+", "]
  }]
[H: id = strfind(statblock, "Ref (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Reflex=getGroup(id, 1, 1)-DexB]
  [output=output+"Ref: "+reflex+", "]
  }]

[H: id = strfind(statblock, "Will (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Will=getGroup(id, 1, 1)-WisB]
  [output=output+"Will: "+Will+"<br>"]
  }]
<!-- SAVES END -->

[H: id = strfind(statblock, "hp ([0-9]+).+?([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [HP=getGroup(id, 1, 1)]
  [HPmax=HP]
  [HPavg=HP]
  [HD=getGroup(id, 1, 2)]
  [Level = max(1,HD)]
  [output=output+"HP: "+HP+", HD: "+HD+"<br>"]
  }]

[H: id = strfind(statblock, "(hp [0-9]+ )\\(([0-9]+d[0-9]+([+-][0-9]+)?(\\)))")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [HitDice=getGroup(id, 1, 2)]
  [HitDice=substring(HitDice,0, length(HitDice)-1)]
  [output=output+"Hit Dice: "+HitDice+"<br>"]
  }]
 
[H: id = strfind(statblock, "Base Atk.?(.?[0-9]+);")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [BAB=getGroup(id, 1, 1)]
  [output=output+"Base Atk: "+BAB+", "]
  }]
 
[H: id = strfind(statblock, "CMB.?(.?[0-9]+);")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [CMBMod=getGroup(id, 1, 1)]
  [output=output+"CMB: "+CMBMod+", "]
  }]

<!-- AC BEGIN -->
[H: id = strfind(statblock, "(.?[0-9]+) natural")]
[H, IF(0<getFindCount(id)): natural=getGroup(id, 1, 1); natural=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Natural", natural)]

[H: id = strfind(statblock, "(.?[0-9]+) armor")]
[H, IF(0<getFindCount(id)): armor=getGroup(id, 1, 1);armor=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Armor", armor)]

[H: id = strfind(statblock, "(.?[0-9]+) deflection")]
[H, IF(0<getFindCount(id)): deflect=getGroup(id, 1, 1); deflect=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Deflection", deflect)]

[H: id = strfind(statblock, "(.?[0-9]+) dodge")]
[H, IF(0<getFindCount(id)): dodge=getGroup(id, 1, 1); dodge=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Dodge", dodge)]

[H: id = strfind(statblock, "(.?[0-9]+) shield")]
[H, IF(0<getFindCount(id)): shield=getGroup(id, 1, 1); shield=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Shield", shield)]

[H: id = strfind(statblock, "AC ([0-9]+),")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [AC=getGroup(id, 1, 1)]
  [tch=AC-armor-shield]
  [FF=AC-dodge-DexB]
  [CMD=10+BAB+StrB+DexB-SizeM+dodge+deflect]
  [CMDFF=CMD-DexB-dodge]
  [AC=concat(AC,"/",tch,"/",FF,"/",CMD,"/",CMDFF)]
  [output=output+"AC/tch/FF/CMD/CMDFF: "+AC+"<br>"]
  }]
<!-- AC END -->


[H: id = strfind(statblock, "(Speed|Spd) ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 2)]
  [output=output+"Spd: "+spd]
  [Speed = json.set(Speed, "base",spd)]
  }]
[H: id = strfind(statblock, "fly ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Fly: "+spd]
  [Speed = json.set(Speed, "fly",spd)]
  }]
[H: id = strfind(statblock, "swim ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Swim: "+spd]
  [Speed = json.set(Speed, "swim",spd)]
  }]
[H: id = strfind(statblock, "burrow ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Burrow: "+spd]
  [Speed = json.set(Speed, "burrow",spd)]
  }]
[H: id = strfind(statblock, "climb ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Climb: "+spd]
  [Speed = json.set(Speed, "climb",spd)]
  }]
[H: output=output+"<br>"]

<!-- SKILLS BEGIN -->
[H: tSkillsJ ="[]"]
[H: output=output+"Skills: "]
[H, FOREACH(s, SkillsJ), CODE:
  {
  [skN = json.get(s, "name")]
  [id=0]
  [id = strfind(statblock, skN+"\\s(.?[0-9]+)")]
  [H, IF(0<getFindCount(id)), CODE:
    {
    [skN = replace(skN, " ", "")] <!-- Remove spaces from skill name -->
    [skStat = getStrProp(SkillStat, skN)]   
    [skVal = getGroup(id, 1, 1)]
    [output=output+skN+" "+skVal+", "]
    [s = json.set(s, "rank", skVal-eval(skStat))]   
    }]
  [tSkillsJ = json.append(tSkillsJ,s)]
  }]
[H: output=output+"<br>"]
[H: SkillsJ=tSkillsJ]
<!-- SKILLS END -->

<!-- FEATS BEGIN -->
[H: output=output+"Feats: "]
[H: id = strfind(statblock, "(Improved Initiative)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedInitiative",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedInitiative",0)]
  }]
[H: id = strfind(statblock, "(Agile Maneuvers)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "AgileManeuvers",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "AgileManeuvers",0)]
  }]
[H: id = strfind(statblock, "(Improved Bull Rush)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedBullRush",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedBullRush",0)]
  }]
[H: id = strfind(statblock, "(Improved Disarm)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedDisarm",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedDisarm",0)]
  }]
[H: id = strfind(statblock, "(Improved Grapple)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedGrapple",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedGrapple",0)]
  }]
[H: id = strfind(statblock, "(Improved Overrun)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedOverrun",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedOverrun",0)]
  }]
[H: id = strfind(statblock, "(Improved Sunder)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedSunder",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedSunder",0)]
  }]
[H: id = strfind(statblock, "(Improved Trip)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedTrip",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedTrip",0)]
  }]
[H: id = strfind(statblock, "(Improved Channeling)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedChanneling",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedChanneling",0)]
  }]
[H: id = strfind(statblock, "(Two.?Weapon Fighting)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "TwoWeaponFighting",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "TwoWeaponFighting",0)]
  }]
[H: id = strfind(statblock, "(Multi.?[aA]ttack)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "MultiAttack",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "MultiAttack",0)]
  }]
 
[H: id = strfind(statblock, "(Power Attack)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "PowerAttack",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "PowerAttack",0)]
  }]

[H: id = strfind(statblock, "(Weapon Finesse)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "WeaponFinesse",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "WeaponFinesse",0)]
  }]
[H: id = strfind(statblock, "(Uncanny Dodge)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "UncannyDodge",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "UncannyDodge",0)]
  }]
[H: id = strfind(statblock, "(Die.?[hH]ard)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "DieHard",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "DieHard",0)]
  }]
[H: output=output+"<br>"]
<!-- FEATS END -->

[H: id = strfind(statblockOrig, "Special Attacks (.+)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [SpecialATK=getGroup(id, 1, 1)]
  [SpecialATK=trim(SpecialATK)]
  [SpecialATK=substring(SpecialATK,0,min(length(SpecialATK),100))]
  [output=output+"SA: "+SpecialATK+"<br>"]
  };{
  [SpecialATK=""]
  }]

<!-- ATTACKS BEGIN -->
<!-- Insert empty weapon strings -->
[H: wpnstr=getPropertyDefault( "Weapon0" )]
[H, c(7,""),CODE:
  {
  [wpn="Weapon"+roll.count]
  [eval(wpn + " = '" + wpnstr+ "'")]
  }]

[H: atkno = 0]

<!-- MELEE -->
<!-- The '(?i)' makes the expression case-insensitive -->
[H: id = strfind(statblock, "Melee (.+?)(?i)(?=Tactic|Face|Space|Reach|Special|Ranged|Stat|Spell-Like Abilities|---)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [allmelee=getGroup(id, 1, 1)]
  [setProperty("OriginalMeleeLine", allmelee)]
  <!-- separate each attack option -->
  [allmelee=stringToList(allmelee, "( or (Melee)?)|(Melee)",":")]
  [atkno = listCount(allmelee, ":")]
  }]
 
<!-- Loop through each attack option and divide into weapons -->
[H: wpnarray=""]
[H: wpnno=0]
[H, FOR(i,0,atkno,1), CODE:
  {
  [atkstr=listget(allmelee, i, ":")]
  [atkstr=stringToList(atkstr, "(?<=\\)) and|(?<=\\)), ",":")]
  [wpns = listCount(atkstr, ":")]
 
  [FOR(j,0,wpns,1), CODE:
  {
    [WpnName = "Weapon" + wpnno]
    [wpnarray=json.append(wpnarray, trim(listGet(atkstr,j,":")))]
    [ x = eval(WpnName) ]
    [IF(j>0):eval(WpnName + "= '" + replace(x,"Primary=\\d+", "Primary=2")+ "'")]
   
    <!-- Set attack options after first to secondary attacks -->
    [eval(WpnName + "= '" + replace(x,"OHLight=\\d+", "OHLight=2")+ "'")]
   
   <!-- Default to not multiattack -->
    [wpnno = wpnno +1]
    }]
  }]
 
<!-- RANGED -->
[H: atkno = 0]
[H: id = strfind(statblock, "Ranged (.+?)(?=Tac|Face|Space|Reach|Special|Ranged|STAT|Stat|Spell-Like Abilities|---)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [allranged=getGroup(id, 1, 1)]
  [setProperty("OriginalRangedLine", allranged)]
  <!-- separate each attack option -->
  [allranged=stringToList(allranged, "(\\s?or (Ranged)?)|(Ranged)",":")]
  [atkno = listCount(allranged, ":")]
  }]
<!-- Loop through each attack option and divide into weapons -->
[H, FOR(i,0,atkno,1), CODE:
  {
  [atkstr=listget(allranged, i, ":")]
  [atkstr=stringToList(atkstr, "(?<=\\)) and|(?<=\\)), ",":")]
  [wpns = listCount(atkstr, ":")]
  [FOR(j,0,wpns,1), CODE:
    {
    [WpnName = "Weapon" + wpnno]
    [wpnarray=json.append(wpnarray, trim(listGet(atkstr,j,":")))]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Ranged", 1)+ "'")]
    [wpnno = wpnno +1]
    }]
  }]
 
<!-- extract info from each attack  -->
[H: wpnno=0]
[H, FOREACH(atkstr, wpnarray), CODE: {
  [atkstr=trim(atkstr)]
  [id = strfind(atkstr, "([+-]\\d+)?(\\d+)?(.+(?= [\\+-]\\d+ \\()) ([+-]\\d+)[/+\\-0-9\\s]*?\\((.+)\\)")]
  [regexptofindweaponname = ".+(?= (/?[\\+-]\\d+)+ \\()"]
 
  [IF(0<getFindCount(id)), CODE: {
    [WpnName = "Weapon" + wpnno]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Name", getGroup(id, 1, 3)) + "'")]
   
    <!-- Quantity -->
    [wquant = 1]
    [wbonus = ""]
    [IF(getGroup(id,1,1)==""): wquant = getGroup(id, 1, 2); wbonus="+ "+getGroup(id,1,1)]
    [IF(getGroup(id,1,2)==""): wquant = 1]
    [IF(1<wquant):eval(WpnName + "= '" + setStrProp(eval(WpnName),"Quantity", wquant)+ "'")]
   
   <!-- Manufactored ? -->
    [id2 = strfind(atkstr, "(slam|bite|claw|gore|hoof|tentacle|wing|pincer|tail|sting|talon)")]
    [IF(0==getFindCount(id2)):eval(WpnName + "= '" + setStrProp(eval(WpnName),"Manufactured", 1)+ "'")]
   
   <!-- Not a natural weapon -->
    <!-- Attack bonus (assumes StrB for melee and DexB for ranged) -->
    [watkbonus=getGroup(id, 1, 4)]
    [Ranged=getStrProp(eval(WpnName),"Ranged")]
    [IF(Ranged>0):watkbonus=watkbonus-BAB-DexB-SizeM;watkbonus=watkbonus-BAB-StrB-SizeM]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"AtkBonus", watkbonus)+ "'")]
   
   <!-- CritMult-->
    [wdam=getGroup(id, 1, 5)]
    [CritMult=2]
    [id2 = strfind(wdam, "/[xX](\\d)")]
    [IF(0<getFindCount(id2)):CritMult=getGroup(id2, 1, 1)]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritMult", CritMult)+ "'")]
   
   <!-- CritRange-->
    [CritRange=20]
    [id2 = strfind(wdam, "/(1[0-9])")]
    [IF(0<getFindCount(id2)):CritRange=getGroup(id2, 1, 1)]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritRange", CritRange)+ "'")]
   
   <!-- Damage -->
    [Damage="0d4 plus" + wdam]
    [id2 = strfind(wdam, "(\\d+d\\d+)([^p]*)(plus .+)?")]
    [IF(0<getFindCount(id2)):Damage=getGroup(id2, 1, 1)+wbonus+" "+getGroup(id2, 1, 3)]
   
   [DmgBonus = number(getGroup(id2, 1, 2))]
   [DmgPlus = getGroup(id2, 1, 3)]
   [Damage123=replace(Damage, " ", "")]
   
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Damage", Damage)+ "'")]
   
   <!-- Two handed ? -->
    <!-- Default to onehanded weapon -->
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 0)+ "'")]

    [id2 = strfind(atkstr, "(?i)(longspear|quarterstaff| spear|falchion|glaive|greataxe|greatclub|greatsword|guisarme|halberd|lance|ranseur|scythe|spiked chain|elven curve blade|dire flail|two-bladed sword|urgrosh|hooked hammer)")]

    [IF(0<getFindCount(id2)):eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 1)+ "'")]
   [DmgBonus = round(if(0<getFindCount(id2), DmgBonus-Str2hB, DmgBonus-StrB))]

    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"DmgBonus", DmgBonus)+ "'")]

   [output = output +"Weapon DmgBonus?: " + DmgBonus + "<br>"]
   [output = output +"Weapon DmgPlus?: " + DmgPlus + "<br>"]
  }]
  [wpnno = wpnno +1]
}]

[H: output = output + "Weapons: " + wpnarray+"<br>"]

<!--
Name=Slam ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=0 ; Ranged=0  ;
ATTACKS END -->

<!-- Getting treasure from Ecology section. -->
[H: id = strfind(statblockOrig, "(?i)(?<=Treasure )(None|Standard|Double|Triple|Incidental|NPC gear)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [TreasureType=getGroup(id, 1, 0)]
  [output=output+"Treasure Type: "+TreasureType+"<br>"]
  }]

<!-- Setting Fast Healing if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Fast Healing )([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [FastHealing=getGroup(id, 1, 0)]
  [output=output+"Fast Healing: "+FastHealing+"<br>"]
  }]
 
<!-- Setting Regeneration if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Regeneration )([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Regeneration=getGroup(id, 1, 0)]
  [output=output+"Regeneration: "+Regeneration+"<br>"]
  }]

<!-- Setting Anti Regeneration damage type if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Regeneration )([0-9]+.+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [AntiRegen=getGroup(id, 1, 0)]
  [output=output+"Anti-Regen Damage Type: "+AntiRegen+"<br>"]
  }]

<!-- Statblock from HeroLab -->
[H: id = strfind(statblockOrig, "(?i)(Hero Lab logo are Registered Trademarks)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [HeroLab=1]
  [HideMeleeRange=1]
  [output=output+"Stat block generated from Hero Lab.<br>"]
  }]
 
[R,S,G: output]

[H: HP = HPmax ]
[H: HPNonLethalDMG = 0]
[H: tToken = currentToken() ]
[H, MACRO( "[email protected]:libDnD35Pathfinder" ): "Token=" + tToken]
[H: setState("Prone", 0)]
[H: setState("Unconscious", 0)]
[H: setLayer("TOKEN") ]
[/spoiler]
-Jamz
____________________
Custom MapTool 1.4.x.x Fork: maptool.nerps.net
Custom TokenTool 2.0 Fork: tokentool.nerps.net
More information here: MapTool Nerps! Fork

User avatar
JamzTheMan
Great Wyrm
Posts: 1872
Joined: Mon May 10, 2010 12:59 pm
Location: Chicagoland
Contact:

Re: PF statblock importer

Post by JamzTheMan »

Current token properties for Pathfinder:

[spoiler=Pathfinder Properties]

Code: Select all

[spoiler=Campaign Properties for Pathfinder]
Private:" ; "
PrivateJSON:{}
Race:{"name":"","family":"","type":"","subtype":[],"notes":""}
@CreatureType:[R:  json.get(Race, "type") + " " + json.toList(json.get(Race, "subtype"))]
SizeM:0
Level:1
Levels:TurnLevel=0 ; ECL=Level ;
@LevelsInfo (Level/CR):[R: Level] | [R: eval( "" + getStrProp(getProperty("Levels"), "ECL") ) ]
@Languages:[R: json.get(getProperty("Race"), "notes")]
@HP:0
@HPmax:[R: max( Level, ( 1 + (ConB * Level) ) )]
@HPtemp:0
@HPNonLethalDMG:0
IsBloodied (Is Bloodied):[r:if(HP/HPmax < 0.5, "YES!", "")]
BAB:0
CMBMod:0
CMDMod:0
#Reach:5
MiscATK:0
MiscDMG:0
---| Daily Uses |---
ChannelEnergy:0
HealingSurges:0
Daily:ChannelEnergy=0 ; HealingSurges=0 ; NegativeLevels=0 ;
---| Informational Text |---
InitMod:0
@Movement:[R: json.get(getProperty("Speed"), "base") + json.get(getProperty("SpeedMod"), "base")]
Speed:{"base" : 30,"climb" : 0,"swim" : 0,"burrow" : 0,"fly" : 0,"flymaneuver" : 0,"encumbered" : 0,"special" : ""}
SpeedMod:{"base" : 0,"climb" : 0,"swim" : 0,"burrow" : 0,"fly" : 0,"flymaneuver" : 0,"encumbered" : 0,"special" : ""}
@MoveRemain
MoveActive:base
Elevation (Elv)
AC (AC/TH/FF/CMD/CMDFF)
ArmorClass:Armor=0 ; ArmorMod=0 ; Shield=0 ; ShieldMod=0 ; ArmorACP=0 ; ShieldACP=0 ; MaxDex=50 ; Natural=0 ; NaturalMod=0 ; Deflection=0 ; Dodge=0 ; ACMod=0 ; Description= ;
@SpecialATK:NA
@SpecialQual:NA
@SpecialDefense:NA
@DR
DRER:{"Damage Reduction":{"All":0,"Adamantine":0,"ColdIron":0,"Epic":0,"Magic":0,"Silver":0,"Bludgeoning":0,"Piercing":0,"Slashing":0,"Chaos":0,"Evil":0,"Good":0,"Law":0,"Vorpal":0,"Wood":0,"Lethal":0,"NonMagic":0,"Note":""},"Energy Resistance":{"Acid":0,"Cold":0,"Electricity":0,"Fire":0,"Sonic":0,"Note":""}}
DRERMod:{"DR_All":0,"DR_Adamantine":0,"DR_ColdIron":0,"DR_Epic":0,"DR_Magic":0,"DR_Silver":0,"DR_Bludgeoning":0,"DR_Piercing":0,"DR_Slashing":0,"DR_Chaos":0,"DR_Evil":0,"DR_Good":0,"DR_Law":0,"ER_Acid":0,"ER_Cold":0,"ER_Electricity":0,"ER_Fire":0,"ER_Sonic":0}
@Immune
BonusTypedItems:{}
ItemSlots:{}
---| Stats/Saves |---
Strength (Str):10
StrMod:0
Dexterity (Dex):10
DexMod:0
Constitution (Con):10
ConMod:0
Intelligence (Int):10
IntMod:0
Wisdom (Wis):10
WisMod:0
Charisma (Cha):10
ChaMod:0
StatCheckMod:{"StrengthCheckMod":0,"DexterityCheckMod":0,"ConstitutionCheckMod":0,"IntelligenceCheckMod":0,"WisdomCheckMod":0,"CharismaCheckMod":0}
Fort:0
FortBonus:0
Reflex:0
ReflexBonus:0
Will:0
WillBonus:0
---| Skills and Feats |---
SkillsJ:[{"name":"Acrobatics","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Appraise","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Bluff","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Climb","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Craft","subcat":"99","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0},{"name":"Diplomacy","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Disable Device","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Disguise","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Escape Artist","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Fly","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Handle Animal","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Heal","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Intimidate","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Knowledge","subcat":"99","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0},{"name":"Linguistics","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Perception","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Perform","subcat":"99","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0},{"name":"Profession","subcat":"99","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0},{"name":"Ride","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Sense Motive","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Sleight of Hand","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Spellcraft","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Stealth","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Survival","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Swim","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Use Magic Device","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""}]
Skills:Acrobatics=0 ; Appraise=0 ; Bluff=0 ; Climb=0 ; Diplomacy=0 ; DisableDevice=0 ; Disguise=0 ; EscapeArtist=0 ; Fly=0 ; HandleAnimal=0 ; Heal=0 ; Intimidate=0 ; KnowledgeArcana=0 ; KnowledgeDungeoneering=0 ; KnowledgeEngineering=0 ; KnowledgeGeography=0 ; KnowledgeHistory=0 ; KnowledgeLocal=0 ; KnowledgeNature=0 ; KnowledgeNobility=0 ; KnowledgePlanes=0 ; KnowledgeReligion=0 ; Linguistics=0 ; Perception=0 ; Perform=0 ; Ride=0 ; SenseMotive=0 ; SleightOfHand=0 ; Spellcraft=0 ; Stealth=0 ; Survival=0 ; Swim=0 ; UseMagicDevice=0 ;
SkillStat:Acrobatics=DexB ; Appraise=IntB ; Bluff=ChaB ; Climb=StrB ; Diplomacy=ChaB ; DisableDevice=DexB ; Disguise=ChaB ; EscapeArtist=DexB ; Fly=DexB ; HandleAnimal=ChaB ; Heal=WisB ; Intimidate=ChaB ; KnowledgeArcana=IntB ; KnowledgeDungeoneering=IntB ; KnowledgeEngineering=IntB ; KnowledgeGeography=IntB ; KnowledgeHistory=IntB ; KnowledgeLocal=IntB ; KnowledgeNature=IntB ; KnowledgeNobility=IntB ; KnowledgePlanes=IntB ; KnowledgeReligion=IntB ; Linguistics=IntB ; Perception=WisB ; Perform=ChaB ; Ride=DexB ; SenseMotive=WisB ; SleightOfHand=DexB ; Spellcraft=IntB ; Stealth=DexB ; Survival=WisB ; Swim=StrB ; UseMagicDevice=ChaB ;
SkillArmor:Acrobatics=1 ; Appraise=0 ; Bluff=0 ; Climb=1 ; Diplomacy=0 ; DisableDevice=0 ; Disguise=0 ; EscapeArtist=1 ; Fly=1 ; HandleAnimal=0 ; Heal=0 ; Intimidate=0 ; KnowledgeArcana=0 ; KnowledgeDungeoneering=0 ; KnowledgeEngineering=0 ; KnowledgeGeography=0 ; KnowledgeHistory=0 ; KnowledgeLocal=0 ; KnowledgeNature=0 ; KnowledgeNobility=0 ; KnowledgePlanes=0 ; KnowledgeReligion=0 ; Linguistics=0 ; Perception=0 ; Perform=0 ; Ride=0 ; SenseMotive=0 ; SleightOfHand=1 ; Spellcraft=0 ; Stealth=1 ; Survival=0 ; Swim=1 ; UseMagicDevice=0 ;
ArmorCheckPenalty:0
SkillMisc:0
Feats:ImprovedInitiative=0 ; AgileManeuvers=0 ; ImprovedBullRush=0 ; ImprovedDisarm=0 ; ImprovedGrapple=0 ; ImprovedOverrun=0 ; ImprovedSunder=0 ; ImprovedTrip=0 ; PointBlankShot=0 ; ManyShot=0 ; TwoWeaponFighting=0 ; ImprovedTwoWeaponFighting=0 ; GreaterTwoWeaponFighting=0 ; MultiAttack=0 ; WeaponFinesse=0 ; CriticalFocus=0 ; UncannyDodge=0 ; ImprovedTurning=0 ; VitalStrike=0 ; ImprovedVitalStrike = 0 ; GreaterVitalStrike = 0 ;
---| Weapons |---
Weapon0:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon1:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon2:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon3:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon4:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon5:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon6:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon7:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon8:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon9:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon10:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon11:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon12:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon13:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon14:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon15:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon16:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon17:Name=Slam ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon18:Name=Touch ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=0d1 ; DmgMax=0 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=0 ; TwoHanded=0 ; Finesse=1 ; OHLight=2 ; Ranged=0 ;
Weapon19:Name=Ranged Touch ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=0d1 ; DmgMax=0 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=0 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=1 ;
HelpWeaponProperty:Primary=0-NotInUse 1-Primary 2-Secondary ; Quantity= # natural attacks ; Manufactured= 0-Natural 1-Manufactured (for multi attack if BAB>5) ; AtkBonus= Magic/Masterwork/Feat ; DmgBonus=Adjust str damage ; CritRange= Lower end 19-20 is 19 ; DmgExtra= 1d6 (EX from flaming) set to 0d6 for none ; DmgExtraCrit= 1d10 (EX burst) set to 0d10 for none; DmgExtraName= Fire / Cold / Acid / etc. ; DmgBonusCap=0-No STR Bonus, >0 - Cap to STR bonus (STR Bow) ; TwoHanded=0-One  Handed, 1-Two Handed ; Finesse=0-Not Finessable, 1-Finessable ; OHLight=0-Offhand heavy, 1-Offhand Light, 2-Not  Multi-attack
---| Calculated |---
StrB:[R: floor((Strength+StrMod-10)/2)]
Str2hB:[R: floor(floor((Strength+StrMod-10)/2)+(max(0,floor((Strength+StrMod-10)/4))))]
StrSecB:[R: floor((Strength+StrMod-10)/4)]
DexB:[R: floor((Dexterity+DexMod-10)/2)]
ConB:[R: floor((Constitution+ConMod-10)/2)]
IntB:[R: floor((Intelligence+IntMod-10)/2)]
WisB:[R: floor((Wisdom+WisMod-10)/2)]
ChaB:[R: floor((Charisma+ChaMod-10)/2)]
---| Wrathgon |---
CasterBackup:{}
SAGroup:{}
MasterEH:{}
PCFeats:[]
---| Wrathgon And Plothos |---
CasterInfo:{}
SpecAbils:{}
SACats
---| Plothos |---
CI_SpecAbils:{}
CISA_Groups:{}
SAGroups:{}
AMSL:0
BMSL:0
BGMSL:0
CMSL:0
DMSL:0
PMSL:0
RMSL:0
SMSL:0
WMSL:0
ACL:0
BCL:0
BGCL:0
CCL:0
DCL:0
PCL:0
RCL:0
SCL:0
WCL:0
APL:0
BpL:0
BGPL:0
CPL:0
DPL:0
PPL:0
RPL:0
SPL:0
WPL:0
IsCaster:0
FirstDomain:(None)
SecondDomain:(None)
Cleric_Good_or_Evil:Good
SchoolSpec:(None)
ProhibSchool1:(None)
ProhibSchool2:(None)
ObjectBond:0
Bloodline:(None)
AssassinSPD:1=0;2=0;3=0;4=0
AssassinSpellsLeft:1=0;2=0;3=0;4=0
Assassin1:(None)
Assassin2:(None)
Assassin3:(None)
Assassin4:(None)
BardSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0
BardSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0
Bard0:(None)
Bard1:(None)
Bard2:(None)
Bard3:(None)
Bard4:(None)
Bard5:(None)
Bard6:(None)
BlackguardSPD:1=0;2=0;3=0;4=0
BlackguardSpellsLeft:1=0;2=0;3=0;4=0
BlackguardPrep:1=(None);2=(None);3=(None);4=(None)
Blackguard1:(None)
Blackguard2:(None)
Blackguard3:(None)
Blackguard4:(None)
ClericSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
ClericSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
ClericDomsPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
ClericDomsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
ClericDomainPowers:(None)
ClericPrep:0=(None);1=(None);2=(None);3=(None);4=(None);5=(None);6=(None);7=(None);8=(None);9=(None);
Cleric0:(None)
Cleric1:(None)
Domain1:(None)
Domain1Prepped:(None)
Cleric2:(None)
Domain2:(None)
Domain2Prepped:(None)
Cleric3:(None)
Domain3:(None)
Domain3Prepped:(None)
Cleric4:(None)
Domain4:(None)
Domain4Prepped:(None)
Cleric5:(None)
Domain5:(None)
Domain5Prepped:(None)
Cleric6:(None)
Domain6:(None)
Domain6Prepped:(None)
Cleric7:(None)
Domain7:(None)
Domain7Prepped:(None)
Cleric8:(None)
Domain8:(None)
Domain8Prepped:(None)
Cleric9:(None)
Domain9:(None)
Domain9Prepped:(None)
DruidSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
DruidSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
DruidPrep:0=(None);1=(None);2=(None);3=(None);4=(None);5=(None);6=(None);7=(None);8=(None);9=(None);
Druid0:(None)
Druid1:(None)
Druid2:(None)
Druid3:(None)
Druid4:(None)
Druid5:(None)
Druid6:(None)
Druid7:(None)
Druid8:(None)
Druid9:(None)
PaladinSPD:1=0;2=0;3=0;4=0
PaladinSpellsLeft:1=0;2=0;3=0;4=0
PaladinPrep:1=(None);2=(None);3=(None);4=(None)
Paladin1:(None)
Paladin2:(None)
Paladin3:(None)
Paladin4:(None)
RangerSPD:1=0;2=0;3=0;4=0
RangerSpellsLeft:1=0;2=0;3=0;4=0
RangerPrep:1=(None);2=(None);3=(None);4=(None)
Ranger1:(None)
Ranger2:(None)
Ranger3:(None)
Ranger4:(None)
SorcererSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
SorcererSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0;
Sorcerer0:(None)
Sorcerer1:(None)
Sorcerer2:(None)
Sorcerer3:(None)
Sorcerer4:(None)
Sorcerer5:(None)
Sorcerer6:(None)
Sorcerer7:(None)
Sorcerer8:(None)
Sorcerer9:(None)
BloodlinePowers:(None)
WizardSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
WizardSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
WizardSpecsPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
WizardSpecsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
WizardBondPD:0
WizardBondLeft:0
WizardPowers:(None)
WizardPrep:0=(None);1=(None);2=(None);3=(None);4=(None);5=(None);6=(None);7=(None);8=(None);9=(None);
Wizard0:(None)
Wizard1:(None)
Wizard2:(None)
Wizard3:(None)
Wizard4:(None)
Wizard5:(None)
Wizard6:(None)
Wizard7:(None)
Wizard8:(None)
Wizard9:(None)
Template
am.spellManager
---| Nerps Custom Properties |---
Nerps_Wiki (Wiki)
HeroLab:0
HideMeleeRange:0
OriginalMeleeLine
OriginalRangedLine
XP:0
NewXP:0
XPadvancmentPace:1
NextLevelXP:[r: json.get(json.get(XPAdv, XPadvancmentPace), (Level  - 1))]
XPAdv:[[1300, 3300, 6000, 10000, 15000, 23000, 34000, 50000, 71000, 105000, 145000, 210000, 295000, 425000, 600000, 850000, 1200000, 1700000, 2400000], [2000, 5000, 9000, 15000, 23000, 35000, 51000, 75000, 105000, 155000, 220000, 315000, 445000, 635000, 890000, 1300000, 1800000, 2550000, 3600000], [3000, 7500, 14000, 23000, 35000, 53000, 77000, 115000, 160000, 235000, 330000, 475000, 665000, 955000, 1350000, 1900000, 2700000, 3850000, 5350000]]
HitDice
HPavg
---| Nerps Alt Statsheet Output |---
newStr:1
Regeneration
AntiRegen
*#DisplayCreatureType (Creature Type):[R: CreatureType]
*@DisplayLevelsInfo (Level/CR):[R: LevelsInfo]
*#DisplayLanguages (Languages):[R: Languages]
*#DisplayPerception (Perception):[R: getStrProp(Skills, "Perception")]
*#DisplayInitMod (Initiative):[R: InitMod]
*#DisplayHitDice (Hit Dice):{HitDice}
*#DisplayHitPoints (Hit Points):[R: HP + HPtemp + " (" + HPmax][r:if(HPtemp>0, "+"+HPtemp+")", ")")][r:if(HP<0, " [-"+(Constitution+ConMod)+" max]", "")]
*#DisplayHPNonLethalDMG (Non-Lethal Damage):[r:if(HPNonLethalDMG!=0, HPNonLethalDMG, "")]
*#FastHealing (Fast Healing)
*#DisplayRegeneration (Regeneration):[R: AntiRegen]
*#DisplayBaseAttack (BAB/CMB):[R: BAB]/[R: CMBMod]
*#DisplayReach (Reach):[R: Reach]
*#DisplayMiscATK (Misc Attack Bonus):[r:if(MiscATK!=0, MiscATK, "")]
*#DisplayMiscDMG (Misc Damage Bonus):[r:if(MiscDMG!=0, MiscDMG, "")]
*#DisplayMovement (Movement):[R: Movement]
*#DisplayMoveRemain (Move Remaining):[R: MoveRemain]
*#DisplayAC (AC/Touch/FF/CMD/CMDFF):[R: AC]
*#AllStats (Str,Dex,Con,Int,Wis,Cha):[R: Strength+StrMod],[R:Dexterity+DexMod],[R:Constitution+ConMod],[R:Intelligence+IntMod],[R:Wisdom+WisMod],[R:Charisma+ChaMod]
*#AllSaves (Fortitude, Reflex, Will):[R:Fort+ConB+FortBonus], [R:Reflex+DexB+ReflexBonus], [R:Will+WisB+WillBonus]
*#SaveMisc
*#DisplaySpecialDefense (Special Defense):[r:if(SpecialDefense != "NA", SpecialDefense, "")]
*#DisplaySpecialATK (Special Attacks):[r:if(SpecialATK != "NA", SpecialATK, "")]
*#DisplaySpecialQual (Special Qualities):[r:if(SpecialQual != "NA", SpecialQual, "")]
*#DisplayDR (DR):{DR}
*#DisplayImmune (Immunities):{Immune}
*#DisplayMelee (Melee):[r: if(HideMeleeRange == 1, "", OriginalMeleeLine)]
*#DisplayRanged (Ranged):[r: if(HideMeleeRange == 1, "", OriginalRangedLine)]
*#DisplayFeats (Combat Feats):[R: "" + if(getStrProp(Feats, "AgileManeuvers")==1, " [AM]", "") + if(getStrProp(Feats, "ImprovedBullRush")==1, " [IBR]", "") + if(getStrProp(Feats, "ImprovedDisarm")==1, " [ID]", "") + if(getStrProp(Feats, "ImprovedGrapple")==1, " [IG]", "") + if(getStrProp(Feats, "ImprovedOverrun")==1, " [IO]", "") + if(getStrProp(Feats, "ImprovedSunder")==1, " [IS]", "") + if(getStrProp(Feats, "ImprovedTrip")==1, " [IT]", "") + if(getStrProp(Feats, "PointBlankShot")==1, " [PBS]", "") + if(getStrProp(Feats, "ManyShot")==1, " [MS]", "") + if(getStrProp(Feats, "TwoWeaponFighting")==1, " [TWF]", "") + if(getStrProp(Feats, "ImprovedTwoWeaponFighting")==1, " [ITWF]", "") + if(getStrProp(Feats, "GreaterTwoWeaponFighting")==1, " [GTWF]", "") + if(getStrProp(Feats, "MultiAttack")==1, " [MA]", "") + if(getStrProp(Feats, "PowerAttack")==1, " [PA]", "") + if(getStrProp(Feats, "UncannyDodge")==1, " [UD]", "") + if(getStrProp(Feats, "WeaponFinesse")==1, " [WF]", "") + if(getStrProp(Feats, "ImprovedTurning")==1, " [ITurn]", "") + if(getStrProp(Feats, "CriticalFocus")==1, " [CF]", "") + if(getStrProp(Feats, "VitalStrike")==1, " [VS]", "") + if(getStrProp(Feats, "ImprovedVitalStrike")==1, " [IVS]", "") + if(getStrProp(Feats, "GreaterVitalStrike")==1, " [GVS]", "") + if(getStrProp(Feats, "ImprovedChanneling")==1, " [IC]", "") + if(getStrProp(Feats, "DieHard")==1, " [DH]", "")]
*#Attack #1:[R: if(getStrProp(Weapon0, "Name") == "NA", "", if(getStrProp(Weapon0, "Quantity") > 1, getStrProp(Weapon0, "Quantity") + " ", "") + getStrProp(Weapon0, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon0, "AtkBonus") + if(getStrProp(Weapon0, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon0, "Damage") + strformat("%+d", (if(getStrProp(Weapon0, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon0, "DmgBonus", 0))) + " / " + getStrProp(Weapon0, "CritRange") + "x" + getStrProp(Weapon0, "CritMult") + ")")]
*#Attack #2:[R: if(getStrProp(Weapon1, "Name") == "NA", "", if(getStrProp(Weapon1, "Quantity") > 1, getStrProp(Weapon1, "Quantity") + " ", "") + getStrProp(Weapon1, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon1, "AtkBonus") + if(getStrProp(Weapon1, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon1, "Damage") + strformat("%+d", (if(getStrProp(Weapon1, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon1, "DmgBonus", 0))) + " / " + getStrProp(Weapon1, "CritRange") + "x" + getStrProp(Weapon1, "CritMult") + ")")]
*#Attack #3:[R: if(getStrProp(Weapon2, "Name") == "NA", "", if(getStrProp(Weapon2, "Quantity") > 1, getStrProp(Weapon2, "Quantity") + " ", "") + getStrProp(Weapon2, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon2, "AtkBonus") + if(getStrProp(Weapon2, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon2, "Damage") + strformat("%+d", (if(getStrProp(Weapon2, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon2, "DmgBonus", 0))) + " / " + getStrProp(Weapon2, "CritRange") + "x" + getStrProp(Weapon2, "CritMult") + ")")]
*#Attack #4:[R: if(getStrProp(Weapon3, "Name") == "NA", "", if(getStrProp(Weapon3, "Quantity") > 1, getStrProp(Weapon3, "Quantity") + " ", "") + getStrProp(Weapon3, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon3, "AtkBonus") + if(getStrProp(Weapon3, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon3, "Damage") + strformat("%+d", (if(getStrProp(Weapon3, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon3, "DmgBonus", 0))) + " / " + getStrProp(Weapon3, "CritRange") + "x" + getStrProp(Weapon3, "CritMult") + ")")]
*#Attack #5:[R: if(getStrProp(Weapon4, "Name") == "NA", "", if(getStrProp(Weapon4, "Quantity") > 1, getStrProp(Weapon4, "Quantity") + " ", "") + getStrProp(Weapon4, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon4, "AtkBonus") + if(getStrProp(Weapon4, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon4, "Damage") + strformat("%+d", (if(getStrProp(Weapon4, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon4, "DmgBonus", 0))) + " / " + getStrProp(Weapon4, "CritRange") + "x" + getStrProp(Weapon4, "CritMult") + ")")]
*#Attack #6:[R: if(getStrProp(Weapon5, "Name") == "NA", "", if(getStrProp(Weapon5, "Quantity") > 1, getStrProp(Weapon5, "Quantity") + " ", "") + getStrProp(Weapon5, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon5, "AtkBonus") + if(getStrProp(Weapon5, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon5, "Damage") + strformat("%+d", (if(getStrProp(Weapon5, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon5, "DmgBonus", 0))) + " / " + getStrProp(Weapon5, "CritRange") + "x" + getStrProp(Weapon5, "CritMult") + ")")]
*#Attack #7:[R: if(getStrProp(Weapon6, "Name") == "NA", "", if(getStrProp(Weapon6, "Quantity") > 1, getStrProp(Weapon6, "Quantity") + " ", "") + getStrProp(Weapon6, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon6, "AtkBonus") + if(getStrProp(Weapon6, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon6, "Damage") + strformat("%+d", (if(getStrProp(Weapon6, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon6, "DmgBonus", 0))) + " / " + getStrProp(Weapon6, "CritRange") + "x" + getStrProp(Weapon6, "CritMult") + ")")]
*#Attack #8:[R: if(getStrProp(Weapon7, "Name") == "NA", "", if(getStrProp(Weapon7, "Quantity") > 1, getStrProp(Weapon7, "Quantity") + " ", "") + getStrProp(Weapon7, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon7, "AtkBonus") + if(getStrProp(Weapon7, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon7, "Damage") + strformat("%+d", (if(getStrProp(Weapon7, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon7, "DmgBonus", 0))) + " / " + getStrProp(Weapon7, "CritRange") + "x" + getStrProp(Weapon7, "CritMult") + ")")]
*#Attack #9:[R: if(getStrProp(Weapon8, "Name") == "NA", "", if(getStrProp(Weapon8, "Quantity") > 1, getStrProp(Weapon8, "Quantity") + " ", "") + getStrProp(Weapon8, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon8, "AtkBonus") + if(getStrProp(Weapon8, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon8, "Damage") + strformat("%+d", (if(getStrProp(Weapon8, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon8, "DmgBonus", 0))) + " / " + getStrProp(Weapon8, "CritRange") + "x" + getStrProp(Weapon8, "CritMult") + ")")]
*#Touch/Ranged Touch:[R: strformat("%+d", (BAB + getStrProp(Weapon9, "AtkBonus") + StrB + SizeM)) + " / " + strformat("%+d", (BAB + getStrProp(Weapon9, "AtkBonus") + DexB + SizeM))]
*#TreasureType (Treasure)
*#Nerps_Treasure (Additional Treasure)
*@DisplayXP (Current XP):[r: if(XP > 0 && isPC(), XP + if(NewXP > 0, " (+" + NewXP + ")", "") + " / " + NextLevelXP,"")]
*#Test:[R: if(getStrProp(Weapon8, "Name") == "NA", "WTF", if(getStrProp(Weapon8, "Quantity") > 1, getStrProp(Weapon8, "Quantity") + " ", "") + getStrProp(Weapon8, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon8, "AtkBonus") + if(getStrProp(Weapon8, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon8, "Damage") + strformat("%+d", (if(getStrProp(Weapon8, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon8, "DmgBonus", 0))) + " / " + getStrProp(Weapon8, "CritRange") + "x" + getStrProp(Weapon8, "CritMult") + ")")]
[/spoiler]
[/spoiler]
-Jamz
____________________
Custom MapTool 1.4.x.x Fork: maptool.nerps.net
Custom TokenTool 2.0 Fork: tokentool.nerps.net
More information here: MapTool Nerps! Fork

neofax
Great Wyrm
Posts: 1694
Joined: Tue May 26, 2009 8:51 pm
Location: Philadelphia, PA
Contact:

Re: PF statblock importer

Post by neofax »

I am assuming you are using a older version of Lindsays FW as the DRER and DRERMod properties are different as he added SR and Vulnerabilites to his. This is where the code chokes for me with the previous error. Here is what it looks like:

Code: Select all

DRER:{"Damage Reduction":{"All":0, "Adamantine":0, "ColdIron":0, "Epic":0, "Magic":0, "Silver":0, "Bludgeoning":0, "Piercing":0, "Slashing":0, "Chaos":0, "Evil":0, "Good":0, "Law":0, "Note":""}, "Energy Resistance":{"Acid":0, "Cold":0, "Electricity":0, "Fire":0, "Sonic":0, "Note":""}, "Energy Vulnerability":{"V.Acid":0, "V.Cold":0, "V.Electricity":0, "V.Fire":0, "V.Sonic":0, "Note":""}, "Spell Resistance":{"SR":0, "Note":""}}
DRERMod:{"DR_All":0, "DR_Adamantine":0, "DR_ColdIron":0, "DR_Epic":0, "DR_Magic":0, "DR_Silver":0, "DR_Bludgeoning":0, "DR_Piercing":0, "DR_Slashing":0, "DR_Chaos":0, "DR_Evil":0, "DR_Good":0, "DR_Law":0, "DP_P.All":0, "DP_P.Adamantine":0, "DP_P.ColdIron":0, "DP_P.Epic":0, "DP_P.Magic":0, "DP_P.Silver":0, "DP_P.Bludgeoning":0, "DP_P.Piercing":0, "DP_P.Slashing":0, "DP_P.Chaos":0, "DP_P.Evil":0, "DP_P.Good":0, "DP_P.Law":0, "ER_Acid":0, "ER_Cold":0, "ER_Electricity":0, "ER_Fire":0, "ER_Sonic":0, "EP_P.Acid":0, "EP_P.Cold":0, "EP_P.Electricity":0, "EP_P.Fire":0, "EP_P.Sonic":0, "EV_V.Acid":0, "EV_V.Cold":0, "EV_V.Electricity":0, "EV_V.Fire":0, "EV_V.Sonic":0, "SR_SR":0}
Image
Time-Zone information UTC -5

User avatar
JamzTheMan
Great Wyrm
Posts: 1872
Joined: Mon May 10, 2010 12:59 pm
Location: Chicagoland
Contact:

Re: PF statblock importer

Post by JamzTheMan »

Hmmm, ya, i'm on b86.03, kind of a pain to update the framework once you start modifying things. I wish it was as easy as Wolf's Bag of Tricks :(
-Jamz
____________________
Custom MapTool 1.4.x.x Fork: maptool.nerps.net
Custom TokenTool 2.0 Fork: tokentool.nerps.net
More information here: MapTool Nerps! Fork

neofax
Great Wyrm
Posts: 1694
Joined: Tue May 26, 2009 8:51 pm
Location: Philadelphia, PA
Contact:

Re: PF statblock importer

Post by neofax »

JamzTheMan wrote:Hmmm, ya, i'm on b86.03, kind of a pain to update the framework once you start modifying things. I wish it was as easy as Wolf's Bag of Tricks :(

Just put all of your code on a Lib:Token and make calls from a html frame and then your updates are easy to export for others or for yourself. No problem, I will try to fix it to work with the newest version.
Image
Time-Zone information UTC -5

User avatar
JamzTheMan
Great Wyrm
Posts: 1872
Joined: Mon May 10, 2010 12:59 pm
Location: Chicagoland
Contact:

Re: PF statblock importer

Post by JamzTheMan »

Ya, but i have had to make changes to macros in the current framework, including those in lib tokens. As well as new property types and such. For new stand alone macros, i can migrate those easy enough.

Times like these i wish framework coding were external files not tied to campaign files and could be easily shared via git or some such. Then we could simply "patch" things :)

Also i was able to break my code by adding the new json values but for the life of me couldnt figure out why. It was throwing an error on the json command in the for each.
-Jamz
____________________
Custom MapTool 1.4.x.x Fork: maptool.nerps.net
Custom TokenTool 2.0 Fork: tokentool.nerps.net
More information here: MapTool Nerps! Fork

neofax
Great Wyrm
Posts: 1694
Joined: Tue May 26, 2009 8:51 pm
Location: Philadelphia, PA
Contact:

Re: PF statblock importer

Post by neofax »

You could use git with Aliasmask's macro editor. Just export the macro, make changes and load to git, then reimport to the macro. Or see if Lindsay will incorporate your changes into his FW.

As for the new JSON, would you like me to add the code for it here? I should be able to find it easily enough.
Image
Time-Zone information UTC -5

User avatar
JamzTheMan
Great Wyrm
Posts: 1872
Joined: Mon May 10, 2010 12:59 pm
Location: Chicagoland
Contact:

Re: PF statblock importer

Post by JamzTheMan »

Ok, here's my latest version. It now works with the new ER/DR info (although I'm not filling in the new weakness & sr values yet).

I've got the weapons working much better (for my statsheet at least). Add Defensive Abilities, immunities, weaknessess (ie light sensitivity), and first line of spell like abilities (more of a reminder to me that he has them).

Let me if it still chokes and if so where.

[spoiler=PF Statblock2Token 2.2]

Code: Select all

<!-- Statblock2Token v2.2
Jamz: Now paste formatted text into GM text (which stays formatted) and handles CR now.
Jamz: Added Fast-Healing, Regeneration, Treasure type, adjusted Weapons to be Hero Labs friendly
Jamz: Added DR/ER, updated weapons adding dmgbonus calc

Changes: HD fixed, Resets token, Skills with space in the name except SleightOfHand
Macro takes a Pathfinder statblock as input and updates selected token with various stats.
Macro assumes pathfinder properties in the selected token.
Statblock format should mirror PF bestiary format.
Not handled: SQ, Spells
-->
[H: ids = getSelected()]
[H: abort(if(ids == "", 0, 1))]

<!-- Lets keep nice formated text in GMNotes and paste there first manually and then retrieve it from there
   H: status=input("statblock|Insert statblock here|Enter statblock|TEXT|WIDTH=40")
   H: abort(if(status < 1, 0, 1))
   H: setGMNotes(statblock)
-->

[H: setPropertyType("Pathfinder")]

<!--Lets keep my custom Nerps properties if already populated-->
[H: Nerps_WikiTemp=getProperty("Nerps_Wiki")]
[H: Nerps_TreasureTemp=getProperty("Nerps_Treasure")]
[H: XPTemp=getProperty("XP")]
[H: NewXPTemp=getProperty("NewXP")]
[H: XPadvancmentPaceTemp=getProperty("XPadvancmentPace")]

[H: propnames = getPropertyNames()]
[H, foreach(propname,propnames),CODE:
  {
  [resetProperty(propname)]
  }]

[H: setProperty("Nerps_Wiki", Nerps_WikiTemp)]
[H: setProperty("Nerps_Treasure", Nerps_TreasureTemp)]
[H: setProperty("XP", XPTemp)]
[H: setProperty("NewXP", NewXPTemp)]
[H: setProperty("XPadvancmentPace", XPadvancmentPaceTemp)]

<!-- Lets clean up those pesky non-ascii characters! -->
[H: statblock = getGMNotes()]
[H: statblock = replace(statblock, "\\xD7", "x")]
[H: statblock = replace(statblock, "\\u2013", "-")]
[H: statblock = replace(statblock, "&#151;", "-")]
[H: statblock = replace(statblock, "%E2%80%93", "-")]
[H: statblock = replace(statblock, "Ecolo gy", "Ecology")]

[H: setGMNotes(statblock)]
[H: statblockOrig = statblock]
[H: statblock = replace(statblock, "\\n", " ")]

[H: output="Token Updated:<br>"]
[H: id = strfind(statblock, "^(.+).*CR ")]
[H, IF(0<getFindCount(id)),CODE: {
  [currentName = getName()]
  [newName=trim(getGroup(id, 1, 1))]
  [n1 = upper(currentName)]
  [n2 = upper(newName)]
  [if(n1 == n2): newName = currentName)]
  [setName(newName)]
  [setGMName(newName)]
  [Race = json.set(Race, "name", newName)]
  [output=output+"Name: "+newName+", "]
}]

<!-- Setting ECL to CR from statblock. For CR 1/3 & 1/6 we will set it to .338 & .1625 so XP calcs correctly. -->
[H: id = strfind(statblockOrig, "(?<=[ |\\t]CR )([0-9]+)(/[0-9]+)?")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [ECL=trim(getGroup(id, 1, 0))]
  [output=output+"CR: "+ECL+", "]
  [IF(ECL == "1/3"),CODE:{
    [ECL=".338"]
  }]
  [IF(ECL == "1/6"),CODE:{
    [ECL=".1625"]
  }]
  [Levels = setStrProp(Levels, "ECL", ECL)]
  }]


<!-- Getting Perception. -->
[H: id = strfind(statblockOrig, "(?<=Perception )(.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Perception=trim(getGroup(id, 1, 0))]
  [output=output+"Perception: "+Perception+", "]
  [Skills = setStrProp(Skills, "Perception", Perception)]
  }]
 
<!-- Find Size --> 
[H: id = strfind(statblock, "(Fine|Diminutive|Tiny|Small|Medium|Large|Huge|Gargantuan|Colossal).([a-zA-Z]+\\s?[a-zA-Z]*?)\\s?(\\((.+)\\))?.?Init")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Size_txt=getGroup(id, 1, 1)]
  [setSize(Size_txt)]
  [sizeList = table( "SysVars", json.get( table( "SysVars", 0 ), "sizeList" ) ) ]
  [sizeModList = "8,4,2,1,0,-1,-2,-4,-8"]
  [Size=listFind(sizeList, Size_txt)]
  [SizeM = listGet(sizeModList, Size)]
  [type=upper(substring(getGroup(id, 1, 2),0,1))+substring(getGroup(id, 1, 2),1)]
  [Race =  json.set(Race, "type", type)]
  [subtypes=getGroup(id, 1, 4)]
  [output=output+"Size: "+Size_txt+", type: "+type+", subtypes: "+subtypes+"<br>"]
  [subtypes="['"+replace(subtypes,", *","','")+"']"]
  [Race =  json.set(Race, "subtype",subtypes)]
  }]

<!-- Find Initiative --> 
[H: id = strfind(statblock, "Init ([+-][0-9]+);")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [InitMod=getGroup(id, 1, 1)]
  [output=output+"Init: "+InitMod+", "]
  }]

<!-- Find Senses --> 
[H: id = strfind(statblock, "Senses ([lL]ow-?light|[dD]arkvision)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [sighttype=upper(substring(getGroup(id, 1, 1),0,1))+substring(getGroup(id, 1, 1),1)]
  [sighttype=replace(sighttype, "-", "")]
  [setSightType(sighttype)]
  [setHasSight(1)]
  [output=output+"Sighttype: "+sighttype+", "]
  }]

<!-- Find Reach -->
[H: id = strfind(statblock, "Reach ([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Reach=getGroup(id, 1, 1)]
  [output=output+"Reach: "+Reach+", "]
  }]

<!-- Defensive Abilities Sample: Defensive Abilities incorporeal, channel resistance +2; -->
[H: id = strfind(statblockOrig, "(?i)(?<=\\bDefensive Abilities\\b )([a-zA-Z +-,]+\\d?)")]
[H, IF(0<getFindCount(id)),CODE: {
  [SpecialDefense=getGroup(id, 1, 1)]
  [output=output+"Defensive Abilities: "+getFindCount(id)+", "]
}]

<!-- Find Immunities. Sample: Immune acid, curse effects, flanking, mind-affecting effects, paralysis, poison, sleep -->
[H: id = strfind(statblockOrig, "\\bImmune \\b((\\w+-?,? ?)+)")]
[H, IF(0<getFindCount(id)),CODE: {
  [Immune = trim(getGroup(id, 1, 1)))]
  [output=output+"Immunities: "+Immune+", "]
}]

<!-- Find Weaknesses. Sample: Weaknesses light sensitivity -->
[H: id = strfind(statblock, "(?i)(?<=Weaknesse?s? )((\\w+-?,? ?)+)")]
[H, IF(0<getFindCount(id)),CODE: {
  [Weaknesses = trim(getGroup(id, 1, 1)))]
  [output=output+"Weaknesses: "+Weaknesses+", "]
}]

<!-- Find Spell Like Abilities. Sample: Spell-Like Abilities (CL 7th; concentration +7)
3/day—alter self, fog cloud -->
[H: id = strfind(statblockOrig, "Spell-Like Abilities ([\\w ()/;,+-]+)")]
[H, IF(0<getFindCount(id)),CODE: {
  [SpellLikeAbilities = trim(getGroup(id, 1, 1)))]
  [output=output+"Spell-Like Abilities: "+SpellLikeAbilities+", "]
}]

<!-- Find DR. Sample: 1/-, 2/adamantine, 3/good -->
[h: DRSearch = ""]
[H: id = strfind(statblock, "DR(.?[0-9]+)/(.+?)[;O]")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [DRSearch = getGroup(id, 1, 1)+"/"+getGroup(id, 1, 2))]
  [DRSearch = replace(DRSearch, "/-", "/All")]
  [DRSearch = replace(DRSearch, "(?i)/Cold Iron", "/ColdIron")]
  [DRSearch = replace(DRSearch, "(?i)/Chaotic", "/Chaos")]
  [DRSearch = replace(DRSearch, "(?i)/Lawful", "/Law")]
}]
 
<!-- Find Resistences. Sample: Resist acid 5, cold 5, electricity 5 -->
[h: resistSearch = ""]
[H: id = strfind(statblock, "(\\bResist \\b(\\w+ \\d+,? ?)+)")]
[H, IF(0<getFindCount(id)),CODE: {
  [resistSearch = trim(getGroup(id, 1, 1)))]
}]

<!-- Put DR & Resist values into JSON Property DRER -->
[H, FOREACH( reduceTypes, json.fields( DRER ) ), CODE: {
   [jRC = json.get( DRER, reduceTypes ) ]
   [prefixT = substring( reduceTypes, 0, 1 ) ]
   [FOREACH( reduceType, json.fields( jRC ) ), CODE: {
      [preValue = json.get( jRC, reduceType ) ]
    
     [reduceVal = 0]

     [resistFind = strfind(resistSearch, "(?i)("+reduceType+" )(\\d+)")]
     [IF(0<getFindCount(resistFind) && prefixT == "E"): reduceVal = getGroup(resistFind, 1, 2)]

     [drFind = strfind(DRSearch, "(?i)(\\d+)/("+reduceType+")")]
     [IF(0<getFindCount(drFind) && prefixT == "D"): reduceVal = getGroup(drFind, 1, 1)]
    
     [ chgValue = eval( "" + prefixT + reduceType + "=" + reduceVal ) ]
    
      [IF( reduceType != "Note" ): tmodV = json.get( DRERMod, if( reduceTypes == "Damage Reduction", "DR_", "ER_" ) + reduceType ) ]
      [IF( reduceType != "Note" ): tVal = max( chgValue, tmodV ); tVal = chgValue ]
     
     [IF( tVal != 0 && tVal != "" && prefixT == "D"): DR = listAppend( DR, tVal + if( reduceType == "Note", "", "/" + if( reduceType == "All", "-", reduceType ) ) ) ]
    
     [IF( tVal != 0 && tVal != "" && prefixT == "E"): DR = listAppend( DR, reduceType + if( reduceType == "Note", "", " (" + if( tVal == "999", "Immune", tVal ) + ")" ) ) ]
    
      [IF( reduceType == "Note" && chgValue == 0 ): chgValue = "" ]
      [IF( preValue != chgValue ):  output = output + reduceType + "= " + chgValue + " (" + preValue + "), "]
      [IF( preValue != chgValue ): jRC = json.set( jRC, reduceType, chgValue ) ]
   }]
   [setProperty( "DRER", json.set( DRER, reduceTypes, jRC ) ) ]
   [IF(DRSearch != "" || resistSearch != ""): output=output+"<br>"]
}]

<!-- Find SR --> 
[H: id = strfind(statblock, "SR ([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [SR=getGroup(id, 1, 1)]
  [SpecialQual="SR "+SR]
  [output=output+"SR: "+SR+", "]
  }]

<!-- STATS BEGIN -->
[H: id = strfind(statblockOrig, "Str.+?([0-9]*).+?Dex ?([0-9]*).+?Con.?([0-9]*).+?Int.?([0-9]*).+?Wis.?([0-9]*).+?Cha.?([0-9]*)")]

[H, IF(0<getFindCount(id)), CODE:
  {
  [Strength=getGroup(id, 1, 1)]
  [IF(Strength==""):Strength=10]
  [Dexterity=getGroup(id, 1, 2)]
  [IF(Dexterity==""):Dexterity=10]
  [Constitution=getGroup(id, 1, 3)]
  [IF(Constitution==""):Constitution=10]
  [Intelligence=getGroup(id, 1, 4)]
  [IF(Intelligence==""):Intelligence=10]
  [Wisdom=getGroup(id, 1, 5)]
  [IF(Wisdom==""):Wisdom=10]
  [Charisma=getGroup(id, 1, 6)]
  [IF(Charisma==""):Charisma=10]
  [output=output+"Str: "+Strength+", Dex: "+Dexterity+", Con: "+Constitution+", Int: "+Intelligence+", Wis: "+Wisdom+", Cha: "+Charisma+"<br>"]
  }]
<!-- STATS END -->

<!-- SAVES BEGIN -->
[H: id = strfind(statblock, "Fort (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Fort=getGroup(id, 1, 1)-ConB]
  [output=output+"Fort: "+fort+", "]
  }]
[H: id = strfind(statblock, "Ref (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Reflex=getGroup(id, 1, 1)-DexB]
  [output=output+"Ref: "+reflex+", "]
  }]

[H: id = strfind(statblock, "Will (.?[0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Will=getGroup(id, 1, 1)-WisB]
  [output=output+"Will: "+Will+"<br>"]
  }]
<!-- SAVES END -->

[H: id = strfind(statblock, "hp ([0-9]+).+?([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [HP=getGroup(id, 1, 1)]
  [HPmax=HP]
  [HPavg=HP]
  [HD=getGroup(id, 1, 2)]
  [Level = max(1,HD)]
  [output=output+"HP: "+HP+", HD: "+HD+"<br>"]
  }]

[H: id = strfind(statblock, "(hp [0-9]+ )\\(([0-9]+d[0-9]+([+-][0-9]+)?(\\)))")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [HitDice=getGroup(id, 1, 2)]
  [HitDice=substring(HitDice,0, length(HitDice)-1)]
  [output=output+"Hit Dice: "+HitDice+"<br>"]
  }]
 
[H: id = strfind(statblock, "Base Atk.?(.?[0-9]+);")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [BAB=getGroup(id, 1, 1)]
  [output=output+"Base Atk: "+BAB+", "]
  }]
 
[H: id = strfind(statblock, "CMB.?(.?[0-9]+);")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [CMBMod=getGroup(id, 1, 1)]
  [output=output+"CMB: "+CMBMod+", "]
  }]

<!-- AC BEGIN -->
[H: id = strfind(statblock, "(.?[0-9]+) natural")]
[H, IF(0<getFindCount(id)): natural=getGroup(id, 1, 1); natural=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Natural", natural)]

[H: id = strfind(statblock, "(.?[0-9]+) armor")]
[H, IF(0<getFindCount(id)): armor=getGroup(id, 1, 1);armor=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Armor", armor)]

[H: id = strfind(statblock, "(.?[0-9]+) deflection")]
[H, IF(0<getFindCount(id)): deflect=getGroup(id, 1, 1); deflect=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Deflection", deflect)]

[H: id = strfind(statblock, "(.?[0-9]+) dodge")]
[H, IF(0<getFindCount(id)): dodge=getGroup(id, 1, 1); dodge=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Dodge", dodge)]

[H: id = strfind(statblock, "(.?[0-9]+) shield")]
[H, IF(0<getFindCount(id)): shield=getGroup(id, 1, 1); shield=0]
[H: ArmorClass =  setStrProp(ArmorClass, "Shield", shield)]

[H: id = strfind(statblock, "AC ([0-9]+),")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [AC=getGroup(id, 1, 1)]
  [tch=AC-armor-shield]
  [FF=AC-dodge-DexB]
  [CMD=10+BAB+StrB+DexB-SizeM+dodge+deflect]
  [CMDFF=CMD-DexB-dodge]
  [AC=concat(AC,"/",tch,"/",FF,"/",CMD,"/",CMDFF)]
  [output=output+"AC/tch/FF/CMD/CMDFF: "+AC+"<br>"]
  }]
<!-- AC END -->


[H: id = strfind(statblock, "(Speed|Spd) ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 2)]
  [output=output+"Spd: "+spd]
  [Speed = json.set(Speed, "base",spd)]
  }]
[H: id = strfind(statblock, "fly ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Fly: "+spd]
  [Speed = json.set(Speed, "fly",spd)]
  }]
[H: id = strfind(statblock, "swim ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Swim: "+spd]
  [Speed = json.set(Speed, "swim",spd)]
  }]
[H: id = strfind(statblock, "burrow ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Burrow: "+spd]
  [Speed = json.set(Speed, "burrow",spd)]
  }]
[H: id = strfind(statblock, "climb ([0-9]+) ft")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [spd=getGroup(id, 1, 1)]
  [output=output+", Climb: "+spd]
  [Speed = json.set(Speed, "climb",spd)]
  }]
[H: output=output+"<br>"]

<!-- SKILLS BEGIN -->
[H: tSkillsJ ="[]"]
[H: output=output+"Skills: "]
[H, FOREACH(s, SkillsJ), CODE:
  {
  [skN = json.get(s, "name")]
  [id=0]
  [id = strfind(statblock, skN+"\\s(.?[0-9]+)")]
  [H, IF(0<getFindCount(id)), CODE:
    {
    [skN = replace(skN, " ", "")] <!-- Remove spaces from skill name -->
    [skStat = getStrProp(SkillStat, skN)]   
    [skVal = getGroup(id, 1, 1)]
    [output=output+skN+" "+skVal+", "]
    [s = json.set(s, "rank", skVal-eval(skStat))]   
    }]
  [tSkillsJ = json.append(tSkillsJ,s)]
  }]
[H: output=output+"<br>"]
[H: SkillsJ=tSkillsJ]
<!-- SKILLS END -->

<!-- FEATS BEGIN -->
[H: output=output+"Feats: "]
[H: id = strfind(statblock, "(Improved Initiative)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedInitiative",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedInitiative",0)]
  }]
[H: id = strfind(statblock, "(Agile Maneuvers)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "AgileManeuvers",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "AgileManeuvers",0)]
  }]
[H: id = strfind(statblock, "(Improved Bull Rush)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedBullRush",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedBullRush",0)]
  }]
[H: id = strfind(statblock, "(Improved Disarm)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedDisarm",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedDisarm",0)]
  }]
[H: id = strfind(statblock, "(Improved Grapple)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedGrapple",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedGrapple",0)]
  }]
[H: id = strfind(statblock, "(Improved Overrun)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedOverrun",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedOverrun",0)]
  }]
[H: id = strfind(statblock, "(Improved Sunder)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedSunder",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedSunder",0)]
  }]
[H: id = strfind(statblock, "(Improved Trip)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedTrip",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedTrip",0)]
  }]
[H: id = strfind(statblock, "(Improved Channeling)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "ImprovedChanneling",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "ImprovedChanneling",0)]
  }]
[H: id = strfind(statblock, "(Two.?Weapon Fighting)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "TwoWeaponFighting",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "TwoWeaponFighting",0)]
  }]
[H: id = strfind(statblock, "(Multi.?[aA]ttack)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "MultiAttack",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "MultiAttack",0)]
  }]
 
[H: id = strfind(statblock, "(Power Attack)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "PowerAttack",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "PowerAttack",0)]
  }]

[H: id = strfind(statblock, "(Weapon Finesse)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "WeaponFinesse",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "WeaponFinesse",0)]
  }]
[H: id = strfind(statblock, "(Uncanny Dodge)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "UncannyDodge",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "UncannyDodge",0)]
  }]
[H: id = strfind(statblock, "(Die.?[hH]ard)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "DieHard",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  };{
  [Feats=setStrProp(Feats, "DieHard",0)]
  }]

<!-- Ferocity for Orcs works just like Die Hard -->
[H: id = strfind(SpecialDefense, "(?i)(ferocity)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [Feats=setStrProp(Feats, "DieHard",1)]
  [H: output=output+getGroup(id, 1, 1)+", "]
  }] 
 
[H: output=output+"<br>"]
<!-- FEATS END -->

[H: id = strfind(statblockOrig, "Special Attacks (.+)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [SpecialATK=getGroup(id, 1, 1)]
  [SpecialATK=trim(SpecialATK)]
  [SpecialATK=substring(SpecialATK,0,min(length(SpecialATK),100))]
  [output=output+"SA: "+SpecialATK+"<br>"]
  };{
  [SpecialATK=""]
  }]

<!-- ATTACKS BEGIN -->
<!-- Insert empty weapon strings -->
[H: wpnstr=getPropertyDefault( "Weapon0" )]
[H, c(7,""),CODE:
  {
  [wpn="Weapon"+roll.count]
  [eval(wpn + " = '" + wpnstr+ "'")]
  }]

[H: atkno = 0]

<!-- MELEE -->
<!-- The '(?i)' makes the expression case-insensitive -->
[H: id = strfind(statblock, "Melee (.+?)(?i)(?=Tactic|Face|Space|Reach|Special|Ranged|Stat|Spell-Like Abilities|---)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [allmelee=getGroup(id, 1, 1)]
  [setProperty("OriginalMeleeLine", allmelee)]
  <!-- separate each attack option -->
  [allmelee=stringToList(allmelee, "( or (Melee)?)|(Melee)",":")]
  [atkno = listCount(allmelee, ":")]
  }]
 
<!-- Loop through each attack option and divide into weapons -->
[H: wpnarray=""]
[H: wpnno=0]
[H, FOR(i,0,atkno,1), CODE:
  {
  [atkstr=listget(allmelee, i, ":")]
  [atkstr=stringToList(atkstr, "(?<=\\)) and|(?<=\\)), ",":")]
  [wpns = listCount(atkstr, ":")]
 
  [FOR(j,0,wpns,1), CODE:
  {
    [WpnName = "Weapon" + wpnno]
    [wpnarray=json.append(wpnarray, trim(listGet(atkstr,j,":")))]
    [ x = eval(WpnName) ]
    [IF(j>0):eval(WpnName + "= '" + replace(x,"Primary=\\d+", "Primary=2")+ "'")]
   
    <!-- Set attack options after first to secondary attacks -->
    [eval(WpnName + "= '" + replace(x,"OHLight=\\d+", "OHLight=2")+ "'")]
   
   <!-- Default to not multiattack -->
    [wpnno = wpnno +1]
    }]
  }]
 
<!-- RANGED -->
[H: atkno = 0]
[H: id = strfind(statblock, "Ranged (.+?)(?=Tac|Face|Space|Reach|Special|Ranged|STAT|Stat|Spell-Like Abilities|---)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [allranged=getGroup(id, 1, 1)]
  [setProperty("OriginalRangedLine", allranged)]
  <!-- separate each attack option -->
  [allranged=stringToList(allranged, "(\\s?or (Ranged)?)|(Ranged)",":")]
  [atkno = listCount(allranged, ":")]
  }]
<!-- Loop through each attack option and divide into weapons -->
[H, FOR(i,0,atkno,1), CODE:
  {
  [atkstr=listget(allranged, i, ":")]
  [atkstr=stringToList(atkstr, "(?<=\\)) and|(?<=\\)), ",":")]
  [wpns = listCount(atkstr, ":")]
  [FOR(j,0,wpns,1), CODE:
    {
    [WpnName = "Weapon" + wpnno]
    [wpnarray=json.append(wpnarray, trim(listGet(atkstr,j,":")))]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Ranged", 1)+ "'")]
    [wpnno = wpnno +1]
    }]
  }]
 
<!-- extract info from each attack  -->
[H: wpnno=0]
[H, FOREACH(atkstr, wpnarray), CODE: {
  [atkstr=trim(atkstr)]
  [id = strfind(atkstr, "([+-]\\d+)?(\\d+)?(.+(?= [\\+-]\\d+ (x\\d )?\\()) ([+-]\\d+)[/+\\-0-9\\s(x\\d )?]*?\\((.+)\\)")]
  [regexptofindweaponname = ".+(?= (/?[\\+-]\\d+)+ \\()"]
 
  [IF(0<getFindCount(id)), CODE: {
    [WpnName = "Weapon" + wpnno]
   
    <!-- Quantity / Weapon Bonus-->
    [wquant = 1]
    [wbonus = ""]
    [IF(getGroup(id,1,1)==""): wquant = getGroup(id, 1, 2); wbonus="+ "+getGroup(id, 1, 1)]
    [IF(getGroup(id,1,2)==""): wquant = 1]
    [IF(1<wquant):eval(WpnName + "= '" + setStrProp(eval(WpnName),"Quantity", wquant)+ "'")]
   
   <!-- Weapon Name -->
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Name", replace(wbonus, " ", "") + getGroup(id, 1, 3)) + "'")]
   
   <!-- Manufactored ? -->
    [id2 = strfind(atkstr, "(slam|bite|claw|gore|hoof|tentacle|wing|pincer|tail|sting|talon)")]
    [IF(0==getFindCount(id2)):eval(WpnName + "= '" + setStrProp(eval(WpnName),"Manufactured", 1)+ "'")]
   
   <!-- Not a natural weapon -->
    <!-- Attack bonus (assumes StrB for melee and DexB for ranged) -->
    [watkbonus=getGroup(id, 1, 5)]
    [Ranged=getStrProp(eval(WpnName),"Ranged")]
    [IF(Ranged>0):watkbonus=watkbonus-BAB-DexB-SizeM;watkbonus=watkbonus-BAB-StrB-SizeM]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"AtkBonus", watkbonus)+ "'")]
   
   <!-- CritMult-->
    [wdam=getGroup(id, 1, 6)]
    [CritMult=2]
    [id2 = strfind(wdam, "/[xX](\\d)")]
    [IF(0<getFindCount(id2)):CritMult=getGroup(id2, 1, 1)]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritMult", CritMult)+ "'")]
   
   <!-- CritRange-->
    [CritRange=20]
    [id2 = strfind(wdam, "/(1[0-9])")]
    [IF(0<getFindCount(id2)):CritRange=getGroup(id2, 1, 1)]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritRange", CritRange)+ "'")]
   
   <!-- Damage -->
    [Damage="0d4 plus" + wdam]
   [DmgBonus = 0]
   [DmgPlus = ""]
   [wbonusNum = 0]
    [id2 = strfind(wdam, "(\\d+d\\d+)([^p^/]*)(plus .+)?")]
    [IF(0<getFindCount(id2)):Damage=getGroup(id2, 1, 1)+wbonus]

   [DmgBonus = number(getGroup(id2, 1, 2))]
   [DmgPlus = replace(getGroup(id2, 1, 3), "plus ", "+")]
   [wbonusNum = number(replace(wbonus, " ", ""))]
   [Damage123=replace(Damage, " ", "")]
   
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Damage", Damage)+ "'")]
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"DmgPlus", DmgPlus)+ "'")]
   
   <!-- Two handed ? -->
    <!-- Default to onehanded weapon -->
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 0)+ "'")]

    [id2 = strfind(atkstr, "(?i)(longspear|quarterstaff| spear|falchion|glaive|greataxe|greatclub|greatsword|guisarme|halberd|lance|ranseur|scythe|spiked chain|elven curve blade|dire flail|two-bladed sword|urgrosh|hooked hammer)")]

    [IF(0<getFindCount(id2)):eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 1)+ "'")]
   [DmgBonus = round(if(0<getFindCount(id2), DmgBonus-Str2hB-wbonusNum, DmgBonus-StrB-wbonusNum))]

    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"DmgBonus", DmgBonus)+ "'")]

   [output2 = output +"Weapon DmgBonus: " + DmgBonus + "<br>"]
   [output2 = output +"Weapon wdam: " + wdam + "<br>"]
   
   [output2 = output +"Weapon DmgPlus: " + DmgPlus + "<br>"]
  }]
  [wpnno = wpnno +1]
}]

[H: output = output + "Weapons: " + wpnarray+"<br>"]

<!--
Name=Slam ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=0 ; Ranged=0  ;
ATTACKS END -->

<!-- Getting treasure from Ecology section. -->
[H: id = strfind(statblockOrig, "(?i)(?<=Treasure )(None|Standard|Double|Triple|Incidental|NPC gear)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [TreasureType=getGroup(id, 1, 0)]
  [output=output+"Treasure Type: "+TreasureType+"<br>"]
  }]

<!-- Setting Fast Healing if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Fast Healing )([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [FastHealing=getGroup(id, 1, 0)]
  [output=output+"Fast Healing: "+FastHealing+"<br>"]
  }]
 
<!-- Setting Regeneration if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Regeneration )([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [Regeneration=getGroup(id, 1, 0)]
  [output=output+"Regeneration: "+Regeneration+"<br>"]
  }]

<!-- Setting Anti Regeneration damage type if present -->
[H: id = strfind(statblockOrig, "(?i)(?<=Regeneration )([0-9]+.+)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [AntiRegen=getGroup(id, 1, 0)]
  [output=output+"Anti-Regen Damage Type: "+AntiRegen+"<br>"]
  }]

<!-- Statblock from HeroLab -->
[H: id = strfind(statblockOrig, "(?i)(Hero Lab logo are Registered Trademarks)")]
[H, IF(0<getFindCount(id)),CODE:
  {
  [HeroLab=1]
  [HideMeleeRange=1]
  [output=output+"Stat block generated from Hero Lab.<br>"]
  }]
 
[R,S,G: output]

[H: HP = HPmax ]
[H: HPNonLethalDMG = 0]
[H: tToken = currentToken() ]
[H, MACRO( "[email protected]:libDnD35Pathfinder" ): "Token=" + tToken]
[H: setState("Prone", 0)]
[H: setState("Unconscious", 0)]
[H: setLayer("TOKEN") ]
[/spoiler]
-Jamz
____________________
Custom MapTool 1.4.x.x Fork: maptool.nerps.net
Custom TokenTool 2.0 Fork: tokentool.nerps.net
More information here: MapTool Nerps! Fork

User avatar
JamzTheMan
Great Wyrm
Posts: 1872
Joined: Mon May 10, 2010 12:59 pm
Location: Chicagoland
Contact:

Re: PF statblock importer

Post by JamzTheMan »

And my latest campaign properties to go with the macro...

Major change is adding DmgBonus=0 to all the Weapon props. And @Immune, @Weaknesses, @SpellLikeAbilities

[spoiler=Campaign Properties: Pathfinder]

Code: Select all

Private:" ; "
PrivateJSON:{}
Race:{"name":"","family":"","type":"","subtype":[],"notes":""}
@CreatureType:[R:  json.get(Race, "type") + " " + json.toList(json.get(Race, "subtype"))]
SizeM:0
Level:1
Levels:TurnLevel=0 ; ECL=Level ;
@LevelsInfo (Level/CR):[R: Level] | [R: eval( "" + getStrProp(getProperty("Levels"), "ECL") ) ]
@Languages:[R: json.get(getProperty("Race"), "notes")]
@HP:0
@HPmax:[R: max( Level, ( 1 + (ConB * Level) ) )]
@HPtemp:0
@HPNonLethalDMG:0
IsBloodied (Is Bloodied):[r:if(HP/HPmax < 0.5, "YES!", "")]
BAB:0
CMBMod:0
CMDMod:0
#Reach:5
MiscATK:0
MiscDMG:0
---| Daily Uses |---
ChannelEnergy:0
HealingSurges:0
Daily:ChannelEnergy=0 ; HealingSurges=0 ; NegativeLevels=0 ;
---| Informational Text |---
InitMod:0
@Movement:[R: json.get(getProperty("Speed"), "base") + json.get(getProperty("SpeedMod"), "base")]
Speed:{"base" : 30,"climb" : 0,"swim" : 0,"burrow" : 0,"fly" : 0,"flymaneuver" : 0,"encumbered" : 0,"special" : ""}
SpeedMod:{"base" : 0,"climb" : 0,"swim" : 0,"burrow" : 0,"fly" : 0,"flymaneuver" : 0,"encumbered" : 0,"special" : ""}
@MoveRemain
MoveActive:base
Elevation (Elv)
AC (AC/TH/FF/CMD/CMDFF)
ArmorClass:Armor=0 ; ArmorMod=0 ; Shield=0 ; ShieldMod=0 ; ArmorACP=0 ; ShieldACP=0 ; MaxDex=50 ; Natural=0 ; NaturalMod=0 ; Deflection=0 ; Dodge=0 ; ACMod=0 ; Description= ;
@SpecialATK:NA
@SpecialQual:NA
@SpecialDefense:NA
@DR
DRER_old:{"Damage Reduction":{"All":0,"Adamantine":0,"ColdIron":0,"Epic":0,"Magic":0,"Silver":0,"Bludgeoning":0,"Piercing":0,"Slashing":0,"Chaos":0,"Evil":0,"Good":0,"Law":0,"Vorpal":0,"Wood":0,"Lethal":0,"NonMagic":0,"Note":""},"Energy Resistance":{"Acid":0,"Cold":0,"Electricity":0,"Fire":0,"Sonic":0,"Note":""}}
DRERMod_old:{"DR_All":0,"DR_Adamantine":0,"DR_ColdIron":0,"DR_Epic":0,"DR_Magic":0,"DR_Silver":0,"DR_Bludgeoning":0,"DR_Piercing":0,"DR_Slashing":0,"DR_Chaos":0,"DR_Evil":0,"DR_Good":0,"DR_Law":0,"ER_Acid":0,"ER_Cold":0,"ER_Electricity":0,"ER_Fire":0,"ER_Sonic":0}
DRER:{"Damage Reduction":{"All":0, "Adamantine":0, "ColdIron":0, "Epic":0, "Magic":0, "Silver":0, "Bludgeoning":0, "Piercing":0, "Slashing":0, "Chaos":0, "Evil":0, "Good":0, "Law":0, "Note":""}, "Energy Resistance":{"Acid":0, "Cold":0, "Electricity":0, "Fire":0, "Sonic":0, "Note":""}, "Energy Vulnerability":{"V.Acid":0, "V.Cold":0, "V.Electricity":0, "V.Fire":0, "V.Sonic":0, "Note":""}, "Spell Resistance":{"SR":0, "Note":""}}
DRERMod:{"DR_All":0, "DR_Adamantine":0, "DR_ColdIron":0, "DR_Epic":0, "DR_Magic":0, "DR_Silver":0, "DR_Bludgeoning":0, "DR_Piercing":0, "DR_Slashing":0, "DR_Chaos":0, "DR_Evil":0, "DR_Good":0, "DR_Law":0, "DP_P.All":0, "DP_P.Adamantine":0, "DP_P.ColdIron":0, "DP_P.Epic":0, "DP_P.Magic":0, "DP_P.Silver":0, "DP_P.Bludgeoning":0, "DP_P.Piercing":0, "DP_P.Slashing":0, "DP_P.Chaos":0, "DP_P.Evil":0, "DP_P.Good":0, "DP_P.Law":0, "ER_Acid":0, "ER_Cold":0, "ER_Electricity":0, "ER_Fire":0, "ER_Sonic":0, "EP_P.Acid":0, "EP_P.Cold":0, "EP_P.Electricity":0, "EP_P.Fire":0, "EP_P.Sonic":0, "EV_V.Acid":0, "EV_V.Cold":0, "EV_V.Electricity":0, "EV_V.Fire":0, "EV_V.Sonic":0, "SR_SR":0}
@Immune
@Weaknesses
@SpellLikeAbilities
BonusTypedItems:{}
ItemSlots:{}
---| Stats/Saves |---
Strength (Str):10
StrMod:0
Dexterity (Dex):10
DexMod:0
Constitution (Con):10
ConMod:0
Intelligence (Int):10
IntMod:0
Wisdom (Wis):10
WisMod:0
Charisma (Cha):10
ChaMod:0
StatCheckMod:{"StrengthCheckMod":0,"DexterityCheckMod":0,"ConstitutionCheckMod":0,"IntelligenceCheckMod":0,"WisdomCheckMod":0,"CharismaCheckMod":0}
Fort:0
FortBonus:0
Reflex:0
ReflexBonus:0
Will:0
WillBonus:0
---| Skills and Feats |---
SkillsJ:[{"name":"Acrobatics","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Appraise","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Bluff","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Climb","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Craft","subcat":"99","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0},{"name":"Diplomacy","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Disable Device","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Disguise","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Escape Artist","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Fly","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Handle Animal","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Heal","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Intimidate","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Knowledge","subcat":"99","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0},{"name":"Linguistics","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Perception","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Perform","subcat":"99","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0},{"name":"Profession","subcat":"99","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0},{"name":"Ride","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Sense Motive","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Sleight of Hand","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Spellcraft","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Stealth","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Survival","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Swim","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""},{"name":"Use Magic Device","rank":0,"classskill":0,"racialmod":0,"synergy":0,"feats":0,"equip":0,"misc":0,"notes":"","altstat":"","speedmod":0,"subcat":""}]
Skills:Acrobatics=0 ; Appraise=0 ; Bluff=0 ; Climb=0 ; Diplomacy=0 ; DisableDevice=0 ; Disguise=0 ; EscapeArtist=0 ; Fly=0 ; HandleAnimal=0 ; Heal=0 ; Intimidate=0 ; KnowledgeArcana=0 ; KnowledgeDungeoneering=0 ; KnowledgeEngineering=0 ; KnowledgeGeography=0 ; KnowledgeHistory=0 ; KnowledgeLocal=0 ; KnowledgeNature=0 ; KnowledgeNobility=0 ; KnowledgePlanes=0 ; KnowledgeReligion=0 ; Linguistics=0 ; Perception=0 ; Perform=0 ; Ride=0 ; SenseMotive=0 ; SleightOfHand=0 ; Spellcraft=0 ; Stealth=0 ; Survival=0 ; Swim=0 ; UseMagicDevice=0 ;
SkillStat:Acrobatics=DexB ; Appraise=IntB ; Bluff=ChaB ; Climb=StrB ; Diplomacy=ChaB ; DisableDevice=DexB ; Disguise=ChaB ; EscapeArtist=DexB ; Fly=DexB ; HandleAnimal=ChaB ; Heal=WisB ; Intimidate=ChaB ; KnowledgeArcana=IntB ; KnowledgeDungeoneering=IntB ; KnowledgeEngineering=IntB ; KnowledgeGeography=IntB ; KnowledgeHistory=IntB ; KnowledgeLocal=IntB ; KnowledgeNature=IntB ; KnowledgeNobility=IntB ; KnowledgePlanes=IntB ; KnowledgeReligion=IntB ; Linguistics=IntB ; Perception=WisB ; Perform=ChaB ; Ride=DexB ; SenseMotive=WisB ; SleightOfHand=DexB ; Spellcraft=IntB ; Stealth=DexB ; Survival=WisB ; Swim=StrB ; UseMagicDevice=ChaB ;
SkillArmor:Acrobatics=1 ; Appraise=0 ; Bluff=0 ; Climb=1 ; Diplomacy=0 ; DisableDevice=0 ; Disguise=0 ; EscapeArtist=1 ; Fly=1 ; HandleAnimal=0 ; Heal=0 ; Intimidate=0 ; KnowledgeArcana=0 ; KnowledgeDungeoneering=0 ; KnowledgeEngineering=0 ; KnowledgeGeography=0 ; KnowledgeHistory=0 ; KnowledgeLocal=0 ; KnowledgeNature=0 ; KnowledgeNobility=0 ; KnowledgePlanes=0 ; KnowledgeReligion=0 ; Linguistics=0 ; Perception=0 ; Perform=0 ; Ride=0 ; SenseMotive=0 ; SleightOfHand=1 ; Spellcraft=0 ; Stealth=1 ; Survival=0 ; Swim=1 ; UseMagicDevice=0 ;
ArmorCheckPenalty:0
SkillMisc:0
Feats:ImprovedInitiative=0 ; AgileManeuvers=0 ; ImprovedBullRush=0 ; ImprovedDisarm=0 ; ImprovedGrapple=0 ; ImprovedOverrun=0 ; ImprovedSunder=0 ; ImprovedTrip=0 ; PointBlankShot=0 ; ManyShot=0 ; TwoWeaponFighting=0 ; ImprovedTwoWeaponFighting=0 ; GreaterTwoWeaponFighting=0 ; MultiAttack=0 ; WeaponFinesse=0 ; CriticalFocus=0 ; UncannyDodge=0 ; ImprovedTurning=0 ; VitalStrike=0 ; ImprovedVitalStrike = 0 ; GreaterVitalStrike = 0 ;
---| Weapons |---
Weapon0:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon1:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon2:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon3:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon4:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon5:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon6:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon7:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon8:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon9:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon10:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon11:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon12:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon13:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon14:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon15:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon16:Name=NA ; Primary=1 ; Quantity=1 ; Manufactured=0  ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ;  DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon17:Name=Slam ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=1d4 ; DmgPlus= ; DmgMax=4 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=50 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=0  ;
Weapon18:Name=Touch ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=0d1 ; DmgPlus= ; DmgMax=0 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=0 ; TwoHanded=0 ; Finesse=1 ; OHLight=2 ; Ranged=0 ;
Weapon19:Name=Ranged Touch ; Primary=1 ; Quantity=1 ; Manufactured=0 ; AtkBonus=0 ; DmgBonus=0 ; CritMult=2 ; CritRange=20 ; Damage=0d1 ; DmgPlus= ; DmgMax=0 ; DmgExtra=0d6 ; DmgExtraCrit=0d10 ; DmgExtraName= ; DmgBonusCap=0 ; TwoHanded=0 ; Finesse=0 ; OHLight=2 ; Ranged=1 ;
HelpWeaponProperty:Primary=0-NotInUse 1-Primary 2-Secondary ; Quantity= # natural attacks ; Manufactured= 0-Natural 1-Manufactured (for multi attack if BAB>5) ; AtkBonus= Magic/Masterwork/Feat ; DmgBonus=Adjust str damage ; CritRange= Lower end 19-20 is 19 ; DmgExtra= 1d6 (EX from flaming) set to 0d6 for none ; DmgExtraCrit= 1d10 (EX burst) set to 0d10 for none; DmgExtraName= Fire / Cold / Acid / etc. ; DmgBonusCap=0-No STR Bonus, >0 - Cap to STR bonus (STR Bow) ; TwoHanded=0-One  Handed, 1-Two Handed ; Finesse=0-Not Finessable, 1-Finessable ; OHLight=0-Offhand heavy, 1-Offhand Light, 2-Not  Multi-attack
---| Calculated |---
StrB:[R: floor((Strength+StrMod-10)/2)]
Str2hB:[R: floor(floor((Strength+StrMod-10)/2)+(max(0,floor((Strength+StrMod-10)/4))))]
StrSecB:[R: floor((Strength+StrMod-10)/4)]
DexB:[R: floor((Dexterity+DexMod-10)/2)]
ConB:[R: floor((Constitution+ConMod-10)/2)]
IntB:[R: floor((Intelligence+IntMod-10)/2)]
WisB:[R: floor((Wisdom+WisMod-10)/2)]
ChaB:[R: floor((Charisma+ChaMod-10)/2)]
---| Wrathgon |---
CasterBackup:{}
SAGroup:{}
MasterEH:{}
PCFeats:[]
---| Wrathgon And Plothos |---
CasterInfo:{}
SpecAbils:{}
SACats
---| Plothos |---
CI_SpecAbils:{}
CISA_Groups:{}
SAGroups:{}
AMSL:0
BMSL:0
BGMSL:0
CMSL:0
DMSL:0
PMSL:0
RMSL:0
SMSL:0
WMSL:0
ACL:0
BCL:0
BGCL:0
CCL:0
DCL:0
PCL:0
RCL:0
SCL:0
WCL:0
APL:0
BpL:0
BGPL:0
CPL:0
DPL:0
PPL:0
RPL:0
SPL:0
WPL:0
IsCaster:0
FirstDomain:(None)
SecondDomain:(None)
Cleric_Good_or_Evil:Good
SchoolSpec:(None)
ProhibSchool1:(None)
ProhibSchool2:(None)
ObjectBond:0
Bloodline:(None)
AssassinSPD:1=0;2=0;3=0;4=0
AssassinSpellsLeft:1=0;2=0;3=0;4=0
Assassin1:(None)
Assassin2:(None)
Assassin3:(None)
Assassin4:(None)
BardSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0
BardSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0
Bard0:(None)
Bard1:(None)
Bard2:(None)
Bard3:(None)
Bard4:(None)
Bard5:(None)
Bard6:(None)
BlackguardSPD:1=0;2=0;3=0;4=0
BlackguardSpellsLeft:1=0;2=0;3=0;4=0
BlackguardPrep:1=(None);2=(None);3=(None);4=(None)
Blackguard1:(None)
Blackguard2:(None)
Blackguard3:(None)
Blackguard4:(None)
ClericSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
ClericSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
ClericDomsPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
ClericDomsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
ClericDomainPowers:(None)
ClericPrep:0=(None);1=(None);2=(None);3=(None);4=(None);5=(None);6=(None);7=(None);8=(None);9=(None);
Cleric0:(None)
Cleric1:(None)
Domain1:(None)
Domain1Prepped:(None)
Cleric2:(None)
Domain2:(None)
Domain2Prepped:(None)
Cleric3:(None)
Domain3:(None)
Domain3Prepped:(None)
Cleric4:(None)
Domain4:(None)
Domain4Prepped:(None)
Cleric5:(None)
Domain5:(None)
Domain5Prepped:(None)
Cleric6:(None)
Domain6:(None)
Domain6Prepped:(None)
Cleric7:(None)
Domain7:(None)
Domain7Prepped:(None)
Cleric8:(None)
Domain8:(None)
Domain8Prepped:(None)
Cleric9:(None)
Domain9:(None)
Domain9Prepped:(None)
DruidSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
DruidSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
DruidPrep:0=(None);1=(None);2=(None);3=(None);4=(None);5=(None);6=(None);7=(None);8=(None);9=(None);
Druid0:(None)
Druid1:(None)
Druid2:(None)
Druid3:(None)
Druid4:(None)
Druid5:(None)
Druid6:(None)
Druid7:(None)
Druid8:(None)
Druid9:(None)
PaladinSPD:1=0;2=0;3=0;4=0
PaladinSpellsLeft:1=0;2=0;3=0;4=0
PaladinPrep:1=(None);2=(None);3=(None);4=(None)
Paladin1:(None)
Paladin2:(None)
Paladin3:(None)
Paladin4:(None)
RangerSPD:1=0;2=0;3=0;4=0
RangerSpellsLeft:1=0;2=0;3=0;4=0
RangerPrep:1=(None);2=(None);3=(None);4=(None)
Ranger1:(None)
Ranger2:(None)
Ranger3:(None)
Ranger4:(None)
SorcererSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
SorcererSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0;
Sorcerer0:(None)
Sorcerer1:(None)
Sorcerer2:(None)
Sorcerer3:(None)
Sorcerer4:(None)
Sorcerer5:(None)
Sorcerer6:(None)
Sorcerer7:(None)
Sorcerer8:(None)
Sorcerer9:(None)
BloodlinePowers:(None)
WizardSPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
WizardSpellsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
WizardSpecsPD:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
WizardSpecsLeft:0=0;1=0;2=0;3=0;4=0;5=0;6=0;7=0;8=0;9=0
WizardBondPD:0
WizardBondLeft:0
WizardPowers:(None)
WizardPrep:0=(None);1=(None);2=(None);3=(None);4=(None);5=(None);6=(None);7=(None);8=(None);9=(None);
Wizard0:(None)
Wizard1:(None)
Wizard2:(None)
Wizard3:(None)
Wizard4:(None)
Wizard5:(None)
Wizard6:(None)
Wizard7:(None)
Wizard8:(None)
Wizard9:(None)
Template
am.spellManager
---| Nerps Custom Properties |---
Nerps_Wiki (Wiki)
HeroLab:0
HideMeleeRange:1
OriginalMeleeLine
OriginalRangedLine
XP:0
NewXP:0
XPadvancmentPace:1
NextLevelXP:[r: json.get(json.get(XPAdv, XPadvancmentPace), (Level  - 1))]
XPAdv:[[1300, 3300, 6000, 10000, 15000, 23000, 34000, 50000, 71000, 105000, 145000, 210000, 295000, 425000, 600000, 850000, 1200000, 1700000, 2400000], [2000, 5000, 9000, 15000, 23000, 35000, 51000, 75000, 105000, 155000, 220000, 315000, 445000, 635000, 890000, 1300000, 1800000, 2550000, 3600000], [3000, 7500, 14000, 23000, 35000, 53000, 77000, 115000, 160000, 235000, 330000, 475000, 665000, 955000, 1350000, 1900000, 2700000, 3850000, 5350000]]
HitDice
HPavg
---| Nerps Alt Statsheet Output |---
newStr:1
Regeneration
AntiRegen
*#DisplayCreatureType (Creature Type):[R: CreatureType]
*@DisplayLevelsInfo (Level/CR):[R: LevelsInfo]
*#DisplayLanguages (Languages):[R: Languages]
*#DisplayPerception (Perception):[R: getStrProp(Skills, "Perception")]
*#DisplayInitMod (Initiative):[R: InitMod]
*#DisplayHitDice (Hit Dice):{HitDice}
*#DisplayHitPoints (Hit Points):[R: HP + HPtemp + " (" + HPmax][r:if(HPtemp>0, "+"+HPtemp+")", ")")][r:if(HP<0, " [-"+(Constitution+ConMod)+" max]", "")]
*#DisplayHPNonLethalDMG (Non-Lethal Damage):[r:if(HPNonLethalDMG!=0, HPNonLethalDMG, "")]
*#FastHealing (Fast Healing)
*#DisplayRegeneration (Regeneration):[R: AntiRegen]
*#DisplayBaseAttack (BAB/CMB):[R: BAB]/[R: CMBMod]
*#DisplayReach (Reach):[R: Reach]
*#DisplayMiscATK (Misc Attack Bonus):[r:if(MiscATK!=0, MiscATK, "")]
*#DisplayMiscDMG (Misc Damage Bonus):[r:if(MiscDMG!=0, MiscDMG, "")]
*#DisplayMovement (Movement):[R: Movement]
*#DisplayMoveRemain (Move Remaining):[R: MoveRemain]
*#DisplayAC (AC/Touch/FF/CMD/CMDFF):[R: AC]
*#AllStats (Str,Dex,Con,Int,Wis,Cha):[R: Strength+StrMod],[R:Dexterity+DexMod],[R:Constitution+ConMod],[R:Intelligence+IntMod],[R:Wisdom+WisMod],[R:Charisma+ChaMod]
*#AllSaves (Fortitude, Reflex, Will):[R:Fort+ConB+FortBonus], [R:Reflex+DexB+ReflexBonus], [R:Will+WisB+WillBonus]
*#SaveMisc
*#DisplaySpecialQual (Special Qualities):[r:if(SpecialQual != "NA", SpecialQual, "")]
*#DisplaySpecialDefense (Special Defense):[r:if(SpecialDefense != "NA", SpecialDefense, "")]
*#DisplaySpecialATK (Special Attacks):[r:if(SpecialATK != "NA", SpecialATK, "")]
*#DisplaySpellLikeAbilities (Spell Like Abilities):{SpellLikeAbilities}
*#DisplayDR (DR):{DR}
*#DisplayImmune (Immunities):{Immune}
*#DisplayWeaknesses (Weaknesses):{Weaknesses}
*#DisplayMelee (Melee):[r: if(HideMeleeRange == 1, "", OriginalMeleeLine)]
*#DisplayRanged (Ranged):[r: if(HideMeleeRange == 1, "", OriginalRangedLine)]
*#DisplayFeats (Combat Feats):[R: "" + if(getStrProp(Feats, "AgileManeuvers")==1, " [AM]", "") + if(getStrProp(Feats, "ImprovedBullRush")==1, " [IBR]", "") + if(getStrProp(Feats, "ImprovedDisarm")==1, " [ID]", "") + if(getStrProp(Feats, "ImprovedGrapple")==1, " [IG]", "") + if(getStrProp(Feats, "ImprovedOverrun")==1, " [IO]", "") + if(getStrProp(Feats, "ImprovedSunder")==1, " [IS]", "") + if(getStrProp(Feats, "ImprovedTrip")==1, " [IT]", "") + if(getStrProp(Feats, "PointBlankShot")==1, " [PBS]", "") + if(getStrProp(Feats, "ManyShot")==1, " [MS]", "") + if(getStrProp(Feats, "TwoWeaponFighting")==1, " [TWF]", "") + if(getStrProp(Feats, "ImprovedTwoWeaponFighting")==1, " [ITWF]", "") + if(getStrProp(Feats, "GreaterTwoWeaponFighting")==1, " [GTWF]", "") + if(getStrProp(Feats, "MultiAttack")==1, " [MA]", "") + if(getStrProp(Feats, "PowerAttack")==1, " [PA]", "") + if(getStrProp(Feats, "UncannyDodge")==1, " [UD]", "") + if(getStrProp(Feats, "WeaponFinesse")==1, " [WF]", "") + if(getStrProp(Feats, "ImprovedTurning")==1, " [ITurn]", "") + if(getStrProp(Feats, "CriticalFocus")==1, " [CF]", "") + if(getStrProp(Feats, "VitalStrike")==1, " [VS]", "") + if(getStrProp(Feats, "ImprovedVitalStrike")==1, " [IVS]", "") + if(getStrProp(Feats, "GreaterVitalStrike")==1, " [GVS]", "") + if(getStrProp(Feats, "ImprovedChanneling")==1, " [IC]", "") + if(getStrProp(Feats, "DieHard")==1, " [DH]", "")]
*#Attack #1:[R: if(getStrProp(Weapon0, "Name") == "NA", "", if(getStrProp(Weapon0, "Quantity") > 1, getStrProp(Weapon0, "Quantity") + " ", "") + getStrProp(Weapon0, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon0, "AtkBonus") + if(getStrProp(Weapon0, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon0, "Damage") + strformat("%+d", (if(getStrProp(Weapon0, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon0, "DmgBonus", 0))) + getStrProp(Weapon0, "DmgPlus", 0) + " / " + getStrProp(Weapon0, "CritRange") + "x" + getStrProp(Weapon0, "CritMult") + ")")]
*#Attack #2:[R: if(getStrProp(Weapon1, "Name") == "NA", "", if(getStrProp(Weapon1, "Quantity") > 1, getStrProp(Weapon1, "Quantity") + " ", "") + getStrProp(Weapon1, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon1, "AtkBonus") + if(getStrProp(Weapon1, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon1, "Damage") + strformat("%+d", (if(getStrProp(Weapon1, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon1, "DmgBonus", 0))) + getStrProp(Weapon1, "DmgPlus", 0) + " / " + getStrProp(Weapon1, "CritRange") + "x" + getStrProp(Weapon1, "CritMult") + ")")]
*#Attack #3:[R: if(getStrProp(Weapon2, "Name") == "NA", "", if(getStrProp(Weapon2, "Quantity") > 1, getStrProp(Weapon2, "Quantity") + " ", "") + getStrProp(Weapon2, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon2, "AtkBonus") + if(getStrProp(Weapon2, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon2, "Damage") + strformat("%+d", (if(getStrProp(Weapon2, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon2, "DmgBonus", 0))) + getStrProp(Weapon2, "DmgPlus", 0) + " / " + getStrProp(Weapon2, "CritRange") + "x" + getStrProp(Weapon2, "CritMult") + ")")]
*#Attack #4:[R: if(getStrProp(Weapon3, "Name") == "NA", "", if(getStrProp(Weapon3, "Quantity") > 1, getStrProp(Weapon3, "Quantity") + " ", "") + getStrProp(Weapon3, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon3, "AtkBonus") + if(getStrProp(Weapon3, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon3, "Damage") + strformat("%+d", (if(getStrProp(Weapon3, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon3, "DmgBonus", 0))) + getStrProp(Weapon3, "DmgPlus", 0) + " / " + getStrProp(Weapon3, "CritRange") + "x" + getStrProp(Weapon3, "CritMult") + ")")]
*#Attack #5:[R: if(getStrProp(Weapon4, "Name") == "NA", "", if(getStrProp(Weapon4, "Quantity") > 1, getStrProp(Weapon4, "Quantity") + " ", "") + getStrProp(Weapon4, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon4, "AtkBonus") + if(getStrProp(Weapon4, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon4, "Damage") + strformat("%+d", (if(getStrProp(Weapon4, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon4, "DmgBonus", 0))) + getStrProp(Weapon4, "DmgPlus", 0) + " / " + getStrProp(Weapon4, "CritRange") + "x" + getStrProp(Weapon4, "CritMult") + ")")]
*#Attack #6:[R: if(getStrProp(Weapon5, "Name") == "NA", "", if(getStrProp(Weapon5, "Quantity") > 1, getStrProp(Weapon5, "Quantity") + " ", "") + getStrProp(Weapon5, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon5, "AtkBonus") + if(getStrProp(Weapon5, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon5, "Damage") + strformat("%+d", (if(getStrProp(Weapon5, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon5, "DmgBonus", 0))) + getStrProp(Weapon5, "DmgPlus", 0) + " / " + getStrProp(Weapon5, "CritRange") + "x" + getStrProp(Weapon5, "CritMult") + ")")]
*#Attack #7:[R: if(getStrProp(Weapon6, "Name") == "NA", "", if(getStrProp(Weapon6, "Quantity") > 1, getStrProp(Weapon6, "Quantity") + " ", "") + getStrProp(Weapon6, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon6, "AtkBonus") + if(getStrProp(Weapon6, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon6, "Damage") + strformat("%+d", (if(getStrProp(Weapon6, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon6, "DmgBonus", 0))) + getStrProp(Weapon6, "DmgPlus", 0) + " / " + getStrProp(Weapon6, "CritRange") + "x" + getStrProp(Weapon6, "CritMult") + ")")]
*#Attack #8:[R: if(getStrProp(Weapon7, "Name") == "NA", "", if(getStrProp(Weapon7, "Quantity") > 1, getStrProp(Weapon7, "Quantity") + " ", "") + getStrProp(Weapon7, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon7, "AtkBonus") + if(getStrProp(Weapon7, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon7, "Damage") + strformat("%+d", (if(getStrProp(Weapon7, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon7, "DmgBonus", 0))) + getStrProp(Weapon7, "DmgPlus", 0) + " / " + getStrProp(Weapon7, "CritRange") + "x" + getStrProp(Weapon7, "CritMult") + ")")]
*#Attack #9:[R: if(getStrProp(Weapon8, "Name") == "NA", "", if(getStrProp(Weapon8, "Quantity") > 1, getStrProp(Weapon8, "Quantity") + " ", "") + getStrProp(Weapon8, "Name") + " " + strformat("%+d", (BAB + getStrProp(Weapon8, "AtkBonus") + if(getStrProp(Weapon8, "Ranged") == 0, StrB, DexB) + SizeM)) + " (" + getStrProp(Weapon8, "Damage") + strformat("%+d", (if(getStrProp(Weapon8, "TwoHanded") == 0, StrB, Str2hB) + getStrProp(Weapon8, "DmgBonus", 0))) + getStrProp(Weapon8, "DmgPlus", 0) + " / " + getStrProp(Weapon8, "CritRange") + "x" + getStrProp(Weapon8, "CritMult") + ")")]
*#Touch/Ranged Touch:[R: strformat("%+d", (BAB + getStrProp(Weapon9, "AtkBonus") + StrB + SizeM)) + " / " + strformat("%+d", (BAB + getStrProp(Weapon9, "AtkBonus") + DexB + SizeM))]
*#TreasureType (Treasure)
*#Nerps_Treasure (Additional Treasure)
*@DisplayXP (Current XP):[r: if(XP > 0 && isPC(), XP + if(NewXP > 0, " (+" + NewXP + ")", "") + " / " + NextLevelXP,"")]
[/spoiler]
-Jamz
____________________
Custom MapTool 1.4.x.x Fork: maptool.nerps.net
Custom TokenTool 2.0 Fork: tokentool.nerps.net
More information here: MapTool Nerps! Fork

Deuterazamus
Kobold
Posts: 14
Joined: Tue Oct 23, 2012 8:34 am

Re: PF statblock importer

Post by Deuterazamus »

Hey Jamz! I see that your statblock importing macro and properties handle Fast Healing and Regeneration, among other things. Do you happen to have some macros to account for that during combat? Or those properties are just there for the GM to remind (which, bw is already a very handy addon)?

Cheers!

User avatar
JamzTheMan
Great Wyrm
Posts: 1872
Joined: Mon May 10, 2010 12:59 pm
Location: Chicagoland
Contact:

Re: PF statblock importer

Post by JamzTheMan »

Actually the pathfinder framework handles them on the standard damage macro, i don't think i had to modify out at all IIRC. Ooh, actually this prob happens more on the init macro, as it heals them on there init. It prompts so you can deny it.

I probably should post my latest version, did some work to better handle multi attacks especially due to high BAB.
-Jamz
____________________
Custom MapTool 1.4.x.x Fork: maptool.nerps.net
Custom TokenTool 2.0 Fork: tokentool.nerps.net
More information here: MapTool Nerps! Fork

Post Reply

Return to “[D&D3.5 + Pathfinder] Campaign Macros”