about summary refs log tree commit diff stats
path: root/Archipelago
Commit message (Collapse)AuthorAgeFilesLines
* Send checked paintings to serverStar Rauchenberger2024-05-152-59/+85
|
* Bump version v3.0.1Star Rauchenberger2024-04-221-1/+1
|
* Make progression items resistant to renamesStar Rauchenberger2024-04-221-57/+17
|
* Prevent pilgrimage_terminator reformatting issue v3.0.0Star Rauchenberger2024-04-181-1/+2
|
* Bump version and AP versionStar Rauchenberger2024-04-181-2/+2
|
* Fix duplication from mergeStar Rauchenberger2024-04-181-5/+0
|
* Merge branch 'sunwarps' into futureStar Rauchenberger2024-04-1810-19/+196
|\
| * Backwards compatibility with 0.4.5Star Rauchenberger2024-04-182-1/+13
| |
| * Merge branch 'main' into sunwarpsStar Rauchenberger2024-04-185-17/+185
| |\
| * | Fix atbash never clearingStar Rauchenberger2024-03-171-0/+4
| | |
| * | Fixed pilgrimage terminator load for compileStar Rauchenberger2024-03-171-3/+1
| | |
| * | Set beta versionStar Rauchenberger2024-03-171-1/+1
| | |
| * | Merge branch 'future' into sunwarpsStar Rauchenberger2024-03-176-66/+186
| |\ \
| * | | Added sunwarp shufflingStar Rauchenberger2024-03-022-0/+70
| | | |
| * | | Add pilgrimage allows roof access / paintingsStar Rauchenberger2024-02-2810-17/+92
| | | |
| * | | Fix sunwarp accessStar Rauchenberger2024-02-282-14/+11
| | | |
| * | | Added pilgrimage goalStar Rauchenberger2024-02-262-1/+9
| | | |
| * | | Sun Painting should be vanilla when pilgrimage is onStar Rauchenberger2024-02-262-2/+10
| | | |
* | | | Reapply "Added support for warp items (including sunwarps)"Star Rauchenberger2024-04-183-0/+51
| |_|/ |/| | | | | | | | This reverts commit 17572f8cd5945536eccffbbe832517d75993c03f.
* | | Bump version v2.2.0Star Rauchenberger2024-04-171-1/+1
| | |
* | | Prevent colorful cdp if genned before 0.4.5Star Rauchenberger2024-04-172-11/+28
| | |
* | | Add connection historyStar Rauchenberger2024-04-172-1/+36
| | |
* | | Bump version v2.1.1Star Rauchenberger2024-04-111-1/+1
| | |
* | | Log Steam build ID for debuggingStar Rauchenberger2024-04-091-0/+6
| | |
* | | Bump version v2.1.0Star Rauchenberger2024-04-031-1/+1
| | |
* | | Added player position trackingStar Rauchenberger2024-04-034-1/+47
| | |
* | | AFD 2024: Remove inverted camera thingStar Rauchenberger2024-04-011-15/+0
| | |
* | | Bump version v2.0.0Star Rauchenberger2024-03-311-1/+1
| | |
* | | Merge branch 'future'Star Rauchenberger2024-03-312-3/+28
|\ \ \ | | |/ | |/|
| * | Bump AP versionStar Rauchenberger2024-03-151-1/+1
| | |
| * | Bump beta versionStar Rauchenberger2024-03-151-1/+1
| | |
| * | Merge branch 'main' into futureStar Rauchenberger2024-03-156-64/+184
| |\ \
| * | | Bump versionStar Rauchenberger2024-02-201-1/+1
| | | |
| * | | Revert "Added support for warp items (including sunwarps)"Star Rauchenberger2024-02-203-51/+0
| | |/ | |/| | | | | | | This reverts commit b2b098573ef5bcd03d61e827d11b969460d992af.
| * | Added support for warp items (including sunwarps)Star Rauchenberger2024-01-313-0/+51
| | |
| * | Need to delete door blocking Colorful cdpStar Rauchenberger2024-01-191-0/+1
| | |
| * | Add progressive colorfulStar Rauchenberger2024-01-121-0/+13
| | |
| * | Turn THE COLORFUL into a cdpStar Rauchenberger2024-01-121-1/+12
| | |
* | | AFD notnerbStar Rauchenberger2024-03-291-0/+18
| | |
* | | AFD inverted cameraStar Rauchenberger2024-03-281-0/+15
| | |
* | | Fix Wanderer entrance door on reloadStar Rauchenberger2024-03-251-1/+1
| | | | | | | | | | | | Turns out when you instantiate scripts with exported reference fields, you have to create new values for those fields because otherwise they use a shared value like idk man it's weird.
* | | Geronimo gets you a puzzle skipStar Rauchenberger2024-03-242-2/+21
| | |
* | | Transition into using level1_stableStar Rauchenberger2024-03-231-1/+6
| | |
* | | Replace the roof of The Artistic in painting shuffleStar Rauchenberger2024-03-231-1/+23
| |/ |/|
* | Fix panel count subtractionStar Rauchenberger2024-02-092-2/+2
| |
* | Bump version v1.2.0Star Rauchenberger2024-02-041-1/+1
| |
* | Persist traps between connectionsStar Rauchenberger2024-02-043-8/+63
| |
* | Atbash Trap now stacksStar Rauchenberger2024-02-042-10/+14
| |
* | More accurate wall snipe detectionStar Rauchenberger2024-02-041-4/+15
| |
* | Effects text is more prompt nowStar Rauchenberger2024-01-232-42/+79
| | | | | | | | Slowness and Iceland aren't forced to tick at the same time anymore. Puzzle skip popups show up instantly and disappear instantly. Puzzle skip popups do not show up for puzzles hidden behind walls (although you can still press p to skip).
span><< "Invalid color: " << str; TrackerLog(errmsg.str()); return LingoColor::kNone; } } struct GameData { std::vector<Room> rooms_; std::vector<Door> doors_; std::vector<Panel> panels_; std::vector<MapArea> map_areas_; std::map<std::string, int> room_by_id_; std::map<std::string, int> door_by_id_; std::map<std::string, int> panel_by_id_; std::map<std::string, int> area_by_id_; std::vector<int> door_definition_order_; std::map<std::string, int> room_by_painting_; std::vector<int> achievement_panels_; std::map<LingoColor, int> ap_id_by_color_; bool loaded_area_data_ = false; std::set<std::string> malconfigured_areas_; GameData() { YAML::Node lingo_config = YAML::LoadFile(GetAbsolutePath("assets/LL1.yaml")); YAML::Node areas_config = YAML::LoadFile(GetAbsolutePath("assets/areas.yaml")); YAML::Node pilgrimage_config = YAML::LoadFile(GetAbsolutePath("assets/pilgrimage.yaml")); YAML::Node ids_config = YAML::LoadFile(GetAbsolutePath("assets/ids.yaml")); auto init_color_id = [this, &ids_config](const std::string &color_name) { if (ids_config["special_items"] && ids_config["special_items"][color_name]) { std::string input_name = color_name; input_name[0] = std::tolower(input_name[0]); ap_id_by_color_[GetColorForString(input_name)] = ids_config["special_items"][color_name].as<int>(); } else { std::ostringstream errmsg; errmsg << "Missing AP item ID for color " << color_name; TrackerLog(errmsg.str()); } }; init_color_id("Black"); init_color_id("Red"); init_color_id("Blue"); init_color_id("Yellow"); init_color_id("Green"); init_color_id("Orange"); init_color_id("Purple"); init_color_id("Brown"); init_color_id("Gray"); rooms_.reserve(lingo_config.size() * 2); for (const auto &room_it : lingo_config) { int room_id = AddOrGetRoom(room_it.first.as<std::string>()); for (const auto &entrance_it : room_it.second["entrances"]) { int from_room_id = AddOrGetRoom(entrance_it.first.as<std::string>()); switch (entrance_it.second.Type()) { case YAML::NodeType::Scalar: { // This is just "true". rooms_[from_room_id].exits.push_back({.destination_room = room_id}); break; } case YAML::NodeType::Map: { Exit exit_obj; exit_obj.destination_room = room_id; if (entrance_it.second["door"]) { std::string door_room = rooms_[room_id].name; if (entrance_it.second["room"]) { door_room = entrance_it.second["room"].as<std::string>(); } exit_obj.door = AddOrGetDoor( door_room, entrance_it.second["door"].as<std::string>()); } if (entrance_it.second["painting"]) { exit_obj.painting = entrance_it.second["painting"].as<bool>(); } rooms_[from_room_id].exits.push_back(exit_obj); break; } case YAML::NodeType::Sequence: { for (const auto &option : entrance_it.second) { Exit exit_obj; exit_obj.destination_room = room_id; std::string door_room = rooms_[room_id].name; if (option["room"]) { door_room = option["room"].as<std::string>(); } exit_obj.door = AddOrGetDoor(door_room, option["door"].as<std::string>()); if (option["painting"]) { exit_obj.painting = option["painting"].as<bool>(); } rooms_[from_room_id].exits.push_back(exit_obj); } break; } default: { // This shouldn't happen. std::cout << "Error reading game data: " << entrance_it << std::endl; break; } } } if (room_it.second["panels"]) { for (const auto &panel_it : room_it.second["panels"]) { int panel_id = AddOrGetPanel(rooms_[room_id].name, panel_it.first.as<std::string>()); rooms_[room_id].panels.push_back(panel_id); if (panel_it.second["colors"]) { if (panel_it.second["colors"].IsScalar()) { panels_[panel_id].colors.push_back(GetColorForString( panel_it.second["colors"].as<std::string>())); } else { for (const auto &color_node : panel_it.second["colors"]) { panels_[panel_id].colors.push_back( GetColorForString(color_node.as<std::string>())); } } } if (panel_it.second["required_room"]) { if (panel_it.second["required_room"].IsScalar()) { panels_[panel_id].required_rooms.push_back(AddOrGetRoom( panel_it.second["required_room"].as<std::string>())); } else { for (const auto &rr_node : panel_it.second["required_room"]) { panels_[panel_id].required_rooms.push_back( AddOrGetRoom(rr_node.as<std::string>())); } } } if (panel_it.second["required_door"]) { if (panel_it.second["required_door"].IsMap()) { std::string rd_room = rooms_[room_id].name; if (panel_it.second["required_door"]["room"]) { rd_room = panel_it.second["required_door"]["room"].as<std::string>(); } panels_[panel_id].required_doors.push_back(AddOrGetDoor( rd_room, panel_it.second["required_door"]["door"].as<std::string>())); } else { for (const auto &rr_node : panel_it.second["required_door"]) { std::string rd_room = rooms_[room_id].name; if (rr_node["room"]) { rd_room = rr_node["room"].as<std::string>(); }; panels_[panel_id].required_doors.push_back( AddOrGetDoor(rd_room, rr_node["door"].as<std::string>())); } } } if (panel_it.second["required_panel"]) { if (panel_it.second["required_panel"].IsMap()) { std::string rp_room = rooms_[room_id].name; if (panel_it.second["required_panel"]["room"]) { rp_room = panel_it.second["required_panel"]["room"].as<std::string>(); } int rp_id = AddOrGetPanel( rp_room, panel_it.second["required_panel"]["panel"].as<std::string>()); panels_[panel_id].required_panels.push_back(rp_id); } else { for (const auto &rp_node : panel_it.second["required_panel"]) { std::string rp_room = rooms_[room_id].name; if (rp_node["room"]) { rp_room = rp_node["room"].as<std::string>(); } int rp_id = AddOrGetPanel(rp_room, rp_node["panel"].as<std::string>()); panels_[panel_id].required_panels.push_back(rp_id); } } } if (panel_it.second["check"]) { panels_[panel_id].check = panel_it.second["check"].as<bool>(); } if (panel_it.second["achievement"]) { panels_[panel_id].achievement = true; panels_[panel_id].achievement_name = panel_it.second["achievement"].as<std::string>(); achievement_panels_.push_back(panel_id); } if (panel_it.second["hunt"]) { panels_[panel_id].hunt = panel_it.second["hunt"].as<bool>(); } if (panel_it.second["exclude_reduce"]) { panels_[panel_id].exclude_reduce = panel_it.second["exclude_reduce"].as<bool>(); } if (panel_it.second["non_counting"]) { panels_[panel_id].non_counting = panel_it.second["non_counting"].as<bool>(); } if (ids_config["panels"] && ids_config["panels"][rooms_[room_id].name] && ids_config["panels"][rooms_[room_id].name] [panels_[panel_id].name]) { panels_[panel_id].ap_location_id = ids_config["panels"][rooms_[room_id].name] [panels_[panel_id].name] .as<int>(); } else { std::ostringstream errmsg; errmsg << "Missing AP location ID for panel " << rooms_[room_id].name << " - " << panels_[panel_id].name; TrackerLog(errmsg.str()); } } } if (room_it.second["doors"]) { for (const auto &door_it : room_it.second["doors"]) { int door_id = AddOrGetDoor(rooms_[room_id].name, door_it.first.as<std::string>()); door_definition_order_.push_back(door_id); bool has_external_panels = false; std::vector<std::string> panel_names; for (const auto &panel_node : door_it.second["panels"]) { if (panel_node.IsScalar()) { panel_names.push_back(panel_node.as<std::string>()); doors_[door_id].panels.push_back(AddOrGetPanel( rooms_[room_id].name, panel_node.as<std::string>())); } else { has_external_panels = true; panel_names.push_back(panel_node["panel"].as<std::string>()); doors_[door_id].panels.push_back( AddOrGetPanel(panel_node["room"].as<std::string>(), panel_node["panel"].as<std::string>())); } } if (door_it.second["skip_location"]) { doors_[door_id].skip_location = door_it.second["skip_location"].as<bool>(); } if (door_it.second["skip_item"]) { doors_[door_id].skip_item = door_it.second["skip_item"].as<bool>(); } if (door_it.second["event"]) { doors_[door_id].skip_location = door_it.second["event"].as<bool>(); doors_[door_id].skip_item = door_it.second["event"].as<bool>(); doors_[door_id].is_event = door_it.second["event"].as<bool>(); } if (door_it.second["item_name"]) { doors_[door_id].item_name = door_it.second["item_name"].as<std::string>(); } else if (!door_it.second["skip_item"] && !door_it.second["event"]) { doors_[door_id].item_name = rooms_[room_id].name + " - " + doors_[door_id].name; } if (!door_it.second["skip_item"] && !door_it.second["event"]) { if (ids_config["doors"] && ids_config["doors"][rooms_[room_id].name] && ids_config["doors"][rooms_[room_id].name] [doors_[door_id].name] && ids_config["doors"][rooms_[room_id].name][doors_[door_id].name] ["item"]) { doors_[door_id].ap_item_id = ids_config["doors"][rooms_[room_id].name] [doors_[door_id].name]["item"] .as<int>(); } else { std::ostringstream errmsg; errmsg << "Missing AP item ID for door " << rooms_[room_id].name << " - " << doors_[door_id].name; TrackerLog(errmsg.str()); } } if (door_it.second["group"]) { doors_[door_id].group_name = door_it.second["group"].as<std::string>(); if (ids_config["door_groups"] && ids_config["door_groups"][doors_[door_id].group_name]) { doors_[door_id].group_ap_item_id = ids_config["door_groups"][doors_[door_id].group_name] .as<int>(); } else { std::ostringstream errmsg; errmsg << "Missing AP item ID for door group " << doors_[door_id].group_name; TrackerLog(errmsg.str()); } } if (door_it.second["location_name"]) { doors_[door_id].location_name = door_it.second["location_name"].as<std::string>(); } else if (!door_it.second["skip_location"] && !door_it.second["event"]) { if (has_external_panels) { std::ostringstream errmsg; errmsg << rooms_[room_id].name << " - " << doors_[door_id].name << " has panels from other rooms but does not have an " "explicit " "location name and is not marked skip_location or event"; TrackerLog(errmsg.str()); } doors_[door_id].location_name = rooms_[room_id].name + " - " + hatkirby::implode(panel_names, ", "); } if (!door_it.second["skip_location"] && !door_it.second["event"]) { if (ids_config["doors"] && ids_config["doors"][rooms_[room_id].name] && ids_config["doors"][rooms_[room_id].name] [doors_[door_id].name] && ids_config["doors"][rooms_[room_id].name][doors_[door_id].name] ["location"]) { doors_[door_id].ap_location_id = ids_config["doors"][rooms_[room_id].name] [doors_[door_id].name]["location"] .as<int>(); } else { std::ostringstream errmsg; errmsg << "Missing AP location ID for door " << rooms_[room_id].name << " - " << doors_[door_id].name; TrackerLog(errmsg.str()); } } if (door_it.second["include_reduce"]) { doors_[door_id].exclude_reduce = !door_it.second["include_reduce"].as<bool>(); } } } if (room_it.second["paintings"]) { for (const auto &painting : room_it.second["paintings"]) { std::string painting_id = painting["id"].as<std::string>(); room_by_painting_[painting_id] = room_id; if (!painting["exit_only"] || !painting["exit_only"].as<bool>()) { PaintingExit painting_exit; painting_exit.id = painting_id; if (painting["required_door"]) { std::string rd_room = rooms_[room_id].name; if (painting["required_door"]["room"]) { rd_room = painting["required_door"]["room"].as<std::string>(); } painting_exit.door = AddOrGetDoor( rd_room, painting["required_door"]["door"].as<std::string>()); } rooms_[room_id].paintings.push_back(painting_exit); } } } if (room_it.second["progression"]) { for (const auto &progression_it : room_it.second["progression"]) { std::string progressive_item_name = progression_it.first.as<std::string>(); int progressive_item_id = -1; if (ids_config["progression"] && ids_config["progression"][progressive_item_name]) { progressive_item_id = ids_config["progression"][progressive_item_name].as<int>(); } else { std::ostringstream errmsg; errmsg << "Missing AP item ID for progressive item " << progressive_item_name; TrackerLog(errmsg.str()); } int index = 1; for (const auto &stage : progression_it.second) { int door_id = -1; if (stage.IsScalar()) { door_id = AddOrGetDoor(rooms_[room_id].name, stage.as<std::string>()); } else { door_id = AddOrGetDoor(stage["room"].as<std::string>(), stage["door"].as<std::string>()); } doors_[door_id].progressives.push_back( {.item_name = progressive_item_name, .ap_item_id = progressive_item_id, .quantity = index}); index++; } } } } map_areas_.reserve(areas_config.size()); std::map<std::string, int> fold_areas; for (const auto &area_it : areas_config) { if (area_it.second["map"]) { int area_id = AddOrGetArea(area_it.first.as<std::string>()); MapArea &area_obj = map_areas_[area_id]; area_obj.map_x = area_it.second["map"][0].as<int>(); area_obj.map_y = area_it.second["map"][1].as<int>(); } else if (area_it.second["fold_into"]) { fold_areas[area_it.first.as<std::string>()] = AddOrGetArea(area_it.second["fold_into"].as<std::string>()); } } loaded_area_data_ = true; // Only locations for the panels are kept here. std::map<std::string, std::tuple<int, int>> locations_by_name; for (const Panel &panel : panels_) { 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; } 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, .ap_location_id = panel.ap_location_id, .room = panel.room, .panels = {panel.id}, .classification = classification, .hunt = panel.hunt}); 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 classification = kLOCATION_NORMAL; if (!door.exclude_reduce) { classification |= kLOCATION_REDUCED; } 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 { 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; } 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, .ap_location_id = door.ap_location_id, .room = door.room, .panels = door.panels, .classification = classification}); } } } for (MapArea &map_area : map_areas_) { for (const Location &location : map_area.locations) { map_area.classification |= location.classification; map_area.hunt |= location.hunt; } } // Set up fake pilgrimage. int fake_pilgrim_panel_id = AddOrGetPanel("Starting Room", "!! Fake Pilgrimage Panel"); Panel &fake_pilgrim_panel_obj = panels_[fake_pilgrim_panel_id]; fake_pilgrim_panel_obj.non_counting = true; for (const auto &config_node : pilgrimage_config) { fake_pilgrim_panel_obj.required_doors.push_back( AddOrGetDoor(config_node["room"].as<std::string>(), config_node["door"].as<std::string>())); } int fake_pilgrim_door_id = AddOrGetDoor("Starting Room", "!! Fake Pilgrimage Door"); Door &fake_pilgrim_door_obj = doors_[fake_pilgrim_door_id]; fake_pilgrim_door_obj.panels.push_back(fake_pilgrim_panel_id); fake_pilgrim_door_obj.skip_location = true; fake_pilgrim_door_obj.skip_item = true; fake_pilgrim_door_obj.is_event = true; int starting_room_id = AddOrGetRoom("Starting Room"); Room &starting_room_obj = rooms_[starting_room_id]; starting_room_obj.panels.push_back(fake_pilgrim_panel_id); 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) { if (!room_by_id_.count(room)) { room_by_id_[room] = rooms_.size(); rooms_.push_back({.name = room}); } return room_by_id_[room]; } int AddOrGetDoor(std::string room, std::string door) { std::string full_name = room + " - " + door; if (!door_by_id_.count(full_name)) { door_by_id_[full_name] = doors_.size(); doors_.push_back({.room = AddOrGetRoom(room), .name = door}); } return door_by_id_[full_name]; } int AddOrGetPanel(std::string room, std::string panel) { std::string full_name = room + " - " + panel; if (!panel_by_id_.count(full_name)) { int panel_id = panels_.size(); panel_by_id_[full_name] = panel_id; panels_.push_back( {.id = panel_id, .room = AddOrGetRoom(room), .name = panel}); } return panel_by_id_[full_name]; } 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}); } return area_by_id_[area]; } }; GameData &GetState() { static GameData *instance = new GameData(); return *instance; } } // namespace const std::vector<MapArea> &GD_GetMapAreas() { return GetState().map_areas_; } const MapArea &GD_GetMapArea(int id) { return GetState().map_areas_.at(id); } int GD_GetRoomByName(const std::string &name) { return GetState().room_by_id_.at(name); } const Room &GD_GetRoom(int room_id) { return GetState().rooms_.at(room_id); } const std::vector<Door> &GD_GetDoors() { return GetState().doors_; } const Door &GD_GetDoor(int door_id) { return GetState().doors_.at(door_id); } const Panel &GD_GetPanel(int panel_id) { return GetState().panels_.at(panel_id); } int GD_GetRoomForPainting(const std::string &painting_id) { return GetState().room_by_painting_.at(painting_id); } const std::vector<int> &GD_GetAchievementPanels() { return GetState().achievement_panels_; } int GD_GetItemIdForColor(LingoColor color) { return GetState().ap_id_by_color_.at(color); }