diff --git a/BaseClasses.py b/BaseClasses.py index 9e0f3a55..d54a2fd1 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -129,6 +129,7 @@ class World(object): set_player_attr('keydropshuffle', False) set_player_attr('mixed_travel', 'prevent') + set_player_attr('standardize_palettes', 'standardize') set_player_attr('force_fix', {'gt': False, 'sw': False, 'pod': False, 'tr': False}); def get_name_string_for_object(self, obj): @@ -148,6 +149,11 @@ class World(object): for door in doors: self._door_cache[(door.name, door.player)] = door + def remove_door(self, door, player): + if (door, player) in self._door_cache.keys(): + del self._door_cache[(door, player)] + self.doors.remove(door) + def get_regions(self, player=None): return self.regions if player is None else self._region_cache[player].values() @@ -176,6 +182,10 @@ class World(object): return exit raise RuntimeError('No such entrance %s for player %d' % (entrance, player)) + def remove_entrance(self, entrance, player): + if (entrance, player) in self._entrance_cache.keys(): + del self._entrance_cache[(entrance, player)] + def get_location(self, location, player): if isinstance(location, Location): return location @@ -862,6 +872,7 @@ class CollectionState(object): @unique class RegionType(Enum): + Menu = 0 LightWorld = 1 DarkWorld = 2 Cave = 3 # Also includes Houses diff --git a/CLI.py b/CLI.py index 5634c14b..087bc739 100644 --- a/CLI.py +++ b/CLI.py @@ -95,7 +95,7 @@ def parse_cli(argv, no_defaults=False): 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep', - 'remote_items', 'keydropshuffle', 'mixed_travel']: + 'remote_items', 'keydropshuffle', 'mixed_travel', 'standardize_palettes']: value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) if player == 1: setattr(ret, name, {1: value}) @@ -146,6 +146,7 @@ def parse_settings(): "experimental": False, "dungeon_counters": "default", "mixed_travel": "prevent", + "standardize_palettes": "standardize", "multi": 1, "names": "", diff --git a/DoorShuffle.py b/DoorShuffle.py index f9372c5c..bffd7dc7 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -40,7 +40,15 @@ def link_doors(world, player): connect_two_way(world, entrance, ext, player) for entrance, ext in straight_staircases: connect_two_way(world, entrance, ext, player) - + + if world.intensity[player] < 3 or world.doorShuffle == 'vanilla': + mirror_route = world.get_entrance('Sanctuary Mirror Route', player) + mr_door = mirror_route.door + sanctuary = mirror_route.parent_region + sanctuary.exits.remove(mirror_route) + world.remove_entrance(mirror_route, player) + world.remove_door(mr_door, player) + connect_custom(world, player) find_inaccessible_regions(world, player) @@ -637,6 +645,11 @@ def within_dungeon(world, player): logging.getLogger('').info('%s: %s', world.fish.translate("cli", "cli", "keydoor.shuffle.time"), time.process_time()-start) smooth_door_pairs(world, player) + if world.intensity[player] >= 3: + portal = world.get_portal('Sanctuary', player) + target = portal.door.entrance.parent_region + connect_simple_door(world, 'Sanctuary Mirror Route', target, player) + def handle_split_dungeons(dungeon_builders, recombinant_builders, entrances_map, builder_info): dungeon_entrances, split_dungeon_entrances, world, player = builder_info @@ -916,10 +929,18 @@ def cross_dungeon(world, player): if state.visited_at_all(sanctuary): reachable_portals.append(portal) world.sanc_portal[player] = random.choice(reachable_portals) + if world.intensity[player] >= 3: + if player in world.sanc_portal: + portal = world.sanc_portal[player] + else: + portal = world.get_portal('Sanctuary', player) + target = portal.door.entrance.parent_region + connect_simple_door(world, 'Sanctuary Mirror Route', target, player) check_entrance_fixes(world, player) - palette_assignment(world, player) + if world.standardize_palettes[player] == 'standardize': + palette_assignment(world, player) refine_hints(dungeon_builders) @@ -1093,6 +1114,10 @@ def palette_assignment(world, player): queue.append((ext.connected_region, dist+1)) visited_regions.add(ext.connected_region) + sanc = world.get_region('Sanctuary', player) + if sanc.dungeon.name == 'Hyrule Castle': + room = world.get_room(0x12, player) + room.palette = 0x1d for connection in ['Sanctuary S', 'Sanctuary N']: adjacent = world.get_entrance(connection, player) if adjacent.door.dest and adjacent.door.dest.entrance.parent_region.type == RegionType.Dungeon: @@ -1143,7 +1168,7 @@ def convert_to_sectors(region_names, world, player): if existing not in matching_sectors: matching_sectors.append(existing) else: - if door and not door.controller and not door.dest and not door.entranceFlag: + if door and not door.controller and not door.dest and not door.entranceFlag and door.type != DoorType.Logical: outstanding_doors.append(door) sector = Sector() if not new_sector: @@ -1418,7 +1443,8 @@ def find_key_door_candidates(region, checked, world, player): valid = True if valid and d not in candidates: candidates.append(d) - if ext.connected_region.type != RegionType.Dungeon or ext.connected_region.dungeon == dungeon: + connected = ext.connected_region + if connected and (connected.type != RegionType.Dungeon or connected.dungeon == dungeon): queue.append((ext.connected_region, d, current)) if d is not None: checked_doors.append(d) @@ -1815,6 +1841,8 @@ class DROptions(Flag): Map_Info = 0x04 Debug = 0x08 Rails = 0x10 # If on, draws rails + OriginalPalettes = 0x20 + Reserved = 0x40 # Reserved for PoD sliding wall? Open_Desert_Wall = 0x80 # If on, pre opens the desert wall, no fire required diff --git a/Doors.py b/Doors.py index 97e37f7f..460bf0d9 100644 --- a/Doors.py +++ b/Doors.py @@ -120,6 +120,7 @@ def create_doors(world, player): # logically one way the sanc, but should be linked - also toggle create_door(player, 'Sanctuary N', Nrml).dir(No, 0x12, Mid, High).no_exit().toggler().pos(0), create_door(player, 'Sanctuary S', Nrml).dir(So, 0x12, Mid, High).pos(2).portal(Z, 0x22, 1), + create_door(player, 'Sanctuary Mirror Route', Lgcl), # Eastern Palace create_door(player, 'Eastern Lobby S', Nrml).dir(So, 0xc9, Mid, High).pos(4).portal(Z, 0x20), diff --git a/ItemList.py b/ItemList.py index 3414ed60..ae05e9ee 100644 --- a/ItemList.py +++ b/ItemList.py @@ -266,7 +266,7 @@ def generate_itempool(world, player): amt = world.pool_adjustment[player] if amt < 0: for _ in range(amt, 0): - pool.remove('Rupees (20)') + pool.remove(next(iter([x for x in pool if x in ['Rupees (20)', 'Rupees (5)', 'Rupee (1)']]))) elif amt > 0: for _ in range(0, amt): pool.append('Rupees (20)') diff --git a/KeyDoorShuffle.py b/KeyDoorShuffle.py index 8d40f2e2..26db7f9e 100644 --- a/KeyDoorShuffle.py +++ b/KeyDoorShuffle.py @@ -978,21 +978,31 @@ def filter_big_chest(locations): return [x for x in locations if '- Big Chest' not in x.name] +def count_locations_exclude_logic(locations, key_logic): + cnt = 0 + for loc in locations: + if loc not in key_logic.bk_restricted and not loc.forced_item and not prize_or_event(loc): + cnt += 1 + return cnt + + +def prize_or_event(loc): + return loc.name in dungeon_events or '- Prize' in loc.name or loc.name in ['Agahnim 1', 'Agahnim 2'] + + def count_free_locations(state): cnt = 0 for loc in state.found_locations: - if '- Prize' not in loc.name and loc.name not in dungeon_events and not loc.forced_item: - if loc.name not in ['Agahnim 1', 'Agahnim 2']: - cnt += 1 + if not prize_or_event(loc) and not loc.forced_item: + cnt += 1 return cnt def count_locations_exclude_big_chest(state): cnt = 0 for loc in state.found_locations: - if '- Big Chest' not in loc.name and '- Prize' not in loc.name and loc.name not in dungeon_events: - if not loc.forced_item and loc.name not in ['Agahnim 1', 'Agahnim 2']: - cnt += 1 + if '- Big Chest' not in loc.name and not loc.forced_item and not prize_or_event(loc): + cnt += 1 return cnt diff --git a/Main.py b/Main.py index e6298edb..3e9248ab 100644 --- a/Main.py +++ b/Main.py @@ -24,7 +24,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute from ItemList import generate_itempool, difficulties, fill_prizes, fill_specific_items from Utils import output_path, parse_player_names -__version__ = '0.2.0.10u' +__version__ = '0.2.0.11u' class EnemizerError(RuntimeError): pass @@ -68,6 +68,7 @@ def main(args, seed=None, fish=None): world.fish = fish world.keydropshuffle = args.keydropshuffle.copy() world.mixed_travel = args.mixed_travel.copy() + world.standardize_palettes = args.standardize_palettes.copy() world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)} @@ -126,6 +127,7 @@ def main(args, seed=None, fish=None): else: mark_dark_world_regions(world, player) logger.info(world.fish.translate("cli","cli","generating.itempool")) + logger.info(world.fish.translate("cli","cli","generating.itempool")) for player in range(1, world.players + 1): generate_itempool(world, player) @@ -379,6 +381,7 @@ def copy_world(world): ret.experimental = world.experimental.copy() ret.keydropshuffle = world.keydropshuffle.copy() ret.mixed_travel = world.mixed_travel.copy() + ret.standardize_palettes = world.standardize_palettes.copy() for player in range(1, world.players + 1): if world.mode[player] != 'inverted': diff --git a/README.md b/README.md index 1b890e7e..964891e3 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,16 @@ The rooms are left alone and it is up to the discretion of the player whether to The two disjointed sections are forced to be in the same dungeon but never logically required to complete that game. +### Standardize Palettes (--standardize_palettes) +No effect if door shuffle is not on crossed + +#### Standardize +Rooms in the same dungeon have their palettes changed to match. Hyrule Castle is split between Sewer and HC palette. +Rooms adjacent to sanctuary get their coloring to match sanc. + +#### Original +Room keep their original palettes. + ## Map/Compass/Small Key/Big Key shuffle (aka Keysanity) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index feb93b7c..427ddb4e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -36,6 +36,13 @@ otherwise unconnected logically can be reach using these glitches. To prevent th # Bug Fixes +* 2.0.11u + * Option to keep original palettes in crossed dungeon mode + * If sanc if in a DW dungeon because of crossed+ ER, then you start in bunny form + * Mirroring from sanc to the portal is now in logic + * Another fix for animated tiles (fairy fountains) + * GT Big Key stat fixed on credits + * Todo: Standard logic fixes for lobbies * 2.0.10u * Fix POD, TR, GT and SKULL 3 entrance if sanc ends up in that dungeon in crossed ER+ * TR Lobbies that need a bomb and can be entered before bombing should be pre-opened diff --git a/Regions.py b/Regions.py index 7e000ad7..7b895891 100644 --- a/Regions.py +++ b/Regions.py @@ -4,7 +4,7 @@ from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType def create_regions(world, player): world.regions += [ - create_lw_region(player, 'Menu', None, ['Links House S&Q', 'Sanctuary S&Q', 'Old Man S&Q']), + create_menu_region(player, 'Menu', None, ['Links House S&Q', 'Sanctuary S&Q', 'Old Man S&Q']), create_lw_region(player, 'Light World', ['Mushroom', 'Bottle Merchant', 'Flute Spot', 'Sunken Treasure', 'Purple Chest'], ["Blinds Hideout", "Hyrule Castle Secret Entrance Drop", 'Zoras River', 'Kings Grave Outer Rocks', 'Dam', 'Links House', 'Tavern North', 'Chicken House', 'Aginahs Cave', 'Sahasrahlas Hut', 'Kakariko Well Drop', 'Kakariko Well Cave', @@ -273,7 +273,7 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Sewers Pull Switch', 'Hyrule Castle', None, ['Sewers Pull Switch N', 'Sewers Pull Switch S']), create_dungeon_region(player, 'Sanctuary', 'Hyrule Castle', ['Sanctuary'] if not std_flag else ['Sanctuary', 'Zelda Drop Off'], - ['Sanctuary S', 'Sanctuary N']), + ['Sanctuary S', 'Sanctuary N', 'Sanctuary Mirror Route']), # Eastern Palace create_dungeon_region(player, 'Eastern Lobby', 'Eastern Palace', None, ['Eastern Lobby N', 'Eastern Lobby S', 'Eastern Lobby NW', 'Eastern Lobby NE']), @@ -788,15 +788,22 @@ def create_dungeon_regions(world, player): world.get_region('GT Crystal Circles', player).crystal_switch = True +def create_menu_region(player, name, locations=None, exits=None): + return _create_region(player, name, RegionType.Menu, 'Menu', locations, exits) + + def create_lw_region(player, name, locations=None, exits=None): return _create_region(player, name, RegionType.LightWorld, 'Light World', locations, exits) + def create_dw_region(player, name, locations=None, exits=None): return _create_region(player, name, RegionType.DarkWorld, 'Dark World', locations, exits) + def create_cave_region(player, name, hint='Hyrule', locations=None, exits=None): return _create_region(player, name, RegionType.Cave, hint, locations, exits) + def create_dungeon_region(player, name, hint='Hyrule', locations=None, exits=None): return _create_region(player, name, RegionType.Dungeon, hint, locations, exits) diff --git a/Rom.py b/Rom.py index 19ff3c4d..0c1b0158 100644 --- a/Rom.py +++ b/Rom.py @@ -14,6 +14,7 @@ import bps.io from BaseClasses import CollectionState, ShopType, Region, Location, DoorType, RegionType from DoorShuffle import compass_data, DROptions, boss_indicator from Dungeons import dungeon_music_addresses +from KeyDoorShuffle import count_locations_exclude_logic from Regions import location_table from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_texts @@ -24,7 +25,7 @@ from EntranceShuffle import door_addresses, exit_ids JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'e16cc8659527baecc02e3b49b83fa49b' +RANDOMIZERBASEHASH = 'f6be3fdaac906a2217e7ee328e27b95b' class JsonRom(object): @@ -623,11 +624,13 @@ def patch_rom(world, rom, player, team, enemized): dr_flags = DROptions.Eternal_Mini_Bosses if world.doorShuffle[player] == 'vanilla' else DROptions.Town_Portal if world.doorShuffle[player] == 'crossed': dr_flags |= DROptions.Map_Info - if world.experimental[player]: + if world.experimental[player] and world.goal[player] != 'triforcehunt': dr_flags |= DROptions.Debug if world.doorShuffle[player] == 'crossed' and world.logic[player] != 'nologic'\ and world.mixed_travel[player] == 'prevent': dr_flags |= DROptions.Rails + if world.standardize_palettes[player] == 'original': + dr_flags |= DROptions.OriginalPalettes # fix hc big key problems (map and compass too) @@ -656,6 +659,9 @@ def patch_rom(world, rom, player, team, enemized): rom.write_byte(0x13f038+offset*2, bk_status) if player in world.sanc_portal.keys(): rom.write_byte(0x159a6, world.sanc_portal[player].ent_offset) + sanc_region = world.sanc_portal[player].door.entrance.parent_region + if sanc_region.is_dark_world and not sanc_region.is_light_world: + rom.write_byte(0x13ff00, 1) for room in world.rooms: if room.player == player and room.palette is not None: rom.write_byte(0x13f200+room.index, room.palette) @@ -723,10 +729,10 @@ def patch_rom(world, rom, player, team, enemized): # bot: $7A is 1, 7B is 2, etc so 7D=4, 82=9 (zero unknown...) return 0x53+num, 0x79+num - # collection rate address: 238C37 - if world.keydropshuffle[player]: rom.write_byte(0x140000, 1) + rom.write_byte(0x187010, 249) # dynamic credits + # collection rate address: 238C37 mid_top, mid_bot = credits_digit(4) last_top, last_bot = credits_digit(9) # top half @@ -736,6 +742,23 @@ def patch_rom(world, rom, player, team, enemized): rom.write_byte(0x118C71, mid_bot) rom.write_byte(0x118C72, last_bot) + if world.keydropshuffle[player] or world.doorShuffle[player] != 'vanilla': + gt = world.dungeon_layouts[player]['Ganons Tower'] + gt_logic = world.key_logic[player]['Ganons Tower'] + total = 0 + for region in gt.master_sector.regions: + total += count_locations_exclude_logic(region.locations, gt_logic) + rom.write_byte(0x187012, total) # dynamic credits + # gt big key address: 238B59 + mid_top, mid_bot = credits_digit(total // 10) + last_top, last_bot = credits_digit(total % 10) + # top half + rom.write_byte(0x118B75, mid_top) + rom.write_byte(0x118B76, last_top) + # bottom half + rom.write_byte(0x118B93, mid_bot) + rom.write_byte(0x118B94, last_bot) + # patch medallion requirements if world.required_medallions[player][0] == 'Bombos': rom.write_byte(0x180022, 0x00) # requirement diff --git a/Rules.py b/Rules.py index 3da0561c..606e2c3d 100644 --- a/Rules.py +++ b/Rules.py @@ -832,8 +832,10 @@ def standard_rules(world, player): set_rule(world.get_entrance('Sanctuary S&Q', player), lambda state: state.can_reach('Sanctuary', 'Region', player)) # these are because of rails if world.shuffle[player] != 'vanilla': + # todo: set_rule(world.get_entrance('Hyrule Castle Exit (East)', player), lambda state: state.has('Zelda Delivered', player)) set_rule(world.get_entrance('Hyrule Castle Exit (West)', player), lambda state: state.has('Zelda Delivered', player)) + set_rule(world.get_entrance('Sanctuary Exit', player), lambda state: state.has('Zelda Delivered', player)) # too restrictive for crossed? def uncle_item_rule(item): @@ -874,7 +876,7 @@ def standard_rules(world, player): rule_list, debug_path = find_rules_for_zelda_delivery(world, player) set_rule(world.get_location('Zelda Drop Off', player), lambda state: state.has('Zelda Herself', player) and check_rule_list(state, rule_list)) - for location in ['Mushroom', 'Bottle Merchant', 'Flute Spot', 'Sunken Treasure', 'Purple Chest']: + for location in ['Mushroom', 'Bottle Merchant', 'Flute Spot', 'Sunken Treasure', 'Purple Chest', 'Maze Race']: add_rule(world.get_location(location, player), lambda state: state.has('Zelda Delivered', player)) # Bonk Fairy (Light) is a notable omission in ER shuffles/Retro diff --git a/asm/doorrando.asm b/asm/doorrando.asm index e5e5706a..7de554fd 100644 --- a/asm/doorrando.asm +++ b/asm/doorrando.asm @@ -34,6 +34,7 @@ incsrc overrides.asm incsrc edges.asm incsrc math.asm incsrc hudadditions.asm +incsrc dr_lobby.asm warnpc $279700 incsrc doortables.asm diff --git a/asm/doortables.asm b/asm/doortables.asm index ab23c604..73a07c1d 100644 --- a/asm/doortables.asm +++ b/asm/doortables.asm @@ -641,3 +641,8 @@ db $00,$07,$20,$20,$07,$07,$07,$07,$07,$20,$20,$07,$20,$20,$20,$20 db $07,$07,$02,$02,$02,$02,$07,$07,$07,$20,$20,$07,$20,$20,$20,$07 ;27f300 + +; +org $27ff00 +SancDarkWorldFlag: +db 0 diff --git a/asm/dr_lobby.asm b/asm/dr_lobby.asm new file mode 100644 index 00000000..c2f08fa6 --- /dev/null +++ b/asm/dr_lobby.asm @@ -0,0 +1,9 @@ +CheckDarkWorldSanc: + STA $A0 : STA $048E ; what we wrote over + LDA.l SancDarkWorldFlag : BEQ + + SEP #$30 + LDA $A0 : CMP #$12 : BNE ++ + LDA.l $7EF357 : BNE ++ ; moon pearl? + LDA #$17 : STA $5D : INC $02E0 : LDA.b #$40 : STA !DARK_WORLD + ++ REP #$30 ++ RTL diff --git a/asm/drhooks.asm b/asm/drhooks.asm index c99b1f7b..bde005d5 100644 --- a/asm/drhooks.asm +++ b/asm/drhooks.asm @@ -153,6 +153,9 @@ JSL StoreTempBunnyState org $08c450 ; <- ancilla_receive_item.asm : 146-148 (STY $5D : STZ $02D8) JSL RetrieveBunnyState : NOP +org $02d9ce ; <- Bank02.asm : Dungeon_LoadEntrance 10829 (STA $A0 : STA $048E) +JSL CheckDarkWorldSanc : NOP + ; These two, if enabled together, have implications for vanilla BK doors in IP/Hera/Mire ; IPBJ is common enough to consider not doing this. Mire is not a concern for vanilla - maybe glitched modes ; Hera BK door back can be seen with Pot clipping - likely useful for no logic seeds diff --git a/asm/gfx.asm b/asm/gfx.asm index d17ce07b..b22fba62 100644 --- a/asm/gfx.asm +++ b/asm/gfx.asm @@ -34,7 +34,8 @@ GfxFixer: } FixAnimatedTiles: - LDA.L DRMode : cmp #$02 : bne + + LDA.L DRMode : CMP #$02 : BNE + + LDA $040C : CMP.b #$FF : BEQ + PHX LDX $A0 : LDA.l TilesetTable, x CMP $0AA1 : beq ++ @@ -74,6 +75,7 @@ CgramAuxToMain: ; ripped this from bank02 because it ended with rts OverridePaletteHeader: lda.l DRMode : cmp #$02 : bne + + lda.l DRFlags : and #$20 : bne + cpx #$01c2 : !bge + rep #$20 txa : lsr : tax diff --git a/asm/keydropshuffle.asm b/asm/keydropshuffle.asm index 67241d71..f75434cf 100644 --- a/asm/keydropshuffle.asm +++ b/asm/keydropshuffle.asm @@ -121,20 +121,19 @@ KeyGet: lda $a0 : cmp #$87 : bne + jsr ShouldKeyBeCountedForDungeon : bcc - jsl CountChestKeyLong : bra - - + phy - jsr KeyGetPlayer : sta !MULTIWORLD_ITEM_PLAYER_ID - jsl.l $0791b3 ; Player_HaltDashAttackLong - jsl.l Link_ReceiveItem - pla : sta $00 - lda !MULTIWORLD_ITEM_PLAYER_ID : bne .end - phx - lda $040c : lsr : tax - lda $00 : cmp KeyTable, x : bne + - - plx : pla : rtl - + cmp #$af : beq - ; universal key - cmp #$24 : beq - ; small key for this dungeon - plx - .end + + sty $00 + jsr KeyGetPlayer : sta !MULTIWORLD_ITEM_PLAYER_ID + lda !MULTIWORLD_ITEM_PLAYER_ID : bne .receive + phx + lda $040c : lsr : tax + lda $00 : cmp KeyTable, x : bne + + - plx : pla : rtl + + cmp #$af : beq - ; universal key + cmp #$24 : beq - ; small key for this dungeon + plx + .receive + jsl.l $0791b3 ; Player_HaltDashAttackLong + jsl.l Link_ReceiveItem pla : dec : rtl } diff --git a/data/base2current.bps b/data/base2current.bps index 84fc51df..35790ec8 100644 Binary files a/data/base2current.bps and b/data/base2current.bps differ diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 04400bbe..70bc1148 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -70,6 +70,12 @@ "force" ] }, + "standardize_palettes" : { + "choices": [ + "standardize", + "original" + ] + }, "timer": { "choices": [ "none", diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index d60fa7c9..68d136c9 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -251,6 +251,11 @@ "Allow: Take the rails off, \"I know what I'm doing\"", "Force: Force these troublesome connections to be in the same dungeon (but not in logic). No rails will appear" ], + "standardize_palettes": [ + "In cross dungeon shuffle, we can keep the rooms original palette or attempt to standardize them", + "Standardize: Attempts to make the palette the same between dungeons", + "Original: Dungeons rooms retain original palettes" + ], "retro": [ "Keys are universal, shooting arrows costs rupees,", "and a few other little things make this more like Zelda-1. (default: %(default)s)" diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 852491df..84bfab76 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -77,6 +77,10 @@ "randomizer.dungeon.mixed_travel.allow": "Allow Mixed Dungeon Travel", "randomizer.dungeon.mixed_travel.force": "Force Reachable Areas to Same Dungeon", + "randomizer.dungeon.standardize_palettes": "Crossed Dungeon Palette ", + "randomizer.dungeon.standardize_palettes.standardize": "Standardize Palettes", + "randomizer.dungeon.standardize_palettes.original": "Keep Original Palettes", + "randomizer.enemizer.potshuffle": "Pot Shuffle", "randomizer.enemizer.enemyshuffle": "Enemy Shuffle", diff --git a/resources/app/gui/randomize/dungeon/widgets.json b/resources/app/gui/randomize/dungeon/widgets.json index f6c52bff..13dd211a 100644 --- a/resources/app/gui/randomize/dungeon/widgets.json +++ b/resources/app/gui/randomize/dungeon/widgets.json @@ -35,7 +35,7 @@ }, "mixed_travel": { "type" : "selectbox", - "default": "auto", + "default": "prevent", "options": [ "prevent", "allow", @@ -44,6 +44,17 @@ "config": { "width": 35 } + }, + "standardize_palettes" : { + "type": "selectbox", + "default": "standardize", + "options": [ + "standardize", + "original" + ], + "config": { + "width": 35 + } } } } diff --git a/source/classes/constants.py b/source/classes/constants.py index 0d2157cb..0d97f148 100644 --- a/source/classes/constants.py +++ b/source/classes/constants.py @@ -91,7 +91,8 @@ SETTINGSTOPROCESS = { "dungeonintensity": "intensity", "experimental": "experimental", "dungeon_counters": "dungeon_counters", - "mixed_travel": "mixed_travel" + "mixed_travel": "mixed_travel", + "standardize_palettes": "standardize_palettes", }, "gameoptions": { "hints": "hints",