Skip to content

Girls.girlsx schema

Pack-author grammar for .girlsx (named girls) and .rgirlsx (random templates). One shape, one mental model — only the role-specific attributes differ. Identity stays on <Girl> as attributes; stats, skills, traits, gold, and inventory live as typed child elements.

Every legacy shape ever written for these files keeps loading silently — see Accepted variants at the bottom. New packs should use the canonical shape below.

<?xml version="1.0" encoding="UTF-8"?>
<Girl Name="Azula" Desc="Princess of the Fire Nation." Status="Slave">
<Stat name="Age" value="22" />
<Stat name="Beauty" value="65" />
<Stat name="Charisma" value="85" />
<Skill name="Service" value="30" />
<Trait name="Pretty" />
<Trait name="Royal Blood" />
<Gold value="500" />
<Inventory>
<Item Name="Lucky Charm" />
</Inventory>
</Girl>

That’s enough for the game to load her. Everything else has defaults.

<?xml version="1.0" encoding="UTF-8"?>
<Girl Name="Cute Girl">
<Stat name="Age" min="18" max="24" />
<Stat name="Beauty" min="40" max="70" />
<Stat name="Charisma" value="60" /> <!-- sugar: min = max = 60 -->
<Stat name="Constitution" min="50" /> <!-- partial: only min set -->
<Skill name="Service" min="10" max="30" />
<Trait name="Pretty" percent="40" />
<Trait name="Shy" /> <!-- no percent: uses the trait's RandomChance -->
<Gold min="50" max="150" />
</Girl>

Random templates use min= / max= (or value= as min=max sugar) on stats, skills, and gold; named girls use value=. Trait percent= is only honoured for random templates — named girls always get the trait. On a random template, a trait listed without percent= falls back to the trait’s own RandomChance (from its .traitsx definition) rather than never rolling.

Attribute Required Purpose
Name Yes Display name. For named girls (and template-policy randoms), must match the Characters/<Name>/ folder exactly.
Realname No True name if Name is an alias.
Desc No Short description shown in girl details.
Status No Where she turns up: Slave (slave market) or Catacombs (found exploring). Absent or anything else: met in town.
Virgin No True / False — sets virgin status and overrides the age/skill-derived default (skipping that roll). Omit to derive from age + skill spread. Preferred over the legacy Virgin trait.
UseAntiPreg No True if she uses contraception by default.
Comments No Free-text notes; not shown in-game.

Status is the entry channel, not a rarity. The game keeps one pool of named characters you have not met yet and draws from it by this flag: Slave characters are offered by the slave market caravan, Catacombs characters are found when workers or gangs explore the Catacombs (and arrive as captives), and everyone else is met walking the town or brought in by a gang kidnapping. A character is in exactly one channel.

Age is a stat, not an identity attribute. Use <Stat name="Age" value="22"/>. (The legacy <Girl Age="22"> form still works — see Accepted variants.)

Attribute Named girls (.girlsx) Random templates (.rgirlsx)
name Required. Stat name (see list). Required. Stat name.
value Required. Integer value. Optional sugar — sets min = max = value.
min Ignored. Optional. Lower bound. If only min is set, max stays default.
max Ignored. Optional. Upper bound. Partial range tolerated.

Recognised stat names (22 total):

Charisma, Happiness, Libido, Constitution, Intelligence, Confidence,
Mana, Agility, Fame, Level, AskPrice, House, Exp, Age, Obedience,
Spirit, Beauty, Tiredness, Health, PCFear, PCLove, PCHate

Lookup is case-insensitive. An unknown stat name is silently skipped.

Same attribute shape as <Stat> (name + value for named, name + min/max + value-sugar for random). Skills default to 0 or a small starting value; only list the ones you want to set.

Recognised skill names (22 total):

Anal, Magic, BDSM, NormalSex, Beastiality, Group, Lesbian,
Service, Strip, Combat, Performance, Farming, AnimalHandling, Crafting,
Herbalism, Brewing, Cooking, Medicine, OralSex, TittySex, Handjob, Footjob

Eleven of these arrive with game 1.21, which is not released yet, and they are not all in the same state. OralSex, TittySex, Handjob and Footjob are already weighed by the Escort job, so setting them does change a shift. The seven occupational skills (Farming, AnimalHandling, Crafting, Herbalism, Brewing, Cooking, Medicine) are accepted everywhere but no job reads them yet, so setting one changes nothing in a shift until the Farm jobs are wired to them. A random template that does not give the eleven newer skills a range sets them to 0, while the original eleven keep their usual unranged default.

