Difference between revisions of "Creature Specification (Savage)"

From HLKitWiki
Jump to: navigation, search
(User Manipulation of Derived Traits)
 
Line 231: Line 231:
  
 
The problem is that derived traits are always calculated in the end. We need to handle them in a way that will smoothly integrate with their calculated nature. Unfortunately, there is no clean way of doing that by having the derived trait value be specified explicitly for a creature. The only way to reasonably accomplish it is to utilize an adjustment that gets incorporated into the calculated final value.
 
The problem is that derived traits are always calculated in the end. We need to handle them in a way that will smoothly integrate with their calculated nature. Unfortunately, there is no clean way of doing that by having the derived trait value be specified explicitly for a creature. The only way to reasonably accomplish it is to utilize an adjustment that gets incorporated into the calculated final value.
 
====Specifying the Derived Traits Values====
 
  
 
This means that we need to define four new fields for the "Creature" component. We need one field apiece for the four derived traits, where each field specifies an adjustment from the standard calculated value. If a field is not specified, then no extra adjustment will be applied for that trait.
 
This means that we need to define four new fields for the "Creature" component. We need one field apiece for the four derived traits, where each field specifies an adjustment from the standard calculated value. If a field is not specified, then no extra adjustment will be applied for that trait.
Line 276: Line 274:
 
</pre>
 
</pre>
  
====Supporting User Adjustment====
+
We now need to communicate the adjustment value for each derived trait from the creature. Each derived trait needs to know what the particular adjustment value is. We'll define a new field on the "Derived" component for this purpose, which should look like below.
 
+
Integrating these new fields into the calculation is relatively simple. All we need is an Eval script that applies the adjustment values to the traits via the "traitadjust" script macro. If we do that, then the adjustment included in the standard calculation of the derived trait, without any special handling.
+
 
+
Unfortunately, there is a serious limitation with this approach. The user will not be able to directly modify the values for derived traits. We've made sure that the user can easily adjust the values for attributes and skills via the standard incrementers. What we need is a similar solution for derived traits, and applying the adjustments via an Eval script won't get it done.
+
 
+
If we use the same basic approach as attributes and skills, then the user can adjust the values freely. That would entail assigning the adjustment value to the "trtUser" field for each derived trait. But that field is not used for those traits. We're going to need to change that behavior and use the "trtUser" field for derived traits on creatures.
+
 
+
Derived traits calculate their final value via an Eval script on the "Derived" component. Within that script, the "trtUser" field is never used. It would be easy to add the "trtUser" value to the calculation for creatures. If we properly initialize the "trtUser" field values to the adjustments via the Creation script of the "Creature" component, then we can expose the "trtUser" field via an incrementer and allow the user to modify it.
+
 
+
Before we go down this path, though, we should think through the implications and how it's all going to work. The starting adjustments will be loaded into the "trtUser" field, which will be modified by the user. We'll want to bound that field so that it can be adjusted within a reasonable range of the starting value (e.g. -3 to +3). This will allow the user to tailor a creature appropriately without going completely wild. We'll then add the user value into the final trait calculation. This all seems perfectly sound.
+
 
+
Unfortunately, there's a critical hole in this approach. It's a subtle timing issue that comes into play with the bounding of the user value. Since the "trtUser" field is also used for normal (i.e. non-derived) traits, the bounding logic needs to be changed for our purposes. That can be handled, but the bounding must be performed '''''before''''' the initial calculation of "trtFinal" within the "Traits" component. For our purposes, we need to access the net values calculated for our derived traits in order to do proper bounding. For example, the Toughness trait must be calculated so that we know what the bounding range can be. This means we'll need to do the bounding '''''after''''' "trtFinal" is calculated. We have a chicken-and-egg problem.
+
 
+
The timing of the Bound script for the "trtUser" field is fixed. If we could schedule it at one time for normal traits and a different time for derived traits, we could make this work. Sadly, it must always be invoked at the same time for all traits. This means we can't use the "trtUser" field for our purposes.
+
 
+
====Alternate Field for User Adjustment====
+
 
+
The good news is that we can simply create a '''''different''''' field for our needs and proceed with our original plan. Our new field will behave very similarly to "trtUser", so we start by cloning it. The field is only needed for derived traits, so we'll add it to the "Derived" component.
+
 
