From e1f85efbef1eed79a60782cee10a4b30faa89f40 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 13 Apr 2022 13:31:47 -0600 Subject: [PATCH 01/25] Fixes for overworld_map map mode --- Main.py | 2 +- RELEASENOTES.md | 3 +++ Rom.py | 11 ++++++++--- data/base2current.bps | Bin 82182 -> 86427 bytes 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Main.py b/Main.py index 22c73a50..913f79a8 100644 --- a/Main.py +++ b/Main.py @@ -31,7 +31,7 @@ from Utils import output_path, parse_player_names from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config -__version__ = '1.0.0.2-u' +__version__ = '1.0.0.3-u' from source.classes.BabelFish import BabelFish diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 67394d00..9a86fec7 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -114,6 +114,9 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o ## Notes and Bug Fixes +* 1.0.0.3 + * overworld_map=map mode fixed. Location of dungeons with maps are not shown until map is retrieved. (Dungeon that do not have map like Castle Tower are simply never shown) + * Aga2 completion on overworld_map now tied to boss defeat flag instead of pyramid hole being opened (fast ganon fix) * 1.0.0.2 * Include 1.0.1 fixes * District hint rework diff --git a/Rom.py b/Rom.py index ed4c208a..4f219949 100644 --- a/Rom.py +++ b/Rom.py @@ -32,7 +32,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '4e4d7c1352c6b85dfe0d3f19aa2afae2' +RANDOMIZERBASEHASH = '7f28f440ac83d3ddca458dfc64e87978' class JsonRom(object): @@ -1412,8 +1412,13 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): for idx, x_map in enumerate(x_map_position_generic): rom.write_bytes(0x53df6+idx*2, int16_as_bytes(x_map)) rom.write_bytes(0x53e16+idx*2, int16_as_bytes(0xFC0)) - if world.compassshuffle[player] and world.overworld_map[player] == 'compass': - compass_mode |= 0x40 # compasses are wild + if world.overworld_map[player] == 'compass': + compass_mode |= 0x20 # check for compass + if world.compassshuffle[player]: + compass_mode |= 0x40 # compasses are wild + elif world.overworld_map[player] == 'map': + if world.mapshuffle[player]: + compass_mode |= 0x40 # maps are wild for dungeon, portal_list in dungeon_portals.items(): ow_map_index = dungeon_table[dungeon].map_index if len(portal_list) == 1: diff --git a/data/base2current.bps b/data/base2current.bps index bb57b114eaec0c3e0c86bda2e555fbd90e5c7614..57aa7d1d9fd0839bb5c7e696ba8c3e41a007119f 100644 GIT binary patch delta 18500 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 Tf!>#QKmmsc&{Hc#^oN|&=w!C2 delta 14098 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%0DW<6>=JPuUm#o?Jjzjkt9 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 YUbbcPkBog1USQvqqV4GS`0Td-18E*c-~a#s From c7de8dad79d3897ceb969cfe53bee86ef1c1c427 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 13 Apr 2022 14:27:45 -0600 Subject: [PATCH 02/25] Minor bug in dungeon_only algoithm (also affected fallback grouping in major_only and vanilla) --- RELEASENOTES.md | 1 + source/item/FillUtil.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9a86fec7..4a9de8b2 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -117,6 +117,7 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o * 1.0.0.3 * overworld_map=map mode fixed. Location of dungeons with maps are not shown until map is retrieved. (Dungeon that do not have map like Castle Tower are simply never shown) * Aga2 completion on overworld_map now tied to boss defeat flag instead of pyramid hole being opened (fast ganon fix) + * Minor issue in dungeon_only algorithm fixed (minorly affected major_only keyshuffle and vanilla fallbacks) * 1.0.0.2 * Include 1.0.1 fixes * District hint rework diff --git a/source/item/FillUtil.py b/source/item/FillUtil.py index 170d3a13..a716fbd8 100644 --- a/source/item/FillUtil.py +++ b/source/item/FillUtil.py @@ -699,7 +699,7 @@ mode_grouping = { 'Sewers - Dark Cross', 'Desert Palace - Torch', 'Tower of Hera - Basement Cage', 'Castle Tower - Room 03', 'Castle Tower - Dark Maze', 'Palace of Darkness - Stalfos Basement', 'Palace of Darkness - Dark Basement - Right', - 'Palace of Darkness - Dark Maze - Bottom', 'Palace of Darkness - Shooter Room', + 'Palace of Darkness - Harmless Hellway', 'Palace of Darkness - Shooter Room', 'Palace of Darkness - The Arena - Bridge', 'Palace of Darkness - The Arena - Ledge', "Thieves' Town - Blind's Cell", 'Skull Woods - Bridge Room', 'Ice Palace - Spike Room', 'Skull Woods - Pot Prison', 'Skull Woods - Pinball Room', 'Misery Mire - Spike Chest', From 606148bdbebf1a1067f59d456ee38611bec0cf87 Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 19 Apr 2022 14:34:44 -0600 Subject: [PATCH 03/25] Minor map feature --- data/base2current.bps | Bin 86427 -> 86436 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/base2current.bps b/data/base2current.bps index 57aa7d1d9fd0839bb5c7e696ba8c3e41a007119f..139e9b03e655c8aaa67576c99f3084222e06094b 100644 GIT binary patch delta 282 zcmV+#0pot>;*;MDG=HIXz6#0z@K(QfvVws| zngoHBKKj~<3aXO=fPol~FMy570q_uy9Ds^tfQy&zhJpH$MV^`946p-CEx^(ws;%0o z0FNM4e;~ubkR*>CfRzaWk04ZkmU(=h;m`@croIaB3{1emzoxzl&;v}s!5{&`kP4F; zf`I~)f{RUnm6M4L8v#O-r44K>0m6_SfE~Y%CmaDXsyEP;VYOr3>*2A5Z}kPfmq7A$y!y-2T0fH2Sn gXh}eT0cdNb8Bjr2eP{lJ>HD?*IS* delta 242 zcmVot>+LPZ5G(drOvVws|ngoHBKKj~< z3aXRxff$b;fQ`uk@DPs-fQn^+fp+$Sf%=j~o|)hbumemjz|thDt=g#ok04ZkAiI-X z4I2`;!M~=y3eW>gxWOR#!H^1*3X_QqBmp{;t_^G~`N5DKfE~Y*2A4;(nGUiz s794nky-2T0fH2SnXh}eT0cdNb8 Date: Tue, 19 Apr 2022 14:40:27 -0600 Subject: [PATCH 04/25] Documentation update --- RELEASENOTES.md | 2 +- Rom.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4a9de8b2..d6e8ebaf 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -57,7 +57,7 @@ These districts are chosen at random and then filled with major items. If a loca In entrance shuffle, what is shuffled to the entrances is considered instead of where the interior was originally. For example, if Blind's Hut is shuffled to the Dam, then the 5 chests in Blind's Hut are part of Central Hyrule instead of Kakariko. -Bombos Table, Lake Hylia Island, Bumper Cave Ledge, the Floating Island, Cave 45, the Graveyard Cave, Checkerboard Cave and Mimic Cave are considered part of the dark world region that you mirror from to get there (except in inverted where these are only accessible in the Light World). Note that Spectacle Rock is always part of light Death Mountain. +Note: Bombos Tablet, Lake Hylia Island, Bumper Cave Ledge, the Floating Island, Cave 45, the Graveyard Cave, Checkerboard Cave and Mimic Cave are considered part of the light world region rather than the dark world region you mirror from. In multiworld, the districts chosen apply to all players. diff --git a/Rom.py b/Rom.py index 4f219949..46231dd8 100644 --- a/Rom.py +++ b/Rom.py @@ -32,7 +32,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '7f28f440ac83d3ddca458dfc64e87978' +RANDOMIZERBASEHASH = '02967596217f7cae048e4fbf727762d8' class JsonRom(object): From abf57e02557cb68399d3e774be326c6bc5dcbea2 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 20 Apr 2022 09:08:55 -0600 Subject: [PATCH 05/25] Fix for a map bug (link not shown when eastern prize is) --- Rom.py | 2 +- data/base2current.bps | Bin 86436 -> 86438 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 46231dd8..ca416cbb 100644 --- a/Rom.py +++ b/Rom.py @@ -32,7 +32,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '02967596217f7cae048e4fbf727762d8' +RANDOMIZERBASEHASH = 'a2dddb51072556881537dadd7e461c3d' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 139e9b03e655c8aaa67576c99f3084222e06094b..d8e7300e8b0b6587aa5a356b81554e9f96296217 100644 GIT binary patch delta 277 zcmV+w0qXvwqXnj;1+X~*1X_Kig0npVoC^j3!H@$?Xj~sxCWq^y9?uNDc+UOuI#roh3umemjz|v}pt=g#ok04Zk zAjFeg4I4MX!M~=y3eW>g!NDK`!jKA+9D;!YlY)y+fR*rk$pX+8n?`^sfCk_Luxx+` z;0my2-~*6izeAI*4Qwm|!jK(+9lw^o3h)=&zfi&os=s9OejgO{e)>OM!U~raJBpRB zJAg3oIhzubMh-y|P?d>qfG}_@fq_U&orQn~mszu!4zf5FE_j2zNUutOFwg~PNkD)B bXltb#mmz~;N4H@|0Xqr^CwJ#kp%H2x{Xutp delta 275 zcmV+u0qp*!qXnd+1+X~*1dM!hgR?yWoC^m3z>ot>;*;MDJ3>~!cd~+kMw$eHl|K5~ ziVCWe0)T-Sk1v3Y$pP>Xj~sxCWq^y9?uLQ-l0}}G;0&+>OfA6DB&x02sQ`~4RDU4D zlU@xQH^9NaroIZ$15CidAOXUV3X>XwfdZ3)i%o!)@O;Sv&=#9SfGL0m-~+I1fC%6U zux8)`kYc|=lduhJECIrh9e^Fbmc9z`7uvs1!V0RtWb=L>6!d=jKU~5JmlHdRm9IO1 zFz`8>5R*s_K@wDziEw~0a4dm=NKBoDfCiUWvzrdGI2J5;gS|+vN`NrX1!ze?fB|T0 Zr5l$YgJVaxV@Cly3J6zpuB85`1(FJXcbfnJ From 163988ca1b2defefc2ed622cd6da6a62b83169e8 Mon Sep 17 00:00:00 2001 From: cassidoxa Date: Wed, 20 Apr 2022 22:00:05 -0400 Subject: [PATCH 06/25] New SRAM changes --- InitialSram.py | 252 ++++++++++++++++++++++++++++++++++++++++++ Items.py | 1 + Rom.py | 213 +++++++---------------------------- Utils.py | 5 + data/base2current.bps | Bin 85671 -> 85800 bytes 5 files changed, 300 insertions(+), 171 deletions(-) create mode 100644 InitialSram.py diff --git a/InitialSram.py b/InitialSram.py new file mode 100644 index 00000000..7a1ccba4 --- /dev/null +++ b/InitialSram.py @@ -0,0 +1,252 @@ +from dataclasses import dataclass, field + +from BaseClasses import CollectionState +from Utils import count_set_bits + +SRAM_SIZE = 0x500 +ROOM_DATA = 0x000 +OVERWORLD_DATA = 0x280 + +def _new_default_sram(): + sram_buf = [0x00] * 0x500 + sram_buf[ROOM_DATA+0x20D] = 0xF0 + sram_buf[ROOM_DATA+0x20F] = 0xF0 + sram_buf[0x379] = 0x68 + sram_buf[0x401] = 0xFF + sram_buf[0x402] = 0xFF + return sram_buf + +@dataclass +class InitialSram: + _initial_sram_bytes: list[int] = field(default_factory=_new_default_sram) + + def _set_value(self, idx: int, val:int): + if idx > SRAM_SIZE: + raise IndexError('SRAM index out of bounds: {idx}') + if not (-1 < val < 256): + raise ValueError('SRAM value must be between 0 and 255: {val}') + self._initial_sram_bytes[idx] = val + + def _or_value(self, idx: int, val:int): + if idx > SRAM_SIZE: + raise IndexError('SRAM index out of bounds: {idx}') + if not (-1 < val < 256): + raise ValueError('SRAM value must be between 0 and 255: {val}') + self._initial_sram_bytes[idx] |= val + + def pre_open_aga_curtains(self): + self._or_value(ROOM_DATA+0x61, 0x80) + + def pre_open_skullwoods_curtains(self): + self._or_value(ROOM_DATA+0x93, 0x80) + + def pre_open_lumberjack(self): + self._or_value(OVERWORLD_DATA+0x02, 0x20) + + def pre_open_castle_gate(self): + self._or_value(OVERWORLD_DATA+0x1B, 0x20) + + def pre_open_ganons_tower(self): + self._or_value(OVERWORLD_DATA+0x43, 0x20) + + def pre_open_pyramid_hole(self): + self._or_value(OVERWORLD_DATA+0x5B, 0x20) + + def set_starting_equipment(self, world: object, player: int): + equip = [0] * (0x340 + 0x4F) + equip[0x36C] = 0x18 + equip[0x36D] = 0x18 + equip[0x379] = 0x68 + if world.bombbag[player]: + starting_max_bombs = 0 + else: + starting_max_bombs = 10 + starting_max_arrows = 30 + starting_bomb_cap_upgrades = 0 + starting_arrow_cap_upgrades = 0 + starting_bombs = 0 + starting_arrows = 0 + + startingstate = CollectionState(world) + + if startingstate.has('Bow', player): + equip[0x340] = 3 if startingstate.has('Silver Arrows', player) else 1 + equip[0x38E] |= 0x20 # progressive flag to get the correct hint in all cases + if not world.retro[player]: + equip[0x38E] |= 0x80 + if startingstate.has('Silver Arrows', player): + equip[0x38E] |= 0x40 + + if startingstate.has('Titans Mitts', player): + equip[0x354] = 2 + elif startingstate.has('Power Glove', player): + equip[0x354] = 1 + + if startingstate.has('Golden Sword', player): + equip[0x359] = 4 + elif startingstate.has('Tempered Sword', player): + equip[0x359] = 3 + elif startingstate.has('Master Sword', player): + equip[0x359] = 2 + elif startingstate.has('Fighter Sword', player): + equip[0x359] = 1 + + if startingstate.has('Mirror Shield', player): + equip[0x35A] = 3 + elif startingstate.has('Red Shield', player): + equip[0x35A] = 2 + elif startingstate.has('Blue Shield', player): + equip[0x35A] = 1 + + if startingstate.has('Red Mail', player): + equip[0x35B] = 2 + elif startingstate.has('Blue Mail', player): + equip[0x35B] = 1 + + if startingstate.has('Magic Upgrade (1/4)', player): + equip[0x37B] = 2 + equip[0x36E] = 0x80 + elif startingstate.has('Magic Upgrade (1/2)', player): + equip[0x37B] = 1 + equip[0x36E] = 0x80 + + for item in world.precollected_items: + if item.player != player: + continue + + if item.name in ['Bow', 'Silver Arrows', 'Progressive Bow', 'Progressive Bow (Alt)', + 'Titans Mitts', 'Power Glove', 'Progressive Glove', + 'Golden Sword', 'Tempered Sword', 'Master Sword', 'Fighter Sword', 'Progressive Sword', + 'Mirror Shield', 'Red Shield', 'Blue Shield', 'Progressive Shield', + 'Red Mail', 'Blue Mail', 'Progressive Armor', + 'Magic Upgrade (1/4)', 'Magic Upgrade (1/2)']: + continue + + set_table = {'Book of Mudora': (0x34E, 1), 'Hammer': (0x34B, 1), 'Bug Catching Net': (0x34D, 1), 'Hookshot': (0x342, 1), 'Magic Mirror': (0x353, 2), + 'Cape': (0x352, 1), 'Lamp': (0x34A, 1), 'Moon Pearl': (0x357, 1), 'Cane of Somaria': (0x350, 1), 'Cane of Byrna': (0x351, 1), + 'Fire Rod': (0x345, 1), 'Ice Rod': (0x346, 1), 'Bombos': (0x347, 1), 'Ether': (0x348, 1), 'Quake': (0x349, 1)} + or_table = {'Green Pendant': (0x374, 0x04), 'Red Pendant': (0x374, 0x01), 'Blue Pendant': (0x374, 0x02), + 'Crystal 1': (0x37A, 0x02), 'Crystal 2': (0x37A, 0x10), 'Crystal 3': (0x37A, 0x40), 'Crystal 4': (0x37A, 0x20), + 'Crystal 5': (0x37A, 0x04), 'Crystal 6': (0x37A, 0x01), 'Crystal 7': (0x37A, 0x08), + 'Big Key (Eastern Palace)': (0x367, 0x20), 'Compass (Eastern Palace)': (0x365, 0x20), 'Map (Eastern Palace)': (0x369, 0x20), + 'Big Key (Desert Palace)': (0x367, 0x10), 'Compass (Desert Palace)': (0x365, 0x10), 'Map (Desert Palace)': (0x369, 0x10), + 'Big Key (Tower of Hera)': (0x366, 0x20), 'Compass (Tower of Hera)': (0x364, 0x20), 'Map (Tower of Hera)': (0x368, 0x20), + 'Big Key (Escape)': (0x367, 0xC0), 'Compass (Escape)': (0x365, 0xC0), 'Map (Escape)': (0x369, 0xC0), + 'Big Key (Agahnims Tower)': (0x367, 0x08), 'Compass (Agahnims Tower)': (0x365, 0x08), 'Map (Agahnims Tower)': (0x369, 0x08), + 'Big Key (Palace of Darkness)': (0x367, 0x02), 'Compass (Palace of Darkness)': (0x365, 0x02), 'Map (Palace of Darkness)': (0x369, 0x02), + 'Big Key (Thieves Town)': (0x366, 0x10), 'Compass (Thieves Town)': (0x364, 0x10), 'Map (Thieves Town)': (0x368, 0x10), + 'Big Key (Skull Woods)': (0x366, 0x80), 'Compass (Skull Woods)': (0x364, 0x80), 'Map (Skull Woods)': (0x368, 0x80), + 'Big Key (Swamp Palace)': (0x367, 0x04), 'Compass (Swamp Palace)': (0x365, 0x04), 'Map (Swamp Palace)': (0x369, 0x04), + 'Big Key (Ice Palace)': (0x366, 0x40), 'Compass (Ice Palace)': (0x364, 0x40), 'Map (Ice Palace)': (0x368, 0x40), + 'Big Key (Misery Mire)': (0x367, 0x01), 'Compass (Misery Mire)': (0x365, 0x01), 'Map (Misery Mire)': (0x369, 0x01), + 'Big Key (Turtle Rock)': (0x366, 0x08), 'Compass (Turtle Rock)': (0x364, 0x08), 'Map (Turtle Rock)': (0x368, 0x08), + 'Big Key (Ganons Tower)': (0x366, 0x04), 'Compass (Ganons Tower)': (0x364, 0x04), 'Map (Ganons Tower)': (0x368, 0x04)} + set_or_table = {'Flippers': (0x356, 1, 0x379, 0x02),'Pegasus Boots': (0x355, 1, 0x379, 0x04), + 'Shovel': (0x34C, 1, 0x38C, 0x04), 'Ocarina': (0x34C, 3, 0x38C, 0x01), + 'Mushroom': (0x344, 1, 0x38C, 0x20 | 0x08), 'Magic Powder': (0x344, 2, 0x38C, 0x10), + 'Blue Boomerang': (0x341, 1, 0x38C, 0x80), 'Red Boomerang': (0x341, 2, 0x38C, 0x40)} + keys = {'Small Key (Eastern Palace)': [0x37E], 'Small Key (Desert Palace)': [0x37F], + 'Small Key (Tower of Hera)': [0x386], + 'Small Key (Agahnims Tower)': [0x380], 'Small Key (Palace of Darkness)': [0x382], + 'Small Key (Thieves Town)': [0x387], + 'Small Key (Skull Woods)': [0x384], 'Small Key (Swamp Palace)': [0x381], + 'Small Key (Ice Palace)': [0x385], + 'Small Key (Misery Mire)': [0x383], 'Small Key (Turtle Rock)': [0x388], + 'Small Key (Ganons Tower)': [0x389], + 'Small Key (Universal)': [0x38B], 'Small Key (Escape)': [0x37C, 0x37D]} + bottles = {'Bottle': 2, 'Bottle (Red Potion)': 3, 'Bottle (Green Potion)': 4, 'Bottle (Blue Potion)': 5, + 'Bottle (Fairy)': 6, 'Bottle (Bee)': 7, 'Bottle (Good Bee)': 8} + rupees = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)': 50, 'Rupees (100)': 100, 'Rupees (300)': 300} + bomb_caps = {'Bomb Upgrade (+5)': 5, 'Bomb Upgrade (+10)': 10} + arrow_caps = {'Arrow Upgrade (+5)': 5, 'Arrow Upgrade (+10)': 10} + bombs = {'Single Bomb': 1, 'Bombs (3)': 3, 'Bombs (10)': 10} + arrows = {'Single Arrow': 1, 'Arrows (10)': 10} + + if item.name in set_table: + equip[set_table[item.name][0]] = set_table[item.name][1] + elif item.name in or_table: + equip[or_table[item.name][0]] |= or_table[item.name][1] + elif item.name in set_or_table: + equip[set_or_table[item.name][0]] = set_or_table[item.name][1] + equip[set_or_table[item.name][2]] |= set_or_table[item.name][3] + elif item.name in keys: + for address in keys[item.name]: + equip[address] = min(equip[address] + 1, 99) + elif item.name in bottles: + if equip[0x34F] < world.difficulty_requirements[player].progressive_bottle_limit: + equip[0x35C + equip[0x34F]] = bottles[item.name] + equip[0x34F] += 1 + elif item.name in rupees: + equip[0x360:0x362] = list(min(equip[0x360] + (equip[0x361] << 8) + rupees[item.name], 9999).to_bytes(2, byteorder='little', signed=False)) + equip[0x362:0x364] = list(min(equip[0x362] + (equip[0x363] << 8) + rupees[item.name], 9999).to_bytes(2, byteorder='little', signed=False)) + elif item.name in bomb_caps: + starting_bomb_cap_upgrades += bomb_caps[item.name] + elif item.name in arrow_caps: + starting_arrow_cap_upgrades += arrow_caps[item.name] + elif item.name in bombs: + starting_bombs += bombs[item.name] + elif item.name in arrows: + if world.retro[player]: + equip[0x38E] |= 0x80 + starting_arrows = 1 + else: + starting_arrows += arrows[item.name] + elif item.name in ['Piece of Heart', 'Boss Heart Container', 'Sanctuary Heart Container']: + if item.name == 'Piece of Heart': + equip[0x36B] = (equip[0x36B] + 1) % 4 + if item.name != 'Piece of Heart' or equip[0x36B] == 0: + equip[0x36C] = min(equip[0x36C] + 0x08, 0xA0) + equip[0x36D] = min(equip[0x36D] + 0x08, 0xA0) + else: + raise RuntimeError(f'Unsupported item in starting equipment: {item.name}') + + equip[0x370] = min(starting_bomb_cap_upgrades, 50) + equip[0x371] = min(starting_arrow_cap_upgrades, 70) + equip[0x343] = min(starting_bombs, (equip[0x370] + starting_max_bombs)) + equip[0x377] = min(starting_arrows, (equip[0x371] + starting_max_arrows)) + + # Assertion and copy equip to initial_sram_bytes + assert equip[:0x340] == [0] * 0x340 + self._initial_sram_bytes[0x340:0x38F] = equip[0x340:0x38F] + + # Set counters and highest equipment values + self._initial_sram_bytes[0x471] = count_set_bits(self._initial_sram_bytes[0x37A]) + self._initial_sram_bytes[0x429] = count_set_bits(self._initial_sram_bytes[0x374]) + self._initial_sram_bytes[0x417] = self._initial_sram_bytes[0x359] + self._initial_sram_bytes[0x422] = self._initial_sram_bytes[0x35A] + self._initial_sram_bytes[0x46E] = self._initial_sram_bytes[0x35B] + + if world.swords[player] == "swordless": + self.__initial_sram_bytes[0x359] = 0xFF + self.__initial_sram_bytes[0x417] = 0x00 + + def set_starting_rupees(self, rupees: int): + if not (-1 < rupees < 10000): + raise ValueError("Starting rupees must be between 0 and 9999") + self._initial_sram_bytes[0x362] = self._initial_sram_bytes[0x360] = rupees & 0xFF + self._initial_sram_bytes[0x363] = self._initial_sram_bytes[0x361] = rupees >> 8 + + def set_progress_indicator(self, indicator: int): + self._set_value(0x3C5, indicator) + + def set_progress_flags(self, flags: int): + self._set_value(0x3C6, flags) + + def set_starting_entrance(self, entrance: int): + self._set_value(0x3C8, entrance) + + def set_starting_timer(self, seconds: int): + timer = (seconds * 60).to_bytes(4, "little") + self._initial_sram_bytes[0x454] = timer[0] + self._initial_sram_bytes[0x455] = timer[1] + self._initial_sram_bytes[0x456] = timer[2] + self._initial_sram_bytes[0x457] = timer[3] + + def set_swordless_curtains(self): + self._or_value(ROOM_DATA+0x61, 0x80) + self._or_value(ROOM_DATA+0x93, 0x80) + + def get_initial_sram(self): + assert len(self._initial_sram_bytes) == SRAM_SIZE + + return self._initial_sram_bytes[:] diff --git a/Items.py b/Items.py index c88bccf7..f8bc7a85 100644 --- a/Items.py +++ b/Items.py @@ -57,6 +57,7 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche 'Master Sword': (True, False, 'Sword', 0x50, 100, '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', 'the Master Sword'), 'Tempered Sword': (True, False, 'Sword', 0x02, 150, 'I stole the\nblacksmith\'s\njob!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again', 'the Tempered Sword'), 'Fighter Sword': (True, False, 'Sword', 0x49, 50, 'A pathetic\nsword rests\nhere!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again', 'the small sword'), + 'Sword and Shield': (True, False, 'Sword', 0x00, 'An uncle\nsword rests\nhere!', 'the sword and shield', 'sword and shield-wielding kid', 'training set for sale', 'fungus for training set', 'sword and shield boy fights again', 'the small sword and shield'), 'Golden Sword': (True, False, 'Sword', 0x03, 200, 'The butter\nsword rests\nhere!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again', 'the Golden Sword'), 'Progressive Sword': (True, False, 'Sword', 0x5E, 150, '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', 'a sword'), 'Progressive Glove': (True, False, None, 0x61, 150, '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', 'a glove'), diff --git a/Rom.py b/Rom.py index 0a392c1f..e0134579 100644 --- a/Rom.py +++ b/Rom.py @@ -29,13 +29,14 @@ from Text import Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, M from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc from Items import ItemFactory from EntranceShuffle import door_addresses, exit_ids, ow_prize_table +from InitialSram import InitialSram from source.classes.SFX import randomize_sfx from source.item.FillUtil import valid_pot_items JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '8d196e8024faebbbbe1304032158ccea' +RANDOMIZERBASEHASH = '65c56d252ed3d6d94546912526bffb70' class JsonRom(object): @@ -46,6 +47,7 @@ class JsonRom(object): self.orig_buffer = None self.patches = {} self.addresses = [] + self.initial_sram = InitialSram() def write_byte(self, address, value): self.write_bytes(address, [value]) @@ -75,6 +77,9 @@ class JsonRom(object): del self.patches[str(intervalstart)] del self.addresses[pos] + def write_initial_sram(self): + self.write_bytes(0x183000, self.initial_sram.get_initial_sram()) + def write_to_file(self, file): with open(file, 'w') as stream: json.dump([self.patches], stream) @@ -92,6 +97,7 @@ class LocalRom(object): self.hash = hash self.orig_buffer = None self.file = file + self.initial_sram = InitialSram() self.has_smc_header = False if not os.path.isfile(file): raise RuntimeError("Could not find valid local base rom for patching at expected path %s." % file) @@ -107,6 +113,9 @@ class LocalRom(object): def write_bytes(self, startaddress, values): self.buffer[startaddress:startaddress + len(values)] = values + def write_initial_sram(self): + self.write_bytes(0x183000, self.initial_sram.get_initial_sram()) + def write_to_file(self, file): with open(file, 'wb') as outfile: outfile.write(self.buffer) @@ -956,11 +965,11 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): # set open mode: if world.mode[player] in ['open', 'inverted']: - rom.write_byte(0x180032, 0x01) # open mode + init_open_mode_sram(rom) if world.mode[player] == 'inverted': - set_inverted_mode(world, player, rom) + set_inverted_mode(world, rom) elif world.mode[player] == 'standard': - rom.write_byte(0x180032, 0x00) # standard mode + init_standard_mode_sram(rom) uncle_location = world.get_location('Link\'s Uncle', player) if uncle_location.item is None or uncle_location.item.name not in ['Master Sword', 'Tempered Sword', 'Fighter Sword', 'Golden Sword', 'Progressive Sword']: @@ -1184,10 +1193,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): # set swordless mode settings rom.write_byte(0x18003F, 0x01 if world.swords[player] == 'swordless' else 0x00) # hammer can harm ganon - rom.write_byte(0x180040, 0x01 if world.swords[player] == 'swordless' else 0x00) # open curtains rom.write_byte(0x180041, 0x01 if world.swords[player] == 'swordless' else 0x00) # swordless medallions - rom.write_byte(0x180043, 0xFF if world.swords[player] == 'swordless' else 0x00) # starting sword for link rom.write_byte(0x180044, 0x01 if world.swords[player] == 'swordless' else 0x00) # hammer activates tablets + rom.initial_sram.set_swordless_curtains() # open curtains # set up clocks for timed modes if world.shuffle[player] == 'vanilla': @@ -1203,34 +1211,34 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): write_int32(rom, 0x180200, 0) # red clock adjustment time (in frames, sint32) write_int32(rom, 0x180204, 0) # blue clock adjustment time (in frames, sint32) write_int32(rom, 0x180208, 0) # green clock adjustment time (in frames, sint32) - write_int32(rom, 0x18020C, 0) # starting time (in frames, sint32) + rom.initial_sram.set_starting_timer(0) # starting time (in frames, sint32) elif world.clock_mode == 'ohko': rom.write_bytes(0x180190, [0x01, 0x02, 0x01]) # ohko timer with resetable timer functionality write_int32(rom, 0x180200, 0) # red clock adjustment time (in frames, sint32) write_int32(rom, 0x180204, 0) # blue clock adjustment time (in frames, sint32) write_int32(rom, 0x180208, 0) # green clock adjustment time (in frames, sint32) - write_int32(rom, 0x18020C, 0) # starting time (in frames, sint32) + rom.initial_sram.set_starting_timer(0) # starting time (in frames, sint32) elif world.clock_mode == 'countdown-ohko': rom.write_bytes(0x180190, [0x01, 0x02, 0x01]) # ohko timer with resetable timer functionality write_int32(rom, 0x180200, -100 * 60 * 60 * 60) # red clock adjustment time (in frames, sint32) write_int32(rom, 0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) write_int32(rom, 0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) - if world.difficulty_adjustments[player] == 'normal': - write_int32(rom, 0x18020C, (10 + ERtimeincrease) * 60 * 60) # starting time (in frames, sint32) + if world.difficulty_adjustments == 'normal': + rom.initial_sram.set_starting_timer((10 + ERtimeincrease) * 60) # starting time (in seconds) else: - write_int32(rom, 0x18020C, int((5 + ERtimeincrease / 2) * 60 * 60)) # starting time (in frames, sint32) + rom.initial_sram.set_starting_timer(int((5 + ERtimeincrease / 2) * 60)) # starting time (in seconds) if world.clock_mode == 'stopwatch': rom.write_bytes(0x180190, [0x02, 0x01, 0x00]) # set stopwatch mode write_int32(rom, 0x180200, -2 * 60 * 60) # red clock adjustment time (in frames, sint32) write_int32(rom, 0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) write_int32(rom, 0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) - write_int32(rom, 0x18020C, 0) # starting time (in frames, sint32) + rom.initial_sram.set_starting_timer(0) # starting time (in frames, sint32) if world.clock_mode == 'countdown': rom.write_bytes(0x180190, [0x01, 0x01, 0x00]) # set countdown, with no reset available write_int32(rom, 0x180200, -2 * 60 * 60) # red clock adjustment time (in frames, sint32) write_int32(rom, 0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) write_int32(rom, 0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) - write_int32(rom, 0x18020C, (40 + ERtimeincrease) * 60 * 60) # starting time (in frames, sint32) + rom.initial_sram.set_starting_timer((40 + ERtimeincrease) * 60) # starting time (in seconds) # set up goals for treasure hunt rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon[player] == 'Triforce Piece' else [0x0D, 0x28]) @@ -1255,14 +1263,16 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(0x180169, 0x02) # lock aga/ganon tower door with crystals in inverted rom.write_byte(0x180171, 0x01 if world.ganon_at_pyramid[player] else 0x00) # Enable respawning on pyramid after ganon death rom.write_byte(0x180173, 0x01) # Bob is enabled - rom.write_byte(0x180168, 0x08) # Spike Cave Damage + rom.write_byte(0x180195, 0x08) # Spike Cave Damage rom.write_bytes(0x18016B, [0x04, 0x02, 0x01]) # Set spike cave and MM spike room Byrna usage rom.write_bytes(0x18016E, [0x04, 0x08, 0x10]) # Set spike cave and MM spike room Cape usage rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest rom.write_byte(0x50599, 0x00) # disable below ganon chest rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest - rom.write_byte(0x18008B, 0x01 if world.open_pyramid[player] else 0x00) # pre-open Pyramid Hole - rom.write_byte(0x18008C, 0x01 if world.crystals_needed_for_gt[player] == 0 else 0x00) # GT pre-opened if crystal requirement is 0 + if world.open_pyramid[player]: + rom.initial_sram.pre_open_pyramid_hole() + if world.crystals_needed_for_gt == 0: + rom.initial_sram.pre_open_ganons_tower() rom.write_byte(0xF5D73, 0xF0) # bees are catchable rom.write_byte(0xF5F10, 0xF0) # bees are catchable rom.write_byte(0x180086, 0x00 if world.aga_randomness else 0x01) # set blue ball and ganon warp randomness @@ -1274,161 +1284,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): # Starting equipment if world.pseudoboots[player]: rom.write_byte(0x18008E, 0x01) - - equip = [0] * (0x340 + 0x4F) - equip[0x36C] = 0x18 - equip[0x36D] = 0x18 - equip[0x379] = 0x68 - if world.bombbag[player]: - starting_max_bombs = 0 - else: - starting_max_bombs = 10 - starting_max_arrows = 30 - - startingstate = CollectionState(world) - - if startingstate.has('Bow', player): - equip[0x340] = 3 if startingstate.has('Silver Arrows', player) else 1 - equip[0x38E] |= 0x20 # progressive flag to get the correct hint in all cases - if not world.retro[player]: - equip[0x38E] |= 0x80 - if startingstate.has('Silver Arrows', player): - equip[0x38E] |= 0x40 - - if startingstate.has('Titans Mitts', player): - equip[0x354] = 2 - elif startingstate.has('Power Glove', player): - equip[0x354] = 1 - - if startingstate.has('Golden Sword', player): - equip[0x359] = 4 - elif startingstate.has('Tempered Sword', player): - equip[0x359] = 3 - elif startingstate.has('Master Sword', player): - equip[0x359] = 2 - elif startingstate.has('Fighter Sword', player): - equip[0x359] = 1 - - if startingstate.has('Mirror Shield', player): - equip[0x35A] = 3 - elif startingstate.has('Red Shield', player): - equip[0x35A] = 2 - elif startingstate.has('Blue Shield', player): - equip[0x35A] = 1 - - if startingstate.has('Red Mail', player): - equip[0x35B] = 2 - elif startingstate.has('Blue Mail', player): - equip[0x35B] = 1 - - if startingstate.has('Magic Upgrade (1/4)', player): - equip[0x37B] = 2 - equip[0x36E] = 0x80 - elif startingstate.has('Magic Upgrade (1/2)', player): - equip[0x37B] = 1 - equip[0x36E] = 0x80 - - for item in world.precollected_items: - if item.player != player: - continue - - if item.name in ['Bow', 'Silver Arrows', 'Progressive Bow', 'Progressive Bow (Alt)', - 'Titans Mitts', 'Power Glove', 'Progressive Glove', - 'Golden Sword', 'Tempered Sword', 'Master Sword', 'Fighter Sword', 'Progressive Sword', - 'Mirror Shield', 'Red Shield', 'Blue Shield', 'Progressive Shield', - 'Red Mail', 'Blue Mail', 'Progressive Armor', - 'Magic Upgrade (1/4)', 'Magic Upgrade (1/2)']: - continue - - set_table = {'Book of Mudora': (0x34E, 1), 'Hammer': (0x34B, 1), 'Bug Catching Net': (0x34D, 1), 'Hookshot': (0x342, 1), 'Magic Mirror': (0x353, 2), - 'Cape': (0x352, 1), 'Lamp': (0x34A, 1), 'Moon Pearl': (0x357, 1), 'Cane of Somaria': (0x350, 1), 'Cane of Byrna': (0x351, 1), - 'Fire Rod': (0x345, 1), 'Ice Rod': (0x346, 1), 'Bombos': (0x347, 1), 'Ether': (0x348, 1), 'Quake': (0x349, 1)} - or_table = {'Green Pendant': (0x374, 0x04), 'Red Pendant': (0x374, 0x01), 'Blue Pendant': (0x374, 0x02), - 'Crystal 1': (0x37A, 0x02), 'Crystal 2': (0x37A, 0x10), 'Crystal 3': (0x37A, 0x40), 'Crystal 4': (0x37A, 0x20), - 'Crystal 5': (0x37A, 0x04), 'Crystal 6': (0x37A, 0x01), 'Crystal 7': (0x37A, 0x08), - 'Big Key (Eastern Palace)': (0x367, 0x20), 'Compass (Eastern Palace)': (0x365, 0x20), 'Map (Eastern Palace)': (0x369, 0x20), - 'Big Key (Desert Palace)': (0x367, 0x10), 'Compass (Desert Palace)': (0x365, 0x10), 'Map (Desert Palace)': (0x369, 0x10), - 'Big Key (Tower of Hera)': (0x366, 0x20), 'Compass (Tower of Hera)': (0x364, 0x20), 'Map (Tower of Hera)': (0x368, 0x20), - 'Big Key (Escape)': (0x367, 0xC0), 'Compass (Escape)': (0x365, 0xC0), 'Map (Escape)': (0x369, 0xC0), - 'Big Key (Agahnims Tower)': (0x367, 0x08), 'Compass (Agahnims Tower)': (0x365, 0x08), 'Map (Agahnims Tower)': (0x369, 0x08), - 'Big Key (Palace of Darkness)': (0x367, 0x02), 'Compass (Palace of Darkness)': (0x365, 0x02), 'Map (Palace of Darkness)': (0x369, 0x02), - 'Big Key (Thieves Town)': (0x366, 0x10), 'Compass (Thieves Town)': (0x364, 0x10), 'Map (Thieves Town)': (0x368, 0x10), - 'Big Key (Skull Woods)': (0x366, 0x80), 'Compass (Skull Woods)': (0x364, 0x80), 'Map (Skull Woods)': (0x368, 0x80), - 'Big Key (Swamp Palace)': (0x367, 0x04), 'Compass (Swamp Palace)': (0x365, 0x04), 'Map (Swamp Palace)': (0x369, 0x04), - 'Big Key (Ice Palace)': (0x366, 0x40), 'Compass (Ice Palace)': (0x364, 0x40), 'Map (Ice Palace)': (0x368, 0x40), - 'Big Key (Misery Mire)': (0x367, 0x01), 'Compass (Misery Mire)': (0x365, 0x01), 'Map (Misery Mire)': (0x369, 0x01), - 'Big Key (Turtle Rock)': (0x366, 0x08), 'Compass (Turtle Rock)': (0x364, 0x08), 'Map (Turtle Rock)': (0x368, 0x08), - 'Big Key (Ganons Tower)': (0x366, 0x04), 'Compass (Ganons Tower)': (0x364, 0x04), 'Map (Ganons Tower)': (0x368, 0x04)} - set_or_table = {'Flippers': (0x356, 1, 0x379, 0x02),'Pegasus Boots': (0x355, 1, 0x379, 0x04), - 'Shovel': (0x34C, 1, 0x38C, 0x04), 'Ocarina': (0x34C, 3, 0x38C, 0x01), - 'Mushroom': (0x344, 1, 0x38C, 0x20 | 0x08), 'Magic Powder': (0x344, 2, 0x38C, 0x10), - 'Blue Boomerang': (0x341, 1, 0x38C, 0x80), 'Red Boomerang': (0x341, 2, 0x38C, 0x40)} - keys = {'Small Key (Eastern Palace)': [0x37E], 'Small Key (Desert Palace)': [0x37F], - 'Small Key (Tower of Hera)': [0x386], - 'Small Key (Agahnims Tower)': [0x380], 'Small Key (Palace of Darkness)': [0x382], - 'Small Key (Thieves Town)': [0x387], - 'Small Key (Skull Woods)': [0x384], 'Small Key (Swamp Palace)': [0x381], - 'Small Key (Ice Palace)': [0x385], - 'Small Key (Misery Mire)': [0x383], 'Small Key (Turtle Rock)': [0x388], - 'Small Key (Ganons Tower)': [0x389], - 'Small Key (Universal)': [0x38B], 'Small Key (Escape)': [0x37C, 0x37D]} - bottles = {'Bottle': 2, 'Bottle (Red Potion)': 3, 'Bottle (Green Potion)': 4, 'Bottle (Blue Potion)': 5, - 'Bottle (Fairy)': 6, 'Bottle (Bee)': 7, 'Bottle (Good Bee)': 8} - rupees = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)': 50, 'Rupees (100)': 100, 'Rupees (300)': 300} - bomb_caps = {'Bomb Upgrade (+5)': 5, 'Bomb Upgrade (+10)': 10} - arrow_caps = {'Arrow Upgrade (+5)': 5, 'Arrow Upgrade (+10)': 10} - bombs = {'Single Bomb': 1, 'Bombs (3)': 3, 'Bombs (10)': 10} - arrows = {'Single Arrow': 1, 'Arrows (10)': 10} - - if item.name in set_table: - equip[set_table[item.name][0]] = set_table[item.name][1] - elif item.name in or_table: - equip[or_table[item.name][0]] |= or_table[item.name][1] - elif item.name in set_or_table: - equip[set_or_table[item.name][0]] = set_or_table[item.name][1] - equip[set_or_table[item.name][2]] |= set_or_table[item.name][3] - elif item.name in keys: - for address in keys[item.name]: - equip[address] = min(equip[address] + 1, 99) - elif item.name in bottles: - if equip[0x34F] < world.difficulty_requirements[player].progressive_bottle_limit: - equip[0x35C + equip[0x34F]] = bottles[item.name] - equip[0x34F] += 1 - elif item.name in rupees: - equip[0x360:0x362] = list(min(equip[0x360] + (equip[0x361] << 8) + rupees[item.name], 9999).to_bytes(2, byteorder='little', signed=False)) - equip[0x362:0x364] = list(min(equip[0x362] + (equip[0x363] << 8) + rupees[item.name], 9999).to_bytes(2, byteorder='little', signed=False)) - elif item.name in bomb_caps: - starting_max_bombs = min(starting_max_bombs + bomb_caps[item.name], 50) - elif item.name in arrow_caps: - starting_max_arrows = min(starting_max_arrows + arrow_caps[item.name], 70) - elif item.name in bombs: - equip[0x343] += bombs[item.name] - elif item.name in arrows: - if world.retro[player]: - equip[0x38E] |= 0x80 - equip[0x377] = 1 - else: - equip[0x377] += arrows[item.name] - elif item.name in ['Piece of Heart', 'Boss Heart Container', 'Sanctuary Heart Container']: - if item.name == 'Piece of Heart': - equip[0x36B] = (equip[0x36B] + 1) % 4 - if item.name != 'Piece of Heart' or equip[0x36B] == 0: - equip[0x36C] = min(equip[0x36C] + 0x08, 0xA0) - equip[0x36D] = min(equip[0x36D] + 0x08, 0xA0) - else: - raise RuntimeError(f'Unsupported item in starting equipment: {item.name}') - - equip[0x343] = min(equip[0x343], starting_max_bombs) - rom.write_byte(0x180034, starting_max_bombs) - equip[0x377] = min(equip[0x377], starting_max_arrows) - rom.write_byte(0x180035, starting_max_arrows) - rom.write_bytes(0x180046, equip[0x360:0x362]) - if equip[0x359]: - rom.write_byte(0x180043, equip[0x359]) - - assert equip[:0x340] == [0] * 0x340 - rom.write_bytes(0x183000, equip[0x340:]) - rom.write_bytes(0x271A6, equip[0x340:0x340+60]) + rom.initial_sram.set_starting_equipment(world, player) + rom.write_byte(0x180034, 10 if not world.bombbag[player] else 0) # starting max bombs + rom.write_byte(0x180035, 30) # starting max arrows rom.write_byte(0x18004A, 0x00 if world.mode[player] != 'inverted' else 0x01) # Inverted mode rom.write_byte(0x18005D, 0x00) # Hammer always breaks barrier @@ -1678,6 +1536,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): write_strings(rom, world, player, team) + # write initial sram + rom.write_initial_sram() + rom.write_byte(0x18636C, 1 if world.remote_items[player] else 0) # set rom name @@ -2501,6 +2362,16 @@ def text_for_item(item, world, player, team): else: return f'{item.hint_text} for {world.player_names[item.player][team]}' +def init_open_mode_sram(rom): + rom.initial_sram.pre_open_castle_gate() + rom.initial_sram.set_progress_indicator(0x02) + rom.initial_sram.set_progress_flags(0x14) + rom.initial_sram.set_starting_entrance(0x01) + +def init_standard_mode_sram(rom): + rom.initial_sram.set_progress_indicator(0x00) + rom.initial_sram.set_progress_flags(0x0) + rom.initial_sram.set_starting_entrance(0x00) def set_inverted_mode(world, player, rom): rom.write_byte(snes_to_pc(0x0283E0), 0xF0) # residual portals diff --git a/Utils.py b/Utils.py index a307a6cd..74386593 100644 --- a/Utils.py +++ b/Utils.py @@ -678,6 +678,11 @@ def extract_data_from_jp_rom(rom): # print_data_block(secretdata) # print() +def count_set_bits(val): + if val == 0: + return 0 + else: + return (val & 1) + count_set_bits(val >> 1) if __name__ == '__main__': # make_new_base2current() diff --git a/data/base2current.bps b/data/base2current.bps index e4759a9cb06c9a0621447ee21979121ff6fe9960..c2e58058f06d3c93f3ccee851d7d25316d1d4f54 100644 GIT binary patch delta 21690 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 delta 21497 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 Date: Wed, 20 Apr 2022 22:10:02 -0400 Subject: [PATCH 07/25] Fix swordless --- InitialSram.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InitialSram.py b/InitialSram.py index 7a1ccba4..e0622591 100644 --- a/InitialSram.py +++ b/InitialSram.py @@ -217,8 +217,8 @@ class InitialSram: self._initial_sram_bytes[0x46E] = self._initial_sram_bytes[0x35B] if world.swords[player] == "swordless": - self.__initial_sram_bytes[0x359] = 0xFF - self.__initial_sram_bytes[0x417] = 0x00 + self._initial_sram_bytes[0x359] = 0xFF + self._initial_sram_bytes[0x417] = 0x00 def set_starting_rupees(self, rupees: int): if not (-1 < rupees < 10000): From 86128c76ff72f996aaea085666dc3080b77b256c Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 8 Mar 2022 08:47:25 -0700 Subject: [PATCH 08/25] Add major_only algorithm to code --- BaseClasses.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index b79af29d..8df66c3f 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2727,8 +2727,12 @@ e_dmg = {"default": 0, "shuffled": 1, "random": 2} # byte 8: RRAA A??? (restrict boss mode, algorithm, ? = unused) rb_mode = {"none": 0, "mapcompass": 1, "dungeon": 2} -# algorithm: todo with "biased shuffles" -algo_mode = {"balanced": 0, "equitable": 1, "vanilla_fill": 2, "dungeon_only": 3, "district": 4} +# algorithm: +algo_mode = {"balanced": 0, "equitable": 1, "vanilla_fill": 2, "dungeon_only": 3, "district": 4, 'major_only': 5} +boss_mode = {"none": 0, "simple": 1, "full": 2, "chaos": 3, 'random': 3, 'unique': 4} + + +# byte 10: settings_version # additions # psuedoboots does not effect code From 39ccc59849a597449df6fdd2a5a5cb8a854dce6c Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 21 Apr 2022 12:43:41 -0600 Subject: [PATCH 09/25] Update example --- mystery_example.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mystery_example.yml b/mystery_example.yml index a7f26ddb..b51c58c5 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -5,6 +5,10 @@ major_only: 1 dungeon_only: 1 district: 1 + restrict_boss_items: + none: 1 +# mapcompass: 1 Bug exists, not recommended + dungeon: 1 door_shuffle: vanilla: 0 basic: 2 @@ -17,11 +21,15 @@ on: 1 off: 1 pottery: - none: 4 + none: 8 keys: 1 cave: 1 dungeon: 1 lottery: 1 + cavekeys: 1 + reduced: 1 + clustered: 1 + nonempty: 1 shopsanity: on: 1 off: 1 From 1c4e3e09ba8dceb5d7ada3d723fd986e9920ed58 Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 21 Apr 2022 13:13:41 -0600 Subject: [PATCH 10/25] Major only update (split pot keys and key drops) --- source/item/FillUtil.py | 72 +++++++++-------------------------------- 1 file changed, 16 insertions(+), 56 deletions(-) diff --git a/source/item/FillUtil.py b/source/item/FillUtil.py index 4be12667..f9fe4c18 100644 --- a/source/item/FillUtil.py +++ b/source/item/FillUtil.py @@ -29,7 +29,6 @@ class LocationGroup(object): # flags self.keyshuffle = False - self.keydropshuffle = False self.shopsanity = False self.retro = False @@ -37,9 +36,8 @@ class LocationGroup(object): self.locations = list(locs) return self - def flags(self, k, d=False, s=False, r=False): + def flags(self, k, s=False, r=False): self.keyshuffle = k - self.keydropshuffle = d self.shopsanity = s self.retro = r return self @@ -124,12 +122,14 @@ def create_item_pool_config(world): groups = LocationGroup('Major').locs(init_set) if world.bigkeyshuffle[player]: groups.locations.extend(mode_grouping['Big Keys']) - if world.keydropshuffle[player] != 'none': + if world.dropshuffle[player] != 'none': groups.locations.extend(mode_grouping['Big Key Drops']) if world.keyshuffle[player]: groups.locations.extend(mode_grouping['Small Keys']) - if world.keydropshuffle[player] != 'none': + if world.dropshuffle[player] != 'none': groups.locations.extend(mode_grouping['Key Drops']) + if world.pottery[player] not in ['none', 'cave']: + groups.locations.extend(mode_grouping['Pot Keys']) if world.compassshuffle[player]: groups.locations.extend(mode_grouping['Compasses']) if world.mapshuffle[player]: @@ -329,49 +329,6 @@ def count_major_items(config, world, player): return sum(1 for x in world.itempool if x.name in config.item_pool[player] and x.player == player) -def calc_dungeon_limits(world, player): - b, s, c, m, k, r, bi = (world.bigkeyshuffle[player], world.keyshuffle[player], world.compassshuffle[player], - world.mapshuffle[player], world.keydropshuffle[player], world.retro[player], - world.restrict_boss_items[player]) - if world.doorShuffle[player] in ['vanilla', 'basic']: - limits = {} - for dungeon, info in dungeon_table.items(): - val = info.free_items - if bi != 'none' and info.prize: - if bi == 'mapcompass' and (not c or not m): - val -= 1 - if bi == 'dungeon' and (not c or not m or not (s or r) or not b): - val -= 1 - if b: - val += 1 if info.bk_present else 0 - if k != 'none': - val += 1 if info.bk_drops else 0 - if s or r: - val += info.key_num - if k != 'none': - val += info.key_drops - if c: - val += 1 if info.compass_present else 0 - if m: - val += 1 if info.map_present else 0 - limits[dungeon] = val - else: - limits = 60 - if world.bigkeyshuffle[player]: - limits += 11 - if world.keydropshuffle[player] != 'none': - limits += 1 - if world.keyshuffle[player] or world.retro[player]: - limits += 29 - if world.keydropshuffle[player] != 'none': - limits += 32 - if world.compassshuffle[player]: - limits += 11 - if world.mapshuffle[player]: - limits += 12 - return limits - - def determine_major_items(world, player): major_item_set = set(major_items) if world.progressive == 'off': @@ -776,19 +733,22 @@ mode_grouping = { ], 'Key Drops': [ 'Hyrule Castle - Map Guard Key Drop', 'Hyrule Castle - Boomerang Guard Key Drop', - 'Hyrule Castle - Key Rat Key Drop', 'Eastern Palace - Dark Square Pot Key', - 'Eastern Palace - Dark Eyegore Key Drop', 'Desert Palace - Desert Tiles 1 Pot Key', - 'Desert Palace - Beamos Hall Pot Key', 'Desert Palace - Desert Tiles 2 Pot Key', + 'Hyrule Castle - Key Rat Key Drop', 'Eastern Palace - Dark Eyegore Key Drop', 'Castle Tower - Dark Archer Key Drop', 'Castle Tower - Circle of Pots Key Drop', + 'Skull Woods - Spike Corner Key Drop', 'Ice Palace - Jelly Key Drop', 'Ice Palace - Conveyor Key Drop', + 'Misery Mire - Conveyor Crystal Key Drop', 'Turtle Rock - Pokey 1 Key Drop', + 'Turtle Rock - Pokey 2 Key Drop', 'Ganons Tower - Mini Helmasuar Key Drop', + ], + 'Pot Keys': [ + 'Eastern Palace - Dark Square Pot Key', 'Desert Palace - Desert Tiles 1 Pot Key', + 'Desert Palace - Beamos Hall Pot Key', 'Desert Palace - Desert Tiles 2 Pot Key', 'Swamp Palace - Pot Row Pot Key', 'Swamp Palace - Trench 1 Pot Key', 'Swamp Palace - Hookshot Pot Key', 'Swamp Palace - Trench 2 Pot Key', 'Swamp Palace - Waterway Pot Key', 'Skull Woods - West Lobby Pot Key', - 'Skull Woods - Spike Corner Key Drop', "Thieves' Town - Hallway Pot Key", - "Thieves' Town - Spike Switch Pot Key", 'Ice Palace - Jelly Key Drop', 'Ice Palace - Conveyor Key Drop', + "Thieves' Town - Hallway Pot Key", "Thieves' Town - Spike Switch Pot Key", 'Ice Palace - Hammer Block Key Drop', 'Ice Palace - Many Pots Pot Key', 'Misery Mire - Spikes Pot Key', - 'Misery Mire - Fishbone Pot Key', 'Misery Mire - Conveyor Crystal Key Drop', 'Turtle Rock - Pokey 1 Key Drop', - 'Turtle Rock - Pokey 2 Key Drop', 'Ganons Tower - Conveyor Cross Pot Key', + 'Misery Mire - Fishbone Pot Key', 'Ganons Tower - Conveyor Cross Pot Key', 'Ganons Tower - Double Switch Pot Key', 'Ganons Tower - Conveyor Star Pits Pot Key', - 'Ganons Tower - Mini Helmasuar Key Drop', + ], 'Big Key Drops': ['Hyrule Castle - Big Key Drop'], 'Shops': [ From e0a6f26279d9a3f6105f7567396863af53f8880d Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 21 Apr 2022 13:19:50 -0600 Subject: [PATCH 11/25] Font work --- Rom.py | 4 ++-- Text.py | 34 ++++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Rom.py b/Rom.py index d99ffef7..81d82b62 100644 --- a/Rom.py +++ b/Rom.py @@ -2446,8 +2446,8 @@ def write_strings(rom, world, player, team): # inverted spawn menu changes if world.mode[player] == 'inverted': - tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s house\n Dark Chapel\n{CHOICE3}" - tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s house\n Dark Chapel\n Mountain Cave\n{CHOICE2}" + tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s House\n Dark Chapel\n{CHOICE3}" + tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s House\n Dark Chapel\n Mountain Cave\n{CHOICE2}" tt['intro_main'] = CompressedTextMapper.convert( "{INTRO}\n Episode III\n{PAUSE3}\n A Link to\n the Past\n" + "{PAUSE3}\nInverted\n Randomizer\n{PAUSE3}\nAfter mostly disregarding what happened in the first two games.\n" diff --git a/Text.py b/Text.py index c84a202c..071dc2a7 100644 --- a/Text.py +++ b/Text.py @@ -627,8 +627,8 @@ class MultiByteCoreTextMapper(object): } @classmethod - def convert(cls, text, pause=True, wrap=14): - text = text.upper() + def convert(cls, text, pause=True, wrap=19): + # text = text.upper() lines = text.split('\n') outbuf = bytearray() lineindex = 0 @@ -655,7 +655,8 @@ class MultiByteCoreTextMapper(object): pending_space = False while words: word = words.pop(0) - # sanity check: if the word we have is more than 14 characters, we take as much as we can still fit and push the rest back for later + # sanity check: if the word we have is more than 19 characters, + # we take as much as we can still fit and push the rest back for later if cls.wordlen(word) > wrap: (word_first, word_rest) = cls.splitword(word, linespace) words.insert(0, word_rest) @@ -736,7 +737,7 @@ class CompressedTextMapper(object): } @classmethod - def convert(cls, text, pause=True, max_bytes_expanded=0x800, wrap=14): + def convert(cls, text, pause=True, max_bytes_expanded=0x800, wrap=19): inbuf = MultiByteCoreTextMapper.convert(text, pause, wrap) # Links name will need 8 bytes in the target buffer @@ -772,20 +773,23 @@ class CompressedTextMapper(object): class CharTextMapper(object): number_offset = None alpha_offset = 0 + alpha_lower_offset = 0 char_map = {} @classmethod def map_char(cls, char): if cls.number_offset is not None: - if 0x30 <= ord(char) <= 0x39: + if 0x30 <= ord(char) <= 0x39: return ord(char) + cls.number_offset + if 0x41 <= ord(char) <= 0x5A: + return ord(char) + 0x20 + cls.alpha_offset if 0x61 <= ord(char) <= 0x7A: - return ord(char) + cls.alpha_offset + return ord(char) + cls.alpha_lower_offset return cls.char_map.get(char, cls.char_map[' ']) @classmethod def convert(cls, text): buf = bytearray() - for char in text.lower(): + for char in text: buf.append(cls.map_char(char)) return buf @@ -1240,6 +1244,7 @@ class RawMBTextMapper(CharTextMapper): "月": 0xFE, "姫": 0xFF} alpha_offset = 0x49 + alpha_lower_offset = -0x31 number_offset = 0x70 @classmethod @@ -1251,7 +1256,7 @@ class RawMBTextMapper(CharTextMapper): @classmethod def convert(cls, text): buf = bytearray() - for char in text.lower(): + for char in text: res = cls.map_char(char) if isinstance(res, int): buf.extend([0x00, res]) @@ -1267,16 +1272,19 @@ class GoldCreditMapper(CharTextMapper): '-': 0x36, '.': 0x37,} alpha_offset = -0x47 + alpha_lower_offset = -0x47 class GreenCreditMapper(CharTextMapper): char_map = {' ': 0x9F, '·': 0x52} alpha_offset = -0x29 + alpha_lower_offset = -0x29 class RedCreditMapper(CharTextMapper): char_map = {' ': 0x9F} alpha_offset = -0x61 + alpha_lower_offset = -0x61 class LargeCreditTopMapper(CharTextMapper): char_map = {' ': 0x9F, @@ -1296,6 +1304,7 @@ class LargeCreditTopMapper(CharTextMapper): '◢': 0xAA, '◣': 0xAB,} alpha_offset = -0x04 + alpha_lower_offset = -0x04 number_offset = 0x23 @@ -1317,6 +1326,7 @@ class LargeCreditBottomMapper(CharTextMapper): '◢': 0xCA, '◣': 0xCB,} alpha_offset = 0x22 + alpha_lower_offset = 0x22 number_offset = 0x49 class TextTable(object): @@ -1955,16 +1965,16 @@ class TextTable(object): text['game_chest_lost_woods'] = CompressedTextMapper.convert("Pay 100 rupees open 1 chest. Are you lucky?\nSo, Play game?\n ≥ play\n never!\n{CHOICE}") text['kakariko_flophouse_man_no_flippers'] = CompressedTextMapper.convert("I really hate mowing my yard.\nI moved my house and everyone else's to avoid it.\n{PAGEBREAK}\nI hope you don't mind.") text['kakariko_flophouse_man'] = CompressedTextMapper.convert("I really hate mowing my yard.\nI moved my house and everyone else's to avoid it.\n{PAGEBREAK}\nI hope you don't mind.") - text['menu_start_2'] = CompressedTextMapper.convert("{MENU}\n{SPEED0}\n≥@'s house\n Sanctuary\n{CHOICE3}", False) - text['menu_start_3'] = CompressedTextMapper.convert("{MENU}\n{SPEED0}\n≥@'s house\n Sanctuary\n Mountain Cave\n{CHOICE2}", False) - text['menu_pause'] = CompressedTextMapper.convert("{SPEED0}\n≥continue\n save and quit\n{CHOICE3}", False) + text['menu_start_2'] = CompressedTextMapper.convert("{MENU}\n{SPEED0}\n≥@'s House\n Sanctuary\n{CHOICE3}", False) + text['menu_start_3'] = CompressedTextMapper.convert("{MENU}\n{SPEED0}\n≥@'s House\n Sanctuary\n Mountain Cave\n{CHOICE2}", False) + text['menu_pause'] = CompressedTextMapper.convert("{SPEED0}\n≥Continue\n Save and Quit\n{CHOICE3}", False) text['game_digging_choice'] = CompressedTextMapper.convert("Have 80 Rupees? Want to play digging game?\n ≥yes\n no\n{CHOICE}") text['game_digging_start'] = CompressedTextMapper.convert("Okay, use the shovel with Y!") text['game_digging_no_cash'] = CompressedTextMapper.convert("Shovel rental is 80 rupees.\nI have all day") text['game_digging_end_time'] = CompressedTextMapper.convert("Time's up!\nTime for you to go.") text['game_digging_come_back_later'] = CompressedTextMapper.convert("Come back later, I have to bury things.") text['game_digging_no_follower'] = CompressedTextMapper.convert("Something is following you. I don't like.") - text['menu_start_4'] = CompressedTextMapper.convert("{MENU}\n{SPEED0}\n≥@'s house\n Mountain Cave\n{CHOICE3}", False) + text['menu_start_4'] = CompressedTextMapper.convert("{MENU}\n{SPEED0}\n≥@'s House\n Mountain Cave\n{CHOICE3}", False) # Start of new text data text['ganon_fall_in_alt'] = CompressedTextMapper.convert("You think you\nare ready to\nface me?\n\nI will not die\n\nunless you\ncomplete your\ngoals. Dingus!") text['ganon_phase_3_alt'] = CompressedTextMapper.convert("Got wax in\nyour ears?\nI cannot die!") From b514df76c399b8e143f401ae48e5076fdda93ac0 Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 21 Apr 2022 15:44:52 -0600 Subject: [PATCH 12/25] Prize letters and numbers Minor bug with max keys: prevent negative values --- DoorShuffle.py | 2 +- Items.py | 18 +++++++++--------- Rom.py | 2 +- asm/hudadditions.asm | 6 +++--- data/base2current.bps | Bin 90002 -> 90014 bytes 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/DoorShuffle.py b/DoorShuffle.py index de82ca40..8dfcb726 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -1088,7 +1088,7 @@ def assign_cross_keys(dungeon_builders, world, player): # Step 2: Initial Key Number Assignment & Calculate Flexibility for name, builder in dungeon_builders.items(): calculated = int(round(builder.key_doors_num*total_keys/total_candidates)) - max_keys = builder.location_cnt - calc_used_dungeon_items(builder) + max_keys = max(0, builder.location_cnt - calc_used_dungeon_items(builder)) cand_len = max(0, len(builder.candidates) - builder.key_drop_cnt) limit = min(max_keys, cand_len) suggested = min(calculated, limit) diff --git a/Items.py b/Items.py index c88bccf7..e1b4d945 100644 --- a/Items.py +++ b/Items.py @@ -61,19 +61,19 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche 'Progressive Sword': (True, False, 'Sword', 0x5E, 150, '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', 'a sword'), 'Progressive Glove': (True, False, None, 0x61, 150, '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', 'a glove'), 'Silver Arrows': (True, False, None, 0x58, 100, 'Do you fancy\nsilver tipped\narrows?', 'and the ganonsbane', 'ganon-killing kid', 'ganon doom for sale', 'fungus for pork', 'archer boy shines again', 'the silver arrows'), - 'Green Pendant': (True, False, 'Crystal', [0x04, 0x38, 0x62, 0x00, 0x69, 0x01, 0x01], 999, None, None, None, None, None, None, None), - 'Blue Pendant': (True, False, 'Crystal', [0x02, 0x34, 0x60, 0x00, 0x69, 0x02, 0x02], 999, None, None, None, None, None, None, None), - 'Red Pendant': (True, False, 'Crystal', [0x01, 0x32, 0x60, 0x00, 0x69, 0x03, 0x02], 999, None, None, None, None, None, None, None), + 'Green Pendant': (True, False, 'Crystal', [0x04, 0x38, 0x62, 0x00, 0x69, 0x01, 0x08], 999, None, None, None, None, None, None, None), + 'Blue Pendant': (True, False, 'Crystal', [0x02, 0x34, 0x60, 0x00, 0x69, 0x02, 0x09], 999, None, None, None, None, None, None, None), + 'Red Pendant': (True, False, 'Crystal', [0x01, 0x32, 0x60, 0x00, 0x69, 0x03, 0x0a], 999, None, None, None, None, None, None, None), 'Triforce': (True, False, None, 0x6A, 777, '\n YOU WIN!', 'and the triforce', 'victorious kid', 'victory for sale', 'fungus for the win', 'greedy boy wins game again', 'the Triforce'), 'Power Star': (True, False, None, 0x6B, 100, 'a small victory', 'and the power star', 'star-struck kid', 'star for sale', 'see stars with shroom', 'mario powers up again', 'a Power Star'), 'Triforce Piece': (True, False, None, 0x6C, 100, 'a small victory', 'and the thirdforce', 'triangular kid', 'triangle for sale', 'fungus for triangle', 'wise boy has triangle again', 'a Triforce Piece'), - 'Crystal 1': (True, False, 'Crystal', [0x02, 0x34, 0x64, 0x40, 0x7F, 0x06, 0x04], 999, None, None, None, None, None, None, None), - 'Crystal 2': (True, False, 'Crystal', [0x10, 0x34, 0x64, 0x40, 0x79, 0x06, 0x04], 999, None, None, None, None, None, None, None), - 'Crystal 3': (True, False, 'Crystal', [0x40, 0x34, 0x64, 0x40, 0x6C, 0x06, 0x04], 999, None, None, None, None, None, None, None), + 'Crystal 1': (True, False, 'Crystal', [0x02, 0x34, 0x64, 0x40, 0x7F, 0x06, 0x01], 999, None, None, None, None, None, None, None), + 'Crystal 2': (True, False, 'Crystal', [0x10, 0x34, 0x64, 0x40, 0x79, 0x06, 0x02], 999, None, None, None, None, None, None, None), + 'Crystal 3': (True, False, 'Crystal', [0x40, 0x34, 0x64, 0x40, 0x6C, 0x06, 0x03], 999, None, None, None, None, None, None, None), 'Crystal 4': (True, False, 'Crystal', [0x20, 0x34, 0x64, 0x40, 0x6D, 0x06, 0x04], 999, None, None, None, None, None, None, None), - 'Crystal 5': (True, False, 'Crystal', [0x04, 0x32, 0x64, 0x40, 0x6E, 0x06, 0x03], 999, None, None, None, None, None, None, None), - 'Crystal 6': (True, False, 'Crystal', [0x01, 0x32, 0x64, 0x40, 0x6F, 0x06, 0x03], 999, None, None, None, None, None, None, None), - 'Crystal 7': (True, False, 'Crystal', [0x08, 0x34, 0x64, 0x40, 0x7C, 0x06, 0x04], 999, None, None, None, None, None, None, None), + 'Crystal 5': (True, False, 'Crystal', [0x04, 0x32, 0x64, 0x40, 0x6E, 0x06, 0x05], 999, None, None, None, None, None, None, None), + 'Crystal 6': (True, False, 'Crystal', [0x01, 0x32, 0x64, 0x40, 0x6F, 0x06, 0x06], 999, None, None, None, None, None, None, None), + 'Crystal 7': (True, False, 'Crystal', [0x08, 0x34, 0x64, 0x40, 0x7C, 0x06, 0x07], 999, None, None, None, None, None, None, None), 'Single Arrow': (False, False, None, 0x43, 3, 'a lonely arrow\nsits here.', 'and the arrow', 'stick-collecting kid', 'sewing needle for sale', 'fungus for arrow', 'archer boy sews again', 'an arrow'), 'Arrows (10)': (False, False, None, 0x44, 30, 'This will give\nyou ten shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'ten arrows'), 'Arrow Upgrade (+10)': (False, False, None, 0x54, 100, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), diff --git a/Rom.py b/Rom.py index 81d82b62..c899f6ec 100644 --- a/Rom.py +++ b/Rom.py @@ -36,7 +36,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'd143684aa6a8e4560eb3ac912d600525' +RANDOMIZERBASEHASH = 'd2a55aa9c4fa20ad1056db532cd2c593' class JsonRom(object): diff --git a/asm/hudadditions.asm b/asm/hudadditions.asm index 14844ad9..575e189f 100644 --- a/asm/hudadditions.asm +++ b/asm/hudadditions.asm @@ -196,8 +196,8 @@ OldHudToNewHudTable: dw 1, 2, 3, 10, 4, 6, 5, 8, 11, 9, 7, 12, 13 IndicatorCharacters: - ; check G P R C - dw $2426, $2590, $2599, $259B, $258C + ; check 1 2 3 4 5 6 7 G B R + dw $2426, $2817, $2818, $2819, $281A, $281B, $281C, $281D, $2590, $258B, $259B MapIndicator: LDA.l CrystalPendantFlags_3, X : AND #$00FF @@ -223,7 +223,7 @@ ConvertToDisplay: ConvertToDisplay2: and.w #$00ff : beq ++ cmp #$000a : !blt + - !add #$2553 : rts + !add #$2553 : rts ; todo: use 2580 with 258A as "A" for non transparent digits + !add #$2816 : rts ++ lda #$2827 : rts ; 0/O for 0 or placeholder digit ;2483 diff --git a/data/base2current.bps b/data/base2current.bps index ff88366f6fca21d3890411499756befd84ad933f..617d2d584a638d611bb627b3178ca1dd0b043d09 100644 GIT binary patch delta 236 zcmVSUiC>kgmC>$sqD3B$KC7YL{1p!MDLI9+R7ARnk z$&n(d#-!SpHJASd0YCv-mp}#q6b)Mmn}xzK50!LnftOvkVFm#>3IQ~inh*g&5HEj- mk!U(=prEf4HjtYPHka!V0YL#Pw=EF?T}}vFo%}BvFdr>;!%qzW delta 238 zcmVesU00;mJ00{sG01N;P045}mC7C6gC5)G^1p!MDDgdO37ARnk$&n(d#-!Sp9hVCR z0YD-`k%H>0XPZ)9G9jL0YMNK oe~6K2I%}YyuM;+qn{+jo_YeU=0TZ`55dmFJ2 Date: Sat, 23 Apr 2022 01:25:34 -0400 Subject: [PATCH 13/25] Change pot addresses --- MultiClient.py | 4 ++-- Regions.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MultiClient.py b/MultiClient.py index 4504fed7..bc496f5b 100644 --- a/MultiClient.py +++ b/MultiClient.py @@ -90,8 +90,8 @@ INGAME_MODES = {0x07, 0x09, 0x0b} SAVEDATA_START = WRAM_START + 0xF000 SAVEDATA_SIZE = 0x500 -POT_ITEMS_SRAM_START = WRAM_START + 0x016600 -SPRITE_ITEMS_SRAM_START = WRAM_START + 0x016850 +POT_ITEMS_SRAM_START = WRAM_START + 0x016018 +SPRITE_ITEMS_SRAM_START = WRAM_START + 0x016268 ITEM_SRAM_SIZE = 0x250 RECV_PROGRESS_ADDR = SAVEDATA_START + 0x4D0 # 2 bytes diff --git a/Regions.py b/Regions.py index 1d952189..a452c52f 100644 --- a/Regions.py +++ b/Regions.py @@ -1090,7 +1090,7 @@ def create_pot_location(pot, pot_index, super_tile, world, player): def pot_address(pot_index, super_tile): - return 0x7f6600 + super_tile * 2 + (pot_index << 24) + return 0x7f6018 + super_tile * 2 + (pot_index << 24) # (type, room_id, shopkeeper, custom, locked, [items]) From 7a35bbfc41a6f16d0adbc0aeecde44ed4eccf367 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 27 Apr 2022 13:48:20 -0600 Subject: [PATCH 14/25] Fixed typing issue. New baserom for minor multiclient issue with pot switches --- InitialSram.py | 3 ++- Rom.py | 2 +- data/base2current.bps | Bin 90014 -> 90117 bytes 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/InitialSram.py b/InitialSram.py index e0622591..772e1d46 100644 --- a/InitialSram.py +++ b/InitialSram.py @@ -1,4 +1,5 @@ from dataclasses import dataclass, field +from typing import List from BaseClasses import CollectionState from Utils import count_set_bits @@ -18,7 +19,7 @@ def _new_default_sram(): @dataclass class InitialSram: - _initial_sram_bytes: list[int] = field(default_factory=_new_default_sram) + _initial_sram_bytes: List[int] = field(default_factory=_new_default_sram) def _set_value(self, idx: int, val:int): if idx > SRAM_SIZE: diff --git a/Rom.py b/Rom.py index 7a14021f..3f1506ea 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'd2a55aa9c4fa20ad1056db532cd2c593' +RANDOMIZERBASEHASH = '3c85536ef5463d329adb2e9e3cda654a' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 617d2d584a638d611bb627b3178ca1dd0b043d09..43f2319ea5e516ec4af6be3c1a619e3d043adfab 100644 GIT binary patch delta 21147 zcmX`T2V4}#`#8MU;OJF4ax6$uRK$je3Km2~#Tv`0sHo^!h$Yr=vnMAWu{$x-J46M0C>c=*kq!~RDmx~k9!e+^i;gqMMj8-O21{#MT8j75ryZF zM-Oh%8@kB=I(p8o3UVYJ-6YD2f28ZYWKzJ}zAA|B-lC<+OXYkDMYm?6cu!~-Qc8-O zsLJ=%a!g|Wi4gRxij3;yyWvM)-QArfc)ZQ)?oMx|$->JfIVvMp;h#i->dDon?z=R3 z=B_EGP`A0mw7Nhy+QMhTdv@O8yIqk^YvJ{HNEF&}geHeo@H=js$tY|}d@d(zJ4~6B z?mZnHl3zv+HNmU4PzEyXHs1{++<2S6Mw2^>qazC&N%l5RZo2QL)bBK<6wsu)Bzh0G zVWx&=%HnvdQbQ|?pYgsG)#MAE$==`Yi!`~e*z}MlFQA&eG`Y2mkAzp0;%ae{$bf$o z_Z0tj1OF|ao^tq-=@$06qEiaIlBG#n;Ip;5-wdWm=*ZnNzB`kl$*Ail`&#AS=EuUj zzb}YZFfN0Ylrx%xuOG4%Irs_%;F2+Ad`vl1DnRfp-bZKRURQfmZ z@4x@X4@SBY94PCPU=sK_yUH_WP%)HFWib6%Ic54!o)k?|jeKNj8L4{0Be$`8%E$;< z?C#tHl`&m-t1Lo&?XGDM%y`OO$j#Y}H$)djYRky!_T&!KFgmcvzJZW^$twqLNA$cO z_-?E2s~`BY269my-(5a@$@eE#j4jO4(4?u7_e2%sZP>-K?z6hTEBS}Iv6cK-O82RP z4?#NeL?t(V(yn-<^Qz=$Qf1_c3f`+J;ErNUet=d-zy>HI*PC#hLzp_Gj{mndaT@Il z%_em4O*Gl3gP#M7df-0)QfGV22T&&_YA@k%1E7ww z)>nACnZqj-Zf5Ut?>?Fg7-Z^MKFhw*$*VuGOKGctjQN4j8f2uEFgfv>Dl*>0+r(Mj zaauJ^4(a3vA?>D%_~BUC2}Kv#b#qJ4a`7`twd91UDCJm+MmOUkpQ&fJzCXq~-^eJ} zU28fRQlcC8Js(n4M((zs$4IJnS_rL6yksJF(&WnnrpTRI2b-^Ezi${$E~3dSZTu-eg2efA!owGoy1z0HdiSp)KQ3r+kjChW1cyW2z+&7pLnI$o;L z#=cip=#-uJvB)ad=u9SlW1a4aiHGCx;I3(G0rfkVDW(*RuJIe#jPWP=Hr=$T_>G#Q3GbC%NfhlOr3O zK-D>s_k@E%q<(KSUq;@ySM`PQ^}EGqx&aBA3>k6X!1{Lbt0DVzr+v*&7n;)9GIFbZ zfSx5Z=~QHTYap-O=etu14CG%h#VLmjq$fPO5$XQ1@JggRsBSu#)4X2+q-MLsx*!C| z!C$2&B>;~*CM7PJ@}ka3@%EEds%^ko3axn(Fg59!bd=^I!8R zu%-(udA-Db3*0M-zNOo!<*(@^xAYNtptuiliglN-OPRA(;Z%eOmMW>!$1 zDe$I{`>A}l7c zwAMhLHQ{B>VQLsZS@M$CSIl_LlRaPYF?0p_@G772HY1wQwdf&M9ca#RSrR zr+-G1J$~SusJpd2H41})oK((t`~IUPpX1L|NZYNS2`j(pDevmMvrPFl^r>5V0eiWI z;xJbS+|Sipex&hW2oTYmINdc$+0$xL0^RZKFadufmvfR>I+vpQG*yss1{3+=GMD#x z!A$5p+@MkoZ59*VHkwo#Os!%4X6 zx>dGfno(!Md4nzt=DI|K}c|$qW48r+$8+TLFcI?zS@W4{gBs>ZyC4o07_vnuEra^Ff7xSiW zI{{e11D9b?{sou*7PyXg@+K=R0b~|;t}EF6gGW*EiNqBJx~ZYf+dT~;ba+T94=qxPA7%=04o1e4mr9@o`=B<|jI(qrnFa^`IsB^0Y>} zE57E_%z-;A$kW$M866iCFjkN2CY~l8uA7vwBKz@vpA`APTP8V>sQ~=MCq_M#HnEeo zo?>%dPs2=(Wpq0IP(xj!+^i1HdocZ6~S3fE9Y2}7a(-w{KVwu)m`B$eYrifNXLwm)HNE1op zF&ZKaF=OFI^zJn6pm48UCvnj=Zp2;%svS}jmv10b@nPRG_3(PrpgKI%dCwKf<1YMh zK~uT5|4;%}JGO!^=3JK6js^ZndG#4DHR?#Gr)*HjE<2U*)EJaKp7Y%?)Gx}qr+jze z#6w*Qa?Vcs_RpT2okjw?nsu<6bTgS$ik~g2jMi%Mv*)~30(&AZ0O)iuYHsUM5Jhf$ z%x47@>bfnwZ-Gt;i6Y$-VEuoll>|Bw;(&A)@XF*Eb>x-W{+nBjb64?reowt_orBDU zeO=BbQn{#fZGdjhK3%JY--4JejC`LC?uwLponYY!ptPs&^Enju8bPX!s*E2Ek3LC= z7u?24KbDMp$LywFa2o2b%5_64sh5Wa9(xdjK8X@C;=KVJKYVjwVk2@l_5A zLj<+uj;@b|k3^KmzS{X=KO0_HEUzfkl4o(hjw`y1 zCwvC1o<(PJ)l%i`@~J^fugkMt zA*`U{Z6QJc(^Rx?C3OQ*dN*MY6(9SFuu93dnD0{5h>*C3Xo%UCqZQ|9MLAj`tF!U0 znAH8mrwe=A@@&!^jZ~Urak2UfC2#U#Q*5pRMa5ek%n~N$OgA^)r;Fc>Z!rWEN14i4knyJ zvOh4-D#=)bKcpx`3LKa^wRa3BDWrmHHM;97s0+K9vAT*iR!7oy)x`W*widAd-{4}y zIzZOqf>bhmsZIwHXoI}4QP*Y@o7+5AzR6=&vi`daNI%M=zmbivrp^yqqb+p4?kcq& zaGpUi|LU5oA(c4^4=CRo(RkG8=!o)h;@8@Jzm{(wg(hqE-4*YHbJzH7 zA9GaXLaZB|sWul_rdZvD?QimIGV@e!TmLTILhEcCfsXnL{%`Yc=uy1hSuhwK5MH+C zmEn_BZl1tRS@Vh_8oCX@Nt-h{4}^nHCh|VE}Q;LYnE~W)1Mhq zpq`9NLX-pd-ataDrPxT}T1`>rICR`9HA|7RMFdcW#KsERl4VWcWRzhoRNRBb6jfHc z8R_P~$;108l5<8>1oyLHvDHtQiNg>T%q>Cq=$Js+3JPaw@QpG44t=$hGai6nj)`*$ zD5t$FO;+rW!^iq~Z41??kZR1^epKAhy$#}Fd-2$@J6&;DpVA{4ORCs`OBwwA*t|ta zslQxz*sG|O(mmWTx5(J3gyn2;P{sL5&JOW@US2Hz}*Hn9L&jxtL7sFbNorf{Z+J)ub}HCaQ#F z6mOeWK51ylKAZ|Wh0pRJa>&0`>-kni`Lk^&Av zb;MQr@RMyWPC9FuVG$EHXCeDd-l)K{CfnF9MWNcLr{QV;Z))gv1?u@KKXqrjLZ!I9 zhs2jnD*Hx?PiqUdjcJqFMzu+8!`obKL)%W{(e!6Mk(FK#$2kYmIa%p~|M0hYFbc~A ztJq9fG9eZPU6M9A*GZEO=F~|u!pd?WU~f%X0r7+oNam_GCyQN^-dQg8c#SK@k8q8d z{r;E6hhm!>$ThfYJShk9#_Ft)mt)uTSn&)`JT!fdIKdqo(g)4C#q!E6mrOVcl}R#` ztiUq`cxA6ETCr{ayzKpyPvtTXid9Bk(aM5Y6~$)ddm);w3%2<*x=JmdtR8i|tlH`z zd=3=FHRE}?P=n&Fei;OdLnp+9tzw)1)H#^ttQ0X$+R|B01x#tV!l{6AuPJ25yW;E# zQ^d=C@v#ZnVv!ODO-u^#Q~dFpST8Y)RKhjbY~+W%yf#!t-omRV&dCno_=98$$CKM? zcm_xtob0wJYY!ZLo$@%c>eg#_M3Bt}N3yEIF(BhZMIyPk1J1mva~=t@IvaC66uI&I zLG-np3~c1}z0>CjM5fy2NP@tdky6=$+{vKBIA&7lL{Mm;r;tY1@aC(pgW43Za6@6? z5@F$n*__Fg8eT6o_e)d-sBn++&yhG$)w0kPs`)@Q52)q>)g05I9xj;_DGU0Q4IYC} zOzN3x?|4O99tk6eE)?^%?U; z@9?)7QSow~%gLww&h$l;=K~Eb=Pk1OXbqM6C|7f4e!e{&Q=g`#MnBS=8Ks3Jj+~t6 z1-ZlPr{`1SAa|0z5?(WTih6jBWng_mAvFzhH|S|dI@WK~Q`7%1InSP)0m-HRl{(a~ z(o-`bx#quQZ2d+(HS7P9hwaJP|CjvPp8O1wTX)%8*4GmS)SUlInjq;+&Hew=&10wR z6g$n>sXHhna`IYi%~bUBs;@pM%zG4%QY<~|mGzX@qyFeb#DVh%h53*vGZO@#)}?@b z!>mNH2=|;8*LUu%Dt7_a!z#~VNLqZ`g7FP>zhI4%#qFRhECPN!+}DjVckMTo{cG za=GF%iFu65La;r>=(@-%F^^SQ!~n*r%xNk(N^zV788>{g*Jt_>AU(Xz!+WT{tfpF_ zGWSziK3HRMcp##D8W#UUxk06%e~mrW6gc@^n_R{lWm$t1XX-Zp$+hVx~`9 zUYEig$;7th)r!cXgFMq43KQD$a-jQo;Y>34{9*e*nmo)REjKOGSYZ~YBR8|y7(Fu| zb2A64{f57wT(Jg6%U&9gvstX=f>fGEWZ*NcumPv`M&Bg%Mp{)mUK51019NbUKeB`g zci!d!19$gro}GA@3FIbdsI2;3TC)mozk3Nd8=Ko9UQEDlXCQ$b%EyHqyq=>{jBad- zXjjyAr6)f3Ahca|&)A4LKUY2LQb0+&V!tw6OQ{;Be$h#}H)!yJOyqzfC8a&^hFL3I z%X4PdV<--?W#_PiG;PZ2ah>qhAa}3?cs8xsdWc%+@FYZ$MLASl*j_@k2jIO;VW~)CgT3n?s6F`3fG|4lxDuF+q-opfZjf>IRIAqwC(_K z$fs3rFY{?N*~@%ePuk0TTdd|Mwj^EErtn(%;m14Nm4>AZFQQYTn+eFnr~vFWR6 z`Pu>fn&~QyqY-g76vbZ66;`3*cC(h`N z*0t@E)tPswa}U@WgS+PUO7%U-(G+3SaIxFo<3U^BGhbHIiO;i%25Ai??L%pp@LCWY zoQ0@bN^DP#GeJ@$Of*r1Kee60b8)(ILIkMZg=v{;ptCYE{GCiyLri)*`Q+Q^cgkUq z>YOKMN8@A4&yvP$`Rfz{vC903f$ABO(_IR7N8ACKX77zvnQG|sqf@OSOFXpmA4*u_ zZ)C!ulVse%;}(qeh*@?^gaX#B2DY~KWVRZYFUU~OT-R0yT-*dp6vV6W2-I@0T~RAK z)VlpNe@IbqdfP{Kd%r)qFXH~J&bWHAj)%70YWw^A^V*WEe`7{85w55?ZT0|YAAwF` zb2k$&1Y=N-f9ephh|J1NwJ;sK?W}ec0QFef#$&KO&2G?8*&t5OlLE2~FI%WkF9`hY zl!zb-16Cq0J9X%a-)l@>@v<*!_soJ5U=?Vh9olQV22#4r9`R4=2W$185Pu zb@Qic=#_Ykxtf-gZzkB+_HM;`!h~!*V@{!EWA-_W0q7TQo=5wKiCCbi(DrDYF2^>16|NV_i@zm~6~EJM7CRG?JSSR&Gr7bV=V$LgmX8R3({EKg6rx=*^ zKVp&1sm{~l+9Xl*!w<8j_Mg{g91y8BrVP0_$sPct&r?9|+s=R0Aa6;7OZ zsC7xE+Rkqm*00A47bo^v3M^Eny0c+O(e)sk)Cl|hBO0$$Si|l6&&d&gz>CYv%p!XM zKEF7+XCJR`8iCoi?-B`-!4b6g*l0iUEW;Kn7PeuIBLYIUq}yO)HFA|@VFJ8p{YrmzxmvhG0JC;)~+hau_@xg8FB(mSxaDp1| z_}*pwf6&1t%&3sTEJ7}3T-2iY?t)p|nJ%d8LaJi-1ss2J9I%d7$A_*qiNe-?h+i*_?wj&;mqP21?U*jiFEY+7skU#TkF_FaXExlq zxO9}awg-x_k7V109TyNDmpvfZHTww;L`)2#8frJ*tF9{zSSr$%=4`_QM_@yCqB`p$ zlUT)W+DCam(wrDv$Eh^HA8?B_bvdfDAWn>}<5jHJisv|T)pMPq^CGibr#OF+T_1tC z?NP{*b&*GokU_3J3}T19d@t@7jVdgW){uF8B$jPMH7+AN%hl6Cp?C#E-FY}+1){d$ zk)^)?RoY<1>C4`cE*<eH4!mgjz|i*> z8((HZb_+2r@v*#$m_|R$Y!Od;>|DhTO2WeO2=$wb%<-b7NcZa9MP>jI3WNT{I1toKd~?1_k_zZ0u~eXvMu4rI>`yAjT-14dHoVJdn?rQ_^N zM@7s)*s6mv)#R`a{(!gS0i9EU+;6T4`>Awf@1mpXid+v>x}0q9;Pvvb1H)%%@PJEr z-iq+R=N-t?5>HrN@RSNlj}tu*lj@7uVQcW76%nC%k_Tl%FBH#g;IvwsbIq!aHz_Y> zx7H>%h6mzXE2fDoI4UPu93aBkIgtaWc9f!Zr< z@^zhypkjSz=2w^u^pMP{=H33+iVd-ce^$}^SP zXV2d6uXq?n=)aHo*b%(}FJCz{LAmLHap>d+l&W;auIuRn3G%m;%)iPD5&vPPtK1Uz zpQ}^hj({SIs6J#QzOgbo!r?{r0|rdTAacrB)%tHwr9N;Au=7QEP6~T|EwKRyt%?%O z#;L0mvC$Kd!QU?Gv-5v2SS0$0L^kV(7BteX5rWHhf;eEMh)JpUoPY~geI}oC4K`W; zyA(fPW!Iz1RDF92*V8-Y|EVJ-n#V+&tJRI^i_A`lDFziJ@C&LDsUv!TH3V-eD-*7_ zC0X50B=n_p!>yt9%lc9`V)|0l7`BnJoq0md;be%t$hc{M&pQ7dS8l#Sv?+kBhvIKl zy@KvZ_3ogAaRvp9L)$`|7)dg8-?k06GVa)Gb>LX_w-yiX8085UV+d!YoVZddj4Q?C zGTzfrF?g#fhHJ~;Z84{q}4WBj) z1UL*ARu9#?wIwwg+xFbxW4 z)n3rfu^LsVdZE=-nENI#=n$8U42vK!4|lWSyR=zW9J&^OsXswFw|tcQHJ#HZTco*I4aXa7T;w2w~Pm*sfinoH?NHoFW2I_wY>-Z(xu2! zT>8$gUk=hrf0gQGg$&?X0@-lP0@8k#{WQUD3V)jyuu{&1!=^ZkljZ|^rImwy;F!` zCLyiIA!a(FV{J?fGaePqM2t>^KIUWz(e}4`G61rK-u5;j$`WYU*=jMI){AvcVg^!* zjW@HH*E)OEJx8+?6TVm3=g#UZOlJn7f*-T*levN{{;sy=23W1w##ct*i@>jnWe z_7XOMuG%Gu0bmv}W6FaRWIP0wD%+j^Um)hGf*&A~RMs#)CjW*kVzT#f@M$8}aDRd--3! zWggkL;^HUOskTqCpI%k8eLB^SlVmvW^U1z_>!`n3*Infs7wFi)KeQqh4tt0nd>*hc zZZm>I9q5Oc%w1fc0-Zw+!<^OT81WWAWF}Ld^W-HkO4#uSA=J+k5W7JuZ?_%A#jQDfP$s}Y`&is~nh0>j(z6jcA2*|?N4EcyY6 zJ$Jus8}J~!TWwxL7)nY(+Jou%6*IJ{OvFqDVV@i9(@mwbU#xy!mO~x}HU&rBQXhR_ zr~a{?Hb-E)#F(c88T@7NHiPQJ@OowZm;t4H4DBhao2u%oGLo&@f%y$#-1PH=O}EUq>Y+>Do+ z<8{FLl@A^XckTXlnWfsV;!AeJ%L&GisopQN2My}-0Iv$@iF3Ug+>5I(0Z6Xy62UHm&nn%K%&svDEXC%5j3!Ly;Pu_bK zd0u<^o(Ia`KYZ8&W-3_03(vUWITW6i{9CmX?ChUBlnaD%T(&WJ)RIw;@!TlX0t1$} z{(V`b46T!?$fG9Xx~o(VU^GRVDmc^L2h)Xx^{Z-*DnY$2-26+%fbmSleU^>AHifzT z+-Z^OMM+?s?!?14sXW~mJ=PK`Hg^ib(It$d1%JJ1uz1y7{M)9Xqhi7NPO7Xr<{-q{ zSrnz=n8N|_pi+aP$*0}3S@N>1%M`7s;Y1 z%zu$Mu5Skw$t0t?L#_RO;;+N;P38s$e=rO(%hMa!^?@I%n&MHEWxSPShM?Nfmnq-M z*`B*V=T?fhb{LxEzlw}?7%y08k28IlYqT(LPKFdg`j@=SG7 z5<{1n!I#IZ8IC^aGXDG(-`<=o^1|L*W{8~d@-5LGu{*2&{1pgaqWSfFG*g53Z7C;x zUTYg-@C+5YH03U_?^%edN!qqoFEfAoge2u_Kj-mGJacPb2k=VdroYAoTge`a&bRCl zAvYZ&z%YqLNMc^wumqpm8Wyl_Ce;F(OmUM_j@gwLDFeG?IYZI<9r)eW3F7|4amuy? zx#h`K=fLjTjdsHCu!3(36OT;C{@X|UZXNXAkbbB&MZ*RDtt)(% z#AQpm@!IXv-TL*>mNBc&=d~_5vAiF?zI}x_EEo^jksuxthF9$f^&dBCPnojiWU!Vn z`VQM;2ox3&1UFTM_wPsx$$QQ#Up(i{?u;mgFiZc7-Rv>fb7Se3BSnFD)R!rt!xnZ^ z5;i&&Q|Vk>*e64_Bw(4i*$-9mS!5{Q_ho3v2H(4v_6Dr+8-3V+v|e=O1(@tWr~5tO zbyxctzWrr}dd2Hdlt5P!D)V}6CFp+yH5K2kusR$k6sDJ|IzsWwZ=lq?kViKBD>iP5 ze213|{)1Bu{sXT9xB=jLfZG9X11K5t2Nn#BFk^uVv>^XO$;VAJa?0#zrp1jd>N~Uw*^s>NxlLga4rSqE&UJ1TrQJ!y5HG7q@9$wDRyr zM=mE5KUEK39x>`+BXkjdrFG&u2i1YT4#vt#ZI@>a5=JTIz%ChQ+dZM*izLL_m$8&ur|DoOVnmb^R4pN)g)sygU z)KfGV*P{qU)H`akQA2HJG)BogU@!i+$>A%>t2nd(k;lQxmW{j7QgF?fLiP6_?2Jy0 zg%gtArBK!RfR;+Bm_#iA!HJ3wUH2;4=h49H!3XYjDS*t42LiL_9}ngF-9+n46aIzr zi65uRuLCRGGf=<0sqtjN+5M+a`u85)_bN}0IcribEq9&SI$V>3cWBbwqrmss7Z~py&F=ZSq0Ls!1(7%Y9E=6D)-fjQ z!jf!Msu*HvHsvqybE|O)5ZE>ORA9{w(dv-{`d);WNz0yP5oVtIj++m6OwDF6r&20xZOZ~#u7FHZNR(B;} zB~hLjuhGef7p%`%Jh?#;kvh4sq3?!&sE9-BoKI+LO263$&iG$PsMs6S0Crod69U7% zz9BgL<9<`SC+SyZQr!GnDS1h>djis~sBu@3K1LI%uEN(EMvJGc$DW6K!~73F9PPB~ zZQgea2%cDtRfh+`(d7>pN2`_=RRw@oACm`q_b)a?|DDfv)To7wkw{7|^=&q$Go78dLNoeWfCu5LwOn0l}d`lXo z?0XKcJGw$N1>ZT^E2!5KCa*{cNhv8+&e3B3@g;_ ziDCW(E*+h<=jgxA7+P$Tl5=m!g@qtHgNk#D&ceR*H{F8 zFb9enjUGLUD;)wfRW^r~cz26fRX;4bpe#VeTzZqo`6ZVgi&K1R;wxwMei}>3ZQ>`y zZqKeRpt%ioguRI@(9hwLV_`iX6xaO@`ZPC`pm3o9^|XpnG@e{bi5SfSgs&Y75-rA0 zkM$($TK=^&<;cm-sOv;FQ5O5z_#dmD*?kCYZ?f3LemMGgnj}X38s{GO6)y|IyN>T1 zM)dpx2L~5p-{4|Uo17_==77CDhwYnNRA&KQw#+Q5fxCOumz3cODDvgF-)f}wK{zlI zkN!GZJoyW(`g(kXJmXHO|58e){(|B*#WBOsN0m?sJa)LS-md36)Y`$|+g~pfyZ6U~ zPYe`C_~KP3dO2*#K(%=exa>p>IX$(&5c`)(D8b9XgTHRROWzx+xW>gxCpeXanaImjsOft0ay%8LRH^ z_Qsg*_J(r7r`Aw1v!51Bq>&KSd4Z@QGdpN~Rph~HlXA&^6Pchfk?(LcIpU;=Bv30k zjW&_9EGA`-f83b$=kv(bdw5kk8N%}9qrE)&8*8`N%fUG>wVaR1DPJ6Bs0M}7mXB`a z`U<>?(#7Pc81)`*>y%=Hr#3{D{%WNcr4<%6xDo)SaKQwHbKc@1t7)Cs=D_wJ$>2dF zK?Ji!v%!GxXr+SdvsR@X>Z?lh4%kMQJuJnnS3&sgvyJ^?BCfC}1R*M`3Dfw!KH_T~~sQ)Pk?HlZi$S2_-X z5$@~L1H6{b_^Dc6*B{PeREMcN$GZ@JI2|=}X5Saw0o=@egUL(Th2K$DW#sN}oa3z*qOeKKmajvQ!rJdAtn)@CY<(P(R;nZnYve+D3{yCQ!N z{`^doS}rRc^@F*@3xr&P{?#6jYD*)x8TQ)L)1)m3UWhxycPX9p+u4!n?l&agcLwN z5jK~a%@zEQo(lB^jACjEjJK%J`g&@eaWAN;_LTjIgFoV^|0H5*v>cxJ=CLrzsn0L<_-dFHSZ?=#%)j^B!HILFu z7>DPgs+!gcKFdo;W4EA+jtV~8OBm0VRNScGbG(Ff!0uG=tG$E?fIWb*c?lB%dkTH` z5+(ums)B#!B}`^LP=zCO$xE2R(iI-iyDV=Z6Hxz3KHFQE23S}npW`h|2Q0dhU+pc- zz`fBa{&!D73F8Xb!>{)e7O<{}{@qJh$k94)VG-V?73ShG+M+hPppyT<{7;8clWG(4 zX_Ν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 aw)N_Ws$|krQV2`r!o&}(^RJl~I{yz^Td7b0 delta 21079 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 Date: Thu, 28 Apr 2022 16:27:37 -0600 Subject: [PATCH 15/25] New baserom with various fixes for both font and multiclient issue with pottery Bump TFH limit to 850. It throws an error if you try to generate with too many pieces. --- ItemList.py | 15 +++++++++------ Main.py | 4 ++-- RELEASENOTES.md | 9 +++++++++ Rom.py | 7 ++++--- data/base2current.bps | Bin 90117 -> 93063 bytes source/item/FillUtil.py | 2 +- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/ItemList.py b/ItemList.py index 935e2e61..dacbdf14 100644 --- a/ItemList.py +++ b/ItemList.py @@ -44,6 +44,7 @@ Difficulty = namedtuple('Difficulty', 'progressive_bow_limit', 'heart_piece_limit', 'boss_heart_container_limit']) total_items_to_place = 153 +max_goal = 850 difficulties = { 'normal': Difficulty( @@ -203,6 +204,7 @@ def generate_itempool(world, player): world.push_item(loc, ItemFactory('Triforce', player), False) loc.event = True loc.locked = True + loc.forced_item = loc.item world.get_location('Ganon', player).event = True world.get_location('Ganon', player).locked = True @@ -774,7 +776,8 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, if goal in ['triforcehunt', 'trinity']: if treasure_hunt_total == 0: treasure_hunt_total = 30 if goal == 'triforcehunt' else 10 - triforcepool = ['Triforce Piece'] * int(treasure_hunt_total) + # triforce pieces max out + triforcepool = ['Triforce Piece'] * min(treasure_hunt_total, max_goal) pool.extend(alwaysitems) @@ -967,8 +970,8 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s pool.append(thisbottle) if customitemarray["triforcepieces"] > 0 or customitemarray["triforcepiecesgoal"] > 0: - # To display, count must be between 1 and 254 - larger values are not yet supported - treasure_hunt_count = max(min(customitemarray["triforcepiecesgoal"], 254), 1) + # Location pool doesn't support larger values + treasure_hunt_count = max(min(customitemarray["triforcepiecesgoal"], max_goal), 1) treasure_hunt_icon = 'Triforce Piece' # Ensure game is always possible to complete here, force sufficient pieces if the player is unwilling. if ((customitemarray["triforcepieces"] < treasure_hunt_count) and (goal in ['triforcehunt', 'trinity']) @@ -1053,7 +1056,7 @@ def make_customizer_pool(world, player): return pool, placed_items, precollected_items, clock_mode, 1 -# To display, count must be between 1 and 254 - larger values are not yet supported +# location pool doesn't support larger values at this time def set_default_triforce(goal, custom_goal, custom_total): triforce_goal, triforce_total = 0, 0 if goal == 'triforcehunt': @@ -1061,9 +1064,9 @@ def set_default_triforce(goal, custom_goal, custom_total): elif goal == 'trinity': triforce_goal, triforce_total = 8, 10 if custom_goal > 0: - triforce_goal = max(min(custom_goal, 254), 1) + triforce_goal = max(min(custom_goal, max_goal), 1) if custom_total > 0: - triforce_total = max(min(custom_total, 254), triforce_goal) + triforce_total = max(min(custom_total, max_goal), triforce_goal) return triforce_goal, triforce_total diff --git a/Main.py b/Main.py index c2af3655..75fd4dd6 100644 --- a/Main.py +++ b/Main.py @@ -103,8 +103,8 @@ def main(args, seed=None, fish=None): world.potshuffle = args.shufflepots.copy() world.mixed_travel = args.mixed_travel.copy() world.standardize_palettes = args.standardize_palettes.copy() - world.treasure_hunt_count = args.triforce_goal.copy() - world.treasure_hunt_total = args.triforce_pool.copy() + world.treasure_hunt_count = {k: int(v) for k, v in args.triforce_goal.items()} + world.treasure_hunt_total = {k: int(v) for k, v in args.triforce_pool.items()} world.shufflelinks = args.shufflelinks.copy() world.pseudoboots = args.pseudoboots.copy() world.overworld_map = args.overworld_map.copy() diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b18c1af0..668c1c52 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -157,6 +157,15 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o #### Volatile +* 1.0.2.0 + * Updated baserom to bleeding edge + * Pottery and enemy SRAM re-located to final destination + * Bulk of work on new font + * Updated TFH to support up to 850 pieces + * Fix for major item algorithm and pottery + * Updated map display on keysanity menu to work better with overworld_amp option + * Minor bug in crossed doors + * Minor bug in MultiClient which would count switches * 1.0.1.13 * New pottery modes * Trinity goal added diff --git a/Rom.py b/Rom.py index 3f1506ea..dcda3719 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '3c85536ef5463d329adb2e9e3cda654a' +RANDOMIZERBASEHASH = '8b87b7c4f37ab57463b93c5afd353299' class JsonRom(object): @@ -1197,7 +1197,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(0x18003F, 0x01 if world.swords[player] == 'swordless' else 0x00) # hammer can harm ganon rom.write_byte(0x180041, 0x01 if world.swords[player] == 'swordless' else 0x00) # swordless medallions rom.write_byte(0x180044, 0x01 if world.swords[player] == 'swordless' else 0x00) # hammer activates tablets - rom.initial_sram.set_swordless_curtains() # open curtains + if world.swords[player] == 'swordless': + rom.initial_sram.set_swordless_curtains() # open curtains # set up clocks for timed modes if world.shuffle[player] == 'vanilla': @@ -1245,7 +1246,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): # set up goals for treasure hunt rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon[player] == 'Triforce Piece' else [0x0D, 0x28]) if world.goal[player] in ['triforcehunt', 'trinity']: - rom.write_byte(0x180167, int(world.treasure_hunt_count[player]) % 256) + rom.write_bytes(0x180167, int16_as_bytes(world.treasure_hunt_count[player])) rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled) rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed diff --git a/data/base2current.bps b/data/base2current.bps index 43f2319ea5e516ec4af6be3c1a619e3d043adfab..ecddb99bb1d1ae348ba05409d10987cebdec1886 100644 GIT binary patch delta 8094 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 diff --git a/source/item/FillUtil.py b/source/item/FillUtil.py index 4f052bd4..9614eeef 100644 --- a/source/item/FillUtil.py +++ b/source/item/FillUtil.py @@ -275,7 +275,7 @@ def massage_item_pool(world): world.itempool.remove(deleted) discrepancy -= 1 if discrepancy > 0: - logging.getLogger('').warning(f'Too many good items in pool, something will be removed at random') + raise Exception(f'Too many required items in pool, {discrepancy} items cannot be placed') if world.item_pool_config.placeholders is not None: removed = 0 single_rupees = [item for item in world.itempool if item.name == 'Rupee (1)'] From ecf6a0bd108c215274ae7cf29da4c04dec0e3dc5 Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 29 Apr 2022 08:10:08 -0600 Subject: [PATCH 16/25] Version bump Generation fix for inverted --- Main.py | 2 +- Rom.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Main.py b/Main.py index 75fd4dd6..7421e8cb 100644 --- a/Main.py +++ b/Main.py @@ -31,7 +31,7 @@ from Utils import output_path, parse_player_names from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config from source.tools.BPS import create_bps_from_data -__version__ = '1.0.1.13v' +__version__ = '1.0.2.0-v' from source.classes.BabelFish import BabelFish diff --git a/Rom.py b/Rom.py index dcda3719..554f3451 100644 --- a/Rom.py +++ b/Rom.py @@ -15,7 +15,7 @@ try: except ImportError: raise Exception('Could not load BPS module') -from BaseClasses import CollectionState, ShopType, Region, Location, Door, DoorType, RegionType, PotItem, LocationType +from BaseClasses import ShopType, Region, Location, Door, DoorType, RegionType, LocationType from DoorShuffle import compass_data, DROptions, boss_indicator, dungeon_portals from Dungeons import dungeon_music_addresses, dungeon_table from Regions import location_table, shop_to_location_table, retro_shops @@ -969,7 +969,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): if world.mode[player] in ['open', 'inverted']: init_open_mode_sram(rom) if world.mode[player] == 'inverted': - set_inverted_mode(world, rom) + set_inverted_mode(world, player, rom) elif world.mode[player] == 'standard': init_standard_mode_sram(rom) @@ -2724,7 +2724,7 @@ OtherEntrances = {'Blinds Hideout': 'Blind\'s old house', 'Kings Grave': 'The northeastmost grave', 'Bonk Fairy (Light)': 'The rock pile near your home', 'Hookshot Fairy': 'The left paired cave on east DM', - 'Bonk Fairy (Dark)': 'The rock pile near the old bomb shop', + 'Bonk Fairy (Dark)': 'The rock pile near the old bomb shop', 'Dark Lake Hylia Fairy': 'The cave NE dark Lake Hylia', 'C-Shaped House': 'The NE house in Village of Outcasts', 'Dark Death Mountain Fairy': 'The SW cave on dark DM', From ea745ff22e1d66a6386a40341cb0427af525a762 Mon Sep 17 00:00:00 2001 From: aerinon Date: Sat, 30 Apr 2022 15:28:29 -0600 Subject: [PATCH 17/25] Hotfix for paired doors Also made dashable filter work --- DoorShuffle.py | 6 ++++-- Main.py | 2 +- RELEASENOTES.md | 3 +++ Rom.py | 2 +- data/base2current.bps | Bin 93063 -> 93062 bytes 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/DoorShuffle.py b/DoorShuffle.py index 8dfcb726..0d36a2b0 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -1810,8 +1810,10 @@ ohko_forbidden = { def filter_dashable_candidates(candidates, world): - forbidden_set = dashable_forbidden if world.timer in ['ohko', 'timed-ohko'] else ohko_forbidden - return [x for x in candidates if x not in forbidden_set and x.dest not in forbidden_set] + forbidden_set = dashable_forbidden + if world.timer in ['ohko', 'timed-ohko']: + forbidden_set = ohko_forbidden.union(dashable_forbidden) + return [x for x in candidates if x.name not in forbidden_set and x.dest.name not in forbidden_set] def shuffle_bombable_dashable(bd_candidates, world, player): diff --git a/Main.py b/Main.py index 7421e8cb..ba55ad46 100644 --- a/Main.py +++ b/Main.py @@ -31,7 +31,7 @@ from Utils import output_path, parse_player_names from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config from source.tools.BPS import create_bps_from_data -__version__ = '1.0.2.0-v' +__version__ = '1.0.2.1-v' from source.classes.BabelFish import BabelFish diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 668c1c52..ebaf2919 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -157,6 +157,9 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o #### Volatile +* 1.0.2.1 + * Fix for paired doors + * Fix for forbidding certain dashable doors (it actually does something this time) * 1.0.2.0 * Updated baserom to bleeding edge * Pottery and enemy SRAM re-located to final destination diff --git a/Rom.py b/Rom.py index 554f3451..3819158a 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '8b87b7c4f37ab57463b93c5afd353299' +RANDOMIZERBASEHASH = '490b6fa137b3f76a76d4e4905ddfb34b' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index ecddb99bb1d1ae348ba05409d10987cebdec1886..0f751ab3d93517643c9682d32f5a16a11fcf30d6 100644 GIT binary patch delta 99 zcmV-p0G$7a*9C^x1+Y>93&k)33k3iH01i#@gIoc(Tmb-VfWJ)(p+EjX0h%(5B2tRCtu+DCH3+@zAaD<% Fl>qn>AnX7D delta 100 zcmV-q0Gt1Y*9C{y1+Y>93XL!V3k8U&HciQcT>-aU0RaLF3!S9`DFFY41Fx4ew`mLk zA1NgpH-I!?aFj64^Xx2!b*(lrRM|8FVs G6`PA*hazeK From 6ab426b9f3dd63f26d74c7cfc3cc8b75cee1e7b8 Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 3 May 2022 13:55:39 -0600 Subject: [PATCH 18/25] Fix for keydrops/enemy drops to not be repeatable --- Main.py | 2 +- PotShuffle.py | 2 +- RELEASENOTES.md | 3 +++ Rom.py | 2 +- data/base2current.bps | Bin 93062 -> 93043 bytes 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Main.py b/Main.py index ba55ad46..ea40af54 100644 --- a/Main.py +++ b/Main.py @@ -31,7 +31,7 @@ from Utils import output_path, parse_player_names from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config from source.tools.BPS import create_bps_from_data -__version__ = '1.0.2.1-v' +__version__ = '1.0.2.2-v' from source.classes.BabelFish import BabelFish diff --git a/PotShuffle.py b/PotShuffle.py index 17107bae..90258478 100644 --- a/PotShuffle.py +++ b/PotShuffle.py @@ -1052,7 +1052,7 @@ class PotSecretTable(object): rom.write_bytes(pointer_address + room * 2, int16_as_bytes(data_address)) for pot in self.room_map[room]: rom.write_bytes(data_pointer + list_idx * 3, pot.pot_data()) - if pot.location is not None: + if pot.location is not None and not pot.location.forced_item: collection_rate_mask |= 1 << (15 - list_idx) if colorize and pot.obj_ref: pot.obj_ref.change_type(Shuffled_Pot) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ebaf2919..8c5a8589 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -157,6 +157,9 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o #### Volatile +* 1.0.2.2 + * Change to all key pots and enemy key drops: always use the same address + * Don't colorize key pots in mystery is the item is "forced" * 1.0.2.1 * Fix for paired doors * Fix for forbidding certain dashable doors (it actually does something this time) diff --git a/Rom.py b/Rom.py index 3819158a..25ee90e3 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '490b6fa137b3f76a76d4e4905ddfb34b' +RANDOMIZERBASEHASH = '94fd47b16641a1aa44f22e21c8a7a024' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 0f751ab3d93517643c9682d32f5a16a11fcf30d6..9643a3cd34345ca166283b87a106c8f27708a869 100644 GIT binary patch delta 228 zcmVO6>*B6zTbQ*}{;+}y zwh93r6afjBA07cD2*(I~gMk^Vf|pz#0cHVim%|XtSOmT(h$XLIDZ$u&C;|jUoiG zgZ>G({s{pd6ag8R9UcKB8Lv>PsFQc8jTt!5YnOB;gn Date: Fri, 13 May 2022 16:09:03 -0600 Subject: [PATCH 19/25] MultiClient fix for shop sram move --- Main.py | 2 +- MultiClient.py | 10 +++++----- RELEASENOTES.md | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Main.py b/Main.py index ea40af54..2c43b714 100644 --- a/Main.py +++ b/Main.py @@ -31,7 +31,7 @@ from Utils import output_path, parse_player_names from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config from source.tools.BPS import create_bps_from_data -__version__ = '1.0.2.2-v' +__version__ = '1.0.2.3-v' from source.classes.BabelFish import BabelFish diff --git a/MultiClient.py b/MultiClient.py index bc496f5b..fbde673d 100644 --- a/MultiClient.py +++ b/MultiClient.py @@ -90,9 +90,11 @@ INGAME_MODES = {0x07, 0x09, 0x0b} SAVEDATA_START = WRAM_START + 0xF000 SAVEDATA_SIZE = 0x500 -POT_ITEMS_SRAM_START = WRAM_START + 0x016018 -SPRITE_ITEMS_SRAM_START = WRAM_START + 0x016268 +POT_ITEMS_SRAM_START = WRAM_START + 0x016018 # 2 bytes per room +SPRITE_ITEMS_SRAM_START = WRAM_START + 0x016268 # 2 bytes per room +SHOP_SRAM_START = WRAM_START + 0x0164B8 # 2 bytes? ITEM_SRAM_SIZE = 0x250 +SHOP_SRAM_LEN = 0x29 # 41 tracked items RECV_PROGRESS_ADDR = SAVEDATA_START + 0x4D0 # 2 bytes RECV_ITEM_ADDR = SAVEDATA_START + 0x4D2 # 1 byte @@ -103,11 +105,9 @@ SCOUT_LOCATION_ADDR = SAVEDATA_START + 0x4D7 # 1 byte SCOUTREPLY_LOCATION_ADDR = SAVEDATA_START + 0x4D8 # 1 byte SCOUTREPLY_ITEM_ADDR = SAVEDATA_START + 0x4D9 # 1 byte SCOUTREPLY_PLAYER_ADDR = SAVEDATA_START + 0x4DA # 1 byte -SHOP_ADDR = SAVEDATA_START + 0x302 # 2 bytes? DYNAMIC_TOTAL_ADDR = SAVEDATA_START + 0x33E # 2 bytes MODE_FLAGS = SAVEDATA_START + 0x33D # 1 byte -SHOP_SRAM_LEN = 0x29 # 41 tracked items location_shop_order = [Regions.shop_to_location_table.keys()] + [Regions.retro_shops.keys()] location_shop_ids = {0x0112, 0x0110, 0x010F, 0x00FF, 0x011F, 0x0109, 0x0115} @@ -894,7 +894,7 @@ async def track_locations(ctx : Context, roomid, roomdata): try: if ctx.shop_mode or ctx.retro_mode: - misc_data = await snes_read(ctx, SHOP_ADDR, SHOP_SRAM_LEN) + misc_data = await snes_read(ctx, SHOP_SRAM_START, SHOP_SRAM_LEN) for cnt, b in enumerate(misc_data): my_check = Regions.shop_table_by_location_id[0x400000 + cnt] if int(b) > 0 and my_check not in ctx.locations_checked: diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8c5a8589..1ea8bfb4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -157,6 +157,9 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o #### Volatile +* 1.0.2.3 + * Fix MultiClient for new shop data location in SRAM + * Some minor text updates * 1.0.2.2 * Change to all key pots and enemy key drops: always use the same address * Don't colorize key pots in mystery is the item is "forced" From 7025f6756cc1ce3c138129cad7066c481af756ff Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 13 May 2022 16:09:49 -0600 Subject: [PATCH 20/25] Text for a few lowercase spot --- Items.py | 38 +++++++------- PotShuffle.py | 4 +- Regions.py | 20 ++++---- Text.py | 137 +++++++++++++++++++++++++------------------------- 4 files changed, 99 insertions(+), 100 deletions(-) diff --git a/Items.py b/Items.py index 028c3cac..06e1dcec 100644 --- a/Items.py +++ b/Items.py @@ -27,23 +27,23 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche 'Progressive Bow': (True, False, None, 0x64, 150, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'), 'Progressive Bow (Alt)': (True, False, None, 0x65, 150, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'), 'Book of Mudora': (True, False, None, 0x1D, 150, 'This is a\nparadox?!', 'and the story book', 'the scholarly kid', 'moon runes for sale', 'drugs for literacy', 'book-worm boy can read again', 'the Book'), - 'Hammer': (True, False, None, 0x09, 250, 'stop\nhammer time!', 'and m c hammer', 'hammer-smashing kid', 'm c hammer for sale', 'stop... hammer time', 'stop, hammer time', 'the hammer'), + 'Hammer': (True, False, None, 0x09, 250, 'stop\nhammer time!', 'and m c hammer', 'hammer-smashing kid', 'm c hammer for sale', 'stop... hammer time', 'stop, hammer time', 'the Hammer'), 'Hookshot': (True, False, None, 0x0A, 250, 'BOING!!!\nBOING!!!\nBOING!!!', 'and the tickle beam', 'tickle-monster kid', 'tickle beam for sale', 'witch and tickle boy', 'beam boy tickles again', 'the Hookshot'), 'Magic Mirror': (True, False, None, 0x1A, 250, 'Isn\'t your\nreflection so\npretty?', 'the face reflector', 'the narcissistic kid', 'your face for sale', 'trades looking-glass', 'narcissistic boy is happy again', 'the Mirror'), 'Ocarina': (True, False, None, 0x14, 250, 'Save the duck\nand fly to\nfreedom!', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'ocarina boy plays again', 'the Flute'), 'Pegasus Boots': (True, False, None, 0x4B, 250, 'Gotta go fast!', 'and the sprint shoes', 'the running-man kid', 'sprint shoe for sale', 'shrooms for speed', 'gotta-go-fast boy runs again', 'the Boots'), - 'Power Glove': (True, False, None, 0x1B, 100, 'Now you can\nlift weak\nstuff!', 'and the grey mittens', 'body-building kid', 'lift glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'the glove'), - 'Cape': (True, False, None, 0x19, 50, 'Wear this to\nbecome\ninvisible!', 'the camouflage cape', 'red riding-hood kid', 'red hood for sale', 'hood from a hood', 'dapper boy hides again', 'the cape'), - 'Mushroom': (True, False, None, 0x29, 50, 'I\'m a fun guy!\n\nI\'m a funghi!', 'and the legal drugs', 'the drug-dealing kid', 'legal drugs for sale', 'shroom swap', 'shroom boy sells drugs again', 'the mushroom'), - 'Shovel': (True, False, None, 0x13, 50, 'Can\n You\n Dig it?', 'and the spade', 'archaeologist kid', 'dirt spade for sale', 'can you dig it', 'shovel boy digs again', 'the shovel'), - 'Lamp': (True, False, None, 0x12, 150, 'Baby, baby,\nbaby.\nLight my way!', 'and the flashlight', 'light-shining kid', 'flashlight for sale', 'fungus for illumination', 'illuminated boy can see again', 'the lamp'), - 'Magic Powder': (True, False, None, 0x0D, 50, 'you can turn\nanti-faeries\ninto faeries', 'and the magic sack', 'the sack-holding kid', 'magic sack for sale', 'the witch and assistant', 'magic boy plays marbles again', 'the powder'), - 'Moon Pearl': (True, False, None, 0x1F, 200, ' Bunny Link\n be\n gone!', 'and the jaw breaker', 'fortune-telling kid', 'lunar orb for sale', 'shrooms for moon rock', 'moon boy plays ball again', 'the moon pearl'), - 'Cane of Somaria': (True, False, None, 0x15, 250, 'I make blocks\nto hold down\nswitches!', 'and the red blocks', 'the block-making kid', 'block stick for sale', 'block stick for trade', 'cane boy makes blocks again', 'the red cane'), - 'Fire Rod': (True, False, None, 0x07, 250, 'I\'m the hot\nrod. I make\nthings burn!', 'and the flamethrower', 'fire-starting kid', 'rage rod for sale', 'fungus for rage-rod', 'firestarter boy burns again', 'the fire rod'), - 'Flippers': (True, False, None, 0x1E, 250, 'fancy a swim?', 'and the toewebs', 'the swimming kid', 'finger webs for sale', 'shrooms let you swim', 'swimming boy swims again', 'the flippers'), - 'Ice Rod': (True, False, None, 0x08, 250, 'I\'m the cold\nrod. I make\nthings freeze!', 'and the freeze ray', 'the ice-bending kid', 'freeze ray for sale', 'fungus for ice-rod', 'ice-cube boy freezes again', 'the ice rod'), - 'Titans Mitts': (True, False, None, 0x1C, 200, 'Now you can\nlift heavy\nstuff!', 'and the golden glove', 'body-building kid', 'carry glove for sale', 'fungus for bling-gloves', 'body-building boy has gold again', 'the mitts'), + 'Power Glove': (True, False, None, 0x1B, 100, 'Now you can\nlift weak\nstuff!', 'and the grey mittens', 'body-building kid', 'lift glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'the Glove'), + 'Cape': (True, False, None, 0x19, 50, 'Wear this to\nbecome\ninvisible!', 'the camouflage cape', 'red riding-hood kid', 'red hood for sale', 'hood from a hood', 'dapper boy hides again', 'the Cape'), + 'Mushroom': (True, False, None, 0x29, 50, 'I\'m a fun guy!\n\nI\'m a funghi!', 'and the legal drugs', 'the drug-dealing kid', 'legal drugs for sale', 'shroom swap', 'shroom boy sells drugs again', 'the Mushroom'), + 'Shovel': (True, False, None, 0x13, 50, 'Can\n You\n Dig it?', 'and the spade', 'archaeologist kid', 'dirt spade for sale', 'can you dig it', 'shovel boy digs again', 'the Shovel'), + 'Lamp': (True, False, None, 0x12, 150, 'Baby, baby,\nbaby.\nLight my way!', 'and the flashlight', 'light-shining kid', 'flashlight for sale', 'fungus for illumination', 'illuminated boy can see again', 'the Lamp'), + 'Magic Powder': (True, False, None, 0x0D, 50, 'you can turn\nanti-faeries\ninto faeries', 'and the magic sack', 'the sack-holding kid', 'magic sack for sale', 'the witch and assistant', 'magic boy plays marbles again', 'the Powder'), + 'Moon Pearl': (True, False, None, 0x1F, 200, ' Bunny Link\n be\n gone!', 'and the jaw breaker', 'fortune-telling kid', 'lunar orb for sale', 'shrooms for moon rock', 'moon boy plays ball again', 'the Moon Pearl'), + 'Cane of Somaria': (True, False, None, 0x15, 250, 'I make blocks\nto hold down\nswitches!', 'and the red blocks', 'the block-making kid', 'block stick for sale', 'block stick for trade', 'cane boy makes blocks again', 'the red Cane'), + 'Fire Rod': (True, False, None, 0x07, 250, 'I\'m the hot\nrod. I make\nthings burn!', 'and the flamethrower', 'fire-starting kid', 'rage rod for sale', 'fungus for rage-rod', 'firestarter boy burns again', 'the Fire Rod'), + 'Flippers': (True, False, None, 0x1E, 250, 'fancy a swim?', 'and the toewebs', 'the swimming kid', 'finger webs for sale', 'shrooms let you swim', 'swimming boy swims again', 'the Flippers'), + 'Ice Rod': (True, False, None, 0x08, 250, 'I\'m the cold\nrod. I make\nthings freeze!', 'and the freeze ray', 'the ice-bending kid', 'freeze ray for sale', 'fungus for ice-rod', 'ice-cube boy freezes again', 'the Ice Rod'), + 'Titans Mitts': (True, False, None, 0x1C, 200, 'Now you can\nlift heavy\nstuff!', 'and the golden glove', 'body-building kid', 'carry glove for sale', 'fungus for bling-gloves', 'body-building boy has gold again', 'the Mitts'), 'Bombos': (True, False, None, 0x0F, 100, 'Burn, baby,\nburn! Fear my\nring of fire!', 'and the swirly coin', 'coin-collecting kid', 'swirly coin for sale', 'shrooms for swirly-coin', 'medallion boy melts room again', 'Bombos'), 'Ether': (True, False, None, 0x10, 100, 'This magic\ncoin freezes\neverything!', 'and the bolt coin', 'coin-collecting kid', 'bolt coin for sale', 'shrooms for bolt-coin', 'medallion boy sees floor again', 'Ether'), 'Quake': (True, False, None, 0x11, 100, 'Maxing out the\nRichter scale\nis what I do!', 'and the wavy coin', 'coin-collecting kid', 'wavy coin for sale', 'shrooms for wavy-coin', 'medallion boy shakes dirt again', 'Quake'), @@ -93,12 +93,12 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche 'Progressive Armor': (False, True, None, 0x60, 50, 'time for a\nchange of\nclothes?', 'and the unknown hat', 'the protected kid', 'new hat for sale', 'the clothing store', 'tailor boy has threads again', 'some armor'), 'Blue Boomerang': (True, False, None, 0x0C, 50, 'No matter what\nyou do, blue\nreturns to you', 'and the bluemarang', 'the bat-throwing kid', 'bent stick for sale', 'fungus for puma-stick', 'throwing boy plays fetch again', 'the blue boomerang'), 'Red Boomerang': (True, False, None, 0x2A, 50, 'No matter what\nyou do, red\nreturns to you', 'and the badmarang', 'the bat-throwing kid', 'air foil for sale', 'fungus for return-stick', 'magical boy plays fetch again', 'the red boomerang'), - 'Blue Shield': (False, True, None, 0x04, 50, 'Now you can\ndefend against\npebbles!', 'and the stone blocker', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'the blue shield'), - 'Red Shield': (False, True, None, 0x05, 500, 'Now you can\ndefend against\nfireballs!', 'and the shot blocker', 'shield-wielding kid', 'fire shield for sale', 'fungus for fire shield', 'shield boy defends again', 'the red shield'), - 'Mirror Shield': (True, False, None, 0x06, 200, 'Now you can\ndefend against\nlasers!', 'and the laser blocker', 'shield-wielding kid', 'face shield for sale', 'fungus for face shield', 'shield boy defends again', 'the mirror shield'), + 'Blue Shield': (False, True, None, 0x04, 50, 'Now you can\ndefend against\npebbles!', 'and the stone blocker', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a blue shield'), + 'Red Shield': (False, True, None, 0x05, 500, 'Now you can\ndefend against\nfireballs!', 'and the shot blocker', 'shield-wielding kid', 'fire shield for sale', 'fungus for fire shield', 'shield boy defends again', 'a red shield'), + 'Mirror Shield': (True, False, None, 0x06, 200, 'Now you can\ndefend against\nlasers!', 'and the laser blocker', 'shield-wielding kid', 'face shield for sale', 'fungus for face shield', 'shield boy defends again', 'the Mirror Shield'), 'Progressive Shield': (True, False, None, 0x5F, 50, 'have a better\nblocker in\nfront of you', 'and the new shield', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a shield'), 'Bug Catching Net': (True, False, None, 0x21, 50, 'Let\'s catch\nsome bees and\nfaeries!', 'and the bee catcher', 'the bug-catching kid', 'stick web for sale', 'fungus for butterflies', 'wrong boy catches bees again', 'the bug net'), - 'Cane of Byrna': (True, False, None, 0x18, 50, 'Use this to\nbecome\ninvincible!', 'and the bad cane', 'the spark-making kid', 'spark stick for sale', 'spark-stick for trade', 'cane boy encircles again', 'the blue cane'), + 'Cane of Byrna': (True, False, None, 0x18, 50, 'Use this to\nbecome\ninvincible!', 'and the bad cane', 'the spark-making kid', 'spark stick for sale', 'spark-stick for trade', 'cane boy encircles again', 'the blue Cane'), 'Boss Heart Container': (False, True, None, 0x3E, 40, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'), 'Sanctuary Heart Container': (False, True, None, 0x3F, 50, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'), 'Piece of Heart': (False, False, None, 0x17, 10, 'Just a little\npiece of love!', 'and the broken heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart piece'), @@ -114,8 +114,8 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche 'Green Clock': (False, True, None, 0x5D, 200, 'a lot of time', 'the emerald clock', 'the emerald-time kid', 'green time for sale', 'for emerald time', 'moment boy adjusts time again', 'a red clock'), 'Single RNG': (False, True, None, 0x62, 300, 'something you don\'t yet have', None, None, None, None, 'unknown boy somethings again', 'a new mystery'), 'Multi RNG': (False, True, None, 0x63, 100, 'something you may already have', None, None, None, None, 'unknown boy somethings again', 'a total mystery'), - 'Magic Upgrade (1/2)': (True, False, None, 0x4E, 50, 'Your magic\npower has been\ndoubled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'half magic'), # can be required to beat mothula in an open seed in very very rare circumstance - 'Magic Upgrade (1/4)': (True, False, None, 0x4F, 100, 'Your magic\npower has been\nquadrupled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'quarter magic'), # can be required to beat mothula in an open seed in very very rare circumstance + 'Magic Upgrade (1/2)': (True, False, None, 0x4E, 50, 'Your magic\npower has been\ndoubled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Half Magic'), # can be required to beat mothula in an open seed in very very rare circumstance + 'Magic Upgrade (1/4)': (True, False, None, 0x4F, 100, 'Your magic\npower has been\nquadrupled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Quarter Magic'), # can be required to beat mothula in an open seed in very very rare circumstance 'Small Key (Eastern Palace)': (False, False, 'SmallKey', 0xA2, 40, 'A small key to Armos Knights', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Eastern Palace'), 'Big Key (Eastern Palace)': (False, False, 'BigKey', 0x9D, 60, 'A big key to Armos Knights', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Eastern Palace'), 'Compass (Eastern Palace)': (False, True, 'Compass', 0x8D, 10, 'Now you can find the Armos Knights!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Eastern Palace'), diff --git a/PotShuffle.py b/PotShuffle.py index 90258478..a1c96783 100644 --- a/PotShuffle.py +++ b/PotShuffle.py @@ -1015,8 +1015,8 @@ key_drop_data = { 'Swamp Palace - Waterway Pot Key': ['Pot', 0x16, 'in a pot in Swamp Palace', 'Small Key (Swamp Palace)'], 'Skull Woods - West Lobby Pot Key': ['Pot', 0x56, 'in a pot in Skull Woods', 'Small Key (Skull Woods)'], 'Skull Woods - Spike Corner Key Drop': ['Drop', (0x09DD74, 0x39, 1), 'dropped near Mothula', 'Small Key (Skull Woods)'], - "Thieves' Town - Hallway Pot Key": ['Pot', 0xBC, "in a pot in Thieves' Town", 'Small Key (Thieves Town)'], - "Thieves' Town - Spike Switch Pot Key": ['Pot', 0xAB, "in a pot in Thieves' Town", 'Small Key (Thieves Town)'], + "Thieves' Town - Hallway Pot Key": ['Pot', 0xBC, "in a pot in Thieves Town", 'Small Key (Thieves Town)'], + "Thieves' Town - Spike Switch Pot Key": ['Pot', 0xAB, "in a pot in Thieves Town", 'Small Key (Thieves Town)'], 'Ice Palace - Jelly Key Drop': ['Drop', (0x09DA21, 0xE, 3), 'dropped in Ice Palace', 'Small Key (Ice Palace)'], 'Ice Palace - Conveyor Key Drop': ['Drop', (0x09DE08, 0x3E, 8), 'dropped in Ice Palace', 'Small Key (Ice Palace)'], 'Ice Palace - Hammer Block Key Drop': ['Pot', 0x3F, 'under a block in Ice Palace', 'Small Key (Ice Palace)'], diff --git a/Regions.py b/Regions.py index 5d4c6f43..29d61bf9 100644 --- a/Regions.py +++ b/Regions.py @@ -1251,7 +1251,7 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), 'Paradox Cave Lower - Middle': (0xeb36, 0x18630a, False, 'in a cave with seven chests'), 'Paradox Cave Upper - Left': (0xeb39, 0x18630d, False, 'in a cave with seven chests'), 'Paradox Cave Upper - Right': (0xeb3c, 0x186310, False, 'in a cave with seven chests'), - 'Spiral Cave': (0xe9bf, 0x186193, False, 'in spiral cave'), + 'Spiral Cave': (0xe9bf, 0x186193, False, 'in Spiral Cave'), 'Ether Tablet': (0x180016, 0x18633b, False, 'at a monolith'), 'Spectacle Rock': (0x180140, 0x18634f, False, 'atop a rock'), 'Tower of Hera - Basement Cage': (0x180162, 0x18633a, False, 'in Tower of Hera'), @@ -1260,7 +1260,7 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), 'Tower of Hera - Compass Chest': (0xe9fb, 0x1861cf, False, 'in Tower of Hera'), 'Tower of Hera - Big Chest': (0xe9f8, 0x1861cc, False, 'in Tower of Hera'), 'Tower of Hera - Boss': (0x180152, 0x186340, False, 'with Moldorm'), - 'Pyramid': (0x180147, 0x186356, False, 'on the pyramid'), + 'Pyramid': (0x180147, 0x186356, False, 'on the Pyramid'), 'Catfish': (0xee185, 0x186361, False, 'with a catfish'), 'Stumpy': (0x330c7, 0x18636a, False, 'with tree boy'), 'Digging Game': (0x180148, 0x186357, False, 'underground'), @@ -1298,13 +1298,13 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), 'Swamp Palace - Flooded Room - Right': (0xeaac, 0x186280, False, 'in Swamp Palace'), 'Swamp Palace - Waterfall Room': (0xeaaf, 0x186283, False, 'in Swamp Palace'), 'Swamp Palace - Boss': (0x180154, 0x186342, False, 'with Arrghus'), - "Thieves' Town - Big Key Chest": (0xea04, 0x1861d8, False, "in Thieves' Town"), - "Thieves' Town - Map Chest": (0xea01, 0x1861d5, False, "in Thieves' Town"), - "Thieves' Town - Compass Chest": (0xea07, 0x1861db, False, "in Thieves' Town"), - "Thieves' Town - Ambush Chest": (0xea0a, 0x1861de, False, "in Thieves' Town"), - "Thieves' Town - Attic": (0xea0d, 0x1861e1, False, "in Thieves' Town"), - "Thieves' Town - Big Chest": (0xea10, 0x1861e4, False, "in Thieves' Town"), - "Thieves' Town - Blind's Cell": (0xea13, 0x1861e7, False, "in Thieves' Town"), + "Thieves' Town - Big Key Chest": (0xea04, 0x1861d8, False, "in Thieves Town"), + "Thieves' Town - Map Chest": (0xea01, 0x1861d5, False, "in Thieves Town"), + "Thieves' Town - Compass Chest": (0xea07, 0x1861db, False, "in Thieves Town"), + "Thieves' Town - Ambush Chest": (0xea0a, 0x1861de, False, "in Thieves Town"), + "Thieves' Town - Attic": (0xea0d, 0x1861e1, False, "in Thieves Town"), + "Thieves' Town - Big Chest": (0xea10, 0x1861e4, False, "in Thieves Town"), + "Thieves' Town - Blind's Cell": (0xea13, 0x1861e7, False, "in Thieves Town"), "Thieves' Town - Boss": (0x180156, 0x186344, False, 'with Blind'), 'Skull Woods - Compass Chest': (0xe992, 0x186166, False, 'in Skull Woods'), 'Skull Woods - Map Chest': (0xe99b, 0x18616f, False, 'in Skull Woods'), @@ -1405,7 +1405,7 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), 'Tower of Hera - Prize': ([0x120A5, 0x53E78, 0x53E79, 0x18005A, 0x180071, 0xC706, 0x186FEA], None, True, 'Tower of Hera'), 'Palace of Darkness - Prize': ([0x120A1, 0x53E7C, 0x53E7D, 0x180056, 0x180073, 0xC702, 0x186FE6], None, True, 'Palace of Darkness'), 'Swamp Palace - Prize': ([0x120A0, 0x53E88, 0x53E89, 0x180055, 0x180079, 0xC701, 0x186FE5], None, True, 'Swamp Palace'), - 'Thieves\' Town - Prize': ([0x120A6, 0x53E82, 0x53E83, 0x18005B, 0x180076, 0xC707, 0x186FEB], None, True, 'Thieves\' Town'), + 'Thieves\' Town - Prize': ([0x120A6, 0x53E82, 0x53E83, 0x18005B, 0x180076, 0xC707, 0x186FEB], None, True, 'Thieves Town'), 'Skull Woods - Prize': ([0x120A3, 0x53E7E, 0x53E7F, 0x180058, 0x180074, 0xC704, 0x186FE8], None, True, 'Skull Woods'), 'Ice Palace - Prize': ([0x120A4, 0x53E86, 0x53E87, 0x180059, 0x180078, 0xC705, 0x186FE9], None, True, 'Ice Palace'), 'Misery Mire - Prize': ([0x120A2, 0x53E84, 0x53E85, 0x180057, 0x180077, 0xC703, 0x186FE7], None, True, 'Misery Mire'), diff --git a/Text.py b/Text.py index 071dc2a7..f420d6b1 100644 --- a/Text.py +++ b/Text.py @@ -45,7 +45,7 @@ Uncle_texts = [ "I am leaving\nforever.\nGoodbye.", "Don't worry.\nI got this\ncovered.", "Race you to\nthe castle!", - "\n hi", + "\n Hi", "I'M JUST GOING\nOUT FOR A\nPACK OF SMOKES", "It's dangerous\nto go alone.\nSee ya!", "ARE YOU A BAD\nENOUGH DUDE TO\nRESCUE ZELDA?", @@ -89,49 +89,49 @@ Triforce_texts = [ 'Product has Hole in center. Bad seller, 0 out of 5.', 'Who stole the fourth triangle?', 'Trifource?\nMore Like Tritrice, am I right?' - '\n Well Done!', + '\n Well Done!', 'You just wasted 2 hours of your life.', 'This was meant to be a trapezoid', # these ones are from web randomizer - "\n G G", - "All your base\nare belong\nto us.", - "You have ended\nthe domination\nof Dr. Wily", - " thanks for\n playing!!!", - "\n You Win!", - " Thank you!\n your quest\n is over.", - " A winner\n is\n you!", - "\n WINNER!!", - "\n I'm sorry\n\n but your\nprincess is in\nanother castle", - "\n success!", + "\n G G", + " All your base\n are belong\n to us.", + " You have ended\n the domination\n of Dr. Wily", + " Thanks for\n playing!!!", + "\n You Win!", + " Thank you!\n Your quest\n is over.", + " A winner\n is you!", + "\n WINNER!!", + "\n I'm sorry\n\nbut our princess is\n in another castle", + "\n Success!", " Whelp…\n that just\n happened", - " Oh hey…\n it's you", - "\n Wheeeeee!!", - " Time for\n another one?", - "and\n\n scene", - "\n GOT EM!!", - "\nTHE VALUUUE!!!", - "Cool seed,\n\nright?", - "\n We did it!", - " Spam those\n emotes in\n wilds chat", - "\n O M G", - " Hello. Will\n you be my\n friend?", - " Beetorp\n was\n here!", - "The Wind Fish\nwill wake\nsoon. Hoot!", - "meow meow meow\nmeow meow meow\n oh my god!", - "Ahhhhhhhhh\nYa ya yaaaah\nYa ya yaaah", - ".done\n\n.comment lol", - "You get to\ndrink from\nthe firehose", - "Do you prefer\n bacon, pork,\n or ham?", - "You get one\nwish. Choose\nwisely, hero!", - "Can you please\nbreak us three\nup? Thanks.", - " Pick us up\n before we\n get dizzy!", - "Thank you,\nMikey. You’re\n2 minutes late", - "This was a\n7000 series\ntrain.", - " I'd buy\n that for\n a rupee!", - " Did you like\n that bow\n placement?", - "I promise the\nnext seed will\nbe better.", - "\n Honk.", - "Breakfast\nis served!", + " Oh hey…\n it's you", + "\n Wheeeeee!!", + " Time for\n another one?", + " And\n\n scene", + "\n GOT EM!!", + "\n THE VALUUUE!!!", + " Cool seed,\n\n right?", + "\n We did it!", + " Spam those\n emotes in\n wilds chat", + "\n O M G", + " Hello. Will you\n you be my friend?", + " Beetorp\n was\n here!", + " The Wind Fish\n will wake soon.\n Hoot!", + " Meow Meow Meow\n Meow Meow Meow\n Oh my god!", + " Ahhhhhhhhh\n Ya ya yaaaah\n Ya ya yaaah", + " .done\n\n .comment lol", + " You get to\n drink from\n the firehose", + " Do you prefer\n bacon, pork,\n or ham?", + " You get one\n wish. Choose\n wisely, hero!", + " Can you please\n break us three\n up? Thanks.", + " Pick us up\n before we\n get dizzy!", + " Thank you,\n Mikey. You’re\n 2 minutes late", + " This was a\n 7000 series\n train.", + " I'd buy\n that for\n a rupee!", + " Did you like\n that bow\n placement?", + " I promise the\n next seed will\n be better.", + "\n Honk.", + " Breakfast\n is served!", ] BombShop2_texts = ['Bombs!\nBombs!\nBiggest!\nBestest!\nGreatest!\nBoomest!'] Sahasrahla2_texts = ['You already got my item, idiot.', 'Why are you still talking to me?', 'This text won\'t change.', 'Have you met my brother, Hasarahshla?'] @@ -217,7 +217,7 @@ Ganon1_texts = [ "The Hemiptera\nor true bugs\nare an order\nof insects\ncovering 50k\nto 80k species\nlike aphids,\ncicadas, and\nshield bugs.", "Thanks for\ndropping in.\nThe first\npassengers\nin a hot\nair balloon\nwere a duck,\na sheep,\nand a rooster.", "You think you\nare so smart?\n\nI bet you\ndidn't know\nyou can't hum\nwhile holding\nyour nose\nclosed.", - "grumble,\n\ngrumble…\ngrumble,\n\ngrumble…\nSeriously, you\nwere supposed\nto bring food.", + "Grumble,\n\ngrumble…\nGrumble,\n\ngrumble…\nSeriously, you\nwere supposed\nto bring food.", "Join me hero,\nand I shall\nmake your face\nthe greatest\nin the Dark\nWorld!\n\nOr else you\nwill die!", "Why rule over\na desert full\nof stereotypes\nwhen I can\ncorrupt a\nworld into\npure evil and\nrule over\nthat instead?", "When I conquer\nthe Light\nWorld, I'll\nhold a parade\nof all my\nmonsters to\ndemonstrate my\nmight to the\npeople!", @@ -628,7 +628,6 @@ class MultiByteCoreTextMapper(object): @classmethod def convert(cls, text, pause=True, wrap=19): - # text = text.upper() lines = text.split('\n') outbuf = bytearray() lineindex = 0 @@ -1559,7 +1558,7 @@ class TextTable(object): text['tutorial_guard_7'] = CompressedTextMapper.convert("Jeeze! There really are a lot of things.") text['priest_sanctuary_before_leave'] = CompressedTextMapper.convert("Go be a hero!") text['sanctuary_enter'] = CompressedTextMapper.convert("YAY!\nYou saved Zelda!") - text['zelda_sanctuary_story'] = CompressedTextMapper.convert("Do you want to hear me say this again?\n{HARP}\n ≥ no\n yes\n{CHOICE}") + text['zelda_sanctuary_story'] = CompressedTextMapper.convert("Do you want to hear me say this again?\n{HARP}\n ≥ No\n Yes\n{CHOICE}") text['priest_sanctuary_before_pendants'] = CompressedTextMapper.convert("Go'on and get them pendants so you can beat up Agahnim.") text['priest_sanctuary_after_pendants_before_master_sword'] = CompressedTextMapper.convert("Kudos! But seriously, you should be getting the master sword, not having a kegger in here.") text['priest_sanctuary_dying'] = CompressedTextMapper.convert("They took her to the castle! Take your sword and save her!") @@ -1573,14 +1572,14 @@ class TextTable(object): text['zelda_push_throne'] = CompressedTextMapper.convert("Let's push it from the left!") text['zelda_switch_room_pull'] = CompressedTextMapper.convert("Pull this lever using A.") text['zelda_save_lets_go'] = CompressedTextMapper.convert("Let's get out of here!") - text['zelda_save_repeat'] = CompressedTextMapper.convert("I like talking, do you?\n ≥ no\n yes\n{CHOICE}") + text['zelda_save_repeat'] = CompressedTextMapper.convert("I like talking, do you?\n ≥ No\n Yes\n{CHOICE}") text['zelda_before_pendants'] = CompressedTextMapper.convert("You need to find all the pendants…\n\n\nNumpty.") text['zelda_after_pendants_before_master_sword'] = CompressedTextMapper.convert("Very pretty pendants, but really you should be getting that sword in the forest!") text['telepathic_zelda_right_after_master_sword'] = CompressedTextMapper.convert("{NOBORDER}\n{SPEED6}\nHi @,\nHave you been thinking about me?\narrrrrgghh…\n… … …") text['zelda_sewers'] = CompressedTextMapper.convert("Just a little further to the Sanctuary.") text['zelda_switch_room'] = CompressedTextMapper.convert("The Sanctuary!\n\nPull my finger") text['kakariko_saharalasa_wife'] = CompressedTextMapper.convert("Heya, @!\nLong time no see.\nYou want a master sword?\n\nWell good luck with that.") - text['kakariko_saharalasa_wife_sword_story'] = CompressedTextMapper.convert("It occurs to me that I like toast and jam, but cheese and crackers is better.\nYou like?\n ≥ cheese\n jam\n{CHOICE}") + text['kakariko_saharalasa_wife_sword_story'] = CompressedTextMapper.convert("It occurs to me that I like toast and jam, but cheese and crackers is better.\nYou like?\n ≥ Cheese\n Jam\n{CHOICE}") text['kakariko_saharalasa_wife_closing'] = CompressedTextMapper.convert("Anywho, I have things to do. You see those 2 ovens?\n\nYeah 2!\nWho has 2 ovens nowadays?") text['kakariko_saharalasa_after_master_sword'] = CompressedTextMapper.convert("Cool sword!\n\n\n…\n\n\n…\n\n\nPlease save us") text['kakariko_alert_guards'] = CompressedTextMapper.convert("GUARDS! HELP!\nThe creeper\n@ is here!") @@ -1590,7 +1589,7 @@ class TextTable(object): text['sahasrahla_quest_information'] = CompressedTextMapper.convert( "{BOTTOM}\n" + "Sahasrahla, I am. You would do well to find the 3 pendants from the 3 dungeons in the Light World.\n" - + "Understand?\n ≥ yes\n no\n{CHOICE}") + + "Understand?\n ≥ Yes\n No\n{CHOICE}") text['sahasrahla_bring_courage'] = CompressedTextMapper.convert( "{BOTTOM}\n" + "While you're here, could you do me a solid and get the green pendant from that dungeon?\n" @@ -1681,15 +1680,15 @@ class TextTable(object): text['talking_tree_other'] = CompressedTextMapper.convert("I can breathe!") text['item_get_pendant_power_alt'] = CompressedTextMapper.convert("We have the Pendant of Power! How robust!") text['item_get_pendant_wisdom_alt'] = CompressedTextMapper.convert("We have the Pendant of Wisdom! How astute!") - text['game_shooting_choice'] = CompressedTextMapper.convert("20 rupees.\n5 arrows.\nWin rupees!\nWant to play?\n ≥ yes\n no\n{CHOICE}") + text['game_shooting_choice'] = CompressedTextMapper.convert("20 rupees.\n5 arrows.\nWin rupees!\nWant to play?\n ≥ Yes\n No\n{CHOICE}") text['game_shooting_yes'] = CompressedTextMapper.convert("Let's do this!") text['game_shooting_no'] = CompressedTextMapper.convert("Where are you going? Straight up!") text['game_shooting_continue'] = CompressedTextMapper.convert("Keep playing?\n ≥ yes\n no\n{CHOICE}") text['pond_of_wishing'] = CompressedTextMapper.convert("-Wishing Pond-\n\n On Vacation") text['pond_item_select'] = CompressedTextMapper.convert("Pick something\nto throw in.\n{ITEMSELECT}") - text['pond_item_test'] = CompressedTextMapper.convert("You toss this?\n ≥ yup\n wrong\n{CHOICE}") + text['pond_item_test'] = CompressedTextMapper.convert("You toss this?\n ≥ Yup\n Wrong\n{CHOICE}") text['pond_will_upgrade'] = CompressedTextMapper.convert("You're honest, so I'll give you a present.") - text['pond_item_test_no'] = CompressedTextMapper.convert("You sure?\n ≥ oh yeah\n um\n{CHOICE}") + text['pond_item_test_no'] = CompressedTextMapper.convert("You sure?\n ≥ Oh yeah\n Um\n{CHOICE}") text['pond_item_test_no_no'] = CompressedTextMapper.convert("Well, I don't want it, so take it back.") text['pond_item_boomerang'] = CompressedTextMapper.convert("I don't much like you, so have this worse Boomerang.") # 90 @@ -1698,7 +1697,7 @@ class TextTable(object): text['pond_item_bottle_filled'] = CompressedTextMapper.convert("Bottle Filled!\nMoney Saved!") text['pond_item_sword'] = CompressedTextMapper.convert("Thank you for the sword, here is a stick of butter.") text['pond_of_wishing_happiness'] = CompressedTextMapper.convert("Happiness up!\nYou are now\nᚌᚋ happy!") - text['pond_of_wishing_choice'] = CompressedTextMapper.convert("Your wish?\n ≥more bombs\n more arrows\n{CHOICE}") + text['pond_of_wishing_choice'] = CompressedTextMapper.convert("Your wish?\n ≥More bombs\n More arrows\n{CHOICE}") text['pond_of_wishing_bombs'] = CompressedTextMapper.convert("Woo-hoo!\nYou can now\ncarry ᚌᚋ bombs") text['pond_of_wishing_arrows'] = CompressedTextMapper.convert("Woo-hoo!\nYou can now\nhold ᚌᚋ arrows") text['pond_of_wishing_full_upgrades'] = CompressedTextMapper.convert("Youhave all I can give you, here are your rupees back.") @@ -1719,7 +1718,7 @@ class TextTable(object): text['running_man'] = CompressedTextMapper.convert("Hi, Do you\nknow Veetorp?\n\nYou really\nshould. And\nall the other great guys who made this possible.\nGo thank them.\n\n\nIf you can catch them…") text['game_race_sign'] = CompressedTextMapper.convert("Why are you reading this sign? Run!!!") text['sign_bumper_cave'] = CompressedTextMapper.convert("You need Cape, but not Hookshot") - text['sign_catfish'] = CompressedTextMapper.convert("toss rocks\ntoss items\ntoss cookies") + text['sign_catfish'] = CompressedTextMapper.convert("Toss rocks\nToss items\nToss cookies") text['sign_north_village_of_outcasts'] = CompressedTextMapper.convert("↑ Skull Woods\n\n↓ Steve's Town") text['sign_south_of_bumper_cave'] = CompressedTextMapper.convert("\n→ Karkats cave") text['sign_east_of_pyramid'] = CompressedTextMapper.convert("\n→ Dark Palace") @@ -1727,7 +1726,7 @@ class TextTable(object): text['sign_east_of_mire'] = CompressedTextMapper.convert("\n← Misery Mire\n no way in.\n no way out.") text['sign_village_of_outcasts'] = CompressedTextMapper.convert("Have a Trulie Awesome Day!") # B0 - text['sign_before_wishing_pond'] = CompressedTextMapper.convert("waterfall\nup ahead\nmake wishes") + text['sign_before_wishing_pond'] = CompressedTextMapper.convert("Waterfall\nup ahead\nMake wishes") text['sign_before_catfish_area'] = CompressedTextMapper.convert("→↑ Have you met Woeful Ike?") text['castle_wall_guard'] = CompressedTextMapper.convert("Looking for a Princess? Look downstairs.") text['gate_guard'] = CompressedTextMapper.convert("No Lonks Allowed!") @@ -1752,8 +1751,8 @@ class TextTable(object): text['telepathic_tile_ice_stalfos_knights_room'] = CompressedTextMapper.convert("{NOBORDER}\nKnock 'em down and then bomb them dead.") text['telepathic_tile_tower_of_hera_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nThis is a bad place, with a guy who will make you fall…\n\n\na lot.") text['houlihan_room'] = CompressedTextMapper.convert("Randomizer tournament winners\n{HARP}\n ~~~2018~~~\nS: Andy\n\n ~~~2017~~~\nA: ajneb174\nS: ajneb174") - text['caught_a_bee'] = CompressedTextMapper.convert("Caught a Bee\n ≥ keep\n release\n{CHOICE}") - text['caught_a_fairy'] = CompressedTextMapper.convert("Caught Fairy!\n ≥ keep\n release\n{CHOICE}") + text['caught_a_bee'] = CompressedTextMapper.convert("Caught a Bee\n ≥ Keep\n Release\n{CHOICE}") + text['caught_a_fairy'] = CompressedTextMapper.convert("Caught Fairy!\n ≥ Keep\n Release\n{CHOICE}") text['no_empty_bottles'] = CompressedTextMapper.convert("Whoa, bucko!\nNo empty bottles.") text['game_race_boy_time'] = CompressedTextMapper.convert("Your time was\nᚎᚍ min ᚌᚋ sec.") text['game_race_girl'] = CompressedTextMapper.convert("You have 15 seconds,\nGo… Go… Go…") @@ -1783,7 +1782,7 @@ class TextTable(object): text['blacksmiths_still_working'] = CompressedTextMapper.convert("Something this precious takes time… Come back later.") text['blacksmiths_saving_bows'] = CompressedTextMapper.convert("Thanks!\n\nThanks!") text['blacksmiths_hammer_anvil'] = CompressedTextMapper.convert("Dernt Take Er Jerbs!") - text['dark_flute_boy_storytime'] = CompressedTextMapper.convert("Hi!\nI'm Stumpy\nI've been chillin' in this world for a while now, but I miss my flute. If I gave you a shovel, would you go digging for it?\n ≥ sure\n nahh\n{CHOICE}") + text['dark_flute_boy_storytime'] = CompressedTextMapper.convert("Hi!\nI'm Stumpy\nI've been chillin' in this world for a while now, but I miss my flute. If I gave you a shovel, would you go digging for it?\n ≥ Sure\n Nahh\n{CHOICE}") text['dark_flute_boy_get_shovel'] = CompressedTextMapper.convert("Schaweet! Here you go. Happy digging!") text['dark_flute_boy_no_get_shovel'] = CompressedTextMapper.convert("Oh I see, not good enough for you… FINE!") text['dark_flute_boy_flute_not_found'] = CompressedTextMapper.convert("Still haven't found the item? Dig in the Light World around here, dingus!") @@ -1797,7 +1796,7 @@ class TextTable(object): text['shop_fortune_teller_lw_hint_6'] = CompressedTextMapper.convert("{BOTTOM}\nBy the black cats, Spin, Hammer, or Net to hurt Agahnim") text['shop_fortune_teller_lw_hint_7'] = CompressedTextMapper.convert("{BOTTOM}\nBy the black cats, You can jump in the well by the blacksmiths") text['shop_fortune_teller_lw_no_rupees'] = CompressedTextMapper.convert("{BOTTOM}\nThe black cats are hungry, come back with rupees") - text['shop_fortune_teller_lw'] = CompressedTextMapper.convert("{BOTTOM}\nWelcome to the Fortune Shoppe!\nFancy a read?\n ≥I must know\n negative\n{CHOICE}") + text['shop_fortune_teller_lw'] = CompressedTextMapper.convert("{BOTTOM}\nWelcome to the Fortune Shoppe!\nFancy a read?\n ≥I must know\n Negative\n{CHOICE}") text['shop_fortune_teller_lw_post_hint'] = CompressedTextMapper.convert("{BOTTOM}\nFor ᚋᚌ rupees\nIt is done.\nBe gone!") text['shop_fortune_teller_lw_no'] = CompressedTextMapper.convert("{BOTTOM}\nWell then, why did you even come in here?") text['shop_fortune_teller_lw_hint_8'] = CompressedTextMapper.convert("{BOTTOM}\nBy the black cats, why you do?") @@ -1808,7 +1807,7 @@ class TextTable(object): text['shop_fortune_teller_lw_hint_13'] = CompressedTextMapper.convert("{BOTTOM}\nBy the black cats, big bombs blow up cracked walls in pyramids") text['shop_fortune_teller_lw_hint_14'] = CompressedTextMapper.convert("{BOTTOM}\nBy the black cats, you need all the crystals to open Ganon's Tower") text['shop_fortune_teller_lw_hint_15'] = CompressedTextMapper.convert("{BOTTOM}\nBy the black cats, Silver Arrows will defeat Ganon in his final phase") - text['dark_sanctuary'] = CompressedTextMapper.convert("For 20 rupees I'll tell you something?\nHow about it?\n ≥ yes\n no\n{CHOICE}") + text['dark_sanctuary'] = CompressedTextMapper.convert("For 20 rupees I'll tell you something?\nHow about it?\n ≥ Yes\n No\n{CHOICE}") text['dark_sanctuary_hint_0'] = CompressedTextMapper.convert("I once was a tea kettle, but then I moved up in the world, and now you can see me as this. Makes you wonder. What I could be next time.") # 100 text['dark_sanctuary_no'] = CompressedTextMapper.convert("Then go away!") @@ -1824,8 +1823,8 @@ class TextTable(object): text['sick_kid_trade'] = CompressedTextMapper.convert("{BOTTOM}\nCool Bottle! Here's something for you.") text['sick_kid_post_trade'] = CompressedTextMapper.convert("{BOTTOM}\nLeave me alone\nI'm sick. You have my item.") text['desert_thief_sitting'] = CompressedTextMapper.convert("………………………") - text['desert_thief_following'] = CompressedTextMapper.convert("why……………") - text['desert_thief_question'] = CompressedTextMapper.convert("I was a thief, I open purple chests!\nKeep secret?\n ≥ sure thing\n never!\n{CHOICE}") + text['desert_thief_following'] = CompressedTextMapper.convert("Why……………") + text['desert_thief_question'] = CompressedTextMapper.convert("I was a thief, I open purple chests!\nKeep secret?\n ≥ Sure thing\n Never!\n{CHOICE}") text['desert_thief_question_yes'] = CompressedTextMapper.convert("Cool, bring me any purple chests you find.") text['desert_thief_after_item_get'] = CompressedTextMapper.convert("You tell anyone and I will give you such a pinch!") text['desert_thief_reassure'] = CompressedTextMapper.convert("Bring chests. It's a secret to everyone.") @@ -1851,10 +1850,10 @@ class TextTable(object): text['bomb_shop_big_bomb'] = CompressedTextMapper.convert("30 bombs for 100 rupees, 100 rupees 1 BIG bomb. Good deals all day!") text['bomb_shop_big_bomb_buy'] = CompressedTextMapper.convert("Thanks!\nBoom goes the dynamite!") text['item_get_big_bomb'] = CompressedTextMapper.convert("YAY! press A to splode it!") - text['kiki_second_extortion'] = CompressedTextMapper.convert("For 100 more, I'll open this place.\nHow about it?\n ≥ open\n nah\n{CHOICE}") + text['kiki_second_extortion'] = CompressedTextMapper.convert("For 100 more, I'll open this place.\nHow about it?\n ≥ Open\n Nah\n{CHOICE}") text['kiki_second_extortion_no'] = CompressedTextMapper.convert("Heh, good luck getting in.") text['kiki_second_extortion_yes'] = CompressedTextMapper.convert("Yay! Rupees!\nOkay, let's do this!") - text['kiki_first_extortion'] = CompressedTextMapper.convert("I'm Kiki, I like rupees, may I have 10?\nHow about it?\n ≥ yes\n no\n{CHOICE}") + text['kiki_first_extortion'] = CompressedTextMapper.convert("I'm Kiki, I like rupees, may I have 10?\nHow about it?\n ≥ Yes\n No\n{CHOICE}") text['kiki_first_extortion_yes'] = CompressedTextMapper.convert("Nice. I'll tag along with you for a bit.") # 120 text['kiki_first_extortion_no'] = CompressedTextMapper.convert("Pfft. I have no reason to hang. See ya!") @@ -1913,7 +1912,7 @@ class TextTable(object): text['pond_of_wishing_good_luck'] = CompressedTextMapper.convert("\n is good luck") text['pond_of_wishing_meh_luck'] = CompressedTextMapper.convert("\n is meh luck") # Repurposed to no items in Randomizer - text['pond_of_wishing_bad_luck'] = CompressedTextMapper.convert("Why you come in here and pretend like you have something this fountain wants? Come back with bottles!") + text['pond_of_wishing_bad_luck'] = CompressedTextMapper.convert("Why come in here and pretend like you have something this fountain wants? Come back with bottles!") text['pond_of_wishing_fortune'] = CompressedTextMapper.convert("by the way, your fortune,") text['item_get_14_heart'] = CompressedTextMapper.convert("3 more to go\n ¼\nYay!") text['item_get_24_heart'] = CompressedTextMapper.convert("2 more to go\n ½\nWhee!") @@ -1927,7 +1926,7 @@ class TextTable(object): text['death_mountain_bully_with_pearl'] = CompressedTextMapper.convert("I think I forgot how to smile…") text['shop_darkworld_enter'] = CompressedTextMapper.convert("It's dangerous outside, buy my crap for safety.") # 160 - text['game_chest_village_of_outcasts'] = CompressedTextMapper.convert("Pay 30 rupees, open 2 chests. Are you lucky?\nSo, Play game?\n ≥ play\n never!\n{CHOICE}") + text['game_chest_village_of_outcasts'] = CompressedTextMapper.convert("Pay 30 rupees, open 2 chests. Are you lucky?\nSo, Play game?\n ≥ Play\n Never!\n{CHOICE}") text['game_chest_no_cash'] = CompressedTextMapper.convert("So, like, you need 30 rupees.\nSilly!") text['game_chest_not_played'] = CompressedTextMapper.convert("You want to play a game?\nTalk to me.") text['game_chest_played'] = CompressedTextMapper.convert("You've opened the chests!\nTime to go.") @@ -1958,17 +1957,17 @@ class TextTable(object): text['cukeman_2'] = CompressedTextMapper.convert("You found Shabadoo, huh?\nNiiiiice.") text['potion_shop_no_cash'] = CompressedTextMapper.convert("Yo! I'm not running a charity here.") text['kakariko_powdered_chicken'] = CompressedTextMapper.convert("Smallhacker…\n\n\nWas hiding, you found me!\n\n\nOkay, you can leave now.") - text['game_chest_south_of_kakariko'] = CompressedTextMapper.convert("Pay 20 rupees, open 1 chest. Are you lucky?\nSo, Play game?\n ≥ play\n never!\n{CHOICE}") + text['game_chest_south_of_kakariko'] = CompressedTextMapper.convert("Pay 20 rupees, open 1 chest. Are you lucky?\nSo, Play game?\n ≥ Play\n Never!\n{CHOICE}") text['game_chest_play_yes'] = CompressedTextMapper.convert("Good luck then") # 180 text['game_chest_play_no'] = CompressedTextMapper.convert("Well fine, I didn't want your rupees.") - text['game_chest_lost_woods'] = CompressedTextMapper.convert("Pay 100 rupees open 1 chest. Are you lucky?\nSo, Play game?\n ≥ play\n never!\n{CHOICE}") + text['game_chest_lost_woods'] = CompressedTextMapper.convert("Pay 100 rupees open 1 chest. Are you lucky?\nSo, Play game?\n ≥ Play\n Never!\n{CHOICE}") text['kakariko_flophouse_man_no_flippers'] = CompressedTextMapper.convert("I really hate mowing my yard.\nI moved my house and everyone else's to avoid it.\n{PAGEBREAK}\nI hope you don't mind.") text['kakariko_flophouse_man'] = CompressedTextMapper.convert("I really hate mowing my yard.\nI moved my house and everyone else's to avoid it.\n{PAGEBREAK}\nI hope you don't mind.") text['menu_start_2'] = CompressedTextMapper.convert("{MENU}\n{SPEED0}\n≥@'s House\n Sanctuary\n{CHOICE3}", False) text['menu_start_3'] = CompressedTextMapper.convert("{MENU}\n{SPEED0}\n≥@'s House\n Sanctuary\n Mountain Cave\n{CHOICE2}", False) text['menu_pause'] = CompressedTextMapper.convert("{SPEED0}\n≥Continue\n Save and Quit\n{CHOICE3}", False) - text['game_digging_choice'] = CompressedTextMapper.convert("Have 80 Rupees? Want to play digging game?\n ≥yes\n no\n{CHOICE}") + text['game_digging_choice'] = CompressedTextMapper.convert("Have 80 Rupees? Want to play digging game?\n ≥Yes\n No\n{CHOICE}") text['game_digging_start'] = CompressedTextMapper.convert("Okay, use the shovel with Y!") text['game_digging_no_cash'] = CompressedTextMapper.convert("Shovel rental is 80 rupees.\nI have all day") text['game_digging_end_time'] = CompressedTextMapper.convert("Time's up!\nTime for you to go.") @@ -1976,8 +1975,8 @@ class TextTable(object): text['game_digging_no_follower'] = CompressedTextMapper.convert("Something is following you. I don't like.") text['menu_start_4'] = CompressedTextMapper.convert("{MENU}\n{SPEED0}\n≥@'s House\n Mountain Cave\n{CHOICE3}", False) # Start of new text data - text['ganon_fall_in_alt'] = CompressedTextMapper.convert("You think you\nare ready to\nface me?\n\nI will not die\n\nunless you\ncomplete your\ngoals. Dingus!") - text['ganon_phase_3_alt'] = CompressedTextMapper.convert("Got wax in\nyour ears?\nI cannot die!") + text['ganon_fall_in_alt'] = CompressedTextMapper.convert("You think you are ready to face me?\n\nI will not die unless you complete your goals. Dingus!") + text['ganon_phase_3_alt'] = CompressedTextMapper.convert("Got wax in your ears? I cannot die!") # 190 text['sign_east_death_mountain_bridge'] = CompressedTextMapper.convert("How did you get up here?") text['fish_money'] = CompressedTextMapper.convert("It's a secret to everyone.") @@ -1989,4 +1988,4 @@ class TextTable(object): text['ganon_phase_3_silvers'] = CompressedTextMapper.convert("Oh no! Silver! My one true weakness!") text['murahdahla'] = CompressedTextMapper.convert("Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n{PAUSE3}\n… … …\nWait! you can see me? I knew I should have\nhidden in a hollow tree.") text['end_pad_data'] = bytearray([0xfb]) - text['terminator'] = bytearray([0xFF, 0xFF]) + text['terminator'] = bytearray([0xFF, 0xFF]) From e1bf283e1ce5cd274c8b55bbce58703eb3b23b3f Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 13 May 2022 16:37:27 -0600 Subject: [PATCH 21/25] Fix help --- resources/app/cli/lang/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index ffdf63be..59aecc23 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -261,8 +261,8 @@ "Keys: Key pots are included in the location pool and other items can take their place", "Cave: Only pots in houses and caves are included in the location pool", "CaveKeys: Both pots in houses and caves and keys pots are included in the location pool", - "Reduced: Same as KeyCaves + 25% of Pots in dungeons (dynamic mode)", - "Clustered: Same as KeyCaves + 50% of Pots in dungeons, chosen by logical group (dynamic mode)", + "Reduced: Same as KeyCaves + 25%% of Pots in dungeons (dynamic mode)", + "Clustered: Same as KeyCaves + 50%% of Pots in dungeons, chosen by logical group (dynamic mode)", "NonEmpty: All pots that are not originally empty are included in the location pool", "Dungeon: Only pots in dungeons are included in the location pool", "Lottery: All pots are part of the location pool" From bcc77759b742fb01d9bc8daff9c74388dddde1da Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 18 May 2022 15:01:24 -0600 Subject: [PATCH 22/25] Update tourney winners --- Text.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Text.py b/Text.py index f420d6b1..07b076f9 100644 --- a/Text.py +++ b/Text.py @@ -1740,7 +1740,7 @@ class TextTable(object): text['telepathic_tile_misery_mire'] = CompressedTextMapper.convert("{NOBORDER}\nLighting 4 torches will open your way forward!") text['hylian_text_2'] = CompressedTextMapper.convert("%%^= %==%\n ^ =%^=\n==%= ^^%^") text['desert_entry_translated'] = CompressedTextMapper.convert("Kneel before this stone, and magic will move around you.") - text['telepathic_tile_under_ganon'] = CompressedTextMapper.convert("Secondary tournament winners\n{HARP}\n ~~~2017~~~\nA: Zaen") + text['telepathic_tile_under_ganon'] = CompressedTextMapper.convert("Doors Async League winners\n{HARP}\n ~~~2022~~~\nAndy\n\n ~~~2021~~~\nprdwong") text['telepathic_tile_palace_of_darkness'] = CompressedTextMapper.convert("{NOBORDER}\nThis is a funny looking Enemizer") # C0 text['telepathic_tile_desert_bonk_torch_room'] = CompressedTextMapper.convert("{NOBORDER}\nThings can be knocked down, if you fancy yourself a dashing dude.") @@ -1750,7 +1750,7 @@ class TextTable(object): text['telepathic_tile_ice_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nYou can use Fire Rod or Bombos to pass.") text['telepathic_tile_ice_stalfos_knights_room'] = CompressedTextMapper.convert("{NOBORDER}\nKnock 'em down and then bomb them dead.") text['telepathic_tile_tower_of_hera_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nThis is a bad place, with a guy who will make you fall…\n\n\na lot.") - text['houlihan_room'] = CompressedTextMapper.convert("Randomizer tournament winners\n{HARP}\n ~~~2018~~~\nS: Andy\n\n ~~~2017~~~\nA: ajneb174\nS: ajneb174") + text['houlihan_room'] = CompressedTextMapper.convert("Randomizer tournament winners\n{HARP}\n ~~~2021~~~\nDaaanty\n\n ~~~2019~~~\nJet082\n\n ~~~2018~~~\nAndy\n\n ~~~2017~~~\nA: ajneb174\nS: ajneb174") text['caught_a_bee'] = CompressedTextMapper.convert("Caught a Bee\n ≥ Keep\n Release\n{CHOICE}") text['caught_a_fairy'] = CompressedTextMapper.convert("Caught Fairy!\n ≥ Keep\n Release\n{CHOICE}") text['no_empty_bottles'] = CompressedTextMapper.convert("Whoa, bucko!\nNo empty bottles.") @@ -1978,7 +1978,7 @@ class TextTable(object): text['ganon_fall_in_alt'] = CompressedTextMapper.convert("You think you are ready to face me?\n\nI will not die unless you complete your goals. Dingus!") text['ganon_phase_3_alt'] = CompressedTextMapper.convert("Got wax in your ears? I cannot die!") # 190 - text['sign_east_death_mountain_bridge'] = CompressedTextMapper.convert("How did you get up here?") + text['sign_east_death_mountain_bridge'] = CompressedTextMapper.convert("Glitched\ntournament\nwinners\n{HARP}\n~~~HMG 2021~~~\nKrithel\n\n~~~OWG 2019~~~\nGlan\n\n~~~OWG 2018~~~\nChristosOwen\nthe numpty") text['fish_money'] = CompressedTextMapper.convert("It's a secret to everyone.") text['sign_ganons_tower'] = CompressedTextMapper.convert("You need all 7 crystals to enter.") text['sign_ganon'] = CompressedTextMapper.convert("You need all 7 crystals to beat Ganon.") From afdb8ebac8e3e41fe60f8f32417eefd311bc96a6 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 18 May 2022 15:04:20 -0600 Subject: [PATCH 23/25] DungeonCompletion fixed Minor issue with dungeon counters fixed --- Main.py | 2 +- RELEASENOTES.md | 3 +++ Rom.py | 2 +- data/base2current.bps | Bin 93043 -> 93017 bytes 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Main.py b/Main.py index 2c43b714..f3dcb0ee 100644 --- a/Main.py +++ b/Main.py @@ -31,7 +31,7 @@ from Utils import output_path, parse_player_names from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config from source.tools.BPS import create_bps_from_data -__version__ = '1.0.2.3-v' +__version__ = '1.0.2.4-v' from source.classes.BabelFish import BabelFish diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1ea8bfb4..e7a722f4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -157,6 +157,9 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o #### Volatile +* 1.0.2.4 + * Updated tourney winners (included Doors Async League winners) + * Fixed a couple issues with dungeon counters and the DungeonCompletion field for autotracking * 1.0.2.3 * Fix MultiClient for new shop data location in SRAM * Some minor text updates diff --git a/Rom.py b/Rom.py index 25ee90e3..62a5edde 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '94fd47b16641a1aa44f22e21c8a7a024' +RANDOMIZERBASEHASH = '636b8484ebe22bff0b74aa7268fc2766' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 9643a3cd34345ca166283b87a106c8f27708a869..5d318246653c122cf68631a4ce0b229a18bc5759 100644 GIT binary patch delta 9523 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 AcK`qY From b0ea301c201e9002e1e724976bc38e855a4e5ef6 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 18 May 2022 16:08:41 -0600 Subject: [PATCH 24/25] Typo --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e7a722f4..31d1e10e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -165,7 +165,7 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o * Some minor text updates * 1.0.2.2 * Change to all key pots and enemy key drops: always use the same address - * Don't colorize key pots in mystery is the item is "forced" + * Don't colorize key pots in mystery if the item is "forced" * 1.0.2.1 * Fix for paired doors * Fix for forbidding certain dashable doors (it actually does something this time) From 62ec084a98cbae1b10e7cdf0e452ee6c1bc77b46 Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 19 May 2022 10:36:51 -0600 Subject: [PATCH 25/25] DungeonCompletion bitfield --- Rom.py | 2 +- data/base2current.bps | Bin 93017 -> 93021 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 62a5edde..836a164e 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '636b8484ebe22bff0b74aa7268fc2766' +RANDOMIZERBASEHASH = '01166fb16b38b49ef79acc9993dc4f02' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 5d318246653c122cf68631a4ce0b229a18bc5759..bd6417a47ef665eabc70d7f6055e50cdcb4562a4 100644 GIT binary patch delta 2476 zcmW+%4OCM{7S80Ce^U7g|E5n5zfxmCRODB&QlNlnE!xn+7Hafqi-3TD$viO9Kprt% z(`Ze3fcWVJ-?(yiO-KKINycV_N6GvA$WzI*S@ zNzv^|(ePFzeE5e2J@5{y=L@D`3KgJIh~_6PUo^ow`)Fdr1p6gTwCJN2w+#_B6D+ak zmbda?OJ7DSO=voz4wwI*UI{7n=jSux2v$8`pHDC&%8xy3%v{q-IjM4ide zUePi4*o;;a(b2~`VgqT96AHHCF&H@MSg3c1+cfY&@0x!s;)mry2R5$yJe_u)_p@&S9WOYw*${tKr)A`ynKJyv`E z_5;V}X|sVQ)z6jQ1y3d)#vBYf)F*m`c zfMOH@Ljj`^1NT{>MMuocFd<E;})f2(d4Y);*t-@-}33+q0gVuy8oQ*31$O_=)FZ=fpdaZ|I2IP^j(m0Wn$%u1>f zcYYA0D?XyT;$Z8sq2AzjM8`3bF`)a@!SeLn7lL=18f^l7+Aj14JWW%e7>G+xM|L37 z$B_b3GIG%S_SOvkvXDQ2;w4l_$K;nr5A%GhepVZ*U`tD9+OqChIJ!H`f2n`F!B>R) zNyDBe>LGz(Jb0i9zS`}dBwBcb=JUpVn1&|D2+uLfa~0qW2YTW86!MQ6Q*gXPWa$}F z@Ei)BD+Y%+ym?F%gjPic9{b`#$X4$Rh5rQ;6zp2Ysy+o ziQx4BY$!Znj%(G4RR+Tat;zz?f!Iof&$7e~hLzti4I&xt+?YK;sUSs$N6Pu-f-wb2 zl+1_QO6(etRcE<3?8MYX<_=R0<<;`?8WMvb6Av_`;f0t?#{+L!E$>mrlt~s#%(qMp zD)IvBeOx`b5bsFG+LPHZXV_*lAwxl-MrBU-b5hw1Z`Z6zMU3>bBy9eA2ywzyO3UQH!G!}L2KQ|7I6v(W9z@Bc{5<&7R=dgbF+_D3R)DTH35CFD?Pin!vbqT514(tM ze8FwlQ@6siIhlYRm#76v-AMv1)UIc%{c7V@N^Jj!By9UW?)x+ zGMa>w^{MD5n5o~$d6M_Wa-NF4N6}i4G~|o8l4UN3tqsMpm`&70m(al*^OH~w*5#tIQ3=9x4~dzDyoOs#$9xY$AF@FR^k7x_X}$-hOhReqj`8qoe^GL;-myjR3=c_=Jz9>8_NYj6?}Uj?qN%b zr|^L~JS^US>gwU3U4d&(%hnu3*Z(ypC$p!wew{3x(k8-yI!_^c6pmk|yLqIwO505y z(|d~7kt*) zGKeZDQ)xeMfOpBhQblRU6y|Mt^V*_E<`XZ>Nvep6%$@J8)DGRh|B>`bsVxC3T<*O^ zRaPz=o=fN(LULgF6R4*W#GcA$zAiP4P(6W-9{5~Vp(Z)|uAJ=mqj@hY<++p$%9|72 z8eO#uz7PGfz|J;j`uYgC_US(+w>8;)_UruZbH?j2KFiA6dxETdo#_p8CjAWN*FjlPLVn0DZSOsJX`_zNqkV@X3Md)vcx=(s1>O+FS^o zW6fxvJ>YUST2vOQhpnM{DjUw5geof{RZMkdd%vSl;}TiXF&@e6wc{)AB2jc6KAr_X zTs`2vw^-j1l8P-}Q2oWJ;Pe8$QK}6iv*&_eqO`Vm2U9dyYs)w1LejPEd~q2Zy%vG$ zVDwtCC_{!VSrC5x!b>|dDU;2@VMv+4&UKjUV$SQ!P`EwJk&6OE0{Yyz=P^qcdq*n2 z40xGM&v@CJZmi=6H2Tt(24C73>lZ>VVcOuWJiR5-KKZ3p==n-IHcB1BanIu~+uOdH z7NAMo8BP!_;|z~eUHf2`dCd` z<>u`*`k{5xFRE34TTF&)1+(6MXJVUFEb;CzH+k9Ln0f5xSr>$jvT<))yhU!$nM*>V zjp-fCE1-4V60M5tV3O<=k9xgCkp&p??QYK++z?_~#3&Ydo%uwJJR~THIp>YiP{Nu2 dcq2cFXse21cAb$1pv=u~Juz*+?i*V<`9Jl`G_n8y delta 2490 zcmW+%3s6(n7R|{QNCHuQ0R-Z$1^KnHf>q>O(V|jBt5(|}RItY0zRFKQKFPUA#6T`F zY~vMDnp-}_Krz^~W3@UusI{@3H?&nAV*6@owU}omN^9S9th{UI%&c?vo;hdlv(MV= z{4gfEJ|-G|9SNx-9Shq~4S)7JjH7i(0}J^}QlhW1o?e=G685~f{3dFT(%)e38r`>8C3SL* z;i3_4v02SlqOF&8tL_>*pi8{)nVvDGgdVjJXpAjRw$mCehPttfNac2v0lDA@i7riYl`W8C3$g6@F;C)G+%+cHcPN^G33iw!PPg>tGFD=r zvDf2Kw9$lbYwzzC;)5HkC#%^)Tm{C5mUMbqEF=;k!8Z(j4=a6RB7PcY71&Bt{ENkc zQrtldU1z;Q&&DR22!;c`Y3L8Q;7deh+-8-(sFE{6+`RAB?5f#kqXP(0iTT!`9XZqNp#gdIWSp?*KGPm}eV==J1qRpQJ7%uTQ{ zcnb=Lq2TjTJyWdEZX_meGvV_N7(HCw8ZDZ8Q>p3dOu<`UbJ8Wdf*|HXzu=cW7p<>>H`bH~p=qXdmxb${2OQ|y4 z{;txvXCS92DB(Y8~^WkR*=-1(!tfQsLB<_dEX{@;oj-RL}L*^ExPI~l9JbDVo- zbY5wynVTHQyy8gsyf*VPAKXVi^$ZCFqhbA3GJMwGA*A_y2ciW6qUMpDv^7M*o$`pV zRUcT=aFSbO?;29`+-jaT4u`wtJSG|5A?Xa~X zA8mqT6$z_0?!}Y{vV*a?;D9Zm*(lbU&1Vc+JE%gig9y9B5?2^jb;UZkF9f&0n%hrl zAvqMEDCL(5M${xx_%PC0=&FXW${gQ{cQAF9xyg|5R;4QW9TG!b7VfXez|puQ6ZgO7 zu$NGlrDH6X*lt*Bwd5IA-lH3g#@jQo;aDzAn~UIdWq3&bcPD-{n`U%z3a`Y$H|H>0 zE3r8TJeBI?oz$(u%69||>98_+iRswzsHaEUT7FTr%x^V#w|Y$k%RBi@ThZW|(< z>8`g1qH#kZ2E_vW#iks}c+PTtI`6yzt_R?z_m?mG(Y%f$YRl(x*g}B>iuSA)1!dj> z1Veka`kkC`3lE`GQgsp(dnyWWX6E-Q*zK9pV zSG8+6-B!PnUr9HgH=3;~fuXu|R0jX4Tj8IO{HG;%;9ORtE$p$e1k&nD zxSnO}wP-!~HY`S3NN_&3U*qOAbFYsf?oAW)YTNfvr20TY`IRIY7X)U2gcpxnWCh2So>n0N?fx=60c z+H@hDtdASi;LznQ4Y(hPU!XgAq@%*nNp|y`dP+T_8Wn%aQ#ITr`*^C;zmey%F6fBC zCw#kp!5a%WkxBP8(HW?;Ww)K=@?x*eh2ltgy*5W>1KkuANt)&bjYFkm>Lqq<3+lNo#7zdqe z^P8D%Z_W%&O&wIs6gwAl8sYoC|LTu9=Fiesgd(zER)wLSS}Yc5o?6JZ?%bcHU%%|?ZOjhvpS{K6pb?d`-sRt9RJdj= zU&i?_D{bvkI`}-Zu0RjZg8Or;BwK2tn(R5S<4m;VHJOPzXn)<+dgh)evM|`xDONUi zdBtbd{%$_mPcCn^DoOLD8J#T`j*K*-J+80|x#*c)5hmCkVWM*3bE{D6K%|zbD{Jj@ z7wEkr2kPdLOu4J+Vi6Ll@^DWcOkFzQi?*8D!qc%m2&%sr2zz;*$)YgKBXg(c%%Kd< zqQPW6HaPQbDSTN@FsyMd22XN_)awZQo1?(7UkfTHJ=^ zizxH@1s;Rryp0Mv{D2+E!WOr%>V+%}aqa2WKpjPw{D=8x%hfb^)9O;SKW9kw) zn;+;%hssu7Wg1#J@l?Y4TH><2FEW{~U#{&`hy&zpHlf_L{`LbOsa}aKp`&tVl6|2o ze|iZLy^-0*ECHkUhA2CxjmdEBy8pgR6txb+W|!!JL(& h43u#4u^a_TL>sgev*Tn?Fv{NSBkMCv96Xag`+r