175 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			175 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								from BaseClasses import CollectionState
							 | 
						||
| 
								 | 
							
								from .region_base import JakAndDaxterRegion
							 | 
						||
| 
								 | 
							
								from ..options import EnableOrbsanity
							 | 
						||
| 
								 | 
							
								from typing import TYPE_CHECKING
							 | 
						||
| 
								 | 
							
								if TYPE_CHECKING:
							 | 
						||
| 
								 | 
							
								    from .. import JakAndDaxterWorld
							 | 
						||
| 
								 | 
							
								from ..rules import can_fight, can_reach_orbs_level
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def build_regions(level_name: str, world: "JakAndDaxterWorld") -> JakAndDaxterRegion:
							 | 
						||
| 
								 | 
							
								    multiworld = world.multiworld
							 | 
						||
| 
								 | 
							
								    options = world.options
							 | 
						||
| 
								 | 
							
								    player = world.player
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # This level is full of short-medium gaps that cannot be crossed by single jump alone.
							 | 
						||
| 
								 | 
							
								    # These helper functions list out the moves that can cross all these gaps (painting with a broad brush but...)
							 | 
						||
| 
								 | 
							
								    def can_jump_farther(state: CollectionState, p: int) -> bool:
							 | 
						||
| 
								 | 
							
								        return (state.has_any(("Double Jump", "Jump Kick"), p)
							 | 
						||
| 
								 | 
							
								                or state.has_all(("Punch", "Punch Uppercut"), p))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def can_jump_higher(state: CollectionState, p: int) -> bool:
							 | 
						||
| 
								 | 
							
								        return (state.has("Double Jump", p)
							 | 
						||
| 
								 | 
							
								                or state.has_all(("Crouch", "Crouch Jump"), p)
							 | 
						||
| 
								 | 
							
								                or state.has_all(("Crouch", "Crouch Uppercut"), p)
							 | 
						||
| 
								 | 
							
								                or state.has_all(("Punch", "Punch Uppercut"), p))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Orb crates and fly box in this area can be gotten with yellow eco and goggles.
							 | 
						||
| 
								 | 
							
								    # Start with the first yellow eco cluster near first_bats and work your way backward toward the entrance.
							 | 
						||
| 
								 | 
							
								    main_area = JakAndDaxterRegion("Main Area", player, multiworld, level_name, 23)
							 | 
						||
| 
								 | 
							
								    main_area.add_fly_locations([43])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Includes 4 orbs collectable with the blue eco vent.
							 | 
						||
| 
								 | 
							
								    first_bats = JakAndDaxterRegion("First Bats Area", player, multiworld, level_name, 4)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    first_jump_pad = JakAndDaxterRegion("First Jump Pad", player, multiworld, level_name, 0)
							 | 
						||
| 
								 | 
							
								    first_jump_pad.add_fly_locations([393259])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # The tethers in this level are all out of order... a casual playthrough has the following order for the cell ID's:
							 | 
						||
| 
								 | 
							
								    # 42, 39, 40, 41. So that is the order we're calling "first, second, third, fourth".
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # First tether cell is collectable with yellow eco and goggles.
							 | 
						||
| 
								 | 
							
								    first_tether = JakAndDaxterRegion("First Tether", player, multiworld, level_name, 7)
							 | 
						||
| 
								 | 
							
								    first_tether.add_cell_locations([42])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # This rat colony has 3 orbs on top of it, requires special movement.
							 | 
						||
| 
								 | 
							
								    first_tether_rat_colony = JakAndDaxterRegion("First Tether Rat Colony", player, multiworld, level_name, 3)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # If quick enough, combat not required.
							 | 
						||
| 
								 | 
							
								    second_jump_pad = JakAndDaxterRegion("Second Jump Pad", player, multiworld, level_name, 0)
							 | 
						||
| 
								 | 
							
								    second_jump_pad.add_fly_locations([65579])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    first_pole_course = JakAndDaxterRegion("First Pole Course", player, multiworld, level_name, 28)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # You can break this tether with a yellow eco vent and goggles,
							 | 
						||