+
We can re-use the "trtMinimum" and "trtMaximum" fields for bounding, and we won't need to do any special handling of the bounds. We want to display the final value within the incrementer, which we can pull from the "trtDisplay" field. Lastly, we want to allow the user to edit that value directly, so we'll include delta handling for our field. Our resulting field should look like the following.
+
 
+
<pre>
+
<field
+
  id="trtUserCre"
+
  name="User Value for Creature"
+
  type="user"
+
  defvalue="0"
+
  usedelta="yes"
+
  maxfinal="50">
+
  <!-- Bound the user value to the limits established for the trait -->
+
  <bound phase="Traits" priority="5500" name="Bound trtUserCre">
+
    <before name="Derived trtFinal"/><![CDATA[
+
    @minimum = field[trtMinimum].value
+
    @maximum = field[trtMaximum].value
+
    ]]></bound>
+
  <!-- Display the final calculated value to the user -->
+
  <finalize><![CDATA[
+
    @text = field[trtDisplay].text
+
    ]]></finalize>
+
  </field>
+
</pre>
+
 
+
With the field in place, we need to set it up properly. To accomplish this, we'll revise the Creation script for the "Creature" component. In addition to setting up the attributes, we must also assign the initial user values for the derived traits. This consists of adding the following lines of code to the script.
+
 
+
<pre>
+
~assign the appropriate adjustment values to derived traits
+
hero.child[trPace].field[trtUserCre].value = field[crePace].value
+
hero.child[trParry].field[trtUserCre].value = field[creParry].value
+
hero.child[trTough].field[trtUserCre].value = field[creTough].value
+
hero.child[trCharisma].field[trtUserCre].value = field[creCharis].value
+
</pre>
+
 
+
The next step is to include the "trtUserCre" field value in the calculation of the final value. For this, we need to modify the Eval script that calculates "trtFinal" within the "Derived" component. After the value is calculated normally, we can add the lines of code below to factor in the "trtUserCre" field for creatures.
+
 
+
<pre>
+
~if this is a creature, we need to add the user value as a custom adjustment
+
if (hero.tagis[Hero.Creature] <> 0) then
+
  field[trtFinal].value += field[trtUserCre].value
+
  endif
+
</pre>
+
 
+
====Bounding the Derived Traits====
+
 
+
At this point, we've got a user-modifiable value that will be setup properly and factored into the final adjustment calculation. The final piece we're missing is the bounding. We need to setup appropriate value for "trtMinimum" and "trtMaximum" so that the user can adjust the starting value within reason. In order to bound the value, we need to know the original starting value, since we'll establish our limits relative to that value. We also need to know what the absolute minimum value is for a given trait (i.e. its "floor" value). This value differs for each derived trait, since Charisma can go negative, Pace can't drop below one, and the others can't drop below two.
+
 
+
We need to introduce two new fields on the "Derived" component to track these values. Both of these values will be setup appropriately by the creature, so they are simple derived values. The two fields should look like below.
+
  
 
<pre>
 
<pre>
Line 348: Line 280:
 
   id="trtCreatur"
 
   id="trtCreatur"
 
   name="Creature Start"
 
   name="Creature Start"
  type="derived">
 
  </field>
 
 
<field
 
  id="trtFloor"
 
  name="Creature Floor"
 
 
   type="derived">
 
   type="derived">
 
   </field>
 
   </field>
 
</pre>
 
</pre>
  
These values are derived, which means they don't persist like "user" fields. We need to set them up every evaluation cycle. This is done by adding a new Eval script to the "Creature" component. All this script needs to do is assign the appropriate values to both of these fields for each derived trait. This needs to be done early in the evaluation cycle, resulting in the following new script.
+
Each creature can tell its derived traits the value to be used via an Eval script on the "Creature" component. This script must be invoked early in the evaluation cycle, but it is otherwise very simple. The result script is shown below.
  
 
<pre>
 
<pre>
Line 367: Line 293:
 
   hero.child[trTough].field[trtCreatur].value = field[creTough].value
 
   hero.child[trTough].field[trtCreatur].value = field[creTough].value
 
   hero.child[trCharisma].field[trtCreatur].value = field[creCharis].value
 
   hero.child[trCharisma].field[trtCreatur].value = field[creCharis].value
 
  ~setup the proper floor values for each trait
 
  hero.child[trPace].field[trtFloor].value = 1
 
  hero.child[trParry].field[trtFloor].value = 2
 
  hero.child[trTough].field[trtFloor].value = 2
 
  hero.child[trCharisma].field[trtFloor].value = -4
 
 
   ]]></eval>
 
   ]]></eval>
 
