Implementing the Character Sheet (Savage)
Context: HL Kit … Authoring Examples … Savage Worlds Walk-Through
Overview
Our design is in place, so it's time to start actually implementing our new character sheet. Since we're adapting the sheet provided by the Skeleton files, we'll find what we need in the file "sheet_standard1.dat".
Before We Get Started
We're going to be using this sheet both as our starting point for our changes and as a source of examples for how to do various tasks. As such, we should make a copy of this file somewhere (not within our data file folder). We can keep the copy around for use as a reference or guide on how to do things. We can then freely change the file in our game system folder to morph it into our new character sheet for Savage Worlds.
During the development of our character sheet, we're going to be taking a look at how things behave dozens of times. There is generally no need to print anything during our testing. Instead, you can use the Print Preview mechanism within HL, which can be accessed quickly via the keystroke sequence <Alt+F><V>. After doing a quick-reload, you'll find yourself following with these keystrokes on a regular basis.
We also want to see a meaningful character being displayed when testing our character sheet. If you haven't done so already, create a character for testing. It's probably best to have the character be invalid and have more capabilities than a starting character normally should. This way, you really see how all the different facets of the character sheet will work. For example, give the character an arcane background and powers to see how that stuff works. Give him an assortment of skills, hindrances, edges, weapons, armor, and gears. That way, when you're testing things, you'll get a good sense of how everything looks by just using the existing character. The entire process goes much more quickly this way.
Character Basics
The provided character sheet that we using as our template places the basic information in the top left corner. We'll start there for simplicity and then develop our character sheet in a systematic fashion by proceeding down the left column and then down the right column.
The character name is placed within the header bar for the section, so that's a nice prominent place that works well for us. Beneath that, the Skeleton files have three visible sections of information, with each being less prominent than the one above. The first shows the player name in a large bold font. The official character sheets don't include this and it takes up valuable space when we're trying to keep things compact, so we'll just omit that from our sheet. The second section shows the character points in bold, which don't apply to Savage Worlds, and the third shows basic character details. Having two sections ought to work nicely for us, with one in bold and one not, but we need to re-apportion the information and add some details.
In the first section, we should show the two most important facets of the character that will be included in the character basics. Those are the character's race and rank (with XP). If we do this, that leaves the physical characteristics for display beneath. We could include the hair, eyes, and skin tone in this section, but that would generally require a second line of text on the character sheet and we're trying to keep everything compact. So we'll leave that information out and switch to centering the remaining details on the line.
All of this information is managed via the "oHeroInfo" portal, so we'll adapt it for our purposes. The text is simply synthesized by a single script. Once we finish revising it, the result should look similar to the new script below.
~start with the character's race var temp as string temp = hero.firstchild["component.Race"].field[name].text if (empty(temp) <> 0) then temp = "Unknown" endif @text &= "{size 36}Race: " & temp ~append the rank and XP, showing any unspent advances var rankvalue as number var ranktext as string rankvalue = herofield[acRank].value call RankName @text &= "; " & ranktext & " (" @text &= hero.child[resXP].field[resMax].text & " XP)" if (#resleft[resAdvance] > 0) then @text &= "; " & #resleft[resAdvance] & " Advance(s)" endif ~sart a new line and turn off bold @text &= "{br}{/b}" ~append the gender, age, height, and weight if (hero.child[mscPerson].field[perGender].value = 0) then @text &= "Male" else @text &= "Female" endif @text &= "; Age: " & hero.child[mscPerson].field[perAge].text @text &= "; Height: " & hero.child[mscPerson].field[perHeight].text @text &= "; Weight: " & hero.child[mscPerson].field[perWeight].text
Attributes
Moving downward, the next section we want to include is the attributes, and they conveniently happen to be next in the provided files. However, the way attributes are handled in the Skeleton files is a bit different from how we're going to be handling them. In the Skeleton files, attributes have a header across the top and a bunch of pieces for display. For our purposes, all we need is a basic title at the top and relatively simple display elements for each attribute. So we've got a bit of work to do in revamping how attributes work.
The first thing we need to do is revise the attributes table portal appropriately, which has the id "oAttribute". We'll eliminate the use of a header template and designate that we'll be using a two-column table. We then need to add our simple header by adding a suitable "headertitle" element. Lastly, we need to accommodate the hidden attribute for super powers appropriately, which requires we define a List tag expression that omits hidden attributes. This results in a revised portal that looks similar to the one below.
<portal id="oAttribute" style="outNormal"> <output_table component="Attribute" showtemplate="oAttrPick" showsortset="explicit" columns="2"> <list>!Hide.Attribute</list> <headertitle><![CDATA[ @text = "Attributes" ]]></headertitle> </output_table> </portal>
We next shift our focus to the "oAttrPick" template used for displaying each attribute. We'll start by changing the vertical margin to zero, and we can increase it later if want. The next step is to eliminate all of the existing portals that are used as the header, since we won't be using them. We can also eliminate the Header script that is no longer needed. This leaves us with six portals that we need to deal with. We obviously want to keep the name portal, and we'll also need portals for both the final die-type