Senior Member
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321
|
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. |
#1 |
Senior Member
Lone Wolf Staff
Join Date: May 2005
Posts: 13,213
|
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. |
#2 |
Senior Member
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321
|
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> Code:
<!-- Track whether the first copy --> <eval index="1" phase="Setup" priority="100"><![CDATA[ doneif (this.ispick = 0) perform assign[Helper.FirstCopy] ]]></eval> |
#3 |
Senior Member
Join Date: Mar 2007
Location: Muskegon, MI
Posts: 2,975
|
Maybe a foreach that assigns firstcopy and then exits after 1 is assigned, or a findchild or something that only gets 1 response.
|
#4 |
Senior Member
Lone Wolf Staff
Join Date: May 2005
Posts: 13,213
|
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> 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> |
#5 |
Senior Member
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321
|
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. |
#6 |
Senior Member
Volunteer Data File Contributor
Join Date: Jun 2010
Posts: 623
|
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"/> 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. |
#7 |
Senior Member
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321
|
@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 - |
#8 |
Senior Member
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321
|
@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 - |
#9 |
Senior Member
Join Date: Jan 2007
Location: NW Arkansas
Posts: 1,321
|
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 - |
#10 |
|
|