diff --git a/d2warehouse/item.py b/d2warehouse/item.py index 14240d2..b66a684 100644 --- a/d2warehouse/item.py +++ b/d2warehouse/item.py @@ -31,6 +31,7 @@ _unique_map = None _set_item_map = None _runeword_map = None _affix_map = None +_skills_map = None class Quality(IntEnum): @@ -77,8 +78,18 @@ class Stat: for val in self.values: subst_text = subst_text.replace("#", str(val), 1) if param: - subst_text = re.sub(r"\[[^\]]*\]", str(param), subst_text, 1) + subst_text = self.try_add_skill_text(subst_text) return subst_text + + def try_add_skill_text(self, subst_text: str) -> str | None: + if self.id == 107: # +X to [Skill] ([Class] only) + return re.sub(r"\[[^\]]*\]", lookup_skill_name(self.parameter), subst_text, 1) + elif self.id == 188: # +X to [Skill] + if '[' in subst_text: + return subst_text[:subst_text.find('[')] + lookup_random_skill_tab(self.parameter) + return re.sub(r"\[[^\]]*\]", lookup_random_skill_tab(self.parameter), subst_text, 1) + else: + return re.sub(r"\[[^\]]*\]", str(self.parameter), subst_text, 1) def txtbits(bits: bitarray) -> str: @@ -546,3 +557,57 @@ def lookup_affix(id: int, prefix: bool) -> dict: with open(os.path.join(_data_path, "affixes.json")) as f: _affix_map = json.load(f) return _affix_map["prefixes" if prefix else "suffixes"][str(id)] + + +def _get_skills_map(): + global _skills_map + if _skills_map is None: + with open(os.path.join(_data_path, "skills.json")) as f: + _skills_map = json.load(f) + return _skills_map + + +def lookup_skill_name(id: int) -> str: + # FIXME: This hackish way of calculating the key is because we directly index into local/lng/strings/skills.json + # but the actual ID points to global/excel/skills.txt + skills_map = _get_skills_map() + try: + try: + return skills_map[f"Skillname{id + 1}"] + except KeyError: + return skills_map[f"skillname{id}"] + except KeyError: + return f"" + + +def lookup_random_skill_tab(id: int) -> str: + # (ClassId * 8) is the id of the first tab for that class + skills_map = _get_skills_map() + class_name = lookup_class(int(id / 8)) + two_letter_class_code = lookup_class(int(id / 8))[:2] + tab_index = 3 - id % 8 # for some reason local/lng/strings/skills.json index backwards (0 -> 3, 1 -> 2, ...) + try: + return skills_map[f"SkillCategory{two_letter_class_code}{tab_index}"] + f" ({class_name} only)" + except KeyError: + return f"" + + +def lookup_class(id: int) -> str: + match id: + case 0: + return "Amazon" + case 1: + return "Sorceress" + case 2: + return "Necromancer" + case 3: + return "Paladin" + case 4: + return "Barbarian" + case 5: + return "Druid" + case 6: + return "Assassin" + case _: + # TODO: In 3.11 replace this with assert_never + assert False, f"{id} Should be unreachable"