Initial commit

This commit is contained in:
2025-12-08 22:45:24 +01:00
commit 92289523ad
14 changed files with 1745 additions and 0 deletions

303
data/Constants.py Normal file
View File

@@ -0,0 +1,303 @@
EPISODES = {
"An Opera of Fear": [
[
"Police HQ"
],
[
"Octavio Snap",
"Into the Depths",
"Canal Chase"
],
[
"Turf War!",
"Tar Ball",
"Run 'n Bomb",
"Guard Duty",
],
[
"Operation: Tar-Be Gone!"
]
],
"Rumble Down Under": [
[
"Search for the Guru"
],
[
"Spelunking",
"Dark Caves",
"Big Truck",
"Unleash the Guru"
],
[
"The Claw",
"Lemon Rage",
"Hungry Croc"
],
[
"Operation: Moon Crash"
]
],
"Flight of Fancy": [
[
"Hidden Flight Roster"
],
[
"Frame Team Belgium",
"Frame Team Iceland",
"Cooper Hangar Defense",
"ACES Semifinals"
],
[
"Giant Wolf Massacre",
"Windmill Firewall",
"Beauty and the Beast"
],
[
"Operation: Turbo Dominant Eagle"
]
],
"A Cold Alliance": [
[
"King of Fire"
],
[
"Get a Job",
"Tearful Reunion",
"Grapple-Cam Break-In",
"Laptop Retrieval"
],
[
"Vampiric Demise",
"Down the Line",
"A Battery of Peril"
],
[
"Operation: Wedding Crasher"
]
],
"Dead Men Tell No Tales": [
[
"The Talk of Pirates"
],
[
"Dynamic Duo",
"Jollyboat of Destruction",
"X Marks the Spot"
],
[
"Crusher from the Depths",
"Deep Sea Danger",
"Battle on the High Seas"
],
[
"Operation: Reverse Double-Cross"
]
],
"Honor Among Thieves": [
[
"Carmelita to the Rescue",
"A Deadly Bite",
"The Dark Current",
"Bump-Charge-Jump",
"Danger in the Skies",
"The Ancestor's Gauntlet",
"Stand Your Ground",
"Final Legacy"
]
]
}
CHALLENGES = {
"An Opera of Fear": [
[],
[
"Canal Chase - Expert Course"
],
[
"Air Time",
"Tower Scramble",
"Coin Chase",
],
[
"Speed Bombing",
"Octavio Canal Challenge",
"Octavio's Last Stand",
"Venice Treasure Hunt"
]
],
"Rumble Down Under": [
[
"Rock Run"
],
[
"Cave Sprint",
"Cave Mayhem",
"Scaling the Drill",
"Guard Swappin'"
],
[
"Quick Claw",
"Pressure Brawl",
"Croc and Coins"
],
[
"Carmelita Climb",
"Outback Treasure Hunt"
]
],
"Flight of Fancy": [
[
"Castle Quick Climb"
],
[
"Muggshot Goon Attack",
"Security Breach",
"Defend the Hangar",
"Precision Air Duel"
],
[
"Wolf Rampage",
"One Woman Army",
],
[
"Going Out On A Wing",
"Holland Treasure Hunt"
]
],
"A Cold Alliance": [
[
"Big Air in China"
],
[
"Sharpshooter",
"Treetop Tangle",
"Tsao Showdown"
],
[],
[
"China Treasure Hunt"
]
],
"Dead Men Tell No Tales": [
[
"Patch Grab",
"Stealth Challenge"
],
[
"Boat Bash",
"Last Ship Sailing"
],
[],
[
"Pirate Treasure Hunt"
]
],
"Honor Among Thieves": [
[
"Beauty versus the Beast",
"Road Rage",
"Dr. M Dogfight",
"Ultimate Gauntlet",
"Battle Against Time"
]
]
}
ADDRESSES = {
"SCUS-97464" : {
"map id": 0x47989C,
"job id": 0x36DB98,
"reload": 0x4797C4,
"reload values": 0x4797CC,
"episode unlocks": 0x56AEC8,
"frame counter": 0x389BE0,
"x pressed": 0x36E78E,
"skip cutscene": 0x389C20,
"jobs": [
[
[0x1335d10]
],
[
[0x1350560,0x1357f80,0x135aba0]
],
[],
[],
[],
[]
],
"text": {
"powerups": [
{},
{},
{
"Trigger Bomb": (0x592c40,0x592e00),
"Fishing Pole": (0x59b000,0x59b2d0),
"Alarm Clock": (0x5962b0,0x5964c0),
"Adrenaline Burst": (0x593410,0x5934f0),
"Health Extractor": (0x5935c0,0x593660),
"Hover Pack": (0x593750,0x593840),
"Insanity Strike": (0x598480,0x598690),
"Grapple-Cam": (0x59acd0,0x59ae50),
"Size Destabilizer": (0x592f30,0x593010),
"Rage Bomb": (0x599250,0x599420),
"Reduction Bomb": (0x5939b0,0x593b00),
"Be The Ball": (0x59a9c0,0x59ab70),
"Berserker Charge": (0x5955a0,0x595700),
"Juggernaut Throw": (0x594c50,0x594dd0),
"Guttural Roar": (0x595830,0x595920),
"Fists of Flame": (0x5944a0,0x594610),
"Temporal Lock": (0x593c40,0x593e60),
"Raging Inferno Flop": (0x595a50,0x595bd0),
"Diablo Fire Slam": (0x595260,0x595450),
"Smoke Bomb": (0x595d60,0x595ee0),
"Combat Dodge": (0x596050,0x596190),
"Paraglide": (0x5966d0,0x5968d0),
"Silent Obliteration": (0x596ba0,0x596df0),
"Feral Pounce": (0x597290,0x5973f0),
"Mega Jump": (0x5975f0,0x597780),
"Knockout Dive": (0x597e10,0x598130),
"Shadow Power Level 1": (0x599c30,0x599eb0),
"Thief Reflexes": (0x596f70,0x597110),
"Shadow Power Level 2": (0x59a140,0x59a310),
"Rocket Boots": (0x57aa00,0x57ace0),
"Treasure Map": (0x57a3e0,0x57a780),
"ENGLISHpowerup_shield_name": (0x59b550,0x579c50),
"Venice Disguise": (0x57ae40,0x57b040),
"Photographer Disguise": (0x57b220,0x57b3b0),
"Pirate Disguise": (0x57b5d0,0x57b7b0),
"Spin Attack Level 1": (0x57b9e0,0x57bc40),
"Spin Attack Level 2": (0x57be80,0x57c130),
"Spin Attack Level 3": (0x57c300,0x57c5b0),
"Jump Attack Level 1": (0x57c7c0,0x57c970),
"Jump Attack Level 2": (0x57cb00,0x57cc30),
"Jump Attack Level 3": (0x57cdf0,0x57d010),
"Push Attack Level 1": (0x57d370,0x57d680),
"Push Attack Level 2": (0x57d940,0x57dc80),
"Push Attack Level 3": (0x57e070,0x57e3b0),
},
{},
{},
{}
]
}
}
}
MENU_RETURN_DATA = (
"794C15EE"+
"419A69B1"+
"FA2319BC"+
"FF2E5E8A"+
"ACD1E787"+
"3A2B7DB0"+
"B94681B3"+
"95777951"+
"CE8FEAA9"+
"07FB6D94"+
"F890094F"+
"3BFA55F6"+
"A0310D22"+
"F93E1EEE"+
"7F2319BC"+
"7B8274B1"
)

