Creature Refinement (Savage)
We've now got the ability to define and customize creatures in place. However, there are still a fair number of tasks we need to complete before creatures are fully handled. The sections below address these remaining issues.
Between all the races and creatures, we've got a long list of special abilities. These abilities seem to break down into five different classifications.
- Common racial abilities that can be shared by multiple races (e.g. Tough, Agile)
- Race-specific abilities that are unique to a single race (e.g. Avion Flight, Saurian Senses)
- Common creature abilities that can be shared by multiple creature (e.g. Size, Infravision)
- Creature-specific abilities that are unique to a single creature (e.g. Rollover, Bear Hug)
- Generic abilities that are shared by both races and creatures (e.g. Natural Weapons, Natural Armor)
To keep everything organized, we'll partition these abilities across three separate data files.
- One file will contain all the races and race-specific abilities ("thing_races.dat")
- Another file will contain all the creatures and creature-specific abilities ("thing_creatures.dat")
- The third file will contain only re-usable special abilities for both races and/or creatures ("thing_abilities.dat")
We need a way to readily identify common creature abilities as such. For this, we'll define a new "User.Creature" tag, which we can then assign to all abilities that can be used freely by any creature. These abilities will consist of the two generic abilities we created for natural weapons and armor, as well as all of the common creature abilities spelled out in the rulebook.
We can now focus on getting all of the common creature abilities properly defined. The core rulebook outlines a couple dozen of these abilities. We should get them all into place before we start defining lots of creatures that depend on them.
We'll pick a few of these abilities to implement as examples here. We'll start with the "Size" ability, which specifies a non-standard size for the creature. The ability requires the specification of a size bonus (or penalty). We'll utilize the customizable ability mechanism and define the size bonus via the "abilValue" field. This bonus is both applied to the "Toughness" trait as an adjustment and incorporated into the name for display. This results in the ability definition below, which is followed by an example of its use.
<thing id="abSize" name="Size" compset="RaceAbil" isunique="yes" description="Description goes here"> <tag group="User" tag="Creature"/> <!-- Apply the size bonus to the Toughness trait --> <eval index="1" phase="PreTraits" priority="5000"> <before name="Calc trtFinal"/><![CDATA[ perform #traitadjust[trTough,+,field[abilValue].value,"Size"] field[livename].text = field[name].text & " " & signed(field[abilValue].value) ]]></eval> </thing>
<bootstrap thing="abSize"> <assignval field="abilValue" value="2"/> </bootstrap>
Our next example is the "Immunity" ability. This ability requires that specification of the nature of the immunity. The customizable ability mechanism can again be used, only this time we'll specify the specific immunity via the "abilText" field. The immunity can then be integrated into the name for the display. This yields the ability definition below, followed by an example of its use.
<thing id="abImmunity" name="Immunity" compset="RaceAbil" description="Description goes here"> <tag group="User" tag="Creature"/> <!-- Append the immunity to the name --> <eval index="1" phase="Traits" priority="10000"><![CDATA[ field[livename].text &= " " & field[abilText].text ]]></eval> </thing>
<bootstrap thing="abImmunity"> <assignval field="abilText" value="Fire"/> </bootstrap>
Some abilities automatically confer other abilities. For example, the "Elemental" ability confers the "Fearless" ability. This is easily achieved by simply bootstrapping the conferred ability, as shown in the definition below.
<thing id="abElement" name="Elemental" compset="RaceAbil" isunique="yes" description="Description goes here"> <tag group="User" tag="Creature"/> <bootstrap thing="abFearless"/> </thing>
You should now be able to implement all the various abilities utilized in the rulebook. Alternately, you can simply look at the completed Savage Worlds data files provided with HL.
Defining Complete Creatures
- walk-through of three different creatures
New Abilities Tab
- allow user to specify facets of dynamic abilities that are needed (value/text)
- User.NeedText and User.NeedValue tags
Cleanup the Interface
Due to our changes in how creatures are handled, there are a number of facets of the interface that need some work. We'll start with the issues on the "Basics" tab.
The first thing we can't miss on the "Basics" tab is the display of XP information and the list of creation resources. Creatures don't track any XP and they don't observe any special creation rules regarding point allocations. Consequently, both of these sections of information and any associated separators need to be hidden for creatures. This can be handled easily by adding the block of code below to the Position script for the "basics" layout.
~if we're creating a creature, don't show XP or creation details if (hero.tagis[Hero.Creature] <> 0) then portal[baRank].visible = 0 portal[baCreation].visible = 0 portal[separator1].visible = 0 portal[separator2].visible = 0 endif
There is also the matter of the header above the table of attributes. The header shows the number of remaining points that can be spent, which is meaningless for creatures. We need to revise the header to simply show the text "Attributes" when the user is creating a creature. This is accomplished by changing the code for the HeaderTitle script to that shown below.
@text = "Attributes" if (hero.tagis[Hero.Creature] = 0) then @text &= " - " & hero.child[resAttrib].field[resSummary].text endif
We can now proceed to the "Skills" tab, where we'll find a few additional issues to address. For example, the header above the list of skills suffers the same problem that the one above the attributes did on the previous tab. The solution is the same, replacing the HeaderTitle script with the new code below.
@text = "Skills" if (hero.tagis[Hero.Creature] = 0) then @text &= " - " & hero.child[resSkill].field[resSummary].text endif
If we click on the "add" item at the bottom of the table of skills, we'll see a similar problem again. The title shown at the top of the selection form shows same extra information. We need to revise the Titlebar script in the same way, as shown below.
@text = "Add a Skill" if (hero.tagis[Hero.Creature] = 0) then @text &= " - " & hero.child[resSkill].field[resSummary].text endif
The final issue on the "Skills" tab is that the "add" item at the bottom of the table is using the highlight information for a normal character. This information is controlled via the "resAddItem" field of the resource. We already disabled the special formatting for NPCs, and we need to change that logic to apply to any non-PC character (i.e. including creatures). This is done by changing the one line of code in the Finalize script to the following.
if (tagis[Helper.NPCImpact] + !hero.tagis[Hero.PC] >= 2) then
The first thing we'll notice regarding the validation report is that various resources will sometimes report that they have been overspent. These are the same resources that we disabled for NPC creation, and they must also be disabled for creatures. This can be solved by modifying the Eval Rule on the "Resource" component to consider the rule as valid for any non-PC. The new line of code required is shown below.
if (tagis[Helper.NPCImpact] + !hero.tagis[Hero.PC] >= 2) then
If the user elects to construct a creature, the specific creature type needs to be specified. We need a validation rule to verify this is done. We already a thing defined with a validation rule to verify a race is selected. We can easily clone that thing and adapt it for use with the creature type chooser, resulting in the thing shown below.
<thing id="valCreatur" name="Creature Type" compset="Simple"> <tag group="Helper" tag="Bootstrap"/> <evalrule index="1" phase="Validate" priority="8000" message="Must be selected"><![CDATA[ ~if we have a creature type selected, we're good if (hero.tagis[Creature.?] <> 0) then @valid = 1 done endif ]]></evalrule> </thing>
Unfortunately, we have a small problem still. If we create a normal character, we always get a validation error about the creature type. If we create a creature, we always get a validation error about the race. Each of these validation rules needs to be applied only when the appropriate character type is in use. One solution would be to utilize an appropriate ContainerReq on each of the validation things. An easier solution is to test whether we have a creature within the Eval Rule script. The revised script code for the "valRace" and "valCreatur" things is shown below.
~if we have a race selected or we are a creature, we're good if (hero.tagis[Race.?] + hero.tagis[Hero.Creature] <> 0) then @valid = 1 done endif
~if we have a creature type selected or we're not a creature, we're good if (hero.tagis[Creature.?] + !hero.tagis[Hero.Creature] <> 0) then @valid = 1 done endif
- show "creature type" instead of Race within character sheet
- same for statblock output
- define a "custom" creature that allows the author to create whatever he wants
- define a "custom" ability that allows the author to annotate the behaviors without actually creating a new ability in the Editor
- just like custom containers