mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-14 11:33:47 -07:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e53b5324f5 | ||
|
|
25bbbdbecd | ||
|
|
d739d04380 | ||
|
|
f7da0265c4 | ||
|
|
82ae21420d |
@@ -61,7 +61,7 @@ NAME: "{app}"; Flags: setntfscompression; Permissions: everyone-modify users-mod
|
||||
|
||||
[Files]
|
||||
Source: "{code:GetROMPath}"; DestDir: "{app}"; DestName: "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc"; Flags: external; Components: client/lttp or generator
|
||||
Source: "{#sourcepath}\*"; Excludes: "*.sfc, *.log, data\sprites\alttpr, SNI, EnemizerCLI, *exe"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "{#sourcepath}\*"; Excludes: "*.sfc, *.log, data\sprites\alttpr, SNI, EnemizerCLI, Archipelago*.exe"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "{#sourcepath}\SNI\*"; Excludes: "*.sfc, *.log"; DestDir: "{app}\SNI"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: client/lttp
|
||||
Source: "{#sourcepath}\EnemizerCLI\*"; Excludes: "*.sfc, *.log"; DestDir: "{app}\EnemizerCLI"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: generator
|
||||
|
||||
|
||||
3
setup.py
3
setup.py
@@ -162,6 +162,9 @@ if signtool:
|
||||
os.system(signtool + os.path.join(buildfolder, exe.target_name))
|
||||
print(f"Signing SNI")
|
||||
os.system(signtool + os.path.join(buildfolder, "SNI", "SNI.exe"))
|
||||
print(f"Signing OoT Utils")
|
||||
for exe_path in (("Compress", "Compress.exe"), ("Decompress", "Decompress.exe")):
|
||||
os.system(signtool + os.path.join(buildfolder, "lib", "worlds", "oot", "data", *exe_path))
|
||||
|
||||
remove_sprites_from_folder(buildfolder / "data" / "sprites" / "alttpr")
|
||||
|
||||
|
||||
@@ -640,21 +640,12 @@ def buildWorldGossipHints(world, checkedLocations=None):
|
||||
# Seed the RNG
|
||||
world.hint_rng = world.world.slot_seeds[world.player]
|
||||
|
||||
# Gather woth, barren, major items
|
||||
world.gather_hint_data()
|
||||
|
||||
# rebuild hint exclusion list
|
||||
hintExclusions(world, clear_cache=True)
|
||||
|
||||
world.barren_dungeon = 0
|
||||
world.woth_dungeon = 0
|
||||
|
||||
# search = Search.max_explore([w.state for w in orlds])
|
||||
# for stone in gossipLocations.values():
|
||||
# stone.reachable = (
|
||||
# search.spot_access(world.get_location(stone.location))
|
||||
# and search.state_list[world.id].guarantee_hint())
|
||||
|
||||
if checkedLocations is None:
|
||||
checkedLocations = {player: set() for player in world.world.player_ids}
|
||||
|
||||
@@ -669,8 +660,6 @@ def buildWorldGossipHints(world, checkedLocations=None):
|
||||
|
||||
stoneIDs = list(gossipLocations.keys())
|
||||
|
||||
# world.distribution.configure_gossip(stoneIDs)
|
||||
|
||||
if 'disabled' in world.hint_dist_user:
|
||||
for stone_name in world.hint_dist_user['disabled']:
|
||||
try:
|
||||
|
||||
@@ -88,15 +88,11 @@ class Rom(BigStream):
|
||||
raise RuntimeError('ROM file %s is not a valid OoT 1.0 US ROM.' % file)
|
||||
elif len(self.buffer) == 0x2000000:
|
||||
# If Input ROM is compressed, then Decompress it
|
||||
subcall = []
|
||||
|
||||
sub_dir = data_path("Decompress")
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
if 8 * struct.calcsize("P") == 64:
|
||||
subcall = [sub_dir + "\\Decompress.exe", file, decomp_file]
|
||||
else:
|
||||
subcall = [sub_dir + "\\Decompress32.exe", file, decomp_file]
|
||||
subcall = [sub_dir + "\\Decompress.exe", file, decomp_file]
|
||||
elif platform.system() == 'Linux':
|
||||
if platform.uname()[4] == 'aarch64' or platform.uname()[4] == 'arm64':
|
||||
subcall = [sub_dir + "/Decompress_ARM64", file, decomp_file]
|
||||
@@ -288,10 +284,7 @@ def compress_rom_file(input_file, output_file):
|
||||
compressor_path = data_path("Compress")
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
if 8 * struct.calcsize("P") == 64:
|
||||
compressor_path += "\\Compress.exe"
|
||||
else:
|
||||
compressor_path += "\\Compress32.exe"
|
||||
compressor_path += "\\Compress.exe"
|
||||
elif platform.system() == 'Linux':
|
||||
if platform.uname()[4] == 'aarch64' or platform.uname()[4] == 'arm64':
|
||||
compressor_path += "/Compress_ARM64"
|
||||
|
||||
@@ -8,7 +8,7 @@ __version__ = Utils.__version__ + ' f.LUM'
|
||||
|
||||
|
||||
def data_path(*args):
|
||||
return Utils.local_path('worlds', 'oot', 'data', *args)
|
||||
return os.path.join(os.path.dirname(__file__), 'data', *args)
|
||||
|
||||
|
||||
@lru_cache(maxsize=13) # Cache Overworld.json and the 12 dungeons
|
||||
|
||||
@@ -35,6 +35,7 @@ location_id_offset = 67000
|
||||
|
||||
# OoT's generate_output doesn't benefit from more than 2 threads, instead it uses a lot of memory.
|
||||
i_o_limiter = threading.Semaphore(2)
|
||||
hint_data_available = threading.Event()
|
||||
|
||||
|
||||
class OOTWorld(World):
|
||||
@@ -646,8 +647,10 @@ class OOTWorld(World):
|
||||
impa.event = True
|
||||
self.world.itempool.remove(item_to_place)
|
||||
|
||||
# For now we will always output a patch file.
|
||||
def generate_output(self, output_directory: str):
|
||||
if self.hints != 'none':
|
||||
hint_data_available.wait()
|
||||
|
||||
with i_o_limiter:
|
||||
# Make ice traps appear as other random items
|
||||
ice_traps = [loc.item for loc in self.get_locations() if loc.item.name == 'Ice Trap']
|
||||
@@ -655,8 +658,7 @@ class OOTWorld(World):
|
||||
trap.looks_like_item = self.create_item(self.world.slot_seeds[self.player].choice(self.fake_items).name)
|
||||
|
||||
outfile_name = f"AP_{self.world.seed_name}_P{self.player}_{self.world.get_player_name(self.player)}"
|
||||
rom = Rom(
|
||||
file=get_options()['oot_options']['rom_file']) # a ROM must be provided, cannot produce patches without it
|
||||
rom = Rom(file=get_options()['oot_options']['rom_file'])
|
||||
if self.hints != 'none':
|
||||
buildWorldGossipHints(self)
|
||||
patch_rom(self, rom)
|
||||
@@ -665,6 +667,47 @@ class OOTWorld(World):
|
||||
create_patch_file(rom, output_path(output_directory, outfile_name + '.apz5'))
|
||||
rom.restore()
|
||||
|
||||
# Gathers hint data for OoT. Loops over all world locations for woth, barren, and major item locations.
|
||||
def stage_generate_output(world: MultiWorld, output_directory: str):
|
||||
try:
|
||||
items_by_region = {player: {} for player in world.get_game_players("Ocarina of Time") if world.worlds[player].hints != 'none'}
|
||||
if items_by_region:
|
||||
for player in items_by_region:
|
||||
for r in world.worlds[player].regions:
|
||||
items_by_region[player][r.hint_text] = {'dungeon': False, 'weight': 0, 'prog_items': 0}
|
||||
for d in world.worlds[player].dungeons:
|
||||
items_by_region[player][d.hint_text] = {'dungeon': True, 'weight': 0, 'prog_items': 0}
|
||||
del (items_by_region[player]["Link's Pocket"])
|
||||
del (items_by_region[player][None])
|
||||
|
||||
for loc in world.get_locations():
|
||||
player = loc.item.player
|
||||
autoworld = world.worlds[player]
|
||||
if ((player in items_by_region and (autoworld.is_major_item(loc.item) or loc.item.name in autoworld.item_added_hint_types['item']))
|
||||
or (loc.player in items_by_region and loc.name in world.worlds[loc.player].added_hint_types['item'])):
|
||||
autoworld.major_item_locations.append(loc)
|
||||
|
||||
if loc.game == "Ocarina of Time":
|
||||
if loc.item.code and (not loc.locked or loc.item.type == 'Song'): # shuffled item
|
||||
hint_area = get_hint_area(loc)
|
||||
items_by_region[loc.player][hint_area]['weight'] += 1
|
||||
if loc.item.advancement:
|
||||
# Non-locked progression. Increment counter
|
||||
items_by_region[loc.player][hint_area]['prog_items'] += 1
|
||||
# Skip item at location and see if game is still beatable
|
||||
state = CollectionState(world)
|
||||
state.locations_checked.add(loc)
|
||||
if not world.can_beat_game(state):
|
||||
world.worlds[loc.player].required_locations.append(loc)
|
||||
|
||||
for autoworld in world.get_game_worlds("Ocarina of Time"):
|
||||
autoworld.empty_areas = {region: info for (region, info) in items_by_region[autoworld.player].items() if not info['prog_items']}
|
||||
except Exception as e:
|
||||
raise e
|
||||
finally:
|
||||
hint_data_available.set()
|
||||
|
||||
|
||||
# Helper functions
|
||||
def get_shuffled_entrances(self):
|
||||
return []
|
||||
@@ -708,37 +751,3 @@ class OOTWorld(World):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
# Run this once for to gather up all required locations (for WOTH), barren regions (for foolish), and location of major items.
|
||||
# required_locations and major_item_locations need to be ordered for deterministic hints.
|
||||
def gather_hint_data(self):
|
||||
if self.required_locations and self.empty_areas and self.major_item_locations:
|
||||
return
|
||||
|
||||
items_by_region = {}
|
||||
for r in self.regions:
|
||||
items_by_region[r.hint_text] = {'dungeon': False, 'weight': 0, 'prog_items': 0}
|
||||
for d in self.dungeons:
|
||||
items_by_region[d.hint_text] = {'dungeon': True, 'weight': 0, 'prog_items': 0}
|
||||
del (items_by_region["Link's Pocket"])
|
||||
del (items_by_region[None])
|
||||
|
||||
for loc in self.get_locations():
|
||||
if loc.item.code: # is a real item
|
||||
hint_area = get_hint_area(loc)
|
||||
items_by_region[hint_area]['weight'] += 1
|
||||
if loc.item.advancement and (not loc.locked or loc.item.type == 'Song'):
|
||||
# Non-locked progression. Increment counter
|
||||
items_by_region[hint_area]['prog_items'] += 1
|
||||
# Skip item at location and see if game is still beatable
|
||||
state = CollectionState(self.world)
|
||||
state.locations_checked.add(loc)
|
||||
if not self.world.can_beat_game(state):
|
||||
self.required_locations.append(loc)
|
||||
self.empty_areas = {region: info for (region, info) in items_by_region.items() if not info['prog_items']}
|
||||
|
||||
for loc in self.world.get_filled_locations():
|
||||
if (loc.item.player == self.player and self.is_major_item(loc.item)
|
||||
or (loc.item.player == self.player and loc.item.name in self.item_added_hint_types['item'])
|
||||
or (loc.name in self.added_hint_types['item'] and loc.player == self.player)):
|
||||
self.major_item_locations.append(loc)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user