Compare commits

..

13 Commits

Author SHA1 Message Date
NewSoupVi
da256d7252 Take Counter back out of RestrictedUnpickler 2025-07-07 01:53:16 +02:00
Doug Hoskisson
e68b1ad428 CommonClient: fix extra panels added to main_area_container (#5151) 2025-07-06 19:22:02 +02:00
Ixrec
072e2ece15 Docs: 'get_prefill_items' -> 'get_pre_fill_items' (#5167) 2025-07-05 17:01:08 -04:00
agilbert1412
11130037fe Stardew Valley: Fixed luck level requirements for slot machines #5160
# Conflicts:
#	worlds/stardew_valley/data/craftable_data.py
2025-07-03 21:08:36 +02:00
Scipio Wright
ba66ef14cc Update world api.md (#5149) 2025-07-02 14:14:35 +02:00
Jérémie Bolduc
8aacc23882 SDV: Add "Desert Transportation" and "Island Transportation" Item Groups (#5143) 2025-06-28 11:36:09 -04:00
Jonathan Tan
03e5fd3dae TWW: Fix Swords in Swordless Mode (#5137)
Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
2025-06-28 10:46:37 -04:00
Fly Hyping
da52598c08 Wargroove: Fix Communication Thread (#5125) 2025-06-27 19:42:35 -04:00
Jonathan Tan
52389731eb TWW: Update Preset S7 to S8 (#5138) 2025-06-27 18:46:00 -04:00
LiquidCat64
21864f6f95 CVCotM: Fix Advance Collection ROM (#5132) 2025-06-27 18:25:45 -04:00
DJ-lennart
00f8625280 Civilization VI: Updated setup and info pages (#5123)
* Update setup_en.md

Updated setup instructions for Civilization VI in Archipelago

* Update en_Civilization VI.md

Updated info page for Civilization VI in Archipelago

* Update setup_en.md
2025-06-21 16:31:12 +02:00
James White
c34e29c712 Pokemon RB: Client: Send bounce messages with current map ID (#5121) 2025-06-20 22:52:54 +02:00
palex00
e0ae3359f1 Pokémon RB: Use new link for a new tracker (#5122)
* Update setup_en.md

* Update setup_es.md
2025-06-20 20:55:49 +02:00
19 changed files with 224 additions and 146 deletions

View File

@@ -441,9 +441,6 @@ class RestrictedUnpickler(pickle.Unpickler):
def find_class(self, module: str, name: str) -> type:
if module == "builtins" and name in safe_builtins:
return getattr(builtins, name)
# used by OptionCounter
if module == "collections" and name == "Counter":
return collections.Counter
# used by MultiServer -> savegame/multidata
if module == "NetUtils" and name in {"NetworkItem", "ClientStatus", "Hint",
"SlotType", "NetworkSlot", "HintStatus"}:

View File

@@ -266,7 +266,7 @@ like entrance randomization in logic.
Regions have a list called `exits`, containing `Entrance` objects representing transitions to other regions.
There must be one special region (Called "Menu" by default, but configurable using [origin_region_name](https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/AutoWorld.py#L298-L299)),
There must be one special region (Called "Menu" by default, but configurable using [origin_region_name](https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/AutoWorld.py#L310-L311)),
from which the logic unfolds. AP assumes that a player will always be able to return to this starting region by resetting the game ("Save and quit").
### Entrances
@@ -533,7 +533,7 @@ In addition, the following methods can be implemented and are called in this ord
called to modify item placement before, during, and after the regular fill process; all finishing before
`generate_output`. Any items that need to be placed during `pre_fill` should not exist in the itempool, and if there
are any items that need to be filled this way, but need to be in state while you fill other items, they can be
returned from `get_prefill_items`.
returned from `get_pre_fill_items`.
* `generate_output(self, output_directory: str)`
creates the output files if there is output to be generated. When this is called,
`self.multiworld.get_locations(self.player)` has all locations for the player, with attribute `item` pointing to the

View File

@@ -921,9 +921,11 @@ class GameManager(ThemedApp):
hint_panel = self.add_client_tab("Hints", HintLayout(self.hint_log))
self.log_panels["Hints"] = hint_panel.content
self.main_area_container = MDGridLayout(size_hint_y=1, cols=1)
self.main_area_container.add_widget(self.tabs)
self.main_area_container.add_widget(self.screens)
self.main_area_container = MDGridLayout(size_hint_y=1, rows=1)
tab_container = MDGridLayout(size_hint_y=1, cols=1)
tab_container.add_widget(self.tabs)
tab_container.add_widget(self.screens)
self.main_area_container.add_widget(tab_container)
self.grid.add_widget(self.main_area_container)

View File

@@ -382,7 +382,7 @@ class World(metaclass=AutoWorldRegister):
def create_items(self) -> None:
"""
Method for creating and submitting items to the itempool. Items and Regions must *not* be created and submitted
to the MultiWorld after this step. If items need to be placed during pre_fill use `get_prefill_items`.
to the MultiWorld after this step. If items need to be placed during pre_fill use `get_pre_fill_items`.
"""
pass

View File

@@ -20,16 +20,17 @@ A short period after receiving an item, you will get a notification indicating y
## FAQs
- Do I need the DLC to play this?
- Yes, you need both Rise & Fall and Gathering Storm.
- You need both expansions, Rise & Fall and Gathering Storm. You do not need the other DLCs but they fully work with this.
- Does this work with Multiplayer?
- It does not and, despite my best efforts, probably won't until there's a new way for external programs to be able to interact with the game.
- Does my mod that reskins Barbarians as various Pro Wrestlers work with this?
- Only one way to find out! Any mods that modify techs/civics will most likely cause issues, though.
- Does this work with other mods?
- A lot of mods seem to work without issues combined with this, but you should avoid any mods that change things in the tech or civic tree, as even if they would work it could cause issues with the logic.
- "Help! I can't see any of the items that have been sent to me!"
- Both trees by default will show you the researchable Archipelago locations. To view the normal tree, you can click "Toggle Archipelago Tree" in the top-left corner of the tree view.
- "Oh no! I received the Machinery tech and now instead of getting an Archer next turn, I have to wait an additional 10 turns to get a Crossbowman!"
- Vanilla prevents you from building units of the same class from an earlier tech level after you have researched a later variant. For example, this could be problematic if someone unlocks Crossbowmen for you right out the gate since you won't be able to make Archers (which have a much lower production cost).
Solution: You can now go in to the tech tree, click "Toggle Archipelago Tree" to view your unlocked techs, and then can click any tech you have unlocked to toggle whether it is currently active or not.
- Solution: You can now go in to the tech tree, click "Toggle Archipelago Tree" to view your unlocked techs, and then can click any tech you have unlocked to toggle whether it is currently active or not.
- If you think you should be able to make Field Cannons but seemingly can't try disabling `Telecommunications`
- "How does DeathLink work? Am I going to have to start a new game every time one of my friends dies?"
- Heavens no, my fellow Archipelago appreciator. When configuring your Archipelago options for Civilization on the options page, there are several choices available for you to fine tune the way you'd like to be punished for the follies of your friends. These include: Having a random unit destroyed, losing a percentage of gold or faith, or even losing a point on your era score. If you can't make up your mind, you can elect to have any of them be selected every time a death link is sent your way.
In the event you lose one of your units in combat (this means captured units don't count), then you will send a death link event to the rest of your friends.
@@ -39,7 +40,8 @@ Solution: You can now go in to the tech tree, click "Toggle Archipelago Tree" to
1. `TECH_WRITING`
2. `TECH_EDUCATION`
3. `TECH_CHEMISTRY`
- If you want to see the details around each item, you can review [this file](https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/civ_6/data/progressive_districts.json).
- An important thing to note is that the seaport is part of progressive industrial zones, due to electricity having both an industrial zone building and the seaport.
- If you want to see the details around each item, you can review [this file](https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/civ_6/data/progressive_districts.py).
## Boostsanity
Boostsanity takes all of the Eureka & Inspiration events and makes them location checks. This feature is the one to change up the way Civilization is played in an AP multiworld/randomizer. What normally are mundane tasks that are passively collected now become a novel and interesting bucket list that you need to pay attention to in order to unlock items for yourself and others!
@@ -56,4 +58,3 @@ Boosts have logic associated with them in order to verify you can always reach t
- The unpredictable timing of boosts and unlocking them can occasionally lead to scenarios where you'll have to first encounter a locked era defeat and then load a previous save. To help reduce the frequency of this, local `PROGRESSIVE_ERA` items will never be located at a boost check.
- There's too many boosts, how will I know which one's I should focus on?!
- In order to give a little more focus to all the boosts rather than just arbitrarily picking them at random, items in both of the vanilla trees will now have an advisor icon on them if its associated boost contains a progression item.

View File

@@ -6,12 +6,14 @@ This guide is meant to help you get up and running with Civilization VI in Archi
The following are required in order to play Civ VI in Archipelago:
- Windows OS (Firaxis does not support the necessary tooling for Mac, or Linux)
- Windows OS (Firaxis does not support the necessary tooling for Mac, or Linux).
- Installed [Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases) v0.4.5 or higher.
- Installed [Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases).
- The latest version of the [Civ VI AP Mod](https://github.com/hesto2/civilization_archipelago_mod/releases/latest).
- A copy of the game `Civilization VI` including the two expansions `Rise & Fall` and `Gathering Storm` (both the Steam and Epic version should work).
## Enabling the tuner
In the main menu, navigate to the "Game Options" page. On the "Game" menu, make sure that "Tuner (disables achievements)" is enabled.
@@ -20,27 +22,32 @@ In the main menu, navigate to the "Game Options" page. On the "Game" menu, make
1. Download and unzip the latest release of the mod from [GitHub](https://github.com/hesto2/civilization_archipelago_mod/releases/latest).
2. Copy the folder containing the mod files to your Civ VI mods folder. On Windows, this is usually located at `C:\Users\YOUR_USER\Documents\My Games\Sid Meier's Civilization VI\Mods`. If you use OneDrive, check if the folder is instead located in your OneDrive file structure.
2. Copy the folder containing the mod files to your Civ VI mods folder. On Windows, this is usually located at `C:\Users\YOUR_USER\Documents\My Games\Sid Meier's Civilization VI\Mods`. If you use OneDrive, check if the folder is instead located in your OneDrive file structure, and use that path when relevant in future steps.
3. After the Archipelago host generates a game, you should be given a `.apcivvi` file. Associate the file with the Archipelago Launcher and double click it.
4. Copy the contents of the new folder it generates (it will have the same name as the `.apcivvi` file) into your Civilization VI Archipelago Mod folder. If double clicking the `.apcivvi` file doesn't generate a folder, you can just rename it to a file ending with `.zip` and extract its contents to a new folder. To do this, right click the `.apcivvi` file and click "Rename", make sure it ends in `.zip`, then right click it again and select "Extract All".
4. Copy the contents of the new folder it generates (it will have the same name as the `.apcivvi` file) into your Civilization VI Archipelago Mod folder. If double clicking the `.apcivvi` file doesn't generate a folder, you can instead open it as a zip file. You can do this by either right clicking it and opening it with a program that handles zip files, or by right clicking and renaming the file extension from `apcivvi` to `zip`.
5. Your finished mod folder should look something like this:
- Civ VI Mods Directory
- civilization_archipelago_mod
- NewItems.xml
- InitOptions.lua
- Archipelago.modinfo
- All the other mod files, etc.
5. Place the files generated from the `.apcivvi` in your archipelago mod folder (there should be five files placed there from the apcivvi file, overwrite if asked). Your mod path should look something like `C:\Users\YOUR_USER\Documents\My Games\Sid Meier's Civilization VI\Mods\civilization_archipelago_mod`.
## Configuring your game
When configuring your game, make sure to start the game in the Ancient Era and leave all settings related to starting technologies and civics as the defaults. Other than that, configure difficulty, AI, etc. as you normally would.
Make sure you enable the mod in the main title under Additional Content > Mods. When configuring your game, make sure to start the game in the Ancient Era and leave all settings related to starting technologies and civics as the defaults. Other than that, configure difficulty, AI, etc. as you normally would.
## Troubleshooting
- If you have troubles with file extension related stuff, make sure Windows shows file extensions as they are turned off by default. If you don't know how to turn them on it is just a quick google search away.
- If you are getting an error: "The remote computer refused the network connection", or something else related to the client (or tuner) not being able to connect, it likely indicates the tuner is not actually enabled. One simple way to verify that it is enabled is, after completing the setup steps, go to Main Menu &rarr; Options &rarr; Look for an option named "Tuner" and verify it is set to "Enabled"
- If your game gets in a state where someone has sent you items or you have sent locations but these are not correctly sent to the multiworld, you can run `/resync` from the Civ 6 client. This may take up to a minute depending on how many items there are.
- If your game gets in a state where someone has sent you items or you have sent locations but these are not correctly sent to the multiworld, you can run `/resync` from the Civ 6 client. This may take up to a minute depending on how many items there are. This can resend certain items to you, like one time bonuses.
- If the archipelago mod does not appear in the mod selector in the game, make sure the mod is correctly placed as a folder in the `Sid Meier's Civilization VI\Mods` folder, there should not be any loose files in there only folders. As in the path should look something like `C:\Users\YOUR_USER\Documents\My Games\Sid Meier's Civilization VI\Mods\civilization_archipelago_mod`.
- If it still does not appear make sure you have the right folder, one way to verify you are in the right place is to find the general folder area where your Civ VI save files are located.
- If you get an error when trying to start a game saying `Error - One or more Mods failed to load content`, make sure the files from the `.apcivvi` are placed into the `civilization_archipelago_mod` as loose files and not as a folder.
- If you still have any errors make sure the two expansions Rise & Fall and Gathering Storm are active in the mod selector (all the official DLC works without issues but Rise & Fall and Gathering Storm are required for the mod).
- If boostsanity is enabled and those items are not being sent out but regular techs are, make sure you placed the files from your new room in the mod folder.

View File

@@ -734,8 +734,8 @@ def get_start_inventory_data(world: "CVCotMWorld") -> Tuple[Dict[int, bytes], bo
magic_items_array[array_offset] += 1
# Add the start inventory arrays to the offset data in bytes form.
start_inventory_data[0x680080] = bytes(magic_items_array)
start_inventory_data[0x6800A0] = bytes(cards_array)
start_inventory_data[0x690080] = bytes(magic_items_array)
start_inventory_data[0x6900A0] = bytes(cards_array)
# Add the extra max HP/MP/Hearts to all classes' base stats. Doing it this way makes us less likely to hit the max
# possible Max Ups.

View File

@@ -132,40 +132,40 @@ start_inventory_giver = [
# Magic Items
0x13, 0x48, # ldr r0, =0x202572F
0x14, 0x49, # ldr r1, =0x8680080
0x14, 0x49, # ldr r1, =0x8690080
0x00, 0x22, # mov r2, #0
0x8B, 0x5C, # ldrb r3, [r1, r2]
0x83, 0x54, # strb r3, [r0, r2]
0x01, 0x32, # adds r2, #1
0x08, 0x2A, # cmp r2, #8
0xFA, 0xDB, # blt 0x8680006
0xFA, 0xDB, # blt 0x8690006
# Max Ups
0x11, 0x48, # ldr r0, =0x202572C
0x12, 0x49, # ldr r1, =0x8680090
0x12, 0x49, # ldr r1, =0x8690090
0x00, 0x22, # mov r2, #0
0x8B, 0x5C, # ldrb r3, [r1, r2]
0x83, 0x54, # strb r3, [r0, r2]
0x01, 0x32, # adds r2, #1
0x03, 0x2A, # cmp r2, #3
0xFA, 0xDB, # blt 0x8680016
0xFA, 0xDB, # blt 0x8690016
# Cards
0x0F, 0x48, # ldr r0, =0x2025674
0x10, 0x49, # ldr r1, =0x86800A0
0x10, 0x49, # ldr r1, =0x86900A0
0x00, 0x22, # mov r2, #0
0x8B, 0x5C, # ldrb r3, [r1, r2]
0x83, 0x54, # strb r3, [r0, r2]
0x01, 0x32, # adds r2, #1
0x14, 0x2A, # cmp r2, #0x14
0xFA, 0xDB, # blt 0x8680026
0xFA, 0xDB, # blt 0x8690026
# Inventory Items (not currently supported)
0x0D, 0x48, # ldr r0, =0x20256ED
0x0E, 0x49, # ldr r1, =0x86800C0
0x0E, 0x49, # ldr r1, =0x86900C0
0x00, 0x22, # mov r2, #0
0x8B, 0x5C, # ldrb r3, [r1, r2]
0x83, 0x54, # strb r3, [r0, r2]
0x01, 0x32, # adds r2, #1
0x36, 0x2A, # cmp r2, #36
0xFA, 0xDB, # blt 0x8680036
0xFA, 0xDB, # blt 0x8690036
# Return to the function that checks for Magician Mode.
0xBA, 0x21, # movs r1, #0xBA
0x89, 0x00, # lsls r1, r1, #2
@@ -176,13 +176,13 @@ start_inventory_giver = [
# LDR number pool
0x78, 0x7F, 0x00, 0x08,
0x2F, 0x57, 0x02, 0x02,
0x80, 0x00, 0x68, 0x08,
0x80, 0x00, 0x69, 0x08,
0x2C, 0x57, 0x02, 0x02,
0x90, 0x00, 0x68, 0x08,
0x90, 0x00, 0x69, 0x08,
0x74, 0x56, 0x02, 0x02,
0xA0, 0x00, 0x68, 0x08,
0xA0, 0x00, 0x69, 0x08,
0xED, 0x56, 0x02, 0x02,
0xC0, 0x00, 0x68, 0x08,
0xC0, 0x00, 0x69, 0x08,
]
max_max_up_checker = [

View File

@@ -335,8 +335,8 @@ class CVCotMPatchExtensions(APPatchExtension):
rom_data.write_bytes(0x679A60, patches.kickless_roc_height_shortener)
# Give the player their Start Inventory upon entering their name on a new file.
rom_data.write_bytes(0x7F70, [0x00, 0x48, 0x87, 0x46, 0x00, 0x00, 0x68, 0x08])
rom_data.write_bytes(0x680000, patches.start_inventory_giver)
rom_data.write_bytes(0x7F70, [0x00, 0x48, 0x87, 0x46, 0x00, 0x00, 0x69, 0x08])
rom_data.write_bytes(0x690000, patches.start_inventory_giver)
# Prevent Max Ups from exceeding 255.
rom_data.write_bytes(0x5E170, [0x00, 0x4A, 0x97, 0x46, 0x00, 0x00, 0x6A, 0x08])

View File

@@ -23,6 +23,7 @@ DATA_LOCATIONS = {
"DexSanityFlag": (0x1A71, 19),
"GameStatus": (0x1A84, 0x01),
"Money": (0x141F, 3),
"CurrentMap": (0x1436, 1),
"ResetCheck": (0x0100, 4),
# First and second Vermilion Gym trash can selection. Second is not used, so should always be 0.
# First should never be above 0x0F. This is just before Event Flags.
@@ -65,6 +66,7 @@ class PokemonRBClient(BizHawkClient):
self.banking_command = None
self.game_state = False
self.last_death_link = 0
self.current_map = 0
async def validate_rom(self, ctx):
game_name = await read(ctx.bizhawk_ctx, [(0x134, 12, "ROM")])
@@ -230,6 +232,10 @@ class PokemonRBClient(BizHawkClient):
}])
self.banking_command = None
if data["CurrentMap"][0] != self.current_map:
await ctx.send_msgs([{"cmd": "Bounce", "slots": [ctx.slot], "data": {"currentMap": data["CurrentMap"][0]}}])
self.current_map = data["CurrentMap"][0]
# VICTORY
if data["EventFlag"][280] & 1 and not ctx.finished_game:

View File

@@ -15,7 +15,7 @@ As we are using BizHawk, this guide is only applicable to Windows and Linux syst
## Optional Software
- [Pokémon Red and Blue Archipelago Map Tracker](https://github.com/coveleski/rb_tracker/releases/latest), for use with [PopTracker](https://github.com/black-sliver/PopTracker/releases)
- [Pokémon Red and Blue Archipelago Map Tracker](https://github.com/palex00/rb_tracker/releases/latest), for use with [PopTracker](https://github.com/black-sliver/PopTracker/releases)
## Configuring BizHawk
@@ -109,7 +109,7 @@ server uses password, type in the bottom textfield `/connect <address>:<port> [p
Pokémon Red and Blue has a fully functional map tracker that supports auto-tracking.
1. Download [Pokémon Red and Blue Archipelago Map Tracker](https://github.com/coveleski/rb_tracker/releases/latest) and [PopTracker](https://github.com/black-sliver/PopTracker/releases).
1. Download [Pokémon Red and Blue Archipelago Map Tracker](https://github.com/palex00/rb_tracker/releases/latest) and [PopTracker](https://github.com/black-sliver/PopTracker/releases).
2. Open PopTracker, and load the Pokémon Red and Blue pack.
3. Click on the "AP" symbol at the top.
4. Enter the AP address, slot name and password.

View File

@@ -16,7 +16,7 @@ Al usar BizHawk, esta guía solo es aplicable en los sistemas de Windows y Linux
## Software Opcional
- [Tracker de mapa para Pokémon Red and Blue Archipelago](https://github.com/coveleski/rb_tracker/releases/latest), para usar con [PopTracker](https://github.com/black-sliver/PopTracker/releases)
- [Tracker de mapa para Pokémon Red and Blue Archipelago](https://github.com/palex00/rb_tracker/releases/latest), para usar con [PopTracker](https://github.com/black-sliver/PopTracker/releases)
## Configurando BizHawk
@@ -114,7 +114,7 @@ presiona enter (si el servidor usa contraseña, escribe en el campo de texto inf
Pokémon Red and Blue tiene un mapa completamente funcional que soporta seguimiento automático.
1. Descarga el [Tracker de mapa para Pokémon Red and Blue Archipelago](https://github.com/coveleski/rb_tracker/releases/latest) y [PopTracker](https://github.com/black-sliver/PopTracker/releases).
1. Descarga el [Tracker de mapa para Pokémon Red and Blue Archipelago](https://github.com/palex00/rb_tracker/releases/latest) y [PopTracker](https://github.com/black-sliver/PopTracker/releases).
2. Abre PopTracker, y carga el pack de Pokémon Red and Blue.
3. Haz clic en el símbolo "AP" en la parte superior.
4. Ingresa la dirección de AP, nombre del slot y contraseña (si es que hay).

View File

@@ -386,7 +386,7 @@ coppper_slot_machine = skill_recipe(ModMachine.copper_slot_machine, ModSkill.luc
Forageable.salmonberry: 1, Material.clay: 1, Trash.joja_cola: 1}, ModNames.luck_skill)
gold_slot_machine = skill_recipe(ModMachine.gold_slot_machine, ModSkill.luck, 4, {MetalBar.gold: 15, ModMachine.copper_slot_machine: 1}, ModNames.luck_skill)
iridium_slot_machine = skill_recipe(ModMachine.iridium_slot_machine, ModSkill.luck, 4, {MetalBar.iridium: 15, ModMachine.gold_slot_machine: 1}, ModNames.luck_skill)
radioactive_slot_machine = skill_recipe(ModMachine.radioactive_slot_machine, ModSkill.luck, 4, {MetalBar.radioactive: 15, ModMachine.iridium_slot_machine: 1}, ModNames.luck_skill)
iridium_slot_machine = skill_recipe(ModMachine.iridium_slot_machine, ModSkill.luck, 6, {MetalBar.iridium: 15, ModMachine.gold_slot_machine: 1}, ModNames.luck_skill)
radioactive_slot_machine = skill_recipe(ModMachine.radioactive_slot_machine, ModSkill.luck, 8, {MetalBar.radioactive: 15, ModMachine.iridium_slot_machine: 1}, ModNames.luck_skill)
all_crafting_recipes_by_name = {recipe.item: recipe for recipe in all_crafting_recipes}

View File

@@ -6,7 +6,7 @@ id,name,classification,groups,mod_name
18,Greenhouse,progression,COMMUNITY_REWARD,
19,Glittering Boulder Removed,progression,COMMUNITY_REWARD,
20,Minecarts Repair,useful,COMMUNITY_REWARD,
21,Bus Repair,progression,COMMUNITY_REWARD,
21,Bus Repair,progression,"COMMUNITY_REWARD,DESERT_TRANSPORTATION",
22,Progressive Movie Theater,"progression,trap",COMMUNITY_REWARD,
23,Stardrop,progression,,
24,Progressive Backpack,progression,,
@@ -63,8 +63,8 @@ id,name,classification,groups,mod_name
77,Combat Level,progression,SKILL_LEVEL_UP,
78,Earth Obelisk,progression,WIZARD_BUILDING,
79,Water Obelisk,progression,WIZARD_BUILDING,
80,Desert Obelisk,progression,WIZARD_BUILDING,
81,Island Obelisk,progression,"WIZARD_BUILDING,GINGER_ISLAND",
80,Desert Obelisk,progression,"WIZARD_BUILDING,DESERT_TRANSPORTATION",
81,Island Obelisk,progression,"WIZARD_BUILDING,GINGER_ISLAND,ISLAND_TRANSPORTATION",
82,Junimo Hut,useful,WIZARD_BUILDING,
83,Gold Clock,progression,WIZARD_BUILDING,
84,Progressive Coop,progression,BUILDING,
@@ -242,7 +242,7 @@ id,name,classification,groups,mod_name
257,Peach Sapling,progression,"RESOURCE_PACK,RESOURCE_PACK_USEFUL,CROPSANITY",
258,Banana Sapling,progression,"GINGER_ISLAND,RESOURCE_PACK,RESOURCE_PACK_USEFUL,CROPSANITY",
259,Mango Sapling,progression,"GINGER_ISLAND,RESOURCE_PACK,RESOURCE_PACK_USEFUL,CROPSANITY",
260,Boat Repair,progression,GINGER_ISLAND,
260,Boat Repair,progression,"GINGER_ISLAND,ISLAND_TRANSPORTATION",
261,Open Professor Snail Cave,progression,GINGER_ISLAND,
262,Island North Turtle,progression,"GINGER_ISLAND,WALNUT_PURCHASE",
263,Island West Turtle,progression,"GINGER_ISLAND,WALNUT_PURCHASE",
1 id name classification groups mod_name
6 18 Greenhouse progression COMMUNITY_REWARD
7 19 Glittering Boulder Removed progression COMMUNITY_REWARD
8 20 Minecarts Repair useful COMMUNITY_REWARD
9 21 Bus Repair progression COMMUNITY_REWARD COMMUNITY_REWARD,DESERT_TRANSPORTATION
10 22 Progressive Movie Theater progression,trap COMMUNITY_REWARD
11 23 Stardrop progression
12 24 Progressive Backpack progression
63 77 Combat Level progression SKILL_LEVEL_UP
64 78 Earth Obelisk progression WIZARD_BUILDING
65 79 Water Obelisk progression WIZARD_BUILDING
66 80 Desert Obelisk progression WIZARD_BUILDING WIZARD_BUILDING,DESERT_TRANSPORTATION
67 81 Island Obelisk progression WIZARD_BUILDING,GINGER_ISLAND WIZARD_BUILDING,GINGER_ISLAND,ISLAND_TRANSPORTATION
68 82 Junimo Hut useful WIZARD_BUILDING
69 83 Gold Clock progression WIZARD_BUILDING
70 84 Progressive Coop progression BUILDING
242 257 Peach Sapling progression RESOURCE_PACK,RESOURCE_PACK_USEFUL,CROPSANITY
243 258 Banana Sapling progression GINGER_ISLAND,RESOURCE_PACK,RESOURCE_PACK_USEFUL,CROPSANITY
244 259 Mango Sapling progression GINGER_ISLAND,RESOURCE_PACK,RESOURCE_PACK_USEFUL,CROPSANITY
245 260 Boat Repair progression GINGER_ISLAND GINGER_ISLAND,ISLAND_TRANSPORTATION
246 261 Open Professor Snail Cave progression GINGER_ISLAND
247 262 Island North Turtle progression GINGER_ISLAND,WALNUT_PURCHASE
248 263 Island West Turtle progression GINGER_ISLAND,WALNUT_PURCHASE

View File

@@ -33,6 +33,8 @@ class Group(enum.Enum):
SKILL_MASTERY = enum.auto()
BUILDING = enum.auto()
WIZARD_BUILDING = enum.auto()
DESERT_TRANSPORTATION = enum.auto()
ISLAND_TRANSPORTATION = enum.auto()
ARCADE_MACHINE_BUFFS = enum.auto()
BASE_RESOURCE = enum.auto()
WARP_TOTEM = enum.auto()

View File

@@ -1,61 +1,122 @@
from typing import Any
tww_options_presets: dict[str, dict[str, Any]] = {
"Tournament S7": {
"Tournament S8": {
"progression_dungeon_secrets": True,
"progression_combat_secret_caves": True,
"progression_short_sidequests": True,
"progression_long_sidequests": True,
"progression_spoils_trading": True,
"progression_big_octos_gunboats": True,
"progression_mail": True,
"progression_platforms_rafts": True,
"progression_submarines": True,
"progression_big_octos_gunboats": True,
"progression_expensive_purchases": True,
"progression_island_puzzles": True,
"progression_misc": True,
"randomize_mapcompass": "startwith",
"randomize_bigkeys": "startwith",
"required_bosses": True,
"num_required_bosses": 3,
"num_required_bosses": 4,
"included_dungeons": ["Forsaken Fortress"],
"chest_type_matches_contents": True,
"logic_obscurity": "hard",
"randomize_dungeon_entrances": True,
"randomize_starting_island": True,
"add_shortcut_warps_between_dungeons": True,
"start_inventory_from_pool": {
"Telescope": 1,
"Wind Waker": 1,
"Goddess Tingle Statue": 1,
"Earth Tingle Statue": 1,
"Wind Tingle Statue": 1,
"Wind's Requiem": 1,
"Ballad of Gales": 1,
"Command Melody": 1,
"Earth God's Lyric": 1,
"Wind God's Aria": 1,
"Song of Passing": 1,
"Progressive Magic Meter": 2,
"Triforce Shard 1": 1,
"Triforce Shard 2": 1,
"Triforce Shard 3": 1,
"Skull Necklace": 20,
"Golden Feather": 20,
"Knight's Crest": 10,
"Green Chu Jelly": 15,
"Nayru's Pearl": 1,
"Din's Pearl": 1,
},
"start_location_hints": ["Ganon's Tower - Maze Chest"],
"start_location_hints": [
"Windfall Island - Chu Jelly Juice Shop - Give 15 Blue Chu Jelly",
"Ganon's Tower - Maze Chest",
],
"exclude_locations": [
"Outset Island - Orca - Give 10 Knight's Crests",
"Outset Island - Great Fairy",
"Windfall Island - Chu Jelly Juice Shop - Give 15 Green Chu Jelly",
"Windfall Island - Mrs. Marie - Give 1 Joy Pendant",
"Windfall Island - Mrs. Marie - Give 21 Joy Pendants",
"Windfall Island - Mrs. Marie - Give 40 Joy Pendants",
"Windfall Island - Maggie's Father - Give 20 Skull Necklaces",
"Dragon Roost Island - Rito Aerie - Give Hoskit 20 Golden Feathers",
"Windfall Island - Lenzo's House - Become Lenzo's Assistant",
"Windfall Island - Lenzo's House - Bring Forest Firefly",
"Windfall Island - Sam - Decorate the Town",
"Windfall Island - Kamo - Full Moon Photo",
"Windfall Island - Linda and Anton",
"Dragon Roost Island - Secret Cave",
"Greatfish Isle - Hidden Chest",
"Mother and Child Isles - Inside Mother Isle",
"Fire Mountain - Cave - Chest",
"Fire Mountain - Lookout Platform Chest",
"Fire Mountain - Lookout Platform - Destroy the Cannons",
"Fire Mountain - Big Octo",
"Mailbox - Letter from Hoskit's Girlfriend",
"Headstone Island - Top of the Island",
"Headstone Island - Submarine",
"Earth Temple - Behind Curtain Next to Hammer Button",
"The Great Sea - Goron Trading Reward",
"The Great Sea - Withered Trees",
"Private Oasis - Big Octo",
"Boating Course - Raft",
"Boating Course - Cave",
"Stone Watcher Island - Cave",
"Stone Watcher Island - Lookout Platform Chest",
"Stone Watcher Island - Lookout Platform - Destroy the Cannons",
"Overlook Island - Cave",
"Bird's Peak Rock - Cave",
"Pawprint Isle - Wizzrobe Cave",
"Thorned Fairy Island - Great Fairy",
"Thorned Fairy Island - Northeastern Lookout Platform - Destroy the Cannons",
"Thorned Fairy Island - Southwestern Lookout Platform - Defeat the Enemies",
"Eastern Fairy Island - Great Fairy",
"Eastern Fairy Island - Lookout Platform - Defeat the Cannons and Enemies",
"Western Fairy Island - Great Fairy",
"Southern Fairy Island - Great Fairy",
"Northern Fairy Island - Great Fairy",
"Western Fairy Island - Lookout Platform",
"Tingle Island - Ankle - Reward for All Tingle Statues",
"Tingle Island - Big Octo",
"Diamond Steppe Island - Big Octo",
"Rock Spire Isle - Cave",
"Rock Spire Isle - Beedle's Special Shop Ship - 500 Rupee Item",
"Rock Spire Isle - Beedle's Special Shop Ship - 950 Rupee Item",
"Rock Spire Isle - Beedle's Special Shop Ship - 900 Rupee Item",
"Rock Spire Isle - Western Lookout Platform - Destroy the Cannons",
"Rock Spire Isle - Eastern Lookout Platform - Destroy the Cannons",
"Rock Spire Isle - Center Lookout Platform",
"Rock Spire Isle - Southeast Gunboat",
"Shark Island - Cave",
"Horseshoe Island - Northwestern Lookout Platform",
"Horseshoe Island - Southeastern Lookout Platform",
"Flight Control Platform - Submarine",
"Star Island - Cave",
"Star Island - Lookout Platform",
"Star Belt Archipelago - Lookout Platform",
"Five-Star Isles - Lookout Platform - Destroy the Cannons",
"Five-Star Isles - Raft",
"Five-Star Isles - Submarine",
"Seven-Star Isles - Center Lookout Platform",
"Seven-Star Isles - Northern Lookout Platform",
"Seven-Star Isles - Southern Lookout Platform",
"Seven-Star Isles - Big Octo",
"Cyclops Reef - Lookout Platform - Defeat the Enemies",
"Two-Eye Reef - Lookout Platform",
"Two-Eye Reef - Big Octo Great Fairy",
"Five-Eye Reef - Lookout Platform",
"Six-Eye Reef - Lookout Platform - Destroy the Cannons",
"Six-Eye Reef - Submarine",
],
},
"Miniblins 2025": {

View File

@@ -76,10 +76,11 @@ at least normal.
A few presets are available on the [player options page](../player-options) for your convenience.
- **Tournament S7**: These are (as close to as possible) the settings used in the WWR Racing Server's
[Season 7 Tournament](https://docs.google.com/document/d/1mJj7an-DvpYilwNt-DdlFOy1fz5_NMZaPZvHeIekplc).
The preset features 3 required bosses and hard obscurity difficulty, and while the list of enabled progression options
may seem intimidating, the preset also excludes several locations.
- **Tournament S8**: These are (as close to as possible) the settings used in the WWR Racing Server's
[Season 8 Tournament](https://docs.google.com/document/d/1b8F5DL3P5fgsQC_URiwhpMfqTpsGh2M-KmtTdXVigh4).
The preset features 4 required bosses (with Helmaroc King guaranteed required), dungeon entrance rando, hard obscurity
difficulty, and a variety of overworld checks. While the list of enabled progression options may seem intimidating,
the preset also excludes several locations and starts you with a handful of items.
- **Miniblins 2025**: These are (as close to as possible) the settings used in the WWR Racing Server's
[2025 Season of Miniblins](https://docs.google.com/document/d/19vT68eU6PepD2BD2ZjR9ikElfqs8pXfqQucZ-TcscV8). This
preset is great if you're new to Wind Waker! There aren't too many locations in the world, and you only need to

View File

@@ -110,6 +110,14 @@ def get_pool_core(world: "TWWWorld") -> tuple[list[str], list[str]]:
else:
filler_pool.extend([item] * data.quantity)
# If the player starts with a sword, add one to the precollected items list and remove one from the item pool.
if world.options.sword_mode == "start_with_sword":
precollected_items.append("Progressive Sword")
progression_pool.remove("Progressive Sword")
# Or, if it's swordless mode, remove all swords from the item pool.
elif world.options.sword_mode == "swordless":
useful_pool = [item for item in useful_pool if item != "Progressive Sword"]
# Assign useful and filler items to item pools in the world.
world.random.shuffle(useful_pool)
world.random.shuffle(filler_pool)
@@ -141,17 +149,6 @@ def get_pool_core(world: "TWWWorld") -> tuple[list[str], list[str]]:
pool.extend(progression_pool)
num_items_left_to_place -= len(progression_pool)
# If the player starts with a sword, add one to the precollected items list and remove one from the item pool.
if world.options.sword_mode == "start_with_sword":
precollected_items.append("Progressive Sword")
num_items_left_to_place += 1
pool.remove("Progressive Sword")
# Or, if it's swordless mode, remove all swords from the item pool.
elif world.options.sword_mode == "swordless":
while "Progressive Sword" in pool:
num_items_left_to_place += 1
pool.remove("Progressive Sword")
# Place useful items, then filler items to fill out the remaining locations.
pool.extend([world.get_filler_item_name(strict=False) for _ in range(num_items_left_to_place)])

View File

@@ -496,70 +496,74 @@ class WargrooveContext(CommonContext):
async def game_watcher(ctx: WargrooveContext):
while not ctx.exit_event.is_set():
if ctx.syncing == True:
sync_msg = [{'cmd': 'Sync'}]
if ctx.locations_checked:
sync_msg.append({"cmd": "LocationChecks", "locations": list(ctx.locations_checked)})
await ctx.send_msgs(sync_msg)
ctx.syncing = False
sending = []
victory = False
for root, dirs, files in os.walk(ctx.game_communication_path):
for file in files:
if file == "deathLinkSend" and ctx.has_death_link:
with open(os.path.join(ctx.game_communication_path, file), 'r') as f:
failed_mission = f.read()
if ctx.slot is not None:
await ctx.send_death(f"{ctx.player_names[ctx.slot]} failed {failed_mission}")
os.remove(os.path.join(ctx.game_communication_path, file))
if file.find("send") > -1:
st = file.split("send", -1)[1]
sending = sending+[(int(st))]
os.remove(os.path.join(ctx.game_communication_path, file))
if file.find("victory") > -1:
victory = True
os.remove(os.path.join(ctx.game_communication_path, file))
if file == "unitSacrifice" or file == "unitSacrificeAI":
if ctx.has_sacrifice_summon:
stored_units_key = ctx.player_stored_units_key
if file == "unitSacrificeAI":
stored_units_key = ctx.ai_stored_units_key
try:
if ctx.syncing == True:
sync_msg = [{'cmd': 'Sync'}]
if ctx.locations_checked:
sync_msg.append({"cmd": "LocationChecks", "locations": list(ctx.locations_checked)})
await ctx.send_msgs(sync_msg)
ctx.syncing = False
sending = []
victory = False
for root, dirs, files in os.walk(ctx.game_communication_path):
for file in files:
if file == "deathLinkSend" and ctx.has_death_link:
with open(os.path.join(ctx.game_communication_path, file), 'r') as f:
unit_class = f.read()
message = [{"cmd": 'Set', "key": stored_units_key,
"default": [],
"want_reply": True,
"operations": [{"operation": "add", "value": [unit_class[:64]]}]}]
await ctx.send_msgs(message)
os.remove(os.path.join(ctx.game_communication_path, file))
if file == "unitSummonRequestAI" or file == "unitSummonRequest":
if ctx.has_sacrifice_summon:
stored_units_key = ctx.player_stored_units_key
if file == "unitSummonRequestAI":
stored_units_key = ctx.ai_stored_units_key
with open(os.path.join(ctx.game_communication_path, "unitSummonResponse"), 'w') as f:
if stored_units_key in ctx.stored_data:
stored_units = ctx.stored_data[stored_units_key]
if stored_units is None:
stored_units = []
wg1_stored_units = [unit for unit in stored_units if unit in ctx.unit_classes]
if len(wg1_stored_units) != 0:
summoned_unit = random.choice(wg1_stored_units)
message = [{"cmd": 'Set', "key": stored_units_key,
"default": [],
"want_reply": True,
"operations": [{"operation": "remove", "value": summoned_unit[:64]}]}]
await ctx.send_msgs(message)
f.write(summoned_unit)
os.remove(os.path.join(ctx.game_communication_path, file))
failed_mission = f.read()
if ctx.slot is not None:
await ctx.send_death(f"{ctx.player_names[ctx.slot]} failed {failed_mission}")
os.remove(os.path.join(ctx.game_communication_path, file))
if file.find("send") > -1:
st = file.split("send", -1)[1]
sending = sending+[(int(st))]
os.remove(os.path.join(ctx.game_communication_path, file))
if file.find("victory") > -1:
victory = True
os.remove(os.path.join(ctx.game_communication_path, file))
if file == "unitSacrifice" or file == "unitSacrificeAI":
if ctx.has_sacrifice_summon:
stored_units_key = ctx.player_stored_units_key
if file == "unitSacrificeAI":
stored_units_key = ctx.ai_stored_units_key
with open(os.path.join(ctx.game_communication_path, file), 'r') as f:
unit_class = f.read()
message = [{"cmd": 'Set', "key": stored_units_key,
"default": [],
"want_reply": True,
"operations": [{"operation": "add", "value": [unit_class[:64]]}]}]
await ctx.send_msgs(message)
os.remove(os.path.join(ctx.game_communication_path, file))
if file == "unitSummonRequestAI" or file == "unitSummonRequest":
if ctx.has_sacrifice_summon:
stored_units_key = ctx.player_stored_units_key
if file == "unitSummonRequestAI":
stored_units_key = ctx.ai_stored_units_key
with open(os.path.join(ctx.game_communication_path, "unitSummonResponse"), 'w') as f:
if stored_units_key in ctx.stored_data:
stored_units = ctx.stored_data[stored_units_key]
if stored_units is None:
stored_units = []
wg1_stored_units = [unit for unit in stored_units if unit in ctx.unit_classes]
if len(wg1_stored_units) != 0:
summoned_unit = random.choice(wg1_stored_units)
message = [{"cmd": 'Set', "key": stored_units_key,
"default": [],
"want_reply": True,
"operations": [{"operation": "remove", "value": summoned_unit[:64]}]}]
await ctx.send_msgs(message)
f.write(summoned_unit)
os.remove(os.path.join(ctx.game_communication_path, file))
ctx.locations_checked = sending
message = [{"cmd": 'LocationChecks', "locations": sending}]
await ctx.send_msgs(message)
if not ctx.finished_game and victory:
await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}])
ctx.finished_game = True
await asyncio.sleep(0.1)
ctx.locations_checked = sending
message = [{"cmd": 'LocationChecks', "locations": sending}]
await ctx.send_msgs(message)
if not ctx.finished_game and victory:
await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}])
ctx.finished_game = True
await asyncio.sleep(0.1)
except Exception as err:
logger.warn("Exception in communication thread, a check may not have been sent: " + str(err))
def print_error_and_close(msg):