Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The Messenger: Fix precollected notes not being removed from the itempool #3066

Merged
merged 2 commits into from
Mar 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions worlds/messenger/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
from datetime import date
from typing import Any, ClassVar, Dict, List, Optional, TextIO

from BaseClasses import CollectionState, Entrance, Item, ItemClassification, MultiWorld, Tutorial
Expand All @@ -9,7 +10,8 @@
from worlds.LauncherComponents import Component, Type, components
from .client_setup import launch_game
from .connections import CONNECTIONS, RANDOMIZED_CONNECTIONS, TRANSITIONS
from .constants import ALL_ITEMS, ALWAYS_LOCATIONS, BOSS_LOCATIONS, FILLER, NOTES, PHOBEKINS, PROG_ITEMS, USEFUL_ITEMS
from .constants import ALL_ITEMS, ALWAYS_LOCATIONS, BOSS_LOCATIONS, FILLER, NOTES, PHOBEKINS, PROG_ITEMS, TRAPS, \
USEFUL_ITEMS
from .options import AvailablePortals, Goal, Logic, MessengerOptions, NotesNeeded, ShuffleTransitions
from .portals import PORTALS, add_closed_portal_reqs, disconnect_portals, shuffle_portals, validate_portals
from .regions import LEVELS, MEGA_SHARDS, LOCATIONS, REGION_CONNECTIONS
Expand Down Expand Up @@ -110,7 +112,7 @@ class MessengerWorld(World):
},
}

required_client_version = (0, 4, 3)
required_client_version = (0, 4, 4)

web = MessengerWeb()

Expand All @@ -127,6 +129,7 @@ class MessengerWorld(World):
portal_mapping: List[int]
transitions: List[Entrance]
reachable_locs: int = 0
filler: Dict[str, int]

def generate_early(self) -> None:
if self.options.goal == Goal.option_power_seal_hunt:
Expand All @@ -146,15 +149,20 @@ def generate_early(self) -> None:
self.starting_portals = [f"{portal} Portal"
for portal in starting_portals[:3] +
self.random.sample(starting_portals[3:], k=self.options.available_portals - 3)]

# super complicated method for adding searing crags to starting portals if it wasn't chosen
# need to add a check for transition shuffle when that gets added back in
# TODO add a check for transition shuffle when that gets added back in
if not self.options.shuffle_portals and "Searing Crags Portal" not in self.starting_portals:
self.starting_portals.append("Searing Crags Portal")
if len(self.starting_portals) > 4:
portals_to_strip = [portal for portal in ["Riviere Turquoise Portal", "Sunken Shrine Portal"]
if portal in self.starting_portals]
self.starting_portals.remove(self.random.choice(portals_to_strip))

self.filler = FILLER.copy()
if (not hasattr(self.options, "traps") and date.today() < date(2024, 4, 2)) or self.options.traps:
self.filler.update(TRAPS)

self.plando_portals = []
self.portal_mapping = []
self.spoiler_portal_mapping = {}
Expand Down Expand Up @@ -182,12 +190,13 @@ def create_regions(self) -> None:
def create_items(self) -> None:
# create items that are always in the item pool
main_movement_items = ["Rope Dart", "Wingsuit"]
precollected_names = [item.name for item in self.multiworld.precollected_items[self.player]]
itempool: List[MessengerItem] = [
self.create_item(item)
for item in self.item_name_to_id
if "Time Shard" not in item and item not in {
if item not in {
"Power Seal", *NOTES, *FIGURINES, *main_movement_items,
*{collected_item.name for collected_item in self.multiworld.precollected_items[self.player]},
*precollected_names, *FILLER, *TRAPS,
}
]

Expand All @@ -199,7 +208,7 @@ def create_items(self) -> None:
if self.options.goal == Goal.option_open_music_box:
# make a list of all notes except those in the player's defined starting inventory, and adjust the
# amount we need to put in the itempool and precollect based on that
notes = [note for note in NOTES if note not in self.multiworld.precollected_items[self.player]]
notes = [note for note in NOTES if note not in precollected_names]
self.random.shuffle(notes)
precollected_notes_amount = NotesNeeded.range_end - \
self.options.notes_needed - \
Expand Down Expand Up @@ -228,8 +237,8 @@ def create_items(self) -> None:
remaining_fill = len(self.multiworld.get_unfilled_locations(self.player)) - len(itempool)
if remaining_fill < 10:
self._filler_items = self.random.choices(
list(FILLER)[2:],
weights=list(FILLER.values())[2:],
list(self.filler)[2:],
weights=list(self.filler.values())[2:],
k=remaining_fill
)
filler = [self.create_filler() for _ in range(remaining_fill)]
Expand Down Expand Up @@ -300,8 +309,8 @@ def fill_slot_data(self) -> Dict[str, Any]:
def get_filler_item_name(self) -> str:
if not getattr(self, "_filler_items", None):
self._filler_items = [name for name in self.random.choices(
list(FILLER),
weights=list(FILLER.values()),
list(self.filler),
weights=list(self.filler.values()),
k=20
)]
return self._filler_items.pop(0)
Expand Down Expand Up @@ -335,6 +344,9 @@ def get_item_classification(self, name: str) -> ItemClassification:

if name in {*USEFUL_ITEMS, *USEFUL_SHOP_ITEMS}:
return ItemClassification.useful

if name in TRAPS:
return ItemClassification.trap

return ItemClassification.filler

Expand Down
7 changes: 7 additions & 0 deletions worlds/messenger/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
"Time Shard (500)": 5,
}

TRAPS = {
"Teleport Trap": 5,
"Prophecy Trap": 10,
}

# item_name_to_id needs to be deterministic and match upstream
ALL_ITEMS = [
*NOTES,
Expand All @@ -71,6 +76,8 @@
*SHOP_ITEMS,
*FIGURINES,
"Money Wrench",
"Teleport Trap",
"Prophecy Trap",
]

# locations
Expand Down
9 changes: 9 additions & 0 deletions worlds/messenger/options.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from dataclasses import dataclass
from datetime import date
from typing import Dict

from schema import And, Optional, Or, Schema
Expand Down Expand Up @@ -123,6 +124,11 @@ class RequiredSeals(Range):
default = range_end


class Traps(Toggle):
"""Whether traps should be included in the itempool."""
display_name = "Include Traps"


class ShopPrices(Range):
"""Percentage modifier for shuffled item prices in shops"""
display_name = "Shop Prices Modifier"
Expand Down Expand Up @@ -199,3 +205,6 @@ class MessengerOptions(DeathLinkMixin, PerGameCommonOptions):
percent_seals_required: RequiredSeals
shop_price: ShopPrices
shop_price_plan: PlannedShopPrices

if date.today() > date(2024, 4, 1):
traps: Traps
Loading