Last active
July 10, 2023 14:09
-
-
Save Mijago/2591d9229a33c3ac32d0bf64860e967b to your computer and use it in GitHub Desktop.
A very simple script to see which Destiny 2 exotic has which intrinsic stat focus.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests, os, json | |
####################################################### | |
# First, download the manifest overview | |
# https://www.bungie.net/Platform/Destiny2/Manifest/ | |
# Define the required tables. We need InventoryItem and the Plugs | |
requiredTables = [ | |
"DestinyInventoryItemDefinition", | |
"DestinyPlugSetDefinition" | |
] | |
STAT_TO_INDEX = { | |
2996146975: 0, # Mobility | |
392767087: 1, # Resilience | |
1943323491: 2, # Recovery | |
1735777505: 3, # Discipline | |
144602215: 4, # Intellect | |
4244567218: 5 # Strength | |
} | |
# Get the manifest | |
manifest = requests.get('https://www.bungie.net/Platform/Destiny2/Manifest/').json() | |
manifest_version = manifest['Response']['version'] | |
# create the manifest directories | |
if not os.path.exists('manifest'): | |
os.makedirs('manifest') | |
if not os.path.exists('manifest/' + manifest_version): | |
os.makedirs('manifest/' + manifest_version) | |
# download the tables, if they are not already downloaded | |
for table in requiredTables: | |
filename = 'manifest/' + manifest_version + '/' + table + '.json' | |
if os.path.isfile(filename): | |
print(table + " already downloaded") | |
continue | |
print("Downloading " + table + "...") | |
table_url = 'http://www.bungie.net' + manifest['Response']['jsonWorldComponentContentPaths']['en'][table] | |
table_file = requests.get(table_url) | |
with open(filename, 'wb') as f: | |
f.write(table_file.content) | |
print("Downloaded " + table + " to " + filename) | |
####################################################### | |
# Actually load the manifest | |
print("Loading manifest...") | |
tables = {table:json.load(open(f"manifest/{manifest_version}/{table}.json", encoding="utf8")) for table in requiredTables} | |
####################################################### | |
# Grab exotic armor | |
exotic_armor = [ | |
k for _, k in tables["DestinyInventoryItemDefinition"].items() | |
if k["itemType"] == 2 # type: armor | |
and k["inventory"]["tierType"] == 6 # tier: exotic | |
# armor 2.0 | |
and k["sockets"]["socketEntries"][0]["socketTypeHash"] in [1718047805] # MRR | |
] | |
####################################################### | |
# | |
def get_stat_minimum(item): | |
# Get plugs. MRR are sockets 0 and 1, DIS are sockets 2 and 3 | |
socketCategories = [ | |
_["socketIndexes"][:4] for _ in item["sockets"]["socketCategories"] if _["socketCategoryHash"] == 3154740035 | |
][0] | |
sockets = [sock for k, sock in enumerate(item["sockets"]["socketEntries"]) if k in socketCategories] | |
# map sockets to their plugs | |
socket_plugs = [ | |
tables["DestinyPlugSetDefinition"][str(socket["randomizedPlugSetHash"])] | |
for socket in sockets | |
] | |
# now map the plugs to their inventory items, and then to their stats | |
def mapToStats(plug): | |
result = [0,0,0,0,0,0] | |
entries = tables["DestinyInventoryItemDefinition"][str(plug["plugItemHash"])]["investmentStats"] | |
for entry in entries: | |
result[STAT_TO_INDEX[entry["statTypeHash"]]] = entry["value"] | |
return result | |
socket_plugs = [ | |
[mapToStats(i) for i in socket_plug["reusablePlugItems"]] | |
for socket_plug in socket_plugs | |
] | |
# flatten and dedupe | |
socket_plugs = [item for sublist in socket_plugs for item in sublist] | |
socket_plugs = list(set([tuple(plug) for plug in socket_plugs])) | |
# now we have an array with shape [sockets][6] | |
# we want to find the minimum of each stat | |
minima = [min([plug[i] for plug in socket_plugs if plug[i] > 0]) for i in range(6)] | |
# if any stat is > 1, return the index; otherwise, -1 | |
if any([minima[i] > 1 for i in range(6)]): | |
return minima.index(max(minima)) | |
return -1 | |
intrinsics = {item["displayProperties"]["name"]: get_stat_minimum(item) for item in exotic_armor} | |
STAT_NAMES = ["Mobility", "Resilience", "Recovery", "Discipline", "Intellect", "Strength", "-"] | |
# sort by name (key) | |
intrinsics = {k: v for k, v in sorted(intrinsics.items(), key=lambda item: item[0])} | |
for name in intrinsics: | |
print(f"{name:30} {STAT_NAMES[intrinsics[name]]}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ACD/0 Feedback Fence - | |
Abeyant Leap - | |
Actium War Rig - | |
Aeon Safe - | |
Aeon Soul - | |
Aeon Swift - | |
An Insurmountable Skullfort Strength | |
Antaeus Wards - | |
Apotheosis Veil Intellect | |
Arbor Warden - | |
Armamentarium Discipline | |
Ashen Wake Discipline | |
Assassin's Cowl - | |
Astrocyte Verse - | |
Athrys's Embrace Strength | |
Ballidorse Wrathweavers - | |
Blight Ranger - | |
Boots of the Assembler - | |
Cadmus Ridge Lancecap - | |
Caliban's Hand - | |
Celestial Nighthawk Intellect | |
Cenotaph Mask - | |
Chromatic Fire - | |
Citan's Ramparts Resilience | |
Claws of Ahamkara Strength | |
Contraverse Hold Discipline | |
Crest of Alpha Lupi - | |
Crown of Tempests - | |
Cuirass of the Falling Star Intellect | |
Cyrtarachne's Facade - | |
Dawn Chorus - | |
Doom Fang Pauldron - | |
Dunemarchers - | |
Eternal Warrior Intellect | |
Eye of Another World - | |
Fallen Sunstar - | |
Felwinter's Helm - | |
Foetracer - | |
Fr0st-EE5 - | |
Gemini Jester Mobility | |
Geomag Stabilizers - | |
Getaway Artist Discipline | |
Graviton Forfeit - | |
Gwisin Vest Intellect | |
Gyrfalcon's Hauberk - | |
Hallowfire Heart - | |
Heart of Inmost Light - | |
Helm of Saint-14 Intellect | |
Hoarfrost-Z - | |
Icefall Mantle Resilience | |
Karnstein Armlets - | |
Khepri's Horn - | |
Khepri's Sting Strength | |
Knucklehead Radar - | |
Liar's Handshake - | |
Lion Rampant - | |
Loreley Splendor Helm - | |
Lucky Pants - | |
Lucky Raspberry Discipline | |
Lunafaction Boots Recovery | |
Mantle of Battle Harmony - | |
Mask of Bakris Mobility | |
Mask of the Quiet One - | |
Mechaneer's Tricksleeves - | |
Mk. 44 Stand Asides - | |
Necrotic Grip - | |
Nezarec's Sin - | |
No Backup Plans - | |
Nothing Manacles Discipline | |
Oathkeeper - | |
Omnioculus - | |
One-Eyed Mask - | |
Ophidia Spathe Strength | |
Ophidian Aspect - | |
Orpheus Rig Intellect | |
Osmiomancy Gloves - | |
Peacekeepers - | |
Peregrine Greaves Strength | |
Phoenix Cradle - | |
Phoenix Protocol Intellect | |
Point-Contact Cannon Brace - | |
Precious Scars - | |
Promethium Spur Intellect | |
Radiant Dance Machines - | |
Raiden Flux Intellect | |
Raiju's Harness Intellect | |
Rain of Fire - | |
Renewal Grasps - | |
Sanguine Alchemy Recovery | |
Sealed Ahamkara Grasps - | |
Secant Filaments - | |
Second Chance - | |
Severance Enclosure - | |
Shards of Galanor Intellect | |
Shinobu's Vow Discipline | |
Skull of Dire Ahamkara Intellect | |
Speedloader Slacks - | |
St0mp-EE5 - | |
Star-Eater Scales Intellect | |
Starfire Protocol Discipline | |
Stormdancer's Brace Intellect | |
Stronghold - | |
Sunbracers - | |
Swarmers - | |
Synthoceps - | |
The Bombardiers Mobility | |
The Dragon's Shadow Mobility | |
The Path of Burning Steps - | |
The Sixth Coyote Mobility | |
The Stag - | |
Transversive Steps - | |
Triton Vice - | |
Ursa Furiosa - | |
Verity's Brow - | |
Vesper of Radius Recovery | |
Wings of Sacred Dawn - | |
Winter's Guile - | |
Wormgod Caress - | |
Wormhusk Crown Mobility | |
Young Ahamkara's Spine Discipline |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment