#pragma once #include "Localization.h" #include #include #include #include #include namespace FRG { // One location of a campaign, loaded from resources/config/locations/.json. // Optional paths may be left empty; Location::setup skips them. struct LocationConfig { std::string id; std::string gameObjectsJsonPath; std::string interactiveObjectsJsonPath; std::string npcsJsonPath; std::string dialoguesJsonPath; std::vector navigationJsonPaths; std::string scriptPath; std::string teleportsJsonPath; std::string triggerZonesJsonPath; std::string lightsJsonPath; Eigen::Vector3f playerPosition = Eigen::Vector3f::Zero(); // Where the taxi drives in when the player calls it. No taxi when absent. struct Taxi { Eigen::Vector3f triggerPosition = Eigen::Vector3f::Zero(); std::vector waypoints; Eigen::Vector3f initialPosition = Eigen::Vector3f::Zero(); float initialRotation = 0.f; float waypointReachRadius = 5.f; }; std::optional taxi; // Interactive objects stay locked until the tutorial reaches "pick up an item". bool lockInteractiveObjectsDuringTutorial = false; // Returns false (and logs) when the file can't be read or parsed. static bool fromFile(const std::string& path, const std::string& zipFile, LocationConfig& out); }; // A playable campaign: its own set of locations, quests and starting state. struct CampaignConfig { std::string id; std::map titles; // language code -> title std::vector locationConfigPaths; std::string startLocation; std::string startMusic; std::string startStatePath; std::string questsPath; bool tutorial = false; // UI layout shown while the campaign loads (preloaded with the rest of the UI). std::string loadingScreenPath = kDefaultLoadingScreen; static constexpr const char* kDefaultLoadingScreen = "resources/w/ui/screen_loading.json"; std::string title(Language lang) const; }; // Campaigns listed in resources/config/campaigns.json, in display order. class CampaignRegistry { public: static constexpr const char* kDefaultCampaignId = "main"; static CampaignRegistry& instance(); void loadFromJson(const std::string& jsonPath, const std::string& zipFile = ""); const std::vector& all() const { return campaigns_; } // Returns nullptr if not found. const CampaignConfig* find(const std::string& id) const; private: CampaignRegistry() = default; std::vector campaigns_; }; } // namespace FRG