Bootstraps

From HLKitWiki
Jump to navigationJump to search

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.

Bootstrapped Picks are Not Deletable

The topic name pretty much sums it. When a pick is bootstrapped into a container, only the source that performs the bootstrap has control over the pick's existence. Consequently, all bootstrapped picks of fundamentally not deletable. Any attempt to delete a bootstrapped pick will fail.

If you want to pre-select a pick into a table or chooser, and you want the user to be able to delete that selection, you need to use a different technique. Please refer to the section "Automatically Adding Picks to Actors".

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.

Component Bootstraps

The vast majority of bootstraps are simple. The bootstrap is always performed for the source context it is defined within. However, bootstraps on components are sometimes an exception. 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 Match tag expression can be specified with the bootstrap. This tag expression is applied to each thing derived from the component. Only the things that satisfy the tag expression are assigned the bootstrap. Note that the tag expression is tested against the tags possessed by each thing, so each thing uniquely controls whether it does or does not receive the bootstrap. This also means that only the initial tags each thing possesses are tested.

Conditional Bootstraps

There is another potential wrinkle with bootstraps. Some things can be added to different containers or under different circumstances. Depending on the situation, you may want the bootstrap to be added in some cases but omitted in others. For example, a special ability that is selected directly by the user for an actor may behave one way, while that same ability being added as a power within a magic item may behave a bit differently.

To accommodate special cases like this, a Condition tag expression may be specified. This tag expression is applied to the prospective container for the new pick. If the container satisfies the condition test, then the bootstrap is added normally. However, if the container does not satisfy the test, no bootstrap is added.

The Condition test on bootstraps works differently from the Match tag expression. In addition to focusing on the container, the test is applied against tags that are dynamically assigned to that container. This means that the Condition test must be scheduled at a specific phase and priority during the evaluation cycle.


-The "live" test performed for a bootstrap provides the reference pick of the

   bootstrap for use in testing field values within the tagexpr
   -All field value tests in the tagexpr are applied to the reference pick that
       chains to the pick whose live state is being updated
   -The author is responsible for ensuring field values are only tested for picks
       that actually have reference picks, since global bootstraps possess no
       reference pick and attempts to access missing fields will report an error

-The "live" tag expression of bootstraps is special for gizmos and minions

   -The "live" tagexpr normally uses the reference pick that attaches bootstrap,
       but gizmos and minions don't have a normal reference pick
   -Gizmos use the pick that attaches the gizmo as a special bootstrap reference
   -Minions use the anchor/master pick as a special bootstrap reference
   -Provides a suitable target for use of "fieldval" within bootstrap tagexpr

-The timing of all bootstrap condition tests is properly factored into the

   determination of the "latest" condition timing for each thing
   -If a bootstrap condition test occurs latest than other condition tests for
       a given thing, the "latest" timing for that thing uses the new timing
   -Ensures that the final condition test is scheduled late enough to properly
       incorporate the effects of all bootstrap condition tests
   -Ensures that any scripts scheduled to be processed earlier than bootstrap
       condition tests are properly flagged as a conflict during compilation

-Condition tests are not allowed for bootstraps on entities and rulesets