mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
The Witness: The Secret Feature (#4370)
* Secret Feature * Fixes * Fixes and unit tests * renaming some variables * Fix the thing * unit test for elevator egg * Docstring * reword * Fix duplicate locations I think? * Remove debug thing * Add the tests back lol * Make it so that you can exclude an egg to disable it * Improve hint text for easter eggs * Update worlds/witness/options.py Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Update worlds/witness/player_logic.py Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Update worlds/witness/options.py Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Update worlds/witness/player_logic.py Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Update worlds/witness/rules.py Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Update test_easter_egg_shuffle.py * This was actually not necessary, since this is the Egg requirements, nothing to do with location names * Move one of them * Improve logic * Lol * Moar * Adjust unit tests * option docstring adjustment * Recommend door shuffle * Don't overlap IDs * Option description idk * Change the way the difficulties work to reward playing higher modes * Fix merge * add some stuff to generate_data_file (this file is not imported during gen, don't review it :D) * oop * space * This can be earlier than I thought, apparently. * buffer * Comment * Make sure the option is VERY visible * Some mypy stuff * apparently ruff wants this * . * durinig * Update options.py * Explain the additional effects of each difficulty * Fix logic of flood room secret * Add Southern Peninsula Area * oop --------- Co-authored-by: Scipio Wright <scipiowright@gmail.com>
This commit is contained in:
@@ -5,7 +5,7 @@ import dataclasses
|
|||||||
from logging import error, warning
|
from logging import error, warning
|
||||||
from typing import Any, Dict, List, Optional, cast
|
from typing import Any, Dict, List, Optional, cast
|
||||||
|
|
||||||
from BaseClasses import CollectionState, Entrance, Location, Region, Tutorial
|
from BaseClasses import CollectionState, Entrance, Location, LocationProgressType, Region, Tutorial
|
||||||
|
|
||||||
from Options import OptionError, PerGameCommonOptions, Toggle
|
from Options import OptionError, PerGameCommonOptions, Toggle
|
||||||
from worlds.AutoWorld import WebWorld, World
|
from worlds.AutoWorld import WebWorld, World
|
||||||
@@ -380,6 +380,10 @@ class WitnessWorld(World):
|
|||||||
if isinstance(item_name, dict):
|
if isinstance(item_name, dict):
|
||||||
item_name = next(iter(item_name))
|
item_name = next(iter(item_name))
|
||||||
|
|
||||||
|
# Easter Egg events with arbitrary sizes
|
||||||
|
if item_name.startswith("+") and "Easter Egg" in item_name:
|
||||||
|
return WitnessItem.make_egg_event(item_name, self.player)
|
||||||
|
|
||||||
# this conditional is purely for unit tests, which need to be able to create an item before generate_early
|
# this conditional is purely for unit tests, which need to be able to create an item before generate_early
|
||||||
item_data: ItemData
|
item_data: ItemData
|
||||||
if hasattr(self, "player_items") and self.player_items and item_name in self.player_items.item_data:
|
if hasattr(self, "player_items") and self.player_items and item_name in self.player_items.item_data:
|
||||||
@@ -389,6 +393,18 @@ class WitnessWorld(World):
|
|||||||
|
|
||||||
return WitnessItem(item_name, item_data.classification, item_data.ap_code, player=self.player)
|
return WitnessItem(item_name, item_data.classification, item_data.ap_code, player=self.player)
|
||||||
|
|
||||||
|
def collect(self, state: "CollectionState", item: WitnessItem) -> bool:
|
||||||
|
changed = super().collect(state, item)
|
||||||
|
if changed and item.eggs:
|
||||||
|
state.prog_items[self.player]["Egg"] += item.eggs
|
||||||
|
return changed
|
||||||
|
|
||||||
|
def remove(self, state: "CollectionState", item: WitnessItem) -> bool:
|
||||||
|
changed = super().remove(state, item)
|
||||||
|
if changed and item.eggs:
|
||||||
|
state.prog_items[self.player]["Egg"] -= item.eggs
|
||||||
|
return changed
|
||||||
|
|
||||||
def get_filler_item_name(self) -> str:
|
def get_filler_item_name(self) -> str:
|
||||||
return "Speed Boost"
|
return "Speed Boost"
|
||||||
|
|
||||||
@@ -398,11 +414,9 @@ class WitnessLocation(Location):
|
|||||||
Archipelago Location for The Witness
|
Archipelago Location for The Witness
|
||||||
"""
|
"""
|
||||||
game: str = "The Witness"
|
game: str = "The Witness"
|
||||||
entity_hex: int = -1
|
|
||||||
|
|
||||||
def __init__(self, player: int, name: str, address: Optional[int], parent: Region, ch_hex: int = -1) -> None:
|
def __init__(self, player: int, name: str, address: Optional[int], parent: Region) -> None:
|
||||||
super().__init__(player, name, address, parent)
|
super().__init__(player, name, address, parent)
|
||||||
self.entity_hex = ch_hex
|
|
||||||
|
|
||||||
|
|
||||||
def create_region(world: WitnessWorld, name: str, player_locations: WitnessPlayerLocations,
|
def create_region(world: WitnessWorld, name: str, player_locations: WitnessPlayerLocations,
|
||||||
@@ -416,14 +430,13 @@ def create_region(world: WitnessWorld, name: str, player_locations: WitnessPlaye
|
|||||||
for location in region_locations:
|
for location in region_locations:
|
||||||
loc_id = player_locations.CHECK_LOCATION_TABLE[location]
|
loc_id = player_locations.CHECK_LOCATION_TABLE[location]
|
||||||
|
|
||||||
entity_hex = -1
|
location_obj = WitnessLocation(world.player, location, loc_id, ret)
|
||||||
|
|
||||||
if location in static_witness_logic.ENTITIES_BY_NAME:
|
if location in static_witness_logic.ENTITIES_BY_NAME:
|
||||||
entity_hex = int(
|
entity_hex = static_witness_logic.ENTITIES_BY_NAME[location]["entity_hex"]
|
||||||
static_witness_logic.ENTITIES_BY_NAME[location]["entity_hex"], 0
|
|
||||||
)
|
if entity_hex in world.player_logic.EXCLUDED_ENTITIES:
|
||||||
location_obj = WitnessLocation(
|
location_obj.progress_type = LocationProgressType.EXCLUDED
|
||||||
world.player, location, loc_id, ret, entity_hex
|
|
||||||
)
|
|
||||||
|
|
||||||
ret.locations.append(location_obj)
|
ret.locations.append(location_obj)
|
||||||
if exits:
|
if exits:
|
||||||
|
@@ -206,7 +206,7 @@ Door - 0x0A24B (Flood Room Entry) - 0x0A249
|
|||||||
159043 - 0x0A14C (Pond Room Near Reflection EP) - True - True
|
159043 - 0x0A14C (Pond Room Near Reflection EP) - True - True
|
||||||
159044 - 0x0A14D (Pond Room Far Reflection EP) - True - True
|
159044 - 0x0A14D (Pond Room Far Reflection EP) - True - True
|
||||||
|
|
||||||
Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316:
|
Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316 - Desert Flood Room Underwater - 0x1C260:
|
||||||
158097 - 0x1C2DF (Reduce Water Level Far Left) - True - True
|
158097 - 0x1C2DF (Reduce Water Level Far Left) - True - True
|
||||||
158098 - 0x1831E (Reduce Water Level Far Right) - True - True
|
158098 - 0x1831E (Reduce Water Level Far Right) - True - True
|
||||||
158099 - 0x1C260 (Reduce Water Level Near Left) - True - True
|
158099 - 0x1C260 (Reduce Water Level Near Left) - True - True
|
||||||
@@ -224,6 +224,8 @@ Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316:
|
|||||||
Door - 0x0C316 (Elevator Room Entry) - 0x18076
|
Door - 0x0C316 (Elevator Room Entry) - 0x18076
|
||||||
159034 - 0x337F8 (Flood Room EP) - 0x1C2DF - True
|
159034 - 0x337F8 (Flood Room EP) - 0x1C2DF - True
|
||||||
|
|
||||||
|
Desert Flood Room Underwater (Desert):
|
||||||
|
|
||||||
Desert Elevator Room (Desert) - Desert Behind Elevator - 0x01317:
|
Desert Elevator Room (Desert) - Desert Behind Elevator - 0x01317:
|
||||||
158111 - 0x17C31 (Elevator Room Transparent) - True - True
|
158111 - 0x17C31 (Elevator Room Transparent) - True - True
|
||||||
158113 - 0x012D7 (Elevator Room Hexagonal) - 0x17C31 & 0x0A015 - True
|
158113 - 0x012D7 (Elevator Room Hexagonal) - 0x17C31 & 0x0A015 - True
|
||||||
@@ -501,7 +503,7 @@ Laser - 0x17C65 (Laser) - 0x17CA4
|
|||||||
159121 - 0x03BE3 (Garden Right EP) - True - True
|
159121 - 0x03BE3 (Garden Right EP) - True - True
|
||||||
159122 - 0x0A409 (Wall EP) - True - True
|
159122 - 0x0A409 (Wall EP) - True - True
|
||||||
|
|
||||||
Inside Monastery (Monastery):
|
Inside Monastery (Monastery) - Monastery North Shutters - 0x09D9B:
|
||||||
158213 - 0x09D9B (Shutters Control) - True - Dots
|
158213 - 0x09D9B (Shutters Control) - True - Dots
|
||||||
158214 - 0x193A7 (Inside 1) - 0x00037 - True
|
158214 - 0x193A7 (Inside 1) - 0x00037 - True
|
||||||
158215 - 0x193AA (Inside 2) - 0x193A7 - True
|
158215 - 0x193AA (Inside 2) - 0x193A7 - True
|
||||||
@@ -513,6 +515,8 @@ Inside Monastery (Monastery):
|
|||||||
|
|
||||||
Monastery Garden (Monastery):
|
Monastery Garden (Monastery):
|
||||||
|
|
||||||
|
Monastery North Shutters (Monastery):
|
||||||
|
|
||||||
==Town==
|
==Town==
|
||||||
|
|
||||||
Town Obelisk (Town) - Entry - True:
|
Town Obelisk (Town) - Entry - True:
|
||||||
@@ -637,9 +641,13 @@ Door - 0x3CCDF (Exit Right) - 0x33AB2
|
|||||||
159556 - 0x33A2A (Door EP) - 0x03553 - True
|
159556 - 0x33A2A (Door EP) - 0x03553 - True
|
||||||
159558 - 0x33B06 (Church EP) - 0x0354E - True
|
159558 - 0x33B06 (Church EP) - 0x0354E - True
|
||||||
|
|
||||||
|
==Southern Peninsula==
|
||||||
|
|
||||||
|
Southern Peninsula (Southern Peninsula) - Main Island - True:
|
||||||
|
|
||||||
==Jungle==
|
==Jungle==
|
||||||
|
|
||||||
Jungle (Jungle) - Main Island - True - The Ocean - 0x17CDF:
|
Jungle (Jungle) - Main Island - True - The Ocean - 0x17CDF - Jungle Under Popup Wall - 0x1475B:
|
||||||
158251 - 0x17CDF (Shore Boat Spawn) - True - Boat
|
158251 - 0x17CDF (Shore Boat Spawn) - True - Boat
|
||||||
158609 - 0x17F9B (Discard) - True - Triangles
|
158609 - 0x17F9B (Discard) - True - Triangles
|
||||||
158252 - 0x002C4 (First Row 1) - True - True
|
158252 - 0x002C4 (First Row 1) - True - True
|
||||||
@@ -670,6 +678,8 @@ Door - 0x3873B (Laser Shortcut) - 0x337FA
|
|||||||
159350 - 0x035CB (Bamboo CCW EP) - True - True
|
159350 - 0x035CB (Bamboo CCW EP) - True - True
|
||||||
159351 - 0x035CF (Bamboo CW EP) - True - True
|
159351 - 0x035CF (Bamboo CW EP) - True - True
|
||||||
|
|
||||||
|
Jungle Under Popup Wall (Jungle):
|
||||||
|
|
||||||
Outside Jungle River (Jungle) - Main Island - True - Monastery Garden - 0x0CF2A - Jungle Vault - 0x15287:
|
Outside Jungle River (Jungle) - Main Island - True - Monastery Garden - 0x0CF2A - Jungle Vault - 0x15287:
|
||||||
158267 - 0x17CAA (Monastery Garden Shortcut Panel) - True - True
|
158267 - 0x17CAA (Monastery Garden Shortcut Panel) - True - True
|
||||||
Door - 0x0CF2A (Monastery Garden Shortcut) - 0x17CAA
|
Door - 0x0CF2A (Monastery Garden Shortcut) - 0x17CAA
|
||||||
@@ -712,9 +722,11 @@ Bunker Ultraviolet Room (Bunker) - Bunker Elevator Section - 0x0A08D:
|
|||||||
158285 - 0x17E67 (UV Room 2) - 0x17E63 & 0x34BC6 - Colored Squares & Black/White Squares
|
158285 - 0x17E67 (UV Room 2) - 0x17E63 & 0x34BC6 - Colored Squares & Black/White Squares
|
||||||
Door - 0x0A08D (Elevator Room Entry) - 0x17E67
|
Door - 0x0A08D (Elevator Room Entry) - 0x17E67
|
||||||
|
|
||||||
Bunker Elevator Section (Bunker) - Bunker Elevator - TrueOneWay:
|
Bunker Elevator Section (Bunker) - Bunker Elevator - TrueOneWay - Bunker Under Elevator - 0x0A079 | Bunker Green Room | Bunker Cyan Room | Bunker Laser Platform:
|
||||||
159311 - 0x035F5 (Tinted Door EP) - 0x17C79 - True
|
159311 - 0x035F5 (Tinted Door EP) - 0x17C79 - True
|
||||||
|
|
||||||
|
Bunker Under Elevator (Bunker):
|
||||||
|
|
||||||
Bunker Elevator (Bunker) - Bunker Elevator Section - 0x0A079 - Bunker Cyan Room - 0x0A079 - Bunker Green Room - 0x0A079 - Bunker Laser Platform - 0x0A079 - Outside Bunker - 0x0A079:
|
Bunker Elevator (Bunker) - Bunker Elevator Section - 0x0A079 - Bunker Cyan Room - 0x0A079 - Bunker Green Room - 0x0A079 - Bunker Laser Platform - 0x0A079 - Outside Bunker - 0x0A079:
|
||||||
158286 - 0x0A079 (Elevator Control) - True - Colored Squares & Black/White Squares
|
158286 - 0x0A079 (Elevator Control) - True - Colored Squares & Black/White Squares
|
||||||
|
|
||||||
@@ -1005,7 +1017,7 @@ Mountaintop (Mountaintop) - Mountain Floor 1 - 0x17C34:
|
|||||||
Mountain Floor 1 (Mountain Floor 1) - Mountain Floor 1 Bridge - 0x09E39:
|
Mountain Floor 1 (Mountain Floor 1) - Mountain Floor 1 Bridge - 0x09E39:
|
||||||
158408 - 0x09E39 (Light Bridge Controller) - True - Black/White Squares & Colored Squares & Eraser
|
158408 - 0x09E39 (Light Bridge Controller) - True - Black/White Squares & Colored Squares & Eraser
|
||||||
|
|
||||||
Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneWay:
|
Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneWay - Mountain Floor 1 Trash Pillar - TrueOneWay - Mountain Floor 1 Back Section - TrueOneWay:
|
||||||
158409 - 0x09E7A (Right Row 1) - True - Black/White Squares & Dots
|
158409 - 0x09E7A (Right Row 1) - True - Black/White Squares & Dots
|
||||||
158410 - 0x09E71 (Right Row 2) - 0x09E7A - Black/White Squares & Dots
|
158410 - 0x09E71 (Right Row 2) - 0x09E7A - Black/White Squares & Dots
|
||||||
158411 - 0x09E72 (Right Row 3) - 0x09E71 - Black/White Squares & Shapers & Dots
|
158411 - 0x09E72 (Right Row 3) - 0x09E71 - Black/White Squares & Shapers & Dots
|
||||||
@@ -1018,11 +1030,15 @@ Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneW
|
|||||||
158418 - 0x09E6C (Left Row 5) - 0x09E79 - Stars & Black/White Squares & Stars + Same Colored Symbol
|
158418 - 0x09E6C (Left Row 5) - 0x09E79 - Stars & Black/White Squares & Stars + Same Colored Symbol
|
||||||
158419 - 0x09E6F (Left Row 6) - 0x09E6C - Stars & Rotated Shapers & Shapers
|
158419 - 0x09E6F (Left Row 6) - 0x09E6C - Stars & Rotated Shapers & Shapers
|
||||||
158420 - 0x09E6B (Left Row 7) - 0x09E6F - Stars & Dots
|
158420 - 0x09E6B (Left Row 7) - 0x09E6F - Stars & Dots
|
||||||
|
158424 - 0x09EAD (Trash Pillar 1) - True - Black/White Squares & Shapers
|
||||||
|
158425 - 0x09EAF (Trash Pillar 2) - 0x09EAD - Black/White Squares & Shaper
|
||||||
|
|
||||||
|
Mountain Floor 1 Trash Pillar (Mountain Floor 1):
|
||||||
|
|
||||||
|
Mountain Floor 1 Back Section (Mountain Floor 1):
|
||||||
158421 - 0x33AF5 (Back Row 1) - True - Black/White Squares & Symmetry
|
158421 - 0x33AF5 (Back Row 1) - True - Black/White Squares & Symmetry
|
||||||
158422 - 0x33AF7 (Back Row 2) - 0x33AF5 - Black/White Squares & Stars
|
158422 - 0x33AF7 (Back Row 2) - 0x33AF5 - Black/White Squares & Stars
|
||||||
158423 - 0x09F6E (Back Row 3) - 0x33AF7 - Symmetry & Dots
|
158423 - 0x09F6E (Back Row 3) - 0x33AF7 - Symmetry & Dots
|
||||||
158424 - 0x09EAD (Trash Pillar 1) - True - Black/White Squares & Shapers
|
|
||||||
158425 - 0x09EAF (Trash Pillar 2) - 0x09EAD - Black/White Squares & Shapers
|
|
||||||
|
|
||||||
Mountain Floor 1 At Door (Mountain Floor 1) - Mountain Floor 2 - 0x09E54:
|
Mountain Floor 1 At Door (Mountain Floor 1) - Mountain Floor 2 - 0x09E54:
|
||||||
Door - 0x09E54 (Exit) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
|
Door - 0x09E54 (Exit) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
|
||||||
@@ -1098,14 +1114,16 @@ Elevator (Mountain Bottom Floor):
|
|||||||
Mountain Pink Bridge EP (Mountain Floor 2):
|
Mountain Pink Bridge EP (Mountain Floor 2):
|
||||||
159312 - 0x09D63 (Pink Bridge EP) - 0x09E39 - True
|
159312 - 0x09D63 (Pink Bridge EP) - 0x09E39 - True
|
||||||
|
|
||||||
Mountain Path to Caves (Mountain Bottom Floor) - Caves - 0x2D77D:
|
Mountain Path to Caves (Mountain Bottom Floor) - Caves - 0x2D77D - Caves Entry Door - TrueOneWay:
|
||||||
158447 - 0x00FF8 (Caves Entry Panel) - True - Triangles & Black/White Squares
|
158447 - 0x00FF8 (Caves Entry Panel) - True - Triangles & Black/White Squares
|
||||||
Door - 0x2D77D (Caves Entry) - 0x00FF8
|
Door - 0x2D77D (Caves Entry) - 0x00FF8
|
||||||
158448 - 0x334E1 (Rock Control) - True - True
|
158448 - 0x334E1 (Rock Control) - True - True
|
||||||
|
|
||||||
==Caves==
|
==Caves==
|
||||||
|
|
||||||
Caves (Caves) - Main Island - 0x2D73F | 0x2D859 - Caves Path to Challenge - 0x019A5:
|
Caves Entry Door (Caves):
|
||||||
|
|
||||||
|
Caves (Caves) - Main Island - 0x2D73F | 0x2D859 - Caves Path to Challenge - 0x019A5 - Caves Entry Door - TrueOneWay:
|
||||||
158451 - 0x335AB (Elevator Inside Control) - True - Dots & Black/White Squares
|
158451 - 0x335AB (Elevator Inside Control) - True - Dots & Black/White Squares
|
||||||
158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Black/White Squares
|
158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Black/White Squares
|
||||||
158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Black/White Squares & Dots
|
158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Black/White Squares & Dots
|
||||||
@@ -1219,3 +1237,7 @@ The Ocean (Boat) - Main Island - TrueOneWay - Swamp Near Boat - TrueOneWay - Tre
|
|||||||
159521 - 0x33879 (Tutorial Reflection EP) - True - True
|
159521 - 0x33879 (Tutorial Reflection EP) - True - True
|
||||||
159522 - 0x03C19 (Tutorial Moss EP) - True - True
|
159522 - 0x03C19 (Tutorial Moss EP) - True - True
|
||||||
159531 - 0x035C9 (Cargo Box EP) - 0x0A0C9 - True
|
159531 - 0x035C9 (Cargo Box EP) - 0x0A0C9 - True
|
||||||
|
|
||||||
|
==Easter Eggs==
|
||||||
|
|
||||||
|
Easter Eggs (Easter Eggs) - Entry - True:
|
||||||
|
@@ -206,7 +206,7 @@ Door - 0x0A24B (Flood Room Entry) - 0x0A249
|
|||||||
159043 - 0x0A14C (Pond Room Near Reflection EP) - True - True
|
159043 - 0x0A14C (Pond Room Near Reflection EP) - True - True
|
||||||
159044 - 0x0A14D (Pond Room Far Reflection EP) - True - True
|
159044 - 0x0A14D (Pond Room Far Reflection EP) - True - True
|
||||||
|
|
||||||
Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316:
|
Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316 - Desert Flood Room Underwater - 0x1C260:
|
||||||
158097 - 0x1C2DF (Reduce Water Level Far Left) - True - True
|
158097 - 0x1C2DF (Reduce Water Level Far Left) - True - True
|
||||||
158098 - 0x1831E (Reduce Water Level Far Right) - True - True
|
158098 - 0x1831E (Reduce Water Level Far Right) - True - True
|
||||||
158099 - 0x1C260 (Reduce Water Level Near Left) - True - True
|
158099 - 0x1C260 (Reduce Water Level Near Left) - True - True
|
||||||
@@ -224,6 +224,8 @@ Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316:
|
|||||||
Door - 0x0C316 (Elevator Room Entry) - 0x18076
|
Door - 0x0C316 (Elevator Room Entry) - 0x18076
|
||||||
159034 - 0x337F8 (Flood Room EP) - 0x1C2DF - True
|
159034 - 0x337F8 (Flood Room EP) - 0x1C2DF - True
|
||||||
|
|
||||||
|
Desert Flood Room Underwater (Desert):
|
||||||
|
|
||||||
Desert Elevator Room (Desert) - Desert Behind Elevator - 0x01317:
|
Desert Elevator Room (Desert) - Desert Behind Elevator - 0x01317:
|
||||||
158111 - 0x17C31 (Elevator Room Transparent) - True - True
|
158111 - 0x17C31 (Elevator Room Transparent) - True - True
|
||||||
158113 - 0x012D7 (Elevator Room Hexagonal) - 0x17C31 & 0x0A015 - True
|
158113 - 0x012D7 (Elevator Room Hexagonal) - 0x17C31 & 0x0A015 - True
|
||||||
@@ -501,7 +503,7 @@ Laser - 0x17C65 (Laser) - 0x17CA4
|
|||||||
159121 - 0x03BE3 (Garden Right EP) - True - True
|
159121 - 0x03BE3 (Garden Right EP) - True - True
|
||||||
159122 - 0x0A409 (Wall EP) - True - True
|
159122 - 0x0A409 (Wall EP) - True - True
|
||||||
|
|
||||||
Inside Monastery (Monastery):
|
Inside Monastery (Monastery) - Monastery North Shutters - 0x09D9B:
|
||||||
158213 - 0x09D9B (Shutters Control) - True - Dots
|
158213 - 0x09D9B (Shutters Control) - True - Dots
|
||||||
158214 - 0x193A7 (Inside 1) - 0x00037 - True
|
158214 - 0x193A7 (Inside 1) - 0x00037 - True
|
||||||
158215 - 0x193AA (Inside 2) - 0x193A7 - True
|
158215 - 0x193AA (Inside 2) - 0x193A7 - True
|
||||||
@@ -513,6 +515,8 @@ Inside Monastery (Monastery):
|
|||||||
|
|
||||||
Monastery Garden (Monastery):
|
Monastery Garden (Monastery):
|
||||||
|
|
||||||
|
Monastery North Shutters (Monastery):
|
||||||
|
|
||||||
==Town==
|
==Town==
|
||||||
|
|
||||||
Town Obelisk (Town) - Entry - True:
|
Town Obelisk (Town) - Entry - True:
|
||||||
@@ -637,9 +641,13 @@ Door - 0x3CCDF (Exit Right) - 0x33AB2
|
|||||||
159556 - 0x33A2A (Door EP) - 0x03553 - True
|
159556 - 0x33A2A (Door EP) - 0x03553 - True
|
||||||
159558 - 0x33B06 (Church EP) - 0x0354E - True
|
159558 - 0x33B06 (Church EP) - 0x0354E - True
|
||||||
|
|
||||||
|
==Southern Peninsula==
|
||||||
|
|
||||||
|
Southern Peninsula (Southern Peninsula) - Main Island - True:
|
||||||
|
|
||||||
==Jungle==
|
==Jungle==
|
||||||
|
|
||||||
Jungle (Jungle) - Main Island - True - The Ocean - 0x17CDF:
|
Jungle (Jungle) - Main Island - True - The Ocean - 0x17CDF - Jungle Under Popup Wall - 0x1475B:
|
||||||
158251 - 0x17CDF (Shore Boat Spawn) - True - Boat
|
158251 - 0x17CDF (Shore Boat Spawn) - True - Boat
|
||||||
158609 - 0x17F9B (Discard) - True - Arrows
|
158609 - 0x17F9B (Discard) - True - Arrows
|
||||||
158252 - 0x002C4 (First Row 1) - True - True
|
158252 - 0x002C4 (First Row 1) - True - True
|
||||||
@@ -670,6 +678,8 @@ Door - 0x3873B (Laser Shortcut) - 0x337FA
|
|||||||
159350 - 0x035CB (Bamboo CCW EP) - True - True
|
159350 - 0x035CB (Bamboo CCW EP) - True - True
|
||||||
159351 - 0x035CF (Bamboo CW EP) - True - True
|
159351 - 0x035CF (Bamboo CW EP) - True - True
|
||||||
|
|
||||||
|
Jungle Under Popup Wall (Jungle):
|
||||||
|
|
||||||
Outside Jungle River (Jungle) - Main Island - True - Monastery Garden - 0x0CF2A - Jungle Vault - 0x15287:
|
Outside Jungle River (Jungle) - Main Island - True - Monastery Garden - 0x0CF2A - Jungle Vault - 0x15287:
|
||||||
158267 - 0x17CAA (Monastery Garden Shortcut Panel) - True - True
|
158267 - 0x17CAA (Monastery Garden Shortcut Panel) - True - True
|
||||||
Door - 0x0CF2A (Monastery Garden Shortcut) - 0x17CAA
|
Door - 0x0CF2A (Monastery Garden Shortcut) - 0x17CAA
|
||||||
@@ -712,9 +722,11 @@ Bunker Ultraviolet Room (Bunker) - Bunker Elevator Section - 0x0A08D:
|
|||||||
158285 - 0x17E67 (UV Room 2) - 0x17E63 & 0x34BC6 - Squares & Colored Squares & Black/White Squares
|
158285 - 0x17E67 (UV Room 2) - 0x17E63 & 0x34BC6 - Squares & Colored Squares & Black/White Squares
|
||||||
Door - 0x0A08D (Elevator Room Entry) - 0x17E67
|
Door - 0x0A08D (Elevator Room Entry) - 0x17E67
|
||||||
|
|
||||||
Bunker Elevator Section (Bunker) - Bunker Elevator - TrueOneWay:
|
Bunker Elevator Section (Bunker) - Bunker Elevator - TrueOneWay - Bunker Under Elevator - 0x0A079 | Bunker Green Room | Bunker Cyan Room | Bunker Laser Platform:
|
||||||
159311 - 0x035F5 (Tinted Door EP) - 0x17C79 - True
|
159311 - 0x035F5 (Tinted Door EP) - 0x17C79 - True
|
||||||
|
|
||||||
|
Bunker Under Elevator (Bunker):
|
||||||
|
|
||||||
Bunker Elevator (Bunker) - Bunker Elevator Section - 0x0A079 - Bunker Cyan Room - 0x0A079 - Bunker Green Room - 0x0A079 - Bunker Laser Platform - 0x0A079 - Outside Bunker - 0x0A079:
|
Bunker Elevator (Bunker) - Bunker Elevator Section - 0x0A079 - Bunker Cyan Room - 0x0A079 - Bunker Green Room - 0x0A079 - Bunker Laser Platform - 0x0A079 - Outside Bunker - 0x0A079:
|
||||||
158286 - 0x0A079 (Elevator Control) - True - Colored Squares & Black/White Squares
|
158286 - 0x0A079 (Elevator Control) - True - Colored Squares & Black/White Squares
|
||||||
|
|
||||||
@@ -1005,7 +1017,7 @@ Mountaintop (Mountaintop) - Mountain Floor 1 - 0x17C34:
|
|||||||
Mountain Floor 1 (Mountain Floor 1) - Mountain Floor 1 Bridge - 0x09E39:
|
Mountain Floor 1 (Mountain Floor 1) - Mountain Floor 1 Bridge - 0x09E39:
|
||||||
158408 - 0x09E39 (Light Bridge Controller) - True - Eraser & Triangles
|
158408 - 0x09E39 (Light Bridge Controller) - True - Eraser & Triangles
|
||||||
|
|
||||||
Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneWay:
|
Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneWay - Mountain Floor 1 Trash Pillar - TrueOneWay - Mountain Floor 1 Back Section - TrueOneWay:
|
||||||
158409 - 0x09E7A (Right Row 1) - True - Black/White Squares & Dots & Stars & Stars + Same Colored Symbol
|
158409 - 0x09E7A (Right Row 1) - True - Black/White Squares & Dots & Stars & Stars + Same Colored Symbol
|
||||||
158410 - 0x09E71 (Right Row 2) - 0x09E7A - Black/White Squares & Triangles
|
158410 - 0x09E71 (Right Row 2) - 0x09E7A - Black/White Squares & Triangles
|
||||||
158411 - 0x09E72 (Right Row 3) - 0x09E71 - Black/White Squares & Shapers & Stars & Stars + Same Colored Symbol
|
158411 - 0x09E72 (Right Row 3) - 0x09E71 - Black/White Squares & Shapers & Stars & Stars + Same Colored Symbol
|
||||||
@@ -1018,11 +1030,15 @@ Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneW
|
|||||||
158418 - 0x09E6C (Left Row 5) - 0x09E79 - Stars & Shapers & Negative Shapers & Stars + Same Colored Symbol
|
158418 - 0x09E6C (Left Row 5) - 0x09E79 - Stars & Shapers & Negative Shapers & Stars + Same Colored Symbol
|
||||||
158419 - 0x09E6F (Left Row 6) - 0x09E6C - Symmetry & Stars & Colored Squares & Black/White Squares & Stars + Same Colored Symbol & Symmetry & Eraser
|
158419 - 0x09E6F (Left Row 6) - 0x09E6C - Symmetry & Stars & Colored Squares & Black/White Squares & Stars + Same Colored Symbol & Symmetry & Eraser
|
||||||
158420 - 0x09E6B (Left Row 7) - 0x09E6F - Symmetry & Dots & Full Dots & Triangles
|
158420 - 0x09E6B (Left Row 7) - 0x09E6F - Symmetry & Dots & Full Dots & Triangles
|
||||||
|
158424 - 0x09EAD (Trash Pillar 1) - True - Rotated Shapers & Stars
|
||||||
|
158425 - 0x09EAF (Trash Pillar 2) - 0x09EAD - Rotated Shapers & Triangles
|
||||||
|
|
||||||
|
Mountain Floor 1 Trash Pillar (Mountain Floor 1):
|
||||||
|
|
||||||
|
Mountain Floor 1 Back Section (Mountain Floor 1):
|
||||||
158421 - 0x33AF5 (Back Row 1) - True - Symmetry & Black/White Squares & Triangles
|
158421 - 0x33AF5 (Back Row 1) - True - Symmetry & Black/White Squares & Triangles
|
||||||
158422 - 0x33AF7 (Back Row 2) - 0x33AF5 - Symmetry & Stars & Triangles & Stars + Same Colored Symbol
|
158422 - 0x33AF7 (Back Row 2) - 0x33AF5 - Symmetry & Stars & Triangles & Stars + Same Colored Symbol
|
||||||
158423 - 0x09F6E (Back Row 3) - 0x33AF7 - Symmetry & Stars & Shapers & Stars + Same Colored Symbol
|
158423 - 0x09F6E (Back Row 3) - 0x33AF7 - Symmetry & Stars & Shapers & Stars + Same Colored Symbol
|
||||||
158424 - 0x09EAD (Trash Pillar 1) - True - Rotated Shapers & Stars
|
|
||||||
158425 - 0x09EAF (Trash Pillar 2) - 0x09EAD - Rotated Shapers & Triangles
|
|
||||||
|
|
||||||
Mountain Floor 1 At Door (Mountain Floor 1) - Mountain Floor 2 - 0x09E54:
|
Mountain Floor 1 At Door (Mountain Floor 1) - Mountain Floor 2 - 0x09E54:
|
||||||
Door - 0x09E54 (Exit) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
|
Door - 0x09E54 (Exit) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
|
||||||
@@ -1098,14 +1114,16 @@ Elevator (Mountain Bottom Floor):
|
|||||||
Mountain Pink Bridge EP (Mountain Floor 2):
|
Mountain Pink Bridge EP (Mountain Floor 2):
|
||||||
159312 - 0x09D63 (Pink Bridge EP) - 0x09E39 - True
|
159312 - 0x09D63 (Pink Bridge EP) - 0x09E39 - True
|
||||||
|
|
||||||
Mountain Path to Caves (Mountain Bottom Floor) - Caves - 0x2D77D:
|
Mountain Path to Caves (Mountain Bottom Floor) - Caves - 0x2D77D - Caves Entry Door - TrueOneWay:
|
||||||
158447 - 0x00FF8 (Caves Entry Panel) - True - Arrows & Black/White Squares
|
158447 - 0x00FF8 (Caves Entry Panel) - True - Arrows & Black/White Squares
|
||||||
Door - 0x2D77D (Caves Entry) - 0x00FF8
|
Door - 0x2D77D (Caves Entry) - 0x00FF8
|
||||||
158448 - 0x334E1 (Rock Control) - True - True
|
158448 - 0x334E1 (Rock Control) - True - True
|
||||||
|
|
||||||
==Caves==
|
==Caves==
|
||||||
|
|
||||||
Caves (Caves) - Main Island - 0x2D73F | 0x2D859 - Caves Path to Challenge - 0x019A5:
|
Caves Entry Door (Caves):
|
||||||
|
|
||||||
|
Caves (Caves) - Main Island - 0x2D73F | 0x2D859 - Caves Path to Challenge - 0x019A5 - Caves Entry Door - TrueOneWay:
|
||||||
158451 - 0x335AB (Elevator Inside Control) - True - Dots & Squares & Black/White Squares
|
158451 - 0x335AB (Elevator Inside Control) - True - Dots & Squares & Black/White Squares
|
||||||
158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Squares & Black/White Squares
|
158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Squares & Black/White Squares
|
||||||
158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Squares & Black/White Squares & Dots
|
158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Squares & Black/White Squares & Dots
|
||||||
@@ -1219,3 +1237,7 @@ The Ocean (Boat) - Main Island - TrueOneWay - Swamp Near Boat - TrueOneWay - Tre
|
|||||||
159521 - 0x33879 (Tutorial Reflection EP) - True - True
|
159521 - 0x33879 (Tutorial Reflection EP) - True - True
|
||||||
159522 - 0x03C19 (Tutorial Moss EP) - True - True
|
159522 - 0x03C19 (Tutorial Moss EP) - True - True
|
||||||
159531 - 0x035C9 (Cargo Box EP) - 0x0A0C9 - True
|
159531 - 0x035C9 (Cargo Box EP) - 0x0A0C9 - True
|
||||||
|
|
||||||
|
==Easter Eggs==
|
||||||
|
|
||||||
|
Easter Eggs (Easter Eggs) - Entry - True:
|
||||||
|
@@ -206,7 +206,7 @@ Door - 0x0A24B (Flood Room Entry) - 0x0A249
|
|||||||
159043 - 0x0A14C (Pond Room Near Reflection EP) - True - True
|
159043 - 0x0A14C (Pond Room Near Reflection EP) - True - True
|
||||||
159044 - 0x0A14D (Pond Room Far Reflection EP) - True - True
|
159044 - 0x0A14D (Pond Room Far Reflection EP) - True - True
|
||||||
|
|
||||||
Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316:
|
Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316 - Desert Flood Room Underwater - 0x1C260:
|
||||||
158097 - 0x1C2DF (Reduce Water Level Far Left) - True - True
|
158097 - 0x1C2DF (Reduce Water Level Far Left) - True - True
|
||||||
158098 - 0x1831E (Reduce Water Level Far Right) - True - True
|
158098 - 0x1831E (Reduce Water Level Far Right) - True - True
|
||||||
158099 - 0x1C260 (Reduce Water Level Near Left) - True - True
|
158099 - 0x1C260 (Reduce Water Level Near Left) - True - True
|
||||||
@@ -224,6 +224,8 @@ Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316:
|
|||||||
Door - 0x0C316 (Elevator Room Entry) - 0x18076
|
Door - 0x0C316 (Elevator Room Entry) - 0x18076
|
||||||
159034 - 0x337F8 (Flood Room EP) - 0x1C2DF - True
|
159034 - 0x337F8 (Flood Room EP) - 0x1C2DF - True
|
||||||
|
|
||||||
|
Desert Flood Room Underwater (Desert):
|
||||||
|
|
||||||
Desert Elevator Room (Desert) - Desert Behind Elevator - 0x01317:
|
Desert Elevator Room (Desert) - Desert Behind Elevator - 0x01317:
|
||||||
158111 - 0x17C31 (Elevator Room Transparent) - True - True
|
158111 - 0x17C31 (Elevator Room Transparent) - True - True
|
||||||
158113 - 0x012D7 (Elevator Room Hexagonal) - 0x17C31 & 0x0A015 - True
|
158113 - 0x012D7 (Elevator Room Hexagonal) - 0x17C31 & 0x0A015 - True
|
||||||
@@ -501,7 +503,7 @@ Laser - 0x17C65 (Laser) - 0x17CA4
|
|||||||
159121 - 0x03BE3 (Garden Right EP) - True - True
|
159121 - 0x03BE3 (Garden Right EP) - True - True
|
||||||
159122 - 0x0A409 (Wall EP) - True - True
|
159122 - 0x0A409 (Wall EP) - True - True
|
||||||
|
|
||||||
Inside Monastery (Monastery):
|
Inside Monastery (Monastery) - Monastery North Shutters - 0x09D9B:
|
||||||
158213 - 0x09D9B (Shutters Control) - True - Dots
|
158213 - 0x09D9B (Shutters Control) - True - Dots
|
||||||
158214 - 0x193A7 (Inside 1) - 0x00037 - True
|
158214 - 0x193A7 (Inside 1) - 0x00037 - True
|
||||||
158215 - 0x193AA (Inside 2) - 0x193A7 - True
|
158215 - 0x193AA (Inside 2) - 0x193A7 - True
|
||||||
@@ -513,6 +515,8 @@ Inside Monastery (Monastery):
|
|||||||
|
|
||||||
Monastery Garden (Monastery):
|
Monastery Garden (Monastery):
|
||||||
|
|
||||||
|
Monastery North Shutters (Monastery):
|
||||||
|
|
||||||
==Town==
|
==Town==
|
||||||
|
|
||||||
Town Obelisk (Town) - Entry - True:
|
Town Obelisk (Town) - Entry - True:
|
||||||
@@ -637,9 +641,13 @@ Door - 0x3CCDF (Exit Right) - 0x33AB2
|
|||||||
159556 - 0x33A2A (Door EP) - 0x03553 - True
|
159556 - 0x33A2A (Door EP) - 0x03553 - True
|
||||||
159558 - 0x33B06 (Church EP) - 0x0354E - True
|
159558 - 0x33B06 (Church EP) - 0x0354E - True
|
||||||
|
|
||||||
|
==Southern Peninsula==
|
||||||
|
|
||||||
|
Southern Peninsula (Southern Peninsula) - Main Island - True:
|
||||||
|
|
||||||
==Jungle==
|
==Jungle==
|
||||||
|
|
||||||
Jungle (Jungle) - Main Island - True - The Ocean - 0x17CDF:
|
Jungle (Jungle) - Main Island - True - The Ocean - 0x17CDF - Jungle Under Popup Wall - 0x1475B:
|
||||||
158251 - 0x17CDF (Shore Boat Spawn) - True - Boat
|
158251 - 0x17CDF (Shore Boat Spawn) - True - Boat
|
||||||
158609 - 0x17F9B (Discard) - True - Triangles
|
158609 - 0x17F9B (Discard) - True - Triangles
|
||||||
158252 - 0x002C4 (First Row 1) - True - True
|
158252 - 0x002C4 (First Row 1) - True - True
|
||||||
@@ -670,6 +678,8 @@ Door - 0x3873B (Laser Shortcut) - 0x337FA
|
|||||||
159350 - 0x035CB (Bamboo CCW EP) - True - True
|
159350 - 0x035CB (Bamboo CCW EP) - True - True
|
||||||
159351 - 0x035CF (Bamboo CW EP) - True - True
|
159351 - 0x035CF (Bamboo CW EP) - True - True
|
||||||
|
|
||||||
|
Jungle Under Popup Wall (Jungle):
|
||||||
|
|
||||||
Outside Jungle River (Jungle) - Main Island - True - Monastery Garden - 0x0CF2A - Jungle Vault - 0x15287:
|
Outside Jungle River (Jungle) - Main Island - True - Monastery Garden - 0x0CF2A - Jungle Vault - 0x15287:
|
||||||
158267 - 0x17CAA (Monastery Garden Shortcut Panel) - True - True
|
158267 - 0x17CAA (Monastery Garden Shortcut Panel) - True - True
|
||||||
Door - 0x0CF2A (Monastery Garden Shortcut) - 0x17CAA
|
Door - 0x0CF2A (Monastery Garden Shortcut) - 0x17CAA
|
||||||
@@ -712,9 +722,11 @@ Bunker Ultraviolet Room (Bunker) - Bunker Elevator Section - 0x0A08D:
|
|||||||
158285 - 0x17E67 (UV Room 2) - 0x17E63 & 0x34BC6 - Colored Squares & Black/White Squares
|
158285 - 0x17E67 (UV Room 2) - 0x17E63 & 0x34BC6 - Colored Squares & Black/White Squares
|
||||||
Door - 0x0A08D (Elevator Room Entry) - 0x17E67
|
Door - 0x0A08D (Elevator Room Entry) - 0x17E67
|
||||||
|
|
||||||
Bunker Elevator Section (Bunker) - Bunker Elevator - TrueOneWay:
|
Bunker Elevator Section (Bunker) - Bunker Elevator - TrueOneWay - Bunker Under Elevator - 0x0A079 | Bunker Green Room | Bunker Cyan Room | Bunker Laser Platform:
|
||||||
159311 - 0x035F5 (Tinted Door EP) - 0x17C79 - True
|
159311 - 0x035F5 (Tinted Door EP) - 0x17C79 - True
|
||||||
|
|
||||||
|
Bunker Under Elevator (Bunker):
|
||||||
|
|
||||||
Bunker Elevator (Bunker) - Bunker Elevator Section - 0x0A079 - Bunker Cyan Room - 0x0A079 - Bunker Green Room - 0x0A079 - Bunker Laser Platform - 0x0A079 - Outside Bunker - 0x0A079:
|
Bunker Elevator (Bunker) - Bunker Elevator Section - 0x0A079 - Bunker Cyan Room - 0x0A079 - Bunker Green Room - 0x0A079 - Bunker Laser Platform - 0x0A079 - Outside Bunker - 0x0A079:
|
||||||
158286 - 0x0A079 (Elevator Control) - True - Colored Squares & Black/White Squares
|
158286 - 0x0A079 (Elevator Control) - True - Colored Squares & Black/White Squares
|
||||||
|
|
||||||
@@ -1005,7 +1017,7 @@ Mountaintop (Mountaintop) - Mountain Floor 1 - 0x17C34:
|
|||||||
Mountain Floor 1 (Mountain Floor 1) - Mountain Floor 1 Bridge - 0x09E39:
|
Mountain Floor 1 (Mountain Floor 1) - Mountain Floor 1 Bridge - 0x09E39:
|
||||||
158408 - 0x09E39 (Light Bridge Controller) - True - Black/White Squares & Rotated Shapers
|
158408 - 0x09E39 (Light Bridge Controller) - True - Black/White Squares & Rotated Shapers
|
||||||
|
|
||||||
Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneWay:
|
Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneWay - Mountain Floor 1 Trash Pillar - TrueOneWay - Mountain Floor 1 Back Section - TrueOneWay:
|
||||||
158409 - 0x09E7A (Right Row 1) - True - Black/White Squares & Dots
|
158409 - 0x09E7A (Right Row 1) - True - Black/White Squares & Dots
|
||||||
158410 - 0x09E71 (Right Row 2) - 0x09E7A - Black/White Squares & Dots
|
158410 - 0x09E71 (Right Row 2) - 0x09E7A - Black/White Squares & Dots
|
||||||
158411 - 0x09E72 (Right Row 3) - 0x09E71 - Black/White Squares & Shapers
|
158411 - 0x09E72 (Right Row 3) - 0x09E71 - Black/White Squares & Shapers
|
||||||
@@ -1018,11 +1030,15 @@ Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneW
|
|||||||
158418 - 0x09E6C (Left Row 5) - 0x09E79 - Stars & Black/White Squares
|
158418 - 0x09E6C (Left Row 5) - 0x09E79 - Stars & Black/White Squares
|
||||||
158419 - 0x09E6F (Left Row 6) - 0x09E6C - Shapers & Dots
|
158419 - 0x09E6F (Left Row 6) - 0x09E6C - Shapers & Dots
|
||||||
158420 - 0x09E6B (Left Row 7) - 0x09E6F - Dots
|
158420 - 0x09E6B (Left Row 7) - 0x09E6F - Dots
|
||||||
|
158424 - 0x09EAD (Trash Pillar 1) - True - Black/White Squares & Shapers
|
||||||
|
158425 - 0x09EAF (Trash Pillar 2) - 0x09EAD - Black/White Squares & Shapers
|
||||||
|
|
||||||
|
Mountain Floor 1 Trash Pillar (Mountain Floor 1):
|
||||||
|
|
||||||
|
Mountain Floor 1 Back Section (Mountain Floor 1):
|
||||||
158421 - 0x33AF5 (Back Row 1) - True - Black/White Squares & Symmetry
|
158421 - 0x33AF5 (Back Row 1) - True - Black/White Squares & Symmetry
|
||||||
158422 - 0x33AF7 (Back Row 2) - 0x33AF5 - Black/White Squares
|
158422 - 0x33AF7 (Back Row 2) - 0x33AF5 - Black/White Squares
|
||||||
158423 - 0x09F6E (Back Row 3) - 0x33AF7 - Symmetry & Dots
|
158423 - 0x09F6E (Back Row 3) - 0x33AF7 - Symmetry & Dots
|
||||||
158424 - 0x09EAD (Trash Pillar 1) - True - Black/White Squares & Shapers
|
|
||||||
158425 - 0x09EAF (Trash Pillar 2) - 0x09EAD - Black/White Squares & Shapers
|
|
||||||
|
|
||||||
Mountain Floor 1 At Door (Mountain Floor 1) - Mountain Floor 2 - 0x09E54:
|
Mountain Floor 1 At Door (Mountain Floor 1) - Mountain Floor 2 - 0x09E54:
|
||||||
Door - 0x09E54 (Exit) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
|
Door - 0x09E54 (Exit) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
|
||||||
@@ -1098,14 +1114,16 @@ Elevator (Mountain Bottom Floor):
|
|||||||
Mountain Pink Bridge EP (Mountain Floor 2):
|
Mountain Pink Bridge EP (Mountain Floor 2):
|
||||||
159312 - 0x09D63 (Pink Bridge EP) - 0x09E39 - True
|
159312 - 0x09D63 (Pink Bridge EP) - 0x09E39 - True
|
||||||
|
|
||||||
Mountain Path to Caves (Mountain Bottom Floor) - Caves - 0x2D77D:
|
Mountain Path to Caves (Mountain Bottom Floor) - Caves - 0x2D77D - Caves Entry Door - TrueOneWay:
|
||||||
158447 - 0x00FF8 (Caves Entry Panel) - True - Black/White Squares
|
158447 - 0x00FF8 (Caves Entry Panel) - True - Black/White Squares
|
||||||
Door - 0x2D77D (Caves Entry) - 0x00FF8
|
Door - 0x2D77D (Caves Entry) - 0x00FF8
|
||||||
158448 - 0x334E1 (Rock Control) - True - True
|
158448 - 0x334E1 (Rock Control) - True - True
|
||||||
|
|
||||||
==Caves==
|
==Caves==
|
||||||
|
|
||||||
Caves (Caves) - Main Island - 0x2D73F | 0x2D859 - Caves Path to Challenge - 0x019A5:
|
Caves Entry Door (Caves):
|
||||||
|
|
||||||
|
Caves (Caves) - Main Island - 0x2D73F | 0x2D859 - Caves Path to Challenge - 0x019A5 - Caves Entry Door - TrueOneWay:
|
||||||
158451 - 0x335AB (Elevator Inside Control) - True - Dots & Black/White Squares
|
158451 - 0x335AB (Elevator Inside Control) - True - Dots & Black/White Squares
|
||||||
158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Black/White Squares
|
158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Black/White Squares
|
||||||
158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Black/White Squares & Dots
|
158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Black/White Squares & Dots
|
||||||
@@ -1219,3 +1237,7 @@ The Ocean (Boat) - Main Island - TrueOneWay - Swamp Near Boat - TrueOneWay - Tre
|
|||||||
159521 - 0x33879 (Tutorial Reflection EP) - True - True
|
159521 - 0x33879 (Tutorial Reflection EP) - True - True
|
||||||
159522 - 0x03C19 (Tutorial Moss EP) - True - True
|
159522 - 0x03C19 (Tutorial Moss EP) - True - True
|
||||||
159531 - 0x035C9 (Cargo Box EP) - 0x0A0C9 - True
|
159531 - 0x035C9 (Cargo Box EP) - 0x0A0C9 - True
|
||||||
|
|
||||||
|
==Easter Eggs==
|
||||||
|
|
||||||
|
Easter Eggs (Easter Eggs) - Entry - True:
|
||||||
|
@@ -206,7 +206,7 @@ Door - 0x0A24B (Flood Room Entry) - 0x0A249
|
|||||||
159043 - 0x0A14C (Pond Room Near Reflection EP) - True - True
|
159043 - 0x0A14C (Pond Room Near Reflection EP) - True - True
|
||||||
159044 - 0x0A14D (Pond Room Far Reflection EP) - True - True
|
159044 - 0x0A14D (Pond Room Far Reflection EP) - True - True
|
||||||
|
|
||||||
Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316:
|
Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316 - Desert Flood Room Underwater - 0x1C260:
|
||||||
158097 - 0x1C2DF (Reduce Water Level Far Left) - True - True
|
158097 - 0x1C2DF (Reduce Water Level Far Left) - True - True
|
||||||
158098 - 0x1831E (Reduce Water Level Far Right) - True - True
|
158098 - 0x1831E (Reduce Water Level Far Right) - True - True
|
||||||
158099 - 0x1C260 (Reduce Water Level Near Left) - True - True
|
158099 - 0x1C260 (Reduce Water Level Near Left) - True - True
|
||||||
@@ -224,6 +224,8 @@ Desert Flood Room (Desert) - Desert Elevator Room - 0x0C316:
|
|||||||
Door - 0x0C316 (Elevator Room Entry) - 0x18076
|
Door - 0x0C316 (Elevator Room Entry) - 0x18076
|
||||||
159034 - 0x337F8 (Flood Room EP) - 0x1C2DF - True
|
159034 - 0x337F8 (Flood Room EP) - 0x1C2DF - True
|
||||||
|
|
||||||
|
Desert Flood Room Underwater (Desert):
|
||||||
|
|
||||||
Desert Elevator Room (Desert) - Desert Behind Elevator - 0x01317:
|
Desert Elevator Room (Desert) - Desert Behind Elevator - 0x01317:
|
||||||
158111 - 0x17C31 (Elevator Room Transparent) - True - True
|
158111 - 0x17C31 (Elevator Room Transparent) - True - True
|
||||||
158113 - 0x012D7 (Elevator Room Hexagonal) - 0x17C31 & 0x0A015 - True
|
158113 - 0x012D7 (Elevator Room Hexagonal) - 0x17C31 & 0x0A015 - True
|
||||||
@@ -501,7 +503,7 @@ Laser - 0x17C65 (Laser) - 0x17CA4
|
|||||||
159121 - 0x03BE3 (Garden Right EP) - True - True
|
159121 - 0x03BE3 (Garden Right EP) - True - True
|
||||||
159122 - 0x0A409 (Wall EP) - True - True
|
159122 - 0x0A409 (Wall EP) - True - True
|
||||||
|
|
||||||
Inside Monastery (Monastery):
|
Inside Monastery (Monastery) - Monastery North Shutters - 0x09D9B:
|
||||||
158213 - 0x09D9B (Shutters Control) - True - Dots
|
158213 - 0x09D9B (Shutters Control) - True - Dots
|
||||||
158214 - 0x193A7 (Inside 1) - 0x00037 - True
|
158214 - 0x193A7 (Inside 1) - 0x00037 - True
|
||||||
158215 - 0x193AA (Inside 2) - 0x193A7 - True
|
158215 - 0x193AA (Inside 2) - 0x193A7 - True
|
||||||
@@ -513,6 +515,8 @@ Inside Monastery (Monastery):
|
|||||||
|
|
||||||
Monastery Garden (Monastery):
|
Monastery Garden (Monastery):
|
||||||
|
|
||||||
|
Monastery North Shutters (Monastery):
|
||||||
|
|
||||||
==Town==
|
==Town==
|
||||||
|
|
||||||
Town Obelisk (Town) - Entry - True:
|
Town Obelisk (Town) - Entry - True:
|
||||||
@@ -637,9 +641,13 @@ Door - 0x3CCDF (Exit Right) - 0x33AB2
|
|||||||
159556 - 0x33A2A (Door EP) - 0x03553 - True
|
159556 - 0x33A2A (Door EP) - 0x03553 - True
|
||||||
159558 - 0x33B06 (Church EP) - 0x0354E - True
|
159558 - 0x33B06 (Church EP) - 0x0354E - True
|
||||||
|
|
||||||
|
==Southern Peninsula==
|
||||||
|
|
||||||
|
Southern Peninsula (Southern Peninsula) - Main Island - True:
|
||||||
|
|
||||||
==Jungle==
|
==Jungle==
|
||||||
|
|
||||||
Jungle (Jungle) - Main Island - True - The Ocean - 0x17CDF:
|
Jungle (Jungle) - Main Island - True - The Ocean - 0x17CDF - Jungle Under Popup Wall - 0x1475B:
|
||||||
158251 - 0x17CDF (Shore Boat Spawn) - True - Boat
|
158251 - 0x17CDF (Shore Boat Spawn) - True - Boat
|
||||||
158609 - 0x17F9B (Discard) - True - Arrows & Triangles
|
158609 - 0x17F9B (Discard) - True - Arrows & Triangles
|
||||||
158252 - 0x002C4 (First Row 1) - True - True
|
158252 - 0x002C4 (First Row 1) - True - True
|
||||||
@@ -670,6 +678,8 @@ Door - 0x3873B (Laser Shortcut) - 0x337FA
|
|||||||
159350 - 0x035CB (Bamboo CCW EP) - True - True
|
159350 - 0x035CB (Bamboo CCW EP) - True - True
|
||||||
159351 - 0x035CF (Bamboo CW EP) - True - True
|
159351 - 0x035CF (Bamboo CW EP) - True - True
|
||||||
|
|
||||||
|
Jungle Under Popup Wall (Jungle):
|
||||||
|
|
||||||
Outside Jungle River (Jungle) - Main Island - True - Monastery Garden - 0x0CF2A - Jungle Vault - 0x15287:
|
Outside Jungle River (Jungle) - Main Island - True - Monastery Garden - 0x0CF2A - Jungle Vault - 0x15287:
|
||||||
158267 - 0x17CAA (Monastery Garden Shortcut Panel) - True - True
|
158267 - 0x17CAA (Monastery Garden Shortcut Panel) - True - True
|
||||||
Door - 0x0CF2A (Monastery Garden Shortcut) - 0x17CAA
|
Door - 0x0CF2A (Monastery Garden Shortcut) - 0x17CAA
|
||||||
@@ -712,9 +722,11 @@ Bunker Ultraviolet Room (Bunker) - Bunker Elevator Section - 0x0A08D:
|
|||||||
158285 - 0x17E67 (UV Room 2) - 0x17E63 & 0x34BC6 - Colored Squares & Black/White Squares
|
158285 - 0x17E67 (UV Room 2) - 0x17E63 & 0x34BC6 - Colored Squares & Black/White Squares
|
||||||
Door - 0x0A08D (Elevator Room Entry) - 0x17E67
|
Door - 0x0A08D (Elevator Room Entry) - 0x17E67
|
||||||
|
|
||||||
Bunker Elevator Section (Bunker) - Bunker Elevator - TrueOneWay:
|
Bunker Elevator Section (Bunker) - Bunker Elevator - TrueOneWay - Bunker Under Elevator - 0x0A079 | Bunker Green Room | Bunker Cyan Room | Bunker Laser Platform:
|
||||||
159311 - 0x035F5 (Tinted Door EP) - 0x17C79 - True
|
159311 - 0x035F5 (Tinted Door EP) - 0x17C79 - True
|
||||||
|
|
||||||
|
Bunker Under Elevator (Bunker):
|
||||||
|
|
||||||
Bunker Elevator (Bunker) - Bunker Elevator Section - 0x0A079 - Bunker Cyan Room - 0x0A079 - Bunker Green Room - 0x0A079 - Bunker Laser Platform - 0x0A079 - Outside Bunker - 0x0A079:
|
Bunker Elevator (Bunker) - Bunker Elevator Section - 0x0A079 - Bunker Cyan Room - 0x0A079 - Bunker Green Room - 0x0A079 - Bunker Laser Platform - 0x0A079 - Outside Bunker - 0x0A079:
|
||||||
158286 - 0x0A079 (Elevator Control) - True - Colored Squares & Black/White Squares
|
158286 - 0x0A079 (Elevator Control) - True - Colored Squares & Black/White Squares
|
||||||
|
|
||||||
@@ -1005,7 +1017,7 @@ Mountaintop (Mountaintop) - Mountain Floor 1 - 0x17C34:
|
|||||||
Mountain Floor 1 (Mountain Floor 1) - Mountain Floor 1 Bridge - 0x09E39:
|
Mountain Floor 1 (Mountain Floor 1) - Mountain Floor 1 Bridge - 0x09E39:
|
||||||
158408 - 0x09E39 (Light Bridge Controller) - True - Black/White Squares & Colored Squares & Eraser
|
158408 - 0x09E39 (Light Bridge Controller) - True - Black/White Squares & Colored Squares & Eraser
|
||||||
|
|
||||||
Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneWay:
|
Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneWay - Mountain Floor 1 Trash Pillar - TrueOneWay - Mountain Floor 1 Back Section - TrueOneWay:
|
||||||
158409 - 0x09E7A (Right Row 1) - True - Black/White Squares & Dots
|
158409 - 0x09E7A (Right Row 1) - True - Black/White Squares & Dots
|
||||||
158410 - 0x09E71 (Right Row 2) - 0x09E7A - Black/White Squares & Dots & Stars & Stars + Same Colored Symbol
|
158410 - 0x09E71 (Right Row 2) - 0x09E7A - Black/White Squares & Dots & Stars & Stars + Same Colored Symbol
|
||||||
158411 - 0x09E72 (Right Row 3) - 0x09E71 - Black/White Squares & Shapers & Stars & Stars + Same Colored Symbol
|
158411 - 0x09E72 (Right Row 3) - 0x09E71 - Black/White Squares & Shapers & Stars & Stars + Same Colored Symbol
|
||||||
@@ -1018,11 +1030,15 @@ Mountain Floor 1 Bridge (Mountain Floor 1) - Mountain Floor 1 At Door - TrueOneW
|
|||||||
158418 - 0x09E6C (Left Row 5) - 0x09E79 - Arrows & Black/White Squares & Stars & Stars + Same Colored Symbol
|
158418 - 0x09E6C (Left Row 5) - 0x09E79 - Arrows & Black/White Squares & Stars & Stars + Same Colored Symbol
|
||||||
158419 - 0x09E6F (Left Row 6) - 0x09E6C - Arrows & Dots & Full Dots
|
158419 - 0x09E6F (Left Row 6) - 0x09E6C - Arrows & Dots & Full Dots
|
||||||
158420 - 0x09E6B (Left Row 7) - 0x09E6F - Arrows & Dots & Full Dots
|
158420 - 0x09E6B (Left Row 7) - 0x09E6F - Arrows & Dots & Full Dots
|
||||||
|
158424 - 0x09EAD (Trash Pillar 1) - True - Triangles & Arrows
|
||||||
|
158425 - 0x09EAF (Trash Pillar 2) - 0x09EAD - Triangles & Arrows
|
||||||
|
|
||||||
|
Mountain Floor 1 Trash Pillar (Mountain Floor 1):
|
||||||
|
|
||||||
|
Mountain Floor 1 Back Section (Mountain Floor 1):
|
||||||
158421 - 0x33AF5 (Back Row 1) - True - Symmetry & Triangles
|
158421 - 0x33AF5 (Back Row 1) - True - Symmetry & Triangles
|
||||||
158422 - 0x33AF7 (Back Row 2) - 0x33AF5 - Triangles
|
158422 - 0x33AF7 (Back Row 2) - 0x33AF5 - Triangles
|
||||||
158423 - 0x09F6E (Back Row 3) - 0x33AF7 - Symmetry & Triangles
|
158423 - 0x09F6E (Back Row 3) - 0x33AF7 - Symmetry & Triangles
|
||||||
158424 - 0x09EAD (Trash Pillar 1) - True - Triangles & Arrows
|
|
||||||
158425 - 0x09EAF (Trash Pillar 2) - 0x09EAD - Triangles & Arrows
|
|
||||||
|
|
||||||
Mountain Floor 1 At Door (Mountain Floor 1) - Mountain Floor 2 - 0x09E54:
|
Mountain Floor 1 At Door (Mountain Floor 1) - Mountain Floor 2 - 0x09E54:
|
||||||
Door - 0x09E54 (Exit) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
|
Door - 0x09E54 (Exit) - 0x09EAF & 0x09F6E & 0x09E6B & 0x09E7B
|
||||||
@@ -1098,14 +1114,16 @@ Elevator (Mountain Bottom Floor):
|
|||||||
Mountain Pink Bridge EP (Mountain Floor 2):
|
Mountain Pink Bridge EP (Mountain Floor 2):
|
||||||
159312 - 0x09D63 (Pink Bridge EP) - 0x09E39 - True
|
159312 - 0x09D63 (Pink Bridge EP) - 0x09E39 - True
|
||||||
|
|
||||||
Mountain Path to Caves (Mountain Bottom Floor) - Caves - 0x2D77D:
|
Mountain Path to Caves (Mountain Bottom Floor) - Caves - 0x2D77D - Caves Entry Door - TrueOneWay:
|
||||||
158447 - 0x00FF8 (Caves Entry Panel) - True - Black/White Squares & Arrows & Triangles
|
158447 - 0x00FF8 (Caves Entry Panel) - True - Black/White Squares & Arrows & Triangles
|
||||||
Door - 0x2D77D (Caves Entry) - 0x00FF8
|
Door - 0x2D77D (Caves Entry) - 0x00FF8
|
||||||
158448 - 0x334E1 (Rock Control) - True - True
|
158448 - 0x334E1 (Rock Control) - True - True
|
||||||
|
|
||||||
==Caves==
|
==Caves==
|
||||||
|
|
||||||
Caves (Caves) - Main Island - 0x2D73F | 0x2D859 - Caves Path to Challenge - 0x019A5:
|
Caves Entry Door (Caves):
|
||||||
|
|
||||||
|
Caves (Caves) - Main Island - 0x2D73F | 0x2D859 - Caves Path to Challenge - 0x019A5 - Caves Entry Door - TrueOneWay:
|
||||||
158451 - 0x335AB (Elevator Inside Control) - True - Dots & Black/White Squares
|
158451 - 0x335AB (Elevator Inside Control) - True - Dots & Black/White Squares
|
||||||
158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Black/White Squares
|
158452 - 0x335AC (Elevator Upper Outside Control) - 0x335AB - Black/White Squares
|
||||||
158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Black/White Squares & Dots
|
158453 - 0x3369D (Elevator Lower Outside Control) - 0x335AB - Black/White Squares & Dots
|
||||||
@@ -1219,3 +1237,7 @@ The Ocean (Boat) - Main Island - TrueOneWay - Swamp Near Boat - TrueOneWay - Tre
|
|||||||
159521 - 0x33879 (Tutorial Reflection EP) - True - True
|
159521 - 0x33879 (Tutorial Reflection EP) - True - True
|
||||||
159522 - 0x03C19 (Tutorial Moss EP) - True - True
|
159522 - 0x03C19 (Tutorial Moss EP) - True - True
|
||||||
159531 - 0x035C9 (Cargo Box EP) - 0x0A0C9 - True
|
159531 - 0x035C9 (Cargo Box EP) - 0x0A0C9 - True
|
||||||
|
|
||||||
|
==Easter Eggs==
|
||||||
|
|
||||||
|
Easter Eggs (Easter Eggs) - Entry - True:
|
||||||
|
75
worlds/witness/data/settings/easter_eggs.py
Normal file
75
worlds/witness/data/settings/easter_eggs.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
MAXIMUM_EASTER_EGG_CHECKS = 50
|
||||||
|
|
||||||
|
EASTER_EGGS = {
|
||||||
|
"Tutorial": 1,
|
||||||
|
"Outside Tutorial": 4,
|
||||||
|
"Outside Tutorial Path To Outpost": 1,
|
||||||
|
"Outside Tutorial Outpost": 1,
|
||||||
|
"Orchard Beyond First Gate": 1,
|
||||||
|
"Orchard End": 1,
|
||||||
|
"Inside Glass Factory": 2,
|
||||||
|
"Symmetry Island Lower": 2,
|
||||||
|
"Symmetry Island Upper": 1,
|
||||||
|
"Desert Outside": 6,
|
||||||
|
"Desert Vault": 1,
|
||||||
|
"Desert Pond Room": 2,
|
||||||
|
"Desert Flood Room Underwater": 1,
|
||||||
|
"Desert Elevator Room": 1,
|
||||||
|
"Outside Quarry": 2,
|
||||||
|
"Quarry": 5,
|
||||||
|
"Quarry Stoneworks Upper Floor": 2,
|
||||||
|
"Quarry Boathouse": 2,
|
||||||
|
"Shadows": 2,
|
||||||
|
"Shadows Ledge": 1,
|
||||||
|
"Shadows Laser Room": 1,
|
||||||
|
"Keep": 1,
|
||||||
|
"Keep 3rd Maze": 3,
|
||||||
|
"Keep 2nd Pressure Plate": 2,
|
||||||
|
"Keep 3rd Pressure Plate": 1,
|
||||||
|
"Keep 4th Pressure Plate": 1,
|
||||||
|
"Keep Tower": 2,
|
||||||
|
"Shipwreck": 5,
|
||||||
|
"Inside Monastery": 1,
|
||||||
|
"Monastery North Shutters": 1,
|
||||||
|
"Monastery Garden": 1,
|
||||||
|
"Town": 5,
|
||||||
|
"Town Wooden Rooftop": 1,
|
||||||
|
"Town RGB House": 2,
|
||||||
|
"Town Tower Top": 1,
|
||||||
|
"Windmill Interior": 2,
|
||||||
|
"Theater": 1,
|
||||||
|
"Southern Peninsula": 5,
|
||||||
|
"Jungle": 2,
|
||||||
|
"Jungle Under Popup Wall": 1,
|
||||||
|
"Jungle Vault": 1,
|
||||||
|
"Outside Bunker": 3,
|
||||||
|
"Bunker Glass Room": 1,
|
||||||
|
"Bunker Under Elevator": 1,
|
||||||
|
"Bunker Green Room": 1,
|
||||||
|
"Outside Swamp": 2,
|
||||||
|
"Swamp Entry Area": 1,
|
||||||
|
"Swamp Platform": 1,
|
||||||
|
"Swamp Cyan Underwater": 1,
|
||||||
|
"Swamp Near Boat": 1,
|
||||||
|
"Swamp Laser Area": 1,
|
||||||
|
"Treehouse Beach": 1,
|
||||||
|
"Treehouse Yellow Bridge": 1,
|
||||||
|
"Treehouse Junction": 2,
|
||||||
|
"Treehouse Second Purple Bridge": 1,
|
||||||
|
"Treehouse Green Bridge Left House": 1,
|
||||||
|
"Treehouse Laser Room Back Platform": 1,
|
||||||
|
"Treehouse Burned House": 1,
|
||||||
|
"Treehouse Drawbridge Platform": 1,
|
||||||
|
"Mountainside": 4,
|
||||||
|
"Mountaintop": 1,
|
||||||
|
"Mountain Floor 1 Trash Pillar": 1,
|
||||||
|
"Mountain Floor 1 Back Section": 1,
|
||||||
|
"Mountain Floor 2": 1,
|
||||||
|
"Mountain Bottom Floor Pillars Room": 1,
|
||||||
|
"Caves Entry Door": 1,
|
||||||
|
"Caves": 2,
|
||||||
|
"Caves Path to Challenge": 1,
|
||||||
|
"Challenge": 2,
|
||||||
|
"Tunnels": 2,
|
||||||
|
"The Ocean": 2,
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
from collections import defaultdict
|
from collections import Counter, defaultdict
|
||||||
from typing import Any, Dict, List, Optional, Set, Tuple
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
||||||
|
|
||||||
from Utils import cache_argsless
|
from Utils import cache_argsless
|
||||||
@@ -11,6 +11,7 @@ from .item_definition_classes import (
|
|||||||
ProgressiveItemDefinition,
|
ProgressiveItemDefinition,
|
||||||
WeightedItemDefinition,
|
WeightedItemDefinition,
|
||||||
)
|
)
|
||||||
|
from .settings.easter_eggs import EASTER_EGGS
|
||||||
from .utils import (
|
from .utils import (
|
||||||
WitnessRule,
|
WitnessRule,
|
||||||
define_new_region,
|
define_new_region,
|
||||||
@@ -49,6 +50,70 @@ class StaticWitnessLogicObj:
|
|||||||
self.reverse_connections()
|
self.reverse_connections()
|
||||||
self.combine_connections()
|
self.combine_connections()
|
||||||
|
|
||||||
|
def add_easter_eggs(self) -> None:
|
||||||
|
egg_counter = 0
|
||||||
|
area_counts: Dict[str, int] = Counter()
|
||||||
|
for region_name, entity_amount in EASTER_EGGS.items():
|
||||||
|
region_object = self.ALL_REGIONS_BY_NAME[region_name]
|
||||||
|
correct_area = region_object["area"]
|
||||||
|
|
||||||
|
for _ in range(entity_amount):
|
||||||
|
location_id = 160200 + egg_counter
|
||||||
|
entity_hex = hex(0xEE000 + egg_counter)
|
||||||
|
egg_counter += 1
|
||||||
|
|
||||||
|
area_counts[correct_area["name"]] += 1
|
||||||
|
full_entity_name = f"{correct_area['name']} Easter Egg {area_counts[correct_area['name']]}"
|
||||||
|
|
||||||
|
self.ENTITIES_BY_HEX[entity_hex] = {
|
||||||
|
"checkName": full_entity_name,
|
||||||
|
"entity_hex": entity_hex,
|
||||||
|
"region": region_object,
|
||||||
|
"id": int(location_id),
|
||||||
|
"entityType": "Easter Egg",
|
||||||
|
"locationType": "Easter Egg",
|
||||||
|
"area": correct_area,
|
||||||
|
"order": len(self.ENTITIES_BY_HEX),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ENTITIES_BY_NAME[self.ENTITIES_BY_HEX[entity_hex]["checkName"]] = self.ENTITIES_BY_HEX[entity_hex]
|
||||||
|
|
||||||
|
self.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX[entity_hex] = {
|
||||||
|
"entities": frozenset({frozenset({})})
|
||||||
|
}
|
||||||
|
region_object["entities"].append(entity_hex)
|
||||||
|
region_object["physical_entities"].append(entity_hex)
|
||||||
|
|
||||||
|
easter_egg_region = self.ALL_REGIONS_BY_NAME["Easter Eggs"]
|
||||||
|
easter_egg_area = easter_egg_region["area"]
|
||||||
|
for i in range(sum(EASTER_EGGS.values())):
|
||||||
|
location_id = 160000 + i
|
||||||
|
entity_hex = hex(0xEE200 + i)
|
||||||
|
|
||||||
|
if i == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
full_entity_name = f"{i + 1} Easter Eggs Collected"
|
||||||
|
|
||||||
|
self.ENTITIES_BY_HEX[entity_hex] = {
|
||||||
|
"checkName": full_entity_name,
|
||||||
|
"entity_hex": entity_hex,
|
||||||
|
"region": easter_egg_region,
|
||||||
|
"id": int(location_id),
|
||||||
|
"entityType": "Easter Egg Total",
|
||||||
|
"locationType": "Easter Egg Total",
|
||||||
|
"area": easter_egg_area,
|
||||||
|
"order": len(self.ENTITIES_BY_HEX),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ENTITIES_BY_NAME[self.ENTITIES_BY_HEX[entity_hex]["checkName"]] = self.ENTITIES_BY_HEX[entity_hex]
|
||||||
|
|
||||||
|
self.STATIC_DEPENDENT_REQUIREMENTS_BY_HEX[entity_hex] = {
|
||||||
|
"entities": frozenset({frozenset({})})
|
||||||
|
}
|
||||||
|
easter_egg_region["entities"].append(entity_hex)
|
||||||
|
easter_egg_region["physical_entities"].append(entity_hex)
|
||||||
|
|
||||||
def read_logic_file(self, lines: List[str]) -> None:
|
def read_logic_file(self, lines: List[str]) -> None:
|
||||||
"""
|
"""
|
||||||
Reads the logic file and does the initial population of data structures
|
Reads the logic file and does the initial population of data structures
|
||||||
@@ -66,7 +131,7 @@ class StaticWitnessLogicObj:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if line[-1] == ":":
|
if line[-1] == ":":
|
||||||
new_region_and_connections = define_new_region(line)
|
new_region_and_connections = define_new_region(line, current_area)
|
||||||
current_region = new_region_and_connections[0]
|
current_region = new_region_and_connections[0]
|
||||||
region_name = current_region["name"]
|
region_name = current_region["name"]
|
||||||
self.ALL_REGIONS_BY_NAME[region_name] = current_region
|
self.ALL_REGIONS_BY_NAME[region_name] = current_region
|
||||||
@@ -198,6 +263,8 @@ class StaticWitnessLogicObj:
|
|||||||
current_region["entities"].append(entity_hex)
|
current_region["entities"].append(entity_hex)
|
||||||
current_region["physical_entities"].append(entity_hex)
|
current_region["physical_entities"].append(entity_hex)
|
||||||
|
|
||||||
|
self.add_easter_eggs()
|
||||||
|
|
||||||
def reverse_connection(self, source_region: str, connection: Tuple[str, Set[WitnessRule]]) -> None:
|
def reverse_connection(self, source_region: str, connection: Tuple[str, Set[WitnessRule]]) -> None:
|
||||||
target = connection[0]
|
target = connection[0]
|
||||||
traversal_options = connection[1]
|
traversal_options = connection[1]
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
from datetime import date
|
||||||
from math import floor
|
from math import floor
|
||||||
from pkgutil import get_data
|
from pkgutil import get_data
|
||||||
from random import Random
|
from random import Random
|
||||||
@@ -61,7 +62,7 @@ def build_weighted_int_list(inputs: Collection[float], total: int) -> List[int]:
|
|||||||
return rounded_output
|
return rounded_output
|
||||||
|
|
||||||
|
|
||||||
def define_new_region(region_string: str) -> Tuple[Dict[str, Any], Set[Tuple[str, WitnessRule]]]:
|
def define_new_region(region_string: str, area: dict[str, Any]) -> Tuple[Dict[str, Any], Set[Tuple[str, WitnessRule]]]:
|
||||||
"""
|
"""
|
||||||
Returns a region object by parsing a line in the logic file
|
Returns a region object by parsing a line in the logic file
|
||||||
"""
|
"""
|
||||||
@@ -91,6 +92,7 @@ def define_new_region(region_string: str) -> Tuple[Dict[str, Any], Set[Tuple[str
|
|||||||
"shortName": region_name_simple,
|
"shortName": region_name_simple,
|
||||||
"entities": [],
|
"entities": [],
|
||||||
"physical_entities": [],
|
"physical_entities": [],
|
||||||
|
"area": area,
|
||||||
}
|
}
|
||||||
return region_obj, options
|
return region_obj, options
|
||||||
|
|
||||||
@@ -264,3 +266,15 @@ def logical_and_witness_rules(witness_rules: Iterable[WitnessRule]) -> WitnessRu
|
|||||||
|
|
||||||
def logical_or_witness_rules(witness_rules: Iterable[WitnessRule]) -> WitnessRule:
|
def logical_or_witness_rules(witness_rules: Iterable[WitnessRule]) -> WitnessRule:
|
||||||
return optimize_witness_rule(frozenset.union(*witness_rules))
|
return optimize_witness_rule(frozenset.union(*witness_rules))
|
||||||
|
|
||||||
|
|
||||||
|
def is_easter_time() -> bool:
|
||||||
|
# dateutils would have been nice here, because it has an easter() function.
|
||||||
|
# But adding it as a requirement seems heavier than necessary.
|
||||||
|
# Thus, we just take a range from the earliest to latest possible easter dates.
|
||||||
|
|
||||||
|
today = date.today()
|
||||||
|
earliest_easter_day = date(today.year, 3, 20) # Earliest possible is 3/22 + 2 day buffer for Good Friday
|
||||||
|
last_easter_day = date(today.year, 4, 26) # Latest possible is 4/25 + 1 day buffer for Easter Monday
|
||||||
|
|
||||||
|
return earliest_easter_day <= today <= last_easter_day
|
||||||
|
@@ -43,3 +43,12 @@ if __name__ == "__main__":
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
datafile.write("\n};\n\n")
|
datafile.write("\n};\n\n")
|
||||||
|
|
||||||
|
datafile.write("inline std::map<int, std::string> entityToName = {")
|
||||||
|
datafile.write(
|
||||||
|
"\n".join(
|
||||||
|
"\t{ " + entity_hex + ', "' + entity_object["checkName"] + '" },'
|
||||||
|
for entity_hex, entity_object in static_witness_logic.ENTITIES_BY_HEX.items()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
datafile.write("\n};\n\n")
|
||||||
|
@@ -241,7 +241,10 @@ def word_direct_hint(world: "WitnessWorld", hint: WitnessLocationHint) -> Witnes
|
|||||||
area = chosen_group
|
area = chosen_group
|
||||||
|
|
||||||
# local locations should only ever return a location group, as Witness defines groups for every location.
|
# local locations should only ever return a location group, as Witness defines groups for every location.
|
||||||
hint_text = f"{item_name} can be found in the {area} area."
|
if area == "Easter Eggs":
|
||||||
|
hint_text = f"{item_name} can be found by collecting Easter Eggs."
|
||||||
|
else:
|
||||||
|
hint_text = f"{item_name} can be found in the {area} area."
|
||||||
else:
|
else:
|
||||||
player_name = world.multiworld.get_player_name(hint.location.player)
|
player_name = world.multiworld.get_player_name(hint.location.player)
|
||||||
|
|
||||||
@@ -505,10 +508,13 @@ def word_area_hint(world: "WitnessWorld", hinted_area: str, area_items: List[Ite
|
|||||||
|
|
||||||
area_progression_word = "Both" if total_progression == 2 else "All"
|
area_progression_word = "Both" if total_progression == 2 else "All"
|
||||||
|
|
||||||
hint_string = f"In the {hinted_area} area, you will find "
|
if hinted_area == "Easter Eggs":
|
||||||
|
hint_string = "Through collecting Easter Eggs, you will find "
|
||||||
|
else:
|
||||||
|
hint_string = f"In the {hinted_area} area, you will find "
|
||||||
|
|
||||||
hunt_panels = None
|
hunt_panels = None
|
||||||
if world.options.victory_condition == "panel_hunt":
|
if world.options.victory_condition == "panel_hunt" and hinted_area != "Easter Eggs":
|
||||||
hunt_panels = sum(
|
hunt_panels = sum(
|
||||||
static_witness_logic.ENTITIES_BY_HEX[hunt_entity]["area"]["name"] == hinted_area
|
static_witness_logic.ENTITIES_BY_HEX[hunt_entity]["area"]["name"] == hinted_area
|
||||||
for hunt_entity in world.player_logic.HUNT_ENTITIES
|
for hunt_entity in world.player_logic.HUNT_ENTITIES
|
||||||
|
@@ -19,7 +19,7 @@ class WitnessPlayerLocations:
|
|||||||
def __init__(self, world: "WitnessWorld", player_logic: WitnessPlayerLogic) -> None:
|
def __init__(self, world: "WitnessWorld", player_logic: WitnessPlayerLogic) -> None:
|
||||||
"""Defines locations AFTER logic changes due to options"""
|
"""Defines locations AFTER logic changes due to options"""
|
||||||
|
|
||||||
self.PANEL_TYPES_TO_SHUFFLE = {"General", "Good Boi"}
|
self.PANEL_TYPES_TO_SHUFFLE = {"General", "Good Boi", "Easter Egg Total"}
|
||||||
self.CHECK_LOCATIONS = static_witness_locations.GENERAL_LOCATIONS.copy()
|
self.CHECK_LOCATIONS = static_witness_locations.GENERAL_LOCATIONS.copy()
|
||||||
|
|
||||||
if world.options.shuffle_discarded_panels:
|
if world.options.shuffle_discarded_panels:
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
from schema import And, Schema
|
from schema import And, Schema
|
||||||
|
|
||||||
@@ -18,6 +20,7 @@ from Options import (
|
|||||||
|
|
||||||
from .data import static_logic as static_witness_logic
|
from .data import static_logic as static_witness_logic
|
||||||
from .data.item_definition_classes import ItemCategory, WeightedItemDefinition
|
from .data.item_definition_classes import ItemCategory, WeightedItemDefinition
|
||||||
|
from .data.utils import is_easter_time
|
||||||
from .entity_hunt import ALL_HUNTABLE_PANELS
|
from .entity_hunt import ALL_HUNTABLE_PANELS
|
||||||
|
|
||||||
|
|
||||||
@@ -142,6 +145,53 @@ class ShuffleEnvironmentalPuzzles(Choice):
|
|||||||
option_obelisk_sides = 2
|
option_obelisk_sides = 2
|
||||||
|
|
||||||
|
|
||||||
|
class EasterEggHunt(Choice):
|
||||||
|
"""
|
||||||
|
Adds up to 120 Easter Eggs to the game, placed by NewSoupVi, Exempt-Medic, hatkirby, Scipio, and Rever.
|
||||||
|
These can be collected by simply clicking on them.
|
||||||
|
|
||||||
|
The difficulty options differ by how many Eggs you need to collect for each check and how many are logically required for each check.
|
||||||
|
|
||||||
|
- "Easy": 3 / 8
|
||||||
|
- "Normal": 3 / 6
|
||||||
|
- "Hard": 4 / 6
|
||||||
|
- "Very Hard": 4 / 5
|
||||||
|
- "Extreme": 4 / 4 (You are expected to collect every Easter Egg)
|
||||||
|
|
||||||
|
Checks that require more Eggs than logically available still exist, but are excluded.
|
||||||
|
For example, on "Easy", the "63 Eggs Collected" check can physically be obtained, but would logically require 125 Easter Eggs, which is impossible. Thus, it is excluded.
|
||||||
|
|
||||||
|
On "Easy", "Normal", and "Hard", you will start with an "Egg Radar" that you can activate using the Puzzle Skip key.
|
||||||
|
On every difficulty except "Extreme", there will be a message when you've collected all Easter Eggs in an area.
|
||||||
|
On "Easy", there will be an additional message after every Easter Egg telling you how many Easter Eggs are remaining in the area.
|
||||||
|
|
||||||
|
It is recommended that you play this mode together with Door Shuffle. Without it, more than half of the Easter Eggs will be in sphere 1.
|
||||||
|
"""
|
||||||
|
|
||||||
|
visibility = Visibility.all if is_easter_time() else Visibility.none
|
||||||
|
|
||||||
|
display_name = "Easter Egg Hunt"
|
||||||
|
option_off = 0
|
||||||
|
# Number represents the amount of eggs needed per check
|
||||||
|
option_easy = 1
|
||||||
|
option_normal = 2
|
||||||
|
option_hard = 3
|
||||||
|
option_very_hard = 4
|
||||||
|
option_extreme = 5
|
||||||
|
default = 2 if is_easter_time() else 0
|
||||||
|
|
||||||
|
def get_step_and_logical_step(self) -> Tuple[int, int]:
|
||||||
|
if self == "easy":
|
||||||
|
return 3, 8
|
||||||
|
if self == "normal":
|
||||||
|
return 3, 6
|
||||||
|
if self == "hard":
|
||||||
|
return 4, 6
|
||||||
|
if self == "very_hard":
|
||||||
|
return 4, 5
|
||||||
|
return 4, 4
|
||||||
|
|
||||||
|
|
||||||
class ShuffleDog(Choice):
|
class ShuffleDog(Choice):
|
||||||
"""
|
"""
|
||||||
Adds petting the dog statue in Town into the location pool.
|
Adds petting the dog statue in Town into the location pool.
|
||||||
@@ -504,6 +554,7 @@ class TheWitnessOptions(PerGameCommonOptions):
|
|||||||
death_link_amnesty: DeathLinkAmnesty
|
death_link_amnesty: DeathLinkAmnesty
|
||||||
puzzle_randomization_seed: PuzzleRandomizationSeed
|
puzzle_randomization_seed: PuzzleRandomizationSeed
|
||||||
shuffle_dog: ShuffleDog
|
shuffle_dog: ShuffleDog
|
||||||
|
easter_egg_hunt: EasterEggHunt
|
||||||
|
|
||||||
|
|
||||||
witness_option_groups = [
|
witness_option_groups = [
|
||||||
@@ -561,3 +612,13 @@ witness_option_groups = [
|
|||||||
ShuffleDog,
|
ShuffleDog,
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Make sure that Easter Egg Hunt is VERY visible during easter time (when it's enabled by default)
|
||||||
|
if is_easter_time():
|
||||||
|
easter_special_option_group = OptionGroup("EASTER SPECIAL", [
|
||||||
|
EasterEggHunt,
|
||||||
|
])
|
||||||
|
witness_option_groups = [easter_special_option_group, *witness_option_groups]
|
||||||
|
else:
|
||||||
|
silly_options_group = next(group for group in witness_option_groups if group.name == "Silly Options")
|
||||||
|
silly_options_group.options.append(EasterEggHunt)
|
||||||
|
@@ -31,6 +31,13 @@ class WitnessItem(Item):
|
|||||||
Item from the game The Witness
|
Item from the game The Witness
|
||||||
"""
|
"""
|
||||||
game: str = "The Witness"
|
game: str = "The Witness"
|
||||||
|
eggs: int = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def make_egg_event(cls, item_name: str, player: int):
|
||||||
|
ret = cls(item_name, ItemClassification.progression, None, player)
|
||||||
|
ret.eggs = int(item_name[1:].split(" ", 1)[0])
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class WitnessPlayerItems:
|
class WitnessPlayerItems:
|
||||||
|
@@ -24,7 +24,6 @@ from .data.item_definition_classes import DoorItemDefinition, ItemCategory, Prog
|
|||||||
from .data.static_logic import StaticWitnessLogicObj
|
from .data.static_logic import StaticWitnessLogicObj
|
||||||
from .data.utils import (
|
from .data.utils import (
|
||||||
WitnessRule,
|
WitnessRule,
|
||||||
define_new_region,
|
|
||||||
get_boat,
|
get_boat,
|
||||||
get_caves_except_path_to_challenge_exclusion_list,
|
get_caves_except_path_to_challenge_exclusion_list,
|
||||||
get_complex_additional_panels,
|
get_complex_additional_panels,
|
||||||
@@ -119,6 +118,8 @@ class WitnessPlayerLogic:
|
|||||||
self.PRE_PICKED_HUNT_ENTITIES: Set[str] = set()
|
self.PRE_PICKED_HUNT_ENTITIES: Set[str] = set()
|
||||||
self.HUNT_ENTITIES: Set[str] = set()
|
self.HUNT_ENTITIES: Set[str] = set()
|
||||||
|
|
||||||
|
self.AVAILABLE_EASTER_EGGS: Set[str] = set()
|
||||||
|
self.AVAILABLE_EASTER_EGGS_PER_REGION: Dict[str, int] = {}
|
||||||
self.ALWAYS_EVENT_NAMES_BY_HEX = {
|
self.ALWAYS_EVENT_NAMES_BY_HEX = {
|
||||||
"0x00509": "+1 Laser",
|
"0x00509": "+1 Laser",
|
||||||
"0x012FB": "+1 Laser (Unredirected)",
|
"0x012FB": "+1 Laser (Unredirected)",
|
||||||
@@ -154,6 +155,9 @@ class WitnessPlayerLogic:
|
|||||||
picker = EntityHuntPicker(self, world, self.PRE_PICKED_HUNT_ENTITIES)
|
picker = EntityHuntPicker(self, world, self.PRE_PICKED_HUNT_ENTITIES)
|
||||||
self.HUNT_ENTITIES = picker.pick_panel_hunt_panels(world.options.panel_hunt_total.value)
|
self.HUNT_ENTITIES = picker.pick_panel_hunt_panels(world.options.panel_hunt_total.value)
|
||||||
|
|
||||||
|
if world.options.easter_egg_hunt:
|
||||||
|
self.finalize_easter_eggs(world)
|
||||||
|
|
||||||
# Finalize which items actually exist in the MultiWorld and which get grouped into progressive items.
|
# Finalize which items actually exist in the MultiWorld and which get grouped into progressive items.
|
||||||
self.finalize_items()
|
self.finalize_items()
|
||||||
|
|
||||||
@@ -241,6 +245,8 @@ class WitnessPlayerLogic:
|
|||||||
if option_entity in {"7 Lasers", "11 Lasers", "7 Lasers + Redirect", "11 Lasers + Redirect",
|
if option_entity in {"7 Lasers", "11 Lasers", "7 Lasers + Redirect", "11 Lasers + Redirect",
|
||||||
"PP2 Weirdness", "Theater to Tunnels", "Entity Hunt"}:
|
"PP2 Weirdness", "Theater to Tunnels", "Entity Hunt"}:
|
||||||
new_items = frozenset({frozenset([option_entity])})
|
new_items = frozenset({frozenset([option_entity])})
|
||||||
|
elif "Eggs" in option_entity:
|
||||||
|
new_items = frozenset({frozenset([option_entity])})
|
||||||
elif option_entity in self.DISABLE_EVERYTHING_BEHIND:
|
elif option_entity in self.DISABLE_EVERYTHING_BEHIND:
|
||||||
new_items = frozenset()
|
new_items = frozenset()
|
||||||
else:
|
else:
|
||||||
@@ -387,13 +393,6 @@ class WitnessPlayerLogic:
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if adj_type == "Region Changes":
|
|
||||||
new_region_and_options = define_new_region(line + ":")
|
|
||||||
|
|
||||||
self.CONNECTIONS_BY_REGION_NAME_THEORETICAL[new_region_and_options[0]["name"]] = new_region_and_options[1]
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
if adj_type == "New Connections":
|
if adj_type == "New Connections":
|
||||||
line_split = line.split(" - ")
|
line_split = line.split(" - ")
|
||||||
source_region = line_split[0]
|
source_region = line_split[0]
|
||||||
@@ -533,6 +532,55 @@ class WitnessPlayerLogic:
|
|||||||
|
|
||||||
return postgame_adjustments
|
return postgame_adjustments
|
||||||
|
|
||||||
|
def set_easter_egg_requirements(self, world: "WitnessWorld") -> None:
|
||||||
|
eggs_per_check, logically_required_eggs_per_check = world.options.easter_egg_hunt.get_step_and_logical_step()
|
||||||
|
|
||||||
|
for entity_hex, entity_obj in static_witness_logic.ENTITIES_BY_HEX.items():
|
||||||
|
if entity_obj["entityType"] != "Easter Egg Total":
|
||||||
|
continue
|
||||||
|
|
||||||
|
direct_egg_count = int(entity_obj["checkName"].split(" ")[0])
|
||||||
|
|
||||||
|
if direct_egg_count % eggs_per_check:
|
||||||
|
self.COMPLETELY_DISABLED_ENTITIES.add(entity_hex)
|
||||||
|
|
||||||
|
requirement = direct_egg_count // eggs_per_check * logically_required_eggs_per_check
|
||||||
|
self.DEPENDENT_REQUIREMENTS_BY_HEX[entity_hex] = {
|
||||||
|
"entities": frozenset({frozenset({f"{requirement} Eggs"})})
|
||||||
|
}
|
||||||
|
|
||||||
|
def finalize_easter_eggs(self, world: "WitnessWorld") -> None:
|
||||||
|
self.AVAILABLE_EASTER_EGGS = {
|
||||||
|
entity_hex for entity_hex, entity_obj in static_witness_logic.ENTITIES_BY_HEX.items()
|
||||||
|
if entity_obj["entityType"] == "Easter Egg" and self.solvability_guaranteed(entity_hex)
|
||||||
|
}
|
||||||
|
max_eggs = len(self.AVAILABLE_EASTER_EGGS)
|
||||||
|
|
||||||
|
self.AVAILABLE_EASTER_EGGS_PER_REGION = defaultdict(int)
|
||||||
|
for entity_hex in self.AVAILABLE_EASTER_EGGS:
|
||||||
|
region_name = static_witness_logic.ENTITIES_BY_HEX[entity_hex]["region"]["name"]
|
||||||
|
self.AVAILABLE_EASTER_EGGS_PER_REGION[region_name] += 1
|
||||||
|
|
||||||
|
eggs_per_check, logically_required_eggs_per_check = world.options.easter_egg_hunt.get_step_and_logical_step()
|
||||||
|
|
||||||
|
for entity_hex, entity_obj in static_witness_logic.ENTITIES_BY_HEX.items():
|
||||||
|
if entity_obj["entityType"] != "Easter Egg Total":
|
||||||
|
continue
|
||||||
|
if entity_hex in self.COMPLETELY_DISABLED_ENTITIES:
|
||||||
|
continue
|
||||||
|
|
||||||
|
direct_egg_count = int(entity_obj["checkName"].split(" ", 1)[0])
|
||||||
|
logically_required_egg_count = direct_egg_count // eggs_per_check * logically_required_eggs_per_check
|
||||||
|
if direct_egg_count > max_eggs:
|
||||||
|
self.COMPLETELY_DISABLED_ENTITIES.add(entity_hex)
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.ADDED_CHECKS.add(entity_obj["checkName"])
|
||||||
|
if logically_required_egg_count > max_eggs:
|
||||||
|
# Exclude and set logic to require every egg
|
||||||
|
self.EXCLUDED_ENTITIES.add(entity_hex)
|
||||||
|
self.REQUIREMENTS_BY_HEX[entity_hex] = frozenset({frozenset({f"{max_eggs} Eggs"})})
|
||||||
|
|
||||||
def make_options_adjustments(self, world: "WitnessWorld") -> None:
|
def make_options_adjustments(self, world: "WitnessWorld") -> None:
|
||||||
"""Makes logic adjustments based on options"""
|
"""Makes logic adjustments based on options"""
|
||||||
adjustment_linesets_in_order = []
|
adjustment_linesets_in_order = []
|
||||||
@@ -641,6 +689,8 @@ class WitnessPlayerLogic:
|
|||||||
adjustment_linesets_in_order.append([
|
adjustment_linesets_in_order.append([
|
||||||
"New Connections:",
|
"New Connections:",
|
||||||
"Outside Bunker - Bunker Elevator - TrueOneWay",
|
"Outside Bunker - Bunker Elevator - TrueOneWay",
|
||||||
|
"Bunker Elevator Section - Bunker Under Elevator - "
|
||||||
|
"0x0A079 | Bunker Green Room | Bunker Cyan Room | Bunker Laser Platform | Outside Bunker",
|
||||||
])
|
])
|
||||||
if "Swamp Long Bridge" in world.options.elevators_come_to_you:
|
if "Swamp Long Bridge" in world.options.elevators_come_to_you:
|
||||||
adjustment_linesets_in_order.append([
|
adjustment_linesets_in_order.append([
|
||||||
@@ -655,6 +705,14 @@ class WitnessPlayerLogic:
|
|||||||
# "New Connections:"
|
# "New Connections:"
|
||||||
# "Town Red Rooftop - Town Maze Rooftop - TrueOneWay"
|
# "Town Red Rooftop - Town Maze Rooftop - TrueOneWay"
|
||||||
|
|
||||||
|
if world.options.easter_egg_hunt:
|
||||||
|
self.set_easter_egg_requirements(world)
|
||||||
|
else:
|
||||||
|
self.COMPLETELY_DISABLED_ENTITIES.update({
|
||||||
|
entity_hex for entity_hex, entity_obj in static_witness_logic.ENTITIES_BY_HEX.items()
|
||||||
|
if "Easter Egg" in entity_obj["entityType"]
|
||||||
|
})
|
||||||
|
|
||||||
if world.options.victory_condition == "panel_hunt":
|
if world.options.victory_condition == "panel_hunt":
|
||||||
adjustment_linesets_in_order.append(get_entity_hunt())
|
adjustment_linesets_in_order.append(get_entity_hunt())
|
||||||
|
|
||||||
@@ -691,6 +749,9 @@ class WitnessPlayerLogic:
|
|||||||
if loc_obj["entityType"] == "EP":
|
if loc_obj["entityType"] == "EP":
|
||||||
self.COMPLETELY_DISABLED_ENTITIES.add(loc_obj["entity_hex"])
|
self.COMPLETELY_DISABLED_ENTITIES.add(loc_obj["entity_hex"])
|
||||||
|
|
||||||
|
if loc_obj["entityType"] == "Easter Egg":
|
||||||
|
self.COMPLETELY_DISABLED_ENTITIES.add(loc_obj["entity_hex"])
|
||||||
|
|
||||||
elif loc_obj["entityType"] == "Panel":
|
elif loc_obj["entityType"] == "Panel":
|
||||||
self.EXCLUDED_ENTITIES.add(loc_obj["entity_hex"])
|
self.EXCLUDED_ENTITIES.add(loc_obj["entity_hex"])
|
||||||
|
|
||||||
@@ -937,6 +998,7 @@ class WitnessPlayerLogic:
|
|||||||
doors = world.options.shuffle_doors
|
doors = world.options.shuffle_doors
|
||||||
shortbox_req = world.options.mountain_lasers
|
shortbox_req = world.options.mountain_lasers
|
||||||
longbox_req = world.options.challenge_lasers
|
longbox_req = world.options.challenge_lasers
|
||||||
|
eggs_exist = world.options.easter_egg_hunt
|
||||||
|
|
||||||
swamp_bridge_comes_to_you = "Swamp Long Bridge" in world.options.elevators_come_to_you
|
swamp_bridge_comes_to_you = "Swamp Long Bridge" in world.options.elevators_come_to_you
|
||||||
quarry_elevator_comes_to_you = "Quarry Elevator" in world.options.elevators_come_to_you
|
quarry_elevator_comes_to_you = "Quarry Elevator" in world.options.elevators_come_to_you
|
||||||
@@ -953,17 +1015,17 @@ class WitnessPlayerLogic:
|
|||||||
# It is easier to think about when these items *are* required, so we make that dict first
|
# It is easier to think about when these items *are* required, so we make that dict first
|
||||||
# If the entity is disabled anyway, we don't need to consider that case
|
# If the entity is disabled anyway, we don't need to consider that case
|
||||||
is_item_required_dict = {
|
is_item_required_dict = {
|
||||||
"0x03750": eps_shuffled, # Monastery Garden Entry Door
|
"0x03750": eps_shuffled or eggs_exist, # Monastery Garden Entry Door
|
||||||
"0x275FA": eps_shuffled, # Boathouse Hook Control
|
"0x275FA": eps_shuffled, # Boathouse Hook Control
|
||||||
"0x17D02": eps_shuffled, # Windmill Turn Control
|
"0x17D02": eps_shuffled, # Windmill Turn Control
|
||||||
"0x0368A": symbols_shuffled or door_panels, # Quarry Stoneworks Stairs Door
|
"0x0368A": symbols_shuffled or door_panels, # Quarry Stoneworks Stairs Door
|
||||||
"0x3865F": symbols_shuffled or door_panels or eps_shuffled, # Quarry Boathouse 2nd Barrier
|
"0x3865F": symbols_shuffled or door_panels or eps_shuffled, # Quarry Boathouse 2nd Barrier
|
||||||
"0x17CC4": quarry_elevator_comes_to_you or eps_shuffled, # Quarry Elevator Panel
|
"0x17CC4": quarry_elevator_comes_to_you or eps_shuffled, # Quarry Elevator Panel
|
||||||
"0x17E2B": swamp_bridge_comes_to_you and boat_shuffled or eps_shuffled, # Swamp Long Bridge
|
"0x17E2B": swamp_bridge_comes_to_you and boat_shuffled or eps_shuffled, # Swamp Long Bridge
|
||||||
"0x0CF2A": False, # Jungle Monastery Garden Shortcut
|
"0x0CF2A": eggs_exist, # Jungle Monastery Garden Shortcut
|
||||||
"0x0364E": False, # Monastery Laser Shortcut Door
|
"0x0364E": False, # Monastery Laser Shortcut Door
|
||||||
"0x03713": remote_doors, # Monastery Laser Shortcut Panel
|
"0x03713": remote_doors, # Monastery Laser Shortcut Panel
|
||||||
"0x03313": False, # Orchard Second Gate
|
"0x03313": eggs_exist, # Orchard Second Gate
|
||||||
"0x337FA": remote_doors, # Jungle Bamboo Laser Shortcut Panel
|
"0x337FA": remote_doors, # Jungle Bamboo Laser Shortcut Panel
|
||||||
"0x3873B": False, # Jungle Bamboo Laser Shortcut Door
|
"0x3873B": False, # Jungle Bamboo Laser Shortcut Door
|
||||||
"0x335AB": False, # Caves Elevator Controls
|
"0x335AB": False, # Caves Elevator Controls
|
||||||
@@ -1026,4 +1088,9 @@ class WitnessPlayerLogic:
|
|||||||
entity_name = entity_obj["checkName"]
|
entity_name = entity_obj["checkName"]
|
||||||
self.EVENT_ITEM_PAIRS[entity_name + " (Panel Hunt)"] = ("+1 Panel Hunt", entity_hex)
|
self.EVENT_ITEM_PAIRS[entity_name + " (Panel Hunt)"] = ("+1 Panel Hunt", entity_hex)
|
||||||
|
|
||||||
|
for region_name, easter_egg_count in self.AVAILABLE_EASTER_EGGS_PER_REGION.items():
|
||||||
|
plural = "s" if easter_egg_count != 1 else ""
|
||||||
|
event_name = f"+{easter_egg_count} Easter Egg{plural}"
|
||||||
|
self.EVENT_ITEM_PAIRS[f"{region_name} Easter Egg{plural}"] = (event_name, region_name)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@@ -117,12 +117,17 @@ class WitnessPlayerRegions:
|
|||||||
event_locations_per_region = defaultdict(dict)
|
event_locations_per_region = defaultdict(dict)
|
||||||
|
|
||||||
for event_location, event_item_and_entity in player_logic.EVENT_ITEM_PAIRS.items():
|
for event_location, event_item_and_entity in player_logic.EVENT_ITEM_PAIRS.items():
|
||||||
region = static_witness_logic.ENTITIES_BY_HEX[event_item_and_entity[1]]["region"]
|
entity_or_region = event_item_and_entity[1]
|
||||||
if region is None:
|
if entity_or_region in static_witness_logic.ALL_REGIONS_BY_NAME:
|
||||||
region_name = "Entry"
|
region_name = entity_or_region
|
||||||
|
order = -1
|
||||||
else:
|
else:
|
||||||
region_name = region["name"]
|
region = static_witness_logic.ENTITIES_BY_HEX[event_item_and_entity[1]]["region"]
|
||||||
order = self.reference_logic.ENTITIES_BY_HEX[event_item_and_entity[1]]["order"]
|
if region is None:
|
||||||
|
region_name = "Entry"
|
||||||
|
else:
|
||||||
|
region_name = region["name"]
|
||||||
|
order = self.reference_logic.ENTITIES_BY_HEX[entity_or_region]["order"]
|
||||||
event_locations_per_region[region_name][event_location] = order
|
event_locations_per_region[region_name][event_location] = order
|
||||||
|
|
||||||
for region_name, region in regions_to_create.items():
|
for region_name, region in regions_to_create.items():
|
||||||
|
@@ -2,7 +2,7 @@ line-length = 120
|
|||||||
|
|
||||||
[lint]
|
[lint]
|
||||||
select = ["C", "E", "F", "R", "W", "I", "N", "Q", "UP", "RUF", "ISC", "T20"]
|
select = ["C", "E", "F", "R", "W", "I", "N", "Q", "UP", "RUF", "ISC", "T20"]
|
||||||
ignore = ["C9", "RUF012", "RUF100"]
|
ignore = ["C9", "RUF012", "RUF021", "RUF100", "UP006", "UP035"]
|
||||||
|
|
||||||
[lint.per-file-ignores]
|
[lint.per-file-ignores]
|
||||||
# The way options definitions work right now, I am forced to break line length requirements.
|
# The way options definitions work right now, I am forced to break line length requirements.
|
||||||
|
@@ -196,6 +196,8 @@ def _has_item(item: str, world: "WitnessWorld",
|
|||||||
if item == "Entity Hunt":
|
if item == "Entity Hunt":
|
||||||
# Right now, panel hunt is the only type of entity hunt. This may need to be changed later
|
# Right now, panel hunt is the only type of entity hunt. This may need to be changed later
|
||||||
return _can_do_panel_hunt(world)
|
return _can_do_panel_hunt(world)
|
||||||
|
if "Eggs" in item:
|
||||||
|
return SimpleItemRepresentation("Egg", int(item.split(" ")[0]))
|
||||||
if item == "PP2 Weirdness":
|
if item == "PP2 Weirdness":
|
||||||
return lambda state: _can_do_expert_pp2(state, world)
|
return lambda state: _can_do_expert_pp2(state, world)
|
||||||
if item == "Theater to Tunnels":
|
if item == "Theater to Tunnels":
|
||||||
@@ -303,6 +305,11 @@ def make_lambda(entity_hex: str, world: "WitnessWorld") -> Optional[CollectionRu
|
|||||||
return _meets_item_requirements(entity_req, world)
|
return _meets_item_requirements(entity_req, world)
|
||||||
|
|
||||||
|
|
||||||
|
def make_region_lambda(region_name: str, world: "WitnessWorld") -> CollectionRule:
|
||||||
|
region = world.get_region(region_name)
|
||||||
|
return lambda state: region.can_reach(state)
|
||||||
|
|
||||||
|
|
||||||
def set_rules(world: "WitnessWorld") -> None:
|
def set_rules(world: "WitnessWorld") -> None:
|
||||||
"""
|
"""
|
||||||
Sets all rules for all locations
|
Sets all rules for all locations
|
||||||
@@ -312,8 +319,12 @@ def set_rules(world: "WitnessWorld") -> None:
|
|||||||
real_location = location
|
real_location = location
|
||||||
|
|
||||||
if location in world.player_locations.EVENT_LOCATION_TABLE:
|
if location in world.player_locations.EVENT_LOCATION_TABLE:
|
||||||
entity_hex = world.player_logic.EVENT_ITEM_PAIRS[location][1]
|
entity_hex_or_region_name = world.player_logic.EVENT_ITEM_PAIRS[location][1]
|
||||||
real_location = static_witness_logic.ENTITIES_BY_HEX[entity_hex]["checkName"]
|
if entity_hex_or_region_name in static_witness_logic.ALL_REGIONS_BY_NAME:
|
||||||
|
set_rule(world.get_location(location), make_region_lambda(entity_hex_or_region_name, world))
|
||||||
|
continue
|
||||||
|
|
||||||
|
real_location = static_witness_logic.ENTITIES_BY_HEX[entity_hex_or_region_name]["checkName"]
|
||||||
|
|
||||||
associated_entity = world.player_logic.REFERENCE_LOGIC.ENTITIES_BY_NAME[real_location]
|
associated_entity = world.player_logic.REFERENCE_LOGIC.ENTITIES_BY_NAME[real_location]
|
||||||
entity_hex = associated_entity["entity_hex"]
|
entity_hex = associated_entity["entity_hex"]
|
||||||
|
155
worlds/witness/test/test_easter_egg_shuffle.py
Normal file
155
worlds/witness/test/test_easter_egg_shuffle.py
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
from typing import cast
|
||||||
|
|
||||||
|
from BaseClasses import LocationProgressType
|
||||||
|
|
||||||
|
from .. import WitnessWorld
|
||||||
|
from ..test import WitnessMultiworldTestBase
|
||||||
|
|
||||||
|
|
||||||
|
class TestEasterEggShuffle(WitnessMultiworldTestBase):
|
||||||
|
options_per_world = [
|
||||||
|
{
|
||||||
|
"easter_egg_hunt": "off",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"easter_egg_hunt": "easy",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"easter_egg_hunt": "normal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"easter_egg_hunt": "hard",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"easter_egg_hunt": "very_hard",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"easter_egg_hunt": "extreme",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_easter_egg_hunt(self) -> None:
|
||||||
|
with self.subTest("Test that player without Easter Egg Hunt has no easter egg related locations"):
|
||||||
|
egg_locations = {location for location in self.multiworld.get_locations(1) if "Egg" in location.name}
|
||||||
|
self.assertFalse(egg_locations)
|
||||||
|
|
||||||
|
for player, eggs_per_check, logical_eggs_per_check in zip([2, 3, 4, 5, 6], [3, 3, 4, 4, 4], [8, 6, 6, 5, 4]):
|
||||||
|
world = cast(WitnessWorld, self.multiworld.worlds[player])
|
||||||
|
option_name = world.options.easter_egg_hunt
|
||||||
|
|
||||||
|
with self.subTest(f"Test that {option_name} Egg Hunt player starts with 0 eggs"):
|
||||||
|
self.assertEqual(self.multiworld.state.count("Egg", player), 0)
|
||||||
|
|
||||||
|
with self.subTest(f"Test that the correct Egg Collection locations exist for {option_name} player"):
|
||||||
|
first_egg_location = f"{eggs_per_check} Easter Eggs Collected"
|
||||||
|
one_less_location = f"{eggs_per_check - 1} Easter Eggs Collected"
|
||||||
|
one_more_location = f"{eggs_per_check + 1} Easter Eggs Collected"
|
||||||
|
self.assert_location_exists(first_egg_location, player)
|
||||||
|
self.assert_location_does_not_exist(one_less_location, player, strict_check=False)
|
||||||
|
self.assert_location_does_not_exist(one_more_location, player, strict_check=False)
|
||||||
|
|
||||||
|
one_too_few = logical_eggs_per_check - 1
|
||||||
|
with self.subTest(f'Test that "+{one_too_few} Easter Eggs" item adds 4 easter eggs'):
|
||||||
|
item = world.create_item(f"+{one_too_few} Easter Eggs")
|
||||||
|
self.multiworld.state.collect(item, prevent_sweep=True)
|
||||||
|
self.assertEqual(self.multiworld.state.count("Egg", player), one_too_few)
|
||||||
|
|
||||||
|
with self.subTest(
|
||||||
|
f"Test that {one_too_few} Easter Eggs are not enough for {option_name} player's first location"
|
||||||
|
):
|
||||||
|
self.assertFalse(self.multiworld.state.can_reach_location(first_egg_location, player))
|
||||||
|
|
||||||
|
with self.subTest(
|
||||||
|
f"Test that {logical_eggs_per_check} Easter Eggs are enough for {option_name} player's first location"
|
||||||
|
):
|
||||||
|
item = world.create_item("+1 Easter Egg")
|
||||||
|
self.multiworld.state.collect(item, prevent_sweep=True)
|
||||||
|
self.assertTrue(self.multiworld.state.can_reach_location(first_egg_location, player))
|
||||||
|
|
||||||
|
|
||||||
|
class TestEggRestrictions(WitnessMultiworldTestBase):
|
||||||
|
options_per_world = [
|
||||||
|
{
|
||||||
|
"shuffle_postgame": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shuffle_postgame": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shuffle_postgame": True,
|
||||||
|
"exclude_locations": frozenset({"Bunker Easter Egg 3"}),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
common_options = {
|
||||||
|
"victory_condition": "mountain_box_short",
|
||||||
|
"shuffle_doors": "off",
|
||||||
|
"easter_egg_hunt": "very_hard",
|
||||||
|
"shuffle_vault_boxes": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_egg_restrictions(self) -> None:
|
||||||
|
with self.subTest("Test that locations beyond 108 Easter Eggs don't exist for a seed without Mountain"):
|
||||||
|
self.assert_location_exists("108 Easter Eggs Collected", 1)
|
||||||
|
self.assert_location_does_not_exist("112 Easter Eggs Collected", 1)
|
||||||
|
|
||||||
|
with self.subTest(
|
||||||
|
"Test that locations beyond 86 Easter Eggs, which would logically require more than 108 Eggs, are excluded"
|
||||||
|
):
|
||||||
|
egg_84_location = self.multiworld.get_location("84 Easter Eggs Collected", 1)
|
||||||
|
egg_88_location = self.multiworld.get_location("88 Easter Eggs Collected", 1)
|
||||||
|
|
||||||
|
self.assertNotEqual(egg_84_location.progress_type, LocationProgressType.EXCLUDED)
|
||||||
|
self.assertEqual(egg_88_location.progress_type, LocationProgressType.EXCLUDED)
|
||||||
|
|
||||||
|
with self.subTest("Test that in a seed with the whole game included, the 120 egg location exists"):
|
||||||
|
self.assert_location_exists("120 Easter Eggs Collected", 2)
|
||||||
|
|
||||||
|
with self.subTest(
|
||||||
|
"Test that locations beyond 96 Easter Eggs, which would logically require more than 120 Eggs, are excluded"
|
||||||
|
):
|
||||||
|
egg_96_location = self.multiworld.get_location("96 Easter Eggs Collected", 2)
|
||||||
|
egg_100_location = self.multiworld.get_location("100 Easter Eggs Collected", 2)
|
||||||
|
|
||||||
|
self.assertNotEqual(egg_96_location.progress_type, LocationProgressType.EXCLUDED)
|
||||||
|
self.assertEqual(egg_100_location.progress_type, LocationProgressType.EXCLUDED)
|
||||||
|
|
||||||
|
with self.subTest("Test that you can exclude and egg to disable it"):
|
||||||
|
self.assert_location_exists("116 Easter Eggs Collected", 3)
|
||||||
|
self.assert_location_does_not_exist("120 Easter Eggs Collected", 3)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBunkerElevatorEgg(WitnessMultiworldTestBase):
|
||||||
|
options_per_world = [
|
||||||
|
{
|
||||||
|
"elevators_come_to_you": frozenset()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"elevators_come_to_you": frozenset({"Bunker Elevator"})
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
common_options = {
|
||||||
|
"easter_egg_hunt": "normal",
|
||||||
|
"shuffle_doors": "panels",
|
||||||
|
"shuffle_symbols": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_bunker_elevator_egg(self) -> None:
|
||||||
|
items_to_reach_bunker_elevator = [
|
||||||
|
"Bunker Entry (Panel)",
|
||||||
|
"Bunker Tinted Glass Door (Panel)",
|
||||||
|
"Bunker Drop-Down Door Controls (Panel)"
|
||||||
|
]
|
||||||
|
|
||||||
|
with self.subTest("Test that normally, the egg behind the elevator needs Elevator Control"):
|
||||||
|
self.assertFalse(self.multiworld.state.can_reach_location("Bunker Under Elevator Easter Egg", 1))
|
||||||
|
self.collect_by_name(items_to_reach_bunker_elevator, 1)
|
||||||
|
self.assertFalse(self.multiworld.state.can_reach_location("Bunker Under Elevator Easter Egg", 1))
|
||||||
|
self.collect_by_name(["Bunker Elevator Control (Panel)"], 1)
|
||||||
|
self.assertTrue(self.multiworld.state.can_reach_location("Bunker Under Elevator Easter Egg", 1))
|
||||||
|
|
||||||
|
with self.subTest("Test that with auto-elevators, the egg behind the elevator doesn't need Elevator Control"):
|
||||||
|
self.assertFalse(self.multiworld.state.can_reach_location("Bunker Under Elevator Easter Egg", 2))
|
||||||
|
self.collect_by_name(items_to_reach_bunker_elevator, 2)
|
||||||
|
self.assertTrue(self.multiworld.state.can_reach_location("Bunker Under Elevator Easter Egg", 2))
|
Reference in New Issue
Block a user