 85d02b2dc5
			
		
	
	85d02b2dc5
	
	
	
		
			
			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()
 |