</pre>
 
</pre>
  
We can now utilize those values for properly bounding the "trtUserCre" value. We'll define a new Eval script on the "Derived" component for this purpose. Our minimum and maximum will range from -3 to +3 from the original starting value. We'll also use the floor value to verify that we don't let the user drop a trait below its absolute minimum. The only special detail about this script is its timing. We have to schedule this script after all standard traits are calculated and before the Bound script is evaluated on the "trtUserCre" field. This results in the new Eval script below.
+
At this point, each derived trait should know the adjustment value specified by any selected creature. Integrating that value into the final calculation for the derived trait is relatively simple. All we need to do is revise the Eval script that calculates the value of "trtFinal" to add in the adjustment for creatures. We can achieve this by adding the lines of code below to the Eval script.
  
 
<pre>
 
<pre>
<eval index="3" phase="Traits" priority="5300">
+
~if this is a creature, we need to add the user value as a custom adjustment
  <before name="Bound trtUserCre"/><![CDATA[
+
  ~setup a minimum at 3 below the starting value; if our minimum will yield a
+
  ~value below the minimum for this trait, limit it to the minimum
+
  field[trtMinimum].value = field[trtCreatur].value - 3
+
  var bonus as number
+
  bonus = field[trtBonus].value + field[trtInPlay].value
+
  if (field[trtMinimum].value + bonus < field[trtFloor].value) then
+
    field[trtMinimum].value = field[trtFloor].value - bonus
+
    endif
+
 
+
  ~now setup a maximum at 3 above the starting value
+
  field[trtMaximum].value = field[trtCreatur].value + 3
+
  ]]></eval>
+
</pre>
+
 
+
====Setup the Delta====
+
 
+
All of our behaviors are in place, except for one. Derived trait values are simple numbers and not die types. Consequently, we want to let the user edit the value directly within the incrementer where they are shown. However, we want the user to edit a value that makes sense to him (i.e. the final result) instead of the adjustment. To do this, we need to set the "delta" for the "trtUserCre" field to the difference between the actual user value and the value the user will see. Once that's done, HL will handle the rest for us. The new Eval script should look like the following.
+
 
+
<pre>
+
<eval index="4" phase="Render" priority="5000"><![CDATA[
+
  if (hero.tagis[Hero.Creature] <> 0) then
+
    field[trtUserCre].delta = field[trtBonus].value + field[trtInPlay].value + herofield[acNetPenal].value
+
    endif
+
  ]]></eval>
+
</pre>
+
 
+
That was a fair amount of work, but everything should now be in place to setup the initial values for each creature and allow users to adjust them.
+
 
+
===User Manipulation of Derived Traits===
+
 
+
At this point, we have the internal workings in place and need to expose the field value for change by the user. This entails modifying the "baTrtPick" template that is used to show derived traits on the "Basics" tab. If we want the user to modify the value, we need to add a new incrementer portal. We can use a simple incrementer style that is provided by the Skeleton files, which results in the new portal shown below.
+
 
+
<pre>
+
<portal
+
  id="value"
+
  style="incrSimple">
+
  <incrementer
+
    field="trtUserCre">
+
    </incrementer>
+
  <mouseinfo><![CDATA[
+
    @text = "Adjust this trait by clicking on the arrows to increase/decrease the value assigned."
+
    ]]></mouseinfo>
+
  </portal>
+
</pre>
+
 
+
Within the Position script, we need to do two things. First, we must make sure that we only show either the new incrementer or the old "details" portal, which means controlling visibility based on whether we have a creature or not. This can be done at any point in the script. Second, we need to center our new incrementer in the same general region used by the existing "details" portal so that it occupies the same region. We have to do this after the "details" portal is positioned. This results in the following code being added to the Position script.
+
 
+
<pre>
+
~the incrementer is visible if we have a creature, else the details
+
 
if (hero.tagis[Hero.Creature] <> 0) then
 
if (hero.tagis[Hero.Creature] <> 0) then
   portal[details].visible = 0
+
   field[trtFinal].value += field[trtCreatur].value
else
+
  portal[value].visible = 0
+
 
   endif
 
   endif
 
~center the incrementer over the details portal
 
perform portal[value].centeron[horz,details]
 
perform portal[value].centervert
 
 
</pre>
 
