mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-08-16 06:56:36 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7c4fcb4c6 | ||
|
|
bcd3f9a74c | ||
|
|
6262235161 | ||
|
|
030cb4b578 | ||
|
|
36bab6f52a | ||
|
|
e0cfef3407 | ||
|
|
bb2a775c05 | ||
|
|
427b147818 | ||
|
|
3f3c343fb3 | ||
|
|
debe4cf035 | ||
|
|
68f25f4642 | ||
|
|
3c4af8f432 |
@@ -24,7 +24,6 @@ Currently, the following games are supported:
|
|||||||
* The Witness
|
* The Witness
|
||||||
* Sonic Adventure 2: Battle
|
* Sonic Adventure 2: Battle
|
||||||
* Starcraft 2
|
* Starcraft 2
|
||||||
* Donkey Kong Country 3
|
|
||||||
* Dark Souls 3
|
* Dark Souls 3
|
||||||
* Super Mario World
|
* Super Mario World
|
||||||
* Pokémon Red and Blue
|
* Pokémon Red and Blue
|
||||||
|
|||||||
+2
-1
@@ -110,13 +110,14 @@ if __name__ == "__main__":
|
|||||||
logging.exception(e)
|
logging.exception(e)
|
||||||
logging.warning("Could not update LttP sprites.")
|
logging.warning("Could not update LttP sprites.")
|
||||||
app = get_app()
|
app = get_app()
|
||||||
from worlds import AutoWorldRegister
|
from worlds import AutoWorldRegister, network_data_package
|
||||||
# Update to only valid WebHost worlds
|
# Update to only valid WebHost worlds
|
||||||
invalid_worlds = {name for name, world in AutoWorldRegister.world_types.items()
|
invalid_worlds = {name for name, world in AutoWorldRegister.world_types.items()
|
||||||
if not hasattr(world.web, "tutorials")}
|
if not hasattr(world.web, "tutorials")}
|
||||||
if invalid_worlds:
|
if invalid_worlds:
|
||||||
logging.error(f"Following worlds not loaded as they are invalid for WebHost: {invalid_worlds}")
|
logging.error(f"Following worlds not loaded as they are invalid for WebHost: {invalid_worlds}")
|
||||||
AutoWorldRegister.world_types = {k: v for k, v in AutoWorldRegister.world_types.items() if k not in invalid_worlds}
|
AutoWorldRegister.world_types = {k: v for k, v in AutoWorldRegister.world_types.items() if k not in invalid_worlds}
|
||||||
|
network_data_package["games"] = {k: v for k, v in network_data_package["games"].items() if k not in invalid_worlds}
|
||||||
create_options_files()
|
create_options_files()
|
||||||
copy_tutorials_files_to_static()
|
copy_tutorials_files_to_static()
|
||||||
if app.config["SELFLAUNCH"]:
|
if app.config["SELFLAUNCH"]:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% block footer %}
|
{% block footer %}
|
||||||
<footer id="island-footer">
|
<footer id="island-footer">
|
||||||
<div id="copyright-notice">Copyright 2025 Archipelago</div>
|
<div id="copyright-notice">Copyright 2026 Archipelago</div>
|
||||||
<div id="links">
|
<div id="links">
|
||||||
<a href="/sitemap">Site Map</a>
|
<a href="/sitemap">Site Map</a>
|
||||||
-
|
-
|
||||||
|
|||||||
@@ -56,9 +56,6 @@
|
|||||||
# Dark Souls III
|
# Dark Souls III
|
||||||
/worlds/dark_souls_3/ @Marechal-L @nex3
|
/worlds/dark_souls_3/ @Marechal-L @nex3
|
||||||
|
|
||||||
# Donkey Kong Country 3
|
|
||||||
/worlds/dkc3/ @PoryGone
|
|
||||||
|
|
||||||
# DLCQuest
|
# DLCQuest
|
||||||
/worlds/dlcquest/ @axe-y @agilbert1412
|
/worlds/dlcquest/ @axe-y @agilbert1412
|
||||||
|
|
||||||
|
|||||||
@@ -69,12 +69,6 @@ flowchart LR
|
|||||||
end
|
end
|
||||||
SNI <-- Various, depending on SNES device --> SMZ
|
SNI <-- Various, depending on SNES device --> SMZ
|
||||||
|
|
||||||
%% Donkey Kong Country 3
|
|
||||||
subgraph Donkey Kong Country 3
|
|
||||||
DK3[SNES]
|
|
||||||
end
|
|
||||||
SNI <-- Various, depending on SNES device --> DK3
|
|
||||||
|
|
||||||
%% Super Mario World
|
%% Super Mario World
|
||||||
subgraph Super Mario World
|
subgraph Super Mario World
|
||||||
SMW[SNES]
|
SMW[SNES]
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ Example:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
...
|
...
|
||||||
"Donkey Kong Country 3":"f90acedcd958213f483a6a4c238e2a3faf92165e",
|
|
||||||
"Factorio":"a699194a9589db3ebc0d821915864b422c782f44",
|
"Factorio":"a699194a9589db3ebc0d821915864b422c782f44",
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,11 +98,6 @@ Root: HKCR; Subkey: "{#MyAppName}smpatch"; ValueData: "Arc
|
|||||||
Root: HKCR; Subkey: "{#MyAppName}smpatch\DefaultIcon"; ValueData: "{app}\ArchipelagoSNIClient.exe,0"; ValueType: string; ValueName: "";
|
Root: HKCR; Subkey: "{#MyAppName}smpatch\DefaultIcon"; ValueData: "{app}\ArchipelagoSNIClient.exe,0"; ValueType: string; ValueName: "";
|
||||||
Root: HKCR; Subkey: "{#MyAppName}smpatch\shell\open\command"; ValueData: """{app}\ArchipelagoSNIClient.exe"" ""%1"""; ValueType: string; ValueName: "";
|
Root: HKCR; Subkey: "{#MyAppName}smpatch\shell\open\command"; ValueData: """{app}\ArchipelagoSNIClient.exe"" ""%1"""; ValueType: string; ValueName: "";
|
||||||
|
|
||||||
Root: HKCR; Subkey: ".apdkc3"; ValueData: "{#MyAppName}dkc3patch"; Flags: uninsdeletevalue; ValueType: string; ValueName: "";
|
|
||||||
Root: HKCR; Subkey: "{#MyAppName}dkc3patch"; ValueData: "Archipelago Donkey Kong Country 3 Patch"; Flags: uninsdeletekey; ValueType: string; ValueName: "";
|
|
||||||
Root: HKCR; Subkey: "{#MyAppName}dkc3patch\DefaultIcon"; ValueData: "{app}\ArchipelagoSNIClient.exe,0"; ValueType: string; ValueName: "";
|
|
||||||
Root: HKCR; Subkey: "{#MyAppName}dkc3patch\shell\open\command"; ValueData: """{app}\ArchipelagoSNIClient.exe"" ""%1"""; ValueType: string; ValueName: "";
|
|
||||||
|
|
||||||
Root: HKCR; Subkey: ".apsmw"; ValueData: "{#MyAppName}smwpatch"; Flags: uninsdeletevalue; ValueType: string; ValueName: "";
|
Root: HKCR; Subkey: ".apsmw"; ValueData: "{#MyAppName}smwpatch"; Flags: uninsdeletevalue; ValueType: string; ValueName: "";
|
||||||
Root: HKCR; Subkey: "{#MyAppName}smwpatch"; ValueData: "Archipelago Super Mario World Patch"; Flags: uninsdeletekey; ValueType: string; ValueName: "";
|
Root: HKCR; Subkey: "{#MyAppName}smwpatch"; ValueData: "Archipelago Super Mario World Patch"; Flags: uninsdeletekey; ValueType: string; ValueName: "";
|
||||||
Root: HKCR; Subkey: "{#MyAppName}smwpatch\DefaultIcon"; ValueData: "{app}\ArchipelagoSNIClient.exe,0"; ValueType: string; ValueName: "";
|
Root: HKCR; Subkey: "{#MyAppName}smwpatch\DefaultIcon"; ValueData: "{app}\ArchipelagoSNIClient.exe,0"; ValueType: string; ValueName: "";
|
||||||
|
|||||||
@@ -269,8 +269,9 @@ if not is_frozen():
|
|||||||
from Launcher import open_folder
|
from Launcher import open_folder
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
parser = argparse.ArgumentParser("Build script for APWorlds")
|
parser = argparse.ArgumentParser(prog="Build APWorlds", description="Build script for APWorlds")
|
||||||
parser.add_argument("worlds", type=str, default=(), nargs="*", help="Names of APWorlds to build.")
|
parser.add_argument("worlds", type=str, default=(), nargs="*", help="names of APWorlds to build")
|
||||||
|
parser.add_argument("--skip_open_folder", action="store_true", help="don't open the output build folder")
|
||||||
args = parser.parse_args(launch_args)
|
args = parser.parse_args(launch_args)
|
||||||
|
|
||||||
if args.worlds:
|
if args.worlds:
|
||||||
@@ -320,7 +321,9 @@ if not is_frozen():
|
|||||||
zf.write(pathlib.Path(world_directory, file), pathlib.Path(file_name, file))
|
zf.write(pathlib.Path(world_directory, file), pathlib.Path(file_name, file))
|
||||||
|
|
||||||
zf.writestr(apworld.manifest_path, json.dumps(manifest))
|
zf.writestr(apworld.manifest_path, json.dumps(manifest))
|
||||||
open_folder(apworlds_folder)
|
|
||||||
|
if not args.skip_open_folder:
|
||||||
|
open_folder(apworlds_folder)
|
||||||
|
|
||||||
components.append(Component("Build APWorlds", func=_build_apworlds, cli=True,
|
components.append(Component("Build APWorlds", func=_build_apworlds, cli=True,
|
||||||
description="Build APWorlds from loose-file world folders."))
|
description="Build APWorlds from loose-file world folders."))
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ from Options import PerGameCommonOptions
|
|||||||
from .Locations import location_table, AdventureLocation, dragon_room_to_region
|
from .Locations import location_table, AdventureLocation, dragon_room_to_region
|
||||||
|
|
||||||
|
|
||||||
def connect(world: MultiWorld, player: int, source: str, target: str, rule: callable = lambda state: True,
|
def connect(multiworld: MultiWorld, player: int, source: str, target: str, rule: callable = lambda state: True,
|
||||||
one_way=False, name=None):
|
one_way=False, name=None):
|
||||||
source_region = world.get_region(source, player)
|
source_region = multiworld.get_region(source, player)
|
||||||
target_region = world.get_region(target, player)
|
target_region = multiworld.get_region(target, player)
|
||||||
|
|
||||||
if name is None:
|
if name is None:
|
||||||
name = source + " to " + target
|
name = source + " to " + target
|
||||||
@@ -22,7 +22,7 @@ def connect(world: MultiWorld, player: int, source: str, target: str, rule: call
|
|||||||
source_region.exits.append(connection)
|
source_region.exits.append(connection)
|
||||||
connection.connect(target_region)
|
connection.connect(target_region)
|
||||||
if not one_way:
|
if not one_way:
|
||||||
connect(world, player, target, source, rule, True)
|
connect(multiworld, player, target, source, rule, True)
|
||||||
|
|
||||||
|
|
||||||
def create_regions(options: PerGameCommonOptions, multiworld: MultiWorld, player: int, dragon_rooms: []) -> None:
|
def create_regions(options: PerGameCommonOptions, multiworld: MultiWorld, player: int, dragon_rooms: []) -> None:
|
||||||
|
|||||||
+25
-25
@@ -3,47 +3,47 @@ from worlds.generic.Rules import add_rule, set_rule, forbid_item
|
|||||||
|
|
||||||
|
|
||||||
def set_rules(self) -> None:
|
def set_rules(self) -> None:
|
||||||
world = self.multiworld
|
multiworld = self.multiworld
|
||||||
use_bat_logic = self.options.bat_logic.value == BatLogic.option_use_logic
|
use_bat_logic = self.options.bat_logic.value == BatLogic.option_use_logic
|
||||||
|
|
||||||
set_rule(world.get_entrance("YellowCastlePort", self.player),
|
set_rule(multiworld.get_entrance("YellowCastlePort", self.player),
|
||||||
lambda state: state.has("Yellow Key", self.player))
|
lambda state: state.has("Yellow Key", self.player))
|
||||||
set_rule(world.get_entrance("BlackCastlePort", self.player),
|
set_rule(multiworld.get_entrance("BlackCastlePort", self.player),
|
||||||
lambda state: state.has("Black Key", self.player))
|
lambda state: state.has("Black Key", self.player))
|
||||||
set_rule(world.get_entrance("WhiteCastlePort", self.player),
|
set_rule(multiworld.get_entrance("WhiteCastlePort", self.player),
|
||||||
lambda state: state.has("White Key", self.player))
|
lambda state: state.has("White Key", self.player))
|
||||||
|
|
||||||
# a future thing would be to make the bat an actual item, or at least allow it to
|
# a future thing would be to make the bat an actual item, or at least allow it to
|
||||||
# be placed in a castle, which would require some additions to the rules when
|
# be placed in a castle, which would require some additions to the rules when
|
||||||
# use_bat_logic is true
|
# use_bat_logic is true
|
||||||
if not use_bat_logic:
|
if not use_bat_logic:
|
||||||
set_rule(world.get_entrance("WhiteCastleSecretPassage", self.player),
|
set_rule(multiworld.get_entrance("WhiteCastleSecretPassage", self.player),
|
||||||
lambda state: state.has("Bridge", self.player))
|
lambda state: state.has("Bridge", self.player))
|
||||||
set_rule(world.get_entrance("WhiteCastlePeekPassage", self.player),
|
set_rule(multiworld.get_entrance("WhiteCastlePeekPassage", self.player),
|
||||||
lambda state: state.has("Bridge", self.player) or
|
lambda state: state.has("Bridge", self.player) or
|
||||||
state.has("Magnet", self.player))
|
state.has("Magnet", self.player))
|
||||||
set_rule(world.get_entrance("BlackCastleVaultEntrance", self.player),
|
set_rule(multiworld.get_entrance("BlackCastleVaultEntrance", self.player),
|
||||||
lambda state: state.has("Bridge", self.player) or
|
lambda state: state.has("Bridge", self.player) or
|
||||||
state.has("Magnet", self.player))
|
state.has("Magnet", self.player))
|
||||||
|
|
||||||
dragon_slay_check = self.options.dragon_slay_check.value
|
dragon_slay_check = self.options.dragon_slay_check.value
|
||||||
if dragon_slay_check:
|
if dragon_slay_check:
|
||||||
if self.difficulty_switch_b == DifficultySwitchB.option_hard_with_unlock_item:
|
if self.difficulty_switch_b == DifficultySwitchB.option_hard_with_unlock_item:
|
||||||
set_rule(world.get_location("Slay Yorgle", self.player),
|
set_rule(multiworld.get_location("Slay Yorgle", self.player),
|
||||||
lambda state: state.has("Sword", self.player) and
|
lambda state: state.has("Sword", self.player) and
|
||||||
state.has("Right Difficulty Switch", self.player))
|
state.has("Right Difficulty Switch", self.player))
|
||||||
set_rule(world.get_location("Slay Grundle", self.player),
|
set_rule(multiworld.get_location("Slay Grundle", self.player),
|
||||||
lambda state: state.has("Sword", self.player) and
|
lambda state: state.has("Sword", self.player) and
|
||||||
state.has("Right Difficulty Switch", self.player))
|
state.has("Right Difficulty Switch", self.player))
|
||||||
set_rule(world.get_location("Slay Rhindle", self.player),
|
set_rule(multiworld.get_location("Slay Rhindle", self.player),
|
||||||
lambda state: state.has("Sword", self.player) and
|
lambda state: state.has("Sword", self.player) and
|
||||||
state.has("Right Difficulty Switch", self.player))
|
state.has("Right Difficulty Switch", self.player))
|
||||||
else:
|
else:
|
||||||
set_rule(world.get_location("Slay Yorgle", self.player),
|
set_rule(multiworld.get_location("Slay Yorgle", self.player),
|
||||||
lambda state: state.has("Sword", self.player))
|
lambda state: state.has("Sword", self.player))
|
||||||
set_rule(world.get_location("Slay Grundle", self.player),
|
set_rule(multiworld.get_location("Slay Grundle", self.player),
|
||||||
lambda state: state.has("Sword", self.player))
|
lambda state: state.has("Sword", self.player))
|
||||||
set_rule(world.get_location("Slay Rhindle", self.player),
|
set_rule(multiworld.get_location("Slay Rhindle", self.player),
|
||||||
lambda state: state.has("Sword", self.player))
|
lambda state: state.has("Sword", self.player))
|
||||||
|
|
||||||
# really this requires getting the dot item, and having another item or enemy
|
# really this requires getting the dot item, and having another item or enemy
|
||||||
@@ -51,37 +51,37 @@ def set_rules(self) -> None:
|
|||||||
# to actually make randomized, since it is invisible. May add some options
|
# to actually make randomized, since it is invisible. May add some options
|
||||||
# for how that works in the distant future, but for now, just say you need
|
# for how that works in the distant future, but for now, just say you need
|
||||||
# the bridge and black key to get to it, as that simplifies things a lot
|
# the bridge and black key to get to it, as that simplifies things a lot
|
||||||
set_rule(world.get_entrance("CreditsWall", self.player),
|
set_rule(multiworld.get_entrance("CreditsWall", self.player),
|
||||||
lambda state: state.has("Bridge", self.player) and
|
lambda state: state.has("Bridge", self.player) and
|
||||||
state.has("Black Key", self.player))
|
state.has("Black Key", self.player))
|
||||||
|
|
||||||
if not use_bat_logic:
|
if not use_bat_logic:
|
||||||
set_rule(world.get_entrance("CreditsToFarSide", self.player),
|
set_rule(multiworld.get_entrance("CreditsToFarSide", self.player),
|
||||||
lambda state: state.has("Magnet", self.player))
|
lambda state: state.has("Magnet", self.player))
|
||||||
|
|
||||||
# bridge literally does not fit in this space, I think. I'll just exclude it
|
# bridge literally does not fit in this space, I think. I'll just exclude it
|
||||||
forbid_item(world.get_location("Dungeon Vault", self.player), "Bridge", self.player)
|
forbid_item(multiworld.get_location("Dungeon Vault", self.player), "Bridge", self.player)
|
||||||
# don't put magnet in locations that can pull in-logic items out of reach unless the bat is in play
|
# don't put magnet in locations that can pull in-logic items out of reach unless the bat is in play
|
||||||
if not use_bat_logic:
|
if not use_bat_logic:
|
||||||
forbid_item(world.get_location("Dungeon Vault", self.player), "Magnet", self.player)
|
forbid_item(multiworld.get_location("Dungeon Vault", self.player), "Magnet", self.player)
|
||||||
forbid_item(world.get_location("Red Maze Vault Entrance", self.player), "Magnet", self.player)
|
forbid_item(multiworld.get_location("Red Maze Vault Entrance", self.player), "Magnet", self.player)
|
||||||
forbid_item(world.get_location("Credits Right Side", self.player), "Magnet", self.player)
|
forbid_item(multiworld.get_location("Credits Right Side", self.player), "Magnet", self.player)
|
||||||
|
|
||||||
# and obviously we don't want to start with the game already won
|
# and obviously we don't want to start with the game already won
|
||||||
forbid_item(world.get_location("Inside Yellow Castle", self.player), "Chalice", self.player)
|
forbid_item(multiworld.get_location("Inside Yellow Castle", self.player), "Chalice", self.player)
|
||||||
overworld = world.get_region("Overworld", self.player)
|
overworld = multiworld.get_region("Overworld", self.player)
|
||||||
|
|
||||||
for loc in overworld.locations:
|
for loc in overworld.locations:
|
||||||
forbid_item(loc, "Chalice", self.player)
|
forbid_item(loc, "Chalice", self.player)
|
||||||
|
|
||||||
add_rule(world.get_location("Chalice Home", self.player),
|
add_rule(multiworld.get_location("Chalice Home", self.player),
|
||||||
lambda state: state.has("Chalice", self.player) and state.has("Yellow Key", self.player))
|
lambda state: state.has("Chalice", self.player) and state.has("Yellow Key", self.player))
|
||||||
|
|
||||||
# world.random.choice(overworld.locations).progress_type = LocationProgressType.PRIORITY
|
# multiworld.random.choice(overworld.locations).progress_type = LocationProgressType.PRIORITY
|
||||||
|
|
||||||
# all_locations = world.get_locations(self.player).copy()
|
# all_locations = multiworld.get_locations(self.player).copy()
|
||||||
# while priority_count < get_num_items():
|
# while priority_count < get_num_items():
|
||||||
# loc = world.random.choice(all_locations)
|
# loc = multiworld.random.choice(all_locations)
|
||||||
# if loc.progress_type == LocationProgressType.DEFAULT:
|
# if loc.progress_type == LocationProgressType.DEFAULT:
|
||||||
# loc.progress_type = LocationProgressType.PRIORITY
|
# loc.progress_type = LocationProgressType.PRIORITY
|
||||||
# priority_count += 1
|
# priority_count += 1
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ class AdventureWorld(World):
|
|||||||
location_name_to_id: ClassVar[Dict[str, int]] = {name: data.location_id for name, data in location_table.items()}
|
location_name_to_id: ClassVar[Dict[str, int]] = {name: data.location_id for name, data in location_table.items()}
|
||||||
required_client_version: Tuple[int, int, int] = (0, 3, 9)
|
required_client_version: Tuple[int, int, int] = (0, 3, 9)
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int):
|
def __init__(self, multiworld: MultiWorld, player: int):
|
||||||
super().__init__(world, player)
|
super().__init__(multiworld, player)
|
||||||
self.rom_name: Optional[bytearray] = bytearray("", "utf8" )
|
self.rom_name: Optional[bytearray] = bytearray("", "utf8" )
|
||||||
self.dragon_rooms: [int] = [0x14, 0x19, 0x4]
|
self.dragon_rooms: [int] = [0x14, 0x19, 0x4]
|
||||||
self.dragon_slay_check: Optional[int] = 0
|
self.dragon_slay_check: Optional[int] = 0
|
||||||
|
|||||||
@@ -30,7 +30,10 @@
|
|||||||
C to fire available Confetti Cannons
|
C to fire available Confetti Cannons
|
||||||
Number Keys + Backspace for Math Trap\n
|
Number Keys + Backspace for Math Trap\n
|
||||||
|
|
||||||
Rebinding controls might be added in the future :)"""
|
[b]Click to move also works![/b]
|
||||||
|
|
||||||
|
Click/tap Confetti Cannon to fire it
|
||||||
|
Submit Math Trap solution in the command line at the bottom"""
|
||||||
|
|
||||||
<VolumeSliderView>:
|
<VolumeSliderView>:
|
||||||
orientation: "horizontal"
|
orientation: "horizontal"
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ from argparse import Namespace
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from CommonClient import CommonContext, gui_enabled, logger, server_loop
|
from CommonClient import ClientCommandProcessor, CommonContext, logger, server_loop
|
||||||
from NetUtils import ClientStatus
|
from NetUtils import ClientStatus
|
||||||
|
from Utils import gui_enabled
|
||||||
|
|
||||||
from ..game.events import ConfettiFired, LocationClearedEvent, MathProblemSolved, MathProblemStarted, VictoryEvent
|
from ..game.events import ConfettiFired, LocationClearedEvent, MathProblemSolved, MathProblemStarted, VictoryEvent
|
||||||
from ..game.game import Game
|
from ..game.game import Game
|
||||||
@@ -41,6 +42,16 @@ class ConnectionStatus(Enum):
|
|||||||
GAME_RUNNING = 3
|
GAME_RUNNING = 3
|
||||||
|
|
||||||
|
|
||||||
|
class APQuestClientCommandProcessor(ClientCommandProcessor):
|
||||||
|
ctx: "APQuestContext"
|
||||||
|
|
||||||
|
def default(self, raw: str) -> None:
|
||||||
|
if self.ctx.external_math_trap_input(raw):
|
||||||
|
return
|
||||||
|
|
||||||
|
super().default(raw)
|
||||||
|
|
||||||
|
|
||||||
class APQuestContext(CommonContext):
|
class APQuestContext(CommonContext):
|
||||||
game = "APQuest"
|
game = "APQuest"
|
||||||
items_handling = 0b111 # full remote
|
items_handling = 0b111 # full remote
|
||||||
@@ -65,6 +76,7 @@ class APQuestContext(CommonContext):
|
|||||||
delay_intro_song: bool
|
delay_intro_song: bool
|
||||||
|
|
||||||
ui: APQuestManager
|
ui: APQuestManager
|
||||||
|
command_processor = APQuestClientCommandProcessor
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, server_address: str | None = None, password: str | None = None, delay_intro_song: bool = False
|
self, server_address: str | None = None, password: str | None = None, delay_intro_song: bool = False
|
||||||
@@ -172,7 +184,6 @@ class APQuestContext(CommonContext):
|
|||||||
assert self.ap_quest_game is not None
|
assert self.ap_quest_game is not None
|
||||||
self.ap_quest_game.gameboard.fill_remote_location_content(remote_item_graphic_overrides)
|
self.ap_quest_game.gameboard.fill_remote_location_content(remote_item_graphic_overrides)
|
||||||
self.render()
|
self.render()
|
||||||
self.ui.game_view.bind_keyboard()
|
|
||||||
|
|
||||||
self.connection_status = ConnectionStatus.GAME_RUNNING
|
self.connection_status = ConnectionStatus.GAME_RUNNING
|
||||||
self.ui.game_started()
|
self.ui.game_started()
|
||||||
@@ -244,6 +255,59 @@ class APQuestContext(CommonContext):
|
|||||||
self.ap_quest_game.input(input_key)
|
self.ap_quest_game.input(input_key)
|
||||||
self.render()
|
self.render()
|
||||||
|
|
||||||
|
def queue_auto_move(self, target_x: int, target_y: int) -> None:
|
||||||
|
if self.ap_quest_game is None:
|
||||||
|
return
|
||||||
|
if not self.ap_quest_game.gameboard.ready:
|
||||||
|
return
|
||||||
|
if not self.ui.game_view.focused > 1: # Must already be in focus
|
||||||
|
return
|
||||||
|
self.ap_quest_game.queue_auto_move(target_x, target_y)
|
||||||
|
self.ui.start_auto_move()
|
||||||
|
|
||||||
|
def do_auto_move_and_rerender(self) -> None:
|
||||||
|
if self.ap_quest_game is None:
|
||||||
|
return
|
||||||
|
if not self.ap_quest_game.gameboard.ready:
|
||||||
|
return
|
||||||
|
changed = self.ap_quest_game.do_auto_move()
|
||||||
|
if changed:
|
||||||
|
self.render()
|
||||||
|
|
||||||
|
def confetti_and_rerender(self) -> None:
|
||||||
|
# Used by tap mode
|
||||||
|
if self.ap_quest_game is None:
|
||||||
|
return
|
||||||
|
if not self.ap_quest_game.gameboard.ready:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.ap_quest_game.attempt_fire_confetti_cannon():
|
||||||
|
self.render()
|
||||||
|
|
||||||
|
def external_math_trap_input(self, raw: str) -> bool:
|
||||||
|
if self.ap_quest_game is None:
|
||||||
|
return False
|
||||||
|
if not self.ap_quest_game.gameboard.ready:
|
||||||
|
return False
|
||||||
|
if not self.ap_quest_game.active_math_problem:
|
||||||
|
return False
|
||||||
|
|
||||||
|
raw = raw.strip()
|
||||||
|
|
||||||
|
if not raw:
|
||||||
|
return False
|
||||||
|
if not raw.isnumeric():
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.ap_quest_game.math_problem_replace([int(digit) for digit in raw])
|
||||||
|
|
||||||
|
if not self.ap_quest_game.active_math_problem:
|
||||||
|
self.ui.game_view.force_focus()
|
||||||
|
|
||||||
|
self.render()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def make_gui(self) -> "type[kvui.GameManager]":
|
def make_gui(self) -> "type[kvui.GameManager]":
|
||||||
self.load_kv()
|
self.load_kv()
|
||||||
return APQuestManager
|
return APQuestManager
|
||||||
|
|||||||
@@ -4,29 +4,26 @@ from math import sqrt
|
|||||||
from random import choice, random
|
from random import choice, random
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from kivy.core.window import Keyboard, Window
|
from kivy.core.window import Window
|
||||||
from kivy.graphics import Color, Triangle
|
from kivy.graphics import Color, Triangle
|
||||||
from kivy.graphics.instructions import Canvas
|
from kivy.graphics.instructions import Canvas
|
||||||
from kivy.input import MotionEvent
|
from kivy.uix.behaviors import ButtonBehavior
|
||||||
from kivy.uix.boxlayout import BoxLayout
|
from kivy.uix.boxlayout import BoxLayout
|
||||||
from kivy.uix.gridlayout import GridLayout
|
from kivy.uix.gridlayout import GridLayout
|
||||||
|
from kivy.uix.image import Image
|
||||||
|
from kivy.uix.widget import Widget
|
||||||
from kivymd.uix.recycleview import MDRecycleView
|
from kivymd.uix.recycleview import MDRecycleView
|
||||||
|
|
||||||
from CommonClient import logger
|
from CommonClient import logger
|
||||||
|
|
||||||
from ..game.inputs import Input
|
from ..game.inputs import Input
|
||||||
|
|
||||||
|
INPUT_MAP_STR = {
|
||||||
INPUT_MAP = {
|
|
||||||
"up": Input.UP,
|
|
||||||
"w": Input.UP,
|
"w": Input.UP,
|
||||||
"down": Input.DOWN,
|
|
||||||
"s": Input.DOWN,
|
"s": Input.DOWN,
|
||||||
"right": Input.RIGHT,
|
|
||||||
"d": Input.RIGHT,
|
"d": Input.RIGHT,
|
||||||
"left": Input.LEFT,
|
|
||||||
"a": Input.LEFT,
|
"a": Input.LEFT,
|
||||||
"spacebar": Input.ACTION,
|
" ": Input.ACTION,
|
||||||
"c": Input.CONFETTI,
|
"c": Input.CONFETTI,
|
||||||
"0": Input.ZERO,
|
"0": Input.ZERO,
|
||||||
"1": Input.ONE,
|
"1": Input.ONE,
|
||||||
@@ -38,38 +35,52 @@ INPUT_MAP = {
|
|||||||
"7": Input.SEVEN,
|
"7": Input.SEVEN,
|
||||||
"8": Input.EIGHT,
|
"8": Input.EIGHT,
|
||||||
"9": Input.NINE,
|
"9": Input.NINE,
|
||||||
"backspace": Input.BACKSPACE,
|
}
|
||||||
|
|
||||||
|
INPUT_MAP_SPECIAL_INT = {
|
||||||
|
# Arrow Keys and Backspace
|
||||||
|
273: Input.UP,
|
||||||
|
274: Input.DOWN,
|
||||||
|
275: Input.RIGHT,
|
||||||
|
276: Input.LEFT,
|
||||||
|
8: Input.BACKSPACE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class APQuestGameView(MDRecycleView):
|
class APQuestGameView(MDRecycleView):
|
||||||
_keyboard: Keyboard | None = None
|
focused: int = 1
|
||||||
input_function: Callable[[Input], None]
|
input_function: Callable[[Input], None]
|
||||||
|
|
||||||
def __init__(self, input_function: Callable[[Input], None], **kwargs: Any) -> None:
|
def __init__(self, input_function: Callable[[Input], None], **kwargs: Any) -> None:
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.input_function = input_function
|
self.input_function = input_function
|
||||||
self.bind_keyboard()
|
Window.bind(on_key_down=self._on_keyboard_down)
|
||||||
|
Window.bind(on_touch_down=self.check_focus)
|
||||||
|
self.opacity = 0.5
|
||||||
|
|
||||||
def on_touch_down(self, touch: MotionEvent) -> None:
|
def check_focus(self, _, touch, *args, **kwargs) -> None:
|
||||||
self.bind_keyboard()
|
if self.parent.collide_point(*touch.pos):
|
||||||
|
self.focused += 1
|
||||||
def bind_keyboard(self) -> None:
|
self.opacity = 1
|
||||||
if self._keyboard is not None:
|
|
||||||
return
|
return
|
||||||
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
|
|
||||||
self._keyboard.bind(on_key_down=self._on_keyboard_down)
|
|
||||||
|
|
||||||
def _keyboard_closed(self) -> None:
|
self.focused = 0
|
||||||
if self._keyboard is None:
|
self.opacity = 0.5
|
||||||
return
|
|
||||||
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
|
|
||||||
self._keyboard = None
|
|
||||||
|
|
||||||
def _on_keyboard_down(self, _: Any, keycode: tuple[int, str], _1: Any, _2: Any) -> bool:
|
def force_focus(self) -> None:
|
||||||
if keycode[1] in INPUT_MAP:
|
Window.release_keyboard()
|
||||||
self.input_function(INPUT_MAP[keycode[1]])
|
self.focused = 1
|
||||||
return True
|
self.opacity = 1
|
||||||
|
|
||||||
|
def _on_keyboard_down(self, _: Any, keycode_int: int, _2: Any, keycode: str, _4: Any) -> bool:
|
||||||
|
if not self.focused:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if keycode in INPUT_MAP_STR:
|
||||||
|
self.input_function(INPUT_MAP_STR[keycode])
|
||||||
|
elif keycode_int in INPUT_MAP_SPECIAL_INT:
|
||||||
|
self.input_function(INPUT_MAP_SPECIAL_INT[keycode_int])
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class APQuestGrid(GridLayout):
|
class APQuestGrid(GridLayout):
|
||||||
@@ -203,13 +214,23 @@ class Confetti:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class ConfettiView(MDRecycleView):
|
class ConfettiView(Widget):
|
||||||
confetti: list[Confetti]
|
confetti: list[Confetti]
|
||||||
|
|
||||||
def __init__(self, **kwargs: Any) -> None:
|
def __init__(self, **kwargs: Any) -> None:
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.confetti = []
|
self.confetti = []
|
||||||
|
|
||||||
|
# Don't eat tap events for the game grid under the confetti view
|
||||||
|
def on_touch_down(self, touch) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def on_touch_move(self, touch) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def on_touch_up(self, touch) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
def check_resize(self, _: int, _1: int) -> None:
|
def check_resize(self, _: int, _1: int) -> None:
|
||||||
parent_width, parent_height = self.parent.size
|
parent_width, parent_height = self.parent.size
|
||||||
|
|
||||||
@@ -254,3 +275,32 @@ class VolumeSliderView(BoxLayout):
|
|||||||
|
|
||||||
class APQuestControlsView(BoxLayout):
|
class APQuestControlsView(BoxLayout):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TapImage(ButtonBehavior, Image):
|
||||||
|
callback: Callable[[], None]
|
||||||
|
|
||||||
|
def __init__(self, callback: Callable[[], None], **kwargs) -> None:
|
||||||
|
self.callback = callback
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def on_release(self) -> bool:
|
||||||
|
self.callback()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class TapIfConfettiCannonImage(ButtonBehavior, Image):
|
||||||
|
callback: Callable[[], None]
|
||||||
|
|
||||||
|
is_confetti_cannon: bool = False
|
||||||
|
|
||||||
|
def __init__(self, callback: Callable[[], None], **kwargs: dict[str, Any]) -> None:
|
||||||
|
self.callback = callback
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def on_release(self) -> bool:
|
||||||
|
if self.is_confetti_cannon:
|
||||||
|
self.callback()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from kvui import GameManager, MDNavigationItemBase
|
|||||||
# isort: on
|
# isort: on
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
|
from kivy._clock import ClockEvent
|
||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
from kivy.uix.gridlayout import GridLayout
|
from kivy.uix.gridlayout import GridLayout
|
||||||
from kivy.uix.image import Image
|
from kivy.uix.image import Image
|
||||||
@@ -13,7 +14,16 @@ from kivy.uix.layout import Layout
|
|||||||
from kivymd.uix.recycleview import MDRecycleView
|
from kivymd.uix.recycleview import MDRecycleView
|
||||||
|
|
||||||
from ..game.game import Game
|
from ..game.game import Game
|
||||||
from .custom_views import APQuestControlsView, APQuestGameView, APQuestGrid, ConfettiView, VolumeSliderView
|
from ..game.graphics import Graphic
|
||||||
|
from .custom_views import (
|
||||||
|
APQuestControlsView,
|
||||||
|
APQuestGameView,
|
||||||
|
APQuestGrid,
|
||||||
|
ConfettiView,
|
||||||
|
TapIfConfettiCannonImage,
|
||||||
|
TapImage,
|
||||||
|
VolumeSliderView,
|
||||||
|
)
|
||||||
from .graphics import PlayerSprite, get_texture
|
from .graphics import PlayerSprite, get_texture
|
||||||
from .sounds import SoundManager
|
from .sounds import SoundManager
|
||||||
|
|
||||||
@@ -28,15 +38,17 @@ class APQuestManager(GameManager):
|
|||||||
lower_game_grid: GridLayout
|
lower_game_grid: GridLayout
|
||||||
upper_game_grid: GridLayout
|
upper_game_grid: GridLayout
|
||||||
|
|
||||||
game_view: MDRecycleView
|
game_view: MDRecycleView | None = None
|
||||||
game_view_tab: MDNavigationItemBase
|
game_view_tab: MDNavigationItemBase
|
||||||
|
|
||||||
sound_manager: SoundManager
|
sound_manager: SoundManager
|
||||||
|
|
||||||
bottom_image_grid: list[list[Image]]
|
bottom_image_grid: list[list[Image]]
|
||||||
top_image_grid: list[list[Image]]
|
top_image_grid: list[list[TapImage]]
|
||||||
confetti_view: ConfettiView
|
confetti_view: ConfettiView
|
||||||
|
|
||||||
|
move_event: ClockEvent | None
|
||||||
|
|
||||||
bottom_grid_is_grass: bool
|
bottom_grid_is_grass: bool
|
||||||
|
|
||||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
@@ -45,6 +57,7 @@ class APQuestManager(GameManager):
|
|||||||
self.sound_manager.allow_intro_to_play = not self.ctx.delay_intro_song
|
self.sound_manager.allow_intro_to_play = not self.ctx.delay_intro_song
|
||||||
self.top_image_grid = []
|
self.top_image_grid = []
|
||||||
self.bottom_image_grid = []
|
self.bottom_image_grid = []
|
||||||
|
self.move_event = None
|
||||||
self.bottom_grid_is_grass = False
|
self.bottom_grid_is_grass = False
|
||||||
|
|
||||||
def allow_intro_song(self) -> None:
|
def allow_intro_song(self) -> None:
|
||||||
@@ -71,10 +84,12 @@ class APQuestManager(GameManager):
|
|||||||
|
|
||||||
def game_started(self) -> None:
|
def game_started(self) -> None:
|
||||||
self.switch_to_game_tab()
|
self.switch_to_game_tab()
|
||||||
|
if self.game_view is not None:
|
||||||
|
self.game_view.force_focus()
|
||||||
self.sound_manager.game_started = True
|
self.sound_manager.game_started = True
|
||||||
|
|
||||||
def render(self, game: Game, player_sprite: PlayerSprite) -> None:
|
def render(self, game: Game, player_sprite: PlayerSprite) -> None:
|
||||||
self.setup_game_grid_if_not_setup(game.gameboard.size)
|
self.setup_game_grid_if_not_setup(game)
|
||||||
|
|
||||||
# This calls game.render(), which needs to happen to update the state of math traps
|
# This calls game.render(), which needs to happen to update the state of math traps
|
||||||
self.render_gameboard(game, player_sprite)
|
self.render_gameboard(game, player_sprite)
|
||||||
@@ -104,6 +119,8 @@ class APQuestManager(GameManager):
|
|||||||
for item_graphic, image_row in zip(rendered_item_column, self.top_image_grid, strict=False):
|
for item_graphic, image_row in zip(rendered_item_column, self.top_image_grid, strict=False):
|
||||||
image = image_row[-1]
|
image = image_row[-1]
|
||||||
|
|
||||||
|
image.is_confetti_cannon = item_graphic == Graphic.CONFETTI_CANNON
|
||||||
|
|
||||||
texture = get_texture(item_graphic)
|
texture = get_texture(item_graphic)
|
||||||
if texture is None:
|
if texture is None:
|
||||||
image.opacity = 0
|
image.opacity = 0
|
||||||
@@ -136,23 +153,25 @@ class APQuestManager(GameManager):
|
|||||||
|
|
||||||
self.bottom_grid_is_grass = grass
|
self.bottom_grid_is_grass = grass
|
||||||
|
|
||||||
def setup_game_grid_if_not_setup(self, size: tuple[int, int]) -> None:
|
def setup_game_grid_if_not_setup(self, game: Game) -> None:
|
||||||
if self.upper_game_grid.children:
|
if self.upper_game_grid.children:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.top_image_grid = []
|
self.top_image_grid = []
|
||||||
self.bottom_image_grid = []
|
self.bottom_image_grid = []
|
||||||
|
|
||||||
for _row in range(size[1]):
|
size = game.gameboard.size
|
||||||
|
|
||||||
|
for row in range(size[1]):
|
||||||
self.top_image_grid.append([])
|
self.top_image_grid.append([])
|
||||||
self.bottom_image_grid.append([])
|
self.bottom_image_grid.append([])
|
||||||
|
|
||||||
for _column in range(size[0]):
|
for column in range(size[0]):
|
||||||
bottom_image = Image(fit_mode="fill", color=(0.3, 0.3, 0.3))
|
bottom_image = Image(fit_mode="fill", color=(0.3, 0.3, 0.3))
|
||||||
self.lower_game_grid.add_widget(bottom_image)
|
self.lower_game_grid.add_widget(bottom_image)
|
||||||
self.bottom_image_grid[-1].append(bottom_image)
|
self.bottom_image_grid[-1].append(bottom_image)
|
||||||
|
|
||||||
top_image = Image(fit_mode="fill")
|
top_image = TapImage(lambda y=row, x=column: self.ctx.queue_auto_move(x, y), fit_mode="fill")
|
||||||
self.upper_game_grid.add_widget(top_image)
|
self.upper_game_grid.add_widget(top_image)
|
||||||
self.top_image_grid[-1].append(top_image)
|
self.top_image_grid[-1].append(top_image)
|
||||||
|
|
||||||
@@ -160,11 +179,19 @@ class APQuestManager(GameManager):
|
|||||||
image = Image(fit_mode="fill", color=(0.3, 0.3, 0.3))
|
image = Image(fit_mode="fill", color=(0.3, 0.3, 0.3))
|
||||||
self.lower_game_grid.add_widget(image)
|
self.lower_game_grid.add_widget(image)
|
||||||
|
|
||||||
image2 = Image(fit_mode="fill", opacity=0)
|
image2 = TapIfConfettiCannonImage(lambda: self.ctx.confetti_and_rerender(), fit_mode="fill", opacity=0)
|
||||||
self.upper_game_grid.add_widget(image2)
|
self.upper_game_grid.add_widget(image2)
|
||||||
|
|
||||||
self.top_image_grid[-1].append(image2)
|
self.top_image_grid[-1].append(image2)
|
||||||
|
|
||||||
|
def start_auto_move(self) -> None:
|
||||||
|
if self.move_event is not None:
|
||||||
|
self.move_event.cancel()
|
||||||
|
|
||||||
|
self.ctx.do_auto_move_and_rerender()
|
||||||
|
|
||||||
|
self.move_event = Clock.schedule_interval(lambda _: self.ctx.do_auto_move_and_rerender(), 0.10)
|
||||||
|
|
||||||
def build(self) -> Layout:
|
def build(self) -> Layout:
|
||||||
container = super().build()
|
container = super().build()
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
- Die [APQuest-apworld](https://github.com/NewSoupVi/Archipelago/releases),
|
- Die [APQuest-apworld](https://github.com/NewSoupVi/Archipelago/releases),
|
||||||
falls diese nicht mit deiner Version von Archipelago gebündelt ist.
|
falls diese nicht mit deiner Version von Archipelago gebündelt ist.
|
||||||
|
|
||||||
|
## Optionale Software
|
||||||
|
|
||||||
|
- [APQuest AP Tracker](https://github.com/palex00/ap-quest-tracker/releases/latest), zur Verwendung mit
|
||||||
|
[PopTracker](https://github.com/black-sliver/PopTracker/releases)
|
||||||
|
|
||||||
## Wie man spielt
|
## Wie man spielt
|
||||||
|
|
||||||
Zuerst brauchst du einen Raum, mit dem du dich verbinden kannst.
|
Zuerst brauchst du einen Raum, mit dem du dich verbinden kannst.
|
||||||
@@ -41,3 +46,15 @@ Du solltest jetzt verbunden sein und kannst APQuest spielen.
|
|||||||
Der APQuest Client kann zwischen verschiedenen Slots wechseln, ohne neugestartet werden zu müssen,
|
Der APQuest Client kann zwischen verschiedenen Slots wechseln, ohne neugestartet werden zu müssen,
|
||||||
|
|
||||||
Klicke einfach den "Disconnect"-Knopf. Dann verbinde dich mit dem anderen Raum / Slot.
|
Klicke einfach den "Disconnect"-Knopf. Dann verbinde dich mit dem anderen Raum / Slot.
|
||||||
|
|
||||||
|
|
||||||
|
## Automatisches Tracken
|
||||||
|
|
||||||
|
AP Quest verfügt über einen voll funktionsfähigen, automatischen Tracker mit Karten der Spielwelt.
|
||||||
|
|
||||||
|
1. Lade [APQuest AP Tracker](https://github.com/palex00/ap-quest-tracker/releases/latest) und
|
||||||
|
[PopTracker](https://github.com/black-sliver/PopTracker/releases) herunter.
|
||||||
|
2. Lege das Tracker-Pack im Ordner „packs/“ deiner PopTracker-Installation ab.
|
||||||
|
3. Öffne PopTracker und lade das APQuest-Pack.
|
||||||
|
4. Für das automatische Tracking klick oben auf das „AP“-Symbol.
|
||||||
|
5. Gib die Serveradresse von Archipelago (die, mit der du deinen Client verbunden hast), den Slot-Namen und das Passwort ein.
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
- [The APQuest apworld](https://github.com/NewSoupVi/Archipelago/releases),
|
- [The APQuest apworld](https://github.com/NewSoupVi/Archipelago/releases),
|
||||||
if not bundled with your version of Archipelago
|
if not bundled with your version of Archipelago
|
||||||
|
|
||||||
|
## Optional Software
|
||||||
|
|
||||||
|
- [APQuest AP Tracker](https://github.com/palex00/ap-quest-tracker/releases/latest), for use with
|
||||||
|
[PopTracker](https://github.com/black-sliver/PopTracker/releases)
|
||||||
|
|
||||||
## How to play
|
## How to play
|
||||||
|
|
||||||
First, you need a room to connect to. For this, you or someone you know has to generate a game.
|
First, you need a room to connect to. For this, you or someone you know has to generate a game.
|
||||||
@@ -40,3 +45,14 @@ You should now be connected and able to play APQuest.
|
|||||||
The APQuest Client can seamlessly switch rooms without restarting.
|
The APQuest Client can seamlessly switch rooms without restarting.
|
||||||
|
|
||||||
Simply click the "Disconnect" button, then connect to a different slot/room.
|
Simply click the "Disconnect" button, then connect to a different slot/room.
|
||||||
|
|
||||||
|
## Auto-Tracking
|
||||||
|
|
||||||
|
AP Quest has a fully functional map tracker that supports auto-tracking.
|
||||||
|
|
||||||
|
1. Download [APQuest AP Tracker](https://github.com/palex00/ap-quest-tracker/releases/latest) and
|
||||||
|
[PopTracker](https://github.com/black-sliver/PopTracker/releases).
|
||||||
|
2. Put the tracker pack into packs/ in your PopTracker install.
|
||||||
|
3. Open PopTracker, and load the APQuest pack.
|
||||||
|
4. For autotracking, click on the "AP" symbol at the top.
|
||||||
|
5. Enter the Archipelago server address (the one you connected your client to), slot name, and password.
|
||||||
|
|||||||
@@ -17,8 +17,10 @@ class Entity:
|
|||||||
|
|
||||||
|
|
||||||
class InteractableMixin:
|
class InteractableMixin:
|
||||||
|
auto_move_attempt_passing_through = False
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def interact(self, player: Player) -> None:
|
def interact(self, player: Player) -> bool:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -89,15 +91,16 @@ class Chest(Entity, InteractableMixin, LocationMixin):
|
|||||||
self.is_open = True
|
self.is_open = True
|
||||||
self.update_solidity()
|
self.update_solidity()
|
||||||
|
|
||||||
def interact(self, player: Player) -> None:
|
def interact(self, player: Player) -> bool:
|
||||||
if self.has_given_content:
|
if self.has_given_content:
|
||||||
return
|
return False
|
||||||
|
|
||||||
if self.is_open:
|
if self.is_open:
|
||||||
self.give_content(player)
|
self.give_content(player)
|
||||||
return
|
return True
|
||||||
|
|
||||||
self.open()
|
self.open()
|
||||||
|
return True
|
||||||
|
|
||||||
def content_success(self) -> None:
|
def content_success(self) -> None:
|
||||||
self.update_solidity()
|
self.update_solidity()
|
||||||
@@ -135,47 +138,59 @@ class Door(Entity):
|
|||||||
|
|
||||||
|
|
||||||
class KeyDoor(Door, InteractableMixin):
|
class KeyDoor(Door, InteractableMixin):
|
||||||
|
auto_move_attempt_passing_through = True
|
||||||
|
|
||||||
closed_graphic = Graphic.KEY_DOOR
|
closed_graphic = Graphic.KEY_DOOR
|
||||||
|
|
||||||
def interact(self, player: Player) -> None:
|
def interact(self, player: Player) -> bool:
|
||||||
if self.is_open:
|
if self.is_open:
|
||||||
return
|
return False
|
||||||
|
|
||||||
if not player.has_item(Item.KEY):
|
if not player.has_item(Item.KEY):
|
||||||
return
|
return False
|
||||||
|
|
||||||
player.remove_item(Item.KEY)
|
player.remove_item(Item.KEY)
|
||||||
|
|
||||||
self.open()
|
self.open()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class BreakableBlock(Door, InteractableMixin):
|
class BreakableBlock(Door, InteractableMixin):
|
||||||
|
auto_move_attempt_passing_through = True
|
||||||
|
|
||||||
closed_graphic = Graphic.BREAKABLE_BLOCK
|
closed_graphic = Graphic.BREAKABLE_BLOCK
|
||||||
|
|
||||||
def interact(self, player: Player) -> None:
|
def interact(self, player: Player) -> bool:
|
||||||
if self.is_open:
|
if self.is_open:
|
||||||
return
|
return False
|
||||||
|
|
||||||
if not player.has_item(Item.HAMMER):
|
if not player.has_item(Item.HAMMER):
|
||||||
return
|
return False
|
||||||
|
|
||||||
player.remove_item(Item.HAMMER)
|
player.remove_item(Item.HAMMER)
|
||||||
|
|
||||||
self.open()
|
self.open()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class Bush(Door, InteractableMixin):
|
class Bush(Door, InteractableMixin):
|
||||||
|
auto_move_attempt_passing_through = True
|
||||||
|
|
||||||
closed_graphic = Graphic.BUSH
|
closed_graphic = Graphic.BUSH
|
||||||
|
|
||||||
def interact(self, player: Player) -> None:
|
def interact(self, player: Player) -> bool:
|
||||||
if self.is_open:
|
if self.is_open:
|
||||||
return
|
return False
|
||||||
|
|
||||||
if not player.has_item(Item.SWORD):
|
if not player.has_item(Item.SWORD):
|
||||||
return
|
return False
|
||||||
|
|
||||||
self.open()
|
self.open()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class Button(Entity, InteractableMixin):
|
class Button(Entity, InteractableMixin):
|
||||||
solid = True
|
solid = True
|
||||||
@@ -186,12 +201,13 @@ class Button(Entity, InteractableMixin):
|
|||||||
def __init__(self, activates: ActivatableMixin) -> None:
|
def __init__(self, activates: ActivatableMixin) -> None:
|
||||||
self.activates = activates
|
self.activates = activates
|
||||||
|
|
||||||
def interact(self, player: Player) -> None:
|
def interact(self, player: Player) -> bool:
|
||||||
if self.activated:
|
if self.activated:
|
||||||
return
|
return False
|
||||||
|
|
||||||
self.activated = True
|
self.activated = True
|
||||||
self.activates.activate(player)
|
self.activates.activate(player)
|
||||||
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def graphic(self) -> Graphic:
|
def graphic(self) -> Graphic:
|
||||||
@@ -240,9 +256,9 @@ class Enemy(Entity, InteractableMixin):
|
|||||||
return
|
return
|
||||||
self.current_health = self.max_health
|
self.current_health = self.max_health
|
||||||
|
|
||||||
def interact(self, player: Player) -> None:
|
def interact(self, player: Player) -> bool:
|
||||||
if self.dead:
|
if self.dead:
|
||||||
return
|
return False
|
||||||
|
|
||||||
if player.has_item(Item.SWORD):
|
if player.has_item(Item.SWORD):
|
||||||
self.current_health = max(0, self.current_health - 1)
|
self.current_health = max(0, self.current_health - 1)
|
||||||
@@ -250,9 +266,10 @@ class Enemy(Entity, InteractableMixin):
|
|||||||
if self.current_health == 0:
|
if self.current_health == 0:
|
||||||
if not self.dead:
|
if not self.dead:
|
||||||
self.die()
|
self.die()
|
||||||
return
|
return True
|
||||||
|
|
||||||
player.damage(2)
|
player.damage(2)
|
||||||
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def graphic(self) -> Graphic:
|
def graphic(self) -> Graphic:
|
||||||
@@ -270,13 +287,15 @@ class EnemyWithLoot(Enemy, LocationMixin):
|
|||||||
self.dead = True
|
self.dead = True
|
||||||
self.solid = not self.has_given_content
|
self.solid = not self.has_given_content
|
||||||
|
|
||||||
def interact(self, player: Player) -> None:
|
def interact(self, player: Player) -> bool:
|
||||||
if self.dead:
|
if self.dead:
|
||||||
if not self.has_given_content:
|
if not self.has_given_content:
|
||||||
self.give_content(player)
|
self.give_content(player)
|
||||||
return
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
super().interact(player)
|
super().interact(player)
|
||||||
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def graphic(self) -> Graphic:
|
def graphic(self) -> Graphic:
|
||||||
@@ -303,10 +322,12 @@ class FinalBoss(Enemy):
|
|||||||
}
|
}
|
||||||
enemy_default_graphic = Graphic.BOSS_1_HEALTH
|
enemy_default_graphic = Graphic.BOSS_1_HEALTH
|
||||||
|
|
||||||
def interact(self, player: Player) -> None:
|
def interact(self, player: Player) -> bool:
|
||||||
dead_before = self.dead
|
dead_before = self.dead
|
||||||
|
|
||||||
super().interact(player)
|
changed = super().interact(player)
|
||||||
|
|
||||||
if not dead_before and self.dead:
|
if not dead_before and self.dead:
|
||||||
player.victory()
|
player.victory()
|
||||||
|
|
||||||
|
return changed
|
||||||
|
|||||||
+74
-10
@@ -23,6 +23,8 @@ class Game:
|
|||||||
active_math_problem: MathProblem | None
|
active_math_problem: MathProblem | None
|
||||||
active_math_problem_input: list[int] | None
|
active_math_problem_input: list[int] | None
|
||||||
|
|
||||||
|
auto_target_path: list[tuple[int, int]] = []
|
||||||
|
|
||||||
remotely_received_items: set[tuple[int, int, int]]
|
remotely_received_items: set[tuple[int, int, int]]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -32,6 +34,7 @@ class Game:
|
|||||||
self.gameboard = create_gameboard(hard_mode, hammer_exists, extra_chest)
|
self.gameboard = create_gameboard(hard_mode, hammer_exists, extra_chest)
|
||||||
self.player = Player(self.gameboard, self.queued_events.append)
|
self.player = Player(self.gameboard, self.queued_events.append)
|
||||||
self.active_math_problem = None
|
self.active_math_problem = None
|
||||||
|
self.active_math_problem_input = None
|
||||||
self.remotely_received_items = set()
|
self.remotely_received_items = set()
|
||||||
|
|
||||||
if random_object is None:
|
if random_object is None:
|
||||||
@@ -94,29 +97,40 @@ class Game:
|
|||||||
|
|
||||||
return tuple(graphics_array)
|
return tuple(graphics_array)
|
||||||
|
|
||||||
def attempt_player_movement(self, direction: Direction) -> None:
|
def attempt_player_movement(self, direction: Direction, cancel_auto_move: bool = True) -> bool:
|
||||||
|
if cancel_auto_move:
|
||||||
|
self.cancel_auto_move()
|
||||||
|
|
||||||
self.player.facing = direction
|
self.player.facing = direction
|
||||||
|
|
||||||
delta_x, delta_y = direction.value
|
delta_x, delta_y = direction.value
|
||||||
new_x, new_y = self.player.current_x + delta_x, self.player.current_y + delta_y
|
new_x, new_y = self.player.current_x + delta_x, self.player.current_y + delta_y
|
||||||
|
|
||||||
if not self.gameboard.get_entity_at(new_x, new_y).solid:
|
if self.gameboard.get_entity_at(new_x, new_y).solid:
|
||||||
self.player.current_x = new_x
|
return False
|
||||||
self.player.current_y = new_y
|
|
||||||
|
|
||||||
def attempt_interact(self) -> None:
|
self.player.current_x = new_x
|
||||||
|
self.player.current_y = new_y
|
||||||
|
return True
|
||||||
|
|
||||||
|
def attempt_interact(self) -> bool:
|
||||||
delta_x, delta_y = self.player.facing.value
|
delta_x, delta_y = self.player.facing.value
|
||||||
entity_x, entity_y = self.player.current_x + delta_x, self.player.current_y + delta_y
|
entity_x, entity_y = self.player.current_x + delta_x, self.player.current_y + delta_y
|
||||||
|
|
||||||
entity = self.gameboard.get_entity_at(entity_x, entity_y)
|
entity = self.gameboard.get_entity_at(entity_x, entity_y)
|
||||||
|
|
||||||
if isinstance(entity, InteractableMixin):
|
if isinstance(entity, InteractableMixin):
|
||||||
entity.interact(self.player)
|
return entity.interact(self.player)
|
||||||
|
|
||||||
def attempt_fire_confetti_cannon(self) -> None:
|
return False
|
||||||
if self.player.has_item(Item.CONFETTI_CANNON):
|
|
||||||
self.player.remove_item(Item.CONFETTI_CANNON)
|
def attempt_fire_confetti_cannon(self) -> bool:
|
||||||
self.queued_events.append(ConfettiFired(self.player.current_x, self.player.current_y))
|
if not self.player.has_item(Item.CONFETTI_CANNON):
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.player.remove_item(Item.CONFETTI_CANNON)
|
||||||
|
self.queued_events.append(ConfettiFired(self.player.current_x, self.player.current_y))
|
||||||
|
return True
|
||||||
|
|
||||||
def math_problem_success(self) -> None:
|
def math_problem_success(self) -> None:
|
||||||
self.active_math_problem = None
|
self.active_math_problem = None
|
||||||
@@ -154,6 +168,12 @@ class Game:
|
|||||||
self.active_math_problem_input.pop()
|
self.active_math_problem_input.pop()
|
||||||
self.check_math_problem_result()
|
self.check_math_problem_result()
|
||||||
|
|
||||||
|
def math_problem_replace(self, input: list[int]) -> None:
|
||||||
|
if self.active_math_problem_input is None:
|
||||||
|
return
|
||||||
|
self.active_math_problem_input = input[:2]
|
||||||
|
self.check_math_problem_result()
|
||||||
|
|
||||||
def input(self, input_key: Input) -> None:
|
def input(self, input_key: Input) -> None:
|
||||||
if not self.gameboard.ready:
|
if not self.gameboard.ready:
|
||||||
return
|
return
|
||||||
@@ -201,3 +221,47 @@ class Game:
|
|||||||
def force_clear_location(self, location_id: int) -> None:
|
def force_clear_location(self, location_id: int) -> None:
|
||||||
location = Location(location_id)
|
location = Location(location_id)
|
||||||
self.gameboard.force_clear_location(location)
|
self.gameboard.force_clear_location(location)
|
||||||
|
|
||||||
|
def cancel_auto_move(self) -> None:
|
||||||
|
self.auto_target_path = []
|
||||||
|
|
||||||
|
def queue_auto_move(self, target_x: int, target_y: int) -> None:
|
||||||
|
self.cancel_auto_move()
|
||||||
|
path = self.gameboard.calculate_shortest_path(self.player.current_x, self.player.current_y, target_x, target_y)
|
||||||
|
self.auto_target_path = path
|
||||||
|
|
||||||
|
def do_auto_move(self) -> bool:
|
||||||
|
if not self.auto_target_path:
|
||||||
|
return False
|
||||||
|
|
||||||
|
target_x, target_y = self.auto_target_path.pop(0)
|
||||||
|
movement = target_x - self.player.current_x, target_y - self.player.current_y
|
||||||
|
direction = Direction(movement)
|
||||||
|
moved = self.attempt_player_movement(direction, cancel_auto_move=False)
|
||||||
|
|
||||||
|
if moved:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# We are attempting to interact with something on the path.
|
||||||
|
# First, make the player face it.
|
||||||
|
if self.player.facing != direction:
|
||||||
|
self.player.facing = direction
|
||||||
|
self.auto_target_path.insert(0, (target_x, target_y))
|
||||||
|
return True
|
||||||
|
|
||||||
|
# If we are facing it, attempt to interact with it.
|
||||||
|
changed = self.attempt_interact()
|
||||||
|
|
||||||
|
if not changed:
|
||||||
|
self.cancel_auto_move()
|
||||||
|
return False
|
||||||
|
|
||||||
|
# If the interaction was successful, and this was the end of the path, stop
|
||||||
|
# (i.e. don't try to attack the attacked enemy over and over until it's dead)
|
||||||
|
if not self.auto_target_path:
|
||||||
|
self.cancel_auto_move()
|
||||||
|
return True
|
||||||
|
|
||||||
|
# If there is more to go, keep going along the path
|
||||||
|
self.auto_target_path.insert(0, (target_x, target_y))
|
||||||
|
return True
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from .entities import (
|
|||||||
EnemyWithLoot,
|
EnemyWithLoot,
|
||||||
Entity,
|
Entity,
|
||||||
FinalBoss,
|
FinalBoss,
|
||||||
|
InteractableMixin,
|
||||||
KeyDoor,
|
KeyDoor,
|
||||||
LocationMixin,
|
LocationMixin,
|
||||||
Wall,
|
Wall,
|
||||||
@@ -23,6 +24,7 @@ from .generate_math_problem import MathProblem
|
|||||||
from .graphics import DIGIT_TO_GRAPHIC, DIGIT_TO_GRAPHIC_ZERO_EMPTY, MATH_PROBLEM_TYPE_TO_GRAPHIC, Graphic
|
from .graphics import DIGIT_TO_GRAPHIC, DIGIT_TO_GRAPHIC_ZERO_EMPTY, MATH_PROBLEM_TYPE_TO_GRAPHIC, Graphic
|
||||||
from .items import Item
|
from .items import Item
|
||||||
from .locations import DEFAULT_CONTENT, Location
|
from .locations import DEFAULT_CONTENT, Location
|
||||||
|
from .path_finding import find_path_or_closest
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .player import Player
|
from .player import Player
|
||||||
@@ -107,6 +109,21 @@ class Gameboard:
|
|||||||
|
|
||||||
return tuple(graphics)
|
return tuple(graphics)
|
||||||
|
|
||||||
|
def as_traversability_bools(self) -> tuple[tuple[bool, ...], ...]:
|
||||||
|
traversability = []
|
||||||
|
|
||||||
|
for y, row in enumerate(self.gameboard):
|
||||||
|
traversable_row = []
|
||||||
|
for x, entity in enumerate(row):
|
||||||
|
traversable_row.append(
|
||||||
|
not entity.solid
|
||||||
|
or (isinstance(entity, InteractableMixin) and entity.auto_move_attempt_passing_through)
|
||||||
|
)
|
||||||
|
|
||||||
|
traversability.append(tuple(traversable_row))
|
||||||
|
|
||||||
|
return tuple(traversability)
|
||||||
|
|
||||||
def render_math_problem(
|
def render_math_problem(
|
||||||
self, problem: MathProblem, current_input_digits: list[int], current_input_int: int | None
|
self, problem: MathProblem, current_input_digits: list[int], current_input_int: int | None
|
||||||
) -> tuple[tuple[Graphic, ...], ...]:
|
) -> tuple[tuple[Graphic, ...], ...]:
|
||||||
@@ -186,6 +203,23 @@ class Gameboard:
|
|||||||
entity = self.remote_entity_by_location_id[location]
|
entity = self.remote_entity_by_location_id[location]
|
||||||
entity.force_clear()
|
entity.force_clear()
|
||||||
|
|
||||||
|
def calculate_shortest_path(
|
||||||
|
self, source_x: int, source_y: int, target_x: int, target_y: int
|
||||||
|
) -> list[tuple[int, int]]:
|
||||||
|
gameboard_traversability = self.as_traversability_bools()
|
||||||
|
|
||||||
|
path = find_path_or_closest(gameboard_traversability, source_x, source_y, target_x, target_y)
|
||||||
|
|
||||||
|
if not path:
|
||||||
|
return path
|
||||||
|
|
||||||
|
# If the path stops just short of target, attempt interacting with it at the end
|
||||||
|
if abs(path[-1][0] - target_x) + abs(path[-1][1] - target_y) == 1:
|
||||||
|
if isinstance(self.gameboard[target_y][target_x], InteractableMixin):
|
||||||
|
path.append((target_x, target_y))
|
||||||
|
|
||||||
|
return path[1:] # Cut off starting tile
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ready(self) -> bool:
|
def ready(self) -> bool:
|
||||||
return self.content_filled
|
return self.content_filled
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from typing import NamedTuple
|
|||||||
|
|
||||||
_random = random.Random()
|
_random = random.Random()
|
||||||
|
|
||||||
|
|
||||||
class NumberChoiceConstraints(NamedTuple):
|
class NumberChoiceConstraints(NamedTuple):
|
||||||
num_1_min: int
|
num_1_min: int
|
||||||
num_1_max: int
|
num_1_max: int
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import heapq
|
||||||
|
from collections.abc import Generator
|
||||||
|
|
||||||
|
Point = tuple[int, int]
|
||||||
|
|
||||||
|
|
||||||
|
def heuristic(a: Point, b: Point) -> int:
|
||||||
|
# Manhattan distance (good for 4-directional grids)
|
||||||
|
return abs(a[0] - b[0]) + abs(a[1] - b[1])
|
||||||
|
|
||||||
|
|
||||||
|
def reconstruct_path(came_from: dict[Point, Point], current: Point) -> list[Point]:
|
||||||
|
path = [current]
|
||||||
|
while current in came_from:
|
||||||
|
current = came_from[current]
|
||||||
|
path.append(current)
|
||||||
|
path.reverse()
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def find_path_or_closest(
|
||||||
|
grid: tuple[tuple[bool, ...], ...], source_x: int, source_y: int, target_x: int, target_y: int
|
||||||
|
) -> list[Point]:
|
||||||
|
start = source_x, source_y
|
||||||
|
goal = target_x, target_y
|
||||||
|
|
||||||
|
rows, cols = len(grid), len(grid[0])
|
||||||
|
|
||||||
|
def in_bounds(p: Point) -> bool:
|
||||||
|
return 0 <= p[0] < rows and 0 <= p[1] < cols
|
||||||
|
|
||||||
|
def passable(p: Point) -> bool:
|
||||||
|
return grid[p[1]][p[0]]
|
||||||
|
|
||||||
|
def neighbors(p: Point) -> Generator[Point, None, None]:
|
||||||
|
x, y = p
|
||||||
|
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
|
||||||
|
np = (x + dx, y + dy)
|
||||||
|
if in_bounds(np) and passable(np):
|
||||||
|
yield np
|
||||||
|
|
||||||
|
open_heap: list[tuple[int, tuple[int, int]]] = []
|
||||||
|
heapq.heappush(open_heap, (0, start))
|
||||||
|
|
||||||
|
came_from: dict[Point, Point] = {}
|
||||||
|
g_score = {start: 0}
|
||||||
|
|
||||||
|
# Track best fallback node
|
||||||
|
best_node = start
|
||||||
|
best_dist = heuristic(start, goal)
|
||||||
|
|
||||||
|
visited = set()
|
||||||
|
|
||||||
|
while open_heap:
|
||||||
|
_, current = heapq.heappop(open_heap)
|
||||||
|
|
||||||
|
if current in visited:
|
||||||
|
continue
|
||||||
|
visited.add(current)
|
||||||
|
|
||||||
|
# Check if we reached the goal
|
||||||
|
if current == goal:
|
||||||
|
return reconstruct_path(came_from, current)
|
||||||
|
|
||||||
|
# Update "closest node" fallback
|
||||||
|
dist = heuristic(current, goal)
|
||||||
|
if dist < best_dist or (dist == best_dist and g_score[current] < g_score.get(best_node, float("inf"))):
|
||||||
|
best_node = current
|
||||||
|
best_dist = dist
|
||||||
|
|
||||||
|
for neighbor in neighbors(current):
|
||||||
|
tentative_g = g_score[current] + 1 # cost is 1 per move
|
||||||
|
|
||||||
|
if tentative_g < g_score.get(neighbor, float("inf")):
|
||||||
|
came_from[neighbor] = current
|
||||||
|
g_score[neighbor] = tentative_g
|
||||||
|
f_score = tentative_g + heuristic(neighbor, goal)
|
||||||
|
heapq.heappush(open_heap, (f_score, neighbor))
|
||||||
|
|
||||||
|
# Goal not reachable → return path to closest node
|
||||||
|
if best_node is not None:
|
||||||
|
return reconstruct_path(came_from, best_node)
|
||||||
|
|
||||||
|
return []
|
||||||
@@ -116,7 +116,7 @@ def versum_hill_rave(state: CollectionState, player: int, limit: bool, glitched:
|
|||||||
else:
|
else:
|
||||||
return (
|
return (
|
||||||
graffitiL(state, player, limit, 85)
|
graffitiL(state, player, limit, 85)
|
||||||
and graffitiXL(state, player, limit, 48)
|
and graffitiXL(state, player, limit, 49)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"game": "Bomb Rush Cyberfunk",
|
||||||
|
"world_version": "1.0.6",
|
||||||
|
"authors": ["TRPG"]
|
||||||
|
}
|
||||||
+105
-105
@@ -16,213 +16,213 @@ from .Locations import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_regions(world: MultiWorld, options: CCCharlesOptions, player: int) -> None:
|
def create_regions(multiworld: MultiWorld, options: CCCharlesOptions, player: int) -> None:
|
||||||
menu_region = Region("Menu", player, world, "Aranearum")
|
menu_region = Region("Menu", player, multiworld, "Aranearum")
|
||||||
world.regions.append(menu_region)
|
multiworld.regions.append(menu_region)
|
||||||
|
|
||||||
start_camp_region = Region("Start Camp", player, world)
|
start_camp_region = Region("Start Camp", player, multiworld)
|
||||||
start_camp_region.add_locations(loc_start_camp, CCCharlesLocation)
|
start_camp_region.add_locations(loc_start_camp, CCCharlesLocation)
|
||||||
world.regions.append(start_camp_region)
|
multiworld.regions.append(start_camp_region)
|
||||||
|
|
||||||
tony_tiddle_mission_region = Region("Tony Tiddle Mission", player, world)
|
tony_tiddle_mission_region = Region("Tony Tiddle Mission", player, multiworld)
|
||||||
tony_tiddle_mission_region.add_locations(loc_tony_tiddle_mission, CCCharlesLocation)
|
tony_tiddle_mission_region.add_locations(loc_tony_tiddle_mission, CCCharlesLocation)
|
||||||
world.regions.append(tony_tiddle_mission_region)
|
multiworld.regions.append(tony_tiddle_mission_region)
|
||||||
|
|
||||||
barn_region = Region("Barn", player, world)
|
barn_region = Region("Barn", player, multiworld)
|
||||||
barn_region.add_locations(loc_barn, CCCharlesLocation)
|
barn_region.add_locations(loc_barn, CCCharlesLocation)
|
||||||
world.regions.append(barn_region)
|
multiworld.regions.append(barn_region)
|
||||||
|
|
||||||
candice_mission_region = Region("Candice Mission", player, world)
|
candice_mission_region = Region("Candice Mission", player, multiworld)
|
||||||
candice_mission_region.add_locations(loc_candice_mission, CCCharlesLocation)
|
candice_mission_region.add_locations(loc_candice_mission, CCCharlesLocation)
|
||||||
world.regions.append(candice_mission_region)
|
multiworld.regions.append(candice_mission_region)
|
||||||
|
|
||||||
tutorial_house_region = Region("Tutorial House", player, world)
|
tutorial_house_region = Region("Tutorial House", player, multiworld)
|
||||||
tutorial_house_region.add_locations(loc_tutorial_house, CCCharlesLocation)
|
tutorial_house_region.add_locations(loc_tutorial_house, CCCharlesLocation)
|
||||||
world.regions.append(tutorial_house_region)
|
multiworld.regions.append(tutorial_house_region)
|
||||||
|
|
||||||
swamp_edges_region = Region("Swamp Edges", player, world)
|
swamp_edges_region = Region("Swamp Edges", player, multiworld)
|
||||||
swamp_edges_region.add_locations(loc_swamp_edges, CCCharlesLocation)
|
swamp_edges_region.add_locations(loc_swamp_edges, CCCharlesLocation)
|
||||||
world.regions.append(swamp_edges_region)
|
multiworld.regions.append(swamp_edges_region)
|
||||||
|
|
||||||
swamp_mission_region = Region("Swamp Mission", player, world)
|
swamp_mission_region = Region("Swamp Mission", player, multiworld)
|
||||||
swamp_mission_region.add_locations(loc_swamp_mission, CCCharlesLocation)
|
swamp_mission_region.add_locations(loc_swamp_mission, CCCharlesLocation)
|
||||||
world.regions.append(swamp_mission_region)
|
multiworld.regions.append(swamp_mission_region)
|
||||||
|
|
||||||
junkyard_area_region = Region("Junkyard Area", player, world)
|
junkyard_area_region = Region("Junkyard Area", player, multiworld)
|
||||||
junkyard_area_region.add_locations(loc_junkyard_area, CCCharlesLocation)
|
junkyard_area_region.add_locations(loc_junkyard_area, CCCharlesLocation)
|
||||||
world.regions.append(junkyard_area_region)
|
multiworld.regions.append(junkyard_area_region)
|
||||||
|
|
||||||
south_house_region = Region("South House", player, world)
|
south_house_region = Region("South House", player, multiworld)
|
||||||
south_house_region.add_locations(loc_south_house, CCCharlesLocation)
|
south_house_region.add_locations(loc_south_house, CCCharlesLocation)
|
||||||
world.regions.append(south_house_region)
|
multiworld.regions.append(south_house_region)
|
||||||
|
|
||||||
junkyard_shed_region = Region("Junkyard Shed", player, world)
|
junkyard_shed_region = Region("Junkyard Shed", player, multiworld)
|
||||||
junkyard_shed_region.add_locations(loc_junkyard_shed, CCCharlesLocation)
|
junkyard_shed_region.add_locations(loc_junkyard_shed, CCCharlesLocation)
|
||||||
world.regions.append(junkyard_shed_region)
|
multiworld.regions.append(junkyard_shed_region)
|
||||||
|
|
||||||
military_base_region = Region("Military Base", player, world)
|
military_base_region = Region("Military Base", player, multiworld)
|
||||||
military_base_region.add_locations(loc_military_base, CCCharlesLocation)
|
military_base_region.add_locations(loc_military_base, CCCharlesLocation)
|
||||||
world.regions.append(military_base_region)
|
multiworld.regions.append(military_base_region)
|
||||||
|
|
||||||
south_mine_outside_region = Region("South Mine Outside", player, world)
|
south_mine_outside_region = Region("South Mine Outside", player, multiworld)
|
||||||
south_mine_outside_region.add_locations(loc_south_mine_outside, CCCharlesLocation)
|
south_mine_outside_region.add_locations(loc_south_mine_outside, CCCharlesLocation)
|
||||||
world.regions.append(south_mine_outside_region)
|
multiworld.regions.append(south_mine_outside_region)
|
||||||
|
|
||||||
south_mine_inside_region = Region("South Mine Inside", player, world)
|
south_mine_inside_region = Region("South Mine Inside", player, multiworld)
|
||||||
south_mine_inside_region.add_locations(loc_south_mine_inside, CCCharlesLocation)
|
south_mine_inside_region.add_locations(loc_south_mine_inside, CCCharlesLocation)
|
||||||
world.regions.append(south_mine_inside_region)
|
multiworld.regions.append(south_mine_inside_region)
|
||||||
|
|
||||||
middle_station_region = Region("Middle Station", player, world)
|
middle_station_region = Region("Middle Station", player, multiworld)
|
||||||
middle_station_region.add_locations(loc_middle_station, CCCharlesLocation)
|
middle_station_region.add_locations(loc_middle_station, CCCharlesLocation)
|
||||||
world.regions.append(middle_station_region)
|
multiworld.regions.append(middle_station_region)
|
||||||
|
|
||||||
canyon_region = Region("Canyon", player, world)
|
canyon_region = Region("Canyon", player, multiworld)
|
||||||
canyon_region.add_locations(loc_canyon, CCCharlesLocation)
|
canyon_region.add_locations(loc_canyon, CCCharlesLocation)
|
||||||
world.regions.append(canyon_region)
|
multiworld.regions.append(canyon_region)
|
||||||
|
|
||||||
watchtower_region = Region("Watchtower", player, world)
|
watchtower_region = Region("Watchtower", player, multiworld)
|
||||||
watchtower_region.add_locations(loc_watchtower, CCCharlesLocation)
|
watchtower_region.add_locations(loc_watchtower, CCCharlesLocation)
|
||||||
world.regions.append(watchtower_region)
|
multiworld.regions.append(watchtower_region)
|
||||||
|
|
||||||
boulder_field_region = Region("Boulder Field", player, world)
|
boulder_field_region = Region("Boulder Field", player, multiworld)
|
||||||
boulder_field_region.add_locations(loc_boulder_field, CCCharlesLocation)
|
boulder_field_region.add_locations(loc_boulder_field, CCCharlesLocation)
|
||||||
world.regions.append(boulder_field_region)
|
multiworld.regions.append(boulder_field_region)
|
||||||
|
|
||||||
haunted_house_region = Region("Haunted House", player, world)
|
haunted_house_region = Region("Haunted House", player, multiworld)
|
||||||
haunted_house_region.add_locations(loc_haunted_house, CCCharlesLocation)
|
haunted_house_region.add_locations(loc_haunted_house, CCCharlesLocation)
|
||||||
world.regions.append(haunted_house_region)
|
multiworld.regions.append(haunted_house_region)
|
||||||
|
|
||||||
santiago_house_region = Region("Santiago House", player, world)
|
santiago_house_region = Region("Santiago House", player, multiworld)
|
||||||
santiago_house_region.add_locations(loc_santiago_house, CCCharlesLocation)
|
santiago_house_region.add_locations(loc_santiago_house, CCCharlesLocation)
|
||||||
world.regions.append(santiago_house_region)
|
multiworld.regions.append(santiago_house_region)
|
||||||
|
|
||||||
port_region = Region("Port", player, world)
|
port_region = Region("Port", player, multiworld)
|
||||||
port_region.add_locations(loc_port, CCCharlesLocation)
|
port_region.add_locations(loc_port, CCCharlesLocation)
|
||||||
world.regions.append(port_region)
|
multiworld.regions.append(port_region)
|
||||||
|
|
||||||
trench_house_region = Region("Trench House", player, world)
|
trench_house_region = Region("Trench House", player, multiworld)
|
||||||
trench_house_region.add_locations(loc_trench_house, CCCharlesLocation)
|
trench_house_region.add_locations(loc_trench_house, CCCharlesLocation)
|
||||||
world.regions.append(trench_house_region)
|
multiworld.regions.append(trench_house_region)
|
||||||
|
|
||||||
doll_woods_region = Region("Doll Woods", player, world)
|
doll_woods_region = Region("Doll Woods", player, multiworld)
|
||||||
doll_woods_region.add_locations(loc_doll_woods, CCCharlesLocation)
|
doll_woods_region.add_locations(loc_doll_woods, CCCharlesLocation)
|
||||||
world.regions.append(doll_woods_region)
|
multiworld.regions.append(doll_woods_region)
|
||||||
|
|
||||||
lost_stairs_region = Region("Lost Stairs", player, world)
|
lost_stairs_region = Region("Lost Stairs", player, multiworld)
|
||||||
lost_stairs_region.add_locations(loc_lost_stairs, CCCharlesLocation)
|
lost_stairs_region.add_locations(loc_lost_stairs, CCCharlesLocation)
|
||||||
world.regions.append(lost_stairs_region)
|
multiworld.regions.append(lost_stairs_region)
|
||||||
|
|
||||||
east_house_region = Region("East House", player, world)
|
east_house_region = Region("East House", player, multiworld)
|
||||||
east_house_region.add_locations(loc_east_house, CCCharlesLocation)
|
east_house_region.add_locations(loc_east_house, CCCharlesLocation)
|
||||||
world.regions.append(east_house_region)
|
multiworld.regions.append(east_house_region)
|
||||||
|
|
||||||
rockets_testing_ground_region = Region("Rockets Testing Ground", player, world)
|
rockets_testing_ground_region = Region("Rockets Testing Ground", player, multiworld)
|
||||||
rockets_testing_ground_region.add_locations(loc_rockets_testing_ground, CCCharlesLocation)
|
rockets_testing_ground_region.add_locations(loc_rockets_testing_ground, CCCharlesLocation)
|
||||||
world.regions.append(rockets_testing_ground_region)
|
multiworld.regions.append(rockets_testing_ground_region)
|
||||||
|
|
||||||
rockets_testing_bunker_region = Region("Rockets Testing Bunker", player, world)
|
rockets_testing_bunker_region = Region("Rockets Testing Bunker", player, multiworld)
|
||||||
rockets_testing_bunker_region.add_locations(loc_rockets_testing_bunker, CCCharlesLocation)
|
rockets_testing_bunker_region.add_locations(loc_rockets_testing_bunker, CCCharlesLocation)
|
||||||
world.regions.append(rockets_testing_bunker_region)
|
multiworld.regions.append(rockets_testing_bunker_region)
|
||||||
|
|
||||||
workshop_region = Region("Workshop", player, world)
|
workshop_region = Region("Workshop", player, multiworld)
|
||||||
workshop_region.add_locations(loc_workshop, CCCharlesLocation)
|
workshop_region.add_locations(loc_workshop, CCCharlesLocation)
|
||||||
world.regions.append(workshop_region)
|
multiworld.regions.append(workshop_region)
|
||||||
|
|
||||||
east_tower_region = Region("East Tower", player, world)
|
east_tower_region = Region("East Tower", player, multiworld)
|
||||||
east_tower_region.add_locations(loc_east_tower, CCCharlesLocation)
|
east_tower_region.add_locations(loc_east_tower, CCCharlesLocation)
|
||||||
world.regions.append(east_tower_region)
|
multiworld.regions.append(east_tower_region)
|
||||||
|
|
||||||
lighthouse_region = Region("Lighthouse", player, world)
|
lighthouse_region = Region("Lighthouse", player, multiworld)
|
||||||
lighthouse_region.add_locations(loc_lighthouse, CCCharlesLocation)
|
lighthouse_region.add_locations(loc_lighthouse, CCCharlesLocation)
|
||||||
world.regions.append(lighthouse_region)
|
multiworld.regions.append(lighthouse_region)
|
||||||
|
|
||||||
north_mine_outside_region = Region("North Mine Outside", player, world)
|
north_mine_outside_region = Region("North Mine Outside", player, multiworld)
|
||||||
north_mine_outside_region.add_locations(loc_north_mine_outside, CCCharlesLocation)
|
north_mine_outside_region.add_locations(loc_north_mine_outside, CCCharlesLocation)
|
||||||
world.regions.append(north_mine_outside_region)
|
multiworld.regions.append(north_mine_outside_region)
|
||||||
|
|
||||||
north_mine_inside_region = Region("North Mine Inside", player, world)
|
north_mine_inside_region = Region("North Mine Inside", player, multiworld)
|
||||||
north_mine_inside_region.add_locations(loc_north_mine_inside, CCCharlesLocation)
|
north_mine_inside_region.add_locations(loc_north_mine_inside, CCCharlesLocation)
|
||||||
world.regions.append(north_mine_inside_region)
|
multiworld.regions.append(north_mine_inside_region)
|
||||||
|
|
||||||
wood_bridge_region = Region("Wood Bridge", player, world)
|
wood_bridge_region = Region("Wood Bridge", player, multiworld)
|
||||||
wood_bridge_region.add_locations(loc_wood_bridge, CCCharlesLocation)
|
wood_bridge_region.add_locations(loc_wood_bridge, CCCharlesLocation)
|
||||||
world.regions.append(wood_bridge_region)
|
multiworld.regions.append(wood_bridge_region)
|
||||||
|
|
||||||
museum_region = Region("Museum", player, world)
|
museum_region = Region("Museum", player, multiworld)
|
||||||
museum_region.add_locations(loc_museum, CCCharlesLocation)
|
museum_region.add_locations(loc_museum, CCCharlesLocation)
|
||||||
world.regions.append(museum_region)
|
multiworld.regions.append(museum_region)
|
||||||
|
|
||||||
barbed_shelter_region = Region("Barbed Shelter", player, world)
|
barbed_shelter_region = Region("Barbed Shelter", player, multiworld)
|
||||||
barbed_shelter_region.add_locations(loc_barbed_shelter, CCCharlesLocation)
|
barbed_shelter_region.add_locations(loc_barbed_shelter, CCCharlesLocation)
|
||||||
world.regions.append(barbed_shelter_region)
|
multiworld.regions.append(barbed_shelter_region)
|
||||||
|
|
||||||
west_beach_region = Region("West Beach", player, world)
|
west_beach_region = Region("West Beach", player, multiworld)
|
||||||
west_beach_region.add_locations(loc_west_beach, CCCharlesLocation)
|
west_beach_region.add_locations(loc_west_beach, CCCharlesLocation)
|
||||||
world.regions.append(west_beach_region)
|
multiworld.regions.append(west_beach_region)
|
||||||
|
|
||||||
church_region = Region("Church", player, world)
|
church_region = Region("Church", player, multiworld)
|
||||||
church_region.add_locations(loc_church, CCCharlesLocation)
|
church_region.add_locations(loc_church, CCCharlesLocation)
|
||||||
world.regions.append(church_region)
|
multiworld.regions.append(church_region)
|
||||||
|
|
||||||
west_cottage_region = Region("West Cottage", player, world)
|
west_cottage_region = Region("West Cottage", player, multiworld)
|
||||||
west_cottage_region.add_locations(loc_west_cottage, CCCharlesLocation)
|
west_cottage_region.add_locations(loc_west_cottage, CCCharlesLocation)
|
||||||
world.regions.append(west_cottage_region)
|
multiworld.regions.append(west_cottage_region)
|
||||||
|
|
||||||
caravan_region = Region("Caravan", player, world)
|
caravan_region = Region("Caravan", player, multiworld)
|
||||||
caravan_region.add_locations(loc_caravan, CCCharlesLocation)
|
caravan_region.add_locations(loc_caravan, CCCharlesLocation)
|
||||||
world.regions.append(caravan_region)
|
multiworld.regions.append(caravan_region)
|
||||||
|
|
||||||
trailer_cabin_region = Region("Trailer Cabin", player, world)
|
trailer_cabin_region = Region("Trailer Cabin", player, multiworld)
|
||||||
trailer_cabin_region.add_locations(loc_trailer_cabin, CCCharlesLocation)
|
trailer_cabin_region.add_locations(loc_trailer_cabin, CCCharlesLocation)
|
||||||
world.regions.append(trailer_cabin_region)
|
multiworld.regions.append(trailer_cabin_region)
|
||||||
|
|
||||||
towers_region = Region("Towers", player, world)
|
towers_region = Region("Towers", player, multiworld)
|
||||||
towers_region.add_locations(loc_towers, CCCharlesLocation)
|
towers_region.add_locations(loc_towers, CCCharlesLocation)
|
||||||
world.regions.append(towers_region)
|
multiworld.regions.append(towers_region)
|
||||||
|
|
||||||
north_beach_region = Region("North beach", player, world)
|
north_beach_region = Region("North beach", player, multiworld)
|
||||||
north_beach_region.add_locations(loc_north_beach, CCCharlesLocation)
|
north_beach_region.add_locations(loc_north_beach, CCCharlesLocation)
|
||||||
world.regions.append(north_beach_region)
|
multiworld.regions.append(north_beach_region)
|
||||||
|
|
||||||
mine_shaft_region = Region("Mine Shaft", player, world)
|
mine_shaft_region = Region("Mine Shaft", player, multiworld)
|
||||||
mine_shaft_region.add_locations(loc_mine_shaft, CCCharlesLocation)
|
mine_shaft_region.add_locations(loc_mine_shaft, CCCharlesLocation)
|
||||||
world.regions.append(mine_shaft_region)
|
multiworld.regions.append(mine_shaft_region)
|
||||||
|
|
||||||
mob_camp_region = Region("Mob Camp", player, world)
|
mob_camp_region = Region("Mob Camp", player, multiworld)
|
||||||
mob_camp_region.add_locations(loc_mob_camp, CCCharlesLocation)
|
mob_camp_region.add_locations(loc_mob_camp, CCCharlesLocation)
|
||||||
world.regions.append(mob_camp_region)
|
multiworld.regions.append(mob_camp_region)
|
||||||
|
|
||||||
mob_camp_locked_room_region = Region("Mob Camp Locked Room", player, world)
|
mob_camp_locked_room_region = Region("Mob Camp Locked Room", player, multiworld)
|
||||||
mob_camp_locked_room_region.add_locations(loc_mob_camp_locked_room, CCCharlesLocation)
|
mob_camp_locked_room_region.add_locations(loc_mob_camp_locked_room, CCCharlesLocation)
|
||||||
world.regions.append(mob_camp_locked_room_region)
|
multiworld.regions.append(mob_camp_locked_room_region)
|
||||||
|
|
||||||
mine_elevator_exit_region = Region("Mine Elevator Exit", player, world)
|
mine_elevator_exit_region = Region("Mine Elevator Exit", player, multiworld)
|
||||||
mine_elevator_exit_region.add_locations(loc_mine_elevator_exit, CCCharlesLocation)
|
mine_elevator_exit_region.add_locations(loc_mine_elevator_exit, CCCharlesLocation)
|
||||||
world.regions.append(mine_elevator_exit_region)
|
multiworld.regions.append(mine_elevator_exit_region)
|
||||||
|
|
||||||
mountain_ruin_outside_region = Region("Mountain Ruin Outside", player, world)
|
mountain_ruin_outside_region = Region("Mountain Ruin Outside", player, multiworld)
|
||||||
mountain_ruin_outside_region.add_locations(loc_mountain_ruin_outside, CCCharlesLocation)
|
mountain_ruin_outside_region.add_locations(loc_mountain_ruin_outside, CCCharlesLocation)
|
||||||
world.regions.append(mountain_ruin_outside_region)
|
multiworld.regions.append(mountain_ruin_outside_region)
|
||||||
|
|
||||||
mountain_ruin_inside_region = Region("Mountain Ruin Inside", player, world)
|
mountain_ruin_inside_region = Region("Mountain Ruin Inside", player, multiworld)
|
||||||
mountain_ruin_inside_region.add_locations(loc_mountain_ruin_inside, CCCharlesLocation)
|
mountain_ruin_inside_region.add_locations(loc_mountain_ruin_inside, CCCharlesLocation)
|
||||||
world.regions.append(mountain_ruin_inside_region)
|
multiworld.regions.append(mountain_ruin_inside_region)
|
||||||
|
|
||||||
prism_temple_region = Region("Prism Temple", player, world)
|
prism_temple_region = Region("Prism Temple", player, multiworld)
|
||||||
prism_temple_region.add_locations(loc_prism_temple, CCCharlesLocation)
|
prism_temple_region.add_locations(loc_prism_temple, CCCharlesLocation)
|
||||||
world.regions.append(prism_temple_region)
|
multiworld.regions.append(prism_temple_region)
|
||||||
|
|
||||||
pickle_val_region = Region("Pickle Val", player, world)
|
pickle_val_region = Region("Pickle Val", player, multiworld)
|
||||||
pickle_val_region.add_locations(loc_pickle_val, CCCharlesLocation)
|
pickle_val_region.add_locations(loc_pickle_val, CCCharlesLocation)
|
||||||
world.regions.append(pickle_val_region)
|
multiworld.regions.append(pickle_val_region)
|
||||||
|
|
||||||
shrine_near_temple_region = Region("Shrine Near Temple", player, world)
|
shrine_near_temple_region = Region("Shrine Near Temple", player, multiworld)
|
||||||
shrine_near_temple_region.add_locations(loc_shrine_near_temple, CCCharlesLocation)
|
shrine_near_temple_region.add_locations(loc_shrine_near_temple, CCCharlesLocation)
|
||||||
world.regions.append(shrine_near_temple_region)
|
multiworld.regions.append(shrine_near_temple_region)
|
||||||
|
|
||||||
morse_bunker_region = Region("Morse Bunker", player, world)
|
morse_bunker_region = Region("Morse Bunker", player, multiworld)
|
||||||
morse_bunker_region.add_locations(loc_morse_bunker, CCCharlesLocation)
|
morse_bunker_region.add_locations(loc_morse_bunker, CCCharlesLocation)
|
||||||
world.regions.append(morse_bunker_region)
|
multiworld.regions.append(morse_bunker_region)
|
||||||
|
|
||||||
# Place "Victory" event at "Final Boss" location
|
# Place "Victory" event at "Final Boss" location
|
||||||
loc_final_boss = CCCharlesLocation(player, "Final Boss", None, prism_temple_region)
|
loc_final_boss = CCCharlesLocation(player, "Final Boss", None, prism_temple_region)
|
||||||
|
|||||||
+74
-74
@@ -4,212 +4,212 @@ from .Options import CCCharlesOptions
|
|||||||
|
|
||||||
# Go mode: Green Egg + Blue Egg + Red Egg + Temple Key + Bug Spray (+ Remote Explosive x8 but the base game ignores it)
|
# Go mode: Green Egg + Blue Egg + Red Egg + Temple Key + Bug Spray (+ Remote Explosive x8 but the base game ignores it)
|
||||||
|
|
||||||
def set_rules(world: MultiWorld, options: CCCharlesOptions, player: int) -> None:
|
def set_rules(multiworld: MultiWorld, options: CCCharlesOptions, player: int) -> None:
|
||||||
# Tony Tiddle
|
# Tony Tiddle
|
||||||
set_rule(world.get_entrance("Barn Door", player),
|
set_rule(multiworld.get_entrance("Barn Door", player),
|
||||||
lambda state: state.has("Barn Key", player))
|
lambda state: state.has("Barn Key", player))
|
||||||
|
|
||||||
# Candice
|
# Candice
|
||||||
set_rule(world.get_entrance("Tutorial House Door", player),
|
set_rule(multiworld.get_entrance("Tutorial House Door", player),
|
||||||
lambda state: state.has("Candice's Key", player))
|
lambda state: state.has("Candice's Key", player))
|
||||||
|
|
||||||
# Lizbeth Murkwater
|
# Lizbeth Murkwater
|
||||||
set_rule(world.get_location("Swamp Lizbeth Murkwater Mission End", player),
|
set_rule(multiworld.get_location("Swamp Lizbeth Murkwater Mission End", player),
|
||||||
lambda state: state.has("Dead Fish", player))
|
lambda state: state.has("Dead Fish", player))
|
||||||
|
|
||||||
# Daryl
|
# Daryl
|
||||||
set_rule(world.get_location("Junkyard Area Chest Ancient Tablet", player),
|
set_rule(multiworld.get_location("Junkyard Area Chest Ancient Tablet", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Junkyard Area Daryl Mission End", player),
|
set_rule(multiworld.get_location("Junkyard Area Daryl Mission End", player),
|
||||||
lambda state: state.has("Ancient Tablet", player))
|
lambda state: state.has("Ancient Tablet", player))
|
||||||
|
|
||||||
# South House
|
# South House
|
||||||
set_rule(world.get_location("South House Chest Scraps 1", player),
|
set_rule(multiworld.get_location("South House Chest Scraps 1", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("South House Chest Scraps 2", player),
|
set_rule(multiworld.get_location("South House Chest Scraps 2", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("South House Chest Scraps 3", player),
|
set_rule(multiworld.get_location("South House Chest Scraps 3", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("South House Chest Scraps 4", player),
|
set_rule(multiworld.get_location("South House Chest Scraps 4", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("South House Chest Scraps 5", player),
|
set_rule(multiworld.get_location("South House Chest Scraps 5", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("South House Chest Scraps 6", player),
|
set_rule(multiworld.get_location("South House Chest Scraps 6", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# South Mine
|
# South Mine
|
||||||
set_rule(world.get_entrance("South Mine Gate", player),
|
set_rule(multiworld.get_entrance("South Mine Gate", player),
|
||||||
lambda state: state.has("South Mine Key", player))
|
lambda state: state.has("South Mine Key", player))
|
||||||
|
|
||||||
set_rule(world.get_location("South Mine Inside Green Paint Can", player),
|
set_rule(multiworld.get_location("South Mine Inside Green Paint Can", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Theodore
|
# Theodore
|
||||||
set_rule(world.get_location("Middle Station Theodore Mission End", player),
|
set_rule(multiworld.get_location("Middle Station Theodore Mission End", player),
|
||||||
lambda state: state.has("Blue Box", player))
|
lambda state: state.has("Blue Box", player))
|
||||||
|
|
||||||
# Watchtower
|
# Watchtower
|
||||||
set_rule(world.get_location("Watchtower Pink Paint Can", player),
|
set_rule(multiworld.get_location("Watchtower Pink Paint Can", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Sasha
|
# Sasha
|
||||||
set_rule(world.get_location("Haunted House Sasha Mission End", player),
|
set_rule(multiworld.get_location("Haunted House Sasha Mission End", player),
|
||||||
lambda state: state.has("Page Drawing", player, 8))
|
lambda state: state.has("Page Drawing", player, 8))
|
||||||
|
|
||||||
# Santiago
|
# Santiago
|
||||||
set_rule(world.get_location("Port Santiago Mission End", player),
|
set_rule(multiworld.get_location("Port Santiago Mission End", player),
|
||||||
lambda state: state.has("Journal", player))
|
lambda state: state.has("Journal", player))
|
||||||
|
|
||||||
# Trench House
|
# Trench House
|
||||||
set_rule(world.get_location("Trench House Chest Scraps 1", player),
|
set_rule(multiworld.get_location("Trench House Chest Scraps 1", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Trench House Chest Scraps 2", player),
|
set_rule(multiworld.get_location("Trench House Chest Scraps 2", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Trench House Chest Scraps 3", player),
|
set_rule(multiworld.get_location("Trench House Chest Scraps 3", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Trench House Chest Scraps 4", player),
|
set_rule(multiworld.get_location("Trench House Chest Scraps 4", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Trench House Chest Scraps 5", player),
|
set_rule(multiworld.get_location("Trench House Chest Scraps 5", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Trench House Chest Scraps 6", player),
|
set_rule(multiworld.get_location("Trench House Chest Scraps 6", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# East House
|
# East House
|
||||||
set_rule(world.get_location("East House Chest Scraps 1", player),
|
set_rule(multiworld.get_location("East House Chest Scraps 1", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("East House Chest Scraps 2", player),
|
set_rule(multiworld.get_location("East House Chest Scraps 2", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("East House Chest Scraps 3", player),
|
set_rule(multiworld.get_location("East House Chest Scraps 3", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("East House Chest Scraps 4", player),
|
set_rule(multiworld.get_location("East House Chest Scraps 4", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("East House Chest Scraps 5", player),
|
set_rule(multiworld.get_location("East House Chest Scraps 5", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Rocket Testing Bunker
|
# Rocket Testing Bunker
|
||||||
set_rule(world.get_entrance("Stuck Bunker Door", player),
|
set_rule(multiworld.get_entrance("Stuck Bunker Door", player),
|
||||||
lambda state: state.has("Timed Dynamite", player))
|
lambda state: state.has("Timed Dynamite", player))
|
||||||
|
|
||||||
# John Smith
|
# John Smith
|
||||||
set_rule(world.get_location("Workshop John Smith Mission End", player),
|
set_rule(multiworld.get_location("Workshop John Smith Mission End", player),
|
||||||
lambda state: state.has("Box of Rockets", player))
|
lambda state: state.has("Box of Rockets", player))
|
||||||
|
|
||||||
# Claire
|
# Claire
|
||||||
set_rule(world.get_location("Lighthouse Claire Mission End", player),
|
set_rule(multiworld.get_location("Lighthouse Claire Mission End", player),
|
||||||
lambda state: state.has("Breaker", player, 4))
|
lambda state: state.has("Breaker", player, 4))
|
||||||
|
|
||||||
# North Mine
|
# North Mine
|
||||||
set_rule(world.get_entrance("North Mine Gate", player),
|
set_rule(multiworld.get_entrance("North Mine Gate", player),
|
||||||
lambda state: state.has("North Mine Key", player))
|
lambda state: state.has("North Mine Key", player))
|
||||||
|
|
||||||
set_rule(world.get_location("North Mine Inside Blue Paint Can", player),
|
set_rule(multiworld.get_location("North Mine Inside Blue Paint Can", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Paul
|
# Paul
|
||||||
set_rule(world.get_location("Museum Paul Mission End", player),
|
set_rule(multiworld.get_location("Museum Paul Mission End", player),
|
||||||
lambda state: state.has("Remote Explosive x8", player))
|
lambda state: state.has("Remote Explosive x8", player))
|
||||||
# lambda state: state.has("Remote Explosive", player, 8)) # TODO: Add an option to split remote explosives
|
# lambda state: state.has("Remote Explosive", player, 8)) # TODO: Add an option to split remote explosives
|
||||||
|
|
||||||
# West Beach
|
# West Beach
|
||||||
set_rule(world.get_location("West Beach Chest Scraps 1", player),
|
set_rule(multiworld.get_location("West Beach Chest Scraps 1", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("West Beach Chest Scraps 2", player),
|
set_rule(multiworld.get_location("West Beach Chest Scraps 2", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("West Beach Chest Scraps 3", player),
|
set_rule(multiworld.get_location("West Beach Chest Scraps 3", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("West Beach Chest Scraps 4", player),
|
set_rule(multiworld.get_location("West Beach Chest Scraps 4", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("West Beach Chest Scraps 5", player),
|
set_rule(multiworld.get_location("West Beach Chest Scraps 5", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("West Beach Chest Scraps 6", player),
|
set_rule(multiworld.get_location("West Beach Chest Scraps 6", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Caravan
|
# Caravan
|
||||||
set_rule(world.get_location("Caravan Chest Scraps 1", player),
|
set_rule(multiworld.get_location("Caravan Chest Scraps 1", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Caravan Chest Scraps 2", player),
|
set_rule(multiworld.get_location("Caravan Chest Scraps 2", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Caravan Chest Scraps 3", player),
|
set_rule(multiworld.get_location("Caravan Chest Scraps 3", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Caravan Chest Scraps 4", player),
|
set_rule(multiworld.get_location("Caravan Chest Scraps 4", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Caravan Chest Scraps 5", player),
|
set_rule(multiworld.get_location("Caravan Chest Scraps 5", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Ronny
|
# Ronny
|
||||||
set_rule(world.get_location("Towers Ronny Mission End", player),
|
set_rule(multiworld.get_location("Towers Ronny Mission End", player),
|
||||||
lambda state: state.has("Employment Contracts", player))
|
lambda state: state.has("Employment Contracts", player))
|
||||||
|
|
||||||
# North Beach
|
# North Beach
|
||||||
set_rule(world.get_location("North Beach Chest Scraps 1", player),
|
set_rule(multiworld.get_location("North Beach Chest Scraps 1", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("North Beach Chest Scraps 2", player),
|
set_rule(multiworld.get_location("North Beach Chest Scraps 2", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("North Beach Chest Scraps 3", player),
|
set_rule(multiworld.get_location("North Beach Chest Scraps 3", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("North Beach Chest Scraps 4", player),
|
set_rule(multiworld.get_location("North Beach Chest Scraps 4", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Mine Shaft
|
# Mine Shaft
|
||||||
set_rule(world.get_location("Mine Shaft Chest Scraps 1", player),
|
set_rule(multiworld.get_location("Mine Shaft Chest Scraps 1", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Mine Shaft Chest Scraps 2", player),
|
set_rule(multiworld.get_location("Mine Shaft Chest Scraps 2", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Mine Shaft Chest Scraps 3", player),
|
set_rule(multiworld.get_location("Mine Shaft Chest Scraps 3", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Mine Shaft Chest Scraps 4", player),
|
set_rule(multiworld.get_location("Mine Shaft Chest Scraps 4", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Mine Shaft Chest Scraps 5", player),
|
set_rule(multiworld.get_location("Mine Shaft Chest Scraps 5", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Mine Shaft Chest Scraps 6", player),
|
set_rule(multiworld.get_location("Mine Shaft Chest Scraps 6", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Mine Shaft Chest Scraps 7", player),
|
set_rule(multiworld.get_location("Mine Shaft Chest Scraps 7", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Mob Camp
|
# Mob Camp
|
||||||
set_rule(world.get_entrance("Mob Camp Locked Door", player),
|
set_rule(multiworld.get_entrance("Mob Camp Locked Door", player),
|
||||||
lambda state: state.has("Mob Camp Key", player))
|
lambda state: state.has("Mob Camp Key", player))
|
||||||
|
|
||||||
set_rule(world.get_location("Mob Camp Locked Room Stolen Bob", player),
|
set_rule(multiworld.get_location("Mob Camp Locked Room Stolen Bob", player),
|
||||||
lambda state: state.has("Broken Bob", player))
|
lambda state: state.has("Broken Bob", player))
|
||||||
|
|
||||||
# Mountain Ruin
|
# Mountain Ruin
|
||||||
set_rule(world.get_entrance("Mountain Ruin Gate", player),
|
set_rule(multiworld.get_entrance("Mountain Ruin Gate", player),
|
||||||
lambda state: state.has("Mountain Ruin Key", player))
|
lambda state: state.has("Mountain Ruin Key", player))
|
||||||
|
|
||||||
set_rule(world.get_location("Mountain Ruin Inside Red Paint Can", player),
|
set_rule(multiworld.get_location("Mountain Ruin Inside Red Paint Can", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Prism Temple
|
# Prism Temple
|
||||||
set_rule(world.get_location("Prism Temple Chest Scraps 1", player),
|
set_rule(multiworld.get_location("Prism Temple Chest Scraps 1", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Prism Temple Chest Scraps 2", player),
|
set_rule(multiworld.get_location("Prism Temple Chest Scraps 2", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Prism Temple Chest Scraps 3", player),
|
set_rule(multiworld.get_location("Prism Temple Chest Scraps 3", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Pickle Lady
|
# Pickle Lady
|
||||||
set_rule(world.get_location("Pickle Val Jar of Pickles", player),
|
set_rule(multiworld.get_location("Pickle Val Jar of Pickles", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Pickle Val Pickle Lady Mission End", player),
|
set_rule(multiworld.get_location("Pickle Val Pickle Lady Mission End", player),
|
||||||
lambda state: state.has("Jar of Pickles", player))
|
lambda state: state.has("Jar of Pickles", player))
|
||||||
|
|
||||||
# Morse Bunker
|
# Morse Bunker
|
||||||
set_rule(world.get_location("Morse Bunker Chest Scraps 1", player),
|
set_rule(multiworld.get_location("Morse Bunker Chest Scraps 1", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Morse Bunker Chest Scraps 2", player),
|
set_rule(multiworld.get_location("Morse Bunker Chest Scraps 2", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Morse Bunker Chest Scraps 3", player),
|
set_rule(multiworld.get_location("Morse Bunker Chest Scraps 3", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Morse Bunker Chest Scraps 4", player),
|
set_rule(multiworld.get_location("Morse Bunker Chest Scraps 4", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
set_rule(world.get_location("Morse Bunker Chest Scraps 5", player),
|
set_rule(multiworld.get_location("Morse Bunker Chest Scraps 5", player),
|
||||||
lambda state: state.has("Lockpicks", player))
|
lambda state: state.has("Lockpicks", player))
|
||||||
|
|
||||||
# Add rules to reach the "Go mode"
|
# Add rules to reach the "Go mode"
|
||||||
set_rule(world.get_location("Final Boss", player),
|
set_rule(multiworld.get_location("Final Boss", player),
|
||||||
lambda state: state.has("Temple Key", player)
|
lambda state: state.has("Temple Key", player)
|
||||||
and state.has("Green Egg", player)
|
and state.has("Green Egg", player)
|
||||||
and state.has("Blue Egg", player)
|
and state.has("Blue Egg", player)
|
||||||
and state.has("Red Egg", player))
|
and state.has("Red Egg", player))
|
||||||
world.completion_condition[player] = lambda state: state.has("Victory", player)
|
multiworld.completion_condition[player] = lambda state: state.has("Victory", player)
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
# Donkey Kong Country 3 - Changelog
|
|
||||||
|
|
||||||
|
|
||||||
## v1.1
|
|
||||||
|
|
||||||
### Features:
|
|
||||||
|
|
||||||
- KONGsanity option (Collect all KONG letters in each level for a check)
|
|
||||||
- Autosave option
|
|
||||||
- Difficulty option
|
|
||||||
- MERRY option
|
|
||||||
- Handle collected/co-op locations
|
|
||||||
|
|
||||||
### Bug Fixes:
|
|
||||||
|
|
||||||
- Fixed Mekanos softlock
|
|
||||||
- Prevent Brothers Bear giving extra Banana Birds
|
|
||||||
- Fixed Banana Bird Mother check sending prematurely
|
|
||||||
- Fix Logic bug with Krematoa level costs
|
|
||||||
|
|
||||||
|
|
||||||
## v1.0
|
|
||||||
|
|
||||||
### Features:
|
|
||||||
|
|
||||||
- Goal
|
|
||||||
- Knautilus
|
|
||||||
- Scuttle the Knautilus in Krematoa and defeat Baron K. Roolenstein to win
|
|
||||||
- Banana Bird Hunt
|
|
||||||
- Find the Banana Birds and rescue their mother to win
|
|
||||||
- Locations included:
|
|
||||||
- Level Flags
|
|
||||||
- Bonuses
|
|
||||||
- DK Coins
|
|
||||||
- Banana Bird Caves
|
|
||||||
- Items included:
|
|
||||||
- Progressive Boat Upgrade
|
|
||||||
- Three are placed into the item pool (Patch -> First Ski -> Second Ski)
|
|
||||||
- Bonus Coins
|
|
||||||
- DK Coins
|
|
||||||
- Krematoa Cogs
|
|
||||||
- Bear Coins
|
|
||||||
- 1-Up Balloons
|
|
||||||
- Level Shuffle is supported
|
|
||||||
- Music Shuffle is supported
|
|
||||||
- Kong Palette options are supported
|
|
||||||
- Starting life count can be set
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
import logging
|
|
||||||
|
|
||||||
from NetUtils import ClientStatus, color
|
|
||||||
from worlds.AutoSNIClient import SNIClient
|
|
||||||
|
|
||||||
snes_logger = logging.getLogger("SNES")
|
|
||||||
|
|
||||||
# FXPAK Pro protocol memory mapping used by SNI
|
|
||||||
ROM_START = 0x000000
|
|
||||||
WRAM_START = 0xF50000
|
|
||||||
WRAM_SIZE = 0x20000
|
|
||||||
SRAM_START = 0xE00000
|
|
||||||
|
|
||||||
DKC3_ROMNAME_START = 0x00FFC0
|
|
||||||
DKC3_ROMHASH_START = 0x7FC0
|
|
||||||
ROMNAME_SIZE = 0x15
|
|
||||||
ROMHASH_SIZE = 0x15
|
|
||||||
|
|
||||||
DKC3_RECV_PROGRESS_ADDR = WRAM_START + 0x632
|
|
||||||
DKC3_FILE_NAME_ADDR = WRAM_START + 0x5D9
|
|
||||||
DEATH_LINK_ACTIVE_ADDR = DKC3_ROMNAME_START + 0x15 # DKC3_TODO: Find a permanent home for this
|
|
||||||
|
|
||||||
|
|
||||||
class DKC3SNIClient(SNIClient):
|
|
||||||
game = "Donkey Kong Country 3"
|
|
||||||
patch_suffix = ".apdkc3"
|
|
||||||
|
|
||||||
async def deathlink_kill_player(self, ctx):
|
|
||||||
pass
|
|
||||||
# DKC3_TODO: Handle Receiving Deathlink
|
|
||||||
|
|
||||||
|
|
||||||
async def validate_rom(self, ctx):
|
|
||||||
from SNIClient import snes_read
|
|
||||||
|
|
||||||
rom_name = await snes_read(ctx, DKC3_ROMHASH_START, ROMHASH_SIZE)
|
|
||||||
if rom_name is None or rom_name == bytes([0] * ROMHASH_SIZE) or rom_name[:2] != b"D3":
|
|
||||||
return False
|
|
||||||
|
|
||||||
ctx.game = self.game
|
|
||||||
ctx.items_handling = 0b111 # remote items
|
|
||||||
|
|
||||||
ctx.rom = rom_name
|
|
||||||
|
|
||||||
#death_link = await snes_read(ctx, DEATH_LINK_ACTIVE_ADDR, 1)
|
|
||||||
## DKC3_TODO: Handle Deathlink
|
|
||||||
#if death_link:
|
|
||||||
# ctx.allow_collect = bool(death_link[0] & 0b100)
|
|
||||||
# await ctx.update_death_link(bool(death_link[0] & 0b1))
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
async def game_watcher(self, ctx):
|
|
||||||
from SNIClient import snes_buffered_write, snes_flush_writes, snes_read
|
|
||||||
# DKC3_TODO: Handle Deathlink
|
|
||||||
save_file_name = await snes_read(ctx, DKC3_FILE_NAME_ADDR, 0x5)
|
|
||||||
if save_file_name is None or save_file_name[0] == 0x00 or save_file_name == bytes([0x55] * 0x05):
|
|
||||||
# We haven't loaded a save file
|
|
||||||
return
|
|
||||||
|
|
||||||
new_checks = []
|
|
||||||
from .Rom import location_rom_data, item_rom_data, boss_location_ids, level_unlock_map
|
|
||||||
location_ram_data = await snes_read(ctx, WRAM_START + 0x5FE, 0x81)
|
|
||||||
for loc_id, loc_data in location_rom_data.items():
|
|
||||||
if loc_id not in ctx.locations_checked:
|
|
||||||
data = location_ram_data[loc_data[0] - 0x5FE]
|
|
||||||
masked_data = data & (1 << loc_data[1])
|
|
||||||
bit_set = (masked_data != 0)
|
|
||||||
invert_bit = ((len(loc_data) >= 3) and loc_data[2])
|
|
||||||
if bit_set != invert_bit:
|
|
||||||
# DKC3_TODO: Handle non-included checks
|
|
||||||
new_checks.append(loc_id)
|
|
||||||
|
|
||||||
verify_save_file_name = await snes_read(ctx, DKC3_FILE_NAME_ADDR, 0x5)
|
|
||||||
if verify_save_file_name is None or verify_save_file_name[0] == 0x00 or verify_save_file_name == bytes([0x55] * 0x05) or verify_save_file_name != save_file_name:
|
|
||||||
# We have somehow exited the save file (or worse)
|
|
||||||
ctx.rom = None
|
|
||||||
return
|
|
||||||
|
|
||||||
rom = await snes_read(ctx, DKC3_ROMHASH_START, ROMHASH_SIZE)
|
|
||||||
if rom != ctx.rom:
|
|
||||||
ctx.rom = None
|
|
||||||
# We have somehow loaded a different ROM
|
|
||||||
return
|
|
||||||
|
|
||||||
for new_check_id in new_checks:
|
|
||||||
ctx.locations_checked.add(new_check_id)
|
|
||||||
location = ctx.location_names.lookup_in_game(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]}])
|
|
||||||
|
|
||||||
# DKC3_TODO: Make this actually visually display new things received (ASM Hook required)
|
|
||||||
recv_count = await snes_read(ctx, DKC3_RECV_PROGRESS_ADDR, 1)
|
|
||||||
recv_index = recv_count[0]
|
|
||||||
|
|
||||||
if recv_index < len(ctx.items_received):
|
|
||||||
item = ctx.items_received[recv_index]
|
|
||||||
recv_index += 1
|
|
||||||
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
|
|
||||||
color(ctx.item_names.lookup_in_game(item.item), 'red', 'bold'),
|
|
||||||
color(ctx.player_names[item.player], 'yellow'),
|
|
||||||
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:
|
|
||||||
item_count = await snes_read(ctx, WRAM_START + item_rom_data[item.item][0], 0x1)
|
|
||||||
new_item_count = item_count[0] + 1
|
|
||||||
for address in item_rom_data[item.item]:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + address, bytes([new_item_count]))
|
|
||||||
|
|
||||||
# Handle Coin Displays
|
|
||||||
current_level = await snes_read(ctx, WRAM_START + 0x5E3, 0x5)
|
|
||||||
overworld_locked = ((await snes_read(ctx, WRAM_START + 0x5FC, 0x1))[0] == 0x01)
|
|
||||||
if item.item == 0xDC3002 and not overworld_locked and (current_level[0] == 0x0A and current_level[2] == 0x00 and current_level[4] == 0x03):
|
|
||||||
# Bazaar and Barter
|
|
||||||
item_count = await snes_read(ctx, WRAM_START + 0xB02, 0x1)
|
|
||||||
new_item_count = item_count[0] + 1
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0xB02, bytes([new_item_count]))
|
|
||||||
elif item.item == 0xDC3002 and not overworld_locked and current_level[0] == 0x04:
|
|
||||||
# Swanky
|
|
||||||
item_count = await snes_read(ctx, WRAM_START + 0xA26, 0x1)
|
|
||||||
new_item_count = item_count[0] + 1
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0xA26, bytes([new_item_count]))
|
|
||||||
elif item.item == 0xDC3003 and not overworld_locked and (current_level[0] == 0x0A and current_level[2] == 0x08 and current_level[4] == 0x01):
|
|
||||||
# Boomer
|
|
||||||
item_count = await snes_read(ctx, WRAM_START + 0xB02, 0x1)
|
|
||||||
new_item_count = item_count[0] + 1
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0xB02, bytes([new_item_count]))
|
|
||||||
else:
|
|
||||||
# Handle Patch and Skis
|
|
||||||
if item.item == 0xDC3007:
|
|
||||||
num_upgrades = 1
|
|
||||||
inventory = await snes_read(ctx, WRAM_START + 0x605, 0xF)
|
|
||||||
|
|
||||||
if (inventory[0] & 0x02):
|
|
||||||
num_upgrades = 3
|
|
||||||
elif (inventory[13] & 0x08) or (inventory[0] & 0x01):
|
|
||||||
num_upgrades = 2
|
|
||||||
|
|
||||||
if num_upgrades == 1:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x605, bytes([inventory[0] | 0x01]))
|
|
||||||
if inventory[4] == 0:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x609, bytes([0x01]))
|
|
||||||
elif inventory[6] == 0:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x60B, bytes([0x01]))
|
|
||||||
elif inventory[8] == 0:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x60D, bytes([0x01]))
|
|
||||||
elif inventory[10] == 0:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x60F, bytes([0x01]))
|
|
||||||
|
|
||||||
cove_mekanos_progress = await snes_read(ctx, WRAM_START + 0x691, 0x2)
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x691, bytes([cove_mekanos_progress[0] | 0x01]))
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x692, bytes([cove_mekanos_progress[1] | 0x01]))
|
|
||||||
elif num_upgrades == 2:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x605, bytes([inventory[0] | 0x02]))
|
|
||||||
if inventory[4] == 0:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x609, bytes([0x02]))
|
|
||||||
elif inventory[6] == 0:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x60B, bytes([0x02]))
|
|
||||||
elif inventory[8] == 0:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x60D, bytes([0x02]))
|
|
||||||
elif inventory[10] == 0:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x60F, bytes([0x02]))
|
|
||||||
elif num_upgrades == 3:
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x606, bytes([inventory[1] | 0x20]))
|
|
||||||
|
|
||||||
k3_ridge_progress = await snes_read(ctx, WRAM_START + 0x693, 0x2)
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x693, bytes([k3_ridge_progress[0] | 0x01]))
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0x694, bytes([k3_ridge_progress[1] | 0x01]))
|
|
||||||
elif item.item == 0xDC3000:
|
|
||||||
# Handle Victory
|
|
||||||
if not ctx.finished_game:
|
|
||||||
await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}])
|
|
||||||
ctx.finished_game = True
|
|
||||||
else:
|
|
||||||
print("Item Not Recognized: ", item.item)
|
|
||||||
pass
|
|
||||||
|
|
||||||
await snes_flush_writes(ctx)
|
|
||||||
|
|
||||||
# Handle Collected Locations
|
|
||||||
levels_to_tiles = await snes_read(ctx, ROM_START + 0x3FF800, 0x60)
|
|
||||||
tiles_to_levels = await snes_read(ctx, ROM_START + 0x3FF860, 0x60)
|
|
||||||
for loc_id in ctx.checked_locations:
|
|
||||||
if loc_id not in ctx.locations_checked and loc_id not in boss_location_ids:
|
|
||||||
loc_data = location_rom_data[loc_id]
|
|
||||||
data = await snes_read(ctx, WRAM_START + loc_data[0], 1)
|
|
||||||
invert_bit = ((len(loc_data) >= 3) and loc_data[2])
|
|
||||||
if not invert_bit:
|
|
||||||
masked_data = data[0] | (1 << loc_data[1])
|
|
||||||
snes_buffered_write(ctx, WRAM_START + loc_data[0], bytes([masked_data]))
|
|
||||||
|
|
||||||
if (loc_data[1] == 1):
|
|
||||||
# Make the next levels accessible
|
|
||||||
level_id = loc_data[0] - 0x632
|
|
||||||
tile_id = levels_to_tiles[level_id] if levels_to_tiles[level_id] != 0xFF else level_id
|
|
||||||
tile_id = tile_id + 0x632
|
|
||||||
if tile_id in level_unlock_map:
|
|
||||||
for next_level_address in level_unlock_map[tile_id]:
|
|
||||||
next_level_id = next_level_address - 0x632
|
|
||||||
next_tile_id = tiles_to_levels[next_level_id] if tiles_to_levels[next_level_id] != 0xFF else next_level_id
|
|
||||||
next_tile_id = next_tile_id + 0x632
|
|
||||||
next_data = await snes_read(ctx, WRAM_START + next_tile_id, 1)
|
|
||||||
snes_buffered_write(ctx, WRAM_START + next_tile_id, bytes([next_data[0] | 0x01]))
|
|
||||||
|
|
||||||
await snes_flush_writes(ctx)
|
|
||||||
else:
|
|
||||||
masked_data = data[0] & ~(1 << loc_data[1])
|
|
||||||
snes_buffered_write(ctx, WRAM_START + loc_data[0], bytes([masked_data]))
|
|
||||||
await snes_flush_writes(ctx)
|
|
||||||
ctx.locations_checked.add(loc_id)
|
|
||||||
|
|
||||||
# Calculate Boomer Cost Text
|
|
||||||
boomer_cost_text = await snes_read(ctx, WRAM_START + 0xAAFD, 2)
|
|
||||||
if boomer_cost_text[0] == 0x31 and boomer_cost_text[1] == 0x35:
|
|
||||||
boomer_cost = await snes_read(ctx, ROM_START + 0x349857, 1)
|
|
||||||
boomer_cost_tens = int(boomer_cost[0]) // 10
|
|
||||||
boomer_cost_ones = int(boomer_cost[0]) % 10
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0xAAFD, bytes([0x30 + boomer_cost_tens, 0x30 + boomer_cost_ones]))
|
|
||||||
await snes_flush_writes(ctx)
|
|
||||||
|
|
||||||
boomer_final_cost_text = await snes_read(ctx, WRAM_START + 0xAB9B, 2)
|
|
||||||
if boomer_final_cost_text[0] == 0x32 and boomer_final_cost_text[1] == 0x35:
|
|
||||||
boomer_cost = await snes_read(ctx, ROM_START + 0x349857, 1)
|
|
||||||
boomer_cost_tens = boomer_cost[0] // 10
|
|
||||||
boomer_cost_ones = boomer_cost[0] % 10
|
|
||||||
snes_buffered_write(ctx, WRAM_START + 0xAB9B, bytes([0x30 + boomer_cost_tens, 0x30 + boomer_cost_ones]))
|
|
||||||
await snes_flush_writes(ctx)
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import typing
|
|
||||||
|
|
||||||
from BaseClasses import Item
|
|
||||||
from .Names import ItemName
|
|
||||||
|
|
||||||
|
|
||||||
class ItemData(typing.NamedTuple):
|
|
||||||
code: typing.Optional[int]
|
|
||||||
progression: bool
|
|
||||||
quantity: int = 1
|
|
||||||
event: bool = False
|
|
||||||
|
|
||||||
|
|
||||||
class DKC3Item(Item):
|
|
||||||
game: str = "Donkey Kong Country 3"
|
|
||||||
|
|
||||||
|
|
||||||
# Separate tables for each type of item.
|
|
||||||
junk_table = {
|
|
||||||
ItemName.one_up_balloon: ItemData(0xDC3001, False),
|
|
||||||
ItemName.bear_coin: ItemData(0xDC3002, False),
|
|
||||||
}
|
|
||||||
|
|
||||||
collectable_table = {
|
|
||||||
ItemName.bonus_coin: ItemData(0xDC3003, True),
|
|
||||||
ItemName.dk_coin: ItemData(0xDC3004, True),
|
|
||||||
ItemName.banana_bird: ItemData(0xDC3005, True),
|
|
||||||
ItemName.krematoa_cog: ItemData(0xDC3006, True),
|
|
||||||
ItemName.progressive_boat: ItemData(0xDC3007, True),
|
|
||||||
}
|
|
||||||
|
|
||||||
inventory_table = {
|
|
||||||
ItemName.present: ItemData(0xDC3008, True),
|
|
||||||
ItemName.bowling_ball: ItemData(0xDC3009, True),
|
|
||||||
ItemName.shell: ItemData(0xDC300A, True),
|
|
||||||
ItemName.mirror: ItemData(0xDC300B, True),
|
|
||||||
ItemName.flower: ItemData(0xDC300C, True),
|
|
||||||
ItemName.wrench: ItemData(0xDC300D, True),
|
|
||||||
}
|
|
||||||
|
|
||||||
event_table = {
|
|
||||||
ItemName.victory: ItemData(0xDC3000, True),
|
|
||||||
}
|
|
||||||
|
|
||||||
# Complete item table.
|
|
||||||
item_table = {
|
|
||||||
**junk_table,
|
|
||||||
**collectable_table,
|
|
||||||
**event_table,
|
|
||||||
}
|
|
||||||
|
|
||||||
lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_table.items() if data.code}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
Modified MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2025 PoryGone
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, and/or distribute copies of the Software,
|
|
||||||
and to permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
No copy or substantial portion of the Software shall be sublicensed or relicensed
|
|
||||||
without the express written permission of the copyright holder(s)
|
|
||||||
|
|
||||||
No copy or substantial portion of the Software shall be sold without the express
|
|
||||||
written permission of the copyright holder(s)
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
|
|
||||||
from .Names import LocationName
|
|
||||||
|
|
||||||
class DKC3Level():
|
|
||||||
nameIDAddress: int
|
|
||||||
levelIDAddress: int
|
|
||||||
nameID: int
|
|
||||||
levelID: int
|
|
||||||
|
|
||||||
def __init__(self, nameIDAddress: int, levelIDAddress: int, nameID: int, levelID: int):
|
|
||||||
self.nameIDAddress = nameIDAddress
|
|
||||||
self.levelIDAddress = levelIDAddress
|
|
||||||
self.nameID = nameID
|
|
||||||
self.levelID = levelID
|
|
||||||
|
|
||||||
|
|
||||||
level_dict = {
|
|
||||||
LocationName.lakeside_limbo_region: DKC3Level(0x34D19C, 0x34D19D, 0x01, 0x25),
|
|
||||||
LocationName.doorstop_dash_region: DKC3Level(0x34D1A7, 0x34D1A8, 0x02, 0x28),
|
|
||||||
LocationName.tidal_trouble_region: DKC3Level(0x34D1BD, 0x34D1BE, 0x04, 0x27),
|
|
||||||
LocationName.skiddas_row_region: DKC3Level(0x34D1C8, 0x34D1C9, 0x05, 0x2B),
|
|
||||||
LocationName.murky_mill_region: DKC3Level(0x34D1D3, 0x34D1D4, 0x0D, 0x2A),
|
|
||||||
|
|
||||||
LocationName.barrel_shield_bust_up_region: DKC3Level(0x34D217, 0x34D218, 0x0B, 0x30),
|
|
||||||
LocationName.riverside_race_region: DKC3Level(0x34D22D, 0x34D22E, 0x0C, 0x32),
|
|
||||||
LocationName.squeals_on_wheels_region: DKC3Level(0x34D238, 0x34D239, 0x06, 0x29),
|
|
||||||
LocationName.springin_spiders_region: DKC3Level(0x34D24E, 0x34D24F, 0x0E, 0x2F),
|
|
||||||
LocationName.bobbing_barrel_brawl_region: DKC3Level(0x34D264, 0x34D265, 0x37, 0x34),
|
|
||||||
|
|
||||||
LocationName.bazzas_blockade_region: DKC3Level(0x34D29D, 0x34D29E, 0x14, 0x35),
|
|
||||||
LocationName.rocket_barrel_ride_region: DKC3Level(0x34D2A8, 0x34D2A9, 0x15, 0x38),
|
|
||||||
LocationName.kreeping_klasps_region: DKC3Level(0x34D2BE, 0x34D2BF, 0x16, 0x26),
|
|
||||||
LocationName.tracker_barrel_trek_region: DKC3Level(0x34D2D4, 0x34D2D5, 0x17, 0x39),
|
|
||||||
LocationName.fish_food_frenzy_region: DKC3Level(0x34D2DF, 0x34D2E0, 0x18, 0x36),
|
|
||||||
|
|
||||||
LocationName.fire_ball_frenzy_region: DKC3Level(0x34D30D, 0x34D30E, 0x1B, 0x3B),
|
|
||||||
LocationName.demolition_drain_pipe_region: DKC3Level(0x34D323, 0x34D324, 0x1D, 0x40),
|
|
||||||
LocationName.ripsaw_rage_region: DKC3Level(0x34D339, 0x34D33A, 0x1E, 0x2E),
|
|
||||||
LocationName.blazing_bazookas_region: DKC3Level(0x34D34F, 0x34D350, 0x1F, 0x3C),
|
|
||||||
LocationName.low_g_labyrinth_region: DKC3Level(0x34D35A, 0x34D35B, 0x20, 0x3E),
|
|
||||||
|
|
||||||
LocationName.krevice_kreepers_region: DKC3Level(0x34D388, 0x34D389, 0x23, 0x41),
|
|
||||||
LocationName.tearaway_toboggan_region: DKC3Level(0x34D393, 0x34D394, 0x24, 0x2D),
|
|
||||||
LocationName.barrel_drop_bounce_region: DKC3Level(0x34D39E, 0x34D39F, 0x25, 0x3A),
|
|
||||||
LocationName.krack_shot_kroc_region: DKC3Level(0x34D3A9, 0x34D3AA, 0x26, 0x3D),
|
|
||||||
LocationName.lemguin_lunge_region: DKC3Level(0x34D3B4, 0x34D3B5, 0x27, 0x2C),
|
|
||||||
|
|
||||||
LocationName.buzzer_barrage_region: DKC3Level(0x34D40E, 0x34D40F, 0x2B, 0x44),
|
|
||||||
LocationName.kong_fused_cliffs_region: DKC3Level(0x34D424, 0x34D425, 0x2D, 0x42),
|
|
||||||
LocationName.floodlit_fish_region: DKC3Level(0x34D42F, 0x34D430, 0x2E, 0x37),
|
|
||||||
LocationName.pothole_panic_region: DKC3Level(0x34D43A, 0x34D43B, 0x2F, 0x45),
|
|
||||||
LocationName.ropey_rumpus_region: DKC3Level(0x34D450, 0x34D451, 0x30, 0x43),
|
|
||||||
|
|
||||||
LocationName.konveyor_rope_clash_region: DKC3Level(0x34D489, 0x34D48A, 0x38, 0x48),
|
|
||||||
LocationName.creepy_caverns_region: DKC3Level(0x34D49F, 0x34D4A0, 0x36, 0x46),
|
|
||||||
LocationName.lightning_lookout_region: DKC3Level(0x34D4AA, 0x34D4AB, 0x10, 0x33),
|
|
||||||
LocationName.koindozer_klamber_region: DKC3Level(0x34D4C0, 0x34D4C1, 0x34, 0x47),
|
|
||||||
LocationName.poisonous_pipeline_region: DKC3Level(0x34D4D6, 0x34D4D7, 0x39, 0x3F),
|
|
||||||
|
|
||||||
LocationName.stampede_sprint_region: DKC3Level(0x34D51A, 0x34D51B, 0x3D, 0x49),
|
|
||||||
LocationName.criss_cross_cliffs_region: DKC3Level(0x34D525, 0x34D526, 0x3E, 0x4A),
|
|
||||||
LocationName.tyrant_twin_tussle_region: DKC3Level(0x34D530, 0x34D531, 0x3F, 0x4B),
|
|
||||||
LocationName.swoopy_salvo_region: DKC3Level(0x34D53B, 0x34D53C, 0x40, 0x31),
|
|
||||||
#LocationName.rocket_rush_region: DKC3Level(0x34D546, 0x34D547, 0x05, 0x4C), # Rocket Rush is not getting shuffled
|
|
||||||
}
|
|
||||||
|
|
||||||
level_list = [
|
|
||||||
LocationName.lakeside_limbo_region,
|
|
||||||
LocationName.doorstop_dash_region,
|
|
||||||
LocationName.tidal_trouble_region,
|
|
||||||
LocationName.skiddas_row_region,
|
|
||||||
LocationName.murky_mill_region,
|
|
||||||
|
|
||||||
LocationName.barrel_shield_bust_up_region,
|
|
||||||
LocationName.riverside_race_region,
|
|
||||||
LocationName.squeals_on_wheels_region,
|
|
||||||
LocationName.springin_spiders_region,
|
|
||||||
LocationName.bobbing_barrel_brawl_region,
|
|
||||||
|
|
||||||
LocationName.bazzas_blockade_region,
|
|
||||||
LocationName.rocket_barrel_ride_region,
|
|
||||||
LocationName.kreeping_klasps_region,
|
|
||||||
LocationName.tracker_barrel_trek_region,
|
|
||||||
LocationName.fish_food_frenzy_region,
|
|
||||||
|
|
||||||
LocationName.fire_ball_frenzy_region,
|
|
||||||
LocationName.demolition_drain_pipe_region,
|
|
||||||
LocationName.ripsaw_rage_region,
|
|
||||||
LocationName.blazing_bazookas_region,
|
|
||||||
LocationName.low_g_labyrinth_region,
|
|
||||||
|
|
||||||
LocationName.krevice_kreepers_region,
|
|
||||||
LocationName.tearaway_toboggan_region,
|
|
||||||
LocationName.barrel_drop_bounce_region,
|
|
||||||
LocationName.krack_shot_kroc_region,
|
|
||||||
LocationName.lemguin_lunge_region,
|
|
||||||
|
|
||||||
LocationName.buzzer_barrage_region,
|
|
||||||
LocationName.kong_fused_cliffs_region,
|
|
||||||
LocationName.floodlit_fish_region,
|
|
||||||
LocationName.pothole_panic_region,
|
|
||||||
LocationName.ropey_rumpus_region,
|
|
||||||
|
|
||||||
LocationName.konveyor_rope_clash_region,
|
|
||||||
LocationName.creepy_caverns_region,
|
|
||||||
LocationName.lightning_lookout_region,
|
|
||||||
LocationName.koindozer_klamber_region,
|
|
||||||
LocationName.poisonous_pipeline_region,
|
|
||||||
|
|
||||||
LocationName.stampede_sprint_region,
|
|
||||||
LocationName.criss_cross_cliffs_region,
|
|
||||||
LocationName.tyrant_twin_tussle_region,
|
|
||||||
LocationName.swoopy_salvo_region,
|
|
||||||
#LocationName.rocket_rush_region,
|
|
||||||
]
|
|
||||||
@@ -1,337 +0,0 @@
|
|||||||
import typing
|
|
||||||
|
|
||||||
from BaseClasses import Location
|
|
||||||
from .Names import LocationName
|
|
||||||
from worlds.AutoWorld import World
|
|
||||||
|
|
||||||
|
|
||||||
class DKC3Location(Location):
|
|
||||||
game: str = "Donkey Kong Country 3"
|
|
||||||
|
|
||||||
progress_byte: int = 0x000000
|
|
||||||
progress_bit: int = 0
|
|
||||||
inverted_bit: bool = False
|
|
||||||
|
|
||||||
def __init__(self, player: int, name: str = '', address: int = None, parent=None, prog_byte: int = None, prog_bit: int = None, invert: bool = False):
|
|
||||||
super().__init__(player, name, address, parent)
|
|
||||||
self.progress_byte = prog_byte
|
|
||||||
self.progress_bit = prog_bit
|
|
||||||
self.inverted_bit = invert
|
|
||||||
|
|
||||||
|
|
||||||
level_location_table = {
|
|
||||||
LocationName.lakeside_limbo_flag: 0xDC3000,
|
|
||||||
LocationName.lakeside_limbo_bonus_1: 0xDC3001,
|
|
||||||
LocationName.lakeside_limbo_bonus_2: 0xDC3002,
|
|
||||||
LocationName.lakeside_limbo_dk: 0xDC3003,
|
|
||||||
|
|
||||||
LocationName.doorstop_dash_flag: 0xDC3004,
|
|
||||||
LocationName.doorstop_dash_bonus_1: 0xDC3005,
|
|
||||||
LocationName.doorstop_dash_bonus_2: 0xDC3006,
|
|
||||||
LocationName.doorstop_dash_dk: 0xDC3007,
|
|
||||||
|
|
||||||
LocationName.tidal_trouble_flag: 0xDC3008,
|
|
||||||
LocationName.tidal_trouble_bonus_1: 0xDC3009,
|
|
||||||
LocationName.tidal_trouble_bonus_2: 0xDC300A,
|
|
||||||
LocationName.tidal_trouble_dk: 0xDC300B,
|
|
||||||
|
|
||||||
LocationName.skiddas_row_flag: 0xDC300C,
|
|
||||||
LocationName.skiddas_row_bonus_1: 0xDC300D,
|
|
||||||
LocationName.skiddas_row_bonus_2: 0xDC300E,
|
|
||||||
LocationName.skiddas_row_dk: 0xDC300F,
|
|
||||||
|
|
||||||
LocationName.murky_mill_flag: 0xDC3010,
|
|
||||||
LocationName.murky_mill_bonus_1: 0xDC3011,
|
|
||||||
LocationName.murky_mill_bonus_2: 0xDC3012,
|
|
||||||
LocationName.murky_mill_dk: 0xDC3013,
|
|
||||||
|
|
||||||
LocationName.barrel_shield_bust_up_flag: 0xDC3014,
|
|
||||||
LocationName.barrel_shield_bust_up_bonus_1: 0xDC3015,
|
|
||||||
LocationName.barrel_shield_bust_up_bonus_2: 0xDC3016,
|
|
||||||
LocationName.barrel_shield_bust_up_dk: 0xDC3017,
|
|
||||||
|
|
||||||
LocationName.riverside_race_flag: 0xDC3018,
|
|
||||||
LocationName.riverside_race_bonus_1: 0xDC3019,
|
|
||||||
LocationName.riverside_race_bonus_2: 0xDC301A,
|
|
||||||
LocationName.riverside_race_dk: 0xDC301B,
|
|
||||||
|
|
||||||
LocationName.squeals_on_wheels_flag: 0xDC301C,
|
|
||||||
LocationName.squeals_on_wheels_bonus_1: 0xDC301D,
|
|
||||||
LocationName.squeals_on_wheels_bonus_2: 0xDC301E,
|
|
||||||
LocationName.squeals_on_wheels_dk: 0xDC301F,
|
|
||||||
|
|
||||||
LocationName.springin_spiders_flag: 0xDC3020,
|
|
||||||
LocationName.springin_spiders_bonus_1: 0xDC3021,
|
|
||||||
LocationName.springin_spiders_bonus_2: 0xDC3022,
|
|
||||||
LocationName.springin_spiders_dk: 0xDC3023,
|
|
||||||
|
|
||||||
LocationName.bobbing_barrel_brawl_flag: 0xDC3024,
|
|
||||||
LocationName.bobbing_barrel_brawl_bonus_1: 0xDC3025,
|
|
||||||
LocationName.bobbing_barrel_brawl_bonus_2: 0xDC3026,
|
|
||||||
LocationName.bobbing_barrel_brawl_dk: 0xDC3027,
|
|
||||||
|
|
||||||
LocationName.bazzas_blockade_flag: 0xDC3028,
|
|
||||||
LocationName.bazzas_blockade_bonus_1: 0xDC3029,
|
|
||||||
LocationName.bazzas_blockade_bonus_2: 0xDC302A,
|
|
||||||
LocationName.bazzas_blockade_dk: 0xDC302B,
|
|
||||||
|
|
||||||
LocationName.rocket_barrel_ride_flag: 0xDC302C,
|
|
||||||
LocationName.rocket_barrel_ride_bonus_1: 0xDC302D,
|
|
||||||
LocationName.rocket_barrel_ride_bonus_2: 0xDC302E,
|
|
||||||
LocationName.rocket_barrel_ride_dk: 0xDC302F,
|
|
||||||
|
|
||||||
LocationName.kreeping_klasps_flag: 0xDC3030,
|
|
||||||
LocationName.kreeping_klasps_bonus_1: 0xDC3031,
|
|
||||||
LocationName.kreeping_klasps_bonus_2: 0xDC3032,
|
|
||||||
LocationName.kreeping_klasps_dk: 0xDC3033,
|
|
||||||
|
|
||||||
LocationName.tracker_barrel_trek_flag: 0xDC3034,
|
|
||||||
LocationName.tracker_barrel_trek_bonus_1: 0xDC3035,
|
|
||||||
LocationName.tracker_barrel_trek_bonus_2: 0xDC3036,
|
|
||||||
LocationName.tracker_barrel_trek_dk: 0xDC3037,
|
|
||||||
|
|
||||||
LocationName.fish_food_frenzy_flag: 0xDC3038,
|
|
||||||
LocationName.fish_food_frenzy_bonus_1: 0xDC3039,
|
|
||||||
LocationName.fish_food_frenzy_bonus_2: 0xDC303A,
|
|
||||||
LocationName.fish_food_frenzy_dk: 0xDC303B,
|
|
||||||
|
|
||||||
LocationName.fire_ball_frenzy_flag: 0xDC303C,
|
|
||||||
LocationName.fire_ball_frenzy_bonus_1: 0xDC303D,
|
|
||||||
LocationName.fire_ball_frenzy_bonus_2: 0xDC303E,
|
|
||||||
LocationName.fire_ball_frenzy_dk: 0xDC303F,
|
|
||||||
|
|
||||||
LocationName.demolition_drain_pipe_flag: 0xDC3040,
|
|
||||||
LocationName.demolition_drain_pipe_bonus_1: 0xDC3041,
|
|
||||||
LocationName.demolition_drain_pipe_bonus_2: 0xDC3042,
|
|
||||||
LocationName.demolition_drain_pipe_dk: 0xDC3043,
|
|
||||||
|
|
||||||
LocationName.ripsaw_rage_flag: 0xDC3044,
|
|
||||||
LocationName.ripsaw_rage_bonus_1: 0xDC3045,
|
|
||||||
LocationName.ripsaw_rage_bonus_2: 0xDC3046,
|
|
||||||
LocationName.ripsaw_rage_dk: 0xDC3047,
|
|
||||||
|
|
||||||
LocationName.blazing_bazookas_flag: 0xDC3048,
|
|
||||||
LocationName.blazing_bazookas_bonus_1: 0xDC3049,
|
|
||||||
LocationName.blazing_bazookas_bonus_2: 0xDC304A,
|
|
||||||
LocationName.blazing_bazookas_dk: 0xDC304B,
|
|
||||||
|
|
||||||
LocationName.low_g_labyrinth_flag: 0xDC304C,
|
|
||||||
LocationName.low_g_labyrinth_bonus_1: 0xDC304D,
|
|
||||||
LocationName.low_g_labyrinth_bonus_2: 0xDC304E,
|
|
||||||
LocationName.low_g_labyrinth_dk: 0xDC304F,
|
|
||||||
|
|
||||||
LocationName.krevice_kreepers_flag: 0xDC3050,
|
|
||||||
LocationName.krevice_kreepers_bonus_1: 0xDC3051,
|
|
||||||
LocationName.krevice_kreepers_bonus_2: 0xDC3052,
|
|
||||||
LocationName.krevice_kreepers_dk: 0xDC3053,
|
|
||||||
|
|
||||||
LocationName.tearaway_toboggan_flag: 0xDC3054,
|
|
||||||
LocationName.tearaway_toboggan_bonus_1: 0xDC3055,
|
|
||||||
LocationName.tearaway_toboggan_bonus_2: 0xDC3056,
|
|
||||||
LocationName.tearaway_toboggan_dk: 0xDC3057,
|
|
||||||
|
|
||||||
LocationName.barrel_drop_bounce_flag: 0xDC3058,
|
|
||||||
LocationName.barrel_drop_bounce_bonus_1: 0xDC3059,
|
|
||||||
LocationName.barrel_drop_bounce_bonus_2: 0xDC305A,
|
|
||||||
LocationName.barrel_drop_bounce_dk: 0xDC305B,
|
|
||||||
|
|
||||||
LocationName.krack_shot_kroc_flag: 0xDC305C,
|
|
||||||
LocationName.krack_shot_kroc_bonus_1: 0xDC305D,
|
|
||||||
LocationName.krack_shot_kroc_bonus_2: 0xDC305E,
|
|
||||||
LocationName.krack_shot_kroc_dk: 0xDC305F,
|
|
||||||
|
|
||||||
LocationName.lemguin_lunge_flag: 0xDC3060,
|
|
||||||
LocationName.lemguin_lunge_bonus_1: 0xDC3061,
|
|
||||||
LocationName.lemguin_lunge_bonus_2: 0xDC3062,
|
|
||||||
LocationName.lemguin_lunge_dk: 0xDC3063,
|
|
||||||
|
|
||||||
LocationName.buzzer_barrage_flag: 0xDC3064,
|
|
||||||
LocationName.buzzer_barrage_bonus_1: 0xDC3065,
|
|
||||||
LocationName.buzzer_barrage_bonus_2: 0xDC3066,
|
|
||||||
LocationName.buzzer_barrage_dk: 0xDC3067,
|
|
||||||
|
|
||||||
LocationName.kong_fused_cliffs_flag: 0xDC3068,
|
|
||||||
LocationName.kong_fused_cliffs_bonus_1: 0xDC3069,
|
|
||||||
LocationName.kong_fused_cliffs_bonus_2: 0xDC306A,
|
|
||||||
LocationName.kong_fused_cliffs_dk: 0xDC306B,
|
|
||||||
|
|
||||||
LocationName.floodlit_fish_flag: 0xDC306C,
|
|
||||||
LocationName.floodlit_fish_bonus_1: 0xDC306D,
|
|
||||||
LocationName.floodlit_fish_bonus_2: 0xDC306E,
|
|
||||||
LocationName.floodlit_fish_dk: 0xDC306F,
|
|
||||||
|
|
||||||
LocationName.pothole_panic_flag: 0xDC3070,
|
|
||||||
LocationName.pothole_panic_bonus_1: 0xDC3071,
|
|
||||||
LocationName.pothole_panic_bonus_2: 0xDC3072,
|
|
||||||
LocationName.pothole_panic_dk: 0xDC3073,
|
|
||||||
|
|
||||||
LocationName.ropey_rumpus_flag: 0xDC3074,
|
|
||||||
LocationName.ropey_rumpus_bonus_1: 0xDC3075,
|
|
||||||
LocationName.ropey_rumpus_bonus_2: 0xDC3076,
|
|
||||||
LocationName.ropey_rumpus_dk: 0xDC3077,
|
|
||||||
|
|
||||||
LocationName.konveyor_rope_clash_flag: 0xDC3078,
|
|
||||||
LocationName.konveyor_rope_clash_bonus_1: 0xDC3079,
|
|
||||||
LocationName.konveyor_rope_clash_bonus_2: 0xDC307A,
|
|
||||||
LocationName.konveyor_rope_clash_dk: 0xDC307B,
|
|
||||||
|
|
||||||
LocationName.creepy_caverns_flag: 0xDC307C,
|
|
||||||
LocationName.creepy_caverns_bonus_1: 0xDC307D,
|
|
||||||
LocationName.creepy_caverns_bonus_2: 0xDC307E,
|
|
||||||
LocationName.creepy_caverns_dk: 0xDC307F,
|
|
||||||
|
|
||||||
LocationName.lightning_lookout_flag: 0xDC3080,
|
|
||||||
LocationName.lightning_lookout_bonus_1: 0xDC3081,
|
|
||||||
LocationName.lightning_lookout_bonus_2: 0xDC3082,
|
|
||||||
LocationName.lightning_lookout_dk: 0xDC3083,
|
|
||||||
|
|
||||||
LocationName.koindozer_klamber_flag: 0xDC3084,
|
|
||||||
LocationName.koindozer_klamber_bonus_1: 0xDC3085,
|
|
||||||
LocationName.koindozer_klamber_bonus_2: 0xDC3086,
|
|
||||||
LocationName.koindozer_klamber_dk: 0xDC3087,
|
|
||||||
|
|
||||||
LocationName.poisonous_pipeline_flag: 0xDC3088,
|
|
||||||
LocationName.poisonous_pipeline_bonus_1: 0xDC3089,
|
|
||||||
LocationName.poisonous_pipeline_bonus_2: 0xDC308A,
|
|
||||||
LocationName.poisonous_pipeline_dk: 0xDC308B,
|
|
||||||
|
|
||||||
LocationName.stampede_sprint_flag: 0xDC308C,
|
|
||||||
LocationName.stampede_sprint_bonus_1: 0xDC308D,
|
|
||||||
LocationName.stampede_sprint_bonus_2: 0xDC308E,
|
|
||||||
LocationName.stampede_sprint_bonus_3: 0xDC308F,
|
|
||||||
LocationName.stampede_sprint_dk: 0xDC3090,
|
|
||||||
|
|
||||||
LocationName.criss_cross_cliffs_flag: 0xDC3091,
|
|
||||||
LocationName.criss_cross_cliffs_bonus_1: 0xDC3092,
|
|
||||||
LocationName.criss_cross_cliffs_bonus_2: 0xDC3093,
|
|
||||||
LocationName.criss_cross_cliffs_dk: 0xDC3094,
|
|
||||||
|
|
||||||
LocationName.tyrant_twin_tussle_flag: 0xDC3095,
|
|
||||||
LocationName.tyrant_twin_tussle_bonus_1: 0xDC3096,
|
|
||||||
LocationName.tyrant_twin_tussle_bonus_2: 0xDC3097,
|
|
||||||
LocationName.tyrant_twin_tussle_bonus_3: 0xDC3098,
|
|
||||||
LocationName.tyrant_twin_tussle_dk: 0xDC3099,
|
|
||||||
|
|
||||||
LocationName.swoopy_salvo_flag: 0xDC309A,
|
|
||||||
LocationName.swoopy_salvo_bonus_1: 0xDC309B,
|
|
||||||
LocationName.swoopy_salvo_bonus_2: 0xDC309C,
|
|
||||||
LocationName.swoopy_salvo_bonus_3: 0xDC309D,
|
|
||||||
LocationName.swoopy_salvo_dk: 0xDC309E,
|
|
||||||
|
|
||||||
LocationName.rocket_rush_flag: 0xDC309F,
|
|
||||||
LocationName.rocket_rush_dk: 0xDC30A0,
|
|
||||||
}
|
|
||||||
|
|
||||||
kong_location_table = {
|
|
||||||
LocationName.lakeside_limbo_kong: 0xDC3100,
|
|
||||||
LocationName.doorstop_dash_kong: 0xDC3104,
|
|
||||||
LocationName.tidal_trouble_kong: 0xDC3108,
|
|
||||||
LocationName.skiddas_row_kong: 0xDC310C,
|
|
||||||
LocationName.murky_mill_kong: 0xDC3110,
|
|
||||||
|
|
||||||
LocationName.barrel_shield_bust_up_kong: 0xDC3114,
|
|
||||||
LocationName.riverside_race_kong: 0xDC3118,
|
|
||||||
LocationName.squeals_on_wheels_kong: 0xDC311C,
|
|
||||||
LocationName.springin_spiders_kong: 0xDC3120,
|
|
||||||
LocationName.bobbing_barrel_brawl_kong: 0xDC3124,
|
|
||||||
|
|
||||||
LocationName.bazzas_blockade_kong: 0xDC3128,
|
|
||||||
LocationName.rocket_barrel_ride_kong: 0xDC312C,
|
|
||||||
LocationName.kreeping_klasps_kong: 0xDC3130,
|
|
||||||
LocationName.tracker_barrel_trek_kong: 0xDC3134,
|
|
||||||
LocationName.fish_food_frenzy_kong: 0xDC3138,
|
|
||||||
|
|
||||||
LocationName.fire_ball_frenzy_kong: 0xDC313C,
|
|
||||||
LocationName.demolition_drain_pipe_kong: 0xDC3140,
|
|
||||||
LocationName.ripsaw_rage_kong: 0xDC3144,
|
|
||||||
LocationName.blazing_bazookas_kong: 0xDC3148,
|
|
||||||
LocationName.low_g_labyrinth_kong: 0xDC314C,
|
|
||||||
|
|
||||||
LocationName.krevice_kreepers_kong: 0xDC3150,
|
|
||||||
LocationName.tearaway_toboggan_kong: 0xDC3154,
|
|
||||||
LocationName.barrel_drop_bounce_kong: 0xDC3158,
|
|
||||||
LocationName.krack_shot_kroc_kong: 0xDC315C,
|
|
||||||
LocationName.lemguin_lunge_kong: 0xDC3160,
|
|
||||||
|
|
||||||
LocationName.buzzer_barrage_kong: 0xDC3164,
|
|
||||||
LocationName.kong_fused_cliffs_kong: 0xDC3168,
|
|
||||||
LocationName.floodlit_fish_kong: 0xDC316C,
|
|
||||||
LocationName.pothole_panic_kong: 0xDC3170,
|
|
||||||
LocationName.ropey_rumpus_kong: 0xDC3174,
|
|
||||||
|
|
||||||
LocationName.konveyor_rope_clash_kong: 0xDC3178,
|
|
||||||
LocationName.creepy_caverns_kong: 0xDC317C,
|
|
||||||
LocationName.lightning_lookout_kong: 0xDC3180,
|
|
||||||
LocationName.koindozer_klamber_kong: 0xDC3184,
|
|
||||||
LocationName.poisonous_pipeline_kong: 0xDC3188,
|
|
||||||
|
|
||||||
LocationName.stampede_sprint_kong: 0xDC318C,
|
|
||||||
LocationName.criss_cross_cliffs_kong: 0xDC3191,
|
|
||||||
LocationName.tyrant_twin_tussle_kong: 0xDC3195,
|
|
||||||
LocationName.swoopy_salvo_kong: 0xDC319A,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
boss_location_table = {
|
|
||||||
LocationName.belchas_barn: 0xDC30A1,
|
|
||||||
LocationName.arichs_ambush: 0xDC30A2,
|
|
||||||
LocationName.squirts_showdown: 0xDC30A3,
|
|
||||||
LocationName.kaos_karnage: 0xDC30A4,
|
|
||||||
LocationName.bleaks_house: 0xDC30A5,
|
|
||||||
LocationName.barboss_barrier: 0xDC30A6,
|
|
||||||
LocationName.kastle_kaos: 0xDC30A7,
|
|
||||||
LocationName.knautilus: 0xDC30A8,
|
|
||||||
}
|
|
||||||
|
|
||||||
secret_cave_location_table = {
|
|
||||||
LocationName.belchas_burrow: 0xDC30A9,
|
|
||||||
LocationName.kong_cave: 0xDC30AA,
|
|
||||||
LocationName.undercover_cove: 0xDC30AB,
|
|
||||||
LocationName.ks_cache: 0xDC30AC,
|
|
||||||
LocationName.hill_top_hoard: 0xDC30AD,
|
|
||||||
LocationName.bounty_beach: 0xDC30AE,
|
|
||||||
LocationName.smugglers_cove: 0xDC30AF,
|
|
||||||
LocationName.arichs_hoard: 0xDC30B0,
|
|
||||||
LocationName.bounty_bay: 0xDC30B1,
|
|
||||||
LocationName.sky_high_secret: 0xDC30B2,
|
|
||||||
LocationName.glacial_grotto: 0xDC30B3,
|
|
||||||
LocationName.cifftop_cache: 0xDC30B4,
|
|
||||||
LocationName.sewer_stockpile: 0xDC30B5,
|
|
||||||
LocationName.banana_bird_mother: 0xDC30B6,
|
|
||||||
}
|
|
||||||
|
|
||||||
brothers_bear_location_table = {
|
|
||||||
LocationName.bazaars_general_store_1: 0xDC30B7,
|
|
||||||
LocationName.bazaars_general_store_2: 0xDC30B8,
|
|
||||||
LocationName.brambles_bungalow: 0xDC30B9,
|
|
||||||
LocationName.flower_spot: 0xDC30BA,
|
|
||||||
LocationName.barters_swap_shop: 0xDC30BB,
|
|
||||||
LocationName.barnacles_island: 0xDC30BC,
|
|
||||||
LocationName.blues_beach_hut: 0xDC30BD,
|
|
||||||
LocationName.blizzards_basecamp: 0xDC30BE,
|
|
||||||
}
|
|
||||||
|
|
||||||
all_locations = {
|
|
||||||
**level_location_table,
|
|
||||||
**boss_location_table,
|
|
||||||
**secret_cave_location_table,
|
|
||||||
**brothers_bear_location_table,
|
|
||||||
**kong_location_table,
|
|
||||||
}
|
|
||||||
|
|
||||||
location_table = {}
|
|
||||||
|
|
||||||
|
|
||||||
def setup_locations(world: World):
|
|
||||||
location_table = {**level_location_table, **boss_location_table, **secret_cave_location_table}
|
|
||||||
|
|
||||||
if False:#world.options.include_trade_sequence:
|
|
||||||
location_table.update({**brothers_bear_location_table})
|
|
||||||
|
|
||||||
if world.options.kongsanity:
|
|
||||||
location_table.update({**kong_location_table})
|
|
||||||
|
|
||||||
return location_table
|
|
||||||
|
|
||||||
|
|
||||||
lookup_id_to_name: typing.Dict[int, str] = {id: name for name, _ in all_locations.items()}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# Junk Definitions
|
|
||||||
one_up_balloon = "1-Up Balloon"
|
|
||||||
bear_coin = "Bear Coin"
|
|
||||||
|
|
||||||
# Collectable Definitions
|
|
||||||
bonus_coin = "Bonus Coin"
|
|
||||||
dk_coin = "DK Coin"
|
|
||||||
banana_bird = "Banana Bird"
|
|
||||||
krematoa_cog = "Krematoa Cog"
|
|
||||||
|
|
||||||
# Inventory Definitions
|
|
||||||
progressive_boat = "Progressive Boat Upgrade"
|
|
||||||
present = "Present"
|
|
||||||
bowling_ball = "Bowling Ball"
|
|
||||||
shell = "Shell"
|
|
||||||
mirror = "Mirror"
|
|
||||||
flower = "Flupperius Petallus Pongus"
|
|
||||||
wrench = "No. 6 Wrench"
|
|
||||||
|
|
||||||
# Other Definitions
|
|
||||||
victory = "Donkey Kong"
|
|
||||||
@@ -1,375 +0,0 @@
|
|||||||
# Level Definitions
|
|
||||||
lakeside_limbo_flag = "Lakeside Limbo - Flag"
|
|
||||||
lakeside_limbo_kong = "Lakeside Limbo - KONG"
|
|
||||||
lakeside_limbo_bonus_1 = "Lakeside Limbo - Bonus 1"
|
|
||||||
lakeside_limbo_bonus_2 = "Lakeside Limbo - Bonus 2"
|
|
||||||
lakeside_limbo_dk = "Lakeside Limbo - DK Coin"
|
|
||||||
|
|
||||||
doorstop_dash_flag = "Doorstop Dash - Flag"
|
|
||||||
doorstop_dash_kong = "Doorstop Dash - KONG"
|
|
||||||
doorstop_dash_bonus_1 = "Doorstop Dash - Bonus 1"
|
|
||||||
doorstop_dash_bonus_2 = "Doorstop Dash - Bonus 2"
|
|
||||||
doorstop_dash_dk = "Doorstop Dash - DK Coin"
|
|
||||||
|
|
||||||
tidal_trouble_flag = "Tidal Trouble - Flag"
|
|
||||||
tidal_trouble_kong = "Tidal Trouble - KONG"
|
|
||||||
tidal_trouble_bonus_1 = "Tidal Trouble - Bonus 1"
|
|
||||||
tidal_trouble_bonus_2 = "Tidal Trouble - Bonus 2"
|
|
||||||
tidal_trouble_dk = "Tidal Trouble - DK Coin"
|
|
||||||
|
|
||||||
skiddas_row_flag = "Skidda's Row - Flag"
|
|
||||||
skiddas_row_kong = "Skidda's Row - KONG"
|
|
||||||
skiddas_row_bonus_1 = "Skidda's Row - Bonus 1"
|
|
||||||
skiddas_row_bonus_2 = "Skidda's Row - Bonus 2"
|
|
||||||
skiddas_row_dk = "Skidda's Row - DK Coin"
|
|
||||||
|
|
||||||
murky_mill_flag = "Murky Mill - Flag"
|
|
||||||
murky_mill_kong = "Murky Mill - KONG"
|
|
||||||
murky_mill_bonus_1 = "Murky Mill - Bonus 1"
|
|
||||||
murky_mill_bonus_2 = "Murky Mill - Bonus 2"
|
|
||||||
murky_mill_dk = "Murky Mill - DK Coin"
|
|
||||||
|
|
||||||
barrel_shield_bust_up_flag = "Barrel Shield Bust-Up - Flag"
|
|
||||||
barrel_shield_bust_up_kong = "Barrel Shield Bust-Up - KONG"
|
|
||||||
barrel_shield_bust_up_bonus_1 = "Barrel Shield Bust-Up - Bonus 1"
|
|
||||||
barrel_shield_bust_up_bonus_2 = "Barrel Shield Bust-Up - Bonus 2"
|
|
||||||
barrel_shield_bust_up_dk = "Barrel Shield Bust-Up - DK Coin"
|
|
||||||
|
|
||||||
riverside_race_flag = "Riverside Race - Flag"
|
|
||||||
riverside_race_kong = "Riverside Race - KONG"
|
|
||||||
riverside_race_bonus_1 = "Riverside Race - Bonus 1"
|
|
||||||
riverside_race_bonus_2 = "Riverside Race - Bonus 2"
|
|
||||||
riverside_race_dk = "Riverside Race - DK Coin"
|
|
||||||
|
|
||||||
squeals_on_wheels_flag = "Squeals On Wheels - Flag"
|
|
||||||
squeals_on_wheels_kong = "Squeals On Wheels - KONG"
|
|
||||||
squeals_on_wheels_bonus_1 = "Squeals On Wheels - Bonus 1"
|
|
||||||
squeals_on_wheels_bonus_2 = "Squeals On Wheels - Bonus 2"
|
|
||||||
squeals_on_wheels_dk = "Squeals On Wheels - DK Coin"
|
|
||||||
|
|
||||||
springin_spiders_flag = "Springin' Spiders - Flag"
|
|
||||||
springin_spiders_kong = "Springin' Spiders - KONG"
|
|
||||||
springin_spiders_bonus_1 = "Springin' Spiders - Bonus 1"
|
|
||||||
springin_spiders_bonus_2 = "Springin' Spiders - Bonus 2"
|
|
||||||
springin_spiders_dk = "Springin' Spiders - DK Coin"
|
|
||||||
|
|
||||||
bobbing_barrel_brawl_flag = "Bobbing Barrel Brawl - Flag"
|
|
||||||
bobbing_barrel_brawl_kong = "Bobbing Barrel Brawl - KONG"
|
|
||||||
bobbing_barrel_brawl_bonus_1 = "Bobbing Barrel Brawl - Bonus 1"
|
|
||||||
bobbing_barrel_brawl_bonus_2 = "Bobbing Barrel Brawl - Bonus 2"
|
|
||||||
bobbing_barrel_brawl_dk = "Bobbing Barrel Brawl - DK Coin"
|
|
||||||
|
|
||||||
bazzas_blockade_flag = "Bazza's Blockade - Flag"
|
|
||||||
bazzas_blockade_kong = "Bazza's Blockade - KONG"
|
|
||||||
bazzas_blockade_bonus_1 = "Bazza's Blockade - Bonus 1"
|
|
||||||
bazzas_blockade_bonus_2 = "Bazza's Blockade - Bonus 2"
|
|
||||||
bazzas_blockade_dk = "Bazza's Blockade - DK Coin"
|
|
||||||
|
|
||||||
rocket_barrel_ride_flag = "Rocket Barrel Ride - Flag"
|
|
||||||
rocket_barrel_ride_kong = "Rocket Barrel Ride - KONG"
|
|
||||||
rocket_barrel_ride_bonus_1 = "Rocket Barrel Ride - Bonus 1"
|
|
||||||
rocket_barrel_ride_bonus_2 = "Rocket Barrel Ride - Bonus 2"
|
|
||||||
rocket_barrel_ride_dk = "Rocket Barrel Ride - DK Coin"
|
|
||||||
|
|
||||||
kreeping_klasps_flag = "Kreeping Klasps - Flag"
|
|
||||||
kreeping_klasps_kong = "Kreeping Klasps - KONG"
|
|
||||||
kreeping_klasps_bonus_1 = "Kreeping Klasps - Bonus 1"
|
|
||||||
kreeping_klasps_bonus_2 = "Kreeping Klasps - Bonus 2"
|
|
||||||
kreeping_klasps_dk = "Kreeping Klasps - DK Coin"
|
|
||||||
|
|
||||||
tracker_barrel_trek_flag = "Tracker Barrel Trek - Flag"
|
|
||||||
tracker_barrel_trek_kong = "Tracker Barrel Trek - KONG"
|
|
||||||
tracker_barrel_trek_bonus_1 = "Tracker Barrel Trek - Bonus 1"
|
|
||||||
tracker_barrel_trek_bonus_2 = "Tracker Barrel Trek - Bonus 2"
|
|
||||||
tracker_barrel_trek_dk = "Tracker Barrel Trek - DK Coin"
|
|
||||||
|
|
||||||
fish_food_frenzy_flag = "Fish Food Frenzy - Flag"
|
|
||||||
fish_food_frenzy_kong = "Fish Food Frenzy - KONG"
|
|
||||||
fish_food_frenzy_bonus_1 = "Fish Food Frenzy - Bonus 1"
|
|
||||||
fish_food_frenzy_bonus_2 = "Fish Food Frenzy - Bonus 2"
|
|
||||||
fish_food_frenzy_dk = "Fish Food Frenzy - DK Coin"
|
|
||||||
|
|
||||||
fire_ball_frenzy_flag = "Fire-Ball Frenzy - Flag"
|
|
||||||
fire_ball_frenzy_kong = "Fire-Ball Frenzy - KONG"
|
|
||||||
fire_ball_frenzy_bonus_1 = "Fire-Ball Frenzy - Bonus 1"
|
|
||||||
fire_ball_frenzy_bonus_2 = "Fire-Ball Frenzy - Bonus 2"
|
|
||||||
fire_ball_frenzy_dk = "Fire-Ball Frenzy - DK Coin"
|
|
||||||
|
|
||||||
demolition_drain_pipe_flag = "Demolition Drain-Pipe - Flag"
|
|
||||||
demolition_drain_pipe_kong = "Demolition Drain-Pipe - KONG"
|
|
||||||
demolition_drain_pipe_bonus_1 = "Demolition Drain-Pipe - Bonus 1"
|
|
||||||
demolition_drain_pipe_bonus_2 = "Demolition Drain-Pipe - Bonus 2"
|
|
||||||
demolition_drain_pipe_dk = "Demolition Drain-Pipe - DK Coin"
|
|
||||||
|
|
||||||
ripsaw_rage_flag = "Ripsaw Rage - Flag"
|
|
||||||
ripsaw_rage_kong = "Ripsaw Rage - KONG"
|
|
||||||
ripsaw_rage_bonus_1 = "Ripsaw Rage - Bonus 1"
|
|
||||||
ripsaw_rage_bonus_2 = "Ripsaw Rage - Bonus 2"
|
|
||||||
ripsaw_rage_dk = "Ripsaw Rage - DK Coin"
|
|
||||||
|
|
||||||
blazing_bazookas_flag = "Blazing Bazukas - Flag"
|
|
||||||
blazing_bazookas_kong = "Blazing Bazukas - KONG"
|
|
||||||
blazing_bazookas_bonus_1 = "Blazing Bazukas - Bonus 1"
|
|
||||||
blazing_bazookas_bonus_2 = "Blazing Bazukas - Bonus 2"
|
|
||||||
blazing_bazookas_dk = "Blazing Bazukas - DK Coin"
|
|
||||||
|
|
||||||
low_g_labyrinth_flag = "Low-G Labyrinth - Flag"
|
|
||||||
low_g_labyrinth_kong = "Low-G Labyrinth - KONG"
|
|
||||||
low_g_labyrinth_bonus_1 = "Low-G Labyrinth - Bonus 1"
|
|
||||||
low_g_labyrinth_bonus_2 = "Low-G Labyrinth - Bonus 2"
|
|
||||||
low_g_labyrinth_dk = "Low-G Labyrinth - DK Coin"
|
|
||||||
|
|
||||||
krevice_kreepers_flag = "Krevice Kreepers - Flag"
|
|
||||||
krevice_kreepers_kong = "Krevice Kreepers - KONG"
|
|
||||||
krevice_kreepers_bonus_1 = "Krevice Kreepers - Bonus 1"
|
|
||||||
krevice_kreepers_bonus_2 = "Krevice Kreepers - Bonus 2"
|
|
||||||
krevice_kreepers_dk = "Krevice Kreepers - DK Coin"
|
|
||||||
|
|
||||||
tearaway_toboggan_flag = "Tearaway Toboggan - Flag"
|
|
||||||
tearaway_toboggan_kong = "Tearaway Toboggan - KONG"
|
|
||||||
tearaway_toboggan_bonus_1 = "Tearaway Toboggan - Bonus 1"
|
|
||||||
tearaway_toboggan_bonus_2 = "Tearaway Toboggan - Bonus 2"
|
|
||||||
tearaway_toboggan_dk = "Tearaway Toboggan - DK Coin"
|
|
||||||
|
|
||||||
barrel_drop_bounce_flag = "Barrel Drop Bounce - Flag"
|
|
||||||
barrel_drop_bounce_kong = "Barrel Drop Bounce - KONG"
|
|
||||||
barrel_drop_bounce_bonus_1 = "Barrel Drop Bounce - Bonus 1"
|
|
||||||
barrel_drop_bounce_bonus_2 = "Barrel Drop Bounce - Bonus 2"
|
|
||||||
barrel_drop_bounce_dk = "Barrel Drop Bounce - DK Coin"
|
|
||||||
|
|
||||||
krack_shot_kroc_flag = "Krack-Shot Kroc - Flag"
|
|
||||||
krack_shot_kroc_kong = "Krack-Shot Kroc - KONG"
|
|
||||||
krack_shot_kroc_bonus_1 = "Krack-Shot Kroc - Bonus 1"
|
|
||||||
krack_shot_kroc_bonus_2 = "Krack-Shot Kroc - Bonus 2"
|
|
||||||
krack_shot_kroc_dk = "Krack-Shot Kroc - DK Coin"
|
|
||||||
|
|
||||||
lemguin_lunge_flag = "Lemguin Lunge - Flag"
|
|
||||||
lemguin_lunge_kong = "Lemguin Lunge - KONG"
|
|
||||||
lemguin_lunge_bonus_1 = "Lemguin Lunge - Bonus 1"
|
|
||||||
lemguin_lunge_bonus_2 = "Lemguin Lunge - Bonus 2"
|
|
||||||
lemguin_lunge_dk = "Lemguin Lunge - DK Coin"
|
|
||||||
|
|
||||||
buzzer_barrage_flag = "Buzzer Barrage - Flag"
|
|
||||||
buzzer_barrage_kong = "Buzzer Barrage - KONG"
|
|
||||||
buzzer_barrage_bonus_1 = "Buzzer Barrage - Bonus 1"
|
|
||||||
buzzer_barrage_bonus_2 = "Buzzer Barrage - Bonus 2"
|
|
||||||
buzzer_barrage_dk = "Buzzer Barrage - DK Coin"
|
|
||||||
|
|
||||||
kong_fused_cliffs_flag = "Kong-Fused Cliffs - Flag"
|
|
||||||
kong_fused_cliffs_kong = "Kong-Fused Cliffs - KONG"
|
|
||||||
kong_fused_cliffs_bonus_1 = "Kong-Fused Cliffs - Bonus 1"
|
|
||||||
kong_fused_cliffs_bonus_2 = "Kong-Fused Cliffs - Bonus 2"
|
|
||||||
kong_fused_cliffs_dk = "Kong-Fused Cliffs - DK Coin"
|
|
||||||
|
|
||||||
floodlit_fish_flag = "Floodlit Fish - Flag"
|
|
||||||
floodlit_fish_kong = "Floodlit Fish - KONG"
|
|
||||||
floodlit_fish_bonus_1 = "Floodlit Fish - Bonus 1"
|
|
||||||
floodlit_fish_bonus_2 = "Floodlit Fish - Bonus 2"
|
|
||||||
floodlit_fish_dk = "Floodlit Fish - DK Coin"
|
|
||||||
|
|
||||||
pothole_panic_flag = "Pothole Panic - Flag"
|
|
||||||
pothole_panic_kong = "Pothole Panic - KONG"
|
|
||||||
pothole_panic_bonus_1 = "Pothole Panic - Bonus 1"
|
|
||||||
pothole_panic_bonus_2 = "Pothole Panic - Bonus 2"
|
|
||||||
pothole_panic_dk = "Pothole Panic - DK Coin"
|
|
||||||
|
|
||||||
ropey_rumpus_flag = "Ropey Rumpus - Flag"
|
|
||||||
ropey_rumpus_kong = "Ropey Rumpus - KONG"
|
|
||||||
ropey_rumpus_bonus_1 = "Ropey Rumpus - Bonus 1"
|
|
||||||
ropey_rumpus_bonus_2 = "Ropey Rumpus - Bonus 2"
|
|
||||||
ropey_rumpus_dk = "Ropey Rumpus - DK Coin"
|
|
||||||
|
|
||||||
konveyor_rope_clash_flag = "Konveyor Rope Klash - Flag"
|
|
||||||
konveyor_rope_clash_kong = "Konveyor Rope Klash - KONG"
|
|
||||||
konveyor_rope_clash_bonus_1 = "Konveyor Rope Klash - Bonus 1"
|
|
||||||
konveyor_rope_clash_bonus_2 = "Konveyor Rope Klash - Bonus 2"
|
|
||||||
konveyor_rope_clash_dk = "Konveyor Rope Klash - DK Coin"
|
|
||||||
|
|
||||||
creepy_caverns_flag = "Creepy Caverns - Flag"
|
|
||||||
creepy_caverns_kong = "Creepy Caverns - KONG"
|
|
||||||
creepy_caverns_bonus_1 = "Creepy Caverns - Bonus 1"
|
|
||||||
creepy_caverns_bonus_2 = "Creepy Caverns - Bonus 2"
|
|
||||||
creepy_caverns_dk = "Creepy Caverns - DK Coin"
|
|
||||||
|
|
||||||
lightning_lookout_flag = "Lightning Lookout - Flag"
|
|
||||||
lightning_lookout_kong = "Lightning Lookout - KONG"
|
|
||||||
lightning_lookout_bonus_1 = "Lightning Lookout - Bonus 1"
|
|
||||||
lightning_lookout_bonus_2 = "Lightning Lookout - Bonus 2"
|
|
||||||
lightning_lookout_dk = "Lightning Lookout - DK Coin"
|
|
||||||
|
|
||||||
koindozer_klamber_flag = "Koindozer Klamber - Flag"
|
|
||||||
koindozer_klamber_kong = "Koindozer Klamber - KONG"
|
|
||||||
koindozer_klamber_bonus_1 = "Koindozer Klamber - Bonus 1"
|
|
||||||
koindozer_klamber_bonus_2 = "Koindozer Klamber - Bonus 2"
|
|
||||||
koindozer_klamber_dk = "Koindozer Klamber - DK Coin"
|
|
||||||
|
|
||||||
poisonous_pipeline_flag = "Poisonous Pipeline - Flag"
|
|
||||||
poisonous_pipeline_kong = "Poisonous Pipeline - KONG"
|
|
||||||
poisonous_pipeline_bonus_1 = "Poisonous Pipeline - Bonus 1"
|
|
||||||
poisonous_pipeline_bonus_2 = "Poisonous Pipeline - Bonus 2"
|
|
||||||
poisonous_pipeline_dk = "Poisonous Pipeline - DK Coin"
|
|
||||||
|
|
||||||
stampede_sprint_flag = "Stampede Sprint - Flag"
|
|
||||||
stampede_sprint_kong = "Stampede Sprint - KONG"
|
|
||||||
stampede_sprint_bonus_1 = "Stampede Sprint - Bonus 1"
|
|
||||||
stampede_sprint_bonus_2 = "Stampede Sprint - Bonus 2"
|
|
||||||
stampede_sprint_bonus_3 = "Stampede Sprint - Bonus 3"
|
|
||||||
stampede_sprint_dk = "Stampede Sprint - DK Coin"
|
|
||||||
|
|
||||||
criss_cross_cliffs_flag = "Criss Kross Cliffs - Flag"
|
|
||||||
criss_cross_cliffs_kong = "Criss Kross Cliffs - KONG"
|
|
||||||
criss_cross_cliffs_bonus_1 = "Criss Kross Cliffs - Bonus 1"
|
|
||||||
criss_cross_cliffs_bonus_2 = "Criss Kross Cliffs - Bonus 2"
|
|
||||||
criss_cross_cliffs_dk = "Criss Kross Cliffs - DK Coin"
|
|
||||||
|
|
||||||
tyrant_twin_tussle_flag = "Tyrant Twin Tussle - Flag"
|
|
||||||
tyrant_twin_tussle_kong = "Tyrant Twin Tussle - KONG"
|
|
||||||
tyrant_twin_tussle_bonus_1 = "Tyrant Twin Tussle - Bonus 1"
|
|
||||||
tyrant_twin_tussle_bonus_2 = "Tyrant Twin Tussle - Bonus 2"
|
|
||||||
tyrant_twin_tussle_bonus_3 = "Tyrant Twin Tussle - Bonus 3"
|
|
||||||
tyrant_twin_tussle_dk = "Tyrant Twin Tussle - DK Coin"
|
|
||||||
|
|
||||||
swoopy_salvo_flag = "Swoopy Salvo - Flag"
|
|
||||||
swoopy_salvo_kong = "Swoopy Salvo - KONG"
|
|
||||||
swoopy_salvo_bonus_1 = "Swoopy Salvo - Bonus 1"
|
|
||||||
swoopy_salvo_bonus_2 = "Swoopy Salvo - Bonus 2"
|
|
||||||
swoopy_salvo_bonus_3 = "Swoopy Salvo - Bonus 3"
|
|
||||||
swoopy_salvo_dk = "Swoopy Salvo - DK Coin"
|
|
||||||
|
|
||||||
rocket_rush_flag = "Rocket Rush - Flag"
|
|
||||||
rocket_rush_dk = "Rocket Rush - DK Coin"
|
|
||||||
|
|
||||||
# Boss Definitions
|
|
||||||
belchas_barn = "Belcha's Barn"
|
|
||||||
arichs_ambush = "Arich's Ambush"
|
|
||||||
squirts_showdown = "Squirt's Showdown"
|
|
||||||
kaos_karnage = "KAOS Karnage"
|
|
||||||
bleaks_house = "Bleak's House"
|
|
||||||
barboss_barrier = "Barbos's Barrier"
|
|
||||||
kastle_kaos = "Kastle KAOS"
|
|
||||||
knautilus = "Knautilus"
|
|
||||||
|
|
||||||
|
|
||||||
# Banana Bird Cave Definitions
|
|
||||||
belchas_burrow = "Belcha's Burrow"
|
|
||||||
kong_cave = "Kong Cave"
|
|
||||||
undercover_cove = "Undercover Cove"
|
|
||||||
ks_cache = "K's Cache"
|
|
||||||
hill_top_hoard = "Hill-Top Hoard"
|
|
||||||
bounty_beach = "Bounty Beach"
|
|
||||||
smugglers_cove = "Smuggler's Cove"
|
|
||||||
arichs_hoard = "Arich's Hoard"
|
|
||||||
bounty_bay = "Bounty Bay"
|
|
||||||
sky_high_secret = "Sky-High Secret"
|
|
||||||
glacial_grotto = "Glacial Grotto"
|
|
||||||
cifftop_cache = "Clifftop Cache"
|
|
||||||
sewer_stockpile = "Sewer Stockpile"
|
|
||||||
|
|
||||||
banana_bird_mother = "Banana Bird Mother"
|
|
||||||
|
|
||||||
|
|
||||||
# Brothers Bear Definitions
|
|
||||||
bazaars_general_store_1 = "Bazaar's General Store - 1"
|
|
||||||
bazaars_general_store_2 = "Bazaar's General Store - 2"
|
|
||||||
brambles_bungalow = "Bramble's Bungalow"
|
|
||||||
flower_spot = "Flower Spot"
|
|
||||||
barters_swap_shop = "Barter's Swap Shop"
|
|
||||||
barnacles_island = "Barnacle's Island"
|
|
||||||
blues_beach_hut = "Blue's Beach Hut"
|
|
||||||
blizzards_basecamp = "Bizzard's Basecamp"
|
|
||||||
|
|
||||||
|
|
||||||
# Region Definitions
|
|
||||||
menu_region = "Menu"
|
|
||||||
overworld_1_region = "Overworld 1"
|
|
||||||
overworld_2_region = "Overworld 2"
|
|
||||||
overworld_3_region = "Overworld 3"
|
|
||||||
overworld_4_region = "Overworld 4"
|
|
||||||
|
|
||||||
bazaar_region = "Bazaar's General Store Region"
|
|
||||||
bramble_region = "Bramble's Bungalow Region"
|
|
||||||
flower_spot_region = "Flower Spot Region"
|
|
||||||
barter_region = "Barter's Swap Shop Region"
|
|
||||||
barnacle_region = "Barnacle's Island Region"
|
|
||||||
blue_region = "Blue's Beach Hut Region"
|
|
||||||
blizzard_region = "Bizzard's Basecamp Region"
|
|
||||||
|
|
||||||
lake_orangatanga_region = "Lake Orangatanga"
|
|
||||||
kremwood_forest_region = "Kremwood Forest"
|
|
||||||
cotton_top_cove_region = "Cotton-Top Cove"
|
|
||||||
mekanos_region = "Mekanos"
|
|
||||||
k3_region = "K3"
|
|
||||||
razor_ridge_region = "Razor Ridge"
|
|
||||||
kaos_kore_region = "KAOS Kore"
|
|
||||||
krematoa_region = "Krematoa"
|
|
||||||
|
|
||||||
belchas_barn_region = "Belcha's Barn Region"
|
|
||||||
arichs_ambush_region = "Arich's Ambush Region"
|
|
||||||
squirts_showdown_region = "Squirt's Showdown Region"
|
|
||||||
kaos_karnage_region = "KAOS Karnage Region"
|
|
||||||
bleaks_house_region = "Bleak's House Region"
|
|
||||||
barboss_barrier_region = "Barbos's Barrier Region"
|
|
||||||
kastle_kaos_region = "Kastle KAOS Region"
|
|
||||||
knautilus_region = "Knautilus Region"
|
|
||||||
|
|
||||||
belchas_burrow_region = "Belcha's Burrow Region"
|
|
||||||
kong_cave_region = "Kong Cave Region"
|
|
||||||
undercover_cove_region = "Undercover Cove Region"
|
|
||||||
ks_cache_region = "K's Cache Region"
|
|
||||||
hill_top_hoard_region = "Hill-Top Hoard Region"
|
|
||||||
bounty_beach_region = "Bounty Beach Region"
|
|
||||||
smugglers_cove_region = "Smuggler's Cove Region"
|
|
||||||
arichs_hoard_region = "Arich's Hoard Region"
|
|
||||||
bounty_bay_region = "Bounty Bay Region"
|
|
||||||
sky_high_secret_region = "Sky-High Secret Region"
|
|
||||||
glacial_grotto_region = "Glacial Grotto Region"
|
|
||||||
cifftop_cache_region = "Clifftop Cache Region"
|
|
||||||
sewer_stockpile_region = "Sewer Stockpile Region"
|
|
||||||
|
|
||||||
lakeside_limbo_region = "Lakeside Limbo"
|
|
||||||
doorstop_dash_region = "Doorstop Dash"
|
|
||||||
tidal_trouble_region = "Tidal Trouble"
|
|
||||||
skiddas_row_region = "Skidda's Row"
|
|
||||||
murky_mill_region = "Murky Mill"
|
|
||||||
|
|
||||||
barrel_shield_bust_up_region = "Barrel Shield Bust-Up"
|
|
||||||
riverside_race_region = "Riverside Race"
|
|
||||||
squeals_on_wheels_region = "Squeals On Wheels"
|
|
||||||
springin_spiders_region = "Springin' Spiders"
|
|
||||||
bobbing_barrel_brawl_region = "Bobbing Barrel Brawl"
|
|
||||||
|
|
||||||
bazzas_blockade_region = "Bazza's Blockade"
|
|
||||||
rocket_barrel_ride_region = "Rocket Barrel Ride"
|
|
||||||
kreeping_klasps_region = "Kreeping Klasps"
|
|
||||||
tracker_barrel_trek_region = "Tracker Barrel Trek"
|
|
||||||
fish_food_frenzy_region = "Fish Food Frenzy"
|
|
||||||
|
|
||||||
fire_ball_frenzy_region = "Fire-Ball Frenzy"
|
|
||||||
demolition_drain_pipe_region = "Demolition Drain-Pipe"
|
|
||||||
ripsaw_rage_region = "Ripsaw Rage"
|
|
||||||
blazing_bazookas_region = "Blazing Bazukas"
|
|
||||||
low_g_labyrinth_region = "Low-G Labyrinth"
|
|
||||||
|
|
||||||
krevice_kreepers_region = "Krevice Kreepers"
|
|
||||||
tearaway_toboggan_region = "Tearaway Toboggan"
|
|
||||||
barrel_drop_bounce_region = "Barrel Drop Bounce"
|
|
||||||
krack_shot_kroc_region = "Krack-Shot Kroc"
|
|
||||||
lemguin_lunge_region = "Lemguin Lunge"
|
|
||||||
|
|
||||||
buzzer_barrage_region = "Buzzer Barrage"
|
|
||||||
kong_fused_cliffs_region = "Kong-Fused Cliffs"
|
|
||||||
floodlit_fish_region = "Floodlit Fish"
|
|
||||||
pothole_panic_region = "Pothole Panic"
|
|
||||||
ropey_rumpus_region = "Ropey Rumpus"
|
|
||||||
|
|
||||||
konveyor_rope_clash_region = "Konveyor Rope Klash"
|
|
||||||
creepy_caverns_region = "Creepy Caverns"
|
|
||||||
lightning_lookout_region = "Lightning Lookout"
|
|
||||||
koindozer_klamber_region = "Koindozer Klamber"
|
|
||||||
poisonous_pipeline_region = "Poisonous Pipeline"
|
|
||||||
|
|
||||||
stampede_sprint_region = "Stampede Sprint"
|
|
||||||
criss_cross_cliffs_region = "Criss Kross Cliffs"
|
|
||||||
tyrant_twin_tussle_region = "Tyrant Twin Tussle"
|
|
||||||
swoopy_salvo_region = "Swoopy Salvo"
|
|
||||||
rocket_rush_region = "Rocket Rush"
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
from Options import Choice, Range, Toggle, DefaultOnToggle, OptionGroup, PerGameCommonOptions
|
|
||||||
|
|
||||||
|
|
||||||
class Goal(Choice):
|
|
||||||
"""
|
|
||||||
Determines the goal of the seed
|
|
||||||
|
|
||||||
Knautilus: Scuttle the Knautilus in Krematoa and defeat Baron K. Roolenstein
|
|
||||||
|
|
||||||
Banana Bird Hunt: Find a certain number of Banana Birds and rescue their mother
|
|
||||||
"""
|
|
||||||
display_name = "Goal"
|
|
||||||
option_knautilus = 0
|
|
||||||
option_banana_bird_hunt = 1
|
|
||||||
default = 0
|
|
||||||
|
|
||||||
|
|
||||||
class IncludeTradeSequence(Toggle):
|
|
||||||
"""
|
|
||||||
Allows logic to place items at the various steps of the trade sequence
|
|
||||||
"""
|
|
||||||
display_name = "Include Trade Sequence"
|
|
||||||
|
|
||||||
|
|
||||||
class DKCoinsForGyrocopter(Range):
|
|
||||||
"""
|
|
||||||
How many DK Coins are needed to unlock the Gyrocopter
|
|
||||||
|
|
||||||
Note: Achieving this number before unlocking the Turbo Ski will cause the game to grant you a
|
|
||||||
one-time upgrade to the next non-unlocked boat, until you return to Funky. Logic does not assume
|
|
||||||
that you will use this.
|
|
||||||
"""
|
|
||||||
display_name = "DK Coins for Gyrocopter"
|
|
||||||
range_start = 10
|
|
||||||
range_end = 41
|
|
||||||
default = 30
|
|
||||||
|
|
||||||
|
|
||||||
class KrematoaBonusCoinCost(Range):
|
|
||||||
"""
|
|
||||||
How many Bonus Coins are needed to unlock each level in Krematoa
|
|
||||||
"""
|
|
||||||
display_name = "Krematoa Bonus Coins Cost"
|
|
||||||
range_start = 1
|
|
||||||
range_end = 17
|
|
||||||
default = 15
|
|
||||||
|
|
||||||
|
|
||||||
class PercentageOfExtraBonusCoins(Range):
|
|
||||||
"""
|
|
||||||
What Percentage of unneeded Bonus Coins are included in the item pool
|
|
||||||
"""
|
|
||||||
display_name = "Percentage of Extra Bonus Coins"
|
|
||||||
range_start = 0
|
|
||||||
range_end = 100
|
|
||||||
default = 100
|
|
||||||
|
|
||||||
|
|
||||||
class NumberOfBananaBirds(Range):
|
|
||||||
"""
|
|
||||||
How many Banana Birds are put into the item pool
|
|
||||||
"""
|
|
||||||
display_name = "Number of Banana Birds"
|
|
||||||
range_start = 5
|
|
||||||
range_end = 15
|
|
||||||
default = 15
|
|
||||||
|
|
||||||
|
|
||||||
class PercentageOfBananaBirds(Range):
|
|
||||||
"""
|
|
||||||
What Percentage of Banana Birds in the item pool are required for Banana Bird Hunt
|
|
||||||
"""
|
|
||||||
display_name = "Percentage of Banana Birds"
|
|
||||||
range_start = 20
|
|
||||||
range_end = 100
|
|
||||||
default = 100
|
|
||||||
|
|
||||||
|
|
||||||
class KONGsanity(Toggle):
|
|
||||||
"""
|
|
||||||
Whether collecting all four KONG letters in each level grants a check
|
|
||||||
"""
|
|
||||||
display_name = "KONGsanity"
|
|
||||||
|
|
||||||
|
|
||||||
class LevelShuffle(Toggle):
|
|
||||||
"""
|
|
||||||
Whether levels are shuffled
|
|
||||||
"""
|
|
||||||
display_name = "Level Shuffle"
|
|
||||||
|
|
||||||
|
|
||||||
class Difficulty(Choice):
|
|
||||||
"""
|
|
||||||
Which Difficulty Level to use
|
|
||||||
|
|
||||||
NORML: The Normal Difficulty
|
|
||||||
HARDR: Many DK Barrels are removed
|
|
||||||
TUFST: Most DK Barrels and all Midway Barrels are removed
|
|
||||||
"""
|
|
||||||
display_name = "Difficulty"
|
|
||||||
option_norml = 0
|
|
||||||
option_hardr = 1
|
|
||||||
option_tufst = 2
|
|
||||||
default = 0
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_option_name(cls, value) -> str:
|
|
||||||
if cls.auto_display_name:
|
|
||||||
return cls.name_lookup[value].upper()
|
|
||||||
else:
|
|
||||||
return cls.name_lookup[value]
|
|
||||||
|
|
||||||
|
|
||||||
class Autosave(DefaultOnToggle):
|
|
||||||
"""
|
|
||||||
Whether the game should autosave after each level
|
|
||||||
"""
|
|
||||||
display_name = "Autosave"
|
|
||||||
|
|
||||||
|
|
||||||
class MERRY(Toggle):
|
|
||||||
"""
|
|
||||||
Whether the Bonus Barrels will be Christmas-themed
|
|
||||||
"""
|
|
||||||
display_name = "MERRY"
|
|
||||||
|
|
||||||
|
|
||||||
class MusicShuffle(Toggle):
|
|
||||||
"""
|
|
||||||
Whether music is shuffled
|
|
||||||
"""
|
|
||||||
display_name = "Music Shuffle"
|
|
||||||
|
|
||||||
|
|
||||||
class KongPaletteSwap(Choice):
|
|
||||||
"""
|
|
||||||
Which Palette to use for the Kongs
|
|
||||||
"""
|
|
||||||
display_name = "Kong Palette Swap"
|
|
||||||
option_default = 0
|
|
||||||
option_purple = 1
|
|
||||||
option_spooky = 2
|
|
||||||
option_dark = 3
|
|
||||||
option_chocolate = 4
|
|
||||||
option_shadow = 5
|
|
||||||
option_red_gold = 6
|
|
||||||
option_gbc = 7
|
|
||||||
option_halloween = 8
|
|
||||||
default = 0
|
|
||||||
|
|
||||||
|
|
||||||
class StartingLifeCount(Range):
|
|
||||||
"""
|
|
||||||
How many extra lives to start the game with
|
|
||||||
"""
|
|
||||||
display_name = "Starting Life Count"
|
|
||||||
range_start = 1
|
|
||||||
range_end = 99
|
|
||||||
default = 5
|
|
||||||
|
|
||||||
|
|
||||||
dkc3_option_groups = [
|
|
||||||
OptionGroup("Goal Options", [
|
|
||||||
Goal,
|
|
||||||
KrematoaBonusCoinCost,
|
|
||||||
PercentageOfExtraBonusCoins,
|
|
||||||
NumberOfBananaBirds,
|
|
||||||
PercentageOfBananaBirds,
|
|
||||||
]),
|
|
||||||
OptionGroup("Aesthetics", [
|
|
||||||
Autosave,
|
|
||||||
MERRY,
|
|
||||||
MusicShuffle,
|
|
||||||
KongPaletteSwap,
|
|
||||||
StartingLifeCount,
|
|
||||||
]),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class DKC3Options(PerGameCommonOptions):
|
|
||||||
#death_link: DeathLink # Disabled
|
|
||||||
#include_trade_sequence: IncludeTradeSequence # Disabled
|
|
||||||
|
|
||||||
goal: Goal
|
|
||||||
krematoa_bonus_coin_cost: KrematoaBonusCoinCost
|
|
||||||
percentage_of_extra_bonus_coins: PercentageOfExtraBonusCoins
|
|
||||||
number_of_banana_birds: NumberOfBananaBirds
|
|
||||||
percentage_of_banana_birds: PercentageOfBananaBirds
|
|
||||||
|
|
||||||
dk_coins_for_gyrocopter: DKCoinsForGyrocopter
|
|
||||||
kongsanity: KONGsanity
|
|
||||||
level_shuffle: LevelShuffle
|
|
||||||
difficulty: Difficulty
|
|
||||||
|
|
||||||
autosave: Autosave
|
|
||||||
merry: MERRY
|
|
||||||
music_shuffle: MusicShuffle
|
|
||||||
kong_palette_swap: KongPaletteSwap
|
|
||||||
starting_life_count: StartingLifeCount
|
|
||||||
@@ -1,954 +0,0 @@
|
|||||||
import typing
|
|
||||||
|
|
||||||
from BaseClasses import Region, Entrance
|
|
||||||
from worlds.AutoWorld import World
|
|
||||||
from .Locations import DKC3Location
|
|
||||||
from .Names import LocationName, ItemName
|
|
||||||
|
|
||||||
|
|
||||||
def create_regions(world: World, active_locations):
|
|
||||||
menu_region = create_region(world, active_locations, 'Menu', None)
|
|
||||||
|
|
||||||
overworld_1_region_locations = {}
|
|
||||||
if world.options.goal != "knautilus":
|
|
||||||
overworld_1_region_locations.update({LocationName.banana_bird_mother: []})
|
|
||||||
overworld_1_region = create_region(world, active_locations, LocationName.overworld_1_region,
|
|
||||||
overworld_1_region_locations)
|
|
||||||
|
|
||||||
overworld_2_region_locations = {}
|
|
||||||
overworld_2_region = create_region(world, active_locations, LocationName.overworld_2_region,
|
|
||||||
overworld_2_region_locations)
|
|
||||||
|
|
||||||
overworld_3_region_locations = {}
|
|
||||||
overworld_3_region = create_region(world, active_locations, LocationName.overworld_3_region,
|
|
||||||
overworld_3_region_locations)
|
|
||||||
|
|
||||||
overworld_4_region_locations = {}
|
|
||||||
overworld_4_region = create_region(world, active_locations, LocationName.overworld_4_region,
|
|
||||||
overworld_4_region_locations)
|
|
||||||
|
|
||||||
|
|
||||||
lake_orangatanga_region = create_region(world, active_locations, LocationName.lake_orangatanga_region, None)
|
|
||||||
kremwood_forest_region = create_region(world, active_locations, LocationName.kremwood_forest_region, None)
|
|
||||||
cotton_top_cove_region = create_region(world, active_locations, LocationName.cotton_top_cove_region, None)
|
|
||||||
mekanos_region = create_region(world, active_locations, LocationName.mekanos_region, None)
|
|
||||||
k3_region = create_region(world, active_locations, LocationName.k3_region, None)
|
|
||||||
razor_ridge_region = create_region(world, active_locations, LocationName.razor_ridge_region, None)
|
|
||||||
kaos_kore_region = create_region(world, active_locations, LocationName.kaos_kore_region, None)
|
|
||||||
krematoa_region = create_region(world, active_locations, LocationName.krematoa_region, None)
|
|
||||||
|
|
||||||
|
|
||||||
lakeside_limbo_region_locations = {
|
|
||||||
LocationName.lakeside_limbo_flag : [0x657, 1],
|
|
||||||
LocationName.lakeside_limbo_bonus_1 : [0x657, 2],
|
|
||||||
LocationName.lakeside_limbo_bonus_2 : [0x657, 3],
|
|
||||||
LocationName.lakeside_limbo_dk : [0x657, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
lakeside_limbo_region_locations[LocationName.lakeside_limbo_kong] = []
|
|
||||||
lakeside_limbo_region = create_region(world, active_locations, LocationName.lakeside_limbo_region,
|
|
||||||
lakeside_limbo_region_locations)
|
|
||||||
|
|
||||||
doorstop_dash_region_locations = {
|
|
||||||
LocationName.doorstop_dash_flag : [0x65A, 1],
|
|
||||||
LocationName.doorstop_dash_bonus_1 : [0x65A, 2],
|
|
||||||
LocationName.doorstop_dash_bonus_2 : [0x65A, 3],
|
|
||||||
LocationName.doorstop_dash_dk : [0x65A, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
doorstop_dash_region_locations[LocationName.doorstop_dash_kong] = []
|
|
||||||
doorstop_dash_region = create_region(world, active_locations, LocationName.doorstop_dash_region,
|
|
||||||
doorstop_dash_region_locations)
|
|
||||||
|
|
||||||
tidal_trouble_region_locations = {
|
|
||||||
LocationName.tidal_trouble_flag : [0x659, 1],
|
|
||||||
LocationName.tidal_trouble_bonus_1 : [0x659, 2],
|
|
||||||
LocationName.tidal_trouble_bonus_2 : [0x659, 3],
|
|
||||||
LocationName.tidal_trouble_dk : [0x659, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
tidal_trouble_region_locations[LocationName.tidal_trouble_kong] = []
|
|
||||||
tidal_trouble_region = create_region(world, active_locations, LocationName.tidal_trouble_region,
|
|
||||||
tidal_trouble_region_locations)
|
|
||||||
|
|
||||||
skiddas_row_region_locations = {
|
|
||||||
LocationName.skiddas_row_flag : [0x65D, 1],
|
|
||||||
LocationName.skiddas_row_bonus_1 : [0x65D, 2],
|
|
||||||
LocationName.skiddas_row_bonus_2 : [0x65D, 3],
|
|
||||||
LocationName.skiddas_row_dk : [0x65D, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
skiddas_row_region_locations[LocationName.skiddas_row_kong] = []
|
|
||||||
skiddas_row_region = create_region(world, active_locations, LocationName.skiddas_row_region,
|
|
||||||
skiddas_row_region_locations)
|
|
||||||
|
|
||||||
murky_mill_region_locations = {
|
|
||||||
LocationName.murky_mill_flag : [0x65C, 1],
|
|
||||||
LocationName.murky_mill_bonus_1 : [0x65C, 2],
|
|
||||||
LocationName.murky_mill_bonus_2 : [0x65C, 3],
|
|
||||||
LocationName.murky_mill_dk : [0x65C, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
murky_mill_region_locations[LocationName.murky_mill_kong] = []
|
|
||||||
murky_mill_region = create_region(world, active_locations, LocationName.murky_mill_region,
|
|
||||||
murky_mill_region_locations)
|
|
||||||
|
|
||||||
barrel_shield_bust_up_region_locations = {
|
|
||||||
LocationName.barrel_shield_bust_up_flag : [0x662, 1],
|
|
||||||
LocationName.barrel_shield_bust_up_bonus_1 : [0x662, 2],
|
|
||||||
LocationName.barrel_shield_bust_up_bonus_2 : [0x662, 3],
|
|
||||||
LocationName.barrel_shield_bust_up_dk : [0x662, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
barrel_shield_bust_up_region_locations[LocationName.barrel_shield_bust_up_kong] = []
|
|
||||||
barrel_shield_bust_up_region = create_region(world, active_locations,
|
|
||||||
LocationName.barrel_shield_bust_up_region,
|
|
||||||
barrel_shield_bust_up_region_locations)
|
|
||||||
|
|
||||||
riverside_race_region_locations = {
|
|
||||||
LocationName.riverside_race_flag : [0x664, 1],
|
|
||||||
LocationName.riverside_race_bonus_1 : [0x664, 2],
|
|
||||||
LocationName.riverside_race_bonus_2 : [0x664, 3],
|
|
||||||
LocationName.riverside_race_dk : [0x664, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
riverside_race_region_locations[LocationName.riverside_race_kong] = []
|
|
||||||
riverside_race_region = create_region(world, active_locations, LocationName.riverside_race_region,
|
|
||||||
riverside_race_region_locations)
|
|
||||||
|
|
||||||
squeals_on_wheels_region_locations = {
|
|
||||||
LocationName.squeals_on_wheels_flag : [0x65B, 1],
|
|
||||||
LocationName.squeals_on_wheels_bonus_1 : [0x65B, 2],
|
|
||||||
LocationName.squeals_on_wheels_bonus_2 : [0x65B, 3],
|
|
||||||
LocationName.squeals_on_wheels_dk : [0x65B, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
squeals_on_wheels_region_locations[LocationName.squeals_on_wheels_kong] = []
|
|
||||||
squeals_on_wheels_region = create_region(world, active_locations, LocationName.squeals_on_wheels_region,
|
|
||||||
squeals_on_wheels_region_locations)
|
|
||||||
|
|
||||||
springin_spiders_region_locations = {
|
|
||||||
LocationName.springin_spiders_flag : [0x661, 1],
|
|
||||||
LocationName.springin_spiders_bonus_1 : [0x661, 2],
|
|
||||||
LocationName.springin_spiders_bonus_2 : [0x661, 3],
|
|
||||||
LocationName.springin_spiders_dk : [0x661, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
springin_spiders_region_locations[LocationName.springin_spiders_kong] = []
|
|
||||||
springin_spiders_region = create_region(world, active_locations, LocationName.springin_spiders_region,
|
|
||||||
springin_spiders_region_locations)
|
|
||||||
|
|
||||||
bobbing_barrel_brawl_region_locations = {
|
|
||||||
LocationName.bobbing_barrel_brawl_flag : [0x666, 1],
|
|
||||||
LocationName.bobbing_barrel_brawl_bonus_1 : [0x666, 2],
|
|
||||||
LocationName.bobbing_barrel_brawl_bonus_2 : [0x666, 3],
|
|
||||||
LocationName.bobbing_barrel_brawl_dk : [0x666, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
bobbing_barrel_brawl_region_locations[LocationName.bobbing_barrel_brawl_kong] = []
|
|
||||||
bobbing_barrel_brawl_region = create_region(world, active_locations,
|
|
||||||
LocationName.bobbing_barrel_brawl_region,
|
|
||||||
bobbing_barrel_brawl_region_locations)
|
|
||||||
|
|
||||||
bazzas_blockade_region_locations = {
|
|
||||||
LocationName.bazzas_blockade_flag : [0x667, 1],
|
|
||||||
LocationName.bazzas_blockade_bonus_1 : [0x667, 2],
|
|
||||||
LocationName.bazzas_blockade_bonus_2 : [0x667, 3],
|
|
||||||
LocationName.bazzas_blockade_dk : [0x667, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
bazzas_blockade_region_locations[LocationName.bazzas_blockade_kong] = []
|
|
||||||
bazzas_blockade_region = create_region(world, active_locations, LocationName.bazzas_blockade_region,
|
|
||||||
bazzas_blockade_region_locations)
|
|
||||||
|
|
||||||
rocket_barrel_ride_region_locations = {
|
|
||||||
LocationName.rocket_barrel_ride_flag : [0x66A, 1],
|
|
||||||
LocationName.rocket_barrel_ride_bonus_1 : [0x66A, 2],
|
|
||||||
LocationName.rocket_barrel_ride_bonus_2 : [0x66A, 3],
|
|
||||||
LocationName.rocket_barrel_ride_dk : [0x66A, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
rocket_barrel_ride_region_locations[LocationName.rocket_barrel_ride_kong] = []
|
|
||||||
rocket_barrel_ride_region = create_region(world, active_locations, LocationName.rocket_barrel_ride_region,
|
|
||||||
rocket_barrel_ride_region_locations)
|
|
||||||
|
|
||||||
kreeping_klasps_region_locations = {
|
|
||||||
LocationName.kreeping_klasps_flag : [0x658, 1],
|
|
||||||
LocationName.kreeping_klasps_bonus_1 : [0x658, 2],
|
|
||||||
LocationName.kreeping_klasps_bonus_2 : [0x658, 3],
|
|
||||||
LocationName.kreeping_klasps_dk : [0x658, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
kreeping_klasps_region_locations[LocationName.kreeping_klasps_kong] = []
|
|
||||||
kreeping_klasps_region = create_region(world, active_locations, LocationName.kreeping_klasps_region,
|
|
||||||
kreeping_klasps_region_locations)
|
|
||||||
|
|
||||||
tracker_barrel_trek_region_locations = {
|
|
||||||
LocationName.tracker_barrel_trek_flag : [0x66B, 1],
|
|
||||||
LocationName.tracker_barrel_trek_bonus_1 : [0x66B, 2],
|
|
||||||
LocationName.tracker_barrel_trek_bonus_2 : [0x66B, 3],
|
|
||||||
LocationName.tracker_barrel_trek_dk : [0x66B, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
tracker_barrel_trek_region_locations[LocationName.tracker_barrel_trek_kong] = []
|
|
||||||
tracker_barrel_trek_region = create_region(world, active_locations, LocationName.tracker_barrel_trek_region,
|
|
||||||
tracker_barrel_trek_region_locations)
|
|
||||||
|
|
||||||
fish_food_frenzy_region_locations = {
|
|
||||||
LocationName.fish_food_frenzy_flag : [0x668, 1],
|
|
||||||
LocationName.fish_food_frenzy_bonus_1 : [0x668, 2],
|
|
||||||
LocationName.fish_food_frenzy_bonus_2 : [0x668, 3],
|
|
||||||
LocationName.fish_food_frenzy_dk : [0x668, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
fish_food_frenzy_region_locations[LocationName.fish_food_frenzy_kong] = []
|
|
||||||
fish_food_frenzy_region = create_region(world, active_locations, LocationName.fish_food_frenzy_region,
|
|
||||||
fish_food_frenzy_region_locations)
|
|
||||||
|
|
||||||
fire_ball_frenzy_region_locations = {
|
|
||||||
LocationName.fire_ball_frenzy_flag : [0x66D, 1],
|
|
||||||
LocationName.fire_ball_frenzy_bonus_1 : [0x66D, 2],
|
|
||||||
LocationName.fire_ball_frenzy_bonus_2 : [0x66D, 3],
|
|
||||||
LocationName.fire_ball_frenzy_dk : [0x66D, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
fire_ball_frenzy_region_locations[LocationName.fire_ball_frenzy_kong] = []
|
|
||||||
fire_ball_frenzy_region = create_region(world, active_locations, LocationName.fire_ball_frenzy_region,
|
|
||||||
fire_ball_frenzy_region_locations)
|
|
||||||
|
|
||||||
demolition_drain_pipe_region_locations = {
|
|
||||||
LocationName.demolition_drain_pipe_flag : [0x672, 1],
|
|
||||||
LocationName.demolition_drain_pipe_bonus_1 : [0x672, 2],
|
|
||||||
LocationName.demolition_drain_pipe_bonus_2 : [0x672, 3],
|
|
||||||
LocationName.demolition_drain_pipe_dk : [0x672, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
demolition_drain_pipe_region_locations[LocationName.demolition_drain_pipe_kong] = []
|
|
||||||
demolition_drain_pipe_region = create_region(world, active_locations,
|
|
||||||
LocationName.demolition_drain_pipe_region,
|
|
||||||
demolition_drain_pipe_region_locations)
|
|
||||||
|
|
||||||
ripsaw_rage_region_locations = {
|
|
||||||
LocationName.ripsaw_rage_flag : [0x660, 1],
|
|
||||||
LocationName.ripsaw_rage_bonus_1 : [0x660, 2],
|
|
||||||
LocationName.ripsaw_rage_bonus_2 : [0x660, 3],
|
|
||||||
LocationName.ripsaw_rage_dk : [0x660, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
ripsaw_rage_region_locations[LocationName.ripsaw_rage_kong] = []
|
|
||||||
ripsaw_rage_region = create_region(world, active_locations, LocationName.ripsaw_rage_region,
|
|
||||||
ripsaw_rage_region_locations)
|
|
||||||
|
|
||||||
blazing_bazookas_region_locations = {
|
|
||||||
LocationName.blazing_bazookas_flag : [0x66E, 1],
|
|
||||||
LocationName.blazing_bazookas_bonus_1 : [0x66E, 2],
|
|
||||||
LocationName.blazing_bazookas_bonus_2 : [0x66E, 3],
|
|
||||||
LocationName.blazing_bazookas_dk : [0x66E, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
blazing_bazookas_region_locations[LocationName.blazing_bazookas_kong] = []
|
|
||||||
blazing_bazookas_region = create_region(world, active_locations, LocationName.blazing_bazookas_region,
|
|
||||||
blazing_bazookas_region_locations)
|
|
||||||
|
|
||||||
low_g_labyrinth_region_locations = {
|
|
||||||
LocationName.low_g_labyrinth_flag : [0x670, 1],
|
|
||||||
LocationName.low_g_labyrinth_bonus_1 : [0x670, 2],
|
|
||||||
LocationName.low_g_labyrinth_bonus_2 : [0x670, 3],
|
|
||||||
LocationName.low_g_labyrinth_dk : [0x670, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
low_g_labyrinth_region_locations[LocationName.low_g_labyrinth_kong] = []
|
|
||||||
low_g_labyrinth_region = create_region(world, active_locations, LocationName.low_g_labyrinth_region,
|
|
||||||
low_g_labyrinth_region_locations)
|
|
||||||
|
|
||||||
krevice_kreepers_region_locations = {
|
|
||||||
LocationName.krevice_kreepers_flag : [0x673, 1],
|
|
||||||
LocationName.krevice_kreepers_bonus_1 : [0x673, 2],
|
|
||||||
LocationName.krevice_kreepers_bonus_2 : [0x673, 3],
|
|
||||||
LocationName.krevice_kreepers_dk : [0x673, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
krevice_kreepers_region_locations[LocationName.krevice_kreepers_kong] = []
|
|
||||||
krevice_kreepers_region = create_region(world, active_locations, LocationName.krevice_kreepers_region,
|
|
||||||
krevice_kreepers_region_locations)
|
|
||||||
|
|
||||||
tearaway_toboggan_region_locations = {
|
|
||||||
LocationName.tearaway_toboggan_flag : [0x65F, 1],
|
|
||||||
LocationName.tearaway_toboggan_bonus_1 : [0x65F, 2],
|
|
||||||
LocationName.tearaway_toboggan_bonus_2 : [0x65F, 3],
|
|
||||||
LocationName.tearaway_toboggan_dk : [0x65F, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
tearaway_toboggan_region_locations[LocationName.tearaway_toboggan_kong] = []
|
|
||||||
tearaway_toboggan_region = create_region(world, active_locations, LocationName.tearaway_toboggan_region,
|
|
||||||
tearaway_toboggan_region_locations)
|
|
||||||
|
|
||||||
barrel_drop_bounce_region_locations = {
|
|
||||||
LocationName.barrel_drop_bounce_flag : [0x66C, 1],
|
|
||||||
LocationName.barrel_drop_bounce_bonus_1 : [0x66C, 2],
|
|
||||||
LocationName.barrel_drop_bounce_bonus_2 : [0x66C, 3],
|
|
||||||
LocationName.barrel_drop_bounce_dk : [0x66C, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
barrel_drop_bounce_region_locations[LocationName.barrel_drop_bounce_kong] = []
|
|
||||||
barrel_drop_bounce_region = create_region(world, active_locations, LocationName.barrel_drop_bounce_region,
|
|
||||||
barrel_drop_bounce_region_locations)
|
|
||||||
|
|
||||||
krack_shot_kroc_region_locations = {
|
|
||||||
LocationName.krack_shot_kroc_flag : [0x66F, 1],
|
|
||||||
LocationName.krack_shot_kroc_bonus_1 : [0x66F, 2],
|
|
||||||
LocationName.krack_shot_kroc_bonus_2 : [0x66F, 3],
|
|
||||||
LocationName.krack_shot_kroc_dk : [0x66F, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
krack_shot_kroc_region_locations[LocationName.krack_shot_kroc_kong] = []
|
|
||||||
krack_shot_kroc_region = create_region(world, active_locations, LocationName.krack_shot_kroc_region,
|
|
||||||
krack_shot_kroc_region_locations)
|
|
||||||
|
|
||||||
lemguin_lunge_region_locations = {
|
|
||||||
LocationName.lemguin_lunge_flag : [0x65E, 1],
|
|
||||||
LocationName.lemguin_lunge_bonus_1 : [0x65E, 2],
|
|
||||||
LocationName.lemguin_lunge_bonus_2 : [0x65E, 3],
|
|
||||||
LocationName.lemguin_lunge_dk : [0x65E, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
lemguin_lunge_region_locations[LocationName.lemguin_lunge_kong] = []
|
|
||||||
lemguin_lunge_region = create_region(world, active_locations, LocationName.lemguin_lunge_region,
|
|
||||||
lemguin_lunge_region_locations)
|
|
||||||
|
|
||||||
buzzer_barrage_region_locations = {
|
|
||||||
LocationName.buzzer_barrage_flag : [0x676, 1],
|
|
||||||
LocationName.buzzer_barrage_bonus_1 : [0x676, 2],
|
|
||||||
LocationName.buzzer_barrage_bonus_2 : [0x676, 3],
|
|
||||||
LocationName.buzzer_barrage_dk : [0x676, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
buzzer_barrage_region_locations[LocationName.buzzer_barrage_kong] = []
|
|
||||||
buzzer_barrage_region = create_region(world, active_locations, LocationName.buzzer_barrage_region,
|
|
||||||
buzzer_barrage_region_locations)
|
|
||||||
|
|
||||||
kong_fused_cliffs_region_locations = {
|
|
||||||
LocationName.kong_fused_cliffs_flag : [0x674, 1],
|
|
||||||
LocationName.kong_fused_cliffs_bonus_1 : [0x674, 2],
|
|
||||||
LocationName.kong_fused_cliffs_bonus_2 : [0x674, 3],
|
|
||||||
LocationName.kong_fused_cliffs_dk : [0x674, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
kong_fused_cliffs_region_locations[LocationName.kong_fused_cliffs_kong] = []
|
|
||||||
kong_fused_cliffs_region = create_region(world, active_locations, LocationName.kong_fused_cliffs_region,
|
|
||||||
kong_fused_cliffs_region_locations)
|
|
||||||
|
|
||||||
floodlit_fish_region_locations = {
|
|
||||||
LocationName.floodlit_fish_flag : [0x669, 1],
|
|
||||||
LocationName.floodlit_fish_bonus_1 : [0x669, 2],
|
|
||||||
LocationName.floodlit_fish_bonus_2 : [0x669, 3],
|
|
||||||
LocationName.floodlit_fish_dk : [0x669, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
floodlit_fish_region_locations[LocationName.floodlit_fish_kong] = []
|
|
||||||
floodlit_fish_region = create_region(world, active_locations, LocationName.floodlit_fish_region,
|
|
||||||
floodlit_fish_region_locations)
|
|
||||||
|
|
||||||
pothole_panic_region_locations = {
|
|
||||||
LocationName.pothole_panic_flag : [0x677, 1],
|
|
||||||
LocationName.pothole_panic_bonus_1 : [0x677, 2],
|
|
||||||
LocationName.pothole_panic_bonus_2 : [0x677, 3],
|
|
||||||
LocationName.pothole_panic_dk : [0x677, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
pothole_panic_region_locations[LocationName.pothole_panic_kong] = []
|
|
||||||
pothole_panic_region = create_region(world, active_locations, LocationName.pothole_panic_region,
|
|
||||||
pothole_panic_region_locations)
|
|
||||||
|
|
||||||
ropey_rumpus_region_locations = {
|
|
||||||
LocationName.ropey_rumpus_flag : [0x675, 1],
|
|
||||||
LocationName.ropey_rumpus_bonus_1 : [0x675, 2],
|
|
||||||
LocationName.ropey_rumpus_bonus_2 : [0x675, 3],
|
|
||||||
LocationName.ropey_rumpus_dk : [0x675, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
ropey_rumpus_region_locations[LocationName.ropey_rumpus_kong] = []
|
|
||||||
ropey_rumpus_region = create_region(world, active_locations, LocationName.ropey_rumpus_region,
|
|
||||||
ropey_rumpus_region_locations)
|
|
||||||
|
|
||||||
konveyor_rope_clash_region_locations = {
|
|
||||||
LocationName.konveyor_rope_clash_flag : [0x657, 1],
|
|
||||||
LocationName.konveyor_rope_clash_bonus_1 : [0x657, 2],
|
|
||||||
LocationName.konveyor_rope_clash_bonus_2 : [0x657, 3],
|
|
||||||
LocationName.konveyor_rope_clash_dk : [0x657, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
konveyor_rope_clash_region_locations[LocationName.konveyor_rope_clash_kong] = []
|
|
||||||
konveyor_rope_clash_region = create_region(world, active_locations, LocationName.konveyor_rope_clash_region,
|
|
||||||
konveyor_rope_clash_region_locations)
|
|
||||||
|
|
||||||
creepy_caverns_region_locations = {
|
|
||||||
LocationName.creepy_caverns_flag : [0x678, 1],
|
|
||||||
LocationName.creepy_caverns_bonus_1 : [0x678, 2],
|
|
||||||
LocationName.creepy_caverns_bonus_2 : [0x678, 3],
|
|
||||||
LocationName.creepy_caverns_dk : [0x678, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
creepy_caverns_region_locations[LocationName.creepy_caverns_kong] = []
|
|
||||||
creepy_caverns_region = create_region(world, active_locations, LocationName.creepy_caverns_region,
|
|
||||||
creepy_caverns_region_locations)
|
|
||||||
|
|
||||||
lightning_lookout_region_locations = {
|
|
||||||
LocationName.lightning_lookout_flag : [0x665, 1],
|
|
||||||
LocationName.lightning_lookout_bonus_1 : [0x665, 2],
|
|
||||||
LocationName.lightning_lookout_bonus_2 : [0x665, 3],
|
|
||||||
LocationName.lightning_lookout_dk : [0x665, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
lightning_lookout_region_locations[LocationName.lightning_lookout_kong] = []
|
|
||||||
lightning_lookout_region = create_region(world, active_locations, LocationName.lightning_lookout_region,
|
|
||||||
lightning_lookout_region_locations)
|
|
||||||
|
|
||||||
koindozer_klamber_region_locations = {
|
|
||||||
LocationName.koindozer_klamber_flag : [0x679, 1],
|
|
||||||
LocationName.koindozer_klamber_bonus_1 : [0x679, 2],
|
|
||||||
LocationName.koindozer_klamber_bonus_2 : [0x679, 3],
|
|
||||||
LocationName.koindozer_klamber_dk : [0x679, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
koindozer_klamber_region_locations[LocationName.koindozer_klamber_kong] = []
|
|
||||||
koindozer_klamber_region = create_region(world, active_locations, LocationName.koindozer_klamber_region,
|
|
||||||
koindozer_klamber_region_locations)
|
|
||||||
|
|
||||||
poisonous_pipeline_region_locations = {
|
|
||||||
LocationName.poisonous_pipeline_flag : [0x671, 1],
|
|
||||||
LocationName.poisonous_pipeline_bonus_1 : [0x671, 2],
|
|
||||||
LocationName.poisonous_pipeline_bonus_2 : [0x671, 3],
|
|
||||||
LocationName.poisonous_pipeline_dk : [0x671, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
poisonous_pipeline_region_locations[LocationName.poisonous_pipeline_kong] = []
|
|
||||||
poisonous_pipeline_region = create_region(world, active_locations, LocationName.poisonous_pipeline_region,
|
|
||||||
poisonous_pipeline_region_locations)
|
|
||||||
|
|
||||||
stampede_sprint_region_locations = {
|
|
||||||
LocationName.stampede_sprint_flag : [0x67B, 1],
|
|
||||||
LocationName.stampede_sprint_bonus_1 : [0x67B, 2],
|
|
||||||
LocationName.stampede_sprint_bonus_2 : [0x67B, 3],
|
|
||||||
LocationName.stampede_sprint_bonus_3 : [0x67B, 4],
|
|
||||||
LocationName.stampede_sprint_dk : [0x67B, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
stampede_sprint_region_locations[LocationName.stampede_sprint_kong] = []
|
|
||||||
stampede_sprint_region = create_region(world, active_locations, LocationName.stampede_sprint_region,
|
|
||||||
stampede_sprint_region_locations)
|
|
||||||
|
|
||||||
criss_cross_cliffs_region_locations = {
|
|
||||||
LocationName.criss_cross_cliffs_flag : [0x67C, 1],
|
|
||||||
LocationName.criss_cross_cliffs_bonus_1 : [0x67C, 2],
|
|
||||||
LocationName.criss_cross_cliffs_bonus_2 : [0x67C, 3],
|
|
||||||
LocationName.criss_cross_cliffs_dk : [0x67C, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
criss_cross_cliffs_region_locations[LocationName.criss_cross_cliffs_kong] = []
|
|
||||||
criss_cross_cliffs_region = create_region(world, active_locations, LocationName.criss_cross_cliffs_region,
|
|
||||||
criss_cross_cliffs_region_locations)
|
|
||||||
|
|
||||||
tyrant_twin_tussle_region_locations = {
|
|
||||||
LocationName.tyrant_twin_tussle_flag : [0x67D, 1],
|
|
||||||
LocationName.tyrant_twin_tussle_bonus_1 : [0x67D, 2],
|
|
||||||
LocationName.tyrant_twin_tussle_bonus_2 : [0x67D, 3],
|
|
||||||
LocationName.tyrant_twin_tussle_bonus_3 : [0x67D, 4],
|
|
||||||
LocationName.tyrant_twin_tussle_dk : [0x67D, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
tyrant_twin_tussle_region_locations[LocationName.tyrant_twin_tussle_kong] = []
|
|
||||||
tyrant_twin_tussle_region = create_region(world, active_locations, LocationName.tyrant_twin_tussle_region,
|
|
||||||
tyrant_twin_tussle_region_locations)
|
|
||||||
|
|
||||||
swoopy_salvo_region_locations = {
|
|
||||||
LocationName.swoopy_salvo_flag : [0x663, 1],
|
|
||||||
LocationName.swoopy_salvo_bonus_1 : [0x663, 2],
|
|
||||||
LocationName.swoopy_salvo_bonus_2 : [0x663, 3],
|
|
||||||
LocationName.swoopy_salvo_bonus_3 : [0x663, 4],
|
|
||||||
LocationName.swoopy_salvo_dk : [0x663, 5],
|
|
||||||
}
|
|
||||||
if world.options.kongsanity:
|
|
||||||
swoopy_salvo_region_locations[LocationName.swoopy_salvo_kong] = []
|
|
||||||
swoopy_salvo_region = create_region(world, active_locations, LocationName.swoopy_salvo_region,
|
|
||||||
swoopy_salvo_region_locations)
|
|
||||||
|
|
||||||
rocket_rush_region_locations = {
|
|
||||||
LocationName.rocket_rush_flag : [0x67E, 1],
|
|
||||||
LocationName.rocket_rush_dk : [0x67E, 5],
|
|
||||||
}
|
|
||||||
rocket_rush_region = create_region(world, active_locations, LocationName.rocket_rush_region,
|
|
||||||
rocket_rush_region_locations)
|
|
||||||
|
|
||||||
belchas_barn_region_locations = {
|
|
||||||
LocationName.belchas_barn: [0x64F, 1],
|
|
||||||
}
|
|
||||||
belchas_barn_region = create_region(world, active_locations, LocationName.belchas_barn_region,
|
|
||||||
belchas_barn_region_locations)
|
|
||||||
|
|
||||||
arichs_ambush_region_locations = {
|
|
||||||
LocationName.arichs_ambush: [0x650, 1],
|
|
||||||
}
|
|
||||||
arichs_ambush_region = create_region(world, active_locations, LocationName.arichs_ambush_region,
|
|
||||||
arichs_ambush_region_locations)
|
|
||||||
|
|
||||||
squirts_showdown_region_locations = {
|
|
||||||
LocationName.squirts_showdown: [0x651, 1],
|
|
||||||
}
|
|
||||||
squirts_showdown_region = create_region(world, active_locations, LocationName.squirts_showdown_region,
|
|
||||||
squirts_showdown_region_locations)
|
|
||||||
|
|
||||||
kaos_karnage_region_locations = {
|
|
||||||
LocationName.kaos_karnage: [0x652, 1],
|
|
||||||
}
|
|
||||||
kaos_karnage_region = create_region(world, active_locations, LocationName.kaos_karnage_region,
|
|
||||||
kaos_karnage_region_locations)
|
|
||||||
|
|
||||||
bleaks_house_region_locations = {
|
|
||||||
LocationName.bleaks_house: [0x653, 1],
|
|
||||||
}
|
|
||||||
bleaks_house_region = create_region(world, active_locations, LocationName.bleaks_house_region,
|
|
||||||
bleaks_house_region_locations)
|
|
||||||
|
|
||||||
barboss_barrier_region_locations = {
|
|
||||||
LocationName.barboss_barrier: [0x654, 1],
|
|
||||||
}
|
|
||||||
barboss_barrier_region = create_region(world, active_locations, LocationName.barboss_barrier_region,
|
|
||||||
barboss_barrier_region_locations)
|
|
||||||
|
|
||||||
kastle_kaos_region_locations = {
|
|
||||||
LocationName.kastle_kaos: [0x655, 1],
|
|
||||||
}
|
|
||||||
kastle_kaos_region = create_region(world, active_locations, LocationName.kastle_kaos_region,
|
|
||||||
kastle_kaos_region_locations)
|
|
||||||
|
|
||||||
knautilus_region_locations = {
|
|
||||||
LocationName.knautilus: [0x656, 1],
|
|
||||||
}
|
|
||||||
knautilus_region = create_region(world, active_locations, LocationName.knautilus_region,
|
|
||||||
knautilus_region_locations)
|
|
||||||
|
|
||||||
belchas_burrow_region_locations = {
|
|
||||||
LocationName.belchas_burrow: [0x647, 1],
|
|
||||||
}
|
|
||||||
belchas_burrow_region = create_region(world, active_locations, LocationName.belchas_burrow_region,
|
|
||||||
belchas_burrow_region_locations)
|
|
||||||
|
|
||||||
kong_cave_region_locations = {
|
|
||||||
LocationName.kong_cave: [0x645, 1],
|
|
||||||
}
|
|
||||||
kong_cave_region = create_region(world, active_locations, LocationName.kong_cave_region,
|
|
||||||
kong_cave_region_locations)
|
|
||||||
|
|
||||||
undercover_cove_region_locations = {
|
|
||||||
LocationName.undercover_cove: [0x644, 1],
|
|
||||||
}
|
|
||||||
undercover_cove_region = create_region(world, active_locations, LocationName.undercover_cove_region,
|
|
||||||
undercover_cove_region_locations)
|
|
||||||
|
|
||||||
ks_cache_region_locations = {
|
|
||||||
LocationName.ks_cache: [0x642, 1],
|
|
||||||
}
|
|
||||||
ks_cache_region = create_region(world, active_locations, LocationName.ks_cache_region,
|
|
||||||
ks_cache_region_locations)
|
|
||||||
|
|
||||||
hill_top_hoard_region_locations = {
|
|
||||||
LocationName.hill_top_hoard: [0x643, 1],
|
|
||||||
}
|
|
||||||
hill_top_hoard_region = create_region(world, active_locations, LocationName.hill_top_hoard_region,
|
|
||||||
hill_top_hoard_region_locations)
|
|
||||||
|
|
||||||
bounty_beach_region_locations = {
|
|
||||||
LocationName.bounty_beach: [0x646, 1],
|
|
||||||
}
|
|
||||||
bounty_beach_region = create_region(world, active_locations, LocationName.bounty_beach_region,
|
|
||||||
bounty_beach_region_locations)
|
|
||||||
|
|
||||||
smugglers_cove_region_locations = {
|
|
||||||
LocationName.smugglers_cove: [0x648, 1],
|
|
||||||
}
|
|
||||||
smugglers_cove_region = create_region(world, active_locations, LocationName.smugglers_cove_region,
|
|
||||||
smugglers_cove_region_locations)
|
|
||||||
|
|
||||||
arichs_hoard_region_locations = {
|
|
||||||
LocationName.arichs_hoard: [0x649, 1],
|
|
||||||
}
|
|
||||||
arichs_hoard_region = create_region(world, active_locations, LocationName.arichs_hoard_region,
|
|
||||||
arichs_hoard_region_locations)
|
|
||||||
|
|
||||||
bounty_bay_region_locations = {
|
|
||||||
LocationName.bounty_bay: [0x64A, 1],
|
|
||||||
}
|
|
||||||
bounty_bay_region = create_region(world, active_locations, LocationName.bounty_bay_region,
|
|
||||||
bounty_bay_region_locations)
|
|
||||||
|
|
||||||
sky_high_secret_region_locations = {}
|
|
||||||
if False:#world.options.include_trade_sequence:
|
|
||||||
sky_high_secret_region_locations[LocationName.sky_high_secret] = [0x64B, 1]
|
|
||||||
sky_high_secret_region = create_region(world, active_locations, LocationName.sky_high_secret_region,
|
|
||||||
sky_high_secret_region_locations)
|
|
||||||
|
|
||||||
glacial_grotto_region_locations = {
|
|
||||||
LocationName.glacial_grotto: [0x64C, 1],
|
|
||||||
}
|
|
||||||
glacial_grotto_region = create_region(world, active_locations, LocationName.glacial_grotto_region,
|
|
||||||
glacial_grotto_region_locations)
|
|
||||||
|
|
||||||
cifftop_cache_region_locations = {}
|
|
||||||
if False:#world.options.include_trade_sequence:
|
|
||||||
cifftop_cache_region_locations[LocationName.cifftop_cache] = [0x64D, 1]
|
|
||||||
cifftop_cache_region = create_region(world, active_locations, LocationName.cifftop_cache_region,
|
|
||||||
cifftop_cache_region_locations)
|
|
||||||
|
|
||||||
sewer_stockpile_region_locations = {
|
|
||||||
LocationName.sewer_stockpile: [0x64E, 1],
|
|
||||||
}
|
|
||||||
sewer_stockpile_region = create_region(world, active_locations, LocationName.sewer_stockpile_region,
|
|
||||||
sewer_stockpile_region_locations)
|
|
||||||
|
|
||||||
|
|
||||||
# Set up the regions correctly.
|
|
||||||
world.multiworld.regions += [
|
|
||||||
menu_region,
|
|
||||||
overworld_1_region,
|
|
||||||
overworld_2_region,
|
|
||||||
overworld_3_region,
|
|
||||||
overworld_4_region,
|
|
||||||
lake_orangatanga_region,
|
|
||||||
kremwood_forest_region,
|
|
||||||
cotton_top_cove_region,
|
|
||||||
mekanos_region,
|
|
||||||
k3_region,
|
|
||||||
razor_ridge_region,
|
|
||||||
kaos_kore_region,
|
|
||||||
krematoa_region,
|
|
||||||
lakeside_limbo_region,
|
|
||||||
doorstop_dash_region,
|
|
||||||
tidal_trouble_region,
|
|
||||||
skiddas_row_region,
|
|
||||||
murky_mill_region,
|
|
||||||
barrel_shield_bust_up_region,
|
|
||||||
riverside_race_region,
|
|
||||||
squeals_on_wheels_region,
|
|
||||||
springin_spiders_region,
|
|
||||||
bobbing_barrel_brawl_region,
|
|
||||||
bazzas_blockade_region,
|
|
||||||
rocket_barrel_ride_region,
|
|
||||||
kreeping_klasps_region,
|
|
||||||
tracker_barrel_trek_region,
|
|
||||||
fish_food_frenzy_region,
|
|
||||||
fire_ball_frenzy_region,
|
|
||||||
demolition_drain_pipe_region,
|
|
||||||
ripsaw_rage_region,
|
|
||||||
blazing_bazookas_region,
|
|
||||||
low_g_labyrinth_region,
|
|
||||||
krevice_kreepers_region,
|
|
||||||
tearaway_toboggan_region,
|
|
||||||
barrel_drop_bounce_region,
|
|
||||||
krack_shot_kroc_region,
|
|
||||||
lemguin_lunge_region,
|
|
||||||
buzzer_barrage_region,
|
|
||||||
kong_fused_cliffs_region,
|
|
||||||
floodlit_fish_region,
|
|
||||||
pothole_panic_region,
|
|
||||||
ropey_rumpus_region,
|
|
||||||
konveyor_rope_clash_region,
|
|
||||||
creepy_caverns_region,
|
|
||||||
lightning_lookout_region,
|
|
||||||
koindozer_klamber_region,
|
|
||||||
poisonous_pipeline_region,
|
|
||||||
stampede_sprint_region,
|
|
||||||
criss_cross_cliffs_region,
|
|
||||||
tyrant_twin_tussle_region,
|
|
||||||
swoopy_salvo_region,
|
|
||||||
rocket_rush_region,
|
|
||||||
belchas_barn_region,
|
|
||||||
arichs_ambush_region,
|
|
||||||
squirts_showdown_region,
|
|
||||||
kaos_karnage_region,
|
|
||||||
bleaks_house_region,
|
|
||||||
barboss_barrier_region,
|
|
||||||
kastle_kaos_region,
|
|
||||||
knautilus_region,
|
|
||||||
belchas_burrow_region,
|
|
||||||
kong_cave_region,
|
|
||||||
undercover_cove_region,
|
|
||||||
ks_cache_region,
|
|
||||||
hill_top_hoard_region,
|
|
||||||
bounty_beach_region,
|
|
||||||
smugglers_cove_region,
|
|
||||||
arichs_hoard_region,
|
|
||||||
bounty_bay_region,
|
|
||||||
sky_high_secret_region,
|
|
||||||
glacial_grotto_region,
|
|
||||||
cifftop_cache_region,
|
|
||||||
sewer_stockpile_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
bazaar_region_locations = {}
|
|
||||||
bramble_region_locations = {}
|
|
||||||
flower_spot_region_locations = {}
|
|
||||||
barter_region_locations = {}
|
|
||||||
barnacle_region_locations = {}
|
|
||||||
blue_region_locations = {}
|
|
||||||
blizzard_region_locations = {}
|
|
||||||
|
|
||||||
if False:#world.options.include_trade_sequence:
|
|
||||||
bazaar_region_locations.update({
|
|
||||||
LocationName.bazaars_general_store_1: [0x615, 2, True],
|
|
||||||
LocationName.bazaars_general_store_2: [0x615, 3, True],
|
|
||||||
})
|
|
||||||
|
|
||||||
bramble_region_locations[LocationName.brambles_bungalow] = [0x619, 2]
|
|
||||||
|
|
||||||
#flower_spot_region_locations.update({
|
|
||||||
# LocationName.flower_spot: [0x615, 3, True],
|
|
||||||
#})
|
|
||||||
|
|
||||||
barter_region_locations[LocationName.barters_swap_shop] = [0x61B, 3]
|
|
||||||
|
|
||||||
barnacle_region_locations[LocationName.barnacles_island] = [0x61D, 2]
|
|
||||||
|
|
||||||
blue_region_locations[LocationName.blues_beach_hut] = [0x621, 4]
|
|
||||||
|
|
||||||
blizzard_region_locations[LocationName.blizzards_basecamp] = [0x625, 4, True]
|
|
||||||
|
|
||||||
bazaar_region = create_region(world, active_locations, LocationName.bazaar_region, bazaar_region_locations)
|
|
||||||
bramble_region = create_region(world, active_locations, LocationName.bramble_region,
|
|
||||||
bramble_region_locations)
|
|
||||||
flower_spot_region = create_region(world, active_locations, LocationName.flower_spot_region,
|
|
||||||
flower_spot_region_locations)
|
|
||||||
barter_region = create_region(world, active_locations, LocationName.barter_region, barter_region_locations)
|
|
||||||
barnacle_region = create_region(world, active_locations, LocationName.barnacle_region,
|
|
||||||
barnacle_region_locations)
|
|
||||||
blue_region = create_region(world, active_locations, LocationName.blue_region, blue_region_locations)
|
|
||||||
blizzard_region = create_region(world, active_locations, LocationName.blizzard_region,
|
|
||||||
blizzard_region_locations)
|
|
||||||
|
|
||||||
world.multiworld.regions += [
|
|
||||||
bazaar_region,
|
|
||||||
bramble_region,
|
|
||||||
flower_spot_region,
|
|
||||||
barter_region,
|
|
||||||
barnacle_region,
|
|
||||||
blue_region,
|
|
||||||
blizzard_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def connect_regions(world: World, level_list):
|
|
||||||
names: typing.Dict[str, int] = {}
|
|
||||||
|
|
||||||
# Overworld
|
|
||||||
connect(world, world.player, names, 'Menu', LocationName.overworld_1_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.overworld_2_region,
|
|
||||||
lambda state: (state.has(ItemName.progressive_boat, world.player, 1)))
|
|
||||||
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.overworld_3_region,
|
|
||||||
lambda state: (state.has(ItemName.progressive_boat, world.player, 3)))
|
|
||||||
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.overworld_4_region,
|
|
||||||
lambda state: (state.has(ItemName.dk_coin, world.player, world.options.dk_coins_for_gyrocopter.value) and
|
|
||||||
state.has(ItemName.progressive_boat, world.player, 3)))
|
|
||||||
|
|
||||||
# World Connections
|
|
||||||
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.lake_orangatanga_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.kremwood_forest_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.bounty_beach_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_1_region, LocationName.bazaar_region)
|
|
||||||
|
|
||||||
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.cotton_top_cove_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.mekanos_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.kong_cave_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_2_region, LocationName.bramble_region)
|
|
||||||
|
|
||||||
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.k3_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.razor_ridge_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.kaos_kore_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.krematoa_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.undercover_cove_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.flower_spot_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_3_region, LocationName.barter_region)
|
|
||||||
|
|
||||||
connect(world, world.player, names, LocationName.overworld_4_region, LocationName.belchas_burrow_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_4_region, LocationName.ks_cache_region)
|
|
||||||
connect(world, world.player, names, LocationName.overworld_4_region, LocationName.hill_top_hoard_region)
|
|
||||||
|
|
||||||
|
|
||||||
# Lake Orangatanga Connections
|
|
||||||
lake_orangatanga_levels = [
|
|
||||||
level_list[0],
|
|
||||||
level_list[1],
|
|
||||||
level_list[2],
|
|
||||||
level_list[3],
|
|
||||||
level_list[4],
|
|
||||||
LocationName.belchas_barn_region,
|
|
||||||
LocationName.barnacle_region,
|
|
||||||
LocationName.smugglers_cove_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
for i in range(0, len(lake_orangatanga_levels)):
|
|
||||||
connect(world, world.player, names, LocationName.lake_orangatanga_region, lake_orangatanga_levels[i])
|
|
||||||
|
|
||||||
# Kremwood Forest Connections
|
|
||||||
kremwood_forest_levels = [
|
|
||||||
level_list[5],
|
|
||||||
level_list[6],
|
|
||||||
level_list[7],
|
|
||||||
level_list[8],
|
|
||||||
level_list[9],
|
|
||||||
LocationName.arichs_ambush_region,
|
|
||||||
LocationName.arichs_hoard_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
for i in range(0, len(kremwood_forest_levels) - 1):
|
|
||||||
connect(world, world.player, names, LocationName.kremwood_forest_region, kremwood_forest_levels[i])
|
|
||||||
|
|
||||||
connection = connect(world, world.player, names, LocationName.kremwood_forest_region, kremwood_forest_levels[-1],
|
|
||||||
lambda state: (state.can_reach(LocationName.riverside_race_flag, "Location", world.player)))
|
|
||||||
world.multiworld.register_indirect_condition(world.get_location(LocationName.riverside_race_flag).parent_region,
|
|
||||||
connection)
|
|
||||||
|
|
||||||
# Cotton-Top Cove Connections
|
|
||||||
cotton_top_cove_levels = [
|
|
||||||
LocationName.blue_region,
|
|
||||||
level_list[10],
|
|
||||||
level_list[11],
|
|
||||||
level_list[12],
|
|
||||||
level_list[13],
|
|
||||||
level_list[14],
|
|
||||||
LocationName.squirts_showdown_region,
|
|
||||||
LocationName.bounty_bay_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
for i in range(0, len(cotton_top_cove_levels)):
|
|
||||||
connect(world, world.player, names, LocationName.cotton_top_cove_region, cotton_top_cove_levels[i])
|
|
||||||
|
|
||||||
# Mekanos Connections
|
|
||||||
mekanos_levels = [
|
|
||||||
level_list[15],
|
|
||||||
level_list[16],
|
|
||||||
level_list[17],
|
|
||||||
level_list[18],
|
|
||||||
level_list[19],
|
|
||||||
LocationName.kaos_karnage_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
for i in range(0, len(mekanos_levels)):
|
|
||||||
connect(world, world.player, names, LocationName.mekanos_region, mekanos_levels[i])
|
|
||||||
|
|
||||||
if False:#world.options.include_trade_sequence:
|
|
||||||
connect(world, world.player, names, LocationName.mekanos_region, LocationName.sky_high_secret_region,
|
|
||||||
lambda state: (state.has(ItemName.bowling_ball, world.player, 1)))
|
|
||||||
else:
|
|
||||||
connection = connect(world, world.player, names, LocationName.mekanos_region,
|
|
||||||
LocationName.sky_high_secret_region,
|
|
||||||
lambda state: (state.can_reach(LocationName.bleaks_house, "Location", world.player)))
|
|
||||||
world.multiworld.register_indirect_condition(world.get_location(LocationName.bleaks_house).parent_region,
|
|
||||||
connection)
|
|
||||||
|
|
||||||
# K3 Connections
|
|
||||||
k3_levels = [
|
|
||||||
level_list[20],
|
|
||||||
level_list[21],
|
|
||||||
level_list[22],
|
|
||||||
level_list[23],
|
|
||||||
level_list[24],
|
|
||||||
LocationName.bleaks_house_region,
|
|
||||||
LocationName.blizzard_region,
|
|
||||||
LocationName.glacial_grotto_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
for i in range(0, len(k3_levels)):
|
|
||||||
connect(world, world.player, names, LocationName.k3_region, k3_levels[i])
|
|
||||||
|
|
||||||
# Razor Ridge Connections
|
|
||||||
razor_ridge_levels = [
|
|
||||||
level_list[25],
|
|
||||||
level_list[26],
|
|
||||||
level_list[27],
|
|
||||||
level_list[28],
|
|
||||||
level_list[29],
|
|
||||||
LocationName.barboss_barrier_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
for i in range(0, len(razor_ridge_levels)):
|
|
||||||
connect(world, world.player, names, LocationName.razor_ridge_region, razor_ridge_levels[i])
|
|
||||||
|
|
||||||
if False:#world.options.include_trade_sequence:
|
|
||||||
connect(world, world.player, names, LocationName.razor_ridge_region, LocationName.cifftop_cache_region,
|
|
||||||
lambda state: (state.has(ItemName.wrench, world.player, 1)))
|
|
||||||
else:
|
|
||||||
connect(world, world.player, names, LocationName.razor_ridge_region, LocationName.cifftop_cache_region)
|
|
||||||
|
|
||||||
# KAOS Kore Connections
|
|
||||||
kaos_kore_levels = [
|
|
||||||
level_list[30],
|
|
||||||
level_list[31],
|
|
||||||
level_list[32],
|
|
||||||
level_list[33],
|
|
||||||
level_list[34],
|
|
||||||
LocationName.sewer_stockpile_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
for i in range(0, len(kaos_kore_levels)):
|
|
||||||
connect(world, world.player, names, LocationName.kaos_kore_region, kaos_kore_levels[i])
|
|
||||||
|
|
||||||
# Krematoa Connections
|
|
||||||
krematoa_levels = [
|
|
||||||
level_list[35],
|
|
||||||
level_list[36],
|
|
||||||
level_list[37],
|
|
||||||
level_list[38],
|
|
||||||
LocationName.rocket_rush_region,
|
|
||||||
]
|
|
||||||
|
|
||||||
for i in range(0, len(krematoa_levels)):
|
|
||||||
connect(world, world.player, names, LocationName.krematoa_region, krematoa_levels[i],
|
|
||||||
lambda state, i=i: (state.has(ItemName.bonus_coin, world.player, world.options.krematoa_bonus_coin_cost.value * (i+1))))
|
|
||||||
|
|
||||||
if world.options.goal == "knautilus":
|
|
||||||
connect(world, world.player, names, LocationName.kaos_kore_region, LocationName.knautilus_region)
|
|
||||||
connect(world, world.player, names, LocationName.krematoa_region, LocationName.kastle_kaos_region,
|
|
||||||
lambda state: (state.has(ItemName.krematoa_cog, world.player, 5)))
|
|
||||||
else:
|
|
||||||
connect(world, world.player, names, LocationName.kaos_kore_region, LocationName.kastle_kaos_region)
|
|
||||||
connect(world, world.player, names, LocationName.krematoa_region, LocationName.knautilus_region,
|
|
||||||
lambda state: (state.has(ItemName.krematoa_cog, world.player, 5)))
|
|
||||||
|
|
||||||
|
|
||||||
def create_region(world: World, active_locations, name: str, locations=None):
|
|
||||||
# Shamelessly stolen from the ROR2 definition
|
|
||||||
ret = Region(name, world.player, world.multiworld)
|
|
||||||
if locations:
|
|
||||||
for locationName, locationData in locations.items():
|
|
||||||
loc_id = active_locations.get(locationName, 0)
|
|
||||||
if loc_id:
|
|
||||||
loc_byte = locationData[0] if (len(locationData) > 0) else 0
|
|
||||||
loc_bit = locationData[1] if (len(locationData) > 1) else 0
|
|
||||||
loc_invert = locationData[2] if (len(locationData) > 2) else False
|
|
||||||
|
|
||||||
location = DKC3Location(world.player, locationName, loc_id, ret, loc_byte, loc_bit, loc_invert)
|
|
||||||
ret.locations.append(location)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def connect(world: World, player: int, used_names: typing.Dict[str, int], source: str, target: str,
|
|
||||||
rule: typing.Optional[typing.Callable] = None):
|
|
||||||
source_region = world.multiworld.get_region(source, player)
|
|
||||||
target_region = world.multiworld.get_region(target, player)
|
|
||||||
|
|
||||||
if target not in used_names:
|
|
||||||
used_names[target] = 1
|
|
||||||
name = target
|
|
||||||
else:
|
|
||||||
used_names[target] += 1
|
|
||||||
name = target + (' ' * used_names[target])
|
|
||||||
|
|
||||||
connection = Entrance(player, name, source_region)
|
|
||||||
|
|
||||||
if rule:
|
|
||||||
connection.access_rule = rule
|
|
||||||
|
|
||||||
source_region.exits.append(connection)
|
|
||||||
connection.connect(target_region)
|
|
||||||
return connection
|
|
||||||
@@ -1,744 +0,0 @@
|
|||||||
|
|
||||||
import Utils
|
|
||||||
from Utils import read_snes_rom
|
|
||||||
from worlds.AutoWorld import World
|
|
||||||
from worlds.Files import APDeltaPatch
|
|
||||||
from .Levels import level_list, level_dict
|
|
||||||
|
|
||||||
USHASH = '120abf304f0c40fe059f6a192ed4f947'
|
|
||||||
ROM_PLAYER_LIMIT = 65535
|
|
||||||
|
|
||||||
import hashlib
|
|
||||||
import os
|
|
||||||
import math
|
|
||||||
|
|
||||||
|
|
||||||
level_unlock_map = {
|
|
||||||
0x657: [0x65A],
|
|
||||||
0x65A: [0x680, 0x639, 0x659],
|
|
||||||
0x659: [0x65D],
|
|
||||||
0x65D: [0x65C],
|
|
||||||
0x65C: [0x688, 0x64F],
|
|
||||||
|
|
||||||
0x662: [0x681, 0x664],
|
|
||||||
0x664: [0x65B],
|
|
||||||
0x65B: [0x689, 0x661],
|
|
||||||
0x661: [0x63A, 0x666],
|
|
||||||
0x666: [0x650, 0x649],
|
|
||||||
|
|
||||||
0x667: [0x66A],
|
|
||||||
0x66A: [0x682, 0x658],
|
|
||||||
0x658: [0x68A, 0x66B],
|
|
||||||
0x66B: [0x668],
|
|
||||||
0x668: [0x651],
|
|
||||||
|
|
||||||
0x66D: [0x63C, 0x672],
|
|
||||||
0x672: [0x68B, 0x660],
|
|
||||||
0x660: [0x683, 0x66E],
|
|
||||||
0x66E: [0x670],
|
|
||||||
0x670: [0x652],
|
|
||||||
|
|
||||||
0x673: [0x684, 0x65F],
|
|
||||||
0x65F: [0x66C],
|
|
||||||
0x66C: [0x66F],
|
|
||||||
0x66F: [0x65E],
|
|
||||||
0x65E: [0x63D, 0x653, 0x68C, 0x64C],
|
|
||||||
|
|
||||||
0x676: [0x63E, 0x674, 0x685],
|
|
||||||
0x674: [0x63F, 0x669],
|
|
||||||
0x669: [0x677],
|
|
||||||
0x677: [0x68D, 0x675],
|
|
||||||
0x675: [0x654],
|
|
||||||
|
|
||||||
0x67A: [0x640, 0x678],
|
|
||||||
0x678: [0x665],
|
|
||||||
0x665: [0x686, 0x679],
|
|
||||||
0x679: [0x68E, 0x671],
|
|
||||||
|
|
||||||
0x67B: [0x67C],
|
|
||||||
0x67C: [0x67D],
|
|
||||||
0x67D: [0x663],
|
|
||||||
0x663: [0x67E],
|
|
||||||
}
|
|
||||||
|
|
||||||
location_rom_data = {
|
|
||||||
0xDC3000: [0x657, 1], # Lakeside Limbo
|
|
||||||
0xDC3001: [0x657, 2],
|
|
||||||
0xDC3002: [0x657, 3],
|
|
||||||
0xDC3003: [0x657, 5],
|
|
||||||
0xDC3100: [0x657, 7],
|
|
||||||
|
|
||||||
0xDC3004: [0x65A, 1], # Doorstop Dash
|
|
||||||
0xDC3005: [0x65A, 2],
|
|
||||||
0xDC3006: [0x65A, 3],
|
|
||||||
0xDC3007: [0x65A, 5],
|
|
||||||
0xDC3104: [0x65A, 7],
|
|
||||||
|
|
||||||
0xDC3008: [0x659, 1], # Tidal Trouble
|
|
||||||
0xDC3009: [0x659, 2],
|
|
||||||
0xDC300A: [0x659, 3],
|
|
||||||
0xDC300B: [0x659, 5],
|
|
||||||
0xDC3108: [0x659, 7],
|
|
||||||
|
|
||||||
0xDC300C: [0x65D, 1], # Skidda's Row
|
|
||||||
0xDC300D: [0x65D, 2],
|
|
||||||
0xDC300E: [0x65D, 3],
|
|
||||||
0xDC300F: [0x65D, 5],
|
|
||||||
0xDC310C: [0x65D, 7],
|
|
||||||
|
|
||||||
0xDC3010: [0x65C, 1], # Murky Mill
|
|
||||||
0xDC3011: [0x65C, 2],
|
|
||||||
0xDC3012: [0x65C, 3],
|
|
||||||
0xDC3013: [0x65C, 5],
|
|
||||||
0xDC3110: [0x65C, 7],
|
|
||||||
|
|
||||||
|
|
||||||
0xDC3014: [0x662, 1], # Barrel Shield Bust-Up
|
|
||||||
0xDC3015: [0x662, 2],
|
|
||||||
0xDC3016: [0x662, 3],
|
|
||||||
0xDC3017: [0x662, 5],
|
|
||||||
0xDC3114: [0x662, 7],
|
|
||||||
|
|
||||||
0xDC3018: [0x664, 1], # Riverside Race
|
|
||||||
0xDC3019: [0x664, 2],
|
|
||||||
0xDC301A: [0x664, 3],
|
|
||||||
0xDC301B: [0x664, 5],
|
|
||||||
0xDC3118: [0x664, 7],
|
|
||||||
|
|
||||||
0xDC301C: [0x65B, 1], # Squeals on Wheels
|
|
||||||
0xDC301D: [0x65B, 2],
|
|
||||||
0xDC301E: [0x65B, 3],
|
|
||||||
0xDC301F: [0x65B, 5],
|
|
||||||
0xDC311C: [0x65B, 7],
|
|
||||||
|
|
||||||
0xDC3020: [0x661, 1], # Springin' Spiders
|
|
||||||
0xDC3021: [0x661, 2],
|
|
||||||
0xDC3022: [0x661, 3],
|
|
||||||
0xDC3023: [0x661, 5],
|
|
||||||
0xDC3120: [0x661, 7],
|
|
||||||
|
|
||||||
0xDC3024: [0x666, 1], # Bobbing Barrel Brawl
|
|
||||||
0xDC3025: [0x666, 2],
|
|
||||||
0xDC3026: [0x666, 3],
|
|
||||||
0xDC3027: [0x666, 5],
|
|
||||||
0xDC3124: [0x666, 7],
|
|
||||||
|
|
||||||
|
|
||||||
0xDC3028: [0x667, 1], # Bazza's Blockade
|
|
||||||
0xDC3029: [0x667, 2],
|
|
||||||
0xDC302A: [0x667, 3],
|
|
||||||
0xDC302B: [0x667, 5],
|
|
||||||
0xDC3128: [0x667, 7],
|
|
||||||
|
|
||||||
0xDC302C: [0x66A, 1], # Rocket Barrel Ride
|
|
||||||
0xDC302D: [0x66A, 2],
|
|
||||||
0xDC302E: [0x66A, 3],
|
|
||||||
0xDC302F: [0x66A, 5],
|
|
||||||
0xDC312C: [0x66A, 7],
|
|
||||||
|
|
||||||
0xDC3030: [0x658, 1], # Kreeping Klasps
|
|
||||||
0xDC3031: [0x658, 2],
|
|
||||||
0xDC3032: [0x658, 3],
|
|
||||||
0xDC3033: [0x658, 5],
|
|
||||||
0xDC3130: [0x658, 7],
|
|
||||||
|
|
||||||
0xDC3034: [0x66B, 1], # Tracker Barrel Trek
|
|
||||||
0xDC3035: [0x66B, 2],
|
|
||||||
0xDC3036: [0x66B, 3],
|
|
||||||
0xDC3037: [0x66B, 5],
|
|
||||||
0xDC3134: [0x66B, 7],
|
|
||||||
|
|
||||||
0xDC3038: [0x668, 1], # Fish Food Frenzy
|
|
||||||
0xDC3039: [0x668, 2],
|
|
||||||
0xDC303A: [0x668, 3],
|
|
||||||
0xDC303B: [0x668, 5],
|
|
||||||
0xDC3138: [0x668, 7],
|
|
||||||
|
|
||||||
|
|
||||||
0xDC303C: [0x66D, 1], # Fire-ball Frenzy
|
|
||||||
0xDC303D: [0x66D, 2],
|
|
||||||
0xDC303E: [0x66D, 3],
|
|
||||||
0xDC303F: [0x66D, 5],
|
|
||||||
0xDC313C: [0x66D, 7],
|
|
||||||
|
|
||||||
0xDC3040: [0x672, 1], # Demolition Drainpipe
|
|
||||||
0xDC3041: [0x672, 2],
|
|
||||||
0xDC3042: [0x672, 3],
|
|
||||||
0xDC3043: [0x672, 5],
|
|
||||||
0xDC3140: [0x672, 7],
|
|
||||||
|
|
||||||
0xDC3044: [0x660, 1], # Ripsaw Rage
|
|
||||||
0xDC3045: [0x660, 2],
|
|
||||||
0xDC3046: [0x660, 3],
|
|
||||||
0xDC3047: [0x660, 5],
|
|
||||||
0xDC3144: [0x660, 7],
|
|
||||||
|
|
||||||
0xDC3048: [0x66E, 1], # Blazing Bazukas
|
|
||||||
0xDC3049: [0x66E, 2],
|
|
||||||
0xDC304A: [0x66E, 3],
|
|
||||||
0xDC304B: [0x66E, 5],
|
|
||||||
0xDC3148: [0x66E, 7],
|
|
||||||
|
|
||||||
0xDC304C: [0x670, 1], # Low-G Labyrinth
|
|
||||||
0xDC304D: [0x670, 2],
|
|
||||||
0xDC304E: [0x670, 3],
|
|
||||||
0xDC304F: [0x670, 5],
|
|
||||||
0xDC314C: [0x670, 7],
|
|
||||||
|
|
||||||
|
|
||||||
0xDC3050: [0x673, 1], # Krevice Kreepers
|
|
||||||
0xDC3051: [0x673, 2],
|
|
||||||
0xDC3052: [0x673, 3],
|
|
||||||
0xDC3053: [0x673, 5],
|
|
||||||
0xDC3150: [0x673, 7],
|
|
||||||
|
|
||||||
0xDC3054: [0x65F, 1], # Tearaway Toboggan
|
|
||||||
0xDC3055: [0x65F, 2],
|
|
||||||
0xDC3056: [0x65F, 3],
|
|
||||||
0xDC3057: [0x65F, 5],
|
|
||||||
0xDC3154: [0x65F, 7],
|
|
||||||
|
|
||||||
0xDC3058: [0x66C, 1], # Barrel Drop Bounce
|
|
||||||
0xDC3059: [0x66C, 2],
|
|
||||||
0xDC305A: [0x66C, 3],
|
|
||||||
0xDC305B: [0x66C, 5],
|
|
||||||
0xDC3158: [0x66C, 7],
|
|
||||||
|
|
||||||
0xDC305C: [0x66F, 1], # Krack-Shot Kroc
|
|
||||||
0xDC305D: [0x66F, 2],
|
|
||||||
0xDC305E: [0x66F, 3],
|
|
||||||
0xDC305F: [0x66F, 5],
|
|
||||||
0xDC315C: [0x66F, 7],
|
|
||||||
|
|
||||||
0xDC3060: [0x65E, 1], # Lemguin Lunge
|
|
||||||
0xDC3061: [0x65E, 2],
|
|
||||||
0xDC3062: [0x65E, 3],
|
|
||||||
0xDC3063: [0x65E, 5],
|
|
||||||
0xDC3160: [0x65E, 7],
|
|
||||||
|
|
||||||
|
|
||||||
0xDC3064: [0x676, 1], # Buzzer Barrage
|
|
||||||
0xDC3065: [0x676, 2],
|
|
||||||
0xDC3066: [0x676, 3],
|
|
||||||
0xDC3067: [0x676, 5],
|
|
||||||
0xDC3164: [0x676, 7],
|
|
||||||
|
|
||||||
0xDC3068: [0x674, 1], # Kong-Fused Cliffs
|
|
||||||
0xDC3069: [0x674, 2],
|
|
||||||
0xDC306A: [0x674, 3],
|
|
||||||
0xDC306B: [0x674, 5],
|
|
||||||
0xDC3168: [0x674, 7],
|
|
||||||
|
|
||||||
0xDC306C: [0x669, 1], # Floodlit Fish
|
|
||||||
0xDC306D: [0x669, 2],
|
|
||||||
0xDC306E: [0x669, 3],
|
|
||||||
0xDC306F: [0x669, 5],
|
|
||||||
0xDC316C: [0x669, 7],
|
|
||||||
|
|
||||||
0xDC3070: [0x677, 1], # Pothole Panic
|
|
||||||
0xDC3071: [0x677, 2],
|
|
||||||
0xDC3072: [0x677, 3],
|
|
||||||
0xDC3073: [0x677, 5],
|
|
||||||
0xDC3170: [0x677, 7],
|
|
||||||
|
|
||||||
0xDC3074: [0x675, 1], # Ropey Rumpus
|
|
||||||
0xDC3075: [0x675, 2],
|
|
||||||
0xDC3076: [0x675, 3],
|
|
||||||
0xDC3077: [0x675, 5],
|
|
||||||
0xDC3174: [0x675, 7],
|
|
||||||
|
|
||||||
|
|
||||||
0xDC3078: [0x67A, 1], # Konveyor Rope Klash
|
|
||||||
0xDC3079: [0x67A, 2],
|
|
||||||
0xDC307A: [0x67A, 3],
|
|
||||||
0xDC307B: [0x67A, 5],
|
|
||||||
0xDC3178: [0x67A, 7],
|
|
||||||
|
|
||||||
0xDC307C: [0x678, 1], # Creepy Caverns
|
|
||||||
0xDC307D: [0x678, 2],
|
|
||||||
0xDC307E: [0x678, 3],
|
|
||||||
0xDC307F: [0x678, 5],
|
|
||||||
0xDC317C: [0x678, 7],
|
|
||||||
|
|
||||||
0xDC3080: [0x665, 1], # Lightning Lookout
|
|
||||||
0xDC3081: [0x665, 2],
|
|
||||||
0xDC3082: [0x665, 3],
|
|
||||||
0xDC3083: [0x665, 5],
|
|
||||||
0xDC3180: [0x665, 7],
|
|
||||||
|
|
||||||
0xDC3084: [0x679, 1], # Koindozer Klamber
|
|
||||||
0xDC3085: [0x679, 2],
|
|
||||||
0xDC3086: [0x679, 3],
|
|
||||||
0xDC3087: [0x679, 5],
|
|
||||||
0xDC3184: [0x679, 7],
|
|
||||||
|
|
||||||
0xDC3088: [0x671, 1], # Poisonous Pipeline
|
|
||||||
0xDC3089: [0x671, 2],
|
|
||||||
0xDC308A: [0x671, 3],
|
|
||||||
0xDC308B: [0x671, 5],
|
|
||||||
0xDC3188: [0x671, 7],
|
|
||||||
|
|
||||||
|
|
||||||
0xDC308C: [0x67B, 1], # Stampede Sprint
|
|
||||||
0xDC308D: [0x67B, 2],
|
|
||||||
0xDC308E: [0x67B, 3],
|
|
||||||
0xDC308F: [0x67B, 4],
|
|
||||||
0xDC3090: [0x67B, 5],
|
|
||||||
0xDC318C: [0x67B, 7],
|
|
||||||
|
|
||||||
0xDC3091: [0x67C, 1], # Criss Kross Cliffs
|
|
||||||
0xDC3092: [0x67C, 2],
|
|
||||||
0xDC3093: [0x67C, 3],
|
|
||||||
0xDC3094: [0x67C, 5],
|
|
||||||
0xDC3191: [0x67C, 7],
|
|
||||||
|
|
||||||
0xDC3095: [0x67D, 1], # Tyrant Twin Tussle
|
|
||||||
0xDC3096: [0x67D, 2],
|
|
||||||
0xDC3097: [0x67D, 3],
|
|
||||||
0xDC3098: [0x67D, 4],
|
|
||||||
0xDC3099: [0x67D, 5],
|
|
||||||
0xDC3195: [0x67D, 7],
|
|
||||||
|
|
||||||
0xDC309A: [0x663, 1], # Swoopy Salvo
|
|
||||||
0xDC309B: [0x663, 2],
|
|
||||||
0xDC309C: [0x663, 3],
|
|
||||||
0xDC309D: [0x663, 4],
|
|
||||||
0xDC309E: [0x663, 5],
|
|
||||||
0xDC319A: [0x663, 7],
|
|
||||||
|
|
||||||
0xDC309F: [0x67E, 1], # Rocket Rush
|
|
||||||
0xDC30A0: [0x67E, 5],
|
|
||||||
|
|
||||||
0xDC30A1: [0x64F, 1], # Bosses
|
|
||||||
0xDC30A2: [0x650, 1],
|
|
||||||
0xDC30A3: [0x651, 1],
|
|
||||||
0xDC30A4: [0x652, 1],
|
|
||||||
0xDC30A5: [0x653, 1],
|
|
||||||
0xDC30A6: [0x654, 1],
|
|
||||||
0xDC30A7: [0x655, 1],
|
|
||||||
0xDC30A8: [0x656, 1],
|
|
||||||
|
|
||||||
0xDC30A9: [0x647, 1], # Banana Bird Caves
|
|
||||||
0xDC30AA: [0x645, 1],
|
|
||||||
0xDC30AB: [0x644, 1],
|
|
||||||
0xDC30AC: [0x642, 1],
|
|
||||||
0xDC30AD: [0x643, 1],
|
|
||||||
0xDC30AE: [0x646, 1],
|
|
||||||
0xDC30AF: [0x648, 1],
|
|
||||||
0xDC30B0: [0x649, 1],
|
|
||||||
0xDC30B1: [0x64A, 1],
|
|
||||||
#0xDC30B2: [0x64B, 1], # Disabled until Trade Sequence
|
|
||||||
0xDC30B3: [0x64C, 1],
|
|
||||||
#0xDC30B4: [0x64D, 1], # Disabled until Trade Sequence
|
|
||||||
0xDC30B5: [0x64E, 1],
|
|
||||||
|
|
||||||
0xDC30B6: [0x5FE, 4], # Banana Bird Mother
|
|
||||||
|
|
||||||
# DKC3_TODO: Disabled until Trade Sequence
|
|
||||||
#0xDC30B7: [0x615, 2, True],
|
|
||||||
#0xDC30B8: [0x615, 3, True],
|
|
||||||
#0xDC30B9: [0x619, 2],
|
|
||||||
##0xDC30BA:
|
|
||||||
#0xDC30BB: [0x61B, 3],
|
|
||||||
#0xDC30BC: [0x61D, 2],
|
|
||||||
#0xDC30BD: [0x621, 4],
|
|
||||||
#0xDC30BE: [0x625, 4, True],
|
|
||||||
}
|
|
||||||
|
|
||||||
boss_location_ids = [
|
|
||||||
0xDC30A1,
|
|
||||||
0xDC30A2,
|
|
||||||
0xDC30A3,
|
|
||||||
0xDC30A4,
|
|
||||||
0xDC30A5,
|
|
||||||
0xDC30A6,
|
|
||||||
0xDC30A7,
|
|
||||||
0xDC30A8,
|
|
||||||
0xDC30B6,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
item_rom_data = {
|
|
||||||
0xDC3001: [0x5D5], # 1-Up Balloon
|
|
||||||
0xDC3002: [0x5C9], # Bear Coin
|
|
||||||
0xDC3003: [0x5CB], # Bonus Coin
|
|
||||||
0xDC3004: [0x5CF], # DK Coin
|
|
||||||
0xDC3005: [0x5CD], # Banana Bird
|
|
||||||
0xDC3006: [0x5D1, 0x603], # Cog
|
|
||||||
}
|
|
||||||
|
|
||||||
music_rom_data = [
|
|
||||||
0x3D06B1,
|
|
||||||
0x3D0753,
|
|
||||||
0x3D071D,
|
|
||||||
0x3D07FA,
|
|
||||||
0x3D07C4,
|
|
||||||
|
|
||||||
0x3D08FE,
|
|
||||||
0x3D096C,
|
|
||||||
0x3D078E,
|
|
||||||
0x3D08CD,
|
|
||||||
0x3D09DD,
|
|
||||||
|
|
||||||
0x3D0A0E,
|
|
||||||
0x3D0AB3,
|
|
||||||
0x3D06E7,
|
|
||||||
0x3D0AE4,
|
|
||||||
0x3D0A45,
|
|
||||||
|
|
||||||
0x3D0B46,
|
|
||||||
0x3D0C40,
|
|
||||||
0x3D0897,
|
|
||||||
0x3D0B77,
|
|
||||||
0x3D0BD9,
|
|
||||||
|
|
||||||
0x3D0C71,
|
|
||||||
0x3D0866,
|
|
||||||
0x3D0B15,
|
|
||||||
0x3D0BA8,
|
|
||||||
0x3D0830,
|
|
||||||
|
|
||||||
0x3D0D04,
|
|
||||||
0x3D0CA2,
|
|
||||||
0x3D0A7C,
|
|
||||||
0x3D0D35,
|
|
||||||
0x3D0CD3,
|
|
||||||
|
|
||||||
0x3D0DC8,
|
|
||||||
0x3D0D66,
|
|
||||||
0x3D09AC,
|
|
||||||
0x3D0D97,
|
|
||||||
0x3D0C0F,
|
|
||||||
|
|
||||||
0x3D0DF9,
|
|
||||||
0x3D0E31,
|
|
||||||
0x3D0E62,
|
|
||||||
0x3D0934,
|
|
||||||
0x3D0E9A,
|
|
||||||
]
|
|
||||||
|
|
||||||
level_music_ids = [
|
|
||||||
0x06,
|
|
||||||
0x07,
|
|
||||||
0x08,
|
|
||||||
0x0A,
|
|
||||||
0x0B,
|
|
||||||
0x0E,
|
|
||||||
0x0F,
|
|
||||||
0x10,
|
|
||||||
0x17,
|
|
||||||
0x19,
|
|
||||||
0x1C,
|
|
||||||
0x1D,
|
|
||||||
0x1E,
|
|
||||||
0x21,
|
|
||||||
]
|
|
||||||
|
|
||||||
class LocalRom:
|
|
||||||
|
|
||||||
def __init__(self, file, name=None, hash=None):
|
|
||||||
self.name = name
|
|
||||||
self.hash = hash
|
|
||||||
self.orig_buffer = None
|
|
||||||
|
|
||||||
with open(file, 'rb') as stream:
|
|
||||||
self.buffer = read_snes_rom(stream)
|
|
||||||
#if patch:
|
|
||||||
# self.patch_rom()
|
|
||||||
# self.orig_buffer = self.buffer.copy()
|
|
||||||
#if vanillaRom:
|
|
||||||
# with open(vanillaRom, 'rb') as vanillaStream:
|
|
||||||
# self.orig_buffer = read_snes_rom(vanillaStream)
|
|
||||||
|
|
||||||
def read_bit(self, address: int, bit_number: int) -> bool:
|
|
||||||
bitflag = (1 << bit_number)
|
|
||||||
return ((self.buffer[address] & bitflag) != 0)
|
|
||||||
|
|
||||||
def read_byte(self, address: int) -> int:
|
|
||||||
return self.buffer[address]
|
|
||||||
|
|
||||||
def read_bytes(self, startaddress: int, length: int) -> bytearray:
|
|
||||||
return self.buffer[startaddress:startaddress + length]
|
|
||||||
|
|
||||||
def write_byte(self, address: int, value: int):
|
|
||||||
self.buffer[address] = value
|
|
||||||
|
|
||||||
def write_bytes(self, startaddress: int, values):
|
|
||||||
self.buffer[startaddress:startaddress + len(values)] = values
|
|
||||||
|
|
||||||
def write_to_file(self, file):
|
|
||||||
with open(file, 'wb') as outfile:
|
|
||||||
outfile.write(self.buffer)
|
|
||||||
|
|
||||||
def read_from_file(self, file):
|
|
||||||
with open(file, 'rb') as stream:
|
|
||||||
self.buffer = bytearray(stream.read())
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def patch_rom(world: World, rom: LocalRom, active_level_list):
|
|
||||||
|
|
||||||
# Boomer Costs
|
|
||||||
bonus_coin_cost = world.options.krematoa_bonus_coin_cost
|
|
||||||
inverted_bonus_coin_cost = 0x100 - bonus_coin_cost
|
|
||||||
rom.write_byte(0x3498B9, inverted_bonus_coin_cost)
|
|
||||||
rom.write_byte(0x3498BA, inverted_bonus_coin_cost)
|
|
||||||
rom.write_byte(0x3498BB, inverted_bonus_coin_cost)
|
|
||||||
rom.write_byte(0x3498BC, inverted_bonus_coin_cost)
|
|
||||||
rom.write_byte(0x3498BD, inverted_bonus_coin_cost)
|
|
||||||
|
|
||||||
rom.write_byte(0x349857, bonus_coin_cost)
|
|
||||||
rom.write_byte(0x349862, bonus_coin_cost)
|
|
||||||
|
|
||||||
# Gyrocopter Costs
|
|
||||||
dk_coin_cost = world.options.dk_coins_for_gyrocopter
|
|
||||||
rom.write_byte(0x3484A6, dk_coin_cost)
|
|
||||||
rom.write_byte(0x3484D5, dk_coin_cost)
|
|
||||||
rom.write_byte(0x3484D7, 0x90)
|
|
||||||
rom.write_byte(0x3484DC, 0xEA)
|
|
||||||
rom.write_byte(0x3484DD, 0xEA)
|
|
||||||
rom.write_byte(0x3484DE, 0xEA)
|
|
||||||
rom.write_byte(0x348528, 0x80) # Prevent Single-Ski Lock
|
|
||||||
|
|
||||||
# Make Swanky free
|
|
||||||
rom.write_byte(0x348C48, 0x00)
|
|
||||||
|
|
||||||
rom.write_bytes(0x34AB70, bytearray([0xEA, 0xEA]))
|
|
||||||
rom.write_bytes(0x34ABF7, bytearray([0xEA, 0xEA]))
|
|
||||||
rom.write_bytes(0x34ACD0, bytearray([0xEA, 0xEA]))
|
|
||||||
|
|
||||||
# Banana Bird Costs
|
|
||||||
if world.options.goal == "banana_bird_hunt":
|
|
||||||
banana_bird_cost = math.floor(world.options.number_of_banana_birds * world.options.percentage_of_banana_birds / 100.0)
|
|
||||||
rom.write_byte(0x34AB85, banana_bird_cost)
|
|
||||||
rom.write_byte(0x329FD8, banana_bird_cost)
|
|
||||||
rom.write_byte(0x32A025, banana_bird_cost)
|
|
||||||
rom.write_byte(0x329FDA, 0xB0)
|
|
||||||
else:
|
|
||||||
# rom.write_byte(0x34AB84, 0x20) # These cause hangs at Wrinkly's
|
|
||||||
# rom.write_byte(0x329FD8, 0x20)
|
|
||||||
# rom.write_byte(0x32A025, 0x20)
|
|
||||||
rom.write_byte(0x329FDA, 0xB0)
|
|
||||||
|
|
||||||
# Baffle Mirror Fix
|
|
||||||
rom.write_byte(0x9133, 0x08)
|
|
||||||
rom.write_byte(0x9135, 0x0C)
|
|
||||||
rom.write_byte(0x9136, 0x2B)
|
|
||||||
rom.write_byte(0x9137, 0x06)
|
|
||||||
|
|
||||||
# Palette Swap
|
|
||||||
rom.write_byte(0x3B96A5, 0xD0)
|
|
||||||
if world.options.kong_palette_swap == "default":
|
|
||||||
rom.write_byte(0x3B96A9, 0x00)
|
|
||||||
rom.write_byte(0x3B96A8, 0x00)
|
|
||||||
elif world.options.kong_palette_swap == "purple":
|
|
||||||
rom.write_byte(0x3B96A9, 0x00)
|
|
||||||
rom.write_byte(0x3B96A8, 0x3C)
|
|
||||||
elif world.options.kong_palette_swap == "spooky":
|
|
||||||
rom.write_byte(0x3B96A9, 0x00)
|
|
||||||
rom.write_byte(0x3B96A8, 0xA0)
|
|
||||||
elif world.options.kong_palette_swap == "dark":
|
|
||||||
rom.write_byte(0x3B96A9, 0x05)
|
|
||||||
rom.write_byte(0x3B96A8, 0xA0)
|
|
||||||
elif world.options.kong_palette_swap == "chocolate":
|
|
||||||
rom.write_byte(0x3B96A9, 0x1D)
|
|
||||||
rom.write_byte(0x3B96A8, 0xA0)
|
|
||||||
elif world.options.kong_palette_swap == "shadow":
|
|
||||||
rom.write_byte(0x3B96A9, 0x45)
|
|
||||||
rom.write_byte(0x3B96A8, 0xA0)
|
|
||||||
elif world.options.kong_palette_swap == "red_gold":
|
|
||||||
rom.write_byte(0x3B96A9, 0x5D)
|
|
||||||
rom.write_byte(0x3B96A8, 0xA0)
|
|
||||||
elif world.options.kong_palette_swap == "gbc":
|
|
||||||
rom.write_byte(0x3B96A9, 0x20)
|
|
||||||
rom.write_byte(0x3B96A8, 0x3C)
|
|
||||||
elif world.options.kong_palette_swap == "halloween":
|
|
||||||
rom.write_byte(0x3B96A9, 0x70)
|
|
||||||
rom.write_byte(0x3B96A8, 0x3C)
|
|
||||||
|
|
||||||
if world.options.music_shuffle:
|
|
||||||
for address in music_rom_data:
|
|
||||||
rand_song = world.random.choice(level_music_ids)
|
|
||||||
rom.write_byte(address, rand_song)
|
|
||||||
|
|
||||||
# Starting Lives
|
|
||||||
rom.write_byte(0x9130, world.options.starting_life_count.value)
|
|
||||||
rom.write_byte(0x913B, world.options.starting_life_count.value)
|
|
||||||
|
|
||||||
# Cheat options
|
|
||||||
cheat_bytes = [0x00, 0x00]
|
|
||||||
|
|
||||||
if world.options.merry:
|
|
||||||
cheat_bytes[0] |= 0x01
|
|
||||||
|
|
||||||
if world.options.autosave:
|
|
||||||
cheat_bytes[0] |= 0x02
|
|
||||||
|
|
||||||
if world.options.difficulty == "tufst":
|
|
||||||
cheat_bytes[0] |= 0x80
|
|
||||||
cheat_bytes[1] |= 0x80
|
|
||||||
elif world.options.difficulty == "hardr":
|
|
||||||
cheat_bytes[0] |= 0x00
|
|
||||||
cheat_bytes[1] |= 0x00
|
|
||||||
elif world.options.difficulty == "norml":
|
|
||||||
cheat_bytes[1] |= 0x40
|
|
||||||
|
|
||||||
rom.write_bytes(0x8303, bytearray(cheat_bytes))
|
|
||||||
|
|
||||||
# Handle Level Shuffle Here
|
|
||||||
if world.options.level_shuffle:
|
|
||||||
for i in range(len(active_level_list)):
|
|
||||||
rom.write_byte(level_dict[level_list[i]].nameIDAddress, level_dict[active_level_list[i]].nameID)
|
|
||||||
rom.write_byte(level_dict[level_list[i]].levelIDAddress, level_dict[active_level_list[i]].levelID)
|
|
||||||
|
|
||||||
rom.write_byte(0x3FF800 + level_dict[active_level_list[i]].levelID, level_dict[level_list[i]].levelID)
|
|
||||||
rom.write_byte(0x3FF860 + level_dict[level_list[i]].levelID, level_dict[active_level_list[i]].levelID)
|
|
||||||
|
|
||||||
# First levels of each world
|
|
||||||
rom.write_byte(0x34BC3E, (0x32 + level_dict[active_level_list[0]].levelID))
|
|
||||||
rom.write_byte(0x34BC47, (0x32 + level_dict[active_level_list[5]].levelID))
|
|
||||||
rom.write_byte(0x34BC4A, (0x32 + level_dict[active_level_list[10]].levelID))
|
|
||||||
rom.write_byte(0x34BC53, (0x32 + level_dict[active_level_list[15]].levelID))
|
|
||||||
rom.write_byte(0x34BC59, (0x32 + level_dict[active_level_list[20]].levelID))
|
|
||||||
rom.write_byte(0x34BC5C, (0x32 + level_dict[active_level_list[25]].levelID))
|
|
||||||
rom.write_byte(0x34BC65, (0x32 + level_dict[active_level_list[30]].levelID))
|
|
||||||
rom.write_byte(0x34BC6E, (0x32 + level_dict[active_level_list[35]].levelID))
|
|
||||||
|
|
||||||
# Cotton-Top Cove Boss Unlock
|
|
||||||
rom.write_byte(0x34C02A, (0x32 + level_dict[active_level_list[14]].levelID))
|
|
||||||
|
|
||||||
# Kong-Fused Cliffs Unlock
|
|
||||||
rom.write_byte(0x34C213, (0x32 + level_dict[active_level_list[25]].levelID))
|
|
||||||
rom.write_byte(0x34C21B, (0x32 + level_dict[active_level_list[26]].levelID))
|
|
||||||
|
|
||||||
if world.options.goal == "knautilus":
|
|
||||||
# Swap Kastle KAOS and Knautilus
|
|
||||||
rom.write_byte(0x34D4E1, 0xC2)
|
|
||||||
rom.write_byte(0x34D4E2, 0x24)
|
|
||||||
rom.write_byte(0x34D551, 0xBA)
|
|
||||||
rom.write_byte(0x34D552, 0x23)
|
|
||||||
|
|
||||||
rom.write_byte(0x32F339, 0x55)
|
|
||||||
|
|
||||||
# Handle KONGsanity Here
|
|
||||||
if world.options.kongsanity:
|
|
||||||
# Arich's Hoard KONGsanity fix
|
|
||||||
rom.write_bytes(0x34BA8C, bytearray([0xEA, 0xEA]))
|
|
||||||
|
|
||||||
# Don't hide the level flag if the 0x80 bit is set
|
|
||||||
rom.write_bytes(0x34CE92, bytearray([0x80]))
|
|
||||||
|
|
||||||
# Use the `!` next to level name for indicating KONG letters
|
|
||||||
rom.write_bytes(0x34B8F0, bytearray([0x80]))
|
|
||||||
rom.write_bytes(0x34B8F3, bytearray([0x80]))
|
|
||||||
|
|
||||||
# Hijack to code to set the 0x80 flag for the level when you complete KONG
|
|
||||||
rom.write_bytes(0x3BCD4B, bytearray([0x22, 0x80, 0xFA, 0XB8])) # JSL $B8FA80
|
|
||||||
|
|
||||||
rom.write_bytes(0x38FA80, bytearray([0xDA])) # PHX
|
|
||||||
rom.write_bytes(0x38FA81, bytearray([0x48])) # PHA
|
|
||||||
rom.write_bytes(0x38FA82, bytearray([0x08])) # PHP
|
|
||||||
rom.write_bytes(0x38FA83, bytearray([0xE2, 0x20])) # SEP #20
|
|
||||||
rom.write_bytes(0x38FA85, bytearray([0x48])) # PHA
|
|
||||||
rom.write_bytes(0x38FA86, bytearray([0x18])) # CLC
|
|
||||||
rom.write_bytes(0x38FA87, bytearray([0x6D, 0xD3, 0x18])) # ADC $18D3
|
|
||||||
rom.write_bytes(0x38FA8A, bytearray([0x8D, 0xD3, 0x18])) # STA $18D3
|
|
||||||
rom.write_bytes(0x38FA8D, bytearray([0x68])) # PLA
|
|
||||||
rom.write_bytes(0x38FA8E, bytearray([0xC2, 0x20])) # REP 20
|
|
||||||
rom.write_bytes(0x38FA90, bytearray([0X18])) # CLC
|
|
||||||
rom.write_bytes(0x38FA91, bytearray([0x6D, 0xD5, 0x05])) # ADC $05D5
|
|
||||||
rom.write_bytes(0x38FA94, bytearray([0x8D, 0xD5, 0x05])) # STA $05D5
|
|
||||||
rom.write_bytes(0x38FA97, bytearray([0xAE, 0xB9, 0x05])) # LDX $05B9
|
|
||||||
rom.write_bytes(0x38FA9A, bytearray([0xBD, 0x32, 0x06])) # LDA $0632, X
|
|
||||||
rom.write_bytes(0x38FA9D, bytearray([0x09, 0x80, 0x00])) # ORA #8000
|
|
||||||
rom.write_bytes(0x38FAA0, bytearray([0x9D, 0x32, 0x06])) # STA $0632, X
|
|
||||||
rom.write_bytes(0x38FAA3, bytearray([0xAD, 0xD5, 0x18])) # LDA $18D5
|
|
||||||
rom.write_bytes(0x38FAA6, bytearray([0xD0, 0x03])) # BNE $80EA
|
|
||||||
rom.write_bytes(0x38FAA8, bytearray([0x9C, 0xD9, 0x18])) # STZ $18D9
|
|
||||||
rom.write_bytes(0x38FAAB, bytearray([0xA9, 0x78, 0x00])) # LDA #0078
|
|
||||||
rom.write_bytes(0x38FAAE, bytearray([0x8D, 0xD5, 0x18])) # STA $18D5
|
|
||||||
rom.write_bytes(0x38FAB1, bytearray([0x28])) # PLP
|
|
||||||
rom.write_bytes(0x38FAB2, bytearray([0x68])) # PLA
|
|
||||||
rom.write_bytes(0x38FAB3, bytearray([0xFA])) # PLX
|
|
||||||
rom.write_bytes(0x38FAB4, bytearray([0x6B])) # RTL
|
|
||||||
# End Handle KONGsanity
|
|
||||||
|
|
||||||
# Handle Credits
|
|
||||||
rom.write_bytes(0x32A5DF, bytearray([0x41, 0x52, 0x43, 0x48, 0x49, 0x50, 0x45, 0x4C, 0x41, 0x47, 0x4F, 0x20, 0x4D, 0x4F, 0xC4])) # "ARCHIPELAGO MOD"
|
|
||||||
rom.write_bytes(0x32A5EE, bytearray([0x00, 0x03, 0x50, 0x4F, 0x52, 0x59, 0x47, 0x4F, 0x4E, 0xC5])) # "PORYGONE"
|
|
||||||
|
|
||||||
from Utils import __version__
|
|
||||||
rom.name = bytearray(f'D3{__version__.replace(".", "")[0:3]}_{world.player}_{world.multiworld.seed:11}\0', 'utf8')[:21]
|
|
||||||
rom.name.extend([0] * (21 - len(rom.name)))
|
|
||||||
rom.write_bytes(0x7FC0, rom.name)
|
|
||||||
|
|
||||||
# DKC3_TODO: This is a hack, reconsider
|
|
||||||
# Don't grant (DK, Bonus, Bear) Coins
|
|
||||||
rom.write_byte(0x3BD454, 0xEA)
|
|
||||||
rom.write_byte(0x3BD455, 0xEA)
|
|
||||||
|
|
||||||
# Don't grant Cogs
|
|
||||||
rom.write_byte(0x3BD574, 0xEA)
|
|
||||||
rom.write_byte(0x3BD575, 0xEA)
|
|
||||||
rom.write_byte(0x3BD576, 0xEA)
|
|
||||||
|
|
||||||
# Don't grant Banana Birds at their caves
|
|
||||||
rom.write_byte(0x32DD62, 0xEA)
|
|
||||||
rom.write_byte(0x32DD63, 0xEA)
|
|
||||||
rom.write_byte(0x32DD64, 0xEA)
|
|
||||||
|
|
||||||
# Don't grant Banana Birds at Bears
|
|
||||||
rom.write_byte(0x3492DB, 0xEA)
|
|
||||||
rom.write_byte(0x3492DC, 0xEA)
|
|
||||||
rom.write_byte(0x3492DD, 0xEA)
|
|
||||||
rom.write_byte(0x3493F4, 0xEA)
|
|
||||||
rom.write_byte(0x3493F5, 0xEA)
|
|
||||||
rom.write_byte(0x3493F6, 0xEA)
|
|
||||||
|
|
||||||
# Don't grant present at Blizzard
|
|
||||||
rom.write_byte(0x8454, 0x00)
|
|
||||||
|
|
||||||
# Don't grant Patch and Skis from their bosses
|
|
||||||
rom.write_byte(0x3F3762, 0x00)
|
|
||||||
rom.write_byte(0x3F377B, 0x00)
|
|
||||||
rom.write_byte(0x3F3797, 0x00)
|
|
||||||
|
|
||||||
# Always allow Start+Select
|
|
||||||
rom.write_byte(0x8BAB, 0x01)
|
|
||||||
|
|
||||||
# Handle Alt Palettes in Krematoa
|
|
||||||
rom.write_byte(0x3B97E9, 0x80)
|
|
||||||
rom.write_byte(0x3B97EA, 0xEA)
|
|
||||||
|
|
||||||
|
|
||||||
class DKC3DeltaPatch(APDeltaPatch):
|
|
||||||
hash = USHASH
|
|
||||||
game = "Donkey Kong Country 3"
|
|
||||||
patch_file_ending = ".apdkc3"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_source_data(cls) -> bytes:
|
|
||||||
return get_base_rom_bytes()
|
|
||||||
|
|
||||||
|
|
||||||
def get_base_rom_bytes(file_name: str = "") -> bytes:
|
|
||||||
base_rom_bytes = getattr(get_base_rom_bytes, "base_rom_bytes", None)
|
|
||||||
if not base_rom_bytes:
|
|
||||||
file_name = get_base_rom_path(file_name)
|
|
||||||
base_rom_bytes = bytes(read_snes_rom(open(file_name, "rb")))
|
|
||||||
|
|
||||||
basemd5 = hashlib.md5()
|
|
||||||
basemd5.update(base_rom_bytes)
|
|
||||||
if USHASH != basemd5.hexdigest():
|
|
||||||
raise Exception('Supplied Base Rom does not match known MD5 for US(1.0) release. '
|
|
||||||
'Get the correct game and version, then dump it')
|
|
||||||
get_base_rom_bytes.base_rom_bytes = base_rom_bytes
|
|
||||||
return base_rom_bytes
|
|
||||||
|
|
||||||
def get_base_rom_path(file_name: str = "") -> str:
|
|
||||||
if not file_name:
|
|
||||||
from settings import get_settings
|
|
||||||
file_name = get_settings()["dkc3_options"]["rom_file"]
|
|
||||||
if not os.path.exists(file_name):
|
|
||||||
file_name = Utils.user_path(file_name)
|
|
||||||
return file_name
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import math
|
|
||||||
|
|
||||||
from worlds.AutoWorld import World
|
|
||||||
from worlds.generic.Rules import add_rule
|
|
||||||
from .Names import LocationName, ItemName
|
|
||||||
|
|
||||||
|
|
||||||
def set_rules(world: World):
|
|
||||||
|
|
||||||
if False:#world.options.include_trade_sequence:
|
|
||||||
add_rule(world.multiworld.get_location(LocationName.barnacles_island, world.player),
|
|
||||||
lambda state: state.has(ItemName.shell, world.player))
|
|
||||||
|
|
||||||
add_rule(world.multiworld.get_location(LocationName.blues_beach_hut, world.player),
|
|
||||||
lambda state: state.has(ItemName.present, world.player))
|
|
||||||
|
|
||||||
add_rule(world.multiworld.get_location(LocationName.brambles_bungalow, world.player),
|
|
||||||
lambda state: state.has(ItemName.flower, world.player))
|
|
||||||
|
|
||||||
add_rule(world.multiworld.get_location(LocationName.barters_swap_shop, world.player),
|
|
||||||
lambda state: state.has(ItemName.mirror, world.player))
|
|
||||||
|
|
||||||
|
|
||||||
if world.options.goal != "knautilus":
|
|
||||||
required_banana_birds = math.floor(
|
|
||||||
world.options.number_of_banana_birds.value * (world.options.percentage_of_banana_birds.value / 100.0))
|
|
||||||
|
|
||||||
add_rule(world.multiworld.get_location(LocationName.banana_bird_mother, world.player),
|
|
||||||
lambda state: state.has(ItemName.banana_bird, world.player, required_banana_birds))
|
|
||||||
|
|
||||||
world.multiworld.completion_condition[world.player] = lambda state: state.has(ItemName.victory, world.player)
|
|
||||||
@@ -1,233 +0,0 @@
|
|||||||
import dataclasses
|
|
||||||
import math
|
|
||||||
import os
|
|
||||||
import threading
|
|
||||||
import typing
|
|
||||||
|
|
||||||
import settings
|
|
||||||
from BaseClasses import Item, MultiWorld, Tutorial, ItemClassification
|
|
||||||
from Options import PerGameCommonOptions
|
|
||||||
from worlds.AutoWorld import WebWorld, World
|
|
||||||
from .Client import DKC3SNIClient
|
|
||||||
from .Items import DKC3Item, ItemData, item_table, inventory_table, junk_table
|
|
||||||
from .Levels import level_list
|
|
||||||
from .Locations import DKC3Location, all_locations, setup_locations
|
|
||||||
from .Names import ItemName, LocationName
|
|
||||||
from .Options import DKC3Options, dkc3_option_groups
|
|
||||||
from .Regions import create_regions, connect_regions
|
|
||||||
from .Rom import LocalRom, patch_rom, get_base_rom_path, DKC3DeltaPatch
|
|
||||||
from .Rules import set_rules
|
|
||||||
|
|
||||||
|
|
||||||
class DK3Settings(settings.Group):
|
|
||||||
class RomFile(settings.UserFilePath):
|
|
||||||
"""File name of the DKC3 US rom"""
|
|
||||||
copy_to = "Donkey Kong Country 3 - Dixie Kong's Double Trouble! (USA) (En,Fr).sfc"
|
|
||||||
description = "DKC3 (US) ROM File"
|
|
||||||
md5s = [DKC3DeltaPatch.hash]
|
|
||||||
|
|
||||||
rom_file: RomFile = RomFile(RomFile.copy_to)
|
|
||||||
|
|
||||||
|
|
||||||
class DKC3Web(WebWorld):
|
|
||||||
theme = "jungle"
|
|
||||||
|
|
||||||
setup_en = Tutorial(
|
|
||||||
"Multiworld Setup Guide",
|
|
||||||
"A guide to setting up the Donkey Kong Country 3 randomizer connected to an Archipelago Multiworld.",
|
|
||||||
"English",
|
|
||||||
"setup_en.md",
|
|
||||||
"setup/en",
|
|
||||||
["PoryGone"]
|
|
||||||
)
|
|
||||||
|
|
||||||
tutorials = [setup_en]
|
|
||||||
|
|
||||||
option_groups = dkc3_option_groups
|
|
||||||
|
|
||||||
|
|
||||||
class DKC3World(World):
|
|
||||||
"""
|
|
||||||
Donkey Kong Country 3 is an action platforming game.
|
|
||||||
Play as Dixie Kong and her baby cousin Kiddy as they try to solve the
|
|
||||||
mystery of why Donkey Kong and Diddy disappeared while on vacation.
|
|
||||||
"""
|
|
||||||
game: str = "Donkey Kong Country 3"
|
|
||||||
settings: typing.ClassVar[DK3Settings]
|
|
||||||
|
|
||||||
options_dataclass = DKC3Options
|
|
||||||
options: DKC3Options
|
|
||||||
|
|
||||||
topology_present = False
|
|
||||||
#hint_blacklist = {LocationName.rocket_rush_flag}
|
|
||||||
|
|
||||||
item_name_to_id = {name: data.code for name, data in item_table.items()}
|
|
||||||
location_name_to_id = all_locations
|
|
||||||
|
|
||||||
active_level_list: typing.List[str]
|
|
||||||
web = DKC3Web()
|
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int):
|
|
||||||
self.rom_name_available_event = threading.Event()
|
|
||||||
super().__init__(world, player)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def stage_assert_generate(cls, multiworld: MultiWorld):
|
|
||||||
rom_file = get_base_rom_path()
|
|
||||||
if not os.path.exists(rom_file):
|
|
||||||
raise FileNotFoundError(rom_file)
|
|
||||||
|
|
||||||
def _get_slot_data(self):
|
|
||||||
return {
|
|
||||||
#"death_link": self.options.death_link.value,
|
|
||||||
"active_levels": self.active_level_list,
|
|
||||||
}
|
|
||||||
|
|
||||||
def fill_slot_data(self) -> dict:
|
|
||||||
slot_data = self._get_slot_data()
|
|
||||||
for option_name in (attr.name for attr in dataclasses.fields(DKC3Options)
|
|
||||||
if attr not in dataclasses.fields(PerGameCommonOptions)):
|
|
||||||
option = getattr(self.options, option_name)
|
|
||||||
slot_data[option_name] = option.value
|
|
||||||
|
|
||||||
return slot_data
|
|
||||||
|
|
||||||
def create_regions(self):
|
|
||||||
location_table = setup_locations(self)
|
|
||||||
create_regions(self, location_table)
|
|
||||||
|
|
||||||
# Not generate basic
|
|
||||||
self.topology_present = self.options.level_shuffle.value
|
|
||||||
itempool: typing.List[DKC3Item] = []
|
|
||||||
|
|
||||||
# Levels
|
|
||||||
total_required_locations = 159
|
|
||||||
|
|
||||||
number_of_banana_birds = 0
|
|
||||||
# Rocket Rush Cog
|
|
||||||
total_required_locations -= 1
|
|
||||||
number_of_cogs = 4
|
|
||||||
self.multiworld.get_location(LocationName.rocket_rush_flag, self.player).place_locked_item(self.create_item(ItemName.krematoa_cog))
|
|
||||||
number_of_bosses = 8
|
|
||||||
if self.options.goal == "knautilus":
|
|
||||||
self.multiworld.get_location(LocationName.kastle_kaos, self.player).place_locked_item(self.create_item(ItemName.victory))
|
|
||||||
number_of_bosses = 7
|
|
||||||
else:
|
|
||||||
self.multiworld.get_location(LocationName.banana_bird_mother, self.player).place_locked_item(self.create_item(ItemName.victory))
|
|
||||||
number_of_banana_birds = self.options.number_of_banana_birds
|
|
||||||
|
|
||||||
# Bosses
|
|
||||||
total_required_locations += number_of_bosses
|
|
||||||
|
|
||||||
# Secret Caves
|
|
||||||
total_required_locations += 13
|
|
||||||
|
|
||||||
if self.options.kongsanity:
|
|
||||||
total_required_locations += 39
|
|
||||||
|
|
||||||
## Brothers Bear
|
|
||||||
if False:#self.options.include_trade_sequence:
|
|
||||||
total_required_locations += 10
|
|
||||||
|
|
||||||
number_of_bonus_coins = (self.options.krematoa_bonus_coin_cost * 5)
|
|
||||||
number_of_bonus_coins += math.ceil((85 - number_of_bonus_coins) * self.options.percentage_of_extra_bonus_coins / 100)
|
|
||||||
|
|
||||||
itempool += [self.create_item(ItemName.bonus_coin) for _ in range(number_of_bonus_coins)]
|
|
||||||
itempool += [self.create_item(ItemName.dk_coin) for _ in range(41)]
|
|
||||||
itempool += [self.create_item(ItemName.banana_bird) for _ in range(number_of_banana_birds)]
|
|
||||||
itempool += [self.create_item(ItemName.krematoa_cog) for _ in range(number_of_cogs)]
|
|
||||||
itempool += [self.create_item(ItemName.progressive_boat) for _ in range(3)]
|
|
||||||
|
|
||||||
total_junk_count = total_required_locations - len(itempool)
|
|
||||||
|
|
||||||
junk_pool = []
|
|
||||||
for item_name in self.multiworld.random.choices(list(junk_table.keys()), k=total_junk_count):
|
|
||||||
junk_pool.append(self.create_item(item_name))
|
|
||||||
|
|
||||||
itempool += junk_pool
|
|
||||||
|
|
||||||
self.active_level_list = level_list.copy()
|
|
||||||
|
|
||||||
if self.options.level_shuffle:
|
|
||||||
self.random.shuffle(self.active_level_list)
|
|
||||||
|
|
||||||
connect_regions(self, self.active_level_list)
|
|
||||||
|
|
||||||
self.multiworld.itempool += itempool
|
|
||||||
|
|
||||||
def generate_output(self, output_directory: str):
|
|
||||||
try:
|
|
||||||
rom = LocalRom(get_base_rom_path())
|
|
||||||
patch_rom(self, rom, self.active_level_list)
|
|
||||||
|
|
||||||
self.active_level_list.append(LocationName.rocket_rush_region)
|
|
||||||
|
|
||||||
rompath = os.path.join(output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}.sfc")
|
|
||||||
rom.write_to_file(rompath)
|
|
||||||
self.rom_name = rom.name
|
|
||||||
|
|
||||||
patch = DKC3DeltaPatch(os.path.splitext(rompath)[0]+DKC3DeltaPatch.patch_file_ending, player=self.player,
|
|
||||||
player_name=self.multiworld.player_name[self.player], patched_path=rompath)
|
|
||||||
patch.write()
|
|
||||||
except:
|
|
||||||
raise
|
|
||||||
finally:
|
|
||||||
self.rom_name_available_event.set() # make sure threading continues and errors are collected
|
|
||||||
if os.path.exists(rompath):
|
|
||||||
os.unlink(rompath)
|
|
||||||
|
|
||||||
def modify_multidata(self, multidata: dict):
|
|
||||||
import base64
|
|
||||||
# wait for self.rom_name to be available.
|
|
||||||
self.rom_name_available_event.wait()
|
|
||||||
rom_name = getattr(self, "rom_name", None)
|
|
||||||
# we skip in case of error, so that the original error in the output thread is the one that gets raised
|
|
||||||
if rom_name:
|
|
||||||
new_name = base64.b64encode(bytes(self.rom_name)).decode()
|
|
||||||
multidata["connect_names"][new_name] = multidata["connect_names"][self.multiworld.player_name[self.player]]
|
|
||||||
|
|
||||||
def extend_hint_information(self, hint_data: typing.Dict[int, typing.Dict[int, str]]):
|
|
||||||
if self.topology_present:
|
|
||||||
world_names = [
|
|
||||||
LocationName.lake_orangatanga_region,
|
|
||||||
LocationName.kremwood_forest_region,
|
|
||||||
LocationName.cotton_top_cove_region,
|
|
||||||
LocationName.mekanos_region,
|
|
||||||
LocationName.k3_region,
|
|
||||||
LocationName.razor_ridge_region,
|
|
||||||
LocationName.kaos_kore_region,
|
|
||||||
LocationName.krematoa_region,
|
|
||||||
]
|
|
||||||
er_hint_data = {}
|
|
||||||
for world_index in range(len(world_names)):
|
|
||||||
for level_index in range(5):
|
|
||||||
level_id: int = world_index * 5 + level_index
|
|
||||||
|
|
||||||
if level_id >= len(self.active_level_list):
|
|
||||||
break
|
|
||||||
|
|
||||||
level_region = self.multiworld.get_region(self.active_level_list[level_id], self.player)
|
|
||||||
for location in level_region.locations:
|
|
||||||
er_hint_data[location.address] = world_names[world_index]
|
|
||||||
|
|
||||||
hint_data[self.player] = er_hint_data
|
|
||||||
|
|
||||||
def create_item(self, name: str, force_non_progression=False) -> Item:
|
|
||||||
data = item_table[name]
|
|
||||||
|
|
||||||
if force_non_progression:
|
|
||||||
classification = ItemClassification.filler
|
|
||||||
elif data.progression:
|
|
||||||
classification = ItemClassification.progression
|
|
||||||
else:
|
|
||||||
classification = ItemClassification.filler
|
|
||||||
|
|
||||||
created_item = DKC3Item(name, classification, data.code, self.player)
|
|
||||||
|
|
||||||
return created_item
|
|
||||||
|
|
||||||
def get_filler_item_name(self) -> str:
|
|
||||||
return self.multiworld.random.choice(list(junk_table.keys()))
|
|
||||||
|
|
||||||
def set_rules(self):
|
|
||||||
set_rules(self)
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"game": "Donkey Kong Country 3",
|
|
||||||
"authors": [ "PoryGone" ],
|
|
||||||
"minimum_ap_version": "0.6.3",
|
|
||||||
"world_version": "1.1.0"
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Donkey Kong Country 3
|
|
||||||
|
|
||||||
## Where is the options page?
|
|
||||||
|
|
||||||
The [player options page for this game](../player-options) contains all the options you need to configure and export a config file.
|
|
||||||
|
|
||||||
## What does randomization do to this game?
|
|
||||||
|
|
||||||
Items which the player would normally acquire throughout the game have been moved around. Logic remains, so the game is
|
|
||||||
always able to be completed, but because of the item shuffle the player may need to access certain areas before they
|
|
||||||
would in the vanilla game.
|
|
||||||
|
|
||||||
## What is the goal of Donkey Kong Country 3 when randomized?
|
|
||||||
|
|
||||||
There are two goals which can be chosen:
|
|
||||||
- `Knautilus`: Collect Bonus Coins and Krematoa Cogs to reach K. Rool's submarine in Krematoa
|
|
||||||
- `Banana Bird Hunt`: Collect Banana Birds to free the Banana Bird Mother
|
|
||||||
|
|
||||||
## What items and locations get shuffled?
|
|
||||||
|
|
||||||
All Bonus Coins, DK Coins, and Banana Birds (if on a `Banana Bird Hunt` goal) are randomized. Additionally, level clears award a location check.
|
|
||||||
The Patch and two Skis for upgrading the boat are included. Bear Coins are provided if additional items are needed for the item pool.
|
|
||||||
Four of the Five Krematoa Cogs are randomized, but the final one is always in its vanilla location at the Flag of Rocket Rush in Krematoa
|
|
||||||
|
|
||||||
## Which items can be in another player's world?
|
|
||||||
|
|
||||||
Any shuffled item can be in other players' worlds.
|
|
||||||
|
|
||||||
## What does another world's item look like in Donkey Kong Country 3
|
|
||||||
|
|
||||||
Items pickups all retain their original appearance. You won't know if an item belongs to another player until you collect.
|
|
||||||
|
|
||||||
## When the player receives an item, what happens?
|
|
||||||
|
|
||||||
Currently, the items are silently added to the player's inventory, which can be seen when saving the game.
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
# Donkey Kong Country 3 Randomizer Setup Guide
|
|
||||||
|
|
||||||
## Required Software
|
|
||||||
|
|
||||||
- [Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases).
|
|
||||||
|
|
||||||
|
|
||||||
- Hardware or software capable of loading and playing SNES ROM files
|
|
||||||
- An emulator capable of connecting to SNI such as:
|
|
||||||
- snes9x-rr from: [snes9x rr](https://github.com/gocha/snes9x-rr/releases),
|
|
||||||
- BizHawk from: [TASVideos](https://tasvideos.org/BizHawk)
|
|
||||||
- RetroArch 1.10.3 or newer from: [RetroArch Website](https://retroarch.com?page=platforms). Or,
|
|
||||||
- An SD2SNES, FXPak Pro ([FXPak Pro Store Page](https://krikzz.com/store/home/54-fxpak-pro.html)), or other
|
|
||||||
compatible hardware
|
|
||||||
- Your legally obtained Donkey Kong Country 3 ROM file, probably named `Donkey Kong Country 3 - Dixie Kong's Double Trouble! (USA) (En,Fr).sfc`
|
|
||||||
|
|
||||||
## Optional Software
|
|
||||||
- Donkey Kong Country 3 Tracker
|
|
||||||
- PopTracker from: [PopTracker Releases Page](https://github.com/black-sliver/PopTracker/releases/)
|
|
||||||
- Donkey Kong Country 3 Archipelago PopTracker pack from: [DKC3 AP Tracker Releases Page](https://github.com/PoryGone/DKC3_AP_Tracker/releases/)
|
|
||||||
|
|
||||||
## Installation Procedures
|
|
||||||
|
|
||||||
### Windows Setup
|
|
||||||
|
|
||||||
1. Download and install [Archipelago](<https://github.com/ArchipelagoMW/Archipelago/releases/latest>). **The installer
|
|
||||||
file is located in the assets section at the bottom of the version information.**
|
|
||||||
2. The first time you do local generation or patch your game, you will be asked to locate your base ROM file.
|
|
||||||
This is your Donkey Kong Country 3 ROM file. This only needs to be done once.
|
|
||||||
3. If you are using an emulator, you should assign your Lua capable emulator as your default program for launching ROM
|
|
||||||
files.
|
|
||||||
1. Extract your emulator's folder to your Desktop, or somewhere you will remember.
|
|
||||||
2. Right-click on a ROM file and select **Open with...**
|
|
||||||
3. Check the box next to **Always use this app to open .sfc files**
|
|
||||||
4. Scroll to the bottom of the list and click the grey text **Look for another App on this PC**
|
|
||||||
5. Browse for your emulator's `.exe` file and click **Open**. This file should be located inside the folder you
|
|
||||||
extracted in step one.
|
|
||||||
|
|
||||||
## Create a Config (.yaml) File
|
|
||||||
|
|
||||||
### What is a config file and why do I need one?
|
|
||||||
|
|
||||||
See the guide on setting up a basic YAML at the Archipelago setup
|
|
||||||
guide: [Basic Multiworld Setup Guide](/tutorial/Archipelago/setup/en)
|
|
||||||
|
|
||||||
### Where do I get a config file?
|
|
||||||
|
|
||||||
The Player Options page on the website allows you to configure your personal options and export a config file from
|
|
||||||
them. Player options page: [Donkey Kong Country 3 Player Options Page](/games/Donkey%20Kong%20Country%203/player-options)
|
|
||||||
|
|
||||||
### Verifying your config file
|
|
||||||
|
|
||||||
If you would like to validate your config file to make sure it works, you may do so on the YAML Validator page. YAML
|
|
||||||
validator page: [YAML Validation page](/check)
|
|
||||||
|
|
||||||
## Generating a Single-Player Game
|
|
||||||
|
|
||||||
1. Navigate to the Player Options page, configure your options, and click the "Generate Game" button.
|
|
||||||
- Player Options page: [Donkey Kong Country 3 Player Options Page](/games/Donkey%20Kong%20Country%203/player-options)
|
|
||||||
2. You will be presented with a "Seed Info" page.
|
|
||||||
3. Click the "Create New Room" link.
|
|
||||||
4. You will be presented with a server page, from which you can download your patch file.
|
|
||||||
5. Double-click on your patch file, and the Donkey Kong Country 3 Client will launch automatically, create your ROM from the
|
|
||||||
patch file, and open your emulator for you.
|
|
||||||
|
|
||||||
## Joining a MultiWorld Game
|
|
||||||
|
|
||||||
### Obtain your patch file and create your ROM
|
|
||||||
|
|
||||||
When you join a multiworld game, you will be asked to provide your config file to whoever is hosting. Once that is done,
|
|
||||||
the host will provide you with either a link to download your patch file, or with a zip file containing everyone's patch
|
|
||||||
files. Your patch file should have a `.apdkc3` extension.
|
|
||||||
|
|
||||||
Put your patch file on your desktop or somewhere convenient, and double click it. This should automatically launch the
|
|
||||||
client, and will also create your ROM in the same place as your patch file.
|
|
||||||
|
|
||||||
### Connect to the client
|
|
||||||
|
|
||||||
#### With an emulator
|
|
||||||
|
|
||||||
When the client launched automatically, SNI should have also automatically launched in the background. If this is its
|
|
||||||
first time launching, you may be prompted to allow it to communicate through the Windows Firewall.
|
|
||||||
|
|
||||||
##### snes9x-rr
|
|
||||||
|
|
||||||
1. Load your ROM file if it hasn't already been loaded.
|
|
||||||
2. Click on the File menu and hover on **Lua Scripting**
|
|
||||||
3. Click on **New Lua Script Window...**
|
|
||||||
4. In the new window, click **Browse...**
|
|
||||||
5. Select the connector lua file included with your client
|
|
||||||
- Look in the Archipelago folder for `/SNI/lua/Connector.lua`.
|
|
||||||
6. If you see an error while loading the script that states `socket.dll missing` or similar, navigate to the folder of
|
|
||||||
the lua you are using in your file explorer and copy the `socket.dll` to the base folder of your snes9x install.
|
|
||||||
|
|
||||||
##### BizHawk
|
|
||||||
|
|
||||||
1. Ensure you have the BSNES core loaded. This is done with the main menubar, under:
|
|
||||||
- (≤ 2.8) `Config` 〉 `Cores` 〉 `SNES` 〉 `BSNES`
|
|
||||||
- (≥ 2.9) `Config` 〉 `Preferred Cores` 〉 `SNES` 〉 `BSNESv115+`
|
|
||||||
2. Load your ROM file if it hasn't already been loaded.
|
|
||||||
If you changed your core preference after loading the ROM, don't forget to reload it (default hotkey: Ctrl+R).
|
|
||||||
3. Drag+drop the `Connector.lua` file included with your client onto the main EmuHawk window.
|
|
||||||
- Look in the Archipelago folder for `/SNI/lua/Connector.lua`.
|
|
||||||
- You could instead open the Lua Console manually, click `Script` 〉 `Open Script`, and navigate to `Connector.lua`
|
|
||||||
with the file picker.
|
|
||||||
|
|
||||||
##### RetroArch 1.10.3 or newer
|
|
||||||
|
|
||||||
You only have to do these steps once. Note, RetroArch 1.9.x will not work as it is older than 1.10.3.
|
|
||||||
|
|
||||||
1. Enter the RetroArch main menu screen.
|
|
||||||
2. Go to Settings --> User Interface. Set "Show Advanced Settings" to ON.
|
|
||||||
3. Go to Settings --> Network. Set "Network Commands" to ON. (It is found below Request Device 16.) Leave the default
|
|
||||||
Network Command Port at 55355. \
|
|
||||||

|
|
||||||
4. Go to Main Menu --> Online Updater --> Core Downloader. Scroll down and select "Nintendo - SNES / SFC (bsnes-mercury
|
|
||||||
Performance)".
|
|
||||||
|
|
||||||
When loading a ROM, be sure to select a **bsnes-mercury** core. These are the only cores that allow external tools to
|
|
||||||
read ROM data.
|
|
||||||
|
|
||||||
#### With hardware
|
|
||||||
|
|
||||||
This guide assumes you have downloaded the correct firmware for your device. If you have not done so already, please do
|
|
||||||
this now. SD2SNES and FXPak Pro users may download the appropriate firmware on the SD2SNES releases page. SD2SNES
|
|
||||||
releases page: [SD2SNES Releases Page](https://github.com/RedGuyyyy/sd2snes/releases)
|
|
||||||
|
|
||||||
Other hardware may find helpful information on the usb2snes platforms
|
|
||||||
page: [usb2snes Supported Platforms Page](http://usb2snes.com/#supported-platforms)
|
|
||||||
|
|
||||||
1. Close your emulator, which may have auto-launched.
|
|
||||||
2. Power on your device and load the ROM.
|
|
||||||
|
|
||||||
### Connect to the Archipelago Server
|
|
||||||
|
|
||||||
The patch file which launched your client should have automatically connected you to the AP Server. There are a few
|
|
||||||
reasons this may not happen however, including if the game is hosted on the website but was generated elsewhere. If the
|
|
||||||
client window shows "Server Status: Not Connected", simply ask the host for the address of the server, and copy/paste it
|
|
||||||
into the "Server" input field then press enter.
|
|
||||||
|
|
||||||
The client will attempt to reconnect to the new server address, and should momentarily show "Server Status: Connected".
|
|
||||||
|
|
||||||
### Play the game
|
|
||||||
|
|
||||||
When the client shows both SNES Device and Server as connected, you're ready to begin playing. Congratulations on
|
|
||||||
successfully joining a multiworld game!
|
|
||||||
|
|
||||||
## Hosting a MultiWorld game
|
|
||||||
|
|
||||||
The recommended way to host a game is to use our hosting service. The process is relatively simple:
|
|
||||||
|
|
||||||
1. Collect config files from your players.
|
|
||||||
2. Create a zip file containing your players' config files.
|
|
||||||
3. Upload that zip file to the Generate page above.
|
|
||||||
- Generate page: [WebHost Seed Generation Page](/generate)
|
|
||||||
4. Wait a moment while the seed is generated.
|
|
||||||
5. When the seed is generated, you will be redirected to a "Seed Info" page.
|
|
||||||
6. Click "Create New Room". This will take you to the server page. Provide the link to this page to your players, so
|
|
||||||
they may download their patch files from there.
|
|
||||||
7. Note that a link to a MultiWorld Tracker is at the top of the room page. The tracker shows the progress of all
|
|
||||||
players in the game. Any observers may also be given the link to this page.
|
|
||||||
8. Once all players have joined, you may begin playing.
|
|
||||||
+29
-29
@@ -45,35 +45,35 @@ def create_regions(multiworld: MultiWorld, player: int, world_options: Options.D
|
|||||||
|
|
||||||
|
|
||||||
def create_regions_basic_campaign(has_campaign_basic: bool, region_menu: Region, has_item_shuffle: bool, has_coinsanity: bool,
|
def create_regions_basic_campaign(has_campaign_basic: bool, region_menu: Region, has_item_shuffle: bool, has_coinsanity: bool,
|
||||||
coin_bundle_size: int, player: int, world: MultiWorld):
|
coin_bundle_size: int, player: int, multiworld: MultiWorld):
|
||||||
if not has_campaign_basic:
|
if not has_campaign_basic:
|
||||||
return
|
return
|
||||||
|
|
||||||
region_menu.exits += [Entrance(player, "DLC Quest Basic", region_menu)]
|
region_menu.exits += [Entrance(player, "DLC Quest Basic", region_menu)]
|
||||||
locations_move_right = ["Movement Pack", "Animation Pack", "Audio Pack", "Pause Menu Pack"]
|
locations_move_right = ["Movement Pack", "Animation Pack", "Audio Pack", "Pause Menu Pack"]
|
||||||
region_move_right = create_region_and_locations_basic("Move Right", locations_move_right, ["Moving"], player, world, 4)
|
region_move_right = create_region_and_locations_basic("Move Right", locations_move_right, ["Moving"], player, multiworld, 4)
|
||||||
create_coinsanity_locations_dlc_quest(has_coinsanity, coin_bundle_size, player, region_move_right)
|
create_coinsanity_locations_dlc_quest(has_coinsanity, coin_bundle_size, player, region_move_right)
|
||||||
locations_movement_pack = ["Time is Money Pack", "Psychological Warfare Pack", "Armor for your Horse Pack", "Shepherd Sheep"]
|
locations_movement_pack = ["Time is Money Pack", "Psychological Warfare Pack", "Armor for your Horse Pack", "Shepherd Sheep"]
|
||||||
locations_movement_pack += conditional_location(has_item_shuffle, "Sword")
|
locations_movement_pack += conditional_location(has_item_shuffle, "Sword")
|
||||||
create_region_and_locations_basic("Movement Pack", locations_movement_pack, ["Tree", "Cloud"], player, world, 46)
|
create_region_and_locations_basic("Movement Pack", locations_movement_pack, ["Tree", "Cloud"], player, multiworld, 46)
|
||||||
locations_behind_tree = ["Double Jump Pack", "Map Pack", "Between Trees Sheep", "Hole in the Wall Sheep"] + conditional_location(has_item_shuffle, "Gun")
|
locations_behind_tree = ["Double Jump Pack", "Map Pack", "Between Trees Sheep", "Hole in the Wall Sheep"] + conditional_location(has_item_shuffle, "Gun")
|
||||||
create_region_and_locations_basic("Behind Tree", locations_behind_tree, ["Behind Tree Double Jump", "Forest Entrance"], player, world, 60)
|
create_region_and_locations_basic("Behind Tree", locations_behind_tree, ["Behind Tree Double Jump", "Forest Entrance"], player, multiworld, 60)
|
||||||
create_region_and_locations_basic("Psychological Warfare", ["West Cave Sheep"], ["Cloud Double Jump"], player, world, 100)
|
create_region_and_locations_basic("Psychological Warfare", ["West Cave Sheep"], ["Cloud Double Jump"], player, multiworld, 100)
|
||||||
locations_double_jump_left = ["Pet Pack", "Top Hat Pack", "North West Alcove Sheep"]
|
locations_double_jump_left = ["Pet Pack", "Top Hat Pack", "North West Alcove Sheep"]
|
||||||
create_region_and_locations_basic("Double Jump Total Left", locations_double_jump_left, ["Cave Tree", "Cave Roof"], player, world, 50)
|
create_region_and_locations_basic("Double Jump Total Left", locations_double_jump_left, ["Cave Tree", "Cave Roof"], player, multiworld, 50)
|
||||||
create_region_and_locations_basic("Double Jump Total Left Cave", ["Top Hat Sheep"], [], player, world, 9)
|
create_region_and_locations_basic("Double Jump Total Left Cave", ["Top Hat Sheep"], [], player, multiworld, 9)
|
||||||
create_region_and_locations_basic("Double Jump Total Left Roof", ["North West Ceiling Sheep"], [], player, world, 10)
|
create_region_and_locations_basic("Double Jump Total Left Roof", ["North West Ceiling Sheep"], [], player, multiworld, 10)
|
||||||
locations_double_jump_left_ceiling = ["Sexy Outfits Pack", "Double Jump Alcove Sheep", "Sexy Outfits Sheep"]
|
locations_double_jump_left_ceiling = ["Sexy Outfits Pack", "Double Jump Alcove Sheep", "Sexy Outfits Sheep"]
|
||||||
create_region_and_locations_basic("Double Jump Behind Tree", locations_double_jump_left_ceiling, ["True Double Jump"], player, world, 89)
|
create_region_and_locations_basic("Double Jump Behind Tree", locations_double_jump_left_ceiling, ["True Double Jump"], player, multiworld, 89)
|
||||||
create_region_and_locations_basic("True Double Jump Behind Tree", ["Double Jump Floating Sheep", "Cutscene Sheep"], [], player, world, 7)
|
create_region_and_locations_basic("True Double Jump Behind Tree", ["Double Jump Floating Sheep", "Cutscene Sheep"], [], player, multiworld, 7)
|
||||||
create_region_and_locations_basic("The Forest", ["Gun Pack", "Night Map Pack"], ["Behind Ogre", "Forest Double Jump"], player, world, 171)
|
create_region_and_locations_basic("The Forest", ["Gun Pack", "Night Map Pack"], ["Behind Ogre", "Forest Double Jump"], player, multiworld, 171)
|
||||||
create_region_and_locations_basic("The Forest with double Jump", ["The Zombie Pack", "Forest Low Sheep"], ["Forest True Double Jump"], player, world, 76)
|
create_region_and_locations_basic("The Forest with double Jump", ["The Zombie Pack", "Forest Low Sheep"], ["Forest True Double Jump"], player, multiworld, 76)
|
||||||
create_region_and_locations_basic("The Forest with double Jump Part 2", ["Forest High Sheep"], [], player, world, 203)
|
create_region_and_locations_basic("The Forest with double Jump Part 2", ["Forest High Sheep"], [], player, multiworld, 203)
|
||||||
region_final_boss_room = create_region_and_locations_basic("The Final Boss Room", ["Finish the Fight Pack"], [], player, world)
|
region_final_boss_room = create_region_and_locations_basic("The Final Boss Room", ["Finish the Fight Pack"], [], player, multiworld)
|
||||||
|
|
||||||
create_victory_event(region_final_boss_room, "Winning Basic", "Victory Basic", player)
|
create_victory_event(region_final_boss_room, "Winning Basic", "Victory Basic", player)
|
||||||
|
|
||||||
connect_entrances_basic(player, world)
|
connect_entrances_basic(player, multiworld)
|
||||||
|
|
||||||
|
|
||||||
def create_regions_lfod_campaign(coin_bundle_size, has_campaign_lfod, has_coinsanity, has_item_shuffle, multiworld, player, region_menu):
|
def create_regions_lfod_campaign(coin_bundle_size, has_campaign_lfod, has_coinsanity, has_item_shuffle, multiworld, player, region_menu):
|
||||||
@@ -141,20 +141,20 @@ def create_victory_event(region_victory: Region, event_name: str, item_name: str
|
|||||||
location_victory.place_locked_item(create_event(player, item_name))
|
location_victory.place_locked_item(create_event(player, item_name))
|
||||||
|
|
||||||
|
|
||||||
def connect_entrances_basic(player, world):
|
def connect_entrances_basic(player, multiworld):
|
||||||
world.get_entrance("DLC Quest Basic", player).connect(world.get_region("Move Right", player))
|
multiworld.get_entrance("DLC Quest Basic", player).connect(multiworld.get_region("Move Right", player))
|
||||||
world.get_entrance("Moving", player).connect(world.get_region("Movement Pack", player))
|
multiworld.get_entrance("Moving", player).connect(multiworld.get_region("Movement Pack", player))
|
||||||
world.get_entrance("Tree", player).connect(world.get_region("Behind Tree", player))
|
multiworld.get_entrance("Tree", player).connect(multiworld.get_region("Behind Tree", player))
|
||||||
world.get_entrance("Cloud", player).connect(world.get_region("Psychological Warfare", player))
|
multiworld.get_entrance("Cloud", player).connect(multiworld.get_region("Psychological Warfare", player))
|
||||||
world.get_entrance("Cloud Double Jump", player).connect(world.get_region("Double Jump Total Left", player))
|
multiworld.get_entrance("Cloud Double Jump", player).connect(multiworld.get_region("Double Jump Total Left", player))
|
||||||
world.get_entrance("Cave Tree", player).connect(world.get_region("Double Jump Total Left Cave", player))
|
multiworld.get_entrance("Cave Tree", player).connect(multiworld.get_region("Double Jump Total Left Cave", player))
|
||||||
world.get_entrance("Cave Roof", player).connect(world.get_region("Double Jump Total Left Roof", player))
|
multiworld.get_entrance("Cave Roof", player).connect(multiworld.get_region("Double Jump Total Left Roof", player))
|
||||||
world.get_entrance("Forest Entrance", player).connect(world.get_region("The Forest", player))
|
multiworld.get_entrance("Forest Entrance", player).connect(multiworld.get_region("The Forest", player))
|
||||||
world.get_entrance("Behind Tree Double Jump", player).connect(world.get_region("Double Jump Behind Tree", player))
|
multiworld.get_entrance("Behind Tree Double Jump", player).connect(multiworld.get_region("Double Jump Behind Tree", player))
|
||||||
world.get_entrance("Behind Ogre", player).connect(world.get_region("The Final Boss Room", player))
|
multiworld.get_entrance("Behind Ogre", player).connect(multiworld.get_region("The Final Boss Room", player))
|
||||||
world.get_entrance("Forest Double Jump", player).connect(world.get_region("The Forest with double Jump", player))
|
multiworld.get_entrance("Forest Double Jump", player).connect(multiworld.get_region("The Forest with double Jump", player))
|
||||||
world.get_entrance("Forest True Double Jump", player).connect(world.get_region("The Forest with double Jump Part 2", player))
|
multiworld.get_entrance("Forest True Double Jump", player).connect(multiworld.get_region("The Forest with double Jump Part 2", player))
|
||||||
world.get_entrance("True Double Jump", player).connect(world.get_region("True Double Jump Behind Tree", player))
|
multiworld.get_entrance("True Double Jump", player).connect(multiworld.get_region("True Double Jump Behind Tree", player))
|
||||||
|
|
||||||
|
|
||||||
def connect_entrances_lfod(multiworld, player):
|
def connect_entrances_lfod(multiworld, player):
|
||||||
|
|||||||
+194
-194
@@ -18,251 +18,251 @@ def has_enough_coin_freemium(player: int, coin: int):
|
|||||||
return lambda state: state.prog_items[player][" coins freemium"] >= coin
|
return lambda state: state.prog_items[player][" coins freemium"] >= coin
|
||||||
|
|
||||||
|
|
||||||
def set_rules(world, player, world_options: Options.DLCQuestOptions):
|
def set_rules(multiworld, player, world_options: Options.DLCQuestOptions):
|
||||||
set_basic_rules(world_options, player, world)
|
set_basic_rules(world_options, player, multiworld)
|
||||||
set_lfod_rules(world_options, player, world)
|
set_lfod_rules(world_options, player, multiworld)
|
||||||
set_completion_condition(world_options, player, world)
|
set_completion_condition(world_options, player, multiworld)
|
||||||
|
|
||||||
|
|
||||||
def set_basic_rules(world_options, player, world):
|
def set_basic_rules(world_options, player, multiworld):
|
||||||
if world_options.campaign == Options.Campaign.option_live_freemium_or_die:
|
if world_options.campaign == Options.Campaign.option_live_freemium_or_die:
|
||||||
return
|
return
|
||||||
set_basic_entrance_rules(player, world)
|
set_basic_entrance_rules(player, multiworld)
|
||||||
set_basic_self_obtained_items_rules(world_options, player, world)
|
set_basic_self_obtained_items_rules(world_options, player, multiworld)
|
||||||
set_basic_shuffled_items_rules(world_options, player, world)
|
set_basic_shuffled_items_rules(world_options, player, multiworld)
|
||||||
set_double_jump_glitchless_rules(world_options, player, world)
|
set_double_jump_glitchless_rules(world_options, player, multiworld)
|
||||||
set_easy_double_jump_glitch_rules(world_options, player, world)
|
set_easy_double_jump_glitch_rules(world_options, player, multiworld)
|
||||||
self_basic_coinsanity_funded_purchase_rules(world_options, player, world)
|
self_basic_coinsanity_funded_purchase_rules(world_options, player, multiworld)
|
||||||
set_basic_self_funded_purchase_rules(world_options, player, world)
|
set_basic_self_funded_purchase_rules(world_options, player, multiworld)
|
||||||
self_basic_win_condition(world_options, player, world)
|
self_basic_win_condition(world_options, player, multiworld)
|
||||||
|
|
||||||
|
|
||||||
def set_basic_entrance_rules(player, world):
|
def set_basic_entrance_rules(player, multiworld):
|
||||||
set_rule(world.get_entrance("Moving", player),
|
set_rule(multiworld.get_entrance("Moving", player),
|
||||||
lambda state: state.has("Movement Pack", player))
|
lambda state: state.has("Movement Pack", player))
|
||||||
set_rule(world.get_entrance("Cloud", player),
|
set_rule(multiworld.get_entrance("Cloud", player),
|
||||||
lambda state: state.has("Psychological Warfare Pack", player))
|
lambda state: state.has("Psychological Warfare Pack", player))
|
||||||
set_rule(world.get_entrance("Forest Entrance", player),
|
set_rule(multiworld.get_entrance("Forest Entrance", player),
|
||||||
lambda state: state.has("Map Pack", player))
|
lambda state: state.has("Map Pack", player))
|
||||||
set_rule(world.get_entrance("Forest True Double Jump", player),
|
set_rule(multiworld.get_entrance("Forest True Double Jump", player),
|
||||||
lambda state: state.has("Double Jump Pack", player))
|
lambda state: state.has("Double Jump Pack", player))
|
||||||
|
|
||||||
|
|
||||||
def set_basic_self_obtained_items_rules(world_options, player, world):
|
def set_basic_self_obtained_items_rules(world_options, player, multiworld):
|
||||||
if world_options.item_shuffle != Options.ItemShuffle.option_disabled:
|
if world_options.item_shuffle != Options.ItemShuffle.option_disabled:
|
||||||
return
|
return
|
||||||
set_rule(world.get_entrance("Behind Ogre", player),
|
set_rule(multiworld.get_entrance("Behind Ogre", player),
|
||||||
lambda state: state.has("Gun Pack", player))
|
lambda state: state.has("Gun Pack", player))
|
||||||
|
|
||||||
if world_options.time_is_money == Options.TimeIsMoney.option_required:
|
if world_options.time_is_money == Options.TimeIsMoney.option_required:
|
||||||
set_rule(world.get_entrance("Tree", player),
|
set_rule(multiworld.get_entrance("Tree", player),
|
||||||
lambda state: state.has("Time is Money Pack", player))
|
lambda state: state.has("Time is Money Pack", player))
|
||||||
set_rule(world.get_entrance("Cave Tree", player),
|
set_rule(multiworld.get_entrance("Cave Tree", player),
|
||||||
lambda state: state.has("Time is Money Pack", player))
|
lambda state: state.has("Time is Money Pack", player))
|
||||||
set_rule(world.get_location("Shepherd Sheep", player),
|
set_rule(multiworld.get_location("Shepherd Sheep", player),
|
||||||
lambda state: state.has("Time is Money Pack", player))
|
lambda state: state.has("Time is Money Pack", player))
|
||||||
set_rule(world.get_location("North West Ceiling Sheep", player),
|
set_rule(multiworld.get_location("North West Ceiling Sheep", player),
|
||||||
lambda state: state.has("Time is Money Pack", player))
|
lambda state: state.has("Time is Money Pack", player))
|
||||||
set_rule(world.get_location("North West Alcove Sheep", player),
|
set_rule(multiworld.get_location("North West Alcove Sheep", player),
|
||||||
lambda state: state.has("Time is Money Pack", player))
|
lambda state: state.has("Time is Money Pack", player))
|
||||||
set_rule(world.get_location("West Cave Sheep", player),
|
set_rule(multiworld.get_location("West Cave Sheep", player),
|
||||||
lambda state: state.has("Time is Money Pack", player))
|
lambda state: state.has("Time is Money Pack", player))
|
||||||
|
|
||||||
|
|
||||||
def set_basic_shuffled_items_rules(world_options, player, world):
|
def set_basic_shuffled_items_rules(world_options, player, multiworld):
|
||||||
if world_options.item_shuffle != Options.ItemShuffle.option_shuffled:
|
if world_options.item_shuffle != Options.ItemShuffle.option_shuffled:
|
||||||
return
|
return
|
||||||
set_rule(world.get_entrance("Behind Ogre", player),
|
set_rule(multiworld.get_entrance("Behind Ogre", player),
|
||||||
lambda state: state.has("DLC Quest: Progressive Weapon", player, 2))
|
lambda state: state.has("DLC Quest: Progressive Weapon", player, 2))
|
||||||
set_rule(world.get_entrance("Tree", player),
|
set_rule(multiworld.get_entrance("Tree", player),
|
||||||
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
||||||
set_rule(world.get_entrance("Cave Tree", player),
|
set_rule(multiworld.get_entrance("Cave Tree", player),
|
||||||
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
||||||
set_rule(world.get_entrance("True Double Jump", player),
|
set_rule(multiworld.get_entrance("True Double Jump", player),
|
||||||
lambda state: state.has("Double Jump Pack", player))
|
lambda state: state.has("Double Jump Pack", player))
|
||||||
set_rule(world.get_location("Shepherd Sheep", player),
|
set_rule(multiworld.get_location("Shepherd Sheep", player),
|
||||||
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
||||||
set_rule(world.get_location("North West Ceiling Sheep", player),
|
set_rule(multiworld.get_location("North West Ceiling Sheep", player),
|
||||||
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
||||||
set_rule(world.get_location("North West Alcove Sheep", player),
|
set_rule(multiworld.get_location("North West Alcove Sheep", player),
|
||||||
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
||||||
set_rule(world.get_location("West Cave Sheep", player),
|
set_rule(multiworld.get_location("West Cave Sheep", player),
|
||||||
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
lambda state: state.has("DLC Quest: Progressive Weapon", player))
|
||||||
set_rule(world.get_location("Gun", player),
|
set_rule(multiworld.get_location("Gun", player),
|
||||||
lambda state: state.has("Gun Pack", player))
|
lambda state: state.has("Gun Pack", player))
|
||||||
|
|
||||||
if world_options.time_is_money == Options.TimeIsMoney.option_required:
|
if world_options.time_is_money == Options.TimeIsMoney.option_required:
|
||||||
set_rule(world.get_location("Sword", player),
|
set_rule(multiworld.get_location("Sword", player),
|
||||||
lambda state: state.has("Time is Money Pack", player))
|
lambda state: state.has("Time is Money Pack", player))
|
||||||
|
|
||||||
|
|
||||||
def set_double_jump_glitchless_rules(world_options, player, world):
|
def set_double_jump_glitchless_rules(world_options, player, multiworld):
|
||||||
if world_options.double_jump_glitch != Options.DoubleJumpGlitch.option_none:
|
if world_options.double_jump_glitch != Options.DoubleJumpGlitch.option_none:
|
||||||
return
|
return
|
||||||
set_rule(world.get_entrance("Cloud Double Jump", player),
|
set_rule(multiworld.get_entrance("Cloud Double Jump", player),
|
||||||
lambda state: state.has("Double Jump Pack", player))
|
lambda state: state.has("Double Jump Pack", player))
|
||||||
set_rule(world.get_entrance("Forest Double Jump", player),
|
set_rule(multiworld.get_entrance("Forest Double Jump", player),
|
||||||
lambda state: state.has("Double Jump Pack", player))
|
lambda state: state.has("Double Jump Pack", player))
|
||||||
|
|
||||||
|
|
||||||
def set_easy_double_jump_glitch_rules(world_options, player, world):
|
def set_easy_double_jump_glitch_rules(world_options, player, multiworld):
|
||||||
if world_options.double_jump_glitch == Options.DoubleJumpGlitch.option_all:
|
if world_options.double_jump_glitch == Options.DoubleJumpGlitch.option_all:
|
||||||
return
|
return
|
||||||
set_rule(world.get_entrance("Behind Tree Double Jump", player),
|
set_rule(multiworld.get_entrance("Behind Tree Double Jump", player),
|
||||||
lambda state: state.has("Double Jump Pack", player))
|
lambda state: state.has("Double Jump Pack", player))
|
||||||
set_rule(world.get_entrance("Cave Roof", player),
|
set_rule(multiworld.get_entrance("Cave Roof", player),
|
||||||
lambda state: state.has("Double Jump Pack", player))
|
lambda state: state.has("Double Jump Pack", player))
|
||||||
|
|
||||||
|
|
||||||
def self_basic_coinsanity_funded_purchase_rules(world_options, player, world):
|
def self_basic_coinsanity_funded_purchase_rules(world_options, player, multiworld):
|
||||||
if world_options.coinsanity != Options.CoinSanity.option_coin:
|
if world_options.coinsanity != Options.CoinSanity.option_coin:
|
||||||
return
|
return
|
||||||
if world_options.coinbundlequantity == -1:
|
if world_options.coinbundlequantity == -1:
|
||||||
self_basic_coinsanity_piece_rules(player, world)
|
self_basic_coinsanity_piece_rules(player, multiworld)
|
||||||
return
|
return
|
||||||
number_of_bundle = math.floor(825 / world_options.coinbundlequantity)
|
number_of_bundle = math.floor(825 / world_options.coinbundlequantity)
|
||||||
for i in range(number_of_bundle):
|
for i in range(number_of_bundle):
|
||||||
|
|
||||||
item_coin = f"DLC Quest: {world_options.coinbundlequantity * (i + 1)} Coin"
|
item_coin = f"DLC Quest: {world_options.coinbundlequantity * (i + 1)} Coin"
|
||||||
set_rule(world.get_location(item_coin, player),
|
set_rule(multiworld.get_location(item_coin, player),
|
||||||
has_enough_coin(player, world_options.coinbundlequantity * (i + 1)))
|
has_enough_coin(player, world_options.coinbundlequantity * (i + 1)))
|
||||||
if 825 % world_options.coinbundlequantity != 0:
|
if 825 % world_options.coinbundlequantity != 0:
|
||||||
set_rule(world.get_location("DLC Quest: 825 Coin", player),
|
set_rule(multiworld.get_location("DLC Quest: 825 Coin", player),
|
||||||
has_enough_coin(player, 825))
|
has_enough_coin(player, 825))
|
||||||
|
|
||||||
set_rule(world.get_location("Movement Pack", player),
|
set_rule(multiworld.get_location("Movement Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(4 / world_options.coinbundlequantity)))
|
math.ceil(4 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Animation Pack", player),
|
set_rule(multiworld.get_location("Animation Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Audio Pack", player),
|
set_rule(multiworld.get_location("Audio Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Pause Menu Pack", player),
|
set_rule(multiworld.get_location("Pause Menu Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Time is Money Pack", player),
|
set_rule(multiworld.get_location("Time is Money Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(20 / world_options.coinbundlequantity)))
|
math.ceil(20 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Double Jump Pack", player),
|
set_rule(multiworld.get_location("Double Jump Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(100 / world_options.coinbundlequantity)))
|
math.ceil(100 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Pet Pack", player),
|
set_rule(multiworld.get_location("Pet Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Sexy Outfits Pack", player),
|
set_rule(multiworld.get_location("Sexy Outfits Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Top Hat Pack", player),
|
set_rule(multiworld.get_location("Top Hat Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Map Pack", player),
|
set_rule(multiworld.get_location("Map Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(140 / world_options.coinbundlequantity)))
|
math.ceil(140 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Gun Pack", player),
|
set_rule(multiworld.get_location("Gun Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(75 / world_options.coinbundlequantity)))
|
math.ceil(75 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("The Zombie Pack", player),
|
set_rule(multiworld.get_location("The Zombie Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Night Map Pack", player),
|
set_rule(multiworld.get_location("Night Map Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(75 / world_options.coinbundlequantity)))
|
math.ceil(75 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Psychological Warfare Pack", player),
|
set_rule(multiworld.get_location("Psychological Warfare Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(50 / world_options.coinbundlequantity)))
|
math.ceil(50 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Armor for your Horse Pack", player),
|
set_rule(multiworld.get_location("Armor for your Horse Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(250 / world_options.coinbundlequantity)))
|
math.ceil(250 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Finish the Fight Pack", player),
|
set_rule(multiworld.get_location("Finish the Fight Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
lambda state: state.has("DLC Quest: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
|
|
||||||
|
|
||||||
def set_basic_self_funded_purchase_rules(world_options, player, world):
|
def set_basic_self_funded_purchase_rules(world_options, player, multiworld):
|
||||||
if world_options.coinsanity != Options.CoinSanity.option_none:
|
if world_options.coinsanity != Options.CoinSanity.option_none:
|
||||||
return
|
return
|
||||||
set_rule(world.get_location("Movement Pack", player),
|
set_rule(multiworld.get_location("Movement Pack", player),
|
||||||
has_enough_coin(player, 4))
|
has_enough_coin(player, 4))
|
||||||
set_rule(world.get_location("Animation Pack", player),
|
set_rule(multiworld.get_location("Animation Pack", player),
|
||||||
has_enough_coin(player, 5))
|
has_enough_coin(player, 5))
|
||||||
set_rule(world.get_location("Audio Pack", player),
|
set_rule(multiworld.get_location("Audio Pack", player),
|
||||||
has_enough_coin(player, 5))
|
has_enough_coin(player, 5))
|
||||||
set_rule(world.get_location("Pause Menu Pack", player),
|
set_rule(multiworld.get_location("Pause Menu Pack", player),
|
||||||
has_enough_coin(player, 5))
|
has_enough_coin(player, 5))
|
||||||
set_rule(world.get_location("Time is Money Pack", player),
|
set_rule(multiworld.get_location("Time is Money Pack", player),
|
||||||
has_enough_coin(player, 20))
|
has_enough_coin(player, 20))
|
||||||
set_rule(world.get_location("Double Jump Pack", player),
|
set_rule(multiworld.get_location("Double Jump Pack", player),
|
||||||
has_enough_coin(player, 100))
|
has_enough_coin(player, 100))
|
||||||
set_rule(world.get_location("Pet Pack", player),
|
set_rule(multiworld.get_location("Pet Pack", player),
|
||||||
has_enough_coin(player, 5))
|
has_enough_coin(player, 5))
|
||||||
set_rule(world.get_location("Sexy Outfits Pack", player),
|
set_rule(multiworld.get_location("Sexy Outfits Pack", player),
|
||||||
has_enough_coin(player, 5))
|
has_enough_coin(player, 5))
|
||||||
set_rule(world.get_location("Top Hat Pack", player),
|
set_rule(multiworld.get_location("Top Hat Pack", player),
|
||||||
has_enough_coin(player, 5))
|
has_enough_coin(player, 5))
|
||||||
set_rule(world.get_location("Map Pack", player),
|
set_rule(multiworld.get_location("Map Pack", player),
|
||||||
has_enough_coin(player, 140))
|
has_enough_coin(player, 140))
|
||||||
set_rule(world.get_location("Gun Pack", player),
|
set_rule(multiworld.get_location("Gun Pack", player),
|
||||||
has_enough_coin(player, 75))
|
has_enough_coin(player, 75))
|
||||||
set_rule(world.get_location("The Zombie Pack", player),
|
set_rule(multiworld.get_location("The Zombie Pack", player),
|
||||||
has_enough_coin(player, 5))
|
has_enough_coin(player, 5))
|
||||||
set_rule(world.get_location("Night Map Pack", player),
|
set_rule(multiworld.get_location("Night Map Pack", player),
|
||||||
has_enough_coin(player, 75))
|
has_enough_coin(player, 75))
|
||||||
set_rule(world.get_location("Psychological Warfare Pack", player),
|
set_rule(multiworld.get_location("Psychological Warfare Pack", player),
|
||||||
has_enough_coin(player, 50))
|
has_enough_coin(player, 50))
|
||||||
set_rule(world.get_location("Armor for your Horse Pack", player),
|
set_rule(multiworld.get_location("Armor for your Horse Pack", player),
|
||||||
has_enough_coin(player, 250))
|
has_enough_coin(player, 250))
|
||||||
set_rule(world.get_location("Finish the Fight Pack", player),
|
set_rule(multiworld.get_location("Finish the Fight Pack", player),
|
||||||
has_enough_coin(player, 5))
|
has_enough_coin(player, 5))
|
||||||
|
|
||||||
|
|
||||||
def self_basic_win_condition(world_options, player, world):
|
def self_basic_win_condition(world_options, player, multiworld):
|
||||||
if world_options.ending_choice == Options.EndingChoice.option_any:
|
if world_options.ending_choice == Options.EndingChoice.option_any:
|
||||||
set_rule(world.get_location("Winning Basic", player),
|
set_rule(multiworld.get_location("Winning Basic", player),
|
||||||
lambda state: state.has("Finish the Fight Pack", player))
|
lambda state: state.has("Finish the Fight Pack", player))
|
||||||
if world_options.ending_choice == Options.EndingChoice.option_true:
|
if world_options.ending_choice == Options.EndingChoice.option_true:
|
||||||
set_rule(world.get_location("Winning Basic", player),
|
set_rule(multiworld.get_location("Winning Basic", player),
|
||||||
lambda state: state.has("Armor for your Horse Pack", player) and state.has("Finish the Fight Pack",
|
lambda state: state.has("Armor for your Horse Pack", player) and state.has("Finish the Fight Pack",
|
||||||
player))
|
player))
|
||||||
|
|
||||||
|
|
||||||
def set_lfod_rules(world_options, player, world):
|
def set_lfod_rules(world_options, player, multiworld):
|
||||||
if world_options.campaign == Options.Campaign.option_basic:
|
if world_options.campaign == Options.Campaign.option_basic:
|
||||||
return
|
return
|
||||||
set_lfod_entrance_rules(player, world)
|
set_lfod_entrance_rules(player, multiworld)
|
||||||
set_boss_door_requirements_rules(player, world)
|
set_boss_door_requirements_rules(player, multiworld)
|
||||||
set_lfod_self_obtained_items_rules(world_options, player, world)
|
set_lfod_self_obtained_items_rules(world_options, player, multiworld)
|
||||||
set_lfod_shuffled_items_rules(world_options, player, world)
|
set_lfod_shuffled_items_rules(world_options, player, multiworld)
|
||||||
self_lfod_coinsanity_funded_purchase_rules(world_options, player, world)
|
self_lfod_coinsanity_funded_purchase_rules(world_options, player, multiworld)
|
||||||
set_lfod_self_funded_purchase_rules(world_options, has_enough_coin_freemium, player, world)
|
set_lfod_self_funded_purchase_rules(world_options, has_enough_coin_freemium, player, multiworld)
|
||||||
|
|
||||||
|
|
||||||
def set_lfod_entrance_rules(player, world):
|
def set_lfod_entrance_rules(player, multiworld):
|
||||||
set_rule(world.get_entrance("Wall Jump Entrance", player),
|
set_rule(multiworld.get_entrance("Wall Jump Entrance", player),
|
||||||
lambda state: state.has("Wall Jump Pack", player))
|
lambda state: state.has("Wall Jump Pack", player))
|
||||||
set_rule(world.get_entrance("Harmless Plants", player),
|
set_rule(multiworld.get_entrance("Harmless Plants", player),
|
||||||
lambda state: state.has("Harmless Plants Pack", player))
|
lambda state: state.has("Harmless Plants Pack", player))
|
||||||
set_rule(world.get_entrance("Name Change Entrance", player),
|
set_rule(multiworld.get_entrance("Name Change Entrance", player),
|
||||||
lambda state: state.has("Name Change Pack", player))
|
lambda state: state.has("Name Change Pack", player))
|
||||||
set_rule(world.get_entrance("Cut Content Entrance", player),
|
set_rule(multiworld.get_entrance("Cut Content Entrance", player),
|
||||||
lambda state: state.has("Cut Content Pack", player))
|
lambda state: state.has("Cut Content Pack", player))
|
||||||
set_rule(world.get_entrance("Blizzard", player),
|
set_rule(multiworld.get_entrance("Blizzard", player),
|
||||||
lambda state: state.has("Season Pass", player))
|
lambda state: state.has("Season Pass", player))
|
||||||
set_rule(world.get_location("I Get That Reference!", player),
|
set_rule(multiworld.get_location("I Get That Reference!", player),
|
||||||
lambda state: state.has("Death of Comedy Pack", player))
|
lambda state: state.has("Death of Comedy Pack", player))
|
||||||
set_rule(world.get_location("Story is Important", player),
|
set_rule(multiworld.get_location("Story is Important", player),
|
||||||
lambda state: state.has("DLC NPC Pack", player))
|
lambda state: state.has("DLC NPC Pack", player))
|
||||||
|
|
||||||
|
|
||||||
def set_boss_door_requirements_rules(player, world):
|
def set_boss_door_requirements_rules(player, multiworld):
|
||||||
sword_1 = "Big Sword Pack"
|
sword_1 = "Big Sword Pack"
|
||||||
sword_2 = "Really Big Sword Pack"
|
sword_2 = "Really Big Sword Pack"
|
||||||
sword_3 = "Unfathomable Sword Pack"
|
sword_3 = "Unfathomable Sword Pack"
|
||||||
|
|
||||||
big_sword_location = world.get_location(sword_1, player)
|
big_sword_location = multiworld.get_location(sword_1, player)
|
||||||
really_big_sword_location = world.get_location(sword_2, player)
|
really_big_sword_location = multiworld.get_location(sword_2, player)
|
||||||
unfathomable_sword_location = world.get_location(sword_3, player)
|
unfathomable_sword_location = multiworld.get_location(sword_3, player)
|
||||||
|
|
||||||
big_sword_valid_locations = [big_sword_location]
|
big_sword_valid_locations = [big_sword_location]
|
||||||
really_big_sword_valid_locations = [big_sword_location, really_big_sword_location]
|
really_big_sword_valid_locations = [big_sword_location, really_big_sword_location]
|
||||||
@@ -277,7 +277,7 @@ def set_boss_door_requirements_rules(player, world):
|
|||||||
has_3_swords = lambda state: ((state.has(sword_1, player) or big_sword_during_boss_fight) and
|
has_3_swords = lambda state: ((state.has(sword_1, player) or big_sword_during_boss_fight) and
|
||||||
(state.has(sword_2, player) or really_big_sword_during_boss_fight) and
|
(state.has(sword_2, player) or really_big_sword_during_boss_fight) and
|
||||||
(state.has(sword_3, player) or unfathomable_sword_during_boss_fight))
|
(state.has(sword_3, player) or unfathomable_sword_during_boss_fight))
|
||||||
set_rule(world.get_entrance("Boss Door", player), has_3_swords)
|
set_rule(multiworld.get_entrance("Boss Door", player), has_3_swords)
|
||||||
|
|
||||||
|
|
||||||
def set_lfod_self_obtained_items_rules(world_options, player, multiworld):
|
def set_lfod_self_obtained_items_rules(world_options, player, multiworld):
|
||||||
@@ -295,234 +295,234 @@ def set_lfod_self_obtained_items_rules(world_options, player, multiworld):
|
|||||||
multiworld.register_indirect_condition(world.get_region("Cut Content"), world.get_entrance("Pickaxe Hard Cave"))
|
multiworld.register_indirect_condition(world.get_region("Cut Content"), world.get_entrance("Pickaxe Hard Cave"))
|
||||||
|
|
||||||
|
|
||||||
def set_lfod_shuffled_items_rules(world_options, player, world):
|
def set_lfod_shuffled_items_rules(world_options, player, multiworld):
|
||||||
if world_options.item_shuffle != Options.ItemShuffle.option_shuffled:
|
if world_options.item_shuffle != Options.ItemShuffle.option_shuffled:
|
||||||
return
|
return
|
||||||
set_rule(world.get_entrance("Vines", player),
|
set_rule(multiworld.get_entrance("Vines", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Progressive Weapon", player))
|
lambda state: state.has("Live Freemium or Die: Progressive Weapon", player))
|
||||||
set_rule(world.get_entrance("Behind Rocks", player),
|
set_rule(multiworld.get_entrance("Behind Rocks", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Progressive Weapon", player, 2))
|
lambda state: state.has("Live Freemium or Die: Progressive Weapon", player, 2))
|
||||||
set_rule(world.get_entrance("Pickaxe Hard Cave", player),
|
set_rule(multiworld.get_entrance("Pickaxe Hard Cave", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Progressive Weapon", player, 2))
|
lambda state: state.has("Live Freemium or Die: Progressive Weapon", player, 2))
|
||||||
|
|
||||||
set_rule(world.get_location("Wooden Sword", player),
|
set_rule(multiworld.get_location("Wooden Sword", player),
|
||||||
lambda state: state.has("Incredibly Important Pack", player))
|
lambda state: state.has("Incredibly Important Pack", player))
|
||||||
set_rule(world.get_location("Pickaxe", player),
|
set_rule(multiworld.get_location("Pickaxe", player),
|
||||||
lambda state: state.has("Humble Indie Bindle", player))
|
lambda state: state.has("Humble Indie Bindle", player))
|
||||||
set_rule(world.get_location("Humble Indie Bindle", player),
|
set_rule(multiworld.get_location("Humble Indie Bindle", player),
|
||||||
lambda state: state.has("Box of Various Supplies", player) and
|
lambda state: state.has("Box of Various Supplies", player) and
|
||||||
state.can_reach("Cut Content", 'region', player))
|
state.can_reach("Cut Content", 'region', player))
|
||||||
set_rule(world.get_location("Box of Various Supplies", player),
|
set_rule(multiworld.get_location("Box of Various Supplies", player),
|
||||||
lambda state: state.can_reach("Cut Content", 'region', player))
|
lambda state: state.can_reach("Cut Content", 'region', player))
|
||||||
|
|
||||||
|
|
||||||
def self_lfod_coinsanity_funded_purchase_rules(world_options, player, world):
|
def self_lfod_coinsanity_funded_purchase_rules(world_options, player, multiworld):
|
||||||
if world_options.coinsanity != Options.CoinSanity.option_coin:
|
if world_options.coinsanity != Options.CoinSanity.option_coin:
|
||||||
return
|
return
|
||||||
if world_options.coinbundlequantity == -1:
|
if world_options.coinbundlequantity == -1:
|
||||||
self_lfod_coinsanity_piece_rules(player, world)
|
self_lfod_coinsanity_piece_rules(player, multiworld)
|
||||||
return
|
return
|
||||||
number_of_bundle = math.floor(889 / world_options.coinbundlequantity)
|
number_of_bundle = math.floor(889 / world_options.coinbundlequantity)
|
||||||
for i in range(number_of_bundle):
|
for i in range(number_of_bundle):
|
||||||
|
|
||||||
item_coin_freemium = f"Live Freemium or Die: {world_options.coinbundlequantity * (i + 1)} Coin"
|
item_coin_freemium = f"Live Freemium or Die: {world_options.coinbundlequantity * (i + 1)} Coin"
|
||||||
set_rule(world.get_location(item_coin_freemium, player),
|
set_rule(multiworld.get_location(item_coin_freemium, player),
|
||||||
has_enough_coin_freemium(player, world_options.coinbundlequantity * (i + 1)))
|
has_enough_coin_freemium(player, world_options.coinbundlequantity * (i + 1)))
|
||||||
if 889 % world_options.coinbundlequantity != 0:
|
if 889 % world_options.coinbundlequantity != 0:
|
||||||
set_rule(world.get_location("Live Freemium or Die: 889 Coin", player),
|
set_rule(multiworld.get_location("Live Freemium or Die: 889 Coin", player),
|
||||||
has_enough_coin_freemium(player, 889))
|
has_enough_coin_freemium(player, 889))
|
||||||
|
|
||||||
add_rule(world.get_entrance("Boss Door", player),
|
add_rule(multiworld.get_entrance("Boss Door", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(200 / world_options.coinbundlequantity)))
|
math.ceil(200 / world_options.coinbundlequantity)))
|
||||||
|
|
||||||
set_rule(world.get_location("Particles Pack", player),
|
set_rule(multiworld.get_location("Particles Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Day One Patch Pack", player),
|
set_rule(multiworld.get_location("Day One Patch Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Checkpoint Pack", player),
|
set_rule(multiworld.get_location("Checkpoint Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Incredibly Important Pack", player),
|
set_rule(multiworld.get_location("Incredibly Important Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(15 / world_options.coinbundlequantity)))
|
math.ceil(15 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Wall Jump Pack", player),
|
set_rule(multiworld.get_location("Wall Jump Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(35 / world_options.coinbundlequantity)))
|
math.ceil(35 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Health Bar Pack", player),
|
set_rule(multiworld.get_location("Health Bar Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Parallax Pack", player),
|
set_rule(multiworld.get_location("Parallax Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(5 / world_options.coinbundlequantity)))
|
math.ceil(5 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Harmless Plants Pack", player),
|
set_rule(multiworld.get_location("Harmless Plants Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(130 / world_options.coinbundlequantity)))
|
math.ceil(130 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Death of Comedy Pack", player),
|
set_rule(multiworld.get_location("Death of Comedy Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(15 / world_options.coinbundlequantity)))
|
math.ceil(15 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Canadian Dialog Pack", player),
|
set_rule(multiworld.get_location("Canadian Dialog Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(10 / world_options.coinbundlequantity)))
|
math.ceil(10 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("DLC NPC Pack", player),
|
set_rule(multiworld.get_location("DLC NPC Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(15 / world_options.coinbundlequantity)))
|
math.ceil(15 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Cut Content Pack", player),
|
set_rule(multiworld.get_location("Cut Content Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(40 / world_options.coinbundlequantity)))
|
math.ceil(40 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Name Change Pack", player),
|
set_rule(multiworld.get_location("Name Change Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(150 / world_options.coinbundlequantity)))
|
math.ceil(150 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Season Pass", player),
|
set_rule(multiworld.get_location("Season Pass", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(199 / world_options.coinbundlequantity)))
|
math.ceil(199 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("High Definition Next Gen Pack", player),
|
set_rule(multiworld.get_location("High Definition Next Gen Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(20 / world_options.coinbundlequantity)))
|
math.ceil(20 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Increased HP Pack", player),
|
set_rule(multiworld.get_location("Increased HP Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(10 / world_options.coinbundlequantity)))
|
math.ceil(10 / world_options.coinbundlequantity)))
|
||||||
set_rule(world.get_location("Remove Ads Pack", player),
|
set_rule(multiworld.get_location("Remove Ads Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
lambda state: state.has("Live Freemium or Die: Coin Bundle", player,
|
||||||
math.ceil(25 / world_options.coinbundlequantity)))
|
math.ceil(25 / world_options.coinbundlequantity)))
|
||||||
|
|
||||||
|
|
||||||
def set_lfod_self_funded_purchase_rules(world_options, has_enough_coin_freemium, player, world):
|
def set_lfod_self_funded_purchase_rules(world_options, has_enough_coin_freemium, player, multiworld):
|
||||||
if world_options.coinsanity != Options.CoinSanity.option_none:
|
if world_options.coinsanity != Options.CoinSanity.option_none:
|
||||||
return
|
return
|
||||||
add_rule(world.get_entrance("Boss Door", player),
|
add_rule(multiworld.get_entrance("Boss Door", player),
|
||||||
has_enough_coin_freemium(player, 200))
|
has_enough_coin_freemium(player, 200))
|
||||||
|
|
||||||
set_rule(world.get_location("Particles Pack", player),
|
set_rule(multiworld.get_location("Particles Pack", player),
|
||||||
has_enough_coin_freemium(player, 5))
|
has_enough_coin_freemium(player, 5))
|
||||||
set_rule(world.get_location("Day One Patch Pack", player),
|
set_rule(multiworld.get_location("Day One Patch Pack", player),
|
||||||
has_enough_coin_freemium(player, 5))
|
has_enough_coin_freemium(player, 5))
|
||||||
set_rule(world.get_location("Checkpoint Pack", player),
|
set_rule(multiworld.get_location("Checkpoint Pack", player),
|
||||||
has_enough_coin_freemium(player, 5))
|
has_enough_coin_freemium(player, 5))
|
||||||
set_rule(world.get_location("Incredibly Important Pack", player),
|
set_rule(multiworld.get_location("Incredibly Important Pack", player),
|
||||||
has_enough_coin_freemium(player, 15))
|
has_enough_coin_freemium(player, 15))
|
||||||
set_rule(world.get_location("Wall Jump Pack", player),
|
set_rule(multiworld.get_location("Wall Jump Pack", player),
|
||||||
has_enough_coin_freemium(player, 35))
|
has_enough_coin_freemium(player, 35))
|
||||||
set_rule(world.get_location("Health Bar Pack", player),
|
set_rule(multiworld.get_location("Health Bar Pack", player),
|
||||||
has_enough_coin_freemium(player, 5))
|
has_enough_coin_freemium(player, 5))
|
||||||
set_rule(world.get_location("Parallax Pack", player),
|
set_rule(multiworld.get_location("Parallax Pack", player),
|
||||||
has_enough_coin_freemium(player, 5))
|
has_enough_coin_freemium(player, 5))
|
||||||
set_rule(world.get_location("Harmless Plants Pack", player),
|
set_rule(multiworld.get_location("Harmless Plants Pack", player),
|
||||||
has_enough_coin_freemium(player, 130))
|
has_enough_coin_freemium(player, 130))
|
||||||
set_rule(world.get_location("Death of Comedy Pack", player),
|
set_rule(multiworld.get_location("Death of Comedy Pack", player),
|
||||||
has_enough_coin_freemium(player, 15))
|
has_enough_coin_freemium(player, 15))
|
||||||
set_rule(world.get_location("Canadian Dialog Pack", player),
|
set_rule(multiworld.get_location("Canadian Dialog Pack", player),
|
||||||
has_enough_coin_freemium(player, 10))
|
has_enough_coin_freemium(player, 10))
|
||||||
set_rule(world.get_location("DLC NPC Pack", player),
|
set_rule(multiworld.get_location("DLC NPC Pack", player),
|
||||||
has_enough_coin_freemium(player, 15))
|
has_enough_coin_freemium(player, 15))
|
||||||
set_rule(world.get_location("Cut Content Pack", player),
|
set_rule(multiworld.get_location("Cut Content Pack", player),
|
||||||
has_enough_coin_freemium(player, 40))
|
has_enough_coin_freemium(player, 40))
|
||||||
set_rule(world.get_location("Name Change Pack", player),
|
set_rule(multiworld.get_location("Name Change Pack", player),
|
||||||
has_enough_coin_freemium(player, 150))
|
has_enough_coin_freemium(player, 150))
|
||||||
set_rule(world.get_location("Season Pass", player),
|
set_rule(multiworld.get_location("Season Pass", player),
|
||||||
has_enough_coin_freemium(player, 199))
|
has_enough_coin_freemium(player, 199))
|
||||||
set_rule(world.get_location("High Definition Next Gen Pack", player),
|
set_rule(multiworld.get_location("High Definition Next Gen Pack", player),
|
||||||
has_enough_coin_freemium(player, 20))
|
has_enough_coin_freemium(player, 20))
|
||||||
set_rule(world.get_location("Increased HP Pack", player),
|
set_rule(multiworld.get_location("Increased HP Pack", player),
|
||||||
has_enough_coin_freemium(player, 10))
|
has_enough_coin_freemium(player, 10))
|
||||||
set_rule(world.get_location("Remove Ads Pack", player),
|
set_rule(multiworld.get_location("Remove Ads Pack", player),
|
||||||
has_enough_coin_freemium(player, 25))
|
has_enough_coin_freemium(player, 25))
|
||||||
|
|
||||||
|
|
||||||
def set_completion_condition(world_options, player, world):
|
def set_completion_condition(world_options, player, multiworld):
|
||||||
if world_options.campaign == Options.Campaign.option_basic:
|
if world_options.campaign == Options.Campaign.option_basic:
|
||||||
world.completion_condition[player] = lambda state: state.has("Victory Basic", player)
|
multiworld.completion_condition[player] = lambda state: state.has("Victory Basic", player)
|
||||||
if world_options.campaign == Options.Campaign.option_live_freemium_or_die:
|
if world_options.campaign == Options.Campaign.option_live_freemium_or_die:
|
||||||
world.completion_condition[player] = lambda state: state.has("Victory Freemium", player)
|
multiworld.completion_condition[player] = lambda state: state.has("Victory Freemium", player)
|
||||||
if world_options.campaign == Options.Campaign.option_both:
|
if world_options.campaign == Options.Campaign.option_both:
|
||||||
world.completion_condition[player] = lambda state: state.has("Victory Basic", player) and state.has(
|
multiworld.completion_condition[player] = lambda state: state.has("Victory Basic", player) and state.has(
|
||||||
"Victory Freemium", player)
|
"Victory Freemium", player)
|
||||||
|
|
||||||
|
|
||||||
def self_basic_coinsanity_piece_rules(player, world):
|
def self_basic_coinsanity_piece_rules(player, multiworld):
|
||||||
for i in range(1,8251):
|
for i in range(1,8251):
|
||||||
|
|
||||||
item_coin = f"DLC Quest: {i} Coin Piece"
|
item_coin = f"DLC Quest: {i} Coin Piece"
|
||||||
set_rule(world.get_location(item_coin, player),
|
set_rule(multiworld.get_location(item_coin, player),
|
||||||
has_enough_coin(player, math.ceil(i / 10)))
|
has_enough_coin(player, math.ceil(i / 10)))
|
||||||
|
|
||||||
set_rule(world.get_location("Movement Pack", player),
|
set_rule(multiworld.get_location("Movement Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 40))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 40))
|
||||||
set_rule(world.get_location("Animation Pack", player),
|
set_rule(multiworld.get_location("Animation Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Audio Pack", player),
|
set_rule(multiworld.get_location("Audio Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Pause Menu Pack", player),
|
set_rule(multiworld.get_location("Pause Menu Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Time is Money Pack", player),
|
set_rule(multiworld.get_location("Time is Money Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 200))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 200))
|
||||||
set_rule(world.get_location("Double Jump Pack", player),
|
set_rule(multiworld.get_location("Double Jump Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 100))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 100))
|
||||||
set_rule(world.get_location("Pet Pack", player),
|
set_rule(multiworld.get_location("Pet Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Sexy Outfits Pack", player),
|
set_rule(multiworld.get_location("Sexy Outfits Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Top Hat Pack", player),
|
set_rule(multiworld.get_location("Top Hat Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Map Pack", player),
|
set_rule(multiworld.get_location("Map Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 1400))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 1400))
|
||||||
set_rule(world.get_location("Gun Pack", player),
|
set_rule(multiworld.get_location("Gun Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 750))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 750))
|
||||||
set_rule(world.get_location("The Zombie Pack", player),
|
set_rule(multiworld.get_location("The Zombie Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Night Map Pack", player),
|
set_rule(multiworld.get_location("Night Map Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 750))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 750))
|
||||||
set_rule(world.get_location("Psychological Warfare Pack", player),
|
set_rule(multiworld.get_location("Psychological Warfare Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 500))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 500))
|
||||||
set_rule(world.get_location("Armor for your Horse Pack", player),
|
set_rule(multiworld.get_location("Armor for your Horse Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 2500))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 2500))
|
||||||
set_rule(world.get_location("Finish the Fight Pack", player),
|
set_rule(multiworld.get_location("Finish the Fight Pack", player),
|
||||||
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
lambda state: state.has("DLC Quest: Coin Piece", player, 50))
|
||||||
|
|
||||||
|
|
||||||
def self_lfod_coinsanity_piece_rules(player, world):
|
def self_lfod_coinsanity_piece_rules(player, multiworld):
|
||||||
for i in range(1, 8891):
|
for i in range(1, 8891):
|
||||||
|
|
||||||
item_coin_freemium = f"Live Freemium or Die: {i} Coin Piece"
|
item_coin_freemium = f"Live Freemium or Die: {i} Coin Piece"
|
||||||
set_rule(world.get_location(item_coin_freemium, player),
|
set_rule(multiworld.get_location(item_coin_freemium, player),
|
||||||
has_enough_coin_freemium(player, math.ceil(i / 10)))
|
has_enough_coin_freemium(player, math.ceil(i / 10)))
|
||||||
|
|
||||||
add_rule(world.get_entrance("Boss Door", player),
|
add_rule(multiworld.get_entrance("Boss Door", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 2000))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 2000))
|
||||||
|
|
||||||
set_rule(world.get_location("Particles Pack", player),
|
set_rule(multiworld.get_location("Particles Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Day One Patch Pack", player),
|
set_rule(multiworld.get_location("Day One Patch Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Checkpoint Pack", player),
|
set_rule(multiworld.get_location("Checkpoint Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Incredibly Important Pack", player),
|
set_rule(multiworld.get_location("Incredibly Important Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 150))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 150))
|
||||||
set_rule(world.get_location("Wall Jump Pack", player),
|
set_rule(multiworld.get_location("Wall Jump Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 350))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 350))
|
||||||
set_rule(world.get_location("Health Bar Pack", player),
|
set_rule(multiworld.get_location("Health Bar Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Parallax Pack", player),
|
set_rule(multiworld.get_location("Parallax Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 50))
|
||||||
set_rule(world.get_location("Harmless Plants Pack", player),
|
set_rule(multiworld.get_location("Harmless Plants Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 1300))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 1300))
|
||||||
set_rule(world.get_location("Death of Comedy Pack", player),
|
set_rule(multiworld.get_location("Death of Comedy Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 150))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 150))
|
||||||
set_rule(world.get_location("Canadian Dialog Pack", player),
|
set_rule(multiworld.get_location("Canadian Dialog Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 100))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 100))
|
||||||
set_rule(world.get_location("DLC NPC Pack", player),
|
set_rule(multiworld.get_location("DLC NPC Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 150))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 150))
|
||||||
set_rule(world.get_location("Cut Content Pack", player),
|
set_rule(multiworld.get_location("Cut Content Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 400))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 400))
|
||||||
set_rule(world.get_location("Name Change Pack", player),
|
set_rule(multiworld.get_location("Name Change Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 1500))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 1500))
|
||||||
set_rule(world.get_location("Season Pass", player),
|
set_rule(multiworld.get_location("Season Pass", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 199))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 199))
|
||||||
set_rule(world.get_location("High Definition Next Gen Pack", player),
|
set_rule(multiworld.get_location("High Definition Next Gen Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 20))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 20))
|
||||||
set_rule(world.get_location("Increased HP Pack", player),
|
set_rule(multiworld.get_location("Increased HP Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 100))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 100))
|
||||||
set_rule(world.get_location("Remove Ads Pack", player),
|
set_rule(multiworld.get_location("Remove Ads Pack", player),
|
||||||
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 250))
|
lambda state: state.has("Live Freemium or Die: Coin Piece", player, 250))
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class FaxanaduWorld(World):
|
|||||||
item_name_to_item = {item.name: item for item in Items.items}
|
item_name_to_item = {item.name: item for item in Items.items}
|
||||||
location_name_to_id = {loc.name: loc.id for loc in Locations.locations if loc.id is not None}
|
location_name_to_id = {loc.name: loc.id for loc in Locations.locations if loc.id is not None}
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int):
|
def __init__(self, multiworld: MultiWorld, player: int):
|
||||||
self.filler_ratios: Dict[str, int] = {
|
self.filler_ratios: Dict[str, int] = {
|
||||||
item.name: item.count
|
item.name: item.count
|
||||||
for item in Items.items
|
for item in Items.items
|
||||||
@@ -51,7 +51,7 @@ class FaxanaduWorld(World):
|
|||||||
}
|
}
|
||||||
# Remove poison by default to respect itemlinking
|
# Remove poison by default to respect itemlinking
|
||||||
self.filler_ratios["Poison"] = 0
|
self.filler_ratios["Poison"] = 0
|
||||||
super().__init__(world, player)
|
super().__init__(multiworld, player)
|
||||||
|
|
||||||
def create_regions(self):
|
def create_regions(self):
|
||||||
Regions.create_regions(self)
|
Regions.create_regions(self)
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ class FF1Locations:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_menu_region(player: int, locations: Dict[str, int],
|
def create_menu_region(player: int, locations: Dict[str, int],
|
||||||
rules: Dict[str, List[List[str]]], world: MultiWorld) -> Region:
|
rules: Dict[str, List[List[str]]], multiworld: MultiWorld) -> Region:
|
||||||
menu_region = Region("Menu", player, world)
|
menu_region = Region("Menu", player, multiworld)
|
||||||
for name, address in locations.items():
|
for name, address in locations.items():
|
||||||
location = Location(player, name, address, menu_region)
|
location = Location(player, name, address, menu_region)
|
||||||
## TODO REMOVE WHEN LOGIC FOR TOFR IS CORRECT
|
## TODO REMOVE WHEN LOGIC FOR TOFR IS CORRECT
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ class FF1World(World):
|
|||||||
|
|
||||||
web = FF1Web()
|
web = FF1Web()
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int):
|
def __init__(self, multiworld: MultiWorld, player: int):
|
||||||
super().__init__(world, player)
|
super().__init__(multiworld, player)
|
||||||
self.locked_items = []
|
self.locked_items = []
|
||||||
self.locked_locations = []
|
self.locked_locations = []
|
||||||
|
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ def process_rules(spot, access):
|
|||||||
add_rule(spot, lambda state: state.has_all(access, spot.player))
|
add_rule(spot, lambda state: state.has_all(access, spot.player))
|
||||||
|
|
||||||
|
|
||||||
def create_region(world: MultiWorld, player: int, name: str, room_id=None, locations=None, links=None):
|
def create_region(multiworld: MultiWorld, player: int, name: str, room_id=None, locations=None, links=None):
|
||||||
if links is None:
|
if links is None:
|
||||||
links = []
|
links = []
|
||||||
ret = Region(name, player, world)
|
ret = Region(name, player, multiworld)
|
||||||
if locations:
|
if locations:
|
||||||
for location in locations:
|
for location in locations:
|
||||||
location.parent_region = ret
|
location.parent_region = ret
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
from .ExtractedData import region_names, exits, connectors
|
|
||||||
|
|
||||||
|
|
||||||
def create_regions(world, player: int):
|
|
||||||
from . import create_region, HKLocation, HKItem
|
|
||||||
world.regions.append(create_region(world, player, 'Menu', None, ['Hollow Nest S&Q']))
|
|
||||||
for region in region_names:
|
|
||||||
world.regions.append(create_region(world, player, region, [],
|
|
||||||
exits.get(region, [])))
|
|
||||||
for entrance_name, exit_name in connectors.items():
|
|
||||||
if exit_name:
|
|
||||||
target_region = world.get_entrance(exit_name, player).parent_region
|
|
||||||
world.get_entrance(entrance_name, player).connect(target_region)
|
|
||||||
if not entrance_name.endswith("_R"):
|
|
||||||
# a traversable entrance puts the name of the target door "into logic".
|
|
||||||
loc = HKLocation(player, exit_name, None, target_region)
|
|
||||||
loc.place_locked_item(HKItem(exit_name,
|
|
||||||
not exit_name.startswith("White_Palace_"),
|
|
||||||
None, "Event", player))
|
|
||||||
target_region.locations.append(loc)
|
|
||||||
else:
|
|
||||||
ent = world.get_entrance(entrance_name, player)
|
|
||||||
ent.parent_region.exits.remove(ent)
|
|
||||||
|
|
||||||
|
|
||||||
+144
-144
@@ -126,7 +126,7 @@ def enter_hylemxylem(state: CollectionState, player: int) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def set_rules(hylics2world):
|
def set_rules(hylics2world):
|
||||||
world = hylics2world.multiworld
|
multiworld = hylics2world.multiworld
|
||||||
player = hylics2world.player
|
player = hylics2world.player
|
||||||
|
|
||||||
extra = hylics2world.options.extra_items_in_logic
|
extra = hylics2world.options.extra_items_in_logic
|
||||||
@@ -135,23 +135,23 @@ def set_rules(hylics2world):
|
|||||||
start_location = hylics2world.options.start_location
|
start_location = hylics2world.options.start_location
|
||||||
|
|
||||||
# Afterlife
|
# Afterlife
|
||||||
add_rule(world.get_location("Afterlife: TV", player),
|
add_rule(multiworld.get_location("Afterlife: TV", player),
|
||||||
lambda state: cave_key(state, player))
|
lambda state: cave_key(state, player))
|
||||||
|
|
||||||
# New Muldul
|
# New Muldul
|
||||||
add_rule(world.get_location("New Muldul: Underground Chest", player),
|
add_rule(multiworld.get_location("New Muldul: Underground Chest", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("New Muldul: TV", player),
|
add_rule(multiworld.get_location("New Muldul: TV", player),
|
||||||
lambda state: house_key(state, player))
|
lambda state: house_key(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Upper House Chest 1", player),
|
add_rule(multiworld.get_location("New Muldul: Upper House Chest 1", player),
|
||||||
lambda state: upper_house_key(state, player))
|
lambda state: upper_house_key(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Upper House Chest 2", player),
|
add_rule(multiworld.get_location("New Muldul: Upper House Chest 2", player),
|
||||||
lambda state: upper_house_key(state, player))
|
lambda state: upper_house_key(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Pot above Vault", player),
|
add_rule(multiworld.get_location("New Muldul: Pot above Vault", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
|
|
||||||
# New Muldul Vault
|
# New Muldul Vault
|
||||||
add_rule(world.get_location("New Muldul: Rescued Blerol 1", player),
|
add_rule(multiworld.get_location("New Muldul: Rescued Blerol 1", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
@@ -165,7 +165,7 @@ def set_rules(hylics2world):
|
|||||||
)
|
)
|
||||||
or enter_hylemxylem(state, player)
|
or enter_hylemxylem(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("New Muldul: Rescued Blerol 2", player),
|
add_rule(multiworld.get_location("New Muldul: Rescued Blerol 2", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
@@ -179,194 +179,194 @@ def set_rules(hylics2world):
|
|||||||
)
|
)
|
||||||
or enter_hylemxylem(state, player)
|
or enter_hylemxylem(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("New Muldul: Vault Left Chest", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Left Chest", player),
|
||||||
lambda state: enter_hylemxylem(state, player))
|
lambda state: enter_hylemxylem(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Right Chest", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Right Chest", player),
|
||||||
lambda state: enter_hylemxylem(state, player))
|
lambda state: enter_hylemxylem(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Bomb", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Bomb", player),
|
||||||
lambda state: enter_hylemxylem(state, player))
|
lambda state: enter_hylemxylem(state, player))
|
||||||
|
|
||||||
# Viewax's Edifice
|
# Viewax's Edifice
|
||||||
add_rule(world.get_location("Viewax's Edifice: Canopic Jar", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Canopic Jar", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Cave Sarcophagus", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Cave Sarcophagus", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Shielded Key", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Shielded Key", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Shielded Key", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Shielded Key", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Tower Pot", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Tower Pot", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Tower Jar", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Tower Jar", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Tower Chest", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Tower Chest", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
paddle(state, player)
|
paddle(state, player)
|
||||||
and tower_key(state, player)
|
and tower_key(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Viewax Pot", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Viewax Pot", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Defeat Viewax", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Defeat Viewax", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: TV", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: TV", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
paddle(state, player)
|
paddle(state, player)
|
||||||
and jail_key(state, player)
|
and jail_key(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Sage Fridge", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Sage Fridge", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Sage Item 1", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Sage Item 1", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Sage Item 2", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Sage Item 2", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
|
|
||||||
# Arcade 1
|
# Arcade 1
|
||||||
add_rule(world.get_location("Arcade 1: Key", player),
|
add_rule(multiworld.get_location("Arcade 1: Key", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Coin Dash", player),
|
add_rule(multiworld.get_location("Arcade 1: Coin Dash", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Burrito Alcove 1", player),
|
add_rule(multiworld.get_location("Arcade 1: Burrito Alcove 1", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Burrito Alcove 2", player),
|
add_rule(multiworld.get_location("Arcade 1: Burrito Alcove 2", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Behind Spikes Banana", player),
|
add_rule(multiworld.get_location("Arcade 1: Behind Spikes Banana", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Pyramid Banana", player),
|
add_rule(multiworld.get_location("Arcade 1: Pyramid Banana", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Moving Platforms Muscle Applique", player),
|
add_rule(multiworld.get_location("Arcade 1: Moving Platforms Muscle Applique", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Bed Banana", player),
|
add_rule(multiworld.get_location("Arcade 1: Bed Banana", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
|
|
||||||
# Airship
|
# Airship
|
||||||
add_rule(world.get_location("Airship: Talk to Somsnosa", player),
|
add_rule(multiworld.get_location("Airship: Talk to Somsnosa", player),
|
||||||
lambda state: worm_room_key(state, player))
|
lambda state: worm_room_key(state, player))
|
||||||
|
|
||||||
# Foglast
|
# Foglast
|
||||||
add_rule(world.get_location("Foglast: Underground Sarcophagus", player),
|
add_rule(multiworld.get_location("Foglast: Underground Sarcophagus", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Foglast: Shielded Key", player),
|
add_rule(multiworld.get_location("Foglast: Shielded Key", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Foglast: TV", player),
|
add_rule(multiworld.get_location("Foglast: TV", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
and clicker(state, player)
|
and clicker(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Foglast: Buy Clicker", player),
|
add_rule(multiworld.get_location("Foglast: Buy Clicker", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Foglast: Shielded Chest", player),
|
add_rule(multiworld.get_location("Foglast: Shielded Chest", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Foglast: Cave Fridge", player),
|
add_rule(multiworld.get_location("Foglast: Cave Fridge", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Foglast: Roof Sarcophagus", player),
|
add_rule(multiworld.get_location("Foglast: Roof Sarcophagus", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Foglast: Under Lair Sarcophagus 1", player),
|
add_rule(multiworld.get_location("Foglast: Under Lair Sarcophagus 1", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Foglast: Under Lair Sarcophagus 2", player),
|
add_rule(multiworld.get_location("Foglast: Under Lair Sarcophagus 2", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Foglast: Under Lair Sarcophagus 3", player),
|
add_rule(multiworld.get_location("Foglast: Under Lair Sarcophagus 3", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Foglast: Sage Sarcophagus", player),
|
add_rule(multiworld.get_location("Foglast: Sage Sarcophagus", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Foglast: Sage Item 1", player),
|
add_rule(multiworld.get_location("Foglast: Sage Item 1", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Foglast: Sage Item 2", player),
|
add_rule(multiworld.get_location("Foglast: Sage Item 2", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
))
|
))
|
||||||
|
|
||||||
# Drill Castle
|
# Drill Castle
|
||||||
add_rule(world.get_location("Drill Castle: Island Banana", player),
|
add_rule(multiworld.get_location("Drill Castle: Island Banana", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Drill Castle: Island Pot", player),
|
add_rule(multiworld.get_location("Drill Castle: Island Pot", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Drill Castle: Cave Sarcophagus", player),
|
add_rule(multiworld.get_location("Drill Castle: Cave Sarcophagus", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Drill Castle: TV", player),
|
add_rule(multiworld.get_location("Drill Castle: TV", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
|
|
||||||
# Sage Labyrinth
|
# Sage Labyrinth
|
||||||
add_rule(world.get_location("Sage Labyrinth: Sage Item 1", player),
|
add_rule(multiworld.get_location("Sage Labyrinth: Sage Item 1", player),
|
||||||
lambda state: deep_key(state, player))
|
lambda state: deep_key(state, player))
|
||||||
add_rule(world.get_location("Sage Labyrinth: Sage Item 2", player),
|
add_rule(multiworld.get_location("Sage Labyrinth: Sage Item 2", player),
|
||||||
lambda state: deep_key(state, player))
|
lambda state: deep_key(state, player))
|
||||||
add_rule(world.get_location("Sage Labyrinth: Sage Left Arm", player),
|
add_rule(multiworld.get_location("Sage Labyrinth: Sage Left Arm", player),
|
||||||
lambda state: deep_key(state, player))
|
lambda state: deep_key(state, player))
|
||||||
add_rule(world.get_location("Sage Labyrinth: Sage Right Arm", player),
|
add_rule(multiworld.get_location("Sage Labyrinth: Sage Right Arm", player),
|
||||||
lambda state: deep_key(state, player))
|
lambda state: deep_key(state, player))
|
||||||
add_rule(world.get_location("Sage Labyrinth: Sage Left Leg", player),
|
add_rule(multiworld.get_location("Sage Labyrinth: Sage Left Leg", player),
|
||||||
lambda state: deep_key(state, player))
|
lambda state: deep_key(state, player))
|
||||||
add_rule(world.get_location("Sage Labyrinth: Sage Right Leg", player),
|
add_rule(multiworld.get_location("Sage Labyrinth: Sage Right Leg", player),
|
||||||
lambda state: deep_key(state, player))
|
lambda state: deep_key(state, player))
|
||||||
|
|
||||||
# Sage Airship
|
# Sage Airship
|
||||||
add_rule(world.get_location("Sage Airship: TV", player),
|
add_rule(multiworld.get_location("Sage Airship: TV", player),
|
||||||
lambda state: all_tokens(state, player))
|
lambda state: all_tokens(state, player))
|
||||||
|
|
||||||
# Hylemxylem
|
# Hylemxylem
|
||||||
add_rule(world.get_location("Hylemxylem: Upper Chamber Banana", player),
|
add_rule(multiworld.get_location("Hylemxylem: Upper Chamber Banana", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Across Upper Reservoir Chest", player),
|
add_rule(multiworld.get_location("Hylemxylem: Across Upper Reservoir Chest", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Drained Lower Reservoir Chest", player),
|
add_rule(multiworld.get_location("Hylemxylem: Drained Lower Reservoir Chest", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Drained Lower Reservoir Burrito 1", player),
|
add_rule(multiworld.get_location("Hylemxylem: Drained Lower Reservoir Burrito 1", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Drained Lower Reservoir Burrito 2", player),
|
add_rule(multiworld.get_location("Hylemxylem: Drained Lower Reservoir Burrito 2", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Lower Reservoir Hole Pot 1", player),
|
add_rule(multiworld.get_location("Hylemxylem: Lower Reservoir Hole Pot 1", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Lower Reservoir Hole Pot 2", player),
|
add_rule(multiworld.get_location("Hylemxylem: Lower Reservoir Hole Pot 2", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Lower Reservoir Hole Pot 3", player),
|
add_rule(multiworld.get_location("Hylemxylem: Lower Reservoir Hole Pot 3", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Lower Reservoir Hole Sarcophagus", player),
|
add_rule(multiworld.get_location("Hylemxylem: Lower Reservoir Hole Sarcophagus", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Drained Upper Reservoir Burrito 1", player),
|
add_rule(multiworld.get_location("Hylemxylem: Drained Upper Reservoir Burrito 1", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Drained Upper Reservoir Burrito 2", player),
|
add_rule(multiworld.get_location("Hylemxylem: Drained Upper Reservoir Burrito 2", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Drained Upper Reservoir Burrito 3", player),
|
add_rule(multiworld.get_location("Hylemxylem: Drained Upper Reservoir Burrito 3", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Upper Reservoir Hole Key", player),
|
add_rule(multiworld.get_location("Hylemxylem: Upper Reservoir Hole Key", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
|
|
||||||
# extra rules if Extra Items in Logic is enabled
|
# extra rules if Extra Items in Logic is enabled
|
||||||
if extra:
|
if extra:
|
||||||
for i in world.get_region("Foglast", player).entrances:
|
for i in multiworld.get_region("Foglast", player).entrances:
|
||||||
add_rule(i, lambda state: charge_up(state, player))
|
add_rule(i, lambda state: charge_up(state, player))
|
||||||
for i in world.get_region("Sage Airship", player).entrances:
|
for i in multiworld.get_region("Sage Airship", player).entrances:
|
||||||
add_rule(i, lambda state: (
|
add_rule(i, lambda state: (
|
||||||
charge_up(state, player)
|
charge_up(state, player)
|
||||||
and paper_cup(state, player)
|
and paper_cup(state, player)
|
||||||
and worm_room_key(state, player)
|
and worm_room_key(state, player)
|
||||||
))
|
))
|
||||||
for i in world.get_region("Hylemxylem", player).entrances:
|
for i in multiworld.get_region("Hylemxylem", player).entrances:
|
||||||
add_rule(i, lambda state: (
|
add_rule(i, lambda state: (
|
||||||
charge_up(state, player)
|
charge_up(state, player)
|
||||||
and paper_cup(state, player)
|
and paper_cup(state, player)
|
||||||
))
|
))
|
||||||
|
|
||||||
add_rule(world.get_location("Sage Labyrinth: Motor Hunter Sarcophagus", player),
|
add_rule(multiworld.get_location("Sage Labyrinth: Motor Hunter Sarcophagus", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
charge_up(state, player)
|
charge_up(state, player)
|
||||||
and paper_cup(state, player)
|
and paper_cup(state, player)
|
||||||
@@ -374,9 +374,9 @@ def set_rules(hylics2world):
|
|||||||
|
|
||||||
# extra rules if Shuffle Party Members is enabled
|
# extra rules if Shuffle Party Members is enabled
|
||||||
if party:
|
if party:
|
||||||
for i in world.get_region("Arcade Island", player).entrances:
|
for i in multiworld.get_region("Arcade Island", player).entrances:
|
||||||
add_rule(i, lambda state: party_3(state, player))
|
add_rule(i, lambda state: party_3(state, player))
|
||||||
for i in world.get_region("Foglast", player).entrances:
|
for i in multiworld.get_region("Foglast", player).entrances:
|
||||||
add_rule(i, lambda state: (
|
add_rule(i, lambda state: (
|
||||||
party_3(state, player)
|
party_3(state, player)
|
||||||
or (
|
or (
|
||||||
@@ -384,197 +384,197 @@ def set_rules(hylics2world):
|
|||||||
and jail_key(state, player)
|
and jail_key(state, player)
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
for i in world.get_region("Sage Airship", player).entrances:
|
for i in multiworld.get_region("Sage Airship", player).entrances:
|
||||||
add_rule(i, lambda state: party_3(state, player))
|
add_rule(i, lambda state: party_3(state, player))
|
||||||
for i in world.get_region("Hylemxylem", player).entrances:
|
for i in multiworld.get_region("Hylemxylem", player).entrances:
|
||||||
add_rule(i, lambda state: party_3(state, player))
|
add_rule(i, lambda state: party_3(state, player))
|
||||||
|
|
||||||
add_rule(world.get_location("Viewax's Edifice: Defeat Viewax", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Defeat Viewax", player),
|
||||||
lambda state: party_2(state, player))
|
lambda state: party_2(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Rescued Blerol 1", player),
|
add_rule(multiworld.get_location("New Muldul: Rescued Blerol 1", player),
|
||||||
lambda state: party_2(state, player))
|
lambda state: party_2(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Rescued Blerol 2", player),
|
add_rule(multiworld.get_location("New Muldul: Rescued Blerol 2", player),
|
||||||
lambda state: party_2(state, player))
|
lambda state: party_2(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Left Chest", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Left Chest", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Right Chest", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Right Chest", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Bomb", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Bomb", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
add_rule(world.get_location("Juice Ranch: Battle with Somsnosa", player),
|
add_rule(multiworld.get_location("Juice Ranch: Battle with Somsnosa", player),
|
||||||
lambda state: party_2(state, player))
|
lambda state: party_2(state, player))
|
||||||
add_rule(world.get_location("Juice Ranch: Somsnosa Joins", player),
|
add_rule(multiworld.get_location("Juice Ranch: Somsnosa Joins", player),
|
||||||
lambda state: party_2(state, player))
|
lambda state: party_2(state, player))
|
||||||
add_rule(world.get_location("Airship: Talk to Somsnosa", player),
|
add_rule(multiworld.get_location("Airship: Talk to Somsnosa", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
add_rule(world.get_location("Sage Labyrinth: Motor Hunter Sarcophagus", player),
|
add_rule(multiworld.get_location("Sage Labyrinth: Motor Hunter Sarcophagus", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
|
|
||||||
# extra rules if Shuffle Red Medallions is enabled
|
# extra rules if Shuffle Red Medallions is enabled
|
||||||
if medallion:
|
if medallion:
|
||||||
add_rule(world.get_location("New Muldul: Upper House Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Upper House Medallion", player),
|
||||||
lambda state: upper_house_key(state, player))
|
lambda state: upper_house_key(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Rear Left Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Rear Left Medallion", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
enter_foglast(state, player)
|
enter_foglast(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
and air_dash(state, player)
|
and air_dash(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("New Muldul: Vault Rear Right Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Rear Right Medallion", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
enter_foglast(state, player)
|
enter_foglast(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
and air_dash(state, player)
|
and air_dash(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("New Muldul: Vault Center Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Center Medallion", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
enter_foglast(state, player)
|
enter_foglast(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
and air_dash(state, player)
|
and air_dash(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("New Muldul: Vault Front Left Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Front Left Medallion", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
enter_foglast(state, player)
|
enter_foglast(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
and air_dash(state, player)
|
and air_dash(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("New Muldul: Vault Front Right Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Front Right Medallion", player),
|
||||||
lambda state: (
|
lambda state: (
|
||||||
enter_foglast(state, player)
|
enter_foglast(state, player)
|
||||||
and bridge_key(state, player)
|
and bridge_key(state, player)
|
||||||
and air_dash(state, player)
|
and air_dash(state, player)
|
||||||
))
|
))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Fort Wall Medallion", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Fort Wall Medallion", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Jar Medallion", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Jar Medallion", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Viewax's Edifice: Sage Chair Medallion", player),
|
add_rule(multiworld.get_location("Viewax's Edifice: Sage Chair Medallion", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Lonely Medallion", player),
|
add_rule(multiworld.get_location("Arcade 1: Lonely Medallion", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Alcove Medallion", player),
|
add_rule(multiworld.get_location("Arcade 1: Alcove Medallion", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Arcade 1: Lava Medallion", player),
|
add_rule(multiworld.get_location("Arcade 1: Lava Medallion", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Foglast: Under Lair Medallion", player),
|
add_rule(multiworld.get_location("Foglast: Under Lair Medallion", player),
|
||||||
lambda state: bridge_key(state, player))
|
lambda state: bridge_key(state, player))
|
||||||
add_rule(world.get_location("Foglast: Mid-Air Medallion", player),
|
add_rule(multiworld.get_location("Foglast: Mid-Air Medallion", player),
|
||||||
lambda state: air_dash(state, player))
|
lambda state: air_dash(state, player))
|
||||||
add_rule(world.get_location("Foglast: Top of Tower Medallion", player),
|
add_rule(multiworld.get_location("Foglast: Top of Tower Medallion", player),
|
||||||
lambda state: paddle(state, player))
|
lambda state: paddle(state, player))
|
||||||
add_rule(world.get_location("Hylemxylem: Lower Reservoir Hole Medallion", player),
|
add_rule(multiworld.get_location("Hylemxylem: Lower Reservoir Hole Medallion", player),
|
||||||
lambda state: upper_chamber_key(state, player))
|
lambda state: upper_chamber_key(state, player))
|
||||||
|
|
||||||
# extra rules if Shuffle Red Medallions and Party Shuffle are enabled
|
# extra rules if Shuffle Red Medallions and Party Shuffle are enabled
|
||||||
if party and medallion:
|
if party and medallion:
|
||||||
add_rule(world.get_location("New Muldul: Vault Rear Left Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Rear Left Medallion", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Rear Right Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Rear Right Medallion", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Center Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Center Medallion", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Front Left Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Front Left Medallion", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
add_rule(world.get_location("New Muldul: Vault Front Right Medallion", player),
|
add_rule(multiworld.get_location("New Muldul: Vault Front Right Medallion", player),
|
||||||
lambda state: party_3(state, player))
|
lambda state: party_3(state, player))
|
||||||
|
|
||||||
# entrances
|
# entrances
|
||||||
for i in world.get_region("Airship", player).entrances:
|
for i in multiworld.get_region("Airship", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Arcade Island", player).entrances:
|
for i in multiworld.get_region("Arcade Island", player).entrances:
|
||||||
add_rule(i, lambda state: (
|
add_rule(i, lambda state: (
|
||||||
airship(state, player)
|
airship(state, player)
|
||||||
and air_dash(state, player)
|
and air_dash(state, player)
|
||||||
))
|
))
|
||||||
for i in world.get_region("Worm Pod", player).entrances:
|
for i in multiworld.get_region("Worm Pod", player).entrances:
|
||||||
add_rule(i, lambda state: enter_wormpod(state, player))
|
add_rule(i, lambda state: enter_wormpod(state, player))
|
||||||
for i in world.get_region("Foglast", player).entrances:
|
for i in multiworld.get_region("Foglast", player).entrances:
|
||||||
add_rule(i, lambda state: enter_foglast(state, player))
|
add_rule(i, lambda state: enter_foglast(state, player))
|
||||||
for i in world.get_region("Sage Labyrinth", player).entrances:
|
for i in multiworld.get_region("Sage Labyrinth", player).entrances:
|
||||||
add_rule(i, lambda state: skull_bomb(state, player))
|
add_rule(i, lambda state: skull_bomb(state, player))
|
||||||
for i in world.get_region("Sage Airship", player).entrances:
|
for i in multiworld.get_region("Sage Airship", player).entrances:
|
||||||
add_rule(i, lambda state: enter_sageship(state, player))
|
add_rule(i, lambda state: enter_sageship(state, player))
|
||||||
for i in world.get_region("Hylemxylem", player).entrances:
|
for i in multiworld.get_region("Hylemxylem", player).entrances:
|
||||||
add_rule(i, lambda state: enter_hylemxylem(state, player))
|
add_rule(i, lambda state: enter_hylemxylem(state, player))
|
||||||
|
|
||||||
# random start logic (default)
|
# random start logic (default)
|
||||||
if start_location == "waynehouse":
|
if start_location == "waynehouse":
|
||||||
# entrances
|
# entrances
|
||||||
for i in world.get_region("Viewax", player).entrances:
|
for i in multiworld.get_region("Viewax", player).entrances:
|
||||||
add_rule(i, lambda state: (
|
add_rule(i, lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
and airship(state, player)
|
and airship(state, player)
|
||||||
))
|
))
|
||||||
for i in world.get_region("TV Island", player).entrances:
|
for i in multiworld.get_region("TV Island", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Shield Facility", player).entrances:
|
for i in multiworld.get_region("Shield Facility", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Juice Ranch", player).entrances:
|
for i in multiworld.get_region("Juice Ranch", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
|
|
||||||
# random start logic (Viewax's Edifice)
|
# random start logic (Viewax's Edifice)
|
||||||
elif start_location == "viewaxs_edifice":
|
elif start_location == "viewaxs_edifice":
|
||||||
for i in world.get_region("Waynehouse", player).entrances:
|
for i in multiworld.get_region("Waynehouse", player).entrances:
|
||||||
add_rule(i, lambda state: (
|
add_rule(i, lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
or airship(state, player)
|
or airship(state, player)
|
||||||
))
|
))
|
||||||
for i in world.get_region("New Muldul", player).entrances:
|
for i in multiworld.get_region("New Muldul", player).entrances:
|
||||||
add_rule(i, lambda state: (
|
add_rule(i, lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
or airship(state, player)
|
or airship(state, player)
|
||||||
))
|
))
|
||||||
for i in world.get_region("New Muldul Vault", player).entrances:
|
for i in multiworld.get_region("New Muldul Vault", player).entrances:
|
||||||
add_rule(i, lambda state: (
|
add_rule(i, lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
or airship(state, player)
|
or airship(state, player)
|
||||||
))
|
))
|
||||||
for i in world.get_region("Drill Castle", player).entrances:
|
for i in multiworld.get_region("Drill Castle", player).entrances:
|
||||||
add_rule(i, lambda state: (
|
add_rule(i, lambda state: (
|
||||||
air_dash(state, player)
|
air_dash(state, player)
|
||||||
or airship(state, player)
|
or airship(state, player)
|
||||||
))
|
))
|
||||||
for i in world.get_region("TV Island", player).entrances:
|
for i in multiworld.get_region("TV Island", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Shield Facility", player).entrances:
|
for i in multiworld.get_region("Shield Facility", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Juice Ranch", player).entrances:
|
for i in multiworld.get_region("Juice Ranch", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Sage Labyrinth", player).entrances:
|
for i in multiworld.get_region("Sage Labyrinth", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
|
|
||||||
# start logic (TV Island)
|
# start logic (TV Island)
|
||||||
elif start_location == "tv_island":
|
elif start_location == "tv_island":
|
||||||
for i in world.get_region("Waynehouse", player).entrances:
|
for i in multiworld.get_region("Waynehouse", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("New Muldul", player).entrances:
|
for i in multiworld.get_region("New Muldul", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("New Muldul Vault", player).entrances:
|
for i in multiworld.get_region("New Muldul Vault", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Drill Castle", player).entrances:
|
for i in multiworld.get_region("Drill Castle", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Viewax", player).entrances:
|
for i in multiworld.get_region("Viewax", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Shield Facility", player).entrances:
|
for i in multiworld.get_region("Shield Facility", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Juice Ranch", player).entrances:
|
for i in multiworld.get_region("Juice Ranch", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Sage Labyrinth", player).entrances:
|
for i in multiworld.get_region("Sage Labyrinth", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
|
|
||||||
# start logic (Shield Facility)
|
# start logic (Shield Facility)
|
||||||
elif start_location == "shield_facility":
|
elif start_location == "shield_facility":
|
||||||
for i in world.get_region("Waynehouse", player).entrances:
|
for i in multiworld.get_region("Waynehouse", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("New Muldul", player).entrances:
|
for i in multiworld.get_region("New Muldul", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("New Muldul Vault", player).entrances:
|
for i in multiworld.get_region("New Muldul Vault", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Drill Castle", player).entrances:
|
for i in multiworld.get_region("Drill Castle", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Viewax", player).entrances:
|
for i in multiworld.get_region("Viewax", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("TV Island", player).entrances:
|
for i in multiworld.get_region("TV Island", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
for i in world.get_region("Sage Labyrinth", player).entrances:
|
for i in multiworld.get_region("Sage Labyrinth", player).entrances:
|
||||||
add_rule(i, lambda state: airship(state, player))
|
add_rule(i, lambda state: airship(state, player))
|
||||||
|
|||||||
@@ -95,10 +95,10 @@ class MM3World(World):
|
|||||||
web = MM3WebWorld()
|
web = MM3WebWorld()
|
||||||
rom_name: bytearray
|
rom_name: bytearray
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int):
|
def __init__(self, multiworld: MultiWorld, player: int):
|
||||||
self.rom_name = bytearray()
|
self.rom_name = bytearray()
|
||||||
self.rom_name_available_event = threading.Event()
|
self.rom_name_available_event = threading.Event()
|
||||||
super().__init__(world, player)
|
super().__init__(multiworld, player)
|
||||||
self.weapon_damage = deepcopy(weapon_damage)
|
self.weapon_damage = deepcopy(weapon_damage)
|
||||||
self.wily_4_weapons: dict[int, list[int]] = {}
|
self.wily_4_weapons: dict[int, list[int]] = {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"game": "Mega Man 3",
|
"game": "Mega Man 3",
|
||||||
"authors": ["Silvris"],
|
"authors": ["Silvris"],
|
||||||
"world_version": "0.1.7",
|
"world_version": "0.1.8",
|
||||||
"minimum_ap_version": "0.6.4"
|
"minimum_ap_version": "0.6.4"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -463,13 +463,13 @@ class MMBN3World(World):
|
|||||||
rompath: str = ""
|
rompath: str = ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
world = self.multiworld
|
multiworld = self.multiworld
|
||||||
player = self.player
|
player = self.player
|
||||||
|
|
||||||
rom = LocalRom(get_base_rom_path())
|
rom = LocalRom(get_base_rom_path())
|
||||||
|
|
||||||
for location_name in location_table.keys():
|
for location_name in location_table.keys():
|
||||||
location = world.get_location(location_name, player)
|
location = multiworld.get_location(location_name, player)
|
||||||
ap_item = location.item
|
ap_item = location.item
|
||||||
item_id = ap_item.code
|
item_id = ap_item.code
|
||||||
if item_id is not None:
|
if item_id is not None:
|
||||||
@@ -511,7 +511,7 @@ class MMBN3World(World):
|
|||||||
|
|
||||||
rom.insert_hint_text(location_data, item_name_text, long_item_text)
|
rom.insert_hint_text(location_data, item_name_text, long_item_text)
|
||||||
|
|
||||||
rom.inject_name(world.player_name[player])
|
rom.inject_name(self.player_name)
|
||||||
|
|
||||||
rompath = os.path.join(output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}.gba")
|
rompath = os.path.join(output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}.gba")
|
||||||
|
|
||||||
@@ -519,7 +519,7 @@ class MMBN3World(World):
|
|||||||
rom.write_to_file(rompath)
|
rom.write_to_file(rompath)
|
||||||
|
|
||||||
patch = MMBN3DeltaPatch(os.path.splitext(rompath)[0]+MMBN3DeltaPatch.patch_file_ending, player=player,
|
patch = MMBN3DeltaPatch(os.path.splitext(rompath)[0]+MMBN3DeltaPatch.patch_file_ending, player=player,
|
||||||
player_name=world.player_name[player], patched_path=rompath)
|
player_name=self.player_name, patched_path=rompath)
|
||||||
patch.write()
|
patch.write()
|
||||||
except:
|
except:
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ from .Hints import get_hint_area, HintAreaNotFound
|
|||||||
from .Regions import TimeOfDay
|
from .Regions import TimeOfDay
|
||||||
|
|
||||||
|
|
||||||
def set_all_entrances_data(world, player):
|
def set_all_entrances_data(multiworld, player):
|
||||||
for type, forward_entry, *return_entry in entrance_shuffle_table:
|
for type, forward_entry, *return_entry in entrance_shuffle_table:
|
||||||
forward_entrance = world.get_entrance(forward_entry[0], player)
|
forward_entrance = multiworld.get_entrance(forward_entry[0], player)
|
||||||
forward_entrance.data = forward_entry[1]
|
forward_entrance.data = forward_entry[1]
|
||||||
forward_entrance.type = type
|
forward_entrance.type = type
|
||||||
forward_entrance.primary = True
|
forward_entrance.primary = True
|
||||||
@@ -18,7 +18,7 @@ def set_all_entrances_data(world, player):
|
|||||||
forward_entrance.data['index'] = 0x1000 + forward_entrance.data['grotto_id']
|
forward_entrance.data['index'] = 0x1000 + forward_entrance.data['grotto_id']
|
||||||
if return_entry:
|
if return_entry:
|
||||||
return_entry = return_entry[0]
|
return_entry = return_entry[0]
|
||||||
return_entrance = world.get_entrance(return_entry[0], player)
|
return_entrance = multiworld.get_entrance(return_entry[0], player)
|
||||||
return_entrance.data = return_entry[1]
|
return_entrance.data = return_entry[1]
|
||||||
return_entrance.type = type
|
return_entrance.type = type
|
||||||
forward_entrance.bind_two_way(return_entrance)
|
forward_entrance.bind_two_way(return_entrance)
|
||||||
|
|||||||
@@ -336,10 +336,10 @@ def replace_max_item(items, item, max, rand):
|
|||||||
|
|
||||||
|
|
||||||
def generate_itempool(ootworld):
|
def generate_itempool(ootworld):
|
||||||
world = ootworld.multiworld
|
multiworld = ootworld.multiworld
|
||||||
player = ootworld.player
|
player = ootworld.player
|
||||||
global random
|
global random
|
||||||
random = world.random
|
random = multiworld.random
|
||||||
|
|
||||||
junk_pool = get_junk_pool(ootworld)
|
junk_pool = get_junk_pool(ootworld)
|
||||||
|
|
||||||
@@ -347,7 +347,7 @@ def generate_itempool(ootworld):
|
|||||||
(pool, placed_items) = get_pool_core(ootworld)
|
(pool, placed_items) = get_pool_core(ootworld)
|
||||||
ootworld.itempool = [ootworld.create_item(item) for item in pool]
|
ootworld.itempool = [ootworld.create_item(item) for item in pool]
|
||||||
for (location_name, item) in placed_items.items():
|
for (location_name, item) in placed_items.items():
|
||||||
location = world.get_location(location_name, player)
|
location = multiworld.get_location(location_name, player)
|
||||||
location.place_locked_item(ootworld.create_item(item, allow_arbitrary_name=True))
|
location.place_locked_item(ootworld.create_item(item, allow_arbitrary_name=True))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -199,8 +199,8 @@ class Overcooked2Test(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertIn("Overcooked! 2", AutoWorldRegister.world_types.keys())
|
self.assertIn("Overcooked! 2", AutoWorldRegister.world_types.keys())
|
||||||
world_type = AutoWorldRegister.world_types["Overcooked! 2"]
|
world_type = AutoWorldRegister.world_types["Overcooked! 2"]
|
||||||
world = setup_solo_multiworld(world_type)
|
multiworld = setup_solo_multiworld(world_type)
|
||||||
state = world.get_all_state(False)
|
state = multiworld.get_all_state(False)
|
||||||
|
|
||||||
# Test region logic
|
# Test region logic
|
||||||
for logic in overworld_region_logic.values():
|
for logic in overworld_region_logic.values():
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
# 2.5.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Added a new option `dexsanity_encounter_types` to enable/disable dexsanity locations based on whether they can be
|
||||||
|
found in the allowed encounters. In other words, if Bulbasaur can only be found by fishing and fishing is not enabled,
|
||||||
|
a dexsanity location will not be created for Bulbasaur.
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- Fixed generator error if Wailord or Relicanth are blacklisted during a dexsanity seed.
|
||||||
|
- Fixed generator error if player greatly restricts allowed opponent pokemon while force fully evolved is active.
|
||||||
|
|
||||||
# 2.4.1
|
# 2.4.1
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"game": "Pokemon Emerald",
|
"game": "Pokemon Emerald",
|
||||||
"world_version": "2.4.1",
|
"world_version": "2.5.0",
|
||||||
"minimum_ap_version": "0.6.1",
|
"minimum_ap_version": "0.6.1",
|
||||||
"authors": ["Zunawe"]
|
"authors": ["Zunawe"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,8 +236,8 @@ class RaftWorld(World):
|
|||||||
"DeathLink": bool(self.options.death_link)
|
"DeathLink": bool(self.options.death_link)
|
||||||
}
|
}
|
||||||
|
|
||||||
def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None):
|
def create_region(multiworld: MultiWorld, player: int, name: str, locations=None, exits=None):
|
||||||
ret = Region(name, player, world)
|
ret = Region(name, player, multiworld)
|
||||||
if locations:
|
if locations:
|
||||||
for location in locations:
|
for location in locations:
|
||||||
loc_id = locations_lookup_name_to_id.get(location, 0)
|
loc_id = locations_lookup_name_to_id.get(location, 0)
|
||||||
|
|||||||
+10
-10
@@ -116,10 +116,10 @@ class SMWorld(World):
|
|||||||
|
|
||||||
Logic.factory('vanilla')
|
Logic.factory('vanilla')
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int):
|
def __init__(self, multiworld: MultiWorld, player: int):
|
||||||
self.rom_name_available_event = threading.Event()
|
self.rom_name_available_event = threading.Event()
|
||||||
self.locations = {}
|
self.locations = {}
|
||||||
super().__init__(world, player)
|
super().__init__(multiworld, player)
|
||||||
|
|
||||||
def generate_early(self):
|
def generate_early(self):
|
||||||
Logic.factory('vanilla')
|
Logic.factory('vanilla')
|
||||||
@@ -233,8 +233,8 @@ class SMWorld(World):
|
|||||||
for key, value1 in accessPoint.intraTransitions.items():
|
for key, value1 in accessPoint.intraTransitions.items():
|
||||||
set_entrance_rule(self.multiworld.get_entrance(accessPoint.Name + "->" + key, self.player), self.player, value1)
|
set_entrance_rule(self.multiworld.get_entrance(accessPoint.Name + "->" + key, self.player), self.player, value1)
|
||||||
|
|
||||||
def create_region(self, world: MultiWorld, player: int, name: str, locations=None, exits=None):
|
def create_region(self, multiworld: MultiWorld, player: int, name: str, locations=None, exits=None):
|
||||||
ret = Region(name, player, world)
|
ret = Region(name, player, multiworld)
|
||||||
if locations:
|
if locations:
|
||||||
for loc in locations:
|
for loc in locations:
|
||||||
location = self.locations[loc]
|
location = self.locations[loc]
|
||||||
@@ -420,10 +420,10 @@ class SMWorld(World):
|
|||||||
self.variaRando.randoExec.postProcessItemLocs(self.itemLocs, self.variaRando.args.hideItems)
|
self.variaRando.randoExec.postProcessItemLocs(self.itemLocs, self.variaRando.args.hideItems)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def stage_post_fill(cls, world):
|
def stage_post_fill(cls, multiworld):
|
||||||
new_state = CollectionState(world)
|
new_state = CollectionState(multiworld)
|
||||||
progitempool = []
|
progitempool = []
|
||||||
for item in world.itempool:
|
for item in multiworld.itempool:
|
||||||
if item.game == "Super Metroid" and item.advancement:
|
if item.game == "Super Metroid" and item.advancement:
|
||||||
progitempool.append(item)
|
progitempool.append(item)
|
||||||
|
|
||||||
@@ -431,10 +431,10 @@ class SMWorld(World):
|
|||||||
new_state.collect(item, True)
|
new_state.collect(item, True)
|
||||||
|
|
||||||
bossesLoc = ['Draygon', 'Kraid', 'Ridley', 'Phantoon', 'Mother Brain']
|
bossesLoc = ['Draygon', 'Kraid', 'Ridley', 'Phantoon', 'Mother Brain']
|
||||||
for player in world.get_game_players("Super Metroid"):
|
for player in multiworld.get_game_players("Super Metroid"):
|
||||||
for bossLoc in bossesLoc:
|
for bossLoc in bossesLoc:
|
||||||
if not world.get_location(bossLoc, player).can_reach(new_state):
|
if not multiworld.get_location(bossLoc, player).can_reach(new_state):
|
||||||
world.state.smbm[player].onlyBossLeft = True
|
multiworld.state.smbm[player].onlyBossLeft = True
|
||||||
break
|
break
|
||||||
|
|
||||||
def getWordArray(self, w: int) -> List[int]:
|
def getWordArray(self, w: int) -> List[int]:
|
||||||
|
|||||||
+39
-39
@@ -79,12 +79,12 @@ sm64_secrets_to_level = {secret: level for (level,secret) in sm64_level_to_secre
|
|||||||
sm64_entrances_to_level = {**sm64_paintings_to_level, **sm64_secrets_to_level }
|
sm64_entrances_to_level = {**sm64_paintings_to_level, **sm64_secrets_to_level }
|
||||||
sm64_level_to_entrances = {**sm64_level_to_paintings, **sm64_level_to_secrets }
|
sm64_level_to_entrances = {**sm64_level_to_paintings, **sm64_level_to_secrets }
|
||||||
|
|
||||||
def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
def create_regions(multiworld: MultiWorld, options: SM64Options, player: int):
|
||||||
regSS = Region("Menu", player, world, "Castle Area")
|
regSS = Region("Menu", player, multiworld, "Castle Area")
|
||||||
create_default_locs(regSS, locSS_table)
|
create_default_locs(regSS, locSS_table)
|
||||||
world.regions.append(regSS)
|
multiworld.regions.append(regSS)
|
||||||
|
|
||||||
regBoB = create_region("Bob-omb Battlefield", player, world)
|
regBoB = create_region("Bob-omb Battlefield", player, multiworld)
|
||||||
create_locs(regBoB, "BoB: Big Bob-Omb on the Summit", "BoB: Footrace with Koopa The Quick",
|
create_locs(regBoB, "BoB: Big Bob-Omb on the Summit", "BoB: Footrace with Koopa The Quick",
|
||||||
"BoB: Mario Wings to the Sky", "BoB: Behind Chain Chomp's Gate", "BoB: Bob-omb Buddy")
|
"BoB: Mario Wings to the Sky", "BoB: Behind Chain Chomp's Gate", "BoB: Bob-omb Buddy")
|
||||||
bob_island = create_subregion(regBoB, "BoB: Island", "BoB: Shoot to the Island in the Sky", "BoB: Find the 8 Red Coins")
|
bob_island = create_subregion(regBoB, "BoB: Island", "BoB: Shoot to the Island in the Sky", "BoB: Find the 8 Red Coins")
|
||||||
@@ -92,7 +92,7 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(regBoB, "BoB: 100 Coins")
|
create_locs(regBoB, "BoB: 100 Coins")
|
||||||
|
|
||||||
regWhomp = create_region("Whomp's Fortress", player, world)
|
regWhomp = create_region("Whomp's Fortress", player, multiworld)
|
||||||
create_locs(regWhomp, "WF: Chip Off Whomp's Block", "WF: Shoot into the Wild Blue", "WF: Red Coins on the Floating Isle",
|
create_locs(regWhomp, "WF: Chip Off Whomp's Block", "WF: Shoot into the Wild Blue", "WF: Red Coins on the Floating Isle",
|
||||||
"WF: Fall onto the Caged Island", "WF: Blast Away the Wall")
|
"WF: Fall onto the Caged Island", "WF: Blast Away the Wall")
|
||||||
wf_tower = create_subregion(regWhomp, "WF: Tower", "WF: To the Top of the Fortress", "WF: Bob-omb Buddy")
|
wf_tower = create_subregion(regWhomp, "WF: Tower", "WF: To the Top of the Fortress", "WF: Bob-omb Buddy")
|
||||||
@@ -100,8 +100,8 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(regWhomp, "WF: 100 Coins")
|
create_locs(regWhomp, "WF: 100 Coins")
|
||||||
|
|
||||||
regJRBDoor = create_region("Jolly Roger Bay Door", player, world)
|
regJRBDoor = create_region("Jolly Roger Bay Door", player, multiworld)
|
||||||
regJRB = create_region("Jolly Roger Bay", player, world)
|
regJRB = create_region("Jolly Roger Bay", player, multiworld)
|
||||||
create_locs(regJRB, "JRB: Plunder in the Sunken Ship", "JRB: Can the Eel Come Out to Play?", "JRB: Treasure of the Ocean Cave",
|
create_locs(regJRB, "JRB: Plunder in the Sunken Ship", "JRB: Can the Eel Come Out to Play?", "JRB: Treasure of the Ocean Cave",
|
||||||
"JRB: Blast to the Stone Pillar", "JRB: Through the Jet Stream", "JRB: Bob-omb Buddy")
|
"JRB: Blast to the Stone Pillar", "JRB: Through the Jet Stream", "JRB: Bob-omb Buddy")
|
||||||
jrb_upper = create_subregion(regJRB, 'JRB: Upper', "JRB: Red Coins on the Ship Afloat")
|
jrb_upper = create_subregion(regJRB, 'JRB: Upper', "JRB: Red Coins on the Ship Afloat")
|
||||||
@@ -109,12 +109,12 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(jrb_upper, "JRB: 100 Coins")
|
create_locs(jrb_upper, "JRB: 100 Coins")
|
||||||
|
|
||||||
regCCM = create_region("Cool, Cool Mountain", player, world)
|
regCCM = create_region("Cool, Cool Mountain", player, multiworld)
|
||||||
create_default_locs(regCCM, locCCM_table)
|
create_default_locs(regCCM, locCCM_table)
|
||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(regCCM, "CCM: 100 Coins")
|
create_locs(regCCM, "CCM: 100 Coins")
|
||||||
|
|
||||||
regBBH = create_region("Big Boo's Haunt", player, world)
|
regBBH = create_region("Big Boo's Haunt", player, multiworld)
|
||||||
create_locs(regBBH, "BBH: Go on a Ghost Hunt", "BBH: Ride Big Boo's Merry-Go-Round",
|
create_locs(regBBH, "BBH: Go on a Ghost Hunt", "BBH: Ride Big Boo's Merry-Go-Round",
|
||||||
"BBH: Secret of the Haunted Books", "BBH: Seek the 8 Red Coins")
|
"BBH: Secret of the Haunted Books", "BBH: Seek the 8 Red Coins")
|
||||||
bbh_third_floor = create_subregion(regBBH, "BBH: Third Floor", "BBH: Eye to Eye in the Secret Room")
|
bbh_third_floor = create_subregion(regBBH, "BBH: Third Floor", "BBH: Eye to Eye in the Secret Room")
|
||||||
@@ -123,21 +123,21 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(regBBH, "BBH: 100 Coins")
|
create_locs(regBBH, "BBH: 100 Coins")
|
||||||
|
|
||||||
regPSS = create_region("The Princess's Secret Slide", player, world)
|
regPSS = create_region("The Princess's Secret Slide", player, multiworld)
|
||||||
create_default_locs(regPSS, locPSS_table)
|
create_default_locs(regPSS, locPSS_table)
|
||||||
|
|
||||||
regSA = create_region("The Secret Aquarium", player, world)
|
regSA = create_region("The Secret Aquarium", player, multiworld)
|
||||||
create_default_locs(regSA, locSA_table)
|
create_default_locs(regSA, locSA_table)
|
||||||
|
|
||||||
regTotWC = create_region("Tower of the Wing Cap", player, world)
|
regTotWC = create_region("Tower of the Wing Cap", player, multiworld)
|
||||||
create_default_locs(regTotWC, locTotWC_table)
|
create_default_locs(regTotWC, locTotWC_table)
|
||||||
|
|
||||||
regBitDW = create_region("Bowser in the Dark World", player, world)
|
regBitDW = create_region("Bowser in the Dark World", player, multiworld)
|
||||||
create_default_locs(regBitDW, locBitDW_table)
|
create_default_locs(regBitDW, locBitDW_table)
|
||||||
|
|
||||||
create_region("Basement", player, world)
|
create_region("Basement", player, multiworld)
|
||||||
|
|
||||||
regHMC = create_region("Hazy Maze Cave", player, world)
|
regHMC = create_region("Hazy Maze Cave", player, multiworld)
|
||||||
create_locs(regHMC, "HMC: Swimming Beast in the Cavern", "HMC: Metal-Head Mario Can Move!",
|
create_locs(regHMC, "HMC: Swimming Beast in the Cavern", "HMC: Metal-Head Mario Can Move!",
|
||||||
"HMC: Watch for Rolling Rocks", "HMC: Navigating the Toxic Maze","HMC: 1Up Block Past Rolling Rocks")
|
"HMC: Watch for Rolling Rocks", "HMC: Navigating the Toxic Maze","HMC: 1Up Block Past Rolling Rocks")
|
||||||
hmc_red_coin_area = create_subregion(regHMC, "HMC: Red Coin Area", "HMC: Elevate for 8 Red Coins")
|
hmc_red_coin_area = create_subregion(regHMC, "HMC: Red Coin Area", "HMC: Elevate for 8 Red Coins")
|
||||||
@@ -146,7 +146,7 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(hmc_red_coin_area, "HMC: 100 Coins")
|
create_locs(hmc_red_coin_area, "HMC: 100 Coins")
|
||||||
|
|
||||||
regLLL = create_region("Lethal Lava Land", player, world)
|
regLLL = create_region("Lethal Lava Land", player, multiworld)
|
||||||
create_locs(regLLL, "LLL: Boil the Big Bully", "LLL: Bully the Bullies",
|
create_locs(regLLL, "LLL: Boil the Big Bully", "LLL: Bully the Bullies",
|
||||||
"LLL: 8-Coin Puzzle with 15 Pieces", "LLL: Red-Hot Log Rolling")
|
"LLL: 8-Coin Puzzle with 15 Pieces", "LLL: Red-Hot Log Rolling")
|
||||||
lll_upper_volcano = create_subregion(regLLL, "LLL: Upper Volcano", "LLL: Hot-Foot-It into the Volcano", "LLL: Elevator Tour in the Volcano")
|
lll_upper_volcano = create_subregion(regLLL, "LLL: Upper Volcano", "LLL: Hot-Foot-It into the Volcano", "LLL: Elevator Tour in the Volcano")
|
||||||
@@ -154,7 +154,7 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(regLLL, "LLL: 100 Coins")
|
create_locs(regLLL, "LLL: 100 Coins")
|
||||||
|
|
||||||
regSSL = create_region("Shifting Sand Land", player, world)
|
regSSL = create_region("Shifting Sand Land", player, multiworld)
|
||||||
create_locs(regSSL, "SSL: In the Talons of the Big Bird", "SSL: Shining Atop the Pyramid",
|
create_locs(regSSL, "SSL: In the Talons of the Big Bird", "SSL: Shining Atop the Pyramid",
|
||||||
"SSL: Free Flying for 8 Red Coins", "SSL: Bob-omb Buddy",
|
"SSL: Free Flying for 8 Red Coins", "SSL: Bob-omb Buddy",
|
||||||
"SSL: 1Up Block Outside Pyramid", "SSL: 1Up Block Pyramid Left Path", "SSL: 1Up Block Pyramid Back")
|
"SSL: 1Up Block Outside Pyramid", "SSL: 1Up Block Pyramid Left Path", "SSL: 1Up Block Pyramid Back")
|
||||||
@@ -164,30 +164,30 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(regSSL, "SSL: 100 Coins")
|
create_locs(regSSL, "SSL: 100 Coins")
|
||||||
|
|
||||||
regDDD = create_region("Dire, Dire Docks", player, world)
|
regDDD = create_region("Dire, Dire Docks", player, multiworld)
|
||||||
create_locs(regDDD, "DDD: Board Bowser's Sub", "DDD: Chests in the Current", "DDD: Through the Jet Stream",
|
create_locs(regDDD, "DDD: Board Bowser's Sub", "DDD: Chests in the Current", "DDD: Through the Jet Stream",
|
||||||
"DDD: The Manta Ray's Reward", "DDD: Collect the Caps...", "DDD: Pole-Jumping for Red Coins")
|
"DDD: The Manta Ray's Reward", "DDD: Collect the Caps...", "DDD: Pole-Jumping for Red Coins")
|
||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(regDDD, "DDD: 100 Coins")
|
create_locs(regDDD, "DDD: 100 Coins")
|
||||||
|
|
||||||
regCotMC = create_region("Cavern of the Metal Cap", player, world)
|
regCotMC = create_region("Cavern of the Metal Cap", player, multiworld)
|
||||||
create_default_locs(regCotMC, locCotMC_table)
|
create_default_locs(regCotMC, locCotMC_table)
|
||||||
|
|
||||||
regVCutM = create_region("Vanish Cap under the Moat", player, world)
|
regVCutM = create_region("Vanish Cap under the Moat", player, multiworld)
|
||||||
create_default_locs(regVCutM, locVCutM_table)
|
create_default_locs(regVCutM, locVCutM_table)
|
||||||
|
|
||||||
regBitFS = create_region("Bowser in the Fire Sea", player, world)
|
regBitFS = create_region("Bowser in the Fire Sea", player, multiworld)
|
||||||
bitfs_upper = create_subregion(regBitFS, "BitFS: Upper", *locBitFS_table.keys())
|
bitfs_upper = create_subregion(regBitFS, "BitFS: Upper", *locBitFS_table.keys())
|
||||||
regBitFS.subregions = [bitfs_upper]
|
regBitFS.subregions = [bitfs_upper]
|
||||||
|
|
||||||
create_region("Second Floor", player, world)
|
create_region("Second Floor", player, multiworld)
|
||||||
|
|
||||||
regSL = create_region("Snowman's Land", player, world)
|
regSL = create_region("Snowman's Land", player, multiworld)
|
||||||
create_default_locs(regSL, locSL_table)
|
create_default_locs(regSL, locSL_table)
|
||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(regSL, "SL: 100 Coins")
|
create_locs(regSL, "SL: 100 Coins")
|
||||||
|
|
||||||
regWDW = create_region("Wet-Dry World", player, world)
|
regWDW = create_region("Wet-Dry World", player, multiworld)
|
||||||
create_locs(regWDW, "WDW: Express Elevator--Hurry Up!")
|
create_locs(regWDW, "WDW: Express Elevator--Hurry Up!")
|
||||||
wdw_top = create_subregion(regWDW, "WDW: Top", "WDW: Shocking Arrow Lifts!", "WDW: Top o' the Town",
|
wdw_top = create_subregion(regWDW, "WDW: Top", "WDW: Shocking Arrow Lifts!", "WDW: Top o' the Town",
|
||||||
"WDW: Secrets in the Shallows & Sky", "WDW: Bob-omb Buddy")
|
"WDW: Secrets in the Shallows & Sky", "WDW: Bob-omb Buddy")
|
||||||
@@ -196,7 +196,7 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(wdw_top, "WDW: 100 Coins")
|
create_locs(wdw_top, "WDW: 100 Coins")
|
||||||
|
|
||||||
regTTM = create_region("Tall, Tall Mountain", player, world)
|
regTTM = create_region("Tall, Tall Mountain", player, multiworld)
|
||||||
ttm_middle = create_subregion(regTTM, "TTM: Middle", "TTM: Scary 'Shrooms, Red Coins", "TTM: Blast to the Lonely Mushroom",
|
ttm_middle = create_subregion(regTTM, "TTM: Middle", "TTM: Scary 'Shrooms, Red Coins", "TTM: Blast to the Lonely Mushroom",
|
||||||
"TTM: Bob-omb Buddy", "TTM: 1Up Block on Red Mushroom")
|
"TTM: Bob-omb Buddy", "TTM: 1Up Block on Red Mushroom")
|
||||||
ttm_top = create_subregion(ttm_middle, "TTM: Top", "TTM: Scale the Mountain", "TTM: Mystery of the Monkey Cage",
|
ttm_top = create_subregion(ttm_middle, "TTM: Top", "TTM: Scale the Mountain", "TTM: Mystery of the Monkey Cage",
|
||||||
@@ -205,9 +205,9 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(ttm_top, "TTM: 100 Coins")
|
create_locs(ttm_top, "TTM: 100 Coins")
|
||||||
|
|
||||||
create_region("Tiny-Huge Island (Huge)", player, world)
|
create_region("Tiny-Huge Island (Huge)", player, multiworld)
|
||||||
create_region("Tiny-Huge Island (Tiny)", player, world)
|
create_region("Tiny-Huge Island (Tiny)", player, multiworld)
|
||||||
regTHI = create_region("Tiny-Huge Island", player, world)
|
regTHI = create_region("Tiny-Huge Island", player, multiworld)
|
||||||
create_locs(regTHI, "THI: 1Up Block THI Small near Start")
|
create_locs(regTHI, "THI: 1Up Block THI Small near Start")
|
||||||
thi_pipes = create_subregion(regTHI, "THI: Pipes", "THI: The Tip Top of the Huge Island", "THI: Pluck the Piranha Flower", "THI: Rematch with Koopa the Quick",
|
thi_pipes = create_subregion(regTHI, "THI: Pipes", "THI: The Tip Top of the Huge Island", "THI: Pluck the Piranha Flower", "THI: Rematch with Koopa the Quick",
|
||||||
"THI: Five Itty Bitty Secrets", "THI: Wiggler's Red Coins", "THI: Bob-omb Buddy",
|
"THI: Five Itty Bitty Secrets", "THI: Wiggler's Red Coins", "THI: Bob-omb Buddy",
|
||||||
@@ -217,9 +217,9 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(thi_large_top, "THI: 100 Coins")
|
create_locs(thi_large_top, "THI: 100 Coins")
|
||||||
|
|
||||||
regFloor3 = create_region("Third Floor", player, world)
|
regFloor3 = create_region("Third Floor", player, multiworld)
|
||||||
|
|
||||||
regTTC = create_region("Tick Tock Clock", player, world)
|
regTTC = create_region("Tick Tock Clock", player, multiworld)
|
||||||
create_locs(regTTC, "TTC: Stop Time for Red Coins")
|
create_locs(regTTC, "TTC: Stop Time for Red Coins")
|
||||||
ttc_lower = create_subregion(regTTC, "TTC: Lower", "TTC: Roll into the Cage", "TTC: Get a Hand")
|
ttc_lower = create_subregion(regTTC, "TTC: Lower", "TTC: Roll into the Cage", "TTC: Get a Hand")
|
||||||
ttc_upper = create_subregion(ttc_lower, "TTC: Upper", "TTC: Timed Jumps on Moving Bars", "TTC: The Pit and the Pendulums")
|
ttc_upper = create_subregion(ttc_lower, "TTC: Upper", "TTC: Timed Jumps on Moving Bars", "TTC: The Pit and the Pendulums")
|
||||||
@@ -228,7 +228,7 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(ttc_top, "TTC: 100 Coins")
|
create_locs(ttc_top, "TTC: 100 Coins")
|
||||||
|
|
||||||
regRR = create_region("Rainbow Ride", player, world)
|
regRR = create_region("Rainbow Ride", player, multiworld)
|
||||||
create_locs(regRR, "RR: Swingin' in the Breeze", "RR: Tricky Triangles!",
|
create_locs(regRR, "RR: Swingin' in the Breeze", "RR: Tricky Triangles!",
|
||||||
"RR: 1Up Block Top of Red Coin Maze", "RR: 1Up Block Under Fly Guy", "RR: Bob-omb Buddy")
|
"RR: 1Up Block Top of Red Coin Maze", "RR: 1Up Block Under Fly Guy", "RR: Bob-omb Buddy")
|
||||||
rr_maze = create_subregion(regRR, "RR: Maze", "RR: Coins Amassed in a Maze")
|
rr_maze = create_subregion(regRR, "RR: Maze", "RR: Coins Amassed in a Maze")
|
||||||
@@ -238,24 +238,24 @@ def create_regions(world: MultiWorld, options: SM64Options, player: int):
|
|||||||
if options.enable_coin_stars:
|
if options.enable_coin_stars:
|
||||||
create_locs(rr_maze, "RR: 100 Coins")
|
create_locs(rr_maze, "RR: 100 Coins")
|
||||||
|
|
||||||
regWMotR = create_region("Wing Mario over the Rainbow", player, world)
|
regWMotR = create_region("Wing Mario over the Rainbow", player, multiworld)
|
||||||
create_default_locs(regWMotR, locWMotR_table)
|
create_default_locs(regWMotR, locWMotR_table)
|
||||||
|
|
||||||
regBitS = create_region("Bowser in the Sky", player, world)
|
regBitS = create_region("Bowser in the Sky", player, multiworld)
|
||||||
create_locs(regBitS, "Bowser in the Sky 1Up Block")
|
create_locs(regBitS, "Bowser in the Sky 1Up Block")
|
||||||
bits_top = create_subregion(regBitS, "BitS: Top", "Bowser in the Sky Red Coins")
|
bits_top = create_subregion(regBitS, "BitS: Top", "Bowser in the Sky Red Coins")
|
||||||
regBitS.subregions = [bits_top]
|
regBitS.subregions = [bits_top]
|
||||||
|
|
||||||
|
|
||||||
def connect_regions(world: MultiWorld, player: int, source: str, target: str, rule=None) -> Entrance:
|
def connect_regions(multiworld: MultiWorld, player: int, source: str, target: str, rule=None) -> Entrance:
|
||||||
sourceRegion = world.get_region(source, player)
|
sourceRegion = multiworld.get_region(source, player)
|
||||||
targetRegion = world.get_region(target, player)
|
targetRegion = multiworld.get_region(target, player)
|
||||||
return sourceRegion.connect(targetRegion, rule=rule)
|
return sourceRegion.connect(targetRegion, rule=rule)
|
||||||
|
|
||||||
|
|
||||||
def create_region(name: str, player: int, world: MultiWorld) -> SM64Region:
|
def create_region(name: str, player: int, multiworld: MultiWorld) -> SM64Region:
|
||||||
region = SM64Region(name, player, world)
|
region = SM64Region(name, player, multiworld)
|
||||||
world.regions.append(region)
|
multiworld.regions.append(region)
|
||||||
return region
|
return region
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+61
-61
@@ -8,24 +8,24 @@ from .Regions import connect_regions, SM64Levels, sm64_level_to_paintings, sm64_
|
|||||||
sm64_level_to_secrets, sm64_secrets_to_level, sm64_entrances_to_level, sm64_level_to_entrances
|
sm64_level_to_secrets, sm64_secrets_to_level, sm64_entrances_to_level, sm64_level_to_entrances
|
||||||
from .Items import action_item_data_table
|
from .Items import action_item_data_table
|
||||||
|
|
||||||
def shuffle_dict_keys(world, dictionary: dict) -> dict:
|
def shuffle_dict_keys(multiworld: MultiWorld, dictionary: dict) -> dict:
|
||||||
keys = list(dictionary.keys())
|
keys = list(dictionary.keys())
|
||||||
values = list(dictionary.values())
|
values = list(dictionary.values())
|
||||||
world.random.shuffle(keys)
|
multiworld.random.shuffle(keys)
|
||||||
return dict(zip(keys, values))
|
return dict(zip(keys, values))
|
||||||
|
|
||||||
def fix_reg(entrance_map: Dict[SM64Levels, str], entrance: SM64Levels, invalid_regions: Set[str],
|
def fix_reg(entrance_map: Dict[SM64Levels, str], entrance: SM64Levels, invalid_regions: Set[str],
|
||||||
swapdict: Dict[SM64Levels, str], world):
|
swapdict: Dict[SM64Levels, str], multiworld: MultiWorld):
|
||||||
if entrance_map[entrance] in invalid_regions: # Unlucky :C
|
if entrance_map[entrance] in invalid_regions: # Unlucky :C
|
||||||
replacement_regions = [(rand_entrance, rand_region) for rand_entrance, rand_region in swapdict.items()
|
replacement_regions = [(rand_entrance, rand_region) for rand_entrance, rand_region in swapdict.items()
|
||||||
if rand_region not in invalid_regions]
|
if rand_region not in invalid_regions]
|
||||||
rand_entrance, rand_region = world.random.choice(replacement_regions)
|
rand_entrance, rand_region = multiworld.random.choice(replacement_regions)
|
||||||
old_dest = entrance_map[entrance]
|
old_dest = entrance_map[entrance]
|
||||||
entrance_map[entrance], entrance_map[rand_entrance] = rand_region, old_dest
|
entrance_map[entrance], entrance_map[rand_entrance] = rand_region, old_dest
|
||||||
swapdict[entrance], swapdict[rand_entrance] = rand_region, old_dest
|
swapdict[entrance], swapdict[rand_entrance] = rand_region, old_dest
|
||||||
swapdict.pop(entrance)
|
swapdict.pop(entrance)
|
||||||
|
|
||||||
def set_rules(world, options: SM64Options, player: int, area_connections: dict, star_costs: dict, move_rando_bitvec: int):
|
def set_rules(multiworld: MultiWorld, options: SM64Options, player: int, area_connections: dict, star_costs: dict, move_rando_bitvec: int):
|
||||||
randomized_level_to_paintings = sm64_level_to_paintings.copy()
|
randomized_level_to_paintings = sm64_level_to_paintings.copy()
|
||||||
randomized_level_to_secrets = sm64_level_to_secrets.copy()
|
randomized_level_to_secrets = sm64_level_to_secrets.copy()
|
||||||
valid_move_randomizer_start_courses = [
|
valid_move_randomizer_start_courses = [
|
||||||
@@ -34,100 +34,100 @@ def set_rules(world, options: SM64Options, player: int, area_connections: dict,
|
|||||||
"Dire, Dire Docks", "Snowman's Land"
|
"Dire, Dire Docks", "Snowman's Land"
|
||||||
] # Excluding WF, HMC, WDW, TTM, THI, TTC, and RR
|
] # Excluding WF, HMC, WDW, TTM, THI, TTC, and RR
|
||||||
if options.area_rando >= 1: # Some randomization is happening, randomize Courses
|
if options.area_rando >= 1: # Some randomization is happening, randomize Courses
|
||||||
randomized_level_to_paintings = shuffle_dict_keys(world,sm64_level_to_paintings)
|
randomized_level_to_paintings = shuffle_dict_keys(multiworld,sm64_level_to_paintings)
|
||||||
# If not shuffling later, ensure a valid start course on move randomizer
|
# If not shuffling later, ensure a valid start course on move randomizer
|
||||||
if options.area_rando < 3 and move_rando_bitvec > 0:
|
if options.area_rando < 3 and move_rando_bitvec > 0:
|
||||||
swapdict = randomized_level_to_paintings.copy()
|
swapdict = randomized_level_to_paintings.copy()
|
||||||
invalid_start_courses = {course for course in randomized_level_to_paintings.values() if course not in valid_move_randomizer_start_courses}
|
invalid_start_courses = {course for course in randomized_level_to_paintings.values() if course not in valid_move_randomizer_start_courses}
|
||||||
fix_reg(randomized_level_to_paintings, SM64Levels.BOB_OMB_BATTLEFIELD, invalid_start_courses, swapdict, world)
|
fix_reg(randomized_level_to_paintings, SM64Levels.BOB_OMB_BATTLEFIELD, invalid_start_courses, swapdict, multiworld)
|
||||||
fix_reg(randomized_level_to_paintings, SM64Levels.WHOMPS_FORTRESS, invalid_start_courses, swapdict, world)
|
fix_reg(randomized_level_to_paintings, SM64Levels.WHOMPS_FORTRESS, invalid_start_courses, swapdict, multiworld)
|
||||||
|
|
||||||
if options.area_rando == 2: # Randomize Secrets as well
|
if options.area_rando == 2: # Randomize Secrets as well
|
||||||
randomized_level_to_secrets = shuffle_dict_keys(world,sm64_level_to_secrets)
|
randomized_level_to_secrets = shuffle_dict_keys(multiworld, sm64_level_to_secrets)
|
||||||
randomized_entrances = {**randomized_level_to_paintings, **randomized_level_to_secrets}
|
randomized_entrances = {**randomized_level_to_paintings, **randomized_level_to_secrets}
|
||||||
if options.area_rando == 3: # Randomize Courses and Secrets in one pool
|
if options.area_rando == 3: # Randomize Courses and Secrets in one pool
|
||||||
randomized_entrances = shuffle_dict_keys(world, randomized_entrances)
|
randomized_entrances = shuffle_dict_keys(multiworld, randomized_entrances)
|
||||||
# Guarantee first entrance is a course
|
# Guarantee first entrance is a course
|
||||||
swapdict = randomized_entrances.copy()
|
swapdict = randomized_entrances.copy()
|
||||||
if move_rando_bitvec == 0:
|
if move_rando_bitvec == 0:
|
||||||
fix_reg(randomized_entrances, SM64Levels.BOB_OMB_BATTLEFIELD, sm64_secrets_to_level.keys(), swapdict, world)
|
fix_reg(randomized_entrances, SM64Levels.BOB_OMB_BATTLEFIELD, sm64_secrets_to_level.keys(), swapdict, multiworld)
|
||||||
else:
|
else:
|
||||||
invalid_start_courses = {course for course in randomized_entrances.values() if course not in valid_move_randomizer_start_courses}
|
invalid_start_courses = {course for course in randomized_entrances.values() if course not in valid_move_randomizer_start_courses}
|
||||||
fix_reg(randomized_entrances, SM64Levels.BOB_OMB_BATTLEFIELD, invalid_start_courses, swapdict, world)
|
fix_reg(randomized_entrances, SM64Levels.BOB_OMB_BATTLEFIELD, invalid_start_courses, swapdict, multiworld)
|
||||||
fix_reg(randomized_entrances, SM64Levels.WHOMPS_FORTRESS, invalid_start_courses, swapdict, world)
|
fix_reg(randomized_entrances, SM64Levels.WHOMPS_FORTRESS, invalid_start_courses, swapdict, multiworld)
|
||||||
# Guarantee BITFS is not mapped to DDD
|
# Guarantee BITFS is not mapped to DDD
|
||||||
fix_reg(randomized_entrances, SM64Levels.BOWSER_IN_THE_FIRE_SEA, {"Dire, Dire Docks"}, swapdict, world)
|
fix_reg(randomized_entrances, SM64Levels.BOWSER_IN_THE_FIRE_SEA, {"Dire, Dire Docks"}, swapdict, multiworld)
|
||||||
# Guarantee COTMC is not mapped to HMC, cuz thats impossible. If BitFS -> HMC, also no COTMC -> DDD.
|
# Guarantee COTMC is not mapped to HMC, cuz thats impossible. If BitFS -> HMC, also no COTMC -> DDD.
|
||||||
if randomized_entrances[SM64Levels.BOWSER_IN_THE_FIRE_SEA] == "Hazy Maze Cave":
|
if randomized_entrances[SM64Levels.BOWSER_IN_THE_FIRE_SEA] == "Hazy Maze Cave":
|
||||||
fix_reg(randomized_entrances, SM64Levels.CAVERN_OF_THE_METAL_CAP, {"Hazy Maze Cave", "Dire, Dire Docks"}, swapdict, world)
|
fix_reg(randomized_entrances, SM64Levels.CAVERN_OF_THE_METAL_CAP, {"Hazy Maze Cave", "Dire, Dire Docks"}, swapdict, multiworld)
|
||||||
else:
|
else:
|
||||||
fix_reg(randomized_entrances, SM64Levels.CAVERN_OF_THE_METAL_CAP, {"Hazy Maze Cave"}, swapdict, world)
|
fix_reg(randomized_entrances, SM64Levels.CAVERN_OF_THE_METAL_CAP, {"Hazy Maze Cave"}, swapdict, multiworld)
|
||||||
|
|
||||||
# Destination Format: LVL | AREA with LVL = LEVEL_x, AREA = Area as used in sm64 code
|
# Destination Format: LVL | AREA with LVL = LEVEL_x, AREA = Area as used in sm64 code
|
||||||
# Cast to int to not rely on availability of SM64Levels enum. Will cause crash in MultiServer otherwise
|
# Cast to int to not rely on availability of SM64Levels enum. Will cause crash in MultiServer otherwise
|
||||||
area_connections.update({int(entrance_lvl): int(sm64_entrances_to_level[destination]) for (entrance_lvl,destination) in randomized_entrances.items()})
|
area_connections.update({int(entrance_lvl): int(sm64_entrances_to_level[destination]) for (entrance_lvl,destination) in randomized_entrances.items()})
|
||||||
randomized_entrances_s = {sm64_level_to_entrances[entrance_lvl]: destination for (entrance_lvl,destination) in randomized_entrances.items()}
|
randomized_entrances_s = {sm64_level_to_entrances[entrance_lvl]: destination for (entrance_lvl,destination) in randomized_entrances.items()}
|
||||||
|
|
||||||
rf = RuleFactory(world, options, player, move_rando_bitvec)
|
rf = RuleFactory(multiworld, options, player, move_rando_bitvec)
|
||||||
|
|
||||||
connect_regions(world, player, "Menu", randomized_entrances_s["Bob-omb Battlefield"])
|
connect_regions(multiworld, player, "Menu", randomized_entrances_s["Bob-omb Battlefield"])
|
||||||
connect_regions(world, player, "Menu", randomized_entrances_s["Whomp's Fortress"],
|
connect_regions(multiworld, player, "Menu", randomized_entrances_s["Whomp's Fortress"],
|
||||||
rf.build_rule("", painting_lvl_name="WF", star_num_req=1))
|
rf.build_rule("", painting_lvl_name="WF", star_num_req=1))
|
||||||
# JRB door is separated from JRB itself because the secret aquarium can be accessed without entering the painting
|
# JRB door is separated from JRB itself because the secret aquarium can be accessed without entering the painting
|
||||||
connect_regions(world, player, "Menu", "Jolly Roger Bay Door", rf.build_rule("", star_num_req=3))
|
connect_regions(multiworld, player, "Menu", "Jolly Roger Bay Door", rf.build_rule("", star_num_req=3))
|
||||||
connect_regions(world, player, "Jolly Roger Bay Door", randomized_entrances_s["Jolly Roger Bay"],
|
connect_regions(multiworld, player, "Jolly Roger Bay Door", randomized_entrances_s["Jolly Roger Bay"],
|
||||||
rf.build_rule("", painting_lvl_name="JRB"))
|
rf.build_rule("", painting_lvl_name="JRB"))
|
||||||
connect_regions(world, player, "Menu", randomized_entrances_s["Cool, Cool Mountain"],
|
connect_regions(multiworld, player, "Menu", randomized_entrances_s["Cool, Cool Mountain"],
|
||||||
rf.build_rule("", painting_lvl_name="CCM", star_num_req=3))
|
rf.build_rule("", painting_lvl_name="CCM", star_num_req=3))
|
||||||
connect_regions(world, player, "Menu", randomized_entrances_s["Big Boo's Haunt"], lambda state: state.has("Power Star", player, 12))
|
connect_regions(multiworld, player, "Menu", randomized_entrances_s["Big Boo's Haunt"], lambda state: state.has("Power Star", player, 12))
|
||||||
connect_regions(world, player, "Menu", randomized_entrances_s["The Princess's Secret Slide"], lambda state: state.has("Power Star", player, 1))
|
connect_regions(multiworld, player, "Menu", randomized_entrances_s["The Princess's Secret Slide"], lambda state: state.has("Power Star", player, 1))
|
||||||
connect_regions(world, player, "Jolly Roger Bay Door", randomized_entrances_s["The Secret Aquarium"],
|
connect_regions(multiworld, player, "Jolly Roger Bay Door", randomized_entrances_s["The Secret Aquarium"],
|
||||||
rf.build_rule("SF/BF | TJ & LG | MOVELESS & TJ"))
|
rf.build_rule("SF/BF | TJ & LG | MOVELESS & TJ"))
|
||||||
connect_regions(world, player, "Menu", randomized_entrances_s["Tower of the Wing Cap"], lambda state: state.has("Power Star", player, 10))
|
connect_regions(multiworld, player, "Menu", randomized_entrances_s["Tower of the Wing Cap"], lambda state: state.has("Power Star", player, 10))
|
||||||
connect_regions(world, player, "Menu", randomized_entrances_s["Bowser in the Dark World"],
|
connect_regions(multiworld, player, "Menu", randomized_entrances_s["Bowser in the Dark World"],
|
||||||
lambda state: state.has("Power Star", player, star_costs["FirstBowserDoorCost"]))
|
lambda state: state.has("Power Star", player, star_costs["FirstBowserDoorCost"]))
|
||||||
|
|
||||||
connect_regions(world, player, "Menu", "Basement", lambda state: state.has("Basement Key", player) or state.has("Progressive Key", player, 1))
|
connect_regions(multiworld, player, "Menu", "Basement", lambda state: state.has("Basement Key", player) or state.has("Progressive Key", player, 1))
|
||||||
|
|
||||||
connect_regions(world, player, "Basement", randomized_entrances_s["Hazy Maze Cave"])
|
connect_regions(multiworld, player, "Basement", randomized_entrances_s["Hazy Maze Cave"])
|
||||||
connect_regions(world, player, "Basement", randomized_entrances_s["Lethal Lava Land"],
|
connect_regions(multiworld, player, "Basement", randomized_entrances_s["Lethal Lava Land"],
|
||||||
rf.build_rule("", painting_lvl_name="LLL"))
|
rf.build_rule("", painting_lvl_name="LLL"))
|
||||||
connect_regions(world, player, "Basement", randomized_entrances_s["Shifting Sand Land"],
|
connect_regions(multiworld, player, "Basement", randomized_entrances_s["Shifting Sand Land"],
|
||||||
rf.build_rule("", painting_lvl_name="SSL"))
|
rf.build_rule("", painting_lvl_name="SSL"))
|
||||||
connect_regions(world, player, "Basement", randomized_entrances_s["Dire, Dire Docks"],
|
connect_regions(multiworld, player, "Basement", randomized_entrances_s["Dire, Dire Docks"],
|
||||||
rf.build_rule("", painting_lvl_name="DDD", star_num_req=star_costs["BasementDoorCost"]))
|
rf.build_rule("", painting_lvl_name="DDD", star_num_req=star_costs["BasementDoorCost"]))
|
||||||
connect_regions(world, player, "Hazy Maze Cave", randomized_entrances_s["Cavern of the Metal Cap"])
|
connect_regions(multiworld, player, "Hazy Maze Cave", randomized_entrances_s["Cavern of the Metal Cap"])
|
||||||
connect_regions(world, player, "Basement", randomized_entrances_s["Vanish Cap under the Moat"],
|
connect_regions(multiworld, player, "Basement", randomized_entrances_s["Vanish Cap under the Moat"],
|
||||||
rf.build_rule("GP"))
|
rf.build_rule("GP"))
|
||||||
entrance = connect_regions(world, player, "Basement", randomized_entrances_s["Bowser in the Fire Sea"],
|
entrance = connect_regions(multiworld, player, "Basement", randomized_entrances_s["Bowser in the Fire Sea"],
|
||||||
lambda state: state.has("Power Star", player, star_costs["BasementDoorCost"]) and
|
lambda state: state.has("Power Star", player, star_costs["BasementDoorCost"]) and
|
||||||
state.can_reach("DDD: Board Bowser's Sub", 'Location', player))
|
state.can_reach("DDD: Board Bowser's Sub", 'Location', player))
|
||||||
# Access to "DDD: Board Bowser's Sub" does not require access to other locations or regions, so the only region that
|
# Access to "DDD: Board Bowser's Sub" does not require access to other locations or regions, so the only region that
|
||||||
# needs to be registered is its parent region.
|
# needs to be registered is its parent region.
|
||||||
world.register_indirect_condition(world.get_location("DDD: Board Bowser's Sub", player).parent_region, entrance)
|
multiworld.register_indirect_condition(multiworld.get_location("DDD: Board Bowser's Sub", player).parent_region, entrance)
|
||||||
|
|
||||||
connect_regions(world, player, "Menu", "Second Floor", lambda state: state.has("Second Floor Key", player) or state.has("Progressive Key", player, 2))
|
connect_regions(multiworld, player, "Menu", "Second Floor", lambda state: state.has("Second Floor Key", player) or state.has("Progressive Key", player, 2))
|
||||||
|
|
||||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Snowman's Land"],
|
connect_regions(multiworld, player, "Second Floor", randomized_entrances_s["Snowman's Land"],
|
||||||
rf.build_rule("", painting_lvl_name="SL"))
|
rf.build_rule("", painting_lvl_name="SL"))
|
||||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Wet-Dry World"],
|
connect_regions(multiworld, player, "Second Floor", randomized_entrances_s["Wet-Dry World"],
|
||||||
rf.build_rule("", painting_lvl_name="WDW"))
|
rf.build_rule("", painting_lvl_name="WDW"))
|
||||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Tall, Tall Mountain"],
|
connect_regions(multiworld, player, "Second Floor", randomized_entrances_s["Tall, Tall Mountain"],
|
||||||
rf.build_rule("", painting_lvl_name="TTM"))
|
rf.build_rule("", painting_lvl_name="TTM"))
|
||||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Tiny-Huge Island (Tiny)"],
|
connect_regions(multiworld, player, "Second Floor", randomized_entrances_s["Tiny-Huge Island (Tiny)"],
|
||||||
rf.build_rule("", painting_lvl_name="THI"))
|
rf.build_rule("", painting_lvl_name="THI"))
|
||||||
connect_regions(world, player, "Second Floor", randomized_entrances_s["Tiny-Huge Island (Huge)"],
|
connect_regions(multiworld, player, "Second Floor", randomized_entrances_s["Tiny-Huge Island (Huge)"],
|
||||||
rf.build_rule("", painting_lvl_name="THI"))
|
rf.build_rule("", painting_lvl_name="THI"))
|
||||||
connect_regions(world, player, "Tiny-Huge Island (Tiny)", "Tiny-Huge Island")
|
connect_regions(multiworld, player, "Tiny-Huge Island (Tiny)", "Tiny-Huge Island")
|
||||||
connect_regions(world, player, "Tiny-Huge Island (Huge)", "Tiny-Huge Island")
|
connect_regions(multiworld, player, "Tiny-Huge Island (Huge)", "Tiny-Huge Island")
|
||||||
|
|
||||||
connect_regions(world, player, "Second Floor", "Third Floor", lambda state: state.has("Power Star", player, star_costs["SecondFloorDoorCost"]))
|
connect_regions(multiworld, player, "Second Floor", "Third Floor", lambda state: state.has("Power Star", player, star_costs["SecondFloorDoorCost"]))
|
||||||
|
|
||||||
connect_regions(world, player, "Third Floor", randomized_entrances_s["Tick Tock Clock"],
|
connect_regions(multiworld, player, "Third Floor", randomized_entrances_s["Tick Tock Clock"],
|
||||||
rf.build_rule("LG/TJ/SF/BF/WK", painting_lvl_name="TTC"))
|
rf.build_rule("LG/TJ/SF/BF/WK", painting_lvl_name="TTC"))
|
||||||
connect_regions(world, player, "Third Floor", randomized_entrances_s["Rainbow Ride"], rf.build_rule("TJ/SF/BF"))
|
connect_regions(multiworld, player, "Third Floor", randomized_entrances_s["Rainbow Ride"], rf.build_rule("TJ/SF/BF"))
|
||||||
connect_regions(world, player, "Third Floor", randomized_entrances_s["Wing Mario over the Rainbow"], rf.build_rule("TJ/SF/BF"))
|
connect_regions(multiworld, player, "Third Floor", randomized_entrances_s["Wing Mario over the Rainbow"], rf.build_rule("TJ/SF/BF"))
|
||||||
connect_regions(world, player, "Third Floor", "Bowser in the Sky", lambda state: state.has("Power Star", player, star_costs["StarsToFinish"]))
|
connect_regions(multiworld, player, "Third Floor", "Bowser in the Sky", lambda state: state.has("Power Star", player, star_costs["StarsToFinish"]))
|
||||||
|
|
||||||
# Course Rules
|
# Course Rules
|
||||||
# Bob-omb Battlefield
|
# Bob-omb Battlefield
|
||||||
@@ -229,30 +229,30 @@ def set_rules(world, options: SM64Options, player: int, area_connections: dict,
|
|||||||
rf.assign_rule("THI: 100 Coins", "GP")
|
rf.assign_rule("THI: 100 Coins", "GP")
|
||||||
rf.assign_rule("RR: 100 Coins", "GP & WK")
|
rf.assign_rule("RR: 100 Coins", "GP & WK")
|
||||||
# Castle Stars
|
# Castle Stars
|
||||||
add_rule(world.get_location("Toad (Basement)", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, 12))
|
add_rule(multiworld.get_location("Toad (Basement)", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, 12))
|
||||||
add_rule(world.get_location("Toad (Second Floor)", player), lambda state: state.can_reach("Second Floor", 'Region', player) and state.has("Power Star", player, 25))
|
add_rule(multiworld.get_location("Toad (Second Floor)", player), lambda state: state.can_reach("Second Floor", 'Region', player) and state.has("Power Star", player, 25))
|
||||||
add_rule(world.get_location("Toad (Third Floor)", player), lambda state: state.can_reach("Third Floor", 'Region', player) and state.has("Power Star", player, 35))
|
add_rule(multiworld.get_location("Toad (Third Floor)", player), lambda state: state.can_reach("Third Floor", 'Region', player) and state.has("Power Star", player, 35))
|
||||||
|
|
||||||
if star_costs["MIPS1Cost"] > star_costs["MIPS2Cost"]:
|
if star_costs["MIPS1Cost"] > star_costs["MIPS2Cost"]:
|
||||||
(star_costs["MIPS2Cost"], star_costs["MIPS1Cost"]) = (star_costs["MIPS1Cost"], star_costs["MIPS2Cost"])
|
(star_costs["MIPS2Cost"], star_costs["MIPS1Cost"]) = (star_costs["MIPS1Cost"], star_costs["MIPS2Cost"])
|
||||||
rf.assign_rule("MIPS 1", "DV | MOVELESS")
|
rf.assign_rule("MIPS 1", "DV | MOVELESS")
|
||||||
rf.assign_rule("MIPS 2", "DV | MOVELESS")
|
rf.assign_rule("MIPS 2", "DV | MOVELESS")
|
||||||
add_rule(world.get_location("MIPS 1", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, star_costs["MIPS1Cost"]))
|
add_rule(multiworld.get_location("MIPS 1", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, star_costs["MIPS1Cost"]))
|
||||||
add_rule(world.get_location("MIPS 2", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, star_costs["MIPS2Cost"]))
|
add_rule(multiworld.get_location("MIPS 2", player), lambda state: state.can_reach("Basement", 'Region', player) and state.has("Power Star", player, star_costs["MIPS2Cost"]))
|
||||||
|
|
||||||
world.completion_condition[player] = lambda state: state.can_reach("BitS: Top", 'Region', player)
|
multiworld.completion_condition[player] = lambda state: state.can_reach("BitS: Top", 'Region', player)
|
||||||
|
|
||||||
if options.completion_type == "last_bowser_stage":
|
if options.completion_type == "last_bowser_stage":
|
||||||
world.completion_condition[player] = lambda state: state.can_reach("BitS: Top", 'Region', player)
|
multiworld.completion_condition[player] = lambda state: state.can_reach("BitS: Top", 'Region', player)
|
||||||
elif options.completion_type == "all_bowser_stages":
|
elif options.completion_type == "all_bowser_stages":
|
||||||
world.completion_condition[player] = lambda state: state.can_reach("Bowser in the Dark World", 'Region', player) and \
|
multiworld.completion_condition[player] = lambda state: state.can_reach("Bowser in the Dark World", 'Region', player) and \
|
||||||
state.can_reach("BitFS: Upper", 'Region', player) and \
|
state.can_reach("BitFS: Upper", 'Region', player) and \
|
||||||
state.can_reach("BitS: Top", 'Region', player)
|
state.can_reach("BitS: Top", 'Region', player)
|
||||||
|
|
||||||
|
|
||||||
class RuleFactory:
|
class RuleFactory:
|
||||||
|
|
||||||
world: MultiWorld
|
multiworld: MultiWorld
|
||||||
player: int
|
player: int
|
||||||
move_rando_bitvec: bool
|
move_rando_bitvec: bool
|
||||||
area_randomizer: bool
|
area_randomizer: bool
|
||||||
@@ -280,8 +280,8 @@ class RuleFactory:
|
|||||||
class SM64LogicException(Exception):
|
class SM64LogicException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __init__(self, world, options: SM64Options, player: int, move_rando_bitvec: int):
|
def __init__(self, multiworld, options: SM64Options, player: int, move_rando_bitvec: int):
|
||||||
self.world = world
|
self.multiworld = multiworld
|
||||||
self.player = player
|
self.player = player
|
||||||
self.move_rando_bitvec = move_rando_bitvec
|
self.move_rando_bitvec = move_rando_bitvec
|
||||||
self.area_randomizer = options.area_rando > 0
|
self.area_randomizer = options.area_rando > 0
|
||||||
@@ -291,7 +291,7 @@ class RuleFactory:
|
|||||||
self.moveless = not options.strict_move_requirements
|
self.moveless = not options.strict_move_requirements
|
||||||
|
|
||||||
def assign_rule(self, target_name: str, rule_expr: str):
|
def assign_rule(self, target_name: str, rule_expr: str):
|
||||||
target = self.world.get_location(target_name, self.player) if target_name in location_table else self.world.get_entrance(target_name, self.player)
|
target = self.multiworld.get_location(target_name, self.player) if target_name in location_table else self.multiworld.get_entrance(target_name, self.player)
|
||||||
cannon_name = "Cannon Unlock " + target_name.split(':')[0]
|
cannon_name = "Cannon Unlock " + target_name.split(':')[0]
|
||||||
try:
|
try:
|
||||||
rule = self.build_rule(rule_expr, cannon_name)
|
rule = self.build_rule(rule_expr, cannon_name)
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class SMZ3World(World):
|
|||||||
# optimized message queues for 0.4.4
|
# optimized message queues for 0.4.4
|
||||||
required_client_version = (0, 4, 4)
|
required_client_version = (0, 4, 4)
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int):
|
def __init__(self, multiworld: MultiWorld, player: int):
|
||||||
self.rom_name_available_event = threading.Event()
|
self.rom_name_available_event = threading.Event()
|
||||||
self.locations: Dict[str, Location] = {}
|
self.locations: Dict[str, Location] = {}
|
||||||
self.unreachable = []
|
self.unreachable = []
|
||||||
@@ -101,7 +101,7 @@ class SMZ3World(World):
|
|||||||
ItemType.Super,
|
ItemType.Super,
|
||||||
ItemType.PowerBomb
|
ItemType.PowerBomb
|
||||||
]]
|
]]
|
||||||
super().__init__(world, player)
|
super().__init__(multiworld, player)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def isProgression(cls, itemType):
|
def isProgression(cls, itemType):
|
||||||
@@ -672,8 +672,8 @@ class SMZ3World(World):
|
|||||||
self.locations[name] = newLoc
|
self.locations[name] = newLoc
|
||||||
self.smz3World.locationLookup[name].APLocation = newLoc
|
self.smz3World.locationLookup[name].APLocation = newLoc
|
||||||
|
|
||||||
def create_region(self, world: MultiWorld, player: int, name: str, locations=None, exits=None):
|
def create_region(self, multiworld: MultiWorld, player: int, name: str, locations=None, exits=None):
|
||||||
ret = Region(name, player, world)
|
ret = Region(name, player, multiworld)
|
||||||
if locations:
|
if locations:
|
||||||
for loc in locations:
|
for loc in locations:
|
||||||
location = self.locations[loc]
|
location = self.locations[loc]
|
||||||
|
|||||||
@@ -589,8 +589,8 @@ id,name,classification,groups,content_packs
|
|||||||
666,Maru Portrait,filler,"ENDGAME_LOCATION_ITEMS,MAXIMUM_ONE,FILLER_DECORATION,REQUIRES_FRIENDSANITY_MARRIAGE",
|
666,Maru Portrait,filler,"ENDGAME_LOCATION_ITEMS,MAXIMUM_ONE,FILLER_DECORATION,REQUIRES_FRIENDSANITY_MARRIAGE",
|
||||||
667,Penny Portrait,filler,"ENDGAME_LOCATION_ITEMS,MAXIMUM_ONE,FILLER_DECORATION,REQUIRES_FRIENDSANITY_MARRIAGE",
|
667,Penny Portrait,filler,"ENDGAME_LOCATION_ITEMS,MAXIMUM_ONE,FILLER_DECORATION,REQUIRES_FRIENDSANITY_MARRIAGE",
|
||||||
668,Sam Portrait,filler,"ENDGAME_LOCATION_ITEMS,MAXIMUM_ONE,FILLER_DECORATION,REQUIRES_FRIENDSANITY_MARRIAGE",
|
668,Sam Portrait,filler,"ENDGAME_LOCATION_ITEMS,MAXIMUM_ONE,FILLER_DECORATION,REQUIRES_FRIENDSANITY_MARRIAGE",
|
||||||
669,Sebastian Portrait,filler,"FILLER_DECORATION",
|
669,Sebastian Portrait,filler,"ENDGAME_LOCATION_ITEMS,MAXIMUM_ONE,FILLER_DECORATION,REQUIRES_FRIENDSANITY_MARRIAGE",
|
||||||
670,Shane Portrait,filler,"FILLER_DECORATION",
|
670,Shane Portrait,filler,"ENDGAME_LOCATION_ITEMS,MAXIMUM_ONE,FILLER_DECORATION,REQUIRES_FRIENDSANITY_MARRIAGE",
|
||||||
671,Trash Bear Arrival,progression,"TRASH_BEAR,COMMUNITY_REWARD",
|
671,Trash Bear Arrival,progression,"TRASH_BEAR,COMMUNITY_REWARD",
|
||||||
672,Trash Bear Cleanup,filler,"TRASH_BEAR,COMMUNITY_REWARD",
|
672,Trash Bear Cleanup,filler,"TRASH_BEAR,COMMUNITY_REWARD",
|
||||||
673,Progressive Bookseller Days,progression,"BOOKSELLER",
|
673,Progressive Bookseller Days,progression,"BOOKSELLER",
|
||||||
|
|||||||
|
@@ -6,60 +6,6 @@ from . import options
|
|||||||
from .jojapocalypse_options import Jojapocalypse, JojaStartPrice, JojaEndPrice, JojaPricingPattern, JojaPurchasesForMembership, JojaAreYouSure
|
from .jojapocalypse_options import Jojapocalypse, JojaStartPrice, JojaEndPrice, JojaPricingPattern, JojaPurchasesForMembership, JojaAreYouSure
|
||||||
from ..strings.ap_names.ap_option_names import EatsanityOptionName, ChefsanityOptionName, HatsanityOptionName
|
from ..strings.ap_names.ap_option_names import EatsanityOptionName, ChefsanityOptionName, HatsanityOptionName
|
||||||
|
|
||||||
all_random_settings = {
|
|
||||||
"progression_balancing": "random",
|
|
||||||
"accessibility": "random",
|
|
||||||
options.Goal.internal_name: "random",
|
|
||||||
options.FarmType.internal_name: "random",
|
|
||||||
options.StartingMoney.internal_name: "random",
|
|
||||||
options.ProfitMargin.internal_name: "random",
|
|
||||||
options.BundleRandomization.internal_name: "random",
|
|
||||||
options.BundlePrice.internal_name: "random",
|
|
||||||
options.BundlePerRoom.internal_name: "random",
|
|
||||||
options.EntranceRandomization.internal_name: "random",
|
|
||||||
options.SeasonRandomization.internal_name: "random",
|
|
||||||
options.Cropsanity.internal_name: "random",
|
|
||||||
options.BackpackProgression.internal_name: "random",
|
|
||||||
options.BackpackSize.internal_name: "random",
|
|
||||||
options.ToolProgression.internal_name: "random",
|
|
||||||
options.ElevatorProgression.internal_name: "random",
|
|
||||||
options.SkillProgression.internal_name: "random",
|
|
||||||
options.BuildingProgression.internal_name: "random",
|
|
||||||
options.FestivalLocations.internal_name: "random",
|
|
||||||
options.ArcadeMachineLocations.internal_name: "random",
|
|
||||||
options.SpecialOrderLocations.internal_name: "random",
|
|
||||||
options.QuestLocations.internal_name: "random",
|
|
||||||
options.Fishsanity.internal_name: "random",
|
|
||||||
options.Museumsanity.internal_name: "random",
|
|
||||||
options.Monstersanity.internal_name: "random",
|
|
||||||
options.Shipsanity.internal_name: "random",
|
|
||||||
options.Cooksanity.internal_name: "random",
|
|
||||||
options.Craftsanity.internal_name: "random",
|
|
||||||
options.Friendsanity.internal_name: "random",
|
|
||||||
options.FriendsanityHeartSize.internal_name: "random",
|
|
||||||
options.Booksanity.internal_name: "random",
|
|
||||||
options.Moviesanity.internal_name: "random",
|
|
||||||
options.IncludeEndgameLocations.internal_name: "random",
|
|
||||||
options.NumberOfMovementBuffs.internal_name: "random",
|
|
||||||
options.ExcludeGingerIsland.internal_name: "random",
|
|
||||||
options.TrapDifficulty.internal_name: "random",
|
|
||||||
options.MultipleDaySleepEnabled.internal_name: "random",
|
|
||||||
options.MultipleDaySleepCost.internal_name: "random",
|
|
||||||
options.ExperienceMultiplier.internal_name: "random",
|
|
||||||
options.FriendshipMultiplier.internal_name: "random",
|
|
||||||
options.DebrisMultiplier.internal_name: "random",
|
|
||||||
options.QuickStart.internal_name: "random",
|
|
||||||
options.Gifting.internal_name: "random",
|
|
||||||
"death_link": "random",
|
|
||||||
|
|
||||||
options.Jojapocalypse.internal_name: Jojapocalypse.option_disabled,
|
|
||||||
options.JojaStartPrice.internal_name: JojaStartPrice.default,
|
|
||||||
options.JojaEndPrice.internal_name: JojaEndPrice.default,
|
|
||||||
options.JojaPricingPattern.internal_name: JojaPricingPattern.default,
|
|
||||||
options.JojaPurchasesForMembership.internal_name: JojaPurchasesForMembership.default,
|
|
||||||
options.JojaAreYouSure.internal_name: JojaAreYouSure.option_false,
|
|
||||||
}
|
|
||||||
|
|
||||||
easy_settings = {
|
easy_settings = {
|
||||||
options.Goal.internal_name: options.Goal.option_community_center,
|
options.Goal.internal_name: options.Goal.option_community_center,
|
||||||
options.FarmType.internal_name: "random",
|
options.FarmType.internal_name: "random",
|
||||||
@@ -414,9 +360,9 @@ minsanity_settings = {
|
|||||||
options.JojaAreYouSure.internal_name: JojaAreYouSure.option_false,
|
options.JojaAreYouSure.internal_name: JojaAreYouSure.option_false,
|
||||||
}
|
}
|
||||||
|
|
||||||
allsanity_settings = {
|
maxsanity_settings = {
|
||||||
options.Goal.internal_name: options.Goal.default,
|
options.Goal.internal_name: options.Goal.default,
|
||||||
options.FarmType.internal_name: "random",
|
options.FarmType.internal_name: options.FarmType.option_beach,
|
||||||
options.StartingMoney.internal_name: options.StartingMoney.default,
|
options.StartingMoney.internal_name: options.StartingMoney.default,
|
||||||
options.ProfitMargin.internal_name: options.ProfitMargin.default,
|
options.ProfitMargin.internal_name: options.ProfitMargin.default,
|
||||||
options.BundleRandomization.internal_name: options.BundleRandomization.default,
|
options.BundleRandomization.internal_name: options.BundleRandomization.default,
|
||||||
@@ -476,12 +422,11 @@ allsanity_settings = {
|
|||||||
|
|
||||||
|
|
||||||
sv_options_presets: Dict[str, Dict[str, Any]] = {
|
sv_options_presets: Dict[str, Dict[str, Any]] = {
|
||||||
"All random": all_random_settings,
|
|
||||||
"Easy": easy_settings,
|
"Easy": easy_settings,
|
||||||
"Medium": medium_settings,
|
"Medium": medium_settings,
|
||||||
"Hard": hard_settings,
|
"Hard": hard_settings,
|
||||||
"Nightmare": nightmare_settings,
|
"Nightmare": nightmare_settings,
|
||||||
"Short": short_settings,
|
"Short": short_settings,
|
||||||
"Minsanity": minsanity_settings,
|
"Minsanity": minsanity_settings,
|
||||||
"Allsanity": allsanity_settings,
|
"Maxsanity": maxsanity_settings,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class TestItemLinksEverythingIncluded(SVTestBase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def test_filler_of_all_types_generated(self):
|
def test_filler_of_all_types_generated(self):
|
||||||
max_number_filler = 199
|
max_number_filler = 197
|
||||||
filler_generated = []
|
filler_generated = []
|
||||||
at_least_one_trap = False
|
at_least_one_trap = False
|
||||||
at_least_one_island = False
|
at_least_one_island = False
|
||||||
@@ -41,7 +41,7 @@ class TestItemLinksNoIsland(SVTestBase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def test_filler_has_no_island_but_has_traps(self):
|
def test_filler_has_no_island_but_has_traps(self):
|
||||||
max_number_filler = 192
|
max_number_filler = 190
|
||||||
filler_generated = []
|
filler_generated = []
|
||||||
at_least_one_trap = False
|
at_least_one_trap = False
|
||||||
for i in range(0, max_iterations):
|
for i in range(0, max_iterations):
|
||||||
@@ -67,7 +67,7 @@ class TestItemLinksNoTraps(SVTestBase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def test_filler_has_no_traps_but_has_island(self):
|
def test_filler_has_no_traps_but_has_island(self):
|
||||||
max_number_filler = 176
|
max_number_filler = 174
|
||||||
filler_generated = []
|
filler_generated = []
|
||||||
at_least_one_island = False
|
at_least_one_island = False
|
||||||
for i in range(0, max_iterations):
|
for i in range(0, max_iterations):
|
||||||
@@ -93,7 +93,7 @@ class TestItemLinksNoTrapsAndIsland(SVTestBase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def test_filler_generated_without_island_or_traps(self):
|
def test_filler_generated_without_island_or_traps(self):
|
||||||
max_number_filler = 169
|
max_number_filler = 167
|
||||||
filler_generated = []
|
filler_generated = []
|
||||||
for i in range(0, max_iterations):
|
for i in range(0, max_iterations):
|
||||||
filler = self.multiworld.worlds[1].get_filler_item_name()
|
filler = self.multiworld.worlds[1].get_filler_item_name()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from BaseClasses import MultiWorld, get_seed, ItemClassification
|
from BaseClasses import MultiWorld, get_seed, ItemClassification
|
||||||
from .bases import SVTestCase, solo_multiworld, setup_solo_multiworld
|
from .bases import SVTestCase, solo_multiworld, setup_solo_multiworld
|
||||||
from .options.presets import get_minsanity_options, allsanity_no_mods_7_x_x
|
from .options.presets import get_minsanity_options, maxsanity_no_mods_7_x_x
|
||||||
from .. import StardewValleyWorld
|
from .. import StardewValleyWorld
|
||||||
from ..items import Group, item_table
|
from ..items import Group, item_table
|
||||||
from ..options import Friendsanity, SeasonRandomization, Museumsanity, Shipsanity, Goal
|
from ..options import Friendsanity, SeasonRandomization, Museumsanity, Shipsanity, Goal
|
||||||
@@ -44,14 +44,14 @@ class TestItems(SVTestCase):
|
|||||||
self.assertEqual(len(baby_permutations), 4)
|
self.assertEqual(len(baby_permutations), 4)
|
||||||
|
|
||||||
def test_correct_number_of_stardrops(self):
|
def test_correct_number_of_stardrops(self):
|
||||||
allsanity_options = allsanity_no_mods_7_x_x()
|
maxsanity_options = maxsanity_no_mods_7_x_x()
|
||||||
with solo_multiworld(allsanity_options) as (multiworld, _):
|
with solo_multiworld(maxsanity_options) as (multiworld, _):
|
||||||
stardrop_items = [item for item in multiworld.get_items() if item.name == "Stardrop"]
|
stardrop_items = [item for item in multiworld.get_items() if item.name == "Stardrop"]
|
||||||
self.assertEqual(len(stardrop_items), 7)
|
self.assertEqual(len(stardrop_items), 7)
|
||||||
|
|
||||||
def test_no_duplicate_rings(self):
|
def test_no_duplicate_rings(self):
|
||||||
allsanity_options = allsanity_no_mods_7_x_x()
|
maxsanity_options = maxsanity_no_mods_7_x_x()
|
||||||
with solo_multiworld(allsanity_options) as (multiworld, _):
|
with solo_multiworld(maxsanity_options) as (multiworld, _):
|
||||||
ring_items = [item.name for item in multiworld.get_items() if Group.FILLER_RING in item_table[item.name].groups]
|
ring_items = [item.name for item in multiworld.get_items() if Group.FILLER_RING in item_table[item.name].groups]
|
||||||
self.assertEqual(len(ring_items), len(set(ring_items)))
|
self.assertEqual(len(ring_items), len(set(ring_items)))
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from unittest import TestCase, SkipTest
|
|||||||
from BaseClasses import MultiWorld
|
from BaseClasses import MultiWorld
|
||||||
from .assertion import RuleAssertMixin
|
from .assertion import RuleAssertMixin
|
||||||
from .bases import setup_solo_multiworld, skip_long_tests
|
from .bases import setup_solo_multiworld, skip_long_tests
|
||||||
from .options.presets import minimal_locations_maximal_items, allsanity_mods_7_x_x
|
from .options.presets import minimal_locations_maximal_items, maxsanity_mods_7_x_x
|
||||||
from .. import StardewValleyWorld
|
from .. import StardewValleyWorld
|
||||||
from ..data.bundles_data.bundle_data import all_bundle_items_except_money
|
from ..data.bundles_data.bundle_data import all_bundle_items_except_money
|
||||||
from ..logic.logic import StardewLogic
|
from ..logic.logic import StardewLogic
|
||||||
@@ -101,7 +101,7 @@ class LogicTestBase(RuleAssertMixin, TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestAllSanityLogic(LogicTestBase):
|
class TestAllSanityLogic(LogicTestBase):
|
||||||
options = allsanity_mods_7_x_x()
|
options = maxsanity_mods_7_x_x()
|
||||||
|
|
||||||
|
|
||||||
@unittest.skip("This test does not pass because some content is still not in content packs.")
|
@unittest.skip("This test does not pass because some content is still not in content packs.")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from BaseClasses import ItemClassification
|
from BaseClasses import ItemClassification
|
||||||
from .bases import SVTestBase
|
from .bases import SVTestBase
|
||||||
from .options.presets import default_7_x_x, allsanity_no_mods_7_x_x, get_minsanity_options, \
|
from .options.presets import default_7_x_x, maxsanity_no_mods_7_x_x, get_minsanity_options, \
|
||||||
minimal_locations_maximal_items, minimal_locations_maximal_items_with_island, allsanity_mods_7_x_x_exclude_disabled
|
minimal_locations_maximal_items, minimal_locations_maximal_items_with_island, maxsanity_mods_7_x_x_exclude_disabled
|
||||||
from .. import location_table
|
from .. import location_table
|
||||||
from ..items import Group, item_table
|
from ..items import Group, item_table
|
||||||
from ..items.item_data import FILLER_GROUPS
|
from ..items.item_data import FILLER_GROUPS
|
||||||
@@ -63,7 +63,7 @@ class TestDefaultSettingsHasAllExpectedLocations(SVTestBase):
|
|||||||
options = default_7_x_x()
|
options = default_7_x_x()
|
||||||
|
|
||||||
def test_default_settings_has_exactly_locations(self):
|
def test_default_settings_has_exactly_locations(self):
|
||||||
expected_locations = 475
|
expected_locations = 471
|
||||||
real_locations = self.get_real_locations()
|
real_locations = self.get_real_locations()
|
||||||
number_locations = len(real_locations)
|
number_locations = len(real_locations)
|
||||||
print(f"Stardew Valley - Default options locations: {number_locations}")
|
print(f"Stardew Valley - Default options locations: {number_locations}")
|
||||||
@@ -75,33 +75,33 @@ class TestDefaultSettingsHasAllExpectedLocations(SVTestBase):
|
|||||||
|
|
||||||
|
|
||||||
class TestAllSanitySettingsHasAllExpectedLocations(SVTestBase):
|
class TestAllSanitySettingsHasAllExpectedLocations(SVTestBase):
|
||||||
options = allsanity_no_mods_7_x_x()
|
options = maxsanity_no_mods_7_x_x()
|
||||||
|
|
||||||
def test_allsanity_without_mods_has_at_least_locations(self):
|
def test_maxsanity_without_mods_has_at_least_locations(self):
|
||||||
expected_locations = 2812
|
expected_locations = 2812
|
||||||
real_locations = self.get_real_locations()
|
real_locations = self.get_real_locations()
|
||||||
number_locations = len(real_locations)
|
number_locations = len(real_locations)
|
||||||
print(f"Stardew Valley - Allsanity Locations without mods: {number_locations}")
|
print(f"Stardew Valley - Maxsanity Locations without mods: {number_locations}")
|
||||||
self.assertGreaterEqual(number_locations, expected_locations)
|
self.assertGreaterEqual(number_locations, expected_locations)
|
||||||
if number_locations != expected_locations:
|
if number_locations != expected_locations:
|
||||||
print(f"\tNew locations detected!"
|
print(f"\tNew locations detected!"
|
||||||
f"\n\tPlease update test_allsanity_without_mods_has_at_least_locations"
|
f"\n\tPlease update test_maxsanity_without_mods_has_at_least_locations"
|
||||||
f"\n\t\tExpected: {expected_locations}"
|
f"\n\t\tExpected: {expected_locations}"
|
||||||
f"\n\t\tActual: {number_locations}")
|
f"\n\t\tActual: {number_locations}")
|
||||||
|
|
||||||
|
|
||||||
class TestAllSanityWithModsSettingsHasAllExpectedLocations(SVTestBase):
|
class TestAllSanityWithModsSettingsHasAllExpectedLocations(SVTestBase):
|
||||||
options = allsanity_mods_7_x_x_exclude_disabled()
|
options = maxsanity_mods_7_x_x_exclude_disabled()
|
||||||
|
|
||||||
def test_allsanity_with_mods_has_at_least_locations(self):
|
def test_maxsanity_with_mods_has_at_least_locations(self):
|
||||||
expected_locations = 3180 # It was 3473 before disabling SVE
|
expected_locations = 3180 # It was 3473 before disabling SVE
|
||||||
real_locations = self.get_real_locations()
|
real_locations = self.get_real_locations()
|
||||||
number_locations = len(real_locations)
|
number_locations = len(real_locations)
|
||||||
print(f"Stardew Valley - Allsanity Locations with all mods: {number_locations}")
|
print(f"Stardew Valley - Maxsanity Locations with all mods: {number_locations}")
|
||||||
self.assertGreaterEqual(number_locations, expected_locations)
|
self.assertGreaterEqual(number_locations, expected_locations)
|
||||||
if number_locations != expected_locations:
|
if number_locations != expected_locations:
|
||||||
print(f"\tNew locations detected!"
|
print(f"\tNew locations detected!"
|
||||||
f"\n\tPlease update test_allsanity_with_mods_has_at_least_locations"
|
f"\n\tPlease update test_maxsanity_with_mods_has_at_least_locations"
|
||||||
f"\n\t\tExpected: {expected_locations}"
|
f"\n\t\tExpected: {expected_locations}"
|
||||||
f"\n\t\tActual: {number_locations}")
|
f"\n\t\tActual: {number_locations}")
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import unittest
|
|||||||
from BaseClasses import ItemClassification
|
from BaseClasses import ItemClassification
|
||||||
from ..assertion import get_all_location_names
|
from ..assertion import get_all_location_names
|
||||||
from ..bases import skip_long_tests, SVTestCase, solo_multiworld
|
from ..bases import skip_long_tests, SVTestCase, solo_multiworld
|
||||||
from ..options.presets import setting_mins_and_maxes, allsanity_no_mods_7_x_x, get_minsanity_options, default_7_x_x
|
from ..options.presets import setting_mins_and_maxes, maxsanity_no_mods_7_x_x, get_minsanity_options, default_7_x_x
|
||||||
from ...items import Group, item_table
|
from ...items import Group, item_table
|
||||||
from ...items.item_data import FILLER_GROUPS
|
from ...items.item_data import FILLER_GROUPS
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ class TestCountsPerSetting(SVTestCase):
|
|||||||
with self.subTest(f"{name}"):
|
with self.subTest(f"{name}"):
|
||||||
highest_variance_items = -1
|
highest_variance_items = -1
|
||||||
highest_variance_locations = -1
|
highest_variance_locations = -1
|
||||||
for preset in [allsanity_no_mods_7_x_x, default_7_x_x, get_minsanity_options]:
|
for preset in [maxsanity_no_mods_7_x_x, default_7_x_x, get_minsanity_options]:
|
||||||
lowest_items = 9999
|
lowest_items = 9999
|
||||||
lowest_locations = 9999
|
lowest_locations = 9999
|
||||||
highest_items = -1
|
highest_items = -1
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
from ..TestGeneration import get_all_permanent_progression_items
|
from ..TestGeneration import get_all_permanent_progression_items
|
||||||
from ..assertion import ModAssertMixin, WorldAssertMixin
|
from ..assertion import ModAssertMixin, WorldAssertMixin
|
||||||
from ..bases import SVTestCase, SVTestBase, solo_multiworld
|
from ..bases import SVTestCase, SVTestBase, solo_multiworld
|
||||||
from ..options.presets import allsanity_mods_7_x_x
|
from ..options.presets import maxsanity_mods_7_x_x
|
||||||
from ... import options
|
from ... import options
|
||||||
from ...items import Group
|
from ...items import Group
|
||||||
from ...mods.mod_data import invalid_mod_combinations
|
from ...mods.mod_data import invalid_mod_combinations
|
||||||
from ...options.options import all_mods
|
from ...options.options import all_mods
|
||||||
|
|
||||||
|
|
||||||
class TestCanGenerateAllsanityWithMods(WorldAssertMixin, ModAssertMixin, SVTestCase):
|
class TestCanGenerateMaxsanityWithMods(WorldAssertMixin, ModAssertMixin, SVTestCase):
|
||||||
|
|
||||||
def test_allsanity_all_mods_when_generate_then_basic_checks(self):
|
def test_maxsanity_all_mods_when_generate_then_basic_checks(self):
|
||||||
with solo_multiworld(allsanity_mods_7_x_x()) as (multi_world, _):
|
with solo_multiworld(maxsanity_mods_7_x_x()) as (multi_world, _):
|
||||||
self.assert_basic_checks(multi_world)
|
self.assert_basic_checks(multi_world)
|
||||||
|
|
||||||
def test_allsanity_all_mods_exclude_island_when_generate_then_basic_checks(self):
|
def test_maxsanity_all_mods_exclude_island_when_generate_then_basic_checks(self):
|
||||||
world_options = allsanity_mods_7_x_x()
|
world_options = maxsanity_mods_7_x_x()
|
||||||
world_options.update({options.ExcludeGingerIsland.internal_name: options.ExcludeGingerIsland.option_true})
|
world_options.update({options.ExcludeGingerIsland.internal_name: options.ExcludeGingerIsland.option_true})
|
||||||
with solo_multiworld(world_options) as (multi_world, _):
|
with solo_multiworld(world_options) as (multi_world, _):
|
||||||
self.assert_basic_checks(multi_world)
|
self.assert_basic_checks(multi_world)
|
||||||
@@ -106,7 +106,7 @@ class TestVanillaLogicAlternativeWhenQuestsAreNotRandomized(WorldAssertMixin, SV
|
|||||||
"""We often forget to add an alternative rule that works when quests are not randomized. When this happens, some
|
"""We often forget to add an alternative rule that works when quests are not randomized. When this happens, some
|
||||||
Location are not reachable because they depend on items that are only added to the pool when quests are randomized.
|
Location are not reachable because they depend on items that are only added to the pool when quests are randomized.
|
||||||
"""
|
"""
|
||||||
options = allsanity_mods_7_x_x() | {
|
options = maxsanity_mods_7_x_x() | {
|
||||||
options.QuestLocations.internal_name: options.QuestLocations.special_range_names["none"],
|
options.QuestLocations.internal_name: options.QuestLocations.special_range_names["none"],
|
||||||
options.Goal.internal_name: options.Goal.option_perfection,
|
options.Goal.internal_name: options.Goal.option_perfection,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ def default_6_x_x():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def allsanity_no_mods_6_x_x():
|
def maxsanity_no_mods_6_x_x():
|
||||||
return {
|
return {
|
||||||
options.ArcadeMachineLocations.internal_name: options.ArcadeMachineLocations.option_full_shuffling,
|
options.ArcadeMachineLocations.internal_name: options.ArcadeMachineLocations.option_full_shuffling,
|
||||||
options.BackpackProgression.internal_name: options.BackpackProgression.option_progressive,
|
options.BackpackProgression.internal_name: options.BackpackProgression.option_progressive,
|
||||||
@@ -88,16 +88,16 @@ def allsanity_no_mods_6_x_x():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def allsanity_mods_6_x_x_exclude_disabled():
|
def maxsanity_mods_6_x_x_exclude_disabled():
|
||||||
allsanity = allsanity_no_mods_6_x_x()
|
maxsanity = maxsanity_no_mods_6_x_x()
|
||||||
allsanity.update({options.Mods.internal_name: frozenset(options.enabled_mods_except_invalid_combinations)})
|
maxsanity.update({options.Mods.internal_name: frozenset(options.enabled_mods_except_invalid_combinations)})
|
||||||
return allsanity
|
return maxsanity
|
||||||
|
|
||||||
|
|
||||||
def allsanity_mods_6_x_x():
|
def maxsanity_mods_6_x_x():
|
||||||
allsanity = allsanity_no_mods_6_x_x()
|
maxsanity = maxsanity_no_mods_6_x_x()
|
||||||
allsanity.update({options.Mods.internal_name: frozenset(options.all_mods_except_invalid_combinations)})
|
maxsanity.update({options.Mods.internal_name: frozenset(options.all_mods_except_invalid_combinations)})
|
||||||
return allsanity
|
return maxsanity
|
||||||
|
|
||||||
|
|
||||||
def default_7_x_x():
|
def default_7_x_x():
|
||||||
@@ -143,7 +143,7 @@ def default_7_x_x():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def allsanity_no_mods_7_x_x():
|
def maxsanity_no_mods_7_x_x():
|
||||||
return {
|
return {
|
||||||
options.ArcadeMachineLocations.internal_name: options.ArcadeMachineLocations.option_full_shuffling,
|
options.ArcadeMachineLocations.internal_name: options.ArcadeMachineLocations.option_full_shuffling,
|
||||||
options.BackpackProgression.internal_name: options.BackpackProgression.option_progressive,
|
options.BackpackProgression.internal_name: options.BackpackProgression.option_progressive,
|
||||||
@@ -188,16 +188,16 @@ def allsanity_no_mods_7_x_x():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def allsanity_mods_7_x_x():
|
def maxsanity_mods_7_x_x():
|
||||||
allsanity = allsanity_no_mods_7_x_x()
|
maxsanity = maxsanity_no_mods_7_x_x()
|
||||||
allsanity.update({options.Mods.internal_name: frozenset(options.all_mods_except_invalid_combinations)})
|
maxsanity.update({options.Mods.internal_name: frozenset(options.all_mods_except_invalid_combinations)})
|
||||||
return allsanity
|
return maxsanity
|
||||||
|
|
||||||
|
|
||||||
def allsanity_mods_7_x_x_exclude_disabled():
|
def maxsanity_mods_7_x_x_exclude_disabled():
|
||||||
allsanity = allsanity_no_mods_7_x_x()
|
maxsanity = maxsanity_no_mods_7_x_x()
|
||||||
allsanity.update({options.Mods.internal_name: frozenset(options.enabled_mods_except_invalid_combinations)})
|
maxsanity.update({options.Mods.internal_name: frozenset(options.enabled_mods_except_invalid_combinations)})
|
||||||
return allsanity
|
return maxsanity
|
||||||
|
|
||||||
|
|
||||||
def get_minsanity_options():
|
def get_minsanity_options():
|
||||||
@@ -318,7 +318,7 @@ def setting_mins_and_maxes():
|
|||||||
options.Fishsanity.internal_name: [options.Fishsanity.option_none, options.Fishsanity.option_all],
|
options.Fishsanity.internal_name: [options.Fishsanity.option_none, options.Fishsanity.option_all],
|
||||||
options.Friendsanity.internal_name: [options.Friendsanity.option_none, options.Friendsanity.option_all_with_marriage],
|
options.Friendsanity.internal_name: [options.Friendsanity.option_none, options.Friendsanity.option_all_with_marriage],
|
||||||
options.FriendsanityHeartSize.internal_name: [1, 8],
|
options.FriendsanityHeartSize.internal_name: [1, 8],
|
||||||
options.Goal.internal_name: options.Goal.option_allsanity,
|
options.Goal.internal_name: options.Goal.option_maxsanity,
|
||||||
options.IncludeEndgameLocations.internal_name: [options.IncludeEndgameLocations.option_false, options.IncludeEndgameLocations.option_true],
|
options.IncludeEndgameLocations.internal_name: [options.IncludeEndgameLocations.option_false, options.IncludeEndgameLocations.option_true],
|
||||||
options.Mods.internal_name: frozenset(),
|
options.Mods.internal_name: frozenset(),
|
||||||
options.Monstersanity.internal_name: [options.Monstersanity.option_none, options.Monstersanity.option_one_per_monster],
|
options.Monstersanity.internal_name: [options.Monstersanity.option_none, options.Monstersanity.option_one_per_monster],
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from BaseClasses import get_seed
|
|||||||
from Fill import distribute_items_restrictive, balance_multiworld_progression
|
from Fill import distribute_items_restrictive, balance_multiworld_progression
|
||||||
from worlds import AutoWorld
|
from worlds import AutoWorld
|
||||||
from ..bases import SVTestCase, setup_multiworld
|
from ..bases import SVTestCase, setup_multiworld
|
||||||
from ..options.presets import default_6_x_x, allsanity_no_mods_6_x_x, minimal_locations_maximal_items, allsanity_mods_7_x_x, allsanity_no_mods_7_x_x, \
|
from ..options.presets import default_6_x_x, maxsanity_no_mods_6_x_x, minimal_locations_maximal_items, maxsanity_mods_7_x_x, maxsanity_no_mods_7_x_x, \
|
||||||
default_7_x_x
|
default_7_x_x
|
||||||
|
|
||||||
default_number_generations = 25
|
default_number_generations = 25
|
||||||
@@ -213,9 +213,9 @@ class TestMinLocationMaxItems(SVPerformanceTestCase):
|
|||||||
self.performance_test_multiworld(multiworld_options)
|
self.performance_test_multiworld(multiworld_options)
|
||||||
|
|
||||||
|
|
||||||
class TestAllsanityWithoutMods6xx(SVPerformanceTestCase):
|
class TestMaxsanityWithoutMods6xx(SVPerformanceTestCase):
|
||||||
acceptable_time_per_player = 10
|
acceptable_time_per_player = 10
|
||||||
options = allsanity_no_mods_6_x_x()
|
options = maxsanity_no_mods_6_x_x()
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
def test_solo(self):
|
def test_solo(self):
|
||||||
@@ -242,9 +242,9 @@ class TestAllsanityWithoutMods6xx(SVPerformanceTestCase):
|
|||||||
self.performance_test_multiworld(multiworld_options)
|
self.performance_test_multiworld(multiworld_options)
|
||||||
|
|
||||||
|
|
||||||
class TestAllsanityWithoutMods7xx(SVPerformanceTestCase):
|
class TestMaxsanityWithoutMods7xx(SVPerformanceTestCase):
|
||||||
acceptable_time_per_player = 10
|
acceptable_time_per_player = 10
|
||||||
options = allsanity_no_mods_7_x_x()
|
options = maxsanity_no_mods_7_x_x()
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
def test_solo(self):
|
def test_solo(self):
|
||||||
@@ -270,9 +270,9 @@ class TestAllsanityWithoutMods7xx(SVPerformanceTestCase):
|
|||||||
self.performance_test_multiworld(multiworld_options)
|
self.performance_test_multiworld(multiworld_options)
|
||||||
|
|
||||||
|
|
||||||
class TestAllsanityWithMods7xx(SVPerformanceTestCase):
|
class TestMaxsanityWithMods7xx(SVPerformanceTestCase):
|
||||||
acceptable_time_per_player = 25
|
acceptable_time_per_player = 25
|
||||||
options = allsanity_mods_7_x_x()
|
options = maxsanity_mods_7_x_x()
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
@unittest.skip
|
@unittest.skip
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from ..bases import SVTestBase
|
from ..bases import SVTestBase
|
||||||
from ..options.presets import allsanity_mods_7_x_x
|
from ..options.presets import maxsanity_mods_7_x_x
|
||||||
from ... import locations_by_tag
|
from ... import locations_by_tag
|
||||||
from ...content.feature.hatsanity import to_location_name
|
from ...content.feature.hatsanity import to_location_name
|
||||||
from ...data.hats_data import Hats
|
from ...data.hats_data import Hats
|
||||||
@@ -75,7 +75,7 @@ class TestNoHatsLogic(SVTestBase):
|
|||||||
|
|
||||||
|
|
||||||
class TestHatLocations(SVTestBase):
|
class TestHatLocations(SVTestBase):
|
||||||
options = allsanity_mods_7_x_x()
|
options = maxsanity_mods_7_x_x()
|
||||||
|
|
||||||
def test_all_hat_locations_are_added(self):
|
def test_all_hat_locations_are_added(self):
|
||||||
location_names = [location.name for location in self.multiworld.get_locations()]
|
location_names = [location.name for location in self.multiworld.get_locations()]
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class DisabledMuseumRule(LiteralStardewRule):
|
|||||||
|
|
||||||
class TestMuseumsanityDisabledExcludesMuseumDonationsFromOtherLocations(SVTestBase):
|
class TestMuseumsanityDisabledExcludesMuseumDonationsFromOtherLocations(SVTestBase):
|
||||||
options = {
|
options = {
|
||||||
**presets.allsanity_mods_7_x_x(),
|
**presets.maxsanity_mods_7_x_x(),
|
||||||
options.Museumsanity.internal_name: options.Museumsanity.option_none
|
options.Museumsanity.internal_name: options.Museumsanity.option_none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from ..bases import SVTestBase
|
from ..bases import SVTestBase
|
||||||
from ..options.presets import allsanity_mods_7_x_x
|
from ..options.presets import maxsanity_mods_7_x_x
|
||||||
from ...stardew_rule import HasProgressionPercent
|
from ...stardew_rule import HasProgressionPercent
|
||||||
|
|
||||||
|
|
||||||
class TestHasProgressionPercentWithVictory(SVTestBase):
|
class TestHasProgressionPercentWithVictory(SVTestBase):
|
||||||
options = allsanity_mods_7_x_x()
|
options = maxsanity_mods_7_x_x()
|
||||||
skip_default_tests = True
|
skip_default_tests = True
|
||||||
|
|
||||||
def test_has_100_progression_percent_is_false_while_items_are_missing(self):
|
def test_has_100_progression_percent_is_false_while_items_are_missing(self):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from worlds.stardew_valley.test.options.presets import allsanity_mods_7_x_x_exclude_disabled
|
from worlds.stardew_valley.test.options.presets import maxsanity_mods_7_x_x_exclude_disabled
|
||||||
from ..bases import setup_solo_multiworld
|
from ..bases import setup_solo_multiworld
|
||||||
from ...options import FarmType, EntranceRandomization
|
from ...options import FarmType, EntranceRandomization
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ if __name__ == "__main__":
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
seed = args.seed
|
seed = args.seed
|
||||||
|
|
||||||
options = allsanity_mods_7_x_x_exclude_disabled()
|
options = maxsanity_mods_7_x_x_exclude_disabled()
|
||||||
options[FarmType.internal_name] = FarmType.option_standard
|
options[FarmType.internal_name] = FarmType.option_standard
|
||||||
options[EntranceRandomization.internal_name] = EntranceRandomization.option_buildings
|
options[EntranceRandomization.internal_name] = EntranceRandomization.option_buildings
|
||||||
multi_world = setup_solo_multiworld(options, seed=seed)
|
multi_world = setup_solo_multiworld(options, seed=seed)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import unittest
|
|||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
from ..bases import skip_long_tests, SVTestBase
|
from ..bases import skip_long_tests, SVTestBase
|
||||||
from ..options.presets import allsanity_mods_7_x_x
|
from ..options.presets import maxsanity_mods_7_x_x
|
||||||
from ..options.utils import fill_namespace_with_default
|
from ..options.utils import fill_namespace_with_default
|
||||||
from ... import STARDEW_VALLEY
|
from ... import STARDEW_VALLEY
|
||||||
from ...options import FarmType, BundleRandomization, EntranceRandomization
|
from ...options import FarmType, BundleRandomization, EntranceRandomization
|
||||||
@@ -10,7 +10,7 @@ from ...options import FarmType, BundleRandomization, EntranceRandomization
|
|||||||
|
|
||||||
@unittest.skipIf(skip_long_tests(), "Long tests disabled")
|
@unittest.skipIf(skip_long_tests(), "Long tests disabled")
|
||||||
class TestUniversalTrackerGenerationIsStable(SVTestBase):
|
class TestUniversalTrackerGenerationIsStable(SVTestBase):
|
||||||
options = allsanity_mods_7_x_x()
|
options = maxsanity_mods_7_x_x()
|
||||||
options.update({
|
options.update({
|
||||||
EntranceRandomization.internal_name: EntranceRandomization.option_buildings,
|
EntranceRandomization.internal_name: EntranceRandomization.option_buildings,
|
||||||
BundleRandomization.internal_name: BundleRandomization.option_shuffled,
|
BundleRandomization.internal_name: BundleRandomization.option_shuffled,
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
from ...items import items_by_group, Group
|
from ...items import items_by_group, Group
|
||||||
from ...options import TrapDifficulty
|
from ...options import TrapDifficulty
|
||||||
from ...test.bases import SVTestCase, solo_multiworld
|
from ...test.bases import SVTestCase, solo_multiworld
|
||||||
from ...test.options.presets import allsanity_mods_7_x_x, allsanity_no_mods_7_x_x
|
from ...test.options.presets import maxsanity_mods_7_x_x, maxsanity_no_mods_7_x_x
|
||||||
|
|
||||||
|
|
||||||
class TestTraps(SVTestCase):
|
class TestTraps(SVTestCase):
|
||||||
def test_given_no_traps_when_generate_then_no_trap_in_pool(self):
|
def test_given_no_traps_when_generate_then_no_trap_in_pool(self):
|
||||||
world_options = allsanity_no_mods_7_x_x().copy()
|
world_options = maxsanity_no_mods_7_x_x().copy()
|
||||||
world_options[TrapDifficulty.internal_name] = TrapDifficulty.option_no_traps
|
world_options[TrapDifficulty.internal_name] = TrapDifficulty.option_no_traps
|
||||||
with solo_multiworld(world_options) as (multi_world, _):
|
with solo_multiworld(world_options) as (multi_world, _):
|
||||||
trap_items = [item_data.name for item_data in items_by_group[Group.TRAP]]
|
trap_items = [item_data.name for item_data in items_by_group[Group.TRAP]]
|
||||||
@@ -18,7 +18,7 @@ class TestTraps(SVTestCase):
|
|||||||
|
|
||||||
def test_given_traps_when_generate_then_all_traps_in_pool(self):
|
def test_given_traps_when_generate_then_all_traps_in_pool(self):
|
||||||
trap_option = TrapDifficulty
|
trap_option = TrapDifficulty
|
||||||
world_options = allsanity_mods_7_x_x()
|
world_options = maxsanity_mods_7_x_x()
|
||||||
world_options.update({TrapDifficulty.internal_name: trap_option.option_easy})
|
world_options.update({TrapDifficulty.internal_name: trap_option.option_easy})
|
||||||
with solo_multiworld(world_options) as (multi_world, _):
|
with solo_multiworld(world_options) as (multi_world, _):
|
||||||
trap_items = [item_data.name for item_data in items_by_group[Group.TRAP] if Group.DEPRECATED not in item_data.groups]
|
trap_items = [item_data.name for item_data in items_by_group[Group.TRAP] if Group.DEPRECATED not in item_data.groups]
|
||||||
|
|||||||
+188
-188
@@ -6,200 +6,200 @@ from .PreCalculatedWeights import PreCalculatedWeights
|
|||||||
from .LogicExtensions import TimespinnerLogic
|
from .LogicExtensions import TimespinnerLogic
|
||||||
|
|
||||||
|
|
||||||
def create_regions_and_locations(world: MultiWorld, player: int, options: TimespinnerOptions,
|
def create_regions_and_locations(multiworld: MultiWorld, player: int, options: TimespinnerOptions,
|
||||||
precalculated_weights: PreCalculatedWeights):
|
precalculated_weights: PreCalculatedWeights):
|
||||||
|
|
||||||
locations_per_region: Dict[str, List[LocationData]] = split_location_datas_per_region(
|
locations_per_region: Dict[str, List[LocationData]] = split_location_datas_per_region(
|
||||||
get_location_datas(player, options, precalculated_weights))
|
get_location_datas(player, options, precalculated_weights))
|
||||||
|
|
||||||
regions = [
|
regions = [
|
||||||
create_region(world, player, locations_per_region, 'Menu'),
|
create_region(multiworld, player, locations_per_region, 'Menu'),
|
||||||
create_region(world, player, locations_per_region, 'Tutorial'),
|
create_region(multiworld, player, locations_per_region, 'Tutorial'),
|
||||||
create_region(world, player, locations_per_region, 'Lake desolation'),
|
create_region(multiworld, player, locations_per_region, 'Lake desolation'),
|
||||||
create_region(world, player, locations_per_region, 'Upper lake desolation'),
|
create_region(multiworld, player, locations_per_region, 'Upper lake desolation'),
|
||||||
create_region(world, player, locations_per_region, 'Lower lake desolation'),
|
create_region(multiworld, player, locations_per_region, 'Lower lake desolation'),
|
||||||
create_region(world, player, locations_per_region, 'Eastern lake desolation'),
|
create_region(multiworld, player, locations_per_region, 'Eastern lake desolation'),
|
||||||
create_region(world, player, locations_per_region, 'Library'),
|
create_region(multiworld, player, locations_per_region, 'Library'),
|
||||||
create_region(world, player, locations_per_region, 'Library top'),
|
create_region(multiworld, player, locations_per_region, 'Library top'),
|
||||||
create_region(world, player, locations_per_region, 'Varndagroth tower left'),
|
create_region(multiworld, player, locations_per_region, 'Varndagroth tower left'),
|
||||||
create_region(world, player, locations_per_region, 'Varndagroth tower right (upper)'),
|
create_region(multiworld, player, locations_per_region, 'Varndagroth tower right (upper)'),
|
||||||
create_region(world, player, locations_per_region, 'Varndagroth tower right (lower)'),
|
create_region(multiworld, player, locations_per_region, 'Varndagroth tower right (lower)'),
|
||||||
create_region(world, player, locations_per_region, 'Varndagroth tower right (elevator)'),
|
create_region(multiworld, player, locations_per_region, 'Varndagroth tower right (elevator)'),
|
||||||
create_region(world, player, locations_per_region, 'Sealed Caves (Sirens)'),
|
create_region(multiworld, player, locations_per_region, 'Sealed Caves (Sirens)'),
|
||||||
create_region(world, player, locations_per_region, 'Military Fortress'),
|
create_region(multiworld, player, locations_per_region, 'Military Fortress'),
|
||||||
create_region(world, player, locations_per_region, 'Military Fortress (hangar)'),
|
create_region(multiworld, player, locations_per_region, 'Military Fortress (hangar)'),
|
||||||
create_region(world, player, locations_per_region, 'Lab Entrance'),
|
create_region(multiworld, player, locations_per_region, 'Lab Entrance'),
|
||||||
create_region(world, player, locations_per_region, 'Main Lab'),
|
create_region(multiworld, player, locations_per_region, 'Main Lab'),
|
||||||
create_region(world, player, locations_per_region, 'Lab Research'),
|
create_region(multiworld, player, locations_per_region, 'Lab Research'),
|
||||||
create_region(world, player, locations_per_region, 'The lab (upper)'),
|
create_region(multiworld, player, locations_per_region, 'The lab (upper)'),
|
||||||
create_region(world, player, locations_per_region, 'Emperors tower (courtyard)'),
|
create_region(multiworld, player, locations_per_region, 'Emperors tower (courtyard)'),
|
||||||
create_region(world, player, locations_per_region, 'Emperors tower'),
|
create_region(multiworld, player, locations_per_region, 'Emperors tower'),
|
||||||
create_region(world, player, locations_per_region, 'Skeleton Shaft'),
|
create_region(multiworld, player, locations_per_region, 'Skeleton Shaft'),
|
||||||
create_region(world, player, locations_per_region, 'Sealed Caves (Xarion)'),
|
create_region(multiworld, player, locations_per_region, 'Sealed Caves (Xarion)'),
|
||||||
create_region(world, player, locations_per_region, 'Refugee Camp'),
|
create_region(multiworld, player, locations_per_region, 'Refugee Camp'),
|
||||||
create_region(world, player, locations_per_region, 'Forest'),
|
create_region(multiworld, player, locations_per_region, 'Forest'),
|
||||||
create_region(world, player, locations_per_region, 'Left Side forest Caves'),
|
create_region(multiworld, player, locations_per_region, 'Left Side forest Caves'),
|
||||||
create_region(world, player, locations_per_region, 'Upper Lake Serene'),
|
create_region(multiworld, player, locations_per_region, 'Upper Lake Serene'),
|
||||||
create_region(world, player, locations_per_region, 'Lower Lake Serene'),
|
create_region(multiworld, player, locations_per_region, 'Lower Lake Serene'),
|
||||||
create_region(world, player, locations_per_region, 'Caves of Banishment (upper)'),
|
create_region(multiworld, player, locations_per_region, 'Caves of Banishment (upper)'),
|
||||||
create_region(world, player, locations_per_region, 'Caves of Banishment (Maw)'),
|
create_region(multiworld, player, locations_per_region, 'Caves of Banishment (Maw)'),
|
||||||
create_region(world, player, locations_per_region, 'Caves of Banishment (Flooded)'),
|
create_region(multiworld, player, locations_per_region, 'Caves of Banishment (Flooded)'),
|
||||||
create_region(world, player, locations_per_region, 'Caves of Banishment (Sirens)'),
|
create_region(multiworld, player, locations_per_region, 'Caves of Banishment (Sirens)'),
|
||||||
create_region(world, player, locations_per_region, 'Castle Ramparts'),
|
create_region(multiworld, player, locations_per_region, 'Castle Ramparts'),
|
||||||
create_region(world, player, locations_per_region, 'Castle Keep'),
|
create_region(multiworld, player, locations_per_region, 'Castle Keep'),
|
||||||
create_region(world, player, locations_per_region, 'Castle Basement'),
|
create_region(multiworld, player, locations_per_region, 'Castle Basement'),
|
||||||
create_region(world, player, locations_per_region, 'Royal towers (lower)'),
|
create_region(multiworld, player, locations_per_region, 'Royal towers (lower)'),
|
||||||
create_region(world, player, locations_per_region, 'Royal towers'),
|
create_region(multiworld, player, locations_per_region, 'Royal towers'),
|
||||||
create_region(world, player, locations_per_region, 'Royal towers (upper)'),
|
create_region(multiworld, player, locations_per_region, 'Royal towers (upper)'),
|
||||||
create_region(world, player, locations_per_region, 'Temporal Gyre'),
|
create_region(multiworld, player, locations_per_region, 'Temporal Gyre'),
|
||||||
create_region(world, player, locations_per_region, 'Ancient Pyramid (entrance)'),
|
create_region(multiworld, player, locations_per_region, 'Ancient Pyramid (entrance)'),
|
||||||
create_region(world, player, locations_per_region, 'Ancient Pyramid (left)'),
|
create_region(multiworld, player, locations_per_region, 'Ancient Pyramid (left)'),
|
||||||
create_region(world, player, locations_per_region, 'Ancient Pyramid (right)'),
|
create_region(multiworld, player, locations_per_region, 'Ancient Pyramid (right)'),
|
||||||
create_region(world, player, locations_per_region, 'Space time continuum')
|
create_region(multiworld, player, locations_per_region, 'Space time continuum')
|
||||||
]
|
]
|
||||||
|
|
||||||
if options.gyre_archives:
|
if options.gyre_archives:
|
||||||
regions.extend([
|
regions.extend([
|
||||||
create_region(world, player, locations_per_region, 'Ravenlord\'s Lair'),
|
create_region(multiworld, player, locations_per_region, 'Ravenlord\'s Lair'),
|
||||||
create_region(world, player, locations_per_region, 'Ifrit\'s Lair'),
|
create_region(multiworld, player, locations_per_region, 'Ifrit\'s Lair'),
|
||||||
])
|
])
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
throwIfAnyLocationIsNotAssignedToARegion(regions, locations_per_region.keys())
|
throwIfAnyLocationIsNotAssignedToARegion(regions, locations_per_region.keys())
|
||||||
|
|
||||||
world.regions += regions
|
multiworld.regions += regions
|
||||||
|
|
||||||
connectStartingRegion(world, player, options)
|
connectStartingRegion(multiworld, player, options)
|
||||||
|
|
||||||
flooded: PreCalculatedWeights = precalculated_weights
|
flooded: PreCalculatedWeights = precalculated_weights
|
||||||
logic = TimespinnerLogic(player, options, precalculated_weights)
|
logic = TimespinnerLogic(player, options, precalculated_weights)
|
||||||
|
|
||||||
connect(world, player, 'Lake desolation', 'Lower lake desolation', lambda state: flooded.flood_lake_desolation or logic.has_timestop(state) or state.has('Talaria Attachment', player))
|
connect(multiworld, player, 'Lake desolation', 'Lower lake desolation', lambda state: flooded.flood_lake_desolation or logic.has_timestop(state) or state.has('Talaria Attachment', player))
|
||||||
connect(world, player, 'Lake desolation', 'Upper lake desolation', lambda state: logic.has_fire(state) and state.can_reach('Upper Lake Serene', 'Region', player), "Upper Lake Serene")
|
connect(multiworld, player, 'Lake desolation', 'Upper lake desolation', lambda state: logic.has_fire(state) and state.can_reach('Upper Lake Serene', 'Region', player), "Upper Lake Serene")
|
||||||
connect(world, player, 'Lake desolation', 'Skeleton Shaft', lambda state: flooded.flood_lake_desolation or logic.has_doublejump(state))
|
connect(multiworld, player, 'Lake desolation', 'Skeleton Shaft', lambda state: flooded.flood_lake_desolation or logic.has_doublejump(state))
|
||||||
connect(world, player, 'Lake desolation', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Lake desolation', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Upper lake desolation', 'Lake desolation')
|
connect(multiworld, player, 'Upper lake desolation', 'Lake desolation')
|
||||||
connect(world, player, 'Upper lake desolation', 'Eastern lake desolation')
|
connect(multiworld, player, 'Upper lake desolation', 'Eastern lake desolation')
|
||||||
connect(world, player, 'Lower lake desolation', 'Lake desolation')
|
connect(multiworld, player, 'Lower lake desolation', 'Lake desolation')
|
||||||
connect(world, player, 'Lower lake desolation', 'Eastern lake desolation')
|
connect(multiworld, player, 'Lower lake desolation', 'Eastern lake desolation')
|
||||||
connect(world, player, 'Eastern lake desolation', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Eastern lake desolation', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Eastern lake desolation', 'Library')
|
connect(multiworld, player, 'Eastern lake desolation', 'Library')
|
||||||
connect(world, player, 'Eastern lake desolation', 'Lower lake desolation')
|
connect(multiworld, player, 'Eastern lake desolation', 'Lower lake desolation')
|
||||||
connect(world, player, 'Eastern lake desolation', 'Upper lake desolation', lambda state: logic.has_fire(state) and state.can_reach('Upper Lake Serene', 'Region', player), "Upper Lake Serene")
|
connect(multiworld, player, 'Eastern lake desolation', 'Upper lake desolation', lambda state: logic.has_fire(state) and state.can_reach('Upper Lake Serene', 'Region', player), "Upper Lake Serene")
|
||||||
connect(world, player, 'Library', 'Eastern lake desolation')
|
connect(multiworld, player, 'Library', 'Eastern lake desolation')
|
||||||
connect(world, player, 'Library', 'Library top', lambda state: logic.has_doublejump(state) or state.has('Talaria Attachment', player))
|
connect(multiworld, player, 'Library', 'Library top', lambda state: logic.has_doublejump(state) or state.has('Talaria Attachment', player))
|
||||||
connect(world, player, 'Library', 'Varndagroth tower left', logic.has_keycard_D)
|
connect(multiworld, player, 'Library', 'Varndagroth tower left', logic.has_keycard_D)
|
||||||
connect(world, player, 'Library', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Library', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Library top', 'Library')
|
connect(multiworld, player, 'Library top', 'Library')
|
||||||
connect(world, player, 'Varndagroth tower left', 'Library')
|
connect(multiworld, player, 'Varndagroth tower left', 'Library')
|
||||||
connect(world, player, 'Varndagroth tower left', 'Varndagroth tower right (upper)', logic.has_keycard_C)
|
connect(multiworld, player, 'Varndagroth tower left', 'Varndagroth tower right (upper)', logic.has_keycard_C)
|
||||||
connect(world, player, 'Varndagroth tower left', 'Varndagroth tower right (lower)', logic.has_keycard_B)
|
connect(multiworld, player, 'Varndagroth tower left', 'Varndagroth tower right (lower)', logic.has_keycard_B)
|
||||||
connect(world, player, 'Varndagroth tower left', 'Sealed Caves (Sirens)', lambda state: logic.has_keycard_B(state) and state.has('Elevator Keycard', player))
|
connect(multiworld, player, 'Varndagroth tower left', 'Sealed Caves (Sirens)', lambda state: logic.has_keycard_B(state) and state.has('Elevator Keycard', player))
|
||||||
connect(world, player, 'Varndagroth tower left', 'Refugee Camp', lambda state: state.has('Timespinner Wheel', player) and state.has('Timespinner Spindle', player))
|
connect(multiworld, player, 'Varndagroth tower left', 'Refugee Camp', lambda state: state.has('Timespinner Wheel', player) and state.has('Timespinner Spindle', player))
|
||||||
connect(world, player, 'Varndagroth tower right (upper)', 'Varndagroth tower left')
|
connect(multiworld, player, 'Varndagroth tower right (upper)', 'Varndagroth tower left')
|
||||||
connect(world, player, 'Varndagroth tower right (upper)', 'Varndagroth tower right (elevator)', lambda state: state.has('Elevator Keycard', player))
|
connect(multiworld, player, 'Varndagroth tower right (upper)', 'Varndagroth tower right (elevator)', lambda state: state.has('Elevator Keycard', player))
|
||||||
connect(world, player, 'Varndagroth tower right (elevator)', 'Varndagroth tower right (upper)')
|
connect(multiworld, player, 'Varndagroth tower right (elevator)', 'Varndagroth tower right (upper)')
|
||||||
connect(world, player, 'Varndagroth tower right (elevator)', 'Varndagroth tower right (lower)')
|
connect(multiworld, player, 'Varndagroth tower right (elevator)', 'Varndagroth tower right (lower)')
|
||||||
connect(world, player, 'Varndagroth tower right (lower)', 'Varndagroth tower left', logic.has_keycard_B)
|
connect(multiworld, player, 'Varndagroth tower right (lower)', 'Varndagroth tower left', logic.has_keycard_B)
|
||||||
connect(world, player, 'Varndagroth tower right (lower)', 'Varndagroth tower right (elevator)', lambda state: state.has('Elevator Keycard', player))
|
connect(multiworld, player, 'Varndagroth tower right (lower)', 'Varndagroth tower right (elevator)', lambda state: state.has('Elevator Keycard', player))
|
||||||
connect(world, player, 'Varndagroth tower right (lower)', 'Sealed Caves (Sirens)', lambda state: logic.has_keycard_B(state) and state.has('Elevator Keycard', player))
|
connect(multiworld, player, 'Varndagroth tower right (lower)', 'Sealed Caves (Sirens)', lambda state: logic.has_keycard_B(state) and state.has('Elevator Keycard', player))
|
||||||
connect(world, player, 'Varndagroth tower right (lower)', 'Military Fortress', logic.can_kill_all_3_bosses)
|
connect(multiworld, player, 'Varndagroth tower right (lower)', 'Military Fortress', logic.can_kill_all_3_bosses)
|
||||||
connect(world, player, 'Varndagroth tower right (lower)', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Varndagroth tower right (lower)', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Sealed Caves (Sirens)', 'Varndagroth tower left', lambda state: state.has('Elevator Keycard', player))
|
connect(multiworld, player, 'Sealed Caves (Sirens)', 'Varndagroth tower left', lambda state: state.has('Elevator Keycard', player))
|
||||||
connect(world, player, 'Sealed Caves (Sirens)', 'Varndagroth tower right (lower)', lambda state: state.has('Elevator Keycard', player))
|
connect(multiworld, player, 'Sealed Caves (Sirens)', 'Varndagroth tower right (lower)', lambda state: state.has('Elevator Keycard', player))
|
||||||
connect(world, player, 'Sealed Caves (Sirens)', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Sealed Caves (Sirens)', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Military Fortress', 'Varndagroth tower right (lower)', logic.can_kill_all_3_bosses)
|
connect(multiworld, player, 'Military Fortress', 'Varndagroth tower right (lower)', logic.can_kill_all_3_bosses)
|
||||||
connect(world, player, 'Military Fortress', 'Temporal Gyre', lambda state: state.has('Timespinner Wheel', player) and logic.can_kill_all_3_bosses(state))
|
connect(multiworld, player, 'Military Fortress', 'Temporal Gyre', lambda state: state.has('Timespinner Wheel', player) and logic.can_kill_all_3_bosses(state))
|
||||||
connect(world, player, 'Military Fortress', 'Military Fortress (hangar)', logic.has_doublejump)
|
connect(multiworld, player, 'Military Fortress', 'Military Fortress (hangar)', logic.has_doublejump)
|
||||||
connect(world, player, 'Military Fortress (hangar)', 'Military Fortress')
|
connect(multiworld, player, 'Military Fortress (hangar)', 'Military Fortress')
|
||||||
connect(world, player, 'Military Fortress (hangar)', 'Lab Entrance', lambda state: state.has('Water Mask', player) if flooded.flood_lab else logic.has_doublejump(state))
|
connect(multiworld, player, 'Military Fortress (hangar)', 'Lab Entrance', lambda state: state.has('Water Mask', player) if flooded.flood_lab else logic.has_doublejump(state))
|
||||||
connect(world, player, 'Lab Entrance', 'Main Lab', lambda state: logic.has_keycard_B(state))
|
connect(multiworld, player, 'Lab Entrance', 'Main Lab', lambda state: logic.has_keycard_B(state))
|
||||||
connect(world, player, 'Main Lab', 'Lab Entrance')
|
connect(multiworld, player, 'Main Lab', 'Lab Entrance')
|
||||||
connect(world, player, 'Lab Entrance', 'Military Fortress (hangar)')
|
connect(multiworld, player, 'Lab Entrance', 'Military Fortress (hangar)')
|
||||||
connect(world, player, 'Temporal Gyre', 'Military Fortress')
|
connect(multiworld, player, 'Temporal Gyre', 'Military Fortress')
|
||||||
connect(world, player, 'Main Lab', 'Lab Research', lambda state: state.has('Lab Access Research', player) if options.lock_key_amadeus else logic.has_doublejump_of_npc(state))
|
connect(multiworld, player, 'Main Lab', 'Lab Research', lambda state: state.has('Lab Access Research', player) if options.lock_key_amadeus else logic.has_doublejump_of_npc(state))
|
||||||
connect(world, player, 'Main Lab', 'The lab (upper)', lambda state: logic.has_forwarddash_doublejump(state) and ((not options.lock_key_amadeus) or state.has('Lab Access Genza', player)))
|
connect(multiworld, player, 'Main Lab', 'The lab (upper)', lambda state: logic.has_forwarddash_doublejump(state) and ((not options.lock_key_amadeus) or state.has('Lab Access Genza', player)))
|
||||||
connect(world, player, 'The lab (upper)', 'Main Lab', lambda state: options.lock_key_amadeus and state.has('Lab Access Genza', player))
|
connect(multiworld, player, 'The lab (upper)', 'Main Lab', lambda state: options.lock_key_amadeus and state.has('Lab Access Genza', player))
|
||||||
connect(world, player, 'The lab (upper)', 'Emperors tower (courtyard)', logic.has_forwarddash_doublejump)
|
connect(multiworld, player, 'The lab (upper)', 'Emperors tower (courtyard)', logic.has_forwarddash_doublejump)
|
||||||
connect(world, player, 'The lab (upper)', 'Ancient Pyramid (entrance)', lambda state: state.has_all({'Timespinner Wheel', 'Timespinner Spindle', 'Timespinner Gear 1', 'Timespinner Gear 2', 'Timespinner Gear 3'}, player))
|
connect(multiworld, player, 'The lab (upper)', 'Ancient Pyramid (entrance)', lambda state: state.has_all({'Timespinner Wheel', 'Timespinner Spindle', 'Timespinner Gear 1', 'Timespinner Gear 2', 'Timespinner Gear 3'}, player))
|
||||||
connect(world, player, 'Emperors tower (courtyard)', 'The lab (upper)')
|
connect(multiworld, player, 'Emperors tower (courtyard)', 'The lab (upper)')
|
||||||
connect(world, player, 'Emperors tower (courtyard)', 'Emperors tower', logic.has_doublejump)
|
connect(multiworld, player, 'Emperors tower (courtyard)', 'Emperors tower', logic.has_doublejump)
|
||||||
connect(world, player, 'Emperors tower', 'Emperors tower (courtyard)')
|
connect(multiworld, player, 'Emperors tower', 'Emperors tower (courtyard)')
|
||||||
connect(world, player, 'Skeleton Shaft', 'Lake desolation')
|
connect(multiworld, player, 'Skeleton Shaft', 'Lake desolation')
|
||||||
connect(world, player, 'Skeleton Shaft', 'Sealed Caves (Xarion)', logic.has_keycard_A)
|
connect(multiworld, player, 'Skeleton Shaft', 'Sealed Caves (Xarion)', logic.has_keycard_A)
|
||||||
connect(world, player, 'Skeleton Shaft', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Skeleton Shaft', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Sealed Caves (Xarion)', 'Skeleton Shaft')
|
connect(multiworld, player, 'Sealed Caves (Xarion)', 'Skeleton Shaft')
|
||||||
connect(world, player, 'Sealed Caves (Xarion)', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Sealed Caves (Xarion)', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Refugee Camp', 'Forest')
|
connect(multiworld, player, 'Refugee Camp', 'Forest')
|
||||||
connect(world, player, 'Refugee Camp', 'Library', lambda state: (options.pyramid_start or options.inverted) and options.back_to_the_future and state.has_all({'Timespinner Wheel', 'Timespinner Spindle'}, player))
|
connect(multiworld, player, 'Refugee Camp', 'Library', lambda state: (options.pyramid_start or options.inverted) and options.back_to_the_future and state.has_all({'Timespinner Wheel', 'Timespinner Spindle'}, player))
|
||||||
connect(world, player, 'Refugee Camp', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Refugee Camp', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Forest', 'Refugee Camp')
|
connect(multiworld, player, 'Forest', 'Refugee Camp')
|
||||||
connect(world, player, 'Forest', 'Left Side forest Caves', lambda state: flooded.flood_lake_serene_bridge or state.has('Talaria Attachment', player) or logic.has_timestop(state))
|
connect(multiworld, player, 'Forest', 'Left Side forest Caves', lambda state: flooded.flood_lake_serene_bridge or state.has('Talaria Attachment', player) or logic.has_timestop(state))
|
||||||
connect(world, player, 'Forest', 'Caves of Banishment (Sirens)')
|
connect(multiworld, player, 'Forest', 'Caves of Banishment (Sirens)')
|
||||||
connect(world, player, 'Forest', 'Castle Ramparts', lambda state: not options.gate_keep or state.has('Drawbridge Key', player) or logic.has_upwarddash(state))
|
connect(multiworld, player, 'Forest', 'Castle Ramparts', lambda state: not options.gate_keep or state.has('Drawbridge Key', player) or logic.has_upwarddash(state))
|
||||||
connect(world, player, 'Left Side forest Caves', 'Forest')
|
connect(multiworld, player, 'Left Side forest Caves', 'Forest')
|
||||||
connect(world, player, 'Left Side forest Caves', 'Upper Lake Serene', logic.has_timestop)
|
connect(multiworld, player, 'Left Side forest Caves', 'Upper Lake Serene', logic.has_timestop)
|
||||||
connect(world, player, 'Left Side forest Caves', 'Lower Lake Serene', lambda state: not flooded.flood_lake_serene or state.has('Water Mask', player))
|
connect(multiworld, player, 'Left Side forest Caves', 'Lower Lake Serene', lambda state: not flooded.flood_lake_serene or state.has('Water Mask', player))
|
||||||
connect(world, player, 'Left Side forest Caves', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Left Side forest Caves', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Upper Lake Serene', 'Left Side forest Caves')
|
connect(multiworld, player, 'Upper Lake Serene', 'Left Side forest Caves')
|
||||||
connect(world, player, 'Upper Lake Serene', 'Lower Lake Serene', lambda state: not flooded.flood_lake_serene or state.has('Water Mask', player))
|
connect(multiworld, player, 'Upper Lake Serene', 'Lower Lake Serene', lambda state: not flooded.flood_lake_serene or state.has('Water Mask', player))
|
||||||
connect(world, player, 'Lower Lake Serene', 'Upper Lake Serene')
|
connect(multiworld, player, 'Lower Lake Serene', 'Upper Lake Serene')
|
||||||
connect(world, player, 'Lower Lake Serene', 'Left Side forest Caves')
|
connect(multiworld, player, 'Lower Lake Serene', 'Left Side forest Caves')
|
||||||
connect(world, player, 'Lower Lake Serene', 'Caves of Banishment (upper)', lambda state: flooded.flood_lake_serene or logic.has_doublejump(state))
|
connect(multiworld, player, 'Lower Lake Serene', 'Caves of Banishment (upper)', lambda state: flooded.flood_lake_serene or logic.has_doublejump(state))
|
||||||
connect(world, player, 'Caves of Banishment (upper)', 'Lower Lake Serene', lambda state: not flooded.flood_lake_serene or state.has('Water Mask', player))
|
connect(multiworld, player, 'Caves of Banishment (upper)', 'Lower Lake Serene', lambda state: not flooded.flood_lake_serene or state.has('Water Mask', player))
|
||||||
connect(world, player, 'Caves of Banishment (upper)', 'Caves of Banishment (Maw)', lambda state: not flooded.flood_maw or state.has('Water Mask', player))
|
connect(multiworld, player, 'Caves of Banishment (upper)', 'Caves of Banishment (Maw)', lambda state: not flooded.flood_maw or state.has('Water Mask', player))
|
||||||
connect(world, player, 'Caves of Banishment (upper)', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Caves of Banishment (upper)', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Caves of Banishment (Maw)', 'Caves of Banishment (upper)', lambda state: logic.has_doublejump(state) if not flooded.flood_maw else state.has('Water Mask', player))
|
connect(multiworld, player, 'Caves of Banishment (Maw)', 'Caves of Banishment (upper)', lambda state: logic.has_doublejump(state) if not flooded.flood_maw else state.has('Water Mask', player))
|
||||||
connect(world, player, 'Caves of Banishment (Maw)', 'Caves of Banishment (Sirens)', lambda state: state.has_any({'Gas Mask', 'Talaria Attachment'}, player) )
|
connect(multiworld, player, 'Caves of Banishment (Maw)', 'Caves of Banishment (Sirens)', lambda state: state.has_any({'Gas Mask', 'Talaria Attachment'}, player) )
|
||||||
connect(world, player, 'Caves of Banishment (Maw)', 'Caves of Banishment (Flooded)', lambda state: flooded.flood_maw or state.has('Water Mask', player))
|
connect(multiworld, player, 'Caves of Banishment (Maw)', 'Caves of Banishment (Flooded)', lambda state: flooded.flood_maw or state.has('Water Mask', player))
|
||||||
connect(world, player, 'Caves of Banishment (Maw)', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Caves of Banishment (Maw)', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Caves of Banishment (Sirens)', 'Forest')
|
connect(multiworld, player, 'Caves of Banishment (Sirens)', 'Forest')
|
||||||
connect(world, player, 'Castle Ramparts', 'Forest')
|
connect(multiworld, player, 'Castle Ramparts', 'Forest')
|
||||||
connect(world, player, 'Castle Ramparts', 'Castle Keep')
|
connect(multiworld, player, 'Castle Ramparts', 'Castle Keep')
|
||||||
connect(world, player, 'Castle Ramparts', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Castle Ramparts', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Castle Keep', 'Castle Ramparts')
|
connect(multiworld, player, 'Castle Keep', 'Castle Ramparts')
|
||||||
connect(world, player, 'Castle Keep', 'Castle Basement', lambda state: not flooded.flood_basement or state.has('Water Mask', player))
|
connect(multiworld, player, 'Castle Keep', 'Castle Basement', lambda state: not flooded.flood_basement or state.has('Water Mask', player))
|
||||||
connect(world, player, 'Castle Keep', 'Royal towers (lower)', lambda state: logic.has_doublejump(state) and (not options.royal_roadblock or logic.has_pink(state)))
|
connect(multiworld, player, 'Castle Keep', 'Royal towers (lower)', lambda state: logic.has_doublejump(state) and (not options.royal_roadblock or logic.has_pink(state)))
|
||||||
connect(world, player, 'Castle Keep', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Castle Keep', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Royal towers (lower)', 'Castle Keep')
|
connect(multiworld, player, 'Royal towers (lower)', 'Castle Keep')
|
||||||
connect(world, player, 'Royal towers (lower)', 'Royal towers', lambda state: state.has('Timespinner Wheel', player) or logic.has_forwarddash_doublejump(state))
|
connect(multiworld, player, 'Royal towers (lower)', 'Royal towers', lambda state: state.has('Timespinner Wheel', player) or logic.has_forwarddash_doublejump(state))
|
||||||
connect(world, player, 'Royal towers (lower)', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Royal towers (lower)', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Royal towers', 'Royal towers (lower)')
|
connect(multiworld, player, 'Royal towers', 'Royal towers (lower)')
|
||||||
connect(world, player, 'Royal towers', 'Royal towers (upper)', logic.has_doublejump)
|
connect(multiworld, player, 'Royal towers', 'Royal towers (upper)', logic.has_doublejump)
|
||||||
connect(world, player, 'Royal towers (upper)', 'Royal towers')
|
connect(multiworld, player, 'Royal towers (upper)', 'Royal towers')
|
||||||
#connect(world, player, 'Ancient Pyramid (entrance)', 'The lab (upper)', lambda state: not is_option_enabled(world, player, "EnterSandman"))
|
#connect(multiworld, player, 'Ancient Pyramid (entrance)', 'The lab (upper)', lambda state: not is_option_enabled(multiworld, player, "EnterSandman"))
|
||||||
connect(world, player, 'Ancient Pyramid (entrance)', 'Ancient Pyramid (left)', logic.has_doublejump)
|
connect(multiworld, player, 'Ancient Pyramid (entrance)', 'Ancient Pyramid (left)', logic.has_doublejump)
|
||||||
connect(world, player, 'Ancient Pyramid (entrance)', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Ancient Pyramid (entrance)', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Ancient Pyramid (left)', 'Ancient Pyramid (entrance)')
|
connect(multiworld, player, 'Ancient Pyramid (left)', 'Ancient Pyramid (entrance)')
|
||||||
connect(world, player, 'Ancient Pyramid (left)', 'Ancient Pyramid (right)', lambda state: flooded.flood_pyramid_shaft or logic.has_upwarddash(state))
|
connect(multiworld, player, 'Ancient Pyramid (left)', 'Ancient Pyramid (right)', lambda state: flooded.flood_pyramid_shaft or logic.has_upwarddash(state))
|
||||||
connect(world, player, 'Ancient Pyramid (left)', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Ancient Pyramid (left)', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Ancient Pyramid (right)', 'Ancient Pyramid (left)', lambda state: flooded.flood_pyramid_shaft or logic.has_upwarddash(state))
|
connect(multiworld, player, 'Ancient Pyramid (right)', 'Ancient Pyramid (left)', lambda state: flooded.flood_pyramid_shaft or logic.has_upwarddash(state))
|
||||||
connect(world, player, 'Ancient Pyramid (right)', 'Space time continuum', logic.has_teleport)
|
connect(multiworld, player, 'Ancient Pyramid (right)', 'Space time continuum', logic.has_teleport)
|
||||||
connect(world, player, 'Space time continuum', 'Lake desolation', lambda state: logic.can_teleport_to(state, "Present", "GateLakeDesolation"))
|
connect(multiworld, player, 'Space time continuum', 'Lake desolation', lambda state: logic.can_teleport_to(state, "Present", "GateLakeDesolation"))
|
||||||
connect(world, player, 'Space time continuum', 'Lower lake desolation', lambda state: logic.can_teleport_to(state, "Present", "GateKittyBoss"))
|
connect(multiworld, player, 'Space time continuum', 'Lower lake desolation', lambda state: logic.can_teleport_to(state, "Present", "GateKittyBoss"))
|
||||||
connect(world, player, 'Space time continuum', 'Library', lambda state: logic.can_teleport_to(state, "Present", "GateLeftLibrary"))
|
connect(multiworld, player, 'Space time continuum', 'Library', lambda state: logic.can_teleport_to(state, "Present", "GateLeftLibrary"))
|
||||||
connect(world, player, 'Space time continuum', 'Varndagroth tower right (lower)', lambda state: logic.can_teleport_to(state, "Present", "GateMilitaryGate"))
|
connect(multiworld, player, 'Space time continuum', 'Varndagroth tower right (lower)', lambda state: logic.can_teleport_to(state, "Present", "GateMilitaryGate"))
|
||||||
connect(world, player, 'Space time continuum', 'Skeleton Shaft', lambda state: logic.can_teleport_to(state, "Present", "GateSealedCaves"))
|
connect(multiworld, player, 'Space time continuum', 'Skeleton Shaft', lambda state: logic.can_teleport_to(state, "Present", "GateSealedCaves"))
|
||||||
connect(world, player, 'Space time continuum', 'Sealed Caves (Sirens)', lambda state: logic.can_teleport_to(state, "Present", "GateSealedSirensCave"))
|
connect(multiworld, player, 'Space time continuum', 'Sealed Caves (Sirens)', lambda state: logic.can_teleport_to(state, "Present", "GateSealedSirensCave"))
|
||||||
connect(world, player, 'Space time continuum', 'Sealed Caves (Xarion)', lambda state: logic.can_teleport_to(state, "Present", "GateXarion"))
|
connect(multiworld, player, 'Space time continuum', 'Sealed Caves (Xarion)', lambda state: logic.can_teleport_to(state, "Present", "GateXarion"))
|
||||||
connect(world, player, 'Space time continuum', 'Upper Lake Serene', lambda state: logic.can_teleport_to(state, "Past", "GateLakeSereneLeft"))
|
connect(multiworld, player, 'Space time continuum', 'Upper Lake Serene', lambda state: logic.can_teleport_to(state, "Past", "GateLakeSereneLeft"))
|
||||||
connect(world, player, 'Space time continuum', 'Left Side forest Caves', lambda state: logic.can_teleport_to(state, "Past", "GateLakeSereneRight"))
|
connect(multiworld, player, 'Space time continuum', 'Left Side forest Caves', lambda state: logic.can_teleport_to(state, "Past", "GateLakeSereneRight"))
|
||||||
connect(world, player, 'Space time continuum', 'Refugee Camp', lambda state: logic.can_teleport_to(state, "Past", "GateAccessToPast"))
|
connect(multiworld, player, 'Space time continuum', 'Refugee Camp', lambda state: logic.can_teleport_to(state, "Past", "GateAccessToPast"))
|
||||||
connect(world, player, 'Space time continuum', 'Forest', lambda state: logic.can_teleport_to(state, "Past", "GateCastleRamparts"))
|
connect(multiworld, player, 'Space time continuum', 'Forest', lambda state: logic.can_teleport_to(state, "Past", "GateCastleRamparts"))
|
||||||
connect(world, player, 'Space time continuum', 'Castle Keep', lambda state: logic.can_teleport_to(state, "Past", "GateCastleKeep"))
|
connect(multiworld, player, 'Space time continuum', 'Castle Keep', lambda state: logic.can_teleport_to(state, "Past", "GateCastleKeep"))
|
||||||
connect(world, player, 'Space time continuum', 'Royal towers (lower)', lambda state: logic.can_teleport_to(state, "Past", "GateRoyalTowers"))
|
connect(multiworld, player, 'Space time continuum', 'Royal towers (lower)', lambda state: logic.can_teleport_to(state, "Past", "GateRoyalTowers"))
|
||||||
connect(world, player, 'Space time continuum', 'Caves of Banishment (Maw)', lambda state: logic.can_teleport_to(state, "Past", "GateMaw"))
|
connect(multiworld, player, 'Space time continuum', 'Caves of Banishment (Maw)', lambda state: logic.can_teleport_to(state, "Past", "GateMaw"))
|
||||||
connect(world, player, 'Space time continuum', 'Caves of Banishment (upper)', lambda state: logic.can_teleport_to(state, "Past", "GateCavesOfBanishment"))
|
connect(multiworld, player, 'Space time continuum', 'Caves of Banishment (upper)', lambda state: logic.can_teleport_to(state, "Past", "GateCavesOfBanishment"))
|
||||||
connect(world, player, 'Space time continuum', 'Military Fortress (hangar)', lambda state: logic.can_teleport_to(state, "Present", "GateLabEntrance"))
|
connect(multiworld, player, 'Space time continuum', 'Military Fortress (hangar)', lambda state: logic.can_teleport_to(state, "Present", "GateLabEntrance"))
|
||||||
connect(world, player, 'Space time continuum', 'The lab (upper)', lambda state: logic.can_teleport_to(state, "Present", "GateDadsTower"))
|
connect(multiworld, player, 'Space time continuum', 'The lab (upper)', lambda state: logic.can_teleport_to(state, "Present", "GateDadsTower"))
|
||||||
connect(world, player, 'Space time continuum', 'Ancient Pyramid (entrance)', lambda state: logic.can_teleport_to(state, "Time", "GateGyre") or logic.can_teleport_to(state, "Time", "GateLeftPyramid") or (not options.unchained_keys and options.enter_sandman))
|
connect(multiworld, player, 'Space time continuum', 'Ancient Pyramid (entrance)', lambda state: logic.can_teleport_to(state, "Time", "GateGyre") or logic.can_teleport_to(state, "Time", "GateLeftPyramid") or (not options.unchained_keys and options.enter_sandman))
|
||||||
connect(world, player, 'Space time continuum', 'Ancient Pyramid (right)', lambda state: logic.can_teleport_to(state, "Time", "GateRightPyramid"))
|
connect(multiworld, player, 'Space time continuum', 'Ancient Pyramid (right)', lambda state: logic.can_teleport_to(state, "Time", "GateRightPyramid"))
|
||||||
|
|
||||||
if options.gyre_archives:
|
if options.gyre_archives:
|
||||||
connect(world, player, 'The lab (upper)', 'Ravenlord\'s Lair', lambda state: state.has('Merchant Crow', player))
|
connect(multiworld, player, 'The lab (upper)', 'Ravenlord\'s Lair', lambda state: state.has('Merchant Crow', player))
|
||||||
connect(world, player, 'Ravenlord\'s Lair', 'The lab (upper)')
|
connect(multiworld, player, 'Ravenlord\'s Lair', 'The lab (upper)')
|
||||||
connect(world, player, 'Library top', 'Ifrit\'s Lair', lambda state: state.has('Kobo', player) and state.can_reach('Refugee Camp', 'Region', player), "Refugee Camp")
|
connect(multiworld, player, 'Library top', 'Ifrit\'s Lair', lambda state: state.has('Kobo', player) and state.can_reach('Refugee Camp', 'Region', player), "Refugee Camp")
|
||||||
connect(world, player, 'Ifrit\'s Lair', 'Library top')
|
connect(multiworld, player, 'Ifrit\'s Lair', 'Library top')
|
||||||
|
|
||||||
|
|
||||||
def throwIfAnyLocationIsNotAssignedToARegion(regions: List[Region], regionNames: Set[str]):
|
def throwIfAnyLocationIsNotAssignedToARegion(regions: List[Region], regionNames: Set[str]):
|
||||||
@@ -223,8 +223,8 @@ def create_location(player: int, location_data: LocationData, region: Region) ->
|
|||||||
return location
|
return location
|
||||||
|
|
||||||
|
|
||||||
def create_region(world: MultiWorld, player: int, locations_per_region: Dict[str, List[LocationData]], name: str) -> Region:
|
def create_region(multiworld: MultiWorld, player: int, locations_per_region: Dict[str, List[LocationData]], name: str) -> Region:
|
||||||
region = Region(name, player, world)
|
region = Region(name, player, multiworld)
|
||||||
|
|
||||||
if name in locations_per_region:
|
if name in locations_per_region:
|
||||||
for location_data in locations_per_region[name]:
|
for location_data in locations_per_region[name]:
|
||||||
@@ -233,17 +233,17 @@ def create_region(world: MultiWorld, player: int, locations_per_region: Dict[str
|
|||||||
return region
|
return region
|
||||||
|
|
||||||
|
|
||||||
def connectStartingRegion(world: MultiWorld, player: int, options: TimespinnerOptions):
|
def connectStartingRegion(multiworld: MultiWorld, player: int, options: TimespinnerOptions):
|
||||||
menu = world.get_region('Menu', player)
|
menu = multiworld.get_region('Menu', player)
|
||||||
tutorial = world.get_region('Tutorial', player)
|
tutorial = multiworld.get_region('Tutorial', player)
|
||||||
space_time_continuum = world.get_region('Space time continuum', player)
|
space_time_continuum = multiworld.get_region('Space time continuum', player)
|
||||||
|
|
||||||
if options.pyramid_start:
|
if options.pyramid_start:
|
||||||
starting_region = world.get_region('Ancient Pyramid (entrance)', player)
|
starting_region = multiworld.get_region('Ancient Pyramid (entrance)', player)
|
||||||
elif options.inverted:
|
elif options.inverted:
|
||||||
starting_region = world.get_region('Refugee Camp', player)
|
starting_region = multiworld.get_region('Refugee Camp', player)
|
||||||
else:
|
else:
|
||||||
starting_region = world.get_region('Lake desolation', player)
|
starting_region = multiworld.get_region('Lake desolation', player)
|
||||||
|
|
||||||
menu_to_tutorial = Entrance(player, 'Tutorial', menu)
|
menu_to_tutorial = Entrance(player, 'Tutorial', menu)
|
||||||
menu_to_tutorial.connect(tutorial)
|
menu_to_tutorial.connect(tutorial)
|
||||||
@@ -256,20 +256,20 @@ def connectStartingRegion(world: MultiWorld, player: int, options: TimespinnerOp
|
|||||||
space_time_continuum.exits.append(teleport_back_to_start)
|
space_time_continuum.exits.append(teleport_back_to_start)
|
||||||
|
|
||||||
|
|
||||||
def connect(world: MultiWorld, player: int, source: str, target: str,
|
def connect(multiworld: MultiWorld, player: int, source: str, target: str,
|
||||||
rule: Optional[Callable[[CollectionState], bool]] = None,
|
rule: Optional[Callable[[CollectionState], bool]] = None,
|
||||||
indirect: str = ""):
|
indirect: str = ""):
|
||||||
|
|
||||||
sourceRegion = world.get_region(source, player)
|
sourceRegion = multiworld.get_region(source, player)
|
||||||
targetRegion = world.get_region(target, player)
|
targetRegion = multiworld.get_region(target, player)
|
||||||
entrance = sourceRegion.connect(targetRegion, rule=rule)
|
entrance = sourceRegion.connect(targetRegion, rule=rule)
|
||||||
|
|
||||||
if indirect:
|
if indirect:
|
||||||
indirectRegion = world.get_region(indirect, player)
|
indirectRegion = multiworld.get_region(indirect, player)
|
||||||
if indirectRegion in world.indirect_connections:
|
if indirectRegion in multiworld.indirect_connections:
|
||||||
world.indirect_connections[indirectRegion].add(entrance)
|
multiworld.indirect_connections[indirectRegion].add(entrance)
|
||||||
else:
|
else:
|
||||||
world.indirect_connections[indirectRegion] = {entrance}
|
multiworld.indirect_connections[indirectRegion] = {entrance}
|
||||||
|
|
||||||
|
|
||||||
def split_location_datas_per_region(locations: List[LocationData]) -> Dict[str, List[LocationData]]:
|
def split_location_datas_per_region(locations: List[LocationData]) -> Dict[str, List[LocationData]]:
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
from BaseClasses import MultiWorld
|
from BaseClasses import MultiWorld
|
||||||
|
|
||||||
|
|
||||||
def link_undertale_areas(world: MultiWorld, player: int):
|
def link_undertale_areas(multiworld: MultiWorld, player: int):
|
||||||
for (exit, region) in mandatory_connections:
|
for (exit, region) in mandatory_connections:
|
||||||
world.get_entrance(exit, player).connect(world.get_region(region, player))
|
multiworld.get_entrance(exit, player).connect(multiworld.get_region(region, player))
|
||||||
|
|
||||||
|
|
||||||
# (Region name, list of exits)
|
# (Region name, list of exits)
|
||||||
|
|||||||
+11
-11
@@ -5,29 +5,29 @@ from .Locations import V6Location, location_table
|
|||||||
v6areas = ["Laboratory", "The Tower", "Space Station 2", "Warp Zone"]
|
v6areas = ["Laboratory", "The Tower", "Space Station 2", "Warp Zone"]
|
||||||
|
|
||||||
|
|
||||||
def create_regions(world: MultiWorld, player: int):
|
def create_regions(multiworld: MultiWorld, player: int):
|
||||||
regOvr = Region("Menu", player, world, "Dimension VVVVVV")
|
regOvr = Region("Menu", player, multiworld, "Dimension VVVVVV")
|
||||||
locOvr_names = ["Overworld (Pipe-shaped Segment)", "Overworld (Left of Ship)", "Overworld (Square Room)", "Overworld (Sad Elephant)",
|
locOvr_names = ["Overworld (Pipe-shaped Segment)", "Overworld (Left of Ship)", "Overworld (Square Room)", "Overworld (Sad Elephant)",
|
||||||
"It's a Secret to Nobody", "Trench Warfare", "NPC Trinket", "V"]
|
"It's a Secret to Nobody", "Trench Warfare", "NPC Trinket", "V"]
|
||||||
regOvr.locations += [V6Location(player, loc_name, location_table[loc_name], regOvr) for loc_name in locOvr_names]
|
regOvr.locations += [V6Location(player, loc_name, location_table[loc_name], regOvr) for loc_name in locOvr_names]
|
||||||
world.regions.append(regOvr)
|
multiworld.regions.append(regOvr)
|
||||||
|
|
||||||
regLab = Region("Laboratory", player, world)
|
regLab = Region("Laboratory", player, multiworld)
|
||||||
locLab_names = ["Young Man, It's Worth the Challenge", "Overworld (Outside Entanglement Generator)", "The Tantalizing Trinket", "Purest Unobtainium"]
|
locLab_names = ["Young Man, It's Worth the Challenge", "Overworld (Outside Entanglement Generator)", "The Tantalizing Trinket", "Purest Unobtainium"]
|
||||||
regLab.locations += [V6Location(player, loc_name, location_table[loc_name], regLab) for loc_name in locLab_names]
|
regLab.locations += [V6Location(player, loc_name, location_table[loc_name], regLab) for loc_name in locLab_names]
|
||||||
world.regions.append(regLab)
|
multiworld.regions.append(regLab)
|
||||||
|
|
||||||
regTow = Region("The Tower", player, world)
|
regTow = Region("The Tower", player, multiworld)
|
||||||
locTow_names = ["The Tower 1", "The Tower 2"]
|
locTow_names = ["The Tower 1", "The Tower 2"]
|
||||||
regTow.locations += [V6Location(player, loc_name, location_table[loc_name], regTow) for loc_name in locTow_names]
|
regTow.locations += [V6Location(player, loc_name, location_table[loc_name], regTow) for loc_name in locTow_names]
|
||||||
world.regions.append(regTow)
|
multiworld.regions.append(regTow)
|
||||||
|
|
||||||
regSp2 = Region("Space Station 2", player, world)
|
regSp2 = Region("Space Station 2", player, multiworld)
|
||||||
locSp2_names = ["One Way Room", "You Just Keep Coming Back", "Clarion Call", "Prize for the Reckless", "Doing things the hard way"]
|
locSp2_names = ["One Way Room", "You Just Keep Coming Back", "Clarion Call", "Prize for the Reckless", "Doing things the hard way"]
|
||||||
regSp2.locations += [V6Location(player, loc_name, location_table[loc_name], regSp2) for loc_name in locSp2_names]
|
regSp2.locations += [V6Location(player, loc_name, location_table[loc_name], regSp2) for loc_name in locSp2_names]
|
||||||
world.regions.append(regSp2)
|
multiworld.regions.append(regSp2)
|
||||||
|
|
||||||
regWrp = Region("Warp Zone", player, world)
|
regWrp = Region("Warp Zone", player, multiworld)
|
||||||
locWrp_names = ["Edge Games"]
|
locWrp_names = ["Edge Games"]
|
||||||
regWrp.locations += [V6Location(player, loc_name, location_table[loc_name], regWrp) for loc_name in locWrp_names]
|
regWrp.locations += [V6Location(player, loc_name, location_table[loc_name], regWrp) for loc_name in locWrp_names]
|
||||||
world.regions.append(regWrp)
|
multiworld.regions.append(regWrp)
|
||||||
|
|||||||
+65
-65
@@ -16,139 +16,139 @@ class WargrooveLogic(LogicMixin):
|
|||||||
return self.can_reach(region, 'Region', player) and self.has(item, player)
|
return self.can_reach(region, 'Region', player) and self.has(item, player)
|
||||||
|
|
||||||
|
|
||||||
def set_rules(world: MultiWorld, player: int):
|
def set_rules(multiworld: MultiWorld, player: int):
|
||||||
# Final Level
|
# Final Level
|
||||||
set_rule(world.get_location('Wargroove Finale: Victory', player),
|
set_rule(multiworld.get_location('Wargroove Finale: Victory', player),
|
||||||
lambda state: state._wargroove_has_item(player, "Final Bridges") and
|
lambda state: state._wargroove_has_item(player, "Final Bridges") and
|
||||||
state._wargroove_has_item(player, "Final Walls") and
|
state._wargroove_has_item(player, "Final Walls") and
|
||||||
state._wargroove_has_item(player, "Final Sickle"))
|
state._wargroove_has_item(player, "Final Sickle"))
|
||||||
# Level 1
|
# Level 1
|
||||||
set_rule(world.get_location('Humble Beginnings: Caesar', player), lambda state: True)
|
set_rule(multiworld.get_location('Humble Beginnings: Caesar', player), lambda state: True)
|
||||||
set_rule(world.get_location('Humble Beginnings: Chest 1', player), lambda state: True)
|
set_rule(multiworld.get_location('Humble Beginnings: Chest 1', player), lambda state: True)
|
||||||
set_rule(world.get_location('Humble Beginnings: Chest 2', player), lambda state: True)
|
set_rule(multiworld.get_location('Humble Beginnings: Chest 2', player), lambda state: True)
|
||||||
set_rule(world.get_location('Humble Beginnings: Victory', player), lambda state: True)
|
set_rule(multiworld.get_location('Humble Beginnings: Victory', player), lambda state: True)
|
||||||
set_region_exit_rules(world.get_region('Humble Beginnings', player),
|
set_region_exit_rules(multiworld.get_region('Humble Beginnings', player),
|
||||||
[world.get_location('Humble Beginnings: Victory', player)])
|
[multiworld.get_location('Humble Beginnings: Victory', player)])
|
||||||
|
|
||||||
# Levels 2A-2C
|
# Levels 2A-2C
|
||||||
set_rule(world.get_location('Best Friendssss: Find Sedge', player), lambda state: True)
|
set_rule(multiworld.get_location('Best Friendssss: Find Sedge', player), lambda state: True)
|
||||||
set_rule(world.get_location('Best Friendssss: Victory', player), lambda state: True)
|
set_rule(multiworld.get_location('Best Friendssss: Victory', player), lambda state: True)
|
||||||
set_region_exit_rules(world.get_region('Best Friendssss', player),
|
set_region_exit_rules(multiworld.get_region('Best Friendssss', player),
|
||||||
[world.get_location('Best Friendssss: Victory', player)])
|
[multiworld.get_location('Best Friendssss: Victory', player)])
|
||||||
|
|
||||||
set_rule(world.get_location('A Knight\'s Folly: Caesar', player), lambda state: True)
|
set_rule(multiworld.get_location('A Knight\'s Folly: Caesar', player), lambda state: True)
|
||||||
set_rule(world.get_location('A Knight\'s Folly: Victory', player), lambda state: True)
|
set_rule(multiworld.get_location('A Knight\'s Folly: Victory', player), lambda state: True)
|
||||||
set_region_exit_rules(world.get_region('A Knight\'s Folly', player),
|
set_region_exit_rules(multiworld.get_region('A Knight\'s Folly', player),
|
||||||
[world.get_location('A Knight\'s Folly: Victory', player)])
|
[multiworld.get_location('A Knight\'s Folly: Victory', player)])
|
||||||
|
|
||||||
set_rule(world.get_location('Denrunaway: Chest', player), lambda state: True)
|
set_rule(multiworld.get_location('Denrunaway: Chest', player), lambda state: True)
|
||||||
set_rule(world.get_location('Denrunaway: Victory', player), lambda state: True)
|
set_rule(multiworld.get_location('Denrunaway: Victory', player), lambda state: True)
|
||||||
set_region_exit_rules(world.get_region('Denrunaway', player), [world.get_location('Denrunaway: Victory', player)])
|
set_region_exit_rules(multiworld.get_region('Denrunaway', player), [multiworld.get_location('Denrunaway: Victory', player)])
|
||||||
|
|
||||||
# Levels 3AA-3AC
|
# Levels 3AA-3AC
|
||||||
set_rule(world.get_location('Dragon Freeway: Victory', player),
|
set_rule(multiworld.get_location('Dragon Freeway: Victory', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Mage'))
|
lambda state: state._wargroove_has_item(player, 'Mage'))
|
||||||
set_region_exit_rules(world.get_region('Dragon Freeway', player),
|
set_region_exit_rules(multiworld.get_region('Dragon Freeway', player),
|
||||||
[world.get_location('Dragon Freeway: Victory', player)])
|
[multiworld.get_location('Dragon Freeway: Victory', player)])
|
||||||
|
|
||||||
set_rule(world.get_location('Deep Thicket: Find Sedge', player),
|
set_rule(multiworld.get_location('Deep Thicket: Find Sedge', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Mage'))
|
lambda state: state._wargroove_has_item(player, 'Mage'))
|
||||||
set_rule(world.get_location('Deep Thicket: Victory', player),
|
set_rule(multiworld.get_location('Deep Thicket: Victory', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Mage'))
|
lambda state: state._wargroove_has_item(player, 'Mage'))
|
||||||
set_region_exit_rules(world.get_region('Deep Thicket', player),
|
set_region_exit_rules(multiworld.get_region('Deep Thicket', player),
|
||||||
[world.get_location('Deep Thicket: Victory', player)])
|
[multiworld.get_location('Deep Thicket: Victory', player)])
|
||||||
|
|
||||||
set_rule(world.get_location('Corrupted Inlet: Victory', player),
|
set_rule(multiworld.get_location('Corrupted Inlet: Victory', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Barge') or
|
lambda state: state._wargroove_has_item(player, 'Barge') or
|
||||||
state._wargroove_has_item(player, 'Merfolk') or
|
state._wargroove_has_item(player, 'Merfolk') or
|
||||||
state._wargroove_has_item(player, 'Warship'))
|
state._wargroove_has_item(player, 'Warship'))
|
||||||
set_region_exit_rules(world.get_region('Corrupted Inlet', player),
|
set_region_exit_rules(multiworld.get_region('Corrupted Inlet', player),
|
||||||
[world.get_location('Corrupted Inlet: Victory', player)])
|
[multiworld.get_location('Corrupted Inlet: Victory', player)])
|
||||||
|
|
||||||
# Levels 3BA-3BC
|
# Levels 3BA-3BC
|
||||||
set_rule(world.get_location('Mage Mayhem: Caesar', player),
|
set_rule(multiworld.get_location('Mage Mayhem: Caesar', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Harpy') or state._wargroove_has_item(player, 'Dragon'))
|
lambda state: state._wargroove_has_item(player, 'Harpy') or state._wargroove_has_item(player, 'Dragon'))
|
||||||
set_rule(world.get_location('Mage Mayhem: Victory', player),
|
set_rule(multiworld.get_location('Mage Mayhem: Victory', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Harpy') or state._wargroove_has_item(player, 'Dragon'))
|
lambda state: state._wargroove_has_item(player, 'Harpy') or state._wargroove_has_item(player, 'Dragon'))
|
||||||
set_region_exit_rules(world.get_region('Mage Mayhem', player), [world.get_location('Mage Mayhem: Victory', player)])
|
set_region_exit_rules(multiworld.get_region('Mage Mayhem', player), [multiworld.get_location('Mage Mayhem: Victory', player)])
|
||||||
|
|
||||||
set_rule(world.get_location('Endless Knight: Victory', player),
|
set_rule(multiworld.get_location('Endless Knight: Victory', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Eastern Bridges') and (
|
lambda state: state._wargroove_has_item(player, 'Eastern Bridges') and (
|
||||||
state._wargroove_has_item(player, 'Spearman') or
|
state._wargroove_has_item(player, 'Spearman') or
|
||||||
state._wargroove_has_item(player, 'Harpy') or
|
state._wargroove_has_item(player, 'Harpy') or
|
||||||
state._wargroove_has_item(player, 'Dragon')))
|
state._wargroove_has_item(player, 'Dragon')))
|
||||||
set_region_exit_rules(world.get_region('Endless Knight', player),
|
set_region_exit_rules(multiworld.get_region('Endless Knight', player),
|
||||||
[world.get_location('Endless Knight: Victory', player)])
|
[multiworld.get_location('Endless Knight: Victory', player)])
|
||||||
|
|
||||||
set_rule(world.get_location('Ambushed in the Middle: Victory (Blue)', player),
|
set_rule(multiworld.get_location('Ambushed in the Middle: Victory (Blue)', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Spearman'))
|
lambda state: state._wargroove_has_item(player, 'Spearman'))
|
||||||
set_rule(world.get_location('Ambushed in the Middle: Victory (Green)', player),
|
set_rule(multiworld.get_location('Ambushed in the Middle: Victory (Green)', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Spearman'))
|
lambda state: state._wargroove_has_item(player, 'Spearman'))
|
||||||
set_region_exit_rules(world.get_region('Ambushed in the Middle', player),
|
set_region_exit_rules(multiworld.get_region('Ambushed in the Middle', player),
|
||||||
[world.get_location('Ambushed in the Middle: Victory (Blue)', player),
|
[multiworld.get_location('Ambushed in the Middle: Victory (Blue)', player),
|
||||||
world.get_location('Ambushed in the Middle: Victory (Green)', player)])
|
multiworld.get_location('Ambushed in the Middle: Victory (Green)', player)])
|
||||||
|
|
||||||
# Levels 3CA-3CC
|
# Levels 3CA-3CC
|
||||||
set_rule(world.get_location('The Churning Sea: Victory', player),
|
set_rule(multiworld.get_location('The Churning Sea: Victory', player),
|
||||||
lambda state: (state._wargroove_has_item(player, 'Merfolk') or state._wargroove_has_item(player, 'Turtle'))
|
lambda state: (state._wargroove_has_item(player, 'Merfolk') or state._wargroove_has_item(player, 'Turtle'))
|
||||||
and state._wargroove_has_item(player, 'Harpoon Ship'))
|
and state._wargroove_has_item(player, 'Harpoon Ship'))
|
||||||
set_region_exit_rules(world.get_region('The Churning Sea', player),
|
set_region_exit_rules(multiworld.get_region('The Churning Sea', player),
|
||||||
[world.get_location('The Churning Sea: Victory', player)])
|
[multiworld.get_location('The Churning Sea: Victory', player)])
|
||||||
|
|
||||||
set_rule(world.get_location('Frigid Archery: Light the Torch', player),
|
set_rule(multiworld.get_location('Frigid Archery: Light the Torch', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Archer') and
|
lambda state: state._wargroove_has_item(player, 'Archer') and
|
||||||
state._wargroove_has_item(player, 'Southern Walls'))
|
state._wargroove_has_item(player, 'Southern Walls'))
|
||||||
set_rule(world.get_location('Frigid Archery: Victory', player),
|
set_rule(multiworld.get_location('Frigid Archery: Victory', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Archer'))
|
lambda state: state._wargroove_has_item(player, 'Archer'))
|
||||||
set_region_exit_rules(world.get_region('Frigid Archery', player),
|
set_region_exit_rules(multiworld.get_region('Frigid Archery', player),
|
||||||
[world.get_location('Frigid Archery: Victory', player)])
|
[multiworld.get_location('Frigid Archery: Victory', player)])
|
||||||
|
|
||||||
set_rule(world.get_location('Archery Lessons: Chest', player),
|
set_rule(multiworld.get_location('Archery Lessons: Chest', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Knight') and
|
lambda state: state._wargroove_has_item(player, 'Knight') and
|
||||||
state._wargroove_has_item(player, 'Southern Walls'))
|
state._wargroove_has_item(player, 'Southern Walls'))
|
||||||
set_rule(world.get_location('Archery Lessons: Victory', player),
|
set_rule(multiworld.get_location('Archery Lessons: Victory', player),
|
||||||
lambda state: state._wargroove_has_item(player, 'Knight') and
|
lambda state: state._wargroove_has_item(player, 'Knight') and
|
||||||
state._wargroove_has_item(player, 'Southern Walls'))
|
state._wargroove_has_item(player, 'Southern Walls'))
|
||||||
set_region_exit_rules(world.get_region('Archery Lessons', player),
|
set_region_exit_rules(multiworld.get_region('Archery Lessons', player),
|
||||||
[world.get_location('Archery Lessons: Victory', player)])
|
[multiworld.get_location('Archery Lessons: Victory', player)])
|
||||||
|
|
||||||
# Levels 4AA-4AC
|
# Levels 4AA-4AC
|
||||||
set_rule(world.get_location('Surrounded: Caesar', player),
|
set_rule(multiworld.get_location('Surrounded: Caesar', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Knight', 'Surrounded'))
|
lambda state: state._wargroove_has_item_and_region(player, 'Knight', 'Surrounded'))
|
||||||
set_rule(world.get_location('Surrounded: Victory', player),
|
set_rule(multiworld.get_location('Surrounded: Victory', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Knight', 'Surrounded'))
|
lambda state: state._wargroove_has_item_and_region(player, 'Knight', 'Surrounded'))
|
||||||
set_rule(world.get_location('Darkest Knight: Victory', player),
|
set_rule(multiworld.get_location('Darkest Knight: Victory', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Spearman', 'Darkest Knight'))
|
lambda state: state._wargroove_has_item_and_region(player, 'Spearman', 'Darkest Knight'))
|
||||||
set_rule(world.get_location('Robbed: Victory', player),
|
set_rule(multiworld.get_location('Robbed: Victory', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Thief', 'Robbed') and
|
lambda state: state._wargroove_has_item_and_region(player, 'Thief', 'Robbed') and
|
||||||
state._wargroove_has_item(player, 'Rifleman'))
|
state._wargroove_has_item(player, 'Rifleman'))
|
||||||
|
|
||||||
# Levels 4BA-4BC
|
# Levels 4BA-4BC
|
||||||
set_rule(world.get_location('Open Season: Caesar', player),
|
set_rule(multiworld.get_location('Open Season: Caesar', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Mage', 'Open Season') and
|
lambda state: state._wargroove_has_item_and_region(player, 'Mage', 'Open Season') and
|
||||||
state._wargroove_has_item(player, 'Knight'))
|
state._wargroove_has_item(player, 'Knight'))
|
||||||
set_rule(world.get_location('Open Season: Victory', player),
|
set_rule(multiworld.get_location('Open Season: Victory', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Mage', 'Open Season') and
|
lambda state: state._wargroove_has_item_and_region(player, 'Mage', 'Open Season') and
|
||||||
state._wargroove_has_item(player, 'Knight'))
|
state._wargroove_has_item(player, 'Knight'))
|
||||||
set_rule(world.get_location('Doggo Mountain: Find all the Dogs', player),
|
set_rule(multiworld.get_location('Doggo Mountain: Find all the Dogs', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Knight', 'Doggo Mountain'))
|
lambda state: state._wargroove_has_item_and_region(player, 'Knight', 'Doggo Mountain'))
|
||||||
set_rule(world.get_location('Doggo Mountain: Victory', player),
|
set_rule(multiworld.get_location('Doggo Mountain: Victory', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Knight', 'Doggo Mountain'))
|
lambda state: state._wargroove_has_item_and_region(player, 'Knight', 'Doggo Mountain'))
|
||||||
set_rule(world.get_location('Tenri\'s Fall: Victory', player),
|
set_rule(multiworld.get_location('Tenri\'s Fall: Victory', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Mage', 'Tenri\'s Fall') and
|
lambda state: state._wargroove_has_item_and_region(player, 'Mage', 'Tenri\'s Fall') and
|
||||||
state._wargroove_has_item(player, 'Thief'))
|
state._wargroove_has_item(player, 'Thief'))
|
||||||
set_rule(world.get_location('Foolish Canal: Victory', player),
|
set_rule(multiworld.get_location('Foolish Canal: Victory', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Mage', 'Foolish Canal') and
|
lambda state: state._wargroove_has_item_and_region(player, 'Mage', 'Foolish Canal') and
|
||||||
state._wargroove_has_item(player, 'Spearman'))
|
state._wargroove_has_item(player, 'Spearman'))
|
||||||
|
|
||||||
# Levels 4CA-4CC
|
# Levels 4CA-4CC
|
||||||
set_rule(world.get_location('Master of the Lake: Victory', player),
|
set_rule(multiworld.get_location('Master of the Lake: Victory', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Warship', 'Master of the Lake'))
|
lambda state: state._wargroove_has_item_and_region(player, 'Warship', 'Master of the Lake'))
|
||||||
set_rule(world.get_location('A Ballista\'s Revenge: Victory', player),
|
set_rule(multiworld.get_location('A Ballista\'s Revenge: Victory', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Ballista', 'A Ballista\'s Revenge'))
|
lambda state: state._wargroove_has_item_and_region(player, 'Ballista', 'A Ballista\'s Revenge'))
|
||||||
set_rule(world.get_location('Rebel Village: Victory (Pink)', player),
|
set_rule(multiworld.get_location('Rebel Village: Victory (Pink)', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Spearman', 'Rebel Village'))
|
lambda state: state._wargroove_has_item_and_region(player, 'Spearman', 'Rebel Village'))
|
||||||
set_rule(world.get_location('Rebel Village: Victory (Red)', player),
|
set_rule(multiworld.get_location('Rebel Village: Victory (Red)', player),
|
||||||
lambda state: state._wargroove_has_item_and_region(player, 'Spearman', 'Rebel Village'))
|
lambda state: state._wargroove_has_item_and_region(player, 'Spearman', 'Rebel Village'))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -143,8 +143,8 @@ class WargrooveWorld(World):
|
|||||||
return self.multiworld.random.choice(["Commander Defense Boost", "Income Boost"])
|
return self.multiworld.random.choice(["Commander Defense Boost", "Income Boost"])
|
||||||
|
|
||||||
|
|
||||||
def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None):
|
def create_region(multiworld: MultiWorld, player: int, name: str, locations=None, exits=None):
|
||||||
ret = Region(name, player, world)
|
ret = Region(name, player, multiworld)
|
||||||
if locations:
|
if locations:
|
||||||
for location in locations:
|
for location in locations:
|
||||||
loc_id = location_table.get(location, 0)
|
loc_id = location_table.get(location, 0)
|
||||||
|
|||||||
@@ -218,12 +218,12 @@ def dice_simulation_state_change(state, player, frags_per_dice, frags_per_roll,
|
|||||||
return state.prog_items[player]["maximum_achievable_score"]
|
return state.prog_items[player]["maximum_achievable_score"]
|
||||||
|
|
||||||
|
|
||||||
def set_yacht_rules(world: MultiWorld, player: int, frags_per_dice, frags_per_roll, allowed_categories, difficulty):
|
def set_yacht_rules(multiworld: MultiWorld, player: int, frags_per_dice, frags_per_roll, allowed_categories, difficulty):
|
||||||
"""
|
"""
|
||||||
Sets rules on reaching scores
|
Sets rules on reaching scores
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for location in world.get_locations(player):
|
for location in multiworld.get_locations(player):
|
||||||
set_rule(
|
set_rule(
|
||||||
location,
|
location,
|
||||||
lambda state, curscore=location.yacht_dice_score, player=player: dice_simulation_state_change(
|
lambda state, curscore=location.yacht_dice_score, player=player: dice_simulation_state_change(
|
||||||
@@ -233,8 +233,8 @@ def set_yacht_rules(world: MultiWorld, player: int, frags_per_dice, frags_per_ro
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def set_yacht_completion_rules(world: MultiWorld, player: int):
|
def set_yacht_completion_rules(multiworld: MultiWorld, player: int):
|
||||||
"""
|
"""
|
||||||
Sets rules on completion condition
|
Sets rules on completion condition
|
||||||
"""
|
"""
|
||||||
world.completion_condition[player] = lambda state: state.has("Victory", player)
|
multiworld.completion_condition[player] = lambda state: state.has("Victory", player)
|
||||||
|
|||||||
@@ -341,7 +341,6 @@ class YoshisIslandWorld(World):
|
|||||||
def generate_output(self, output_directory: str) -> None:
|
def generate_output(self, output_directory: str) -> None:
|
||||||
rompath = "" # if variable is not declared finally clause may fail
|
rompath = "" # if variable is not declared finally clause may fail
|
||||||
try:
|
try:
|
||||||
world = self.multiworld
|
|
||||||
player = self.player
|
player = self.player
|
||||||
rom = LocalRom(get_base_rom_path())
|
rom = LocalRom(get_base_rom_path())
|
||||||
patch_rom(self, rom, self.player)
|
patch_rom(self, rom, self.player)
|
||||||
@@ -351,7 +350,7 @@ class YoshisIslandWorld(World):
|
|||||||
self.rom_name = rom.name
|
self.rom_name = rom.name
|
||||||
|
|
||||||
patch = YoshisIslandDeltaPatch(os.path.splitext(rompath)[0] + YoshisIslandDeltaPatch.patch_file_ending,
|
patch = YoshisIslandDeltaPatch(os.path.splitext(rompath)[0] + YoshisIslandDeltaPatch.patch_file_ending,
|
||||||
player=player, player_name=world.player_name[player], patched_path=rompath)
|
player=player, player_name=self.player_name, patched_path=rompath)
|
||||||
patch.write()
|
patch.write()
|
||||||
finally:
|
finally:
|
||||||
self.rom_name_available_event.set()
|
self.rom_name_available_event.set()
|
||||||
|
|||||||
@@ -130,8 +130,8 @@ class Yugioh06World(World):
|
|||||||
campaign_opponents: List[OpponentData]
|
campaign_opponents: List[OpponentData]
|
||||||
is_draft_mode: bool
|
is_draft_mode: bool
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int):
|
def __init__(self, multiworld: MultiWorld, player: int):
|
||||||
super().__init__(world, player)
|
super().__init__(multiworld, player)
|
||||||
|
|
||||||
def generate_early(self):
|
def generate_early(self):
|
||||||
self.starting_opponent = ""
|
self.starting_opponent = ""
|
||||||
|
|||||||
@@ -128,8 +128,8 @@ class ZillionWorld(World):
|
|||||||
"""
|
"""
|
||||||
logic_cache: ZillionLogicCache | None = None
|
logic_cache: ZillionLogicCache | None = None
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int) -> None:
|
def __init__(self, multiworld: MultiWorld, player: int) -> None:
|
||||||
super().__init__(world, player)
|
super().__init__(multiworld, player)
|
||||||
self.logger = logging.getLogger("Zillion")
|
self.logger = logging.getLogger("Zillion")
|
||||||
self.lsi = ZillionWorld.LogStreamInterface(self.logger)
|
self.lsi = ZillionWorld.LogStreamInterface(self.logger)
|
||||||
self.zz_system = System()
|
self.zz_system = System()
|
||||||
|
|||||||
Reference in New Issue
Block a user