The Messenger: some miscellaneous cleanup. Also found a logic bug. oops. (#1654)
This commit is contained in:
parent
ffd968d89d
commit
cdd460ae15
|
@ -6,7 +6,7 @@ NOTES = [
|
||||||
"Key of Courage",
|
"Key of Courage",
|
||||||
"Key of Love",
|
"Key of Love",
|
||||||
"Key of Strength",
|
"Key of Strength",
|
||||||
"Key of Symbiosis"
|
"Key of Symbiosis",
|
||||||
]
|
]
|
||||||
|
|
||||||
PROG_ITEMS = [
|
PROG_ITEMS = [
|
||||||
|
@ -20,18 +20,18 @@ PROG_ITEMS = [
|
||||||
"Sun Crest",
|
"Sun Crest",
|
||||||
"Moon Crest",
|
"Moon Crest",
|
||||||
# "Astral Seed",
|
# "Astral Seed",
|
||||||
# "Astral Tea Leaves"
|
# "Astral Tea Leaves",
|
||||||
]
|
]
|
||||||
|
|
||||||
PHOBEKINS = [
|
PHOBEKINS = [
|
||||||
"Necro",
|
"Necro",
|
||||||
"Pyro",
|
"Pyro",
|
||||||
"Claustro",
|
"Claustro",
|
||||||
"Acro"
|
"Acro",
|
||||||
]
|
]
|
||||||
|
|
||||||
USEFUL_ITEMS = [
|
USEFUL_ITEMS = [
|
||||||
"Windmill Shuriken"
|
"Windmill Shuriken",
|
||||||
]
|
]
|
||||||
|
|
||||||
# item_name_to_id needs to be deterministic and match upstream
|
# item_name_to_id needs to be deterministic and match upstream
|
||||||
|
@ -53,7 +53,7 @@ ALL_ITEMS = [
|
||||||
"Moon Crest",
|
"Moon Crest",
|
||||||
*PHOBEKINS,
|
*PHOBEKINS,
|
||||||
"Power Seal",
|
"Power Seal",
|
||||||
"Time Shard" # there's 45 separate instances of this in the client lookup, but hopefully we don't care?
|
"Time Shard", # there's 45 separate instances of this in the client lookup, but hopefully we don't care?
|
||||||
]
|
]
|
||||||
|
|
||||||
# locations
|
# locations
|
||||||
|
@ -87,7 +87,7 @@ ALWAYS_LOCATIONS = [
|
||||||
"Necro",
|
"Necro",
|
||||||
"Pyro",
|
"Pyro",
|
||||||
"Claustro",
|
"Claustro",
|
||||||
"Acro"
|
"Acro",
|
||||||
]
|
]
|
||||||
|
|
||||||
SEALS = [
|
SEALS = [
|
||||||
|
@ -149,5 +149,5 @@ SEALS = [
|
||||||
|
|
||||||
"Elemental Skylands Seal - Air",
|
"Elemental Skylands Seal - Air",
|
||||||
"Elemental Skylands Seal - Water",
|
"Elemental Skylands Seal - Water",
|
||||||
"Elemental Skylands Seal - Fire"
|
"Elemental Skylands Seal - Fire",
|
||||||
]
|
]
|
||||||
|
|
|
@ -22,7 +22,7 @@ REGIONS: Dict[str, List[str]] = {
|
||||||
"Sunken Shrine": ["Ninja Tabi", "Sun Crest", "Moon Crest", "Key of Love"],
|
"Sunken Shrine": ["Ninja Tabi", "Sun Crest", "Moon Crest", "Key of Love"],
|
||||||
"Elemental Skylands": ["Key of Symbiosis"],
|
"Elemental Skylands": ["Key of Symbiosis"],
|
||||||
"Corrupted Future": ["Key of Courage"],
|
"Corrupted Future": ["Key of Courage"],
|
||||||
"Music Box": ["Rescue Phantom"]
|
"Music Box": ["Rescue Phantom"],
|
||||||
}
|
}
|
||||||
"""seal locations have the region in their name and may not need to be created so skip them here"""
|
"""seal locations have the region in their name and may not need to be created so skip them here"""
|
||||||
|
|
||||||
|
@ -47,6 +47,6 @@ REGION_CONNECTIONS: Dict[str, Set[str]] = {
|
||||||
"Dark Cave": {"Catacombs", "Riviere Turquoise"},
|
"Dark Cave": {"Catacombs", "Riviere Turquoise"},
|
||||||
"Riviere Turquoise": set(),
|
"Riviere Turquoise": set(),
|
||||||
"Sunken Shrine": {"Howling Grotto"},
|
"Sunken Shrine": {"Howling Grotto"},
|
||||||
"Elemental Skylands": set()
|
"Elemental Skylands": set(),
|
||||||
}
|
}
|
||||||
"""Vanilla layout mapping with all Tower HQ portals open. from -> to"""
|
"""Vanilla layout mapping with all Tower HQ portals open. from -> to"""
|
||||||
|
|
|
@ -32,7 +32,7 @@ class MessengerRules:
|
||||||
"Forlorn Temple": lambda state: state.has_all({"Wingsuit", *PHOBEKINS}, self.player),
|
"Forlorn Temple": lambda state: state.has_all({"Wingsuit", *PHOBEKINS}, self.player),
|
||||||
"Glacial Peak": self.has_vertical,
|
"Glacial Peak": self.has_vertical,
|
||||||
"Elemental Skylands": lambda state: state.has("Fairy Bottle", self.player),
|
"Elemental Skylands": lambda state: state.has("Fairy Bottle", self.player),
|
||||||
"Music Box": lambda state: state.has_all(set(NOTES), self.player) and self.has_vertical(state)
|
"Music Box": lambda state: state.has_all(set(NOTES), self.player) and self.has_vertical(state),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.location_rules = {
|
self.location_rules = {
|
||||||
|
@ -44,6 +44,7 @@ class MessengerRules:
|
||||||
"Howling Grotto Seal - Windy Saws and Balls": self.has_wingsuit,
|
"Howling Grotto Seal - Windy Saws and Balls": self.has_wingsuit,
|
||||||
"Howling Grotto Seal - Crushing Pits": lambda state: self.has_wingsuit(state) and self.has_dart(state),
|
"Howling Grotto Seal - Crushing Pits": lambda state: self.has_wingsuit(state) and self.has_dart(state),
|
||||||
# searing crags
|
# searing crags
|
||||||
|
"Astral Tea Leaves": lambda state: state.can_reach("Astral Seed", "Location", self.player),
|
||||||
"Key of Strength": lambda state: state.has("Power Thistle", self.player),
|
"Key of Strength": lambda state: state.has("Power Thistle", self.player),
|
||||||
# glacial peak
|
# glacial peak
|
||||||
"Glacial Peak Seal - Ice Climbers": self.has_dart,
|
"Glacial Peak Seal - Ice Climbers": self.has_dart,
|
||||||
|
@ -74,7 +75,7 @@ class MessengerRules:
|
||||||
# corrupted future
|
# corrupted future
|
||||||
"Key of Courage": lambda state: state.has_all({"Demon King Crown", "Fairy Bottle"}, self.player),
|
"Key of Courage": lambda state: state.has_all({"Demon King Crown", "Fairy Bottle"}, self.player),
|
||||||
# the shop
|
# the shop
|
||||||
"Shop Chest": self.has_enough_seals
|
"Shop Chest": self.has_enough_seals,
|
||||||
}
|
}
|
||||||
|
|
||||||
def has_wingsuit(self, state: CollectionState) -> bool:
|
def has_wingsuit(self, state: CollectionState) -> bool:
|
||||||
|
@ -165,7 +166,7 @@ class MessengerChallengeRules(MessengerHardRules):
|
||||||
self.region_rules.update({
|
self.region_rules.update({
|
||||||
"Forlorn Temple": lambda state: (self.has_vertical(state) and state.has_all(set(PHOBEKINS), self.player))
|
"Forlorn Temple": lambda state: (self.has_vertical(state) and state.has_all(set(PHOBEKINS), self.player))
|
||||||
or state.has_all({"Wingsuit", "Windmill Shuriken"}, self.player),
|
or state.has_all({"Wingsuit", "Windmill Shuriken"}, self.player),
|
||||||
"Elemental Skylands": lambda state: self.has_wingsuit(state) or state.has("Fairy Bottle", self.player)
|
"Elemental Skylands": lambda state: self.has_wingsuit(state) or state.has("Fairy Bottle", self.player),
|
||||||
})
|
})
|
||||||
|
|
||||||
self.location_rules.update({
|
self.location_rules.update({
|
||||||
|
@ -188,7 +189,7 @@ class MessengerOOBRules(MessengerRules):
|
||||||
|
|
||||||
self.region_rules = {
|
self.region_rules = {
|
||||||
"Elemental Skylands": lambda state: state.has_any({"Wingsuit", "Rope Dart", "Fairy Bottle"}, self.player),
|
"Elemental Skylands": lambda state: state.has_any({"Wingsuit", "Rope Dart", "Fairy Bottle"}, self.player),
|
||||||
"Music Box": lambda state: state.has_all(set(NOTES), self.player)
|
"Music Box": lambda state: state.has_all(set(NOTES), self.player),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.location_rules = {
|
self.location_rules = {
|
||||||
|
@ -203,7 +204,7 @@ class MessengerOOBRules(MessengerRules):
|
||||||
"Underworld Seal - Fireball Wave": lambda state: state.has_any({"Wingsuit", "Windmill Shuriken"},
|
"Underworld Seal - Fireball Wave": lambda state: state.has_any({"Wingsuit", "Windmill Shuriken"},
|
||||||
self.player),
|
self.player),
|
||||||
"Tower of Time Seal - Time Waster Seal": self.has_dart,
|
"Tower of Time Seal - Time Waster Seal": self.has_dart,
|
||||||
"Shop Chest": self.has_enough_seals
|
"Shop Chest": self.has_enough_seals,
|
||||||
}
|
}
|
||||||
|
|
||||||
def set_messenger_rules(self) -> None:
|
def set_messenger_rules(self) -> None:
|
||||||
|
|
|
@ -20,7 +20,7 @@ class MessengerWeb(WebWorld):
|
||||||
"English",
|
"English",
|
||||||
"setup_en.md",
|
"setup_en.md",
|
||||||
"setup/en",
|
"setup/en",
|
||||||
["alwaysintreble"]
|
["alwaysintreble"],
|
||||||
)
|
)
|
||||||
|
|
||||||
tutorials = [tut_en]
|
tutorials = [tut_en]
|
||||||
|
@ -89,7 +89,7 @@ class MessengerWorld(World):
|
||||||
if item not in
|
if item not in
|
||||||
{
|
{
|
||||||
"Power Seal", "Time Shard", *NOTES,
|
"Power Seal", "Time Shard", *NOTES,
|
||||||
*{collected_item.name for collected_item in self.multiworld.precollected_items[self.player]}
|
*{collected_item.name for collected_item in self.multiworld.precollected_items[self.player]},
|
||||||
# this is a set and currently won't create items for anything that appears in here at all
|
# this is a set and currently won't create items for anything that appears in here at all
|
||||||
# if we get in a position where this can have duplicates of items that aren't Power Seals
|
# if we get in a position where this can have duplicates of items that aren't Power Seals
|
||||||
# or Time shards, this will need to be redone.
|
# or Time shards, this will need to be redone.
|
||||||
|
|
|
@ -56,20 +56,22 @@ for it. The groups you can use for The Messenger are:
|
||||||
is recommended to quit to title and reload the save
|
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
|
* 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
|
* Toggle Windmill Shuriken button is added to option menu once the item is received
|
||||||
|
* The mod option menu will also have a hint item button, as well as a release and collect button that are all placed when
|
||||||
|
the player fulfills the necessary conditions.
|
||||||
|
|
||||||
## Currently known issues
|
## Currently known issues
|
||||||
* Necro cutscene will sometimes not play correctly, but will still reward the item
|
* 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
|
* 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. You can exit
|
* If you receive the Fairy Bottle while in Quillshroom Marsh, The De-curse Queen cutscene will not play. You can exit
|
||||||
to Searing Crags and re-enter to get it to play correctly.
|
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
|
* 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
|
* Sometimes upon teleporting back to HQ, Ninja will run left and enter a different portal than the one entered by the
|
||||||
player.
|
player. This may also cause a softlock.
|
||||||
* Text entry menus don't accept controller input
|
* Text entry menus don't accept controller input
|
||||||
* Opening the shop chest in power seal hunt mode from the tower of time HQ will soft lock the game.
|
* Opening the shop chest in power seal hunt mode from the tower of time HQ will softlock the game.
|
||||||
|
|
||||||
## What do I do if I have a problem?
|
## What do I do if I have a problem?
|
||||||
|
|
||||||
If you believe something happened that isn't intended, please get the `log.txt`from the folder of your game installation
|
If you believe something happened that isn't intended, please get the `log.txt`from the folder of your game installation
|
||||||
and send a bug report either on github or the [Archipelago Discord Server](http://archipelago.gg/discord)
|
and send a bug report either on GitHub or the [Archipelago Discord Server](http://archipelago.gg/discord)
|
||||||
|
|
|
@ -10,10 +10,11 @@
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Download and install Courier Mod Loader using the instructions on the release page
|
1. Read the [Game Info Page](../../../../games/The%20Messenger/info/en) for how the game works, caveats and known issues
|
||||||
|
2. 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)
|
* [Latest release is currently 0.7.1](https://github.com/Brokemia/Courier/releases)
|
||||||
2. Download and install the randomizer mod
|
3. Download and install the randomizer mod
|
||||||
1. Download the latest TheMessengerRandomizerAP.zip from the
|
1. Download the latest TheMessengerRandomizerAP.zip from
|
||||||
[The Messenger Randomizer Mod AP releases page](https://github.com/alwaysintreble/TheMessengerRandomizerModAP/releases)
|
[The Messenger Randomizer Mod AP releases page](https://github.com/alwaysintreble/TheMessengerRandomizerModAP/releases)
|
||||||
2. Extract the zip file to `TheMessenger/Mods/` of your game's install location
|
2. Extract the zip file to `TheMessenger/Mods/` of your game's install location
|
||||||
* You cannot have both the non-AP randomizer and the AP randomizer installed at the same time. The AP randomizer
|
* You cannot have both the non-AP randomizer and the AP randomizer installed at the same time. The AP randomizer
|
||||||
|
@ -35,10 +36,10 @@
|
||||||
2. Navigate to `Options > Third Party Mod Options`
|
2. Navigate to `Options > Third Party Mod Options`
|
||||||
3. Select `Reset Randomizer File Slots`
|
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
|
* 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 afterward.
|
||||||
4. Enter connection info using the relevant option buttons
|
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
|
* **The game is limited to alphanumerical characters and `-` so when entering the host name replace `.` with ` `.
|
||||||
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
|
* 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
|
5. Select the `Connect to Archipelago` button
|
||||||
|
|
|
@ -35,7 +35,7 @@ class AccessTest(MessengerTestBase):
|
||||||
"Tower of Time Seal - Lantern Climb", "Tower of Time Seal - Arcane Orbs",
|
"Tower of Time Seal - Lantern Climb", "Tower of Time Seal - Arcane Orbs",
|
||||||
"Underworld Seal - Sharp and Windy Climb", "Underworld Seal - Fireball Wave",
|
"Underworld Seal - Sharp and Windy Climb", "Underworld Seal - Fireball Wave",
|
||||||
"Elemental Skylands Seal - Air", "Forlorn Temple Seal - Rocket Maze",
|
"Elemental Skylands Seal - Air", "Forlorn Temple Seal - Rocket Maze",
|
||||||
"Forlorn Temple Seal - Rocket Sunset", "Astral Seed"]
|
"Forlorn Temple Seal - Rocket Sunset", "Astral Seed", "Astral Tea Leaves"]
|
||||||
items = [["Wingsuit"]]
|
items = [["Wingsuit"]]
|
||||||
self.assertAccessDependency(locations, items)
|
self.assertAccessDependency(locations, items)
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ class AccessTest(MessengerTestBase):
|
||||||
class ItemsAccessTest(MessengerTestBase):
|
class ItemsAccessTest(MessengerTestBase):
|
||||||
options = {
|
options = {
|
||||||
"shuffle_seals": "false",
|
"shuffle_seals": "false",
|
||||||
"accessibility": "items"
|
"accessibility": "items",
|
||||||
}
|
}
|
||||||
|
|
||||||
def testSelfLockingItems(self) -> None:
|
def testSelfLockingItems(self) -> None:
|
||||||
|
|
|
@ -4,7 +4,7 @@ from . import MessengerTestBase
|
||||||
|
|
||||||
class HardLogicTest(MessengerTestBase):
|
class HardLogicTest(MessengerTestBase):
|
||||||
options = {
|
options = {
|
||||||
"logic_level": "hard"
|
"logic_level": "hard",
|
||||||
}
|
}
|
||||||
|
|
||||||
def testVertical(self) -> None:
|
def testVertical(self) -> None:
|
||||||
|
@ -14,7 +14,7 @@ class HardLogicTest(MessengerTestBase):
|
||||||
"Tower of Time Seal - Time Waster Seal", "Tower of Time Seal - Lantern Climb",
|
"Tower of Time Seal - Time Waster Seal", "Tower of Time Seal - Lantern Climb",
|
||||||
"Tower of Time Seal - Arcane Orbs",
|
"Tower of Time Seal - Arcane Orbs",
|
||||||
# ninja village
|
# ninja village
|
||||||
"Candle", "Astral Seed", "Ninja Village Seal - Tree House",
|
"Candle", "Astral Seed", "Ninja Village Seal - Tree House", "Astral Tea Leaves",
|
||||||
# autumn hills
|
# autumn hills
|
||||||
"Climbing Claws", "Key of Hope",
|
"Climbing Claws", "Key of Hope",
|
||||||
"Autumn Hills Seal - Trip Saws", "Autumn Hills Seal - Double Swing Saws",
|
"Autumn Hills Seal - Trip Saws", "Autumn Hills Seal - Double Swing Saws",
|
||||||
|
@ -54,7 +54,7 @@ class HardLogicTest(MessengerTestBase):
|
||||||
windmill_locs = [
|
windmill_locs = [
|
||||||
"Key of Strength",
|
"Key of Strength",
|
||||||
"Key of Symbiosis",
|
"Key of Symbiosis",
|
||||||
"Underworld Seal - Fireball Wave"
|
"Underworld Seal - Fireball Wave",
|
||||||
]
|
]
|
||||||
for loc in windmill_locs:
|
for loc in windmill_locs:
|
||||||
with self.subTest("can't reach location with nothing", location=loc):
|
with self.subTest("can't reach location with nothing", location=loc):
|
||||||
|
@ -80,13 +80,13 @@ class HardLogicTest(MessengerTestBase):
|
||||||
class ChallengingLogicTest(MessengerTestBase):
|
class ChallengingLogicTest(MessengerTestBase):
|
||||||
options = {
|
options = {
|
||||||
"shuffle_seals": "false",
|
"shuffle_seals": "false",
|
||||||
"logic_level": "challenging"
|
"logic_level": "challenging",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class NoLogicTest(MessengerTestBase):
|
class NoLogicTest(MessengerTestBase):
|
||||||
options = {
|
options = {
|
||||||
"logic_level": "oob"
|
"logic_level": "oob",
|
||||||
}
|
}
|
||||||
|
|
||||||
def testAccess(self) -> None:
|
def testAccess(self) -> None:
|
||||||
|
|
Loading…
Reference in New Issue