Attribute Named girls Random templates
name Required. Required.
percent Ignored — always applied. Optional. Chance (0-100) the trait is rolled. Omit to fall back to the trait’s RandomChance.

Trait names match the Name attribute in .traitsx definitions exactly (case-sensitive — unlike stat / skill names). The core trait list is in resources/data/traits/. Pack-defined traits work too.

The legacy <Trait name="Virgin"/> is still accepted for back-compat, but it is migrated to the Virgin flag and dropped from the trait list — virginity is status data, not a descriptive trait. Use Virgin="true" on <Girl> instead (the validator warns about the trait form).

Attribute Named girls Random templates
value Required. Starting gold. Optional sugar — sets min = max = value.
min Ignored. Optional. Lower bound.
max Ignored. Optional. Upper bound.

Items she starts with. Item names match the Name attribute of an item in any loaded .itemsx file (including resources/data/Items.itemsx).

<Inventory>
<Item Name="Simple Dress" />
<Item Name="Lucky Charm" />
</Inventory>

Each item is added to the girl’s inventory and equipped automatically when she loads. Items that cannot be worn — Food and Makeup — are added but left unequipped. Unknown item names are skipped, with a note in the game log. The inventory holds 40 slots; items past that are dropped.

The <Inventory> wrapper is optional: bare <Item> elements placed directly inside <Girl> are read the same way. Random templates don’t carry inventory.

The loader silently accepts every legacy shape that ever worked. New packs should use the canonical shape above; existing packs do not need to migrate.

Optional wrappers around typed children. <Stats>, <Skills>, <Traits>, <Inventory> are equivalent to writing the children directly under <Girl>:

<Stats>
<Stat name="Beauty" value="65" />
</Stats>
<!-- same as -->
<Stat name="Beauty" value="65" />

This is the shape some older kit copies documented. Both work.

Capital attribute names. <Stat Name="Beauty" Value="65"/> (capital N and V) parses the same as the canonical lowercase form. Same for Min=, Max=, Percent=. The canonical docs and snippet templates use lowercase; either works.

Legacy flat stat attributes (.girlsx). Pre-rethink named girls put every stat as a <Girl> attribute:

<Girl Name="LegacyAlice" Beauty="65" Charisma="80" Age="22" />

Still works. Stats also set by a <Stat> child win; flat attributes only fill stats the structured walk didn’t touch.

Legacy bare-child <Stat> (.rgirlsx). Pre-rethink random templates wrote ranges as direct children with capital attributes:

<Stat Name="Beauty" Min="40" Max="70" />

Still works. Equivalent to the canonical lowercase form.

For authors who want to convert legacy files to the canonical shape:

Terminal window
python3 tools/pack-authoring-kit/tools/migrate-girlsx.py resources/packages/MyPack/

Dry-run by default — prints what would change without touching files. Add --write to apply the rewrite (with .bak sidecars; --no-backup skips them). The tool refuses to rewrite files containing save-format <Stats> content (a safety check; pack authoring files should not have that shape).

VS Code authors get the same as palette tasks: Tasks: Run Task → Migrate girlsx (dry-run) or Migrate girlsx (write).

The images for a girl go in Characters/<Name>/. The folder name must match the Name attribute of the <Girl> exactly (case-sensitive). If the folder is missing or empty, the Content Manager flags the girl as “Missing Images” and the game falls back to placeholder art.

By default a random template’s Name is just a label; the engine assigns each spawned girl a fresh random name. Two attributes let a pack control this — set them on the <Girls> root of a .rgirlsx file (per-file) or in package.xml (pack-wide default):

Attribute Value Effect
RandomGirlNaming engine (default) Engine picks a random name from its built-in pool.
RandomGirlNaming template Each spawned girl keeps the template’s Name.
RandomGirlNaming pool Draw names from the file named by NamePool.
NamePool a filename Newline-delimited names file (beside the .rgirlsx or package). Blank lines and # comment lines are skipped.

An invalid RandomGirlNaming value is ignored with a log warning and the engine default is used. Because the spawned name can differ from the template’s Name under engine / pool, those spawned girls draw images from the template’s folder, not from their assigned name.

A .girlsx or .rgirlsx file can hold any number of <Girl> blocks under a <Girls> root. Split them across files however you like: one per girl, one per theme, or all in one. The loader doesn’t care.

  • tools/pack-authoring-kit/snippets/Girls.girlsx: paste-and-edit named-girl skeleton.
  • tools/pack-authoring-kit/snippets/RandomGirls.rgirlsx: random-template skeleton.
  • examples/packs/Sample_Full/Girls.girlsx (game 1.21 on; resources/packages/Sample_Full/ before): worked example with every block.