Obligatory GitHub Link.

Over the holiday and weekend, I plowed through some massive rewrites/refactors of my character generator, applying lessons learned from working on Blades in the Dark. One of the bigger changes was consolidating several objects through the use of static inner classes.

When I first wrote the enums for Weapons, Armor, Tools, Classes, Spells (and numerous other things), I didn’t know how to use them to create the objects I wanted them to represent. Instead, I wrote external objects that used the enums for classification. Then I learned what making an inner class “static” actually does.

Now instead of having Weapon & GameWeapon, Armor & GameArmor, Spell & Spellcasting, Tool & GameTool (and so on) objects, I have a couple of static inner classes within Weapon, Armor, and other enumerated objects. I even used the same essential architecture… just, you know… better.

For items which can have both magical and mundane versions, I have an inner “prototype” class, and a separate “instance” class that handles modifications to the essential object. Since they’re contained within the same class, I don’t have long dot-operators referencing their names. It’s nice.

I did a whole lot of other stuff that I don’t really have time to get into, but since sample output speaks louder than me… just talking about it, here’s some sample output (sample characters names from Xanathar’s Guide to Everything tables):

HENRY the level 1 HUMAN WIZARD (DIVINER)
AC 10 || 5 hp || SHOCKING_GRASP +3 1d8 (4) || CR 1/4 (50)
[14, 10, 14, 13, 10, 8]
[DAGGER]
[ACID_SPLASH, FEATHER_FALL, FIND_FAMILIAR, GREASE, MAGE_ARMOR, MAGE_HAND, RAY_OF_SICKNESS, SHOCKING_GRASP, UNSEEN_SERVANT]

MALQUIS the level 1 DARK_ELF BARD (LORE_COLLEGE)
AC 8 || 8 hp || VICIOUS_MOCKERY +5 1d4 (2) || CR 1/4 (50)
[12, 5, 13, 9, 13, 17]
[LIGHT_HAMMER, DAGGER]
[LEATHER_ARMOR]
[INSPIRATION_D6]
[ANIMAL_FRIENDSHIP, CURE_WOUNDS, DANCING_LIGHTS, THUNDERWAVE, UNSEEN_SERVANT, VICIOUS_MOCKERY]

HABOR the level 1 TIEFLING PALADIN (VENGEANCE_OATH)
AC 18 || 4 hp || JAVELIN +2 1d6+0 (3) || CR 1 (200)
[11, 9, 11, 10, 9, 11]
[GREATAXE, SHIELD, JAVELIN]
[CHAIN_MAIL]

CHEM the level 1 TIEFLING BARD (VALOR_COLLEGE)
AC 8 || 1 hp || Cantrip +5 0 || CR 0 (10)
[10, 5, 8, 13, 13, 17]
[LIGHT_HAMMER, DAGGER]
[LEATHER_ARMOR]
[INSPIRATION_D6]
[CHARM_PERSON, COMPREHEND_LANGUAGES, FRIENDS, LIGHT, LONGSTRIDER, SILENT_IMAGE]

SIMON the level 1 HUMAN RANGER (HUNTER)
AC 16 || 2 hp || LIGHT_HAMMER +1 1d4-1 (1) || CR 1/2 (100)
[ 8, 15, 7, 9, 8, 11]
[LIGHT_HAMMER, GREATCLUB, LONGBOW, ARROW (20)]
[SCALE_MAIL]

GERALD the level 1 HUMAN FIGHTER (BATTLE_MASTER)
AC 16 || 1 hp || SLING -2 1d4-4 || CR 1/2 (100)
[14, 3, 9, 6, 11, 7]
[SLING, BULLET (20), LIGHT_CROSSBOW, BOLT (20)]
[CHAIN_MAIL]

JANE the level 1 HUMAN SORCERER (CHAOS_ORIGIN)
AC 11 || 6 hp || Cantrip +3 0 || CR 1/4 (50)
[ 8, 12, 13, 13, 15, 12]
[LIGHT_CROSSBOW, BOLT (20), DAGGER, DAGGER]
[BLADE_WARD, DANCING_LIGHTS, FALSE_LIFE, LIGHT, RAY_OF_SICKNESS, TRUE_STRIKE]

