15 Commits

10 changed files with 123 additions and 78 deletions

View File

@@ -164,6 +164,7 @@ class World(object):
set_player_attr('bigkeyshuffle', 'none')
set_player_attr('prizeshuffle', 'none')
set_player_attr('showloot', 'never')
set_player_attr('loothud', 'never')
set_player_attr('showmap', 'map')
set_player_attr('restrict_boss_items', 'none')
set_player_attr('bombbag', False)
@@ -202,6 +203,7 @@ class World(object):
set_player_attr('damage_challenge', 'normal')
set_player_attr('shuffle_damage_table', 'vanilla')
set_player_attr('crystal_book', False)
set_player_attr('extra_keys', 0)
set_player_attr('collection_rate', False)
set_player_attr('colorizepots', True)
set_player_attr('pot_pool', {})
@@ -1978,6 +1980,7 @@ class Dungeon(object):
self.prize = None
self.big_key = big_key
self.small_keys = small_keys
self.extra_small_keys = 0
self.dungeon_items = dungeon_items
self.bosses = dict()
self.player = player
@@ -3154,6 +3157,7 @@ class Spoiler(object):
'bigkeyshuffle': self.world.bigkeyshuffle,
'prizeshuffle': self.world.prizeshuffle,
'showloot': self.world.showloot,
'loothud': self.world.loothud,
'showmap': self.world.showmap,
'boss_shuffle': self.world.boss_shuffle,
'enemy_shuffle': self.world.enemy_shuffle,
@@ -3174,6 +3178,7 @@ class Spoiler(object):
'damage_challenge': self.world.damage_challenge,
'shuffle_damage_table': self.world.shuffle_damage_table,
'crystal_book': self.world.crystal_book,
'extra_keys': self.world.extra_keys,
'triforcegoal': self.world.treasure_hunt_count,
'triforcepool': self.world.treasure_hunt_total,
'race': self.world.settings.world_rep['meta']['race'],
@@ -3181,6 +3186,8 @@ class Spoiler(object):
'code': {p: Settings.make_code(self.world, p) for p in range(1, self.world.players + 1)},
'seed': self.world.seed
}
if self.hashes:
self.metadata['hash'] = {p: self.hashes[p, 0] for p in range(1, self.world.players + 1)} # TODO: make this work for multiple teams
for p in range(1, self.world.players + 1):
from ItemList import set_default_triforce
@@ -3427,6 +3434,7 @@ class Spoiler(object):
outfile.write('Big Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['bigkeyshuffle'][player])
outfile.write('Prize Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['prizeshuffle'][player])
outfile.write('Show Value of Checks:'.ljust(line_width) + '%s\n' % self.metadata['showloot'][player])
outfile.write('Show Value of Checks on HUD:'.ljust(line_width) + '%s\n' % self.metadata['loothud'][player])
outfile.write('Show Map:'.ljust(line_width) + '%s\n' % self.metadata['showmap'][player])
outfile.write('Key Logic Algorithm:'.ljust(line_width) + '%s\n' % self.metadata['key_logic'][player])
outfile.write('\n')
@@ -3453,6 +3461,7 @@ class Spoiler(object):
outfile.write('Damage Challenge:'.ljust(line_width) + '%s\n' % self.metadata['damage_challenge'][player])
outfile.write('Damage Table Randomization:'.ljust(line_width) + '%s\n' % self.metadata['shuffle_damage_table'][player])
outfile.write('Crystal Book:'.ljust(line_width) + '%s\n' % yn(self.metadata['crystal_book'][player]))
outfile.write('Extra Keys:'.ljust(line_width) + '%d%%\n' % self.metadata['extra_keys'][player])
outfile.write('Hints:'.ljust(line_width) + '%s\n' % yn(self.metadata['hints'][player]))
outfile.write('Race:'.ljust(line_width) + '%s\n' % yn(self.world.settings.world_rep['meta']['race']))

53
CLI.py
View File

@@ -153,31 +153,32 @@ def parse_cli(argv, no_defaults=False):
'crystals_ganon', 'crystals_gt', 'bosses_ganon',
'bosshunt_include_agas', 'ganon_item', 'openpyramid',
'mapshuffle', 'compassshuffle', 'keyshuffle',
'bigkeyshuffle', 'prizeshuffle', 'showloot', 'showmap',
'startinventory', 'usestartinventory', 'bombbag',
'shuffleganon', 'overworld_map', 'restrict_boss_items',
'triforce_max_difference', 'triforce_pool_min',
'triforce_pool_max', 'triforce_goal_min',
'triforce_goal_max', 'triforce_min_difference',
'triforce_goal', 'triforce_pool', 'shufflelinks',
'shuffletavern', 'skullwoods', 'linked_drops',
'pseudoboots', 'mirrorscroll', 'dark_rooms',
'damage_challenge', 'shuffle_damage_table',
'crystal_book', 'retro', 'accessibility', 'hints',
'beemizer', 'experimental', 'dungeon_counters',
'shufflebosses', 'shuffleenemies', 'enemy_health',
'enemy_damage', 'shufflepots', 'ow_palettes',
'uw_palettes', 'sprite', 'triforce_gfx', 'disablemusic',
'quickswap', 'fastmenu', 'heartcolor', 'heartbeep',
'remote_items', 'shopsanity', 'dropshuffle', 'pottery',
'keydropshuffle', 'mixed_travel',
'standardize_palettes', 'code', 'reduce_flashing',
'shuffle_sfx', 'shuffle_sfxinstruments',
'shuffle_songinstruments', 'msu_resume',
'collection_rate', 'colorizepots', 'decoupledoors',
'door_type_mode', 'bonk_drops', 'trap_door_mode',
'key_logic_algorithm', 'door_self_loops',
'any_enemy_logic', 'aga_randomness', 'money_balance']:
'bigkeyshuffle', 'prizeshuffle', 'showloot', 'loothud',
'showmap', 'startinventory', 'usestartinventory',
'bombbag', 'shuffleganon', 'overworld_map',
'restrict_boss_items', 'triforce_max_difference',
'triforce_pool_min', 'triforce_pool_max',
'triforce_goal_min', 'triforce_goal_max',
'triforce_min_difference', 'triforce_goal',
'triforce_pool', 'shufflelinks', 'shuffletavern',
'skullwoods', 'linked_drops', 'pseudoboots',
'mirrorscroll', 'dark_rooms', 'damage_challenge',
'shuffle_damage_table', 'crystal_book', 'extra_keys',
'retro', 'accessibility', 'hints', 'beemizer',
'experimental', 'dungeon_counters', 'shufflebosses',
'shuffleenemies', 'enemy_health', 'enemy_damage',
'shufflepots', 'ow_palettes', 'uw_palettes', 'sprite',
'triforce_gfx', 'disablemusic', 'quickswap', 'fastmenu',
'heartcolor', 'heartbeep', 'remote_items', 'shopsanity',
'dropshuffle', 'pottery', 'keydropshuffle',
'mixed_travel', 'standardize_palettes', 'code',
'reduce_flashing', 'shuffle_sfx',
'shuffle_sfxinstruments', 'shuffle_songinstruments',
'msu_resume', 'collection_rate', 'colorizepots',
'decoupledoors', 'door_type_mode', 'bonk_drops',
'trap_door_mode', 'key_logic_algorithm',
'door_self_loops', 'any_enemy_logic', 'aga_randomness',
'money_balance']:
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
if player == 1:
setattr(ret, name, {1: value})
@@ -254,6 +255,7 @@ def parse_settings():
"damage_challenge": "normal",
"shuffle_damage_table": "vanilla",
"crystal_book": False,
"extra_keys": 0,
"shuffleenemies": "none",
"shufflebosses": "none",
@@ -273,6 +275,7 @@ def parse_settings():
"bigkeyshuffle": "none",
"prizeshuffle": "none",
"showloot": "never",
"loothud": "never",
"showmap": "map",
"keysanity": False,
"door_shuffle": "vanilla",

