UW Enemizer work

Refinements for data table support
This commit is contained in:
aerinon
2022-09-27 14:40:43 -06:00
parent 037a9479d8
commit 3c0f6ca0e6
13 changed files with 128 additions and 105 deletions

View File

@@ -87,7 +87,7 @@ class World(object):
self._portal_cache = {}
self.sanc_portal = {}
self.fish = BabelFish()
self.pot_contents = {}
self.data_tables = {}
for player in range(1, players + 1):
def set_player_attr(attr, val):
@@ -151,6 +151,7 @@ class World(object):
set_player_attr('exp_cache', defaultdict(dict))
set_player_attr('enabled_entrances', {})
set_player_attr('data_tables', None)
def finish_init(self):
for player in range(1, self.players + 1):
@@ -393,7 +394,7 @@ class World(object):
item.location = location
item.world = self
if location.player != item.player and location.type == LocationType.Pot:
self.pot_contents[location.player].multiworld_count += 1
self.data_tables[location.player].pot_secret_table.multiworld_count += 1
if collect:
self.state.collect(item, location.event, location)
@@ -2136,6 +2137,7 @@ class Location(object):
self.skip = False
self.type = LocationType.Normal if not crystal else LocationType.Prize
self.pot = None
self.drop = None
def can_fill(self, state, item, check_access=True):
if not self.valid_multiworld(state, item):
@@ -2144,7 +2146,7 @@ class Location(object):
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 state.world.data_tables[self.player].pot_secret_table.multiworld_count < 256
return True
def can_reach(self, state):

View File

@@ -581,7 +581,7 @@ def fast_fill_pot_for_multiworld(world, item_pool, 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
flex = 256 - world.data_tables[player].pot_secret_table.multiworld_count
fill_count = len(pot_fill_locations[player]) - flex
if fill_count > 0:
fill_spots = random.sample(pot_fill_locations[player], fill_count)

View File

@@ -32,6 +32,8 @@ from source.item.FillUtil import create_item_pool_config, massage_item_pool, dis
from source.overworld.EntranceShuffle2 import link_entrances_new
from source.tools.BPS import create_bps_from_data
from source.classes.CustomSettings import CustomSettings
from source.rom.DataTables import init_data_tables
__version__ = '1.0.1.3-x'
@@ -186,6 +188,7 @@ def main(args, seed=None, fish=None):
create_doors(world, player)
create_rooms(world, player)
create_dungeons(world, player)
world.data_tables[player] = init_data_tables(world, player)
adjust_locations(world, player)
place_bosses(world, player)

View File

@@ -919,14 +919,14 @@ def shuffle_pots(world, player):
new_pot_contents.room_map[super_tile] = new_pots
world.pot_contents[player] = new_pot_contents
world.data_tables[player].pot_secret_table = 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]
new_pots = world.data_tables[player].pot_secret_table.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)

View File

@@ -3,6 +3,8 @@ from Items import ItemFactory
from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType, LocationType, PotItem, PotFlags
from PotShuffle import key_drop_data, vanilla_pots, choose_pots, PotSecretTable
from source.dungeon.EnemyList import setup_enemy_locations
def create_regions(world, player):
world.regions += [
@@ -1005,7 +1007,7 @@ def create_shops(world, player):
def adjust_locations(world, player):
# handle pots
world.pot_contents[player] = PotSecretTable()
world.data_tables[player].pot_secret_table = PotSecretTable()
for location, datum in key_drop_data.items():
loc = world.get_location(location, player)
drop_location = 'Drop' == datum[0]
@@ -1013,6 +1015,7 @@ def adjust_locations(world, player):
loc.type = LocationType.Drop
snes_address, room, sprite_idx = datum[1]
loc.address = snes_address
world.data_tables[player].uw_enemy_table.room_map[room][sprite_idx].location = loc
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)
@@ -1044,7 +1047,7 @@ def adjust_locations(world, player):
pot = world.get_location(loc, player).pot
else:
pot = pot_orig.copy()
world.pot_contents[player].room_map[super_tile].append(pot)
world.data_tables[player].pot_secret_table.room_map[super_tile].append(pot)
if valid_pot_location(pot, world.pot_pool[player], world, player):
create_pot_location(pot, pot_index, super_tile, world, player)
@@ -1057,6 +1060,7 @@ def adjust_locations(world, player):
loc.type = LocationType.Shop
# player address? it is in the shop table
index += 1
setup_enemy_locations(world, player)
# unreal events:
for l in ['Ganon', 'Agahnim 1', 'Agahnim 2', 'Dark Blacksmith Ruins', 'Frog', 'Missing Smith', 'Floodgate',
'Trench 1 Switch', 'Trench 2 Switch', 'Swamp Drain', 'Attic Cracked Floor', 'Suspicious Maiden',
@@ -1180,7 +1184,7 @@ flooded_keys_reverse = {
'Swamp Palace - Trench 2 Pot Key': 'Trench 2 Switch'
}
lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int}
location_table = {'Mushroom': (0x180013, 0x186df8, False, 'in the woods'),
'Bottle Merchant': (0x2eb18, 0x186df9, False, 'with a merchant'),
'Flute Spot': (0x18014a, 0x186dfd, False, 'underground'),
@@ -1457,6 +1461,7 @@ location_table = {'Mushroom': (0x180013, 0x186df8, False, 'in the woods'),
'Potion Shop - Middle': (None, None, False, 'for sale near potions'),
'Potion Shop - Right': (None, None, False, 'for sale near potions'),
}
lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int}
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.update(shop_table_by_location)

