diff --git a/PyPoE/cli/exporter/wiki/parsers/item.py b/PyPoE/cli/exporter/wiki/parsers/item.py index cbc88e71..68e0196b 100644 --- a/PyPoE/cli/exporter/wiki/parsers/item.py +++ b/PyPoE/cli/exporter/wiki/parsers/item.py @@ -56,6 +56,7 @@ def _apply_column_map(infobox, column_map, list_object): + for k, data in column_map: value = list_object[k] if data.get('condition') and not data['condition'](value): @@ -573,7 +574,7 @@ class ItemsParser(SkillParserShared): 'Ritual': '3.13.0', 'Ultimatum': '3.14.0', 'Expedition': '3.15.0', - 'Hellscape': '3.16.0', #AKA Scourge + 'Scourge': '3.16.0' } _IGNORE_DROP_LEVEL_CLASSES = ( @@ -776,6 +777,7 @@ class ItemsParser(SkillParserShared): 'Metadata/Items/Gems/SupportGemConcentratedEffect': '', 'Metadata/Items/Gems/SupportGemIncreasedCriticalStrikes': '', 'Metadata/Items/Gems/SupportGemMeleeSplash': '', + 'Metadata/Items/Gems/SkillGemEnergyBlade': '', # ================================================================= # One Hand Axes # ================================================================= @@ -787,6 +789,19 @@ class ItemsParser(SkillParserShared): 'Metadata/Items/Weapons/OneHandWeapons/OneHandAxes/OneHandAxe22': '', + + # ================================================================= + # One Hand Swords + # ================================================================= + 'Metadata/Items/Weapons/OneHandWeapons/OneHandSwords/StormBladeOneHand': + ' (One Handed Sword)', + + # ================================================================= + # Two Hand Swords + # ================================================================= + 'Metadata/Items/Weapons/TwoHandWeapons/TwoHandSwords/StormBladeTwoHand': + ' (Two Handed Sword)', + # ================================================================= # Boots # ================================================================= @@ -2708,24 +2723,40 @@ def _type_amulet(self, infobox, base_item_type): _type_armour = _type_factory( data_file='ArmourTypes.dat', data_mapping=( - ('Armour', { - 'template': 'armour', + ('ArmourMin', { + 'template': 'armour_min', 'condition': lambda v: v > 0, }), - ('Evasion', { - 'template': 'evasion', + ('ArmourMax', { + 'template': 'armour_max', 'condition': lambda v: v > 0, }), - ('EnergyShield', { - 'template': 'energy_shield', + ('EvasionMin', { + 'template': 'evasion_min', + 'condition': lambda v: v > 0, + }), + ('EvasionMin', { + 'template': 'evasion_max', + 'condition': lambda v: v > 0, + }), + ('EnergyShieldMin', { + 'template': 'energy_shield_min', + 'condition': lambda v: v > 0, + }), + ('EnergyShieldMax', { + 'template': 'energy_shield_max', 'condition': lambda v: v > 0, }), ('IncreasedMovementSpeed', { 'template': 'movement_speed', 'condition': lambda v: v != 0, }), - ('Ward', { - 'template': 'ward', + ('WardMin', { + 'template': 'ward_min', + 'condition': lambda v: v != 0, + }), + ('WardMax', { + 'template': 'ward_max', 'condition': lambda v: v != 0, }), ), @@ -2881,25 +2912,6 @@ def _currency_extra(self, infobox, base_item_type, currency): ), ) - _master_hideout_doodad_map = ( - ('HideoutNPCsKey', { - 'template': 'master', - 'format': lambda v: v['Hideout_NPCsKey']['Name'], - 'condition': lambda v: v is not None, - }), - ('MasterLevel', { - 'template': 'master_level_requirement', - }), - ('FavourCost', { - 'template': 'master_favour_cost', - }), - ) - - def _apply_master_map(self, infobox, base_item_type, hideout): - if not hideout['IsNonMasterDoodad']: - _apply_column_map(infobox, self._master_hideout_doodad_map, - hideout) - _type_hideout_doodad = _type_factory( data_file='HideoutDoodads.dat', data_mapping=( @@ -2907,26 +2919,12 @@ def _apply_master_map(self, infobox, base_item_type, hideout): 'template': 'is_master_doodad', 'format': lambda v: not v, }), - ('HideoutNPCsKey', { - 'template': 'master', - 'format': lambda v: v['Hideout_NPCsKey']['Name'], - 'condition': lambda v: v, - }), - ('FavourCost', { - 'template': 'master_favour_cost', - #'condition': lambda v: v, - }), - ('MasterLevel', { - 'template': 'master_level_requirement', - #'condition': lambda v: v, - }), ('Variation_AOFiles', { 'template': 'variation_count', 'format': lambda v: len(v), }), ), row_index=True, - function=_apply_master_map, ) def _maps_extra(self, infobox, base_item_type, maps): @@ -3301,10 +3299,15 @@ def _harvest_plant_booster_extra(self, infobox, base_item_type, row_index=True, ) - _cls_map = { + _cls_map = dict() + ''' + This defines the expected data elements for an item class. + ''' + _cls_map = { # Jewellery 'Amulet': (_type_amulet, ), # Armour types + 'Armour': (_type_level, _type_attribute, _type_armour, ), 'Gloves': (_type_level, _type_attribute, _type_armour, ), 'Boots': (_type_level, _type_attribute, _type_armour, ), 'Body Armour': (_type_level, _type_attribute, _type_armour, ), @@ -3509,7 +3512,8 @@ def _conflict_atlas_region_upgrade( _conflict_resolver_map = { 'Active Skill Gem': _conflict_active_skill_gems, 'QuestItem': _conflict_quest_items, - 'HideoutDoodad': _conflict_hideout_doodad, + #TODO: Make a new doodad resolver that doesn't rely on 'HideoutNPCsKey' + #'HideoutDoodad': _conflict_hideout_doodad, 'Map': _conflict_maps, 'MapFragment': _conflict_map_fragments, 'DivinationCard': _conflict_divination_card, diff --git a/PyPoE/cli/exporter/wiki/parsers/lua.py b/PyPoE/cli/exporter/wiki/parsers/lua.py index e63ae1b9..6396840e 100644 --- a/PyPoE/cli/exporter/wiki/parsers/lua.py +++ b/PyPoE/cli/exporter/wiki/parsers/lua.py @@ -507,7 +507,8 @@ def main(self, parsed_args): row, self._COPY_KEYS_BESTIARY_COMPONENTS, components ) if row['BeastRarity'] != RARITY.ANY: - components[-1]['rarity'] = self.rr['ClientStrings.dat'].index['Id']['ItemDisplayString' + row['BeastRarity'].name_upper]['Text'] + display_string = 'ItemDisplayString' + row['BeastRarity'].name_upper + components[-1]['rarity'] = self.rr['ClientStrings.dat'].index['Id'][display_string]['Text'] recipe_components = [] for recipe_id, data in recipe_components_temp.items(): diff --git a/PyPoE/cli/exporter/wiki/parsers/passives.py b/PyPoE/cli/exporter/wiki/parsers/passives.py index 6771ebd6..952015cd 100644 --- a/PyPoE/cli/exporter/wiki/parsers/passives.py +++ b/PyPoE/cli/exporter/wiki/parsers/passives.py @@ -39,6 +39,7 @@ # Python import re import os.path +import warnings from functools import partialmethod from collections import OrderedDict @@ -289,6 +290,10 @@ def export(self, parsed_args, passives): data['icon'] = '%s (%s)' % (icon[-1], icon[-2]) else: data['icon'] = icon[-1] + #atlas_start_node doesn't have an icon path + else: + data['icon'] = '' + warnings.warn(f"Icon path file not found for {passive['Id']}: {passive['Name']}") data['icon'] = data['icon'].replace('.dds', '') diff --git a/PyPoE/poe/constants.py b/PyPoE/poe/constants.py index 985a6e33..c2d7cba5 100644 --- a/PyPoE/poe/constants.py +++ b/PyPoE/poe/constants.py @@ -605,23 +605,27 @@ class MAP_FRAGMENT_FAMILIES(IntEnumOverride): """ Representation of map fragment families (MapFragmentFamilies.dat) """ - BESTIARY = 0 + BESTIARY_AND_SULPHITE = 0 #Maybe just master-related? BREACH = 1 - CARTOGRAPHY = 2 - RELIQUARY = 3 - SHAPER = 4 - ELDER = 5 - DIVINATION = 6 - TORMENT = 7 - AMBUSH = 8 - HARBINGER = 9 - PERANDUS = 10 - LEGION = 11 - METAMORPH = 12 - REGULAR = 13 - RITUAL = 14 - EXPEDITION = 15 - SCOURGE = 16 + CARTOGRAPHY_SCARAB = 2 + RELIQUARY_SCARAB = 3 + SHAPER_SCARAB = 4 + ELDER_SCARAB = 5 + DIVINATION_SCARAB = 6 + TORMENT_SCARAB = 7 + AMBUSH_SCARAB = 8 + HARBINGER_SCARAB = 9 + EXPEDITION_SCARAB = 10 + LEGION_SCARAB = 11 + METAMORPH_SCARAB = 12 + BLIGHT_SCARAB = 13 + ABYSS_SCARAB = 14 + KARUI = 15 + MARAKETH = 16 + ETERNAL = 17 + TEMPLAR = 18 + VAAL = 19 + REGULAR = 20 DEFAULT = REGULAR STANDARD = REGULAR diff --git a/PyPoE/poe/file/psg.py b/PyPoE/poe/file/psg.py index 27ef4b12..1f7e1153 100644 --- a/PyPoE/poe/file/psg.py +++ b/PyPoE/poe/file/psg.py @@ -270,15 +270,23 @@ def _read(self, buffer, *args, **kwargs): version = struct.unpack_from(' 1000): + raise ValueError( + f'root_length is unrealistically large at {root_length}.\nStopping to prevent allocating too much memory' + ) offset += 4 self.root_passives = list(struct.unpack_from( diff --git a/PyPoE/poe/file/specification/data/stable.py b/PyPoE/poe/file/specification/data/stable.py index 84649039..e0235a44 100644 --- a/PyPoE/poe/file/specification/data/stable.py +++ b/PyPoE/poe/file/specification/data/stable.py @@ -4015,7 +4015,7 @@ key='BuffDefinitions.dat', ), Field( - name='Data0', + name='Buff_StatValues', type='ref|list|int', ), Field( @@ -5096,7 +5096,7 @@ type='ref|string', ), Field( - name='Unknown0', + name='Unknown0', #Might be a rate divisor. The per-minute costs are 60 while normal costs are 1 type='int', ), ), @@ -5279,6 +5279,23 @@ ), ), ), + 'CraftingBenchSortCategories.dat': File( + fields=( + Field( + name='Id', + type='ref|string', + unique=True, + ), + Field( + name='Key0', + type='ulong', + ), + Field( + name='IsVisible', + type='bool', + ), + ), + ), 'CraftingBenchUnlockCategories.dat': File( fields=( Field( @@ -10751,6 +10768,14 @@ type='ulong', key='Stats.dat', ), + Field( + name='ConsoleBlueprintLegend', + type='ref|string', + ), + Field( + name='Description', + type='ref|string', + ), ), ), 'HeistJobsExperiencePerLevel.dat': File( @@ -11615,19 +11640,31 @@ ), ), ), - 'HideoutDoodads.dat': File( + 'HellscapeAOReplacements.dat': File( fields=( Field( - name='BaseItemTypesKey', + name='Unknown0', + type='ref|string', + ), + Field( + name='HASH32', + type='int', + ), + Field( + name='Unknown1', + type='ref|string', + ), + ), + ), + 'HellscapeAreaPacks.dat': File( + fields=( + Field( + name='Key0', type='ulong', - key='BaseItemTypes.dat', - unique=True, ), Field( - name='Variation_AOFiles', - type='ref|list|ref|string', - file_path=True, - file_ext='.ao', + name='Keys0', + type='ref|list|ulong', ), Field( name='IsNonMasterDoodad', @@ -14400,18 +14437,6 @@ name='HeistTier', type='int', ), - Field( - name='RitualTier', - type='int', - ), - Field( - name='ExpeditionTier', - type='int', - ), - Field( - name='HellscapeTier', #AKA Scourge - type='int', - ), ), ), 'MapStatConditions.dat': File( @@ -19282,7 +19307,7 @@ ), Field( name='Stuck_AOFile', - type='ref|string', + type='ref|list|ref|string', file_path=True, file_ext='.ao', ), @@ -19340,10 +19365,6 @@ name='Keys0', type='ref|list|ulong', ), - Field( - name='Key3', - type='ulong', - ), Field( name='Flag5', type='bool', @@ -19352,6 +19373,10 @@ name='Unknown12', type='int', ), + Field( + name='Unknown13', + type='int', + ), ), ), 'Prophecies.dat': File( diff --git a/PyPoE/poe/file/translations.py b/PyPoE/poe/file/translations.py index ff4cfe0d..54c22aa8 100644 --- a/PyPoE/poe/file/translations.py +++ b/PyPoE/poe/file/translations.py @@ -1052,8 +1052,7 @@ def register_from_string(self, string: str): try: self.index_handlers[handler.id].append(int(args[0])) except ValueError as e: - warnings.warn('Broken quantifier "%s" - Error: %s' % - (string, e.args[0]), TranslationWarning) + warnings.warn(f'Broken quantifier "{string}" - Error: {e.args[0]}', TranslationWarning) elif handler.type == TranslationQuantifier.QuantifierTypes.STRING: self.string_handlers[handler.id] = args else: @@ -1595,8 +1594,7 @@ def _add_translation_hashed(self, translation_id, translation): translation.diff(other) print('')''' - warnings.warn('Duplicate id "%s"' % - translation_id, DuplicateIdentifierWarning) + warnings.warn(f'Duplicate id "{translation_id}"', DuplicateIdentifierWarning) self.translations_hash[translation_id].append(translation) else: self.translations_hash[translation_id] = [translation, ]