예제 #1
0
 def to_json(self):
     self_dict = super().to_json()
     if list(self_dict.keys()) == ['region']:
         return str(self.region)
     else:
         self_dict['from'] = self_dict['origin']
         del self_dict['origin']
         return CollapseDict(self_dict)
예제 #2
0
def patch_heart_colors(rom, settings, log, symbols):
    # patch heart colors
    hearts = [
        ('Heart Color', 'heart_color', symbols['CFG_HEART_COLOR'], 0xBB0994,
         ([0x14DA474, 0x14DA594, 0x14B701C, 0x14B70DC], [
             0x14B70FC, 0x14DA494, 0x14DA5B4, 0x14B700C, 0x14B702C, 0x14B703C,
             0x14B704C, 0x14B705C, 0x14B706C, 0x14B707C, 0x14B708C, 0x14B709C,
             0x14B70AC, 0x14B70BC, 0x14B70CC
         ])),  # GI Model DList colors
    ]
    heart_color_list = get_heart_colors()

    for heart, heart_setting, symbol, file_select_address, model_addresses in hearts:
        heart_option = settings.__dict__[heart_setting]

        # Handle Plando
        if log.src_dict.get('ui_colors', {}).get(heart, {}).get('color', ''):
            heart_option = log.src_dict['ui_colors'][heart]['color']

        # handle random
        if heart_option == 'Random Choice':
            heart_option = random.choice(heart_color_list)
        # handle completely random
        if heart_option == 'Completely Random':
            color = generate_random_color()
        # grab the color from the list
        elif heart_option in heart_colors:
            color = list(heart_colors[heart_option])
        # build color from hex code
        else:
            color = hex_to_color(heart_option)
            heart_option = 'Custom'
        rom.write_int16s(symbol, color)  # symbol for ingame HUD
        rom.write_int16s(file_select_address,
                         color)  # file select normal hearts
        if heart_option != 'Red':
            rom.write_int16s(file_select_address + 6,
                             color)  # file select DD hearts
        else:
            original_dd_color = rom.original.read_bytes(
                file_select_address + 6, 6)
            rom.write_bytes(file_select_address + 6, original_dd_color)
        if settings.correct_model_colors and heart_option != 'Red':
            patch_model_colors(rom, color,
                               model_addresses)  # heart model colors
            icon.patch_overworld_icon(rom, color,
                                      0xF43D80)  # Overworld Heart Icon
        else:
            patch_model_colors(rom, None, model_addresses)
            icon.patch_overworld_icon(rom, None, 0xF43D80)
        log.ui_colors[heart] = CollapseDict({
            ':option': heart_option,
            'color': color_to_hex(color),
        })
예제 #3
0
def patch_tunic_colors(rom, settings, log, symbols):
    # patch tunic colors
    tunics = [
        ('Kokiri Tunic', 'kokiri_color', 0x00B6DA38),
        ('Goron Tunic', 'goron_color', 0x00B6DA3B),
        ('Zora Tunic', 'zora_color', 0x00B6DA3E),
    ]
    tunic_color_list = get_tunic_colors()

    for tunic, tunic_setting, address in tunics:
        tunic_option = settings.__dict__[tunic_setting]

        # Handle Plando
        if log.src_dict.get('equipment_colors', {}).get(tunic,
                                                        {}).get('color', ''):
            tunic_option = log.src_dict['equipment_colors'][tunic]['color']

        # handle random
        if tunic_option == 'Random Choice':
            tunic_option = random.choice(tunic_color_list)
        # handle completely random
        if tunic_option == 'Completely Random':
            color = generate_random_color()
        # grab the color from the list
        elif tunic_option in tunic_colors:
            color = list(tunic_colors[tunic_option])
        # build color from hex code
        else:
            color = hex_to_color(tunic_option)
            tunic_option = 'Custom'
        # "Weird" weirdshots will crash if the Kokiri Tunic Green value is > 0x99. Brickwall it.
        if settings.logic_rules != 'glitchless' and tunic == 'Kokiri Tunic':
            color[1] = min(color[1], 0x98)
        rom.write_bytes(address, color)

        # patch the tunic icon
        if [tunic, tunic_option] not in [['Kokiri Tunic', 'Kokiri Green'],
                                         ['Goron Tunic', 'Goron Red'],
                                         ['Zora Tunic', 'Zora Blue']]:
            patch_tunic_icon(rom, tunic, color)
        else:
            patch_tunic_icon(rom, tunic, None)

        log.equipment_colors[tunic] = CollapseDict({
            ':option':
            tunic_option,
            'color':
            color_to_hex(color),
        })
예제 #4
0
def patch_shield_frame_colors(rom, settings, log, symbols):
    # patch shield frame colors
    shield_frames = [
        ('Mirror Shield Frame', 'mirror_shield_frame_color',
         [0xFA7274, 0xFA776C, 0xFAA27C, 0xFAC564, 0xFAC984,
          0xFAEDD4], ([0x1616FCC], [0x1616FD4])),
    ]
    shield_frame_color_list = get_shield_frame_colors()

    for shield_frame, shield_frame_setting, addresses, model_addresses in shield_frames:
        shield_frame_option = settings.__dict__[shield_frame_setting]

        # Handle Plando
        if log.src_dict.get('equipment_colors', {}).get(shield_frame,
                                                        {}).get('color', ''):
            shield_frame_option = log.src_dict['equipment_colors'][
                shield_frame]['color']

        # handle random
        if shield_frame_option == 'Random Choice':
            shield_frame_option = random.choice(shield_frame_color_list)
        # handle completely random
        if shield_frame_option == 'Completely Random':
            color = [
                random.getrandbits(8),
                random.getrandbits(8),
                random.getrandbits(8)
            ]
        # grab the color from the list
        elif shield_frame_option in shield_frame_colors:
            color = list(shield_frame_colors[shield_frame_option])
        # build color from hex code
        else:
            color = hex_to_color(shield_frame_option)
            shield_frame_option = 'Custom'
        for address in addresses:
            rom.write_bytes(address, color)
        if settings.correct_model_colors and shield_frame_option != 'Red':
            patch_model_colors(rom, color, model_addresses)
        else:
            patch_model_colors(rom, None, model_addresses)

        log.equipment_colors[shield_frame] = CollapseDict({
            ':option':
            shield_frame_option,
            'color':
            color_to_hex(color),
        })
예제 #5
0
def patch_gauntlet_colors(rom, settings, log, symbols):
    # patch gauntlet colors
    gauntlets = [
        ('Silver Gauntlets', 'silver_gauntlets_color', 0x00B6DA44,
         ([0x173B4CC], [0x173B4D4, 0x173B50C,
                        0x173B514])),  # GI Model DList colors
        ('Gold Gauntlets', 'golden_gauntlets_color', 0x00B6DA47,
         ([0x173B4EC], [0x173B4F4, 0x173B52C,
                        0x173B534])),  # GI Model DList colors
    ]
    gauntlet_color_list = get_gauntlet_colors()

    for gauntlet, gauntlet_setting, address, model_addresses in gauntlets:
        gauntlet_option = settings.__dict__[gauntlet_setting]

        # Handle Plando
        if log.src_dict.get('equipment_colors', {}).get(gauntlet,
                                                        {}).get('color', ''):
            gauntlet_option = log.src_dict['equipment_colors'][gauntlet][
                'color']

        # handle random
        if gauntlet_option == 'Random Choice':
            gauntlet_option = random.choice(gauntlet_color_list)
        # handle completely random
        if gauntlet_option == 'Completely Random':
            color = generate_random_color()
        # grab the color from the list
        elif gauntlet_option in gauntlet_colors:
            color = list(gauntlet_colors[gauntlet_option])
        # build color from hex code
        else:
            color = hex_to_color(gauntlet_option)
            gauntlet_option = 'Custom'
        rom.write_bytes(address, color)
        if settings.correct_model_colors:
            patch_model_colors(rom, color, model_addresses)
        else:
            patch_model_colors(rom, None, model_addresses)
        log.equipment_colors[gauntlet] = CollapseDict({
            ':option':
            gauntlet_option,
            'color':
            color_to_hex(color),
        })
