Lone Wolf Development Forums  

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

Notices

Reply
 
Thread Tools Display Modes
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 949

Old February 11th, 2016, 10:21 AM
I am working on a dataset where I need to use something similar to the xCount/xIndex/Helper.FirstCopy functionality.

I figured I could set up a component with both fields, and if the component becomes a pick and doesn't have the FirstCopy tag, add it.

How so i deal with the count and index fields though? Are they in incremented by scripts on the overall component or something on the fields themselves?

Any suggestions or examples?
TC

Last edited by TCArknight; February 11th, 2016 at 10:59 AM.
TCArknight is offline   #1 Reply With Quote
Mathias
Senior Member
Lone Wolf Staff
 
Join Date: May 2005
Posts: 12,255

Old February 11th, 2016, 10:56 AM
The xCount and xIndex fields are generated with a foreach that uses a sort order to search through the abilities in order by the level they're added at.

The script that assigns them runs after FirstCopy is assigned, and is only run by the firstcopy. As it finds each copy, it increments a variable by +1 and then assigns the current value of that variable to that copy's xIndex.

Then at the end, that variable's value becomes xCount, and then in a script soon after that, all the other copies find the firstcopy of themselves, and set their own xCount equal to the firstcopy's xCount.
Mathias is online now   #2 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 949

Old February 11th, 2016, 04:55 PM
Hmmm.... I think I'm missing something on adding the FirstCopy tag....
Code:
  <component
    id="xTracker"
    name="Enhancement Gizmo Helper">
    
    <!-- Selection Tag Expressions -->
    <field
      id="xIndex"
      name="Index of Copy"
      type="user"
      defvalue="0">
      </field>
      
    <field
      id="xCount"
      name="Number of Copies"
      type="user"
      defvalue="0">
      </field>  
    </component>
This is the component that adds the xIndex and xCount fields and is a component included in the compset for the needed abilities.

Code:
    
    <!-- Track whether the first copy -->
    <eval index="1" phase="Setup" priority="100"><![CDATA[
      doneif (this.ispick = 0)
      
      perform assign[Helper.FirstCopy]
      ]]></eval>
This is the eval script for adding the FirstCopy tag. If I put it on the xTracker component, every <thing> will then get a FirstCopy tag...
TCArknight is offline   #3 Reply With Quote
AndrewD2
Senior Member
 
Join Date: Mar 2007
Location: Muskegon, MI
Posts: 2,975

Old February 11th, 2016, 09:00 PM
Maybe a foreach that assigns firstcopy and then exits after 1 is assigned, or a findchild or something that only gets 1 response.
AndrewD2 is offline   #4 Reply With Quote
Mathias
Senior Member
Lone Wolf Staff
 
Join Date: May 2005
Posts: 12,255

Old February 12th, 2016, 08:35 AM
Okay, looks like the quickadd mechanism that we use isn't in any of the documentation, so here's the relevant scripts in Pathfinder;

On the hero:

Code:
    <eval value="31" phase="PostLevel" priority="149" name="Prepare First Copy"><![CDATA[
      ~This eval script is meant to foreach through all the class specials
      ~and mark each as a FirstCopy or not. We do this with a foreach rather
      ~than a component script so that we can proceed from the lower level
      ~copies to the higher level copies, ensuring that Helper.FirstCopy ends
      ~up on the lowest level copy that is not disabled or replaced.
      foreach pick in hero from BaseClSpec where "!Helper.SpcDisable & !Helper.SpcReplace" sortas ClassSpec
        ~For things which are multiple copies, each independant, all of them are "first" copies.
        if (eachpick.tagis[Helper.MultiCopy] <> 0) then
          perform eachpick.assign[Helper.FirstCopy]
        else

          ~add the first active thing we found to our quick list - if quickadd
          ~returns nonzero, we were the first version, so add the "first copy" tag
          ~to ourselves.
          ~NOTE: at this point, we'll assume that the first copy is the only copy -
          ~the OnlyCopy tag is deleted in the "Determine First Copy" script if
          ~there's more than one.
          if (eachpick.quickadd <> 0) then
            perform eachpick.assign[Helper.FirstCopy]
            perform eachpick.assign[Helper.OnlyCopy]
            perform eachpick.quickadd
            endif
          endif
        nexteach

      ~The next step is going to take place in the BaseClSpec component script.
      ]]></eval>