| 
								 | 
							
								    # but you can't reach the platform unless you can jump high.
							 | 
						||
| 
								 | 
							
								    second_tether = JakAndDaxterRegion("Second Tether", player, multiworld, level_name, 0)
							 | 
						||
| 
								 | 
							
								    second_tether.add_cell_locations([39], access_rule=lambda state: can_jump_higher(state, player))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Fly and orbs are collectable with nearby blue eco cluster.
							 | 
						||
| 
								 | 
							
								    second_bats = JakAndDaxterRegion("Second Bats Area", player, multiworld, level_name, 27)
							 | 
						||
| 
								 | 
							
								    second_bats.add_fly_locations([262187], access_rule=lambda state: can_jump_farther(state, player))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    third_jump_pad = JakAndDaxterRegion("Third Jump Pad (Arena)", player, multiworld, level_name, 0)
							 | 
						||
| 
								 | 
							
								    third_jump_pad.add_cell_locations([38], access_rule=lambda state: can_fight(state, player))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # The platform for the third tether might look high, but you can get a boost from the yellow eco vent.
							 | 
						||
| 
								 | 
							
								    fourth_jump_pad = JakAndDaxterRegion("Fourth Jump Pad (Third Tether)", player, multiworld, level_name, 9)
							 | 
						||
| 
								 | 
							
								    fourth_jump_pad.add_cell_locations([40])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Orbs collectable here with yellow eco and goggles.
							 | 
						||
| 
								 | 
							
								    flut_flut_pad = JakAndDaxterRegion("Flut Flut Pad", player, multiworld, level_name, 36)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    flut_flut_course = JakAndDaxterRegion("Flut Flut Course", player, multiworld, level_name, 23)
							 | 
						||
| 
								 | 
							
								    flut_flut_course.add_cell_locations([37])
							 | 
						||
| 
								 | 
							
								    flut_flut_course.add_fly_locations([327723, 131115])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Includes some orbs on the way to the cabin, blue+yellow eco to collect.
							 | 
						||
| 
								 | 
							
								    farthy_snacks = JakAndDaxterRegion("Farthy's Snacks", player, multiworld, level_name, 7)
							 | 
						||
| 
								 | 
							
								    farthy_snacks.add_cell_locations([36])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Scout fly in this field can be broken with yellow eco.
							 | 
						||
| 
								 | 
							
								    box_field = JakAndDaxterRegion("Field of Boxes", player, multiworld, level_name, 10)
							 | 
						||
| 
								 | 
							
								    box_field.add_fly_locations([196651])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    last_tar_pit = JakAndDaxterRegion("Last Tar Pit", player, multiworld, level_name, 12)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    fourth_tether = JakAndDaxterRegion("Fourth Tether", player, multiworld, level_name, 11)
							 | 
						||
| 
								 | 
							
								    fourth_tether.add_cell_locations([41], access_rule=lambda state: can_jump_higher(state, player))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    main_area.connect(first_bats, rule=lambda state: can_jump_farther(state, player))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    first_bats.connect(main_area)
							 | 
						||
| 
								 | 
							
								    first_bats.connect(first_jump_pad)
							 | 
						||
| 
								 | 
							
								    first_bats.connect(first_tether)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    first_jump_pad.connect(first_bats)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    first_tether.connect(first_bats)
							 | 
						||
| 
								 | 
							
								    first_tether.connect(first_tether_rat_colony, rule=lambda state:
							 | 
						||
| 
								 | 
							
								                         (state.has_all(("Roll", "Roll Jump"), player)
							 | 
						||
| 
								 | 
							
								                          or state.has_all(("Double Jump", "Jump Kick"), player)))
							 | 
						||
| 
								 | 
							
								    first_tether.connect(second_jump_pad)
							 | 
						||
