Merge remote-tracking branch 'origin/DoorDev' into DoorDev
This commit is contained in:
@@ -41,7 +41,7 @@ class World(object):
|
|||||||
self.shuffle_bonk_prizes = False
|
self.shuffle_bonk_prizes = False
|
||||||
self.light_world_light_cone = False
|
self.light_world_light_cone = False
|
||||||
self.dark_world_light_cone = False
|
self.dark_world_light_cone = False
|
||||||
self.clock_mode = 'off'
|
self.clock_mode = 'none'
|
||||||
self.rupoor_cost = 10
|
self.rupoor_cost = 10
|
||||||
self.aga_randomness = True
|
self.aga_randomness = True
|
||||||
self.lock_aga_door_in_escape = False
|
self.lock_aga_door_in_escape = False
|
||||||
|
|||||||
4
CLI.py
4
CLI.py
@@ -188,7 +188,7 @@ def parse_arguments(argv, no_defaults=False):
|
|||||||
base game.
|
base game.
|
||||||
''')
|
''')
|
||||||
parser.add_argument('--experimental', default=defval(settings["experimental"] != 0), help='Enable experimental features', action='store_true')
|
parser.add_argument('--experimental', default=defval(settings["experimental"] != 0), help='Enable experimental features', action='store_true')
|
||||||
parser.add_argument('--dungeon_counters', default=defval(settings["dungeon_counters"]), help='Enable dungeon chest counters', const='off', nargs='?', choices=['off', 'on', 'pickup'])
|
parser.add_argument('--dungeon_counters', default=defval(settings["dungeon_counters"]), help='Enable dungeon chest counters', const='off', nargs='?', choices=['off', 'on', 'pickup', 'default'])
|
||||||
parser.add_argument('--crystals_ganon', default=defval(settings["crystals_ganon"]), const='7', nargs='?', choices=['random', '0', '1', '2', '3', '4', '5', '6', '7'],
|
parser.add_argument('--crystals_ganon', default=defval(settings["crystals_ganon"]), const='7', nargs='?', choices=['random', '0', '1', '2', '3', '4', '5', '6', '7'],
|
||||||
help='''\
|
help='''\
|
||||||
How many crystals are needed to defeat ganon. Any other
|
How many crystals are needed to defeat ganon. Any other
|
||||||
@@ -358,7 +358,7 @@ def get_settings():
|
|||||||
"keysanity": False,
|
"keysanity": False,
|
||||||
"door_shuffle": "basic",
|
"door_shuffle": "basic",
|
||||||
"experimental": 0,
|
"experimental": 0,
|
||||||
"dungeon_counters": "off",
|
"dungeon_counters": "default",
|
||||||
|
|
||||||
"multi": 1,
|
"multi": 1,
|
||||||
"names": "",
|
"names": "",
|
||||||
|
|||||||
@@ -202,8 +202,7 @@ def connect_simple_door(world, exit_name, region_name, player):
|
|||||||
d.dest = region
|
d.dest = region
|
||||||
|
|
||||||
|
|
||||||
def connect_door_only(world, exit_name, region_name, player):
|
def connect_door_only(world, exit_name, region, player):
|
||||||
region = world.get_region(region_name, player)
|
|
||||||
d = world.check_for_door(exit_name, player)
|
d = world.check_for_door(exit_name, player)
|
||||||
if d is not None:
|
if d is not None:
|
||||||
d.dest = region
|
d.dest = region
|
||||||
@@ -1357,8 +1356,8 @@ def add_inaccessible_doors(world, player):
|
|||||||
# todo: ignore standard mode hyrule castle ledge?
|
# todo: ignore standard mode hyrule castle ledge?
|
||||||
for inaccessible_region in world.inaccessible_regions[player]:
|
for inaccessible_region in world.inaccessible_regions[player]:
|
||||||
region = world.get_region(inaccessible_region, player)
|
region = world.get_region(inaccessible_region, player)
|
||||||
for exit in region.exits:
|
for ext in region.exits:
|
||||||
create_door(world, player, exit.name, region.name)
|
create_door(world, player, ext.name, region.name)
|
||||||
|
|
||||||
|
|
||||||
def create_door(world, player, entName, region_name):
|
def create_door(world, player, entName, region_name):
|
||||||
@@ -1464,6 +1463,7 @@ def check_for_pinball_fix(state, bad_region, world, player):
|
|||||||
|
|
||||||
@unique
|
@unique
|
||||||
class DROptions(Flag):
|
class DROptions(Flag):
|
||||||
|
NoOptions = 0x00
|
||||||
Eternal_Mini_Bosses = 0x01 # If on, GT minibosses marked as defeated when they try to spawn a heart
|
Eternal_Mini_Bosses = 0x01 # If on, GT minibosses marked as defeated when they try to spawn a heart
|
||||||
Town_Portal = 0x02 # If on, Players will start with mirror scroll
|
Town_Portal = 0x02 # If on, Players will start with mirror scroll
|
||||||
Open_Desert_Wall = 0x80 # If on, pre opens the desert wall, no fire required
|
Open_Desert_Wall = 0x80 # If on, pre opens the desert wall, no fire required
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ def get_custom_array_key(item):
|
|||||||
key = label_switcher.get(key)
|
key = label_switcher.get(key)
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
|
||||||
def generate_itempool(world, player):
|
def generate_itempool(world, player):
|
||||||
if (world.difficulty[player] not in ['normal', 'hard', 'expert'] or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals']
|
if (world.difficulty[player] not in ['normal', 'hard', 'expert'] or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals']
|
||||||
or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']):
|
or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']):
|
||||||
@@ -194,7 +195,7 @@ def generate_itempool(world, player):
|
|||||||
region = world.get_region('Light World',player)
|
region = world.get_region('Light World',player)
|
||||||
|
|
||||||
loc = Location(player, "Murahdahla", parent=region)
|
loc = Location(player, "Murahdahla", parent=region)
|
||||||
loc.access_rule = lambda state: state.item_count(get_custom_array_key('Triforce Piece'), player) + state.item_count(get_custom_array_key('Power Star'), player) > state.world.treasure_hunt_count[player]
|
loc.access_rule = lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) > state.world.treasure_hunt_count[player]
|
||||||
region.locations.append(loc)
|
region.locations.append(loc)
|
||||||
world.dynamic_locations.append(loc)
|
world.dynamic_locations.append(loc)
|
||||||
|
|
||||||
@@ -253,7 +254,6 @@ def generate_itempool(world, player):
|
|||||||
world.get_location('Zelda Drop Off', player).event = True
|
world.get_location('Zelda Drop Off', player).event = True
|
||||||
world.get_location('Zelda Drop Off', player).locked = True
|
world.get_location('Zelda Drop Off', player).locked = True
|
||||||
|
|
||||||
|
|
||||||
# set up item pool
|
# set up item pool
|
||||||
if world.custom:
|
if world.custom:
|
||||||
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.customitemarray)
|
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.customitemarray)
|
||||||
@@ -265,10 +265,10 @@ def generate_itempool(world, player):
|
|||||||
amt = world.pool_adjustment[player]
|
amt = world.pool_adjustment[player]
|
||||||
if amt < 0:
|
if amt < 0:
|
||||||
for i in range(0, amt):
|
for i in range(0, amt):
|
||||||
pool.remove(get_custom_array_key('Rupees (20)'))
|
pool.remove('Rupees (20)')
|
||||||
elif amt > 0:
|
elif amt > 0:
|
||||||
for i in range(0, amt):
|
for i in range(0, amt):
|
||||||
pool.append(get_custom_array_key('Rupees (20)'))
|
pool.append('Rupees (20)')
|
||||||
|
|
||||||
for item in precollected_items:
|
for item in precollected_items:
|
||||||
world.push_precollected(ItemFactory(item, player))
|
world.push_precollected(ItemFactory(item, player))
|
||||||
@@ -407,6 +407,7 @@ def set_up_take_anys(world, player):
|
|||||||
|
|
||||||
world.initialize_regions()
|
world.initialize_regions()
|
||||||
|
|
||||||
|
|
||||||
def create_dynamic_shop_locations(world, player):
|
def create_dynamic_shop_locations(world, player):
|
||||||
for shop in world.shops:
|
for shop in world.shops:
|
||||||
if shop.region.player == player:
|
if shop.region.player == player:
|
||||||
|
|||||||
@@ -705,7 +705,7 @@ def unique_doors(doors):
|
|||||||
def count_unique_sm_doors(doors):
|
def count_unique_sm_doors(doors):
|
||||||
unique_d_set = set()
|
unique_d_set = set()
|
||||||
for d in doors:
|
for d in doors:
|
||||||
if d not in unique_d_set and d.dest not in unique_d_set and not d.bigKey:
|
if d not in unique_d_set and (d.dest not in unique_d_set or d.type == DoorType.SpiralStairs) and not d.bigKey:
|
||||||
unique_d_set.add(d)
|
unique_d_set.add(d)
|
||||||
return len(unique_d_set)
|
return len(unique_d_set)
|
||||||
|
|
||||||
@@ -718,6 +718,7 @@ def count_unique_small_doors(key_counter, proposal):
|
|||||||
if door in proposal and door not in counted:
|
if door in proposal and door not in counted:
|
||||||
cnt += 1
|
cnt += 1
|
||||||
counted.add(door)
|
counted.add(door)
|
||||||
|
if door.type != DoorType.SpiralStairs:
|
||||||
counted.add(door.dest)
|
counted.add(door.dest)
|
||||||
return cnt
|
return cnt
|
||||||
|
|
||||||
@@ -1069,15 +1070,6 @@ def invalid_self_locking_key(state, prev_state, prev_avail, world, player):
|
|||||||
return prev_avail - 1 == 0
|
return prev_avail - 1 == 0
|
||||||
|
|
||||||
|
|
||||||
# does not allow dest doors
|
|
||||||
def count_unique_sm_doors(doors):
|
|
||||||
unique_d_set = set()
|
|
||||||
for d in doors:
|
|
||||||
if d not in unique_d_set and d.dest not in unique_d_set and not d.bigKey:
|
|
||||||
unique_d_set.add(d)
|
|
||||||
return len(unique_d_set)
|
|
||||||
|
|
||||||
|
|
||||||
def enough_small_locations(state, avail_small_loc):
|
def enough_small_locations(state, avail_small_loc):
|
||||||
unique_d_set = set()
|
unique_d_set = set()
|
||||||
for exp_door in state.small_doors:
|
for exp_door in state.small_doors:
|
||||||
|
|||||||
2
Main.py
2
Main.py
@@ -24,7 +24,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute
|
|||||||
from ItemList import generate_itempool, difficulties, fill_prizes
|
from ItemList import generate_itempool, difficulties, fill_prizes
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
|
|
||||||
__version__ = '0.0.18dev'
|
__version__ = '0.0.18.3d'
|
||||||
|
|
||||||
|
|
||||||
def main(args, seed=None):
|
def main(args, seed=None):
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ def roll_settings(weights):
|
|||||||
ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla'
|
ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla'
|
||||||
door_shuffle = get_choice('door_shuffle')
|
door_shuffle = get_choice('door_shuffle')
|
||||||
ret.door_shuffle = door_shuffle if door_shuffle != 'none' else 'vanilla'
|
ret.door_shuffle = door_shuffle if door_shuffle != 'none' else 'vanilla'
|
||||||
|
ret.experimental = get_choice('experimental') == 'on'
|
||||||
|
|
||||||
goal = get_choice('goals')
|
goal = get_choice('goals')
|
||||||
ret.goal = {'ganon': 'ganon',
|
ret.goal = {'ganon': 'ganon',
|
||||||
@@ -156,7 +157,7 @@ def roll_settings(weights):
|
|||||||
'pedestal': 'pedestal',
|
'pedestal': 'pedestal',
|
||||||
'triforce-hunt': 'triforcehunt'
|
'triforce-hunt': 'triforcehunt'
|
||||||
}[goal]
|
}[goal]
|
||||||
ret.openpyramid = goal == 'fast_ganon'
|
ret.openpyramid = goal == 'fast_ganon' if ret.shuffle in ['vanilla', 'dungeonsfull', 'dungeonssimple'] else False
|
||||||
|
|
||||||
ret.crystals_gt = get_choice('tower_open')
|
ret.crystals_gt = get_choice('tower_open')
|
||||||
|
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ Doors are shuffled between dungeons as well.
|
|||||||
|
|
||||||
Doors are not shuffled.
|
Doors are not shuffled.
|
||||||
|
|
||||||
### Experimental
|
|
||||||
|
|
||||||
Used for development testing. This will be removed in a future version. Use at your own risk. Might play like a plando.
|
|
||||||
|
|
||||||
## Map/Compass/Small Key/Big Key shuffle (aka Keysanity)
|
## Map/Compass/Small Key/Big Key shuffle (aka Keysanity)
|
||||||
|
|
||||||
These settings allow dungeon specific items to be distributed anywhere in the world and not just in their native dungeon.
|
These settings allow dungeon specific items to be distributed anywhere in the world and not just in their native dungeon.
|
||||||
|
|||||||
6
Rom.py
6
Rom.py
@@ -591,7 +591,7 @@ def patch_rom(world, rom, player, team, enemized):
|
|||||||
patch_shuffled_dark_sanc(world, rom, player)
|
patch_shuffled_dark_sanc(world, rom, player)
|
||||||
|
|
||||||
# patch doors
|
# patch doors
|
||||||
dr_flags = DROptions.Eternal_Mini_Bosses if not world.experimental[player] else DROptions.Town_Portal
|
dr_flags = DROptions.Eternal_Mini_Bosses if world.doorShuffle[player] == 'vanilla' or not world.experimental[player] else DROptions.Town_Portal
|
||||||
if world.doorShuffle[player] == 'crossed':
|
if world.doorShuffle[player] == 'crossed':
|
||||||
rom.write_byte(0x139004, 2)
|
rom.write_byte(0x139004, 2)
|
||||||
rom.write_byte(0x151f1, 2)
|
rom.write_byte(0x151f1, 2)
|
||||||
@@ -899,7 +899,7 @@ def patch_rom(world, rom, player, team, enemized):
|
|||||||
ERtimeincrease = 20
|
ERtimeincrease = 20
|
||||||
if world.keyshuffle[player] or world.bigkeyshuffle[player] or world.mapshuffle[player]:
|
if world.keyshuffle[player] or world.bigkeyshuffle[player] or world.mapshuffle[player]:
|
||||||
ERtimeincrease = ERtimeincrease + 15
|
ERtimeincrease = ERtimeincrease + 15
|
||||||
if world.clock_mode == 'off':
|
if world.clock_mode == 'none':
|
||||||
rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode
|
rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode
|
||||||
write_int32(rom, 0x180200, 0) # red clock adjustment time (in frames, sint32)
|
write_int32(rom, 0x180200, 0) # red clock adjustment time (in frames, sint32)
|
||||||
write_int32(rom, 0x180204, 0) # blue clock adjustment time (in frames, sint32)
|
write_int32(rom, 0x180204, 0) # blue clock adjustment time (in frames, sint32)
|
||||||
@@ -1157,7 +1157,7 @@ def patch_rom(world, rom, player, team, enemized):
|
|||||||
rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] else 0x00) # maps showing crystals on overworld
|
rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] else 0x00) # maps showing crystals on overworld
|
||||||
|
|
||||||
# compasses showing dungeon count
|
# compasses showing dungeon count
|
||||||
if world.clock_mode != 'off' or world.dungeon_counters[player] == 'off':
|
if world.clock_mode != 'none' or world.dungeon_counters[player] == 'off':
|
||||||
rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location
|
rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location
|
||||||
elif world.dungeon_counters[player] == 'on':
|
elif world.dungeon_counters[player] == 'on':
|
||||||
rom.write_byte(0x18003C, 0x02) # always on
|
rom.write_byte(0x18003C, 0x02) # always on
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
from tkinter import ttk, StringVar, Entry, Frame, Label, N, E, W, LEFT, RIGHT, X, VERTICAL, Y
|
from tkinter import ttk, Frame, N, LEFT, VERTICAL, Y
|
||||||
import gui.widgets as widgets
|
import gui.widgets as widgets
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import classes.constants as CONST
|
import classes.constants as CONST
|
||||||
|
|
||||||
|
|
||||||
def custom_page(top, parent):
|
def custom_page(top, parent):
|
||||||
# Custom Item Pool
|
# Custom Item Pool
|
||||||
self = ttk.Frame(parent)
|
self = ttk.Frame(parent)
|
||||||
|
|||||||
@@ -37,9 +37,10 @@
|
|||||||
"selectbox": {
|
"selectbox": {
|
||||||
"side": "right"
|
"side": "right"
|
||||||
},
|
},
|
||||||
"default": "Off"
|
"default": "Auto"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
"Auto": "default",
|
||||||
"Off": "off",
|
"Off": "off",
|
||||||
"On": "on",
|
"On": "on",
|
||||||
"On Compass Pickup": "pickup"
|
"On Compass Pickup": "pickup"
|
||||||
|
|||||||
Reference in New Issue
Block a user