On a component that's added to everything that needs FirstCopy mechanics:

Code:
    <!-- Note that the first part of this, "Prepare First Copy" has been moved
      to a script on the actor, and now uses a foreach instead of a component
      script on this component. This is because a foreach can use a SortAs to
      proceed up the copies of class specials, assigning Helper.FirstCopy to the
      lowest level copy of a class special which isn't disabled or replaced. The
      previous implementation would assign Helper.FirstCopy to the first copy
      of a multi-bootstrapped class special to run the component script (which
      was random since they all had the same priority).

      That would lead to a bug where crossblooded sorcerers could not target a
      class special to be re-enabled even though they were high enough level to
      do so (because Helper.FirstCopy had been assigned to the 2nd or 3rd copy
      of the class ability).

      The gap between the actor script foreach and this step has also been
      widened slightly, so that certain targetted scripts (like those of the
      crossblooded sorcerer) can occur between them.
      -->
    <eval index="3" phase="PostLevel" priority="155" name="Determine First Copy"><![CDATA[
      doneif (tagis[Helper.FirstCopy] <> 0)

      ~if we're not the first copy of a special ability, we need to set up a
      ~redirection to the actual first copy. That means whenever another pick
      ~does a "hero.child[x]" to find pick x, they always arrive at the first
      ~copy. This allows the first copy to be determined at every evaluation,
      ~and the first copy is then the one used to display the totals for the
      ~ability, even if it's added in multiple places (e.g. sneak attack, which
      ~can be added by multiple classes). The first copy is the one in the
      ~quickfind list, so retrieve it.
      perform quickfind.setfocus

      ~if we found a copy to set our focus to, we're a secondary copy of this
      ~ability, delete the Helper.OnlyCopy tag from the first (primary) copy.
      ~That means the Helper.OnlyCopy tag will only be left on those picks that
      ~are the only copy of their things.
      if (state.isfocus <> 0) then
        perform focus.redirect
        perform assign[Helper.SpecUp]
        perform focus.delete[Helper.OnlyCopy]
        endif
      ]]></eval>

    <eval index="4" phase="PostLevel" priority="200" name="Calc xAllLev and xMaxLev"><![CDATA[
      ~we only need to run this if we're not the only copy
      ~if we aren't the only copy, we need to search the rest of our copies and get information
      if (tagis[Helper.OnlyCopy] = 0) then

        ~only run these for the first copy
        if (tagis[Helper.FirstCopy] <> 0) then

          var searchexpr as string
          searchexpr = "thingid." & this.idstring

          var index as number
          index = 1

          var runonce as number

          foreach pick in hero from BaseClSpec where searchexpr sortas ClSpecSrch

            ~generate an index value
            ~if our SpecSource tags are different from the last thing we checked, reset the counter
            if (eachpick.intersect[SpecSource,TempSource,all] = 0) then
              perform delete[TempSource.?]
              perform eachpick.pulltags[SpecSource.?,TempSource]
              index = 1

              ~once for each class, we want to set our xalllev value, so if we
              ~find that we're on a new class, we reset that test, so that we'll
              ~get the new value for the new class
              runonce = 0
              endif

            ~we only calculate the xAllLev of the FirstCopy one time, based on
            ~the first non-disabled copy we find.
            if (runonce = 0) then

              ~some things should only be done for active copies
              if (eachpick.tagis[Helper.SpcDisable] = 0) then
                ~we found a copy, so we won't be calculating this again.
                runonce = 1

                ~we use the copy we found to calculate our xAllLev and xMaxLev
                ~values.
                if (eachpick.tagis[Helper.FirstCopy] <> 0) then
                  field[xAllLev].value += eachpick.field[xTotalLev].value
                  field[xMaxLev].value = maximum(field[xMaxLev].value, eachpick.field[xTotalLev].value)
                else
                  field[xAllLev].value += eachpick.field[xTotalLev].value + eachpick.field[xEffectLev].value
                  field[xMaxLev].value = maximum(field[xMaxLev].value, eachpick.field[xTotalLev].value + eachpick.field[xEffectLev].value)
                  endif
                endif
              endif

            ~assign this thing the current index value, then increment the index for the next thing
            eachpick.field[xIndex].value = index
            index += 1

            nexteach

        else
          field[xCount].value += 1
          endif
      else
        ~if we are the only copy, our xAllLev and xMaxLev fields are simply our own xTotalLev
        ~and xIndex and xCount = 1
        field[xAllLev].value = field[xTotalLev].value
        field[xMaxLev].value = field[xTotalLev].value
        field[xIndex].value = 1
        field[xCount].value = 1
        endif

      ~The new UseTotLev tag means we should use our total character level
      if (tagis[Helper.UseTotLev] <> 0) then
        field[xAllLev].value = maximum(field[xAllLev].value,#totallevelcount[])
        field[xMaxLev].value = maximum(field[xMaxLev].value,#totallevelcount[])
        endif

      perform delete[TempSource.?]
      ]]></eval>

    <eval index="5" phase="PostLevel" priority="250" name="Calc xCount, copy xAllLev and xMaxLev"><![CDATA[
      ~we only need to run this if we're not the only copy
      ~if we aren't the only copy, we need to search the rest of our copies and get information
      doneif (tagis[Helper.OnlyCopy] <> 0)

      var index as number
      var source as string

      ~only run these if we're the first copy
      if (tagis[Helper.FirstCopy] <> 0) then
        var searchexpr as string
        searchexpr = "thingid." & this.idstring

        foreach pick in hero from BaseClSpec where searchexpr sortas ClSpecSrch
          ~set the xAllLev and xMaxLev fields of anything we come across (other than ourself)
          if (eachpick.tagis[Helper.FirstCopy] = 0) then
             eachpick.field[xAllLev].value = field[xAllLev].value
             eachpick.field[xMaxLev].value = field[xMaxLev].value
             endif

          ~some things should only be done for active copies
          if (eachpick.tagis[Helper.SpcDisable] = 0) then
            ~if the special has reached the appropriate level, add it to our count
            if (eachpick.tagis[Helper.UseOwnLev] <> 0) then
              if (eachpick.tagvalue[ClSpecWhen.?] <= eachpick.field[xTotalLev].value) then
                field[xCount].value += 1
                ~any AddReq tags that have been applied to an active copy apply to the FirstCopy, too
                perform eachpick.pulltags[AddReq.?]
                endif
            else

              ~generate an index value
              ~if our SpecSource tags are different from the last thing we checked, reset the counter
              if (eachpick.intersect[SpecSource,TempSource,all] = 0) then
                perform delete[TempSource.?]
                perform eachpick.pulltags[SpecSource.?,TempSource]
                index = 1
                endif

              if (eachpick.tagvalue[ClSpecWhen.?] <= eachpick.field[xAllLev].value) then
                field[xCount].value = maximum(field[xCount].value, index)
                index += 1
                ~any AddReq tags that have been applied to an active copy apply to the FirstCopy, too
                perform eachpick.pulltags[AddReq.?]
                endif

              endif
            endif
          nexteach
        endif

      perform delete[TempSource.?]
      ]]></eval>
Mathias is online now   #5 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 949

Old February 12th, 2016, 10:43 AM
Thank you Mathias!

I'll see what I can do with this. I'm sure this will help others too, so I'll post what I do.
TCArknight is offline   #6 Reply With Quote
risner
Senior Member
Volunteer Data File Contributor
 
Join Date: Jun 2010
Posts: 610

Old July 25th, 2018, 10:11 AM
Mathias, I'm trying to implement this code. I had to guess at the sortsets (included below). I also have a SpecSource script to copy source from parents, so duplicate specials from different classes have different SpecSource values.

The xTotal, xAllLev, and xMaxLev are not right. I suspect it's from the SortSets and the missing Calculation scripts. xIndex is right (starts at 1 on first copy and goes up.) But xCount isn't right either.

Are there examples of Helper.MultiCopy in pathfinder?

Code:
My SortSets
    id="ClassSpec"
    <sortkey isfield="no" id="ClSpecWhen" isascend="yes"/>

    id="ClSpecSrch"
    <sortkey isfield="no" id="SpecSource" isascend="yes"/>
    <sortkey isfield="no" id="ClSpecWhen" isascend="yes"/>
Note: I've kept a lot of "Pathfinder" ism's like ClSpecWhen due to being easier to remember a familiar item.

Last edited by risner; July 26th, 2018 at 07:58 AM. Reason: Figured out a typo causing the multiple classes to share the same bootstrap. Made them unique fixed the tagging issue.
risner is offline   #7 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 949

Old August 10th, 2018, 05:09 AM
@risner: See if this helps.

In my system, Talents (the Talent component) can be taken multiple times and so need the xCount/Index functionality. "Effects" is a phase right after Setup.

1) Add xCount and xIndex (and xTotal, xAllLev, and xMaxLev if using them ) fields to the component you want to use this on
2) Add the "Prepare First Copy" script to the actor component.
3) Add the other scripts on the component you want to track.