</pre>
  
We're now ready to give our changes a try. When we create a new creature, our incrementers show up where they should and have appropriate initial values displayed. Let's put our changes to the test with an actual creature that applies adjustments.
+
That's all there is to it. We're now ready to give our changes a try. When we select a creature from the chooser, the appropriate values should be applied as adjustments to the final derived trait values. Let's put our changes to the test with an actual creature that applies adjustments.
  
 
We'll modify our sample creature for this purpose. We can assign a few field values on the creature to apply our adjustments. We'll assign a "Pace" of "5" and a "Parry" adjustment of "1". To do this, we'll add the following XML elements to the creature's definition.
 
We'll modify our sample creature for this purpose. We can assign a few field values on the creature to apply our adjustments. We'll assign a "Pace" of "5" and a "Parry" adjustment of "1". To do this, we'll add the following XML elements to the creature's definition.
Line 451: Line 315:
  
 
Reload the data files and create a creature. Take a look at the default values shown for the derived traits. From the chooser, select our test creature. The "Pace" value should immediately change to "5", and the "Parry" value should change from "2" to "3". Our derived traits are working smoothly now.
 
Reload the data files and create a creature. Take a look at the default values shown for the derived traits. From the chooser, select our test creature. The "Pace" value should immediately change to "5", and the "Parry" value should change from "2" to "3". Our derived traits are working smoothly now.
 
Let's attempt to adjust the derived traits. Decreasing Parry stops us at "2", since we set that up as our absolute floor. However, we can increase Parry a total of three notches. Our Toughness defaults to "4" and has the same behaviors. Our Pace is limited to a range of "2" to "8". Everything checks out.
 
 
We should also verify our delta is working properly. Click within the incrementer showing the Parry and it should show the current value for editing. Enter the new value "4" and everything appears to work fine. Now try entering a value of "9". The new value is automatically bounded to the maximum we established of "6" (i.e. our initial value of 3 plus and additional 3). Derived traits are fully operational.
 
  
 
===Assigning Gear===
 
===Assigning Gear===

Latest revision as of 20:22, 10 February 2009

Context: HL KitAuthoring Examples … Savage Worlds Walk-Through 

Overview

It's now time to figure out how we're going to be handling the details of creatures. Each creature in the rulebook has die-types specified for each attribute. Creatures also have a list of skills, with the appropriate die-type for each. Derived traits are specified, incorporating any special adjustments beyond the standard derived value. Lastly, a list of gear and/or special abilities is given.

Our solution for creatures must enable all of these different facets to be readily assigned to each creature. We want a design that is both easy to use and also easy to utilize via the integrated Editor. For the latter, it's always easiest when tags are utilized, since users can simply pick from a controlled list that the Editor presents. The next easiest mechanism is simple fields, wherein the user can enter text or a value. After that, whatever works is going to be pretty much the same.

Given the list of requirements and goals above, we'll see about devising a good solution. As an added user benefit, we'll also strive to allow the user to customize the default values for each creature if he wants.

Internal Approach

There are two different facets of traits that we'll need to handle. The first is the basic die-type for the trait, ranging from "d4" to "d12". The second is the roll bonus in situations where the creature has a trait that exceeds a "d12" rating.

These two facets are managed internally via two separate fields for each trait. As such, our first thought will likely be to do the same. We could have two separate fields that specify the starting die-type and bonus for each trait. An Eval script could be written that assigns the die-type value to the "trtBonus" field and the bonus value to the "trtRoll" field.

This would give us a workable solution, but it would be far from ideal. Since we're applying the values as bonuses, we run into a number of limitations. The most important limitation is that we are unable to allow the user to adjust the trait values. Since the attributes start at the minimum and the bonus is applied, users can increase the die-type but not decrease it. Consequently, we can't allow adjustment, since users will expect full range of adjustment to be possible. Another issue is that users would be unable to adjust the roll bonus. If the user wanted to change a trait from "d12+2" to "d12+1", there would be no way to do it, other than applying a permanent adjustment to the creature.

Giving the problem a bit more thought, a better approach would be to actually set the "trtUser" field of the trait to the proper die-type. This would make it possible for the user to then edit the die-type as he saw fit. Unfortunately, there are two liabilities with this technique. There would still be no way for the user to easily adjust any roll bonus, plus there would be nothing to prevent the user from modifying the die-type independently from the roll bonus. For example, a trait of "d12+1" could have only the die-type modified downwards one notch, which would result in a trait of "d10+1" instead of "d12".