예제 #6
0
def patch_magic_colors(rom, settings, log, symbols):
    # patch magic colors
    magic = [
        ('Magic Meter Color', 'magic_color', symbols["CFG_MAGIC_COLOR"],
         ([0x154C654, 0x154CFB4], [0x154C65C,
                                   0x154CFBC])),  # GI Model DList colors
    ]
    magic_color_list = get_magic_colors()

    for magic_color, magic_setting, symbol, model_addresses in magic:
        magic_option = settings.__dict__[magic_setting]

        # Handle Plando
        if log.src_dict.get('ui_colors', {}).get(magic_color,
                                                 {}).get('color', ''):
            magic_option = log.src_dict['ui_colors'][magic_color]['color']

        if magic_option == 'Random Choice':
            magic_option = random.choice(magic_color_list)

        if magic_option == 'Completely Random':
            color = generate_random_color()
        elif magic_option in magic_colors:
            color = list(magic_colors[magic_option])
        else:
            color = hex_to_color(magic_option)
            magic_option = 'Custom'
        rom.write_int16s(symbol, color)
        if magic_option != 'Green' and settings.correct_model_colors:
            patch_model_colors(rom, color, model_addresses)
            icon.patch_overworld_icon(
                rom, color, 0xF45650,
                data_path('icons/magicSmallExtras.raw'))  # Overworld Small Pot
            icon.patch_overworld_icon(
                rom, color, 0xF47650,
                data_path('icons/magicLargeExtras.raw'))  # Overworld Big Pot
        else:
            patch_model_colors(rom, None, model_addresses)
            icon.patch_overworld_icon(rom, None, 0xF45650)
            icon.patch_overworld_icon(rom, None, 0xF47650)
        log.ui_colors[magic_color] = CollapseDict({
            ':option': magic_option,
            'color': color_to_hex(color),
        })
예제 #7
0
 def to_json(self):
     if self.colors is not None:
         self.colors = CollapseList(self.colors)
     return CollapseDict(super().to_json())
예제 #8
0
 def to_json(self):
     self_dict = super().to_json()
     if list(self_dict.keys()) == ['item']:
         return str(self.item)
     else:
         return CollapseDict(self_dict)
예제 #9
0
 def to_json(self):
     if self.type == 'set':
         return self.count
     else:
         return CollapseDict(super().to_json())
예제 #10
0
def patch_button_colors(rom, settings, log, symbols):
    buttons = [
        ('A Button Color', 'a_button_color', a_button_colors,
            [('A Button Color', symbols['CFG_A_BUTTON_COLOR'],
                None),
             ('Text Cursor Color', symbols['CFG_TEXT_CURSOR_COLOR'],
                [(0xB88E81, 0xB88E85, 0xB88E9)]), # Initial Inner Color
             ('Shop Cursor Color', symbols['CFG_SHOP_CURSOR_COLOR'],
                None),
             ('Save/Death Cursor Color', None,
                [(0xBBEBC2, 0xBBEBC3, 0xBBEBD6), (0xBBEDDA, 0xBBEDDB, 0xBBEDDE)]), # Save Cursor / Death Cursor
             ('Pause Menu A Cursor Color', None,
                [(0xBC7849, 0xBC784B, 0xBC784D), (0xBC78A9, 0xBC78AB, 0xBC78AD), (0xBC78BB, 0xBC78BD, 0xBC78BF)]), # Inner / Pulse 1 / Pulse 2
             ('Pause Menu A Icon Color', None,
                [(0x845754, 0x845755, 0x845756)]),
             ('A Note Color', symbols['CFG_A_NOTE_COLOR'], # For Textbox Song Display
                [(0xBB299A, 0xBB299B, 0xBB299E), (0xBB2C8E, 0xBB2C8F, 0xBB2C92), (0xBB2F8A, 0xBB2F8B, 0xBB2F96)]), # Pause Menu Song Display
            ]),
        ('B Button Color', 'b_button_color', b_button_colors,
            [('B Button Color', symbols['CFG_B_BUTTON_COLOR'],
                None),
            ]),
        ('C Button Color', 'c_button_color', c_button_colors,
            [('C Button Color', symbols['CFG_C_BUTTON_COLOR'],
                None),
             ('Pause Menu C Cursor Color', None,
                [(0xBC7843, 0xBC7845, 0xBC7847), (0xBC7891, 0xBC7893, 0xBC7895), (0xBC78A3, 0xBC78A5, 0xBC78A7)]), # Inner / Pulse 1 / Pulse 2
             ('Pause Menu C Icon Color', None,
                [(0x8456FC, 0x8456FD, 0x8456FE)]),
             ('C Note Color', symbols['CFG_C_NOTE_COLOR'], # For Textbox Song Display
                [(0xBB2996, 0xBB2997, 0xBB29A2), (0xBB2C8A, 0xBB2C8B, 0xBB2C96), (0xBB2F86, 0xBB2F87, 0xBB2F9A)]), # Pause Menu Song Display
            ]),
        ('Start Button Color', 'start_button_color', start_button_colors,
            [('Start Button Color', None,
                [(0xAE9EC6, 0xAE9EC7, 0xAE9EDA)]),
            ]),
    ]

    for button, button_setting, button_colors, patches in buttons:
        button_option = settings.__dict__[button_setting]
        color_set = None
        colors = {}
        log_dict = CollapseDict({':option': button_option, 'colors': {}})
        log.ui_colors[button] = log_dict

        # Setup Plando
        plando_colors = log.src_dict.get('ui_colors', {}).get(button, {}).get('colors', {})

        # handle random
        if button_option == 'Random Choice':
            button_option = random.choice(list(button_colors.keys()))
        # handle completely random
        if button_option == 'Completely Random':
            fixed_font_color = [10, 10, 10]
            color = [0, 0, 0]
            # Avoid colors which have a low contrast with the font inside buttons (eg. the A letter)
            while contrast_ratio(color, fixed_font_color) <= 3:
                color = generate_random_color()
        # grab the color from the list
        elif button_option in button_colors:
            color_set = [button_colors[button_option]] if isinstance(button_colors[button_option][0], int) else list(button_colors[button_option])
            color = color_set[0]
        # build color from hex code
        else:
            color = hex_to_color(button_option)
            button_option = 'Custom'
        log_dict[':option'] = button_option

        # apply all button color patches
        for i, (patch, symbol, byte_addresses) in enumerate(patches):
            if plando_colors.get(patch, ''):
                colors[patch] = hex_to_color(plando_colors[patch])
            elif color_set is not None and len(color_set) > i and color_set[i]:
                colors[patch] = color_set[i]
            else:
                colors[patch] = color

            if symbol:
                rom.write_int16s(symbol, colors[patch])

            if byte_addresses:
                for r_addr, g_addr, b_addr in byte_addresses:
                    rom.write_byte(r_addr, colors[patch][0])
                    rom.write_byte(g_addr, colors[patch][1])
                    rom.write_byte(b_addr, colors[patch][2])

            log_dict['colors'][patch] = color_to_hex(colors[patch])
