Suppose we wanted to define a new race. How would we go about defining something like the Halfling from the d20 SRD?
- +2 Dexterity, -2 Strength.
- Small: As a Small creature, a halfling gains a +1 size bonus to Armor Class, a +1 size bonus on attack rolls, and a +4 size bonus on Hide checks, but she uses smaller weapons than humans use, and her lifting and carrying limits are three-quarters of those of a Medium character.
- Halfling base land speed is 20 feet.
- +2 racial bonus on Climb, Jump, Listen, and Move Silently checks.
- +1 racial bonus on all saving throws.
- +2 morale bonus on saving throws against fear: This bonus stacks with the halfling’s +1 bonus on saving throws in general.
- … (list of traits continues)
The PCGen Documentation > List Files > LST File Classes, Lessons 3 through 6, Fundamentals of Race Building, walks through the construction of example races. These lessons are enough to learn the basics.
My concern with the LST File Classes is that they were written many years ago, and don’t always show the “modern” way of doing things. e.g. the use of the
SAB tag where the
ASPECT tag would be preferred for new code. I would prefer to learn the language by dissecting the Pathfinder and DnD 3.5 data files, which are the most up-to-date available in the PCGen project.
In this article, I will dissect the Pathfinder data files
cr_abilities_race.lst files to determine how the
Dwarf race is defined, and trace back the code responsible for implementing the
Dwarf ~ Defensive Training ability (one of a half-dozen abilities making up the
In dissecting these files, I have discovered that the Pathfinder and DnD 3.5e data files are made quite complicated by the need to support sub-races (i.e. Hill Dwarf, Aquatic Dwarf, Desert Dwarf…).
Home-brew races don’t need this complexity, and are therefore much easier to implement. I will write a separate article walking through the coding of a home-brew race. Those who are only interested in simple home-brew code may await that article.
For the time being, let us press on with the dissection of the PCGen data files.
Files where races are defined
In PCGen, the races for the Pathfinder system are defined in the following files, all found in
cr_races.lst- basic statistical information for each race, such as:
SIZE:- small, medium, large, huge
cr_abilities_race.lst- a collection of
ABILITYrecords which define each race’s traits and abilities, such as:
- stat bonuses (+2 CON, -2 CHA)
- skill bonuses (+2 to Open Lock)
- saving throw bonuses (+1 Luck bonus to all saves)
cr_abilitycategories.lst- a small file - defines the categories of abilities ,such as
Dwarf Racial Trait,
Fighter Bonus Feat, etc. which are used when coding
cr_abilities_race.lst. The most obvious use of this file is to group abilities for the player to choose amongst, i.e. the category
Fighter Bonus Featwhich contains all the feats that Fighter-class characters are allowed to take at 1st, 2nd, 4th, etc. levels.
Note the file-names all start with
cr standing for the [Pathfinder] core rulebook.
The 3.5ed files are similarly named
rsrd for the Revised System Reference Document - look in
[x]_races.lst etc. are standardised according to the Data LST standards.
Basic race information:
The definition of the Dwarf race in
cr_races.lst is fairly straightforward.
This is mainly basic information like the creature’s size (M, medium), the race’s type (Humanoid) and subtype (Dwarf), and so on.
Before moving on, note two features here:
a_base_pcis alphabetically first in the list of all race names, so it appears at the top of the list in the PCGen GUI. This means that you don’t have to wade through the hundreds of monster races (ape, bear, cheetah, deep one, earth elemental…) to get to the PC races (human, dwarf, elf, etc.)
STARTFEATS:1grants the race one bonus feat at first level. All PC races get a feat at 1st, but monster races don’t, so we have to be explicit about whether we want a given race to get a free feat at 1st, or not.
The real meat of the race definition is called out by the tag
ABILITY:Internal|AUTOMATIC|Race Traits ~ Dwarf. This calls into the record called
Race Traits ~ Dwarf in
Race ability definitions:
This is an ability
.lst file. Each record (line) in this file defines an ability.
If we search for
Race Traits ~ Dwarf we find the following, apparently empty, ability record:
The record has a
CATEGORY tag, but nothing else.
What’s going on here?
A bit more searching shows more lines matching
Race Traits ~ Dwarf:
CATEGORY=Internal|Race Traits ~ Dwarf.MOD are modifying the “empty” record
Race Traits ~ Dwarf. This is a trick for breaking up a long record into multiple lines, which is explained in my earlier post Exploring the PCGen file format – Part 1: Really long lines.
.MOD lines have modified the existing
Race Traits ~ Dwarf record, the end result is:
Race Traits ~ Dwarf ability record now contains ten
ABILITY tags within it. That is, the
Race Traits ~ Dwarf ability is coded to grant ten more sub-abilities. These include
Dwarf ~ Defensive Training,
Dwarf ~ Greed,
Dwarf ~ Hatred, and so on.
Actual ability definitions
We have seen that the
Race Traits ~ Dwarf ability is just an in-direct handle to a number of sub-abilities, like:
The actual mechanical effects of the
Dwarf ~ Defensive Training ability are defined in a separate record, further down in the file, as:
From this, we conclude that the
cr_abilities_race.lst file works like this:
cr_abilities_race.lst, a blank definition is written for the
Race Traits ~ Dwarfability.
The details of the Dwarf racial abilities are defined in individual records, one per sub-ability, like
Dwarf ~ Defensive Training,
Dwarf ~ Greed,
Dwarf ~ Hatred, and so on.
CATEGORY=Internal|Race Traits ~ Dwarf.MOD...syntax is used to add pointers from the
Race Traits ~ Dwarfability to each of the sub-abilities,
Dwarf ~ Defensive Training,
Dwarf ~ Greed, and so on.
Dwarfrace as having just the one ability,
Race Traits ~ Dwarf. Since this points to all the sub-abilities, granting
Race Traits ~ Dwarfautomatically grants all the sub-abilities, without needing to refer to each one individually in
One thing remains un-explained.
If it was only required to use the
Race Traits ~ Dwarf ability as a handle onto the ten sub-abilities, then this would suffice:
However the actual code looks like this:
PREABILITY is used to implement conditional logic. If the
PREABILITY condition evaluates ‘True’, the tag is applied. If the
PREABILITY condition evaluates ‘False’, the tag is ignored.
! to the front inverts the logic.
!PREABILITY will cause the tag to be applied if the condition evaluates ‘False’ and vice-versa.
Having recalled how
!PREABILITY operate, we ask: Why would we ever want to remove any of the Dwarf racial abilities? Surely all dwarves have
Dwarf ~ Defensive Training? (+4 Dodge AC vs. Giant).
The answer is: No, only the default kind of Dwarf (the ‘Hill Dwarf’) has +4 Dodge AC vs. Giants. There are multiple subtypes of dwarf, and these subtypes have different bonuses.
Searching through the entire Pathfinder data file directory for
Ouatclass (a type of Monk from the Inner Sea Combat book) is made up of dwarves who have rejected the traditional Dwarf training vs. Giants, so they don’t have +4 AC vs anything. (
Saltbeardfrom the Advanced Races Guide is a sub-race of dwarves who live on the high seas. There are no giants in the ocean, so a Saltbeard loses the +4 AC vs. giants, but gains +2 AC vs. any creature of the Water or Aquatic subtypes. (
This indicates that all the
!PREABILITY logic is there to support racial sub-types.
The logic looks like:
which is read as NOT having an ability of TYPE = DwarfDefensiveTraining.
If the default Dwarf is used, then there will be no pre-existing abilities of the type
DwarfDefensiveTraining, so the logic will evaluate to ‘True’. The
ABILITY:Dwarf Racial Trait|AUTOMATIC|Dwarf ~ Defensive Training tag will be applied, granting the
Dwarf ~ Defensive Training ability.
If a racial sub-type defines an ability of the type
DwarfDefensiveTraining (in the ability category
Special Ability), then the
!PREABILITY logic will evaluate to ‘False’. The
ABILITY:Dwarf Racial Trait|AUTOMATIC|Dwarf ~ Defensive Training will be ignored.
Racial abilities are implemented by adding references from the race definition in
_races.lst to one (or more) abilities in
A smart way of doing this is to make one reference from
_races.lst to a ‘master’ ability in
Race Traits ~ Dwarf, and then add further references from the ‘master’ ability to multiple sub-abilities.
Advanced !PREABILITY logic for sub-races
The Pathfinder and DnD 3.5 data files contain some advanced logic in the racial ability definitions:
The logic is in there to support sub-races, i.e. Dwarf → Saltbeard, which requires the ‘default’ racial abilities to be disabled in favour of the sub-race’s abilities.
The happy news is that most home-brewers won’t be interested in sub-races, and so won’t need to implement anything with this level of complexity.
The simpler code:
will be quite sufficient for most home-brew.
From Andrew Maitland (2015-07-06) we have the below comment, and another more detailed forum post.
Only two “sub races”? I wouldn’t have coded up that crazy advanced logic if the issue was simply two subraces (which tend to be ignored in pathfinder).
That code is invoked quite a bit, thanks to the Advanced Player’s Guide giving new rules to swap Racial Traits – that is when I coded up those up (took three distinctive iterations before I finally got the correct method – first pass involved kits, it wasn’t pretty… numerous bugs for having elf traits as a halfling). Each race trait beyond the originals has a COST:0 plus an exclusion “PC cannot possess TYPE=x, or in your example “DwarfDefensiveTraining” – which the original trait does not include to avoid circular logic, the exclusion is to avoid taking two traits that affect the same racial trait. For 3.5e the Unearthed Arcana book introduced OGL subrace options, which is why the logic exists in the RSRD. Otherwise the RSRD code support would have only been to support homebrew options beyond our official releases.
You are correct about empty records. Much easier to debug issues over multiple lines. You should have seen the race files before I made that change… complicated doesn’t begin to describe it. If you want a trip down memory lane, I can get you a copy of them.
For the SORTKEY, that is overkill to be honest. TYPE:PC places it at the top of the race list already. But most people wouldn’t know that TYPE:PC actually does that, so shrug I included it. Class sorting has the same logic – “Base” = top, “Prestige” next and then everything else in alpha order after.
One correction I see – STARTFEATS is absolutely required IF the race/class ever acquires feats. Non-Intelligent beings, such as Oozes, mindless undead and mindless constructs, never gain skills or feats, hence they will lack that entry.
As to ye olde documentation. Yes, those are over ten years old easily. The problem with keeping those updated is lack of volunteers. Do you want new books, or updated documentation? Most people ask for books.
I would say you’d make a great documentation monkey. We have openings
Cheers, Andrew Maitland