User Guide: Launch-time Effect Parametrization
From AFXWiki
Contents |
Launch-time effect parametrization is a broad category of capability added to AFX in version 2. With it, effects can be designed with launch-time parameters that conditionally vary aspects of the effect at the time the effect is executed.
Here are some of the benefits of launch-time effect parametrization:
- Effect attributes can vary randomly so that the overall effect looks a little different each time it occurs.
- A single spell-effect can represent multiple game spells and vary according to which game spell is cast.
- ...
- Reduces the need for multiple parallel datablocks when implementing conditional effect choices. In many cases, conditional modifications can be applied directly to datablock fields.
Temporary Datablock Cloning
Temporary datablock cloning is a low-level engine customization that is fundamental to the implementation of launch-time effect parametrization. Although most AFX users will not deal directly with temporary datablock cloning, some understanding of the mechanism will help clarify how to best use higher level features like field substitutions.
A common practice throughout Torque, is to use datablocks as object templates which are then used to instantiate objects with initial attributes matching those in the datablock. By convention, datablocks are considered static and their attributes are shared across multiple object instances. Generally this mechanism is efficient and useful but, as implemented, many instanced objects within Torque remain linked to their initializing datablocks and may even repeatedly reference values within the datablock over the life of the object instance. Because of this, many object attributes are permanently fixed to the values in their datablocks and this prohibits the changing of these attributes on a per-instance basis. While you can change the value of the datablock attribute itself, this usually has the undesirable result of changing the attribute for all objects initialized with the same datablock.
To get around this limitation for most object attributes, AFX implements the mechanism of temporary datablock cloning. The concept behind it is quite simple. For most of the objects used by AFX, at the point where an object instance will be created and then initialized using a datablock, the datablock is first evaluated to see if some of its values will be replaced in a per-instance fashion. If so, a temporary copy of the datablock is created and the copy rather than the original is use to initialize the object instance. Attributes of the datablock copy (or clone) can be altered as needed without affecting any other object instances. When the object instance is eventually deleted, its datablock is also deleted (if it's a temporary clone).
Datablock Field Substitutions
With temporary datablock cloning in place, AFX adds a mechanism called datablock field substitution which is used to describe how to alter datablock fields at the time the datablock is used to instantiate an object.
For datablocks that support field substitution, any of its fields can be specified using a substitution statement. A substitution statement is a string that begins with a special token consisting of two adjacent dollar signs, “$$”. The rest of the substitution statement should consist of a single statement of TorqueScript that, when executed, returns an appropriate value to be used as a replacement for the original value of the substituted field. (Specifically, a substitution statement of the form “$$ TORQUE_SCRIPT_STATEMENT” will be converted to the form, “return TORQUE_SCRIPT_STATEMENT;” and then used as an argument to Con::evaluate(). Note in particular that the terminating “;” is added.)
For example, here is a substitution statement applied to the radius field of an afxZodiac effect:
datablock afxZodiacData(ExampleZodiacDatablock)
{
radius = “$$ getRandomF(0.5, 3.5)”;
};
Every time this datablock is used to initialize a new zodiac instance, the field substitution will be evaluated first and a randomized value will be assigned to the radius field.
Within a datablock, substitution statements are stored in parallel with the actual field values. If you assign a value and a substitution statement to a field, both the value and the substitution statement will exist separately until the substitution is evaluated and its result replaces the field value. In some cases, it makes sense for the substitution to return the special token “~~” which means that the datablock field should retain its original, unchanged value.
Substitution Tokens
As described so far, field substitutions are already quite useful, but as plain TorqueScript statements, they have limited access to information that might be useful when calculating a replacement value for the substituted field. To make them a little more useful, substitution statements recognize a couple of special tokens which are expanded before the statement is passed along to Con::evaluate().
Internally, whenever a substitution is performed, another object is provided as an argument and the id of this object will replace occurrences of the special token, “%%” within the substitution. (Theoretically, this object can be any subclass of SimObject, but in AFX it is always the choreographer instance (afxMagicSpell, afxEffectron, or afxSelectron) that owns the current effect that is being processed.)
For example, here is different substitution statement applied to the radius field of an afxZodiac effect:
datablock afxZodiacData(ExampleZodiacDatablock)
{
radius = “$$ %%._scale*3.5”;
};
Here, by using the “%%” token, the substitution can access the spell instance managing this zodiac and use the value of its _scale field in a calculation to assign a the zodiac's radius. The utility of this token is described further in the next section, Special Dynamic Datablock Fields.
Another special field substitution token is the group index which is specified as “##”. The source of the group index value can vary according to context, but it always expands to an integer value within the substitution. The group index is covered in more detail in the section, Effect Groups and the Group Index.
Special Dynamic Datablock Fields
Effect Groups and the Group Index
Effect Parametrization In Practice
Previous: User Guide: Transform Modifiers (Xmods)
