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:
commit
1174502290
10 changed files with 447 additions and 256 deletions
|
@ -4,4 +4,3 @@ from .commands import available_commands
|
|||
from .tables import available_tables
|
||||
|
||||
__all__ = ["commands", "tables", "available_commands", "available_tables"]
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ from .dndinfo import DndinfoCommand
|
|||
from .dndnew import DndnewCommand
|
||||
from .dndedit import DndeditCommand
|
||||
from .dndroll import DndrollCommand
|
||||
from .dndrolladv import DndrolladvCommand
|
||||
from .dndrolldis import DndrolldisCommand
|
||||
|
||||
# Enter the commands of your Pack here!
|
||||
available_commands = [
|
||||
|
@ -18,8 +16,6 @@ available_commands = [
|
|||
DndnewCommand,
|
||||
DndeditCommand,
|
||||
DndrollCommand,
|
||||
DndrolladvCommand,
|
||||
DndrolldisCommand,
|
||||
]
|
||||
|
||||
# Don't change this, it should automatically generate __all__
|
||||
|
|
|
@ -1,60 +1,35 @@
|
|||
import re
|
||||
from royalnet.commands import *
|
||||
from .dndnew import DndnewCommand
|
||||
from ..tables import DndCharacter, DndActiveCharacter
|
||||
|
||||
|
||||
class DndeditCommand(Command):
|
||||
class DndeditCommand(DndnewCommand):
|
||||
name: str = "dndedit"
|
||||
|
||||
description: str = "Edit the active DnD character."
|
||||
|
||||
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}
|
||||
|
||||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||
name, level, strength, dexterity, constitution, intelligence, wisdom, charisma, max_hp, armor_class = \
|
||||
args.match(r"([\w ]+\w)\s*"
|
||||
r"LV\s+(\d+)\s+"
|
||||
r"STR\s+(\d+)\s+"
|
||||
r"DEX\s+(\d+)\s+"
|
||||
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.")
|
||||
character_sheet = args.joined()
|
||||
|
||||
if character_sheet == "":
|
||||
await data.reply(self._syntax())
|
||||
return
|
||||
|
||||
author = await data.get_author(error_if_none=True)
|
||||
char = author.dnd_active_character.character
|
||||
char.name = name
|
||||
char.level = level
|
||||
char.strength = strength
|
||||
char.dexterity = dexterity
|
||||
char.constitution = constitution
|
||||
char.intelligence = intelligence
|
||||
char.wisdom = wisdom
|
||||
char.charisma = charisma
|
||||
char.max_hp = max_hp
|
||||
char.armor_class = armor_class
|
||||
data.session.add(char)
|
||||
if author.dnd_active_character is None:
|
||||
raise CommandError("You don't have an active character.")
|
||||
|
||||
char: DndCharacter = author.dnd_active_character.character
|
||||
|
||||
arguments = self._parse(character_sheet)
|
||||
for key in arguments:
|
||||
char.__setattr__(key, arguments[key])
|
||||
|
||||
await data.session_commit()
|
||||
|
||||
await data.reply(f"✅ Edit successful!")
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import re
|
||||
# noinspection PyUnresolvedReferences
|
||||
from royalnet.commands import *
|
||||
from ..tables import DndCharacter
|
||||
from ..utils import DndProficiencyType
|
||||
|
||||
|
||||
class DndnewCommand(Command):
|
||||
|
@ -10,51 +12,60 @@ class DndnewCommand(Command):
|
|||
|
||||
aliases = ["dn", "dndn", "new", "dnew"]
|
||||
|
||||
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}"
|
||||
syntax = "{name}\n{character_sheet}"
|
||||
|
||||
tables = {DndCharacter}
|
||||
|
||||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||
name, level, strength, dexterity, constitution, intelligence, wisdom, charisma, max_hp, armor_class = \
|
||||
args.match(r"([\w ]+\w)\s*"
|
||||
r"LV\s+(\d+)\s+"
|
||||
r"STR\s+(\d+)\s+"
|
||||
r"DEX\s+(\d+)\s+"
|
||||
r"COS\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
|
||||
def _search_value(self, name: str, string: str):
|
||||
return re.search(r"\s*" + name + r"\s*([0-9]+)\s*", string, re.IGNORECASE)
|
||||
|
||||
def _parse(self, character_sheet: str) -> dict:
|
||||
columns = list(self.alchemy.DndCharacter.__table__.columns)
|
||||
column_names = [column.name for column in columns if (not column.primary_key and
|
||||
not column.foreign_keys and
|
||||
column.name != "name")]
|
||||
arguments = {}
|
||||
for column_name in column_names:
|
||||
match = self._search_value(column_name, character_sheet)
|
||||
if match:
|
||||
if column_name.endswith("_proficiency"):
|
||||
arguments[column_name] = DndProficiencyType(float(match.group(1)))
|
||||
else:
|
||||
raise CommandError("Character names cannot be composed of only a number.")
|
||||
author = await data.get_author(error_if_none=True)
|
||||
char = self.alchemy.DndCharacter(name=name,
|
||||
level=level,
|
||||
strength=strength,
|
||||
dexterity=dexterity,
|
||||
constitution=constitution,
|
||||
intelligence=intelligence,
|
||||
wisdom=wisdom,
|
||||
charisma=charisma,
|
||||
max_hp=max_hp,
|
||||
armor_class=armor_class,
|
||||
creator=author)
|
||||
data.session.add(char)
|
||||
arguments[column_name] = match.group(1)
|
||||
return arguments
|
||||
|
||||
def _syntax(self) -> str:
|
||||
columns = list(self.alchemy.DndCharacter.__table__.columns)
|
||||
column_names = [column.name for column in columns if (not column.primary_key and
|
||||
not column.foreign_keys and
|
||||
column.name != "name")]
|
||||
message = "ℹ️ Character Sheet syntax:\n[p]\nName\n"
|
||||
for column_name in column_names:
|
||||
message += f"{column_name} _\n"
|
||||
message += "[/p]"
|
||||
return message
|
||||
|
||||
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.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!")
|
||||
|
|
|
@ -1,94 +1,146 @@
|
|||
import typing
|
||||
import re
|
||||
import random
|
||||
from royalnet.commands import *
|
||||
from royalnet.utils import plusformat
|
||||
from ..tables import DndCharacter, DndActiveCharacter
|
||||
from royalnet.utils import plusformat
|
||||
|
||||
|
||||
class DndrollCommand(Command):
|
||||
name: str = "dndroll"
|
||||
|
||||
description: str = "Roll as the active DnD character."
|
||||
description: str = "Roll dice as the active DnD character."
|
||||
|
||||
aliases = ["dr", "dndr", "droll"]
|
||||
|
||||
syntax = "{stat} [proficiency] [modifier]"
|
||||
aliases = ["dr", "dndr", "roll", "droll"]
|
||||
|
||||
tables = {DndCharacter, DndActiveCharacter}
|
||||
|
||||
@staticmethod
|
||||
def _roll():
|
||||
return random.randrange(1, 21)
|
||||
_skill_names = {
|
||||
"str": "strength",
|
||||
"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:
|
||||
author = await data.get_author(error_if_none=True)
|
||||
if author.dnd_active_character is None:
|
||||
raise CommandError("You don't have an active character.")
|
||||
char: DndCharacter = author.dnd_active_character.character
|
||||
stat: str = args[0]
|
||||
second: typing.Optional[str] = args.optional(1)
|
||||
third: typing.Optional[str] = args.optional(2)
|
||||
|
||||
first = args[0]
|
||||
second = args.optional(1)
|
||||
third = args.optional(2)
|
||||
|
||||
advantage = False
|
||||
disadvantage = False
|
||||
extra_modifier = 0
|
||||
|
||||
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:
|
||||
extra_mod: int = 0
|
||||
raise InvalidInputError("Invalid advantage string (second parameter).")
|
||||
|
||||
if second:
|
||||
if second.startswith("e") or second.startswith("x"):
|
||||
proficiency_mul: float = 2.0
|
||||
proficiency_name: str = " with Expertise"
|
||||
elif second.startswith("f") or second.startswith("n") or second.startswith("c"):
|
||||
proficiency_mul: float = 1.0
|
||||
proficiency_name: str = " with Proficiency"
|
||||
elif second.startswith("h") or second == "/" or second.startswith("m"):
|
||||
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]"
|
||||
elif second:
|
||||
try:
|
||||
extra_modifier = int(second)
|
||||
except ValueError:
|
||||
if second.startswith("a") or second.startswith("v"):
|
||||
advantage = True
|
||||
elif second.startswith("d") or second.startswith("d"):
|
||||
disadvantage = True
|
||||
else:
|
||||
raise CommandError(f"Unknown proficiency type '{second}'")
|
||||
proficiency_mod: int = int(char.proficiency_bonus * proficiency_mul)
|
||||
raise InvalidInputError("Invalid modifier value or advantage string (second parameter).")
|
||||
|
||||
skill_short_name = first
|
||||
for root in self._skill_names:
|
||||
if skill_short_name.startswith(root):
|
||||
skill_name = self._skill_names[root]
|
||||
break
|
||||
else:
|
||||
proficiency_name: str = ""
|
||||
proficiency_mod: int = 0
|
||||
raise CommandError("Invalid skill name (first parameter).")
|
||||
|
||||
if stat.startswith("st") or stat.startswith("fo"):
|
||||
stat_mod: int = char.strength_mod
|
||||
stat_name: str = "[i]STR[/i]"
|
||||
elif stat.startswith("de"):
|
||||
stat_mod: int = char.dexterity_mod
|
||||
stat_name: str = "[i]DEX[/i]"
|
||||
elif stat.startswith("co"):
|
||||
stat_mod: int = char.constitution_mod
|
||||
stat_name: str = "[i]CON[/i]"
|
||||
elif stat.startswith("in"):
|
||||
stat_mod: int = char.intelligence_mod
|
||||
stat_name: str = "[i]INT[/i]"
|
||||
elif stat.startswith("wi") or stat.startswith("sa"):
|
||||
stat_mod: int = char.wisdom_mod
|
||||
stat_name: str = "[i]WIS[/i]"
|
||||
elif stat.startswith("ch") or stat.startswith("ca"):
|
||||
stat_mod: int = char.charisma_mod
|
||||
stat_name: str = "[i]CHA[/i]"
|
||||
skill_modifier = char.__getattribute__(skill_name)
|
||||
modifier = skill_modifier + extra_modifier
|
||||
modifier_str = plusformat(modifier, empty_if_zero=True)
|
||||
|
||||
if advantage:
|
||||
roll_a = random.randrange(1, 21)
|
||||
roll_b = random.randrange(1, 21)
|
||||
roll = max([roll_a, roll_b])
|
||||
total = roll + modifier
|
||||
await data.reply(f"🎲 2d20h1{modifier_str} = ({roll_a}|{roll_b}){modifier_str} = [b]{total}[/b]")
|
||||
elif disadvantage:
|
||||
roll_a = random.randrange(1, 21)
|
||||
roll_b = random.randrange(1, 21)
|
||||
roll = min([roll_a, roll_b])
|
||||
total = roll + modifier
|
||||
await data.reply(f"🎲 2d20l1{modifier_str} = ({roll_a}|{roll_b}){modifier_str} = [b]{total}[/b]")
|
||||
else:
|
||||
raise CommandError(f"Unknown stat '{stat}'")
|
||||
|
||||
total_mod = stat_mod + proficiency_mod + extra_mod
|
||||
|
||||
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]")
|
||||
roll = random.randrange(1, 21)
|
||||
total = roll + modifier
|
||||
await data.reply(f"🎲 1d20{modifier_str} = {roll}{modifier_str} = [b]{total}[/b]")
|
||||
|
|
|
@ -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"
|
|
@ -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"
|
|
@ -1,6 +1,7 @@
|
|||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import *
|
||||
from sqlalchemy.ext.declarative import *
|
||||
from ..utils import DndProficiencyType
|
||||
|
||||
|
||||
class DndCharacter:
|
||||
|
@ -20,71 +21,267 @@ class DndCharacter:
|
|||
|
||||
@declared_attr
|
||||
def name(self):
|
||||
return Column(String)
|
||||
return Column(String, nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def strength_score(self):
|
||||
return Column(Integer, nullable=False)
|
||||
|
||||
@property
|
||||
def strength(self):
|
||||
return Column(Integer)
|
||||
|
||||
@property
|
||||
def strength_mod(self):
|
||||
return (self.strength - 10) // 2
|
||||
return (self.strength_score - 10) // 2
|
||||
|
||||
@declared_attr
|
||||
def dexterity_score(self):
|
||||
return Column(Integer, nullable=False)
|
||||
|
||||
@property
|
||||
def dexterity(self):
|
||||
return Column(Integer)
|
||||
|
||||
@property
|
||||
def dexterity_mod(self):
|
||||
return (self.dexterity - 10) // 2
|
||||
return (self.dexterity_score - 10) // 2
|
||||
|
||||
@declared_attr
|
||||
def constitution_score(self):
|
||||
return Column(Integer, nullable=False)
|
||||
|
||||
@property
|
||||
def constitution(self):
|
||||
return Column(Integer)
|
||||
|
||||
@property
|
||||
def constitution_mod(self):
|
||||
return (self.constitution - 10) // 2
|
||||
return (self.constitution_score - 10) // 2
|
||||
|
||||
@declared_attr
|
||||
def intelligence_score(self):
|
||||
return Column(Integer, nullable=False)
|
||||
|
||||
@property
|
||||
def intelligence(self):
|
||||
return Column(Integer)
|
||||
|
||||
@property
|
||||
def intelligence_mod(self):
|
||||
return (self.intelligence - 10) // 2
|
||||
return (self.intelligence_score - 10) // 2
|
||||
|
||||
@declared_attr
|
||||
def wisdom_score(self):
|
||||
return Column(Integer, nullable=False)
|
||||
|
||||
@property
|
||||
def wisdom(self):
|
||||
return Column(Integer)
|
||||
|
||||
@property
|
||||
def wisdom_mod(self):
|
||||
return (self.wisdom - 10) // 2
|
||||
return (self.wisdom_score - 10) // 2
|
||||
|
||||
@declared_attr
|
||||
def charisma(self):
|
||||
return Column(Integer)
|
||||
def charisma_score(self):
|
||||
return Column(Integer, nullable=False)
|
||||
|
||||
@property
|
||||
def charisma_mod(self):
|
||||
return (self.charisma - 10) // 2
|
||||
def charisma(self):
|
||||
return (self.charisma_score - 10) // 2
|
||||
|
||||
@declared_attr
|
||||
def level(self):
|
||||
return Column(Integer)
|
||||
return Column(Integer, nullable=False)
|
||||
|
||||
@property
|
||||
def proficiency_bonus(self):
|
||||
return ((self.level - 1) // 4) + 2
|
||||
|
||||
@declared_attr
|
||||
def current_hp(self):
|
||||
return Column(Integer, nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def max_hp(self):
|
||||
return Column(Integer)
|
||||
return Column(Integer, nullable=False)
|
||||
|
||||
@declared_attr
|
||||
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):
|
||||
return f"<{self.__class__.__qualname__} {self.name}>"
|
||||
|
@ -92,14 +289,13 @@ class DndCharacter:
|
|||
def __str__(self):
|
||||
return f"{self.name}"
|
||||
|
||||
def character_sheet(self):
|
||||
return f"{self.name}\n" \
|
||||
f"LV {self.level}\n\n" \
|
||||
f"STR {self.strength}\n" \
|
||||
f"DEX {self.dexterity}\n" \
|
||||
f"CON {self.constitution}\n" \
|
||||
f"INT {self.intelligence}\n" \
|
||||
f"WIS {self.wisdom}\n" \
|
||||
f"CHA {self.charisma}\n\n" \
|
||||
f"MAXHP {self.max_hp}\n" \
|
||||
f"AC {self.armor_class}\n" \
|
||||
def character_sheet(self) -> str:
|
||||
columns = list(self.__class__.__table__.columns)
|
||||
column_names = [column.name for column in columns if (not column.primary_key and
|
||||
not column.foreign_keys and
|
||||
column.name != "name")]
|
||||
message = f"[b]{self.name}[/b]\n"
|
||||
for column_name in column_names:
|
||||
value = self.__getattribute__(column_name)
|
||||
message += f"{column_name} {value}\n"
|
||||
return message
|
||||
|
|
3
royalnet/packs/rpg/utils/__init__.py
Normal file
3
royalnet/packs/rpg/utils/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from .dndproficiencytype import DndProficiencyType
|
||||
|
||||
__all__ = ["DndProficiencyType"]
|
11
royalnet/packs/rpg/utils/dndproficiencytype.py
Normal file
11
royalnet/packs/rpg/utils/dndproficiencytype.py
Normal 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)
|
Loading…
Reference in a new issue