mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-07-11 16:29:34 -07:00
f110a7efbc
* Update GauntletLegendsClient.py * Continuation of obelisk update * APPP Implementation Groundwork. * Continuation of APPP Implementation * Create Pain.asm * ROM verification modified since crc32 hash can no longer be calculated. * Initial upload of barrel/chest locations. * Finished adding and naming all chests/barrels. * Continued locations. * Added new yaml options * Work on mirror shards * Python 3.8 compatibility * Finalized location names. Fixed lambda bug. * v1.0 * Removed excess Docs and Changed item counts. * Update Archipelago Unittests.run.xml * Started working on Docs. * Updated item arrays for client * Fix client bugs * Flake8 fixes + Yaml fix * Update speed boots * v1.1 * Update GauntletLegendsClient.py * Update GauntletLegendsClient.py * Update GauntletLegendsClient.py * Update GauntletLegendsClient.py * v1.0.4 * Initial Ruff format * Formatting part-2 * More formatting + Doc changes * Updated Docs * Move client to root * Update Client Name * Make Imports Relative * Add new yaml options + rename obelisks * v1.1 Initial Upload * v1.1.0 + some additions * Client Update * Client Updates * pre-v1.1.1 * Update GauntletLegendsClient.py * pre-1.2 * 1.2.0 * v1.2.1 * Client fixes * v1.3.0 * v1.4.0 * v1.4.1 * Merged Changes * Experimental * pre-v1.5.0 * Changes * v1.5.0 * Update GauntletLegendsClient.py * Death Update * pre v1.5.1 * Obelisk rule changes * pre-v1.5.1 * Update GauntletLegendsClient.py * v1.5.1 * v1.5.1 * Update GauntletLegendsClient.py * Small fix * Update GauntletLegendsClient.py * v1.5.2 * pre-v1.6.0 * pre-v1.6.0 * v1.6.0 * Update * Update GauntletLegendsClient.py * Test * pre-v1.6.0 * Client Updtaes * Update GauntletLegendsClient.py * Update GauntletLegendsClient.py * Update GauntletLegendsClient.py * Update Rom.py * Update GauntletLegendsClient.py * Update Rom.py * Added Logging on stage enter * v1.6.2 * v1.6.2 * Update Rom.py * Update GauntletLegendsClient.py * v1.6.3 * Small Update * Update GauntletLegendsClient.py * Update GauntletLegendsClient.py * Update GauntletLegendsClient.py * Changes ready for review * Update Rom.py * Remove root client * Update inno_setup.iss * Update client * Initial Review Refactor * Update Arrays.py * Review refactor * Update __init__.py * Small tweaks after test generations * Update GauntletLegendsClient.py * Implement new check_locations() function * Add name for Skorn to level_names Dict * Fix for #4671 * Update __init__.py * Adjust item frequency + Place 50% of filler as local * Oops I modified the itempool after create_items teehee * Update __init__.py * Check MD5 hash before patching ROM * Update __init__.py * Fix get_filler_item_name() * Update MD5 check to built in method in FilePath * Update Rom.py * Update worlds/gl/Rom.py Co-authored-by: qwint <qwint.42@gmail.com> * WIP Generation fixes * v1.7.1 * Update Archipelago Unittests.run.xml * 0.7.2 * Update GauntletLegendsClient.py * Review Edits * Update World description * Fuzz fixes * Update GauntletLegendsClient.py * Make static data immutable * Update option comparisons since no longer a Choice * Update worlds/gl/Rom.py Co-authored-by: Doug Hoskisson <beauxq@users.noreply.github.com> * Update __init__.py * Initial Update commit * Progress * Remove un-used import + Add manifest * Add missing docstring for client command * Progress * pre-v2.0.0-BETA * Updates * Progress * Working Generations * Working IN-Game * v2.0.0-BETA * Create archipelago.json * v2.0.1 * v2.0.1 FINAL * pre v2.0.2 * Delete report.json * Cleanup * pre v2.0.2 * v2.0.2 * PR Ready * Update Items.py * Delete fuzz.py * Update Items.py * Update GauntletLegendsClient.py * Fix scouting disabled locations * Client Updates * v2.0.3 * Increment World Version * Docstring + slot_data updates * Option name update + Remove redundant option * Code Cleanup * Trenches is level 24 * Frequencies * More cleanup and removal of stale code. MISSING BASEPATCH * v2.1.0 * Minor enemy changes * Small fix * Update Rom.py * v2.1.1 * Small fixes * Update basepatch.bsdiff4 * Update GauntletLegendsClient.py * Socket error clarity * Delete settings.local.json * Update GauntletLegendsClient.py * v2.1.2 fixes * Boss portal fix * Small client fix + Item Frequencies * Update archipelago.json * Fix for games playing with max difficulty lower than 4 not sending locations * Update archipelago.json * v2.1.5 * Fix for Chimera's lair mirror shard * Update archipelago.json * Mod Re-Base + Queue limits + Item Receiving fixes * Options cleanup and newlines for some files * Include v2.x features in docs * Make sure players has at least 1 item * v2.1.6 * Update archipelago.json * Review Edits + Client Tweaks --------- Co-authored-by: qwint <qwint.42@gmail.com> Co-authored-by: Doug Hoskisson <beauxq@users.noreply.github.com> Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com> Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com>
460 lines
13 KiB
Python
460 lines
13 KiB
Python
from collections.abc import Mapping, Sequence
|
|
from types import MappingProxyType
|
|
from typing import Final
|
|
|
|
from .Locations import LocationData, get_locations_by_tags
|
|
|
|
# Item name to ram value conversion
|
|
item_ids: Final[Mapping[str, int]] = MappingProxyType({
|
|
"Strength": 0x000002,
|
|
"Speed": 0x000003,
|
|
"Magic": 0x000004,
|
|
"Armour": 0x000005,
|
|
"Gold": 0x000006,
|
|
"Key": 0x000007,
|
|
"XP": 0x000009,
|
|
"Level": 0x00000A,
|
|
"Class": 0x00000B,
|
|
"Max": 0x00000D,
|
|
"Compass": 0x000270,
|
|
"Lightning Potion": 0x001008,
|
|
"Light Potion": 0x002008,
|
|
"Acid Potion": 0x003008,
|
|
"Fire Potion": 0x004008,
|
|
"Acid Breath": 0x800480,
|
|
"Lightning Breath": 0x8004F0,
|
|
"Fire Breath": 0x800460,
|
|
"Light Amulet": 0x400870,
|
|
"Acid Amulet": 0x400880,
|
|
"Lightning Amulet": 0x4008F0,
|
|
"Fire Amulet": 0x400860,
|
|
"Lightning Shield": 0x400CF0,
|
|
"Fire Shield": 0x400C60,
|
|
"Invisibility": 0x4000E0,
|
|
"Levitate": 0x400030,
|
|
"Speed Boots": 0x400173,
|
|
"3-Way Shot": 0x400020,
|
|
"5-Way Shot": 0x400160,
|
|
"Rapid Fire": 0x400050,
|
|
"Reflective Shot": 0x400840,
|
|
"Reflective Shield": 0x400C40,
|
|
"Super Shot": 0x8008B0,
|
|
"Timestop": 0x4000D0,
|
|
"Phoenix Familiar": 0x400110,
|
|
"Growth": 0x400120,
|
|
"Shrink": 0x400130,
|
|
"Thunder Hammer": 0x800940,
|
|
"Anti-Death Halo": 0x7000A0,
|
|
"Invulnerability": 0x7000C0,
|
|
"Health": 0x000001,
|
|
"Runestone": 0x008210,
|
|
"Mirror Shard": 0x008260,
|
|
"Ice Axe of Untar": 0x8201C0,
|
|
"Flame of Tarkana": 0x8201D0,
|
|
"Scimitar of Decapitation": 0x8201E0,
|
|
"Marker's Javelin": 0x8201F0,
|
|
"Soul Savior": 0x820200,
|
|
"Mountain": 0x00804A,
|
|
"Castle": 0x00801A,
|
|
"Hell": 0x00806A,
|
|
"Ice": 0x00807A,
|
|
"Town": 0x00808A,
|
|
"Temple": 0x00809A,
|
|
"Battlefield": 0x0080DA,
|
|
"Skorne": 0x0080EA,
|
|
"Secret": 0x0080FA,
|
|
"Obelisk": 0x00800C,
|
|
"Minotaur": 0x0001A1,
|
|
"Falconess": 0x0001A2,
|
|
"Jackal": 0x0001A3,
|
|
"Tigress": 0x0001A4,
|
|
"Sumner": 0x0001A5,
|
|
"Skorne's Mask": 0x840620,
|
|
"Skorne's Horns": 0x840630,
|
|
"Skorne's Right Gauntlet": 0x840A40,
|
|
"Skorne's Left Gauntlet": 0x840A50,
|
|
"Death": 0x0000F0,
|
|
"Crossbow Shooter": 0x0000F1,
|
|
"Bomb Thrower": 0x0000F2,
|
|
"Bomb Runner": 0x0000F3,
|
|
"Golem": 0x0000F4,
|
|
})
|
|
|
|
# Character names used for slot data
|
|
characters: Final[tuple[str, ...]] = ("Minotaur", "Falconess", "Tigress", "Jackal", "Sumner")
|
|
|
|
# Base item charge count per pickup
|
|
# Some items are bitwise
|
|
base_count: Final[Mapping[str, int]] = MappingProxyType({
|
|
"Key": 1,
|
|
"Lightning Potion": 1,
|
|
"Light Potion": 1,
|
|
"Acid Potion": 1,
|
|
"Fire Potion": 1,
|
|
"Acid Breath": 5,
|
|
"Lightning Breath": 5,
|
|
"Fire Breath": 5,
|
|
"Light Amulet": 30,
|
|
"Acid Amulet": 30,
|
|
"Lightning Amulet": 30,
|
|
"Fire Amulet": 30,
|
|
"Lightning Shield": 10,
|
|
"Fire Shield": 10,
|
|
"Invisibility": 30,
|
|
"Levitate": 30,
|
|
"Speed Boots": 30,
|
|
"3-Way Shot": 30,
|
|
"5-Way Shot": 30,
|
|
"Rapid Fire": 30,
|
|
"Reflective Shot": 30,
|
|
"Reflective Shield": 30,
|
|
"Super Shot": 3,
|
|
"Timestop": 15,
|
|
"Phoenix Familiar": 30,
|
|
"Growth": 30,
|
|
"Shrink": 30,
|
|
"Thunder Hammer": 3,
|
|
"Anti-Death Halo": 30,
|
|
"Invulnerability": 30,
|
|
"Fruit": 50,
|
|
"Meat": 100,
|
|
"Gold": 100,
|
|
"Runestone 1": 1,
|
|
"Runestone 2": 2,
|
|
"Runestone 3": 3,
|
|
"Runestone 4": 4,
|
|
"Runestone 5": 5,
|
|
"Runestone 6": 6,
|
|
"Runestone 7": 7,
|
|
"Runestone 8": 8,
|
|
"Runestone 9": 9,
|
|
"Runestone 10": 10,
|
|
"Runestone 11": 11,
|
|
"Runestone 12": 12,
|
|
"Runestone 13": 13,
|
|
"Dragon Mirror Shard": 1,
|
|
"Chimera Mirror Shard": 3,
|
|
"Plague Fiend Mirror Shard": 4,
|
|
"Yeti Mirror Shard": 2,
|
|
"Valley of Fire Obelisk": 1,
|
|
"Dagger Peak Obelisk": 2,
|
|
"Cliffs of Desolation Obelisk": 3,
|
|
"Poisoned Fields Obelisk": 4,
|
|
"Haunted Cemetery Obelisk": 5,
|
|
"Castle Courtyard Obelisk": 6,
|
|
"Dungeon of Torment Obelisk": 7,
|
|
"Ice Axe of Untar": 1,
|
|
"Flame of Tarkana": 1,
|
|
"Scimitar of Decapitation": 1,
|
|
"Marker's Javelin": 1,
|
|
"Soul Savior": 1,
|
|
"Minotaur": 1,
|
|
"Falconess": 1,
|
|
"Tigress": 1,
|
|
"Jackal": 1,
|
|
"Sumner": 1,
|
|
"Poison Fruit": -50,
|
|
"Skorne's Mask": 50,
|
|
"Skorne's Horns": 50,
|
|
"Skorne's Left Gauntlet": 100,
|
|
"Skorne's Right Gauntlet": 100,
|
|
"Portal to Dagger Peak": 1,
|
|
"Portal to Cliffs of Desolation": 2,
|
|
"Portal to Lost Cave": 3,
|
|
"Portal to Volcanic Caverns": 4,
|
|
"Portal to Dragon's Lair": 5,
|
|
"Portal to Dungeon of Torment": 1,
|
|
"Portal to Tower Armory": 2,
|
|
"Portal to Castle Treasury": 3,
|
|
"Portal to Chimera's Keep": 4,
|
|
"Portal to Haunted Cemetery": 1,
|
|
"Portal to Venomous Spire": 2,
|
|
"Portal to Toxic Air Ship": 3,
|
|
"Portal to Vat of the Plague Fiend": 4,
|
|
"Portal to Frozen Camp": 1,
|
|
"Portal to Crystal Mine": 2,
|
|
"Portal to Erupting Fissure": 3,
|
|
"Portal to Yeti's Cavern": 4,
|
|
"Portal to Fortified Towers": 1,
|
|
"Portal to Infernal Fortress": 2,
|
|
"Death": 1,
|
|
"Crossbow Shooter": 1,
|
|
"Bomb Thrower": 1,
|
|
"Bomb Runner": 1,
|
|
"Golem": 1
|
|
})
|
|
|
|
# (zone_config << 4) + room_config -> location list
|
|
level_locations: Final[Mapping[int, Sequence[LocationData]]] = MappingProxyType({
|
|
# Zone 0x00 - Castle
|
|
0x00: get_locations_by_tags("castle_courtyard"),
|
|
0x01: get_locations_by_tags("dungeon_of_torment"),
|
|
0x02: get_locations_by_tags("tower_armory"),
|
|
0x03: get_locations_by_tags("castle_treasury"),
|
|
0x08: get_locations_by_tags("chimeras_keep"),
|
|
|
|
# Zone 0x03 - Mountain
|
|
0x30: get_locations_by_tags("valley_of_fire"),
|
|
0x31: get_locations_by_tags("dagger_peak"),
|
|
0x32: get_locations_by_tags("cliffs_of_desolation"),
|
|
0x33: get_locations_by_tags("lost_cave"),
|
|
0x34: get_locations_by_tags("volcanic_cavern"),
|
|
0x38: get_locations_by_tags("dragons_lair"),
|
|
|
|
# Zone 0x07 - Town
|
|
0x70: get_locations_by_tags("poisoned_fields"),
|
|
0x71: get_locations_by_tags("haunted_cemetery"),
|
|
0x72: get_locations_by_tags("venomous_spire"),
|
|
0x73: get_locations_by_tags("toxic_air_ship"),
|
|
0x78: get_locations_by_tags("plague_fiend"),
|
|
|
|
# Zone 0x05 - Underworld
|
|
0x50: get_locations_by_tags("gates_of_the_underworld"),
|
|
|
|
# Zone 0x06 - Ice
|
|
0x60: get_locations_by_tags("arctic_docks"),
|
|
0x61: get_locations_by_tags("frozen_camp"),
|
|
0x62: get_locations_by_tags("crystal_mine"),
|
|
0x63: get_locations_by_tags("erupting_fissure"),
|
|
0x68: get_locations_by_tags("yeti"),
|
|
|
|
# Zone 0x0D - Temple
|
|
0xD0: get_locations_by_tags("desecrated_temple"),
|
|
0xD8: get_locations_by_tags("altar_of_skorne"),
|
|
|
|
# Zone 0x0C - Battlefield
|
|
0xC0: get_locations_by_tags("battle_trenches"),
|
|
0xC1: get_locations_by_tags("fortified_towers"),
|
|
0xC2: get_locations_by_tags("infernal_fortress"),
|
|
})
|
|
|
|
# Compressed level size in ROM
|
|
level_size: Final[tuple[int, ...]] = (
|
|
0x9E0,
|
|
0x5E0,
|
|
0x740,
|
|
0x8A0,
|
|
0x90,
|
|
0x3B0,
|
|
0x5A0,
|
|
0x890,
|
|
0x670,
|
|
0x7D0,
|
|
0x90,
|
|
0xCE0,
|
|
0xA50,
|
|
0xA30,
|
|
0x8E0,
|
|
0x20,
|
|
0x760,
|
|
0xE90,
|
|
0xE40,
|
|
0xE00,
|
|
0xCD0,
|
|
0x20,
|
|
0x3F0,
|
|
0x0,
|
|
0xB00,
|
|
0xA30,
|
|
0xB30
|
|
)
|
|
|
|
# Level address in ROM
|
|
level_address: Final[tuple[int, ...]] = (
|
|
0xF939B0,
|
|
0xF958B0,
|
|
0xF945B0,
|
|
0xF94EE0,
|
|
0xF84CC0,
|
|
0xF910B0,
|
|
0xF915B0,
|
|
0xF91D00,
|
|
0xF92710,
|
|
0xF92F40,
|
|
0xF84B70,
|
|
0xF84FA0,
|
|
0xF85EB0,
|
|
0xF86B60,
|
|
0xF877C0,
|
|
0xF880E0,
|
|
0xF901C0,
|
|
0xF884E0,
|
|
0xF89370,
|
|
0xF8A5F0,
|
|
0xF8B760,
|
|
0xF8C7C0,
|
|
0xF90B50,
|
|
0x0,
|
|
0xF8D960,
|
|
0xF8E6E0,
|
|
0xF8F110
|
|
)
|
|
|
|
# Level header address in ROM
|
|
level_header: Final[tuple[int, ...]] = (
|
|
0xF9DD9C,
|
|
0xF9E07C,
|
|
0xF9DE54,
|
|
0xF9DF0C,
|
|
0xF9DFC4,
|
|
0xF9E6E0,
|
|
0xF9E798,
|
|
0xF9E850,
|
|
0xF9E908,
|
|
0xF9E9C0,
|
|
0xF9EA78,
|
|
0xF9F004,
|
|
0xF9F0BC,
|
|
0xF9F174,
|
|
0xF9F22C,
|
|
0xF9F2E4,
|
|
0xF9E1C0,
|
|
0xF9E330,
|
|
0xF9E3E4,
|
|
0xF9E498,
|
|
0xF9E54C,
|
|
0xF9E600,
|
|
0xF9DC2C,
|
|
0x0,
|
|
0xF9DA04,
|
|
0xF9DABC,
|
|
0xF9DB74
|
|
)
|
|
|
|
# Runestones required to access difficulties
|
|
# Used in Rules.py for access calculation
|
|
difficulty_lambda: Final[Mapping[int, Sequence[int]]] = MappingProxyType({
|
|
0x3: (0, 2, 3, 4),
|
|
0x0: (0, 5, 6, 7),
|
|
0x7: (0, 8, 9, 10),
|
|
0x6: (0, 11, 12, 13),
|
|
0xD: (0, 14, 15, 16),
|
|
0xC: (0, 17, 18, 19),
|
|
0x5: (0, 20, 21, 22)
|
|
})
|
|
|
|
# Runestones required to access difficulties
|
|
# Used in Rules.py for access calculation
|
|
difficulty_lambda_no_portal: Final[Mapping[int, Sequence[int]]] = MappingProxyType({
|
|
0x3: (0, 0, 1, 2),
|
|
0x0: (0, 2, 3, 4),
|
|
0x7: (0, 5, 6, 7),
|
|
0x6: (0, 8, 9, 10),
|
|
0xD: (0, 11, 12, 13),
|
|
0xC: (0, 14, 15, 16),
|
|
0x5: (0, 17, 18, 19)
|
|
})
|
|
|
|
# ID's for names said by announcer
|
|
sounds: Final[Mapping[int, int]] = MappingProxyType({
|
|
0: 0x9D,
|
|
1: 0x9E,
|
|
2: 0xA7,
|
|
3: 0xA5,
|
|
5: 0x9F,
|
|
6: 0xA1,
|
|
7: 0xA0,
|
|
8: 0xA2,
|
|
9: 0xA7
|
|
})
|
|
|
|
# ID's for colors said by announcer
|
|
colors: Final[Mapping[int, int]] = MappingProxyType({
|
|
0: 0xA3,
|
|
1: 0xA6,
|
|
2: 0x9C,
|
|
3: 0xA4
|
|
})
|
|
|
|
obelisks: Final[tuple[str, ...]] = (
|
|
"Valley of Fire Obelisk",
|
|
"Dagger Peak Obelisk",
|
|
"Cliffs of Desolation Obelisk",
|
|
"Poisoned Fields Obelisk",
|
|
"Haunted Cemetery Obelisk",
|
|
"Castle Courtyard Obelisk",
|
|
"Dungeon of Torment Obelisk"
|
|
)
|
|
|
|
mirror_shards: Final[tuple[str, ...]] = (
|
|
"Dragon Mirror Shard",
|
|
"Chimera Mirror Shard",
|
|
"Yeti Mirror Shard",
|
|
"Plague Fiend Mirror Shard"
|
|
)
|
|
|
|
portals: Final[Mapping[str, str]] = MappingProxyType({
|
|
"Portal to Dagger Peak": "Mountain",
|
|
"Portal to Cliffs of Desolation": "Mountain",
|
|
"Portal to Lost Cave": "Mountain",
|
|
"Portal to Volcanic Caverns": "Mountain",
|
|
"Portal to Dragon's Lair": "Mountain",
|
|
"Portal to Dungeon of Torment": "Castle",
|
|
"Portal to Tower Armory": "Castle",
|
|
"Portal to Castle Treasury": "Castle",
|
|
"Portal to Chimera's Keep": "Castle",
|
|
"Portal to Frozen Camp": "Ice",
|
|
"Portal to Crystal Mine": "Ice",
|
|
"Portal to Erupting Fissure": "Ice",
|
|
"Portal to Yeti's Cavern": "Ice",
|
|
"Portal to Haunted Cemetery": "Town",
|
|
"Portal to Venomous Spire": "Town",
|
|
"Portal to Toxic Air Ship": "Town",
|
|
"Portal to Vat of the Plague Fiend": "Town",
|
|
"Portal to Fortified Towers": "Battlefield",
|
|
"Portal to Infernal Fortress": "Battlefield"
|
|
})
|
|
|
|
excluded_portals: Final[Mapping[str, list[str]]] = MappingProxyType({
|
|
"Castle" : ["Portal to Dungeon of Torment", "Portal to Tower Armory", "Portal to Castle Treasury", "Portal to Chimera's Keep"],
|
|
"Town" : ["Portal to Haunted Cemetery", "Portal to Venomous Spire", "Portal to Toxic Air Ship", "Portal to Vat of the Plague Fiend"],
|
|
"Ice" : ["Portal to Frozen Camp", "Portal to Crystal Mine", "Portal to Erupting Fissure", "Portal to Yeti's Cavern"],
|
|
"Battlefield" : ["Portal to Fortified Towers", "Portal to Infernal Fortress"]
|
|
})
|
|
|
|
excluded_levels: Final[Mapping[str, list[str]]] = MappingProxyType({
|
|
"Mountain" : ["Valley of Fire", "Dagger Peak", "Cliffs of Desolation", "Lost Cave", "Volcanic Caverns", "Dragon's Lair"],
|
|
"Castle" : ["Castle Courtyard" ,"Dungeon of Torment", "Tower Armory", "Castle Treasury", "Chimera's Keep"],
|
|
"Ice" : ["Arctic Docks", "Frozen Camp", "Crystal Mine", "Erupting Fissure", "Yeti's Cavern"],
|
|
"Town" : ["Poisoned Fields", "Haunted Cemetery", "Venomous Spire", "Toxic Air Ship", "Vat of the Plague Fiend"],
|
|
"Battlefield" : ["Battle Trenches", "Fortified Towers", "Infernal Fortress"]
|
|
})
|
|
|
|
excluded_obelisks: Final[Mapping[str, list[str]]] = MappingProxyType({
|
|
"Castle" : ["Valley of Fire Obelisk", "Dagger Peak Obelisk", "Cliffs of Desolation Obelisk"],
|
|
"Town" : ["Castle Courtyard Obelisk", "Dungeon of Torment Obelisk"],
|
|
"Ice" : ["Poisoned Fields Obelisk", "Haunted Cemetery Obelisk"],
|
|
})
|
|
|
|
# Map location names to offsets in decompressed boss.bin
|
|
boss_location_offsets: Final[Mapping[str, int]] = MappingProxyType({
|
|
"Dragon's Lair - Dragon Mirror Shard": 0x9C08,
|
|
"Yeti's Cavern - Yeti Mirror Shard": 0x9C18,
|
|
"Chimera's Keep - Chimera Mirror Shard": 0x9C28,
|
|
"Vat of the Plague Fiend - Plague Fiend Mirror Shard": 0x9C38,
|
|
"Altar of Skorne - Skorne's Mask": 0x9C48,
|
|
"Altar of Skorne - Skorne's Horns": 0x9C58,
|
|
"Altar of Skorne - Skorne's Left Gauntlet": 0x9C68,
|
|
"Altar of Skorne - Skorne's Right Gauntlet": 0x9C78
|
|
})
|
|
|
|
boss_regions: Final[tuple[str, ...]] = (
|
|
"Dragon's Lair",
|
|
"Yeti's Cavern",
|
|
"Chimera's Keep",
|
|
"Vat of the Plague Fiend",
|
|
"Altar of Skorne",
|
|
"Gates of the Underworld",
|
|
)
|
|
|
|
|
|
# Item IDs for spawner traps (77780087-77780090)
|
|
spawner_trap_ids: Final[tuple[int, ...]] = (77780087, 77780088, 77780089, 77780090)
|
|
|
|
player_compass_index: Final[Mapping[int, int]] = MappingProxyType({
|
|
1: 1,
|
|
2: 0,
|
|
3: 3,
|
|
4: 2
|
|
})
|