about summary refs log tree commit diff stats
path: root/src/tracker_state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tracker_state.cpp')
-rw-r--r--src/tracker_state.cpp48
1 files changed, 44 insertions, 4 deletions
diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index eaf3e6b..14d302b 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp
@@ -1,5 +1,8 @@
1#include "tracker_state.h" 1#include "tracker_state.h"
2 2
3#include <fmt/core.h>
4#include <hkutil/string.h>
5
3#include <list> 6#include <list>
4#include <map> 7#include <map>
5#include <mutex> 8#include <mutex>
@@ -9,6 +12,7 @@
9 12
10#include "ap_state.h" 13#include "ap_state.h"
11#include "game_data.h" 14#include "game_data.h"
15#include "logger.h"
12 16
13namespace { 17namespace {
14 18
@@ -231,7 +235,9 @@ class StateCalculator {
231 PaintingExit target_painting = 235 PaintingExit target_painting =
232 GD_GetPaintingExit(GD_GetPaintingByName( 236 GD_GetPaintingExit(GD_GetPaintingByName(
233 AP_GetPaintingMapping().at(cur_painting.internal_id))); 237 AP_GetPaintingMapping().at(cur_painting.internal_id)));
238 painting_exit.source_room = cur_painting.room;
234 painting_exit.destination_room = target_painting.room; 239 painting_exit.destination_room = target_painting.room;
240 painting_exit.type = EntranceType::kPainting;
235 241
236 new_boundary.push_back(painting_exit); 242 new_boundary.push_back(painting_exit);
237 } 243 }
@@ -258,6 +264,12 @@ class StateCalculator {
258 reachable_rooms_.insert(room_exit.destination_room); 264 reachable_rooms_.insert(room_exit.destination_room);
259 reachable_changed = true; 265 reachable_changed = true;
260 266
267#ifndef NDEBUG
268 std::list<int> room_path = paths_[room_exit.source_room];
269 room_path.push_back(room_exit.destination_room);
270 paths_[room_exit.destination_room] = room_path;
271#endif
272
261 const Room& room_obj = GD_GetRoom(room_exit.destination_room); 273 const Room& room_obj = GD_GetRoom(room_exit.destination_room);
262 for (const Exit& out_edge : room_obj.exits) { 274 for (const Exit& out_edge : room_obj.exits) {
263 if (out_edge.type == EntranceType::kPainting && 275 if (out_edge.type == EntranceType::kPainting &&
@@ -296,20 +308,33 @@ class StateCalculator {
296 308
297 if (AP_HasEarlyColorHallways() && room_obj.name == "Starting Room") { 309 if (AP_HasEarlyColorHallways() && room_obj.name == "Starting Room") {
298 new_boundary.push_back( 310 new_boundary.push_back(
299 {.destination_room = GD_GetRoomByName("Outside The Undeterred"), 311 {.source_room = room_exit.destination_room,
312 .destination_room = GD_GetRoomByName("Outside The Undeterred"),
300 .type = EntranceType::kPainting}); 313 .type = EntranceType::kPainting});
301 } 314 }
302 315
303 if (AP_IsPilgrimageEnabled()) { 316 if (AP_IsPilgrimageEnabled()) {
304 if (room_obj.name == "Hub Room") { 317 int pilgrimage_start_id = GD_GetRoomByName("Hub Room");
318 if (AP_IsSunwarpShuffle()) {
319 for (const auto& [start_index, mapping] :
320 AP_GetSunwarpMapping()) {
321 if (mapping.dots == 1) {
322 pilgrimage_start_id = GD_GetRoomForSunwarp(start_index);
323 }
324 }
325 }
326
327 if (room_exit.destination_room == pilgrimage_start_id) {
305 new_boundary.push_back( 328 new_boundary.push_back(
306 {.destination_room = GD_GetRoomByName("Pilgrim Antechamber"), 329 {.source_room = room_exit.destination_room,
330 .destination_room = GD_GetRoomByName("Pilgrim Antechamber"),
307 .type = EntranceType::kPilgrimage}); 331 .type = EntranceType::kPilgrimage});
308 } 332 }
309 } else { 333 } else {
310 if (room_obj.name == "Starting Room") { 334 if (room_obj.name == "Starting Room") {
311 new_boundary.push_back( 335 new_boundary.push_back(
312 {.destination_room = GD_GetRoomByName("Pilgrim Antechamber"), 336 {.source_room = room_exit.destination_room,
337 .destination_room = GD_GetRoomByName("Pilgrim Antechamber"),
313 .door = 338 .door =
314 GD_GetDoorByName("Pilgrim Antechamber - Sun Painting"), 339 GD_GetDoorByName("Pilgrim Antechamber - Sun Painting"),
315 .type = EntranceType::kPainting}); 340 .type = EntranceType::kPainting});
@@ -350,6 +375,19 @@ class StateCalculator {
350 return door_report_; 375 return door_report_;
351 } 376 }
352 377
378 std::string GetPathToRoom(int room_id) const {
379 if (!paths_.count(room_id)) {
380 return "";
381 }
382
383 const std::list<int>& path = paths_.at(room_id);
384 std::vector<std::string> room_names;
385 for (int room_id : path) {
386 room_names.push_back(GD_GetRoom(room_id).name);
387 }
388 return hatkirby::implode(room_names, " -> ");
389 }
390
353 private: 391 private:
354 template <typename T> 392 template <typename T>
355 Decision IsNonGroupedDoorReachable(const T& door_obj) { 393 Decision IsNonGroupedDoorReachable(const T& door_obj) {
@@ -603,6 +641,8 @@ class StateCalculator {
603 std::set<int> solveable_panels_; 641 std::set<int> solveable_panels_;
604 std::set<int> reachable_paintings_; 642 std::set<int> reachable_paintings_;
605 std::map<int, std::map<std::string, bool>> door_report_; 643 std::map<int, std::map<std::string, bool>> door_report_;
644
645 std::map<int, std::list<int>> paths_;
606}; 646};
607 647
608} // namespace 648} // namespace
_size.GetWidth() * image_size.GetHeight()) / image_size.GetWidth(); final_y = (panel_size.GetHeight() - final_height) / 2; } else { final_width = (image_size.GetWidth() * panel_size.GetHeight()) / image_size.GetHeight(); final_x = (panel_size.GetWidth() - final_width) / 2; } rendered_ = wxBitmap( map_image_.Scale(final_width, final_height, wxIMAGE_QUALITY_NORMAL) .Size(panel_size, {final_x, final_y}, 0, 0, 0)); offset_x_ = final_x; offset_y_ = final_y; scale_x_ = static_cast<double>(final_width) / image_size.GetWidth(); scale_y_ = static_cast<double>(final_height) / image_size.GetHeight(); int player_width = PLAYER_SIZE * scale_x_; int player_height = PLAYER_SIZE * scale_y_; scaled_player_ = wxBitmap(player_image_.Scale(player_width > 0 ? player_width : 1, player_height > 0 ? player_height : 1)); wxMemoryDC dc; dc.SelectObject(rendered_); int real_area_size = final_width * AREA_EFFECTIVE_SIZE / image_size.GetWidth(); int actual_border_size = real_area_size * AREA_BORDER_SIZE / AREA_EFFECTIVE_SIZE; const wxPoint upper_left_triangle[] = { {0, 0}, {0, real_area_size}, {real_area_size, 0}}; const wxPoint lower_right_triangle[] = {{0, real_area_size - 1}, {real_area_size - 1, 0}, {real_area_size, real_area_size}}; for (AreaIndicator &area : areas_) { const MapArea &map_area = GD_GetMapArea(area.area_id); if (!AP_IsLocationVisible(map_area.classification) && !(map_area.hunt && GetTrackerConfig().show_hunt_panels) && !(AP_IsPaintingShuffle() && !map_area.paintings.empty())) { area.active = false; continue; } else { area.active = true; } bool has_reachable_unchecked = false; bool has_unreachable_unchecked = false; for (const Location &section : map_area.locations) { bool has_unchecked = false; if (IsLocationWinCondition(section)) { has_unchecked = !AP_HasReachedGoal(); } else if (AP_IsLocationVisible(section.classification)) { has_unchecked = !AP_HasCheckedGameLocation(section.ap_location_id); } else if (section.hunt && GetTrackerConfig().show_hunt_panels) { has_unchecked = !AP_HasCheckedHuntPanel(section.ap_location_id); } if (has_unchecked) { if (IsLocationReachable(section.ap_location_id)) { has_reachable_unchecked = true; } else { has_unreachable_unchecked = true; } } } if (AP_IsPaintingShuffle()) { for (int painting_id : map_area.paintings) { const PaintingExit &painting = GD_GetPaintingExit(painting_id); if (!AP_IsPaintingChecked(painting.internal_id)) { bool reachable = IsPaintingReachable(painting_id); 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)) * final_width / image_size.GetWidth(); if (has_reachable_unchecked && has_unreachable_unchecked && GetTrackerConfig().hybrid_areas) { dc.SetPen(*wxTRANSPARENT_PEN); dc.SetBrush(*wxGREEN_BRUSH); dc.DrawPolygon(3, upper_left_triangle, real_area_x, real_area_y); dc.SetBrush(*wxRED_BRUSH); dc.DrawPolygon(3, lower_right_triangle, real_area_x, real_area_y); dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size)); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRectangle({real_area_x, real_area_y}, {real_area_size, real_area_size}); } else { const wxBrush *brush_color = wxGREY_BRUSH; if (has_reachable_unchecked && has_unreachable_unchecked) { brush_color = wxYELLOW_BRUSH; } else if (has_reachable_unchecked) { brush_color = wxGREEN_BRUSH; } else if (has_unreachable_unchecked) { brush_color = wxRED_BRUSH; } dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size)); dc.SetBrush(*brush_color); dc.DrawRectangle({real_area_x, real_area_y}, {real_area_size, real_area_size}); } area.real_x1 = real_area_x; area.real_x2 = real_area_x + real_area_size; area.real_y1 = real_area_y; area.real_y2 = real_area_y + real_area_size; int popup_x = 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->SetClientSize( area.popup->GetVirtualSize().GetWidth(), std::min(panel_size.GetHeight(), area.popup->GetVirtualSize().GetHeight())); if (popup_x + area.popup->GetSize().GetWidth() > panel_size.GetWidth()) { popup_x = panel_size.GetWidth() - area.popup->GetSize().GetWidth(); } if (popup_y + area.popup->GetSize().GetHeight() > panel_size.GetHeight()) { popup_y = panel_size.GetHeight() - area.popup->GetSize().GetHeight(); } area.popup->SetPosition({popup_x, popup_y}); } }