15
Rom.py
View File

@@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '61c296effe6180274721d570d2471e1c'
RANDOMIZERBASEHASH = '0587709ac8c5f2abf95b14d1e1264945'
class JsonRom(object):
@@ -1539,20 +1539,11 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
if room.player == player and room.modified:
rom.write_bytes(room.address(), room.rom_data())
if world.pottery[player] not in ['none']:
rom.write_bytes(snes_to_pc(0x1F8375), int32_as_bytes(0x2B8000))
# make hammer pegs use different tiles
Room0127.write_to_rom(snes_to_pc(0x2B8000), rom)
if world.pot_contents[player]:
if world.data_tables[player]:
colorize_pots = is_mystery or (world.pottery[player] not in ['vanilla', 'lottery']
and (world.colorizepots[player]
or world.pottery[player] in ['reduced', 'clustered']))
if world.pot_contents[player].size() > 0x11c0:
raise Exception('Pot table is too big for current area')
world.pot_contents[player].write_pot_data_to_rom(rom, colorize_pots)
# todo: write sprites
world.data_tables[player].write_to_rom(rom)
write_strings(rom, world, player, team)

View File

@@ -14,6 +14,11 @@ def int16_as_bytes(value):
return [value & 0xFF, (value >> 8) & 0xFF]
def int24_as_bytes(value):
value = value & 0xFFFFFF
return [value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF]
def int32_as_bytes(value):
value = value & 0xFFFFFFFF
return [value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF, (value >> 24) & 0xFF]

Binary file not shown.

View File

