Lone Wolf Development Forums  

Go Back   Lone Wolf Development Forums > Hero Lab Forums > HL - Authoring Kit

Notices

Reply
 
Thread Tools Display Modes
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 1,502

Old August 30th, 2017, 05:46 PM
This seems like something bush leagues that I should have picked up on already, but I'm having difficulties. I have a bootstrapped thing, an fPlusSk1 that might have one or more SkillBonus tags where I want to add 1 to those skills as an innate bonus.



I want to go through each of the SkillBonus tags, and run "perform hero.child[eachpick.idstring].field[trtBG].modify[+,1,"Background"]" on it. It feels like it should be something like:
Quote:
foreach pick in hero where "SkillBonus.?"
perform hero.child[eachpick.idstring].field[trtBG].modify[+,1,"Background"]
nexteach
But, of course, that runs down the tags attached to the Hero. How do I make it instead attach to the current thing (an fPlusSk1) and look through the tags attached to that?
Attached Images
File Type: png TagsOnBootstrap.png (232.7 KB, 36 views)
Duggan is offline   #1 Reply With Quote
Aaron
Senior Member
 
Join Date: Oct 2011
Posts: 6,793

Old August 31st, 2017, 07:00 AM
Not bush league. Converting a series of tags into a list of picks is kinda a PiTA, but it is doable. Basically you convert the tagids into a string, set up a marker between each tag, then use a for loop to carve up the string, one marker at a time. I'll look up an example for you, give me a sec.
Aaron is offline   #2 Reply With Quote
Aaron
Senior Member
 
Join Date: Oct 2011
Posts: 6,793

Old August 31st, 2017, 07:10 AM
This is the way that Pathfinder converts a series of ReqFeat tags into a pre-requisite script for matching feats on the hero. It uses the basic principle I described above, but is more complex because it has to work both while a pick and a thing and has to handle various wacky substitutions.