107
data/Items.py Normal file
View File

@@ -0,0 +1,107 @@
from typing import NamedTuple
from BaseClasses import Item, ItemClassification
from .Constants import EPISODES
class Sly3Item(Item):
game: str = "Sly 3: Honor Among Thieves"
class Sly3ItemData(NamedTuple):
name: str
code: int
category: str
classification: ItemClassification
filler_list = [
("Coins", ItemClassification.filler, "Filler"),
]
powerup_list = [
("Binocucom", ItemClassification.progression, "Power-Up"),
("Smoke Bomb", ItemClassification.useful, "Power-Up"),
("Knockout Dive", ItemClassification.useful, "Power-Up"),
("Combat Dodge", ItemClassification.useful, "Power-Up"),
("Paraglider", ItemClassification.progression, "Power-Up"),
("Rocket Boots", ItemClassification.useful, "Power-Up"),
("Silent Obliteration", ItemClassification.progression, "Power-Up"),
("Feral Pounce", ItemClassification.useful, "Power-Up"),
("Thief Reflexes", ItemClassification.useful, "Power-Up"),
("Progressive Shadow Power", ItemClassification.useful, "Power-Up"),
("Treasure Map", ItemClassification.progression, "Power-Up"),
("Disguise (Venice)", ItemClassification.progression, "Power-Up"),
("Disguise (Photographer)", ItemClassification.progression, "Power-Up"),
("Disguise (Pirate)", ItemClassification.progression, "Power-Up"),
("Progressive Spin Attack", ItemClassification.useful, "Power-Up"),
("Progressive Jump Attack", ItemClassification.useful, "Power-Up"),
("Progressive Push Attack", ItemClassification.useful, "Power-Up"),
("Mega Jump", ItemClassification.useful, "Power-Up"),
("Bombs", ItemClassification.progression, "Power-Up"),
("Trigger Bomb", ItemClassification.useful, "Power-Up"),
("Fishing Pole", ItemClassification.progression, "Power-Up"),
("Alarm Clock", ItemClassification.useful, "Power-Up"),
("Adrenaline Burst", ItemClassification.useful, "Power-Up"),
("Health Extractor", ItemClassification.useful, "Power-Up"),
("Insanity Strike", ItemClassification.useful, "Power-Up"),
("Grapple-Cam", ItemClassification.progression, "Power-Up"),
("Size Destabilizer", ItemClassification.useful, "Power-Up"),
("Rage Bomb", ItemClassification.useful, "Power-Up"),
("Reduction Bomb", ItemClassification.useful, "Power-Up"),
("Hover Pack", ItemClassification.progression, "Power-Up"),
("Ball Form", ItemClassification.progression, "Power-Up"),
("Berserker Charge", ItemClassification.useful, "Power-Up"),
("Juggernaut Throw", ItemClassification.useful, "Power-Up"),
("Guttural Roar", ItemClassification.useful, "Power-Up"),
("Fists of Flame", ItemClassification.useful, "Power-Up"),
("Temporal Lock", ItemClassification.useful, "Power-Up"),
("Raging Inferno Flop", ItemClassification.useful, "Power-Up"),
("Diablo Fire Slam", ItemClassification.useful, "Power-Up")
]
crew_list = [
("Bentley", ItemClassification.progression, "Crew"),
("Murray", ItemClassification.progression, "Crew"),
("Guru", ItemClassification.progression, "Crew"),
("Penelope", ItemClassification.progression, "Crew"),
("Panda King", ItemClassification.progression, "Crew"),
("Dimitri", ItemClassification.progression, "Crew"),
("Carmelita", ItemClassification.progression, "Crew")
]
progressive_episode_list = [
(f"Progressive {e}", ItemClassification.progression, "Episode")
for e in list(EPISODES.keys())[:-1]
]
item_list = (
filler_list +
powerup_list +
crew_list +
progressive_episode_list
)
base_code = 5318008
item_dict = {
name: Sly3ItemData(name, base_code+code, category, classification)
for code, (name, classification, category) in enumerate(item_list)
}
item_groups = {
key: {item.name for item in item_dict.values() if item.category == key}
for key in [
"Filler",
"Power-Up",
"Episode",
"Crew"
]
}
def from_id(item_id: int) -> Sly3ItemData:
matching = [item for item in item_dict.values() if item.code == item_id]
if len(matching) == 0:
raise ValueError(f"No item data for item id '{item_id}'")
assert len(matching) < 2, f"Multiple item data with id '{item_id}'. Please report."
return matching[0]