예제 #11
0
def patch_trails(rom, settings, log, trails):
    for trail_name, trail_setting, trail_color_list, trail_color_dict, trail_symbols in trails:
        color_inner_symbol, color_outer_symbol, rainbow_inner_symbol, rainbow_outer_symbol = trail_symbols
        option_inner = settings.__dict__[trail_setting+'_inner']
        option_outer = settings.__dict__[trail_setting+'_outer']
        plando_colors = log.src_dict.get('misc_colors', {}).get(trail_name, {}).get('colors', [])

        # handle random choice
        if option_inner == 'Random Choice':
            option_inner = random.choice(trail_color_list)
        if option_outer == 'Random Choice':
            option_outer = random.choice(trail_color_list)

        if option_outer == '[Same as Inner]':
            option_outer = option_inner

        option_dict = {}
        colors = {}

        for index, (trail_part, option, rainbow_symbol, color_symbol) in enumerate([
            ('inner', option_inner, rainbow_inner_symbol, color_inner_symbol),
            ('outer', option_outer, rainbow_outer_symbol, color_outer_symbol),
        ]):
            color = None

            # Plando
            if len(plando_colors) > 0 and plando_colors[0].get(trail_part, ''):
                color = hex_to_color(plando_colors[0][trail_part])

            # set rainbow option
            if option == 'Rainbow':
                rom.write_byte(rainbow_symbol, 0x01)
                color = [0x00, 0x00, 0x00]
            else:
                rom.write_byte(rainbow_symbol, 0x00)

            # handle completely random
            if color is None and option == 'Completely Random':
                # Specific handling for inner bombchu trails for contrast purposes.
                if trail_name == 'Bombchu Trail' and trail_part == 'inner':
                    fixed_dark_color = [0, 0, 0]
                    color = [0, 0, 0]
                    # Avoid colors which have a low contrast so the bombchu ticking is still visible
                    while contrast_ratio(color, fixed_dark_color) <= 4:
                        color = generate_random_color()
                else:
                    color = generate_random_color()

            # grab the color from the list
            if color is None and option in trail_color_dict:
                color = list(trail_color_dict[option])

            # build color from hex code
            if color is None:
                color = hex_to_color(option)
                option = 'Custom'

            option_dict[trail_part] = option
            colors[trail_part] = color

            # write color
            rom.write_bytes(color_symbol, color)

        # Get the colors into the log.
        log.misc_colors[trail_name] = CollapseDict({
            ':option_inner': option_dict['inner'],
            ':option_outer': option_dict['outer'],
            'colors': [],
        })
        if option_dict['inner'] != "Rainbow" or option_dict['outer'] != "Rainbow":
            colors_str = CollapseDict()
            log.misc_colors[trail_name]['colors'].append(colors_str)
            for part, color in colors.items():
                if log.misc_colors[trail_name][f':option_{part}'] != "Rainbow":
                    colors_str[part] = color_to_hex(color)
        else:
            del log.misc_colors[trail_name]['colors']
