• 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

Equipment validation

Minous

Well-known member
Is it possible to create something that can be added to a character that checks for minimum quantities of a given list of equipment?

What I am trying to do is ensure that all of my characters always have at least 3 alchemist fires, anti-plague, anti-toxin and a few other items. (IE stuff that everyone should have) How would one go about looking at the character's gear, counting up what it has and checking that against a list of what it should have?

Yes I know this will involve the editor, just looking for a good starting point.
 
I would create an item on the Simple table that uses an eval rule to enforce this. Name this item something like "campaign rules".

Then, create a mechanic, and bootstrap this item from it - that will place it on your character.

You're going to be using a foreach pick in hero to search the character's gear.

My 2014 Gen Con seminar was about how to set up searches: https://www.youtube.com/watch?v=9UPWoih8-q8&t=890s
 
Thanks for that info, I have a basic working tool. I used a Vanity instead of a mechanic as I wanted it to be an optional check. One of the last things I have to check for is custom CLW wands. the easiest thing I saw would be to iterate over thingid.sCustomWnd and look for the gizmo pick id spCureLig1. How would one go about checking the gizmo values of a eachpick ?
 
Use findchild to get to the spell inside the wand and check that, then clear the focus and check the next.

Something like:

Code:
foreach BLAH
  eachpick.gizmo.findchild[BaseSpell].setfocus

  if (state.isfocus <> 0) then
  ~ DO WHATEVER
    endif

  perform state.clearfocus
  nexteach
 
Why the heck don't we forward a tag to the wand to say which spell is in there? That's something that really ought to be more accessible. I'll get that fixed for the next update.
 
Why the heck don't we forward a tag to the wand to say which spell is in there? That's something that really ought to be more accessible. I'll get that fixed for the next update.
I have wondered that very question before. :) I think I actually did this for the new wand gizmo I added to d20. If not I should make sure it does the same thing....
 
Code:
      ~ CLW
      var item_count as number
      item_count = 30
      foreach pick in hero where "thingid.sCustomWnd"
        eachpick.gizmo.findchild[spCureLig1].setfocus
          if (state.isfocus <> 0) then
            item_count = item_count -(eachpick.field[trkMax] - eachpick.field[trkUser])
          endif

        perform state.clearfocus
        nexteach
      if (item_count > 0) then
        field[DescAppend].text = field[DescAppend].text & "Need to buy " & item_count  & " Cure Light's\n"
      endif

is now throwing

Code:
Hero Lab was forced to stop compilation after the following errors were detected:

Syntax error in 'eval' script for Thing 'pfsGearChk' (Eval Script '#15') on line 5
  -> Non-existent component 'spCureLig1' used by script
 
Follow Aaron's script more exactly where he says what findchild to use. Or, start there, and then modify it to only find CLW.
 
Last edited:
Im kind of at a loss then, your saying that findchild doesnt work that way, but I am using the example above. I have tired it with findchild[BaseSpell] and I am not getting anywhere.
 
Post #7 here talks about findchild: http://forums.wolflair.com/showthread.php?t=21663

Homework assignment: study that, and tell me what's wrong with findchild[spCureLig1] and why findchild[BaseSpell] isn't specific to cure light wounds - why it's ok with any spell that's there.

Honestly I have no clue, I have been digging thru the lacking documentation, I have read your linked post at least 5 times, Googled for similar use cases, and tried several different attempts at what I think should work for findchild, but every single time I try something line 5 throws an error. As a programmer myself I wouldnt be asking for assistance unless I needed it. The simple eachpick.gizmo.findchild[BaseSpell].setfocus (which is exactly what was given above) fails to compile. If it was a case of BaseSpell finding all spells I could work with that and add in extra if's to achieve my goal. However its failing to compile, which means there must be a syntax issue that I am missing.
 
Last edited:
If a line of code in Hero Lab isn't blank, about the flow (deciding where to go next, like a foreach/nexteach, or an if () then/endif) or a comment, it has to be one of two things:

It has to set one thing equal to another thing.

or

It has to start with "perform"

So in this case, what you want to do is to perform the setfocus operation, after transitioning to the location of that spell.
 
