View Single Post
Mathias
Senior Member
Lone Wolf Staff
 
Join Date: May 2005
Posts: 13,207

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 offline   #5 Reply With Quote