예제 #12
0
def patch_sword_trails(rom, settings, log, symbols):
    # patch sword trail duration
    rom.write_byte(0x00BEFF8C, settings.sword_trail_duration)

    # patch sword trail colors
    sword_trails = [
        ('Sword Trail', 'sword_trail_color',
            [(0x00BEFF7C, 0xB0, 0x40, 0xB0, 0xFF), (0x00BEFF84, 0x20, 0x00, 0x10, 0x00)],
            symbols.get('CFG_RAINBOW_SWORD_INNER_ENABLED', None), symbols.get('CFG_RAINBOW_SWORD_OUTER_ENABLED', None)),
    ]

    sword_trail_color_list = get_sword_trail_colors()
    rainbow_error = None

    for trail_name, trail_setting, trail_addresses, rainbow_inner_symbol, rainbow_outer_symbol in sword_trails:
        option_inner = settings.__dict__[trail_setting+'_inner']
        option_outer = settings.__dict__[trail_setting+'_outer']
        plando_colors = log.src_dict.get('misc_colors', {}).get(trail_name, {}).get('colors', [])

        # handle random choice
        if option_inner == 'Random Choice':
            option_inner = random.choice(sword_trail_color_list)
        if option_outer == 'Random Choice':
            option_outer = random.choice(sword_trail_color_list)

        if option_outer == '[Same as Inner]':
            option_outer = option_inner

        colors = []
        option_dict = {}
        for address_index, (address, inner_transparency, inner_white_transparency, outer_transparency, outer_white_transparency) in enumerate(trail_addresses):
            address_colors = {}
            colors.append(address_colors)
            transparency_dict = {}
            for index, (trail_part, option, rainbow_symbol, white_transparency, transparency) in enumerate([
                ('inner', option_inner, rainbow_inner_symbol, inner_white_transparency, inner_transparency),
                ('outer', option_outer, rainbow_outer_symbol, outer_white_transparency, outer_transparency),
            ]):
                color = None

                # Plando
                if len(plando_colors) > address_index and plando_colors[address_index].get(trail_part, ''):
                    color = hex_to_color(plando_colors[address_index][trail_part])

                # set rainbow option
                if rainbow_symbol is not None and option == 'Rainbow':
                    rom.write_byte(rainbow_symbol, 0x01)
                    color = [0x00, 0x00, 0x00]
                elif rainbow_symbol is not None:
                    rom.write_byte(rainbow_symbol, 0x00)
                elif option == 'Rainbow':
                    rainbow_error = "Rainbow Sword Trail is not supported by this patch version. Using 'Completely Random' as a substitute."
                    option = 'Completely Random'

                # completely random is random for every subgroup
                if color is None and option == 'Completely Random':
                    color = generate_random_color()

                # grab the color from the list
                if color is None and option in sword_trail_colors:
                    color = list(sword_trail_colors[option])

                # build color from hex code
                if color is None:
                    color = hex_to_color(option)
                    option = 'Custom'

                # Check color validity
                if color is None:
                    raise Exception(f'Invalid {trail_part} color {option} for {trail_name}')

                # handle white transparency
                if option == 'White':
                    transparency_dict[trail_part] = white_transparency
                else:
                    transparency_dict[trail_part] = transparency

                address_colors[trail_part] = color
                option_dict[trail_part] = option

            # write color
            color = address_colors['outer'] + [transparency_dict['outer']] + address_colors['inner'] + [transparency_dict['inner']]
            rom.write_bytes(address, color)

        # Get the colors into the log.
        log.misc_colors[trail_name] = CollapseDict({
            ':option_inner': option_dict['inner'],
            ':option_outer': option_dict['outer'],
            'colors': [],
        })
        if option_dict['inner'] != "Rainbow" or option_dict['outer'] != "Rainbow" or rainbow_error:
            for address_colors in colors:
                address_colors_str = CollapseDict()
                log.misc_colors[trail_name]['colors'].append(address_colors_str)
                for part, color in address_colors.items():
                    if log.misc_colors[trail_name][f':option_{part}'] != "Rainbow" or rainbow_error:
                        address_colors_str[part] = color_to_hex(color)
        else:
            del log.misc_colors[trail_name]['colors']

    if rainbow_error:
        log.errors.append(rainbow_error)
