adding support for managing class attributes
This commit is contained in:
+21
-10
@@ -53,16 +53,16 @@ data = {
|
||||
],
|
||||
|
||||
'AncestryTrait': [
|
||||
{ 'id': 1, 'name': '+1 to All Ability Scores', },
|
||||
{ 'id': 2, 'name': 'Breath Weapon', },
|
||||
{ 'id': 3, 'name': 'Darkvision', },
|
||||
{'id': 1, 'name': '+1 to All Ability Scores', },
|
||||
{'id': 2, 'name': 'Breath Weapon', },
|
||||
{'id': 3, 'name': 'Darkvision', },
|
||||
],
|
||||
|
||||
'AncestryTraitMap': [
|
||||
{ 'ancestry_id': 1, 'ancestry_trait_id': 1, 'level': 1}, # human +1 to scores
|
||||
{ 'ancestry_id': 2, 'ancestry_trait_id': 2, 'level': 1}, # dragonborn breath weapon
|
||||
{ 'ancestry_id': 3, 'ancestry_trait_id': 3, 'level': 1}, # tiefling darkvision
|
||||
{ 'ancestry_id': 2, 'ancestry_trait_id': 2, 'level': 1}, # elf darkvision
|
||||
{'ancestry_id': 1, 'ancestry_trait_id': 1, 'level': 1}, # human +1 to scores
|
||||
{'ancestry_id': 2, 'ancestry_trait_id': 2, 'level': 1}, # dragonborn breath weapon
|
||||
{'ancestry_id': 3, 'ancestry_trait_id': 3, 'level': 1}, # tiefling darkvision
|
||||
{'ancestry_id': 2, 'ancestry_trait_id': 2, 'level': 1}, # elf darkvision
|
||||
],
|
||||
|
||||
'CharacterClassMap': [
|
||||
@@ -101,15 +101,26 @@ data = {
|
||||
],
|
||||
|
||||
'ClassAttribute': [
|
||||
{'id': 1, 'name': 'Fighting Style', 'value': 'Archery'},
|
||||
{'id': 1, 'name': 'Fighting Style'},
|
||||
{'id': 2, 'name': 'Another Attribute'},
|
||||
],
|
||||
|
||||
'ClassAttributeOption': [
|
||||
{'id': 1, 'attribute_id': 1, 'name': 'Archery'},
|
||||
{'id': 2, 'attribute_id': 1, 'name': 'Battlemaster'},
|
||||
{'id': 3, 'attribute_id': 2, 'name': 'Another Option 1'},
|
||||
{'id': 4, 'attribute_id': 2, 'name': 'Another Option 2'},
|
||||
],
|
||||
|
||||
|
||||
'ClassAttributeMap': [
|
||||
{'class_attribute_id': 1, 'character_class_id': 1, 'level': 2}, # Fighter: Archery fighting style
|
||||
{'class_attribute_id': 1, 'character_class_id': 1, 'level': 2}, # Fighter: Fighting Style
|
||||
{'class_attribute_id': 2, 'character_class_id': 1, 'level': 1}, # Fighter: Another Attr
|
||||
],
|
||||
|
||||
'CharacterClassAttributeMap': [
|
||||
{'class_attribute_id': 1, 'character_id': 1}, # Sabetha: Archery fighting style
|
||||
{'character_id': 1, 'class_attribute_id': 2, 'option_id': 4}, # Sabetha, another option, option 2
|
||||
{'character_id': 1, 'class_attribute_id': 1, 'option_id': 1}, # Sabetha, fighting style, archery
|
||||
],
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import logging
|
||||
|
||||
|
||||
from ttfrog.db.base import Bases, BaseObject, IterableMixin, SavingThrowsMixin, SkillsMixin
|
||||
from ttfrog.db.base import CreatureTypesEnum
|
||||
|
||||
@@ -24,11 +21,17 @@ __all__ = [
|
||||
'Character',
|
||||
]
|
||||
|
||||
|
||||
def class_map_creator(fields):
|
||||
if isinstance(fields, CharacterClassMap):
|
||||
return fields
|
||||
return CharacterClassMap(**fields)
|
||||
|
||||
def attr_map_creator(fields):
|
||||
if isinstance(fields, CharacterClassAttributeMap):
|
||||
return fields
|
||||
return CharacterClassAttributeMap(**fields)
|
||||
|
||||
|
||||
class AncestryTraitMap(BaseObject):
|
||||
__tablename__ = "trait_map"
|
||||
@@ -62,7 +65,7 @@ class AncestryTrait(BaseObject, IterableMixin):
|
||||
description = Column(Text)
|
||||
|
||||
|
||||
class CharacterClassMap(BaseObject):
|
||||
class CharacterClassMap(BaseObject, IterableMixin):
|
||||
__tablename__ = "class_map"
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
character_id = Column(Integer, ForeignKey("character.id"))
|
||||
@@ -73,11 +76,16 @@ class CharacterClassMap(BaseObject):
|
||||
level = Column(Integer, nullable=False, info={'min': 1, 'max': 20}, default=1)
|
||||
|
||||
|
||||
class CharacterClassAttributeMap(BaseObject):
|
||||
class CharacterClassAttributeMap(BaseObject, IterableMixin):
|
||||
__tablename__ = "character_class_attribute_map"
|
||||
class_attribute_id = Column(Integer, ForeignKey("class_attribute.id"), primary_key=True)
|
||||
character_id = Column(Integer, ForeignKey("character.id"), primary_key=True)
|
||||
attribute = relationship("ClassAttribute", lazy='immediate')
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
character_id = Column(Integer, ForeignKey("character.id"), nullable=False)
|
||||
class_attribute_id = Column(Integer, ForeignKey("class_attribute.id"), nullable=False)
|
||||
option_id = Column(Integer, ForeignKey("class_attribute_option.id"), nullable=False)
|
||||
mapping = UniqueConstraint(character_id, class_attribute_id)
|
||||
|
||||
class_attribute = relationship("ClassAttribute", lazy='immediate')
|
||||
option = relationship("ClassAttributeOption", lazy='immediate')
|
||||
|
||||
|
||||
class Character(*Bases, SavingThrowsMixin, SkillsMixin):
|
||||
@@ -100,7 +108,8 @@ class Character(*Bases, SavingThrowsMixin, SkillsMixin):
|
||||
class_map = relationship("CharacterClassMap", cascade='all,delete,delete-orphan')
|
||||
classes = association_proxy('class_map', 'id', creator=class_map_creator)
|
||||
|
||||
attributes = relationship("CharacterClassAttributeMap")
|
||||
character_class_attribute_map = relationship("CharacterClassAttributeMap", cascade='all,delete,delete-orphan')
|
||||
class_attributes = association_proxy('character_class_attribute_map', 'id', creator=attr_map_creator)
|
||||
|
||||
ancestry_id = Column(Integer, ForeignKey("ancestry.id"), nullable=False, default='1')
|
||||
ancestry = relationship("Ancestry", uselist=False)
|
||||
|
||||
@@ -13,15 +13,15 @@ from sqlalchemy.orm import relationship
|
||||
__all__ = [
|
||||
'ClassAttributeMap',
|
||||
'ClassAttribute',
|
||||
'ClassAttributeOption',
|
||||
'CharacterClass',
|
||||
]
|
||||
|
||||
|
||||
class ClassAttributeMap(BaseObject):
|
||||
class ClassAttributeMap(BaseObject, IterableMixin):
|
||||
__tablename__ = "class_attribute_map"
|
||||
class_attribute_id = Column(Integer, ForeignKey("class_attribute.id"), primary_key=True)
|
||||
character_class_id = Column(Integer, ForeignKey("character_class.id"), primary_key=True)
|
||||
attribute = relationship("ClassAttribute", lazy='immediate')
|
||||
level = Column(Integer, nullable=False, info={'min': 1, 'max': 20}, default=1)
|
||||
|
||||
|
||||
@@ -29,8 +29,17 @@ class ClassAttribute(BaseObject, IterableMixin):
|
||||
__tablename__ = "class_attribute"
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name = Column(String, nullable=False)
|
||||
value = Column(String, nullable=False)
|
||||
description = Column(Text)
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.id}: {self.name}"
|
||||
|
||||
|
||||
class ClassAttributeOption(BaseObject, IterableMixin):
|
||||
__tablename__ = "class_attribute_option"
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name = Column(String, nullable=False)
|
||||
attribute_id = Column(Integer, ForeignKey("class_attribute.id"), nullable=False)
|
||||
# attribute = relationship("ClassAttribute", uselist=False)
|
||||
|
||||
|
||||
class CharacterClass(*Bases, SavingThrowsMixin, SkillsMixin):
|
||||
|
||||
Reference in New Issue
Block a user