Based on this analysis, we need a single unified value that represents both the die-type and the roll bonus. Once the value reaches a "d12" rating, increasing it one step would become "d12+1". The increase would steadily adjust the roll bonus as soon as the maximum die-type was reached. How can we do this?

The trick is to modify the behavior of the "trtUser" field when dealing with a creature. For a normal character, the "trtUser" field has a fixed range of 2-6, corresponding to the "d4" through "d12" die-types. However, we already have to handle the case of the die-type exceeding "d12" when determining what to display, so having a value of 8 will still result in a "d12" being displayed. This means we can change the maximum limit to higher than 6 and the die-type display will continue to work fine.

Armed with this knowledge, we can consider values larger than 6 to indicate progressive increases in the roll bonus. A value of 7 would translate to "d12+1", while 8 would translate to "d12+2", etc. We can write an Eval script to detect a value greater than 6 and automatically apply the excess as a roll bonus by modifying the "trtRoll" field.

Since the "trtUser" field is directly modifiable by the user via the incrementer, this approach affords the user with a simple, intuitive means of adjusting traits. They start out at "d4", progress upwards through "d12", and then continue to increase as "d12+N". Decrementing the trait works seamlessly in the other direction.

We've got our strategy mapped out, so let's put the basic mechanisms into place. There are two changes we need to make internally to support this approach. The first is to setup a different maximum value for traits when creating a creature. We'll support up to "d12+10", so we'll set out maximum accordingly. The Eval script where the ranges are specified can be changed to the following.

<eval index="3" phase="Initialize" priority="3000"><![CDATA[
  ~since die types range from d4 to d12, in multiples of 2, we have a range of
  ~2-6 for traits - we'll convert to the die type for display in a separate script
  ~Note: Creatures treat excess as a roll bonus, so let the maximum go to 16 (+10).
  field[trtMinimum].value = 2
  if (hero.tagis[Hero.Creature] <> 0) then
    field[trtMaximum].value = 16
  else
    field[trtMaximum].value = 6
    endif
  ]]></eval>

With the maximum relaxed, we can add the handling for a value that exceeds 6. We'll define a new Eval script that only does something when we have a creature with a trait that exceeds 6. If we do, then the excess is added to the "trtRoll" field and becomes a roll bonus. The new Eval script should look like the one below.

<eval index="5" phase="Traits" priority="8000">
  <before name="Calc trtNetRoll"/><![CDATA[
    ~for creatures with a die-type greater than 6, the excess is a roll bonus
    if (hero.tagis[Hero.Creature] <> 0) then
      if (field[trtUser].value > 6) then
        field[trtRoll].value = field[trtUser].value - 6
        endif
      endif
  ]]></eval>

External Approach

We also have to figure out a convenient way to let authors specify the die-type and roll bonus values for each trait. Whatever we come up with should be readily adaptable for use within the integrated Editor, thereby allowing users to add their own custom creatures easily.

As above, the first idea is probably going to be two separate fields that can be specified. Since we're only assigning starting values, we don't have to worry about having a smooth progression. However, two separate values does make it possible for the user to inadvertently specify a roll bonus with a die-type less than "d12", such as "d8+2". So a single value would be ideal.

If we only have a single value, we then need to assess what that value will be and how the user will specify it. We currently use a value of 2-6 for the die-types "d4" through "d12". Our internal solution calls for using values of 7+ to indicate the roll bonus beyond a "d12". While all this makes perfect sense for internal use, it's going to seem like nonsense to a user with no knowledge about the inner workings of our data files. An most users don't want to understand the inner workings - they just want to knock out a quick creature for use in the upcoming game and be done with it. That means field values are a poor solution.

The best solution is to use an assortment of tags. We could define a new tag group that contains tags corresponding to each internal value we want to support. Each tag could be defined with a suitable publicly visible name that presents something intuitive to the user. For example, the tag for the value "7" would have a name of "d12+1", so the user would select "d12+1" within the Editor and the proper value of 7 would be assigned internally. We can use the "tagvalue" target reference within the scripting language to extract a value from the unique id of each tag, so we simply need to ensure that the unique id of the tags is the value we want to use internally.

An example of what the tag group should look like is provided below. We define tags that extend up to a "+10" bonus on the trait, which will be the maximum we support.

