about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2024-05-29 12:56:29 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2024-05-29 12:56:29 -0400
commit13d2a129f6972e6e752da9c9cb686a63d5550517 (patch)
treeea0cfe2197c25732dd0d4d0f0e37717fd977792f /src
parentd3e2d9518403eb89eb150fa2158966c3483d5339 (diff)
downloadlingo-ap-tracker-13d2a129f6972e6e752da9c9cb686a63d5550517.tar.gz
lingo-ap-tracker-13d2a129f6972e6e752da9c9cb686a63d5550517.tar.bz2
lingo-ap-tracker-13d2a129f6972e6e752da9c9cb686a63d5550517.zip
Show unchecked paintings
Diffstat (limited to 'src')
-rw-r--r--src/ap_state.cpp12
-rw-r--r--src/ap_state.h2
-rw-r--r--src/area_popup.cpp32
-rw-r--r--src/game_data.cpp33
-rw-r--r--src/game_data.h1
-rw-r--r--src/tracker_panel.cpp14
-rw-r--r--src/tracker_state.cpp32
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 {
427 return std::any_cast<const std::set<std::string>&>(data_storage.at(key)); 427 return std::any_cast<const std::set<std::string>&>(data_storage.at(key));
428 } 428 }
429 429
430 bool IsPaintingChecked(const std::string& painting_id) {
431 const auto& checked_paintings = GetCheckedPaintings();
432
433 return checked_paintings.count(painting_id) ||
434 (painting_mapping.count(painting_id) &&
435 checked_paintings.count(painting_mapping.at(painting_id)));
436 }
437
430 void RefreshTracker(bool reset) { 438 void RefreshTracker(bool reset) {
431 wxLogVerbose("Refreshing display..."); 439 wxLogVerbose("Refreshing display...");
432 440
@@ -506,6 +514,10 @@ const std::set<std::string>& AP_GetCheckedPaintings() {
506 return GetState().GetCheckedPaintings(); 514 return GetState().GetCheckedPaintings();
507} 515}
508 516
517bool AP_IsPaintingChecked(const std::string& painting_id) {
518 return GetState().IsPaintingChecked(painting_id);
519}
520
509int AP_GetMasteryRequirement() { return GetState().mastery_requirement; } 521int AP_GetMasteryRequirement() { return GetState().mastery_requirement; }
510 522
511int AP_GetLevel2Requirement() { return GetState().level_2_requirement; } 523int 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<std::string, std::string>& AP_GetPaintingMapping();
61 61
62const std::set<std::string>& AP_GetCheckedPaintings(); 62const std::set<std::string>& AP_GetCheckedPaintings();
63 63
64bool AP_IsPaintingChecked(const std::string& painting_id);
65
64int AP_GetMasteryRequirement(); 66int AP_GetMasteryRequirement();
65 67
66int AP_GetLevel2Requirement(); 68int 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() {
65 } 65 }
66 } 66 }
67 67
68 if (AP_IsPaintingShuffle()) {
69 for (const PaintingExit& painting : map_area.paintings) {
70 wxSize item_extent = mem_dc.GetTextExtent(painting.id);
71 int item_height = std::max(32, item_extent.GetHeight()) + 10;
72 acc_height += item_height;
73
74 if (item_extent.GetWidth() > col_width) {
75 col_width = item_extent.GetWidth();
76 }
77 }
78 }
79
68 int item_width = col_width + 10 + 32; 80 int item_width = col_width + 10 + 32;
69 int full_width = std::max(header_extent.GetWidth(), item_width) + 20; 81 int full_width = std::max(header_extent.GetWidth(), item_width) + 20;
70 82
@@ -109,6 +121,26 @@ void AreaPopup::UpdateIndicators() {
109 121
110 cur_height += 10 + 32; 122 cur_height += 10 + 32;
111 } 123 }
124
125 if (AP_IsPaintingShuffle()) {
126 for (const PaintingExit& painting : map_area.paintings) {
127 bool checked = AP_IsPaintingChecked(painting.id);
128 wxBitmap* eye_ptr = checked ? &checked_eye_ : &unchecked_eye_;
129
130 mem_dc.DrawBitmap(*eye_ptr, {10, cur_height});
131
132 bool reachable = painting.door ? IsDoorOpen(*painting.door) : true;
133 const wxColour* text_color = reachable ? wxWHITE : wxRED;
134 mem_dc.SetTextForeground(*text_color);
135
136 wxSize item_extent = mem_dc.GetTextExtent(painting.id);
137 mem_dc.DrawText(painting.id,
138 {10 + 32 + 10,
139 cur_height + (32 - mem_dc.GetFontMetrics().height) / 2});
140
141 cur_height += 10 + 32;
142 }
143 }
112} 144}
113 145
114void AreaPopup::OnPaint(wxPaintEvent& event) { 146void 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 {
284 .as<int>(); 284 .as<int>();
285 } else { 285 } else {
286 wxLogError("Missing AP location ID for panel %s - %s", 286 wxLogError("Missing AP location ID for panel %s - %s",
287 rooms_[room_id].name, panels_[panel_id].name); 287 rooms_[room_id].name, panels_[panel_id].name);
288 } 288 }
289 } 289 }
290 } 290 }
@@ -348,7 +348,7 @@ struct GameData {
348 .as<int>(); 348 .as<int>();
349 } else { 349 } else {
350 wxLogError("Missing AP item ID for door %s - %s", 350 wxLogError("Missing AP item ID for door %s - %s",
351 rooms_[room_id].name, doors_[door_id].name); 351 rooms_[room_id].name, doors_[door_id].name);
352 } 352 }
353 } 353 }
354 354
@@ -422,7 +422,8 @@ struct GameData {
422 std::string painting_id = painting["id"].as<std::string>(); 422 std::string painting_id = painting["id"].as<std::string>();
423 room_by_painting_[painting_id] = room_id; 423 room_by_painting_[painting_id] = room_id;
424 424
425 if (!painting["exit_only"] || !painting["exit_only"].as<bool>()) { 425 if ((!painting["exit_only"] || !painting["exit_only"].as<bool>()) &&
426 (!painting["disable"] || !painting["disable"].as<bool>())) {
426 PaintingExit painting_exit; 427 PaintingExit painting_exit;
427 painting_exit.id = painting_id; 428 painting_exit.id = painting_id;
428 429
@@ -594,11 +595,28 @@ struct GameData {
594 } 595 }
595 } 596 }
596 597
598 for (const Room &room : rooms_) {
599 std::string area_name = room.name;
600 if (fold_areas.count(room.name)) {
601 int fold_area_id = fold_areas[room.name];
602 area_name = map_areas_[fold_area_id].name;
603 }
604
605 if (!room.paintings.empty()) {
606 int area_id = AddOrGetArea(area_name);
607 MapArea &map_area = map_areas_[area_id];
608
609 for (const PaintingExit &painting : room.paintings) {
610 map_area.paintings.push_back(painting);
611 }
612 }
613 }
614
597 // Report errors. 615 // Report errors.
598 for (const std::string &area : malconfigured_areas_) { 616 for (const std::string &area : malconfigured_areas_) {
599 wxLogError("Area data not found for: %s", area); 617 wxLogError("Area data not found for: %s", area);
600 } 618 }
601 619
602 // Read in subway items. 620 // Read in subway items.
603 YAML::Node subway_config = 621 YAML::Node subway_config =
604 YAML::LoadFile(GetAbsolutePath("assets/subway.yaml")); 622 YAML::LoadFile(GetAbsolutePath("assets/subway.yaml"));
@@ -687,7 +705,8 @@ struct GameData {
687 if (!door_by_id_.count(full_name)) { 705 if (!door_by_id_.count(full_name)) {
688 int door_id = doors_.size(); 706 int door_id = doors_.size();
689 door_by_id_[full_name] = doors_.size(); 707 door_by_id_[full_name] = doors_.size();
690 doors_.push_back({.id = door_id, .room = AddOrGetRoom(room), .name = door}); 708 doors_.push_back(
709 {.id = door_id, .room = AddOrGetRoom(room), .name = door});
691 } 710 }
692 711
693 return door_by_id_[full_name]; 712 return door_by_id_[full_name];
@@ -728,7 +747,7 @@ GameData &GetState() {
728 747
729} // namespace 748} // namespace
730 749
731bool SubwaySunwarp::operator<(const SubwaySunwarp& rhs) const { 750bool SubwaySunwarp::operator<(const SubwaySunwarp &rhs) const {
732 return std::tie(dots, type) < std::tie(rhs.dots, rhs.type); 751 return std::tie(dots, type) < std::tie(rhs.dots, rhs.type);
733} 752}
734 753
@@ -782,7 +801,7 @@ const SubwayItem &GD_GetSubwayItem(int id) {
782 return GetState().subway_items_.at(id); 801 return GetState().subway_items_.at(id);
783} 802}
784 803
785int GD_GetSubwayItemForPainting(const std::string& painting_id) { 804int GD_GetSubwayItemForPainting(const std::string &painting_id) {
786#ifndef NDEBUG 805#ifndef NDEBUG
787 if (!GetState().subway_item_by_painting_.count(painting_id)) { 806 if (!GetState().subway_item_by_painting_.count(painting_id)) {
788 wxLogError("No subway item for painting %s", painting_id); 807 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 {
113 int id; 113 int id;
114 std::string name; 114 std::string name;
115 std::vector<Location> locations; 115 std::vector<Location> locations;
116 std::vector<PaintingExit> paintings;
116 int map_x; 117 int map_x;
117 int map_y; 118 int map_y;
118 int classification = 0; 119 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() {
171 } 171 }
172 } 172 }
173 173
174 if (AP_IsPaintingShuffle()) {
175 for (const PaintingExit &painting : map_area.paintings) {
176 if (!AP_IsPaintingChecked(painting.id)) {
177 bool reachable = painting.door ? IsDoorOpen(*painting.door) : true;
178
179 if (reachable) {
180 has_reachable_unchecked = true;
181 } else {
182 has_unreachable_unchecked = true;
183 }
184 }
185 }
186 }
187
174 int real_area_x = final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) * 188 int real_area_x = final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) *
175 final_width / image_size.GetWidth(); 189 final_width / image_size.GetWidth();
176 int real_area_y = final_y + (map_area.map_y - (AREA_EFFECTIVE_SIZE / 2)) * 190 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 {
15struct Requirements { 15struct Requirements {
16 bool disabled = false; 16 bool disabled = false;
17 17
18 std::set<int> doors; // non-grouped, handles progressive 18 std::set<int> doors; // non-grouped, handles progressive
19 std::set<int> items; // all other items 19 std::set<int> items; // all other items
20 std::set<int> rooms; // maybe 20 std::set<int> rooms; // maybe
21 bool mastery = false; // maybe 21 bool mastery = false; // maybe
22 bool panel_hunt = false; // maybe 22 bool panel_hunt = false; // maybe
23 23
24 void Merge(const Requirements& rhs) { 24 void Merge(const Requirements& rhs) {
25 if (rhs.disabled) { 25 if (rhs.disabled) {
@@ -228,7 +228,8 @@ class StateCalculator {
228 228
229 if (AP_IsPaintingShuffle()) { 229 if (AP_IsPaintingShuffle()) {
230 for (const PaintingExit& out_edge : room_obj.paintings) { 230 for (const PaintingExit& out_edge : room_obj.paintings) {
231 if (AP_GetPaintingMapping().count(out_edge.id)) { 231 if (AP_GetPaintingMapping().count(out_edge.id) &&
232 AP_GetCheckedPaintings().count(out_edge.id)) {
232 Exit painting_exit; 233 Exit painting_exit;
233 painting_exit.destination_room = GD_GetRoomForPainting( 234 painting_exit.destination_room = GD_GetRoomForPainting(
234 AP_GetPaintingMapping().at(out_edge.id)); 235 AP_GetPaintingMapping().at(out_edge.id));
@@ -286,7 +287,8 @@ class StateCalculator {
286 panel_boundary = new_panel_boundary; 287 panel_boundary = new_panel_boundary;
287 } 288 }
288 289
289 // Now that we know the full reachable area, let's make sure all doors are evaluated. 290 // Now that we know the full reachable area, let's make sure all doors are
291 // evaluated.
290 for (const Door& door : GD_GetDoors()) { 292 for (const Door& door : GD_GetDoors()) {
291 int discard = IsDoorReachable(door.id); 293 int discard = IsDoorReachable(door.id);
292 } 294 }
@@ -320,7 +322,8 @@ class StateCalculator {
320 return has_item ? kYes : kNo; 322 return has_item ? kYes : kNo;
321 } 323 }
322 324
323 Decision AreRequirementsSatisfied(const Requirements& reqs, std::map<std::string, bool>* report = nullptr) { 325 Decision AreRequirementsSatisfied(
326 const Requirements& reqs, std::map<std::string, bool>* report = nullptr) {
324 if (reqs.disabled) { 327 if (reqs.disabled) {
325 return kNo; 328 return kNo;
326 } 329 }
@@ -339,7 +342,7 @@ class StateCalculator {
339 final_decision = decision; 342 final_decision = decision;
340 } 343 }
341 } 344 }
342 345
343 for (int item_id : reqs.items) { 346 for (int item_id : reqs.items) {
344 bool has_item = AP_HasItem(item_id); 347 bool has_item = AP_HasItem(item_id);
345 if (report) { 348 if (report) {
@@ -353,10 +356,9 @@ class StateCalculator {
353 356
354 for (int room_id : reqs.rooms) { 357 for (int room_id : reqs.rooms) {
355 bool reachable = reachable_rooms_.count(room_id); 358 bool reachable = reachable_rooms_.count(room_id);
356 359
357 if (report) { 360 if (report) {
358 std::string report_name = 361 std::string report_name = "Reach \"" + GD_GetRoom(room_id).name + "\"";
359 "Reach \"" + GD_GetRoom(room_id).name + "\"";
360 (*report)[report_name] = reachable; 362 (*report)[report_name] = reachable;
361 } 363 }
362 364
@@ -364,7 +366,7 @@ class StateCalculator {
364 final_decision = kMaybe; 366 final_decision = kMaybe;
365 } 367 }
366 } 368 }
367 369
368 if (reqs.mastery) { 370 if (reqs.mastery) {
369 int achievements_accessible = 0; 371 int achievements_accessible = 0;
370 372
@@ -407,7 +409,7 @@ class StateCalculator {
407 std::to_string(AP_GetLevel2Requirement()) + " Panels"; 409 std::to_string(AP_GetLevel2Requirement()) + " Panels";
408 (*report)[report_name] = can_level2; 410 (*report)[report_name] = can_level2;
409 } 411 }
410 412
411 if (can_level2 && final_decision != kNo) { 413 if (can_level2 && final_decision != kNo) {
412 final_decision = kMaybe; 414 final_decision = kMaybe;
413 } 415 }
@@ -422,7 +424,7 @@ class StateCalculator {
422 } else { 424 } else {
423 door_report_[door_id] = {}; 425 door_report_[door_id] = {};
424 } 426 }
425 427
426 return AreRequirementsSatisfied(GetState().requirements.GetDoor(door_id), 428 return AreRequirementsSatisfied(GetState().requirements.GetDoor(door_id),
427 &door_report_[door_id]); 429 &door_report_[door_id]);
428 } 430 }