예제 #13
0
def patch_navi_colors(rom, settings, log, symbols):
    # patch navi colors
    navi = [
        # colors for Navi
        ('Navi Idle',            'navi_color_default',
         [0x00B5E184],  # Default (Player)
         symbols.get('CFG_RAINBOW_NAVI_IDLE_INNER_ENABLED', None), symbols.get('CFG_RAINBOW_NAVI_IDLE_OUTER_ENABLED', None)),
        ('Navi Targeting Enemy', 'navi_color_enemy',
            [0x00B5E19C, 0x00B5E1BC],  # Enemy, Boss
            symbols.get('CFG_RAINBOW_NAVI_ENEMY_INNER_ENABLED', None), symbols.get('CFG_RAINBOW_NAVI_ENEMY_OUTER_ENABLED', None)),
        ('Navi Targeting NPC',   'navi_color_npc',
            [0x00B5E194], # NPC
            symbols.get('CFG_RAINBOW_NAVI_NPC_INNER_ENABLED', None), symbols.get('CFG_RAINBOW_NAVI_NPC_OUTER_ENABLED', None)),
        ('Navi Targeting Prop',  'navi_color_prop',
            [0x00B5E174, 0x00B5E17C, 0x00B5E18C, 0x00B5E1A4, 0x00B5E1AC,
             0x00B5E1B4, 0x00B5E1C4, 0x00B5E1CC, 0x00B5E1D4], # Everything else
            symbols.get('CFG_RAINBOW_NAVI_PROP_INNER_ENABLED', None), symbols.get('CFG_RAINBOW_NAVI_PROP_OUTER_ENABLED', None)),
    ]

    navi_color_list = get_navi_colors()
    rainbow_error = None

    for navi_action, navi_setting, navi_addresses, rainbow_inner_symbol, rainbow_outer_symbol in navi:
        navi_option_inner = settings.__dict__[navi_setting+'_inner']
        navi_option_outer = settings.__dict__[navi_setting+'_outer']
        plando_colors = log.src_dict.get('misc_colors', {}).get(navi_action, {}).get('colors', [])

        # choose a random choice for the whole group
        if navi_option_inner == 'Random Choice':
            navi_option_inner = random.choice(navi_color_list)
        if navi_option_outer == 'Random Choice':
            navi_option_outer = random.choice(navi_color_list)

        if navi_option_outer == '[Same as Inner]':
            navi_option_outer = navi_option_inner

        colors = []
        option_dict = {}
        for address_index, address in enumerate(navi_addresses):
            address_colors = {}
            colors.append(address_colors)
            for index, (navi_part, option, rainbow_symbol) in enumerate([
                ('inner', navi_option_inner, rainbow_inner_symbol),
                ('outer', navi_option_outer, rainbow_outer_symbol),
            ]):
                color = None

                # Plando
                if len(plando_colors) > address_index and plando_colors[address_index].get(navi_part, ''):
                    color = hex_to_color(plando_colors[address_index][navi_part])

                # set rainbow option
                if rainbow_symbol is not None and option == 'Rainbow':
                    rom.write_byte(rainbow_symbol, 0x01)
                    color = [0x00, 0x00, 0x00]
                elif rainbow_symbol is not None:
                    rom.write_byte(rainbow_symbol, 0x00)
                elif option == 'Rainbow':
                    rainbow_error = "Rainbow Navi is not supported by this patch version. Using 'Completely Random' as a substitute."
                    option = 'Completely Random'

                # completely random is random for every subgroup
                if color is None and option == 'Completely Random':
                    color = generate_random_color()

                # grab the color from the list
                if color is None and option in NaviColors:
                    color = list(NaviColors[option][index])

                # build color from hex code
                if color is None:
                    color = hex_to_color(option)
                    option = 'Custom'

                # Check color validity
                if color is None:
                    raise Exception(f'Invalid {navi_part} color {option} for {navi_action}')

                address_colors[navi_part] = color
                option_dict[navi_part] = option

            # write color
            color = address_colors['inner'] + [0xFF] + address_colors['outer'] + [0xFF]
            rom.write_bytes(address, color)

        # Get the colors into the log.
        log.misc_colors[navi_action] = CollapseDict({
            ':option_inner': option_dict['inner'],
            ':option_outer': option_dict['outer'],
            'colors': [],
        })
        if option_dict['inner'] != "Rainbow" or option_dict['outer'] != "Rainbow" or rainbow_error:
            for address_colors in colors:
                address_colors_str = CollapseDict()
                log.misc_colors[navi_action]['colors'].append(address_colors_str)
                for part, color in address_colors.items():
                    if log.misc_colors[navi_action][f':option_{part}'] != "Rainbow" or rainbow_error:
                        address_colors_str[part] = color_to_hex(color)
        else:
            del log.misc_colors[navi_action]['colors']

    if rainbow_error:
        log.errors.append(rainbow_error)
