• Please note: In an effort to ensure that all of our users feel welcome on our forums, we’ve updated our forum rules. You can review the updated rules here: http://forums.wolflair.com/showthread.php?t=5528.

    If a fellow Community member is not following the forum rules, please report the post by clicking the Report button (the red yield sign on the left) located on every post. This will notify the moderators directly. If you have any questions about these new rules, please contact support@wolflair.com.

    - The Lone Wolf Development Team

"This ability (or an equivalent) has already been added to the hero"

TheIronGolem

Well-known member
Some class specials grant a bonus feat at a certain level. The classic example is the Ranger with Endurance. In Hero Lab, this means bootstrapping the feat from a class special with a condition of "count:Classes.classID >= X", so that the feat only appears live on the hero once they have the requisite number of levels. However, if the character doesn't have the requisite number of class levels it's still possible to add the feat to the character by hand, and prerequisites are handled normally by HL.

I'm trying to implement a class feature that does this, but with my custom component for Spheres of Power (a "talent", which if you're not familiar with that system works a lot like a feat). I've found that if I make a talent Add Once instead of Unique, the user can add a conditionally-bootstrapped talent "prematurely", but in the menu it appears with a validation error saying "this ability (or an equivalent) has already been added to the hero", like so:

30aba5i.png


I'm trying to figure out how to make my component's behavior in this respect mirror that of feats, so that a user with levels in this class have the option of taking the talent before it's granted by the class, without seeing that validation error. This is because the class feature in question gives the hero a bonus talent at the appropriate level if they already have the talent in question.

I know I can simply grant a bonus talent and then use an eval rule to yell at the user if they don't have the talent in question. But I'm hoping to automate this so that required action on the user's part is minimized.

I also realize this issue doesn't actually stop the user from adding the talent if they want to, but I'd really like to find a solution that doesn't require me to tell users "it's fine, ignore the error" - especially since most users would probably not even ask me about it and will instead incorrectly assume that they can't take the talent.
 
You can assign a level as a bootstrap condition. Look at the bottom of this page for a code example:

http://hlkitwiki.wolflair.com/index.php5?title=Bootstrap_Element_(Data)

I know; I'm already doing that and the conditional bootstrap works just fine.

The problem I'm trying to solve is the case of when the user tries to manually add the ability in question at an earlier level. HL handles this fine with feats; try adding Endurance to a level 1 or 2 Ranger and you'll find you can do it with no issue. But if you do the same thing with my component, it gives that validation error. I'm trying to figure out why that is.
 
Are all your components totally made by you or are you including LW components in your component set?

Several LW components are included: Value, Ability, Tracker, DescInfo, Domain, Activated, UserSelect, SetName, SpecialTab, StatblName.

I tried adding in the other components that feats use as an experiment, but no joy.
 
Several LW components are included: Value, Ability, Tracker, DescInfo, Domain, Activated, UserSelect, SetName, SpecialTab, StatblName.

I tried adding in the other components that feats use as an experiment, but no joy.
Actually I expect one of those to be the one giving the error. The error message is NOT a HL core feature. I am 99% sure its coming from a pre-req script on the LW component Ability.

I just tested using a Rogue Talent and a Endurance feat bootstrapped to an Adjustment. Both the Rogue Talent and the Endurance feat give the "exact" same error message about the ability already being added. :(

Noname.jpg
 
I'm trying to implement a class feature that does this, but with my custom component for Spheres of Power (a "talent", which if you're not familiar with that system works a lot like a feat). I've found that if I make a talent Add Once instead of Unique, the user can add a conditionally-bootstrapped talent "prematurely", but in the menu it appears with a validation error saying "this ability (or an equivalent) has already been added to the hero", like so:
Re-reading this. Maybe I am confused. I think your saying the issue is your bootstrapped talent which is not yet "LIVE" is causing an error in the list? Are you 100% sure the talent is not live on the hero?
 
Re-reading this. Maybe I am confused. I think your saying the issue is your bootstrapped talent which is not yet "LIVE" is causing an error in the list? Are you 100% sure the talent is not live on the hero?

Pretty sure, yeah. As it happens, this talent is one that increases the damage done by a different ability, so I can tell whether it's live pretty easily just by checking the damage listed in that ability's livename:

Level 6:
2vx13py.png


Level 7:
15npo2v.png


I also tested the talent with a notify statement, just to be sure.

I'd be inclined to agree that the Ability component is the culprit, except that feats also have the Ability component and the Ranger's Endurance bonus feat doesn't have the same issue. I really hope that isn't the problem, because I definitely can't remove Ability from the compset!
 