@@ -542,21 +542,21 @@ def init_vanilla_sprites():
create_sprite(0x0004, EnemySprite.Blob, 0x00, 0, 0x1a, 0x1a, 'TR Tongue Pull')
create_sprite(0x0004, EnemySprite.Blob, 0x00, 0, 0x15, 0x1b, 'TR Tongue Pull')
create_sprite(0x0004, EnemySprite.Pokey, 0x00, 0, 0x07, 0x18, 'TR Dash Room')
create_sprite(0x0006, EnemySprite.Arrghus, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x17)
create_sprite(0x0007, EnemySprite.Moldorm, 0x00, 0, 0x12, 0x0e)
create_sprite(0x0006, EnemySprite.Arrghus, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0006, EnemySprite.Arrghi, 0x00, 0, 0x07, 0x07)
create_sprite(0x0007, EnemySprite.Moldorm, 0x00, 0, 0x9, 0x09)
create_sprite(0x0008, EnemySprite.BigFairy, 0x00, 0, 0x07, 0x16)
create_sprite(0x0009, EnemySprite.Medusa, 0x00, 0, 0x07, 0x08)
create_sprite(0x0009, EnemySprite.Medusa, 0x00, 0, 0x08, 0x08)
@@ -660,13 +660,13 @@ def init_vanilla_sprites():
create_sprite(0x001b, EnemySprite.RedEyegoreMimic, 0x00, 0, 0x07, 0x14, 'PoD Mimics 2')
create_sprite(0x001b, EnemySprite.GreenEyegoreMimic, 0x00, 0, 0x03, 0x1c, 'PoD Mimics 2')
create_sprite(0x001b, EnemySprite.GreenEyegoreMimic, 0x00, 0, 0x0c, 0x1c, 'PoD Mimics 2')
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x14, 0x15)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x17, 0x15)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x1a, 0x15)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x1a, 0x18)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x17, 0x18)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x14, 0x18)
create_sprite(0x001c, 0x19, SpriteType.Overlord, 0, 0x17, 0x18)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x04, 0x05)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x07, 0x05)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x0a, 0x05)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x0a, 0x08)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x07, 0x08)
create_sprite(0x001c, EnemySprite.ArmosKnight, 0x00, 0, 0x04, 0x08)
create_sprite(0x001c, 0x19, SpriteType.Overlord, 0, 0x07, 0x08)
create_sprite(0x001c, EnemySprite.Faerie, 0x00, 0, 0x07, 0x07)
create_sprite(0x001c, EnemySprite.Faerie, 0x00, 0, 0x08, 0x07)
create_sprite(0x001c, EnemySprite.Faerie, 0x00, 0, 0x07, 0x08)
@@ -741,7 +741,7 @@ def init_vanilla_sprites():
create_sprite(0x0028, EnemySprite.Hover, 0x00, 0, 0x0b, 0x0a, 'Swamp Entrance')
create_sprite(0x0028, EnemySprite.Hover, 0x00, 0, 0x07, 0x0d, 'Swamp Entrance')
create_sprite(0x0028, EnemySprite.SpikeBlock, 0x00, 0, 0x08, 0x10, 'Swamp Entrance')
create_sprite(0x0029, EnemySprite.Mothula, 0x00, 0, 0x18, 0x16)
create_sprite(0x0029, EnemySprite.Mothula, 0x00, 0, 0x08, 0x06)
create_sprite(0x0029, 0x07, SpriteType.Overlord, 0, 0x07, 0x16)
create_sprite(0x002a, EnemySprite.CrystalSwitch, 0x00, 0, 0x10, 0x17, 'PoD Arena Main')
create_sprite(0x002a, EnemySprite.Bumper, 0x00, 0, 0x0f, 0x0f, 'PoD Arena Main')
@@ -787,9 +787,9 @@ def init_vanilla_sprites():
create_sprite(0x0032, EnemySprite.Keese, 0x00, 0, 0x13, 0x0d, 'Sewers Dark Cross')
create_sprite(0x0032, EnemySprite.Snake, 0x00, 0, 0x10, 0x0e, 'Sewers Dark Cross')
create_sprite(0x0032, EnemySprite.Snake, 0x00, 0, 0x12, 0x0f, 'Sewers Dark Cross')
create_sprite(0x0033, EnemySprite.Lanmolas, 0x00, 0, 0x06, 0x17)
create_sprite(0x0033, EnemySprite.Lanmolas, 0x00, 0, 0x09, 0x17)
create_sprite(0x0033, EnemySprite.Lanmolas, 0x00, 0, 0x07, 0x19)
create_sprite(0x0033, EnemySprite.Lanmolas, 0x00, 0, 0x06, 0x07)
create_sprite(0x0033, EnemySprite.Lanmolas, 0x00, 0, 0x09, 0x07)
create_sprite(0x0033, EnemySprite.Lanmolas, 0x00, 0, 0x07, 0x09)
create_sprite(0x0034, EnemySprite.Hover, 0x00, 0, 0x0f, 0x0b, 'Swamp West Shallows')
create_sprite(0x0034, EnemySprite.Hover, 0x00, 0, 0x10, 0x12, 'Swamp West Shallows')
create_sprite(0x0034, EnemySprite.Kyameron, 0x00, 0, 0x0f, 0x15, 'Swamp West Shallows')
@@ -965,7 +965,7 @@ def init_vanilla_sprites():
create_sprite(0x004c, EnemySprite.MiniHelmasaur, 0x00, 0, 0x18, 0x0a, 'GT Frozen Over')
create_sprite(0x004c, EnemySprite.MiniHelmasaur, 0x00, 0, 0x14, 0x15, 'GT Frozen Over')
create_sprite(0x004c, EnemySprite.SpikeBlock, 0x00, 0, 0x13, 0x18, 'GT Frozen Over')
create_sprite(0x004d, EnemySprite.Moldorm, 0x00, 0, 0x0e, 0x0e)
create_sprite(0x004d, EnemySprite.Moldorm, 0x00, 0, 0x09, 0x09)
create_sprite(0x004e, EnemySprite.Blob, 0x00, 0, 0x14, 0x08, 'Ice Narrow Corridor')
create_sprite(0x004e, EnemySprite.Blob, 0x00, 0, 0x16, 0x08, 'Ice Narrow Corridor')
create_sprite(0x004e, EnemySprite.Blob, 0x00, 0, 0x18, 0x08, 'Ice Narrow Corridor')
@@ -1056,7 +1056,7 @@ def init_vanilla_sprites():
create_sprite(0x0059, EnemySprite.Gibdo, 0x00, 0, 0x17, 0x14, 'Skull East Bridge')
create_sprite(0x0059, EnemySprite.Gibdo, 0x00, 1, 0x15, 0x15, 'Skull East Bridge')
create_sprite(0x0059, EnemySprite.Gibdo, 0x00, 1, 0x1a, 0x15, 'Skull East Bridge')
create_sprite(0x005a, EnemySprite.HelmasaurKing, 0x00, 0, 0x17, 0x16)
create_sprite(0x005a, EnemySprite.HelmasaurKing, 0x00, 0, 0x07, 0x06)
create_sprite(0x005b, EnemySprite.CrystalSwitch, 0x00, 1, 0x17, 0x0c)
create_sprite(0x005b, EnemySprite.CrystalSwitch, 0x00, 1, 0x18, 0x13)
create_sprite(0x005b, EnemySprite.SpikeBlock, 0x00, 1, 0x17, 0x15, 'GT Hidden Spikes')
@@ -1169,9 +1169,9 @@ def init_vanilla_sprites():
create_sprite(0x006b, EnemySprite.Beamos, 0x00, 0, 0x1b, 0x15, 'GT Mimics 2')
create_sprite(0x006b, EnemySprite.Beamos, 0x00, 0, 0x14, 0x1b, 'GT Mimics 2')
create_sprite(0x006b, EnemySprite.RedEyegoreMimic, 0x00, 0, 0x18, 0x1b, 'GT Mimics 2')
create_sprite(0x006c, EnemySprite.Lanmolas, 0x00, 0, 0x06, 0x17, 'GT Lanmolas 2')
create_sprite(0x006c, EnemySprite.Lanmolas, 0x00, 0, 0x09, 0x17, 'GT Lanmolas 2')
create_sprite(0x006c, EnemySprite.Lanmolas, 0x00, 0, 0x07, 0x19, 'GT Lanmolas 2')
create_sprite(0x006c, EnemySprite.Lanmolas, 0x00, 0, 0x06, 0x07, 'GT Lanmolas 2')
create_sprite(0x006c, EnemySprite.Lanmolas, 0x00, 0, 0x09, 0x07, 'GT Lanmolas 2')
create_sprite(0x006c, EnemySprite.Lanmolas, 0x00, 0, 0x07, 0x09, 'GT Lanmolas 2')
create_sprite(0x006c, EnemySprite.BunnyBeam, 0x00, 0, 0x17, 0x18, 'GT Beam Dash')
create_sprite(0x006c, EnemySprite.Medusa, 0x00, 0, 0x03, 0x1c, 'GT Lanmolas 2')
create_sprite(0x006d, EnemySprite.RedZazak, 0x00, 0, 0x05, 0x06, 'GT Gauntlet 4')
@@ -1369,7 +1369,7 @@ def init_vanilla_sprites():
create_sprite(0x008e, EnemySprite.Blob, 0x00, 0, 0x16, 0x0a, 'Ice Lonely Freezor')
create_sprite(0x008e, EnemySprite.Blob, 0x00, 0, 0x14, 0x0b, 'Ice Lonely Freezor')
create_sprite(0x008e, EnemySprite.Blob, 0x00, 0, 0x18, 0x0b, 'Ice Lonely Freezor')
create_sprite(0x0090, EnemySprite.Vitreous, 0x00, 0, 0x07, 0x15)
create_sprite(0x0090, EnemySprite.Vitreous, 0x00, 0, 0x07, 0x05)
create_sprite(0x0091, EnemySprite.CrystalSwitch, 0x00, 0, 0x18, 0x04, 'Mire Falling Foes')
create_sprite(0x0091, EnemySprite.SpikeBlock, 0x00, 0, 0x1b, 0x0e, 'Mire Falling Foes')
create_sprite(0x0091, 0x08, SpriteType.Overlord, 0, 0x17, 0x0f)
@@ -1475,9 +1475,9 @@ def init_vanilla_sprites():
create_sprite(0x00a1, EnemySprite.Stalfos, 0x00, 0, 0x15, 0x19, 'Mire South Fish')
create_sprite(0x00a1, EnemySprite.BunnyBeam, 0x00, 0, 0x17, 0x19, 'Mire South Fish')
create_sprite(0x00a1, EnemySprite.Stalfos, 0x00, 0, 0x1b, 0x19, 'Mire South Fish')
create_sprite(0x00a4, EnemySprite.TrinexxRockHead, 0x00, 0, 0x07, 0x15)
create_sprite(0x00a4, EnemySprite.TrinexxFireHead, 0x00, 0, 0x07, 0x15)
create_sprite(0x00a4, EnemySprite.TrinexxIceHead, 0x00, 0, 0x07, 0x15)
create_sprite(0x00a4, EnemySprite.TrinexxRockHead, 0x00, 0, 0x07, 0x05)
create_sprite(0x00a4, EnemySprite.TrinexxFireHead, 0x00, 0, 0x07, 0x05)
create_sprite(0x00a4, EnemySprite.TrinexxIceHead, 0x00, 0, 0x07, 0x05)
create_sprite(0x00a5, EnemySprite.Wizzrobe, 0x00, 0, 0x16, 0x05, 'GT Wizzrobes 2')
create_sprite(0x00a5, EnemySprite.Wizzrobe, 0x00, 0, 0x19, 0x05, 'GT Wizzrobes 2')
create_sprite(0x00a5, EnemySprite.Wizzrobe, 0x00, 0, 0x04, 0x07, 'GT Wizzrobes 1')
@@ -1521,7 +1521,7 @@ def init_vanilla_sprites():
create_sprite(0x00ab, EnemySprite.SpikeBlock, 0x00, 0, 0x03, 0x19, 'Thieves Spike Switch')
create_sprite(0x00ab, EnemySprite.SpikeBlock, 0x00, 0, 0x0c, 0x1a, 'Thieves Spike Switch')
create_sprite(0x00ab, EnemySprite.SpikeBlock, 0x00, 0, 0x03, 0x1b, 'Thieves Spike Switch')
create_sprite(0x00ac, EnemySprite.Blind, 0x00, 0, 0x19, 0x15)
create_sprite(0x00ac, EnemySprite.Blind, 0x00, 0, 0x09, 0x05)
create_sprite(0x00ae, EnemySprite.BlueBari, 0x00, 0, 0x13, 0x07, 'Iced T')
create_sprite(0x00ae, EnemySprite.BlueBari, 0x00, 0, 0x15, 0x07, 'Iced T')
create_sprite(0x00af, EnemySprite.FirebarCW, 0x00, 0, 0x0a, 0x08, 'Ice Catwalk')
@@ -1688,13 +1688,13 @@ def init_vanilla_sprites():
create_sprite(0x00c6, EnemySprite.FloatingSkull, 0x00, 0, 0x10, 0x0e, 'TR Hub Ledges')
create_sprite(0x00c6, EnemySprite.BlueBari, 0x00, 0, 0x18, 0x14, 'TR Hub Ledges')
create_sprite(0x00c6, EnemySprite.BlueBari, 0x00, 0, 0x08, 0x17, 'TR Hub Ledges')
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x14, 0x15)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x17, 0x15)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x1a, 0x15)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x1a, 0x18)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x17, 0x18)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x14, 0x18)
create_sprite(0x00c8, 0x19, SpriteType.Overlord, 0, 0x17, 0x18)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x04, 0x05)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x07, 0x05)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x0a, 0x05)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x0a, 0x08)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x07, 0x08)
create_sprite(0x00c8, EnemySprite.ArmosKnight, 0x00, 0, 0x04, 0x08)
create_sprite(0x00c8, 0x19, SpriteType.Overlord, 0, 0x07, 0x08)
create_sprite(0x00c9, EnemySprite.Popo2, 0x00, 0, 0x10, 0x05, 'Eastern Lobby Bridge')
create_sprite(0x00c9, EnemySprite.Popo2, 0x00, 0, 0x0f, 0x06, 'Eastern Lobby Bridge')
create_sprite(0x00c9, EnemySprite.Popo2, 0x00, 0, 0x10, 0x07, 'Eastern Lobby Bridge')
@@ -1804,9 +1804,9 @@ def init_vanilla_sprites():
create_sprite(0x00dc, EnemySprite.Firesnake, 0x00, 1, 0x16, 0x17, 'Thieves Compass Room')
create_sprite(0x00dc, EnemySprite.Firesnake, 0x00, 0, 0x05, 0x1c, 'Thieves Compass Room')
create_sprite(0x00dc, EnemySprite.Blob, 0x00, 0, 0x0f, 0x1c, 'Thieves Compass Room')
create_sprite(0x00de, EnemySprite.KholdstareShell, 0x00, 0, 0x17, 0x05)
create_sprite(0x00de, EnemySprite.FallingIce, 0x00, 0, 0x17, 0x05)
create_sprite(0x00de, EnemySprite.Kholdstare, 0x00, 0, 0x17, 0x05)
create_sprite(0x00de, EnemySprite.KholdstareShell, 0x00, 0, 0x07, 0x05)
create_sprite(0x00de, EnemySprite.FallingIce, 0x00, 0, 0x07, 0x05)
create_sprite(0x00de, EnemySprite.Kholdstare, 0x00, 0, 0x07, 0x05)
create_sprite(0x00df, EnemySprite.MiniMoldorm, 0x00, 1, 0x0c, 0x15, 'Paradox Cave')
create_sprite(0x00df, EnemySprite.MiniMoldorm, 0x00, 1, 0x0c, 0x16, 'Paradox Cave')
create_sprite(0x00e0, EnemySprite.BallNChain, 0x00, 0, 0x04, 0x06, 'Tower Gold Knights')
@@ -2075,8 +2075,8 @@ class EnemyTable:
for sprite in self.room_map[room]:
data = sprite.sprite_data()
rom.write_bytes(data_pointer + list_offset, data)
list_offset + len(data)
rom.write_byte(data_pointer, 0xff)
list_offset += len(data)
rom.write_byte(data_pointer + list_offset, 0xff)
data_pointer += list_offset + 1
else:
rom.write_bytes(pointer_address + room * 2, int16_as_bytes(empty_pointer))
@@ -2090,23 +2090,16 @@ class EnemyTable:
def setup_enemy_locations(world, player):
world.enemy_list[player] = EnemyTable()
for super_tile, enemy_list in vanilla_sprites.items():
for super_tile, enemy_list in world.data_tables[player].uw_enemy_table.room_map.items():
for index, sprite in enumerate(enemy_list):
# if sprite.drops_item and sprite.drop_item_kind == 0xe4:
# # normal key drops
# pass
my_sprite = sprite.copy()
world.enemy_list[player].room_map[super_tile].append()
if valid_drop_location(my_sprite, world, player):
create_drop_location(my_sprite, index, super_tile, world, player)
if valid_drop_location(sprite, world, player):
create_drop_location(sprite, index, super_tile, world, player)
def valid_drop_location(sprite, world, player):
if world.dropshuffle[player] == 'underworld':
if sprite.drops_item and sprite.drop_item_kind == 0xe4:
# already has a location -- hook it up?
# already has a location
return False
else:
stat = enemy_stats[sprite.kind]

