Statblock Output (Savage)
Context: HL Kit … Authoring Examples … Savage Worlds Walk-Through
Overview
Most game systems have a standard format for presenting a character in a relatively compact, text-only format. The more commonly used term for this format is a "statblock". You'll find NPCs and monsters generally presented using this format within the various rulebooks. Savage Worlds has such a format, so we'll now make sure that we generate the appropriate output.
The Game Plan
The statblock format we'll use for Savage Worlds can be found in the Bestiary section of the core rulebook. It's a simple text format that makes use of bold text for important names. While most creatures in the Bestiary don't possess any gear, there are a few that do. We'll be using the way those entries are formatted as a guideline for how we should be synthesizing our statblock output.
All statblock output is generated via a Synthesize script within a "dossier" element. We're going to start with the statblock that is provided by the Skeleton data files. This starting point can be readily adapted for our purposes with Savage Worlds. It can be found within the file "out_statblock.dat", which also includes a number of procedures that are called directly from the Synthesize script.
How Output Works
As mentioned above, text output is generated via a Synthesize script. Since text output is really just a single big stream of text, it's very clunky to require the author to keep remembering to append data to a string variable. It's also very inefficient from a scripting standpoint. Consequently, the Kit provides a special mechanism that is is specific to text output. The text being synthesized is managed internally by HL and the "append" statement allows the author to easily tack more material onto the end of the output. This results in a simplified process for authors, although it also requires the output be generated in a serialized fashion.
The general mechanism is designed to support various different types of output, including plain text, HTML, and BBCode. In order to make this easy for authors, there are a number of different special symbols that are pre-defined by the Kit. Based on the output format chosen by the user, these symbols map to the appropriate codes for that format. For example, the "@boldon" symbol is used to enable bold text within the output. When the user selects HTML output, this symbol maps to "{b}", while it is empty for plain text output. This allows authors to synthesize the output once and let HL do the work of tailoring it to the appropriate format.
The following sequence of script code will output a series of attributes as text, where each is listed on a new line, the name of the field is in bold, and the description is not.
foreach pick in hero where "component.Attribute" append @boldon & eachpick.field[name].text & @boldoff append ": " & eachpick.field[description] append @newline nexteach
Outputting the Basics
The mechanism provided by the Skeleton files generates all of the basic details for a generic statblock. We're going to adapt it to the specifics of Savage Worlds, and we'll start with the attributes, skills, and derived traits.
The sample script includes the age as an example of inserting personal information about the character. The Savage Worlds format does not include such data, so we need to omit it. That means deleting the code that outputs the age.
For attributes and skills, a procedure is used that is passed in the tag expression to select the proper picks. In both uses, we need to modify the tag expression to omit the attributes and skills that are hidden from output. This results in the revised code below.
~output attributes append @boldon & "Attributes: " & @boldoff tagexpr = "component.Attribute & !Hide.Attribute" call sbtraits ~output skills append @boldon & "Skills: " & @boldoff tagexpr = "component.Skill & !Hide.Skill" call sbtraits
Now we need to revise the procedure contents. The current procedure works perfectly for attributes and most skills. However, it doesn't handle "Knowledge" skills that possess a domain. If a skill has a domain, we need to put that domain in parentheses. This entails modifying the procedure to look like the following.
var tagexpr as string var ismore as number ismore = 0 foreach pick in hero where tagexpr if (ismore <> 0) then append ", " endif append eachpick.field[name].text if (eachpick.tagis[User.NeedDomain] <> 0) then append " (" & eachpick.field[domDomain].text & ")" endif append " " & eachpick.field[trtDisplay].text ismore = 1 nexteach append @newline
Attributes and skills are now handled, so that leaves derived traits. Savage Worlds uses a different format for derived traits, so we need to implement them separately. Since the format is only used for derived traits, we can either write a procedure that does it or put the code directly into the Synthesize script. If the Synthesize script was large and complex, it would probably we worth using a separate procedure, but the script is relatively simple, so we'll just insert the code directly.
The Skeleton files provide logic for outputting derived traits after special abilities. We'll start by moving that code up to just below the output of skills. Once that's done, we'll adapt the code. Since Savage Worlds uses a comma-separated list for derived traits, we need to track when we need to insert a comma. We'll use the same technique as the various procedures, which have an "ismore" variable that starts at zero and gets changed to one after something is output. If the variable is non-zero, we need to insert a comma before the next item. This yields the following block of code.
~output derived traits var ismore as number ismore = 0 foreach pick in hero where "component.Derived & !Hide.Trait" sortas explicit if (ismore <> 0) then append ", " endif append @boldon & eachpick.field[name].text & ": " & @boldoff append eachpick.field[trtDisplay].text ismore = 1 nexteach append @newline