Adding Hindrances (Savage): Difference between revisions

From HLKitWiki
Jump to navigationJump to search
New page: {{context|Authoring Examples|Savage Worlds Walk-Through}} ===Overview=== Now that all of the mechanics are in place for hindrances, it's possible to actually define them. To keep them al...
 
 
(One intermediate revision by the same user not shown)
Line 7: Line 7:
===General Reminders===
===General Reminders===


Some hindrances apply penalties that are situational. When the situation may persist for an extended period, the user may want to toggle the effects on and leave them that way for a period of time. To support this, appropriate hindrances should be designated as able to be user-activated by assigning the "User.Activation" tag. This will display the hindrance as something the user can toggle on and off on the "In-Play" tab. A script that applies the effects can then check the actual activation state of the hindrance and apply the effects when appropriate.
Some hindrances apply penalties that are situational. When the situation may persist for an extended period, the user may want to toggle the effects on and leave them that way for a period of time. To support this, appropriate hindrances should be designated as able to be user-activated by assigning the "User.Activation" tag. This will display the hindrance as something the user can toggle on and off within the "In-Play" tab. A script that applies the effects can then check the actual activation state of the hindrance and apply the effects when appropriate.


If you need to reference a trait from a script of some sort (e.g. within a pre-requisite test), be careful to handle it properly. If the trait is a skill or something else the user can optionally add to the character, the trait might not exist on the character. If that's possible, be sure to use the "#traitfound" macro instead of "#trait", else you will receive run-time errors from Hero Lab that you're trying to access picks that don't exist. 
If you need to reference a trait from a script of some sort (e.g. within a pre-requisite test), be careful to handle it properly. If the trait is a skill or something else the user can optionally add to the character, the trait might not exist on the character. If that's possible, be sure to use the "#traitfound" macro instead of "#trait", else you will receive run-time errors from HL that you're trying to access picks that don't exist. 


