about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--assets/owl.pngbin0 -> 439 bytes
-rw-r--r--assets/subway.pngbin0 -> 184533 bytes
-rw-r--r--assets/subway.yaml614
-rw-r--r--src/game_data.cpp62
-rw-r--r--src/game_data.h25
-rw-r--r--src/subway_map.cpp89
-rw-r--r--src/subway_map.h35
-rw-r--r--src/tracker_frame.cpp13
-rw-r--r--src/tracker_frame.h2
-rw-r--r--src/tracker_state.cpp20
-rw-r--r--src/tracker_state.h2
12 files changed, 859 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a6f6342..99b15f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -43,6 +43,7 @@ add_executable(lingo_ap_tracker
43 "src/achievements_pane.cpp" 43 "src/achievements_pane.cpp"
44 "src/settings_dialog.cpp" 44 "src/settings_dialog.cpp"
45 "src/global.cpp" 45 "src/global.cpp"
46 "src/subway_map.cpp"
46 "vendor/whereami/whereami.c" 47 "vendor/whereami/whereami.c"
47) 48)
48set_property(TARGET lingo_ap_tracker PROPERTY CXX_STANDARD 20) 49set_property(TARGET lingo_ap_tracker PROPERTY CXX_STANDARD 20)
diff --git a/assets/owl.png b/assets/owl.png new file mode 100644 index 0000000..0210303 --- /dev/null +++ b/assets/owl.png
Binary files differ
diff --git a/assets/subway.png b/assets/subway.png new file mode 100644 index 0000000..3860d2c --- /dev/null +++ b/assets/subway.png
Binary files differ
diff --git a/assets/subway.yaml b/assets/subway.yaml new file mode 100644 index 0000000..b0d9c84 --- /dev/null +++ b/assets/subway.yaml
@@ -0,0 +1,614 @@
1---
2- pos: [1050, 954]
3 room: Starting Room
4 door: Back Right Door
5- pos: [986, 1034]
6 room: Starting Room
7 door: Rhyme Room Entrance
8- pos: [990, 956]
9 special: starting_room_paintings # Early Color Hallways painting is a hardcoded special case
10 paintings:
11 - arrows_painting
12- pos: [905, 841]
13 room: Hedge Maze
14 door: Painting Shortcut
15 paintings:
16 - garden_painting_tower2
17 tags:
18 - garden_starting
19- pos: [1066, 841]
20 room: Courtyard
21 door: Painting Shortcut
22 paintings:
23 - flower_painting_8
24 tags:
25 - flower_starting
26- pos: [905, 895]
27 room: The Wondrous (Doorknob)
28 door: Painting Shortcut
29 paintings:
30 - symmetry_painting_a_starter
31 tags:
32 - symmetry_starting
33- pos: [1066, 868]
34 room: Outside The Bold
35 door: Painting Shortcut
36 paintings:
37 - pencil_painting6
38 tags:
39 - pencil_starting
40- pos: [1066, 895]
41 room: Outside The Undeterred
42 door: Painting Shortcut
43 paintings:
44 - blueman_painting_3
45 tags:
46 - blueman_starting
47- pos: [905, 868]
48 room: Outside The Agreeable
49 door: Painting Shortcut
50 paintings:
51 - eyes_yellow_painting2
52 tags:
53 - street_starting
54- pos: [1211, 879]
55 room: Hidden Room
56 door: Dead End Door
57- pos: [1291, 906]
58 room: Hidden Room
59 door: Knight Night Entrance
60- pos: [1103, 980]
61 room: Hidden Room
62 door: Seeker Entrance
63- pos: [1173, 980]
64 room: Hidden Room
65 door: Rhyme Room Entrance
66- pos: [1116, 939]
67 paintings:
68 - owl_painting
69 tags:
70 - owl_hidden
71- pos: [986, 793]
72 room: Second Room
73 door: Exit Door
74- pos: [798, 584]
75 room: Hub Room
76 door: Crossroads Entrance
77- pos: [932, 665]
78 room: Hub Room
79 door: Tenacious Entrance
80- pos: [1361, 578]
81 room: Hub Room
82 door: Shortcut to Hedge Maze
83- pos: [1312, 841]
84 room: Hub Room
85 door: Near RAT Door
86- pos: [1371, 729]
87 room: Hub Room
88 door: Traveled Entrance
89- pos: [1313, 686]
90 paintings:
91 - maze_painting
92 tags:
93 - green_owl
94 - green_numbers
95- pos: [1172, 760]
96 sunwarp:
97 dots: 1
98 type: enter
99- pos: [1302, 638]
100 room: Outside The Undeterred
101 door: Fours
102- pos: [1243, 819]
103 room: Outside The Undeterred
104 door: Fours
105- pos: [1276, 819]
106 room: Outside The Undeterred
107 door: Eights
108- pos: [1263, 867]
109 paintings:
110 - smile_painting_6
111 tags:
112 - smiley_deadend
113- pos: [1012, 1086]
114 sunwarp:
115 dots: 6
116 type: final
117- pos: [938, 1002]
118 room: Pilgrim Antechamber
119 door: Sun Painting
120 special: sun_painting
121- pos: [1053, 1090]
122 invisible: true
123 special: sun_painting_exit
124- pos: [1077, 1061]
125 room: Pilgrim Room
126 door: Shortcut to The Seeker
127- pos: [713, 359]
128 room: Number Hunt
129 door: Eights
130- pos: [932, 348]
131 room: Crossroads
132 door: Hollow Hallway
133- pos: [798, 290]
134 room: Crossroads
135 door: Tower Entrance
136- pos: [932, 477]
137 room: Crossroads
138 door: Tenacious Entrance
139- pos: [638, 477]
140 room: Crossroads
141 door: Discerning Entrance
142- pos: [905, 290]
143 room: Crossroads
144 door: Tower Back Entrance
145- pos: [894, 423]
146 room: Crossroads
147 door: Words Sword Door
148- pos: [632, 643]
149 room: Crossroads
150 door: Eye Wall
151- pos: [638, 520]
152 room: Crossroads
153 door: Roof Access
154- pos: [756, 400]
155 paintings:
156 - smile_painting_4
157 tags:
158 - smiley_crossroads
159- pos: [878, 509]
160 sunwarp:
161 dots: 1
162 type: exit
163- pos: [1056, 344]
164 room: Lost Area
165 door: Exit
166- pos: [954, 290]
167 room: Lost Area
168 door: Exit
169- pos: [986, 290]
170 room: Number Hunt
171 door: Eights
172- pos: [954, 247]
173 room: Amen Name Area
174 door: Exit
175- pos: [954, 222]
176 paintings:
177 - west_afar
178- pos: [986, 697]
179 room: The Tenacious
180 door: Shortcut to Hub Room
181- pos: [1173, 665]
182 room: Near Far Area
183 door: Door
184- pos: [1173, 622]
185 room: Warts Straw Area
186 door: Door
187- pos: [1173, 579]
188 room: Leaf Feel Area
189 door: Door
190- pos: [1173, 333]
191 room: Outside The Agreeable
192 door: Purple Barrier
193- pos: [1088, 289]
194 room: Outside The Undeterred
195 door: Fives
196- pos: [1088, 418]
197 room: Outside The Undeterred
198 door: Fives
199- pos: [1039, 477]
200 room: Outside The Agreeable
201 door: Tenacious Entrance
202- pos: [1147, 525]
203 room: Outside The Agreeable
204 door: Black Door
205- pos: [1216, 525]
206 room: Outside The Agreeable
207 door: Agreeable Entrance
208- pos: [1138, 287]
209 paintings:
210 - eyes_yellow_painting
211 tags:
212 - street_starting
213- pos: [1088, 385]
214 sunwarp:
215 dots: 6
216 type: enter
217- pos: [1195, 450]
218 room: Compass Room
219 door: Lookout Entrance
220- pos: [1214, 457]
221 paintings:
222 - pencil_painting7
223 tags:
224 - pencil_compass
225- pos: [1196, 417]
226 invisible: true
227 tags:
228 - agreeable_to_lookout
229- pos: [1657, 1392]
230 room: Room Room
231 door: Excavation
232- pos: [1725, 1441]
233 invisible: true
234 tags:
235 - agreeable_to_lookout
236- pos: [1040, 665]
237 room: Dread Hallway
238 door: Tenacious Entrance
239- pos: [1324, 525]
240 room: The Agreeable
241 door: Shortcut to Hedge Maze
242- pos: [1484, 392]
243 room: Hedge Maze
244 door: Perceptive Entrance
245- pos: [1441, 241]
246 room: Hedge Maze
247 door: Observant Entrance
248- pos: [1714, 434]
249 room: Hedge Maze
250 door: Observant Entrance
251- pos: [1477, 343]
252 paintings:
253 - garden_painting_tower
254 tags:
255 - garden_starting
256- pos: [1565, 311]
257 room: The Fearless (First Floor)
258 door: Second Floor
259- pos: [1597, 279]
260 room: The Fearless (Second Floor)
261 door: Third Floor
262- pos: [1414, 209]
263 room: The Observant
264 door: Backside Door
265- pos: [1624, 188]
266 room: The Observant
267 door: Stairs
268- pos: [1667, 686]
269 room: The Incomparable
270 door: Eight Door
271- pos: [1784, 569]
272 paintings:
273 - crown_painting
274 tags:
275 - crown_tower6
276- pos: [1653, 717]
277 paintings:
278 - eight_painting2
279 tags:
280 - eight_alcove
281- pos: [1653, 662]
282 paintings:
283 - eight_painting
284 tags:
285 - eight_alcove
286- pos: [697, 1471]
287 room: Orange Tower
288 door: Second Floor
289- pos: [633, 1406]
290 room: Orange Tower
291 door: Third Floor
292- pos: [570, 1343]
293 room: Orange Tower
294 door: Fourth Floor
295- pos: [504, 1279]
296 room: Orange Tower
297 door: Fifth Floor
298- pos: [440, 1215]
299 room: Orange Tower
300 door: Sixth Floor
301- pos: [379, 1153]
302 room: Orange Tower
303 door: Seventh Floor
304- pos: [905, 793]
305 room: Orange Tower First Floor
306 door: Shortcut to Hub Room
307- pos: [686, 820]
308 room: Orange Tower First Floor
309 door: Salt Pepper Door
310- pos: [755, 787]
311 sunwarp:
312 dots: 4
313 type: enter
314- pos: [719, 846]
315 tags:
316 - tower1_tower1
317- pos: [681, 1506]
318 tags:
319 - tower1_tower1
320- pos: [722, 1439]
321 tags:
322 - tower2_undeterred
323- pos: [533, 1375]
324 tags:
325 - tower3_tower3
326- pos: [662, 1375]
327 tags:
328 - tower3_gallery
329- pos: [483, 1307]
330 tags:
331 - tower4_room
332- pos: [598, 1307]
333 tags:
334 - tower4_tower4
335- pos: [598, 1287]
336 tags:
337 - tower4_courtyard
338- pos: [533, 1245]
339 tags:
340 - tower5_welcome
341- pos: [419, 1245]
342 tags:
343 - tower5_cellar
344- pos: [419, 1267]
345 tags:
346 - tower5_quadruple
347- pos: [203, 1014]
348 tags:
349 - tower2_undeterred
350- pos: [1325, 1191]
351 tags:
352 - tower3_tower3
353- pos: [1700, 1021]
354 tags:
355 - tower3_gallery
356- pos: [1653, 1318]
357 tags:
358 - tower4_room
359- pos: [918, 222]
360 tags:
361 - tower4_tower4
362- pos: [806, 222]
363 tags:
364 - tower4_courtyard
365- pos: [652, 951]
366 tags:
367 - tower5_welcome
368- pos: [1553, 1440]
369 tags:
370 - tower5_cellar
371- pos: [1459, 1119]
372 tags:
373 - tower5_quadruple
374- pos: [1216, 1280]
375 room: Orange Tower Third Floor
376 door: Red Barrier
377- pos: [1173, 1248]
378 room: Orange Tower Third Floor
379 door: Rhyme Room Entrance
380- pos: [1270, 1231]
381 paintings:
382 - arrows_painting_6
383 - flower_painting_5
384- pos: [1216, 1216]
385 sunwarp:
386 dots: 2
387 type: exit
388- pos: [1253, 1172]
389 sunwarp:
390 dots: 3
391 type: enter
392- pos: [852, 198]
393 room: Orange Tower Fourth Floor
394 door: Hot Crusts Door
395- pos: [830, 289]
396 sunwarp:
397 dots: 5
398 type: enter
399- pos: [877, 155]
400 room: Number Hunt
401 door: Eights
402- pos: [844, 134]
403 paintings:
404 - smile_painting_8
405 tags:
406 - smiley_hotcrusts
407- pos: [797, 155]
408 sunwarp:
409 dots: 2
410 type: enter
411- pos: [679, 985]
412 room: Number Hunt
413 door: Nines
414- pos: [723, 953]
415 room: Orange Tower Fifth Floor
416 door: Welcome Back
417- pos: [683, 944]
418 paintings:
419 - east_afar
420- pos: [548, 1221]
421 paintings:
422 - hi_solved_painting3
423- pos: [1574, 1425]
424 paintings:
425 - hi_solved_painting2
426- pos: [411, 1186]
427 paintings:
428 - arrows_painting_10
429 - owl_painting_3
430 - clock_painting
431 - scenery_painting_5d_2
432 - symmetry_painting_b_7
433 - panda_painting_2
434 - crown_painting2
435 - colors_painting2
436 - cherry_painting2
437 - hi_solved_painting
438 tags:
439 - owl_tower6
440 - wise_tower6
441 - panda_tower6
442 - crown_tower6
443 - apple_tower6
444 - hi_scientific
445- pos: [349, 1124]
446 paintings:
447 - map_painting2
448- pos: [436, 1159]
449 room: Orange Tower Seventh Floor
450 door: Mastery
451- pos: [544, 1159]
452 paintings:
453 - arrows_painting_11
454- pos: [498, 284]
455 room: Courtyard
456 door: Green Barrier
457- pos: [556, 233]
458 paintings:
459 - flower_painting_7
460 tags:
461 - flower_starting
462 - flower_arrow
463- pos: [600, 332]
464 room: Number Hunt
465 door: Nines
466- pos: [579, 350]
467 paintings:
468 - blueman_painting
469 tags:
470 - blueman_courtyard
471- pos: [530, 310]
472 room: First Second Third Fourth
473 door: Backside Door
474- pos: [584, 107]
475 room: The Colorful (White)
476 door: Progress Door
477- pos: [622, 107]
478 room: The Colorful (Black)
479 door: Progress Door
480- pos: [659, 107]
481 room: The Colorful (Red)
482 door: Progress Door
483- pos: [697, 107]
484 room: The Colorful (Yellow)
485 door: Progress Door
486- pos: [734, 107]
487 room: The Colorful (Blue)
488 door: Progress Door
489- pos: [772, 107]
490 room: The Colorful (Purple)
491 door: Progress Door
492- pos: [809, 107]
493 room: The Colorful (Orange)
494 door: Progress Door
495- pos: [847, 107]
496 room: The Colorful (Green)
497 door: Progress Door
498- pos: [884, 107]
499 room: The Colorful (Brown)
500 door: Progress Door
501- pos: [922, 107]
502 room: The Colorful (Gray)
503 door: Progress Door
504- pos: [967, 107]
505 paintings:
506 - arrows_painting_12
507- pos: [878, 954]
508 room: Welcome Back Area
509 door: Shortcut to Starting Room
510- pos: [773, 954]
511 tags:
512 - hub_wb
513 - wondrous_wb
514 - undeterred_wb
515 - agreeable_wb
516 - wanderer_wb
517 - observant_wb
518 - gallery_wb
519 - scientific_wb
520 - cellar_wb
521- pos: [1107, 749]
522 tags:
523 - hub_wb
524- pos: [408, 817]
525 tags:
526 - wondrous_wb
527- pos: [281, 1017]
528 tags:
529 - undeterred_wb
530- pos: [1017, 289]
531 tags:
532 - agreeable_wb
533- pos: [907, 1385]
534 tags:
535 - wanderer_wb
536- pos: [1737, 1053]
537 tags:
538 - gallery_wb
539- pos: [1690, 268]
540 tags:
541 - observant_wb
542- pos: [250, 604]
543 tags:
544 - scientific_wb
545- pos: [1553, 1467]
546 tags:
547 - cellar_wb
548- pos: [1478, 498]
549 room: Owl Hallway
550 door: Shortcut to Hedge Maze
551- pos: [1480, 551]
552 paintings:
553 - arrows_painting_8
554 - maze_painting_2
555 - owl_painting_2
556 - clock_painting_4
557 tags:
558 - green_owl
559 - owl_hidden
560 - owl_tower6
561- pos: [1478, 938]
562 room: Number Hunt
563 door: Sevens
564- pos: [1580, 853]
565 room: Number Hunt
566 door: Sevens
567- pos: [1478, 905]
568 room: Number Hunt
569 door: Eights
570- pos: [1452, 841]
571 room: Number Hunt
572 door: Nines
573- pos: [1420, 841]
574 room: Outside The Initiated
575 door: Blue Barrier
576- pos: [1479, 1018]
577 room: Outside The Initiated
578 door: Orange Barrier
579- pos: [1360, 847]
580 room: Outside The Initiated
581 door: Shortcut to Hub Room
582- pos: [1511, 841]
583 room: Outside The Initiated
584 door: Initiated Entrance
585- pos: [1141, 1441]
586 room: Orange Tower Third Floor
587 door: Orange Barrier
588- pos: [1173, 1441]
589 room: Outside The Initiated
590 door: Green Barrier
591- pos: [1206, 1441]
592 room: Outside The Initiated
593 door: Purple Barrier
594- pos: [1189, 1355]
595 room: Outside The Initiated
596 door: Entrance
597- pos: [1580, 729]
598 room: Outside The Initiated
599 door: Eight Door
600- pos: [1530, 938]
601 paintings:
602 - clock_painting_5
603 tags:
604 - clock_initiated
605- pos: [1546, 938]
606 paintings:
607 - clock_painting_2
608 tags:
609 - clock_tower6
610 - clock_initiated
611- pos: [1579, 813]
612 sunwarp:
613 dots: 3
614 type: exit
diff --git a/src/game_data.cpp b/src/game_data.cpp index c98f532..4348967 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp
@@ -44,6 +44,7 @@ struct GameData {
44 std::vector<Door> doors_; 44 std::vector<Door> doors_;
45 std::vector<Panel> panels_; 45 std::vector<Panel> panels_;
46 std::vector<MapArea> map_areas_; 46 std::vector<MapArea> map_areas_;
47 std::vector<SubwayItem> subway_items_;
47 48
48 std::map<std::string, int> room_by_id_; 49 std::map<std::string, int> room_by_id_;
49 std::map<std::string, int> door_by_id_; 50 std::map<std::string, int> door_by_id_;
@@ -606,6 +607,56 @@ struct GameData {
606 errstr << "Area data not found for: " << area; 607 errstr << "Area data not found for: " << area;
607 TrackerLog(errstr.str()); 608 TrackerLog(errstr.str());
608 } 609 }
610
611 // Read in subway items.
612 YAML::Node subway_config =
613 YAML::LoadFile(GetAbsolutePath("assets/subway.yaml"));
614 for (const auto &subway_it : subway_config) {
615 SubwayItem subway_item;
616 subway_item.id = subway_items_.size();
617 subway_item.x = subway_it["pos"][0].as<int>();
618 subway_item.y = subway_it["pos"][1].as<int>();
619
620 if (subway_it["door"]) {
621 subway_item.door = AddOrGetDoor(subway_it["room"].as<std::string>(),
622 subway_it["door"].as<std::string>());
623 }
624
625 if (subway_it["paintings"]) {
626 for (const auto &painting_it : subway_it["paintings"]) {
627 subway_item.paintings.push_back(painting_it.as<std::string>());
628 }
629 }
630
631 if (subway_it["tags"]) {
632 for (const auto &tag_it : subway_it["tags"]) {
633 subway_item.tags.push_back(tag_it.as<std::string>());
634 }
635 }
636
637 if (subway_it["sunwarp"]) {
638 SubwaySunwarp sunwarp;
639 sunwarp.dots = subway_it["sunwarp"]["dots"].as<int>();
640
641 std::string sunwarp_type =
642 subway_it["sunwarp"]["type"].as<std::string>();
643 if (sunwarp_type == "final") {
644 sunwarp.type = SubwaySunwarpType::kFinal;
645 } else if (sunwarp_type == "exit") {
646 sunwarp.type = SubwaySunwarpType::kExit;
647 } else {
648 sunwarp.type = SubwaySunwarpType::kEnter;
649 }
650
651 subway_item.sunwarp = sunwarp;
652 }
653
654 if (subway_it["special"]) {
655 subway_item.special = subway_it["special"].as<std::string>();
656 }
657
658 subway_items_.push_back(subway_item);
659 }
609 } 660 }
610 661
611 int AddOrGetRoom(std::string room) { 662 int AddOrGetRoom(std::string room) {
@@ -621,8 +672,9 @@ struct GameData {
621 std::string full_name = room + " - " + door; 672 std::string full_name = room + " - " + door;
622 673
623 if (!door_by_id_.count(full_name)) { 674 if (!door_by_id_.count(full_name)) {
675 int door_id = doors_.size();
624 door_by_id_[full_name] = doors_.size(); 676 door_by_id_[full_name] = doors_.size();
625 doors_.push_back({.room = AddOrGetRoom(room), .name = door}); 677 doors_.push_back({.id = door_id, .room = AddOrGetRoom(room), .name = door});
626 } 678 }
627 679
628 return door_by_id_[full_name]; 680 return door_by_id_[full_name];
@@ -704,3 +756,11 @@ const std::vector<int> &GD_GetSunwarpDoors() {
704int GD_GetRoomForSunwarp(int index) { 756int GD_GetRoomForSunwarp(int index) {
705 return GetState().room_by_sunwarp_.at(index); 757 return GetState().room_by_sunwarp_.at(index);
706} 758}
759
760const std::vector<SubwayItem> &GD_GetSubwayItems() {
761 return GetState().subway_items_;
762}
763
764const SubwayItem &GD_GetSubwayItem(int id) {
765 return GetState().subway_items_.at(id);
766}
diff --git a/src/game_data.h b/src/game_data.h index cd09627..37d1eb3 100644 --- a/src/game_data.h +++ b/src/game_data.h
@@ -62,6 +62,7 @@ struct ProgressiveRequirement {
62}; 62};
63 63
64struct Door { 64struct Door {
65 int id;
65 int room; 66 int room;
66 std::string name; 67 std::string name;
67 std::string location_name; 68 std::string location_name;
@@ -118,6 +119,28 @@ struct MapArea {
118 bool hunt = false; 119 bool hunt = false;
119}; 120};
120 121
122enum class SubwaySunwarpType {
123 kEnter,
124 kExit,
125 kFinal
126};
127
128struct SubwaySunwarp {
129 int dots;
130 SubwaySunwarpType type;
131};
132
133struct SubwayItem {
134 int id;
135 int x;
136 int y;
137 std::optional<int> door;
138 std::vector<std::string> paintings;
139 std::vector<std::string> tags;
140 std::optional<SubwaySunwarp> sunwarp;
141 std::optional<std::string> special;
142};
143
121const std::vector<MapArea>& GD_GetMapAreas(); 144const std::vector<MapArea>& GD_GetMapAreas();
122const MapArea& GD_GetMapArea(int id); 145const MapArea& GD_GetMapArea(int id);
123int GD_GetRoomByName(const std::string& name); 146int GD_GetRoomByName(const std::string& name);
@@ -131,5 +154,7 @@ const std::vector<int>& GD_GetAchievementPanels();
131int GD_GetItemIdForColor(LingoColor color); 154int GD_GetItemIdForColor(LingoColor color);
132const std::vector<int>& GD_GetSunwarpDoors(); 155const std::vector<int>& GD_GetSunwarpDoors();
133int GD_GetRoomForSunwarp(int index); 156int GD_GetRoomForSunwarp(int index);
157const std::vector<SubwayItem>& GD_GetSubwayItems();
158const SubwayItem& GD_GetSubwayItem(int id);
134 159
135#endif /* end of include guard: GAME_DATA_H_9C42AC51 */ 160#endif /* end of include guard: GAME_DATA_H_9C42AC51 */
diff --git a/src/subway_map.cpp b/src/subway_map.cpp new file mode 100644 index 0000000..c58b2d1 --- /dev/null +++ b/src/subway_map.cpp
@@ -0,0 +1,89 @@
1#include "subway_map.h"
2
3#include "game_data.h"
4#include "global.h"
5#include "tracker_state.h"
6
7constexpr int AREA_ACTUAL_SIZE = 21;
8
9SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
10 map_image_ =
11 wxImage(GetAbsolutePath("assets/subway.png").c_str(), wxBITMAP_TYPE_PNG);
12 if (!map_image_.IsOk()) {
13 return;
14 }
15
16 Redraw();
17 Resize();
18
19 Bind(wxEVT_PAINT, &SubwayMap::OnPaint, this);
20 Bind(wxEVT_MOTION, &SubwayMap::OnMouseMove, this);
21}
22
23void SubwayMap::UpdateIndicators() {
24 Redraw();
25 Resize();
26}
27
28void SubwayMap::OnPaint(wxPaintEvent &event) {
29 if (GetSize() != resized_.GetSize()) {
30 Resize();
31 }
32
33 wxPaintDC dc(this);
34 dc.DrawBitmap(resized_, 0, 0);
35
36 event.Skip();
37}
38
39void SubwayMap::OnMouseMove(wxMouseEvent &event) {
40 event.Skip();
41}
42
43void SubwayMap::Redraw() {
44 rendered_ = wxBitmap(map_image_);
45
46 wxMemoryDC dc;
47 dc.SelectObject(rendered_);
48
49 for (const SubwayItem &subway_item : GD_GetSubwayItems()) {
50 const wxBrush *brush_color = wxGREY_BRUSH;
51 if (subway_item.door) {
52 if (IsDoorOpen(*subway_item.door)) {
53 brush_color = wxGREEN_BRUSH;
54 } else {
55 brush_color = wxRED_BRUSH;
56 }
57 }
58
59 dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1));
60 dc.SetBrush(*brush_color);
61 dc.DrawRectangle({subway_item.x, subway_item.y},
62 {AREA_ACTUAL_SIZE, AREA_ACTUAL_SIZE});
63 }
64}
65
66void SubwayMap::Resize() {
67 wxSize panel_size = GetSize();
68 wxSize image_size = rendered_.GetSize();
69
70 render_x_ = 0;
71 render_y_ = 0;
72 render_width_ = panel_size.GetWidth();
73 render_height_ = panel_size.GetHeight();
74
75 if (image_size.GetWidth() * panel_size.GetHeight() >
76 panel_size.GetWidth() * image_size.GetHeight()) {
77 render_height_ = (panel_size.GetWidth() * image_size.GetHeight()) /
78 image_size.GetWidth();
79 render_y_ = (panel_size.GetHeight() - render_height_) / 2;
80 } else {
81 render_width_ = (image_size.GetWidth() * panel_size.GetHeight()) /
82 image_size.GetHeight();
83 render_x_ = (panel_size.GetWidth() - render_width_) / 2;
84 }
85
86 resized_ = wxBitmap(rendered_.ConvertToImage()
87 .Scale(render_width_, render_height_, wxIMAGE_QUALITY_BILINEAR)
88 .Size(panel_size, {render_x_, render_y_}, 0, 0, 0));
89}
diff --git a/src/subway_map.h b/src/subway_map.h new file mode 100644 index 0000000..dc67867 --- /dev/null +++ b/src/subway_map.h
@@ -0,0 +1,35 @@
1#ifndef SUBWAY_MAP_H_BD2D843E
2#define SUBWAY_MAP_H_BD2D843E
3
4#include <wx/wxprec.h>
5
6#ifndef WX_PRECOMP
7#include <wx/wx.h>
8#endif
9
10#include <vector>
11
12class SubwayMap : public wxPanel {
13 public:
14 SubwayMap(wxWindow *parent);
15
16 void UpdateIndicators();
17
18 private:
19 void OnPaint(wxPaintEvent &event);
20 void OnMouseMove(wxMouseEvent &event);
21
22 void Redraw();
23 void Resize();
24
25 wxImage map_image_;
26 wxBitmap rendered_;
27 wxBitmap resized_;
28 int render_x_ = 0;
29 int render_y_ = 0;
30 int render_width_ = 0;
31 int render_height_ = 0;
32
33};
34
35#endif /* end of include guard: SUBWAY_MAP_H_BD2D843E */
diff --git a/src/tracker_frame.cpp b/src/tracker_frame.cpp index 8a0c764..70fee2d 100644 --- a/src/tracker_frame.cpp +++ b/src/tracker_frame.cpp
@@ -11,6 +11,7 @@
11#include "ap_state.h" 11#include "ap_state.h"
12#include "connection_dialog.h" 12#include "connection_dialog.h"
13#include "settings_dialog.h" 13#include "settings_dialog.h"
14#include "subway_map.h"
14#include "tracker_config.h" 15#include "tracker_config.h"
15#include "tracker_panel.h" 16#include "tracker_panel.h"
16#include "version.h" 17#include "version.h"
@@ -58,15 +59,20 @@ TrackerFrame::TrackerFrame()
58 Bind(STATE_CHANGED, &TrackerFrame::OnStateChanged, this); 59 Bind(STATE_CHANGED, &TrackerFrame::OnStateChanged, this);
59 Bind(STATUS_CHANGED, &TrackerFrame::OnStatusChanged, this); 60 Bind(STATUS_CHANGED, &TrackerFrame::OnStatusChanged, this);
60 61
61 wxChoicebook *choicebook = new wxChoicebook(this, wxID_ANY);
62 achievements_pane_ = new AchievementsPane(this); 62 achievements_pane_ = new AchievementsPane(this);
63
64 wxChoicebook *choicebook = new wxChoicebook(this, wxID_ANY);
63 choicebook->AddPage(achievements_pane_, "Achievements"); 65 choicebook->AddPage(achievements_pane_, "Achievements");
64 66
65 tracker_panel_ = new TrackerPanel(this); 67 wxNotebook *rightpane = new wxNotebook(this, wxID_ANY);
68 tracker_panel_ = new TrackerPanel(rightpane);
69 subway_map_ = new SubwayMap(rightpane);
70 rightpane->AddPage(tracker_panel_, "Map");
71 rightpane->AddPage(subway_map_, "Subway");
66 72
67 wxBoxSizer *top_sizer = new wxBoxSizer(wxHORIZONTAL); 73 wxBoxSizer *top_sizer = new wxBoxSizer(wxHORIZONTAL);
68 top_sizer->Add(choicebook, wxSizerFlags().Expand().Proportion(1)); 74 top_sizer->Add(choicebook, wxSizerFlags().Expand().Proportion(1));
69 top_sizer->Add(tracker_panel_, wxSizerFlags().Expand().Proportion(3)); 75 top_sizer->Add(rightpane, wxSizerFlags().Expand().Proportion(3));
70 76
71 SetSizerAndFit(top_sizer); 77 SetSizerAndFit(top_sizer);
72 SetSize(1280, 728); 78 SetSize(1280, 728);
@@ -165,6 +171,7 @@ void TrackerFrame::OnCheckForUpdates(wxCommandEvent &event) {
165void TrackerFrame::OnStateChanged(wxCommandEvent &event) { 171void TrackerFrame::OnStateChanged(wxCommandEvent &event) {
166 tracker_panel_->UpdateIndicators(); 172 tracker_panel_->UpdateIndicators();
167 achievements_pane_->UpdateIndicators(); 173 achievements_pane_->UpdateIndicators();
174 subway_map_->UpdateIndicators();
168 Refresh(); 175 Refresh();
169} 176}
170 177
diff --git a/src/tracker_frame.h b/src/tracker_frame.h index e5bf97e..c7c6772 100644 --- a/src/tracker_frame.h +++ b/src/tracker_frame.h
@@ -8,6 +8,7 @@
8#endif 8#endif
9 9
10class AchievementsPane; 10class AchievementsPane;
11class SubwayMap;
11class TrackerPanel; 12class TrackerPanel;
12 13
13wxDECLARE_EVENT(STATE_CHANGED, wxCommandEvent); 14wxDECLARE_EVENT(STATE_CHANGED, wxCommandEvent);
@@ -35,6 +36,7 @@ class TrackerFrame : public wxFrame {
35 36
36 TrackerPanel *tracker_panel_; 37 TrackerPanel *tracker_panel_;
37 AchievementsPane *achievements_pane_; 38 AchievementsPane *achievements_pane_;
39 SubwayMap *subway_map_;
38}; 40};
39 41
40#endif /* end of include guard: TRACKER_FRAME_H_86BD8DFB */ 42#endif /* end of include guard: TRACKER_FRAME_H_86BD8DFB */
diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index 640a159..5588c7f 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp
@@ -14,6 +14,7 @@ namespace {
14 14
15struct TrackerState { 15struct TrackerState {
16 std::map<int, bool> reachability; 16 std::map<int, bool> reachability;
17 std::set<int> reachable_doors;
17 std::mutex reachability_mutex; 18 std::mutex reachability_mutex;
18}; 19};
19 20
@@ -156,6 +157,11 @@ class StateCalculator {
156 flood_boundary = new_boundary; 157 flood_boundary = new_boundary;
157 panel_boundary = new_panel_boundary; 158 panel_boundary = new_panel_boundary;
158 } 159 }
160
161 // Now that we know the full reachable area, let's make sure all doors are evaluated.
162 for (const Door& door : GD_GetDoors()) {
163 int discard = IsDoorReachable(door.id);
164 }
159 } 165 }
160 166
161 const std::set<int>& GetReachableRooms() const { return reachable_rooms_; } 167 const std::set<int>& GetReachableRooms() const { return reachable_rooms_; }
@@ -422,9 +428,17 @@ void RecalculateReachability() {
422 } 428 }
423 } 429 }
424 430
431 std::set<int> new_reachable_doors;
432 for (const auto& [door_id, decision] : state_calculator.GetDoorDecisions()) {
433 if (decision == kYes) {
434 new_reachable_doors.insert(door_id);
435 }
436 }
437
425 { 438 {
426 std::lock_guard reachability_guard(GetState().reachability_mutex); 439 std::lock_guard reachability_guard(GetState().reachability_mutex);
427 std::swap(GetState().reachability, new_reachability); 440 std::swap(GetState().reachability, new_reachability);
441 std::swap(GetState().reachable_doors, new_reachable_doors);
428 } 442 }
429} 443}
430 444
@@ -437,3 +451,9 @@ bool IsLocationReachable(int location_id) {
437 return false; 451 return false;
438 } 452 }
439} 453}
454
455bool IsDoorOpen(int door_id) {
456 std::lock_guard reachability_guard(GetState().reachability_mutex);
457
458 return GetState().reachable_doors.count(door_id);
459}
diff --git a/src/tracker_state.h b/src/tracker_state.h index e73607f..119b3b5 100644 --- a/src/tracker_state.h +++ b/src/tracker_state.h
@@ -5,4 +5,6 @@ void RecalculateReachability();
5 5
6bool IsLocationReachable(int location_id); 6bool IsLocationReachable(int location_id);
7 7
8bool IsDoorOpen(int door_id);
9
8#endif /* end of include guard: TRACKER_STATE_H_8639BC90 */ 10#endif /* end of include guard: TRACKER_STATE_H_8639BC90 */