What can be done with Tags?
Here are some common things which can be done with tags.
~ add a tag
perform assign[TagGroup.TagID]
~ delete a tag
perform delete[TagGroup.TagID]
~ replace tag #1 with tag #2
perform tagreplace[TagGroup.TagID1,TagGroup.TagID2]
~ pull a tag from the current context to the initial context for the script. In other words, pull the tag from PickID to the Pick which is running this eval script.
perform hero.childfound[PickID].pulltags[TagGroup.TagID]
~ push a tag from the initial context to the current context. In other words, push it from the Pick running this eval script to the PickID Pick.
perform hero.childfound[PickID].pushtags[TagGroup.TagID]
~ similar to pushtags, but the destination is always the container (for most picks, the container is the hero)
perform forward[TagGroup.TagID]
What can be Learned about Tags?
Here are some common things which can be learned about tags in a given context. Note that these operations do not require you to place "perform" before them, and will in fact error if you do so.
~ Is this tag present?
tagis[TagGroup.TagID]
~ How many of this tag are present?
tagcount[TagGroup.TagID]
~ What are the TagIDs of all tags from a tag group, output as a string of text? Note that this uses wildcards (see below)
tagids[TagGroup.?]
~ What are the TagIDs of all tags from a tag group, output as a string of text, including a seperator between each tag? Note that this uses wildcards (see below)
tagids[TagGroup.?,"seperator"]
~ What are the names of all tags from a tag group, output as a string of text? Note that this uses wildcards (see below)
tagnames[TagGroup.?]
~ What are the names of all tags from a tag group, output as a string of text, including a seperator between each tag? Note that this uses wildcards (see below)
tagnames[TagGroup.?,"seperator"]
Wildcards
When dealing with tags, a wildcard allows you to alter several tags that match the TagID up to a certain point marked by a ?. For example, say that your Pick has 3 tags on it "Helper.SetCastNon", "Helper.SetCastBoo", and "Helper.BookRead". Here are some examples of how wildcards would react to that set of tags.
~ This wildcard is at the start, so it catches every tag of the Helper group, deleting all 3 Helper tags.
perform delete[Helper.?]
~ Helper.SetCastNon and Helper.SetCastBoo both match what is defined before the Wildcard, so they are deleted. Helper.BookRead does not match, so it is not deleted.
perform delete[Helper.Set?]
~ Only Helper.SetCastNon matches what is defined before the Wildcard, so it is deleted and the other two remain
perform delete[Helper.SetCastN?]
Wildcards can only be used with tag IDs, not tag groups, and they work for most tag functions except "assign". There is no equivalent when working with fields.
How Do I Know what tags to Manipulate?
The best way to learn what tags do is to look at something already doing what you want to do with a tag, and see the names of the tags present there. In many cases the name/unique ID of the tag will give you a good idea of its function, so start looking there and experiment by assigning those tags. You may also want to see how the tags on a pick react to changes on the hero. For example, if you want to set up an ability that triggers only when you wear heavy armor, you might look at tags on the hero and see what new tags are added when they equip a set of Heavy Armor.
How do I learn what Fields/Tags are Present on a Pick or on the Hero?
To look at field values and tags present, use the Develop menu in hero lab and check "Enable Data File Debugging". This will open up various options. For picks displayed in HL's UI you can right click and select whether you want to copy the unique ID of that pick, see the fields and their values for it, or view the tags present.
For anything not present in the UI, like Class Helpers or other background Picks, you can go to "Develop -> Floating Info Windows -> Show Selection Tags/Fields"
Code:
~ Cantrip Array
focus.field[cArrKnCan].arrayvalue[2] += 2
focus.field[cArrKnCan].arrayvalue[9] += 3
~ Spells Known Array
focus.field[cArrKnSpl].arrayvalue[2] += 3
focus.field[cArrKnSpl].arrayvalue[3] += 4
focus.field[cArrKnSpl].arrayvalue[6] += 5
focus.field[cArrKnSpl].arrayvalue[7] += 6
focus.field[cArrKnSpl].arrayvalue[9] += 7
focus.field[cArrKnSpl].arrayvalue[10] += 8
focus.field[cArrKnSpl].arrayvalue[12] += 9
focus.field[cArrKnSpl].arrayvalue[13] += 10
focus.field[cArrKnSpl].arrayvalue[15] += 11
focus.field[cArrKnSpl].arrayvalue[18] += 12
focus.field[cArrKnSpl].arrayvalue[19] += 13
~ Max Spell Levels Array
focus.field[cArrKnLev].arrayvalue[2] += 1
focus.field[cArrKnLev].arrayvalue[6] += 2
focus.field[cArrKnLev].arrayvalue[12] += 3
focus.field[cArrKnLev].arrayvalue[18] += 4
We discussed array fields a bit in Tutorial 3. These lines are setting the contents of various rows of 3 different array fields (the row being targetted is in the final set of brackets). cArrKnCan is an array field which stores the number of known cantrips at certain levels, cArrKnSpl does the same for known spells. cArrKnLev maintains the levels at which the highest spell level that can be known changes.
How do I navigate to different types of value fields?
~ Normal field
field[FieldID].value
~ Array field (rownum is the row of the array you want to manipulate)
field[FieldID].arrayvalue[rownum]
~ Matrix field (rownum is the row of the matrix, and colnum is the column. Together they define the cell in the matrix you want to manipulate)
field[FieldID].matrixvalue[rownum,colnum]
How can Value fields and numeric variables be manipulated?
"+=" add the number to the right
"-=" subtract the number to the right
"*=" multiply by the number to the right
"/=" divide by the number to the right
"=" overwrite the field value with the number on the right (use this with caution, it is almost always better to add some number to 0, rather than overwriting it)
"field[FieldID].value = maximum(field[FieldID].value, number)" increase the field value to a number, if it is less than that number.
"field[FieldID].value = minimum(field[FieldID].value, number)" decrease the field value to a number, if it is greater than that number.
"field[FieldID].value = round(field[FieldID].value, number of decimals, round behavior)" round the value of the field to some number of digits (defined by the second aspect in the parenthesis, 0 meaning to whole numbers). Round behavior of 0 means "round up if .5 or greater", 1 means "always round up", and -1 means "always round down". The first aspect can include some manipulation of its own. For example:
Code:
~ Set our value equal to half our level field's value, rounded to the nearest whole number, and always rounded down.
field[abValue].value = round(field[xAllLev].value/2, 0, -1)
How do I navigate to different types of text fields?
~ Normal field
field[FieldID].text
~ Array field (rownum is the row of the array you want to manipulate)
field[FieldID].arraytext[rownum]
~ Matrix field (rownum is the row of the matrix, and colnum is the column. Together they define the cell in the matrix you want to manipulate)
field[FieldID].matrixtext[rownum,colnum]
How can Text fields and string variables be manipulated?
"&=" append the text to the right to the end of the text on the left
~ Splice some new text into a field, with a seperator if there is already text present (but none if the field was empty before the splice.
field[FieldID].text = splice(field[FieldID].text, "newtext", "seperator")
Example 1:
Code:
~ abText begins empty
field[abText].text = splice(field[abText].text, "dance", " or ")
~ Result is "dance"
Example 2:
Code:
~ abText begins with the text "sing"
field[abText].text = splice(field[abText].text, "dance", " or ")
~ Because the field already has text, the seperator is inserted, so the result is "sing or dance"
The order can be flipped to splice new text at the start rather than the end. Example 3:
Code:
~ abText begins with the text "sing"
field[abText].text = splice("dance", field[abText].text, " or ")
~ Because the field already has text, the seperator is inserted, so the result is "dance or sing"
~ Replace some text in a field, with replacetext if the searchtext is found. Number of replacements of 0 means replace all instances found, any positive number X means replace the first X instances found.
field[FieldID].text = replace(field[FieldID].text, "searchtext", "replacetext", number of replacements)
Example 1:
Code:
~ abText begins with "The brown dog is jumping on the brown boat."
field[abText].text = replace(field[abText].text, "brown", "red", 1)
~ Result is "The red dog is jumping on the brown boat."
Example 2:
Code:
~ abText begins with "The brown dog is jumping on the brown boat."
field[abText].text = replace(field[abText].text, "brown", "red", 0)
~ Result is "The red dog is jumping on the red boat."
Manipulations of Case
lowercase(field[FieldID].text)
Code:
~ abText begins with "The brown dog Cassius punched Hitler."
field[abText].text = lowercase(field[abText].text)
~ Result is "the brown dog cassius punched hitler."
uppercase(field[FieldID].text)
Code:
~ abText begins with "The brown dog Cassius punched Hitler."
field[abText].text = uppercase(field[abText].text)
~ Result is "THE BROWN DOG CASSIUS PUNCHED HITLER."
sentencase(field[FieldID].text)
Code:
~ abText begins with "The brown dog Cassius punched Hitler."
field[abText].text = sentencase(field[abText].text)
~ Result is "The brown dog cassius punched hitler."
titlecase(field[FieldID].text)
Code:
~ abText begins with "The brown dog Cassius punched Hitler."
field[abText].text = titlecase(field[abText].text)
~ Result is "The Brown Dog Cassius Punched Hitler."
Conversion of numbers to Strings of text
"ordinal(number)" converts the number in the parenthesis to an appropriate 3 letter string. For example, 1 becomes "1st", 3 becomes "3rd", 9 becomes "9th".
"signed(number)" converts the number in the parenthesis by prepending a + or - depending on whether the number is positive or negative. For example, 4 becomes "+4", -8 remains "-8"