The New Way to Import Statblocks

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! :)
Imper1um
Cave Troll
Posts: 92
Joined: Mon Sep 28, 2009 7:46 am

Re: The New Way to Import Statblocks

Post by Imper1um »

Hmm, I'll see what I can do to fix it. I've been busy with the holiday season. :(

Jazlizard
Kobold
Posts: 22
Joined: Sun Jun 15, 2008 11:28 pm

Re: The New Way to Import Statblocks

Post by Jazlizard »

Yeah I have the same issue. Anyone have a working copy they can send me? Maybe there is something with the conversion to .msi installer?

mcbobbo
Kobold
Posts: 20
Joined: Wed Jul 21, 2010 11:26 pm

Re: The New Way to Import Statblocks

Post by mcbobbo »

I cannot seem to get either the importer or the exporter to show. The dll's will load, but that's all that I can make happen.

User avatar
lmarkus001
Great Wyrm
Posts: 1867
Joined: Sat Mar 29, 2008 12:30 am
Location: Layfayette Hill, PA

Re: The New Way to Import Statblocks

Post by lmarkus001 »

Yeah neither this nor the 2.0 macro based importers seem to function. The v1.6 statblock2token macro works reasonably.

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

Re: The New Way to Import Statblocks

Post by Azhrei »

lmarkus001 wrote:Yeah neither this nor the 2.0 macro based importers seem to function. The v1.6 statblock2token macro works reasonably.
I have a version that I'm calling "1.8", probably because of some local modifications although I don't recall what they are. :(

I think I fixed some of the skill name checks (the original didn't handle skill names with spaces like "Sense Motive" nor did it handle subskills like K(A) correctly). I think there was a fix to the weapon attacks as well.

I'll try to find my most recent version and post it to one of the D&D/PF threads to see if there's anything in there that people can use...

Caraldur
Kobold
Posts: 12
Joined: Tue Sep 02, 2008 9:52 am

Re: The New Way to Import Statblocks

Post by Caraldur »

I keep getting a parse error every time I try to import a herolab stat block using the herolab v5 dll

Here is the statblock I am trying to import

Code: Select all

BRAASHNAK	CR 1
Male Half-Orc Fighter (Polearm Master) 2
CN Medium Humanoid (Orc)
Init +2; Senses Darkvision (60 feet); Perception +1
--------------------
DEFENSE
--------------------
AC 16, touch 12, flat-footed 14   (+3 armor, +1 shield, +2 Dex)
hp 26 (2d10+4)
Fort +5, Ref +2, Will +1
--------------------
OFFENSE
--------------------
Spd 30 ft.
Melee Bite (Razortusk) +6 (1d4+6/20/x2) and
   Lucerne Hammer +6 (1d12+6/20/x2) and
   Shield, Light Steel +6 (1d3+4/20/x2) and
   Unarmed Strike +6 (1d3+4/20/x2)
Ranged Crossbow, Light +2 (1d8/19-20/x2)
Special Attacks Pole Fighting -4
--------------------
STATISTICS
--------------------
Str 18,  Dex 14,  Con 15,  Int 14,  Wis 13,  Cha 14
Base Atk +2; CMB +6; CMD 18
Feats Improved Unarmed Strike, Intimidating Prowess, Razortusk
Traits Adopted, Boarded In Cheliax, World Traveler: Sense Motive
Skills Acrobatics +0, Climb +8, Escape Artist +0, Fly +0, Handle Animal +6, Intimidate +13, Knowledge: Nature +3, Ride +0, Sense Motive +6, Stealth +0, Survival +5, Swim +6
Languages Abyssal, Common, Giant, Orc
SQ Orc Ferocity (1/day), Ram, portable
Combat Gear Studded Leather, Shield, Light Steel, Lucerne Hammer, Crossbow, Light, Bolts, Crossbow (20); Other Gear Backpack (empty), Bedroll, Blanket, Climber's kit, Flint and steel, Oil (1-pint flask), Ram, portable, Rope, hempen (50 ft.), Saw, Torch, Waterskin
--------------------
SPECIAL ABILITIES
--------------------
Boarded In Cheliax +2 Knowledge (Geography) in the Mwangi Expanse.
Darkvision (60 feet) You can see in the dark (black and white vision only).
Improved Unarmed Strike Unarmed strikes don't cause attacks of opportunity, and can be lethal.
Orc Ferocity (1/day) 1/day, when brought below 0 HP but not killed, you can fight on for 1 more round as if disabled.  The next round, unless brought to at least 0 HP, you immediately fall unconscious and begin dying.
Pole Fighting -4 (Ex) Use a spear or polearm against adjacent targets with a -4 penalty.
Ram, portable +2 to STR checks to break open a door, and allows a second helper (+2).

Created With Hero Lab® - try it for free at http://www.wolflair.com!
I even tried version 4 but same error. Not sure what is wrong or if I am doing something wrong.

-Fred

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

Re: The New Way to Import Statblocks

Post by Azhrei »

Caraldur wrote:I keep getting a parse error every time I try to import a herolab stat block using the herolab v5 dll
I doubt this is related, but that build is wrong. The statblock uses the word "and" between weapon entries and it should be using a comma.

The word "and" means that multiple attacks are allowed (such as "bite and claws") while a comma indicates multiple different attacks that are not part of the same attack routine (such as "longsword, shortsword, sling").

I seriously doubt that the statblock reader is being that persnickety about it (hm, good word!) but I figured I'd mention it anyway...

Caraldur
Kobold
Posts: 12
Joined: Tue Sep 02, 2008 9:52 am

Re: The New Way to Import Statblocks

Post by Caraldur »

I tried remove the and and replacing it with a comma but still no luck. Below is the statblock I am using.

Code: Select all

BRAASHNAK   CR 1
Male Half-Orc Fighter (Polearm Master) 2
CN Medium Humanoid (Orc)
Init +2; Senses Darkvision (60 feet); Perception +1
--------------------
DEFENSE
--------------------
AC 16, touch 12, flat-footed 14   (+3 armor, +1 shield, +2 Dex)
hp 26 (2d10+4)
Fort +5, Ref +2, Will +1
--------------------
OFFENSE
--------------------
Spd 30 ft.
Melee Bite (Razortusk) +6 (1d4+6/20/x2), Lucerne Hammer +6 (1d12+6/20/x2)
--------------------
STATISTICS
--------------------
Str 18,  Dex 14,  Con 15,  Int 14,  Wis 13,  Cha 14
Base Atk +2; CMB +6; CMD 18
Feats Improved Unarmed Strike, Intimidating Prowess, Razortusk
Traits Adopted, Boarded In Cheliax, World Traveler: Sense Motive
Skills Acrobatics +0, Climb +8, Escape Artist +0, Fly +0, Handle Animal +6, Intimidate +13, Knowledge: Nature +3, Ride +0, Sense Motive +6, Stealth +0, Survival +5, Swim +6
Languages Abyssal, Common, Giant, Orc
Here is the exact error message:

Code: Select all

System.MissingMethodException: Method not found: 'Void 
Bridge.Base.Constructs.Character.set_Current(Int32)'.
	at Pathfinder.Base.Importer.PFStatBlockImporter.Convert(String input)
	at Bridge.Base.Converter.StatblockConverter`1.ConvertStatblock(String input)
	at Bridge.UI.ImportStatblock.buttonCreate_Click(Object sender, 
RoutedEventArgs e) in C:\Users\zsylvestre\Documents\Visual Studio 2010
\Projects\CharacterBridge\Bridge.UI\UI\ImportStatblock.xaml/cs/line 95
-Fred

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

Re: The New Way to Import Statblocks

Post by Azhrei »

Caraldur wrote:I tried remove the and and replacing it with a comma but still no luck.
Well, I didn't think that was likely to be the whole problem.

And I don't do Windows, but that error looks like there's a DLL or other system library missing. Make sure you're running an updated .NET environment.

Voltang
Cave Troll
Posts: 88
Joined: Wed Dec 03, 2008 5:13 pm

Re: The New Way to Import Statblocks

Post by Voltang »

Any advice on how best to make use of this in Ubuntu Linux? I was going to they Virtualbox first, but if there's a way to port directly into Linux, that would be awesome.

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

Re: The New Way to Import Statblocks

Post by Azhrei »

Voltang wrote:Any advice on how best to make use of this in Ubuntu Linux? I was going to they Virtualbox first, but if there's a way to port directly into Linux, that would be awesome.
Well, there's the Mono project. But it's not a 100% clone of the C# runtime environment though. (The compiler and core libraries work, but the WSF isn't completely implemented, IIRC.)

I never understood why single-platform languages become popular. :? I suppose it's an example of the saying, "If all you have is a hammer..."

Elorebaen
Dragon
Posts: 365
Joined: Sat Dec 22, 2007 5:37 pm

Re: The New Way to Import Statblocks

Post by Elorebaen »

Azhrei wrote:
lmarkus001 wrote:Yeah neither this nor the 2.0 macro based importers seem to function. The v1.6 statblock2token macro works reasonably.
I have a version that I'm calling "1.8", probably because of some local modifications although I don't recall what they are. :(

I think I fixed some of the skill name checks (the original didn't handle skill names with spaces like "Sense Motive" nor did it handle subskills like K(A) correctly). I think there was a fix to the weapon attacks as well.

I'll try to find my most recent version and post it to one of the D&D/PF threads to see if there's anything in there that people can use...
Az, I would love to see this version, if you still want to share :)

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

Re: The New Way to Import Statblocks

Post by Azhrei »

Sorry, been reaaaallly busy. I'll try to find it when I get back to the hotel this evening.

Elorebaen
Dragon
Posts: 365
Joined: Sat Dec 22, 2007 5:37 pm

Re: The New Way to Import Statblocks

Post by Elorebaen »

Azhrei wrote:Sorry, been reaaaallly busy. I'll try to find it when I get back to the hotel this evening.
No problem. Thank you!

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

Re: The New Way to Import Statblocks

Post by neofax »

Well, I seem to have stumbled upon the mystical Azhrei version 1.8 of the Statblock2Token. Here it is in it's entirety:

Code: Select all

<!-- Statblock2Token v1.8
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=""]
[H: id = strfind(statblock, "^(.+).*CR ")]
[H, IF(0<getFindCount(id)),CODE:
  { 
  [name=getGroup(id, 1, 1)]
  [output="Name: "+name+", "]
  [Race =  json.set(Race, "name", name)]
  [setName( name)]
   }]


[H: id = strfind(statblock, "(Fine|Diminiutive|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 -->

Token Updated:<br>[R,S,G: output]

Post Reply

Return to “D&D 3.5/Pathfinder 1e Campaign Macros”