mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
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:
@@ -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:
|
||||
|
Reference in New Issue
Block a user