Core: Add a function to allow worlds to easily allow self-locking items (#1383)

* implement function to allow self locking items for items accessibility

* swap some lttp locations to use new functionality

* lambda capture `item_name` and `location`

* don't lambda capture location

* Revert weird visual indent

* make location.always_allow additive

* fix always_allow rule for multiple items

* don't need to lambda capture item_names

* oop

* move player assignment to the beginning

* always_allow should only be for that player so prevent non_local_items

* messenger got merged so have it use this

* Core: fix doc string indentation for allow_self_locking_items

* Core: fix doc string indentation for allow_self_locking_items, number two

---------

Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com>
This commit is contained in:
alwaysintreble
2023-03-13 18:55:34 -05:00
committed by GitHub
parent 060ee926e7
commit 573a1a8402
4 changed files with 50 additions and 56 deletions

View File

@@ -1,7 +1,7 @@
import collections
import typing
from BaseClasses import LocationProgressType, MultiWorld
from BaseClasses import LocationProgressType, MultiWorld, Location, Region, Entrance
if typing.TYPE_CHECKING:
import BaseClasses
@@ -143,14 +143,41 @@ def add_item_rule(location: "BaseClasses.Location", rule: ItemRule, combine: str
def item_in_locations(state: "BaseClasses.CollectionState", item: str, player: int,
locations: typing.Sequence["BaseClasses.Location"]) -> bool:
for location in locations:
if item_name(state, location[0], location[1]) == (item, player):
if location_item_name(state, location[0], location[1]) == (item, player):
return True
return False
def item_name(state: "BaseClasses.CollectionState", location: str, player: int) -> \
def location_item_name(state: "BaseClasses.CollectionState", location: str, player: int) -> \
typing.Optional[typing.Tuple[str, int]]:
location = state.multiworld.get_location(location, player)
if location.item is None:
return None
return location.item.name, location.item.player
def allow_self_locking_items(spot: typing.Union[Location, Region], *item_names: str) -> None:
"""
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
item_names: item name or names that are allowed to be placed in the Location or Region
"""
player = spot.player
def add_allowed_rules(area: typing.Union[Location, Entrance], location: Location) -> None:
def set_always_allow(location: Location, rule: typing.Callable) -> None:
location.always_allow = rule
for item_name in item_names:
add_rule(area, lambda state, item_name=item_name:
location_item_name(state, location.name, player) == (item_name, player), "or")
set_always_allow(location, lambda state, item:
item.player == player and item.name in [item_name for item_name in item_names])
if isinstance(spot, Region):
for entrance in spot.entrances:
for location in spot.locations:
add_allowed_rules(entrance, location)
else:
add_allowed_rules(spot, spot)