Ok, I think I have moved on past that issue, now the state.isfocus is throwing an error.

Code:
      ~ CLW
      var item_count as number
      item_count = 30
      foreach pick in hero where "thingid.sCustomWnd"
          perform eachpick.gizmo.findchild[BaseSpell,"iwSpells.spCureLig1"].setfocus
          
          if (state.isfocus <> 0) then
            field[DescAppend].text = state.field[actName]
            ~item_count = item_count -(eachpick.field[trkMax] - eachpick.field[trkUser])
          endif
Code:
Hero Lab was forced to stop compilation after the following errors were detected:

Syntax error in 'eval' script for Thing 'pfsGearChk' (Eval Script '#15') on line 8
  -> Reference to undeclared variable: 'state'
 
"state.field[actName]" is the problem.

state isn't a transition to a pick, and you have nothing to close the reference ".value/.text", depending on the field.
 
Guys Im not trying to be difficult here but a little guidance/help is needed. Just pointing out what is broken doesn't provide much insight on the solution. I've been digging around both the almost non-existent documentation and random forum posts, Im drowning here. HL uses its own proprietary language that isnt quickly learned, and is confusing as hell to a programmer.
 
Guys Im not trying to be difficult here but a little guidance/help is needed. Just pointing out what is broken doesn't provide much insight on the solution. I've been digging around both the almost non-existent documentation and random forum posts, Im drowning here. HL uses its own proprietary language that isnt quickly learned, and is confusing as hell to a programmer.
Be careful when counting "line" numbers in HL scripts. I see you as being one line of code off:

Code:
      ~ CLW
      var item_count as number
      item_count = 30
      foreach pick in hero where "thingid.sCustomWnd"
          perform eachpick.gizmo.findchild[BaseSpell,"iwSpells.spCureLig1"].setfocus
          
          if (state.isfocus <> 0) then
            field[DescAppend].text = [B]state.field[actName][/B]
            ~item_count = item_count -(eachpick.field[trkMax] - eachpick.field[trkUser])
          endif
The highlighted code above is what is wrong and Aaron is talking about. NOT the state.isfocus which is correct.
 
I've been digging around both the almost non-existent documentation and random forum posts, Im drowning here. HL uses its own proprietary language that isnt quickly learned, and is confusing as hell to a programmer.
So I agree mostly with what your finding here about HL scripting. On the other hand you are dealing with Gizmo's which is REALLY hard place to do scripting. You didn't just jump into the deep end of HL scripting you went in with rocks on your feat and sharks in the water. :D

Overall you are actually doing really well.

The issue above is transitioning to the correct Pick in HL. Transitioning means to have a pointer to the correct location or the correct Xpath if you are use to XML.

In an XML structure:
Code:
<item_master>
   <item>
      <partnumber>
      <part_desc>
   </item>
</item_master>
So for the above if I wanted to reference Part Description I would have "transition" down the Xpath to it. Like so:

Code:
item_master\item\part_desc

This concept works exactly the same in HL which is built on XML tech:
Code:
Top Level Container (Hero)
-Picks live on the Hero (child)
--A feat on the character (fDodge)
---Fields on fDodge
----Values
---Tags on fDodge
--A weapon on the character (wLongsword)
---Fields on wLongsword
----Values
---Tags on wLongsword
--A Magic Weapon (gizmo)
---Longsword Pick (wLongsword)
Based on the above if I wanted to access the non-magical longsword I would do this:
Code:
hero.child[wLongsword].field[xxx].value

If in a script you have "just" a field name:
Code:
field[abValue].value
HL adds in the transition logic "This" for you meaning you are getting the field from the Pick you are actually on.
Code:
this.field[abValue].value

The last thought is "eachpick" which means a generic pointer name that transitions to the Pick that the foreach loop grabbed.

And finally we have "setfocus" which is another generic pointer that is used to place a memory pointer at a single specific Pick. From the HL example above I could say "setfocus" to the fDodge feat. Once I have set that pointer I can access any "field" or "tag" on the fDodge feat by using the "focus" keyword which has all the "transition" logic built in from the setfocus.
Code:
~ Set pointer
perform hero.child[fDodge].setfocus
~ Did the pointer actually set to the fDodge fea?
doneif (state.isfocus = 0) 

