Merge branch 'StandingItems' into DoorDevVolatile
# Conflicts: # Rules.py # source/item/FillUtil.py
This commit is contained in:
+92
-34
@@ -86,6 +86,7 @@ class World(object):
|
|||||||
self._portal_cache = {}
|
self._portal_cache = {}
|
||||||
self.sanc_portal = {}
|
self.sanc_portal = {}
|
||||||
self.fish = BabelFish()
|
self.fish = BabelFish()
|
||||||
|
self.pot_contents = {}
|
||||||
|
|
||||||
for player in range(1, players + 1):
|
for player in range(1, players + 1):
|
||||||
# If World State is Retro, set to Open and set Retro flag
|
# If World State is Retro, set to Open and set Retro flag
|
||||||
@@ -139,7 +140,7 @@ class World(object):
|
|||||||
set_player_attr('pseudoboots', False)
|
set_player_attr('pseudoboots', False)
|
||||||
|
|
||||||
set_player_attr('shopsanity', False)
|
set_player_attr('shopsanity', False)
|
||||||
set_player_attr('keydropshuffle', False)
|
set_player_attr('keydropshuffle', 'none')
|
||||||
set_player_attr('mixed_travel', 'prevent')
|
set_player_attr('mixed_travel', 'prevent')
|
||||||
set_player_attr('standardize_palettes', 'standardize')
|
set_player_attr('standardize_palettes', 'standardize')
|
||||||
set_player_attr('force_fix', {'gt': False, 'sw': False, 'pod': False, 'tr': False})
|
set_player_attr('force_fix', {'gt': False, 'sw': False, 'pod': False, 'tr': False})
|
||||||
@@ -381,6 +382,8 @@ class World(object):
|
|||||||
location.item = item
|
location.item = item
|
||||||
item.location = location
|
item.location = location
|
||||||
item.world = self
|
item.world = self
|
||||||
|
if location.player != item.player and location.type == LocationType.Pot:
|
||||||
|
self.pot_contents[location.player].multiworld_count += 1
|
||||||
if collect:
|
if collect:
|
||||||
self.state.collect(item, location.event, location)
|
self.state.collect(item, location.event, location)
|
||||||
|
|
||||||
@@ -2119,10 +2122,19 @@ class Location(object):
|
|||||||
self.item_rule = lambda item: True
|
self.item_rule = lambda item: True
|
||||||
self.player = player
|
self.player = player
|
||||||
self.skip = False
|
self.skip = False
|
||||||
|
self.type = LocationType.Normal if not crystal else LocationType.Prize
|
||||||
|
self.pot = None
|
||||||
|
|
||||||
def can_fill(self, state, item, check_access=True):
|
def can_fill(self, state, item, check_access=True):
|
||||||
|
if not self.valid_multiworld(state, item):
|
||||||
|
return False
|
||||||
return self.always_allow(state, item) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state)))
|
return self.always_allow(state, item) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state)))
|
||||||
|
|
||||||
|
def valid_multiworld(self, state, item):
|
||||||
|
if self.type == LocationType.Pot and self.player != item.player:
|
||||||
|
return state.world.pot_contents[self.player].multiworld_count < 256
|
||||||
|
return True
|
||||||
|
|
||||||
def can_reach(self, state):
|
def can_reach(self, state):
|
||||||
return self.parent_region.can_reach(state) and self.access_rule(state)
|
return self.parent_region.can_reach(state) and self.access_rule(state)
|
||||||
|
|
||||||
@@ -2158,6 +2170,15 @@ class Location(object):
|
|||||||
return hash((self.name, self.player))
|
return hash((self.name, self.player))
|
||||||
|
|
||||||
|
|
||||||
|
class LocationType(FastEnum):
|
||||||
|
Normal = 0
|
||||||
|
Prize = 1
|
||||||
|
Logical = 2
|
||||||
|
Shop = 3
|
||||||
|
Pot = 4
|
||||||
|
Drop = 5
|
||||||
|
|
||||||
|
|
||||||
class Item(object):
|
class Item(object):
|
||||||
|
|
||||||
def __init__(self, name='', advancement=False, priority=False, type=None, code=None, price=999, pedestal_hint=None,
|
def __init__(self, name='', advancement=False, priority=False, type=None, code=None, price=999, pedestal_hint=None,
|
||||||
@@ -2372,11 +2393,11 @@ class Spoiler(object):
|
|||||||
listed_locations.update(cave_locations)
|
listed_locations.update(cave_locations)
|
||||||
|
|
||||||
for dungeon in self.world.dungeons:
|
for dungeon in self.world.dungeons:
|
||||||
dungeon_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon and not loc.forced_item]
|
dungeon_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon and not loc.forced_item and not loc.skip]
|
||||||
self.locations[str(dungeon)] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in dungeon_locations])
|
self.locations[str(dungeon)] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in dungeon_locations])
|
||||||
listed_locations.update(dungeon_locations)
|
listed_locations.update(dungeon_locations)
|
||||||
|
|
||||||
other_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations]
|
other_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and not loc.skip]
|
||||||
if other_locations:
|
if other_locations:
|
||||||
self.locations['Other Locations'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in other_locations])
|
self.locations['Other Locations'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in other_locations])
|
||||||
listed_locations.update(other_locations)
|
listed_locations.update(other_locations)
|
||||||
@@ -2454,11 +2475,12 @@ class Spoiler(object):
|
|||||||
'enemy_shuffle': self.world.enemy_shuffle,
|
'enemy_shuffle': self.world.enemy_shuffle,
|
||||||
'enemy_health': self.world.enemy_health,
|
'enemy_health': self.world.enemy_health,
|
||||||
'enemy_damage': self.world.enemy_damage,
|
'enemy_damage': self.world.enemy_damage,
|
||||||
'potshuffle': self.world.potshuffle,
|
|
||||||
'players': self.world.players,
|
'players': self.world.players,
|
||||||
'teams': self.world.teams,
|
'teams': self.world.teams,
|
||||||
'experimental': self.world.experimental,
|
'experimental': self.world.experimental,
|
||||||
'keydropshuffle': self.world.keydropshuffle,
|
'dropshuffle': self.world.dropshuffle,
|
||||||
|
'pottery': self.world.pottery,
|
||||||
|
'potshuffle': self.world.potshuffle,
|
||||||
'shopsanity': self.world.shopsanity,
|
'shopsanity': self.world.shopsanity,
|
||||||
'pseudoboots': self.world.pseudoboots,
|
'pseudoboots': self.world.pseudoboots,
|
||||||
'triforcegoal': self.world.treasure_hunt_count,
|
'triforcegoal': self.world.treasure_hunt_count,
|
||||||
@@ -2519,6 +2541,9 @@ class Spoiler(object):
|
|||||||
outfile.write(f"Link's House Shuffled: {yn(self.metadata['shufflelinks'])}\n")
|
outfile.write(f"Link's House Shuffled: {yn(self.metadata['shufflelinks'])}\n")
|
||||||
outfile.write('Door Shuffle: %s\n' % self.metadata['door_shuffle'][player])
|
outfile.write('Door Shuffle: %s\n' % self.metadata['door_shuffle'][player])
|
||||||
outfile.write('Intensity: %s\n' % self.metadata['intensity'][player])
|
outfile.write('Intensity: %s\n' % self.metadata['intensity'][player])
|
||||||
|
outfile.write(f"Drop Shuffle: {yn(self.metadata['dropshuffle'][player])}\n")
|
||||||
|
outfile.write(f"Pottery Mode: {self.metadata['pottery'][player]}\n")
|
||||||
|
outfile.write(f"Pot Shuffle (Legacy): {yn(self.metadata['potshuffle'][player])}\n")
|
||||||
addition = ' (Random)' if self.world.crystals_gt_orig[player] == 'random' else ''
|
addition = ' (Random)' if self.world.crystals_gt_orig[player] == 'random' else ''
|
||||||
outfile.write('Crystals required for GT: %s\n' % (str(self.metadata['gt_crystals'][player]) + addition))
|
outfile.write('Crystals required for GT: %s\n' % (str(self.metadata['gt_crystals'][player]) + addition))
|
||||||
addition = ' (Random)' if self.world.crystals_ganon_orig[player] == 'random' else ''
|
addition = ' (Random)' if self.world.crystals_ganon_orig[player] == 'random' else ''
|
||||||
@@ -2534,10 +2559,8 @@ class Spoiler(object):
|
|||||||
outfile.write('Enemy shuffle: %s\n' % self.metadata['enemy_shuffle'][player])
|
outfile.write('Enemy shuffle: %s\n' % self.metadata['enemy_shuffle'][player])
|
||||||
outfile.write('Enemy health: %s\n' % self.metadata['enemy_health'][player])
|
outfile.write('Enemy health: %s\n' % self.metadata['enemy_health'][player])
|
||||||
outfile.write('Enemy damage: %s\n' % self.metadata['enemy_damage'][player])
|
outfile.write('Enemy damage: %s\n' % self.metadata['enemy_damage'][player])
|
||||||
outfile.write(f"Pot shuffle: {yn(self.metadata['potshuffle'][player])}\n")
|
|
||||||
outfile.write(f"Hints: {yn(self.metadata['hints'][player])}\n")
|
outfile.write(f"Hints: {yn(self.metadata['hints'][player])}\n")
|
||||||
outfile.write(f"Experimental: {yn(self.metadata['experimental'][player])}\n")
|
outfile.write(f"Experimental: {yn(self.metadata['experimental'][player])}\n")
|
||||||
outfile.write(f"Key Drops shuffled: {yn(self.metadata['keydropshuffle'][player])}\n")
|
|
||||||
outfile.write(f"Shopsanity: {yn(self.metadata['shopsanity'][player])}\n")
|
outfile.write(f"Shopsanity: {yn(self.metadata['shopsanity'][player])}\n")
|
||||||
outfile.write(f"Bombbag: {yn(self.metadata['bombbag'][player])}\n")
|
outfile.write(f"Bombbag: {yn(self.metadata['bombbag'][player])}\n")
|
||||||
outfile.write(f"Pseudoboots: {yn(self.metadata['pseudoboots'][player])}\n")
|
outfile.write(f"Pseudoboots: {yn(self.metadata['pseudoboots'][player])}\n")
|
||||||
@@ -2681,6 +2704,8 @@ class PotFlags(FastEnum):
|
|||||||
Normal = 0x0
|
Normal = 0x0
|
||||||
NoSwitch = 0x1 # A switch should never go here
|
NoSwitch = 0x1 # A switch should never go here
|
||||||
SwitchLogicChange = 0x2 # A switch can go here, but requires a logic change
|
SwitchLogicChange = 0x2 # A switch can go here, but requires a logic change
|
||||||
|
Block = 0x4 # This is actually a block
|
||||||
|
LowerRegion = 0x8 # This is a pot in the lower region
|
||||||
|
|
||||||
|
|
||||||
class Pot(object):
|
class Pot(object):
|
||||||
@@ -2690,6 +2715,23 @@ class Pot(object):
|
|||||||
self.item = item
|
self.item = item
|
||||||
self.room = room
|
self.room = room
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
|
self.indicator = None # 0x80 for standing item, 0xC0 multiworld item
|
||||||
|
self.standing_item_code = None # standing item code if nay
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
return Pot(self.x, self.y, self.item, self.room, self.flags)
|
||||||
|
|
||||||
|
def empty(self):
|
||||||
|
return self.item == PotItem.Nothing and self.indicator is None
|
||||||
|
|
||||||
|
def pot_data(self):
|
||||||
|
high_byte = self.y
|
||||||
|
if self.flags & PotFlags.LowerRegion:
|
||||||
|
high_byte |= 0x20
|
||||||
|
if self.indicator:
|
||||||
|
high_byte |= self.indicator
|
||||||
|
item = self.item if not self.indicator else self.standing_item_code
|
||||||
|
return [self.x, high_byte, item]
|
||||||
|
|
||||||
|
|
||||||
# byte 0: DDDE EEEE (DR, ER)
|
# byte 0: DDDE EEEE (DR, ER)
|
||||||
@@ -2707,27 +2749,33 @@ goal_mode = {"ganon": 0, "pedestal": 1, "dungeons": 2, "triforcehunt": 3, "cryst
|
|||||||
diff_mode = {"normal": 0, "hard": 1, "expert": 2}
|
diff_mode = {"normal": 0, "hard": 1, "expert": 2}
|
||||||
func_mode = {"normal": 0, "hard": 1, "expert": 2}
|
func_mode = {"normal": 0, "hard": 1, "expert": 2}
|
||||||
|
|
||||||
# byte 3: SKMM PIII (shop, keydrop, mixed, palettes, intensity)
|
# byte 3: S?MM PIII (shop, unused, mixed, palettes, intensity)
|
||||||
|
# keydrop now has it's own byte
|
||||||
mixed_travel_mode = {"prevent": 0, "allow": 1, "force": 2}
|
mixed_travel_mode = {"prevent": 0, "allow": 1, "force": 2}
|
||||||
# intensity is 3 bits (reserves 4-7 levels)
|
# intensity is 3 bits (reserves 4-7 levels)
|
||||||
|
|
||||||
# byte 4: CCCC CTTX (crystals gt, ctr2, experimental)
|
# new byte 4: ?DDD PPPP (unused, drop, pottery)
|
||||||
|
# dropshuffle reserves 2 bits, pottery needs 2 but reserves 2 for future modes)
|
||||||
|
pottery_mode = {"none": 0, "shuffle": 1, "keys": 2, "lottery": 3}
|
||||||
|
|
||||||
|
# byte 5: CCCC CTTX (crystals gt, ctr2, experimental)
|
||||||
counter_mode = {"default": 0, "off": 1, "on": 2, "pickup": 3}
|
counter_mode = {"default": 0, "off": 1, "on": 2, "pickup": 3}
|
||||||
|
|
||||||
# byte 5: CCCC CPAA (crystals ganon, pyramid, access
|
# byte 6: CCCC CPAA (crystals ganon, pyramid, access
|
||||||
access_mode = {"items": 0, "locations": 1, "none": 2}
|
access_mode = {"items": 0, "locations": 1, "none": 2}
|
||||||
|
|
||||||
# byte 6: BSMC BBEE (big, small, maps, compass, bosses, enemies)
|
# byte 7: BSMC BBEE (big, small, maps, compass, bosses, enemies)
|
||||||
boss_mode = {"none": 0, "simple": 1, "full": 2, "random": 3, "chaos": 3}
|
boss_mode = {"none": 0, "simple": 1, "full": 2, "random": 3, "chaos": 3}
|
||||||
enemy_mode = {"none": 0, "shuffled": 1, "random": 2, "chaos": 2, "legacy": 3}
|
enemy_mode = {"none": 0, "shuffled": 1, "random": 2, "chaos": 2, "legacy": 3}
|
||||||
|
|
||||||
# byte 7: HHHD DPBS (enemy_health, enemy_dmg, potshuffle, bomb logic, shuffle links)
|
# byte 8: HHHD DPBS (enemy_health, enemy_dmg, potshuffle, bomb logic, shuffle links)
|
||||||
|
# potshuffle decprecated, now unused
|
||||||
e_health = {"default": 0, "easy": 1, "normal": 2, "hard": 3, "expert": 4}
|
e_health = {"default": 0, "easy": 1, "normal": 2, "hard": 3, "expert": 4}
|
||||||
e_dmg = {"default": 0, "shuffled": 1, "random": 2}
|
e_dmg = {"default": 0, "shuffled": 1, "random": 2}
|
||||||
|
|
||||||
# byte 8: RRAA A??? (restrict boss mode, algorithm, ? = unused)
|
# byte 9: RRAA A??? (restrict boss mode, algorithm, ? = unused)
|
||||||
rb_mode = {"none": 0, "mapcompass": 1, "dungeon": 2}
|
rb_mode = {"none": 0, "mapcompass": 1, "dungeon": 2}
|
||||||
# algorithm: todo with "biased shuffles"
|
# algorithm:
|
||||||
algo_mode = {"balanced": 0, "equitable": 1, "vanilla_fill": 2, "dungeon_only": 3, "district": 4}
|
algo_mode = {"balanced": 0, "equitable": 1, "vanilla_fill": 2, "dungeon_only": 3, "district": 4}
|
||||||
|
|
||||||
# additions
|
# additions
|
||||||
@@ -2748,10 +2796,12 @@ class Settings(object):
|
|||||||
(goal_mode[w.goal[p]] << 5) | (diff_mode[w.difficulty[p]] << 3)
|
(goal_mode[w.goal[p]] << 5) | (diff_mode[w.difficulty[p]] << 3)
|
||||||
| (func_mode[w.difficulty_adjustments[p]] << 1) | (1 if w.hints[p] else 0),
|
| (func_mode[w.difficulty_adjustments[p]] << 1) | (1 if w.hints[p] else 0),
|
||||||
|
|
||||||
(0x80 if w.shopsanity[p] else 0) | (0x40 if w.keydropshuffle[p] else 0)
|
(0x80 if w.shopsanity[p] else 0) | (mixed_travel_mode[w.mixed_travel[p]] << 4)
|
||||||
| (mixed_travel_mode[w.mixed_travel[p]] << 4) | (0x8 if w.standardize_palettes[p] == "original" else 0)
|
| (0x8 if w.standardize_palettes[p] == "original" else 0)
|
||||||
| (0 if w.intensity[p] == "random" else w.intensity[p]),
|
| (0 if w.intensity[p] == "random" else w.intensity[p]),
|
||||||
|
|
||||||
|
(0x10 if w.dropshuffle[p] else 0) | (pottery_mode[w.pottery[p]]),
|
||||||
|
|
||||||
((8 if w.crystals_gt_orig[p] == "random" else int(w.crystals_gt_orig[p])) << 3)
|
((8 if w.crystals_gt_orig[p] == "random" else int(w.crystals_gt_orig[p])) << 3)
|
||||||
| (counter_mode[w.dungeon_counters[p]] << 1) | (1 if w.experimental[p] else 0),
|
| (counter_mode[w.dungeon_counters[p]] << 1) | (1 if w.experimental[p] else 0),
|
||||||
|
|
||||||
@@ -2788,31 +2838,39 @@ class Settings(object):
|
|||||||
args.hints[p] = True if settings[2] & 0x01 else False
|
args.hints[p] = True if settings[2] & 0x01 else False
|
||||||
args.retro[p] = True if settings[1] & 0x01 else False
|
args.retro[p] = True if settings[1] & 0x01 else False
|
||||||
args.shopsanity[p] = True if settings[3] & 0x80 else False
|
args.shopsanity[p] = True if settings[3] & 0x80 else False
|
||||||
args.keydropshuffle[p] = True if settings[3] & 0x40 else False
|
# args.keydropshuffle[p] = True if settings[3] & 0x40 else False
|
||||||
args.mixed_travel[p] = r(mixed_travel_mode)[(settings[3] & 0x30) >> 4]
|
args.mixed_travel[p] = r(mixed_travel_mode)[(settings[3] & 0x30) >> 4]
|
||||||
args.standardize_palettes[p] = "original" if settings[3] & 0x8 else "standardize"
|
args.standardize_palettes[p] = "original" if settings[3] & 0x8 else "standardize"
|
||||||
intensity = settings[3] & 0x7
|
intensity = settings[3] & 0x7
|
||||||
args.intensity[p] = "random" if intensity == 0 else intensity
|
args.intensity[p] = "random" if intensity == 0 else intensity
|
||||||
args.dungeon_counters[p] = r(counter_mode)[(settings[4] & 0x6) >> 1]
|
|
||||||
cgt = (settings[4] & 0xf8) >> 3
|
# args.shuffleswitches[p] = True if settings[4] & 0x80 else False
|
||||||
|
args.dropshuffle[p] = True if settings[4] & 0x10 else False
|
||||||
|
args.pottery[p] = r(pottery_mode)[settings[4] & 0x0F]
|
||||||
|
|
||||||
|
args.dungeon_counters[p] = r(counter_mode)[(settings[5] & 0x6) >> 1]
|
||||||
|
cgt = (settings[5] & 0xf8) >> 3
|
||||||
args.crystals_gt[p] = "random" if cgt == 8 else cgt
|
args.crystals_gt[p] = "random" if cgt == 8 else cgt
|
||||||
args.experimental[p] = True if settings[4] & 0x1 else False
|
args.experimental[p] = True if settings[5] & 0x1 else False
|
||||||
cgan = (settings[5] & 0xf8) >> 3
|
|
||||||
|
cgan = (settings[6] & 0xf8) >> 3
|
||||||
args.crystals_ganon[p] = "random" if cgan == 8 else cgan
|
args.crystals_ganon[p] = "random" if cgan == 8 else cgan
|
||||||
args.openpyramid[p] = True if settings[5] & 0x4 else False
|
args.openpyramid[p] = True if settings[6] & 0x4 else False
|
||||||
args.bigkeyshuffle[p] = True if settings[6] & 0x80 else False
|
|
||||||
args.keyshuffle[p] = True if settings[6] & 0x40 else False
|
args.bigkeyshuffle[p] = True if settings[7] & 0x80 else False
|
||||||
args.mapshuffle[p] = True if settings[6] & 0x20 else False
|
args.keyshuffle[p] = True if settings[7] & 0x40 else False
|
||||||
args.compassshuffle[p] = True if settings[6] & 0x10 else False
|
args.mapshuffle[p] = True if settings[7] & 0x20 else False
|
||||||
args.shufflebosses[p] = r(boss_mode)[(settings[6] & 0xc) >> 2]
|
args.compassshuffle[p] = True if settings[7] & 0x10 else False
|
||||||
args.shuffleenemies[p] = r(enemy_mode)[settings[6] & 0x3]
|
args.shufflebosses[p] = r(boss_mode)[(settings[7] & 0xc) >> 2]
|
||||||
args.enemy_health[p] = r(e_health)[(settings[7] & 0xE0) >> 5]
|
args.shuffleenemies[p] = r(enemy_mode)[settings[7] & 0x3]
|
||||||
args.enemy_damage[p] = r(e_dmg)[(settings[7] & 0x18) >> 3]
|
|
||||||
|
args.enemy_health[p] = r(e_health)[(settings[8] & 0xE0) >> 5]
|
||||||
|
args.enemy_damage[p] = r(e_dmg)[(settings[8] & 0x18) >> 3]
|
||||||
args.shufflepots[p] = True if settings[7] & 0x4 else False
|
args.shufflepots[p] = True if settings[7] & 0x4 else False
|
||||||
args.bombbag[p] = True if settings[7] & 0x2 else False
|
args.bombbag[p] = True if settings[8] & 0x2 else False
|
||||||
args.shufflelinks[p] = True if settings[7] & 0x1 else False
|
args.shufflelinks[p] = True if settings[8] & 0x1 else False
|
||||||
if len(settings) > 8:
|
if len(settings) > 9:
|
||||||
args.restrict_boss_items[p] = True if r(rb_mode)[(settings[8] & 0x80) >> 6] else False
|
args.restrict_boss_items[p] = r(rb_mode)[(settings[9] & 0x80) >> 6]
|
||||||
|
|
||||||
|
|
||||||
class KeyRuleType(FastEnum):
|
class KeyRuleType(FastEnum):
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
if ret.keysanity:
|
if ret.keysanity:
|
||||||
ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = [True] * 4
|
ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = [True] * 4
|
||||||
|
|
||||||
|
if ret.keydropshuffle:
|
||||||
|
ret.dropshuffle = True
|
||||||
|
ret.pottery = 'keys' if ret.pottery == 'none' else ret.pottery
|
||||||
|
|
||||||
if multiargs.multi:
|
if multiargs.multi:
|
||||||
defaults = copy.deepcopy(ret)
|
defaults = copy.deepcopy(ret)
|
||||||
for player in range(1, multiargs.multi + 1):
|
for player in range(1, multiargs.multi + 1):
|
||||||
@@ -101,9 +105,9 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'pseudoboots',
|
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'pseudoboots',
|
||||||
'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
|
'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
|
||||||
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||||
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep',
|
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
|
||||||
'remote_items', 'shopsanity', 'keydropshuffle', 'mixed_travel', 'standardize_palettes', 'code',
|
'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery',
|
||||||
'reduce_flashing', 'shuffle_sfx']:
|
'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx']:
|
||||||
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})
|
||||||
@@ -150,7 +154,6 @@ def parse_settings():
|
|||||||
"overworld_map": "default",
|
"overworld_map": "default",
|
||||||
"pseudoboots": False,
|
"pseudoboots": False,
|
||||||
|
|
||||||
"shufflepots": False,
|
|
||||||
"shuffleenemies": "none",
|
"shuffleenemies": "none",
|
||||||
"shufflebosses": "none",
|
"shufflebosses": "none",
|
||||||
"enemy_damage": "default",
|
"enemy_damage": "default",
|
||||||
@@ -158,7 +161,10 @@ def parse_settings():
|
|||||||
"enemizercli": os.path.join(".", "EnemizerCLI", "EnemizerCLI.Core"),
|
"enemizercli": os.path.join(".", "EnemizerCLI", "EnemizerCLI.Core"),
|
||||||
|
|
||||||
"shopsanity": False,
|
"shopsanity": False,
|
||||||
"keydropshuffle": False,
|
'keydropshuffle': False,
|
||||||
|
'dropshuffle': False,
|
||||||
|
'pottery': 'none',
|
||||||
|
'shufflepots': False,
|
||||||
"mapshuffle": False,
|
"mapshuffle": False,
|
||||||
"compassshuffle": False,
|
"compassshuffle": False,
|
||||||
"keyshuffle": False,
|
"keyshuffle": False,
|
||||||
|
|||||||
+35
-13
@@ -6,6 +6,7 @@ from enum import unique, Flag
|
|||||||
from typing import DefaultDict, Dict, List
|
from typing import DefaultDict, Dict, List
|
||||||
|
|
||||||
from BaseClasses import RegionType, Region, Door, DoorType, Direction, Sector, CrystalBarrier, DungeonInfo, dungeon_keys
|
from BaseClasses import RegionType, Region, Door, DoorType, Direction, Sector, CrystalBarrier, DungeonInfo, dungeon_keys
|
||||||
|
from BaseClasses import PotFlags, LocationType
|
||||||
from Doors import reset_portals
|
from Doors import reset_portals
|
||||||
from Dungeons import dungeon_regions, region_starts, standard_starts, split_region_starts
|
from Dungeons import dungeon_regions, region_starts, standard_starts, split_region_starts
|
||||||
from Dungeons import dungeon_bigs, dungeon_hints
|
from Dungeons import dungeon_bigs, dungeon_hints
|
||||||
@@ -378,7 +379,7 @@ def choose_portals(world, player):
|
|||||||
if world.doorShuffle[player] in ['basic', 'crossed']:
|
if world.doorShuffle[player] in ['basic', 'crossed']:
|
||||||
cross_flag = world.doorShuffle[player] == 'crossed'
|
cross_flag = world.doorShuffle[player] == 'crossed'
|
||||||
# key drops allow the big key in the right place in Desert Tiles 2
|
# key drops allow the big key in the right place in Desert Tiles 2
|
||||||
bk_shuffle = world.bigkeyshuffle[player] or world.keydropshuffle[player]
|
bk_shuffle = world.bigkeyshuffle[player] or world.dropshuffle[player]
|
||||||
std_flag = world.mode[player] == 'standard'
|
std_flag = world.mode[player] == 'standard'
|
||||||
# roast incognito doors
|
# roast incognito doors
|
||||||
world.get_room(0x60, player).delete(5)
|
world.get_room(0x60, player).delete(5)
|
||||||
@@ -994,10 +995,15 @@ def cross_dungeon(world, player):
|
|||||||
|
|
||||||
assign_cross_keys(dungeon_builders, world, player)
|
assign_cross_keys(dungeon_builders, world, player)
|
||||||
all_dungeon_items_cnt = len(list(y for x in world.dungeons if x.player == player for y in x.all_items))
|
all_dungeon_items_cnt = len(list(y for x in world.dungeons if x.player == player for y in x.all_items))
|
||||||
if world.keydropshuffle[player]:
|
target_items = 34
|
||||||
target_items = 35 if world.retro[player] else 96
|
if world.retro[player]:
|
||||||
|
target_items += 1 if world.dropshuffle[player] else 0 # the hc big key
|
||||||
else:
|
else:
|
||||||
target_items = 34 if world.retro[player] else 63
|
target_items += 29 # small keys in chests
|
||||||
|
if world.dropshuffle[player]:
|
||||||
|
target_items += 14 # 13 dropped smalls + 1 big
|
||||||
|
if world.pottery[player] != 'none':
|
||||||
|
target_items += 19 # 19 pot keys
|
||||||
d_items = target_items - all_dungeon_items_cnt
|
d_items = target_items - all_dungeon_items_cnt
|
||||||
world.pool_adjustment[player] = d_items
|
world.pool_adjustment[player] = d_items
|
||||||
smooth_door_pairs(world, player)
|
smooth_door_pairs(world, player)
|
||||||
@@ -1055,7 +1061,11 @@ def assign_cross_keys(dungeon_builders, world, player):
|
|||||||
logging.getLogger('').info(world.fish.translate("cli", "cli", "shuffling.keydoors"))
|
logging.getLogger('').info(world.fish.translate("cli", "cli", "shuffling.keydoors"))
|
||||||
start = time.process_time()
|
start = time.process_time()
|
||||||
if world.retro[player]:
|
if world.retro[player]:
|
||||||
remaining = 61 if world.keydropshuffle[player] else 29
|
remaining = 29
|
||||||
|
if world.dropshuffle[player]:
|
||||||
|
remaining += 13
|
||||||
|
if world.pottery[player] in ['keys', 'lottery']:
|
||||||
|
remaining += 19
|
||||||
else:
|
else:
|
||||||
remaining = len(list(x for dgn in world.dungeons if dgn.player == player for x in dgn.small_keys))
|
remaining = len(list(x for dgn in world.dungeons if dgn.player == player for x in dgn.small_keys))
|
||||||
total_keys = remaining
|
total_keys = remaining
|
||||||
@@ -1074,7 +1084,6 @@ def assign_cross_keys(dungeon_builders, world, player):
|
|||||||
total_candidates += builder.key_doors_num
|
total_candidates += builder.key_doors_num
|
||||||
start_regions_map[name] = start_regions
|
start_regions_map[name] = start_regions
|
||||||
|
|
||||||
|
|
||||||
# Step 2: Initial Key Number Assignment & Calculate Flexibility
|
# Step 2: Initial Key Number Assignment & Calculate Flexibility
|
||||||
for name, builder in dungeon_builders.items():
|
for name, builder in dungeon_builders.items():
|
||||||
calculated = int(round(builder.key_doors_num*total_keys/total_candidates))
|
calculated = int(round(builder.key_doors_num*total_keys/total_candidates))
|
||||||
@@ -1251,6 +1260,12 @@ def refine_hints(dungeon_builders):
|
|||||||
for region in builder.master_sector.regions:
|
for region in builder.master_sector.regions:
|
||||||
for location in region.locations:
|
for location in region.locations:
|
||||||
if not location.event and '- Boss' not in location.name and '- Prize' not in location.name and location.name != 'Sanctuary':
|
if not location.event and '- Boss' not in location.name and '- Prize' not in location.name and location.name != 'Sanctuary':
|
||||||
|
if location.type == LocationType.Pot and location.pot:
|
||||||
|
hint_text = ('under a block' if location.pot.flags & PotFlags.Block else 'in a pot')
|
||||||
|
location.hint_text = f'{hint_text} {dungeon_hints[name]}'
|
||||||
|
elif location.type == LocationType.Drop:
|
||||||
|
location.hint_text = f'dropped {dungeon_hints[name]}'
|
||||||
|
else:
|
||||||
location.hint_text = dungeon_hints[name]
|
location.hint_text = dungeon_hints[name]
|
||||||
|
|
||||||
|
|
||||||
@@ -2105,6 +2120,7 @@ logical_connections = [
|
|||||||
('Hera Startile Wide Crystal Exit', 'Hera Startile Wide'),
|
('Hera Startile Wide Crystal Exit', 'Hera Startile Wide'),
|
||||||
('Hera Big Chest Hook Path', 'Hera Big Chest Landing'),
|
('Hera Big Chest Hook Path', 'Hera Big Chest Landing'),
|
||||||
('Hera Big Chest Landing Exit', 'Hera 4F'),
|
('Hera Big Chest Landing Exit', 'Hera 4F'),
|
||||||
|
('Hera 5F Orange Path', 'Hera 5F Pot Block'),
|
||||||
|
|
||||||
('PoD Pit Room Block Path N', 'PoD Pit Room Blocked'),
|
('PoD Pit Room Block Path N', 'PoD Pit Room Blocked'),
|
||||||
('PoD Pit Room Block Path S', 'PoD Pit Room'),
|
('PoD Pit Room Block Path S', 'PoD Pit Room'),
|
||||||
@@ -2168,6 +2184,7 @@ logical_connections = [
|
|||||||
('Swamp Trench 1 Departure Approach', 'Swamp Trench 1 Approach'),
|
('Swamp Trench 1 Departure Approach', 'Swamp Trench 1 Approach'),
|
||||||
('Swamp Trench 1 Departure Key', 'Swamp Trench 1 Key Ledge'),
|
('Swamp Trench 1 Departure Key', 'Swamp Trench 1 Key Ledge'),
|
||||||
('Swamp Hub Hook Path', 'Swamp Hub North Ledge'),
|
('Swamp Hub Hook Path', 'Swamp Hub North Ledge'),
|
||||||
|
('Swamp Hub Side Hook Path', 'Swamp Hub Side Ledges'),
|
||||||
('Swamp Hub North Ledge Drop Down', 'Swamp Hub'),
|
('Swamp Hub North Ledge Drop Down', 'Swamp Hub'),
|
||||||
('Swamp Crystal Switch Outer to Inner Barrier - Blue', 'Swamp Crystal Switch Inner'),
|
('Swamp Crystal Switch Outer to Inner Barrier - Blue', 'Swamp Crystal Switch Inner'),
|
||||||
('Swamp Crystal Switch Outer to Ranged Crystal', 'Swamp Crystal Switch Outer - Ranged Crystal'),
|
('Swamp Crystal Switch Outer to Ranged Crystal', 'Swamp Crystal Switch Outer - Ranged Crystal'),
|
||||||
@@ -2205,7 +2222,9 @@ logical_connections = [
|
|||||||
('Thieves Hellway Blue Barrier', 'Thieves Hellway N Crystal'),
|
('Thieves Hellway Blue Barrier', 'Thieves Hellway N Crystal'),
|
||||||
('Thieves Hellway Crystal Blue Barrier', 'Thieves Hellway'),
|
('Thieves Hellway Crystal Blue Barrier', 'Thieves Hellway'),
|
||||||
('Thieves Attic Orange Barrier', 'Thieves Attic Hint'),
|
('Thieves Attic Orange Barrier', 'Thieves Attic Hint'),
|
||||||
|
('Thieves Attic Blue Barrier', 'Thieves Attic Switch'),
|
||||||
('Thieves Attic Hint Orange Barrier', 'Thieves Attic'),
|
('Thieves Attic Hint Orange Barrier', 'Thieves Attic'),
|
||||||
|
('Thieves Attic Switch Blue Barrier', 'Thieves Attic'),
|
||||||
('Thieves Basement Block Path', 'Thieves Blocked Entry'),
|
('Thieves Basement Block Path', 'Thieves Blocked Entry'),
|
||||||
('Thieves Blocked Entry Path', 'Thieves Basement Block'),
|
('Thieves Blocked Entry Path', 'Thieves Basement Block'),
|
||||||
('Thieves Conveyor Bridge Block Path', 'Thieves Conveyor Block'),
|
('Thieves Conveyor Bridge Block Path', 'Thieves Conveyor Block'),
|
||||||
@@ -2302,16 +2321,18 @@ logical_connections = [
|
|||||||
('TR Crystal Maze End to Interior Barrier - Blue', 'TR Crystal Maze Interior'),
|
('TR Crystal Maze End to Interior Barrier - Blue', 'TR Crystal Maze Interior'),
|
||||||
('TR Crystal Maze End to Ranged Crystal', 'TR Crystal Maze End - Ranged Crystal'),
|
('TR Crystal Maze End to Ranged Crystal', 'TR Crystal Maze End - Ranged Crystal'),
|
||||||
('TR Crystal Maze End Ranged Crystal Exit', 'TR Crystal Maze End'),
|
('TR Crystal Maze End Ranged Crystal Exit', 'TR Crystal Maze End'),
|
||||||
|
('TR Final Abyss Balcony Path', 'TR Final Abyss Ledge'),
|
||||||
|
('TR Final Abyss Ledge Path', 'TR Final Abyss Balcony'),
|
||||||
|
|
||||||
('GT Blocked Stairs Block Path', 'GT Big Chest'),
|
('GT Blocked Stairs Block Path', 'GT Big Chest'),
|
||||||
('GT Speed Torch South Path', 'GT Speed Torch'),
|
('GT Speed Torch South Path', 'GT Speed Torch'),
|
||||||
('GT Speed Torch North Path', 'GT Speed Torch Upper'),
|
('GT Speed Torch North Path', 'GT Speed Torch Upper'),
|
||||||
('GT Hookshot East-North Path', 'GT Hookshot North Platform'),
|
('GT Hookshot East-Mid Path', 'GT Hookshot Mid Platform'),
|
||||||
('GT Hookshot East-South Path', 'GT Hookshot South Platform'),
|
('GT Hookshot Mid-East Path', 'GT Hookshot East Platform'),
|
||||||
('GT Hookshot North-East Path', 'GT Hookshot East Platform'),
|
('GT Hookshot North-Mid Path', 'GT Hookshot Mid Platform'),
|
||||||
('GT Hookshot North-South Path', 'GT Hookshot South Platform'),
|
('GT Hookshot Mid-North Path', 'GT Hookshot North Platform'),
|
||||||
('GT Hookshot South-East Path', 'GT Hookshot East Platform'),
|
('GT Hookshot South-Mid Path', 'GT Hookshot Mid Platform'),
|
||||||
('GT Hookshot South-North Path', 'GT Hookshot North Platform'),
|
('GT Hookshot Mid-South Path', 'GT Hookshot South Platform'),
|
||||||
('GT Hookshot Platform Blue Barrier', 'GT Hookshot South Entry'),
|
('GT Hookshot Platform Blue Barrier', 'GT Hookshot South Entry'),
|
||||||
('GT Hookshot Platform Barrier Bypass', 'GT Hookshot South Entry'),
|
('GT Hookshot Platform Barrier Bypass', 'GT Hookshot South Entry'),
|
||||||
('GT Hookshot Entry Blue Barrier', 'GT Hookshot South Platform'),
|
('GT Hookshot Entry Blue Barrier', 'GT Hookshot South Platform'),
|
||||||
@@ -3009,7 +3030,8 @@ palette_map = {
|
|||||||
'Tower of Hera': (0x6, None),
|
'Tower of Hera': (0x6, None),
|
||||||
'Thieves Town': (0x17, None), # the attic uses 0x23
|
'Thieves Town': (0x17, None), # the attic uses 0x23
|
||||||
'Turtle Rock': (0x18, 0x19, 'TR Boss SW'),
|
'Turtle Rock': (0x18, 0x19, 'TR Boss SW'),
|
||||||
'Ganons Tower': (0x28, 0x1b, 'GT Agahnim 2 SW'), # other palettes: 0x1a (other) 0x24 (Gauntlet - Lanmo) 0x25 (conveyor-torch-wizzrode moldorm pit f5?)
|
'Ganons Tower': (0x28, 0x1b, 'GT Agahnim 2 SW'),
|
||||||
|
# other palettes: 0x1a (other) 0x24 (Gauntlet - Lanmo) 0x25 (conveyor-torch-wizzrobe moldorm pit f5?)
|
||||||
}
|
}
|
||||||
|
|
||||||
# implications:
|
# implications:
|
||||||
|
|||||||
@@ -309,6 +309,7 @@ def create_doors(world, player):
|
|||||||
create_door(player, 'Hera 5F Star Hole', Hole),
|
create_door(player, 'Hera 5F Star Hole', Hole),
|
||||||
create_door(player, 'Hera 5F Pothole Chain', Hole),
|
create_door(player, 'Hera 5F Pothole Chain', Hole),
|
||||||
create_door(player, 'Hera 5F Normal Holes', Hole),
|
create_door(player, 'Hera 5F Normal Holes', Hole),
|
||||||
|
create_door(player, 'Hera 5F Orange Path', Lgcl),
|
||||||
create_door(player, 'Hera Fairies\' Warp', Warp),
|
create_door(player, 'Hera Fairies\' Warp', Warp),
|
||||||
create_door(player, 'Hera Boss Down Stairs', Sprl).dir(Dn, 0x07, 0, HTH).ss(S, 0x61, 0xb0).kill(),
|
create_door(player, 'Hera Boss Down Stairs', Sprl).dir(Dn, 0x07, 0, HTH).ss(S, 0x61, 0xb0).kill(),
|
||||||
create_door(player, 'Hera Boss Outer Hole', Hole),
|
create_door(player, 'Hera Boss Outer Hole', Hole),
|
||||||
@@ -500,6 +501,7 @@ def create_doors(world, player):
|
|||||||
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),
|
||||||
|
create_door(player, 'Swamp Hub Side Hook Path', Lgcl),
|
||||||
create_door(player, 'Swamp Hub Dead Ledge EN', Nrml).dir(Ea, 0x36, Top, High).pos(0),
|
create_door(player, 'Swamp Hub Dead Ledge EN', Nrml).dir(Ea, 0x36, Top, High).pos(0),
|
||||||
create_door(player, 'Swamp Hub North Ledge N', Nrml).dir(No, 0x36, Mid, High).small_key().pos(1),
|
create_door(player, 'Swamp Hub North Ledge N', Nrml).dir(No, 0x36, Mid, High).small_key().pos(1),
|
||||||
create_door(player, 'Swamp Hub North Ledge Drop Down', Lgcl),
|
create_door(player, 'Swamp Hub North Ledge Drop Down', Lgcl),
|
||||||
@@ -684,7 +686,9 @@ def create_doors(world, player):
|
|||||||
create_door(player, 'Thieves Attic Down Stairs', Sprl).dir(Dn, 0x64, 0, HTH).ss(Z, 0x11, 0x80, True, True),
|
create_door(player, 'Thieves Attic Down Stairs', Sprl).dir(Dn, 0x64, 0, HTH).ss(Z, 0x11, 0x80, True, True),
|
||||||
create_door(player, 'Thieves Attic ES', Intr).dir(Ea, 0x64, Bot, High).pos(0),
|
create_door(player, 'Thieves Attic ES', Intr).dir(Ea, 0x64, Bot, High).pos(0),
|
||||||
create_door(player, 'Thieves Attic Orange Barrier', Lgcl),
|
create_door(player, 'Thieves Attic Orange Barrier', Lgcl),
|
||||||
|
create_door(player, 'Thieves Attic Blue Barrier', Lgcl),
|
||||||
create_door(player, 'Thieves Attic Hint Orange Barrier', Lgcl),
|
create_door(player, 'Thieves Attic Hint Orange Barrier', Lgcl),
|
||||||
|
create_door(player, 'Thieves Attic Switch Blue Barrier', Lgcl),
|
||||||
create_door(player, 'Thieves Cricket Hall Left WS', Intr).dir(We, 0x64, Bot, High).pos(0),
|
create_door(player, 'Thieves Cricket Hall Left WS', Intr).dir(We, 0x64, Bot, High).pos(0),
|
||||||
create_door(player, 'Thieves Cricket Hall Left Edge', Open).dir(Ea, 0x64, None, High).edge(0, X, 0x30),
|
create_door(player, 'Thieves Cricket Hall Left Edge', Open).dir(Ea, 0x64, None, High).edge(0, X, 0x30),
|
||||||
create_door(player, 'Thieves Cricket Hall Right Edge', Open).dir(We, 0x65, None, High).edge(0, Z, 0x30),
|
create_door(player, 'Thieves Cricket Hall Right Edge', Open).dir(We, 0x65, None, High).edge(0, Z, 0x30),
|
||||||
@@ -1048,6 +1052,8 @@ def create_doors(world, player):
|
|||||||
create_door(player, 'TR Crystal Maze End Ranged Crystal Exit', Lgcl),
|
create_door(player, 'TR Crystal Maze End Ranged Crystal Exit', Lgcl),
|
||||||
create_door(player, 'TR Crystal Maze North Stairs', StrS).dir(No, 0xc4, Mid, High),
|
create_door(player, 'TR Crystal Maze North Stairs', StrS).dir(No, 0xc4, Mid, High),
|
||||||
create_door(player, 'TR Final Abyss South Stairs', StrS).dir(So, 0xb4, Mid, High),
|
create_door(player, 'TR Final Abyss South Stairs', StrS).dir(So, 0xb4, Mid, High),
|
||||||
|
create_door(player, 'TR Final Abyss Balcony Path', Lgcl),
|
||||||
|
create_door(player, 'TR Final Abyss Ledge Path', Lgcl),
|
||||||
create_door(player, 'TR Final Abyss NW', Nrml).dir(No, 0xb4, Left, High).big_key().pos(0),
|
create_door(player, 'TR Final Abyss NW', Nrml).dir(No, 0xb4, Left, High).big_key().pos(0),
|
||||||
create_door(player, 'TR Boss SW', Nrml).dir(So, 0xa4, Left, High).no_exit().trap(0x4).pos(0), # .portal(Z, 0x00), -enemizer doesn't work
|
create_door(player, 'TR Boss SW', Nrml).dir(So, 0xa4, Left, High).no_exit().trap(0x4).pos(0), # .portal(Z, 0x00), -enemizer doesn't work
|
||||||
|
|
||||||
@@ -1098,12 +1104,12 @@ def create_doors(world, player):
|
|||||||
create_door(player, 'GT Conveyor Cross EN', Nrml).dir(Ea, 0x8b, Top, High).pos(2),
|
create_door(player, 'GT Conveyor Cross EN', Nrml).dir(Ea, 0x8b, Top, High).pos(2),
|
||||||
create_door(player, 'GT Conveyor Cross WN', Intr).dir(We, 0x8b, Top, High).pos(0),
|
create_door(player, 'GT Conveyor Cross WN', Intr).dir(We, 0x8b, Top, High).pos(0),
|
||||||
create_door(player, 'GT Hookshot EN', Intr).dir(Ea, 0x8b, Top, High).pos(0),
|
create_door(player, 'GT Hookshot EN', Intr).dir(Ea, 0x8b, Top, High).pos(0),
|
||||||
create_door(player, 'GT Hookshot East-North Path', Lgcl),
|
create_door(player, 'GT Hookshot East-Mid Path', Lgcl),
|
||||||
create_door(player, 'GT Hookshot East-South Path', Lgcl),
|
create_door(player, 'GT Hookshot Mid-East Path', Lgcl),
|
||||||
create_door(player, 'GT Hookshot North-East Path', Lgcl),
|
create_door(player, 'GT Hookshot North-Mid Path', Lgcl),
|
||||||
create_door(player, 'GT Hookshot North-South Path', Lgcl),
|
create_door(player, 'GT Hookshot Mid-North Path', Lgcl),
|
||||||
create_door(player, 'GT Hookshot South-East Path', Lgcl),
|
create_door(player, 'GT Hookshot South-Mid Path', Lgcl),
|
||||||
create_door(player, 'GT Hookshot South-North Path', Lgcl),
|
create_door(player, 'GT Hookshot Mid-South Path', Lgcl),
|
||||||
create_door(player, 'GT Hookshot Platform Blue Barrier', Lgcl),
|
create_door(player, 'GT Hookshot Platform Blue Barrier', Lgcl),
|
||||||
create_door(player, 'GT Hookshot Entry Blue Barrier', Lgcl),
|
create_door(player, 'GT Hookshot Entry Blue Barrier', Lgcl),
|
||||||
create_door(player, 'GT Hookshot Platform Barrier Bypass', Lgcl),
|
create_door(player, 'GT Hookshot Platform Barrier Bypass', Lgcl),
|
||||||
@@ -1291,6 +1297,7 @@ def create_doors(world, player):
|
|||||||
world.get_door('Hera Beetles Holes Front', player).c_switch()
|
world.get_door('Hera Beetles Holes Front', player).c_switch()
|
||||||
world.get_door('Hera Beetles Holes Landing', player).c_switch()
|
world.get_door('Hera Beetles Holes Landing', player).c_switch()
|
||||||
world.get_door('Hera Startile Wide Crystal Exit', player).c_switch()
|
world.get_door('Hera Startile Wide Crystal Exit', player).c_switch()
|
||||||
|
world.get_door('Hera 5F Orange Path', player).barrier(CrystalBarrier.Orange)
|
||||||
|
|
||||||
world.get_door('PoD Arena North to Landing Barrier - Orange', player).barrier(CrystalBarrier.Orange)
|
world.get_door('PoD Arena North to Landing Barrier - Orange', player).barrier(CrystalBarrier.Orange)
|
||||||
world.get_door('PoD Arena Main to Landing Barrier - Blue', player).barrier(CrystalBarrier.Blue)
|
world.get_door('PoD Arena Main to Landing Barrier - Blue', player).barrier(CrystalBarrier.Blue)
|
||||||
@@ -1345,7 +1352,9 @@ def create_doors(world, player):
|
|||||||
world.get_door('Thieves Hellway Orange Barrier', player).barrier(CrystalBarrier.Orange)
|
world.get_door('Thieves Hellway Orange Barrier', player).barrier(CrystalBarrier.Orange)
|
||||||
world.get_door('Thieves Hellway Crystal Orange Barrier', player).barrier(CrystalBarrier.Orange)
|
world.get_door('Thieves Hellway Crystal Orange Barrier', player).barrier(CrystalBarrier.Orange)
|
||||||
world.get_door('Thieves Attic Orange Barrier', player).barrier(CrystalBarrier.Orange)
|
world.get_door('Thieves Attic Orange Barrier', player).barrier(CrystalBarrier.Orange)
|
||||||
|
world.get_door('Thieves Attic Blue Barrier', player).barrier(CrystalBarrier.Blue)
|
||||||
world.get_door('Thieves Attic Hint Orange Barrier', player).barrier(CrystalBarrier.Orange)
|
world.get_door('Thieves Attic Hint Orange Barrier', player).barrier(CrystalBarrier.Orange)
|
||||||
|
world.get_door('Thieves Attic Switch Blue Barrier', player).barrier(CrystalBarrier.Blue)
|
||||||
|
|
||||||
world.get_door('Ice Bomb Drop SE', player).c_switch()
|
world.get_door('Ice Bomb Drop SE', player).c_switch()
|
||||||
world.get_door('Ice Conveyor Crystal Exit', player).c_switch()
|
world.get_door('Ice Conveyor Crystal Exit', player).c_switch()
|
||||||
@@ -1421,8 +1430,7 @@ def create_doors(world, player):
|
|||||||
world.get_door('GT Crystal Conveyor Ranged Crystal Exit', player).c_switch()
|
world.get_door('GT Crystal Conveyor Ranged Crystal Exit', player).c_switch()
|
||||||
world.get_door('GT Crystal Conveyor Corner Ranged Crystal Exit', player).c_switch()
|
world.get_door('GT Crystal Conveyor Corner Ranged Crystal Exit', player).c_switch()
|
||||||
world.get_door('GT Crystal Conveyor Corner to Left Bypass', player).barrier(CrystalBarrier.Blue)
|
world.get_door('GT Crystal Conveyor Corner to Left Bypass', player).barrier(CrystalBarrier.Blue)
|
||||||
world.get_door('GT Hookshot South-North Path', player).c_switch()
|
world.get_door('GT Hookshot South-Mid Path', player).c_switch()
|
||||||
world.get_door('GT Hookshot South-East Path', player).c_switch()
|
|
||||||
world.get_door('GT Hookshot ES', player).c_switch()
|
world.get_door('GT Hookshot ES', player).c_switch()
|
||||||
world.get_door('GT Hookshot Platform Barrier Bypass', player).barrier(CrystalBarrier.Orange)
|
world.get_door('GT Hookshot Platform Barrier Bypass', player).barrier(CrystalBarrier.Orange)
|
||||||
world.get_door('GT Hookshot Platform Blue Barrier', player).barrier(CrystalBarrier.Blue)
|
world.get_door('GT Hookshot Platform Blue Barrier', player).barrier(CrystalBarrier.Blue)
|
||||||
|
|||||||
+74
-12
@@ -1326,7 +1326,17 @@ def create_dungeon_builders(all_sectors, connections_tuple, world, player,
|
|||||||
polarized_sectors[sector] = None
|
polarized_sectors[sector] = None
|
||||||
if bow_sectors:
|
if bow_sectors:
|
||||||
assign_bow_sectors(dungeon_map, bow_sectors, global_pole)
|
assign_bow_sectors(dungeon_map, bow_sectors, global_pole)
|
||||||
assign_location_sectors(dungeon_map, free_location_sectors, global_pole, world, player)
|
leftover = assign_location_sectors_minimal(dungeon_map, free_location_sectors, global_pole, world, player)
|
||||||
|
free_location_sectors = scatter_extra_location_sectors(dungeon_map, leftover, global_pole)
|
||||||
|
for sector in free_location_sectors:
|
||||||
|
if sector.c_switch:
|
||||||
|
crystal_switches[sector] = None
|
||||||
|
elif sector.blue_barrier:
|
||||||
|
crystal_barriers[sector] = None
|
||||||
|
elif sector.polarity().is_neutral():
|
||||||
|
neutral_sectors[sector] = None
|
||||||
|
else:
|
||||||
|
polarized_sectors[sector] = None
|
||||||
leftover = assign_crystal_switch_sectors(dungeon_map, crystal_switches, crystal_barriers, global_pole)
|
leftover = assign_crystal_switch_sectors(dungeon_map, crystal_switches, crystal_barriers, global_pole)
|
||||||
ensure_crystal_switches_reachable(dungeon_map, leftover, polarized_sectors, crystal_barriers, global_pole)
|
ensure_crystal_switches_reachable(dungeon_map, leftover, polarized_sectors, crystal_barriers, global_pole)
|
||||||
for sector in leftover:
|
for sector in leftover:
|
||||||
@@ -1558,21 +1568,45 @@ def assign_bow_sectors(dungeon_map, bow_sectors, global_pole):
|
|||||||
assign_sector(sector_list[i], builder, bow_sectors, global_pole)
|
assign_sector(sector_list[i], builder, bow_sectors, global_pole)
|
||||||
|
|
||||||
|
|
||||||
def assign_location_sectors(dungeon_map, free_location_sectors, global_pole, world, player):
|
def scatter_extra_location_sectors(dungeon_map, free_location_sectors, global_pole):
|
||||||
|
population = [n for n in dungeon_map.keys()]
|
||||||
|
k = round(len(free_location_sectors) * .50)
|
||||||
valid = False
|
valid = False
|
||||||
choices = None
|
choices = None
|
||||||
|
candidates = []
|
||||||
|
sector_list = list(free_location_sectors)
|
||||||
|
while not valid:
|
||||||
|
candidates = random.sample(sector_list, k=k)
|
||||||
|
choices = random.choices(population, k=len(candidates))
|
||||||
|
sector_dict = defaultdict(list)
|
||||||
|
for i, choice in enumerate(choices):
|
||||||
|
builder = dungeon_map[choice]
|
||||||
|
sector_dict[builder].append(candidates[i])
|
||||||
|
valid = global_pole.is_valid_multi_choice_2(dungeon_map, dungeon_map.values(), sector_dict)
|
||||||
|
for i, choice in enumerate(choices):
|
||||||
|
builder = dungeon_map[choice]
|
||||||
|
assign_sector(candidates[i], builder, free_location_sectors, global_pole)
|
||||||
|
return free_location_sectors
|
||||||
|
|
||||||
|
|
||||||
|
def assign_location_sectors_minimal(dungeon_map, free_location_sectors, global_pole, world, player):
|
||||||
|
valid = False
|
||||||
|
choices = defaultdict(list)
|
||||||
sector_list = list(free_location_sectors)
|
sector_list = list(free_location_sectors)
|
||||||
random.shuffle(sector_list)
|
random.shuffle(sector_list)
|
||||||
orig_location_set = build_orig_location_set(dungeon_map)
|
orig_location_set = build_orig_location_set(dungeon_map)
|
||||||
num_dungeon_items = requested_dungeon_items(world, player)
|
num_dungeon_items = requested_dungeon_items(world, player)
|
||||||
|
d_idx = {builder.name: i for i, builder in enumerate(dungeon_map.values())}
|
||||||
|
next_sector = sector_list.pop()
|
||||||
while not valid:
|
while not valid:
|
||||||
choices, d_idx, totals = weighted_random_locations(dungeon_map, sector_list)
|
choice, totals, location_set = weighted_random_location(dungeon_map, choices, orig_location_set, world, player)
|
||||||
location_set = {x: set(y) for x, y in orig_location_set.items()}
|
if not choice:
|
||||||
for i, sector in enumerate(sector_list):
|
break
|
||||||
d_name = choices[i].name
|
choices[choice].append(next_sector)
|
||||||
choice = d_idx[d_name]
|
if global_pole.is_valid_multi_choice_2(dungeon_map, dungeon_map.values(), choices):
|
||||||
totals[choice] += sector.chest_locations
|
idx = d_idx[choice.name]
|
||||||
location_set[d_name].update(sector.chest_location_set)
|
totals[idx] += next_sector.chest_locations
|
||||||
|
location_set[choice.name].update(next_sector.chest_location_set)
|
||||||
valid = True
|
valid = True
|
||||||
for d_name, idx in d_idx.items():
|
for d_name, idx in d_idx.items():
|
||||||
free_items = count_reserved_locations(world, player, location_set[d_name])
|
free_items = count_reserved_locations(world, player, location_set[d_name])
|
||||||
@@ -1580,11 +1614,39 @@ def assign_location_sectors(dungeon_map, free_location_sectors, global_pole, wor
|
|||||||
if totals[idx] < target:
|
if totals[idx] < target:
|
||||||
valid = False
|
valid = False
|
||||||
break
|
break
|
||||||
for i, choice in enumerate(choices):
|
if not valid:
|
||||||
builder = dungeon_map[choice.name]
|
if len(sector_list) == 0:
|
||||||
assign_sector(sector_list[i], builder, free_location_sectors, global_pole)
|
choices = defaultdict(list)
|
||||||
|
sector_list = list(free_location_sectors)
|
||||||
|
else:
|
||||||
|
next_sector = sector_list.pop()
|
||||||
|
else:
|
||||||
|
choices[choice].remove(next_sector)
|
||||||
|
for builder, choice_list in choices.items():
|
||||||
|
for choice in choice_list:
|
||||||
|
assign_sector(choice, builder, free_location_sectors, global_pole)
|
||||||
|
return free_location_sectors
|
||||||
|
|
||||||
|
|
||||||
|
def weighted_random_location(dungeon_map, choices, orig_location_set, world, player):
|
||||||
|
population = []
|
||||||
|
totals = []
|
||||||
|
location_set = {x: set(y) for x, y in orig_location_set.items()}
|
||||||
|
num_dungeon_items = requested_dungeon_items(world, player)
|
||||||
|
for i, dungeon_builder in enumerate(dungeon_map.values()):
|
||||||
|
ttl = dungeon_builder.location_cnt + sum(sector.chest_locations for sector in choices[dungeon_builder])
|
||||||
|
totals.append(ttl)
|
||||||
|
builder_set = location_set[dungeon_builder.name]
|
||||||
|
builder_set.update(set().union(*(s.chest_location_set for s in choices[dungeon_builder])))
|
||||||
|
free_items = count_reserved_locations(world, player, builder_set)
|
||||||
|
target = max(free_items, 2) + num_dungeon_items
|
||||||
|
if ttl < target:
|
||||||
|
population.append(dungeon_builder)
|
||||||
|
choice = random.choice(population) if len(population) > 0 else None
|
||||||
|
return choice, totals, location_set
|
||||||
|
|
||||||
|
|
||||||
|
# deprecated
|
||||||
def weighted_random_locations(dungeon_map, free_location_sectors):
|
def weighted_random_locations(dungeon_map, free_location_sectors):
|
||||||
population = []
|
population = []
|
||||||
ttl_assigned = 0
|
ttl_assigned = 0
|
||||||
|
|||||||
+29
-27
@@ -84,7 +84,7 @@ hera_regions = [
|
|||||||
'Hera Back - Ranged Crystal', 'Hera Basement Cage', 'Hera Basement Cage - Crystal', 'Hera Tile Room',
|
'Hera Back - Ranged Crystal', 'Hera Basement Cage', 'Hera Basement Cage - Crystal', 'Hera Tile Room',
|
||||||
'Hera Tridorm', 'Hera Tridorm - Crystal', 'Hera Torches', 'Hera Beetles', 'Hera Startile Corner',
|
'Hera Tridorm', 'Hera Tridorm - Crystal', 'Hera Torches', 'Hera Beetles', 'Hera Startile Corner',
|
||||||
'Hera Startile Wide', 'Hera Startile Wide - Crystal', 'Hera 4F', 'Hera Big Chest Landing', 'Hera 5F',
|
'Hera Startile Wide', 'Hera Startile Wide - Crystal', 'Hera 4F', 'Hera Big Chest Landing', 'Hera 5F',
|
||||||
'Hera Fairies', 'Hera Boss', 'Hera Portal'
|
'Hera 5F Pot Block', 'Hera Fairies', 'Hera Boss', 'Hera Portal'
|
||||||
]
|
]
|
||||||
|
|
||||||
tower_regions = [
|
tower_regions = [
|
||||||
@@ -110,15 +110,15 @@ pod_regions = [
|
|||||||
swamp_regions = [
|
swamp_regions = [
|
||||||
'Swamp Lobby', 'Swamp Entrance', 'Swamp Pot Row', 'Swamp Map Ledge', 'Swamp Trench 1 Approach',
|
'Swamp Lobby', 'Swamp Entrance', 'Swamp Pot Row', 'Swamp Map Ledge', 'Swamp Trench 1 Approach',
|
||||||
'Swamp Trench 1 Nexus', 'Swamp Trench 1 Alcove', 'Swamp Trench 1 Key Ledge', 'Swamp Trench 1 Departure',
|
'Swamp Trench 1 Nexus', 'Swamp Trench 1 Alcove', 'Swamp Trench 1 Key Ledge', 'Swamp Trench 1 Departure',
|
||||||
'Swamp Hammer Switch', 'Swamp Hub', 'Swamp Hub Dead Ledge', 'Swamp Hub North Ledge', 'Swamp Donut Top',
|
'Swamp Hammer Switch', 'Swamp Hub', 'Swamp Hub Side Ledges', 'Swamp Hub Dead Ledge', 'Swamp Hub North Ledge',
|
||||||
'Swamp Donut Bottom', 'Swamp Compass Donut', 'Swamp Crystal Switch Outer', 'Swamp Crystal Switch Outer - Ranged Crystal',
|
'Swamp Donut Top', 'Swamp Donut Bottom', 'Swamp Compass Donut', 'Swamp Crystal Switch Outer',
|
||||||
'Swamp Crystal Switch Inner', 'Swamp Crystal Switch Inner - Crystal', 'Swamp Shortcut', 'Swamp Trench 2 Pots',
|
'Swamp Crystal Switch Outer - Ranged Crystal', 'Swamp Crystal Switch Inner', 'Swamp Crystal Switch Inner - Crystal',
|
||||||
'Swamp Trench 2 Blocks', 'Swamp Trench 2 Alcove', 'Swamp Trench 2 Departure', 'Swamp Big Key Ledge',
|
'Swamp Shortcut', 'Swamp Trench 2 Pots', 'Swamp Trench 2 Blocks', 'Swamp Trench 2 Alcove',
|
||||||
'Swamp West Shallows', 'Swamp West Block Path', 'Swamp West Ledge', 'Swamp Barrier Ledge', 'Swamp Barrier',
|
'Swamp Trench 2 Departure', 'Swamp Big Key Ledge', 'Swamp West Shallows', 'Swamp West Block Path',
|
||||||
'Swamp Attic', 'Swamp Push Statue', 'Swamp Shooters', 'Swamp Left Elbow', 'Swamp Right Elbow', 'Swamp Drain Left',
|
'Swamp West Ledge', 'Swamp Barrier Ledge', 'Swamp Barrier', 'Swamp Attic', 'Swamp Push Statue', 'Swamp Shooters',
|
||||||
'Swamp Drain Right', 'Swamp Flooded Room', 'Swamp Flooded Spot', 'Swamp Basement Shallows', 'Swamp Waterfall Room',
|
'Swamp Left Elbow', 'Swamp Right Elbow', 'Swamp Drain Left', 'Swamp Drain Right', 'Swamp Flooded Room',
|
||||||
'Swamp Refill', 'Swamp Behind Waterfall', 'Swamp C', 'Swamp Waterway', 'Swamp I', 'Swamp T', 'Swamp Boss',
|
'Swamp Flooded Spot', 'Swamp Basement Shallows', 'Swamp Waterfall Room', 'Swamp Refill', 'Swamp Behind Waterfall',
|
||||||
'Swamp Portal'
|
'Swamp C', 'Swamp Waterway', 'Swamp I', 'Swamp T', 'Swamp Boss', 'Swamp Portal'
|
||||||
]
|
]
|
||||||
|
|
||||||
skull_regions = [
|
skull_regions = [
|
||||||
@@ -135,10 +135,10 @@ thieves_regions = [
|
|||||||
'Thieves Big Chest Nook', 'Thieves Hallway', 'Thieves Boss', 'Thieves Pot Alcove Mid', 'Thieves Pot Alcove Bottom',
|
'Thieves Big Chest Nook', 'Thieves Hallway', 'Thieves Boss', 'Thieves Pot Alcove Mid', 'Thieves Pot Alcove Bottom',
|
||||||
'Thieves Pot Alcove Top', 'Thieves Conveyor Maze', 'Thieves Spike Track', 'Thieves Hellway',
|
'Thieves Pot Alcove Top', 'Thieves Conveyor Maze', 'Thieves Spike Track', 'Thieves Hellway',
|
||||||
'Thieves Hellway N Crystal', 'Thieves Hellway S Crystal', 'Thieves Triple Bypass', 'Thieves Spike Switch',
|
'Thieves Hellway N Crystal', 'Thieves Hellway S Crystal', 'Thieves Triple Bypass', 'Thieves Spike Switch',
|
||||||
'Thieves Attic', 'Thieves Attic Hint', 'Thieves Cricket Hall Left', 'Thieves Cricket Hall Right',
|
'Thieves Attic', 'Thieves Attic Hint', 'Thieves Attic Switch', 'Thieves Cricket Hall Left',
|
||||||
'Thieves Attic Window', 'Thieves Basement Block', 'Thieves Blocked Entry', 'Thieves Lonely Zazak',
|
'Thieves Cricket Hall Right', 'Thieves Attic Window', 'Thieves Basement Block', 'Thieves Blocked Entry',
|
||||||
"Thieves Blind's Cell", "Thieves Blind's Cell Interior", 'Thieves Conveyor Bridge', 'Thieves Conveyor Block',
|
'Thieves Lonely Zazak', "Thieves Blind's Cell", "Thieves Blind's Cell Interior", 'Thieves Conveyor Bridge',
|
||||||
'Thieves Big Chest Room', 'Thieves Trap', 'Thieves Town Portal'
|
'Thieves Conveyor Block', 'Thieves Big Chest Room', 'Thieves Trap', 'Thieves Town Portal'
|
||||||
]
|
]
|
||||||
|
|
||||||
ice_regions = [
|
ice_regions = [
|
||||||
@@ -170,27 +170,29 @@ mire_regions = [
|
|||||||
tr_regions = [
|
tr_regions = [
|
||||||
'TR Main Lobby', 'TR Lobby Ledge', 'TR Compass Room', 'TR Hub', 'TR Torches Ledge', 'TR Torches', 'TR Roller Room',
|
'TR Main Lobby', 'TR Lobby Ledge', 'TR Compass Room', 'TR Hub', 'TR Torches Ledge', 'TR Torches', 'TR Roller Room',
|
||||||
'TR Tile Room', 'TR Refill', 'TR Pokey 1', 'TR Chain Chomps Top', 'TR Chain Chomps Top - Crystal',
|
'TR Tile Room', 'TR Refill', 'TR Pokey 1', 'TR Chain Chomps Top', 'TR Chain Chomps Top - Crystal',
|
||||||
'TR Chain Chomps Bottom', 'TR Chain Chomps Bottom - Ranged Crystal', 'TR Pipe Pit', 'TR Pipe Ledge', 'TR Lava Dual Pipes',
|
'TR Chain Chomps Bottom', 'TR Chain Chomps Bottom - Ranged Crystal', 'TR Pipe Pit', 'TR Pipe Ledge',
|
||||||
'TR Lava Island', 'TR Lava Escape', 'TR Pokey 2 Top', 'TR Pokey 2 Top - Crystal', 'TR Pokey 2 Bottom', 'TR Pokey 2 Bottom - Ranged Crystal',
|
'TR Lava Dual Pipes', 'TR Lava Island', 'TR Lava Escape', 'TR Pokey 2 Top', 'TR Pokey 2 Top - Crystal',
|
||||||
'TR Twin Pokeys', 'TR Hallway', 'TR Dodgers', 'TR Big View','TR Big Chest', 'TR Big Chest Entrance',
|
'TR Pokey 2 Bottom', 'TR Pokey 2 Bottom - Ranged Crystal', 'TR Twin Pokeys', 'TR Hallway', 'TR Dodgers',
|
||||||
'TR Lazy Eyes', 'TR Dash Room', 'TR Tongue Pull', 'TR Rupees', 'TR Crystaroller Bottom',
|
'TR Big View','TR Big Chest', 'TR Big Chest Entrance', 'TR Lazy Eyes', 'TR Dash Room', 'TR Tongue Pull',
|
||||||
'TR Crystaroller Middle', 'TR Crystaroller Top', 'TR Crystaroller Top - Crystal', 'TR Crystaroller Chest',
|
'TR Rupees', 'TR Crystaroller Bottom', 'TR Crystaroller Middle', 'TR Crystaroller Top',
|
||||||
'TR Crystaroller Middle - Ranged Crystal', 'TR Crystaroller Bottom - Ranged Crystal', 'TR Dark Ride', 'TR Dash Bridge', 'TR Eye Bridge',
|
'TR Crystaroller Top - Crystal', 'TR Crystaroller Chest', 'TR Crystaroller Middle - Ranged Crystal',
|
||||||
|
'TR Crystaroller Bottom - Ranged Crystal', 'TR Dark Ride', 'TR Dash Bridge', 'TR Eye Bridge',
|
||||||
'TR Crystal Maze Start', 'TR Crystal Maze Start - Crystal', 'TR Crystal Maze Interior', 'TR Crystal Maze End',
|
'TR Crystal Maze Start', 'TR Crystal Maze Start - Crystal', 'TR Crystal Maze Interior', 'TR Crystal Maze End',
|
||||||
'TR Crystal Maze End - Ranged Crystal', 'TR Final Abyss', 'TR Boss', 'Turtle Rock Main Portal',
|
'TR Crystal Maze End - Ranged Crystal', 'TR Final Abyss Balcony', 'TR Final Abyss Ledge', 'TR Boss',
|
||||||
'Turtle Rock Lazy Eyes Portal', 'Turtle Rock Chest Portal', 'Turtle Rock Eye Bridge Portal'
|
'Turtle Rock Main Portal', 'Turtle Rock Lazy Eyes Portal', 'Turtle Rock Chest Portal',
|
||||||
|
'Turtle Rock Eye Bridge Portal'
|
||||||
]
|
]
|
||||||
|
|
||||||
gt_regions = [
|
gt_regions = [
|
||||||
'GT Lobby', 'GT Bob\'s Torch', 'GT Hope Room', 'GT Big Chest', 'GT Blocked Stairs', 'GT Bob\'s Room',
|
'GT Lobby', 'GT Bob\'s Torch', 'GT Hope Room', 'GT Big Chest', 'GT Blocked Stairs', 'GT Bob\'s Room',
|
||||||
'GT Tile Room', 'GT Speed Torch', 'GT Speed Torch Upper', 'GT Pots n Blocks', 'GT Crystal Conveyor',
|
'GT Tile Room', 'GT Speed Torch', 'GT Speed Torch Upper', 'GT Pots n Blocks', 'GT Crystal Conveyor',
|
||||||
'GT Crystal Conveyor Corner', 'GT Crystal Conveyor Left', 'GT Crystal Conveyor - Ranged Crystal',
|
'GT Crystal Conveyor Corner', 'GT Crystal Conveyor Left', 'GT Crystal Conveyor - Ranged Crystal',
|
||||||
'GT Crystal Conveyor Corner - Ranged Crystal',
|
'GT Crystal Conveyor Corner - Ranged Crystal', 'GT Compass Room', 'GT Invisible Bridges', 'GT Invisible Catwalk',
|
||||||
'GT Compass Room', 'GT Invisible Bridges', 'GT Invisible Catwalk', 'GT Conveyor Cross', 'GT Hookshot East Platform',
|
'GT Conveyor Cross', 'GT Hookshot East Platform', 'GT Hookshot Mid Platform', 'GT Hookshot North Platform',
|
||||||
'GT Hookshot North Platform', 'GT Hookshot South Platform', 'GT Hookshot South Entry', 'GT Hookshot South Entry - Ranged Crystal', 'GT Map Room',
|
'GT Hookshot South Platform', 'GT Hookshot South Entry', 'GT Hookshot South Entry - Ranged Crystal', 'GT Map Room',
|
||||||
'GT Double Switch Entry', 'GT Double Switch Pot Corners - Ranged Switches', 'GT Double Switch Pot Corners',
|
'GT Double Switch Entry', 'GT Double Switch Pot Corners - Ranged Switches', 'GT Double Switch Pot Corners',
|
||||||
'GT Double Switch Left', 'GT Double Switch Left - Crystal',
|
'GT Double Switch Left', 'GT Double Switch Left - Crystal', 'GT Double Switch Entry - Ranged Switches',
|
||||||
'GT Double Switch Entry - Ranged Switches', 'GT Double Switch Exit', 'GT Spike Crystal Left',
|
'GT Double Switch Exit', 'GT Spike Crystal Left',
|
||||||
'GT Spike Crystal Right', 'GT Warp Maze - Left Section', 'GT Warp Maze - Mid Section',
|
'GT Spike Crystal Right', 'GT Warp Maze - Left Section', 'GT Warp Maze - Mid Section',
|
||||||
'GT Warp Maze - Right Section', 'GT Warp Maze - Pit Section', 'GT Warp Maze - Pit Exit Warp Spot',
|
'GT Warp Maze - Right Section', 'GT Warp Maze - Pit Section', 'GT Warp Maze - Pit Exit Warp Spot',
|
||||||
'GT Warp Maze Exit Section', 'GT Firesnake Room', 'GT Firesnake Room Ledge', 'GT Warp Maze - Rail Choice',
|
'GT Warp Maze Exit Section', 'GT Firesnake Room', 'GT Firesnake Room Ledge', 'GT Warp Maze - Rail Choice',
|
||||||
|
|||||||
+18
-4
@@ -3070,12 +3070,14 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
|
|||||||
('Kings Grave Inner Rocks', 'Light World'),
|
('Kings Grave Inner Rocks', 'Light World'),
|
||||||
('Kings Grave Mirror Spot', 'Kings Grave Area'),
|
('Kings Grave Mirror Spot', 'Kings Grave Area'),
|
||||||
('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'),
|
('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'),
|
||||||
|
('Kakariko Well (top to back)', 'Kakariko Well (back)'),
|
||||||
('Master Sword Meadow', 'Master Sword Meadow'),
|
('Master Sword Meadow', 'Master Sword Meadow'),
|
||||||
('Hobo Bridge', 'Hobo Bridge'),
|
('Hobo Bridge', 'Hobo Bridge'),
|
||||||
('Bat Cave Drop Ledge', 'Bat Cave Drop Ledge'),
|
('Bat Cave Drop Ledge', 'Bat Cave Drop Ledge'),
|
||||||
('Bat Cave Door', 'Bat Cave (left)'),
|
('Bat Cave Door', 'Bat Cave (left)'),
|
||||||
('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'),
|
('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'),
|
||||||
('Lumberjack Tree (top to bottom)', 'Lumberjack Tree (bottom)'),
|
('Lumberjack Tree (top to bottom)', 'Lumberjack Tree (bottom)'),
|
||||||
|
('Blinds Hideout N', 'Blinds Hideout (Top)'),
|
||||||
('Desert Palace Stairs', 'Desert Palace Stairs'),
|
('Desert Palace Stairs', 'Desert Palace Stairs'),
|
||||||
('Desert Palace Stairs Drop', 'Light World'),
|
('Desert Palace Stairs Drop', 'Light World'),
|
||||||
('Desert Palace Entrance (North) Rocks', 'Desert Palace Entrance (North) Spot'),
|
('Desert Palace Entrance (North) Rocks', 'Desert Palace Entrance (North) Spot'),
|
||||||
@@ -3088,6 +3090,8 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
|
|||||||
('Death Mountain Entrance Drop', 'Light World'),
|
('Death Mountain Entrance Drop', 'Light World'),
|
||||||
('Spectacle Rock Cave Drop', 'Spectacle Rock Cave (Bottom)'),
|
('Spectacle Rock Cave Drop', 'Spectacle Rock Cave (Bottom)'),
|
||||||
('Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave (Bottom)'),
|
('Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave (Bottom)'),
|
||||||
|
('Death Mountain Return Cave E', 'Death Mountain Return Cave (right)'),
|
||||||
|
('Death Mountain Return Cave W', 'Death Mountain Return Cave (left)'),
|
||||||
('Death Mountain Return Ledge Drop', 'Light World'),
|
('Death Mountain Return Ledge Drop', 'Light World'),
|
||||||
('Old Man Cave Dropdown', 'Old Man Cave'),
|
('Old Man Cave Dropdown', 'Old Man Cave'),
|
||||||
('Old Man House Front to Back', 'Old Man House Back'),
|
('Old Man House Front to Back', 'Old Man House Back'),
|
||||||
@@ -3146,6 +3150,7 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
|
|||||||
('Death Mountain Teleporter', 'Dark Death Mountain (West Bottom)'),
|
('Death Mountain Teleporter', 'Dark Death Mountain (West Bottom)'),
|
||||||
('Paradox Cave Push Block Reverse', 'Paradox Cave Chest Area'),
|
('Paradox Cave Push Block Reverse', 'Paradox Cave Chest Area'),
|
||||||
('Paradox Cave Push Block', 'Paradox Cave Front'),
|
('Paradox Cave Push Block', 'Paradox Cave Front'),
|
||||||
|
('Paradox Cave Chest Area NE', 'Paradox Cave Bomb Area'),
|
||||||
('Paradox Cave Bomb Jump', 'Paradox Cave'),
|
('Paradox Cave Bomb Jump', 'Paradox Cave'),
|
||||||
('Paradox Cave Drop', 'Paradox Cave Chest Area'),
|
('Paradox Cave Drop', 'Paradox Cave Chest Area'),
|
||||||
('Light World Death Mountain Shop', 'Light World Death Mountain Shop'),
|
('Light World Death Mountain Shop', 'Light World Death Mountain Shop'),
|
||||||
@@ -3166,6 +3171,8 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
|
|||||||
('Hookshot Cave Middle to Front', 'Hookshot Cave (Front)'),
|
('Hookshot Cave Middle to Front', 'Hookshot Cave (Front)'),
|
||||||
('Hookshot Cave Middle to Back', 'Hookshot Cave (Back)'),
|
('Hookshot Cave Middle to Back', 'Hookshot Cave (Back)'),
|
||||||
('Hookshot Cave Back to Middle', 'Hookshot Cave (Middle)'),
|
('Hookshot Cave Back to Middle', 'Hookshot Cave (Middle)'),
|
||||||
|
('Hookshot Cave Bonk Path', 'Hookshot Cave (Bonk Islands)'),
|
||||||
|
('Hookshot Cave Hook Path', 'Hookshot Cave (Hook Islands)'),
|
||||||
('Turtle Rock Teleporter', 'Turtle Rock (Top)'),
|
('Turtle Rock Teleporter', 'Turtle Rock (Top)'),
|
||||||
('Turtle Rock Drop', 'Dark Death Mountain (Top)'),
|
('Turtle Rock Drop', 'Dark Death Mountain (Top)'),
|
||||||
('Floating Island Drop', 'Dark Death Mountain (Top)'),
|
('Floating Island Drop', 'Dark Death Mountain (Top)'),
|
||||||
@@ -3195,12 +3202,14 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
|
|||||||
('Kings Grave Outer Rocks', 'Kings Grave Area'),
|
('Kings Grave Outer Rocks', 'Kings Grave Area'),
|
||||||
('Kings Grave Inner Rocks', 'Light World'),
|
('Kings Grave Inner Rocks', 'Light World'),
|
||||||
('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'),
|
('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'),
|
||||||
|
('Kakariko Well (top to back)', 'Kakariko Well (back)'),
|
||||||
('Master Sword Meadow', 'Master Sword Meadow'),
|
('Master Sword Meadow', 'Master Sword Meadow'),
|
||||||
('Hobo Bridge', 'Hobo Bridge'),
|
('Hobo Bridge', 'Hobo Bridge'),
|
||||||
('Bat Cave Drop Ledge', 'Bat Cave Drop Ledge'),
|
('Bat Cave Drop Ledge', 'Bat Cave Drop Ledge'),
|
||||||
('Bat Cave Door', 'Bat Cave (left)'),
|
('Bat Cave Door', 'Bat Cave (left)'),
|
||||||
('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'),
|
('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'),
|
||||||
('Lumberjack Tree (top to bottom)', 'Lumberjack Tree (bottom)'),
|
('Lumberjack Tree (top to bottom)', 'Lumberjack Tree (bottom)'),
|
||||||
|
('Blinds Hideout N', 'Blinds Hideout (Top)'),
|
||||||
('Desert Palace Stairs', 'Desert Palace Stairs'),
|
('Desert Palace Stairs', 'Desert Palace Stairs'),
|
||||||
('Desert Palace Stairs Drop', 'Light World'),
|
('Desert Palace Stairs Drop', 'Light World'),
|
||||||
('Desert Palace Entrance (North) Rocks', 'Desert Palace Entrance (North) Spot'),
|
('Desert Palace Entrance (North) Rocks', 'Desert Palace Entrance (North) Spot'),
|
||||||
@@ -3208,6 +3217,8 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
|
|||||||
('Sewer Drop', 'Sewers Rat Path'),
|
('Sewer Drop', 'Sewers Rat Path'),
|
||||||
('Death Mountain Entrance Rock', 'Death Mountain Entrance'),
|
('Death Mountain Entrance Rock', 'Death Mountain Entrance'),
|
||||||
('Death Mountain Entrance Drop', 'Light World'),
|
('Death Mountain Entrance Drop', 'Light World'),
|
||||||
|
('Death Mountain Return Cave E', 'Death Mountain Return Cave (right)'),
|
||||||
|
('Death Mountain Return Cave W', 'Death Mountain Return Cave (left)'),
|
||||||
('Spectacle Rock Cave Drop', 'Spectacle Rock Cave (Bottom)'),
|
('Spectacle Rock Cave Drop', 'Spectacle Rock Cave (Bottom)'),
|
||||||
('Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave (Bottom)'),
|
('Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave (Bottom)'),
|
||||||
('Death Mountain Return Ledge Drop', 'Light World'),
|
('Death Mountain Return Ledge Drop', 'Light World'),
|
||||||
@@ -3251,6 +3262,7 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
|
|||||||
('Skull Woods Forest', 'Skull Woods Forest'),
|
('Skull Woods Forest', 'Skull Woods Forest'),
|
||||||
('Paradox Cave Push Block Reverse', 'Paradox Cave Chest Area'),
|
('Paradox Cave Push Block Reverse', 'Paradox Cave Chest Area'),
|
||||||
('Paradox Cave Push Block', 'Paradox Cave Front'),
|
('Paradox Cave Push Block', 'Paradox Cave Front'),
|
||||||
|
('Paradox Cave Chest Area NE', 'Paradox Cave Bomb Area'),
|
||||||
('Paradox Cave Bomb Jump', 'Paradox Cave'),
|
('Paradox Cave Bomb Jump', 'Paradox Cave'),
|
||||||
('Paradox Cave Drop', 'Paradox Cave Chest Area'),
|
('Paradox Cave Drop', 'Paradox Cave Chest Area'),
|
||||||
('Light World Death Mountain Shop', 'Light World Death Mountain Shop'),
|
('Light World Death Mountain Shop', 'Light World Death Mountain Shop'),
|
||||||
@@ -3288,6 +3300,8 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
|
|||||||
('Hookshot Cave Middle to Front', 'Hookshot Cave (Front)'),
|
('Hookshot Cave Middle to Front', 'Hookshot Cave (Front)'),
|
||||||
('Hookshot Cave Middle to Back', 'Hookshot Cave (Back)'),
|
('Hookshot Cave Middle to Back', 'Hookshot Cave (Back)'),
|
||||||
('Hookshot Cave Back to Middle', 'Hookshot Cave (Middle)'),
|
('Hookshot Cave Back to Middle', 'Hookshot Cave (Middle)'),
|
||||||
|
('Hookshot Cave Bonk Path', 'Hookshot Cave (Bonk Islands)'),
|
||||||
|
('Hookshot Cave Hook Path', 'Hookshot Cave (Hook Islands)'),
|
||||||
('Desert Ledge Drop', 'Light World'),
|
('Desert Ledge Drop', 'Light World'),
|
||||||
('Floating Island Drop', 'Dark Death Mountain'),
|
('Floating Island Drop', 'Dark Death Mountain'),
|
||||||
('Dark Lake Hylia Central Island Teleporter', 'Lake Hylia Central Island'),
|
('Dark Lake Hylia Central Island Teleporter', 'Lake Hylia Central Island'),
|
||||||
@@ -3426,8 +3440,8 @@ default_connections = [('Links House', 'Links House'),
|
|||||||
('Old Man House Exit (Bottom)', 'Death Mountain'),
|
('Old Man House Exit (Bottom)', 'Death Mountain'),
|
||||||
('Old Man House (Top)', 'Old Man House Back'),
|
('Old Man House (Top)', 'Old Man House Back'),
|
||||||
('Old Man House Exit (Top)', 'Death Mountain'),
|
('Old Man House Exit (Top)', 'Death Mountain'),
|
||||||
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'),
|
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave (right)'),
|
||||||
('Death Mountain Return Cave (West)', 'Death Mountain Return Cave'),
|
('Death Mountain Return Cave (West)', 'Death Mountain Return Cave (left)'),
|
||||||
('Death Mountain Return Cave Exit (West)', 'Death Mountain Return Ledge'),
|
('Death Mountain Return Cave Exit (West)', 'Death Mountain Return Ledge'),
|
||||||
('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
|
('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
|
||||||
('Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Peak)'),
|
('Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Peak)'),
|
||||||
@@ -3631,7 +3645,7 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
|
|||||||
('Inverted Dark Sanctuary', 'Inverted Dark Sanctuary'),
|
('Inverted Dark Sanctuary', 'Inverted Dark Sanctuary'),
|
||||||
('Inverted Dark Sanctuary Exit', 'West Dark World'),
|
('Inverted Dark Sanctuary Exit', 'West Dark World'),
|
||||||
('Old Man Cave (West)', 'Bumper Cave'),
|
('Old Man Cave (West)', 'Bumper Cave'),
|
||||||
('Old Man Cave (East)', 'Death Mountain Return Cave'),
|
('Old Man Cave (East)', 'Death Mountain Return Cave (left)'),
|
||||||
('Old Man Cave Exit (West)', 'West Dark World'),
|
('Old Man Cave Exit (West)', 'West Dark World'),
|
||||||
('Old Man Cave Exit (East)', 'Dark Death Mountain'),
|
('Old Man Cave Exit (East)', 'Dark Death Mountain'),
|
||||||
('Dark Death Mountain Fairy', 'Old Man Cave'),
|
('Dark Death Mountain Fairy', 'Old Man Cave'),
|
||||||
@@ -3640,7 +3654,7 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
|
|||||||
('Bumper Cave Exit (Top)', 'Death Mountain Return Ledge'),
|
('Bumper Cave Exit (Top)', 'Death Mountain Return Ledge'),
|
||||||
('Bumper Cave Exit (Bottom)', 'Light World'),
|
('Bumper Cave Exit (Bottom)', 'Light World'),
|
||||||
('Death Mountain Return Cave (West)', 'Bumper Cave'),
|
('Death Mountain Return Cave (West)', 'Bumper Cave'),
|
||||||
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'),
|
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave (right)'),
|
||||||
('Death Mountain Return Cave Exit (West)', 'Death Mountain'),
|
('Death Mountain Return Cave Exit (West)', 'Death Mountain'),
|
||||||
('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
|
('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
|
||||||
('Hookshot Cave Front Exit', 'Dark Death Mountain'),
|
('Hookshot Cave Front Exit', 'Dark Death Mountain'),
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import collections
|
|||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from BaseClasses import CollectionState, FillError
|
from BaseClasses import CollectionState, FillError, LocationType
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from Regions import shop_to_location_table, retro_shops
|
from Regions import shop_to_location_table, retro_shops
|
||||||
from source.item.FillUtil import filter_locations, classify_major_items, replace_trash_item, vanilla_fallback
|
from source.item.FillUtil import filter_locations, classify_major_items, replace_trash_item, vanilla_fallback
|
||||||
|
from source.item.FillUtil import filter_pot_locations, valid_pot_items
|
||||||
|
|
||||||
|
|
||||||
def get_dungeon_item_pool(world):
|
def get_dungeon_item_pool(world):
|
||||||
@@ -350,6 +351,25 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
|||||||
|
|
||||||
# get items to distribute
|
# get items to distribute
|
||||||
classify_major_items(world)
|
classify_major_items(world)
|
||||||
|
# handle pot shuffle
|
||||||
|
pots_used = False
|
||||||
|
pot_item_pool = collections.defaultdict(list)
|
||||||
|
for item in world.itempool:
|
||||||
|
if item.name in ['Chicken', 'Big Magic']: # can only fill these in that players world
|
||||||
|
pot_item_pool[item.player].append(item)
|
||||||
|
for player, pot_pool in pot_item_pool.items():
|
||||||
|
if pot_pool:
|
||||||
|
for pot_item in pot_pool:
|
||||||
|
world.itempool.remove(pot_item)
|
||||||
|
pot_locations = [location for location in fill_locations
|
||||||
|
if location.type == LocationType.Pot and location.player == player]
|
||||||
|
pot_locations = filter_pot_locations(pot_locations, world)
|
||||||
|
fast_fill_helper(world, pot_pool, pot_locations)
|
||||||
|
pots_used = True
|
||||||
|
if pots_used:
|
||||||
|
fill_locations = world.get_unfilled_locations()
|
||||||
|
random.shuffle(fill_locations)
|
||||||
|
|
||||||
random.shuffle(world.itempool)
|
random.shuffle(world.itempool)
|
||||||
progitempool = [item for item in world.itempool if item.advancement]
|
progitempool = [item for item in world.itempool if item.advancement]
|
||||||
prioitempool = [item for item in world.itempool if not item.advancement and item.priority]
|
prioitempool = [item for item in world.itempool if not item.advancement and item.priority]
|
||||||
@@ -415,6 +435,8 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
|||||||
fill_locations.remove(l)
|
fill_locations.remove(l)
|
||||||
filtered_fill(world, placeholder_items, placeholder_locations)
|
filtered_fill(world, placeholder_items, placeholder_locations)
|
||||||
|
|
||||||
|
if world.players > 1:
|
||||||
|
fast_fill_pot_for_multiworld(world, restitempool, fill_locations)
|
||||||
if world.algorithm == 'vanilla_fill':
|
if world.algorithm == 'vanilla_fill':
|
||||||
fast_vanilla_fill(world, restitempool, fill_locations)
|
fast_vanilla_fill(world, restitempool, fill_locations)
|
||||||
else:
|
else:
|
||||||
@@ -425,6 +447,26 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
|||||||
if unplaced or unfilled:
|
if unplaced or unfilled:
|
||||||
logging.warning('Unplaced items: %s - Unfilled Locations: %s', unplaced, unfilled)
|
logging.warning('Unplaced items: %s - Unfilled Locations: %s', unplaced, unfilled)
|
||||||
|
|
||||||
|
for loc in world.get_locations():
|
||||||
|
# convert Arrows 5 and Nothing when necessary
|
||||||
|
if (loc.item.name in {'Arrows (5)', 'Nothing'}
|
||||||
|
and (loc.type != LocationType.Pot or loc.item.player != loc.player)):
|
||||||
|
loc.item = ItemFactory(invalid_location_replacement[loc.item.name], loc.item.player)
|
||||||
|
# don't write out all pots to spoiler
|
||||||
|
if loc.type == LocationType.Pot and loc.item.name in valid_pot_items:
|
||||||
|
loc.skip = True
|
||||||
|
|
||||||
|
|
||||||
|
invalid_location_replacement = {'Arrows (5)': 'Arrows (10)', 'Nothing': 'Rupees (5)'}
|
||||||
|
|
||||||
|
|
||||||
|
def fast_fill_helper(world, item_pool, fill_locations):
|
||||||
|
if world.algorithm == 'vanilla_fill':
|
||||||
|
fast_vanilla_fill(world, item_pool, fill_locations)
|
||||||
|
else:
|
||||||
|
fast_fill(world, item_pool, fill_locations)
|
||||||
|
# todo: other fast fill methods?
|
||||||
|
|
||||||
|
|
||||||
def fast_fill(world, item_pool, fill_locations):
|
def fast_fill(world, item_pool, fill_locations):
|
||||||
while item_pool and fill_locations:
|
while item_pool and fill_locations:
|
||||||
@@ -433,6 +475,28 @@ def fast_fill(world, item_pool, fill_locations):
|
|||||||
world.push_item(spot_to_fill, item_to_place, False)
|
world.push_item(spot_to_fill, item_to_place, False)
|
||||||
|
|
||||||
|
|
||||||
|
def fast_fill_pot_for_multiworld(world, item_pool, fill_locations):
|
||||||
|
pot_item_pool = collections.defaultdict(list)
|
||||||
|
pot_fill_locations = collections.defaultdict(list)
|
||||||
|
for item in item_pool:
|
||||||
|
if item.name in valid_pot_items:
|
||||||
|
pot_item_pool[item.player].append(item)
|
||||||
|
for loc in fill_locations:
|
||||||
|
if loc.type == LocationType.Pot:
|
||||||
|
pot_fill_locations[loc.player].append(loc)
|
||||||
|
for player in range(1, world.players+1):
|
||||||
|
flex = 256 - world.pot_contents[player].multiworld_count
|
||||||
|
fill_count = len(pot_fill_locations[player]) - flex
|
||||||
|
if fill_count > 0:
|
||||||
|
fill_spots = random.sample(pot_fill_locations[player], fill_count)
|
||||||
|
fill_items = random.sample(pot_item_pool[player], fill_count)
|
||||||
|
for x in fill_items:
|
||||||
|
item_pool.remove(x)
|
||||||
|
for x in fill_spots:
|
||||||
|
fill_locations.remove(x)
|
||||||
|
fast_fill(world, fill_items, fill_spots)
|
||||||
|
|
||||||
|
|
||||||
def filtered_fill(world, item_pool, fill_locations):
|
def filtered_fill(world, item_pool, fill_locations):
|
||||||
while item_pool and fill_locations:
|
while item_pool and fill_locations:
|
||||||
item_to_place = item_pool.pop()
|
item_to_place = item_pool.pop()
|
||||||
|
|||||||
+20
-17
@@ -2,7 +2,6 @@ import collections
|
|||||||
from BaseClasses import RegionType
|
from BaseClasses import RegionType
|
||||||
from Regions import create_lw_region, create_dw_region, create_cave_region, create_dungeon_region, create_menu_region
|
from Regions import create_lw_region, create_dw_region, create_cave_region, create_dungeon_region, create_menu_region
|
||||||
|
|
||||||
# todo: shopsanity locations
|
|
||||||
def create_inverted_regions(world, player):
|
def create_inverted_regions(world, player):
|
||||||
|
|
||||||
world.regions += [
|
world.regions += [
|
||||||
@@ -25,11 +24,10 @@ def create_inverted_regions(world, player):
|
|||||||
create_lw_region(player, 'Hyrule Castle Secret Entrance Area', None, ['Hyrule Castle Secret Entrance Stairs', 'Secret Passage Inner Bushes']),
|
create_lw_region(player, 'Hyrule Castle Secret Entrance Area', None, ['Hyrule Castle Secret Entrance Stairs', 'Secret Passage Inner Bushes']),
|
||||||
create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop', 'Bumper Cave Entrance Mirror Spot']),
|
create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop', 'Bumper Cave Entrance Mirror Spot']),
|
||||||
create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Mirror Spot']),
|
create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Mirror Spot']),
|
||||||
create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', ["Blind\'s Hideout - Top",
|
create_cave_region(player, 'Blinds Hideout', 'a bounty of five items',
|
||||||
"Blind\'s Hideout - Left",
|
["Blind's Hideout - Left", "Blind's Hideout - Right", "Blind's Hideout - Far Left",
|
||||||
"Blind\'s Hideout - Right",
|
"Blind's Hideout - Far Right"], ['Blinds Hideout N']),
|
||||||
"Blind\'s Hideout - Far Left",
|
create_cave_region(player, 'Blinds Hideout (Top)', 'a bounty of five items', ["Blind's Hideout - Top"]),
|
||||||
"Blind\'s Hideout - Far Right"]),
|
|
||||||
create_lw_region(player, 'Northeast Light World', None, ['Zoras River', 'Waterfall of Wishing Cave', 'Potion Shop Outer Rock', 'Catfish Mirror Spot', 'Northeast Light World Warp']),
|
create_lw_region(player, 'Northeast Light World', None, ['Zoras River', 'Waterfall of Wishing Cave', 'Potion Shop Outer Rock', 'Catfish Mirror Spot', 'Northeast Light World Warp']),
|
||||||
create_lw_region(player, 'Waterfall of Wishing Cave', None, ['Waterfall of Wishing', 'Northeast Light World Return']),
|
create_lw_region(player, 'Waterfall of Wishing Cave', None, ['Waterfall of Wishing', 'Northeast Light World Return']),
|
||||||
create_lw_region(player, 'Potion Shop Area', None, ['Potion Shop', 'Potion Shop Inner Bushes', 'Potion Shop Inner Rock', 'Potion Shop Mirror Spot', 'Potion Shop River Drop']),
|
create_lw_region(player, 'Potion Shop Area', None, ['Potion Shop', 'Potion Shop Inner Bushes', 'Potion Shop Inner Rock', 'Potion Shop Mirror Spot', 'Potion Shop River Drop']),
|
||||||
@@ -68,12 +66,15 @@ def create_inverted_regions(world, player):
|
|||||||
create_cave_region(player, 'Chicken House', 'a house with a chest', ['Chicken House']),
|
create_cave_region(player, 'Chicken House', 'a house with a chest', ['Chicken House']),
|
||||||
create_cave_region(player, 'Aginahs Cave', 'a cave with a chest', ['Aginah\'s Cave']),
|
create_cave_region(player, 'Aginahs Cave', 'a cave with a chest', ['Aginah\'s Cave']),
|
||||||
create_cave_region(player, 'Sahasrahlas Hut', 'Sahasrahla', ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right', 'Sahasrahla']),
|
create_cave_region(player, 'Sahasrahlas Hut', 'Sahasrahla', ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right', 'Sahasrahla']),
|
||||||
create_cave_region(player, 'Kakariko Well (top)', 'a drop\'s exit', ['Kakariko Well - Top', 'Kakariko Well - Left', 'Kakariko Well - Middle',
|
create_cave_region(player, 'Kakariko Well (top)', 'a drop',
|
||||||
'Kakariko Well - Right', 'Kakariko Well - Bottom'], ['Kakariko Well (top to bottom)']),
|
['Kakariko Well - Left', 'Kakariko Well - Middle', 'Kakariko Well - Right',
|
||||||
|
'Kakariko Well - Bottom'],
|
||||||
|
['Kakariko Well (top to bottom)', 'Kakariko Well (top to back)']),
|
||||||
|
create_cave_region(player, 'Kakariko Well (back)', 'a drop', ['Kakariko Well - Top']),
|
||||||
create_cave_region(player, 'Kakariko Well (bottom)', 'a drop\'s exit', None, ['Kakariko Well Exit']),
|
create_cave_region(player, 'Kakariko Well (bottom)', 'a drop\'s exit', None, ['Kakariko Well Exit']),
|
||||||
create_cave_region(player, 'Blacksmiths Hut', 'the smith', ['Blacksmith', 'Missing Smith']),
|
create_cave_region(player, 'Blacksmiths Hut', 'the smith', ['Blacksmith', 'Missing Smith']),
|
||||||
create_lw_region(player, 'Bat Cave Drop Ledge', None, ['Bat Cave Drop']),
|
create_lw_region(player, 'Bat Cave Drop Ledge', None, ['Bat Cave Drop']),
|
||||||
create_cave_region(player, 'Bat Cave (right)', 'a drop\'s exit', ['Magic Bat'], ['Bat Cave Door']),
|
create_cave_region(player, 'Bat Cave (right)', 'a drop', ['Magic Bat'], ['Bat Cave Door']),
|
||||||
create_cave_region(player, 'Bat Cave (left)', 'a drop\'s exit', None, ['Bat Cave Exit']),
|
create_cave_region(player, 'Bat Cave (left)', 'a drop\'s exit', None, ['Bat Cave Exit']),
|
||||||
create_cave_region(player, 'Sick Kids House', 'the sick kid', ['Sick Kid']),
|
create_cave_region(player, 'Sick Kids House', 'the sick kid', ['Sick Kid']),
|
||||||
create_lw_region(player, 'Hobo Bridge', ['Hobo']),
|
create_lw_region(player, 'Hobo Bridge', ['Hobo']),
|
||||||
@@ -114,8 +115,8 @@ def create_inverted_regions(world, player):
|
|||||||
create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']),
|
create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']),
|
||||||
create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave',
|
create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave',
|
||||||
'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot']),
|
'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot']),
|
||||||
create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']),
|
create_cave_region(player, 'Death Mountain Return Cave (left)', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave E']),
|
||||||
create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Bumper Cave Ledge Mirror Spot']),
|
create_cave_region(player, 'Death Mountain Return Cave (right)', 'a connector', None, ['Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave W']),
|
||||||
create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']),
|
create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']),
|
||||||
create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']),
|
create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']),
|
||||||
create_cave_region(player, 'Spectacle Rock Cave (Peak)', 'a connector', None, ['Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave Exit (Peak)']),
|
create_cave_region(player, 'Spectacle Rock Cave (Peak)', 'a connector', None, ['Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave Exit (Peak)']),
|
||||||
@@ -127,10 +128,10 @@ def create_inverted_regions(world, player):
|
|||||||
'Paradox Cave Lower - Left',
|
'Paradox Cave Lower - Left',
|
||||||
'Paradox Cave Lower - Right',
|
'Paradox Cave Lower - Right',
|
||||||
'Paradox Cave Lower - Far Right',
|
'Paradox Cave Lower - Far Right',
|
||||||
'Paradox Cave Lower - Middle',
|
'Paradox Cave Lower - Middle'],
|
||||||
'Paradox Cave Upper - Left',
|
['Paradox Cave Push Block', 'Paradox Cave Bomb Jump', 'Paradox Cave Chest Area NE']),
|
||||||
'Paradox Cave Upper - Right'],
|
create_cave_region(player, 'Paradox Cave Bomb Area', 'a connector', ['Paradox Cave Upper - Left',
|
||||||
['Paradox Cave Push Block', 'Paradox Cave Bomb Jump']),
|
'Paradox Cave Upper - Right']),
|
||||||
create_cave_region(player, 'Paradox Cave', 'a connector', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']),
|
create_cave_region(player, 'Paradox Cave', 'a connector', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']),
|
||||||
create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop', ['Paradox Shop - Left', 'Paradox Shop - Middle', 'Paradox Shop - Right']),
|
create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop', ['Paradox Shop - Left', 'Paradox Shop - Middle', 'Paradox Shop - Right']),
|
||||||
create_lw_region(player, 'East Death Mountain (Top)', ['Floating Island'], ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'East Death Mountain Mirror Spot (Top)', 'Fairy Ascension Ledge Access', 'Mimic Cave Ledge Access',
|
create_lw_region(player, 'East Death Mountain (Top)', ['Floating Island'], ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'East Death Mountain Mirror Spot (Top)', 'Fairy Ascension Ledge Access', 'Mimic Cave Ledge Access',
|
||||||
@@ -199,8 +200,10 @@ def create_inverted_regions(world, player):
|
|||||||
create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']),
|
create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']),
|
||||||
create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']),
|
create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']),
|
||||||
create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']),
|
create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']),
|
||||||
create_cave_region(player, 'Hookshot Cave (Front)', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'],
|
create_cave_region(player, 'Hookshot Cave (Front)', 'a connector', None,
|
||||||
['Hookshot Cave Front to Middle', 'Hookshot Cave Front Exit']),
|
['Hookshot Cave Front to Middle', 'Hookshot Cave Front Exit', 'Hookshot Cave Bonk Path', 'Hookshot Cave Hook Path']),
|
||||||
|
create_cave_region(player, 'Hookshot Cave (Bonk Islands)', 'a connector', ['Hookshot Cave - Bottom Right']),
|
||||||
|
create_cave_region(player, 'Hookshot Cave (Hook Islands)', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Left']),
|
||||||
create_cave_region(player, 'Hookshot Cave (Back)', 'a connector', None, ['Hookshot Cave Back to Middle', 'Hookshot Cave Back Exit']),
|
create_cave_region(player, 'Hookshot Cave (Back)', 'a connector', None, ['Hookshot Cave Back to Middle', 'Hookshot Cave Back Exit']),
|
||||||
create_cave_region(player, 'Hookshot Cave (Middle)', 'a connector', None, ['Hookshot Cave Middle to Back', 'Hookshot Cave Middle to Front']),
|
create_cave_region(player, 'Hookshot Cave (Middle)', 'a connector', None, ['Hookshot Cave Middle to Back', 'Hookshot Cave Middle to Front']),
|
||||||
|
|
||||||
|
|||||||
+19
-4
@@ -3,13 +3,14 @@ import logging
|
|||||||
import math
|
import math
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
|
|
||||||
from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState
|
from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem
|
||||||
from EntranceShuffle import connect_entrance
|
from EntranceShuffle import connect_entrance
|
||||||
from Regions import shop_to_location_table, retro_shops, shop_table_by_location
|
from Regions import shop_to_location_table, retro_shops, shop_table_by_location
|
||||||
from Fill import FillError, fill_restrictive, fast_fill, get_dungeon_item_pool
|
from Fill import FillError, fill_restrictive, fast_fill, get_dungeon_item_pool
|
||||||
|
from PotShuffle import vanilla_pots
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
|
|
||||||
from source.item.FillUtil import trash_items
|
from source.item.FillUtil import trash_items, pot_items
|
||||||
|
|
||||||
import source.classes.constants as CONST
|
import source.classes.constants as CONST
|
||||||
|
|
||||||
@@ -388,11 +389,17 @@ def generate_itempool(world, player):
|
|||||||
|
|
||||||
if world.retro[player]:
|
if world.retro[player]:
|
||||||
set_up_take_anys(world, player)
|
set_up_take_anys(world, player)
|
||||||
if world.keydropshuffle[player]:
|
if world.dropshuffle[player]:
|
||||||
world.itempool += [ItemFactory('Small Key (Universal)', player)] * 32
|
world.itempool += [ItemFactory('Small Key (Universal)', player)] * 13
|
||||||
|
if world.pottery[player] != 'none':
|
||||||
|
world.itempool += [ItemFactory('Small Key (Universal)', player)] * 19
|
||||||
|
|
||||||
|
|
||||||
create_dynamic_shop_locations(world, player)
|
create_dynamic_shop_locations(world, player)
|
||||||
|
|
||||||
|
if world.pottery[player] == 'lottery':
|
||||||
|
add_pot_contents(world, player)
|
||||||
|
|
||||||
|
|
||||||
take_any_locations = [
|
take_any_locations = [
|
||||||
'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut',
|
'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut',
|
||||||
@@ -748,6 +755,13 @@ rupee_chart = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)'
|
|||||||
'Rupees (100)': 100, 'Rupees (300)': 300}
|
'Rupees (100)': 100, 'Rupees (300)': 300}
|
||||||
|
|
||||||
|
|
||||||
|
def add_pot_contents(world, player):
|
||||||
|
for super_tile, pot_list in vanilla_pots.items():
|
||||||
|
for pot in pot_list:
|
||||||
|
if pot.item not in [PotItem.Hole, PotItem.Key, PotItem.Switch]:
|
||||||
|
world.itempool.append(ItemFactory(pot_items[pot.item], player))
|
||||||
|
|
||||||
|
|
||||||
def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic):
|
def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic):
|
||||||
pool = []
|
pool = []
|
||||||
placed_items = {}
|
placed_items = {}
|
||||||
@@ -894,6 +908,7 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
|
|||||||
pool.extend(['Small Key (Universal)'])
|
pool.extend(['Small Key (Universal)'])
|
||||||
return (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms)
|
return (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms)
|
||||||
|
|
||||||
|
|
||||||
def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, bombbag, customitemarray):
|
def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, bombbag, customitemarray):
|
||||||
if isinstance(customitemarray,dict) and 1 in customitemarray:
|
if isinstance(customitemarray,dict) and 1 in customitemarray:
|
||||||
customitemarray = customitemarray[1]
|
customitemarray = customitemarray[1]
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
|
|||||||
'Arrow Upgrade (+10)': (False, False, None, 0x54, 100, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
|
'Arrow Upgrade (+10)': (False, False, None, 0x54, 100, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
|
||||||
'Arrow Upgrade (+5)': (False, False, None, 0x53, 100, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
|
'Arrow Upgrade (+5)': (False, False, None, 0x53, 100, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
|
||||||
'Single Bomb': (False, False, None, 0x27, 5, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'),
|
'Single Bomb': (False, False, None, 0x27, 5, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'),
|
||||||
|
'Arrows (5)': (False, False, None, 0x5A, 15, 'This will give\nyou five shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'five arrows'),
|
||||||
|
'Small Magic': (False, False, None, 0x45, 5, 'A bit of magic', 'and the bit of magic', 'bit-o-magic kid', 'magic bit for sale', 'fungus for magic', 'magic boy conjures again', 'a bit of magic'),
|
||||||
|
'Big Magic': (False, False, None, 0x5A, 40, 'A lot of magic', 'and lots of magic', 'lot-o-magic kid', 'magic refill for sale', 'fungus for magic', 'magic boy conjures again', 'a magic refill'),
|
||||||
|
'Chicken': (False, False, None, 0x5A, 999, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'),
|
||||||
'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'),
|
'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'),
|
||||||
'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'),
|
'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'),
|
||||||
'Bomb Upgrade (+10)': (False, False, None, 0x52, 100, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
|
'Bomb Upgrade (+10)': (False, False, None, 0x52, 100, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from Bosses import place_bosses
|
|||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from KeyDoorShuffle import validate_key_placement
|
from KeyDoorShuffle import validate_key_placement
|
||||||
from OverworldGlitchRules import create_owg_connections
|
from OverworldGlitchRules import create_owg_connections
|
||||||
from PotShuffle import shuffle_pots
|
from PotShuffle import shuffle_pots, shuffle_pot_switches
|
||||||
from Regions import create_regions, create_shops, mark_light_world_regions, create_dungeon_regions, adjust_locations
|
from Regions import create_regions, create_shops, mark_light_world_regions, create_dungeon_regions, adjust_locations
|
||||||
from InvertedRegions import create_inverted_regions, mark_dark_world_regions
|
from InvertedRegions import create_inverted_regions, mark_dark_world_regions
|
||||||
from EntranceShuffle import link_entrances, link_inverted_entrances
|
from EntranceShuffle import link_entrances, link_inverted_entrances
|
||||||
@@ -31,7 +31,7 @@ from Utils import output_path, parse_player_names
|
|||||||
from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config
|
from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config
|
||||||
|
|
||||||
|
|
||||||
__version__ = '1.0.0.1-u'
|
__version__ = '1.0.1.0-v'
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
from source.classes.BabelFish import BabelFish
|
||||||
|
|
||||||
@@ -96,10 +96,11 @@ def main(args, seed=None, fish=None):
|
|||||||
world.intensity = {player: random.randint(1, 3) if args.intensity[player] == 'random' else int(args.intensity[player]) for player in range(1, world.players + 1)}
|
world.intensity = {player: random.randint(1, 3) if args.intensity[player] == 'random' else int(args.intensity[player]) for player in range(1, world.players + 1)}
|
||||||
world.experimental = args.experimental.copy()
|
world.experimental = args.experimental.copy()
|
||||||
world.dungeon_counters = args.dungeon_counters.copy()
|
world.dungeon_counters = args.dungeon_counters.copy()
|
||||||
world.potshuffle = args.shufflepots.copy()
|
|
||||||
world.fish = fish
|
world.fish = fish
|
||||||
world.shopsanity = args.shopsanity.copy()
|
world.shopsanity = args.shopsanity.copy()
|
||||||
world.keydropshuffle = args.keydropshuffle.copy()
|
world.dropshuffle = args.dropshuffle.copy()
|
||||||
|
world.pottery = args.pottery.copy()
|
||||||
|
world.potshuffle = args.shufflepots.copy()
|
||||||
world.mixed_travel = args.mixed_travel.copy()
|
world.mixed_travel = args.mixed_travel.copy()
|
||||||
world.standardize_palettes = args.standardize_palettes.copy()
|
world.standardize_palettes = args.standardize_palettes.copy()
|
||||||
world.treasure_hunt_count = args.triforce_goal.copy()
|
world.treasure_hunt_count = args.triforce_goal.copy()
|
||||||
@@ -157,7 +158,10 @@ def main(args, seed=None, fish=None):
|
|||||||
logger.info(world.fish.translate("cli", "cli", "shuffling.pots"))
|
logger.info(world.fish.translate("cli", "cli", "shuffling.pots"))
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
if world.potshuffle[player]:
|
if world.potshuffle[player]:
|
||||||
|
if world.pottery[player] != 'lottery':
|
||||||
shuffle_pots(world, player)
|
shuffle_pots(world, player)
|
||||||
|
else:
|
||||||
|
shuffle_pot_switches(world, player)
|
||||||
|
|
||||||
logger.info(world.fish.translate("cli","cli","shuffling.world"))
|
logger.info(world.fish.translate("cli","cli","shuffling.world"))
|
||||||
|
|
||||||
@@ -397,13 +401,13 @@ def copy_world(world):
|
|||||||
ret.intensity = world.intensity.copy()
|
ret.intensity = world.intensity.copy()
|
||||||
ret.experimental = world.experimental.copy()
|
ret.experimental = world.experimental.copy()
|
||||||
ret.shopsanity = world.shopsanity.copy()
|
ret.shopsanity = world.shopsanity.copy()
|
||||||
ret.keydropshuffle = world.keydropshuffle.copy()
|
ret.dropshuffle = world.dropshuffle.copy()
|
||||||
|
ret.pottery = world.pottery.copy()
|
||||||
|
ret.potshuffle = world.potshuffle.copy()
|
||||||
ret.mixed_travel = world.mixed_travel.copy()
|
ret.mixed_travel = world.mixed_travel.copy()
|
||||||
ret.standardize_palettes = world.standardize_palettes.copy()
|
ret.standardize_palettes = world.standardize_palettes.copy()
|
||||||
ret.restrict_boss_items = world.restrict_boss_items.copy()
|
ret.restrict_boss_items = world.restrict_boss_items.copy()
|
||||||
|
|
||||||
ret.exp_cache = world.exp_cache.copy()
|
|
||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
if world.mode[player] != 'inverted':
|
if world.mode[player] != 'inverted':
|
||||||
create_regions(ret, player)
|
create_regions(ret, player)
|
||||||
@@ -416,6 +420,9 @@ def copy_world(world):
|
|||||||
if world.logic[player] in ('owglitches', 'nologic'):
|
if world.logic[player] in ('owglitches', 'nologic'):
|
||||||
create_owg_connections(ret, player)
|
create_owg_connections(ret, player)
|
||||||
|
|
||||||
|
# there are region references here they must be migrated to preserve integrity
|
||||||
|
# ret.exp_cache = world.exp_cache.copy()
|
||||||
|
|
||||||
copy_dynamic_regions_and_locations(world, ret)
|
copy_dynamic_regions_and_locations(world, ret)
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
if world.mode[player] == 'standard':
|
if world.mode[player] == 'standard':
|
||||||
@@ -464,6 +471,7 @@ def copy_world(world):
|
|||||||
new_location.access_rule = lambda state: True
|
new_location.access_rule = lambda state: True
|
||||||
new_location.item_rule = lambda state: True
|
new_location.item_rule = lambda state: True
|
||||||
new_location.forced_item = location.forced_item
|
new_location.forced_item = location.forced_item
|
||||||
|
new_location.pot = location.pot
|
||||||
|
|
||||||
# copy remaining itempool. No item in itempool should have an assigned location
|
# copy remaining itempool. No item in itempool should have an assigned location
|
||||||
for item in world.itempool:
|
for item in world.itempool:
|
||||||
|
|||||||
+77
-13
@@ -8,8 +8,10 @@ import shlex
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
import websockets
|
import websockets
|
||||||
|
|
||||||
|
from BaseClasses import PotItem, PotFlags
|
||||||
import Items
|
import Items
|
||||||
import Regions
|
import Regions
|
||||||
|
import PotShuffle
|
||||||
|
|
||||||
|
|
||||||
class ReceivedItem:
|
class ReceivedItem:
|
||||||
@@ -57,8 +59,13 @@ class Context:
|
|||||||
self.key_drop_mode = False
|
self.key_drop_mode = False
|
||||||
self.shop_mode = False
|
self.shop_mode = False
|
||||||
self.retro_mode = False
|
self.retro_mode = False
|
||||||
|
self.pottery_mode = False
|
||||||
|
self.mystery_mode = False
|
||||||
self.ignore_count = 0
|
self.ignore_count = 0
|
||||||
|
|
||||||
|
self.lookup_name_to_id = {}
|
||||||
|
self.lookup_id_to_name = {}
|
||||||
|
|
||||||
def color_code(*args):
|
def color_code(*args):
|
||||||
codes = {'reset': 0, 'bold': 1, 'underline': 4, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33, 'blue': 34,
|
codes = {'reset': 0, 'bold': 1, 'underline': 4, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33, 'blue': 34,
|
||||||
'magenta': 35, 'cyan': 36, 'white': 37 , 'black_bg': 40, 'red_bg': 41, 'green_bg': 42, 'yellow_bg': 43,
|
'magenta': 35, 'cyan': 36, 'white': 37 , 'black_bg': 40, 'red_bg': 41, 'green_bg': 42, 'yellow_bg': 43,
|
||||||
@@ -83,6 +90,10 @@ INGAME_MODES = {0x07, 0x09, 0x0b}
|
|||||||
SAVEDATA_START = WRAM_START + 0xF000
|
SAVEDATA_START = WRAM_START + 0xF000
|
||||||
SAVEDATA_SIZE = 0x500
|
SAVEDATA_SIZE = 0x500
|
||||||
|
|
||||||
|
POT_ITEMS_SRAM_START = WRAM_START + 0x016600
|
||||||
|
SPRITE_ITEMS_SRAM_START = WRAM_START + 0x016850
|
||||||
|
ITEM_SRAM_SIZE = 0x250
|
||||||
|
|
||||||
RECV_PROGRESS_ADDR = SAVEDATA_START + 0x4D0 # 2 bytes
|
RECV_PROGRESS_ADDR = SAVEDATA_START + 0x4D0 # 2 bytes
|
||||||
RECV_ITEM_ADDR = SAVEDATA_START + 0x4D2 # 1 byte
|
RECV_ITEM_ADDR = SAVEDATA_START + 0x4D2 # 1 byte
|
||||||
RECV_ITEM_PLAYER_ADDR = SAVEDATA_START + 0x4D3 # 1 byte
|
RECV_ITEM_PLAYER_ADDR = SAVEDATA_START + 0x4D3 # 1 byte
|
||||||
@@ -349,6 +360,8 @@ location_table_misc = {'Bottle Merchant': (0x3c9, 0x2),
|
|||||||
'Purple Chest': (0x3c9, 0x10),
|
'Purple Chest': (0x3c9, 0x10),
|
||||||
"Link's Uncle": (0x3c6, 0x1),
|
"Link's Uncle": (0x3c6, 0x1),
|
||||||
'Hobo': (0x3c9, 0x1)}
|
'Hobo': (0x3c9, 0x1)}
|
||||||
|
location_table_pot_items = {}
|
||||||
|
location_table_sprite_items = {}
|
||||||
|
|
||||||
SNES_DISCONNECTED = 0
|
SNES_DISCONNECTED = 0
|
||||||
SNES_CONNECTING = 1
|
SNES_CONNECTING = 1
|
||||||
@@ -676,7 +689,7 @@ async def process_server_cmd(ctx : Context, cmd, args):
|
|||||||
ctx.player_names = {p: n for p, n in args[1]}
|
ctx.player_names = {p: n for p, n in args[1]}
|
||||||
msgs = []
|
msgs = []
|
||||||
if ctx.locations_checked:
|
if ctx.locations_checked:
|
||||||
msgs.append(['LocationChecks', [Regions.lookup_name_to_id[loc] for loc in ctx.locations_checked]])
|
msgs.append(['LocationChecks', [ctx.lookup_name_to_id[loc] for loc in ctx.locations_checked]])
|
||||||
if ctx.locations_scouted:
|
if ctx.locations_scouted:
|
||||||
msgs.append(['LocationScouts', list(ctx.locations_scouted)])
|
msgs.append(['LocationScouts', list(ctx.locations_scouted)])
|
||||||
if msgs:
|
if msgs:
|
||||||
@@ -689,7 +702,7 @@ async def process_server_cmd(ctx : Context, cmd, args):
|
|||||||
elif start_index != len(ctx.items_received):
|
elif start_index != len(ctx.items_received):
|
||||||
sync_msg = [['Sync']]
|
sync_msg = [['Sync']]
|
||||||
if ctx.locations_checked:
|
if ctx.locations_checked:
|
||||||
sync_msg.append(['LocationChecks', [Regions.lookup_name_to_id[loc] for loc in ctx.locations_checked]])
|
sync_msg.append(['LocationChecks', [ctx.lookup_name_to_id[loc] for loc in ctx.locations_checked]])
|
||||||
await send_msgs(ctx.socket, sync_msg)
|
await send_msgs(ctx.socket, sync_msg)
|
||||||
if start_index == len(ctx.items_received):
|
if start_index == len(ctx.items_received):
|
||||||
for item in items:
|
for item in items:
|
||||||
@@ -701,7 +714,7 @@ async def process_server_cmd(ctx : Context, cmd, args):
|
|||||||
if location not in ctx.locations_info:
|
if location not in ctx.locations_info:
|
||||||
replacements = {0xA2: 'Small Key', 0x9D: 'Big Key', 0x8D: 'Compass', 0x7D: 'Map'}
|
replacements = {0xA2: 'Small Key', 0x9D: 'Big Key', 0x8D: 'Compass', 0x7D: 'Map'}
|
||||||
item_name = replacements.get(item, get_item_name_from_id(item))
|
item_name = replacements.get(item, get_item_name_from_id(item))
|
||||||
logging.info(f"Saw {color(item_name, 'red', 'bold')} at {list(Regions.lookup_id_to_name.keys())[location - 1]}")
|
logging.info(f"Saw {color(item_name, 'red', 'bold')} at {list(ctx.lookup_id_to_name.keys())[location - 1]}")
|
||||||
ctx.locations_info[location] = (item, player)
|
ctx.locations_info[location] = (item, player)
|
||||||
ctx.watcher_event.set()
|
ctx.watcher_event.set()
|
||||||
|
|
||||||
@@ -710,7 +723,8 @@ async def process_server_cmd(ctx : Context, cmd, args):
|
|||||||
item = color(get_item_name_from_id(item), 'cyan' if player_sent != ctx.slot else 'green')
|
item = color(get_item_name_from_id(item), 'cyan' if player_sent != ctx.slot else 'green')
|
||||||
player_sent = color(ctx.player_names[player_sent], 'yellow' if player_sent != ctx.slot else 'magenta')
|
player_sent = color(ctx.player_names[player_sent], 'yellow' if player_sent != ctx.slot else 'magenta')
|
||||||
player_recvd = color(ctx.player_names[player_recvd], 'yellow' if player_recvd != ctx.slot else 'magenta')
|
player_recvd = color(ctx.player_names[player_recvd], 'yellow' if player_recvd != ctx.slot else 'magenta')
|
||||||
logging.info('%s sent %s to %s (%s)' % (player_sent, item, player_recvd, get_location_name_from_address(location)))
|
location_name = get_location_name_from_address(ctx, location)
|
||||||
|
logging.info('%s sent %s to %s (%s)' % (player_sent, item, player_recvd, location_name))
|
||||||
|
|
||||||
if cmd == 'Print':
|
if cmd == 'Print':
|
||||||
logging.info(args)
|
logging.info(args)
|
||||||
@@ -779,10 +793,10 @@ async def console_loop(ctx : Context):
|
|||||||
for index, item in enumerate(ctx.items_received, 1):
|
for index, item in enumerate(ctx.items_received, 1):
|
||||||
logging.info('%s from %s (%s) (%d/%d in list)' % (
|
logging.info('%s from %s (%s) (%d/%d in list)' % (
|
||||||
color(get_item_name_from_id(item.item), 'red', 'bold'), color(ctx.player_names[item.player], 'yellow'),
|
color(get_item_name_from_id(item.item), 'red', 'bold'), color(ctx.player_names[item.player], 'yellow'),
|
||||||
get_location_name_from_address(item.location), index, len(ctx.items_received)))
|
get_location_name_from_address(ctx, item.location), index, len(ctx.items_received)))
|
||||||
|
|
||||||
if command[0] == '/missing':
|
if command[0] == '/missing':
|
||||||
for location in [k for k, v in Regions.lookup_name_to_id.items()
|
for location in [k for k, v in ctx.lookup_name_to_id.items()
|
||||||
if type(v) is int and not filter_location(ctx, k)]:
|
if type(v) is int and not filter_location(ctx, k)]:
|
||||||
if location not in ctx.locations_checked:
|
if location not in ctx.locations_checked:
|
||||||
logging.info('Missing: ' + location)
|
logging.info('Missing: ' + location)
|
||||||
@@ -804,15 +818,19 @@ def get_item_name_from_id(code):
|
|||||||
return items[0] if items else f'Unknown item (ID:{code})'
|
return items[0] if items else f'Unknown item (ID:{code})'
|
||||||
|
|
||||||
|
|
||||||
def get_location_name_from_address(address):
|
def get_location_name_from_address(ctx, address):
|
||||||
if type(address) is str:
|
if type(address) is str:
|
||||||
return address
|
return address
|
||||||
|
|
||||||
return Regions.lookup_id_to_name.get(address, f'Unknown location (ID:{address})')
|
return ctx.lookup_id_to_name.get(address, f'Unknown location (ID:{address})')
|
||||||
|
|
||||||
|
|
||||||
def filter_location(ctx, location):
|
def filter_location(ctx, location):
|
||||||
if not ctx.key_drop_mode and ('Key Drop' in location or 'Pot Key' in location):
|
if (not ctx.key_drop_mode and location in PotShuffle.key_drop_data
|
||||||
|
and PotShuffle.key_drop_data[location][0] == 'Drop'):
|
||||||
|
return True
|
||||||
|
if (not ctx.pottery_mode and location in PotShuffle.key_drop_data
|
||||||
|
and PotShuffle.key_drop_data[location][0] == 'Pot'):
|
||||||
return True
|
return True
|
||||||
if not ctx.shop_mode and location in Regions.flat_normal_shops:
|
if not ctx.shop_mode and location in Regions.flat_normal_shops:
|
||||||
return True
|
return True
|
||||||
@@ -821,6 +839,31 @@ def filter_location(ctx, location):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def init_lookups(ctx):
|
||||||
|
ctx.lookup_id_to_name = {x: y for x, y in Regions.lookup_id_to_name.items()}
|
||||||
|
ctx.lookup_name_to_id = {x: y for x, y in Regions.lookup_name_to_id.items()}
|
||||||
|
for location, datum in PotShuffle.key_drop_data.items():
|
||||||
|
type = datum[0]
|
||||||
|
if type == 'Drop':
|
||||||
|
location_id, super_tile, sprite_index = datum[1]
|
||||||
|
location_table_sprite_items[location] = (2 * super_tile, 0x8000 >> sprite_index)
|
||||||
|
ctx.lookup_name_to_id[location] = location_id
|
||||||
|
ctx.lookup_id_to_name[location_id] = location
|
||||||
|
for super_tile, pot_list in PotShuffle.vanilla_pots.items():
|
||||||
|
for pot_index, pot in enumerate(pot_list):
|
||||||
|
if pot.item != PotItem.Hole:
|
||||||
|
if pot.item == PotItem.Key:
|
||||||
|
loc_name = next(loc for loc, datum in PotShuffle.key_drop_data.items()
|
||||||
|
if datum[1] == super_tile)
|
||||||
|
else:
|
||||||
|
descriptor = 'Large Block' if pot.flags & PotFlags.Block else f'Pot #{pot_index+1}'
|
||||||
|
loc_name = f'{pot.room} {descriptor}'
|
||||||
|
location_table_pot_items[loc_name] = (2 * super_tile, 0x8000 >> pot_index)
|
||||||
|
location_id = Regions.pot_address(pot_index, super_tile)
|
||||||
|
ctx.lookup_name_to_id[loc_name] = location_id
|
||||||
|
ctx.lookup_id_to_name[location_id] = loc_name
|
||||||
|
|
||||||
|
|
||||||
async def track_locations(ctx : Context, roomid, roomdata):
|
async def track_locations(ctx : Context, roomid, roomdata):
|
||||||
new_locations = []
|
new_locations = []
|
||||||
|
|
||||||
@@ -832,9 +875,12 @@ async def track_locations(ctx : Context, roomid, roomdata):
|
|||||||
|
|
||||||
if ctx.mode_flags is None:
|
if ctx.mode_flags is None:
|
||||||
flags = await snes_read(ctx, MODE_FLAGS, 1)
|
flags = await snes_read(ctx, MODE_FLAGS, 1)
|
||||||
|
ctx.mode_flags = flags
|
||||||
ctx.key_drop_mode = flags[0] & 0x1
|
ctx.key_drop_mode = flags[0] & 0x1
|
||||||
ctx.shop_mode = flags[0] & 0x2
|
ctx.shop_mode = flags[0] & 0x2
|
||||||
ctx.retro_mode = flags[0] & 0x4
|
ctx.retro_mode = flags[0] & 0x4
|
||||||
|
ctx.pottery_mode = flags[0] & 0x8
|
||||||
|
ctx.mystery_mode = flags[0] & 0x10
|
||||||
|
|
||||||
def new_check(location):
|
def new_check(location):
|
||||||
ctx.locations_checked.add(location)
|
ctx.locations_checked.add(location)
|
||||||
@@ -842,8 +888,9 @@ async def track_locations(ctx : Context, roomid, roomdata):
|
|||||||
if ignored:
|
if ignored:
|
||||||
ctx.ignore_count += 1
|
ctx.ignore_count += 1
|
||||||
else:
|
else:
|
||||||
logging.info(f"New check: {location} ({len(ctx.locations_checked)-ctx.ignore_count}/{ctx.total_locations})")
|
total = '???' if ctx.mystery_mode else ctx.total_locations
|
||||||
new_locations.append(Regions.lookup_name_to_id[location])
|
logging.info(f"New check: {location} ({len(ctx.locations_checked)-ctx.ignore_count}/{total})")
|
||||||
|
new_locations.append(ctx.lookup_name_to_id[location])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if ctx.shop_mode or ctx.retro_mode:
|
if ctx.shop_mode or ctx.retro_mode:
|
||||||
@@ -908,6 +955,22 @@ async def track_locations(ctx : Context, roomid, roomdata):
|
|||||||
if misc_data[offset - 0x3c6] & mask != 0 and location not in ctx.locations_checked:
|
if misc_data[offset - 0x3c6] & mask != 0 and location not in ctx.locations_checked:
|
||||||
new_check(location)
|
new_check(location)
|
||||||
|
|
||||||
|
if not all([location in ctx.locations_checked for location in location_table_pot_items.keys()]):
|
||||||
|
pot_items_data = await snes_read(ctx, POT_ITEMS_SRAM_START, ITEM_SRAM_SIZE)
|
||||||
|
if pot_items_data is not None:
|
||||||
|
for location, (offset, mask) in location_table_pot_items.items():
|
||||||
|
pot_value = pot_items_data[offset] | (pot_items_data[offset + 1] << 8)
|
||||||
|
if pot_value & mask != 0 and location not in ctx.locations_checked:
|
||||||
|
new_check(location)
|
||||||
|
|
||||||
|
if not all([location in ctx.locations_checked for location in location_table_sprite_items.keys()]):
|
||||||
|
sprite_items_data = await snes_read(ctx, SPRITE_ITEMS_SRAM_START, ITEM_SRAM_SIZE)
|
||||||
|
if sprite_items_data is not None:
|
||||||
|
for location, (offset, mask) in location_table_sprite_items.items():
|
||||||
|
sprite_value = sprite_items_data[offset] | (sprite_items_data[offset + 1] << 8)
|
||||||
|
if sprite_value & mask != 0 and location not in ctx.locations_checked:
|
||||||
|
new_check(location)
|
||||||
|
|
||||||
await send_msgs(ctx.socket, [['LocationChecks', new_locations]])
|
await send_msgs(ctx.socket, [['LocationChecks', new_locations]])
|
||||||
|
|
||||||
async def game_watcher(ctx : Context):
|
async def game_watcher(ctx : Context):
|
||||||
@@ -955,7 +1018,7 @@ async def game_watcher(ctx : Context):
|
|||||||
item = ctx.items_received[recv_index]
|
item = ctx.items_received[recv_index]
|
||||||
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
|
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
|
||||||
color(get_item_name_from_id(item.item), 'red', 'bold'), color(ctx.player_names[item.player], 'yellow'),
|
color(get_item_name_from_id(item.item), 'red', 'bold'), color(ctx.player_names[item.player], 'yellow'),
|
||||||
get_location_name_from_address(item.location), recv_index + 1, len(ctx.items_received)))
|
get_location_name_from_address(ctx, item.location), recv_index + 1, len(ctx.items_received)))
|
||||||
recv_index += 1
|
recv_index += 1
|
||||||
snes_buffered_write(ctx, RECV_PROGRESS_ADDR, bytes([recv_index & 0xFF, (recv_index >> 8) & 0xFF]))
|
snes_buffered_write(ctx, RECV_PROGRESS_ADDR, bytes([recv_index & 0xFF, (recv_index >> 8) & 0xFF]))
|
||||||
snes_buffered_write(ctx, RECV_ITEM_ADDR, bytes([item.item]))
|
snes_buffered_write(ctx, RECV_ITEM_ADDR, bytes([item.item]))
|
||||||
@@ -969,7 +1032,7 @@ async def game_watcher(ctx : Context):
|
|||||||
|
|
||||||
if scout_location > 0 and scout_location not in ctx.locations_scouted:
|
if scout_location > 0 and scout_location not in ctx.locations_scouted:
|
||||||
ctx.locations_scouted.add(scout_location)
|
ctx.locations_scouted.add(scout_location)
|
||||||
logging.info(f'Scouting item at {list(Regions.lookup_id_to_name.keys())[scout_location - 1]}')
|
logging.info(f'Scouting item at {list(ctx.lookup_id_to_name.keys())[scout_location - 1]}')
|
||||||
await send_msgs(ctx.socket, [['LocationScouts', [scout_location]]])
|
await send_msgs(ctx.socket, [['LocationScouts', [scout_location]]])
|
||||||
await track_locations(ctx, roomid, roomdata)
|
await track_locations(ctx, roomid, roomdata)
|
||||||
|
|
||||||
@@ -984,6 +1047,7 @@ async def main():
|
|||||||
logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
||||||
|
|
||||||
ctx = Context(args.snes, args.connect, args.password)
|
ctx = Context(args.snes, args.connect, args.password)
|
||||||
|
init_lookups(ctx)
|
||||||
|
|
||||||
input_task = asyncio.create_task(console_loop(ctx))
|
input_task = asyncio.create_task(console_loop(ctx))
|
||||||
|
|
||||||
|
|||||||
+35
-5
@@ -10,8 +10,10 @@ import urllib.request
|
|||||||
import websockets
|
import websockets
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
|
from BaseClasses import PotItem, PotFlags
|
||||||
import Items
|
import Items
|
||||||
import Regions
|
import Regions
|
||||||
|
import PotShuffle
|
||||||
from MultiClient import ReceivedItem, get_item_name_from_id, get_location_name_from_address
|
from MultiClient import ReceivedItem, get_item_name_from_id, get_location_name_from_address
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
@@ -40,6 +42,9 @@ class Context:
|
|||||||
self.clients = []
|
self.clients = []
|
||||||
self.received_items = {}
|
self.received_items = {}
|
||||||
|
|
||||||
|
self.lookup_name_to_id = {}
|
||||||
|
self.lookup_id_to_name = {}
|
||||||
|
|
||||||
async def send_msgs(websocket, msgs):
|
async def send_msgs(websocket, msgs):
|
||||||
if not websocket or not websocket.open or websocket.closed:
|
if not websocket or not websocket.open or websocket.closed:
|
||||||
return
|
return
|
||||||
@@ -176,7 +181,8 @@ def register_location_checks(ctx : Context, team, slot, locations):
|
|||||||
recvd_items.append(new_item)
|
recvd_items.append(new_item)
|
||||||
if slot != target_player:
|
if slot != target_player:
|
||||||
broadcast_team(ctx, team, [['ItemSent', (slot, location, target_player, target_item)]])
|
broadcast_team(ctx, team, [['ItemSent', (slot, location, target_player, target_item)]])
|
||||||
logging.info('(Team #%d) %s sent %s to %s (%s)' % (team+1, ctx.player_names[(team, slot)], get_item_name_from_id(target_item), ctx.player_names[(team, target_player)], get_location_name_from_address(location)))
|
loc_name = get_location_name_from_address(ctx, location)
|
||||||
|
logging.info('(Team #%d) %s sent %s to %s (%s)' % (team+1, ctx.player_names[(team, slot)], get_item_name_from_id(target_item), ctx.player_names[(team, target_player)], loc_name))
|
||||||
found_items = True
|
found_items = True
|
||||||
send_new_items(ctx)
|
send_new_items(ctx)
|
||||||
|
|
||||||
@@ -249,11 +255,11 @@ async def process_client_cmd(ctx : Context, client : Client, cmd, args):
|
|||||||
return
|
return
|
||||||
locs = []
|
locs = []
|
||||||
for location in args:
|
for location in args:
|
||||||
if type(location) is not int or 0 >= location > len(Regions.lookup_id_to_name.keys()):
|
if type(location) is not int or 0 >= location > len(ctx.lookup_id_to_name.keys()):
|
||||||
await send_msgs(client.socket, [['InvalidArguments', 'LocationScouts']])
|
await send_msgs(client.socket, [['InvalidArguments', 'LocationScouts']])
|
||||||
return
|
return
|
||||||
loc_name = list(Regions.lookup_id_to_name.keys())[location - 1]
|
loc_name = list(ctx.lookup_id_to_name.keys())[location - 1]
|
||||||
target_item, target_player = ctx.locations[(Regions.lookup_name_to_id[loc_name], client.slot)]
|
target_item, target_player = ctx.locations[(ctx.lookup_name_to_id[loc_name], client.slot)]
|
||||||
|
|
||||||
replacements = {'SmallKey': 0xA2, 'BigKey': 0x9D, 'Compass': 0x8D, 'Map': 0x7D}
|
replacements = {'SmallKey': 0xA2, 'BigKey': 0x9D, 'Compass': 0x8D, 'Map': 0x7D}
|
||||||
item_type = [i[2] for i in Items.item_table.values() if type(i[3]) is int and i[3] == target_item]
|
item_type = [i[2] for i in Items.item_table.values() if type(i[3]) is int and i[3] == target_item]
|
||||||
@@ -339,6 +345,30 @@ async def console(ctx : Context):
|
|||||||
if command[0][0] != '/':
|
if command[0][0] != '/':
|
||||||
notify_all(ctx, '[Server]: ' + input)
|
notify_all(ctx, '[Server]: ' + input)
|
||||||
|
|
||||||
|
|
||||||
|
def init_lookups(ctx):
|
||||||
|
ctx.lookup_id_to_name = {x: y for x, y in Regions.lookup_id_to_name.items()}
|
||||||
|
ctx.lookup_name_to_id = {x: y for x, y in Regions.lookup_name_to_id.items()}
|
||||||
|
for location, datum in PotShuffle.key_drop_data.items():
|
||||||
|
type = datum[0]
|
||||||
|
if type == 'Drop':
|
||||||
|
location_id = datum[1][0]
|
||||||
|
ctx.lookup_name_to_id[location] = location_id
|
||||||
|
ctx.lookup_id_to_name[location_id] = location
|
||||||
|
for super_tile, pot_list in PotShuffle.vanilla_pots.items():
|
||||||
|
for pot_index, pot in enumerate(pot_list):
|
||||||
|
if pot.item != PotItem.Hole:
|
||||||
|
if pot.item == PotItem.Key:
|
||||||
|
loc_name = next(loc for loc, datum in PotShuffle.key_drop_data.items()
|
||||||
|
if datum[1] == super_tile)
|
||||||
|
else:
|
||||||
|
descriptor = 'Large Block' if pot.flags & PotFlags.Block else f'Pot #{pot_index+1}'
|
||||||
|
loc_name = f'{pot.room} {descriptor}'
|
||||||
|
location_id = Regions.pot_address(pot_index, super_tile)
|
||||||
|
ctx.lookup_name_to_id[loc_name] = location_id
|
||||||
|
ctx.lookup_id_to_name[location_id] = loc_name
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--host', default=None)
|
parser.add_argument('--host', default=None)
|
||||||
@@ -353,7 +383,7 @@ async def main():
|
|||||||
logging.basicConfig(format='[%(asctime)s] %(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
logging.basicConfig(format='[%(asctime)s] %(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
||||||
|
|
||||||
ctx = Context(args.host, args.port, args.password)
|
ctx = Context(args.host, args.port, args.password)
|
||||||
|
init_lookups(ctx)
|
||||||
ctx.data_filename = args.multidata
|
ctx.data_filename = args.multidata
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
+3
-3
@@ -173,7 +173,9 @@ def roll_settings(weights):
|
|||||||
ret.shufflelinks = get_choice('shufflelinks') == 'on'
|
ret.shufflelinks = get_choice('shufflelinks') == 'on'
|
||||||
ret.pseudoboots = get_choice('pseudoboots') == 'on'
|
ret.pseudoboots = get_choice('pseudoboots') == 'on'
|
||||||
ret.shopsanity = get_choice('shopsanity') == 'on'
|
ret.shopsanity = get_choice('shopsanity') == 'on'
|
||||||
ret.keydropshuffle = get_choice('keydropshuffle') == 'on'
|
ret.dropshuffle = get_choice('dropshuffle') == 'on'
|
||||||
|
ret.pottery = get_choice('pottery') if 'pottery' in weights else 'none'
|
||||||
|
ret.shuffleswitches = get_choice('shuffleswitches') == 'on'
|
||||||
ret.mixed_travel = get_choice('mixed_travel') if 'mixed_travel' in weights else 'prevent'
|
ret.mixed_travel = get_choice('mixed_travel') if 'mixed_travel' in weights else 'prevent'
|
||||||
ret.standardize_palettes = get_choice('standardize_palettes') if 'standardize_palettes' in weights else 'standardize'
|
ret.standardize_palettes = get_choice('standardize_palettes') if 'standardize_palettes' in weights else 'standardize'
|
||||||
|
|
||||||
@@ -243,8 +245,6 @@ def roll_settings(weights):
|
|||||||
|
|
||||||
ret.enemy_health = get_choice('enemy_health')
|
ret.enemy_health = get_choice('enemy_health')
|
||||||
|
|
||||||
ret.shufflepots = get_choice('pot_shuffle') == 'on'
|
|
||||||
|
|
||||||
ret.beemizer = 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', {})
|
||||||
|
|||||||
+309
-106
@@ -1,11 +1,11 @@
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from BaseClasses import PotItem, Pot, PotFlags, CrystalBarrier
|
from BaseClasses import PotItem, Pot, PotFlags, CrystalBarrier, LocationType
|
||||||
from Regions import key_drop_data
|
from Utils import int16_as_bytes, pc_to_snes
|
||||||
|
|
||||||
movable_switch_rooms = defaultdict(lambda: [],
|
movable_switch_rooms = defaultdict(lambda: [],
|
||||||
{'PoD Stalfos Basement': ['PoD Basement Ledge'],
|
{'PoD Stalfos Basement': ['PoD Basement Ledge'],
|
||||||
'Thieves Attic': ['Thieves Attic Hint'],
|
'Thieves Attic Switch': ['Thieves Attic Hint'],
|
||||||
'Mire Hub Switch': ['Mire Hub', 'Mire Hub Right']})
|
'Mire Hub Switch': ['Mire Hub', 'Mire Hub Right']})
|
||||||
|
|
||||||
invalid_key_rooms = {
|
invalid_key_rooms = {
|
||||||
@@ -18,21 +18,27 @@ invalid_key_rooms = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vanilla_pots = {
|
vanilla_pots = {
|
||||||
2: [Pot(80, 6, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(80, 8, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(44, 8, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(44, 10, PotItem.Nothing, 'Sewers Yet More Rats')],
|
2: [Pot(80, 6, PotItem.Nothing, 'Sewers Yet More Rats', PotFlags.LowerRegion),
|
||||||
|
Pot(80, 8, PotItem.Nothing, 'Sewers Yet More Rats', PotFlags.LowerRegion),
|
||||||
|
Pot(44, 8, PotItem.Nothing, 'Sewers Yet More Rats', PotFlags.LowerRegion),
|
||||||
|
Pot(44, 10, PotItem.Nothing, 'Sewers Yet More Rats', PotFlags.LowerRegion)],
|
||||||
4: [Pot(162, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 22, PotItem.Nothing, 'TR Dash Room'), Pot(162, 22, PotItem.Nothing, 'TR Dash Room'), Pot(204, 19, PotItem.Bomb, 'TR Tongue Pull'),
|
4: [Pot(162, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 22, PotItem.Nothing, 'TR Dash Room'), Pot(162, 22, PotItem.Nothing, 'TR Dash Room'), Pot(204, 19, PotItem.Bomb, 'TR Tongue Pull'),
|
||||||
Pot(240, 19, PotItem.Bomb, 'TR Tongue Pull')],
|
Pot(240, 19, PotItem.Bomb, 'TR Tongue Pull')],
|
||||||
9: [Pot(12, 4, PotItem.OneRupee, 'PoD Shooter Room'), Pot(48, 4, PotItem.Heart, 'PoD Shooter Room'), Pot(12, 12, PotItem.Switch, 'PoD Shooter Room')],
|
9: [Pot(12, 4, PotItem.OneRupee, 'PoD Shooter Room'), Pot(48, 4, PotItem.Heart, 'PoD Shooter Room'), Pot(12, 12, PotItem.Switch, 'PoD Shooter Room')],
|
||||||
10: [Pot(96, 8, PotItem.Heart, 'PoD Stalfos Basement'), Pot(104, 8, PotItem.Heart, 'PoD Stalfos Basement'), Pot(204, 11, PotItem.Switch, 'PoD Stalfos Basement'), Pot(100, 9, PotItem.Nothing, 'PoD Stalfos Basement'),
|
0xa: [Pot(96, 8, PotItem.Heart, 'PoD Stalfos Basement'), Pot(104, 8, PotItem.Heart, 'PoD Stalfos Basement'),
|
||||||
Pot(156, 17, PotItem.Bomb, 'PoD Basement Ledge', PotFlags.SwitchLogicChange), Pot(160, 17, PotItem.FiveArrows, 'PoD Basement Ledge', PotFlags.SwitchLogicChange)],
|
Pot(204, 11, PotItem.Switch, 'PoD Stalfos Basement'), Pot(100, 9, PotItem.Nothing, 'PoD Stalfos Basement'),
|
||||||
11: [Pot(202, 3, PotItem.Bomb, 'PoD Dark Pegs Left'), Pot(202, 12, PotItem.Bomb, 'PoD Dark Pegs Left')],
|
Pot(100, 7, PotItem.Nothing, 'PoD Stalfos Basement'),
|
||||||
17: [Pot(152, 19, PotItem.Nothing, 'Sewers Secret Room'), Pot(152, 15, PotItem.Nothing, 'Sewers Secret Room'), Pot(144, 15, PotItem.Heart, 'Sewers Secret Room'), Pot(160, 15, PotItem.Heart, 'Sewers Secret Room'),
|
Pot(156, 17, PotItem.Bomb, 'PoD Basement Ledge', PotFlags.SwitchLogicChange),
|
||||||
|
Pot(160, 17, PotItem.FiveArrows, 'PoD Basement Ledge', PotFlags.SwitchLogicChange)],
|
||||||
|
0xb: [Pot(202, 3, PotItem.Bomb, 'PoD Dark Pegs Left'), Pot(202, 12, PotItem.Bomb, 'PoD Dark Pegs Left')],
|
||||||
|
0x11: [Pot(152, 19, PotItem.Nothing, 'Sewers Secret Room'), Pot(152, 15, PotItem.Nothing, 'Sewers Secret Room'), Pot(144, 15, PotItem.Heart, 'Sewers Secret Room'), Pot(160, 15, PotItem.Heart, 'Sewers Secret Room'),
|
||||||
Pot(144, 19, PotItem.Heart, 'Sewers Secret Room'), Pot(160, 19, PotItem.Heart, 'Sewers Secret Room')],
|
Pot(144, 19, PotItem.Heart, 'Sewers Secret Room'), Pot(160, 19, PotItem.Heart, 'Sewers Secret Room')],
|
||||||
21: [Pot(96, 4, PotItem.Bomb, 'TR Pipe Pit'), Pot(100, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(104, 4, PotItem.Heart, 'TR Pipe Pit'), Pot(108, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(112, 4, PotItem.FiveArrows, 'TR Pipe Pit'),
|
0x15: [Pot(96, 4, PotItem.Bomb, 'TR Pipe Pit'), Pot(100, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(104, 4, PotItem.Heart, 'TR Pipe Pit'), Pot(108, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(112, 4, PotItem.FiveArrows, 'TR Pipe Pit'),
|
||||||
Pot(12, 6, PotItem.OneRupee, 'TR Pipe Pit'), Pot(16, 6, PotItem.FiveArrows, 'TR Pipe Pit'), Pot(20, 6, PotItem.FiveRupees, 'TR Pipe Pit'), Pot(70, 11, PotItem.BigMagic, 'TR Pipe Ledge')],
|
Pot(12, 6, PotItem.OneRupee, 'TR Pipe Pit'), Pot(16, 6, PotItem.FiveArrows, 'TR Pipe Pit'), Pot(20, 6, PotItem.FiveRupees, 'TR Pipe Pit'), Pot(70, 11, PotItem.BigMagic, 'TR Pipe Ledge')],
|
||||||
22: [Pot(188, 3, PotItem.Heart, 'Swamp I'), Pot(192, 3, PotItem.Heart, 'Swamp I'), Pot(188, 4, PotItem.SmallMagic, 'Swamp I'), Pot(192, 4, PotItem.SmallMagic, 'Swamp I'), Pot(188, 5, PotItem.FiveArrows, 'Swamp I'),
|
0x16: [Pot(188, 3, PotItem.Heart, 'Swamp I'), Pot(192, 3, PotItem.Heart, 'Swamp I'), Pot(188, 4, PotItem.SmallMagic, 'Swamp I'), Pot(192, 4, PotItem.SmallMagic, 'Swamp I'), Pot(188, 5, PotItem.FiveArrows, 'Swamp I'),
|
||||||
Pot(192, 5, PotItem.FiveArrows, 'Swamp I'), Pot(188, 6, PotItem.Bomb, 'Swamp I'), Pot(192, 6, PotItem.Bomb, 'Swamp I'), Pot(240, 19, PotItem.Key, 'Swamp Waterway')],
|
Pot(192, 5, PotItem.FiveArrows, 'Swamp I'), Pot(188, 6, PotItem.Bomb, 'Swamp I'), Pot(192, 6, PotItem.Bomb, 'Swamp I'), Pot(240, 19, PotItem.Key, 'Swamp Waterway')],
|
||||||
23: [Pot(100, 13, PotItem.Heart, 'Hera 5F'), Pot(100, 14, PotItem.Heart, 'Hera 5F'), Pot(100, 15, PotItem.Heart, 'Hera 5F'), Pot(100, 16, PotItem.Heart, 'Hera 5F'), Pot(100, 17, PotItem.Heart, 'Hera 5F'), Pot(100, 18, PotItem.Heart, 'Hera 5F'),
|
0x17: [Pot(100, 13, PotItem.Heart, 'Hera 5F Pot Block'), Pot(100, 14, PotItem.Heart, 'Hera 5F Pot Block'), Pot(100, 15, PotItem.Heart, 'Hera 5F Pot Block'), Pot(100, 16, PotItem.Heart, 'Hera 5F Pot Block'), Pot(100, 17, PotItem.Heart, 'Hera 5F Pot Block'), Pot(100, 18, PotItem.Heart, 'Hera 5F Pot Block'),
|
||||||
Pot(104, 13, PotItem.Heart, 'Hera 5F'), Pot(104, 14, PotItem.Heart, 'Hera 5F'), Pot(104, 15, PotItem.Heart, 'Hera 5F'), Pot(104, 16, PotItem.Heart, 'Hera 5F'), Pot(104, 17, PotItem.Heart, 'Hera 5F'), Pot(104, 18, PotItem.Heart, 'Hera 5F')],
|
Pot(104, 13, PotItem.Heart, 'Hera 5F Pot Block'), Pot(104, 14, PotItem.Heart, 'Hera 5F Pot Block'), Pot(104, 15, PotItem.Heart, 'Hera 5F Pot Block'), Pot(104, 16, PotItem.Heart, 'Hera 5F Pot Block'), Pot(104, 17, PotItem.Heart, 'Hera 5F Pot Block'), Pot(104, 18, PotItem.Heart, 'Hera 5F Pot Block')],
|
||||||
26: [Pot(28, 5, PotItem.Bomb, 'PoD Falling Bridge Ledge'), Pot(32, 5, PotItem.Bomb, 'PoD Falling Bridge Ledge'), Pot(28, 27, PotItem.Bomb, 'PoD Falling Bridge'), Pot(32, 27, PotItem.Bomb, 'PoD Falling Bridge'),
|
26: [Pot(28, 5, PotItem.Bomb, 'PoD Falling Bridge Ledge'), Pot(32, 5, PotItem.Bomb, 'PoD Falling Bridge Ledge'), Pot(28, 27, PotItem.Bomb, 'PoD Falling Bridge'), Pot(32, 27, PotItem.Bomb, 'PoD Falling Bridge'),
|
||||||
Pot(232, 19, PotItem.Nothing, 'PoD Harmless Hellway'), Pot(212, 19, PotItem.Nothing, 'PoD Harmless Hellway')],
|
Pot(232, 19, PotItem.Nothing, 'PoD Harmless Hellway'), Pot(212, 19, PotItem.Nothing, 'PoD Harmless Hellway')],
|
||||||
27: [Pot(20, 23, PotItem.FiveArrows, 'PoD Mimics 2'), Pot(40, 23, PotItem.FiveArrows, 'PoD Mimics 2')],
|
27: [Pot(20, 23, PotItem.FiveArrows, 'PoD Mimics 2'), Pot(40, 23, PotItem.FiveArrows, 'PoD Mimics 2')],
|
||||||
@@ -52,32 +58,50 @@ vanilla_pots = {
|
|||||||
Pot(44, 7, PotItem.Bomb, 'PoD Sexy Statue'), Pot(146, 21, PotItem.Bomb, 'PoD Map Balcony'), Pot(170, 21, PotItem.FiveArrows, 'PoD Map Balcony'), Pot(146, 22, PotItem.Bomb, 'PoD Map Balcony'),
|
Pot(44, 7, PotItem.Bomb, 'PoD Sexy Statue'), Pot(146, 21, PotItem.Bomb, 'PoD Map Balcony'), Pot(170, 21, PotItem.FiveArrows, 'PoD Map Balcony'), Pot(146, 22, PotItem.Bomb, 'PoD Map Balcony'),
|
||||||
Pot(170, 22, PotItem.FiveArrows, 'PoD Map Balcony')],
|
Pot(170, 22, PotItem.FiveArrows, 'PoD Map Balcony')],
|
||||||
44: [Pot(108, 24, PotItem.Heart, 'Hookshot Cave (Middle)'), Pot(112, 24, PotItem.Heart, 'Hookshot Cave (Middle)')],
|
44: [Pot(108, 24, PotItem.Heart, 'Hookshot Cave (Middle)'), Pot(112, 24, PotItem.Heart, 'Hookshot Cave (Middle)')],
|
||||||
47: [Pot(28, 7, PotItem.Heart, 'Kakariko Well (top)'), Pot(32, 7, PotItem.Heart, 'Kakariko Well (top)'), Pot(28, 9, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(32, 9, PotItem.FiveRupees, 'Kakariko Well (top)'),
|
0x2F: [Pot(28, 7, PotItem.Heart, 'Kakariko Well (back)'), Pot(32, 7, PotItem.Heart, 'Kakariko Well (back)'),
|
||||||
Pot(172, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(180, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(104, 27, PotItem.Heart, 'Kakariko Well (bottom)'), Pot(104, 28, PotItem.Heart, 'Kakariko Well (bottom)')],
|
Pot(28, 9, PotItem.FiveRupees, 'Kakariko Well (back)'), Pot(32, 9, PotItem.FiveRupees, 'Kakariko Well (back)'),
|
||||||
|
Pot(172, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(180, 19, PotItem.FiveRupees, 'Kakariko Well (top)'),
|
||||||
|
Pot(104, 27, PotItem.Heart, 'Kakariko Well (bottom)'), Pot(104, 28, PotItem.Heart, 'Kakariko Well (bottom)')],
|
||||||
49: [Pot(92, 28, PotItem.Bomb, 'Hera Beetles'), Pot(96, 28, PotItem.Nothing, 'Hera Beetles')],
|
49: [Pot(92, 28, PotItem.Bomb, 'Hera Beetles'), Pot(96, 28, PotItem.Nothing, 'Hera Beetles')],
|
||||||
50: [Pot(28, 13, PotItem.SmallMagic, 'Sewers Dark Cross')],
|
50: [Pot(28, 13, PotItem.SmallMagic, 'Sewers Dark Cross')],
|
||||||
52: [Pot(78, 8, PotItem.FiveRupees, 'Swamp Barrier Ledge'), Pot(92, 8, PotItem.FiveRupees, 'Swamp Barrier Ledge')],
|
52: [Pot(78, 8, PotItem.FiveRupees, 'Swamp Barrier Ledge'), Pot(92, 8, PotItem.FiveRupees, 'Swamp Barrier Ledge')],
|
||||||
53: [Pot(60, 6, PotItem.Key, 'Swamp Trench 2 Alcove'), Pot(20, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(24, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(28, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'),
|
0x35: [Pot(60, 6, PotItem.Key, 'Swamp Trench 2 Alcove'), Pot(20, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(24, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(28, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'),
|
||||||
Pot(32, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(36, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(48, 20, PotItem.Heart, 'Swamp Trench 2 Departure'), Pot(76, 23, PotItem.Nothing, 'Swamp Trench 2 Pots'),
|
Pot(32, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(36, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(48, 20, PotItem.Heart, 'Swamp Trench 2 Departure'), Pot(76, 23, PotItem.Nothing, 'Swamp Trench 2 Pots'),
|
||||||
Pot(88, 23, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(100, 27, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(242, 28, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(240, 22, PotItem.Heart, 'Swamp Trench 2 Pots'),
|
Pot(88, 23, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(100, 27, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(242, 28, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(240, 22, PotItem.Heart, 'Swamp Trench 2 Pots'),
|
||||||
Pot(76, 28, PotItem.Heart, 'Swamp Trench 2 Pots')],
|
Pot(76, 28, PotItem.Heart, 'Swamp Trench 2 Pots')],
|
||||||
54: [Pot(108, 4, PotItem.Bomb, 'Swamp Hub Dead Ledge'), Pot(112, 4, PotItem.FiveRupees, 'Swamp Hub Dead Ledge'), Pot(10, 16, PotItem.Heart, 'Swamp Hub'), Pot(154, 15, PotItem.Nothing, 'Swamp Hub'), Pot(114, 16, PotItem.Key, 'Swamp Hub'),
|
0x36: [Pot(108, 4, PotItem.Bomb, 'Swamp Hub Dead Ledge'), Pot(112, 4, PotItem.FiveRupees, 'Swamp Hub Dead Ledge'),
|
||||||
Pot(222, 15, PotItem.Nothing, 'Swamp Hub'), Pot(188, 5, PotItem.Nothing, 'Swamp Hub North Ledge'), Pot(192, 5, PotItem.Nothing, 'Swamp Hub North Ledge')],
|
Pot(10, 16, PotItem.Heart, 'Swamp Hub Side Ledges'), Pot(154, 15, PotItem.Nothing, 'Swamp Hub Side Ledges'),
|
||||||
55: [Pot(60, 6, PotItem.Key, 'Swamp Trench 1 Alcove'), Pot(48, 20, PotItem.Nothing, 'Swamp Trench 1 Key Ledge')],
|
Pot(114, 16, PotItem.Key, 'Swamp Hub Side Ledges'), Pot(222, 15, PotItem.Nothing, 'Swamp Hub Side Ledges'),
|
||||||
56: [Pot(164, 12, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 13, PotItem.FiveRupees, 'Swamp Pot Row'), Pot(164, 18, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 19, PotItem.Key, 'Swamp Pot Row')],
|
Pot(188, 5, PotItem.Nothing, 'Swamp Hub North Ledge'),
|
||||||
57: [Pot(12, 20, PotItem.Heart, 'Skull Spike Corner'), Pot(48, 28, PotItem.FiveArrows, 'Skull Spike Corner'), Pot(100, 22, PotItem.SmallMagic, 'Skull Final Drop'), Pot(100, 26, PotItem.FiveArrows, 'Skull Final Drop')],
|
Pot(192, 5, PotItem.Nothing, 'Swamp Hub North Ledge')],
|
||||||
60: [Pot(24, 8, PotItem.SmallMagic, 'Hookshot Cave (Front)'), Pot(64, 12, PotItem.FiveRupees, 'Hookshot Cave (Front)'), Pot(20, 14, PotItem.OneRupee, 'Hookshot Cave (Front)'), Pot(20, 19, PotItem.Nothing, 'Hookshot Cave (Front)'),
|
0x37: [Pot(60, 6, PotItem.Key, 'Swamp Trench 1 Alcove'), Pot(48, 20, PotItem.Nothing, 'Swamp Trench 1 Key Ledge')],
|
||||||
Pot(68, 18, PotItem.FiveRupees, 'Hookshot Cave (Front)'), Pot(96, 19, PotItem.Heart, 'Hookshot Cave (Front)'), Pot(64, 20, PotItem.FiveRupees, 'Hookshot Cave (Front)'), Pot(64, 26, PotItem.FiveRupees, 'Hookshot Cave (Front)')],
|
0x38: [Pot(164, 12, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 13, PotItem.FiveRupees, 'Swamp Pot Row'), Pot(164, 18, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 19, PotItem.Key, 'Swamp Pot Row')],
|
||||||
61: [Pot(76, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(112, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(24, 22, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(40, 22, PotItem.FiveArrows, 'GT Crystal Inner Circle'),
|
0x39: [Pot(12, 20, PotItem.Heart, 'Skull Spike Corner'), Pot(48, 28, PotItem.FiveArrows, 'Skull Spike Corner'), Pot(100, 22, PotItem.SmallMagic, 'Skull Final Drop'), Pot(100, 26, PotItem.FiveArrows, 'Skull Final Drop')],
|
||||||
|
0x3C: [Pot(24, 8, PotItem.SmallMagic, 'Hookshot Cave (Hook Islands)'),
|
||||||
|
Pot(64, 12, PotItem.FiveRupees, 'Hookshot Cave (Hook Islands)'),
|
||||||
|
Pot(20, 14, PotItem.OneRupee, 'Hookshot Cave (Hook Islands)'),
|
||||||
|
Pot(20, 19, PotItem.Nothing, 'Hookshot Cave (Hook Islands)'),
|
||||||
|
Pot(68, 18, PotItem.FiveRupees, 'Hookshot Cave (Bonk Islands)'),
|
||||||
|
Pot(96, 19, PotItem.Heart, 'Hookshot Cave (Front)'),
|
||||||
|
Pot(64, 20, PotItem.FiveRupees, 'Hookshot Cave (Bonk Islands)'),
|
||||||
|
Pot(64, 26, PotItem.FiveRupees, 'Hookshot Cave (Bonk Islands)')],
|
||||||
|
0x3D: [Pot(76, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(112, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(24, 22, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(40, 22, PotItem.FiveArrows, 'GT Crystal Inner Circle'),
|
||||||
Pot(32, 24, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(20, 26, PotItem.FiveRupees, 'GT Crystal Inner Circle'), Pot(36, 26, PotItem.BigMagic, 'GT Crystal Inner Circle')],
|
Pot(32, 24, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(20, 26, PotItem.FiveRupees, 'GT Crystal Inner Circle'), Pot(36, 26, PotItem.BigMagic, 'GT Crystal Inner Circle')],
|
||||||
62: [Pot(96, 6, PotItem.Bomb, 'Ice Stalfos Hint'), Pot(100, 6, PotItem.SmallMagic, 'Ice Stalfos Hint'), Pot(88, 10, PotItem.Heart, 'Ice Stalfos Hint'), Pot(92, 10, PotItem.SmallMagic, 'Ice Stalfos Hint')],
|
0x3E: [Pot(96, 6, PotItem.Bomb, 'Ice Stalfos Hint'), Pot(100, 6, PotItem.SmallMagic, 'Ice Stalfos Hint'), Pot(88, 10, PotItem.Heart, 'Ice Stalfos Hint'), Pot(92, 10, PotItem.SmallMagic, 'Ice Stalfos Hint')],
|
||||||
63: [Pot(12, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(20, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(12, 26, PotItem.Bomb, 'Ice Hammer Block'), Pot(20, 26, PotItem.Bomb, 'Ice Hammer Block'),
|
0x3F: [Pot(12, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(20, 25, PotItem.OneRupee, 'Ice Hammer Block'),
|
||||||
Pot(12, 27, PotItem.Switch, 'Ice Hammer Block'), Pot(20, 27, PotItem.Heart, 'Ice Hammer Block'), Pot(28, 23, PotItem.Key, 'Ice Hammer Block')],
|
Pot(12, 26, PotItem.Bomb, 'Ice Hammer Block'), Pot(20, 26, PotItem.Bomb, 'Ice Hammer Block'),
|
||||||
65: [Pot(100, 10, PotItem.Heart, 'Sewers Behind Tapestry'), Pot(52, 15, PotItem.OneRupee, 'Sewers Behind Tapestry'), Pot(52, 16, PotItem.SmallMagic, 'Sewers Behind Tapestry'), Pot(148, 22, PotItem.SmallMagic, 'Sewers Behind Tapestry')],
|
Pot(12, 27, PotItem.Switch, 'Ice Hammer Block'), Pot(20, 27, PotItem.Heart, 'Ice Hammer Block'),
|
||||||
67: [Pot(66, 4, PotItem.FiveArrows, 'Desert Wall Slide'), Pot(78, 4, PotItem.SmallMagic, 'Desert Wall Slide'), Pot(66, 9, PotItem.Heart, 'Desert Wall Slide'), Pot(78, 9, PotItem.Heart, 'Desert Wall Slide'),
|
Pot(28, 23, PotItem.Key, 'Ice Hammer Block', PotFlags.Block)],
|
||||||
|
0x41: [Pot(100, 10, PotItem.Heart, 'Sewers Behind Tapestry'), Pot(52, 15, PotItem.OneRupee, 'Sewers Behind Tapestry'), Pot(52, 16, PotItem.SmallMagic, 'Sewers Behind Tapestry'), Pot(148, 22, PotItem.SmallMagic, 'Sewers Behind Tapestry')],
|
||||||
|
0x43: [Pot(66, 4, PotItem.FiveArrows, 'Desert Wall Slide'), Pot(78, 4, PotItem.SmallMagic, 'Desert Wall Slide'), Pot(66, 9, PotItem.Heart, 'Desert Wall Slide'), Pot(78, 9, PotItem.Heart, 'Desert Wall Slide'),
|
||||||
Pot(112, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 20, PotItem.Nothing, 'Desert Tiles 2'), Pot(112, 20, PotItem.Key, 'Desert Tiles 2')],
|
Pot(112, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 20, PotItem.Nothing, 'Desert Tiles 2'), Pot(112, 20, PotItem.Key, 'Desert Tiles 2')],
|
||||||
69: [Pot(12, 4, PotItem.FiveArrows, 'Thieves Basement Block'), Pot(48, 12, PotItem.FiveArrows, 'Thieves Basement Block'), Pot(92, 11, PotItem.Nothing, "Thieves Blind's Cell"), Pot(108, 11, PotItem.Heart, "Thieves Blind's Cell"),
|
0x44: [Pot(204, 7, PotItem.Nothing, 'Thieves Conveyor Bridge', PotFlags.Block)],
|
||||||
Pot(220, 16, PotItem.SmallMagic, "Thieves Blind's Cell"), Pot(236, 16, PotItem.Heart, "Thieves Blind's Cell")],
|
0x45: [Pot(12, 4, PotItem.FiveArrows, 'Thieves Basement Block'),
|
||||||
|
Pot(48, 12, PotItem.FiveArrows, 'Thieves Basement Block'),
|
||||||
|
Pot(92, 11, PotItem.Nothing, "Thieves Blind's Cell Interior"), Pot(108, 11, PotItem.Heart, "Thieves Blind's Cell Interior"),
|
||||||
|
Pot(220, 16, PotItem.SmallMagic, "Thieves Blind's Cell Interior"),
|
||||||
|
Pot(236, 16, PotItem.Heart, "Thieves Blind's Cell Interior"),
|
||||||
|
Pot(0x9C, 7, PotItem.Nothing, 'Thieves Basement Block', PotFlags.Block)],
|
||||||
70: [Pot(96, 5, PotItem.Heart, 'Swamp Donut Top'), Pot(28, 27, PotItem.Heart, 'Swamp Donut Bottom')],
|
70: [Pot(96, 5, PotItem.Heart, 'Swamp Donut Top'), Pot(28, 27, PotItem.Heart, 'Swamp Donut Bottom')],
|
||||||
73: [Pot(104, 15, PotItem.SmallMagic, 'Skull Torch Room'), Pot(104, 16, PotItem.SmallMagic, 'Skull Torch Room'), Pot(156, 27, PotItem.Nothing, 'Skull Star Pits'), Pot(172, 24, PotItem.Nothing, 'Skull Star Pits'),
|
73: [Pot(104, 15, PotItem.SmallMagic, 'Skull Torch Room'), Pot(104, 16, PotItem.SmallMagic, 'Skull Torch Room'), Pot(156, 27, PotItem.Nothing, 'Skull Star Pits'), Pot(172, 24, PotItem.Nothing, 'Skull Star Pits'),
|
||||||
Pot(172, 23, PotItem.Nothing, 'Skull Star Pits'), Pot(144, 20, PotItem.Nothing, 'Skull Star Pits'), Pot(144, 19, PotItem.SmallMagic, 'Skull Star Pits'), Pot(172, 20, PotItem.Heart, 'Skull Star Pits'),
|
Pot(172, 23, PotItem.Nothing, 'Skull Star Pits'), Pot(144, 20, PotItem.Nothing, 'Skull Star Pits'), Pot(144, 19, PotItem.SmallMagic, 'Skull Star Pits'), Pot(172, 20, PotItem.Heart, 'Skull Star Pits'),
|
||||||
@@ -87,12 +111,13 @@ vanilla_pots = {
|
|||||||
75: [Pot(20, 6, PotItem.FiveArrows, 'PoD Mimics 1'), Pot(40, 6, PotItem.Heart, 'PoD Mimics 1')],
|
75: [Pot(20, 6, PotItem.FiveArrows, 'PoD Mimics 1'), Pot(40, 6, PotItem.Heart, 'PoD Mimics 1')],
|
||||||
78: [Pot(140, 7, PotItem.Nothing, 'Ice Bomb Jump Catwalk'), Pot(48, 10, PotItem.Nothing, 'Ice Bomb Jump Catwalk'), Pot(140, 11, PotItem.Switch, 'Ice Bomb Jump Catwalk'), Pot(28, 12, PotItem.Heart, 'Ice Bomb Jump Catwalk'),
|
78: [Pot(140, 7, PotItem.Nothing, 'Ice Bomb Jump Catwalk'), Pot(48, 10, PotItem.Nothing, 'Ice Bomb Jump Catwalk'), Pot(140, 11, PotItem.Switch, 'Ice Bomb Jump Catwalk'), Pot(28, 12, PotItem.Heart, 'Ice Bomb Jump Catwalk'),
|
||||||
Pot(112, 12, PotItem.SmallMagic, 'Ice Narrow Corridor')],
|
Pot(112, 12, PotItem.SmallMagic, 'Ice Narrow Corridor')],
|
||||||
80: [Pot(96, 38, PotItem.Heart, 'Hyrule Castle West Hall'), Pot(100, 38, PotItem.Heart, 'Hyrule Castle West Hall')],
|
0x50: [Pot(96, 0x6, PotItem.Heart, 'Hyrule Castle West Hall', PotFlags.LowerRegion),
|
||||||
|
Pot(100, 0x6, PotItem.Heart, 'Hyrule Castle West Hall', PotFlags.LowerRegion)],
|
||||||
82: [Pot(138, 3, PotItem.Heart, 'Hyrule Castle East Hall'), Pot(194, 26, PotItem.Heart, 'Hyrule Castle East Hall')],
|
82: [Pot(138, 3, PotItem.Heart, 'Hyrule Castle East Hall'), Pot(194, 26, PotItem.Heart, 'Hyrule Castle East Hall')],
|
||||||
83: [Pot(92, 11, PotItem.Heart, 'Desert Beamos Hall'), Pot(96, 11, PotItem.SmallMagic, 'Desert Beamos Hall'), Pot(100, 11, PotItem.Key, 'Desert Beamos Hall'), Pot(104, 11, PotItem.Heart, 'Desert Beamos Hall')],
|
0x53: [Pot(92, 11, PotItem.Heart, 'Desert Beamos Hall'), Pot(96, 11, PotItem.SmallMagic, 'Desert Beamos Hall'), Pot(100, 11, PotItem.Key, 'Desert Beamos Hall'), Pot(104, 11, PotItem.Heart, 'Desert Beamos Hall')],
|
||||||
84: [Pot(186, 25, PotItem.FiveRupees, 'Swamp Attic'), Pot(186, 26, PotItem.Heart, 'Swamp Attic'), Pot(186, 27, PotItem.Heart, 'Swamp Attic'), Pot(186, 28, PotItem.Heart, 'Swamp Attic')],
|
84: [Pot(186, 25, PotItem.FiveRupees, 'Swamp Attic'), Pot(186, 26, PotItem.Heart, 'Swamp Attic'), Pot(186, 27, PotItem.Heart, 'Swamp Attic'), Pot(186, 28, PotItem.Heart, 'Swamp Attic')],
|
||||||
85: [Pot(230, 24, PotItem.SmallMagic, 'Secret Passage'), Pot(230, 25, PotItem.SmallMagic, 'Secret Passage')],
|
85: [Pot(230, 24, PotItem.SmallMagic, 'Hyrule Castle Secret Entrance'), Pot(230, 25, PotItem.SmallMagic, 'Hyrule Castle Secret Entrance')],
|
||||||
86: [Pot(100, 6, PotItem.Nothing, 'Skull Back Drop'), Pot(96, 10, PotItem.Nothing, 'Skull Back Drop'), Pot(92, 10, PotItem.Nothing, 'Skull Back Drop'), Pot(20, 6, PotItem.SmallMagic, 'Skull X Room'),
|
0x56: [Pot(100, 6, PotItem.Nothing, 'Skull Back Drop'), Pot(96, 10, PotItem.Nothing, 'Skull Back Drop'), Pot(92, 10, PotItem.Nothing, 'Skull Back Drop'), Pot(20, 6, PotItem.SmallMagic, 'Skull X Room'),
|
||||||
Pot(40, 6, PotItem.SmallMagic, 'Skull X Room'), Pot(24, 7, PotItem.SmallMagic, 'Skull X Room'), Pot(36, 7, PotItem.SmallMagic, 'Skull X Room'), Pot(12, 8, PotItem.Heart, 'Skull X Room'), Pot(48, 8, PotItem.Heart, 'Skull X Room'),
|
Pot(40, 6, PotItem.SmallMagic, 'Skull X Room'), Pot(24, 7, PotItem.SmallMagic, 'Skull X Room'), Pot(36, 7, PotItem.SmallMagic, 'Skull X Room'), Pot(12, 8, PotItem.Heart, 'Skull X Room'), Pot(48, 8, PotItem.Heart, 'Skull X Room'),
|
||||||
Pot(24, 9, PotItem.SmallMagic, 'Skull X Room'), Pot(36, 9, PotItem.SmallMagic, 'Skull X Room'), Pot(20, 10, PotItem.FiveRupees, 'Skull X Room'), Pot(40, 10, PotItem.FiveRupees, 'Skull X Room'), Pot(12, 20, PotItem.Key, 'Skull 2 West Lobby'),
|
Pot(24, 9, PotItem.SmallMagic, 'Skull X Room'), Pot(36, 9, PotItem.SmallMagic, 'Skull X Room'), Pot(20, 10, PotItem.FiveRupees, 'Skull X Room'), Pot(40, 10, PotItem.FiveRupees, 'Skull X Room'), Pot(12, 20, PotItem.Key, 'Skull 2 West Lobby'),
|
||||||
Pot(48, 20, PotItem.Nothing, 'Skull 2 West Lobby')],
|
Pot(48, 20, PotItem.Nothing, 'Skull 2 West Lobby')],
|
||||||
@@ -103,8 +128,13 @@ vanilla_pots = {
|
|||||||
Pot(96, 9, PotItem.Nothing, 'Skull Pot Circle'), Pot(92, 8, PotItem.Nothing, 'Skull Pot Circle'), Pot(108, 8, PotItem.Nothing, 'Skull Pot Circle'), Pot(108, 6, PotItem.Nothing, 'Skull Pot Circle'),
|
Pot(96, 9, PotItem.Nothing, 'Skull Pot Circle'), Pot(92, 8, PotItem.Nothing, 'Skull Pot Circle'), Pot(108, 8, PotItem.Nothing, 'Skull Pot Circle'), Pot(108, 6, PotItem.Nothing, 'Skull Pot Circle'),
|
||||||
Pot(104, 5, PotItem.Nothing, 'Skull Pot Circle'), Pot(92, 6, PotItem.Nothing, 'Skull Pot Circle'), Pot(96, 5, PotItem.Bomb, 'Skull Pot Circle'), Pot(100, 5, PotItem.SmallMagic, 'Skull Pot Circle'),
|
Pot(104, 5, PotItem.Nothing, 'Skull Pot Circle'), Pot(92, 6, PotItem.Nothing, 'Skull Pot Circle'), Pot(96, 5, PotItem.Bomb, 'Skull Pot Circle'), Pot(100, 5, PotItem.SmallMagic, 'Skull Pot Circle'),
|
||||||
Pot(92, 7, PotItem.Heart, 'Skull Pot Circle'), Pot(108, 7, PotItem.Heart, 'Skull Pot Circle'), Pot(100, 9, PotItem.SmallMagic, 'Skull Pot Circle'), Pot(104, 9, PotItem.Bomb, 'Skull Pot Circle')],
|
Pot(92, 7, PotItem.Heart, 'Skull Pot Circle'), Pot(108, 7, PotItem.Heart, 'Skull Pot Circle'), Pot(100, 9, PotItem.SmallMagic, 'Skull Pot Circle'), Pot(104, 9, PotItem.Bomb, 'Skull Pot Circle')],
|
||||||
89: [Pot(26, 43, PotItem.Heart, 'Skull 3 Lobby'), Pot(32, 40, PotItem.Nothing, 'Skull 3 Lobby'), Pot(76, 28, PotItem.Nothing, 'Skull East Bridge'), Pot(112, 28, PotItem.Nothing, 'Skull East Bridge')],
|
0x59: [Pot(26, 0xb, PotItem.Heart, 'Skull 3 Lobby', PotFlags.LowerRegion),
|
||||||
91: [Pot(218, 37, PotItem.Nothing, 'GT Hidden Spikes'), Pot(222, 37, PotItem.Switch, 'GT Hidden Spikes'), Pot(226, 37, PotItem.Nothing, 'GT Hidden Spikes')],
|
Pot(32, 8, PotItem.Nothing, 'Skull 3 Lobby', PotFlags.LowerRegion),
|
||||||
|
Pot(76, 28, PotItem.Nothing, 'Skull East Bridge'),
|
||||||
|
Pot(112, 28, PotItem.Nothing, 'Skull East Bridge')],
|
||||||
|
0x5B: [Pot(218, 0x5, PotItem.Nothing, 'GT Hidden Spikes', PotFlags.LowerRegion),
|
||||||
|
Pot(222, 0x5, PotItem.Switch, 'GT Hidden Spikes', PotFlags.LowerRegion),
|
||||||
|
Pot(226, 0x5, PotItem.Nothing, 'GT Hidden Spikes', PotFlags.LowerRegion)],
|
||||||
92: [Pot(228, 25, PotItem.Nothing, 'GT Refill'), Pot(104, 24, PotItem.Nothing, 'GT Refill'), Pot(228, 22, PotItem.Nothing, 'GT Refill'), Pot(216, 25, PotItem.Nothing, 'GT Refill'), Pot(84, 24, PotItem.Nothing, 'GT Refill'),
|
92: [Pot(228, 25, PotItem.Nothing, 'GT Refill'), Pot(104, 24, PotItem.Nothing, 'GT Refill'), Pot(228, 22, PotItem.Nothing, 'GT Refill'), Pot(216, 25, PotItem.Nothing, 'GT Refill'), Pot(84, 24, PotItem.Nothing, 'GT Refill'),
|
||||||
Pot(216, 22, PotItem.Nothing, 'GT Refill'), Pot(94, 22, PotItem.Bomb, 'GT Refill'), Pot(94, 26, PotItem.BigMagic, 'GT Refill')],
|
Pot(216, 22, PotItem.Nothing, 'GT Refill'), Pot(94, 22, PotItem.Bomb, 'GT Refill'), Pot(94, 26, PotItem.BigMagic, 'GT Refill')],
|
||||||
93: [Pot(16, 5, PotItem.Bomb, 'GT Gauntlet 2'), Pot(44, 5, PotItem.FiveRupees, 'GT Gauntlet 2'), Pot(16, 11, PotItem.OneRupee, 'GT Gauntlet 2'), Pot(44, 11, PotItem.FiveArrows, 'GT Gauntlet 2'), Pot(12, 20, PotItem.FiveArrows, 'GT Gauntlet 3'),
|
93: [Pot(16, 5, PotItem.Bomb, 'GT Gauntlet 2'), Pot(44, 5, PotItem.FiveRupees, 'GT Gauntlet 2'), Pot(16, 11, PotItem.OneRupee, 'GT Gauntlet 2'), Pot(44, 11, PotItem.FiveArrows, 'GT Gauntlet 2'), Pot(12, 20, PotItem.FiveArrows, 'GT Gauntlet 3'),
|
||||||
@@ -113,14 +143,23 @@ vanilla_pots = {
|
|||||||
95: [Pot(44, 27, PotItem.Switch, 'Ice Spike Room')],
|
95: [Pot(44, 27, PotItem.Switch, 'Ice Spike Room')],
|
||||||
96: [Pot(76, 4, PotItem.Heart, 'Hyrule Castle West Lobby'), Pot(112, 4, PotItem.Heart, 'Hyrule Castle West Lobby')],
|
96: [Pot(76, 4, PotItem.Heart, 'Hyrule Castle West Lobby'), Pot(112, 4, PotItem.Heart, 'Hyrule Castle West Lobby')],
|
||||||
98: [Pot(208, 21, PotItem.Heart, 'Hyrule Castle East Lobby')],
|
98: [Pot(208, 21, PotItem.Heart, 'Hyrule Castle East Lobby')],
|
||||||
99: [Pot(48, 4, PotItem.Nothing, 'Desert Tiles 1'), Pot(12, 4, PotItem.Nothing, 'Desert Tiles 1'), Pot(12, 8, PotItem.Nothing, 'Desert Tiles 1'), Pot(48, 12, PotItem.Nothing, 'Desert Tiles 1'), Pot(48, 8, PotItem.Heart, 'Desert Tiles 1'),
|
0x63: [Pot(48, 4, PotItem.Nothing, 'Desert Tiles 1'), Pot(12, 4, PotItem.Nothing, 'Desert Tiles 1'), Pot(12, 8, PotItem.Nothing, 'Desert Tiles 1'), Pot(48, 12, PotItem.Nothing, 'Desert Tiles 1'), Pot(48, 8, PotItem.Heart, 'Desert Tiles 1'),
|
||||||
Pot(12, 12, PotItem.Key, 'Desert Tiles 1')],
|
Pot(12, 12, PotItem.Key, 'Desert Tiles 1')],
|
||||||
100: [Pot(12, 22, PotItem.Bomb, 'Thieves Attic Hint', PotFlags.SwitchLogicChange), Pot(16, 22, PotItem.Bomb, 'Thieves Attic Hint', PotFlags.SwitchLogicChange), Pot(20, 22, PotItem.Bomb, 'Thieves Attic Hint', PotFlags.SwitchLogicChange),
|
0x64: [Pot(12, 22, PotItem.Bomb, 'Thieves Attic Hint', PotFlags.SwitchLogicChange),
|
||||||
Pot(36, 28, PotItem.Bomb, 'Thieves Attic'), Pot(40, 28, PotItem.SmallMagic, 'Thieves Attic'),
|
Pot(16, 22, PotItem.Bomb, 'Thieves Attic Hint', PotFlags.SwitchLogicChange),
|
||||||
Pot(44, 28, PotItem.SmallMagic, 'Thieves Attic'), Pot(48, 28, PotItem.Switch, 'Thieves Attic')],
|
Pot(20, 22, PotItem.Bomb, 'Thieves Attic Hint', PotFlags.SwitchLogicChange),
|
||||||
101: [Pot(100, 28, PotItem.Bomb, 'Thieves Attic Window'), Pot(104, 28, PotItem.Bomb, 'Thieves Attic Window')],
|
Pot(36, 28, PotItem.Bomb, 'Thieves Attic Switch'), Pot(40, 28, PotItem.SmallMagic, 'Thieves Attic Switch'),
|
||||||
102: [Pot(48, 37, PotItem.FiveArrows, 'Swamp Refill'), Pot(52, 37, PotItem.Bomb, 'Swamp Refill'), Pot(56, 37, PotItem.FiveRupees, 'Swamp Refill'), Pot(48, 38, PotItem.FiveArrows, 'Swamp Refill'), Pot(52, 38, PotItem.Bomb, 'Swamp Refill'),
|
Pot(44, 28, PotItem.SmallMagic, 'Thieves Attic Switch'), Pot(48, 28, PotItem.Switch, 'Thieves Attic Switch')],
|
||||||
Pot(56, 38, PotItem.FiveRupees, 'Swamp Refill'), Pot(84, 5, PotItem.Heart, 'Swamp Behind Waterfall'), Pot(104, 5, PotItem.FiveArrows, 'Swamp Behind Waterfall'), Pot(84, 6, PotItem.Heart, 'Swamp Behind Waterfall'),
|
0x65: [Pot(100, 28, PotItem.Bomb, 'Thieves Attic Window'), Pot(104, 28, PotItem.Bomb, 'Thieves Attic Window')],
|
||||||
|
0x66: [Pot(48, 0x5, PotItem.FiveArrows, 'Swamp Refill', PotFlags.LowerRegion),
|
||||||
|
Pot(52, 0x5, PotItem.Bomb, 'Swamp Refill', PotFlags.LowerRegion),
|
||||||
|
Pot(56, 0x5, PotItem.FiveRupees, 'Swamp Refill', PotFlags.LowerRegion),
|
||||||
|
Pot(48, 0x6, PotItem.FiveArrows, 'Swamp Refill', PotFlags.LowerRegion),
|
||||||
|
Pot(52, 0x6, PotItem.Bomb, 'Swamp Refill', PotFlags.LowerRegion),
|
||||||
|
Pot(56, 0x6, PotItem.FiveRupees, 'Swamp Refill', PotFlags.LowerRegion),
|
||||||
|
Pot(84, 5, PotItem.Heart, 'Swamp Behind Waterfall'),
|
||||||
|
Pot(104, 5, PotItem.FiveArrows, 'Swamp Behind Waterfall'),
|
||||||
|
Pot(84, 6, PotItem.Heart, 'Swamp Behind Waterfall'),
|
||||||
Pot(104, 6, PotItem.Bomb, 'Swamp Behind Waterfall')],
|
Pot(104, 6, PotItem.Bomb, 'Swamp Behind Waterfall')],
|
||||||
103: [Pot(22, 26, PotItem.Nothing, 'Skull Left Drop'), Pot(18, 22, PotItem.Nothing, 'Skull Left Drop'), Pot(12, 7, PotItem.FiveArrows, 'Skull Left Drop'), Pot(48, 7, PotItem.SmallMagic, 'Skull Left Drop'),
|
103: [Pot(22, 26, PotItem.Nothing, 'Skull Left Drop'), Pot(18, 22, PotItem.Nothing, 'Skull Left Drop'), Pot(12, 7, PotItem.FiveArrows, 'Skull Left Drop'), Pot(48, 7, PotItem.SmallMagic, 'Skull Left Drop'),
|
||||||
Pot(18, 23, PotItem.SmallMagic, 'Skull Left Drop'), Pot(18, 26, PotItem.Heart, 'Skull Left Drop'), Pot(96, 19, PotItem.Heart, 'Skull Compass Room'), Pot(74, 20, PotItem.SmallMagic, 'Skull Compass Room'),
|
Pot(18, 23, PotItem.SmallMagic, 'Skull Left Drop'), Pot(18, 26, PotItem.Heart, 'Skull Left Drop'), Pot(96, 19, PotItem.Heart, 'Skull Compass Room'), Pot(74, 20, PotItem.SmallMagic, 'Skull Compass Room'),
|
||||||
@@ -128,10 +167,10 @@ vanilla_pots = {
|
|||||||
104: [Pot(84, 14, PotItem.Nothing, 'Skull Pinball'), Pot(84, 13, PotItem.Nothing, 'Skull Pinball'), Pot(88, 12, PotItem.Nothing, 'Skull Pinball'), Pot(88, 6, PotItem.Nothing, 'Skull Pinball'), Pot(88, 5, PotItem.Nothing, 'Skull Pinball'),
|
104: [Pot(84, 14, PotItem.Nothing, 'Skull Pinball'), Pot(84, 13, PotItem.Nothing, 'Skull Pinball'), Pot(88, 12, PotItem.Nothing, 'Skull Pinball'), Pot(88, 6, PotItem.Nothing, 'Skull Pinball'), Pot(88, 5, PotItem.Nothing, 'Skull Pinball'),
|
||||||
Pot(88, 4, PotItem.Nothing, 'Skull Pinball'), Pot(64, 17, PotItem.Nothing, 'Skull Pinball'), Pot(64, 15, PotItem.Nothing, 'Skull Pinball'), Pot(64, 7, PotItem.Heart, 'Skull Pinball'), Pot(88, 7, PotItem.SmallMagic, 'Skull Pinball'),
|
Pot(88, 4, PotItem.Nothing, 'Skull Pinball'), Pot(64, 17, PotItem.Nothing, 'Skull Pinball'), Pot(64, 15, PotItem.Nothing, 'Skull Pinball'), Pot(64, 7, PotItem.Heart, 'Skull Pinball'), Pot(88, 7, PotItem.SmallMagic, 'Skull Pinball'),
|
||||||
Pot(64, 16, PotItem.Heart, 'Skull Pinball'), Pot(64, 24, PotItem.SmallMagic, 'Skull Pinball'), Pot(64, 25, PotItem.Heart, 'Skull Pinball')],
|
Pot(64, 16, PotItem.Heart, 'Skull Pinball'), Pot(64, 24, PotItem.SmallMagic, 'Skull Pinball'), Pot(64, 25, PotItem.Heart, 'Skull Pinball')],
|
||||||
107: [Pot(28, 5, PotItem.Heart, 'GT Crystal Paths'), Pot(44, 5, PotItem.Nothing, 'GT Crystal Paths'), Pot(28, 8, PotItem.Nothing, 'GT Crystal Paths'), Pot(44, 8, PotItem.SmallMagic, 'GT Crystal Paths'),
|
0x6B: [Pot(28, 5, PotItem.Heart, 'GT Crystal Paths'), Pot(44, 5, PotItem.Nothing, 'GT Crystal Paths'), Pot(28, 8, PotItem.Nothing, 'GT Crystal Paths'), Pot(44, 8, PotItem.SmallMagic, 'GT Crystal Paths'),
|
||||||
Pot(28, 11, PotItem.SmallMagic, 'GT Crystal Paths'), Pot(44, 11, PotItem.Nothing, 'GT Crystal Paths'), Pot(94, 25, PotItem.Nothing, 'GT Mimics 2'), Pot(98, 25, PotItem.FiveArrows, 'GT Mimics 2')],
|
Pot(28, 11, PotItem.SmallMagic, 'GT Crystal Paths'), Pot(44, 11, PotItem.Nothing, 'GT Crystal Paths'), Pot(90, 25, PotItem.Nothing, 'GT Mimics 2'), Pot(98, 25, PotItem.FiveArrows, 'GT Mimics 2')],
|
||||||
108: [Pot(20, 6, PotItem.Heart, 'GT Quad Pot'), Pot(40, 6, PotItem.FiveArrows, 'GT Quad Pot'), Pot(20, 10, PotItem.Bomb, 'GT Quad Pot'), Pot(40, 10, PotItem.SmallMagic, 'GT Quad Pot')],
|
0x6C: [Pot(20, 6, PotItem.Heart, 'GT Quad Pot'), Pot(40, 6, PotItem.FiveArrows, 'GT Quad Pot'), Pot(20, 10, PotItem.Bomb, 'GT Quad Pot'), Pot(40, 10, PotItem.SmallMagic, 'GT Quad Pot')],
|
||||||
109: [Pot(28, 26, PotItem.Heart, 'GT Gauntlet 5'), Pot(32, 26, PotItem.Heart, 'GT Gauntlet 5'), Pot(28, 27, PotItem.SmallMagic, 'GT Gauntlet 5'), Pot(32, 27, PotItem.SmallMagic, 'GT Gauntlet 5')],
|
0x6D: [Pot(28, 26, PotItem.Heart, 'GT Gauntlet 5'), Pot(32, 26, PotItem.Heart, 'GT Gauntlet 5'), Pot(28, 27, PotItem.SmallMagic, 'GT Gauntlet 5'), Pot(32, 27, PotItem.SmallMagic, 'GT Gauntlet 5')],
|
||||||
115: [Pot(154, 21, PotItem.FiveArrows, 'Desert Circle of Pots'), Pot(158, 21, PotItem.OneRupee, 'Desert Circle of Pots'), Pot(20, 23, PotItem.Switch, 'Desert Circle of Pots'), Pot(36, 23, PotItem.FiveRupees, 'Desert Circle of Pots'),
|
115: [Pot(154, 21, PotItem.FiveArrows, 'Desert Circle of Pots'), Pot(158, 21, PotItem.OneRupee, 'Desert Circle of Pots'), Pot(20, 23, PotItem.Switch, 'Desert Circle of Pots'), Pot(36, 23, PotItem.FiveRupees, 'Desert Circle of Pots'),
|
||||||
Pot(144, 24, PotItem.Heart, 'Desert Circle of Pots'), Pot(168, 24, PotItem.FiveArrows, 'Desert Circle of Pots'), Pot(20, 26, PotItem.SmallMagic, 'Desert Circle of Pots'), Pot(36, 26, PotItem.Heart, 'Desert Circle of Pots'),
|
Pot(144, 24, PotItem.Heart, 'Desert Circle of Pots'), Pot(168, 24, PotItem.FiveArrows, 'Desert Circle of Pots'), Pot(20, 26, PotItem.SmallMagic, 'Desert Circle of Pots'), Pot(36, 26, PotItem.Heart, 'Desert Circle of Pots'),
|
||||||
Pot(154, 27, PotItem.OneRupee, 'Desert Circle of Pots'), Pot(158, 27, PotItem.FiveRupees, 'Desert Circle of Pots')],
|
Pot(154, 27, PotItem.OneRupee, 'Desert Circle of Pots'), Pot(158, 27, PotItem.FiveRupees, 'Desert Circle of Pots')],
|
||||||
@@ -139,22 +178,24 @@ vanilla_pots = {
|
|||||||
Pot(46, 11, PotItem.FiveArrows, 'Desert Map Room'), Pot(78, 11, PotItem.FiveArrows, 'Desert Map Room'), Pot(110, 11, PotItem.Heart, 'Desert Map Room')],
|
Pot(46, 11, PotItem.FiveArrows, 'Desert Map Room'), Pot(78, 11, PotItem.FiveArrows, 'Desert Map Room'), Pot(110, 11, PotItem.Heart, 'Desert Map Room')],
|
||||||
117: [Pot(148, 22, PotItem.SmallMagic, 'Desert Arrow Pot Corner'), Pot(160, 22, PotItem.FiveArrows, 'Desert Arrow Pot Corner'), Pot(172, 22, PotItem.Heart, 'Desert Arrow Pot Corner')],
|
117: [Pot(148, 22, PotItem.SmallMagic, 'Desert Arrow Pot Corner'), Pot(160, 22, PotItem.FiveArrows, 'Desert Arrow Pot Corner'), Pot(172, 22, PotItem.Heart, 'Desert Arrow Pot Corner')],
|
||||||
118: [Pot(112, 12, PotItem.Heart, 'Swamp Drain Right'), Pot(84, 23, PotItem.Heart, 'Swamp Flooded Spot'), Pot(96, 23, PotItem.Heart, 'Swamp Flooded Spot')],
|
118: [Pot(112, 12, PotItem.Heart, 'Swamp Drain Right'), Pot(84, 23, PotItem.Heart, 'Swamp Flooded Spot'), Pot(96, 23, PotItem.Heart, 'Swamp Flooded Spot')],
|
||||||
123: [Pot(48, 10, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(88, 10, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(76, 7, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(60, 4, PotItem.Heart, 'GT Conveyor Star Pits'),
|
0x7B: [Pot(48, 10, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(88, 10, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(76, 7, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(60, 4, PotItem.Heart, 'GT Conveyor Star Pits'),
|
||||||
Pot(64, 4, PotItem.Key, 'GT Conveyor Star Pits')],
|
Pot(64, 4, PotItem.Key, 'GT Conveyor Star Pits')],
|
||||||
124: [Pot(36, 21, PotItem.Nothing, 'GT Falling Bridge'), Pot(24, 11, PotItem.Nothing, 'GT Falling Bridge'), Pot(28, 4, PotItem.Heart, 'GT Falling Bridge'), Pot(32, 4, PotItem.Heart, 'GT Falling Bridge')],
|
124: [Pot(36, 21, PotItem.Nothing, 'GT Falling Bridge'), Pot(24, 11, PotItem.Nothing, 'GT Falling Bridge'), Pot(28, 4, PotItem.Heart, 'GT Falling Bridge'), Pot(32, 4, PotItem.Heart, 'GT Falling Bridge')],
|
||||||
125: [Pot(44, 12, PotItem.Nothing, 'GT Firesnake Room'), Pot(44, 6, PotItem.Nothing, 'GT Firesnake Room'), Pot(112, 6, PotItem.Heart, 'GT Firesnake Room'), Pot(108, 20, PotItem.FiveArrows, 'GT Warp Maze - Pot Rail'),
|
125: [Pot(44, 12, PotItem.Nothing, 'GT Firesnake Room'), Pot(44, 6, PotItem.Nothing, 'GT Firesnake Room'), Pot(112, 6, PotItem.Heart, 'GT Firesnake Room'), Pot(108, 20, PotItem.FiveArrows, 'GT Warp Maze - Pot Rail'),
|
||||||
Pot(114, 20, PotItem.Bomb, 'GT Petting Zoo'), Pot(76, 28, PotItem.Bomb, 'GT Petting Zoo')],
|
Pot(114, 20, PotItem.Bomb, 'GT Petting Zoo'), Pot(76, 28, PotItem.Bomb, 'GT Petting Zoo')],
|
||||||
126: [Pot(86, 15, PotItem.Heart, 'Ice Tall Hint'), Pot(82, 26, PotItem.SmallMagic, 'Ice Tall Hint'), Pot(100, 26, PotItem.Switch, 'Ice Tall Hint'), Pot(104, 26, PotItem.Nothing, 'Ice Tall Hint')],
|
126: [Pot(86, 15, PotItem.Heart, 'Ice Tall Hint'), Pot(82, 26, PotItem.SmallMagic, 'Ice Tall Hint'), Pot(100, 26, PotItem.Switch, 'Ice Tall Hint'), Pot(104, 26, PotItem.Nothing, 'Ice Tall Hint')],
|
||||||
128: [Pot(48, 4, PotItem.Heart, 'Hyrule Dungeon Cellblock'), Pot(52, 4, PotItem.Heart, 'Hyrule Dungeon Cellblock'), Pot(56, 4, PotItem.Heart, 'Hyrule Dungeon Cellblock')],
|
128: [Pot(48, 4, PotItem.Heart, 'Hyrule Dungeon Cellblock'), Pot(52, 4, PotItem.Heart, 'Hyrule Dungeon Cellblock'), Pot(56, 4, PotItem.Heart, 'Hyrule Dungeon Cellblock')],
|
||||||
130: [Pot(50, 5, PotItem.Nothing, 'Hyrule Dungeon South Abyss'), Pot(50, 10, PotItem.Nothing, 'Hyrule Dungeon South Abyss'), Pot(76, 50, PotItem.Heart, 'Hyrule Dungeon South Abyss')],
|
0x82: [Pot(50, 0x5, PotItem.Nothing, 'Hyrule Dungeon South Abyss', PotFlags.LowerRegion),
|
||||||
|
Pot(50, 0xA, PotItem.Nothing, 'Hyrule Dungeon South Abyss', PotFlags.LowerRegion),
|
||||||
|
Pot(76, 0x12, PotItem.Heart, 'Hyrule Dungeon South Abyss', PotFlags.LowerRegion)],
|
||||||
131: [Pot(76, 4, PotItem.FiveArrows, 'Desert West Wing'), Pot(80, 4, PotItem.OneRupee, 'Desert West Wing'), Pot(76, 28, PotItem.FiveRupees, 'Desert West Wing'), Pot(80, 28, PotItem.FiveArrows, 'Desert West Wing')],
|
131: [Pot(76, 4, PotItem.FiveArrows, 'Desert West Wing'), Pot(80, 4, PotItem.OneRupee, 'Desert West Wing'), Pot(76, 28, PotItem.FiveRupees, 'Desert West Wing'), Pot(80, 28, PotItem.FiveArrows, 'Desert West Wing')],
|
||||||
132: [Pot(64, 17, PotItem.Nothing, 'Desert Main Lobby'), Pot(60, 17, PotItem.Nothing, 'Desert Main Lobby'), Pot(80, 14, PotItem.Nothing, 'Desert Main Lobby'), Pot(44, 14, PotItem.Nothing, 'Desert Main Lobby'),
|
132: [Pot(64, 17, PotItem.Nothing, 'Desert Main Lobby'), Pot(60, 17, PotItem.Nothing, 'Desert Main Lobby'), Pot(80, 14, PotItem.Nothing, 'Desert Main Lobby'), Pot(44, 14, PotItem.Nothing, 'Desert Main Lobby'),
|
||||||
Pot(100, 6, PotItem.Nothing, 'Desert Main Lobby'), Pot(24, 6, PotItem.Nothing, 'Desert Main Lobby'), Pot(24, 7, PotItem.FiveArrows, 'Desert Main Lobby'), Pot(100, 7, PotItem.FiveArrows, 'Desert Main Lobby')],
|
Pot(100, 6, PotItem.Nothing, 'Desert Main Lobby'), Pot(24, 6, PotItem.Nothing, 'Desert Main Lobby'), Pot(24, 7, PotItem.FiveArrows, 'Desert Main Lobby'), Pot(100, 7, PotItem.FiveArrows, 'Desert Main Lobby')],
|
||||||
133: [Pot(44, 28, PotItem.Heart, 'Desert East Wing'), Pot(48, 28, PotItem.FiveArrows, 'Desert East Wing')],
|
133: [Pot(44, 28, PotItem.Heart, 'Desert East Wing'), Pot(48, 28, PotItem.FiveArrows, 'Desert East Wing')],
|
||||||
135: [Pot(12, 11, PotItem.Nothing, 'Hera Tile Room'), Pot(16, 12, PotItem.Nothing, 'Hera Tile Room'), Pot(40, 12, PotItem.Nothing, 'Hera Tile Room'), Pot(32, 12, PotItem.Nothing, 'Hera Tile Room'), Pot(24, 12, PotItem.Nothing, 'Hera Tile Room'),
|
135: [Pot(12, 11, PotItem.Nothing, 'Hera Tile Room'), Pot(16, 12, PotItem.Nothing, 'Hera Tile Room'), Pot(40, 12, PotItem.Nothing, 'Hera Tile Room'), Pot(32, 12, PotItem.Nothing, 'Hera Tile Room'), Pot(24, 12, PotItem.Nothing, 'Hera Tile Room'),
|
||||||
Pot(16, 11, PotItem.Nothing, 'Hera Tile Room'), Pot(76, 20, PotItem.SmallMagic, 'Hera Torches'), Pot(112, 20, PotItem.BigMagic, 'Hera Torches')],
|
Pot(16, 11, PotItem.Nothing, 'Hera Tile Room'), Pot(76, 20, PotItem.SmallMagic, 'Hera Torches'), Pot(112, 20, PotItem.BigMagic, 'Hera Torches')],
|
||||||
139: [Pot(76, 12, PotItem.Nothing, 'GT Conveyor Cross'), Pot(112, 12, PotItem.Key, 'GT Conveyor Cross'), Pot(32, 23, PotItem.Nothing, 'GT Hookshot South Platform'), Pot(28, 23, PotItem.Nothing, 'GT Hookshot South Platform'),
|
0x8B: [Pot(76, 12, PotItem.Nothing, 'GT Conveyor Cross'), Pot(112, 12, PotItem.Key, 'GT Conveyor Cross'), Pot(32, 23, PotItem.Nothing, 'GT Hookshot South Platform'), Pot(28, 23, PotItem.Nothing, 'GT Hookshot South Platform'),
|
||||||
Pot(32, 9, PotItem.SmallMagic, 'GT Hookshot East Platform'), Pot(76, 20, PotItem.Nothing, 'GT Map Room'), Pot(76, 28, PotItem.Heart, 'GT Map Room')],
|
Pot(32, 9, PotItem.SmallMagic, 'GT Hookshot Mid Platform'), Pot(76, 20, PotItem.Nothing, 'GT Map Room'), Pot(76, 28, PotItem.Heart, 'GT Map Room')],
|
||||||
140: [Pot(76, 12, PotItem.Switch, 'GT Hope Room'), Pot(112, 12, PotItem.SmallMagic, 'GT Hope Room'), Pot(76, 20, PotItem.Bomb, "GT Bob's Room"), Pot(92, 20, PotItem.Bomb, "GT Bob's Room"), Pot(100, 21, PotItem.FiveArrows, "GT Bob's Room"),
|
140: [Pot(76, 12, PotItem.Switch, 'GT Hope Room'), Pot(112, 12, PotItem.SmallMagic, 'GT Hope Room'), Pot(76, 20, PotItem.Bomb, "GT Bob's Room"), Pot(92, 20, PotItem.Bomb, "GT Bob's Room"), Pot(100, 21, PotItem.FiveArrows, "GT Bob's Room"),
|
||||||
Pot(104, 26, PotItem.Bomb, "GT Bob's Room"), Pot(88, 27, PotItem.Bomb, "GT Bob's Room")],
|
Pot(104, 26, PotItem.Bomb, "GT Bob's Room"), Pot(88, 27, PotItem.Bomb, "GT Bob's Room")],
|
||||||
141: [Pot(204, 11, PotItem.Nothing, 'GT Speed Torch Upper'), Pot(204, 14, PotItem.BigMagic, 'GT Speed Torch Upper'), Pot(28, 23, PotItem.Heart, 'GT Pots n Blocks'), Pot(36, 23, PotItem.Heart, 'GT Pots n Blocks'),
|
141: [Pot(204, 11, PotItem.Nothing, 'GT Speed Torch Upper'), Pot(204, 14, PotItem.BigMagic, 'GT Speed Torch Upper'), Pot(28, 23, PotItem.Heart, 'GT Pots n Blocks'), Pot(36, 23, PotItem.Heart, 'GT Pots n Blocks'),
|
||||||
@@ -162,47 +203,69 @@ vanilla_pots = {
|
|||||||
142: [Pot(80, 5, PotItem.FiveArrows, 'Ice Lonely Freezor'), Pot(80, 6, PotItem.Nothing, 'Ice Lonely Freezor')],
|
142: [Pot(80, 5, PotItem.FiveArrows, 'Ice Lonely Freezor'), Pot(80, 6, PotItem.Nothing, 'Ice Lonely Freezor')],
|
||||||
145: [Pot(84, 4, PotItem.Heart, 'Mire Falling Foes'), Pot(104, 4, PotItem.SmallMagic, 'Mire Falling Foes')],
|
145: [Pot(84, 4, PotItem.Heart, 'Mire Falling Foes'), Pot(104, 4, PotItem.SmallMagic, 'Mire Falling Foes')],
|
||||||
146: [Pot(86, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(92, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(98, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(104, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy')],
|
146: [Pot(86, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(92, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(98, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(104, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy')],
|
||||||
147: [Pot(28, 7, PotItem.Switch, 'Mire Dark Shooters'), Pot(96, 7, PotItem.Heart, 'Mire Dark Shooters', PotFlags.NoSwitch)],
|
0x93: [Pot(28, 7, PotItem.Switch, 'Mire Dark Shooters'),
|
||||||
150: [Pot(14, 18, PotItem.Nothing, 'GT Torch Cross'), Pot(32, 5, PotItem.Nothing, 'GT Torch Cross'), Pot(32, 17, PotItem.SmallMagic, 'GT Torch Cross'), Pot(32, 24, PotItem.SmallMagic, 'GT Torch Cross'),
|
Pot(0x9C, 0x17, PotItem.Nothing, 'Mire Block X', PotFlags.Block),
|
||||||
Pot(14, 24, PotItem.Nothing, 'GT Torch Cross'), Pot(76, 21, PotItem.Heart, 'GT Staredown'), Pot(112, 21, PotItem.BigMagic, 'GT Staredown')],
|
Pot(96, 7, PotItem.Heart, 'Mire Dark Shooters', PotFlags.NoSwitch)],
|
||||||
|
0x96: [Pot(14, 18, PotItem.Nothing, 'GT Torch Cross'),
|
||||||
|
Pot(32, 5, PotItem.Nothing, 'GT Torch Cross'),
|
||||||
|
Pot(0x2e, 0xb, PotItem.Nothing, 'GT Torch Cross'),
|
||||||
|
Pot(32, 17, PotItem.SmallMagic, 'GT Torch Cross'),
|
||||||
|
Pot(32, 24, PotItem.SmallMagic, 'GT Torch Cross'),
|
||||||
|
Pot(14, 24, PotItem.Nothing, 'GT Torch Cross'),
|
||||||
|
Pot(76, 21, PotItem.Heart, 'GT Staredown'),
|
||||||
|
Pot(112, 21, PotItem.BigMagic, 'GT Staredown')],
|
||||||
153: [Pot(40, 20, PotItem.SmallMagic, 'Eastern Darkness'), Pot(84, 20, PotItem.Heart, 'Eastern Darkness')],
|
153: [Pot(40, 20, PotItem.SmallMagic, 'Eastern Darkness'), Pot(84, 20, PotItem.Heart, 'Eastern Darkness')],
|
||||||
155: [Pot(48, 4, PotItem.SmallMagic, 'GT Double Switch Pot Corners'), Pot(48, 12, PotItem.Key, 'GT Double Switch Pot Corners'), Pot(28, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section'), Pot(32, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section')],
|
0x9B: [Pot(48, 4, PotItem.SmallMagic, 'GT Double Switch Pot Corners'), Pot(48, 12, PotItem.Key, 'GT Double Switch Pot Corners'), Pot(28, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section'), Pot(32, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section')],
|
||||||
156: [Pot(56, 8, PotItem.SmallMagic, 'GT Invisible Catwalk'), Pot(56, 9, PotItem.FiveArrows, 'GT Invisible Catwalk')],
|
156: [Pot(56, 8, PotItem.SmallMagic, 'GT Invisible Catwalk'), Pot(56, 9, PotItem.FiveArrows, 'GT Invisible Catwalk')],
|
||||||
157: [Pot(76, 4, PotItem.Bomb, 'GT Crystal Conveyor Left'), Pot(84, 4, PotItem.SmallMagic, 'GT Crystal Conveyor Left'), Pot(32, 7, PotItem.Nothing, 'GT Compass Room'), Pot(40, 9, PotItem.Nothing, 'GT Compass Room')],
|
157: [Pot(76, 4, PotItem.Bomb, 'GT Crystal Conveyor Left'), Pot(84, 4, PotItem.SmallMagic, 'GT Crystal Conveyor Left'), Pot(32, 7, PotItem.Nothing, 'GT Compass Room'), Pot(40, 9, PotItem.Nothing, 'GT Compass Room')],
|
||||||
159: [Pot(138, 20, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 19, PotItem.Heart, 'Ice Many Pots'), Pot(178, 19, PotItem.Heart, 'Ice Many Pots'), Pot(40, 21, PotItem.Switch, 'Ice Many Pots'), Pot(138, 21, PotItem.Key, 'Ice Many Pots'),
|
0x9F: [Pot(138, 20, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 19, PotItem.Heart, 'Ice Many Pots'), Pot(178, 19, PotItem.Heart, 'Ice Many Pots'), Pot(40, 21, PotItem.Switch, 'Ice Many Pots'), Pot(138, 21, PotItem.Key, 'Ice Many Pots'),
|
||||||
Pot(20, 27, PotItem.Heart, 'Ice Many Pots'), Pot(138, 27, PotItem.Heart, 'Ice Many Pots'), Pot(178, 28, PotItem.Heart, 'Ice Many Pots'), Pot(178, 21, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 20, PotItem.Nothing, 'Ice Many Pots'),
|
Pot(20, 27, PotItem.Heart, 'Ice Many Pots'), Pot(138, 27, PotItem.Heart, 'Ice Many Pots'), Pot(178, 28, PotItem.Heart, 'Ice Many Pots'), Pot(178, 21, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 20, PotItem.Nothing, 'Ice Many Pots'),
|
||||||
Pot(40, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 26, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 28, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 26, PotItem.Nothing, 'Ice Many Pots'),
|
Pot(40, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 26, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 28, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 26, PotItem.Nothing, 'Ice Many Pots'),
|
||||||
Pot(20, 21, PotItem.Nothing, 'Ice Many Pots')],
|
Pot(20, 21, PotItem.Nothing, 'Ice Many Pots')],
|
||||||
161: [Pot(150, 6, PotItem.Key, 'Mire Fishbone'), Pot(100, 11, PotItem.SmallMagic, 'Mire Fishbone'), Pot(104, 12, PotItem.Heart, 'Mire Fishbone'), Pot(108, 13, PotItem.SmallMagic, 'Mire Fishbone'), Pot(112, 14, PotItem.Heart, 'Mire Fishbone'),
|
0xA1: [Pot(150, 6, PotItem.Key, 'Mire Fishbone'), Pot(100, 11, PotItem.SmallMagic, 'Mire Fishbone'), Pot(104, 12, PotItem.Heart, 'Mire Fishbone'), Pot(108, 13, PotItem.SmallMagic, 'Mire Fishbone'), Pot(112, 14, PotItem.Heart, 'Mire Fishbone'),
|
||||||
Pot(96, 27, PotItem.Nothing, 'Mire South Fish'), Pot(92, 21, PotItem.Nothing, 'Mire South Fish'), Pot(96, 23, PotItem.Heart, 'Mire South Fish'), Pot(92, 25, PotItem.Nothing, 'Mire South Fish'),
|
Pot(96, 27, PotItem.Nothing, 'Mire South Fish'), Pot(92, 21, PotItem.Nothing, 'Mire South Fish'), Pot(96, 23, PotItem.Heart, 'Mire South Fish'), Pot(92, 25, PotItem.Nothing, 'Mire South Fish'),
|
||||||
Pot(76, 28, PotItem.Nothing, 'Mire South Fish'), Pot(112, 28, PotItem.Nothing, 'Mire South Fish')],
|
Pot(76, 28, PotItem.Nothing, 'Mire South Fish'), Pot(112, 28, PotItem.Nothing, 'Mire South Fish')],
|
||||||
162: [Pot(12, 28, PotItem.BigMagic, 'Mire Left Bridge')],
|
0xA2: [Pot(12, 28, PotItem.BigMagic, 'Mire Left Bridge')],
|
||||||
168: [Pot(138, 28, PotItem.Nothing, 'Eastern Stalfos Spawn'), Pot(178, 28, PotItem.Nothing, 'Eastern Stalfos Spawn'), Pot(178, 19, PotItem.Nothing, 'Eastern Stalfos Spawn'), Pot(138, 19, PotItem.Heart, 'Eastern Stalfos Spawn'),
|
168: [Pot(138, 28, PotItem.Nothing, 'Eastern Stalfos Spawn'), Pot(178, 28, PotItem.Nothing, 'Eastern Stalfos Spawn'), Pot(178, 19, PotItem.Nothing, 'Eastern Stalfos Spawn'), Pot(138, 19, PotItem.Heart, 'Eastern Stalfos Spawn'),
|
||||||
Pot(30, 24, PotItem.OneRupee, 'Eastern Stalfos Spawn')],
|
Pot(30, 24, PotItem.OneRupee, 'Eastern Stalfos Spawn')],
|
||||||
169: [Pot(144, 43, PotItem.FiveArrows, 'Eastern Courtyard'), Pot(236, 43, PotItem.FiveArrows, 'Eastern Courtyard'), Pot(144, 44, PotItem.FiveArrows, 'Eastern Courtyard'), Pot(236, 44, PotItem.Heart, 'Eastern Courtyard'),
|
0xA9: [Pot(144, 0xB, PotItem.FiveArrows, 'Eastern Courtyard', PotFlags.LowerRegion),
|
||||||
Pot(12, 19, PotItem.Nothing, 'Eastern Courtyard Ledge'), Pot(112, 19, PotItem.Nothing, 'Eastern Courtyard Ledge'), Pot(16, 20, PotItem.Heart, 'Eastern Courtyard Ledge'), Pot(108, 20, PotItem.Heart, 'Eastern Courtyard Ledge')],
|
Pot(236, 0xB, PotItem.FiveArrows, 'Eastern Courtyard', PotFlags.LowerRegion),
|
||||||
170: [Pot(212, 10, PotItem.Nothing, 'Eastern Pot Switch'), Pot(232, 10, PotItem.Nothing, 'Eastern Pot Switch'), Pot(232, 5, PotItem.Nothing, 'Eastern Pot Switch'), Pot(212, 5, PotItem.Heart, 'Eastern Pot Switch'),
|
Pot(144, 0xC, PotItem.FiveArrows, 'Eastern Courtyard', PotFlags.LowerRegion),
|
||||||
Pot(94, 8, PotItem.Switch, 'Eastern Pot Switch'), Pot(108, 55, PotItem.Heart, 'Eastern Map Balcony'), Pot(108, 56, PotItem.Heart, 'Eastern Map Balcony'), Pot(108, 57, PotItem.Heart, 'Eastern Map Balcony')],
|
Pot(236, 0xC, PotItem.Heart, 'Eastern Courtyard', PotFlags.LowerRegion),
|
||||||
171: [Pot(20, 24, PotItem.Key, 'Thieves Spike Switch')],
|
Pot(12, 19, PotItem.Nothing, 'Eastern Courtyard Ledge'),
|
||||||
|
Pot(112, 19, PotItem.Nothing, 'Eastern Courtyard Ledge'),
|
||||||
|
Pot(16, 20, PotItem.Heart, 'Eastern Courtyard Ledge'),
|
||||||
|
Pot(108, 20, PotItem.Heart, 'Eastern Courtyard Ledge')],
|
||||||
|
0xAA: [Pot(212, 10, PotItem.Nothing, 'Eastern Pot Switch'), Pot(232, 10, PotItem.Nothing, 'Eastern Pot Switch'),
|
||||||
|
Pot(232, 5, PotItem.Nothing, 'Eastern Pot Switch'), Pot(212, 5, PotItem.Heart, 'Eastern Pot Switch'),
|
||||||
|
Pot(94, 8, PotItem.Switch, 'Eastern Pot Switch'),
|
||||||
|
Pot(108, 0x17, PotItem.Heart, 'Eastern Map Balcony', PotFlags.LowerRegion),
|
||||||
|
Pot(108, 0x18, PotItem.Heart, 'Eastern Map Balcony', PotFlags.LowerRegion),
|
||||||
|
Pot(108, 0x19, PotItem.Heart, 'Eastern Map Balcony', PotFlags.LowerRegion)],
|
||||||
|
0xAB: [Pot(20, 24, PotItem.Key, 'Thieves Spike Switch')],
|
||||||
174: [Pot(76, 12, PotItem.Switch, 'Iced T')],
|
174: [Pot(76, 12, PotItem.Switch, 'Iced T')],
|
||||||
176: [Pot(20, 27, PotItem.Nothing, 'Tower Circle of Pots'), Pot(24, 24, PotItem.Nothing, 'Tower Circle of Pots'), Pot(44, 25, PotItem.Nothing, 'Tower Circle of Pots'), Pot(20, 21, PotItem.Bomb, 'Tower Circle of Pots'),
|
176: [Pot(20, 27, PotItem.Nothing, 'Tower Circle of Pots'), Pot(24, 24, PotItem.Nothing, 'Tower Circle of Pots'), Pot(44, 25, PotItem.Nothing, 'Tower Circle of Pots'), Pot(20, 21, PotItem.Bomb, 'Tower Circle of Pots'),
|
||||||
Pot(28, 21, PotItem.OneRupee, 'Tower Circle of Pots'), Pot(32, 21, PotItem.FiveRupees, 'Tower Circle of Pots'), Pot(40, 21, PotItem.FiveArrows, 'Tower Circle of Pots'), Pot(16, 23, PotItem.FiveRupees, 'Tower Circle of Pots'),
|
Pot(28, 21, PotItem.OneRupee, 'Tower Circle of Pots'), Pot(32, 21, PotItem.FiveRupees, 'Tower Circle of Pots'), Pot(40, 21, PotItem.FiveArrows, 'Tower Circle of Pots'), Pot(16, 23, PotItem.FiveRupees, 'Tower Circle of Pots'),
|
||||||
Pot(44, 23, PotItem.OneRupee, 'Tower Circle of Pots'), Pot(36, 24, PotItem.Heart, 'Tower Circle of Pots'), Pot(16, 25, PotItem.Heart, 'Tower Circle of Pots'), Pot(28, 27, PotItem.FiveArrows, 'Tower Circle of Pots'),
|
Pot(44, 23, PotItem.OneRupee, 'Tower Circle of Pots'), Pot(36, 24, PotItem.Heart, 'Tower Circle of Pots'), Pot(16, 25, PotItem.Heart, 'Tower Circle of Pots'), Pot(28, 27, PotItem.FiveArrows, 'Tower Circle of Pots'),
|
||||||
Pot(40, 27, PotItem.Bomb, 'Tower Circle of Pots'), Pot(32, 27, PotItem.Nothing, 'Tower Circle of Pots')],
|
Pot(40, 27, PotItem.Bomb, 'Tower Circle of Pots'), Pot(32, 27, PotItem.Nothing, 'Tower Circle of Pots')],
|
||||||
177: [Pot(76, 4, PotItem.Heart, 'Mire Spike Barrier'), Pot(112, 4, PotItem.OneRupee, 'Mire Spike Barrier')],
|
177: [Pot(76, 4, PotItem.Heart, 'Mire Spike Barrier'), Pot(112, 4, PotItem.OneRupee, 'Mire Spike Barrier')],
|
||||||
178: [Pot(48, 40, PotItem.OneRupee, 'Mire BK Door Room'), Pot(76, 40, PotItem.OneRupee, 'Mire BK Door Room'), Pot(48, 41, PotItem.Nothing, 'Mire BK Door Room'), Pot(76, 41, PotItem.Heart, 'Mire BK Door Room'),
|
0xB2: [Pot(48, 0x8, PotItem.OneRupee, 'Mire BK Door Room', PotFlags.LowerRegion),
|
||||||
Pot(48, 42, PotItem.Nothing, 'Mire BK Door Room'), Pot(76, 40, PotItem.Nothing, 'Mire BK Door Room')],
|
Pot(76, 0x8, PotItem.OneRupee, 'Mire BK Door Room', PotFlags.LowerRegion),
|
||||||
179: [Pot(12, 20, PotItem.Key, 'Mire Spikes'), Pot(48, 20, PotItem.SmallMagic, 'Mire Spikes'), Pot(48, 28, PotItem.Switch, 'Mire Spikes')],
|
Pot(48, 0x9, PotItem.Nothing, 'Mire BK Door Room', PotFlags.LowerRegion),
|
||||||
180: [Pot(44, 28, PotItem.BigMagic, 'TR Final Abyss'), Pot(48, 28, PotItem.Heart, 'TR Final Abyss')],
|
Pot(76, 0x9, PotItem.Heart, 'Mire BK Door Room', PotFlags.LowerRegion),
|
||||||
181: [Pot(112, 4, PotItem.FiveRupees, 'TR Dark Ride'), Pot(112, 15, PotItem.Heart, 'TR Dark Ride'), Pot(76, 16, PotItem.Switch, 'TR Dark Ride'), Pot(112, 16, PotItem.BigMagic, 'TR Dark Ride'), Pot(112, 17, PotItem.Heart, 'TR Dark Ride'),
|
Pot(48, 0xA, PotItem.Nothing, 'Mire BK Door Room', PotFlags.LowerRegion),
|
||||||
|
Pot(76, 0xA, PotItem.Nothing, 'Mire BK Door Room', PotFlags.LowerRegion)],
|
||||||
|
0xB3: [Pot(12, 20, PotItem.Key, 'Mire Spikes'), Pot(48, 20, PotItem.SmallMagic, 'Mire Spikes'), Pot(48, 28, PotItem.Switch, 'Mire Spikes')],
|
||||||
|
0xB4: [Pot(44, 28, PotItem.BigMagic, 'TR Final Abyss Balcony'), Pot(48, 28, PotItem.Heart, 'TR Final Abyss Balcony')],
|
||||||
|
0xB5: [Pot(112, 4, PotItem.FiveRupees, 'TR Dark Ride'), Pot(112, 15, PotItem.Heart, 'TR Dark Ride'), Pot(76, 16, PotItem.Switch, 'TR Dark Ride'), Pot(112, 16, PotItem.BigMagic, 'TR Dark Ride'), Pot(112, 17, PotItem.Heart, 'TR Dark Ride'),
|
||||||
Pot(112, 28, PotItem.Bomb, 'TR Dark Ride')],
|
Pot(112, 28, PotItem.Bomb, 'TR Dark Ride')],
|
||||||
182: [Pot(94, 9, PotItem.BigMagic, 'TR Refill')],
|
0xB6: [Pot(94, 9, PotItem.BigMagic, 'TR Refill')],
|
||||||
183: [Pot(30, 5, PotItem.SmallMagic, 'TR Roller Room')],
|
0xB7: [Pot(30, 5, PotItem.SmallMagic, 'TR Roller Room')],
|
||||||
184: [Pot(96, 13, PotItem.Switch, 'Eastern Big Key'), Pot(88, 16, PotItem.Heart, 'Eastern Big Key'), Pot(104, 16, PotItem.Heart, 'Eastern Big Key')],
|
0xB8: [Pot(96, 13, PotItem.Switch, 'Eastern Big Key'), Pot(88, 16, PotItem.Heart, 'Eastern Big Key'), Pot(104, 16, PotItem.Heart, 'Eastern Big Key')],
|
||||||
185: [Pot(92, 18, PotItem.OneRupee, 'Eastern Cannonball'), Pot(96, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(104, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(108, 18, PotItem.OneRupee, 'Eastern Cannonball')],
|
0xB9: [Pot(92, 18, PotItem.OneRupee, 'Eastern Cannonball'), Pot(96, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(104, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(108, 18, PotItem.OneRupee, 'Eastern Cannonball')],
|
||||||
186: [Pot(100, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(88, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(94, 4, PotItem.OneRupee, 'Eastern Dark Pots'), Pot(76, 6, PotItem.Heart, 'Eastern Dark Pots'),
|
0xBA: [Pot(100, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(88, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(94, 4, PotItem.OneRupee, 'Eastern Dark Pots'), Pot(76, 6, PotItem.Heart, 'Eastern Dark Pots'),
|
||||||
Pot(112, 6, PotItem.Key, 'Eastern Dark Pots'), Pot(76, 10, PotItem.Heart, 'Eastern Dark Pots'), Pot(112, 10, PotItem.SmallMagic, 'Eastern Dark Pots'), Pot(94, 12, PotItem.OneRupee, 'Eastern Dark Pots')],
|
Pot(112, 6, PotItem.Key, 'Eastern Dark Pots'), Pot(76, 10, PotItem.Heart, 'Eastern Dark Pots'), Pot(112, 10, PotItem.SmallMagic, 'Eastern Dark Pots'), Pot(94, 12, PotItem.OneRupee, 'Eastern Dark Pots')],
|
||||||
188: [Pot(86, 4, PotItem.Heart, 'Thieves Hallway'), Pot(102, 4, PotItem.Key, 'Thieves Hallway'), Pot(138, 3, PotItem.Bomb, 'Thieves Conveyor Maze'), Pot(178, 3, PotItem.Switch, 'Thieves Conveyor Maze'),
|
0xBC: [Pot(86, 4, PotItem.Heart, 'Thieves Hallway'), Pot(102, 4, PotItem.Key, 'Thieves Hallway'), Pot(138, 3, PotItem.Bomb, 'Thieves Conveyor Maze'), Pot(178, 3, PotItem.Switch, 'Thieves Conveyor Maze'),
|
||||||
Pot(138, 12, PotItem.Heart, 'Thieves Conveyor Maze'), Pot(178, 12, PotItem.Bomb, 'Thieves Conveyor Maze'), Pot(12, 20, PotItem.Nothing, 'Thieves Pot Alcove Mid'), Pot(48, 20, PotItem.Bomb, 'Thieves Pot Alcove Mid'),
|
Pot(138, 12, PotItem.Heart, 'Thieves Conveyor Maze'), Pot(178, 12, PotItem.Bomb, 'Thieves Conveyor Maze'), Pot(12, 20, PotItem.Nothing, 'Thieves Pot Alcove Mid'), Pot(48, 20, PotItem.Bomb, 'Thieves Pot Alcove Mid'),
|
||||||
Pot(12, 28, PotItem.Bomb, 'Thieves Pot Alcove Mid'), Pot(48, 28, PotItem.Bomb, 'Thieves Pot Alcove Mid'), Pot(28, 21, PotItem.FiveRupees, 'Thieves Pot Alcove Top'), Pot(32, 21, PotItem.FiveRupees, 'Thieves Pot Alcove Top'),
|
Pot(12, 28, PotItem.Bomb, 'Thieves Pot Alcove Mid'), Pot(48, 28, PotItem.Bomb, 'Thieves Pot Alcove Mid'), Pot(28, 21, PotItem.FiveRupees, 'Thieves Pot Alcove Top'), Pot(32, 21, PotItem.FiveRupees, 'Thieves Pot Alcove Top'),
|
||||||
Pot(28, 27, PotItem.FiveRupees, 'Thieves Pot Alcove Bottom'), Pot(32, 27, PotItem.FiveRupees, 'Thieves Pot Alcove Bottom')],
|
Pot(28, 27, PotItem.FiveRupees, 'Thieves Pot Alcove Bottom'), Pot(32, 27, PotItem.FiveRupees, 'Thieves Pot Alcove Bottom')],
|
||||||
@@ -210,7 +273,10 @@ vanilla_pots = {
|
|||||||
191: [Pot(40, 20, PotItem.FiveArrows, 'Ice Refill'), Pot(44, 20, PotItem.Heart, 'Ice Refill'), Pot(48, 20, PotItem.Bomb, 'Ice Refill'), Pot(40, 28, PotItem.SmallMagic, 'Ice Refill'), Pot(44, 28, PotItem.SmallMagic, 'Ice Refill'),
|
191: [Pot(40, 20, PotItem.FiveArrows, 'Ice Refill'), Pot(44, 20, PotItem.Heart, 'Ice Refill'), Pot(48, 20, PotItem.Bomb, 'Ice Refill'), Pot(40, 28, PotItem.SmallMagic, 'Ice Refill'), Pot(44, 28, PotItem.SmallMagic, 'Ice Refill'),
|
||||||
Pot(48, 28, PotItem.SmallMagic, 'Ice Refill')],
|
Pot(48, 28, PotItem.SmallMagic, 'Ice Refill')],
|
||||||
192: [Pot(48, 10, PotItem.Bomb, 'Tower Dark Pits'), Pot(12, 14, PotItem.FiveRupees, 'Tower Dark Pits'), Pot(12, 26, PotItem.Heart, 'Tower Dark Pits'), Pot(28, 27, PotItem.OneRupee, 'Tower Dark Pits')],
|
192: [Pot(48, 10, PotItem.Bomb, 'Tower Dark Pits'), Pot(12, 14, PotItem.FiveRupees, 'Tower Dark Pits'), Pot(12, 26, PotItem.Heart, 'Tower Dark Pits'), Pot(28, 27, PotItem.OneRupee, 'Tower Dark Pits')],
|
||||||
194: [Pot(180, 7, PotItem.Switch, 'Mire Hub Switch'), Pot(100, 46, PotItem.SmallMagic, 'Mire Hub Right'), Pot(68, 48, PotItem.OneRupee, 'Mire Hub'), Pot(64, 52, PotItem.FiveArrows, 'Mire Hub')],
|
0xC2: [Pot(180, 7, PotItem.Switch, 'Mire Hub Switch'),
|
||||||
|
Pot(100, 0xE, PotItem.SmallMagic, 'Mire Hub Right', PotFlags.LowerRegion),
|
||||||
|
Pot(68, 0x10, PotItem.OneRupee, 'Mire Hub', PotFlags.LowerRegion),
|
||||||
|
Pot(64, 0x14, PotItem.FiveArrows, 'Mire Hub', PotFlags.LowerRegion)],
|
||||||
196: [Pot(84, 9, PotItem.Bomb, 'TR Crystal Maze Interior'), Pot(24, 14, PotItem.Heart, 'TR Crystal Maze Interior'), Pot(56, 17, PotItem.FiveRupees, 'TR Crystal Maze Interior'), Pot(84, 17, PotItem.Bomb, 'TR Crystal Maze Interior'),
|
196: [Pot(84, 9, PotItem.Bomb, 'TR Crystal Maze Interior'), Pot(24, 14, PotItem.Heart, 'TR Crystal Maze Interior'), Pot(56, 17, PotItem.FiveRupees, 'TR Crystal Maze Interior'), Pot(84, 17, PotItem.Bomb, 'TR Crystal Maze Interior'),
|
||||||
Pot(12, 21, PotItem.FiveArrows, 'TR Crystal Maze Interior'), Pot(76, 23, PotItem.OneRupee, 'TR Crystal Maze Interior'), Pot(48, 25, PotItem.SmallMagic, 'TR Crystal Maze Interior'), Pot(12, 26, PotItem.Heart, 'TR Crystal Maze Interior')],
|
Pot(12, 21, PotItem.FiveArrows, 'TR Crystal Maze Interior'), Pot(76, 23, PotItem.OneRupee, 'TR Crystal Maze Interior'), Pot(48, 25, PotItem.SmallMagic, 'TR Crystal Maze Interior'), Pot(12, 26, PotItem.Heart, 'TR Crystal Maze Interior')],
|
||||||
198: [Pot(12, 7, PotItem.BigMagic, 'TR Hub'), Pot(12, 25, PotItem.Heart, 'TR Hub')],
|
198: [Pot(12, 7, PotItem.BigMagic, 'TR Hub'), Pot(12, 25, PotItem.Heart, 'TR Hub')],
|
||||||
@@ -218,8 +284,10 @@ vanilla_pots = {
|
|||||||
201: [Pot(30, 22, PotItem.OneRupee, 'Eastern Lobby'), Pot(94, 22, PotItem.OneRupee, 'Eastern Lobby'), Pot(60, 22, PotItem.Switch, 'Eastern Lobby')],
|
201: [Pot(30, 22, PotItem.OneRupee, 'Eastern Lobby'), Pot(94, 22, PotItem.OneRupee, 'Eastern Lobby'), Pot(60, 22, PotItem.Switch, 'Eastern Lobby')],
|
||||||
203: [Pot(80, 4, PotItem.Nothing, 'Thieves Ambush'), Pot(80, 28, PotItem.Nothing, 'Thieves Ambush'), Pot(88, 16, PotItem.Heart, 'Thieves Ambush'), Pot(88, 28, PotItem.FiveRupees, 'Thieves Ambush')],
|
203: [Pot(80, 4, PotItem.Nothing, 'Thieves Ambush'), Pot(80, 28, PotItem.Nothing, 'Thieves Ambush'), Pot(88, 16, PotItem.Heart, 'Thieves Ambush'), Pot(88, 28, PotItem.FiveRupees, 'Thieves Ambush')],
|
||||||
204: [Pot(36, 4, PotItem.FiveRupees, 'Thieves Rail Ledge'), Pot(36, 28, PotItem.FiveRupees, 'Thieves Rail Ledge'), Pot(112, 4, PotItem.Heart, 'Thieves BK Corner'), Pot(112, 28, PotItem.Bomb, 'Thieves BK Corner')],
|
204: [Pot(36, 4, PotItem.FiveRupees, 'Thieves Rail Ledge'), Pot(36, 28, PotItem.FiveRupees, 'Thieves Rail Ledge'), Pot(112, 4, PotItem.Heart, 'Thieves BK Corner'), Pot(112, 28, PotItem.Bomb, 'Thieves BK Corner')],
|
||||||
206: [Pot(76, 8, PotItem.SmallMagic, 'Ice Antechamber'), Pot(80, 8, PotItem.SmallMagic, 'Ice Antechamber'), Pot(108, 12, PotItem.Bomb, 'Ice Antechamber'), Pot(112, 12, PotItem.FiveArrows, 'Ice Antechamber'),
|
0xCE: [Pot(76, 8, PotItem.SmallMagic, 'Ice Antechamber'), Pot(80, 8, PotItem.SmallMagic, 'Ice Antechamber'),
|
||||||
Pot(204, 11, PotItem.Hole, 'Ice Antechamber')],
|
Pot(108, 12, PotItem.Bomb, 'Ice Antechamber'), Pot(112, 12, PotItem.FiveArrows, 'Ice Antechamber'),
|
||||||
|
Pot(204, 11, PotItem.Hole, 'Ice Antechamber'),
|
||||||
|
Pot(0x6c, 8, PotItem.Nothing, 'Ice Antechamber', PotFlags.Block)],
|
||||||
208: [Pot(158, 5, PotItem.SmallMagic, 'Tower Dark Maze'), Pot(140, 11, PotItem.OneRupee, 'Tower Dark Maze'), Pot(42, 13, PotItem.SmallMagic, 'Tower Dark Maze'), Pot(48, 16, PotItem.Heart, 'Tower Dark Maze'),
|
208: [Pot(158, 5, PotItem.SmallMagic, 'Tower Dark Maze'), Pot(140, 11, PotItem.OneRupee, 'Tower Dark Maze'), Pot(42, 13, PotItem.SmallMagic, 'Tower Dark Maze'), Pot(48, 16, PotItem.Heart, 'Tower Dark Maze'),
|
||||||
Pot(176, 20, PotItem.OneRupee, 'Tower Dark Maze'), Pot(146, 23, PotItem.FiveRupees, 'Tower Dark Maze'), Pot(12, 28, PotItem.Heart, 'Tower Dark Maze')],
|
Pot(176, 20, PotItem.OneRupee, 'Tower Dark Maze'), Pot(146, 23, PotItem.FiveRupees, 'Tower Dark Maze'), Pot(12, 28, PotItem.Heart, 'Tower Dark Maze')],
|
||||||
209: [Pot(48, 4, PotItem.BigMagic, 'Mire Conveyor Barrier'), Pot(168, 7, PotItem.OneRupee, 'Mire Conveyor Barrier'), Pot(76, 4, PotItem.OneRupee, 'Mire Neglected Room'), Pot(112, 4, PotItem.FiveArrows, 'Mire Neglected Room'),
|
209: [Pot(48, 4, PotItem.BigMagic, 'Mire Conveyor Barrier'), Pot(168, 7, PotItem.OneRupee, 'Mire Conveyor Barrier'), Pot(76, 4, PotItem.OneRupee, 'Mire Neglected Room'), Pot(112, 4, PotItem.FiveArrows, 'Mire Neglected Room'),
|
||||||
@@ -229,58 +297,76 @@ vanilla_pots = {
|
|||||||
Pot(202, 12, PotItem.FiveArrows, 'Eastern Duo Eyegores'), Pot(242, 12, PotItem.Heart, 'Eastern Duo Eyegores'), Pot(92, 24, PotItem.Heart, 'Eastern Single Eyegore'), Pot(96, 24, PotItem.FiveArrows, 'Eastern Single Eyegore')],
|
Pot(202, 12, PotItem.FiveArrows, 'Eastern Duo Eyegores'), Pot(242, 12, PotItem.Heart, 'Eastern Duo Eyegores'), Pot(92, 24, PotItem.Heart, 'Eastern Single Eyegore'), Pot(96, 24, PotItem.FiveArrows, 'Eastern Single Eyegore')],
|
||||||
217: [Pot(92, 20, PotItem.FiveArrows, 'Eastern False Switches'), Pot(92, 28, PotItem.Heart, 'Eastern False Switches')],
|
217: [Pot(92, 20, PotItem.FiveArrows, 'Eastern False Switches'), Pot(92, 28, PotItem.Heart, 'Eastern False Switches')],
|
||||||
218: [Pot(24, 23, PotItem.FiveArrows, 'Eastern Attic Start'), Pot(36, 23, PotItem.FiveArrows, 'Eastern Attic Start'), Pot(24, 25, PotItem.Switch, 'Eastern Attic Start'), Pot(36, 25, PotItem.Heart, 'Eastern Attic Start')],
|
218: [Pot(24, 23, PotItem.FiveArrows, 'Eastern Attic Start'), Pot(36, 23, PotItem.FiveArrows, 'Eastern Attic Start'), Pot(24, 25, PotItem.Switch, 'Eastern Attic Start'), Pot(36, 25, PotItem.Heart, 'Eastern Attic Start')],
|
||||||
219: [Pot(12, 4, PotItem.Nothing, 'Thieves Lobby'), Pot(62, 19, PotItem.Nothing, 'Thieves Lobby'), Pot(112, 4, PotItem.FiveRupees, 'Thieves Lobby'), Pot(88, 16, PotItem.Heart, 'Thieves Lobby')],
|
0xDB: [Pot(12, 4, PotItem.Nothing, 'Thieves Lobby'),
|
||||||
220: [Pot(56, 4, PotItem.FiveRupees, 'Thieves Compass Room'), Pot(112, 4, PotItem.Bomb, 'Thieves Compass Room'), Pot(68, 16, PotItem.Heart, 'Thieves Compass Room'), Pot(12, 28, PotItem.FiveArrows, 'Thieves Compass Room')],
|
Pot(62, 19, PotItem.Nothing, 'Thieves Lobby', PotFlags.LowerRegion),
|
||||||
227: [Pot(88, 55, PotItem.Nothing, 'Bat Cave (right)'), Pot(100, 57, PotItem.OneRupee, 'Bat Cave (right)')],
|
Pot(112, 4, PotItem.FiveRupees, 'Thieves Lobby'), Pot(88, 16, PotItem.Heart, 'Thieves Lobby')],
|
||||||
228: [Pot(32, 9, PotItem.FiveRupees, 'Old Man House'), Pot(112, 10, PotItem.OneRupee, 'Old Man House')],
|
0xDC: [Pot(56, 4, PotItem.FiveRupees, 'Thieves Compass Room'), Pot(112, 4, PotItem.Bomb, 'Thieves Compass Room'), Pot(68, 16, PotItem.Heart, 'Thieves Compass Room'), Pot(12, 28, PotItem.FiveArrows, 'Thieves Compass Room')],
|
||||||
229: [Pot(48, 4, PotItem.OneRupee, 'Old Man House Back'), Pot(76, 4, PotItem.OneRupee, 'Old Man House Back'), Pot(112, 16, PotItem.OneRupee, 'Old Man House Back'), Pot(64, 18, PotItem.FiveRupees, 'Old Man House Back')],
|
0xE3: [Pot(88, 0x17, PotItem.Nothing, 'Bat Cave (right)', PotFlags.LowerRegion),
|
||||||
230: [Pot(108, 12, PotItem.FiveArrows, 'Death Mountain Return Cave'), Pot(88, 16, PotItem.Heart, 'Death Mountain Return Cave'), Pot(72, 20, PotItem.Nothing, 'Death Mountain Return Cave'),
|
Pot(100, 0x19, PotItem.OneRupee, 'Bat Cave (right)', PotFlags.LowerRegion)],
|
||||||
Pot(56, 24, PotItem.OneRupee, 'Death Mountain Return Cave')],
|
0xE4: [Pot(32, 9, PotItem.FiveRupees, 'Old Man House'), Pot(112, 10, PotItem.OneRupee, 'Old Man House')],
|
||||||
231: [Pot(68, 5, PotItem.OneRupee, 'Death Mountain Return Cave'), Pot(72, 5, PotItem.OneRupee, 'Death Mountain Return Cave')],
|
0xE5: [Pot(48, 4, PotItem.OneRupee, 'Old Man House Back'), Pot(76, 4, PotItem.OneRupee, 'Old Man House Back'), Pot(112, 16, PotItem.OneRupee, 'Old Man House Back'), Pot(64, 18, PotItem.FiveRupees, 'Old Man House Back')],
|
||||||
232: [Pot(96, 4, PotItem.Heart, 'Superbunny Cave')],
|
0xE6: [Pot(108, 12, PotItem.FiveArrows, 'Death Mountain Return Cave (left)'), Pot(88, 16, PotItem.Heart, 'Death Mountain Return Cave (left)'), Pot(72, 20, PotItem.Nothing, 'Death Mountain Return Cave (left)'),
|
||||||
|
Pot(56, 24, PotItem.OneRupee, 'Death Mountain Return Cave (left)')],
|
||||||
|
0xE7: [Pot(68, 5, PotItem.OneRupee, 'Death Mountain Return Cave (right)'), Pot(72, 5, PotItem.OneRupee, 'Death Mountain Return Cave (right)')],
|
||||||
|
232: [Pot(96, 4, PotItem.Heart, 'Superbunny Cave (Bottom)')],
|
||||||
235: [Pot(206, 8, PotItem.FiveRupees, 'Bumper Cave'), Pot(210, 8, PotItem.FiveRupees, 'Bumper Cave'), Pot(88, 14, PotItem.SmallMagic, 'Bumper Cave'), Pot(92, 14, PotItem.Heart, 'Bumper Cave'), Pot(96, 14, PotItem.SmallMagic, 'Bumper Cave')],
|
235: [Pot(206, 8, PotItem.FiveRupees, 'Bumper Cave'), Pot(210, 8, PotItem.FiveRupees, 'Bumper Cave'), Pot(88, 14, PotItem.SmallMagic, 'Bumper Cave'), Pot(92, 14, PotItem.Heart, 'Bumper Cave'), Pot(96, 14, PotItem.SmallMagic, 'Bumper Cave')],
|
||||||
241: [Pot(64, 5, PotItem.Heart, 'Old Man Cave')],
|
241: [Pot(64, 5, PotItem.Heart, 'Old Man Cave')],
|
||||||
248: [Pot(242, 13, PotItem.BigMagic, 'Superbunny Cave')],
|
0xF3: [Pot(0x28, 0x14, PotItem.Nothing, 'Elder House'),
|
||||||
|
Pot(0x2C, 0x14, PotItem.Nothing, 'Elder House'),
|
||||||
|
Pot(0x30, 0x14, PotItem.Nothing, 'Elder House')],
|
||||||
|
248: [Pot(242, 13, PotItem.BigMagic, 'Superbunny Cave (Top)')],
|
||||||
253: [Pot(88, 6, PotItem.FiveRupees, 'Fairy Ascension Cave (Top)'), Pot(100, 6, PotItem.FiveRupees, 'Fairy Ascension Cave (Top)'), Pot(84, 23, PotItem.FiveRupees, 'Fairy Ascension Cave (Bottom)'),
|
253: [Pot(88, 6, PotItem.FiveRupees, 'Fairy Ascension Cave (Top)'), Pot(100, 6, PotItem.FiveRupees, 'Fairy Ascension Cave (Top)'), Pot(84, 23, PotItem.FiveRupees, 'Fairy Ascension Cave (Bottom)'),
|
||||||
Pot(84, 24, PotItem.FiveRupees, 'Fairy Ascension Cave (Bottom)')],
|
Pot(84, 24, PotItem.FiveRupees, 'Fairy Ascension Cave (Bottom)')],
|
||||||
255: [Pot(92, 8, PotItem.Heart, 'Paradox Cave'), Pot(96, 8, PotItem.Heart, 'Paradox Cave'), Pot(112, 28, PotItem.OneRupee, 'Paradox Cave Front')],
|
255: [Pot(92, 8, PotItem.Heart, 'Paradox Cave Bomb Area'), Pot(96, 8, PotItem.Heart, 'Paradox Cave Bomb Area'), Pot(112, 28, PotItem.OneRupee, 'Paradox Cave Front')],
|
||||||
257: [Pot(12, 20, PotItem.Heart, 'Snitch Lady (East)'), Pot(224, 19, PotItem.Chicken, 'Snitch Lady (West)'), Pot(228, 19, PotItem.Heart, 'Snitch Lady (West)')],
|
257: [Pot(12, 20, PotItem.Heart, 'Snitch Lady (East)'), Pot(224, 19, PotItem.Chicken, 'Snitch Lady (West)'), Pot(228, 19, PotItem.Heart, 'Snitch Lady (West)')],
|
||||||
258: [Pot(146, 19, PotItem.Heart, 'Sick Kids House'), Pot(150, 19, PotItem.Heart, 'Sick Kids House')],
|
258: [Pot(146, 19, PotItem.Heart, 'Sick Kids House'), Pot(150, 19, PotItem.Heart, 'Sick Kids House')],
|
||||||
259: [Pot(140, 7, PotItem.Chicken, 'Tavern'), Pot(140, 9, PotItem.Nothing, 'Tavern'), Pot(12, 12, PotItem.Heart, 'Tavern (Front)')],
|
259: [Pot(140, 7, PotItem.Chicken, 'Tavern'), Pot(140, 9, PotItem.Nothing, 'Tavern'), Pot(12, 12, PotItem.Heart, 'Tavern (Front)')],
|
||||||
260: [Pot(202, 21, PotItem.Heart, 'Links House'), Pot(202, 22, PotItem.Heart, 'Links House'), Pot(202, 23, PotItem.Heart, 'Links House')],
|
260: [Pot(202, 21, PotItem.Heart, 'Links House'), Pot(202, 22, PotItem.Heart, 'Links House'), Pot(202, 23, PotItem.Heart, 'Links House')],
|
||||||
261: [Pot(30, 20, PotItem.Heart, 'Sahasrahlas Hut'), Pot(28, 21, PotItem.Heart, 'Sahasrahlas Hut'), Pot(32, 21, PotItem.Heart, 'Sahasrahlas Hut')],
|
261: [Pot(30, 20, PotItem.Heart, 'Sahasrahlas Hut'), Pot(28, 21, PotItem.Heart, 'Sahasrahlas Hut'), Pot(32, 21, PotItem.Heart, 'Sahasrahlas Hut')],
|
||||||
|
0x106: [Pot(0x6c, 0x1b, PotItem.Nothing, 'Brewery')],
|
||||||
263: [Pot(214, 23, PotItem.Bomb, 'Light World Bomb Hut'), Pot(222, 23, PotItem.FiveArrows, 'Light World Bomb Hut'), Pot(230, 23, PotItem.Bomb, 'Light World Bomb Hut'), Pot(214, 25, PotItem.OneRupee, 'Light World Bomb Hut'),
|
263: [Pot(214, 23, PotItem.Bomb, 'Light World Bomb Hut'), Pot(222, 23, PotItem.FiveArrows, 'Light World Bomb Hut'), Pot(230, 23, PotItem.Bomb, 'Light World Bomb Hut'), Pot(214, 25, PotItem.OneRupee, 'Light World Bomb Hut'),
|
||||||
Pot(222, 25, PotItem.Nothing, 'Light World Bomb Hut'), Pot(230, 25, PotItem.OneRupee, 'Light World Bomb Hut'), Pot(214, 27, PotItem.Bomb, 'Light World Bomb Hut'), Pot(230, 27, PotItem.Bomb, 'Light World Bomb Hut')],
|
Pot(222, 25, PotItem.Nothing, 'Light World Bomb Hut'), Pot(230, 25, PotItem.OneRupee, 'Light World Bomb Hut'), Pot(214, 27, PotItem.Bomb, 'Light World Bomb Hut'), Pot(230, 27, PotItem.Bomb, 'Light World Bomb Hut')],
|
||||||
264: [Pot(166, 19, PotItem.Chicken, 'Chicken House')],
|
264: [Pot(166, 19, PotItem.Chicken, 'Chicken House')],
|
||||||
268: [Pot(88, 14, PotItem.Heart, 'Hookshot Fairy')],
|
268: [Pot(88, 14, PotItem.Heart, 'Hookshot Fairy')],
|
||||||
276: [Pot(92, 4, PotItem.Heart, 'Dark Desert Hint'), Pot(96, 4, PotItem.Heart, 'Dark Desert Hint'), Pot(92, 5, PotItem.Bomb, 'Dark Desert Hint'), Pot(96, 5, PotItem.Bomb, 'Dark Desert Hint'), Pot(92, 10, PotItem.FiveArrows, 'Dark Desert Hint'),
|
276: [Pot(92, 4, PotItem.Heart, 'Dark Desert Hint'), Pot(96, 4, PotItem.Heart, 'Dark Desert Hint'), Pot(92, 5, PotItem.Bomb, 'Dark Desert Hint'), Pot(96, 5, PotItem.Bomb, 'Dark Desert Hint'), Pot(92, 10, PotItem.FiveArrows, 'Dark Desert Hint'),
|
||||||
Pot(96, 10, PotItem.Heart, 'Dark Desert Hint')],
|
Pot(96, 10, PotItem.Heart, 'Dark Desert Hint')],
|
||||||
279: [Pot(138, 3, PotItem.Heart, 'Spike Cave'), Pot(142, 3, PotItem.Heart, 'Spike Cave'), Pot(166, 3, PotItem.Heart, 'Spike Cave'), Pot(170, 3, PotItem.Heart, 'Spike Cave'), Pot(138, 4, PotItem.Heart, 'Spike Cave'),
|
0x117: [Pot(138, 3, PotItem.Heart, 'Spike Cave'), Pot(142, 3, PotItem.Heart, 'Spike Cave'),
|
||||||
Pot(142, 4, PotItem.Heart, 'Spike Cave'), Pot(166, 4, PotItem.Heart, 'Spike Cave'), Pot(170, 4, PotItem.Heart, 'Spike Cave')],
|
Pot(166, 3, PotItem.Heart, 'Spike Cave'), Pot(170, 3, PotItem.Heart, 'Spike Cave'),
|
||||||
|
Pot(138, 4, PotItem.Heart, 'Spike Cave'), Pot(142, 4, PotItem.Heart, 'Spike Cave'),
|
||||||
|
Pot(166, 4, PotItem.Heart, 'Spike Cave'), Pot(170, 4, PotItem.Heart, 'Spike Cave'),
|
||||||
|
Pot(0x18, 0x8, PotItem.Nothing, 'Spike Cave', PotFlags.Block)],
|
||||||
281: [Pot(44, 28, PotItem.Heart, 'Blinds Hideout'), Pot(48, 28, PotItem.OneRupee, 'Blinds Hideout'), Pot(76, 28, PotItem.Heart, 'Blinds Hideout'), Pot(80, 28, PotItem.Heart, 'Blinds Hideout')],
|
281: [Pot(44, 28, PotItem.Heart, 'Blinds Hideout'), Pot(48, 28, PotItem.OneRupee, 'Blinds Hideout'), Pot(76, 28, PotItem.Heart, 'Blinds Hideout'), Pot(80, 28, PotItem.Heart, 'Blinds Hideout')],
|
||||||
282: [Pot(214, 10, PotItem.Heart, 'Palace of Darkness Hint'), Pot(218, 10, PotItem.Heart, 'Palace of Darkness Hint'), Pot(226, 10, PotItem.Heart, 'Palace of Darkness Hint'), Pot(230, 10, PotItem.Heart, 'Palace of Darkness Hint')],
|
282: [Pot(214, 10, PotItem.Heart, 'Palace of Darkness Hint'), Pot(218, 10, PotItem.Heart, 'Palace of Darkness Hint'), Pot(226, 10, PotItem.Heart, 'Palace of Darkness Hint'), Pot(230, 10, PotItem.Heart, 'Palace of Darkness Hint')],
|
||||||
283: [Pot(24, 53, PotItem.Nothing, 'Cave 45'), Pot(24, 54, PotItem.Heart, 'Cave 45'), Pot(32, 54, PotItem.Heart, 'Cave 45'), Pot(40, 54, PotItem.Heart, 'Cave 45'), Pot(24, 55, PotItem.Heart, 'Cave 45'), Pot(28, 56, PotItem.Heart, 'Cave 45'),
|
0x11B: [Pot(24, 0x15, PotItem.Nothing, 'Cave 45', PotFlags.LowerRegion),
|
||||||
Pot(92, 22, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 22, PotItem.Heart, 'Graveyard Cave'), Pot(92, 23, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 23, PotItem.Heart, 'Graveyard Cave'), Pot(92, 24, PotItem.Bomb, 'Graveyard Cave'),
|
Pot(24, 0x16, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
|
||||||
Pot(96, 24, PotItem.Heart, 'Graveyard Cave'), Pot(92, 25, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 25, PotItem.Heart, 'Graveyard Cave')],
|
Pot(32, 0x16, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
|
||||||
285: [Pot(60, 6, PotItem.FiveRupees, 'Blinds Hideout'), Pot(64, 6, PotItem.FiveRupees, 'Blinds Hideout'), Pot(60, 7, PotItem.FiveRupees, 'Blinds Hideout'), Pot(64, 7, PotItem.FiveRupees, 'Blinds Hideout'),
|
Pot(40, 0x16, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
|
||||||
Pot(60, 8, PotItem.FiveRupees, 'Blinds Hideout'), Pot(64, 8, PotItem.FiveRupees, 'Blinds Hideout')],
|
Pot(24, 0x17, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
|
||||||
287: [Pot(174, 28, PotItem.Heart, 'Lumberjack House'), Pot(178, 28, PotItem.Heart, 'Lumberjack House')],
|
Pot(28, 0x18, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
|
||||||
|
Pot(92, 22, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 22, PotItem.Heart, 'Graveyard Cave'),
|
||||||
|
Pot(92, 23, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 23, PotItem.Heart, 'Graveyard Cave'),
|
||||||
|
Pot(92, 24, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 24, PotItem.Heart, 'Graveyard Cave'),
|
||||||
|
Pot(92, 25, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 25, PotItem.Heart, 'Graveyard Cave')],
|
||||||
|
0x11D: [Pot(60, 6, PotItem.FiveRupees, 'Blinds Hideout (Top)'), Pot(64, 6, PotItem.FiveRupees, 'Blinds Hideout (Top)'),
|
||||||
|
Pot(60, 7, PotItem.FiveRupees, 'Blinds Hideout (Top)'), Pot(64, 7, PotItem.FiveRupees, 'Blinds Hideout (Top)'),
|
||||||
|
Pot(60, 8, PotItem.FiveRupees, 'Blinds Hideout (Top)'), Pot(64, 8, PotItem.FiveRupees, 'Blinds Hideout (Top)')],
|
||||||
|
0x11F: [Pot(174, 28, PotItem.Heart, 'Lumberjack House'), Pot(178, 28, PotItem.Heart, 'Lumberjack House')],
|
||||||
292: [Pot(20, 20, PotItem.FiveRupees, '50 Rupee Cave'), Pot(40, 20, PotItem.FiveRupees, '50 Rupee Cave'), Pot(20, 21, PotItem.FiveRupees, '50 Rupee Cave'), Pot(40, 21, PotItem.FiveRupees, '50 Rupee Cave'),
|
292: [Pot(20, 20, PotItem.FiveRupees, '50 Rupee Cave'), Pot(40, 20, PotItem.FiveRupees, '50 Rupee Cave'), Pot(20, 21, PotItem.FiveRupees, '50 Rupee Cave'), Pot(40, 21, PotItem.FiveRupees, '50 Rupee Cave'),
|
||||||
Pot(20, 22, PotItem.FiveRupees, '50 Rupee Cave'), Pot(40, 22, PotItem.FiveRupees, '50 Rupee Cave'), Pot(24, 24, PotItem.FiveRupees, '50 Rupee Cave'), Pot(28, 24, PotItem.FiveRupees, '50 Rupee Cave'),
|
Pot(20, 22, PotItem.FiveRupees, '50 Rupee Cave'), Pot(40, 22, PotItem.FiveRupees, '50 Rupee Cave'), Pot(24, 24, PotItem.FiveRupees, '50 Rupee Cave'), Pot(28, 24, PotItem.FiveRupees, '50 Rupee Cave'),
|
||||||
Pot(32, 24, PotItem.FiveRupees, '50 Rupee Cave'), Pot(36, 24, PotItem.FiveRupees, '50 Rupee Cave')],
|
Pot(32, 24, PotItem.FiveRupees, '50 Rupee Cave'), Pot(36, 24, PotItem.FiveRupees, '50 Rupee Cave')],
|
||||||
293: [Pot(24, 25, PotItem.FiveRupees, '20 Rupee Cave'), Pot(28, 25, PotItem.FiveRupees, '20 Rupee Cave'), Pot(32, 25, PotItem.FiveRupees, '20 Rupee Cave'), Pot(36, 25, PotItem.FiveRupees, '20 Rupee Cave'),
|
293: [Pot(24, 25, PotItem.FiveRupees, '20 Rupee Cave'), Pot(28, 25, PotItem.FiveRupees, '20 Rupee Cave'), Pot(32, 25, PotItem.FiveRupees, '20 Rupee Cave'), Pot(36, 25, PotItem.FiveRupees, '20 Rupee Cave'),
|
||||||
Pot(88, 22, PotItem.Heart, 'Dev Cave Hint'), Pot(100, 22, PotItem.Heart, 'Dev Cave Hint'), Pot(88, 28, PotItem.Heart, 'Dev Cave Hint'), Pot(100, 28, PotItem.Heart, 'Dev Cave Hint')],
|
Pot(88, 22, PotItem.Heart, 'Dark Lake Hylia Ledge Spike Cave'), Pot(100, 22, PotItem.Heart, 'Dark Lake Hylia Ledge Spike Cave'), Pot(88, 28, PotItem.Heart, 'Dark Lake Hylia Ledge Spike Cave'), Pot(100, 28, PotItem.Heart, 'Dark Lake Hylia Ledge Spike Cave')],
|
||||||
295: [Pot(24, 25, PotItem.Nothing, 'Hammer Pegs Cave'), Pot(28, 25, PotItem.Nothing, 'Hammer Pegs Cave'), Pot(32, 25, PotItem.Nothing, 'Hammer Pegs Cave'), Pot(36, 25, PotItem.Nothing, 'Hammer Pegs Cave')],
|
0x127: [Pot(24, 25, PotItem.Nothing, 'Dark World Hammer Peg Cave'), Pot(28, 25, PotItem.Nothing, 'Dark World Hammer Peg Cave'), Pot(32, 25, PotItem.Nothing, 'Dark World Hammer Peg Cave'), Pot(36, 25, PotItem.Nothing, 'Dark World Hammer Peg Cave')],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def shuffle_pots(world, player):
|
def shuffle_pots(world, player):
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
|
|
||||||
new_pot_contents = {}
|
new_pot_contents = PotSecretTable()
|
||||||
|
|
||||||
for supertile in vanilla_pots:
|
for super_tile in vanilla_pots:
|
||||||
old_pots = vanilla_pots[supertile]
|
old_pots = vanilla_pots[super_tile]
|
||||||
new_pots = [Pot(pot.x, pot.y, PotItem.Nothing, pot.room, pot.flags) for pot in old_pots]
|
new_pots = [Pot(pot.x, pot.y, PotItem.Nothing, pot.room, pot.flags) for pot in old_pots]
|
||||||
# sort in the order Hole, Switch, Key, Other, Nothing
|
# sort in the order Hole, Switch, Key, Other, Nothing
|
||||||
sort_order = {PotItem.Hole: 4, PotItem.Switch: 3, PotItem.Key: 2, PotItem.Nothing: 0}
|
sort_order = {PotItem.Hole: 4, PotItem.Switch: 3, PotItem.Key: 2, PotItem.Nothing: 0}
|
||||||
@@ -295,7 +381,7 @@ def shuffle_pots(world, player):
|
|||||||
elif old_pot.item == PotItem.Switch:
|
elif old_pot.item == PotItem.Switch:
|
||||||
available_pots = (pot for pot in new_pots if (pot.room == old_pot.room or pot.room in movable_switch_rooms[old_pot.room]) and not (pot.flags & PotFlags.NoSwitch))
|
available_pots = (pot for pot in new_pots if (pot.room == old_pot.room or pot.room in movable_switch_rooms[old_pot.room]) and not (pot.flags & PotFlags.NoSwitch))
|
||||||
elif old_pot.item == PotItem.Key:
|
elif old_pot.item == PotItem.Key:
|
||||||
if world.doorShuffle[player] == 'vanilla' and not world.retro[player] and not world.keydropshuffle[player] and world.logic[player] != 'nologic':
|
if world.doorShuffle[player] == 'vanilla' and not world.retro[player] and world.keydropshuffle[player] == 'none' and world.logic[player] != 'nologic':
|
||||||
available_pots = (pot for pot in new_pots if pot.room not in invalid_key_rooms)
|
available_pots = (pot for pot in new_pots if pot.room not in invalid_key_rooms)
|
||||||
else:
|
else:
|
||||||
available_pots = new_pots
|
available_pots = new_pots
|
||||||
@@ -309,9 +395,11 @@ def shuffle_pots(world, player):
|
|||||||
if world.retro[player] and new_pot.item == PotItem.FiveArrows:
|
if world.retro[player] and new_pot.item == PotItem.FiveArrows:
|
||||||
new_pot.item = PotItem.FiveRupees
|
new_pot.item = PotItem.FiveRupees
|
||||||
|
|
||||||
if new_pot.item == PotItem.Key and new_pot.room != old_pot.room:
|
if new_pot.item == PotItem.Key:
|
||||||
# Move pot key to new room
|
|
||||||
key = next(location for location in world.get_region(old_pot.room, player).locations if location.name in key_drop_data)
|
key = next(location for location in world.get_region(old_pot.room, player).locations if location.name in key_drop_data)
|
||||||
|
key.pot = new_pot
|
||||||
|
if new_pot.room != old_pot.room:
|
||||||
|
# Move pot key to new room
|
||||||
world.get_region(old_pot.room, player).locations.remove(key)
|
world.get_region(old_pot.room, player).locations.remove(key)
|
||||||
world.get_region(new_pot.room, player).locations.append(key)
|
world.get_region(new_pot.room, player).locations.append(key)
|
||||||
key.parent_region = world.get_region(new_pot.room, player)
|
key.parent_region = world.get_region(new_pot.room, player)
|
||||||
@@ -328,8 +416,123 @@ def shuffle_pots(world, player):
|
|||||||
# Rule is created based on barrier
|
# Rule is created based on barrier
|
||||||
world.get_door('Thieves Attic ES', player).barrier(CrystalBarrier.Orange)
|
world.get_door('Thieves Attic ES', player).barrier(CrystalBarrier.Orange)
|
||||||
else:
|
else:
|
||||||
raise Exception("Switch locattion in room %s requires logic change" % new_pot.room)
|
raise Exception("Switch location in room %s requires logic change" % new_pot.room)
|
||||||
|
|
||||||
new_pot_contents[supertile] = new_pots
|
new_pot_contents.room_map[super_tile] = new_pots
|
||||||
|
|
||||||
world.pot_contents[player] = new_pot_contents
|
world.pot_contents[player] = new_pot_contents
|
||||||
|
|
||||||
|
|
||||||
|
def shuffle_pot_switches(world, player):
|
||||||
|
import RaceRandom as random
|
||||||
|
|
||||||
|
for super_tile in vanilla_pots:
|
||||||
|
new_pots = world.pot_contents[player].room_map[super_tile]
|
||||||
|
# sort in the order Hole, Switch, Key, Other, Nothing
|
||||||
|
sort_order = {PotItem.Hole: 4, PotItem.Switch: 3, PotItem.Key: 2, PotItem.Nothing: 0}
|
||||||
|
old_pots = sorted(new_pots, key=lambda pot: sort_order.get(pot.item, 1), reverse=True)
|
||||||
|
|
||||||
|
for old_pot in old_pots:
|
||||||
|
if old_pot.item != PotItem.Switch:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
available_pots = [pot for pot in new_pots if (pot.room == old_pot.room or pot.room in movable_switch_rooms[old_pot.room]) and not (pot.flags & PotFlags.NoSwitch)]
|
||||||
|
|
||||||
|
new_pot = random.choice(available_pots)
|
||||||
|
new_pot.item, old_pot.item = old_pot.item, new_pot.item
|
||||||
|
if world.retro[player] and new_pot.item == PotItem.FiveArrows:
|
||||||
|
new_pot.item = PotItem.FiveRupees
|
||||||
|
|
||||||
|
if new_pot.item == PotItem.Switch and (new_pot.flags & PotFlags.SwitchLogicChange):
|
||||||
|
if new_pot.room == 'PoD Basement Ledge':
|
||||||
|
basement = world.get_region(old_pot.room, player)
|
||||||
|
ledge = world.get_region(new_pot.room, player)
|
||||||
|
ledge.locations.append(basement.locations.pop())
|
||||||
|
elif new_pot.room == 'Swamp Push Statue':
|
||||||
|
from Rules import set_rule
|
||||||
|
set_rule(world.get_entrance('Swamp Push Statue NE', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
|
world.get_door('Swamp Push Statue NW', player).blocked = True
|
||||||
|
elif new_pot.room == 'Thieves Attic Hint':
|
||||||
|
# Rule is created based on barrier
|
||||||
|
world.get_door('Thieves Attic ES', player).barrier(CrystalBarrier.Orange)
|
||||||
|
else:
|
||||||
|
raise Exception("Switch location in room %s requires logic change" % new_pot.room)
|
||||||
|
for location in world.get_locations():
|
||||||
|
if location.player == player and location.type == LocationType.Pot and location.pot.item == PotItem.Switch:
|
||||||
|
location.real = False
|
||||||
|
if location in world.dynamic_locations:
|
||||||
|
world.dynamic_locations.remove(location)
|
||||||
|
location.parent_region.locations.remove(location)
|
||||||
|
world.clear_location_cache()
|
||||||
|
|
||||||
|
|
||||||
|
key_drop_data = {
|
||||||
|
'Hyrule Castle - Map Guard Key Drop': ['Drop', (0x09E20C, 0x72, 0), 'dropped in Hyrule Castle', 'Small Key (Escape)'],
|
||||||
|
'Hyrule Castle - Boomerang Guard Key Drop': ['Drop', (0x09E204, 0x71, 1), 'dropped in Hyrule Castle', 'Small Key (Escape)'],
|
||||||
|
'Hyrule Castle - Key Rat Key Drop': ['Drop', (0x09DB80, 0x21, 0), 'dropped in Hyrule Castle', 'Small Key (Escape)'],
|
||||||
|
'Hyrule Castle - Big Key Drop': ['Drop', (0x09E327, 0x80, 2), 'dropped in Hyrule Castle', 'Big Key (Escape)'],
|
||||||
|
'Eastern Palace - Dark Square Pot Key': ['Pot', 0xBA, 'in a pot in Eastern Palace', 'Small Key (Eastern Palace)'],
|
||||||
|
'Eastern Palace - Dark Eyegore Key Drop': ['Drop', (0x09E4F8, 0x99, 3), 'dropped in Eastern Palace', 'Small Key (Eastern Palace)'],
|
||||||
|
'Desert Palace - Desert Tiles 1 Pot Key': ['Pot', 0x63, 'in a pot in Desert Palace', 'Small Key (Desert Palace)'],
|
||||||
|
'Desert Palace - Beamos Hall Pot Key': ['Pot', 0x53, 'in a pot in Desert Palace', 'Small Key (Desert Palace)'],
|
||||||
|
'Desert Palace - Desert Tiles 2 Pot Key': ['Pot', 0x43, 'in a pot in Desert Palace', 'Small Key (Desert Palace)'],
|
||||||
|
'Castle Tower - Dark Archer Key Drop': ['Drop', (0x09E7C9, 0xC0, 3), 'dropped in Castle Tower', 'Small Key (Agahnims Tower)'],
|
||||||
|
'Castle Tower - Circle of Pots Key Drop': ['Drop', (0x09E688, 0xB0, 10), 'dropped in Castle Tower', 'Small Key (Agahnims Tower)'],
|
||||||
|
'Swamp Palace - Pot Row Pot Key': ['Pot', 0x38, 'in a pot in Swamp Palace', 'Small Key (Swamp Palace)'],
|
||||||
|
'Swamp Palace - Trench 1 Pot Key': ['Pot', 0x37, 'in a pot in Swamp Palace', 'Small Key (Swamp Palace)'],
|
||||||
|
'Swamp Palace - Hookshot Pot Key': ['Pot', 0x36, 'in a pot in Swamp Palace', 'Small Key (Swamp Palace)'],
|
||||||
|
'Swamp Palace - Trench 2 Pot Key': ['Pot', 0x35, 'in a pot in Swamp Palace', 'Small Key (Swamp Palace)'],
|
||||||
|
'Swamp Palace - Waterway Pot Key': ['Pot', 0x16, 'in a pot in Swamp Palace', 'Small Key (Swamp Palace)'],
|
||||||
|
'Skull Woods - West Lobby Pot Key': ['Pot', 0x56, 'in a pot in Skull Woods', 'Small Key (Skull Woods)'],
|
||||||
|
'Skull Woods - Spike Corner Key Drop': ['Drop', (0x09DD74, 0x39, 1), 'dropped near Mothula', 'Small Key (Skull Woods)'],
|
||||||
|
"Thieves' Town - Hallway Pot Key": ['Pot', 0xBC, "in a pot in Thieves' Town", 'Small Key (Thieves Town)'],
|
||||||
|
"Thieves' Town - Spike Switch Pot Key": ['Pot', 0xAB, "in a pot in Thieves' Town", 'Small Key (Thieves Town)'],
|
||||||
|
'Ice Palace - Jelly Key Drop': ['Drop', (0x09DA21, 0xE, 3), 'dropped in Ice Palace', 'Small Key (Ice Palace)'],
|
||||||
|
'Ice Palace - Conveyor Key Drop': ['Drop', (0x09DE08, 0x3E, 8), 'dropped in Ice Palace', 'Small Key (Ice Palace)'],
|
||||||
|
'Ice Palace - Hammer Block Key Drop': ['Pot', 0x3F, 'under a block in Ice Palace', 'Small Key (Ice Palace)'],
|
||||||
|
'Ice Palace - Many Pots Pot Key': ['Pot', 0x9F, 'int a pot in Ice Palace', 'Small Key (Ice Palace)'],
|
||||||
|
'Misery Mire - Spikes Pot Key': ['Pot', 0xB3, 'in a pot in Misery Mire', 'Small Key (Misery Mire)'],
|
||||||
|
'Misery Mire - Fishbone Pot Key': ['Pot', 0xA1, 'in a pot in forgotten Mire', 'Small Key (Misery Mire)'],
|
||||||
|
'Misery Mire - Conveyor Crystal Key Drop': ['Drop', (0x09E7FB, 0xC1, 9), 'dropped in Misery Mire', 'Small Key (Misery Mire)'],
|
||||||
|
'Turtle Rock - Pokey 1 Key Drop': ['Drop', (0x09E70D, 0xB6, 5), 'dropped in Turtle Rock', 'Small Key (Turtle Rock)'],
|
||||||
|
'Turtle Rock - Pokey 2 Key Drop': ['Drop', (0x09DA5D, 0x13, 6), 'dropped in Turtle Rock', 'Small Key (Turtle Rock)'],
|
||||||
|
'Ganons Tower - Conveyor Cross Pot Key': ['Pot', 0x8B, "in a pot in Ganon's Tower", 'Small Key (Ganons Tower)'],
|
||||||
|
'Ganons Tower - Double Switch Pot Key': ['Pot', 0x9B, "in a pot in Ganon's Tower", 'Small Key (Ganons Tower)'],
|
||||||
|
'Ganons Tower - Conveyor Star Pits Pot Key': ['Pot', 0x7B, "in a pot in Ganon's Tower", 'Small Key (Ganons Tower)'],
|
||||||
|
'Ganons Tower - Mini Helmasaur Key Drop': ['Drop', (0x09DDC4, 0x3D, 2), "dropped atop Ganon's Tower", 'Small Key (Ganons Tower)']
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PotSecretTable(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.room_map = defaultdict(list)
|
||||||
|
self.multiworld_count = 0
|
||||||
|
|
||||||
|
def write_pot_data_to_rom(self, rom):
|
||||||
|
pointer_address = 0x140000 # pots currently in bank 28
|
||||||
|
pointer_offset = 0x128 * 2
|
||||||
|
empty_address = (pointer_address + pointer_offset)
|
||||||
|
empty_pointer = pc_to_snes(empty_address) & 0xFFFF
|
||||||
|
data_pointer = pointer_address + pointer_offset + 2
|
||||||
|
for room in range(0, 0x128):
|
||||||
|
if room in self.room_map and any(p for p in self.room_map[room] if not p.empty()):
|
||||||
|
list_idx = 0
|
||||||
|
data_address = pc_to_snes(data_pointer) & 0xFFFF
|
||||||
|
rom.write_bytes(pointer_address + room * 2, int16_as_bytes(data_address))
|
||||||
|
for pot in self.room_map[room]:
|
||||||
|
rom.write_bytes(data_pointer + list_idx * 3, pot.pot_data())
|
||||||
|
list_idx += 1
|
||||||
|
rom.write_bytes(data_pointer + list_idx * 3, [0xFF, 0xFF])
|
||||||
|
data_pointer += 3 * list_idx + 2
|
||||||
|
else:
|
||||||
|
rom.write_bytes(pointer_address + room * 2, int16_as_bytes(empty_pointer))
|
||||||
|
rom.write_bytes(empty_address, [0xFF, 0xFF])
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
size = 0x128 * 2
|
||||||
|
for room in range(0, 0x128):
|
||||||
|
if room in self.room_map:
|
||||||
|
pot_list = [p for p in self.room_map[room]]
|
||||||
|
if pot_list:
|
||||||
|
size += len(pot_list) * 3 + 2
|
||||||
|
return size
|
||||||
|
|||||||
@@ -1,5 +1,37 @@
|
|||||||
## New Features
|
## New Features
|
||||||
|
|
||||||
|
## Pottery Lottery and Key Drop Shuffle Changes
|
||||||
|
|
||||||
|
### Pottery
|
||||||
|
|
||||||
|
New pottery option that control which pots are in the locations pool:
|
||||||
|
|
||||||
|
* None: No pots are in the pool, like normal randomizer
|
||||||
|
* Key Pots: The pots that have keys are in the pool. This is about half of the old keydropshuffle option
|
||||||
|
* Lottery: All pots and large blocks are in the pool
|
||||||
|
|
||||||
|
By default, switches remain in their vanilla location (unless you turn on the legacy option below)
|
||||||
|
|
||||||
|
CLI `--pottery <option>` from `none, keys, lottery`
|
||||||
|
|
||||||
|
Note for multiworld: due to the design of the pottery lottery, only 256 items for other players can be under pots in your world.
|
||||||
|
|
||||||
|
### Shuffle key drops
|
||||||
|
|
||||||
|
Enemies that drop keys can have their drop shuffled into the pool. This is the other half of the keydropshuffle option.
|
||||||
|
|
||||||
|
CLI `--dropshuffle`
|
||||||
|
|
||||||
|
#### Legacy options
|
||||||
|
|
||||||
|
"Drop and Pot Keys" or `--keydropshuffle` is still availabe for use. This simply sets the pottery to keys and turns dropshuffle on as well to have the same behavior as the
|
||||||
|
|
||||||
|
The old "Pot Shuffle" option is available under "Shuffle Pot Switches" or `--shuffleswitches` and works the same by shuffling all pots on a supertile. It works with the lottery option as well to move the switches while having every pot in the pool. I have no justification for the name change on the CLI/Mystery, it just kind of happened and I was too lazy to change it back.
|
||||||
|
|
||||||
|
#### Tracking Notes
|
||||||
|
|
||||||
|
The sram locations for pots and sprite drops have been moved, please reach out for assistance or investigate the rom changes.
|
||||||
|
|
||||||
## Restricted Item Placement Algorithm
|
## Restricted Item Placement Algorithm
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+94
-68
@@ -1,6 +1,7 @@
|
|||||||
import collections
|
import collections
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType
|
from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType, LocationType, PotItem, PotFlags
|
||||||
|
from PotShuffle import key_drop_data, vanilla_pots, PotSecretTable
|
||||||
|
|
||||||
|
|
||||||
def create_regions(world, player):
|
def create_regions(world, player):
|
||||||
@@ -18,11 +19,13 @@ def create_regions(world, player):
|
|||||||
'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid']),
|
'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid']),
|
||||||
create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop']),
|
create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop']),
|
||||||
create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Teleporter']),
|
create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Teleporter']),
|
||||||
create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', ["Blind\'s Hideout - Top",
|
create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', [
|
||||||
"Blind\'s Hideout - Left",
|
"Blind's Hideout - Left",
|
||||||
"Blind\'s Hideout - Right",
|
"Blind's Hideout - Right",
|
||||||
"Blind\'s Hideout - Far Left",
|
"Blind's Hideout - Far Left",
|
||||||
"Blind\'s Hideout - Far Right"]),
|
"Blind's Hideout - Far Right"],
|
||||||
|
['Blinds Hideout N']),
|
||||||
|
create_cave_region(player, 'Blinds Hideout (Top)', 'a bounty of five items', ["Blind's Hideout - Top"]),
|
||||||
create_cave_region(player, 'Hyrule Castle Secret Entrance', 'a drop\'s exit', ['Link\'s Uncle', 'Secret Passage'], ['Hyrule Castle Secret Entrance Exit']),
|
create_cave_region(player, 'Hyrule Castle Secret Entrance', 'a drop\'s exit', ['Link\'s Uncle', 'Secret Passage'], ['Hyrule Castle Secret Entrance Exit']),
|
||||||
create_lw_region(player, 'Zoras River', ['King Zora', 'Zora\'s Ledge']),
|
create_lw_region(player, 'Zoras River', ['King Zora', 'Zora\'s Ledge']),
|
||||||
create_cave_region(player, 'Waterfall of Wishing', 'a cave with two chests', ['Waterfall Fairy - Left', 'Waterfall Fairy - Right']),
|
create_cave_region(player, 'Waterfall of Wishing', 'a cave with two chests', ['Waterfall Fairy - Left', 'Waterfall Fairy - Right']),
|
||||||
@@ -55,12 +58,15 @@ def create_regions(world, player):
|
|||||||
create_cave_region(player, 'Chicken House', 'a house with a chest', ['Chicken House']),
|
create_cave_region(player, 'Chicken House', 'a house with a chest', ['Chicken House']),
|
||||||
create_cave_region(player, 'Aginahs Cave', 'a cave with a chest', ['Aginah\'s Cave']),
|
create_cave_region(player, 'Aginahs Cave', 'a cave with a chest', ['Aginah\'s Cave']),
|
||||||
create_cave_region(player, 'Sahasrahlas Hut', 'Sahasrahla', ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right', 'Sahasrahla']),
|
create_cave_region(player, 'Sahasrahlas Hut', 'Sahasrahla', ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right', 'Sahasrahla']),
|
||||||
create_cave_region(player, 'Kakariko Well (top)', 'a drop\'s exit', ['Kakariko Well - Top', 'Kakariko Well - Left', 'Kakariko Well - Middle',
|
create_cave_region(player, 'Kakariko Well (top)', 'a drop',
|
||||||
'Kakariko Well - Right', 'Kakariko Well - Bottom'], ['Kakariko Well (top to bottom)']),
|
['Kakariko Well - Left', 'Kakariko Well - Middle', 'Kakariko Well - Right',
|
||||||
|
'Kakariko Well - Bottom'],
|
||||||
|
['Kakariko Well (top to bottom)', 'Kakariko Well (top to back)']),
|
||||||
|
create_cave_region(player, 'Kakariko Well (back)', 'a drop', ['Kakariko Well - Top']),
|
||||||
create_cave_region(player, 'Kakariko Well (bottom)', 'a drop\'s exit', None, ['Kakariko Well Exit']),
|
create_cave_region(player, 'Kakariko Well (bottom)', 'a drop\'s exit', None, ['Kakariko Well Exit']),
|
||||||
create_cave_region(player, 'Blacksmiths Hut', 'the smith', ['Blacksmith', 'Missing Smith']),
|
create_cave_region(player, 'Blacksmiths Hut', 'the smith', ['Blacksmith', 'Missing Smith']),
|
||||||
create_lw_region(player, 'Bat Cave Drop Ledge', None, ['Bat Cave Drop']),
|
create_lw_region(player, 'Bat Cave Drop Ledge', None, ['Bat Cave Drop']),
|
||||||
create_cave_region(player, 'Bat Cave (right)', 'a drop\'s exit', ['Magic Bat'], ['Bat Cave Door']),
|
create_cave_region(player, 'Bat Cave (right)', 'a drop', ['Magic Bat'], ['Bat Cave Door']),
|
||||||
create_cave_region(player, 'Bat Cave (left)', 'a drop\'s exit', None, ['Bat Cave Exit']),
|
create_cave_region(player, 'Bat Cave (left)', 'a drop\'s exit', None, ['Bat Cave Exit']),
|
||||||
create_cave_region(player, 'Sick Kids House', 'the sick kid', ['Sick Kid']),
|
create_cave_region(player, 'Sick Kids House', 'the sick kid', ['Sick Kid']),
|
||||||
create_lw_region(player, 'Hobo Bridge', ['Hobo']),
|
create_lw_region(player, 'Hobo Bridge', ['Hobo']),
|
||||||
@@ -106,7 +112,8 @@ def create_regions(world, player):
|
|||||||
create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']),
|
create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']),
|
||||||
create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']),
|
create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']),
|
||||||
create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter']),
|
create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter']),
|
||||||
create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']),
|
create_cave_region(player, 'Death Mountain Return Cave (left)', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave E']),
|
||||||
|
create_cave_region(player, 'Death Mountain Return Cave (right)', 'a connector', None, ['Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave W']),
|
||||||
create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)']),
|
create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)']),
|
||||||
create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']),
|
create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']),
|
||||||
create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']),
|
create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']),
|
||||||
@@ -119,9 +126,10 @@ def create_regions(world, player):
|
|||||||
'Paradox Cave Lower - Right',
|
'Paradox Cave Lower - Right',
|
||||||
'Paradox Cave Lower - Far Right',
|
'Paradox Cave Lower - Far Right',
|
||||||
'Paradox Cave Lower - Middle',
|
'Paradox Cave Lower - Middle',
|
||||||
'Paradox Cave Upper - Left',
|
],
|
||||||
'Paradox Cave Upper - Right'],
|
['Paradox Cave Push Block', 'Paradox Cave Bomb Jump', 'Paradox Cave Chest Area NE']),
|
||||||
['Paradox Cave Push Block', 'Paradox Cave Bomb Jump']),
|
create_cave_region(player, 'Paradox Cave Bomb Area', 'a connector', ['Paradox Cave Upper - Left',
|
||||||
|
'Paradox Cave Upper - Right']),
|
||||||
create_cave_region(player, 'Paradox Cave', 'a connector', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']),
|
create_cave_region(player, 'Paradox Cave', 'a connector', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']),
|
||||||
create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop', ['Paradox Shop - Left', 'Paradox Shop - Middle', 'Paradox Shop - Right']),
|
create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop', ['Paradox Shop - Left', 'Paradox Shop - Middle', 'Paradox Shop - Right']),
|
||||||
create_lw_region(player, 'East Death Mountain (Top)', None, ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'Turtle Rock Teleporter', 'Fairy Ascension Ledge']),
|
create_lw_region(player, 'East Death Mountain (Top)', None, ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'Turtle Rock Teleporter', 'Fairy Ascension Ledge']),
|
||||||
@@ -190,8 +198,10 @@ def create_regions(world, player):
|
|||||||
create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']),
|
create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']),
|
||||||
create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']),
|
create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']),
|
||||||
create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']),
|
create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']),
|
||||||
create_cave_region(player, 'Hookshot Cave (Front)', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'],
|
create_cave_region(player, 'Hookshot Cave (Front)', 'a connector', None,
|
||||||
['Hookshot Cave Front to Middle', 'Hookshot Cave Front Exit']),
|
['Hookshot Cave Front to Middle', 'Hookshot Cave Front Exit', 'Hookshot Cave Bonk Path', 'Hookshot Cave Hook Path']),
|
||||||
|
create_cave_region(player, 'Hookshot Cave (Bonk Islands)', 'a connector', ['Hookshot Cave - Bottom Right']),
|
||||||
|
create_cave_region(player, 'Hookshot Cave (Hook Islands)', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Left']),
|
||||||
create_cave_region(player, 'Hookshot Cave (Back)', 'a connector', None, ['Hookshot Cave Back to Middle', 'Hookshot Cave Back Exit']),
|
create_cave_region(player, 'Hookshot Cave (Back)', 'a connector', None, ['Hookshot Cave Back to Middle', 'Hookshot Cave Back Exit']),
|
||||||
create_cave_region(player, 'Hookshot Cave (Middle)', 'a connector', None, ['Hookshot Cave Middle to Back', 'Hookshot Cave Middle to Front']),
|
create_cave_region(player, 'Hookshot Cave (Middle)', 'a connector', None, ['Hookshot Cave Middle to Back', 'Hookshot Cave Middle to Front']),
|
||||||
|
|
||||||
@@ -368,7 +378,8 @@ def create_dungeon_regions(world, player):
|
|||||||
create_dungeon_region(player, 'Hera Startile Wide - Crystal', 'Tower of Hera', None, ['Hera Startile Wide Crystal Exit']),
|
create_dungeon_region(player, 'Hera Startile Wide - Crystal', 'Tower of Hera', None, ['Hera Startile Wide Crystal Exit']),
|
||||||
create_dungeon_region(player, 'Hera 4F', 'Tower of Hera', ['Tower of Hera - Compass Chest'], ['Hera 4F Down Stairs', 'Hera 4F Up Stairs', 'Hera Big Chest Hook Path', 'Hera 4F Holes']),
|
create_dungeon_region(player, 'Hera 4F', 'Tower of Hera', ['Tower of Hera - Compass Chest'], ['Hera 4F Down Stairs', 'Hera 4F Up Stairs', 'Hera Big Chest Hook Path', 'Hera 4F Holes']),
|
||||||
create_dungeon_region(player, 'Hera Big Chest Landing', 'Tower of Hera', ['Tower of Hera - Big Chest'], ['Hera Big Chest Landing Exit', 'Hera Big Chest Landing Holes']),
|
create_dungeon_region(player, 'Hera Big Chest Landing', 'Tower of Hera', ['Tower of Hera - Big Chest'], ['Hera Big Chest Landing Exit', 'Hera Big Chest Landing Holes']),
|
||||||
create_dungeon_region(player, 'Hera 5F', 'Tower of Hera', None, ['Hera 5F Down Stairs', 'Hera 5F Up Stairs', 'Hera 5F Star Hole', 'Hera 5F Pothole Chain', 'Hera 5F Normal Holes']),
|
create_dungeon_region(player, 'Hera 5F', 'Tower of Hera', None, ['Hera 5F Down Stairs', 'Hera 5F Up Stairs', 'Hera 5F Star Hole', 'Hera 5F Pothole Chain', 'Hera 5F Normal Holes', 'Hera 5F Orange Path']),
|
||||||
|
create_dungeon_region(player, 'Hera 5F Pot Block', 'Tower of Hera', None),
|
||||||
create_dungeon_region(player, 'Hera Fairies', 'Tower of Hera', None, ['Hera Fairies\' Warp']),
|
create_dungeon_region(player, 'Hera Fairies', 'Tower of Hera', None, ['Hera Fairies\' Warp']),
|
||||||
create_dungeon_region(player, 'Hera Boss', 'Tower of Hera', ['Tower of Hera - Boss', 'Tower of Hera - Prize'], ['Hera Boss Down Stairs', 'Hera Boss Outer Hole', 'Hera Boss Inner Hole']),
|
create_dungeon_region(player, 'Hera Boss', 'Tower of Hera', ['Tower of Hera - Boss', 'Tower of Hera - Prize'], ['Hera Boss Down Stairs', 'Hera Boss Outer Hole', 'Hera Boss Inner Hole']),
|
||||||
|
|
||||||
@@ -456,7 +467,8 @@ def create_dungeon_regions(world, player):
|
|||||||
create_dungeon_region(player, 'Swamp Trench 1 Key Ledge', 'Swamp Palace', None, ['Swamp Trench 1 Key Ledge Dry', 'Swamp Trench 1 Key Approach', 'Swamp Trench 1 Key Ledge Depart', 'Swamp Trench 1 Key Ledge NW']),
|
create_dungeon_region(player, 'Swamp Trench 1 Key Ledge', 'Swamp Palace', None, ['Swamp Trench 1 Key Ledge Dry', 'Swamp Trench 1 Key Approach', 'Swamp Trench 1 Key Ledge Depart', 'Swamp Trench 1 Key Ledge NW']),
|
||||||
create_dungeon_region(player, 'Swamp Trench 1 Departure', 'Swamp Palace', None, ['Swamp Trench 1 Departure Dry', 'Swamp Trench 1 Departure Approach', 'Swamp Trench 1 Departure Key', 'Swamp Trench 1 Departure WS']),
|
create_dungeon_region(player, 'Swamp Trench 1 Departure', 'Swamp Palace', None, ['Swamp Trench 1 Departure Dry', 'Swamp Trench 1 Departure Approach', 'Swamp Trench 1 Departure Key', 'Swamp Trench 1 Departure WS']),
|
||||||
create_dungeon_region(player, 'Swamp Hammer Switch', 'Swamp Palace', ['Trench 1 Switch'], ['Swamp Hammer Switch SW', 'Swamp Hammer Switch WN']),
|
create_dungeon_region(player, 'Swamp Hammer Switch', 'Swamp Palace', ['Trench 1 Switch'], ['Swamp Hammer Switch SW', 'Swamp Hammer Switch WN']),
|
||||||
create_dungeon_region(player, 'Swamp Hub', 'Swamp Palace', ['Swamp Palace - Big Chest', 'Swamp Palace - Hookshot Pot Key'], ['Swamp Hub ES', 'Swamp Hub S', 'Swamp Hub WS', 'Swamp Hub WN', 'Swamp Hub Hook Path']),
|
create_dungeon_region(player, 'Swamp Hub', 'Swamp Palace', ['Swamp Palace - Big Chest'], ['Swamp Hub ES', 'Swamp Hub S', 'Swamp Hub WS', 'Swamp Hub WN', 'Swamp Hub Hook Path', 'Swamp Hub Side Hook Path']),
|
||||||
|
create_dungeon_region(player, 'Swamp Hub Side Ledges', 'Swamp Palace', ['Swamp Palace - Hookshot Pot Key']),
|
||||||
create_dungeon_region(player, 'Swamp Hub Dead Ledge', 'Swamp Palace', None, ['Swamp Hub Dead Ledge EN']),
|
create_dungeon_region(player, 'Swamp Hub Dead Ledge', 'Swamp Palace', None, ['Swamp Hub Dead Ledge EN']),
|
||||||
create_dungeon_region(player, 'Swamp Hub North Ledge', 'Swamp Palace', None, ['Swamp Hub North Ledge N', 'Swamp Hub North Ledge Drop Down']),
|
create_dungeon_region(player, 'Swamp Hub North Ledge', 'Swamp Palace', None, ['Swamp Hub North Ledge N', 'Swamp Hub North Ledge Drop Down']),
|
||||||
create_dungeon_region(player, 'Swamp Donut Top', 'Swamp Palace', None, ['Swamp Donut Top N', 'Swamp Donut Top SE']),
|
create_dungeon_region(player, 'Swamp Donut Top', 'Swamp Palace', None, ['Swamp Donut Top N', 'Swamp Donut Top SE']),
|
||||||
@@ -543,7 +555,8 @@ def create_dungeon_regions(world, player):
|
|||||||
create_dungeon_region(player, 'Thieves Hellway S Crystal', 'Thieves\' Town', None, ['Thieves Hellway Crystal Orange Barrier', 'Thieves Hellway Crystal ES']),
|
create_dungeon_region(player, 'Thieves Hellway S Crystal', 'Thieves\' Town', None, ['Thieves Hellway Crystal Orange Barrier', 'Thieves Hellway Crystal ES']),
|
||||||
create_dungeon_region(player, 'Thieves Triple Bypass', 'Thieves\' Town', None, ['Thieves Triple Bypass WN', 'Thieves Triple Bypass EN', 'Thieves Triple Bypass SE']),
|
create_dungeon_region(player, 'Thieves Triple Bypass', 'Thieves\' Town', None, ['Thieves Triple Bypass WN', 'Thieves Triple Bypass EN', 'Thieves Triple Bypass SE']),
|
||||||
create_dungeon_region(player, 'Thieves Spike Switch', 'Thieves\' Town', ['Thieves\' Town - Spike Switch Pot Key'], ['Thieves Spike Switch SW', 'Thieves Spike Switch Up Stairs']),
|
create_dungeon_region(player, 'Thieves Spike Switch', 'Thieves\' Town', ['Thieves\' Town - Spike Switch Pot Key'], ['Thieves Spike Switch SW', 'Thieves Spike Switch Up Stairs']),
|
||||||
create_dungeon_region(player, 'Thieves Attic', 'Thieves\' Town', None, ['Thieves Attic Down Stairs', 'Thieves Attic ES', 'Thieves Attic Orange Barrier']),
|
create_dungeon_region(player, 'Thieves Attic', 'Thieves\' Town', None, ['Thieves Attic Down Stairs', 'Thieves Attic ES', 'Thieves Attic Orange Barrier', 'Thieves Attic Blue Barrier']),
|
||||||
|
create_dungeon_region(player, 'Thieves Attic Switch', 'Thieves\' Town', None, ['Thieves Attic Switch Blue Barrier']),
|
||||||
create_dungeon_region(player, 'Thieves Attic Hint', 'Thieves\' Town', None, ['Thieves Attic Hint Orange Barrier']),
|
create_dungeon_region(player, 'Thieves Attic Hint', 'Thieves\' Town', None, ['Thieves Attic Hint Orange Barrier']),
|
||||||
create_dungeon_region(player, 'Thieves Cricket Hall Left', 'Thieves\' Town', None, ['Thieves Cricket Hall Left WS', 'Thieves Cricket Hall Left Edge']),
|
create_dungeon_region(player, 'Thieves Cricket Hall Left', 'Thieves\' Town', None, ['Thieves Cricket Hall Left WS', 'Thieves Cricket Hall Left Edge']),
|
||||||
create_dungeon_region(player, 'Thieves Cricket Hall Right', 'Thieves\' Town', None, ['Thieves Cricket Hall Right Edge', 'Thieves Cricket Hall Right ES']),
|
create_dungeon_region(player, 'Thieves Cricket Hall Right', 'Thieves\' Town', None, ['Thieves Cricket Hall Right Edge', 'Thieves Cricket Hall Right ES']),
|
||||||
@@ -718,7 +731,8 @@ def create_dungeon_regions(world, player):
|
|||||||
create_dungeon_region(player, 'TR Crystal Maze Interior', 'Turtle Rock', None, ['TR Crystal Maze Interior to End Barrier - Blue', 'TR Crystal Maze Interior to Start Barrier - Blue', 'TR Crystal Maze Interior to Start Bypass', 'TR Crystal Maze Interior to End Bypass']),
|
create_dungeon_region(player, 'TR Crystal Maze Interior', 'Turtle Rock', None, ['TR Crystal Maze Interior to End Barrier - Blue', 'TR Crystal Maze Interior to Start Barrier - Blue', 'TR Crystal Maze Interior to Start Bypass', 'TR Crystal Maze Interior to End Bypass']),
|
||||||
create_dungeon_region(player, 'TR Crystal Maze End', 'Turtle Rock', None, ['TR Crystal Maze North Stairs', 'TR Crystal Maze End to Interior Barrier - Blue', 'TR Crystal Maze End to Ranged Crystal']),
|
create_dungeon_region(player, 'TR Crystal Maze End', 'Turtle Rock', None, ['TR Crystal Maze North Stairs', 'TR Crystal Maze End to Interior Barrier - Blue', 'TR Crystal Maze End to Ranged Crystal']),
|
||||||
create_dungeon_region(player, 'TR Crystal Maze End - Ranged Crystal', 'Turtle Rock', None, ['TR Crystal Maze End Ranged Crystal Exit']),
|
create_dungeon_region(player, 'TR Crystal Maze End - Ranged Crystal', 'Turtle Rock', None, ['TR Crystal Maze End Ranged Crystal Exit']),
|
||||||
create_dungeon_region(player, 'TR Final Abyss', 'Turtle Rock', None, ['TR Final Abyss South Stairs', 'TR Final Abyss NW']),
|
create_dungeon_region(player, 'TR Final Abyss Balcony', 'Turtle Rock', None, ['TR Final Abyss South Stairs', 'TR Final Abyss Balcony Path']),
|
||||||
|
create_dungeon_region(player, 'TR Final Abyss Ledge', 'Turtle Rock', None, ['TR Final Abyss NW', 'TR Final Abyss Ledge Path']),
|
||||||
create_dungeon_region(player, 'TR Boss', 'Turtle Rock', ['Turtle Rock - Boss', 'Turtle Rock - Prize'], ['TR Boss SW']),
|
create_dungeon_region(player, 'TR Boss', 'Turtle Rock', ['Turtle Rock - Boss', 'Turtle Rock - Prize'], ['TR Boss SW']),
|
||||||
|
|
||||||
# gt
|
# gt
|
||||||
@@ -743,9 +757,10 @@ def create_dungeon_regions(world, player):
|
|||||||
create_dungeon_region(player, 'GT Invisible Bridges', 'Ganon\'s Tower', None, ['GT Invisible Bridges WS']),
|
create_dungeon_region(player, 'GT Invisible Bridges', 'Ganon\'s Tower', None, ['GT Invisible Bridges WS']),
|
||||||
create_dungeon_region(player, 'GT Invisible Catwalk', 'Ganon\'s Tower', None, ['GT Invisible Catwalk ES', 'GT Invisible Catwalk WS', 'GT Invisible Catwalk NW', 'GT Invisible Catwalk NE']),
|
create_dungeon_region(player, 'GT Invisible Catwalk', 'Ganon\'s Tower', None, ['GT Invisible Catwalk ES', 'GT Invisible Catwalk WS', 'GT Invisible Catwalk NW', 'GT Invisible Catwalk NE']),
|
||||||
create_dungeon_region(player, 'GT Conveyor Cross', 'Ganon\'s Tower', ['Ganons Tower - Conveyor Cross Pot Key'], ['GT Conveyor Cross EN', 'GT Conveyor Cross WN']),
|
create_dungeon_region(player, 'GT Conveyor Cross', 'Ganon\'s Tower', ['Ganons Tower - Conveyor Cross Pot Key'], ['GT Conveyor Cross EN', 'GT Conveyor Cross WN']),
|
||||||
create_dungeon_region(player, 'GT Hookshot East Platform', 'Ganon\'s Tower', None, ['GT Hookshot EN', 'GT Hookshot East-North Path', 'GT Hookshot East-South Path']),
|
create_dungeon_region(player, 'GT Hookshot East Platform', 'Ganon\'s Tower', None, ['GT Hookshot EN', 'GT Hookshot East-Mid Path']),
|
||||||
create_dungeon_region(player, 'GT Hookshot North Platform', 'Ganon\'s Tower', None, ['GT Hookshot NW', 'GT Hookshot North-East Path', 'GT Hookshot North-South Path']),
|
create_dungeon_region(player, 'GT Hookshot Mid Platform', 'Ganon\'s Tower', None, ['GT Hookshot Mid-East Path', 'GT Hookshot Mid-South Path', 'GT Hookshot Mid-North Path']),
|
||||||
create_dungeon_region(player, 'GT Hookshot South Platform', 'Ganon\'s Tower', None, ['GT Hookshot ES', 'GT Hookshot South-East Path', 'GT Hookshot South-North Path', 'GT Hookshot Platform Blue Barrier', 'GT Hookshot Platform Barrier Bypass']),
|
create_dungeon_region(player, 'GT Hookshot North Platform', 'Ganon\'s Tower', None, ['GT Hookshot NW', 'GT Hookshot North-Mid Path']),
|
||||||
|
create_dungeon_region(player, 'GT Hookshot South Platform', 'Ganon\'s Tower', None, ['GT Hookshot ES', 'GT Hookshot South-Mid Path', 'GT Hookshot Platform Blue Barrier', 'GT Hookshot Platform Barrier Bypass']),
|
||||||
create_dungeon_region(player, 'GT Hookshot South Entry', 'Ganon\'s Tower', None, ['GT Hookshot SW', 'GT Hookshot Entry Blue Barrier', 'GT Hookshot South Entry to Ranged Crystal']),
|
create_dungeon_region(player, 'GT Hookshot South Entry', 'Ganon\'s Tower', None, ['GT Hookshot SW', 'GT Hookshot Entry Blue Barrier', 'GT Hookshot South Entry to Ranged Crystal']),
|
||||||
create_dungeon_region(player, 'GT Hookshot South Entry - Ranged Crystal', 'Ganon\'s Tower', None, ['GT HookShot South Entry Ranged Crystal Exit']),
|
create_dungeon_region(player, 'GT Hookshot South Entry - Ranged Crystal', 'Ganon\'s Tower', None, ['GT HookShot South Entry Ranged Crystal Exit']),
|
||||||
create_dungeon_region(player, 'GT Map Room', 'Ganon\'s Tower', ['Ganons Tower - Map Chest'], ['GT Map Room WS']),
|
create_dungeon_region(player, 'GT Map Room', 'Ganon\'s Tower', ['Ganons Tower - Map Chest'], ['GT Map Room WS']),
|
||||||
@@ -974,30 +989,54 @@ def create_shops(world, player):
|
|||||||
|
|
||||||
|
|
||||||
def adjust_locations(world, player):
|
def adjust_locations(world, player):
|
||||||
if world.keydropshuffle[player]:
|
# handle pots
|
||||||
for location in key_drop_data.keys():
|
world.pot_contents[player] = PotSecretTable()
|
||||||
|
for location, datum in key_drop_data.items():
|
||||||
loc = world.get_location(location, player)
|
loc = world.get_location(location, player)
|
||||||
|
drop_location = 'Drop' == datum[0]
|
||||||
|
if drop_location:
|
||||||
|
loc.type = LocationType.Drop
|
||||||
|
snes_address, room, sprite_idx = datum[1]
|
||||||
|
loc.address = snes_address
|
||||||
|
else:
|
||||||
|
loc.type = LocationType.Pot
|
||||||
|
pot, pot_index = next((p, i) for i, p in enumerate(vanilla_pots[datum[1]]) if p.item == PotItem.Key)
|
||||||
|
pot = pot.copy()
|
||||||
|
loc.address = pot_address(pot_index, datum[1])
|
||||||
|
loc.pot = pot
|
||||||
|
if (not world.dropshuffle[player] and drop_location)\
|
||||||
|
or (not drop_location and world.pottery[player] == 'none'):
|
||||||
|
loc.skip = True
|
||||||
|
else:
|
||||||
key_item = loc.item
|
key_item = loc.item
|
||||||
key_item.location = None
|
key_item.location = None
|
||||||
|
|
||||||
loc.forced_item = None
|
loc.forced_item = None
|
||||||
loc.item = None
|
loc.item = None
|
||||||
loc.event = False
|
loc.event = False
|
||||||
loc.address = key_drop_data[location][1]
|
item_dungeon = key_item.dungeon
|
||||||
loc.player_address = key_drop_data[location][0]
|
|
||||||
|
|
||||||
item_dungeon = key_item.name.split('(')[1][:-1]
|
|
||||||
item_dungeon = 'Hyrule Castle' if item_dungeon == 'Escape' else item_dungeon
|
|
||||||
dungeon = world.get_dungeon(item_dungeon, player)
|
dungeon = world.get_dungeon(item_dungeon, player)
|
||||||
if key_item.smallkey and not world.retro[player]:
|
if key_item.smallkey and not world.retro[player]:
|
||||||
dungeon.small_keys.append(key_item)
|
dungeon.small_keys.append(key_item)
|
||||||
elif key_item.bigkey:
|
elif key_item.bigkey:
|
||||||
dungeon.big_key = key_item
|
dungeon.big_key = key_item
|
||||||
|
for super_tile, pot_list in vanilla_pots.items():
|
||||||
|
for pot_index, pot_orig in enumerate(pot_list):
|
||||||
|
if pot_orig.item == PotItem.Key:
|
||||||
|
loc = next(location for location, datum in key_drop_data.items() if datum[1] == super_tile)
|
||||||
|
pot = world.get_location(loc, player).pot
|
||||||
|
else:
|
||||||
|
pot = pot_orig.copy()
|
||||||
|
world.pot_contents[player].room_map[super_tile].append(pot)
|
||||||
|
if world.pottery[player] == 'lottery':
|
||||||
|
create_pot_location(pot, pot_index, super_tile, world, player)
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
index = 0
|
index = 0
|
||||||
for shop, location_list in shop_to_location_table.items():
|
for shop, location_list in shop_to_location_table.items():
|
||||||
for location in location_list:
|
for location in location_list:
|
||||||
world.get_location(location, player).address = 0x400000 + index
|
loc = world.get_location(location, player)
|
||||||
|
loc.address = 0x400000 + index
|
||||||
|
loc.type = LocationType.Shop
|
||||||
# player address? it is in the shop table
|
# player address? it is in the shop table
|
||||||
index += 1
|
index += 1
|
||||||
# unreal events:
|
# unreal events:
|
||||||
@@ -1006,9 +1045,34 @@ def adjust_locations(world, player):
|
|||||||
'Revealing Light', 'Ice Block Drop', 'Zelda Pickup', 'Zelda Drop Off']:
|
'Revealing Light', 'Ice Block Drop', 'Zelda Pickup', 'Zelda Drop Off']:
|
||||||
location = world.get_location_unsafe(l, player)
|
location = world.get_location_unsafe(l, player)
|
||||||
if location:
|
if location:
|
||||||
|
location.type = LocationType.Logical
|
||||||
location.real = False
|
location.real = False
|
||||||
|
if l not in ['Ganon', 'Agahnim 1', 'Agahnim 2']:
|
||||||
|
location.skip = True
|
||||||
|
|
||||||
|
|
||||||
|
def create_pot_location(pot, pot_index, super_tile, world, player):
|
||||||
|
if (pot.item not in [PotItem.Key, PotItem.Hole]
|
||||||
|
and (pot.item != PotItem.Switch or world.potshuffle[player])):
|
||||||
|
address = pot_address(pot_index, super_tile)
|
||||||
|
parent = world.get_region(pot.room, player)
|
||||||
|
descriptor = 'Large Block' if pot.flags & PotFlags.Block else f'Pot #{pot_index+1}'
|
||||||
|
hint_text = ('under a block' if pot.flags & PotFlags.Block else 'in a pot')
|
||||||
|
modifier = parent.hint_text not in {'a storyteller', 'fairies deep in a cave', 'a spiky hint',
|
||||||
|
'a bounty of five items', 'the sick kid', 'Sahasrahla'}
|
||||||
|
hint_text = f'{hint_text} {"in" if modifier else "near"} {parent.hint_text}'
|
||||||
|
pot_location = Location(player, f'{pot.room} {descriptor}', address, hint_text=hint_text,
|
||||||
|
parent=parent)
|
||||||
|
world.dynamic_locations.append(pot_location)
|
||||||
|
pot_location.pot = pot
|
||||||
|
|
||||||
|
pot_location.type = LocationType.Pot
|
||||||
|
parent.locations.append(pot_location)
|
||||||
|
|
||||||
|
|
||||||
|
def pot_address(pot_index, super_tile):
|
||||||
|
return 0x7f6600 + super_tile * 2 + (pot_index << 24)
|
||||||
|
|
||||||
|
|
||||||
# (type, room_id, shopkeeper, custom, locked, [items])
|
# (type, room_id, shopkeeper, custom, locked, [items])
|
||||||
# item = (item, price, max=0, replacement=None, replacement_price=0)
|
# item = (item, price, max=0, replacement=None, replacement_price=0)
|
||||||
@@ -1060,42 +1124,6 @@ shop_table_by_location_id = {0x400000+cnt: x for cnt, x in enumerate(flat_normal
|
|||||||
shop_table_by_location_id = {**shop_table_by_location_id, **{0x400020+cnt: x for cnt, x in enumerate(flat_retro_shops)}}
|
shop_table_by_location_id = {**shop_table_by_location_id, **{0x400020+cnt: x for cnt, x in enumerate(flat_retro_shops)}}
|
||||||
shop_table_by_location = {y: x for x, y in shop_table_by_location_id.items()}
|
shop_table_by_location = {y: x for x, y in shop_table_by_location_id.items()}
|
||||||
|
|
||||||
key_drop_data = {
|
|
||||||
'Hyrule Castle - Map Guard Key Drop': [0x140036, 0x140037, 'in Hyrule Castle', 'Small Key (Escape)'],
|
|
||||||
'Hyrule Castle - Boomerang Guard Key Drop': [0x140033, 0x140034, 'in Hyrule Castle', 'Small Key (Escape)'],
|
|
||||||
'Hyrule Castle - Key Rat Key Drop': [0x14000c, 0x14000d, 'in Hyrule Castle', 'Small Key (Escape)'],
|
|
||||||
'Hyrule Castle - Big Key Drop': [0x14003c, 0x14003d, 'in Hyrule Castle', 'Big Key (Escape)'],
|
|
||||||
'Eastern Palace - Dark Square Pot Key': [0x14005a, 0x14005b, 'in Eastern Palace', 'Small Key (Eastern Palace)'],
|
|
||||||
'Eastern Palace - Dark Eyegore Key Drop': [0x140048, 0x140049, 'in Eastern Palace', 'Small Key (Eastern Palace)'],
|
|
||||||
'Desert Palace - Desert Tiles 1 Pot Key': [0x140030, 0x140031, 'in Desert Palace', 'Small Key (Desert Palace)'],
|
|
||||||
'Desert Palace - Beamos Hall Pot Key': [0x14002a, 0x14002b, 'in Desert Palace', 'Small Key (Desert Palace)'],
|
|
||||||
'Desert Palace - Desert Tiles 2 Pot Key': [0x140027, 0x140028, 'in Desert Palace', 'Small Key (Desert Palace)'],
|
|
||||||
'Castle Tower - Dark Archer Key Drop': [0x140060, 0x140061, 'in Castle Tower', 'Small Key (Agahnims Tower)'],
|
|
||||||
'Castle Tower - Circle of Pots Key Drop': [0x140051, 0x140052, 'in Castle Tower', 'Small Key (Agahnims Tower)'],
|
|
||||||
'Swamp Palace - Pot Row Pot Key': [0x140018, 0x140019, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
|
|
||||||
'Swamp Palace - Trench 1 Pot Key': [0x140015, 0x140016, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
|
|
||||||
'Swamp Palace - Hookshot Pot Key': [0x140012, 0x140013, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
|
|
||||||
'Swamp Palace - Trench 2 Pot Key': [0x14000f, 0x140010, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
|
|
||||||
'Swamp Palace - Waterway Pot Key': [0x140009, 0x14000a, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
|
|
||||||
'Skull Woods - West Lobby Pot Key': [0x14002d, 0x14002e, 'in Skull Woods', 'Small Key (Skull Woods)'],
|
|
||||||
'Skull Woods - Spike Corner Key Drop': [0x14001b, 0x14001c, 'near Mothula', 'Small Key (Skull Woods)'],
|
|
||||||
"Thieves' Town - Hallway Pot Key": [0x14005d, 0x14005e, "in Thieves' Town", 'Small Key (Thieves Town)'],
|
|
||||||
"Thieves' Town - Spike Switch Pot Key": [0x14004e, 0x14004f, "in Thieves' Town", 'Small Key (Thieves Town)'],
|
|
||||||
'Ice Palace - Jelly Key Drop': [0x140003, 0x140004, 'in Ice Palace', 'Small Key (Ice Palace)'],
|
|
||||||
'Ice Palace - Conveyor Key Drop': [0x140021, 0x140022, 'in Ice Palace', 'Small Key (Ice Palace)'],
|
|
||||||
'Ice Palace - Hammer Block Key Drop': [0x140024, 0x140025, 'in Ice Palace', 'Small Key (Ice Palace)'],
|
|
||||||
'Ice Palace - Many Pots Pot Key': [0x140045, 0x140046, 'in Ice Palace', 'Small Key (Ice Palace)'],
|
|
||||||
'Misery Mire - Spikes Pot Key': [0x140054, 0x140055 , 'in Misery Mire', 'Small Key (Misery Mire)'],
|
|
||||||
'Misery Mire - Fishbone Pot Key': [0x14004b, 0x14004c, 'in forgotten Mire', 'Small Key (Misery Mire)'],
|
|
||||||
'Misery Mire - Conveyor Crystal Key Drop': [0x140063, 0x140064 , 'in Misery Mire', 'Small Key (Misery Mire)'],
|
|
||||||
'Turtle Rock - Pokey 1 Key Drop': [0x140057, 0x140058, 'in Turtle Rock', 'Small Key (Turtle Rock)'],
|
|
||||||
'Turtle Rock - Pokey 2 Key Drop': [0x140006, 0x140007, 'in Turtle Rock', 'Small Key (Turtle Rock)'],
|
|
||||||
'Ganons Tower - Conveyor Cross Pot Key': [0x14003f, 0x140040, "in Ganon's Tower", 'Small Key (Ganons Tower)'],
|
|
||||||
'Ganons Tower - Double Switch Pot Key': [0x140042, 0x140043, "in Ganon's Tower", 'Small Key (Ganons Tower)'],
|
|
||||||
'Ganons Tower - Conveyor Star Pits Pot Key': [0x140039, 0x14003a, "in Ganon's Tower", 'Small Key (Ganons Tower)'],
|
|
||||||
'Ganons Tower - Mini Helmasaur Key Drop': [0x14001e, 0x14001f, "atop Ganon's Tower", 'Small Key (Ganons Tower)']
|
|
||||||
}
|
|
||||||
|
|
||||||
dungeon_events = [
|
dungeon_events = [
|
||||||
'Trench 1 Switch',
|
'Trench 1 Switch',
|
||||||
'Trench 2 Switch',
|
'Trench 2 Switch',
|
||||||
@@ -1389,8 +1417,6 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int}
|
lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int}
|
||||||
lookup_id_to_name = {**lookup_id_to_name, **{data[1]: name for name, data in key_drop_data.items()}}
|
|
||||||
lookup_id_to_name.update(shop_table_by_location_id)
|
lookup_id_to_name.update(shop_table_by_location_id)
|
||||||
lookup_name_to_id = {name: data[0] for name, data in location_table.items() if type(data[0]) == int}
|
lookup_name_to_id = {name: data[0] for name, data in location_table.items() if type(data[0]) == int}
|
||||||
lookup_name_to_id = {**lookup_name_to_id, **{name: data[1] for name, data in key_drop_data.items()}}
|
|
||||||
lookup_name_to_id.update(shop_table_by_location)
|
lookup_name_to_id.update(shop_table_by_location)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import bisect
|
import bisect
|
||||||
|
import collections
|
||||||
import io
|
import io
|
||||||
import itertools
|
|
||||||
import json
|
import json
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
@@ -15,7 +15,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
raise Exception('Could not load BPS module')
|
raise Exception('Could not load BPS module')
|
||||||
|
|
||||||
from BaseClasses import CollectionState, ShopType, Region, Location, Door, DoorType, RegionType, PotItem
|
from BaseClasses import CollectionState, ShopType, Region, Location, Door, DoorType, RegionType, PotItem, LocationType
|
||||||
from DoorShuffle import compass_data, DROptions, boss_indicator, dungeon_portals
|
from DoorShuffle import compass_data, DROptions, boss_indicator, dungeon_portals
|
||||||
from Dungeons import dungeon_music_addresses, dungeon_table
|
from Dungeons import dungeon_music_addresses, dungeon_table
|
||||||
from Regions import location_table, shop_to_location_table, retro_shops
|
from Regions import location_table, shop_to_location_table, retro_shops
|
||||||
@@ -23,16 +23,19 @@ from RoomData import DoorKind
|
|||||||
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
|
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
|
||||||
from Text import Uncle_texts, Ganon1_texts, Ganon_Phase_3_No_Silvers_texts, TavernMan_texts, Sahasrahla2_texts
|
from Text import Uncle_texts, Ganon1_texts, Ganon_Phase_3_No_Silvers_texts, TavernMan_texts, Sahasrahla2_texts
|
||||||
from Text import Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
|
from Text import Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
|
||||||
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
|
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts
|
||||||
|
from Text import LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts
|
||||||
|
from Text import Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
|
||||||
from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc
|
from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from EntranceShuffle import door_addresses, exit_ids, ow_prize_table
|
from EntranceShuffle import door_addresses, exit_ids, ow_prize_table
|
||||||
|
|
||||||
from source.classes.SFX import randomize_sfx
|
from source.classes.SFX import randomize_sfx
|
||||||
|
from source.item.FillUtil import valid_pot_items
|
||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '4e4d7c1352c6b85dfe0d3f19aa2afae2'
|
RANDOMIZERBASEHASH = 'dea3a3bc1435aa0895181c5d46dc6d43'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -548,6 +551,21 @@ class Sprite(object):
|
|||||||
return array_chunk(palette_as_colors, 15)
|
return array_chunk(palette_as_colors, 15)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_native_dungeon(location, itemid):
|
||||||
|
# Keys in their native dungeon should use the original item code for keys
|
||||||
|
if location.parent_region.dungeon:
|
||||||
|
if location.parent_region.dungeon.name == location.item.dungeon:
|
||||||
|
if location.item.bigkey:
|
||||||
|
return 0x32
|
||||||
|
if location.item.smallkey:
|
||||||
|
return 0x24
|
||||||
|
if location.item.map:
|
||||||
|
return 0x33
|
||||||
|
if location.item.compass:
|
||||||
|
return 0x25
|
||||||
|
return itemid
|
||||||
|
|
||||||
|
|
||||||
def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||||
random.seed(world.rom_seeds[player])
|
random.seed(world.rom_seeds[player])
|
||||||
|
|
||||||
@@ -559,28 +577,47 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
distinguished_prog_bow_loc.item.code = 0x65
|
distinguished_prog_bow_loc.item.code = 0x65
|
||||||
|
|
||||||
# patch items
|
# patch items
|
||||||
|
pot_mw_index = 0
|
||||||
for location in world.get_locations():
|
for location in world.get_locations():
|
||||||
if location.player != player:
|
if location.player != player:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
itemid = location.item.code if location.item is not None else 0x5A
|
itemid = location.item.code if location.item is not None else 0x5A
|
||||||
|
if location.type == LocationType.Pot:
|
||||||
|
if location.item.name in valid_pot_items and location.item.player == player:
|
||||||
|
location.pot.item = valid_pot_items[location.item.name]
|
||||||
|
location.forced_item = True
|
||||||
|
else:
|
||||||
|
code = handle_native_dungeon(location, itemid)
|
||||||
|
standing_item_flag = 0x80
|
||||||
|
if location.item.player != player:
|
||||||
|
standing_item_flag |= 0x40
|
||||||
|
rom.write_byte(0x142800 + pot_mw_index * 2, code)
|
||||||
|
rom.write_byte(0x142800 + pot_mw_index * 2 + 1, location.item.player)
|
||||||
|
code = pot_mw_index
|
||||||
|
pot_mw_index += 1
|
||||||
|
location.pot.indicator = standing_item_flag
|
||||||
|
location.pot.standing_item_code = code
|
||||||
|
continue
|
||||||
|
elif location.type == LocationType.Drop:
|
||||||
|
if location.item.player != player:
|
||||||
|
code = 0xF9
|
||||||
|
else:
|
||||||
|
code = 0xF8
|
||||||
|
sprite_pointer = snes_to_pc(location.address)
|
||||||
|
rom.write_byte(sprite_pointer, handle_native_dungeon(location, itemid))
|
||||||
|
if code == 0xF9:
|
||||||
|
rom.write_byte(sprite_pointer+1, location.item.player)
|
||||||
|
else:
|
||||||
|
rom.write_byte(sprite_pointer+1, 0)
|
||||||
|
rom.write_byte(sprite_pointer+2, code)
|
||||||
|
continue
|
||||||
if location.address is None or (type(location.address) is int and location.address >= 0x400000):
|
if location.address is None or (type(location.address) is int and location.address >= 0x400000):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not location.crystal:
|
if not location.crystal:
|
||||||
if location.item is not None:
|
if location.item is not None:
|
||||||
# Keys in their native dungeon should use the original item code for keys
|
# Keys in their native dungeon should use the original item code for keys
|
||||||
if location.parent_region.dungeon:
|
itemid = handle_native_dungeon(location, itemid)
|
||||||
if location.parent_region.dungeon.is_dungeon_item(location.item):
|
|
||||||
if location.item.bigkey:
|
|
||||||
itemid = 0x32
|
|
||||||
if location.item.smallkey:
|
|
||||||
itemid = 0x24
|
|
||||||
if location.item.map:
|
|
||||||
itemid = 0x33
|
|
||||||
if location.item.compass:
|
|
||||||
itemid = 0x25
|
|
||||||
if world.remote_items[player]:
|
if world.remote_items[player]:
|
||||||
itemid = list(location_table.keys()).index(location.name) + 1
|
itemid = list(location_table.keys()).index(location.name) + 1
|
||||||
assert itemid < 0x100
|
assert itemid < 0x100
|
||||||
@@ -609,7 +646,16 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x155C9, random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle
|
rom.write_byte(0x155C9, random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle
|
||||||
|
|
||||||
if world.pot_contents[player]:
|
if world.pot_contents[player]:
|
||||||
write_pots_to_rom(rom, world.pot_contents[player])
|
if world.pot_contents[player].size() > 0x2800:
|
||||||
|
raise Exception('Pot table is too big for current area')
|
||||||
|
world.pot_contents[player].write_pot_data_to_rom(rom)
|
||||||
|
# fix for swamp drains if necessary
|
||||||
|
swamp1location = world.get_location('Swamp Palace - Trench 1 Pot Key', player)
|
||||||
|
if not swamp1location.pot.indicator:
|
||||||
|
rom.write_byte(0x142A53, 0)
|
||||||
|
swamp2location = world.get_location('Swamp Palace - Trench 2 Pot Key', player)
|
||||||
|
if not swamp2location.pot.indicator:
|
||||||
|
rom.write_byte(0x142A54, 0)
|
||||||
|
|
||||||
# patch entrance/exits/holes
|
# patch entrance/exits/holes
|
||||||
for region in world.regions:
|
for region in world.regions:
|
||||||
@@ -692,14 +738,20 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
if world.logic[player] != 'nologic':
|
if world.logic[player] != 'nologic':
|
||||||
dr_flags |= DROptions.Fix_EG
|
dr_flags |= DROptions.Fix_EG
|
||||||
|
|
||||||
|
my_locations = world.get_filled_locations(player)
|
||||||
|
valid_locations = [l for l in my_locations if ((l.type == LocationType.Pot and not l.forced_item)
|
||||||
|
or (l.type == LocationType.Drop and not l.forced_item)
|
||||||
|
or (l.type == LocationType.Normal and not l.forced_item)
|
||||||
|
or (l.type == LocationType.Shop and world.shopsanity[player]))]
|
||||||
|
valid_loc_by_dungeon = valid_dungeon_locations(valid_locations)
|
||||||
|
|
||||||
# fix hc big key problems (map and compass too)
|
# fix hc big key problems (map and compass too)
|
||||||
if world.doorShuffle[player] == 'crossed' or world.keydropshuffle[player]:
|
if world.doorShuffle[player] == 'crossed' or world.dropshuffle[player]:
|
||||||
rom.write_byte(0x151f1, 2)
|
rom.write_byte(0x151f1, 2)
|
||||||
rom.write_byte(0x15270, 2)
|
rom.write_byte(0x15270, 2)
|
||||||
sanctuary = world.get_region('Sanctuary', player)
|
sanctuary = world.get_region('Sanctuary', player)
|
||||||
rom.write_byte(0x1597b, sanctuary.dungeon.dungeon_id*2)
|
rom.write_byte(0x1597b, sanctuary.dungeon.dungeon_id*2)
|
||||||
update_compasses(rom, world, player)
|
update_compasses(rom, valid_loc_by_dungeon, world, player)
|
||||||
|
|
||||||
def should_be_bunny(region, mode):
|
def should_be_bunny(region, mode):
|
||||||
if mode != 'inverted':
|
if mode != 'inverted':
|
||||||
@@ -732,9 +784,12 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x13f020+offset, layout.max_chests + layout.max_drops) # not currently used
|
rom.write_byte(0x13f020+offset, layout.max_chests + layout.max_drops) # not currently used
|
||||||
rom.write_byte(0x13f030+offset, layout.max_chests)
|
rom.write_byte(0x13f030+offset, layout.max_chests)
|
||||||
builder = world.dungeon_layouts[player][name]
|
builder = world.dungeon_layouts[player][name]
|
||||||
rom.write_byte(0x13f080+offset, builder.location_cnt % 10)
|
valid_cnt = len(valid_loc_by_dungeon[name])
|
||||||
rom.write_byte(0x13f090+offset, builder.location_cnt // 10)
|
if valid_cnt > 99:
|
||||||
rom.write_byte(0x13f0a0+offset, builder.location_cnt)
|
logging.getLogger('').warning(f'{name} exceeds 99 in locations ({valid_cnt})')
|
||||||
|
rom.write_byte(0x13f080+offset, valid_cnt % 10)
|
||||||
|
rom.write_byte(0x13f090+offset, valid_cnt // 10)
|
||||||
|
rom.write_byte(0x13f0a0+offset, valid_cnt)
|
||||||
bk_status = 1 if builder.bk_required else 0
|
bk_status = 1 if builder.bk_required else 0
|
||||||
bk_status = 2 if builder.bk_provided else bk_status
|
bk_status = 2 if builder.bk_provided else bk_status
|
||||||
rom.write_byte(0x13f040+offset*2, bk_status)
|
rom.write_byte(0x13f040+offset*2, bk_status)
|
||||||
@@ -817,31 +872,31 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
# bot: $7A is 1, 7B is 2, etc so 7D=4, 82=9 (zero unknown...)
|
# bot: $7A is 1, 7B is 2, etc so 7D=4, 82=9 (zero unknown...)
|
||||||
return 0x53+int(num), 0x79+int(num)
|
return 0x53+int(num), 0x79+int(num)
|
||||||
|
|
||||||
credits_total = 216
|
credits_total = len(valid_locations)
|
||||||
if world.keydropshuffle[player]:
|
|
||||||
credits_total += 33
|
|
||||||
if world.shopsanity[player]:
|
|
||||||
credits_total += 32
|
|
||||||
if world.retro[player]:
|
|
||||||
credits_total += 9 if world.shopsanity[player] else 5
|
|
||||||
|
|
||||||
if world.keydropshuffle[player]:
|
if world.dropshuffle[player] or world.pottery[player] != 'none':
|
||||||
rom.write_byte(0x140000, 1)
|
rom.write_byte(0x142A50, 1)
|
||||||
multiClientFlags = ((0x1 if world.keydropshuffle[player] else 0) | (0x2 if world.shopsanity[player] else 0)
|
multiClientFlags = ((0x1 if world.dropshuffle[player] else 0)
|
||||||
| (0x4 if world.retro[player] else 0))
|
| (0x2 if world.shopsanity[player] else 0)
|
||||||
rom.write_byte(0x140001, multiClientFlags)
|
| (0x4 if world.retro[player] else 0)
|
||||||
|
| (0x8 if world.pottery[player] in ['keys', 'lottery'] else 0)
|
||||||
|
| (0x10 if is_mystery else 0))
|
||||||
|
rom.write_byte(0x142A51, multiClientFlags)
|
||||||
|
|
||||||
write_int16(rom, 0x187010, credits_total) # dynamic credits
|
write_int16(rom, 0x187010, credits_total) # dynamic credits
|
||||||
if credits_total != 216:
|
if credits_total != 216:
|
||||||
# collection rate address (hi):
|
# collection rate address (hi):
|
||||||
cr_address = 0x238057
|
cr_address = 0x238057
|
||||||
cr_pc = cr_address - 0x120000 # convert to pc
|
cr_pc = cr_address - 0x120000 # convert to pc
|
||||||
|
first_top, first_bot = credits_digit((credits_total // 100) % 10)
|
||||||
mid_top, mid_bot = credits_digit((credits_total // 10) % 10)
|
mid_top, mid_bot = credits_digit((credits_total // 10) % 10)
|
||||||
last_top, last_bot = credits_digit(credits_total % 10)
|
last_top, last_bot = credits_digit(credits_total % 10)
|
||||||
# top half
|
# top half
|
||||||
|
rom.write_byte(cr_pc, first_top)
|
||||||
rom.write_byte(cr_pc+0x1, mid_top)
|
rom.write_byte(cr_pc+0x1, mid_top)
|
||||||
rom.write_byte(cr_pc+0x2, last_top)
|
rom.write_byte(cr_pc+0x2, last_top)
|
||||||
# bottom half
|
# bottom half
|
||||||
|
rom.write_byte(cr_pc+0x1e, first_bot)
|
||||||
rom.write_byte(cr_pc+0x1f, mid_bot)
|
rom.write_byte(cr_pc+0x1f, mid_bot)
|
||||||
rom.write_byte(cr_pc+0x20, last_bot)
|
rom.write_byte(cr_pc+0x20, last_bot)
|
||||||
|
|
||||||
@@ -1154,7 +1209,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
|
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
|
||||||
|
|
||||||
gametype = 0x04 # item
|
gametype = 0x04 # item
|
||||||
if world.shuffle[player] != 'vanilla' or world.doorShuffle[player] != 'vanilla' or world.keydropshuffle[player]:
|
if (world.shuffle[player] != 'vanilla' or world.doorShuffle[player] != 'vanilla' or world.dropshuffle[player]
|
||||||
|
or world.pottery[player] != 'none'):
|
||||||
gametype |= 0x02 # entrance/door
|
gametype |= 0x02 # entrance/door
|
||||||
if enemized:
|
if enemized:
|
||||||
gametype |= 0x01 # enemizer
|
gametype |= 0x01 # enemizer
|
||||||
@@ -1404,7 +1460,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x18003C, 0x00)
|
rom.write_byte(0x18003C, 0x00)
|
||||||
elif world.dungeon_counters[player] == 'on':
|
elif world.dungeon_counters[player] == 'on':
|
||||||
compass_mode = 0x02 # always on
|
compass_mode = 0x02 # always on
|
||||||
elif world.compassshuffle[player] or world.doorShuffle[player] != 'vanilla' or world.dungeon_counters[player] == 'pickup':
|
elif (world.compassshuffle[player] or world.doorShuffle[player] != 'vanilla' or world.dropshuffle[player]
|
||||||
|
or world.dungeon_counters[player] == 'pickup' or world.pottery[player] != 'none'):
|
||||||
compass_mode = 0x01 # show on pickup
|
compass_mode = 0x01 # show on pickup
|
||||||
if world.shuffle[player] != 'vanilla' and world.overworld_map[player] != 'default':
|
if world.shuffle[player] != 'vanilla' and world.overworld_map[player] != 'default':
|
||||||
compass_mode |= 0x80 # turn on locating dungeons
|
compass_mode |= 0x80 # turn on locating dungeons
|
||||||
@@ -1579,7 +1636,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0xFED31, 0x0E) # preopen bombable exit
|
rom.write_byte(0xFED31, 0x0E) # preopen bombable exit
|
||||||
rom.write_byte(0xFEE41, 0x0E) # preopen bombable exit
|
rom.write_byte(0xFEE41, 0x0E) # preopen bombable exit
|
||||||
|
|
||||||
if world.doorShuffle[player] != 'vanilla' or world.keydropshuffle[player]:
|
if (world.doorShuffle[player] != 'vanilla' or world.dropshuffle[player]
|
||||||
|
or world.pottery[player] != 'none'):
|
||||||
for room in world.rooms:
|
for room in world.rooms:
|
||||||
if room.player == player and room.modified:
|
if room.player == player and room.modified:
|
||||||
rom.write_bytes(room.address(), room.rom_data())
|
rom.write_bytes(room.address(), room.rom_data())
|
||||||
@@ -2579,12 +2637,20 @@ def patch_shuffled_dark_sanc(world, rom, player):
|
|||||||
rom.write_bytes(0x180262, [unknown_1, unknown_2, 0x00])
|
rom.write_bytes(0x180262, [unknown_1, unknown_2, 0x00])
|
||||||
|
|
||||||
|
|
||||||
def update_compasses(rom, world, player):
|
def valid_dungeon_locations(valid_locations):
|
||||||
|
dungeon_locations = collections.defaultdict(set)
|
||||||
|
for l in valid_locations:
|
||||||
|
if l.parent_region.dungeon:
|
||||||
|
dungeon_locations[l.parent_region.dungeon.name].add(l)
|
||||||
|
return dungeon_locations
|
||||||
|
|
||||||
|
|
||||||
|
def update_compasses(rom, dungeon_locations, world, player):
|
||||||
layouts = world.dungeon_layouts[player]
|
layouts = world.dungeon_layouts[player]
|
||||||
provided_dungeon = False
|
provided_dungeon = False
|
||||||
for name, builder in layouts.items():
|
for name, builder in layouts.items():
|
||||||
dungeon_id = compass_data[name][4]
|
dungeon_id = compass_data[name][4]
|
||||||
rom.write_byte(0x187000 + dungeon_id//2, builder.location_cnt)
|
rom.write_byte(0x187000 + dungeon_id//2, len(dungeon_locations[name]))
|
||||||
if builder.bk_provided:
|
if builder.bk_provided:
|
||||||
if provided_dungeon:
|
if provided_dungeon:
|
||||||
logging.getLogger('').warning('Multiple dungeons have forced BKs! Compass code might need updating?')
|
logging.getLogger('').warning('Multiple dungeons have forced BKs! Compass code might need updating?')
|
||||||
@@ -2853,29 +2919,3 @@ hash_alphabet = [
|
|||||||
"Lamp", "Hammer", "Shovel", "Ocarina", "Bug Net", "Book", "Bottle", "Potion", "Cane", "Cape", "Mirror", "Boots",
|
"Lamp", "Hammer", "Shovel", "Ocarina", "Bug Net", "Book", "Bottle", "Potion", "Cane", "Cape", "Mirror", "Boots",
|
||||||
"Gloves", "Flippers", "Pearl", "Shield", "Tunic", "Heart", "Map", "Compass", "Key"
|
"Gloves", "Flippers", "Pearl", "Shield", "Tunic", "Heart", "Map", "Compass", "Key"
|
||||||
]
|
]
|
||||||
|
|
||||||
pot_item_room_table_lookup = 0xDB67
|
|
||||||
|
|
||||||
###
|
|
||||||
# Pointer to pot location and contents for each non-empty pot in a supertile
|
|
||||||
# Format: [(x, y, item)] FF FF (Note: x,y are bit packed to include layer)
|
|
||||||
pot_item_table = 0xDDE7
|
|
||||||
pot_item_table_end = 0xE6B0
|
|
||||||
|
|
||||||
def write_pots_to_rom(rom, pot_contents):
|
|
||||||
n = pot_item_table
|
|
||||||
rom.write_bytes(n, [0xFF,0xFF])
|
|
||||||
n += 2
|
|
||||||
for i in range(0x140):
|
|
||||||
if i in pot_contents:
|
|
||||||
pots = [pot for pot in pot_contents[i] if pot.item != PotItem.Nothing]
|
|
||||||
if len(pots) > 0:
|
|
||||||
write_int16(rom, pot_item_room_table_lookup + 2*i, n)
|
|
||||||
rom.write_bytes(n, list(itertools.chain.from_iterable(((pot.x, pot.y, pot.item) for pot in pots))))
|
|
||||||
n += 3*len(pots) + 2
|
|
||||||
rom.write_bytes(n - 2, [0xFF,0xFF])
|
|
||||||
else:
|
|
||||||
write_int16(rom, pot_item_room_table_lookup + 2*i, n-2)
|
|
||||||
else:
|
|
||||||
write_int16(rom, pot_item_room_table_lookup + 2*i, n-2)
|
|
||||||
assert n <= pot_item_table_end
|
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import logging
|
|||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
import OverworldGlitchRules
|
import OverworldGlitchRules
|
||||||
from BaseClasses import CollectionState, RegionType, DoorType, Entrance, CrystalBarrier, KeyRuleType
|
from BaseClasses import CollectionState, RegionType, DoorType, Entrance, CrystalBarrier, KeyRuleType, LocationType
|
||||||
|
from BaseClasses import PotFlags
|
||||||
from Dungeons import dungeon_table
|
from Dungeons import dungeon_table
|
||||||
from RoomData import DoorKind
|
from RoomData import DoorKind
|
||||||
from OverworldGlitchRules import overworld_glitches_rules
|
from OverworldGlitchRules import overworld_glitches_rules
|
||||||
@@ -33,6 +34,7 @@ def set_rules(world, player):
|
|||||||
raise NotImplementedError('Not implemented yet')
|
raise NotImplementedError('Not implemented yet')
|
||||||
|
|
||||||
bomb_rules(world, player)
|
bomb_rules(world, player)
|
||||||
|
pot_rules(world, player)
|
||||||
|
|
||||||
if world.logic[player] == 'noglitches':
|
if world.logic[player] == 'noglitches':
|
||||||
no_glitches_rules(world, player)
|
no_glitches_rules(world, player)
|
||||||
@@ -180,6 +182,9 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_location('Hookshot Cave - Bottom Right', player), lambda state: state.has('Hookshot', player) or state.has('Pegasus Boots', player))
|
set_rule(world.get_location('Hookshot Cave - Bottom Right', player), lambda state: state.has('Hookshot', player) or state.has('Pegasus Boots', player))
|
||||||
set_rule(world.get_location('Hookshot Cave - Bottom Left', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_location('Hookshot Cave - Bottom Left', player), lambda state: state.has('Hookshot', player))
|
||||||
|
|
||||||
|
set_rule(world.get_entrance('Hookshot Cave Bonk Path', player), lambda state: state.has('Hookshot', player) or state.has('Pegasus Boots', player))
|
||||||
|
set_rule(world.get_entrance('Hookshot Cave Hook Path', player), lambda state: state.has('Hookshot', player))
|
||||||
|
|
||||||
# Start of door rando rules
|
# Start of door rando rules
|
||||||
# TODO: Do these need to flag off when door rando is off? - some of them, yes
|
# TODO: Do these need to flag off when door rando is off? - some of them, yes
|
||||||
|
|
||||||
@@ -244,6 +249,7 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_entrance('Swamp Trench 1 Departure Key', player), lambda state: state.has('Flippers', player) and state.has('Trench 1 Filled', player))
|
set_rule(world.get_entrance('Swamp Trench 1 Departure Key', player), lambda state: state.has('Flippers', player) and state.has('Trench 1 Filled', player))
|
||||||
set_rule(world.get_location('Trench 1 Switch', player), lambda state: state.has('Hammer', player))
|
set_rule(world.get_location('Trench 1 Switch', player), lambda state: state.has('Hammer', player))
|
||||||
set_rule(world.get_entrance('Swamp Hub Hook Path', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('Swamp Hub Hook Path', player), lambda state: state.has('Hookshot', player))
|
||||||
|
set_rule(world.get_entrance('Swamp Hub Side Hook Path', player), lambda state: state.has('Hookshot', player))
|
||||||
set_rule(world.get_location('Swamp Palace - Hookshot Pot Key', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_location('Swamp Palace - Hookshot Pot Key', player), lambda state: state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('Swamp Trench 2 Pots Dry', player), lambda state: not state.has('Trench 2 Filled', player))
|
set_rule(world.get_entrance('Swamp Trench 2 Pots Dry', player), lambda state: not state.has('Trench 2 Filled', player))
|
||||||
set_rule(world.get_entrance('Swamp Trench 2 Pots Wet', player), lambda state: state.has('Flippers', player) and state.has('Trench 2 Filled', player))
|
set_rule(world.get_entrance('Swamp Trench 2 Pots Wet', player), lambda state: state.has('Flippers', player) and state.has('Trench 2 Filled', player))
|
||||||
@@ -280,8 +286,8 @@ def global_rules(world, player):
|
|||||||
# for location in ['Thieves\' Town - Blind\'s Cell', 'Thieves\' Town - Boss']:
|
# for location in ['Thieves\' Town - Blind\'s Cell', 'Thieves\' Town - Boss']:
|
||||||
# forbid_item(world.get_location(location, player), 'Big Key (Thieves Town)', player)
|
# forbid_item(world.get_location(location, player), 'Big Key (Thieves Town)', player)
|
||||||
# forbid_item(world.get_location('Thieves\' Town - Blind\'s Cell', player), 'Big Key (Thieves Town)', player)
|
# forbid_item(world.get_location('Thieves\' Town - Blind\'s Cell', player), 'Big Key (Thieves Town)', player)
|
||||||
for location in ['Suspicious Maiden', 'Thieves\' Town - Blind\'s Cell']:
|
# for location in ['Suspicious Maiden', 'Thieves\' Town - Blind\'s Cell']:
|
||||||
set_rule(world.get_location(location, player), lambda state: state.has('Big Key (Thieves Town)', player))
|
# set_rule(world.get_location(location, player), lambda state: state.has('Big Key (Thieves Town)', player))
|
||||||
set_rule(world.get_location('Revealing Light', player), lambda state: state.has('Shining Light', player) and state.has('Maiden Rescued', player))
|
set_rule(world.get_location('Revealing Light', player), lambda state: state.has('Shining Light', player) and state.has('Maiden Rescued', player))
|
||||||
set_rule(world.get_location('Thieves\' Town - Boss', player), lambda state: state.has('Maiden Unmasked', player) and world.get_location('Thieves\' Town - Boss', player).parent_region.dungeon.boss.can_defeat(state))
|
set_rule(world.get_location('Thieves\' Town - Boss', player), lambda state: state.has('Maiden Unmasked', player) and world.get_location('Thieves\' Town - Boss', player).parent_region.dungeon.boss.can_defeat(state))
|
||||||
set_rule(world.get_location('Thieves\' Town - Prize', player), lambda state: state.has('Maiden Unmasked', player) and world.get_location('Thieves\' Town - Prize', player).parent_region.dungeon.boss.can_defeat(state))
|
set_rule(world.get_location('Thieves\' Town - Prize', player), lambda state: state.has('Maiden Unmasked', player) and world.get_location('Thieves\' Town - Prize', player).parent_region.dungeon.boss.can_defeat(state))
|
||||||
@@ -313,6 +319,9 @@ def global_rules(world, player):
|
|||||||
state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player)) # need to defeat wizzrobes, bombs don't work ...
|
state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player)) # need to defeat wizzrobes, bombs don't work ...
|
||||||
# byrna could work with sufficient magic
|
# byrna could work with sufficient magic
|
||||||
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
||||||
|
loc = world.get_location('Misery Mire - Spikes Pot Key', player)
|
||||||
|
if loc.pot.x == 48 and loc.pot.y == 28: # pot shuffled to spike area
|
||||||
|
set_rule(loc, lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
||||||
set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player))
|
set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player))
|
||||||
set_rule(world.get_entrance('Mire Attic Hint Hole', player), lambda state: state.has_fire_source(player))
|
set_rule(world.get_entrance('Mire Attic Hint Hole', player), lambda state: state.has_fire_source(player))
|
||||||
@@ -334,8 +343,10 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_entrance('TR Big Chest Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has_Boots(player))
|
set_rule(world.get_entrance('TR Big Chest Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has_Boots(player))
|
||||||
set_rule(world.get_entrance('TR Dark Ride Up Stairs', player), lambda state: state.has('Cane of Somaria', player))
|
set_rule(world.get_entrance('TR Dark Ride Up Stairs', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
set_rule(world.get_entrance('TR Dark Ride SW', player), lambda state: state.has('Cane of Somaria', player))
|
set_rule(world.get_entrance('TR Dark Ride SW', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
set_rule(world.get_entrance('TR Final Abyss South Stairs', player), lambda state: state.has('Cane of Somaria', player))
|
for location in world.get_region('TR Dark Ride', player).locations:
|
||||||
set_rule(world.get_entrance('TR Final Abyss NW', player), lambda state: state.has('Cane of Somaria', player))
|
set_rule(location, lambda state: state.has('Cane of Somaria', player))
|
||||||
|
set_rule(world.get_entrance('TR Final Abyss Balcony Path', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
|
set_rule(world.get_entrance('TR Final Abyss Ledge Path', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
|
set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
|
||||||
set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
|
set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
|
||||||
set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
|
set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
|
||||||
@@ -349,12 +360,12 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_entrance('GT Conveyor Cross EN', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('GT Conveyor Cross EN', player), lambda state: state.has('Hookshot', player))
|
||||||
if not world.get_door('GT Speed Torch SE', player).entranceFlag:
|
if not world.get_door('GT Speed Torch SE', player).entranceFlag:
|
||||||
set_rule(world.get_entrance('GT Speed Torch SE', player), lambda state: state.has('Fire Rod', player))
|
set_rule(world.get_entrance('GT Speed Torch SE', player), lambda state: state.has('Fire Rod', player))
|
||||||
set_rule(world.get_entrance('GT Hookshot East-North Path', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('GT Hookshot South-Mid Path', player), lambda state: state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('GT Hookshot South-East Path', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('GT Hookshot Mid-North Path', player), lambda state: state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('GT Hookshot South-North Path', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('GT Hookshot East-Mid Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
|
||||||
set_rule(world.get_entrance('GT Hookshot East-South Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
|
set_rule(world.get_entrance('GT Hookshot North-Mid Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
|
||||||
set_rule(world.get_entrance('GT Hookshot North-East Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
|
set_rule(world.get_entrance('GT Hookshot Mid-South Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
|
||||||
set_rule(world.get_entrance('GT Hookshot North-South Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
|
set_rule(world.get_entrance('GT Hookshot Mid-East Path', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player))
|
||||||
set_rule(world.get_entrance('GT Firesnake Room Hook Path', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('GT Firesnake Room Hook Path', player), lambda state: state.has('Hookshot', player))
|
||||||
|
|
||||||
# I am tempted to stick an invincibility rule for getting across falling bridge
|
# I am tempted to stick an invincibility rule for getting across falling bridge
|
||||||
@@ -391,6 +402,8 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_entrance('Thieves Attic ES', player), lambda state: state.can_reach_blue(world.get_region('Thieves Attic', player), player))
|
set_rule(world.get_entrance('Thieves Attic ES', player), lambda state: state.can_reach_blue(world.get_region('Thieves Attic', player), player))
|
||||||
else:
|
else:
|
||||||
set_rule(world.get_entrance('Thieves Attic ES', player), lambda state: state.can_reach_orange(world.get_region('Thieves Attic', player), player))
|
set_rule(world.get_entrance('Thieves Attic ES', player), lambda state: state.can_reach_orange(world.get_region('Thieves Attic', player), player))
|
||||||
|
set_rule(world.get_entrance('Thieves Attic Orange Barrier', player), lambda state: state.can_reach_orange(world.get_region('Thieves Attic', player), player))
|
||||||
|
set_rule(world.get_entrance('Thieves Attic Blue Barrier', player), lambda state: state.can_reach_blue(world.get_region('Thieves Attic', player), player))
|
||||||
|
|
||||||
set_rule(world.get_entrance('Hera Lobby to Front Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Hera Lobby', player), player))
|
set_rule(world.get_entrance('Hera Lobby to Front Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Hera Lobby', player), player))
|
||||||
set_rule(world.get_entrance('Hera Front to Lobby Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Hera Front', player), player))
|
set_rule(world.get_entrance('Hera Front to Lobby Barrier - Blue', player), lambda state: state.can_reach_blue(world.get_region('Hera Front', player), player))
|
||||||
@@ -414,6 +427,7 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_entrance('Hera Basement Cage to Crystal', player), lambda state: state.can_hit_crystal(player))
|
set_rule(world.get_entrance('Hera Basement Cage to Crystal', player), lambda state: state.can_hit_crystal(player))
|
||||||
set_rule(world.get_entrance('Hera Tridorm to Crystal', player), lambda state: state.can_hit_crystal(player))
|
set_rule(world.get_entrance('Hera Tridorm to Crystal', player), lambda state: state.can_hit_crystal(player))
|
||||||
set_rule(world.get_entrance('Hera Startile Wide to Crystal', player), lambda state: state.can_hit_crystal(player))
|
set_rule(world.get_entrance('Hera Startile Wide to Crystal', player), lambda state: state.can_hit_crystal(player))
|
||||||
|
set_rule(world.get_entrance('Hera 5F Orange Path', player), lambda state: state.can_reach_orange(world.get_region('Hera 5F', player), player))
|
||||||
|
|
||||||
set_rule(world.get_entrance('PoD Arena North to Landing Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Arena North', player), player))
|
set_rule(world.get_entrance('PoD Arena North to Landing Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Arena North', player), player))
|
||||||
set_rule(world.get_entrance('PoD Arena Landing to North Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Arena Landing', player), player))
|
set_rule(world.get_entrance('PoD Arena Landing to North Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('PoD Arena Landing', player), player))
|
||||||
@@ -584,18 +598,20 @@ def global_rules(world, player):
|
|||||||
|
|
||||||
|
|
||||||
def bomb_rules(world, player):
|
def bomb_rules(world, player):
|
||||||
|
# todo: kak well, pod hint (bonkable pots), hookshot pot, spike cave pots
|
||||||
bonkable_doors = ['Two Brothers House Exit (West)', 'Two Brothers House Exit (East)'] # Technically this is incorrectly defined, but functionally the same as what is intended.
|
bonkable_doors = ['Two Brothers House Exit (West)', 'Two Brothers House Exit (East)'] # Technically this is incorrectly defined, but functionally the same as what is intended.
|
||||||
bombable_doors = ['Ice Rod Cave', 'Light World Bomb Hut', 'Light World Death Mountain Shop', 'Mini Moldorm Cave',
|
bombable_doors = ['Ice Rod Cave', 'Light World Bomb Hut', 'Light World Death Mountain Shop', 'Mini Moldorm Cave',
|
||||||
'Hookshot Cave Back to Middle', 'Hookshot Cave Front to Middle', 'Hookshot Cave Middle to Front','Hookshot Cave Middle to Back',
|
'Hookshot Cave Back to Middle', 'Hookshot Cave Front to Middle', 'Hookshot Cave Middle to Front',
|
||||||
'Dark Lake Hylia Ledge Fairy', 'Hype Cave', 'Brewery', 'Light Hype Fairy']
|
'Hookshot Cave Middle to Back', 'Dark Lake Hylia Ledge Fairy', 'Hype Cave', 'Brewery',
|
||||||
|
'Paradox Cave Chest Area NE', 'Blinds Hideout N', 'Kakariko Well (top to back)',
|
||||||
|
'Light Hype Fairy']
|
||||||
for entrance in bonkable_doors:
|
for entrance in bonkable_doors:
|
||||||
add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player))
|
add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player))
|
||||||
for entrance in bombable_doors:
|
for entrance in bombable_doors:
|
||||||
add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player))
|
add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player))
|
||||||
|
|
||||||
bonkable_items = ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right']
|
bonkable_items = ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right']
|
||||||
bombable_items = ['Blind\'s Hideout - Top', 'Kakariko Well - Top', 'Chicken House', 'Aginah\'s Cave', 'Graveyard Cave',
|
bombable_items = ['Chicken House', 'Aginah\'s Cave', 'Graveyard Cave',
|
||||||
'Paradox Cave Upper - Left', 'Paradox Cave Upper - Right',
|
|
||||||
'Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', 'Hype Cave - Bottom']
|
'Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', 'Hype Cave - Bottom']
|
||||||
for location in bonkable_items:
|
for location in bonkable_items:
|
||||||
add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player))
|
add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player))
|
||||||
@@ -694,6 +710,37 @@ def bomb_rules(world, player):
|
|||||||
elif door.kind(world) in [DoorKind.Bombable]:
|
elif door.kind(world) in [DoorKind.Bombable]:
|
||||||
add_rule(door.entrance, lambda state: state.can_use_bombs(player))
|
add_rule(door.entrance, lambda state: state.can_use_bombs(player))
|
||||||
|
|
||||||
|
|
||||||
|
def pot_rules(world, player):
|
||||||
|
if world.pottery[player] == 'lottery':
|
||||||
|
blocks = [l for l in world.get_locations() if l.type == LocationType.Pot and l.pot.flags & PotFlags.Block]
|
||||||
|
for block_pot in blocks:
|
||||||
|
add_rule(block_pot, lambda state: state.can_lift_rocks(player))
|
||||||
|
for l in world.get_region('Hookshot Fairy', player).locations:
|
||||||
|
if l.type == LocationType.Pot:
|
||||||
|
add_rule(l, lambda state: state.has('Hookshot', player))
|
||||||
|
for l in world.get_region('Spike Cave', player).locations:
|
||||||
|
if l.type == LocationType.Pot:
|
||||||
|
add_rule(l, lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and
|
||||||
|
((state.has('Cape', player) and state.can_extend_magic(player, 16, True)) or
|
||||||
|
(state.has('Cane of Byrna', player) and
|
||||||
|
(state.can_extend_magic(player, 12, True) or
|
||||||
|
(state.world.can_take_damage and (state.has_Boots(player) or state.has_hearts(player, 4)))))))
|
||||||
|
for l in world.get_region('Dark Desert Hint', player).locations:
|
||||||
|
if l.type == LocationType.Pot:
|
||||||
|
add_rule(l, lambda state: state.can_use_bombs(player))
|
||||||
|
for l in world.get_region('Palace of Darkness Hint', player).locations:
|
||||||
|
if l.type == LocationType.Pot:
|
||||||
|
add_rule(l, lambda state: state.can_use_bombs(player) or state.has_Boots(player))
|
||||||
|
for l in world.get_region('Dark Lake Hylia Ledge Spike Cave', player).locations:
|
||||||
|
if l.type == LocationType.Pot:
|
||||||
|
add_rule(l, lambda state: state.world.can_take_damage or state.has('Hookshot', player))
|
||||||
|
loc = world.get_location_unsafe('Mire Spikes Pot #3', player)
|
||||||
|
if loc:
|
||||||
|
set_rule(loc, lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def default_rules(world, player):
|
def default_rules(world, player):
|
||||||
# overworld requirements
|
# overworld requirements
|
||||||
set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player))
|
set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player))
|
||||||
@@ -1070,6 +1117,10 @@ def add_conditional_lamps(world, player):
|
|||||||
'Sewers Rope Room': {'sewer': True, 'entrances': ['Sewers Rope Room Up Stairs', 'Sewers Rope Room North Stairs'], 'locations': []},
|
'Sewers Rope Room': {'sewer': True, 'entrances': ['Sewers Rope Room Up Stairs', 'Sewers Rope Room North Stairs'], 'locations': []},
|
||||||
'Sewers Water': {'sewer': True, 'entrances': ['Sewers Water S', 'Sewers Water W'], 'locations': []},
|
'Sewers Water': {'sewer': True, 'entrances': ['Sewers Water S', 'Sewers Water W'], 'locations': []},
|
||||||
'Sewers Key Rat': {'sewer': True, 'entrances': ['Sewers Key Rat E', 'Sewers Key Rat Key Door N'], 'locations': ['Hyrule Castle - Key Rat Key Drop']},
|
'Sewers Key Rat': {'sewer': True, 'entrances': ['Sewers Key Rat E', 'Sewers Key Rat Key Door N'], 'locations': ['Hyrule Castle - Key Rat Key Drop']},
|
||||||
|
'Old Man Cave': {'sewer': False, 'entrances': ['Old Man Cave Exit (East)']},
|
||||||
|
'Old Man House Back': {'sewer': False, 'entrances': ['Old Man House Back to Front', 'Old Man House Exit (Top)']},
|
||||||
|
'Death Mountain Return Cave (left)': {'sewer': False, 'entrances': ['Death Mountain Return Cave E', 'Death Mountain Return Cave Exit (West)']},
|
||||||
|
'Death Mountain Return Cave (right)': {'sewer': False, 'entrances': ['Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave W']},
|
||||||
}
|
}
|
||||||
|
|
||||||
dark_debug_set = set()
|
dark_debug_set = set()
|
||||||
@@ -1086,17 +1137,12 @@ def add_conditional_lamps(world, player):
|
|||||||
dark_debug_set.add(region)
|
dark_debug_set.add(region)
|
||||||
for ent in info['entrances']:
|
for ent in info['entrances']:
|
||||||
add_conditional_lamp(ent, region, 'Entrance')
|
add_conditional_lamp(ent, region, 'Entrance')
|
||||||
for loc in info['locations']:
|
r = world.get_region(region, player)
|
||||||
|
for loc in r.locations:
|
||||||
add_conditional_lamp(loc, region, 'Location')
|
add_conditional_lamp(loc, region, 'Location')
|
||||||
logging.getLogger('').debug('Non Dark Regions: ' + ', '.join(set(dark_rooms.keys()).difference(dark_debug_set)))
|
logging.getLogger('').debug('Non Dark Regions: ' + ', '.join(set(dark_rooms.keys()).difference(dark_debug_set)))
|
||||||
|
|
||||||
add_conditional_lamp('Old Man', 'Old Man Cave', 'Location')
|
|
||||||
add_conditional_lamp('Old Man Cave Exit (East)', 'Old Man Cave', 'Entrance')
|
|
||||||
add_conditional_lamp('Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave', 'Entrance')
|
|
||||||
add_conditional_lamp('Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave', 'Entrance')
|
|
||||||
add_conditional_lamp('Old Man House Front to Back', 'Old Man House', 'Entrance')
|
add_conditional_lamp('Old Man House Front to Back', 'Old Man House', 'Entrance')
|
||||||
add_conditional_lamp('Old Man House Back to Front', 'Old Man House', 'Entrance')
|
|
||||||
|
|
||||||
|
|
||||||
def open_rules(world, player):
|
def open_rules(world, player):
|
||||||
# softlock protection as you can reach the sewers small key door with a guard drop key
|
# softlock protection as you can reach the sewers small key door with a guard drop key
|
||||||
@@ -1880,7 +1926,7 @@ bunny_revivable_entrances = {
|
|||||||
"Ice Many Pots", "Mire South Fish", "Mire Right Bridge", "Mire Left Bridge",
|
"Ice Many Pots", "Mire South Fish", "Mire Right Bridge", "Mire Left Bridge",
|
||||||
"TR Boss", "Eastern Hint Tile Blocked Path", "Thieves Spike Switch",
|
"TR Boss", "Eastern Hint Tile Blocked Path", "Thieves Spike Switch",
|
||||||
"Thieves Boss", "Mire Spike Barrier", "Mire Cross", "Mire Hidden Shooters",
|
"Thieves Boss", "Mire Spike Barrier", "Mire Cross", "Mire Hidden Shooters",
|
||||||
"Mire Spikes", "TR Final Abyss", "TR Dark Ride", "TR Pokey 1", "TR Tile Room",
|
"Mire Spikes", "TR Final Abyss Balcony", "TR Dark Ride", "TR Pokey 1", "TR Tile Room",
|
||||||
"TR Roller Room", "Eastern Cannonball", "Thieves Hallway", "Ice Switch Room",
|
"TR Roller Room", "Eastern Cannonball", "Thieves Hallway", "Ice Switch Room",
|
||||||
"Mire Tile Room", "Mire Conveyor Crystal", "Mire Hub", "TR Dash Bridge",
|
"Mire Tile Room", "Mire Conveyor Crystal", "Mire Hub", "TR Dash Bridge",
|
||||||
"TR Hub", "Eastern Boss", "Eastern Lobby", "Thieves Ambush",
|
"TR Hub", "Eastern Boss", "Eastern Lobby", "Thieves Ambush",
|
||||||
@@ -1948,11 +1994,11 @@ bunny_impassible_doors = {
|
|||||||
'TR Pokey 2 Bottom to Top Barrier - Blue', 'TR Pokey 2 Top to Bottom Barrier - Blue', 'TR Twin Pokeys SW', 'TR Twin Pokeys EN', 'TR Big Chest Gap',
|
'TR Pokey 2 Bottom to Top Barrier - Blue', 'TR Pokey 2 Top to Bottom Barrier - Blue', 'TR Twin Pokeys SW', 'TR Twin Pokeys EN', 'TR Big Chest Gap',
|
||||||
'TR Big Chest Entrance Gap', 'TR Lazy Eyes ES', 'TR Tongue Pull WS', 'TR Tongue Pull NE', 'TR Dark Ride Up Stairs',
|
'TR Big Chest Entrance Gap', 'TR Lazy Eyes ES', 'TR Tongue Pull WS', 'TR Tongue Pull NE', 'TR Dark Ride Up Stairs',
|
||||||
'TR Dark Ride SW', 'TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze End to Interior Barrier - Blue',
|
'TR Dark Ride SW', 'TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze End to Interior Barrier - Blue',
|
||||||
'TR Final Abyss South Stairs', 'TR Final Abyss NW', 'GT Hope Room EN', 'GT Blocked Stairs Block Path',
|
'TR Final Abyss Balcony Path', 'TR Final Abyss Ledge Path', 'GT Hope Room EN', 'GT Blocked Stairs Block Path',
|
||||||
'GT Bob\'s Room Hole', 'GT Speed Torch SE', 'GT Speed Torch South Path', 'GT Speed Torch North Path',
|
'GT Bob\'s Room Hole', 'GT Speed Torch SE', 'GT Speed Torch South Path', 'GT Speed Torch North Path',
|
||||||
'GT Crystal Conveyor NE', 'GT Crystal Conveyor WN', 'GT Conveyor Cross EN', 'GT Conveyor Cross WN',
|
'GT Crystal Conveyor NE', 'GT Crystal Conveyor WN', 'GT Conveyor Cross EN', 'GT Conveyor Cross WN',
|
||||||
'GT Hookshot East-North Path', 'GT Hookshot East-South Path', 'GT Hookshot North-East Path',
|
'GT Hookshot East-Mid Path', 'GT Hookshot South-Mid Path', 'GT Hookshot North-Mid Path',
|
||||||
'GT Hookshot North-South Path', 'GT Hookshot South-East Path', 'GT Hookshot South-North Path',
|
'GT Hookshot Mid-South Path', 'GT Hookshot Mid-East Path', 'GT Hookshot Mid-North Path',
|
||||||
'GT Hookshot Platform Blue Barrier', 'GT Hookshot Entry Blue Barrier', 'GT Double Switch Pot Corners to Exit Barrier - Blue',
|
'GT Hookshot Platform Blue Barrier', 'GT Hookshot Entry Blue Barrier', 'GT Double Switch Pot Corners to Exit Barrier - Blue',
|
||||||
'GT Double Switch Exit to Blue Barrier', 'GT Firesnake Room Hook Path', 'GT Falling Bridge WN', 'GT Falling Bridge WS',
|
'GT Double Switch Exit to Blue Barrier', 'GT Firesnake Room Hook Path', 'GT Falling Bridge WN', 'GT Falling Bridge WS',
|
||||||
'GT Ice Armos NE', 'GT Ice Armos WS', 'GT Crystal Paths SW', 'GT Mimics 1 NW', 'GT Mimics 1 ES', 'GT Mimics 2 WS',
|
'GT Ice Armos NE', 'GT Ice Armos WS', 'GT Crystal Paths SW', 'GT Mimics 1 NW', 'GT Mimics 1 ES', 'GT Mimics 2 WS',
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ def main(args=None):
|
|||||||
|
|
||||||
test("Vanilla ", "--shuffle vanilla")
|
test("Vanilla ", "--shuffle vanilla")
|
||||||
test("Retro ", "--retro --shuffle vanilla")
|
test("Retro ", "--retro --shuffle vanilla")
|
||||||
test("Keysanity ", "--shuffle vanilla --keydropshuffle --keysanity")
|
test("Keysanity ", "--shuffle vanilla --keydropshuffle drops_only --keysanity")
|
||||||
test("Shopsanity", "--shuffle vanilla --shopsanity")
|
test("Shopsanity", "--shuffle vanilla --shopsanity")
|
||||||
test("Simple ", "--shuffle simple")
|
test("Simple ", "--shuffle simple")
|
||||||
test("Full ", "--shuffle full")
|
test("Full ", "--shuffle full")
|
||||||
|
|||||||
@@ -580,10 +580,11 @@ def extract_data_from_jp_rom(rom):
|
|||||||
with open(rom, 'rb') as stream:
|
with open(rom, 'rb') as stream:
|
||||||
rom_data = bytearray(stream.read())
|
rom_data = bytearray(stream.read())
|
||||||
|
|
||||||
rooms = [0x1c, 0x1d, 0x4e]
|
rooms = range(0, 0x128)
|
||||||
# rooms = [0x7b, 0x7c, 0x7d, 0x8b, 0x8c, 0x8d, 0x9b, 0x9c, 0x9d]
|
# rooms = [0x7b, 0x7c, 0x7d, 0x8b, 0x8c, 0x8d, 0x9b, 0x9c, 0x9d]
|
||||||
# rooms = [0x1a, 0x2a, 0xd1]
|
# rooms = [0x1a, 0x2a, 0xd1]
|
||||||
for room in rooms:
|
for room in rooms:
|
||||||
|
# print(f'Room {room:02x}')
|
||||||
b2idx = room*2
|
b2idx = room*2
|
||||||
b3idx = room*3
|
b3idx = room*3
|
||||||
headerptr = 0x271e2 + b2idx
|
headerptr = 0x271e2 + b2idx
|
||||||
@@ -600,6 +601,7 @@ def extract_data_from_jp_rom(rom):
|
|||||||
stop, idx = False, 0
|
stop, idx = False, 0
|
||||||
ffcnt = 0
|
ffcnt = 0
|
||||||
mode = 0
|
mode = 0
|
||||||
|
secret_cnt = 0
|
||||||
# first two bytes
|
# first two bytes
|
||||||
b1 = rom_data[objectloc+idx]
|
b1 = rom_data[objectloc+idx]
|
||||||
b2 = rom_data[objectloc+idx+1]
|
b2 = rom_data[objectloc+idx+1]
|
||||||
@@ -621,9 +623,20 @@ def extract_data_from_jp_rom(rom):
|
|||||||
idx += 2
|
idx += 2
|
||||||
elif not mode and ffcnt < 3:
|
elif not mode and ffcnt < 3:
|
||||||
objectdata.append(b3)
|
objectdata.append(b3)
|
||||||
|
if b3 == 0xFA and ((b2 & 0x3) << 2) | (b1 & 0x3) in [0xf, 0xc]:
|
||||||
|
# potcalc
|
||||||
|
vram = ((b1 & 0xFC) >> 1) | ((b2 & 0xFC) << 5)
|
||||||
|
low = vram & 0xFF
|
||||||
|
high = (vram & 0xFF00) >> 8
|
||||||
|
if ffcnt == 1:
|
||||||
|
high |= 0x20
|
||||||
|
print(f'db {", ".join([f"${low:02x}", f"${high:02x}"])}')
|
||||||
|
secret_cnt += 1
|
||||||
idx += 3
|
idx += 3
|
||||||
else:
|
else:
|
||||||
idx += 2
|
idx += 2
|
||||||
|
if secret_cnt:
|
||||||
|
print(f'Room {room:02x} {secret_cnt}')
|
||||||
spriteptr = 0x4d62e + b2idx
|
spriteptr = 0x4d62e + b2idx
|
||||||
spriteloc = rom_data[spriteptr] + rom_data[spriteptr+1]*0x100 + 0x40000
|
spriteloc = rom_data[spriteptr] + rom_data[spriteptr+1]*0x100 + 0x40000
|
||||||
secretptr = 0xdb67 + b2idx
|
secretptr = 0xdb67 + b2idx
|
||||||
@@ -647,23 +660,23 @@ def extract_data_from_jp_rom(rom):
|
|||||||
else:
|
else:
|
||||||
secretdata.append(b3)
|
secretdata.append(b3)
|
||||||
idx += 3
|
idx += 3
|
||||||
print(f'Room {room:02x}')
|
# print(f'Room {room:02x}')
|
||||||
print(f'HeaderPtr {headerptr:06x}')
|
# print(f'HeaderPtr {headerptr:06x}')
|
||||||
print(f'HeaderLoc {headerloc:06x}')
|
# print(f'HeaderLoc {headerloc:06x}')
|
||||||
print(f'db {",".join([f"${x:02x}" for x in header])}')
|
# print(f'db {",".join([f"${x:02x}" for x in header])}')
|
||||||
print(f'Obj Length: {len(objectdata)}')
|
# print(f'Obj Length: {len(objectdata)}')
|
||||||
print(f'ObjectPtr {objectptr:06x}')
|
# print(f'ObjectPtr {objectptr:06x}')
|
||||||
print(f'ObjectLoc {objectloc:06x}')
|
# print(f'ObjectLoc {objectloc:06x}')
|
||||||
for i in range(0, len(objectdata)//16 + 1):
|
# for i in range(0, len(objectdata)//16 + 1):
|
||||||
slice = objectdata[i*16:i*16+16]
|
# slice = objectdata[i*16:i*16+16]
|
||||||
print(f'db {",".join([f"${x:02x}" for x in slice])}')
|
# print(f'db {",".join([f"${x:02x}" for x in slice])}')
|
||||||
print(f'SpritePtr {spriteptr:06x}')
|
# print(f'SpritePtr {spriteptr:06x}')
|
||||||
print(f'SpriteLoc {spriteloc:06x}')
|
# print(f'SpriteLoc {spriteloc:06x}')
|
||||||
print_data_block(spritedata)
|
# print_data_block(spritedata)
|
||||||
print(f'SecretPtr {secretptr:06x}')
|
# print(f'SecretPtr {secretptr:06x}')
|
||||||
print(f'SecretLoc {secretloc:06x}')
|
# print(f'SecretLoc {secretloc:06x}')
|
||||||
print_data_block(secretdata)
|
# print_data_block(secretdata)
|
||||||
print()
|
# print()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -42,6 +42,3 @@ warnpc $279C00
|
|||||||
|
|
||||||
incsrc doortables.asm
|
incsrc doortables.asm
|
||||||
warnpc $288000
|
warnpc $288000
|
||||||
|
|
||||||
; deals with own hooks
|
|
||||||
incsrc keydropshuffle.asm
|
|
||||||
|
|||||||
@@ -1,181 +0,0 @@
|
|||||||
org $06926e ; <- 3126e - sprite_prep.asm : 2664 (LDA $0B9B : STA $0CBA, X)
|
|
||||||
jsl SpriteKeyPrep : nop #2
|
|
||||||
|
|
||||||
org $06d049 ; <- 35049 sprite_absorbable : 31-32 (JSL Sprite_DrawRippleIfInWater : JSR Sprite_DrawAbsorbable)
|
|
||||||
jsl SpriteKeyDrawGFX : bra + : nop : +
|
|
||||||
|
|
||||||
org $06d180
|
|
||||||
jsl BigKeyGet : bcs $07 : nop #5
|
|
||||||
|
|
||||||
org $06d18d ; <- 3518D - sprite_absorbable.asm : 274 (LDA $7EF36F : INC A : STA $7EF36F)
|
|
||||||
jsl KeyGet
|
|
||||||
|
|
||||||
org $06f9f3 ; bank06.asm : 6732 (JSL Sprite_LoadProperties)
|
|
||||||
jsl LoadProperties_PreserveItemMaybe
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
org $06d23a
|
|
||||||
Sprite_DrawAbsorbable:
|
|
||||||
org $1eff81
|
|
||||||
Sprite_DrawRippleIfInWater:
|
|
||||||
org $0db818
|
|
||||||
Sprite_LoadProperties:
|
|
||||||
|
|
||||||
org $288000 ;140000
|
|
||||||
ShuffleKeyDrops:
|
|
||||||
db 0
|
|
||||||
MultiClientFlags: ; 140001 -> stored in SRAM at 7ef33d
|
|
||||||
db 0
|
|
||||||
|
|
||||||
LootTable: ;PC: 140002
|
|
||||||
db $0e, $00, $24 ;; ice jelly key
|
|
||||||
db $13, $00, $24 ;; pokey 2
|
|
||||||
db $16, $00, $24 ;; swamp waterway pot
|
|
||||||
db $21, $00, $24 ;; key rat
|
|
||||||
db $35, $00, $24 ;; swamp trench 2 pot
|
|
||||||
db $36, $00, $24 ;; hookshot pot
|
|
||||||
db $37, $00, $24 ;; trench 1 pot
|
|
||||||
db $38, $00, $24 ;; pot row pot
|
|
||||||
db $39, $00, $24 ;; skull gibdo
|
|
||||||
db $3d, $00, $24 ;; gt minihelma
|
|
||||||
db $3e, $00, $24 ;; ice conveyor
|
|
||||||
db $3f, $00, $24 ;; ice hammer block ??? is this a dungeon secret?
|
|
||||||
db $43, $00, $24 ;; tiles 2 pot
|
|
||||||
db $53, $00, $24 ;; beamos hall pot
|
|
||||||
db $56, $00, $24 ;; skull west lobby pot
|
|
||||||
db $63, $00, $24 ;; desert tiles 1 pot
|
|
||||||
db $71, $00, $24 ;; boomerang guard
|
|
||||||
db $72, $00, $24 ;; hc map guard
|
|
||||||
db $7b, $00, $24 ;; gt star pits pot
|
|
||||||
db $80, $00, $32 ;; a big key (for the current dungeon)
|
|
||||||
db $8b, $00, $24 ;; gt conv cross block
|
|
||||||
db $9b, $00, $24 ;; gt dlb switch pot
|
|
||||||
db $9f, $00, $24 ;; ice many pots
|
|
||||||
db $99, $00, $24 ;; eastern eyegore
|
|
||||||
db $a1, $00, $24 ;; mire fishbone pot
|
|
||||||
db $ab, $00, $24 ;; tt spike switch pot
|
|
||||||
db $b0, $00, $24 ;; tower circle of pots usain
|
|
||||||
db $b3, $00, $24 ;; mire spikes pot
|
|
||||||
db $b6, $00, $24 ;; pokey 1
|
|
||||||
db $ba, $00, $24 ;; eastern dark pot
|
|
||||||
db $bc, $00, $24 ;; tt hallway pot
|
|
||||||
db $c0, $00, $24 ;; tower dark archer
|
|
||||||
db $c1, $00, $24 ;; mire glitchy jelly
|
|
||||||
db $ff, $00, $ff
|
|
||||||
;140068
|
|
||||||
|
|
||||||
KeyTable:
|
|
||||||
db $a0, $a0, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $aa, $ab, $ac, $ad
|
|
||||||
|
|
||||||
SpriteKeyPrep:
|
|
||||||
{
|
|
||||||
lda $0b9b : sta $0cba, x ; what we wrote over
|
|
||||||
pha
|
|
||||||
lda.l ShuffleKeyDrops : beq +
|
|
||||||
phx
|
|
||||||
ldx #$fd
|
|
||||||
- inx #3 : lda.l LootTable, x : cmp #$ff : beq ++ : cmp $a0 : bne -
|
|
||||||
inx : lda.l LootTable, x : sta !MULTIWORLD_SPRITEITEM_PLAYER_ID
|
|
||||||
inx : lda.l LootTable, x
|
|
||||||
plx : sta $0e80, x
|
|
||||||
cmp #$24 : bne +++
|
|
||||||
lda $a0 : cmp #$80 : bne + : lda #$24
|
|
||||||
+++ jsl PrepDynamicTile : bra +
|
|
||||||
++ plx : lda #$24 : sta $0e80, x
|
|
||||||
+ pla
|
|
||||||
rtl
|
|
||||||
}
|
|
||||||
|
|
||||||
SpriteKeyDrawGFX:
|
|
||||||
{
|
|
||||||
jsl Sprite_DrawRippleIfInWater
|
|
||||||
pha
|
|
||||||
lda.l ShuffleKeyDrops : bne +
|
|
||||||
- pla
|
|
||||||
phk : pea.w .jslrtsreturn-1
|
|
||||||
pea.w $068014 ; an rtl address - 1 in Bank06
|
|
||||||
jml Sprite_DrawAbsorbable
|
|
||||||
.jslrtsreturn
|
|
||||||
rtl
|
|
||||||
+ lda $0e80, x
|
|
||||||
cmp #$24 : bne +
|
|
||||||
lda $a0 : cmp #$80 : bne - : lda #$24
|
|
||||||
+ jsl DrawDynamicTile ; see DrawHeartPieceGFX if problems
|
|
||||||
cmp #$03 : bne +
|
|
||||||
pha : lda $0e60, x : ora.b #$20 : sta $0E60, x : pla
|
|
||||||
+
|
|
||||||
jsl.l Sprite_DrawShadowLong
|
|
||||||
|
|
||||||
pla : rtl
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyGet:
|
|
||||||
{
|
|
||||||
lda $7ef36f ; what we wrote over
|
|
||||||
pha
|
|
||||||
lda.l ShuffleKeyDrops : bne +
|
|
||||||
- pla : rtl
|
|
||||||
+ ldy $0e80, x
|
|
||||||
lda $a0 : cmp #$87 : bne +
|
|
||||||
jsr ShouldKeyBeCountedForDungeon : bcc -
|
|
||||||
jsl CountChestKeyLong : bra -
|
|
||||||
+ sty $00
|
|
||||||
jsr KeyGetPlayer : sta !MULTIWORLD_ITEM_PLAYER_ID
|
|
||||||
lda !MULTIWORLD_ITEM_PLAYER_ID : bne .receive
|
|
||||||
phx
|
|
||||||
lda $040c : lsr : tax
|
|
||||||
lda $00 : CMP.l KeyTable, x : bne +
|
|
||||||
- JSL.l FullInventoryExternal : jsl CountChestKeyLong : plx : pla : rtl
|
|
||||||
+ cmp #$af : beq - ; universal key
|
|
||||||
cmp #$24 : beq - ; small key for this dungeon
|
|
||||||
plx
|
|
||||||
.receive
|
|
||||||
jsl.l $0791b3 ; Player_HaltDashAttackLong
|
|
||||||
jsl.l Link_ReceiveItem
|
|
||||||
pla : dec : rtl
|
|
||||||
}
|
|
||||||
|
|
||||||
; Input Y - the item type
|
|
||||||
ShouldKeyBeCountedForDungeon:
|
|
||||||
{
|
|
||||||
phx
|
|
||||||
lda $040c : lsr : tax
|
|
||||||
tya : cmp KeyTable, x : bne +
|
|
||||||
- plx : sec : rts
|
|
||||||
+ cmp #$24 : beq -
|
|
||||||
plx : clc : rts
|
|
||||||
}
|
|
||||||
|
|
||||||
BigKeyGet:
|
|
||||||
{
|
|
||||||
lda.l ShuffleKeyDrops : bne +
|
|
||||||
- stz $02e9 : ldy.b #$32 ; what we wrote over
|
|
||||||
phx : jsl Link_ReceiveItem : plx ; what we wrote over
|
|
||||||
clc : rtl
|
|
||||||
+
|
|
||||||
ldy $0e80, x
|
|
||||||
cpy #$32 : beq -
|
|
||||||
+ sec : rtl
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyGetPlayer:
|
|
||||||
{
|
|
||||||
phx
|
|
||||||
ldx #$fd
|
|
||||||
- inx #3 : lda.l LootTable, x : cmp #$ff : beq ++ : cmp $a0 : bne -
|
|
||||||
++ inx : lda.l LootTable, x
|
|
||||||
plx
|
|
||||||
rts
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadProperties_PreserveItemMaybe:
|
|
||||||
{
|
|
||||||
lda.l ShuffleKeyDrops : bne +
|
|
||||||
JML Sprite_LoadProperties
|
|
||||||
+ lda $0e80, x : pha
|
|
||||||
jsl Sprite_LoadProperties
|
|
||||||
pla : sta $0e80, x
|
|
||||||
rtl
|
|
||||||
}
|
|
||||||
Binary file not shown.
+3
-2
@@ -8,8 +8,9 @@
|
|||||||
2: 2
|
2: 2
|
||||||
3: 4
|
3: 4
|
||||||
keydropshuffle:
|
keydropshuffle:
|
||||||
on: 1
|
none: 1
|
||||||
off: 1
|
keydrops: 1
|
||||||
|
potsanity: 1
|
||||||
shopsanity:
|
shopsanity:
|
||||||
on: 1
|
on: 1
|
||||||
off: 1
|
off: 1
|
||||||
|
|||||||
@@ -68,6 +68,21 @@
|
|||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
},
|
||||||
|
"dropshuffle" : {
|
||||||
|
"action": "store_true",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
|
"pottery" : {
|
||||||
|
"choices" : [
|
||||||
|
"none",
|
||||||
|
"keys",
|
||||||
|
"lottery"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"shufflepots": {
|
||||||
|
"action": "store_true",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
"mixed_travel" : {
|
"mixed_travel" : {
|
||||||
"choices": [
|
"choices": [
|
||||||
"prevent",
|
"prevent",
|
||||||
@@ -385,10 +400,6 @@
|
|||||||
"random"
|
"random"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"shufflepots": {
|
|
||||||
"action": "store_true",
|
|
||||||
"type": "bool"
|
|
||||||
},
|
|
||||||
"remote_items": {
|
"remote_items": {
|
||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
|
|||||||
@@ -254,7 +254,13 @@
|
|||||||
"keyshuffle": [ "Small Keys are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ],
|
"keyshuffle": [ "Small Keys are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ],
|
||||||
"bigkeyshuffle": [ "Big Keys are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ],
|
"bigkeyshuffle": [ "Big Keys are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ],
|
||||||
"shopsanity": ["Shop contents are shuffle in the main item pool and other items can take their place. (default: %(default)s)"],
|
"shopsanity": ["Shop contents are shuffle in the main item pool and other items can take their place. (default: %(default)s)"],
|
||||||
"keydropshuffle": [ "Key Drops (Pots and Enemies) are shuffled and other items can take their place (default: %(default)s)" ],
|
"dropshuffle": [ "Keys dropped by enemies are shuffled and other items can take their place. (default: %(default)s)"],
|
||||||
|
"pottery": [ "Controls how items under pots are shuffled and if other items can take their place:",
|
||||||
|
"None: No pots are changed",
|
||||||
|
"Keys: Key pots are included in the location pool and other items can take their place",
|
||||||
|
"Lottery: All pots are part of the location pool"
|
||||||
|
],
|
||||||
|
"shufflepots": [ "Pots and switches are shuffled on the supertile (legacy potshuffle) (default: %(default)s)"],
|
||||||
"mixed_travel": [
|
"mixed_travel": [
|
||||||
"How to handle potential traversal between dungeon in Crossed door shuffle",
|
"How to handle potential traversal between dungeon in Crossed door shuffle",
|
||||||
"Prevent: Rails are placed to prevent bombs jump and hovering from changing dungeon except with glitched logic settings",
|
"Prevent: Rails are placed to prevent bombs jump and hovering from changing dungeon except with glitched logic settings",
|
||||||
|
|||||||
@@ -53,7 +53,13 @@
|
|||||||
"randomizer.dungeon.compassshuffle": "Compasses",
|
"randomizer.dungeon.compassshuffle": "Compasses",
|
||||||
"randomizer.dungeon.smallkeyshuffle": "Small Keys",
|
"randomizer.dungeon.smallkeyshuffle": "Small Keys",
|
||||||
"randomizer.dungeon.bigkeyshuffle": "Big Keys",
|
"randomizer.dungeon.bigkeyshuffle": "Big Keys",
|
||||||
"randomizer.dungeon.keydropshuffle": "Key Drops (pots and enemies)",
|
"randomizer.dungeon.keydropshuffle": "Drop and Pot Keys",
|
||||||
|
"randomizer.dungeon.dropshuffle": "Shuffle Key Drops",
|
||||||
|
"randomizer.dungeon.potshuffle": "Pot Shuffle (Legacy)",
|
||||||
|
"randomizer.dungeon.pottery": "Pottery",
|
||||||
|
"randomizer.dungeon.pottery.none": "None",
|
||||||
|
"randomizer.dungeon.pottery.keys": "Key Pots",
|
||||||
|
"randomizer.dungeon.pottery.lottery": "Lottery (All Pots and Large Blocks)",
|
||||||
|
|
||||||
"randomizer.dungeon.dungeondoorshuffle": "Dungeon Door Shuffle",
|
"randomizer.dungeon.dungeondoorshuffle": "Dungeon Door Shuffle",
|
||||||
"randomizer.dungeon.dungeondoorshuffle.vanilla": "Vanilla",
|
"randomizer.dungeon.dungeondoorshuffle.vanilla": "Vanilla",
|
||||||
@@ -66,7 +72,6 @@
|
|||||||
"randomizer.dungeon.dungeonintensity.3": "3: Dungeon Lobbies",
|
"randomizer.dungeon.dungeonintensity.3": "3: Dungeon Lobbies",
|
||||||
"randomizer.dungeon.dungeonintensity.random": "Random",
|
"randomizer.dungeon.dungeonintensity.random": "Random",
|
||||||
|
|
||||||
"randomizer.dungeon.potshuffle": "Pot Shuffle",
|
|
||||||
"randomizer.dungeon.experimental": "Enable Experimental Features",
|
"randomizer.dungeon.experimental": "Enable Experimental Features",
|
||||||
|
|
||||||
"randomizer.dungeon.dungeon_counters": "Dungeon Chest Counters",
|
"randomizer.dungeon.dungeon_counters": "Dungeon Chest Counters",
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
"mapshuffle": { "type": "checkbox" },
|
"mapshuffle": { "type": "checkbox" },
|
||||||
"compassshuffle": { "type": "checkbox" },
|
"compassshuffle": { "type": "checkbox" },
|
||||||
"smallkeyshuffle": { "type": "checkbox" },
|
"smallkeyshuffle": { "type": "checkbox" },
|
||||||
"bigkeyshuffle": { "type": "checkbox" },
|
"bigkeyshuffle": { "type": "checkbox" }
|
||||||
"keydropshuffle": { "type": "checkbox" }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,20 @@
|
|||||||
"width": 45
|
"width": 45
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"keydropshuffle": { "type": "checkbox" },
|
||||||
|
"pottery": {
|
||||||
|
"type": "selectbox",
|
||||||
|
"default": "none",
|
||||||
|
"options": [
|
||||||
|
"none",
|
||||||
|
"keys",
|
||||||
|
"lottery"
|
||||||
|
],
|
||||||
|
"config": {
|
||||||
|
"width": 35
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dropshuffle": { "type": "checkbox" },
|
||||||
"potshuffle": { "type": "checkbox" },
|
"potshuffle": { "type": "checkbox" },
|
||||||
"experimental": { "type": "checkbox" },
|
"experimental": { "type": "checkbox" },
|
||||||
"dungeon_counters": {
|
"dungeon_counters": {
|
||||||
|
|||||||
@@ -93,9 +93,11 @@ SETTINGSTOPROCESS = {
|
|||||||
"compassshuffle": "compassshuffle",
|
"compassshuffle": "compassshuffle",
|
||||||
"smallkeyshuffle": "keyshuffle",
|
"smallkeyshuffle": "keyshuffle",
|
||||||
"bigkeyshuffle": "bigkeyshuffle",
|
"bigkeyshuffle": "bigkeyshuffle",
|
||||||
"keydropshuffle": "keydropshuffle",
|
|
||||||
"dungeondoorshuffle": "door_shuffle",
|
"dungeondoorshuffle": "door_shuffle",
|
||||||
"dungeonintensity": "intensity",
|
"dungeonintensity": "intensity",
|
||||||
|
"keydropshuffle": "keydropshuffle",
|
||||||
|
"dropshuffle": "dropshuffle",
|
||||||
|
"pottery": "pottery",
|
||||||
"potshuffle": "shufflepots",
|
"potshuffle": "shufflepots",
|
||||||
"experimental": "experimental",
|
"experimental": "experimental",
|
||||||
"dungeon_counters": "dungeon_counters",
|
"dungeon_counters": "dungeon_counters",
|
||||||
|
|||||||
+71
-29
@@ -1,12 +1,13 @@
|
|||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
import logging
|
import logging
|
||||||
from math import ceil
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from source.item.District import resolve_districts
|
from source.item.District import resolve_districts
|
||||||
|
from BaseClasses import PotItem, PotFlags
|
||||||
from DoorShuffle import validate_vanilla_reservation
|
from DoorShuffle import validate_vanilla_reservation
|
||||||
from Dungeons import dungeon_table
|
from Dungeons import dungeon_table
|
||||||
from Items import item_table, ItemFactory
|
from Items import item_table, ItemFactory
|
||||||
|
from PotShuffle import vanilla_pots
|
||||||
|
|
||||||
|
|
||||||
class ItemPoolConfig(object):
|
class ItemPoolConfig(object):
|
||||||
@@ -64,34 +65,40 @@ def create_item_pool_config(world):
|
|||||||
config.static_placement = {}
|
config.static_placement = {}
|
||||||
config.location_groups = {}
|
config.location_groups = {}
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
config.static_placement[player] = vanilla_mapping.copy()
|
config.static_placement[player] = defaultdict(list)
|
||||||
if world.keydropshuffle[player]:
|
config.static_placement[player].update(vanilla_mapping)
|
||||||
|
if world.dropshuffle[player]:
|
||||||
for item, locs in keydrop_vanilla_mapping.items():
|
for item, locs in keydrop_vanilla_mapping.items():
|
||||||
if item in config.static_placement[player]:
|
|
||||||
config.static_placement[player][item].extend(locs)
|
config.static_placement[player][item].extend(locs)
|
||||||
else:
|
if world.pottery[player] != 'none':
|
||||||
config.static_placement[player][item] = list(locs)
|
for item, locs in potkeys_vanilla_mapping.items():
|
||||||
|
config.static_placement[player][item].extend(locs)
|
||||||
|
if world.pottery[player] == 'lottery':
|
||||||
|
for super_tile, pot_list in vanilla_pots.items():
|
||||||
|
for pot_index, pot in enumerate(pot_list):
|
||||||
|
if pot.item not in [PotItem.Key, PotItem.Hole, PotItem.Switch]:
|
||||||
|
item = pot_items[pot.item]
|
||||||
|
descriptor = 'Large Block' if pot.flags & PotFlags.Block else f'Pot #{pot_index+1}'
|
||||||
|
location = f'{pot.room} {descriptor}'
|
||||||
|
config.static_placement[player][item].append(location)
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
for item, locs in shop_vanilla_mapping.items():
|
for item, locs in shop_vanilla_mapping.items():
|
||||||
if item in config.static_placement[player]:
|
|
||||||
config.static_placement[player][item].extend(locs)
|
config.static_placement[player][item].extend(locs)
|
||||||
else:
|
|
||||||
config.static_placement[player][item] = list(locs)
|
|
||||||
if world.retro[player]:
|
if world.retro[player]:
|
||||||
for item, locs in retro_vanilla_mapping.items():
|
for item, locs in retro_vanilla_mapping.items():
|
||||||
if item in config.static_placement[player]:
|
|
||||||
config.static_placement[player][item].extend(locs)
|
config.static_placement[player][item].extend(locs)
|
||||||
else:
|
|
||||||
config.static_placement[player][item] = list(locs)
|
|
||||||
# universal keys
|
# universal keys
|
||||||
universal_key_locations = []
|
universal_key_locations = []
|
||||||
for item, locs in vanilla_mapping.items():
|
for item, locs in vanilla_mapping.items():
|
||||||
if 'Small Key' in item:
|
if 'Small Key' in item:
|
||||||
universal_key_locations.extend(locs)
|
universal_key_locations.extend(locs)
|
||||||
if world.keydropshuffle[player]:
|
if world.dropshuffle[player]:
|
||||||
for item, locs in keydrop_vanilla_mapping.items():
|
for item, locs in keydrop_vanilla_mapping.items():
|
||||||
if 'Small Key' in item:
|
if 'Small Key' in item:
|
||||||
universal_key_locations.extend(locs)
|
universal_key_locations.extend(locs)
|
||||||
|
if world.pottery[player] != 'none':
|
||||||
|
for item, locs in potkeys_vanilla_mapping.items():
|
||||||
|
universal_key_locations.extend(locs)
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
single_arrow_placement = list(shop_vanilla_mapping['Red Potion'])
|
single_arrow_placement = list(shop_vanilla_mapping['Red Potion'])
|
||||||
single_arrow_placement.append('Red Shield Shop - Right')
|
single_arrow_placement.append('Red Shield Shop - Right')
|
||||||
@@ -117,11 +124,11 @@ def create_item_pool_config(world):
|
|||||||
groups = LocationGroup('Major').locs(init_set)
|
groups = LocationGroup('Major').locs(init_set)
|
||||||
if world.bigkeyshuffle[player]:
|
if world.bigkeyshuffle[player]:
|
||||||
groups.locations.extend(mode_grouping['Big Keys'])
|
groups.locations.extend(mode_grouping['Big Keys'])
|
||||||
if world.keydropshuffle[player]:
|
if world.keydropshuffle[player] != 'none':
|
||||||
groups.locations.extend(mode_grouping['Big Key Drops'])
|
groups.locations.extend(mode_grouping['Big Key Drops'])
|
||||||
if world.keyshuffle[player]:
|
if world.keyshuffle[player]:
|
||||||
groups.locations.extend(mode_grouping['Small Keys'])
|
groups.locations.extend(mode_grouping['Small Keys'])
|
||||||
if world.keydropshuffle[player]:
|
if world.keydropshuffle[player] != 'none':
|
||||||
groups.locations.extend(mode_grouping['Key Drops'])
|
groups.locations.extend(mode_grouping['Key Drops'])
|
||||||
if world.compassshuffle[player]:
|
if world.compassshuffle[player]:
|
||||||
groups.locations.extend(mode_grouping['Compasses'])
|
groups.locations.extend(mode_grouping['Compasses'])
|
||||||
@@ -337,11 +344,11 @@ def calc_dungeon_limits(world, player):
|
|||||||
val -= 1
|
val -= 1
|
||||||
if b:
|
if b:
|
||||||
val += 1 if info.bk_present else 0
|
val += 1 if info.bk_present else 0
|
||||||
if k:
|
if k != 'none':
|
||||||
val += 1 if info.bk_drops else 0
|
val += 1 if info.bk_drops else 0
|
||||||
if s or r:
|
if s or r:
|
||||||
val += info.key_num
|
val += info.key_num
|
||||||
if k:
|
if k != 'none':
|
||||||
val += info.key_drops
|
val += info.key_drops
|
||||||
if c:
|
if c:
|
||||||
val += 1 if info.compass_present else 0
|
val += 1 if info.compass_present else 0
|
||||||
@@ -352,11 +359,11 @@ def calc_dungeon_limits(world, player):
|
|||||||
limits = 60
|
limits = 60
|
||||||
if world.bigkeyshuffle[player]:
|
if world.bigkeyshuffle[player]:
|
||||||
limits += 11
|
limits += 11
|
||||||
if world.keydropshuffle[player]:
|
if world.keydropshuffle[player] != 'none':
|
||||||
limits += 1
|
limits += 1
|
||||||
if world.keyshuffle[player] or world.retro[player]:
|
if world.keyshuffle[player] or world.retro[player]:
|
||||||
limits += 29
|
limits += 29
|
||||||
if world.keydropshuffle[player]:
|
if world.keydropshuffle[player] != 'none':
|
||||||
limits += 32
|
limits += 32
|
||||||
if world.compassshuffle[player]:
|
if world.compassshuffle[player]:
|
||||||
limits += 11
|
limits += 11
|
||||||
@@ -448,6 +455,19 @@ def filter_locations(item_to_place, locations, world, vanilla_skip=False):
|
|||||||
return locations
|
return locations
|
||||||
|
|
||||||
|
|
||||||
|
def filter_pot_locations(locations, world):
|
||||||
|
if world.algorithm == 'district':
|
||||||
|
config = world.item_pool_config
|
||||||
|
restricted = config.location_groups[0].locations
|
||||||
|
filtered = [l for l in locations if l.name not in restricted or l.player not in restricted[l.name]]
|
||||||
|
return filtered if len(filtered) > 0 else locations
|
||||||
|
if world.algorithm == 'vanilla_fill':
|
||||||
|
filtered = [l for l in locations if l.pot and l.pot.item in [PotItem.Chicken, PotItem.BigMagic]]
|
||||||
|
return filtered if len(filtered) > 0 else locations
|
||||||
|
return locations
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vanilla_mapping = {
|
vanilla_mapping = {
|
||||||
'Green Pendant': ['Eastern Palace - Prize'],
|
'Green Pendant': ['Eastern Palace - Prize'],
|
||||||
'Red Pendant': ['Desert Palace - Prize', 'Tower of Hera - Prize'],
|
'Red Pendant': ['Desert Palace - Prize', 'Tower of Hera - Prize'],
|
||||||
@@ -608,25 +628,31 @@ vanilla_mapping = {
|
|||||||
|
|
||||||
|
|
||||||
keydrop_vanilla_mapping = {
|
keydrop_vanilla_mapping = {
|
||||||
'Small Key (Desert Palace)': ['Desert Palace - Desert Tiles 1 Pot Key',
|
'Small Key (Eastern Palace)': ['Eastern Palace - Dark Eyegore Key Drop'],
|
||||||
'Desert Palace - Beamos Hall Pot Key', 'Desert Palace - Desert Tiles 2 Pot Key'],
|
|
||||||
'Small Key (Eastern Palace)': ['Eastern Palace - Dark Square Pot Key', 'Eastern Palace - Dark Eyegore Key Drop'],
|
|
||||||
'Small Key (Escape)': ['Hyrule Castle - Map Guard Key Drop', 'Hyrule Castle - Boomerang Guard Key Drop',
|
'Small Key (Escape)': ['Hyrule Castle - Map Guard Key Drop', 'Hyrule Castle - Boomerang Guard Key Drop',
|
||||||
'Hyrule Castle - Key Rat Key Drop'],
|
'Hyrule Castle - Key Rat Key Drop'],
|
||||||
'Big Key (Escape)': ['Hyrule Castle - Big Key Drop'],
|
'Big Key (Escape)': ['Hyrule Castle - Big Key Drop'],
|
||||||
'Small Key (Agahnims Tower)': ['Castle Tower - Dark Archer Key Drop', 'Castle Tower - Circle of Pots Key Drop'],
|
'Small Key (Agahnims Tower)': ['Castle Tower - Dark Archer Key Drop', 'Castle Tower - Circle of Pots Key Drop'],
|
||||||
|
'Small Key (Skull Woods)': ['Skull Woods - Spike Corner Key Drop'],
|
||||||
|
'Small Key (Ice Palace)': ['Ice Palace - Jelly Key Drop', 'Ice Palace - Conveyor Key Drop'],
|
||||||
|
'Small Key (Misery Mire)': ['Misery Mire - Conveyor Crystal Key Drop'],
|
||||||
|
'Small Key (Turtle Rock)': ['Turtle Rock - Pokey 1 Key Drop', 'Turtle Rock - Pokey 2 Key Drop'],
|
||||||
|
'Small Key (Ganons Tower)': ['Ganons Tower - Mini Helmasaur Key Drop'],
|
||||||
|
}
|
||||||
|
|
||||||
|
potkeys_vanilla_mapping = {
|
||||||
|
'Small Key (Desert Palace)': ['Desert Palace - Desert Tiles 1 Pot Key',
|
||||||
|
'Desert Palace - Beamos Hall Pot Key', 'Desert Palace - Desert Tiles 2 Pot Key'],
|
||||||
|
'Small Key (Eastern Palace)': ['Eastern Palace - Dark Square Pot Key'],
|
||||||
'Small Key (Thieves Town)': ["Thieves' Town - Hallway Pot Key", "Thieves' Town - Spike Switch Pot Key"],
|
'Small Key (Thieves Town)': ["Thieves' Town - Hallway Pot Key", "Thieves' Town - Spike Switch Pot Key"],
|
||||||
'Small Key (Skull Woods)': ['Skull Woods - West Lobby Pot Key', 'Skull Woods - Spike Corner Key Drop'],
|
'Small Key (Skull Woods)': ['Skull Woods - West Lobby Pot Key'],
|
||||||
'Small Key (Swamp Palace)': ['Swamp Palace - Pot Row Pot Key', 'Swamp Palace - Trench 1 Pot Key',
|
'Small Key (Swamp Palace)': ['Swamp Palace - Pot Row Pot Key', 'Swamp Palace - Trench 1 Pot Key',
|
||||||
'Swamp Palace - Hookshot Pot Key', 'Swamp Palace - Trench 2 Pot Key',
|
'Swamp Palace - Hookshot Pot Key', 'Swamp Palace - Trench 2 Pot Key',
|
||||||
'Swamp Palace - Waterway Pot Key'],
|
'Swamp Palace - Waterway Pot Key'],
|
||||||
'Small Key (Ice Palace)': ['Ice Palace - Jelly Key Drop', 'Ice Palace - Conveyor Key Drop',
|
'Small Key (Ice Palace)': ['Ice Palace - Hammer Block Key Drop', 'Ice Palace - Many Pots Pot Key'],
|
||||||
'Ice Palace - Hammer Block Key Drop', 'Ice Palace - Many Pots Pot Key'],
|
'Small Key (Misery Mire)': ['Misery Mire - Spikes Pot Key', 'Misery Mire - Fishbone Pot Key'],
|
||||||
'Small Key (Misery Mire)': ['Misery Mire - Spikes Pot Key',
|
|
||||||
'Misery Mire - Fishbone Pot Key', 'Misery Mire - Conveyor Crystal Key Drop'],
|
|
||||||
'Small Key (Turtle Rock)': ['Turtle Rock - Pokey 1 Key Drop', 'Turtle Rock - Pokey 2 Key Drop'],
|
|
||||||
'Small Key (Ganons Tower)': ['Ganons Tower - Conveyor Cross Pot Key', 'Ganons Tower - Double Switch Pot Key',
|
'Small Key (Ganons Tower)': ['Ganons Tower - Conveyor Cross Pot Key', 'Ganons Tower - Double Switch Pot Key',
|
||||||
'Ganons Tower - Conveyor Star Pits Pot Key', 'Ganons Tower - Mini Helmasuar Key Drop'],
|
'Ganons Tower - Conveyor Star Pits Pot Key'],
|
||||||
}
|
}
|
||||||
|
|
||||||
shop_vanilla_mapping = {
|
shop_vanilla_mapping = {
|
||||||
@@ -810,7 +836,9 @@ trash_items = {
|
|||||||
'Bombs (3)': 3,
|
'Bombs (3)': 3,
|
||||||
'Arrows (10)': 3,
|
'Arrows (10)': 3,
|
||||||
'Bombs (10)': 3,
|
'Bombs (10)': 3,
|
||||||
|
'Small Magic': 3,
|
||||||
|
|
||||||
|
'Big Magic': 4,
|
||||||
'Red Potion': 4,
|
'Red Potion': 4,
|
||||||
'Blue Shield': 4,
|
'Blue Shield': 4,
|
||||||
'Rupees (50)': 4,
|
'Rupees (50)': 4,
|
||||||
@@ -819,3 +847,17 @@ trash_items = {
|
|||||||
|
|
||||||
'Piece of Heart': 17
|
'Piece of Heart': 17
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pot_items = {
|
||||||
|
PotItem.Nothing: 'Nothing',
|
||||||
|
PotItem.Bomb: 'Single Bomb',
|
||||||
|
PotItem.FiveArrows: 'Arrows (5)', # convert to 10
|
||||||
|
PotItem.OneRupee: 'Rupee (1)',
|
||||||
|
PotItem.FiveRupees: 'Rupees (5)',
|
||||||
|
PotItem.Heart: 'Small Heart',
|
||||||
|
PotItem.BigMagic: 'Big Magic', # fast fill
|
||||||
|
PotItem.SmallMagic: 'Small Magic',
|
||||||
|
PotItem.Chicken: 'Chicken' # fast fill
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_pot_items = {y: x for x, y in pot_items.items()}
|
||||||
|
|||||||
Reference in New Issue
Block a user