GIMBLE the level 1 GNOME SORCERER (CHAOS_ORIGIN)
AC 8 || 2 hp || Cantrip +3 0 || CR 0 (10)
[12, 7, 9, 10, 10, 13]
[LIGHT_CROSSBOW, BOLT (20), DAGGER, DAGGER]
[BLADE_WARD, DISGUISE_SELF, EXPEDITIOUS_RETREAT, FRIENDS, MESSAGE, MINOR_ILLUSION]

EVERARD the level 1 HUMAN PALADIN (DEVOTION_OATH)
AC 16 || 7 hp || BLOWGUN +3 1d1+1 (1) || CR 1/2 (100)
[17, 12, 15, 9, 9, 12]
[BLOWGUN, NEEDLE (50), FLAIL, JAVELIN]
[CHAIN_MAIL]

FARGRIM the level 1 DWARF FIGHTER (BATTLE_MASTER)
AC 16 || 4 hp || HANDAXE +4 1d6+2 (5) || CR 1/2 (100)
[14, 9, 7, 12, 10, 3]
[LIGHT_CROSSBOW, BOLT (20), HANDAXE, HANDAXE]
[CHAIN_MAIL]

HUGOLINA the level 1 HUMAN SORCERER (DRAGON_ORIGIN)
AC 9 || 5 hp || Cantrip +3 0 || CR 0 (10)
[ 7, 8, 9, 8, 15, 13]
[SLING, BULLET (20), DAGGER, DAGGER]
[DANCING_LIGHTS, DISGUISE_SELF, FEATHER_FALL, FRIENDS, MAGE_HAND, PRESTIDIGITATION]

BEIRO the level 1 WOOD_ELF FIGHTER (ELDRITCH_KNIGHT)
AC 16 || 5 hp || SPEAR +3 1d6+1 (4) || CR 1/2 (100)
[13, 8, 10, 10, 10, 12]
[SPEAR, HANDAXE, HANDAXE]
[CHAIN_MAIL]

HUGH the level 1 HUMAN ROGUE (THIEF)
AC 8 || 2 hp || RAPIER -1 1d8-3 (1) || CR 1/8 (25)
[ 9, 5, 8, 7, 6, 6]
[RAPIER, SHORTBOW, ARROW (20), DAGGER, DAGGER]
[LEATHER_ARMOR]

NEDDA the level 1 HALFLING BARBARIAN (BERSERKER)
AC 10 || 6 hp || JAVELIN (4) +3 1d6+1 (4) || CR 1/8 (25)
[12, 8, 13, 10, 11, 10]
[GREATAXE, HANDAXE, HANDAXE, JAVELIN (4)]
[RAGE, RAGE_PER_DAY_2, RAGE_BONUS_2, UNARMORED_DEFENSE_BARBARIAN]

ROLAND the level 1 HUMAN MONK (SHADOW_WAY)
AC 11 || 6 hp || SHORTSWORD +1 1d6-1 (2) || CR 1/8 (25)
[ 6, 8, 6, 14, 15, 7]
[SHORTSWORD, DART (10)]

ANSELM the level 1 HUMAN DRUID (LAND_CIRCLE)
AC 12 || 1 hp || POISON_SPRAY +3 1d12 (6) || CR 1/4 (50)
[12, 12, 7, 12, 12, 6]
[JAVELIN, HANDAXE]
[LEATHER_ARMOR]
[GUIDANCE, POISON_SPRAY]

KORINN the level 1 DRAGONBORN BARD (LORE_COLLEGE)
AC 8 || 4 hp || Cantrip +3 0 || CR 1/4 (50)
[ 4, 5, 7, 14, 13, 12]
[LONGSWORD, DAGGER]
[LEATHER_ARMOR]
[INSPIRATION_D6]
[BLADE_WARD, COMPREHEND_LANGUAGES, CURE_WOUNDS, DISGUISE_SELF, MINOR_ILLUSION, THUNDERWAVE]

AGATHA the level 1 HUMAN ROGUE (ARCANE_TRICKSTER)
AC 11 || 6 hp || SHORTSWORD +2 1d6+0 (3) || CR 1/8 (25)
[ 7, 10, 9, 11, 5, 10]
[SHORTSWORD, SHORTSWORD, DAGGER, DAGGER]
[LEATHER_ARMOR]

