@ -1,10 +1,6 @@
import random
import json
#TODO 1 Languages
#TODO 2 Tool Proficiencies
#TODO 3 Weapon Proficiencies
#TODO 4 Rogue Expertise
#TODO 5 AC? Or Gold Start no AC?
#TODO 6 Sub Classes?
@ -23,12 +19,14 @@ BACKGROUND_LIST = ["Acolyte", "Charlatan", "Criminal / Spy", "Entertainer", "Fol
" Guild Artisan / Guild Merchant " , " Hermit " , " Knight " , " Noble " , " Outlander " , " Pirate " , " Sage " ,
" Sailor " , " Soldier " , " Urchin " , ]
INSTRUMENT_LIST = [ " Bagpipes " , " Birdpipes " , " Clarinet " , " Drum " , " Dulcimer " , " Fiddle " , " Flute " , " Glaur " , " Hand Drum " ,
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 = [ " Abyssal " , " Celestial " , " Deep Speech " , " Draconic " , " Dwarvish " , " Elvish " , " Giant " , " Gnomish " , " Goblin " ,
" Halfling " , " Infernal " , " Orc " , " Primordial " , " Sylvan " , " Undercommon " ]
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 " ]
GAMING_SETS = [ " Bowls " , " Darts " , " Dice Set " , " Dragonchess Set " , " Playing Card Set " , " Quoits " , " Three-Dragon Ante Set " ]
@ -52,15 +50,25 @@ class HeroCreation:
self . skill_generation ( )
self . skill_proficiency ( )
self . instruments = " None "
self . instrument_proficiencies ( )
self . artisan_tools = " None "
self . artisan_tool_proficiencies ( )
self . additional_tools = " None "
self . armor_proficiency = " None "
self . race_proficiencies ( )
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 . stat_block = ( f " Stat Block \n ---------- \n Charisma: { self . charisma } \n Constitution: { self . constitution } \n "
f " Dexterity: { self . dexterity } \n Intelligence: { self . intelligence } \n "
f " Strength: { self . strength } \n Wisdom: { self . wisdom } \n " )
self . saves = ( f " Saving Throws \n ---------- \n Charisma Save: { self . charisma_save } \n "
f " Constitution Save: { self . constitution_save } \n "
f " Dexterity Save: { self . dexterity_save } \n "
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 ---------- \n Starting HP: { self . starting_hp } \n Hit Die: { self . hit_die } \n "
f " Initiative Bonus: { self . initiative } \n " )
self . skill_bonuses = ( f " Skill Bonuses \n ---------- \n Acrobatics: { self . acrobatics } \n Animal Handling: { self . animal_handling } "
@ -70,8 +78,12 @@ class HeroCreation:
f " \n Perception: { self . perception } \n Performance: { self . performance } \n Persuasion: { self . persuasion } "
f " \n Religion: { self . religion } \n Sleight of Hand: { self . sleight_of_hand } "
f " \n Stealth: { self . stealth } \n Survival: { self . survival } \n " )
self . other_proficiencies = ( f " Additional Proficiencies \n ---------- \n Instruments: { self . instruments } \n "
f " Artisan ' s Tools: { self . artisan_tools } " )
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 } \n Additional Tools: { 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
def grammar ( self ) :
@ -114,7 +126,7 @@ class HeroCreation:
combined_name = f " { first_name } { sur_name } "
setattr ( self , " name " , combined_name )
#Created skill 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 )
@ -128,6 +140,11 @@ class HeroCreation:
self . apply_skill_modifiers ( " wisdom " , skill )
elif skill in [ " deception " , " intimidation " , " performance " , " persuasion " ] :
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 )
def apply_skill_modifiers ( self , attribute_name , skill_name ) :
attribute = getattr ( self , attribute_name )
@ -160,7 +177,7 @@ class HeroCreation:
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 )
@ -175,15 +192,24 @@ class HeroCreation:
for skill in background_dict :
if skill in job_skill_list :
job_skill_list . remove ( skill )
#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 )
new_score = str ( current_score + 2 )
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 " )
new_score = score_value + 4
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 " ]
@ -192,33 +218,141 @@ class HeroCreation:
setattr ( self , " starting_hp " , starting_hp_value )
def instrument _proficiencies( self ) :
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 )
if tool_choice == 0 :
instrument_value = 1
else :
artisan_tool_value = 1
else :
try :
instrument_value = job_data [ self . job ] [ " Instruments " ]
except KeyError :
pass
try :
artisan_tool_value = job_data [ self . job ] [ " Artisan ' s Tools " ]
except KeyError :
pass
instrument_prof_list = [ ]
artisan_prof_list = [ ]
try :
for value in range ( job_data [ self . job ] [ " Instruments " ] ) :
new_instrument = random . choice ( INSTRUMENT_LIST )
INSTRUMENT_LIST . remove ( new_instrument )
for value in range ( 0 , instrument_value ) :
new_instrument = random . choice ( instrument_list )
instrument_list . remove ( new_instrument )
instrument_prof_list . append ( new_instrument )
instrument_string = " , " . join ( instrument_prof_list )
setattr ( self , " instruments " , str ( instrument_string ) )
except KeyError :
except UnboundLocal Error:
pass
def artisan_tool_proficiencies ( self ) :
with open ( ' jobs.json ' ) as json_file :
job_data = json . load ( json_file )
artisan_prof_list = [ ]
try :
for value in range ( job_data [ self . job ] [ " Artisan ' s Tools " ] ) :
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 )
artisan_tool_string = " , " . join ( artisan_prof_list )
setattr ( self , " artisan_tools " , str ( artisan_tool_string ) )
except UnboundLocalError :
pass
try :
additional_tool_list = job_data [ self . job ] [ " Additional Tools " ]
additional_tool_string = " , " . join ( additional_tool_list )
setattr ( self , " additional_tools " , str ( additional_tool_string ) )
except KeyError :
pass
armor_prof_list = job_data [ self . job ] [ " Armor Proficiency " ]
if not armor_prof_list :
setattr ( self , " armor_proficiency " , " None " )
else :
armor_prof_string = " , " . join ( armor_prof_list )
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 )
for attribute in job_data [ self . job ] [ " Saving Throws " ] :
current_score = getattr ( self , f " { attribute } _save " )
new_score = str ( current_score + 2 )
setattr ( self , f " { attribute } _save " , f " { new_score } (Prof) " )
def background_proficiencies ( self ) :
global known_language_list
with open ( ' backgrounds.json ' ) as json_file :
background_data = json . load ( json_file )
#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 " )
if current_instruments == " None " :
setattr ( self , " instruments " , f " { new_instrument } " )
else :
setattr ( self , " instruments " , current_instruments + f " , { new_instrument } " )
#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 " )
if current_tools == " None " :
setattr ( self , " artisan_tools " , f " { new_tool } " )
else :
setattr ( self , " artisan_tools " , current_tools + f " , { new_tool } " )
#language proficiencies
try :
language_value = background_data [ self . background ] [ " Additional Proficiencies " ] [ " Languages " ]
except UnboundLocalError :
pass
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_list = background_data [ self . background ] [ " Additional Proficiencies " ] [ " Additional Tools " ]
if not additional_tool_list :
pass
else :
current_tools = getattr ( self , " additional_tools " )
if current_tools == " None " :
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 )
def race_proficiencies ( self ) :
global known_language_list
try :
known_languages = self . race_string [ " Languages " ]
for language in known_languages :
known_language_list . append ( language )
languages . remove ( language )
except KeyError :
pass
for value in range ( 0 , self . race_string [ " AdditionalLanguages " ] ) :
try :
new_language = random . choice ( languages )
known_language_list . append ( new_language )
languages . remove ( new_language )
except IndexError :
pass
def finalize_languages ( self ) :
global known_language_list
language_string = " , " . join ( known_language_list )
setattr ( self , " languages " , language_string )
#Used for interactively moving around stats in case of a bad allocation.