~ Increase the abValue field on the fDodge feat by 1
focus.field[abValue].value += 1

~ Set the disable feat tag on to fDodge
perform focus.assign[Helper.ftDisable]

So now based on all the above can you see what is wrong here? Is "state" anything I have listed above for transitioning? Is "field[actName]" not a complete transition?
Code:
state.field[actName]
 
Thanks for the help it actually explains a lot. Looking at my code below, line 10 isnt finding a custom Cure Light Wounds wand with the search that I am giving. Any suggestions? PS I am using the found variable to enter and exit the gizmo scope and if found do the tracker math.

Code:
      ~ CLW
      var item_count as number
      var found as number
      found = 0
      ~ set the number of charges
      item_count = 30
      ~ itterate over custom wands
      foreach pick in hero where "thingid.sCustomWnd"
        ~ check if the wand has a CLW 
        perform eachpick.gizmo.findchild[BaseSpell,"iwSpells.spCureLig1"].setfocus
        if (state.isfocus <> 0) then 
          found =1
        endif
        ~ exit gizmo
        perform state.clearfocus
        if (found = 1) then
          ~ calculate the remaining needed charges 
          ~ Current total - Number of currently used charges)
          item_count = item_count - eachpick.field[trkLeft].value
        endif
        found = 0
        ~ move to next pick
        nexteach
      ~ if we still need a quanity include it in this Vanity's description 
      if (item_count > 0) then
        field[DescAppend].text = field[DescAppend].text & "Need to buy " & item_count  & " Cure Light's\n"
      endif
 
Ok, so I scrapped my previous approach since I wasn't able to get iwSpells to be detected as valid. See below for the working version of the code:

Code:
      ~ CLW
      var item_count as number
      var found as number
      found = 0
      ~ set the number of charges
      item_count = 30
      ~ itterate over custom wands
      foreach pick in hero where "thingid.sCustomWnd"
        ~ check if the wand has a CLW 
        foreach pick in eachpick.gizmo
          if (compare(eachpick.idstring,"spCureLig1") = 0) then
            found = 1
          endif
        nexteach
        if (found = 1) then
          ~ calculate the remaining needed charges 
          item_count = item_count - eachpick.field[trkLeft].value
        endif
        found = 0
        ~ move to next pick
        nexteach
      ~ if we still need a quanity include it in this Vanity's description 
      if (item_count > 0) then
        field[DescAppend].text = field[DescAppend].text & "Need to buy " & item_count  & " Cure Light's\n"
      endif
 
Code:
      ~ CLW
      var item_count as number
      var found as number
      found = 0
      ~ set the number of charges
      item_count = 30
      ~ itterate over custom wands
      foreach pick in hero where "thingid.sCustomWnd"
        ~ check if the wand has a CLW 
        foreach pick in eachpick.gizmo
          [B]if (compare(eachpick.idstring,"spCureLig1") = 0) then[/B]
            found = 1
          endif
        nexteach
        if (found = 1) then
          ~ calculate the remaining needed charges 
          item_count = item_count - eachpick.field[trkLeft].value
        endif
        found = 0
        ~ move to next pick
        nexteach
      ~ if we still need a quanity include it in this Vanity's description 
      if (item_count > 0) then
        field[DescAppend].text = field[DescAppend].text & "Need to buy " & item_count  & " Cure Light's\n"
      endif
As an FYI the above code to check a tag should be avoided as string compare vs tag compare is allot slower and harder for HL to do.

Instead just do this:
Code:
if (eachpick.tagis[thingid.spCureLig1) = 1) then

To expand on this concept never use Thing ID to check actually. Better off in the long run checking a different tag. The one reason is that down the road you may have multiple Things that count as the same Thing for the purpose of your script. In example for checking for a longsword we would use IsWeapon.wLongsword not thingid.wLongsword. This allows easy logic to be added for weapons that get treated "like" a longsword (ie Aldori Dueling Sword).

For a spell I would use KnowSpell.? tag group:
Code:
if (eachpick.tagis[KnowSpell.spCureLig1) = 1) then

Just an FYI as the above will "work" but its better to check tags always. :)
 
Back
Top