Bootstraps
Context: HL Kit … Advanced Authoring Concepts
There will be many situations where you want to add a pick to a container automatically. For example, you'll need to make sure that every actor starts out with all of the attributes possessed by characters. You'll also want to re-use abilities, so you'll need to have one thing automatically add another thing.
Within the Kit, this process is referred to as "bootstrapping". Correspondingly, when you add a thing to a container automatically, the resulting pick is referred to as a "bootstrapped" pick. There are a number of important implications associated with bootstrapping, which are discussed in the topics below.
Things Bootstrapping Other Things
You can bootstrap picks from a variety of situations. However, the most common situation will be when you have one thing bootstrap another. This will regularly occur when the game system has an assortment of abilities that are conferred from a variety of sources. For example, consider the "low-light vision" ability within the d20 System. This ability is conferred by multiple different races, certain magic weapons, etc. You're only going to want to define the ability once, after which you can have each race and weapon simply bootstrap the ability.
When a pick is bootstrapped by another pick, the pick that does the bootstrapping is referred to as the "root" pick. The root pick has complete control control of the bootstrapped pick. If the root pick is deleted, the bootstrapped pick is also deleted. If the root pick goes non-live, so does the bootstrapped pick. The bootstrapped pick still has its own independent existence, but that state is wholly dependent upon the root pick as well.
Situations Where You Can Bootstrap
In addition to things bootstrapping each other, there are a number of additional situations in which bootstrapping of things can be performed. These situations are outlined below. In each of these cases, the dependency relationships outlined above for things bootstrapping things do not apply.
- Things can be bootstrapped onto all actors when the actor is initially created.
- Things can be bootstrapped onto entities as part of the entity's definition. The bootstrapped picks are part of every gizmo created from that entity.
- Things can be bootstrapped onto entities when they are attached. The bootstrapped picks are only included on gizmos created by that thing.
- Things can be bootstrapped onto minions when they are attached. The bootstrapped picks are only included on minions created by that thing.
Bootstrapping the Same Thing Multiple Times
At this point, you may be wondering what happens when the same thing is bootstrapped multiple times into a container. The answer depends on whether the thing is designated as being unique. If not, then separate, independent picks are always created, and their behaviors are not linked in any way. However, if the thing is designated as unique, then only one pick is ever added to a given container. This means that all of the bootstrap actions will actually reference the identical pick.
When the first bootstrap occurs, the new pick is created. Each subsequent bootstrap simply increases the reference count for the pick. As long as at least one of the sources for the bootstrap remains in existence, so will the bootstrapped pick. This is important when things bootstrap over things and those things are user-added. Consider the situation where both ThingA and ThingB bootstrap ThingZ. When the user added ThingA, ThingZ is bootstrapped. When the user adds ThingB, the reference count is increased. If ThingA is deleted, the reference count is decreased, but ThingZ still exists. When ThingB is deleted, the reference count goes to zero and ThingZ is finally deleted as well.
When multiple things bootstrap the same, unique thing, their effects are cumulative upon the new pick. If ThingA specifies an auto-tag for ThingZ, and ThingB specifies a different auto-tag for ThingZ, then both auto-tags are assigned to ThingZ. If only ThingA is added to the container, only its auto-tags are assigned, and the same holds for ThingB. However, if both things are added to the container, both auto-tags are assigned.
If multiple things bootstrap the same, unique thing, all of the conditions associated with the root picks must be handled in accordance with some sort of rules. For example, we'll assume ThingA and ThingB both bootstrap ThingZ, and both ThingA and ThingB have been added to the same container. Now we'll further assume that ThingA has a Live test that is currently failed. This means that ThingA is treated as not existing within the container, although ThingB has no dependency and therefore fully exists. So what happens with ThingZ?
To resolve situations like this, the Kit treats each root pick independently. If any one of the root picks for a bootstrapped pick is considered live, then the bootstrapped pick is also considered live. In the example above, this means that ThingZ would be treated as being live due to ThingB being live. The fact that ThingA is not live is irrelevant.
The Mechanics of Bootstrapping
The process of bootstrapping a thing is accomplished via the the "bootstrap" element. Since there are a variety of places where bootstrapping can be performed, this element is re-used throughout the Kit.
At a minimum, the "bootstrap" element requires you to specify the unique id of the specific thing to be added. You may also specify tags that will be automatically assigned to the pick when it is added.
The vast majority of bootstraps are simple. The bootstrap is always performed for the source context it is defined within. However, there are some situations where you want the bootstrap to only be applicable under certain circumstances. For example, a bootstrap definition on a component will be inherited by all things derived from that component. However, you may only want the bootstrap to be applied to most of those things, with some not having the bootstrap.
In these situations, a Condition tag expression may be specified.
phase and priority for condition test
match tagexpr