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)
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), })
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), })
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), })
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), })
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), })
def to_json(self): if self.colors is not None: self.colors = CollapseList(self.colors) return CollapseDict(super().to_json())
def to_json(self): self_dict = super().to_json() if list(self_dict.keys()) == ['item']: return str(self.item) else: return CollapseDict(self_dict)
def to_json(self): if self.type == 'set': return self.count else: return CollapseDict(super().to_json())
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])
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']
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)
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)
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), })