Statblock2Token v1.8 ? I only see v1.6

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

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

Forum rules
Discussion regarding lmarkus001's framework only. Other posts deleted without notice! :)
DMFTodd
Cave Troll
Posts: 95
Joined: Mon Jun 29, 2009 11:17 pm

Re: Statblock2Token v1.8 ? I only see v1.6

Post by DMFTodd »

I'm using the Statblock2token, works pretty well, but on the occasions it doesn't work I'm stumped. Is there any tips & trips for getting the 1.8 import to work smoothly?

Or, if you want specifics, how come this stat block fails to create the attack for the Shortsword?

Code: Select all

Zyphus Cultist CR 1
Male or Female human fortune-spurned warrior 1
NE Medium humanoid (human)
Init +1; Senses Perception –2
Aura aura of misfortune (10 ft.)
Defense
AC 17, touch 11, flat-footed 16 (+4 armor, +1 Dex, +2 shield)
hp 9 (1d10+4)
Fort +1, Ref –1, Will –3
Offense
Speed 30 ft.
Melee short sword +2 (1d6+1/19–20)
Tactics
Before Combat The cultists rest in the light of a single torch in
the northeast corner of the tunnels. If they know the PCs are
coming, they move back out of sight and wait to ambush the
PCs either in the northeast corner or in the south where the
two tunnels reconnect.
During Combat The cultists are not strategic fighters—they pick
the nearest target, get close, and attack furiously.
Morale With no other options left to them, the cultists fight to
the death.
Statistics
Str 13, Dex 12, Con 13, Int 10, Wis 9, Cha 8
Base Atk +1; CMB +2; CMD 13
Feats Toughness, Weapon Focus (short sword)
Skills Climb –1, Intimidate +1, Knowledge (religion) –1, Perception
–2; Racial Modifiers A fortune-spurned creature takes a –
2
penalty on all skill checks—this penalty stacks with the one it
takes on opposed checks
Languages Common
SQ cursed, diminished criticals, twist of fate, unlucky strike (DC 9)
Combat Gear potion of cure light wounds; Other Gear chain shirt,
heavy wooden shield, short sword

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

Re: Statblock2Token v1.8 ? I only see v1.6

Post by neofax »

Yes, your em-dashes kill the regular expression matching. I bet you were getting a "java.lang.String, expecting java.math.BigDecimal" error when running the macro. It was dying on the first em-dash in Ref -1 and anything after that did not get added to the properties. Use notepad++ to remove those em-dashes with actual dashes and it will work fine.

P.S. I attached the token to my post.
Attachments
Zyphus Cultist.rptok
(73.66 KiB) Downloaded 199 times
Image
Time-Zone information UTC -5

DMFTodd
Cave Troll
Posts: 95
Joined: Mon Jun 29, 2009 11:17 pm

Re: Statblock2Token v1.8 ? I only see v1.6

Post by DMFTodd »

That did it. Thanks a bunch.

DMFTodd
Cave Troll
Posts: 95
Joined: Mon Jun 29, 2009 11:17 pm

Re: Statblock2Token v1.8 ? I only see v1.6

Post by DMFTodd »

Anybody see a problem with this one:

Code: Select all

Greater Reefclaws (3) CR 2
Advanced reefclaw (Pathfinder RPG Bestiary 2 234, 292)
CN Small aberration (aquatic)
Init +7; Senses darkvision 60 ft., low-light vision; Perception +8
DEFENSE
AC 18, touch 14, flat-footed 15 (+3 Dex, +4 natural, +1 size)
hp 17 each (2d8+8)
Fort +4, Ref +3, Will +6
Defensive Abilities ferocity; Resist cold 5
OFFENSE
Speed 5 ft., swim 40 ft.
Melee 2 claws +4 (1d4+2 plus grab and poison)
Special Attacks death frenzy, constrict (1d4+2)
TACTICS
Before Combat The reefclaws wait until the entire party
has entered the chamber or one of their foes has its back
turned before they attack, surrounding their enemies to
block the exit.
During Combat Silently drifting from the watery recesses of
the southernmost chamber, they pounce from the water
and grab their prey, attempting to drag creatures back
toward the water to drown them.
Morale The reefclaws fight to the death.
STATISTICS
Str 14, Dex 17, Con 18, Int 9, Wis 16, Cha 17
Base Atk +1; CMB +2 (+10 grapple); CMD 15 (can’t be tripped)
Feats Improved Initiative
Skills Perception +8, Swim +10
Languages Common (can’t speak)
SQ amphibious
SPECIAL ABILITIES
Death Frenzy (Su) See Subtier 1–2.
Grab (Ex) See Subtier 1–2.
Poison (Ex) Claw—injury; save Fort DC 15; frequency 1/round
for 4 rounds; effect 1d2 Str; cure 1 save. The save DC is
Constitution-based.

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

Re: Statblock2Token v1.8 ? I only see v1.6

Post by neofax »

I just made the token both with the 1.8 version and 1.9. Can you post your error?
Image
Time-Zone information UTC -5

DMFTodd
Cave Troll
Posts: 95
Joined: Mon Jun 29, 2009 11:17 pm

Re: Statblock2Token v1.8 ? I only see v1.6

Post by DMFTodd »

There's no error but when you hit "F2" for an attack, it asks "Value for Feats". Checking the token, the attack information is not there.

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

