Compare commits

...

16 Commits

Author SHA1 Message Date
Fabian Dill
257b2e4e85 SMZ3: fix type 2024-01-01 20:39:58 +01:00
Fabian Dill
ad2275c78a Core: Move Location.always_allow to a subclass 2024-01-01 18:07:08 +01:00
lordlou
e674e37e08 SMZ3: optimized message queues (#2611) 2023-12-28 16:43:16 -06:00
Jarno
d1a17a350d Docs: Add missing Get location_name_groups_* to network protocol (#2550) 2023-12-28 14:41:24 +01:00
Fabian Dill
24ac3de125 Factorio: "improve" default start items (#2588)
Makes it less likely that people kill themselves via pollution and gives them some healing items they may not even know about.
2023-12-28 14:30:10 +01:00
Scipio Wright
901201f675 Noita: Don't allow impossible slot names (#2608)
* Noita: Add note about allowable slot names

* Update character list

* Update init to raise an exception if a yaml has bad characters

* Slightly adjust exception message
2023-12-28 14:21:54 +01:00
t3hf1gm3nt
c7617f92dd TLOZ: Try accounting for non_local_items with the pool of starting weapons (#2620)
It was brought up that if you attempt to non_local any of the starting weapons, there is still a chance for it to get chosen as your starting weapon if you are on a StartingPosition value lower than very_dangerous. This fix will attempt to build the starting weapons list accounting for non_local items, but if all possible weapons have been set to non_local, force one of them to be your starting weapon anyway since the player is still expecting a starting weapon in their world if they have chosen one of the lower StartingPosition values.
2023-12-28 14:17:23 +01:00
NewSoupVi
8e708f829d The Witness: Fix an instance of multiworld.random being used (#2630)
o_o
2023-12-28 14:12:37 +01:00
Fabian Dill
7af654e619 WebHost: validate uploaded datapackage and calculate own checksum (#2639) 2023-12-28 13:57:41 +01:00
TheLynk
af1f6e9113 Oot : Update setup fr (#2394)
* add new translation

* Add translation for OOT Setup in french

* Update setup_fr.md

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/minecraft/docs/minecraft_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/minecraft/docs/minecraft_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/minecraft/docs/minecraft_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/minecraft/docs/minecraft_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/minecraft/docs/minecraft_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/minecraft/docs/minecraft_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/minecraft/docs/minecraft_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/minecraft/docs/minecraft_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>

* Update setup_fr.md

Fix treu to true

* Update worlds/oot/docs/setup_fr.md

Co-authored-by: Marech <marechal-l@gmx.com>

* Update OOT Init and Update Minecraft Init

* Fix formatting errors

* Fix wrong link in stardew valley randomizer setup guide

Fix wrong link in stardew valley randomizer setup guide

* Add new translation for Adventure and Archipidle in french

Add new translation for Adventure and Archipidle in french

* Add more store in setup page subnautica for more fairness

Add more store in setup page subnautica for more fairness

* tweak update merge #1685 for lua file

tweak update merge #1685 for lua file

* fix text

fix text

* fix wrong translation

fix wrong translation

* Yes it's better

Yes it's better

Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com>

* Update OOT Setup FR

Update OOT Setup FR

* Tweak Text

Tweak Text

---------

Co-authored-by: Ludovic Marechal <marechal-l@gmx.com>
Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com>
Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com>
2023-12-28 13:43:42 +01:00
Bryce Wilson
04d194db74 Pokemon Emerald: Change "settings" to "options" in docs (#2517)
* Pokemon Emerald: Change "settings" to "options" in docs

* Pokemon Emerald: Fix two more usages of "setting" instead of "option"

* Pokemon Emerald: Minor rephrase in docs

Co-authored-by: Aaron Wagener <mmmcheese158@gmail.com>

---------

Co-authored-by: Aaron Wagener <mmmcheese158@gmail.com>
2023-12-28 13:33:30 +01:00
Rosalie-A
70eb2b58f5 [TLOZ] Fix bug with item drops in non-expanded item pool (#2623)
There was a bug in non-expanded item pool where due to the base patch changes to accommodate more items in dungeons, some items were transformed into glitch items that removed bombs (this also happened in expanded item pool, but the item placement would overwrite the results of this bug so it didn't appear as frequently). Being a Zelda game, losing bombs is bad. This PR fixes the base patch process to avoid this bug, by properly carrying the value of a variable through a procedure.
2023-12-28 12:16:38 +01:00
Alchav
576c705106 Pokémon R/B: Badge plando fix (#2628)
Only attempt to place badges in badge locations if they are empty. Return unplaced badges to the item pool if fewer than 8 locations are being filled.
This should fix errors that occur when items are placed into badge locations via plando, or whatever other worlds may do.
2023-12-28 12:15:48 +01:00
lordlou
b99c734954 SM: strict rom validation fix (#2632)
added a more robust ROM tag validation to free oher games to use tag starting with "SM" followed by another letter (SMW, SMZ3, SMRPG, SMMR,...)
2023-12-28 12:14:13 +01:00
Yussur Mustafa Oraji
7c70b87f29 sm64ex: Fix randomizing Courses and Secrets separately (#2637)
Backported from #2569
2023-12-28 08:01:48 +01:00
Trevor L
2512eb7501 Hylics 2: Add missing logic (#2638) 2023-12-28 06:25:41 +01:00
23 changed files with 149 additions and 448 deletions

View File

@@ -1018,10 +1018,9 @@ class Location:
self.parent_region = parent
def can_fill(self, state: CollectionState, item: Item, check_access=True) -> bool:
return ((self.always_allow(state, item) and item.name not in state.multiworld.non_local_items[item.player])
or ((self.progress_type != LocationProgressType.EXCLUDED or not (item.advancement or item.useful))
and self.item_rule(item)
and (not check_access or self.can_reach(state))))
return ((self.progress_type != LocationProgressType.EXCLUDED or not (item.advancement or item.useful))
and self.item_rule(item)
and (not check_access or self.can_reach(state)))
def can_reach(self, state: CollectionState) -> bool:
# self.access_rule computes faster on average, so placing it first for faster abort
@@ -1062,6 +1061,15 @@ class Location:
return "at " + self.name.replace("_", " ").replace("-", " ")
class AlwaysAllowLocation(Location):
"""Subclass of Location that allows an always_allow item rule, which overrides all other requirements."""
always_allow: Callable[[Item], bool] = staticmethod(lambda item, state: False)
def can_fill(self, state: CollectionState, item: Item, check_access=True) -> bool:
return ((self.always_allow(state, item) and item.name not in state.multiworld.non_local_items[item.player])
or super().can_fill(state, item, check_access))
class ItemClassification(IntFlag):
filler = 0b0000 # aka trash, as in filler items like ammo, currency etc,
progression = 0b0001 # Item that is logically relevant

View File

@@ -11,11 +11,14 @@ from flask import request, flash, redirect, url_for, session, render_template
from markupsafe import Markup
from pony.orm import commit, flush, select, rollback
from pony.orm.core import TransactionIntegrityError
import schema
import MultiServer
from NetUtils import SlotType
from Utils import VersionException, __version__
from worlds import GamesPackage
from worlds.Files import AutoPatchRegister
from worlds.AutoWorld import data_package_checksum
from . import app
from .models import Seed, Room, Slot, GameDataPackage
@@ -23,6 +26,15 @@ banned_extensions = (".sfc", ".z64", ".n64", ".nes", ".smc", ".sms", ".gb", ".gb
allowed_options_extensions = (".yaml", ".json", ".yml", ".txt", ".zip")
allowed_generation_extensions = (".archipelago", ".zip")
games_package_schema = schema.Schema({
"item_name_groups": {str: [str]},
"item_name_to_id": {str: int},
"location_name_groups": {str: [str]},
"location_name_to_id": {str: int},
schema.Optional("checksum"): str,
schema.Optional("version"): int,
})
def allowed_options(filename: str) -> bool:
return filename.endswith(allowed_options_extensions)
@@ -37,6 +49,8 @@ def banned_file(filename: str) -> bool:
def process_multidata(compressed_multidata, files={}):
game_data: GamesPackage
decompressed_multidata = MultiServer.Context.decompress(compressed_multidata)
slots: typing.Set[Slot] = set()
@@ -45,11 +59,19 @@ def process_multidata(compressed_multidata, files={}):
game_data_packages: typing.List[GameDataPackage] = []
for game, game_data in decompressed_multidata["datapackage"].items():
if game_data.get("checksum"):
original_checksum = game_data.pop("checksum")
game_data = games_package_schema.validate(game_data)
game_data = {key: value for key, value in sorted(game_data.items())}
game_data["checksum"] = data_package_checksum(game_data)
game_data_package = GameDataPackage(checksum=game_data["checksum"],
data=pickle.dumps(game_data))
if original_checksum != game_data["checksum"]:
raise Exception(f"Original checksum {original_checksum} != "
f"calculated checksum {game_data['checksum']} "
f"for game {game}.")
decompressed_multidata["datapackage"][game] = {
"version": game_data.get("version", 0),
"checksum": game_data["checksum"]
"checksum": game_data["checksum"],
}
try:
commit() # commit game data package
@@ -64,14 +86,15 @@ def process_multidata(compressed_multidata, files={}):
if slot_info.type == SlotType.group:
continue
slots.add(Slot(data=files.get(slot, None),
player_name=slot_info.name,
player_id=slot,
game=slot_info.game))
player_name=slot_info.name,
player_id=slot,
game=slot_info.game))
flush() # commit slots
compressed_multidata = compressed_multidata[0:1] + zlib.compress(pickle.dumps(decompressed_multidata), 9)
return slots, compressed_multidata
def upload_zip_to_db(zfile: zipfile.ZipFile, owner=None, meta={"race": False}, sid=None):
if not owner:
owner = session["_id"]

View File

@@ -380,12 +380,13 @@ Additional arguments sent in this package will also be added to the [Retrieved](
Some special keys exist with specific return data, all of them have the prefix `_read_`, so `hints_{team}_{slot}` is `_read_hints_{team}_{slot}`.
| Name | Type | Notes |
|------------------------------|-------------------------------|---------------------------------------------------|
| hints_{team}_{slot} | list\[[Hint](#Hint)\] | All Hints belonging to the requested Player. |
| slot_data_{slot} | dict\[str, any\] | slot_data belonging to the requested slot. |
| item_name_groups_{game_name} | dict\[str, list\[str\]\] | item_name_groups belonging to the requested game. |
| client_status_{team}_{slot} | [ClientStatus](#ClientStatus) | The current game status of the requested player. |
| Name | Type | Notes |
|----------------------------------|-------------------------------|-------------------------------------------------------|
| hints_{team}_{slot} | list\[[Hint](#Hint)\] | All Hints belonging to the requested Player. |
| slot_data_{slot} | dict\[str, any\] | slot_data belonging to the requested slot. |
| item_name_groups_{game_name} | dict\[str, list\[str\]\] | item_name_groups belonging to the requested game. |
| location_name_groups_{game_name} | dict\[str, list\[str\]\] | location_name_groups belonging to the requested game. |
| client_status_{team}_{slot} | [ClientStatus](#ClientStatus) | The current game status of the requested player. |
### Set
Used to write data to the server's data storage, that data can then be shared across worlds or just saved for later. Values for keys in the data storage can be retrieved with a [Get](#Get) package, or monitored with a [SetNotify](#SetNotify) package.

View File

@@ -2,14 +2,14 @@
from typing import Optional, TYPE_CHECKING
from enum import IntEnum
from BaseClasses import Location, Item, ItemClassification, Region, MultiWorld
from BaseClasses import AlwaysAllowLocation, Item, ItemClassification, Region, MultiWorld
if TYPE_CHECKING:
from .Dungeons import Dungeon
from .Regions import LTTPRegion
class ALttPLocation(Location):
class ALttPLocation(AlwaysAllowLocation):
game: str = "A Link to the Past"
crystal: bool
player_address: Optional[int]

View File

@@ -210,7 +210,7 @@ class RecipeIngredientsOffset(Range):
class FactorioStartItems(OptionDict):
"""Mapping of Factorio internal item-name to amount granted on start."""
display_name = "Starting Items"
default = {"burner-mining-drill": 19, "stone-furnace": 19}
default = {"burner-mining-drill": 4, "stone-furnace": 4, "raw-fish": 50}
class FactorioFreeSampleBlacklist(OptionSet):

View File

@@ -168,7 +168,8 @@ def allow_self_locking_items(spot: typing.Union[Location, Region], *item_names:
"""
This function sets rules on the supplied spot, such that the supplied item_name(s) can possibly be placed there.
spot: Location or Region that the item(s) are allowed to be placed in
spot: Location or Region that the item(s) are allowed to be placed in.
Affected Locations must subclass AlwaysAllowLocation.
item_names: item name or names that are allowed to be placed in the Location or Region
"""
player = spot.player

View File

@@ -444,6 +444,8 @@ def set_rules(hylics2world):
lambda state: paddle(state, player))
add_rule(world.get_location("Arcade 1: Alcove Medallion", player),
lambda state: paddle(state, player))
add_rule(world.get_location("Arcade 1: Lava Medallion", player),
lambda state: paddle(state, player))
add_rule(world.get_location("Foglast: Under Lair Medallion", player),
lambda state: bridge_key(state, player))
add_rule(world.get_location("Foglast: Mid-Air Medallion", player),

View File

@@ -1,7 +1,7 @@
from functools import cached_property
from typing import Optional, TYPE_CHECKING, cast
from BaseClasses import CollectionState, Item, ItemClassification, Location, Region
from BaseClasses import CollectionState, Item, ItemClassification, AlwaysAllowLocation, Region
from .constants import NOTES, PHOBEKINS, PROG_ITEMS, USEFUL_ITEMS
from .regions import MEGA_SHARDS, REGIONS, SEALS
from .shop import FIGURINES, PROG_SHOP_ITEMS, SHOP_ITEMS, USEFUL_SHOP_ITEMS
@@ -33,7 +33,7 @@ class MessengerRegion(Region):
world.multiworld.regions.append(self)
class MessengerLocation(Location):
class MessengerLocation(AlwaysAllowLocation):
game = "The Messenger"
def __init__(self, player: int, name: str, loc_id: Optional[int], parent: MessengerRegion) -> None:

View File

@@ -35,6 +35,10 @@ class NoitaWorld(World):
web = NoitaWeb()
def generate_early(self):
if not self.multiworld.get_player_name(self.player).isascii():
raise Exception("Noita yaml's slot name has invalid character(s).")
# Returned items will be sent over to the client
def fill_slot_data(self):
return {name: getattr(self.multiworld, name)[self.player].value for name in self.option_definitions}

View File

@@ -40,6 +40,8 @@ or try restarting your game.
### What is a YAML and why do I need one?
You can see the [basic multiworld setup guide](/tutorial/Archipelago/setup/en) here on the Archipelago website to learn
about why Archipelago uses YAML files and what they're for.
Please note that Noita only allows you to type certain characters for your slot name.
These characters are: `` !#$%&'()+,-.0123456789;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{}~<>|\/``
### Where do I get a YAML?
You can use the [game settings page for Noita](/games/Noita/player-settings) here on the Archipelago website to
@@ -54,4 +56,4 @@ Place the unzipped pack in the `packs` folder. Then, open Poptracker and open th
Click on the "AP" symbol at the top, then enter the desired address, slot name, and password.
That's all you need for it. It will provide you with a quick reference to see which checks you've done and
which checks you still have left.
which checks you still have left.

View File

@@ -1,422 +1,70 @@
# Guide d'installation Archipelago pour Ocarina of Time
# Guide de configuration pour Ocarina of Time Archipelago
## Important
Comme nous utilisons BizHawk, ce guide ne s'applique qu'aux systèmes Windows et Linux.
Comme nous utilisons BizHawk, ce guide s'applique uniquement aux systèmes Windows et Linux.
## Logiciel requis
- BizHawk : [BizHawk sort de TASVideos] (https://tasvideos.org/BizHawk/ReleaseHistory)
- Les versions 2.3.1 et ultérieures sont prises en charge. La version 2.7 est recommandée pour la stabilité.
- BizHawk : [Sorties BizHawk de TASVideos](https://tasvideos.org/BizHawk/ReleaseHistory)
- Les versions 2.3.1 et ultérieures sont prises en charge. La version 2.7 est recommandée pour des raisons de stabilité.
- Des instructions d'installation détaillées pour BizHawk peuvent être trouvées sur le lien ci-dessus.
- Les utilisateurs Windows doivent d'abord exécuter le programme d'installation prereq, qui peut également être trouvé sur le lien ci-dessus.
- Les utilisateurs Windows doivent d'abord exécuter le programme d'installation des prérequis, qui peut également être trouvé sur le lien ci-dessus.
- Le client Archipelago intégré, qui peut être installé [ici](https://github.com/ArchipelagoMW/Archipelago/releases)
(sélectionnez `Ocarina of Time Client` lors de l'installation).
(sélectionnez « Ocarina of Time Client » lors de l'installation).
- Une ROM Ocarina of Time v1.0.
## Configuration de BizHawk
Une fois BizHawk installé, ouvrez BizHawk et modifiez les paramètres suivants :
Une fois BizHawk installé, ouvrez EmuHawk et modifiez les paramètres suivants :
- Allez dans Config > Personnaliser. Basculez vers l'onglet Avancé, puis basculez le Lua Core de "NLua+KopiLua" vers
"Interface Lua+Lua". Redémarrez ensuite BizHawk. Ceci est nécessaire pour que le script Lua fonctionne correctement.
**REMARQUE : Même si "Lua+LuaInterface" est déjà sélectionné, basculez entre les deux options et resélectionnez-le. Nouvelles installations**
** des versions plus récentes de BizHawk ont tendance à afficher "Lua+LuaInterface" comme option sélectionnée par défaut mais se chargent toujours **
**"NLua+KopiLua" jusqu'à ce que cette étape soit terminée.**
- Sous Config > Personnaliser > Avancé, assurez-vous que la case pour AutoSaveRAM est cochée et cliquez sur le bouton 5s.
Cela réduit la possibilité de perdre des données de sauvegarde en cas de plantage de l'émulateur.
- Sous Config > Personnaliser, cochez les cases "Exécuter en arrière-plan" et "Accepter la saisie en arrière-plan". Cela vous permettra de
continuer à jouer en arrière-plan, même si une autre fenêtre est sélectionnée.
- Sous Config> Raccourcis clavier, de nombreux raccourcis clavier sont répertoriés, dont beaucoup sont liés aux touches communes du clavier. Vous voudrez probablement
désactiver la plupart d'entre eux, ce que vous pouvez faire rapidement en utilisant `Esc`.
- Si vous jouez avec une manette, lorsque vous liez les commandes, désactivez "P1 A Up", "P1 A Down", "P1 A Left" et "P1 A Right"
car ceux-ci interfèrent avec la visée s'ils sont liés. Définissez l'entrée directionnelle à l'aide de l'onglet Analogique à la place.
- Sous N64, activez "Utiliser l'emplacement d'extension". Ceci est nécessaire pour que les sauvegardes fonctionnent.
- (≤ 2,8) Allez dans Config > Personnaliser. Passez à l'onglet Avancé, puis faites passer le Lua Core de "NLua+KopiLua" à
"Lua+LuaInterface". Puis redémarrez EmuHawk. Ceci est nécessaire pour que le script Lua fonctionne correctement.
**REMARQUE : Même si « Lua+LuaInterface » est déjà sélectionné, basculez entre les deux options et resélectionnez-la. Nouvelles installations**
**des versions plus récentes d'EmuHawk ont tendance à afficher "Lua+LuaInterface" comme option sélectionnée par défaut mais ce pendant refait l'épate juste au dessus par précautions**
- Sous Config > Personnaliser > Avancé, assurez-vous que la case AutoSaveRAM est cochée et cliquez sur le bouton 5s.
Cela réduit la possibilité de perdre des données de sauvegarde en cas de crash de l'émulateur.
- Sous Config > Personnaliser, cochez les cases « Exécuter en arrière-plan » et « Accepter la saisie en arrière-plan ». Cela vous permettra continuez à jouer en arrière-plan, même si une autre fenêtre est sélectionnée.
- Sous Config > Hotkeys, de nombreux raccourcis clavier sont répertoriés, dont beaucoup sont liés aux touches communes du clavier. Vous voudrez probablement pour désactiver la plupart d'entre eux, ce que vous pouvez faire rapidement en utilisant « Esc ».
- Si vous jouez avec une manette, lorsque vous associez des commandes, désactivez "P1 A Up", "P1 A Down", "P1 A Left" et "P1 A Right".
car ceux-ci interfèrent avec la visée sils sont liés. Définissez plutôt l'entrée directionnelle à l'aide de l'onglet Analogique.
- Sous N64, activez "Utiliser le connecteur d'extension". Ceci est nécessaire pour que les états de sauvegarde fonctionnent.
(Le menu N64 n'apparaît qu'après le chargement d'une ROM.)
Il est fortement recommandé d'associer les extensions de rom N64 (\*.n64, \*.z64) au BizHawk que nous venons d'installer.
Pour ce faire, nous devons simplement rechercher n'importe quelle rom N64 que nous possédons, faire un clic droit et sélectionner "Ouvrir avec ...", dépliez
la liste qui apparaît et sélectionnez l'option du bas "Rechercher une autre application", puis naviguez jusqu'au dossier BizHawk
et sélectionnez EmuHawk.exe.
Il est fortement recommandé d'associer les extensions de rom N64 (\*.n64, \*.z64) à l'EmuHawk que nous venons d'installer.
Pour ce faire, vous devez simplement rechercher n'importe quelle rom N64 que vous possédez, faire un clic droit et sélectionner "Ouvrir avec...", déplier la liste qui apparaît et sélectionnez l'option du bas "Rechercher une autre application", puis accédez au dossier BizHawk et sélectionnez EmuHawk.exe.
Un guide de configuration BizHawk alternatif ainsi que divers conseils de dépannage peuvent être trouvés
Un guide de configuration BizHawk alternatif ainsi que divers conseils de dépannage sont disponibles
[ici](https://wiki.ootrandomizer.com/index.php?title=Bizhawk).
## Configuration de votre fichier YAML
## Créer un fichier de configuration (.yaml)
### Qu'est-ce qu'un fichier YAML et pourquoi en ai-je besoin ?
### Qu'est-ce qu'un fichier de configuration et pourquoi en ai-je besoin ?
Votre fichier YAML contient un ensemble d'options de configuration qui fournissent au générateur des informations sur la façon dont il doit
générer votre jeu. Chaque joueur d'un multimonde fournira son propre fichier YAML. Cette configuration permet à chaque joueur de profiter
d'une expérience personnalisée à leur goût, et différents joueurs dans le même multimonde peuvent tous avoir des options différentes.
Consultez le guide sur la configuration d'un YAML de base lors de la configuration de l'archipel.
guide : [Guide de configuration de base de Multiworld](/tutorial/Archipelago/setup/en)
### Où puis-je obtenir un fichier YAML ?
### Où puis-je obtenir un fichier de configuration (.yaml) ?
Un yaml OoT de base ressemblera à ceci. Il y a beaucoup d'options cosmétiques qui ont été supprimées pour le plaisir de ce
tutoriel, si vous voulez voir une liste complète, téléchargez Archipelago depuis
la [Archipelago Releases Page](https://github.com/ArchipelagoMW/Archipelago/releases) et recherchez l'exemple de fichier dans
le dossier "Lecteurs".
La page Paramètres du lecteur sur le site Web vous permet de configurer vos paramètres personnels et d'exporter un fichier de configuration depuis eux. Page des paramètres du joueur : [Page des paramètres du joueur d'Ocarina of Time](/games/Ocarina%20of%20Time/player-settings)
``` yaml
description: Modèle par défaut d'Ocarina of Time # Utilisé pour décrire votre yaml. Utile si vous avez plusieurs fichiers
# Votre nom dans le jeu. Les espaces seront remplacés par des underscores et il y a une limite de 16 caractères
name: VotreNom
game:
Ocarina of Time: 1
requires:
version: 0.1.7 # Version d'Archipelago requise pour que ce yaml fonctionne comme prévu.
# Options partagées prises en charge par tous les jeux :
accessibility:
items: 0 # Garantit que vous pourrez acquérir tous les articles, mais vous ne pourrez peut-être pas accéder à tous les emplacements
locations: 50 # Garantit que vous pourrez accéder à tous les emplacements, et donc à tous les articles
none: 0 # Garantit seulement que le jeu est battable. Vous ne pourrez peut-être pas accéder à tous les emplacements ou acquérir tous les objets
progression_balancing: # Un système pour réduire le BK, comme dans les périodes où vous ne pouvez rien faire, en déplaçant vos éléments dans une sphère d'accès antérieure
0: 0 # Choisissez un nombre inférieur si cela ne vous dérange pas d'avoir un multimonde plus long, ou si vous pouvez glitch / faire du hors logique.
25: 0
50: 50 # Faites en sorte que vous ayez probablement des choses à faire.
99: 0 # Obtenez les éléments importants tôt et restez en tête de la progression.
Ocarina of Time:
logic_rules: # définit la logique utilisée pour le générateur.
glitchless: 50
glitched: 0
no_logic: 0
logic_no_night_tokens_without_suns_song: # Les skulltulas nocturnes nécessiteront logiquement le Chant du soleil.
false: 50
true: 0
open_forest: # Définissez l'état de la forêt de Kokiri et du chemin vers l'arbre Mojo.
open: 50
closed_deku: 0
closed: 0
open_kakariko: # Définit l'état de la porte du village de Kakariko.
open: 50
zelda: 0
closed: 0
open_door_of_time: # Ouvre la Porte du Temps par défaut, sans le Chant du Temps.
false: 0
true: 50
zora_fountain: # Définit l'état du roi Zora, bloquant le chemin vers la fontaine de Zora.
open: 0
adult: 0
closed: 50
gerudo_fortress: # Définit les conditions d'accès à la forteresse Gerudo.
normal: 0
fast: 50
open: 0
bridge: # Définit les exigences pour le pont arc-en-ciel.
open: 0
vanilla: 0
stones: 0
medallions: 50
dungeons: 0
tokens: 0
trials: # Définit le nombre d'épreuves requises dans le Château de Ganon.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
0: 50 # valeur minimale
6: 0 # valeur maximale
random: 0
random-low: 0
random-higt: 0
starting_age: # Choisissez l'âge auquel Link commencera.
child: 50
adult: 0
triforce_hunt: # Rassemblez des morceaux de la Triforce dispersés dans le monde entier pour terminer le jeu.
false: 50
true: 0
triforce_goal: # Nombre de pièces Triforce nécessaires pour terminer le jeu. Nombre total placé déterminé par le paramètre Item Pool.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
1: 0 # valeur minimale
50: 0 # valeur maximale
random: 0
random-low: 0
random-higt: 0
20: 50
bombchus_in_logic: # Les Bombchus sont correctement pris en compte dans la logique. Le premier pack trouvé aura 20 chus ; Kokiri Shop et Bazaar vendent des recharges ; bombchus ouvre Bombchu Bowling.
false: 50
true: 0
bridge_stones: # Définissez le nombre de pierres spirituelles requises pour le pont arc-en-ciel.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
0: 0 # valeur minimale
3: 50 # valeur maximale
random: 0
random-low: 0
random-high: 0
bridge_medallions: # Définissez le nombre de médaillons requis pour le pont arc-en-ciel.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
0: 0 # valeur minimale
6: 50 # valeur maximale
random: 0
random-low: 0
random-high: 0
bridge_rewards: # Définissez le nombre de récompenses de donjon requises pour le pont arc-en-ciel.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
0: 0 # valeur minimale
9: 50 # valeur maximale
random: 0
random-low: 0
random-high: 0
bridge_tokens: # Définissez le nombre de jetons Gold Skulltula requis pour le pont arc-en-ciel.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
0: 0 # valeur minimale
100: 50 # valeur maximale
random: 0
random-low: 0
random-high: 0
shuffle_mapcompass: # Contrôle où mélanger les cartes et boussoles des donjons.
remove: 0
startwith: 50
vanilla: 0
dungeon: 0
overworld: 0
any_dungeon: 0
keysanity: 0
shuffle_smallkeys: # Contrôle où mélanger les petites clés de donjon.
remove: 0
vanilla: 0
dungeon: 50
overworld: 0
any_dungeon: 0
keysanity: 0
shuffle_hideoutkeys: # Contrôle où mélanger les petites clés de la Forteresse Gerudo.
vanilla: 50
overworld: 0
any_dungeon: 0
keysanity: 0
shuffle_bosskeys: # Contrôle où mélanger les clés du boss, à l'exception de la clé du boss du château de Ganon.
remove: 0
vanilla: 0
dungeon: 50
overworld: 0
any_dungeon: 0
keysanity: 0
shuffle_ganon_bosskey: # Contrôle où mélanger la clé du patron du château de Ganon.
remove: 50
vanilla: 0
dungeon: 0
overworld: 0
any_dungeon: 0
keysanity: 0
on_lacs: 0
enhance_map_compass: # La carte indique si un donjon est vanille ou MQ. La boussole indique quelle est la récompense du donjon.
false: 50
true: 0
lacs_condition: # Définissez les exigences pour la cinématique de la Flèche lumineuse dans le Temple du temps.
vanilla: 50
stones: 0
medallions: 0
dungeons: 0
tokens: 0
lacs_stones: # Définissez le nombre de pierres spirituelles requises pour le LACS.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
0: 0 # valeur minimale
3: 50 # valeur maximale
random: 0
random-low: 0
random-high: 0
lacs_medallions: # Définissez le nombre de médaillons requis pour LACS.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
0: 0 # valeur minimale
6: 50 # valeur maximale
random: 0
random-low: 0
random-high: 0
lacs_rewards: # Définissez le nombre de récompenses de donjon requises pour LACS.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
0: 0 # valeur minimale
9: 50 # valeur maximale
random: 0
random-low: 0
random-high: 0
lacs_tokens: # Définissez le nombre de jetons Gold Skulltula requis pour le LACS.
# vous pouvez ajouter des valeurs supplémentaires entre minimum et maximum
0: 0 # valeur minimale
100: 50 # valeur maximale
random: 0
random-low: 0
random-high: 0
shuffle_song_items: # Définit où les chansons peuvent apparaître.
song: 50
dungeon: 0
any: 0
shopsanity: # Randomise le contenu de la boutique. Réglez sur "off" pour ne pas mélanger les magasins ; "0" mélange les magasins mais ne n'autorise pas les articles multimonde dans les magasins.
0: 0
1: 0
2: 0
3: 0
4: 0
random_value: 0
off: 50
tokensanity : # les récompenses en jetons des Skulltulas dorées sont mélangées dans la réserve.
off: 50
dungeons: 0
overworld: 0
all: 0
shuffle_scrubs: # Mélangez les articles vendus par Business Scrubs et fixez les prix.
off: 50
low: 0
regular: 0
random_prices: 0
shuffle_cows: # les vaches donnent des objets lorsque la chanson d'Epona est jouée.
false: 50
true: 0
shuffle_kokiri_sword: # Mélangez l'épée Kokiri dans la réserve d'objets.
false: 50
true: 0
shuffle_ocarinas: # Mélangez l'Ocarina des fées et l'Ocarina du temps dans la réserve d'objets.
false: 50
true: 0
shuffle_weird_egg: # Mélangez l'œuf bizarre de Malon au château d'Hyrule.
false: 50
true: 0
shuffle_gerudo_card: # Mélangez la carte de membre Gerudo dans la réserve d'objets.
false: 50
true: 0
shuffle_beans: # Ajoute un paquet de 10 haricots au pool d'objets et change le vendeur de haricots pour qu'il vende un objet pour 60 roupies.
false: 50
true: 0
shuffle_medigoron_carpet_salesman: # Mélangez les objets vendus par Medigoron et le vendeur de tapis Haunted Wasteland.
false: 50
true: 0
skip_child_zelda: # le jeu commence avec la lettre de Zelda, l'objet de la berceuse de Zelda et les événements pertinents déjà terminés.
false: 50
true: 0
no_escape_sequence: # Ignore la séquence d'effondrement de la tour entre les combats de Ganondorf et de Ganon.
false: 50
true: 0
no_guard_stealth: # Le vide sanitaire du château d'Hyrule passe directement à Zelda.
false: 50
true: 0
no_epona_race: # Epona peut toujours être invoquée avec Epona's Song.
false: 50
true: 0
skip_some_minigame_phases: # Dampe Race et Horseback Archery donnent les deux récompenses si la deuxième condition est remplie lors de la première tentative.
false: 50
true: 0
complete_mask_quest: # Tous les masques sont immédiatement disponibles à l'emprunt dans la boutique Happy Mask.
false: 50
true: 0
useful_cutscenes: # Réactive la cinématique Poe dans le Temple de la forêt, Darunia dans le Temple du feu et l'introduction de Twinrova. Surtout utile pour les pépins.
false: 50
true: 0
fast_chests: # Toutes les animations des coffres sont rapides. Si désactivé, les éléments principaux ont une animation lente.
false: 50
true: 0
free_scarecrow: # Sortir l'ocarina près d'un point d'épouvantail fait apparaître Pierre sans avoir besoin de la chanson.
false: 50
true: 0
fast_bunny_hood: # Bunny Hood vous permet de vous déplacer 1,5 fois plus vite comme dans Majora's Mask.
false: 50
true: 0
chicken_count: # Contrôle le nombre de Cuccos pour qu'Anju donne un objet en tant qu'enfant.
\# vous pouvez ajouter des valeurs supplémentaires entre le minimum et le maximum
0: 0 # valeur minimale
7: 50 # valeur maximale
random: 0
random-low: 0
random-high: 0
hints: # les pierres à potins peuvent donner des indices sur l'emplacement des objets.
none: 0
mask: 0
agony: 0
always: 50
hint_dist: # Choisissez la distribution d'astuces à utiliser. Affecte la fréquence des indices forts, quels éléments sont toujours indiqués, etc.
balanced: 50
ddr: 0
league: 0
mw2: 0
scrubs: 0
strong: 0
tournament: 0
useless: 0
very_strong: 0
text_shuffle: # Randomise le texte dans le jeu pour un effet comique.
none: 50
except_hints: 0
complete: 0
damage_multiplier: # contrôle la quantité de dégâts subis par Link.
half: 0
normal: 50
double: 0
quadruple: 0
ohko: 0
no_collectible_hearts: # les cœurs ne tomberont pas des ennemis ou des objets.
false: 50
true: 0
starting_tod: # Changer l'heure de début de la journée.
default: 50
sunrise: 0
morning: 0
noon: 0
afternoon: 0
sunset: 0
evening: 0
midnight: 0
witching_hour: 0
start_with_consumables: # Démarrez le jeu avec des Deku Sticks et des Deku Nuts pleins.
false: 50
true: 0
start_with_rupees: # Commencez avec un portefeuille plein. Les mises à niveau de portefeuille rempliront également votre portefeuille.
false: 50
true: 0
item_pool_value: # modifie le nombre d'objets disponibles dans le jeu.
plentiful: 0
balanced: 50
scarce: 0
minimal: 0
junk_ice_traps: # Ajoute des pièges à glace au pool d'objets.
off: 0
normal: 50
on: 0
mayhem: 0
onslaught: 0
ice_trap_appearance: # modifie l'apparence des pièges à glace en tant qu'éléments autonomes.
major_only: 50
junk_only: 0
anything: 0
logic_earliest_adult_trade: # premier élément pouvant apparaître dans la séquence d'échange pour adultes.
pocket_egg: 0
pocket_cucco: 0
cojiro: 0
odd_mushroom: 0
poachers_saw: 0
broken_sword: 0
prescription: 50
eyeball_frog: 0
eyedrops: 0
claim_check: 0
logic_latest_adult_trade: # Dernier élément pouvant apparaître dans la séquence d'échange pour adultes.
pocket_egg: 0
pocket_cucco: 0
cojiro: 0
odd_mushroom: 0
poachers_saw: 0
broken_sword: 0
prescription: 0
eyeball_frog: 0
eyedrops: 0
claim_check: 50
### Vérification de votre fichier de configuration
```
Si vous souhaitez valider votre fichier de configuration pour vous assurer qu'il fonctionne, vous pouvez le faire sur la page YAML Validator.
YAML page du validateur : [page de validation YAML](/mysterycheck)
## Rejoindre une partie MultiWorld
## Rejoindre un jeu multimonde
### Obtenez votre fichier de correctif OOT
### Obtenez votre fichier OOT modifié
Lorsque vous rejoignez un jeu multimonde, il vous sera demandé de fournir votre fichier YAML à l'hébergeur. Une fois que c'est Fini,
l'hébergeur vous fournira soit un lien pour télécharger votre fichier de données, soit un fichier zip contenant les données de chacun
des dossiers. Votre fichier de données doit avoir une extension `.apz5`.
Lorsque vous rejoignez un jeu multimonde, il vous sera demandé de fournir votre fichier YAML à celui qui l'héberge. Une fois cela fait, l'hébergeur vous fournira soit un lien pour télécharger votre fichier de données, soit un fichier zip contenant les données de chacun des dossiers. Votre fichier de données doit avoir une extension « .apz5 ».
Double-cliquez sur votre fichier `.apz5` pour démarrer votre client et démarrer le processus de patch ROM. Une fois le processus terminé
(cela peut prendre un certain temps), le client et l'émulateur seront lancés automatiquement (si vous avez associé l'extension
à l'émulateur comme recommandé).
Double-cliquez sur votre fichier « .apz5 » pour démarrer votre client et démarrer le processus de correctif ROM. Une fois le processus terminé (cela peut prendre un certain temps), le client et l'émulateur seront automatiquement démarrés (si vous avez associé l'extension à l'émulateur comme recommandé).
### Connectez-vous au multiserveur
Une fois le client et l'émulateur démarrés, vous devez les connecter. Dans l'émulateur, cliquez sur "Outils"
menu et sélectionnez "Console Lua". Cliquez sur le bouton du dossier ou appuyez sur Ctrl+O pour ouvrir un script Lua.
Une fois le client et l'émulateur démarrés, vous devez les connecter. Accédez à votre dossier d'installation Archipelago, puis vers `data/lua`, et faites glisser et déposez le script `connector_oot.lua` sur la fenêtre principale d'EmuHawk. (Vous pourrez plutôt ouvrir depuis la console Lua manuellement, cliquez sur `Script``Open Script` et accédez à `connector_oot.lua` avec le sélecteur de fichiers.)
Accédez à votre dossier d'installation Archipelago et ouvrez `data/lua/connector_oot.lua`.
Pour connecter le client au multiserveur, mettez simplement `<adresse>:<port>` dans le champ de texte en haut et appuyez sur Entrée (si le serveur utilise un mot de passe, tapez dans le champ de texte inférieur `/connect <adresse>:<port> [mot de passe]`)
Pour connecter le client au multiserveur, mettez simplement `<adresse>:<port>` dans le champ de texte en haut et appuyez sur Entrée (si le
le serveur utilise un mot de passe, saisissez dans le champ de texte inférieur `/connect <adresse>:<port> [mot de passe]`)
Vous êtes maintenant prêt à commencer votre aventure à Hyrule.
Vous êtes maintenant prêt à commencer votre aventure dans Hyrule.

View File

@@ -1,15 +1,15 @@
# Pokémon Emerald
## Where is the settings page?
## Where is the options page?
You can read through all the settings and generate a YAML [here](../player-settings).
You can read through all the options and generate a YAML [here](../player-options).
## What does randomization do to this game?
This randomizer handles both item randomization and pokémon randomization. Badges, HMs, gifts from NPCs, and items on
the ground can all be randomized. There are also many options for randomizing wild pokémon, starters, opponent pokémon,
abilities, types, etc… You can even change a percentage of single battles into double battles. Check the
[settings page](../player-settings) for a more comprehensive list of what can be changed.
[options page](../player-options) for a more comprehensive list of what can be changed.
## What items and locations get randomized?
@@ -28,7 +28,7 @@ randomizer. Here are some of the more important ones:
- You can have both bikes simultaneously
- You can run or bike (almost) anywhere
- The Wally catching tutorial is skipped
- All text is instant, and with a setting it can be automatically progressed by holding A
- All text is instant and, with an option, can be automatically progressed by holding A
- When a Repel runs out, you will be prompted to use another
- Many more minor improvements…
@@ -44,7 +44,7 @@ your inventory.
## When the player receives an item, what happens?
You will only receive items while in the overworld and not during battles. Depending on your `Receive Item Messages`
setting, the received item will either be silently added to your bag or you will be shown a text box with the item's
option, the received item will either be silently added to your bag or you will be shown a text box with the item's
name and the item will be added to your bag while a fanfare plays.
## Can I play offline?

View File

@@ -26,8 +26,8 @@ clear it.
## Generating and Patching a Game
1. Create your settings file (YAML). You can make one on the
[Pokémon Emerald settings page](../../../games/Pokemon%20Emerald/player-settings).
1. Create your options file (YAML). You can make one on the
[Pokémon Emerald options page](../../../games/Pokemon%20Emerald/player-options).
2. Follow the general Archipelago instructions for [generating a game](../../Archipelago/setup/en#generating-a-game).
This will generate an output file for you. Your patch file will have the `.apemerald` file extension.
3. Open `ArchipelagoLauncher.exe`

View File

@@ -281,18 +281,20 @@ class PokemonRedBlueWorld(World):
self.multiworld.itempool.remove(badge)
progitempool.remove(badge)
for _ in range(5):
badgelocs = [self.multiworld.get_location(loc, self.player) for loc in [
"Pewter Gym - Brock Prize", "Cerulean Gym - Misty Prize",
"Vermilion Gym - Lt. Surge Prize", "Celadon Gym - Erika Prize",
"Fuchsia Gym - Koga Prize", "Saffron Gym - Sabrina Prize",
"Cinnabar Gym - Blaine Prize", "Viridian Gym - Giovanni Prize"]]
badgelocs = [
self.multiworld.get_location(loc, self.player) for loc in [
"Pewter Gym - Brock Prize", "Cerulean Gym - Misty Prize",
"Vermilion Gym - Lt. Surge Prize", "Celadon Gym - Erika Prize",
"Fuchsia Gym - Koga Prize", "Saffron Gym - Sabrina Prize",
"Cinnabar Gym - Blaine Prize", "Viridian Gym - Giovanni Prize"
] if self.multiworld.get_location(loc, self.player).item is None]
state = self.multiworld.get_all_state(False)
self.multiworld.random.shuffle(badges)
self.multiworld.random.shuffle(badgelocs)
badgelocs_copy = badgelocs.copy()
# allow_partial so that unplaced badges aren't lost, for debugging purposes
fill_restrictive(self.multiworld, state, badgelocs_copy, badges, True, True, allow_partial=True)
if badges:
if len(badges) > 8 - len(badgelocs):
for location in badgelocs:
if location.item:
badges.append(location.item)
@@ -302,6 +304,7 @@ class PokemonRedBlueWorld(World):
for location in badgelocs:
if location.item:
fill_locations.remove(location)
progitempool += badges
break
else:
raise FillError(f"Failed to place badges for player {self.player}")

View File

@@ -1,5 +1,5 @@
from BaseClasses import Location
from BaseClasses import AlwaysAllowLocation
from .rom_addresses import rom_addresses
from . import poke_data
loc_id_start = 172000000
@@ -2767,7 +2767,7 @@ for mon in poke_data.evolves_from:
location_data.append(LocationData("Evolution", mon, mon, event=True))
class PokemonRBLocation(Location):
class PokemonRBLocation(AlwaysAllowLocation):
game = "Pokemon Red and Blue"
def __init__(self, player, name, address, rom_address, type, level, level_address):

View File

@@ -61,7 +61,7 @@ class SMSNIClient(SNIClient):
from SNIClient import snes_buffered_write, snes_flush_writes, snes_read
rom_name = await snes_read(ctx, SM_ROMNAME_START, ROMNAME_SIZE)
if rom_name is None or rom_name == bytes([0] * ROMNAME_SIZE) or rom_name[:2] != b"SM" or rom_name[:3] == b"SMW":
if rom_name is None or rom_name == bytes([0] * ROMNAME_SIZE) or rom_name[:2] != b"SM" or rom_name[2] not in b"1234567890":
return False
ctx.game = self.game

View File

@@ -21,7 +21,7 @@ def fix_reg(entrance_map: dict, entrance: SM64Levels, invalid_regions: set,
def set_rules(world, player: int, area_connections: dict):
randomized_level_to_paintings = sm64_level_to_paintings.copy()
randomized_level_to_secrets = sm64_level_to_secrets.copy()
if world.AreaRandomizer[player].value == 1: # Some randomization is happening, randomize Courses
if world.AreaRandomizer[player].value >= 1: # Some randomization is happening, randomize Courses
randomized_level_to_paintings = shuffle_dict_keys(world,sm64_level_to_paintings)
if world.AreaRandomizer[player].value == 2: # Randomize Secrets as well
randomized_level_to_secrets = shuffle_dict_keys(world,sm64_level_to_secrets)

View File

@@ -69,7 +69,7 @@ class SMZ3SNIClient(SNIClient):
ctx.finished_game = True
return
data = await snes_read(ctx, SMZ3_RECV_PROGRESS_ADDR + 0x680, 4)
data = await snes_read(ctx, SMZ3_RECV_PROGRESS_ADDR + 0xD3C, 4)
if data is None:
return
@@ -77,14 +77,14 @@ class SMZ3SNIClient(SNIClient):
recv_item = data[2] | (data[3] << 8)
while (recv_index < recv_item):
item_address = recv_index * 8
message = await snes_read(ctx, SMZ3_RECV_PROGRESS_ADDR + 0x700 + item_address, 8)
is_z3_item = ((message[5] & 0x80) != 0)
masked_part = (message[5] & 0x7F) if is_z3_item else message[5]
item_index = ((message[4] | (masked_part << 8)) >> 3) + (256 if is_z3_item else 0)
item_address = recv_index * 2
message = await snes_read(ctx, SMZ3_RECV_PROGRESS_ADDR + 0xDA0 + item_address, 2)
is_z3_item = ((message[1] & 0x80) != 0)
masked_part = (message[1] & 0x7F) if is_z3_item else message[1]
item_index = ((message[0] | (masked_part << 8)) >> 3) + (256 if is_z3_item else 0)
recv_index += 1
snes_buffered_write(ctx, SMZ3_RECV_PROGRESS_ADDR + 0x680, bytes([recv_index & 0xFF, (recv_index >> 8) & 0xFF]))
snes_buffered_write(ctx, SMZ3_RECV_PROGRESS_ADDR + 0xD3C, bytes([recv_index & 0xFF, (recv_index >> 8) & 0xFF]))
from .TotalSMZ3.Location import locations_start_id
from . import convertLocSMZ3IDToAPID
@@ -95,7 +95,7 @@ class SMZ3SNIClient(SNIClient):
snes_logger.info(f'New Check: {location} ({len(ctx.locations_checked)}/{len(ctx.missing_locations) + len(ctx.checked_locations)})')
await ctx.send_msgs([{"cmd": 'LocationChecks', "locations": [location_id]}])
data = await snes_read(ctx, SMZ3_RECV_PROGRESS_ADDR + 0x600, 4)
data = await snes_read(ctx, SMZ3_RECV_PROGRESS_ADDR + 0xD36, 4)
if data is None:
return
@@ -106,10 +106,10 @@ class SMZ3SNIClient(SNIClient):
item = ctx.items_received[item_out_ptr]
item_id = item.item - items_start_id
player_id = item.player if item.player <= SMZ3_ROM_PLAYER_LIMIT else 0
snes_buffered_write(ctx, SMZ3_RECV_PROGRESS_ADDR + item_out_ptr * 4, bytes([player_id & 0xFF, (player_id >> 8) & 0xFF, item_id & 0xFF, (item_id >> 8) & 0xFF]))
player_id = item.player if item.player < SMZ3_ROM_PLAYER_LIMIT else 0
snes_buffered_write(ctx, SMZ3_RECV_PROGRESS_ADDR + item_out_ptr * 2, bytes([player_id, item_id]))
item_out_ptr += 1
snes_buffered_write(ctx, SMZ3_RECV_PROGRESS_ADDR + 0x602, bytes([item_out_ptr & 0xFF, (item_out_ptr >> 8) & 0xFF]))
snes_buffered_write(ctx, SMZ3_RECV_PROGRESS_ADDR + 0xD38, bytes([item_out_ptr & 0xFF, (item_out_ptr >> 8) & 0xFF]))
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
color(ctx.item_names[item.item], 'red', 'bold'), color(ctx.player_names[item.player], 'yellow'),
ctx.location_names[item.location], item_out_ptr, len(ctx.items_received)))

View File

@@ -1,3 +1,5 @@
from __future__ import annotations
import logging
import copy
import os
@@ -5,7 +7,7 @@ import random
import threading
from typing import Dict, Set, TextIO
from BaseClasses import Region, Entrance, Location, MultiWorld, Item, ItemClassification, CollectionState, \
from BaseClasses import Region, Entrance, AlwaysAllowLocation, MultiWorld, Item, ItemClassification, CollectionState, \
Tutorial
from worlds.generic.Rules import set_rule
from .TotalSMZ3.Item import ItemType
@@ -80,11 +82,12 @@ class SMZ3World(World):
locationNamesGT: Set[str] = {loc.Name for loc in GanonsTower(None, None).Locations}
# first added for 0.2.6
required_client_version = (0, 2, 6)
# optimized message queues for 0.4.4
required_client_version = (0, 4, 4)
def __init__(self, world: MultiWorld, player: int):
self.rom_name_available_event = threading.Event()
self.locations: Dict[str, Location] = {}
self.locations: Dict[str, SMZ3Location] = {}
self.unreachable = []
super().__init__(world, player)
@@ -651,7 +654,7 @@ class SMZ3World(World):
return ret
class SMZ3Location(Location):
class SMZ3Location(AlwaysAllowLocation):
game: str = "SMZ3"
def __init__(self, player: int, name: str, address=None, parent=None):

Binary file not shown.

View File

@@ -93,7 +93,11 @@ def get_pool_core(world):
# Starting Weapon
start_weapon_locations = starting_weapon_locations.copy()
starting_weapon = random.choice(starting_weapons)
final_starting_weapons = [weapon for weapon in starting_weapons
if weapon not in world.multiworld.non_local_items[world.player]]
if not final_starting_weapons:
final_starting_weapons = starting_weapons
starting_weapon = random.choice(final_starting_weapons)
if world.multiworld.StartingPosition[world.player] == StartingPosition.option_safe:
placed_items[start_weapon_locations[0]] = starting_weapon
elif world.multiworld.StartingPosition[world.player] in \

View File

@@ -200,15 +200,17 @@ class TLoZWorld(World):
for i in range(0, 0x7F):
item = rom_data[first_quest_dungeon_items_early + i]
if item & 0b00100000:
rom_data[first_quest_dungeon_items_early + i] = item & 0b11011111
rom_data[first_quest_dungeon_items_early + i] = item | 0b01000000
item = item & 0b11011111
item = item | 0b01000000
rom_data[first_quest_dungeon_items_early + i] = item
if item & 0b00011111 == 0b00000011: # Change all Item 03s to Item 3F, the proper "nothing"
rom_data[first_quest_dungeon_items_early + i] = item | 0b00111111
item = rom_data[first_quest_dungeon_items_late + i]
if item & 0b00100000:
rom_data[first_quest_dungeon_items_late + i] = item & 0b11011111
rom_data[first_quest_dungeon_items_late + i] = item | 0b01000000
item = item & 0b11011111
item = item | 0b01000000
rom_data[first_quest_dungeon_items_late + i] = item
if item & 0b00011111 == 0b00000011:
rom_data[first_quest_dungeon_items_late + i] = item | 0b00111111
return rom_data

View File

@@ -143,7 +143,7 @@ class WitnessWorld(World):
# Pick an early item to place on the tutorial gate.
early_items = [item for item in self.items.get_early_items() if item in self.items.get_mandatory_items()]
if early_items:
random_early_item = self.multiworld.random.choice(early_items)
random_early_item = self.random.choice(early_items)
if self.options.puzzle_randomization == 1:
# In Expert, only tag the item as early, rather than forcing it onto the gate.
self.multiworld.local_early_items[self.player][random_early_item] = 1