from django.db import models from polymorphic.models import PolymorphicModel import multiselectfield from random import randint from math import ceil #==============================================================================# #-------------------------------- OPTION LISTS --------------------------------# #==============================================================================# ATTRIBUTES = [ ( "Physical", ( ("Strength", "Strength"), ("Dexterity", "Dexterity"), ("Stamina", "Stamina"), ), ), ( "Social", ( ("Charisma", "Charisma"), ("Manipulation", "Manipulation"), ("Appearance", "Appearance"), ), ), ( "Mental", ( ("Perception", "Perception"), ("Intelligence", "Intelligence"), ("Wits", "Wits"), ), ), ] ABILITIES = [ ( "War", ( ("Archery", "Archery"), ("Athletics", "Athletics"), ("Awareness", "Awareness"), ("Brawl", "Brawl"), ("Dodge", "Dodge"), ("Integrity", "Integrity"), ("Melee", "Melee"), ("Resistance", "Resistance"), ("Thrown", "Thrown"), ("War", "War"), ), ), ( "Life", ( ("Craft", "Craft"), ("Larceny", "Larceny"), ("Linguistics", "Linguistics"), ("Performance", "Performance"), ("Presence", "Presence"), ("Ride", "Ride"), ("Sail", "Sail"), ("Socialise", "Socialise"), ("Stealth", "Stealth"), ("Survival", "Survival"), ), ), ( "Wisdom", ( ("Bureaucracy", "Bureaucracy"), ("Investigation", "Investigation"), ("Lore", "Lore"), ("Medicine", "Medicine"), ("Occult", "Occult"), ), ), ] ATTRIBUTE_TYPES = [ ("Physical", "Physical"), ("Social", "Social"), ("Mental", "Mental"), ] ABILITY_TYPES = [ ("War", "War"), ("Life", "Life"), ("Wisdom", "Wisdom"), ("Additional", "Additional") ] STATICS = [ ("Natural Soak", "Natural Soak"), ("Armored Soak", "Armored Soak"), ("Total Soak", "Total Soak"), ("Hardness", "Hardness"), ("Parry", "Parry"), ("Evasion", "Evasion"), ("Resolve", "Resolve"), ("Guile", "Guile"), ("Rush", "Rush"), ("Disengage", "Disengage"), ("Join Battle", "Join Battle"), ] CATEGORIES = [ ("Light", "Light"), ("Medium", "Medium"), ("Heavy", "Heavy"), ] TAGS_WEAPONS = [ ( "General", ( ("One Handed", "One Handed"), ("Two Handed", "Two Handed"), ("Bashing", "Bashing"), ("Concealable", "Concealable"), ("Lethal", "Lethal"), ("Mounted", "Mounted"), ("Piercing", "Piercing"), ("Special", "Special"), ), ), ( "Melee", ( ("Melee", "Melee"), ("Balanced", "Balanced"), ("Brawl", "Brawl"), ("Chopping", "Chopping"), ("Disarming", "Disarming"), ("Flexible", "Flexible"), ("Improvised", "Improvised"), ("Grappling", "Grappling"), ("Martial Arts", "Martial Arts"), ("Natural", "Natural"), ("Reaching", "Reaching"), ("Shield", "Shield"), ("Smashing", "Smashing"), ("Worn", "Worn"), ), ), ( "Thrown", ( ("Thrown", "Thrown"), ("Occult", "Occult"), ("Cutting", "Cutting"), ("Poisonable", "Poisonable"), ("Subtle", "Subtle"), ), ), ( "Archery", ( ("Archery", "Archery"), ("Crossbow", "Crossbow"), ("Flame", "Flame"), ("Powerful", "Powerful"), ("Slow", "Slow"), ), ), ] TAGS_ARMOR = [ ("Buoyant", "Buoyant"), ("Concealable", "Concealable"), ("Silent", "Silent"), ] INTENSITIES = [ ("Minor", "Minor"), ("Major", "Major"), ("Defining", "Defining"), ] DIE_TYPES = [ ("None", "None"), ("Success", "Success"), ("Double", "Double"), ("Exploding / Disappearing", "Exploding / Disappearing"), ("Subtracting", "Subtracting") ] CHARM_TYPES = [ ("Permanent", "Permanent"), ("Simple", "Simple"), ("Reflexive", "Reflexive"), ("Suplemental", "Suplemental"), ] CHARM_DURATIONS = [ ("", ""), ("One Round", "One Round"), ("One Scene", "One Scene"), ("Indefinite", "Indefinite"), ] CHARM_KEYWORDS = [ ( "Charms", ( ("Advantage", "Advantage"), ("Attack-Action", "Attack-Action"), ("Counterattack", "Counterattack"), ("Form", "Form"), ("Group", "Group"), ("Mute", "Mute"), ("Perilous", "Perilous"), ("Once Per Scene", "Once Per Scene"), ("Once Per Day", "Once Per Day"), ("Once Per Story", "Once Per Story"), ("Once Per Season", "Once Per Season"), ("Pilot", "Pilot"), ("Post-Roll", "Post-Roll"), ("Psyche", "Psyche"), ("Quickshot", "Quickshot"), ) ), ( "Evocations", ( ("Dissonant", "Dissonant"), ("Resonant", "Resonant"), ) ), ] CASTES_SOLAR = [ ("Dawn", "Dawn"), ("Zenith", "Zenith"), ("Twilight", "Twilight"), ("Night", "Night"), ("Eclipse", "Eclipse"), ] CASTES_LUNAR = [ ("Full Moon", "Full Moon"), ("Changing Moon", "Changing Moon"), ("No Moon", "No Moon"), ("Castless", "Castless") ] SHAPE_SIZES = [ ("Normal", "Normal"), ] SHAPE_TYPES = [ ("Human", "Human"), ("Animal", "Animal"), ] #==============================================================================# #------------------------------- CUSTOM MODELS --------------------------------# #==============================================================================# class NameField(models.CharField): def __init__(self, *args, **kwargs): kwargs['verbose_name'] = "Name" kwargs['blank'] = False kwargs['max_length'] = 100 super().__init__(*args, **kwargs) class DescriptionField(models.TextField): def __init__(self, *args, **kwargs): kwargs['verbose_name'] = "Description" kwargs['blank'] = True kwargs['max_length'] = 1000 super().__init__(*args, **kwargs) class DotField(models.IntegerField): def __init__(self, verbose_name, *args, **kwargs): kwargs['verbose_name'] = verbose_name kwargs['blank'] = False kwargs['default'] = 0 super().__init__(*args, **kwargs) class SingleChoiceField(models.CharField): def __init__(self, verbose_name, choices, *args, **kwargs): kwargs['verbose_name'] = verbose_name kwargs['choices'] = choices kwargs['blank'] = True kwargs['max_length'] = 100 super().__init__(*args, **kwargs) class MultiChoiceField(multiselectfield.MultiSelectField): def __init__(self, verbose_name, choices, *args, **kwargs): kwargs['verbose_name'] = verbose_name kwargs['choices'] = choices kwargs['blank'] = True kwargs['max_length'] = 100 super().__init__(*args, **kwargs) class NamedIntegerField(models.IntegerField): def __init__(self, verbose_name, desc=None, *args, **kwargs): kwargs['verbose_name'] = verbose_name kwargs['help_text'] = desc kwargs['blank'] = False kwargs['default'] = 0 super().__init__(*args, **kwargs) class NamedCharField(models.CharField): def __init__(self, verbose_name, *args, **kwargs): kwargs['verbose_name'] = verbose_name kwargs['blank'] = False kwargs['max_length'] = 100 super().__init__(*args, **kwargs) class DieField(multiselectfield.MultiSelectField): def __init__(self, verbose_name, number, default, *args, **kwargs): self.number = number kwargs['verbose_name'] = verbose_name kwargs['default'] = default kwargs['choices'] = DIE_TYPES kwargs['blank'] = False kwargs['max_length'] = 100 super().__init__(*args, **kwargs) def deconstruct(self): name, path, args, kwargs = super().deconstruct() kwargs['number'] = self.number return name, path, args, kwargs class NamedBooleanField(models.BooleanField): def __init__(self, verbose_name, default=False, *args, **kwargs): kwargs['verbose_name'] = verbose_name kwargs['default'] = default kwargs['blank'] = False super().__init__(*args, **kwargs) class NamedForeignKeyField(models.ForeignKey): def __init__(self, verbose_name, *args, **kwargs): kwargs['verbose_name'] = verbose_name kwargs['on_delete'] = models.CASCADE kwargs['blank'] = True kwargs['null'] = True super().__init__(*args, **kwargs) class NamedManyToManyField(models.ManyToManyField): def __init__(self, verbose_name, *args, **kwargs): kwargs['verbose_name'] = verbose_name kwargs['blank'] = True super().__init__(*args, **kwargs) class NamedOneToOneField(models.OneToOneField): def __init__(self, verbose_name, *args, **kwargs): kwargs['verbose_name'] = verbose_name kwargs['on_delete'] = models.CASCADE kwargs['blank'] = True kwargs['null'] = True super().__init__(*args, **kwargs) #==============================================================================# #-------------------------------- DICE ROLLING --------------------------------# #==============================================================================# class RollConfiguration(PolymorphicModel): def __str__(self): return self.name name = NameField() successesAuto = NamedIntegerField("Auto-Successes") r01 = DieField("1s", 1, ["NONE"]) r02 = DieField("2s", 2, ["NONE"]) r03 = DieField("3s", 3, ["NONE"]) r04 = DieField("4s", 4, ["NONE"]) r05 = DieField("5s", 5, ["NONE"]) r06 = DieField("6s", 6, ["NONE"]) r07 = DieField("7s", 7, ["SUCCESS"]) r08 = DieField("8s", 8, ["SUCCESS"]) r09 = DieField("9s", 9, ["SUCCESS"]) r10 = DieField("10s", 10, ["SUCCESS", "DOUBLE"]) def roll(self, pool=1, successesStunt=0): listDice = [ self.r01, self.r02, self.r03, self.r04, self.r05, self.r06, self.r07, self.r08, self.r09, self.r10, ] listSuccess, listDouble, listExplodingDisappearing, listSubtracting = [], [], [], [] for die in listDice: if "SUCCESS" in die: listSuccess.append(die.number) if "DOUBLE" in die: listDouble.append(die.number) if "EXPLODING_DISAPPEARING" in die: listExplodingDisappearing.append(die.number) if "SUBTRACTING" in die: listSubtracting.append(die.number) successes = self.successesAuto + successesStunt listExploded, listDisappeared = [], [] listRoll = [0 for die in range(pool)] while 0 in listRoll: for die in listRoll: if die == 0: die = randint(1, 10) if die in listExplodingDisappearing: if die in listSuccess: listExploded.append(die) else: listDisappeared.append(die) die = 0 for die in listRoll + listExploded: if die in listSuccess: successes += 1 if die in listDouble: successes += 1 if die in listSubtracting: successes -= 1 if successes < 0: successes = 0 botch = (successes == 0) and (1 in listRoll) return successes, botch, listRoll, listExploded, listDisappeared #==============================================================================# #--------------------------------- PROPERTIES ---------------------------------# #==============================================================================# class PropertyBase(PolymorphicModel): name = NameField() description = DescriptionField() class PropertyAttribute(PropertyBase): propertyType = SingleChoiceField("Type", ATTRIBUTE_TYPES) core = NamedBooleanField("Core?") class PropertyAbility(PropertyBase): propertyType = SingleChoiceField("Type", ABILITY_TYPES) class PropertyStatic(PropertyBase): propertyType = None #==============================================================================# #--------------------------------- MODIFIERS ----------------------------------# #==============================================================================# class ModifierBase(PolymorphicModel): value = NamedIntegerField("Modifier Value") class ModifierAttribute(ModifierBase): def __str__(self): return "{} [{}]".format(self.keyword, self.value) keyword = SingleChoiceField("Attribute", ATTRIBUTES) class ModifierAbility(ModifierBase): def __str__(self): return "{} [{}]".format(self.keyword, self.value) keyword = SingleChoiceField("Ability", ABILITIES) class ModifierStatic(ModifierBase): def __str__(self): return "{} [{}]".format(self.keyword, self.value) keyword = SingleChoiceField("Static", STATICS) #==============================================================================# #--------------------------------- CHARACTERS ---------------------------------# #==============================================================================# class CharacterBase(PolymorphicModel): def __str__(self): return self.name #======== MODIFIER METHODS ========# def effectModifier(self, PropertyBase): modifier = 0 try: ownerships = [ownership for ownership in ownershipBase.objects.all() if (ownership.owner == self) and (ownership.active)] for ownership in ownerships: try: modifier += ownership.target.modifier(keyword) except: pass except: pass return modifier #============ GENERAL =============# name = NameField() player = models.CharField(verbose_name="Player", max_length=100, blank=True) concept = models.TextField(blank=True) #=========== ATTRIBUTES ===========# # Reverse Reference def attributeSet(self): try: return [ownership.target for ownership in self.OwnershipPropertyAttribute_set.all()] except: return None #=========== ABILITIES ============# # Reverse Reference def abilitySet(self): output = [] try: ownerships = self.ownershipPropertyAbility_set.order_by("target__name") output.append(("War", [ownership for ownership in ownerships if ownership.target.propertyType=="War"])) output.append(("Life", [ownership for ownership in ownerships if ownership.target.propertyType=="Life"])) output.append(("Wisdom", [ownership for ownership in ownerships if ownership.target.propertyType=="Wisdom"])) output.append(("Additional", [ownership for ownership in ownerships if ownership.target.propertyType=="Additional"])) except: output.append(("War", [])) output.append(("Life", [])) output.append(("Wisdom", [])) output.append(("Additional", [])) return output #============= MERITS =============# # Reverse relation def meritSet(self): output = [] try: ownerships = self.ownershipMerit_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output #========== SPECIALITIES ==========# # Reverse relation def specialitySet(self): output = [] try: ownerships = self.ownershipSpeciality_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output #=========== INTIMACIES ===========# # Reverse relation # character.intimactBase_set.all() # character.intimacyTie_set.object.all() # character.intimacyPrincipal_set.all() #=========== WILLPOWER ============# willpowerMax = NamedIntegerField("Maximum Willpower") willpower = NamedIntegerField("Current Willpower") def dotsTriWillpower(self): output = [0 for i in range(10)] for i in range(10): if i < self.willpowerMax and i >= self.willpower: output[i] = 1 elif i < self.willpower: output[i] = 2 return output #=========== EXPERIENCE ===========# experienceTotal = NamedIntegerField("Total Experience") experience = NamedIntegerField("Current Experience") #============ WEAPONS =============# # Reverse relation def itemWeaponSet(self): output = [] try: ownerships = self.ownershipItemWeapon_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output #============= ARMOR ==============# # Reverse relation def itemArmorSet(self): output = [] try: ownerships = self.ownershipItemArmor_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output def armorSoak(self): armor = None modifier = 0 try: armor = self.itemArmorSet().filter(equipped=True) except: pass if armor: for item in armor: modifier += item.soak return modifier def armorHardness(self): armor = None modifier = 0 try: armor = self.itemArmorSet().filter(equipped=True) except: pass if armor: for item in armor: modifier += item.hardness return modifier def armorMobilityPenalty(self): armor = None modifier = 0 try: armor = self.itemArmorSet().filter(equipped=True) except: pass if armor: for item in armor: modifier += item.mobilityPenalty return modifier #============= ITEMS ==============# # Reverse relation def itemSet(self): output = [] try: ownerships = self.ownershipItem_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output #============ ESSENCE =============# essence = NamedIntegerField("Essence") def dotsEssence(self): output = [] for i in range(self.essence): output.append(True) for i in range(5 - self.essence): output.append(False) return output #============= HEALTH =============# health0 = NamedIntegerField("'-0' Health Levels") health1 = NamedIntegerField("'-1' Health Levels") health2 = NamedIntegerField("'-2' Health Levels") healthIndex = NamedIntegerField("Health Track Index") def healthTrack(self): return ["Healthy"] + ["-0" for i in range(self.health0)] + ["-1" for i in range(self.health1)] + ["-1" for i in range(self.health1)] + ["-4", "i"] def healthLevel(self): return self.healthTrack()[self.healthIndex] def healthDots(self): output = [] for i in range(len(self.healthTrack()) - 1): output.append((self.healthTrack()[i+1], i < self.healthIndex)) return output #============ STATICS =============# # def resolve(self, speciality=None, mod=0): # return mod + ceil((self.attributeWits() + self.abilityIntegrity()) / 2) + self.effectModifier("RESOLVE") # # def guile(self, speciality=None, mod=0): # return mod + ceil((self.attributeManipulation() + self.abilitySocialize()) / 2) + self.effectModifier("GUILE") # # def soakNatural(self, mod=0): # return mod + self.attributeStamina() + self.effectModifier("SOAK NATURAL") # # def soakArmored(self, mod=0): # return mod + self.armorSoak() # # def soakTotal(self, mod=0): # return mod + self.soakNatural() + self.soakArmored() # # def hardness(self, mod=0): # return mod + self.armorHardness() + self.effectModifier("HARDNESS") # # def joinBattle(self, mod=0): # return mod + self.attributeWits() + self.abilityAwareness() + 3 + self.effectModifier("JOIN BATTLE") # # def evasion(self, mod=0): # return mod + ceil((self.attributeDexterity() + self.abilityDodge()) / 2) - self.armorMobilityPenalty() + self.effectModifier("EVASION") # # def rush(self, mod=0): # return mod + self.attributeDexterity() + self.abilityAthletics() + self.effectModifier("RUSH") # # def disengage(self, mod=0): # return mod + self.attributeDexterity() + self.abilityDodge() + self.effectModifier("DISENGAGE") class CharacterMortal(CharacterBase): def type(self): return "Mortal" class CharacterExaltBase(CharacterBase): anima = models.CharField(verbose_name="Anima", max_length=100) #============= MOTES ==============# motesPersonalMax = NamedIntegerField("Maximum Personal Motes") motesPersonal = NamedIntegerField("Current Personal Motes") motesPeripheralMax = NamedIntegerField("Maximum Peripheral Motes") motesPeripheral = NamedIntegerField("Current Peripheral Motes") motesCommitted = NamedIntegerField("Committed Motes") #============= LIMIT ==============# limitTrigger = models.TextField(verbose_name="Limit Trigger", blank="False", max_length=1000) limitBreak = NamedIntegerField("Limit Break") def dotsLimit(self): output = [False for i in range(10)] for i in range(10): output[i] = i < self.limitBreak return output #======= EXALTED EXPERIENCE =======# experienceExaltedTotal = NamedIntegerField("Total Exalted Experience") experienceExalted = NamedIntegerField("Current Exalted Experience") #========== MARTIAL ARTS ==========# # Reverse relation def martialArtSet(self): output = [] try: ownerships = self.ownershipCharmMartialArt_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output #=========== EVOCATIONS ===========# # Reverse relation def evocationSet(self): output = [] try: ownerships = self.ownershipCharmEvocation_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output class CharacterExaltSolar(CharacterExaltBase): def type(self): return "Solar Exalt" caste = SingleChoiceField("Solar Caste", CASTES_SOLAR) #============= CHARMS =============# # Reverse relation def charmSet(self): output = [] try: ownerships = self.ownershipCharmSolar_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output #======= SUPERNAL & FAVORED =======# abilitySupernal = SingleChoiceField("Supernal Ability", ABILITIES) abilityFavored = MultiChoiceField("Favoured Abilities", ABILITIES) class CharacterExaltLunar(CharacterExaltBase): def type(self): return "Lunar Exalt" caste = SingleChoiceField("Lunar Caste", CASTES_LUNAR) #========= SHAPESHIFTING ==========# spiritShape = models.CharField(verbose_name="Spirit Shape", max_length=100) # Reverse relation def lunarShapeSet(self): output = [] try: ownerships = self.ownershipCharmLunarShape_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output #============= CHARMS =============# # Reverse relation def charmSet(self): output = [] try: ownerships = self.ownershipCharmLunar_set.all() for ownership in ownerships: output.append(ownership.target) except: pass return output #============ FAVORED =============# attributeFavored = MultiChoiceField("Favoured Attributes", ATTRIBUTES) #==============================================================================# #----------------------------------- ITEMS ------------------------------------# #==============================================================================# class ItemBase(PolymorphicModel): def __str__(self): return self.name name = NameField() description = DescriptionField() class Item(ItemBase): pass #==============================================================================# #---------------------------------- WEAPONS -----------------------------------# #==============================================================================# class ItemWeaponBase(ItemBase): category = SingleChoiceField("Category", CATEGORIES) tags = MultiChoiceField("Tags", TAGS_WEAPONS) accuracy = NamedIntegerField("Accuracy") damage = NamedIntegerField("Damage") defense = NamedIntegerField("Defense") overwhelming = NamedIntegerField("Overwhelming") attunement = NamedIntegerField("Attunement") class ItemWeaponMelee(ItemWeaponBase): def attack(self, ability, mod=0, withering=True): if withering: return mod + ability + self.dexterity + weapon.accuracy else: return mod + ability + self.dexterity def parry(self, ability, mod=0): if self.character.charmsActive(): mod += sum([]) return mod + ceil((self.dexterity + ability) / 2) + weapon.defense class ItemWeaponRanged(ItemWeaponBase): rangeClose = NamedIntegerField("Close Range") rangeShort = NamedIntegerField("Short Range") rangeMedium = NamedIntegerField("Medium Range") rangeLong = NamedIntegerField("Long Range") rangeExtreme = NamedIntegerField("Extreme Range") def attack(self, ability, rangeBand, mod=0, withering=True): rangeBand = rangeBand.lower() if rangeBand == "close" or rangeBand == "c": rangeModifier = self.rangeClose elif rangeBand == "short" or rangeBand == "s": rangeModifier = self.rangeShort elif rangeBand == "medium" or rangeBand == "m": rangeModifier = self.rangeMedium elif rangeBand == "long" or rangeBand == "l": rangeModifier = self.rangeLong elif rangeBand == "extreme" or rangeBand == "e": rangeModifier = self.rangeExtreme else: rangeModifier = 0 if withering: return mod + rangeModifier + ability + self.dexterity + weapon.accuracy else: return mod + rangeModifier + ability + self.dexterity #==============================================================================# #----------------------------------- ARMOR ------------------------------------# #==============================================================================# class ItemArmor(ItemBase): category = SingleChoiceField("Category", CATEGORIES) tags = MultiChoiceField("Tags", TAGS_ARMOR) soak = NamedIntegerField("Soak") hardness = NamedIntegerField("Hardness") mobilityPenalty = NamedIntegerField("Mobility Penalty") attunement = NamedIntegerField("Attunement") #==============================================================================# #---------------------------------- EFFECTS -----------------------------------# #==============================================================================# class EffectBase(PolymorphicModel): def __str__(self): return self.name name = NameField() description = DescriptionField() rollConfiguration = NamedManyToManyField("Roll Configurations", RollConfiguration) modifiers = NamedManyToManyField("Modifiers", ModifierBase) def modifier(self, keyword): output = 0 for modifier in self.modifiers.all(): if keyword == modifier.keyword: output += modifier.value return output #==============================================================================# #----------------------------------- CHARMS -----------------------------------# #==============================================================================# class CharmBase(EffectBase): levelEssence = NamedIntegerField("Essence Level") charmType = SingleChoiceField("Charm Type", CHARM_TYPES) duration = SingleChoiceField("Charm Duration", CHARM_DURATIONS) keywords = MultiChoiceField("Charm Keywords", CHARM_KEYWORDS) class CharmMartialArt(CharmBase): def type(self): return "Martial Art" levelKey = NamedIntegerField("Martial Arts Level") key = None class CharmEvocation(CharmBase): def type(self): return "Evocation" levelKey = 0 key = NamedForeignKeyField("Artifact", ItemBase) class CharmSolar(CharmBase): def type(self): return "Solar" levelKey = NamedIntegerField("Ability Level") key = SingleChoiceField("Key Ability", ABILITIES) class CharmLunar(CharmBase): def type(self): return "Lunar" levelKey = NamedIntegerField("Attribute Level") key = SingleChoiceField("Key Attribute", ATTRIBUTES) class CharmLunarShape(CharmBase): levelKey = 0 def type(self): return "Lunar Shape" key = None size = SingleChoiceField("Size", SHAPE_SIZES) shapeType = SingleChoiceField("Shape Type", SHAPE_TYPES) #==============================================================================# #----------------------------------- MERITS -----------------------------------# #==============================================================================# class Merit(EffectBase): dots = DotField("Dots") def dotsDisplay(self): output = [] for i in range(self.dots): output.append(True) for i in range(5 - self.dots): output.append(False) return output #==============================================================================# #-------------------------------- SPECIALITIES --------------------------------# #==============================================================================# class Speciality(EffectBase): pass #==============================================================================# #--------------------------------- INTIMACIES ---------------------------------# #==============================================================================# class IntimacyBase(PolymorphicModel): def __str__(self): return "[{}] {}".format(self.description, self.intensity) description = DescriptionField() intensity = SingleChoiceField("Intensity", INTENSITIES) character = NamedForeignKeyField("Character", CharacterBase, related_name="intimacy_set") class IntimacyTie(IntimacyBase): target = NamedCharField("Target") class IntimacyPrincipal(IntimacyBase): pass #==============================================================================# #--------------------------------- OWNERSHIP ----------------------------------# #==============================================================================# class OwnershipBase(PolymorphicModel): notes = models.TextField(verbose_name="Notes", blank=True) active = NamedBooleanField("Active/Equipped?") class OwnershipItem(OwnershipBase): target = NamedForeignKeyField("Item", Item, related_name="ownershipItemTarget_set") owner = NamedForeignKeyField("Owner", CharacterBase, related_name="ownershipItem_set") class OwnershipItemWeapon(OwnershipBase): target = NamedForeignKeyField("Weapon", ItemWeaponBase, related_name="ownershipItemWeaponTarget_set") owner = NamedForeignKeyField("Owner", CharacterBase, related_name="ownershipItemWeapon_set") class OwnershipItemArmor(OwnershipBase): target = NamedForeignKeyField("Armor", ItemArmor, related_name="ownershipItemArmorTarget_set") owner = NamedForeignKeyField("Owner", CharacterBase, related_name="ownershipItemArmor_set") class OwnershipPropertyAttribute(OwnershipBase): target = NamedForeignKeyField("Attribute", PropertyAttribute, related_name="ownershipPropertyAttributeTarget_set") character = NamedForeignKeyField("Owner", CharacterBase, related_name="ownershipPropertyAttribute_set") value = NamedIntegerField("Dots") def dots(self): output = [] for i in range(self.value): output.append(True) for i in range(5 - self.value): output.append(False) return output class OwnershipPropertyAbility(OwnershipBase): target = NamedForeignKeyField("Ability", PropertyAbility, related_name="ownershipPropertyAbilityTarget_set") character = NamedForeignKeyField("Owner", CharacterBase, related_name="ownershipPropertyAbility_set") value = NamedIntegerField("Dots") def dots(self): output = [] for i in range(self.value): output.append(True) for i in range(5 - self.value): output.append(False) return output class OwnershipPropertyStatic(OwnershipBase): target = NamedForeignKeyField("Static", PropertyStatic, related_name="ownershipPropertyStaticTarget_set") character = NamedForeignKeyField("Owner", CharacterBase, related_name="ownershipPropertyStaticTarget_set") class OwnershipCharmMartialArt(OwnershipBase): target = NamedForeignKeyField("Martial Arts Charm", CharmMartialArt, related_name="ownershipCharmMartialArtTarget_set") owner = NamedForeignKeyField("Exalted Owner", CharacterExaltBase, related_name="ownershipCharmMartialArt_set") class OwnershipCharmEvocation(OwnershipBase): target = NamedForeignKeyField("Evocation", CharmEvocation, related_name="ownershipCharmEvocationTarget_set") owner = NamedForeignKeyField("Exalted Owner", CharacterExaltBase, related_name="ownershipCharmEvocation_set") class OwnershipCharmSolar(OwnershipBase): target = NamedForeignKeyField("Solar Charm", CharmSolar, related_name="ownershipCharmSolarTarget_set") owner = NamedForeignKeyField("Solar Exalted Owner", CharacterExaltSolar, related_name="ownershipCharmSolar_set") class OwnershipCharmLunar(OwnershipBase): target = NamedForeignKeyField("Lunar Charm", CharmLunar, related_name="ownershipCharmLunarTarget_set") owner = NamedForeignKeyField("Lunar Exalted Owner", CharacterExaltLunar, related_name="ownershipCharmLunar_set") class OwnershipCharmLunarShape(OwnershipBase): target = NamedForeignKeyField("Lunar Shape", CharmLunarShape, related_name="ownershipCharmLunarShapeTarget_set") owner = NamedForeignKeyField("Lunar Exalted Owner", CharacterExaltLunar, related_name="ownershipCharmLunarShape_set") class OwnershipMerit(OwnershipBase): target = NamedForeignKeyField("Merit", Merit, related_name="ownershipMeritTarget_set") owner = NamedForeignKeyField("Owner", CharacterBase, related_name="ownershipMerit_set") class OwnershipSpeciality(OwnershipBase): target = NamedForeignKeyField("Speciality", Speciality, related_name="ownershipSpecialityTarget_set") owner = NamedForeignKeyField("Owner", CharacterBase, related_name="ownershipSpeciality_set")