Merged DR 0.4.0.6
This commit is contained in:
5
CLI.py
5
CLI.py
@@ -74,7 +74,6 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
parser.add_argument('--customitemarray', default={}, help=argparse.SUPPRESS)
|
parser.add_argument('--customitemarray', default={}, help=argparse.SUPPRESS)
|
||||||
|
|
||||||
# included for backwards compatibility
|
# included for backwards compatibility
|
||||||
parser.add_argument('--beemizer', default=defval(settings["beemizer"]), type=lambda value: min(max(int(value), 0), 4))
|
|
||||||
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))
|
||||||
parser.add_argument('--securerandom', default=defval(settings["securerandom"]), action='store_true')
|
parser.add_argument('--securerandom', default=defval(settings["securerandom"]), action='store_true')
|
||||||
parser.add_argument('--teams', default=defval(1), type=lambda value: max(int(value), 1))
|
parser.add_argument('--teams', default=defval(1), type=lambda value: max(int(value), 1))
|
||||||
@@ -181,9 +180,7 @@ def parse_settings():
|
|||||||
"names": "",
|
"names": "",
|
||||||
"securerandom": False,
|
"securerandom": False,
|
||||||
|
|
||||||
# Hints default to TRUE
|
"hints": False,
|
||||||
"hints": True,
|
|
||||||
"no_hints": False,
|
|
||||||
"disablemusic": False,
|
"disablemusic": False,
|
||||||
"quickswap": False,
|
"quickswap": False,
|
||||||
"heartcolor": "red",
|
"heartcolor": "red",
|
||||||
|
|||||||
@@ -443,10 +443,16 @@ def choose_portals(world, player):
|
|||||||
if not hc_south.entranceFlag:
|
if not hc_south.entranceFlag:
|
||||||
world.get_room(0x61, player).delete(6)
|
world.get_room(0x61, player).delete(6)
|
||||||
world.get_room(0x61, player).change(4, DoorKind.NormalLow)
|
world.get_room(0x61, player).change(4, DoorKind.NormalLow)
|
||||||
|
else:
|
||||||
|
world.get_room(0x61, player).change(4, DoorKind.DungeonEntrance)
|
||||||
|
world.get_room(0x61, player).change(6, DoorKind.CaveEntranceLow)
|
||||||
sanctuary_door = world.get_door('Sanctuary S', player)
|
sanctuary_door = world.get_door('Sanctuary S', player)
|
||||||
if not sanctuary_door.entranceFlag:
|
if not sanctuary_door.entranceFlag:
|
||||||
world.get_room(0x12, player).delete(3)
|
world.get_room(0x12, player).delete(3)
|
||||||
world.get_room(0x12, player).change(2, DoorKind.NormalLow)
|
world.get_room(0x12, player).change(2, DoorKind.NormalLow)
|
||||||
|
else:
|
||||||
|
world.get_room(0x12, player).change(2, DoorKind.DungeonEntrance)
|
||||||
|
world.get_room(0x12, player).change(3, DoorKind.CaveEntranceLow)
|
||||||
hera_door = world.get_door('Hera Lobby S', player)
|
hera_door = world.get_door('Hera Lobby S', player)
|
||||||
if not hera_door.entranceFlag:
|
if not hera_door.entranceFlag:
|
||||||
world.get_room(0x77, player).change(0, DoorKind.NormalLow2)
|
world.get_room(0x77, player).change(0, DoorKind.NormalLow2)
|
||||||
@@ -578,7 +584,12 @@ def assign_portal(candidates, possible_portals, world, player):
|
|||||||
world.get_room(old_door.roomIndex, player).change(old_door.doorListPos, old_door_kind)
|
world.get_room(old_door.roomIndex, player).change(old_door.doorListPos, old_door_kind)
|
||||||
portal.change_door(candidate)
|
portal.change_door(candidate)
|
||||||
if candidate.name not in ['Hyrule Castle Lobby S', 'Sanctuary S']:
|
if candidate.name not in ['Hyrule Castle Lobby S', 'Sanctuary S']:
|
||||||
new_door_kind = DoorKind.DungeonEntranceLow if candidate.layer or candidate.pseudo_bg else DoorKind.DungeonEntrance
|
if candidate.name == 'Swamp Hub S':
|
||||||
|
new_door_kind = DoorKind.CaveEntranceLow
|
||||||
|
elif candidate.layer or candidate.pseudo_bg:
|
||||||
|
new_door_kind = DoorKind.DungeonEntranceLow
|
||||||
|
else:
|
||||||
|
new_door_kind = DoorKind.DungeonEntrance
|
||||||
world.get_room(candidate.roomIndex, player).change(candidate.doorListPos, new_door_kind)
|
world.get_room(candidate.roomIndex, player).change(candidate.doorListPos, new_door_kind)
|
||||||
candidate.entranceFlag = True
|
candidate.entranceFlag = True
|
||||||
return candidate, portal
|
return candidate, portal
|
||||||
|
|||||||
4
Doors.py
4
Doors.py
@@ -496,7 +496,7 @@ def create_doors(world, player):
|
|||||||
create_door(player, 'Swamp Hammer Switch SW', Intr).dir(So, 0x37, Left, High).small_key().pos(2),
|
create_door(player, 'Swamp Hammer Switch SW', Intr).dir(So, 0x37, Left, High).small_key().pos(2),
|
||||||
create_door(player, 'Swamp Hammer Switch WN', Nrml).dir(We, 0x37, Top, High).pos(0),
|
create_door(player, 'Swamp Hammer Switch WN', Nrml).dir(We, 0x37, Top, High).pos(0),
|
||||||
create_door(player, 'Swamp Hub ES', Nrml).dir(Ea, 0x36, Bot, High).pos(4),
|
create_door(player, 'Swamp Hub ES', Nrml).dir(Ea, 0x36, Bot, High).pos(4),
|
||||||
create_door(player, 'Swamp Hub S', Nrml).dir(So, 0x36, Mid, High).pos(5), # .portal(Z, 0x22, 1), couldn't figure this out
|
create_door(player, 'Swamp Hub S', Nrml).dir(So, 0x36, Mid, High).pos(5).portal(Z, 0x22, 1),
|
||||||
create_door(player, 'Swamp Hub WS', Nrml).dir(We, 0x36, Bot, High).pos(3),
|
create_door(player, 'Swamp Hub WS', Nrml).dir(We, 0x36, Bot, High).pos(3),
|
||||||
create_door(player, 'Swamp Hub WN', Nrml).dir(We, 0x36, Top, High).small_key().pos(2),
|
create_door(player, 'Swamp Hub WN', Nrml).dir(We, 0x36, Top, High).small_key().pos(2),
|
||||||
create_door(player, 'Swamp Hub Hook Path', Lgcl),
|
create_door(player, 'Swamp Hub Hook Path', Lgcl),
|
||||||
@@ -981,7 +981,7 @@ def create_doors(world, player):
|
|||||||
create_door(player, 'TR Lava Dual Pipes SW', Nrml).dir(So, 0x14, Left, High).pos(4).portal(Z, 0x22),
|
create_door(player, 'TR Lava Dual Pipes SW', Nrml).dir(So, 0x14, Left, High).pos(4).portal(Z, 0x22),
|
||||||
create_door(player, 'TR Lava Island WS', Nrml).dir(We, 0x14, Bot, High).small_key().pos(1),
|
create_door(player, 'TR Lava Island WS', Nrml).dir(We, 0x14, Bot, High).small_key().pos(1),
|
||||||
create_door(player, 'TR Lava Island ES', Nrml).dir(Ea, 0x14, Bot, High).pos(6),
|
create_door(player, 'TR Lava Island ES', Nrml).dir(Ea, 0x14, Bot, High).pos(6),
|
||||||
create_door(player, 'TR Lava Escape SE', Nrml).dir(So, 0x14, Right, High).small_key().pos(0),
|
create_door(player, 'TR Lava Escape SE', Nrml).dir(So, 0x14, Right, High).small_key().pos(0).portal(X, 0x22),
|
||||||
create_door(player, 'TR Lava Escape NW', Nrml).dir(No, 0x14, Left, High).pos(2),
|
create_door(player, 'TR Lava Escape NW', Nrml).dir(No, 0x14, Left, High).pos(2),
|
||||||
create_door(player, 'TR Pokey 2 EN', Nrml).dir(Ea, 0x13, Top, High).pos(1),
|
create_door(player, 'TR Pokey 2 EN', Nrml).dir(Ea, 0x13, Top, High).pos(1),
|
||||||
create_door(player, 'TR Pokey 2 Top to Bottom Barrier - Blue', Lgcl),
|
create_door(player, 'TR Pokey 2 Top to Bottom Barrier - Blue', Lgcl),
|
||||||
|
|||||||
69
ItemList.py
69
ItemList.py
@@ -304,9 +304,17 @@ def generate_itempool(world, player):
|
|||||||
if shop.region.name in shop_to_location_table:
|
if shop.region.name in shop_to_location_table:
|
||||||
for index, slot in enumerate(shop.inventory):
|
for index, slot in enumerate(shop.inventory):
|
||||||
if slot:
|
if slot:
|
||||||
pool.append(slot['item'])
|
item = slot['item']
|
||||||
|
if shop.region.name == 'Capacity Upgrade' and world.difficulty[player] != 'normal':
|
||||||
|
pool.append('Rupees (20)')
|
||||||
|
else:
|
||||||
|
pool.append(item)
|
||||||
|
|
||||||
items = ItemFactory(pool, player)
|
items = ItemFactory(pool, player)
|
||||||
|
if world.shopsanity[player]:
|
||||||
|
for potion in ['Green Potion', 'Blue Potion', 'Red Potion']:
|
||||||
|
p_item = next(item for item in items if item.name == potion and item.player == player)
|
||||||
|
p_item.priority = True # don't beemize one of each potion
|
||||||
|
|
||||||
world.lamps_needed_for_dark_rooms = lamps_needed_for_dark_rooms
|
world.lamps_needed_for_dark_rooms = lamps_needed_for_dark_rooms
|
||||||
|
|
||||||
@@ -338,11 +346,11 @@ def generate_itempool(world, player):
|
|||||||
for hp in adv_heart_pieces:
|
for hp in adv_heart_pieces:
|
||||||
hp.advancement = True
|
hp.advancement = True
|
||||||
|
|
||||||
beeweights = {0: {None: 100},
|
beeweights = {'0': {None: 100},
|
||||||
1: {None: 75, 'trap': 25},
|
'1': {None: 75, 'trap': 25},
|
||||||
2: {None: 40, 'trap': 40, 'bee': 20},
|
'2': {None: 40, 'trap': 40, 'bee': 20},
|
||||||
3: {'trap': 50, 'bee': 50},
|
'3': {'trap': 50, 'bee': 50},
|
||||||
4: {'trap': 100}}
|
'4': {'trap': 100}}
|
||||||
def beemizer(item):
|
def beemizer(item):
|
||||||
if world.beemizer[item.player] and not item.advancement and not item.priority and not item.type:
|
if world.beemizer[item.player] and not item.advancement and not item.priority and not item.type:
|
||||||
choice = random.choices(list(beeweights[world.beemizer[item.player]].keys()), weights=list(beeweights[world.beemizer[item.player]].values()))[0]
|
choice = random.choices(list(beeweights[world.beemizer[item.player]].keys()), weights=list(beeweights[world.beemizer[item.player]].values()))[0]
|
||||||
@@ -553,30 +561,31 @@ def customize_shops(world, player):
|
|||||||
shopkeeper = random.choice([0xC1, 0xA0, 0xE2, 0xE3])
|
shopkeeper = random.choice([0xC1, 0xA0, 0xE2, 0xE3])
|
||||||
shop.shopkeeper_config = shopkeeper
|
shop.shopkeeper_config = shopkeeper
|
||||||
# handle capacity upgrades - randomly choose a bomb bunch or arrow bunch to become capacity upgrades
|
# handle capacity upgrades - randomly choose a bomb bunch or arrow bunch to become capacity upgrades
|
||||||
if not found_bomb_upgrade and len(possible_replacements) > 0:
|
if world.difficulty[player] == 'normal':
|
||||||
choices = []
|
if not found_bomb_upgrade and len(possible_replacements) > 0:
|
||||||
for shop, idx, loc, item in possible_replacements:
|
choices = []
|
||||||
if item.name in ['Bombs (3)', 'Bombs (10)']:
|
for shop, idx, loc, item in possible_replacements:
|
||||||
choices.append((shop, idx, loc, item))
|
if item.name in ['Bombs (3)', 'Bombs (10)']:
|
||||||
if len(choices) > 0:
|
choices.append((shop, idx, loc, item))
|
||||||
shop, idx, loc, item = random.choice(choices)
|
if len(choices) > 0:
|
||||||
upgrade = ItemFactory('Bomb Upgrade (+5)', player)
|
shop, idx, loc, item = random.choice(choices)
|
||||||
shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6,
|
upgrade = ItemFactory('Bomb Upgrade (+5)', player)
|
||||||
item.name, randomize_price(item.price), player=item.player)
|
shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6,
|
||||||
loc.item = upgrade
|
item.name, randomize_price(item.price), player=item.player)
|
||||||
upgrade.location = loc
|
loc.item = upgrade
|
||||||
if not found_arrow_upgrade and len(possible_replacements) > 0:
|
upgrade.location = loc
|
||||||
choices = []
|
if not found_arrow_upgrade and len(possible_replacements) > 0:
|
||||||
for shop, idx, loc, item in possible_replacements:
|
choices = []
|
||||||
if item.name == 'Arrows (10)' or (item.name == 'Single Arrow' and not world.retro[player]):
|
for shop, idx, loc, item in possible_replacements:
|
||||||
choices.append((shop, idx, loc, item))
|
if item.name == 'Arrows (10)' or (item.name == 'Single Arrow' and not world.retro[player]):
|
||||||
if len(choices) > 0:
|
choices.append((shop, idx, loc, item))
|
||||||
shop, idx, loc, item = random.choice(choices)
|
if len(choices) > 0:
|
||||||
upgrade = ItemFactory('Arrow Upgrade (+5)', player)
|
shop, idx, loc, item = random.choice(choices)
|
||||||
shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6,
|
upgrade = ItemFactory('Arrow Upgrade (+5)', player)
|
||||||
item.name, randomize_price(item.price), player=item.player)
|
shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6,
|
||||||
loc.item = upgrade
|
item.name, randomize_price(item.price), player=item.player)
|
||||||
upgrade.location = loc
|
loc.item = upgrade
|
||||||
|
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)
|
||||||
|
|
||||||
|
|||||||
2
Items.py
2
Items.py
@@ -165,7 +165,7 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
|
|||||||
'Map (Ganons Tower)': (False, True, 'Map', 0x72, 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 Ganon\'s Tower'),
|
'Map (Ganons Tower)': (False, True, 'Map', 0x72, 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 Ganon\'s Tower'),
|
||||||
'Small Key (Universal)': (False, True, None, 0xAF, 100, 'A small key for any door', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key'),
|
'Small Key (Universal)': (False, True, None, 0xAF, 100, 'A small key for any door', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key'),
|
||||||
'Nothing': (False, False, None, 0x5A, 1, 'Some Hot Air', 'and the Nothing', 'the zen kid', 'outright theft', 'shroom theft', 'empty boy is bored again', 'nothing'),
|
'Nothing': (False, False, None, 0x5A, 1, 'Some Hot Air', 'and the Nothing', 'the zen kid', 'outright theft', 'shroom theft', 'empty boy is bored again', 'nothing'),
|
||||||
'Bee Trap': (False, False, None, 0xB0, 0, 'We will sting your face a whole lot!', 'and the sting buddies', 'the beekeeper kid', 'insects for sale', 'shroom pollenation', 'bottle boy has mad bees again', 'friendship'),
|
'Bee Trap': (False, False, None, 0xB0, 50, 'We will sting your face a whole lot!', 'and the sting buddies', 'the beekeeper kid', 'insects for sale', 'shroom pollenation', 'bottle boy has mad bees again', 'friendship'),
|
||||||
'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'),
|
||||||
|
|||||||
2
Main.py
2
Main.py
@@ -28,7 +28,7 @@ from Fill import sell_potions, sell_keys, balance_multiworld_progression, balanc
|
|||||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
|
|
||||||
__version__ = '0.4.0.5-u'
|
__version__ = '0.4.0.6-u'
|
||||||
|
|
||||||
|
|
||||||
class EnemizerError(RuntimeError):
|
class EnemizerError(RuntimeError):
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ def roll_settings(weights):
|
|||||||
|
|
||||||
ret.shufflepots = get_choice('pot_shuffle') == 'on'
|
ret.shufflepots = get_choice('pot_shuffle') == 'on'
|
||||||
|
|
||||||
ret.beemizer = int(get_choice('beemizer')) if 'beemizer' in weights else 0
|
ret.beemizer = get_choice('beemizer') if 'beemizer' in weights else '0'
|
||||||
|
|
||||||
inventoryweights = weights.get('startinventory', {})
|
inventoryweights = weights.get('startinventory', {})
|
||||||
startitems = []
|
startitems = []
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# New Features
|
# New Features
|
||||||
|
|
||||||
|
## Maiden Hint for Theives Town Attic
|
||||||
|
|
||||||
|
In crossed dungeon mode, if you bring the maiden to the boss room when the attic is not bombed (and thus no light in the room), she mentions the dungeon where you can find the cracked floor.
|
||||||
|
|
||||||
## Shuffle Links House
|
## Shuffle Links House
|
||||||
|
|
||||||
Links house can now be shuffled in different ER settings. It will be limited to the Light World (or Dark World in inverted) if Crossed or Insanity shuffle is not one. It it also limited if door shuffle settings allow the Sanctuary to be in the dark world. (This is prevent having no Light World spawn points in Open modes) This setting is ignored by standard mode. THe CLI parameter is --shufflelinks
|
Links house can now be shuffled in different ER settings. It will be limited to the Light World (or Dark World in inverted) if Crossed or Insanity shuffle is not one. It it also limited if door shuffle settings allow the Sanctuary to be in the dark world. (This is prevent having no Light World spawn points in Open modes) This setting is ignored by standard mode. THe CLI parameter is --shufflelinks
|
||||||
@@ -10,6 +14,14 @@ Thanks to qadan, cheuer, & compiling
|
|||||||
|
|
||||||
# Bug Fixes and Notes.
|
# Bug Fixes and Notes.
|
||||||
|
|
||||||
|
* 0.4.0.6
|
||||||
|
* Hints now default to off
|
||||||
|
* The maiden gives you a hint to the attic if you bring her to the unlit boss room
|
||||||
|
* Beemizer support and fix for shopsanity
|
||||||
|
* Capacity upgrades removed in hard/expert item difficulties
|
||||||
|
* Swamp Hub added to lobby shuffle with ugly cave entrance.
|
||||||
|
* TR Lava Escape added to lobby shuffle.
|
||||||
|
* Hyrule Main Lobby and Sanctuary can now have a more visible outside exit, and rugs modified to be fully clipped.
|
||||||
* 0.4.0.5
|
* 0.4.0.5
|
||||||
* Insanity - less restrictions on exiting (all modes)
|
* Insanity - less restrictions on exiting (all modes)
|
||||||
* Fix for simple bosses shuffle
|
* Fix for simple bosses shuffle
|
||||||
@@ -51,8 +63,7 @@ Thanks to qadan, cheuer, & compiling
|
|||||||
# Known Issues
|
# Known Issues
|
||||||
|
|
||||||
* Shopsanity Issues
|
* Shopsanity Issues
|
||||||
* Hints for items in shops can be misleading
|
* Hints for items in shops can be misleading (ER)
|
||||||
* Capacity upgrades present in hard/expert item pools
|
|
||||||
* Forfeit in Multiworld not granting all shop items
|
* Forfeit in Multiworld not granting all shop items
|
||||||
* Potential keylocks in multi-entrance dungeons
|
* Potential keylocks in multi-entrance dungeons
|
||||||
* Incorrect vanilla key logic for Mire
|
* Incorrect vanilla key logic for Mire
|
||||||
|
|||||||
21
Rom.py
21
Rom.py
@@ -27,7 +27,7 @@ from EntranceShuffle import door_addresses, exit_ids
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = 'e5d8410de046832272951f3e6b4fade2'
|
RANDOMIZERBASEHASH = '2f83a44f0ac2720b489d50bfa8e56837'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -716,6 +716,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
if should_be_bunny(links_house, world.mode[player]):
|
if should_be_bunny(links_house, world.mode[player]):
|
||||||
rom.write_bytes(0x13fff0, [0x04, 0x01])
|
rom.write_bytes(0x13fff0, [0x04, 0x01])
|
||||||
|
|
||||||
|
old_man_house = world.get_region('Old Man House', player)
|
||||||
|
if should_be_bunny(old_man_house, world.mode[player]):
|
||||||
|
rom.write_bytes(0x13fff4, [0xe4, 0x00])
|
||||||
|
|
||||||
# patch doors
|
# patch doors
|
||||||
if world.doorShuffle[player] == 'crossed':
|
if world.doorShuffle[player] == 'crossed':
|
||||||
@@ -1633,6 +1636,9 @@ def write_custom_shops(rom, world, player):
|
|||||||
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:
|
||||||
loc_item = ItemFactory(item['item'], player)
|
loc_item = ItemFactory(item['item'], player)
|
||||||
|
if (not world.shopsanity[player] and shop.region.name == 'Capacity Upgrade'
|
||||||
|
and world.difficulty[player] != 'normal'):
|
||||||
|
continue # skip cap upgrades except in normal/shopsanity
|
||||||
item_id = loc_item.code
|
item_id = loc_item.code
|
||||||
price = int16_as_bytes(item['price'])
|
price = int16_as_bytes(item['price'])
|
||||||
replace = ItemFactory(item['replacement'], player).code if item['replacement'] else 0xFF
|
replace = ItemFactory(item['replacement'], player).code if item['replacement'] else 0xFF
|
||||||
@@ -2064,7 +2070,7 @@ def write_strings(rom, world, player, team):
|
|||||||
if world.doorShuffle[player] in ['crossed']:
|
if world.doorShuffle[player] in ['crossed']:
|
||||||
attic_hint = world.get_location("Thieves' Town - Attic", player).parent_region.dungeon.name
|
attic_hint = world.get_location("Thieves' Town - Attic", player).parent_region.dungeon.name
|
||||||
this_hint = 'A cracked floor can be found in ' + attic_hint + '.'
|
this_hint = 'A cracked floor can be found in ' + attic_hint + '.'
|
||||||
if hint_locations[0] == 'telepathic_tile_thieves_town_upstairs':
|
if world.intensity[player] < 2 and hint_locations[0] == 'telepathic_tile_thieves_town_upstairs':
|
||||||
tt[hint_locations.pop(1)] = this_hint
|
tt[hint_locations.pop(1)] = this_hint
|
||||||
else:
|
else:
|
||||||
tt[hint_locations.pop(0)] = this_hint
|
tt[hint_locations.pop(0)] = this_hint
|
||||||
@@ -2153,6 +2159,17 @@ def write_strings(rom, world, player, team):
|
|||||||
bombos_text = 'Some Hot Air' if bombositem is None else hint_text(bombositem, True) if bombositem.pedestal_hint_text is not None else 'Unknown Item'
|
bombos_text = 'Some Hot Air' if bombositem is None else hint_text(bombositem, True) if bombositem.pedestal_hint_text is not None else 'Unknown Item'
|
||||||
tt['tablet_bombos_book'] = bombos_text
|
tt['tablet_bombos_book'] = bombos_text
|
||||||
|
|
||||||
|
# attic hint
|
||||||
|
if world.doorShuffle[player] in ['crossed']:
|
||||||
|
attic_hint = world.get_location("Thieves' Town - Attic", player).parent_region.dungeon.name
|
||||||
|
tt['blind_not_that_way'] = f'{attic_hint} is too bright for my eyes'
|
||||||
|
# see tagalog.asm tables at 957,967 or Follower_HandleTrigger in JPDASM
|
||||||
|
# also the baserom table at org $09A4C2 in hooks.asm (Escort text)
|
||||||
|
rom.write_byte(0x04a4be, 0xac) # change the room to blind's room
|
||||||
|
rom.write_byte(0x04a526, 0xb8) # y coordinate, shifted down
|
||||||
|
rom.write_byte(0x04a529, 0x19) # x tile shifted right a few tiles
|
||||||
|
rom.write_byte(0x04a52e, 0x06) # follower set to blind maiden
|
||||||
|
|
||||||
# inverted spawn menu changes
|
# inverted spawn menu changes
|
||||||
if world.mode[player] == 'inverted':
|
if world.mode[player] == 'inverted':
|
||||||
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s house\n Dark Chapel\n{CHOICE3}"
|
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s house\n Dark Chapel\n{CHOICE3}"
|
||||||
|
|||||||
29
Utils.py
29
Utils.py
@@ -294,29 +294,18 @@ def update_deprecated_args(args):
|
|||||||
if args:
|
if args:
|
||||||
argVars = vars(args)
|
argVars = vars(args)
|
||||||
truthy = [1, True, "True", "true"]
|
truthy = [1, True, "True", "true"]
|
||||||
# Hints default to TRUE
|
# Hints default to FALSE
|
||||||
# Don't do: Yes
|
# Don't do: Yes
|
||||||
# Do: No
|
# Do: No
|
||||||
if "no_hints" in argVars:
|
if "no_hints" in argVars:
|
||||||
src = "no_hints"
|
if args.no_hints in truthy:
|
||||||
if isinstance(argVars["hints"], dict):
|
if isinstance(argVars["hints"], dict):
|
||||||
tmp = {}
|
tmp = {}
|
||||||
for idx in range(1, len(argVars["hints"]) + 1):
|
for idx in range(1, len(argVars["hints"]) + 1):
|
||||||
tmp[idx] = argVars[src] not in truthy # tmp = !src
|
tmp[idx] = False
|
||||||
args.hints = tmp # dest = tmp
|
args.hints = tmp
|
||||||
else:
|
else:
|
||||||
args.hints = args.no_hints not in truthy # dest = !src
|
args.hints = False
|
||||||
# Don't do: No
|
|
||||||
# Do: Yes
|
|
||||||
if "hints" in argVars:
|
|
||||||
src = "hints"
|
|
||||||
if isinstance(argVars["hints"], dict):
|
|
||||||
tmp = {}
|
|
||||||
for idx in range(1, len(argVars["hints"]) + 1):
|
|
||||||
tmp[idx] = argVars[src] not in truthy # tmp = !src
|
|
||||||
args.no_hints = tmp # dest = tmp
|
|
||||||
else:
|
|
||||||
args.no_hints = args.hints not in truthy # dest = !src
|
|
||||||
|
|
||||||
# Spoiler defaults to TRUE
|
# Spoiler defaults to TRUE
|
||||||
# Don't do: Yes
|
# Don't do: Yes
|
||||||
|
|||||||
@@ -572,6 +572,18 @@ InroomStairsY:
|
|||||||
dw $0058, $0148, $0198, $0190
|
dw $0058, $0148, $0198, $0190
|
||||||
|
|
||||||
|
|
||||||
|
org $27E000
|
||||||
|
CutoffRooms:
|
||||||
|
; TT Alcove, Mire Bridge Left & Right, Mire Bent Bridge, Mire Hub
|
||||||
|
; Pod Falling & Harmless, SW Star Pits, TR Lava Escape & TR Dual Pipes, Bob's Room & GT Big Chest
|
||||||
|
dw $00bc, $00a2, $00a3, $00c2, $001a, $0049, $0014, $008c
|
||||||
|
; Ice Many Pots, Swamp Waterfall, GT Gauntlet 3, Eastern Push Block, Eastern Courtyard, Eastern Map Valley
|
||||||
|
; Eastern Cannonball, HC East Hall
|
||||||
|
dw $009f, $0066, $005d, $00a8, $00a9, $00aa, $00b9, $0052
|
||||||
|
; HC West Hall, TR Dash Bridge, TR Hub, Pod Arena, GT Petting Zoo
|
||||||
|
dw $0050, $00c5, $00c6, $0009, $0003, $002a, $007d
|
||||||
|
dw $ffff
|
||||||
|
|
||||||
; dungeon tables
|
; dungeon tables
|
||||||
; HC HC EP DP AT SP PD MM SW IP TH TT TR GT
|
; HC HC EP DP AT SP PD MM SW IP TH TT TR GT
|
||||||
org $27f000
|
org $27f000
|
||||||
@@ -676,3 +688,5 @@ LinksHouseDarkWorld:
|
|||||||
dw $ffff
|
dw $ffff
|
||||||
SanctuaryDarkWorld:
|
SanctuaryDarkWorld:
|
||||||
dw $ffff
|
dw $ffff
|
||||||
|
OldManDarkWorld:
|
||||||
|
dw $ffff
|
||||||
@@ -3,7 +3,8 @@ CheckDarkWorldSpawn:
|
|||||||
LDA.l DRFlags : AND #$0200 : BEQ + ; skip if the flag isn't set
|
LDA.l DRFlags : AND #$0200 : BEQ + ; skip if the flag isn't set
|
||||||
LDA.l $7EF357 : AND #$00FF : BNE + ; moon pearl?
|
LDA.l $7EF357 : AND #$00FF : BNE + ; moon pearl?
|
||||||
LDA.l LinksHouseDarkWorld : CMP $A0 : BEQ ++
|
LDA.l LinksHouseDarkWorld : CMP $A0 : BEQ ++
|
||||||
LDA.l SanctuaryDarkWorld : CMP $A0 : BNE +
|
LDA.l SanctuaryDarkWorld : CMP $A0 : BEQ ++
|
||||||
|
LDA.l OldManDarkWorld : CMP $A0 : BNE +
|
||||||
++ SEP #$30 : LDA #$17 : STA $5D
|
++ SEP #$30 : LDA #$17 : STA $5D
|
||||||
INC $02E0 : LDA.b #$40 : STA !DARK_WORLD : REP #$30
|
INC $02E0 : LDA.b #$40 : STA !DARK_WORLD : REP #$30
|
||||||
+ RTL
|
+ RTL
|
||||||
|
|||||||
@@ -173,6 +173,12 @@ JSL RainPrevention : NOP #2
|
|||||||
org $1edabf ; <- sprite_energy_ball.asm : 86-7 Sprite_EnergyBall (LDA.b #$10 : LDX.b #$00)
|
org $1edabf ; <- sprite_energy_ball.asm : 86-7 Sprite_EnergyBall (LDA.b #$10 : LDX.b #$00)
|
||||||
JSL StandardAgaDmg
|
JSL StandardAgaDmg
|
||||||
|
|
||||||
|
|
||||||
|
org $09a681 ; < - similar to talalong.asm : 1157 (JSL Main_ShowTextMessage)
|
||||||
|
JSL BlindsAtticHint : NOP #2
|
||||||
|
org $1cfd69
|
||||||
|
Main_ShowTextMessage:
|
||||||
|
|
||||||
; These two, if enabled together, have implications for vanilla BK doors in IP/Hera/Mire
|
; These two, if enabled together, have implications for vanilla BK doors in IP/Hera/Mire
|
||||||
; IPBJ is common enough to consider not doing this. Mire is not a concern for vanilla - maybe glitched modes
|
; IPBJ is common enough to consider not doing this. Mire is not a concern for vanilla - maybe glitched modes
|
||||||
; Hera BK door back can be seen with Pot clipping - likely useful for no logic seeds
|
; Hera BK door back can be seen with Pot clipping - likely useful for no logic seeds
|
||||||
|
|||||||
@@ -84,32 +84,24 @@ SuctionOverworldFix:
|
|||||||
stz $49
|
stz $49
|
||||||
+ rtl
|
+ rtl
|
||||||
|
|
||||||
; TT Alcove, Mire bridges, pod falling, SW torch room, TR Pipe room, Bob's Room, Ice Many Pots, Mire Hub
|
!CutoffTable = "$27E000"
|
||||||
; swamp waterfall, Gauntlet 3, Eastern Push block
|
|
||||||
CutoffRooms:
|
|
||||||
db $bc, $a2, $1a, $49, $14, $8c, $9f, $c2
|
|
||||||
db $66, $5d, $a8
|
|
||||||
; Don't forget CutoffRoomCount!!!
|
|
||||||
|
|
||||||
CutoffEntranceRug:
|
CutoffEntranceRug:
|
||||||
pha : phx
|
PHA : PHX
|
||||||
lda.l DRMode : beq .norm
|
LDA.l DRMode : BEQ .norm
|
||||||
lda $04 : cmp #$000A : beq +
|
LDA $04 : cmp #$000A : BEQ + ; only affect A & C objects
|
||||||
cmp #$000C : bne .norm
|
cmp #$000C : BNE .norm
|
||||||
+ lda $a0 : sep #$20 : ldx #$0000
|
+ LDX #$0000 : LDA !CutoffTable, x
|
||||||
- cmp.l CutoffRooms, x : beq .check
|
- CMP.W $A0 : BEQ .check
|
||||||
inx : cpx #$000B : !blt - ; CutoffRoomCount is here!
|
INX #2 : LDA !CutoffTable, x : CMP.w #$FFFF : BNE -
|
||||||
rep #$20
|
.norm PLX : PLA : LDA $9B52, y : STA $7E2000, x ; what we wrote over
|
||||||
.norm plx : pla : lda $9B52, y : sta $7E2000, x ; what we wrote over
|
RTL
|
||||||
rtl
|
|
||||||
.check
|
.check
|
||||||
rep #$20
|
LDA $0c : CMP #$0004 : !BGE .skip
|
||||||
lda $0c : cmp #$0006 : !bge .skip
|
LDA $0e : CMP #$0008 : !BGE .skip
|
||||||
lda $0e : cmp #$0008 : !bge .skip
|
CMP.l #$0004 : !BLT .skip
|
||||||
cmp #$0004 : !blt .skip
|
BRA .norm
|
||||||
bra .norm
|
.skip PLX : PLA : RTL
|
||||||
.skip plx : pla : rtl
|
|
||||||
|
|
||||||
|
|
||||||
StoreTempBunnyState:
|
StoreTempBunnyState:
|
||||||
LDA $5D : CMP #$1C : BNE +
|
LDA $5D : CMP #$1C : BNE +
|
||||||
@@ -131,7 +123,7 @@ RainPrevention:
|
|||||||
LDA.l BlockSanctuaryDoorInRain : BEQ .done ;flagged
|
LDA.l BlockSanctuaryDoorInRain : BEQ .done ;flagged
|
||||||
LDA $A0 : CMP #$0012 : BNE + ;we're in the sanctuary
|
LDA $A0 : CMP #$0012 : BNE + ;we're in the sanctuary
|
||||||
LDA.l $7EF3CC : AND #$00FF : CMP #$0001 : BEQ .done ; zelda is following
|
LDA.l $7EF3CC : AND #$00FF : CMP #$0001 : BEQ .done ; zelda is following
|
||||||
LDA $00 : CMP #$02A1 : BNE .done
|
LDA $00 : AND #$00FF : CMP #$00A1 : BNE .done ; position is a1
|
||||||
PLA : LDA #$0008 : RTL
|
PLA : LDA #$0008 : RTL
|
||||||
+ LDA.l BlockCastleDoorsInRain : AND #$00FF : BEQ .done ;flagged
|
+ LDA.l BlockCastleDoorsInRain : AND #$00FF : BEQ .done ;flagged
|
||||||
LDX #$FFFE
|
LDX #$FFFE
|
||||||
@@ -148,3 +140,11 @@ StandardAgaDmg:
|
|||||||
LDA.b #$10 ; hurt him!
|
LDA.b #$10 ; hurt him!
|
||||||
+ RTL ; A is zero if the AND results in zero and then Agahnim's invincible!
|
+ RTL ; A is zero if the AND results in zero and then Agahnim's invincible!
|
||||||
|
|
||||||
|
; note: this skips both maiden dialog triggers if the hole is open
|
||||||
|
BlindsAtticHint:
|
||||||
|
REP #$20
|
||||||
|
CMP.w #$0122 : BNE +
|
||||||
|
LDA $7EF0CA : AND.w #$0100 : BEQ +
|
||||||
|
SEP #$20 : RTL ; skip the dialog box if the hole is already open
|
||||||
|
+ SEP #$20 : JML Main_ShowTextMessage
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -189,6 +189,11 @@
|
|||||||
"random"
|
"random"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"beemizer": {
|
||||||
|
"choices": [
|
||||||
|
"4", "3", "2", "1", "0"
|
||||||
|
]
|
||||||
|
},
|
||||||
"openpyramid": {
|
"openpyramid": {
|
||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
|
|||||||
@@ -135,7 +135,7 @@
|
|||||||
"randomizer.entrance.entranceshuffle.dungeonssimple": "Dungeons + Simple",
|
"randomizer.entrance.entranceshuffle.dungeonssimple": "Dungeons + Simple",
|
||||||
|
|
||||||
|
|
||||||
"randomizer.gameoptions.hints": "Include Helpful Hints",
|
|
||||||
"randomizer.gameoptions.nobgm": "Disable Music & MSU-1",
|
"randomizer.gameoptions.nobgm": "Disable Music & MSU-1",
|
||||||
"randomizer.gameoptions.quickswap": "L/R Quickswapping",
|
"randomizer.gameoptions.quickswap": "L/R Quickswapping",
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@
|
|||||||
"randomizer.generation.rom.dialog.romfiles": "Rom Files",
|
"randomizer.generation.rom.dialog.romfiles": "Rom Files",
|
||||||
"randomizer.generation.rom.dialog.allfiles": "All Files",
|
"randomizer.generation.rom.dialog.allfiles": "All Files",
|
||||||
|
|
||||||
|
"randomizer.item.hints": "Include Helpful Hints",
|
||||||
"randomizer.item.retro": "Retro mode (universal keys)",
|
"randomizer.item.retro": "Retro mode (universal keys)",
|
||||||
|
|
||||||
"randomizer.item.worldstate": "World State",
|
"randomizer.item.worldstate": "World State",
|
||||||
@@ -241,6 +241,13 @@
|
|||||||
"randomizer.item.weapons.swordless": "Swordless",
|
"randomizer.item.weapons.swordless": "Swordless",
|
||||||
"randomizer.item.weapons.vanilla": "Vanilla",
|
"randomizer.item.weapons.vanilla": "Vanilla",
|
||||||
|
|
||||||
|
"randomizer.item.beemizer": "Beemizer",
|
||||||
|
"randomizer.item.beemizer.0": "No Bee Traps",
|
||||||
|
"randomizer.item.beemizer.1": "25% Bee Traps",
|
||||||
|
"randomizer.item.beemizer.2": "40% Traps, 20% Refills",
|
||||||
|
"randomizer.item.beemizer.3": "50% Traps, 50% Refills",
|
||||||
|
"randomizer.item.beemizer.4": "100% Bee Traps",
|
||||||
|
|
||||||
"randomizer.item.itempool": "Item Pool",
|
"randomizer.item.itempool": "Item Pool",
|
||||||
"randomizer.item.itempool.normal": "Normal",
|
"randomizer.item.itempool.normal": "Normal",
|
||||||
"randomizer.item.itempool.hard": "Hard",
|
"randomizer.item.itempool.hard": "Hard",
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
{
|
{
|
||||||
"checkboxes": {
|
"checkboxes": {
|
||||||
"hints": {
|
|
||||||
"type": "checkbox",
|
|
||||||
"default": "true"
|
|
||||||
},
|
|
||||||
"nobgm": { "type": "checkbox" },
|
"nobgm": { "type": "checkbox" },
|
||||||
"quickswap": { "type": "checkbox" }
|
"quickswap": { "type": "checkbox" }
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
{
|
{
|
||||||
"checkboxes": {
|
"checkboxes": {
|
||||||
"retro": { "type": "checkbox" },
|
"retro": { "type": "checkbox" },
|
||||||
"shopsanity": { "type": "checkbox" }
|
"shopsanity": { "type": "checkbox" },
|
||||||
|
"hints": {
|
||||||
|
"type": "checkbox"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"leftItemFrame": {
|
"leftItemFrame": {
|
||||||
"worldstate": {
|
"worldstate": {
|
||||||
@@ -55,6 +58,12 @@
|
|||||||
"swordless",
|
"swordless",
|
||||||
"vanilla"
|
"vanilla"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"beemizer": {
|
||||||
|
"type": "selectbox",
|
||||||
|
"options": [
|
||||||
|
"0", "1", "2", "3", "4"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rightItemFrame": {
|
"rightItemFrame": {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ CUSTOMITEMLABELS = [
|
|||||||
SETTINGSTOPROCESS = {
|
SETTINGSTOPROCESS = {
|
||||||
"randomizer": {
|
"randomizer": {
|
||||||
"item": {
|
"item": {
|
||||||
|
"hints": "hints",
|
||||||
"retro": "retro",
|
"retro": "retro",
|
||||||
"shopsanity": "shopsanity",
|
"shopsanity": "shopsanity",
|
||||||
"worldstate": "mode",
|
"worldstate": "mode",
|
||||||
@@ -68,7 +69,8 @@ SETTINGSTOPROCESS = {
|
|||||||
"timer": "timer",
|
"timer": "timer",
|
||||||
"progressives": "progressive",
|
"progressives": "progressive",
|
||||||
"accessibility": "accessibility",
|
"accessibility": "accessibility",
|
||||||
"sortingalgo": "algorithm"
|
"sortingalgo": "algorithm",
|
||||||
|
"beemizer": "beemizer"
|
||||||
},
|
},
|
||||||
"overworld": {
|
"overworld": {
|
||||||
"overworldshuffle": "ow_shuffle",
|
"overworldshuffle": "ow_shuffle",
|
||||||
@@ -101,7 +103,6 @@ SETTINGSTOPROCESS = {
|
|||||||
"standardize_palettes": "standardize_palettes",
|
"standardize_palettes": "standardize_palettes",
|
||||||
},
|
},
|
||||||
"gameoptions": {
|
"gameoptions": {
|
||||||
"hints": "hints",
|
|
||||||
"nobgm": "disablemusic",
|
"nobgm": "disablemusic",
|
||||||
"quickswap": "quickswap",
|
"quickswap": "quickswap",
|
||||||
"heartcolor": "heartcolor",
|
"heartcolor": "heartcolor",
|
||||||
|
|||||||
Reference in New Issue
Block a user