Merge remote-tracking branch 'Archipelago/main' into Archipelago_Main

This commit is contained in:
Fabian Dill 2021-10-18 22:58:45 +02:00
commit f8569db21b
8 changed files with 292 additions and 158 deletions

View File

@ -0,0 +1,25 @@
# Super Metroid
## Where is the settings page?
The player settings page for this game is located <a href="../player-settings">here</a>. It 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 items and locations get shuffled?
All power-ups and ammunition can be shuffled, and all locations in the game which could contain any of those items
may have their contents changed.
## Which items can be in another player's world?
Any of the items which can be shuffled may also be placed into another player's world. It is possible to choose to
limit certain items to your own world.
## What does another world's item look like in Super Metroid?
A unique item sprite has been added to the game to represent items belonging to another world.
## When the player receives an item, what happens?
When the player receives an item, a text box will appear to show which item was received, and from whom.

View File

@ -0,0 +1,126 @@
# Super Metroid Setup Guide
## Required Software
- [Super Metroid Client](https://github.com/ArchipelagoMW/SuperMetroidClient/releases)
- **sniConnector.lua** (located on the client download page)
- [SNI](https://github.com/alttpo/sni/releases) (Included in the Super Metroid Client)
- Hardware or software capable of loading and playing SNES ROM files
- An emulator capable of connecting to SNI
([snes9x Multitroid](https://drive.google.com/drive/folders/1_ej-pwWtCAHYXIrvs5Hro16A1s9Hi3Jz),
[BizHawk](http://tasvideos.org/BizHawk.html))
- An SD2SNES, [FXPak Pro](https://krikzz.com/store/home/54-fxpak-pro.html), or other compatible hardware
- Your Super Metroid ROM file, probably named `Super Metroid (Japan, USA).sfc`
## Installation Procedures
### Windows Setup
1. Download and install the Super Metroid Client from the link above, making sure to install the most recent version.
**The file is located in the assets section at the bottom of the version information**.
2. During setup, you will be asked to locate your base ROM file. This is your Super Metroid ROM file.
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.
### Macintosh Setup
- We need volunteers to help fill this section! Please contact **Farrak Kilhn** on Discord if you want to help.
## Create a Config (.yaml) File
### What is a config file and why do I need one?
Your config file contains a set of configuration options which provide the generator with information about how
it should generate your game. Each player of a multiworld will provide their own config file. This setup allows
each player to enjoy an experience customized for their taste, and different players in the same multiworld
can all have different options.
### Where do I get a config file?
The [Player Settings](/games/Super%20Metroid/player-settings) page on the website allows you to configure your
personal settings and export a config file from them.
### 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](/mysterycheck) page.
## Generating a Single-Player Game
1. Navigate to the [Player Settings](/games/Super%20Metroid/player-settings) page, configure your options, and click
the "Generate Game" button.
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 Super Metroid Client will launch automatically, create your ROM from
the patch file, and open your emulator for you.
6. Since this is a single-player game, you will no longer need the client, so feel free to close it.
## 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 `.apm3` 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 Multitroid
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 `sniConnector.lua` file you downloaded above
##### BizHawk
1. Ensure you have the BSNES core loaded. You may do this by clicking on the Tools menu in BizHawk and following
these menu options:
`Config --> Cores --> SNES --> BSNES`
Once you have changed the loaded core, you must restart BizHawk.
2. Load your ROM file if it hasn't already been loaded.
3. Click on the Tools menu and click on **Lua Console**
4. Click the button to open a new Lua script.
5. Select the `sniConnector.lua` file you downloaded above
#### 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
[here](https://github.com/RedGuyyyy/sd2snes/releases). Other hardware may find helpful information
[on this 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](/generate). 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 website linked above.
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.

View File

@ -223,5 +223,24 @@
]
}
]
},
{
"gameTitle": "Super Metroid",
"tutorials": [
{
"name": "Multiworld Setup Guide",
"description": "A guide to setting up the Super Metroid Client on your computer. This guide covers single-player, multiworld, and related software.",
"files": [
{
"language": "English",
"filename": "super-metroid/multiworld_en.md",
"link": "super-metroid/multiworld/en",
"authors": [
"Farrak Kilhn"
]
}
]
}
]
}
]

View File

@ -1,14 +1,9 @@
# A Link to the Past Randomizer Setup Guide
<div id="tutorial-video-container">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/mJKEHaiyR_Y" frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen>
</iframe>
</div>
## Required Software
- [Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases)
- [SNI](https://github.com/alttpo/sni/releases) (Included in Archipelago)
- [Z3Client](https://github.com/ArchipelagoMW/Z3Client/releases)
- **sniConnector.lua** (located on the client download page)
- [SNI](https://github.com/alttpo/sni/releases) (Included in the Super Metroid Client)
- Hardware or software capable of loading and playing SNES ROM files
- An emulator capable of connecting to SNI
([snes9x Multitroid](https://drive.google.com/drive/folders/1_ej-pwWtCAHYXIrvs5Hro16A1s9Hi3Jz),
@ -19,19 +14,14 @@
## Installation Procedures
### Windows Setup
1. Download and install Archipelago from the link above, making sure to install the most recent version.
**The file is located in the assets section at the bottom of the version information**. If you intend to play normal
multiworld games, you want `Setup.Archipelago.exe`
- During the installation process, you will be asked to browse for your Japanese 1.0 ROM file. If you have
installed this software before and are simply upgrading now, you will not be prompted to locate your
ROM file a second time.
- You may also be prompted to install Microsoft Visual C++. If you already have this software on your computer
(possibly because a Steam game installed it already), the installer will not prompt you to install it again.
1. Download and install the Z3Client from the link above, making sure to install the most recent version.
**The file is located in the assets section at the bottom of the version information**.
- During setup, you will be asked to locate your base ROM file. This is your Japanese Link to the Past ROM file.
2. 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...**
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
@ -40,37 +30,41 @@ for launching ROM files.
### Macintosh Setup
- We need volunteers to help fill this section! Please contact **Farrak Kilhn** on Discord if you want to help.
## Configuring your YAML file
## Create a Config (.yaml) File
### What is a YAML file and why do I need one?
Your YAML file contains a set of configuration options which provide the generator with information about how
it should generate your game. Each player of a multiworld will provide their own YAML file. This setup allows
### What is a config file and why do I need one?
Your config file contains a set of configuration options which provide the generator with information about how
it should generate your game. Each player of a multiworld will provide their own config file. This setup allows
each player to enjoy an experience customized for their taste, and different players in the same multiworld
can all have different options.
### Where do I get a YAML file?
The [Generate Game](/games/A Link to the Past/player-settings) page on the website allows you to configure your personal settings and
export a YAML file from them.
### Where do I get a config file?
The [Player Settings](/games/A%20Link%20to%20the%20Past/player-settings) page on the website allows you to configure
your personal settings and export a config file from them.
### Verifying your YAML file
If you would like to validate your YAML file to make sure it works, you may do so on the
### 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](/mysterycheck) page.
## Generating a Single-Player Game
1. Navigate to the [Player Settings](/games/A%20Link%20to%20the%20Past/player-settings) page, configure your options, and click the "Generate Game" button.
2. You will be presented with a "Seed Info" page, where you can download your patch file.
3. Double-click on your patch file, and the emulator should launch with your game automatically. As the
Client is unnecessary for single player games, you may close it and the WebUI.
1. Navigate to the [Player Settings](/games/A%20Link%20to%20the%20Past/player-settings) page, configure your options,
and click the "Generate Game" button.
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 Super Metroid Client will launch automatically, create your ROM from
the patch file, and open your emulator for you.
6. Since this is a single-player game, you will no longer need the client, so feel free to close it.
## 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 YAML file to whoever is hosting. Once that
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 `.apbp` 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 file in the same place as your patch file.
launch the client, and will also create your ROM in the same place as your patch file.
### Connect to the client
@ -84,23 +78,17 @@ Firewall.
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. Browse to the location you extracted snes9x Multitroid to, enter the `lua` folder, and choose `multibridge.lua`
6. Observe a name has been assigned to you, and that the client shows "SNES Device: Connected", with that same
name in the upper left corner.
5. Select the `sniConnector.lua` file you downloaded above
##### BizHawk
1. Ensure you have the BSNES core loaded. You may do this by clicking on the Tools menu in BizHawk and following
these menu options:
these menu options:
`Config --> Cores --> SNES --> BSNES`
Once you have changed the loaded core, you must restart BizHawk.
2. Load your ROM file if it hasn't already been loaded.
3. Click on the Tools menu and click on **Lua Console**
4. Click the button to open a new Lua script.
5. Browse to your MultiWorld Utilities installation directory, and into the following directories:
`SNI`
6. Select `Connector.lua` and click Open.
7. Observe a name has been assigned to you, and that the client shows "SNES Device: Connected", with that same
name in the upper left corner.
5. Select the `sniConnector.lua` file you downloaded above
#### With hardware
This guide assumes you have downloaded the correct firmware for your device. If you have not
@ -110,54 +98,30 @@ done so already, please do this now. SD2SNES and FXPak Pro users may download th
1. Close your emulator, which may have auto-launched.
2. Power on your device and load the ROM.
3. Observe the client window now shows "SNES Device: Connected", and lists the name of your device.
### Connect to the MultiServer
The patch file which launched your client should have automatically connected you to the MultiServer.
### 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". If the client does not connect after a few moments, you may need to refresh the page.
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 the hosting service provided on
[the website](/generate). The process is relatively simple:
The recommended way to host a game is to use our [hosting service](/generate). The process is relatively simple:
1. Collect YAML files from your players.
2. Create a zip file containing your players' YAML files.
1. Collect config files from your players.
2. Create a zip file containing your players' config files.
3. Upload that zip file to the website linked above.
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.
**Note:** The patch files provided on this page will allow players to automatically connect to the server,
while the patch files on the "Seed Info" page will not.
7. Note that a link to a MultiWorld Tracker is at the top of the room page. You should also provide this link
to your players, so they can watch the progress of the game. Any observers may also be given the link to
this page.
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.
## Auto-Tracking
If you would like to use auto-tracking for your game, several pieces of software provide this functionality.
The recommended software for auto-tracking is currently
[OpenTracker](https://github.com/trippsc2/OpenTracker/releases).
### Installation
1. Download the appropriate installation file for your computer (Windows users want the `.msi` file).
2. During the installation process, you may be asked to install the Microsoft Visual Studio Build Tools. A link
to this software is provided during the installation procedure, and it must be installed manually.
### Enable auto-tracking
1. With OpenTracker launched, click the Tracking menu at the top of the window, then choose **AutoTracker...**
2. Click the **Get Devices** button
3. Select your SNES device from the drop-down list
4. If you would like to track small keys and dungeon items, check the box labeled **Race Illegal Tracking**
5. Click the **Start Autotracking** button
6. Close the AutoTracker window, as it is no longer necessary

View File

@ -32,18 +32,18 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
LocationData('Upper lake desolation', 'Crash site chest 1', 1337016, lambda state: state.has_all(['Killed Maw', 'Gas Mask'], player)),
LocationData('Upper lake desolation', 'Crash site chest 2', 1337017, lambda state: state.has_all(['Killed Maw', 'Gas Mask'], player)),
LocationData('Upper lake desolation', 'Kitty Boss', 1337018),
LocationData('Libary', 'Basement', 1337019),
LocationData('Libary', 'Consolation', 1337020),
LocationData('Libary', 'Librarian', 1337021),
LocationData('Libary', 'Reading nook chest', 1337022),
LocationData('Libary', 'Storage room chest 1', 1337023, lambda state: state._timespinner_has_keycard_D(world, player)),
LocationData('Libary', 'Storage room chest 2', 1337024, lambda state: state._timespinner_has_keycard_D(world, player)),
LocationData('Libary', 'Storage room chest 3', 1337025, lambda state: state._timespinner_has_keycard_D(world, player)),
LocationData('Libary top', 'Backer room chest 5', 1337026),
LocationData('Libary top', 'Backer room chest 4', 1337027),
LocationData('Libary top', 'Backer room chest 3', 1337028),
LocationData('Libary top', 'Backer room chest 2', 1337029),
LocationData('Libary top', 'Backer room chest 1', 1337030),
LocationData('Library', 'Basement', 1337019),
LocationData('Library', 'Consolation', 1337020),
LocationData('Library', 'Librarian', 1337021),
LocationData('Library', 'Reading nook chest', 1337022),
LocationData('Library', 'Storage room chest 1', 1337023, lambda state: state._timespinner_has_keycard_D(world, player)),
LocationData('Library', 'Storage room chest 2', 1337024, lambda state: state._timespinner_has_keycard_D(world, player)),
LocationData('Library', 'Storage room chest 3', 1337025, lambda state: state._timespinner_has_keycard_D(world, player)),
LocationData('Library top', 'Backer room chest 5', 1337026),
LocationData('Library top', 'Backer room chest 4', 1337027),
LocationData('Library top', 'Backer room chest 3', 1337028),
LocationData('Library top', 'Backer room chest 2', 1337029),
LocationData('Library top', 'Backer room chest 1', 1337030),
LocationData('Varndagroth tower left', 'Elevator Key not required', 1337031),
LocationData('Varndagroth tower left', 'Ye olde Timespinner', 1337032),
LocationData('Varndagroth tower left', 'C Keycard chest', 1337033, lambda state: state._timespinner_has_keycard_C(world, player)),
@ -114,19 +114,19 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
LocationData('Forest', 'Batcave', 1337096),
LocationData('Forest', 'Bridge Chest', 1337097),
LocationData('Left Side forest Caves', 'Solitary bat room', 1337098),
LocationData('Upper Lake Sirine', 'Rat nest', 1337099),
LocationData('Upper Lake Sirine', 'Double jump cave platform (past)', 1337100, lambda state: state._timespinner_has_doublejump(world, player)),
LocationData('Upper Lake Sirine', 'Double jump cave floor (past)', 1337101),
LocationData('Upper Lake Sirine', 'West lake serene cave secret', 1337102, lambda state: state._timespinner_can_break_walls(world, player)),
LocationData('Upper Lake Sirine', 'Chest behind vines', 1337103),
LocationData('Upper Lake Sirine', 'Pyramid keys room', 1337104),
LocationData('Lower Lake Sirine', 'Deep dive', 1337105),
LocationData('Lower Lake Sirine', 'Under the eels', 1337106),
LocationData('Lower Lake Sirine', 'Water spikes room', 1337107),
LocationData('Lower Lake Sirine', 'Underwater secret', 1337108, lambda state: state._timespinner_can_break_walls(world, player)),
LocationData('Lower Lake Sirine', 'T chest', 1337109),
LocationData('Lower Lake Sirine', 'Past the eels', 1337110),
LocationData('Lower Lake Sirine', 'Underwater pedestal', 1337111),
LocationData('Upper Lake Serene', 'Rat nest', 1337099),
LocationData('Upper Lake Serene', 'Double jump cave platform (past)', 1337100, lambda state: state._timespinner_has_doublejump(world, player)),
LocationData('Upper Lake Serene', 'Double jump cave floor (past)', 1337101),
LocationData('Upper Lake Serene', 'West lake serene cave secret', 1337102, lambda state: state._timespinner_can_break_walls(world, player)),
LocationData('Upper Lake Serene', 'Chest behind vines', 1337103),
LocationData('Upper Lake Serene', 'Pyramid keys room', 1337104),
LocationData('Lower Lake Serene', 'Deep dive', 1337105),
LocationData('Lower Lake Serene', 'Under the eels', 1337106),
LocationData('Lower Lake Serene', 'Water spikes room', 1337107),
LocationData('Lower Lake Serene', 'Underwater secret', 1337108, lambda state: state._timespinner_can_break_walls(world, player)),
LocationData('Lower Lake Serene', 'T chest', 1337109),
LocationData('Lower Lake Serene', 'Past the eels', 1337110),
LocationData('Lower Lake Serene', 'Underwater pedestal', 1337111),
LocationData('Caves of Banishment (upper)', 'Mushroom double jump', 1337112, lambda state: state._timespinner_has_doublejump(world, player)),
LocationData('Caves of Banishment (upper)', 'Caves of banishment secret room', 1337113),
LocationData('Caves of Banishment (upper)', 'Below caves of banishment secret', 1337114),
@ -144,30 +144,30 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
LocationData('Caves of Banishment (Sirens)', 'Underwater sirens left', 1337125, lambda state: state.has('Water Mask', player)),
LocationData('Caves of Banishment (Sirens)', 'Underwater sirens right', 1337126, lambda state: state.has('Water Mask', player)),
LocationData('Caves of Banishment (Sirens)', 'Water hook', 1337127),
LocationData('Caste Ramparts', 'Caste Bomber chest', 1337128, lambda state: state._timespinner_has_multiple_small_jumps_of_npc(world, player)),
LocationData('Caste Ramparts', 'Freeze the engineer', 1337129, lambda state: state.has('Talaria Attachment', player) or state._timespinner_has_timestop(world, player)),
LocationData('Caste Ramparts', 'Giantess guarded room', 1337130),
LocationData('Caste Ramparts', 'Knight and archer guarded room', 1337131),
LocationData('Caste Ramparts', 'Castle pedestal', 1337132),
LocationData('Caste Keep', 'Basement secret pedestal', 1337133, lambda state: state._timespinner_can_break_walls(world, player)),
LocationData('Caste Keep', 'Break the wall', 1337134),
LocationData('Castle Ramparts', 'Castle Bomber chest', 1337128, lambda state: state._timespinner_has_multiple_small_jumps_of_npc(world, player)),
LocationData('Castle Ramparts', 'Freeze the engineer', 1337129, lambda state: state.has('Talaria Attachment', player) or state._timespinner_has_timestop(world, player)),
LocationData('Castle Ramparts', 'Giantess guarded room', 1337130),
LocationData('Castle Ramparts', 'Knight and archer guarded room', 1337131),
LocationData('Castle Ramparts', 'Castle pedestal', 1337132),
LocationData('Castle Keep', 'Basement secret pedestal', 1337133, lambda state: state._timespinner_can_break_walls(world, player)),
LocationData('Castle Keep', 'Break the wall', 1337134),
LocationData('Royal towers (lower)', 'Yas queen room', 1337135, lambda state: state._timespinner_has_pink(world, player)),
LocationData('Caste Keep', 'Basement hammer', 1337136),
LocationData('Caste Keep', 'Omelette chest', 1337137),
LocationData('Caste Keep', 'Just an egg', 1337138),
LocationData('Caste Keep', 'Out of the way', 1337139),
LocationData('Caste Keep', 'Killed Twins', EventId, lambda state: state._timespinner_has_timestop(world, player)),
LocationData('Caste Keep', 'Twins', 1337140, lambda state: state._timespinner_has_timestop(world, player)),
LocationData('Caste Keep', 'Royal guard tiny room', 1337141, lambda state: state._timespinner_has_doublejump(world, player)),
LocationData('Castle Keep', 'Basement hammer', 1337136),
LocationData('Castle Keep', 'Omelette chest', 1337137),
LocationData('Castle Keep', 'Just an egg', 1337138),
LocationData('Castle Keep', 'Out of the way', 1337139),
LocationData('Castle Keep', 'Killed Twins', EventId, lambda state: state._timespinner_has_timestop(world, player)),
LocationData('Castle Keep', 'Twins', 1337140, lambda state: state._timespinner_has_timestop(world, player)),
LocationData('Castle Keep', 'Royal guard tiny room', 1337141, lambda state: state._timespinner_has_doublejump(world, player)),
LocationData('Royal towers (lower)', 'Royal tower floor secret', 1337142, lambda state: state._timespinner_has_doublejump(world, player) and state._timespinner_can_break_walls(world, player)),
LocationData('Royal towers', 'Above the gap', 1337143),
LocationData('Royal towers', 'Under the ice mage', 1337144),
LocationData('Royal towers (upper)', 'Next to easy struggle juggle room', 1337145),
LocationData('Royal towers (upper)', 'Easy struggle juggle', 1337146, lambda state: state._timespinner_has_doublejump_of_npc(world, player)),
LocationData('Royal towers (upper)', 'Hard struggle juggle', 1337147, lambda state: state._timespinner_has_doublejump_of_npc(world, player)),
LocationData('Royal towers (upper)', 'No sturggle required', 1337148, lambda state: state._timespinner_has_doublejump_of_npc(world, player)),
LocationData('Royal towers (upper)', 'No struggle required', 1337148, lambda state: state._timespinner_has_doublejump_of_npc(world, player)),
LocationData('Royal towers', 'Right tower freebie', 1337149),
LocationData('Royal towers (upper)', 'Above the cide mage', 1337150),
LocationData('Royal towers (upper)', 'Above the ice mage', 1337150),
LocationData('Royal towers (upper)', 'Royal guard big room', 1337151),
LocationData('Royal towers (upper)', 'Before Aelana', 1337152),
LocationData('Royal towers (upper)', 'Killed Aelana', EventId),
@ -196,14 +196,14 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
downloadable_items: Tuple[LocationData, ...] = (
# DownloadTerminals
LocationData('Libary', 'Library terminal 1', 1337157, lambda state: state.has('Tablet', player)),
LocationData('Libary', 'Library terminal 2', 1337156, lambda state: state.has('Tablet', player)),
LocationData('Library', 'Library terminal 1', 1337157, lambda state: state.has('Tablet', player)),
LocationData('Library', 'Library terminal 2', 1337156, lambda state: state.has('Tablet', player)),
# 1337158 Is Lost in time
LocationData('Libary', 'Library terminal 3', 1337159, lambda state: state.has('Tablet', player)),
LocationData('Libary', 'V terminal 1', 1337160, lambda state: state.has_all(['Tablet', 'Library Keycard V'], player)),
LocationData('Libary', 'V terminal 2', 1337161, lambda state: state.has_all(['Tablet', 'Library Keycard V'], player)),
LocationData('Libary', 'V terminal 3', 1337162, lambda state: state.has_all(['Tablet', 'Library Keycard V'], player)),
LocationData('Libary top', 'Backer room terminal', 1337163, lambda state: state.has('Tablet', player)),
LocationData('Library', 'Library terminal 3', 1337159, lambda state: state.has('Tablet', player)),
LocationData('Library', 'V terminal 1', 1337160, lambda state: state.has_all(['Tablet', 'Library Keycard V'], player)),
LocationData('Library', 'V terminal 2', 1337161, lambda state: state.has_all(['Tablet', 'Library Keycard V'], player)),
LocationData('Library', 'V terminal 3', 1337162, lambda state: state.has_all(['Tablet', 'Library Keycard V'], player)),
LocationData('Library top', 'Backer room terminal', 1337163, lambda state: state.has('Tablet', player)),
LocationData('Varndagroth tower right (elevator)', 'Medbay', 1337164, lambda state: state.has('Tablet', player) and state._timespinner_has_keycard_B(world, player)),
LocationData('The lab (upper)', 'Chest and download terminal', 1337165, lambda state: state.has('Tablet', player)),
LocationData('The lab (power off)', 'Lab terminal middle', 1337166, lambda state: state.has('Tablet', player)),

View File

@ -39,7 +39,7 @@ class Inverted(Toggle):
display_name = "Inverted"
#class StinkyMaw(Toggle):
# "Require gassmask for Maw"
# "Require gasmask for Maw"
# display_name = "Stinky Maw"
# Some options that are available in the timespinner randomizer arent currently implemented

View File

@ -12,8 +12,8 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData
create_region(world, player, locations_per_region, location_cache, 'Lake desolation'),
create_region(world, player, locations_per_region, location_cache, 'Upper lake desolation'),
create_region(world, player, locations_per_region, location_cache, 'Lower lake desolation'),
create_region(world, player, locations_per_region, location_cache, 'Libary'),
create_region(world, player, locations_per_region, location_cache, 'Libary top'),
create_region(world, player, locations_per_region, location_cache, 'Library'),
create_region(world, player, locations_per_region, location_cache, 'Library top'),
create_region(world, player, locations_per_region, location_cache, 'Varndagroth tower left'),
create_region(world, player, locations_per_region, location_cache, 'Varndagroth tower right (upper)'),
create_region(world, player, locations_per_region, location_cache, 'Varndagroth tower right (lower)'),
@ -30,13 +30,13 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData
create_region(world, player, locations_per_region, location_cache, 'Refugee Camp'),
create_region(world, player, locations_per_region, location_cache, 'Forest'),
create_region(world, player, locations_per_region, location_cache, 'Left Side forest Caves'),
create_region(world, player, locations_per_region, location_cache, 'Upper Lake Sirine'),
create_region(world, player, locations_per_region, location_cache, 'Lower Lake Sirine'),
create_region(world, player, locations_per_region, location_cache, 'Upper Lake Serene'),
create_region(world, player, locations_per_region, location_cache, 'Lower Lake Serene'),
create_region(world, player, locations_per_region, location_cache, 'Caves of Banishment (upper)'),
create_region(world, player, locations_per_region, location_cache, 'Caves of Banishment (Maw)'),
create_region(world, player, locations_per_region, location_cache, 'Caves of Banishment (Sirens)'),
create_region(world, player, locations_per_region, location_cache, 'Caste Ramparts'),
create_region(world, player, locations_per_region, location_cache, 'Caste Keep'),
create_region(world, player, locations_per_region, location_cache, 'Castle Ramparts'),
create_region(world, player, locations_per_region, location_cache, 'Castle Keep'),
create_region(world, player, locations_per_region, location_cache, 'Royal towers (lower)'),
create_region(world, player, locations_per_region, location_cache, 'Royal towers'),
create_region(world, player, locations_per_region, location_cache, 'Royal towers (upper)'),
@ -50,20 +50,20 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData
names: Dict[str, int] = {}
connect(world, player, names, 'Lake desolation', 'Lower lake desolation', lambda state: state._timespinner_has_timestop(world, player or state.has('Talaria Attachment', player)))
connect(world, player, names, 'Lake desolation', 'Upper lake desolation', lambda state: state._timespinner_has_fire(world, player) and state.can_reach('Upper Lake Sirine', 'Region', player))
connect(world, player, names, 'Lake desolation', 'Upper lake desolation', lambda state: state._timespinner_has_fire(world, player) and state.can_reach('Upper Lake Serene', 'Region', player))
connect(world, player, names, 'Lake desolation', 'Skeleton Shaft', lambda state: state._timespinner_has_doublejump(world, player))
connect(world, player, names, 'Lake desolation', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Upper lake desolation', 'Lake desolation')
connect(world, player, names, 'Upper lake desolation', 'Lower lake desolation')
connect(world, player, names, 'Lower lake desolation', 'Lake desolation')
connect(world, player, names, 'Lower lake desolation', 'Libary')
connect(world, player, names, 'Lower lake desolation', 'Library')
connect(world, player, names, 'Lower lake desolation', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Libary', 'Lower lake desolation')
connect(world, player, names, 'Libary', 'Libary top', lambda state: state._timespinner_has_doublejump(world, player) or state.has('Talaria Attachment', player))
connect(world, player, names, 'Libary', 'Varndagroth tower left', lambda state: state._timespinner_has_keycard_D(world, player))
connect(world, player, names, 'Libary', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Libary top', 'Libary')
connect(world, player, names, 'Varndagroth tower left', 'Libary')
connect(world, player, names, 'Library', 'Lower lake desolation')
connect(world, player, names, 'Library', 'Library top', lambda state: state._timespinner_has_doublejump(world, player) or state.has('Talaria Attachment', player))
connect(world, player, names, 'Library', 'Varndagroth tower left', lambda state: state._timespinner_has_keycard_D(world, player))
connect(world, player, names, 'Library', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Library top', 'Library')
connect(world, player, names, 'Varndagroth tower left', 'Library')
connect(world, player, names, 'Varndagroth tower left', 'Varndagroth tower right (upper)', lambda state: state._timespinner_has_keycard_C(world, player))
connect(world, player, names, 'Varndagroth tower left', 'Varndagroth tower right (lower)', lambda state: state._timespinner_has_keycard_B(world, player))
connect(world, player, names, 'Varndagroth tower left', 'Sealed Caves (Sirens)', lambda state: state._timespinner_has_keycard_B(world, player) and state.has('Elevator Keycard', player))
@ -98,35 +98,35 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData
connect(world, player, names, 'Sealed Caves (Xarion)', 'Sealed Caves (upper)', lambda state: state._timespinner_has_forwarddash_doublejump(world, player))
connect(world, player, names, 'Sealed Caves (Xarion)', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Refugee Camp', 'Forest')
connect(world, player, names, 'Refugee Camp', 'Libary', lambda state: not is_option_enabled(world, player, "Inverted"))
connect(world, player, names, 'Refugee Camp', 'Library', lambda state: not is_option_enabled(world, player, "Inverted"))
connect(world, player, names, 'Refugee Camp', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Forest', 'Refugee Camp')
connect(world, player, names, 'Forest', 'Left Side forest Caves', lambda state: state.has('Talaria Attachment', player) or state._timespinner_has_timestop(world, player))
connect(world, player, names, 'Forest', 'Caves of Banishment (Sirens)')
connect(world, player, names, 'Forest', 'Caste Ramparts')
connect(world, player, names, 'Forest', 'Castle Ramparts')
connect(world, player, names, 'Left Side forest Caves', 'Forest')
connect(world, player, names, 'Left Side forest Caves', 'Upper Lake Sirine', lambda state: state._timespinner_has_timestop(world, player))
connect(world, player, names, 'Left Side forest Caves', 'Lower Lake Sirine', lambda state: state.has('Water Mask', player))
connect(world, player, names, 'Left Side forest Caves', 'Upper Lake Serene', lambda state: state._timespinner_has_timestop(world, player))
connect(world, player, names, 'Left Side forest Caves', 'Lower Lake Serene', lambda state: state.has('Water Mask', player))
connect(world, player, names, 'Left Side forest Caves', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Upper Lake Sirine', 'Left Side forest Caves')
connect(world, player, names, 'Upper Lake Sirine', 'Lower Lake Sirine', lambda state: state.has('Water Mask', player))
connect(world, player, names, 'Lower Lake Sirine', 'Upper Lake Sirine')
connect(world, player, names, 'Lower Lake Sirine', 'Left Side forest Caves')
connect(world, player, names, 'Lower Lake Sirine', 'Caves of Banishment (upper)')
connect(world, player, names, 'Caves of Banishment (upper)', 'Upper Lake Sirine', lambda state: state.has('Water Mask', player))
connect(world, player, names, 'Upper Lake Serene', 'Left Side forest Caves')
connect(world, player, names, 'Upper Lake Serene', 'Lower Lake Serene', lambda state: state.has('Water Mask', player))
connect(world, player, names, 'Lower Lake Serene', 'Upper Lake Serene')
connect(world, player, names, 'Lower Lake Serene', 'Left Side forest Caves')
connect(world, player, names, 'Lower Lake Serene', 'Caves of Banishment (upper)')
connect(world, player, names, 'Caves of Banishment (upper)', 'Upper Lake Serene', lambda state: state.has('Water Mask', player))
connect(world, player, names, 'Caves of Banishment (upper)', 'Caves of Banishment (Maw)', lambda state: state.has('Twin Pyramid Key', player) or state._timespinner_has_forwarddash_doublejump(world, player))
connect(world, player, names, 'Caves of Banishment (upper)', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Caves of Banishment (Maw)', 'Caves of Banishment (upper)', lambda state: state._timespinner_has_forwarddash_doublejump(world, player))
connect(world, player, names, 'Caves of Banishment (Maw)', 'Caves of Banishment (Sirens)', lambda state: state.has('Gas Mask', player))
connect(world, player, names, 'Caves of Banishment (Maw)', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Caves of Banishment (Sirens)', 'Forest')
connect(world, player, names, 'Caste Ramparts', 'Forest')
connect(world, player, names, 'Caste Ramparts', 'Caste Keep')
connect(world, player, names, 'Caste Ramparts', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Caste Keep', 'Caste Ramparts')
connect(world, player, names, 'Caste Keep', 'Royal towers (lower)', lambda state: state._timespinner_has_doublejump(world, player))
connect(world, player, names, 'Caste Keep', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Royal towers (lower)', 'Caste Keep')
connect(world, player, names, 'Castle Ramparts', 'Forest')
connect(world, player, names, 'Castle Ramparts', 'Castle Keep')
connect(world, player, names, 'Castle Ramparts', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Castle Keep', 'Castle Ramparts')
connect(world, player, names, 'Castle Keep', 'Royal towers (lower)', lambda state: state._timespinner_has_doublejump(world, player))
connect(world, player, names, 'Castle Keep', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Royal towers (lower)', 'Castle Keep')
connect(world, player, names, 'Royal towers (lower)', 'Royal towers', lambda state: state.has('Timespinner Wheel', player) or state._timespinner_has_forwarddash_doublejump(world, player))
connect(world, player, names, 'Royal towers (lower)', 'Space time continuum', lambda state: state.has('Twin Pyramid Key', player))
connect(world, player, names, 'Royal towers', 'Royal towers (lower)')
@ -137,14 +137,14 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData
connect(world, player, names, 'Ancient Pyramid (right)', 'Ancient Pyramid (left)', lambda state: state._timespinner_has_upwarddash(world, player))
connect(world, player, names, 'Space time continuum', 'Lake desolation', lambda state: pyramid_keys_unlock == "GateLakeDesolation")
connect(world, player, names, 'Space time continuum', 'Lower lake desolation', lambda state: pyramid_keys_unlock == "GateKittyBoss")
connect(world, player, names, 'Space time continuum', 'Libary', lambda state: pyramid_keys_unlock == "GateLeftLibrary")
connect(world, player, names, 'Space time continuum', 'Library', lambda state: pyramid_keys_unlock == "GateLeftLibrary")
connect(world, player, names, 'Space time continuum', 'Varndagroth tower right (lower)', lambda state: pyramid_keys_unlock == "GateMilitairyGate")
connect(world, player, names, 'Space time continuum', 'Skeleton Shaft', lambda state: pyramid_keys_unlock == "GateSealedCaves")
connect(world, player, names, 'Space time continuum', 'Sealed Caves (Sirens)', lambda state: pyramid_keys_unlock == "GateSealedSirensCave")
connect(world, player, names, 'Space time continuum', 'Left Side forest Caves', lambda state: pyramid_keys_unlock == "GateLakeSirineRight")
connect(world, player, names, 'Space time continuum', 'Refugee Camp', lambda state: pyramid_keys_unlock == "GateAccessToPast")
connect(world, player, names, 'Space time continuum', 'Caste Ramparts', lambda state: pyramid_keys_unlock == "GateCastleRamparts")
connect(world, player, names, 'Space time continuum', 'Caste Keep', lambda state: pyramid_keys_unlock == "GateCastleKeep")
connect(world, player, names, 'Space time continuum', 'Castle Ramparts', lambda state: pyramid_keys_unlock == "GateCastleRamparts")
connect(world, player, names, 'Space time continuum', 'Castle Keep', lambda state: pyramid_keys_unlock == "GateCastleKeep")
connect(world, player, names, 'Space time continuum', 'Royal towers (lower)', lambda state: pyramid_keys_unlock == "GateRoyalTowers")
connect(world, player, names, 'Space time continuum', 'Caves of Banishment (Maw)', lambda state: pyramid_keys_unlock == "GateMaw")
connect(world, player, names, 'Space time continuum', 'Caves of Banishment (upper)', lambda state: pyramid_keys_unlock == "GateCavesOfBanishment")

View File

@ -18,7 +18,7 @@ class TimespinnerWorld(World):
game = "Timespinner"
topology_present = True
remote_items = False
data_version = 2
data_version = 3
item_name_to_id = {name: data.code for name, data in item_table.items()}
location_name_to_id = {location.name: location.code for location in get_locations(None, None)}