mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-05-27 11:29:56 -07:00
Merge remote-tracking branch 'remotes/origin/main' into Satisfactory_ToBeVerified
# Conflicts: # README.md
This commit is contained in:
@@ -260,11 +260,7 @@ class HatInTimeWorld(World):
|
||||
f"{item_name} ({self.multiworld.get_player_name(loc.item.player)})")
|
||||
|
||||
slot_data["ShopItemNames"] = shop_item_names
|
||||
|
||||
for name, value in self.options.as_dict(*self.options_dataclass.type_hints).items():
|
||||
if name in slot_data_options:
|
||||
slot_data[name] = value
|
||||
|
||||
slot_data.update(self.options.as_dict(*slot_data_options))
|
||||
return slot_data
|
||||
|
||||
def extend_hint_information(self, hint_data: Dict[int, Dict[int, str]]):
|
||||
|
||||
@@ -505,10 +505,11 @@ class ALTTPWorld(World):
|
||||
def pre_fill(self):
|
||||
from Fill import fill_restrictive, FillError
|
||||
attempts = 5
|
||||
all_state = self.multiworld.get_all_state(use_cache=False)
|
||||
all_state = self.multiworld.get_all_state(perform_sweep=False)
|
||||
crystals = [self.create_item(name) for name in ['Red Pendant', 'Blue Pendant', 'Green Pendant', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 7', 'Crystal 5', 'Crystal 6']]
|
||||
for crystal in crystals:
|
||||
all_state.remove(crystal)
|
||||
all_state.sweep_for_advancements()
|
||||
crystal_locations = [self.get_location('Turtle Rock - Prize'),
|
||||
self.get_location('Eastern Palace - Prize'),
|
||||
self.get_location('Desert Palace - Prize'),
|
||||
|
||||
@@ -207,11 +207,7 @@ class EnemyScaling(DefaultOnToggle):
|
||||
|
||||
|
||||
class BlasphemousDeathLink(DeathLink):
|
||||
"""
|
||||
When you die, everyone dies. The reverse is also true.
|
||||
|
||||
Note that Guilt Fragments will not appear when killed by Death Link.
|
||||
"""
|
||||
__doc__ = DeathLink.__doc__ + "\n\n Note that Guilt Fragments will not appear when killed by death link."
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -175,11 +175,7 @@ class DamageMultiplier(Range):
|
||||
|
||||
|
||||
class BRCDeathLink(DeathLink):
|
||||
"""
|
||||
When you die, everyone dies. The reverse is also true.
|
||||
|
||||
This can be changed later in the options menu inside the Archipelago phone app.
|
||||
"""
|
||||
__doc__ = DeathLink.__doc__ + "\n\n This can be changed later in the options menu inside the Archipelago phone app."
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from dataclasses import dataclass
|
||||
from Options import (OptionGroup, Choice, DefaultOnToggle, ItemsAccessibility, PerGameCommonOptions, Range, Toggle,
|
||||
StartInventoryPool)
|
||||
StartInventoryPool, DeathLink)
|
||||
|
||||
|
||||
class CharacterStages(Choice):
|
||||
@@ -507,12 +507,11 @@ class WindowColorA(Range):
|
||||
default = 8
|
||||
|
||||
|
||||
class DeathLink(Choice):
|
||||
"""
|
||||
When you die, everyone dies. Of course the reverse is true too.
|
||||
Explosive: Makes received DeathLinks kill you via the Magical Nitro explosion instead of the normal death animation.
|
||||
"""
|
||||
display_name = "DeathLink"
|
||||
class CV64DeathLink(Choice):
|
||||
__doc__ = (DeathLink.__doc__ + "\n\n Explosive: Makes received death links kill you via the Magical Nitro " +
|
||||
"explosion instead of the normal death animation.")
|
||||
|
||||
display_name = "Death Link"
|
||||
option_off = 0
|
||||
alias_no = 0
|
||||
alias_true = 1
|
||||
@@ -575,7 +574,7 @@ class CV64Options(PerGameCommonOptions):
|
||||
map_lighting: MapLighting
|
||||
fall_guard: FallGuard
|
||||
cinematic_experience: CinematicExperience
|
||||
death_link: DeathLink
|
||||
death_link: CV64DeathLink
|
||||
|
||||
|
||||
cv64_option_groups = [
|
||||
@@ -584,7 +583,7 @@ cv64_option_groups = [
|
||||
RenonFightCondition, VincentFightCondition, BadEndingCondition, IncreaseItemLimit, NerfHealingItems,
|
||||
LoadingZoneHeals, InvisibleItems, DropPreviousSubWeapon, PermanentPowerUps, IceTrapPercentage,
|
||||
IceTrapAppearance, DisableTimeRestrictions, SkipGondolas, SkipWaterwayBlocks, Countdown, BigToss, PantherDash,
|
||||
IncreaseShimmySpeed, FallGuard, DeathLink
|
||||
IncreaseShimmySpeed, FallGuard, CV64DeathLink
|
||||
]),
|
||||
OptionGroup("cosmetics", [
|
||||
WindowColorR, WindowColorG, WindowColorB, WindowColorA, BackgroundMusic, MapLighting, CinematicExperience
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@ from .text import cv64_string_to_bytearray, cv64_text_truncate, cv64_text_wrap
|
||||
from .aesthetics import renon_item_dialogue, get_item_text_color
|
||||
from .locations import get_location_info
|
||||
from .options import CharacterStages, VincentFightCondition, RenonFightCondition, PostBehemothBoss, RoomOfClocksBoss, \
|
||||
BadEndingCondition, DeathLink, DraculasCondition, InvisibleItems, Countdown, PantherDash
|
||||
BadEndingCondition, CV64DeathLink, DraculasCondition, InvisibleItems, Countdown, PantherDash
|
||||
from settings import get_settings
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -356,7 +356,7 @@ class CV64PatchExtensions(APPatchExtension):
|
||||
rom_data.write_int32s(0xBFE190, patches.subweapon_surface_checker)
|
||||
|
||||
# Make received DeathLinks blow you to smithereens instead of kill you normally.
|
||||
if options["death_link"] == DeathLink.option_explosive:
|
||||
if options["death_link"] == CV64DeathLink.option_explosive:
|
||||
rom_data.write_int32s(0xBFC0D0, patches.deathlink_nitro_edition)
|
||||
rom_data.write_int32(0x27A70, 0x10000008) # B [forward 0x08]
|
||||
rom_data.write_int32(0x27AA0, 0x0C0FFA78) # JAL 0x803FE9E0
|
||||
@@ -365,7 +365,7 @@ class CV64PatchExtensions(APPatchExtension):
|
||||
rom_data.write_int32(0x32DBC, 0x00000000)
|
||||
|
||||
# Set the DeathLink ROM flag if it's on at all.
|
||||
if options["death_link"] != DeathLink.option_off:
|
||||
if options["death_link"] != CV64DeathLink.option_off:
|
||||
rom_data.write_byte(0xBFBFDE, 0x01)
|
||||
|
||||
# DeathLink counter decrementer code
|
||||
|
||||
@@ -39,16 +39,14 @@ randomized item and (optionally) enemy locations. You only need to do this once
|
||||
|
||||
To run _Dark Souls III_ in Archipelago mode:
|
||||
|
||||
1. Start Steam. **Do not run in offline mode.** Running Steam in offline mode will make certain
|
||||
scripted invaders fail to spawn. Instead, change the game itself to offline mode on the menu
|
||||
screen.
|
||||
1. Start Steam. **Do not run Steam in offline mode.** Running Steam in offline mode will make certain
|
||||
scripted invaders fail to spawn.
|
||||
|
||||
2. Run `launchmod_darksouls3.bat`. This will start _Dark Souls III_ as well as a command prompt that
|
||||
2. To prevent you from getting penalized, **make sure to set _Dark Souls III_ to offline mode in the game options.**
|
||||
|
||||
3. Run `launchmod_darksouls3.bat`. This will start _Dark Souls III_ as well as a command prompt that
|
||||
you can use to interact with the Archipelago server.
|
||||
|
||||
3. Type `/connect {SERVER_IP}:{SERVER_PORT} {SLOT_NAME}` into the command prompt, with the
|
||||
appropriate values filled in. For example: `/connect archipelago.gg:24242 PlayerName`.
|
||||
|
||||
4. Start playing as normal. An "Archipelago connected" message will appear onscreen once you have
|
||||
control of your character and the connection is established.
|
||||
|
||||
|
||||
+19
-1
@@ -154,7 +154,17 @@ class HKWeb(WebWorld):
|
||||
["JoaoVictor-FA"]
|
||||
)
|
||||
|
||||
tutorials = [setup_en, setup_pt_br]
|
||||
setup_es = Tutorial(
|
||||
setup_en.tutorial_name,
|
||||
setup_en.description,
|
||||
"Español",
|
||||
"setup_es.md",
|
||||
"setup/es",
|
||||
["GreenMarco", "Panto UwUr"]
|
||||
)
|
||||
|
||||
tutorials = [setup_en, setup_pt_br, setup_es]
|
||||
game_info_languages = ["en", "es"]
|
||||
|
||||
bug_report_page = "https://github.com/Ijwu/Archipelago.HollowKnight/issues/new?assignees=&labels=bug%2C+needs+investigation&template=bug_report.md&title="
|
||||
|
||||
@@ -218,6 +228,11 @@ class HKWorld(World):
|
||||
wp = self.options.WhitePalace
|
||||
if wp <= WhitePalace.option_nopathofpain:
|
||||
exclusions.update(path_of_pain_locations)
|
||||
exclusions.update((
|
||||
"Soul_Totem-Path_of_Pain",
|
||||
"Lore_Tablet-Path_of_Pain_Entrance",
|
||||
"Journal_Entry-Seal_of_Binding",
|
||||
))
|
||||
if wp <= WhitePalace.option_kingfragment:
|
||||
exclusions.update(white_palace_checks)
|
||||
if wp == WhitePalace.option_exclude:
|
||||
@@ -226,6 +241,9 @@ class HKWorld(World):
|
||||
# If charms are randomized, this will be junk-filled -- so transitions and events are not progression
|
||||
exclusions.update(white_palace_transitions)
|
||||
exclusions.update(white_palace_events)
|
||||
exclusions.update(item_name_groups["PalaceJournal"])
|
||||
exclusions.update(item_name_groups["PalaceLore"])
|
||||
exclusions.update(item_name_groups["PalaceTotem"])
|
||||
return exclusions
|
||||
|
||||
def create_regions(self):
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Hollow Knight
|
||||
|
||||
## ¿Dónde está la página de opciones?
|
||||
|
||||
La [página de opciones de jugador para este juego](../player-options) contiene todas las opciones que necesitas para
|
||||
configurar y exportar un archivo de configuración.
|
||||
|
||||
## ¿Qué se randomiza en este juego?
|
||||
|
||||
El randomizer cambia la ubicación de los objetos. Los objetos que se intercambian se eligen dentro de tu YAML.
|
||||
Los costes de las tiendas son aleatorios. Los objetos que podrían ser aleatorios, pero no lo son, permanecerán sin
|
||||
modificar en sus ubicaciones habituales. En particular, cuando los ítems con el PadreLarva y la Vidente están
|
||||
parcialmente randomizados, los ítems randomizados se obtendrán de un cofre en la habitación, mientras que los ítems no
|
||||
randomizados serán dados por el NPC de forma normal.
|
||||
|
||||
## ¿Qué objetos de Hollow Knight pueden aparecer en los mundos de otros jugadores?
|
||||
|
||||
Esto depende enteramente de tus opciones YAML. Algunos ejemplos son: amuletos, larvas, capullos de saviavida, geo, etc.
|
||||
|
||||
## ¿Qué aspecto tienen los objetos de otro mundo en Hollow Knight?
|
||||
|
||||
Cuando el jugador de Hollow Knight recoja un objeto de un lugar y sea un objeto para otro juego, aparecerá en la
|
||||
pantalla de objetos recientes de ese jugador como un objeto enviado a otro jugador. Si el objeto es para otro jugador
|
||||
de Hollow Knight entonces el sprite será el del sprite original del objeto. Si el objeto pertenece a un jugador que no
|
||||
está jugando a Hollow Knight, el sprite será el logo del Archipiélago.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Hollow Knight Archipelago
|
||||
|
||||
## Software requerido
|
||||
* Descarga y descomprime Lumafly Mod manager desde el [sitio web de Lumafly](https://themulhima.github.io/Lumafly/)
|
||||
* Tener una copia legal de Hollow Knight.
|
||||
* Las versiones de Steam, GOG y Xbox Game Pass son compatibles
|
||||
* Las versiones de Windows, Mac y Linux (Incluyendo Steam Deck) son compatibles
|
||||
|
||||
## Instalación del mod de Archipelago con Lumafly
|
||||
1. Ejecuta Lumafly y asegurate de localizar la carpeta de instalación de Hollow Knight
|
||||
2. Instala el mod de Archipiélago haciendo click en cualquiera de los siguientes:
|
||||
* Haz clic en uno de los enlaces de abajo para permitir Lumafly para instalar los mods. Lumafly pedirá
|
||||
confirmación.
|
||||
* [Archipiélago y dependencias solamente](https://themulhima.github.io/Lumafly/commands/download/?mods=Archipelago)
|
||||
* [Archipelago con rando essentials](https://themulhima.github.io/Lumafly/commands/download/?mods=Archipelago/Archipelago%20Map%20Mod/RecentItemsDisplay/DebugMod/RandoStats/Additional%20Timelines/CompassAlwaysOn/AdditionalMaps/)
|
||||
(incluye Archipelago Map Mod, RecentItemsDisplay, DebugMod, RandoStats, AdditionalTimelines, CompassAlwaysOn,
|
||||
y AdditionalMaps).
|
||||
* Haz clic en el botón "Instalar" situado junto a la entrada del mod "Archipiélago". Si lo deseas, instala también
|
||||
"Archipelago Map Mod" para utilizarlo como rastreador en el juego.
|
||||
Si lo requieres (Y recomiendo hacerlo) busca e instala Archipelago Map Mod para usar un tracker in-game
|
||||
3. Ejecuta el juego desde el apartado de inicio haciendo click en el botón Launch with Mods
|
||||
|
||||
## Que hago si Lumafly no encontro la ruta de instalación de mi juego?
|
||||
1. Busca el directorio manualmente
|
||||
* En Xbox Game pass:
|
||||
1. Entra a la Xbox App y dirigete sobre el icono de Hollow Knight que esta a la izquierda.
|
||||
2. Haz click en los 3 puntitos y elige el apartado Administrar
|
||||
3. Dirigete al apartado Archivos Locales y haz click en Buscar
|
||||
4. Abre en Hollow Knight, luego Content y copia la ruta de archivos que esta en la barra de navegación.
|
||||
* En Steam:
|
||||
1. Si instalaste Hollow Knight en algún otro disco que no sea el predeterminado, ya sabrás donde se encuentra
|
||||
el juego, ve a esa carpeta, abrela y copia la ruta de archivos que se encuentra en la barra de navegación.
|
||||
* En Windows, la ruta predeterminada suele ser:`C:\Program Files (x86)\Steam\steamapps\common\Hollow Knight`
|
||||
* En linux/Steam Deck suele ser: ~/.local/share/Steam/steamapps/common/Hollow Knight
|
||||
* En Mac suele ser: ~/Library/Application Support/Steam/steamapps/common/Hollow Knight/hollow_knight.app
|
||||
2. Ejecuta Lumafly como administrador y, cuando te pregunte por la ruta de instalación, pega la ruta que copeaste
|
||||
anteriormente.
|
||||
|
||||
## Configuración de tu fichero YAML
|
||||
### ¿Qué es un YAML y por qué necesito uno?
|
||||
Un archivo YAML es la forma en la que proporcionas tus opciones de jugador a Archipelago.
|
||||
Mira la [guía básica de configuración multiworld](/tutorial/Archipelago/setup/en) aquí en la web de Archipelago para
|
||||
aprender más, (solo se encuentra en Inglés).
|
||||
|
||||
### ¿Dónde consigo un YAML?
|
||||
Puedes usar la [página de opciones de juego para Hollow Knight](/games/Hollow%20Knight/player-options) aquí en la web
|
||||
de Archipelago para generar un YAML usando una interfaz gráfica.
|
||||
|
||||
## Unete a una partida de Archipelago en Hollow Knight
|
||||
1. Inicia el juego con los mods necesarios indicados anteriormente.
|
||||
2. Crea una **nueva partida.**
|
||||
3. Elige el modo **Archipelago** en la selección de modos de partida.
|
||||
4. Introduce la configuración correcta para tu servidor de Archipelago.
|
||||
5. Pulsa **Iniciar** para iniciar la partida. El juego se quedará con la pantalla en negro unos segundos mientras
|
||||
coloca todos los objetos.
|
||||
6. El juego debera comenzar y ya estaras dentro del servidor.
|
||||
* Si estas esperando a que termine un contador/timer, procura presionar el boton Start cuando el contador/timer
|
||||
termine.
|
||||
* Otra manera es pausar el juego y esperar a que el contador/timer termine cuando ingreses a la partida.
|
||||
|
||||
## Consejos y otros comandos
|
||||
Mientras juegas en un multiworld, puedes interactuar con el servidor usando varios comandos listados en la
|
||||
[guía de comandos](/tutorial/Archipelago/commands/en). Puedes usar el Cliente de Texto Archipelago para hacer esto,
|
||||
que está incluido en la última versión del [software de Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases/latest).
|
||||
@@ -57,13 +57,8 @@ class ExtraLogic(DefaultOnToggle):
|
||||
|
||||
|
||||
class Hylics2DeathLink(DeathLink):
|
||||
"""
|
||||
When you die, everyone dies. The reverse is also true.
|
||||
|
||||
Note that this also includes death by using the PERISH gesture.
|
||||
|
||||
Can be toggled via in-game console command "/deathlink".
|
||||
"""
|
||||
__doc__ = (DeathLink.__doc__ + "\n\n Note that this also includes death by using the PERISH gesture." +
|
||||
"\n\n Can be toggled via in-game console command \"/deathlink\".")
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -287,13 +287,13 @@ class BadStartingWeapons(Toggle):
|
||||
|
||||
class DonaldDeathLink(Toggle):
|
||||
"""
|
||||
If Donald is KO'ed, so is Sora. If Death Link is toggled on in your client, this will send a death to everyone.
|
||||
If Donald is KO'ed, so is Sora. If Death Link is toggled on in your client, this will send a death to everyone who enabled death link.
|
||||
"""
|
||||
display_name = "Donald Death Link"
|
||||
|
||||
class GoofyDeathLink(Toggle):
|
||||
"""
|
||||
If Goofy is KO'ed, so is Sora. If Death Link is toggled on in your client, this will send a death to everyone.
|
||||
If Goofy is KO'ed, so is Sora. If Death Link is toggled on in your client, this will send a death to everyone who enabled death link.
|
||||
"""
|
||||
display_name = "Goofy Death Link"
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ class LingoPlayerLogic:
|
||||
or painting.room in required_painting_rooms:
|
||||
return False
|
||||
|
||||
if world.options.shuffle_doors == ShuffleDoors.option_none:
|
||||
if world.options.shuffle_doors != ShuffleDoors.option_doors:
|
||||
if painting.req_blocked_when_no_doors:
|
||||
return False
|
||||
|
||||
|
||||
@@ -121,10 +121,8 @@ class ShopPrice(Choice):
|
||||
|
||||
|
||||
class NoitaDeathLink(DeathLink):
|
||||
"""
|
||||
When you die, everyone dies. Of course, the reverse is true too.
|
||||
You can disable this in the in-game mod options.
|
||||
"""
|
||||
__doc__ = (DeathLink.__doc__ + "\n\n You can disable this or set it to give yourself a trap effect when " +
|
||||
"another player dies in the in-game mod options.")
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -1324,10 +1324,20 @@ class OOTWorld(World):
|
||||
state.prog_items[self.player][alt_item_name] -= count
|
||||
if state.prog_items[self.player][alt_item_name] < 1:
|
||||
del (state.prog_items[self.player][alt_item_name])
|
||||
# invalidate caches, nothing can be trusted anymore now
|
||||
state.child_reachable_regions[self.player] = set()
|
||||
state.child_blocked_connections[self.player] = set()
|
||||
state.adult_reachable_regions[self.player] = set()
|
||||
state.adult_blocked_connections[self.player] = set()
|
||||
state._oot_stale[self.player] = True
|
||||
return True
|
||||
changed = super().remove(state, item)
|
||||
if changed:
|
||||
# invalidate caches, nothing can be trusted anymore now
|
||||
state.child_reachable_regions[self.player] = set()
|
||||
state.child_blocked_connections[self.player] = set()
|
||||
state.adult_reachable_regions[self.player] = set()
|
||||
state.adult_blocked_connections[self.player] = set()
|
||||
state._oot_stale[self.player] = True
|
||||
return changed
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
from typing import Dict, Any
|
||||
|
||||
from BaseClasses import CollectionState, Item, MultiWorld, Tutorial, Region
|
||||
from Options import OptionError
|
||||
from worlds.AutoWorld import LogicMixin, World, WebWorld
|
||||
from .items import item_table, PaintItem, item_data_table, traps, deathlink_traps
|
||||
from .locations import location_table, PaintLocation, location_data_table
|
||||
from .options import PaintOptions
|
||||
|
||||
|
||||
class PaintWebWorld(WebWorld):
|
||||
theme = "partyTime"
|
||||
|
||||
setup_en = Tutorial(
|
||||
tutorial_name="Start Guide",
|
||||
description="A guide to playing Paint in Archipelago.",
|
||||
language="English",
|
||||
file_name="guide_en.md",
|
||||
link="guide/en",
|
||||
authors=["MarioManTAW"]
|
||||
)
|
||||
|
||||
tutorials = [setup_en]
|
||||
|
||||
|
||||
class PaintWorld(World):
|
||||
"""
|
||||
The classic Microsoft app, reimagined as an Archipelago game! Find your tools, expand your canvas, and paint the
|
||||
greatest image the world has ever seen.
|
||||
"""
|
||||
game = "Paint"
|
||||
options_dataclass = PaintOptions
|
||||
options: PaintOptions
|
||||
web = PaintWebWorld()
|
||||
location_name_to_id = location_table
|
||||
item_name_to_id = item_table
|
||||
origin_region_name = "Canvas"
|
||||
|
||||
def generate_early(self) -> None:
|
||||
if self.options.canvas_size_increment < 50 and self.options.logic_percent <= 55:
|
||||
if self.multiworld.players == 1:
|
||||
raise OptionError("Logic Percent must be greater than 55 when generating a single-player world with "
|
||||
"Canvas Size Increment below 50.")
|
||||
|
||||
def get_filler_item_name(self) -> str:
|
||||
if self.random.randint(0, 99) >= self.options.trap_count:
|
||||
return "Additional Palette Color"
|
||||
elif self.options.death_link:
|
||||
return self.random.choice(deathlink_traps)
|
||||
else:
|
||||
return self.random.choice(traps)
|
||||
|
||||
def create_item(self, name: str) -> PaintItem:
|
||||
item = PaintItem(name, item_data_table[name].type, item_data_table[name].code, self.player)
|
||||
return item
|
||||
|
||||
def create_items(self) -> None:
|
||||
starting_tools = ["Brush", "Pencil", "Eraser/Color Eraser", "Airbrush", "Line", "Rectangle", "Ellipse",
|
||||
"Rounded Rectangle"]
|
||||
self.push_precollected(self.create_item("Magnifier"))
|
||||
self.push_precollected(self.create_item(starting_tools.pop(self.options.starting_tool)))
|
||||
items_to_create = ["Free-Form Select", "Select", "Fill With Color", "Pick Color", "Text", "Curve", "Polygon"]
|
||||
items_to_create += starting_tools
|
||||
items_to_create += ["Progressive Canvas Width"] * (400 // self.options.canvas_size_increment)
|
||||
items_to_create += ["Progressive Canvas Height"] * (300 // self.options.canvas_size_increment)
|
||||
depth_items = ["Progressive Color Depth (Red)", "Progressive Color Depth (Green)",
|
||||
"Progressive Color Depth (Blue)"]
|
||||
for item in depth_items:
|
||||
self.push_precollected(self.create_item(item))
|
||||
items_to_create += depth_items * 6
|
||||
pre_filled = len(items_to_create)
|
||||
to_fill = len(self.get_region("Canvas").locations)
|
||||
if pre_filled > to_fill:
|
||||
raise OptionError(f"{self.player_name}'s Paint world has too few locations for its required items. "
|
||||
"Consider adding more locations by raising logic percent or adding fractional checks. "
|
||||
"Alternatively, increasing the canvas size increment will require fewer items.")
|
||||
while len(items_to_create) < (to_fill - pre_filled) * (self.options.trap_count / 100) + pre_filled:
|
||||
if self.options.death_link:
|
||||
items_to_create += [self.random.choice(deathlink_traps)]
|
||||
else:
|
||||
items_to_create += [self.random.choice(traps)]
|
||||
while len(items_to_create) < to_fill:
|
||||
items_to_create += ["Additional Palette Color"]
|
||||
self.multiworld.itempool += [self.create_item(item) for item in items_to_create]
|
||||
|
||||
def create_regions(self) -> None:
|
||||
canvas = Region("Canvas", self.player, self.multiworld)
|
||||
canvas.locations += [PaintLocation(self.player, loc_name, loc_data.address, canvas)
|
||||
for loc_name, loc_data in location_data_table.items()
|
||||
if location_exists_with_options(self, loc_data.address)]
|
||||
|
||||
self.multiworld.regions += [canvas]
|
||||
|
||||
def set_rules(self) -> None:
|
||||
from .rules import set_completion_rules
|
||||
set_completion_rules(self, self.player)
|
||||
|
||||
def fill_slot_data(self) -> Dict[str, Any]:
|
||||
return dict(self.options.as_dict("logic_percent", "goal_percent", "goal_image", "death_link",
|
||||
"canvas_size_increment"), version="0.5.2")
|
||||
|
||||
def collect(self, state: CollectionState, item: Item) -> bool:
|
||||
change = super().collect(state, item)
|
||||
if change:
|
||||
state.paint_percent_stale[self.player] = True
|
||||
return change
|
||||
|
||||
def remove(self, state: CollectionState, item: Item) -> bool:
|
||||
change = super().remove(state, item)
|
||||
if change:
|
||||
state.paint_percent_stale[self.player] = True
|
||||
return change
|
||||
|
||||
|
||||
def location_exists_with_options(world: PaintWorld, location: int):
|
||||
l = location % 198600
|
||||
return l <= world.options.logic_percent * 4 and (l % 4 == 0 or
|
||||
(l > world.options.half_percent_checks * 4 and l % 2 == 0) or
|
||||
l > world.options.quarter_percent_checks * 4)
|
||||
|
||||
|
||||
class PaintState(LogicMixin):
|
||||
paint_percent_available: dict[int, float] # per player
|
||||
paint_percent_stale: dict[int, bool]
|
||||
|
||||
def init_mixin(self, multiworld: MultiWorld) -> None:
|
||||
self.paint_percent_available = {player: 0 for player in multiworld.get_game_players("Paint")}
|
||||
self.paint_percent_stale = {player: True for player in multiworld.get_game_players("Paint")}
|
||||
@@ -0,0 +1,35 @@
|
||||
# Paint
|
||||
|
||||
## Where is the options page?
|
||||
|
||||
You can read through all the options and generate a YAML [here](../player-options).
|
||||
|
||||
## What does randomization do to this game?
|
||||
|
||||
Most tools are locked from the start, leaving only the Magnifier and one drawing tool, specified in the game options.
|
||||
Canvas size is locked and will only expand when the Progressive Canvas Width and Progressive Canvas Height items are
|
||||
obtained. Additionally, color selection is limited, starting with only a few possible colors but gaining more options
|
||||
when Progressive Color Depth items are obtained in each of the red, green, and blue components.
|
||||
|
||||
Location checks are sent out based on similarity to a target image, measured as a percentage. Every percentage point up
|
||||
to a maximum set in the game options will send a new check, and the game will be considered done when a certain target
|
||||
percentage (also set in the game options) is reached.
|
||||
|
||||
## What other changes are made to the game?
|
||||
|
||||
This project is based on [JS Paint](https://jspaint.app), an open-source remake of Microsoft Paint. Most features will
|
||||
work similarly to this version but some features have also been removed. Most notably, pasting functionality has been
|
||||
completely removed to prevent cheating.
|
||||
|
||||
With the addition of a second canvas to display the target image, there are some additional features that may not be
|
||||
intuitive. There are two special functions in the Extras menu to help visualize how to improve your score. Similarity
|
||||
Mode (shortcut Ctrl+Shift+M) shows the similarity of each portion of the image in grayscale, with white representing
|
||||
perfect similarity and black representing no similarity. Conversely, Difference Mode (shortcut Ctrl+M) visualizes the
|
||||
differences between what has been drawn and the target image in full color, showing the direction both hue and
|
||||
lightness need to shift to match the target. Additionally, once unlocked, the Pick Color tool can be used on both the
|
||||
main and target canvases.
|
||||
|
||||
Custom colors have been streamlined for Archipelago play. The only starting palette options are black and white, but
|
||||
additional palette slots can be unlocked as Archipelago items. Double-clicking on any palette slot will allow you to
|
||||
edit the color in that slot directly and shift-clicking a palette slot will allow you to override the slot with your
|
||||
currently selected color.
|
||||
@@ -0,0 +1,8 @@
|
||||
# Paint Randomizer Start Guide
|
||||
|
||||
After rolling your seed, go to the [Archipelago Paint](https://mariomantaw.github.io/jspaint/) site and enter the
|
||||
server details, your slot name, and a room password if one is required. Then click "Connect". If desired, you may then
|
||||
load a custom target image with File->Open Goal Image. If playing asynchronously, note that progress is saved using the
|
||||
hash that will appear at the end of the URL so it is recommended to leave the tab open or save the URL with the hash to
|
||||
avoid losing progress.
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
from typing import NamedTuple, Dict
|
||||
|
||||
from BaseClasses import Item, ItemClassification
|
||||
|
||||
|
||||
class PaintItem(Item):
|
||||
game = "Paint"
|
||||
|
||||
|
||||
class PaintItemData(NamedTuple):
|
||||
code: int
|
||||
type: ItemClassification
|
||||
|
||||
|
||||
item_data_table: Dict[str, PaintItemData] = {
|
||||
"Progressive Canvas Width": PaintItemData(198501, ItemClassification.progression),
|
||||
"Progressive Canvas Height": PaintItemData(198502, ItemClassification.progression),
|
||||
"Progressive Color Depth (Red)": PaintItemData(198503, ItemClassification.progression),
|
||||
"Progressive Color Depth (Green)": PaintItemData(198504, ItemClassification.progression),
|
||||
"Progressive Color Depth (Blue)": PaintItemData(198505, ItemClassification.progression),
|
||||
"Free-Form Select": PaintItemData(198506, ItemClassification.useful),
|
||||
"Select": PaintItemData(198507, ItemClassification.useful),
|
||||
"Eraser/Color Eraser": PaintItemData(198508, ItemClassification.useful),
|
||||
"Fill With Color": PaintItemData(198509, ItemClassification.useful),
|
||||
"Pick Color": PaintItemData(198510, ItemClassification.progression),
|
||||
"Magnifier": PaintItemData(198511, ItemClassification.useful),
|
||||
"Pencil": PaintItemData(198512, ItemClassification.useful),
|
||||
"Brush": PaintItemData(198513, ItemClassification.useful),
|
||||
"Airbrush": PaintItemData(198514, ItemClassification.useful),
|
||||
"Text": PaintItemData(198515, ItemClassification.useful),
|
||||
"Line": PaintItemData(198516, ItemClassification.useful),
|
||||
"Curve": PaintItemData(198517, ItemClassification.useful),
|
||||
"Rectangle": PaintItemData(198518, ItemClassification.useful),
|
||||
"Polygon": PaintItemData(198519, ItemClassification.useful),
|
||||
"Ellipse": PaintItemData(198520, ItemClassification.useful),
|
||||
"Rounded Rectangle": PaintItemData(198521, ItemClassification.useful),
|
||||
# "Change Background Color": PaintItemData(198522, ItemClassification.useful),
|
||||
"Additional Palette Color": PaintItemData(198523, ItemClassification.filler),
|
||||
"Undo Trap": PaintItemData(198524, ItemClassification.trap),
|
||||
"Clear Image Trap": PaintItemData(198525, ItemClassification.trap),
|
||||
"Invert Colors Trap": PaintItemData(198526, ItemClassification.trap),
|
||||
"Flip Horizontal Trap": PaintItemData(198527, ItemClassification.trap),
|
||||
"Flip Vertical Trap": PaintItemData(198528, ItemClassification.trap),
|
||||
}
|
||||
|
||||
item_table = {name: data.code for name, data in item_data_table.items()}
|
||||
traps = ["Undo Trap", "Clear Image Trap", "Invert Colors Trap", "Flip Horizontal Trap", "Flip Vertical Trap"]
|
||||
deathlink_traps = ["Invert Colors Trap", "Flip Horizontal Trap", "Flip Vertical Trap"]
|
||||
@@ -0,0 +1,24 @@
|
||||
from typing import NamedTuple, Dict
|
||||
|
||||
from BaseClasses import CollectionState, Location
|
||||
|
||||
|
||||
class PaintLocation(Location):
|
||||
game = "Paint"
|
||||
def access_rule(self, state: CollectionState):
|
||||
from .rules import paint_percent_available
|
||||
return paint_percent_available(state, state.multiworld.worlds[self.player], self.player) >=\
|
||||
(self.address % 198600) / 4
|
||||
|
||||
|
||||
class PaintLocationData(NamedTuple):
|
||||
region: str
|
||||
address: int
|
||||
|
||||
|
||||
location_data_table: Dict[str, PaintLocationData] = {
|
||||
# f"Similarity: {i}%": PaintLocationData("Canvas", 198500 + i) for i in range(1, 96)
|
||||
f"Similarity: {i/4}%": PaintLocationData("Canvas", 198600 + i) for i in range(1, 381)
|
||||
}
|
||||
|
||||
location_table = {name: data.address for name, data in location_data_table.items()}
|
||||
@@ -0,0 +1,107 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from Options import Range, PerGameCommonOptions, StartInventoryPool, Toggle, Choice, Visibility
|
||||
|
||||
|
||||
class LogicPercent(Range):
|
||||
"""Sets the maximum percent similarity required for a check to be in logic.
|
||||
Higher values are more difficult and items/locations will not be generated beyond this number."""
|
||||
display_name = "Logic Percent"
|
||||
range_start = 50
|
||||
range_end = 95
|
||||
default = 80
|
||||
|
||||
|
||||
class GoalPercent(Range):
|
||||
"""Sets the percent similarity required to achieve your goal.
|
||||
If this number is higher than the value for logic percent,
|
||||
reaching goal will be in logic upon obtaining all progression items."""
|
||||
display_name = "Goal Percent"
|
||||
range_start = 50
|
||||
range_end = 95
|
||||
default = 80
|
||||
|
||||
|
||||
class HalfPercentChecks(Range):
|
||||
"""Sets the lowest percent at which locations will be created for each 0.5% of similarity.
|
||||
Below this number, there will be a check every 1%.
|
||||
Above this number, there will be a check every 0.5%."""
|
||||
display_name = "Half Percent Checks"
|
||||
range_start = 0
|
||||
range_end = 95
|
||||
default = 50
|
||||
|
||||
|
||||
class QuarterPercentChecks(Range):
|
||||
"""Sets the lowest percent at which locations will be created for each 0.25% of similarity.
|
||||
This number will override Half Percent Checks if it is lower."""
|
||||
display_name = "Quarter Percent Checks"
|
||||
range_start = 0
|
||||
range_end = 95
|
||||
default = 70
|
||||
|
||||
|
||||
class CanvasSizeIncrement(Choice):
|
||||
"""Sets the number of pixels the canvas will expand for each width/height item received.
|
||||
Ensure an adequate number of locations are generated if setting this below 50."""
|
||||
display_name = "Canvas Size Increment"
|
||||
# option_10 = 10
|
||||
# option_20 = 20
|
||||
option_25 = 25
|
||||
option_50 = 50
|
||||
option_100 = 100
|
||||
default = 100
|
||||
|
||||
|
||||
class GoalImage(Range):
|
||||
"""Sets the numbered image you will be required to match.
|
||||
See https://github.com/MarioManTAW/jspaint/tree/master/images/archipelago
|
||||
for a list of possible images or choose random.
|
||||
This can also be overwritten client-side by using File->Open."""
|
||||
display_name = "Goal Image"
|
||||
range_start = 1
|
||||
range_end = 1
|
||||
default = 1
|
||||
visibility = Visibility.none
|
||||
|
||||
|
||||
class StartingTool(Choice):
|
||||
"""Sets which tool (other than Magnifier) you will be able to use from the start."""
|
||||
option_brush = 0
|
||||
option_pencil = 1
|
||||
option_eraser = 2
|
||||
option_airbrush = 3
|
||||
option_line = 4
|
||||
option_rectangle = 5
|
||||
option_ellipse = 6
|
||||
option_rounded_rectangle = 7
|
||||
default = 0
|
||||
|
||||
|
||||
class TrapCount(Range):
|
||||
"""Sets the percentage of filler items to be replaced by random traps."""
|
||||
display_name = "Trap Fill Percent"
|
||||
range_start = 0
|
||||
range_end = 100
|
||||
default = 0
|
||||
|
||||
|
||||
class DeathLink(Toggle):
|
||||
"""If on, using the Undo or Clear Image functions will send a death to all other players with death link on.
|
||||
Receiving a death will clear the image and reset the history.
|
||||
This option also prevents Undo and Clear Image traps from being generated in the item pool."""
|
||||
display_name = "Death Link"
|
||||
|
||||
|
||||
@dataclass
|
||||
class PaintOptions(PerGameCommonOptions):
|
||||
logic_percent: LogicPercent
|
||||
goal_percent: GoalPercent
|
||||
half_percent_checks: HalfPercentChecks
|
||||
quarter_percent_checks: QuarterPercentChecks
|
||||
canvas_size_increment: CanvasSizeIncrement
|
||||
goal_image: GoalImage
|
||||
starting_tool: StartingTool
|
||||
trap_count: TrapCount
|
||||
death_link: DeathLink
|
||||
start_inventory_from_pool: StartInventoryPool
|
||||
@@ -0,0 +1,40 @@
|
||||
from math import sqrt
|
||||
|
||||
from BaseClasses import CollectionState
|
||||
from . import PaintWorld
|
||||
|
||||
|
||||
def paint_percent_available(state: CollectionState, world: PaintWorld, player: int) -> bool:
|
||||
if state.paint_percent_stale[player]:
|
||||
state.paint_percent_available[player] = calculate_paint_percent_available(state, world, player)
|
||||
state.paint_percent_stale[player] = False
|
||||
return state.paint_percent_available[player]
|
||||
|
||||
|
||||
def calculate_paint_percent_available(state: CollectionState, world: PaintWorld, player: int) -> float:
|
||||
p = state.has("Pick Color", player)
|
||||
r = min(state.count("Progressive Color Depth (Red)", player), 7)
|
||||
g = min(state.count("Progressive Color Depth (Green)", player), 7)
|
||||
b = min(state.count("Progressive Color Depth (Blue)", player), 7)
|
||||
if not p:
|
||||
r = min(r, 2)
|
||||
g = min(g, 2)
|
||||
b = min(b, 2)
|
||||
w = state.count("Progressive Canvas Width", player)
|
||||
h = state.count("Progressive Canvas Height", player)
|
||||
# This code looks a little messy but it's a mathematical formula derived from the similarity calculations in the
|
||||
# client. The first line calculates the maximum score achievable for a single pixel with the current items in the
|
||||
# worst possible case. This per-pixel score is then multiplied by the number of pixels currently available (the
|
||||
# starting canvas is 400x300) over the total number of pixels with everything unlocked (800x600) to get the
|
||||
# total score achievable assuming the worst possible target image. Finally, this is multiplied by the logic percent
|
||||
# option which restricts the logic so as to not require pixel perfection.
|
||||
return ((1 - ((sqrt(((2 ** (7 - r) - 1) ** 2 + (2 ** (7 - g) - 1) ** 2 + (2 ** (7 - b) - 1) ** 2) * 12)) / 765)) *
|
||||
min(400 + w * world.options.canvas_size_increment, 800) *
|
||||
min(300 + h * world.options.canvas_size_increment, 600) *
|
||||
world.options.logic_percent / 480000)
|
||||
|
||||
|
||||
def set_completion_rules(world: PaintWorld, player: int) -> None:
|
||||
world.multiworld.completion_condition[player] = \
|
||||
lambda state: (paint_percent_available(state, world, player) >=
|
||||
min(world.options.logic_percent, world.options.goal_percent))
|
||||
@@ -93,7 +93,7 @@ class RaftWorld(World):
|
||||
dupeItemPool = list(dupeItemPool)
|
||||
# Finally, add items as necessary
|
||||
for item in dupeItemPool:
|
||||
self.extraItemNamePool.append(self.replace_item_name_as_necessary(item))
|
||||
self.extraItemNamePool.append(self.replace_item_name_as_necessary(item["name"]))
|
||||
|
||||
assert self.extraItemNamePool, f"Don't know what extra items to create for {self.player_name}."
|
||||
|
||||
|
||||
+108
-24
@@ -1,5 +1,5 @@
|
||||
import typing
|
||||
from Options import Choice, PerGameCommonOptions, Range, OptionDict, OptionList, OptionSet, Option, Toggle, DefaultOnToggle
|
||||
from Options import Choice, PerGameCommonOptions, Range, OptionDict, OptionList, OptionSet, OptionGroup, Toggle, DefaultOnToggle
|
||||
from .variaRandomizer.utils.objectives import _goals
|
||||
from dataclasses import dataclass
|
||||
|
||||
@@ -8,8 +8,15 @@ class StartItemsRemovesFromPool(Toggle):
|
||||
display_name = "StartItems Removes From Item Pool"
|
||||
|
||||
class Preset(Choice):
|
||||
"""Choose one of the presets or specify "varia_custom" to use varia_custom_preset option or specify "custom" to use
|
||||
custom_preset option."""
|
||||
"""Determines the general difficulty of the item placements by adjusting the list of tricks that logic allows.
|
||||
- Newbie: New to randomizers, but completed Super Metroid 100% and knows basic techniques (Wall Jump, Shinespark, Mid-air Morph)
|
||||
- Casual: Occasional rando player. No hell runs or suitless Maridia, some easy to learn tricks in logic.
|
||||
- Regular: Plays rando regularly. Knows many tricks that open up the game.
|
||||
- Veteran: Experienced rando player. Harder everything, some tougher tricks in logic.
|
||||
- Expert: Knows almost all tricks: full suitless Maridia, Lower Norfair hell runs, etc.
|
||||
- Master: Everything on hardest, all tricks known.
|
||||
In-depth details on each preset can be found on the VARIA website: https://varia.run/presets
|
||||
You may also specify "varia_custom" to use varia_custom_preset option, or specify "custom" to use custom_preset option."""
|
||||
display_name = "Preset"
|
||||
option_newbie = 0
|
||||
option_casual = 1
|
||||
@@ -46,7 +53,8 @@ class StartLocation(Choice):
|
||||
default = 1
|
||||
|
||||
class DeathLink(Choice):
|
||||
"""When DeathLink is enabled and someone dies, you will die. With survive reserve tanks can save you."""
|
||||
"""When DeathLink is enabled and someone else with DeathLink dies, you will die.
|
||||
If "Enable Survive" is selected, reserve tanks can save you."""
|
||||
display_name = "Death Link"
|
||||
option_disable = 0
|
||||
option_enable = 1
|
||||
@@ -56,11 +64,13 @@ class DeathLink(Choice):
|
||||
default = 0
|
||||
|
||||
class RemoteItems(Toggle):
|
||||
"""Indicates you get items sent from your own world. This allows coop play of a world."""
|
||||
display_name = "Remote Items"
|
||||
"""Items from your own world are sent via the Archipelago server. This allows co-op play of a world and means that
|
||||
you will not lose items on death or save file loss."""
|
||||
display_name = "Remote Items"
|
||||
|
||||
class MaxDifficulty(Choice):
|
||||
"""Depending on the perceived difficulties of the techniques, bosses, hell runs etc. from the preset, it will
|
||||
"""Maximum difficulty of tricks that are allowed from the seed's Preset.
|
||||
Depending on the perceived difficulties of the techniques, bosses, hell runs etc. from the preset, it will
|
||||
prevent the Randomizer from placing an item in a location too difficult to reach with the current items."""
|
||||
display_name = "Maximum Difficulty"
|
||||
option_easy = 0
|
||||
@@ -73,7 +83,7 @@ class MaxDifficulty(Choice):
|
||||
default = 4
|
||||
|
||||
class MorphPlacement(Choice):
|
||||
"""Influences where the Morphing Ball with be placed."""
|
||||
"""Influences where the Morphing Ball will be placed."""
|
||||
display_name = "Morph Placement"
|
||||
option_early = 0
|
||||
option_normal = 1
|
||||
@@ -85,21 +95,21 @@ class StrictMinors(Toggle):
|
||||
display_name = "Strict Minors"
|
||||
|
||||
class MissileQty(Range):
|
||||
"""The higher the number the higher the probability of choosing missles when placing a minor."""
|
||||
"""The higher the number, the higher the probability of choosing Missiles when placing a minor."""
|
||||
display_name = "Missile Quantity"
|
||||
range_start = 10
|
||||
range_end = 90
|
||||
default = 30
|
||||
|
||||
class SuperQty(Range):
|
||||
"""The higher the number the higher the probability of choosing super missles when placing a minor."""
|
||||
"""The higher the number, the higher the probability of choosing Super Missiles when placing a minor."""
|
||||
display_name = "Super Quantity"
|
||||
range_start = 10
|
||||
range_end = 90
|
||||
default = 20
|
||||
|
||||
class PowerBombQty(Range):
|
||||
"""The higher the number the higher the probability of choosing power bombs when placing a minor."""
|
||||
"""The higher the number, the higher the probability of choosing Power Bombs when placing a minor."""
|
||||
display_name = "Power Bomb Quantity"
|
||||
range_start = 10
|
||||
range_end = 90
|
||||
@@ -123,7 +133,13 @@ class EnergyQty(Choice):
|
||||
default = 3
|
||||
|
||||
class AreaRandomization(Choice):
|
||||
"""Randomize areas together using bidirectional access portals."""
|
||||
"""Randomize areas together using bidirectional access portals.
|
||||
- Off: No change. All rooms are connected the same as in the original game.
|
||||
- Full: All doors connecting areas will be randomized. "Areas" are roughly determined, but generally are regions
|
||||
with different tilesets or music. For example, red Brinstar and green/pink Brinstar are different areas, Crocomire
|
||||
and upper Norfair are different areas, etc.
|
||||
- Light: Keep the same number of transitions between areas as in vanilla. So Crocomire area will always be connected
|
||||
to upper Norfair, there'll always be two transitions between Crateria/blue Brinstar and green/pink Brinstar, etc."""
|
||||
display_name = "Area Randomization"
|
||||
option_off = 0
|
||||
option_light = 1
|
||||
@@ -136,13 +152,13 @@ class AreaLayout(Toggle):
|
||||
display_name = "Area Layout"
|
||||
|
||||
class DoorsColorsRando(Toggle):
|
||||
"""Randomize the color of Red/Green/Yellow doors. Add four new type of doors which require Ice/Wave/Spazer/Plasma
|
||||
beams to open them."""
|
||||
"""Randomize the color of Red/Green/Yellow doors. Add four new types of doors which require Ice/Wave/Spazer/Plasma
|
||||
Beams to open them."""
|
||||
display_name = "Doors Colors Rando"
|
||||
|
||||
class AllowGreyDoors(Toggle):
|
||||
"""When randomizing the color of Red/Green/Yellow doors, some doors can be randomized to Grey. Grey doors will never
|
||||
open, you will have to go around them."""
|
||||
open; you will have to go around them."""
|
||||
display_name = "Allow Grey Doors"
|
||||
|
||||
class BossRandomization(Toggle):
|
||||
@@ -169,7 +185,10 @@ class LayoutPatches(DefaultOnToggle):
|
||||
display_name = "Layout Patches"
|
||||
|
||||
class VariaTweaks(Toggle):
|
||||
"""Include minor tweaks for the game to behave 'as it should' in a randomizer context"""
|
||||
"""Include minor tweaks for the game to behave 'as it should' in a randomizer context:
|
||||
- Bomb Torizo always activates after picking up its item and does not require Bomb to activate
|
||||
- Wrecked Ship item on the Energy Tank Chozo statue is present before defeating Phantoon
|
||||
- Lower Norfair Chozo statue that lowers the acid toward Gold Torizo does not require Space Jump to activate"""
|
||||
display_name = "Varia Tweaks"
|
||||
|
||||
class NerfedCharge(Toggle):
|
||||
@@ -179,7 +198,12 @@ class NerfedCharge(Toggle):
|
||||
display_name = "Nerfed Charge"
|
||||
|
||||
class GravityBehaviour(Choice):
|
||||
"""Modify the heat damage and enemy damage reduction qualities of the Gravity and Varia Suits."""
|
||||
"""Modify the heat damage and enemy damage reduction qualities of the Gravity and Varia Suits.
|
||||
- Vanilla: Gravity provides full protection against all environmental damage (heat, spikes, etc.)
|
||||
- Balanced: Removes Gravity environmental protection. Doubles Varia environmental protection. Enemy damage protection
|
||||
is vanilla (50% Varia, 75% Gravity).
|
||||
- Progressive: Gravity provides 50% heat reduction, Varia provides full heat reduction. Each suit adds 50% enemy
|
||||
and environmental reduction, stacking to 75% reduction if you have both."""
|
||||
display_name = "Gravity Behaviour"
|
||||
option_Vanilla = 0
|
||||
option_Balanced = 1
|
||||
@@ -233,7 +257,7 @@ class RandomMusic(Toggle):
|
||||
|
||||
class CustomPreset(OptionDict):
|
||||
"""
|
||||
see https://randommetroidsolver.pythonanywhere.com/presets for detailed info on each preset settings
|
||||
see https://varia.run/presets for detailed info on each preset settings
|
||||
knows: each skill (know) has a pair [can use, perceived difficulty using one of 1, 5, 10, 25, 50 or 100 each one
|
||||
matching a max_difficulty]
|
||||
settings: hard rooms, hellruns and bosses settings
|
||||
@@ -246,7 +270,7 @@ class CustomPreset(OptionDict):
|
||||
}
|
||||
|
||||
class VariaCustomPreset(OptionList):
|
||||
"""use an entry from the preset list on https://randommetroidsolver.pythonanywhere.com/presets"""
|
||||
"""use an entry from the preset list on https://varia.run/presets"""
|
||||
display_name = "Varia Custom Preset"
|
||||
default = {}
|
||||
|
||||
@@ -259,7 +283,7 @@ class EscapeRando(Toggle):
|
||||
During the escape sequence:
|
||||
- All doors are opened
|
||||
- Maridia tube is opened
|
||||
- The Hyper Beam can destroy Bomb , Power Bomb and Super Missile blocks and open blue/green gates from both sides
|
||||
- The Hyper Beam can destroy Bomb, Power Bomb and Super Missile blocks and open blue/green gates from both sides
|
||||
- All mini bosses are defeated
|
||||
- All minor enemies are removed to allow you to move faster and remove lag
|
||||
|
||||
@@ -281,9 +305,9 @@ class RemoveEscapeEnemies(Toggle):
|
||||
class Tourian(Choice):
|
||||
"""
|
||||
Choose endgame Tourian behaviour:
|
||||
Vanilla: regular vanilla Tourian
|
||||
Fast: speed up Tourian to skip Metroids, Zebetites, and all cutscenes (including Mother Brain 3 fight). Golden Four statues are replaced by an invincible Gadora until all objectives are completed.
|
||||
Disabled: skip Tourian entirely, ie. escape sequence is triggered as soon as all objectives are completed.
|
||||
- Vanilla: regular vanilla Tourian
|
||||
- Fast: speed up Tourian to skip Metroids, Zebetites, and all cutscenes (including Mother Brain 3 fight). Golden Four statues are replaced by an invincible Gadora until all objectives are completed.
|
||||
- Disabled: skip Tourian entirely; the escape sequence is triggered as soon as all objectives are completed.
|
||||
"""
|
||||
display_name = "Endgame behavior with Tourian"
|
||||
option_Vanilla = 0
|
||||
@@ -373,10 +397,71 @@ class RelaxedRoundRobinCF(Toggle):
|
||||
"""
|
||||
display_name = "Relaxed round robin Crystal Flash"
|
||||
|
||||
sm_option_groups = [
|
||||
OptionGroup("Logic", [
|
||||
Preset,
|
||||
MaxDifficulty,
|
||||
StartLocation,
|
||||
VariaCustomPreset,
|
||||
CustomPreset,
|
||||
]),
|
||||
OptionGroup("Objectives and Endgame", [
|
||||
Objective,
|
||||
CustomObjective,
|
||||
CustomObjectiveCount,
|
||||
CustomObjectiveList,
|
||||
Tourian,
|
||||
EscapeRando,
|
||||
RemoveEscapeEnemies,
|
||||
Animals,
|
||||
]),
|
||||
OptionGroup("Areas and Layout", [
|
||||
AreaRandomization,
|
||||
AreaLayout,
|
||||
DoorsColorsRando,
|
||||
AllowGreyDoors,
|
||||
BossRandomization,
|
||||
LayoutPatches,
|
||||
]),
|
||||
OptionGroup("Item Pool", [
|
||||
MorphPlacement,
|
||||
StrictMinors,
|
||||
MissileQty,
|
||||
SuperQty,
|
||||
PowerBombQty,
|
||||
MinorQty,
|
||||
EnergyQty,
|
||||
FunCombat,
|
||||
FunMovement,
|
||||
FunSuits,
|
||||
]),
|
||||
OptionGroup("Misc Tweaks", [
|
||||
VariaTweaks,
|
||||
GravityBehaviour,
|
||||
NerfedCharge,
|
||||
SpinJumpRestart,
|
||||
SpeedKeep,
|
||||
InfiniteSpaceJump,
|
||||
RelaxedRoundRobinCF,
|
||||
]),
|
||||
OptionGroup("Quality of Life", [
|
||||
ElevatorsSpeed,
|
||||
DoorsSpeed,
|
||||
RefillBeforeSave,
|
||||
]),
|
||||
OptionGroup("Cosmetic", [
|
||||
Hud,
|
||||
HideItems,
|
||||
NoMusic,
|
||||
RandomMusic,
|
||||
]),
|
||||
]
|
||||
|
||||
@dataclass
|
||||
class SMOptions(PerGameCommonOptions):
|
||||
start_inventory_removes_from_pool: StartItemsRemovesFromPool
|
||||
preset: Preset
|
||||
max_difficulty: MaxDifficulty
|
||||
start_location: StartLocation
|
||||
remote_items: RemoteItems
|
||||
death_link: DeathLink
|
||||
@@ -384,7 +469,6 @@ class SMOptions(PerGameCommonOptions):
|
||||
#scav_num_locs: "10"
|
||||
#scav_randomized: "off"
|
||||
#scav_escape: "off"
|
||||
max_difficulty: MaxDifficulty
|
||||
#progression_speed": "medium"
|
||||
#progression_difficulty": "normal"
|
||||
morph_placement: MorphPlacement
|
||||
|
||||
@@ -15,7 +15,7 @@ from worlds.generic.Rules import add_rule, set_rule
|
||||
|
||||
logger = logging.getLogger("Super Metroid")
|
||||
|
||||
from .Options import SMOptions
|
||||
from .Options import SMOptions, sm_option_groups
|
||||
from .Client import SMSNIClient
|
||||
from .Rom import SM_ROM_MAX_PLAYERID, SM_ROM_PLAYERDATA_COUNT, SMProcedurePatch, get_sm_symbols
|
||||
import Utils
|
||||
@@ -78,6 +78,7 @@ class SMWeb(WebWorld):
|
||||
"multiworld/en",
|
||||
["Farrak Kilhn"]
|
||||
)]
|
||||
option_groups = sm_option_groups
|
||||
|
||||
|
||||
class ByteEdit(TypedDict):
|
||||
@@ -852,7 +853,7 @@ class SMWorld(World):
|
||||
def fill_slot_data(self):
|
||||
slot_data = {}
|
||||
if not self.multiworld.is_race:
|
||||
slot_data = self.options.as_dict(*self.options_dataclass.type_hints)
|
||||
slot_data = self.options.as_dict("start_location", "max_difficulty", "area_randomization", "doors_colors_rando", "boss_randomization")
|
||||
slot_data["Preset"] = { "Knows": {},
|
||||
"Settings": {"hardRooms": Settings.SettingsDict[self.player].hardRooms,
|
||||
"bossesDifficulty": Settings.SettingsDict[self.player].bossesDifficulty,
|
||||
|
||||
@@ -500,7 +500,14 @@ class SMZ3World(World):
|
||||
multidata["connect_names"][new_name] = payload
|
||||
|
||||
def fill_slot_data(self):
|
||||
slot_data = {}
|
||||
slot_data = {
|
||||
"goal": self.options.goal.value,
|
||||
"open_tower": self.options.open_tower.value,
|
||||
"ganon_vulnerable": self.options.ganon_vulnerable.value,
|
||||
"open_tourian": self.options.open_tourian.value,
|
||||
"sm_logic": self.options.sm_logic.value,
|
||||
"key_shuffle": self.options.key_shuffle.value,
|
||||
}
|
||||
return slot_data
|
||||
|
||||
def collect(self, state: CollectionState, item: Item) -> bool:
|
||||
|
||||
@@ -50,15 +50,25 @@ class StardewWebWorld(WebWorld):
|
||||
options_presets = sv_options_presets
|
||||
option_groups = sv_option_groups
|
||||
|
||||
tutorials = [
|
||||
Tutorial(
|
||||
"Multiworld Setup Guide",
|
||||
"A guide to playing Stardew Valley with Archipelago.",
|
||||
"English",
|
||||
"setup_en.md",
|
||||
"setup/en",
|
||||
["KaitoKid", "Jouramie", "Witchybun (Mod Support)", "Exempt-Medic (Proofreading)"]
|
||||
)]
|
||||
setup_en = Tutorial(
|
||||
"Multiworld Setup Guide",
|
||||
"A guide to playing Stardew Valley with Archipelago.",
|
||||
"English",
|
||||
"setup_en.md",
|
||||
"setup/en",
|
||||
["KaitoKid", "Jouramie", "Witchybun (Mod Support)", "Exempt-Medic (Proofreading)"]
|
||||
)
|
||||
|
||||
setup_fr = Tutorial(
|
||||
"Guide de configuration MultiWorld",
|
||||
"Un guide pour configurer Stardew Valley sur Archipelago",
|
||||
"Français",
|
||||
"setup_fr.md",
|
||||
"setup/fr",
|
||||
["Eindall"]
|
||||
)
|
||||
|
||||
tutorials = [setup_en, setup_fr]
|
||||
|
||||
|
||||
class StardewValleyWorld(World):
|
||||
|
||||
@@ -2316,100 +2316,100 @@ id,region,name,tags,mod_name
|
||||
4069,Museum,Read Note From Gunther,"BOOKSANITY,BOOKSANITY_LOST",
|
||||
4070,Museum,Read Goblins by M. Jasper,"BOOKSANITY,BOOKSANITY_LOST",
|
||||
4071,Museum,Read Secret Statues Acrostics,"BOOKSANITY,BOOKSANITY_LOST",
|
||||
4101,Clint's Blacksmith,Open Golden Coconut,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4102,Island West,Fishing Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4103,Island West,Fishing Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4104,Island North,Fishing Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4105,Island North,Fishing Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4106,Island Southeast,Fishing Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4107,Island East,Jungle Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4108,Island East,Banana Altar,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4109,Leo's Hut,Leo's Tree,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4110,Island Shrine,Gem Birds Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4111,Island Shrine,Gem Birds Shrine,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4112,Island West,Harvesting Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4113,Island West,Harvesting Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4114,Island West,Harvesting Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4115,Island West,Harvesting Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4116,Island West,Harvesting Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4117,Gourmand Frog Cave,Gourmand Frog Melon,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4118,Gourmand Frog Cave,Gourmand Frog Wheat,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4119,Gourmand Frog Cave,Gourmand Frog Garlic,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4120,Island West,Journal Scrap #6,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4121,Island West,Mussel Node Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4122,Island West,Mussel Node Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4123,Island West,Mussel Node Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4124,Island West,Mussel Node Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4125,Island West,Mussel Node Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4126,Shipwreck,Shipwreck Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4127,Island West,Whack A Mole,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4128,Island West,Starfish Triangle,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4129,Island West,Starfish Diamond,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4130,Island West,X in the sand,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4131,Island West,Diamond Of Indents,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4132,Island West,Bush Behind Coconut Tree,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4133,Island West,Journal Scrap #4,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4134,Island West,Walnut Room Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4135,Island West,Coast Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4136,Island West,Tiger Slime Walnut,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4137,Island West,Bush Behind Mahogany Tree,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4138,Island West,Circle Of Grass,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4139,Island West,Below Colored Crystals Cave Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4140,Colored Crystals Cave,Colored Crystals,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4141,Island West,Cliff Edge Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4142,Island West,Diamond Of Pebbles,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4143,Island West,Farm Parrot Express Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4144,Island West,Farmhouse Cliff Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4145,Island North,Big Circle Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4146,Island North,Grove Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4147,Island North,Diamond Of Grass,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4148,Island North,Small Circle Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4149,Island North,Patch Of Sand,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4150,Dig Site,Crooked Circle Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4151,Dig Site,Above Dig Site Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4152,Dig Site,Above Field Office Bush 1,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4153,Dig Site,Above Field Office Bush 2,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4154,Field Office,Complete Large Animal Collection,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4155,Field Office,Complete Snake Collection,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4156,Field Office,Complete Mummified Frog Collection,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4157,Field Office,Complete Mummified Bat Collection,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4158,Field Office,Purple Flowers Island Survey,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4159,Field Office,Purple Starfish Island Survey,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4160,Island North,Bush Behind Volcano Tree,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4161,Island North,Arc Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4162,Island North,Protruding Tree Walnut,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4163,Island North,Journal Scrap #10,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4164,Island North,Northmost Point Circle Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4165,Island North,Hidden Passage Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4166,Volcano Secret Beach,Secret Beach Bush 1,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4167,Volcano Secret Beach,Secret Beach Bush 2,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4168,Volcano - Floor 5,Volcano Rocks Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4169,Volcano - Floor 5,Volcano Rocks Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4170,Volcano - Floor 10,Volcano Rocks Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4171,Volcano - Floor 10,Volcano Rocks Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4172,Volcano - Floor 10,Volcano Rocks Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4173,Volcano - Floor 5,Volcano Monsters Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4174,Volcano - Floor 5,Volcano Monsters Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4175,Volcano - Floor 10,Volcano Monsters Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4176,Volcano - Floor 10,Volcano Monsters Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4177,Volcano - Floor 10,Volcano Monsters Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4178,Volcano - Floor 5,Volcano Crates Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4179,Volcano - Floor 5,Volcano Crates Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4180,Volcano - Floor 10,Volcano Crates Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4181,Volcano - Floor 10,Volcano Crates Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4182,Volcano - Floor 10,Volcano Crates Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4183,Volcano - Floor 5,Volcano Common Chest Walnut,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4184,Volcano - Floor 10,Volcano Rare Chest Walnut,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4185,Volcano - Floor 10,Forge Entrance Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4186,Volcano - Floor 10,Forge Exit Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4187,Island North,Cliff Over Island South Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4188,Island Southeast,Starfish Tide Pool,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4189,Island Southeast,Diamond Of Yellow Starfish,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4190,Island Southeast,Mermaid Song,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4191,Pirate Cove,Pirate Darts 1,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4192,Pirate Cove,Pirate Darts 2,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4193,Pirate Cove,Pirate Darts 3,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4194,Pirate Cove,Pirate Cove Patch Of Sand,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4101,Clint's Blacksmith,Walnutsanity: Open Golden Coconut,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4102,Island West,Walnutsanity: Fishing Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4103,Island West,Walnutsanity: Fishing Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4104,Island North,Walnutsanity: Fishing Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4105,Island North,Walnutsanity: Fishing Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4106,Island Southeast,Walnutsanity: Fishing Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4107,Island East,Walnutsanity: Jungle Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4108,Island East,Walnutsanity: Banana Altar,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4109,Leo's Hut,Walnutsanity: Leo's Tree,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4110,Island Shrine,Walnutsanity: Gem Birds Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4111,Island Shrine,Walnutsanity: Gem Birds Shrine,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4112,Island West,Walnutsanity: Harvesting Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4113,Island West,Walnutsanity: Harvesting Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4114,Island West,Walnutsanity: Harvesting Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4115,Island West,Walnutsanity: Harvesting Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4116,Island West,Walnutsanity: Harvesting Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4117,Gourmand Frog Cave,Walnutsanity: Gourmand Frog Melon,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4118,Gourmand Frog Cave,Walnutsanity: Gourmand Frog Wheat,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4119,Gourmand Frog Cave,Walnutsanity: Gourmand Frog Garlic,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4120,Island West,Walnutsanity: Journal Scrap #6,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4121,Island West,Walnutsanity: Mussel Node Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4122,Island West,Walnutsanity: Mussel Node Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4123,Island West,Walnutsanity: Mussel Node Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4124,Island West,Walnutsanity: Mussel Node Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4125,Island West,Walnutsanity: Mussel Node Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4126,Shipwreck,Walnutsanity: Shipwreck Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4127,Island West,Walnutsanity: Whack A Mole,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4128,Island West,Walnutsanity: Starfish Triangle,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4129,Island West,Walnutsanity: Starfish Diamond,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4130,Island West,Walnutsanity: X in the sand,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4131,Island West,Walnutsanity: Diamond Of Indents,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4132,Island West,Walnutsanity: Bush Behind Coconut Tree,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4133,Island West,Walnutsanity: Journal Scrap #4,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4134,Island West,Walnutsanity: Walnut Room Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4135,Island West,Walnutsanity: Coast Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4136,Island West,Walnutsanity: Tiger Slime Walnut,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4137,Island West,Walnutsanity: Bush Behind Mahogany Tree,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4138,Island West,Walnutsanity: Circle Of Grass,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4139,Island West,Walnutsanity: Below Colored Crystals Cave Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4140,Colored Crystals Cave,Walnutsanity: Colored Crystals,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4141,Island West,Walnutsanity: Cliff Edge Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4142,Island West,Walnutsanity: Diamond Of Pebbles,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4143,Island West,Walnutsanity: Farm Parrot Express Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4144,Island West,Walnutsanity: Farmhouse Cliff Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4145,Island North,Walnutsanity: Big Circle Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4146,Island North,Walnutsanity: Grove Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4147,Island North,Walnutsanity: Diamond Of Grass,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4148,Island North,Walnutsanity: Small Circle Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4149,Island North,Walnutsanity: Patch Of Sand,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4150,Dig Site,Walnutsanity: Crooked Circle Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4151,Dig Site,Walnutsanity: Above Dig Site Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4152,Dig Site,Walnutsanity: Above Field Office Bush 1,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4153,Dig Site,Walnutsanity: Above Field Office Bush 2,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4154,Field Office,Walnutsanity: Complete Large Animal Collection,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4155,Field Office,Walnutsanity: Complete Snake Collection,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4156,Field Office,Walnutsanity: Complete Mummified Frog Collection,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4157,Field Office,Walnutsanity: Complete Mummified Bat Collection,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4158,Field Office,Walnutsanity: Purple Flowers Island Survey,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4159,Field Office,Walnutsanity: Purple Starfish Island Survey,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4160,Island North,Walnutsanity: Bush Behind Volcano Tree,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4161,Island North,Walnutsanity: Arc Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4162,Island North,Walnutsanity: Protruding Tree Walnut,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4163,Island North,Walnutsanity: Journal Scrap #10,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4164,Island North,Walnutsanity: Northmost Point Circle Of Stones,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4165,Island North,Walnutsanity: Hidden Passage Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4166,Volcano Secret Beach,Walnutsanity: Secret Beach Bush 1,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4167,Volcano Secret Beach,Walnutsanity: Secret Beach Bush 2,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4168,Volcano - Floor 5,Walnutsanity: Volcano Rocks Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4169,Volcano - Floor 5,Walnutsanity: Volcano Rocks Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4170,Volcano - Floor 10,Walnutsanity: Volcano Rocks Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4171,Volcano - Floor 10,Walnutsanity: Volcano Rocks Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4172,Volcano - Floor 10,Walnutsanity: Volcano Rocks Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4173,Volcano - Floor 5,Walnutsanity: Volcano Monsters Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4174,Volcano - Floor 5,Walnutsanity: Volcano Monsters Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4175,Volcano - Floor 10,Walnutsanity: Volcano Monsters Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4176,Volcano - Floor 10,Walnutsanity: Volcano Monsters Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4177,Volcano - Floor 10,Walnutsanity: Volcano Monsters Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4178,Volcano - Floor 5,Walnutsanity: Volcano Crates Walnut 1,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4179,Volcano - Floor 5,Walnutsanity: Volcano Crates Walnut 2,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4180,Volcano - Floor 10,Walnutsanity: Volcano Crates Walnut 3,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4181,Volcano - Floor 10,Walnutsanity: Volcano Crates Walnut 4,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4182,Volcano - Floor 10,Walnutsanity: Volcano Crates Walnut 5,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4183,Volcano - Floor 5,Walnutsanity: Volcano Common Chest Walnut,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4184,Volcano - Floor 10,Walnutsanity: Volcano Rare Chest Walnut,"WALNUTSANITY,WALNUTSANITY_REPEATABLE",
|
||||
4185,Volcano - Floor 10,Walnutsanity: Forge Entrance Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4186,Volcano - Floor 10,Walnutsanity: Forge Exit Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4187,Island North,Walnutsanity: Cliff Over Island South Bush,"WALNUTSANITY,WALNUTSANITY_BUSH",
|
||||
4188,Island Southeast,Walnutsanity: Starfish Tide Pool,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4189,Island Southeast,Walnutsanity: Diamond Of Yellow Starfish,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
4190,Island Southeast,Walnutsanity: Mermaid Song,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4191,Pirate Cove,Walnutsanity: Pirate Darts 1,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4192,Pirate Cove,Walnutsanity: Pirate Darts 2,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4193,Pirate Cove,Walnutsanity: Pirate Darts 3,"WALNUTSANITY,WALNUTSANITY_PUZZLE",
|
||||
4194,Pirate Cove,Walnutsanity: Pirate Cove Patch Of Sand,"WALNUTSANITY,WALNUTSANITY_DIG",
|
||||
5001,Stardew Valley,Level 1 Luck,"LUCK_LEVEL,SKILL_LEVEL",Luck Skill
|
||||
5002,Stardew Valley,Level 2 Luck,"LUCK_LEVEL,SKILL_LEVEL",Luck Skill
|
||||
5003,Stardew Valley,Level 3 Luck,"LUCK_LEVEL,SKILL_LEVEL",Luck Skill
|
||||
|
||||
|
@@ -0,0 +1,87 @@
|
||||
# Guide de configuration du Randomizer Stardew Valley
|
||||
|
||||
## Logiciels nécessaires
|
||||
|
||||
- Stardew Valley 1.6 sur PC (Recommandé: [Steam](https://store.steampowered.com/app/413150/Stardew_Valley/))
|
||||
- SMAPI ([Mod loader pour Stardew Valley](https://www.nexusmods.com/stardewvalley/mods/2400?tab=files))
|
||||
- [StardewArchipelago Version 6.x.x](https://github.com/agilbert1412/StardewArchipelago/releases)
|
||||
- Il est important d'utiliser une release en 6.x.x pour jouer sur des seeds générées ici. Les versions ultérieures peuvent uniquement être utilisées pour des release ultérieures du générateur de mondes, qui ne sont pas encore hébergées sur archipelago.gg
|
||||
|
||||
## Logiciels optionnels
|
||||
|
||||
- Launcher Archipelago à partir de la [page des versions d'Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases)
|
||||
- (Uniquement pour le client textuel)
|
||||
- Autres [mods supportés](https://github.com/agilbert1412/StardewArchipelago/blob/6.x.x/Documentation/Supported%20Mods.md) que vous pouvez ajouter au yaml pour les inclure dans la randomization d'Archipelago
|
||||
|
||||
- Il n'est **pas** recommandé de modder Stardew Valley avec des mods non supportés, même s'il est possible de le faire.
|
||||
Les interactions entre mods peuvent être imprévisibles, et aucune aide ne sera fournie pour les bugs qui y sont liés.
|
||||
- Plus vous avez de mods non supportés, et plus ils sont gros, plus vous avez de chances de casser des choses.
|
||||
|
||||
## Configuration du fichier YAML
|
||||
|
||||
### Qu'est qu'un fichier YAML et pourquoi en ai-je besoin ?
|
||||
|
||||
Voir le guide pour paramètrer un fichier YAML dans le guide de configuration d'Archipelago (en anglais): [Guide de configuration d'un MultiWorld basique](/tutorial/Archipelago/setup/en)
|
||||
|
||||
### Où puis-je récupèrer un fichier YAML
|
||||
|
||||
Vous pouvez personnaliser vos options en visitant la [Page d'options de joueur pour Stardew Valley](/games/Stardew%20Valley/player-options)
|
||||
|
||||
## Rejoindre une partie en MultiWorld
|
||||
|
||||
### Installation du mod
|
||||
|
||||
- Installer [SMAPI](https://www.nexusmods.com/stardewvalley/mods/2400?tab=files) en suivant les instructions sur la page du mod.
|
||||
- Télécharger et extraire le mod [StardewArchipelago](https://github.com/agilbert1412/StardewArchipelago/releases) dans le dossier "Mods" de Stardew Valley.
|
||||
- *Optionnel*: Si vous voulez lancer le jeu depuis Steam, ajouter l'option de lancement suivante à Stardew Valley : `"[PATH TO STARDEW VALLEY]\Stardew Valley\StardewModdingAPI.exe" %command%`
|
||||
- Sinon, exécutez juste "StardewModdingAPI.exe" dans le dossier d'installation de Stardew Valley.
|
||||
- Stardew Valley devrait se lancer avec une console qui liste les informations des mods installés, et intéragit avec certains d'entre eux.
|
||||
|
||||
### Se connecter au MultiServer
|
||||
|
||||
Lancer Stardew Valley avec SMAPI. Une fois que vous avez atteint l'écran titre du jeu, créez une nouvelle ferme.
|
||||
|
||||
Dans la fenêtre de création de personnage, vous verrez 3 nouveaux champs, qui permettent de relier votre personnage à un MultiWorld Archipelago.
|
||||
|
||||

|
||||
|
||||
Vous pouvez personnaliser votre personnage comme vous le souhaitez.
|
||||
|
||||
Le champ "Server" nécessite l'adresse **et** le port, et le "Slotname" est le nom que vous avez spécifié dans votre YAML.
|
||||
|
||||
`archipelago.gg:12345`
|
||||
|
||||
`StardewPlayer`
|
||||
|
||||
Le mot de passe est optionnel.
|
||||
|
||||
Votre jeu se connectera automatiquement à Archipelago, et se reconnectera automatiquement également quand vous chargerez votre sauvegarde, plus tard.
|
||||
|
||||
Vous n'aurez plus besoin d'entrer ces informations à nouveau pour ce personnage, à moins que votre session ne change d'ip ou de port.
|
||||
Si l'ip ou le port de la session **change**, vous pouvez suivre ces instructions pour modifier les informations de connexion liées à votre sauvegarde :
|
||||
|
||||
- Lancer Stardew Valley moddé
|
||||
- Dans le **menu principal** du jeu, entrer la commande suivante **dans la console de SMAPI** :
|
||||
- `connect_override ip:port slot password`
|
||||
- Par exemple : `connect_override archipelago.gg:54321 StardewPlayer`
|
||||
- Chargez votre partie. Les nouvelles informations de connexion seront utilisées à la place de celles enregistrées initialement.
|
||||
- Jouez une journée, dormez et sauvegarder la partie. Les nouvelles informations de connexion iront écraser les précédentes, et deviendront permanentes.
|
||||
|
||||
### Intéragir avec le MultiWorld depuis le jeu
|
||||
|
||||
Quand vous vous connectez, vous devriez voir un message dans le chat vous informant de l'existence de la commande `!!help`. Cette commande liste les autres commandes exclusives à Stardew Valley que vous pouvez utiliser.
|
||||
|
||||
De plus, vous pouvez utiliser le chat en jeu pour parler aux autres joueurs du MultiWorld, pour peu qu'ils aient un jeu qui supporte le chat.
|
||||
|
||||
Enfin, vous pouvez également utiliser les commandes Archipelago (`!help` pour les lister) depuis le chat du jeu, permettant de demander des indices (via la commande `!hint`) sur certains objets.
|
||||
|
||||
Il est important de préciser que le chat de Stardew Valley est assez limité. Par exemple, il ne permet pas de remonter l'historique de conversation. La console SMAPI qui tourne à côté aura quant à elle l'historique complet et sera plus pratique pour consulter des messages moins récents.
|
||||
Pour une meilleure expérience avec le chat, vous pouvez aussi utiliser le client textuel d'Archipelago, bien qu'il ne permettra pas de lancer les commandes exclusives à Stardew Valley.
|
||||
|
||||
### Jouer avec des mods supportés
|
||||
|
||||
Voir la [documentation des mods supportés](https://github.com/agilbert1412/StardewArchipelago/blob/6.x.x/Documentation/Supported%20Mods.md) (en Anglais).
|
||||
|
||||
### Multijoueur
|
||||
|
||||
Vous ne pouvez pas jouer à Stardew Valley en mode multijoueur pour le moment. Il n'y a aucun plan d'action pour ajouter cette fonctionalité à court terme.
|
||||
@@ -443,27 +443,27 @@ def set_walnut_puzzle_rules(logic: StardewLogic, multiworld, player, world_optio
|
||||
if WalnutsanityOptionName.puzzles not in world_options.walnutsanity:
|
||||
return
|
||||
|
||||
set_rule(multiworld.get_location("Open Golden Coconut", player), logic.has(Geode.golden_coconut))
|
||||
set_rule(multiworld.get_location("Banana Altar", player), logic.has(Fruit.banana))
|
||||
set_rule(multiworld.get_location("Leo's Tree", player), logic.tool.has_tool(Tool.axe))
|
||||
set_rule(multiworld.get_location("Gem Birds Shrine", player), logic.has(Mineral.amethyst) & logic.has(Mineral.aquamarine) &
|
||||
set_rule(multiworld.get_location("Walnutsanity: Open Golden Coconut", player), logic.has(Geode.golden_coconut))
|
||||
set_rule(multiworld.get_location("Walnutsanity: Banana Altar", player), logic.has(Fruit.banana))
|
||||
set_rule(multiworld.get_location("Walnutsanity: Leo's Tree", player), logic.tool.has_tool(Tool.axe))
|
||||
set_rule(multiworld.get_location("Walnutsanity: Gem Birds Shrine", player), logic.has(Mineral.amethyst) & logic.has(Mineral.aquamarine) &
|
||||
logic.has(Mineral.emerald) & logic.has(Mineral.ruby) & logic.has(Mineral.topaz) &
|
||||
logic.region.can_reach_all((Region.island_north, Region.island_west, Region.island_east, Region.island_south)))
|
||||
set_rule(multiworld.get_location("Gourmand Frog Melon", player), logic.has(Fruit.melon) & logic.region.can_reach(Region.island_west))
|
||||
set_rule(multiworld.get_location("Gourmand Frog Wheat", player), logic.has(Vegetable.wheat) &
|
||||
logic.region.can_reach(Region.island_west) & logic.region.can_reach_location("Gourmand Frog Melon"))
|
||||
set_rule(multiworld.get_location("Gourmand Frog Garlic", player), logic.has(Vegetable.garlic) &
|
||||
logic.region.can_reach(Region.island_west) & logic.region.can_reach_location("Gourmand Frog Wheat"))
|
||||
set_rule(multiworld.get_location("Whack A Mole", player), logic.tool.has_tool(Tool.watering_can, ToolMaterial.iridium))
|
||||
set_rule(multiworld.get_location("Complete Large Animal Collection", player), logic.walnut.can_complete_large_animal_collection())
|
||||
set_rule(multiworld.get_location("Complete Snake Collection", player), logic.walnut.can_complete_snake_collection())
|
||||
set_rule(multiworld.get_location("Complete Mummified Frog Collection", player), logic.walnut.can_complete_frog_collection())
|
||||
set_rule(multiworld.get_location("Complete Mummified Bat Collection", player), logic.walnut.can_complete_bat_collection())
|
||||
set_rule(multiworld.get_location("Purple Flowers Island Survey", player), logic.walnut.can_start_field_office)
|
||||
set_rule(multiworld.get_location("Purple Starfish Island Survey", player), logic.walnut.can_start_field_office)
|
||||
set_rule(multiworld.get_location("Protruding Tree Walnut", player), logic.combat.has_slingshot)
|
||||
set_rule(multiworld.get_location("Starfish Tide Pool", player), logic.tool.has_fishing_rod(1))
|
||||
set_rule(multiworld.get_location("Mermaid Song", player), logic.has(Furniture.flute_block))
|
||||
set_rule(multiworld.get_location("Walnutsanity: Gourmand Frog Melon", player), logic.has(Fruit.melon) & logic.region.can_reach(Region.island_west))
|
||||
set_rule(multiworld.get_location("Walnutsanity: Gourmand Frog Wheat", player), logic.has(Vegetable.wheat) &
|
||||
logic.region.can_reach(Region.island_west) & logic.region.can_reach_location("Walnutsanity: Gourmand Frog Melon"))
|
||||
set_rule(multiworld.get_location("Walnutsanity: Gourmand Frog Garlic", player), logic.has(Vegetable.garlic) &
|
||||
logic.region.can_reach(Region.island_west) & logic.region.can_reach_location("Walnutsanity: Gourmand Frog Wheat"))
|
||||
set_rule(multiworld.get_location("Walnutsanity: Whack A Mole", player), logic.tool.has_tool(Tool.watering_can, ToolMaterial.iridium))
|
||||
set_rule(multiworld.get_location("Walnutsanity: Complete Large Animal Collection", player), logic.walnut.can_complete_large_animal_collection())
|
||||
set_rule(multiworld.get_location("Walnutsanity: Complete Snake Collection", player), logic.walnut.can_complete_snake_collection())
|
||||
set_rule(multiworld.get_location("Walnutsanity: Complete Mummified Frog Collection", player), logic.walnut.can_complete_frog_collection())
|
||||
set_rule(multiworld.get_location("Walnutsanity: Complete Mummified Bat Collection", player), logic.walnut.can_complete_bat_collection())
|
||||
set_rule(multiworld.get_location("Walnutsanity: Purple Flowers Island Survey", player), logic.walnut.can_start_field_office)
|
||||
set_rule(multiworld.get_location("Walnutsanity: Purple Starfish Island Survey", player), logic.walnut.can_start_field_office)
|
||||
set_rule(multiworld.get_location("Walnutsanity: Protruding Tree Walnut", player), logic.combat.has_slingshot)
|
||||
set_rule(multiworld.get_location("Walnutsanity: Starfish Tide Pool", player), logic.tool.has_fishing_rod(1))
|
||||
set_rule(multiworld.get_location("Walnutsanity: Mermaid Song", player), logic.has(Furniture.flute_block))
|
||||
|
||||
|
||||
def set_walnut_bushes_rules(logic, multiworld, player, world_options):
|
||||
@@ -490,13 +490,13 @@ def set_walnut_repeatable_rules(logic, multiworld, player, world_options):
|
||||
if WalnutsanityOptionName.repeatables not in world_options.walnutsanity:
|
||||
return
|
||||
for i in range(1, 6):
|
||||
set_rule(multiworld.get_location(f"Fishing Walnut {i}", player), logic.tool.has_fishing_rod(1))
|
||||
set_rule(multiworld.get_location(f"Harvesting Walnut {i}", player), logic.skill.can_get_farming_xp)
|
||||
set_rule(multiworld.get_location(f"Mussel Node Walnut {i}", player), logic.tool.has_tool(Tool.pickaxe))
|
||||
set_rule(multiworld.get_location(f"Volcano Rocks Walnut {i}", player), logic.tool.has_tool(Tool.pickaxe))
|
||||
set_rule(multiworld.get_location(f"Volcano Monsters Walnut {i}", player), logic.combat.has_galaxy_weapon)
|
||||
set_rule(multiworld.get_location(f"Volcano Crates Walnut {i}", player), logic.combat.has_any_weapon)
|
||||
set_rule(multiworld.get_location(f"Tiger Slime Walnut", player), logic.monster.can_kill(Monster.tiger_slime))
|
||||
set_rule(multiworld.get_location(f"Walnutsanity: Fishing Walnut {i}", player), logic.tool.has_fishing_rod(1))
|
||||
set_rule(multiworld.get_location(f"Walnutsanity: Harvesting Walnut {i}", player), logic.skill.can_get_farming_xp)
|
||||
set_rule(multiworld.get_location(f"Walnutsanity: Mussel Node Walnut {i}", player), logic.tool.has_tool(Tool.pickaxe))
|
||||
set_rule(multiworld.get_location(f"Walnutsanity: Volcano Rocks Walnut {i}", player), logic.tool.has_tool(Tool.pickaxe))
|
||||
set_rule(multiworld.get_location(f"Walnutsanity: Volcano Monsters Walnut {i}", player), logic.combat.has_galaxy_weapon)
|
||||
set_rule(multiworld.get_location(f"Walnutsanity: Volcano Crates Walnut {i}", player), logic.combat.has_any_weapon)
|
||||
set_rule(multiworld.get_location(f"Walnutsanity: Tiger Slime Walnut", player), logic.monster.can_kill(Monster.tiger_slime))
|
||||
|
||||
|
||||
def set_cropsanity_rules(logic: StardewLogic, multiworld, player, world_content: StardewContent):
|
||||
|
||||
@@ -1,26 +1,46 @@
|
||||
import unittest
|
||||
|
||||
from .bases import SVTestBase
|
||||
from ..options import ExcludeGingerIsland, Walnutsanity, ToolProgression, SkillProgression
|
||||
from ..strings.ap_names.ap_option_names import WalnutsanityOptionName
|
||||
|
||||
|
||||
class TestWalnutsanityNone(SVTestBase):
|
||||
class SVWalnutsanityTestBase(SVTestBase):
|
||||
expected_walnut_locations: set[str] = set()
|
||||
unexpected_walnut_locations: set[str] = set()
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
if cls is SVWalnutsanityTestBase:
|
||||
raise unittest.SkipTest("Base tests disabled")
|
||||
|
||||
super().setUpClass()
|
||||
|
||||
def test_walnut_locations(self):
|
||||
location_names = {location.name for location in self.multiworld.get_locations()}
|
||||
for location in self.expected_walnut_locations:
|
||||
self.assertIn(location, location_names, f"{location} should be in the location names")
|
||||
for location in self.unexpected_walnut_locations:
|
||||
self.assertNotIn(location, location_names, f"{location} should not be in the location names")
|
||||
|
||||
|
||||
class TestWalnutsanityNone(SVWalnutsanityTestBase):
|
||||
options = {
|
||||
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
||||
Walnutsanity: Walnutsanity.preset_none,
|
||||
SkillProgression: ToolProgression.option_progressive,
|
||||
ToolProgression: ToolProgression.option_progressive,
|
||||
}
|
||||
|
||||
def test_no_walnut_locations(self):
|
||||
location_names = {location.name for location in self.multiworld.get_locations()}
|
||||
self.assertNotIn("Open Golden Coconut", location_names)
|
||||
self.assertNotIn("Fishing Walnut 4", location_names)
|
||||
self.assertNotIn("Journal Scrap #6", location_names)
|
||||
self.assertNotIn("Starfish Triangle", location_names)
|
||||
self.assertNotIn("Bush Behind Coconut Tree", location_names)
|
||||
self.assertNotIn("Purple Starfish Island Survey", location_names)
|
||||
self.assertNotIn("Volcano Monsters Walnut 3", location_names)
|
||||
self.assertNotIn("Cliff Over Island South Bush", location_names)
|
||||
unexpected_walnut_locations = {
|
||||
"Walnutsanity: Open Golden Coconut",
|
||||
"Walnutsanity: Fishing Walnut 4",
|
||||
"Walnutsanity: Journal Scrap #6",
|
||||
"Walnutsanity: Starfish Triangle",
|
||||
"Walnutsanity: Bush Behind Coconut Tree",
|
||||
"Walnutsanity: Purple Starfish Island Survey",
|
||||
"Walnutsanity: Volcano Monsters Walnut 3",
|
||||
"Walnutsanity: Cliff Over Island South Bush",
|
||||
}
|
||||
|
||||
def test_logic_received_walnuts(self):
|
||||
# You need to receive 0, and collect 40
|
||||
@@ -48,28 +68,30 @@ class TestWalnutsanityNone(SVTestBase):
|
||||
self.assertTrue(self.multiworld.state.can_reach_location("Parrot Express", self.player))
|
||||
|
||||
|
||||
class TestWalnutsanityPuzzles(SVTestBase):
|
||||
class TestWalnutsanityPuzzles(SVWalnutsanityTestBase):
|
||||
options = {
|
||||
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
||||
Walnutsanity: frozenset({WalnutsanityOptionName.puzzles}),
|
||||
SkillProgression: ToolProgression.option_progressive,
|
||||
ToolProgression: ToolProgression.option_progressive,
|
||||
}
|
||||
|
||||
def test_only_puzzle_walnut_locations(self):
|
||||
location_names = {location.name for location in self.multiworld.get_locations()}
|
||||
self.assertIn("Open Golden Coconut", location_names)
|
||||
self.assertNotIn("Fishing Walnut 4", location_names)
|
||||
self.assertNotIn("Journal Scrap #6", location_names)
|
||||
self.assertNotIn("Starfish Triangle", location_names)
|
||||
self.assertNotIn("Bush Behind Coconut Tree", location_names)
|
||||
self.assertIn("Purple Starfish Island Survey", location_names)
|
||||
self.assertNotIn("Volcano Monsters Walnut 3", location_names)
|
||||
self.assertNotIn("Cliff Over Island South Bush", location_names)
|
||||
expected_walnut_locations = {
|
||||
"Walnutsanity: Open Golden Coconut",
|
||||
"Walnutsanity: Purple Starfish Island Survey",
|
||||
}
|
||||
unexpected_walnut_locations = {
|
||||
"Walnutsanity: Fishing Walnut 4",
|
||||
"Walnutsanity: Journal Scrap #6",
|
||||
"Walnutsanity: Starfish Triangle",
|
||||
"Walnutsanity: Bush Behind Coconut Tree",
|
||||
"Walnutsanity: Volcano Monsters Walnut 3",
|
||||
"Walnutsanity: Cliff Over Island South Bush",
|
||||
}
|
||||
|
||||
def test_field_office_locations_require_professor_snail(self):
|
||||
location_names = ["Complete Large Animal Collection", "Complete Snake Collection", "Complete Mummified Frog Collection",
|
||||
"Complete Mummified Bat Collection", "Purple Flowers Island Survey", "Purple Starfish Island Survey", ]
|
||||
location_names = ["Walnutsanity: Complete Large Animal Collection", "Walnutsanity: Complete Snake Collection",
|
||||
"Walnutsanity: Complete Mummified Frog Collection", "Walnutsanity: Complete Mummified Bat Collection",
|
||||
"Walnutsanity: Purple Flowers Island Survey", "Walnutsanity: Purple Starfish Island Survey", ]
|
||||
self.collect("Island Obelisk")
|
||||
self.collect("Island North Turtle")
|
||||
self.collect("Island West Turtle")
|
||||
@@ -90,40 +112,42 @@ class TestWalnutsanityPuzzles(SVTestBase):
|
||||
self.assert_can_reach_location(location)
|
||||
|
||||
|
||||
class TestWalnutsanityBushes(SVTestBase):
|
||||
class TestWalnutsanityBushes(SVWalnutsanityTestBase):
|
||||
options = {
|
||||
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
||||
Walnutsanity: frozenset({WalnutsanityOptionName.bushes}),
|
||||
}
|
||||
|
||||
def test_only_bush_walnut_locations(self):
|
||||
location_names = {location.name for location in self.multiworld.get_locations()}
|
||||
self.assertNotIn("Open Golden Coconut", location_names)
|
||||
self.assertNotIn("Fishing Walnut 4", location_names)
|
||||
self.assertNotIn("Journal Scrap #6", location_names)
|
||||
self.assertNotIn("Starfish Triangle", location_names)
|
||||
self.assertIn("Bush Behind Coconut Tree", location_names)
|
||||
self.assertNotIn("Purple Starfish Island Survey", location_names)
|
||||
self.assertNotIn("Volcano Monsters Walnut 3", location_names)
|
||||
self.assertIn("Cliff Over Island South Bush", location_names)
|
||||
expected_walnut_locations = {
|
||||
"Walnutsanity: Bush Behind Coconut Tree",
|
||||
"Walnutsanity: Cliff Over Island South Bush",
|
||||
}
|
||||
unexpected_walnut_locations = {
|
||||
"Walnutsanity: Open Golden Coconut",
|
||||
"Walnutsanity: Fishing Walnut 4",
|
||||
"Walnutsanity: Journal Scrap #6",
|
||||
"Walnutsanity: Starfish Triangle",
|
||||
"Walnutsanity: Purple Starfish Island Survey",
|
||||
"Walnutsanity: Volcano Monsters Walnut 3",
|
||||
}
|
||||
|
||||
|
||||
class TestWalnutsanityPuzzlesAndBushes(SVTestBase):
|
||||
class TestWalnutsanityPuzzlesAndBushes(SVWalnutsanityTestBase):
|
||||
options = {
|
||||
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
||||
Walnutsanity: frozenset({WalnutsanityOptionName.puzzles, WalnutsanityOptionName.bushes}),
|
||||
}
|
||||
|
||||
def test_only_bush_walnut_locations(self):
|
||||
location_names = {location.name for location in self.multiworld.get_locations()}
|
||||
self.assertIn("Open Golden Coconut", location_names)
|
||||
self.assertNotIn("Fishing Walnut 4", location_names)
|
||||
self.assertNotIn("Journal Scrap #6", location_names)
|
||||
self.assertNotIn("Starfish Triangle", location_names)
|
||||
self.assertIn("Bush Behind Coconut Tree", location_names)
|
||||
self.assertIn("Purple Starfish Island Survey", location_names)
|
||||
self.assertNotIn("Volcano Monsters Walnut 3", location_names)
|
||||
self.assertIn("Cliff Over Island South Bush", location_names)
|
||||
expected_walnut_locations = {
|
||||
"Walnutsanity: Open Golden Coconut",
|
||||
"Walnutsanity: Bush Behind Coconut Tree",
|
||||
"Walnutsanity: Purple Starfish Island Survey",
|
||||
"Walnutsanity: Cliff Over Island South Bush",
|
||||
}
|
||||
unexpected_walnut_locations = {
|
||||
"Walnutsanity: Fishing Walnut 4",
|
||||
"Walnutsanity: Journal Scrap #6",
|
||||
"Walnutsanity: Starfish Triangle",
|
||||
"Walnutsanity: Volcano Monsters Walnut 3",
|
||||
}
|
||||
|
||||
def test_logic_received_walnuts(self):
|
||||
# You need to receive 25, and collect 15
|
||||
@@ -136,58 +160,59 @@ class TestWalnutsanityPuzzlesAndBushes(SVTestBase):
|
||||
self.assertTrue(self.multiworld.state.can_reach_location("Parrot Express", self.player))
|
||||
|
||||
|
||||
class TestWalnutsanityDigSpots(SVTestBase):
|
||||
class TestWalnutsanityDigSpots(SVWalnutsanityTestBase):
|
||||
options = {
|
||||
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
||||
Walnutsanity: frozenset({WalnutsanityOptionName.dig_spots}),
|
||||
}
|
||||
|
||||
def test_only_dig_spots_walnut_locations(self):
|
||||
location_names = {location.name for location in self.multiworld.get_locations()}
|
||||
self.assertNotIn("Open Golden Coconut", location_names)
|
||||
self.assertNotIn("Fishing Walnut 4", location_names)
|
||||
self.assertIn("Journal Scrap #6", location_names)
|
||||
self.assertIn("Starfish Triangle", location_names)
|
||||
self.assertNotIn("Bush Behind Coconut Tree", location_names)
|
||||
self.assertNotIn("Purple Starfish Island Survey", location_names)
|
||||
self.assertNotIn("Volcano Monsters Walnut 3", location_names)
|
||||
self.assertNotIn("Cliff Over Island South Bush", location_names)
|
||||
expected_walnut_locations = {
|
||||
"Walnutsanity: Journal Scrap #6",
|
||||
"Walnutsanity: Starfish Triangle",
|
||||
}
|
||||
unexpected_walnut_locations = {
|
||||
"Walnutsanity: Open Golden Coconut",
|
||||
"Walnutsanity: Fishing Walnut 4",
|
||||
"Walnutsanity: Bush Behind Coconut Tree",
|
||||
"Walnutsanity: Purple Starfish Island Survey",
|
||||
"Walnutsanity: Volcano Monsters Walnut 3",
|
||||
"Walnutsanity: Cliff Over Island South Bush",
|
||||
}
|
||||
|
||||
|
||||
class TestWalnutsanityRepeatables(SVTestBase):
|
||||
class TestWalnutsanityRepeatables(SVWalnutsanityTestBase):
|
||||
options = {
|
||||
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
||||
Walnutsanity: frozenset({WalnutsanityOptionName.repeatables}),
|
||||
}
|
||||
|
||||
def test_only_repeatable_walnut_locations(self):
|
||||
location_names = {location.name for location in self.multiworld.get_locations()}
|
||||
self.assertNotIn("Open Golden Coconut", location_names)
|
||||
self.assertIn("Fishing Walnut 4", location_names)
|
||||
self.assertNotIn("Journal Scrap #6", location_names)
|
||||
self.assertNotIn("Starfish Triangle", location_names)
|
||||
self.assertNotIn("Bush Behind Coconut Tree", location_names)
|
||||
self.assertNotIn("Purple Starfish Island Survey", location_names)
|
||||
self.assertIn("Volcano Monsters Walnut 3", location_names)
|
||||
self.assertNotIn("Cliff Over Island South Bush", location_names)
|
||||
expected_walnut_locations = {
|
||||
"Walnutsanity: Fishing Walnut 4",
|
||||
"Walnutsanity: Volcano Monsters Walnut 3",
|
||||
}
|
||||
unexpected_walnut_locations = {
|
||||
"Walnutsanity: Open Golden Coconut",
|
||||
"Walnutsanity: Journal Scrap #6",
|
||||
"Walnutsanity: Starfish Triangle",
|
||||
"Walnutsanity: Bush Behind Coconut Tree",
|
||||
"Walnutsanity: Purple Starfish Island Survey",
|
||||
"Walnutsanity: Cliff Over Island South Bush",
|
||||
}
|
||||
|
||||
|
||||
class TestWalnutsanityAll(SVTestBase):
|
||||
class TestWalnutsanityAll(SVWalnutsanityTestBase):
|
||||
options = {
|
||||
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
||||
Walnutsanity: Walnutsanity.preset_all,
|
||||
}
|
||||
|
||||
def test_all_walnut_locations(self):
|
||||
location_names = {location.name for location in self.multiworld.get_locations()}
|
||||
self.assertIn("Open Golden Coconut", location_names)
|
||||
self.assertIn("Fishing Walnut 4", location_names)
|
||||
self.assertIn("Journal Scrap #6", location_names)
|
||||
self.assertIn("Starfish Triangle", location_names)
|
||||
self.assertIn("Bush Behind Coconut Tree", location_names)
|
||||
self.assertIn("Purple Starfish Island Survey", location_names)
|
||||
self.assertIn("Volcano Monsters Walnut 3", location_names)
|
||||
self.assertIn("Cliff Over Island South Bush", location_names)
|
||||
expected_walnut_locations = {
|
||||
"Walnutsanity: Open Golden Coconut",
|
||||
"Walnutsanity: Fishing Walnut 4",
|
||||
"Walnutsanity: Journal Scrap #6",
|
||||
"Walnutsanity: Starfish Triangle",
|
||||
"Walnutsanity: Bush Behind Coconut Tree",
|
||||
"Walnutsanity: Purple Starfish Island Survey",
|
||||
"Walnutsanity: Volcano Monsters Walnut 3",
|
||||
"Walnutsanity: Cliff Over Island South Bush",
|
||||
}
|
||||
|
||||
def test_logic_received_walnuts(self):
|
||||
# You need to receive 40, and collect 4
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
from test.bases import WorldTestBase
|
||||
|
||||
|
||||
class TunicTestBase(WorldTestBase):
|
||||
game = "TUNIC"
|
||||
player = 1
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
from test.bases import WorldTestBase
|
||||
|
||||
|
||||
class TunicTestBase(WorldTestBase):
|
||||
game = "TUNIC"
|
||||
@@ -1,5 +1,5 @@
|
||||
from . import TunicTestBase
|
||||
from .. import options
|
||||
from .bases import TunicTestBase
|
||||
|
||||
|
||||
class TestAccess(TunicTestBase):
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
from BaseClasses import ItemClassification
|
||||
from collections import Counter
|
||||
|
||||
from . import TunicTestBase
|
||||
from .. import options
|
||||
from .. import options, TunicWorld
|
||||
from .bases import TunicTestBase
|
||||
from ..combat_logic import (check_combat_reqs, area_data, get_money_count, calc_effective_hp, get_potion_level,
|
||||
get_hp_level, get_def_level, get_sp_level, has_combat_reqs)
|
||||
from ..items import item_table
|
||||
from .. import TunicWorld
|
||||
|
||||
|
||||
class TestCombat(TunicTestBase):
|
||||
options = {options.CombatLogic.internal_name: options.CombatLogic.option_on}
|
||||
player = 1
|
||||
world: TunicWorld
|
||||
combat_items = []
|
||||
# these are items that are progression that do not contribute to combat logic
|
||||
|
||||
@@ -27,14 +27,32 @@ from .rules import set_rules
|
||||
|
||||
class WitnessWebWorld(WebWorld):
|
||||
theme = "jungle"
|
||||
tutorials = [Tutorial(
|
||||
setup_en = Tutorial(
|
||||
"Multiworld Setup Guide",
|
||||
"A guide to playing The Witness with Archipelago.",
|
||||
"English",
|
||||
"setup_en.md",
|
||||
"setup/en",
|
||||
["NewSoupVi", "Jarno"]
|
||||
)]
|
||||
)
|
||||
setup_de = Tutorial(
|
||||
setup_en.tutorial_name,
|
||||
setup_en.description,
|
||||
"German",
|
||||
"setup_de.md",
|
||||
"setup/de",
|
||||
["NewSoupVi"]
|
||||
)
|
||||
setup_fr = Tutorial(
|
||||
setup_en.tutorial_name,
|
||||
setup_en.description,
|
||||
"Français",
|
||||
"setup_fr.md",
|
||||
"setup/fr",
|
||||
["Rever"]
|
||||
)
|
||||
|
||||
tutorials = [setup_en, setup_de, setup_fr]
|
||||
|
||||
options_presets = witness_option_presets
|
||||
option_groups = witness_option_groups
|
||||
|
||||
@@ -18,6 +18,7 @@ GENERAL_LOCATIONS = {
|
||||
"Outside Tutorial Outpost Entry Panel",
|
||||
"Outside Tutorial Outpost Exit Panel",
|
||||
|
||||
"Glass Factory Entry Panel",
|
||||
"Glass Factory Discard",
|
||||
"Glass Factory Back Wall 5",
|
||||
"Glass Factory Front 3",
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# The Witness Randomizer Setup
|
||||
|
||||
## Benötigte Software
|
||||
|
||||
- [The Witness für ein 64-bit-Windows-Betriebssystem (z.B. Steam-Version)](https://store.steampowered.com/app/210970/The_Witness/)
|
||||
- [The Witness Archipelago Randomizer](https://github.com/NewSoupVi/The-Witness-Randomizer-for-Archipelago/releases/latest)
|
||||
|
||||
## Optionale Software
|
||||
|
||||
- [ArchipelagoTextClient](https://github.com/ArchipelagoMW/Archipelago/releases)
|
||||
- [The Witness Auto-Tracker mit Kartenansicht](https://github.com/NewSoupVi/witness_archipelago_tracker/releases), benutzbar mit [PopTracker](https://github.com/black-sliver/PopTracker/releases)
|
||||
|
||||
## Verbindung mit einem Multiworld-Spiel
|
||||
|
||||
1. Öffne The Witness.
|
||||
2. Erstelle einen neuen Speicherstand.
|
||||
3. Öffne [The Witness Archipelago Randomizer](https://github.com/NewSoupVi/The-Witness-Randomizer-for-Archipelago/releases/latest).
|
||||
4. Gib die Archipelago-Adresse, deinen Namen und evtl. das Passwort ein.
|
||||
5. Drücke "Connect".
|
||||
6. Viel Spaß!
|
||||
|
||||
Wenn du ein vorheriges Spiel fortsetzen willst, ist das auch möüglich:
|
||||
|
||||
1. Öffne The Witness.
|
||||
2. Lade den Speicherstand für das Multiworld-Spiel, das du weiterspielen willst - Wenn das nicht sowieso schon der ist, den das Spiel automatisch geladen hat.
|
||||
3. Öffne [The Witness Archipelago Randomizer](https://github.com/NewSoupVi/The-Witness-Randomizer-for-Archipelago/releases/latest).
|
||||
4. Drücke "Load Credentials", um Adresse, Namen und Passwort automatisch zu laden (oder tippe diese manuell ein).
|
||||
5. Drücke "Connect".
|
||||
|
||||
## Archipelago Text Client
|
||||
|
||||
Es ist empfehlenswert, den "Archipelago Text Client", der eine Textansicht für gesendete und erhaltene Items liefert, beim Spielen nebenbei sichtbar zu haben.
|
||||
<br/>Diese Nachrichten werden zwar auch im Spiel angezeigt, jedoch nur für ein paar Sekunden. Es ist leicht, eine dieser Nachrichten zu übersehen.
|
||||
|
||||
<br/><br/>Alternativ gibt es den visuellen Auto-Tracker mit Kartenansicht, der im nächsten Kapitel beschrieben wird.
|
||||
|
||||
## Auto-Tracking
|
||||
|
||||
The Witness hat einen voll funktionsfähigen Tracker mit Kartenansicht und Autotracking.
|
||||
|
||||
1. Installiere [PopTracker](https://github.com/black-sliver/PopTracker/releases) und lade den [The Witness Auto-Tracker mit Kartenansicht](https://github.com/NewSoupVi/witness_archipelago_tracker/releases) herunter.
|
||||
2. Öffne PopTracker, und lade das "The Witness"-Packet.
|
||||
3. Klicke auf das "AP"-Symbol am oberen Fensterrand.
|
||||
4. Gib die Archipelago-Adresse, deinen Namen und evtl. das Passwort ein.
|
||||
|
||||
Der Rest sollte vollautomatisch ohne weitere Eingabe funktionieren. Der Tracker wird deine momentanen Items anzeigen und lösbare Rätsel grün auf der Karte anzeigen. Sobald du eine Rätselsequenz abschließt, wird sie grau markiert.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Guide d'installation du Witness randomizer
|
||||
|
||||
## Logiciels Requis
|
||||
|
||||
- [The Witness pour Windows 64-bit (par exemple, la version Steam)](https://store.steampowered.com/app/210970/The_Witness/)
|
||||
- [The Witness Archipelago Randomizer](https://github.com/NewSoupVi/The-Witness-Randomizer-for-Archipelago/releases/latest)
|
||||
|
||||
## Logiciels Facultatifs
|
||||
|
||||
- [ArchipelagoTextClient](https://github.com/ArchipelagoMW/Archipelago/releases)
|
||||
- [The Witness Map- et Auto-Tracker](https://github.com/NewSoupVi/witness_archipelago_tracker/releases), pour usage avec [PopTracker](https://github.com/black-sliver/PopTracker/releases)
|
||||
|
||||
## Rejoindre un jeu multimonde
|
||||
|
||||
1. Lancez The Witness
|
||||
2. Commencez une nouvelle partie
|
||||
3. Lancez [The Witness Archipelago Randomizer](https://github.com/NewSoupVi/The-Witness-Randomizer-for-Archipelago/releases/latest)
|
||||
4. Inscrivez l'adresse Archipelago, votre nom de joueur et le mot de passe du jeu multimonde
|
||||
5. Cliquez sur "Connect"
|
||||
6. Jouez!
|
||||
|
||||
Pour continuer un jeu multimonde précedemment commencé:
|
||||
|
||||
1. Lancez The Witness
|
||||
2. Chargez la sauvegarde sur laquelle vous avez dernièrement joué ce monde, si ce n'est pas celle qui a été chargée automatiquement
|
||||
3. Lancez [The Witness Archipelago Randomizer](https://github.com/NewSoupVi/The-Witness-Randomizer-for-Archipelago/releases/latest)
|
||||
4. Cliquez sur "Load Credentials" (ou tapez les manuellement)
|
||||
5. Cliquez sur "Connect"
|
||||
|
||||
## Archipelago Text Client
|
||||
|
||||
Il est recommandé d'utiliser le "Archipelago Text Client" en parallèle afin de suivre quels items vous envoyez et recevez.
|
||||
<br/>The Witness affiche également ces informations en jeu, mais seulement pour une courte période et donc il est facile de manquer ces messages.
|
||||
|
||||
<br/><br/>Bien sûr, vous pouvez également utiliser l'auto-tracker!
|
||||
|
||||
## Auto-Tracking
|
||||
|
||||
The Witness a un tracker fonctionnel qui supporte l'auto-tracking.
|
||||
|
||||
1. Téléchargez [The Witness Map- and Auto-Tracker](https://github.com/NewSoupVi/witness_archipelago_tracker/releases) et [PopTracker](https://github.com/black-sliver/PopTracker/releases).
|
||||
2. Ouvrez Poptracker, puis chargez le pack Witness.
|
||||
3. Cliquez sur l'icone "AP" qui se situe au dessus de la carte.
|
||||
4. Inscrivez l'adresse Archipelago, votre nom de joueur et le mot de passe du jeu multimonde.
|
||||
|
||||
Le reste devrait être pris en charge par Poptracker - les items que vous recevrez et les puzzles que vous résolverez seront automatiquement indiqués. De plus, Poptracker est en mesure de détecter
|
||||
vos paramètres de jeu - les puzzles accessibles seront alors masqués ou affichés en fonction de vos paramètres de randomization et de logique. Veuillez noter que le tracker peut être obsolète.
|
||||
Reference in New Issue
Block a user