Re: Statblock2Token v1.8 ? I only see v1.6

Post by neofax »

I'll try it on the PC at work and see if I can get it working.
Image
Time-Zone information UTC -5

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

Re: Statblock2Token v1.8 ? I only see v1.6

Post by neofax »

I have no clue. The regular expression catches the claws attack, but for some reason it doesn't add it as a weapon. I am going to have to place debugging pauses in to see where it doesn't work. I won't be able to do this until tomorrow evening.
Image
Time-Zone information UTC -5

DMFTodd
Cave Troll
Posts: 95
Joined: Mon Jun 29, 2009 11:17 pm

Re: Statblock2Token v1.8 ? I only see v1.6

Post by DMFTodd »

It appears to be the word "and" in the attack's "plus grab and poison" that is confusing things. Remove the "and" and the 1.8 import works fine. Parser must be seeing "and" and thinking another attack is starting.

User avatar
Azhrei
Site Admin
Posts: 12086
Joined: Mon Jun 12, 2006 1:20 pm
Location: Tampa, FL

Re: Statblock2Token v1.8 ? I only see v1.6

Post by Azhrei »

I don't recall that RE off-hand, but the word "and" might be looking like a dice roll where the number of dice is "an" (since the letter "d" is how dice are rolled).

It seems unlikely though unless the RE is playing it fast-and-loose; I would typically use "\\dd" which would mean a digit followed by a "d"... Don't know if that's my RE creation or not...

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

Re: Statblock2Token v1.8 ? I only see v1.6

Post by JamzTheMan »

Am I doing something wrong or do the statBlock importers not handle CR properly?

Tried creating a rat, kobold, and orc and it set them all to level/cr 1. It doesn't seem to like CR < 1?
-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

DMFTodd
Cave Troll
Posts: 95
Joined: Mon Jun 29, 2009 11:17 pm

Re: Statblock2Token v1.8 ? I only see v1.6

Post by DMFTodd »

I don't think it does it. My imports have CR less than 1 wrong as well.

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

Re: Statblock2Token v1.8 ? I only see v1.6

Post by JamzTheMan »

I did some more importing last night and it looks like it just ignores CR completely, it looks like it grabs the HD, puts that in correctly, and then just leaves CR == 'Level'.

Maybe there is an option somewhere I'm missing? Just started to play with the framework this week and spent 2 hours messing with pits/traps before I figured out you had to use the Init Pads macro (which I thought was for TP pads only). There's SO much lol

May have to dive into that macro and take a peek...

BTW, does anyone know what the difference is between 1.6 and 1.8? I've tried both with PDF and d20pfrd site and tokens seem to come out the same so far.
-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: Statblock2Token v1.8 ? I only see v1.6

Post by neofax »

Skills with spaces in the name like Sleight of Hand. That is the difference between 1.6 and 1.8. Yes, the CR is ignored as the original author I assume didn't care to use the XP macro in the campaign.
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: Statblock2Token v1.8 ? I only see v1.6

Post by JamzTheMan »

OK, so where IS the latest version of this drop-in? I see a post of a .txt above and a copy/paste of code but not sure which one is the latest and some don't work quite right?

I've taken the 1.8 that was int the framework (latest!), which btw, also seems out of date with most of the drop-ins :(

I'm not complaining and love all the work, it's just taking me forever to cobble together the latest code everywhere for my new PF campaign...

If anyone needs the the correct parsing of CR, here's what I added:

Code: Select all

<!-- 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(statblock, "(?<=[ |\\t]CR )([1-9]+)(/[1-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)]
  }]
Complete macro code based on 1.8 in latest FW

Code: Select all

<!-- Statblock2Token v1.9
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))]

[H: status=input("statblock|Insert statblock here|Enter statblock|TEXT|WIDTH=40")]
[H: abort(if(status < 1, 0, 1))]

[H: setPropertyType("Pathfinder")]

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

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

<!-- 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(statblock, "(?<=[ |\\t]CR )([1-9]+)(/[1-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)]
  }]

[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, "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(statblock, "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="[R: max(Level, ( "+(HP-ConB*Level)+" + (ConB * Level) ) )]"]
  [HD=getGroup(id, 1, 2)]
  [Level = max(1,HD)]
  [output=output+"HP: "+HP+", HD: "+HD+"<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+", "]
  }]

<!-- 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, "(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(statblock, "Special Attacks (.+)(Statis|STATIS)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [SpecialATK=getGroup(id, 1, 1)]
  [SpecialATK=trim(SpecialATK)]
  [SpecialATK=substring(SpecialATK,0,min(length(SpecialATK),70))]
  [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)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [allmelee=getGroup(id, 1, 1)]
  <!-- 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)")]
[H, IF(0<getFindCount(id)), CODE:
  {
  [allranged=getGroup(id, 1, 1)]
  <!-- 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?\\s?[a-zA-Z ]+?) ([+-]\\d+)[/+\\-0-9\\s]*?\\((.+)\\)")]
  [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;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)]
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Damage", Damage)+ "'")]
    <!-- Two handed ? -->
    [eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 0)+ "'")] <!-- Default to onehanded weapon -->
    [id2 = strfind(atkstr, "(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 -->

[R,S,G: output]
-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&D 3.5/Pathfinder 1e Campaign Macros”