Skip to content

Commit

Permalink
Merge pull request #72 from angelic-knight/patches-map-icons
Browse files Browse the repository at this point in the history
Support Exporting Shaper Guardian and Harbinger Maps
  • Loading branch information
pm5k authored Feb 28, 2022
2 parents 4c2f1f6 + 542e745 commit 3dde8de
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 28 deletions.
83 changes: 55 additions & 28 deletions PyPoE/cli/exporter/wiki/parsers/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

# Self
from PyPoE.poe.constants import RARITY
from PyPoE.cli.exporter.wiki.parsers.itemconstants import MAPS_IN_SERIES_BUT_NOT_ON_ATLAS, MAPS_TO_SKIP_COLORING, MAPS_TO_SKIP_COMPOSITING
from PyPoE.poe.file.dat import RelationalReader
from PyPoE.poe.file.ot import OTFile
from PyPoE.poe.sim.formula import gem_stat_requirement, GemTypes
Expand Down Expand Up @@ -3974,6 +3975,9 @@ def _get_map_series(self, parsed_args):
def export_map_icons(self, parsed_args):
r = ExporterResult()

# This needs to fall back to baseitemtype -> ItemVisualIdentity.
# It's failing on the weird Harbinger base map types and the shaper guardian maps.

if not parsed_args.store_images or not parsed_args.convert_images:
console(
'Image storage options must be specified for this function',
Expand All @@ -3985,16 +3989,20 @@ def export_map_icons(self, parsed_args):
if map_series is False:
return r

# base images
# === Base map icons ===
self._image_init(parsed_args)

# output base icon (without map symbol) to .../Base.dds
base_ico = os.path.join(self._img_path, 'Base.dds')

# read from the file path in the BaseIcon_DDSFile field from MapSeries.dat.
self._write_dds(
data=self.file_system.get_file(map_series['BaseIcon_DDSFile']),
out_path=base_ico,
parsed_args=parsed_args,
)

# === Maps from Atlas ===
for atlas_node in self.rr['AtlasNode.dat']:
if not atlas_node['ItemVisualIdentityKey']['DDSFile']:
warnings.warn(
Expand Down Expand Up @@ -4046,21 +4054,27 @@ def export_map(self, parsed_args):
self.rr['AtlasNode.dat'].build_index('MapsKey')
names = set(parsed_args.name)
map_series_tiers = {}
# For each map, save off the atlas node
for row in self.rr['MapSeriesTiers.dat']:
maps = row['MapsKey']

# Try to find the atlas node for the map. Save that as atlas_node by breaking.
for atlas_node in self.rr['AtlasNode.dat'].index['MapsKey'][maps]:
# This excludes the unique maps
if atlas_node['ItemVisualIdentityKey'][
'IsAtlasOfWorldsMapIcon']:
if atlas_node['ItemVisualIdentityKey']['IsAtlasOfWorldsMapIcon']:
break
# If we couldn't find the atlas node, set atlas_node to None to clear the last value.
else:
# Maps that are no longer on the atlas such as guardian maps
# or harbinger
atlas_node = None
if names and maps['BaseItemTypesKey']['Name'] in names or \
not names:

# Save off the atlas_node for each map in the series,
# filtering to the maps from the names command argument if it was provided.
if (names and maps['BaseItemTypesKey']['Name'] in names) or not names:
map_series_tiers[row] = atlas_node

# Save off the base icon
if parsed_args.store_images:
if not parsed_args.convert_images:
console(
Expand All @@ -4080,7 +4094,6 @@ def export_map(self, parsed_args):

base_ico = base_ico.replace('.dds', '.png')

#
self.rr['MapSeriesTiers.dat'].build_index('MapsKey')
self.rr['MapPurchaseCosts.dat'].build_index('Tier')
self.rr['UniqueMaps.dat'].build_index('ItemVisualIdentityKey')
Expand Down Expand Up @@ -4119,6 +4132,7 @@ def export_map(self, parsed_args):
else:
infobox['inventory_icon'] = name

starting_tier = tier
if atlas_node:
if latest:

Expand Down Expand Up @@ -4194,7 +4208,7 @@ def export_map(self, parsed_args):

r.add_result(
text=cond,
out_file='map_%s.txt' % name,
out_file=f'map_{name}.txt',
wiki_page=[
{
'page': name,
Expand All @@ -4204,41 +4218,54 @@ def export_map(self, parsed_args):
wiki_message='Map exporter',
)

# Export map icons
if parsed_args.store_images:
if atlas_node is None or \
not atlas_node['ItemVisualIdentityKey']['DDSFile']:
# Warn about and skip maps that aren't on the atlas and may not exist.
if atlas_node is None and base_item_type['Id'] not in MAPS_IN_SERIES_BUT_NOT_ON_ATLAS:
warnings.warn(
'Missing 2d art inventory icon for item "%s"' %
base_item_type['Name']
f"{base_item_type['Name']} ({base_item_type['Id']}) is not currently on the Atlas"
)
continue

# Warn about and skip maps that are on atlas but have no icon.
elif atlas_node is not None and not atlas_node['ItemVisualIdentityKey']['DDSFile']:
warnings.warn(f'Missing 2d art inventory icon for item "{base_item_type["Name"]}"')
continue

ico = os.path.join(self._img_path, name + ' inventory icon.dds')

# If the atlas doesn't point to an icon, use the base_item_type for the icon.
if atlas_node is not None:
dds_file_path = atlas_node['ItemVisualIdentityKey']['DDSFile']
else:
dds_file_path = base_item_type['ItemVisualIdentityKey']['DDSFile']

# Save off the map's icon (which still needs to be layered onto the base map)
self._write_dds(
data=self.file_system.get_file(
atlas_node['ItemVisualIdentityKey']['DDSFile']),
data=self.file_system.get_file(dds_file_path),
out_path=ico,
parsed_args=parsed_args,
)

ico = ico.replace('.dds', '.png')

color = None
if 5 < tier <= 10:
color = self._MAP_COLORS['mid tier']
elif 10 < tier <= 15:
color = self._MAP_COLORS['high tier']
if color:
# Recolor the map icon if appropriate and layer the map icon with the base icon.
if base_item_type['Id'] not in MAPS_TO_SKIP_COLORING:
color = None
if 5 < starting_tier <= 10:
color = self._MAP_COLORS['mid tier']
if 10 < starting_tier:
color = self._MAP_COLORS['high tier']

# This isn't how the game actually makes these map icons, so it isn't ideal, but it works.
if color:
os.system(
f'magick convert "{ico}" -fill rgb({color}) -colorize 100 "{ico}"'
)

if base_item_type['Id'] not in MAPS_TO_SKIP_COMPOSITING:
os.system(
'''magick convert "%s" -fill rgb(%s) -colorize 100 "%s"''' % (
ico, color, ico
))

os.system(
'magick composite -gravity center "%s" "%s" "%s"' % (
ico, base_ico, ico
))
f'magick composite -gravity center "{ico}" "{base_ico}" "{ico}"'
)

return r

Expand Down
73 changes: 73 additions & 0 deletions PyPoE/cli/exporter/wiki/parsers/itemconstants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
Overview
===============================================================================
+----------+------------------------------------------------------------------+
| Path | PyPoE/poe/constants.py |
+----------+------------------------------------------------------------------+
| Version | 1.0.0a0 |
+----------+------------------------------------------------------------------+
| Revision | $Id$ |
+----------+------------------------------------------------------------------+
| Author | angelic_knight |
+----------+------------------------------------------------------------------+
Description
===============================================================================
Global constants the item exporter such as lists of items to exclude from exporting.
Agreement
===============================================================================
See PyPoE/LICENSE
Documentation
===============================================================================
"""

# =============================================================================
# Imports
# =============================================================================

# Python

# 3rd-party

# self

# =============================================================================
# Globals
# =============================================================================


MAPS_IN_SERIES_BUT_NOT_ON_ATLAS = {
'Metadata/Items/Maps/MapWorldsHarbingerUber',
'Metadata/Items/Maps/MapWorldsHarbingerHigh',
'Metadata/Items/Maps/MapWorldsHarbingerMid',
'Metadata/Items/Maps/MapWorldsHarbingerLow',
'Metadata/Items/Maps/MapWorldsPhoenix',
'Metadata/Items/Maps/MapWorldsChimera',
'Metadata/Items/Maps/MapWorldsHydra',
'Metadata/Items/Maps/MapWorldsMinotaur',
'Metadata/Items/Maps/MapWorldsVaalTemple',
}

MAPS_TO_SKIP_COLORING = {
'Metadata/Items/Maps/MapWorldsHarbingerUber',
'Metadata/Items/Maps/MapWorldsHarbingerHigh',
'Metadata/Items/Maps/MapWorldsHarbingerMid',
'Metadata/Items/Maps/MapWorldsHarbingerLow',
'Metadata/Items/Maps/MapWorldsPhoenix',
'Metadata/Items/Maps/MapWorldsChimera',
'Metadata/Items/Maps/MapWorldsHydra',
'Metadata/Items/Maps/MapWorldsMinotaur',
'Metadata/Items/Maps/MapWorldsVaalTemple',
}

MAPS_TO_SKIP_COMPOSITING = {
'Metadata/Items/Maps/MapWorldsHarbingerUber',
'Metadata/Items/Maps/MapWorldsHarbingerHigh',
'Metadata/Items/Maps/MapWorldsHarbingerMid',
'Metadata/Items/Maps/MapWorldsHarbingerLow',
}

0 comments on commit 3dde8de

Please sign in to comment.