about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2023-08-25 22:14:51 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2023-08-25 22:14:51 -0400
commit9bf6a50624284ab7422f56375b3e57c894200faf (patch)
tree9951ee08e5ebbed1363d190b57fa01606e0fbb94 /src
parentbaf43ede759f9ff0ca8c71de764e0389469f9ae1 (diff)
downloadlingo-ap-tracker-9bf6a50624284ab7422f56375b3e57c894200faf.tar.gz
lingo-ap-tracker-9bf6a50624284ab7422f56375b3e57c894200faf.tar.bz2
lingo-ap-tracker-9bf6a50624284ab7422f56375b3e57c894200faf.zip
Panelsanity support
Diffstat (limited to 'src')
-rw-r--r--src/ap_state.cpp22
-rw-r--r--src/ap_state.h4
-rw-r--r--src/area_popup.cpp23
-rw-r--r--src/area_popup.h2
-rw-r--r--src/game_data.cpp132
-rw-r--r--src/game_data.h8
-rw-r--r--src/tracker_panel.cpp16
7 files changed, 131 insertions, 76 deletions
diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 02f1f5a..ced4f83 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp
@@ -62,7 +62,7 @@ struct APState {
62 bool painting_shuffle = false; 62 bool painting_shuffle = false;
63 int mastery_requirement = 21; 63 int mastery_requirement = 21;
64 int level_2_requirement = 223; 64 int level_2_requirement = 223;
65 bool reduce_checks = false; 65 LocationChecks location_checks = kNORMAL_LOCATIONS;
66 VictoryCondition victory_condition = kTHE_END; 66 VictoryCondition victory_condition = kTHE_END;
67 67
68 std::map<std::string, std::string> painting_mapping; 68 std::map<std::string, std::string> painting_mapping;
@@ -122,7 +122,7 @@ struct APState {
122 painting_mapping.clear(); 122 painting_mapping.clear();
123 mastery_requirement = 21; 123 mastery_requirement = 21;
124 level_2_requirement = 223; 124 level_2_requirement = 223;
125 reduce_checks = false; 125 location_checks = kNORMAL_LOCATIONS;
126 victory_condition = kTHE_END; 126 victory_condition = kTHE_END;
127 127
128 connected = false; 128 connected = false;
@@ -209,12 +209,11 @@ struct APState {
209 data_storage_prefix = 209 data_storage_prefix =
210 "Lingo_" + std::to_string(apclient->get_player_number()) + "_"; 210 "Lingo_" + std::to_string(apclient->get_player_number()) + "_";
211 door_shuffle_mode = slot_data["shuffle_doors"].get<DoorShuffleMode>(); 211 door_shuffle_mode = slot_data["shuffle_doors"].get<DoorShuffleMode>();
212 color_shuffle = slot_data["shuffle_colors"].get<bool>(); 212 color_shuffle = slot_data["shuffle_colors"].get<int>() == 1;
213 painting_shuffle = slot_data["shuffle_paintings"].get<bool>(); 213 painting_shuffle = slot_data["shuffle_paintings"].get<int>() == 1;
214 mastery_requirement = slot_data["mastery_achievements"].get<int>(); 214 mastery_requirement = slot_data["mastery_achievements"].get<int>();
215 level_2_requirement = slot_data["level_2_requirement"].get<int>(); 215 level_2_requirement = slot_data["level_2_requirement"].get<int>();
216 reduce_checks = (door_shuffle_mode == kNO_DOORS) && 216 location_checks = slot_data["location_checks"].get<LocationChecks>();
217 slot_data["reduce_checks"].get<bool>();
218 victory_condition = 217 victory_condition =
219 slot_data["victory_condition"].get<VictoryCondition>(); 218 slot_data["victory_condition"].get<VictoryCondition>();
220 219
@@ -444,7 +443,16 @@ int AP_GetMasteryRequirement() { return GetState().mastery_requirement; }
444 443
445int AP_GetLevel2Requirement() { return GetState().level_2_requirement; } 444int AP_GetLevel2Requirement() { return GetState().level_2_requirement; }
446 445
447bool AP_IsReduceChecks() { return GetState().reduce_checks; } 446bool AP_IsLocationVisible(int classification) {
447 switch (GetState().location_checks) {
448 case kNORMAL_LOCATIONS:
449 return classification & kLOCATION_NORMAL;
450 case kREDUCED_LOCATIONS:
451 return classification & kLOCATION_REDUCED;
452 case kPANELSANITY:
453 return classification & kLOCATION_INSANITY;
454 }
455}
448 456
449VictoryCondition AP_GetVictoryCondition() { 457VictoryCondition AP_GetVictoryCondition() {
450 return GetState().victory_condition; 458 return GetState().victory_condition;
diff --git a/src/ap_state.h b/src/ap_state.h index fb5c969..e9b9f92 100644 --- a/src/ap_state.h +++ b/src/ap_state.h
@@ -12,6 +12,8 @@ enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 };
12 12
13enum VictoryCondition { kTHE_END = 0, kTHE_MASTER = 1, kLEVEL_2 = 2 }; 13enum VictoryCondition { kTHE_END = 0, kTHE_MASTER = 1, kLEVEL_2 = 2 };
14 14
15enum LocationChecks { kNORMAL_LOCATIONS = 0, kREDUCED_LOCATIONS = 1, kPANELSANITY = 2 };
16
15void AP_SetTrackerFrame(TrackerFrame* tracker_frame); 17void AP_SetTrackerFrame(TrackerFrame* tracker_frame);
16 18
17void AP_Connect(std::string server, std::string player, std::string password); 19void AP_Connect(std::string server, std::string player, std::string password);
@@ -34,7 +36,7 @@ int AP_GetMasteryRequirement();
34 36
35int AP_GetLevel2Requirement(); 37int AP_GetLevel2Requirement();
36 38
37bool AP_IsReduceChecks(); 39bool AP_IsLocationVisible(int classification);
38 40
39VictoryCondition AP_GetVictoryCondition(); 41VictoryCondition AP_GetVictoryCondition();
40 42
diff --git a/src/area_popup.cpp b/src/area_popup.cpp index a3ac588..28554d0 100644 --- a/src/area_popup.cpp +++ b/src/area_popup.cpp
@@ -5,7 +5,7 @@
5#include "tracker_state.h" 5#include "tracker_state.h"
6 6
7AreaPopup::AreaPopup(wxWindow* parent, int area_id) 7AreaPopup::AreaPopup(wxWindow* parent, int area_id)
8 : wxPanel(parent, wxID_ANY), area_id_(area_id) { 8 : wxScrolledWindow(parent, wxID_ANY), area_id_(area_id) {
9 const MapArea& map_area = GD_GetMapArea(area_id); 9 const MapArea& map_area = GD_GetMapArea(area_id);
10 10
11 wxFlexGridSizer* section_sizer = new wxFlexGridSizer(2, 10, 10); 11 wxFlexGridSizer* section_sizer = new wxFlexGridSizer(2, 10, 10);
@@ -34,6 +34,7 @@ AreaPopup::AreaPopup(wxWindow* parent, int area_id)
34 top_sizer->Add(section_sizer, wxSizerFlags().DoubleBorder(wxALL).Expand()); 34 top_sizer->Add(section_sizer, wxSizerFlags().DoubleBorder(wxALL).Expand());
35 35
36 SetSizerAndFit(top_sizer); 36 SetSizerAndFit(top_sizer);
37 SetScrollRate(5, 5);
37 38
38 SetBackgroundColour(*wxBLACK); 39 SetBackgroundColour(*wxBLACK);
39 Hide(); 40 Hide();
@@ -44,18 +45,16 @@ void AreaPopup::UpdateIndicators() {
44 for (int section_id = 0; section_id < map_area.locations.size(); 45 for (int section_id = 0; section_id < map_area.locations.size();
45 section_id++) { 46 section_id++) {
46 const Location& location = map_area.locations.at(section_id); 47 const Location& location = map_area.locations.at(section_id);
47 if (location.exclude_reduce) { 48 wxSizer* container_sizer =
48 wxSizer* container_sizer = 49 section_labels_[section_id]->GetContainingSizer();
49 section_labels_[section_id]->GetContainingSizer();
50 50
51 if (AP_IsReduceChecks()) { 51 if (!AP_IsLocationVisible(location.classification)) {
52 container_sizer->Hide(section_labels_[section_id]); 52 container_sizer->Hide(section_labels_[section_id]);
53 container_sizer->Hide(eye_indicators_[section_id]); 53 container_sizer->Hide(eye_indicators_[section_id]);
54 continue; 54 continue;
55 } else { 55 } else {
56 container_sizer->Show(section_labels_[section_id]); 56 container_sizer->Show(section_labels_[section_id]);
57 container_sizer->Show(eye_indicators_[section_id]); 57 container_sizer->Show(eye_indicators_[section_id]);
58 }
59 } 58 }
60 59
61 bool checked = AP_HasCheckedGameLocation(area_id_, section_id); 60 bool checked = AP_HasCheckedGameLocation(area_id_, section_id);
diff --git a/src/area_popup.h b/src/area_popup.h index b602b63..d5f6a50 100644 --- a/src/area_popup.h +++ b/src/area_popup.h
@@ -9,7 +9,7 @@
9 9
10#include "eye_indicator.h" 10#include "eye_indicator.h"
11 11
12class AreaPopup : public wxPanel { 12class AreaPopup : public wxScrolledWindow {
13 public: 13 public:
14 AreaPopup(wxWindow* parent, int area_id); 14 AreaPopup(wxWindow* parent, int area_id);
15 15
diff --git a/src/game_data.cpp b/src/game_data.cpp index 4393373..06eb80a 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp
@@ -4,6 +4,9 @@
4#include <yaml-cpp/yaml.h> 4#include <yaml-cpp/yaml.h>
5 5
6#include <iostream> 6#include <iostream>
7#include <sstream>
8
9#include "logger.h"
7 10
8namespace { 11namespace {
9 12
@@ -49,6 +52,9 @@ struct GameData {
49 52
50 std::vector<int> achievement_panels_; 53 std::vector<int> achievement_panels_;
51 54
55 bool loaded_area_data_ = false;
56 std::set<std::string> malconfigured_areas_;
57
52 GameData() { 58 GameData() {
53 YAML::Node lingo_config = YAML::LoadFile("assets/LL1.yaml"); 59 YAML::Node lingo_config = YAML::LoadFile("assets/LL1.yaml");
54 YAML::Node areas_config = YAML::LoadFile("assets/areas.yaml"); 60 YAML::Node areas_config = YAML::LoadFile("assets/areas.yaml");
@@ -179,7 +185,8 @@ struct GameData {
179 if (panel_it.second["required_panel"].IsMap()) { 185 if (panel_it.second["required_panel"].IsMap()) {
180 std::string rp_room = room_obj.name; 186 std::string rp_room = room_obj.name;
181 if (panel_it.second["required_panel"]["room"]) { 187 if (panel_it.second["required_panel"]["room"]) {
182 rp_room = panel_it.second["required_panel"]["room"].as<std::string>(); 188 rp_room =
189 panel_it.second["required_panel"]["room"].as<std::string>();
183 } 190 }
184 191
185 panel_obj.required_panels.push_back(AddOrGetPanel( 192 panel_obj.required_panels.push_back(AddOrGetPanel(
@@ -204,7 +211,8 @@ struct GameData {
204 211
205 if (panel_it.second["achievement"]) { 212 if (panel_it.second["achievement"]) {
206 panel_obj.achievement = true; 213 panel_obj.achievement = true;
207 panel_obj.achievement_name = panel_it.second["achievement"].as<std::string>(); 214 panel_obj.achievement_name =
215 panel_it.second["achievement"].as<std::string>();
208 216
209 achievement_panels_.push_back(panel_id); 217 achievement_panels_.push_back(panel_id);
210 } 218 }
@@ -356,71 +364,88 @@ struct GameData {
356 } 364 }
357 } 365 }
358 366
367 loaded_area_data_ = true;
368
369 // Only locations for the panels are kept here.
370 std::map<std::string, std::tuple<int, int>> locations_by_name;
371
359 for (const Panel &panel : panels_) { 372 for (const Panel &panel : panels_) {
360 if (panel.check) { 373 int room_id = panel.room;
361 int room_id = panel.room; 374 std::string room_name = rooms_[room_id].name;
362 std::string room_name = rooms_[room_id].name;
363 375
364 std::string area_name = room_name; 376 std::string area_name = room_name;
365 if (fold_areas.count(room_name)) { 377 if (fold_areas.count(room_name)) {
366 int fold_area_id = fold_areas[room_name]; 378 int fold_area_id = fold_areas[room_name];
367 area_name = map_areas_[fold_area_id].name; 379 area_name = map_areas_[fold_area_id].name;
368 } 380 }
369 381
370 int area_id = AddOrGetArea(area_name); 382 int classification = kLOCATION_INSANITY;
371 MapArea &map_area = map_areas_[area_id]; 383 if (panel.check) {
372 // room field should be the original room ID 384 classification |= kLOCATION_NORMAL;
373 map_area.locations.push_back( 385 if (!panel.exclude_reduce) {
374 {.name = panel.name, 386 classification |= kLOCATION_REDUCED;
375 .ap_location_name = room_name + " - " + panel.name, 387 }
376 .room = panel.room,
377 .panels = {panel.id},
378 .exclude_reduce = panel.exclude_reduce});
379 } 388 }
389
390 int area_id = AddOrGetArea(area_name);
391 MapArea &map_area = map_areas_[area_id];
392 // room field should be the original room ID
393 map_area.locations.push_back(
394 {.name = panel.name,
395 .ap_location_name = room_name + " - " + panel.name,
396 .room = panel.room,
397 .panels = {panel.id},
398 .classification = classification});
399 locations_by_name[map_area.locations.back().ap_location_name] = {
400 area_id, map_area.locations.size() - 1};
380 } 401 }
381 402
382 for (int door_id : door_definition_order_) { 403 for (int door_id : door_definition_order_) {
383 const Door &door = doors_.at(door_id); 404 const Door &door = doors_.at(door_id);
384 405
385 if (!door.skip_location) { 406 if (!door.skip_location) {
386 int room_id = door.room; 407 int classification = kLOCATION_NORMAL;
387 std::string area_name = rooms_[room_id].name; 408 if (!door.exclude_reduce) {
388 std::string section_name; 409 classification |= kLOCATION_REDUCED;
410 }
389 411
390 size_t divider_pos = door.location_name.find(" - "); 412 if (locations_by_name.count(door.location_name)) {
391 if (divider_pos == std::string::npos) { 413 auto [area_id, section_id] = locations_by_name[door.location_name];
392 section_name = door.location_name; 414 map_areas_[area_id].locations[section_id].classification |=
415 classification;
393 } else { 416 } else {
394 area_name = door.location_name.substr(0, divider_pos); 417 int room_id = door.room;
395 section_name = door.location_name.substr(divider_pos + 3); 418 std::string area_name = rooms_[room_id].name;
396 } 419 std::string section_name;
420
421 size_t divider_pos = door.location_name.find(" - ");
422 if (divider_pos == std::string::npos) {
423 section_name = door.location_name;
424 } else {
425 area_name = door.location_name.substr(0, divider_pos);
426 section_name = door.location_name.substr(divider_pos + 3);
427 }
397 428
398 if (fold_areas.count(area_name)) { 429 if (fold_areas.count(area_name)) {
399 int fold_area_id = fold_areas[area_name]; 430 int fold_area_id = fold_areas[area_name];
400 area_name = map_areas_[fold_area_id].name; 431 area_name = map_areas_[fold_area_id].name;
401 } 432 }
402 433
403 int area_id = AddOrGetArea(area_name); 434 int area_id = AddOrGetArea(area_name);
404 MapArea &map_area = map_areas_[area_id]; 435 MapArea &map_area = map_areas_[area_id];
405 // room field should be the original room ID 436 // room field should be the original room ID
406 map_area.locations.push_back({.name = section_name, 437 map_area.locations.push_back({.name = section_name,
407 .ap_location_name = door.location_name, 438 .ap_location_name = door.location_name,
408 .room = door.room, 439 .room = door.room,
409 .panels = door.panels, 440 .panels = door.panels,
410 .exclude_reduce = door.exclude_reduce}); 441 .classification = classification});
442 }
411 } 443 }
412 } 444 }
413 445
414 for (MapArea &map_area : map_areas_) { 446 for (MapArea &map_area : map_areas_) {
415 bool all_exclude_reduce = true;
416 for (const Location &location : map_area.locations) { 447 for (const Location &location : map_area.locations) {
417 if (!location.exclude_reduce) { 448 map_area.classification |= location.classification;
418 all_exclude_reduce = false;
419 break;
420 }
421 }
422 if (all_exclude_reduce) {
423 map_area.exclude_reduce = true;
424 } 449 }
425 } 450 }
426 451
@@ -450,6 +475,13 @@ struct GameData {
450 starting_room_obj.exits.push_back( 475 starting_room_obj.exits.push_back(
451 Exit{.destination_room = AddOrGetRoom("Pilgrim Antechamber"), 476 Exit{.destination_room = AddOrGetRoom("Pilgrim Antechamber"),
452 .door = fake_pilgrim_door_id}); 477 .door = fake_pilgrim_door_id});
478
479 // Report errors.
480 for (const std::string &area : malconfigured_areas_) {
481 std::ostringstream errstr;
482 errstr << "Area data not found for: " << area;
483 TrackerLog(errstr.str());
484 }
453 } 485 }
454 486
455 int AddOrGetRoom(std::string room) { 487 int AddOrGetRoom(std::string room) {
@@ -487,6 +519,10 @@ struct GameData {
487 519
488 int AddOrGetArea(std::string area) { 520 int AddOrGetArea(std::string area) {
489 if (!area_by_id_.count(area)) { 521 if (!area_by_id_.count(area)) {
522 if (loaded_area_data_) {
523 malconfigured_areas_.insert(area);
524 }
525
490 int area_id = map_areas_.size(); 526 int area_id = map_areas_.size();
491 area_by_id_[area] = area_id; 527 area_by_id_[area] = area_id;
492 map_areas_.push_back({.id = area_id, .name = area}); 528 map_areas_.push_back({.id = area_id, .name = area});
diff --git a/src/game_data.h b/src/game_data.h index 959d5c8..d9c909b 100644 --- a/src/game_data.h +++ b/src/game_data.h
@@ -19,6 +19,10 @@ enum class LingoColor {
19 kGray 19 kGray
20}; 20};
21 21
22constexpr int kLOCATION_NORMAL = 1;
23constexpr int kLOCATION_REDUCED = 2;
24constexpr int kLOCATION_INSANITY = 4;
25
22struct Panel { 26struct Panel {
23 int id; 27 int id;
24 int room; 28 int room;
@@ -76,7 +80,7 @@ struct Location {
76 std::string ap_location_name; 80 std::string ap_location_name;
77 int room; 81 int room;
78 std::vector<int> panels; 82 std::vector<int> panels;
79 bool exclude_reduce = false; 83 int classification = 0;
80}; 84};
81 85
82struct MapArea { 86struct MapArea {
@@ -85,7 +89,7 @@ struct MapArea {
85 std::vector<Location> locations; 89 std::vector<Location> locations;
86 int map_x; 90 int map_x;
87 int map_y; 91 int map_y;
88 bool exclude_reduce = false; 92 int classification = 0;
89}; 93};
90 94
91const std::vector<MapArea>& GD_GetMapAreas(); 95const std::vector<MapArea>& GD_GetMapAreas();
diff --git a/src/tracker_panel.cpp b/src/tracker_panel.cpp index 90b8eb9..40d3ced 100644 --- a/src/tracker_panel.cpp +++ b/src/tracker_panel.cpp
@@ -52,9 +52,9 @@ void TrackerPanel::OnPaint(wxPaintEvent &event) {
52 52
53void TrackerPanel::OnMouseMove(wxMouseEvent &event) { 53void TrackerPanel::OnMouseMove(wxMouseEvent &event) {
54 for (AreaIndicator &area : areas_) { 54 for (AreaIndicator &area : areas_) {
55 if (area.active && 55 if (area.active && area.real_x1 <= event.GetX() &&
56 area.real_x1 <= event.GetX() && event.GetX() < area.real_x2 && 56 event.GetX() < area.real_x2 && area.real_y1 <= event.GetY() &&
57 area.real_y1 <= event.GetY() && event.GetY() < area.real_y2) { 57 event.GetY() < area.real_y2) {
58 area.popup->Show(); 58 area.popup->Show();
59 } else { 59 } else {
60 area.popup->Hide(); 60 area.popup->Hide();
@@ -95,7 +95,7 @@ void TrackerPanel::Redraw() {
95 const wxBrush *brush_color = wxGREY_BRUSH; 95 const wxBrush *brush_color = wxGREY_BRUSH;
96 96
97 const MapArea &map_area = GD_GetMapArea(area.area_id); 97 const MapArea &map_area = GD_GetMapArea(area.area_id);
98 if (map_area.exclude_reduce && AP_IsReduceChecks()) { 98 if (!AP_IsLocationVisible(map_area.classification)) {
99 area.active = false; 99 area.active = false;
100 continue; 100 continue;
101 } else { 101 } else {
@@ -106,7 +106,9 @@ void TrackerPanel::Redraw() {
106 bool has_unreachable_unchecked = false; 106 bool has_unreachable_unchecked = false;
107 for (int section_id = 0; section_id < map_area.locations.size(); 107 for (int section_id = 0; section_id < map_area.locations.size();
108 section_id++) { 108 section_id++) {
109 if (!AP_HasCheckedGameLocation(area.area_id, section_id)) { 109 if (AP_IsLocationVisible(
110 map_area.locations.at(section_id).classification) &&
111 !AP_HasCheckedGameLocation(area.area_id, section_id)) {
110 if (IsLocationReachable(area.area_id, section_id)) { 112 if (IsLocationReachable(area.area_id, section_id)) {
111 has_reachable_unchecked = true; 113 has_reachable_unchecked = true;
112 } else { 114 } else {
@@ -146,6 +148,10 @@ void TrackerPanel::Redraw() {
146 final_x + map_area.map_x * final_width / image_size.GetWidth(); 148 final_x + map_area.map_x * final_width / image_size.GetWidth();
147 int popup_y = 149 int popup_y =
148 final_y + map_area.map_y * final_width / image_size.GetWidth(); 150 final_y + map_area.map_y * final_width / image_size.GetWidth();
151
152 area.popup->SetMaxSize(panel_size);
153 area.popup->GetSizer()->Fit(area.popup);
154
149 if (popup_x + area.popup->GetSize().GetWidth() > panel_size.GetWidth()) { 155 if (popup_x + area.popup->GetSize().GetWidth() > panel_size.GetWidth()) {
150 popup_x = panel_size.GetWidth() - area.popup->GetSize().GetWidth(); 156 popup_x = panel_size.GetWidth() - area.popup->GetSize().GetWidth();
151 } 157 }