Merge remote-tracking branch 'origin' into OverworldShuffle
This commit is contained in:
@@ -2,12 +2,15 @@ import os
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
import yaml
|
||||
from typing import Any
|
||||
from yaml.representer import Representer
|
||||
from Utils import HexInt, hex_representer
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
import RaceRandom as random
|
||||
from BaseClasses import LocationType, DoorType
|
||||
from OverworldShuffle import default_flute_connections, flute_data
|
||||
from source.tools.MysteryUtils import roll_settings, get_weights
|
||||
|
||||
|
||||
@@ -46,8 +49,8 @@ class CustomSettings(object):
|
||||
return meta['players']
|
||||
|
||||
def adjust_args(self, args):
|
||||
def get_setting(value, default):
|
||||
if value:
|
||||
def get_setting(value: Any, default):
|
||||
if value or value == 0:
|
||||
if isinstance(value, dict):
|
||||
return random.choices(list(value.keys()), list(value.values()), k=1)[0]
|
||||
else:
|
||||
@@ -62,6 +65,7 @@ class CustomSettings(object):
|
||||
args.suppress_rom = get_setting(meta['suppress_rom'], args.suppress_rom)
|
||||
args.names = get_setting(meta['names'], args.names)
|
||||
args.race = get_setting(meta['race'], args.race)
|
||||
args.notes = get_setting(meta['user_notes'], args.notes)
|
||||
self.player_range = range(1, args.multi + 1)
|
||||
if 'settings' in self.file_source:
|
||||
for p in self.player_range:
|
||||
@@ -72,6 +76,14 @@ class CustomSettings(object):
|
||||
args.mystery = True
|
||||
else:
|
||||
settings = defaultdict(lambda: None, player_setting)
|
||||
args.ow_shuffle[p] = get_setting(settings['ow_shuffle'], args.ow_shuffle[p])
|
||||
args.ow_terrain[p] = get_setting(settings['ow_terrain'], args.ow_terrain[p])
|
||||
args.ow_crossed[p] = get_setting(settings['ow_crossed'], args.ow_crossed[p])
|
||||
args.ow_keepsimilar[p] = get_setting(settings['ow_keepsimilar'], args.ow_keepsimilar[p])
|
||||
args.ow_mixed[p] = get_setting(settings['ow_mixed'], args.ow_mixed[p])
|
||||
args.ow_whirlpool[p] = get_setting(settings['ow_whirlpool'], args.ow_whirlpool[p])
|
||||
args.ow_fluteshuffle[p] = get_setting(settings['ow_fluteshuffle'], args.ow_fluteshuffle[p])
|
||||
args.bonk_drops[p] = get_setting(settings['bonk_drops'], args.bonk_drops[p])
|
||||
args.shuffle[p] = get_setting(settings['shuffle'], args.shuffle[p])
|
||||
args.door_shuffle[p] = get_setting(settings['door_shuffle'], args.door_shuffle[p])
|
||||
args.logic[p] = get_setting(settings['logic'], args.logic[p])
|
||||
@@ -112,10 +124,12 @@ class CustomSettings(object):
|
||||
args.trap_door_mode[p] = get_setting(settings['trap_door_mode'], args.trap_door_mode[p])
|
||||
args.key_logic_algorithm[p] = get_setting(settings['key_logic_algorithm'], args.key_logic_algorithm[p])
|
||||
args.decoupledoors[p] = get_setting(settings['decoupledoors'], args.decoupledoors[p])
|
||||
args.door_self_loops[p] = get_setting(settings['door_self_loops'], args.door_self_loops[p])
|
||||
args.dungeon_counters[p] = get_setting(settings['dungeon_counters'], args.dungeon_counters[p])
|
||||
args.crystals_gt[p] = get_setting(settings['crystals_gt'], args.crystals_gt[p])
|
||||
args.crystals_ganon[p] = get_setting(settings['crystals_ganon'], args.crystals_ganon[p])
|
||||
args.experimental[p] = get_setting(settings['experimental'], args.experimental[p])
|
||||
args.collection_rate[p] = get_setting(settings['collection_rate'], args.collection_rate[p])
|
||||
args.openpyramid[p] = get_setting(settings['openpyramid'], args.openpyramid[p])
|
||||
args.bigkeyshuffle[p] = get_setting(settings['bigkeyshuffle'], args.bigkeyshuffle[p])
|
||||
args.keyshuffle[p] = get_setting(settings['keyshuffle'], args.keyshuffle[p])
|
||||
@@ -129,8 +143,8 @@ class CustomSettings(object):
|
||||
args.mapshuffle[p] = True
|
||||
args.compassshuffle[p] = True
|
||||
|
||||
args.shufflebosses[p] = get_setting(settings['shufflebosses'], args.shufflebosses[p])
|
||||
args.shuffleenemies[p] = get_setting(settings['shuffleenemies'], args.shuffleenemies[p])
|
||||
args.shufflebosses[p] = get_setting(settings['boss_shuffle'], args.shufflebosses[p])
|
||||
args.shuffleenemies[p] = get_setting(settings['enemy_shuffle'], args.shuffleenemies[p])
|
||||
args.enemy_health[p] = get_setting(settings['enemy_health'], args.enemy_health[p])
|
||||
args.enemy_damage[p] = get_setting(settings['enemy_damage'], args.enemy_damage[p])
|
||||
args.shufflepots[p] = get_setting(settings['shufflepots'], args.shufflepots[p])
|
||||
@@ -142,6 +156,12 @@ class CustomSettings(object):
|
||||
args.pseudoboots[p] = get_setting(settings['pseudoboots'], args.pseudoboots[p])
|
||||
args.triforce_goal[p] = get_setting(settings['triforce_goal'], args.triforce_goal[p])
|
||||
args.triforce_pool[p] = get_setting(settings['triforce_pool'], args.triforce_pool[p])
|
||||
args.triforce_goal_min[p] = get_setting(settings['triforce_goal_min'], args.triforce_goal_min[p])
|
||||
args.triforce_goal_max[p] = get_setting(settings['triforce_goal_max'], args.triforce_goal_max[p])
|
||||
args.triforce_pool_min[p] = get_setting(settings['triforce_pool_min'], args.triforce_pool_min[p])
|
||||
args.triforce_pool_max[p] = get_setting(settings['triforce_pool_max'], args.triforce_pool_max[p])
|
||||
args.triforce_min_difference[p] = get_setting(settings['triforce_min_difference'], args.triforce_min_difference[p])
|
||||
args.triforce_max_difference[p] = get_setting(settings['triforce_max_difference'], args.triforce_max_difference[p])
|
||||
args.beemizer[p] = get_setting(settings['beemizer'], args.beemizer[p])
|
||||
|
||||
# mystery usage
|
||||
@@ -176,6 +196,16 @@ class CustomSettings(object):
|
||||
return self.file_source['advanced_placements']
|
||||
return None
|
||||
|
||||
def get_owtileflips(self):
|
||||
if 'ow-tileflips' in self.file_source:
|
||||
return self.file_source['ow-tileflips']
|
||||
return None
|
||||
|
||||
def get_owflutespots(self):
|
||||
if 'ow-flutespots' in self.file_source:
|
||||
return self.file_source['ow-flutespots']
|
||||
return None
|
||||
|
||||
def get_entrances(self):
|
||||
if 'entrances' in self.file_source:
|
||||
return self.file_source['entrances']
|
||||
@@ -206,17 +236,26 @@ class CustomSettings(object):
|
||||
return self.file_source['drops']
|
||||
return None
|
||||
|
||||
def create_from_world(self, world, race):
|
||||
def create_from_world(self, world, settings):
|
||||
self.player_range = range(1, world.players + 1)
|
||||
settings_dict, meta_dict = {}, {}
|
||||
self.world_rep['meta'] = meta_dict
|
||||
meta_dict['players'] = world.players
|
||||
meta_dict['algorithm'] = world.algorithm
|
||||
meta_dict['seed'] = world.seed
|
||||
meta_dict['race'] = race
|
||||
meta_dict['race'] = settings.race
|
||||
meta_dict['user_notes'] = settings.notes
|
||||
self.world_rep['settings'] = settings_dict
|
||||
for p in self.player_range:
|
||||
settings_dict[p] = {}
|
||||
settings_dict[p]['ow_shuffle'] = world.owShuffle[p]
|
||||
settings_dict[p]['ow_terrain'] = world.owTerrain[p]
|
||||
settings_dict[p]['ow_crossed'] = world.owCrossed[p]
|
||||
settings_dict[p]['ow_keepsimilar'] = world.owKeepSimilar[p]
|
||||
settings_dict[p]['ow_mixed'] = world.owMixed[p]
|
||||
settings_dict[p]['ow_whirlpool'] = world.owWhirlpoolShuffle[p]
|
||||
settings_dict[p]['ow_fluteshuffle'] = world.owFluteShuffle[p]
|
||||
settings_dict[p]['bonk_drops'] = world.shuffle_bonk_drops[p]
|
||||
settings_dict[p]['shuffle'] = world.shuffle[p]
|
||||
settings_dict[p]['door_shuffle'] = world.doorShuffle[p]
|
||||
settings_dict[p]['intensity'] = world.intensity[p]
|
||||
@@ -224,6 +263,7 @@ class CustomSettings(object):
|
||||
settings_dict[p]['trap_door_mode'] = world.trap_door_mode[p]
|
||||
settings_dict[p]['key_logic_algorithm'] = world.key_logic_algorithm[p]
|
||||
settings_dict[p]['decoupledoors'] = world.decoupledoors[p]
|
||||
settings_dict[p]['door_self_loops'] = world.door_self_loops[p]
|
||||
settings_dict[p]['logic'] = world.logic[p]
|
||||
settings_dict[p]['mode'] = world.mode[p]
|
||||
settings_dict[p]['swords'] = world.swords[p]
|
||||
@@ -244,6 +284,7 @@ class CustomSettings(object):
|
||||
settings_dict[p]['crystals_gt'] = world.crystals_gt_orig[p]
|
||||
settings_dict[p]['crystals_ganon'] = world.crystals_ganon_orig[p]
|
||||
settings_dict[p]['experimental'] = world.experimental[p]
|
||||
settings_dict[p]['collection_rate'] = world.collection_rate[p]
|
||||
settings_dict[p]['openpyramid'] = world.open_pyramid[p]
|
||||
settings_dict[p]['bigkeyshuffle'] = world.bigkeyshuffle[p]
|
||||
settings_dict[p]['keyshuffle'] = world.keyshuffle[p]
|
||||
@@ -313,6 +354,23 @@ class CustomSettings(object):
|
||||
else:
|
||||
placements[location.player][location.name] = location.item.name
|
||||
|
||||
def record_overworld(self, world):
|
||||
self.world_rep['ow-tileflips'] = flips = {}
|
||||
for p in self.player_range:
|
||||
if p in world.owswaps and len(world.owswaps[p][0]) > 0:
|
||||
flips[p] = {}
|
||||
flips[p]['force_flip'] = list(HexInt(f) for f in world.owswaps[p][0] if f < 0x40 or f >= 0x80)
|
||||
flips[p]['force_flip'].sort()
|
||||
flips[p]['undefined_chance'] = 0
|
||||
self.world_rep['ow-flutespots'] = flute = {}
|
||||
for p in self.player_range:
|
||||
flute[p] = {}
|
||||
if p in world.owflutespots:
|
||||
flute[p]['force'] = list(HexInt(id) for id in sorted(world.owflutespots[p]))
|
||||
else:
|
||||
flute[p]['force'] = list(HexInt(id) for id in sorted(default_flute_connections))
|
||||
flute[p]['forbid'] = []
|
||||
|
||||
def record_entrances(self, world):
|
||||
self.world_rep['entrances'] = entrances = {}
|
||||
world.custom_entrances = {}
|
||||
@@ -375,6 +433,7 @@ class CustomSettings(object):
|
||||
|
||||
def write_to_file(self, destination):
|
||||
yaml.add_representer(defaultdict, Representer.represent_dict)
|
||||
yaml.add_representer(HexInt, hex_representer)
|
||||
with open(destination, 'w') as file:
|
||||
yaml.dump(self.world_rep, file)
|
||||
|
||||
|
||||
@@ -56,10 +56,9 @@ SETTINGSTOPROCESS = {
|
||||
"randomizer": {
|
||||
"item": {
|
||||
"hints": "hints",
|
||||
"retro": "retro",
|
||||
"bombbag": "bombbag",
|
||||
"shopsanity": "shopsanity",
|
||||
"pseudoboots": "pseudoboots",
|
||||
"race": "race",
|
||||
|
||||
"worldstate": "mode",
|
||||
"logiclevel": "logic",
|
||||
"goal": "goal",
|
||||
@@ -67,15 +66,28 @@ SETTINGSTOPROCESS = {
|
||||
"crystals_ganon": "crystals_ganon",
|
||||
"ganon_item": "ganon_item",
|
||||
"weapons": "swords",
|
||||
"itempool": "difficulty",
|
||||
|
||||
"retro": "retro",
|
||||
"sortingalgo": "algorithm",
|
||||
"accessibility": "accessibility",
|
||||
"restrict_boss_items": "restrict_boss_items",
|
||||
"itemfunction": "item_functionality",
|
||||
"timer": "timer",
|
||||
|
||||
"shopsanity": "shopsanity",
|
||||
"bonk_drops": "bonk_drops",
|
||||
"pottery": "pottery",
|
||||
"colorizepots": "colorizepots",
|
||||
"potshuffle": "shufflepots",
|
||||
"dropshuffle": "dropshuffle",
|
||||
"keydropshuffle": "keydropshuffle",
|
||||
"take_any": "take_any",
|
||||
|
||||
"itempool": "difficulty",
|
||||
"flute_mode": "flute_mode",
|
||||
"bow_mode": "bow_mode",
|
||||
"timer": "timer",
|
||||
"accessibility": "accessibility",
|
||||
"sortingalgo": "algorithm",
|
||||
"beemizer": "beemizer",
|
||||
"restrict_boss_items": "restrict_boss_items"
|
||||
"bombbag": "bombbag"
|
||||
},
|
||||
"overworld": {
|
||||
"overworldshuffle": "ow_shuffle",
|
||||
@@ -84,17 +96,32 @@ SETTINGSTOPROCESS = {
|
||||
"keepsimilar": "ow_keepsimilar",
|
||||
"mixed": "ow_mixed",
|
||||
"whirlpool": "ow_whirlpool",
|
||||
"bonk_drops": "bonk_drops",
|
||||
"overworldflute": "ow_fluteshuffle"
|
||||
},
|
||||
"entrance": {
|
||||
"openpyramid": "openpyramid",
|
||||
"entranceshuffle": "shuffle",
|
||||
"shuffleganon": "shuffleganon",
|
||||
"shufflelinks": "shufflelinks",
|
||||
"shuffletavern": "shuffletavern",
|
||||
"entranceshuffle": "shuffle",
|
||||
"openpyramid": "openpyramid",
|
||||
"overworld_map": "overworld_map",
|
||||
"take_any": "take_any",
|
||||
},
|
||||
"dungeon": {
|
||||
"smallkeyshuffle": "keyshuffle",
|
||||
"mapshuffle": "mapshuffle",
|
||||
"compassshuffle": "compassshuffle",
|
||||
"bigkeyshuffle": "bigkeyshuffle",
|
||||
"key_logic_algorithm": "key_logic_algorithm",
|
||||
"dungeondoorshuffle": "door_shuffle",
|
||||
"dungeonintensity": "intensity",
|
||||
"door_type_mode": "door_type_mode",
|
||||
"trap_door_mode": "trap_door_mode",
|
||||
"decoupledoors": "decoupledoors",
|
||||
"door_self_loops": "door_self_loops",
|
||||
"experimental": "experimental",
|
||||
"dungeon_counters": "dungeon_counters",
|
||||
"mixed_travel": "mixed_travel",
|
||||
"standardize_palettes": "standardize_palettes",
|
||||
},
|
||||
"enemizer": {
|
||||
"enemyshuffle": "shuffleenemies",
|
||||
@@ -102,27 +129,6 @@ SETTINGSTOPROCESS = {
|
||||
"enemydamage": "enemy_damage",
|
||||
"enemyhealth": "enemy_health"
|
||||
},
|
||||
"dungeon": {
|
||||
"mapshuffle": "mapshuffle",
|
||||
"compassshuffle": "compassshuffle",
|
||||
"smallkeyshuffle": "keyshuffle",
|
||||
"bigkeyshuffle": "bigkeyshuffle",
|
||||
"dungeondoorshuffle": "door_shuffle",
|
||||
"dungeonintensity": "intensity",
|
||||
"door_type_mode": "door_type_mode",
|
||||
"trap_door_mode": "trap_door_mode",
|
||||
"key_logic_algorithm": "key_logic_algorithm",
|
||||
"decoupledoors": "decoupledoors",
|
||||
"keydropshuffle": "keydropshuffle",
|
||||
"dropshuffle": "dropshuffle",
|
||||
"pottery": "pottery",
|
||||
"colorizepots": "colorizepots",
|
||||
"potshuffle": "shufflepots",
|
||||
"experimental": "experimental",
|
||||
"dungeon_counters": "dungeon_counters",
|
||||
"mixed_travel": "mixed_travel",
|
||||
"standardize_palettes": "standardize_palettes"
|
||||
},
|
||||
"gameoptions": {
|
||||
"nobgm": "disablemusic",
|
||||
"quickswap": "quickswap",
|
||||
@@ -142,12 +148,15 @@ SETTINGSTOPROCESS = {
|
||||
"createrom": "create_rom",
|
||||
"calcplaythrough": "calc_playthrough",
|
||||
"print_custom_yaml": "print_custom_yaml",
|
||||
"usestartinventory": "usestartinventory",
|
||||
"usecustompool": "custom",
|
||||
"race": "race",
|
||||
"saveonexit": "saveonexit"
|
||||
}
|
||||
},
|
||||
"startinventory": {
|
||||
"usestartinventory": "usestartinventory"
|
||||
},
|
||||
"custom": {
|
||||
"usecustompool": "custom"
|
||||
},
|
||||
"bottom": {
|
||||
"content": {
|
||||
"names": "names",
|
||||
|
||||
@@ -22,7 +22,7 @@ def generate_dungeon(builder, entrance_region_names, split_dungeon, world, playe
|
||||
queue = collections.deque(proposed_map.items())
|
||||
while len(queue) > 0:
|
||||
a, b = queue.popleft()
|
||||
if world.decoupledoors[player]:
|
||||
if a == b or world.decoupledoors[player]:
|
||||
connect_doors_one_way(a, b)
|
||||
else:
|
||||
connect_doors(a, b)
|
||||
@@ -128,14 +128,14 @@ def create_random_proposal(doors_to_connect, world, player):
|
||||
next_hook = random.choice(hooks_left)
|
||||
primary_door = random.choice(primary_bucket[next_hook])
|
||||
opp_hook, secondary_door = type_map[next_hook], None
|
||||
while (secondary_door is None or secondary_door == primary_door
|
||||
while (secondary_door is None or (secondary_door == primary_door and not world.door_self_loops[player])
|
||||
or decouple_check(primary_bucket[next_hook], secondary_bucket[opp_hook],
|
||||
primary_door, secondary_door, world, player)):
|
||||
secondary_door = random.choice(secondary_bucket[opp_hook])
|
||||
proposal[primary_door] = secondary_door
|
||||
primary_bucket[next_hook].remove(primary_door)
|
||||
secondary_bucket[opp_hook].remove(secondary_door)
|
||||
if not world.decoupledoors[player]:
|
||||
if primary_door != secondary_door and not world.decoupledoors[player]:
|
||||
proposal[secondary_door] = primary_door
|
||||
primary_bucket[opp_hook].remove(secondary_door)
|
||||
secondary_bucket[next_hook].remove(primary_door)
|
||||
@@ -200,11 +200,19 @@ def modify_proposal(proposed_map, explored_state, doors_to_connect, hash_code_se
|
||||
unvisted_bucket[opp_hook].sort(key=lambda d: d.name)
|
||||
new_door = random.choice(unvisted_bucket[opp_hook])
|
||||
old_target = proposed_map[attempt]
|
||||
proposed_map[attempt] = new_door
|
||||
if not world.decoupledoors[player]:
|
||||
old_attempt = proposed_map[new_door]
|
||||
else:
|
||||
old_attempt = next(x for x in proposed_map if proposed_map[x] == new_door)
|
||||
# ensure nothing gets messed up when something loops with itself
|
||||
if attempt == old_target and old_attempt == new_door:
|
||||
old_attempt = new_door
|
||||
old_target = attempt
|
||||
elif attempt == old_target:
|
||||
old_target = old_attempt
|
||||
elif old_attempt == new_door:
|
||||
old_attempt = old_target
|
||||
proposed_map[attempt] = new_door
|
||||
proposed_map[old_attempt] = old_target
|
||||
if not world.decoupledoors[player]:
|
||||
proposed_map[old_target] = old_attempt
|
||||
|
||||
@@ -203,13 +203,20 @@ def create_guiargs(parent):
|
||||
|
||||
# Cycle through each page
|
||||
for mainpage in options:
|
||||
subpage = None
|
||||
_, v = next(iter(options[mainpage].items()))
|
||||
if isinstance(v, str):
|
||||
subpage = ""
|
||||
# Cycle through each subpage (in case of Item Randomizer)
|
||||
for subpage in options[mainpage]:
|
||||
for subpage in (options[mainpage] if subpage is None else [subpage]):
|
||||
# Cycle through each widget
|
||||
for widget in options[mainpage][subpage]:
|
||||
for widget in (options[mainpage][subpage] if subpage != "" else options[mainpage]):
|
||||
# Get the value and set it
|
||||
arg = options[mainpage][subpage][widget]
|
||||
setattr(guiargs, arg, parent.pages[mainpage].pages[subpage].widgets[widget].storageVar.get())
|
||||
arg = options[mainpage][subpage][widget] if subpage != "" else options[mainpage][widget]
|
||||
page = parent.pages[mainpage].pages[subpage] if subpage != "" else parent.pages[mainpage]
|
||||
pagewidgets = page.content.customWidgets if mainpage == "custom" else page.content.startingWidgets if mainpage == "startinventory" else page.widgets
|
||||
if hasattr(pagewidgets[widget], 'storageVar'):
|
||||
setattr(guiargs, arg, pagewidgets[widget].storageVar.get())
|
||||
|
||||
# Get EnemizerCLI setting
|
||||
guiargs.enemizercli = parent.pages["randomizer"].pages["enemizer"].widgets["enemizercli"].storageVar.get()
|
||||
@@ -226,7 +233,7 @@ def create_guiargs(parent):
|
||||
guiargs.customizer = customizer_value
|
||||
|
||||
# Get if we're using the Custom Item Pool
|
||||
guiargs.custom = bool(parent.pages["randomizer"].pages["generation"].widgets["usecustompool"].storageVar.get())
|
||||
guiargs.custom = bool(parent.pages["custom"].content.customWidgets["usecustompool"].storageVar.get())
|
||||
|
||||
# Get Seed ID
|
||||
guiargs.seed = None
|
||||
@@ -280,17 +287,4 @@ def create_guiargs(parent):
|
||||
|
||||
guiargs = update_deprecated_args(guiargs)
|
||||
|
||||
# Key drop shuffle stuff
|
||||
if guiargs.keydropshuffle:
|
||||
guiargs.dropshuffle = 1
|
||||
guiargs.pottery = 'keys' if guiargs.pottery == 'none' else guiargs.pottery
|
||||
|
||||
if guiargs.retro or guiargs.mode == 'retro':
|
||||
if guiargs.bow_mode == 'progressive':
|
||||
guiargs.bow_mode = 'retro'
|
||||
elif guiargs.bow_mode == 'silvers':
|
||||
guiargs.bow_mode = 'retro_silvers'
|
||||
guiargs.take_any = 'random' if guiargs.take_any == 'none' else guiargs.take_any
|
||||
guiargs.keyshuffle = 'universal'
|
||||
|
||||
return guiargs
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, Frame, N, E, W, LEFT, X, VERTICAL, Y
|
||||
from tkinter import ttk, Frame, N, E, W, LEFT, TOP, X, VERTICAL, Y
|
||||
import source.gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -11,10 +11,10 @@ def custom_page(top,parent):
|
||||
|
||||
# Create uniform list columns
|
||||
def create_list_frame(parent, framename):
|
||||
parent.frames[framename] = Frame(parent)
|
||||
parent.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
|
||||
parent.frames[framename].thisRow = 0
|
||||
parent.frames[framename].thisCol = 0
|
||||
self.frames[framename] = Frame(parent)
|
||||
self.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
|
||||
self.frames[framename].thisRow = 0
|
||||
self.frames[framename].thisCol = 0
|
||||
|
||||
# Create a vertical rule to help with splitting columns visually
|
||||
def create_vertical_rule(num=1):
|
||||
@@ -34,6 +34,8 @@ def custom_page(top,parent):
|
||||
|
||||
# Custom Item Pool option sections
|
||||
self.frames = {}
|
||||
self.frames["customHeader"] = Frame(self)
|
||||
self.frames["customHeader"].pack(side=TOP, anchor=W)
|
||||
# Create 5 columns with 2 vertical rules in between each
|
||||
create_list_frame(self, "itemList1")
|
||||
create_vertical_rule(2)
|
||||
@@ -50,9 +52,14 @@ def custom_page(top,parent):
|
||||
with open(os.path.join("resources", "app", "gui", "custom", "overview", "widgets.json")) as widgetDefns:
|
||||
myDict = json.load(widgetDefns)
|
||||
for framename,theseWidgets in myDict.items():
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
|
||||
for key in dictWidgets:
|
||||
self.customWidgets[key] = dictWidgets[key]
|
||||
if framename in self.frames:
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
|
||||
for key in dictWidgets:
|
||||
self.customWidgets[key] = dictWidgets[key]
|
||||
if framename == "customHeader":
|
||||
packAttrs = {"anchor":W}
|
||||
packAttrs = widgets.add_padding_from_config(packAttrs, theseWidgets[key])
|
||||
self.customWidgets[key].pack(packAttrs)
|
||||
|
||||
# Load Custom Item Pool settings from settings file
|
||||
for key in CONST.CUSTOMITEMS:
|
||||
|
||||
@@ -23,34 +23,44 @@ def loadcliargs(gui, args, settings=None):
|
||||
|
||||
# Cycle through each page
|
||||
for mainpage in options:
|
||||
subpage = None
|
||||
_, v = next(iter(options[mainpage].items()))
|
||||
if isinstance(v, str):
|
||||
subpage = ""
|
||||
# Cycle through each subpage (in case of Item Randomizer)
|
||||
for subpage in options[mainpage]:
|
||||
for subpage in (options[mainpage] if subpage is None else [subpage]):
|
||||
# Cycle through each widget
|
||||
for widget in options[mainpage][subpage]:
|
||||
if widget in gui.pages[mainpage].pages[subpage].widgets:
|
||||
for widget in (options[mainpage][subpage] if subpage != "" else options[mainpage]):
|
||||
page = gui.pages[mainpage].pages[subpage] if subpage != "" else gui.pages[mainpage]
|
||||
pagewidgets = page.content.customWidgets if mainpage == "custom" else page.content.startingWidgets if mainpage == "startinventory" else page.widgets
|
||||
if widget in pagewidgets:
|
||||
thisType = ""
|
||||
# Get the value and set it
|
||||
arg = options[mainpage][subpage][widget]
|
||||
arg = options[mainpage][subpage][widget] if subpage != "" else options[mainpage][widget]
|
||||
if args[arg] == None:
|
||||
args[arg] = ""
|
||||
label = fish.translate("gui","gui",mainpage + '.' + subpage + '.' + widget)
|
||||
if hasattr(gui.pages[mainpage].pages[subpage].widgets[widget],"type"):
|
||||
thisType = gui.pages[mainpage].pages[subpage].widgets[widget].type
|
||||
label_ref = mainpage + ('.' + subpage if subpage != "" else '') + '.' + widget
|
||||
label = fish.translate("gui","gui", label_ref)
|
||||
if hasattr(pagewidgets[widget],"type"):
|
||||
thisType = pagewidgets[widget].type
|
||||
if thisType == "checkbox":
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].checkbox.configure(text=label)
|
||||
pagewidgets[widget].checkbox.configure(text=label)
|
||||
elif thisType == "selectbox":
|
||||
theseOptions = gui.pages[mainpage].pages[subpage].widgets[widget].selectbox.options
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].label.configure(text=label)
|
||||
theseOptions = pagewidgets[widget].selectbox.options
|
||||
pagewidgets[widget].label.configure(text=label)
|
||||
i = 0
|
||||
for value in theseOptions["values"]:
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].selectbox.options["labels"][i] = fish.translate("gui","gui",mainpage + '.' + subpage + '.' + widget + '.' + str(value))
|
||||
pagewidgets[widget].selectbox.options["labels"][i] = fish.translate("gui","gui", label_ref + '.' + str(value))
|
||||
i += 1
|
||||
for i in range(0, len(theseOptions["values"])):
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].selectbox["menu"].entryconfigure(i, label=theseOptions["labels"][i])
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].selectbox.options = theseOptions
|
||||
pagewidgets[widget].selectbox["menu"].entryconfigure(i, label=theseOptions["labels"][i])
|
||||
pagewidgets[widget].selectbox.options = theseOptions
|
||||
elif thisType == "spinbox":
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].label.configure(text=label)
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].storageVar.set(args[arg])
|
||||
pagewidgets[widget].label.configure(text=label)
|
||||
elif thisType == 'button':
|
||||
pagewidgets[widget].button.configure(text=label)
|
||||
if hasattr(pagewidgets[widget], 'storageVar'):
|
||||
pagewidgets[widget].storageVar.set(args[arg])
|
||||
# If we're on the Game Options page and it's not about Hints
|
||||
if subpage == "gameoptions" and widget not in ["hints", "collection_rate"]:
|
||||
# Check if we've got settings
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, Frame, Label, E, W, LEFT, RIGHT
|
||||
from tkinter import ttk, Frame, Label, E, W, LEFT, RIGHT, TOP
|
||||
import source.gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -16,8 +16,8 @@ def dungeon_page(parent):
|
||||
self.frames["keysanity"].pack(anchor=W)
|
||||
|
||||
## Dungeon Item Shuffle
|
||||
mscbLabel = Label(self.frames["keysanity"], text="Shuffle: ")
|
||||
mscbLabel.pack(side=LEFT)
|
||||
mscbLabel = Label(self.frames["keysanity"], text="Dungeon Items: ")
|
||||
mscbLabel.pack(side=TOP, anchor=W)
|
||||
|
||||
# Load Dungeon Shuffle option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
@@ -28,7 +28,9 @@ def dungeon_page(parent):
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["keysanity"])
|
||||
for key in dictWidgets:
|
||||
self.widgets[key] = dictWidgets[key]
|
||||
self.widgets[key].pack(side=LEFT)
|
||||
packAttrs = {"side":LEFT}
|
||||
packAttrs = widgets.add_padding_from_config(packAttrs, myDict[key])
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
# These get split left & right
|
||||
self.frames["widgets"] = Frame(self)
|
||||
@@ -39,6 +41,8 @@ def dungeon_page(parent):
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["widgets"])
|
||||
for key in dictWidgets:
|
||||
self.widgets[key] = dictWidgets[key]
|
||||
self.widgets[key].pack(anchor=W)
|
||||
packAttrs = {"anchor":W}
|
||||
packAttrs = widgets.add_padding_from_config(packAttrs, myDict[key])
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
return self
|
||||
|
||||
@@ -26,9 +26,8 @@ def entrando_page(parent):
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
|
||||
for key in dictWidgets:
|
||||
self.widgets[key] = dictWidgets[key]
|
||||
packAttrs = {"anchor":E}
|
||||
if self.widgets[key].type == "checkbox" or key in ["openpyramid", "take_any"]:
|
||||
packAttrs["anchor"] = W
|
||||
packAttrs = {"anchor":W}
|
||||
packAttrs = widgets.add_padding_from_config(packAttrs, theseWidgets[key])
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
return self
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, Frame, E, W, LEFT, RIGHT, Label
|
||||
from tkinter import ttk, font, Frame, E, W, NW, TOP, LEFT, RIGHT, Y, Label
|
||||
import source.gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -17,13 +17,42 @@ def item_page(parent):
|
||||
self.frames["checkboxes"] = Frame(self)
|
||||
self.frames["checkboxes"].pack(anchor=W)
|
||||
|
||||
various_options = Label(self.frames["checkboxes"], text="")
|
||||
various_options = Label(self.frames["checkboxes"], text="Options: ")
|
||||
various_options.pack(side=LEFT)
|
||||
|
||||
self.frames["leftItemFrame"] = Frame(self)
|
||||
self.frames["rightItemFrame"] = Frame(self)
|
||||
self.frames["mainFrame"] = Frame(self)
|
||||
self.frames["mainFrame"].pack(side=TOP, pady=(20,0))
|
||||
|
||||
self.frames["poolFrame"] = Frame(self)
|
||||
self.frames["poolFrame"].pack(fill=Y)
|
||||
|
||||
self.frames["leftItemFrame"] = Frame(self.frames["mainFrame"])
|
||||
self.frames["leftItemFrame"].pack(side=LEFT)
|
||||
self.frames["rightItemFrame"] = Frame(self.frames["mainFrame"])
|
||||
self.frames["rightItemFrame"].pack(side=RIGHT)
|
||||
|
||||
self.frames["leftPoolContainer"] = Frame(self.frames["poolFrame"])
|
||||
self.frames["leftPoolContainer"].pack(side=LEFT, padx=(0,20))
|
||||
|
||||
base_font = font.nametofont('TkTextFont').actual()
|
||||
underline_font = f'"{base_font["family"]}" {base_font["size"]} underline'
|
||||
various_options = Label(self.frames["leftPoolContainer"], text="Pool Expansions", font=underline_font)
|
||||
various_options.pack(side=TOP, pady=(20,0))
|
||||
|
||||
self.frames["leftPoolHeader"] = Frame(self.frames["leftPoolContainer"])
|
||||
self.frames["leftPoolHeader"].pack(side=TOP, anchor=W)
|
||||
|
||||
self.frames["leftPoolFrame"] = Frame(self.frames["leftPoolContainer"])
|
||||
self.frames["leftPoolFrame"].pack(side=TOP, fill=Y)
|
||||
|
||||
self.frames["leftPoolFrame2"] = Frame(self.frames["leftPoolContainer"])
|
||||
self.frames["leftPoolFrame2"].pack(side=LEFT, fill=Y)
|
||||
|
||||
self.frames["rightPoolFrame"] = Frame(self.frames["poolFrame"])
|
||||
self.frames["rightPoolFrame"].pack(side=RIGHT)
|
||||
|
||||
various_options = Label(self.frames["rightPoolFrame"], text="Pool Modifications", font=underline_font)
|
||||
various_options.pack(side=TOP, pady=(20,0))
|
||||
|
||||
# Load Item Randomizer option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
@@ -36,8 +65,17 @@ def item_page(parent):
|
||||
for key in dictWidgets:
|
||||
self.widgets[key] = dictWidgets[key]
|
||||
packAttrs = {"anchor":E}
|
||||
if self.widgets[key].type == "checkbox":
|
||||
if key == "retro":
|
||||
packAttrs["side"] = RIGHT
|
||||
if self.widgets[key].type == "checkbox" or framename.startswith("leftPoolFrame"):
|
||||
packAttrs["anchor"] = W
|
||||
if framename == "checkboxes":
|
||||
packAttrs["side"] = LEFT
|
||||
packAttrs["padx"] = (10, 0)
|
||||
elif framename == "leftPoolHeader":
|
||||
packAttrs["side"] = LEFT
|
||||
packAttrs["padx"] = (0, 20)
|
||||
packAttrs = widgets.add_padding_from_config(packAttrs, theseWidgets[key])
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
return self
|
||||
|
||||
@@ -15,33 +15,24 @@ def overworld_page(parent):
|
||||
|
||||
# Load Overworld Shuffle option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
self.frames["topOverworldFrame"] = Frame(self)
|
||||
self.frames["leftOverworldFrame"] = Frame(self)
|
||||
self.frames["rightOverworldFrame"] = Frame(self)
|
||||
|
||||
self.frames["topOverworldFrame"].pack(side=TOP, anchor=NW)
|
||||
self.frames["leftOverworldFrame"].pack(side=LEFT, anchor=NW, fill=Y)
|
||||
self.frames["rightOverworldFrame"].pack(anchor=NW, fill=Y)
|
||||
|
||||
shuffleLabel = Label(self.frames["topOverworldFrame"], text="Shuffle: ")
|
||||
shuffleLabel.pack(side=LEFT)
|
||||
|
||||
with open(os.path.join("resources","app","gui","randomize","overworld","widgets.json")) as overworldWidgets:
|
||||
myDict = json.load(overworldWidgets)
|
||||
for framename,theseWidgets in myDict.items():
|
||||
if not theseWidgets:
|
||||
continue
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
|
||||
for key in dictWidgets:
|
||||
self.widgets[key] = dictWidgets[key]
|
||||
packAttrs = {"anchor":E}
|
||||
if key == "terrain":
|
||||
packAttrs = {"anchor":W, "pady":(3,0)}
|
||||
elif key == "keepsimilar":
|
||||
packAttrs = {"anchor":W, "pady":(6,0)}
|
||||
elif key == "overworldflute":
|
||||
packAttrs["pady"] = (20,0)
|
||||
elif key in ["mixed", "whirlpool"]:
|
||||
packAttrs = {"anchor":W, "padx":(79,0)}
|
||||
|
||||
packAttrs = {"anchor":W}
|
||||
if self.widgets[key].type != "checkbox":
|
||||
packAttrs["anchor"] = E
|
||||
packAttrs = widgets.add_padding_from_config(packAttrs, theseWidgets[key])
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
return self
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, Frame, N, E, W, LEFT, X, VERTICAL, Y
|
||||
from tkinter import ttk, Frame, N, E, W, LEFT, TOP, X, VERTICAL, Y
|
||||
import source.gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -11,10 +11,10 @@ def startinventory_page(top,parent):
|
||||
|
||||
# Create uniform list columns
|
||||
def create_list_frame(parent, framename):
|
||||
parent.frames[framename] = Frame(parent)
|
||||
parent.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
|
||||
parent.frames[framename].thisRow = 0
|
||||
parent.frames[framename].thisCol = 0
|
||||
self.frames[framename] = Frame(parent)
|
||||
self.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
|
||||
self.frames[framename].thisRow = 0
|
||||
self.frames[framename].thisCol = 0
|
||||
|
||||
# Create a vertical rule to help with splitting columns visually
|
||||
def create_vertical_rule(num=1):
|
||||
@@ -34,6 +34,8 @@ def startinventory_page(top,parent):
|
||||
|
||||
# Starting Inventory option sections
|
||||
self.frames = {}
|
||||
self.frames["startHeader"] = Frame(self)
|
||||
self.frames["startHeader"].pack(side=TOP, anchor=W)
|
||||
# Create 5 columns with 2 vertical rules in between each
|
||||
create_list_frame(self,"itemList1")
|
||||
create_vertical_rule(2)
|
||||
@@ -55,9 +57,14 @@ def startinventory_page(top,parent):
|
||||
if key in myDict[thisList]:
|
||||
del myDict[thisList][key]
|
||||
for framename,theseWidgets in myDict.items():
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
|
||||
for key in dictWidgets:
|
||||
self.startingWidgets[key] = dictWidgets[key]
|
||||
if framename in self.frames:
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
|
||||
for key in dictWidgets:
|
||||
self.startingWidgets[key] = dictWidgets[key]
|
||||
if framename == "startHeader":
|
||||
packAttrs = {"anchor":W}
|
||||
packAttrs = widgets.add_padding_from_config(packAttrs, theseWidgets[key])
|
||||
self.startingWidgets[key].pack(packAttrs)
|
||||
|
||||
# Load Custom Starting Inventory settings from settings file, ignoring ones to be excluded
|
||||
for key in CONST.CUSTOMITEMS:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from tkinter import Checkbutton, Entry, Frame, IntVar, Label, OptionMenu, Spinbox, StringVar, LEFT, RIGHT, X
|
||||
from tkinter import messagebox, Checkbutton, Entry, Frame, IntVar, Label, OptionMenu, Spinbox, StringVar, LEFT, RIGHT, X
|
||||
from tkinter import Button
|
||||
from source.classes.Empty import Empty
|
||||
|
||||
# Override Spinbox to include mousewheel support for changing value
|
||||
@@ -16,7 +17,7 @@ class mySpinbox(Spinbox):
|
||||
self.invoke('buttonup')
|
||||
|
||||
# Make a Checkbutton with a label
|
||||
def make_checkbox(self, parent, label, storageVar, manager, managerAttrs):
|
||||
def make_checkbox(self, parent, label, storageVar, manager, managerAttrs, config):
|
||||
self = Frame(parent)
|
||||
self.storageVar = storageVar
|
||||
if managerAttrs is not None and "default" in managerAttrs:
|
||||
@@ -25,7 +26,10 @@ def make_checkbox(self, parent, label, storageVar, manager, managerAttrs):
|
||||
elif managerAttrs["default"] == "false" or managerAttrs["default"] == False:
|
||||
self.storageVar.set(False)
|
||||
del managerAttrs["default"]
|
||||
self.checkbox = Checkbutton(self, text=label, variable=self.storageVar)
|
||||
options = {"text":label, "variable":self.storageVar}
|
||||
if config and "command" in config:
|
||||
options.update({"command":lambda m=config["command"]: widget_command(self, m)})
|
||||
self.checkbox = Checkbutton(self, options)
|
||||
if managerAttrs is not None:
|
||||
self.checkbox.pack(managerAttrs)
|
||||
else:
|
||||
@@ -43,7 +47,11 @@ def make_selectbox(self, parent, label, options, storageVar, manager, managerAtt
|
||||
|
||||
self.labelVar = StringVar()
|
||||
self.storageVar = storageVar
|
||||
self.selectbox = OptionMenu(self, self.labelVar, *labels)
|
||||
if config and "command" in config:
|
||||
self.command = config["command"]
|
||||
self.selectbox = OptionMenu(self, self.labelVar, *labels, command=lambda m: widget_command(self, self.command))
|
||||
else:
|
||||
self.selectbox = OptionMenu(self, self.labelVar, *labels)
|
||||
self.selectbox.options = {}
|
||||
|
||||
if isinstance(options,dict):
|
||||
@@ -96,7 +104,7 @@ def make_selectbox(self, parent, label, options, storageVar, manager, managerAtt
|
||||
else:
|
||||
self.label.pack(side=LEFT)
|
||||
|
||||
self.selectbox.config(width=config['width'] if config and config['width'] else 20)
|
||||
self.selectbox.config(width=config['width'] if config and 'width' in config else 20)
|
||||
idx = 0
|
||||
default = self.selectbox.options["values"][idx]
|
||||
if managerAttrs is not None and "default" in managerAttrs:
|
||||
@@ -165,6 +173,22 @@ def make_textbox(self, parent, label, storageVar, manager, managerAttrs):
|
||||
widget.textbox.pack(managerAttrs["textbox"] if managerAttrs is not None and "textbox" in managerAttrs else None)
|
||||
return widget
|
||||
|
||||
|
||||
def make_button(self, parent, label, manager, managerAttrs, config):
|
||||
self = Frame(parent)
|
||||
if config and "command" in config:
|
||||
self.command = config["command"]
|
||||
else:
|
||||
self.command = lambda: None
|
||||
|
||||
self.button = Button(parent, text=label, command=lambda: widget_command(self, self.command))
|
||||
if managerAttrs is not None:
|
||||
self.button.pack(managerAttrs)
|
||||
else:
|
||||
self.button.pack(anchor='w')
|
||||
return self
|
||||
|
||||
|
||||
# Make a generic widget
|
||||
def make_widget(self, type, parent, label, storageVar=None, manager=None, managerAttrs=dict(),
|
||||
options=None, config=None):
|
||||
@@ -181,7 +205,7 @@ def make_widget(self, type, parent, label, storageVar=None, manager=None, manage
|
||||
if type == "checkbox":
|
||||
if thisStorageVar is None:
|
||||
thisStorageVar = IntVar()
|
||||
widget = make_checkbox(self, parent, label, thisStorageVar, manager, managerAttrs)
|
||||
widget = make_checkbox(self, parent, label, thisStorageVar, manager, managerAttrs, config)
|
||||
elif type == "selectbox":
|
||||
if thisStorageVar is None:
|
||||
thisStorageVar = StringVar()
|
||||
@@ -194,6 +218,8 @@ def make_widget(self, type, parent, label, storageVar=None, manager=None, manage
|
||||
if thisStorageVar is None:
|
||||
thisStorageVar = StringVar()
|
||||
widget = make_textbox(self, parent, label, thisStorageVar, manager, managerAttrs)
|
||||
elif type == 'button':
|
||||
widget = make_button(self, parent, label, manager, managerAttrs, config)
|
||||
widget.type = type
|
||||
return widget
|
||||
|
||||
@@ -221,3 +247,50 @@ def make_widgets_from_dict(self, defns, parent):
|
||||
for key,defn in defns.items():
|
||||
widgets[key] = make_widget_from_dict(self, defn, parent)
|
||||
return widgets
|
||||
|
||||
# Add padding to widget
|
||||
def add_padding_from_config(packAttrs, defn):
|
||||
if "config" in defn:
|
||||
config = defn["config"]
|
||||
if 'padx' in config:
|
||||
packAttrs["padx"] = config['padx']
|
||||
if 'pady' in config:
|
||||
packAttrs["pady"] = config['pady']
|
||||
return packAttrs
|
||||
|
||||
# Callback when a widget issues a command
|
||||
def widget_command(widget, command=""):
|
||||
root = widget.winfo_toplevel()
|
||||
text_output = ""
|
||||
if command == "retro":
|
||||
temp_widget = root.pages["randomizer"].pages["dungeon"].widgets["smallkeyshuffle"]
|
||||
text_output += f'\n {temp_widget.label.cget("text")}'
|
||||
temp_widget.storageVar.set('universal')
|
||||
|
||||
temp_widget = root.pages["randomizer"].pages["item"].widgets["bow_mode"]
|
||||
text_output += f'\n {temp_widget.label.cget("text")}'
|
||||
if temp_widget.storageVar.get() == 'progressive':
|
||||
temp_widget.storageVar.set('retro')
|
||||
elif temp_widget.storageVar.get() == 'silvers':
|
||||
temp_widget.storageVar.set('retro_silvers')
|
||||
|
||||
temp_widget = root.pages["randomizer"].pages["item"].widgets["take_any"]
|
||||
text_output += f'\n {temp_widget.label.cget("text")}'
|
||||
if temp_widget.storageVar.get() == 'none':
|
||||
temp_widget.storageVar.set('random')
|
||||
|
||||
messagebox.showinfo('', f'The following settings were changed:{text_output}')
|
||||
elif command == "keydropshuffle":
|
||||
temp_widget = root.pages["randomizer"].pages["item"].widgets["pottery"]
|
||||
text_output += f'\n {temp_widget.label.cget("text")}'
|
||||
if temp_widget.storageVar.get() == 'none':
|
||||
temp_widget.storageVar.set('keys')
|
||||
|
||||
temp_widget = root.pages["randomizer"].pages["item"].widgets["dropshuffle"]
|
||||
text_output += f'\n {temp_widget.checkbox.cget("text")}'
|
||||
if temp_widget.storageVar.get() == 0:
|
||||
temp_widget.storageVar.set(1)
|
||||
|
||||
if text_output:
|
||||
messagebox.showinfo('', f'The following settings were changed:{text_output}')
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ def resolve_districts(world):
|
||||
if not location.item and location.real:
|
||||
district.locations.add(location.name)
|
||||
for ext in region.exits:
|
||||
if ext.connected_region is not None and ext.connected_region not in visited:
|
||||
if ext.connected_region and ext.connected_region not in visited:
|
||||
queue.appendleft(ext.connected_region)
|
||||
elif region.type == RegionType.Dungeon and region.dungeon:
|
||||
district.dungeons.add(region.dungeon.name)
|
||||
@@ -138,10 +138,10 @@ def find_reachable_locations(state, player):
|
||||
return check_set
|
||||
|
||||
|
||||
inaccessible_regions_std = {'Desert Palace Stairs', 'Bumper Cave Ledge', 'Skull Woods Forest (West)',
|
||||
inaccessible_regions_std = {'Desert Mouth', 'Bumper Cave Ledge', 'Skull Woods Forest (West)',
|
||||
'Dark Death Mountain Ledge', 'Dark Death Mountain Isolated Ledge',
|
||||
'Dark Death Mountain Floating Island'}
|
||||
'Death Mountain Floating Island'}
|
||||
|
||||
|
||||
inaccessible_regions_inv = {'Desert Palace Stairs', 'Maze Race Ledge', 'Desert Ledge',
|
||||
'Desert Palace Entrance (North) Spot', 'Hyrule Castle Ledge', 'Mountain Entry Ledge'}
|
||||
inaccessible_regions_inv = {'Desert Mouth', 'Maze Race Ledge', 'Desert Ledge',
|
||||
'Desert Ledge Keep', 'Hyrule Castle Ledge', 'Mountain Pass Ledge'}
|
||||
|
||||
@@ -3,7 +3,7 @@ import logging
|
||||
from collections import defaultdict
|
||||
|
||||
from source.item.District import resolve_districts
|
||||
from BaseClasses import PotItem, PotFlags
|
||||
from BaseClasses import PotItem, PotFlags, LocationType
|
||||
from DoorShuffle import validate_vanilla_reservation
|
||||
from Dungeons import dungeon_table
|
||||
from Items import item_table, ItemFactory
|
||||
@@ -82,8 +82,8 @@ def create_item_pool_config(world):
|
||||
if pot.item not in [PotItem.Key, PotItem.Hole, PotItem.Switch]:
|
||||
item = pot_items[pot.item]
|
||||
descriptor = 'Large Block' if pot.flags & PotFlags.Block else f'Pot #{pot_index+1}'
|
||||
location = f'{pot.room} {descriptor}'
|
||||
config.static_placement[player][item].append(location)
|
||||
loc = f'{pot.room} {descriptor}'
|
||||
config.static_placement[player][item].append(loc)
|
||||
if world.shopsanity[player]:
|
||||
for item, locs in shop_vanilla_mapping.items():
|
||||
config.static_placement[player][item].extend(locs)
|
||||
@@ -151,9 +151,6 @@ def create_item_pool_config(world):
|
||||
config.item_pool[player] = determine_major_items(world, player)
|
||||
config.location_groups[0].locations = set(groups.locations)
|
||||
config.reserved_locations[player].update(groups.locations)
|
||||
backup = (mode_grouping['Heart Pieces'] + mode_grouping['Dungeon Trash'] + mode_grouping['Shops']
|
||||
+ mode_grouping['Overworld Trash'] + mode_grouping['GT Trash'] + mode_grouping['RetroShops'])
|
||||
config.location_groups[1].locations = set(backup)
|
||||
elif world.algorithm == 'dungeon_only':
|
||||
config.location_groups = [
|
||||
LocationGroup('Dungeons'),
|
||||
@@ -164,12 +161,13 @@ def create_item_pool_config(world):
|
||||
mode_grouping['Heart Containers'] + mode_grouping['GT Trash'] + mode_grouping['Small Keys'] +
|
||||
mode_grouping['Compasses'] + mode_grouping['Maps'] + mode_grouping['Key Drops'] +
|
||||
mode_grouping['Pot Keys'] + mode_grouping['Big Key Drops'])
|
||||
dungeon_set = set(dungeon_set)
|
||||
for loc in world.get_locations():
|
||||
if loc.parent_region.dungeon and loc.type in [LocationType.Pot, LocationType.Drop]:
|
||||
dungeon_set.add(loc.name)
|
||||
for player in range(1, world.players + 1):
|
||||
config.item_pool[player] = determine_major_items(world, player)
|
||||
config.location_groups[0].locations = set(dungeon_set)
|
||||
backup = (mode_grouping['Heart Pieces'] + mode_grouping['Overworld Major']
|
||||
+ mode_grouping['Overworld Trash'] + mode_grouping['Shops'] + mode_grouping['RetroShops'])
|
||||
config.location_groups[1].locations = set(backup)
|
||||
|
||||
|
||||
def district_item_pool_config(world):
|
||||
@@ -217,7 +215,7 @@ def district_item_pool_config(world):
|
||||
scale_factors = defaultdict(int)
|
||||
scale_total = 0
|
||||
for p in range(1, world.players + 1):
|
||||
ent = 'Agahnims Tower' if world.is_atgt_swapped(player) else 'Ganons Tower'
|
||||
ent = 'Agahnims Tower' if world.is_atgt_swapped(p) else 'Ganons Tower'
|
||||
dungeon = world.get_entrance(ent, p).connected_region.dungeon
|
||||
if dungeon:
|
||||
scale = world.crystals_needed_for_gt[p]
|
||||
@@ -359,7 +357,7 @@ def determine_major_items(world, player):
|
||||
major_item_set.add('Single Arrow')
|
||||
if world.keyshuffle[player] == 'universal':
|
||||
major_item_set.add('Small Key (Universal)')
|
||||
if world.goal in ['triforcehunt', 'trinity']:
|
||||
if world.goal[player] in ['triforcehunt', 'trinity', 'ganonhunt']:
|
||||
major_item_set.add('Triforce Piece')
|
||||
if world.bombbag[player]:
|
||||
major_item_set.add('Bomb Upgrade (+10)')
|
||||
@@ -415,14 +413,11 @@ def filter_locations(item_to_place, locations, world, vanilla_skip=False, potion
|
||||
if item_to_place.name in config.item_pool[item_to_place.player]:
|
||||
restricted = config.location_groups[0].locations
|
||||
filtered = [l for l in locations if l.name in restricted]
|
||||
if len(filtered) == 0:
|
||||
restricted = config.location_groups[1].locations
|
||||
filtered = [l for l in locations if l.name in restricted]
|
||||
# bias toward certain location in overflow? (thinking about this for major_bias)
|
||||
return filtered if len(filtered) > 0 else locations
|
||||
return filtered
|
||||
if world.algorithm == 'district':
|
||||
config = world.item_pool_config
|
||||
if item_to_place == 'Placeholder' or item_to_place.name in config.item_pool[item_to_place.player]:
|
||||
if ((isinstance(item_to_place,str) and item_to_place == 'Placeholder')
|
||||
or item_to_place.name in config.item_pool[item_to_place.player]):
|
||||
restricted = config.location_groups[0].locations
|
||||
filtered = [l for l in locations if l.name in restricted and l.player in restricted[l.name]]
|
||||
return filtered if len(filtered) > 0 else locations
|
||||
@@ -816,7 +811,7 @@ trash_items = {
|
||||
'Nothing': -1,
|
||||
'Bee Trap': 0,
|
||||
'Rupee (1)': 1, 'Rupees (5)': 1, 'Small Heart': 1, 'Bee': 1, 'Arrows (5)': 1, 'Chicken': 1, 'Single Bomb': 1,
|
||||
'Rupees (20)': 2, 'Small Magic': 2,
|
||||
'Rupees (20)': 2, 'Small Magic': 2, 'Good Bee': 2,
|
||||
'Bombs (3)': 3, 'Arrows (10)': 3, 'Bombs (10)': 3, 'Apples': 3,
|
||||
'Fairy': 4, 'Big Magic': 4, 'Red Potion': 4, 'Blue Shield': 4, 'Rupees (50)': 4, 'Rupees (100)': 4,
|
||||
'Rupees (300)': 5,
|
||||
@@ -830,9 +825,10 @@ pot_items = {
|
||||
PotItem.OneRupee: 'Rupee (1)',
|
||||
PotItem.FiveRupees: 'Rupees (5)',
|
||||
PotItem.Heart: 'Small Heart',
|
||||
PotItem.BigMagic: 'Big Magic', # fast fill
|
||||
PotItem.BigMagic: 'Big Magic',
|
||||
PotItem.SmallMagic: 'Small Magic',
|
||||
PotItem.Chicken: 'Chicken' # fast fill
|
||||
PotItem.Chicken: 'Chicken',
|
||||
PotItem.Fairy: 'Fairy'
|
||||
}
|
||||
|
||||
valid_pot_items = {y: x for x, y in pot_items.items()}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -98,6 +98,7 @@ def roll_settings(weights):
|
||||
ret.trap_door_mode = get_choice('trap_door_mode')
|
||||
ret.key_logic_algorithm = get_choice('key_logic_algorithm')
|
||||
ret.decoupledoors = get_choice('decoupledoors') == 'on'
|
||||
ret.door_self_loops = get_choice('door_self_loops') == 'on'
|
||||
ret.experimental = get_choice('experimental') == 'on'
|
||||
ret.collection_rate = get_choice('collection_rate') == 'on'
|
||||
|
||||
@@ -111,7 +112,7 @@ def roll_settings(weights):
|
||||
ret.dropshuffle = get_choice('dropshuffle') == 'on' or keydropshuffle
|
||||
ret.pottery = get_choice('pottery') if 'pottery' in weights else 'none'
|
||||
ret.pottery = 'keys' if ret.pottery == 'none' and keydropshuffle else ret.pottery
|
||||
ret.colorizepots = get_choice('colorizepots') == 'on'
|
||||
ret.colorizepots = get_choice_default('colorizepots', default='on') == 'on'
|
||||
ret.shufflepots = get_choice('pot_shuffle') == 'on'
|
||||
ret.mixed_travel = get_choice('mixed_travel') if 'mixed_travel' in weights else 'prevent'
|
||||
ret.standardize_palettes = (get_choice('standardize_palettes') if 'standardize_palettes' in weights
|
||||
@@ -142,15 +143,14 @@ def roll_settings(weights):
|
||||
ganon_item = get_choice('ganon_item')
|
||||
ret.ganon_item = ganon_item if ganon_item != 'none' else 'default'
|
||||
|
||||
from ItemList import set_default_triforce
|
||||
default_tf_goal, default_tf_pool = set_default_triforce(ret.goal, 0, 0)
|
||||
goal_min = get_choice_default('triforce_goal_min', default=default_tf_goal)
|
||||
goal_max = get_choice_default('triforce_goal_max', default=default_tf_goal)
|
||||
pool_min = get_choice_default('triforce_pool_min', default=default_tf_pool)
|
||||
pool_max = get_choice_default('triforce_pool_max', default=default_tf_pool)
|
||||
ret.triforce_goal = random.randint(int(goal_min), int(goal_max))
|
||||
min_diff = get_choice_default('triforce_min_difference', default=(default_tf_pool-default_tf_goal))
|
||||
ret.triforce_pool = random.randint(max(int(pool_min), ret.triforce_goal + int(min_diff)), int(pool_max))
|
||||
ret.triforce_pool = get_choice_default('triforce_pool', default=0)
|
||||
ret.triforce_goal = get_choice_default('triforce_goal', default=0)
|
||||
ret.triforce_pool_min = get_choice_default('triforce_pool_min', default=0)
|
||||
ret.triforce_pool_max = get_choice_default('triforce_pool_max', default=0)
|
||||
ret.triforce_goal_min = get_choice_default('triforce_goal_min', default=0)
|
||||
ret.triforce_goal_max = get_choice_default('triforce_goal_max', default=0)
|
||||
ret.triforce_min_difference = get_choice_default('triforce_min_difference', default=0)
|
||||
ret.triforce_max_difference = get_choice_default('triforce_max_difference', default=10000)
|
||||
|
||||
ret.mode = get_choice('world_state')
|
||||
if ret.mode == 'retro':
|
||||
|
||||
Reference in New Issue
Block a user