make world-local items available as a general option

This commit is contained in:
Fabian Dill 2020-06-03 22:13:58 +02:00
parent 38cbcc662f
commit e55726efca
7 changed files with 53 additions and 7 deletions

View File

@ -113,6 +113,7 @@ class World(object):
set_player_attr('can_take_damage', True) set_player_attr('can_take_damage', True)
set_player_attr('glitch_boots', True) set_player_attr('glitch_boots', True)
set_player_attr('progression_balancing', True) set_player_attr('progression_balancing', True)
set_player_attr('local_items', set())
def get_name_string_for_object(self, obj) -> str: def get_name_string_for_object(self, obj) -> str:
return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})' return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})'

View File

@ -236,7 +236,10 @@ def parse_arguments(argv, no_defaults=False):
Keys are universal, shooting arrows costs rupees, Keys are universal, shooting arrows costs rupees,
and a few other little things make this more like Zelda-1. and a few other little things make this more like Zelda-1.
''', action='store_true') ''', action='store_true')
parser.add_argument('--startinventory', default=defval(''), help='Specifies a list of items that will be in your starting inventory (separated by commas)') parser.add_argument('--startinventory', default=defval(''),
help='Specifies a list of items that will be in your starting inventory (separated by commas)')
parser.add_argument('--local_items', default=defval(''),
help='Specifies a list of items that will not spread across the multiworld (separated by commas)')
parser.add_argument('--custom', default=defval(False), help='Not supported.') parser.add_argument('--custom', default=defval(False), help='Not supported.')
parser.add_argument('--customitemarray', default=defval(False), help='Not supported.') parser.add_argument('--customitemarray', default=defval(False), help='Not supported.')
parser.add_argument('--accessibility', default=defval('items'), const='items', nargs='?', choices=['items', 'locations', 'none'], help='''\ parser.add_argument('--accessibility', default=defval('items'), const='items', nargs='?', choices=['items', 'locations', 'none'], help='''\
@ -323,7 +326,7 @@ def parse_arguments(argv, no_defaults=False):
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
'shuffle', 'crystals_ganon', 'crystals_gt', 'openpyramid', 'timer', 'shuffle', 'crystals_ganon', 'crystals_gt', 'openpyramid', 'timer',
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory', 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
'retro', 'accessibility', 'hints', 'beemizer', 'local_items', 'retro', 'accessibility', 'hints', 'beemizer',
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
'heartbeep', "skip_progression_balancing", 'heartbeep', "skip_progression_balancing",

View File

@ -184,3 +184,24 @@ item_table = {'Bow': (True, False, None, 0x0B, 'You have\nchosen the\narcher cla
lookup_id_to_name = {data[3]: name for name, data in item_table.items()} lookup_id_to_name = {data[3]: name for name, data in item_table.items()}
hint_blacklist = {"Triforce"} hint_blacklist = {"Triforce"}
item_name_groups = {"Bows": {"Bow", "Silver Arrows", "Progressive Bow (Alt)", "Progressive Bow"}}
# generic groups, (Name, substring)
_simple_groups = {("Swords", "Sword"),
("Small Keys", "Small Key"),
("Big Keys", "Big Key"),
("Compasses", "Compass"),
("Maps", "Map"),
("Bottles", "Bottle"),
("Potions", "Potion"),
("Rupees", "Rupee")
}
for basename, substring in _simple_groups:
tempset = item_name_groups[basename] = set()
for itemname in item_table:
if substring in itemname:
tempset.add(itemname)
del (_simple_groups)

View File

@ -85,6 +85,7 @@ def main(args, seed=None):
item = ItemFactory(tok.strip(), player) item = ItemFactory(tok.strip(), player)
if item: if item:
world.push_precollected(item) world.push_precollected(item)
world.local_items[player] = {item.strip() for item in args.local_items[player].split(',')}
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
create_regions(world, player) create_regions(world, player)

View File

@ -14,6 +14,7 @@ from Utils import parse_yaml
from Rom import get_sprite_from_name from Rom import get_sprite_from_name
from EntranceRandomizer import parse_arguments from EntranceRandomizer import parse_arguments
from Main import main as ERmain from Main import main as ERmain
from Items import item_name_groups, item_table
@ -355,11 +356,22 @@ def roll_settings(weights):
startitems.append(item) startitems.append(item)
elif itemvalue: elif itemvalue:
startitems.append(item) startitems.append(item)
ret.glitch_boots = get_choice('glitch_boots', weights) if 'glitch_boots' in weights else True
ret.startinventory = ','.join(startitems) ret.startinventory = ','.join(startitems)
ret.glitch_boots = get_choice('glitch_boots', weights) if 'glitch_boots' in weights else True
ret.remote_items = get_choice('remote_items', weights) if 'remote_items' in weights else False ret.remote_items = get_choice('remote_items', weights) if 'remote_items' in weights else False
ret.local_items = set()
for item_name in weights.get('local_items', []):
items = item_name_groups.get(item_name, {item_name})
for item in items:
if item in item_table:
ret.local_items.add(item)
else:
logging.warning(f"Could not force item {item} to be world-local, as it was not recognized.")
ret.local_items = ",".join(ret.local_items)
if 'rom' in weights: if 'rom' in weights:
romweights = weights['rom'] romweights = weights['rom']
ret.sprite = get_choice('sprite', romweights) ret.sprite = get_choice('sprite', romweights)

View File

@ -138,9 +138,12 @@ def global_rules(world, player):
# ganon can only carry triforce # ganon can only carry triforce
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player) add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)
if world.goal[player] == "localtriforcehunt": if world.goal[player] == "localtriforcehunt":
world.local_items[player].add('Triforce Piece')
if world.local_items[player]:
for location in world.get_locations(): for location in world.get_locations():
if location.player != player: if location.player != player:
forbid_item(location, 'Triforce Piece', player) for item in world.local_items[player]:
forbid_item(location, item, player)
# determines which S&Q locations are available - hide from paths since it isn't an in-game location # determines which S&Q locations are available - hide from paths since it isn't an in-game location
world.get_region('Menu', player).can_reach_private = lambda state: True world.get_region('Menu', player).can_reach_private = lambda state: True
for exit in world.get_region('Menu', player).exits: for exit in world.get_region('Menu', player).exits:

View File

@ -151,6 +151,11 @@ timer:
ohko: 0 ohko: 0
timed_countdown: 0 timed_countdown: 0
display: 0 display: 0
#can be uncommented to use it
#local_items: #force certain items to appear in your world only, not across the multiworld. Recognizes some group names, like "Swords"
# - "Moon Pearl"
# - "Small Keys"
# - "Big Keys"
glitch_boots: glitch_boots:
on: 1 # enables that you start with Pegasus Boots in any glitched logic mode on: 1 # enables that you start with Pegasus Boots in any glitched logic mode
off: 0 off: 0