Encumbrance (Savage): Difference between revisions

From HLKitWiki
Jump to navigationJump to search
New page: {{context|Authoring Examples|Savage Worlds Walk-Through}} ===Overview=== In reviewing all of the hindrances and edges, there is an additional game mechanic that edges can influence: encu...
 
 
(One intermediate revision by the same user not shown)
Line 20: Line 20:
===New Resources===
===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 new 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:  
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:  


<pre>
<pre>
Line 29: Line 29:
   <fieldval field="resMin" value="0"/>
   <fieldval field="resMin" value="0"/>
   <tag group="Helper" tag="Bootstrap"/>  
   <tag group="Helper" tag="Bootstrap"/>  
   <eval value="1" phase="Final" priority="500">
 
   <eval index="1" phase="Final" priority="500">
     <before name="Calc resLeft"/><![CDATA[
     <before name="Calc resLeft"/><![CDATA[
     ~get our limit from the load limit resource
     ~get our limit from the load limit resource
     var limit as number
     var limit as number
     limit = #resmax[resLoadLim]  
     limit = #resmax[resLoadLim]  
     ~calculate how many multiples we've consumed via the load limit details
     ~calculate how many multiples we've consumed via the load limit details
     var multiples as number
     var multiples as number
Line 40: Line 42:
       multiples += round(field[resSpent].value / limit,0,-1)
       multiples += round(field[resSpent].value / limit,0,-1)
       endif  
       endif  
     ~set our maximum appropriately for encumbrance reporting
     ~set our maximum appropriately for encumbrance reporting
     field[resMax].value = multiples * limit
     field[resMax].value = multiples * limit
Line 51: Line 54:
   <fieldval field="resMin" value="0"/>
   <fieldval field="resMin" value="0"/>
   <tag group="Helper" tag="Bootstrap"/>  
   <tag group="Helper" tag="Bootstrap"/>  
   <eval value="1" phase="Traits" priority="7000" name="Calc LoadLimit">
 
   <eval index="1" phase="Traits" priority="7000" name="Calc LoadLimit">
     <before name="Calc resLeft"/><![CDATA[
     <before name="Calc resLeft"/><![CDATA[
     ~our maximum is based on the Strength and load limit multiplier
     ~our maximum is based on the Strength and load limit multiplier
     field[resMax].value = herofield[acLoadMult].value * #trait[attrStr] * 2
     field[resMax].value = herofield[acLoadMult].value * #trait[attrStr] * 2
     ]]></eval>  
     ]]></eval>  
   <eval value="2" phase="Traits" priority="8000" name="Apply LoadLimit">
 
   <eval index="2" phase="Traits" priority="8000" name="Apply LoadLimit">
     <after name="Accrue Weight"/>
     <after name="Accrue Weight"/>
     <after name="Calc LoadLimit"/><![CDATA[
     <after name="Calc LoadLimit"/><![CDATA[
Line 63: Line 68:
     spent = #resspent[resEncumb]
     spent = #resspent[resEncumb]
     field[resExtra].value = spent  
     field[resExtra].value = spent  
     ~if we haven't exceeded the load limit, there's nothing to do
     ~if we haven't exceeded the load limit, there's nothing to do
     if (spent <= field[resMax].value) then
     if (spent <= field[resMax].value) then
       done
       done
       endif  
       endif  
     ~calculate how many multiples we exceeded the limit by
     ~calculate how many multiples we exceeded the limit by
     var overage as number
     var overage as number
     overage = round(spent / field[resMax].value,0,-1)  
     overage = round(spent / field[resMax].value,0,-1)  
     ~apply the appropriate penalty to all Strength and Agility rolls
     ~apply the appropriate penalty to all Strength and Agility rolls
     #traitroll[attrStr] -= overage
     #traitroll[attrStr] -= overage
     #traitroll[attrAgi] -= overage  
     #traitroll[attrAgi] -= overage  
     ~apply the penalty to all skills based on Strength and Agility
     ~apply the penalty to all skills based on Strength and Agility
     ~???? we can't do this yet ????
     ~???? we can't do this yet ????
Line 83: Line 92:
===Identifying Skills Tied to Attributes===
===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 Hero Lab 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:
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:


<pre>
<pre>
Line 89: Line 98:
</pre>
</pre>


We now have an identity tag defined for every attribute, with that tag being 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 Hero Lab do all of the work for us. The new script for the "Skill" component should look something like the following:  
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:  


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


===Revising the Resource===
===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 Hero Lab's "foreach" statement within scripts, which iterates through all picks that match a given tag expression and allows you to process them.   
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:
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:
Line 107: Line 116:
</pre>
</pre>


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 "each." 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.  
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.  


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

Latest revision as of 04:14, 18 December 2008

Context: HL Kit &#133; Authoring Examples &#133; 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