def get_resistances(self): out = {'resist': [], 'immune': [], 'vuln': []} if not self.additional: # requires 2.0 return Resistances.from_dict(out) for rownum in range(69, 80): for resist_type, col in RESIST_COLS: try: dtype = self.additional.value(f"{col}{rownum}") except IndexError: dtype = None if dtype: out[resist_type].append(dtype.lower()) return Resistances.from_dict(out)
def get_resistances(self): out = {'resist': [], 'immune': [], 'vuln': []} if not self.additional: # requires 2.0 return Resistances.from_dict(out) for resist_row in range(69, 80): # T69:T79 resist = self.additional.cell(f"T{resist_row}").value if resist: out['resist'].append(resist.lower()) for immune_row in range(69, 80): # AE69:AE79 immune = self.additional.cell(f"AE{immune_row}").value if immune: out['immune'].append(immune.lower()) return Resistances.from_dict(out)
def get_resistances(self): resist = { 'resist': set(), 'immune': set(), 'vuln': set() } for mod in self.modifiers(): if mod['type'] == 'resistance': resist['resist'].add(mod['subType'].lower()) elif mod['type'] == 'immunity': resist['immune'].add(mod['subType'].lower()) elif mod['type'] == 'vulnerability': resist['vuln'].add(mod['subType'].lower()) for override in self.character_data['customDefenseAdjustments']: if not override['type'] == 2: continue if override['id'] not in RESIST_OVERRIDE_MAP: continue dtype, rtype = RESIST_OVERRIDE_MAP[override['id']] resist[RESIST_TYPE_MAP[rtype]].add(dtype.lower()) resist = {k: list(v) for k, v in resist.items()} return Resistances.from_dict(resist)
def __init__(self, name: str, stats: BaseStats = None, levels: Levels = None, attacks: AttackList = None, skills: Skills = None, saves: Saves = None, resistances: Resistances = None, spellbook: Spellbook = None, ac: int = None, max_hp: int = None, hp: int = None, temp_hp: int = 0): if stats is None: stats = BaseStats.default() if levels is None: levels = Levels() if attacks is None: attacks = AttackList() if skills is None: skills = Skills.default(stats) if saves is None: saves = Saves.default(stats) if resistances is None: resistances = Resistances() if spellbook is None: spellbook = Spellbook() if hp is None: hp = max_hp # ===== static ===== # all actors have a name self._name = name # ability scores self._stats = stats # at least a total level self._levels = levels # attacks - list of automation actions self._attacks = attacks # skill profs/saving throws self._skills = skills self._saves = saves # defensive resistances self._resistances = resistances # ===== dynamic ===== # hp/ac self._ac = ac self._max_hp = max_hp self._hp = hp self._temp_hp = temp_hp # spellbook self._spellbook = spellbook
def get_resistances(self): resist = {'resist': [], 'immune': [], 'vuln': []} for modtype in self.character_data['modifiers'].values(): for mod in modtype: if mod['type'] == 'resistance': resist['resist'].append(mod['subType']) elif mod['type'] == 'immunity': resist['immune'].append(mod['subType']) elif mod['type'] == 'vulnerability': resist['vuln'].append(mod['subType']) return Resistances.from_dict(resist)
def get_resistances(self) -> Resistances: if self.character_data is None: raise Exception('You must call get_character() first.') out = {'resist': [], 'immune': [], 'vuln': []} for dmgType in DAMAGE_TYPES: mult = self.calculate_stat(f"{dmgType}Multiplier", 1) if mult <= 0: out['immune'].append(dmgType) elif mult < 1: out['resist'].append(dmgType) elif mult > 1: out['vuln'].append(dmgType) return Resistances.from_dict(out)
def from_bestiary(cls, data): for key in ('traits', 'actions', 'reactions', 'legactions'): data[key] = [Trait(**t) for t in data.pop(key)] data['spellcasting'] = Spellbook.from_dict(data.pop('spellbook')) data['saves'] = Saves.from_dict(data['saves']) data['skills'] = Skills.from_dict(data['skills']) data['ability_scores'] = BaseStats.from_dict(data['ability_scores']) data['attacks'] = AttackList.from_dict(data['attacks']) if 'display_resists' in data: data['display_resists'] = Resistances.from_dict( data['display_resists']) return cls(**data)
def resistances(self): checked = [] out = {} for k in reversed(RESIST_TYPES): out[k] = [] for _type in self.active_effects(k): if _type not in checked: out[k].append(_type) checked.append(_type) for k in reversed(RESIST_TYPES): for _type in self._resistances[k]: if _type not in checked: out[k].append(_type) checked.append(_type) return Resistances.from_dict(out)
def __init__(self, name: str, size: str, race: str, alignment: str, ac: int, armortype: str, hp: int, hitdice: str, speed: str, ability_scores: BaseStats, cr: str, xp: int, passiveperc: int = None, senses: str = '', vuln: list = None, resist: list = None, immune: list = None, condition_immune: list = None, saves: Saves = None, skills: Skills = None, languages: list = None, traits: list = None, actions: list = None, reactions: list = None, legactions: list = None, la_per_round=3, srd=True, source='homebrew', attacks: AttackList = None, proper: bool = False, image_url: str = None, spellcasting=None, page=None, display_resists: Resistances = None, **_): if vuln is None: vuln = [] if resist is None: resist = [] if immune is None: immune = [] if condition_immune is None: condition_immune = [] if saves is None: saves = Saves.default(ability_scores) if skills is None: skills = Skills.default(ability_scores) if languages is None: languages = [] if traits is None: traits = [] if actions is None: actions = [] if reactions is None: reactions = [] if legactions is None: legactions = [] if attacks is None: attacks = AttackList() if spellcasting is None: spellcasting = Spellbook({}, {}, []) if passiveperc is None: passiveperc = 10 + skills.perception.value try: levels = Levels({"Monster": spellcasting.caster_level or int(cr)}) except ValueError: levels = None resistances = Resistances(vuln=vuln, resist=resist, immune=immune) super(Monster, self).__init__(name=name, stats=ability_scores, attacks=attacks, skills=skills, saves=saves, resistances=resistances, spellbook=spellcasting, ac=ac, max_hp=hp, levels=levels) self.size = size self.race = race self.alignment = alignment self.armortype = armortype self.hitdice = hitdice self.speed = speed self.cr = cr self.xp = xp self.passive = passiveperc self.senses = senses self.condition_immune = condition_immune self.languages = languages self.traits = traits self.actions = actions self.reactions = reactions self.legactions = legactions self.la_per_round = la_per_round self.srd = srd self.source = source self.proper = proper self.image_url = image_url self.page = page # this should really be by source, but oh well # resistances including notes, e.g. "Bludgeoning from nonmagical weapons" self._displayed_resistances = display_resists or resistances
def from_data(cls, data): # print(f"Parsing {data['name']}") _type = parse_type(data['type']) alignment = parse_alignment(data['alignment']) speed = parse_speed(data['speed']) ac = data['ac']['ac'] armortype = data['ac'].get('armortype') or None if not 'special' in data['hp']: hp = data['hp']['average'] hitdice = data['hp']['formula'] else: hp = 0 hitdice = data['hp']['special'] scores = BaseStats(0, data['str'] or 10, data['dex'] or 10, data['con'] or 10, data['int'] or 10, data['wis'] or 10, data['cha'] or 10) if isinstance(data['cr'], dict): cr = data['cr']['cr'] else: cr = data['cr'] # resistances vuln = parse_resists(data['vulnerable'], notated=False) if 'vulnerable' in data else None resist = parse_resists(data['resist'], notated=False) if 'resist' in data else None immune = parse_resists(data['immune'], notated=False) if 'immune' in data else None display_resists = Resistances(*[ parse_resists(data.get(r)) for r in ('resist', 'immune', 'vulnerable') ]) condition_immune = data.get('conditionImmune', []) if 'conditionImmune' in data else None languages = data.get('languages', '').split(', ') if 'languages' in data else None traits = [Trait(t['name'], t['text']) for t in data.get('trait', [])] actions = [Trait(t['name'], t['text']) for t in data.get('action', [])] legactions = [ Trait(t['name'], t['text']) for t in data.get('legendary', []) ] reactions = [ Trait(t['name'], t['text']) for t in data.get('reaction', []) ] skills = Skills.default(scores) skills.update(data['skill']) saves = Saves.default(scores) saves.update(data['save']) scores.prof_bonus = _calc_prof(scores, saves, skills) source = data['source'] proper = bool(data.get('isNamedCreature') or data.get('isNPC')) attacks = AttackList.from_dict(data.get('attacks', [])) spellcasting = data.get('spellcasting', {}) spells = [SpellbookSpell(s) for s in spellcasting.get('spells', [])] spellbook = Spellbook({}, {}, spells, spellcasting.get('dc'), spellcasting.get('attackBonus'), spellcasting.get('casterLevel', 1)) return cls(data['name'], parsesize(data['size']), _type, alignment, ac, armortype, hp, hitdice, speed, scores, cr, xp_by_cr(cr), data['passive'], data.get('senses', ''), vuln, resist, immune, condition_immune, saves, skills, languages, traits, actions, reactions, legactions, 3, data.get('srd', False), source, attacks, spellcasting=spellbook, page=data.get('page'), proper=proper, display_resists=display_resists)