52
data/Locations.py Normal file
View File

@@ -0,0 +1,52 @@
from typing import NamedTuple
from .Constants import EPISODES, CHALLENGES
class Sly3LocationData(NamedTuple):
name: str
code: int
category: str
jobs_list = [
(f"{ep} - {job}", "Job")
for ep, chapters in EPISODES.items()
for jobs in chapters
for job in jobs
]
purchases_list = [
(f"ThiefNet {i+1:02}", "Purchase")
for i in range(37)
]
challenges_list = [
(f"{ep} - {challenge}", "Challenge")
for ep, chapters in CHALLENGES.items()
for challenges in chapters
for challenge in challenges
]
location_list = jobs_list + purchases_list + challenges_list
base_code = 8008135
location_dict = {
name: Sly3LocationData(name, base_code+code, category)
for code, (name, category) in enumerate(location_list)
}
location_groups = {
key: {location.name for location in location_dict.values() if location.category == key}
for key in [
"Job",
"Purchase",
"Challenge"
]
}
def from_id(location_id: int) -> Sly3LocationData:
matching = [location for location in location_dict.values() if location.code == location_id]
if len(matching) == 0:
raise ValueError(f"No location data for location id '{location_id}'")
assert len(matching) < 2, f"Multiple locations data with id '{location_id}'. Please report."
return matching[0]