<group
  id="DieType"
  name="Die-Type">
  <value id="2" name="d4"/>
  <value id="3" name="d6"/>
  <value id="4" name="d8"/>
  <value id="5" name="d10"/>
  <value id="6" name="d12"/>
  <value id="7" name="d12+1"/>
  <value id="8" name="d12+2"/>
  <value id="9" name="d12+3"/>
  <value id="10" name="d12+4"/>
  <value id="11" name="d12+5"/>
  <value id="12" name="d12+6"/>
  <value id="13" name="d12+7"/>
  <value id="14" name="d12+8"/>
  <value id="15" name="d12+9"/>
  <value id="16" name="d12+10"/>
  </group>

At this point, we now have both our internal and external approaches mapped out. We can now begin implementing our solution.

Assigning Attributes

We'll first setup the means for specifying the attribute values to be used when defining creatures. We need to use a group of tags to specify both the die-type and roll bonus for each attribute. However, if we only define one set of tags and re-use them, we'll run into the problem of determining which tag is associated with which attribute. This means we need a separate set of tags for each attribute. Each of the tag groups is shown below, and the full set of tags defined in the previous section must be specified for each tag group.

<group
  id="AgiDie"
  name="Agility Die-Type">
  ...
  </group>

<group
  id="SmaDie"
  name="Smarts Die-Type">
  ...
  </group>

<group
  id="SpiDie"
  name="Spirit Die-Type">
  ...
  </group>

<group
  id="StrDie"
  name="Strength Die-Type">
  ...
  </group>

<group
  id="VigDie"
  name="Vigor Die-Type">
  ...
  </group>

We now have five tag groups, each with its own set of tags. Each creature can be assigned a single tag from each tag group, with each tag dictating the appropriate die-type and roll bonus for its corresponding attribute. For example, the creature below would be assigned die-types of "d4" through "d12" for the various attributes.

<thing
  id="creSample"
  name="Sample"
  compset="Creature"
  isunique="yes"
  description="Description goes here">
  <tag group="AgiDie" tag="2"/>
  <tag group="SmaDie" tag="3"/>
  <tag group="SpiDie" tag="4"/>
  <tag group="StrDie" tag="5"/>
  <tag group="VigDie" tag="6"/>
  </thing>

The final piece we need to handle is taking the values dictated by the tags and assigning them to the appropriate attributes. Our first instinct will be to create a new Eval script. In that script, we can assign the value of each tag to the "trtUser" field of the trait. Unfortunately, that won't work.

The problem is that using an Eval script will result in the value being applied to the field during every evaluation cycle. If we do that, the user can modify the attribute all he wants, but we'll always keep resetting the value back to the initial value for the creature. That's not what we had in mind.

Fields of type "user" work differently from "derived" fields. A "derived" field is reset at the start of each evaluation cycle and must be set to an appropriate value within each cycle. In contrast, a "user" field is only ever changed when the user makes a change or a script assigns a new value. Consequently, what we need to do is assign the proper values to the "user" fields when the creature is created and never touch them again. That way, we initialize them and hand control to the user thereafter.

The Kit provides a mechanism to handle exactly this type of situation. Every component can define a Creation script. This script is invoked exactly once for every pick derived from that component - at the time the pick is first created. If we assign the values within this script, they will be setup once and never modified again. The appropriate Creation script for setting up the various attributes is shown below.

<creation><![CDATA[
  ~assign the appropriate die-type ratings to attributes
  #traituser[attrAgi] = tagvalue[AgiDie.?]
  #traituser[attrSma] = tagvalue[SmaDie.?]
  #traituser[attrSpi] = tagvalue[SpiDie.?]
  #traituser[attrStr] = tagvalue[StrDie.?]
  #traituser[attrVig] = tagvalue[VigDie.?]
  ]]></creation>

Reload the data files, create a creature, and then select the sample creature above. If everything is working, each of the attributes should be initialized to the proper die-type. Modifying the various attributes up and down via the incrementer will properly adjust the attributes, allowing the user to fully control everything after the creature is first added.

The one limitation of this approach is that changing the creature will reset any adjustments made by the user. In general, that behavior is a good thing, since a new creature should always start out with the default values assigned in the rulebook.

Assigning Skills

The overall technique for assigning skills is very similar to the one used for attributes. However, there is a very important wrinkle in dealing with skills. In Savage Worlds, skills are not added to every character, so that means creatures don't begin with any skills. The technique we used for attributes assumes that the attribute is already on the character so that it can be properly adjusted.

