SA2B: v2.4 - Minigame Madness (#4663)

Changelog:

Features:
- New Goal
  - Minigame Madness
    - Win a certain number of each type of Minigame Trap, then defeat the Finalhazard to win!
	- How many of each Minigame are required can be set by an Option
	- When the required amount of a Minigame has been received, that Minigame can be replayed in the Chao World Lobby
- New optional Location Checks
  - Bigsanity
    - Go fishing with Big in each stage for a Location Check
  - Itemboxsanity
    - Either Extra Life Boxes or All Item Boxes
- New Items
  - New Traps
    - Literature Trap
	- Controller Drift Trap
	- Poison Trap
	- Bee Trap
  - New Minigame Traps
    - Breakout Trap
	- Fishing Trap
	- Trivia Trap
	- Pokemon Trivia Trap
	- Pokemon Count Trap
	- Number Sequence Trap
	- Light Up Path Trap
	- Pinball Trap
	- Math Quiz Trap
	- Snake Trap
	- Input Sequence Trap
- Trap Link
  - When you receive a trap, you send a copy of it to every other player with Trap Link enabled
- Boss Gate Plando
- Expert Logic Difficulty
	- Use at your own risk. This difficulty requires complete mastery of SA2.
- Missions can now be enabled and disabled per-character, instead of just per-style
- Minigame Difficulty can now be set to "Chaos", which selects a new difficulty randomly per-trap received

Quality of Life:
- Gate Stages and Mission Orders are now displayed in the spoiler log
- Additional play stats are saved and displayed with the randomizer credits
- Stage Locations progress UI now displays in multiple pages when Itemboxsanity is enabled
- Current stage mission order and progress are now shown when paused in-level
- Chaos Emeralds are now shown when paused in-level
- Location Name Groups were created
- Moved SA2B to the new Options system
- Option Presets were created
- Error Messages are more obvious

Bug Fixes:
- Added missing `Dry Lagoon - 12 Animals` location
- Flying Dog boss should no longer crash when you have done at least 3 Intermediate Kart Races
- Invincibility can no longer be received in the King Boom Boo fight, preventing a crash
- Chaos Emeralds should no longer disproportionately end up in Cannon's Core or the final Level Gate
- Going into submenus from the pause menu should no longer reset traps
- `Sonic - Magic Gloves` are now plural
- Junk items will no longer cause a crash when in a falling state
- Chao Garden:
	- Prevent races from occasionally becoming uncompletable when using the "Prize Only" option
	- Properly allow Hero Chao to participate in Dark Races
	- Don't allow the Chao Garden to send locations when connected to an invalid server
	- Prevent the Chao Garden from resetting your life count
	- Fix Chao World Entrance Shuffle causing inaccessible Neutral Garden
	- Fix pressing the 'B' button to take you to the proper location in Chao World Entrance Shuffle
	- Prevent Chao Karate progress icon overflow
	- Prevent changing Chao Timescale while paused or while a Minigame is active
- Logic Fixes:
	- `Mission Street - Chao Key 1` (Hard Logic) now requires no upgrades
	- `Mission Street - Chao Key 2` (Hard Logic) now requires no upgrades
	- `Crazy Gadget - Hidden 1` (Standard Logic) now requires `Sonic - Bounce Bracelet` instead of `Sonic - Light Shoes`
	- `Lost Colony - Hidden 1` (Standard Logic) now requires `Eggman - Jet Engine`
	- `Mad Space - Gold Beetle` (Standard Logic) now only requires `Rouge - Iron Boots`
	- `Cosmic Wall - Gold Beetle` (Standard and Hard Logic) now only requires `Eggman - Jet Engine`
This commit is contained in:
PoryGone
2025-03-22 08:00:07 -04:00
committed by GitHub
parent 0e99888926
commit 294a67a4b4
13 changed files with 7612 additions and 2270 deletions

View File

@@ -150,6 +150,26 @@ sample_chao_names = [
"Hubert",
"Corvus",
"Nigel",
"Benjamin",
"Gooey",
"Maddy",
"AFGNCAAP",
"Reinhardt",
"Claire",
"Yoshi",
"Peasley",
"Faux",
"Naija",
"Kaiba",
"Hat Kid",
"TzTokJad",
"Sora",
"WoodMan",
"Yachty",
"Grieve",
"Portia",
"Graves",
"Kaycee",
]
totally_real_item_names = [
@@ -240,6 +260,35 @@ totally_real_item_names = [
"Ladder",
"Visible Dots",
"CooCoo",
"Blueberry",
"Ear of Luigi",
"Mega Nut",
"DUELIST ALLIANCE",
"DUEL OVERLOAD",
"POWER OF THE ELEMENTS",
"S:P Little Knight",
"Red-Eyes Dark Dragoon",
"Fire Hat",
"Area: Taverly",
"Area: Meiyerditch",
"Fire Cape",
"Donald Zeta Flare",
"Category One of a Kind",
"Category Fuller House",
"Passive Camoflage",
"Earth Card",
]
all_exits = [

View File

@@ -1,6 +1,82 @@
# Sonic Adventure 2 Battle - Changelog
## v2.4 - Minigame Madness
### Features:
- New Goal
- Minigame Madness
- Win a certain number of each type of Minigame Trap, then defeat the Finalhazard to win!
- How many of each Minigame are required can be set by an Option
- When the required amount of a Minigame has been received, that Minigame can be replayed in the Chao World Lobby
- New optional Location Checks
- Bigsanity
- Go fishing with Big in each stage for a Location Check
- Itemboxsanity
- Either Extra Life Boxes or All Item Boxes
- New Items
- New Traps
- Literature Trap
- Controller Drift Trap
- Poison Trap
- Bee Trap
- New Minigame Traps
- Breakout Trap
- Fishing Trap
- Trivia Trap
- Pokemon Trivia Trap
- Pokemon Count Trap
- Number Sequence Trap
- Light Up Path Trap
- Pinball Trap
- Math Quiz Trap
- Snake Trap
- Input Sequence Trap
- Trap Link
- When you receive a trap, you send a copy of it to every other player with Trap Link enabled
- Boss Gate Plando
- Expert Logic Difficulty
- Use at your own risk. This difficulty requires complete mastery of SA2.
- Missions can now be enabled and disabled per-character, instead of just per-style
- Minigame Difficulty can now be set to "Chaos", which selects a new difficulty randomly per-trap received
### Quality of Life:
- Gate Stages and Mission Orders are now displayed in the spoiler log
- Additional play stats are saved and displayed with the randomizer credits
- Stage Locations progress UI now displays in multiple pages when Itemboxsanity is enabled
- Current stage mission order and progress are now shown when paused in-level
- Chaos Emeralds are now shown when paused in-level
- Location Name Groups were created
- Moved SA2B to the new Options system
- Option Presets were created
- Error Messages are more obvious
### Bug Fixes:
- Added missing `Dry Lagoon - 12 Animals` location
- Flying Dog boss should no longer crash when you have done at least 3 Intermediate Kart Races
- Invincibility can no longer be received in the King Boom Boo fight, preventing a crash
- Chaos Emeralds should no longer disproportionately end up in Cannon's Core or the final Level Gate
- Going into submenus from the pause menu should no longer reset traps
- `Sonic - Magic Gloves` are now plural
- Junk items will no longer cause a crash when in a falling state
- Chao Garden:
- Prevent races from occasionally becoming uncompletable when using the "Prize Only" option
- Properly allow Hero Chao to participate in Dark Races
- Don't allow the Chao Garden to send locations when connected to an invalid server
- Prevent the Chao Garden from resetting your life count
- Fix Chao World Entrance Shuffle causing inaccessible Neutral Garden
- Fix pressing the 'B' button to take you to the proper location in Chao World Entrance Shuffle
- Prevent Chao Karate progress icon overflow
- Prevent changing Chao Timescale while paused or while a Minigame is active
- Logic Fixes:
- `Mission Street - Chao Key 1` (Hard Logic) now requires no upgrades
- `Mission Street - Chao Key 2` (Hard Logic) now requires no upgrades
- `Crazy Gadget - Hidden 1` (Standard Logic) now requires `Sonic - Bounce Bracelet` instead of `Sonic - Light Shoes`
- `Lost Colony - Hidden 1` (Standard Logic) now requires `Eggman - Jet Engine`
- `Mad Space - Gold Beetle` (Standard Logic) now only requires `Rouge - Iron Boots`
- `Cosmic Wall - Gold Beetle` (Standard and Hard Logic) now only requires `Eggman - Jet Engine`
## v2.3 - The Chao Update
### Features:

View File

@@ -1,18 +1,23 @@
import typing
from BaseClasses import MultiWorld
from worlds.AutoWorld import World
speed_characters_1 = "Sonic vs Shadow 1"
speed_characters_2 = "Sonic vs Shadow 2"
mech_characters_1 = "Tails vs Eggman 1"
mech_characters_2 = "Tails vs Eggman 2"
hunt_characters_1 = "Knuckles vs Rouge 1"
big_foot = "F-6t BIG FOOT"
hot_shot = "B-3x HOT SHOT"
flying_dog = "R-1/A FLYING DOG"
egg_golem_sonic = "Egg Golem (Sonic)"
egg_golem_eggman = "Egg Golem (Eggman)"
king_boom_boo = "King Boom Boo"
from .Names import LocationName
from .Options import GateBossPlando
speed_characters_1 = "sonic vs shadow 1"
speed_characters_2 = "sonic vs shadow 2"
mech_characters_1 = "tails vs eggman 1"
mech_characters_2 = "tails vs eggman 2"
hunt_characters_1 = "knuckles vs rouge 1"
big_foot = "big foot"
hot_shot = "hot shot"
flying_dog = "flying dog"
egg_golem_sonic = "egg golem (sonic)"
egg_golem_eggman = "egg golem (eggman)"
king_boom_boo = "king boom boo"
gate_bosses_no_requirements_table = {
speed_characters_1: 0,
@@ -45,44 +50,83 @@ all_gate_bosses_table = {
}
boss_id_to_name = {
0: "Sonic vs Shadow 1",
1: "Sonic vs Shadow 2",
2: "Tails vs Eggman 1",
3: "Tails vs Eggman 2",
4: "Knuckles vs Rouge 1",
5: "F-6t BIG FOOT",
6: "B-3x HOT SHOT",
7: "R-1/A FLYING DOG",
8: "Egg Golem (Sonic)",
9: "Egg Golem (Eggman)",
10: "King Boom Boo",
11: "Sonic vs Shadow 1",
12: "Sonic vs Shadow 2",
13: "Tails vs Eggman 1",
14: "Tails vs Eggman 2",
15: "Knuckles vs Rouge 1",
}
def get_boss_name(boss: int):
for key, value in gate_bosses_no_requirements_table.items():
if value == boss:
return key
for key, value in gate_bosses_with_requirements_table.items():
if value == boss:
return key
for key, value in extra_boss_rush_bosses_table.items():
if value == boss:
return key
return boss_id_to_name[boss]
def boss_has_requirement(boss: int):
return boss >= len(gate_bosses_no_requirements_table)
def get_gate_bosses(multiworld: MultiWorld, world: World):
def get_gate_bosses(world: World):
selected_bosses: typing.List[int] = []
boss_gates: typing.List[int] = []
available_bosses: typing.List[str] = list(gate_bosses_no_requirements_table.keys())
multiworld.random.shuffle(available_bosses)
halfway = False
world.random.shuffle(available_bosses)
gate_boss_plando: typing.Union[int, str] = world.options.gate_boss_plando.value
plando_bosses = ["None", "None", "None", "None", "None"]
if isinstance(gate_boss_plando, str):
# boss plando
options = gate_boss_plando.split(";")
gate_boss_plando = GateBossPlando.options[options.pop()]
for option in options:
if "-" in option:
loc, boss = option.split("-")
boss_num = LocationName.boss_gate_names[loc]
if boss_num >= world.options.number_of_level_gates.value:
# Don't reject bosses plando'd into gate bosses that won't exist
pass
if boss in plando_bosses:
# TODO: Raise error here. Duplicates not allowed
pass
plando_bosses[boss_num] = boss
if boss in available_bosses:
available_bosses.remove(boss)
for x in range(world.options.number_of_level_gates):
if (not halfway) and ((x + 1) / world.options.number_of_level_gates) > 0.5:
if ("king boom boo" not in selected_bosses) and ("king boom boo" not in available_bosses) and ((x + 1) / world.options.number_of_level_gates) > 0.5:
available_bosses.extend(gate_bosses_with_requirements_table)
multiworld.random.shuffle(available_bosses)
halfway = True
selected_bosses.append(all_gate_bosses_table[available_bosses[0]])
world.random.shuffle(available_bosses)
chosen_boss = available_bosses[0]
if plando_bosses[x] != "None":
available_bosses.append(plando_bosses[x])
chosen_boss = plando_bosses[x]
selected_bosses.append(all_gate_bosses_table[chosen_boss])
boss_gates.append(x + 1)
available_bosses.remove(available_bosses[0])
available_bosses.remove(chosen_boss)
bosses: typing.Dict[int, int] = dict(zip(boss_gates, selected_bosses))
return bosses
def get_boss_rush_bosses(multiworld: MultiWorld, world: World):
def get_boss_rush_bosses(world: World):
if world.options.boss_rush_shuffle == 0:
boss_list_o = list(range(0, 16))
@@ -92,21 +136,21 @@ def get_boss_rush_bosses(multiworld: MultiWorld, world: World):
elif world.options.boss_rush_shuffle == 1:
boss_list_o = list(range(0, 16))
boss_list_s = boss_list_o.copy()
multiworld.random.shuffle(boss_list_s)
world.random.shuffle(boss_list_s)
return dict(zip(boss_list_o, boss_list_s))
elif world.options.boss_rush_shuffle == 2:
boss_list_o = list(range(0, 16))
boss_list_s = [multiworld.random.choice(boss_list_o) for i in range(0, 16)]
boss_list_s = [world.random.choice(boss_list_o) for i in range(0, 16)]
if 10 not in boss_list_s:
boss_list_s[multiworld.random.randint(0, 15)] = 10
boss_list_s[world.random.randint(0, 15)] = 10
return dict(zip(boss_list_o, boss_list_s))
elif world.options.boss_rush_shuffle == 3:
boss_list_o = list(range(0, 16))
boss_list_s = [multiworld.random.choice(boss_list_o)] * len(boss_list_o)
boss_list_s = [world.random.choice(boss_list_o)] * len(boss_list_o)
if 10 not in boss_list_s:
boss_list_s[multiworld.random.randint(0, 15)] = 10
boss_list_s[world.random.randint(0, 15)] = 10
return dict(zip(boss_list_o, boss_list_s))
else:

View File

@@ -2,7 +2,6 @@ import typing
from BaseClasses import Item, ItemClassification
from .Names import ItemName
from worlds.alttp import ALTTPWorld
class ItemData(typing.NamedTuple):
@@ -14,7 +13,7 @@ class ItemData(typing.NamedTuple):
class SA2BItem(Item):
game: str = "Sonic Adventure 2: Battle"
game: str = "Sonic Adventure 2 Battle"
def __init__(self, name, classification: ItemClassification, code: int = None, player: int = None):
super(SA2BItem, self).__init__(name, classification, code, player)
@@ -84,8 +83,25 @@ trap_table = {
ItemName.slow_trap: ItemData(0xFF0038, False, True),
ItemName.cutscene_trap: ItemData(0xFF0039, False, True),
ItemName.reverse_trap: ItemData(0xFF003A, False, True),
ItemName.literature_trap: ItemData(0xFF003B, False, True),
ItemName.controller_drift_trap: ItemData(0xFF003C, False, True),
ItemName.poison_trap: ItemData(0xFF003D, False, True),
ItemName.bee_trap: ItemData(0xFF003E, False, True),
}
minigame_trap_table = {
ItemName.pong_trap: ItemData(0xFF0050, False, True),
ItemName.breakout_trap: ItemData(0xFF0051, False, True),
ItemName.fishing_trap: ItemData(0xFF0052, False, True),
ItemName.trivia_trap: ItemData(0xFF0053, False, True),
ItemName.pokemon_trivia_trap: ItemData(0xFF0054, False, True),
ItemName.pokemon_count_trap: ItemData(0xFF0055, False, True),
ItemName.number_sequence_trap: ItemData(0xFF0056, False, True),
ItemName.light_up_path_trap: ItemData(0xFF0057, False, True),
ItemName.pinball_trap: ItemData(0xFF0058, False, True),
ItemName.math_quiz_trap: ItemData(0xFF0059, False, True),
ItemName.snake_trap: ItemData(0xFF005A, False, True),
ItemName.input_sequence_trap: ItemData(0xFF005B, False, True),
}
emeralds_table = {
@@ -235,7 +251,7 @@ chaos_drives_table = {
}
event_table = {
ItemName.maria: ItemData(0xFF001D, True),
ItemName.maria: ItemData(None, True),
}
# Complete item table.
@@ -244,6 +260,7 @@ item_table = {
**upgrades_table,
**junk_table,
**trap_table,
**minigame_trap_table,
**emeralds_table,
**eggs_table,
**fruits_table,
@@ -251,7 +268,6 @@ item_table = {
**hats_table,
**animals_table,
**chaos_drives_table,
**event_table,
}
lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_table.items() if data.code}
@@ -263,7 +279,12 @@ item_groups: typing.Dict[str, str] = {
"Seeds": list(seeds_table.keys()),
"Hats": list(hats_table.keys()),
"Traps": list(trap_table.keys()),
"Minigames": list(minigame_trap_table.keys()),
}
ALTTPWorld.pedestal_credit_texts[item_table[ItemName.sonic_light_shoes].code] = "and the Soap Shoes"
ALTTPWorld.pedestal_credit_texts[item_table[ItemName.shadow_air_shoes].code] = "and the Soap Shoes"
try:
from worlds.alttp import ALTTPWorld
ALTTPWorld.pedestal_credit_texts[item_table[ItemName.sonic_light_shoes].code] = "and the Soap Shoes"
ALTTPWorld.pedestal_credit_texts[item_table[ItemName.shadow_air_shoes].code] = "and the Soap Shoes"
except ModuleNotFoundError:
pass

File diff suppressed because it is too large Load Diff

View File

@@ -119,11 +119,14 @@ mission_orders: typing.List[typing.List[int]] = [
[4, 5, 3, 2, 1],
]
### 0: Speed
### 1: Mech
### 2: Hunt
### 3: Kart
### 4: Cannon's Core
### 0: Sonic
### 1: Tails
### 2: Knuckles
### 3: Shadow
### 4: Eggman
### 5: Rouge
### 6: Kart
### 7: Cannon's Core
level_styles: typing.List[int] = [
0,
2,
@@ -133,7 +136,7 @@ level_styles: typing.List[int] = [
2,
1,
2,
3,
6,
1,
0,
2,
@@ -142,22 +145,22 @@ level_styles: typing.List[int] = [
0,
0,
1,
2,
1,
0,
2,
1,
1,
2,
0,
3,
0,
2,
1,
0,
4,
5,
4,
3,
5,
4,
4,
5,
3,
6,
3,
5,
4,
3,
7,
]
stage_name_prefixes: typing.List[str] = [
@@ -201,21 +204,33 @@ def get_mission_count_table(multiworld: MultiWorld, world: World, player: int):
for level in range(31):
mission_count_table[level] = 0
else:
speed_active_missions = 1
mech_active_missions = 1
hunt_active_missions = 1
sonic_active_missions = 1
tails_active_missions = 1
knuckles_active_missions = 1
shadow_active_missions = 1
eggman_active_missions = 1
rouge_active_missions = 1
kart_active_missions = 1
cannons_core_active_missions = 1
for i in range(2,6):
if getattr(world.options, "speed_mission_" + str(i), None):
speed_active_missions += 1
if getattr(world.options, "sonic_mission_" + str(i), None):
sonic_active_missions += 1
if getattr(world.options, "mech_mission_" + str(i), None):
mech_active_missions += 1
if getattr(world.options, "tails_mission_" + str(i), None):
tails_active_missions += 1
if getattr(world.options, "hunt_mission_" + str(i), None):
hunt_active_missions += 1
if getattr(world.options, "knuckles_mission_" + str(i), None):
knuckles_active_missions += 1
if getattr(world.options, "shadow_mission_" + str(i), None):
shadow_active_missions += 1
if getattr(world.options, "eggman_mission_" + str(i), None):
eggman_active_missions += 1
if getattr(world.options, "rouge_mission_" + str(i), None):
rouge_active_missions += 1
if getattr(world.options, "kart_mission_" + str(i), None):
kart_active_missions += 1
@@ -223,16 +238,22 @@ def get_mission_count_table(multiworld: MultiWorld, world: World, player: int):
if getattr(world.options, "cannons_core_mission_" + str(i), None):
cannons_core_active_missions += 1
speed_active_missions = min(speed_active_missions, world.options.speed_mission_count.value)
mech_active_missions = min(mech_active_missions, world.options.mech_mission_count.value)
hunt_active_missions = min(hunt_active_missions, world.options.hunt_mission_count.value)
sonic_active_missions = min(sonic_active_missions, world.options.sonic_mission_count.value)
tails_active_missions = min(tails_active_missions, world.options.tails_mission_count.value)
knuckles_active_missions = min(knuckles_active_missions, world.options.knuckles_mission_count.value)
shadow_active_missions = min(shadow_active_missions, world.options.sonic_mission_count.value)
eggman_active_missions = min(eggman_active_missions, world.options.eggman_mission_count.value)
rouge_active_missions = min(rouge_active_missions, world.options.rouge_mission_count.value)
kart_active_missions = min(kart_active_missions, world.options.kart_mission_count.value)
cannons_core_active_missions = min(cannons_core_active_missions, world.options.cannons_core_mission_count.value)
active_missions: typing.List[typing.List[int]] = [
speed_active_missions,
mech_active_missions,
hunt_active_missions,
sonic_active_missions,
tails_active_missions,
knuckles_active_missions,
shadow_active_missions,
eggman_active_missions,
rouge_active_missions,
kart_active_missions,
cannons_core_active_missions
]
@@ -252,22 +273,34 @@ def get_mission_table(multiworld: MultiWorld, world: World, player: int):
for level in range(31):
mission_table[level] = 0
else:
speed_active_missions: typing.List[int] = [1]
mech_active_missions: typing.List[int] = [1]
hunt_active_missions: typing.List[int] = [1]
sonic_active_missions: typing.List[int] = [1]
tails_active_missions: typing.List[int] = [1]
knuckles_active_missions: typing.List[int] = [1]
shadow_active_missions: typing.List[int] = [1]
eggman_active_missions: typing.List[int] = [1]
rouge_active_missions: typing.List[int] = [1]
kart_active_missions: typing.List[int] = [1]
cannons_core_active_missions: typing.List[int] = [1]
# Add included missions
for i in range(2,6):
if getattr(world.options, "speed_mission_" + str(i), None):
speed_active_missions.append(i)
if getattr(world.options, "sonic_mission_" + str(i), None):
sonic_active_missions.append(i)
if getattr(world.options, "mech_mission_" + str(i), None):
mech_active_missions.append(i)
if getattr(world.options, "tails_mission_" + str(i), None):
tails_active_missions.append(i)
if getattr(world.options, "hunt_mission_" + str(i), None):
hunt_active_missions.append(i)
if getattr(world.options, "knuckles_mission_" + str(i), None):
knuckles_active_missions.append(i)
if getattr(world.options, "shadow_mission_" + str(i), None):
shadow_active_missions.append(i)
if getattr(world.options, "eggman_mission_" + str(i), None):
eggman_active_missions.append(i)
if getattr(world.options, "rouge_mission_" + str(i), None):
rouge_active_missions.append(i)
if getattr(world.options, "kart_mission_" + str(i), None):
kart_active_missions.append(i)
@@ -276,9 +309,12 @@ def get_mission_table(multiworld: MultiWorld, world: World, player: int):
cannons_core_active_missions.append(i)
active_missions: typing.List[typing.List[int]] = [
speed_active_missions,
mech_active_missions,
hunt_active_missions,
sonic_active_missions,
tails_active_missions,
knuckles_active_missions,
shadow_active_missions,
eggman_active_missions,
rouge_active_missions,
kart_active_missions,
cannons_core_active_missions
]
@@ -338,3 +374,50 @@ def get_first_and_last_cannons_core_missions(mission_map: typing.Dict[int, int],
last_location_name: str = stage_prefix + str(last_mission_number)
return first_location_name, last_location_name
def print_mission_orders_to_spoiler(mission_map: typing.Dict[int, int],
mission_count_map: typing.Dict[int, int],
shuffled_region_list: typing.Dict[int, int],
levels_per_gate: typing.Dict[int, int],
player_name: str,
spoiler_handle: typing.TextIO):
spoiler_handle.write("\n")
header_text = "SA2 Mission Orders for {}:\n"
header_text = header_text.format(player_name)
spoiler_handle.write(header_text)
level_index = 0
for gate_idx in range(len(levels_per_gate)):
gate_len = levels_per_gate[gate_idx]
gate_levels = shuffled_region_list[int(level_index):int(level_index+gate_len)]
gate_levels.sort()
gate_text = "Gate {}:\n"
gate_text = gate_text.format(gate_idx)
spoiler_handle.write(gate_text)
for i in range(len(gate_levels)):
stage = gate_levels[i]
mission_count = mission_count_map[stage]
mission_order: typing.List[int] = mission_orders[mission_map[stage]]
stage_prefix: str = stage_name_prefixes[stage]
for mission in range(mission_count):
stage_prefix += str(mission_order[mission]) + " "
spoiler_handle.write(stage_prefix)
spoiler_handle.write("\n")
level_index += gate_len
spoiler_handle.write("\n")
mission_count = mission_count_map[30]
mission_order: typing.List[int] = mission_orders[mission_map[30]]
stage_prefix: str = stage_name_prefixes[30]
for mission in range(mission_count):
stage_prefix += str(mission_order[mission]) + " "
spoiler_handle.write(stage_prefix)
spoiler_handle.write("\n\n")

View File

@@ -5,7 +5,7 @@ emblem = "Emblem"
market_token = "Chao Coin"
# Upgrade Definitions
sonic_gloves = "Sonic - Magic Glove"
sonic_gloves = "Sonic - Magic Gloves"
sonic_light_shoes = "Sonic - Light Shoes"
sonic_ancient_light = "Sonic - Ancient Light"
sonic_bounce_bracelet = "Sonic - Bounce Bracelet"
@@ -62,8 +62,23 @@ ice_trap = "Ice Trap"
slow_trap = "Slow Trap"
cutscene_trap = "Cutscene Trap"
reverse_trap = "Reverse Trap"
literature_trap = "Literature Trap"
controller_drift_trap = "Controller Drift Trap"
poison_trap = "Poison Trap"
bee_trap = "Bee Trap"
pong_trap = "Pong Trap"
breakout_trap = "Breakout Trap"
fishing_trap = "Fishing Trap"
trivia_trap = "Trivia Trap"
pokemon_trivia_trap = "Pokemon Trivia Trap"
pokemon_count_trap = "Pokemon Count Trap"
number_sequence_trap = "Number Sequence Trap"
light_up_path_trap = "Light Up Path Trap"
pinball_trap = "Pinball Trap"
math_quiz_trap = "Math Quiz Trap"
snake_trap = "Snake Trap"
input_sequence_trap = "Input Sequence Trap"
# Chaos Emeralds

View File

@@ -51,6 +51,18 @@ city_escape_animal_17 = "City Escape - 17 Animals"
city_escape_animal_18 = "City Escape - 18 Animals"
city_escape_animal_19 = "City Escape - 19 Animals"
city_escape_animal_20 = "City Escape - 20 Animals"
city_escape_lifebox_1 = "City Escape - Extra Life Box 1"
city_escape_lifebox_2 = "City Escape - Extra Life Box 2"
city_escape_itembox_1 = "City Escape - Item Box 1"
city_escape_itembox_2 = "City Escape - Item Box 2"
city_escape_itembox_3 = "City Escape - Item Box 3"
city_escape_itembox_4 = "City Escape - Item Box 4"
city_escape_itembox_5 = "City Escape - Item Box 5"
city_escape_itembox_6 = "City Escape - Item Box 6"
city_escape_itembox_7 = "City Escape - Item Box 7"
city_escape_itembox_8 = "City Escape - Item Box 8"
city_escape_itembox_9 = "City Escape - Item Box 9"
city_escape_big = "City Escape - Big"
city_escape_upgrade = "City Escape - Upgrade"
metal_harbor_1 = "Metal Harbor - 1"
metal_harbor_2 = "Metal Harbor - 2"
@@ -81,6 +93,15 @@ metal_harbor_animal_11 = "Metal Harbor - 11 Animals"
metal_harbor_animal_12 = "Metal Harbor - 12 Animals"
metal_harbor_animal_13 = "Metal Harbor - 13 Animals"
metal_harbor_animal_14 = "Metal Harbor - 14 Animals"
metal_harbor_lifebox_1 = "Metal Harbor - Extra Life Box 1"
metal_harbor_lifebox_2 = "Metal Harbor - Extra Life Box 2"
metal_harbor_lifebox_3 = "Metal Harbor - Extra Life Box 3"
metal_harbor_itembox_1 = "Metal Harbor - Item Box 1"
metal_harbor_itembox_2 = "Metal Harbor - Item Box 2"
metal_harbor_itembox_3 = "Metal Harbor - Item Box 3"
metal_harbor_itembox_4 = "Metal Harbor - Item Box 4"
metal_harbor_itembox_5 = "Metal Harbor - Item Box 5"
metal_harbor_big = "Metal Harbor - Big"
metal_harbor_upgrade = "Metal Harbor - Upgrade"
green_forest_1 = "Green Forest - 1"
green_forest_2 = "Green Forest - 2"
@@ -115,6 +136,24 @@ green_forest_animal_15 = "Green Forest - 15 Animals"
green_forest_animal_16 = "Green Forest - 16 Animals"
green_forest_animal_17 = "Green Forest - 17 Animals"
green_forest_animal_18 = "Green Forest - 18 Animals"
green_forest_lifebox_1 = "Green Forest - Extra Life Box 1"
green_forest_lifebox_2 = "Green Forest - Extra Life Box 2"
green_forest_lifebox_3 = "Green Forest - Extra Life Box 3"
green_forest_lifebox_4 = "Green Forest - Extra Life Box 4"
green_forest_itembox_1 = "Green Forest - Item Box 1"
green_forest_itembox_2 = "Green Forest - Item Box 2"
green_forest_itembox_3 = "Green Forest - Item Box 3"
green_forest_itembox_4 = "Green Forest - Item Box 4"
green_forest_itembox_5 = "Green Forest - Item Box 5"
green_forest_itembox_6 = "Green Forest - Item Box 6"
green_forest_itembox_7 = "Green Forest - Item Box 7"
green_forest_itembox_8 = "Green Forest - Item Box 8"
green_forest_itembox_9 = "Green Forest - Item Box 9"
green_forest_itembox_10 = "Green Forest - Item Box 10"
green_forest_itembox_11 = "Green Forest - Item Box 11"
green_forest_itembox_12 = "Green Forest - Item Box 12"
green_forest_itembox_13 = "Green Forest - Item Box 13"
green_forest_big = "Green Forest - Big"
green_forest_upgrade = "Green Forest - Upgrade"
pyramid_cave_1 = "Pyramid Cave - 1"
pyramid_cave_2 = "Pyramid Cave - 2"
@@ -152,6 +191,29 @@ pyramid_cave_animal_16 = "Pyramid Cave - 16 Animals"
pyramid_cave_animal_17 = "Pyramid Cave - 17 Animals"
pyramid_cave_animal_18 = "Pyramid Cave - 18 Animals"
pyramid_cave_animal_19 = "Pyramid Cave - 19 Animals"
pyramid_cave_lifebox_1 = "Pyramid Cave - Extra Life Box 1"
pyramid_cave_lifebox_2 = "Pyramid Cave - Extra Life Box 2"
pyramid_cave_lifebox_3 = "Pyramid Cave - Extra Life Box 3"
pyramid_cave_lifebox_4 = "Pyramid Cave - Extra Life Box 4"
pyramid_cave_lifebox_5 = "Pyramid Cave - Extra Life Box 5"
pyramid_cave_lifebox_6 = "Pyramid Cave - Extra Life Box 6"
pyramid_cave_lifebox_7 = "Pyramid Cave - Extra Life Box 7"
pyramid_cave_itembox_1 = "Pyramid Cave - Item Box 1"
pyramid_cave_itembox_2 = "Pyramid Cave - Item Box 2"
pyramid_cave_itembox_3 = "Pyramid Cave - Item Box 3"
pyramid_cave_itembox_4 = "Pyramid Cave - Item Box 4"
pyramid_cave_itembox_5 = "Pyramid Cave - Item Box 5"
pyramid_cave_itembox_6 = "Pyramid Cave - Item Box 6"
pyramid_cave_itembox_7 = "Pyramid Cave - Item Box 7"
pyramid_cave_itembox_8 = "Pyramid Cave - Item Box 8"
pyramid_cave_itembox_9 = "Pyramid Cave - Item Box 9"
pyramid_cave_itembox_10 = "Pyramid Cave - Item Box 10"
pyramid_cave_itembox_11 = "Pyramid Cave - Item Box 11"
pyramid_cave_itembox_12 = "Pyramid Cave - Item Box 12"
pyramid_cave_itembox_13 = "Pyramid Cave - Item Box 13"
pyramid_cave_itembox_14 = "Pyramid Cave - Item Box 14"
pyramid_cave_itembox_15 = "Pyramid Cave - Item Box 15"
pyramid_cave_big = "Pyramid Cave - Big"
pyramid_cave_upgrade = "Pyramid Cave - Upgrade"
crazy_gadget_1 = "Crazy Gadget - 1"
crazy_gadget_2 = "Crazy Gadget - 2"
@@ -196,6 +258,25 @@ crazy_gadget_animal_13 = "Crazy Gadget - 13 Animals"
crazy_gadget_animal_14 = "Crazy Gadget - 14 Animals"
crazy_gadget_animal_15 = "Crazy Gadget - 15 Animals"
crazy_gadget_animal_16 = "Crazy Gadget - 16 Animals"
crazy_gadget_lifebox_1 = "Crazy Gadget - Extra Life Box 1"
crazy_gadget_lifebox_2 = "Crazy Gadget - Extra Life Box 2"
crazy_gadget_lifebox_3 = "Crazy Gadget - Extra Life Box 3"
crazy_gadget_lifebox_4 = "Crazy Gadget - Extra Life Box 4"
crazy_gadget_itembox_1 = "Crazy Gadget - Item Box 1"
crazy_gadget_itembox_2 = "Crazy Gadget - Item Box 2"
crazy_gadget_itembox_3 = "Crazy Gadget - Item Box 3"
crazy_gadget_itembox_4 = "Crazy Gadget - Item Box 4"
crazy_gadget_itembox_5 = "Crazy Gadget - Item Box 5"
crazy_gadget_itembox_6 = "Crazy Gadget - Item Box 6"
crazy_gadget_itembox_7 = "Crazy Gadget - Item Box 7"
crazy_gadget_itembox_8 = "Crazy Gadget - Item Box 8"
crazy_gadget_itembox_9 = "Crazy Gadget - Item Box 9"
crazy_gadget_itembox_10 = "Crazy Gadget - Item Box 10"
crazy_gadget_itembox_11 = "Crazy Gadget - Item Box 11"
crazy_gadget_itembox_12 = "Crazy Gadget - Item Box 12"
crazy_gadget_itembox_13 = "Crazy Gadget - Item Box 13"
crazy_gadget_itembox_14 = "Crazy Gadget - Item Box 14"
crazy_gadget_big = "Crazy Gadget - Big"
crazy_gadget_upgrade = "Crazy Gadget - Upgrade"
final_rush_1 = "Final Rush - 1"
final_rush_2 = "Final Rush - 2"
@@ -227,6 +308,60 @@ final_rush_animal_13 = "Final Rush - 13 Animals"
final_rush_animal_14 = "Final Rush - 14 Animals"
final_rush_animal_15 = "Final Rush - 15 Animals"
final_rush_animal_16 = "Final Rush - 16 Animals"
final_rush_lifebox_1 = "Final Rush - Extra Life Box 1"
final_rush_lifebox_2 = "Final Rush - Extra Life Box 2"
final_rush_lifebox_3 = "Final Rush - Extra Life Box 3"
final_rush_lifebox_4 = "Final Rush - Extra Life Box 4"
final_rush_lifebox_5 = "Final Rush - Extra Life Box 5"
final_rush_lifebox_6 = "Final Rush - Extra Life Box 6"
final_rush_lifebox_7 = "Final Rush - Extra Life Box 7"
final_rush_lifebox_8 = "Final Rush - Extra Life Box 8"
final_rush_lifebox_9 = "Final Rush - Extra Life Box 9"
final_rush_lifebox_10 = "Final Rush - Extra Life Box 10"
final_rush_lifebox_11 = "Final Rush - Extra Life Box 11"
final_rush_lifebox_12 = "Final Rush - Extra Life Box 12"
final_rush_lifebox_13 = "Final Rush - Extra Life Box 13"
final_rush_itembox_1 = "Final Rush - Item Box 1"
final_rush_itembox_2 = "Final Rush - Item Box 2"
final_rush_itembox_3 = "Final Rush - Item Box 3"
final_rush_itembox_4 = "Final Rush - Item Box 4"
final_rush_itembox_5 = "Final Rush - Item Box 5"
final_rush_itembox_6 = "Final Rush - Item Box 6"
final_rush_itembox_7 = "Final Rush - Item Box 7"
final_rush_itembox_8 = "Final Rush - Item Box 8"
final_rush_itembox_9 = "Final Rush - Item Box 9"
final_rush_itembox_10 = "Final Rush - Item Box 10"
final_rush_itembox_11 = "Final Rush - Item Box 11"
final_rush_itembox_12 = "Final Rush - Item Box 12"
final_rush_itembox_13 = "Final Rush - Item Box 13"
final_rush_itembox_14 = "Final Rush - Item Box 14"
final_rush_itembox_15 = "Final Rush - Item Box 15"
final_rush_itembox_16 = "Final Rush - Item Box 16"
final_rush_itembox_17 = "Final Rush - Item Box 17"
final_rush_itembox_18 = "Final Rush - Item Box 18"
final_rush_itembox_19 = "Final Rush - Item Box 19"
final_rush_itembox_20 = "Final Rush - Item Box 20"
final_rush_itembox_21 = "Final Rush - Item Box 21"
final_rush_itembox_22 = "Final Rush - Item Box 22"
final_rush_itembox_23 = "Final Rush - Item Box 23"
final_rush_itembox_24 = "Final Rush - Item Box 24"
final_rush_itembox_25 = "Final Rush - Item Box 25"
final_rush_itembox_26 = "Final Rush - Item Box 26"
final_rush_itembox_27 = "Final Rush - Item Box 27"
final_rush_itembox_28 = "Final Rush - Item Box 28"
final_rush_itembox_29 = "Final Rush - Item Box 29"
final_rush_itembox_30 = "Final Rush - Item Box 30"
final_rush_itembox_31 = "Final Rush - Item Box 31"
final_rush_itembox_32 = "Final Rush - Item Box 32"
final_rush_itembox_33 = "Final Rush - Item Box 33"
final_rush_itembox_34 = "Final Rush - Item Box 34"
final_rush_itembox_35 = "Final Rush - Item Box 35"
final_rush_itembox_36 = "Final Rush - Item Box 36"
final_rush_itembox_37 = "Final Rush - Item Box 37"
final_rush_itembox_38 = "Final Rush - Item Box 38"
final_rush_itembox_39 = "Final Rush - Item Box 39"
final_rush_itembox_40 = "Final Rush - Item Box 40"
final_rush_big = "Final Rush - Big"
final_rush_upgrade = "Final Rush - Upgrade"
# Tails Mission Definitions
@@ -270,6 +405,15 @@ prison_lane_animal_12 = "Prison Lane - 12 Animals"
prison_lane_animal_13 = "Prison Lane - 13 Animals"
prison_lane_animal_14 = "Prison Lane - 14 Animals"
prison_lane_animal_15 = "Prison Lane - 15 Animals"
prison_lane_lifebox_1 = "Prison Lane - Extra Life Box 1"
prison_lane_lifebox_2 = "Prison Lane - Extra Life Box 2"
prison_lane_itembox_1 = "Prison Lane - Item Box 1"
prison_lane_itembox_2 = "Prison Lane - Item Box 2"
prison_lane_itembox_3 = "Prison Lane - Item Box 3"
prison_lane_itembox_4 = "Prison Lane - Item Box 4"
prison_lane_itembox_5 = "Prison Lane - Item Box 5"
prison_lane_itembox_6 = "Prison Lane - Item Box 6"
prison_lane_big = "Prison Lane - Big"
prison_lane_upgrade = "Prison Lane - Upgrade"
mission_street_1 = "Mission Street - 1"
mission_street_2 = "Mission Street - 2"
@@ -311,12 +455,26 @@ mission_street_animal_13 = "Mission Street - 13 Animals"
mission_street_animal_14 = "Mission Street - 14 Animals"
mission_street_animal_15 = "Mission Street - 15 Animals"
mission_street_animal_16 = "Mission Street - 16 Animals"
mission_street_lifebox_1 = "Mission Street - Extra Life Box 1"
mission_street_lifebox_2 = "Mission Street - Extra Life Box 2"
mission_street_itembox_1 = "Mission Street - Item Box 1"
mission_street_itembox_2 = "Mission Street - Item Box 2"
mission_street_itembox_3 = "Mission Street - Item Box 3"
mission_street_itembox_4 = "Mission Street - Item Box 4"
mission_street_itembox_5 = "Mission Street - Item Box 5"
mission_street_itembox_6 = "Mission Street - Item Box 6"
mission_street_big = "Mission Street - Big"
mission_street_upgrade = "Mission Street - Upgrade"
route_101_1 = "Route 101 - 1"
route_101_2 = "Route 101 - 2"
route_101_3 = "Route 101 - 3"
route_101_4 = "Route 101 - 4"
route_101_5 = "Route 101 - 5"
route_101_itembox_1 = "Route 101 - Balloon 1"
route_101_itembox_2 = "Route 101 - Balloon 2"
route_101_itembox_3 = "Route 101 - Balloon 3"
route_101_itembox_4 = "Route 101 - Balloon 4"
route_101_itembox_5 = "Route 101 - Balloon 5"
hidden_base_1 = "Hidden Base - 1"
hidden_base_2 = "Hidden Base - 2"
hidden_base_3 = "Hidden Base - 3"
@@ -349,6 +507,13 @@ hidden_base_animal_12 = "Hidden Base - 12 Animals"
hidden_base_animal_13 = "Hidden Base - 13 Animals"
hidden_base_animal_14 = "Hidden Base - 14 Animals"
hidden_base_animal_15 = "Hidden Base - 15 Animals"
hidden_base_lifebox_1 = "Hidden Base - Extra Life Box 1"
hidden_base_itembox_1 = "Hidden Base - Item Box 1"
hidden_base_itembox_2 = "Hidden Base - Item Box 2"
hidden_base_itembox_3 = "Hidden Base - Item Box 3"
hidden_base_itembox_4 = "Hidden Base - Item Box 4"
hidden_base_itembox_5 = "Hidden Base - Item Box 5"
hidden_base_big = "Hidden Base - Big"
hidden_base_upgrade = "Hidden Base - Upgrade"
eternal_engine_1 = "Eternal Engine - 1"
eternal_engine_2 = "Eternal Engine - 2"
@@ -391,6 +556,23 @@ eternal_engine_animal_12 = "Eternal Engine - 12 Animals"
eternal_engine_animal_13 = "Eternal Engine - 13 Animals"
eternal_engine_animal_14 = "Eternal Engine - 14 Animals"
eternal_engine_animal_15 = "Eternal Engine - 15 Animals"
eternal_engine_lifebox_1 = "Eternal Engine - Extra Life Box 1"
eternal_engine_lifebox_2 = "Eternal Engine - Extra Life Box 2"
eternal_engine_itembox_1 = "Eternal Engine - Item Box 1"
eternal_engine_itembox_2 = "Eternal Engine - Item Box 2"
eternal_engine_itembox_3 = "Eternal Engine - Item Box 3"
eternal_engine_itembox_4 = "Eternal Engine - Item Box 4"
eternal_engine_itembox_5 = "Eternal Engine - Item Box 5"
eternal_engine_itembox_6 = "Eternal Engine - Item Box 6"
eternal_engine_itembox_7 = "Eternal Engine - Item Box 7"
eternal_engine_itembox_8 = "Eternal Engine - Item Box 8"
eternal_engine_itembox_9 = "Eternal Engine - Item Box 9"
eternal_engine_itembox_10 = "Eternal Engine - Item Box 10"
eternal_engine_itembox_11 = "Eternal Engine - Item Box 11"
eternal_engine_itembox_12 = "Eternal Engine - Item Box 12"
eternal_engine_itembox_13 = "Eternal Engine - Item Box 13"
eternal_engine_itembox_14 = "Eternal Engine - Item Box 14"
eternal_engine_big = "Eternal Engine - Big"
eternal_engine_upgrade = "Eternal Engine - Upgrade"
# Knuckles Mission Definitions
@@ -426,6 +608,16 @@ wild_canyon_animal_7 = "Wild Canyon - 7 Animals"
wild_canyon_animal_8 = "Wild Canyon - 8 Animals"
wild_canyon_animal_9 = "Wild Canyon - 9 Animals"
wild_canyon_animal_10 = "Wild Canyon - 10 Animals"
wild_canyon_lifebox_1 = "Wild Canyon - Extra Life Box 1"
wild_canyon_lifebox_2 = "Wild Canyon - Extra Life Box 2"
wild_canyon_itembox_1 = "Wild Canyon - Item Box 1"
wild_canyon_itembox_2 = "Wild Canyon - Item Box 2"
wild_canyon_itembox_3 = "Wild Canyon - Item Box 3"
wild_canyon_itembox_4 = "Wild Canyon - Item Box 4"
wild_canyon_itembox_5 = "Wild Canyon - Item Box 5"
wild_canyon_itembox_6 = "Wild Canyon - Item Box 6"
wild_canyon_itembox_7 = "Wild Canyon - Item Box 7"
wild_canyon_itembox_8 = "Wild Canyon - Item Box 8"
wild_canyon_upgrade = "Wild Canyon - Upgrade"
pumpkin_hill_1 = "Pumpkin Hill - 1"
pumpkin_hill_2 = "Pumpkin Hill - 2"
@@ -459,6 +651,18 @@ pumpkin_hill_animal_8 = "Pumpkin Hill - 8 Animals"
pumpkin_hill_animal_9 = "Pumpkin Hill - 9 Animals"
pumpkin_hill_animal_10 = "Pumpkin Hill - 10 Animals"
pumpkin_hill_animal_11 = "Pumpkin Hill - 11 Animals"
pumpkin_hill_lifebox_1 = "Pumpkin Hill - Extra Life Box 1"
pumpkin_hill_itembox_1 = "Pumpkin Hill - Item Box 1"
pumpkin_hill_itembox_2 = "Pumpkin Hill - Item Box 2"
pumpkin_hill_itembox_3 = "Pumpkin Hill - Item Box 3"
pumpkin_hill_itembox_4 = "Pumpkin Hill - Item Box 4"
pumpkin_hill_itembox_5 = "Pumpkin Hill - Item Box 5"
pumpkin_hill_itembox_6 = "Pumpkin Hill - Item Box 6"
pumpkin_hill_itembox_7 = "Pumpkin Hill - Item Box 7"
pumpkin_hill_itembox_8 = "Pumpkin Hill - Item Box 8"
pumpkin_hill_itembox_9 = "Pumpkin Hill - Item Box 9"
pumpkin_hill_itembox_10 = "Pumpkin Hill - Item Box 10"
pumpkin_hill_big = "Pumpkin Hill - Big"
pumpkin_hill_upgrade = "Pumpkin Hill - Upgrade"
aquatic_mine_1 = "Aquatic Mine - 1"
aquatic_mine_2 = "Aquatic Mine - 2"
@@ -489,6 +693,14 @@ aquatic_mine_animal_7 = "Aquatic Mine - 7 Animals"
aquatic_mine_animal_8 = "Aquatic Mine - 8 Animals"
aquatic_mine_animal_9 = "Aquatic Mine - 9 Animals"
aquatic_mine_animal_10 = "Aquatic Mine - 10 Animals"
aquatic_mine_lifebox_1 = "Aquatic Mine - Extra Life Box 1"
aquatic_mine_itembox_1 = "Aquatic Mine - Item Box 1"
aquatic_mine_itembox_2 = "Aquatic Mine - Item Box 2"
aquatic_mine_itembox_3 = "Aquatic Mine - Item Box 3"
aquatic_mine_itembox_4 = "Aquatic Mine - Item Box 4"
aquatic_mine_itembox_5 = "Aquatic Mine - Item Box 5"
aquatic_mine_itembox_6 = "Aquatic Mine - Item Box 6"
aquatic_mine_big = "Aquatic Mine - Big"
aquatic_mine_upgrade = "Aquatic Mine - Upgrade"
death_chamber_1 = "Death Chamber - 1"
death_chamber_2 = "Death Chamber - 2"
@@ -523,6 +735,19 @@ death_chamber_animal_7 = "Death Chamber - 7 Animals"
death_chamber_animal_8 = "Death Chamber - 8 Animals"
death_chamber_animal_9 = "Death Chamber - 9 Animals"
death_chamber_animal_10 = "Death Chamber - 10 Animals"
death_chamber_lifebox_1 = "Death Chamber - Extra Life Box 1"
death_chamber_itembox_1 = "Death Chamber - Item Box 1"
death_chamber_itembox_2 = "Death Chamber - Item Box 2"
death_chamber_itembox_3 = "Death Chamber - Item Box 3"
death_chamber_itembox_4 = "Death Chamber - Item Box 4"
death_chamber_itembox_5 = "Death Chamber - Item Box 5"
death_chamber_itembox_6 = "Death Chamber - Item Box 6"
death_chamber_itembox_7 = "Death Chamber - Item Box 7"
death_chamber_itembox_8 = "Death Chamber - Item Box 8"
death_chamber_itembox_9 = "Death Chamber - Item Box 9"
death_chamber_itembox_10 = "Death Chamber - Item Box 10"
death_chamber_itembox_11 = "Death Chamber - Item Box 11"
death_chamber_big = "Death Chamber - Big"
death_chamber_upgrade = "Death Chamber - Upgrade"
meteor_herd_1 = "Meteor Herd - 1"
meteor_herd_2 = "Meteor Herd - 2"
@@ -550,6 +775,24 @@ meteor_herd_animal_8 = "Meteor Herd - 8 Animals"
meteor_herd_animal_9 = "Meteor Herd - 9 Animals"
meteor_herd_animal_10 = "Meteor Herd - 10 Animals"
meteor_herd_animal_11 = "Meteor Herd - 11 Animals"
meteor_herd_lifebox_1 = "Meteor Herd - Extra Life Box 1"
meteor_herd_lifebox_2 = "Meteor Herd - Extra Life Box 2"
meteor_herd_lifebox_3 = "Meteor Herd - Extra Life Box 3"
meteor_herd_lifebox_4 = "Meteor Herd - Extra Life Box 4"
meteor_herd_lifebox_5 = "Meteor Herd - Extra Life Box 5"
meteor_herd_itembox_1 = "Meteor Herd - Item Box 1"
meteor_herd_itembox_2 = "Meteor Herd - Item Box 2"
meteor_herd_itembox_3 = "Meteor Herd - Item Box 3"
meteor_herd_itembox_4 = "Meteor Herd - Item Box 4"
meteor_herd_itembox_5 = "Meteor Herd - Item Box 5"
meteor_herd_itembox_6 = "Meteor Herd - Item Box 6"
meteor_herd_itembox_7 = "Meteor Herd - Item Box 7"
meteor_herd_itembox_8 = "Meteor Herd - Item Box 8"
meteor_herd_itembox_9 = "Meteor Herd - Item Box 9"
meteor_herd_itembox_10 = "Meteor Herd - Item Box 10"
meteor_herd_itembox_11 = "Meteor Herd - Item Box 11"
meteor_herd_itembox_12 = "Meteor Herd - Item Box 12"
meteor_herd_big = "Meteor Herd - Big"
meteor_herd_upgrade = "Meteor Herd - Upgrade"
@@ -597,6 +840,16 @@ radical_highway_animal_17 = "Radical Highway - 17 Animals"
radical_highway_animal_18 = "Radical Highway - 18 Animals"
radical_highway_animal_19 = "Radical Highway - 19 Animals"
radical_highway_animal_20 = "Radical Highway - 20 Animals"
radical_highway_lifebox_1 = "Radical Highway - Extra Life Box 1"
radical_highway_lifebox_2 = "Radical Highway - Extra Life Box 2"
radical_highway_itembox_1 = "Radical Highway - Item Box 1"
radical_highway_itembox_2 = "Radical Highway - Item Box 2"
radical_highway_itembox_3 = "Radical Highway - Item Box 3"
radical_highway_itembox_4 = "Radical Highway - Item Box 4"
radical_highway_itembox_5 = "Radical Highway - Item Box 5"
radical_highway_itembox_6 = "Radical Highway - Item Box 6"
radical_highway_itembox_7 = "Radical Highway - Item Box 7"
radical_highway_big = "Radical Highway - Big"
radical_highway_upgrade = "Radical Highway - Upgrade"
white_jungle_1 = "White Jungle - 1"
white_jungle_2 = "White Jungle - 2"
@@ -635,6 +888,18 @@ white_jungle_animal_13 = "White Jungle - 13 Animals"
white_jungle_animal_14 = "White Jungle - 14 Animals"
white_jungle_animal_15 = "White Jungle - 15 Animals"
white_jungle_animal_16 = "White Jungle - 16 Animals"
white_jungle_lifebox_1 = "White Jungle - Extra Life Box 1"
white_jungle_lifebox_2 = "White Jungle - Extra Life Box 2"
white_jungle_itembox_1 = "White Jungle - Item Box 1"
white_jungle_itembox_2 = "White Jungle - Item Box 2"
white_jungle_itembox_3 = "White Jungle - Item Box 3"
white_jungle_itembox_4 = "White Jungle - Item Box 4"
white_jungle_itembox_5 = "White Jungle - Item Box 5"
white_jungle_itembox_6 = "White Jungle - Item Box 6"
white_jungle_itembox_7 = "White Jungle - Item Box 7"
white_jungle_itembox_8 = "White Jungle - Item Box 8"
white_jungle_big_1 = "White Jungle - Big 1"
white_jungle_big_2 = "White Jungle - Big 2"
white_jungle_upgrade = "White Jungle - Upgrade"
sky_rail_1 = "Sky Rail - 1"
sky_rail_2 = "Sky Rail - 2"
@@ -671,6 +936,39 @@ sky_rail_animal_17 = "Sky Rail - 17 Animals"
sky_rail_animal_18 = "Sky Rail - 18 Animals"
sky_rail_animal_19 = "Sky Rail - 19 Animals"
sky_rail_animal_20 = "Sky Rail - 20 Animals"
sky_rail_lifebox_1 = "Sky Rail - Extra Life Box 1"
sky_rail_lifebox_2 = "Sky Rail - Extra Life Box 2"
sky_rail_lifebox_3 = "Sky Rail - Extra Life Box 3"
sky_rail_lifebox_4 = "Sky Rail - Extra Life Box 4"
sky_rail_lifebox_5 = "Sky Rail - Extra Life Box 5"
sky_rail_lifebox_6 = "Sky Rail - Extra Life Box 6"
sky_rail_lifebox_7 = "Sky Rail - Extra Life Box 7"
sky_rail_lifebox_8 = "Sky Rail - Extra Life Box 8"
sky_rail_lifebox_9 = "Sky Rail - Extra Life Box 9"
sky_rail_itembox_1 = "Sky Rail - Item Box 1"
sky_rail_itembox_2 = "Sky Rail - Item Box 2"
sky_rail_itembox_3 = "Sky Rail - Item Box 3"
sky_rail_itembox_4 = "Sky Rail - Item Box 4"
sky_rail_itembox_5 = "Sky Rail - Item Box 5"
sky_rail_itembox_6 = "Sky Rail - Item Box 6"
sky_rail_itembox_7 = "Sky Rail - Item Box 7"
sky_rail_itembox_8 = "Sky Rail - Item Box 8"
sky_rail_itembox_9 = "Sky Rail - Item Box 9"
sky_rail_itembox_10 = "Sky Rail - Item Box 10"
sky_rail_itembox_11 = "Sky Rail - Item Box 11"
sky_rail_itembox_12 = "Sky Rail - Item Box 12"
sky_rail_itembox_13 = "Sky Rail - Item Box 13"
sky_rail_itembox_14 = "Sky Rail - Item Box 14"
sky_rail_itembox_15 = "Sky Rail - Item Box 15"
sky_rail_itembox_16 = "Sky Rail - Item Box 16"
sky_rail_itembox_17 = "Sky Rail - Item Box 17"
sky_rail_itembox_18 = "Sky Rail - Item Box 18"
sky_rail_itembox_19 = "Sky Rail - Item Box 19"
sky_rail_itembox_20 = "Sky Rail - Item Box 20"
sky_rail_itembox_21 = "Sky Rail - Item Box 21"
sky_rail_itembox_22 = "Sky Rail - Item Box 22"
sky_rail_itembox_23 = "Sky Rail - Item Box 23"
sky_rail_big = "Sky Rail - Big"
sky_rail_upgrade = "Sky Rail - Upgrade"
final_chase_1 = "Final Chase - 1"
final_chase_2 = "Final Chase - 2"
@@ -705,6 +1003,51 @@ final_chase_animal_17 = "Final Chase - 17 Animals"
final_chase_animal_18 = "Final Chase - 18 Animals"
final_chase_animal_19 = "Final Chase - 19 Animals"
final_chase_animal_20 = "Final Chase - 20 Animals"
final_chase_lifebox_1 = "Final Chase - Extra Life Box 1"
final_chase_lifebox_2 = "Final Chase - Extra Life Box 2"
final_chase_lifebox_3 = "Final Chase - Extra Life Box 3"
final_chase_lifebox_4 = "Final Chase - Extra Life Box 4"
final_chase_lifebox_5 = "Final Chase - Extra Life Box 5"
final_chase_lifebox_6 = "Final Chase - Extra Life Box 6"
final_chase_lifebox_7 = "Final Chase - Extra Life Box 7"
final_chase_lifebox_8 = "Final Chase - Extra Life Box 8"
final_chase_lifebox_9 = "Final Chase - Extra Life Box 9"
final_chase_itembox_1 = "Final Chase - Item Box 1"
final_chase_itembox_2 = "Final Chase - Item Box 2"
final_chase_itembox_3 = "Final Chase - Item Box 3"
final_chase_itembox_4 = "Final Chase - Item Box 4"
final_chase_itembox_5 = "Final Chase - Item Box 5"
final_chase_itembox_6 = "Final Chase - Item Box 6"
final_chase_itembox_7 = "Final Chase - Item Box 7"
final_chase_itembox_8 = "Final Chase - Item Box 8"
final_chase_itembox_9 = "Final Chase - Item Box 9"
final_chase_itembox_10 = "Final Chase - Item Box 10"
final_chase_itembox_11 = "Final Chase - Item Box 11"
final_chase_itembox_12 = "Final Chase - Item Box 12"
final_chase_itembox_13 = "Final Chase - Item Box 13"
final_chase_itembox_14 = "Final Chase - Item Box 14"
final_chase_itembox_15 = "Final Chase - Item Box 15"
final_chase_itembox_16 = "Final Chase - Item Box 16"
final_chase_itembox_17 = "Final Chase - Item Box 17"
final_chase_itembox_18 = "Final Chase - Item Box 18"
final_chase_itembox_19 = "Final Chase - Item Box 19"
final_chase_itembox_20 = "Final Chase - Item Box 20"
final_chase_itembox_21 = "Final Chase - Item Box 21"
final_chase_itembox_22 = "Final Chase - Item Box 22"
final_chase_itembox_23 = "Final Chase - Item Box 23"
final_chase_itembox_24 = "Final Chase - Item Box 24"
final_chase_itembox_25 = "Final Chase - Item Box 25"
final_chase_itembox_26 = "Final Chase - Item Box 26"
final_chase_itembox_27 = "Final Chase - Item Box 27"
final_chase_itembox_28 = "Final Chase - Item Box 28"
final_chase_itembox_29 = "Final Chase - Item Box 29"
final_chase_itembox_30 = "Final Chase - Item Box 30"
final_chase_itembox_31 = "Final Chase - Item Box 31"
final_chase_itembox_32 = "Final Chase - Item Box 32"
final_chase_itembox_33 = "Final Chase - Item Box 33"
final_chase_itembox_34 = "Final Chase - Item Box 34"
final_chase_itembox_35 = "Final Chase - Item Box 35"
final_chase_big = "Final Chase - Big"
final_chase_upgrade = "Final Chase - Upgrade"
# Eggman Mission Definitions
@@ -743,6 +1086,27 @@ iron_gate_animal_12 = "Iron Gate - 12 Animals"
iron_gate_animal_13 = "Iron Gate - 13 Animals"
iron_gate_animal_14 = "Iron Gate - 14 Animals"
iron_gate_animal_15 = "Iron Gate - 15 Animals"
iron_gate_lifebox_1 = "Iron Gate - Extra Life Box 1"
iron_gate_lifebox_2 = "Iron Gate - Extra Life Box 2"
iron_gate_lifebox_3 = "Iron Gate - Extra Life Box 3"
iron_gate_lifebox_4 = "Iron Gate - Extra Life Box 4"
iron_gate_itembox_1 = "Iron Gate - Item Box 1"
iron_gate_itembox_2 = "Iron Gate - Item Box 2"
iron_gate_itembox_3 = "Iron Gate - Item Box 3"
iron_gate_itembox_4 = "Iron Gate - Item Box 4"
iron_gate_itembox_5 = "Iron Gate - Item Box 5"
iron_gate_itembox_6 = "Iron Gate - Item Box 6"
iron_gate_itembox_7 = "Iron Gate - Item Box 7"
iron_gate_itembox_8 = "Iron Gate - Item Box 8"
iron_gate_itembox_9 = "Iron Gate - Item Box 9"
iron_gate_itembox_10 = "Iron Gate - Item Box 10"
iron_gate_itembox_11 = "Iron Gate - Item Box 11"
iron_gate_itembox_12 = "Iron Gate - Item Box 12"
iron_gate_itembox_13 = "Iron Gate - Item Box 13"
iron_gate_itembox_14 = "Iron Gate - Item Box 14"
iron_gate_itembox_15 = "Iron Gate - Item Box 15"
iron_gate_itembox_16 = "Iron Gate - Item Box 16"
iron_gate_big = "Iron Gate - Big"
iron_gate_upgrade = "Iron Gate - Upgrade"
sand_ocean_1 = "Sand Ocean - 1"
sand_ocean_2 = "Sand Ocean - 2"
@@ -775,6 +1139,20 @@ sand_ocean_animal_12 = "Sand Ocean - 12 Animals"
sand_ocean_animal_13 = "Sand Ocean - 13 Animals"
sand_ocean_animal_14 = "Sand Ocean - 14 Animals"
sand_ocean_animal_15 = "Sand Ocean - 15 Animals"
sand_ocean_lifebox_1 = "Sand Ocean - Extra Life Box 1"
sand_ocean_lifebox_2 = "Sand Ocean - Extra Life Box 2"
sand_ocean_lifebox_3 = "Sand Ocean - Extra Life Box 3"
sand_ocean_itembox_1 = "Sand Ocean - Item Box 1"
sand_ocean_itembox_2 = "Sand Ocean - Item Box 2"
sand_ocean_itembox_3 = "Sand Ocean - Item Box 3"
sand_ocean_itembox_4 = "Sand Ocean - Item Box 4"
sand_ocean_itembox_5 = "Sand Ocean - Item Box 5"
sand_ocean_itembox_6 = "Sand Ocean - Item Box 6"
sand_ocean_itembox_7 = "Sand Ocean - Item Box 7"
sand_ocean_itembox_8 = "Sand Ocean - Item Box 8"
sand_ocean_itembox_9 = "Sand Ocean - Item Box 9"
sand_ocean_itembox_10 = "Sand Ocean - Item Box 10"
sand_ocean_big = "Sand Ocean - Big"
sand_ocean_upgrade = "Sand Ocean - Upgrade"
lost_colony_1 = "Lost Colony - 1"
lost_colony_2 = "Lost Colony - 2"
@@ -810,6 +1188,17 @@ lost_colony_animal_11 = "Lost Colony - 11 Animals"
lost_colony_animal_12 = "Lost Colony - 12 Animals"
lost_colony_animal_13 = "Lost Colony - 13 Animals"
lost_colony_animal_14 = "Lost Colony - 14 Animals"
lost_colony_lifebox_1 = "Lost Colony - Extra Life Box 1"
lost_colony_itembox_1 = "Lost Colony - Item Box 1"
lost_colony_itembox_2 = "Lost Colony - Item Box 2"
lost_colony_itembox_3 = "Lost Colony - Item Box 3"
lost_colony_itembox_4 = "Lost Colony - Item Box 4"
lost_colony_itembox_5 = "Lost Colony - Item Box 5"
lost_colony_itembox_6 = "Lost Colony - Item Box 6"
lost_colony_itembox_7 = "Lost Colony - Item Box 7"
lost_colony_itembox_8 = "Lost Colony - Item Box 8"
lost_colony_itembox_9 = "Lost Colony - Item Box 9"
lost_colony_big = "Lost Colony - Big"
lost_colony_upgrade = "Lost Colony - Upgrade"
weapons_bed_1 = "Weapons Bed - 1"
weapons_bed_2 = "Weapons Bed - 2"
@@ -842,6 +1231,15 @@ weapons_bed_animal_12 = "Weapons Bed - 12 Animals"
weapons_bed_animal_13 = "Weapons Bed - 13 Animals"
weapons_bed_animal_14 = "Weapons Bed - 14 Animals"
weapons_bed_animal_15 = "Weapons Bed - 15 Animals"
weapons_bed_lifebox_1 = "Weapons Bed - Extra Life Box 1"
weapons_bed_itembox_1 = "Weapons Bed - Item Box 1"
weapons_bed_itembox_2 = "Weapons Bed - Item Box 2"
weapons_bed_itembox_3 = "Weapons Bed - Item Box 3"
weapons_bed_itembox_4 = "Weapons Bed - Item Box 4"
weapons_bed_itembox_5 = "Weapons Bed - Item Box 5"
weapons_bed_itembox_6 = "Weapons Bed - Item Box 6"
weapons_bed_itembox_7 = "Weapons Bed - Item Box 7"
weapons_bed_big = "Weapons Bed - Big"
weapons_bed_upgrade = "Weapons Bed - Upgrade"
cosmic_wall_1 = "Cosmic Wall - 1"
cosmic_wall_2 = "Cosmic Wall - 2"
@@ -873,6 +1271,33 @@ cosmic_wall_animal_12 = "Cosmic Wall - 12 Animals"
cosmic_wall_animal_13 = "Cosmic Wall - 13 Animals"
cosmic_wall_animal_14 = "Cosmic Wall - 14 Animals"
cosmic_wall_animal_15 = "Cosmic Wall - 15 Animals"
cosmic_wall_itembox_1 = "Cosmic Wall - Item Box 1"
cosmic_wall_itembox_2 = "Cosmic Wall - Item Box 2"
cosmic_wall_itembox_3 = "Cosmic Wall - Item Box 3"
cosmic_wall_itembox_4 = "Cosmic Wall - Item Box 4"
cosmic_wall_itembox_5 = "Cosmic Wall - Item Box 5"
cosmic_wall_itembox_6 = "Cosmic Wall - Item Box 6"
cosmic_wall_itembox_7 = "Cosmic Wall - Item Box 7"
cosmic_wall_itembox_8 = "Cosmic Wall - Item Box 8"
cosmic_wall_itembox_9 = "Cosmic Wall - Item Box 9"
cosmic_wall_itembox_10 = "Cosmic Wall - Item Box 10"
cosmic_wall_itembox_11 = "Cosmic Wall - Item Box 11"
cosmic_wall_itembox_12 = "Cosmic Wall - Item Box 12"
cosmic_wall_itembox_13 = "Cosmic Wall - Item Box 13"
cosmic_wall_itembox_14 = "Cosmic Wall - Item Box 14"
cosmic_wall_itembox_15 = "Cosmic Wall - Item Box 15"
cosmic_wall_itembox_16 = "Cosmic Wall - Item Box 16"
cosmic_wall_itembox_17 = "Cosmic Wall - Item Box 17"
cosmic_wall_itembox_18 = "Cosmic Wall - Item Box 18"
cosmic_wall_itembox_19 = "Cosmic Wall - Item Box 19"
cosmic_wall_itembox_20 = "Cosmic Wall - Item Box 20"
cosmic_wall_itembox_21 = "Cosmic Wall - Item Box 21"
cosmic_wall_itembox_22 = "Cosmic Wall - Item Box 22"
cosmic_wall_itembox_23 = "Cosmic Wall - Item Box 23"
cosmic_wall_itembox_24 = "Cosmic Wall - Item Box 24"
cosmic_wall_itembox_25 = "Cosmic Wall - Item Box 25"
cosmic_wall_itembox_26 = "Cosmic Wall - Item Box 26"
cosmic_wall_itembox_27 = "Cosmic Wall - Item Box 27"
cosmic_wall_upgrade = "Cosmic Wall - Upgrade"
# Rouge Mission Definitions
@@ -910,6 +1335,18 @@ dry_lagoon_animal_8 = "Dry Lagoon - 8 Animals"
dry_lagoon_animal_9 = "Dry Lagoon - 9 Animals"
dry_lagoon_animal_10 = "Dry Lagoon - 10 Animals"
dry_lagoon_animal_11 = "Dry Lagoon - 11 Animals"
dry_lagoon_animal_12 = "Dry Lagoon - 12 Animals"
dry_lagoon_lifebox_1 = "Dry Lagoon - Extra Life Box 1"
dry_lagoon_lifebox_2 = "Dry Lagoon - Extra Life Box 2"
dry_lagoon_lifebox_3 = "Dry Lagoon - Extra Life Box 3"
dry_lagoon_lifebox_4 = "Dry Lagoon - Extra Life Box 4"
dry_lagoon_itembox_1 = "Dry Lagoon - Item Box 1"
dry_lagoon_itembox_2 = "Dry Lagoon - Item Box 2"
dry_lagoon_itembox_3 = "Dry Lagoon - Item Box 3"
dry_lagoon_itembox_4 = "Dry Lagoon - Item Box 4"
dry_lagoon_itembox_5 = "Dry Lagoon - Item Box 5"
dry_lagoon_itembox_6 = "Dry Lagoon - Item Box 6"
dry_lagoon_big = "Dry Lagoon - Big"
dry_lagoon_upgrade = "Dry Lagoon - Upgrade"
egg_quarters_1 = "Egg Quarters - 1"
egg_quarters_2 = "Egg Quarters - 2"
@@ -941,6 +1378,20 @@ egg_quarters_animal_7 = "Egg Quarters - 7 Animals"
egg_quarters_animal_8 = "Egg Quarters - 8 Animals"
egg_quarters_animal_9 = "Egg Quarters - 9 Animals"
egg_quarters_animal_10 = "Egg Quarters - 10 Animals"
egg_quarters_lifebox_1 = "Egg Quarters - Extra Life Box 1"
egg_quarters_lifebox_2 = "Egg Quarters - Extra Life Box 2"
egg_quarters_itembox_1 = "Egg Quarters - Item Box 1"
egg_quarters_itembox_2 = "Egg Quarters - Item Box 2"
egg_quarters_itembox_3 = "Egg Quarters - Item Box 3"
egg_quarters_itembox_4 = "Egg Quarters - Item Box 4"
egg_quarters_itembox_5 = "Egg Quarters - Item Box 5"
egg_quarters_itembox_6 = "Egg Quarters - Item Box 6"
egg_quarters_itembox_7 = "Egg Quarters - Item Box 7"
egg_quarters_itembox_8 = "Egg Quarters - Item Box 8"
egg_quarters_itembox_9 = "Egg Quarters - Item Box 9"
egg_quarters_itembox_10 = "Egg Quarters - Item Box 10"
egg_quarters_itembox_11 = "Egg Quarters - Item Box 11"
egg_quarters_big = "Egg Quarters - Big"
egg_quarters_upgrade = "Egg Quarters - Upgrade"
security_hall_1 = "Security Hall - 1"
security_hall_2 = "Security Hall - 2"
@@ -973,12 +1424,41 @@ security_hall_animal_5 = "Security Hall - 5 Animals"
security_hall_animal_6 = "Security Hall - 6 Animals"
security_hall_animal_7 = "Security Hall - 7 Animals"
security_hall_animal_8 = "Security Hall - 8 Animals"
security_hall_lifebox_1 = "Security Hall - Extra Life Box 1"
security_hall_itembox_1 = "Security Hall - Item Box 1"
security_hall_itembox_2 = "Security Hall - Item Box 2"
security_hall_itembox_3 = "Security Hall - Item Box 3"
security_hall_itembox_4 = "Security Hall - Item Box 4"
security_hall_itembox_5 = "Security Hall - Item Box 5"
security_hall_itembox_6 = "Security Hall - Item Box 6"
security_hall_itembox_7 = "Security Hall - Item Box 7"
security_hall_itembox_8 = "Security Hall - Item Box 8"
security_hall_itembox_9 = "Security Hall - Item Box 9"
security_hall_itembox_10 = "Security Hall - Item Box 10"
security_hall_itembox_11 = "Security Hall - Item Box 11"
security_hall_itembox_12 = "Security Hall - Item Box 12"
security_hall_itembox_13 = "Security Hall - Item Box 13"
security_hall_itembox_14 = "Security Hall - Item Box 14"
security_hall_itembox_15 = "Security Hall - Item Box 15"
security_hall_itembox_16 = "Security Hall - Item Box 16"
security_hall_itembox_17 = "Security Hall - Item Box 17"
security_hall_itembox_18 = "Security Hall - Item Box 18"
security_hall_itembox_19 = "Security Hall - Item Box 19"
security_hall_itembox_20 = "Security Hall - Item Box 20"
security_hall_itembox_21 = "Security Hall - Item Box 21"
security_hall_itembox_22 = "Security Hall - Item Box 22"
security_hall_itembox_23 = "Security Hall - Item Box 23"
security_hall_itembox_24 = "Security Hall - Item Box 24"
security_hall_big = "Security Hall - Big"
security_hall_upgrade = "Security Hall - Upgrade"
route_280_1 = "Route 280 - 1"
route_280_2 = "Route 280 - 2"
route_280_3 = "Route 280 - 3"
route_280_4 = "Route 280 - 4"
route_280_5 = "Route 280 - 5"
route_280_itembox_1 = "Route 280 - Balloon 1"
route_280_itembox_2 = "Route 280 - Balloon 2"
route_280_itembox_3 = "Route 280 - Balloon 3"
mad_space_1 = "Mad Space - 1"
mad_space_2 = "Mad Space - 2"
mad_space_3 = "Mad Space - 3"
@@ -1007,6 +1487,31 @@ mad_space_animal_7 = "Mad Space - 7 Animals"
mad_space_animal_8 = "Mad Space - 8 Animals"
mad_space_animal_9 = "Mad Space - 9 Animals"
mad_space_animal_10 = "Mad Space - 10 Animals"
mad_space_lifebox_1 = "Mad Space - Extra Life Box 1"
mad_space_lifebox_2 = "Mad Space - Extra Life Box 2"
mad_space_lifebox_3 = "Mad Space - Extra Life Box 3"
mad_space_lifebox_4 = "Mad Space - Extra Life Box 4"
mad_space_itembox_1 = "Mad Space - Item Box 1"
mad_space_itembox_2 = "Mad Space - Item Box 2"
mad_space_itembox_3 = "Mad Space - Item Box 3"
mad_space_itembox_4 = "Mad Space - Item Box 4"
mad_space_itembox_5 = "Mad Space - Item Box 5"
mad_space_itembox_6 = "Mad Space - Item Box 6"
mad_space_itembox_7 = "Mad Space - Item Box 7"
mad_space_itembox_8 = "Mad Space - Item Box 8"
mad_space_itembox_9 = "Mad Space - Item Box 9"
mad_space_itembox_10 = "Mad Space - Item Box 10"
mad_space_itembox_11 = "Mad Space - Item Box 11"
mad_space_itembox_12 = "Mad Space - Item Box 12"
mad_space_itembox_13 = "Mad Space - Item Box 13"
mad_space_itembox_14 = "Mad Space - Item Box 14"
mad_space_itembox_15 = "Mad Space - Item Box 15"
mad_space_itembox_16 = "Mad Space - Item Box 16"
mad_space_itembox_17 = "Mad Space - Item Box 17"
mad_space_itembox_18 = "Mad Space - Item Box 18"
mad_space_itembox_19 = "Mad Space - Item Box 19"
mad_space_itembox_20 = "Mad Space - Item Box 20"
mad_space_big = "Mad Space - Big"
mad_space_upgrade = "Mad Space - Upgrade"
# Final Mission Definitions
@@ -1053,11 +1558,40 @@ cannon_core_animal_16 = "Cannon's Core - 16 Animals"
cannon_core_animal_17 = "Cannon's Core - 17 Animals"
cannon_core_animal_18 = "Cannon's Core - 18 Animals"
cannon_core_animal_19 = "Cannon's Core - 19 Animals"
cannon_core_lifebox_1 = "Cannon's Core - Extra Life Box 1"
cannon_core_itembox_1 = "Cannon's Core - Item Box 1"
cannon_core_itembox_2 = "Cannon's Core - Item Box 2"
cannon_core_itembox_3 = "Cannon's Core - Item Box 3"
cannon_core_itembox_4 = "Cannon's Core - Item Box 4"
cannon_core_itembox_5 = "Cannon's Core - Item Box 5"
cannon_core_itembox_6 = "Cannon's Core - Item Box 6"
cannon_core_itembox_7 = "Cannon's Core - Item Box 7"
cannon_core_itembox_8 = "Cannon's Core - Item Box 8"
cannon_core_itembox_9 = "Cannon's Core - Item Box 9"
cannon_core_itembox_10 = "Cannon's Core - Item Box 10"
cannon_core_itembox_11 = "Cannon's Core - Item Box 11"
cannon_core_itembox_12 = "Cannon's Core - Item Box 12"
cannon_core_big_1 = "Cannon's Core - Tails - Big"
cannon_core_big_2 = "Cannon's Core - Eggman - Big"
cannon_core_big_3 = "Cannon's Core - Rouge - Big"
cannon_core_big_4 = "Cannon's Core - Knuckles - Big"
cannon_core_big_5 = "Cannon's Core - Sonic - Big"
# Green Hill Definitions
green_hill = "Green Hill"
green_hill = "Green Hill - 1"
green_hill_chao_1 = "Green Hill - Chao Key 1"
green_hill_animal_1 = "Green Hill - 1 Animal"
green_hill_itembox_1 = "Green Hill - Item Box 1"
green_hill_itembox_2 = "Green Hill - Item Box 2"
green_hill_itembox_3 = "Green Hill - Item Box 3"
green_hill_itembox_4 = "Green Hill - Item Box 4"
green_hill_itembox_5 = "Green Hill - Item Box 5"
green_hill_itembox_6 = "Green Hill - Item Box 6"
green_hill_itembox_7 = "Green Hill - Item Box 7"
green_hill_itembox_8 = "Green Hill - Item Box 8"
green_hill_itembox_9 = "Green Hill - Item Box 9"
green_hill_itembox_10 = "Green Hill - Item Box 10"
green_hill_itembox_11 = "Green Hill - Item Box 11"
# Boss Definitions
gate_1_boss = "Gate 1 Boss"
@@ -1380,6 +1914,28 @@ gate_3_boss_region = "Gate 3 Boss"
gate_4_boss_region = "Gate 4 Boss"
gate_5_boss_region = "Gate 5 Boss"
boss_gate_names = {
"gate 1 boss": 0,
"gate 2 boss": 1,
"gate 3 boss": 2,
"gate 4 boss": 3,
"gate 5 boss": 4,
}
boss_names = {
"sonic vs shadow 1": 0,
"sonic vs shadow 2": 1,
"tails vs eggman 1": 2,
"tails vs eggman 2": 3,
"knuckles vs rouge 1": 4,
"big foot": 5,
"hot shot": 6,
"flying dog": 7,
"egg golem (sonic)": 8,
"egg golem (eggman)": 9,
"king boom boo": 10,
}
boss_rush_1_region = "Boss Rush 1"
boss_rush_2_region = "Boss Rush 2"
boss_rush_3_region = "Boss Rush 3"

View File

@@ -1,6 +1,8 @@
from dataclasses import dataclass
from Options import Choice, Range, Toggle, DeathLink, DefaultOnToggle, OptionGroup, PerGameCommonOptions
from Options import Choice, Range, Option, OptionGroup, Toggle, DeathLink, DefaultOnToggle, PerGameCommonOptions, PlandoBosses
from .Names import LocationName
class Goal(Choice):
@@ -22,6 +24,8 @@ class Goal(Choice):
Boss Rush Chaos Emerald Hunt: Find the Seven Chaos Emeralds, then beat all of the bosses in the Boss Rush, ending with Finalhazard
Chaos Chao: Raise a Chaos Chao to win
Minigame Madness: Win a certain amount of each Minigame Trap, then defeat Finalhazard
"""
display_name = "Goal"
option_biolizard = 0
@@ -32,6 +36,7 @@ class Goal(Choice):
option_cannons_core_boss_rush = 5
option_boss_rush_chaos_emerald_hunt = 6
option_chaos_chao = 7
option_minigame_madness = 8
default = 0
@classmethod
@@ -71,6 +76,66 @@ class BossRushShuffle(Choice):
default = 0
class GateBossPlando(PlandoBosses):
"""
Possible Locations:
"Gate 1 Boss"
"Gate 2 Boss"
"Gate 3 Boss"
"Gate 4 Boss"
"Gate 5 Boss"
Possible Bosses:
"Sonic vs Shadow 1"
"Sonic vs Shadow 2"
"Tails vs Eggman 1"
"Tails vs Eggman 2"
"Knuckles vs Rouge 1"
"BIG FOOT"
"HOT SHOT"
"FLYING DOG"
"Egg Golem (Sonic)"
"Egg Golem (Eggman)"
"King Boom Boo"
"""
bosses = frozenset(LocationName.boss_names.keys())
locations = frozenset(LocationName.boss_gate_names.keys())
duplicate_bosses = False
@classmethod
def can_place_boss(cls, boss: str, location: str) -> bool:
return True
display_name = "Boss Shuffle"
option_plando = 0
class MinigameMadnessRequirement(Range):
"""
Determines how many of each Minigame Trap must be won (for Minigame Madness goal)
Receiving this many of a Minigame Trap will allow you to replay that minigame at-will in the Chao World lobby
"""
display_name = "Minigame Madness Trap Requirement"
range_start = 1
range_end = 10
default = 3
class MinigameMadnessMinimum(Range):
"""
Determines the minimum number of each Minigame Trap that are created (for Minigame Madness goal)
At least this many of each trap will be created as "Progression Traps", regardless of other trap option selections
"""
display_name = "Minigame Madness Trap Minimum"
range_start = 1
range_end = 10
default = 5
class BaseTrapWeight(Choice):
"""
Base Class for Trap Weights
@@ -159,6 +224,34 @@ class ReverseTrapWeight(BaseTrapWeight):
display_name = "Reverse Trap Weight"
class LiteratureTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to read
"""
display_name = "Literature Trap Weight"
class ControllerDriftTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which causes your control sticks to drift
"""
display_name = "Controller Drift Trap Weight"
class PoisonTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which causes you to lose rings over time
"""
display_name = "Poison Trap Weight"
class BeeTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which spawns a swarm of bees
"""
display_name = "Bee Trap Weight"
class PongTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Pong minigame
@@ -166,14 +259,106 @@ class PongTrapWeight(BaseTrapWeight):
display_name = "Pong Trap Weight"
class BreakoutTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Breakout minigame
"""
display_name = "Breakout Trap Weight"
class FishingTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Fishing minigame
"""
display_name = "Fishing Trap Weight"
class TriviaTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Trivia minigame
"""
display_name = "Trivia Trap Weight"
class PokemonTriviaTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Pokemon Trivia minigame
"""
display_name = "Pokemon Trivia Trap Weight"
class PokemonCountTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Pokemon Count minigame
"""
display_name = "Pokemon Count Trap Weight"
class NumberSequenceTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Number Sequence minigame
"""
display_name = "Number Sequence Trap Weight"
class LightUpPathTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Light Up Path minigame
"""
display_name = "Light Up Path Trap Weight"
class PinballTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Pinball minigame
"""
display_name = "Pinball Trap Weight"
class MathQuizTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to solve a math problem
"""
display_name = "Math Quiz Trap Weight"
class SnakeTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to play a Snake minigame
"""
display_name = "Snake Trap Weight"
class InputSequenceTrapWeight(BaseTrapWeight):
"""
Likelihood of receiving a trap which forces you to press a sequence of inputs
"""
display_name = "Input Sequence Trap Weight"
class MinigameTrapDifficulty(Choice):
"""
How difficult any Minigame-style traps are
Chaos causes the difficulty to be random per-minigame
"""
display_name = "Minigame Trap Difficulty"
option_easy = 0
option_medium = 1
option_hard = 2
option_chaos = 3
default = 1
class BigFishingDifficulty(Choice):
"""
How difficult Big's Fishing Minigames are
Chaos causes the difficulty to be random per-minigame
"""
display_name = "Big Fishing Difficulty"
option_easy = 0
option_medium = 1
option_hard = 2
option_chaos = 3
default = 1
@@ -197,7 +382,7 @@ class TrapFillPercentage(Range):
default = 0
class Keysanity(Toggle):
class Keysanity(DefaultOnToggle):
"""
Determines whether picking up Chao Keys grants checks
(86 Locations)
@@ -225,7 +410,7 @@ class Whistlesanity(Choice):
default = 0
class Beetlesanity(Toggle):
class Beetlesanity(DefaultOnToggle):
"""
Determines whether destroying Gold Beetles grants checks
(27 Locations)
@@ -244,13 +429,35 @@ class Omosanity(Toggle):
class Animalsanity(Toggle):
"""
Determines whether unique counts of animals grant checks.
(421 Locations)
(422 Locations)
ALL animals must be collected in a single run of a mission to get all checks.
"""
display_name = "Animalsanity"
class ItemBoxsanity(Choice):
"""
Determines whether collecting Item Boxes grants checks
None: No Item Boxes grant checks
Extra Lives: Extra Life Boxes grant checks (94 Locations)
All: All Item Boxes grant checks (502 Locations Total)
"""
display_name = "Itemboxsanity"
option_none = 0
option_extra_lives = 1
option_all = 2
default = 0
class Bigsanity(Toggle):
"""
Determines whether helping Big fish grants checks.
(32 Locations)
"""
display_name = "Bigsanity"
class KartRaceChecks(Choice):
"""
Determines whether Kart Race Mode grants checks
@@ -313,7 +520,7 @@ class LevelGateCosts(Choice):
option_low = 0
option_medium = 1
option_high = 2
default = 2
default = 0
class MaximumEmblemCap(Range):
@@ -523,109 +730,214 @@ class BaseMissionCount(Range):
default = 2
class SpeedMissionCount(BaseMissionCount):
class SonicMissionCount(BaseMissionCount):
"""
The number of active missions to include for Sonic and Shadow stages
The number of active missions to include for Sonic stages
"""
display_name = "Speed Mission Count"
display_name = "Sonic Mission Count"
class SpeedMission2(DefaultOnToggle):
class SonicMission2(DefaultOnToggle):
"""
Determines if the Sonic and Shadow 100 rings missions should be included
Determines if the Sonic 100 rings missions should be included
"""
display_name = "Speed Mission 2"
display_name = "Sonic Mission 2"
class SpeedMission3(DefaultOnToggle):
class SonicMission3(DefaultOnToggle):
"""
Determines if the Sonic and Shadow lost chao missions should be included
Determines if the Sonic lost chao missions should be included
"""
display_name = "Speed Mission 3"
display_name = "Sonic Mission 3"
class SpeedMission4(DefaultOnToggle):
class SonicMission4(DefaultOnToggle):
"""
Determines if the Sonic and Shadow time trial missions should be included
Determines if the Sonic time trial missions should be included
"""
display_name = "Speed Mission 4"
display_name = "Sonic Mission 4"
class SpeedMission5(DefaultOnToggle):
class SonicMission5(DefaultOnToggle):
"""
Determines if the Sonic and Shadow hard missions should be included
Determines if the Sonic hard missions should be included
"""
display_name = "Speed Mission 5"
display_name = "Sonic Mission 5"
class MechMissionCount(BaseMissionCount):
class ShadowMissionCount(BaseMissionCount):
"""
The number of active missions to include for Tails and Eggman stages
The number of active missions to include for Shadow stages
"""
display_name = "Mech Mission Count"
display_name = "Shadow Mission Count"
class MechMission2(DefaultOnToggle):
class ShadowMission2(DefaultOnToggle):
"""
Determines if the Tails and Eggman 100 rings missions should be included
Determines if the Shadow 100 rings missions should be included
"""
display_name = "Mech Mission 2"
display_name = "Shadow Mission 2"
class MechMission3(DefaultOnToggle):
class ShadowMission3(DefaultOnToggle):
"""
Determines if the Tails and Eggman lost chao missions should be included
Determines if the Shadow lost chao missions should be included
"""
display_name = "Mech Mission 3"
display_name = "Shadow Mission 3"
class MechMission4(DefaultOnToggle):
class ShadowMission4(DefaultOnToggle):
"""
Determines if the Tails and Eggman time trial missions should be included
Determines if the Shadow time trial missions should be included
"""
display_name = "Mech Mission 4"
display_name = "Shadow Mission 4"
class MechMission5(DefaultOnToggle):
class ShadowMission5(DefaultOnToggle):
"""
Determines if the Tails and Eggman hard missions should be included
Determines if the Shadow hard missions should be included
"""
display_name = "Mech Mission 5"
display_name = "Shadow Mission 5"
class HuntMissionCount(BaseMissionCount):
class TailsMissionCount(BaseMissionCount):
"""
The number of active missions to include for Knuckles and Rouge stages
The number of active missions to include for Tails stages
"""
display_name = "Hunt Mission Count"
display_name = "Tails Mission Count"
class HuntMission2(DefaultOnToggle):
class TailsMission2(DefaultOnToggle):
"""
Determines if the Knuckles and Rouge 100 rings missions should be included
Determines if the Tails 100 rings missions should be included
"""
display_name = "Hunt Mission 2"
display_name = "Tails Mission 2"
class HuntMission3(DefaultOnToggle):
class TailsMission3(DefaultOnToggle):
"""
Determines if the Knuckles and Rouge lost chao missions should be included
Determines if the Tails lost chao missions should be included
"""
display_name = "Hunt Mission 3"
display_name = "Tails Mission 3"
class HuntMission4(DefaultOnToggle):
class TailsMission4(DefaultOnToggle):
"""
Determines if the Knuckles and Rouge time trial missions should be included
Determines if the Tails time trial missions should be included
"""
display_name = "Hunt Mission 4"
display_name = "Tails Mission 4"
class HuntMission5(DefaultOnToggle):
class TailsMission5(DefaultOnToggle):
"""
Determines if the Knuckles and Rouge hard missions should be included
Determines if the Tails hard missions should be included
"""
display_name = "Hunt Mission 5"
display_name = "Tails Mission 5"
class EggmanMissionCount(BaseMissionCount):
"""
The number of active missions to include for Eggman stages
"""
display_name = "Eggman Mission Count"
class EggmanMission2(DefaultOnToggle):
"""
Determines if the Eggman 100 rings missions should be included
"""
display_name = "Eggman Mission 2"
class EggmanMission3(DefaultOnToggle):
"""
Determines if the Eggman lost chao missions should be included
"""
display_name = "Eggman Mission 3"
class EggmanMission4(DefaultOnToggle):
"""
Determines if the Eggman time trial missions should be included
"""
display_name = "Eggman Mission 4"
class EggmanMission5(DefaultOnToggle):
"""
Determines if the Eggman hard missions should be included
"""
display_name = "Eggman Mission 5"
class KnucklesMissionCount(BaseMissionCount):
"""
The number of active missions to include for Knuckles stages
"""
display_name = "Knuckles Mission Count"
class KnucklesMission2(DefaultOnToggle):
"""
Determines if the Knuckles 100 rings missions should be included
"""
display_name = "Knuckles Mission 2"
class KnucklesMission3(DefaultOnToggle):
"""
Determines if the Knuckles lost chao missions should be included
"""
display_name = "Knuckles Mission 3"
class KnucklesMission4(DefaultOnToggle):
"""
Determines if the Knuckles time trial missions should be included
"""
display_name = "Knuckles Mission 4"
class KnucklesMission5(DefaultOnToggle):
"""
Determines if the Knuckles hard missions should be included
"""
display_name = "Knuckles Mission 5"
class RougeMissionCount(BaseMissionCount):
"""
The number of active missions to include for Rouge stages
"""
display_name = "Rouge Mission Count"
class RougeMission2(DefaultOnToggle):
"""
Determines if the Rouge 100 rings missions should be included
"""
display_name = "Rouge Mission 2"
class RougeMission3(DefaultOnToggle):
"""
Determines if the Rouge lost chao missions should be included
"""
display_name = "Rouge Mission 3"
class RougeMission4(DefaultOnToggle):
"""
Determines if the Rouge time trial missions should be included
"""
display_name = "Rouge Mission 4"
class RougeMission5(DefaultOnToggle):
"""
Determines if the Rouge hard missions should be included
"""
display_name = "Rouge Mission 5"
class KartMissionCount(BaseMissionCount):
@@ -706,7 +1018,7 @@ class RingLoss(Choice):
Modern: You lose 20 rings when hit
OHKO: You die immediately when hit (NOTE: Some Hard Logic tricks may require damage boosts!)
OHKO: You die immediately when hit (NOTE: Some Hard or Expert Logic tricks may require damage boosts!)
"""
display_name = "Ring Loss"
option_classic = 0
@@ -729,6 +1041,16 @@ class RingLink(Toggle):
display_name = "Ring Link"
class TrapLink(Toggle):
"""
Whether your received traps are linked to other players
You will also receive any linked traps from other players with Trap Link enabled,
if you have a weight above "none" set for that trap
"""
display_name = "Trap Link"
class SADXMusic(Choice):
"""
Whether the randomizer will include Sonic Adventure DX Music in the music pool
@@ -823,11 +1145,14 @@ class LogicDifficulty(Choice):
Standard: The logic assumes the "intended" usage of Upgrades to progress through levels
Hard: Some simple skips or sequence breaks may be required
Hard: Some simple skips or sequence breaks may be required, but no out-of-bounds
Expert: If it is humanly possible, it may be required
"""
display_name = "Logic Difficulty"
option_standard = 0
option_hard = 1
option_expert = 2
default = 0
@@ -835,6 +1160,8 @@ sa2b_option_groups = [
OptionGroup("General Options", [
Goal,
BossRushShuffle,
MinigameMadnessRequirement,
MinigameMadnessMinimum,
LogicDifficulty,
RequiredRank,
MaximumEmblemCap,
@@ -854,6 +1181,8 @@ sa2b_option_groups = [
Beetlesanity,
Omosanity,
Animalsanity,
ItemBoxsanity,
Bigsanity,
KartRaceChecks,
]),
OptionGroup("Chao", [
@@ -885,29 +1214,68 @@ sa2b_option_groups = [
SlowTrapWeight,
CutsceneTrapWeight,
ReverseTrapWeight,
LiteratureTrapWeight,
ControllerDriftTrapWeight,
PoisonTrapWeight,
BeeTrapWeight,
]),
OptionGroup("Minigames", [
PongTrapWeight,
BreakoutTrapWeight,
FishingTrapWeight,
TriviaTrapWeight,
PokemonTriviaTrapWeight,
PokemonCountTrapWeight,
NumberSequenceTrapWeight,
LightUpPathTrapWeight,
PinballTrapWeight,
MathQuizTrapWeight,
SnakeTrapWeight,
InputSequenceTrapWeight,
MinigameTrapDifficulty,
BigFishingDifficulty,
]),
OptionGroup("Speed Missions", [
SpeedMissionCount,
SpeedMission2,
SpeedMission3,
SpeedMission4,
SpeedMission5,
OptionGroup("Sonic Missions", [
SonicMissionCount,
SonicMission2,
SonicMission3,
SonicMission4,
SonicMission5,
]),
OptionGroup("Mech Missions", [
MechMissionCount,
MechMission2,
MechMission3,
MechMission4,
MechMission5,
OptionGroup("Shadow Missions", [
ShadowMissionCount,
ShadowMission2,
ShadowMission3,
ShadowMission4,
ShadowMission5,
]),
OptionGroup("Hunt Missions", [
HuntMissionCount,
HuntMission2,
HuntMission3,
HuntMission4,
HuntMission5,
OptionGroup("Tails Missions", [
TailsMissionCount,
TailsMission2,
TailsMission3,
TailsMission4,
TailsMission5,
]),
OptionGroup("Eggman Missions", [
EggmanMissionCount,
EggmanMission2,
EggmanMission3,
EggmanMission4,
EggmanMission5,
]),
OptionGroup("Knuckles Missions", [
KnucklesMissionCount,
KnucklesMission2,
KnucklesMission3,
KnucklesMission4,
KnucklesMission5,
]),
OptionGroup("Rouge Missions", [
RougeMissionCount,
RougeMission2,
RougeMission3,
RougeMission4,
RougeMission5,
]),
OptionGroup("Kart Missions", [
KartMissionCount,
@@ -931,11 +1299,13 @@ sa2b_option_groups = [
]),
]
@dataclass
class SA2BOptions(PerGameCommonOptions):
goal: Goal
boss_rush_shuffle: BossRushShuffle
minigame_madness_requirement: MinigameMadnessRequirement
minigame_madness_minimum: MinigameMadnessMinimum
gate_boss_plando: GateBossPlando
logic_difficulty: LogicDifficulty
required_rank: RequiredRank
max_emblem_cap: MaximumEmblemCap
@@ -953,6 +1323,8 @@ class SA2BOptions(PerGameCommonOptions):
beetlesanity: Beetlesanity
omosanity: Omosanity
animalsanity: Animalsanity
itemboxsanity: ItemBoxsanity
bigsanity: Bigsanity
kart_race_checks: KartRaceChecks
black_market_slots: BlackMarketSlots
@@ -983,31 +1355,65 @@ class SA2BOptions(PerGameCommonOptions):
slow_trap_weight: SlowTrapWeight
cutscene_trap_weight: CutsceneTrapWeight
reverse_trap_weight: ReverseTrapWeight
literature_trap_weight: LiteratureTrapWeight
controller_drift_trap_weight: ControllerDriftTrapWeight
poison_trap_weight: PoisonTrapWeight
bee_trap_weight: BeeTrapWeight
pong_trap_weight: PongTrapWeight
breakout_trap_weight: BreakoutTrapWeight
fishing_trap_weight: FishingTrapWeight
trivia_trap_weight: TriviaTrapWeight
pokemon_trivia_trap_weight: PokemonTriviaTrapWeight
pokemon_count_trap_weight: PokemonCountTrapWeight
number_sequence_trap_weight: NumberSequenceTrapWeight
light_up_path_trap_weight: LightUpPathTrapWeight
pinball_trap_weight: PinballTrapWeight
math_quiz_trap_weight: MathQuizTrapWeight
snake_trap_weight: SnakeTrapWeight
input_sequence_trap_weight: InputSequenceTrapWeight
minigame_trap_difficulty: MinigameTrapDifficulty
big_fishing_difficulty: BigFishingDifficulty
sadx_music: SADXMusic
music_shuffle: MusicShuffle
voice_shuffle: VoiceShuffle
narrator: Narrator
speed_mission_count: SpeedMissionCount
speed_mission_2: SpeedMission2
speed_mission_3: SpeedMission3
speed_mission_4: SpeedMission4
speed_mission_5: SpeedMission5
sonic_mission_count: SonicMissionCount
sonic_mission_2: SonicMission2
sonic_mission_3: SonicMission3
sonic_mission_4: SonicMission4
sonic_mission_5: SonicMission5
mech_mission_count: MechMissionCount
mech_mission_2: MechMission2
mech_mission_3: MechMission3
mech_mission_4: MechMission4
mech_mission_5: MechMission5
shadow_mission_count: ShadowMissionCount
shadow_mission_2: ShadowMission2
shadow_mission_3: ShadowMission3
shadow_mission_4: ShadowMission4
shadow_mission_5: ShadowMission5
hunt_mission_count: HuntMissionCount
hunt_mission_2: HuntMission2
hunt_mission_3: HuntMission3
hunt_mission_4: HuntMission4
hunt_mission_5: HuntMission5
tails_mission_count: TailsMissionCount
tails_mission_2: TailsMission2
tails_mission_3: TailsMission3
tails_mission_4: TailsMission4
tails_mission_5: TailsMission5
eggman_mission_count: EggmanMissionCount
eggman_mission_2: EggmanMission2
eggman_mission_3: EggmanMission3
eggman_mission_4: EggmanMission4
eggman_mission_5: EggmanMission5
knuckles_mission_count: KnucklesMissionCount
knuckles_mission_2: KnucklesMission2
knuckles_mission_3: KnucklesMission3
knuckles_mission_4: KnucklesMission4
knuckles_mission_5: KnucklesMission5
rouge_mission_count: RougeMissionCount
rouge_mission_2: RougeMission2
rouge_mission_3: RougeMission3
rouge_mission_4: RougeMission4
rouge_mission_5: RougeMission5
kart_mission_count: KartMissionCount
kart_mission_2: KartMission2
@@ -1022,4 +1428,5 @@ class SA2BOptions(PerGameCommonOptions):
cannons_core_mission_5: CannonsCoreMission5
ring_link: RingLink
trap_link: TrapLink
death_link: DeathLink

502
worlds/sa2b/Presets.py Normal file
View File

@@ -0,0 +1,502 @@
from typing import Dict, Any
from .Options import *
minsanity = {
"goal": Goal.option_chaos_chao,
"max_emblem_cap": MaximumEmblemCap.range_start,
"keysanity": False,
"whistlesanity": Whistlesanity.option_none,
"beetlesanity": False,
"omosanity": False,
"animalsanity": False,
"itemboxsanity": ItemBoxsanity.option_none,
"bigsanity": False,
"kart_race_checks": KartRaceChecks.option_none,
"junk_fill_percentage": 0,
"sonic_mission_count": BaseMissionCount.range_start,
"sonic_mission_2": False,
"sonic_mission_3": False,
"sonic_mission_4": False,
"sonic_mission_5": False,
"shadow_mission_count": BaseMissionCount.range_start,
"shadow_mission_2": False,
"shadow_mission_3": False,
"shadow_mission_4": False,
"shadow_mission_5": False,
"tails_mission_count": BaseMissionCount.range_start,
"tails_mission_2": False,
"tails_mission_3": False,
"tails_mission_4": False,
"tails_mission_5": False,
"eggman_mission_count": BaseMissionCount.range_start,
"eggman_mission_2": False,
"eggman_mission_3": False,
"eggman_mission_4": False,
"eggman_mission_5": False,
"knuckles_mission_count": BaseMissionCount.range_start,
"knuckles_mission_2": False,
"knuckles_mission_3": False,
"knuckles_mission_4": False,
"knuckles_mission_5": False,
"rouge_mission_count": BaseMissionCount.range_start,
"rouge_mission_2": False,
"rouge_mission_3": False,
"rouge_mission_4": False,
"rouge_mission_5": False,
"kart_mission_count": BaseMissionCount.range_start,
"kart_mission_2": False,
"kart_mission_3": False,
"kart_mission_4": False,
"kart_mission_5": False,
"cannons_core_mission_count": BaseMissionCount.range_start,
"cannons_core_mission_2": False,
"cannons_core_mission_3": False,
"cannons_core_mission_4": False,
"cannons_core_mission_5": False,
}
chao_centric = {
"goal": Goal.option_chaos_chao,
"keysanity": False,
"whistlesanity": Whistlesanity.option_none,
"beetlesanity": False,
"omosanity": False,
"animalsanity": False,
"itemboxsanity": ItemBoxsanity.option_none,
"bigsanity": False,
"kart_race_checks": KartRaceChecks.option_none,
"black_market_slots": BlackMarketSlots.range_end,
"black_market_unlock_costs": BlackMarketUnlockCosts.option_high,
"chao_race_difficulty": ChaoRaceDifficulty.option_expert,
"chao_karate_difficulty": ChaoKarateDifficulty.option_super,
"chao_stadium_checks": ChaoStadiumChecks.option_all,
"chao_animal_parts": True,
"chao_stats": ChaoStats.range_end,
"chao_stats_frequency": 1,
"chao_stats_stamina": True,
"chao_stats_hidden": True,
"chao_kindergarten": ChaoKindergarten.option_full,
"junk_fill_percentage": 50,
"sonic_mission_count": BaseMissionCount.range_start,
"sonic_mission_2": False,
"sonic_mission_3": False,
"sonic_mission_4": False,
"sonic_mission_5": False,
"shadow_mission_count": BaseMissionCount.range_start,
"shadow_mission_2": False,
"shadow_mission_3": False,
"shadow_mission_4": False,
"shadow_mission_5": False,
"tails_mission_count": BaseMissionCount.range_start,
"tails_mission_2": False,
"tails_mission_3": False,
"tails_mission_4": False,
"tails_mission_5": False,
"eggman_mission_count": BaseMissionCount.range_start,
"eggman_mission_2": False,
"eggman_mission_3": False,
"eggman_mission_4": False,
"eggman_mission_5": False,
"knuckles_mission_count": BaseMissionCount.range_start,
"knuckles_mission_2": False,
"knuckles_mission_3": False,
"knuckles_mission_4": False,
"knuckles_mission_5": False,
"rouge_mission_count": BaseMissionCount.range_start,
"rouge_mission_2": False,
"rouge_mission_3": False,
"rouge_mission_4": False,
"rouge_mission_5": False,
"kart_mission_count": BaseMissionCount.range_start,
"kart_mission_2": False,
"kart_mission_3": False,
"kart_mission_4": False,
"kart_mission_5": False,
"cannons_core_mission_count": BaseMissionCount.range_start,
"cannons_core_mission_2": False,
"cannons_core_mission_3": False,
"cannons_core_mission_4": False,
"cannons_core_mission_5": False,
}
allsanity_no_chao = {
"goal": Goal.option_cannons_core_boss_rush,
"boss_rush_shuffle": BossRushShuffle.option_chaos,
"minigame_madness_requirement": MinigameMadnessRequirement.range_end,
"minigame_madness_minimum": MinigameMadnessMinimum.range_end,
"max_emblem_cap": MaximumEmblemCap.range_end,
"mission_shuffle": True,
"required_cannons_core_missions": RequiredCannonsCoreMissions.option_all_active,
"emblem_percentage_for_cannons_core": EmblemPercentageForCannonsCore.range_end,
"number_of_level_gates": NumberOfLevelGates.range_end,
"level_gate_costs": LevelGateCosts.option_high,
"keysanity": True,
"whistlesanity": Whistlesanity.option_both,
"beetlesanity": True,
"omosanity": True,
"animalsanity": True,
"itemboxsanity": ItemBoxsanity.option_all,
"bigsanity": True,
"kart_race_checks": KartRaceChecks.option_full,
"junk_fill_percentage": 25,
"trap_fill_percentage": 25,
"omochao_trap_weight": BaseTrapWeight.option_high,
"timestop_trap_weight": BaseTrapWeight.option_high,
"confusion_trap_weight": BaseTrapWeight.option_high,
"tiny_trap_weight": BaseTrapWeight.option_high,
"gravity_trap_weight": BaseTrapWeight.option_high,
"exposition_trap_weight": BaseTrapWeight.option_high,
"ice_trap_weight": BaseTrapWeight.option_high,
"slow_trap_weight": BaseTrapWeight.option_high,
"cutscene_trap_weight": BaseTrapWeight.option_high,
"reverse_trap_weight": BaseTrapWeight.option_high,
"literature_trap_weight": BaseTrapWeight.option_high,
"controller_drift_trap_weight": BaseTrapWeight.option_high,
"poison_trap_weight": BaseTrapWeight.option_high,
"bee_trap_weight": BaseTrapWeight.option_high,
"pong_trap_weight": BaseTrapWeight.option_high,
"breakout_trap_weight": BaseTrapWeight.option_high,
"fishing_trap_weight": BaseTrapWeight.option_high,
"trivia_trap_weight": BaseTrapWeight.option_high,
"pokemon_trivia_trap_weight": BaseTrapWeight.option_high,
"pokemon_count_trap_weight": BaseTrapWeight.option_high,
"number_sequence_trap_weight": BaseTrapWeight.option_high,
"light_up_path_trap_weight": BaseTrapWeight.option_high,
"pinball_trap_weight": BaseTrapWeight.option_high,
"math_quiz_trap_weight": BaseTrapWeight.option_high,
"snake_trap_weight": BaseTrapWeight.option_high,
"input_sequence_trap_weight": BaseTrapWeight.option_high,
"minigame_trap_difficulty": MinigameTrapDifficulty.option_chaos,
"big_fishing_difficulty": BigFishingDifficulty.option_chaos,
"music_shuffle": MusicShuffle.option_full,
"voice_shuffle": VoiceShuffle.option_shuffled,
"sonic_mission_count": BaseMissionCount.range_end,
"sonic_mission_2": True,
"sonic_mission_3": True,
"sonic_mission_4": True,
"sonic_mission_5": True,
"shadow_mission_count": BaseMissionCount.range_end,
"shadow_mission_2": True,
"shadow_mission_3": True,
"shadow_mission_4": True,
"shadow_mission_5": True,
"tails_mission_count": BaseMissionCount.range_end,
"tails_mission_2": True,
"tails_mission_3": True,
"tails_mission_4": True,
"tails_mission_5": True,
"eggman_mission_count": BaseMissionCount.range_end,
"eggman_mission_2": True,
"eggman_mission_3": True,
"eggman_mission_4": True,
"eggman_mission_5": True,
"knuckles_mission_count": BaseMissionCount.range_end,
"knuckles_mission_2": True,
"knuckles_mission_3": True,
"knuckles_mission_4": True,
"knuckles_mission_5": True,
"rouge_mission_count": BaseMissionCount.range_end,
"rouge_mission_2": True,
"rouge_mission_3": True,
"rouge_mission_4": True,
"rouge_mission_5": True,
"kart_mission_count": BaseMissionCount.range_end,
"kart_mission_2": True,
"kart_mission_3": True,
"kart_mission_4": True,
"kart_mission_5": True,
"cannons_core_mission_count": BaseMissionCount.range_end,
"cannons_core_mission_2": True,
"cannons_core_mission_3": True,
"cannons_core_mission_4": True,
"cannons_core_mission_5": True,
}
allsanity = {
"goal": Goal.option_cannons_core_boss_rush,
"boss_rush_shuffle": BossRushShuffle.option_chaos,
"minigame_madness_requirement": MinigameMadnessRequirement.range_end,
"minigame_madness_minimum": MinigameMadnessMinimum.range_end,
"max_emblem_cap": MaximumEmblemCap.range_end,
"mission_shuffle": True,
"required_cannons_core_missions": RequiredCannonsCoreMissions.option_all_active,
"emblem_percentage_for_cannons_core": EmblemPercentageForCannonsCore.range_end,
"number_of_level_gates": NumberOfLevelGates.range_end,
"level_gate_costs": LevelGateCosts.option_high,
"keysanity": True,
"whistlesanity": Whistlesanity.option_both,
"beetlesanity": True,
"omosanity": True,
"animalsanity": True,
"itemboxsanity": ItemBoxsanity.option_all,
"bigsanity": True,
"kart_race_checks": KartRaceChecks.option_full,
"black_market_slots": BlackMarketSlots.range_end,
"black_market_unlock_costs": BlackMarketUnlockCosts.option_high,
"chao_race_difficulty": ChaoRaceDifficulty.option_expert,
"chao_karate_difficulty": ChaoKarateDifficulty.option_super,
"chao_stadium_checks": ChaoStadiumChecks.option_all,
"chao_animal_parts": True,
"chao_stats": ChaoStats.range_end,
"chao_stats_frequency": 1,
"chao_stats_stamina": True,
"chao_stats_hidden": True,
"chao_kindergarten": ChaoKindergarten.option_full,
"junk_fill_percentage": 25,
"trap_fill_percentage": 25,
"omochao_trap_weight": BaseTrapWeight.option_high,
"timestop_trap_weight": BaseTrapWeight.option_high,
"confusion_trap_weight": BaseTrapWeight.option_high,
"tiny_trap_weight": BaseTrapWeight.option_high,
"gravity_trap_weight": BaseTrapWeight.option_high,
"exposition_trap_weight": BaseTrapWeight.option_high,
"ice_trap_weight": BaseTrapWeight.option_high,
"slow_trap_weight": BaseTrapWeight.option_high,
"cutscene_trap_weight": BaseTrapWeight.option_high,
"reverse_trap_weight": BaseTrapWeight.option_high,
"literature_trap_weight": BaseTrapWeight.option_high,
"controller_drift_trap_weight": BaseTrapWeight.option_high,
"poison_trap_weight": BaseTrapWeight.option_high,
"bee_trap_weight": BaseTrapWeight.option_high,
"pong_trap_weight": BaseTrapWeight.option_high,
"breakout_trap_weight": BaseTrapWeight.option_high,
"fishing_trap_weight": BaseTrapWeight.option_high,
"trivia_trap_weight": BaseTrapWeight.option_high,
"pokemon_trivia_trap_weight": BaseTrapWeight.option_high,
"pokemon_count_trap_weight": BaseTrapWeight.option_high,
"number_sequence_trap_weight": BaseTrapWeight.option_high,
"light_up_path_trap_weight": BaseTrapWeight.option_high,
"pinball_trap_weight": BaseTrapWeight.option_high,
"math_quiz_trap_weight": BaseTrapWeight.option_high,
"snake_trap_weight": BaseTrapWeight.option_high,
"input_sequence_trap_weight": BaseTrapWeight.option_high,
"minigame_trap_difficulty": MinigameTrapDifficulty.option_chaos,
"big_fishing_difficulty": BigFishingDifficulty.option_chaos,
"music_shuffle": MusicShuffle.option_full,
"voice_shuffle": VoiceShuffle.option_shuffled,
"sonic_mission_count": BaseMissionCount.range_end,
"sonic_mission_2": True,
"sonic_mission_3": True,
"sonic_mission_4": True,
"sonic_mission_5": True,
"shadow_mission_count": BaseMissionCount.range_end,
"shadow_mission_2": True,
"shadow_mission_3": True,
"shadow_mission_4": True,
"shadow_mission_5": True,
"tails_mission_count": BaseMissionCount.range_end,
"tails_mission_2": True,
"tails_mission_3": True,
"tails_mission_4": True,
"tails_mission_5": True,
"eggman_mission_count": BaseMissionCount.range_end,
"eggman_mission_2": True,
"eggman_mission_3": True,
"eggman_mission_4": True,
"eggman_mission_5": True,
"knuckles_mission_count": BaseMissionCount.range_end,
"knuckles_mission_2": True,
"knuckles_mission_3": True,
"knuckles_mission_4": True,
"knuckles_mission_5": True,
"rouge_mission_count": BaseMissionCount.range_end,
"rouge_mission_2": True,
"rouge_mission_3": True,
"rouge_mission_4": True,
"rouge_mission_5": True,
"kart_mission_count": BaseMissionCount.range_end,
"kart_mission_2": True,
"kart_mission_3": True,
"kart_mission_4": True,
"kart_mission_5": True,
"cannons_core_mission_count": BaseMissionCount.range_end,
"cannons_core_mission_2": True,
"cannons_core_mission_3": True,
"cannons_core_mission_4": True,
"cannons_core_mission_5": True,
}
all_random = {
"goal": "random",
"boss_rush_shuffle": "random",
"minigame_madness_requirement": "random",
"minigame_madness_minimum": "random",
"logic_difficulty": "random",
"required_rank": "random",
"max_emblem_cap": "random",
"ring_loss": "random",
"mission_shuffle": "random",
"required_cannons_core_missions": "random",
"emblem_percentage_for_cannons_core": "random",
"number_of_level_gates": "random",
"level_gate_distribution": "random",
"level_gate_costs": "random",
"keysanity": "random",
"whistlesanity": "random",
"beetlesanity": "random",
"omosanity": "random",
"animalsanity": "random",
"itemboxsanity": "random",
"bigsanity": "random",
"kart_race_checks": "random",
"black_market_slots": "random",
"black_market_unlock_costs": "random",
"black_market_price_multiplier": "random",
"chao_race_difficulty": "random",
"chao_karate_difficulty": "random",
"chao_stadium_checks": "random",
"chao_animal_parts": "random",
"chao_stats": "random",
"chao_stats_frequency": "random",
"chao_stats_stamina": "random",
"chao_stats_hidden": "random",
"chao_kindergarten": "random",
"shuffle_starting_chao_eggs": "random",
"chao_entrance_randomization": "random",
"junk_fill_percentage": "random",
"trap_fill_percentage": "random",
"omochao_trap_weight": "random",
"timestop_trap_weight": "random",
"confusion_trap_weight": "random",
"tiny_trap_weight": "random",
"gravity_trap_weight": "random",
"exposition_trap_weight": "random",
"ice_trap_weight": "random",
"slow_trap_weight": "random",
"cutscene_trap_weight": "random",
"reverse_trap_weight": "random",
"literature_trap_weight": "random",
"controller_drift_trap_weight": "random",
"poison_trap_weight": "random",
"bee_trap_weight": "random",
"pong_trap_weight": "random",
"breakout_trap_weight": "random",
"fishing_trap_weight": "random",
"trivia_trap_weight": "random",
"pokemon_trivia_trap_weight": "random",
"pokemon_count_trap_weight": "random",
"number_sequence_trap_weight": "random",
"light_up_path_trap_weight": "random",
"pinball_trap_weight": "random",
"math_quiz_trap_weight": "random",
"snake_trap_weight": "random",
"input_sequence_trap_weight": "random",
"minigame_trap_difficulty": "random",
"big_fishing_difficulty": "random",
"sadx_music": "random",
"music_shuffle": "random",
"voice_shuffle": "random",
"narrator": "random",
"sonic_mission_count": "random",
"sonic_mission_2": "random",
"sonic_mission_3": "random",
"sonic_mission_4": "random",
"sonic_mission_5": "random",
"shadow_mission_count": "random",
"shadow_mission_2": "random",
"shadow_mission_3": "random",
"shadow_mission_4": "random",
"shadow_mission_5": "random",
"tails_mission_count": "random",
"tails_mission_2": "random",
"tails_mission_3": "random",
"tails_mission_4": "random",
"tails_mission_5": "random",
"eggman_mission_count": "random",
"eggman_mission_2": "random",
"eggman_mission_3": "random",
"eggman_mission_4": "random",
"eggman_mission_5": "random",
"knuckles_mission_count": "random",
"knuckles_mission_2": "random",
"knuckles_mission_3": "random",
"knuckles_mission_4": "random",
"knuckles_mission_5": "random",
"rouge_mission_count": "random",
"rouge_mission_2": "random",
"rouge_mission_3": "random",
"rouge_mission_4": "random",
"rouge_mission_5": "random",
"kart_mission_count": "random",
"kart_mission_2": "random",
"kart_mission_3": "random",
"kart_mission_4": "random",
"kart_mission_5": "random",
"cannons_core_mission_count": "random",
"cannons_core_mission_2": "random",
"cannons_core_mission_3": "random",
"cannons_core_mission_4": "random",
"cannons_core_mission_5": "random",
"ring_link": "random",
"trap_link": "random",
"death_link": "random",
}
sa2b_options_presets: Dict[str, Dict[str, Any]] = {
"Minsanity": minsanity,
"Chao-centric": chao_centric,
"Allsanity No Chao": allsanity_no_chao,
"Allsanity": allsanity,
"All Random": all_random,
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,12 +8,13 @@ from worlds.AutoWorld import WebWorld, World
from .AestheticData import chao_name_conversion, sample_chao_names, totally_real_item_names, \
all_exits, all_destinations, multi_rooms, single_rooms, room_to_exits_map, exit_to_room_map, valid_kindergarten_exits
from .GateBosses import get_gate_bosses, get_boss_rush_bosses, get_boss_name
from .Items import SA2BItem, ItemData, item_table, upgrades_table, emeralds_table, junk_table, trap_table, item_groups, \
eggs_table, fruits_table, seeds_table, hats_table, animals_table, chaos_drives_table
from .Locations import SA2BLocation, all_locations, setup_locations, chao_animal_event_location_table, black_market_location_table
from .Missions import get_mission_table, get_mission_count_table, get_first_and_last_cannons_core_missions
from .Items import SA2BItem, ItemData, item_table, upgrades_table, emeralds_table, junk_table, minigame_trap_table, item_groups, \
eggs_table, fruits_table, seeds_table, hats_table, animals_table, chaos_drives_table, event_table
from .Locations import SA2BLocation, all_locations, location_groups, setup_locations, chao_animal_event_location_table, black_market_location_table
from .Missions import get_mission_table, get_mission_count_table, get_first_and_last_cannons_core_missions, print_mission_orders_to_spoiler
from .Names import ItemName, LocationName
from .Options import SA2BOptions, sa2b_option_groups
from .Presets import sa2b_options_presets
from .Regions import create_regions, shuffleable_regions, connect_regions, LevelGate, gate_0_whitelist_regions, \
gate_0_blacklist_regions
from .Rules import set_rules
@@ -33,6 +34,7 @@ class SA2BWeb(WebWorld):
tutorials = [setup_en]
option_groups = sa2b_option_groups
options_presets = sa2b_options_presets
def check_for_impossible_shuffle(shuffled_levels: typing.List[int], gate_0_range: int, multiworld: MultiWorld):
@@ -60,11 +62,14 @@ class SA2BWorld(World):
topology_present = False
item_name_groups = item_groups
location_name_groups = location_groups
item_name_to_id = {name: data.code for name, data in item_table.items()}
location_name_to_id = all_locations
location_table: typing.Dict[str, int]
shuffled_region_list: typing.List[int]
levels_per_gate: typing.List[int]
mission_map: typing.Dict[int, int]
mission_count_map: typing.Dict[int, int]
emblems_for_cannons_core: int
@@ -78,7 +83,7 @@ class SA2BWorld(World):
def fill_slot_data(self) -> dict:
return {
"ModVersion": 203,
"ModVersion": 204,
"Goal": self.options.goal.value,
"MusicMap": self.generate_music_data(),
"VoiceMap": self.generate_voice_data(),
@@ -89,14 +94,20 @@ class SA2BWorld(World):
"MusicShuffle": self.options.music_shuffle.value,
"Narrator": self.options.narrator.value,
"MinigameTrapDifficulty": self.options.minigame_trap_difficulty.value,
"BigFishingDifficulty": self.options.big_fishing_difficulty.value,
"RingLoss": self.options.ring_loss.value,
"RingLink": self.options.ring_link.value,
"TrapLink": self.options.trap_link.value,
"RequiredRank": self.options.required_rank.value,
"MinigameMadnessAmount": self.options.minigame_madness_requirement.value,
"LogicDifficulty": self.options.logic_difficulty.value,
"ChaoKeys": self.options.keysanity.value,
"Whistlesanity": self.options.whistlesanity.value,
"GoldBeetles": self.options.beetlesanity.value,
"OmochaoChecks": self.options.omosanity.value,
"AnimalChecks": self.options.animalsanity.value,
"ItemBoxChecks": self.options.itemboxsanity.value,
"BigChecks": self.options.bigsanity.value,
"KartRaceChecks": self.options.kart_race_checks.value,
"ChaoStadiumChecks": self.options.chao_stadium_checks.value,
"ChaoRaceDifficulty": self.options.chao_race_difficulty.value,
@@ -122,6 +133,7 @@ class SA2BWorld(World):
"GateCosts": self.gate_costs,
"GateBosses": self.gate_bosses,
"BossRushMap": self.boss_rush_map,
"ActiveTraps": self.output_active_traps(),
"PlayerNum": self.player,
}
@@ -151,12 +163,42 @@ class SA2BWorld(World):
valid_trap_weights = self.options.exposition_trap_weight.value + \
self.options.reverse_trap_weight.value + \
self.options.pong_trap_weight.value
self.options.literature_trap_weight.value + \
self.options.controller_drift_trap_weight.value + \
self.options.poison_trap_weight.value + \
self.options.bee_trap_weight.value + \
self.options.pong_trap_weight.value + \
self.options.breakout_trap_weight.value + \
self.options.fishing_trap_weight.value + \
self.options.trivia_trap_weight.value + \
self.options.pokemon_trivia_trap_weight.value + \
self.options.pokemon_count_trap_weight.value + \
self.options.number_sequence_trap_weight.value + \
self.options.light_up_path_trap_weight.value + \
self.options.pinball_trap_weight.value + \
self.options.math_quiz_trap_weight.value + \
self.options.snake_trap_weight.value + \
self.options.input_sequence_trap_weight.value
if valid_trap_weights == 0:
self.options.exposition_trap_weight.value = 4
self.options.reverse_trap_weight.value = 4
self.options.literature_trap_weight.value = 4
self.options.controller_drift_trap_weight.value = 4
self.options.poison_trap_weight.value = 4
self.options.bee_trap_weight.value = 4
self.options.pong_trap_weight.value = 4
self.options.breakout_trap_weight.value = 4
self.options.fishing_trap_weight.value = 4
self.options.trivia_trap_weight.value = 4
self.options.pokemon_trivia_trap_weight.value = 4
self.options.pokemon_count_trap_weight.value = 4
self.options.number_sequence_trap_weight.value = 4
self.options.light_up_path_trap_weight.value = 4
self.options.pinball_trap_weight.value = 4
self.options.math_quiz_trap_weight.value = 4
self.options.snake_trap_weight.value = 4
self.options.input_sequence_trap_weight.value = 4
if self.options.kart_race_checks.value == 0:
self.options.kart_race_checks.value = 2
@@ -164,8 +206,8 @@ class SA2BWorld(World):
self.gate_bosses = {}
self.boss_rush_map = {}
else:
self.gate_bosses = get_gate_bosses(self.multiworld, self)
self.boss_rush_map = get_boss_rush_bosses(self.multiworld, self)
self.gate_bosses = get_gate_bosses(self)
self.boss_rush_map = get_boss_rush_bosses(self)
def create_regions(self):
self.mission_map = get_mission_table(self.multiworld, self, self.player)
@@ -177,7 +219,7 @@ class SA2BWorld(World):
# Not Generate Basic
self.black_market_costs = dict()
if self.options.goal.value in [0, 2, 4, 5, 6]:
if self.options.goal.value in [0, 2, 4, 5, 6, 8]:
self.multiworld.get_location(LocationName.finalhazard, self.player).place_locked_item(self.create_item(ItemName.maria))
elif self.options.goal.value == 1:
self.multiworld.get_location(LocationName.green_hill, self.player).place_locked_item(self.create_item(ItemName.maria))
@@ -202,7 +244,7 @@ class SA2BWorld(World):
if self.options.goal.value != 3:
# Fill item pool with all required items
for item in {**upgrades_table}:
itempool += [self.create_item(item, False, self.options.goal.value)]
itempool += [self.create_item(item, None, self.options.goal.value)]
if self.options.goal.value in [1, 2, 6]:
# Some flavor of Chaos Emerald Hunt
@@ -212,6 +254,25 @@ class SA2BWorld(World):
# Black Market
itempool += [self.create_item(ItemName.market_token) for _ in range(self.options.black_market_slots.value)]
if self.options.goal.value in [8]:
available_locations: int = total_required_locations - len(itempool) - self.options.number_of_level_gates.value
while (self.options.minigame_madness_requirement.value * len(minigame_trap_table)) > available_locations:
self.options.minigame_madness_requirement.value -= 1
while (self.options.minigame_madness_minimum.value * len(minigame_trap_table)) > available_locations:
self.options.minigame_madness_minimum.value -= 1
traps_to_create: int = max(self.options.minigame_madness_minimum.value, self.options.minigame_madness_requirement.value)
# Minigame Madness
for item in {**minigame_trap_table}:
for i in range(traps_to_create):
classification: ItemClassification = ItemClassification.trap
if i < self.options.minigame_madness_requirement.value:
classification |= ItemClassification.progression
itempool.append(self.create_item(item, classification))
black_market_unlock_mult = 1.0
if self.options.black_market_unlock_costs.value == 0:
black_market_unlock_mult = 0.5
@@ -235,12 +296,12 @@ class SA2BWorld(World):
elif self.options.level_gate_costs.value == 1:
gate_cost_mult = 0.8
shuffled_region_list = list(range(30))
self.shuffled_region_list = list(range(30))
emblem_requirement_list = list()
self.multiworld.random.shuffle(shuffled_region_list)
levels_per_gate = self.get_levels_per_gate()
self.multiworld.random.shuffle(self.shuffled_region_list)
self.levels_per_gate = self.get_levels_per_gate()
check_for_impossible_shuffle(shuffled_region_list, math.ceil(levels_per_gate[0]), self.multiworld)
check_for_impossible_shuffle(self.shuffled_region_list, math.ceil(self.levels_per_gate[0]), self.multiworld)
levels_added_to_gate = 0
total_levels_added = 0
current_gate = 0
@@ -250,11 +311,11 @@ class SA2BWorld(World):
gates = list()
gates.append(LevelGate(0))
for i in range(30):
gates[current_gate].gate_levels.append(shuffled_region_list[i])
gates[current_gate].gate_levels.append(self.shuffled_region_list[i])
emblem_requirement_list.append(current_gate_emblems)
levels_added_to_gate += 1
total_levels_added += 1
if levels_added_to_gate >= levels_per_gate[current_gate]:
if levels_added_to_gate >= self.levels_per_gate[current_gate]:
current_gate += 1
if current_gate > self.options.number_of_level_gates.value:
current_gate = self.options.number_of_level_gates.value
@@ -265,18 +326,19 @@ class SA2BWorld(World):
self.gate_costs[current_gate] = current_gate_emblems
levels_added_to_gate = 0
self.region_emblem_map = dict(zip(shuffled_region_list, emblem_requirement_list))
self.region_emblem_map = dict(zip(self.shuffled_region_list, emblem_requirement_list))
first_cannons_core_mission, final_cannons_core_mission = get_first_and_last_cannons_core_missions(self.mission_map, self.mission_count_map)
connect_regions(self.multiworld, self, self.player, gates, self.emblems_for_cannons_core, self.gate_bosses, self.boss_rush_map, first_cannons_core_mission, final_cannons_core_mission)
max_required_emblems = max(max(emblem_requirement_list), self.emblems_for_cannons_core)
max_required_emblems = min(int(max_required_emblems * 1.1), total_emblem_count)
itempool += [self.create_item(ItemName.emblem) for _ in range(max_required_emblems)]
non_required_emblems = (total_emblem_count - max_required_emblems)
junk_count = math.floor(non_required_emblems * (self.options.junk_fill_percentage.value / 100.0))
itempool += [self.create_item(ItemName.emblem, True) for _ in range(non_required_emblems - junk_count)]
itempool += [self.create_item(ItemName.emblem, ItemClassification.filler) for _ in range(non_required_emblems - junk_count)]
# Carve Traps out of junk_count
trap_weights = []
@@ -291,7 +353,22 @@ class SA2BWorld(World):
trap_weights += ([ItemName.slow_trap] * self.options.slow_trap_weight.value)
trap_weights += ([ItemName.cutscene_trap] * self.options.cutscene_trap_weight.value)
trap_weights += ([ItemName.reverse_trap] * self.options.reverse_trap_weight.value)
trap_weights += ([ItemName.literature_trap] * self.options.literature_trap_weight.value)
trap_weights += ([ItemName.controller_drift_trap] * self.options.controller_drift_trap_weight.value)
trap_weights += ([ItemName.poison_trap] * self.options.poison_trap_weight.value)
trap_weights += ([ItemName.bee_trap] * self.options.bee_trap_weight.value)
trap_weights += ([ItemName.pong_trap] * self.options.pong_trap_weight.value)
trap_weights += ([ItemName.breakout_trap] * self.options.breakout_trap_weight.value)
trap_weights += ([ItemName.fishing_trap] * self.options.fishing_trap_weight.value)
trap_weights += ([ItemName.trivia_trap] * self.options.trivia_trap_weight.value)
trap_weights += ([ItemName.pokemon_trivia_trap] * self.options.pokemon_trivia_trap_weight.value)
trap_weights += ([ItemName.pokemon_count_trap] * self.options.pokemon_count_trap_weight.value)
trap_weights += ([ItemName.number_sequence_trap] * self.options.number_sequence_trap_weight.value)
trap_weights += ([ItemName.light_up_path_trap] * self.options.light_up_path_trap_weight.value)
trap_weights += ([ItemName.pinball_trap] * self.options.pinball_trap_weight.value)
trap_weights += ([ItemName.math_quiz_trap] * self.options.math_quiz_trap_weight.value)
trap_weights += ([ItemName.snake_trap] * self.options.snake_trap_weight.value)
trap_weights += ([ItemName.input_sequence_trap] * self.options.input_sequence_trap_weight.value)
junk_count += extra_junk_count
trap_count = 0 if (len(trap_weights) == 0) else math.ceil(junk_count * (self.options.trap_fill_percentage.value / 100.0))
@@ -347,11 +424,15 @@ class SA2BWorld(World):
def create_item(self, name: str, force_non_progression=False, goal=0) -> Item:
def create_item(self, name: str, force_classification=None, goal=0) -> Item:
data = None
if name in event_table:
data = event_table[name]
else:
data = item_table[name]
if force_non_progression:
classification = ItemClassification.filler
if force_classification is not None:
classification = force_classification
elif name == ItemName.emblem or \
name in emeralds_table.keys() or \
(name == ItemName.knuckles_shovel_claws and goal in [4, 5]):
@@ -380,9 +461,16 @@ class SA2BWorld(World):
set_rules(self.multiworld, self, self.player, self.gate_bosses, self.boss_rush_map, self.mission_map, self.mission_count_map, self.black_market_costs)
def write_spoiler(self, spoiler_handle: typing.TextIO):
print_mission_orders_to_spoiler(self.mission_map,
self.mission_count_map,
self.shuffled_region_list,
self.levels_per_gate,
self.multiworld.player_name[self.player],
spoiler_handle)
if self.options.number_of_level_gates.value > 0 or self.options.goal.value in [4, 5, 6]:
spoiler_handle.write("\n")
header_text = "Sonic Adventure 2 Bosses for {}:\n"
header_text = "SA2 Bosses for {}:\n"
header_text = header_text.format(self.multiworld.player_name[self.player])
spoiler_handle.write(header_text)
@@ -435,20 +523,20 @@ class SA2BWorld(World):
continue
level_region = exit.connected_region
for location in level_region.locations:
if location.address != None:
er_hint_data[location.address] = gate_name
for i in range(self.options.black_market_slots.value):
location = self.multiworld.get_location(LocationName.chao_black_market_base + str(i + 1), self.player)
er_hint_data[location.address] = str(self.black_market_costs[i]) + " " + str(ItemName.market_token)
hint_data[self.player] = er_hint_data
@classmethod
def stage_fill_hook(cls, multiworld: MultiWorld, progitempool, usefulitempool, filleritempool, fill_locations):
if multiworld.get_game_players("Sonic Adventure 2 Battle"):
progitempool.sort(
key=lambda item: 0 if (item.name != 'Emblem') else 1)
key=lambda item: 0 if ("Emblem" in item.name and item.game == "Sonic Adventure 2 Battle") else 1)
def get_levels_per_gate(self) -> list:
levels_per_gate = list()
@@ -486,6 +574,39 @@ class SA2BWorld(World):
return levels_per_gate
def output_active_traps(self) -> typing.Dict[int, int]:
trap_data = {}
trap_data[0x30] = self.options.omochao_trap_weight.value
trap_data[0x31] = self.options.timestop_trap_weight.value
trap_data[0x32] = self.options.confusion_trap_weight.value
trap_data[0x33] = self.options.tiny_trap_weight.value
trap_data[0x34] = self.options.gravity_trap_weight.value
trap_data[0x35] = self.options.exposition_trap_weight.value
trap_data[0x37] = self.options.ice_trap_weight.value
trap_data[0x38] = self.options.slow_trap_weight.value
trap_data[0x39] = self.options.cutscene_trap_weight.value
trap_data[0x3A] = self.options.reverse_trap_weight.value
trap_data[0x3B] = self.options.literature_trap_weight.value
trap_data[0x3C] = self.options.controller_drift_trap_weight.value
trap_data[0x3D] = self.options.poison_trap_weight.value
trap_data[0x3E] = self.options.bee_trap_weight.value
trap_data[0x50] = self.options.pong_trap_weight.value
trap_data[0x51] = self.options.breakout_trap_weight.value
trap_data[0x52] = self.options.fishing_trap_weight.value
trap_data[0x53] = self.options.trivia_trap_weight.value
trap_data[0x54] = self.options.pokemon_trivia_trap_weight.value
trap_data[0x55] = self.options.pokemon_count_trap_weight.value
trap_data[0x56] = self.options.number_sequence_trap_weight.value
trap_data[0x57] = self.options.light_up_path_trap_weight.value
trap_data[0x58] = self.options.pinball_trap_weight.value
trap_data[0x59] = self.options.math_quiz_trap_weight.value
trap_data[0x5A] = self.options.snake_trap_weight.value
trap_data[0x5B] = self.options.input_sequence_trap_weight.value
return trap_data
def any_chao_locations_active(self) -> bool:
if self.options.chao_race_difficulty.value > 0 or \
self.options.chao_karate_difficulty.value > 0 or \
@@ -686,7 +807,6 @@ class SA2BWorld(World):
exit_choice = self.random.choice(valid_kindergarten_exits)
exit_room = exit_to_room_map[exit_choice]
all_exits_copy.remove(exit_choice)
multi_rooms_copy.remove(exit_room)
destination = 0x06
single_rooms_copy.remove(destination)
@@ -723,7 +843,8 @@ class SA2BWorld(World):
er_layout[exit_choice] = destination
reverse_exit = self.random.choice(room_to_exits_map[destination])
possible_reverse_exits = [exit for exit in room_to_exits_map[destination] if exit in all_exits_copy]
reverse_exit = self.random.choice(possible_reverse_exits)
er_layout[reverse_exit] = exit_room