View File

@@ -3,6 +3,7 @@ import time
from collections import defaultdict, deque
from enum import Flag, unique
from itertools import chain
from math import ceil
from typing import DefaultDict, Dict, List
import RaceRandom as random
@@ -1599,7 +1600,11 @@ def assign_cross_keys(dungeon_builders, world, player):
if actual_chest_keys == 0:
dungeon.small_keys = []
else:
dungeon.small_keys = [ItemFactory(dungeon_keys[name], player)] * actual_chest_keys
extra_keys = ceil(actual_chest_keys * world.extra_keys[player] / 100)
logger.debug(f'Adding {extra_keys} extra small keys to {name}')
dungeon.extra_small_keys = extra_keys
created_keys = actual_chest_keys + extra_keys
dungeon.small_keys = [ItemFactory(dungeon_keys[name], player)] * created_keys
logger.info(f'{world.fish.translate("cli", "cli", "keydoor.shuffle.time.crossed")}: {time.process_time()-start}')
@@ -2171,7 +2176,10 @@ def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, all_
if actual_chest_keys == 0:
dungeon.small_keys = []
else:
dungeon.small_keys = [ItemFactory(dungeon_keys[dungeon_name], player) for _ in range(actual_chest_keys)]
extra_keys = ceil(actual_chest_keys * world.extra_keys[player] / 100)
dungeon.extra_small_keys = extra_keys
created_keys = actual_chest_keys + extra_keys
dungeon.small_keys = [ItemFactory(dungeon_keys[dungeon_name], player) for _ in range(created_keys)]
for name, small_list in small_map.items():
used_doors.update(flatten_pair_list(small_list))