예제 #14
0
def patch_extra_equip_colors(rom, settings, log, symbols):
    # Various equipment color patches
    extra_equip_patches = [
        ('Mirror Shield Main',
         [0xFA722C, 0xFA7724, 0xFAA234, 0xFAC5D4, 0xFAC9F4,
          0xFAEE44], ([0x16170FC], [0x1617104])),
        ('Mirror Shield Symbol',
         [0xFA763C, 0xFA7A34, 0xFAA624, 0xFAC89C, 0xFACBE4,
          0xFAEEE4], ([0x16171E4], [0x16171EC])),
        ('Gauntlets Crystal', [0xFAB404, 0xFAB564, 0xFAB784,
                               0xFAB8E4], ([0x173B79C], [0x173B7A4])),
        ('Kokiri Sword Blade', [0xFD216C,
                                0xFD5844], ([0x196897C], [0x1968984])),
        ('Master Sword Blade', [0xFA7FEC, 0xFAD21C,
                                0xFD36F4], ([0x125CC24], [0x125CC2C])),
        ('Biggoron Sword Blade', [0xFA9A84, 0xFA9F0C, 0xFAE9A4,
                                  0xFAF39C], ([0x163F61C], [0x163F624])),
        ('Hammer Metal', [0xFA94EC, 0xFAE394], ([0x163D9EC, 0x163DBB4], [])),
        ('Hammer Handle', [0xFA945C, 0xFAE304], ([0x163DC2C], [0x163DC34])),
        ('Bow Tip', [0xFA8E5C, 0xFADC34,
                     0xFB033C], ([0x1605BF4], [0x1605BFC])),
        ('Bow Limbs', [0xFA8E8C, 0xFADC5C,
                       0xFB0374], ([0x16059AC], [0x16059B4])),
        ('Bow Riser', [0xFA8E24, 0xFADC04,
                       0xFB02C4], ([0x1605AFC], [0x1605B04])),
        ('Boomerang Main', [0xFD2744, 0xFD4944,
                            0xF0F7A4], ([0x1604A4C], [0x1604A54])),
        ('Boomerang Crystal', [0xFD26CC,
                               0xF0F734], ([0x1604C8C], [0x1604C94])),
    ]

    for name, addresses, model_addresses in extra_equip_patches:
        option = 'Completely Random' if settings.extra_equip_colors else 'Vanilla'

        # Handle Plando
        if log.src_dict.get('equipment_colors', {}).get(name,
                                                        {}).get('color', ''):
            option = log.src_dict['equipment_colors'][name]['color']

        # handle completely random
        if option == 'Completely Random':
            color = [
                random.getrandbits(8),
                random.getrandbits(8),
                random.getrandbits(8)
            ]
        # handle vanilla
        elif option == 'Vanilla':
            color = rom.original.read_bytes(addresses[0], 3)
        # build color from hex code
        else:
            color = hex_to_color(option)
            option = 'Custom'

        for address in addresses:
            rom.write_bytes(address, color)

        if settings.correct_model_colors and option != 'Vanilla':
            patch_model_colors(rom, color, model_addresses)
        else:
            patch_model_colors(rom, None, model_addresses)

        log.equipment_colors[name] = CollapseDict({
            ':option': option,
            'color': color_to_hex(color),
        })