RPTools.net

Discussion and Support

Skip to content

It is currently Thu Oct 19, 2017 1:28 pm 




Forum rules


Discussion regarding lmarkus001's framework only. Other posts deleted without notice! :)



Reply to topic  [ 50 posts ]  Go to page Previous  1, 2, 3, 4  Next

Previous topic | Next topic 

  Print view

Author Message
User avatar  Offline
Deity
 
Joined: Tue Nov 10, 2009 6:11 pm
Posts: 7885
Location: Bay Area
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Wed Aug 26, 2015 2:04 pm 
Which output, casting a spell?

_________________
Downloads:


Top
 Profile  
 
User avatar  Offline
Great Wyrm
 
Joined: Fri Mar 28, 2008 11:30 pm
Posts: 1866
Location: Layfayette Hill, PA
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Wed Aug 26, 2015 3:00 pm 
Yeah, output.basic. I am going to resolve that now.

It is a Mote bug around isGM(). I am reporting it.

_________________
D&D3.5 / Pathfinder Framework


Top
 Profile  
 
User avatar  Offline
Deity
 
Joined: Tue Nov 10, 2009 6:11 pm
Posts: 7885
Location: Bay Area
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Wed Aug 26, 2015 3:51 pm 
lmarkus001 wrote:
Yeah, output.basic. I am going to resolve that now.

It is a Mote bug around isGM(). I am reporting it.


Ah, I think that was an MT change after their port. I have a better solution.

REMOVE
Code:
[H: players.gm = "[]"]
[H, foreach(player,players.all), if(isGM(player)): players.gm = json.append(players.gm,player)]

ADD IN ITS PLACE
Code:
[H: players.gm = json.get(getInfo("server"),"gm")]


This too was a change after their port, but I recall discussion on one of their forums about adding this. This will only work in MT b91 or later though. I'm not sure if they kept the same function name or changed it to one of their other naming conventions.

_________________
Downloads:


Top
 Profile  
 
User avatar  Offline
Great Wyrm
 
Joined: Fri Mar 28, 2008 11:30 pm
Posts: 1866
Location: Layfayette Hill, PA
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Wed Aug 26, 2015 5:06 pm 
Nice thought, but the Mote getInfo() reports differently...


So here is my near term workaround where I do version checking and use isGM() on MT and getGMNames() on Mote. Next Mote version will include isGM() functionality :-)

Code:
[H: info        = getInfo("client")]
[
H: mtVersion    = json.get(info, "version")]
[
h: id        = strfind(mtVersion, ".+\\.(.+)\\.[A-z]*([0-9]+)[A-z]*")]
[
H: mtMainVerNr    = getGroup(id, 1, 1)]
[
H: mtVersionNr    = getGroup(id, 1, 2)]

<!--
 validate token is on current map -->
[
H: tokenId = findToken(token)]
[
H, if(! json.isEmpty(tokenId)), code: {
   [H: tokenName = getName(tokenId)]
   [H: tokenImage = getImage(tokenName)]
};{}]

<!--
 parse list of targets in to list of players names -->
[
H, if(json.type(targets) == "UNKNOWN"): targets = json.fromList(targets)]

<!--
 get player groups -->
[
H: players.all = getAllPlayerNames("json")]

[
H,IF(mtVersionNr>88),CODE: {
    [H: players.gm = "[]"]
    [H, foreach(player,players.all), if(isGM(player)): players.gm = json.append(players.gm,player);""]    
};{
    [H: players.gm = getGMNames("json")]
}]
 


Libspells3.rptok [549.52 KiB]
Downloaded 49 times

_________________
D&D3.5 / Pathfinder Framework
Top
 Profile  
 
User avatar  Offline
Deity
 
Joined: Tue Nov 10, 2009 6:11 pm
Posts: 7885
Location: Bay Area
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Wed Aug 26, 2015 6:23 pm 
Maybe we can skip the longer version checking with this:

Code:
...
<!--
 get player groups -->
[
H: isMT = json.contains(json.fields(getInfo("server"),"json"),"gm")]
[
H, if(isMT): players.gm = json.get(getInfo("server"),"gm"); players.gm = getGMNames("json")]
[
H: players.all = getAllPlayerNames("json")]
[
H: player.self = json.append("",getPlayerName())]
...
 

It accomplishes the same thing, but has the same flaw of when "gm" doesn't exist it will call a function that doesn't exist. We already know it's a pain in the behind to get gm Names before b89(?) so I'll just leave this as an incompatibility with versions.

_________________
Downloads:


Top
 Profile  
 
User avatar  Offline
Deity
 
Joined: Tue Nov 10, 2009 6:11 pm
Posts: 7885
Location: Bay Area
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Sun Aug 30, 2015 6:58 pm 
I just found a mistake (oversight) with the template fix. When counting spells, I only counted the number of different spells rather than the number memorized. This only matter if you're a prep caster and you memorized duplicates. It will wrongly show you have an extra spell(s) to memorize. I'll fix this tomorrow.

_________________
Downloads:


Top
 Profile  
 
User avatar  Offline
Great Wyrm
 
Joined: Fri Mar 28, 2008 11:30 pm
Posts: 1866
Location: Layfayette Hill, PA
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Mon Aug 31, 2015 12:16 pm 
Here is the output.basic version check I am now using...

Code:
[HclientType json.get(getInfo("client"),"name")]
[
Hplayers.gm "[]"]
[
H, if(clientType=="Mote"), CODE: {
    [ 
players.gm getGMNames() ]
};{
    [
H, foreach(player,players.all), if(isGM(player)): players.gm json.append(players.gm,player);""]
}] 

_________________
D&D3.5 / Pathfinder Framework


Top
 Profile  
 
User avatar  Offline
Deity
 
Joined: Tue Nov 10, 2009 6:11 pm
Posts: 7885
Location: Bay Area
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Mon Aug 31, 2015 12:32 pm 
isGM(player) and json.get(getInfo("server"),"gm") were implemented at the same time so there's no advantage as far as version-ing goes, but I personally like getting a single value over running a loop. So, it's just apples and oranges at this point and they accomplish the same thing. I also try to avoid the double roll option which is an MT quirk that MOTE gave in and implemented by prioritizing left to right when running the roll options.

_________________
Downloads:


Top
 Profile  
 
User avatar  Offline
Great Wyrm
 
Joined: Fri Mar 28, 2008 11:30 pm
Posts: 1866
Location: Layfayette Hill, PA
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Mon Aug 31, 2015 3:07 pm 
The isGM("player") was broken as implemented in Mote (hence my alternate code). They just repaired it today :-)

_________________
D&D3.5 / Pathfinder Framework


Top
 Profile  
 
User avatar  Offline
Deity
 
Joined: Tue Nov 10, 2009 6:11 pm
Posts: 7885
Location: Bay Area
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Tue Sep 01, 2015 10:26 pm 
More updates to lib:spells3

