summaryrefslogtreecommitdiff
path: root/character.py
diff options
context:
space:
mode:
Diffstat (limited to 'character.py')
-rw-r--r--character.py105
1 files changed, 65 insertions, 40 deletions
diff --git a/character.py b/character.py
index 75329ed..2a306f9 100644
--- a/character.py
+++ b/character.py
@@ -1,36 +1,10 @@
import re
import json
+import copy
from dataclasses import dataclass, asdict
-from items import Armor
-from game import LevelingPlan
-
-
-_skill_ability = {
-# "classDC"
- "perception": "wis",
- "fortitude": "con",
- "reflex": "dex",
- "will": "wis",
- "acrobatics": "dex",
- "arcana": "int",
- "athletics": "str",
- "crafting": "int",
- "deception": "cha",
- "diplomacy": "cha",
- "intimidation": "cha",
- "medicine": "wis",
- "nature": "wis",
- "occultism": "int",
- "performance": "cha",
- "religion": "wis",
- "society": "int",
- "stealth": "dex",
- "survival": "wis",
- "thievery": "dex",
- "lore1": "int",
- "lore2": "int"
-}
+from items import Armor, Weapon
+from game import LevelingPlan, Features, Modifier, Conditions
class FeaturesPlan(LevelingPlan, dict):
@@ -58,10 +32,9 @@ class FeaturesPlan(LevelingPlan, dict):
class Abilities(dict):
- field_names = ["str", "dex", "int", "wis", "cha", "con"]
def __init__(self, data=None, **kwargs):
- super().__init__({field: 10 for field in Abilities.field_names})
+ super().__init__({field: 10 for field in Features.abilities})
if data:
self.update(data)
if kwargs:
@@ -123,6 +96,7 @@ class Character:
abilities: Abilities
features: dict
armor: Armor
+ conditions: Conditions
def __init__(self, data):
self.data = data
@@ -132,7 +106,9 @@ class Character:
self.level = 1
self.abilities = Abilities()
self.features = dict()
- self.armor = Armor("Leather armor", "light", 1)
+ self.armor = Armor("Unarmored", "light", 0)
+ self.weapons = [Weapon("Fist", "unarmed", "brawling", 4)]
+ self.conditions = Conditions()
def max_hp(self):
per_level = self.hp_per_level + self.abilities.modifier("con")
@@ -141,25 +117,62 @@ class Character:
def skill_ability(self, skill):
if skill == "classDC":
return self.data["keyability"]
- return _skill_ability.get(skill)
+ return Features.skill_ability.get(skill)
+
+ def ability_modifier(self, ability):
+ return self.conditions.modifier([ability]) + self.abilities.modifier(ability)
def proficiency_bonus(self, skill):
- return self.features.get(skill, 0) + self.level
+ bonus = self.features.get(skill, 0)
+ if bonus == 0:
+ return 0
+ return bonus + self.level
def proficiency(self, skill):
- # TODO + item bonuses
- ability = self.skill_ability(skill)
- ability = self.abilities.modifier(ability) if ability else 0
- return ability + self.proficiency_bonus(skill)
+ ability_name = self.skill_ability(skill)
+ res = Modifier()
+ if ability_name:
+ res += self.ability_modifier(ability_name)
+ res += self.proficiency_bonus(skill) + self.conditions.modifier([skill])
+ return res.total()
def ac(self):
- dex_bonus = min(self.armor.dex_cap, self.abilities.modifier("dex"))
+ dex_mod = self.conditions.modifier(["dex"], exclude=["ac"])
+ dex_mod += self.abilities.modifier("dex")
+ dex_bonus = min(self.armor.dex_cap, dex_mod.total())
prof = self.proficiency(self.armor.category)
- return 10 + dex_bonus + prof + self.armor.ac
+ armor = Modifier(item=self.armor.ac+self.armor.potency)
+ armor += self.conditions.modifier(["ac"])
+ return (10 + dex_bonus + prof + armor).total()
def classDC(self):
return 10 + self.proficiency("classDC")
+ def update_fundamental_runes(self):
+ try:
+ self.armor.potency = self.features["armor potency"]
+ self.armor.resilient = self.features["resilient"]
+ except KeyError:
+ pass
+ try:
+ for weapon in self.weapons:
+ weapon.potency = self.features["weapon potency"]
+ weapon.striking = self.features["striking"]
+ except KeyError:
+ pass
+
+ def attack_bonus(self, weapon: Weapon, strike_type="melee"):
+ dex = self.ability_modifier("dex").total()
+ mod = self.ability_modifier("str").total()
+ if strike_type == "melee":
+ if weapon.finesse:
+ mod = max(mod, dex)
+ elif strike_type == "ranged":
+ mod = dex
+ prof = max(self.features.get(weapon.category, 0),
+ self.features.get(weapon.name, 0))
+ return mod + prof + weapon.potency
+
def toJSON(self):
methods = ["classDC", "max_hp", "ac"]
obj = asdict(self)
@@ -168,6 +181,18 @@ class Character:
return json.dumps(obj, indent=2)
+class Attack:
+ attacker = None
+ target = None
+ previous_attacks = 0
+ distance = 0
+ # def map(self, previous_attacks):
+ # factor = max(0, min(2, previous_attacks))
+ # if self.agile:
+ # return factor * -4
+ # return factor * -5
+
+
class CharacterPlan(LevelingPlan):
def __init__(self, data) -> None:
self.data = data