| 
								 | 
							
								    first_tether.connect(first_pole_course)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    first_tether_rat_colony.connect(first_tether)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    second_jump_pad.connect(first_tether)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    first_pole_course.connect(first_tether)
							 | 
						||
| 
								 | 
							
								    first_pole_course.connect(second_tether)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    second_tether.connect(first_pole_course, rule=lambda state: can_jump_higher(state, player))
							 | 
						||
| 
								 | 
							
								    second_tether.connect(second_bats)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    second_bats.connect(second_tether)
							 | 
						||
| 
								 | 
							
								    second_bats.connect(third_jump_pad)
							 | 
						||
| 
								 | 
							
								    second_bats.connect(fourth_jump_pad)
							 | 
						||
| 
								 | 
							
								    second_bats.connect(flut_flut_pad)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    third_jump_pad.connect(second_bats)
							 | 
						||
| 
								 | 
							
								    fourth_jump_pad.connect(second_bats)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    flut_flut_pad.connect(second_bats)
							 | 
						||
| 
								 | 
							
								    flut_flut_pad.connect(flut_flut_course, rule=lambda state: state.has("Flut Flut", player))  # Naturally.
							 | 
						||
| 
								 | 
							
								    flut_flut_pad.connect(farthy_snacks)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    flut_flut_course.connect(flut_flut_pad)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    farthy_snacks.connect(flut_flut_pad)
							 | 
						||
| 
								 | 
							
								    farthy_snacks.connect(box_field, rule=lambda state: can_jump_higher(state, player))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    box_field.connect(farthy_snacks, rule=lambda state: can_jump_higher(state, player))
							 | 
						||
| 
								 | 
							
								    box_field.connect(last_tar_pit, rule=lambda state: can_jump_farther(state, player))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    last_tar_pit.connect(box_field, rule=lambda state: can_jump_farther(state, player))
							 | 
						||
| 
								 | 
							
								    last_tar_pit.connect(fourth_tether, rule=lambda state: can_jump_farther(state, player))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    fourth_tether.connect(last_tar_pit, rule=lambda state: can_jump_farther(state, player))
							 | 
						||
| 
								 | 
							
								    fourth_tether.connect(main_area)  # Fall down.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(main_area)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(first_bats)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(first_jump_pad)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(first_tether)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(first_tether_rat_colony)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(second_jump_pad)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(first_pole_course)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(second_tether)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(second_bats)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(third_jump_pad)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(fourth_jump_pad)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(flut_flut_pad)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(flut_flut_course)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(farthy_snacks)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(box_field)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(last_tar_pit)
							 | 
						||
| 
								 | 
							
								    world.level_to_regions[level_name].append(fourth_tether)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # If Per-Level Orbsanity is enabled, build the special Orbsanity Region. This is a virtual region always
							 | 
						||
| 
								 | 
							
								    # accessible to Main Area. The Locations within are automatically checked when you collect enough orbs.
							 | 
						||
| 
								 | 
							
								    if options.enable_orbsanity == EnableOrbsanity.option_per_level:
							 | 
						||
| 
								 | 
							
								        orbs = JakAndDaxterRegion("Orbsanity", player, multiworld, level_name)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        bundle_count = 200 // world.orb_bundle_size
							 | 
						||
| 
								 | 
							
								        for bundle_index in range(bundle_count):
							 | 
						||
| 
								 | 
							
								            amount = world.orb_bundle_size * (bundle_index + 1)
							 | 
						||
| 
								 | 
							
								            orbs.add_orb_locations(8,
							 | 
						||
| 
								 | 
							
								                                   bundle_index,
							 | 
						||
| 
								 | 
							
								                                   access_rule=lambda state, level=level_name, orb_amount=amount:
							 | 
						||
| 
								 | 
							
								                                   can_reach_orbs_level(state, player, world, level, orb_amount))
							 | 
						||
| 
								 | 
							
								        multiworld.regions.append(orbs)
							 | 
						||
| 
								 | 
							
								        main_area.connect(orbs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return main_area
							 |