Skip to content

Commit 63bb0f1

Browse files
committed
Mickey's refactor.
1 parent bd5b807 commit 63bb0f1

8 files changed

Lines changed: 305 additions & 329 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
# Python-Character-Creator
22
Python for a DnD character creator.
33
Code is supposed to receive inputs from a user so they may be walked through the creation of a DnD character.
4+
5+
TODO:
6+
- critical hits
7+
- critical damage
8+
- more content

character.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import math
2+
from random import randint
3+
from dataclasses import dataclass
4+
5+
from entity import Entity
6+
from equipment import armors, weapons
7+
from dice import roll
8+
9+
10+
CHARACTER_ATTRIBUTES = ("Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma")
11+
12+
13+
@dataclass
14+
class PlayerClass:
15+
name: str
16+
starting_hp: int
17+
hit_die: int
18+
19+
20+
classes = list()
21+
classes.append(PlayerClass("Fighter", 6, 10))
22+
23+
24+
class Character(Entity):
25+
def __init__(self):
26+
Entity.__init__(self, input("Name your character: "))
27+
self.level = 1
28+
self.picker("class", classes)
29+
self.reset_attributes()
30+
self.pick_attributes(26)
31+
self.max_hp = self.player_class.starting_hp + \
32+
self.get_attribute_mod(CHARACTER_ATTRIBUTES[2]) * self.level
33+
self.current_hp = self.max_hp
34+
print(self.get_attrs_str())
35+
self.picker("armor", armors)
36+
self.picker("weapon", weapons)
37+
38+
39+
def get_attribute_mod(self, attribute):
40+
return math.floor((self.attributes[attribute] - 10) / 2)
41+
42+
43+
def get_attribute_mod_cost(self, attribute):
44+
a = self.attributes[attribute]
45+
if a < 14:
46+
return 1
47+
elif a == 14:
48+
return 2
49+
elif a > 14:
50+
return "MAX"
51+
52+
53+
def reset_attributes(self):
54+
self.attributes = dict()
55+
for a in CHARACTER_ATTRIBUTES:
56+
self.attributes[a] = 8
57+
58+
59+
def pick_attributes(self, points):
60+
numbers = range(1, len(CHARACTER_ATTRIBUTES) + 1)
61+
error = ""
62+
63+
while points > 0:
64+
print(" Attribute\tValue\tModifier\tCost")
65+
for n, a in zip(numbers, CHARACTER_ATTRIBUTES):
66+
print(f"{n}: {a}\t{self.attributes[a]}\t{self.get_attribute_mod(a)}\t{self.get_attribute_mod_cost(a)}")
67+
print()
68+
print(f"Attribute Points: {points}")
69+
print(error)
70+
choice = int(input("Choose an attribute to increase: "))
71+
print()
72+
if choice in numbers:
73+
choice -= 1
74+
a = CHARACTER_ATTRIBUTES[choice]
75+
cost = self.get_attribute_mod_cost(a)
76+
if cost == "MAX":
77+
error = f"{CHARACTER_ATTRIBUTES[choice]} is at maximum"
78+
elif cost <= points:
79+
self.attributes[a] += 1
80+
points -= cost
81+
error = ""
82+
else:
83+
error = f"Not enough points to increase {a}"
84+
else:
85+
error = f"Please pick a number between {min(numbers)} and {max(numbers)}"
86+
87+
88+
def get_attack_bonus(self):
89+
return self.get_attack_attr_bonus() + self.get_proficiency_bonus()
90+
91+
92+
def get_attack_attr_bonus(self):
93+
return max(self.get_attribute_mod["Strength"],
94+
self.get_attribute_mod["Dexterity"]) \
95+
if self.weapon.finesse else self.get_attribute_mod("Strength")
96+
97+
98+
def get_proficiency_bonus(self):
99+
return math.floor(2 + ((self.level - 1) * 0.25))
100+
101+
102+
def roll_weapon_damage(self):
103+
return roll(*self.weapon.damage) + self.get_attack_attr_bonus()
104+
105+
106+
def __str__(self):
107+
return f"{self.name} is a level {self.level} {self.player_class.name}\n" \
108+
f"{self.get_health_str()}\n" \
109+
f"Armor: {self.armor.name} AC: {self.armor.armor_class} Weapon: {self.weapon.name}" \
110+
f"{self.get_attrs_str()}"
111+
112+
113+
def get_attrs_str(self):
114+
return ''.join([f"{a}: {self.attributes[a]}\n" for a in CHARACTER_ATTRIBUTES])
115+
116+
117+
def picker(self, pick_type, pick_list):
118+
choices = [g.name for g in pick_list]
119+
numbers = range(1, len(pick_list) + 1)
120+
121+
for i, name in zip(numbers, choices):
122+
print(f"{i}: {name}")
123+
124+
prompt = f"Which {pick_type} would you like? "
125+
126+
while True:
127+
choice = int(input(prompt))
128+
if choice in numbers:
129+
break
130+
else:
131+
prompt = f"Please pick a number between {min(numbers)} and {max(numbers)}: "
132+
133+
if pick_type == "armor":
134+
self.armor = armors[choice - 1]
135+
print(f"You chose {self.armor.name}.\n")
136+
elif pick_type == "weapon":
137+
self.weapon = weapons[choice - 1]
138+
print(f"You chose {self.weapon.name}.\n")
139+
elif pick_type == "class":
140+
self.player_class= classes[choice - 1]
141+
print(f"You chose {self.player_class.name}.\n")
142+
143+
144+
def attack(self, enemy):
145+
attack_roll = roll(1, 20) + self.get_attack_bonus()
146+
print(f"{self.name} swings their {self.weapon.name} at the {enemy.name}!")
147+
if enemy.armor_class < attack_roll:
148+
print(f"{self.name} smacks the {enemy.name} a good one! {attack_roll} vs {enemy.get_ac()} AC")
149+
enemy.take_damage(self.roll_weapon_damage())
150+
else:
151+
print(f"{self.name} wiffs!")
152+
153+
154+
def get_ac(self):
155+
return self.armor.ac + min(self.armor.max_dex_bonus, self.attributes["Dexterity"])

0 commit comments

Comments
 (0)