mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-04-22 21:13:31 -07:00
Merge branch 'ArchipelagoMW:main' into main
This commit is contained in:
@@ -3,18 +3,14 @@ from __future__ import annotations
|
||||
import hashlib
|
||||
import logging
|
||||
import pathlib
|
||||
from random import Random
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
from random import Random
|
||||
from dataclasses import make_dataclass
|
||||
from typing import (Any, Callable, ClassVar, Dict, FrozenSet, List, Mapping,
|
||||
Optional, Set, TextIO, Tuple, TYPE_CHECKING, Type, Union)
|
||||
from typing import (Any, Callable, ClassVar, Dict, FrozenSet, List, Mapping, Optional, Set, TextIO, Tuple,
|
||||
TYPE_CHECKING, Type, Union)
|
||||
|
||||
from Options import (
|
||||
ExcludeLocations, ItemLinks, LocalItems, NonLocalItems, OptionGroup, PerGameCommonOptions,
|
||||
PriorityLocations, StartHints, StartInventory, StartInventoryPool, StartLocationHints
|
||||
)
|
||||
from Options import item_and_loc_options, OptionGroup, PerGameCommonOptions
|
||||
from BaseClasses import CollectionState
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -55,17 +51,12 @@ class AutoWorldRegister(type):
|
||||
dct["item_name_groups"] = {group_name: frozenset(group_set) for group_name, group_set
|
||||
in dct.get("item_name_groups", {}).items()}
|
||||
dct["item_name_groups"]["Everything"] = dct["item_names"]
|
||||
dct["item_descriptions"] = {name: _normalize_description(description) for name, description
|
||||
in dct.get("item_descriptions", {}).items()}
|
||||
dct["item_descriptions"]["Everything"] = "All items in the entire game."
|
||||
|
||||
dct["location_names"] = frozenset(dct["location_name_to_id"])
|
||||
dct["location_name_groups"] = {group_name: frozenset(group_set) for group_name, group_set
|
||||
in dct.get("location_name_groups", {}).items()}
|
||||
dct["location_name_groups"]["Everywhere"] = dct["location_names"]
|
||||
dct["all_item_and_group_names"] = frozenset(dct["item_names"] | set(dct.get("item_name_groups", {})))
|
||||
dct["location_descriptions"] = {name: _normalize_description(description) for name, description
|
||||
in dct.get("location_descriptions", {}).items()}
|
||||
dct["location_descriptions"]["Everywhere"] = "All locations in the entire game."
|
||||
|
||||
# move away from get_required_client_version function
|
||||
if "game" in dct:
|
||||
@@ -125,13 +116,19 @@ class WebWorldRegister(type):
|
||||
# don't allow an option to appear in multiple groups, allow "Item & Location Options" to appear anywhere by the
|
||||
# dev, putting it at the end if they don't define options in it
|
||||
option_groups: List[OptionGroup] = dct.get("option_groups", [])
|
||||
item_and_loc_options = [LocalItems, NonLocalItems, StartInventory, StartInventoryPool, StartHints,
|
||||
StartLocationHints, ExcludeLocations, PriorityLocations, ItemLinks]
|
||||
prebuilt_options = ["Game Options", "Item & Location Options"]
|
||||
seen_options = []
|
||||
item_group_in_list = False
|
||||
for group in option_groups:
|
||||
assert group.name != "Game Options", "Game Options is a pre-determined group and can not be defined."
|
||||
assert group.options, "A custom defined Option Group must contain at least one Option."
|
||||
# catch incorrectly titled versions of the prebuilt groups so they don't create extra groups
|
||||
title_name = group.name.title()
|
||||
if title_name in prebuilt_options:
|
||||
group.name = title_name
|
||||
|
||||
if group.name == "Item & Location Options":
|
||||
assert not any(option in item_and_loc_options for option in group.options), \
|
||||
f"Item and Location Options cannot be specified multiple times"
|
||||
group.options.extend(item_and_loc_options)
|
||||
item_group_in_list = True
|
||||
else:
|
||||
@@ -143,7 +140,7 @@ class WebWorldRegister(type):
|
||||
assert option not in seen_options, f"{option} found in two option groups"
|
||||
seen_options.append(option)
|
||||
if not item_group_in_list:
|
||||
option_groups.append(OptionGroup("Item & Location Options", item_and_loc_options))
|
||||
option_groups.append(OptionGroup("Item & Location Options", item_and_loc_options, True))
|
||||
return super().__new__(mcs, name, bases, dct)
|
||||
|
||||
|
||||
@@ -226,6 +223,12 @@ class WebWorld(metaclass=WebWorldRegister):
|
||||
option_groups: ClassVar[List[OptionGroup]] = []
|
||||
"""Ordered list of option groupings. Any options not set in a group will be placed in a pre-built "Game Options"."""
|
||||
|
||||
location_descriptions: Dict[str, str] = {}
|
||||
"""An optional map from location names (or location group names) to brief descriptions for users."""
|
||||
|
||||
item_descriptions: Dict[str, str] = {}
|
||||
"""An optional map from item names (or item group names) to brief descriptions for users."""
|
||||
|
||||
|
||||
class World(metaclass=AutoWorldRegister):
|
||||
"""A World object encompasses a game's Items, Locations, Rules and additional data or functionality required.
|
||||
@@ -252,35 +255,9 @@ class World(metaclass=AutoWorldRegister):
|
||||
item_name_groups: ClassVar[Dict[str, Set[str]]] = {}
|
||||
"""maps item group names to sets of items. Example: {"Weapons": {"Sword", "Bow"}}"""
|
||||
|
||||
item_descriptions: ClassVar[Dict[str, str]] = {}
|
||||
"""An optional map from item names (or item group names) to brief descriptions for users.
|
||||
|
||||
Individual newlines and indentation will be collapsed into spaces before these descriptions are
|
||||
displayed. This may cover only a subset of items.
|
||||
"""
|
||||
|
||||
location_name_groups: ClassVar[Dict[str, Set[str]]] = {}
|
||||
"""maps location group names to sets of locations. Example: {"Sewer": {"Sewer Key Drop 1", "Sewer Key Drop 2"}}"""
|
||||
|
||||
location_descriptions: ClassVar[Dict[str, str]] = {}
|
||||
"""An optional map from location names (or location group names) to brief descriptions for users.
|
||||
|
||||
Individual newlines and indentation will be collapsed into spaces before these descriptions are
|
||||
displayed. This may cover only a subset of locations.
|
||||
"""
|
||||
|
||||
data_version: ClassVar[int] = 0
|
||||
"""
|
||||
Increment this every time something in your world's names/id mappings changes.
|
||||
|
||||
When this is set to 0, that world's DataPackage is considered in "testing mode", which signals to servers/clients
|
||||
that it should not be cached, and clients should request that world's DataPackage every connection. Not
|
||||
recommended for production-ready worlds.
|
||||
|
||||
Deprecated. Clients should utilize `checksum` to determine if DataPackage has changed since last connection and
|
||||
request a new DataPackage, if necessary.
|
||||
"""
|
||||
|
||||
required_client_version: Tuple[int, int, int] = (0, 1, 6)
|
||||
"""
|
||||
override this if changes to a world break forward-compatibility of the client
|
||||
@@ -554,7 +531,6 @@ class World(metaclass=AutoWorldRegister):
|
||||
"item_name_to_id": cls.item_name_to_id,
|
||||
"location_name_groups": sorted_location_name_groups,
|
||||
"location_name_to_id": cls.location_name_to_id,
|
||||
"version": cls.data_version,
|
||||
}
|
||||
res["checksum"] = data_package_checksum(res)
|
||||
return res
|
||||
@@ -572,18 +548,3 @@ def data_package_checksum(data: "GamesPackage") -> str:
|
||||
assert sorted(data) == list(data), "Data not ordered"
|
||||
from NetUtils import encode
|
||||
return hashlib.sha1(encode(data).encode()).hexdigest()
|
||||
|
||||
|
||||
def _normalize_description(description):
|
||||
"""
|
||||
Normalizes a description in item_descriptions or location_descriptions.
|
||||
|
||||
This allows authors to write descritions with nice indentation and line lengths in their world
|
||||
definitions without having it affect the rendered format.
|
||||
"""
|
||||
# First, collapse the whitespace around newlines and the ends of the description.
|
||||
description = re.sub(r' *\n *', '\n', description.strip())
|
||||
# Next, condense individual newlines into spaces.
|
||||
description = re.sub(r'(?<!\n)\n(?!\n)', ' ', description)
|
||||
return description
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ class GamesPackage(TypedDict, total=False):
|
||||
location_name_groups: Dict[str, List[str]]
|
||||
location_name_to_id: Dict[str, int]
|
||||
checksum: str
|
||||
version: int # TODO: Remove support after per game data packages API change.
|
||||
|
||||
|
||||
class DataPackage(TypedDict):
|
||||
|
||||
@@ -103,7 +103,7 @@ async def connect(ctx: BizHawkContext) -> bool:
|
||||
return True
|
||||
except (TimeoutError, ConnectionRefusedError):
|
||||
continue
|
||||
|
||||
|
||||
# No ports worked
|
||||
ctx.streams = None
|
||||
ctx.connection_status = ConnectionStatus.NOT_CONNECTED
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
A module containing the BizHawkClient base class and metaclass
|
||||
"""
|
||||
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import abc
|
||||
@@ -12,14 +11,13 @@ from worlds.LauncherComponents import Component, SuffixIdentifier, Type, compone
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .context import BizHawkClientContext
|
||||
else:
|
||||
BizHawkClientContext = object
|
||||
|
||||
|
||||
def launch_client(*args) -> None:
|
||||
from .context import launch
|
||||
launch_subprocess(launch, name="BizHawkClient")
|
||||
|
||||
|
||||
component = Component("BizHawk Client", "BizHawkClient", component_type=Type.CLIENT, func=launch_client,
|
||||
file_identifier=SuffixIdentifier())
|
||||
components.append(component)
|
||||
@@ -56,7 +54,7 @@ class AutoBizHawkClientRegister(abc.ABCMeta):
|
||||
return new_class
|
||||
|
||||
@staticmethod
|
||||
async def get_handler(ctx: BizHawkClientContext, system: str) -> Optional[BizHawkClient]:
|
||||
async def get_handler(ctx: "BizHawkClientContext", system: str) -> Optional[BizHawkClient]:
|
||||
for systems, handlers in AutoBizHawkClientRegister.game_handlers.items():
|
||||
if system in systems:
|
||||
for handler in handlers.values():
|
||||
@@ -77,7 +75,7 @@ class BizHawkClient(abc.ABC, metaclass=AutoBizHawkClientRegister):
|
||||
"""The file extension(s) this client is meant to open and patch (e.g. ".apz3")"""
|
||||
|
||||
@abc.abstractmethod
|
||||
async def validate_rom(self, ctx: BizHawkClientContext) -> bool:
|
||||
async def validate_rom(self, ctx: "BizHawkClientContext") -> bool:
|
||||
"""Should return whether the currently loaded ROM should be handled by this client. You might read the game name
|
||||
from the ROM header, for example. This function will only be asked to validate ROMs from the system set by the
|
||||
client class, so you do not need to check the system yourself.
|
||||
@@ -86,18 +84,18 @@ class BizHawkClient(abc.ABC, metaclass=AutoBizHawkClientRegister):
|
||||
as necessary (such as setting `ctx.game = self.game`, modifying `ctx.items_handling`, etc...)."""
|
||||
...
|
||||
|
||||
async def set_auth(self, ctx: BizHawkClientContext) -> None:
|
||||
async def set_auth(self, ctx: "BizHawkClientContext") -> None:
|
||||
"""Should set ctx.auth in anticipation of sending a `Connected` packet. You may override this if you store slot
|
||||
name in your patched ROM. If ctx.auth is not set after calling, the player will be prompted to enter their
|
||||
username."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
async def game_watcher(self, ctx: BizHawkClientContext) -> None:
|
||||
async def game_watcher(self, ctx: "BizHawkClientContext") -> None:
|
||||
"""Runs on a loop with the approximate interval `ctx.watcher_timeout`. The currently loaded ROM is guaranteed
|
||||
to have passed your validator when this function is called, and the emulator is very likely to be connected."""
|
||||
...
|
||||
|
||||
def on_package(self, ctx: BizHawkClientContext, cmd: str, args: dict) -> None:
|
||||
def on_package(self, ctx: "BizHawkClientContext", cmd: str, args: dict) -> None:
|
||||
"""For handling packages from the server. Called from `BizHawkClientContext.on_package`."""
|
||||
pass
|
||||
|
||||
@@ -3,7 +3,6 @@ A module containing context and functions relevant to running the client. This m
|
||||
checking or launching the client, otherwise it will probably cause circular import issues.
|
||||
"""
|
||||
|
||||
|
||||
import asyncio
|
||||
import enum
|
||||
import subprocess
|
||||
@@ -77,7 +76,7 @@ class BizHawkClientContext(CommonContext):
|
||||
if self.client_handler is not None:
|
||||
self.client_handler.on_package(self, cmd, args)
|
||||
|
||||
async def server_auth(self, password_requested: bool = False):
|
||||
async def server_auth(self, password_requested: bool=False):
|
||||
self.password_requested = password_requested
|
||||
|
||||
if self.bizhawk_ctx.connection_status != ConnectionStatus.CONNECTED:
|
||||
@@ -103,7 +102,7 @@ class BizHawkClientContext(CommonContext):
|
||||
await self.send_connect()
|
||||
self.auth_status = AuthStatus.PENDING
|
||||
|
||||
async def disconnect(self, allow_autoreconnect: bool = False):
|
||||
async def disconnect(self, allow_autoreconnect: bool=False):
|
||||
self.auth_status = AuthStatus.NOT_AUTHENTICATED
|
||||
await super().disconnect(allow_autoreconnect)
|
||||
|
||||
@@ -148,7 +147,8 @@ async def _game_watcher(ctx: BizHawkClientContext):
|
||||
script_version = await get_script_version(ctx.bizhawk_ctx)
|
||||
|
||||
if script_version != EXPECTED_SCRIPT_VERSION:
|
||||
logger.info(f"Connector script is incompatible. Expected version {EXPECTED_SCRIPT_VERSION} but got {script_version}. Disconnecting.")
|
||||
logger.info(f"Connector script is incompatible. Expected version {EXPECTED_SCRIPT_VERSION} but "
|
||||
f"got {script_version}. Disconnecting.")
|
||||
disconnect(ctx.bizhawk_ctx)
|
||||
continue
|
||||
|
||||
@@ -177,7 +177,8 @@ async def _game_watcher(ctx: BizHawkClientContext):
|
||||
|
||||
if ctx.client_handler is None:
|
||||
if not showed_no_handler_message:
|
||||
logger.info("No handler was found for this game")
|
||||
logger.info("No handler was found for this game. Double-check that the apworld is installed "
|
||||
"correctly and that you loaded the right ROM file.")
|
||||
showed_no_handler_message = True
|
||||
continue
|
||||
else:
|
||||
|
||||
@@ -113,7 +113,6 @@ class AdventureWorld(World):
|
||||
settings: ClassVar[AdventureSettings]
|
||||
item_name_to_id: ClassVar[Dict[str, int]] = {name: data.id for name, data in item_table.items()}
|
||||
location_name_to_id: ClassVar[Dict[str, int]] = {name: data.location_id for name, data in location_table.items()}
|
||||
data_version: ClassVar[int] = 1
|
||||
required_client_version: Tuple[int, int, int] = (0, 3, 9)
|
||||
|
||||
def __init__(self, world: MultiWorld, player: int):
|
||||
|
||||
@@ -339,7 +339,7 @@ async def track_locations(ctx, roomid, roomdata) -> bool:
|
||||
def new_check(location_id):
|
||||
new_locations.append(location_id)
|
||||
ctx.locations_checked.add(location_id)
|
||||
location = ctx.location_names[location_id]
|
||||
location = ctx.location_names.lookup_in_slot(location_id)
|
||||
snes_logger.info(
|
||||
f'New Check: {location} ' +
|
||||
f'({len(ctx.checked_locations) + 1 if ctx.checked_locations else len(ctx.locations_checked)}/' +
|
||||
@@ -552,9 +552,9 @@ class ALTTPSNIClient(SNIClient):
|
||||
item = ctx.items_received[recv_index]
|
||||
recv_index += 1
|
||||
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
|
||||
color(ctx.item_names[item.item], 'red', 'bold'),
|
||||
color(ctx.item_names.lookup_in_slot(item.item), 'red', 'bold'),
|
||||
color(ctx.player_names[item.player], 'yellow'),
|
||||
ctx.location_names[item.location], recv_index, len(ctx.items_received)))
|
||||
ctx.location_names.lookup_in_slot(item.location, item.player), recv_index, len(ctx.items_received)))
|
||||
|
||||
snes_buffered_write(ctx, RECV_PROGRESS_ADDR,
|
||||
bytes([recv_index & 0xFF, (recv_index >> 8) & 0xFF]))
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import typing
|
||||
|
||||
from BaseClasses import MultiWorld
|
||||
from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink, StartInventoryPool, PlandoBosses,\
|
||||
FreeText, Removed
|
||||
from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink, \
|
||||
StartInventoryPool, PlandoBosses, PlandoConnections, PlandoTexts, FreeText, Removed
|
||||
from .EntranceShuffle import default_connections, default_dungeon_connections, \
|
||||
inverted_default_connections, inverted_default_dungeon_connections
|
||||
from .Text import TextTable
|
||||
|
||||
|
||||
class GlitchesRequired(Choice):
|
||||
@@ -721,7 +724,27 @@ class AllowCollect(DefaultOnToggle):
|
||||
display_name = "Allow Collection of checks for other players"
|
||||
|
||||
|
||||
class ALttPPlandoConnections(PlandoConnections):
|
||||
entrances = set([connection[0] for connection in (
|
||||
*default_connections, *default_dungeon_connections, *inverted_default_connections,
|
||||
*inverted_default_dungeon_connections)])
|
||||
exits = set([connection[1] for connection in (
|
||||
*default_connections, *default_dungeon_connections, *inverted_default_connections,
|
||||
*inverted_default_dungeon_connections)])
|
||||
|
||||
|
||||
class ALttPPlandoTexts(PlandoTexts):
|
||||
"""Text plando. Format is:
|
||||
- text: 'This is your text'
|
||||
at: text_key
|
||||
percentage: 100
|
||||
Percentage is an integer from 1 to 100, and defaults to 100 when omitted."""
|
||||
valid_keys = TextTable.valid_keys
|
||||
|
||||
|
||||
alttp_options: typing.Dict[str, type(Option)] = {
|
||||
"plando_connections": ALttPPlandoConnections,
|
||||
"plando_texts": ALttPPlandoTexts,
|
||||
"start_inventory_from_pool": StartInventoryPool,
|
||||
"goal": Goal,
|
||||
"mode": Mode,
|
||||
|
||||
@@ -1269,7 +1269,8 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
|
||||
rom.write_int32(0x18020C, 0) # starting time (in frames, sint32)
|
||||
|
||||
# set up goals for treasure hunt
|
||||
rom.write_int16(0x180163, local_world.treasure_hunt_required)
|
||||
rom.write_int16(0x180163, max(0, local_world.treasure_hunt_required -
|
||||
sum(1 for item in world.precollected_items[player] if item.name == "Triforce Piece")))
|
||||
rom.write_bytes(0x180165, [0x0E, 0x28]) # Triforce Piece Sprite
|
||||
rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled)
|
||||
|
||||
@@ -1372,7 +1373,7 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
|
||||
'Golden Sword', 'Tempered Sword', 'Master Sword', 'Fighter Sword', 'Progressive Sword',
|
||||
'Mirror Shield', 'Red Shield', 'Blue Shield', 'Progressive Shield',
|
||||
'Red Mail', 'Blue Mail', 'Progressive Mail',
|
||||
'Magic Upgrade (1/4)', 'Magic Upgrade (1/2)'}:
|
||||
'Magic Upgrade (1/4)', 'Magic Upgrade (1/2)', 'Triforce Piece'}:
|
||||
continue
|
||||
|
||||
set_table = {'Book of Mudora': (0x34E, 1), 'Hammer': (0x34B, 1), 'Bug Catching Net': (0x34D, 1),
|
||||
@@ -2475,6 +2476,9 @@ def write_strings(rom, world, player):
|
||||
tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[local_random.randint(0, len(Sahasrahla2_texts) - 1)]
|
||||
tt['blind_by_the_light'] = Blind_texts[local_random.randint(0, len(Blind_texts) - 1)]
|
||||
|
||||
triforce_pieces_required = max(0, w.treasure_hunt_required -
|
||||
sum(1 for item in world.precollected_items[player] if item.name == "Triforce Piece"))
|
||||
|
||||
if world.goal[player] in ['triforce_hunt', 'local_triforce_hunt']:
|
||||
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
|
||||
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
||||
@@ -2482,16 +2486,16 @@ def write_strings(rom, world, player):
|
||||
tt['sign_ganon'] = 'Go find the Triforce pieces with your friends... Ganon is invincible!'
|
||||
else:
|
||||
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
|
||||
if w.treasure_hunt_required > 1:
|
||||
if triforce_pieces_required > 1:
|
||||
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\n" \
|
||||
"invisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\n" \
|
||||
"hidden in a hollow tree. If you bring\n%d Triforce pieces out of %d, I can reassemble it." % \
|
||||
(w.treasure_hunt_required, w.treasure_hunt_total)
|
||||
(triforce_pieces_required, w.treasure_hunt_total)
|
||||
else:
|
||||
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\n" \
|
||||
"invisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\n" \
|
||||
"hidden in a hollow tree. If you bring\n%d Triforce piece out of %d, I can reassemble it." % \
|
||||
(w.treasure_hunt_required, w.treasure_hunt_total)
|
||||
(triforce_pieces_required, w.treasure_hunt_total)
|
||||
elif world.goal[player] in ['pedestal']:
|
||||
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.'
|
||||
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
||||
@@ -2500,20 +2504,20 @@ def write_strings(rom, world, player):
|
||||
tt['ganon_fall_in'] = Ganon1_texts[local_random.randint(0, len(Ganon1_texts) - 1)]
|
||||
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
|
||||
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
|
||||
if w.treasure_hunt_required > 1:
|
||||
if triforce_pieces_required > 1:
|
||||
if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1:
|
||||
tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d with your friends to defeat Ganon.' % \
|
||||
(w.treasure_hunt_required, w.treasure_hunt_total)
|
||||
(triforce_pieces_required, w.treasure_hunt_total)
|
||||
elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']:
|
||||
tt['sign_ganon'] = 'You need to find %d Triforce pieces out of %d to defeat Ganon.' % \
|
||||
(w.treasure_hunt_required, w.treasure_hunt_total)
|
||||
(triforce_pieces_required, w.treasure_hunt_total)
|
||||
else:
|
||||
if world.goal[player] == 'ganon_triforce_hunt' and world.players > 1:
|
||||
tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d with your friends to defeat Ganon.' % \
|
||||
(w.treasure_hunt_required, w.treasure_hunt_total)
|
||||
(triforce_pieces_required, w.treasure_hunt_total)
|
||||
elif world.goal[player] in ['ganon_triforce_hunt', 'local_ganon_triforce_hunt']:
|
||||
tt['sign_ganon'] = 'You need to find %d Triforce piece out of %d to defeat Ganon.' % \
|
||||
(w.treasure_hunt_required, w.treasure_hunt_total)
|
||||
(triforce_pieces_required, w.treasure_hunt_total)
|
||||
|
||||
tt['kakariko_tavern_fisherman'] = TavernMan_texts[local_random.randint(0, len(TavernMan_texts) - 1)]
|
||||
|
||||
@@ -2538,12 +2542,12 @@ def write_strings(rom, world, player):
|
||||
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s house\n Dark Chapel\n{CHOICE3}"
|
||||
tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s house\n Dark Chapel\n Mountain Cave\n{CHOICE2}"
|
||||
|
||||
for at, text in world.plando_texts[player].items():
|
||||
for at, text, _ in world.plando_texts[player]:
|
||||
|
||||
if at not in tt:
|
||||
raise Exception(f"No text target \"{at}\" found.")
|
||||
else:
|
||||
tt[at] = text
|
||||
tt[at] = "\n".join(text)
|
||||
|
||||
rom.write_bytes(0xE0000, tt.getBytes())
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ from worlds.generic.Rules import add_rule
|
||||
|
||||
from BaseClasses import CollectionState
|
||||
from .SubClasses import ALttPLocation
|
||||
from .EntranceShuffle import door_addresses
|
||||
|
||||
from .Items import item_name_groups
|
||||
from .Options import small_key_shuffle, RandomizeShopInventories
|
||||
|
||||
from .StateHelpers import has_hearts, can_use_bombs, can_hold_arrows
|
||||
|
||||
logger = logging.getLogger("Shops")
|
||||
@@ -66,6 +66,7 @@ class Shop:
|
||||
return 0
|
||||
|
||||
def get_bytes(self) -> List[int]:
|
||||
from .EntranceShuffle import door_addresses
|
||||
# [id][roomID-low][roomID-high][doorID][zero][shop_config][shopkeeper_config][sram_index]
|
||||
entrances = self.region.entrances
|
||||
config = self.item_count
|
||||
@@ -181,7 +182,7 @@ def push_shop_inventories(multiworld):
|
||||
|
||||
|
||||
def create_shops(multiworld, player: int):
|
||||
|
||||
from .Options import RandomizeShopInventories
|
||||
player_shop_table = shop_table.copy()
|
||||
if multiworld.include_witch_hut[player]:
|
||||
player_shop_table["Potion Shop"] = player_shop_table["Potion Shop"]._replace(locked=False)
|
||||
@@ -304,6 +305,7 @@ shop_generation_types = {
|
||||
|
||||
|
||||
def set_up_shops(multiworld, player: int):
|
||||
from .Options import small_key_shuffle
|
||||
# TODO: move hard+ mode changes for shields here, utilizing the new shops
|
||||
|
||||
if multiworld.retro_bow[player]:
|
||||
@@ -426,7 +428,7 @@ def get_price_modifier(item):
|
||||
|
||||
def get_price(multiworld, item, player: int, price_type=None):
|
||||
"""Converts a raw Rupee price into a special price type"""
|
||||
|
||||
from .Options import small_key_shuffle
|
||||
if price_type:
|
||||
price_types = [price_type]
|
||||
else:
|
||||
|
||||
@@ -1289,6 +1289,415 @@ class LargeCreditBottomMapper(CharTextMapper):
|
||||
class TextTable(object):
|
||||
SIZE = 0x7355
|
||||
|
||||
valid_keys = [
|
||||
"set_cursor",
|
||||
"set_cursor2",
|
||||
"game_over_menu",
|
||||
"var_test",
|
||||
"follower_no_enter",
|
||||
"choice_1_3",
|
||||
"choice_2_3",
|
||||
"choice_3_3",
|
||||
"choice_1_2",
|
||||
"choice_2_2",
|
||||
"uncle_leaving_text",
|
||||
"uncle_dying_sewer",
|
||||
"tutorial_guard_1",
|
||||
"tutorial_guard_2",
|
||||
"tutorial_guard_3",
|
||||
"tutorial_guard_4",
|
||||
"tutorial_guard_5",
|
||||
"tutorial_guard_6",
|
||||
"tutorial_guard_7",
|
||||
"priest_sanctuary_before_leave",
|
||||
"sanctuary_enter",
|
||||
"zelda_sanctuary_story",
|
||||
"priest_sanctuary_before_pendants",
|
||||
"priest_sanctuary_after_pendants_before_master_sword",
|
||||
"priest_sanctuary_dying",
|
||||
"zelda_save_sewers",
|
||||
"priest_info",
|
||||
"zelda_sanctuary_before_leave",
|
||||
"telepathic_intro",
|
||||
"telepathic_reminder",
|
||||
"zelda_go_to_throne",
|
||||
"zelda_push_throne",
|
||||
"zelda_switch_room_pull",
|
||||
"zelda_save_lets_go",
|
||||
"zelda_save_repeat",
|
||||
"zelda_before_pendants",
|
||||
"zelda_after_pendants_before_master_sword",
|
||||
"telepathic_zelda_right_after_master_sword",
|
||||
"zelda_sewers",
|
||||
"zelda_switch_room",
|
||||
"kakariko_saharalasa_wife",
|
||||
"kakariko_saharalasa_wife_sword_story",
|
||||
"kakariko_saharalasa_wife_closing",
|
||||
"kakariko_saharalasa_after_master_sword",
|
||||
"kakariko_alert_guards",
|
||||
"sahasrahla_quest_have_pendants",
|
||||
"sahasrahla_quest_have_master_sword",
|
||||
"sahasrahla_quest_information",
|
||||
"sahasrahla_bring_courage",
|
||||
"sahasrahla_have_ice_rod",
|
||||
"telepathic_sahasrahla_beat_agahnim",
|
||||
"telepathic_sahasrahla_beat_agahnim_no_pearl",
|
||||
"sahasrahla_have_boots_no_icerod",
|
||||
"sahasrahla_have_courage",
|
||||
"sahasrahla_found",
|
||||
"sign_rain_north_of_links_house",
|
||||
"sign_north_of_links_house",
|
||||
"sign_path_to_death_mountain",
|
||||
"sign_lost_woods",
|
||||
"sign_zoras",
|
||||
"sign_outside_magic_shop",
|
||||
"sign_death_mountain_cave_back",
|
||||
"sign_east_of_links_house",
|
||||
"sign_south_of_lumberjacks",
|
||||
"sign_east_of_desert",
|
||||
"sign_east_of_sanctuary",
|
||||
"sign_east_of_castle",
|
||||
"sign_north_of_lake",
|
||||
"sign_desert_thief",
|
||||
"sign_lumberjacks_house",
|
||||
"sign_north_kakariko",
|
||||
"witch_bring_mushroom",
|
||||
"witch_brewing_the_item",
|
||||
"witch_assistant_no_bottle",
|
||||
"witch_assistant_no_empty_bottle",
|
||||
"witch_assistant_informational",
|
||||
"witch_assistant_no_bottle_buying",
|
||||
"potion_shop_no_empty_bottles",
|
||||
"item_get_lamp",
|
||||
"item_get_boomerang",
|
||||
"item_get_bow",
|
||||
"item_get_shovel",
|
||||
"item_get_magic_cape",
|
||||
"item_get_powder",
|
||||
"item_get_flippers",
|
||||
"item_get_power_gloves",
|
||||
"item_get_pendant_courage",
|
||||
"item_get_pendant_power",
|
||||
"item_get_pendant_wisdom",
|
||||
"item_get_mushroom",
|
||||
"item_get_book",
|
||||
"item_get_moonpearl",
|
||||
"item_get_compass",
|
||||
"item_get_map",
|
||||
"item_get_ice_rod",
|
||||
"item_get_fire_rod",
|
||||
"item_get_ether",
|
||||
"item_get_bombos",
|
||||
"item_get_quake",
|
||||
"item_get_hammer",
|
||||
"item_get_flute",
|
||||
"item_get_cane_of_somaria",
|
||||
"item_get_hookshot",
|
||||
"item_get_bombs",
|
||||
"item_get_bottle",
|
||||
"item_get_big_key",
|
||||
"item_get_titans_mitts",
|
||||
"item_get_magic_mirror",
|
||||
"item_get_fake_mastersword",
|
||||
"post_item_get_mastersword",
|
||||
"item_get_red_potion",
|
||||
"item_get_green_potion",
|
||||
"item_get_blue_potion",
|
||||
"item_get_bug_net",
|
||||
"item_get_blue_mail",
|
||||
"item_get_red_mail",
|
||||
"item_get_temperedsword",
|
||||
"item_get_mirror_shield",
|
||||
"item_get_cane_of_byrna",
|
||||
"missing_big_key",
|
||||
"missing_magic",
|
||||
"item_get_pegasus_boots",
|
||||
"talking_tree_info_start",
|
||||
"talking_tree_info_1",
|
||||
"talking_tree_info_2",
|
||||
"talking_tree_info_3",
|
||||
"talking_tree_info_4",
|
||||
"talking_tree_other",
|
||||
"item_get_pendant_power_alt",
|
||||
"item_get_pendant_wisdom_alt",
|
||||
"game_shooting_choice",
|
||||
"game_shooting_yes",
|
||||
"game_shooting_no",
|
||||
"game_shooting_continue",
|
||||
"pond_of_wishing",
|
||||
"pond_item_select",
|
||||
"pond_item_test",
|
||||
"pond_will_upgrade",
|
||||
"pond_item_test_no",
|
||||
"pond_item_test_no_no",
|
||||
"pond_item_boomerang",
|
||||
"pond_item_shield",
|
||||
"pond_item_silvers",
|
||||
"pond_item_bottle_filled",
|
||||
"pond_item_sword",
|
||||
"pond_of_wishing_happiness",
|
||||
"pond_of_wishing_choice",
|
||||
"pond_of_wishing_bombs",
|
||||
"pond_of_wishing_arrows",
|
||||
"pond_of_wishing_full_upgrades",
|
||||
"mountain_old_man_first",
|
||||
"mountain_old_man_deadend",
|
||||
"mountain_old_man_turn_right",
|
||||
"mountain_old_man_lost_and_alone",
|
||||
"mountain_old_man_drop_off",
|
||||
"mountain_old_man_in_his_cave_pre_agahnim",
|
||||
"mountain_old_man_in_his_cave",
|
||||
"mountain_old_man_in_his_cave_post_agahnim",
|
||||
"tavern_old_man_awake",
|
||||
"tavern_old_man_unactivated_flute",
|
||||
"tavern_old_man_know_tree_unactivated_flute",
|
||||
"tavern_old_man_have_flute",
|
||||
"chicken_hut_lady",
|
||||
"running_man",
|
||||
"game_race_sign",
|
||||
"sign_bumper_cave",
|
||||
"sign_catfish",
|
||||
"sign_north_village_of_outcasts",
|
||||
"sign_south_of_bumper_cave",
|
||||
"sign_east_of_pyramid",
|
||||
"sign_east_of_bomb_shop",
|
||||
"sign_east_of_mire",
|
||||
"sign_village_of_outcasts",
|
||||
"sign_before_wishing_pond",
|
||||
"sign_before_catfish_area",
|
||||
"castle_wall_guard",
|
||||
"gate_guard",
|
||||
"telepathic_tile_eastern_palace",
|
||||
"telepathic_tile_tower_of_hera_floor_4",
|
||||
"hylian_text_1",
|
||||
"mastersword_pedestal_translated",
|
||||
"telepathic_tile_spectacle_rock",
|
||||
"telepathic_tile_swamp_entrance",
|
||||
"telepathic_tile_thieves_town_upstairs",
|
||||
"telepathic_tile_misery_mire",
|
||||
"hylian_text_2",
|
||||
"desert_entry_translated",
|
||||
"telepathic_tile_under_ganon",
|
||||
"telepathic_tile_palace_of_darkness",
|
||||
"telepathic_tile_desert_bonk_torch_room",
|
||||
"telepathic_tile_castle_tower",
|
||||
"telepathic_tile_ice_large_room",
|
||||
"telepathic_tile_turtle_rock",
|
||||
"telepathic_tile_ice_entrance",
|
||||
"telepathic_tile_ice_stalfos_knights_room",
|
||||
"telepathic_tile_tower_of_hera_entrance",
|
||||
"houlihan_room",
|
||||
"caught_a_bee",
|
||||
"caught_a_fairy",
|
||||
"no_empty_bottles",
|
||||
"game_race_boy_time",
|
||||
"game_race_girl",
|
||||
"game_race_boy_success",
|
||||
"game_race_boy_failure",
|
||||
"game_race_boy_already_won",
|
||||
"game_race_boy_sneaky",
|
||||
"bottle_vendor_choice",
|
||||
"bottle_vendor_get",
|
||||
"bottle_vendor_no",
|
||||
"bottle_vendor_already_collected",
|
||||
"bottle_vendor_bee",
|
||||
"bottle_vendor_fish",
|
||||
"hobo_item_get_bottle",
|
||||
"blacksmiths_what_you_want",
|
||||
"blacksmiths_paywall",
|
||||
"blacksmiths_extra_okay",
|
||||
"blacksmiths_tempered_already",
|
||||
"blacksmiths_temper_no",
|
||||
"blacksmiths_bogart_sword",
|
||||
"blacksmiths_get_sword",
|
||||
"blacksmiths_shop_before_saving",
|
||||
"blacksmiths_shop_saving",
|
||||
"blacksmiths_collect_frog",
|
||||
"blacksmiths_still_working",
|
||||
"blacksmiths_saving_bows",
|
||||
"blacksmiths_hammer_anvil",
|
||||
"dark_flute_boy_storytime",
|
||||
"dark_flute_boy_get_shovel",
|
||||
"dark_flute_boy_no_get_shovel",
|
||||
"dark_flute_boy_flute_not_found",
|
||||
"dark_flute_boy_after_shovel_get",
|
||||
"shop_fortune_teller_lw_hint_0",
|
||||
"shop_fortune_teller_lw_hint_1",
|
||||
"shop_fortune_teller_lw_hint_2",
|
||||
"shop_fortune_teller_lw_hint_3",
|
||||
"shop_fortune_teller_lw_hint_4",
|
||||
"shop_fortune_teller_lw_hint_5",
|
||||
"shop_fortune_teller_lw_hint_6",
|
||||
"shop_fortune_teller_lw_hint_7",
|
||||
"shop_fortune_teller_lw_no_rupees",
|
||||
"shop_fortune_teller_lw",
|
||||
"shop_fortune_teller_lw_post_hint",
|
||||
"shop_fortune_teller_lw_no",
|
||||
"shop_fortune_teller_lw_hint_8",
|
||||
"shop_fortune_teller_lw_hint_9",
|
||||
"shop_fortune_teller_lw_hint_10",
|
||||
"shop_fortune_teller_lw_hint_11",
|
||||
"shop_fortune_teller_lw_hint_12",
|
||||
"shop_fortune_teller_lw_hint_13",
|
||||
"shop_fortune_teller_lw_hint_14",
|
||||
"shop_fortune_teller_lw_hint_15",
|
||||
"dark_sanctuary",
|
||||
"dark_sanctuary_hint_0",
|
||||
"dark_sanctuary_no",
|
||||
"dark_sanctuary_hint_1",
|
||||
"dark_sanctuary_yes",
|
||||
"dark_sanctuary_hint_2",
|
||||
"sick_kid_no_bottle",
|
||||
"sick_kid_trade",
|
||||
"sick_kid_post_trade",
|
||||
"desert_thief_sitting",
|
||||
"desert_thief_following",
|
||||
"desert_thief_question",
|
||||
"desert_thief_question_yes",
|
||||
"desert_thief_after_item_get",
|
||||
"desert_thief_reassure",
|
||||
"hylian_text_3",
|
||||
"tablet_ether_book",
|
||||
"tablet_bombos_book",
|
||||
"magic_bat_wake",
|
||||
"magic_bat_give_half_magic",
|
||||
"intro_main",
|
||||
"intro_throne_room",
|
||||
"intro_zelda_cell",
|
||||
"intro_agahnim",
|
||||
"pickup_purple_chest",
|
||||
"bomb_shop",
|
||||
"bomb_shop_big_bomb",
|
||||
"bomb_shop_big_bomb_buy",
|
||||
"item_get_big_bomb",
|
||||
"kiki_second_extortion",
|
||||
"kiki_second_extortion_no",
|
||||
"kiki_second_extortion_yes",
|
||||
"kiki_first_extortion",
|
||||
"kiki_first_extortion_yes",
|
||||
"kiki_first_extortion_no",
|
||||
"kiki_leaving_screen",
|
||||
"blind_in_the_cell",
|
||||
"blind_by_the_light",
|
||||
"blind_not_that_way",
|
||||
"aginah_l1sword_no_book",
|
||||
"aginah_l1sword_with_pendants",
|
||||
"aginah",
|
||||
"aginah_need_better_sword",
|
||||
"aginah_have_better_sword",
|
||||
"catfish",
|
||||
"catfish_after_item",
|
||||
"lumberjack_right",
|
||||
"lumberjack_left",
|
||||
"lumberjack_left_post_agahnim",
|
||||
"fighting_brothers_right",
|
||||
"fighting_brothers_right_opened",
|
||||
"fighting_brothers_left",
|
||||
"maiden_crystal_1",
|
||||
"maiden_crystal_2",
|
||||
"maiden_crystal_3",
|
||||
"maiden_crystal_4",
|
||||
"maiden_crystal_5",
|
||||
"maiden_crystal_6",
|
||||
"maiden_crystal_7",
|
||||
"maiden_ending",
|
||||
"maiden_confirm_understood",
|
||||
"barrier_breaking",
|
||||
"maiden_crystal_7_again",
|
||||
"agahnim_zelda_teleport",
|
||||
"agahnim_magic_running_away",
|
||||
"agahnim_hide_and_seek_found",
|
||||
"agahnim_defeated",
|
||||
"agahnim_final_meeting",
|
||||
"zora_meeting",
|
||||
"zora_tells_cost",
|
||||
"zora_get_flippers",
|
||||
"zora_no_cash",
|
||||
"zora_no_buy_item",
|
||||
"kakariko_saharalasa_grandson",
|
||||
"kakariko_saharalasa_grandson_next",
|
||||
"dark_palace_tree_dude",
|
||||
"fairy_wishing_ponds",
|
||||
"fairy_wishing_ponds_no",
|
||||
"pond_of_wishing_no",
|
||||
"pond_of_wishing_return_item",
|
||||
"pond_of_wishing_throw",
|
||||
"pond_pre_item_silvers",
|
||||
"pond_of_wishing_great_luck",
|
||||
"pond_of_wishing_good_luck",
|
||||
"pond_of_wishing_meh_luck",
|
||||
"pond_of_wishing_bad_luck",
|
||||
"pond_of_wishing_fortune",
|
||||
"item_get_14_heart",
|
||||
"item_get_24_heart",
|
||||
"item_get_34_heart",
|
||||
"item_get_whole_heart",
|
||||
"item_get_sanc_heart",
|
||||
"fairy_fountain_refill",
|
||||
"death_mountain_bullied_no_pearl",
|
||||
"death_mountain_bullied_with_pearl",
|
||||
"death_mountain_bully_no_pearl",
|
||||
"death_mountain_bully_with_pearl",
|
||||
"shop_darkworld_enter",
|
||||
"game_chest_village_of_outcasts",
|
||||
"game_chest_no_cash",
|
||||
"game_chest_not_played",
|
||||
"game_chest_played",
|
||||
"game_chest_village_of_outcasts_play",
|
||||
"shop_first_time",
|
||||
"shop_already_have",
|
||||
"shop_buy_shield",
|
||||
"shop_buy_red_potion",
|
||||
"shop_buy_arrows",
|
||||
"shop_buy_bombs",
|
||||
"shop_buy_bee",
|
||||
"shop_buy_heart",
|
||||
"shop_first_no_bottle_buy",
|
||||
"shop_buy_no_space",
|
||||
"ganon_fall_in",
|
||||
"ganon_phase_3",
|
||||
"lost_woods_thief",
|
||||
"blinds_hut_dude",
|
||||
"end_triforce",
|
||||
"toppi_fallen",
|
||||
"kakariko_tavern_fisherman",
|
||||
"thief_money",
|
||||
"thief_desert_rupee_cave",
|
||||
"thief_ice_rupee_cave",
|
||||
"telepathic_tile_south_east_darkworld_cave",
|
||||
"cukeman",
|
||||
"cukeman_2",
|
||||
"potion_shop_no_cash",
|
||||
"kakariko_powdered_chicken",
|
||||
"game_chest_south_of_kakariko",
|
||||
"game_chest_play_yes",
|
||||
"game_chest_play_no",
|
||||
"game_chest_lost_woods",
|
||||
"kakariko_flophouse_man_no_flippers",
|
||||
"kakariko_flophouse_man",
|
||||
"menu_start_2",
|
||||
"menu_start_3",
|
||||
"menu_pause",
|
||||
"game_digging_choice",
|
||||
"game_digging_start",
|
||||
"game_digging_no_cash",
|
||||
"game_digging_end_time",
|
||||
"game_digging_come_back_later",
|
||||
"game_digging_no_follower",
|
||||
"menu_start_4",
|
||||
"ganon_fall_in_alt",
|
||||
"ganon_phase_3_alt",
|
||||
"sign_east_death_mountain_bridge",
|
||||
"fish_money",
|
||||
"sign_ganons_tower",
|
||||
"sign_ganon",
|
||||
"ganon_phase_3_no_bow",
|
||||
"ganon_phase_3_no_silvers_alt",
|
||||
"ganon_phase_3_no_silvers",
|
||||
"ganon_phase_3_silvers",
|
||||
"murahdahla",
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
self._text = OrderedDict()
|
||||
self.setDefaultText()
|
||||
|
||||
@@ -213,7 +213,6 @@ class ALTTPWorld(World):
|
||||
item_name_to_id = {name: data.item_code for name, data in item_table.items() if type(data.item_code) == int}
|
||||
location_name_to_id = lookup_name_to_id
|
||||
|
||||
data_version = 9
|
||||
required_client_version = (0, 4, 1)
|
||||
web = ALTTPWeb()
|
||||
|
||||
|
||||
34
worlds/apsudoku/__init__.py
Normal file
34
worlds/apsudoku/__init__.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from typing import Dict
|
||||
|
||||
from BaseClasses import Tutorial
|
||||
from ..AutoWorld import WebWorld, World
|
||||
|
||||
class AP_SudokuWebWorld(WebWorld):
|
||||
options_page = "games/Sudoku/info/en"
|
||||
theme = 'partyTime'
|
||||
|
||||
setup_en = Tutorial(
|
||||
tutorial_name='Setup Guide',
|
||||
description='A guide to playing APSudoku',
|
||||
language='English',
|
||||
file_name='setup_en.md',
|
||||
link='setup/en',
|
||||
authors=['EmilyV']
|
||||
)
|
||||
|
||||
tutorials = [setup_en]
|
||||
|
||||
class AP_SudokuWorld(World):
|
||||
"""
|
||||
Play a little Sudoku while you're in BK mode to maybe get some useful hints
|
||||
"""
|
||||
game = "Sudoku"
|
||||
web = AP_SudokuWebWorld()
|
||||
|
||||
item_name_to_id: Dict[str, int] = {}
|
||||
location_name_to_id: Dict[str, int] = {}
|
||||
|
||||
@classmethod
|
||||
def stage_assert_generate(cls, multiworld):
|
||||
raise Exception("APSudoku cannot be used for generating worlds, the client can instead connect to any slot from any world")
|
||||
|
||||
13
worlds/apsudoku/docs/en_Sudoku.md
Normal file
13
worlds/apsudoku/docs/en_Sudoku.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# APSudoku
|
||||
|
||||
## Hint Games
|
||||
|
||||
HintGames do not need to be added at the start of a seed, and do not create a 'slot'- instead, you connect the HintGame client to a different game's slot. By playing a HintGame, you can earn hints for the connected slot.
|
||||
|
||||
## What is this game?
|
||||
|
||||
Play Sudoku puzzles of varying difficulties, earning a hint for each puzzle correctly solved. Harder puzzles are more likely to grant a hint towards a Progression item, though otherwise what hint is granted is random.
|
||||
|
||||
## Where is the options page?
|
||||
|
||||
There is no options page; this game cannot be used in your .yamls. Instead, the client can connect to any slot in a multiworld.
|
||||
37
worlds/apsudoku/docs/setup_en.md
Normal file
37
worlds/apsudoku/docs/setup_en.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# APSudoku Setup Guide
|
||||
|
||||
## Required Software
|
||||
- [APSudoku](https://github.com/EmilyV99/APSudoku)
|
||||
- Windows (most tested on Win10)
|
||||
- Other platforms might be able to build from source themselves; and may be included in the future.
|
||||
|
||||
## General Concept
|
||||
|
||||
This is a HintGame client, which can connect to any multiworld slot, allowing you to play Sudoku to unlock random hints for that slot's locations.
|
||||
|
||||
Does not need to be added at the start of a seed, as it does not create any slots of its own, nor does it have any YAML files.
|
||||
|
||||
## Installation Procedures
|
||||
|
||||
Go to the latest release from the [APSudoku Releases page](https://github.com/EmilyV99/APSudoku/releases). Download and extract the `APSudoku.zip` file.
|
||||
|
||||
## Joining a MultiWorld Game
|
||||
|
||||
1. Run APSudoku.exe
|
||||
2. Under the 'Archipelago' tab at the top-right:
|
||||
- Enter the server url & port number
|
||||
- Enter the name of the slot you wish to connect to
|
||||
- Enter the room password (optional)
|
||||
- Select DeathLink related settings (optional)
|
||||
- Press connect
|
||||
3. Go back to the 'Sudoku' tab
|
||||
- Click the various '?' buttons for information on how to play / control
|
||||
4. Choose puzzle difficulty
|
||||
5. Try to solve the Sudoku. Click 'Check' when done.
|
||||
|
||||
## DeathLink Support
|
||||
|
||||
If 'DeathLink' is enabled when you click 'Connect':
|
||||
- Lose a life if you check an incorrect puzzle (not an _incomplete_ puzzle- if any cells are empty, you get off with a warning), or quit a puzzle without solving it (including disconnecting).
|
||||
- Life count customizable (default 0). Dying with 0 lives left kills linked players AND resets your puzzle.
|
||||
- On receiving a DeathLink from another player, your puzzle resets.
|
||||
@@ -77,41 +77,41 @@ class ItemData:
|
||||
item_table = {
|
||||
# name: ID, Nb, Item Type, Item Group
|
||||
"Anemone": ItemData(698000, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_anemone
|
||||
"Arnassi statue": ItemData(698001, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_arnassi_statue
|
||||
"Big seed": ItemData(698002, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_big_seed
|
||||
"Glowing seed": ItemData(698003, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_bio_seed
|
||||
"Black pearl": ItemData(698004, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_blackpearl
|
||||
"Baby blaster": ItemData(698005, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_blaster
|
||||
"Crab armor": ItemData(698006, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_crab_costume
|
||||
"Baby dumbo": ItemData(698007, 1, ItemType.PROGRESSION, ItemGroup.UTILITY), # collectible_dumbo
|
||||
"Arnassi Statue": ItemData(698001, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_arnassi_statue
|
||||
"Big Seed": ItemData(698002, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_big_seed
|
||||
"Glowing Seed": ItemData(698003, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_bio_seed
|
||||
"Black Pearl": ItemData(698004, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_blackpearl
|
||||
"Baby Blaster": ItemData(698005, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_blaster
|
||||
"Crab Armor": ItemData(698006, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_crab_costume
|
||||
"Baby Dumbo": ItemData(698007, 1, ItemType.PROGRESSION, ItemGroup.UTILITY), # collectible_dumbo
|
||||
"Tooth": ItemData(698008, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_energy_boss
|
||||
"Energy statue": ItemData(698009, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_energy_statue
|
||||
"Krotite armor": ItemData(698010, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_energy_temple
|
||||
"Golden starfish": ItemData(698011, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_gold_star
|
||||
"Golden gear": ItemData(698012, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_golden_gear
|
||||
"Jelly beacon": ItemData(698013, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_jelly_beacon
|
||||
"Jelly costume": ItemData(698014, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_jelly_costume
|
||||
"Jelly plant": ItemData(698015, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_jelly_plant
|
||||
"Mithalas doll": ItemData(698016, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithala_doll
|
||||
"Mithalan dress": ItemData(698017, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithalan_costume
|
||||
"Mithalas banner": ItemData(698018, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithalas_banner
|
||||
"Mithalas pot": ItemData(698019, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithalas_pot
|
||||
"Mutant costume": ItemData(698020, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mutant_costume
|
||||
"Baby nautilus": ItemData(698021, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_nautilus
|
||||
"Baby piranha": ItemData(698022, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_piranha
|
||||
"Energy Statue": ItemData(698009, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_energy_statue
|
||||
"Krotite Armor": ItemData(698010, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_energy_temple
|
||||
"Golden Starfish": ItemData(698011, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_gold_star
|
||||
"Golden Gear": ItemData(698012, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_golden_gear
|
||||
"Jelly Beacon": ItemData(698013, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_jelly_beacon
|
||||
"Jelly Costume": ItemData(698014, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_jelly_costume
|
||||
"Jelly Plant": ItemData(698015, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_jelly_plant
|
||||
"Mithalas Doll": ItemData(698016, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithala_doll
|
||||
"Mithalan Dress": ItemData(698017, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithalan_costume
|
||||
"Mithalas Banner": ItemData(698018, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithalas_banner
|
||||
"Mithalas Pot": ItemData(698019, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithalas_pot
|
||||
"Mutant Costume": ItemData(698020, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mutant_costume
|
||||
"Baby Nautilus": ItemData(698021, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_nautilus
|
||||
"Baby Piranha": ItemData(698022, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_piranha
|
||||
"Arnassi Armor": ItemData(698023, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_seahorse_costume
|
||||
"Seed bag": ItemData(698024, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_seed_bag
|
||||
"Seed Bag": ItemData(698024, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_seed_bag
|
||||
"King's Skull": ItemData(698025, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_skull
|
||||
"Song plant spore": ItemData(698026, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_spore_seed
|
||||
"Stone head": ItemData(698027, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_stone_head
|
||||
"Sun key": ItemData(698028, 1, ItemType.NORMAL, ItemGroup.COLLECTIBLE), # collectible_sun_key
|
||||
"Girl costume": ItemData(698029, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_teen_costume
|
||||
"Odd container": ItemData(698030, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_treasure_chest
|
||||
"Song Plant Spore": ItemData(698026, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_spore_seed
|
||||
"Stone Head": ItemData(698027, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_stone_head
|
||||
"Sun Key": ItemData(698028, 1, ItemType.NORMAL, ItemGroup.COLLECTIBLE), # collectible_sun_key
|
||||
"Girl Costume": ItemData(698029, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_teen_costume
|
||||
"Odd Container": ItemData(698030, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_treasure_chest
|
||||
"Trident": ItemData(698031, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_trident_head
|
||||
"Turtle egg": ItemData(698032, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_turtle_egg
|
||||
"Jelly egg": ItemData(698033, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_upsidedown_seed
|
||||
"Urchin costume": ItemData(698034, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_urchin_costume
|
||||
"Baby walker": ItemData(698035, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_walker
|
||||
"Turtle Egg": ItemData(698032, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_turtle_egg
|
||||
"Jelly Egg": ItemData(698033, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_upsidedown_seed
|
||||
"Urchin Costume": ItemData(698034, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_urchin_costume
|
||||
"Baby Walker": ItemData(698035, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_walker
|
||||
"Vedha's Cure-All-All": ItemData(698036, 1, ItemType.NORMAL, ItemGroup.RECIPE), # ingredient_Vedha'sCure-All
|
||||
"Zuuna's perogi": ItemData(698037, 1, ItemType.NORMAL, ItemGroup.RECIPE), # ingredient_Zuuna'sperogi
|
||||
"Arcane poultice": ItemData(698038, 7, ItemType.NORMAL, ItemGroup.RECIPE), # ingredient_arcanepoultice
|
||||
@@ -206,9 +206,9 @@ item_table = {
|
||||
"Transturtle Open Water top right": ItemData(698127, 1, ItemType.PROGRESSION,
|
||||
ItemGroup.TURTLE), # transport_openwater03
|
||||
"Transturtle Forest bottom left": ItemData(698128, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_forest04
|
||||
"Transturtle Home water": ItemData(698129, 1, ItemType.NORMAL, ItemGroup.TURTLE), # transport_mainarea
|
||||
"Transturtle Home Water": ItemData(698129, 1, ItemType.NORMAL, ItemGroup.TURTLE), # transport_mainarea
|
||||
"Transturtle Abyss right": ItemData(698130, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_abyss03
|
||||
"Transturtle Final Boss": ItemData(698131, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_finalboss
|
||||
"Transturtle Simon says": ItemData(698132, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_forest05
|
||||
"Transturtle Arnassi ruins": ItemData(698133, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_seahorse
|
||||
"Transturtle Simon Says": ItemData(698132, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_forest05
|
||||
"Transturtle Arnassi Ruins": ItemData(698133, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_seahorse
|
||||
}
|
||||
|
||||
@@ -29,213 +29,213 @@ class AquariaLocation(Location):
|
||||
class AquariaLocations:
|
||||
|
||||
locations_verse_cave_r = {
|
||||
"Verse cave, bulb in the skeleton room": 698107,
|
||||
"Verse cave, bulb in the path left of the skeleton room": 698108,
|
||||
"Verse cave right area, Big Seed": 698175,
|
||||
"Verse Cave, bulb in the skeleton room": 698107,
|
||||
"Verse Cave, bulb in the path left of the skeleton room": 698108,
|
||||
"Verse Cave right area, Big Seed": 698175,
|
||||
}
|
||||
|
||||
locations_verse_cave_l = {
|
||||
"Verse cave, the Naija hint about here shield ability": 698200,
|
||||
"Verse cave left area, bulb in the center part": 698021,
|
||||
"Verse cave left area, bulb in the right part": 698022,
|
||||
"Verse cave left area, bulb under the rock at the end of the path": 698023,
|
||||
"Verse Cave, the Naija hint about the shield ability": 698200,
|
||||
"Verse Cave left area, bulb in the center part": 698021,
|
||||
"Verse Cave left area, bulb in the right part": 698022,
|
||||
"Verse Cave left area, bulb under the rock at the end of the path": 698023,
|
||||
}
|
||||
|
||||
locations_home_water = {
|
||||
"Home water, bulb below the grouper fish": 698058,
|
||||
"Home water, bulb in the path below Nautilus Prime": 698059,
|
||||
"Home water, bulb in the little room above the grouper fish": 698060,
|
||||
"Home water, bulb in the end of the left path from the verse cave": 698061,
|
||||
"Home water, bulb in the top left path": 698062,
|
||||
"Home water, bulb in the bottom left room": 698063,
|
||||
"Home water, bulb close to the Naija's home": 698064,
|
||||
"Home water, bulb under the rock in the left path from the verse cave": 698065,
|
||||
"Home Water, bulb below the grouper fish": 698058,
|
||||
"Home Water, bulb in the path below Nautilus Prime": 698059,
|
||||
"Home Water, bulb in the little room above the grouper fish": 698060,
|
||||
"Home Water, bulb in the end of the left path from the Verse Cave": 698061,
|
||||
"Home Water, bulb in the top left path": 698062,
|
||||
"Home Water, bulb in the bottom left room": 698063,
|
||||
"Home Water, bulb close to Naija's Home": 698064,
|
||||
"Home Water, bulb under the rock in the left path from the Verse Cave": 698065,
|
||||
}
|
||||
|
||||
locations_home_water_nautilus = {
|
||||
"Home water, Nautilus Egg": 698194,
|
||||
"Home Water, Nautilus Egg": 698194,
|
||||
}
|
||||
|
||||
locations_home_water_transturtle = {
|
||||
"Home water, Transturtle": 698213,
|
||||
"Home Water, Transturtle": 698213,
|
||||
}
|
||||
|
||||
locations_naija_home = {
|
||||
"Naija's home, bulb after the energy door": 698119,
|
||||
"Naija's home, bulb under the rock at the right of the main path": 698120,
|
||||
"Naija's Home, bulb after the energy door": 698119,
|
||||
"Naija's Home, bulb under the rock at the right of the main path": 698120,
|
||||
}
|
||||
|
||||
locations_song_cave = {
|
||||
"Song cave, Erulian spirit": 698206,
|
||||
"Song cave, bulb in the top left part": 698071,
|
||||
"Song cave, bulb in the big anemone room": 698072,
|
||||
"Song cave, bulb in the path to the singing statues": 698073,
|
||||
"Song cave, bulb under the rock in the path to the singing statues": 698074,
|
||||
"Song cave, bulb under the rock close to the song door": 698075,
|
||||
"Song cave, Verse egg": 698160,
|
||||
"Song cave, Jelly beacon": 698178,
|
||||
"Song cave, Anemone seed": 698162,
|
||||
"Song Cave, Erulian spirit": 698206,
|
||||
"Song Cave, bulb in the top left part": 698071,
|
||||
"Song Cave, bulb in the big anemone room": 698072,
|
||||
"Song Cave, bulb in the path to the singing statues": 698073,
|
||||
"Song Cave, bulb under the rock in the path to the singing statues": 698074,
|
||||
"Song Cave, bulb under the rock close to the song door": 698075,
|
||||
"Song Cave, Verse Egg": 698160,
|
||||
"Song Cave, Jelly Beacon": 698178,
|
||||
"Song Cave, Anemone Seed": 698162,
|
||||
}
|
||||
|
||||
locations_energy_temple_1 = {
|
||||
"Energy temple first area, beating the energy statue": 698205,
|
||||
"Energy temple first area, bulb in the bottom room blocked by a rock": 698027,
|
||||
"Energy Temple first area, beating the Energy Statue": 698205,
|
||||
"Energy Temple first area, bulb in the bottom room blocked by a rock": 698027,
|
||||
}
|
||||
|
||||
locations_energy_temple_idol = {
|
||||
"Energy temple first area, Energy Idol": 698170,
|
||||
"Energy Temple first area, Energy Idol": 698170,
|
||||
}
|
||||
|
||||
locations_energy_temple_2 = {
|
||||
"Energy temple second area, bulb under the rock": 698028,
|
||||
"Energy Temple second area, bulb under the rock": 698028,
|
||||
}
|
||||
|
||||
locations_energy_temple_altar = {
|
||||
"Energy temple bottom entrance, Krotite armor": 698163,
|
||||
"Energy Temple bottom entrance, Krotite Armor": 698163,
|
||||
}
|
||||
|
||||
locations_energy_temple_3 = {
|
||||
"Energy temple third area, bulb in the bottom path": 698029,
|
||||
"Energy Temple third area, bulb in the bottom path": 698029,
|
||||
}
|
||||
|
||||
locations_energy_temple_boss = {
|
||||
"Energy temple boss area, Fallen god tooth": 698169,
|
||||
"Energy Temple boss area, Fallen God Tooth": 698169,
|
||||
}
|
||||
|
||||
locations_energy_temple_blaster_room = {
|
||||
"Energy temple blaster room, Blaster egg": 698195,
|
||||
"Energy Temple blaster room, Blaster Egg": 698195,
|
||||
}
|
||||
|
||||
locations_openwater_tl = {
|
||||
"Open water top left area, bulb under the rock in the right path": 698001,
|
||||
"Open water top left area, bulb under the rock in the left path": 698002,
|
||||
"Open water top left area, bulb to the right of the save cristal": 698003,
|
||||
"Open Water top left area, bulb under the rock in the right path": 698001,
|
||||
"Open Water top left area, bulb under the rock in the left path": 698002,
|
||||
"Open Water top left area, bulb to the right of the save crystal": 698003,
|
||||
}
|
||||
|
||||
locations_openwater_tr = {
|
||||
"Open water top right area, bulb in the small path before Mithalas": 698004,
|
||||
"Open water top right area, bulb in the path from the left entrance": 698005,
|
||||
"Open water top right area, bulb in the clearing close to the bottom exit": 698006,
|
||||
"Open water top right area, bulb in the big clearing close to the save cristal": 698007,
|
||||
"Open water top right area, bulb in the big clearing to the top exit": 698008,
|
||||
"Open water top right area, first urn in the Mithalas exit": 698148,
|
||||
"Open water top right area, second urn in the Mithalas exit": 698149,
|
||||
"Open water top right area, third urn in the Mithalas exit": 698150,
|
||||
"Open Water top right area, bulb in the small path before Mithalas": 698004,
|
||||
"Open Water top right area, bulb in the path from the left entrance": 698005,
|
||||
"Open Water top right area, bulb in the clearing close to the bottom exit": 698006,
|
||||
"Open Water top right area, bulb in the big clearing close to the save crystal": 698007,
|
||||
"Open Water top right area, bulb in the big clearing to the top exit": 698008,
|
||||
"Open Water top right area, first urn in the Mithalas exit": 698148,
|
||||
"Open Water top right area, second urn in the Mithalas exit": 698149,
|
||||
"Open Water top right area, third urn in the Mithalas exit": 698150,
|
||||
}
|
||||
locations_openwater_tr_turtle = {
|
||||
"Open water top right area, bulb in the turtle room": 698009,
|
||||
"Open water top right area, Transturtle": 698211,
|
||||
"Open Water top right area, bulb in the turtle room": 698009,
|
||||
"Open Water top right area, Transturtle": 698211,
|
||||
}
|
||||
|
||||
locations_openwater_bl = {
|
||||
"Open water bottom left area, bulb behind the chomper fish": 698011,
|
||||
"Open water bottom left area, bulb inside the lowest fish pass": 698010,
|
||||
"Open Water bottom left area, bulb behind the chomper fish": 698011,
|
||||
"Open Water bottom left area, bulb inside the lowest fish pass": 698010,
|
||||
}
|
||||
|
||||
locations_skeleton_path = {
|
||||
"Open water skeleton path, bulb close to the right exit": 698012,
|
||||
"Open water skeleton path, bulb behind the chomper fish": 698013,
|
||||
"Open Water skeleton path, bulb close to the right exit": 698012,
|
||||
"Open Water skeleton path, bulb behind the chomper fish": 698013,
|
||||
}
|
||||
|
||||
locations_skeleton_path_sc = {
|
||||
"Open water skeleton path, King skull": 698177,
|
||||
"Open Water skeleton path, King Skull": 698177,
|
||||
}
|
||||
|
||||
locations_arnassi = {
|
||||
"Arnassi Ruins, bulb in the right part": 698014,
|
||||
"Arnassi Ruins, bulb in the left part": 698015,
|
||||
"Arnassi Ruins, bulb in the center part": 698016,
|
||||
"Arnassi ruins, Song plant spore on the top of the ruins": 698179,
|
||||
"Arnassi ruins, Arnassi Armor": 698191,
|
||||
"Arnassi Ruins, Song Plant Spore": 698179,
|
||||
"Arnassi Ruins, Arnassi Armor": 698191,
|
||||
}
|
||||
|
||||
locations_arnassi_path = {
|
||||
"Arnassi Ruins, Arnassi statue": 698164,
|
||||
"Arnassi Ruins, Arnassi Statue": 698164,
|
||||
"Arnassi Ruins, Transturtle": 698217,
|
||||
}
|
||||
|
||||
locations_arnassi_crab_boss = {
|
||||
"Arnassi ruins, Crab armor": 698187,
|
||||
"Arnassi Ruins, Crab Armor": 698187,
|
||||
}
|
||||
|
||||
locations_simon = {
|
||||
"Kelp forest, beating Simon says": 698156,
|
||||
"Simon says area, Transturtle": 698216,
|
||||
"Simon Says area, beating Simon Says": 698156,
|
||||
"Simon Says area, Transturtle": 698216,
|
||||
}
|
||||
|
||||
locations_mithalas_city = {
|
||||
"Mithalas city, first bulb in the left city part": 698030,
|
||||
"Mithalas city, second bulb in the left city part": 698035,
|
||||
"Mithalas city, bulb in the right part": 698031,
|
||||
"Mithalas city, bulb at the top of the city": 698033,
|
||||
"Mithalas city, first bulb in a broken home": 698034,
|
||||
"Mithalas city, second bulb in a broken home": 698041,
|
||||
"Mithalas city, bulb in the bottom left part": 698037,
|
||||
"Mithalas city, first bulb in one of the homes": 698038,
|
||||
"Mithalas city, second bulb in one of the homes": 698039,
|
||||
"Mithalas city, first urn in one of the homes": 698123,
|
||||
"Mithalas city, second urn in one of the homes": 698124,
|
||||
"Mithalas city, first urn in the city reserve": 698125,
|
||||
"Mithalas city, second urn in the city reserve": 698126,
|
||||
"Mithalas city, third urn in the city reserve": 698127,
|
||||
"Mithalas City, first bulb in the left city part": 698030,
|
||||
"Mithalas City, second bulb in the left city part": 698035,
|
||||
"Mithalas City, bulb in the right part": 698031,
|
||||
"Mithalas City, bulb at the top of the city": 698033,
|
||||
"Mithalas City, first bulb in a broken home": 698034,
|
||||
"Mithalas City, second bulb in a broken home": 698041,
|
||||
"Mithalas City, bulb in the bottom left part": 698037,
|
||||
"Mithalas City, first bulb in one of the homes": 698038,
|
||||
"Mithalas City, second bulb in one of the homes": 698039,
|
||||
"Mithalas City, first urn in one of the homes": 698123,
|
||||
"Mithalas City, second urn in one of the homes": 698124,
|
||||
"Mithalas City, first urn in the city reserve": 698125,
|
||||
"Mithalas City, second urn in the city reserve": 698126,
|
||||
"Mithalas City, third urn in the city reserve": 698127,
|
||||
}
|
||||
|
||||
locations_mithalas_city_top_path = {
|
||||
"Mithalas city, first bulb at the end of the top path": 698032,
|
||||
"Mithalas city, second bulb at the end of the top path": 698040,
|
||||
"Mithalas city, bulb in the top path": 698036,
|
||||
"Mithalas city, Mithalas pot": 698174,
|
||||
"Mithalas city, urn in the cathedral flower tube entrance": 698128,
|
||||
"Mithalas City, first bulb at the end of the top path": 698032,
|
||||
"Mithalas City, second bulb at the end of the top path": 698040,
|
||||
"Mithalas City, bulb in the top path": 698036,
|
||||
"Mithalas City, Mithalas Pot": 698174,
|
||||
"Mithalas City, urn in the Cathedral flower tube entrance": 698128,
|
||||
}
|
||||
|
||||
locations_mithalas_city_fishpass = {
|
||||
"Mithalas city, Doll": 698173,
|
||||
"Mithalas city, urn inside a home fish pass": 698129,
|
||||
"Mithalas City, Doll": 698173,
|
||||
"Mithalas City, urn inside a home fish pass": 698129,
|
||||
}
|
||||
|
||||
locations_cathedral_l = {
|
||||
"Mithalas city castle, bulb in the flesh hole": 698042,
|
||||
"Mithalas city castle, Blue banner": 698165,
|
||||
"Mithalas city castle, urn in the bedroom": 698130,
|
||||
"Mithalas city castle, first urn of the single lamp path": 698131,
|
||||
"Mithalas city castle, second urn of the single lamp path": 698132,
|
||||
"Mithalas city castle, urn in the bottom room": 698133,
|
||||
"Mithalas city castle, first urn on the entrance path": 698134,
|
||||
"Mithalas city castle, second urn on the entrance path": 698135,
|
||||
"Mithalas City Castle, bulb in the flesh hole": 698042,
|
||||
"Mithalas City Castle, Blue banner": 698165,
|
||||
"Mithalas City Castle, urn in the bedroom": 698130,
|
||||
"Mithalas City Castle, first urn of the single lamp path": 698131,
|
||||
"Mithalas City Castle, second urn of the single lamp path": 698132,
|
||||
"Mithalas City Castle, urn in the bottom room": 698133,
|
||||
"Mithalas City Castle, first urn on the entrance path": 698134,
|
||||
"Mithalas City Castle, second urn on the entrance path": 698135,
|
||||
}
|
||||
|
||||
locations_cathedral_l_tube = {
|
||||
"Mithalas castle, beating the priests": 698208,
|
||||
"Mithalas City Castle, beating the Priests": 698208,
|
||||
}
|
||||
|
||||
locations_cathedral_l_sc = {
|
||||
"Mithalas city castle, Trident head": 698183,
|
||||
"Mithalas City Castle, Trident Head": 698183,
|
||||
}
|
||||
|
||||
locations_cathedral_r = {
|
||||
"Mithalas cathedral, first urn in the top right room": 698136,
|
||||
"Mithalas cathedral, second urn in the top right room": 698137,
|
||||
"Mithalas cathedral, third urn in the top right room": 698138,
|
||||
"Mithalas cathedral, urn in the flesh room with fleas": 698139,
|
||||
"Mithalas cathedral, first urn in the bottom right path": 698140,
|
||||
"Mithalas cathedral, second urn in the bottom right path": 698141,
|
||||
"Mithalas cathedral, urn behind the flesh vein": 698142,
|
||||
"Mithalas cathedral, urn in the top left eyes boss room": 698143,
|
||||
"Mithalas cathedral, first urn in the path behind the flesh vein": 698144,
|
||||
"Mithalas cathedral, second urn in the path behind the flesh vein": 698145,
|
||||
"Mithalas cathedral, third urn in the path behind the flesh vein": 698146,
|
||||
"Mithalas cathedral, one of the urns in the top right room": 698147,
|
||||
"Mithalas cathedral, Mithalan Dress": 698189,
|
||||
"Mithalas cathedral right area, urn below the left entrance": 698198,
|
||||
"Mithalas Cathedral, first urn in the top right room": 698136,
|
||||
"Mithalas Cathedral, second urn in the top right room": 698137,
|
||||
"Mithalas Cathedral, third urn in the top right room": 698138,
|
||||
"Mithalas Cathedral, urn in the flesh room with fleas": 698139,
|
||||
"Mithalas Cathedral, first urn in the bottom right path": 698140,
|
||||
"Mithalas Cathedral, second urn in the bottom right path": 698141,
|
||||
"Mithalas Cathedral, urn behind the flesh vein": 698142,
|
||||
"Mithalas Cathedral, urn in the top left eyes boss room": 698143,
|
||||
"Mithalas Cathedral, first urn in the path behind the flesh vein": 698144,
|
||||
"Mithalas Cathedral, second urn in the path behind the flesh vein": 698145,
|
||||
"Mithalas Cathedral, third urn in the path behind the flesh vein": 698146,
|
||||
"Mithalas Cathedral, fourth urn in the top right room": 698147,
|
||||
"Mithalas Cathedral, Mithalan Dress": 698189,
|
||||
"Mithalas Cathedral right area, urn below the left entrance": 698198,
|
||||
}
|
||||
|
||||
locations_cathedral_underground = {
|
||||
"Cathedral underground, bulb in the center part": 698113,
|
||||
"Cathedral underground, first bulb in the top left part": 698114,
|
||||
"Cathedral underground, second bulb in the top left part": 698115,
|
||||
"Cathedral underground, third bulb in the top left part": 698116,
|
||||
"Cathedral underground, bulb close to the save cristal": 698117,
|
||||
"Cathedral underground, bulb in the bottom right path": 698118,
|
||||
"Cathedral Underground, bulb in the center part": 698113,
|
||||
"Cathedral Underground, first bulb in the top left part": 698114,
|
||||
"Cathedral Underground, second bulb in the top left part": 698115,
|
||||
"Cathedral Underground, third bulb in the top left part": 698116,
|
||||
"Cathedral Underground, bulb close to the save crystal": 698117,
|
||||
"Cathedral Underground, bulb in the bottom right path": 698118,
|
||||
}
|
||||
|
||||
locations_cathedral_boss = {
|
||||
@@ -250,8 +250,8 @@ class AquariaLocations:
|
||||
}
|
||||
|
||||
locations_forest_tl_fp = {
|
||||
"Kelp Forest top left area, bulb close to the Verse egg": 698047,
|
||||
"Kelp forest top left area, Verse egg": 698158,
|
||||
"Kelp Forest top left area, bulb close to the Verse Egg": 698047,
|
||||
"Kelp Forest top left area, Verse Egg": 698158,
|
||||
}
|
||||
|
||||
locations_forest_tr = {
|
||||
@@ -260,7 +260,7 @@ class AquariaLocations:
|
||||
"Kelp Forest top right area, bulb in the left path's big room": 698051,
|
||||
"Kelp Forest top right area, bulb in the left path's small room": 698052,
|
||||
"Kelp Forest top right area, bulb at the top of the center clearing": 698053,
|
||||
"Kelp forest top right area, Black pearl": 698167,
|
||||
"Kelp Forest top right area, Black Pearl": 698167,
|
||||
}
|
||||
|
||||
locations_forest_tr_fp = {
|
||||
@@ -269,16 +269,16 @@ class AquariaLocations:
|
||||
|
||||
locations_forest_bl = {
|
||||
"Kelp Forest bottom left area, bulb close to the spirit crystals": 698054,
|
||||
"Kelp forest bottom left area, Walker baby": 698186,
|
||||
"Kelp Forest bottom left area, Walker baby": 698186,
|
||||
"Kelp Forest bottom left area, Transturtle": 698212,
|
||||
}
|
||||
|
||||
locations_forest_br = {
|
||||
"Kelp forest bottom right area, Odd Container": 698168,
|
||||
"Kelp Forest bottom right area, Odd Container": 698168,
|
||||
}
|
||||
|
||||
locations_forest_boss = {
|
||||
"Kelp forest boss area, beating Drunian God": 698204,
|
||||
"Kelp Forest boss area, beating Drunian God": 698204,
|
||||
}
|
||||
|
||||
locations_forest_boss_entrance = {
|
||||
@@ -286,7 +286,7 @@ class AquariaLocations:
|
||||
}
|
||||
|
||||
locations_forest_fish_cave = {
|
||||
"Kelp Forest bottom left area, Fish cave puzzle": 698207,
|
||||
"Kelp Forest bottom left area, Fish Cave puzzle": 698207,
|
||||
}
|
||||
|
||||
locations_forest_sprite_cave = {
|
||||
@@ -295,7 +295,7 @@ class AquariaLocations:
|
||||
|
||||
locations_forest_sprite_cave_tube = {
|
||||
"Kelp Forest sprite cave, bulb in the second room": 698057,
|
||||
"Kelp Forest Sprite Cave, Seed bag": 698176,
|
||||
"Kelp Forest sprite cave, Seed Bag": 698176,
|
||||
}
|
||||
|
||||
locations_mermog_cave = {
|
||||
@@ -307,14 +307,14 @@ class AquariaLocations:
|
||||
}
|
||||
|
||||
locations_veil_tl = {
|
||||
"The veil top left area, In the Li cave": 698199,
|
||||
"The veil top left area, bulb under the rock in the top right path": 698078,
|
||||
"The veil top left area, bulb hidden behind the blocking rock": 698076,
|
||||
"The veil top left area, Transturtle": 698209,
|
||||
"The Veil top left area, In Li's cave": 698199,
|
||||
"The Veil top left area, bulb under the rock in the top right path": 698078,
|
||||
"The Veil top left area, bulb hidden behind the blocking rock": 698076,
|
||||
"The Veil top left area, Transturtle": 698209,
|
||||
}
|
||||
|
||||
locations_veil_tl_fp = {
|
||||
"The veil top left area, bulb inside the fish pass": 698077,
|
||||
"The Veil top left area, bulb inside the fish pass": 698077,
|
||||
}
|
||||
|
||||
locations_turtle_cave = {
|
||||
@@ -322,56 +322,56 @@ class AquariaLocations:
|
||||
}
|
||||
|
||||
locations_turtle_cave_bubble = {
|
||||
"Turtle cave, bulb in bubble cliff": 698000,
|
||||
"Turtle cave, Urchin costume": 698193,
|
||||
"Turtle cave, bulb in Bubble Cliff": 698000,
|
||||
"Turtle cave, Urchin Costume": 698193,
|
||||
}
|
||||
|
||||
locations_veil_tr_r = {
|
||||
"The veil top right area, bulb in the middle of the wall jump cliff": 698079,
|
||||
"The veil top right area, golden starfish at the bottom right of the bottom path": 698180,
|
||||
"The Veil top right area, bulb in the middle of the wall jump cliff": 698079,
|
||||
"The Veil top right area, Golden Starfish": 698180,
|
||||
}
|
||||
|
||||
locations_veil_tr_l = {
|
||||
"The veil top right area, bulb in the top of the water fall": 698080,
|
||||
"The veil top right area, Transturtle": 698210,
|
||||
"The Veil top right area, bulb in the top of the waterfall": 698080,
|
||||
"The Veil top right area, Transturtle": 698210,
|
||||
}
|
||||
|
||||
locations_veil_bl = {
|
||||
"The veil bottom area, bulb in the left path": 698082,
|
||||
"The Veil bottom area, bulb in the left path": 698082,
|
||||
}
|
||||
|
||||
locations_veil_b_sc = {
|
||||
"The veil bottom area, bulb in the spirit path": 698081,
|
||||
"The Veil bottom area, bulb in the spirit path": 698081,
|
||||
}
|
||||
|
||||
locations_veil_bl_fp = {
|
||||
"The veil bottom area, Verse egg": 698157,
|
||||
"The Veil bottom area, Verse Egg": 698157,
|
||||
}
|
||||
|
||||
locations_veil_br = {
|
||||
"The veil bottom area, Stone Head": 698181,
|
||||
"The Veil bottom area, Stone Head": 698181,
|
||||
}
|
||||
|
||||
locations_octo_cave_t = {
|
||||
"Octopus cave, Dumbo Egg": 698196,
|
||||
"Octopus Cave, Dumbo Egg": 698196,
|
||||
}
|
||||
|
||||
locations_octo_cave_b = {
|
||||
"Octopus cave, bulb in the path below the octopus cave path": 698122,
|
||||
"Octopus Cave, bulb in the path below the Octopus Cave path": 698122,
|
||||
}
|
||||
|
||||
locations_sun_temple_l = {
|
||||
"Sun temple, bulb in the top left part": 698094,
|
||||
"Sun temple, bulb in the top right part": 698095,
|
||||
"Sun temple, bulb at the top of the high dark room": 698096,
|
||||
"Sun temple, Golden Gear": 698171,
|
||||
"Sun Temple, bulb in the top left part": 698094,
|
||||
"Sun Temple, bulb in the top right part": 698095,
|
||||
"Sun Temple, bulb at the top of the high dark room": 698096,
|
||||
"Sun Temple, Golden Gear": 698171,
|
||||
}
|
||||
|
||||
locations_sun_temple_r = {
|
||||
"Sun temple, first bulb of the temple": 698091,
|
||||
"Sun temple, bulb on the left part": 698092,
|
||||
"Sun temple, bulb in the hidden room of the right part": 698093,
|
||||
"Sun temple, Sun key": 698182,
|
||||
"Sun Temple, first bulb of the temple": 698091,
|
||||
"Sun Temple, bulb on the left part": 698092,
|
||||
"Sun Temple, bulb in the hidden room of the right part": 698093,
|
||||
"Sun Temple, Sun Key": 698182,
|
||||
}
|
||||
|
||||
locations_sun_temple_boss_path = {
|
||||
@@ -382,13 +382,13 @@ class AquariaLocations:
|
||||
}
|
||||
|
||||
locations_sun_temple_boss = {
|
||||
"Sun temple boss area, beating Sun God": 698203,
|
||||
"Sun Temple boss area, beating Sun God": 698203,
|
||||
}
|
||||
|
||||
locations_abyss_l = {
|
||||
"Abyss left area, bulb in hidden path room": 698024,
|
||||
"Abyss left area, bulb in the right part": 698025,
|
||||
"Abyss left area, Glowing seed": 698166,
|
||||
"Abyss left area, Glowing Seed": 698166,
|
||||
"Abyss left area, Glowing Plant": 698172,
|
||||
}
|
||||
|
||||
@@ -405,87 +405,87 @@ class AquariaLocations:
|
||||
}
|
||||
|
||||
locations_ice_cave = {
|
||||
"Ice cave, bulb in the room to the right": 698083,
|
||||
"Ice cave, First bulbs in the top exit room": 698084,
|
||||
"Ice cave, Second bulbs in the top exit room": 698085,
|
||||
"Ice cave, third bulbs in the top exit room": 698086,
|
||||
"Ice cave, bulb in the left room": 698087,
|
||||
"Ice Cave, bulb in the room to the right": 698083,
|
||||
"Ice Cave, first bulb in the top exit room": 698084,
|
||||
"Ice Cave, second bulb in the top exit room": 698085,
|
||||
"Ice Cave, third bulb in the top exit room": 698086,
|
||||
"Ice Cave, bulb in the left room": 698087,
|
||||
}
|
||||
|
||||
locations_bubble_cave = {
|
||||
"Bubble cave, bulb in the left cave wall": 698089,
|
||||
"Bubble cave, bulb in the right cave wall (behind the ice cristal)": 698090,
|
||||
"Bubble Cave, bulb in the left cave wall": 698089,
|
||||
"Bubble Cave, bulb in the right cave wall (behind the ice crystal)": 698090,
|
||||
}
|
||||
|
||||
locations_bubble_cave_boss = {
|
||||
"Bubble cave, Verse egg": 698161,
|
||||
"Bubble Cave, Verse Egg": 698161,
|
||||
}
|
||||
|
||||
locations_king_jellyfish_cave = {
|
||||
"King Jellyfish cave, bulb in the right path from King Jelly": 698088,
|
||||
"King Jellyfish cave, Jellyfish Costume": 698188,
|
||||
"King Jellyfish Cave, bulb in the right path from King Jelly": 698088,
|
||||
"King Jellyfish Cave, Jellyfish Costume": 698188,
|
||||
}
|
||||
|
||||
locations_whale = {
|
||||
"The whale, Verse egg": 698159,
|
||||
"The Whale, Verse Egg": 698159,
|
||||
}
|
||||
|
||||
locations_sunken_city_r = {
|
||||
"Sunken city right area, crate close to the save cristal": 698154,
|
||||
"Sunken city right area, crate in the left bottom room": 698155,
|
||||
"Sunken City right area, crate close to the save crystal": 698154,
|
||||
"Sunken City right area, crate in the left bottom room": 698155,
|
||||
}
|
||||
|
||||
locations_sunken_city_l = {
|
||||
"Sunken city left area, crate in the little pipe room": 698151,
|
||||
"Sunken city left area, crate close to the save cristal": 698152,
|
||||
"Sunken city left area, crate before the bedroom": 698153,
|
||||
"Sunken City left area, crate in the little pipe room": 698151,
|
||||
"Sunken City left area, crate close to the save crystal": 698152,
|
||||
"Sunken City left area, crate before the bedroom": 698153,
|
||||
}
|
||||
|
||||
locations_sunken_city_l_bedroom = {
|
||||
"Sunken city left area, Girl Costume": 698192,
|
||||
"Sunken City left area, Girl Costume": 698192,
|
||||
}
|
||||
|
||||
locations_sunken_city_boss = {
|
||||
"Sunken city, bulb on the top of the boss area (boiler room)": 698043,
|
||||
"Sunken City, bulb on top of the boss area": 698043,
|
||||
}
|
||||
|
||||
locations_body_c = {
|
||||
"The body center area, breaking li cage": 698201,
|
||||
"The body main area, bulb on the main path blocking tube": 698097,
|
||||
"The Body center area, breaking Li's cage": 698201,
|
||||
"The Body main area, bulb on the main path blocking tube": 698097,
|
||||
}
|
||||
|
||||
locations_body_l = {
|
||||
"The body left area, first bulb in the top face room": 698066,
|
||||
"The body left area, second bulb in the top face room": 698069,
|
||||
"The body left area, bulb below the water stream": 698067,
|
||||
"The body left area, bulb in the top path to the top face room": 698068,
|
||||
"The body left area, bulb in the bottom face room": 698070,
|
||||
"The Body left area, first bulb in the top face room": 698066,
|
||||
"The Body left area, second bulb in the top face room": 698069,
|
||||
"The Body left area, bulb below the water stream": 698067,
|
||||
"The Body left area, bulb in the top path to the top face room": 698068,
|
||||
"The Body left area, bulb in the bottom face room": 698070,
|
||||
}
|
||||
|
||||
locations_body_rt = {
|
||||
"The body right area, bulb in the top face room": 698100,
|
||||
"The Body right area, bulb in the top face room": 698100,
|
||||
}
|
||||
|
||||
locations_body_rb = {
|
||||
"The body right area, bulb in the top path to the bottom face room": 698098,
|
||||
"The body right area, bulb in the bottom face room": 698099,
|
||||
"The Body right area, bulb in the top path to the bottom face room": 698098,
|
||||
"The Body right area, bulb in the bottom face room": 698099,
|
||||
}
|
||||
|
||||
locations_body_b = {
|
||||
"The body bottom area, bulb in the Jelly Zap room": 698101,
|
||||
"The body bottom area, bulb in the nautilus room": 698102,
|
||||
"The body bottom area, Mutant Costume": 698190,
|
||||
"The Body bottom area, bulb in the Jelly Zap room": 698101,
|
||||
"The Body bottom area, bulb in the nautilus room": 698102,
|
||||
"The Body bottom area, Mutant Costume": 698190,
|
||||
}
|
||||
|
||||
locations_final_boss_tube = {
|
||||
"Final boss area, first bulb in the turtle room": 698103,
|
||||
"Final boss area, second bulbs in the turtle room": 698104,
|
||||
"Final boss area, third bulbs in the turtle room": 698105,
|
||||
"Final boss area, Transturtle": 698215,
|
||||
"Final Boss area, first bulb in the turtle room": 698103,
|
||||
"Final Boss area, second bulb in the turtle room": 698104,
|
||||
"Final Boss area, third bulb in the turtle room": 698105,
|
||||
"Final Boss area, Transturtle": 698215,
|
||||
}
|
||||
|
||||
locations_final_boss = {
|
||||
"Final boss area, bulb in the boss third form room": 698106,
|
||||
"Final Boss area, bulb in the boss third form room": 698106,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ class BindSongNeededToGetUnderRockBulb(Toggle):
|
||||
|
||||
class UnconfineHomeWater(Choice):
|
||||
"""
|
||||
Open the way out of the Home water area so that Naija can go to open water and beyond without the bind song.
|
||||
Open the way out of the Home Water area so that Naija can go to open water and beyond without the bind song.
|
||||
"""
|
||||
display_name = "Unconfine Home Water Area"
|
||||
option_off = 0
|
||||
|
||||
@@ -36,8 +36,8 @@ def _has_li(state:CollectionState, player: int) -> bool:
|
||||
|
||||
def _has_damaging_item(state:CollectionState, player: int) -> bool:
|
||||
"""`player` in `state` has the shield song item"""
|
||||
return state.has_any({"Energy form", "Nature form", "Beast form", "Li and Li song", "Baby nautilus",
|
||||
"Baby piranha", "Baby blaster"}, player)
|
||||
return state.has_any({"Energy form", "Nature form", "Beast form", "Li and Li song", "Baby Nautilus",
|
||||
"Baby Piranha", "Baby Blaster"}, player)
|
||||
|
||||
|
||||
def _has_shield_song(state:CollectionState, player: int) -> bool:
|
||||
@@ -72,7 +72,7 @@ def _has_sun_form(state:CollectionState, player: int) -> bool:
|
||||
|
||||
def _has_light(state:CollectionState, player: int) -> bool:
|
||||
"""`player` in `state` has the light item"""
|
||||
return state.has("Baby dumbo", player) or _has_sun_form(state, player)
|
||||
return state.has("Baby Dumbo", player) or _has_sun_form(state, player)
|
||||
|
||||
|
||||
def _has_dual_form(state:CollectionState, player: int) -> bool:
|
||||
@@ -237,26 +237,26 @@ class AquariaRegions:
|
||||
AquariaLocations.locations_home_water_nautilus)
|
||||
self.home_water_transturtle = self.__add_region("Home Water, turtle room",
|
||||
AquariaLocations.locations_home_water_transturtle)
|
||||
self.naija_home = self.__add_region("Naija's home", AquariaLocations.locations_naija_home)
|
||||
self.song_cave = self.__add_region("Song cave", AquariaLocations.locations_song_cave)
|
||||
self.naija_home = self.__add_region("Naija's Home", AquariaLocations.locations_naija_home)
|
||||
self.song_cave = self.__add_region("Song Cave", AquariaLocations.locations_song_cave)
|
||||
|
||||
def __create_energy_temple(self) -> None:
|
||||
"""
|
||||
Create the `energy_temple_*` regions
|
||||
"""
|
||||
self.energy_temple_1 = self.__add_region("Energy temple first area",
|
||||
self.energy_temple_1 = self.__add_region("Energy Temple first area",
|
||||
AquariaLocations.locations_energy_temple_1)
|
||||
self.energy_temple_2 = self.__add_region("Energy temple second area",
|
||||
self.energy_temple_2 = self.__add_region("Energy Temple second area",
|
||||
AquariaLocations.locations_energy_temple_2)
|
||||
self.energy_temple_3 = self.__add_region("Energy temple third area",
|
||||
self.energy_temple_3 = self.__add_region("Energy Temple third area",
|
||||
AquariaLocations.locations_energy_temple_3)
|
||||
self.energy_temple_altar = self.__add_region("Energy temple bottom entrance",
|
||||
self.energy_temple_altar = self.__add_region("Energy Temple bottom entrance",
|
||||
AquariaLocations.locations_energy_temple_altar)
|
||||
self.energy_temple_boss = self.__add_region("Energy temple fallen God room",
|
||||
self.energy_temple_boss = self.__add_region("Energy Temple fallen God room",
|
||||
AquariaLocations.locations_energy_temple_boss)
|
||||
self.energy_temple_idol = self.__add_region("Energy temple Idol room",
|
||||
self.energy_temple_idol = self.__add_region("Energy Temple Idol room",
|
||||
AquariaLocations.locations_energy_temple_idol)
|
||||
self.energy_temple_blaster_room = self.__add_region("Energy temple blaster room",
|
||||
self.energy_temple_blaster_room = self.__add_region("Energy Temple blaster room",
|
||||
AquariaLocations.locations_energy_temple_blaster_room)
|
||||
|
||||
def __create_openwater(self) -> None:
|
||||
@@ -264,18 +264,18 @@ class AquariaRegions:
|
||||
Create the `openwater_*`, `skeleton_path`, `arnassi*` and `simon`
|
||||
regions
|
||||
"""
|
||||
self.openwater_tl = self.__add_region("Open water top left area",
|
||||
self.openwater_tl = self.__add_region("Open Water top left area",
|
||||
AquariaLocations.locations_openwater_tl)
|
||||
self.openwater_tr = self.__add_region("Open water top right area",
|
||||
self.openwater_tr = self.__add_region("Open Water top right area",
|
||||
AquariaLocations.locations_openwater_tr)
|
||||
self.openwater_tr_turtle = self.__add_region("Open water top right area, turtle room",
|
||||
self.openwater_tr_turtle = self.__add_region("Open Water top right area, turtle room",
|
||||
AquariaLocations.locations_openwater_tr_turtle)
|
||||
self.openwater_bl = self.__add_region("Open water bottom left area",
|
||||
self.openwater_bl = self.__add_region("Open Water bottom left area",
|
||||
AquariaLocations.locations_openwater_bl)
|
||||
self.openwater_br = self.__add_region("Open water bottom right area", None)
|
||||
self.skeleton_path = self.__add_region("Open water skeleton path",
|
||||
self.openwater_br = self.__add_region("Open Water bottom right area", None)
|
||||
self.skeleton_path = self.__add_region("Open Water skeleton path",
|
||||
AquariaLocations.locations_skeleton_path)
|
||||
self.skeleton_path_sc = self.__add_region("Open water skeleton path spirit cristal",
|
||||
self.skeleton_path_sc = self.__add_region("Open Water skeleton path spirit crystal",
|
||||
AquariaLocations.locations_skeleton_path_sc)
|
||||
self.arnassi = self.__add_region("Arnassi Ruins", AquariaLocations.locations_arnassi)
|
||||
self.arnassi_path = self.__add_region("Arnassi Ruins, back entrance path",
|
||||
@@ -287,20 +287,20 @@ class AquariaRegions:
|
||||
"""
|
||||
Create the `mithalas_city*` and `cathedral_*` regions
|
||||
"""
|
||||
self.mithalas_city = self.__add_region("Mithalas city",
|
||||
self.mithalas_city = self.__add_region("Mithalas City",
|
||||
AquariaLocations.locations_mithalas_city)
|
||||
self.mithalas_city_fishpass = self.__add_region("Mithalas city fish pass",
|
||||
self.mithalas_city_fishpass = self.__add_region("Mithalas City fish pass",
|
||||
AquariaLocations.locations_mithalas_city_fishpass)
|
||||
self.mithalas_city_top_path = self.__add_region("Mithalas city top path",
|
||||
self.mithalas_city_top_path = self.__add_region("Mithalas City top path",
|
||||
AquariaLocations.locations_mithalas_city_top_path)
|
||||
self.cathedral_l = self.__add_region("Mithalas castle", AquariaLocations.locations_cathedral_l)
|
||||
self.cathedral_l_tube = self.__add_region("Mithalas castle, plant tube entrance",
|
||||
AquariaLocations.locations_cathedral_l_tube)
|
||||
self.cathedral_l_sc = self.__add_region("Mithalas castle spirit cristal",
|
||||
self.cathedral_l_sc = self.__add_region("Mithalas castle spirit crystal",
|
||||
AquariaLocations.locations_cathedral_l_sc)
|
||||
self.cathedral_r = self.__add_region("Mithalas Cathedral",
|
||||
AquariaLocations.locations_cathedral_r)
|
||||
self.cathedral_underground = self.__add_region("Mithalas Cathedral underground area",
|
||||
self.cathedral_underground = self.__add_region("Mithalas Cathedral Underground area",
|
||||
AquariaLocations.locations_cathedral_underground)
|
||||
self.cathedral_boss_r = self.__add_region("Mithalas Cathedral, Mithalan God room",
|
||||
AquariaLocations.locations_cathedral_boss)
|
||||
@@ -310,73 +310,73 @@ class AquariaRegions:
|
||||
"""
|
||||
Create the `forest_*` dans `mermog_cave` regions
|
||||
"""
|
||||
self.forest_tl = self.__add_region("Kelp forest top left area",
|
||||
self.forest_tl = self.__add_region("Kelp Forest top left area",
|
||||
AquariaLocations.locations_forest_tl)
|
||||
self.forest_tl_fp = self.__add_region("Kelp forest top left area fish pass",
|
||||
self.forest_tl_fp = self.__add_region("Kelp Forest top left area fish pass",
|
||||
AquariaLocations.locations_forest_tl_fp)
|
||||
self.forest_tr = self.__add_region("Kelp forest top right area",
|
||||
self.forest_tr = self.__add_region("Kelp Forest top right area",
|
||||
AquariaLocations.locations_forest_tr)
|
||||
self.forest_tr_fp = self.__add_region("Kelp forest top right area fish pass",
|
||||
self.forest_tr_fp = self.__add_region("Kelp Forest top right area fish pass",
|
||||
AquariaLocations.locations_forest_tr_fp)
|
||||
self.forest_bl = self.__add_region("Kelp forest bottom left area",
|
||||
self.forest_bl = self.__add_region("Kelp Forest bottom left area",
|
||||
AquariaLocations.locations_forest_bl)
|
||||
self.forest_br = self.__add_region("Kelp forest bottom right area",
|
||||
self.forest_br = self.__add_region("Kelp Forest bottom right area",
|
||||
AquariaLocations.locations_forest_br)
|
||||
self.forest_sprite_cave = self.__add_region("Kelp forest spirit cave",
|
||||
self.forest_sprite_cave = self.__add_region("Kelp Forest spirit cave",
|
||||
AquariaLocations.locations_forest_sprite_cave)
|
||||
self.forest_sprite_cave_tube = self.__add_region("Kelp forest spirit cave after the plant tube",
|
||||
self.forest_sprite_cave_tube = self.__add_region("Kelp Forest spirit cave after the plant tube",
|
||||
AquariaLocations.locations_forest_sprite_cave_tube)
|
||||
self.forest_boss = self.__add_region("Kelp forest Drunian God room",
|
||||
self.forest_boss = self.__add_region("Kelp Forest Drunian God room",
|
||||
AquariaLocations.locations_forest_boss)
|
||||
self.forest_boss_entrance = self.__add_region("Kelp forest Drunian God room entrance",
|
||||
self.forest_boss_entrance = self.__add_region("Kelp Forest Drunian God room entrance",
|
||||
AquariaLocations.locations_forest_boss_entrance)
|
||||
self.mermog_cave = self.__add_region("Kelp forest Mermog cave",
|
||||
self.mermog_cave = self.__add_region("Kelp Forest Mermog cave",
|
||||
AquariaLocations.locations_mermog_cave)
|
||||
self.mermog_boss = self.__add_region("Kelp forest Mermog cave boss",
|
||||
self.mermog_boss = self.__add_region("Kelp Forest Mermog cave boss",
|
||||
AquariaLocations.locations_mermog_boss)
|
||||
self.forest_fish_cave = self.__add_region("Kelp forest fish cave",
|
||||
self.forest_fish_cave = self.__add_region("Kelp Forest fish cave",
|
||||
AquariaLocations.locations_forest_fish_cave)
|
||||
self.simon = self.__add_region("Kelp forest, Simon's room", AquariaLocations.locations_simon)
|
||||
self.simon = self.__add_region("Kelp Forest, Simon's room", AquariaLocations.locations_simon)
|
||||
|
||||
def __create_veil(self) -> None:
|
||||
"""
|
||||
Create the `veil_*`, `octo_cave` and `turtle_cave` regions
|
||||
"""
|
||||
self.veil_tl = self.__add_region("The veil top left area", AquariaLocations.locations_veil_tl)
|
||||
self.veil_tl_fp = self.__add_region("The veil top left area fish pass",
|
||||
self.veil_tl = self.__add_region("The Veil top left area", AquariaLocations.locations_veil_tl)
|
||||
self.veil_tl_fp = self.__add_region("The Veil top left area fish pass",
|
||||
AquariaLocations.locations_veil_tl_fp)
|
||||
self.turtle_cave = self.__add_region("The veil top left area, turtle cave",
|
||||
self.turtle_cave = self.__add_region("The Veil top left area, turtle cave",
|
||||
AquariaLocations.locations_turtle_cave)
|
||||
self.turtle_cave_bubble = self.__add_region("The veil top left area, turtle cave bubble cliff",
|
||||
self.turtle_cave_bubble = self.__add_region("The Veil top left area, turtle cave Bubble Cliff",
|
||||
AquariaLocations.locations_turtle_cave_bubble)
|
||||
self.veil_tr_l = self.__add_region("The veil top right area, left of temple",
|
||||
self.veil_tr_l = self.__add_region("The Veil top right area, left of temple",
|
||||
AquariaLocations.locations_veil_tr_l)
|
||||
self.veil_tr_r = self.__add_region("The veil top right area, right of temple",
|
||||
self.veil_tr_r = self.__add_region("The Veil top right area, right of temple",
|
||||
AquariaLocations.locations_veil_tr_r)
|
||||
self.octo_cave_t = self.__add_region("Octopus cave top entrance",
|
||||
self.octo_cave_t = self.__add_region("Octopus Cave top entrance",
|
||||
AquariaLocations.locations_octo_cave_t)
|
||||
self.octo_cave_b = self.__add_region("Octopus cave bottom entrance",
|
||||
self.octo_cave_b = self.__add_region("Octopus Cave bottom entrance",
|
||||
AquariaLocations.locations_octo_cave_b)
|
||||
self.veil_bl = self.__add_region("The veil bottom left area",
|
||||
self.veil_bl = self.__add_region("The Veil bottom left area",
|
||||
AquariaLocations.locations_veil_bl)
|
||||
self.veil_b_sc = self.__add_region("The veil bottom spirit cristal area",
|
||||
self.veil_b_sc = self.__add_region("The Veil bottom spirit crystal area",
|
||||
AquariaLocations.locations_veil_b_sc)
|
||||
self.veil_bl_fp = self.__add_region("The veil bottom left area, in the sunken ship",
|
||||
self.veil_bl_fp = self.__add_region("The Veil bottom left area, in the sunken ship",
|
||||
AquariaLocations.locations_veil_bl_fp)
|
||||
self.veil_br = self.__add_region("The veil bottom right area",
|
||||
self.veil_br = self.__add_region("The Veil bottom right area",
|
||||
AquariaLocations.locations_veil_br)
|
||||
|
||||
def __create_sun_temple(self) -> None:
|
||||
"""
|
||||
Create the `sun_temple*` regions
|
||||
"""
|
||||
self.sun_temple_l = self.__add_region("Sun temple left area",
|
||||
self.sun_temple_l = self.__add_region("Sun Temple left area",
|
||||
AquariaLocations.locations_sun_temple_l)
|
||||
self.sun_temple_r = self.__add_region("Sun temple right area",
|
||||
self.sun_temple_r = self.__add_region("Sun Temple right area",
|
||||
AquariaLocations.locations_sun_temple_r)
|
||||
self.sun_temple_boss_path = self.__add_region("Sun temple before boss area",
|
||||
self.sun_temple_boss_path = self.__add_region("Sun Temple before boss area",
|
||||
AquariaLocations.locations_sun_temple_boss_path)
|
||||
self.sun_temple_boss = self.__add_region("Sun temple boss area",
|
||||
self.sun_temple_boss = self.__add_region("Sun Temple boss area",
|
||||
AquariaLocations.locations_sun_temple_boss)
|
||||
|
||||
def __create_abyss(self) -> None:
|
||||
@@ -388,9 +388,9 @@ class AquariaRegions:
|
||||
AquariaLocations.locations_abyss_l)
|
||||
self.abyss_lb = self.__add_region("Abyss left bottom area", AquariaLocations.locations_abyss_lb)
|
||||
self.abyss_r = self.__add_region("Abyss right area", AquariaLocations.locations_abyss_r)
|
||||
self.ice_cave = self.__add_region("Ice cave", AquariaLocations.locations_ice_cave)
|
||||
self.bubble_cave = self.__add_region("Bubble cave", AquariaLocations.locations_bubble_cave)
|
||||
self.bubble_cave_boss = self.__add_region("Bubble cave boss area", AquariaLocations.locations_bubble_cave_boss)
|
||||
self.ice_cave = self.__add_region("Ice Cave", AquariaLocations.locations_ice_cave)
|
||||
self.bubble_cave = self.__add_region("Bubble Cave", AquariaLocations.locations_bubble_cave)
|
||||
self.bubble_cave_boss = self.__add_region("Bubble Cave boss area", AquariaLocations.locations_bubble_cave_boss)
|
||||
self.king_jellyfish_cave = self.__add_region("Abyss left area, King jellyfish cave",
|
||||
AquariaLocations.locations_king_jellyfish_cave)
|
||||
self.whale = self.__add_region("Inside the whale", AquariaLocations.locations_whale)
|
||||
@@ -400,35 +400,35 @@ class AquariaRegions:
|
||||
"""
|
||||
Create the `sunken_city_*` regions
|
||||
"""
|
||||
self.sunken_city_l = self.__add_region("Sunken city left area",
|
||||
self.sunken_city_l = self.__add_region("Sunken City left area",
|
||||
AquariaLocations.locations_sunken_city_l)
|
||||
self.sunken_city_l_bedroom = self.__add_region("Sunken city left area, bedroom",
|
||||
self.sunken_city_l_bedroom = self.__add_region("Sunken City left area, bedroom",
|
||||
AquariaLocations.locations_sunken_city_l_bedroom)
|
||||
self.sunken_city_r = self.__add_region("Sunken city right area",
|
||||
self.sunken_city_r = self.__add_region("Sunken City right area",
|
||||
AquariaLocations.locations_sunken_city_r)
|
||||
self.sunken_city_boss = self.__add_region("Sunken city boss area",
|
||||
self.sunken_city_boss = self.__add_region("Sunken City boss area",
|
||||
AquariaLocations.locations_sunken_city_boss)
|
||||
|
||||
def __create_body(self) -> None:
|
||||
"""
|
||||
Create the `body_*` and `final_boss* regions
|
||||
"""
|
||||
self.body_c = self.__add_region("The body center area",
|
||||
self.body_c = self.__add_region("The Body center area",
|
||||
AquariaLocations.locations_body_c)
|
||||
self.body_l = self.__add_region("The body left area",
|
||||
self.body_l = self.__add_region("The Body left area",
|
||||
AquariaLocations.locations_body_l)
|
||||
self.body_rt = self.__add_region("The body right area, top path",
|
||||
self.body_rt = self.__add_region("The Body right area, top path",
|
||||
AquariaLocations.locations_body_rt)
|
||||
self.body_rb = self.__add_region("The body right area, bottom path",
|
||||
self.body_rb = self.__add_region("The Body right area, bottom path",
|
||||
AquariaLocations.locations_body_rb)
|
||||
self.body_b = self.__add_region("The body bottom area",
|
||||
self.body_b = self.__add_region("The Body bottom area",
|
||||
AquariaLocations.locations_body_b)
|
||||
self.final_boss_loby = self.__add_region("The body, before final boss", None)
|
||||
self.final_boss_tube = self.__add_region("The body, final boss area turtle room",
|
||||
self.final_boss_loby = self.__add_region("The Body, before final boss", None)
|
||||
self.final_boss_tube = self.__add_region("The Body, final boss area turtle room",
|
||||
AquariaLocations.locations_final_boss_tube)
|
||||
self.final_boss = self.__add_region("The body, final boss",
|
||||
self.final_boss = self.__add_region("The Body, final boss",
|
||||
AquariaLocations.locations_final_boss)
|
||||
self.final_boss_end = self.__add_region("The body, final boss area", None)
|
||||
self.final_boss_end = self.__add_region("The Body, final boss area", None)
|
||||
|
||||
def __connect_one_way_regions(self, source_name: str, destination_name: str,
|
||||
source_region: Region,
|
||||
@@ -455,99 +455,99 @@ class AquariaRegions:
|
||||
"""
|
||||
Connect entrances of the different regions around `home_water`
|
||||
"""
|
||||
self.__connect_regions("Menu", "Verse cave right area",
|
||||
self.__connect_regions("Menu", "Verse Cave right area",
|
||||
self.menu, self.verse_cave_r)
|
||||
self.__connect_regions("Verse cave left area", "Verse cave right area",
|
||||
self.__connect_regions("Verse Cave left area", "Verse Cave right area",
|
||||
self.verse_cave_l, self.verse_cave_r)
|
||||
self.__connect_regions("Verse cave", "Home water", self.verse_cave_l, self.home_water)
|
||||
self.__connect_regions("Verse Cave", "Home Water", self.verse_cave_l, self.home_water)
|
||||
self.__connect_regions("Home Water", "Haija's home", self.home_water, self.naija_home)
|
||||
self.__connect_regions("Home Water", "Song cave", self.home_water, self.song_cave)
|
||||
self.__connect_regions("Home Water", "Home water, nautilus nest",
|
||||
self.__connect_regions("Home Water", "Song Cave", self.home_water, self.song_cave)
|
||||
self.__connect_regions("Home Water", "Home Water, nautilus nest",
|
||||
self.home_water, self.home_water_nautilus,
|
||||
lambda state: _has_energy_form(state, self.player) and _has_bind_song(state, self.player))
|
||||
self.__connect_regions("Home Water", "Home water transturtle room",
|
||||
self.__connect_regions("Home Water", "Home Water transturtle room",
|
||||
self.home_water, self.home_water_transturtle)
|
||||
self.__connect_regions("Home Water", "Energy temple first area",
|
||||
self.__connect_regions("Home Water", "Energy Temple first area",
|
||||
self.home_water, self.energy_temple_1,
|
||||
lambda state: _has_bind_song(state, self.player))
|
||||
self.__connect_regions("Home Water", "Energy temple_altar",
|
||||
self.__connect_regions("Home Water", "Energy Temple_altar",
|
||||
self.home_water, self.energy_temple_altar,
|
||||
lambda state: _has_energy_form(state, self.player) and
|
||||
_has_bind_song(state, self.player))
|
||||
self.__connect_regions("Energy temple first area", "Energy temple second area",
|
||||
self.__connect_regions("Energy Temple first area", "Energy Temple second area",
|
||||
self.energy_temple_1, self.energy_temple_2,
|
||||
lambda state: _has_energy_form(state, self.player))
|
||||
self.__connect_regions("Energy temple first area", "Energy temple idol room",
|
||||
self.__connect_regions("Energy Temple first area", "Energy Temple idol room",
|
||||
self.energy_temple_1, self.energy_temple_idol,
|
||||
lambda state: _has_fish_form(state, self.player))
|
||||
self.__connect_regions("Energy temple idol room", "Energy temple boss area",
|
||||
self.__connect_regions("Energy Temple idol room", "Energy Temple boss area",
|
||||
self.energy_temple_idol, self.energy_temple_boss,
|
||||
lambda state: _has_energy_form(state, self.player))
|
||||
self.__connect_one_way_regions("Energy temple first area", "Energy temple boss area",
|
||||
self.__connect_one_way_regions("Energy Temple first area", "Energy Temple boss area",
|
||||
self.energy_temple_1, self.energy_temple_boss,
|
||||
lambda state: _has_beast_form(state, self.player) and
|
||||
_has_energy_form(state, self.player))
|
||||
self.__connect_one_way_regions("Energy temple boss area", "Energy temple first area",
|
||||
self.__connect_one_way_regions("Energy Temple boss area", "Energy Temple first area",
|
||||
self.energy_temple_boss, self.energy_temple_1,
|
||||
lambda state: _has_energy_form(state, self.player))
|
||||
self.__connect_regions("Energy temple second area", "Energy temple third area",
|
||||
self.__connect_regions("Energy Temple second area", "Energy Temple third area",
|
||||
self.energy_temple_2, self.energy_temple_3,
|
||||
lambda state: _has_bind_song(state, self.player) and
|
||||
_has_energy_form(state, self.player))
|
||||
self.__connect_regions("Energy temple boss area", "Energy temple blaster room",
|
||||
self.__connect_regions("Energy Temple boss area", "Energy Temple blaster room",
|
||||
self.energy_temple_boss, self.energy_temple_blaster_room,
|
||||
lambda state: _has_nature_form(state, self.player) and
|
||||
_has_bind_song(state, self.player) and
|
||||
_has_energy_form(state, self.player))
|
||||
self.__connect_regions("Energy temple first area", "Energy temple blaster room",
|
||||
self.__connect_regions("Energy Temple first area", "Energy Temple blaster room",
|
||||
self.energy_temple_1, self.energy_temple_blaster_room,
|
||||
lambda state: _has_nature_form(state, self.player) and
|
||||
_has_bind_song(state, self.player) and
|
||||
_has_energy_form(state, self.player) and
|
||||
_has_beast_form(state, self.player))
|
||||
self.__connect_regions("Home Water", "Open water top left area",
|
||||
self.__connect_regions("Home Water", "Open Water top left area",
|
||||
self.home_water, self.openwater_tl)
|
||||
|
||||
def __connect_open_water_regions(self) -> None:
|
||||
"""
|
||||
Connect entrances of the different regions around open water
|
||||
"""
|
||||
self.__connect_regions("Open water top left area", "Open water top right area",
|
||||
self.__connect_regions("Open Water top left area", "Open Water top right area",
|
||||
self.openwater_tl, self.openwater_tr)
|
||||
self.__connect_regions("Open water top left area", "Open water bottom left area",
|
||||
self.__connect_regions("Open Water top left area", "Open Water bottom left area",
|
||||
self.openwater_tl, self.openwater_bl)
|
||||
self.__connect_regions("Open water top left area", "forest bottom right area",
|
||||
self.__connect_regions("Open Water top left area", "forest bottom right area",
|
||||
self.openwater_tl, self.forest_br)
|
||||
self.__connect_regions("Open water top right area", "Open water top right area, turtle room",
|
||||
self.__connect_regions("Open Water top right area", "Open Water top right area, turtle room",
|
||||
self.openwater_tr, self.openwater_tr_turtle,
|
||||
lambda state: _has_beast_form(state, self.player))
|
||||
self.__connect_regions("Open water top right area", "Open water bottom right area",
|
||||
self.__connect_regions("Open Water top right area", "Open Water bottom right area",
|
||||
self.openwater_tr, self.openwater_br)
|
||||
self.__connect_regions("Open water top right area", "Mithalas city",
|
||||
self.__connect_regions("Open Water top right area", "Mithalas City",
|
||||
self.openwater_tr, self.mithalas_city)
|
||||
self.__connect_regions("Open water top right area", "Veil bottom left area",
|
||||
self.__connect_regions("Open Water top right area", "Veil bottom left area",
|
||||
self.openwater_tr, self.veil_bl)
|
||||
self.__connect_one_way_regions("Open water top right area", "Veil bottom right",
|
||||
self.__connect_one_way_regions("Open Water top right area", "Veil bottom right",
|
||||
self.openwater_tr, self.veil_br,
|
||||
lambda state: _has_beast_form(state, self.player))
|
||||
self.__connect_one_way_regions("Veil bottom right", "Open water top right area",
|
||||
self.__connect_one_way_regions("Veil bottom right", "Open Water top right area",
|
||||
self.veil_br, self.openwater_tr,
|
||||
lambda state: _has_beast_form(state, self.player))
|
||||
self.__connect_regions("Open water bottom left area", "Open water bottom right area",
|
||||
self.__connect_regions("Open Water bottom left area", "Open Water bottom right area",
|
||||
self.openwater_bl, self.openwater_br)
|
||||
self.__connect_regions("Open water bottom left area", "Skeleton path",
|
||||
self.__connect_regions("Open Water bottom left area", "Skeleton path",
|
||||
self.openwater_bl, self.skeleton_path)
|
||||
self.__connect_regions("Abyss left area", "Open water bottom left area",
|
||||
self.__connect_regions("Abyss left area", "Open Water bottom left area",
|
||||
self.abyss_l, self.openwater_bl)
|
||||
self.__connect_regions("Skeleton path", "skeleton_path_sc",
|
||||
self.skeleton_path, self.skeleton_path_sc,
|
||||
lambda state: _has_spirit_form(state, self.player))
|
||||
self.__connect_regions("Abyss right area", "Open water bottom right area",
|
||||
self.__connect_regions("Abyss right area", "Open Water bottom right area",
|
||||
self.abyss_r, self.openwater_br)
|
||||
self.__connect_one_way_regions("Open water bottom right area", "Arnassi",
|
||||
self.__connect_one_way_regions("Open Water bottom right area", "Arnassi",
|
||||
self.openwater_br, self.arnassi,
|
||||
lambda state: _has_beast_form(state, self.player))
|
||||
self.__connect_one_way_regions("Arnassi", "Open water bottom right area",
|
||||
self.__connect_one_way_regions("Arnassi", "Open Water bottom right area",
|
||||
self.arnassi, self.openwater_br)
|
||||
self.__connect_regions("Arnassi", "Arnassi path",
|
||||
self.arnassi, self.arnassi_path)
|
||||
@@ -562,23 +562,23 @@ class AquariaRegions:
|
||||
"""
|
||||
Connect entrances of the different regions around Mithalas
|
||||
"""
|
||||
self.__connect_one_way_regions("Mithalas city", "Mithalas city top path",
|
||||
self.__connect_one_way_regions("Mithalas City", "Mithalas City top path",
|
||||
self.mithalas_city, self.mithalas_city_top_path,
|
||||
lambda state: _has_beast_form(state, self.player))
|
||||
self.__connect_one_way_regions("Mithalas city_top_path", "Mithalas city",
|
||||
self.__connect_one_way_regions("Mithalas City_top_path", "Mithalas City",
|
||||
self.mithalas_city_top_path, self.mithalas_city)
|
||||
self.__connect_regions("Mithalas city", "Mithalas city home with fishpass",
|
||||
self.__connect_regions("Mithalas City", "Mithalas City home with fishpass",
|
||||
self.mithalas_city, self.mithalas_city_fishpass,
|
||||
lambda state: _has_fish_form(state, self.player))
|
||||
self.__connect_regions("Mithalas city", "Mithalas castle",
|
||||
self.__connect_regions("Mithalas City", "Mithalas castle",
|
||||
self.mithalas_city, self.cathedral_l,
|
||||
lambda state: _has_fish_form(state, self.player))
|
||||
self.__connect_one_way_regions("Mithalas city top path", "Mithalas castle, flower tube",
|
||||
self.__connect_one_way_regions("Mithalas City top path", "Mithalas castle, flower tube",
|
||||
self.mithalas_city_top_path,
|
||||
self.cathedral_l_tube,
|
||||
lambda state: _has_nature_form(state, self.player) and
|
||||
_has_energy_form(state, self.player))
|
||||
self.__connect_one_way_regions("Mithalas castle, flower tube area", "Mithalas city top path",
|
||||
self.__connect_one_way_regions("Mithalas castle, flower tube area", "Mithalas City top path",
|
||||
self.cathedral_l_tube,
|
||||
self.mithalas_city_top_path,
|
||||
lambda state: _has_beast_form(state, self.player) and
|
||||
@@ -690,22 +690,22 @@ class AquariaRegions:
|
||||
self.veil_tl, self.veil_tr_r)
|
||||
self.__connect_regions("Veil top left area", "Turtle cave",
|
||||
self.veil_tl, self.turtle_cave)
|
||||
self.__connect_regions("Turtle cave", "Turtle cave bubble cliff",
|
||||
self.__connect_regions("Turtle cave", "Turtle cave Bubble Cliff",
|
||||
self.turtle_cave, self.turtle_cave_bubble,
|
||||
lambda state: _has_beast_form(state, self.player))
|
||||
self.__connect_regions("Veil right of sun temple", "Sun temple right area",
|
||||
self.__connect_regions("Veil right of sun temple", "Sun Temple right area",
|
||||
self.veil_tr_r, self.sun_temple_r)
|
||||
self.__connect_regions("Sun temple right area", "Sun temple left area",
|
||||
self.__connect_regions("Sun Temple right area", "Sun Temple left area",
|
||||
self.sun_temple_r, self.sun_temple_l,
|
||||
lambda state: _has_bind_song(state, self.player))
|
||||
self.__connect_regions("Sun temple left area", "Veil left of sun temple",
|
||||
self.__connect_regions("Sun Temple left area", "Veil left of sun temple",
|
||||
self.sun_temple_l, self.veil_tr_l)
|
||||
self.__connect_regions("Sun temple left area", "Sun temple before boss area",
|
||||
self.__connect_regions("Sun Temple left area", "Sun Temple before boss area",
|
||||
self.sun_temple_l, self.sun_temple_boss_path)
|
||||
self.__connect_regions("Sun temple before boss area", "Sun temple boss area",
|
||||
self.__connect_regions("Sun Temple before boss area", "Sun Temple boss area",
|
||||
self.sun_temple_boss_path, self.sun_temple_boss,
|
||||
lambda state: _has_energy_form(state, self.player))
|
||||
self.__connect_one_way_regions("Sun temple boss area", "Veil left of sun temple",
|
||||
self.__connect_one_way_regions("Sun Temple boss area", "Veil left of sun temple",
|
||||
self.sun_temple_boss, self.veil_tr_l)
|
||||
self.__connect_regions("Veil left of sun temple", "Octo cave top path",
|
||||
self.veil_tr_l, self.octo_cave_t,
|
||||
@@ -724,7 +724,7 @@ class AquariaRegions:
|
||||
self.__connect_regions("Abyss left area", "Abyss bottom of left area",
|
||||
self.abyss_l, self.abyss_lb,
|
||||
lambda state: _has_nature_form(state, self.player))
|
||||
self.__connect_regions("Abyss left bottom area", "Sunken city right area",
|
||||
self.__connect_regions("Abyss left bottom area", "Sunken City right area",
|
||||
self.abyss_lb, self.sunken_city_r,
|
||||
lambda state: _has_li(state, self.player))
|
||||
self.__connect_one_way_regions("Abyss left bottom area", "Body center area",
|
||||
@@ -748,13 +748,13 @@ class AquariaRegions:
|
||||
_has_sun_form(state, self.player) and
|
||||
_has_bind_song(state, self.player) and
|
||||
_has_energy_form(state, self.player))
|
||||
self.__connect_regions("Abyss right area", "Ice cave",
|
||||
self.__connect_regions("Abyss right area", "Ice Cave",
|
||||
self.abyss_r, self.ice_cave,
|
||||
lambda state: _has_spirit_form(state, self.player))
|
||||
self.__connect_regions("Abyss right area", "Bubble cave",
|
||||
self.__connect_regions("Abyss right area", "Bubble Cave",
|
||||
self.ice_cave, self.bubble_cave,
|
||||
lambda state: _has_beast_form(state, self.player))
|
||||
self.__connect_regions("Bubble cave boss area", "Bubble cave",
|
||||
self.__connect_regions("Bubble Cave boss area", "Bubble Cave",
|
||||
self.bubble_cave, self.bubble_cave_boss,
|
||||
lambda state: _has_nature_form(state, self.player) and _has_bind_song(state, self.player)
|
||||
)
|
||||
@@ -763,12 +763,12 @@ class AquariaRegions:
|
||||
"""
|
||||
Connect entrances of the different regions around The Sunken City
|
||||
"""
|
||||
self.__connect_regions("Sunken city right area", "Sunken city left area",
|
||||
self.__connect_regions("Sunken City right area", "Sunken City left area",
|
||||
self.sunken_city_r, self.sunken_city_l)
|
||||
self.__connect_regions("Sunken city left area", "Sunken city bedroom",
|
||||
self.__connect_regions("Sunken City left area", "Sunken City bedroom",
|
||||
self.sunken_city_l, self.sunken_city_l_bedroom,
|
||||
lambda state: _has_spirit_form(state, self.player))
|
||||
self.__connect_regions("Sunken city left area", "Sunken city boss area",
|
||||
self.__connect_regions("Sunken City left area", "Sunken City boss area",
|
||||
self.sunken_city_l, self.sunken_city_boss,
|
||||
lambda state: _has_beast_form(state, self.player) and
|
||||
_has_energy_form(state, self.player) and
|
||||
@@ -776,7 +776,7 @@ class AquariaRegions:
|
||||
|
||||
def __connect_body_regions(self) -> None:
|
||||
"""
|
||||
Connect entrances of the different regions around The body
|
||||
Connect entrances of the different regions around The Body
|
||||
"""
|
||||
self.__connect_regions("Body center area", "Body left area",
|
||||
self.body_c, self.body_l)
|
||||
@@ -787,13 +787,13 @@ class AquariaRegions:
|
||||
self.__connect_regions("Body center area", "Body bottom area",
|
||||
self.body_c, self.body_b,
|
||||
lambda state: _has_dual_form(state, self.player))
|
||||
self.__connect_regions("Body bottom area", "Final boss area",
|
||||
self.__connect_regions("Body bottom area", "Final Boss area",
|
||||
self.body_b, self.final_boss_loby,
|
||||
lambda state: _has_dual_form(state, self.player))
|
||||
self.__connect_regions("Before Final boss", "Final boss tube",
|
||||
self.__connect_regions("Before Final Boss", "Final Boss tube",
|
||||
self.final_boss_loby, self.final_boss_tube,
|
||||
lambda state: _has_nature_form(state, self.player))
|
||||
self.__connect_one_way_regions("Before Final boss", "Final boss",
|
||||
self.__connect_one_way_regions("Before Final Boss", "Final Boss",
|
||||
self.final_boss_loby, self.final_boss,
|
||||
lambda state: _has_energy_form(state, self.player) and
|
||||
_has_dual_form(state, self.player) and
|
||||
@@ -814,7 +814,7 @@ class AquariaRegions:
|
||||
|
||||
def __connect_arnassi_path_transturtle(self, item_source: str, item_target: str, region_source: Region,
|
||||
region_target: Region) -> None:
|
||||
"""Connect the Arnassi ruins transturtle to another one"""
|
||||
"""Connect the Arnassi Ruins transturtle to another one"""
|
||||
self.__connect_one_way_regions(item_source, item_target, region_source, region_target,
|
||||
lambda state: state.has(item_target, self.player) and
|
||||
_has_fish_form(state, self.player))
|
||||
@@ -825,25 +825,25 @@ class AquariaRegions:
|
||||
self.__connect_transturtle(item, "Transturtle Veil top right", region, self.veil_tr_l)
|
||||
self.__connect_transturtle(item, "Transturtle Open Water top right", region, self.openwater_tr_turtle)
|
||||
self.__connect_transturtle(item, "Transturtle Forest bottom left", region, self.forest_bl)
|
||||
self.__connect_transturtle(item, "Transturtle Home water", region, self.home_water_transturtle)
|
||||
self.__connect_transturtle(item, "Transturtle Home Water", region, self.home_water_transturtle)
|
||||
self.__connect_transturtle(item, "Transturtle Abyss right", region, self.abyss_r)
|
||||
self.__connect_transturtle(item, "Transturtle Final Boss", region, self.final_boss_tube)
|
||||
self.__connect_transturtle(item, "Transturtle Simon says", region, self.simon)
|
||||
self.__connect_transturtle(item, "Transturtle Arnassi ruins", region, self.arnassi_path,
|
||||
lambda state: state.has("Transturtle Arnassi ruins", self.player) and
|
||||
self.__connect_transturtle(item, "Transturtle Simon Says", region, self.simon)
|
||||
self.__connect_transturtle(item, "Transturtle Arnassi Ruins", region, self.arnassi_path,
|
||||
lambda state: state.has("Transturtle Arnassi Ruins", self.player) and
|
||||
_has_fish_form(state, self.player))
|
||||
|
||||
def _connect_arnassi_path_transturtle_to_other(self, item: str, region: Region) -> None:
|
||||
"""Connect the Arnassi ruins transturtle to all others"""
|
||||
"""Connect the Arnassi Ruins transturtle to all others"""
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Veil top left", region, self.veil_tl)
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Veil top right", region, self.veil_tr_l)
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Open Water top right", region,
|
||||
self.openwater_tr_turtle)
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Forest bottom left", region, self.forest_bl)
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Home water", region, self.home_water_transturtle)
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Home Water", region, self.home_water_transturtle)
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Abyss right", region, self.abyss_r)
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Final Boss", region, self.final_boss_tube)
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Simon says", region, self.simon)
|
||||
self.__connect_arnassi_path_transturtle(item, "Transturtle Simon Says", region, self.simon)
|
||||
|
||||
def __connect_transturtles(self) -> None:
|
||||
"""Connect every transturtle with others"""
|
||||
@@ -851,11 +851,11 @@ class AquariaRegions:
|
||||
self._connect_transturtle_to_other("Transturtle Veil top right", self.veil_tr_l)
|
||||
self._connect_transturtle_to_other("Transturtle Open Water top right", self.openwater_tr_turtle)
|
||||
self._connect_transturtle_to_other("Transturtle Forest bottom left", self.forest_bl)
|
||||
self._connect_transturtle_to_other("Transturtle Home water", self.home_water_transturtle)
|
||||
self._connect_transturtle_to_other("Transturtle Home Water", self.home_water_transturtle)
|
||||
self._connect_transturtle_to_other("Transturtle Abyss right", self.abyss_r)
|
||||
self._connect_transturtle_to_other("Transturtle Final Boss", self.final_boss_tube)
|
||||
self._connect_transturtle_to_other("Transturtle Simon says", self.simon)
|
||||
self._connect_arnassi_path_transturtle_to_other("Transturtle Arnassi ruins", self.arnassi_path)
|
||||
self._connect_transturtle_to_other("Transturtle Simon Says", self.simon)
|
||||
self._connect_arnassi_path_transturtle_to_other("Transturtle Arnassi Ruins", self.arnassi_path)
|
||||
|
||||
def connect_regions(self) -> None:
|
||||
"""
|
||||
@@ -907,7 +907,7 @@ class AquariaRegions:
|
||||
|
||||
def __add_event_mini_bosses(self) -> None:
|
||||
"""
|
||||
Add every mini bosses (excluding Energy statue and Simon says)
|
||||
Add every mini bosses (excluding Energy Statue and Simon Says)
|
||||
events to the `world`
|
||||
"""
|
||||
self.__add_event_location(self.home_water_nautilus,
|
||||
@@ -967,100 +967,100 @@ class AquariaRegions:
|
||||
|
||||
def __adjusting_urns_rules(self) -> None:
|
||||
"""Since Urns need to be broken, add a damaging item to rules"""
|
||||
add_rule(self.multiworld.get_location("Open water top right area, first urn in the Mithalas exit", self.player),
|
||||
add_rule(self.multiworld.get_location("Open Water top right area, first urn in the Mithalas exit", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Open water top right area, second urn in the Mithalas exit", self.player),
|
||||
add_rule(self.multiworld.get_location("Open Water top right area, second urn in the Mithalas exit", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Open water top right area, third urn in the Mithalas exit", self.player),
|
||||
add_rule(self.multiworld.get_location("Open Water top right area, third urn in the Mithalas exit", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city, first urn in one of the homes", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City, first urn in one of the homes", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city, second urn in one of the homes", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City, second urn in one of the homes", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city, first urn in the city reserve", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City, first urn in the city reserve", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city, second urn in the city reserve", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City, second urn in the city reserve", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city, third urn in the city reserve", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City, third urn in the city reserve", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city, urn in the cathedral flower tube entrance", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City, urn in the Cathedral flower tube entrance", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city castle, urn in the bedroom", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City Castle, urn in the bedroom", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city castle, first urn of the single lamp path", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City Castle, first urn of the single lamp path", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city castle, second urn of the single lamp path", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City Castle, second urn of the single lamp path", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city castle, urn in the bottom room", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City Castle, urn in the bottom room", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city castle, first urn on the entrance path", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City Castle, first urn on the entrance path", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city castle, second urn on the entrance path", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City Castle, second urn on the entrance path", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Mithalas city, urn inside a home fish pass", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas City, urn inside a home fish pass", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
|
||||
def __adjusting_crates_rules(self) -> None:
|
||||
"""Since Crate need to be broken, add a damaging item to rules"""
|
||||
add_rule(self.multiworld.get_location("Sunken city right area, crate close to the save cristal", self.player),
|
||||
add_rule(self.multiworld.get_location("Sunken City right area, crate close to the save crystal", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Sunken city right area, crate in the left bottom room", self.player),
|
||||
add_rule(self.multiworld.get_location("Sunken City right area, crate in the left bottom room", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Sunken city left area, crate in the little pipe room", self.player),
|
||||
add_rule(self.multiworld.get_location("Sunken City left area, crate in the little pipe room", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Sunken city left area, crate close to the save cristal", self.player),
|
||||
add_rule(self.multiworld.get_location("Sunken City left area, crate close to the save crystal", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Sunken city left area, crate before the bedroom", self.player),
|
||||
add_rule(self.multiworld.get_location("Sunken City left area, crate before the bedroom", self.player),
|
||||
lambda state: _has_damaging_item(state, self.player))
|
||||
|
||||
def __adjusting_soup_rules(self) -> None:
|
||||
"""
|
||||
Modify rules for location that need soup
|
||||
"""
|
||||
add_rule(self.multiworld.get_location("Turtle cave, Urchin costume", self.player),
|
||||
add_rule(self.multiworld.get_location("Turtle cave, Urchin Costume", self.player),
|
||||
lambda state: _has_hot_soup(state, self.player) and _has_beast_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Sun Worm path, first cliff bulb", self.player),
|
||||
lambda state: _has_hot_soup(state, self.player) and _has_beast_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Sun Worm path, second cliff bulb", self.player),
|
||||
lambda state: _has_hot_soup(state, self.player) and _has_beast_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("The veil top right area, bulb in the top of the water fall", self.player),
|
||||
add_rule(self.multiworld.get_location("The Veil top right area, bulb in the top of the waterfall", self.player),
|
||||
lambda state: _has_hot_soup(state, self.player) and _has_beast_form(state, self.player))
|
||||
|
||||
def __adjusting_under_rock_location(self) -> None:
|
||||
"""
|
||||
Modify rules implying bind song needed for bulb under rocks
|
||||
"""
|
||||
add_rule(self.multiworld.get_location("Home water, bulb under the rock in the left path from the verse cave",
|
||||
add_rule(self.multiworld.get_location("Home Water, bulb under the rock in the left path from the Verse Cave",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Verse cave left area, bulb under the rock at the end of the path",
|
||||
add_rule(self.multiworld.get_location("Verse Cave left area, bulb under the rock at the end of the path",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Naija's home, bulb under the rock at the right of the main path",
|
||||
add_rule(self.multiworld.get_location("Naija's Home, bulb under the rock at the right of the main path",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Song cave, bulb under the rock in the path to the singing statues",
|
||||
add_rule(self.multiworld.get_location("Song Cave, bulb under the rock in the path to the singing statues",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Song cave, bulb under the rock close to the song door",
|
||||
add_rule(self.multiworld.get_location("Song Cave, bulb under the rock close to the song door",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Energy temple second area, bulb under the rock",
|
||||
add_rule(self.multiworld.get_location("Energy Temple second area, bulb under the rock",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Open water top left area, bulb under the rock in the right path",
|
||||
add_rule(self.multiworld.get_location("Open Water top left area, bulb under the rock in the right path",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Open water top left area, bulb under the rock in the left path",
|
||||
add_rule(self.multiworld.get_location("Open Water top left area, bulb under the rock in the left path",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Kelp Forest top right area, bulb under the rock in the right path",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("The veil top left area, bulb under the rock in the top right path",
|
||||
add_rule(self.multiworld.get_location("The Veil top left area, bulb under the rock in the top right path",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Abyss right area, bulb behind the rock in the whale room",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Abyss right area, bulb in the middle path",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("The veil top left area, bulb under the rock in the top right path",
|
||||
add_rule(self.multiworld.get_location("The Veil top left area, bulb under the rock in the top right path",
|
||||
self.player), lambda state: _has_bind_song(state, self.player))
|
||||
|
||||
def __adjusting_light_in_dark_place_rules(self) -> None:
|
||||
add_rule(self.multiworld.get_location("Kelp forest top right area, Black pearl", self.player),
|
||||
add_rule(self.multiworld.get_location("Kelp Forest top right area, Black Pearl", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Kelp forest bottom right area, Odd Container", self.player),
|
||||
add_rule(self.multiworld.get_location("Kelp Forest bottom right area, Odd Container", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Transturtle Veil top left to Transturtle Abyss right", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
@@ -1070,103 +1070,103 @@ class AquariaRegions:
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Transturtle Forest bottom left to Transturtle Abyss right", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Transturtle Home water to Transturtle Abyss right", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Transturtle Home Water to Transturtle Abyss right", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Transturtle Final Boss to Transturtle Abyss right", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Transturtle Simon says to Transturtle Abyss right", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Transturtle Simon Says to Transturtle Abyss right", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Transturtle Arnassi ruins to Transturtle Abyss right", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Transturtle Arnassi Ruins to Transturtle Abyss right", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Body center area to Abyss left bottom area", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Veil left of sun temple to Octo cave top path", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Open water bottom right area to Abyss right area", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Open Water bottom right area to Abyss right area", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Open water bottom left area to Abyss left area", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Open Water bottom left area to Abyss left area", self.player),
|
||||
lambda state: _has_light(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Sun temple left area to Sun temple right area", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Sun Temple left area to Sun Temple right area", self.player),
|
||||
lambda state: _has_light(state, self.player) or _has_sun_crystal(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Sun temple right area to Sun temple left area", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Sun Temple right area to Sun Temple left area", self.player),
|
||||
lambda state: _has_light(state, self.player) or _has_sun_crystal(state, self.player))
|
||||
add_rule(self.multiworld.get_entrance("Veil left of sun temple to Sun temple left area", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Veil left of sun temple to Sun Temple left area", self.player),
|
||||
lambda state: _has_light(state, self.player) or _has_sun_crystal(state, self.player))
|
||||
|
||||
def __adjusting_manual_rules(self) -> None:
|
||||
add_rule(self.multiworld.get_location("Mithalas cathedral, Mithalan Dress", self.player),
|
||||
add_rule(self.multiworld.get_location("Mithalas Cathedral, Mithalan Dress", self.player),
|
||||
lambda state: _has_beast_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Open water bottom left area, bulb inside the lowest fish pass", self.player),
|
||||
add_rule(self.multiworld.get_location("Open Water bottom left area, bulb inside the lowest fish pass", self.player),
|
||||
lambda state: _has_fish_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Kelp forest bottom left area, Walker baby", self.player),
|
||||
add_rule(self.multiworld.get_location("Kelp Forest bottom left area, Walker baby", self.player),
|
||||
lambda state: _has_spirit_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("The veil top left area, bulb hidden behind the blocking rock", self.player),
|
||||
add_rule(self.multiworld.get_location("The Veil top left area, bulb hidden behind the blocking rock", self.player),
|
||||
lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Turtle cave, Turtle Egg", self.player),
|
||||
lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Abyss left area, bulb in the bottom fish pass", self.player),
|
||||
lambda state: _has_fish_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Song cave, Anemone seed", self.player),
|
||||
add_rule(self.multiworld.get_location("Song Cave, Anemone Seed", self.player),
|
||||
lambda state: _has_nature_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Song cave, Verse egg", self.player),
|
||||
add_rule(self.multiworld.get_location("Song Cave, Verse Egg", self.player),
|
||||
lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Verse cave right area, Big Seed", self.player),
|
||||
add_rule(self.multiworld.get_location("Verse Cave right area, Big Seed", self.player),
|
||||
lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Arnassi ruins, Song plant spore on the top of the ruins", self.player),
|
||||
add_rule(self.multiworld.get_location("Arnassi Ruins, Song Plant Spore", self.player),
|
||||
lambda state: _has_beast_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Energy temple first area, bulb in the bottom room blocked by a rock",
|
||||
add_rule(self.multiworld.get_location("Energy Temple first area, bulb in the bottom room blocked by a rock",
|
||||
self.player), lambda state: _has_energy_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Home water, bulb in the bottom left room", self.player),
|
||||
add_rule(self.multiworld.get_location("Home Water, bulb in the bottom left room", self.player),
|
||||
lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Home water, bulb in the path below Nautilus Prime", self.player),
|
||||
add_rule(self.multiworld.get_location("Home Water, bulb in the path below Nautilus Prime", self.player),
|
||||
lambda state: _has_bind_song(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Naija's home, bulb after the energy door", self.player),
|
||||
add_rule(self.multiworld.get_location("Naija's Home, bulb after the energy door", self.player),
|
||||
lambda state: _has_energy_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Abyss right area, bulb behind the rock in the whale room", self.player),
|
||||
lambda state: _has_spirit_form(state, self.player) and
|
||||
_has_sun_form(state, self.player))
|
||||
add_rule(self.multiworld.get_location("Arnassi ruins, Arnassi Armor", self.player),
|
||||
add_rule(self.multiworld.get_location("Arnassi Ruins, Arnassi Armor", self.player),
|
||||
lambda state: _has_fish_form(state, self.player) and
|
||||
_has_spirit_form(state, self.player))
|
||||
|
||||
def __no_progression_hard_or_hidden_location(self) -> None:
|
||||
self.multiworld.get_location("Energy temple boss area, Fallen god tooth",
|
||||
self.multiworld.get_location("Energy Temple boss area, Fallen God Tooth",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Cathedral boss area, beating Mithalan God",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Kelp forest boss area, beating Drunian God",
|
||||
self.multiworld.get_location("Kelp Forest boss area, beating Drunian God",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Sun temple boss area, beating Sun God",
|
||||
self.multiworld.get_location("Sun Temple boss area, beating Sun God",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Sunken city, bulb on the top of the boss area (boiler room)",
|
||||
self.multiworld.get_location("Sunken City, bulb on top of the boss area",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Home water, Nautilus Egg",
|
||||
self.multiworld.get_location("Home Water, Nautilus Egg",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Energy temple blaster room, Blaster egg",
|
||||
self.multiworld.get_location("Energy Temple blaster room, Blaster Egg",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Mithalas castle, beating the priests",
|
||||
self.multiworld.get_location("Mithalas City Castle, beating the Priests",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Mermog cave, Piranha Egg",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Octopus cave, Dumbo Egg",
|
||||
self.multiworld.get_location("Octopus Cave, Dumbo Egg",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("King Jellyfish cave, bulb in the right path from King Jelly",
|
||||
self.multiworld.get_location("King Jellyfish Cave, bulb in the right path from King Jelly",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("King Jellyfish cave, Jellyfish Costume",
|
||||
self.multiworld.get_location("King Jellyfish Cave, Jellyfish Costume",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Final boss area, bulb in the boss third form room",
|
||||
self.multiworld.get_location("Final Boss area, bulb in the boss third form room",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Sun Worm path, first cliff bulb",
|
||||
@@ -1175,34 +1175,34 @@ class AquariaRegions:
|
||||
self.multiworld.get_location("Sun Worm path, second cliff bulb",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("The veil top right area, bulb in the top of the water fall",
|
||||
self.multiworld.get_location("The Veil top right area, bulb in the top of the waterfall",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Bubble cave, bulb in the left cave wall",
|
||||
self.multiworld.get_location("Bubble Cave, bulb in the left cave wall",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Bubble cave, bulb in the right cave wall (behind the ice cristal)",
|
||||
self.multiworld.get_location("Bubble Cave, bulb in the right cave wall (behind the ice crystal)",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Bubble cave, Verse egg",
|
||||
self.multiworld.get_location("Bubble Cave, Verse Egg",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Kelp Forest bottom left area, bulb close to the spirit crystals",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Kelp forest bottom left area, Walker baby",
|
||||
self.multiworld.get_location("Kelp Forest bottom left area, Walker baby",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Sun temple, Sun key",
|
||||
self.multiworld.get_location("Sun Temple, Sun Key",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("The body bottom area, Mutant Costume",
|
||||
self.multiworld.get_location("The Body bottom area, Mutant Costume",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Sun temple, bulb in the hidden room of the right part",
|
||||
self.multiworld.get_location("Sun Temple, bulb in the hidden room of the right part",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
self.multiworld.get_location("Arnassi ruins, Arnassi Armor",
|
||||
self.multiworld.get_location("Arnassi Ruins, Arnassi Armor",
|
||||
self.player).item_rule =\
|
||||
lambda item: item.classification != ItemClassification.progression
|
||||
|
||||
@@ -1220,19 +1220,19 @@ class AquariaRegions:
|
||||
self.__adjusting_under_rock_location()
|
||||
|
||||
if options.mini_bosses_to_beat.value > 0:
|
||||
add_rule(self.multiworld.get_entrance("Before Final boss to Final boss", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Before Final Boss to Final Boss", self.player),
|
||||
lambda state: _has_mini_bosses(state, self.player))
|
||||
if options.big_bosses_to_beat.value > 0:
|
||||
add_rule(self.multiworld.get_entrance("Before Final boss to Final boss", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Before Final Boss to Final Boss", self.player),
|
||||
lambda state: _has_big_bosses(state, self.player))
|
||||
if options.objective.value == 1:
|
||||
add_rule(self.multiworld.get_entrance("Before Final boss to Final boss", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Before Final Boss to Final Boss", self.player),
|
||||
lambda state: _has_secrets(state, self.player))
|
||||
if options.unconfine_home_water.value in [0, 1]:
|
||||
add_rule(self.multiworld.get_entrance("Home Water to Home water transturtle room", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Home Water to Home Water transturtle room", self.player),
|
||||
lambda state: _has_bind_song(state, self.player))
|
||||
if options.unconfine_home_water.value in [0, 2]:
|
||||
add_rule(self.multiworld.get_entrance("Home Water to Open water top left area", self.player),
|
||||
add_rule(self.multiworld.get_entrance("Home Water to Open Water top left area", self.player),
|
||||
lambda state: _has_bind_song(state, self.player) and _has_energy_form(state, self.player))
|
||||
if options.early_energy_form:
|
||||
self.multiworld.early_items[self.player]["Energy form"] = 1
|
||||
|
||||
@@ -71,9 +71,9 @@ class AquariaWorld(World):
|
||||
|
||||
item_name_groups = {
|
||||
"Damage": {"Energy form", "Nature form", "Beast form",
|
||||
"Li and Li song", "Baby nautilus", "Baby piranha",
|
||||
"Baby blaster"},
|
||||
"Light": {"Sun form", "Baby dumbo"}
|
||||
"Li and Li song", "Baby Nautilus", "Baby Piranha",
|
||||
"Baby Blaster"},
|
||||
"Light": {"Sun form", "Baby Dumbo"}
|
||||
}
|
||||
"""Grouping item make it easier to find them"""
|
||||
|
||||
@@ -152,20 +152,20 @@ class AquariaWorld(World):
|
||||
precollected = [item.name for item in self.multiworld.precollected_items[self.player]]
|
||||
if self.options.turtle_randomizer.value > 0:
|
||||
if self.options.turtle_randomizer.value == 2:
|
||||
self.__pre_fill_item("Transturtle Final Boss", "Final boss area, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Final Boss", "Final Boss area, Transturtle", precollected)
|
||||
else:
|
||||
self.__pre_fill_item("Transturtle Veil top left", "The veil top left area, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Veil top right", "The veil top right area, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Open Water top right", "Open water top right area, Transturtle",
|
||||
self.__pre_fill_item("Transturtle Veil top left", "The Veil top left area, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Veil top right", "The Veil top right area, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Open Water top right", "Open Water top right area, Transturtle",
|
||||
precollected)
|
||||
self.__pre_fill_item("Transturtle Forest bottom left", "Kelp Forest bottom left area, Transturtle",
|
||||
precollected)
|
||||
self.__pre_fill_item("Transturtle Home water", "Home water, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Home Water", "Home Water, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Abyss right", "Abyss right area, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Final Boss", "Final boss area, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Final Boss", "Final Boss area, Transturtle", precollected)
|
||||
# The last two are inverted because in the original game, they are special turtle that communicate directly
|
||||
self.__pre_fill_item("Transturtle Simon says", "Arnassi Ruins, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Arnassi ruins", "Simon says area, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Simon Says", "Arnassi Ruins, Transturtle", precollected)
|
||||
self.__pre_fill_item("Transturtle Arnassi Ruins", "Simon Says area, Transturtle", precollected)
|
||||
for name, data in item_table.items():
|
||||
if name in precollected:
|
||||
precollected.remove(name)
|
||||
|
||||
@@ -15,14 +15,14 @@ The locations in the randomizer are:
|
||||
- All Mithalas Urns
|
||||
- All Sunken City crates
|
||||
- Collectible treasure locations (including pet eggs and costumes)
|
||||
- Beating Simon says
|
||||
- Beating Simon Says
|
||||
- Li cave
|
||||
- Every Transportation Turtle (also called transturtle)
|
||||
- Locations where you get songs:
|
||||
* Erulian spirit cristal
|
||||
* Erulian spirit crystal
|
||||
* Energy status mini-boss
|
||||
* Beating Mithalan God boss
|
||||
* Fish cave puzzle
|
||||
* Fish Cave puzzle
|
||||
* Beating Drunian God boss
|
||||
* Beating Sun God boss
|
||||
* Breaking Li cage in the body
|
||||
@@ -61,4 +61,4 @@ what has been collected and who will receive it.
|
||||
|
||||
## When the player receives an item, what happens?
|
||||
When you receive an item, a message will pop up to inform you where you received
|
||||
the item from and which one it was.
|
||||
the item from and which one it was.
|
||||
|
||||
@@ -10,148 +10,148 @@ from test.bases import WorldTestBase
|
||||
# Every location accessible after the home water.
|
||||
after_home_water_locations = [
|
||||
"Sun Crystal",
|
||||
"Home water, Transturtle",
|
||||
"Open water top left area, bulb under the rock in the right path",
|
||||
"Open water top left area, bulb under the rock in the left path",
|
||||
"Open water top left area, bulb to the right of the save cristal",
|
||||
"Open water top right area, bulb in the small path before Mithalas",
|
||||
"Open water top right area, bulb in the path from the left entrance",
|
||||
"Open water top right area, bulb in the clearing close to the bottom exit",
|
||||
"Open water top right area, bulb in the big clearing close to the save cristal",
|
||||
"Open water top right area, bulb in the big clearing to the top exit",
|
||||
"Open water top right area, first urn in the Mithalas exit",
|
||||
"Open water top right area, second urn in the Mithalas exit",
|
||||
"Open water top right area, third urn in the Mithalas exit",
|
||||
"Open water top right area, bulb in the turtle room",
|
||||
"Open water top right area, Transturtle",
|
||||
"Open water bottom left area, bulb behind the chomper fish",
|
||||
"Open water bottom left area, bulb inside the lowest fish pass",
|
||||
"Open water skeleton path, bulb close to the right exit",
|
||||
"Open water skeleton path, bulb behind the chomper fish",
|
||||
"Open water skeleton path, King skull",
|
||||
"Home Water, Transturtle",
|
||||
"Open Water top left area, bulb under the rock in the right path",
|
||||
"Open Water top left area, bulb under the rock in the left path",
|
||||
"Open Water top left area, bulb to the right of the save crystal",
|
||||
"Open Water top right area, bulb in the small path before Mithalas",
|
||||
"Open Water top right area, bulb in the path from the left entrance",
|
||||
"Open Water top right area, bulb in the clearing close to the bottom exit",
|
||||
"Open Water top right area, bulb in the big clearing close to the save crystal",
|
||||
"Open Water top right area, bulb in the big clearing to the top exit",
|
||||
"Open Water top right area, first urn in the Mithalas exit",
|
||||
"Open Water top right area, second urn in the Mithalas exit",
|
||||
"Open Water top right area, third urn in the Mithalas exit",
|
||||
"Open Water top right area, bulb in the turtle room",
|
||||
"Open Water top right area, Transturtle",
|
||||
"Open Water bottom left area, bulb behind the chomper fish",
|
||||
"Open Water bottom left area, bulb inside the lowest fish pass",
|
||||
"Open Water skeleton path, bulb close to the right exit",
|
||||
"Open Water skeleton path, bulb behind the chomper fish",
|
||||
"Open Water skeleton path, King Skull",
|
||||
"Arnassi Ruins, bulb in the right part",
|
||||
"Arnassi Ruins, bulb in the left part",
|
||||
"Arnassi Ruins, bulb in the center part",
|
||||
"Arnassi ruins, Song plant spore on the top of the ruins",
|
||||
"Arnassi ruins, Arnassi Armor",
|
||||
"Arnassi Ruins, Arnassi statue",
|
||||
"Arnassi Ruins, Song Plant Spore",
|
||||
"Arnassi Ruins, Arnassi Armor",
|
||||
"Arnassi Ruins, Arnassi Statue",
|
||||
"Arnassi Ruins, Transturtle",
|
||||
"Arnassi ruins, Crab armor",
|
||||
"Simon says area, Transturtle",
|
||||
"Mithalas city, first bulb in the left city part",
|
||||
"Mithalas city, second bulb in the left city part",
|
||||
"Mithalas city, bulb in the right part",
|
||||
"Mithalas city, bulb at the top of the city",
|
||||
"Mithalas city, first bulb in a broken home",
|
||||
"Mithalas city, second bulb in a broken home",
|
||||
"Mithalas city, bulb in the bottom left part",
|
||||
"Mithalas city, first bulb in one of the homes",
|
||||
"Mithalas city, second bulb in one of the homes",
|
||||
"Mithalas city, first urn in one of the homes",
|
||||
"Mithalas city, second urn in one of the homes",
|
||||
"Mithalas city, first urn in the city reserve",
|
||||
"Mithalas city, second urn in the city reserve",
|
||||
"Mithalas city, third urn in the city reserve",
|
||||
"Mithalas city, first bulb at the end of the top path",
|
||||
"Mithalas city, second bulb at the end of the top path",
|
||||
"Mithalas city, bulb in the top path",
|
||||
"Mithalas city, Mithalas pot",
|
||||
"Mithalas city, urn in the cathedral flower tube entrance",
|
||||
"Mithalas city, Doll",
|
||||
"Mithalas city, urn inside a home fish pass",
|
||||
"Mithalas city castle, bulb in the flesh hole",
|
||||
"Mithalas city castle, Blue banner",
|
||||
"Mithalas city castle, urn in the bedroom",
|
||||
"Mithalas city castle, first urn of the single lamp path",
|
||||
"Mithalas city castle, second urn of the single lamp path",
|
||||
"Mithalas city castle, urn in the bottom room",
|
||||
"Mithalas city castle, first urn on the entrance path",
|
||||
"Mithalas city castle, second urn on the entrance path",
|
||||
"Mithalas castle, beating the priests",
|
||||
"Mithalas city castle, Trident head",
|
||||
"Mithalas cathedral, first urn in the top right room",
|
||||
"Mithalas cathedral, second urn in the top right room",
|
||||
"Mithalas cathedral, third urn in the top right room",
|
||||
"Mithalas cathedral, urn in the flesh room with fleas",
|
||||
"Mithalas cathedral, first urn in the bottom right path",
|
||||
"Mithalas cathedral, second urn in the bottom right path",
|
||||
"Mithalas cathedral, urn behind the flesh vein",
|
||||
"Mithalas cathedral, urn in the top left eyes boss room",
|
||||
"Mithalas cathedral, first urn in the path behind the flesh vein",
|
||||
"Mithalas cathedral, second urn in the path behind the flesh vein",
|
||||
"Mithalas cathedral, third urn in the path behind the flesh vein",
|
||||
"Mithalas cathedral, one of the urns in the top right room",
|
||||
"Mithalas cathedral, Mithalan Dress",
|
||||
"Mithalas cathedral right area, urn below the left entrance",
|
||||
"Cathedral underground, bulb in the center part",
|
||||
"Cathedral underground, first bulb in the top left part",
|
||||
"Cathedral underground, second bulb in the top left part",
|
||||
"Cathedral underground, third bulb in the top left part",
|
||||
"Cathedral underground, bulb close to the save cristal",
|
||||
"Cathedral underground, bulb in the bottom right path",
|
||||
"Arnassi Ruins, Crab Armor",
|
||||
"Simon Says area, Transturtle",
|
||||
"Mithalas City, first bulb in the left city part",
|
||||
"Mithalas City, second bulb in the left city part",
|
||||
"Mithalas City, bulb in the right part",
|
||||
"Mithalas City, bulb at the top of the city",
|
||||
"Mithalas City, first bulb in a broken home",
|
||||
"Mithalas City, second bulb in a broken home",
|
||||
"Mithalas City, bulb in the bottom left part",
|
||||
"Mithalas City, first bulb in one of the homes",
|
||||
"Mithalas City, second bulb in one of the homes",
|
||||
"Mithalas City, first urn in one of the homes",
|
||||
"Mithalas City, second urn in one of the homes",
|
||||
"Mithalas City, first urn in the city reserve",
|
||||
"Mithalas City, second urn in the city reserve",
|
||||
"Mithalas City, third urn in the city reserve",
|
||||
"Mithalas City, first bulb at the end of the top path",
|
||||
"Mithalas City, second bulb at the end of the top path",
|
||||
"Mithalas City, bulb in the top path",
|
||||
"Mithalas City, Mithalas Pot",
|
||||
"Mithalas City, urn in the Cathedral flower tube entrance",
|
||||
"Mithalas City, Doll",
|
||||
"Mithalas City, urn inside a home fish pass",
|
||||
"Mithalas City Castle, bulb in the flesh hole",
|
||||
"Mithalas City Castle, Blue banner",
|
||||
"Mithalas City Castle, urn in the bedroom",
|
||||
"Mithalas City Castle, first urn of the single lamp path",
|
||||
"Mithalas City Castle, second urn of the single lamp path",
|
||||
"Mithalas City Castle, urn in the bottom room",
|
||||
"Mithalas City Castle, first urn on the entrance path",
|
||||
"Mithalas City Castle, second urn on the entrance path",
|
||||
"Mithalas City Castle, beating the Priests",
|
||||
"Mithalas City Castle, Trident Head",
|
||||
"Mithalas Cathedral, first urn in the top right room",
|
||||
"Mithalas Cathedral, second urn in the top right room",
|
||||
"Mithalas Cathedral, third urn in the top right room",
|
||||
"Mithalas Cathedral, urn in the flesh room with fleas",
|
||||
"Mithalas Cathedral, first urn in the bottom right path",
|
||||
"Mithalas Cathedral, second urn in the bottom right path",
|
||||
"Mithalas Cathedral, urn behind the flesh vein",
|
||||
"Mithalas Cathedral, urn in the top left eyes boss room",
|
||||
"Mithalas Cathedral, first urn in the path behind the flesh vein",
|
||||
"Mithalas Cathedral, second urn in the path behind the flesh vein",
|
||||
"Mithalas Cathedral, third urn in the path behind the flesh vein",
|
||||
"Mithalas Cathedral, fourth urn in the top right room",
|
||||
"Mithalas Cathedral, Mithalan Dress",
|
||||
"Mithalas Cathedral right area, urn below the left entrance",
|
||||
"Cathedral Underground, bulb in the center part",
|
||||
"Cathedral Underground, first bulb in the top left part",
|
||||
"Cathedral Underground, second bulb in the top left part",
|
||||
"Cathedral Underground, third bulb in the top left part",
|
||||
"Cathedral Underground, bulb close to the save crystal",
|
||||
"Cathedral Underground, bulb in the bottom right path",
|
||||
"Cathedral boss area, beating Mithalan God",
|
||||
"Kelp Forest top left area, bulb in the bottom left clearing",
|
||||
"Kelp Forest top left area, bulb in the path down from the top left clearing",
|
||||
"Kelp Forest top left area, bulb in the top left clearing",
|
||||
"Kelp Forest top left, Jelly Egg",
|
||||
"Kelp Forest top left area, bulb close to the Verse egg",
|
||||
"Kelp forest top left area, Verse egg",
|
||||
"Kelp Forest top left area, bulb close to the Verse Egg",
|
||||
"Kelp Forest top left area, Verse Egg",
|
||||
"Kelp Forest top right area, bulb under the rock in the right path",
|
||||
"Kelp Forest top right area, bulb at the left of the center clearing",
|
||||
"Kelp Forest top right area, bulb in the left path's big room",
|
||||
"Kelp Forest top right area, bulb in the left path's small room",
|
||||
"Kelp Forest top right area, bulb at the top of the center clearing",
|
||||
"Kelp forest top right area, Black pearl",
|
||||
"Kelp Forest top right area, Black Pearl",
|
||||
"Kelp Forest top right area, bulb in the top fish pass",
|
||||
"Kelp Forest bottom left area, bulb close to the spirit crystals",
|
||||
"Kelp forest bottom left area, Walker baby",
|
||||
"Kelp Forest bottom left area, Walker baby",
|
||||
"Kelp Forest bottom left area, Transturtle",
|
||||
"Kelp forest bottom right area, Odd Container",
|
||||
"Kelp forest boss area, beating Drunian God",
|
||||
"Kelp Forest bottom right area, Odd Container",
|
||||
"Kelp Forest boss area, beating Drunian God",
|
||||
"Kelp Forest boss room, bulb at the bottom of the area",
|
||||
"Kelp Forest bottom left area, Fish cave puzzle",
|
||||
"Kelp Forest bottom left area, Fish Cave puzzle",
|
||||
"Kelp Forest sprite cave, bulb inside the fish pass",
|
||||
"Kelp Forest sprite cave, bulb in the second room",
|
||||
"Kelp Forest Sprite Cave, Seed bag",
|
||||
"Kelp Forest sprite cave, Seed Bag",
|
||||
"Mermog cave, bulb in the left part of the cave",
|
||||
"Mermog cave, Piranha Egg",
|
||||
"The veil top left area, In the Li cave",
|
||||
"The veil top left area, bulb under the rock in the top right path",
|
||||
"The veil top left area, bulb hidden behind the blocking rock",
|
||||
"The veil top left area, Transturtle",
|
||||
"The veil top left area, bulb inside the fish pass",
|
||||
"The Veil top left area, In Li's cave",
|
||||
"The Veil top left area, bulb under the rock in the top right path",
|
||||
"The Veil top left area, bulb hidden behind the blocking rock",
|
||||
"The Veil top left area, Transturtle",
|
||||
"The Veil top left area, bulb inside the fish pass",
|
||||
"Turtle cave, Turtle Egg",
|
||||
"Turtle cave, bulb in bubble cliff",
|
||||
"Turtle cave, Urchin costume",
|
||||
"The veil top right area, bulb in the middle of the wall jump cliff",
|
||||
"The veil top right area, golden starfish at the bottom right of the bottom path",
|
||||
"The veil top right area, bulb in the top of the water fall",
|
||||
"The veil top right area, Transturtle",
|
||||
"The veil bottom area, bulb in the left path",
|
||||
"The veil bottom area, bulb in the spirit path",
|
||||
"The veil bottom area, Verse egg",
|
||||
"The veil bottom area, Stone Head",
|
||||
"Octopus cave, Dumbo Egg",
|
||||
"Octopus cave, bulb in the path below the octopus cave path",
|
||||
"Bubble cave, bulb in the left cave wall",
|
||||
"Bubble cave, bulb in the right cave wall (behind the ice cristal)",
|
||||
"Bubble cave, Verse egg",
|
||||
"Sun temple, bulb in the top left part",
|
||||
"Sun temple, bulb in the top right part",
|
||||
"Sun temple, bulb at the top of the high dark room",
|
||||
"Sun temple, Golden Gear",
|
||||
"Sun temple, first bulb of the temple",
|
||||
"Sun temple, bulb on the left part",
|
||||
"Sun temple, bulb in the hidden room of the right part",
|
||||
"Sun temple, Sun key",
|
||||
"Turtle cave, bulb in Bubble Cliff",
|
||||
"Turtle cave, Urchin Costume",
|
||||
"The Veil top right area, bulb in the middle of the wall jump cliff",
|
||||
"The Veil top right area, Golden Starfish",
|
||||
"The Veil top right area, bulb in the top of the waterfall",
|
||||
"The Veil top right area, Transturtle",
|
||||
"The Veil bottom area, bulb in the left path",
|
||||
"The Veil bottom area, bulb in the spirit path",
|
||||
"The Veil bottom area, Verse Egg",
|
||||
"The Veil bottom area, Stone Head",
|
||||
"Octopus Cave, Dumbo Egg",
|
||||
"Octopus Cave, bulb in the path below the Octopus Cave path",
|
||||
"Bubble Cave, bulb in the left cave wall",
|
||||
"Bubble Cave, bulb in the right cave wall (behind the ice crystal)",
|
||||
"Bubble Cave, Verse Egg",
|
||||
"Sun Temple, bulb in the top left part",
|
||||
"Sun Temple, bulb in the top right part",
|
||||
"Sun Temple, bulb at the top of the high dark room",
|
||||
"Sun Temple, Golden Gear",
|
||||
"Sun Temple, first bulb of the temple",
|
||||
"Sun Temple, bulb on the left part",
|
||||
"Sun Temple, bulb in the hidden room of the right part",
|
||||
"Sun Temple, Sun Key",
|
||||
"Sun Worm path, first path bulb",
|
||||
"Sun Worm path, second path bulb",
|
||||
"Sun Worm path, first cliff bulb",
|
||||
"Sun Worm path, second cliff bulb",
|
||||
"Sun temple boss area, beating Sun God",
|
||||
"Sun Temple boss area, beating Sun God",
|
||||
"Abyss left area, bulb in hidden path room",
|
||||
"Abyss left area, bulb in the right part",
|
||||
"Abyss left area, Glowing seed",
|
||||
"Abyss left area, Glowing Seed",
|
||||
"Abyss left area, Glowing Plant",
|
||||
"Abyss left area, bulb in the bottom fish pass",
|
||||
"Abyss right area, bulb behind the rock in the whale room",
|
||||
@@ -159,40 +159,40 @@ after_home_water_locations = [
|
||||
"Abyss right area, bulb behind the rock in the middle path",
|
||||
"Abyss right area, bulb in the left green room",
|
||||
"Abyss right area, Transturtle",
|
||||
"Ice cave, bulb in the room to the right",
|
||||
"Ice cave, First bulbs in the top exit room",
|
||||
"Ice cave, Second bulbs in the top exit room",
|
||||
"Ice cave, third bulbs in the top exit room",
|
||||
"Ice cave, bulb in the left room",
|
||||
"King Jellyfish cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish cave, Jellyfish Costume",
|
||||
"The whale, Verse egg",
|
||||
"Sunken city right area, crate close to the save cristal",
|
||||
"Sunken city right area, crate in the left bottom room",
|
||||
"Sunken city left area, crate in the little pipe room",
|
||||
"Sunken city left area, crate close to the save cristal",
|
||||
"Sunken city left area, crate before the bedroom",
|
||||
"Sunken city left area, Girl Costume",
|
||||
"Sunken city, bulb on the top of the boss area (boiler room)",
|
||||
"The body center area, breaking li cage",
|
||||
"The body main area, bulb on the main path blocking tube",
|
||||
"The body left area, first bulb in the top face room",
|
||||
"The body left area, second bulb in the top face room",
|
||||
"The body left area, bulb below the water stream",
|
||||
"The body left area, bulb in the top path to the top face room",
|
||||
"The body left area, bulb in the bottom face room",
|
||||
"The body right area, bulb in the top face room",
|
||||
"The body right area, bulb in the top path to the bottom face room",
|
||||
"The body right area, bulb in the bottom face room",
|
||||
"The body bottom area, bulb in the Jelly Zap room",
|
||||
"The body bottom area, bulb in the nautilus room",
|
||||
"The body bottom area, Mutant Costume",
|
||||
"Final boss area, first bulb in the turtle room",
|
||||
"Final boss area, second bulbs in the turtle room",
|
||||
"Final boss area, third bulbs in the turtle room",
|
||||
"Final boss area, Transturtle",
|
||||
"Final boss area, bulb in the boss third form room",
|
||||
"Kelp forest, beating Simon says",
|
||||
"Ice Cave, bulb in the room to the right",
|
||||
"Ice Cave, first bulb in the top exit room",
|
||||
"Ice Cave, second bulb in the top exit room",
|
||||
"Ice Cave, third bulb in the top exit room",
|
||||
"Ice Cave, bulb in the left room",
|
||||
"King Jellyfish Cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish Cave, Jellyfish Costume",
|
||||
"The Whale, Verse Egg",
|
||||
"Sunken City right area, crate close to the save crystal",
|
||||
"Sunken City right area, crate in the left bottom room",
|
||||
"Sunken City left area, crate in the little pipe room",
|
||||
"Sunken City left area, crate close to the save crystal",
|
||||
"Sunken City left area, crate before the bedroom",
|
||||
"Sunken City left area, Girl Costume",
|
||||
"Sunken City, bulb on top of the boss area",
|
||||
"The Body center area, breaking Li's cage",
|
||||
"The Body main area, bulb on the main path blocking tube",
|
||||
"The Body left area, first bulb in the top face room",
|
||||
"The Body left area, second bulb in the top face room",
|
||||
"The Body left area, bulb below the water stream",
|
||||
"The Body left area, bulb in the top path to the top face room",
|
||||
"The Body left area, bulb in the bottom face room",
|
||||
"The Body right area, bulb in the top face room",
|
||||
"The Body right area, bulb in the top path to the bottom face room",
|
||||
"The Body right area, bulb in the bottom face room",
|
||||
"The Body bottom area, bulb in the Jelly Zap room",
|
||||
"The Body bottom area, bulb in the nautilus room",
|
||||
"The Body bottom area, Mutant Costume",
|
||||
"Final Boss area, first bulb in the turtle room",
|
||||
"Final Boss area, second bulb in the turtle room",
|
||||
"Final Boss area, third bulb in the turtle room",
|
||||
"Final Boss area, Transturtle",
|
||||
"Final Boss area, bulb in the boss third form room",
|
||||
"Simon Says area, beating Simon Says",
|
||||
"Beating Fallen God",
|
||||
"Beating Mithalan God",
|
||||
"Beating Drunian God",
|
||||
|
||||
@@ -13,33 +13,33 @@ class BeastFormAccessTest(AquariaTestBase):
|
||||
def test_beast_form_location(self) -> None:
|
||||
"""Test locations that require beast form"""
|
||||
locations = [
|
||||
"Mithalas castle, beating the priests",
|
||||
"Arnassi ruins, Crab armor",
|
||||
"Arnassi ruins, Song plant spore on the top of the ruins",
|
||||
"Mithalas city, first bulb at the end of the top path",
|
||||
"Mithalas city, second bulb at the end of the top path",
|
||||
"Mithalas city, bulb in the top path",
|
||||
"Mithalas city, Mithalas pot",
|
||||
"Mithalas city, urn in the cathedral flower tube entrance",
|
||||
"Mithalas City Castle, beating the Priests",
|
||||
"Arnassi Ruins, Crab Armor",
|
||||
"Arnassi Ruins, Song Plant Spore",
|
||||
"Mithalas City, first bulb at the end of the top path",
|
||||
"Mithalas City, second bulb at the end of the top path",
|
||||
"Mithalas City, bulb in the top path",
|
||||
"Mithalas City, Mithalas Pot",
|
||||
"Mithalas City, urn in the Cathedral flower tube entrance",
|
||||
"Mermog cave, Piranha Egg",
|
||||
"Mithalas cathedral, Mithalan Dress",
|
||||
"Turtle cave, bulb in bubble cliff",
|
||||
"Turtle cave, Urchin costume",
|
||||
"Mithalas Cathedral, Mithalan Dress",
|
||||
"Turtle cave, bulb in Bubble Cliff",
|
||||
"Turtle cave, Urchin Costume",
|
||||
"Sun Worm path, first cliff bulb",
|
||||
"Sun Worm path, second cliff bulb",
|
||||
"The veil top right area, bulb in the top of the water fall",
|
||||
"Bubble cave, bulb in the left cave wall",
|
||||
"Bubble cave, bulb in the right cave wall (behind the ice cristal)",
|
||||
"Bubble cave, Verse egg",
|
||||
"Sunken city, bulb on the top of the boss area (boiler room)",
|
||||
"Octopus cave, Dumbo Egg",
|
||||
"The Veil top right area, bulb in the top of the waterfall",
|
||||
"Bubble Cave, bulb in the left cave wall",
|
||||
"Bubble Cave, bulb in the right cave wall (behind the ice crystal)",
|
||||
"Bubble Cave, Verse Egg",
|
||||
"Sunken City, bulb on top of the boss area",
|
||||
"Octopus Cave, Dumbo Egg",
|
||||
"Beating the Golem",
|
||||
"Beating Mergog",
|
||||
"Beating Crabbius Maximus",
|
||||
"Beating Octopus Prime",
|
||||
"Beating Mantis Shrimp Prime",
|
||||
"King Jellyfish cave, Jellyfish Costume",
|
||||
"King Jellyfish cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish Cave, Jellyfish Costume",
|
||||
"King Jellyfish Cave, bulb in the right path from King Jelly",
|
||||
"Beating King Jellyfish God Prime",
|
||||
"Beating Mithalan priests",
|
||||
"Sunken City cleared"
|
||||
|
||||
@@ -17,19 +17,19 @@ class BindSongAccessTest(AquariaTestBase):
|
||||
def test_bind_song_location(self) -> None:
|
||||
"""Test locations that require Bind song"""
|
||||
locations = [
|
||||
"Verse cave right area, Big Seed",
|
||||
"Home water, bulb in the path below Nautilus Prime",
|
||||
"Home water, bulb in the bottom left room",
|
||||
"Home water, Nautilus Egg",
|
||||
"Song cave, Verse egg",
|
||||
"Energy temple first area, beating the energy statue",
|
||||
"Energy temple first area, bulb in the bottom room blocked by a rock",
|
||||
"Energy temple first area, Energy Idol",
|
||||
"Energy temple second area, bulb under the rock",
|
||||
"Energy temple bottom entrance, Krotite armor",
|
||||
"Energy temple third area, bulb in the bottom path",
|
||||
"Energy temple boss area, Fallen god tooth",
|
||||
"Energy temple blaster room, Blaster egg",
|
||||
"Verse Cave right area, Big Seed",
|
||||
"Home Water, bulb in the path below Nautilus Prime",
|
||||
"Home Water, bulb in the bottom left room",
|
||||
"Home Water, Nautilus Egg",
|
||||
"Song Cave, Verse Egg",
|
||||
"Energy Temple first area, beating the Energy Statue",
|
||||
"Energy Temple first area, bulb in the bottom room blocked by a rock",
|
||||
"Energy Temple first area, Energy Idol",
|
||||
"Energy Temple second area, bulb under the rock",
|
||||
"Energy Temple bottom entrance, Krotite Armor",
|
||||
"Energy Temple third area, bulb in the bottom path",
|
||||
"Energy Temple boss area, Fallen God Tooth",
|
||||
"Energy Temple blaster room, Blaster Egg",
|
||||
*after_home_water_locations
|
||||
]
|
||||
items = [["Bind song"]]
|
||||
|
||||
@@ -18,24 +18,24 @@ class BindSongOptionAccessTest(AquariaTestBase):
|
||||
def test_bind_song_location(self) -> None:
|
||||
"""Test locations that require Bind song with the bind song needed option activated"""
|
||||
locations = [
|
||||
"Verse cave right area, Big Seed",
|
||||
"Verse cave left area, bulb under the rock at the end of the path",
|
||||
"Home water, bulb under the rock in the left path from the verse cave",
|
||||
"Song cave, bulb under the rock close to the song door",
|
||||
"Song cave, bulb under the rock in the path to the singing statues",
|
||||
"Naija's home, bulb under the rock at the right of the main path",
|
||||
"Home water, bulb in the path below Nautilus Prime",
|
||||
"Home water, bulb in the bottom left room",
|
||||
"Home water, Nautilus Egg",
|
||||
"Song cave, Verse egg",
|
||||
"Energy temple first area, beating the energy statue",
|
||||
"Energy temple first area, bulb in the bottom room blocked by a rock",
|
||||
"Energy temple first area, Energy Idol",
|
||||
"Energy temple second area, bulb under the rock",
|
||||
"Energy temple bottom entrance, Krotite armor",
|
||||
"Energy temple third area, bulb in the bottom path",
|
||||
"Energy temple boss area, Fallen god tooth",
|
||||
"Energy temple blaster room, Blaster egg",
|
||||
"Verse Cave right area, Big Seed",
|
||||
"Verse Cave left area, bulb under the rock at the end of the path",
|
||||
"Home Water, bulb under the rock in the left path from the Verse Cave",
|
||||
"Song Cave, bulb under the rock close to the song door",
|
||||
"Song Cave, bulb under the rock in the path to the singing statues",
|
||||
"Naija's Home, bulb under the rock at the right of the main path",
|
||||
"Home Water, bulb in the path below Nautilus Prime",
|
||||
"Home Water, bulb in the bottom left room",
|
||||
"Home Water, Nautilus Egg",
|
||||
"Song Cave, Verse Egg",
|
||||
"Energy Temple first area, beating the Energy Statue",
|
||||
"Energy Temple first area, bulb in the bottom room blocked by a rock",
|
||||
"Energy Temple first area, Energy Idol",
|
||||
"Energy Temple second area, bulb under the rock",
|
||||
"Energy Temple bottom entrance, Krotite Armor",
|
||||
"Energy Temple third area, bulb in the bottom path",
|
||||
"Energy Temple boss area, Fallen God Tooth",
|
||||
"Energy Temple blaster room, Blaster Egg",
|
||||
*after_home_water_locations
|
||||
]
|
||||
items = [["Bind song"]]
|
||||
|
||||
@@ -16,5 +16,5 @@ class ConfinedHomeWaterAccessTest(AquariaTestBase):
|
||||
|
||||
def test_confine_home_water_location(self) -> None:
|
||||
"""Test region accessible with confined home water"""
|
||||
self.assertFalse(self.can_reach_region("Open water top left area"), "Can reach Open water top left area")
|
||||
self.assertFalse(self.can_reach_region("Home Water, turtle room"), "Can reach Home Water, turtle room")
|
||||
self.assertFalse(self.can_reach_region("Open Water top left area"), "Can reach Open Water top left area")
|
||||
self.assertFalse(self.can_reach_region("Home Water, turtle room"), "Can reach Home Water, turtle room")
|
||||
|
||||
@@ -16,10 +16,10 @@ class LiAccessTest(AquariaTestBase):
|
||||
def test_li_song_location(self) -> None:
|
||||
"""Test locations that require the dual song"""
|
||||
locations = [
|
||||
"The body bottom area, bulb in the Jelly Zap room",
|
||||
"The body bottom area, bulb in the nautilus room",
|
||||
"The body bottom area, Mutant Costume",
|
||||
"Final boss area, bulb in the boss third form room",
|
||||
"The Body bottom area, bulb in the Jelly Zap room",
|
||||
"The Body bottom area, bulb in the nautilus room",
|
||||
"The Body bottom area, Mutant Costume",
|
||||
"Final Boss area, bulb in the boss third form room",
|
||||
"Objective complete"
|
||||
]
|
||||
items = [["Dual form"]]
|
||||
|
||||
@@ -17,41 +17,41 @@ class EnergyFormAccessTest(AquariaTestBase):
|
||||
def test_energy_form_location(self) -> None:
|
||||
"""Test locations that require Energy form"""
|
||||
locations = [
|
||||
"Home water, Nautilus Egg",
|
||||
"Naija's home, bulb after the energy door",
|
||||
"Energy temple first area, bulb in the bottom room blocked by a rock",
|
||||
"Energy temple second area, bulb under the rock",
|
||||
"Energy temple bottom entrance, Krotite armor",
|
||||
"Energy temple third area, bulb in the bottom path",
|
||||
"Energy temple boss area, Fallen god tooth",
|
||||
"Energy temple blaster room, Blaster egg",
|
||||
"Mithalas castle, beating the priests",
|
||||
"Mithalas cathedral, first urn in the top right room",
|
||||
"Mithalas cathedral, second urn in the top right room",
|
||||
"Mithalas cathedral, third urn in the top right room",
|
||||
"Mithalas cathedral, urn in the flesh room with fleas",
|
||||
"Mithalas cathedral, first urn in the bottom right path",
|
||||
"Mithalas cathedral, second urn in the bottom right path",
|
||||
"Mithalas cathedral, urn behind the flesh vein",
|
||||
"Mithalas cathedral, urn in the top left eyes boss room",
|
||||
"Mithalas cathedral, first urn in the path behind the flesh vein",
|
||||
"Mithalas cathedral, second urn in the path behind the flesh vein",
|
||||
"Mithalas cathedral, third urn in the path behind the flesh vein",
|
||||
"Mithalas cathedral, one of the urns in the top right room",
|
||||
"Mithalas cathedral, Mithalan Dress",
|
||||
"Mithalas cathedral right area, urn below the left entrance",
|
||||
"Home Water, Nautilus Egg",
|
||||
"Naija's Home, bulb after the energy door",
|
||||
"Energy Temple first area, bulb in the bottom room blocked by a rock",
|
||||
"Energy Temple second area, bulb under the rock",
|
||||
"Energy Temple bottom entrance, Krotite Armor",
|
||||
"Energy Temple third area, bulb in the bottom path",
|
||||
"Energy Temple boss area, Fallen God Tooth",
|
||||
"Energy Temple blaster room, Blaster Egg",
|
||||
"Mithalas City Castle, beating the Priests",
|
||||
"Mithalas Cathedral, first urn in the top right room",
|
||||
"Mithalas Cathedral, second urn in the top right room",
|
||||
"Mithalas Cathedral, third urn in the top right room",
|
||||
"Mithalas Cathedral, urn in the flesh room with fleas",
|
||||
"Mithalas Cathedral, first urn in the bottom right path",
|
||||
"Mithalas Cathedral, second urn in the bottom right path",
|
||||
"Mithalas Cathedral, urn behind the flesh vein",
|
||||
"Mithalas Cathedral, urn in the top left eyes boss room",
|
||||
"Mithalas Cathedral, first urn in the path behind the flesh vein",
|
||||
"Mithalas Cathedral, second urn in the path behind the flesh vein",
|
||||
"Mithalas Cathedral, third urn in the path behind the flesh vein",
|
||||
"Mithalas Cathedral, fourth urn in the top right room",
|
||||
"Mithalas Cathedral, Mithalan Dress",
|
||||
"Mithalas Cathedral right area, urn below the left entrance",
|
||||
"Cathedral boss area, beating Mithalan God",
|
||||
"Kelp Forest top left area, bulb close to the Verse egg",
|
||||
"Kelp forest top left area, Verse egg",
|
||||
"Kelp forest boss area, beating Drunian God",
|
||||
"Kelp Forest top left area, bulb close to the Verse Egg",
|
||||
"Kelp Forest top left area, Verse Egg",
|
||||
"Kelp Forest boss area, beating Drunian God",
|
||||
"Mermog cave, Piranha Egg",
|
||||
"Octopus cave, Dumbo Egg",
|
||||
"Sun temple boss area, beating Sun God",
|
||||
"Arnassi ruins, Crab armor",
|
||||
"King Jellyfish cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish cave, Jellyfish Costume",
|
||||
"Sunken city, bulb on the top of the boss area (boiler room)",
|
||||
"Final boss area, bulb in the boss third form room",
|
||||
"Octopus Cave, Dumbo Egg",
|
||||
"Sun Temple boss area, beating Sun God",
|
||||
"Arnassi Ruins, Crab Armor",
|
||||
"King Jellyfish Cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish Cave, Jellyfish Costume",
|
||||
"Sunken City, bulb on top of the boss area",
|
||||
"Final Boss area, bulb in the boss third form room",
|
||||
"Beating Fallen God",
|
||||
"Beating Mithalan God",
|
||||
"Beating Drunian God",
|
||||
@@ -69,4 +69,4 @@ class EnergyFormAccessTest(AquariaTestBase):
|
||||
"Objective complete",
|
||||
]
|
||||
items = [["Energy form"]]
|
||||
self.assertAccessDependency(locations, items)
|
||||
self.assertAccessDependency(locations, items)
|
||||
|
||||
@@ -16,22 +16,22 @@ class FishFormAccessTest(AquariaTestBase):
|
||||
def test_fish_form_location(self) -> None:
|
||||
"""Test locations that require fish form"""
|
||||
locations = [
|
||||
"The veil top left area, bulb inside the fish pass",
|
||||
"Mithalas city, Doll",
|
||||
"Mithalas city, urn inside a home fish pass",
|
||||
"The Veil top left area, bulb inside the fish pass",
|
||||
"Mithalas City, Doll",
|
||||
"Mithalas City, urn inside a home fish pass",
|
||||
"Kelp Forest top right area, bulb in the top fish pass",
|
||||
"The veil bottom area, Verse egg",
|
||||
"Open water bottom left area, bulb inside the lowest fish pass",
|
||||
"Kelp Forest top left area, bulb close to the Verse egg",
|
||||
"Kelp forest top left area, Verse egg",
|
||||
"The Veil bottom area, Verse Egg",
|
||||
"Open Water bottom left area, bulb inside the lowest fish pass",
|
||||
"Kelp Forest top left area, bulb close to the Verse Egg",
|
||||
"Kelp Forest top left area, Verse Egg",
|
||||
"Mermog cave, bulb in the left part of the cave",
|
||||
"Mermog cave, Piranha Egg",
|
||||
"Beating Mergog",
|
||||
"Octopus cave, Dumbo Egg",
|
||||
"Octopus cave, bulb in the path below the octopus cave path",
|
||||
"Octopus Cave, Dumbo Egg",
|
||||
"Octopus Cave, bulb in the path below the Octopus Cave path",
|
||||
"Beating Octopus Prime",
|
||||
"Abyss left area, bulb in the bottom fish pass",
|
||||
"Arnassi ruins, Arnassi Armor"
|
||||
"Arnassi Ruins, Arnassi Armor"
|
||||
]
|
||||
items = [["Fish form"]]
|
||||
self.assertAccessDependency(locations, items)
|
||||
|
||||
@@ -16,27 +16,27 @@ class LiAccessTest(AquariaTestBase):
|
||||
def test_li_song_location(self) -> None:
|
||||
"""Test locations that require Li"""
|
||||
locations = [
|
||||
"Sunken city right area, crate close to the save cristal",
|
||||
"Sunken city right area, crate in the left bottom room",
|
||||
"Sunken city left area, crate in the little pipe room",
|
||||
"Sunken city left area, crate close to the save cristal",
|
||||
"Sunken city left area, crate before the bedroom",
|
||||
"Sunken city left area, Girl Costume",
|
||||
"Sunken city, bulb on the top of the boss area (boiler room)",
|
||||
"The body center area, breaking li cage",
|
||||
"The body main area, bulb on the main path blocking tube",
|
||||
"The body left area, first bulb in the top face room",
|
||||
"The body left area, second bulb in the top face room",
|
||||
"The body left area, bulb below the water stream",
|
||||
"The body left area, bulb in the top path to the top face room",
|
||||
"The body left area, bulb in the bottom face room",
|
||||
"The body right area, bulb in the top face room",
|
||||
"The body right area, bulb in the top path to the bottom face room",
|
||||
"The body right area, bulb in the bottom face room",
|
||||
"The body bottom area, bulb in the Jelly Zap room",
|
||||
"The body bottom area, bulb in the nautilus room",
|
||||
"The body bottom area, Mutant Costume",
|
||||
"Final boss area, bulb in the boss third form room",
|
||||
"Sunken City right area, crate close to the save crystal",
|
||||
"Sunken City right area, crate in the left bottom room",
|
||||
"Sunken City left area, crate in the little pipe room",
|
||||
"Sunken City left area, crate close to the save crystal",
|
||||
"Sunken City left area, crate before the bedroom",
|
||||
"Sunken City left area, Girl Costume",
|
||||
"Sunken City, bulb on top of the boss area",
|
||||
"The Body center area, breaking Li's cage",
|
||||
"The Body main area, bulb on the main path blocking tube",
|
||||
"The Body left area, first bulb in the top face room",
|
||||
"The Body left area, second bulb in the top face room",
|
||||
"The Body left area, bulb below the water stream",
|
||||
"The Body left area, bulb in the top path to the top face room",
|
||||
"The Body left area, bulb in the bottom face room",
|
||||
"The Body right area, bulb in the top face room",
|
||||
"The Body right area, bulb in the top path to the bottom face room",
|
||||
"The Body right area, bulb in the bottom face room",
|
||||
"The Body bottom area, bulb in the Jelly Zap room",
|
||||
"The Body bottom area, bulb in the nautilus room",
|
||||
"The Body bottom area, Mutant Costume",
|
||||
"Final Boss area, bulb in the boss third form room",
|
||||
"Beating the Golem",
|
||||
"Sunken City cleared",
|
||||
"Objective complete"
|
||||
|
||||
@@ -20,19 +20,19 @@ class LightAccessTest(AquariaTestBase):
|
||||
# Since the `assertAccessDependency` sweep for events even if I tell it not to, those location cannot be
|
||||
# tested.
|
||||
# "Third secret",
|
||||
# "Sun temple, bulb in the top left part",
|
||||
# "Sun temple, bulb in the top right part",
|
||||
# "Sun temple, bulb at the top of the high dark room",
|
||||
# "Sun temple, Golden Gear",
|
||||
# "Sun Temple, bulb in the top left part",
|
||||
# "Sun Temple, bulb in the top right part",
|
||||
# "Sun Temple, bulb at the top of the high dark room",
|
||||
# "Sun Temple, Golden Gear",
|
||||
# "Sun Worm path, first path bulb",
|
||||
# "Sun Worm path, second path bulb",
|
||||
# "Sun Worm path, first cliff bulb",
|
||||
"Octopus cave, Dumbo Egg",
|
||||
"Kelp forest bottom right area, Odd Container",
|
||||
"Kelp forest top right area, Black pearl",
|
||||
"Octopus Cave, Dumbo Egg",
|
||||
"Kelp Forest bottom right area, Odd Container",
|
||||
"Kelp Forest top right area, Black Pearl",
|
||||
"Abyss left area, bulb in hidden path room",
|
||||
"Abyss left area, bulb in the right part",
|
||||
"Abyss left area, Glowing seed",
|
||||
"Abyss left area, Glowing Seed",
|
||||
"Abyss left area, Glowing Plant",
|
||||
"Abyss left area, bulb in the bottom fish pass",
|
||||
"Abyss right area, bulb behind the rock in the whale room",
|
||||
@@ -40,32 +40,32 @@ class LightAccessTest(AquariaTestBase):
|
||||
"Abyss right area, bulb behind the rock in the middle path",
|
||||
"Abyss right area, bulb in the left green room",
|
||||
"Abyss right area, Transturtle",
|
||||
"Ice cave, bulb in the room to the right",
|
||||
"Ice cave, First bulbs in the top exit room",
|
||||
"Ice cave, Second bulbs in the top exit room",
|
||||
"Ice cave, third bulbs in the top exit room",
|
||||
"Ice cave, bulb in the left room",
|
||||
"Bubble cave, bulb in the left cave wall",
|
||||
"Bubble cave, bulb in the right cave wall (behind the ice cristal)",
|
||||
"Bubble cave, Verse egg",
|
||||
"Ice Cave, bulb in the room to the right",
|
||||
"Ice Cave, first bulb in the top exit room",
|
||||
"Ice Cave, second bulb in the top exit room",
|
||||
"Ice Cave, third bulb in the top exit room",
|
||||
"Ice Cave, bulb in the left room",
|
||||
"Bubble Cave, bulb in the left cave wall",
|
||||
"Bubble Cave, bulb in the right cave wall (behind the ice crystal)",
|
||||
"Bubble Cave, Verse Egg",
|
||||
"Beating Mantis Shrimp Prime",
|
||||
"King Jellyfish cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish cave, Jellyfish Costume",
|
||||
"King Jellyfish Cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish Cave, Jellyfish Costume",
|
||||
"Beating King Jellyfish God Prime",
|
||||
"The whale, Verse egg",
|
||||
"The Whale, Verse Egg",
|
||||
"First secret",
|
||||
"Sunken city right area, crate close to the save cristal",
|
||||
"Sunken city right area, crate in the left bottom room",
|
||||
"Sunken city left area, crate in the little pipe room",
|
||||
"Sunken city left area, crate close to the save cristal",
|
||||
"Sunken city left area, crate before the bedroom",
|
||||
"Sunken city left area, Girl Costume",
|
||||
"Sunken city, bulb on the top of the boss area (boiler room)",
|
||||
"Sunken City right area, crate close to the save crystal",
|
||||
"Sunken City right area, crate in the left bottom room",
|
||||
"Sunken City left area, crate in the little pipe room",
|
||||
"Sunken City left area, crate close to the save crystal",
|
||||
"Sunken City left area, crate before the bedroom",
|
||||
"Sunken City left area, Girl Costume",
|
||||
"Sunken City, bulb on top of the boss area",
|
||||
"Sunken City cleared",
|
||||
"Beating the Golem",
|
||||
"Beating Octopus Prime",
|
||||
"Final boss area, bulb in the boss third form room",
|
||||
"Final Boss area, bulb in the boss third form room",
|
||||
"Objective complete",
|
||||
]
|
||||
items = [["Sun form", "Baby dumbo", "Has sun crystal"]]
|
||||
items = [["Sun form", "Baby Dumbo", "Has sun crystal"]]
|
||||
self.assertAccessDependency(locations, items)
|
||||
|
||||
@@ -16,41 +16,41 @@ class NatureFormAccessTest(AquariaTestBase):
|
||||
def test_nature_form_location(self) -> None:
|
||||
"""Test locations that require nature form"""
|
||||
locations = [
|
||||
"Song cave, Anemone seed",
|
||||
"Energy temple blaster room, Blaster egg",
|
||||
"Song Cave, Anemone Seed",
|
||||
"Energy Temple blaster room, Blaster Egg",
|
||||
"Beating Blaster Peg Prime",
|
||||
"Kelp forest top left area, Verse egg",
|
||||
"Kelp Forest top left area, bulb close to the Verse egg",
|
||||
"Mithalas castle, beating the priests",
|
||||
"Kelp Forest top left area, Verse Egg",
|
||||
"Kelp Forest top left area, bulb close to the Verse Egg",
|
||||
"Mithalas City Castle, beating the Priests",
|
||||
"Kelp Forest sprite cave, bulb in the second room",
|
||||
"Kelp Forest Sprite Cave, Seed bag",
|
||||
"Kelp Forest sprite cave, Seed Bag",
|
||||
"Beating Mithalan priests",
|
||||
"Abyss left area, bulb in the bottom fish pass",
|
||||
"Bubble cave, Verse egg",
|
||||
"Bubble Cave, Verse Egg",
|
||||
"Beating Mantis Shrimp Prime",
|
||||
"Sunken city right area, crate close to the save cristal",
|
||||
"Sunken city right area, crate in the left bottom room",
|
||||
"Sunken city left area, crate in the little pipe room",
|
||||
"Sunken city left area, crate close to the save cristal",
|
||||
"Sunken city left area, crate before the bedroom",
|
||||
"Sunken city left area, Girl Costume",
|
||||
"Sunken city, bulb on the top of the boss area (boiler room)",
|
||||
"Sunken City right area, crate close to the save crystal",
|
||||
"Sunken City right area, crate in the left bottom room",
|
||||
"Sunken City left area, crate in the little pipe room",
|
||||
"Sunken City left area, crate close to the save crystal",
|
||||
"Sunken City left area, crate before the bedroom",
|
||||
"Sunken City left area, Girl Costume",
|
||||
"Sunken City, bulb on top of the boss area",
|
||||
"Beating the Golem",
|
||||
"Sunken City cleared",
|
||||
"The body center area, breaking li cage",
|
||||
"The body main area, bulb on the main path blocking tube",
|
||||
"The body left area, first bulb in the top face room",
|
||||
"The body left area, second bulb in the top face room",
|
||||
"The body left area, bulb below the water stream",
|
||||
"The body left area, bulb in the top path to the top face room",
|
||||
"The body left area, bulb in the bottom face room",
|
||||
"The body right area, bulb in the top face room",
|
||||
"The body right area, bulb in the top path to the bottom face room",
|
||||
"The body right area, bulb in the bottom face room",
|
||||
"The body bottom area, bulb in the Jelly Zap room",
|
||||
"The body bottom area, bulb in the nautilus room",
|
||||
"The body bottom area, Mutant Costume",
|
||||
"Final boss area, bulb in the boss third form room",
|
||||
"The Body center area, breaking Li's cage",
|
||||
"The Body main area, bulb on the main path blocking tube",
|
||||
"The Body left area, first bulb in the top face room",
|
||||
"The Body left area, second bulb in the top face room",
|
||||
"The Body left area, bulb below the water stream",
|
||||
"The Body left area, bulb in the top path to the top face room",
|
||||
"The Body left area, bulb in the bottom face room",
|
||||
"The Body right area, bulb in the top face room",
|
||||
"The Body right area, bulb in the top path to the bottom face room",
|
||||
"The Body right area, bulb in the bottom face room",
|
||||
"The Body bottom area, bulb in the Jelly Zap room",
|
||||
"The Body bottom area, bulb in the nautilus room",
|
||||
"The Body bottom area, Mutant Costume",
|
||||
"Final Boss area, bulb in the boss third form room",
|
||||
"Objective complete"
|
||||
]
|
||||
items = [["Nature form"]]
|
||||
|
||||
@@ -15,31 +15,31 @@ class UNoProgressionHardHiddenTest(AquariaTestBase):
|
||||
}
|
||||
|
||||
unfillable_locations = [
|
||||
"Energy temple boss area, Fallen god tooth",
|
||||
"Energy Temple boss area, Fallen God Tooth",
|
||||
"Cathedral boss area, beating Mithalan God",
|
||||
"Kelp forest boss area, beating Drunian God",
|
||||
"Sun temple boss area, beating Sun God",
|
||||
"Sunken city, bulb on the top of the boss area (boiler room)",
|
||||
"Home water, Nautilus Egg",
|
||||
"Energy temple blaster room, Blaster egg",
|
||||
"Mithalas castle, beating the priests",
|
||||
"Kelp Forest boss area, beating Drunian God",
|
||||
"Sun Temple boss area, beating Sun God",
|
||||
"Sunken City, bulb on top of the boss area",
|
||||
"Home Water, Nautilus Egg",
|
||||
"Energy Temple blaster room, Blaster Egg",
|
||||
"Mithalas City Castle, beating the Priests",
|
||||
"Mermog cave, Piranha Egg",
|
||||
"Octopus cave, Dumbo Egg",
|
||||
"King Jellyfish cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish cave, Jellyfish Costume",
|
||||
"Final boss area, bulb in the boss third form room",
|
||||
"Octopus Cave, Dumbo Egg",
|
||||
"King Jellyfish Cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish Cave, Jellyfish Costume",
|
||||
"Final Boss area, bulb in the boss third form room",
|
||||
"Sun Worm path, first cliff bulb",
|
||||
"Sun Worm path, second cliff bulb",
|
||||
"The veil top right area, bulb in the top of the water fall",
|
||||
"Bubble cave, bulb in the left cave wall",
|
||||
"Bubble cave, bulb in the right cave wall (behind the ice cristal)",
|
||||
"Bubble cave, Verse egg",
|
||||
"The Veil top right area, bulb in the top of the waterfall",
|
||||
"Bubble Cave, bulb in the left cave wall",
|
||||
"Bubble Cave, bulb in the right cave wall (behind the ice crystal)",
|
||||
"Bubble Cave, Verse Egg",
|
||||
"Kelp Forest bottom left area, bulb close to the spirit crystals",
|
||||
"Kelp forest bottom left area, Walker baby",
|
||||
"Sun temple, Sun key",
|
||||
"The body bottom area, Mutant Costume",
|
||||
"Sun temple, bulb in the hidden room of the right part",
|
||||
"Arnassi ruins, Arnassi Armor",
|
||||
"Kelp Forest bottom left area, Walker baby",
|
||||
"Sun Temple, Sun Key",
|
||||
"The Body bottom area, Mutant Costume",
|
||||
"Sun Temple, bulb in the hidden room of the right part",
|
||||
"Arnassi Ruins, Arnassi Armor",
|
||||
]
|
||||
|
||||
def test_unconfine_home_water_both_location_fillable(self) -> None:
|
||||
|
||||
@@ -15,31 +15,31 @@ class UNoProgressionHardHiddenTest(AquariaTestBase):
|
||||
}
|
||||
|
||||
unfillable_locations = [
|
||||
"Energy temple boss area, Fallen god tooth",
|
||||
"Energy Temple boss area, Fallen God Tooth",
|
||||
"Cathedral boss area, beating Mithalan God",
|
||||
"Kelp forest boss area, beating Drunian God",
|
||||
"Sun temple boss area, beating Sun God",
|
||||
"Sunken city, bulb on the top of the boss area (boiler room)",
|
||||
"Home water, Nautilus Egg",
|
||||
"Energy temple blaster room, Blaster egg",
|
||||
"Mithalas castle, beating the priests",
|
||||
"Kelp Forest boss area, beating Drunian God",
|
||||
"Sun Temple boss area, beating Sun God",
|
||||
"Sunken City, bulb on top of the boss area",
|
||||
"Home Water, Nautilus Egg",
|
||||
"Energy Temple blaster room, Blaster Egg",
|
||||
"Mithalas City Castle, beating the Priests",
|
||||
"Mermog cave, Piranha Egg",
|
||||
"Octopus cave, Dumbo Egg",
|
||||
"King Jellyfish cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish cave, Jellyfish Costume",
|
||||
"Final boss area, bulb in the boss third form room",
|
||||
"Octopus Cave, Dumbo Egg",
|
||||
"King Jellyfish Cave, bulb in the right path from King Jelly",
|
||||
"King Jellyfish Cave, Jellyfish Costume",
|
||||
"Final Boss area, bulb in the boss third form room",
|
||||
"Sun Worm path, first cliff bulb",
|
||||
"Sun Worm path, second cliff bulb",
|
||||
"The veil top right area, bulb in the top of the water fall",
|
||||
"Bubble cave, bulb in the left cave wall",
|
||||
"Bubble cave, bulb in the right cave wall (behind the ice cristal)",
|
||||
"Bubble cave, Verse egg",
|
||||
"The Veil top right area, bulb in the top of the waterfall",
|
||||
"Bubble Cave, bulb in the left cave wall",
|
||||
"Bubble Cave, bulb in the right cave wall (behind the ice crystal)",
|
||||
"Bubble Cave, Verse Egg",
|
||||
"Kelp Forest bottom left area, bulb close to the spirit crystals",
|
||||
"Kelp forest bottom left area, Walker baby",
|
||||
"Sun temple, Sun key",
|
||||
"The body bottom area, Mutant Costume",
|
||||
"Sun temple, bulb in the hidden room of the right part",
|
||||
"Arnassi ruins, Arnassi Armor",
|
||||
"Kelp Forest bottom left area, Walker baby",
|
||||
"Sun Temple, Sun Key",
|
||||
"The Body bottom area, Mutant Costume",
|
||||
"Sun Temple, bulb in the hidden room of the right part",
|
||||
"Arnassi Ruins, Arnassi Armor",
|
||||
]
|
||||
|
||||
def test_unconfine_home_water_both_location_fillable(self) -> None:
|
||||
|
||||
@@ -13,24 +13,24 @@ class SpiritFormAccessTest(AquariaTestBase):
|
||||
def test_spirit_form_location(self) -> None:
|
||||
"""Test locations that require spirit form"""
|
||||
locations = [
|
||||
"The veil bottom area, bulb in the spirit path",
|
||||
"Mithalas city castle, Trident head",
|
||||
"Open water skeleton path, King skull",
|
||||
"Kelp forest bottom left area, Walker baby",
|
||||
"The Veil bottom area, bulb in the spirit path",
|
||||
"Mithalas City Castle, Trident Head",
|
||||
"Open Water skeleton path, King Skull",
|
||||
"Kelp Forest bottom left area, Walker baby",
|
||||
"Abyss right area, bulb behind the rock in the whale room",
|
||||
"The whale, Verse egg",
|
||||
"Ice cave, bulb in the room to the right",
|
||||
"Ice cave, First bulbs in the top exit room",
|
||||
"Ice cave, Second bulbs in the top exit room",
|
||||
"Ice cave, third bulbs in the top exit room",
|
||||
"Ice cave, bulb in the left room",
|
||||
"Bubble cave, bulb in the left cave wall",
|
||||
"Bubble cave, bulb in the right cave wall (behind the ice cristal)",
|
||||
"Bubble cave, Verse egg",
|
||||
"Sunken city left area, Girl Costume",
|
||||
"The Whale, Verse Egg",
|
||||
"Ice Cave, bulb in the room to the right",
|
||||
"Ice Cave, first bulb in the top exit room",
|
||||
"Ice Cave, second bulb in the top exit room",
|
||||
"Ice Cave, third bulb in the top exit room",
|
||||
"Ice Cave, bulb in the left room",
|
||||
"Bubble Cave, bulb in the left cave wall",
|
||||
"Bubble Cave, bulb in the right cave wall (behind the ice crystal)",
|
||||
"Bubble Cave, Verse Egg",
|
||||
"Sunken City left area, Girl Costume",
|
||||
"Beating Mantis Shrimp Prime",
|
||||
"First secret",
|
||||
"Arnassi ruins, Arnassi Armor",
|
||||
"Arnassi Ruins, Arnassi Armor",
|
||||
]
|
||||
items = [["Spirit form"]]
|
||||
self.assertAccessDependency(locations, items)
|
||||
|
||||
@@ -14,11 +14,11 @@ class SunFormAccessTest(AquariaTestBase):
|
||||
"""Test locations that require sun form"""
|
||||
locations = [
|
||||
"First secret",
|
||||
"The whale, Verse egg",
|
||||
"The Whale, Verse Egg",
|
||||
"Abyss right area, bulb behind the rock in the whale room",
|
||||
"Octopus cave, Dumbo Egg",
|
||||
"Octopus Cave, Dumbo Egg",
|
||||
"Beating Octopus Prime",
|
||||
"Final boss area, bulb in the boss third form room",
|
||||
"Final Boss area, bulb in the boss third form room",
|
||||
"Objective complete"
|
||||
]
|
||||
items = [["Sun form"]]
|
||||
|
||||
@@ -17,5 +17,5 @@ class UnconfineHomeWaterBothAccessTest(AquariaTestBase):
|
||||
|
||||
def test_unconfine_home_water_both_location(self) -> None:
|
||||
"""Test locations accessible with unconfined home water via energy door and transportation turtle"""
|
||||
self.assertTrue(self.can_reach_region("Open water top left area"), "Cannot reach Open water top left area")
|
||||
self.assertTrue(self.can_reach_region("Home Water, turtle room"), "Cannot reach Home Water, turtle room")
|
||||
self.assertTrue(self.can_reach_region("Open Water top left area"), "Cannot reach Open Water top left area")
|
||||
self.assertTrue(self.can_reach_region("Home Water, turtle room"), "Cannot reach Home Water, turtle room")
|
||||
|
||||
@@ -16,5 +16,5 @@ class UnconfineHomeWaterEnergyDoorAccessTest(AquariaTestBase):
|
||||
|
||||
def test_unconfine_home_water_energy_door_location(self) -> None:
|
||||
"""Test locations accessible with unconfined home water via energy door"""
|
||||
self.assertTrue(self.can_reach_region("Open water top left area"), "Cannot reach Open water top left area")
|
||||
self.assertFalse(self.can_reach_region("Home Water, turtle room"), "Can reach Home Water, turtle room")
|
||||
self.assertTrue(self.can_reach_region("Open Water top left area"), "Cannot reach Open Water top left area")
|
||||
self.assertFalse(self.can_reach_region("Home Water, turtle room"), "Can reach Home Water, turtle room")
|
||||
|
||||
@@ -17,4 +17,4 @@ class UnconfineHomeWaterTransturtleAccessTest(AquariaTestBase):
|
||||
def test_unconfine_home_water_transturtle_location(self) -> None:
|
||||
"""Test locations accessible with unconfined home water via transportation turtle"""
|
||||
self.assertTrue(self.can_reach_region("Home Water, turtle room"), "Cannot reach Home Water, turtle room")
|
||||
self.assertFalse(self.can_reach_region("Open water top left area"), "Can reach Open water top left area")
|
||||
self.assertFalse(self.can_reach_region("Open Water top left area"), "Can reach Open Water top left area")
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
from typing import Dict
|
||||
|
||||
from BaseClasses import Tutorial
|
||||
from ..AutoWorld import WebWorld, World
|
||||
|
||||
|
||||
class Bk_SudokuWebWorld(WebWorld):
|
||||
options_page = "games/Sudoku/info/en"
|
||||
theme = 'partyTime'
|
||||
|
||||
setup_en = Tutorial(
|
||||
tutorial_name='Setup Guide',
|
||||
description='A guide to playing BK Sudoku',
|
||||
language='English',
|
||||
file_name='setup_en.md',
|
||||
link='setup/en',
|
||||
authors=['Jarno']
|
||||
)
|
||||
setup_de = Tutorial(
|
||||
tutorial_name='Setup Anleitung',
|
||||
description='Eine Anleitung um BK-Sudoku zu spielen',
|
||||
language='Deutsch',
|
||||
file_name='setup_de.md',
|
||||
link='setup/de',
|
||||
authors=['Held_der_Zeit']
|
||||
)
|
||||
|
||||
tutorials = [setup_en, setup_de]
|
||||
|
||||
|
||||
class Bk_SudokuWorld(World):
|
||||
"""
|
||||
Play a little Sudoku while you're in BK mode to maybe get some useful hints
|
||||
"""
|
||||
game = "Sudoku"
|
||||
web = Bk_SudokuWebWorld()
|
||||
data_version = 1
|
||||
|
||||
item_name_to_id: Dict[str, int] = {}
|
||||
location_name_to_id: Dict[str, int] = {}
|
||||
|
||||
@classmethod
|
||||
def stage_assert_generate(cls, multiworld):
|
||||
raise Exception("BK Sudoku cannot be used for generating worlds, the client can instead connect to any other world")
|
||||
@@ -1,21 +0,0 @@
|
||||
# BK-Sudoku
|
||||
|
||||
## Was ist das für ein Spiel?
|
||||
|
||||
BK-Sudoku ist kein typisches Archipelago-Spiel; stattdessen ist es ein gewöhnlicher Sudoku-Client der sich zu jeder
|
||||
beliebigen Multiworld verbinden kann. Einmal verbunden kannst du ein 9x9 Sudoku spielen um einen zufälligen Hinweis
|
||||
für dein Spiel zu erhalten. Es ist zwar langsam, aber es gibt dir etwas zu tun, solltest du mal nicht in der Lage sein
|
||||
weitere „Checks” zu erreichen.
|
||||
(Wer mag kann auch einfach so Sudoku spielen. Man muss nicht mit einer Multiworld verbunden sein, um ein Sudoku zu
|
||||
spielen/generieren.)
|
||||
|
||||
## Wie werden Hinweise freigeschalten?
|
||||
|
||||
Nach dem Lösen eines Sudokus wird für den verbundenen Slot ein zufällig ausgewählter Hinweis freigegeben, für einen
|
||||
Gegenstand der noch nicht gefunden wurde.
|
||||
|
||||
## Wo ist die Seite für die Einstellungen?
|
||||
|
||||
Es gibt keine Seite für die Einstellungen. Dieses Spiel kann nicht in deinen YAML-Dateien benutzt werden. Stattdessen
|
||||
kann sich der Client mit einem beliebigen Slot einer Multiworld verbinden. In dem Client selbst kann aber der
|
||||
Schwierigkeitsgrad des Sudoku ausgewählt werden.
|
||||
@@ -1,13 +0,0 @@
|
||||
# Bk Sudoku
|
||||
|
||||
## What is this game?
|
||||
|
||||
BK Sudoku is not a typical Archipelago game; instead, it is a generic Sudoku client that can connect to any existing multiworld. When connected, you can play Sudoku to unlock random hints for your game. While slow, it will give you something to do when you can't reach the checks in your game.
|
||||
|
||||
## What hints are unlocked?
|
||||
|
||||
After completing a Sudoku puzzle, the game will unlock 1 random hint for an unchecked location in the slot you are connected to.
|
||||
|
||||
## Where is the options page?
|
||||
|
||||
There is no options page; this game cannot be used in your .yamls. Instead, the client can connect to any slot in a multiworld.
|
||||
@@ -1,27 +0,0 @@
|
||||
# BK-Sudoku Setup Anleitung
|
||||
|
||||
## Benötigte Software
|
||||
- [Bk-Sudoku](https://github.com/Jarno458/sudoku)
|
||||
- Windows 8 oder höher
|
||||
|
||||
## Generelles Konzept
|
||||
|
||||
Dies ist ein Client, der sich mit jedem beliebigen Slot einer Multiworld verbinden kann. Er lässt dich ein (9x9) Sudoku
|
||||
spielen, um zufällige Hinweise für den verbundenen Slot freizuschalten.
|
||||
|
||||
Aufgrund des Fakts, dass der Sudoku-Client sich zu jedem beliebigen Slot verbinden kann, ist es daher nicht notwendig
|
||||
eine YAML für dieses Spiel zu generieren, da es keinen neuen Slot zur Multiworld-Session hinzufügt.
|
||||
|
||||
## Installationsprozess
|
||||
|
||||
Gehe zu der aktuellsten (latest) Veröffentlichung der [BK-Sudoku Releases](https://github.com/Jarno458/sudoku/releases).
|
||||
Downloade und extrahiere/entpacke die `Bk_Sudoku.zip`-Datei.
|
||||
|
||||
## Verbinden mit einer Multiworld
|
||||
|
||||
1. Starte `Bk_Sudoku.exe`
|
||||
2. Trage den Namen des Slots ein, mit dem du dich verbinden möchtest
|
||||
3. Trage die Server-URL und den Port ein
|
||||
4. Drücke auf Verbinden (connect)
|
||||
5. Wähle deinen Schwierigkeitsgrad
|
||||
6. Versuche das Sudoku zu Lösen
|
||||
@@ -1,24 +0,0 @@
|
||||
# BK Sudoku Setup Guide
|
||||
|
||||
## Required Software
|
||||
- [Bk Sudoku](https://github.com/Jarno458/sudoku)
|
||||
- Windows 8 or higher
|
||||
|
||||
## General Concept
|
||||
|
||||
This is a client that can connect to any multiworld slot, and lets you play Sudoku to unlock random hints for that slot's locations.
|
||||
|
||||
Due to the fact that the Sudoku client may connect to any slot, it is not necessary to generate a YAML for this game as it does not generate any new slots in the multiworld session.
|
||||
|
||||
## Installation Procedures
|
||||
|
||||
Go to the latest release on [BK Sudoku Releases](https://github.com/Jarno458/sudoku/releases). Download and extract the `Bk_Sudoku.zip` file.
|
||||
|
||||
## Joining a MultiWorld Game
|
||||
|
||||
1. Run Bk_Sudoku.exe
|
||||
2. Enter the name of the slot you wish to connect to
|
||||
3. Enter the server url & port number
|
||||
4. Press connect
|
||||
5. Choose difficulty
|
||||
6. Try to solve the Sudoku
|
||||
@@ -32,7 +32,6 @@ class BlasphemousWorld(World):
|
||||
|
||||
game: str = "Blasphemous"
|
||||
web = BlasphemousWeb()
|
||||
data_version = 2
|
||||
|
||||
item_name_to_id = {item["name"]: (base_id + index) for index, item in enumerate(item_table)}
|
||||
location_name_to_id = {loc["name"]: (base_id + index) for index, loc in enumerate(location_table)}
|
||||
|
||||
@@ -5,17 +5,17 @@ from .Regions import Stages
|
||||
|
||||
|
||||
def graffitiM(state: CollectionState, player: int, limit: bool, spots: int) -> bool:
|
||||
return state.count_group_exclusive("graffitim", player) * 7 >= spots if limit \
|
||||
return state.count_group_unique("graffitim", player) * 7 >= spots if limit \
|
||||
else state.has_group("graffitim", player)
|
||||
|
||||
|
||||
def graffitiL(state: CollectionState, player: int, limit: bool, spots: int) -> bool:
|
||||
return state.count_group_exclusive("graffitil", player) * 6 >= spots if limit \
|
||||
return state.count_group_unique("graffitil", player) * 6 >= spots if limit \
|
||||
else state.has_group("graffitil", player)
|
||||
|
||||
|
||||
def graffitiXL(state: CollectionState, player: int, limit: bool, spots: int) -> bool:
|
||||
return state.count_group_exclusive("graffitixl", player) * 4 >= spots if limit \
|
||||
return state.count_group_unique("graffitixl", player) * 4 >= spots if limit \
|
||||
else state.has_group("graffitixl", player)
|
||||
|
||||
|
||||
@@ -469,7 +469,7 @@ def spots_s_glitchless(state: CollectionState, player: int, limit: bool, access_
|
||||
break
|
||||
|
||||
if limit:
|
||||
sprayable: int = 5 + (state.count_group_exclusive("characters", player) * 5)
|
||||
sprayable: int = 5 + (state.count_group_unique("characters", player) * 5)
|
||||
if total <= sprayable:
|
||||
return total
|
||||
else:
|
||||
@@ -492,7 +492,7 @@ def spots_s_glitched(state: CollectionState, player: int, limit: bool, access_ca
|
||||
break
|
||||
|
||||
if limit:
|
||||
sprayable: int = 5 + (state.count_group_exclusive("characters", player) * 5)
|
||||
sprayable: int = 5 + (state.count_group_unique("characters", player) * 5)
|
||||
if total <= sprayable:
|
||||
return total
|
||||
else:
|
||||
@@ -537,7 +537,7 @@ def spots_m_glitchless(state: CollectionState, player: int, limit: bool, access_
|
||||
break
|
||||
|
||||
if limit:
|
||||
sprayable: int = state.count_group_exclusive("graffitim", player) * 7
|
||||
sprayable: int = state.count_group_unique("graffitim", player) * 7
|
||||
if total <= sprayable:
|
||||
return total
|
||||
else:
|
||||
@@ -563,7 +563,7 @@ def spots_m_glitched(state: CollectionState, player: int, limit: bool, access_ca
|
||||
break
|
||||
|
||||
if limit:
|
||||
sprayable: int = state.count_group_exclusive("graffitim", player) * 7
|
||||
sprayable: int = state.count_group_unique("graffitim", player) * 7
|
||||
if total <= sprayable:
|
||||
return total
|
||||
else:
|
||||
@@ -614,7 +614,7 @@ def spots_l_glitchless(state: CollectionState, player: int, limit: bool, access_
|
||||
break
|
||||
|
||||
if limit:
|
||||
sprayable: int = state.count_group_exclusive("graffitil", player) * 6
|
||||
sprayable: int = state.count_group_unique("graffitil", player) * 6
|
||||
if total <= sprayable:
|
||||
return total
|
||||
else:
|
||||
@@ -641,7 +641,7 @@ def spots_l_glitched(state: CollectionState, player: int, limit: bool, access_ca
|
||||
break
|
||||
|
||||
if limit:
|
||||
sprayable: int = state.count_group_exclusive("graffitil", player) * 6
|
||||
sprayable: int = state.count_group_unique("graffitil", player) * 6
|
||||
if total <= sprayable:
|
||||
return total
|
||||
else:
|
||||
@@ -685,7 +685,7 @@ def spots_xl_glitchless(state: CollectionState, player: int, limit: bool, access
|
||||
break
|
||||
|
||||
if limit:
|
||||
sprayable: int = state.count_group_exclusive("graffitixl", player) * 4
|
||||
sprayable: int = state.count_group_unique("graffitixl", player) * 4
|
||||
if total <= sprayable:
|
||||
return total
|
||||
else:
|
||||
@@ -712,7 +712,7 @@ def spots_xl_glitched(state: CollectionState, player: int, limit: bool, access_c
|
||||
break
|
||||
|
||||
if limit:
|
||||
sprayable: int = state.count_group_exclusive("graffitixl", player) * 4
|
||||
sprayable: int = state.count_group_unique("graffitixl", player) * 4
|
||||
if total <= sprayable:
|
||||
return total
|
||||
else:
|
||||
|
||||
@@ -39,8 +39,6 @@ class BumpStikWorld(World):
|
||||
location_name_to_id = location_table
|
||||
item_name_groups = item_groups
|
||||
|
||||
data_version = 1
|
||||
|
||||
required_client_version = (0, 3, 8)
|
||||
|
||||
options: BumpstikOptions
|
||||
|
||||
@@ -33,8 +33,6 @@ class ChecksFinderWorld(World):
|
||||
item_name_to_id = {name: data.code for name, data in item_table.items()}
|
||||
location_name_to_id = {name: data.id for name, data in advancement_table.items()}
|
||||
|
||||
data_version = 4
|
||||
|
||||
def _get_checksfinder_data(self):
|
||||
return {
|
||||
'world_seed': self.multiworld.per_slot_randoms[self.player].getrandbits(32),
|
||||
|
||||
@@ -37,7 +37,6 @@ class CliqueWorld(World):
|
||||
"""The greatest game of all time."""
|
||||
|
||||
game = "Clique"
|
||||
data_version = 3
|
||||
web = CliqueWebWorld()
|
||||
option_definitions = clique_options
|
||||
location_name_to_id = location_table
|
||||
|
||||
@@ -8,7 +8,7 @@ from BaseClasses import Item, Region, Tutorial, ItemClassification
|
||||
from .items import CV64Item, filler_item_names, get_item_info, get_item_names_to_ids, get_item_counts
|
||||
from .locations import CV64Location, get_location_info, verify_locations, get_location_names_to_ids, base_id
|
||||
from .entrances import verify_entrances, get_warp_entrances
|
||||
from .options import CV64Options, CharacterStages, DraculasCondition, SubWeaponShuffle
|
||||
from .options import CV64Options, cv64_option_groups, CharacterStages, DraculasCondition, SubWeaponShuffle
|
||||
from .stages import get_locations_from_stage, get_normal_stage_exits, vanilla_stage_order, \
|
||||
shuffle_stages, generate_warps, get_region_names
|
||||
from .regions import get_region_info
|
||||
@@ -45,6 +45,8 @@ class CV64Web(WebWorld):
|
||||
["Liquid Cat"]
|
||||
)]
|
||||
|
||||
option_groups = cv64_option_groups
|
||||
|
||||
|
||||
class CV64World(World):
|
||||
"""
|
||||
@@ -62,7 +64,6 @@ class CV64World(World):
|
||||
options: CV64Options
|
||||
settings: typing.ClassVar[CV64Settings]
|
||||
topology_present = True
|
||||
data_version = 1
|
||||
|
||||
item_name_to_id = get_item_names_to_ids()
|
||||
location_name_to_id = get_location_names_to_ids()
|
||||
|
||||
@@ -146,7 +146,7 @@ class Castlevania64Client(BizHawkClient):
|
||||
text_color = bytearray([0xA2, 0x0B])
|
||||
else:
|
||||
text_color = bytearray([0xA2, 0x02])
|
||||
received_text, num_lines = cv64_text_wrap(f"{ctx.item_names[next_item.item]}\n"
|
||||
received_text, num_lines = cv64_text_wrap(f"{ctx.item_names.lookup_in_slot(next_item.item)}\n"
|
||||
f"from {ctx.player_names[next_item.player]}", 96)
|
||||
await bizhawk.guarded_write(ctx.bizhawk_ctx,
|
||||
[(0x389BE1, [next_item.item & 0xFF], "RDRAM"),
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from dataclasses import dataclass
|
||||
from Options import Choice, DefaultOnToggle, Range, Toggle, PerGameCommonOptions, StartInventoryPool
|
||||
from Options import OptionGroup, Choice, DefaultOnToggle, Range, Toggle, PerGameCommonOptions, StartInventoryPool
|
||||
|
||||
|
||||
class CharacterStages(Choice):
|
||||
"""Whether to include Reinhardt-only stages, Carrie-only stages, or both with or without branching paths at the end
|
||||
of Villa and Castle Center."""
|
||||
"""
|
||||
Whether to include Reinhardt-only stages, Carrie-only stages, or both with or without branching paths at the end of Villa and Castle Center.
|
||||
"""
|
||||
display_name = "Character Stages"
|
||||
option_both = 0
|
||||
option_branchless_both = 1
|
||||
@@ -14,14 +15,18 @@ class CharacterStages(Choice):
|
||||
|
||||
|
||||
class StageShuffle(Toggle):
|
||||
"""Shuffles which stages appear in which stage slots. Villa and Castle Center will never appear in any character
|
||||
stage slots if Character Stages is set to Both; they can only be somewhere on the main path.
|
||||
Castle Keep will always be at the end of the line."""
|
||||
"""
|
||||
Shuffles which stages appear in which stage slots.
|
||||
Villa and Castle Center will never appear in any character stage slots if Character Stages is set to Both; they can only be somewhere on the main path.
|
||||
Castle Keep will always be at the end of the line.
|
||||
"""
|
||||
display_name = "Stage Shuffle"
|
||||
|
||||
|
||||
class StartingStage(Choice):
|
||||
"""Which stage to start at if Stage Shuffle is turned on."""
|
||||
"""
|
||||
Which stage to start at if Stage Shuffle is turned on.
|
||||
"""
|
||||
display_name = "Starting Stage"
|
||||
option_forest_of_silence = 0
|
||||
option_castle_wall = 1
|
||||
@@ -39,8 +44,9 @@ class StartingStage(Choice):
|
||||
|
||||
|
||||
class WarpOrder(Choice):
|
||||
"""Arranges the warps in the warp menu in whichever stage order chosen,
|
||||
thereby changing the order they are unlocked in."""
|
||||
"""
|
||||
Arranges the warps in the warp menu in whichever stage order chosen, thereby changing the order they are unlocked in.
|
||||
"""
|
||||
display_name = "Warp Order"
|
||||
option_seed_stage_order = 0
|
||||
option_vanilla_stage_order = 1
|
||||
@@ -49,7 +55,9 @@ class WarpOrder(Choice):
|
||||
|
||||
|
||||
class SubWeaponShuffle(Choice):
|
||||
"""Shuffles all sub-weapons in the game within each other in their own pool or in the main item pool."""
|
||||
"""
|
||||
Shuffles all sub-weapons in the game within each other in their own pool or in the main item pool.
|
||||
"""
|
||||
display_name = "Sub-weapon Shuffle"
|
||||
option_off = 0
|
||||
option_own_pool = 1
|
||||
@@ -58,8 +66,10 @@ class SubWeaponShuffle(Choice):
|
||||
|
||||
|
||||
class SpareKeys(Choice):
|
||||
"""Puts an additional copy of every non-Special key item in the pool for every key item that there is.
|
||||
Chance gives each key item a 50% chance of having a duplicate instead of guaranteeing one for all of them."""
|
||||
"""
|
||||
Puts an additional copy of every non-Special key item in the pool for every key item that there is.
|
||||
Chance gives each key item a 50% chance of having a duplicate instead of guaranteeing one for all of them.
|
||||
"""
|
||||
display_name = "Spare Keys"
|
||||
option_off = 0
|
||||
option_on = 1
|
||||
@@ -68,14 +78,17 @@ class SpareKeys(Choice):
|
||||
|
||||
|
||||
class HardItemPool(Toggle):
|
||||
"""Replaces some items in the item pool with less valuable ones, to make the item pool sort of resemble Hard Mode
|
||||
in the PAL version."""
|
||||
"""
|
||||
Replaces some items in the item pool with less valuable ones, to make the item pool sort of resemble Hard Mode in the PAL version.
|
||||
"""
|
||||
display_name = "Hard Item Pool"
|
||||
|
||||
|
||||
class Special1sPerWarp(Range):
|
||||
"""Sets how many Special1 jewels are needed per warp menu option unlock.
|
||||
This will decrease until the number x 7 is less than or equal to the Total Specail1s if it isn't already."""
|
||||
"""
|
||||
Sets how many Special1 jewels are needed per warp menu option unlock.
|
||||
This will decrease until the number x 7 is less than or equal to the Total Specail1s if it isn't already.
|
||||
"""
|
||||
range_start = 1
|
||||
range_end = 10
|
||||
default = 1
|
||||
@@ -83,7 +96,9 @@ class Special1sPerWarp(Range):
|
||||
|
||||
|
||||
class TotalSpecial1s(Range):
|
||||
"""Sets how many Speical1 jewels are in the pool in total."""
|
||||
"""
|
||||
Sets how many Speical1 jewels are in the pool in total.
|
||||
"""
|
||||
range_start = 7
|
||||
range_end = 70
|
||||
default = 7
|
||||
@@ -91,11 +106,13 @@ class TotalSpecial1s(Range):
|
||||
|
||||
|
||||
class DraculasCondition(Choice):
|
||||
"""Sets the requirement for unlocking and opening the door to Dracula's chamber.
|
||||
"""
|
||||
Sets the requirement for unlocking and opening the door to Dracula's chamber.
|
||||
None: No requirement. Door is unlocked from the start.
|
||||
Crystal: Activate the big crystal in Castle Center's basement. Neither boss afterwards has to be defeated.
|
||||
Bosses: Kill a specified number of bosses with health bars and claim their Trophies.
|
||||
Specials: Find a specified number of Special2 jewels shuffled in the main item pool."""
|
||||
Specials: Find a specified number of Special2 jewels shuffled in the main item pool.
|
||||
"""
|
||||
display_name = "Dracula's Condition"
|
||||
option_none = 0
|
||||
option_crystal = 1
|
||||
@@ -105,7 +122,9 @@ class DraculasCondition(Choice):
|
||||
|
||||
|
||||
class PercentSpecial2sRequired(Range):
|
||||
"""Percentage of Special2s required to enter Dracula's chamber when Dracula's Condition is Special2s."""
|
||||
"""
|
||||
Percentage of Special2s required to enter Dracula's chamber when Dracula's Condition is Special2s.
|
||||
"""
|
||||
range_start = 1
|
||||
range_end = 100
|
||||
default = 80
|
||||
@@ -113,7 +132,9 @@ class PercentSpecial2sRequired(Range):
|
||||
|
||||
|
||||
class TotalSpecial2s(Range):
|
||||
"""How many Speical2 jewels are in the pool in total when Dracula's Condition is Special2s."""
|
||||
"""
|
||||
How many Speical2 jewels are in the pool in total when Dracula's Condition is Special2s.
|
||||
"""
|
||||
range_start = 1
|
||||
range_end = 70
|
||||
default = 25
|
||||
@@ -121,58 +142,70 @@ class TotalSpecial2s(Range):
|
||||
|
||||
|
||||
class BossesRequired(Range):
|
||||
"""How many bosses need to be defeated to enter Dracula's chamber when Dracula's Condition is set to Bosses.
|
||||
This will automatically adjust if there are fewer available bosses than the chosen number."""
|
||||
"""
|
||||
How many bosses need to be defeated to enter Dracula's chamber when Dracula's Condition is set to Bosses.
|
||||
This will automatically adjust if there are fewer available bosses than the chosen number.
|
||||
"""
|
||||
range_start = 1
|
||||
range_end = 16
|
||||
default = 14
|
||||
default = 12
|
||||
display_name = "Bosses Required"
|
||||
|
||||
|
||||
class CarrieLogic(Toggle):
|
||||
"""Adds the 2 checks inside Underground Waterway's crawlspace to the pool.
|
||||
"""
|
||||
Adds the 2 checks inside Underground Waterway's crawlspace to the pool.
|
||||
If you (and everyone else if racing the same seed) are planning to only ever play Reinhardt, don't enable this.
|
||||
Can be combined with Hard Logic to include Carrie-only tricks."""
|
||||
Can be combined with Hard Logic to include Carrie-only tricks.
|
||||
"""
|
||||
display_name = "Carrie Logic"
|
||||
|
||||
|
||||
class HardLogic(Toggle):
|
||||
"""Properly considers sequence break tricks in logic (i.e. maze skip). Can be combined with Carrie Logic to include
|
||||
Carrie-only tricks.
|
||||
See the Game Page for a full list of tricks and glitches that may be logically required."""
|
||||
"""
|
||||
Properly considers sequence break tricks in logic (i.e. maze skip). Can be combined with Carrie Logic to include Carrie-only tricks.
|
||||
See the Game Page for a full list of tricks and glitches that may be logically required.
|
||||
"""
|
||||
display_name = "Hard Logic"
|
||||
|
||||
|
||||
class MultiHitBreakables(Toggle):
|
||||
"""Adds the items that drop from the objects that break in three hits to the pool. There are 18 of these throughout
|
||||
the game, adding up to 79 or 80 checks (depending on sub-weapons
|
||||
being shuffled anywhere or not) in total with all stages.
|
||||
The game will be modified to
|
||||
remember exactly which of their items you've picked up instead of simply whether they were broken or not."""
|
||||
"""
|
||||
Adds the items that drop from the objects that break in three hits to the pool.
|
||||
There are 18 of these throughout the game, adding up to 79 or 80 checks (depending on sub-weapons being shuffled anywhere or not) in total with all stages.
|
||||
The game will be modified to remember exactly which of their items you've picked up instead of simply whether they were broken or not.
|
||||
"""
|
||||
display_name = "Multi-hit Breakables"
|
||||
|
||||
|
||||
class EmptyBreakables(Toggle):
|
||||
"""Adds 9 check locations in the form of breakables that normally have nothing (all empty Forest coffins, etc.)
|
||||
and some additional Red Jewels and/or moneybags into the item pool to compensate."""
|
||||
"""
|
||||
Adds 9 check locations in the form of breakables that normally have nothing (all empty Forest coffins, etc.) and some additional Red Jewels and/or moneybags into the item pool to compensate.
|
||||
"""
|
||||
display_name = "Empty Breakables"
|
||||
|
||||
|
||||
class LizardLockerItems(Toggle):
|
||||
"""Adds the 6 items inside Castle Center 2F's Lizard-man generators to the pool.
|
||||
Picking up all of these can be a very tedious luck-based process, so they are off by default."""
|
||||
"""
|
||||
Adds the 6 items inside Castle Center 2F's Lizard-man generators to the pool.
|
||||
Picking up all of these can be a very tedious luck-based process, so they are off by default.
|
||||
"""
|
||||
display_name = "Lizard Locker Items"
|
||||
|
||||
|
||||
class Shopsanity(Toggle):
|
||||
"""Adds 7 one-time purchases from Renon's shop into the location pool. After buying an item from a slot, it will
|
||||
revert to whatever it is in the vanilla game."""
|
||||
"""
|
||||
Adds 7 one-time purchases from Renon's shop into the location pool.
|
||||
After buying an item from a slot, it will revert to whatever it is in the vanilla game.
|
||||
"""
|
||||
display_name = "Shopsanity"
|
||||
|
||||
|
||||
class ShopPrices(Choice):
|
||||
"""Randomizes the amount of gold each item costs in Renon's shop.
|
||||
Use the below options to control how much or little an item can cost."""
|
||||
"""
|
||||
Randomizes the amount of gold each item costs in Renon's shop.
|
||||
Use the Minimum and Maximum Gold Price options to control how much or how little an item can cost.
|
||||
"""
|
||||
display_name = "Shop Prices"
|
||||
option_vanilla = 0
|
||||
option_randomized = 1
|
||||
@@ -180,7 +213,9 @@ class ShopPrices(Choice):
|
||||
|
||||
|
||||
class MinimumGoldPrice(Range):
|
||||
"""The lowest amount of gold an item can cost in Renon's shop, divided by 100."""
|
||||
"""
|
||||
The lowest amount of gold an item can cost in Renon's shop, divided by 100.
|
||||
"""
|
||||
display_name = "Minimum Gold Price"
|
||||
range_start = 1
|
||||
range_end = 50
|
||||
@@ -188,7 +223,9 @@ class MinimumGoldPrice(Range):
|
||||
|
||||
|
||||
class MaximumGoldPrice(Range):
|
||||
"""The highest amount of gold an item can cost in Renon's shop, divided by 100."""
|
||||
"""
|
||||
The highest amount of gold an item can cost in Renon's shop, divided by 100.
|
||||
"""
|
||||
display_name = "Maximum Gold Price"
|
||||
range_start = 1
|
||||
range_end = 50
|
||||
@@ -196,8 +233,9 @@ class MaximumGoldPrice(Range):
|
||||
|
||||
|
||||
class PostBehemothBoss(Choice):
|
||||
"""Sets which boss is fought in the vampire triplets' room in Castle Center by which characters after defeating
|
||||
Behemoth."""
|
||||
"""
|
||||
Sets which boss is fought in the vampire triplets' room in Castle Center by which characters after defeating Behemoth.
|
||||
"""
|
||||
display_name = "Post-Behemoth Boss"
|
||||
option_vanilla = 0
|
||||
option_inverted = 1
|
||||
@@ -207,7 +245,9 @@ class PostBehemothBoss(Choice):
|
||||
|
||||
|
||||
class RoomOfClocksBoss(Choice):
|
||||
"""Sets which boss is fought at Room of Clocks by which characters."""
|
||||
"""
|
||||
Sets which boss is fought at Room of Clocks by which characters.
|
||||
"""
|
||||
display_name = "Room of Clocks Boss"
|
||||
option_vanilla = 0
|
||||
option_inverted = 1
|
||||
@@ -217,7 +257,9 @@ class RoomOfClocksBoss(Choice):
|
||||
|
||||
|
||||
class RenonFightCondition(Choice):
|
||||
"""Sets the condition on which the Renon fight will trigger."""
|
||||
"""
|
||||
Sets the condition on which the Renon fight will trigger.
|
||||
"""
|
||||
display_name = "Renon Fight Condition"
|
||||
option_never = 0
|
||||
option_spend_30k = 1
|
||||
@@ -226,7 +268,9 @@ class RenonFightCondition(Choice):
|
||||
|
||||
|
||||
class VincentFightCondition(Choice):
|
||||
"""Sets the condition on which the vampire Vincent fight will trigger."""
|
||||
"""
|
||||
Sets the condition on which the vampire Vincent fight will trigger.
|
||||
"""
|
||||
display_name = "Vincent Fight Condition"
|
||||
option_never = 0
|
||||
option_wait_16_days = 1
|
||||
@@ -235,7 +279,9 @@ class VincentFightCondition(Choice):
|
||||
|
||||
|
||||
class BadEndingCondition(Choice):
|
||||
"""Sets the condition on which the currently-controlled character's Bad Ending will trigger."""
|
||||
"""
|
||||
Sets the condition on which the currently-controlled character's Bad Ending will trigger.
|
||||
"""
|
||||
display_name = "Bad Ending Condition"
|
||||
option_never = 0
|
||||
option_kill_vincent = 1
|
||||
@@ -244,24 +290,32 @@ class BadEndingCondition(Choice):
|
||||
|
||||
|
||||
class IncreaseItemLimit(DefaultOnToggle):
|
||||
"""Increases the holding limit of usable items from 10 to 99 of each item."""
|
||||
"""
|
||||
Increases the holding limit of usable items from 10 to 99 of each item.
|
||||
"""
|
||||
display_name = "Increase Item Limit"
|
||||
|
||||
|
||||
class NerfHealingItems(Toggle):
|
||||
"""Decreases the amount of health healed by Roast Chickens to 25%, Roast Beefs to 50%, and Healing Kits to 80%."""
|
||||
"""
|
||||
Decreases the amount of health healed by Roast Chickens to 25%, Roast Beefs to 50%, and Healing Kits to 80%.
|
||||
"""
|
||||
display_name = "Nerf Healing Items"
|
||||
|
||||
|
||||
class LoadingZoneHeals(DefaultOnToggle):
|
||||
"""Whether end-of-level loading zones restore health and cure status aliments or not.
|
||||
Recommended off for those looking for more of a survival horror experience!"""
|
||||
"""
|
||||
Whether end-of-level loading zones restore health and cure status aliments or not.
|
||||
Recommended off for those looking for more of a survival horror experience!
|
||||
"""
|
||||
display_name = "Loading Zone Heals"
|
||||
|
||||
|
||||
class InvisibleItems(Choice):
|
||||
"""Sets which items are visible in their locations and which are invisible until picked up.
|
||||
'Chance' gives each item a 50/50 chance of being visible or invisible."""
|
||||
"""
|
||||
Sets which items are visible in their locations and which are invisible until picked up.
|
||||
'Chance' gives each item a 50/50 chance of being visible or invisible.
|
||||
"""
|
||||
display_name = "Invisible Items"
|
||||
option_vanilla = 0
|
||||
option_reveal_all = 1
|
||||
@@ -271,21 +325,25 @@ class InvisibleItems(Choice):
|
||||
|
||||
|
||||
class DropPreviousSubWeapon(Toggle):
|
||||
"""When receiving a sub-weapon, the one you had before will drop behind you, so it can be taken back if desired."""
|
||||
"""
|
||||
When receiving a sub-weapon, the one you had before will drop behind you, so it can be taken back if desired.
|
||||
"""
|
||||
display_name = "Drop Previous Sub-weapon"
|
||||
|
||||
|
||||
class PermanentPowerUps(Toggle):
|
||||
"""Replaces PowerUps with PermaUps, which upgrade your B weapon level permanently and will stay even after
|
||||
dying and/or continuing.
|
||||
To compensate, only two will be in the pool overall, and they will not drop from any enemy or projectile."""
|
||||
"""
|
||||
Replaces PowerUps with PermaUps, which upgrade your B weapon level permanently and will stay even after dying and/or continuing.
|
||||
To compensate, only two will be in the pool overall, and they will not drop from any enemy or projectile.
|
||||
"""
|
||||
display_name = "Permanent PowerUps"
|
||||
|
||||
|
||||
class IceTrapPercentage(Range):
|
||||
"""Replaces a percentage of junk items with Ice Traps.
|
||||
These will be visibly disguised as other items, and receiving one will freeze you
|
||||
as if you were hit by Camilla's ice cloud attack."""
|
||||
"""
|
||||
Replaces a percentage of junk items with Ice Traps.
|
||||
These will be visibly disguised as other items, and receiving one will freeze you as if you were hit by Camilla's ice cloud attack.
|
||||
"""
|
||||
display_name = "Ice Trap Percentage"
|
||||
range_start = 0
|
||||
range_end = 100
|
||||
@@ -293,7 +351,9 @@ class IceTrapPercentage(Range):
|
||||
|
||||
|
||||
class IceTrapAppearance(Choice):
|
||||
"""What items Ice Traps can possibly be disguised as."""
|
||||
"""
|
||||
What items Ice Traps can possibly be disguised as.
|
||||
"""
|
||||
display_name = "Ice Trap Appearance"
|
||||
option_major_only = 0
|
||||
option_junk_only = 1
|
||||
@@ -302,31 +362,34 @@ class IceTrapAppearance(Choice):
|
||||
|
||||
|
||||
class DisableTimeRestrictions(Toggle):
|
||||
"""Disables the restriction on every event and door that requires the current time
|
||||
to be within a specific range, so they can be triggered at any time.
|
||||
"""
|
||||
Disables the restriction on every event and door that requires the current time to be within a specific range, so they can be triggered at any time.
|
||||
This includes all sun/moon doors and, in the Villa, the meeting with Rosa and the fountain pillar.
|
||||
The Villa coffin is not affected by this."""
|
||||
The Villa coffin is not affected by this.
|
||||
"""
|
||||
display_name = "Disable Time Requirements"
|
||||
|
||||
|
||||
class SkipGondolas(Toggle):
|
||||
"""Makes jumping on and activating a gondola in Tunnel instantly teleport you
|
||||
to the other station, thereby skipping the entire three-minute ride.
|
||||
The item normally at the gondola transfer point is moved to instead be
|
||||
near the red gondola at its station."""
|
||||
"""
|
||||
Makes jumping on and activating a gondola in Tunnel instantly teleport you to the other station, thereby skipping the entire three-minute ride.
|
||||
The item normally at the gondola transfer point is moved to instead be near the red gondola at its station.
|
||||
"""
|
||||
display_name = "Skip Gondolas"
|
||||
|
||||
|
||||
class SkipWaterwayBlocks(Toggle):
|
||||
"""Opens the door to the third switch in Underground Waterway from the start so that the jumping across floating
|
||||
brick platforms won't have to be done. Shopping at the Contract on the other side of them may still be logically
|
||||
required if Shopsanity is on."""
|
||||
"""
|
||||
Opens the door to the third switch in Underground Waterway from the start so that the jumping across floating brick platforms won't have to be done.
|
||||
Shopping at the Contract on the other side of them may still be logically required if Shopsanity is on.
|
||||
"""
|
||||
display_name = "Skip Waterway Blocks"
|
||||
|
||||
|
||||
class Countdown(Choice):
|
||||
"""Displays, near the HUD clock and below the health bar, the number of unobtained progression-marked items
|
||||
or the total check locations remaining in the stage you are currently in."""
|
||||
"""
|
||||
Displays, near the HUD clock and below the health bar, the number of unobtained progression-marked items or the total check locations remaining in the stage you are currently in.
|
||||
"""
|
||||
display_name = "Countdown"
|
||||
option_none = 0
|
||||
option_majors = 1
|
||||
@@ -335,19 +398,21 @@ class Countdown(Choice):
|
||||
|
||||
|
||||
class BigToss(Toggle):
|
||||
"""Makes every non-immobilizing damage source launch you as if you got hit by Behemoth's charge.
|
||||
"""
|
||||
Makes every non-immobilizing damage source launch you as if you got hit by Behemoth's charge.
|
||||
Press A while tossed to cancel the launch momentum and avoid being thrown off ledges.
|
||||
Hold Z to have all incoming damage be treated as it normally would.
|
||||
Any tricks that might be possible with it are NOT considered in logic by any options."""
|
||||
Any tricks that might be possible with it are not in logic.
|
||||
"""
|
||||
display_name = "Big Toss"
|
||||
|
||||
|
||||
class PantherDash(Choice):
|
||||
"""Hold C-right at any time to sprint way faster. Any tricks that might be
|
||||
possible with it are NOT considered in logic by any options and any boss
|
||||
fights with boss health meters, if started, are expected to be finished
|
||||
before leaving their arenas if Dracula's Condition is bosses. Jumpless will
|
||||
prevent jumping while moving at the increased speed to ensure logic cannot be broken with it."""
|
||||
"""
|
||||
Hold C-right at any time to sprint way faster.
|
||||
Any tricks that are possible with it are not in logic and any boss fights with boss health meters, if started, are expected to be finished before leaving their arenas if Dracula's Condition is bosses.
|
||||
Jumpless will prevent jumping while moving at the increased speed to make logic harder to break with it.
|
||||
"""
|
||||
display_name = "Panther Dash"
|
||||
option_off = 0
|
||||
option_on = 1
|
||||
@@ -356,19 +421,25 @@ class PantherDash(Choice):
|
||||
|
||||
|
||||
class IncreaseShimmySpeed(Toggle):
|
||||
"""Increases the speed at which characters shimmy left and right while hanging on ledges."""
|
||||
"""
|
||||
Increases the speed at which characters shimmy left and right while hanging on ledges.
|
||||
"""
|
||||
display_name = "Increase Shimmy Speed"
|
||||
|
||||
|
||||
class FallGuard(Toggle):
|
||||
"""Removes fall damage from landing too hard. Note that falling for too long will still result in instant death."""
|
||||
"""
|
||||
Removes fall damage from landing too hard. Note that falling for too long will still result in instant death.
|
||||
"""
|
||||
display_name = "Fall Guard"
|
||||
|
||||
|
||||
class BackgroundMusic(Choice):
|
||||
"""Randomizes or disables the music heard throughout the game.
|
||||
"""
|
||||
Randomizes or disables the music heard throughout the game.
|
||||
Randomized music is split into two pools: songs that loop and songs that don't.
|
||||
The "lead-in" versions of some songs will be paired accordingly."""
|
||||
The "lead-in" versions of some songs will be paired accordingly.
|
||||
"""
|
||||
display_name = "Background Music"
|
||||
option_normal = 0
|
||||
option_disabled = 1
|
||||
@@ -377,8 +448,10 @@ class BackgroundMusic(Choice):
|
||||
|
||||
|
||||
class MapLighting(Choice):
|
||||
"""Randomizes the lighting color RGB values on every map during every time of day to be literally anything.
|
||||
The colors and/or shading of the following things are affected: fog, maps, player, enemies, and some objects."""
|
||||
"""
|
||||
Randomizes the lighting color RGB values on every map during every time of day to be literally anything.
|
||||
The colors and/or shading of the following things are affected: fog, maps, player, enemies, and some objects.
|
||||
"""
|
||||
display_name = "Map Lighting"
|
||||
option_normal = 0
|
||||
option_randomized = 1
|
||||
@@ -386,12 +459,16 @@ class MapLighting(Choice):
|
||||
|
||||
|
||||
class CinematicExperience(Toggle):
|
||||
"""Enables an unused film reel effect on every cutscene in the game. Purely cosmetic."""
|
||||
"""
|
||||
Enables an unused film reel effect on every cutscene in the game. Purely cosmetic.
|
||||
"""
|
||||
display_name = "Cinematic Experience"
|
||||
|
||||
|
||||
class WindowColorR(Range):
|
||||
"""The red value for the background color of the text windows during gameplay."""
|
||||
"""
|
||||
The red value for the background color of the text windows during gameplay.
|
||||
"""
|
||||
display_name = "Window Color R"
|
||||
range_start = 0
|
||||
range_end = 15
|
||||
@@ -399,7 +476,9 @@ class WindowColorR(Range):
|
||||
|
||||
|
||||
class WindowColorG(Range):
|
||||
"""The green value for the background color of the text windows during gameplay."""
|
||||
"""
|
||||
The green value for the background color of the text windows during gameplay.
|
||||
"""
|
||||
display_name = "Window Color G"
|
||||
range_start = 0
|
||||
range_end = 15
|
||||
@@ -407,7 +486,9 @@ class WindowColorG(Range):
|
||||
|
||||
|
||||
class WindowColorB(Range):
|
||||
"""The blue value for the background color of the text windows during gameplay."""
|
||||
"""
|
||||
The blue value for the background color of the text windows during gameplay.
|
||||
"""
|
||||
display_name = "Window Color B"
|
||||
range_start = 0
|
||||
range_end = 15
|
||||
@@ -415,7 +496,9 @@ class WindowColorB(Range):
|
||||
|
||||
|
||||
class WindowColorA(Range):
|
||||
"""The alpha value for the background color of the text windows during gameplay."""
|
||||
"""
|
||||
The alpha value for the background color of the text windows during gameplay.
|
||||
"""
|
||||
display_name = "Window Color A"
|
||||
range_start = 0
|
||||
range_end = 15
|
||||
@@ -423,9 +506,10 @@ class WindowColorA(Range):
|
||||
|
||||
|
||||
class DeathLink(Choice):
|
||||
"""When you die, everyone dies. Of course the reverse is true too.
|
||||
Explosive: Makes received DeathLinks kill you via the Magical Nitro explosion
|
||||
instead of the normal death animation."""
|
||||
"""
|
||||
When you die, everyone dies. Of course the reverse is true too.
|
||||
Explosive: Makes received DeathLinks kill you via the Magical Nitro explosion instead of the normal death animation.
|
||||
"""
|
||||
display_name = "DeathLink"
|
||||
option_off = 0
|
||||
alias_no = 0
|
||||
@@ -437,6 +521,7 @@ class DeathLink(Choice):
|
||||
|
||||
@dataclass
|
||||
class CV64Options(PerGameCommonOptions):
|
||||
start_inventory_from_pool: StartInventoryPool
|
||||
character_stages: CharacterStages
|
||||
stage_shuffle: StageShuffle
|
||||
starting_stage: StartingStage
|
||||
@@ -479,13 +564,26 @@ class CV64Options(PerGameCommonOptions):
|
||||
big_toss: BigToss
|
||||
panther_dash: PantherDash
|
||||
increase_shimmy_speed: IncreaseShimmySpeed
|
||||
background_music: BackgroundMusic
|
||||
map_lighting: MapLighting
|
||||
fall_guard: FallGuard
|
||||
cinematic_experience: CinematicExperience
|
||||
window_color_r: WindowColorR
|
||||
window_color_g: WindowColorG
|
||||
window_color_b: WindowColorB
|
||||
window_color_a: WindowColorA
|
||||
background_music: BackgroundMusic
|
||||
map_lighting: MapLighting
|
||||
fall_guard: FallGuard
|
||||
cinematic_experience: CinematicExperience
|
||||
death_link: DeathLink
|
||||
start_inventory_from_pool: StartInventoryPool
|
||||
|
||||
|
||||
cv64_option_groups = [
|
||||
OptionGroup("gameplay tweaks", [
|
||||
HardItemPool, ShopPrices, MinimumGoldPrice, MaximumGoldPrice, PostBehemothBoss, RoomOfClocksBoss,
|
||||
RenonFightCondition, VincentFightCondition, BadEndingCondition, IncreaseItemLimit, NerfHealingItems,
|
||||
LoadingZoneHeals, InvisibleItems, DropPreviousSubWeapon, PermanentPowerUps, IceTrapPercentage,
|
||||
IceTrapAppearance, DisableTimeRestrictions, SkipGondolas, SkipWaterwayBlocks, Countdown, BigToss, PantherDash,
|
||||
IncreaseShimmySpeed, FallGuard, DeathLink
|
||||
]),
|
||||
OptionGroup("cosmetics", [
|
||||
WindowColorR, WindowColorG, WindowColorB, WindowColorA, BackgroundMusic, MapLighting, CinematicExperience
|
||||
])
|
||||
]
|
||||
|
||||
@@ -1272,11 +1272,7 @@ _cut_content_items = [DS3ItemData(row[0], row[1], False, row[2]) for row in [
|
||||
]]
|
||||
|
||||
item_descriptions = {
|
||||
"Cinders": """
|
||||
All four Cinders of a Lord.
|
||||
|
||||
Once you have these four, you can fight Soul of Cinder and win the game.
|
||||
""",
|
||||
"Cinders": "All four Cinders of a Lord.\n\nOnce you have these four, you can fight Soul of Cinder and win the game.",
|
||||
}
|
||||
|
||||
_all_items = _vanilla_items + _dlc_items
|
||||
|
||||
@@ -35,6 +35,8 @@ class DarkSouls3Web(WebWorld):
|
||||
|
||||
tutorials = [setup_en, setup_fr]
|
||||
|
||||
item_descriptions = item_descriptions
|
||||
|
||||
|
||||
class DarkSouls3World(World):
|
||||
"""
|
||||
@@ -47,7 +49,6 @@ class DarkSouls3World(World):
|
||||
option_definitions = dark_souls_options
|
||||
topology_present: bool = True
|
||||
web = DarkSouls3Web()
|
||||
data_version = 8
|
||||
base_id = 100000
|
||||
enabled_location_categories: Set[DS3LocationCategory]
|
||||
required_client_version = (0, 4, 2)
|
||||
@@ -61,8 +62,6 @@ class DarkSouls3World(World):
|
||||
"Cinders of a Lord - Lothric Prince"
|
||||
}
|
||||
}
|
||||
item_descriptions = item_descriptions
|
||||
|
||||
|
||||
def __init__(self, multiworld: MultiWorld, player: int):
|
||||
super().__init__(multiworld, player)
|
||||
|
||||
@@ -86,7 +86,7 @@ class DKC3SNIClient(SNIClient):
|
||||
|
||||
for new_check_id in new_checks:
|
||||
ctx.locations_checked.add(new_check_id)
|
||||
location = ctx.location_names[new_check_id]
|
||||
location = ctx.location_names.lookup_in_slot(new_check_id)
|
||||
snes_logger.info(
|
||||
f'New Check: {location} ({len(ctx.locations_checked)}/{len(ctx.missing_locations) + len(ctx.checked_locations)})')
|
||||
await ctx.send_msgs([{"cmd": 'LocationChecks', "locations": [new_check_id]}])
|
||||
@@ -99,9 +99,9 @@ class DKC3SNIClient(SNIClient):
|
||||
item = ctx.items_received[recv_index]
|
||||
recv_index += 1
|
||||
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
|
||||
color(ctx.item_names[item.item], 'red', 'bold'),
|
||||
color(ctx.item_names.lookup_in_slot(item.item), 'red', 'bold'),
|
||||
color(ctx.player_names[item.player], 'yellow'),
|
||||
ctx.location_names[item.location], recv_index, len(ctx.items_received)))
|
||||
ctx.location_names.lookup_in_slot(item.location, item.player), recv_index, len(ctx.items_received)))
|
||||
|
||||
snes_buffered_write(ctx, DKC3_RECV_PROGRESS_ADDR, bytes([recv_index]))
|
||||
if item.item in item_rom_data:
|
||||
|
||||
@@ -61,7 +61,6 @@ class DKC3World(World):
|
||||
options: DKC3Options
|
||||
|
||||
topology_present = False
|
||||
data_version = 2
|
||||
#hint_blacklist = {LocationName.rocket_rush_flag}
|
||||
|
||||
item_name_to_id = {name: data.code for name, data in item_table.items()}
|
||||
|
||||
@@ -43,8 +43,6 @@ class DLCqworld(World):
|
||||
item_name_to_id = {name: data.code for name, data in item_table.items()}
|
||||
location_name_to_id = location_table
|
||||
|
||||
data_version = 1
|
||||
|
||||
options_dataclass = DLCQuestOptions
|
||||
options: DLCQuestOptions
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ class DOOM1993World(World):
|
||||
options: DOOM1993Options
|
||||
game = "DOOM 1993"
|
||||
web = DOOM1993Web()
|
||||
data_version = 3
|
||||
required_client_version = (0, 3, 9)
|
||||
|
||||
item_name_to_id = {data["name"]: item_id for item_id, data in Items.item_table.items()}
|
||||
|
||||
@@ -43,7 +43,6 @@ class DOOM2World(World):
|
||||
options: DOOM2Options
|
||||
game = "DOOM II"
|
||||
web = DOOM2Web()
|
||||
data_version = 3
|
||||
required_client_version = (0, 3, 9)
|
||||
|
||||
item_name_to_id = {data["name"]: item_id for item_id, data in Items.item_table.items()}
|
||||
|
||||
@@ -247,7 +247,7 @@ async def game_watcher(ctx: FactorioContext):
|
||||
if ctx.locations_checked != research_data:
|
||||
bridge_logger.debug(
|
||||
f"New researches done: "
|
||||
f"{[ctx.location_names[rid] for rid in research_data - ctx.locations_checked]}")
|
||||
f"{[ctx.location_names.lookup_in_slot(rid) for rid in research_data - ctx.locations_checked]}")
|
||||
ctx.locations_checked = research_data
|
||||
await ctx.send_msgs([{"cmd": 'LocationChecks', "locations": tuple(research_data)}])
|
||||
death_link_tick = data.get("death_link_tick", 0)
|
||||
@@ -360,7 +360,7 @@ async def factorio_server_watcher(ctx: FactorioContext):
|
||||
transfer_item: NetworkItem = ctx.items_received[ctx.send_index]
|
||||
item_id = transfer_item.item
|
||||
player_name = ctx.player_names[transfer_item.player]
|
||||
item_name = ctx.item_names[item_id]
|
||||
item_name = ctx.item_names.lookup_in_slot(item_id)
|
||||
factorio_server_logger.info(f"Sending {item_name} to Nauvis from {player_name}.")
|
||||
commands[ctx.send_index] = f"/ap-get-technology {item_name}\t{ctx.send_index}\t{player_name}"
|
||||
ctx.send_index += 1
|
||||
|
||||
@@ -95,7 +95,6 @@ class Factorio(World):
|
||||
item_name_groups = {
|
||||
"Progressive": set(progressive_tech_table.keys()),
|
||||
}
|
||||
data_version = 8
|
||||
required_client_version = (0, 4, 2)
|
||||
|
||||
ordered_science_packs: typing.List[str] = MaxSciencePack.get_ordered_science_packs()
|
||||
|
||||
@@ -40,7 +40,6 @@ class FF1World(World):
|
||||
settings_key = "ffr_options"
|
||||
game = "Final Fantasy"
|
||||
topology_present = False
|
||||
data_version = 2
|
||||
|
||||
ff1_items = FF1Items()
|
||||
ff1_locations = FF1Locations()
|
||||
|
||||
@@ -56,8 +56,6 @@ class FFMQWorld(World):
|
||||
create_regions = create_regions
|
||||
set_rules = set_rules
|
||||
stage_set_rules = stage_set_rules
|
||||
|
||||
data_version = 1
|
||||
|
||||
web = FFMQWebWorld()
|
||||
# settings: FFMQSettings
|
||||
@@ -216,4 +214,3 @@ class FFMQWorld(World):
|
||||
hint_data[self.player][location.address] += f"/{hint}"
|
||||
else:
|
||||
hint_data[self.player][location.address] = hint
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ class GenericWorld(World):
|
||||
}
|
||||
hidden = True
|
||||
web = GenericWeb()
|
||||
data_version = 1
|
||||
|
||||
def generate_early(self):
|
||||
self.multiworld.player_types[self.player] = SlotType.spectator # mark as spectator
|
||||
@@ -69,9 +68,3 @@ class PlandoItem(NamedTuple):
|
||||
raise exception(warning)
|
||||
else:
|
||||
self.warn(warning)
|
||||
|
||||
|
||||
class PlandoConnection(NamedTuple):
|
||||
entrance: str
|
||||
exit: str
|
||||
direction: str # entrance, exit or both
|
||||
|
||||
@@ -79,7 +79,7 @@ are `description`, `name`, `game`, `requires`, and the name of the games you wan
|
||||
different weights.
|
||||
|
||||
* `requires` details different requirements from the generator for the YAML to work as you expect it to. Generally this
|
||||
is good for detailing the version of Archipelago this YAML was prepared for as, if it is rolled on an older version,
|
||||
is good for detailing the version of Archipelago this YAML was prepared for. If it is rolled on an older version,
|
||||
options may be missing and as such it will not work as expected. If any plando is used in the file then requiring it
|
||||
here to ensure it will be used is good practice.
|
||||
|
||||
@@ -137,7 +137,7 @@ guide: [Archipelago Plando Guide](/tutorial/Archipelago/plando/en)
|
||||
locations.
|
||||
* `item_links` allows players to link their items into a group with the same item link name and game. The items declared
|
||||
in `item_pool` get combined and when an item is found for the group, all players in the group receive it. Item links
|
||||
can also have local and non local items, forcing the items to either be placed within the worlds of the group or in
|
||||
can also have local and non-local items, forcing the items to either be placed within the worlds of the group or in
|
||||
worlds outside the group. If players have a varying amount of a specific item in the link, the lowest amount from the
|
||||
players will be the amount put into the group.
|
||||
|
||||
@@ -277,7 +277,7 @@ one file, removing the need to manage separate files if one chooses to do so.
|
||||
|
||||
As a precautionary measure, before submitting a multi-game yaml like this one in a synchronous/sync multiworld, please
|
||||
confirm that the other players in the multi are OK with what you are submitting, and please be fairly reasonable about
|
||||
the submission. (ie. Multiple long games (SMZ3, OoT, HK, etc.) for a game intended to be <2 hrs is not likely considered
|
||||
the submission. (i.e. Multiple long games (SMZ3, OoT, HK, etc.) for a game intended to be <2 hrs is not likely considered
|
||||
reasonable, but submitting a ChecksFinder alongside another game OR submitting multiple Slay the Spire runs is likely
|
||||
OK)
|
||||
|
||||
@@ -295,7 +295,7 @@ requires:
|
||||
version: 0.3.2
|
||||
Super Mario 64:
|
||||
progression_balancing: 50
|
||||
accessibilty: items
|
||||
accessibility: items
|
||||
EnableCoinStars: false
|
||||
StrictCapRequirements: true
|
||||
StrictCannonRequirements: true
|
||||
@@ -315,7 +315,7 @@ name: Minecraft
|
||||
game: Minecraft
|
||||
Minecraft:
|
||||
progression_balancing: 50
|
||||
accessibilty: items
|
||||
accessibility: items
|
||||
advancement_goal: 40
|
||||
combat_difficulty: hard
|
||||
include_hard_advancements: false
|
||||
@@ -341,7 +341,7 @@ game: ChecksFinder
|
||||
|
||||
ChecksFinder:
|
||||
progression_balancing: 50
|
||||
accessibilty: items
|
||||
accessibility: items
|
||||
```
|
||||
|
||||
The above example will generate 3 worlds - one Super Mario 64, one Minecraft, and one ChecksFinder.
|
||||
|
||||
@@ -123,10 +123,21 @@ again using the new options `normal`, `pupdunk_hard`, and `pupdunk_mystery`, and
|
||||
new weights for 150 and 200. This allows for two more triggers that will only be used for the new `pupdunk_hard`
|
||||
and `pupdunk_mystery` options so that they will only be triggered on "pupdunk AND hard/mystery".
|
||||
|
||||
Options that define a list, set, or dict can additionally have the character `+` added to the start of their name, which applies the contents of
|
||||
the activated trigger to the already present equivalents in the game options.
|
||||
## Adding or Removing from a List, Set, or Dict Option
|
||||
|
||||
List, set, and dict options can additionally have values added to or removed from itself without overriding the existing
|
||||
option value by prefixing the option name in the trigger block with `+` (add) or `-` (remove). The exact behavior for
|
||||
each will depend on the option type.
|
||||
|
||||
- For sets, `+` will add the value(s) to the set and `-` will remove the value(s) from the set. Sets do not allow
|
||||
duplicates.
|
||||
- For lists, `+` will add new values(s) to the list and `-` will remove the first matching values(s) it comes across.
|
||||
Lists allow duplicate values.
|
||||
- For dicts, `+` will add the value(s) to the given key(s) inside the dict if it exists, or add it otherwise. `-` is the
|
||||
inverse operation of addition (and negative values are allowed).
|
||||
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
Super Metroid:
|
||||
start_location:
|
||||
@@ -134,18 +145,18 @@ Super Metroid:
|
||||
aqueduct: 50
|
||||
start_hints:
|
||||
- Morph Ball
|
||||
triggers:
|
||||
- option_category: Super Metroid
|
||||
option_name: start_location
|
||||
option_result: aqueduct
|
||||
options:
|
||||
Super Metroid:
|
||||
+start_hints:
|
||||
- Gravity Suit
|
||||
start_inventory:
|
||||
Power Bombs: 1
|
||||
triggers:
|
||||
- option_category: Super Metroid
|
||||
option_name: start_location
|
||||
option_result: aqueduct
|
||||
options:
|
||||
Super Metroid:
|
||||
+start_hints:
|
||||
- Gravity Suit
|
||||
```
|
||||
|
||||
In this example, if the `start_location` option rolls `landing_site`, only a starting hint for Morph Ball will be created.
|
||||
If `aqueduct` is rolled, a starting hint for Gravity Suit will also be created alongside the hint for Morph Ball.
|
||||
|
||||
Note that for lists, items can only be added, not removed or replaced. For dicts, defining a value for a present key will
|
||||
replace that value within the dict.
|
||||
In this example, if the `start_location` option rolls `landing_site`, only a starting hint for Morph Ball will be
|
||||
created. If `aqueduct` is rolled, a starting hint for Gravity Suit will also be created alongside the hint for Morph
|
||||
Ball.
|
||||
|
||||
@@ -41,7 +41,6 @@ class HereticWorld(World):
|
||||
options: HereticOptions
|
||||
game = "Heretic"
|
||||
web = HereticWeb()
|
||||
data_version = 3
|
||||
required_client_version = (0, 3, 9)
|
||||
|
||||
item_name_to_id = {data["name"]: item_id for item_id, data in Items.item_table.items()}
|
||||
|
||||
@@ -9,7 +9,7 @@ def set_godhome_rules(hk_world, hk_set_rule):
|
||||
fn = partial(hk_set_rule, hk_world)
|
||||
|
||||
required_events = {
|
||||
"Godhome_Flower_Quest": lambda state: state.count('Defeated_Pantheon_5', player) and state.count('Room_Mansion[left1]', player) and state.count('Fungus3_49[right1]', player),
|
||||
"Godhome_Flower_Quest": lambda state: state.count('Defeated_Pantheon_5', player) and state.count('Room_Mansion[left1]', player) and state.count('Fungus3_49[right1]', player) and state.has('Godtuner', player),
|
||||
|
||||
"Defeated_Pantheon_5": lambda state: state.has('GG_Atrium_Roof', player) and state.has('WINGS', player) and (state.has('LEFTCLAW', player) or state.has('RIGHTCLAW', player)) and ((state.has('Defeated_Pantheon_1', player) and state.has('Defeated_Pantheon_2', player) and state.has('Defeated_Pantheon_3', player) and state.has('Defeated_Pantheon_4', player) and state.has('COMBAT[Radiance]', player))),
|
||||
"GG_Atrium_Roof": lambda state: state.has('GG_Atrium', player) and state.has('Hit_Pantheon_5_Unlock_Orb', player) and state.has('LEFTCLAW', player),
|
||||
|
||||
@@ -105,7 +105,7 @@ default_on = {
|
||||
"RandomizeVesselFragments",
|
||||
"RandomizeCharmNotches",
|
||||
"RandomizePaleOre",
|
||||
"RandomizeRancidEggs"
|
||||
"RandomizeRancidEggs",
|
||||
"RandomizeRelics",
|
||||
"RandomizeStags",
|
||||
"RandomizeLifebloodCocoons"
|
||||
|
||||
@@ -154,7 +154,6 @@ class HKWorld(World):
|
||||
ranges: typing.Dict[str, typing.Tuple[int, int]]
|
||||
charm_costs: typing.List[int]
|
||||
cached_filler_items = {}
|
||||
data_version = 2
|
||||
|
||||
def __init__(self, world, player):
|
||||
super(HKWorld, self).__init__(world, player)
|
||||
@@ -406,7 +405,7 @@ class HKWorld(World):
|
||||
continue
|
||||
if setting == CostSanity.option_shopsonly and location.basename not in multi_locations:
|
||||
continue
|
||||
if location.basename in {'Grubfather', 'Seer', 'Eggshop'}:
|
||||
if location.basename in {'Grubfather', 'Seer', 'Egg_Shop'}:
|
||||
our_weights = dict(weights_geoless)
|
||||
else:
|
||||
our_weights = dict(weights)
|
||||
@@ -659,6 +658,8 @@ class HKItem(Item):
|
||||
def __init__(self, name, advancement, code, type: str, player: int = None):
|
||||
if name == "Mimic_Grub":
|
||||
classification = ItemClassification.trap
|
||||
elif name == "Godtuner":
|
||||
classification = ItemClassification.progression
|
||||
elif type in ("Grub", "DreamWarrior", "Root", "Egg", "Dreamer"):
|
||||
classification = ItemClassification.progression_skip_balancing
|
||||
elif type == "Charm" and name not in progression_charms:
|
||||
|
||||
@@ -37,8 +37,6 @@ class Hylics2World(World):
|
||||
options_dataclass = Hylics2Options
|
||||
options: Hylics2Options
|
||||
|
||||
data_version = 3
|
||||
|
||||
|
||||
def set_rules(self):
|
||||
Rules.set_rules(self)
|
||||
|
||||
@@ -330,9 +330,9 @@ class KDL3SNIClient(SNIClient):
|
||||
item = ctx.items_received[recv_amount]
|
||||
recv_amount += 1
|
||||
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
|
||||
color(ctx.item_names[item.item], 'red', 'bold'),
|
||||
color(ctx.item_names.lookup_in_slot(item.item), 'red', 'bold'),
|
||||
color(ctx.player_names[item.player], 'yellow'),
|
||||
ctx.location_names[item.location], recv_amount, len(ctx.items_received)))
|
||||
ctx.location_names.lookup_in_slot(item.location, item.player), recv_amount, len(ctx.items_received)))
|
||||
|
||||
snes_buffered_write(ctx, KDL3_RECV_COUNT, pack("H", recv_amount))
|
||||
item_idx = item.item & 0x00000F
|
||||
@@ -415,7 +415,7 @@ class KDL3SNIClient(SNIClient):
|
||||
|
||||
for new_check_id in new_checks:
|
||||
ctx.locations_checked.add(new_check_id)
|
||||
location = ctx.location_names[new_check_id]
|
||||
location = ctx.location_names.lookup_in_slot(new_check_id)
|
||||
snes_logger.info(
|
||||
f'New Check: {location} ({len(ctx.locations_checked)}/'
|
||||
f'{len(ctx.missing_locations) + len(ctx.checked_locations)})')
|
||||
|
||||
@@ -2,10 +2,14 @@ import random
|
||||
from dataclasses import dataclass
|
||||
|
||||
from Options import DeathLink, Choice, Toggle, OptionDict, Range, PlandoBosses, DefaultOnToggle, \
|
||||
PerGameCommonOptions
|
||||
PerGameCommonOptions, PlandoConnections
|
||||
from .Names import LocationName
|
||||
|
||||
|
||||
class KDL3PlandoConnections(PlandoConnections):
|
||||
entrances = exits = {f"{i} {j}" for i in LocationName.level_names for j in range(1, 7)}
|
||||
|
||||
|
||||
class Goal(Choice):
|
||||
"""
|
||||
Zero: collect the Heart Stars, and defeat Zero in the Hyper Zone.
|
||||
@@ -400,6 +404,7 @@ class Gifting(Toggle):
|
||||
|
||||
@dataclass
|
||||
class KDL3Options(PerGameCommonOptions):
|
||||
plando_connections: KDL3PlandoConnections
|
||||
death_link: DeathLink
|
||||
game_language: GameLanguage
|
||||
goal: Goal
|
||||
|
||||
@@ -129,8 +129,8 @@ def generate_valid_levels(world: "KDL3World", enforce_world: bool, enforce_patte
|
||||
}
|
||||
|
||||
possible_stages = [default_levels[level][stage] for level in default_levels for stage in range(6)]
|
||||
if world.multiworld.plando_connections[world.player]:
|
||||
for connection in world.multiworld.plando_connections[world.player]:
|
||||
if world.options.plando_connections:
|
||||
for connection in world.options.plando_connections:
|
||||
try:
|
||||
entrance_world, entrance_stage = connection.entrance.rsplit(" ", 1)
|
||||
stage_world, stage_stage = connection.exit.rsplit(" ", 1)
|
||||
|
||||
@@ -2,7 +2,7 @@ import typing
|
||||
from argparse import Namespace
|
||||
|
||||
from BaseClasses import MultiWorld, PlandoOptions, CollectionState
|
||||
from test.TestBase import WorldTestBase
|
||||
from test.bases import WorldTestBase
|
||||
from test.general import gen_steps
|
||||
from worlds import AutoWorld
|
||||
from worlds.AutoWorld import call_all
|
||||
@@ -32,6 +32,5 @@ class KDL3TestBase(WorldTestBase):
|
||||
})
|
||||
self.multiworld.set_options(args)
|
||||
self.multiworld.plando_options = PlandoOptions.connections
|
||||
self.multiworld.plando_connections = self.options["plando_connections"] if "plando_connections" in self.options.keys() else []
|
||||
for step in gen_steps:
|
||||
call_all(self.multiworld, step)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from . import KDL3TestBase
|
||||
from worlds.generic import PlandoConnection
|
||||
from Options import PlandoConnection
|
||||
from ..Names import LocationName
|
||||
import typing
|
||||
|
||||
@@ -49,12 +49,10 @@ class TestShiro(KDL3TestBase):
|
||||
options = {
|
||||
"open_world": False,
|
||||
"plando_connections": [
|
||||
[],
|
||||
[
|
||||
PlandoConnection("Grass Land 1", "Iceberg 5", "both"),
|
||||
PlandoConnection("Grass Land 2", "Ripple Field 5", "both"),
|
||||
PlandoConnection("Grass Land 3", "Grass Land 1", "both")
|
||||
]],
|
||||
],
|
||||
"stage_shuffle": "shuffled",
|
||||
"plando_options": "connections"
|
||||
}
|
||||
|
||||
@@ -78,11 +78,6 @@ class LinksAwakeningWorld(World):
|
||||
settings: typing.ClassVar[LinksAwakeningSettings]
|
||||
topology_present = True # show path to required location checks in spoiler
|
||||
|
||||
# data_version is used to signal that items, locations or their names
|
||||
# changed. Set this to 0 during development so other games' clients do not
|
||||
# cache any texts, then increase by 1 for each release that makes changes.
|
||||
data_version = 1
|
||||
|
||||
# ID of first item and location, could be hard-coded but code may be easier
|
||||
# to read with this as a propery.
|
||||
base_id = BASE_ID
|
||||
|
||||
@@ -30,6 +30,9 @@ def generate_lithograph_hint(world: "LandstalkerWorld"):
|
||||
jewel_items = world.jewel_items
|
||||
|
||||
for item in jewel_items:
|
||||
if item.location is None:
|
||||
continue
|
||||
|
||||
# Jewel hints are composed of 4 'words' shuffled randomly:
|
||||
# - the name of the player whose world contains said jewel (if not ours)
|
||||
# - the color of the jewel (if relevant)
|
||||
@@ -61,7 +64,7 @@ def generate_random_hints(world: "LandstalkerWorld"):
|
||||
excluded_items = ["Life Stock", "EkeEke"]
|
||||
|
||||
progression_items = [item for item in multiworld.itempool if item.advancement and
|
||||
item.name not in excluded_items]
|
||||
item.name not in excluded_items and item.location is not None]
|
||||
|
||||
local_own_progression_items = [item for item in progression_items if item.player == this_player
|
||||
and item.location.player == this_player]
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from typing import Dict, Optional
|
||||
|
||||
from BaseClasses import Location
|
||||
from BaseClasses import Location, ItemClassification, Item
|
||||
from .Regions import LandstalkerRegion
|
||||
from .data.item_source import ITEM_SOURCES_JSON
|
||||
from .data.world_path import WORLD_PATHS_JSON
|
||||
|
||||
BASE_LOCATION_ID = 4000
|
||||
BASE_GROUND_LOCATION_ID = BASE_LOCATION_ID + 256
|
||||
@@ -28,6 +29,18 @@ def create_locations(player: int, regions_table: Dict[str, LandstalkerRegion], n
|
||||
new_location = LandstalkerLocation(player, data["name"], name_to_id_table[data["name"]], region, data["type"])
|
||||
region.locations.append(new_location)
|
||||
|
||||
# Create fake event locations that will be used to determine if some key regions has been visited
|
||||
regions_with_entrance_checks = []
|
||||
for data in WORLD_PATHS_JSON:
|
||||
if "requiredNodes" in data:
|
||||
regions_with_entrance_checks.extend([region_id for region_id in data["requiredNodes"]])
|
||||
regions_with_entrance_checks = list(set(regions_with_entrance_checks))
|
||||
for region_id in regions_with_entrance_checks:
|
||||
region = regions_table[region_id]
|
||||
location = LandstalkerLocation(player, 'event_visited_' + region_id, None, region, "event")
|
||||
location.place_locked_item(Item("event_visited_" + region_id, ItemClassification.progression, None, player))
|
||||
region.locations.append(location)
|
||||
|
||||
# Create a specific end location that will contain a fake win-condition item
|
||||
end_location = LandstalkerLocation(player, "End", None, regions_table["end"], "reward")
|
||||
regions_table["end"].locations.append(end_location)
|
||||
|
||||
@@ -37,7 +37,7 @@ def create_regions(world: "LandstalkerWorld"):
|
||||
for code, region_data in WORLD_NODES_JSON.items():
|
||||
random_hint_name = None
|
||||
if "hints" in region_data:
|
||||
random_hint_name = multiworld.random.choice(region_data["hints"])
|
||||
random_hint_name = world.random.choice(region_data["hints"])
|
||||
region = LandstalkerRegion(code, region_data["name"], player, multiworld, random_hint_name)
|
||||
regions_table[code] = region
|
||||
multiworld.regions.append(region)
|
||||
|
||||
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
def _landstalker_has_visited_regions(state: CollectionState, player: int, regions):
|
||||
return all([state.can_reach(region, None, player) for region in regions])
|
||||
return all(state.has("event_visited_" + region.code, player) for region in regions)
|
||||
|
||||
|
||||
def _landstalker_has_health(state: CollectionState, player: int, health):
|
||||
|
||||
@@ -204,6 +204,9 @@ class LandstalkerWorld(World):
|
||||
for location in self.multiworld.get_locations(self.player):
|
||||
if location.parent_region.name in excluded_regions:
|
||||
location.progress_type = LocationProgressType.EXCLUDED
|
||||
# We need to make that event non-progression since it would crash generation in reach_kazalt goal
|
||||
if location.item is not None and location.item.name == "event_visited_king_nole_labyrinth_raft_entrance":
|
||||
location.item.classification = ItemClassification.filler
|
||||
|
||||
def get_starting_health(self):
|
||||
spawn_id = self.options.spawn_region.current_key
|
||||
|
||||
@@ -9,12 +9,13 @@ from worlds.AutoWorld import WebWorld, World
|
||||
from .datatypes import Room, RoomEntrance
|
||||
from .items import ALL_ITEM_TABLE, ITEMS_BY_GROUP, TRAP_ITEMS, LingoItem
|
||||
from .locations import ALL_LOCATION_TABLE, LOCATIONS_BY_GROUP
|
||||
from .options import LingoOptions
|
||||
from .options import LingoOptions, lingo_option_groups
|
||||
from .player_logic import LingoPlayerLogic
|
||||
from .regions import create_regions
|
||||
|
||||
|
||||
class LingoWebWorld(WebWorld):
|
||||
option_groups = lingo_option_groups
|
||||
theme = "grass"
|
||||
tutorials = [Tutorial(
|
||||
"Multiworld Setup Guide",
|
||||
@@ -36,7 +37,6 @@ class LingoWorld(World):
|
||||
|
||||
base_id = 444400
|
||||
topology_present = True
|
||||
data_version = 1
|
||||
|
||||
options_dataclass = LingoOptions
|
||||
options: LingoOptions
|
||||
|
||||
@@ -2052,6 +2052,7 @@
|
||||
door: Rhyme Room Entrance
|
||||
Art Gallery:
|
||||
warp: True
|
||||
Roof: True # by parkouring through the Bearer shortcut
|
||||
panels:
|
||||
RED:
|
||||
id: Color Arrow Room/Panel_red_afar
|
||||
@@ -2333,6 +2334,7 @@
|
||||
# This is the MASTERY on the other side of THE FEARLESS. It can only be
|
||||
# accessed by jumping from the top of the tower.
|
||||
id: Master Room/Panel_mastery_mastery8
|
||||
location_name: The Fearless - MASTERY
|
||||
tag: midwhite
|
||||
hunt: True
|
||||
required_door:
|
||||
@@ -4098,6 +4100,7 @@
|
||||
Number Hunt:
|
||||
room: Number Hunt
|
||||
door: Door to Directional Gallery
|
||||
Roof: True # through ceiling of sunwarp
|
||||
panels:
|
||||
PEPPER:
|
||||
id: Backside Room/Panel_pepper_salt
|
||||
@@ -5390,6 +5393,7 @@
|
||||
- The Artistic (Apple)
|
||||
- The Artistic (Lattice)
|
||||
check: True
|
||||
location_name: The Artistic - Achievement
|
||||
achievement: The Artistic
|
||||
FINE:
|
||||
id: Ceiling Room/Panel_yellow_top_5
|
||||
@@ -6046,7 +6050,7 @@
|
||||
paintings:
|
||||
- id: symmetry_painting_a_5
|
||||
orientation: east
|
||||
- id: symmetry_painting_a_5
|
||||
- id: symmetry_painting_b_5
|
||||
disable: True
|
||||
The Wondrous (Window):
|
||||
entrances:
|
||||
@@ -6814,9 +6818,6 @@
|
||||
tag: syn rhyme
|
||||
subtag: bot
|
||||
link: rhyme FALL
|
||||
LEAP:
|
||||
id: Double Room/Panel_leap_leap
|
||||
tag: midwhite
|
||||
doors:
|
||||
Exit:
|
||||
id: Double Room Area Doors/Door_room_exit
|
||||
@@ -7065,6 +7066,9 @@
|
||||
tag: syn rhyme
|
||||
subtag: bot
|
||||
link: rhyme CREATIVE
|
||||
LEAP:
|
||||
id: Double Room/Panel_leap_leap
|
||||
tag: midwhite
|
||||
doors:
|
||||
Door to Cross:
|
||||
id: Double Room Area Doors/Door_room_4a
|
||||
@@ -7272,6 +7276,7 @@
|
||||
MASTERY:
|
||||
id: Master Room/Panel_mastery_mastery
|
||||
tag: midwhite
|
||||
hunt: True
|
||||
required_door:
|
||||
room: Orange Tower Seventh Floor
|
||||
door: Mastery
|
||||
|
||||
Binary file not shown.
@@ -766,7 +766,6 @@ panels:
|
||||
BOUNCE: 445010
|
||||
SCRAWL: 445011
|
||||
PLUNGE: 445012
|
||||
LEAP: 445013
|
||||
Rhyme Room (Circle):
|
||||
BIRD: 445014
|
||||
LETTER: 445015
|
||||
@@ -790,6 +789,7 @@ panels:
|
||||
GEM: 445031
|
||||
INNOVATIVE (Top): 445032
|
||||
INNOVATIVE (Bottom): 445033
|
||||
LEAP: 445013
|
||||
Room Room:
|
||||
DOOR (1): 445034
|
||||
DOOR (2): 445035
|
||||
|
||||
@@ -63,6 +63,7 @@ class Panel(NamedTuple):
|
||||
exclude_reduce: bool
|
||||
achievement: bool
|
||||
non_counting: bool
|
||||
location_name: Optional[str]
|
||||
|
||||
|
||||
class Painting(NamedTuple):
|
||||
|
||||
@@ -39,7 +39,7 @@ def load_location_data():
|
||||
|
||||
for room_name, panels in PANELS_BY_ROOM.items():
|
||||
for panel_name, panel in panels.items():
|
||||
location_name = f"{room_name} - {panel_name}"
|
||||
location_name = f"{room_name} - {panel_name}" if panel.location_name is None else panel.location_name
|
||||
|
||||
classification = LocationClassification.insanity
|
||||
if panel.check:
|
||||
|
||||
@@ -2,7 +2,8 @@ from dataclasses import dataclass
|
||||
|
||||
from schema import And, Schema
|
||||
|
||||
from Options import Toggle, Choice, DefaultOnToggle, Range, PerGameCommonOptions, StartInventoryPool, OptionDict
|
||||
from Options import Toggle, Choice, DefaultOnToggle, Range, PerGameCommonOptions, StartInventoryPool, OptionDict, \
|
||||
OptionGroup
|
||||
from .items import TRAP_ITEMS
|
||||
|
||||
|
||||
@@ -32,8 +33,8 @@ class ProgressiveColorful(DefaultOnToggle):
|
||||
|
||||
|
||||
class LocationChecks(Choice):
|
||||
"""On "normal", there will be a location check for each panel set that would ordinarily open a door, as well as for
|
||||
achievement panels and a small handful of other panels.
|
||||
"""Determines what locations are available.
|
||||
On "normal", there will be a location check for each panel set that would ordinarily open a door, as well as for achievement panels and a small handful of other panels.
|
||||
On "reduced", many of the locations that are associated with opening doors are removed.
|
||||
On "insanity", every individual panel in the game is a location check."""
|
||||
display_name = "Location Checks"
|
||||
@@ -43,8 +44,10 @@ class LocationChecks(Choice):
|
||||
|
||||
|
||||
class ShuffleColors(DefaultOnToggle):
|
||||
"""If on, an item is added to the pool for every puzzle color (besides White).
|
||||
You will need to unlock the requisite colors in order to be able to solve puzzles of that color."""
|
||||
"""
|
||||
If on, an item is added to the pool for every puzzle color (besides White).
|
||||
You will need to unlock the requisite colors in order to be able to solve puzzles of that color.
|
||||
"""
|
||||
display_name = "Shuffle Colors"
|
||||
|
||||
|
||||
@@ -62,20 +65,25 @@ class ShufflePaintings(Toggle):
|
||||
|
||||
|
||||
class EnablePilgrimage(Toggle):
|
||||
"""If on, you are required to complete a pilgrimage in order to access the Pilgrim Antechamber.
|
||||
"""Determines how the pilgrimage works.
|
||||
If on, you are required to complete a pilgrimage in order to access the Pilgrim Antechamber.
|
||||
If off, the pilgrimage will be deactivated, and the sun painting will be added to the pool, even if door shuffle is off."""
|
||||
display_name = "Enable Pilgrimage"
|
||||
|
||||
|
||||
class PilgrimageAllowsRoofAccess(DefaultOnToggle):
|
||||
"""If on, you may use the Crossroads roof access during a pilgrimage (and you may be expected to do so).
|
||||
Otherwise, pilgrimage will be deactivated when going up the stairs."""
|
||||
"""
|
||||
If on, you may use the Crossroads roof access during a pilgrimage (and you may be expected to do so).
|
||||
Otherwise, pilgrimage will be deactivated when going up the stairs.
|
||||
"""
|
||||
display_name = "Allow Roof Access for Pilgrimage"
|
||||
|
||||
|
||||
class PilgrimageAllowsPaintings(DefaultOnToggle):
|
||||
"""If on, you may use paintings during a pilgrimage (and you may be expected to do so).
|
||||
Otherwise, pilgrimage will be deactivated when going through a painting."""
|
||||
"""
|
||||
If on, you may use paintings during a pilgrimage (and you may be expected to do so).
|
||||
Otherwise, pilgrimage will be deactivated when going through a painting.
|
||||
"""
|
||||
display_name = "Allow Paintings for Pilgrimage"
|
||||
|
||||
|
||||
@@ -137,8 +145,10 @@ class Level2Requirement(Range):
|
||||
|
||||
|
||||
class EarlyColorHallways(Toggle):
|
||||
"""When on, a painting warp to the color hallways area will appear in the starting room.
|
||||
This lets you avoid being trapped in the starting room for long periods of time when door shuffle is on."""
|
||||
"""
|
||||
When on, a painting warp to the color hallways area will appear in the starting room.
|
||||
This lets you avoid being trapped in the starting room for long periods of time when door shuffle is on.
|
||||
"""
|
||||
display_name = "Early Color Hallways"
|
||||
|
||||
|
||||
@@ -151,8 +161,10 @@ class TrapPercentage(Range):
|
||||
|
||||
|
||||
class TrapWeights(OptionDict):
|
||||
"""Specify the distribution of traps that should be placed into the pool.
|
||||
If you don't want a specific type of trap, set the weight to zero."""
|
||||
"""
|
||||
Specify the distribution of traps that should be placed into the pool.
|
||||
If you don't want a specific type of trap, set the weight to zero.
|
||||
"""
|
||||
display_name = "Trap Weights"
|
||||
schema = Schema({trap_name: And(int, lambda n: n >= 0) for trap_name in TRAP_ITEMS})
|
||||
default = {trap_name: 1 for trap_name in TRAP_ITEMS}
|
||||
@@ -171,6 +183,26 @@ class DeathLink(Toggle):
|
||||
display_name = "Death Link"
|
||||
|
||||
|
||||
lingo_option_groups = [
|
||||
OptionGroup("Pilgrimage", [
|
||||
EnablePilgrimage,
|
||||
PilgrimageAllowsRoofAccess,
|
||||
PilgrimageAllowsPaintings,
|
||||
SunwarpAccess,
|
||||
ShuffleSunwarps,
|
||||
]),
|
||||
OptionGroup("Fine-tuning", [
|
||||
ProgressiveOrangeTower,
|
||||
ProgressiveColorful,
|
||||
MasteryAchievements,
|
||||
Level2Requirement,
|
||||
TrapPercentage,
|
||||
TrapWeights,
|
||||
PuzzleSkipPercentage,
|
||||
])
|
||||
]
|
||||
|
||||
|
||||
@dataclass
|
||||
class LingoOptions(PerGameCommonOptions):
|
||||
shuffle_doors: ShuffleDoors
|
||||
|
||||
@@ -18,19 +18,23 @@ class AccessRequirements:
|
||||
rooms: Set[str]
|
||||
doors: Set[RoomAndDoor]
|
||||
colors: Set[str]
|
||||
the_master: bool
|
||||
|
||||
def __init__(self):
|
||||
self.rooms = set()
|
||||
self.doors = set()
|
||||
self.colors = set()
|
||||
self.the_master = False
|
||||
|
||||
def merge(self, other: "AccessRequirements"):
|
||||
self.rooms |= other.rooms
|
||||
self.doors |= other.doors
|
||||
self.colors |= other.colors
|
||||
self.the_master |= other.the_master
|
||||
|
||||
def __str__(self):
|
||||
return f"AccessRequirements(rooms={self.rooms}, doors={self.doors}, colors={self.colors})"
|
||||
return f"AccessRequirements(rooms={self.rooms}, doors={self.doors}, colors={self.colors})," \
|
||||
f" the_master={self.the_master}"
|
||||
|
||||
|
||||
class PlayerLocation(NamedTuple):
|
||||
@@ -463,6 +467,9 @@ class LingoPlayerLogic:
|
||||
req_panel.panel, world)
|
||||
access_reqs.merge(sub_access_reqs)
|
||||
|
||||
if panel == "THE MASTER":
|
||||
access_reqs.the_master = True
|
||||
|
||||
self.panel_reqs[room][panel] = access_reqs
|
||||
|
||||
return self.panel_reqs[room][panel]
|
||||
@@ -502,15 +509,17 @@ class LingoPlayerLogic:
|
||||
unhindered_panels_by_color: dict[Optional[str], int] = {}
|
||||
|
||||
for panel_name, panel_data in room_data.items():
|
||||
# We won't count non-counting panels. THE MASTER has special access rules and is handled separately.
|
||||
if panel_data.non_counting or panel_name == "THE MASTER":
|
||||
# We won't count non-counting panels.
|
||||
if panel_data.non_counting:
|
||||
continue
|
||||
|
||||
# We won't coalesce any panels that have requirements beyond colors. To simplify things for now, we will
|
||||
# only coalesce single-color panels. Chains/stacks/combo puzzles will be separate.
|
||||
# only coalesce single-color panels. Chains/stacks/combo puzzles will be separate. THE MASTER has
|
||||
# special access rules and is handled separately.
|
||||
if len(panel_data.required_panels) > 0 or len(panel_data.required_doors) > 0\
|
||||
or len(panel_data.required_rooms) > 0\
|
||||
or (world.options.shuffle_colors and len(panel_data.colors) > 1):
|
||||
or (world.options.shuffle_colors and len(panel_data.colors) > 1)\
|
||||
or panel_name == "THE MASTER":
|
||||
self.counting_panel_reqs.setdefault(room_name, []).append(
|
||||
(self.calculate_panel_requirements(room_name, panel_name, world), 1))
|
||||
else:
|
||||
|
||||
@@ -49,8 +49,15 @@ def connect_entrance(regions: Dict[str, Region], source_region: Region, target_r
|
||||
if door is not None:
|
||||
effective_room = target_region.name if door.room is None else door.room
|
||||
if door.door not in world.player_logic.item_by_door.get(effective_room, {}):
|
||||
for region in world.player_logic.calculate_door_requirements(effective_room, door.door, world).rooms:
|
||||
access_reqs = world.player_logic.calculate_door_requirements(effective_room, door.door, world)
|
||||
for region in access_reqs.rooms:
|
||||
world.multiworld.register_indirect_condition(regions[region], connection)
|
||||
|
||||
# This pretty much only applies to Orange Tower Sixth Floor -> Orange Tower Basement.
|
||||
if access_reqs.the_master:
|
||||
for mastery_req in world.player_logic.mastery_reqs:
|
||||
for region in mastery_req.rooms:
|
||||
world.multiworld.register_indirect_condition(regions[region], connection)
|
||||
|
||||
if not pilgrimage and world.options.enable_pilgrimage and is_acceptable_pilgrimage_entrance(entrance_type, world)\
|
||||
and source_region.name != "Menu":
|
||||
|
||||
@@ -42,12 +42,6 @@ def lingo_can_use_level_2_location(state: CollectionState, world: "LingoWorld"):
|
||||
counted_panels += panel_count
|
||||
if counted_panels >= world.options.level_2_requirement.value - 1:
|
||||
return True
|
||||
# THE MASTER has to be handled separately, because it has special access rules.
|
||||
if state.can_reach("Orange Tower Seventh Floor", "Region", world.player)\
|
||||
and lingo_can_use_mastery_location(state, world):
|
||||
counted_panels += 1
|
||||
if counted_panels >= world.options.level_2_requirement.value - 1:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -65,6 +59,9 @@ def _lingo_can_satisfy_requirements(state: CollectionState, access: AccessRequir
|
||||
if not state.has(color.capitalize(), world.player):
|
||||
return False
|
||||
|
||||
if access.the_master and not lingo_can_use_mastery_location(state, world):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -36,4 +36,21 @@ class TestMasteryWhenVictoryIsTheMaster(LingoTestBase):
|
||||
self.assertFalse(self.can_reach_location("Orange Tower Seventh Floor - Mastery Achievements"))
|
||||
|
||||
self.collect_by_name(["Green", "Gray", "Brown", "Yellow"])
|
||||
self.assertTrue(self.can_reach_location("Orange Tower Seventh Floor - Mastery Achievements"))
|
||||
self.assertTrue(self.can_reach_location("Orange Tower Seventh Floor - Mastery Achievements"))
|
||||
|
||||
|
||||
class TestMasteryBlocksDependents(LingoTestBase):
|
||||
options = {
|
||||
"mastery_achievements": "24",
|
||||
"shuffle_colors": "true",
|
||||
"location_checks": "insanity"
|
||||
}
|
||||
|
||||
def test_requirement(self):
|
||||
self.collect_all_but("Gray")
|
||||
self.assertFalse(self.can_reach_location("Orange Tower Basement - THE LIBRARY"))
|
||||
self.assertFalse(self.can_reach_location("The Fearless - MASTERY"))
|
||||
|
||||
self.collect_by_name("Gray")
|
||||
self.assertTrue(self.can_reach_location("Orange Tower Basement - THE LIBRARY"))
|
||||
self.assertTrue(self.can_reach_location("The Fearless - MASTERY"))
|
||||
|
||||
@@ -150,8 +150,6 @@ def process_entrance(source_room, doors, room_obj):
|
||||
def process_panel(room_name, panel_name, panel_data):
|
||||
global PANELS_BY_ROOM
|
||||
|
||||
full_name = f"{room_name} - {panel_name}"
|
||||
|
||||
# required_room can either be a single room or a list of rooms.
|
||||
if "required_room" in panel_data:
|
||||
if isinstance(panel_data["required_room"], list):
|
||||
@@ -229,8 +227,13 @@ def process_panel(room_name, panel_name, panel_data):
|
||||
else:
|
||||
non_counting = False
|
||||
|
||||
if "location_name" in panel_data:
|
||||
location_name = panel_data["location_name"]
|
||||
else:
|
||||
location_name = None
|
||||
|
||||
panel_obj = Panel(required_rooms, required_doors, required_panels, colors, check, event, exclude_reduce,
|
||||
achievement, non_counting)
|
||||
achievement, non_counting, location_name)
|
||||
PANELS_BY_ROOM[room_name][panel_name] = panel_obj
|
||||
|
||||
|
||||
|
||||
@@ -39,11 +39,12 @@ mentioned_doors = Set[]
|
||||
mentioned_panels = Set[]
|
||||
mentioned_sunwarp_entrances = Set[]
|
||||
mentioned_sunwarp_exits = Set[]
|
||||
mentioned_paintings = Set[]
|
||||
|
||||
door_groups = {}
|
||||
|
||||
directives = Set["entrances", "panels", "doors", "paintings", "sunwarps", "progression"]
|
||||
panel_directives = Set["id", "required_room", "required_door", "required_panel", "colors", "check", "exclude_reduce", "tag", "link", "subtag", "achievement", "copy_to_sign", "non_counting", "hunt"]
|
||||
panel_directives = Set["id", "required_room", "required_door", "required_panel", "colors", "check", "exclude_reduce", "tag", "link", "subtag", "achievement", "copy_to_sign", "non_counting", "hunt", "location_name"]
|
||||
door_directives = Set["id", "painting_id", "panels", "item_name", "item_group", "location_name", "skip_location", "skip_item", "door_group", "include_reduce", "event", "warp_id"]
|
||||
painting_directives = Set["id", "enter_only", "exit_only", "orientation", "required_door", "required", "required_when_no_doors", "move", "req_blocked", "req_blocked_when_no_doors"]
|
||||
|
||||
@@ -257,6 +258,12 @@ config.each do |room_name, room|
|
||||
unless paintings.include? painting["id"] then
|
||||
puts "#{room_name} :::: Invalid Painting ID #{painting["id"]}"
|
||||
end
|
||||
|
||||
if mentioned_paintings.include?(painting["id"]) then
|
||||
puts "Painting #{painting["id"]} is mentioned more than once"
|
||||
else
|
||||
mentioned_paintings.add(painting["id"])
|
||||
end
|
||||
else
|
||||
puts "#{room_name} :::: Painting is missing an ID"
|
||||
end
|
||||
|
||||
@@ -147,9 +147,9 @@ class L2ACSNIClient(SNIClient):
|
||||
snes_items_received += 1
|
||||
|
||||
snes_logger.info("Received %s from %s (%s) (%d/%d in list)" % (
|
||||
ctx.item_names[item.item],
|
||||
ctx.item_names.lookup_in_slot(item.item),
|
||||
ctx.player_names[item.player],
|
||||
ctx.location_names[item.location],
|
||||
ctx.location_names.lookup_in_slot(item.location, item.player),
|
||||
snes_items_received, len(ctx.items_received)))
|
||||
snes_buffered_write(ctx, L2AC_RX_ADDR + 2 * (snes_items_received + 1), item_code.to_bytes(2, "little"))
|
||||
snes_buffered_write(ctx, L2AC_RX_ADDR, snes_items_received.to_bytes(2, "little"))
|
||||
|
||||
@@ -65,7 +65,6 @@ class L2ACWorld(World):
|
||||
"Iris treasures": {name for name, data in l2ac_item_table.items() if data.type is ItemType.IRIS_TREASURE},
|
||||
"Party members": {name for name, data in l2ac_item_table.items() if data.type is ItemType.PARTY_MEMBER},
|
||||
}
|
||||
data_version: ClassVar[int] = 2
|
||||
required_client_version: Tuple[int, int, int] = (0, 4, 4)
|
||||
|
||||
# L2ACWorld specific properties
|
||||
|
||||
@@ -44,8 +44,6 @@ class MeritousWorld(World):
|
||||
location_name_to_id = location_table
|
||||
item_name_groups = item_groups
|
||||
|
||||
data_version = 2
|
||||
|
||||
# NOTE: Remember to change this before this game goes live
|
||||
required_client_version = (0, 2, 4)
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@ from typing import Dict
|
||||
|
||||
from schema import And, Optional, Or, Schema
|
||||
|
||||
from Options import Accessibility, Choice, DeathLinkMixin, DefaultOnToggle, OptionDict, PerGameCommonOptions, Range, \
|
||||
StartInventoryPool, Toggle
|
||||
from Options import Accessibility, Choice, DeathLinkMixin, DefaultOnToggle, OptionDict, PerGameCommonOptions, \
|
||||
PlandoConnections, Range, StartInventoryPool, Toggle, Visibility
|
||||
from worlds.messenger.portals import CHECKPOINTS, PORTALS, SHOP_POINTS
|
||||
|
||||
|
||||
class MessengerAccessibility(Accessibility):
|
||||
@@ -13,6 +14,36 @@ class MessengerAccessibility(Accessibility):
|
||||
__doc__ = Accessibility.__doc__.replace(f"default {Accessibility.default}", f"default {default}")
|
||||
|
||||
|
||||
class PortalPlando(PlandoConnections):
|
||||
"""
|
||||
Plando connections to be used with portal shuffle. Direction is ignored.
|
||||
List of valid connections can be found here: https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/messenger/portals.py#L12.
|
||||
The entering Portal should *not* have "Portal" appended.
|
||||
For the exits, those in checkpoints and shops should just be the name of the spot, while portals should have " Portal" at the end.
|
||||
Example:
|
||||
- entrance: Riviere Turquoise
|
||||
exit: Wingsuit
|
||||
- entrance: Sunken Shrine
|
||||
exit: Sunny Day
|
||||
- entrance: Searing Crags
|
||||
exit: Glacial Peak Portal
|
||||
"""
|
||||
portals = [f"{portal} Portal" for portal in PORTALS]
|
||||
shop_points = [point for points in SHOP_POINTS.values() for point in points]
|
||||
checkpoints = [point for points in CHECKPOINTS.values() for point in points]
|
||||
portal_entrances = PORTALS
|
||||
portal_exits = portals + shop_points + checkpoints
|
||||
entrances = portal_entrances
|
||||
exits = portal_exits
|
||||
|
||||
|
||||
# for back compatibility. To later be replaced with transition plando
|
||||
class HiddenPortalPlando(PortalPlando):
|
||||
visibility = Visibility.none
|
||||
entrances = PortalPlando.entrances
|
||||
exits = PortalPlando.exits
|
||||
|
||||
|
||||
class Logic(Choice):
|
||||
"""
|
||||
The level of logic to use when determining what locations in your world are accessible.
|
||||
@@ -205,3 +236,5 @@ class MessengerOptions(DeathLinkMixin, PerGameCommonOptions):
|
||||
traps: Traps
|
||||
shop_price: ShopPrices
|
||||
shop_price_plan: PlannedShopPrices
|
||||
portal_plando: PortalPlando
|
||||
plando_connections: HiddenPortalPlando
|
||||
|
||||
@@ -2,8 +2,7 @@ from copy import deepcopy
|
||||
from typing import List, TYPE_CHECKING
|
||||
|
||||
from BaseClasses import CollectionState, PlandoOptions
|
||||
from worlds.generic import PlandoConnection
|
||||
from .options import ShufflePortals
|
||||
from Options import PlandoConnection
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import MessengerWorld
|
||||
@@ -207,6 +206,8 @@ REGION_ORDER = [
|
||||
|
||||
def shuffle_portals(world: "MessengerWorld") -> None:
|
||||
"""shuffles the output of the portals from the main hub"""
|
||||
from .options import ShufflePortals
|
||||
|
||||
def create_mapping(in_portal: str, warp: str) -> str:
|
||||
"""assigns the chosen output to the input"""
|
||||
parent = out_to_parent[warp]
|
||||
@@ -247,7 +248,9 @@ def shuffle_portals(world: "MessengerWorld") -> None:
|
||||
available_portals = [val for zone in shop_points.values() for val in zone]
|
||||
world.random.shuffle(available_portals)
|
||||
|
||||
plando = world.multiworld.plando_connections[world.player]
|
||||
plando = world.options.portal_plando.value
|
||||
if not plando:
|
||||
plando = world.options.plando_connections.value
|
||||
if plando and world.multiworld.plando_options & PlandoOptions.connections:
|
||||
handle_planned_portals(plando)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user