basic backend for tracking

This commit is contained in:
gymnast86
2026-05-19 22:13:06 -07:00
parent 9e8b451462
commit b74603c883
9 changed files with 146 additions and 9 deletions
+1
View File
@@ -378,6 +378,7 @@ namespace dusk {
}
m_menuRandomizer.windowRandoStats();
m_menuRandomizer.windowRandoGeneration();
m_menuRandomizer.windowRandoTracker();
// Hide mouse cursor if the F1 menu is not open and the cursor is idle for 3 seconds.
if (dusk::getSettings().game.gyroMode.getValue() != GyroMode::Mouse)
+83
View File
@@ -15,6 +15,7 @@
#include <filesystem>
#include "dusk/data.hpp"
#include "dusk/randomizer/generator/logic/search.hpp"
namespace dusk {
@@ -142,6 +143,8 @@ namespace dusk {
}
ImGui::Checkbox("Show Rando Stats", &m_showRandoStats);
ImGui::Checkbox("Show Rando Tracker", &m_showRandoTracker);
ImGui::EndMenu();
}
}
@@ -207,4 +210,84 @@ namespace dusk {
ImGui::End();
}
void ImGuiMenuRandomizer::windowRandoTracker() {
if (!m_showRandoTracker) {
return;
}
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
if (ImGui::Begin("Rando Tracker", nullptr, windowFlags)) {
auto trackerRando = getTrackerRando();
ImGui::Text("Here's where the tracker will be");
if (ImGui::Button("Update Tracker")) {
auto trackerRando = getTrackerRando();
// Generate tracker world if it doesn't exist
auto contextHash = randomizer_GetContext().mHash;
auto trackerHash = trackerRando->GetConfig().GetHash(false);
// If no hash, or seeds switched, try to create tracker world from currently active seed
if (trackerHash.empty() || (trackerHash != contextHash && !contextHash.empty())) {
*trackerRando = randomizer::Randomizer(data::configured_data_path());
trackerRando->GenerateTrackerWorld();
auto trackerWorld = trackerRando->GetWorlds()[0].get();
auto currentItems = trackerWorld->GetStartingItemPool();
m_currentSearch = randomizer::logic::search::Search::Accessible(&trackerRando->GetWorlds(), currentItems);
m_currentSearch.SearchWorlds();
} else {
// Don't try to update inventory when on the title screen
if (!playerIsOnTitleScreen()) {
// TODO: Translate game save inventory into ItemPool that can be used for searching
randomizer::logic::item_pool::ItemPool currentItems = {};
m_currentSearch = randomizer::logic::search::Search::Accessible(&trackerRando->GetWorlds(), currentItems);
}
m_currentSearch.SearchWorlds();
}
}
if (trackerRando->GetConfig().GetHash(false).empty()) {
ImGui::Text("There is currently no tracker world");
} else {
ImGui::Text("Tracker world loaded from seed %s", trackerRando->GetConfig().GetHash().c_str());
// Show total number of available locations
auto locations = trackerRando->GetWorlds()[0]->GetAllLocations();
auto numAvailableLocations = m_currentSearch._visitedLocations.size();
ImGui::Text("Locations Available: %zu / %zu", numAvailableLocations, locations.size());
if (ImGui::BeginChild("ScrollRegion", ImVec2(500, 500), true))
{
// Show all locations. Green for accessible. Red for Unaccessible
for (auto location : locations) {
// Color red
auto color = ImVec4(1.f, 0.f, 0.f, 1.f);
// If the search found this location, change color to green
if (m_currentSearch._visitedLocations.contains(location)) {
color = ImVec4(0.f, 1.f, 0.f, 1.f);
}
ImGui::TextColored(color, "%s", location->GetName().c_str());
// Show requirements for the location below it (formatting isn't pretty right now)
ImGui::Text(" %s", location->GetComputedRequirement().to_string().c_str());
}
}
ImGui::EndChild();
}
}
ImGui::End();
}
randomizer::Randomizer* ImGuiMenuRandomizer::getTrackerRando() {
static randomizer::Randomizer trackerRando{data::configured_data_path()};
return &trackerRando;
}
} // namespace dusk
+15 -2
View File
@@ -1,7 +1,14 @@
#ifndef DUSK_IMGUI_MENU_RANDOMIZER_HPP
#define DUSK_IMGUI_MENU_RANDOMIZER_HPP
#include "dusk/randomizer/generator/logic/search.hpp"
namespace randomizer {
class Randomizer;
namespace logic::search {
class Search;
}
}
namespace dusk {
class ImGuiMenuRandomizer {
@@ -11,10 +18,16 @@ public:
void windowRandoStats();
void windowRandoGeneration();
void windowRandoTracker();
randomizer::Randomizer* getTrackerRando();
private:
bool m_showRandoStats{false};
bool m_showRandoGeneration{false};
bool m_showRandoTracker{false};
randomizer::logic::search::Search m_currentSearch = randomizer::logic::search::Search();
};
}
@@ -10,6 +10,10 @@
namespace randomizer::logic::search
{
Search::Search(): _searchMode(SearchMode::NO_SEARCH) {
}
Search::Search(const SearchMode& searchMode,
world::WorldPool* worlds,
const item_pool::ItemPool& items /* = {} */,
@@ -48,6 +48,7 @@ namespace randomizer::logic::search
{
enum class SearchMode
{
NO_SEARCH,
ACCESSIBLE_LOCATIONS,
GAME_BEATABLE,
ALL_LOCATIONS_REACHABLE,
@@ -59,6 +60,7 @@ namespace randomizer::logic::search
class Search
{
public:
Search();
Search(const SearchMode& searchMode,
world::WorldPool* worlds,
const item_pool::ItemPool& items = {},
+34 -3
View File
@@ -13,10 +13,9 @@
#include <iostream>
#include "seedgen/seed.hpp"
#include "SDL3/SDL_filesystem.h"
#include "dusk/app_info.hpp"
#include "dusk/data.hpp"
#include "dusk/logging.h"
#include "dusk/randomizer/game/randomizer_context.hpp"
namespace randomizer
{
@@ -36,6 +35,38 @@ namespace randomizer
return std::nullopt;
}
void Randomizer::GenerateTrackerWorld() {
auto contextHash = randomizer_GetContext().mHash;
if (contextHash.empty()) {
return;
}
std::filesystem::path seedSettings = dusk::data::configured_data_path() / "randomizer" / "seeds" /
contextHash / (contextHash + " Anti-Spoiler Log.txt");
this->_config.LoadFromFile(seedSettings, GetPrefPath());
this->_config.SetHash(contextHash);
std::unique_ptr<logic::world::World> world = std::make_unique<logic::world::World>(1, this);
world->SetSettings(this->_config.GetSettingsList().front());
world->Build();
this->_worlds.emplace_back(std::move(world));
auto trackerWorld = this->_worlds.at(0).get();
trackerWorld->SetNonProgressLocations();
trackerWorld->AssignAreaProperties();
trackerWorld->AssignGoalLocations();
// Cache exit form times. This *must* run before conducting the flattening search, otherwise
// the flattening search will pollute the exit timeform cache with a bunch of zeros
logic::fill::CacheExitTimeForms(this->_worlds);
// Set raw requirements for each location
FlattenSearch search = FlattenSearch(trackerWorld);
search.doSearch();
}
void Randomizer::GenerateWorlds()
{
utility::time::ScopedTimer<"Seed generation took ", std::chrono::milliseconds> timer;
@@ -19,6 +19,7 @@ namespace randomizer
*/
std::optional<std::string> Generate();
void GenerateWorlds();
void GenerateTrackerWorld();
auto& GetConfig() { return this->_config; }
auto& GetWorlds() { return this->_worlds; }
@@ -320,9 +320,9 @@ namespace randomizer::seedgen::config
WritePreferencesToFile(preferencesPath);
}
std::string Config::GetHash()
std::string Config::GetHash(bool generateIfEmpty)
{
if (this->_hash.empty())
if (this->_hash.empty() && generateIfEmpty)
{
this->_hash = seed::GenerateHash();
}
@@ -71,11 +71,13 @@ namespace randomizer::seedgen::config
// std::string getPermalink(const bool& internal = false) const;
/**
* @brief Returns the hash for the config. If the hash is an empty string, then a new one will be generated.
* @brief Returns the hash for the config.
* @param generateIfEmpty Generates a new hash if the current hash is empty
*
* @return The hash as a string
*/
std::string GetHash();
std::string GetHash(bool generateIfEmpty = true);
void SetHash(const std::string& newHash) { this->_hash = newHash; }
private:
fspath _plandomizerPath;