Data Manipulation Basics
Every compset specifies a pre-defined set of behaviors for the things derived from it. There are three ways to control this behavior uniquely to an individual thing within Hero Lab. The first method is via the set of fields that are defined for the compset. Every component defines a set of fields, and all the fields of the member components are merged into the set of fields for a given compset. Every thing derived from a given compset will possess the same set of fields. The actual values assigned to these fields will differentiate each thing from the others derived from that compset.
The second method for controlling the behavior of a specific thing is via tags. Tags provide a fast and efficient means of assigning an attribute to a thing. Tags are ideal when the values that can be assigned must be one 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 should probably be used to store that characteristic. However, the spell level and casting behavior are ideal situations for a tag. There is a fixed number of levels and only three casting behaviors, so two groups of tags could be defined (one for 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 typically 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") that is easily subject to data entry typos over the span of hundreds of spells. The use of the tag "verbal" makes the value obvious and the restriction of tags matching an existing set eliminates the possibility of typos.
The third method for customizing the behavior of an individual thing is via the use of scripts that are written specifically for that thing. More details regarding scripts will be found in the subsequent sections of this chapter, as well as elsewhere in this documentation.
Tags form a fundamental building block upon which much of Hero Lab is constructed, and this is where they become of critical importance. Since just about everything you'll be managing for user selection is a "thing", there needs to be some way to identify the proper subset of things that apply to a particular situation. For example, attributes, skills, and weapons are used in completely different ways, so you want to keep them separate from each other – but they are all things. The solution is to assign a few key tags to each thing and then use a tag expression (or tagexpr for short) to identify the subset of things that apply in a given situation. An entire chapter is dedicated to the subject of tag expressions, but a brief overview is useful at this point.
A tag expression is essentially a filter that gets applied to all things and selects only the ones that meet the specified criteria. Tag expressions are Boolean expressions (i.e. they evaluate to true or false). They examine all of the assigned tags and determine whether those tags satisfy the expression or not. Separate criteria can be combined, allowing you to require that multiple criteria all be met, one of a set of criteria be met, certain criteria be excluded, or some combination thereof. For example, a tag expression could test whether a thing has the tag "Elven" from the "Language" group. Or a more complex tag expression could test whether a thing has the "Language.Elven" tag and also has either the "Race.Elf" or "Race.HalfElf" tag.
Since tag expressions can utilize full Boolean logic (i.e. "and", "or", "xor", "not") and can even extract and test numeric values from certain tags, tag expressions can model extremely complex conditions without difficulty. The bottom line with tag expressions is that they provide a powerful and flexible method for quickly determining whether to include or exclude something, and they are based exclusively on the set of tags assigned to that something. As such, they are used extensively throughout Hero Lab.
Scripts and Procedures
There is no practical way to develop an engine that inherently handles all the complexities of every game system. And if that could be achieved, some new game system would come out shortly thereafter that adds some new wrinkle. So Hero Lab makes extensive use of scripts to allow the data file author substantial freedom and flexibility. In fact, scripting is such a fundamental and diverse topic that there are multiple chapters of this document dedicated to different facets of writing scripts. Links to these chapters will be found at the end of this topic.
The scripting language syntax within Hero Lab is relatively simple. You can declare variables, assign values, perform simple conditional tests, and utilize a number of built-in intrinsic functions for various purposes. There is also a syntax that allows access to field values and tags that may be assigned to various picks and containers. The language itself is somewhat similar to the age-old Basic language. Using scripts, an author can pretty much do whatever is necessary to properly model the requirements of a given game system.
To make the writing of scripts easier, Hero Lab supports re-usable procedures. A procedure is nothing more than a mini-script that can be called from multiple places. The data files for each game system make extensive use of procedures so that many scripts can be reduced to simply calling one or procedures to do all the work. Unless you plan on writing extensive data files, you'll have no need to write your own procedures. However, you will find yourself re-using pre-defined procedures all over the place as you add your own custom material. Complete details on procedures are covered in the chapters dedicated to covering scripts.
The one type of script that you will almost certainly find yourself writing most often is the eval script. The reason for the term eval script is that these scripts are evaluated as tasks during evaluation processing. As such, each eval script must be assigned an appropriate phase and priority during which the script will be processed.
Every eval script is associated with a thing, but a given eval script can derive from two different sources. It is common to define a small number of eval scripts as part of every component. Each such eval script is automatically inherited by every thing that derives from that component. It is also possible to define additional eval scripts for individual things.
Since an eval script is performed during evaluation processing, a separate task is always created for each eval script. This task can then be scheduled by the engine. However, tasks are not associated with things. If a thing is added to a container multiple times, each eval script must be processed separately for every pick. Consequently, separate eval script tasks are created and scheduled for every pick.
Eval scripts are the most commonly used script due to the ability to schedule them. So many facets of a complex role-playing game system are closely inter-dependent. Dependent calculations must be performed in a carefully ordered sequence to ensure that all of the game mechanics are accurately implemented within the data files. Eval scripts provide the means for this scheduling.
As a companion to eval scripts, Hero Lab also supports eval rules, and you will likely find yourself writing a fair number of these as well. Just like eval scripts, eval rules are scheduled as tasks and performed with specific timing during the evaluation process. Standard validation rules are performed after all evaluation processing is completed, which can often be quite restrictive, thereby making eval rules a valuable resource for data file authors.
Eval rules are a hybrid of eval scripts and validation rules. Since eval rules are tied to things, they are always scheduled as tasks for picks, so all eval rules effectively possess a scope of the specific pick to which they are associated. This might seem limiting at first, but it's actually exactly what you'll want for at least 95% of the rules you'll write for a game system.
Another key facet of eval rules is that they must be assigned a message and an optional summary to be reported to the user if the rule is not satisfied. Like a normal validation rule, the message is the text shown in the validation report within Hero Lab that tells the user what's wrong with the hero. The summary is the text shown in the validation bar at the bottom of the main window, which defaults to the message text if left blank.