The only way to add a skill to a character is by bootstrapping it. This means that each creature must bootstrap each of the skills that it possesses. Once we do that, though, we need a way to initialize the "trtUser" field of the skill appropriately. If we try to do anything within the Creation script of the "Creature" component, it will fail, since the script is invoked immediately upon creation, which is before any bootstrapped picks are added to the creature.

The solution is to leverage the Creation script on the skill itself. We can assign the appropriate die-type tag to the skill as part of the bootstrap process. That tag is considered part of the skill, so it can be utilized within the Creation script of the skill.

This means that we only need a single tag group for all skills. Since the proper tag will be assigned to each separate skill, no skill should have more than one such tag. So we can define a new tag group like the one below that contains all of the various tags for the different die-types.

<group
  id="SkillDie"
  name="Skill Die-Type">
  ...
  </group>

With the tag group in place, we can assign a few skills to our sample creature for testing. Each skill is bootstrapped and assigned the proper tag for the die-type it should possess. The revised sample creature below demonstrates three skills be added to the creature. These skills are then assigned die-types of "d6", "d8", and "d10".

<thing
  id="creSample"
  name="Sample"
  compset="Creature"
  isunique="yes"
  description="Description goes here">
  <tag group="AgiDie" tag="2"/>
  <tag group="SmaDie" tag="3"/>
  <tag group="SpiDie" tag="4"/>
  <tag group="StrDie" tag="5"/>
  <tag group="VigDie" tag="6"/>
  <bootstrap thing="skFighting">
    <autotag group="SkillDie" tag="3"/>
    </bootstrap>
  <bootstrap thing="skGuts">
    <autotag group="SkillDie" tag="4"/>
    </bootstrap>
  <bootstrap thing="skNotice">
    <autotag group="SkillDie" tag="5"/>
    </bootstrap>
  </thing>

The skills are automatically added to the creature and assigned their default rating of "d4". We now need to do something with the tags to initialize the die-type ratings. We'll define a Creation script for the "Skill" component. In this script, we'll first check to make sure that we have a creature and a suitable tag with which to initialize the skill. We can then use the same approach as with attributes, assigning the value of the tag as the initial value of the "trtUser" field. The Creation script below shows the logic in action.

<creation><![CDATA[
  ~if this is a creature with a skill rating, assign the die-type rating to the skill
  if (hero.tagis[Hero.Creature] + tagis[SkillDie.?] >= 2) then
    field[trtUser].value = tagvalue[SkillDie.?]
    endif
  ]]></creation>

At this point, skills should be working smoothly for creatures.

Assigning Derived Traits

Derived traits work quite differently from attributes and skills for normal characters. That's because they are 100% derived from facets of the character. For creatures, though, we need to handle them differently. Various creatures have values assigned for certain derived traits that are not purely derived. The most common trait is "Pace", but other traits vary as well.

The problem is that derived traits are always calculated in the end. We need to handle them in a way that will smoothly integrate with their calculated nature. Unfortunately, there is no clean way of doing that by having the derived trait value be specified explicitly for a creature. The only way to reasonably accomplish it is to utilize an adjustment that gets incorporated into the calculated final value.

This means that we need to define four new fields for the "Creature" component. We need one field apiece for the four derived traits, where each field specifies an adjustment from the standard calculated value. If a field is not specified, then no extra adjustment will be applied for that trait.

From a usage standpoint, the problem with this approach centers on Pace. Virtually all creatures have a custom Pace, so we should really assume that Pace has a starting value of zero instead of the current six. That way, the actual Pace can be specified instead of an adjustment. Since the other derived traits rarely differ from the calculated value, requiring an adjustment to the calculated value is perfectly reasonable.

In order to specify the Pace as an explicit value, we need to modify the trait itself. The "trPace" trait currently assumes a default value of six for the "trtBonus" field. We need to override that behavior when we have a creature. So we'll define the following Eval script on the trait to apply the special handling.

<eval index="2" phase="Initialize" priority="3000"><![CDATA[
  if (hero.tagis[Hero.Creature] <> 0) then
    field[trtBonus].value = 0
    endif
  ]]></eval>

With the change in place, we can shift back to the fields on the "Creature" component. We'll end up with four fields, where the Pace indicates the actual starting value to use and the others indicate an adjustment. Our new fields should looks like the following.