GILBERT the level 1 HUMAN CLERIC (NATURE)
AC 18 || 1 hp || Cantrip +4 0 || CR 1 (200)
[ 8, 14, 6, 14, 15, 8]
[MACE, LIGHT_CROSSBOW, BOLT (20), SHIELD]
[SCALE_MAIL]
[LIGHT, MENDING, SPARE_THE_DYING]

CLEREBOLD the level 1 HUMAN ROGUE (ASSASSIN)
AC 14 || 1 hp || SHORTSWORD +5 1d6+3 (6) || CR 1/4 (50)
[ 8, 16, 5, 11, 7, 8]
[SHORTSWORD, SHORTSWORD, DAGGER, DAGGER]
[LEATHER_ARMOR]

NUTAE the level 1 WOOD_ELF PALADIN (DEVOTION_OATH)
AC 18 || 2 hp || FLAIL +2 1d8+0 (4) || CR 2 (450)
[11, 7, 10, 8, 18, 9]
[FLAIL, SHIELD, JAVELIN (5)]
[CHAIN_MAIL]

GERALD the level 1 HUMAN BARD (VALOR_COLLEGE)
AC 9 || 7 hp || VICIOUS_MOCKERY +4 1d4 (2) || CR 1/8 (25)
[17, 7, 12, 12, 10, 14]
[SLING, BULLET (20), DAGGER]
[LEATHER_ARMOR]
[INSPIRATION_D6]
[ANIMAL_FRIENDSHIP, BANE, FAERIE_FIRE, IDENTIFY, MINOR_ILLUSION, VICIOUS_MOCKERY]

WYMAR the level 1 HUMAN FIGHTER (BATTLE_MASTER)
AC 16 || 9 hp || CLUB +3 1d4+1 (3) || CR 1/2 (100)
[13, 11, 13, 9, 10, 8]
[CLUB, LIGHT_CROSSBOW, BOLT (20)]
[CHAIN_MAIL]

ODO the level 1 HUMAN FIGHTER (CHAMPION)
AC 13 || 4 hp || LONGSWORD +3 1d8+1 (5) || CR 1/8 (25)
[12, 11, 6, 12, 6, 10]
[LONGBOW, ARROW (20), LONGSWORD, SHIELD, HANDAXE, HANDAXE]
[LEATHER_ARMOR]

RAYMOND the level 1 HUMAN WARLOCK (FIEND_PACT)
AC 10 || 4 hp || CHILL_TOUCH +3 1d8 (4) || CR 1/8 (25)
[13, 9, 8, 9, 9, 12]
[CLUB, SICKLE, DAGGER, DAGGER]
[LEATHER_ARMOR]
[BLADE_WARD, CHILL_TOUCH, EXPEDITIOUS_RETREAT, HEX]

HELEN the level 1 HUMAN FIGHTER (ELDRITCH_KNIGHT)
AC 9 || 1 hp || LONGBOW +0 1d8-2 (2) || CR 1/8 (25)
[ 9, 6, 10, 18, 9, 9]
[LONGBOW, ARROW (20), GREATCLUB, LIGHT_CROSSBOW, BOLT (20)]
[LEATHER_ARMOR]

IELENIA the level 1 WOOD_ELF WIZARD (ILLUSIONIST)
AC 10 || 8 hp || SHOCKING_GRASP +3 1d8 (4) || CR 1/4 (50)
[13, 11, 14, 12, 9, 11]
[DAGGER]
[BLADE_WARD, COMPREHEND_LANGUAGES, DETECT_MAGIC, FOG_CLOUD, IDENTIFY, MESSAGE, SHOCKING_GRASP, TASHAS_HIDEOUS_LAUGHTER, THUNDERWAVE]

VALNA the level 1 DARK_ELF BARD (LORE_COLLEGE)
AC 10 || 3 hp || Cantrip +3 0 || CR 0 (10)
[12, 9, 13, 3, 13, 12]
[MACE, DAGGER]
[LEATHER_ARMOR]
[INSPIRATION_D6]
[DETECT_MAGIC, IDENTIFY, LONGSTRIDER, MENDING, MESSAGE, SPEAK_WITH_ANIMALS]

ELIZABETH the level 1 HUMAN FIGHTER (CHAMPION)
AC 12 || 4 hp || NET +1 1d4-1 (1) || CR 1/8 (25)
[ 9, 9, 11, 9, 10, 8]
[LONGBOW, ARROW (20), NET, SHIELD, LIGHT_CROSSBOW, BOLT (20)]
[LEATHER_ARMOR]

