From 9bf6a50624284ab7422f56375b3e57c894200faf Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Fri, 25 Aug 2023 22:14:51 -0400 Subject: Panelsanity support --- assets/areas.yaml | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/ap_state.cpp | 22 ++++++--- src/ap_state.h | 4 +- src/area_popup.cpp | 23 +++++---- src/area_popup.h | 2 +- src/game_data.cpp | 132 ++++++++++++++++++++++++++++++++------------------ src/game_data.h | 8 ++- src/tracker_panel.cpp | 16 ++++-- 8 files changed, 263 insertions(+), 76 deletions(-) diff --git a/assets/areas.yaml b/assets/areas.yaml index 501db5a..1df2771 100755 --- a/assets/areas.yaml +++ b/assets/areas.yaml @@ -9,12 +9,20 @@ map: [1589, 1029] Hub Room: map: [1589, 924] + Dead End Area: + map: [1785, 1125] Pilgrim Room: map: [1493, 1564] + Pilgrim Antechamber: + fold_into: Pilgrim Room Crossroads: map: [1294, 720] + Lost Area: + fold_into: Crossroads Amen Name Area: fold_into: Crossroads + Suits Area: + map: [1566, 322] The Tenacious: map: [1589, 780] Warts Straw Area: @@ -25,6 +33,12 @@ map: [1766, 700] Hallway Room: map: [573, 1631] + Hallway Room (2): + fold_into: Hallway Room + Hallway Room (3): + fold_into: Hallway Room + Hallway Room (4): + fold_into: Hallway Room Dread Hallway: fold_into: Outside The Agreeable The Agreeable: @@ -35,10 +49,16 @@ map: [2251, 600] The Fearless: map: [1790, 2220] + The Fearless (First Floor): + fold_into: The Fearless + The Fearless (Second Floor): + fold_into: The Fearless The Observant: map: [2252, 193] The Incomparable: map: [2642, 872] + Eight Room: + fold_into: The Incomparable Orange Tower First Floor: map: [1285, 928] Color Hunt: @@ -47,6 +67,8 @@ map: [1935, 1575] Orange Tower Fourth Floor: map: [1365, 394] + Hot Crusts Area: + fold_into: Orange Tower Fourth Floor Orange Tower Fifth Floor: map: [1252, 1259] Orange Tower Seventh Floor: @@ -55,8 +77,32 @@ map: [1587, 2000] Courtyard: map: [863, 387] + First Second Third Fourth: + fold_into: Courtyard + Yellow Backside Area: + fold_into: Courtyard The Colorful: map: [863, 200] + The Colorful (Black): + fold_into: The Colorful + The Colorful (Blue): + fold_into: The Colorful + The Colorful (Brown): + fold_into: The Colorful + The Colorful (Gray): + fold_into: The Colorful + The Colorful (Green): + fold_into: The Colorful + The Colorful (Orange): + fold_into: The Colorful + The Colorful (Purple): + fold_into: The Colorful + The Colorful (Red): + fold_into: The Colorful + The Colorful (White): + fold_into: The Colorful + The Colorful (Yellow): + fold_into: The Colorful Welcome Back Area: map: [1472, 1233] Owl Hallway: @@ -85,24 +131,96 @@ map: [1845, 1883] The Bearer: map: [2155, 1764] + Bearer Side Area: + fold_into: The Bearer + The Bearer (East): + fold_into: The Bearer + The Bearer (North): + fold_into: The Bearer + The Bearer (South): + fold_into: The Bearer + The Bearer (West): + fold_into: The Bearer The Steady: map: [2121, 2182] + The Steady (Amber): + fold_into: The Steady + The Steady (Amethyst): + fold_into: The Steady + The Steady (Blueberry): + fold_into: The Steady + The Steady (Carnation): + fold_into: The Steady + The Steady (Cherry): + fold_into: The Steady + The Steady (Emerald): + fold_into: The Steady + The Steady (Lemon): + fold_into: The Steady + The Steady (Lilac): + fold_into: The Steady + The Steady (Lime): + fold_into: The Steady + The Steady (Orange): + fold_into: The Steady + The Steady (Plum): + fold_into: The Steady + The Steady (Rose): + fold_into: The Steady + The Steady (Ruby): + fold_into: The Steady + The Steady (Sapphire): + fold_into: The Steady + The Steady (Sunflower): + fold_into: The Steady + The Steady (Topaz): + fold_into: The Steady Knight Night Room: map: [1990, 1322] + Knight Night (Final): + fold_into: Knight Night Room + Knight Night (Outer Ring): + fold_into: Knight Night Room + Knight Night (Right Lower Segment): + fold_into: Knight Night Room + Knight Night (Right Upper Segment): + fold_into: Knight Night Room + Knight Night Exit: + fold_into: Knight Night Room The Artistic: map: [1151, 1793] The Artistic (Smiley): fold_into: The Artistic + The Artistic (Apple): + fold_into: The Artistic + The Artistic (Hint Room): + fold_into: The Artistic + The Artistic (Lattice): + fold_into: The Artistic + The Artistic (Panda): + fold_into: The Artistic The Discerning: map: [1098, 807] The Ecstatic: map: [972, 805] The Eyes They See: map: [955, 933] + Far Window: + fold_into: The Eyes They See Outside The Wondrous: map: [691, 524] The Wondrous: map: [648, 338] + The Wondrous (Bookcase): + fold_into: The Wondrous + The Wondrous (Chandelier): + fold_into: The Wondrous + The Wondrous (Table): + fold_into: The Wondrous + The Wondrous (Window): + fold_into: The Wondrous + Arrow Garden: + map: [555, 155] Elements Area: map: [908, 1632] The Wanderer: @@ -117,8 +235,14 @@ map: [1587, 1492] Rhyme Room (Target): fold_into: Rhyme Room + Rhyme Room (Circle): + fold_into: Rhyme Room + Rhyme Room (Looped Square): + fold_into: Rhyme Room Room Room: map: [2553, 2153] + Cellar: + fold_into: Room Room Outside The Wise: map: [1087, 1986] The Wise: @@ -129,5 +253,13 @@ map: [1368, 2103] Art Gallery: map: [2474, 1366] + Art Gallery (Second Floor): + fold_into: Art Gallery + Art Gallery (Third Floor): + fold_into: Art Gallery + Art Gallery (Fourth Floor): + fold_into: Art Gallery Challenge Room: map: [1486, 1357] + Roof: + map: [227, 1271] 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 { bool painting_shuffle = false; int mastery_requirement = 21; int level_2_requirement = 223; - bool reduce_checks = false; + LocationChecks location_checks = kNORMAL_LOCATIONS; VictoryCondition victory_condition = kTHE_END; std::map painting_mapping; @@ -122,7 +122,7 @@ struct APState { painting_mapping.clear(); mastery_requirement = 21; level_2_requirement = 223; - reduce_checks = false; + location_checks = kNORMAL_LOCATIONS; victory_condition = kTHE_END; connected = false; @@ -209,12 +209,11 @@ struct APState { data_storage_prefix = "Lingo_" + std::to_string(apclient->get_player_number()) + "_"; door_shuffle_mode = slot_data["shuffle_doors"].get(); - color_shuffle = slot_data["shuffle_colors"].get(); - painting_shuffle = slot_data["shuffle_paintings"].get(); + color_shuffle = slot_data["shuffle_colors"].get() == 1; + painting_shuffle = slot_data["shuffle_paintings"].get() == 1; mastery_requirement = slot_data["mastery_achievements"].get(); level_2_requirement = slot_data["level_2_requirement"].get(); - reduce_checks = (door_shuffle_mode == kNO_DOORS) && - slot_data["reduce_checks"].get(); + location_checks = slot_data["location_checks"].get(); victory_condition = slot_data["victory_condition"].get(); @@ -444,7 +443,16 @@ int AP_GetMasteryRequirement() { return GetState().mastery_requirement; } int AP_GetLevel2Requirement() { return GetState().level_2_requirement; } -bool AP_IsReduceChecks() { return GetState().reduce_checks; } +bool AP_IsLocationVisible(int classification) { + switch (GetState().location_checks) { + case kNORMAL_LOCATIONS: + return classification & kLOCATION_NORMAL; + case kREDUCED_LOCATIONS: + return classification & kLOCATION_REDUCED; + case kPANELSANITY: + return classification & kLOCATION_INSANITY; + } +} VictoryCondition AP_GetVictoryCondition() { 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 }; enum VictoryCondition { kTHE_END = 0, kTHE_MASTER = 1, kLEVEL_2 = 2 }; +enum LocationChecks { kNORMAL_LOCATIONS = 0, kREDUCED_LOCATIONS = 1, kPANELSANITY = 2 }; + void AP_SetTrackerFrame(TrackerFrame* tracker_frame); void AP_Connect(std::string server, std::string player, std::string password); @@ -34,7 +36,7 @@ int AP_GetMasteryRequirement(); int AP_GetLevel2Requirement(); -bool AP_IsReduceChecks(); +bool AP_IsLocationVisible(int classification); VictoryCondition AP_GetVictoryCondition(); 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 @@ #include "tracker_state.h" AreaPopup::AreaPopup(wxWindow* parent, int area_id) - : wxPanel(parent, wxID_ANY), area_id_(area_id) { + : wxScrolledWindow(parent, wxID_ANY), area_id_(area_id) { const MapArea& map_area = GD_GetMapArea(area_id); wxFlexGridSizer* section_sizer = new wxFlexGridSizer(2, 10, 10); @@ -34,6 +34,7 @@ AreaPopup::AreaPopup(wxWindow* parent, int area_id) top_sizer->Add(section_sizer, wxSizerFlags().DoubleBorder(wxALL).Expand()); SetSizerAndFit(top_sizer); + SetScrollRate(5, 5); SetBackgroundColour(*wxBLACK); Hide(); @@ -44,18 +45,16 @@ void AreaPopup::UpdateIndicators() { for (int section_id = 0; section_id < map_area.locations.size(); section_id++) { const Location& location = map_area.locations.at(section_id); - if (location.exclude_reduce) { - wxSizer* container_sizer = - section_labels_[section_id]->GetContainingSizer(); + wxSizer* container_sizer = + section_labels_[section_id]->GetContainingSizer(); - if (AP_IsReduceChecks()) { - container_sizer->Hide(section_labels_[section_id]); - container_sizer->Hide(eye_indicators_[section_id]); - continue; - } else { - container_sizer->Show(section_labels_[section_id]); - container_sizer->Show(eye_indicators_[section_id]); - } + if (!AP_IsLocationVisible(location.classification)) { + container_sizer->Hide(section_labels_[section_id]); + container_sizer->Hide(eye_indicators_[section_id]); + continue; + } else { + container_sizer->Show(section_labels_[section_id]); + container_sizer->Show(eye_indicators_[section_id]); } 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 @@ #include "eye_indicator.h" -class AreaPopup : public wxPanel { +class AreaPopup : public wxScrolledWindow { public: AreaPopup(wxWindow* parent, int area_id); 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 @@ #include #include +#include + +#include "logger.h" namespace { @@ -49,6 +52,9 @@ struct GameData { std::vector achievement_panels_; + bool loaded_area_data_ = false; + std::set malconfigured_areas_; + GameData() { YAML::Node lingo_config = YAML::LoadFile("assets/LL1.yaml"); YAML::Node areas_config = YAML::LoadFile("assets/areas.yaml"); @@ -179,7 +185,8 @@ struct GameData { if (panel_it.second["required_panel"].IsMap()) { std::string rp_room = room_obj.name; if (panel_it.second["required_panel"]["room"]) { - rp_room = panel_it.second["required_panel"]["room"].as(); + rp_room = + panel_it.second["required_panel"]["room"].as(); } panel_obj.required_panels.push_back(AddOrGetPanel( @@ -204,7 +211,8 @@ struct GameData { if (panel_it.second["achievement"]) { panel_obj.achievement = true; - panel_obj.achievement_name = panel_it.second["achievement"].as(); + panel_obj.achievement_name = + panel_it.second["achievement"].as(); achievement_panels_.push_back(panel_id); } @@ -356,71 +364,88 @@ struct GameData { } } + loaded_area_data_ = true; + + // Only locations for the panels are kept here. + std::map> locations_by_name; + for (const Panel &panel : panels_) { - if (panel.check) { - int room_id = panel.room; - std::string room_name = rooms_[room_id].name; + int room_id = panel.room; + std::string room_name = rooms_[room_id].name; - 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; - } + 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; + } - int area_id = AddOrGetArea(area_name); - MapArea &map_area = map_areas_[area_id]; - // room field should be the original room ID - map_area.locations.push_back( - {.name = panel.name, - .ap_location_name = room_name + " - " + panel.name, - .room = panel.room, - .panels = {panel.id}, - .exclude_reduce = panel.exclude_reduce}); + int classification = kLOCATION_INSANITY; + if (panel.check) { + classification |= kLOCATION_NORMAL; + if (!panel.exclude_reduce) { + classification |= kLOCATION_REDUCED; + } } + + int area_id = AddOrGetArea(area_name); + MapArea &map_area = map_areas_[area_id]; + // room field should be the original room ID + map_area.locations.push_back( + {.name = panel.name, + .ap_location_name = room_name + " - " + panel.name, + .room = panel.room, + .panels = {panel.id}, + .classification = classification}); + locations_by_name[map_area.locations.back().ap_location_name] = { + area_id, map_area.locations.size() - 1}; } for (int door_id : door_definition_order_) { const Door &door = doors_.at(door_id); if (!door.skip_location) { - int room_id = door.room; - std::string area_name = rooms_[room_id].name; - std::string section_name; + int classification = kLOCATION_NORMAL; + if (!door.exclude_reduce) { + classification |= kLOCATION_REDUCED; + } - size_t divider_pos = door.location_name.find(" - "); - if (divider_pos == std::string::npos) { - section_name = door.location_name; + if (locations_by_name.count(door.location_name)) { + auto [area_id, section_id] = locations_by_name[door.location_name]; + map_areas_[area_id].locations[section_id].classification |= + classification; } else { - area_name = door.location_name.substr(0, divider_pos); - section_name = door.location_name.substr(divider_pos + 3); - } + int room_id = door.room; + std::string area_name = rooms_[room_id].name; + std::string section_name; + + size_t divider_pos = door.location_name.find(" - "); + if (divider_pos == std::string::npos) { + section_name = door.location_name; + } else { + area_name = door.location_name.substr(0, divider_pos); + section_name = door.location_name.substr(divider_pos + 3); + } - if (fold_areas.count(area_name)) { - int fold_area_id = fold_areas[area_name]; - area_name = map_areas_[fold_area_id].name; - } + if (fold_areas.count(area_name)) { + int fold_area_id = fold_areas[area_name]; + area_name = map_areas_[fold_area_id].name; + } - int area_id = AddOrGetArea(area_name); - MapArea &map_area = map_areas_[area_id]; - // room field should be the original room ID - map_area.locations.push_back({.name = section_name, - .ap_location_name = door.location_name, - .room = door.room, - .panels = door.panels, - .exclude_reduce = door.exclude_reduce}); + int area_id = AddOrGetArea(area_name); + MapArea &map_area = map_areas_[area_id]; + // room field should be the original room ID + map_area.locations.push_back({.name = section_name, + .ap_location_name = door.location_name, + .room = door.room, + .panels = door.panels, + .classification = classification}); + } } } for (MapArea &map_area : map_areas_) { - bool all_exclude_reduce = true; for (const Location &location : map_area.locations) { - if (!location.exclude_reduce) { - all_exclude_reduce = false; - break; - } - } - if (all_exclude_reduce) { - map_area.exclude_reduce = true; + map_area.classification |= location.classification; } } @@ -450,6 +475,13 @@ struct GameData { starting_room_obj.exits.push_back( Exit{.destination_room = AddOrGetRoom("Pilgrim Antechamber"), .door = fake_pilgrim_door_id}); + + // Report errors. + for (const std::string &area : malconfigured_areas_) { + std::ostringstream errstr; + errstr << "Area data not found for: " << area; + TrackerLog(errstr.str()); + } } int AddOrGetRoom(std::string room) { @@ -487,6 +519,10 @@ struct GameData { int AddOrGetArea(std::string area) { if (!area_by_id_.count(area)) { + if (loaded_area_data_) { + malconfigured_areas_.insert(area); + } + int area_id = map_areas_.size(); area_by_id_[area] = area_id; 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 { kGray }; +constexpr int kLOCATION_NORMAL = 1; +constexpr int kLOCATION_REDUCED = 2; +constexpr int kLOCATION_INSANITY = 4; + struct Panel { int id; int room; @@ -76,7 +80,7 @@ struct Location { std::string ap_location_name; int room; std::vector panels; - bool exclude_reduce = false; + int classification = 0; }; struct MapArea { @@ -85,7 +89,7 @@ struct MapArea { std::vector locations; int map_x; int map_y; - bool exclude_reduce = false; + int classification = 0; }; const std::vector& 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) { void TrackerPanel::OnMouseMove(wxMouseEvent &event) { for (AreaIndicator &area : areas_) { - if (area.active && - area.real_x1 <= event.GetX() && event.GetX() < area.real_x2 && - area.real_y1 <= event.GetY() && event.GetY() < area.real_y2) { + if (area.active && area.real_x1 <= event.GetX() && + event.GetX() < area.real_x2 && area.real_y1 <= event.GetY() && + event.GetY() < area.real_y2) { area.popup->Show(); } else { area.popup->Hide(); @@ -95,7 +95,7 @@ void TrackerPanel::Redraw() { const wxBrush *brush_color = wxGREY_BRUSH; const MapArea &map_area = GD_GetMapArea(area.area_id); - if (map_area.exclude_reduce && AP_IsReduceChecks()) { + if (!AP_IsLocationVisible(map_area.classification)) { area.active = false; continue; } else { @@ -106,7 +106,9 @@ void TrackerPanel::Redraw() { bool has_unreachable_unchecked = false; for (int section_id = 0; section_id < map_area.locations.size(); section_id++) { - if (!AP_HasCheckedGameLocation(area.area_id, section_id)) { + if (AP_IsLocationVisible( + map_area.locations.at(section_id).classification) && + !AP_HasCheckedGameLocation(area.area_id, section_id)) { if (IsLocationReachable(area.area_id, section_id)) { has_reachable_unchecked = true; } else { @@ -146,6 +148,10 @@ void TrackerPanel::Redraw() { final_x + map_area.map_x * final_width / image_size.GetWidth(); int popup_y = final_y + map_area.map_y * final_width / image_size.GetWidth(); + + area.popup->SetMaxSize(panel_size); + area.popup->GetSizer()->Fit(area.popup); + if (popup_x + area.popup->GetSize().GetWidth() > panel_size.GetWidth()) { popup_x = panel_size.GetWidth() - area.popup->GetSize().GetWidth(); } -- cgit 1.4.1