<field
  id="crePace"
  name="Base Pace"
  type="static">
  </field>

<field
  id="creParry"
  name="Parry Adjustment"
  type="static">
  </field>

<field
  id="creTough"
  name="Toughness Adjustment"
  type="static">
  </field>

<field
  id="creCharis"
  name="Charisma Adjustment"
  type="static">
  </field>

We now need to communicate the adjustment value for each derived trait from the creature. Each derived trait needs to know what the particular adjustment value is. We'll define a new field on the "Derived" component for this purpose, which should look like below.

<field
  id="trtCreatur"
  name="Creature Start"
  type="derived">
  </field>

Each creature can tell its derived traits the value to be used via an Eval script on the "Creature" component. This script must be invoked early in the evaluation cycle, but it is otherwise very simple. The result script is shown below.

<eval index="3" phase="Setup" priority="5000"><![CDATA[
  ~setup the proper starting values for each trait
  hero.child[trPace].field[trtCreatur].value = field[crePace].value
  hero.child[trParry].field[trtCreatur].value = field[creParry].value
  hero.child[trTough].field[trtCreatur].value = field[creTough].value
  hero.child[trCharisma].field[trtCreatur].value = field[creCharis].value
  ]]></eval>

At this point, each derived trait should know the adjustment value specified by any selected creature. Integrating that value into the final calculation for the derived trait is relatively simple. All we need to do is revise the Eval script that calculates the value of "trtFinal" to add in the adjustment for creatures. We can achieve this by adding the lines of code below to the Eval script.

~if this is a creature, we need to add the user value as a custom adjustment
if (hero.tagis[Hero.Creature] <> 0) then
  field[trtFinal].value += field[trtCreatur].value
  endif

That's all there is to it. We're now ready to give our changes a try. When we select a creature from the chooser, the appropriate values should be applied as adjustments to the final derived trait values. Let's put our changes to the test with an actual creature that applies adjustments.

We'll modify our sample creature for this purpose. We can assign a few field values on the creature to apply our adjustments. We'll assign a "Pace" of "5" and a "Parry" adjustment of "1". To do this, we'll add the following XML elements to the creature's definition.

<fieldval field="crePace" value="5"/>
<fieldval field="creParry" value="1"/>

Reload the data files and create a creature. Take a look at the default values shown for the derived traits. From the chooser, select our test creature. The "Pace" value should immediately change to "5", and the "Parry" value should change from "2" to "3". Our derived traits are working smoothly now.

Assigning Gear

The assignment of standard gear to creatures is incredibly simple. All that's needed is to bootstrap the desired gear onto the creature. If the gear is a weapon or armor, then you may also want to have the gear start out in the "equipped" state, which can be accomplished by assigning the "Equipment.StartEquip" tag to the gear. For example, a "Dagger" can be automatically assigned to a creature and pre-equipped via the XML element below.

<bootstrap thing="wpDagger">
  <autotag group="Equipment" tag="StartEquip"/>
  </bootstrap>

Many creatures also possess a natural attack of some sort and/or natural armor. You can add these as weapons in the same way as other gear. However, you're much better off using the customizable abilities that we defined earlier for this purpose.

Assigning Abilities

The assignment of abilities to a creature is comparable to assigning gear. Once the ability is defined, a simple "bootstrap" element is all that's needed. The definition of abilities has already been outlined previously. For example, the "Rollover" special ability of an Alligator can be defined as shown below and assigned to a creature via the bootstrap beneath.

<thing
  id="abRollover"
  name="Rollover"
  compset="RaceAbil"
  isunique="yes"
  description="Description goes here">
  </thing>
<bootstrap thing="abRollover"/>

If a creature has a natural weapon, it's easiest to use the customizable weapon we defined earlier. No new ability needs to be defined, as the existing "Unarmed Attack" weapon can be tailored to the particulars necessary for the creature. For example, the "Bite" attack of the Alligator can be assigned to the creature via the following.

<bootstrap thing="abWeapon">
  <assignval field="livename" value="Bite"/>
  <assignval field="abilText" value="+d6"/>
  </bootstrap>

A similar mechanism was defined for use with natural armor and can be readily employed. All that's needed is the defensive bonus conferred. For example, the thick skins of the Alligator confer a "+2" armor bonus, which can be assigned via the following.

<bootstrap thing="abArmor">
  <assignval field="abilValue" value="2"/>
  </bootstrap>