DS3: Convert post_fill to stage_post_fill for better performance (#4122)

Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
This commit is contained in:
Mysteryem 2024-12-26 13:50:18 +00:00 committed by GitHub
parent 62942704bd
commit 33ae68c756
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 105 additions and 85 deletions

View File

@ -1366,7 +1366,8 @@ class DarkSouls3World(World):
text = "\n" + text + "\n" text = "\n" + text + "\n"
spoiler_handle.write(text) spoiler_handle.write(text)
def post_fill(self): @classmethod
def stage_post_fill(cls, multiworld: MultiWorld):
"""If item smoothing is enabled, rearrange items so they scale up smoothly through the run. """If item smoothing is enabled, rearrange items so they scale up smoothly through the run.
This determines the approximate order a given silo of items (say, soul items) show up in the This determines the approximate order a given silo of items (say, soul items) show up in the
@ -1375,26 +1376,45 @@ class DarkSouls3World(World):
items, later spheres get higher-level ones. Within a sphere, items in DS3 are distributed in items, later spheres get higher-level ones. Within a sphere, items in DS3 are distributed in
region order, and then the best items in a sphere go into the multiworld. region order, and then the best items in a sphere go into the multiworld.
""" """
ds3_worlds = [world for world in cast(List[DarkSouls3World], multiworld.get_game_worlds(cls.game)) if
world.options.smooth_upgrade_items
or world.options.smooth_soul_items
or world.options.smooth_upgraded_weapons]
if not ds3_worlds:
# No worlds need item smoothing.
return
locations_by_sphere = [ spheres_per_player: Dict[int, List[List[Location]]] = {world.player: [] for world in ds3_worlds}
sorted(loc for loc in sphere if loc.item.player == self.player and not loc.locked) for sphere in multiworld.get_spheres():
for sphere in self.multiworld.get_spheres() locations_per_item_player: Dict[int, List[Location]] = {player: [] for player in spheres_per_player.keys()}
] for location in sphere:
if location.locked:
continue
item_player = location.item.player
if item_player in locations_per_item_player:
locations_per_item_player[item_player].append(location)
for player, locations in locations_per_item_player.items():
# Sort for deterministic results.
locations.sort()
spheres_per_player[player].append(locations)
for ds3_world in ds3_worlds:
locations_by_sphere = spheres_per_player[ds3_world.player]
# All items in the base game in approximately the order they appear # All items in the base game in approximately the order they appear
all_item_order: List[DS3ItemData] = [ all_item_order: List[DS3ItemData] = [
item_dictionary[location.default_item_name] item_dictionary[location.default_item_name]
for region in region_order for region in region_order
# Shuffle locations within each region. # Shuffle locations within each region.
for location in self._shuffle(location_tables[region]) for location in ds3_world._shuffle(location_tables[region])
if self._is_location_available(location) if ds3_world._is_location_available(location)
] ]
# All DarkSouls3Items for this world that have been assigned anywhere, grouped by name # All DarkSouls3Items for this world that have been assigned anywhere, grouped by name
full_items_by_name: Dict[str, List[DarkSouls3Item]] = defaultdict(list) full_items_by_name: Dict[str, List[DarkSouls3Item]] = defaultdict(list)
for location in self.multiworld.get_filled_locations(): for location in multiworld.get_filled_locations():
if location.item.player == self.player and ( if location.item.player == ds3_world.player and (
location.player != self.player or self._is_location_available(location) location.player != ds3_world.player or ds3_world._is_location_available(location)
): ):
full_items_by_name[location.item.name].append(location.item) full_items_by_name[location.item.name].append(location.item)
@ -1441,17 +1461,17 @@ class DarkSouls3World(World):
locations = [loc for loc in sphere if loc.item.name in names] locations = [loc for loc in sphere if loc.item.name in names]
# Check the game, not the player, because we know how to sort within regions for DS3 # Check the game, not the player, because we know how to sort within regions for DS3
offworld = self._shuffle([loc for loc in locations if loc.game != "Dark Souls III"]) offworld = ds3_world._shuffle([loc for loc in locations if loc.game != "Dark Souls III"])
onworld = sorted((loc for loc in locations if loc.game == "Dark Souls III"), onworld = sorted((loc for loc in locations if loc.game == "Dark Souls III"),
key=lambda loc: loc.data.region_value) key=lambda loc: loc.data.region_value)
# Give offworld regions the last (best) items within a given sphere # Give offworld regions the last (best) items within a given sphere
for location in onworld + offworld: for location in onworld + offworld:
new_item = self._pop_item(location, converted_item_order) new_item = ds3_world._pop_item(location, converted_item_order)
location.item = new_item location.item = new_item
new_item.location = location new_item.location = location
if self.options.smooth_upgrade_items: if ds3_world.options.smooth_upgrade_items:
base_names = { base_names = {
"Titanite Shard", "Large Titanite Shard", "Titanite Chunk", "Titanite Slab", "Titanite Shard", "Large Titanite Shard", "Titanite Chunk", "Titanite Slab",
"Titanite Scale", "Twinkling Titanite", "Farron Coal", "Sage's Coal", "Giant's Coal", "Titanite Scale", "Twinkling Titanite", "Farron Coal", "Sage's Coal", "Giant's Coal",
@ -1459,17 +1479,17 @@ class DarkSouls3World(World):
} }
smooth_items([item for item in all_item_order if item.base_name in base_names]) smooth_items([item for item in all_item_order if item.base_name in base_names])
if self.options.smooth_soul_items: if ds3_world.options.smooth_soul_items:
smooth_items([ smooth_items([
item for item in all_item_order item for item in all_item_order
if item.souls and item.classification != ItemClassification.progression if item.souls and item.classification != ItemClassification.progression
]) ])
if self.options.smooth_upgraded_weapons: if ds3_world.options.smooth_upgraded_weapons:
upgraded_weapons = [ upgraded_weapons = [
location.item location.item
for location in self.multiworld.get_filled_locations() for location in multiworld.get_filled_locations()
if location.item.player == self.player if location.item.player == ds3_world.player
and location.item.level and location.item.level > 0 and location.item.level and location.item.level > 0
and location.item.classification != ItemClassification.progression and location.item.classification != ItemClassification.progression
] ]