about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/ap_state.cpp15
-rw-r--r--src/ap_state.h4
-rw-r--r--src/game_data.cpp123
-rw-r--r--src/game_data.h8
-rw-r--r--src/tracker_state.cpp22
-rw-r--r--src/version.cpp5
6 files changed, 162 insertions, 15 deletions
diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 8ff0ccd..a7565cf 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp
@@ -56,6 +56,7 @@ struct APState {
56 std::optional<std::tuple<int, int>> player_pos; 56 std::optional<std::tuple<int, int>> player_pos;
57 57
58 DoorShuffleMode door_shuffle_mode = kNO_DOORS; 58 DoorShuffleMode door_shuffle_mode = kNO_DOORS;
59 bool group_doors = false;
59 bool color_shuffle = false; 60 bool color_shuffle = false;
60 bool painting_shuffle = false; 61 bool painting_shuffle = false;
61 int mastery_requirement = 21; 62 int mastery_requirement = 21;
@@ -135,6 +136,7 @@ struct APState {
135 player_pos = std::nullopt; 136 player_pos = std::nullopt;
136 victory_data_storage_key.clear(); 137 victory_data_storage_key.clear();
137 door_shuffle_mode = kNO_DOORS; 138 door_shuffle_mode = kNO_DOORS;
139 group_doors = false;
138 color_shuffle = false; 140 color_shuffle = false;
139 painting_shuffle = false; 141 painting_shuffle = false;
140 painting_mapping.clear(); 142 painting_mapping.clear();
@@ -227,6 +229,17 @@ struct APState {
227 data_storage_prefix = 229 data_storage_prefix =
228 "Lingo_" + std::to_string(apclient->get_player_number()) + "_"; 230 "Lingo_" + std::to_string(apclient->get_player_number()) + "_";
229 door_shuffle_mode = slot_data["shuffle_doors"].get<DoorShuffleMode>(); 231 door_shuffle_mode = slot_data["shuffle_doors"].get<DoorShuffleMode>();
232 if (slot_data.contains("group_doors")) {
233 group_doors = slot_data.contains("group_doors") &&
234 slot_data["group_doors"].get<int>() == 1;
235 } else {
236 // If group_doors doesn't exist yet, that means kPANELS_MODE is actually
237 // kSIMPLE_DOORS.
238 if (door_shuffle_mode == kPANELS_MODE) {
239 door_shuffle_mode = kDOORS_MODE;
240 group_doors = true;
241 }
242 }
230 color_shuffle = slot_data["shuffle_colors"].get<int>() == 1; 243 color_shuffle = slot_data["shuffle_colors"].get<int>() == 1;
231 painting_shuffle = slot_data["shuffle_paintings"].get<int>() == 1; 244 painting_shuffle = slot_data["shuffle_paintings"].get<int>() == 1;
232 mastery_requirement = slot_data["mastery_achievements"].get<int>(); 245 mastery_requirement = slot_data["mastery_achievements"].get<int>();
@@ -524,6 +537,8 @@ std::string AP_GetItemName(int item_id) {
524 537
525DoorShuffleMode AP_GetDoorShuffleMode() { return GetState().door_shuffle_mode; } 538DoorShuffleMode AP_GetDoorShuffleMode() { return GetState().door_shuffle_mode; }
526 539
540bool AP_AreDoorsGrouped() { return GetState().group_doors; }
541
527bool AP_IsColorShuffle() { return GetState().color_shuffle; } 542bool AP_IsColorShuffle() { return GetState().color_shuffle; }
528 543
529bool AP_IsPaintingShuffle() { return GetState().painting_shuffle; } 544bool AP_IsPaintingShuffle() { return GetState().painting_shuffle; }
diff --git a/src/ap_state.h b/src/ap_state.h index 7af7395..190b21f 100644 --- a/src/ap_state.h +++ b/src/ap_state.h
@@ -11,7 +11,7 @@
11 11
12class TrackerFrame; 12class TrackerFrame;
13 13
14enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 }; 14enum DoorShuffleMode { kNO_DOORS = 0, kPANELS_MODE = 1, kDOORS_MODE = 2 };
15 15
16enum VictoryCondition { 16enum VictoryCondition {
17 kTHE_END = 0, 17 kTHE_END = 0,
@@ -53,6 +53,8 @@ std::string AP_GetItemName(int item_id);
53 53
54DoorShuffleMode AP_GetDoorShuffleMode(); 54DoorShuffleMode AP_GetDoorShuffleMode();
55 55
56bool AP_AreDoorsGrouped();
57
56bool AP_IsColorShuffle(); 58bool AP_IsColorShuffle();
57 59
58bool AP_IsPaintingShuffle(); 60bool AP_IsPaintingShuffle();
diff --git a/src/game_data.cpp b/src/game_data.cpp index 6f1a2e4..1ccf511 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp
@@ -46,6 +46,7 @@ struct GameData {
46 std::vector<Room> rooms_; 46 std::vector<Room> rooms_;
47 std::vector<Door> doors_; 47 std::vector<Door> doors_;
48 std::vector<Panel> panels_; 48 std::vector<Panel> panels_;
49 std::vector<PanelDoor> panel_doors_;
49 std::vector<MapArea> map_areas_; 50 std::vector<MapArea> map_areas_;
50 std::vector<SubwayItem> subway_items_; 51 std::vector<SubwayItem> subway_items_;
51 std::vector<PaintingExit> paintings_; 52 std::vector<PaintingExit> paintings_;
@@ -53,6 +54,7 @@ struct GameData {
53 std::map<std::string, int> room_by_id_; 54 std::map<std::string, int> room_by_id_;
54 std::map<std::string, int> door_by_id_; 55 std::map<std::string, int> door_by_id_;
55 std::map<std::string, int> panel_by_id_; 56 std::map<std::string, int> panel_by_id_;
57 std::map<std::string, int> panel_doors_by_id_;
56 std::map<std::string, int> area_by_id_; 58 std::map<std::string, int> area_by_id_;
57 std::map<std::string, int> painting_by_id_; 59 std::map<std::string, int> painting_by_id_;
58 60
@@ -424,6 +426,59 @@ struct GameData {
424 } 426 }
425 } 427 }
426 428
429 if (room_it.second["panel_doors"]) {
430 for (const auto &panel_door_it : room_it.second["panel_doors"]) {
431 std::string panel_door_name = panel_door_it.first.as<std::string>();
432 int panel_door_id =
433 AddOrGetPanelDoor(rooms_[room_id].name, panel_door_name);
434
435 for (const auto &panel_node : panel_door_it.second["panels"]) {
436 int panel_id = -1;
437
438 if (panel_node.IsScalar()) {
439 panel_id = AddOrGetPanel(rooms_[room_id].name,
440 panel_node.as<std::string>());
441 } else {
442 panel_id = AddOrGetPanel(panel_node["room"].as<std::string>(),
443 panel_node["panel"].as<std::string>());
444 }
445
446 Panel &panel = panels_[panel_id];
447 panel.panel_door = panel_door_id;
448 }
449
450 if (ids_config["panel_doors"] &&
451 ids_config["panel_doors"][rooms_[room_id].name] &&
452 ids_config["panel_doors"][rooms_[room_id].name]
453 [panel_door_name]) {
454 panel_doors_[panel_door_id].ap_item_id =
455 ids_config["panel_doors"][rooms_[room_id].name][panel_door_name]
456 .as<int>();
457 } else {
458 std::ostringstream errmsg;
459 errmsg << "Missing AP item ID for panel door "
460 << rooms_[room_id].name << " - " << panel_door_name;
461 TrackerLog(errmsg.str());
462 }
463
464 if (panel_door_it.second["panel_group"]) {
465 std::string panel_group =
466 panel_door_it.second["panel_group"].as<std::string>();
467
468 if (ids_config["panel_groups"] &&
469 ids_config["panel_groups"][panel_group]) {
470 panel_doors_[panel_door_id].group_ap_item_id =
471 ids_config["panel_groups"][panel_group].as<int>();
472 } else {
473 std::ostringstream errmsg;
474 errmsg << "Missing AP item ID for panel door group "
475 << panel_group;
476 TrackerLog(errmsg.str());
477 }
478 }
479 }
480 }
481
427 if (room_it.second["paintings"]) { 482 if (room_it.second["paintings"]) {
428 for (const auto &painting : room_it.second["paintings"]) { 483 for (const auto &painting : room_it.second["paintings"]) {
429 std::string internal_id = painting["id"].as<std::string>(); 484 std::string internal_id = painting["id"].as<std::string>();
@@ -477,23 +532,47 @@ struct GameData {
477 progressive_item_name); 532 progressive_item_name);
478 } 533 }
479 534
480 int index = 1; 535 if (progression_it.second["doors"]) {
481 for (const auto &stage : progression_it.second) { 536 int index = 1;
482 int door_id = -1; 537 for (const auto &stage : progression_it.second["doors"]) {
538 int door_id = -1;
483 539
484 if (stage.IsScalar()) { 540 if (stage.IsScalar()) {
485 door_id = 541 door_id =
486 AddOrGetDoor(rooms_[room_id].name, stage.as<std::string>()); 542 AddOrGetDoor(rooms_[room_id].name, stage.as<std::string>());
487 } else { 543 } else {
488 door_id = AddOrGetDoor(stage["room"].as<std::string>(), 544 door_id = AddOrGetDoor(stage["room"].as<std::string>(),
489 stage["door"].as<std::string>()); 545 stage["door"].as<std::string>());
546 }
547
548 doors_[door_id].progressives.push_back(
549 {.item_name = progressive_item_name,
550 .ap_item_id = progressive_item_id,
551 .quantity = index});
552 index++;
490 } 553 }
554 }
491 555
492 doors_[door_id].progressives.push_back( 556 if (progression_it.second["panel_doors"]) {
493 {.item_name = progressive_item_name, 557 int index = 1;
494 .ap_item_id = progressive_item_id, 558 for (const auto &stage : progression_it.second["panel_doors"]) {
495 .quantity = index}); 559 int panel_door_id = -1;
496 index++; 560
561 if (stage.IsScalar()) {
562 panel_door_id = AddOrGetPanelDoor(rooms_[room_id].name,
563 stage.as<std::string>());
564 } else {
565 panel_door_id =
566 AddOrGetPanelDoor(stage["room"].as<std::string>(),
567 stage["panel_door"].as<std::string>());
568 }
569
570 panel_doors_[panel_door_id].progressives.push_back(
571 {.item_name = progressive_item_name,
572 .ap_item_id = progressive_item_id,
573 .quantity = index});
574 index++;
575 }
497 } 576 }
498 } 577 }
499 } 578 }
@@ -749,6 +828,18 @@ struct GameData {
749 return panel_by_id_[full_name]; 828 return panel_by_id_[full_name];
750 } 829 }
751 830
831 int AddOrGetPanelDoor(std::string room, std::string panel) {
832 std::string full_name = room + " - " + panel;
833
834 if (!panel_doors_by_id_.count(full_name)) {
835 int panel_door_id = panel_doors_.size();
836 panel_doors_by_id_[full_name] = panel_door_id;
837 panel_doors_.push_back({});
838 }
839
840 return panel_doors_by_id_[full_name];
841 }
842
752 int AddOrGetArea(std::string area) { 843 int AddOrGetArea(std::string area) {
753 if (!area_by_id_.count(area)) { 844 if (!area_by_id_.count(area)) {
754 if (loaded_area_data_) { 845 if (loaded_area_data_) {
@@ -799,6 +890,10 @@ const std::vector<Door> &GD_GetDoors() { return GetState().doors_; }
799 890
800const Door &GD_GetDoor(int door_id) { return GetState().doors_.at(door_id); } 891const Door &GD_GetDoor(int door_id) { return GetState().doors_.at(door_id); }
801 892
893const PanelDoor &GD_GetPanelDoor(int panel_door_id) {
894 return GetState().panel_doors_.at(panel_door_id);
895}
896
802int GD_GetDoorByName(const std::string &name) { 897int GD_GetDoorByName(const std::string &name) {
803 return GetState().door_by_id_.at(name); 898 return GetState().door_by_id_.at(name);
804} 899}
diff --git a/src/game_data.h b/src/game_data.h index e37c276..aca4c3d 100644 --- a/src/game_data.h +++ b/src/game_data.h
@@ -54,6 +54,7 @@ struct Panel {
54 bool non_counting = false; 54 bool non_counting = false;
55 int ap_location_id = -1; 55 int ap_location_id = -1;
56 bool hunt = false; 56 bool hunt = false;
57 int panel_door = -1;
57}; 58};
58 59
59struct ProgressiveRequirement { 60struct ProgressiveRequirement {
@@ -81,6 +82,12 @@ struct Door {
81 DoorType type = DoorType::kNormal; 82 DoorType type = DoorType::kNormal;
82}; 83};
83 84
85struct PanelDoor {
86 int ap_item_id = -1;
87 int group_ap_item_id = -1;
88 std::vector<ProgressiveRequirement> progressives;
89};
90
84struct Exit { 91struct Exit {
85 int destination_room; 92 int destination_room;
86 std::optional<int> door; 93 std::optional<int> door;
@@ -156,6 +163,7 @@ const std::vector<Door>& GD_GetDoors();
156const Door& GD_GetDoor(int door_id); 163const Door& GD_GetDoor(int door_id);
157int GD_GetDoorByName(const std::string& name); 164int GD_GetDoorByName(const std::string& name);
158const Panel& GD_GetPanel(int panel_id); 165const Panel& GD_GetPanel(int panel_id);
166const PanelDoor& GD_GetPanelDoor(int panel_door_id);
159const PaintingExit& GD_GetPaintingExit(int painting_id); 167const PaintingExit& GD_GetPaintingExit(int painting_id);
160int GD_GetPaintingByName(const std::string& name); 168int GD_GetPaintingByName(const std::string& name);
161const std::vector<int>& GD_GetAchievementPanels(); 169const std::vector<int>& GD_GetAchievementPanels();
diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index a4134f9..c475fb7 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp
@@ -486,6 +486,28 @@ class StateCalculator {
486 return IsDoorReachable(*painting.door); 486 return IsDoorReachable(*painting.door);
487 } 487 }
488 488
489 if (panel_obj.panel_door != -1 && AP_GetDoorShuffleMode() == kPANELS_MODE) {
490 const PanelDoor& panel_door_obj = GD_GetPanelDoor(panel_obj.panel_door);
491
492 if (AP_AreDoorsGrouped() && panel_door_obj.group_ap_item_id != -1) {
493 return AP_HasItem(panel_door_obj.group_ap_item_id) ? kYes : kNo;
494 } else {
495 bool has_item = AP_HasItem(panel_door_obj.ap_item_id);
496
497 if (!has_item) {
498 for (const ProgressiveRequirement& prog_req :
499 panel_door_obj.progressives) {
500 if (AP_HasItem(prog_req.ap_item_id, prog_req.quantity)) {
501 has_item = true;
502 break;
503 }
504 }
505 }
506
507 return has_item ? kYes : kNo;
508 }
509 }
510
489 return kYes; 511 return kYes;
490 } 512 }
491 513
diff --git a/src/version.cpp b/src/version.cpp new file mode 100644 index 0000000..3b4d5f3 --- /dev/null +++ b/src/version.cpp
@@ -0,0 +1,5 @@
1#include "version.h"
2
3std::ostream& operator<<(std::ostream& out, const Version& ver) {
4 return out << "v" << ver.major << "." << ver.minor << "." << ver.revision;
5}