Tags and Tag Groups
Context: HL Kit … Basic Concepts and Terminology … Structural Building Blocks
Overview
At the heart of HL's engine is an important concept that is used as one of the basic building blocks for data files: tags. Things can be assigned a virtually limitless variety of tags, where each tag represents a label that describes some facet of the thing. Tags are managed in sets referred to as tag groups. All of the tags in a given tag group are intended to have a related meaning, such as "race", "level", "color", etc. The set of tags and tag groups is unique to each game system.
Things can have any number of tags assigned from any number of tag groups. Sometimes you'll use zero tags and sometimes you'll use a dozen or more for a complex set of behaviors. You can also freely re-use tags on different types of things, and there are times when using the same tags on different types of things can be extremely powerful. One key advantage of tags is that they are fast and flexible when compared to fields. Modifying a field requires modifying the underlying component and then adjusting all of the things derived from that component, whereas tags can be added, modified, or deleted at any time. The most powerful advantage of tags, however, is that tags can be easily utilized in tag expressions, which are a powerful and flexible mechanism used extensively within data files (and discussed in detail elsewhere).
Referencing Tags
Since tags always belong to a given tag group, an individual tag is always identified with the tag group to which it belongs. This is critical, because the same tag could be used in two or more different groups, with each having a different meaning. For example, the tag "Common" could have two very different meanings in two different tag groups for some game systems. Within the "Language" tag group, "Common" might refer to the "Common tongue" used in the game world. However, within the "Rarity" tag group, the "Common" tag might indicate that an item is commonly available for purchase instead of being uncommon or rare.
When referring to tags, the notation used is called a tag template. This notation specifies the unique id of the tag group, followed by the '.' character, followed by the unique id of the tag. For example, the reference "Language.Common" would refer to the "Common" tag within the "Language" tag group. Remember this syntax, since tags are used extensively and you'll be seeing the tag template notation frequently.
REMINDER! Unique ids for almost all elements must be globally unique. The key exception is with tags, for which the unique id must be unique only within the containing tag group. This is possible because tags are always referenced with the associated tag group, so uniqueness is always ensured, even though two tags in different groups may have the same id.
Using Tags
In most cases, you'll be assigning a single tag from a given tag group to a thing. However, sometimes you'll find that the lack of a tag from a particular group can have important meaning. At other times, you'll find that you need to assign multiple tags from a given tag group to a particular thing. For example, spells in the d20 System have different casting behaviors (e.g. verbal, somatic, and material), with any number applying to a particular spell. In this case, you would assign the appropriate tags to a given spell, with the presence of a tag indicating the behavior and the absence of the tags indicating the opposite.
Dynamic Tags
In most cases, each tag group will explicitly define the complete set of tags that exist for that tag group. However, there will be times when a tag group needs to be open-ended for expansion. For example, consider the the "Language" tag group mentioned above. You could populate the group with all of the languages in the game system, but you can be sure some designer will come along at some point in the future with a new language for some new race. To handle these situations, a tag group can be designated as dynamic, allowing new tags to be defined on-the-fly as they are needed. When you define a new dynamic tag, you must specify all its various details.
Tag Values
Tags will usually be used to identify a non-value attribute of a thing. Once in awhile, though, tags will be used to convey a value in addition to an attribute. For example, each spell within the d20 System has a spell class and a level for that class (e.g. Wizard level 4, Cleric level 2). Since the same spell can apply to different classes at different levels, it would be difficult to track all that information easily. So one solution would be to define a "SpellLevel" tag group with tags that combine the class and the level, such as "Wiz4" or "Clr2". The data files could then identify a spell's class from the prefix on the tag and also get the value from the suffix. The tag value of a given tag is the determined by extracting the trailing digits from the tag's unique id and converting it to an integer value,. So the tag id "xyz123" would have the value "123", while the tag "a1b2c3d4" would have the value "4" (the extraction stops at the first non-digit encountered, starting at the end and working towards the front). If a tag id does not end in any digits (e.g. "black"), the tag's value is always treated as zero.
Tags Are Often Better Than Fields
The concept behind fields will likely be familiar to you, while the concept behind tags may not. This makes it quite possible that you will be inclined to use fields to solve most problems. However, you will benefit from learning how to leverage tags, since there are many situations where tags are a better solution than the use of fields.
Tags provide a fast and efficient means of assigning an attribute to something. Tags are ideal when valid values consist of a pre-defined set. For example, spells in the d20 system have a level, a range, an area of effect, and some combination of three different casting behaviors: verbal, somatic, and material. The range and area of effect have a very wide range of possible values, so a field is probably the best way to manage that characteristic. However, the spell level and casting behavior are ideal situations for a tag. There is a fixed number of spell levels and there are only three casting behaviors. Two tag groups could be easily defined to solve this (one for spell level and one for behavior), and individual tags could be defined for each level and each behavior. Appropriate tags would then be assigned to each spell corresponding to the spell level and casting behaviors.
A field could also be used for each of these, but tags are a better solution. This is especially true for the casting behavior, where using a field would either entail having a numeric code that is not immediately obvious (e.g. 1=verbal, 2=somatic, etc.), or it would require using a text value (e.g. "verbal", "somatic"). Using a text value would be prone to data entry typos over the span of hundreds of spells. In contrast, the use of the tag "verbal" makes the value obvious and the requirement that all tags match an existing set eliminates the possibility of typos.