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

@@ -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)
@@ -73,19 +72,36 @@ junk_table = {
}
trap_table = {
ItemName.omochao_trap: ItemData(0xFF0030, False, True),
ItemName.timestop_trap: ItemData(0xFF0031, False, True),
ItemName.confuse_trap: ItemData(0xFF0032, False, True),
ItemName.tiny_trap: ItemData(0xFF0033, False, True),
ItemName.gravity_trap: ItemData(0xFF0034, False, True),
ItemName.exposition_trap: ItemData(0xFF0035, False, True),
#ItemName.darkness_trap: ItemData(0xFF0036, False, True),
ItemName.ice_trap: ItemData(0xFF0037, False, True),
ItemName.slow_trap: ItemData(0xFF0038, False, True),
ItemName.cutscene_trap: ItemData(0xFF0039, False, True),
ItemName.reverse_trap: ItemData(0xFF003A, False, True),
ItemName.omochao_trap: ItemData(0xFF0030, False, True),
ItemName.timestop_trap: ItemData(0xFF0031, False, True),
ItemName.confuse_trap: ItemData(0xFF0032, False, True),
ItemName.tiny_trap: ItemData(0xFF0033, False, True),
ItemName.gravity_trap: ItemData(0xFF0034, False, True),
ItemName.exposition_trap: ItemData(0xFF0035, False, True),
#ItemName.darkness_trap: ItemData(0xFF0036, False, True),
ItemName.ice_trap: ItemData(0xFF0037, False, True),
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),
}
ItemName.pong_trap: ItemData(0xFF0050, 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