Compare commits
46 Commits
cd5bc9a206
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b61c198159 | |||
| e664d73fcb | |||
| c8870742ae | |||
| 0bc1a5c2ad | |||
| 2039159d36 | |||
| 8374960e4e | |||
| d62d02a04a | |||
| b195069c77 | |||
| 844db083a6 | |||
| 68c8d17d32 | |||
| 14cb3e472c | |||
| e23dd30a59 | |||
| 65781912a6 | |||
| 36e57bcdf4 | |||
| b72a04511b | |||
| 5beeea2f83 | |||
| df928f0378 | |||
| 1644535557 | |||
| dcc4121c43 | |||
| 444ebda072 | |||
| 2055ed6d96 | |||
| 1a9cea452d | |||
| 8451a64984 | |||
| f5dde931dc | |||
| b82ec31f98 | |||
| 2ff19b3781 | |||
| 5278f9f2c6 | |||
| 5f1c08920f | |||
| 57db996f27 | |||
| 5af7073ed1 | |||
| 33cd2d076c | |||
| 78819bbd9d | |||
| b2d2aae61a | |||
| 320e518519 | |||
| c39a31b299 | |||
| 0ef55c5f6a | |||
| 151765d8d2 | |||
| 1ae9da59bb | |||
| 84270544bf | |||
| 8ae1aefcf3 | |||
| 821c0ee46e | |||
| a946c2b3b0 | |||
| ec89afaa5e | |||
| d530b68e86 | |||
| 924bd7a616 | |||
| 7bab5b0434 |
@@ -85,6 +85,7 @@ class World(object):
|
|||||||
self.bosses_ganon = {}
|
self.bosses_ganon = {}
|
||||||
self.bosshunt_include_agas = {}
|
self.bosshunt_include_agas = {}
|
||||||
self.ganon_item = {}
|
self.ganon_item = {}
|
||||||
|
self.require_ganon_item = {}
|
||||||
self.ganon_item_orig = {}
|
self.ganon_item_orig = {}
|
||||||
self.custom = custom
|
self.custom = custom
|
||||||
self.customitemarray = customitemarray
|
self.customitemarray = customitemarray
|
||||||
@@ -186,6 +187,7 @@ class World(object):
|
|||||||
set_player_attr('bosses_ganon', 8)
|
set_player_attr('bosses_ganon', 8)
|
||||||
set_player_attr('bosshunt_include_agas', False)
|
set_player_attr('bosshunt_include_agas', False)
|
||||||
set_player_attr('ganon_item', 'silver')
|
set_player_attr('ganon_item', 'silver')
|
||||||
|
set_player_attr('require_ganon_item', False)
|
||||||
set_player_attr('crystals_ganon_orig', {})
|
set_player_attr('crystals_ganon_orig', {})
|
||||||
set_player_attr('crystals_gt_orig', {})
|
set_player_attr('crystals_gt_orig', {})
|
||||||
set_player_attr('ganon_item_orig', 'silver')
|
set_player_attr('ganon_item_orig', 'silver')
|
||||||
@@ -1407,7 +1409,7 @@ class CollectionState(object):
|
|||||||
def can_hit_stunned_ganon(self, player):
|
def can_hit_stunned_ganon(self, player):
|
||||||
ganon_item = self.world.ganon_item[player]
|
ganon_item = self.world.ganon_item[player]
|
||||||
if ganon_item == "silver":
|
if ganon_item == "silver":
|
||||||
return self.has("Silver Arroys", player) and self.can_shoot_arrows(player)
|
return self.has("Silver Arrows", player) and self.can_shoot_arrows(player)
|
||||||
elif ganon_item == "boomerang":
|
elif ganon_item == "boomerang":
|
||||||
return self.has("Blue Boomerang", player) or self.has("Red Boomerang", player)
|
return self.has("Blue Boomerang", player) or self.has("Red Boomerang", player)
|
||||||
elif ganon_item == "hookshot":
|
elif ganon_item == "hookshot":
|
||||||
@@ -1519,7 +1521,10 @@ class CollectionState(object):
|
|||||||
if not item:
|
if not item:
|
||||||
return
|
return
|
||||||
changed = False
|
changed = False
|
||||||
if item.name.startswith('Progressive '):
|
if item.name == "Sword and Shield":
|
||||||
|
self.prog_items["Fighter Sword", item.player] += 1
|
||||||
|
self.prog_items["Blue Shield", item.player] += 1
|
||||||
|
elif item.name.startswith('Progressive '):
|
||||||
if 'Sword' in item.name:
|
if 'Sword' in item.name:
|
||||||
if self.has('Golden Sword', item.player):
|
if self.has('Golden Sword', item.player):
|
||||||
pass
|
pass
|
||||||
@@ -2895,6 +2900,10 @@ class Item(object):
|
|||||||
def compass(self):
|
def compass(self):
|
||||||
return self.type == 'Compass'
|
return self.type == 'Compass'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event(self):
|
||||||
|
return self.type == 'Event'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dungeon(self):
|
def dungeon(self):
|
||||||
if not self.smallkey and not self.bigkey and not self.map and not self.compass:
|
if not self.smallkey and not self.bigkey and not self.map and not self.compass:
|
||||||
@@ -3147,6 +3156,7 @@ class Spoiler(object):
|
|||||||
'ganon_bosses': self.world.bosses_ganon,
|
'ganon_bosses': self.world.bosses_ganon,
|
||||||
'bosshunt_include_agas': self.world.bosshunt_include_agas,
|
'bosshunt_include_agas': self.world.bosshunt_include_agas,
|
||||||
'ganon_item': self.world.ganon_item,
|
'ganon_item': self.world.ganon_item,
|
||||||
|
'require_ganon_item': self.world.require_ganon_item,
|
||||||
'open_pyramid': self.world.open_pyramid,
|
'open_pyramid': self.world.open_pyramid,
|
||||||
'accessibility': self.world.accessibility,
|
'accessibility': self.world.accessibility,
|
||||||
'restricted_boss_items': self.world.restrict_boss_items,
|
'restricted_boss_items': self.world.restrict_boss_items,
|
||||||
@@ -3384,7 +3394,8 @@ class Spoiler(object):
|
|||||||
if custom['murahgoal'] and 'requirements' in custom['murahgoal']:
|
if custom['murahgoal'] and 'requirements' in custom['murahgoal']:
|
||||||
outfile.write('Murahdahla Requirement:'.ljust(line_width) + 'custom\n')
|
outfile.write('Murahdahla Requirement:'.ljust(line_width) + 'custom\n')
|
||||||
outfile.write(' %s\n' % custom['murahgoal']['goaltext'])
|
outfile.write(' %s\n' % custom['murahgoal']['goaltext'])
|
||||||
outfile.write('Item Required for Ganon:'.ljust(line_width) + '%s\n' % str(self.world.ganon_item_orig[player]))
|
outfile.write('Item to Hurt Stunned Ganon:'.ljust(line_width) + '%s\n' % str(self.world.ganon_item_orig[player]))
|
||||||
|
outfile.write('Item Required for Ganon:'.ljust(line_width) + '%s\n' % yn(self.world.require_ganon_item[player]))
|
||||||
outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player])
|
outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player])
|
||||||
outfile.write('\n')
|
outfile.write('\n')
|
||||||
outfile.write('Accessibility:'.ljust(line_width) + '%s\n' % self.metadata['accessibility'][player])
|
outfile.write('Accessibility:'.ljust(line_width) + '%s\n' % self.metadata['accessibility'][player])
|
||||||
|
|||||||
16
CLI.py
16
CLI.py
@@ -89,6 +89,7 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
parser.add_argument('--count', default=defval(int(settings["count"]) if settings["count"] != "" and settings["count"] is not None else 1), help="\n".join(fish.translate("cli", "help", "count")), type=int)
|
parser.add_argument('--count', default=defval(int(settings["count"]) if settings["count"] != "" and settings["count"] is not None else 1), help="\n".join(fish.translate("cli", "help", "count")), type=int)
|
||||||
parser.add_argument('--tries', default=defval(int(settings["tries"]) if settings["tries"] != "" and settings["tries"] is not None else 1), help="\n".join(fish.translate("cli", "help", "tries")), type=int)
|
parser.add_argument('--tries', default=defval(int(settings["tries"]) if settings["tries"] != "" and settings["tries"] is not None else 1), help="\n".join(fish.translate("cli", "help", "tries")), type=int)
|
||||||
parser.add_argument('--customitemarray', default={}, help=argparse.SUPPRESS)
|
parser.add_argument('--customitemarray', default={}, help=argparse.SUPPRESS)
|
||||||
|
parser.add_argument('--skip_money_balance', action="store_true", help=argparse.SUPPRESS)
|
||||||
|
|
||||||
# included for backwards compatibility
|
# included for backwards compatibility
|
||||||
parser.add_argument('--multi', default=defval(settings["multi"]), type=lambda value: min(max(int(value), 1), 255))
|
parser.add_argument('--multi', default=defval(settings["multi"]), type=lambda value: min(max(int(value), 1), 255))
|
||||||
@@ -106,7 +107,14 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
ret = parser.parse_args(argv)
|
ret = parser.parse_args(argv)
|
||||||
|
|
||||||
if ret.keysanity:
|
if ret.keysanity:
|
||||||
ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = ['wild'] * 4
|
if ret.mapshuffle == "none":
|
||||||
|
ret.mapshuffle = "wild"
|
||||||
|
if ret.compassshuffle == "none":
|
||||||
|
ret.compassshuffle = "wild"
|
||||||
|
if ret.keyshuffle == "none":
|
||||||
|
ret.keyshuffle = "wild"
|
||||||
|
if ret.bigkeyshuffle == "none":
|
||||||
|
ret.bigkeyshuffle = "wild"
|
||||||
|
|
||||||
if ret.keydropshuffle:
|
if ret.keydropshuffle:
|
||||||
ret.dropshuffle = 'keys' if ret.dropshuffle == 'none' else ret.dropshuffle
|
ret.dropshuffle = 'keys' if ret.dropshuffle == 'none' else ret.dropshuffle
|
||||||
@@ -151,7 +159,8 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
'take_any', 'boots_hint', 'shuffle_followers',
|
'take_any', 'boots_hint', 'shuffle_followers',
|
||||||
'shuffle', 'door_shuffle', 'intensity',
|
'shuffle', 'door_shuffle', 'intensity',
|
||||||
'crystals_ganon', 'crystals_gt', 'bosses_ganon',
|
'crystals_ganon', 'crystals_gt', 'bosses_ganon',
|
||||||
'bosshunt_include_agas', 'ganon_item', 'openpyramid',
|
'bosshunt_include_agas', 'ganon_item',
|
||||||
|
'require_ganon_item', 'openpyramid',
|
||||||
'mapshuffle', 'compassshuffle', 'keyshuffle',
|
'mapshuffle', 'compassshuffle', 'keyshuffle',
|
||||||
'bigkeyshuffle', 'prizeshuffle', 'showloot', 'loothud',
|
'bigkeyshuffle', 'prizeshuffle', 'showloot', 'loothud',
|
||||||
'showmap', 'startinventory', 'usestartinventory',
|
'showmap', 'startinventory', 'usestartinventory',
|
||||||
@@ -178,7 +187,7 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
'decoupledoors', 'door_type_mode', 'bonk_drops',
|
'decoupledoors', 'door_type_mode', 'bonk_drops',
|
||||||
'trap_door_mode', 'key_logic_algorithm',
|
'trap_door_mode', 'key_logic_algorithm',
|
||||||
'door_self_loops', 'any_enemy_logic', 'aga_randomness',
|
'door_self_loops', 'any_enemy_logic', 'aga_randomness',
|
||||||
'money_balance']:
|
'money_balance', 'patches']:
|
||||||
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
||||||
if player == 1:
|
if player == 1:
|
||||||
setattr(ret, name, {1: value})
|
setattr(ret, name, {1: value})
|
||||||
@@ -212,6 +221,7 @@ def parse_settings():
|
|||||||
"bosses_ganon": "8",
|
"bosses_ganon": "8",
|
||||||
"bosshunt_include_agas": False,
|
"bosshunt_include_agas": False,
|
||||||
"ganon_item": "silver",
|
"ganon_item": "silver",
|
||||||
|
"require_ganon_item": False,
|
||||||
"swords": "random",
|
"swords": "random",
|
||||||
"flute_mode": "normal",
|
"flute_mode": "normal",
|
||||||
"bow_mode": "progressive",
|
"bow_mode": "progressive",
|
||||||
|
|||||||
5
Fill.py
5
Fill.py
@@ -252,6 +252,7 @@ def verify_spot_to_fill(location, item_to_place, max_exp_state, single_player_pl
|
|||||||
or (world.algorithm == 'vanilla_fill' and item_to_place.is_near_dungeon_item(world)))) \
|
or (world.algorithm == 'vanilla_fill' and item_to_place.is_near_dungeon_item(world)))) \
|
||||||
or valid_dungeon_placement(item_to_place, location, world):
|
or valid_dungeon_placement(item_to_place, location, world):
|
||||||
return location
|
return location
|
||||||
|
|
||||||
if item_to_place.smallkey or item_to_place.bigkey or item_to_place.prize:
|
if item_to_place.smallkey or item_to_place.bigkey or item_to_place.prize:
|
||||||
location.item = None
|
location.item = None
|
||||||
location.event = False
|
location.event = False
|
||||||
@@ -311,7 +312,9 @@ def valid_dungeon_placement(item, location, world):
|
|||||||
dungeon = check_dungeon
|
dungeon = check_dungeon
|
||||||
if dungeon:
|
if dungeon:
|
||||||
layout = world.dungeon_layouts[location.player][dungeon.name]
|
layout = world.dungeon_layouts[location.player][dungeon.name]
|
||||||
if not is_dungeon_item(item, world) or item.player != location.player:
|
if item.event:
|
||||||
|
return True
|
||||||
|
elif not is_dungeon_item(item, world) or item.player != location.player:
|
||||||
if item.prize and item.is_near_dungeon_item(world):
|
if item.prize and item.is_near_dungeon_item(world):
|
||||||
return item.dungeon_object == dungeon and layout.free_items > 0
|
return item.dungeon_object == dungeon and layout.free_items > 0
|
||||||
return layout.free_items > 0
|
return layout.free_items > 0
|
||||||
|
|||||||
30
ItemList.py
30
ItemList.py
@@ -372,6 +372,13 @@ def generate_itempool(world, player):
|
|||||||
world.push_precollected(ItemFactory(item, player))
|
world.push_precollected(ItemFactory(item, player))
|
||||||
|
|
||||||
if world.mode[player] == 'standard' and not world.state.has_blunt_weapon(player):
|
if world.mode[player] == 'standard' and not world.state.has_blunt_weapon(player):
|
||||||
|
if world.customizer:
|
||||||
|
placements = world.customizer.get_placements()
|
||||||
|
if placements:
|
||||||
|
custom_uncle = placements.get(player, {}).get("Link's Uncle")
|
||||||
|
if custom_uncle:
|
||||||
|
placed_items["Link's Uncle"] = custom_uncle
|
||||||
|
|
||||||
if "Link's Uncle" not in placed_items:
|
if "Link's Uncle" not in placed_items:
|
||||||
found_sword = False
|
found_sword = False
|
||||||
found_bow = False
|
found_bow = False
|
||||||
@@ -865,7 +872,7 @@ def set_up_shops(world, player):
|
|||||||
rss.locked = True
|
rss.locked = True
|
||||||
cap_shop = world.get_region('Capacity Upgrade', player).shop
|
cap_shop = world.get_region('Capacity Upgrade', player).shop
|
||||||
cap_shop.inventory[1] = None # remove arrow capacity upgrades in retro
|
cap_shop.inventory[1] = None # remove arrow capacity upgrades in retro
|
||||||
for shop in random.sample([s for s in world.shops[player] if not s.locked and s.region.player == player], 5):
|
for shop in random.sample([s for s in world.shops[player] if not s.locked and s.region.name != "Red Shield Shop" and s.region.player == player], 5):
|
||||||
shop.custom = True
|
shop.custom = True
|
||||||
shop.locked = True
|
shop.locked = True
|
||||||
if retro_bow:
|
if retro_bow:
|
||||||
@@ -937,6 +944,7 @@ def customize_shops(world, player):
|
|||||||
rep_price = final_price(loc.name, item.price, world, player)
|
rep_price = final_price(loc.name, item.price, world, player)
|
||||||
shop.add_inventory(idx, upgrade.name, up_price, 6,
|
shop.add_inventory(idx, upgrade.name, up_price, 6,
|
||||||
item.name, rep_price, player=item.player)
|
item.name, rep_price, player=item.player)
|
||||||
|
upgrade.world = loc.item.world
|
||||||
loc.item = upgrade
|
loc.item = upgrade
|
||||||
upgrade.location = loc
|
upgrade.location = loc
|
||||||
if not found_arrow_upgrade and len(possible_replacements) > 0:
|
if not found_arrow_upgrade and len(possible_replacements) > 0:
|
||||||
@@ -952,6 +960,7 @@ def customize_shops(world, player):
|
|||||||
shop.add_inventory(idx, upgrade.name, up_price, 6,
|
shop.add_inventory(idx, upgrade.name, up_price, 6,
|
||||||
item.name, rep_price, player=item.player)
|
item.name, rep_price, player=item.player)
|
||||||
loc.item = upgrade
|
loc.item = upgrade
|
||||||
|
upgrade.world = loc.item.world
|
||||||
upgrade.location = loc
|
upgrade.location = loc
|
||||||
change_shop_items_to_rupees(world, player, shops_to_customize)
|
change_shop_items_to_rupees(world, player, shops_to_customize)
|
||||||
balance_prices(world, player)
|
balance_prices(world, player)
|
||||||
@@ -988,9 +997,11 @@ def change_shop_items_to_rupees(world, player, shops):
|
|||||||
for location in locations:
|
for location in locations:
|
||||||
if location.item.name in shop_transfer.keys() and (location.parent_region.name not in shops or location.name == 'Potion Shop'):
|
if location.item.name in shop_transfer.keys() and (location.parent_region.name not in shops or location.name == 'Potion Shop'):
|
||||||
new_item = ItemFactory(shop_transfer[location.item.name], location.item.player)
|
new_item = ItemFactory(shop_transfer[location.item.name], location.item.player)
|
||||||
|
new_item.world = location.item.world
|
||||||
location.item = new_item
|
location.item = new_item
|
||||||
if location.parent_region.name == 'Capacity Upgrade' and location.item.name in cap_blacklist:
|
if location.parent_region.name == 'Capacity Upgrade' and location.item.name in cap_blacklist:
|
||||||
new_item = ItemFactory('Rupees (300)', location.item.player)
|
new_item = ItemFactory('Rupees (300)', location.item.player)
|
||||||
|
new_item.world = location.item.world
|
||||||
location.item = new_item
|
location.item = new_item
|
||||||
shop = world.get_region('Capacity Upgrade', player).shop
|
shop = world.get_region('Capacity Upgrade', player).shop
|
||||||
slot = shop_to_location_table['Capacity Upgrade'].index(location.name)
|
slot = shop_to_location_table['Capacity Upgrade'].index(location.name)
|
||||||
@@ -1669,12 +1680,15 @@ def fill_specific_items(world):
|
|||||||
item_to_place, event_flag = get_item_and_event_flag(item, world, player,
|
item_to_place, event_flag = get_item_and_event_flag(item, world, player,
|
||||||
dungeon_pool, prize_set, prize_pool)
|
dungeon_pool, prize_set, prize_pool)
|
||||||
if item_to_place:
|
if item_to_place:
|
||||||
world.push_item(loc, item_to_place, False)
|
if not loc.item:
|
||||||
loc.locked = True
|
world.push_item(loc, item_to_place, False)
|
||||||
track_outside_keys(item_to_place, loc, world)
|
loc.locked = True
|
||||||
track_dungeon_items(item_to_place, loc, world)
|
track_outside_keys(item_to_place, loc, world)
|
||||||
loc.event = (event_flag or item_to_place.advancement
|
track_dungeon_items(item_to_place, loc, world)
|
||||||
or item_to_place.bigkey or item_to_place.smallkey)
|
loc.event = (event_flag or item_to_place.advancement
|
||||||
|
or item_to_place.bigkey or item_to_place.smallkey)
|
||||||
|
elif loc.item != item_to_place:
|
||||||
|
logging.getLogger('').warning("Failed to place item %s at location %s because it already contained %s", item_to_place, loc.name, loc.item)
|
||||||
else:
|
else:
|
||||||
raise Exception(f'Did not find "{item}" in item pool to place at "{location}"')
|
raise Exception(f'Did not find "{item}" in item pool to place at "{location}"')
|
||||||
advanced_placements = world.customizer.get_advanced_placements()
|
advanced_placements = world.customizer.get_advanced_placements()
|
||||||
@@ -1802,7 +1816,7 @@ def shuffle_event_items(world, player):
|
|||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise FillError(f'Unable to place followers: {", ".join(list(map(lambda d: d.hint_text, follower_locations)))}')
|
raise FillError(f'Unable to place followers: {", ".join(list(map(lambda f: f.name, pickup_items)))}')
|
||||||
|
|
||||||
|
|
||||||
def get_item_and_event_flag(item, world, player, dungeon_pool, prize_set, prize_pool):
|
def get_item_and_event_flag(item, world, player, dungeon_pool, prize_set, prize_pool):
|
||||||
|
|||||||
15
Items.py
15
Items.py
@@ -55,7 +55,7 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'Bow!\nJoin the archer class
|
|||||||
'Master Sword': (True, False, 'Sword', 0x50, 100, 'Master Sword!\nEvil\'s bane!', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'sword boy fights again', 'the Master Sword'),
|
'Master Sword': (True, False, 'Sword', 0x50, 100, 'Master Sword!\nEvil\'s bane!', '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, 'Tempered Sword!\nMore slashy!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again', 'the Tempered Sword'),
|
'Tempered Sword': (True, False, 'Sword', 0x02, 150, 'Tempered Sword!\nMore slashy!', '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, 'Fighter Sword!\nStarter level slashy!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again', 'the Fighter Sword'),
|
'Fighter Sword': (True, False, 'Sword', 0x49, 50, 'Fighter Sword!\nStarter level slashy!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again', 'the Fighter Sword'),
|
||||||
'Sword and Shield': (True, False, 'Sword', 0x00, 'Sword and Shield!\nUncle sword ahoy!', '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'),
|
'Sword and Shield': (True, False, 'Sword', 0x00, 50, 'Sword and Shield!\nUncle sword ahoy!', '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, 'Golden Sword!\nBest slashy!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again', 'the Golden Sword'),
|
'Golden Sword': (True, False, 'Sword', 0x03, 200, 'Golden Sword!\nBest slashy!', '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, 'Sword!\nA better sword for your time!', 'the unknown sword', 'sword-wielding kid', 'sword for sale', 'fungus for some slasher', 'sword boy fights again', 'a Sword'),
|
'Progressive Sword': (True, False, 'Sword', 0x5E, 150, 'Sword!\nA better sword for 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, 'Glove!\nLift more than you can now!', 'and the lift upgrade', 'body-building kid', 'some glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'a Glove'),
|
'Progressive Glove': (True, False, None, 0x61, 150, 'Glove!\nLift more than you can now!', 'and the lift upgrade', 'body-building kid', 'some glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'a Glove'),
|
||||||
@@ -97,8 +97,8 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'Bow!\nJoin the archer class
|
|||||||
'Progressive Shield': (True, False, None, 0x5F, 50, 'Shield!\nA better shield for your time!', 'and the new shield', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a shield'),
|
'Progressive Shield': (True, False, None, 0x5F, 50, 'Shield!\nA better shield for your time!', '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, 'Bug Net!\nCatch all manner\nof things!', 'and the bee catcher', 'the bug-catching kid', 'stick web for sale', 'fungus for butterflies', 'wrong boy catches bees again', 'the Bug Net'),
|
'Bug Catching Net': (True, False, None, 0x21, 50, 'Bug Net!\nCatch all manner\nof things!', '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, 'Cane of Byrna!\nSwirly protection!', '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, 'Cane of Byrna!\nSwirly protection!', '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, 'Heart Container!\nHealth Increased!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'),
|
'Boss Heart Container': (False, True, None, 0x3E, 40, 'Heart Container!\nHealth Increased!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart container'),
|
||||||
'Sanctuary Heart Container': (False, True, None, 0x3F, 50, 'Heart Container!\nHealth Increased!', '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, 'Heart Container!\nHealth Increased!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart container'),
|
||||||
'Piece of Heart': (False, False, None, 0x17, 10, 'Heart Piece!\nOne step closer\nto more health!', 'and the broken heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart piece'),
|
'Piece of Heart': (False, False, None, 0x17, 10, 'Heart Piece!\nOne step closer\nto more health!', 'and the broken heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart piece'),
|
||||||
'Rupee (1)': (False, False, None, 0x34, 0, 'Rupees!\nJust pocket\nchange.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a green rupee'),
|
'Rupee (1)': (False, False, None, 0x34, 0, 'Rupees!\nJust pocket\nchange.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a green rupee'),
|
||||||
'Rupees (5)': (False, False, None, 0x35, 2, 'Rupees!\nJust pocket\nchange.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a blue rupee'),
|
'Rupees (5)': (False, False, None, 0x35, 2, 'Rupees!\nJust pocket\nchange.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a blue rupee'),
|
||||||
@@ -134,9 +134,9 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'Bow!\nJoin the archer class
|
|||||||
'Big Key (Agahnims Tower)': (False, False, 'BigKey', 0x9B, 60, 'A big key for\nAgahnim\'s Tower', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Castle Tower'),
|
'Big Key (Agahnims Tower)': (False, False, 'BigKey', 0x9B, 60, 'A big key for\nAgahnim\'s Tower', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Castle Tower'),
|
||||||
'Compass (Agahnims Tower)': (False, True, 'Compass', 0x8B, 10, 'A compass for\nAgahnim\'s Tower', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Castle Tower'),
|
'Compass (Agahnims Tower)': (False, True, 'Compass', 0x8B, 10, 'A compass for\nAgahnim\'s Tower', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Castle Tower'),
|
||||||
'Map (Agahnims Tower)': (False, True, 'Map', 0x7B, 10, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Castle Tower'),
|
'Map (Agahnims Tower)': (False, True, 'Map', 0x7B, 10, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Castle Tower'),
|
||||||
'Small Key (Palace of Darkness)': (False, False, 'SmallKey', 0xA6, 40, 'A small key for\nDark Palace', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Palace of Darkness'),
|
'Small Key (Palace of Darkness)': (False, False, 'SmallKey', 0xA6, 40, 'A small key for\nPalace of Darkness', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Palace of Darkness'),
|
||||||
'Big Key (Palace of Darkness)': (False, False, 'BigKey', 0x99, 60, 'A big key for\nDark Palace', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Palace of Darkness'),
|
'Big Key (Palace of Darkness)': (False, False, 'BigKey', 0x99, 60, 'A big key for\nPalace of Darkness', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Palace of Darkness'),
|
||||||
'Compass (Palace of Darkness)': (False, True, 'Compass', 0x89, 10, 'A compass for\nDark Palace', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Palace of Darkness'),
|
'Compass (Palace of Darkness)': (False, True, 'Compass', 0x89, 10, 'A compass for\nPalace of Darkness', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Palace of Darkness'),
|
||||||
'Map (Palace of Darkness)': (False, True, 'Map', 0x79, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Palace of Darkness'),
|
'Map (Palace of Darkness)': (False, True, 'Map', 0x79, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Palace of Darkness'),
|
||||||
'Small Key (Thieves Town)': (False, False, 'SmallKey', 0xAB, 40, 'A small key for\nThieves Town', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Thieves\' Town'),
|
'Small Key (Thieves Town)': (False, False, 'SmallKey', 0xAB, 40, 'A small key for\nThieves Town', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Thieves\' Town'),
|
||||||
'Big Key (Thieves Town)': (False, False, 'BigKey', 0x94, 60, 'A big key for\nThieves Town', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Thieves\' Town'),
|
'Big Key (Thieves Town)': (False, False, 'BigKey', 0x94, 60, 'A big key for\nThieves Town', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Thieves\' Town'),
|
||||||
@@ -172,9 +172,10 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'Bow!\nJoin the archer class
|
|||||||
'Red Potion': (False, False, None, 0x2E, 150, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a red potion'),
|
'Red Potion': (False, False, None, 0x2E, 150, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a red potion'),
|
||||||
'Green Potion': (False, False, None, 0x2F, 60, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a green potion'),
|
'Green Potion': (False, False, None, 0x2F, 60, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a green potion'),
|
||||||
'Blue Potion': (False, False, None, 0x30, 160, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a blue potion'),
|
'Blue Potion': (False, False, None, 0x30, 160, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a blue potion'),
|
||||||
|
'Orange Potion': (False, False, None, 0x66, 1000, 'Energizing orange goop!', 'and the orange goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has orange goo again', 'an orange potion'),
|
||||||
'Bee': (False, False, None, 0x0E, 10, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bee'),
|
'Bee': (False, False, None, 0x0E, 10, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bee'),
|
||||||
'Good Bee': (False, False, None, 0xD6, 10, 'I will sting your foes a lot', 'and the cold buddy', 'the beekeeper kid', 'cold insect for sale', 'shroom pollenation', 'bottle boy has cold bee again', 'a good bee'),
|
'Good Bee': (False, False, None, 0xD6, 10, 'I will sting your foes a lot', 'and the cold buddy', 'the beekeeper kid', 'cold insect for sale', 'shroom pollenation', 'bottle boy has cold bee again', 'a good bee'),
|
||||||
'Small Heart': (False, False, None, 0x42, 10, 'Just a little\npiece of love!', 'and the heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart'),
|
'Small Heart': (False, False, None, 0x42, 10, 'Just a little\npiece of love!', 'and the heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a refill heart'),
|
||||||
'Apples': (False, False, None, 0xD1, 30, 'Just a few pieces of fruit!', 'and the juicy fruit', 'the fruity kid', 'the fruit stand', 'expired fruit', 'bottle boy has fruit again', 'an apple hoard'),
|
'Apples': (False, False, None, 0xD1, 30, 'Just a few pieces of fruit!', 'and the juicy fruit', 'the fruity kid', 'the fruit stand', 'expired fruit', 'bottle boy has fruit again', 'an apple hoard'),
|
||||||
'Fairy': (False, False, None, 0xD2, 50, 'Just a pixie!', 'and the pixie', 'the pixie kid', 'pixie for sale', 'pixie fungus', 'bottle boy has pixie again', 'a pixie'),
|
'Fairy': (False, False, None, 0xD2, 50, 'Just a pixie!', 'and the pixie', 'the pixie kid', 'pixie for sale', 'pixie fungus', 'bottle boy has pixie again', 'a pixie'),
|
||||||
'Beat Boss': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
|
'Beat Boss': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
|
||||||
|
|||||||
31
Main.py
31
Main.py
@@ -67,6 +67,7 @@ from Rom import (
|
|||||||
JsonRom,
|
JsonRom,
|
||||||
LocalRom,
|
LocalRom,
|
||||||
apply_rom_settings,
|
apply_rom_settings,
|
||||||
|
apply_rom_patches,
|
||||||
get_hash_string,
|
get_hash_string,
|
||||||
patch_race_rom,
|
patch_race_rom,
|
||||||
patch_rom,
|
patch_rom,
|
||||||
@@ -335,10 +336,29 @@ def main(args, seed=None, fish=None):
|
|||||||
for player in range(1, world.players+1):
|
for player in range(1, world.players+1):
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
customize_shops(world, player)
|
customize_shops(world, player)
|
||||||
if args.algorithm in ['balanced', 'equitable']:
|
|
||||||
|
if not args.skip_money_balance and args.algorithm in ['balanced', 'equitable']:
|
||||||
balance_money_progression(world)
|
balance_money_progression(world)
|
||||||
ensure_good_items(world, True)
|
ensure_good_items(world, True)
|
||||||
|
|
||||||
|
for player in range(1, world.players+1):
|
||||||
|
if args.orange_potion and world.difficulty[player] == "normal":
|
||||||
|
cap_shop = world.get_region('Capacity Upgrade', player).shop
|
||||||
|
potion = {
|
||||||
|
'item': "Orange Potion",
|
||||||
|
'price': 1000,
|
||||||
|
'max': 0,
|
||||||
|
'replacement': None,
|
||||||
|
'replacement_price': 0,
|
||||||
|
'create_location': False,
|
||||||
|
'player': 0,
|
||||||
|
}
|
||||||
|
if cap_shop.inventory[0] is None:
|
||||||
|
cap_shop.inventory[0] = potion
|
||||||
|
else:
|
||||||
|
cap_shop.inventory.insert(1, potion)
|
||||||
|
|
||||||
|
|
||||||
if args.print_custom_yaml:
|
if args.print_custom_yaml:
|
||||||
world.settings.record_info(world)
|
world.settings.record_info(world)
|
||||||
world.settings.record_overworld(world)
|
world.settings.record_overworld(world)
|
||||||
@@ -364,6 +384,8 @@ def main(args, seed=None, fish=None):
|
|||||||
rom_names.append((player, team, list(rom.name)))
|
rom_names.append((player, team, list(rom.name)))
|
||||||
world.spoiler.hashes[(player, team)] = get_hash_string(rom.hash)
|
world.spoiler.hashes[(player, team)] = get_hash_string(rom.hash)
|
||||||
|
|
||||||
|
if args.patches[player]:
|
||||||
|
apply_rom_patches(rom, map(lambda arg: arg.strip(), args.patches[player].split(",")))
|
||||||
apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player],
|
apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player],
|
||||||
args.fastmenu[player], args.disablemusic[player], args.sprite[player], args.triforce_gfx[player],
|
args.fastmenu[player], args.disablemusic[player], args.sprite[player], args.triforce_gfx[player],
|
||||||
args.ow_palettes[player], args.uw_palettes[player], args.reduce_flashing[player],
|
args.ow_palettes[player], args.uw_palettes[player], args.reduce_flashing[player],
|
||||||
@@ -479,7 +501,7 @@ def export_yaml(args, fish):
|
|||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
|
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
|
||||||
|
|
||||||
set_starting_inventory(world, args)
|
set_starting_inventory(world, args)
|
||||||
|
|
||||||
world.settings = CustomSettings()
|
world.settings = CustomSettings()
|
||||||
@@ -524,6 +546,7 @@ def init_world(args, fish):
|
|||||||
world.crystals_ganon_orig = args.crystals_ganon.copy()
|
world.crystals_ganon_orig = args.crystals_ganon.copy()
|
||||||
world.crystals_gt_orig = args.crystals_gt.copy()
|
world.crystals_gt_orig = args.crystals_gt.copy()
|
||||||
world.ganon_item_orig = args.ganon_item.copy()
|
world.ganon_item_orig = args.ganon_item.copy()
|
||||||
|
world.require_ganon_item = args.require_ganon_item.copy()
|
||||||
world.bosses_ganon = {player: int(args.bosses_ganon[player]) for player in range(1, world.players + 1)}
|
world.bosses_ganon = {player: int(args.bosses_ganon[player]) for player in range(1, world.players + 1)}
|
||||||
world.bosshunt_include_agas = args.bosshunt_include_agas.copy()
|
world.bosshunt_include_agas = args.bosshunt_include_agas.copy()
|
||||||
world.owTerrain = args.ow_terrain.copy()
|
world.owTerrain = args.ow_terrain.copy()
|
||||||
@@ -572,7 +595,7 @@ def init_world(args, fish):
|
|||||||
world.collection_rate = args.collection_rate.copy()
|
world.collection_rate = args.collection_rate.copy()
|
||||||
world.colorizepots = args.colorizepots.copy()
|
world.colorizepots = args.colorizepots.copy()
|
||||||
world.aga_randomness = args.aga_randomness.copy()
|
world.aga_randomness = args.aga_randomness.copy()
|
||||||
world.money_balance = args.money_balance.copy()
|
world.money_balance = {player: int(args.money_balance[player]) for player in range(1, world.players + 1)}
|
||||||
|
|
||||||
# custom settings - these haven't been promoted to full settings yet
|
# custom settings - these haven't been promoted to full settings yet
|
||||||
in_progress_settings = ['force_enemy']
|
in_progress_settings = ['force_enemy']
|
||||||
@@ -849,6 +872,7 @@ def copy_world(world):
|
|||||||
ret.bosses_ganon = world.bosses_ganon.copy()
|
ret.bosses_ganon = world.bosses_ganon.copy()
|
||||||
ret.bosshunt_include_agas = world.bosshunt_include_agas.copy()
|
ret.bosshunt_include_agas = world.bosshunt_include_agas.copy()
|
||||||
ret.ganon_item = world.ganon_item.copy()
|
ret.ganon_item = world.ganon_item.copy()
|
||||||
|
ret.require_ganon_item = world.require_ganon_item.copy()
|
||||||
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
|
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
|
||||||
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
|
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
|
||||||
ret.ganon_item_orig = world.ganon_item_orig.copy()
|
ret.ganon_item_orig = world.ganon_item_orig.copy()
|
||||||
@@ -1083,6 +1107,7 @@ def copy_world_premature(world, player, create_flute_exits=True):
|
|||||||
ret.bosses_ganon = world.bosses_ganon.copy()
|
ret.bosses_ganon = world.bosses_ganon.copy()
|
||||||
ret.bosshunt_include_agas = world.bosshunt_include_agas.copy()
|
ret.bosshunt_include_agas = world.bosshunt_include_agas.copy()
|
||||||
ret.ganon_item = world.ganon_item.copy()
|
ret.ganon_item = world.ganon_item.copy()
|
||||||
|
ret.require_ganon_item = world.require_ganon_item.copy()
|
||||||
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
|
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
|
||||||
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
|
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
|
||||||
ret.ganon_item_orig = world.ganon_item_orig.copy()
|
ret.ganon_item_orig = world.ganon_item_orig.copy()
|
||||||
|
|||||||
@@ -509,7 +509,7 @@ boots_clips = [
|
|||||||
|
|
||||||
mirror_clips_local = [
|
mirror_clips_local = [
|
||||||
('Desert East Mirror Clip', 'Mire Area', 'Desert Mouth'),
|
('Desert East Mirror Clip', 'Mire Area', 'Desert Mouth'),
|
||||||
('EDDM Mirror Clip', 'East Dark Death Mountain (Bottom Left)', 'East Dark Death Mountain (Bottom)'),
|
('EDDM Bridge Mirror Clip', 'East Dark Death Mountain (Bottom Left)', 'East Dark Death Mountain (Bottom)'),
|
||||||
('EDDM Mirror Clip', 'East Dark Death Mountain (Top)', 'Dark Death Mountain Ledge')
|
('EDDM Mirror Clip', 'East Dark Death Mountain (Top)', 'Dark Death Mountain Ledge')
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -520,4 +520,4 @@ mirror_clips = [
|
|||||||
mirror_offsets = [
|
mirror_offsets = [
|
||||||
(['DM Offset Mirror', 'DDM Offset Mirror'], ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)'], ['Hyrule Castle Courtyard Northeast', 'Pyramid Crack'], ['Pyramid Area', 'Hyrule Castle Courtyard']),
|
(['DM Offset Mirror', 'DDM Offset Mirror'], ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)'], ['Hyrule Castle Courtyard Northeast', 'Pyramid Crack'], ['Pyramid Area', 'Hyrule Castle Courtyard']),
|
||||||
(['DM To HC Ledge Offset Mirror', 'DDM To Pyramid Offset Mirror'], ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)'], ['Hyrule Castle Ledge', 'Pyramid Area'], ['Pyramid Area', 'Hyrule Castle Area'])
|
(['DM To HC Ledge Offset Mirror', 'DDM To Pyramid Offset Mirror'], ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)'], ['Hyrule Castle Ledge', 'Pyramid Area'], ['Pyramid Area', 'Hyrule Castle Area'])
|
||||||
]
|
]
|
||||||
|
|||||||
169
Rom.py
169
Rom.py
@@ -85,7 +85,7 @@ from Utils import int16_as_bytes, int32_as_bytes, local_path, snes_to_pc
|
|||||||
from Versions import DRVersion, GKVersion, ORVersion
|
from Versions import DRVersion, GKVersion, ORVersion
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = 'd5b351a79bab079408bdf19b0deaa655'
|
RANDOMIZERBASEHASH = 'd80446af9eeb1726d2b6c1303bec1226'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -948,7 +948,7 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
rom.write_byte(cr_pc+0x1e, 0xEE) # slash
|
rom.write_byte(cr_pc+0x1e, 0xEE) # slash
|
||||||
rom.write_byte(cr_pc+0x1f, thousands_bot)
|
rom.write_byte(cr_pc+0x1f, thousands_bot)
|
||||||
# modify stat config
|
# modify stat config
|
||||||
stat_address = 0x23983E
|
stat_address = 0xA39895
|
||||||
stat_pc = snes_to_pc(stat_address)
|
stat_pc = snes_to_pc(stat_address)
|
||||||
rom.write_byte(stat_pc, 0xa9) # change to pos 21 (from b1)
|
rom.write_byte(stat_pc, 0xa9) # change to pos 21 (from b1)
|
||||||
rom.write_byte(stat_pc+2, 0xc0) # change to 12 bits (from a0)
|
rom.write_byte(stat_pc+2, 0xc0) # change to 12 bits (from a0)
|
||||||
@@ -994,7 +994,7 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
set_inverted_mode(world, player, rom, inverted_buffer)
|
set_inverted_mode(world, player, rom, inverted_buffer)
|
||||||
|
|
||||||
uncle_location = world.get_location('Link\'s Uncle', player)
|
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']:
|
if uncle_location.item is None or uncle_location.item.name not in ['Master Sword', 'Tempered Sword', 'Fighter Sword', 'Golden Sword', 'Progressive Sword', 'Sword and Shield']:
|
||||||
# disable sword sprite from uncle
|
# disable sword sprite from uncle
|
||||||
rom.write_bytes(0x6D263, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
rom.write_bytes(0x6D263, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||||
rom.write_bytes(0x6D26B, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
rom.write_bytes(0x6D26B, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||||
@@ -1007,6 +1007,10 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
rom.write_bytes(0x6D31B, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
|
rom.write_bytes(0x6D31B, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
|
||||||
rom.write_bytes(0x6D323, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
|
rom.write_bytes(0x6D323, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
|
||||||
|
|
||||||
|
bridge_item = world.get_location("Hobo", player).item
|
||||||
|
if bridge_item is None or not bridge_item.name.startswith("Bottle"):
|
||||||
|
rom.write_bytes(0x1E9C0, [0xFB, 0xFF, 0x03, 0x00, 0xAB, 0x00, 0x00, 0x00])
|
||||||
|
|
||||||
# set light cones
|
# set light cones
|
||||||
if world.dark_rooms[player] == 'no_dark_rooms':
|
if world.dark_rooms[player] == 'no_dark_rooms':
|
||||||
light_cone = 0x20
|
light_cone = 0x20
|
||||||
@@ -1446,9 +1450,14 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
"bee": 0x10,
|
"bee": 0x10,
|
||||||
"somaria": 0x11,
|
"somaria": 0x11,
|
||||||
"byrna": 0x12,
|
"byrna": 0x12,
|
||||||
"none": 0xFF,
|
"none": 0x7F,
|
||||||
}
|
}
|
||||||
rom.write_byte(0x18002E, ganon_item_byte[world.ganon_item[player]])
|
ganon_item_value = ganon_item_byte[world.ganon_item[player]]
|
||||||
|
if world.require_ganon_item[player] and world.ganon_item[player] != "none":
|
||||||
|
if world.swords[player] != "swordless" or world.ganon_item[player] not in ["bombos", "ether", "quake"]:
|
||||||
|
ganon_item_value |= 0x80
|
||||||
|
|
||||||
|
rom.write_byte(0x18002E, ganon_item_value)
|
||||||
|
|
||||||
# block HC upstairs doors in rain state in standard mode
|
# block HC upstairs doors in rain state in standard mode
|
||||||
prevent_rain = world.mode[player] == 'standard' and world.shuffle[player] != 'vanilla' and world.logic[player] != 'nologic'
|
prevent_rain = world.mode[player] == 'standard' and world.shuffle[player] != 'vanilla' and world.logic[player] != 'nologic'
|
||||||
@@ -1497,37 +1506,40 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
loot_source = 0x09
|
loot_source = 0x09
|
||||||
if world.prizeshuffle[player] != 'none':
|
if world.prizeshuffle[player] != 'none':
|
||||||
loot_source |= 0x10
|
loot_source |= 0x10
|
||||||
if world.pottery[player] not in ['none', 'cave']:
|
if world.pottery[player] != 'none':
|
||||||
loot_source |= 0x02
|
loot_source |= 0x02
|
||||||
if world.dropshuffle[player] != 'none':
|
if world.dropshuffle[player] != 'none':
|
||||||
loot_source |= 0x04
|
loot_source |= 0x04
|
||||||
rom.write_byte(0x1CFF10, loot_source)
|
rom.write_byte(0x1CFF20, loot_source)
|
||||||
|
|
||||||
if world.loothud[player] == 'never':
|
if world.loothud[player] == 'never':
|
||||||
rom.write_byte(0x1CFF12, 0x00)
|
rom.write_bytes(0x1CFF10, [0x00, 0x00, 0x00, 0x00])
|
||||||
|
rom.write_byte(0x1CFF17, 0x00)
|
||||||
elif world.loothud[player] == 'presence':
|
elif world.loothud[player] == 'presence':
|
||||||
rom.write_byte(0x1CFF12, 0x01)
|
rom.write_bytes(0x1CFF10, [0x01, 0x01, 0x00, 0x00])
|
||||||
rom.write_bytes(0x1CFF0E, [0x01, 0x01])
|
rom.write_byte(0x1CFF17, 0x01)
|
||||||
elif world.loothud[player] == 'value':
|
elif world.loothud[player] == 'value':
|
||||||
rom.write_byte(0x1CFF12, 0x01)
|
rom.write_bytes(0x1CFF10, [0x03, 0x03, 0x00, 0x00])
|
||||||
rom.write_bytes(0x1CFF0E, [0xFF, 0xFF])
|
rom.write_byte(0x1CFF17, 0x01)
|
||||||
elif world.loothud[player] == 'dungeon_value':
|
elif world.loothud[player] == 'dungeon_value':
|
||||||
rom.write_byte(0x1CFF12, 0x01)
|
rom.write_bytes(0x1CFF10, [0x01, 0x03, 0x00, 0x00])
|
||||||
rom.write_bytes(0x1CFF0E, [0xFF, 0x01])
|
rom.write_byte(0x1CFF17, 0x01)
|
||||||
|
elif world.loothud[player] == 'cave_value':
|
||||||
|
rom.write_bytes(0x1CFF10, [0x03, 0x01, 0x00, 0x00])
|
||||||
|
rom.write_byte(0x1CFF17, 0x01)
|
||||||
|
|
||||||
if world.showloot[player] == 'never':
|
if world.showloot[player] == 'never':
|
||||||
rom.write_bytes(0x1CFF08, [0x00, 0x00, 0x00, 0x00])
|
rom.write_bytes(0x1CFF08, [0x00, 0x00, 0x00, 0x00])
|
||||||
rom.write_byte(0x1CFF11, 0x00)
|
rom.write_byte(0x1CFF0F, 0x00)
|
||||||
rom.write_byte(0x1CFF12, 0x00) # turn off hud icon too just to be safe
|
|
||||||
elif world.showloot[player] == 'presence':
|
elif world.showloot[player] == 'presence':
|
||||||
rom.write_bytes(0x1CFF08, [0x01, 0x00, 0x00, 0x00])
|
rom.write_bytes(0x1CFF08, [0x01, 0x00, 0x00, 0x00])
|
||||||
rom.write_byte(0x1CFF11, 0x00)
|
rom.write_byte(0x1CFF0F, 0x01)
|
||||||
elif world.showloot[player] == 'compass':
|
elif world.showloot[player] == 'compass':
|
||||||
rom.write_bytes(0x1CFF08, [0x01, 0x00, 0x02, 0x00])
|
rom.write_bytes(0x1CFF08, [0x02, 0x00, 0x03, 0x00])
|
||||||
rom.write_byte(0x1CFF11, 0x01)
|
rom.write_byte(0x1CFF0F, 0x01)
|
||||||
elif world.showloot[player] == 'always':
|
elif world.showloot[player] == 'always':
|
||||||
rom.write_bytes(0x1CFF08, [0x02, 0x00, 0x00, 0x00])
|
rom.write_bytes(0x1CFF08, [0x03, 0x00, 0x00, 0x00])
|
||||||
rom.write_byte(0x1CFF11, 0x00)
|
rom.write_byte(0x1CFF0F, 0x01)
|
||||||
|
|
||||||
if world.showmap[player] == 'visited':
|
if world.showmap[player] == 'visited':
|
||||||
rom.write_bytes(0x1CFF00, [0x01, 0x00, 0x00, 0x05])
|
rom.write_bytes(0x1CFF00, [0x01, 0x00, 0x00, 0x05])
|
||||||
@@ -1541,7 +1553,7 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
rom.write_byte(loot_icons + 0x52, 0x0B) # bomb bag is major
|
rom.write_byte(loot_icons + 0x52, 0x0B) # bomb bag is major
|
||||||
|
|
||||||
triforce_piece_ids = [0x6B, 0x6C]
|
triforce_piece_ids = [0x6B, 0x6C]
|
||||||
if world.treasure_hunt_count[player] > 20:
|
if world.treasure_hunt_count[player] > 100:
|
||||||
for triforce_piece_id in triforce_piece_ids:
|
for triforce_piece_id in triforce_piece_ids:
|
||||||
rom.write_byte(loot_icons + triforce_piece_id, 0x04)
|
rom.write_byte(loot_icons + triforce_piece_id, 0x04)
|
||||||
|
|
||||||
@@ -1779,14 +1791,15 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
rom.write_byte(0x180358, 0x01 if glitches_enabled else 0x00)
|
rom.write_byte(0x180358, 0x01 if glitches_enabled else 0x00)
|
||||||
rom.write_byte(0x18008B, 0x01 if glitches_enabled else 0x00)
|
rom.write_byte(0x18008B, 0x01 if glitches_enabled else 0x00)
|
||||||
|
|
||||||
# remove shield from uncle
|
if uncle_location.item is None or uncle_location.item.name not in ['Blue Shield', 'Red Shield', 'Mirror Shield', 'Progressive Shield', 'Sword and Shield']:
|
||||||
rom.write_bytes(0x6D253, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
# remove shield from uncle
|
||||||
rom.write_bytes(0x6D25B, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
rom.write_bytes(0x6D253, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||||
rom.write_bytes(0x6D283, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
rom.write_bytes(0x6D25B, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||||
rom.write_bytes(0x6D28B, [0x00, 0x00, 0xf7, 0xff, 0x00, 0x0E])
|
rom.write_bytes(0x6D283, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||||
rom.write_bytes(0x6D2CB, [0x00, 0x00, 0xf6, 0xff, 0x02, 0x0E])
|
rom.write_bytes(0x6D28B, [0x00, 0x00, 0xf7, 0xff, 0x00, 0x0E])
|
||||||
rom.write_bytes(0x6D2FB, [0x00, 0x00, 0xf7, 0xff, 0x02, 0x0E])
|
rom.write_bytes(0x6D2CB, [0x00, 0x00, 0xf6, 0xff, 0x02, 0x0E])
|
||||||
rom.write_bytes(0x6D313, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
|
rom.write_bytes(0x6D2FB, [0x00, 0x00, 0xf7, 0xff, 0x02, 0x0E])
|
||||||
|
rom.write_bytes(0x6D313, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
|
||||||
|
|
||||||
write_int16(rom, 0x180183, 0) # Escape fill rupee bow
|
write_int16(rom, 0x180183, 0) # Escape fill rupee bow
|
||||||
# Uncle / Zelda / Mantle respawn refills (magic, bombs, arrows)
|
# Uncle / Zelda / Mantle respawn refills (magic, bombs, arrows)
|
||||||
@@ -1931,7 +1944,7 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
|
|
||||||
write_enemizer_tweaks(rom, world, player)
|
write_enemizer_tweaks(rom, world, player)
|
||||||
randomize_damage_table(rom, world, player)
|
randomize_damage_table(rom, world, player)
|
||||||
write_strings(rom, world, player, team)
|
write_strings(rom, world, player, team, is_mystery)
|
||||||
|
|
||||||
# write initial sram
|
# write initial sram
|
||||||
rom.write_initial_sram()
|
rom.write_initial_sram()
|
||||||
@@ -2013,7 +2026,15 @@ def write_custom_shops(rom, world, player):
|
|||||||
if world.shopsanity[player] or shop.type == ShopType.TakeAny:
|
if world.shopsanity[player] or shop.type == ShopType.TakeAny:
|
||||||
rom.write_byte(0x186E40 + shop.sram_address + index, 1)
|
rom.write_byte(0x186E40 + shop.sram_address + index, 1)
|
||||||
if world.shopsanity[player] and shop.region.name in shop_to_location_table:
|
if world.shopsanity[player] and shop.region.name in shop_to_location_table:
|
||||||
loc_item = world.get_location(shop_to_location_table[shop.region.name][index], player).item
|
if shop.region.name == "Capacity Upgrade" and shop.item_count == 3:
|
||||||
|
if index == 1:
|
||||||
|
loc_item = ItemFactory(item['item'], player)
|
||||||
|
else:
|
||||||
|
if index == 2:
|
||||||
|
index = 1
|
||||||
|
loc_item = world.get_location(shop_to_location_table[shop.region.name][index], player).item
|
||||||
|
else:
|
||||||
|
loc_item = world.get_location(shop_to_location_table[shop.region.name][index], player).item
|
||||||
elif world.shopsanity[player] and shop.region.name in retro_shops:
|
elif world.shopsanity[player] and shop.region.name in retro_shops:
|
||||||
loc_item = world.get_location(retro_shops[shop.region.name][index], player).item
|
loc_item = world.get_location(retro_shops[shop.region.name][index], player).item
|
||||||
else:
|
else:
|
||||||
@@ -2029,7 +2050,7 @@ def write_custom_shops(rom, world, player):
|
|||||||
replace_price = int16_as_bytes(item['replacement_price'])
|
replace_price = int16_as_bytes(item['replacement_price'])
|
||||||
item_max = item['max']
|
item_max = item['max']
|
||||||
item_player = 0 if item['player'] == player else item['player']
|
item_player = 0 if item['player'] == player else item['player']
|
||||||
item_data = [shop_id, item_id] + price + [item_max, replace] + replace_price + [item_player]
|
item_data = [shop_id, item_id] + price + [item_max, replace] + replace_price + [item_player]
|
||||||
items_data.extend(item_data)
|
items_data.extend(item_data)
|
||||||
|
|
||||||
rom.write_bytes(0x184800, shop_data)
|
rom.write_bytes(0x184800, shop_data)
|
||||||
@@ -2074,6 +2095,49 @@ def hud_format_text(text):
|
|||||||
output += b'\x7f\x00'
|
output += b'\x7f\x00'
|
||||||
return output[:32]
|
return output[:32]
|
||||||
|
|
||||||
|
def read_bytes(f, count):
|
||||||
|
values = f.read(count)
|
||||||
|
if len(values) < count:
|
||||||
|
raise EOFError
|
||||||
|
return values
|
||||||
|
|
||||||
|
def apply_rom_patches(rom, patches):
|
||||||
|
for patch in patches:
|
||||||
|
if not os.path.exists(f"patches/{patch}.ips"):
|
||||||
|
logging.getLogger('').warning("Patch %s not found -- skipping", patch)
|
||||||
|
continue
|
||||||
|
|
||||||
|
with open(f"patches/{patch}.ips", "rb") as f:
|
||||||
|
byte_changes = []
|
||||||
|
try:
|
||||||
|
header = read_bytes(f, 5)
|
||||||
|
if header != b"PATCH":
|
||||||
|
logging.getLogger('').warning("Patch %s invalid -- skipping", patch)
|
||||||
|
continue
|
||||||
|
|
||||||
|
while True:
|
||||||
|
address = read_bytes(f, 3)
|
||||||
|
if address == b"EOF":
|
||||||
|
break
|
||||||
|
|
||||||
|
address = int.from_bytes(address, byteorder="big")
|
||||||
|
length = int.from_bytes(read_bytes(f, 2), byteorder="big")
|
||||||
|
|
||||||
|
if length > 0:
|
||||||
|
byte_changes.append((address, list(f.read(length))))
|
||||||
|
else:
|
||||||
|
length = int.from_bytes(read_bytes(f, 2), byteorder="big")
|
||||||
|
value = read_bytes(f, 1)
|
||||||
|
byte_changes.append((address, length * list(value)))
|
||||||
|
|
||||||
|
for address, values in byte_changes:
|
||||||
|
rom.write_bytes(address, values)
|
||||||
|
|
||||||
|
logging.getLogger("").info("Patch %s applied successfully", patch)
|
||||||
|
|
||||||
|
except EOFError:
|
||||||
|
logging.getLogger('').warning("Patch %s invalid -- skipping", patch)
|
||||||
|
continue
|
||||||
|
|
||||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, triforce_gfx,
|
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, triforce_gfx,
|
||||||
ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx,
|
ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx,
|
||||||
@@ -2390,7 +2454,7 @@ def write_string_to_rom(rom, target, string):
|
|||||||
rom.write_bytes(address, MultiByteTextMapper.convert(string, maxbytes))
|
rom.write_bytes(address, MultiByteTextMapper.convert(string, maxbytes))
|
||||||
|
|
||||||
|
|
||||||
def write_strings(rom, world, player, team):
|
def write_strings(rom, world, player, team, is_mystery=False):
|
||||||
tt = TextTable()
|
tt = TextTable()
|
||||||
tt.removeUnwantedText()
|
tt.removeUnwantedText()
|
||||||
if world.shuffle[player] != 'vanilla':
|
if world.shuffle[player] != 'vanilla':
|
||||||
@@ -2441,6 +2505,15 @@ def write_strings(rom, world, player, team):
|
|||||||
|
|
||||||
# For hints, first we write hints about entrances, some from the inconvenient list others from all reasonable entrances.
|
# For hints, first we write hints about entrances, some from the inconvenient list others from all reasonable entrances.
|
||||||
if world.hints[player]:
|
if world.hints[player]:
|
||||||
|
zoraitem = world.get_location('King Zora', player).item.hint_text
|
||||||
|
if len(zoraitem) <= 15:
|
||||||
|
tt['zora_meeting'] = f"Whaddaya want?\n ≥ {zoraitem.title()}\n Nothin'{{CHOICE}}"
|
||||||
|
else:
|
||||||
|
tt['zora_meeting'] = f"Do you want {zoraitem}?\n ≥ I'll pay\n No thanks{{CHOICE}}"
|
||||||
|
|
||||||
|
bottleitem = world.get_location('Bottle Merchant', player).item.hint_text
|
||||||
|
tt['bottle_vendor_choice'] = f"Do you want {bottleitem}?\n ≥ I'll take it\n No thanks!\n{{CHOICE}}"
|
||||||
|
|
||||||
tt['sign_north_of_links_house'] = '> Randomizer The telepathic tiles can have hints!'
|
tt['sign_north_of_links_house'] = '> Randomizer The telepathic tiles can have hints!'
|
||||||
hint_locations = HintLocations.copy()
|
hint_locations = HintLocations.copy()
|
||||||
random.shuffle(hint_locations)
|
random.shuffle(hint_locations)
|
||||||
@@ -2852,7 +2925,7 @@ def write_strings(rom, world, player, team):
|
|||||||
tt['sign_ganon'] = 'Ganon only respects those who have done everything.'
|
tt['sign_ganon'] = 'Ganon only respects those who have done everything.'
|
||||||
tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)]
|
tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)]
|
||||||
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
|
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
|
||||||
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
|
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI cannot die!'
|
||||||
|
|
||||||
def get_custom_goal_text(type):
|
def get_custom_goal_text(type):
|
||||||
goal_text = world.custom_goals[player][type]['goaltext']
|
goal_text = world.custom_goals[player][type]['goaltext']
|
||||||
@@ -2871,7 +2944,13 @@ def write_strings(rom, world, player, team):
|
|||||||
if world.custom_goals[player]['murahgoal'] and 'goaltext' in world.custom_goals[player]['murahgoal']:
|
if world.custom_goals[player]['murahgoal'] and 'goaltext' in world.custom_goals[player]['murahgoal']:
|
||||||
tt['murahdahla'] = get_custom_goal_text('murahgoal')
|
tt['murahdahla'] = get_custom_goal_text('murahgoal')
|
||||||
|
|
||||||
tt['kakariko_tavern_fisherman'] = TavernMan_texts[random.randint(0, len(TavernMan_texts) - 1)]
|
tavern_texts = random.sample(TavernMan_texts, 5)
|
||||||
|
|
||||||
|
tt['tavern_old_man_awake'] = tavern_texts.pop()
|
||||||
|
tt['tavern_old_man_unactivated_flute'] = tavern_texts.pop()
|
||||||
|
tt['tavern_old_man_know_tree_unactivated_flute'] = tavern_texts.pop()
|
||||||
|
tt['tavern_old_man_have_flute'] = tavern_texts.pop()
|
||||||
|
tt['kakariko_tavern_fisherman'] = tavern_texts.pop()
|
||||||
|
|
||||||
pedestalitem = world.get_location('Master Sword Pedestal', player).item
|
pedestalitem = world.get_location('Master Sword Pedestal', player).item
|
||||||
pedestal_text = 'Some Hot Air' if pedestalitem is None else hint_text(pedestalitem, True) if pedestalitem.pedestal_hint_text is not None else 'Unknown Item'
|
pedestal_text = 'Some Hot Air' if pedestalitem is None else hint_text(pedestalitem, True) if pedestalitem.pedestal_hint_text is not None else 'Unknown Item'
|
||||||
@@ -2905,7 +2984,22 @@ def write_strings(rom, world, player, team):
|
|||||||
sanc_text = "Dark Chapel"
|
sanc_text = "Dark Chapel"
|
||||||
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s " + lh_text + "\n " + sanc_text + "\n{CHOICE3}"
|
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s " + lh_text + "\n " + sanc_text + "\n{CHOICE3}"
|
||||||
tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s " + lh_text + "\n " + sanc_text + "\n Mountain Cave\n{CHOICE2}"
|
tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s " + lh_text + "\n " + sanc_text + "\n Mountain Cave\n{CHOICE2}"
|
||||||
if world.mode[player] == 'inverted':
|
|
||||||
|
if is_mystery:
|
||||||
|
tt['intro_main'] = CompressedTextMapper.convert(
|
||||||
|
"{INTRO}\n Episode III"
|
||||||
|
+ "{PAUSE3}\n A Link to the Past"
|
||||||
|
+ "{PAUSE3}\n Mystery Randomizer"
|
||||||
|
+ "{PAUSE3}\n\n\n"
|
||||||
|
+ "{PAUSE3}\nAfter mostly disregarding what happened in the first two games,"
|
||||||
|
+ "{PAUSE3}\nLink awakens to a massive mystery."
|
||||||
|
+ "{PAUSE3}\nHe doesn't know why he's here, or what he must do."
|
||||||
|
+ "{PAUSE3} {CHANGEPIC}\nGanon has moved around all the items in Hyrule."
|
||||||
|
+ "{PAUSE7}\nYou will have to find all the items necessary to achieve your goal."
|
||||||
|
+ "{PAUSE7}\nThis is your chance to be a hero."
|
||||||
|
+ "{PAUSE3} {CHANGEPIC}\nGood luck out there, and try not to die."
|
||||||
|
+ "{PAUSE9} {CHANGEPIC}", False)
|
||||||
|
elif world.mode[player] == 'inverted':
|
||||||
tt['intro_main'] = CompressedTextMapper.convert(
|
tt['intro_main'] = CompressedTextMapper.convert(
|
||||||
"{INTRO}\n Episode III"
|
"{INTRO}\n Episode III"
|
||||||
+ "{PAUSE3}\n A Link to the Past"
|
+ "{PAUSE3}\n A Link to the Past"
|
||||||
@@ -2919,6 +3013,7 @@ def write_strings(rom, world, player, team):
|
|||||||
+ "{PAUSE7}\nThis is your chance to be a hero."
|
+ "{PAUSE7}\nThis is your chance to be a hero."
|
||||||
+ "{PAUSE3} {CHANGEPIC}\nYou must get the 7 crystals to beat Ganon."
|
+ "{PAUSE3} {CHANGEPIC}\nYou must get the 7 crystals to beat Ganon."
|
||||||
+ "{PAUSE9} {CHANGEPIC}", False)
|
+ "{PAUSE9} {CHANGEPIC}", False)
|
||||||
|
|
||||||
rom.write_bytes(0xE0000, tt.getBytes())
|
rom.write_bytes(0xE0000, tt.getBytes())
|
||||||
|
|
||||||
credits = Credits()
|
credits = Credits()
|
||||||
|
|||||||
14
Rules.py
14
Rules.py
@@ -505,7 +505,7 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_entrance('Skull Woods Rock (West)', player), lambda state: state.can_lift_rocks(player))
|
set_rule(world.get_entrance('Skull Woods Rock (West)', player), lambda state: state.can_lift_rocks(player))
|
||||||
set_rule(world.get_entrance('Skull Woods Rock (East)', player), lambda state: state.can_lift_rocks(player))
|
set_rule(world.get_entrance('Skull Woods Rock (East)', player), lambda state: state.can_lift_rocks(player))
|
||||||
# this more like an ohko rule - dependent on bird being present too - so enemizer could turn this off?
|
# this more like an ohko rule - dependent on bird being present too - so enemizer could turn this off?
|
||||||
set_rule(world.get_entrance('Bumper Cave Ledge Drop', player), lambda state: world.can_take_damage or state.has('Cape', player) or state.has('Cane of Byrna', player) or state.has_sword(player))
|
set_rule(world.get_entrance('Bumper Cave Ledge Drop', player), lambda state: state.has('Cape', player) or state.has('Cane of Byrna', player) or state.has_sword(player))
|
||||||
set_rule(world.get_entrance('Bumper Cave Rock (Outer)', player), lambda state: state.can_lift_rocks(player))
|
set_rule(world.get_entrance('Bumper Cave Rock (Outer)', player), lambda state: state.can_lift_rocks(player))
|
||||||
set_rule(world.get_entrance('Bumper Cave Rock (Inner)', player), lambda state: state.can_lift_rocks(player))
|
set_rule(world.get_entrance('Bumper Cave Rock (Inner)', player), lambda state: state.can_lift_rocks(player))
|
||||||
set_rule(world.get_entrance('Skull Woods Pass Rock (North)', player), lambda state: state.can_lift_heavy_rocks(player))
|
set_rule(world.get_entrance('Skull Woods Pass Rock (North)', player), lambda state: state.can_lift_heavy_rocks(player))
|
||||||
@@ -1026,10 +1026,11 @@ def global_rules(world, player):
|
|||||||
world.get_location('Ganon', player),
|
world.get_location('Ganon', player),
|
||||||
lambda state: state.has_beam_sword(player)
|
lambda state: state.has_beam_sword(player)
|
||||||
and state.has_fire_source(player)
|
and state.has_fire_source(player)
|
||||||
and (state.has('Tempered Sword', player) or state.has('Golden Sword', player)
|
and (state.can_hit_stunned_ganon(player) or (
|
||||||
or state.can_hit_stunned_ganon(player)
|
not world.require_ganon_item[player] and (
|
||||||
or state.has('Lamp', player)
|
state.has('Tempered Sword', player) or state.has('Golden Sword', player)
|
||||||
or state.can_extend_magic(player, 12))) # need to light torch a sufficient amount of times
|
or state.has('Lamp', player)
|
||||||
|
or state.can_extend_magic(player, 12))))) # need to light torch a sufficient amount of times
|
||||||
|
|
||||||
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop
|
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop
|
||||||
|
|
||||||
@@ -1404,8 +1405,7 @@ def ow_bunny_rules(world, player):
|
|||||||
add_bunny_rule(world.get_entrance('Skull Woods Forgotten Bush (East)', player), player)
|
add_bunny_rule(world.get_entrance('Skull Woods Forgotten Bush (East)', player), player)
|
||||||
add_bunny_rule(world.get_entrance('Skull Woods Second Section Hole', player), player)
|
add_bunny_rule(world.get_entrance('Skull Woods Second Section Hole', player), player)
|
||||||
add_bunny_rule(world.get_entrance('East Dark Death Mountain Bushes', player), player)
|
add_bunny_rule(world.get_entrance('East Dark Death Mountain Bushes', player), player)
|
||||||
if not world.can_take_damage:
|
add_bunny_rule(world.get_entrance('Bumper Cave Ledge Drop', player), player)
|
||||||
add_bunny_rule(world.get_entrance('Bumper Cave Ledge Drop', player), player)
|
|
||||||
add_bunny_rule(world.get_entrance('Bumper Cave Rock (Outer)', player), player)
|
add_bunny_rule(world.get_entrance('Bumper Cave Rock (Outer)', player), player)
|
||||||
add_bunny_rule(world.get_entrance('Bumper Cave Rock (Inner)', player), player)
|
add_bunny_rule(world.get_entrance('Bumper Cave Rock (Inner)', player), player)
|
||||||
add_bunny_rule(world.get_entrance('Skull Woods Pass Bush Row (West)', player), player)
|
add_bunny_rule(world.get_entrance('Skull Woods Pass Bush Row (West)', player), player)
|
||||||
|
|||||||
221
Text.py
221
Text.py
@@ -50,18 +50,18 @@ Uncle_texts = [
|
|||||||
"Don't worry.\nI got this\ncovered.",
|
"Don't worry.\nI got this\ncovered.",
|
||||||
"Race you to\nthe castle!",
|
"Race you to\nthe castle!",
|
||||||
"\n Hi",
|
"\n Hi",
|
||||||
"I'M JUST GOING\nOUT FOR A\nPACK OF SMOKES",
|
"I'm just going\nout for a\npack of smokes.",
|
||||||
"It's dangerous\nto go alone.\nSee ya!",
|
"It's dangerous\nto go alone.\nSee ya!",
|
||||||
"ARE YOU A BAD\nENOUGH DUDE TO\nRESCUE ZELDA?",
|
"Are you a bad\nenough dude to\nrescue Zelda?",
|
||||||
"\n\n I AM ERROR",
|
"\n\n I AM ERROR",
|
||||||
"This seed is\nsub 2 hours,\nguaranteed.",
|
"This seed is\nsub 2 hours,\nguaranteed.",
|
||||||
"The chest is\na secret to\neverybody.",
|
"The chest is\na secret to\neverybody.",
|
||||||
"I'm off to\nfind the\nwind fish.",
|
"I'm off to\nfind the\nwind fish.",
|
||||||
"The shortcut\nto Ganon\nis this way!",
|
"The shortcut\nto Ganon\nis this way!",
|
||||||
"THE MOON IS\nCRASHING! RUN\nFOR YOUR LIFE!",
|
"The moon is\ncrashing! Run\nfor your life!",
|
||||||
"Time to fight\nhe who must\nnot be named.",
|
"Time to fight\nhe who must\nnot be named.",
|
||||||
"RED MAIL\nIS FOR\nCOWARDS.",
|
"Red mail\nis for\ncowards.",
|
||||||
"HEY!\n\nLISTEN!",
|
"Hey!\n\nListen!",
|
||||||
"Well\nexcuuuuuse me,\nprincess!",
|
"Well\nexcuuuuuse me,\nprincess!",
|
||||||
"5,000 Rupee\nreward for >\nYou're boned.",
|
"5,000 Rupee\nreward for >\nYou're boned.",
|
||||||
"Welcome to\nStoops Lonk's\nHoose",
|
"Welcome to\nStoops Lonk's\nHoose",
|
||||||
@@ -230,97 +230,92 @@ Ganon1_texts = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
Ganon_Phase_3_No_Silvers_texts = [
|
Ganon_Phase_3_No_Silvers_texts = [
|
||||||
"Did you find\nthe arrows on\nPlanet Zebes?",
|
"Did you find\nthe arrows\non Planet Zebes?",
|
||||||
"Did you find\nthe arrows?\nI think not.",
|
"Did you find\nthe arrows?\nI think not.",
|
||||||
"Silver arrows?\nI have never\nheard of them",
|
"Silver arrows?\nI have never\nheard of them.",
|
||||||
"Did you find\nthe arrows on\nThe Moon?",
|
"Did you find\nthe arrows on\nThe Moon?",
|
||||||
"Did you find\nthe arrows\nIn dev null?",
|
"Did you find\nthe arrows\nin /dev/null?",
|
||||||
"I have sold\nthe arrows for\na green big 20",
|
"I have sold\nthe arrows for\na green big 20.",
|
||||||
"Did you find\nthe arrows in\nCount Dracula?",
|
"Did you find\nthe arrows in\nCount Dracula?",
|
||||||
"Error 404\nSilver arrows\nnot found.",
|
" Error 404\nSilver Arrows\n Not Found",
|
||||||
"No arrows for\nyou today.\nSorry.",
|
"No arrows\nfor you today.\nSorry.",
|
||||||
"No arrows?\nCheck your\njunk mail."
|
"No arrows?\nCheck your\njunk mail."
|
||||||
"Did you find\nthe arrows in\nJabu's belly?",
|
"Did you find\nthe arrows\nin Jabu's belly?",
|
||||||
"Silver is not\nan appropriate\narrow material",
|
"Silver is not\nan appropriate\narrow material.",
|
||||||
"Did you find\nthe arrows in\nNarnia?",
|
"Did you find\nthe arrows\nin nNarnia?",
|
||||||
"DID YOU FIND\nTHE ARROWS IN\nKEFKA'S TOWER",
|
"Did you find\nthe arrows\nin nKefka's Tower.",
|
||||||
"Did you find\nthe arrows in\nyour Recycle Bin?",
|
"Did you find\nthe arrows\nin nyour Recycle Bin?",
|
||||||
"Silver Arrows?\n\nLUL",
|
"Silver Arrows?\n\nLUL",
|
||||||
"Imagine\nfinding the\narrows",
|
"\nImagine finding\nthe arrows.",
|
||||||
"Did you find\nsilvers in\nscenic Ohio?",
|
"Did you find\nthe arrows\nin scenic Ohio?",
|
||||||
"Did you find\nthe arrows in\n*mumblemumble*",
|
"Did you find\nthe arrows\nin •mumblemumble•",
|
||||||
"Did you find\nthe arrows in\nthe hourglass?",
|
"Did you find\nthe arrows\nin the hourglass?",
|
||||||
"Silver Arrows\nare so v30",
|
"\nSilver Arrows\nare so main branch.",
|
||||||
"OH, NO, THEY\nACTUALLY SAID\nSILVER MARROW",
|
"Did you find\nthe arrows\nin World 4-2?",
|
||||||
"SURELY THE\nLEFTMOST TILES\nWILL STAY UP",
|
"Did you find\nthe arrows\nin Ghanti's ears?",
|
||||||
"Did you find\nthe arrows in\nWorld 4-2?",
|
|
||||||
"SILLY HERO,\nSILVER IS FOR\nWEREWOLVES!",
|
|
||||||
"Did you find\nthe silvers in\nGanti's ears",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
Ganon_Phase_3_No_Weakness_texts = [
|
Ganon_Phase_3_No_Weakness_texts = [
|
||||||
"Error 404\nWeakness\nnot found.",
|
"\n Error 404\nWeakness Not Found",
|
||||||
"No weakness\nfor you today.\nSorry",
|
"No weakness\nfor you today.\nSorry.",
|
||||||
"Careful, all\nthat spinning\nmakes me dizzy",
|
"Careful, all\nthat spinning\nmakes me dizzy.",
|
||||||
"Are you ready\nTo spin\nTo win?",
|
"Are you ready\nto spin\nto win?",
|
||||||
"\nSpin To Win!\n",
|
"\n Spin To Win!\n",
|
||||||
"SURELY THE\nLEFTMOST TILES\nWILL STAY UP",
|
"Surely the\nleftmost tiles\nwill stay up!",
|
||||||
"You Spin Me\nRight Round\nLike A Record",
|
"You spin me\nright round\nlike a record.",
|
||||||
"SILLY HERO,\nSILVER IS FOR\nWEREWOLVES!",
|
"Oh, no, they\nactually said\nsilver •marrow•.",
|
||||||
|
"Silly hero,\nsilver is for\nwerewolves!",
|
||||||
]
|
]
|
||||||
|
|
||||||
TavernMan_texts = [
|
TavernMan_texts = [
|
||||||
"What do you\ncall a blind\ndinosaur?\na doyouthink-\nhesaurus.",
|
"What do you call a blind dinosaur?\n\nA doyouthink-\nhesaurus.",
|
||||||
"A blind man\nwalks into\na bar.\nAnd a table.\nAnd a chair.",
|
"What do ducks like to eat?\n\nQuackers!",
|
||||||
"What do ducks\nlike to eat?\n\nQuackers!",
|
"How do you set up a party in space?\n\nYou planet!",
|
||||||
"How do you\nset up a party\nin space?\n\nYou planet!",
|
"I'm glad I know sign language.\nIt's pretty handy.",
|
||||||
"I'm glad I\nknow sign\nlanguage.\nIt's pretty\nhandy.",
|
"What did Zelda say to Link at a secure door?\n\nTriforce!",
|
||||||
"What did Zelda\nsay to Link at\na secure door?\n\nTRIFORCE!",
|
"I am on a seafood diet.\n\nEvery time I see food, I eat it.",
|
||||||
"I am on a\nseafood diet.\n\nEvery time\nI see food,\nI eat it.",
|
"I've decided to sell my vacuum.\n\nIt was just gathering dust.",
|
||||||
"I've decided\nto sell my\nvacuum.\nIt was just\ngathering\ndust.",
|
"What's the best time to go to the dentist?\n\nTooth-hurtie!",
|
||||||
"What's the best\ntime to go to\nthe dentist?\n\nTooth-hurtie!",
|
"Why can't a bike stand on its own?\n\nIt's two-tired!",
|
||||||
"Why can't a\nbike stand on\nits own?\n\nIt's two-tired!",
|
"If you haven't found Quake yet…\n\nit's not your fault.",
|
||||||
"If you haven't\nfound Quake\nyet…\nit's not your\nfault.",
|
"Why is Peter Pan always flying?\n\nBecause he Neverlands!",
|
||||||
"Why is Peter\nPan always\nflying?\nBecause he\nNeverlands!",
|
"I once told a joke to Armos.\n\nBut he remained stone-faced!",
|
||||||
"I once told a\njoke to Armos.\n\nBut he\nremained\nstone-faced!",
|
"Lanmola was late to our dinner party.\n\nHe just came for the desert",
|
||||||
"Lanmola was\nlate to our\ndinner party.\nHe just came\nfor the desert",
|
"Moldorm is such a prankster.\n\nAnd I fall for it every time!",
|
||||||
"Moldorm is\nsuch a\nprankster.\nAnd I fall for\nit every time!",
|
"Helmasaur is throwing a party.\n\nI hope it's a masquerade!",
|
||||||
"Helmasaur is\nthrowing a\nparty.\nI hope it's\na masquerade!",
|
"I'd like to know Arrghus better.\n\nBut he won't come out of his shell!",
|
||||||
"I'd like to\nknow Arrghus\nbetter.\nBut he won't\ncome out of\nhis shell!",
|
"Mothula didn't have much fun at the party.\n\nHe's immune to spiked punch!",
|
||||||
"Mothula didn't\nhave much fun\nat the party.\nHe's immune to\nspiked punch!",
|
"Kholdstare is afraid to go to the circus.\n\nHungry kids thought he was cotton candy!",
|
||||||
"Don't set me\nup with that\nchick from\nSteve's Town.\n\n\nI'm not\ninterested in\na Blind date!",
|
"I asked who Vitreous' best friends are.\n\nHe said, \"Me, Myself, and Eye!\"",
|
||||||
"Kholdstare is\nafraid to go\nto the circus.\nHungry kids\nthought he was\ncotton candy!",
|
"Trinexx can be a hothead or he can be an ice guy. In the end, he's a solid individual!",
|
||||||
"I asked who\nVitreous' best\nfriends are.\nHe said,\n'Me, Myself,\nand Eye!'",
|
"Bari thought I had moved out of town.\n\nHe was shocked to see me!",
|
||||||
"Trinexx can be\na hothead or\nhe can be an\nice guy. In\nthe end, he's\na solid\nindividual!",
|
"Don't argue with a frozen Deadrock.\n\nHe'll never change his position!",
|
||||||
"Bari thought I\nhad moved out\nof town.\nHe was shocked\nto see me!",
|
"I offered a drink to a self-loathing Ghini.\n\nHe said he didn't like spirits!",
|
||||||
"I can only get\nWeetabix\naround here.\nI have to go\nto Steve's\nTown for Count\nChocula!",
|
"I was supposed to meet Gibdo for lunch.\n\nBut he got wrapped up in something!",
|
||||||
"Don't argue\nwith a frozen\nDeadrock.\nHe'll never\nchange his\nposition!",
|
"Goriya sure has changed in this game.\n\nI hope he comes back around!",
|
||||||
"I offered a\ndrink to a\nself-loathing\nGhini.\nHe said he\ndidn't like\nspirits!",
|
"Hinox actually wants to be a lawyer.\n\nToo bad he bombed the bar exam!",
|
||||||
"I was supposed\nto meet Gibdo\nfor lunch.\nBut he got\nwrapped up in\nsomething!",
|
"I'm surprised Moblin's tusks are so gross.\n\nHe always has his Trident with him!",
|
||||||
"Goriya sure\nhas changed\nin this game.\nI hope he\ncomes back\naround!",
|
"Don't tell Stalfos I'm here.\n\nHe has a bone to pick with me!",
|
||||||
"Hinox actually\nwants to be a\nlawyer.\nToo bad he\nbombed the\nBar exam!",
|
"I got Wallmaster to help me move furniture.\n\nHe was really handy!",
|
||||||
"I'm surprised\nMoblin's tusks\nare so gross.\nHe always has\nhis Trident\nwith him!",
|
"Wizzrobe was just here.\n\nHe always vanishes right before we get the check!",
|
||||||
"Don't tell\nStalfos I'm\nhere.\nHe has a bone\nto pick with\nme!",
|
"I shouldn't have picked up Zora's tab.\n\nThat guy drinks like a fish!",
|
||||||
"I got\nWallmaster to\nhelp me move\nfurniture.\nHe was really\nhandy!",
|
"I was sharing a drink with Poe.\n\nFor no reason, he left in a heartbeat!",
|
||||||
"Wizzrobe was\njust here.\nHe always\nvanishes right\nbefore we get\nthe check!",
|
"Don't trust horsemen on Death Mountain.\n\nThey're Lynel the time!",
|
||||||
"I shouldn't\nhave picked up\nZora's tab.\nThat guy\ndrinks like\na fish!",
|
"Today's special is battered bat.\n\nGot slapped for offering a lady a Keese!",
|
||||||
"I was sharing\na drink with\nPoe.\nFor no reason,\nhe left in a\nheartbeat!",
|
"Don't walk under propellered pineapples.\n\nYou may end up wearing a pee hat!",
|
||||||
"Don't trust\nhorsemen on\nDeath Mountain.\nThey're Lynel\nthe time!",
|
"My girlfriend burrowed under the sand.\n\nSo I decided to Leever!",
|
||||||
"Today's\nspecial is\nbattered bat.\nGot slapped\nfor offering a\nlady a Keese!",
|
"Geldman wants to be a Broadway star.\n\nHe's always practicing Jazz Hands!",
|
||||||
"Don't walk\nunder\npropellered\npineapples.\nYou may end up\nwearing\na pee hat!",
|
"Octoballoon must be mad at me.\n\nHe blows up at the sight of me!",
|
||||||
"My girlfriend\nburrowed under\nthe sand.\nSo I decided\nto Leever!",
|
"Toppo is a total pothead.\n\nHe hates it when you take away his grass",
|
||||||
"Geldman wants\nto be a\nBroadway star.\nHe's always\npracticing\nJazz Hands!",
|
"I lost my shield by that house.\n\nWhy did they put up a Pikit fence?!",
|
||||||
"Octoballoon\nmust be mad\nat me.\nHe blows up\nat the sight\nof me!",
|
"Know that fox in Steve's Town?\n\nHe'll Pikku pockets if you aren't careful",
|
||||||
"Toppo is a\ntotal pothead.\n\nHe hates it\nwhen you take\naway his grass",
|
"Dash through Dark World bushes.\n\nYou'll see Ganon is tryin to Stal you!",
|
||||||
"I lost my\nshield by\nthat house.\nWhy did they\nput up a\nPikit fence?!",
|
"Eyegore!\n\nYou gore!\n\nWe all gore those jerks with arrows!",
|
||||||
"Know that fox\nin Steve's\nTown?\nHe'll Pikku\npockets if you\naren't careful",
|
"I like my whiskey neat.\n\nSome prefer it Octoroks!",
|
||||||
"Dash through\nDark World\nbushes.\nYou'll see\nGanon is tryin\nto Stal you!",
|
"I consoled Freezor over a cup of coffee.\n\nHis problems just seemed to melt away!",
|
||||||
"Eyegore!\n\nYou gore!\nWe all gore\nthose jerks\nwith arrows!",
|
"Magic droplets of water don't shut up.\n\nThey just Kyameron!",
|
||||||
"I like my\nwhiskey neat.\n\nSome prefer it\nOctoroks!",
|
"I bought hot wings for Sluggula.\n\nThey gave him explosive diarrhea!",
|
||||||
"I consoled\nFreezor over a\ncup of coffee.\nHis problems\njust seemed to\nmelt away!",
|
"Hardhat Beatle won't Let It Be?\n\nTell it to Get Back or give it a Ticket to Ride down a hole!",
|
||||||
"Magic droplets\nof water don't\nshut up.\nThey just\nKyameron!",
|
|
||||||
"I bought hot\nwings for\nSluggula.\nThey gave him\nexplosive\ndiarrhea!",
|
|
||||||
"Hardhat Beetle\nwon't\nLet It Be?\nTell it to Get\nBack or give\nit a Ticket to\nRide down\na hole!",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
junk_texts = [
|
junk_texts = [
|
||||||
@@ -349,16 +344,15 @@ junk_texts = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
KingsReturn_texts = [
|
KingsReturn_texts = [
|
||||||
'Who is this even',
|
"Who is this even",
|
||||||
'When did he get here',
|
'When did he get here',
|
||||||
'The Harem'
|
|
||||||
] * 2 + [
|
] * 2 + [
|
||||||
"the return of the king",
|
"The Return of the King",
|
||||||
"fellowship of the ring",
|
"Fellowship of the Ring",
|
||||||
"the two towers",
|
"The Two Towers",
|
||||||
]
|
]
|
||||||
Sanctuary_texts = [
|
Sanctuary_texts = [
|
||||||
'A Priest\'s love'
|
"a priest's love"
|
||||||
] * 2 + [
|
] * 2 + [
|
||||||
"the loyal priest",
|
"the loyal priest",
|
||||||
"read a book",
|
"read a book",
|
||||||
@@ -376,31 +370,30 @@ Sahasrahla_names = [
|
|||||||
|
|
||||||
Kakariko_texts = ["{}'s homecoming"]
|
Kakariko_texts = ["{}'s homecoming"]
|
||||||
Blacksmiths_texts = [
|
Blacksmiths_texts = [
|
||||||
'frogs for bread',
|
"Frogs for bread",
|
||||||
'That\'s not a sword',
|
"That's not a sword",
|
||||||
'The Rupeesmiths'
|
"The rupeesmiths",
|
||||||
] * 1 + [
|
"The dwarven breadsmiths",
|
||||||
"the dwarven breadsmiths"
|
|
||||||
]
|
]
|
||||||
DeathMountain_texts = [
|
DeathMountain_texts = [
|
||||||
"the lost old man",
|
"The lost old man",
|
||||||
"gary the old man",
|
"Gary the old man",
|
||||||
"Your ad here"
|
"Your ad here",
|
||||||
]
|
]
|
||||||
LostWoods_texts = [
|
LostWoods_texts = [
|
||||||
'thieves\' stump',
|
"Thieves' stump",
|
||||||
] * 2 + [
|
"Thieves' stump",
|
||||||
"the forest thief",
|
"The forest thief",
|
||||||
"dancing pickles",
|
"Dancing pickles",
|
||||||
"flying crows",
|
"Flying crows",
|
||||||
]
|
]
|
||||||
WishingWell_texts = [
|
WishingWell_texts = [
|
||||||
"venus. queen of faeries",
|
"Venus, Queen of Faeries",
|
||||||
"Venus was her name",
|
"Venus was her name",
|
||||||
"I'm your Venus",
|
"I'm your Venus",
|
||||||
"Yeah, baby, shes got it",
|
"Yeah, baby, she's got it",
|
||||||
"Venus, I'm your fire",
|
"Venus, I'm your fire",
|
||||||
"Venus, At your desire",
|
"Venus, at your desire",
|
||||||
"Venus Love Chain",
|
"Venus Love Chain",
|
||||||
"Venus Crescent Beam",
|
"Venus Crescent Beam",
|
||||||
]
|
]
|
||||||
@@ -489,7 +482,7 @@ class Credits(object):
|
|||||||
],
|
],
|
||||||
'pedestal': [
|
'pedestal': [
|
||||||
SceneSmallCreditLine(19, 'and the master sword'),
|
SceneSmallCreditLine(19, 'and the master sword'),
|
||||||
SceneSmallAltCreditLine(21, 'sleeps again···'),
|
SceneSmallAltCreditLine(21, 'sleeps again…'),
|
||||||
SceneLargeCreditLine(23, 'Forever!'),
|
SceneLargeCreditLine(23, 'Forever!'),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -833,6 +826,8 @@ class CharTextMapper(object):
|
|||||||
|
|
||||||
class RawMBTextMapper(CharTextMapper):
|
class RawMBTextMapper(CharTextMapper):
|
||||||
char_map = {' ': 0xFF,
|
char_map = {' ': 0xFF,
|
||||||
|
'/': 0x97,
|
||||||
|
'•': 0x98,
|
||||||
'≥': 0x99, # Cursor
|
'≥': 0x99, # Cursor
|
||||||
'『': 0xC4,
|
'『': 0xC4,
|
||||||
'』': 0xC5,
|
'』': 0xC5,
|
||||||
@@ -1316,7 +1311,8 @@ class GoldCreditMapper(CharTextMapper):
|
|||||||
|
|
||||||
class GreenCreditMapper(CharTextMapper):
|
class GreenCreditMapper(CharTextMapper):
|
||||||
char_map = {' ': 0x9F,
|
char_map = {' ': 0x9F,
|
||||||
'.': 0x52,
|
'…': 0xFD,
|
||||||
|
'.': 0xFE,
|
||||||
'·': 0x52}
|
'·': 0x52}
|
||||||
alpha_offset = -0x29
|
alpha_offset = -0x29
|
||||||
alpha_lower_offset = -0x29
|
alpha_lower_offset = -0x29
|
||||||
@@ -1766,7 +1762,7 @@ class TextTable(object):
|
|||||||
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_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_south_of_bumper_cave'] = CompressedTextMapper.convert("\n→ Karkats cave")
|
||||||
text['sign_east_of_pyramid'] = CompressedTextMapper.convert("\n→ Dark Palace")
|
text['sign_east_of_pyramid'] = CompressedTextMapper.convert("\n→ Palace of Darkness")
|
||||||
text['sign_east_of_bomb_shop'] = CompressedTextMapper.convert("\n← Bomb Shoppe")
|
text['sign_east_of_bomb_shop'] = CompressedTextMapper.convert("\n← Bomb Shoppe")
|
||||||
text['sign_east_of_mire'] = CompressedTextMapper.convert("\n← Misery Mire\n no way in.\n no way out.")
|
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!")
|
text['sign_village_of_outcasts'] = CompressedTextMapper.convert("Have a Trulie Awesome Day!")
|
||||||
@@ -1870,7 +1866,7 @@ class TextTable(object):
|
|||||||
# 100
|
# 100
|
||||||
text['dark_sanctuary_no'] = CompressedTextMapper.convert("Then go away!")
|
text['dark_sanctuary_no'] = CompressedTextMapper.convert("Then go away!")
|
||||||
text['dark_sanctuary_hint_1'] = CompressedTextMapper.convert("There is a thief in the desert, he can open creepy chests that follow you. But now that we have that out of the way, Do you like my hair? I've spent eons getting it this way.")
|
text['dark_sanctuary_hint_1'] = CompressedTextMapper.convert("There is a thief in the desert, he can open creepy chests that follow you. But now that we have that out of the way, Do you like my hair? I've spent eons getting it this way.")
|
||||||
text['dark_sanctuary_yes'] = CompressedTextMapper.convert("With Crystals 5&6, you can find a great fairy in the pyramid.\n\nFlomp Flomp, Whizzle Whomp")
|
text['dark_sanctuary_yes'] = CompressedTextMapper.convert("With crystals 5 and 6, you can find a great fairy in the pyramid.\n\nFlomp Flomp, Whizzle Whomp")
|
||||||
text['dark_sanctuary_hint_2'] = CompressedTextMapper.convert(
|
text['dark_sanctuary_hint_2'] = CompressedTextMapper.convert(
|
||||||
"All I can say is that my life is pretty plain,\n"
|
"All I can say is that my life is pretty plain,\n"
|
||||||
+ "I like watchin' the puddles gather rain,\n"
|
+ "I like watchin' the puddles gather rain,\n"
|
||||||
@@ -2058,5 +2054,6 @@ class TextTable(object):
|
|||||||
text['ganon_phase_3_silvers'] = CompressedTextMapper.convert("Oh no! Silver! My one true weakness!")
|
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['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['mastersword_pedestal_goal'] = CompressedTextMapper.convert("To claim thy reward, you must present all 3 Pendants of Virtue.")
|
text['mastersword_pedestal_goal'] = CompressedTextMapper.convert("To claim thy reward, you must present all 3 Pendants of Virtue.")
|
||||||
text['end_pad_data'] = bytearray([0xfb])
|
text['orange_potion_refill'] = CompressedTextMapper.convert("This rare orange potion will give you infinite magic, but only until you die or quit the game.")
|
||||||
|
text['end_pad_data'] = bytearray([0xFB])
|
||||||
text['terminator'] = bytearray([0xFF, 0xFF])
|
text['terminator'] = bytearray([0xFF, 0xFF])
|
||||||
|
|||||||
Binary file not shown.
BIN
patches/2way_mirror.ips
Normal file
BIN
patches/2way_mirror.ips
Normal file
Binary file not shown.
BIN
patches/all_starting.ips
Normal file
BIN
patches/all_starting.ips
Normal file
Binary file not shown.
BIN
patches/colordorm.ips
Normal file
BIN
patches/colordorm.ips
Normal file
Binary file not shown.
BIN
patches/no_dungeon_item_popups.ips
Normal file
BIN
patches/no_dungeon_item_popups.ips
Normal file
Binary file not shown.
BIN
patches/no_escape_assist.ips
Normal file
BIN
patches/no_escape_assist.ips
Normal file
Binary file not shown.
BIN
patches/pod_key_swap.ips
Normal file
BIN
patches/pod_key_swap.ips
Normal file
Binary file not shown.
BIN
patches/quiet_zora.ips
Normal file
BIN
patches/quiet_zora.ips
Normal file
Binary file not shown.
@@ -378,6 +378,10 @@
|
|||||||
"none"
|
"none"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"require_ganon_item": {
|
||||||
|
"action": "store_true",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
"beemizer": {
|
"beemizer": {
|
||||||
"choices": [
|
"choices": [
|
||||||
"4", "3", "2", "1", "0"
|
"4", "3", "2", "1", "0"
|
||||||
@@ -491,7 +495,8 @@
|
|||||||
"never",
|
"never",
|
||||||
"presence",
|
"presence",
|
||||||
"value",
|
"value",
|
||||||
"dungeon_value"
|
"dungeon_value",
|
||||||
|
"cave_value"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"showmap": {
|
"showmap": {
|
||||||
@@ -754,6 +759,14 @@
|
|||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
},
|
||||||
"money_balance": {},
|
"money_balance": {},
|
||||||
|
"patches": {
|
||||||
|
"type": "str",
|
||||||
|
"help": "suppress"
|
||||||
|
},
|
||||||
|
"orange_potion": {
|
||||||
|
"action": "store_true",
|
||||||
|
"help": "suppress"
|
||||||
|
},
|
||||||
"settingsonload": {
|
"settingsonload": {
|
||||||
"choices": [
|
"choices": [
|
||||||
"default",
|
"default",
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ UwGeneralDeny:
|
|||||||
- [0x00b0, 7, [ "StalfosKnight", "Blob", "Stal", "Wizzrobe"]] # blocked, but Geldmen are probably okay
|
- [0x00b0, 7, [ "StalfosKnight", "Blob", "Stal", "Wizzrobe"]] # blocked, but Geldmen are probably okay
|
||||||
- [0x00b0, 8, [ "StalfosKnight", "Blob", "Stal", "Wizzrobe"]] # blocked, but Geldmen are probably okay
|
- [0x00b0, 8, [ "StalfosKnight", "Blob", "Stal", "Wizzrobe"]] # blocked, but Geldmen are probably okay
|
||||||
- [ 0x00b1, 2, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Misery Mire - Hourglass - Spike Trap 1"
|
- [ 0x00b1, 2, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Misery Mire - Hourglass - Spike Trap 1"
|
||||||
- [ 0x00b1, 3, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Misery Mire - Hourglass - Spike Trap 2"
|
- [ 0x00b1, 3, [ "RollerVerticalUp", "RollerVerticalDown", "Bumper" ] ] #"Misery Mire - Hourglass - Spike Trap 2"
|
||||||
- [0x00b1, 4, ["Bumper", "BigSpike", "AntiFairyCircle", "Statue"]] # Wizzrobe near door
|
- [0x00b1, 4, ["Bumper", "BigSpike", "AntiFairyCircle", "Statue"]] # Wizzrobe near door
|
||||||
- [ 0x00b2, 1, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
- [ 0x00b2, 1, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
||||||
- [ 0x00b2, 3, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
- [ 0x00b2, 3, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
||||||
|
|||||||
Reference in New Issue
Block a user