From 13d2a129f6972e6e752da9c9cb686a63d5550517 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Wed, 29 May 2024 12:56:29 -0400 Subject: Show unchecked paintings --- src/ap_state.cpp | 12 ++++++++++++ src/ap_state.h | 2 ++ src/area_popup.cpp | 32 ++++++++++++++++++++++++++++++++ src/game_data.cpp | 33 ++++++++++++++++++++++++++------- src/game_data.h | 1 + src/tracker_panel.cpp | 14 ++++++++++++++ src/tracker_state.cpp | 32 +++++++++++++++++--------------- 7 files changed, 104 insertions(+), 22 deletions(-) diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 20245e5..0c75eae 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp @@ -427,6 +427,14 @@ struct APState { return std::any_cast&>(data_storage.at(key)); } + bool IsPaintingChecked(const std::string& painting_id) { + const auto& checked_paintings = GetCheckedPaintings(); + + return checked_paintings.count(painting_id) || + (painting_mapping.count(painting_id) && + checked_paintings.count(painting_mapping.at(painting_id))); + } + void RefreshTracker(bool reset) { wxLogVerbose("Refreshing display..."); @@ -506,6 +514,10 @@ const std::set& AP_GetCheckedPaintings() { return GetState().GetCheckedPaintings(); } +bool AP_IsPaintingChecked(const std::string& painting_id) { + return GetState().IsPaintingChecked(painting_id); +} + int AP_GetMasteryRequirement() { return GetState().mastery_requirement; } int AP_GetLevel2Requirement() { return GetState().level_2_requirement; } diff --git a/src/ap_state.h b/src/ap_state.h index 0ae6a25..2769bb8 100644 --- a/src/ap_state.h +++ b/src/ap_state.h @@ -61,6 +61,8 @@ const std::map& AP_GetPaintingMapping(); const std::set& AP_GetCheckedPaintings(); +bool AP_IsPaintingChecked(const std::string& painting_id); + int AP_GetMasteryRequirement(); int AP_GetLevel2Requirement(); diff --git a/src/area_popup.cpp b/src/area_popup.cpp index 6e70315..b5c1ccb 100644 --- a/src/area_popup.cpp +++ b/src/area_popup.cpp @@ -65,6 +65,18 @@ void AreaPopup::UpdateIndicators() { } } + if (AP_IsPaintingShuffle()) { + for (const PaintingExit& painting : map_area.paintings) { + wxSize item_extent = mem_dc.GetTextExtent(painting.id); + int item_height = std::max(32, item_extent.GetHeight()) + 10; + acc_height += item_height; + + if (item_extent.GetWidth() > col_width) { + col_width = item_extent.GetWidth(); + } + } + } + int item_width = col_width + 10 + 32; int full_width = std::max(header_extent.GetWidth(), item_width) + 20; @@ -109,6 +121,26 @@ void AreaPopup::UpdateIndicators() { cur_height += 10 + 32; } + + if (AP_IsPaintingShuffle()) { + for (const PaintingExit& painting : map_area.paintings) { + bool checked = AP_IsPaintingChecked(painting.id); + wxBitmap* eye_ptr = checked ? &checked_eye_ : &unchecked_eye_; + + mem_dc.DrawBitmap(*eye_ptr, {10, cur_height}); + + bool reachable = painting.door ? IsDoorOpen(*painting.door) : true; + const wxColour* text_color = reachable ? wxWHITE : wxRED; + mem_dc.SetTextForeground(*text_color); + + wxSize item_extent = mem_dc.GetTextExtent(painting.id); + mem_dc.DrawText(painting.id, + {10 + 32 + 10, + cur_height + (32 - mem_dc.GetFontMetrics().height) / 2}); + + cur_height += 10 + 32; + } + } } void AreaPopup::OnPaint(wxPaintEvent& event) { diff --git a/src/game_data.cpp b/src/game_data.cpp index 7c9564b..4dd69e2 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp @@ -284,7 +284,7 @@ struct GameData { .as(); } else { wxLogError("Missing AP location ID for panel %s - %s", - rooms_[room_id].name, panels_[panel_id].name); + rooms_[room_id].name, panels_[panel_id].name); } } } @@ -348,7 +348,7 @@ struct GameData { .as(); } else { wxLogError("Missing AP item ID for door %s - %s", - rooms_[room_id].name, doors_[door_id].name); + rooms_[room_id].name, doors_[door_id].name); } } @@ -422,7 +422,8 @@ struct GameData { std::string painting_id = painting["id"].as(); room_by_painting_[painting_id] = room_id; - if (!painting["exit_only"] || !painting["exit_only"].as()) { + if ((!painting["exit_only"] || !painting["exit_only"].as()) && + (!painting["disable"] || !painting["disable"].as())) { PaintingExit painting_exit; painting_exit.id = painting_id; @@ -594,11 +595,28 @@ struct GameData { } } + for (const Room &room : rooms_) { + std::string area_name = room.name; + if (fold_areas.count(room.name)) { + int fold_area_id = fold_areas[room.name]; + area_name = map_areas_[fold_area_id].name; + } + + if (!room.paintings.empty()) { + int area_id = AddOrGetArea(area_name); + MapArea &map_area = map_areas_[area_id]; + + for (const PaintingExit &painting : room.paintings) { + map_area.paintings.push_back(painting); + } + } + } + // Report errors. for (const std::string &area : malconfigured_areas_) { wxLogError("Area data not found for: %s", area); } - + // Read in subway items. YAML::Node subway_config = YAML::LoadFile(GetAbsolutePath("assets/subway.yaml")); @@ -687,7 +705,8 @@ struct GameData { if (!door_by_id_.count(full_name)) { int door_id = doors_.size(); door_by_id_[full_name] = doors_.size(); - doors_.push_back({.id = door_id, .room = AddOrGetRoom(room), .name = door}); + doors_.push_back( + {.id = door_id, .room = AddOrGetRoom(room), .name = door}); } return door_by_id_[full_name]; @@ -728,7 +747,7 @@ GameData &GetState() { } // namespace -bool SubwaySunwarp::operator<(const SubwaySunwarp& rhs) const { +bool SubwaySunwarp::operator<(const SubwaySunwarp &rhs) const { return std::tie(dots, type) < std::tie(rhs.dots, rhs.type); } @@ -782,7 +801,7 @@ const SubwayItem &GD_GetSubwayItem(int id) { return GetState().subway_items_.at(id); } -int GD_GetSubwayItemForPainting(const std::string& painting_id) { +int GD_GetSubwayItemForPainting(const std::string &painting_id) { #ifndef NDEBUG if (!GetState().subway_item_by_painting_.count(painting_id)) { wxLogError("No subway item for painting %s", painting_id); diff --git a/src/game_data.h b/src/game_data.h index 3afaec3..68ba5e4 100644 --- a/src/game_data.h +++ b/src/game_data.h @@ -113,6 +113,7 @@ struct MapArea { int id; std::string name; std::vector locations; + std::vector paintings; int map_x; int map_y; int classification = 0; diff --git a/src/tracker_panel.cpp b/src/tracker_panel.cpp index 66bce81..0385f89 100644 --- a/src/tracker_panel.cpp +++ b/src/tracker_panel.cpp @@ -171,6 +171,20 @@ void TrackerPanel::Redraw() { } } + if (AP_IsPaintingShuffle()) { + for (const PaintingExit &painting : map_area.paintings) { + if (!AP_IsPaintingChecked(painting.id)) { + bool reachable = painting.door ? IsDoorOpen(*painting.door) : true; + + if (reachable) { + has_reachable_unchecked = true; + } else { + has_unreachable_unchecked = true; + } + } + } + } + int real_area_x = final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) * final_width / image_size.GetWidth(); int real_area_y = final_y + (map_area.map_y - (AREA_EFFECTIVE_SIZE / 2)) * diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index 869f837..faf74cc 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp @@ -15,11 +15,11 @@ namespace { struct Requirements { bool disabled = false; - std::set doors; // non-grouped, handles progressive - std::set items; // all other items - std::set rooms; // maybe - bool mastery = false; // maybe - bool panel_hunt = false; // maybe + std::set doors; // non-grouped, handles progressive + std::set items; // all other items + std::set rooms; // maybe + bool mastery = false; // maybe + bool panel_hunt = false; // maybe void Merge(const Requirements& rhs) { if (rhs.disabled) { @@ -228,7 +228,8 @@ class StateCalculator { if (AP_IsPaintingShuffle()) { for (const PaintingExit& out_edge : room_obj.paintings) { - if (AP_GetPaintingMapping().count(out_edge.id)) { + if (AP_GetPaintingMapping().count(out_edge.id) && + AP_GetCheckedPaintings().count(out_edge.id)) { Exit painting_exit; painting_exit.destination_room = GD_GetRoomForPainting( AP_GetPaintingMapping().at(out_edge.id)); @@ -286,7 +287,8 @@ class StateCalculator { panel_boundary = new_panel_boundary; } - // Now that we know the full reachable area, let's make sure all doors are evaluated. + // Now that we know the full reachable area, let's make sure all doors are + // evaluated. for (const Door& door : GD_GetDoors()) { int discard = IsDoorReachable(door.id); } @@ -320,7 +322,8 @@ class StateCalculator { return has_item ? kYes : kNo; } - Decision AreRequirementsSatisfied(const Requirements& reqs, std::map* report = nullptr) { + Decision AreRequirementsSatisfied( + const Requirements& reqs, std::map* report = nullptr) { if (reqs.disabled) { return kNo; } @@ -339,7 +342,7 @@ class StateCalculator { final_decision = decision; } } - + for (int item_id : reqs.items) { bool has_item = AP_HasItem(item_id); if (report) { @@ -353,10 +356,9 @@ class StateCalculator { for (int room_id : reqs.rooms) { bool reachable = reachable_rooms_.count(room_id); - + if (report) { - std::string report_name = - "Reach \"" + GD_GetRoom(room_id).name + "\""; + std::string report_name = "Reach \"" + GD_GetRoom(room_id).name + "\""; (*report)[report_name] = reachable; } @@ -364,7 +366,7 @@ class StateCalculator { final_decision = kMaybe; } } - + if (reqs.mastery) { int achievements_accessible = 0; @@ -407,7 +409,7 @@ class StateCalculator { std::to_string(AP_GetLevel2Requirement()) + " Panels"; (*report)[report_name] = can_level2; } - + if (can_level2 && final_decision != kNo) { final_decision = kMaybe; } @@ -422,7 +424,7 @@ class StateCalculator { } else { door_report_[door_id] = {}; } - + return AreRequirementsSatisfied(GetState().requirements.GetDoor(door_id), &door_report_[door_id]); } -- cgit 1.4.1