Quote:
(9-1-15)
* Fixed Local Cheating when there is more than one spell casting class.
* Fixed template restore to include correct remainder of spells when prep casters memorize the same spell more than once.
* Fixed ability score mod when ability changes between levels. Re-calcs on Rest now.
* Fixed formula for calculating SPD so it uses class base for that level + ability adjustment.
* Added spells known per level for Oracle (don't know why this was blank)


The recalc of SPD on rest was needed for ability adjustments between levels, but this means if you usually have an abnormal number of spell per day from the class and you change it under local cheating, then you're going not want to do that because of the reset on rest. You will want to make new class and adjust the SPD there. Pain in the behind either way. I may, if there is demand put in an SPD modifier that you can edit. I know there are some classes where you get -1 SPD each level.


Lib_spells3 9-1-15.rptok [548.45 KiB]
Downloaded 57 times

_________________
Downloads:
Top
 Profile  
 
User avatar  Offline
Great Wyrm
 
Joined: Fri Mar 28, 2008 11:30 pm
Posts: 1866
Location: Layfayette Hill, PA
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (8-15-15)
PostPosted: Wed Sep 02, 2015 12:17 pm 
aliasmask wrote:
More updates to lib:spells3

Quote:
(9-1-15)
...
* Added spells known per level for Oracle (don't know why this was blank)

...


So you did not make your changes off of my updated token where there are a lot of class and list updates. Any list of macros modified for your token? That way I can just apply those and avoid another data massage...

_________________
D&D3.5 / Pathfinder Framework


Top
 Profile  
 
User avatar  Offline
Deity
 
Joined: Tue Nov 10, 2009 6:11 pm
Posts: 7885
Location: Bay Area
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (9-1-15)
PostPosted: Wed Sep 02, 2015 1:25 pm 
I did actually use your token. After I did a quick code comparison to make sure we were matched up, I then started using your token as a base for modding. You'll notice the druid_storm in class list which is something I didn't have before. I just remade the oracle by making a new one, using the cleric list and setting the spd and spell known to sorcerer.

_________________
Downloads:


Top
 Profile  
 
User avatar  Offline
Deity
 
Joined: Tue Nov 10, 2009 6:11 pm
Posts: 7885
Location: Bay Area
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (9-1-15)
PostPosted: Wed Sep 02, 2015 1:34 pm 
Let's see I updated:
* Rest Start
* Ability Adjustments
* Tweak Token
* Restore Template

I think that's it.

_________________
Downloads:


Top
 Profile  
 
User avatar  Offline
Great Wyrm
 
Joined: Fri Mar 28, 2008 11:30 pm
Posts: 1866
Location: Layfayette Hill, PA
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (9-1-15)
PostPosted: Tue Sep 08, 2015 10:10 am 
Yep I spoke too soon, lookin good!

_________________
D&D3.5 / Pathfinder Framework


Top
 Profile  
 
User avatar  Offline
Deity
 
Joined: Tue Nov 10, 2009 6:11 pm
Posts: 7885
Location: Bay Area
 Post subject: Re: [AM Macros] Lindsay's PF/3.5 Campaign FW (9-1-15)
PostPosted: Thu Oct 29, 2015 4:25 pm 
Update to pfStatBlockImport

AM (v2.0.5): Fixed Speed when "Spd" is used. Puts blank for XP when not in stat block instead of error. Fixed init/senses line error. (updated)

Lib:libDnD35Pathfinder wrote:
Code:
@@ @pfStatBlockImport
<!-- Statblock2Token v2.0.4 (3-15-15)
   Statblock2Token v2.0.4 (10-29-15)
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
LGM: Corrected vulnerability, Added Feats
AM (v2.0.3): fixed hp each; name get; default sight off; valid ulnerability check; made UDF; output change
AM (v2.0.4): fixed stat sheet input error (infinite loop on mouse over)
AM (v2.0.5): Fixed Speed when "Spd" is used. Puts blank for XP when not in stat block instead of error. Fixed init/senses line error.
-->
[H: ids = getSelected()]
[H: abort(if(ids == "", 0, 1))]

[H: status=input("junk|Statblock info from Creature Name through Treasure line of Ecology (if it exists). Don't include flavor text/background/descriptions.||LABEL|SPAN=TRUE","junk|If Ecology section comes before Special Abilities, be sure to include Special Abilities section as well. Still no flavor text.||LABEL|SPAN=TRUE","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)]
}]

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

<!-- change brackets and braces to parens to avoid stat sheet variable input error -->
[H: statblock = replace(statblock, "[\\[\\{]","(")]
[H: statblock = replace(statblock, "[\\]\\}]",")")]

<!-- Start formatting imported statblock and set it to GM notes -->

<!-- If Ecology section comes before Special Abilities, cut it out and put it last. If the Ecology section doesn't exist, create a blank one last -->
[H: EcologyThenSAbSearch = strfind(statblock, "(?i)(ECOLOGY)(.*?)(Special Abilities)")]
[H, IF(0<getFindCount(EcologythenSAbSearch)), CODE: {
   [IF(getGroup(EcologyThenSAbSearch, 1, 3) == "special abilities" || getGroup(EcologyThenSAbSearch, 1, 3) == "Special Abilities" || getGroup(EcologyThenSAbSearch, 1, 3) == "Special abilities" || getGroup(EcologyThenSAbSearch, 1, 3) == "SPECIAL ABILITIES"), CODE: {
      [EcologyString = getGroup(EcologyThenSAbSearch, 1, 0)]
      [statblock = replace(statblock, "(?i)((ECOLOGY)(.*?))((Special Abilities)(.*))", "\$4  \$1" )]
      [EcologySearch = strfind(statblock, "(?i)(ECOLOGY)(.*)")]
   };{
   }]
};{
   [EcologySearch = strfind(statblock, "(?i)(ECOLOGY)(.*)")]
   [IF(0<getFindCount(EcologySearch)), CODE: {
      [statblock = statblock]
   };{
      [statblock = statblock + " ECOLOGY "]
      [EcologySearch = strfind(statblock, "(?i)(ECOLOGY)(.*)")]
   }]
}]

<!-- Search for lines and sections of statblock individually -->
[H: NameSearch = strfind(statblock, "(.*?)CR")]
[H: CRSearch = strfind(statblock, "(CR ?[0-9]+(/[0-9]+)?)")]
[H: XPSearch = strfind(statblock, "(XP [0-9,]+)")]
[H: GenderEtcSearch = strfind(statblock, "(?i)XP [0-9,]+ ([a-z ,0-9]*)( LG | LN | LE | NG | N | NE | CG | CN | CE )")]
[H: AlignmentSizeRaceSearch = strfind(statblock, "(?i)(( LG | LN | LE | NG | N | NE | CG | CN | CE ).*?)Init")]
[H: InitSensesSearch = strfind(statblock, "(?i)(Init.*?) +(Aura|DEFENSE|Weakness)")]
[H: AuraSearch = strfind(statblock, "(?i)(Aura.*?) DEFENSE")]
[H: ACStringSearch = strfind(statblock, "(?i)(AC [0-9].*?\\)) +HP")]
[H: HPStringSearch = strfind(statblock, "(?i)((HP) .*?)Fort ")]
[H: SavesSearch = strfind(statblock, "(?i)(Fort (.*?))(Defensive Abilit|DR [0-9]|Immune|Resist|SR|Weakness|OFFENSE)")]
[H: DefensiveAbilitiesSearch = strfind(statblock, "(?i)((Defensive Abilities|Defensive Ability|DR |Immune|Resist|SR)(.*?))(Weakness|OFFENSE)")]
[H: WeaknessesSearch = strfind(statblock, "(?i)(Weaknesse?s?(.*?))(DEFENSE|OFFENSE)")]
[H: SpeedSearch = strfind(statblock, "(?i)((Speed|Spd) (.+?))(Melee|Ranged|Tactic|Space|Reach|Special|Ranged|Stat|Spell)")]
[H: MeleeSearch = strfind(statblock, "(?i)(Melee (.+?))(Tactic|Space|Reach|Special|Ranged|Stat|Spell)")]
[H: RangedSearch = strfind(statblock, "(?i)(Ranged (.+?))(Tactic|Space|Reach|Special|Stat|Spell)")]
[H: SpaceReachSearch = strfind(statblock, "(?i)((Space|Reach)(.*?))(Tactic|Special|Stat|Spell)")]
[H: SpecialAttackSearch = strfind(statblock, "(?i)(Special Attacks?(.*?))(Tactic|Stat|Spell)")]
[H: SpellLikeSearch = strfind(statblock,  "(?i)((Arcane School |Gnome |Domain |Bloodline |Hellknight |Transmuter |Paladin |Cleric |Conjurer |Enchanter |Evoker |Necromancer |Arcane )?Spell-Like Abilities (.*?))(?=(Alchemist|Antipaladin|Bard|Cleric|Oracle|Druid|Inquisitor|Magus|Paladin|Ranger|Sorcerer|Wizard|Summoner|Witch|Arcane School|Gnome|Domain|Bloodline|Hellknight|Arcane|Abjurer|Conjurer|Diviner|Enchanter|Evoker|Illusionist|Necromancer|Transmuter|Tactic|Face|Stat|Spell))")]
[H: SpellsKnownSearch = strfind(statblock, "(?i)((Alchemist|Antipaladin|Bard|Cleric|Oracle|Druid|Inquisitor|Magus|Paladin|Ranger|Sorcerer|Wizard|Summoner|Witch|Abjurer|Conjurer|Diviner|Enchanter|Evoker|Illusionist|Necromancer|Transmuter)? ?Spells Known(.*?))(?=(Alchemist|Antipaladin|Bard|Cleric|Oracle|Druid|Inquisitor|Magus|Paladin|Ranger|Sorcerer|Wizard|Summoner|Witch|Abjurer|Conjurer|Diviner|Enchanter|Evoker|Illusionist|Necromancer|Transmuter|Tactic|Stat|Spells))")]
[H: SpellsPreparedSearch = strfind(statblock, "(?i)((Alchemist|Antipaladin|Bard|Cleric|Oracle|Druid|Inquisitor|Magus|Paladin|Ranger|Sorcerer|Wizard|Summoner|Witch|Abjurer|Conjurer|Diviner|Enchanter|Evoker|Illusionist|Necromancer|Transmuter)? ?Spells Prepared(.*?))(?=(Alchemist|Antipaladin|Bard|Cleric|Oracle|Druid|Inquisitor|Magus|Paladin|Ranger|Sorcerer|Wizard|Summoner|Witch|Abjurer|Conjurer|Diviner|Enchanter|Evoker|Illusionist|Necromancer|Transmuter|Tactic|Stat|Spells))")]
[H: TacticsSearch = strfind(statblock, "(?i)TACTICS(.*?)(?<!base )(?:STATISTICS)")]
[H: StatisticsSearch = strfind(statblock, "(?i)(base statistics)?.*?Statistics.*?(Str (.*?))Base Atk")]
[H: BaseAtkSearch = strfind(statblock, "(?i)(base statistics)?.*?Statistics.*?(Base Atk (.*?))(Feats|Skills|Languages|SQ|Combat Gear|Other Gear|Gear|SPECIAL|ECOLOGY)")]
[H: FeatsSearch = strfind(statblock, "(?i)(base statistics)?.*?Statistics.*?(Feats (.*?))(Skills|Languages|SQ|Combat Gear|Other Gear|Gear|SPECIAL|ECOLOGY)")]
[H: SkillsSearch = strfind(statblock, "(?i)(base statistics)?.*?Statistics.*?(Skills (.*?))(Languages|SQ|Combat Gear|Other Gear|Gear|SPECIAL|ECOLOGY)")]
[H: LanguagesSearch = strfind(statblock, "(?i)(base statistics)?.*?Statistics.*?(Languages? (.*?))(SQ|Combat Gear|Other Gear|Gear|SPECIAL|ECOLOGY)")]
[H: SQSearch = strfind(statblock, "(?i)(base statistics)?.*?Statistics.*?(SQ (.*?))(Combat Gear|Other Gear|Gear|SPECIAL|ECOLOGY)")]
[H: GearSearch = strfind(statblock, "(?i)(base statistics)?.*?Statistics.*?((Combat )?Gear (.*?))(BASE STATISTICS|SPECIAL|ECOLOGY) ")]
[H: BaseStatisticsSearch = strfind(statblock, "(?i)(Base Statistics.*?)(STATISTICS.*?Str [0-9]|SPECIAL ABILITIES|ECOLOGY)")]
[H: SpecialAbilitiesSearch = strfind(statblock, "(?i)(SPECIAL ABILITIES)(.*?)(ECOLOGY)")]

<!-- If the line or section exists, put it in a variable and give it a line break before it -->
[H, IF(0<getFindCount(GenderEtcSearch)), CODE: {
   [GenderEtcNote = "
" + trim(getGroup(GenderEtcSearch, 1, 1))]
};{
   [GenderEtcNote = ""]
}]

[H, IF(0<getFindCount(AuraSearch)), CODE: {
   [AuraNote = "
" + trim(getGroup(AuraSearch, 1, 1))]
};{
   [AuraNote = ""]
}]

[H, IF(0<getFindCount(DefensiveAbilitiesSearch)), CODE: {
   [DANote = "
" + trim(getGroup(DefensiveAbilitiesSearch, 1, 1))]
};{
   [DANote = ""]
}]

[H, IF(0<getFindCount(WeaknessesSearch)), CODE: {
   [WeaknessNote = "
" + trim(getGroup(WeaknessesSearch, 1, 1))]
};{
   [WeaknessNote = ""]
}]

[H, IF(0<getFindCount(MeleeSearch)), CODE: {
   [MeleeNote = "
" + trim(getGroup(MeleeSearch, 1, 1))]
};{
   [MeleeNote = ""]
}]

[H, IF(0<getFindCount(RangedSearch)), CODE: {
   [RangedNote = "
" + trim(getGroup(RangedSearch, 1, 1))]
};{
   [RangedNote = ""]
}]

[H, IF(0<getFindCount(SpaceReachSearch)), CODE: {
   [SpaceReachNote = "
" + trim(getGroup(SpaceReachSearch, 1, 1))]
};{
   [SpaceReachNote = ""]
}]

[H, IF(0<getFindCount(SpecialAttackSearch)), CODE: {
   [SANote = "
" + trim(getGroup(SpecialAttackSearch, 1, 1))]
};{
   [SANote = ""]
}]

<!-- If a Spell-Like Abilities section exists, break it up into subsections based on constant/at will/or # per day. Multiple Spell-Like sections may exist from different sources, so create a section for each -->
[H: SLNote = ""]
[H, IF(0<getFindCount(SpellLikeSearch)), FOR(NumSpellLikeTypes, 1, getFindCount(SpellLikeSearch)+1), CODE: {
   [SpellLikeString = getGroup(SpellLikeSearch, NumSpellLikeTypes, 1)]
   [SpellLikeHeaderSearch = strfind(SpellLikeString, "(?i)(.*?)(Constant|At[ -]Will|[0-9]+/day)")]
   [ConstantSearch = strfind(SpellLikeString, "(?i)((Constant)(.*?))(At[ -]Will|[0-9]+/day)")]
   [IF(1>getFindCount(ConstantSearch)): ConstantSearch = strfind(SpellLikeString, "(?i)((Constant)(.*))")]
   [AtWillSearch = strfind(SpellLikeString, "(?i)((At[ -]Will)(.*?))([0-9]+/day)")]
   [IF(1>getFindCount(AtWillSearch)): AtWillSearch = strfind(SpellLikeString, "(?i)((At[ -]Will)(.*))")]
   [PerDayStringSearch = strfind(SpellLikeString, "(?i)(([0-9]+/day)(.*))")]
   [IF(0<getFindCount(PerDayStringSearch)): PerDayString = getGroup(PerDayStringSearch, 1, 1); PerDayString = ""]
   [PerDayTypesSearch = strfind(PerDayString, "(?i)(([0-9]+/day)(.*?))(?=([0-9]+/day))")]
   [PerDayAbilities = ""]
   [IF(0<getFindCount(PerDayTypesSearch)), FOR(DifferentPerDays, 1, getFindCount(PerDayTypesSearch)+1), CODE: {
      [PerDayString = replace(PerDayString, "(?i)([0-9]+/day(.*?))(?=([0-9]+/day))", "")]
      [ThisPerDay = trim(getGroup(PerDayTypesSearch, DifferentPerDays, 1))]
      [PerDayAbilities = PerDayAbilities + "
   " + ThisPerDay]
   }]
   [IF(PerDayString != ""): PerDayAbilities = PerDayAbilities + "
   " + trim(PerDayString)]
   [IF(0<getFindCount(SpellLikeHeaderSearch)): SpellLikeHeader = "

" + trim(getGroup(SpellLikeHeaderSearch, 1, 1)); SpellLikeHeader = "" ]
   [IF(0<getFindCount(ConstantSearch)), CODE: {
      [ConstantAbilities = "
   " + trim(getGroup(ConstantSearch, 1, 1))]
   };{
      [ConstantAbilities = ""]
   }]
   [IF(0<getFindCount(AtWillSearch)), CODE: {
      [AtWillAbilities = "
   " + trim(getGroup(AtWillSearch, 1, 1))]
   };{
      [AtWillAbilities = ""]
   }]
   [SLNote = SLNote + SpellLikeHeader + ConstantAbilities + AtWillAbilities + PerDayAbilities]
};{
   [SLNote = ""]
}]

<!-- If a Spells Known section exists, break it up into subsections based on spell level. Multiple Spells Known sections may exist from different sources, so create a section for each -->
[SKNote = ""]
[H, IF(0<getFindCount(SpellsKnownSearch)), FOR(NumSpellClasses, 1, getFindCount(SpellsKnownSearch)+1), CODE: {
   [ThisSpellClass = getGroup(SpellsKnownSearch, NumSpellClasses, 1)]
   [SpellsKnownHeaderSearch = strfind(ThisSpellClass, "(?i)(.*?\\)) +(9th|8th|7th|6th|5th|4th|3rd|2nd|1st|0 \\(|0th \\()")]
   [NinthLevelSearch = strfind(ThisSpellClass, "(?i)((9th)(.*?))(8th)")]
   [EighthLevelSearch = strfind(ThisSpellClass, "(?i)((8th)(.*?))(7th)")]
   [SeventhLevelSearch = strfind(ThisSpellClass, "(?i)((7th)(.*?))(6th)")]
   [SixthLevelSearch = strfind(ThisSpellClass, "(?i)((6th)(.*?))(5th)")]
   [FifthLevelSearch = strfind(ThisSpellClass, "(?i)((5th)(.*?))(4th)")]
   [FourthLevelSearch = strfind(ThisSpellClass, "(?i)((4th)(.*?))(3rd)")]
   [ThirdLevelSearch = strfind(ThisSpellClass, "(?i)((3rd)(.*?))(2nd)")]
   [SecondLevelSearch = strfind(ThisSpellClass, "(?i)((2nd)(.*?))(1st)")]
   [FirstLevelSearch = strfind(ThisSpellClass, "(?i)((1st)(.*?))(0 \\(|0th \\()")]
   [ThisClassSpecialSearch = strfind(ThisSpellClass, "(?i)((D Domain|Bloodline|Domain|Mystery|Opposition School|Prohibited School)(.*))")]
   [IF(0<getFindCount(ThisClassSpecialSearch)): ZerothLevelSearch = strfind(ThisSpellClass, "(?i)((0 \\(|0th \\()(.*?))(D Domain|Bloodline|Domain|Mystery|Opposition School|Prohibited School)"); ZerothLevelSearch = strfind(ThisSpellClass, "((0 \\(|0th \\()(.*))")]
   [IF(0<getFindCount(SpellsKnownHeaderSearch)): SpellsKnownHeader = "

" + trim(getGroup(SpellsKnownHeaderSearch, 1, 1)); SpellsKnownHeader = ""]
   [IF(0<getFindCount(NinthLevelSearch)), CODE: {
      [NinthLevel = "
   " + trim(getGroup(NinthLevelSearch, 1, 1))]
   };{
      [NinthLevel = ""]
   }]
   [IF(0<getFindCount(EighthLevelSearch)), CODE: {
      [EighthLevel = "
   " + trim(getGroup(EighthLevelSearch, 1, 1))]
   };{
      [EighthLevel = ""]
   }]
   [IF(0<getFindCount(SeventhLevelSearch)), CODE: {
      [SeventhLevel = "
   " + trim(getGroup(SeventhLevelSearch, 1, 1))]
   };{
      [SeventhLevel = ""]
   }]
   [IF(0<getFindCount(SixthLevelSearch)), CODE: {
      [SixthLevel = "
   " + trim(getGroup(SixthLevelSearch, 1, 1))]
   };{
      [SixthLevel = ""]
   }]
   [IF(0<getFindCount(FifthLevelSearch)), CODE: {
      [FifthLevel = "
   " + trim(getGroup(FifthLevelSearch, 1, 1))]
   };{
      [FifthLevel = ""]
   }]
   [IF(0<getFindCount(FourthLevelSearch)), CODE: {
      [FourthLevel = "
   " + trim(getGroup(FourthLevelSearch, 1, 1))]
   };{
      [FourthLevel = ""]
   }]
   [IF(0<getFindCount(ThirdLevelSearch)), CODE: {
      [ThirdLevel = "
   " + trim(getGroup(ThirdLevelSearch, 1, 1))]
   };{
      [ThirdLevel = ""]
   }]
   [IF(0<getFindCount(SecondLevelSearch)), CODE: {
      [SecondLevel = "
   " + trim(getGroup(SecondLevelSearch, 1, 1))]
   };{
      [SecondLevel = ""]
   }]
   [IF(0<getFindCount(FirstLevelSearch)), CODE: {
      [FirstLevel = "
   " + trim(getGroup(FirstLevelSearch, 1, 1))]
   };{
      [FirstLevel = ""]
   }]
   [IF(0<getFindCount(ZerothLevelSearch)), CODE: {
      [ZerothLevel = "
   " + trim(getGroup(ZerothLevelSearch, 1, 1))]
   };{
      [ZerothLevel = ""]
   }]
   [IF(0<getFindCount(ThisClassSpecialSearch)), CODE: {
      [ThisClassSpecial = "
   " + trim(getGroup(ThisClassSpecialSearch, 1, 1))]
   };{
      [ThisClassSpecial = ""]
   }]
   [SKNote = SKNote + SpellsKnownHeader + NinthLevel + EighthLevel + SeventhLevel + SixthLevel + FifthLevel + FourthLevel + ThirdLevel + SecondLevel + FirstLevel + ZerothLevel + ThisClassSpecial]
};{
   [SKNote = ""]
}]

<!-- If a Spells Prepared section exists, break it up into subsections based on spell level. Multiple Spells Prepared sections may exist from different sources, so create a section for each -->
[H: SPNote = ""]
[H, IF(0<getFindCount(SpellsPreparedSearch)), FOR(NumSpellClasses, 1, getFindCount(SpellsPreparedSearch)+1), CODE: {
   [ThisSpellClass = getGroup(SpellsPreparedSearch, NumSpellClasses, 1)]
   [SpellsPreparedHeaderSearch = strfind(ThisSpellClass, "(?i)(.*?\\)) +(9th|8th|7th|6th|5th|4th|3rd|2nd|1st|0 \\(|0th \\))")]
   [NinthLevelSearch = strfind(ThisSpellClass, "(?i)((9th)(.*?))(8th)")]
   [EighthLevelSearch = strfind(ThisSpellClass, "(?i)((8th)(.*?))(7th)")]
   [SeventhLevelSearch = strfind(ThisSpellClass, "(?i)((7th)(.*?))(6th)")]
   [SixthLevelSearch = strfind(ThisSpellClass, "(?i)((6th)(.*?))(5th)")]
   [FifthLevelSearch = strfind(ThisSpellClass, "(?i)((5th)(.*?))(4th)")]
   [FourthLevelSearch = strfind(ThisSpellClass, "(?i)((4th)(.*?))(3rd)")]
   [ThirdLevelSearch = strfind(ThisSpellClass, "(?i)((3rd)(.*?))(2nd)")]
   [SecondLevelSearch = strfind(ThisSpellClass, "(?i)((2nd)(.*?))(1st)")]
   [FirstLevelSearch = strfind(ThisSpellClass, "(?i)((1st)(.*?))(0 \\(|0th \\()")]
   [ThisClassSpecialSearch = strfind(ThisSpellClass, "(?i)((D Domain|Bloodline|Domain|Mystery|Opposition School|Prohibited School)(.*))")]
   [IF(0<getFindCount(ThisClassSpecialSearch)): ZerothLevelSearch = strfind(ThisSpellClass, "(?i)((0 \\(|0th \\()(.*?))(D Domain|Bloodline|Domain|Mystery|Opposition School|Prohibited School)"); ZerothLevelSearch = strfind(ThisSpellClass, "((0 \\(|0th \\()(.*))")]
   [IF(0<getFindCount(SpellsPreparedHeaderSearch)): SpellsPreparedHeader = "

" + trim(getGroup(SpellsPreparedHeaderSearch, 1, 1)); SpellsPreparedHeader = ""]
   [IF(0<getFindCount(NinthLevelSearch)), CODE: {
      [NinthLevel = "
   " + trim(getGroup(NinthLevelSearch, 1, 1))]
   };{
      [NinthLevel = ""]
   }]
   [IF(0<getFindCount(EighthLevelSearch)), CODE: {
      [EighthLevel = "
   " + trim(getGroup(EighthLevelSearch, 1, 1))]
   };{
      [EighthLevel = ""]
   }]
   [IF(0<getFindCount(SeventhLevelSearch)), CODE: {
      [SeventhLevel = "
   " + trim(getGroup(SeventhLevelSearch, 1, 1))]
   };{
      [SeventhLevel = ""]
   }]
   [IF(0<getFindCount(SixthLevelSearch)), CODE: {
      [SixthLevel = "
   " + trim(getGroup(SixthLevelSearch, 1, 1))]
   };{
      [SixthLevel = ""]
   }]
   [IF(0<getFindCount(FifthLevelSearch)), CODE: {
      [FifthLevel = "
   " + trim(getGroup(FifthLevelSearch, 1, 1))]
   };{
      [FifthLevel = ""]
   }]
   [IF(0<getFindCount(FourthLevelSearch)), CODE: {
      [FourthLevel = "
   " + trim(getGroup(FourthLevelSearch, 1, 1))]
   };{
      [FourthLevel = ""]
   }]
   [IF(0<getFindCount(ThirdLevelSearch)), CODE: {
      [ThirdLevel = "
   " + trim(getGroup(ThirdLevelSearch, 1, 1))]
   };{
      [ThirdLevel = ""]
   }]
   [IF(0<getFindCount(SecondLevelSearch)), CODE: {
      [SecondLevel = "
   " + trim(getGroup(SecondLevelSearch, 1, 1))]
   };{
      [SecondLevel = ""]
   }]
   [IF(0<getFindCount(FirstLevelSearch)), CODE: {
      [FirstLevel = "
   " + trim(getGroup(FirstLevelSearch, 1, 1))]
   };{
      [FirstLevel = ""]
   }]
   [IF(0<getFindCount(ZerothLevelSearch)), CODE: {
      [ZerothLevel = "
   " + trim(getGroup(ZerothLevelSearch, 1, 1))]
   };{
      [ZerothLevel = ""]
   }]
   [IF(0<getFindCount(ThisClassSpecialSearch)), CODE: {
      [ThisClassSpecial = "
   " + trim(getGroup(ThisClassSpecialSearch, 1, 1))]
   };{
      [ThisClassSpecial = ""]
   }]
   [SPNote = SPNote + SpellsPreparedHeader + NinthLevel + EighthLevel + SeventhLevel + SixthLevel + FifthLevel + FourthLevel + ThirdLevel + SecondLevel + FirstLevel + ZerothLevel + ThisClassSpecial]
};{
   [SPNote = ""]
}]

<!-- If a tactics section exists, break it up into subsections of Before Combat, During Combat, and Morale. The Base Statistics section, if it exists, may be in Tactics or it may be at the end of the Statistics section. In either case, put it in Tactics -->
[H, IF(0<getFindCount(TacticsSearch)), CODE: {
   [TacticsNote = "

-----TACTICS-----"]
   [TacticsString = getGroup(TacticsSearch, 1, 1)]
   [TacticsBeforeCombatSearch = strfind(TacticsString, "(?i)(Before Combat.*?)(During Combat|Morale|Base Statistics)")]
   [IF(1>getFindCount(TacticsBeforeCombatSearch)): TacticsBeforeCombatSearch = strfind(TacticsString, "(?i)(Before Combat.*)")]
   [IF(0<getFindCount(TacticsBeforeCombatSearch)): TacticsNote = TacticsNote + "
" + trim(getGroup(TacticsBeforeCombatSearch, 1, 1))]
   [TacticsDuringCombatSearch = strfind(TacticsString, "(?i)(During Combat.*?)(Morale|Base Statistics)")]
   [IF(1>getFindCount(TacticsDuringCombatSearch)): TacticsDuringCombatSearch = strfind(TacticsString, "(?i)(During Combat.*)")]
   [IF(0<getFindCount(TacticsDuringCombatSearch)): TacticsNote = TacticsNote + "
" + trim(getGroup(TacticsDuringCombatSearch, 1, 1))]
   [TacticsMoraleSearch = strfind(TacticsString, "(?i)(Morale.*?)(Base Statistics)")]
   [IF(1>getFindCount(TacticsMoraleSearch)): TacticsMoraleSearch = strfind(TacticsString, "(?i)(Morale.*)")]
   [IF(0<getFindCount(TacticsMoraleSearch)): TacticsNote = TacticsNote + "
" + trim(getGroup(TacticsMoraleSearch, 1, 1))]
};{
   [TacticsNote = ""]
}]
[H, IF(0<getFindCount(BaseStatisticsSearch)), CODE: {
   [IF(TacticsNote == ""), CODE: {
      [TacticsNote = "

-----TACTICS-----
" + trim(getGroup(BaseStatisticsSearch, 1, 1)))]
   };{
      [TacticsNote = TacticsNote + "
" + trim(getGroup(BaseStatisticsSearch, 1, 1)))]
   }]
}]

[H, IF(0<getFindCount(FeatsSearch)), CODE: {
   [FeatsNote = "
" + trim(getGroup(FeatsSearch, 1, 2))]
};{
   [FeatsNote = ""]
}]

[H, IF(0<getFindCount(SkillsSearch)), CODE: {
   [SkillsNote = "
" + trim(getGroup(SkillsSearch, 1, 2))]
};{
   [SkillsNote = ""]
}]

[H, IF(0<getFindCount(LanguagesSearch)), CODE: {
   [LangNote = "
" + trim(getGroup(LanguagesSearch, 1, 2))]
};{
   [LangNote = ""]
}]

[H, IF(0<getFindCount(SQSearch)), CODE: {
   [SQNote = "
" + trim(getGroup(SQSearch, 1, 2))]
};{
   [SQNote = ""]
}]

[H, IF(0<getFindCount(GearSearch)), CODE: {
   [GearNote = "
" + trim(getGroup(GearSearch, 1, 2))]
};{
   [GearNote = ""]
}]

<!-- If Special Abilities section exists, break it up into a separate line for each ability with its description -->
[H, IF(0<getFindCount(SpecialAbilitiesSearch)), CODE: {
   [SAbNote = "

-----SPECIAL ABILITIES-----"]
   [SAList = ""]
   [SpecialAbilityString = getGroup(SpecialAbilitiesSearch, 1, 2)]
   [SingleSpecialAbilitySearch = strfind(SpecialAbilityString, "(?i)(.*?\\. +)(?=.*? \\((Ex|Su|Sp)\\))")]
   [IF(0<getFindCount(SingleSpecialAbilitySearch)), FOR(NumOfSpecialAbilities, 1, getFindCount(SingleSpecialAbilitySearch)+1), CODE: {
      [SingleSpecialAbility = getGroup(SingleSpecialAbilitySearch, NumOfSpecialAbilities, 1)]
      [SpecialAbilityString = replace(SpecialAbilityString, "(?i)(.*?\\. +)(?=.*? \\((Ex|Su|Sp)\\))", "")]
      [SearchingForExtraLines = strfind(SingleSpecialAbility, "(?i)\\((Ex|Su|Sp)\\)")]
      [IF(0<getFindCount(SearchingForExtraLines)): SAList = SAList + "
" + trim(SingleSpecialAbility) ; SAList = SAList + " " + trim(SingleSpecialAbility)]
   }]
   [SAList = SAList + "
" + trim(SpecialAbilityString)]
   [SAbNote = SAbNote + SAList]
};{
   [SAbNote = ""]
}]

<!-- If the Ecology section exists, break it up into lines for Environment, Organization, and Treasure -->
[H, IF(0<getFindCount(EcologySearch)), CODE: {
   [EcologyNote = "

-----ECOLOGY-----"]
   [EcologyString = trim(getGroup(EcologySearch, 1, 2))]
   [EnvironmentSearch = strfind(EcologyString, "(?i)(Environment.*?)(Organization|Treasure)")]
   [IF(0<getFindCount(EnvironmentSearch)): EcologyNote = EcologyNote + "
" + trim(getGroup(EnvironmentSearch, 1, 1))]
   [OrganizationSearch = strfind(EcologyString, "(?i)(Organization.*?)(Treasure)")]
   [IF(0<getFindCount(OrganizationSearch)): EcologyNote = EcologyNote + "
" + trim(getGroup(OrganizationSearch, 1, 1))]
   [TreasureSearch = strfind(EcologyString, "(?i)(Treasure.*)")]
   [IF(0<getFindCount(TreasureSearch)), CODE: {
      [TreasureTypeSearch = strfind(getGroup(TreasureSearch, 1, 1), "(none|standard|double|incidental|NPC gear)")]
      [IF(0<getFindCount(TreasureTypeSearch)): TreasureType = getGroup(TreasureTypeSearch, 1, 1)]
   }]
   [IF(0<getFindCount(TreasureSearch)): EcologyNote = EcologyNote + "
" + trim(getGroup(TreasureSearch, 1, 1))]
};{
   [EcologyNote = ""]
}]

<!--Put it all together in the GM notes -->

<!-- AM Update - may use this later to redo gm notes. Needed for debugging. -->
[H: TAB = decode("%09")]
[H: EOL = decode("%0A")]
[H: gmNotes = "[]"]

[H: note.name = trim(getGroup(NameSearch, 1, 1))]
[H: note.cr = trim(getGroup(CRSearch, 1, 1))]
[H: note.align = trim(getGroup(AlignmentSizeRaceSearch, 1, 1))]
[H: note.senses = trim(getGroup(InitSensesSearch, 1, 1))]
[H: note.ac = trim(getGroup(ACStringSearch, 1, 1))]
[H: note.hp = trim(getGroup(HPStringSearch, 1, 1))]
[H: note.saves = trim(getGroup(SavesSearch, 1, 1))]
[H: note.speed = trim(getGroup(SpeedSearch, 1, 2))]
[H: note.stats = trim(getGroup(StatisticsSearch, 1, 2))]
[H: note.bab = trim(getGroup(BaseAtkSearch, 1, 2))]

<!-- This is actual fix for XP not being in statblock. It simply puts a blank -->
[H, if(getFindCount(XPSearch)): note.xp = trim(getGroup(XPSearch, 1, 1)); note.xp = ""]

[H: setGMNotes(trim(getGroup(NameSearch, 1, 1)) + "   " + trim(getGroup(CRSearch, 1, 1)) + "
------------
" + note.xp +
 GenderEtcNote + "
" + trim(getGroup(AlignmentSizeRaceSearch, 1, 1)) + "
" + trim(getGroup(InitSensesSearch, 1, 1)) +
 AuraNote + "

-----DEFENSE-----
" + trim(getGroup(ACStringSearch, 1, 1)) + "
" + trim(getGroup(HPStringSearch, 1, 1)) + "
" + trim(getGroup(SavesSearch, 1, 1)) +
 DANote +
 WeaknessNote + "

-----OFFENSE-----
" + trim(getGroup(SpeedSearch, 1, 2)) +
 MeleeNote +
 RangedNote +
 SpaceReachNote +
 SANote +
 SLNote +
 SKNote +
 SPNote +
 TacticsNote + "

-----STATISTICS-----
" + trim(getGroup(StatisticsSearch, 1, 2)) + "
" + trim(getGroup(BaseAtkSearch, 1, 2)) +
 FeatsNote +
 SkillsNote +
 LangNote +
 SQNote +
 GearNote +
 SAbNote +
 EcologyNote)]

[H: output="Token Updated:<br>"]
[H: id = strfind(statblock, "^(.+?)CR ?[0-9]")]
[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 ?)([0-9]+)(/[1-9]+)?")]
[H, IF(0<getFindCount(id)), CODE: {
   [ECL = trim(getGroup(id, 1, 0))]
   [output=output+"CR: "+ECL+", "]
   [IF(ECL == "1/3"): ECL=".338"]
   [IF(ECL == "1/6"): 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(0)]
   [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+", "]
}]

 <!-- Defensive Abilities Sample: Defensive Abilities incorporeal, channel resistance +2; -->
[H: DefensiveAbil = ""]
[H, IF(0<getFindCount(DefensiveAbilitiesSearch)),CODE: {
   [DefensiveAbilitiesString=getGroup(DefensiveAbilitiesSearch, 1, 1)]
   [DefensiveAloneSearch=strfind(DefensiveAbilitiesString, "(?i)Defensive (Abilities|Ability)(.*?); +(SR|Immune|Resist|DR)")]
   [IF(0==getFindCount(DefensiveAloneSearch)): DefensiveAloneSearch = strfind(DefensiveAbilitiesString, "(?i)Defensive (Ability|Abilities)(.*)")]
   [IF(0<getFindCount(DefensiveAloneSearch)), CODE: {
      [DefensiveAbil = trim(getGroup(DefensiveAloneSearch, 1, 2))]
      [output=output+"Defensive Abilities: "+DefensiveAbil+", "]
   }]
}]

<!-- Find Immunities. Sample: Immune acid, curse effects, flanking, mind-affecting effects, paralysis, poison, sleep -->
[H: Immune = ""]
[H: id = strfind(statblock, "(Immune )(([a-zA-Z]+[-]?,? ?)+);? +(Weakness|OFFENSE|Resist|SR)")]
[H, IF(0<getFindCount(id)),CODE: {
   [id2 = strfind(getGroup(id, 1, 2), "(.*) (Weakness|OFFENSE|[;]|Resist)")]
   [IF(0<getFindCount(id2)): Immune = getGroup(id2, 1, 1); Immune = getGroup(id, 1, 2)]
   [Immune = trim(Immune)]
   [output=output+"Immunities: "+Immune+", "]
 }]

<!-- Find Weaknesses. Sample: Weaknesses light sensitivity -->
[H: Weaknesses = ""]
[H: id = strfind(statblock, "(Weaknesse?s? )((\\w+-?,? ?)+) +(?i)(OFFENSE|DEFENSE)")]
[H, IF(0<getFindCount(id)),CODE: {
   [Weaknesses = trim(getGroup(id, 1, 2))]
   [output=output+"Weaknesses: "+Weaknesses+", "]
}]
 
<!-- Find DR. Sample: 1/-, 2/adamantine, 3/good -->
[h: DRSearch = ""]
[H: id = strfind(statblock, "DR(.?[0-9]+)/(.+?)[,;O]")]
[H, IF(0<getFindCount(id)), COUNT(getFindCount(id)), CODE: {
   [thisrollcount = roll.count+1]
   [thissearchDR = replace(getGroup(id, thisrollcount, 2), "Cold Iron", "ColdIron")]
   [drANDORsearch = strfind(thissearchDR, "(and|or) ([a-zA-Z]+ ?)")]
   [if(0<getFindCount(drANDORsearch)), COUNT(getFindCount(drANDORsearch)), CODE: {
   [DRSearch = trim(DRSearch + " " + getGroup(id, thisrollcount, 1)+"/"+getGroup(drANDORsearch, roll.count+1, 2))]
   }]
   [DRSearch = trim(DRSearch + " " + getGroup(id, thisrollcount, 1)+"/"+thissearchDR)]
   [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))]
}]

<!-- Find SR --> 
[H: SRSearch = ""]
[H: id = strfind(statblock, "SR ([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE: {
   [SRSearch=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_", if( reduceTypes == "Energy Resistance", "ER_", if( reduceTypes == "Spell Resistance", "SR_", "EV_") ) ) + 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, If(Immune != ""), CODE:{
   [jRC = json.get( DRER, "Energy Resistance" )]
   [jRCnew = json.set( jRC, "Note", "Immune: "+Immune)]
   [newDRER = json.set( DRER, "Energy Resistance", JRCnew)]
   [setProperty("DRER", newDRER)]
   [DR = listAppend(DR, "Immune: "+Immune)]
}]

[H, If(SRSearch != ""), CODE:{
   [jRC = json.get( DRER, "Spell Resistance" )]
   [jRCnew = json.set( jRC, "SR", SRSearch)]
   [newDRER = json.set( DRER, "Spell Resistance", JRCnew)]
   [setProperty("DRER", newDRER)]
   [DR = listAppend(DR, "SR: "+SRSearch)]
}]

[H: vulnerability =  strfind(Weaknesses, "(Vulnerability|Vulnerable|vulnerability|vulnerable) to ([a-zA-Z]*)")]
[H: vtypes = getFindCount(vulnerability)]
[H, IF(0<vtypes), CODE: {
   [COUNT(vtypes), CODE: {
      [jRC = json.get(DRER, "Energy Vulnerability")]
      [ tvuln = "V."+upper(lower(getGroup(vulnerability,roll.count+1,2)),1)]
      [ validVulnerability = listContains("V.Acid,V.Cold,V.Electricity,V.Fire,V.Sonic",tvuln)]
      [if(validVulnerability): jRCnew = json.set(jRC, tvuln, 1)]
      [if(validVulnerability): newDRER = json.set(DRER, "Energy Vulnerability", jRCnew)]
      [if(validVulnerability): setProperty("DRER", newDRER)]
      [if(validVulnerability): DR = listAppend(DR, tvuln)]
   }]
}]

<!-- STATS BEGIN -->
[H: id = strfind(statblock, "(?i)(?<!base )STATISTICS.*?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>"]
}]
[H: SavesString = getGroup(SavesSearch, 1, 1)]
[H: id = strfind(SavesString, ";(.*)")]
[H, IF(0<getFindCount(id)), CODE: {
   [SaveMisc = trim(getGroup(id, 1, 1))]
   [output=output+"Saves Misc Notes: "+SaveMisc+"<br>"]
}]

<!-- SAVES END -->

[H: id = strfind(statblock, "hp ([0-9]+).*?\\(([0-9]+ ?HD; ?)?([0-9d+]*)")]
[H: hpString = getGroup(id, 1, 3)]
[H: numOfEachHDType = strfind(hpString, "([0-9]+)d")]
[H: numOfHDTypes = getFindCount(numOfEachHDType)]
[H, IF(0<getFindCount(id)),CODE: {
   [H: HD = 0]
   [H, COUNT(numOfHDTypes), CODE:
   {
      [HD = HD + getGroup(numOfEachHDType, (roll.count+1), 1)]
   }]
   [HP=getGroup(id, 1, 1)]
   [Level = max(1,HD)]
   [HPmax="[R: max(Level, ( "+(HP-(ConB*Level))+" + (ConB * Level) ) )]"]
   [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-natural]
   [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)]
   [Movement = spd]
}; {
   [Speed = json.set(Speed, "base",0)]
   [Movement = 0]
}]
[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)]
   [Movement = getProperty("Movement") + ", Climb:" + 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)]
   [Movement = getProperty("Movement") + ", 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)]
   [Movement = getProperty("Movement") + ", Burrow:" + spd]
}]
[H: id = strfind(statblock, "fly ([0-9]+) ft\\.? ?\\(?([a-zA-Z]+)?\\)? ?(Melee|Ranged|Special|Spell)")]
[H, IF(0<getFindCount(id)), CODE: {
   [spd=getGroup(id, 1, 1)]
   [output=output+", Fly: "+spd]
   [Speed = json.set(Speed, "fly",spd)]
   [flyman=lower(getGroup(id, 1, 2))]
   [SWITCH(flyman), CODE:
      case "": {
         [flyman = "average"]
         [Speed = json.set(Speed, "flymaneuver",4)]
      };
      case "clumsy": {
         [flyman = "Clumsy"]
         [Speed = json.set(Speed, "flymaneuver",2)]
      };
      case "poor": {
         [flyman = "Poor"]
         [Speed = json.set(Speed, "flymaneuver",3)]
      };
      case "average": {
         [flyman = "Average"]
         [Speed = json.set(Speed, "flymaneuver",4)]
      };
      case "good": {
         [flyman = "Good"]
         [Speed = json.set(Speed, "flymaneuver",5)]
      };
      case "perfect": {
         [flyman = "Perfect"]
         [Speed = json.set(Speed, "flymaneuver",6)]
      };
   ]
   [Movement = getProperty("Movement") + ", Fly:" + spd + " (" + flyman + ")"]
}]
[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 -->

<!--Languages Begin-->
[H, IF(0<getFindCount(LanguagesSearch)), CODE: {
   [LanguageList = strfind(getGroup(LanguagesSearch, 1, 2), "Languages?(.*)")]
   [IF(0<getFindCount(LanguageList)): Race = json.set(Race, "notes", trim(getGroup(LanguageList, 1, 1)))]
}]
<!--Languages End-->

<!-- SQ on popup begin -->
[H, IF(0<getFindCount(SQSearch)), CODE: {
   [SpecialQualWithoutSQ = strfind(getGroup(SQSearch, 1, 2), "SQ (.*)")]
   [SpecialQual = trim(getGroup(SpecialQualWithoutSQ, 1, 1))]
}]
<!--SQ on popup end-->

<!-- FEATS BEGIN -->
[H: output=output+"Feats: "]
[H, IF(0<getFindCount(FeatsSearch)), CODE: {
   [ tFeats = replace(getGroup(FeatsSearch, 1, 2), "Feats ", "", 1) ]
   [ tFeats = trim(replace(tFeats, "B,", ",")) ]
   [ tFEflag = endsWith(tFeats, "B") ]
   [ IF(tFEflag): tFeats = substring(tFeats, 0, length(tFeats)-1); "" ]
   [ tFeatsJ = json.fromList(tFeats) ]
   [ tFeatsJ2 = "[]" ]
   [ tFeatsJparam = "{}" ]
   [ Foreach(p, tFeatsJ), CODE: {
      [ tidxp = indexOf(p,"(") ]
      [ IF( tidxp < 0 ): tpm = trim(p); tpm = trim(substring(p,0,tidxp)) ]
      [ IF( tidxp < 0 ): tpsub = ""; tpsub = substring(p,tidxp+1,length(p)-1) ]
      [ tFeatsJ2 = json.append(tFeatsJ2, tpm) ]
      [ IF( tidxp < 0 ): "";  tFeatsJparam = json.set(tFeatsJparam, tpm, tpsub) ]
   }]
   [ tFeatsJ2 = json.sort(tFeatsJ2) ]
   [ setProperty("FeatsJ", tFeatsJ2) ]
   [ setProperty("FeatsJparam", tFeatsJparam) ]
   
   [H: sysVars = table("SysVars", 0)]
   [H: sysFeats = table("SysVars", json.get(sysVars, "sysFeats"))]
   [H: tsfl = json.fields(sysFeats,"json")]
   [H: tFeatsSys = getProperty("Feats")]
   [H, FOREACH(p,tsfl),CODE: {
      [H: tfcont = json.contains(tFeatsJ2,p)]
      [H: tval = if(tfcont,1,0)]
      [H: tFeatsSys = setStrProp(tFeatsSys,json.get(sysFeats,p),tval)]
   }]
   [H: setProperty("Feats", tFeatsSys)]
   [H: output=output+tFeats ]
};{
}]
[H: output=output+"<br>"]
<!-- FEATS END -->

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

[H: id = strfind(statblock, "(?i)Special Attacks? (.*?)(Spells|Spell[ -]Like|Statistics|Tactics)")]
[H, IF(0<getFindCount(id)), CODE: {
   [SpecialATK = trim(getGroup(id, 1, 1))]
   [SpecialATK=substring(SpecialATK,0,min(length(SpecialATK),70))]
   [output=output+"SA: "+SpecialATK+"<br>"]
  };{
   [SpecialATK=""]
}]

[H: id = strfind(statblock, "(Fast Healing )([0-9]+)")]
[H, IF(0<getFindCount(id)),CODE: {
   [FastHealing=getGroup(id, 1, 2)]
   [output=output+"Fast Healing: "+FastHealing+"<br>"]
}]

<!-- Setting Regeneration and Anti Regen Damage Type if present -->
[H: id = strfind(statblock, "(Regeneration )([0-9]+) ([(][a-zA-Z]+[)])?")]
[H, IF(0<getFindCount(id)),CODE: {
   [Regeneration=getGroup(id, 1, 2)]
   [output=output+"Regeneration: "+Regeneration+"<br>"]
   [AntiRegen=if(getGroup(id, 1, 3)=="", "", getGroup(id, 1, 3))]
   [output=output+"Regeneration: "+Regeneration+"<br>"+if(AntiRegen=="", "", "Anti-Regen Damage Type: "+AntiRegen+"<br>")]
}]
 
<!-- ATTACKS BEGIN -->
<!-- Insert empty weapon strings -->
[H: wpnstr=getPropertyDefault( "Weapon0" )]
[H, c(17,""),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|Space|Reach|Special|Ranged|Spell-Like|Spells|Statistic)")]
[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=replace(atkstr, "((\\(.+\\)) and )", "\$2, ")]
   [atkstr=stringToList(atkstr, "(, )",":")]
   [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 (.+?)(?i)(Tactic|Space|Reach|Special|Spell-Like|Spells|Statistic)")]
[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+)(/[+-]\\d+)?( [a-zA-Z]* )?[/+\\-0-9\\s]*?\\((.+)\\)")]
   [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, " ", "") + if(wbonus=="", "", " ") + getGroup(id, 1, 3) + if(getGroup(id, 1, 6)=="", "", " ("+trim(getGroup(id, 1, 6))+")")) + "'")]
   
   <!-- Manufactured ? -->
     [id2 = strfind(atkstr, "(?i)(slam|bite|claw|gore|hoof|tentacle|wing|pincer|tail|sting|talon|Constrict)")]
     [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, 7)]
     [CritMult=2]
     [id2 = strfind(wdam, "([0-9]+d[0-9]+)?([+-][0-9]+)?/?([0-9]+-?[0-9]+)?([xX]([0-9]))? ?([a-zA-Z0-9 ]+)?")]
     [IF(getGroup(id2, 1, 5)==""): CritMult=2; CritMult=replace(getGroup(id2, 1, 5),"[xX]", "")]
     [eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritMult", CritMult)+ "'")]

   <!-- CritRange-->
     [CritRange=20]
     [critFromWdam = getGroup(id2, 1, 3)]
   [critFromWdamsearch = strfind(critFromWdam, "([0-9]+)-20")]
   [IF(0<getFindCount(critFromWdamsearch)): CritRange = getGroup(critFromWdamsearch, 1, 1)]
     [eval(WpnName + "= '" + setStrProp(eval(WpnName),"CritRange", CritRange)+ "'")]
   
   <!-- CritExtraDamage-->
     [DmgExtraCrit=""]

   <!-- Damage -->
     [Damage=if(getGroup(id2, 1, 1) == "", "0", getGroup(id2, 1, 1))]
   [DmgExtra = 0]
   [DmgExtraName = ""]
   [newPlusStr= ""]
   [DamagePlus = ""]
   [DmgExtraCrit = "0d10"]
   [DamagePlus = if(0<getFindCount(id2), getGroup(id2, 1, 6), "")]
   [DmgBonus = 0]
   [DmgBonus = if(0<getFindCount(id2), getGroup(id2, 1, 2), 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)")]
   [DmgBonus = if(DmgBonus == "", 0, DmgBonus)]
     [IF(0<getFindCount(id2)):eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 1)+ "'")]
   [DmgBonus = round(if(0<getFindCount(id2), DmgBonus-Str2hB, DmgBonus-StrB))]
   
     [ExtraDamageSearch = strfind(DamagePlus, "(.*) ([0-9]+[d0-9]+?) ?([a-zA-Z]+) ?(.*)")]
   [IF(0<getFindCount(ExtraDamageSearch)):DmgExtra=getGroup(ExtraDamageSearch, 1, 2)]
   [IF(0<getFindCount(ExtraDamageSearch)):DmgExtraName=getGroup(ExtraDamageSearch, 1, 3)]
   [IF(0<getFindCount(ExtraDamageSearch)):newPlusStr = getGroup(ExtraDamageSearch, 1, 1) + getGroup(ExtraDamageSearch, 1, 4)]
   [IF(0<getFindCount(ExtraDamageSearch)):newPlusStr = replace(newPlusStr, "plus", "")]
   [IF(0<getFindCount(ExtraDamageSearch)):newPlusStr = replace(newPlusStr, "and", "")]
   [IF(0<getFindCount(ExtraDamageSearch)):newPlusStr = trim(newPlusStr)]
   [IF(0<getFindCount(ExtraDamageSearch)):newPlusStr = replace(newPlusStr, "  ", " ")]
   [IF(0<getFindCount(ExtraDamageSearch)):newPlusStr = replace(newPlusStr, " ", " plus ")]
   [IF(0<getFindCount(ExtraDamageSearch)):Damage = trim(Damage + if(DmgBonus<0, "", "+") + DmgBonus + " " + IF(newPlusStr != "", "plus " + newPlusStr, newPlusStr)); Damage = trim(Damage + if(DmgBonus<0, "", "+") + DmgBonus + " " + DamagePlus)]
   [burstsearch = strfind(getGroup(id, 1, 3), "([a-zA-Z]+ )([Bb]urst)")]
   [IF(0<getFindCount(burstsearch)): DmgExtraCrit = "1d10 " + trim(getGroup(burstsearch, 1, 1))]
   
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"Damage", Damage)+ "'")]
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"DmgExtra", DmgExtra)+ "'")]
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"DmgExtraName", DmgExtraName)+ "'")]
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"DmgExtraCrit", DmgExtraCrit)+ "'")]
   <!-- Two handed ? -->
    <!-- Default to onehanded weapon -->
   [eval(WpnName + "= '" + setStrProp(eval(WpnName),"TwoHanded", 0)+ "'")]

}]
 
   [wpnno = wpnno +1]
}]

[H: broadcast(strformat("Import Complete %{name}"),"self,gm")]

!!

_________________
Downloads:


Top
 Profile  
 
Display posts from previous:  Sort by  
Reply to topic  [ 50 posts ]  Go to page Previous  1, 2, 3, 4  Next

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:

Who is online

In total there are 2 users online :: 0 registered, 0 hidden and 2 guests (based on users active over the past 5 minutes)
Most users ever online was 243 on Sun Nov 04, 2012 6:14 am

Users browsing this forum: No registered users and 2 guests





Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group

Style based on Andreas08 by Andreas Viklund

Style by Elizabeth Shulman