Compare commits

..

9 Commits

Author SHA1 Message Date
CaitSith2
5ce892cbb8 docstring updated to clarify impact on collecting player. 2023-03-14 14:14:11 -07:00
CaitSith2
bc7389fbaa Add a todo regarding backwards compatibility 2023-03-14 13:46:24 -07:00
CaitSith2
9cb5a7fc3a Merge branch 'main' into allow_collect 2023-03-14 13:33:39 -07:00
alwaysintreble
e433246f0c The Messenger: docs improvement (#1545)
* The Messenger: docs improvement

* more wordy mod link

Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com>

* indent

* revert accidental indent

oop

Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com>

---------

Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com>
2023-03-14 21:18:55 +01:00
black-sliver
3a190a8fb2 CI: more filters, update CodeQL (#1540)
* CI: fix and more greedy filtering

* CI: only run lint if *.py changed

* CI: only run CodeQL if supported file changed

* CI: fix unittests still triggering for build.yml

* CI: update CodeQL action

* CI: trigger codeql when changing the workflow
2023-03-14 19:29:20 +01:00
Alchav
4b7033fce7 Pokemon R/B: Version 3 final touches (#1542)
* Pokémon R/B: Dexsanity balls

* Pokémon R/B: Early Parcel improvement

* Pokémon R/B: Early Parcel dexsanity stuff only when dexsanity
2023-03-14 18:36:17 +01:00
lordlou
37499b40a1 SMZ3: shop check fix 2 (#1538) 2023-03-14 18:31:51 +01:00
CaitSith2
4311e8dbe2 Merge branch 'main' into allow_collect 2023-02-19 19:19:28 -08:00
CaitSith2
d961022bff Add option for player to allow/disallow collection from their slot. 2023-01-28 05:04:55 -08:00
15 changed files with 84 additions and 71 deletions

View File

@@ -5,12 +5,12 @@ name: Build
on:
push:
paths:
- '.github/workflows/build.yaml'
- '.github/workflows/build.yml'
- 'setup.py'
- 'requirements.txt'
pull_request:
paths:
- '.github/workflows/build.yaml'
- '.github/workflows/build.yml'
- 'setup.py'
- 'requirements.txt'
workflow_dispatch:

View File

@@ -14,9 +14,17 @@ name: "CodeQL"
on:
push:
branches: [ main ]
paths:
- '**.py'
- '**.js'
- '.github/workflows/codeql-analysis.yml'
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
paths:
- '**.py'
- '**.js'
- '.github/workflows/codeql-analysis.yml'
schedule:
- cron: '44 8 * * 1'
@@ -39,7 +47,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -50,7 +58,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -64,4 +72,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2

View File

@@ -3,7 +3,13 @@
name: lint
on: [push, pull_request]
on:
push:
paths:
- '**.py'
pull_request:
paths:
- '**.py'
jobs:
build:

View File

@@ -5,17 +5,23 @@ name: unittests
on:
push:
paths-ignore:
- 'docs/**'
- 'setup.py'
- '*.iss'
- '.gitignore'
paths:
- '**'
- '!docs/**'
- '!setup.py'
- '!*.iss'
- '!.gitignore'
- '!.github/workflows/**'
- '.github/workflows/unittests.yml'
pull_request:
paths-ignore:
- 'docs/**'
- 'setup.py'
- '*.iss'
- '.gitignore'
paths:
- '**'
- '!docs/**'
- '!setup.py'
- '!*.iss'
- '!.gitignore'
- '!.github/workflows/**'
- '.github/workflows/unittests.yml'
jobs:
build:

View File

@@ -67,6 +67,7 @@ class MultiWorld():
local_early_items: Dict[int, Dict[str, int]]
local_items: Dict[int, Options.LocalItems]
non_local_items: Dict[int, Options.NonLocalItems]
allow_collect: Dict[int, Options.AllowCollect]
progression_balancing: Dict[int, Options.ProgressionBalancing]
completion_condition: Dict[int, Callable[[CollectionState], bool]]
indirect_connections: Dict[Region, Set[Entrance]]

View File

@@ -316,7 +316,7 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
client_versions[slot] = player_world.required_client_version
games[slot] = world.game[slot]
slot_info[slot] = NetUtils.NetworkSlot(names[0][slot - 1], world.game[slot],
world.player_types[slot])
world.player_types[slot], bool(world.allow_collect[slot].value))
for slot, group in world.groups.items():
games[slot] = world.game[slot]
slot_info[slot] = NetUtils.NetworkSlot(group["name"], world.game[slot], world.player_types[slot],

View File

@@ -222,6 +222,7 @@ class Context:
self.save_dirty = False
self.tags = ['AP']
self.games: typing.Dict[int, str] = {}
self.allow_collect: typing.Dict[int, bool] = {}
self.minimum_client_versions: typing.Dict[int, Utils.Version] = {}
self.seed_name = ""
self.groups = {}
@@ -391,6 +392,9 @@ class Context:
self.games = {slot: slot_info.game for slot, slot_info in self.slot_info.items()}
self.groups = {slot: slot_info.group_members for slot, slot_info in self.slot_info.items()
if slot_info.type == SlotType.group}
# TODO: around 0.4.2 or so, remove the if/else backwards compatibility check.
self.allow_collect = {slot: slot_info.allow_collect if type(slot_info.allow_collect) is bool else True
for slot, slot_info in self.slot_info.items()}
self.clients = {0: {}}
slot_info: NetworkSlot
@@ -885,6 +889,8 @@ def collect_player(ctx: Context, team: int, slot: int, is_group: bool = False):
"""register any locations that are in the multidata, pointing towards this player"""
all_locations = collections.defaultdict(set)
for source_slot, location_data in ctx.locations.items():
if not ctx.allow_collect[source_slot]:
continue
for location_id, values in location_data.items():
if values[1] == slot:
all_locations[source_slot].add(location_id)

View File

@@ -71,6 +71,7 @@ class NetworkSlot(typing.NamedTuple):
name: str
game: str
type: SlotType
allow_collect: bool = True
group_members: typing.Union[typing.List[int], typing.Tuple] = () # only populated if type == group

View File

@@ -875,9 +875,17 @@ class ProgressionBalancing(SpecialRange):
}
class AllowCollect(DefaultOnToggle):
"""Controls whether items are collected from the slot when a player does a !collect or not.
The impact for the collecting player is that the collector might not get all of their items, until
the player(s) that has disallowed collection actually completes or releases their location checks."""
display_name = "Allow Collect"
common_options = {
"progression_balancing": ProgressionBalancing,
"accessibility": Accessibility
"accessibility": Accessibility,
"allow_collect": AllowCollect
}

View File

@@ -13,26 +13,10 @@ if TYPE_CHECKING:
from BaseClasses import MultiWorld, Item, Location, Tutorial
class WorldVersionIncompatible(Exception):
pass
class AutoWorldRegister(type):
world_types: Dict[str, Type[World]] = {}
def __new__(mcs, name: str, bases: Tuple[type, ...], dct: Dict[str, Any]) -> AutoWorldRegister:
if dct.get("required_archipelago_version", None):
from Utils import version_tuple
if dct["required_archipelago_version"] > version_tuple:
raise WorldVersionIncompatible(
f"World {name} for game {dct.get('game', None)} "
f"requires Archipelago {dct['required_archipelago_version']}, but this is {version_tuple}")
if dct.get("highest_archipelago_version", None):
from Utils import version_tuple
if version_tuple > dct["highest_archipelago_version"]:
raise WorldVersionIncompatible(
f"World {name} for {dct.get('game', None)} "
f"supports Archipelago up to {dct['highest_archipelago_version']}, but this is {version_tuple}")
if "web" in dct:
assert isinstance(dct["web"], WebWorld), "WebWorld has to be instantiated."
# filter out any events
@@ -185,14 +169,6 @@ class World(metaclass=AutoWorldRegister):
required_server_version: Tuple[int, int, int] = (0, 2, 4)
"""update this if the resulting multidata breaks forward-compatibility of the server"""
required_archipelago_version: ClassVar[Optional[Tuple[int, int, int]]] = None
"""Optional. Enter the minimum required Archipelago version that can use this world.
Typically for version checking when distributing as apworld."""
highest_archipelago_version: ClassVar[Optional[Tuple[int, int, int]]] = None
"""Optional. Enter the highest Archipelago version that can use this world.
Typically for version checking when distributing as apworld."""
hint_blacklist: ClassVar[FrozenSet[str]] = frozenset()
"""any names that should not be hintable"""

View File

@@ -1,7 +1,7 @@
# The Messenger
## Quick Links
- [Setup](../../../../games/The%20Messenger/setup/en)
- [Setup](../../../../tutorial/The%20Messenger/setup/en)
- [Settings Page](../../../../games/The%20Messenger/player-settings)
- [Courier Github](https://github.com/Brokemia/Courier)
- [The Messenger Randomizer Github](https://github.com/minous27/TheMessengerRandomizerMod)
@@ -48,25 +48,23 @@ for it. The groups you can use for The Messenger are:
## Other changes
* The player can return to the Tower of Time HQ at any point by selecting the button from the options menu
* This can cause issues if used at specific times. Current known:
* During Boss fights
* After Courage Note collection (Corrupted Future chase)
* This is currently an expected action in logic. If you do need to teleport during this chase sequence, it
is recommended to quit to title and reload the save
* This can cause issues if used at specific times. Current known:
* During Boss fights
* After Courage Note collection (Corrupted Future chase)
* This is currently an expected action in logic. If you do need to teleport during this chase sequence, it
is recommended to quit to title and reload the save
* After reaching ninja village a teleport option is added to the menu to reach it quickly
* Toggle Windmill Shuriken button is added to option menu once the item is received
## Currently known issues
* Necro cutscene will sometimes not play correctly, but will still reward the item
* Ruxxtin Coffin cutscene will sometimes not play correctly, but will still reward the item
* If you receive the Fairy Bottle while in Quillshroom Marsh, The Decurse Queen cutscene will not play
* If you receive the Fairy Bottle while in Quillshroom Marsh, The Decurse Queen cutscene will not play. You can exit
to Searing Crags and re-enter to get it to play correctly.
* If you defeat Barma'thazël, the cutscene afterward will not play correctly since that is what normally transitions
you to 2nd quest. The game will not kill you if you fall here, so you can teleport to HQ at any point after defeating him.
you to 2nd quest. The game will not kill you if you fall here, so you can teleport to HQ at any point after defeating him.
* Sometimes upon teleporting back to HQ, Ninja will run left and enter a different portal than the one entered by the
player.
* If playing the game in non-english, sometimes the text entry menus will say "What is your name?" in local language
instead of the correct text. This can be fixed by going into the game options and selecting your language in the menu.
It does not need to be changed to something else and back.
player.
* Text entry menus don't accept controller input
## What do I do if I have a problem?

View File

@@ -1,31 +1,29 @@
# The Messenger Randomizer Setup Guide
## Quick Links
- [Main Page](../../../../games/The%20Messenger/info/en)
- [Game Info](../../../../games/The%20Messenger/info/en)
- [Settings Page](../../../../games/The%20Messenger/player-settings)
- [Courier Github](https://github.com/Brokemia/Courier)
- [The Messenger Randomizer Github](https://github.com/minous27/TheMessengerRandomizerMod)
- [Jacksonbird8237's Item Tracker](https://github.com/Jacksonbird8237/TheMessengerItemTracker)
- [PopTracker Pack](https://github.com/alwaysintreble/TheMessengerTrackPack)
## Required Software
- [The Messenger](https://store.steampowered.com/app/764790/The_Messenger/)
- Only Steam version is currently supported.
- [Courier Mod Loader](https://github.com/Brokemia/Courier/releases)
- [The Messenger Randomizer Mod](https://github.com/minous27/TheMessengerRandomizerMod/releases)
## Installation
1. Download and install Courier Mod Loader using the instructions on the release page
* [Latest release is currently 0.7.1](https://github.com/Brokemia/Courier/releases)
2. Download and install the randomizer mod
* Download the latest `TheMessengerRandomizer.zip`
* Extract the zip file to `TheMessenger/Mods/` of your game's install location
* Optionally, Backup your save game
1. Download the latest TheMessengerRandomizer.zip from the [The Messenger Randomizer Mod releases page](https://github.com/minous27/TheMessengerRandomizerMod/releases)
2. Extract the zip file to `TheMessenger/Mods/` of your game's install location
3. Optionally, Backup your save game
* On Windows
1. Press `Windows Key + R` to open run
2. Type `%appdata%` to access AppData
3. Navigate to `AppData/locallow/SabotageStudios/The Messenger`
4. Rename `SaveGame.txt` to any name of your choice
* On Linux
1. Navigate to `steamapps/compatdata/764790/pfx/drive_c/users/steamuser/AppData/LocalLow/Sabotage Studio/The Messenger`
2. Rename `SaveGame.txt` to any name of your choice
## Joining a MultiWorld Game
@@ -33,12 +31,12 @@
2. Navigate to `Options > Third Party Mod Options`
3. Select `Reset Randomizer File Slots`
* This will set up all of your save slots with new randomizer save files. You can have up to 3 randomizer files at a
time, but must do this step again to start new runs afterwards.
time, but must do this step again to start new runs afterwards.
4. Enter connection info using the relevant option buttons
* **The game is limited to alphanumerical characters and `-` so when entering the host name replace `.` with ` ` and
ensure that your player name when generating a settings file follows these constrictions**
ensure that your player name when generating a settings file follows these constrictions**
* This defaults to `archipelago.gg` and does not need to be manually changed if connecting to a game hosted on the
website.
website.
5. Select the `Connect to Archipelago` button
6. Navigate to save file selection
7. Select a new valid randomizer save

View File

@@ -287,8 +287,12 @@ class PokemonRedBlueWorld(World):
else:
break
if self.multiworld.old_man[self.player].value == 1:
if self.multiworld.old_man[self.player] == "early_parcel":
self.multiworld.local_early_items[self.player]["Oak's Parcel"] = 1
if self.multiworld.dexsanity[self.player]:
for location in [self.multiworld.get_location(f"Pokedex - {mon}", self.player)
for mon in poke_data.pokemon_data.keys()]:
add_item_rule(location, lambda item: item.name != "Oak's Parcel" or item.player != self.player)
if not self.multiworld.badgesanity[self.player].value:
self.multiworld.non_local_items[self.player].value -= self.item_name_groups["Badges"]

View File

@@ -753,8 +753,9 @@ location_data = [
LocationData("Celadon Game Corner", "Hidden Item at End of Horizontal Machine Row (Coin Case)", "20 Coins", rom_addresses["Hidden_Item_Game_Corner_10"], Hidden(63), inclusion=hidden_items),
LocationData("Celadon Game Corner", "Hidden Item in Front of Horizontal Machine Row (Coin Case)", "100 Coins", rom_addresses["Hidden_Item_Game_Corner_11"], Hidden(64), inclusion=hidden_items),
*[LocationData("Pokedex", mon, None, rom_addresses["Dexsanity_Items"] + i, DexSanityFlag(i),
type="Item", inclusion=dexsanity) for (mon, i) in zip(pokemon_data.keys(), range(0, 152))],
*[LocationData("Pokedex", mon, ball, rom_addresses["Dexsanity_Items"] + i, DexSanityFlag(i), type="Item",
inclusion=dexsanity) for (mon, i, ball) in zip(pokemon_data.keys(), range(0, 152),
["Poke Ball", "Great Ball", "Ultra Ball"]* 51)],
LocationData("Indigo Plateau", "Become Champion", "Become Champion", event=True),
LocationData("Pokemon Tower 7F", "Fuji Saved", "Fuji Saved", event=True),

Binary file not shown.