Ranger's Endurance bonus feat doesn't have the same issue. I really hope that isn't the problem, because I definitely can't remove Ability from the compset!
Well it does as soon as a ranger is level 3+ because the endurance feat becomes live on the hero.

Based on what your saying I agree with you on why you have confusion because I have it now also. Until the talent is live (which the bootstrap condition is preventing) it should NOT be causing an error message to appear. :(

I just created a very simple test user file. An adjustment that bootstraps the rogue talent "Acrobatic Assist" and sets a simple condition requiring level 2+ rogue. At level 1 "Acrobatic Assist" has no warning about an equivalent ability. As soon as I hit level 2 I get the warning...... :confused: :confused:
 
Really sorry I think you may have to wait for Mathias or Aaron I can't see why its doing what its doing.

Just a stupid question you have nothing the "containerreq" section for the talent do you? Maybe for one last check can you post the full XML for this talent that is causing the issue?
 
Huh, weird. I even tried setting the bootstrap condition to "1=2" to ensure the talent would never go live. Same error.

EDIT: Oops, didn't see this:
Just a stupid question you have nothing the "containerreq" section for the talent do you? Maybe for one last check can you post the full XML for this talent that is causing the issue?

Couldn't hurt! And nope, no containerreq. Come to think of it I'm not sure I've ever even used one of those.
Code:
  <thing id="sopTlCreGD" name="Greater Destroy" description="Increase the amount of damage dealt when you use your destroy ability to 1d6 + your caster level." compset="SoPTalent" summary="You do more damage with your destroy ability" uniqueness="useronce">
    <fieldval field="abValue" value="6"/>
    <fieldval field="abValue2" value="1"/>
    <usesource source="pDDSSoP"/>
    <tag group="SoPSphere" tag="Creat"/>
    <tag group="SoPTlClass" tag="Talent"/>
    <tag group="SoPBanDesc" tag="CreAlter"/>
    <tag group="Helper" tag="SpecUp"/>
    <eval phase="PostLevel" priority="5000"><![CDATA[
      ~ Stop if we're disabled
      doneif (tagis[Helper.SpcDisable] <> 0)

      ~ Find the Destroy ability
      perform hero.childfound[sopTlCreDs].setfocus
      doneif (state.isfocus = 0)

      ~ Replace die size, swap out CL progression tag
      focus.field[abValue2].value = maximum(focus.field[abValue2].value,field[abValue].value)
      perform focus.tagreplace[SoPAbV3Sc.1_2CL,SoPAbV3Sc.1_1CL]

      ~ Update description of Destroy
      #appenddesc[sopTlCreDs, "{b}" & field[thingname].text & ":{/b} Increase the amount of damage dealt when you use your destroy ability to 1d6 + your caster level."]]]></eval>
    </thing>
 
Last edited:
Huh, weird.
LOL I give you points cause I can not currently see anything wrong. This should not be acting this way. :(

That talent/Thing looks really normal and you are not doing anything that special in the script. Its nice clean code don't get me wrong. But nothing in it should be causing this......... :confused:
 
Code:
    <prereq message="This ability (or an equivalent) has already been added to the hero.">
      <match><![CDATA[
        thing.useronce
        ]]></match>
      <validate><![CDATA[
        ~ If this is a pick, we're valid
        validif (@ispick <> 0)

        ~ Otherwise, see if the identity tag for this thing appears in the
        ~ "HasFeat" group on the Hero. If it does, we already have this feat,
        ~ so we don't need another copy
        if (altthing.tagis[component.BaseFeat] <> 0) then
          @valid = !altthing.tagmatch[thingid,IsFeat,current]
        else
        ~if we're not a feat, perform the same check using the HasAbility group
          @valid = !altthing.tagmatch[thingid,Ability,current]
          endif
        ]]></validate>
      </prereq>

That's the code for the pre-req. I would say check you custom abilities you've added, see if any of them have the same Ability tag as the one you want to add there. If so, I assume it would be for the purposes of meeting the same pre-reqs as the other, but if that is the case you should be useing HasAbility tags. Although there is a mismatch between the note and code there... Maybe it switched recently? I will look into it.
 
That's the code for the pre-req. I would say check you custom abilities you've added, see if any of them have the same Ability tag as the one you want to add there. If so, I assume it would be for the purposes of meeting the same pre-reqs as the other, but if that is the case you should be useing HasAbility tags. Although there is a mismatch between the note and code there... Maybe it switched recently? I will look into it.

Thanks, Aaron. I looked carefully through all my own code and found nothing that would forward Ability.? tags or assign them to the hero/container. But in order to fully rule out any problem with the talent component I decided to do another experiment.

I started by creating a bare-bones component that has no fields, no tags, no scripts, and no other components in its compset. I also made a single Thing with this component (again, no tags/scripts) and boostrapped it from a class ability with an impossible condition (1=2)

Code:
	  <component
    id="SoPTEST"
	name="test"
	autocompset="yes"
	hasshortname="no"
	ispublic="yes">
	</component>
...
<thing id="SoPtest" name="test thingy" compset="SoPTEST"></thing>

After compiling and reloading, I confirmed that the SoPtest pick existed, but wasn't live. There was no Ability.SoPtest tag on the hero. That's not surprising, of course, because there's no other component in the SoPTEST compset. So I added Ability to the compset:

Code:
	  <component
    id="SoPTEST"
	name="test"
	autocompset="no"
	hasshortname="no"
	ispublic="yes">
	</component>

    <compset
    id="SoPTEST">
    <compref component="SoPTEST"/>
    <compref component="Ability"/>
	</compset>

Again, there's nothing happening in the component or in any Thing from that component.

But this time, the hero had the Ability.SoPtest tag. So I'm guessing that the tag is being forwarded/assigned somewhere from the Ability component, but (because this does not happen with feats), this forwarding/assignment must be preventable by means I do not yet know.

I guess I could have a script that loops through talents and deletes Ability tags from the hero if the corresponding pick isn't live, but that feels pretty hacky and prone to false positives.
 
Here's something else that confuses me: If I test the bootstrapped talent with "hero.childlives[talentID]", this always returns 1, indicating that the talent is indeed live. This happens even if the bootstrap has an impossible condition, and without regard to whether the test occurs before or after the bootstrap condition is scheduled. The only way childlives will fail is if I remove the bootstrap. And yet the talent doesn't act as if it is live unless the boostrap conditions are met (apart from forwarding its Ability tag).

Unfortunately this means my workaround of "delete the Ability tag if the talent isn't live" isn't going to be viable.
 
Here's something else that confuses me: If I test the bootstrapped talent with "hero.childlives[talentID]", this always returns 1, indicating that the talent is indeed live. This happens even if the bootstrap has an impossible condition, and without regard to whether the test occurs before or after the bootstrap condition is scheduled. The only way childlives will fail is if I remove the bootstrap. And yet the talent doesn't act as if it is live unless the boostrap conditions are met (apart from forwarding its Ability tag).

Unfortunately this means my workaround of "delete the Ability tag if the talent isn't live" isn't going to be viable.

I just did a simple test with this in the sample game system:

Code:
    <bootstrap thing="abMarksman">
      <containerreq phase="Initialize" priority="1000">FALSE</containerreq>
      </bootstrap>

    <eval index="1" phase="Initialize" priority="500"><![CDATA[
      debug hero.childlives[abMarksman]
      ]]></eval>
    <eval index="2" phase="PreTraits" priority="500"><![CDATA[
      debug hero.childlives[abMarksman]
      ]]></eval>
Script 1 runs before the bootstrap container test, script 2 runs after.

Right after the pick is added, script 1 prints "1", script 2 prints "0" - this happens because the pick is assumed to be live until the live test is actually run. After that, both scripts print "0". So the basics of this functionality seem to be working.

Are you sure there's not another copy of the pick on the hero that is live? If that's happening, it will make childlives return 1.

If that's not causing it, can you package up your data files and put them on Dropbox (or a similar service) so I can download them and see what's causing it? If not, you can email them to me at colen@wolflair.com.

Hope this helps!
 
Right after the pick is added, script 1 prints "1", script 2 prints "0" - this happens because the pick is assumed to be live until the live test is actually run. After that, both scripts print "0". So the basics of this functionality seem to be working.

Ah, okay, I didn't realize that. So that's one less thing to confuse me at least.

Are you sure there's not another copy of the pick on the hero that is live? If that's happening, it will make childlives return 1.

I'm 99% sure there's no other instance of the pick loading anywhere. Its thing ID doesn't turn up in any of the "show selection..." debug menus unless the class archetype I'm developing is present on the hero.

If that's not causing it, can you package up your data files and put them on Dropbox (or a similar service) so I can download them and see what's causing it? If not, you can email them to me at colen@wolflair.com.

Sent!
 
To update everyone awaiting the exciting conclusion of this thread - childlives is working as expected, but TheIronGolem pointed me towards another bug in Hero Lab that we will be fixing soon. TIG has a workaround that will resolve the issue until the bugfix comes out.
 
Back
Top