Code:
    <prereq iserror="no" message="Feat Required">
      <match><![CDATA[
        count:ReqFeat.? <> 0
        ]]></match>
      <validate><![CDATA[
        ~there's a tag that removes all feat-based prereqs for this ability
        validif (isidentity[NoFeatPre] <> 0)

        var namestrpos as number
        var idstrpos as number
        var splitlen as number
        var tagidstr as string
        var tagnamestr as string
        var thistagid as string
        var thistagnam as string
        var failname as string

        if (@ispick <> 0) then
          ~ If every ReqFeat tag is matched with a tag on the hero, then we're
          ~ valid.
          ~ Note that this isn't foolproof because some substitutions happen
          ~ later. Thus at the end of the process we will have one final validif.
          validif (altpick.intersect[ReqFeat,HasFeat,allsource] <> 0)

          ~ If even one failed, create a string variable, and carve that up in
          ~ a loop, comparing each section to the tags on the hero. If no match,
          ~ then store that in another string we will use to generate our
          ~ failure message.

          ~loop until we run out of items to add as children
          tagidstr = altpick.tagids[ReqFeat.?,#custsplitter[]]
          tagnamestr = altpick.tagnames[ReqFeat.?,#custsplitter[]]

        else
          ~ If every ReqFeat tag is matched with a tag on the hero, then we're
          ~ valid.
          validif (altthing.intersect[ReqFeat,HasFeat,allsource] <> 0)

          ~ If even one failed, create a string variable, and carve that up in
          ~ a loop, comparing each section to the tags on the hero. If no match,
          ~ then store that in another string we will use to generate our
          ~ failure message.

          ~loop until we run out of items to add as children
          tagidstr = altthing.tagids[ReqFeat.?,#custsplitter[]]
          tagnamestr = altthing.tagnames[ReqFeat.?,#custsplitter[]]
          endif

        ~if we're greater

        splitlen = length(#custsplitter[])
        tagidstr = replace(tagidstr,"ReqFeat","HasFeat",0)

        var checktags as number
        var foundtags as number
        while (1 = 1)

          if (empty(tagidstr) <> 0) then
            ~ Normally our valid state would have stoped us from getting this far,
            ~ as we only proceed if we lacked matches at the start. However, if we
            ~ found a match for every tag we checked (probably because of dirty
            ~ fighting substitutions), then we are valid after all!
            validif (foundtags = checktags)

            ~ If that final check didn't work out then we really are invalid, so
            ~ stop now that we have no tags to examine and we have to set the
            ~ failure message.
            @message = failname & " required."
            done
            endif

          ~ The checktags variable counts the number of tags we have considered
          ~ while processing this pre-req. Once we have iterated through all of
          ~ the starting tag string it will be compared to the foundtags variable
          ~ to see if, because of substitutions from Dirty Fighting or other
          ~ things, we actually are valid despite failing the initial test at
          ~ the beginning of this script.
          checktags += 1

          ~find the next place the splitter occurs
          namestrpos = pos(tagidstr, #custsplitter[])
          idstrpos = pos(tagnamestr, #custsplitter[])

          ~if it doesn't, this is the last item in the list
          if (namestrpos < 0) then
            thistagid = tagidstr
            tagidstr = ""

          ~if not, we should break the string in two around the splitter so we can
          ~repeat this operation on the remaining text
          else
            thistagid = left(tagidstr, namestrpos)
            tagidstr = mid(tagidstr, namestrpos + splitlen, -1)
            endif

          ~if it doesn't, this is the last item in the list
          if (idstrpos < 0) then
            thistagnam = tagnamestr
            tagnamestr = ""

          ~if not, we should break the string in two around the splitter so we can
          ~repeat this operation on the remaining text
          else
            thistagnam = left(tagnamestr, idstrpos)
            tagnamestr = mid(tagnamestr, idstrpos + splitlen, -1)
            endif

          ~ If the currently considered tag is for a mythic feat, we need to
          ~ append that to the name in the list we build. Otherwise there is
          ~ nothing to distinguish Mythic Improved Critical vs. normal Improved
          ~ Critical.
          var idonly as string
          idonly = replace(thistagid,"HasFeat.","",0)

          foreach thing in idlist idonly
            if (eachthing.tagis[fCategory.Mythic] <> 0) then
              thistagnam = splice(thistagnam,"(mythic)"," ")
              endif
            nexteach

          ~ Dirty Fighting can substitute for Combat Expertise and Improved Unarmed Attack,
          ~ but only for feats that require an improved maneuver feat
          var tagexpr as string
          tagexpr = #improvedcombatfeatreqexpr[]

          ~ We use a variable here as insurance against future expansion of the
          ~ abilities able to substitute.
          var subtext as string

          ~ reset it each iteration
          subtext = ""

          ~ Handle Dirty Fighting substitutions.
          if (compare(thistagid,"HasFeat.fComExpert") = 0) then
            if (@ispick <> 0) then
              ~ This checks if we are something that requires one of the improved
              ~ maneauver feats which need combat expertise.
              if (altpick.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fDirtyFigh", " | ")
                endif

              ~ This checks if we ARE one of the improved maneauver feats which
              ~ need combat expertise.
              tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

              if (altpick.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fDirtyFigh", " | ")
                endif
            else
              ~ This checks if we are something that requires one of the improved
              ~ maneauver feats which need combat expertise.
              if (altthing.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fDirtyFigh", " | ")
                endif

              ~ This checks if we ARE one of the improved maneauver feats which
              ~ need combat expertise.
              tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

              if (altthing.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fDirtyFigh", " | ")
                endif
              endif
            endif

          ~Kinetic Warrior substitutions.
          ~ Kinetic Warrior counts as Combat Expertise for feat pre-requisites
          if (compare(thistagid,"HasFeat.fComExpert") = 0) then
            if (@ispick <> 0) then
              if (altpick.tagis[component.BaseFeat] <> 0) then
                subtext = splice(subtext,"HasAbility.cKinWarrio", " | ")
                endif
            else
              if (altthing.tagis[component.BaseFeat] <> 0) then
                subtext = splice(subtext,"HasAbility.cKinWarrio", " | ")
                endif
              endif
            endif

          if (compare(thistagid,"HasFeat.fImpUnarm") = 0) then
            if (@ispick <> 0) then
              ~ This checks if we are something that requires one of the improved
              ~ maneauver feats which need improved grapple.
              if (altpick.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fDirtyFigh", " | ")
                endif

              ~ This checks if we ARE one of the improved maneauver feats which
              ~ need combat expertise.
              tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

              if (altpick.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fDirtyFigh", " | ")
                endif
            else
              ~ This checks if we are something that requires one of the improved
              ~ maneauver feats which need improved grapple.
              if (altthing.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fDirtyFigh", " | ")
                endif

              ~ This checks if we ARE one of the improved maneauver feats which
              ~ need combat expertise.
              tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

              if (altthing.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fDirtyFigh", " | ")
                endif
              endif
            endif

          ~ Two-Weapon Grace substitutions.
          ~ Two-Weapon Grace counts as Double Slice for Two-Weapon Rend
          if (compare(thistagid,"HasFeat.fDblSlice") = 0) then
            if (@ispick <> 0) then
              if (altpick.tagis[thingid.fTwoWepRen] <> 0) then
                subtext = splice(subtext,"HasFeat.fTwoWepGra", " | ")
                endif
            else
              if (altthing.tagis[thingid.fTwoWepRen] <> 0) then
                subtext = splice(subtext,"HasFeat.fTwoWepGra", " | ")
                endif
              endif
            endif

          ~ Craft Poppet substitutions.
          ~ Craft Poppet counts as Craft Magic Arms and Armor and Craft Wondrous
          ~ Item for Craft Construct
          if (compare(thistagid,"HasFeat.fCraftMgc") = 0) then
            if (@ispick <> 0) then
              if (altpick.tagis[thingid.fCraftCons] <> 0) then
                subtext = splice(subtext,"HasFeat.fCraftPopp", " | ")
                endif
            else
              if (altthing.tagis[thingid.fCraftCons] <> 0) then
                subtext = splice(subtext,"HasFeat.fCraftPopp", " | ")
                endif
              endif
            endif

          if (compare(thistagid,"HasFeat.fCraftWond") = 0) then
            if (@ispick <> 0) then
              if (altpick.tagis[thingid.fCraftCons] <> 0) then
                subtext = splice(subtext,"HasFeat.fCraftPopp", " | ")
                endif
            else
              if (altthing.tagis[thingid.fCraftCons] <> 0) then
                subtext = splice(subtext,"HasFeat.fCraftPopp", " | ")
                endif
              endif
            endif

          ~ Handle Guarded Charge substitutions.
          ~ Guarded Charge counts as Power Attack for Improved Bull Rush/Improved Overrun
          ~ and anything which requires either of those two feats.
          tagexpr = "ReqFeat.fImpBull | ReqFeat.fImpOver"

          if (compare(thistagid,"HasFeat.fPowerAtt") = 0) then
            if (@ispick <> 0) then
              ~ This checks if we are something that requires improved bull rush
              ~ or improved overrun
              if (altpick.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fGuardChar", " | ")
                endif

              ~ This checks if we ARE improved bull rush or improved overrun
              tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

              if (altpick.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fGuardChar", " | ")
                endif
            else
              ~ This checks if we are something that requires improved bull rush
              ~ or improved overrun
              if (altthing.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fGuardChar", " | ")
                endif

              ~ This checks if we ARE improved bull rush or improved overrun
              tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

              if (altthing.tagsearch[tagexpr] <> 0) then
                subtext = splice(subtext,"HasFeat.fGuardChar", " | ")
                endif
              endif
            endif

          ~ Perfect Aid counts as Combat Expertise for
          ~ Swift Aid
          ~ and anything which requires that feat.

          if (#hasability[cOraPerAid] <> 0) then
            tagexpr = "ReqFeat.fComExpert"

            if (compare(thistagid,"HasFeat.fComExpert") = 0) then
              if (@ispick <> 0) then
                ~ This checks if we are something that requires
                ~ Swift Aid
                if (altpick.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cOraPerAid", " | ")
                  endif

                ~ This checks if we ARE Swift Aid
                tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

                if (altpick.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cOraPerAid", " | ")
                  endif
              else
                ~ This checks if we are something that requires
                ~ Swift Aid
                if (altthing.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cOraPerAid", " | ")
                  endif

                ~ This checks if we ARE Swift Aid
                tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

                if (altthing.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cOraPerAid", " | ")
                  endif
                endif
              endif
            endif

          ~ Dirty Trickser counts as Combat Expertise for Improved Dirty Fighting
          ~ and anything which requires either of those two feats.
          if (#hasability[cBrdDirtyT] <> 0) then
            tagexpr = "ReqFeat.fImpDirTri"

            if (compare(thistagid,"HasFeat.fComExpert") = 0) then
              if (@ispick <> 0) then
                ~ This checks if we are something that requires
                ~ improved dirty trick
                if (altpick.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cBrdDirtyT", " | ")
                  endif

                ~ This checks if we ARE Improved Dirty Trick
                tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

                if (altpick.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cBrdDirtyT", " | ")
                  endif
              else
                ~ This checks if we are something that requires
                ~ Improved Dirty Trick
                if (altthing.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cBrdDirtyT", " | ")
                  endif

                ~ This checks if we ARE Improved Dirty Trick
                tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

                if (altthing.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cBrdDirtyT", " | ")
                  endif

                endif
              endif
            endif

          ~ Consummate Liar counts as Combat Expertise for
          ~ Improved Feint/Greater Feint
          ~ and anything which requires either of those two feats.

          if (#hasability[cMesConLia] <> 0) then
            tagexpr = "ReqFeat.fImpFeint | ReqFeat.fGreatFein"

            if (compare(thistagid,"HasFeat.fComExpert") = 0) then
              if (@ispick <> 0) then
                ~ This checks if we are something that requires
                ~ Improved Feint/Greater Feint
                if (altpick.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cMesConLia", " | ")
                  endif

                ~ This checks if we ARE Improved Feint/Greater Feint
                tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

                if (altpick.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cMesConLia", " | ")
                  endif
              else
                ~ This checks if we are something that requires
                ~ Improved Feint/Greater Feint
                if (altthing.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cMesConLia", " | ")
                  endif

                ~ This checks if we ARE Improved Feint/Greater Feint
                tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

                if (altthing.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cMesConLia", " | ")
                  endif
                endif
              endif
            endif

          ~ Consummate Cruelty counts as Combat Expertise for Improved Dirty
          ~ Trick/Greater Dirty Trick
          ~ and anything which requires either of those two feats.

          if (#hasability[cMesConsCr] <> 0) then
            tagexpr = "ReqFeat.fImpDirTri | ReqFeat.fGreatTric"

            if (compare(thistagid,"HasFeat.fComExpert") = 0) then
              if (@ispick <> 0) then
                ~ This checks if we are something that requires
                ~ Improved Dirty Trick/Greater Dirty Trick
                if (altpick.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cMesConsCr", " | ")
                  endif

                ~ This checks if we ARE Improved Dirty Trick/Greater Dirty Trick
                tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

                if (altpick.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cMesConsCr", " | ")
                  endif
              else
                ~ This checks if we are something that requires
                ~ Improved Dirty Trick/Greater Dirty Trick
                if (altthing.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cMesConsCr", " | ")
                  endif

                ~ This checks if we ARE Improved Dirty Trick/Greater Dirty Trick
                tagexpr = replace(tagexpr,"ReqFeat","thingid",0)

                if (altthing.tagsearch[tagexpr] <> 0) then
                  subtext = splice(subtext,"HasAbility.cMesConsCr", " | ")
                  endif
                endif
              endif
            endif

          ~ If we have any substitute text, append that with an appropriate
          ~ linking "or" to the current tag id check used.
          if (empty(subtext) = 0) then
            subtext = " | " & subtext
            thistagid &= subtext
            endif

          ~ Compare the current thistagid against tags on the hero. If it
          ~ matches, great! Otherwise register the failed tag's name in the
          ~ failname string, for use later.
          if (hero.tagsearch[thistagid] = 0) then
            failname = splice(failname, thistagnam, ", ")
          else
            ~ This variable counts the number of matches, for a final validation
            ~ check at the end.
            foundtags += 1
            endif

          ~ remove the substitute text we may have appended earlier
          thistagid = replace(thistagid,subtext,"",1)
          loop
        ]]></validate>
      </prereq>
Aaron is offline   #3 Reply With Quote
Mathias
Senior Member
Lone Wolf Staff
 
Join Date: May 2005
Posts: 13,207

Old August 31st, 2017, 08:14 AM
Aaron, I think all he's asking for is how to set up a basic foreach:
Code:
foreach pick in hero from Skill where tagids[SkillBonus.?,"|"]
   perform eachpick.field[trtBG].modify[+,1,"Background"]
   nexteach
Mathias is offline   #4 Reply With Quote
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 1,502

Old August 31st, 2017, 08:39 AM
Quote:
Originally Posted by Mathias View Post
Aaron, I think all he's asking for is how to set up a basic foreach:
Code:
foreach pick in hero from Skill where tagids[SkillBonus.?,"|"]
   perform eachpick.field[trtBG].modify[+,1,"Background"]
   nexteach
Pretty much, except that I don't want it on the hero, but on the thing / component that's the bonus.
Duggan is offline   #5 Reply With Quote
Mathias
Senior Member
Lone Wolf Staff
 
Join Date: May 2005
Posts: 13,207

Old August 31st, 2017, 09:24 AM
Quote:
Originally Posted by Duggan View Post
Pretty much, except that I don't want it on the hero, but on the thing / component that's the bonus.
What about that won't work there? That's what I wrote that foreach to do.
Mathias is offline   #6 Reply With Quote
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 1,502

Old August 31st, 2017, 09:29 AM
When I tried it, it seemed to be reading the tags on the Hero, not the fPlusSk1.
Duggan is offline   #7 Reply With Quote
ShadowChemosh
Senior Member
Volunteer Data File Contributor
 
Join Date: Jan 2010
Location: Chicago, IL (USA)
Posts: 10,729

Old August 31st, 2017, 09:47 AM
Quote:
Originally Posted by Duggan View Post
When I tried it, it seemed to be reading the tags on the Hero, not the fPlusSk1.
The question that seems important is "where" did you place the script that Mathias provided?

Is it in a component script or on the Pick of fPlusSk1? Cause the script Mathias wrote assumes its in one of those places when it runs. If the script is running on the hero then it would pick up the tags from the hero.

Hero Lab Resources:
Pathfinder - d20pfsrd and Pathfinder Pack Setup
3.5 D&D (d20) - Community Server Setup
5E D&D - Community Server Setup
Hero Lab Help - Hero Lab FAQ, Editor Tutorials and Videos, Editor & Scripting Resources.
Created by the community for the community
- Realm Works kickstarter backer (Alpha Wolf) and Beta tester.
- d20 HL package volunteer editor.
ShadowChemosh is offline   #8 Reply With Quote
Aaron
Senior Member
 
Join Date: Oct 2011
Posts: 6,793

Old August 31st, 2017, 12:33 PM
I guess I was missing some context then?
Aaron is offline   #9 Reply With Quote
Duggan
Senior Member
Volunteer Data File Contributor
 
Join Date: Nov 2009
Posts: 1,502

Old August 31st, 2017, 12:52 PM
Quote:
Originally Posted by ShadowChemosh View Post
The question that seems important is "where" did you place the script that Mathias provided?

Is it in a component script or on the Pick of fPlusSk1? Cause the script Mathias wrote assumes its in one of those places when it runs. If the script is running on the hero then it would pick up the tags from the hero.
Sorry for being a while in answering. I had to log on to my computer at home to run the code again. I would swear that I had something identical, or almost identical, added last night to fPlusSk1, but apparently not. That works. Thank you.
Duggan is offline   #10 Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -8. The time now is 11:58 PM.


Powered by vBulletin® - Copyright ©2000 - 2024, vBulletin Solutions, Inc.
wolflair.com copyright ©1998-2016 Lone Wolf Development, Inc. View our Privacy Policy here.