Skip to content

Commit

Permalink
Merge pull request #388 from gymnast86/tracker-touchups
Browse files Browse the repository at this point in the history
More Tracker Touchups
  • Loading branch information
CovenEsme authored Jun 28, 2024
2 parents 15a0eec + 402bdf8 commit d72ad1a
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 42 deletions.
5 changes: 5 additions & 0 deletions data/tracker_areas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
- Lanayru
- Sky
- Inside the Thunderhead
- Everything Discovered

- name: Everything Discovered
x: 10
y: 263

- name: Sky
alias: The Sky
Expand Down
2 changes: 0 additions & 2 deletions data/world/Eldin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@
Eldin Volcano - Stamina Fruit above Slope after Volcano Ascent: Nothing

- name: Thrill Digger Cave
hint_region: Eldin Volcano
events:
Can Play Thrill Digger Minigame: Digging_Mitts
exits:
Expand Down Expand Up @@ -313,7 +312,6 @@
Volcano Summit - Goddess Cube in Lava Lake: Fireshield_Earrings and (Long_Range_Skyward_Strike or ('Beaten_Boko_Base' and Goddess_Sword))

- name: Volcano Summit Waterfall
hint_region: Volcano Summit
events:
Can Collect Water: Bottle
exits:
Expand Down
2 changes: 1 addition & 1 deletion data/world/Lanayru.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@
exits:
Shipyard Statue: Nothing
Shipyard End of Minecart Ride: Nothing
Construction Bay Sand Pit: "'Defeat_Shipyard_Moldarach'"
Construction Bay Sand Pit: Nothing
Lanayru Sand Sea: Nothing
locations:
Shipyard - Bonk Sign before Gortram the Rickety Coaster Operator: Nothing
Expand Down
11 changes: 10 additions & 1 deletion gui/components/tracker_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ def get_all_locations(self) -> list[Location]:
if loc not in locations_set:
all_locations.append(loc)
locations_set.add(loc)
# If this is the "Everything Discovered" area, then get everything which has been discovered
# in the world
if self.recent_search and self.area == "Everything Discovered":
connected_areas = self.recent_search.get_all_connected_areas()
for loc in self.recent_search.worlds[0].location_table.values():
if any(
[la for la in loc.loc_access_list if la.area in connected_areas]
):
all_locations.append(loc)
return all_locations

def get_included_locations(
Expand Down Expand Up @@ -126,7 +135,7 @@ def update(self, search: "Search | None" = None) -> None:
if (
len(self.locations) + len(self.tracker_children) == 0
or self.recent_search is None
):
) and self.area != "Everything Discovered":
return

all_unmarked_locations = self.get_unmarked_locations(remove_special_types=False)
Expand Down
12 changes: 10 additions & 2 deletions gui/components/tracker_entrance_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ class TrackerEntranceLabel(QLabel):
disconnect_entrance = Signal(Entrance, str)

