The New Way to Import Statblocks
Moderators: dorpond, trevor, Azhrei, giliath, Gamerdude, jay, Mr.Ice, lmarkus001
Forum rules
Discussion regarding lmarkus001's framework only. Other posts deleted without notice!
Discussion regarding lmarkus001's framework only. Other posts deleted without notice!
Re: The New Way to Import Statblocks
Hmm, I'll see what I can do to fix it. I've been busy with the holiday season.
Re: The New Way to Import Statblocks
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?
Re: The New Way to Import Statblocks
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.
- lmarkus001
- Great Wyrm
- Posts: 1867
- Joined: Sat Mar 29, 2008 12:30 am
- Location: Layfayette Hill, PA
Re: The New Way to Import Statblocks
Yeah neither this nor the 2.0 macro based importers seem to function. The v1.6 statblock2token macro works reasonably.
Re: The New Way to Import Statblocks
I have a version that I'm calling "1.8", probably because of some local modifications although I don't recall what they are.lmarkus001 wrote:Yeah neither this nor the 2.0 macro based importers seem to function. The v1.6 statblock2token macro works reasonably.
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...
Re: The New Way to Import Statblocks
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
I even tried version 4 but same error. Not sure what is wrong or if I am doing something wrong.
-Fred
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!
-Fred
Re: The New Way to Import Statblocks
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.Caraldur wrote:I keep getting a parse error every time I try to import a herolab stat block using the herolab v5 dll
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...
Re: The New Way to Import Statblocks
I tried remove the and and replacing it with a comma but still no luck. Below is the statblock I am using.
Here is the exact error message:
-Fred
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
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
Re: The New Way to Import Statblocks
Well, I didn't think that was likely to be the whole problem.Caraldur wrote:I tried remove the and and replacing it with a comma but still no luck.
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.
Re: The New Way to Import Statblocks
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.
Re: The New Way to Import Statblocks
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.)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.
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..."
Re: The New Way to Import Statblocks
Az, I would love to see this version, if you still want to shareAzhrei wrote:I have a version that I'm calling "1.8", probably because of some local modifications although I don't recall what they are.lmarkus001 wrote:Yeah neither this nor the 2.0 macro based importers seem to function. The v1.6 statblock2token macro works reasonably.
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...
Re: The New Way to Import Statblocks
Sorry, been reaaaallly busy. I'll try to find it when I get back to the hotel this evening.
Re: The New Way to Import Statblocks
No problem. Thank you!Azhrei wrote:Sorry, been reaaaallly busy. I'll try to find it when I get back to the hotel this evening.
Re: The New Way to Import Statblocks
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]