1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 19:44:20 +00:00

Merge pull request #97 from Steffo99/dndproficiency

Use proficiencies for dnd
This commit is contained in:
Steffo 2019-10-24 13:19:46 +02:00 committed by GitHub
commit 1174502290
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 447 additions and 256 deletions

View file

@ -4,4 +4,3 @@ from .commands import available_commands
from .tables import available_tables from .tables import available_tables
__all__ = ["commands", "tables", "available_commands", "available_tables"] __all__ = ["commands", "tables", "available_commands", "available_tables"]

View file

@ -6,8 +6,6 @@ from .dndinfo import DndinfoCommand
from .dndnew import DndnewCommand from .dndnew import DndnewCommand
from .dndedit import DndeditCommand from .dndedit import DndeditCommand
from .dndroll import DndrollCommand from .dndroll import DndrollCommand
from .dndrolladv import DndrolladvCommand
from .dndrolldis import DndrolldisCommand
# Enter the commands of your Pack here! # Enter the commands of your Pack here!
available_commands = [ available_commands = [
@ -18,8 +16,6 @@ available_commands = [
DndnewCommand, DndnewCommand,
DndeditCommand, DndeditCommand,
DndrollCommand, DndrollCommand,
DndrolladvCommand,
DndrolldisCommand,
] ]
# Don't change this, it should automatically generate __all__ # Don't change this, it should automatically generate __all__

View file

@ -1,60 +1,35 @@
import re import re
from royalnet.commands import * from royalnet.commands import *
from .dndnew import DndnewCommand
from ..tables import DndCharacter, DndActiveCharacter from ..tables import DndCharacter, DndActiveCharacter
class DndeditCommand(Command): class DndeditCommand(DndnewCommand):
name: str = "dndedit" name: str = "dndedit"
description: str = "Edit the active DnD character." description: str = "Edit the active DnD character."
aliases = ["de", "dnde", "edit", "dedit"] aliases = ["de", "dnde", "edit", "dedit"]
syntax = "{name}\n" \
"LV {level}\n" \
"\n" \
"STR {strength}\n" \
"DEX {dexterity}\n" \
"CON {constitution}\n" \
"INT {intelligence}\n" \
"WIS {wisdom}\n" \
"CHA {charisma}\n" \
"\n" \
"MAXHP {max_hp}\n" \
"AC {armor_class}"
tables = {DndCharacter, DndActiveCharacter} tables = {DndCharacter, DndActiveCharacter}
async def run(self, args: CommandArgs, data: CommandData) -> None: async def run(self, args: CommandArgs, data: CommandData) -> None:
name, level, strength, dexterity, constitution, intelligence, wisdom, charisma, max_hp, armor_class = \ character_sheet = args.joined()
args.match(r"([\w ]+\w)\s*"
r"LV\s+(\d+)\s+" if character_sheet == "":
r"STR\s+(\d+)\s+" await data.reply(self._syntax())
r"DEX\s+(\d+)\s+" return
r"CON\s+(\d+)\s+"
r"INT\s+(\d+)\s+"
r"WIS\s+(\d+)\s+"
r"CHA\s+(\d+)\s+"
r"MAXHP\s+(\d+)\s+"
r"AC\s+(\d+)", re.IGNORECASE)
try:
int(name)
except ValueError:
pass
else:
raise CommandError("Character names cannot be composed of only a number.")
author = await data.get_author(error_if_none=True) author = await data.get_author(error_if_none=True)
char = author.dnd_active_character.character if author.dnd_active_character is None:
char.name = name raise CommandError("You don't have an active character.")
char.level = level
char.strength = strength char: DndCharacter = author.dnd_active_character.character
char.dexterity = dexterity
char.constitution = constitution arguments = self._parse(character_sheet)
char.intelligence = intelligence for key in arguments:
char.wisdom = wisdom char.__setattr__(key, arguments[key])
char.charisma = charisma
char.max_hp = max_hp
char.armor_class = armor_class
data.session.add(char)
await data.session_commit() await data.session_commit()
await data.reply(f"✅ Edit successful!") await data.reply(f"✅ Edit successful!")

View file

@ -1,6 +1,8 @@
import re import re
# noinspection PyUnresolvedReferences
from royalnet.commands import * from royalnet.commands import *
from ..tables import DndCharacter from ..tables import DndCharacter
from ..utils import DndProficiencyType
class DndnewCommand(Command): class DndnewCommand(Command):
@ -10,51 +12,60 @@ class DndnewCommand(Command):
aliases = ["dn", "dndn", "new", "dnew"] aliases = ["dn", "dndn", "new", "dnew"]
syntax = "{name}\n" \ syntax = "{name}\n{character_sheet}"
"LV {level}\n" \
"\n" \
"STR {strength}\n" \
"DEX {dexterity}\n" \
"CON {constitution}\n" \
"INT {intelligence}\n" \
"WIS {wisdom}\n" \
"CHA {charisma}\n" \
"\n" \
"MAXHP {max_hp}\n" \
"AC {armor_class}"
tables = {DndCharacter} tables = {DndCharacter}
async def run(self, args: CommandArgs, data: CommandData) -> None: def _search_value(self, name: str, string: str):
name, level, strength, dexterity, constitution, intelligence, wisdom, charisma, max_hp, armor_class = \ return re.search(r"\s*" + name + r"\s*([0-9]+)\s*", string, re.IGNORECASE)
args.match(r"([\w ]+\w)\s*"
r"LV\s+(\d+)\s+" def _parse(self, character_sheet: str) -> dict:
r"STR\s+(\d+)\s+" columns = list(self.alchemy.DndCharacter.__table__.columns)
r"DEX\s+(\d+)\s+" column_names = [column.name for column in columns if (not column.primary_key and
r"COS\s+(\d+)\s+" not column.foreign_keys and
r"INT\s+(\d+)\s+" column.name != "name")]
r"WIS\s+(\d+)\s+" arguments = {}
r"CHA\s+(\d+)\s+" for column_name in column_names:
r"MAXHP\s+(\d+)\s+" match = self._search_value(column_name, character_sheet)
r"AC\s+(\d+)", re.IGNORECASE) if match:
try: if column_name.endswith("_proficiency"):
int(name) arguments[column_name] = DndProficiencyType(float(match.group(1)))
except ValueError:
pass
else: else:
raise CommandError("Character names cannot be composed of only a number.") arguments[column_name] = match.group(1)
author = await data.get_author(error_if_none=True) return arguments
char = self.alchemy.DndCharacter(name=name,
level=level, def _syntax(self) -> str:
strength=strength, columns = list(self.alchemy.DndCharacter.__table__.columns)
dexterity=dexterity, column_names = [column.name for column in columns if (not column.primary_key and
constitution=constitution, not column.foreign_keys and
intelligence=intelligence, column.name != "name")]
wisdom=wisdom, message = " Character Sheet syntax:\n[p]\nName\n"
charisma=charisma, for column_name in column_names:
max_hp=max_hp, message += f"{column_name} _\n"
armor_class=armor_class, message += "[/p]"
creator=author) return message
data.session.add(char)
async def run(self, args: CommandArgs, data: CommandData) -> None:
character_sheet = args.joined()
if character_sheet == "":
await data.reply(self._syntax())
return
creator = await data.get_author()
name, rest = character_sheet.split("\n", 1)
character = self.alchemy.DndCharacter(name=name, creator=creator, **self._parse(rest))
data.session.add(character)
try:
await data.session_commit() await data.session_commit()
await data.reply(f"✅ Character [b]{char.name}[/b] ([c]{char.character_id}[/c]) was created!") except Exception as err:
# THIS IS INTENDED
if err.__class__.__name__ == "IntegrityError":
param_name = re.search(r'in column "(\S+)"', err.args[0]).group(1)
raise CommandError(f"Mandatory parameter '{param_name}' is missing.")
raise
await data.reply(f"✅ Character [b]{character.name}[/b] created!")

View file

@ -1,94 +1,146 @@
import typing import re
import random import random
from royalnet.commands import * from royalnet.commands import *
from royalnet.utils import plusformat
from ..tables import DndCharacter, DndActiveCharacter from ..tables import DndCharacter, DndActiveCharacter
from royalnet.utils import plusformat
class DndrollCommand(Command): class DndrollCommand(Command):
name: str = "dndroll" name: str = "dndroll"
description: str = "Roll as the active DnD character." description: str = "Roll dice as the active DnD character."
aliases = ["dr", "dndr", "droll"] aliases = ["dr", "dndr", "roll", "droll"]
syntax = "{stat} [proficiency] [modifier]"
tables = {DndCharacter, DndActiveCharacter} tables = {DndCharacter, DndActiveCharacter}
@staticmethod _skill_names = {
def _roll(): "str": "strength",
return random.randrange(1, 21) "for": "strength",
"dex": "dexterity",
"des": "dexterity",
"con": "constitution",
"cos": "constitution",
"inte": "intelligence",
"wis": "wisdom",
"sag": "wisdom",
"cha": "charisma",
"car": "charisma",
_roll_string = "1d20" "ststr": "strength_save",
"stfor": "strength_save",
"stdex": "dexterity_save",
"stdes": "dexterity_save",
"stcon": "constitution_save",
"stcos": "constitution_save",
"stint": "intelligence_save",
"stwis": "wisdom_save",
"stsag": "wisdom_save",
"stcha": "charisma_save",
"stcar": "charisma_save",
"tsstr": "strength_save",
"tsfor": "strength_save",
"tsdex": "dexterity_save",
"tsdes": "dexterity_save",
"tscon": "constitution_save",
"tscos": "constitution_save",
"tsint": "intelligence_save",
"tswis": "wisdom_save",
"tssag": "wisdom_save",
"tscha": "charisma_save",
"tscar": "charisma_save",
"acr": "acrobatics",
"add": "animal_handling",
"ani": "animal_handling",
"arc": "arcana",
"ath": "athletics",
"dec": "deception",
"ing": "deception",
"his": "history",
"sto": "history",
"ins": "insight",
"intu": "insight",
"inti": "intimidation",
"inv": "investigation",
"med": "medicine",
"nat": "nature",
"perc": "perception",
"perf": "performance",
"pers": "persuasion",
"rel": "religion",
"sle": "sleight_of_hand",
"soh": "sleight_of_hand",
"rap": "sleight_of_hand",
"ste": "stealth",
"nas": "stealth",
"sur": "survival",
"sop": "sopravvivenza",
}
async def run(self, args: CommandArgs, data: CommandData) -> None: async def run(self, args: CommandArgs, data: CommandData) -> None:
author = await data.get_author(error_if_none=True) author = await data.get_author(error_if_none=True)
if author.dnd_active_character is None: if author.dnd_active_character is None:
raise CommandError("You don't have an active character.") raise CommandError("You don't have an active character.")
char: DndCharacter = author.dnd_active_character.character char: DndCharacter = author.dnd_active_character.character
stat: str = args[0]
second: typing.Optional[str] = args.optional(1) first = args[0]
third: typing.Optional[str] = args.optional(2) second = args.optional(1)
third = args.optional(2)
advantage = False
disadvantage = False
extra_modifier = 0
if third: if third:
extra_mod: int = int(third) try:
extra_modifier = int(third)
except ValueError:
raise InvalidInputError("Invalid modifier value (third parameter).")
if second.startswith("a") or second.startswith("v"):
advantage = True
elif second.startswith("d") or second.startswith("d"):
disadvantage = True
else: else:
extra_mod: int = 0 raise InvalidInputError("Invalid advantage string (second parameter).")
if second: elif second:
if second.startswith("e") or second.startswith("x"): try:
proficiency_mul: float = 2.0 extra_modifier = int(second)
proficiency_name: str = " with Expertise" except ValueError:
elif second.startswith("f") or second.startswith("n") or second.startswith("c"): if second.startswith("a") or second.startswith("v"):
proficiency_mul: float = 1.0 advantage = True
proficiency_name: str = " with Proficiency" elif second.startswith("d") or second.startswith("d"):
elif second.startswith("h") or second == "/" or second.startswith("m"): disadvantage = True
proficiency_mul: float = 0.5
proficiency_name: str = " with Half Proficiency"
elif second.startswith("h") or second == "/" or second.startswith("m"):
proficiency_mul: float = 0.0
proficiency_name: str = " [i]without Proficiency[/i]"
else: else:
raise CommandError(f"Unknown proficiency type '{second}'") raise InvalidInputError("Invalid modifier value or advantage string (second parameter).")
proficiency_mod: int = int(char.proficiency_bonus * proficiency_mul)
skill_short_name = first
for root in self._skill_names:
if skill_short_name.startswith(root):
skill_name = self._skill_names[root]
break
else: else:
proficiency_name: str = "" raise CommandError("Invalid skill name (first parameter).")
proficiency_mod: int = 0
if stat.startswith("st") or stat.startswith("fo"): skill_modifier = char.__getattribute__(skill_name)
stat_mod: int = char.strength_mod modifier = skill_modifier + extra_modifier
stat_name: str = "[i]STR[/i]" modifier_str = plusformat(modifier, empty_if_zero=True)
elif stat.startswith("de"):
stat_mod: int = char.dexterity_mod if advantage:
stat_name: str = "[i]DEX[/i]" roll_a = random.randrange(1, 21)
elif stat.startswith("co"): roll_b = random.randrange(1, 21)
stat_mod: int = char.constitution_mod roll = max([roll_a, roll_b])
stat_name: str = "[i]CON[/i]" total = roll + modifier
elif stat.startswith("in"): await data.reply(f"🎲 2d20h1{modifier_str} = ({roll_a}|{roll_b}){modifier_str} = [b]{total}[/b]")
stat_mod: int = char.intelligence_mod elif disadvantage:
stat_name: str = "[i]INT[/i]" roll_a = random.randrange(1, 21)
elif stat.startswith("wi") or stat.startswith("sa"): roll_b = random.randrange(1, 21)
stat_mod: int = char.wisdom_mod roll = min([roll_a, roll_b])
stat_name: str = "[i]WIS[/i]" total = roll + modifier
elif stat.startswith("ch") or stat.startswith("ca"): await data.reply(f"🎲 2d20l1{modifier_str} = ({roll_a}|{roll_b}){modifier_str} = [b]{total}[/b]")
stat_mod: int = char.charisma_mod
stat_name: str = "[i]CHA[/i]"
else: else:
raise CommandError(f"Unknown stat '{stat}'") roll = random.randrange(1, 21)
total = roll + modifier
total_mod = stat_mod + proficiency_mod + extra_mod await data.reply(f"🎲 1d20{modifier_str} = {roll}{modifier_str} = [b]{total}[/b]")
roll = self._roll()
result = roll + total_mod
await data.reply(f"🎲 Rolling {stat_name}{proficiency_name}{plusformat(extra_mod, empty_if_zero=True)}:\n"
f"{self._roll_string}"
f"{plusformat(stat_mod, empty_if_zero=True)}"
f"{plusformat(proficiency_mod, empty_if_zero=True)}"
f"{plusformat(extra_mod, empty_if_zero=True)}"
f" = "
f"{roll}{plusformat(total_mod, empty_if_zero=True)}"
f" = "
f"[b]{result}[/b]")

View file

@ -1,26 +0,0 @@
import typing
import random
from royalnet.commands import *
from royalnet.utils import plusformat
from .dndroll import DndrollCommand
from ..tables import DndCharacter, DndActiveCharacter
class DndrolladvCommand(DndrollCommand):
name: str = "dndrolladv"
description: str = "Roll with advantage as the active DnD character."
aliases = ["dra", "dndra", "drolladv"]
syntax = "{stat} [proficiency] [modifier]"
tables = {DndCharacter, DndActiveCharacter}
@staticmethod
def _roll():
first = random.randrange(1, 21)
second = random.randrange(1, 21)
return max(first, second)
_roll_string = "2d20h1"

View file

@ -1,26 +0,0 @@
import typing
import random
from royalnet.commands import *
from royalnet.utils import plusformat
from .dndroll import DndrollCommand
from ..tables import DndCharacter, DndActiveCharacter
class DndrolldisCommand(DndrollCommand):
name: str = "dndrolldis"
description: str = "Roll with disadvantage as the active DnD character."
aliases = ["drd", "dndrd", "drolldis"]
syntax = "{stat} [proficiency] [modifier]"
tables = {DndCharacter, DndActiveCharacter}
@staticmethod
def _roll():
first = random.randrange(1, 21)
second = random.randrange(1, 21)
return min(first, second)
_roll_string = "2d20l1"

View file

@ -1,6 +1,7 @@
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import * from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import * from sqlalchemy.ext.declarative import *
from ..utils import DndProficiencyType
class DndCharacter: class DndCharacter:
@ -20,71 +21,267 @@ class DndCharacter:
@declared_attr @declared_attr
def name(self): def name(self):
return Column(String) return Column(String, nullable=False)
@declared_attr @declared_attr
def strength_score(self):
return Column(Integer, nullable=False)
@property
def strength(self): def strength(self):
return Column(Integer) return (self.strength_score - 10) // 2
@property
def strength_mod(self):
return (self.strength - 10) // 2
@declared_attr @declared_attr
def dexterity_score(self):
return Column(Integer, nullable=False)
@property
def dexterity(self): def dexterity(self):
return Column(Integer) return (self.dexterity_score - 10) // 2
@property
def dexterity_mod(self):
return (self.dexterity - 10) // 2
@declared_attr @declared_attr
def constitution_score(self):
return Column(Integer, nullable=False)
@property
def constitution(self): def constitution(self):
return Column(Integer) return (self.constitution_score - 10) // 2
@property
def constitution_mod(self):
return (self.constitution - 10) // 2
@declared_attr @declared_attr
def intelligence_score(self):
return Column(Integer, nullable=False)
@property
def intelligence(self): def intelligence(self):
return Column(Integer) return (self.intelligence_score - 10) // 2
@property
def intelligence_mod(self):
return (self.intelligence - 10) // 2
@declared_attr @declared_attr
def wisdom_score(self):
return Column(Integer, nullable=False)
@property
def wisdom(self): def wisdom(self):
return Column(Integer) return (self.wisdom_score - 10) // 2
@property
def wisdom_mod(self):
return (self.wisdom - 10) // 2
@declared_attr @declared_attr
def charisma(self): def charisma_score(self):
return Column(Integer) return Column(Integer, nullable=False)
@property @property
def charisma_mod(self): def charisma(self):
return (self.charisma - 10) // 2 return (self.charisma_score - 10) // 2
@declared_attr @declared_attr
def level(self): def level(self):
return Column(Integer) return Column(Integer, nullable=False)
@property @property
def proficiency_bonus(self): def proficiency_bonus(self):
return ((self.level - 1) // 4) + 2 return ((self.level - 1) // 4) + 2
@declared_attr
def current_hp(self):
return Column(Integer, nullable=False)
@declared_attr @declared_attr
def max_hp(self): def max_hp(self):
return Column(Integer) return Column(Integer, nullable=False)
@declared_attr @declared_attr
def armor_class(self): def armor_class(self):
return Column(Integer) return Column(Integer, nullable=False)
@declared_attr
def strength_save_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def dexterity_save_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def constitution_save_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def intelligence_save_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def wisdom_save_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def charisma_save_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def acrobatics_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def animal_handling_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def arcana_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def athletics_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def deception_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def history_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def insight_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def intimidation_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def investigation_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def medicine_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def nature_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def perception_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def performance_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def persuasion_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def religion_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def sleight_of_hand_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def stealth_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@declared_attr
def survival_proficiency(self):
return Column(Enum(DndProficiencyType), nullable=False, default=DndProficiencyType.NONE)
@property
def strength_save(self):
return self.strength + self.proficiency_bonus * self.strength_save_proficiency.value
@property
def dexterity_save(self):
return self.dexterity + self.proficiency_bonus * self.dexterity_save_proficiency.value
@property
def constitution_save(self):
return self.constitution + self.proficiency_bonus * self.constitution_save_proficiency.value
@property
def intelligence_save(self):
return self.intelligence + self.proficiency_bonus * self.intelligence_save_proficiency.value
@property
def wisdom_save(self):
return self.wisdom + self.proficiency_bonus * self.wisdom_save_proficiency.value
@property
def charisma_save(self):
return self.charisma + self.proficiency_bonus * self.charisma_save_proficiency.value
@property
def acrobatics(self):
return self.dexterity + self.proficiency_bonus * self.acrobatics_proficiency.value
@property
def animal_handling(self):
return self.wisdom + self.proficiency_bonus * self.animal_handling_proficiency.value
@property
def arcana(self):
return self.intelligence + self.proficiency_bonus * self.arcana_proficiency.value
@property
def athletics(self):
return self.strength + self.proficiency_bonus * self.athletics_proficiency.value
@property
def deception(self):
return self.charisma + self.proficiency_bonus * self.deception_proficiency.value
@property
def history(self):
return self.intelligence + self.proficiency_bonus * self.history_proficiency.value
@property
def insight(self):
return self.wisdom + self.proficiency_bonus * self.insight_proficiency.value
@property
def intimidation(self):
return self.charisma + self.proficiency_bonus * self.intimidation_proficiency.value
@property
def investigation(self):
return self.intelligence + self.proficiency_bonus * self.investigation_proficiency.value
@property
def medicine(self):
return self.wisdom + self.proficiency_bonus * self.medicine_proficiency.value
@property
def nature(self):
return self.intelligence + self.proficiency_bonus * self.nature_proficiency.value
@property
def perception(self):
return self.wisdom + self.proficiency_bonus * self.perception_proficiency.value
@property
def performance(self):
return self.charisma + self.proficiency_bonus * self.performance_proficiency.value
@property
def persuasion(self):
return self.charisma + self.proficiency_bonus * self.persuasion_proficiency.value
@property
def religion(self):
return self.intelligence + self.proficiency_bonus * self.religion_proficiency.value
@property
def sleight_of_hand(self):
return self.dexterity + self.proficiency_bonus * self.sleight_of_hand_proficiency.value
@property
def stealth(self):
return self.dexterity + self.proficiency_bonus * self.stealth_proficiency.value
@property
def survival(self):
return self.wisdom + self.proficiency_bonus * self.survival_proficiency.value
def __repr__(self): def __repr__(self):
return f"<{self.__class__.__qualname__} {self.name}>" return f"<{self.__class__.__qualname__} {self.name}>"
@ -92,14 +289,13 @@ class DndCharacter:
def __str__(self): def __str__(self):
return f"{self.name}" return f"{self.name}"
def character_sheet(self): def character_sheet(self) -> str:
return f"{self.name}\n" \ columns = list(self.__class__.__table__.columns)
f"LV {self.level}\n\n" \ column_names = [column.name for column in columns if (not column.primary_key and
f"STR {self.strength}\n" \ not column.foreign_keys and
f"DEX {self.dexterity}\n" \ column.name != "name")]
f"CON {self.constitution}\n" \ message = f"[b]{self.name}[/b]\n"
f"INT {self.intelligence}\n" \ for column_name in column_names:
f"WIS {self.wisdom}\n" \ value = self.__getattribute__(column_name)
f"CHA {self.charisma}\n\n" \ message += f"{column_name} {value}\n"
f"MAXHP {self.max_hp}\n" \ return message
f"AC {self.armor_class}\n" \

View file

@ -0,0 +1,3 @@
from .dndproficiencytype import DndProficiencyType
__all__ = ["DndProficiencyType"]

View file

@ -0,0 +1,11 @@
import enum
class DndProficiencyType(enum.Enum):
NONE = 0
HALF_PROFICIENCY = 0.5
FULL_PROFICIENCY = 1
EXPERTISE = 2
def __str__(self):
return str(self.value)