Compare commits

..

1 Commits

Author SHA1 Message Date
jfmonty2 d5523ba3cb Initial commit 2021-04-17 16:51:28 -07:00
6 changed files with 126 additions and 138 deletions
+2 -12
View File
@@ -1,20 +1,10 @@
This script removes the Aphrodite textures from Supergiant Games' *Hades*. This script removes the Aphrodite textures from Supergiant Games' *Hades*.
To use it, you will need Python installed. You can install it [here.](https://www.python.org/)
Git is not strictly necessary, although it is recommended as it is by far the easiest way of keeping up with updates.
However, if you wish to proceed without Git, you can simply download the repository as a ZIP archive using the button above
(top right, just above the list of files.)
## Installation ## Installation
git clone https://git.jfmonty2.com/jfmonty2/aphremove.git git clone https://git.jfmonty2.com/jfmonty2/aphremove.git
cd aphremove pip install -e aphremove
pip install --editable .
## Usage
aphremove aphremove
If Hades is installed to a Steam library folder somewhere other than the standard `C:\Program Files (x86)\Steam`, then If Hades is installed to a Steam library folder somewhere other than the standard `C:\Program Files (x86)\Steam`, then
@@ -25,4 +15,4 @@ If Hades is installed to a Steam library folder somewhere other than the standar
## Notes ## Notes
Heavy lifting is done by [quaerus/deppth](https://github.com/quaerus/deppth). Heavy lifting is done by [quaerus/deppth](https://github.com/quaerus/deppth).
All credit is due to that project, as there is no way I would have been able to reverse-engineer the Hades package format myself. All thanks are due to that project, as there is no way I would have been able to reverse-engineer the Hades package format myself.
+43 -42
View File
@@ -1,63 +1,64 @@
import json import json
import os import os, os.path
import pathlib import pathlib
import sys import sys
import tempfile import tempfile
from deppth import deppth, sggpio # not sure why the nested path from deppth import deppth # not sure why the nested path
from PIL import Image, ImageDraw from PIL import Image, ImageDraw
entries_file = pathlib.Path(__file__).parent / 'entries.json' def get_list(filename):
with open(entries_file) as f: d = pathlib.Path(__file__).parent
ENTRIES = json.load(f) lines = (d / filename).read_text().splitlines()
return set(lines)
def find_subtextures(pkg_reader): def remove_subtexture(package_dir, manifest, sub_atlas):
for entry in pkg_reader: filename = manifest['name'].split(os.path.sep)[-1] + '.png'
if entry.typeName != 'texture': file = package_dir / 'textures/atlases' / filename
continue img = Image.open(file)
for sub in entry.manifest_entry.subAtlases:
subname = sub['name']
if 'aphrodite' in subname.lower():
if subname in ENTRIES:
if ENTRIES[subname]:
yield entry, sub
else:
print(f'WARNING: Found new subtexture: {subname}. This probably means that Supergiant has added new content to the game. This should probably be re-examined.')
def remove_subtexture(path, sub_atlas):
img = Image.open(path)
draw = ImageDraw.Draw(img) draw = ImageDraw.Draw(img)
r = sub_atlas['rect'] r = sub_atlas['rect']
top_left = (r['x'], r['y']) top_left = (r['x'], r['y'])
bottom_right = (r['x'] + r['width'], r['y'] + r['height']) bottom_right = (r['x'] + r['width'], r['y'] + r['height'])
draw.rectangle(xy=(top_left, bottom_right), fill=(0, 0, 0, 0)) draw.rectangle(xy=(top_left, bottom_right), fill=(0, 0, 0, 0))
img.save(path) img.save(file)
def process_pkg(pkg_path): def process_pkg(src_path, include, exclude):
print('Processing package', src_path,)
with tempfile.TemporaryDirectory() as tmp: with tempfile.TemporaryDirectory() as tmp:
tmp = pathlib.Path(tmp) tmp = pathlib.Path(tmp)
extracted = set() pkg_dir = str(tmp / 'package')
print(' Extracting textures') print('Extracting package - this may take some time.')
with sggpio.PackageWithManifestReader(pkg_path) as reader: deppth.extract(src_path, pkg_dir)
pkg_tmp = tmp / 'package'
for entry, sub in find_subtextures(reader):
entry.manifest_entry.extract(pkg_tmp)
entry.extract(str(pkg_tmp))
filename = pkg_tmp / f'textures/atlases/{entry.short_name()}.png' manifests = []
remove_subtexture(filename, sub) for m in (tmp / 'package/manifest').iterdir():
with open(m) as f:
manifests.append(json.load(f))
print(' Patching package') print('Removing subtextures')
patch_path = tmp / 'patch.pkg' modified = []
deppth.pack(str(pkg_tmp), str(patch_path)) for manifest in manifests:
deppth.patch(pkg_path, patch_path) for sub in manifest['subAtlases']:
if 'aphrodite' in sub['name'].lower():
if sub['name'] in include:
remove_subtexture(tmp / 'package', manifest, sub)
manifest_name = manifest['name'].split(os.path.sep)[-1]
modified.append(manifest_name)
elif sub['name'] not in exclude:
print(f'WARNING: Unknown texture "{sub["name"]}". You may wish to add this texture to include.txt or exclude.txt.')
print('Constructing patches')
patch_path = str(tmp / 'patch.pkg')
deppth.pack(pkg_dir, patch_path, *modified)
print('Repacking package')
deppth.patch(src_path, patch_path)
print('Finished processing package.')
def run(): def run():
@@ -67,15 +68,15 @@ def run():
steam_dir = 'C:/Program Files (x86)/Steam' steam_dir = 'C:/Program Files (x86)/Steam'
base_dir = pathlib.Path(steam_dir) / 'steamapps/common/Hades/Content/Win/Packages' base_dir = pathlib.Path(steam_dir) / 'steamapps/common/Hades/Content/Win/Packages'
if not base_dir.exists(): if not base_dir.exists():
print(f'Could not find Hades game files. Is {steam_dir} the correct location for your Steam library?') print(f'Could not find Hades at {base_dir}. Is {steam_dir} the correct location for your Steam library?')
return 1 return 1
for pkg in 'GUI.pkg', '720p/GUI.pkg', 'BC3/GUI.pkg': include = get_list('include.txt')
exclude = get_list('exclude.txt')
for pkg in 'BC3/GUI.pkg', 'GUI.pkg', '720p/GUI.pkg':
path = str(base_dir / pkg) path = str(base_dir / pkg)
print('Processing package:', pkg) process_pkg(path, include, exclude)
process_pkg(path)
print() print()
print('Finished.') print('Finished.')
-82
View File
@@ -1,82 +0,0 @@
{
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0001": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0002": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0003": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_05_Large": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0004": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0005": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0006": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0007": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0008": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0009": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0045": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0047": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0048": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0049": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0010": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0050": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0011": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0040": false,
"GUI\\HUD\\BoonIconAphrodite": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_13_Large": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0041": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_09_Large": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_11_Large": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0012": false,
"GUI\\Icons\\RoomReward\\Aphrodite": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0042": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_secondary_attack": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0043": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0044": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0014": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0046": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0015": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0016": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0017": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0018": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0019": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0021": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0022": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0023": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_07_Large": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_12_Large": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_Athena_01": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_01_Large": false,
"GUI\\Screens\\AwardMenu\\KeepsakeMaxGift\\Aphrodite_02": false,
"GUI\\Screens\\AwardMenu\\KeepsakeMaxGift\\Aphrodite": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0013": false,
"GUI\\Screens\\BoonSelectSymbols\\Aphrodite": false,
"GUI\\Epilogue\\Olympus_Aphrodite": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0024": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0025": false,
"GUI\\Screens\\BoonSelectSymbols\\Aphrodite2": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0020": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0026": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0032": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0034": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0027": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0035": false,
"GUI\\Screens\\BoonIcons\\Ares_Aphrodite_01": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0028": false,
"GUI\\Screens\\BoonIcons\\Zeus_Aphrodite_01": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0029": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0030": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0031": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0033": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0037": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0036": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0038": false,
"GUI\\Screens\\BoonSelectSymbols\\Spin\\AphroditeIconSpin\\AphroditeIconSpin0039": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_03_Large": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_04_Large": false,
"GUI\\Screens\\BoonIcons\\Artemis_Aphrodite_01": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_06_Large": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_10_Large": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_Demeter_01": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_Poseidon_01": false,
"GUI\\Screens\\BoonIcons\\Dionysus_Aphrodite_01": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_02_Large": false,
"GUI\\Screens\\BoonIcons\\Aphrodite_08_Large": false,
"Portraits\\Codex\\CodexPortrait_Aphrodite": true,
"Portraits\\Portraits_Aphrodite_01": true
}
+78
View File
@@ -0,0 +1,78 @@
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0001
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0002
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0003
GUI\Screens\BoonIcons\Aphrodite_05_Large
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0004
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0005
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0006
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0007
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0008
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0009
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0045
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0047
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0048
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0049
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0010
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0050
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0011
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0040
GUI\HUD\BoonIconAphrodite
GUI\Screens\BoonIcons\Aphrodite_13_Large
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0041
GUI\Screens\BoonIcons\Aphrodite_09_Large
GUI\Screens\BoonIcons\Aphrodite_11_Large
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0012
GUI\Icons\RoomReward\Aphrodite
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0042
GUI\Screens\BoonIcons\Aphrodite_secondary_attack
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0043
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0044
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0014
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0046
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0015
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0016
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0017
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0018
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0019
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0021
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0022
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0023
GUI\Screens\BoonIcons\Aphrodite_07_Large
GUI\Screens\BoonIcons\Aphrodite_12_Large
GUI\Screens\BoonIcons\Aphrodite_Athena_01
GUI\Screens\BoonIcons\Aphrodite_01_Large
GUI\Screens\AwardMenu\KeepsakeMaxGift\Aphrodite_02
GUI\Screens\AwardMenu\KeepsakeMaxGift\Aphrodite
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0013
GUI\Screens\BoonSelectSymbols\Aphrodite
GUI\Epilogue\Olympus_Aphrodite
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0024
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0025
GUI\Screens\BoonSelectSymbols\Aphrodite2
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0020
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0026
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0032
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0034
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0027
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0035
GUI\Screens\BoonIcons\Ares_Aphrodite_01
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0028
GUI\Screens\BoonIcons\Zeus_Aphrodite_01
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0029
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0030
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0031
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0033
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0037
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0036
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0038
GUI\Screens\BoonSelectSymbols\Spin\AphroditeIconSpin\AphroditeIconSpin0039
GUI\Screens\BoonIcons\Aphrodite_03_Large
GUI\Screens\BoonIcons\Aphrodite_04_Large
GUI\Screens\BoonIcons\Artemis_Aphrodite_01
GUI\Screens\BoonIcons\Aphrodite_06_Large
GUI\Screens\BoonIcons\Aphrodite_10_Large
GUI\Screens\BoonIcons\Aphrodite_Demeter_01
GUI\Screens\BoonIcons\Aphrodite_Poseidon_01
GUI\Screens\BoonIcons\Dionysus_Aphrodite_01
GUI\Screens\BoonIcons\Aphrodite_02_Large
GUI\Screens\BoonIcons\Aphrodite_08_Large
+2
View File
@@ -0,0 +1,2 @@
Portraits\Portraits_Aphrodite_01
Portraits\Codex\CodexPortrait_Aphrodite
+1 -2
View File
@@ -6,8 +6,7 @@ setup(
author='Joseph Montanaro', author='Joseph Montanaro',
install_requires=[ install_requires=[
'deppth@https://github.com/quaerus/deppth/releases/download/v0.1.0.0/deppth-0.1.0.0-py3-none-any.whl', 'deppth@https://github.com/quaerus/deppth/releases/download/v0.1.0.0/deppth-0.1.0.0-py3-none-any.whl',
'pillow', 'pillow'
'lz4',
], ],
packages=find_packages(), packages=find_packages(),
entry_points = { entry_points = {