View File

@@ -516,6 +516,7 @@ def init_world(args, fish):
world.bigkeyshuffle = args.bigkeyshuffle.copy()
world.prizeshuffle = args.prizeshuffle.copy()
world.showloot = args.showloot.copy()
world.loothud = args.loothud.copy()
world.showmap = args.showmap.copy()
world.bombbag = args.bombbag.copy()
world.flute_mode = args.flute_mode.copy()
@@ -564,6 +565,7 @@ def init_world(args, fish):
world.damage_challenge = args.damage_challenge.copy()
world.shuffle_damage_table = args.shuffle_damage_table.copy()
world.crystal_book = args.crystal_book.copy()
world.extra_keys = {player: int(args.extra_keys[player]) for player in range(1, world.players + 1)}
world.overworld_map = args.overworld_map.copy()
world.take_any = args.take_any.copy()
world.restrict_boss_items = args.restrict_boss_items.copy()
@@ -836,6 +838,7 @@ def copy_world(world):
ret.bigkeyshuffle = world.bigkeyshuffle.copy()
ret.prizeshuffle = world.prizeshuffle.copy()
ret.showloot = world.showloot.copy()
ret.loothud = world.loothud.copy()
ret.showmap = world.showmap.copy()
ret.bombbag = world.bombbag.copy()
ret.flute_mode = world.flute_mode.copy()
@@ -868,6 +871,7 @@ def copy_world(world):
ret.damage_challenge = world.damage_challenge.copy()
ret.shuffle_damage_table = world.shuffle_damage_table.copy()
ret.crystal_book = world.crystal_book.copy()
ret.extra_keys = world.extra_keys.copy()
ret.overworld_map = world.overworld_map.copy()
ret.take_any = world.take_any.copy()
ret.boss_shuffle = world.boss_shuffle.copy()
@@ -1068,6 +1072,7 @@ def copy_world_premature(world, player, create_flute_exits=True):
ret.bigkeyshuffle = world.bigkeyshuffle.copy()
ret.prizeshuffle = world.prizeshuffle.copy()
ret.showloot = world.showloot.copy()
ret.loothud = world.loothud.copy()
ret.showmap = world.showmap.copy()
ret.bombbag = world.bombbag.copy()
ret.flute_mode = world.flute_mode.copy()
@@ -1100,6 +1105,7 @@ def copy_world_premature(world, player, create_flute_exits=True):
ret.damage_challenge = world.damage_challenge.copy()
ret.shuffle_damage_table = world.shuffle_damage_table.copy()
ret.crystal_book = world.crystal_book.copy()
ret.extra_keys = world.extra_keys.copy()
ret.overworld_map = world.overworld_map.copy()
ret.take_any = world.take_any.copy()
ret.boss_shuffle = world.boss_shuffle.copy()

82
Rom.py
View File

