#ifndef GAME_DATA_H_9C42AC51 #define GAME_DATA_H_9C42AC51 #include #include #include #include enum class LingoColor { kNone, kBlack, kRed, kBlue, kYellow, kGreen, kOrange, kPurple, kBrown, kGray }; struct Panel { int id; int room; std::string name; std::vector colors; std::vector required_rooms; std::vector required_doors; std::vector required_panels; bool check = false; bool exclude_reduce = false; bool achievement = false; std::string achievement_name; bool non_counting = false; }; struct ProgressiveRequirement { std::string item_name; int quantity = 0; }; struct Door { int room; std::string name; std::string location_name; std::string item_name; std::string group_name; bool skip_location = false; bool skip_item = false; std::vector panels; bool exclude_reduce = true; std::vector progressives; }; struct Exit { int destination_room; std::optional door; bool painting = false; }; struct PaintingExit { std::string id; std::optional door; }; struct Room { std::string name; std::vector exits; std::vector paintings; std::vector panels; }; struct Location { std::string name; std::string ap_location_name; int room; std::vector panels; bool exclude_reduce = false; }; struct MapArea { int id; std::string name; std::vector locations; int map_x; int map_y; bool exclude_reduce = false; }; const std::vector& GD_GetMapAreas(); const MapArea& GD_GetMapArea(int id); int GD_GetRoomByName(const std::string& name); const Room& GD_GetRoom(int room_id); const std::vector& GD_GetDoors(); const Door& GD_GetDoor(int door_id); const Panel& GD_GetPanel(int panel_id); int GD_GetRoomForPainting(const std::string& painting_id); const std::vector& GD_GetAchievementPanels(); #endif /* end of include guard: GAME_DATA_H_9C42AC51 */ stats
blob: 5580068d4bd2c54f36c24163855fed815391fee6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "tracker_panel.h"

#include "ap_state.h"
#include "area_popup.h"
#include "game_data.h"
#include "tracker_state.h"

constexpr int AREA_ACTUAL_SIZE = 64;
constexpr int AREA_BORDER_SIZE = 5;
constexpr int AREA_EFFECTIVE_SIZE = AREA_ACTUAL_SIZE + AREA_BORDER_SIZE * 2;

TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
  map_image_ = wxImage("assets/lingo_map.png", wxBITMAP_TYPE_PNG);
  if (!map_image_.IsOk()) {
    return;
  }

  for (const MapArea &map_area : GD_GetMapAreas()) {
    AreaIndicator area;
    area.area_id = map_area.id;

    area.popup = new AreaPopup(this, map_area.id);
    area.popup->SetPosition({0, 0});

    areas_.push_back(area);
  }

  Redraw();

  Bind(wxEVT_PAINT, &TrackerPanel::OnPaint, this);
  Bind(wxEVT_MOTION, &TrackerPanel::OnMouseMove, this);
}

void TrackerPanel::UpdateIndicators() {
  Redraw();

  for (AreaIndicator &area : areas_) {
    area.popup->UpdateIndicators();
  }
}

void TrackerPanel::OnPaint(wxPaintEvent &event) {
  if (GetSize() != rendered_.GetSize()) {
    Redraw();
  }

  wxPaintDC dc(this);
  dc.DrawBitmap(rendered_, 0, 0);

  event.Skip();
}

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) {
      area.popup->Show();
    } else {
      area.popup->Hide();
    }
  }

  event.Skip();
}

void TrackerPanel::Redraw() {
  wxSize panel_size = GetSize();
  wxSize image_size = map_image_.GetSize();

  int final_x = 0;
  int final_y = 0;
  int final_width = panel_size.GetWidth();
  int final_height = panel_size.GetHeight();

  if (image_size.GetWidth() * panel_size.GetHeight() >
      panel_size.GetWidth() * image_size.GetHeight()) {
    final_height = (panel_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));

  wxMemoryDC dc;
  dc.SelectObject(rendered_);

  for (AreaIndicator &area : areas_) {
    const wxBrush *brush_color = wxGREY_BRUSH;

    const MapArea &map_area = GD_GetMapArea(area.area_id);
    if (!AP_IsLocationVisible(map_area.classification)) {
      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) {
      if (AP_IsLocationVisible(section.classification) &&
          !AP_HasCheckedGameLocation(section.ap_location_id)) {
        if (IsLocationReachable(section.ap_location_id)) {
          has_reachable_unchecked = true;
        } else {
          has_unreachable_unchecked = true;
        }
      }
    }

    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;
    }

    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;
    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();

    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->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();
    }
    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});
  }
}