PERCIVAL the level 1 HUMAN WARLOCK (STAR_PACT)
AC 10 || 3 hp || CHILL_TOUCH +3 1d8 (4) || CR 1/4 (50)
[13, 8, 10, 16, 17, 12]
[SHORTBOW, ARROW (20), CLUB, DAGGER, DAGGER]
[LEATHER_ARMOR]
[ARMS_OF_HADAR, CHILL_TOUCH, ILLUSORY_SCRIPT, PRESTIDIGITATION]

JEZEAN the level 1 DRAGONBORN SORCERER (DRAGON_ORIGIN)
AC 12 || 7 hp || Cantrip +5 0 || CR 1/8 (25)
[11, 15, 12, 11, 8, 16]
[SHORTBOW, ARROW (20), DAGGER, DAGGER]
[FOG_CLOUD, LIGHT, MAGE_HAND, MESSAGE, PRESTIDIGITATION, SHIELD]

PENNIE the level 1 HALFLING SORCERER (DRAGON_ORIGIN)
AC 12 || 5 hp || SHOCKING_GRASP +3 1d8 (4) || CR 1/4 (50)
[12, 14, 16, 11, 14, 12]
[QUARTERSTAFF, DAGGER, DAGGER]
[ACID_SPLASH, BLADE_WARD, MINOR_ILLUSION, SHOCKING_GRASP, SILENT_IMAGE, WITCH_BOLT]

BURANA the level 1 DRAGONBORN DRUID (LAND_CIRCLE)
AC 11 || 10 hp || Cantrip +4 0 || CR 1/8 (25)
[12, 10, 14, 5, 15, 11]
[SICKLE, SCIMITAR]
[LEATHER_ARMOR]
[DRUIDCRAFT, GUIDANCE]

THIALA the level 1 DARK_ELF RANGER (BEAST_MASTER)
AC 16 || 12 hp || SHORTSWORD +4 1d6+2 (5) || CR 1 (200)
[10, 14, 15, 6, 9, 8]
[SHORTSWORD, SHORTSWORD, LONGBOW, ARROW (20)]
[SCALE_MAIL]

TIMM the level 1 HUMAN MONK (SHADOW_WAY)
AC 12 || 4 hp || SHORTSWORD +3 1d6+1 (4) || CR 1/8 (25)
[10, 13, 5, 13, 13, 8]
[SHORTSWORD, DART (10)]

ELEANOR the level 1 HUMAN BARD (LORE_COLLEGE)
AC 9 || 2 hp || Cantrip +3 0 || CR 1/4 (50)
[ 6, 7, 10, 8, 8, 13]
[RAPIER, DAGGER]
[LEATHER_ARMOR]
[INSPIRATION_D6]
[DANCING_LIGHTS, DISSONANT_WHISPERS, HEALING_WORD, MAGE_HAND, SPEAK_WITH_ANIMALS, UNSEEN_SERVANT]

JOCELYN the level 1 HALF_ELF WARLOCK (STAR_PACT)
AC 12 || 5 hp || CHILL_TOUCH +5 1d8 (4) || CR 1/8 (25)
[10, 12, 7, 14, 9, 17]
[DAGGER, JAVELIN, DAGGER, DAGGER]
[LEATHER_ARMOR]
[BLADE_WARD, CHILL_TOUCH, COMPREHEND_LANGUAGES, HEX]

TIMM the level 1 HUMAN PALADIN (OATHBREAKER)
AC 18 || 8 hp || NET +2 1d4+0 (2) || CR 1 (200)
[10, 12, 10, 6, 9, 6]
[NET, SHIELD, LIGHT_CROSSBOW, BOLT (20)]
[CHAIN_MAIL]

GIMBLE the level 1 GNOME ROGUE (ASSASSIN)
AC 12 || 4 hp || SHORTSWORD +3 1d6+1 (4) || CR 1/8 (25)
[12, 13, 11, 7, 10, 10]
[SHORTSWORD, SHORTBOW, ARROW (20), DAGGER, DAGGER]
[LEATHER_ARMOR]

