There are a number of facets to the Savage Worlds game system that entail the tracking of a resource. Since those game mechanics are relatively fundamental and will likely come into play soon, we might as well get those handled now. The Skeleton files provide two re-usable components and component sets that we can build upon, depending on what we need for a given resource - there is the "Resource" and the "Tracker", and both will be put to good use. These components are defined in the files "miscellaneous.str" and "components.core", respectively. By convention, all resource and tracker things are defined in the file "thing_miscellaneous.dat".
Number of Edges
We'll start with something easy. Characters begin the game with the ability to choose one or more edges. The number of edges allowed is driven by a number of effects, such as the character's race. In addition, as characters advance, they may purchase access to new edges. So the number will potentially increase over time.
The number of edges is not directly controlled by the user. It is indirectly effected by selections the user makes. As such, edges are best modeled using the "Resource" mechanism. In fact, all that's needed is to setup the edge count as a "Resource" and simply use all of the built-in capabilities of that component set.
Open the file "thing_miscellaneous.dat" and locate the "resCP" resource that is provided. We'll use that as our template and create a new resource with the unique id "resEdge". Since all characters start out with zero edges by default, we don't need an Eval script to setup the starting quantity, so the script can be deleted. However, all characters need to track an edge count, so we need to ensure the resource gets added to every character. This last requirement is achieved by assigning the "Helper.Bootstrap" tag to the thing.
The net result is a resource defined similarly to the following:
<thing id="resEdge" name="Edges" compset="Resource"> <fieldval field="resObject" value="Edge"/> <tag group="Helper" tag="Bootstrap"/> </thing>
Attribute Points and Skill Points
Savage Worlds characters have a starting pool of points that can be spent to increase their initial attributes and skills. There are separate pools for attributes and skills. As such, we need to define a new "Resource" for each of these pools. As with edges, the starting quantity is fixed, so no Eval script is needed, and we need to ensure each resource is added to every character. This results in the following two resources being defined:
<thing id="resAttrib" name="Attribute Points" compset="Resource"> <fieldval field="resObject" value="Attribute"/> <fieldval field="resMax" value="5"/> <tag group="Helper" tag="Bootstrap"/> </thing> <thing id="resSkill" name="Skill Points" compset="Resource"> <fieldval field="resObject" value="Skill"/> <fieldval field="resMax" value="15"/> <tag group="Helper" tag="Bootstrap"/> </thing>
When a character selects a hindrance, he gains one or two points of hindrance that can be spent to gain offsetting benefits. These points then need to be spent. Consequently, these points are an ideal candidate for implementation as a "Resource". Just like the resources above, it's very simple, except for one key difference. Since this resource will be shown to the user as governing the selection of rewards to offset hindrances, we need to assign a suitable name to show to the user (e.g. "Reward"). The net result looks like below:
<thing id="resHinder" name="Hindrance Points" compset="Resource"> <fieldval field="resObject" value="Reward"/> <tag group="Helper" tag="Bootstrap"/> </thing>
The Savage Worlds game system has the interesting mechanic of "Bennies". The expenditure of Bennies is controlled directly by the user during the game, so we need to use the "Tracker" mechanism. We'll set the maximum value for the tracker to be the number of Bennies that the character starts each game with. However, we also need to do some special handling for Bennies that entails we define a new component and component set.
It would be beneficial to show the Bennies on the "Special" tab so that the player has the info readily available. This entails including the "SpecialTab" component within the component set, defining a new tag to govern the sequencing of the info on the tab, and assigning the tag to the thing. The assignment can be accomplished within the component, thereby keeping the thing itself very simple.
We'll start by defining the new tag that's required, which takes us to the file "tags.1st". The tag must be added to the "SpecialTab" tag group, and we'll call it "Bennies" for clarity. Tags in this group are assigned an explicit sequencing order, so we must be sure to assign the "order" attribute with a suitable value.
Next, we'll define the new "Bennies" component, which we can add to the file "miscellaneous.str".We must make sure the new "SpecialTab" tag is assigned, so we'll do that in the component. In addition, the default logic for showing information on the "Special" tab is to just give the name of the thing. Since it would be much more useful to show the actual number of Bennies per game session, we need an Eval script to synthesize a customized name for display. The net result is a component that looks something like the following:
<component id="Bennies" name="Bennies" autocompset="no"> <tag group="SpecialTab" tag="Bennies"/> <eval index="1" phase="Render" priority="5000"><![CDATA[ field[spcName].text = "Bennies (" & #trkmax[trkBennies] & " per game)" ]]></eval> </component>
Once the component is defined, we can define the new component set that builds on top of it (again, within "miscellaneous.str"). Our component set needs to include the standard mechanisms of the "Tracker" component and the new "Bennies" component. We also need to include the "SpecialTab" component so that it will be properly handled for display on the "Special" tab. This translates to the following component set definition:
<compset id="Bennies"> <compref component="Tracker"/> <compref component="SpecialTab"/> <compref component="Bennies"/> </compset>
The last step involved is adding the actual "Bennies" thing to the data files. This can be added to "thing_miscellaneous.dat", just like the other resources above. Since most of the logic is handled by the underlying components, the "Bennies" thing is relatively simple. We need to set appropriate bounds for the value, and we need to make sure that it's added to every character. We also need to designate the tracker as resetting its value to be the maximum instead of the minimum (which is the default behavior). Lastly, Bennies are accrued in open-ended fashion, so there cannot be a hard limit to the number possessed at any time. Consequently, we need to stipulate that Bennies have no maximum bounding behavior. The result is shown below.
<thing id="trkBennies" name="Bennies" compset="Bennies"> <fieldval field="trkMin" value="0"/> <fieldval field="trkMax" value="3"/> <tag group="Helper" tag="Bootstrap"/> <tag group="Helper" tag="ResetMax"/> <tag group="Helper" tag="NoMaxBound"/> </thing>
NOTE! Since there is only one "Bennies" thing, we could have just as easily defined some of the logic for Bennies on the thing instead of the component. For example, the script and tag could instead be defined on the thing. There is no "right" way in a situation like this. However, as a general rule, we recommend putting the logic on the component whenever practical. There will be times when you decide to add a second thing of a particular type, at which point having the logic on the component will come in handy by eliminating the need to replicate the logic on the new thing.
While not maintained by an actual resource object, the cash possessed by characters is an important resource that needs to be tracked. The Skeleton files provide all the mechanics for tracking cash, so we don't have to do much more than configure the built-in mechanisms properly. A character's starting cash is tracked via the "acCashCfg" field within the "Actor" component in the file "actor.str". Characters in Savage Worlds start with a default of $500 in starting cash to spend. We simply need to change the default value for this field to "500" so that characters start with the proper amount of cash.