Adding all the hindrances is a straightforward process of going through and entering all of the details accurately. We'll select a few representative samples to cover in the sections below, pointing out key facets of each.  
Adding all the hindrances is a straightforward process of going through and entering all of the details accurately. We'll select a few representative samples to cover in the sections below, pointing out key facets of each.  
Line 42: Line 42:
   <fieldval field="hinMajor" value="1"/>
   <fieldval field="hinMajor" value="1"/>
   <tag group="User" tag="Activation"/>
   <tag group="User" tag="Activation"/>
   <eval value="1" phase="PreTraits" priority="5000">
 
   <eval index="1" phase="PreTraits" priority="5000">
     <before name="Calc trtFinal"/><![CDATA[
     <before name="Calc trtFinal"/><![CDATA[
     ~if activated, suffer -4 on Charisma
     ~if activated, suffer -4 on Charisma
Line 82: Line 83:
   <fieldval field="hinMajor" value="0"/>
   <fieldval field="hinMajor" value="0"/>
   <tag group="User" tag="UserSelect"/>
   <tag group="User" tag="UserSelect"/>
   <eval value="1" phase="PreTraits" priority="5000">
 
   <eval index="1" phase="PreTraits" priority="5000">
     <before name="Calc trtFinal"/><![CDATA[
     <before name="Calc trtFinal"/><![CDATA[
     ~if this is a minor hindrance, allow the user to activate it
     ~if this is a minor hindrance, allow the user to activate it
Line 88: Line 90:
       perform assign[User.Activation]
       perform assign[User.Activation]
       endif
       endif
     ~if this is a major hindrance or the user has activated it, apply the effects
     ~if this is a major hindrance or the user has activated it, apply the effects
     if (field[hinMajor].value + field[abilActive].value <> 0) then
     if (field[hinMajor].value + field[abilActive].value <> 0) then
Line 99: Line 102:
===Handling Pre-Requisites===
===Handling Pre-Requisites===


In rare cases, a hindrance will have pre-requisites that need to be properly handled. For example, the "Bad Luck" hindrance can't be taken at the same time as the "Luck" edge. For situations like this, we need to define an appropriate "prereq" element that checks the state of the character and reports whether the pre-requisite conditions are satisfied. If not satisfied during selection display, the invalid choice can be highlighted appropriately. However, if an invalid selection is actually added to the character, then a validation message is displayed to the user. We can also designate the tab panel corresponding to the hindrance as invalid to highlight it to the user. We can put it all together into something that looks like the following:
In rare cases, a hindrance will have pre-requisites that need to be properly handled. For example, the "Bad Luck" hindrance can't be taken at the same time as the "Luck" or "Great Luck" edges. For situations like this, we need to define an appropriate pre-requisite test that checks the state of the character and reports whether the pre-requisite conditions are satisfied. If not satisfied during selection display, the invalid choice can be highlighted appropriately. However, if an invalid selection is actually added to the character, then a validation message is displayed to the user. We can also designate the tab panel corresponding to the hindrance as invalid to highlight it to the user. We can put it all together into something that looks like the following:


<pre>
<pre>
Line 109: Line 112:
   description="Description goes here">
   description="Description goes here">
   <fieldval field="hinMajor" value="1"/>
   <fieldval field="hinMajor" value="1"/>
   <eval value="1" phase="PreTraits" priority="5000">
   <eval index="1" phase="PreTraits" priority="5000">
     <before name="Calc trtFinal"/><![CDATA[
     <before name="Calc trtFinal"/><![CDATA[
     #trkmax[trkBennies] -= 1
     #trkmax[trkBennies] -= 1
     ]]></eval>
     ]]></eval>
   <prereq iserror="yes" message="Precluded by Luck and Great Luck.">
<!--
    <valid><![CDATA[
   <pickreq ispreclude="yes" thing="edgLuck"/>
      if (hero.tagis[Edge.edgLuck?] = 0) then
  <pickreq ispreclude="yes" thing="edgLuck2"/>
        @valid = 1
-->
        done
        endif
      altthing.linkvalid = 0
      ]]></valid>
    </prereq>
   </thing>
   </thing>
</pre>
</pre>


{{note}}In the above PreReq script, we check for the existence of one of the Luck edges by checking on tags. These tags won't exist until we actually define the edges, but we can add the script code now if we wish.  
{{note}}In the above "pickreq" elements, we check for the existence of one of the two Luck edges. However, these things won't exist until we actually define the edges, so the compiler will reject the above thing as invalid. For now, we'll comment out the two XML elements, as shown above, and make a note to put these back into place when we actually add the edges later.


===Acknowledging Our Limitations===
===Acknowledging Our Limitations===


Every now and then, you'll come across an incredibly specialized requirement for a particular thing that will require an inordinate amount of work to properly verify within the data files. When this happens, you can either spend many hours to handle the special case situation or you can defer the special case to the user. A perfect example of this within the Savage Worlds data files is the "Elderly" hindrance, which dictates that the extra skill points it confers must be spent on skills based on the "Smarts" attribute. It is simple to increase the number of skill points available to be spent, but requiring them to all be spent on a subset of skills requires that the additional skills be purchased and tracked separately from the standard pool of skills. While possible, it's a lot of work to implement properly, and all for a lone special case that is probably not very frequently used by players. In situations like this, it's often best to simply acknowledge the special case as a limitation of the data files and flag it to the user within the description text for the thing. That's what we're going to do with the "Elderly" hindrance.
Every now and then, you'll come across an incredibly specialized requirement for a particular thing that will require an inordinate amount of work to properly verify within the data files. When this happens, you can either spend many hours to handle the special case situation or you can defer the special case to the user. A perfect example of this within the Savage Worlds data files is the "Elderly" hindrance, which dictates that the extra skill points it confers must be spent on skills based on the "Smarts" attribute. It is simple to increase the number of skill points available to be spent, but requiring them to all be spent on a subset of skills requires that the additional skills be purchased and tracked separately from the standard pool of skills. While possible, it's a lot of work to implement properly, and all for a lone special case that is probably not very frequently used by players. In situations like this, it's often best to simply acknowledge the special case as a limitation of the data files and flag it to the user within the description text for the thing. That's what we're going to do with the "Elderly" hindrance.

Latest revision as of 04:13, 18 December 2008

Context: HL Kit &#133; Authoring Examples &#133; Savage Worlds Walk-Through 

Overview

Now that all of the mechanics are in place for hindrances, it's possible to actually define them. To keep them all together as a group, we create a new "thing_hindrances.dat" file where they will be added. When adding hindrances, be mindful of using the correct "#traitroll" or "#traitbonus" macro, since the two have important differences in their behavior.

General Reminders

Some hindrances apply penalties that are situational. When the situation may persist for an extended period, the user may want to toggle the effects on and leave them that way for a period of time. To support this, appropriate hindrances should be designated as able to be user-activated by assigning the "User.Activation" tag. This will display the hindrance as something the user can toggle on and off within the "In-Play" tab. A script that applies the effects can then check the actual activation state of the hindrance and apply the effects when appropriate.

If you need to reference a trait from a script of some sort (e.g. within a pre-requisite test), be careful to handle it properly. If the trait is a skill or something else the user can optionally add to the character, the trait might not exist on the character. If that's possible, be sure to use the "#traitfound" macro instead of "#trait", else you will receive run-time errors from HL that you're trying to access picks that don't exist. 

Adding all the hindrances is a straightforward process of going through and entering all of the details accurately. We'll select a few representative samples to cover in the sections below, pointing out key facets of each.

Something Simple

We'll start with the "Delusional" hindrance, since it's relatively basic in nature. This hindrance can be either minor or major in severity, so we assign it an initial severity of minor (via the field) and then assign it the "User.UserSelect" tag to indicate the user can select the ultimate severity level. Other than that, there is nothing to do, since the hindrance's effects are something the GM must adjudicate. The result is a simple hindrance as shown below.

<thing
  id="hinDelude"
  name="Delusional"
  compset="Hindrance"
  isunique="yes"
  description="Description goes here">
  <fieldval field="hinMajor" value="0"/>
  <tag group="User" tag="UserSelect"/>
  </thing> 

User Activation

Now we'll look at the "Bloodthirsty" hindrance, since it will demonstrate user-activated behaviors. This hindrance is always major in severity, so we set the field value accordingly. The effects of the hindrance don't always apply, so we allow the user to control when to apply them by assigning the "User.Activation" tag. In the script that applies the effects, we then check whether the activation state is on or off, applying the effects only if activated. The net result is the definition below.

<thing
  id="hinBloodth"
  name="Bloodthirsty"
  compset="Hindrance"
  isunique="yes"
  description="Description goes here">
  <fieldval field="hinMajor" value="1"/>
  <tag group="User" tag="Activation"/>

  <eval index="1" phase="PreTraits" priority="5000">
    <before name="Calc trtFinal"/><![CDATA[
    ~if activated, suffer -4 on Charisma
    if (field[abilActive].value <> 0) then
      #traitbonus[trCharisma] -= 4
      endif
    ]]></eval>
  </thing> 

User-Specified Domains

The "Phobia" hindrance is a perfect example of when the user needs to specify a suitable domain, in this case identifying what the character is afraid of. As far as the mechanics are concerned here, requiring the user to specify a domain is as simple as assigning the "User.NeedDomain" tag. So that's all we need to do besides allowing the user to designate the severity, and the results can be seen below.

<thing
  id="hinPhobia"
  name="Phobia"
  compset="Hindrance"
  isunique="yes"
  description="Description goes here">
  <fieldval field="hinMajor" value="0"/>
  <tag group="User" tag="UserSelect"/>
  <tag group="User" tag="NeedDomain"/>
  </thing> 

Dynamic Control Over User Activation

Now we'll switch to the "Bad Eyes" hindrance, since it demonstrates how to combine many of the mechanics involved and throws an interesting wrinkle into the mix. This hindrance can be either minor or major, so we assign it an appropriate field value and tag. When the hindrance is minor, the user can toggle the penalties on and off based on whether the character has temporarily lost his glasses, so we should probably assign the "User.Activation" tag to give the user control. But when the hindrance is major, the penalties always apply, in which case we don't want the user to have control. So what we really need to do is have the hindrance be user controlled only when it is minor. This requires that we change the behavior dynamically, which can be done within the script by assigning the tag only when the hindrance is minor. Putting it all together yields the following definition:

<thing
  id="hinBadEyes"
  name="Bad Eyes"
  compset="Hindrance"
  isunique="yes"
  description="Description goes here">
  <fieldval field="hinMajor" value="0"/>
  <tag group="User" tag="UserSelect"/>

  <eval index="1" phase="PreTraits" priority="5000">
    <before name="Calc trtFinal"/><![CDATA[
    ~if this is a minor hindrance, allow the user to activate it
    if (field[hinMajor].value = 0) then
      perform assign[User.Activation]
      endif

    ~if this is a major hindrance or the user has activated it, apply the effects
    if (field[hinMajor].value + field[abilActive].value <> 0) then
      #traitroll[skShooting] -= 2
      #traitroll[skNotice] -= 2
      endif
    ]]></eval>
  </thing> 

Handling Pre-Requisites

In rare cases, a hindrance will have pre-requisites that need to be properly handled. For example, the "Bad Luck" hindrance can't be taken at the same time as the "Luck" or "Great Luck" edges. For situations like this, we need to define an appropriate pre-requisite test that checks the state of the character and reports whether the pre-requisite conditions are satisfied. If not satisfied during selection display, the invalid choice can be highlighted appropriately. However, if an invalid selection is actually added to the character, then a validation message is displayed to the user. We can also designate the tab panel corresponding to the hindrance as invalid to highlight it to the user. We can put it all together into something that looks like the following:

<thing
  id="hinBadLuck"
  name="All Thumbs"
  compset="Hindrance"
  isunique="yes"
  description="Description goes here">
  <fieldval field="hinMajor" value="1"/>
  <eval index="1" phase="PreTraits" priority="5000">
    <before name="Calc trtFinal"/><![CDATA[
    #trkmax[trkBennies] -= 1
    ]]></eval>
<!--
  <pickreq ispreclude="yes" thing="edgLuck"/>
  <pickreq ispreclude="yes" thing="edgLuck2"/>
-->
  </thing>

NOTE! In the above "pickreq" elements, we check for the existence of one of the two Luck edges. However, these things won't exist until we actually define the edges, so the compiler will reject the above thing as invalid. For now, we'll comment out the two XML elements, as shown above, and make a note to put these back into place when we actually add the edges later.

Acknowledging Our Limitations

Every now and then, you'll come across an incredibly specialized requirement for a particular thing that will require an inordinate amount of work to properly verify within the data files. When this happens, you can either spend many hours to handle the special case situation or you can defer the special case to the user. A perfect example of this within the Savage Worlds data files is the "Elderly" hindrance, which dictates that the extra skill points it confers must be spent on skills based on the "Smarts" attribute. It is simple to increase the number of skill points available to be spent, but requiring them to all be spent on a subset of skills requires that the additional skills be purchased and tracked separately from the standard pool of skills. While possible, it's a lot of work to implement properly, and all for a lone special case that is probably not very frequently used by players. In situations like this, it's often best to simply acknowledge the special case as a limitation of the data files and flag it to the user within the description text for the thing. That's what we're going to do with the "Elderly" hindrance.