diff --git a/BaseClasses.py b/BaseClasses.py index 62052e90cc..6c9799cf1f 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -63,6 +63,8 @@ class World(object): self.can_take_damage = True self.difficulty_requirements = None self.fix_fake_world = True + self.dynamic_regions = [] + self.dynamic_locations = [] self.spoiler = Spoiler(self) self.lamps_needed_for_dark_rooms = 1 @@ -185,6 +187,9 @@ class World(object): self._cached_locations.extend(region.locations) return self._cached_locations + def clear_location_cache(self): + self._cached_locations = None + def get_unfilled_locations(self): return [location for location in self.get_locations() if location.item is None] @@ -828,19 +833,58 @@ class Spoiler(object): def __init__(self, world): self.world = world - self.entrances = [] + self.entrances = OrderedDict() self.medallions = {} self.playthrough = {} self.locations = {} self.paths = {} self.metadata = {} + self.shops = [] def set_entrance(self, entrance, exit, direction): - self.entrances.append(OrderedDict([('entrance', entrance), ('exit', exit), ('direction', direction)])) + self.entrances[(entrance, direction)] = OrderedDict([('entrance', entrance), ('exit', exit), ('direction', direction)]) def parse_data(self): self.medallions = OrderedDict([('Misery Mire', self.world.required_medallions[0]), ('Turtle Rock', self.world.required_medallions[1])]) - self.locations = {'other locations': OrderedDict([(str(location), str(location.item) if location.item is not None else 'Nothing') for location in self.world.get_locations()])} + + self.locations = OrderedDict() + listed_locations = set() + + lw_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.LightWorld] + self.locations['Light World'] = OrderedDict([(str(location), str(location.item) if location.item is not None else 'Nothing') for location in lw_locations]) + listed_locations.update(lw_locations) + + dw_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.DarkWorld] + self.locations['Dark World'] = OrderedDict([(str(location), str(location.item) if location.item is not None else 'Nothing') for location in dw_locations]) + listed_locations.update(dw_locations) + + cave_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.Cave] + self.locations['Caves'] = OrderedDict([(str(location), str(location.item) if location.item is not None else 'Nothing') for location in cave_locations]) + listed_locations.update(cave_locations) + + for dungeon in self.world.dungeons: + dungeon_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon] + self.locations[dungeon.name] = OrderedDict([(str(location), str(location.item) if location.item is not None else 'Nothing') for location in dungeon_locations]) + listed_locations.update(dungeon_locations) + + other_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations] + if other_locations: + self.locations['Other Locations'] = OrderedDict([(str(location), str(location.item) if location.item is not None else 'Nothing') for location in other_locations]) + listed_locations.update(other_locations) + + for shop in self.world.shops: + if not shop.active: + continue + shopdata = {'location': shop.region.name, + 'type': 'Take Any' if shop.type == ShopType.TakeAny else 'Shop' + } + for index, item in enumerate(shop.inventory): + if item is None: + continue + shopdata['item_{}'.format(index)] = "{} ({})".format(item['item'], item['price']) if item['price'] else item['item'] + self.shops.append(shopdata) + + from Main import __version__ as ERVersion self.metadata = {'version': ERVersion, 'seed': self.world.seed, @@ -862,9 +906,10 @@ class Spoiler(object): def to_json(self): self.parse_data() out = OrderedDict() - out['entrances'] = self.entrances + out['entrances'] = self.entrances.values() out.update(self.locations) out['medallions'] = self.medallions + out['shops'] = self.shops out['playthrough'] = self.playthrough out['paths'] = self.paths out['meta'] = self.metadata @@ -886,12 +931,14 @@ class Spoiler(object): outfile.write('Keysanity enabled: %s' % ('Yes' if self.metadata['keysanity'] else 'No')) if self.entrances: outfile.write('\n\nEntrances:\n\n') - outfile.write('\n'.join(['%s %s %s' % (entry['entrance'], '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', entry['exit']) for entry in self.entrances])) + outfile.write('\n'.join(['%s %s %s' % (entry['entrance'], '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', entry['exit']) for entry in self.entrances.values()])) outfile.write('\n\nMedallions') outfile.write('\n\nMisery Mire Medallion: %s' % self.medallions['Misery Mire']) outfile.write('\nTurtle Rock Medallion: %s' % self.medallions['Turtle Rock']) outfile.write('\n\nLocations:\n\n') - outfile.write('\n'.join(['%s: %s' % (location, item) for (location, item) in self.locations['other locations'].items()])) + outfile.write('\n'.join(['%s: %s' % (location, item) for grouping in self.locations.values() for (location, item) in grouping.items()])) + outfile.write('\n\nShops:\n\n') + outfile.write('\n'.join("{} [{}]\n {}".format(shop['location'], shop['type'], "\n ".join(item for item in [shop.get('item_0', None), shop.get('item_1', None), shop.get('item_2', None)] if item)) for shop in self.shops)) outfile.write('\n\nPlaythrough:\n\n') outfile.write('\n'.join(['%s: {\n%s\n}' % (sphere_nr, '\n'.join([' %s: %s' % (location, item) for (location, item) in sphere.items()])) for (sphere_nr, sphere) in self.playthrough.items()])) outfile.write('\n\nPaths:\n\n') diff --git a/Dungeons.py b/Dungeons.py index 7ec6f57699..747e20befa 100644 --- a/Dungeons.py +++ b/Dungeons.py @@ -26,7 +26,7 @@ def create_dungeons(world): TR = make_dungeon('Turtle Rock', ['Turtle Rock (Entrance)', 'Turtle Rock (First Section)', 'Turtle Rock (Chain Chomp Room)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Turtle Rock (Crystaroller Room)', 'Turtle Rock (Dark Room)', 'Turtle Rock (Eye Bridge)', 'Turtle Rock (Trinexx)'], ItemFactory('Big Key (Turtle Rock)'), ItemFactory(['Small Key (Turtle Rock)'] * 4), ItemFactory(['Map (Turtle Rock)', 'Compass (Turtle Rock)'])) GT = make_dungeon('Ganons Tower', ['Ganons Tower (Entrance)', 'Ganons Tower (Tile Room)', 'Ganons Tower (Compass Room)', 'Ganons Tower (Hookshot Room)', 'Ganons Tower (Map Room)', 'Ganons Tower (Firesnake Room)', 'Ganons Tower (Teleport Room)', 'Ganons Tower (Bottom)', 'Ganons Tower (Top)', 'Ganons Tower (Before Moldorm)', 'Ganons Tower (Moldorm)', 'Agahnim 2'], ItemFactory('Big Key (Ganons Tower)'), ItemFactory(['Small Key (Ganons Tower)'] * 4), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'])) - world.dungeons = [TR, ES, EP, DP, ToH, AT, PoD, TT, SW, IP, MM, GT, SP] + world.dungeons = [ES, EP, DP, ToH, AT, PoD, TT, SW, SP, IP, MM, TR, GT] def fill_dungeons(world): diff --git a/ItemList.py b/ItemList.py index 0eb8b906a9..1124c1090d 100644 --- a/ItemList.py +++ b/ItemList.py @@ -2,9 +2,12 @@ from collections import namedtuple import logging import random -from Items import ItemFactory -from Fill import FillError, fill_restrictive +from BaseClasses import Region, RegionType, Shop, ShopType, Location from Dungeons import get_dungeon_item_pool +from EntranceShuffle import connect_entrance +from Fill import FillError, fill_restrictive +from Items import ItemFactory + #This file sets the item pools for various modes. Timed modes and triforce hunt are enforced first, and then extra items are specified per mode to fill in the remaining space. #Some basic items that various modes require are placed here, including pendants and crystals. Medallion requirements for the two relevant entrances are also decided. @@ -264,9 +267,82 @@ def generate_itempool(world): set_up_shops(world) + if world.retro: + set_up_take_anys(world) + + create_dynamic_shop_locations(world) + # distribute crystals fill_prizes(world) +take_any_locations = [ + 'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut', + 'Fortune Teller (Light)', 'Lake Hylia Fortune Teller', 'Lumberjack House', 'Bonk Fairy (Light)', + 'Bonk Fairy (Dark)', 'Lake Hylia Healer Fairy', 'Swamp Healer Fairy', 'Desert Healer Fairy', + 'Dark Lake Hylia Healer Fairy', 'Dark Lake Hylia Ledge Healer Fairy', 'Dark Desert Healer Fairy', + 'Dark Death Mountain Healer Fairy', 'Long Fairy Cave', 'Good Bee Cave', '20 Rupee Cave', + 'Kakariko Gamble Game', 'Capacity Upgrade', '50 Rupee Cave', 'Lost Woods Gamble', 'Hookshot Fairy', + 'Palace of Darkness Hint', 'East Dark World Hint', 'Archery Game', 'Dark Lake Hylia Ledge Hint', + 'Dark Lake Hylia Ledge Spike Cave', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint', 'Dark Desert Hint'] + +def set_up_take_anys(world): + regions = random.sample(take_any_locations, 5) + + old_man_take_any = Region("Old Man Sword Cave", RegionType.Cave) + world.regions.append(old_man_take_any) + world.dynamic_regions.append(old_man_take_any) + + reg = regions.pop() + entrance = world.get_region(reg).entrances[0] + connect_entrance(world, entrance, old_man_take_any) + entrance.target = 0x58 + old_man_take_any.shop = Shop(old_man_take_any, 0x0112, ShopType.TakeAny, 0xE2, True) + world.shops.append(old_man_take_any.shop) + old_man_take_any.shop.active = True + + swords = [item for item in world.itempool if item.type == 'Sword'] + if swords: + sword = random.choice(swords) + world.itempool.remove(sword) + world.itempool.append(ItemFactory('Rupees (20)')) + old_man_take_any.shop.add_inventory(0, sword.name, 0, 1, create_location=True) + else: + old_man_take_any.shop.add_inventory(0, 'Rupees (300)', 0, 1) + + for num in range(4): + take_any = Region("Take-Any #{}".format(num+1), RegionType.Cave) + world.regions.append(take_any) + world.dynamic_regions.append(take_any) + + target, room_id = random.choice([(0x58, 0x0112), (0x60, 0x010F), (0x46, 0x011F)]) + reg = regions.pop() + entrance = world.get_region(reg).entrances[0] + connect_entrance(world, entrance, take_any) + entrance.target = target + take_any.shop = Shop(take_any, room_id, ShopType.TakeAny, 0xE3, True) + world.shops.append(take_any.shop) + take_any.shop.active = True + take_any.shop.add_inventory(0, 'Blue Potion', 0, 1) + take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 1) + + world.intialize_regions() + +def create_dynamic_shop_locations(world): + for shop in world.shops: + for i, item in enumerate(shop.inventory): + if item is None: + continue + if item['create_location']: + loc = Location("{} Item {}".format(shop.region.name, i+1), parent=shop.region) + shop.region.locations.append(loc) + world.dynamic_locations.append(loc) + + world.clear_location_cache() + + world.push_item(loc, ItemFactory(item['item']), False) + loc.event = True + + def fill_prizes(world, attempts=15): crystals = ItemFactory(['Red Pendant', 'Blue Pendant', 'Green Pendant', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 7', 'Crystal 5', 'Crystal 6']) crystal_locations = [world.get_location('Turtle Rock - Prize'), world.get_location('Eastern Palace - Prize'), world.get_location('Desert Palace - Prize'), world.get_location('Tower of Hera - Prize'), world.get_location('Palace of Darkness - Prize'), @@ -309,6 +385,7 @@ def set_up_shops(world): shop.active = True shop.add_inventory(0, 'Single Arrow', 80) shop.add_inventory(1, 'Small Key (Universal)', 100) + shop.add_inventory(2, 'Bombs (10)', 50) #special shop types diff --git a/Items.py b/Items.py index 3001f5df03..226b953656 100644 --- a/Items.py +++ b/Items.py @@ -52,11 +52,11 @@ item_table = {'Bow': (True, False, None, 0x0B, 'You have\nchosen the\narcher cla 'Bottle (Fairy)': (True, False, None, 0x3D, 'Save me and I will revive you', 'and the captive', 'the tingle kid', 'hostage for sale', 'fairy dust and shrooms', 'bottle boy has friend again'), 'Bottle (Bee)': (True, False, None, 0x3C, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again'), 'Bottle (Good Bee)': (True, False, None, 0x48, 'I will sting your foes a whole lot!', 'and the sparkle sting', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has beetor again'), - 'Master Sword': (True, False, None, 0x50, 'I beat barries and pigs alike', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'sword boy fights again'), - 'Tempered Sword': (True, False, None, 0x02, 'I stole the\nblacksmith\'s\njob!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again'), - 'Fighter Sword': (True, False, None, 0x49, 'A pathetic\nsword rests\nhere!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again'), - 'Golden Sword': (True, False, None, 0x03, 'The butter\nsword rests\nhere!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again'), - 'Progressive Sword': (True, False, None, 0x5E, 'a better copy\nof your sword\nfor your time', 'the unknown sword', 'sword-wielding kid', 'sword for sale', 'fungus for some slasher', 'sword boy fights again'), + 'Master Sword': (True, False, 'Sword', 0x50, 'I beat barries and pigs alike', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'sword boy fights again'), + 'Tempered Sword': (True, False, 'Sword', 0x02, 'I stole the\nblacksmith\'s\njob!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again'), + 'Fighter Sword': (True, False, 'Sword', 0x49, 'A pathetic\nsword rests\nhere!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again'), + 'Golden Sword': (True, False, 'Sword', 0x03, 'The butter\nsword rests\nhere!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again'), + 'Progressive Sword': (True, False, 'Sword', 0x5E, 'a better copy\nof your sword\nfor your time', 'the unknown sword', 'sword-wielding kid', 'sword for sale', 'fungus for some slasher', 'sword boy fights again'), 'Progressive Glove': (True, False, None, 0x61, 'a way to lift\nheavier things', 'and the lift upgrade', 'body-building kid', 'some glove for sale', 'fungus for gloves', 'body-building boy lifts again'), 'Silver Arrows': (True, False, None, 0x58, 'Do you fancy\nsilver tipped\narrows?', 'and the ganonsbane', 'ganon-killing kid', 'ganon doom for sale', 'fungus for pork', 'archer boy shines again'), 'Green Pendant': (True, False, 'Crystal', [0x04, 0x38, 0x62, 0x00, 0x69, 0x01], None, None, None, None, None, None), diff --git a/Main.py b/Main.py index f480e77354..bdfd96dc90 100644 --- a/Main.py +++ b/Main.py @@ -6,7 +6,7 @@ import logging import random import time -from BaseClasses import World, CollectionState, Item +from BaseClasses import World, CollectionState, Item, Region, Location, Entrance, Shop from Regions import create_regions, mark_light_world_regions from EntranceShuffle import link_entrances from Rom import patch_rom, Sprite, LocalRom, JsonRom @@ -158,15 +158,13 @@ def copy_world(world): create_regions(ret) create_dungeons(ret) - #TODO: copy_dynamic_regions_and_locations() # also adds some new shops + copy_dynamic_regions_and_locations(world, ret) for shop in world.shops: copied_shop = ret.get_region(shop.region.name).shop copied_shop.active = shop.active copied_shop.inventory = copy.copy(shop.inventory) - - # connect copied world for region in world.regions: copied_region = ret.get_region(region.name) @@ -195,6 +193,24 @@ def copy_world(world): return ret +def copy_dynamic_regions_and_locations(world, ret): + for region in world.dynamic_regions: + new_reg = Region(region.name, region.type) + ret.regions.append(new_reg) + ret.dynamic_regions.append(new_reg) + + # Note: ideally exits should be copied here, but the current use case (Take anys) do not require this + + if region.shop: + new_reg.shop = Shop(new_reg, region.shop.room_id, region.shop.type, region.shop.shopkeeper_config, region.shop.replaceable) + ret.shops.append(new_reg.shop) + + for location in world.dynamic_locations: + new_loc = Location(location.name, location.address, location.crystal, location.hint_text, location.parent_region) + new_reg = ret.get_region(location.parent_region.name) + new_reg.locations.append(new_loc) + + def create_playthrough(world): # create a copy as we will modify it old_world = world diff --git a/Rom.py b/Rom.py index a4e4e7a5ea..ce50641035 100644 --- a/Rom.py +++ b/Rom.py @@ -541,6 +541,13 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): else: overflow_replacement = GREEN_TWENTY_RUPEES + if world.difficulty in ['easy']: + rom.write_byte(0x180181, 0x03) # auto equip silvers on pickup and at ganon + elif world.retro and world.difficulty in ['hard','expert', 'insane']: #FIXME: this is temporary for v29 baserom + rom.write_byte(0x180181, 0x03) # auto equip silvers on pickup and at ganon + else: + rom.write_byte(0x180181, 0x01) # auto equip silvers on pickup + #Byrna residual magic cost rom.write_bytes(0x45C42, [0x04, 0x02, 0x01]) @@ -796,6 +803,7 @@ def patch_rom(world, rom, hashtable, beep='normal', color='red', sprite=None): rom.write_byte(0x180176, 0x0A if world.retro else 0x00) # wood arrow cost rom.write_byte(0x180178, 0x32 if world.retro else 0x00) # silver arrow cost rom.write_byte(0x301FC, 0xDA if world.retro else 0xE1) # rupees replace arrows under pots + rom.write_byte(0x30052, 0xDB if world.retro else 0xE2) # replace arrows in fish prize from bottle merchant rom.write_bytes(0xECB4E, [0xA9, 0x00, 0xEA, 0xEA] if world.retro else [0xAF, 0x77, 0xF3, 0x7E]) # Thief steals rupees instead of arrows rom.write_bytes(0xF0D96, [0xA9, 0x00, 0xEA, 0xEA] if world.retro else [0xAF, 0x77, 0xF3, 0x7E]) # Pikit steals rupees instead of arrows rom.write_bytes(0xEDA5, [0x35, 0x41] if world.retro else [0x43, 0x44]) # Chest game gives rupees instead of arrows diff --git a/Text.py b/Text.py index 1a6ae7fc3b..c0b508a66b 100644 --- a/Text.py +++ b/Text.py @@ -1083,7 +1083,7 @@ class RawMBTextMapper(CharTextMapper): "服": 0xFD, "月": 0xFE, "姫": 0xFF} - alpha_offset = 0x69 + alpha_offset = 0x49 number_offset = 0x70 @classmethod diff --git a/data/sprites/official/arrghus.1.zspr b/data/sprites/official/arrghus.2.zspr similarity index 98% rename from data/sprites/official/arrghus.1.zspr rename to data/sprites/official/arrghus.2.zspr index fd2eb5e4cd..2064009d3c 100644 Binary files a/data/sprites/official/arrghus.1.zspr and b/data/sprites/official/arrghus.2.zspr differ diff --git a/data/sprites/official/bigkey.1.zspr b/data/sprites/official/bigkey.1.zspr new file mode 100644 index 0000000000..eab4854e38 Binary files /dev/null and b/data/sprites/official/bigkey.1.zspr differ diff --git a/data/sprites/official/blacksmithlink.1.zspr b/data/sprites/official/blacksmithlink.1.zspr new file mode 100644 index 0000000000..e9aeb31aa3 Binary files /dev/null and b/data/sprites/official/blacksmithlink.1.zspr differ diff --git a/data/sprites/official/bob.1.zspr b/data/sprites/official/bob.1.zspr new file mode 100644 index 0000000000..25fc041084 Binary files /dev/null and b/data/sprites/official/bob.1.zspr differ diff --git a/data/sprites/official/boo.1.zspr b/data/sprites/official/boo-two.1.zspr similarity index 100% rename from data/sprites/official/boo.1.zspr rename to data/sprites/official/boo-two.1.zspr diff --git a/data/sprites/official/boo.2.zspr b/data/sprites/official/boo.2.zspr new file mode 100644 index 0000000000..24c74bde23 Binary files /dev/null and b/data/sprites/official/boo.2.zspr differ diff --git a/data/sprites/official/broccoli.1.zspr b/data/sprites/official/broccoli.1.zspr new file mode 100644 index 0000000000..e335df01e4 Binary files /dev/null and b/data/sprites/official/broccoli.1.zspr differ diff --git a/data/sprites/official/boy.1.zspr b/data/sprites/official/bsboy.1.zspr similarity index 100% rename from data/sprites/official/boy.1.zspr rename to data/sprites/official/bsboy.1.zspr diff --git a/data/sprites/official/girl.1.zspr b/data/sprites/official/bsgirl.1.zspr similarity index 100% rename from data/sprites/official/girl.1.zspr rename to data/sprites/official/bsgirl.1.zspr diff --git a/data/sprites/official/cheepcheep.1.zspr b/data/sprites/official/cheepcheep.1.zspr new file mode 100644 index 0000000000..a49545f208 Binary files /dev/null and b/data/sprites/official/cheepcheep.1.zspr differ diff --git a/data/sprites/official/conker.1.zspr b/data/sprites/official/conker.1.zspr new file mode 100644 index 0000000000..121d523330 Binary files /dev/null and b/data/sprites/official/conker.1.zspr differ diff --git a/data/sprites/official/cursor.1.zspr b/data/sprites/official/cursor.1.zspr new file mode 100644 index 0000000000..45bc973919 Binary files /dev/null and b/data/sprites/official/cursor.1.zspr differ diff --git a/data/sprites/official/darkzora.1.zspr b/data/sprites/official/darkzora.2.zspr similarity index 98% rename from data/sprites/official/darkzora.1.zspr rename to data/sprites/official/darkzora.2.zspr index 0540f4d915..fbb15c69f9 100644 Binary files a/data/sprites/official/darkzora.1.zspr and b/data/sprites/official/darkzora.2.zspr differ diff --git a/data/sprites/official/froglink.1.zspr b/data/sprites/official/froglink.2.zspr similarity index 96% rename from data/sprites/official/froglink.1.zspr rename to data/sprites/official/froglink.2.zspr index b249832265..1932df067a 100644 Binary files a/data/sprites/official/froglink.1.zspr and b/data/sprites/official/froglink.2.zspr differ diff --git a/data/sprites/official/garfield.1.zspr b/data/sprites/official/garfield.2.zspr similarity index 94% rename from data/sprites/official/garfield.1.zspr rename to data/sprites/official/garfield.2.zspr index e28c170617..6ca890e850 100644 Binary files a/data/sprites/official/garfield.1.zspr and b/data/sprites/official/garfield.2.zspr differ diff --git a/data/sprites/official/hyruleknight.1.zspr b/data/sprites/official/hyruleknight.1.zspr new file mode 100644 index 0000000000..a8815bc373 Binary files /dev/null and b/data/sprites/official/hyruleknight.1.zspr differ diff --git a/data/sprites/official/jogurt.1.zspr b/data/sprites/official/jogurt.1.zspr new file mode 100644 index 0000000000..b229060c69 Binary files /dev/null and b/data/sprites/official/jogurt.1.zspr differ diff --git a/data/sprites/official/linkhatcolor.1.zspr b/data/sprites/official/linkhatcolor.1.zspr new file mode 100644 index 0000000000..af53898dbc Binary files /dev/null and b/data/sprites/official/linkhatcolor.1.zspr differ diff --git a/data/sprites/official/linktuniccolor.1.zspr b/data/sprites/official/linktuniccolor.1.zspr new file mode 100644 index 0000000000..305a9f8f9d Binary files /dev/null and b/data/sprites/official/linktuniccolor.1.zspr differ diff --git a/data/sprites/official/mangalink.1.zspr b/data/sprites/official/mangalink.1.zspr new file mode 100644 index 0000000000..adb57b9991 Binary files /dev/null and b/data/sprites/official/mangalink.1.zspr differ diff --git a/data/sprites/official/maplequeen.1.zspr b/data/sprites/official/maplequeen.2.zspr similarity index 98% rename from data/sprites/official/maplequeen.1.zspr rename to data/sprites/official/maplequeen.2.zspr index e26032a0ea..35b7deeca8 100644 Binary files a/data/sprites/official/maplequeen.1.zspr and b/data/sprites/official/maplequeen.2.zspr differ diff --git a/data/sprites/official/mario-classic.1.zspr b/data/sprites/official/mario-classic.2.zspr similarity index 99% rename from data/sprites/official/mario-classic.1.zspr rename to data/sprites/official/mario-classic.2.zspr index 60ea7f94af..6443e32749 100644 Binary files a/data/sprites/official/mario-classic.1.zspr and b/data/sprites/official/mario-classic.2.zspr differ diff --git a/data/sprites/official/mariocappy.1.zspr b/data/sprites/official/mariocappy.1.zspr new file mode 100644 index 0000000000..b888396d2f Binary files /dev/null and b/data/sprites/official/mariocappy.1.zspr differ diff --git a/data/sprites/official/missingno.1.zspr b/data/sprites/official/missingno.1.zspr new file mode 100644 index 0000000000..68e61b9b02 Binary files /dev/null and b/data/sprites/official/missingno.1.zspr differ diff --git a/data/sprites/official/mog.1.zspr b/data/sprites/official/mog.2.zspr similarity index 99% rename from data/sprites/official/mog.1.zspr rename to data/sprites/official/mog.2.zspr index 2ef1dfc008..a6ed2225ec 100644 Binary files a/data/sprites/official/mog.1.zspr and b/data/sprites/official/mog.2.zspr differ diff --git a/data/sprites/official/navi.1.zspr b/data/sprites/official/navi.1.zspr new file mode 100644 index 0000000000..4621bf4a04 Binary files /dev/null and b/data/sprites/official/navi.1.zspr differ diff --git a/data/sprites/official/neslink.1.zspr b/data/sprites/official/neslink.1.zspr new file mode 100644 index 0000000000..805b316263 Binary files /dev/null and b/data/sprites/official/neslink.1.zspr differ diff --git a/data/sprites/official/oldman.1.zspr b/data/sprites/official/oldman.2.zspr similarity index 98% rename from data/sprites/official/oldman.1.zspr rename to data/sprites/official/oldman.2.zspr index 1a45e5c7d3..1d47cdacc9 100644 Binary files a/data/sprites/official/oldman.1.zspr and b/data/sprites/official/oldman.2.zspr differ diff --git a/data/sprites/official/pikachu.1.zspr b/data/sprites/official/pikachu.1.zspr new file mode 100644 index 0000000000..0b8a88c48b Binary files /dev/null and b/data/sprites/official/pikachu.1.zspr differ diff --git a/data/sprites/official/pinkribbonlink.1.zspr b/data/sprites/official/pinkribbonlink.2.zspr similarity index 99% rename from data/sprites/official/pinkribbonlink.1.zspr rename to data/sprites/official/pinkribbonlink.2.zspr index 5e0fc9077c..ba516f1854 100644 Binary files a/data/sprites/official/pinkribbonlink.1.zspr and b/data/sprites/official/pinkribbonlink.2.zspr differ diff --git a/data/sprites/official/santalink.1.zspr b/data/sprites/official/santalink.2.zspr similarity index 99% rename from data/sprites/official/santalink.1.zspr rename to data/sprites/official/santalink.2.zspr index 2495f0c0e0..0e78fedb34 100644 Binary files a/data/sprites/official/santalink.1.zspr and b/data/sprites/official/santalink.2.zspr differ diff --git a/data/sprites/official/shadowsaku.1.zspr b/data/sprites/official/shadowsaku.2.zspr similarity index 98% rename from data/sprites/official/shadowsaku.1.zspr rename to data/sprites/official/shadowsaku.2.zspr index 427017553b..8972f9f266 100644 Binary files a/data/sprites/official/shadowsaku.1.zspr and b/data/sprites/official/shadowsaku.2.zspr differ diff --git a/data/sprites/official/soldiersprite.1.zspr b/data/sprites/official/soldiersprite.1.zspr new file mode 100644 index 0000000000..d5e8ee356d Binary files /dev/null and b/data/sprites/official/soldiersprite.1.zspr differ diff --git a/data/sprites/official/squirtle.1.zspr b/data/sprites/official/squirtle.1.zspr new file mode 100644 index 0000000000..274bf1c760 Binary files /dev/null and b/data/sprites/official/squirtle.1.zspr differ diff --git a/data/sprites/official/superbunny.1.zspr b/data/sprites/official/superbunny.2.zspr similarity index 98% rename from data/sprites/official/superbunny.1.zspr rename to data/sprites/official/superbunny.2.zspr index f55713692c..b842d1c35f 100644 Binary files a/data/sprites/official/superbunny.1.zspr and b/data/sprites/official/superbunny.2.zspr differ diff --git a/data/sprites/official/supermeatboy.1.zspr b/data/sprites/official/supermeatboy.1.zspr new file mode 100644 index 0000000000..ad4368bb5f Binary files /dev/null and b/data/sprites/official/supermeatboy.1.zspr differ diff --git a/data/sprites/official/terra.1.zspr b/data/sprites/official/terra.1.zspr new file mode 100644 index 0000000000..e24ca87aad Binary files /dev/null and b/data/sprites/official/terra.1.zspr differ diff --git a/data/sprites/official/tile.1.zspr b/data/sprites/official/tile.1.zspr deleted file mode 100644 index 98820f9ebb..0000000000 Binary files a/data/sprites/official/tile.1.zspr and /dev/null differ diff --git a/data/sprites/official/tile.2.zspr b/data/sprites/official/tile.2.zspr new file mode 100644 index 0000000000..38332bb06f Binary files /dev/null and b/data/sprites/official/tile.2.zspr differ diff --git a/data/sprites/official/toad.1.zspr b/data/sprites/official/toad.2.zspr similarity index 98% rename from data/sprites/official/toad.1.zspr rename to data/sprites/official/toad.2.zspr index a051ed9ec4..6abca2d71e 100644 Binary files a/data/sprites/official/toad.1.zspr and b/data/sprites/official/toad.2.zspr differ diff --git a/data/sprites/official/trogdor.1.zspr b/data/sprites/official/trogdor.1.zspr new file mode 100644 index 0000000000..b37191acc3 Binary files /dev/null and b/data/sprites/official/trogdor.1.zspr differ diff --git a/data/sprites/official/wizzrobe.1.zspr b/data/sprites/official/wizzrobe.2.zspr similarity index 98% rename from data/sprites/official/wizzrobe.1.zspr rename to data/sprites/official/wizzrobe.2.zspr index f8938bdeb3..f79195d239 100644 Binary files a/data/sprites/official/wizzrobe.1.zspr and b/data/sprites/official/wizzrobe.2.zspr differ diff --git a/data/sprites/official/zora.1.zspr b/data/sprites/official/zora.1.zspr deleted file mode 100644 index ca41792125..0000000000 Binary files a/data/sprites/official/zora.1.zspr and /dev/null differ diff --git a/data/sprites/official/zora.2.zspr b/data/sprites/official/zora.2.zspr new file mode 100644 index 0000000000..1ca568e113 Binary files /dev/null and b/data/sprites/official/zora.2.zspr differ