AHVAIN the level 1 HIGH_ELF FIGHTER (ELDRITCH_KNIGHT)
AC 13 || 4 hp || BATTLEAXE +2 1d8+0 (4) || CR 1/8 (25)
[11, 10, 11, 11, 10, 11]
[LONGBOW, ARROW (20), BATTLEAXE, SHIELD, HANDAXE, HANDAXE]
[LEATHER_ARMOR]

MAYNILD the level 1 HALF_ELF WARLOCK (FIEND_PACT)
AC 13 || 10 hp || Cantrip +3 0 || CR 1/8 (25)
[13, 15, 14, 6, 10, 13]
[LIGHT_CROSSBOW, BOLT (20), SLING, BULLET (20), DAGGER, DAGGER]
[LEATHER_ARMOR]
[CHARM_PERSON, EXPEDITIOUS_RETREAT, FRIENDS, PRESTIDIGITATION]

AHVAIN the level 1 WOOD_ELF PALADIN (OATHBREAKER)
AC 18 || 6 hp || WARHAMMER +3 1d8+1 (5) || CR 2 (450)
[13, 12, 8, 10, 12, 12]
[WARHAMMER, SHIELD, JAVELIN (5)]
[CHAIN_MAIL]

UTHEMAR the level 1 WOOD_ELF MONK (SHADOW_WAY)
AC 13 || 3 hp || SHORTSWORD +4 1d6+2 (5) || CR 1/8 (25)
[ 9, 15, 7, 9, 12, 10]
[SHORTSWORD, DART (10)]

RHOGAR the level 1 DRAGONBORN BARBARIAN (WOLF_TOTEM)
AC 9 || 4 hp || FLAIL +2 1d8+0 (4) || CR 1/8 (25)
[10, 11, 9, 16, 6, 7]
[FLAIL, HANDAXE, HANDAXE, JAVELIN (4)]
[RAGE, RAGE_PER_DAY_2, RAGE_BONUS_2, UNARMORED_DEFENSE_BARBARIAN]

SARAH the level 1 HUMAN SORCERER (DRAGON_ORIGIN)
AC 9 || 7 hp || CHILL_TOUCH +3 1d8 (4) || CR 1/4 (50)
[11, 9, 17, 16, 7, 12]
[LIGHT_CROSSBOW, BOLT (20), DAGGER, DAGGER]
[CHILL_TOUCH, COMPREHEND_LANGUAGES, DETECT_MAGIC, MINOR_ILLUSION, PRESTIDIGITATION, TRUE_STRIKE]

EMEN the level 1 HALF_ORC ROGUE (THIEF)
AC 11 || 8 hp || SHORTSWORD +2 1d6+0 (3) || CR 1/8 (25)
[12, 11, 13, 9, 8, 11]
[SHORTSWORD, SHORTSWORD, DAGGER, DAGGER]
[LEATHER_ARMOR]

SUSANNAH the level 1 HUMAN FIGHTER (CHAMPION)
AC 11 || 10 hp || SHIELD +1 1d4-1 (1) || CR 1/8 (25)
[ 9, 10, 13, 12, 8, 6]
[LONGBOW, ARROW (20), GREATSWORD, SHIELD, LIGHT_CROSSBOW, BOLT (20)]
[LEATHER_ARMOR]

FREDERICK the level 1 HUMAN FIGHTER (CHAMPION)
AC 18 || 10 hp || HANDAXE +5 1d6+3 (6) || CR 2 (450)
[16, 12, 10, 10, 9, 13]
[GREATSWORD, SHIELD, HANDAXE, HANDAXE]
[CHAIN_MAIL]

MAKARIA the level 1 TIEFLING ROGUE (THIEF)
AC 11 || 8 hp || SHORTSWORD +2 1d6+0 (3) || CR 1/8 (25)
[ 9, 11, 11, 10, 8, 11]
[SHORTSWORD, SHORTBOW, ARROW (20), DAGGER, DAGGER]
[LEATHER_ARMOR]

MASTEMA the level 1 TIEFLING SORCERER (CHAOS_ORIGIN)
AC 12 || 5 hp || POISON_SPRAY +3 1d12 (6) || CR 1/4 (50)
[ 7, 15, 9, 12, 10, 12]
[LIGHT_CROSSBOW, BOLT (20), DAGGER, DAGGER]
[CHROMATIC_ORB, DANCING_LIGHTS, FEATHER_FALL, MAGE_HAND, POISON_SPRAY, RAY_OF_FROST]