View File

@@ -315,7 +315,8 @@ class RoomHeader:
self.sprite_sheet = byte_array[3]
def write_to_rom(self, rom, base_address):
rom.write_byte(base_address + self.room_id*14 + 3, self.sprite_sheet)
room_offest = self.room_id*14
rom.write_byte(base_address + room_offest + 3, self.sprite_sheet)
def init_room_headers():

View File

@@ -17,23 +17,25 @@ class Room:
self.doors = doors
def write_to_rom(self, address, rom):
offset = 0
rom.write_bytes(address, self.layout)
address += 2
offset += 2
for obj in self.layer1:
rom.write_bytes(address, obj.data)
address += 3
rom.write_bytes(address, [0xFF, 0xFF])
address += 2
rom.write_bytes(address + offset, obj.data)
offset += 3
rom.write_bytes(address + offset, [0xFF, 0xFF])
offset += 2
for obj in self.layer2:
rom.write_bytes(address, obj.data)
address += 3
rom.write_bytes(address, [0xFF, 0xFF, 0xF0, 0xFF])
address += 4
rom.write_bytes(address + offset, obj.data)
offset += 3
rom.write_bytes(address + offset, [0xFF, 0xFF, 0xF0, 0xFF])
offset += 4
door_start = offset
for door in self.doors:
rom.write_bytes(address, door.get_bytes())
address += 2
rom.write_bytes(address, [0xFF, 0xFF])
return address + 2 # where the data ended
rom.write_bytes(address + offset, door.get_bytes())
offset += 2
rom.write_bytes(address + offset, [0xFF, 0xFF])
return door_start, offset + 2 # how many bytes were written
Room0127 = Room([0xE1, 0x00],

View File

@@ -1,3 +1,5 @@
from types import SimpleNamespace
from source.dungeon.EnemyList import enemy_names, SpriteType
from source.enemizer.Enemizer import randomize_underworld_rooms
from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets
@@ -6,7 +8,8 @@ import RaceRandom as random
if __name__ == '__main__':
random.seed(42)
data_tables = init_data_tables(None, None)
world = SimpleNamespace(pottery={1: 'none'})
data_tables = init_data_tables(world, 1)
randomize_underworld_sprite_sheets(data_tables.sprite_sheets)
randomize_underworld_rooms(data_tables)

View File

@@ -1,4 +1,4 @@
from Utils import snes_to_pc
from Utils import snes_to_pc, int24_as_bytes, int16_as_bytes
from source.dungeon.EnemyList import EnemyTable, init_vanilla_sprites, vanilla_sprites
from source.dungeon.RoomHeader import init_room_headers
@@ -9,32 +9,50 @@ from source.enemizer.SpriteSheets import init_sprite_sheets, init_sprite_require
class DataTables:
def __init__(self):
self.room_headers = None
self.room_list = None # todo: for boss rando
self.room_list = None
self.sprite_sheets = None
self.uw_enemy_table = None
self.ow_enemy_tables = None # todo : data migration
self.pot_secret_table = None # todo : migrate storage
self.ow_enemy_table = None # todo : data migration
self.pot_secret_table = None
# associated data
self.sprite_requirements = None
def write_to_rom(self, rom):
for header in self.room_headers.values():
def write_to_rom(self, rom, colorize_pots=False):
if self.pot_secret_table.size() > 0x11c0:
raise Exception('Pot table is too big for current area')
self.pot_secret_table.write_pot_data_to_rom(rom, colorize_pots)
for room_id, header in self.room_headers.items():
data_location = (0x30DA00 + room_id * 14) & 0xFFFF
rom.write_bytes(snes_to_pc(0x04F1E2) + room_id * 2, int16_as_bytes(data_location))
header.write_to_rom(rom, snes_to_pc(0x30DA00)) # new header table, bank30, tables.asm
# room list
room_start_address = 0x378000
for room_id, room in self.room_list.items():
rom.write_bytes(0x1F8000 + room_id * 3, int24_as_bytes(room_start_address))
door_start, bytes_written = room.write_to_rom(snes_to_pc(room_start_address), rom)
rom.write_bytes(0x1F83C0 + room_id * 3, int24_as_bytes(room_start_address + door_start))
room_start_address += bytes_written
# todo: room data doors pointers at 1F83C0
if room_start_address > 0x380000:
raise Exception('Room list exceeded bank size')
# size notes: bank 03 uses 140E bytes
# bank 0A uses 372A bytes
# bank 1F uses 77CE bytes: total is about a bank and a half
# probably should reuse bank 1F if writing all the rooms out
for sheet in self.sprite_sheets.values():
sheet.write_to_rom(snes_to_pc(0x00DB97)) # bank 00, SheetsTable_AA3
sheet.write_to_rom(rom, snes_to_pc(0x00DB97)) # bank 00, SheetsTable_AA3
if self.uw_enemy_table.size() > 0x2800:
raise Exception('Sprite table is too big for current area')
self.uw_enemy_table.write_sprite_data_to_rom(rom)
# todo: write ow enemy table
def init_data_tables(world, player):
data_tables = DataTables()
data_tables.room_headers = init_room_headers()
data_tables.room_list = {}
# if world.pottery[player] not in ['none']:
# data_tables.room_list[0x0127] = Room0127
if world.pottery[player] not in ['none']:
data_tables.room_list[0x0127] = Room0127
data_tables.sprite_requirements = init_sprite_requirements()
data_tables.sprite_sheets = init_sprite_sheets(data_tables.sprite_requirements)
init_vanilla_sprites()