Skip to content

Commit

Permalink
Merge branch 'main' into core/allow-more-iterables-in-option-parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Jouramie authored Mar 1, 2024
2 parents 2954a7d + 983da12 commit a27f4c5
Show file tree
Hide file tree
Showing 16 changed files with 219 additions and 21 deletions.
4 changes: 2 additions & 2 deletions data/options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
# A. This is a .yaml file. You are allowed to use most characters.
# To test if your yaml is valid or not, you can use this website:
# http://www.yamllint.com/
# You can also verify your Archipelago settings are valid at this site:
# You can also verify that your Archipelago options are valid at this site:
# https://archipelago.gg/check

# Your name in-game. Spaces will be replaced with underscores and there is a 16-character limit.
# Your name in-game, limited to 16 characters.
# {player} will be replaced with the player's slot number.
# {PLAYER} will be replaced with the player's slot number, if that slot number is greater than 1.
# {number} will be replaced with the counter value of the name.
Expand Down
2 changes: 1 addition & 1 deletion docs/network protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ Sent to the server to update on the sender's status. Examples include readiness
#### Arguments
| Name | Type | Notes |
| ---- | ---- | ----- |
| status | ClientStatus\[int\] | One of [Client States](#Client-States). Send as int. Follow the link for more information. |
| status | ClientStatus\[int\] | One of [Client States](#ClientStatus). Send as int. Follow the link for more information. |

### Say
Basic chat command which sends text to the server to be distributed to other clients.
Expand Down
5 changes: 3 additions & 2 deletions docs/world api.md
Original file line number Diff line number Diff line change
Expand Up @@ -738,8 +738,9 @@ def generate_output(self, output_directory: str) -> None:

If the game client needs to know information about the generated seed, a preferred method of transferring the data
is through the slot data. This is filled with the `fill_slot_data` method of your world by returning
a `Dict[str, Any]`, but, to not waste resources, should be limited to data that is absolutely necessary. Slot data is
sent to your client once it has successfully [connected](network%20protocol.md#connected).
a `dict` with `str` keys that can be serialized with json.
But, to not waste resources, it should be limited to data that is absolutely necessary. Slot data is sent to your client
once it has successfully [connected](network%20protocol.md#connected).
If you need to know information about locations in your world, instead of propagating the slot data, it is preferable
to use [LocationScouts](network%20protocol.md#locationscouts), since that data already exists on the server. The most
common usage of slot data is sending option results that the client needs to be aware of.
Expand Down
14 changes: 10 additions & 4 deletions worlds/AutoWorld.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import sys
import time
from dataclasses import make_dataclass
from typing import Any, Callable, ClassVar, Dict, Set, Tuple, FrozenSet, List, Optional, TYPE_CHECKING, TextIO, Type, \
Union
from typing import (Any, Callable, ClassVar, Dict, FrozenSet, List, Mapping,
Optional, Set, TextIO, Tuple, TYPE_CHECKING, Type, Union)

from Options import PerGameCommonOptions
from BaseClasses import CollectionState
Expand Down Expand Up @@ -365,13 +365,19 @@ def generate_output(self, output_directory: str) -> None:
If you need any last-second randomization, use self.random instead."""
pass

def fill_slot_data(self) -> Dict[str, Any]: # json of WebHostLib.models.Slot
"""Fill in the `slot_data` field in the `Connected` network package.
def fill_slot_data(self) -> Mapping[str, Any]: # json of WebHostLib.models.Slot
"""What is returned from this function will be in the `slot_data` field
in the `Connected` network package.
It should be a `dict` with `str` keys, and should be serializable with json.
This is a way the generator can give custom data to the client.
The client will receive this as JSON in the `Connected` response.
The generation does not wait for `generate_output` to complete before calling this.
`threading.Event` can be used if you need to wait for something from `generate_output`."""
# The reason for the `Mapping` type annotation, rather than `dict`
# is so that type checkers won't worry about the mutability of `dict`,
# so you can have more specific typing in your world implementation.
return {}

def extend_hint_information(self, hint_data: Dict[int, Dict[int, str]]):
Expand Down
1 change: 0 additions & 1 deletion worlds/blasphemous/docs/setup_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ Optional:
- Quick Prie Dieu warp mod: [GitHub](https://github.com/BadMagic100/Blasphemous-PrieWarp)
- Boots of Pleading mod: [GitHub](https://github.com/BrandenEK/Blasphemous-Boots-of-Pleading)
- Double Jump mod: [GitHub](https://github.com/BrandenEK/Blasphemous-Double-Jump)
- PopTracker pack: [GitHub](https://github.com/sassyvania/Blasphemous-Randomizer-Maptracker)

## Mod Installer (Recommended)

Expand Down
1 change: 1 addition & 0 deletions worlds/dark_souls_3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

class DarkSouls3Web(WebWorld):
bug_report_page = "https://github.com/Marechal-L/Dark-Souls-III-Archipelago-client/issues"
theme = "stone"
setup_en = Tutorial(
"Multiworld Setup Guide",
"A guide to setting up the Archipelago Dark Souls III randomizer on your computer.",
Expand Down
2 changes: 1 addition & 1 deletion worlds/dark_souls_3/docs/setup_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

## General Concept

<span style="color:tomato">
<span style="color:#ff7800">
**This mod can ban you permanently from the FromSoftware servers if used online.**
</span>
The Dark Souls III AP Client is a dinput8.dll triggered when launching Dark Souls III. This .dll file will launch a command
Expand Down
2 changes: 1 addition & 1 deletion worlds/dark_souls_3/docs/setup_fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ permettant de lire des informations de la partie et écrire des commandes pour i

## Procédures d'installation

<span style="color:tomato">
<span style="color:#ff7800">
**Il y a des risques de bannissement permanent des serveurs FromSoftware si ce mod est utilisé en ligne.**
</span>
Ce client a été testé sur la version Steam officielle du jeu (v1.15/1.35), peu importe les DLCs actuellement installés.
Expand Down
12 changes: 11 additions & 1 deletion worlds/pokemon_emerald/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class PokemonEmeraldWebWorld(WebWorld):
Webhost info for Pokemon Emerald
"""
theme = "ocean"

setup_en = Tutorial(
"Multiworld Setup Guide",
"A guide to playing Pokémon Emerald with Archipelago.",
Expand All @@ -45,7 +46,16 @@ class PokemonEmeraldWebWorld(WebWorld):
["Zunawe"]
)

tutorials = [setup_en]
setup_es = Tutorial(
"Guía de configuración para Multiworld",
"Una guía para jugar Pokémon Emerald en Archipelago",
"Español",
"setup_es.md",
"setup/es",
["nachocua"]
)

tutorials = [setup_en, setup_es]


class PokemonEmeraldSettings(settings.Group):
Expand Down
75 changes: 75 additions & 0 deletions worlds/pokemon_emerald/docs/rom changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
## QoL

- The catch tutorial and cutscenes during your first visit to Petalburg are skipped
- The match call tutorial after you leave Devon Corp is skipped
- Cycling and running is allowed in every map (some exceptions like Fortree and Pacifidlog)
- When you run out of Repel steps, you'll be prompted to use another one if you have more in your bag
- Text is always rendered in its entirety on the first frame (instant text)
- With an option set, text will advance if A is held
- The message explaining that the trainer is about to send out a new pokemon is shortened to fit on two lines so that
you can still read the species when deciding whether to change pokemon
- The Pokemon Center Nurse dialogue is entirely removed except for the final text box
- When receiving TMs and HMs, the move that it teaches is consistently displayed in the "received item" message (by
default, certain ways of receiving items would only display the TM/HM number)
- The Pokedex starts in national mode
- The Oldale Pokemart sells Poke Balls at the start of the game
- Pauses during battles (e.g. the ~1 second pause at the start of a turn before an opponent uses a potion) are shorter
by 62.5%
- The sliding animation for trainers and wild pokemon at the start of a battle runs at double speed.
- Bag space was greatly expanded (there is room for one stack of every unique item in every pocket, plus a little bit
extra for some pockets)
- Save data format was changed as a result of this. Shrank some unused space and removed some multiplayer phrases from
the save data.
- Pretty much any code that checks for bag space is ignored or bypassed (this sounds dangerous, but with expanded bag
space you should pretty much never have a full bag unless you're trying to fill it up, and skipping those checks
greatly simplifies detecting when items are picked up)
- Pokemon are never disobedient
- When moving in the overworld, set the input priority based on the most recently pressed direction rather than by some
predetermined priority
- Shoal cave changes state every time you reload the map and is no longer tied to the RTC
- Increased safari zone steps from 500 to 50000
- Trainers will not approach the player if the blind trainers option is set
- Changed trade evolutions to be possible without trading:
- Politoed: Use King's Rock in bag menu
- Alakazam: Level 37
- Machamp: Level 37
- Golem: Level 37
- Slowking: Use King's Rock in bag menu
- Gengar: Level 37
- Steelix: Use Metal Coat in bag menu
- Kingdra: Use Dragon Scale in bag menu
- Scizor: Use Metal Coat in bag menu
- Porygon2: Use Up-Grade in bag menu
- Milotic: Level 30
- Huntail: Use Deep Sea Tooth in bag menu
- Gorebyss: Use Deep Sea Scale in bag menu

## Game State Changes/Softlock Prevention

- Mr. Briney never disappears or stops letting you use his ferry
- Prevent the player from flying or surfing until they have received the Pokedex
- The S.S. Tidal will be available at all times if you have the option enabled
- Some NPCs or tiles are removed on the creation of a new save file based on player options
- Ensured that every species has some damaging move by level 5
- Route 115 may have strength boulders between the beach and cave entrance based on player options
- The Petalburg Gym is set up based on your player options rather than after the first 4 gyms
- The E4 guards will actually check all your badges (or gyms beaten based on your options) instead of just the Feather
Badge
- Steven cuts the conversation short in Granite Cave if you don't have the Letter
- Dock checks that you have the Devon Goods before asking you to deliver them (and thus opening the museum)
- Rydel gives you both bikes at the same time
- The man in Pacifidlog who gives you Frustration and Return will give you both at the same time, does not check
friendship first, and no longer has any behavior related to the RTC
- The woman who gives you the Soothe Bell in Slateport does not check friendship
- When trading the Scanner with Captain Stern, you will receive both the Deep Sea Tooth and Deep Sea Scale

## Misc

- You can no longer try to switch bikes in the bike shop
- The Seashore House only rewards you with 1 Soda Pop instead of 6
- Many small changes that make it possible to swap single battles to double battles
- Includes some safeguards against two trainers seeing you and initiating a battle while one or both of them are
"single trainer double battles"
- Game now properly waits on vblank instead of spinning in a while loop
- Misc small changes to text for consistency
- Many bugfixes to the vanilla game code
74 changes: 74 additions & 0 deletions worlds/pokemon_emerald/docs/setup_es.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Guía de Configuración para Pokémon Emerald

## Software Requerido

- [Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases)
- Una ROM de Pokémon Emerald en Inglés. La comunidad de Archipelago no puede proveerla.
- [BizHawk](https://tasvideos.org/BizHawk/ReleaseHistory) 2.7 o posterior

### Configuración de BizHawk

Una vez que hayas instalado BizHawk, abre `EmuHawk.exe` y cambia las siguientes configuraciones:

- Si estás usando BizHawk 2.7 o 2.8, ve a `Config > Customize`. En la pestaña Advanced, cambia el Lua Core de
`NLua+KopiLua` a `Lua+LuaInterface`, luego reinicia EmuHawk. (Si estás usando BizHawk 2.9, puedes saltar este paso.)
- En `Config > Customize`, activa la opción "Run in background" para prevenir desconexiones del cliente mientras
la aplicación activa no sea EmuHawk.
- Abre el archivo `.gba` en EmuHawk y luego ve a `Config > Controllers…` para configurar los controles. Si no puedes
hacer clic en `Controllers…`, debes abrir cualquier ROM `.gba` primeramente.
- Considera limpiar tus macros y atajos en `Config > Hotkeys…` si no quieres usarlas de manera intencional. Para
limpiarlas, selecciona el atajo y presiona la tecla Esc.

## Software Opcional

- [Pokémon Emerald AP Tracker](https://github.com/AliceMousie/emerald-ap-tracker/releases/latest), para usar con
[PopTracker](https://github.com/black-sliver/PopTracker/releases)

## Generando y Parcheando el Juego

1. Crea tu archivo de configuración (YAML). Puedes hacerlo en
[Página de Opciones de Pokémon Emerald](../../../games/Pokemon%20Emerald/player-options).
2. Sigue las instrucciones generales de Archipelago para [Generar un juego]
(../../Archipelago/setup/en#generating-a-game). Esto generará un archivo de salida (output file) para ti. Tu archivo
de parche tendrá la extensión de archivo`.apemerald`.
3. Abre `ArchipelagoLauncher.exe`
4. Selecciona "Open Patch" en el lado derecho y elige tu archivo de parcheo.
5. Si esta es la primera vez que vas a parchear, se te pedirá que selecciones la ROM sin parchear.
6. Un archivo parcheado con extensión `.gba` será creado en el mismo lugar que el archivo de parcheo.
7. La primera vez que abras un archivo parcheado con el BizHawk Client, se te preguntará donde está localizado
`EmuHawk.exe` en tu instalación de BizHawk.

Si estás jugando una seed Single-Player y no te interesa el auto-tracking o las pistas, puedes parar aquí, cierra el
cliente, y carga la ROM ya parcheada en cualquier emulador. Pero para partidas multi-worlds y para otras
implementaciones de Archipelago, continúa usando BizHawk como tu emulador

## Conectando con el Servidor

Por defecto, al abrir un archivo parcheado, se harán de manera automática 1-5 pasos. Aun así, ten en cuenta lo
siguiente en caso de que debas cerrar y volver a abrir la ventana en mitad de la partida por algún motivo.

1. Pokémon Emerald usa el Archipelago BizHawk Client. Si el cliente no se encuentra abierto al abrir la rom
parcheada, puedes volver a abrirlo desde el Archipelago Launcher.
2. Asegúrate que EmuHawk está corriendo la ROM parcheada.
3. En EmuHawk, ve a `Tools > Lua Console`. Debes tener esta ventana abierta mientras juegas.
4. En la ventana de Lua Console, ve a `Script > Open Script…`.
5. Ve a la carpeta donde está instalado Archipelago y abre `data/lua/connector_bizhawk_generic.lua`.
6. El emulador y el cliente eventualmente se conectarán uno con el otro. La ventana de BizHawk Client indicará que te
has conectado y reconocerá Pokémon Emerald.
7. Para conectar el cliente con el servidor, ingresa la dirección y el puerto de la sala (ej. `archipelago.gg:38281`)
en el campo de texto que se encuentra en la parte superior del cliente y haz click en Connect.

Ahora deberías poder enviar y recibir ítems. Debes seguir estos pasos cada vez que quieras reconectarte. Es seguro
jugar de manera offline; se sincronizará todo cuando te vuelvas a conectar.

## Tracking Automático

Pokémon Emerald tiene un Map Tracker completamente funcional que soporta auto-tracking.

1. Descarga [Pokémon Emerald AP Tracker](https://github.com/AliceMousie/emerald-ap-tracker/releases/latest) y
[PopTracker](https://github.com/black-sliver/PopTracker/releases).
2. Coloca la carpeta del Tracker en la carpeta packs/ dentro de la carpeta de instalación del PopTracker.
3. Abre PopTracker, y carga el Pack de Pokémon Emerald Map Tracker.
4. Para utilizar el auto-tracking, haz click en el símbolo "AP" que se encuentra en la parte superior.
5. Entra la dirección del Servidor de Archipelago (la misma a la que te conectaste para jugar), nombre del jugador, y
contraseña (deja vacío este campo en caso de no utilizar contraseña).
4 changes: 0 additions & 4 deletions worlds/witness/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ class WitnessWorld(World):
"""
game = "The Witness"
topology_present = False

StaticWitnessLogic()
StaticWitnessLocations()
StaticWitnessItems()
web = WitnessWebWorld()

options_dataclass = TheWitnessOptions
Expand Down
12 changes: 9 additions & 3 deletions worlds/witness/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,14 @@ def get_filler_items(self, quantity: int) -> Dict[str, int]:

# Read trap configuration data.
trap_weight = self._world.options.trap_percentage / 100
filler_weight = 1 - trap_weight
trap_items = self._world.options.trap_weights.value

if not sum(trap_items.values()):
trap_weight = 0

# Add filler items to the list.
filler_weight = 1 - trap_weight

filler_items: Dict[str, float]
filler_items = {name: data.definition.weight if isinstance(data.definition, WeightedItemDefinition) else 1
for (name, data) in self.item_data.items() if data.definition.category is ItemCategory.FILLER}
Expand All @@ -187,8 +192,6 @@ def get_filler_items(self, quantity: int) -> Dict[str, int]:

# Add trap items.
if trap_weight > 0:
trap_items = {name: data.definition.weight if isinstance(data.definition, WeightedItemDefinition) else 1
for (name, data) in self.item_data.items() if data.definition.category is ItemCategory.TRAP}
filler_items.update({name: base_weight * trap_weight / sum(trap_items.values())
for name, base_weight in trap_items.items() if base_weight > 0})

Expand Down Expand Up @@ -267,3 +270,6 @@ def get_progressive_item_ids_in_pool(self) -> Dict[int, List[int]]:
output[item.ap_code] = [StaticWitnessItems.item_data[child_item].ap_code
for child_item in item.definition.child_item_names]
return output


StaticWitnessItems()
3 changes: 3 additions & 0 deletions worlds/witness/locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,3 +569,6 @@ def add_location_late(self, entity_name: str):
entity_hex = StaticWitnessLogic.ENTITIES_BY_NAME[entity_name]["entity_hex"]
self.CHECK_LOCATION_TABLE[entity_hex] = entity_name
self.CHECK_PANELHEX_TO_ID[entity_hex] = StaticWitnessLocations.get_id(entity_hex)


StaticWitnessLocations()
26 changes: 25 additions & 1 deletion worlds/witness/options.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from dataclasses import dataclass
from Options import Toggle, DefaultOnToggle, Range, Choice, PerGameCommonOptions

from schema import Schema, And, Optional

from Options import Toggle, DefaultOnToggle, Range, Choice, PerGameCommonOptions, OptionDict

from worlds.witness.static_logic import WeightedItemDefinition, ItemCategory, StaticWitnessLogic


class DisableNonRandomizedPuzzles(Toggle):
Expand Down Expand Up @@ -172,6 +177,24 @@ class TrapPercentage(Range):
default = 20


class TrapWeights(OptionDict):
"""Specify the weights determining how many copies of each trap item will be in your itempool.
If you don't want a specific type of trap, you can set the weight for it to 0 (Do not delete the entry outright!).
If you set all trap weights to 0, you will get no traps, bypassing the "Trap Percentage" option."""

display_name = "Trap Weights"
schema = Schema({
trap_name: And(int, lambda n: n >= 0)
for trap_name, item_definition in StaticWitnessLogic.all_items.items()
if isinstance(item_definition, WeightedItemDefinition) and item_definition.category is ItemCategory.TRAP
})
default = {
trap_name: item_definition.weight
for trap_name, item_definition in StaticWitnessLogic.all_items.items()
if isinstance(item_definition, WeightedItemDefinition) and item_definition.category is ItemCategory.TRAP
}


class PuzzleSkipAmount(Range):
"""Adds this number of Puzzle Skips into the pool, if there is room. Puzzle Skips let you skip one panel.
Works on most panels in the game - The only big exception is The Challenge."""
Expand Down Expand Up @@ -237,6 +260,7 @@ class TheWitnessOptions(PerGameCommonOptions):
early_caves: EarlyCaves
elevators_come_to_you: ElevatorsComeToYou
trap_percentage: TrapPercentage
trap_weights: TrapWeights
puzzle_skip_amount: PuzzleSkipAmount
hint_amount: HintAmount
area_hint_percentage: AreaHintPercentage
Expand Down
3 changes: 3 additions & 0 deletions worlds/witness/static_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,6 @@ def __init__(self):
self.EP_TO_OBELISK_SIDE.update(self.sigma_normal.EP_TO_OBELISK_SIDE)

self.ENTITY_ID_TO_NAME.update(self.sigma_normal.ENTITY_ID_TO_NAME)


StaticWitnessLogic()

0 comments on commit a27f4c5

Please sign in to comment.