I'm not using the xTotal, xAllLev, and xMaxLev because the system doesn't need it. Does that help?

Working on -
TCArknight is offline   #8 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 949

Old August 10th, 2018, 07:21 AM
@Mathias:
How would this need to be modified if the component also includes a Domain (domDomain field)?

For example, I have a talent called Expertise which allows for user entry of the specific expertise.

Right now, if I take expertise and specify a domain value, it correctly is tagged as a FirstCopy/OnlyCopy with xIndex/xCount of 1/1. If I take Expertise again, no matter if I specify a different domain value, it's counting the first Expertise taken as the FirstCopy, and the xCount goes to 2.

First take:
Expertise: Ancient Gods; xCount = 1, xIndex = 1, Helper.FirstCopy, Helper.OnlyCopy, User.NeedDomain

take a second and third time:
Expertise: Ancient Gods; xCount = 3, xIndex = 1, Helper.FirstCopy, User.NeedDomain
Expertise: Firearms; xCount = 2, xIndex = 2, Helper.SpecUp, User.NeedDomain
Expertise: Firearms; xCount = 2, xIndex = 3, Helper.SpecUp, User.NeedDomain

I'm looking for it to be:
Expertise: Ancient Gods; xCount = 1, xIndex = 1, Helper.FirstCopy, Helper.OnlyCopy, User.NeedDomain
Expertise: Firearms; xCount = 2, xIndex = 1, Helper.FirstCopy, User.NeedDomain
Expertise: Firearms; xCount = 2, xIndex = 2, Helper.SpecUp, User.NeedDomain

Does that make sense? Any suggestions?

Thanks!
TC

Working on -
TCArknight is offline   #9 Reply With Quote
TCArknight
Senior Member
 
Join Date: Jan 2007
Location: NW Arkansas
Posts: 949

Old August 12th, 2018, 08:01 AM
Well, after a few stops and starts and bumps, I've managed to get this working the way I intended.

It required some extra Helper/User tags, but in the end it works.

I'll eventually make notes and share.

Working on -
TCArknight 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 08:39 AM.


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