diff --git a/Container.py b/Container.py index 176fe04..83ac40a 100644 --- a/Container.py +++ b/Container.py @@ -303,10 +303,9 @@ def generate_patch(world: "Rac2World", patch: Rac2ProcedurePatch, instruction=No # Set arg0 to 0x18 for ship shack patch.write_token(APTokenTypes.WRITE, address + 0x24, bytes([0x18, 0x00, 0x04, 0x24])) - # Allow first-person mode outside of NG+ if requested in options - if world.options.allow_first_person_mode: - for address in addresses.SPECIAL_MENU_FUNCS: - patch.write_token(APTokenTypes.WRITE, address + 0x1B0, NOP * 2) + # Allow first-person mode outside of NG+ + for address in addresses.SPECIAL_MENU_FUNCS: + patch.write_token(APTokenTypes.WRITE, address + 0x1B0, NOP * 2) # Enable bolt multiplier outside of NG+ if requested in options if world.options.enable_bolt_multiplier: diff --git a/Logic.py b/Logic.py index 1b88745..22a4531 100644 --- a/Logic.py +++ b/Logic.py @@ -1,5 +1,6 @@ from BaseClasses import CollectionState from .data import Items +from .Rac2Options import Rac2Options def can_dynamo(state: CollectionState, player: int) -> bool: @@ -71,3 +72,706 @@ def has_qwark_statuette(state: CollectionState, player: int) -> bool: def has_hypnomatic_parts(state: CollectionState, player: int) -> bool: return state.has(Items.HYPNOMATIC_PART.name, player, 3) + + +FIRST_PERSON_EASY = 1 +FIRST_PERSON_MEDIUM = 2 +FIRST_PERSON_HARD = 3 + + +def get_options(state: CollectionState, player: int) -> Rac2Options: + return state.multiworld.worlds[player].options + + +def oozla_end_store_cutscene_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return can_dynamo(state, player) + + +def oozla_tractor_puzzle_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return can_tractor(state, player) + + +def oozla_swamp_ruins_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return can_dynamo(state, player) + + +def oozla_swamp_monster_ii_rule(state: CollectionState, player: int) -> bool: + return (can_dynamo(state, player) + and can_gravity(state, player)) + + +def maktar_photo_booth_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return (can_electrolyze(state, player) + or can_heli(state, player)) + + return can_electrolyze(state, player) + + +def maktar_deactivate_jamming_array_rule(state: CollectionState, player: int) -> bool: + return can_tractor(state, player) + + +def maktar_jamming_array_pb_rule(state: CollectionState, player: int) -> bool: + return can_tractor(state, player) + + +def endako_rescue_clank_rule(state: CollectionState, player: int) -> bool: + return can_electrolyze(state, player) + + +def endako_crane_pb_rule(state: CollectionState, player: int) -> bool: + return can_electrolyze(state, player) + + +def endako_crane_nt_rule(state: CollectionState, player: int) -> bool: + return (can_electrolyze(state, player) + and can_infiltrate(state, player)) + + +def barlow_inventor_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return can_swingshot(state, player) + + +def barlow_overbike_race_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return can_electrolyze(state, player) + + return (can_improved_jump(state, player) + and can_electrolyze(state, player)) + + +def barlow_hound_cave_pb_rule(state: CollectionState, player: int) -> bool: + return can_swingshot(state, player) + + +def notak_top_pier_telescreen_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return (can_improved_jump(state, player) + and can_thermanate(state, player)) + + +def notak_worker_bots_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return (can_heli(state, player) + and can_thermanate(state, player)) + + +def notak_timed_dynamo_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return (can_dynamo(state, player) + and can_thermanate(state, player) + and can_improved_jump(state, player)) + + +def siberius_defeat_thief_rule(state: CollectionState, player: int) -> bool: + return can_swingshot(state, player) + + +def siberius_flamebot_ledge_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return can_tractor(state, player) + + +def siberius_fenced_area_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return can_heli(state, player) + + +def tabora_meet_angelar_rule(state: CollectionState, player: int) -> bool: + return (can_heli(state, player) + and can_swingshot(state, player)) + + +def tabora_underground_mines_end_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return (can_heli(state, player) + and can_swingshot(state, player)) + + return (can_heli(state, player) + and can_swingshot(state, player) + and can_thermanate(state, player)) + + +def tabora_canyon_glide_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return (can_heli(state, player) + and can_swingshot(state, player) + and can_glide(state, player)) + + return (can_heli(state, player) + and can_swingshot(state, player) + and can_thermanate(state, player) + and can_glide(state, player)) + + +def tabora_northeast_desert_pb_rule(state: CollectionState, player: int) -> bool: + return (can_heli(state, player) + and can_swingshot(state, player)) + + +def tabora_canyon_glide_pillar_nt_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return (can_heli(state, player) + and can_swingshot(state, player) + and can_glide(state, player)) + + return (can_heli(state, player) + and can_swingshot(state, player) + and can_thermanate(state, player) + and can_glide(state, player)) + + +def dobbo_defeat_thug_leader_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return can_swingshot(state, player) + + return (can_swingshot(state, player) + and can_improved_jump(state, player) + and can_dynamo(state, player)) + + +def dobbo_facility_terminal_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return (can_swingshot(state, player) + and can_glide(state, player) + and can_dynamo(state, player) + and can_electrolyze(state, player)) + + +def dobbo_spiderbot_room_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return can_swingshot(state, player) + + return (can_swingshot(state, player) + and can_dynamo(state, player)) + + +def dobbo_facility_glide_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return (can_swingshot(state, player) + and can_glide(state, player) + and can_dynamo(state, player)) + + +def dobbo_facility_glide_nt_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return (can_swingshot(state, player) + and can_glide(state, player) + and can_dynamo(state, player)) + + +def joba_hoverbike_race_rule(state: CollectionState, player: int) -> bool: + return can_swingshot(state, player) + + +def joba_shady_salesman_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return (can_dynamo(state, player) + and can_improved_jump(state, player)) + + +def joba_arena_battle_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return can_levitate(state, player) + + return (can_dynamo(state, player) + and can_improved_jump(state, player) + and can_levitate(state, player)) + + +def joba_arena_cage_match_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return can_levitate(state, player) + + return (can_dynamo(state, player) + and can_improved_jump(state, player) + and can_levitate(state, player)) + + +def joba_hidden_cliff_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return (can_dynamo(state, player) + and can_swingshot(state, player)) + + +def joba_levitator_tower_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return can_levitate(state, player) + + return (can_dynamo(state, player) + and can_improved_jump(state, player) + and can_levitate(state, player)) + + +def joba_timed_dynamo_nt_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return can_dynamo(state, player) + + +def todano_search_rocket_silo_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return (can_electrolyze(state, player) + and can_improved_jump(state, player) + and can_infiltrate(state, player)) + + +def todano_stuart_zurgo_trade_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_HARD: + return has_qwark_statuette(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return (can_tractor(state, player) + and has_qwark_statuette(state, player)) + + return (can_electrolyze(state, player) + and can_tractor(state, player) + and has_qwark_statuette(state, player)) + + +def todano_facility_interior_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_HARD: + return True + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return can_tractor(state, player) + + return (can_electrolyze(state, player) + and can_tractor(state, player)) + + +def todano_near_stuart_zurgo_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_HARD: + return True + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return can_tractor(state, player) + + return (can_electrolyze(state, player) + and can_tractor(state, player)) + + +def todano_spiderbot_conveyor_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return (can_tractor(state, player) + and can_improved_jump(state, player) + and can_spiderbot(state, player)) + + return (can_electrolyze(state, player) + and can_tractor(state, player) + and can_improved_jump(state, player) + and can_spiderbot(state, player)) + + +def todano_rocket_silo_nt_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return (can_electrolyze(state, player) + and can_infiltrate(state, player)) + + +def boldan_find_fizzwidget_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_HARD: + return True + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return (can_gravity(state, player) + and can_improved_jump(state, player)) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return (can_swingshot(state, player) + and can_gravity(state, player)) + + return (can_levitate(state, player) + and can_swingshot(state, player) + and can_gravity(state, player)) + + +def boldan_spiderbot_alley_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return (can_levitate(state, player) + and can_spiderbot(state, player)) + + +def boldan_floating_platform_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return can_gravity(state, player) + + return (can_levitate(state, player) + and can_gravity(state, player)) + + +def boldan_fountain_nt_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return can_levitate(state, player) + + +def aranos_control_room_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_HARD: + return True + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return (can_infiltrate(state, player) + and can_levitate(state, player)) + + return (can_gravity(state, player) + and can_infiltrate(state, player) + and can_levitate(state, player)) + + +def aranos_plumber_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return (can_gravity(state, player) + and can_levitate(state, player)) + + +def aranos_under_ship_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return can_heli(state, player) + + return (can_gravity(state, player) + and can_heli(state, player)) + + +def aranos_omniwrench_12000_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return True + + return can_gravity(state, player) + + +def snivelak_rescue_angelak_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >+ FIRST_PERSON_EASY: + return can_swingshot(state, player) + + return (can_swingshot(state, player) + and can_grind(state, player) + and can_gravity(state, player) + and can_dynamo(state, player)) + + +def snivelak_dynamo_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return can_swingshot(state, player) + + return (can_swingshot(state, player) + and can_grind(state, player) + and can_gravity(state, player) + and can_dynamo(state, player) + and can_heli(state, player)) + + +def snivelak_swingshot_tower_nt_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return can_swingshot(state, player) + + return (can_swingshot(state, player) + and can_heli(state, player)) + + +def smolg_balloon_transmission_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return can_electrolyze(state, player) + + return (can_improved_jump(state, player) + and can_dynamo(state, player) + and can_electrolyze(state, player)) + + +def smolg_distribution_facility_end_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return can_electrolyze(state, player) + + return (can_improved_jump(state, player) + and can_dynamo(state, player) + and can_electrolyze(state, player) + and can_grind(state, player) + and can_infiltrate(state, player)) + + +def smolg_mutant_crab_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + if not can_levitate(state, player): + return False + return (can_swingshot(state, player) + or can_electrolyze(state, player)) + + return (can_swingshot(state, player) + and can_levitate(state, player)) + + +def smolg_floating_platform_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + if not can_levitate(state, player): + return False + return (can_swingshot(state, player) + or can_electrolyze(state, player)) + + return (can_swingshot(state, player) + and can_levitate(state, player)) + + +def smolg_warehouse_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return (can_dynamo(state, player) + or can_improved_jump(state, player)) + + +def damosel_hypnotist_rule(state: CollectionState, player: int) -> bool: + return (can_swingshot(state, player) + and can_improved_jump(state, player) + and can_thermanate(state, player) + and has_hypnomatic_parts(state, player)) + + +def damosel_train_rails_rule(state: CollectionState, player: int) -> bool: + return can_grind(state, player) + + +def damosel_frozen_mountain_pb_rule(state: CollectionState, player: int) -> bool: + return (can_swingshot(state, player) + and can_improved_jump(state, player) + and can_thermanate(state, player) + and can_grind(state, player)) + + +def damosel_pyramid_pb_rule(state: CollectionState, player: int) -> bool: + return (can_swingshot(state, player) + and can_improved_jump(state, player) + and can_hypnotize(state, player)) + + +def grelbin_find_angela_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return can_hypnotize(state, player) + + +def grelbin_mystic_more_moonstones_rule(state: CollectionState, player: int) -> bool: + return (can_glide(state, player) + and can_infiltrate(state, player)) + + +def grelbin_ice_plains_pb_rule(state: CollectionState, player: int) -> bool: + return (can_glide(state, player) + and can_infiltrate(state, player)) + + +def grelbin_underwater_tunnel_pb_rule(state: CollectionState, player: int) -> bool: + return can_hypnotize(state, player) + + +def grelbin_yeti_cave_pb_rule(state: CollectionState, player: int) -> bool: + return (can_glide(state, player) + and can_infiltrate(state, player) + and can_hypnotize(state, player)) + + +def yeedil_defeat_mutated_protopet_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_HARD: + return can_infiltrate(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return (can_hypnotize(state, player) + and can_swingshot(state, player) + and can_infiltrate(state, player)) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return (can_hypnotize(state, player) + and can_swingshot(state, player) + and can_infiltrate(state, player) + and can_dynamo(state, player) + and can_improved_jump(state, player)) + + return (can_hypnotize(state, player) + and can_swingshot(state, player) + and can_infiltrate(state, player) + and can_dynamo(state, player) + and can_improved_jump(state, player) + and can_electrolyze(state, player)) + + +def yeedil_bridge_grindrail_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return True + + return can_grind(state, player) + + +def yeedil_tractor_pillar_pb_rule(state: CollectionState, player: int) -> bool: + options = get_options(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_HARD: + return can_infiltrate(state, player) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_MEDIUM: + return (can_hypnotize(state, player) + and can_swingshot(state, player) + and can_infiltrate(state, player)) + + if options.first_person_mode_glitch_in_logic >= FIRST_PERSON_EASY: + return (can_hypnotize(state, player) + and can_swingshot(state, player) + and can_infiltrate(state, player) + and can_dynamo(state, player) + and can_improved_jump(state, player) + and can_tractor(state, player) + and can_grind(state, player)) + + return (can_hypnotize(state, player) + and can_swingshot(state, player) + and can_infiltrate(state, player) + and can_dynamo(state, player) + and can_improved_jump(state, player) + and can_electrolyze(state, player) + and can_tractor(state, player) + and can_grind(state, player)) \ No newline at end of file diff --git a/Rac2Options.py b/Rac2Options.py index fa8cba8..ea21e4b 100644 --- a/Rac2Options.py +++ b/Rac2Options.py @@ -47,11 +47,6 @@ class SkipWupashNebula(DefaultOnToggle): display_name = "Skip Wupash Nebula" -class AllowFirstPersonMode(DefaultOnToggle): - """Gives access to first person mode in 'Special' menu without being in New Game+.""" - display_name = "Allow First Person Mode" - - class EnableBoltMultiplier(Toggle): """Enables the bolt multiplier feature without being in New Game+.""" display_name = "Enable Bolt Multiplier" @@ -108,6 +103,20 @@ class ExtendWeaponProgression(Toggle): display_name = "Extended Weapon Progression" +class FirstPersonModeGlitchInLogic(Choice): + """Determines if logic should take first person mode glitches into account when evaluating which locations are + reachable. Various difficulty levels can be picked: + - Easy: simple climbs (e.g. getting the Platinum Bolt near Oozla scientist) + - Medium: harder climbs and basic lateral movement (e.g. Getting to the Notak Worker Bots without the Heli-pack nor the Thermanator) + - Hard: full navigation following walls (e.g. Getting to the Mutated Protopet only with the Infiltrator)""" + display_name = "First Person Mode Glitch In Logic" + option_disabled = 0 + option_easy = 1 + option_medium = 2 + option_hard = 3 + default = 0 + + @dataclass class Rac2Options(PerGameCommonOptions): start_inventory_from_pool: StartInventoryPool @@ -117,7 +126,6 @@ class Rac2Options(PerGameCommonOptions): randomize_gadgetron_vendor: RandomizeGadgetronVendor exclude_very_expensive_items: ExcludeVeryExpensiveItems skip_wupash_nebula: SkipWupashNebula - allow_first_person_mode: AllowFirstPersonMode enable_bolt_multiplier: EnableBoltMultiplier no_revisit_reward_change: NoRevisitRewardChange no_kill_reward_degradation: NoKillRewardDegradation @@ -126,3 +134,4 @@ class Rac2Options(PerGameCommonOptions): weapon_xp_multiplier: WeaponExperienceMultiplier extra_spaceship_challenge_locations: ExtraSpaceshipChallengeLocations extend_weapon_progression: ExtendWeaponProgression + first_person_mode_glitch_in_logic: FirstPersonModeGlitchInLogic diff --git a/Simplified Ratchet & Clank 2.yaml b/Simplified Ratchet & Clank 2.yaml index 991fa9a..e9e2149 100644 --- a/Simplified Ratchet & Clank 2.yaml +++ b/Simplified Ratchet & Clank 2.yaml @@ -61,9 +61,6 @@ Ratchet & Clank 2: # Skips the Wupash Nebula ship section that appears when first traveling to Maktar Nebula. skip_wupash_nebula: true - # Gives access to first person mode in 'Special' menu without being in New Game+. - allow_first_person_mode: true - # Enables the bolt multiplier feature without being in New Game+. enable_bolt_multiplier: false @@ -104,6 +101,14 @@ Ratchet & Clank 2: # This effectively makes all weapons that are usually restricted to NG+ available with enough grinding. extend_weapon_progression: false + # Determines if logic should take first person mode glitches into account when evaluating which locations are reachable. + # Various difficulty levels can be picked: + # - Easy: simple climbs (e.g. getting the Platinum Bolt near Oozla scientist) + # - Medium: harder climbs and basic lateral movement (e.g. Getting to the Notak Worker Bots without the Heli-pack nor the Thermanator) + # - Hard: full navigation following walls (e.g. Getting to the Mutated Protopet only with the Infiltrator) + # Can be disabled with value disabled. + first_person_mode_glitch_in_logic: no + # Item & Location Options local_items: # Forces these items to be in their native world. diff --git a/__init__.py b/__init__.py index 6767ea2..51a2362 100644 --- a/__init__.py +++ b/__init__.py @@ -147,4 +147,4 @@ def get_options_as_dict(self) -> Dict[str, Any]: ) def fill_slot_data(self) -> Mapping[str, Any]: - return self.get_options_as_dict() + return self.get_options_as_dict() \ No newline at end of file diff --git a/data/Locations.py b/data/Locations.py index f541441..2d64628 100644 --- a/data/Locations.py +++ b/data/Locations.py @@ -16,45 +16,33 @@ class LocationData(NamedTuple): """ Oozla """ OOZLA_OUTSIDE_MEGACORP_STORE = LocationData(10, "Oozla: Outside Megacorp Store - Dynamo") -OOZLA_END_STORE_CUTSCENE = LocationData(11, "Oozla: End of Store Cutscene", can_dynamo) +OOZLA_END_STORE_CUTSCENE = LocationData(11, "Oozla: End of Store Cutscene", oozla_end_store_cutscene_rule) OOZLA_MEGACORP_SCIENTIST = LocationData(12, "Oozla: Megacorp Scientist - Tractor Beam") -OOZLA_TRACTOR_PUZZLE_PB = LocationData(13, "Oozla: Tractor Puzzle - Platinum Bolt", can_tractor) -OOZLA_SWAMP_RUINS_PB = LocationData(14, "Oozla: Swamp Ruins - Platinum Bolt", can_dynamo) -OOZLA_SWAMP_MONSTER_II = LocationData( - 15, "Oozla: Swamp Monster II - Box Breaker", - lambda state, player: can_dynamo(state, player) and can_gravity(state, player) -) +OOZLA_TRACTOR_PUZZLE_PB = LocationData(13, "Oozla: Tractor Puzzle - Platinum Bolt", oozla_tractor_puzzle_pb_rule) +OOZLA_SWAMP_RUINS_PB = LocationData(14, "Oozla: Swamp Ruins - Platinum Bolt", oozla_swamp_ruins_pb_rule) +OOZLA_SWAMP_MONSTER_II = LocationData(15, "Oozla: Swamp Monster II - Box Breaker",oozla_swamp_monster_ii_rule) """ Maktar """ MAKTAR_ARENA_CHALLENGE = LocationData(20, "Maktar: Arena Challenge - Electrolyzer") -MAKTAR_PHOTO_BOOTH = LocationData(21, "Maktar: Photo Booth", can_electrolyze) -MAKTAR_DEACTIVATE_JAMMING_ARRAY = LocationData(22, "Maktar: Deactivate Jamming Array", can_tractor) -MAKTAR_JAMMING_ARRAY_PB = LocationData(23, "Maktar: Jamming Array - Platinum Bolt", can_tractor) +MAKTAR_PHOTO_BOOTH = LocationData(21, "Maktar: Photo Booth", maktar_photo_booth_rule) +MAKTAR_DEACTIVATE_JAMMING_ARRAY = LocationData(22, "Maktar: Deactivate Jamming Array", maktar_deactivate_jamming_array_rule) +MAKTAR_JAMMING_ARRAY_PB = LocationData(23, "Maktar: Jamming Array - Platinum Bolt", maktar_jamming_array_pb_rule) MAKTAR_CRANE_PB = LocationData(24, "Maktar: Crane - Platinum Bolt") """ Endako """ ENDAKO_CLANK_APARTMENT_SS = LocationData(30, "Endako: Clank's Apartment - Swingshot") ENDAKO_CLANK_APARTMENT_GB = LocationData(31, "Endako: Clank's Apartment - Grindboots") -ENDAKO_RESCUE_CLANK_HELI = LocationData(32, "Endako: Rescue Clank Heli-Pack", can_electrolyze) -ENDAKO_RESCUE_CLANK_THRUSTER = LocationData(33, "Endako: Rescue Clank Thruster-Pack", can_electrolyze) -ENDAKO_LEDGE_PB = LocationData(34, "Endako: Ledge - Platinum Bolt", ) -ENDAKO_CRANE_PB = LocationData(35, "Endako: Crane - Platinum Bolt", can_electrolyze) -ENDAKO_CRANE_NT = LocationData( - 36, "Endako: Crane - Nanotech Boost", - lambda state, player: can_electrolyze(state, player) and can_infiltrate(state, player) -) +ENDAKO_RESCUE_CLANK_HELI = LocationData(32, "Endako: Rescue Clank Heli-Pack", endako_rescue_clank_rule) +ENDAKO_RESCUE_CLANK_THRUSTER = LocationData(33, "Endako: Rescue Clank Thruster-Pack", endako_rescue_clank_rule) +ENDAKO_LEDGE_PB = LocationData(34, "Endako: Ledge - Platinum Bolt") +ENDAKO_CRANE_PB = LocationData(35, "Endako: Crane - Platinum Bolt", endako_crane_pb_rule) +ENDAKO_CRANE_NT = LocationData(36, "Endako: Crane - Nanotech Boost", endako_crane_nt_rule) """ Barlow """ -BARLOW_INVENTOR = LocationData(40, "Barlow: Inventor - Thermanator", can_swingshot) -BARLOW_HOVERBIKE_RACE_TRANSMISSION = LocationData( - 41, "Barlow: Hoverbike Race Transmission", - lambda state, player: can_improved_jump(state, player) and can_electrolyze(state, player) -) -BARLOW_HOVERBIKE_RACE_PB = LocationData( - 42, "Barlow: Hoverbike Race - Platinum Bolt", - lambda state, player: can_improved_jump(state, player) and can_electrolyze(state, player) -) -BARLOW_HOUND_CAVE_PB = LocationData(43, "Barlow: Hound Cave - Platinum Bolt", can_swingshot) +BARLOW_INVENTOR = LocationData(40, "Barlow: Inventor - Thermanator", barlow_inventor_rule) +BARLOW_HOVERBIKE_RACE_TRANSMISSION = LocationData(41, "Barlow: Hoverbike Race Transmission", barlow_overbike_race_rule) +BARLOW_HOVERBIKE_RACE_PB = LocationData(42, "Barlow: Hoverbike Race - Platinum Bolt", barlow_overbike_race_rule) +BARLOW_HOUND_CAVE_PB = LocationData(43, "Barlow: Hound Cave - Platinum Bolt", barlow_hound_cave_pb_rule) """ Feltzin System """ FELTZIN_DEFEAT_THUG_SHIPS = LocationData(50, "Feltzin: Defeat Thug Ships") @@ -77,80 +65,36 @@ class LocationData(NamedTuple): ) """ Notak """ -NOTAK_TOP_PIER_TELESCREEN = LocationData( - 60, "Notak: Top of Pier Telescreen", - lambda state, player: can_improved_jump(state, player) and can_thermanate(state, player) -) -NOTAK_WORKER_BOTS = LocationData( - 61, "Notak: Worker Bots", - lambda state, player: can_heli(state, player) and can_thermanate(state, player) -) +NOTAK_TOP_PIER_TELESCREEN = LocationData(60, "Notak: Top of Pier Telescreen", notak_top_pier_telescreen_rule) +NOTAK_WORKER_BOTS = LocationData(61, "Notak: Worker Bots", notak_worker_bots_rule) NOTAK_BEHIND_BUILDING_PB = LocationData(62, "Notak: Behind Building - Platinum Bolt") NOTAK_PROMENADE_SIGN_PB = LocationData(63, "Notak: Promenade Sign - Platinum Bolt") -NOTAK_TIMED_DYNAMO_PB = LocationData( - 64, "Notak: Timed Dynamo - Platinum Bolt", - lambda state, player: - can_improved_jump(state, player) - and can_thermanate(state, player) - and can_dynamo(state, player) -) +NOTAK_TIMED_DYNAMO_PB = LocationData(64, "Notak: Timed Dynamo - Platinum Bolt", notak_timed_dynamo_rule) NOTAK_PROMENADE_END_NT = LocationData(65, "Notak: Promenade End - Nanotech Boost") """ Siberius """ -SIBERIUS_DEFEAT_THIEF = LocationData(70, "Siberius: Defeat Thief", can_swingshot) -SIBERIUS_FLAMEBOT_LEDGE_PB = LocationData(71, "Siberius: Flamebot Ledge - Platinum Bolt", can_tractor) -SIBERIUS_FENCED_AREA_PB = LocationData(72, "Siberius: Fenced Area - Platinum Bolt", can_heli) +SIBERIUS_DEFEAT_THIEF = LocationData(70, "Siberius: Defeat Thief", siberius_defeat_thief_rule) +SIBERIUS_FLAMEBOT_LEDGE_PB = LocationData(71, "Siberius: Flamebot Ledge - Platinum Bolt", siberius_flamebot_ledge_pb_rule) +SIBERIUS_FENCED_AREA_PB = LocationData(72, "Siberius: Fenced Area - Platinum Bolt", siberius_fenced_area_pb_rule) """ Tabora """ -# NOTICE: Heli-Pack and Swingshot are already logically required in order to access this planet -TABORA_MEET_ANGELA = LocationData(80, "Tabora: Meet Angela") -TABORA_UNDERGROUND_MINES_END = LocationData(81, "Tabora: Underground Mines - Glider", can_thermanate) -TABORA_UNDERGROUND_MINES_PB = LocationData(82, "Tabora: Underground Mines - Platinum Bolt", can_thermanate) -TABORA_CANYON_GLIDE_PB = LocationData( - 83, "Tabora: Canyon Glide - Platinum Bolt", - lambda state, player: can_thermanate(state, player) and can_glide(state, player) -) -TABORA_NORTHEAST_DESERT_PB = LocationData(84, "Tabora: Northeast Desert - Platinum Bolt") -TABORA_CANYON_GLIDE_PILLAR_NT = LocationData( - 85, "Tabora: Canyon Glide Pillar - Nanotech Boost", - lambda state, player: can_thermanate(state, player) and can_glide(state, player) -) +TABORA_MEET_ANGELA = LocationData(80, "Tabora: Meet Angela", tabora_meet_angelar_rule) +TABORA_UNDERGROUND_MINES_END = LocationData(81, "Tabora: Underground Mines - Glider", tabora_underground_mines_end_rule) +TABORA_UNDERGROUND_MINES_PB = LocationData(82, "Tabora: Underground Mines - Platinum Bolt", tabora_underground_mines_end_rule) +TABORA_CANYON_GLIDE_PB = LocationData(83, "Tabora: Canyon Glide - Platinum Bolt", tabora_canyon_glide_pb_rule) +TABORA_NORTHEAST_DESERT_PB = LocationData(84, "Tabora: Northeast Desert - Platinum Bolt", tabora_northeast_desert_pb_rule) +TABORA_CANYON_GLIDE_PILLAR_NT = LocationData(85, "Tabora: Canyon Glide Pillar - Nanotech Boost", tabora_canyon_glide_pillar_nt_rule) TABORA_OMNIWRENCH_10000 = LocationData( 86, "Tabora: OmniWrench 10000", checked_flag_address=lambda ram: ram.tabora_wrench_cutscene_flag ) """ Dobbo """ -DOBBO_DEFEAT_THUG_LEADER = LocationData( - 90, "Dobbo: Defeat Thug Leader", - lambda state, player: - can_improved_jump(state, player) - and can_dynamo(state, player) - and can_swingshot(state, player) -) -DOBBO_FACILITY_TERMINAL = LocationData( - 91, "Dobbo: Facility Terminal", - lambda state, player: - can_dynamo(state, player) - and can_swingshot(state, player) - and can_glide(state, player) - and can_electrolyze(state, player) -) -DOBBO_SPIDERBOT_ROOM_PB = LocationData( - 92, "Dobbo: Spiderbot Room - Platinum Bolt", - lambda state, player: - can_dynamo(state, player) - and can_swingshot(state, player) - and can_spiderbot(state, player) -) -DOBBO_FACILITY_GLIDE_PB = LocationData( - 93, "Dobbo: Facility Glide End - Platinum Bolt", - lambda state, player: can_dynamo(state, player) and can_swingshot(state, player) and can_glide(state, player) -) -DOBBO_FACILITY_GLIDE_NT = LocationData( - 94, "Dobbo: Facility Glide Beginning - Nanotech Boost", - lambda state, player: can_dynamo(state, player) and can_swingshot(state, player) and can_glide(state, player) -) +DOBBO_DEFEAT_THUG_LEADER = LocationData(90, "Dobbo: Defeat Thug Leader", dobbo_defeat_thug_leader_rule) +DOBBO_FACILITY_TERMINAL = LocationData(91, "Dobbo: Facility Terminal", dobbo_facility_terminal_rule) +DOBBO_SPIDERBOT_ROOM_PB = LocationData(92, "Dobbo: Spiderbot Room - Platinum Bolt", dobbo_spiderbot_room_pb_rule) +DOBBO_FACILITY_GLIDE_PB = LocationData(93, "Dobbo: Facility Glide End - Platinum Bolt", dobbo_facility_glide_pb_rule) +DOBBO_FACILITY_GLIDE_NT = LocationData(94, "Dobbo: Facility Glide Beginning - Nanotech Boost", dobbo_facility_glide_nt_rule) """ Hrugis """ HRUGIS_DESTROY_DEFENSES = LocationData(100, "Hrugis Cloud: Destroy Defenses") @@ -172,108 +116,36 @@ class LocationData(NamedTuple): ) """ Joba """ -JOBA_FIRST_HOVERBIKE_RACE = LocationData(110, "Joba: First Hoverbike Race - Charge Boots", can_swingshot) -JOBA_SHADY_SALESMAN = LocationData( - 111, "Joba: Shady Salesman - Levitator", - lambda state, player: can_dynamo(state, player) and can_improved_jump(state, player) -) -JOBA_ARENA_BATTLE = LocationData( - 112, "Joba: Arena Battle - Gravity Boots", - lambda state, player: - can_dynamo(state, player) - and can_improved_jump(state, player) - and can_levitate(state, player) -) -JOBA_ARENA_CAGE_MATCH = LocationData( - 113, "Joba: Arena Cage Match - Infiltrator", - lambda state, player: - can_dynamo(state, player) - and can_improved_jump(state, player) - and can_levitate(state, player) -) -JOBA_HIDDEN_CLIFF_PB = LocationData( - 114, "Joba: Hidden Cliff - Platinum Bolt", - lambda state, player: can_dynamo(state, player) and can_swingshot(state, player) -) -JOBA_LEVITATOR_TOWER_PB = LocationData( - 115, "Joba: Levitator Tower - Platinum Bolt", - lambda state, player: - can_dynamo(state, player) - and can_improved_jump(state, player) - and can_levitate(state, player) -) -JOBA_HOVERBIKE_RACE_SHORTCUT_NT = LocationData(116, "Joba: Hoverbike Race Shortcut - Nanotech Boost", can_swingshot) -JOBA_TIMED_DYNAMO_NT = LocationData(117, "Joba: Timed Dynamo Course - Nanotech Boost", can_dynamo) +JOBA_FIRST_HOVERBIKE_RACE = LocationData(110, "Joba: First Hoverbike Race - Charge Boots", joba_hoverbike_race_rule) +JOBA_SHADY_SALESMAN = LocationData(111, "Joba: Shady Salesman - Levitator", joba_shady_salesman_rule) +JOBA_ARENA_BATTLE = LocationData(112, "Joba: Arena Battle - Gravity Boots", joba_arena_battle_rule) +JOBA_ARENA_CAGE_MATCH = LocationData(113, "Joba: Arena Cage Match - Infiltrator", joba_arena_cage_match_rule) +JOBA_HIDDEN_CLIFF_PB = LocationData(114, "Joba: Hidden Cliff - Platinum Bolt", joba_hidden_cliff_pb_rule) +JOBA_LEVITATOR_TOWER_PB = LocationData(115, "Joba: Levitator Tower - Platinum Bolt", joba_levitator_tower_pb_rule) +JOBA_HOVERBIKE_RACE_SHORTCUT_NT = LocationData(116, "Joba: Hoverbike Race Shortcut - Nanotech Boost", joba_hoverbike_race_rule) +JOBA_TIMED_DYNAMO_NT = LocationData(117, "Joba: Timed Dynamo Course - Nanotech Boost", joba_timed_dynamo_nt_rule) """ Todano """ -TODANO_SEARCH_ROCKET_SILO = LocationData( - 120, "Todano: Search Rocket Silo", - lambda state, player: - can_improved_jump(state, player) - and can_electrolyze(state, player) - and can_infiltrate(state, player) -) -TODANO_STUART_ZURGO_TRADE = LocationData( - 121, "Todano: Stuart Zurgo Trade - Armor Magnetizer", - lambda state, player: - can_electrolyze(state, player) - and can_tractor(state, player) - and has_qwark_statuette(state, player) -) -TODANO_FACILITY_INTERIOR = LocationData( - 122, "Todano: Facility Interior - Sheepinator", - lambda state, player: can_electrolyze(state, player) and can_tractor(state, player) -) -TODANO_NEAR_STUART_ZURGO_PB = LocationData( - 123, "Todano: Near Stuart Zurgo - Platinum Bolt", - lambda state, player: can_electrolyze(state, player) and can_tractor(state, player) -) +TODANO_SEARCH_ROCKET_SILO = LocationData(120, "Todano: Search Rocket Silo", todano_search_rocket_silo_rule) +TODANO_STUART_ZURGO_TRADE = LocationData(121, "Todano: Stuart Zurgo Trade - Armor Magnetizer", todano_stuart_zurgo_trade_rule) +TODANO_FACILITY_INTERIOR = LocationData(122, "Todano: Facility Interior - Sheepinator", todano_facility_interior_rule) +TODANO_NEAR_STUART_ZURGO_PB = LocationData(123, "Todano: Near Stuart Zurgo - Platinum Bolt", todano_near_stuart_zurgo_pb_rule) TODANO_END_TOUR_PB = LocationData(124, "Todano: End of Tour - Platinum Bolt") -TODANO_SPIDERBOT_CONVEYOR_PB = LocationData( - 125, "Todano: Spiderbot Conveyor - Platinum Bolt", - lambda state, player: - can_electrolyze(state, player) - and can_tractor(state, player) - and can_improved_jump(state, player) - and can_spiderbot(state, player) -) -TODANO_ROCKET_SILO_NT = LocationData( - 126, "Todano: Rocket Silo - Nanotech Boost", - lambda state, player: can_electrolyze(state, player) and can_infiltrate(state, player) -) +TODANO_SPIDERBOT_CONVEYOR_PB = LocationData(125, "Todano: Spiderbot Conveyor - Platinum Bolt", todano_spiderbot_conveyor_pb_rule) +TODANO_ROCKET_SILO_NT = LocationData(126, "Todano: Rocket Silo - Nanotech Boost", todano_rocket_silo_nt_rule) """ Boldan """ -BOLDAN_FIND_FIZZWIDGET = LocationData( - 130, "Boldan: Find Fizzwidget", - lambda state, player: - can_levitate(state, player) - and can_gravity(state, player) - and can_swingshot(state, player) -) -BOLDAN_SPIDERBOT_ALLEY_PB = LocationData( - 131, "Boldan: Spiderbot Alley - Platinum Bolt", - lambda state, player: can_levitate(state, player) and can_spiderbot(state, player) -) -BOLDAN_FLOATING_PLATFORM_PB = LocationData( - 132, "Boldan: Floating Platform - Platinum Bolt", - lambda state, player: can_levitate(state, player) and can_gravity(state, player) -) -BOLDAN_UPPER_DOME_PB = LocationData( - 133, "Boldan: Upper Dome - Platinum Bolt", - lambda state, player: - can_levitate(state, player) - and can_gravity(state, player) - and can_swingshot(state, player) -) -BOLDAN_FOUNTAIN_NT = LocationData(134, "Boldan: Fountain - Nanotech Boost", can_levitate) +BOLDAN_FIND_FIZZWIDGET = LocationData(130, "Boldan: Find Fizzwidget", boldan_find_fizzwidget_rule) +BOLDAN_SPIDERBOT_ALLEY_PB = LocationData(131, "Boldan: Spiderbot Alley - Platinum Bolt", boldan_spiderbot_alley_pb_rule) +BOLDAN_FLOATING_PLATFORM_PB = LocationData(132, "Boldan: Floating Platform - Platinum Bolt",boldan_floating_platform_rule) +BOLDAN_UPPER_DOME_PB = LocationData(133, "Boldan: Upper Dome - Platinum Bolt", boldan_find_fizzwidget_rule) +BOLDAN_FOUNTAIN_NT = LocationData(134, "Boldan: Fountain - Nanotech Boost", boldan_fountain_nt_rule) """ Aranos Prison """ -# NOTICE: Gravity Boots, Levitator and Infiltrator are already logically required in order to access this planet -ARANOS_CONTROL_ROOM = LocationData(140, "Aranos: Control Room") -ARANOS_PLUMBER = LocationData(141, "Aranos: Plumber - Qwark Statuette") -ARANOS_UNDER_SHIP_PB = LocationData(142, "Aranos: Under Ship - Platinum Bolt", can_heli) -ARANOS_OMNIWRENCH_12000 = LocationData( - 143, "Aranos: OmniWrench 12000", +ARANOS_CONTROL_ROOM = LocationData(140, "Aranos: Control Room", aranos_control_room_rule) +ARANOS_PLUMBER = LocationData(141, "Aranos: Plumber - Qwark Statuette", aranos_plumber_rule) +ARANOS_UNDER_SHIP_PB = LocationData(142, "Aranos: Under Ship - Platinum Bolt", aranos_under_ship_pb_rule) +ARANOS_OMNIWRENCH_12000 = LocationData(143, "Aranos: OmniWrench 12000", aranos_omniwrench_12000_rule, checked_flag_address=lambda ram: ram.aranos_wrench_cutscene_flag ) @@ -297,134 +169,41 @@ class LocationData(NamedTuple): ) """ Snivelak """ -SNIVELAK_RESCUE_ANGELA = LocationData( - 160, "Snivelak: Rescue Angela", - lambda state, player: - can_swingshot(state, player) - and can_grind(state, player) - and can_gravity(state, player) - and can_dynamo(state, player) -) -SNIVELAK_DYNAMO_PLATFORMS_PB = LocationData( - 161, "Snivelak: Dynamo Platforms - Platinum Bolt", - lambda state, player: - can_swingshot(state, player) - and can_grind(state, player) - and can_gravity(state, player) - and can_dynamo(state, player) - and can_heli(state, player) -) -SNIVELAK_SWINGSHOT_TOWER_NT = LocationData( - 162, "Snivelak: Swingshot Tower - Nanotech Boost", - lambda state, player: can_swingshot(state, player) and can_heli(state, player) -) +SNIVELAK_RESCUE_ANGELA = LocationData(160, "Snivelak: Rescue Angela", snivelak_rescue_angelak_rule) +SNIVELAK_DYNAMO_PLATFORMS_PB = LocationData(161, "Snivelak: Dynamo Platforms - Platinum Bolt", snivelak_dynamo_pb_rule) +SNIVELAK_SWINGSHOT_TOWER_NT = LocationData(162, "Snivelak: Swingshot Tower - Nanotech Boost", snivelak_swingshot_tower_nt_rule) """ Smolg """ -SMOLG_BALLOON_TRANSMISSION = LocationData( - 170, "Smolg: Balloon Transmission", - lambda state, player: - can_improved_jump(state, player) - and can_dynamo(state, player) - and can_electrolyze(state, player) -) -SMOLG_DISTRIBUTION_FACILITY_END = LocationData( - 171, "Smolg: Distribution Facility End - Hypnomatic Part", - access_rule=lambda state, player: - can_improved_jump(state, player) - and can_dynamo(state, player) - and can_electrolyze(state, player) - and can_grind(state, player) - and can_infiltrate(state, player), +SMOLG_BALLOON_TRANSMISSION = LocationData(170, "Smolg: Balloon Transmission", smolg_balloon_transmission_rule) +SMOLG_DISTRIBUTION_FACILITY_END = LocationData(171, "Smolg: Distribution Facility End - Hypnomatic Part", smolg_distribution_facility_end_rule, checked_flag_address=lambda ram: ram.hypnomatic_part1 ) -SMOLG_MUTANT_CRAB = LocationData( - 172, "Smolg: Mutant Crab", - lambda state, player: can_swingshot(state, player) and can_levitate(state, player) -) -SMOLG_FLOATING_PLATFORM_PB = LocationData( - 173, "Smolg: Floating Platform - Platinum Bolt", - lambda state, player: can_swingshot(state, player) and can_levitate(state, player) -) -SMOLG_WAREHOUSE_PB = LocationData( - 174, "Smolg: Warehouse - Platinum Bolt", - lambda state, player: can_improved_jump(state, player) and can_dynamo(state, player) -) +SMOLG_MUTANT_CRAB = LocationData(172, "Smolg: Mutant Crab", smolg_mutant_crab_rule) +SMOLG_FLOATING_PLATFORM_PB = LocationData(173, "Smolg: Floating Platform - Platinum Bolt", smolg_floating_platform_pb_rule) +SMOLG_WAREHOUSE_PB = LocationData(174, "Smolg: Warehouse - Platinum Bolt", smolg_warehouse_pb_rule) """ Damosel """ -DAMOSEL_HYPNOTIST = LocationData( - 180, "Damosel: Hypnotist", - lambda state, player: - can_swingshot(state, player) - and can_improved_jump(state, player) - and can_thermanate(state, player) - and has_hypnomatic_parts(state, player) -) -DAMOSEL_TRAIN_RAILS = LocationData( - 181, "Damosel: Train Rails - Hypnomatic Part", - access_rule=can_grind, +DAMOSEL_HYPNOTIST = LocationData(180, "Damosel: Hypnotist", damosel_hypnotist_rule) +DAMOSEL_TRAIN_RAILS = LocationData(181, "Damosel: Train Rails - Hypnomatic Part", damosel_train_rails_rule, checked_flag_address=lambda ram: ram.hypnomatic_part2 ) DAMOSEL_DEFEAT_MOTHERSHIP = LocationData(182, "Damosel: Defeat Mothership - Mapper") -DAMOSEL_FROZEN_FOUNTAIN_PB = LocationData( - 183, "Damosel: Frozen Fountain - Platinum Bolt", - lambda state, player: - can_swingshot(state, player) - and can_improved_jump(state, player) - and can_thermanate(state, player) - and can_grind(state, player) -) -DAMOSEL_PYRAMID_PB = LocationData( - 184, "Damosel: Pyramid - Platinum Bolt", - lambda state, player: - can_swingshot(state, player) - and can_improved_jump(state, player) - and can_hypnotize(state, player) -) +DAMOSEL_FROZEN_FOUNTAIN_PB = LocationData(183, "Damosel: Frozen Fountain - Platinum Bolt", damosel_frozen_mountain_pb_rule) +DAMOSEL_PYRAMID_PB = LocationData(184, "Damosel: Pyramid - Platinum Bolt", damosel_pyramid_pb_rule) """ Grelbin """ -GRELBIN_FIND_ANGELA = LocationData(190, "Grelbin: Find Angela", can_hypnotize) -GRELBIN_MYSTIC_MORE_MOONSTONES = LocationData( - 191, "Grelbin: Mystic More Moonstones - Hypnomatic Part", - access_rule=lambda state, player: can_glide(state, player) and can_infiltrate(state, player), +GRELBIN_FIND_ANGELA = LocationData(190, "Grelbin: Find Angela", grelbin_find_angela_rule) +GRELBIN_MYSTIC_MORE_MOONSTONES = LocationData(191, "Grelbin: Mystic More Moonstones - Hypnomatic Part", grelbin_mystic_more_moonstones_rule, checked_flag_address=lambda ram: ram.hypnomatic_part3 ) -GRELBIN_ICE_PLAINS_PB = LocationData( - 192, "Grelbin: Ice Plains - Platinum Bolt", - lambda state, player: can_glide(state, player) and can_infiltrate(state, player) -) -GRELBIN_UNDERWATER_TUNNEL_PB = LocationData(193, "Grelbin: Underwater Tunnel - Platinum Bolt", can_hypnotize) -GRELBIN_YETI_CAVE_PB = LocationData( - 194, "Grelbin: Yeti Cave - Platinum Bolt", - lambda state, player: - can_glide(state, player) - and can_infiltrate(state, player) - and can_hypnotize(state, player) -) +GRELBIN_ICE_PLAINS_PB = LocationData(192, "Grelbin: Ice Plains - Platinum Bolt", grelbin_ice_plains_pb_rule) +GRELBIN_UNDERWATER_TUNNEL_PB = LocationData(193, "Grelbin: Underwater Tunnel - Platinum Bolt", grelbin_underwater_tunnel_pb_rule) +GRELBIN_YETI_CAVE_PB = LocationData(194, "Grelbin: Yeti Cave - Platinum Bolt", grelbin_yeti_cave_pb_rule) """ Yeedil """ -YEEDIL_DEFEAT_MUTATED_PROTOPET = LocationData( - None, "Yeedil: Defeat Mutated Protopet", - lambda state, player: - can_swingshot(state, player) - and can_hypnotize(state, player) - and can_improved_jump(state, player) - and can_dynamo(state, player) - and can_infiltrate(state, player) - and can_electrolyze(state, player) -) -YEEDIL_BRIDGE_GRINDRAIL_PB = LocationData(200, "Yeedil: Bridge Grindrail - Platinum Bolt", can_grind) -YEEDIL_TRACTOR_PILLAR_PB = LocationData( - 201, "Yeedil: Tractor Pillar - Platinum Bolt", - lambda state, player: - can_swingshot(state, player) - and can_hypnotize(state, player) - and can_improved_jump(state, player) - and can_dynamo(state, player) - and can_infiltrate(state, player) - and can_electrolyze(state, player) - and can_tractor(state, player) - and can_grind(state, player) -) +YEEDIL_DEFEAT_MUTATED_PROTOPET = LocationData(None, "Yeedil: Defeat Mutated Protopet", yeedil_defeat_mutated_protopet_rule) +YEEDIL_BRIDGE_GRINDRAIL_PB = LocationData(200, "Yeedil: Bridge Grindrail - Platinum Bolt", yeedil_bridge_grindrail_pb_rule) +YEEDIL_TRACTOR_PILLAR_PB = LocationData(201, "Yeedil: Tractor Pillar - Platinum Bolt", yeedil_tractor_pillar_pb_rule) """ Megacorp Vendor """ OOZLA_VENDOR_WEAPON_1 = LocationData(