def __init__(
self, entrance_: Entrance, parent_area_name_: str, recent_search_: Search
self,
entrance_: Entrance,
parent_area_name_: str,
recent_search_: Search,
show_full_connection_: bool,
) -> None:
super().__init__()
self.entrance = entrance_
self.parent_area_name = parent_area_name_
self.recent_search = recent_search_
self.show_full_connection = show_full_connection_
self.setCursor(QCursor(QtCore.Qt.CursorShape.PointingHandCursor))
self.setMargin(10)
self.setMinimumHeight(30)
Expand All @@ -34,7 +39,10 @@ def update_text(self, recent_search_: Search | None = None) -> None:
connected_area = self.entrance.connected_area
original_parent, original_connected = self.entrance.original_name.split(" -> ")
first_part = (
f"{original_parent} to " if original_parent != self.parent_area_name else ""
f"{original_parent} to "
if self.entrance.parent_area.hard_assigned_region != self.parent_area_name
or self.show_full_connection
else ""
)
self.setText(
f"{first_part}{original_connected} -> {connected_area.name if connected_area else '?'}"
Expand Down
13 changes: 11 additions & 2 deletions gui/components/tracker_target_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ class TrackerTargetLabel(QLabel):
clicked = Signal(Entrance, Entrance, str)

def __init__(
self, entrance_: Entrance, target_: Entrance, parent_area_name_: str
self,
entrance_: Entrance,
target_: Entrance,
parent_area_name_: str,
show_full_connection: bool,
) -> None:
super().__init__()
self.entrance = entrance_
Expand All @@ -25,7 +29,12 @@ def __init__(
self.setMaximumWidth(273)
self.setWordWrap(True)

self.setText(self.target.replaces.original_name.split(" -> ")[1])
if show_full_connection:
self.setText(
f"{self.target.connected_area} from {self.target.replaces.parent_area}"
)
else:
self.setText(self.target.replaces.original_name.split(" -> ")[1])

def mouseReleaseEvent(self, ev: QMouseEvent) -> None:
if ev.button() == QtCore.Qt.MouseButton.LeftButton:
Expand Down
134 changes: 100 additions & 34 deletions gui/tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,10 @@ def initialize_tracker_world(
if starting_hearts == "random":
starting_hearts.set_value("6")

# Set starting sword as No Sword if it's random
if self.world.setting("starting_sword") == "random":
self.world.setting("starting_sword").set_value("no_sword")

# Build the world (only as necessary)
self.world.build()
self.world.perform_pre_entrance_shuffle_tasks()
Expand Down Expand Up @@ -761,9 +765,7 @@ def initialize_tracker_world(

# Connect autosaved entrances
if autosaved_entrances := autosave.get("connected_entrances", None):
for entrance in self.world.get_shuffled_entrances(
only_primary=self.world.setting("decouple_entrances") == "off"
):
for entrance in self.world.get_shuffled_entrances():
if saved_target := autosaved_entrances.get(
entrance.original_name, None
):
Expand Down Expand Up @@ -925,6 +927,27 @@ def setup_tracker_entrances(self) -> None:
entrance_pools = create_entrance_pools(self.world)
self.target_entrance_pools = create_target_pools(entrance_pools)

# Create reverse pools for each pool if entrances are not already decoupled.
# This allows users to map any entrance that comes up, and allows us
# to only display the entrances that are possible to connect to
for type, pool in self.target_entrance_pools.copy().items():

# Reverse pools can't exist for non-assumed entrance types
if type in Entrance.NON_ASSUMED_ENTRANCE_TYPES:
continue

reverse_targets: list[Entrance] = []
reverse_type = f"{type} Reverse"
for target in pool:
reverse_target = target.replaces.reverse.assumed
if not target.replaces.decoupled and reverse_target not in pool:
reverse_targets.append(reverse_target)
target.replaces.reverse.type = reverse_type

if reverse_targets:
self.target_entrance_pools[reverse_type] = reverse_targets
print(f"Added {len(reverse_targets)} targets to {reverse_type}")

# Prevent implicit access to any target entrances
for target_pool in self.target_entrance_pools.values():
for target in target_pool:
Expand All @@ -941,14 +964,27 @@ def update_areas_entrances(self) -> None:
area_button.main_entrance_name
)

# Then redistribute entrances to each button
for entrance in self.world.get_shuffled_entrances(
only_primary=self.world.setting("decouple_entrances") == "off"
):
if entrance.requirement.type != RequirementType.IMPOSSIBLE:
for region in entrance.parent_area.hint_regions:
if area_button := self.areas.get(region, None):
area_button.entrances.append(entrance)
# Find all the shuffled entrances for each area and add them
if not area_button.tracker_children:
hard_assigned_areas: list[Area] = []
for area in self.world.areas.values():
if area.hard_assigned_region == area_button.area:
hard_assigned_areas.append(area)

if hard_assigned_areas:
entrance_spheres = hard_assigned_areas[0].find_shuffled_entrances(
hard_assigned_areas
)
for sphere in entrance_spheres:
area_button.entrances.extend(sphere)

# Add all discovered entrances to "Everything Discovered"
if area_button.area == "Everything Discovered":
search, _ = self.get_tracker_search()
connected_areas = search.get_all_connected_areas()
for entrance in self.world.get_shuffled_entrances():
if entrance.parent_area in connected_areas:
area_button.entrances.append(entrance)

def set_map_area(self, area_name: str) -> None:
area = self.areas.get(area_name, None)
Expand Down Expand Up @@ -1093,8 +1129,19 @@ def show_area_entrances(self, area_name: str) -> None:
entrances.sort()

for i, entrance in enumerate(entrances):
# If there are multiple entrances which lead to the same
# area, then show the full connection to differentiate them
show_full_connection = any(
[
e
for e in entrances
if e != entrance
and e.original_connected_area
== entrance.original_connected_area
]
)
entrance_label = TrackerEntranceLabel(
entrance, area_name, area_button.recent_search
entrance, area_name, area_button.recent_search, show_full_connection
)
entrance_label.choose_target.connect(self.show_target_selection_info)
entrance_label.disconnect_entrance.connect(
Expand Down Expand Up @@ -1168,7 +1215,9 @@ def show_target_selection_info(

lead_to_label = QLabel(f"Where did {entrance.original_name} lead to?")
lead_to_label.setMargin(10)
lead_to_label.setWordWrap(True)
back_button = TrackerShowEntrancesButton(parent_area_name, "Back")
back_button.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Fixed)
back_button.show_area_entrances.connect(self.show_area_entrances)

# Add a way to filter entrance targets
Expand Down Expand Up @@ -1196,18 +1245,22 @@ def show_target_selection_info(

targets.sort(key=lambda e: e.replaces.sort_priority)

areas_shown = set()
for i, target in enumerate(targets):
# Only show targets which haven't been connected yet
# and don't show multiple targets that lead to the same
# area

if (
target.connected_area is not None
and target.connected_area not in areas_shown
):
areas_shown.add(target.connected_area)
target_label = TrackerTargetLabel(entrance, target, parent_area_name)
if target.connected_area is not None:
# If this target leads to the same area as other targets
# show the full entrance name to distinguish them from
# one another
show_full_connection = any(
[
t
for t in targets
if t != target and target.connected_area == t.connected_area
]
)
target_label = TrackerTargetLabel(
entrance, target, parent_area_name, show_full_connection
)
target_label.clicked.connect(self.on_click_target_label)

if i < len(targets) / 2:
Expand All @@ -1230,6 +1283,16 @@ def show_target_selection_info(
self.ui.tracker_locations_scroll_layout.addLayout(left_layout)
self.ui.tracker_locations_scroll_layout.addLayout(right_layout)

def show_current_area(self) -> None:
if location_label := self.ui.tracker_locations_scroll_area.findChild(
TrackerLocationLabel
):
self.show_area_locations(location_label.parent_area_button.area)
elif entrance_label := self.ui.tracker_locations_scroll_area.findChild(
TrackerEntranceLabel
):
self.show_area_entrances(entrance_label.parent_area_name)

def on_filter_text_changed(self, filter: str) -> None:
for label in self.ui.tracker_tab.findChildren(TrackerTargetLabel):
label.setVisible(filter.lower() in label.text().lower())
Expand Down Expand Up @@ -1396,10 +1459,7 @@ def compute_tooltips(self) -> None:
tooltips_search = TooltipsSearch(self.world)
tooltips_search.do_search()

def update_tracker(self) -> None:
if not self.started:
return

def get_tracker_search(self) -> tuple:
# Make a copy of the inventory to modify
inventory = self.inventory.copy()

Expand All @@ -1413,6 +1473,13 @@ def update_tracker(self) -> None:

# Use modified inventory for main search
search = Search(SearchMode.ACCESSIBLE_LOCATIONS, [self.world], inventory)
return (search, already_added)

def update_tracker(self) -> None:
if not self.started:
return

search, already_added = self.get_tracker_search()
search.search_worlds()

for area_button in self.areas.values():
Expand Down Expand Up @@ -1441,13 +1508,10 @@ def update_tracker(self) -> None:
location.in_semi_logic = location in semi_logic_locations

# Update any labels that are currently shown
location_label_area_name = ""
for location_label in self.ui.tracker_locations_scroll_area.findChildren(
TrackerLocationLabel
):
location_label.update_color(search)
if not location_label_area_name:
location_label_area_name = location_label.parent_area_button.area

for entrance_label in self.ui.tracker_locations_scroll_area.findChildren(
TrackerEntranceLabel
Expand All @@ -1457,7 +1521,7 @@ def update_tracker(self) -> None:
for dungeon_label in self.ui.tracker_tab.findChildren(TrackerDungeonLabel):
dungeon_label.update_style()

self.show_area_location_info(location_label_area_name)
self.show_current_area()
self.autosave_tracker()
self.update_statistics()
if self.allow_sphere_tracking:
Expand Down Expand Up @@ -1514,8 +1578,10 @@ def autosave_tracker(self) -> None:

# Then read it again to input extra data
autosave: dict = yaml_load(filename)
# Marked locations includes gossip stones, so read directly from
# the location table to include those
autosave["marked_locations"] = [
loc.name for loc in self.world.get_all_item_locations() if loc.marked
loc.name for loc in self.world.location_table.values() if loc.marked
]
autosave["marked_items"] = [item.name for item in self.inventory.elements()]
autosave["connected_entrances"] = {
Expand Down Expand Up @@ -1717,7 +1783,7 @@ def on_click_inventory_button(self, item: Item, item_image: str):
self.sphere_tracked_items[self.last_checked_location] = item.name
self.update_tracker()
if self.last_opened_region is not None:
self.show_area_locations(self.last_opened_region.area)
self.show_current_area()

def update_spheres(self):
# Copy the current inventory to pass into the search
Expand Down Expand Up @@ -1828,7 +1894,7 @@ def on_click_hint_label(self, hint: str, area: TrackerArea):
else:
area.hints.add(hint)

self.show_area_locations(area.area)
self.show_current_area()

def toggle_sphere_tracking(self):
self.allow_sphere_tracking = not self.allow_sphere_tracking
Expand All @@ -1843,7 +1909,7 @@ def toggle_sphere_tracking(self):
self.ui.toggle_sphere_tracking_button.setText("Enable Sphere Tracking")
self.cancel_sphere_tracking()
if self.last_opened_region is not None:
self.show_area_locations(self.last_opened_region.area)
self.show_current_area()

self.update_tracker()

Expand Down
Loading

0 comments on commit d72ad1a

Please sign in to comment.