mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 12:11:33 -06:00

Changelog: Features: - New goal - Chaos Chao - Raise a Chaos Chao to win! - New optional Location Checks - Chao Animal Parts - Each body part from each type of animal is a location - Chao Stats - 0-99 levels of each of the 7 Chao stats can be locations - The frequency of Chao Stat locations can be set (every level, every 2nd level, etc) - Kindergartensanity - Classroom lessons are locations - Either all lessons or any one of each category can be set as locations - Shopsanity - A specified number of locations can be placed in the Chao Black Market - These locations are unlocked by acquiring `Chao Coin`s - Ring costs for these items can be adjusted - Chao Karate can now be set to one location per fight, instead of one per tournament - Items - If any Chao locations are active, the following will be in the item pool: - Chao Eggs - Garden Seeds - Garden Fruit - Chao Hats - Chaos Drives - The starting eggs in the garden can be a random color - Chao World entrances can be shuffled - Chao are given default names - New Traps - Reverse Trap Quality of Life: - Chao Save Data is now separate per-slot in addition to per-seed - This allows a single player to have multiple slots in the same seed, each having separate Chao progress - Chao Race/Karate progress is now displayed on Stage Select (when hovering over Chao World) - All Chao can now enter the Hero and Dark races - Chao Karate difficulty can be set separately from Chao Race difficulty - Chao Aging can be sped up at will, up to 15× - New mod `config` option to fine-tune Chao Stat multiplication - Note: This does not mix well with the Mod Manager "`Chao Stat Multiplier`" code - Pong Traps can now activate in Chao World - Maximum range for possible number of Emblems is now 1000 - General APWorld cleanup and optimization - Option access has moved to the new options system - An item group now exists for trap items Bug Fixes: - Dry Lagoon now has all 11 Animals - Eternal Engine - 2 (Standard and Hard Logic) now requires only `Tails - Booster` - Lost Colony - 2 (Hard Logic) now requires no upgrades - Lost Colony - Animal 9 (Hard Logic) now requires either `Eggman - Jet Engine` or `Eggman - Large Cannon`
114 lines
3.5 KiB
Python
114 lines
3.5 KiB
Python
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"
|
|
|
|
gate_bosses_no_requirements_table = {
|
|
speed_characters_1: 0,
|
|
speed_characters_2: 1,
|
|
mech_characters_1: 2,
|
|
mech_characters_2: 3,
|
|
hunt_characters_1: 4,
|
|
big_foot: 5,
|
|
hot_shot: 6,
|
|
flying_dog: 7,
|
|
egg_golem_sonic: 8,
|
|
egg_golem_eggman: 9,
|
|
}
|
|
|
|
gate_bosses_with_requirements_table = {
|
|
king_boom_boo: 10,
|
|
}
|
|
|
|
extra_boss_rush_bosses_table = {
|
|
speed_characters_1: 11,
|
|
speed_characters_2: 12,
|
|
mech_characters_1: 13,
|
|
mech_characters_2: 14,
|
|
hunt_characters_1: 15,
|
|
}
|
|
|
|
all_gate_bosses_table = {
|
|
**gate_bosses_no_requirements_table,
|
|
**gate_bosses_with_requirements_table,
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
|
def boss_has_requirement(boss: int):
|
|
return boss >= len(gate_bosses_no_requirements_table)
|
|
|
|
|
|
def get_gate_bosses(multiworld: MultiWorld, 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
|
|
|
|
for x in range(world.options.number_of_level_gates):
|
|
if (not halfway) 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]])
|
|
boss_gates.append(x + 1)
|
|
available_bosses.remove(available_bosses[0])
|
|
|
|
bosses: typing.Dict[int, int] = dict(zip(boss_gates, selected_bosses))
|
|
|
|
return bosses
|
|
|
|
|
|
def get_boss_rush_bosses(multiworld: MultiWorld, world: World):
|
|
|
|
if world.options.boss_rush_shuffle == 0:
|
|
boss_list_o = list(range(0, 16))
|
|
boss_list_s = [5, 2, 0, 10, 8, 4, 3, 1, 6, 13, 7, 11, 9, 15, 14, 12]
|
|
|
|
return dict(zip(boss_list_o, boss_list_s))
|
|
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)
|
|
|
|
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)]
|
|
if 10 not in boss_list_s:
|
|
boss_list_s[multiworld.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)
|
|
if 10 not in boss_list_s:
|
|
boss_list_s[multiworld.random.randint(0, 15)] = 10
|
|
|
|
return dict(zip(boss_list_o, boss_list_s))
|
|
else:
|
|
return dict()
|