Encumbrance (Savage)

From HLKitWiki
Revision as of 21:14, 17 December 2008 by Rob (Talk | contribs) (Encumbrance (Skeleton) moved to Encumbrance (Savage))

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Context: HL KitAuthoring Examples … Savage Worlds Walk-Through 

Overview

In reviewing all of the hindrances and edges, there is an additional game mechanic that edges can influence: encumbrance. Consequently, this mechanic should be implemented before we start work on hindrances and edges.

Load Limit Multiplier

A key facet of encumbrance in Savage Worlds is the "load limit", which represents the maximum load a character can carry before incurring penalties. It is derived from the "Strength" attribute and a multiplier. By default, characters have a multiplier of five, but edges can modify this multiplier. Consequently, the multiplier needs to be tracked on the "Actor" component as a field that can be changed dynamically. It should look something like the following:

<field
  id="acLoadMult"
  name="Load Limit Multiplier"
  type="derived"
  defvalue="5">
  </field> 

New Resources

Once the multiplier is in place, we then need to track the actual limit itself. However, the limit depends on the actual encumbrance accrued to the character. So we really need to track both the encumbrance and the load limit as separate items. These are best modeled via "Resource" components, with both calculating their effective maximum limit. Gear carried by the character is accrued into the encumbrance resource as an amount spent. This amount is then shared into the load limit resource, making it easy to automatically determine whether the character has exceeded the load limit, and by how much. If the limit is exceeded, then the appropriate penalties can be applied to the various trait rolls via a script. Similarly, the calculated load limit is shared into the encumbrance resource to determine the next encumbrance threshold for display to the user. This yields a pair of resources that look like the following:

<thing
  id="resEncumb"
  name="Encumbrance"
  compset="Resource">
  <fieldval field="resMin" value="0"/>
  <tag group="Helper" tag="Bootstrap"/> 

  <eval index="1" phase="Final" priority="500">
    <before name="Calc resLeft"/><![CDATA[
    ~get our limit from the load limit resource
    var limit as number
    limit = #resmax[resLoadLim] 

    ~calculate how many multiples we've consumed via the load limit details
    var multiples as number
    multiples = 1
    if (field[resSpent].value >= limit) then
      multiples += round(field[resSpent].value / limit,0,-1)
      endif 

    ~set our maximum appropriately for encumbrance reporting
    field[resMax].value = multiples * limit
    ]]></eval>
  </thing> 

<thing
  id="resLoadLim"
  name="Load Limit"
  compset="Resource">
  <fieldval field="resMin" value="0"/>
  <tag group="Helper" tag="Bootstrap"/> 

  <eval index="1" phase="Traits" priority="7000" name="Calc LoadLimit">
    <before name="Calc resLeft"/><![CDATA[
    ~our maximum is based on the Strength and load limit multiplier
    field[resMax].value = herofield[acLoadMult].value * #trait[attrStr] * 2
    ]]></eval> 

  <eval index="2" phase="Traits" priority="8000" name="Apply LoadLimit">
    <after name="Accrue Weight"/>
    <after name="Calc LoadLimit"/><![CDATA[
    ~get quantity spent from encumbrance resource and save it in "extra" field
    var spent as number
    spent = #resspent[resEncumb]
    field[resExtra].value = spent 

    ~if we haven't exceeded the load limit, there's nothing to do
    if (spent <= field[resMax].value) then
      done
      endif 

    ~calculate how many multiples we exceeded the limit by
    var overage as number
    overage = round(spent / field[resMax].value,0,-1) 

    ~apply the appropriate penalty to all Strength and Agility rolls
    #traitroll[attrStr] -= overage
    #traitroll[attrAgi] -= overage 

    ~apply the penalty to all skills based on Strength and Agility
    ~???? we can't do this yet ????
    ]]></eval>
  </thing>

Calculating and applying the penalties for exceeding the limit can all be handled via a single script. The interesting detail is that we need to apply the penalty to all skills that are linked to the "Strength" and "Agility" traits. Doing this will require that we make a few enhancements to the data files, which are covered in the next section.

Identifying Skills Tied to Attributes

We need to identify which skills are tied to which attributes. The easiest way to do this is to assign a tag to each skill that identifies the attribute it's associated with. So we need to define a new tag for each attribute that uniquely identifies that attribute. We can do this ourselves, or we can let HL do all of the work for us. We'll opt for the latter approach and modify the "Attribute" component to have an "identity" tag group named "Attribute". This will automatically define an "identity" tag for each attribute in the data files. Each tag will have the unique id of the thing, so the "Strength" attribute will have an identity tag of "Attribute.attrStr". We can accomplish all this by adding the single line shown below to the "Attribute" component:

<identity group="Attribute"/>  

We now have an identity tag defined for every attribute, with that tag being automatically assigned to each attribute. However, we still need to get the tag onto the skill. We could do this manually by adding the tag to each skill within its definition, but that is tedious and error prone. Each skill already has a linkage to its associated attribute, and we can access the linked attribute via a script, so we can easily write a script for skills that pulls the identity tag out of the attribute and assigns it to the skill. Since the behavior is the same for every skill, we can add this logic to the "Skill" component and let HL do all of the work for us. The new script for the "Skill" component should look something like the following:

<eval index="2" phase="Setup" priority="5000"><![CDATA[
  ~pull the identity tag of the linked attribute into the skill
  perform linkage[attribute].pullidentity[Attribute]
  ]]></eval> 

Revising the Resource

At this point, every skill should be automatically assigned the appropriate "Attribute" tag for the linked attribute. Now we can leverage this information to get our resource working completely. We need to identify all skills that are tied to the "Strength" or "Agility" attributes and operate on each of them. This is achieved by using the Kit's "foreach" statement within scripts, which iterates through all picks that match a given tag expression and allows you to process them.

We need to determine the tag expression to use. First of all, we need to limit ourselves to processing skills. Every thing in the game system is automatically assigned one or more tags from the "component" tag group. Each component has a tag defined and each thing is assigned a tag for each component it derives from. Therefore, every skill will possess the "component.Skill" tag. In order to limit the proper attribute tags, we can check for each of those explicitly. Putting it all together, we end up with a tag expression that identifies a skill that is also either tied to "Strength" or "Agility", as shown below:

component.Skill & (Attribute.attrStr | Attribute.attrAgi) 

With the tag expression figured out, we can now write the script code to locate each skill we want and apply the appropriate penalty. We process the picks within the "hero", since all skills are assigned directly to the hero (i.e. character), and we apply the penalty to each one we access using the "eachpick." transition. The resulting script code is shown below and can be spliced into the resource where we left the big question mark a moment ago.

foreach pick in hero where "component.Skill & (Attribute.attrStr | Attribute.attrAgi)"
  eachpick.field[trtRoll].value -= overage
  nexteach