From 248f66e4f0374d63c9d797fd0824c9d8fbefb7d5 Mon Sep 17 00:00:00 2001 From: suzan Date: Tue, 17 Jun 2025 10:00:32 -0500 Subject: [PATCH] Added subclass functionality --- creation_engine.py | 179 ++++++++++++++++++++++++++------------------ main.py | 1 - races.json | 181 ++++++++++++++++++++++++++++----------------- 3 files changed, 222 insertions(+), 139 deletions(-) diff --git a/creation_engine.py b/creation_engine.py index a65a7e4..6d909da 100644 --- a/creation_engine.py +++ b/creation_engine.py @@ -1,10 +1,10 @@ import random import json -#TODO 5 AC? Or Gold Start no AC? -#TODO 6 Sub Classes? +# TODO AC? Or Gold Start no AC? +# TODO Feats? -VOWELS = ["A","E","I","O","U"] +VOWELS = ["A", "E", "I", "O", "U"] SKILL_LIST = ["acrobatics", "animal_handling", "arcana", "athletics", "deception", "history", "insight", "intimidation", "investigation", "medicine", "nature", "perception", "performance", "persuasion", "religion", @@ -12,19 +12,21 @@ SKILL_LIST = ["acrobatics", "animal_handling", "arcana", "athletics", "deception ATTRIBUTE_LIST = ["strength", "dexterity", "wisdom", "constitution", "intelligence", "charisma"] -CLASS_LIST = ["Artificer","Barbarian","Bard","Cleric","Druid","Fighter","Monk","Paladin", - "Ranger","Rogue","Sorcerer","Warlock","Wizard","Blood Hunter"] +CLASS_LIST = ["Artificer", "Barbarian", "Bard", "Cleric", "Druid", "Fighter", "Monk", "Paladin", + "Ranger", "Rogue", "Sorcerer", "Warlock", "Wizard", "Blood Hunter"] BACKGROUND_LIST = ["Acolyte", "Charlatan", "Criminal / Spy", "Entertainer", "Folk Hero", "Gladiator", "Guild Artisan / Guild Merchant", "Hermit", "Knight", "Noble", "Outlander", "Pirate", "Sage", - "Sailor", "Soldier", "Urchin",] + "Sailor", "Soldier", "Urchin", ] instrument_list = ["Bagpipes", "Birdpipes", "Clarinet", "Drum", "Dulcimer", "Fiddle", "Flute", "Glaur", "Hand Drum", "Harp", "Horn", "Longhorn", "Lute", "Lyre", "Pan Flute", "Shawm", "Songhorn", "Tantan", "Thelarr", "Tocken", "Trumpet", "Viol", "Wargong", "Yarting", "Zulkoon"] -languages = ["Aarakocra", "Abyssal", "Aquan"," Auran", "Celestial", "Deep Speech", "Draconic", "Dwarvish", "Elvish", "Giant", - "Gith", "Gnomish", "Goblin", "Halfling", "Infernal", "Orc", "Primordial", "Sylvan", "Undercommon", "Vedalken"] +languages = ["Aarakocra", "Abyssal", "Aquan", "Auran", "Celestial", "Deep Speech", "Draconic", "Dwarvish", "Elvish", + "Giant", + "Gith", "Gnomish", "Goblin", "Halfling", "Infernal", "Orc", "Primordial", "Sylvan", "Undercommon", + "Vedalken"] known_language_list = ["Common"] @@ -35,17 +37,29 @@ ARTISANS_TOOLS = ["Alchemist's Supplies", "Brewer's Supplies", "Calligrapher's S "Jeweler's Tools", "Leatherworker's Tools", "Mason's Tools", "Painter's Supplies", "Potter's Tools", "Smith's Tools", "Tinker's Tools", "Weaver's Tools", "Woodcarver's Tools"] +CLERIC_SUBCLASSES = ["Life Domain", "Knowledge Domain", "Light Domain", "Nature Domain", "Tempest Domain", + "Trickery Domain", "War Domain", "Death Domain", "Arcana Domain", "Forge Domain", "Grave Domain", + "Twilight Domain", "Peace Domain", "Order Domain"] + +SORCERER_SUBCLASSES = ["Aberrant Mind", "Clockwork Soul", "Divine Soul", "Draconic Bloodline", "Lunar Sorcery", + "Shadow Magic", "Storm Sorcery", "Wild Magic"] + +WIZARD_SUBCLASSES = ["Bladesinging", "Chronurgy Magic", "Graviturgy Magic", "Order of Scribes", "School of Abjuration", + "School of Conjuration", "School of Divination", "School of Enchantment", "School of Evocation", + "School of Illusion", "School of Necromancy", "School of Transmutation", "War Magic"] + class HeroCreation: def __init__(self): self.name_generation() self.race_selection() self.race = self.race_string["Race"] - #'job' is used in place of 'class' to avoid a function conflict + # 'job' is used in place of 'class' to avoid a function conflict self.job = random.choice(CLASS_LIST) self.job_characteristics() self.background = random.choice(BACKGROUND_LIST) self.stat_rolls() self.racial_bonuses() + self.speed = self.race_string["Speed"] self.article = self.grammar() self.skill_generation() self.skill_proficiency() @@ -57,9 +71,8 @@ class HeroCreation: self.job_proficiencies() self.background_proficiencies() self.finalize_languages() - self.apply_skill_modifiers("dexterity","initiative") - self.whoami = (f"Your new character is {self.name}, {self.article} {self.race} {self.job}, with the " - f"{self.background} background.\n") + self.apply_skill_modifiers("dexterity", "initiative") + self.whoami() self.stat_block = (f"Stat Block\n----------\nCharisma: {self.charisma}\nConstitution: {self.constitution}\n" f"Dexterity: {self.dexterity}\nIntelligence: {self.intelligence}\n" f"Strength: {self.strength}\nWisdom: {self.wisdom}\n") @@ -69,23 +82,26 @@ class HeroCreation: f"Intelligence Save: {self.intelligence_save}\n" f"Strength Save: {self.strength_save}\n" f"Wisdom Save: {self.wisdom_save}\n") - self.additional_stats = (f"Additional Stats\n----------\nStarting HP: {self.starting_hp}\nHit Die: {self.hit_die}\n" - f"Initiative Bonus: {self.initiative}\n") - self.skill_bonuses = (f"Skill Bonuses\n----------\nAcrobatics: {self.acrobatics}\nAnimal Handling: {self.animal_handling}" - f"\nArcana: {self.arcana}\nAthletics: {self.athletics}\nDeception: {self.deception}" - f"\nHistory: {self.history}\nInsight: {self.insight}\nIntimidation: {self.intimidation}" - f"\nInvestigation: {self.investigation}\nMedicine: {self.medicine}\nNature: {self.nature}" - f"\nPerception: {self.perception}\nPerformance: {self.performance}\nPersuasion: {self.persuasion}" - f"\nReligion: {self.religion}\nSleight of Hand: {self.sleight_of_hand}" - f"\nStealth: {self.stealth}\nSurvival: {self.survival}\n") + self.additional_stats = ( + f"Additional Stats\n----------\nStarting HP: {self.starting_hp}\nHit Die: {self.hit_die}\n" + f"Initiative Bonus: {self.initiative}\nSpeed: {self.speed}\n") + self.skill_bonuses = ( + f"Skill Bonuses\n----------\nAcrobatics: {self.acrobatics}\nAnimal Handling: {self.animal_handling}" + f"\nArcana: {self.arcana}\nAthletics: {self.athletics}\nDeception: {self.deception}" + f"\nHistory: {self.history}\nInsight: {self.insight}\nIntimidation: {self.intimidation}" + f"\nInvestigation: {self.investigation}\nMedicine: {self.medicine}\nNature: {self.nature}" + f"\nPerception: {self.perception}\nPerformance: {self.performance}\nPersuasion: {self.persuasion}" + f"\nReligion: {self.religion}\nSleight of Hand: {self.sleight_of_hand}" + f"\nStealth: {self.stealth}\nSurvival: {self.survival}\n") self.other_proficiencies = (f"Additional Proficiencies\n----------\n" f"Languages: {self.languages}\n" f"Instruments: {self.instruments}\n" - f"Artisan's Tools: {self.artisan_tools}\nAdditional Tools: {self.additional_tools}\n" + f"Artisan's Tools: {self.artisan_tools}\nAdditional Tools: " + f"{self.additional_tools}\n" f"Weapon Proficiencies: {self.weapon_proficiency}\n" f"Armor Proficiencies: {self.armor_proficiency}\n") - #Assign the correct a/an article in the 'whoami' attr + # Assign the correct a/an article in the 'whoami' attr def grammar(self): if self.race[0] in VOWELS: return "an" @@ -96,7 +112,7 @@ class HeroCreation: with open('races.json') as json_file: race_data = json.load(json_file) chosen_race = random.choice(race_data) - setattr(self,"race_string",chosen_race) + setattr(self, "race_string", chosen_race) def stat_rolls(self): # Configured to "Re-roll" 1s @@ -107,9 +123,9 @@ class HeroCreation: roll_list.append(random.randint(2, 6)) roll_list.remove(min(roll_list)) stat_total = sum(roll_list) - setattr(self,f"{attribute}", stat_total) + setattr(self, f"{attribute}", stat_total) - #Assign racial stat bonuses + # Assign racial stat bonuses def racial_bonuses(self): self.charisma += self.race_string["Charisma"] self.constitution += self.race_string["Constitution"] @@ -119,35 +135,35 @@ class HeroCreation: self.wisdom += self.race_string["Wisdom"] def name_generation(self): - with open("names.txt","r") as f: + with open("names.txt", "r") as f: name_list = f.read().splitlines() first_name = random.choice(name_list) sur_name = random.choice(name_list) combined_name = f"{first_name} {sur_name}" - setattr(self,"name",combined_name) + setattr(self, "name", combined_name) - #Created skill attributes and save attributes with a base value of +0 to the roll + # Created skill attributes and save attributes with a base value of +0 to the roll def skill_generation(self): for skill in SKILL_LIST: setattr(self, skill, 0) if skill == "athletics": - self.apply_skill_modifiers("strength",skill) + self.apply_skill_modifiers("strength", skill) elif skill in ["acrobatics", "sleight_of_hand", "stealth"]: - self.apply_skill_modifiers("dexterity",skill) + self.apply_skill_modifiers("dexterity", skill) elif skill in ["arcana", "history", "investigation", "nature", "religion"]: - self.apply_skill_modifiers("intelligence",skill) + self.apply_skill_modifiers("intelligence", skill) elif skill in ["animal_handling", "insight", "medicine", "perception", "survival"]: - self.apply_skill_modifiers("wisdom",skill) + self.apply_skill_modifiers("wisdom", skill) elif skill in ["deception", "intimidation", "performance", "persuasion"]: - self.apply_skill_modifiers("charisma",skill) - #Initialization of saving throw modifiers + self.apply_skill_modifiers("charisma", skill) + # Initialization of saving throw modifiers for attribute in ATTRIBUTE_LIST: save_name = f"{attribute}_save" setattr(self, save_name, 0) - self.apply_skill_modifiers(attribute,save_name) + self.apply_skill_modifiers(attribute, save_name) - def apply_skill_modifiers(self,attribute_name,skill_name): - attribute = getattr(self,attribute_name) + def apply_skill_modifiers(self, attribute_name, skill_name): + attribute = getattr(self, attribute_name) if attribute == 1: modifier = -5 elif attribute in [2, 3]: @@ -172,12 +188,12 @@ class HeroCreation: modifier = 5 else: modifier = 0 - setattr(self,skill_name,modifier) + setattr(self, skill_name, modifier) def skill_proficiency(self): with open('backgrounds.json') as json_file: background_data = json.load(json_file) - #Is this actually a dict? + # Is this actually a dict? background_dict = background_data[self.background]["Skills"] for skill in background_dict: current_score = getattr(self, skill) @@ -192,37 +208,36 @@ class HeroCreation: for skill in background_dict: if skill in job_skill_list: job_skill_list.remove(skill) - #rogue list for expertise calculation + # rogue list for expertise calculation rogue_proficient_list = [] for each in range(proficiencies): proficient_skill = random.choice(job_skill_list) if self.job == "Rogue": rogue_proficient_list.append(proficient_skill) job_skill_list.remove(proficient_skill) - current_score = getattr(self,proficient_skill) - setattr(self,f"{proficient_skill}_base_value",current_score) + current_score = getattr(self, proficient_skill) + setattr(self, f"{proficient_skill}_base_value", current_score) new_score = str(current_score + 2) - setattr(self,proficient_skill,f"{new_score} (Prof)") + setattr(self, proficient_skill, f"{new_score} (Prof)") if self.job == "Rogue": expertise_skill = random.choice(rogue_proficient_list) - score_value = getattr(self,f"{expertise_skill}_base_value") + score_value = getattr(self, f"{expertise_skill}_base_value") new_score = score_value + 4 - setattr(self,expertise_skill,f"{new_score} (Expertise)") + setattr(self, expertise_skill, f"{new_score} (Expertise)") def job_characteristics(self): with open('jobs.json') as json_file: job_data = json.load(json_file) hit_die_value = job_data[self.job]["Hit Die"] - setattr(self,"hit_die",hit_die_value) + setattr(self, "hit_die", hit_die_value) starting_hp_value = job_data[self.job]["Starting HP"] - setattr(self,"starting_hp",starting_hp_value) - + setattr(self, "starting_hp", starting_hp_value) def job_proficiencies(self): with open('jobs.json') as json_file: job_data = json.load(json_file) if self.job == "Monk": - tool_choice = random.randint(0,1) + tool_choice = random.randint(0, 1) if tool_choice == 0: instrument_value = 1 else: @@ -239,7 +254,7 @@ class HeroCreation: instrument_prof_list = [] artisan_prof_list = [] try: - for value in range(0,instrument_value): + for value in range(0, instrument_value): new_instrument = random.choice(instrument_list) instrument_list.remove(new_instrument) instrument_prof_list.append(new_instrument) @@ -248,7 +263,7 @@ class HeroCreation: except UnboundLocalError: pass try: - for value in range(0,artisan_tool_value): + for value in range(0, artisan_tool_value): new_tool = random.choice(ARTISANS_TOOLS) ARTISANS_TOOLS.remove(new_tool) artisan_prof_list.append(new_tool) @@ -267,7 +282,7 @@ class HeroCreation: setattr(self, "armor_proficiency", "None") else: armor_prof_string = ", ".join(armor_prof_list) - setattr(self,"armor_proficiency",armor_prof_string) + setattr(self, "armor_proficiency", armor_prof_string) weapon_prof_list = job_data[self.job]["Weapon Proficiency"] weapon_prof_string = ", ".join(weapon_prof_list) setattr(self, "weapon_proficiency", weapon_prof_string) @@ -280,57 +295,57 @@ class HeroCreation: global known_language_list with open('backgrounds.json') as json_file: background_data = json.load(json_file) - #background instrument proficiencies + # background instrument proficiencies try: instrument_value = background_data[self.background]["Additional Proficiencies"]["Instrument"] except KeyError or UnboundLocalError: pass for value in range(0, instrument_value): new_instrument = random.choice(instrument_list) - current_instruments = getattr(self,"instruments") + current_instruments = getattr(self, "instruments") if current_instruments == "None": setattr(self, "instruments", f"{new_instrument}") else: setattr(self, "instruments", current_instruments + f", {new_instrument}") - #background artisan's tools proficiencies + # background artisan's tools proficiencies try: tool_value = background_data[self.background]["Additional Proficiencies"]["Artisan's Tool"] except KeyError or UnboundLocalError: pass for value in range(0, tool_value): new_tool = random.choice(ARTISANS_TOOLS) - current_tools = getattr(self,"artisan_tools") + current_tools = getattr(self, "artisan_tools") if current_tools == "None": setattr(self, "artisan_tools", f"{new_tool}") else: setattr(self, "artisan_tools", current_tools + f", {new_tool}") - #language proficiencies + # language proficiencies try: language_value = background_data[self.background]["Additional Proficiencies"]["Languages"] except UnboundLocalError: pass - for value in range(0,language_value): + for value in range(0, language_value): try: new_language = random.choice(languages) known_language_list.append(new_language) languages.remove(new_language) except IndexError: pass - #additional tool proficiencies + # additional tool proficiencies additional_tool_list = background_data[self.background]["Additional Proficiencies"]["Additional Tools"] if not additional_tool_list: pass else: - current_tools = getattr(self,"additional_tools") + current_tools = getattr(self, "additional_tools") if current_tools == "None": - setattr(self, "additional_tools",", ".join(additional_tool_list)) + setattr(self, "additional_tools", ", ".join(additional_tool_list)) else: for tool in additional_tool_list: if tool in current_tools: pass else: - new_tool_list = getattr(self,"additional_tools") + f", {tool}" - setattr(self,"additional_tools",new_tool_list) + new_tool_list = getattr(self, "additional_tools") + f", {tool}" + setattr(self, "additional_tools", new_tool_list) def race_proficiencies(self): global known_language_list @@ -338,6 +353,7 @@ class HeroCreation: known_languages = self.race_string["Languages"] for language in known_languages: known_language_list.append(language) + print(language) languages.remove(language) except KeyError: pass @@ -354,16 +370,39 @@ class HeroCreation: language_string = ", ".join(known_language_list) setattr(self, "languages", language_string) + def whoami(self): + if self.job == "Cleric": + subclass = random.choice(CLERIC_SUBCLASSES) + setattr(self,"subclass",subclass) + print(f"Your new character is {self.name}, {self.article} {self.race} {self.job}, with the " + f"{self.background} background and the {self.subclass} subclass.\n") + elif self.job == "Sorcerer": + subclass = random.choice(SORCERER_SUBCLASSES) + setattr(self, "subclass", subclass) + print(f"Your new character is {self.name}, {self.article} {self.race} {self.job}, with the " + f"{self.background} background and the {self.subclass} subclass.\n") + elif self.job == "Wizard": + subclass = random.choice(WIZARD_SUBCLASSES) + setattr(self, "subclass", subclass) + print(f"Your new character is {self.name}, {self.article} {self.race} {self.job}, with the " + f"{self.background} background and the {self.subclass} subclass.\n") + else: + print(f"Your new character is {self.name}, {self.article} {self.race} {self.job}, with the " + f"{self.background} background.\n") + + - #Used for interactively moving around stats in case of a bad allocation. - #Disabling for now, as this project is intended to be one-command and self-contained + # Used for interactively moving around stats in case of a bad allocation. + # Disabling for now, as this project is intended to be one-command and self-contained # def stat_moves(self): # finished = False # while not finished: # move_request = input("Would you like to move any of these stats around? (y/n)").lower() # if move_request == "y": - # stat_1 = input("What is the first stat you would like to move? Please enter the full stat name.").lower() - # stat_2 = input("What is the second stat you would like to move? Please enter the full stat name.").lower() + # stat_1 = input("What is the first stat you would like to move? Please enter the full stat + # name.").lower() + # stat_2 = input("What is the second stat you would like to move? Please enter the full stat + # name.").lower() # if hasattr(self, stat_1) and hasattr(self, stat_2): # stat_1_value = getattr(self, stat_1) # stat_2_value = getattr(self, stat_2) @@ -375,8 +414,8 @@ class HeroCreation: # elif move_request == "n": # finished = True - #Currently only used for the stat_moves functionality. Disabling for now + # Currently only used for the stat_moves functionality. Disabling for now # def update_stat_block(self): # self.stat_block = (f"Stat Block\n---------\nCharisma: {self.charisma}\nConstitution: {self.constitution}\n" # f"Dexterity: {self.dexterity}\nIntelligence: {self.intelligence}\n" - # f"Strength: {self.strength}\nWisdom: {self.wisdom}") \ No newline at end of file + # f"Strength: {self.strength}\nWisdom: {self.wisdom}") diff --git a/main.py b/main.py index d49a815..499dbcd 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,6 @@ import creation_engine hero = creation_engine.HeroCreation() -print(hero.whoami) print(hero.stat_block) print(hero.saves) print(hero.additional_stats) diff --git a/races.json b/races.json index cfb71af..c180296 100644 --- a/races.json +++ b/races.json @@ -11,20 +11,8 @@ "Aarakocra", "Auran" ], - "AdditionalLanguages": 1 - }, - { - "Race": "Aasimar", - "Strength": 0, - "Dexterity": 0, - "Constitution": 0, - "Intelligence": 0, - "Wisdom": 1, - "Charisma": 2, - "Languages": [ - "Celestial" - ], - "AdditionalLanguages": 1 + "AdditionalLanguages": 1, + "Speed": 50 }, { "Race": "Aasimar (Fallen)", @@ -37,7 +25,9 @@ "Languages": [ "Celestial" ], - "AdditionalLanguages": 1 + "AdditionalLanguages": 1, + "Speed": 30, + "Resistances": ["Radiant Damage", "Necrotic Damage"] }, { "Race": "Aasimar (Protector)", @@ -50,7 +40,9 @@ "Languages": [ "Celestial" ], - "AdditionalLanguages": 1 + "AdditionalLanguages": 1, + "Speed": 30, + "Resistances": ["Radiant Damage", "Necrotic Damage"] }, { "Race": "Aasimar (Scourge)", @@ -63,7 +55,9 @@ "Languages": [ "Celestial" ], - "AdditionalLanguages": 1 + "AdditionalLanguages": 1, + "Speed": 30, + "Resistances": ["Radiant Damage", "Necrotic Damage"] }, { "Race": "Bugbear", @@ -76,7 +70,8 @@ "Languages": [ "Goblin" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Centaur", @@ -90,7 +85,8 @@ "Sylvan", "Elvish" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 40 }, { "Race": "Dwarf (Duergar)", @@ -104,7 +100,8 @@ "Dwarvish", "Undercommon" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 25 }, { "Race": "Dwarf (Hill)", @@ -117,7 +114,8 @@ "Languages": [ "Dwarvish" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 25 }, { "Race": "Dwarf (Mountain)", @@ -130,7 +128,8 @@ "Languages": [ "Dwarvish" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 25 }, { "Race": "Dragonborn", @@ -143,7 +142,8 @@ "Languages": [ "Draconic" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Elf (Drow)", @@ -157,7 +157,8 @@ "Elvish", "Undercommon" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Elf (Eladrin)", @@ -170,7 +171,8 @@ "Languages": [ "Elvish" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Elf (High)", @@ -183,7 +185,8 @@ "Languages": [ "Elvish" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Elf (Sea)", @@ -197,7 +200,8 @@ "Elvish", "Undercommon" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Elf (Shadar-Kai)", @@ -211,7 +215,8 @@ "Elvish", "Undercommon" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Elf (Wood)", @@ -224,7 +229,8 @@ "Languages": [ "Elvish" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 35 }, { "Race": "Firbolg", @@ -237,7 +243,8 @@ "Languages": [ "Sylvan" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Genasi (Air)", @@ -250,7 +257,8 @@ "Languages": [ "Primordial" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Genasi (Earth)", @@ -263,7 +271,8 @@ "Languages": [ "Primordial" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Genasi (Fire)", @@ -276,7 +285,8 @@ "Languages": [ "Primordial" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Genasi (Water)", @@ -289,7 +299,8 @@ "Languages": [ "Primordial" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Githyanki", @@ -302,7 +313,8 @@ "Languages": [ "Gith" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Githzerai", @@ -315,7 +327,8 @@ "Languages": [ "Gith" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Gnome (Deep)", @@ -329,7 +342,8 @@ "Gnomish", "Undercommon" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 25 }, { "Race": "Gnome (Forest)", @@ -342,7 +356,8 @@ "Languages": [ "Gnomish" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 25 }, { "Race": "Gnome (Rock)", @@ -355,7 +370,8 @@ "Languages": [ "Gnomish" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 25 }, { "Race": "Goblin", @@ -368,7 +384,8 @@ "Languages": [ "Goblin" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Goliath", @@ -381,7 +398,8 @@ "Languages": [ "Giant" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Halfling (Lightfoot)", @@ -394,7 +412,8 @@ "Languages": [ "Halfling" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 25 }, { "Race": "Halfling (Stout)", @@ -407,7 +426,8 @@ "Languages": [ "Halfling" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 25 }, { "Race": "Half-Orc", @@ -420,7 +440,8 @@ "Languages": [ "Orc" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Hobgoblin", @@ -433,7 +454,8 @@ "Languages": [ "Goblin" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Human", @@ -443,7 +465,8 @@ "Intelligence": 1, "Wisdom": 1, "Charisma": 1, - "AdditionalLanguages": 1 + "AdditionalLanguages": 1, + "Speed": 30 }, { "Race": "Kenku", @@ -456,7 +479,8 @@ "Languages": [ "Auran" ], - "AdditionalLanguages": 1 + "AdditionalLanguages": 1, + "Speed": 30 }, { "Race": "Kobold", @@ -469,7 +493,8 @@ "Languages": [ "Draconic" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Lizardfolk", @@ -482,7 +507,8 @@ "Languages": [ "Draconic" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Minotaur", @@ -495,7 +521,8 @@ "Languages": [ "Giant" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Orc", @@ -508,7 +535,8 @@ "Languages": [ "Orc" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Shifter (Beasthide)", @@ -521,7 +549,8 @@ "Languages": [ "Sylvan" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Shifter (Longtooth)", @@ -534,7 +563,8 @@ "Languages": [ "Sylvan" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Shifter (Swiftstride)", @@ -547,7 +577,8 @@ "Languages": [ "Sylvan" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 35 }, { "Race": "Shifter (Wildhunt)", @@ -560,7 +591,8 @@ "Languages": [ "Sylvan" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Tabaxi", @@ -570,7 +602,8 @@ "Intelligence": 0, "Wisdom": 0, "Charisma": 1, - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Tiefling", @@ -583,7 +616,8 @@ "Languages": [ "Infernal" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Tiefling (Dispater)", @@ -596,7 +630,8 @@ "Languages": [ "Infernal" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Tiefling (Glasya)", @@ -609,7 +644,8 @@ "Languages": [ "Infernal" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Tiefling (Feral)", @@ -622,7 +658,8 @@ "Languages": [ "Infernal" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Tiefling (Fierna)", @@ -635,7 +672,8 @@ "Languages": [ "Infernal" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Tiefling (Levistus)", @@ -648,7 +686,8 @@ "Languages": [ "Infernal" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Tiefling (Zariel)", @@ -661,7 +700,8 @@ "Languages": [ "Infernal" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Triton", @@ -674,7 +714,8 @@ "Languages": [ "Aquan" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Vedalken", @@ -688,7 +729,8 @@ "Vedalken", "Undercommon" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Warforged (Juggernaut)", @@ -698,7 +740,8 @@ "Intelligence": 0, "Wisdom": 0, "Charisma": 0, - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Warforged (Skirmisher)", @@ -708,7 +751,8 @@ "Intelligence": 0, "Wisdom": 0, "Charisma": 0, - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 }, { "Race": "Yuan-Ti Pureblood", @@ -722,6 +766,7 @@ "Abyssal", "Draconic" ], - "AdditionalLanguages": 0 + "AdditionalLanguages": 0, + "Speed": 30 } ] \ No newline at end of file