@@ -85,7 +85,7 @@ from Utils import int16_as_bytes, int32_as_bytes, local_path, snes_to_pc
from Versions import DRVersion, GKVersion, ORVersion
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '8945e9fdcefc02eb3ff3ad2a8892a180'
RANDOMIZERBASEHASH = 'd5b351a79bab079408bdf19b0deaa655'
class JsonRom(object):
@@ -818,11 +818,13 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
rom.write_byte(0x138002, 2)
for name, layout in world.key_layout[player].items():
offset = compass_data[name][4]//2
dungeon = world.get_dungeon(name, player)
if world.keyshuffle[player] == 'universal':
rom.write_byte(0x187010+offset, layout.max_chests + layout.max_drops)
else:
rom.write_byte(0x13f020+offset, layout.max_chests + layout.max_drops) # not currently used
rom.write_byte(0x187010+offset, layout.max_chests)
rom.write_byte(0x13f020+offset, layout.max_chests + layout.max_drops + dungeon.extra_small_keys) # not currently used
rom.write_byte(0x187010+offset, layout.max_chests + dungeon.extra_small_keys)
rom.write_byte(0x187000+offset, dungeon.extra_small_keys)
builder = world.dungeon_layouts[player][name]
bk_status = 1 if builder.bk_required else 0
bk_status = 2 if builder.bk_provided else bk_status
@@ -1501,9 +1503,22 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
loot_source |= 0x04
rom.write_byte(0x1CFF10, loot_source)
if world.loothud[player] == 'never':
rom.write_byte(0x1CFF12, 0x00)
elif world.loothud[player] == 'presence':
rom.write_byte(0x1CFF12, 0x01)
rom.write_bytes(0x1CFF0E, [0x01, 0x01])
elif world.loothud[player] == 'value':
rom.write_byte(0x1CFF12, 0x01)
rom.write_bytes(0x1CFF0E, [0xFF, 0xFF])
elif world.loothud[player] == 'dungeon_value':
rom.write_byte(0x1CFF12, 0x01)
rom.write_bytes(0x1CFF0E, [0xFF, 0x01])
if world.showloot[player] == 'never':
rom.write_bytes(0x1CFF08, [0x00, 0x00, 0x00, 0x00])
rom.write_byte(0x1CFF11, 0x00)
rom.write_byte(0x1CFF12, 0x00) # turn off hud icon too just to be safe
elif world.showloot[player] == 'presence':
rom.write_bytes(0x1CFF08, [0x01, 0x00, 0x00, 0x00])
rom.write_byte(0x1CFF11, 0x00)
@@ -1773,44 +1788,30 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
rom.write_bytes(0x6D2FB, [0x00, 0x00, 0xf7, 0xff, 0x02, 0x0E])
rom.write_bytes(0x6D313, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
rom.write_byte(0x18004E, 0) # Escape Fill (nothing)
write_int16(rom, 0x180183, 300) # Escape fill rupee bow
rom.write_bytes(0x180185, [0, 0, 0]) # Uncle respawn refills (magic, bombs, arrows)
rom.write_bytes(0x180188, [0, 0, 0]) # Zelda respawn refills (magic, bombs, arrows)
rom.write_bytes(0x18018B, [0, 0, 0]) # Mantle respawn refills (magic, bombs, arrows)
bow_max, bomb_max, magic_max = 0, 0, 0
bow_small, bomb_small, magic_small = 10, 3, 0x20
write_int16(rom, 0x180183, 0) # Escape fill rupee bow
# Uncle / Zelda / Mantle respawn refills (magic, bombs, arrows)
rom.write_bytes(0x180185, [0] * 9)
if world.mode[player] == 'standard':
if world.doorShuffle[player] not in ['vanilla']:
# If door shuffle, give player small bit of all three ammos on respawn during escape
# Uncle / Zelda / Mantle respawn refills (magic, bombs, arrows)
rom.write_bytes(0x180185, [0x20, 3, 10] * 3)
# Always fully fill ammo of starting weapon on respawn during escape
if uncle_location.item is not None and uncle_location.item.name in ['Bow', 'Progressive Bow']:
rom.write_byte(0x18004E, 1) # Escape Fill (arrows)
write_int16(rom, 0x180183, 300) # Escape fill rupee bow
rom.write_bytes(0x180185, [0, 0, 70]) # Uncle respawn refills (magic, bombs, arrows)
rom.write_bytes(0x180188, [0, 0, 70]) # Zelda respawn refills (magic, bombs, arrows)
rom.write_bytes(0x18018B, [0, 0, 70]) # Mantle respawn refills (magic, bombs, arrows)
bow_max = 70
rom.write_byte(0x180187, 70) # Uncle respawn refill arrows
rom.write_byte(0x18018A, 70) # Zelda respawn refill arrows
rom.write_byte(0x18018D, 70) # Mantle respawn refill arrowss
elif uncle_location.item is not None and uncle_location.item.name in ['Bomb Upgrade (+10)' if world.bombbag[player] else 'Bombs (10)']:
rom.write_byte(0x18004E, 2) # Escape Fill (bombs)
rom.write_bytes(0x180185, [0, 50, 0]) # Uncle respawn refills (magic, bombs, arrows)
rom.write_bytes(0x180188, [0, 50, 0]) # Zelda respawn refills (magic, bombs, arrows)
rom.write_bytes(0x18018B, [0, 50, 0]) # Mantle respawn refills (magic, bombs, arrows)
bomb_max = 50
rom.write_byte(0x180186, 50) # Uncle respawn refill bombs
rom.write_byte(0x180189, 50) # Zelda respawn refill bombs
rom.write_byte(0x18018C, 50) # Mantle respawn refill bombs
elif uncle_location.item is not None and uncle_location.item.name in ['Cane of Somaria', 'Cane of Byrna', 'Fire Rod']:
rom.write_byte(0x18004E, 4) # Escape Fill (magic)
rom.write_bytes(0x180185, [0x80, 0, 0]) # Uncle respawn refills (magic, bombs, arrows)
rom.write_bytes(0x180188, [0x80, 0, 0]) # Zelda respawn refills (magic, bombs, arrows)
rom.write_bytes(0x18018B, [0x80, 0, 0]) # Mantle respawn refills (magic, bombs, arrows)
magic_max = 0x80
if world.doorShuffle[player] not in ['vanilla', 'basic']:
# Uncle respawn refills (magic, bombs, arrows)
rom.write_bytes(0x180185, [max(magic_small, magic_max), max(bomb_small, bomb_max), max(bow_small, bow_max)])
# Zelda respawn refills (magic, bombs, arrows)
rom.write_bytes(0x180188, [max(magic_small, magic_max), max(bomb_small, bomb_max), max(bow_small, bow_max)])
# Mantle respawn refills (magic, bombs, arrows)
rom.write_bytes(0x18018B, [max(magic_small, magic_max), max(bomb_small, bomb_max), max(bow_small, bow_max)])
elif world.doorShuffle[player] == 'basic': # just in case a bomb is needed to get to a chest
rom.write_bytes(0x180185, [max(magic_small, magic_max), max(bomb_small, bomb_max), max(bow_small, bow_max)])
rom.write_bytes(0x180188, [magic_small, max(bomb_small, bomb_max), bow_small]) # Zelda respawn refills (magic, bombs, arrows)
rom.write_bytes(0x18018B, [magic_small, max(bomb_small, bomb_max), bow_small]) # Mantle respawn refills (magic, bombs, arrows)
rom.write_byte(0x180185, 0x80) # Uncle respawn refill magic
rom.write_byte(0x180188, 0x80) # Zelda respawn refill magic
rom.write_byte(0x18018B, 0x80) # Mantle respawn refill magic
# patch swamp: Need to enable permanent drain of water as dam or swamp were moved
rom.write_byte(0x18003D, 0x01 if world.swamp_patch_required[player] else 0x00)
@@ -3526,7 +3527,10 @@ Prizes = ['Green Pendant',
]
hash_alphabet = [
"Bow", "Boomerang", "Hookshot", "Bomb", "Mushroom", "Powder", "Rod", "Pendant", "Bombos", "Ether", "Quake",
"Lamp", "Hammer", "Shovel", "Ocarina", "Bug Net", "Book", "Bottle", "Potion", "Cane", "Cape", "Mirror", "Boots",
"Gloves", "Flippers", "Pearl", "Shield", "Tunic", "Heart", "Map", "Compass", "Key"
"Bow", "Boomerang", "Hookshot", "Bomb", "Mushroom", "Powder",
"Ice Rod", "Green Pendant", "Bombos", "Ether", "Quake", "Lamp",
"Hammer", "Shovel", "Ocarina", "Bug Net", "Book", "Bottle",
"Green Potion", "Somaria", "Cape", "Mirror", "Boots", "Gloves",
"Flippers", "Pearl", "Shield", "Green Tunic", "Heart", "Map",
"Compass", "Key",
]

Binary file not shown.

View File

@@ -486,6 +486,14 @@
"always"
]
},
"loothud": {
"choices": [
"never",
"presence",
"value",
"dungeon_value"
]
},
"showmap": {
"choices": [
"visited",
@@ -665,6 +673,9 @@
"action": "store_true",
"type": "bool"
},
"extra_keys": {
"type": "int"
},
"calc_playthrough": {
"action": "store_false",
"type": "bool"

View File

@@ -425,6 +425,7 @@
"AlwaysInLogic: Dark rooms are always considered to be in logic, even if the player cannot see"
],
"crystal_book": [ " Book can be used indoors to flip the state of colored pegs (default: %(default)s)"],
"extra_keys": [ " Percentage of extra small keys to create for each dungeon when door shuffle is enabled (default: %(default)s)"],
"bombbag": ["Start with 0 bomb capacity. Two capacity upgrades (+10) are added to the pool (default: %(default)s)" ],
"any_enemy_logic": [
"How to handle potential traversal between dungeon in Crossed door shuffle",

View File

@@ -84,7 +84,10 @@ UwGeneralDeny:
- [ 0x0039, 4, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "FirebarCW", "FirebarCCW" ] ] #"Skull Woods - Play Pen - Spike Trap 1"
- [0x0039, 5, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "Bumper", "AntiFairyCircle"]] #"Skull Woods - Play Pen - Hardhat Beetle"
- [ 0x0039, 6, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "FirebarCW", "FirebarCCW" ] ] #"Skull Woods - Play Pen - Spike Trap 2"
- [0x003a, 1, ["RollerVerticalUp", "RollerVerticalDown"]]
- [ 0x003a, 0, ["RollerVerticalUp", "RollerVerticalDown"]]
- [ 0x003a, 1, ["RollerVerticalUp", "RollerVerticalDown"]]
- [ 0x003a, 3, ["RollerHorizontalLeft", "RollerHorizontalRight"]]
- [ 0x003a, 4, ["RollerHorizontalLeft", "RollerHorizontalRight"]]
- [ 0x003b, 1, [ "Bumper", "AntiFairyCircle" ]]
- [ 0x003b, 4, ["RollerVerticalUp", "RollerVerticalDown"]]
- [ 0x003c, 0, ["BigSpike"]]
@@ -339,11 +342,11 @@ UwGeneralDeny:
- [ 0x00c2, 5, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
- [ 0x00c5, 6, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Turtle Rock - Catwalk - Mini Helmasaur"
- [ 0x00c5, 7, [ "Statue" ] ] #"Turtle Rock - Catwalk - Laser Eye (Left) 4"
- [0x00c6, 2, ["Bumper", "AntiFairyCircle"]]
- [0x00c6, 3, ["Bumper", "AntiFairyCircle"]]
- [0x00c6, 4, ["Bumper", "AntiFairyCircle"]]
- [0x00c6, 5, ["Bumper", "AntiFairyCircle"]]
- [0x00c6, 6, ["Bumper", "AntiFairyCircle"]]
- [ 0x00c6, 2, ["Bumper", "AntiFairyCircle", "BigSpike" ]]
- [ 0x00c6, 3, ["Bumper", "AntiFairyCircle", "BigSpike" ]]
- [ 0x00c6, 4, ["Bumper", "AntiFairyCircle", "BigSpike" ]]
- [ 0x00c6, 5, ["Bumper", "AntiFairyCircle", "BigSpike" ]]
- [ 0x00c6, 6, ["Bumper", "AntiFairyCircle", "BigSpike" ]]
- [ 0x00cb, 0, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
- [ 0x00cb, 3, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Thieves' Town - Grand Room NW - Zol 1"
- [ 0x00cb, 5, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Thieves' Town - Grand Room NW - Zol 2"

View File

@@ -58,17 +58,17 @@ class DataTables:
self.bush_sprite_table = {}
# enemizer conditions
self.uw_enemy_denials = {}
self.ow_enemy_denials = {}
self.uw_enemy_drop_denials = {}
self.uw_enemy_denials = defaultdict(set)
self.ow_enemy_denials = defaultdict(set)
self.uw_enemy_drop_denials = defaultdict(set)
self.sheet_choices = []
denial_data = load_cached_yaml(['source', 'enemizer', 'enemy_deny.yaml'])
for denial in denial_data['UwGeneralDeny']:
self.uw_enemy_denials[denial[0], denial[1]] = {sprite_translation[x] for x in denial[2]}
self.uw_enemy_denials[denial[0], denial[1]] |= {sprite_translation[x] for x in denial[2]}
for denial in denial_data['OwGeneralDeny']:
self.ow_enemy_denials[denial[0], denial[1]] = {sprite_translation[x] for x in denial[2]}
self.ow_enemy_denials[denial[0], denial[1]] |= {sprite_translation[x] for x in denial[2]}
for denial in denial_data['UwEnemyDrop']:
self.uw_enemy_drop_denials[denial[0], denial[1]] = {sprite_translation[x] for x in denial[2]}
self.uw_enemy_drop_denials[denial[0], denial[1]] |= {sprite_translation[x] for x in denial[2]}
weights = load_cached_yaml(['source', 'enemizer', 'enemy_weight.yaml'])
self.uw_weights = {sprite_translation[k]: v for k, v in weights['UW'].items()}
self.ow_weights = {sprite_translation[k]: v for k, v in weights['OW'].items()}