aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author BrickPi <49528459+BrickPi@users.noreply.github.com>2023-10-04 20:33:23 +0200
committer hop311 <hop3114@gmail.com>2023-12-10 14:57:14 +0100
commitf981159689aaff401a1bb9461fcb37b598730ab5 (patch)
treec6104733641ff03f650fe2b5ecd9f84925e6c719 /src
parentabb0804b015d8444542af7a6c5db728c0fde4cfb (diff)
Generic Event Loading
Diffstat (limited to 'src')
-rw-r--r--src/openvic-simulation/GameManager.hpp2
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp18
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.hpp4
-rw-r--r--src/openvic-simulation/misc/Event.cpp136
-rw-r--r--src/openvic-simulation/misc/Event.hpp84
5 files changed, 242 insertions, 2 deletions
diff --git a/src/openvic-simulation/GameManager.hpp b/src/openvic-simulation/GameManager.hpp
index e9a9284..9832842 100644
--- a/src/openvic-simulation/GameManager.hpp
+++ b/src/openvic-simulation/GameManager.hpp
@@ -14,6 +14,7 @@
#include "openvic-simulation/pop/Pop.hpp"
#include "openvic-simulation/research/ResearchManager.hpp"
#include "openvic-simulation/research/Technology.hpp"
+#include "openvic-simulation/misc/Event.hpp"
namespace OpenVic {
struct GameManager {
@@ -31,6 +32,7 @@ namespace OpenVic {
PopManager PROPERTY_REF(pop_manager);
CountryManager PROPERTY_REF(country_manager);
CrimeManager PROPERTY_REF(crime_manager);
+ EventManager PROPERTY_REF(event_manager);
UIManager PROPERTY_REF(ui_manager);
GameAdvancementHook PROPERTY_REF(clock);
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index c986a78..8c6704b 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -505,6 +505,20 @@ bool Dataloader::_load_history(GameManager& game_manager, bool unused_history_fi
return ret;
}
+bool Dataloader::_load_events(GameManager& game_manager) const {
+ static constexpr std::string_view events_directory = "events";
+ const bool ret = apply_to_files(
+ lookup_files_in_dir(events_directory, ".txt"),
+ [&game_manager](fs::path const& file) -> bool {
+ return game_manager.get_event_manager().load_event_file(
+ game_manager.get_politics_manager().get_issue_manager(), parse_defines(file).get_file_node()
+ );
+ }
+ );
+ game_manager.get_event_manager().lock_events();
+ return ret;
+}
+
bool Dataloader::_load_map_dir(GameManager& game_manager) const {
static constexpr std::string_view map_directory = "map/";
Map& map = game_manager.get_map();
@@ -795,6 +809,10 @@ bool Dataloader::load_defines(GameManager& game_manager) const {
Logger::error("Failed to load history!");
ret = false;
}
+ if (!_load_events(game_manager)) {
+ Logger::error("Failed to load events!");
+ ret = false;
+ }
return ret;
}
diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp
index e98d220..884588a 100644
--- a/src/openvic-simulation/dataloader/Dataloader.hpp
+++ b/src/openvic-simulation/dataloader/Dataloader.hpp
@@ -13,9 +13,8 @@ namespace OpenVic {
class UIManager;
struct PopManager;
struct UnitManager;
- struct ModifierManager;
- struct TechnologyManager;
struct GoodManager;
+ struct EventManager;
class Dataloader {
public:
@@ -31,6 +30,7 @@ namespace OpenVic {
bool _load_rebel_types(GameManager& game_manager) const;
bool _load_technologies(GameManager& game_manager) const;
bool _load_inventions(GameManager& game_manager) const;
+ bool _load_events(GameManager& game_manager) const;
bool _load_map_dir(GameManager& game_manager) const;
bool _load_history(GameManager& game_manager, bool unused_history_file_warnings) const;
diff --git a/src/openvic-simulation/misc/Event.cpp b/src/openvic-simulation/misc/Event.cpp
new file mode 100644
index 0000000..029336c
--- /dev/null
+++ b/src/openvic-simulation/misc/Event.cpp
@@ -0,0 +1,136 @@
+#include "Event.hpp"
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/politics/Issue.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+Event::EventOption::EventOption(std::string_view new_title) : title { new_title } {}
+
+Event::Event(
+ std::string_view new_identifier, std::string_view new_title, std::string_view new_description,
+ std::string_view new_image, event_type_t new_type, bool new_triggered_only, bool new_major, bool new_fire_only_once,
+ bool new_allows_multiple_instances, bool new_news, std::string_view new_news_title, std::string_view new_news_desc_long,
+ std::string_view new_news_desc_medium, std::string_view new_news_desc_short, bool new_election,
+ IssueGroup const* new_election_issue_group, std::vector<EventOption>&& new_options
+) : HasIdentifier { new_identifier }, title { new_title }, description { new_description }, image { new_image },
+ type { new_type }, triggered_only { new_triggered_only }, major { new_major }, fire_only_once { new_fire_only_once },
+ allows_multiple_instances { new_allows_multiple_instances }, news { new_news }, news_title { new_news_title },
+ news_desc_long { new_news_desc_long }, news_desc_medium { new_news_desc_medium }, news_desc_short { new_news_desc_short },
+ election { new_election }, election_issue_group { new_election_issue_group }, options { std::move(new_options) } {}
+
+EventManager::EventManager() : events { "events" } {}
+
+bool EventManager::register_event(
+ std::string_view identifier, std::string_view title, std::string_view description, std::string_view image,
+ Event::event_type_t type, bool triggered_only, bool major, bool fire_only_once, bool allows_multiple_instances, bool news,
+ std::string_view news_title, std::string_view news_desc_long, std::string_view news_desc_medium,
+ std::string_view news_desc_short, bool election, IssueGroup const* election_issue_group,
+ std::vector<Event::EventOption>&& options
+) {
+ if (identifier.empty()) {
+ Logger::error("Invalid event ID - empty!");
+ return false;
+ }
+ if (title.empty()) {
+ Logger::warning("Event with ID ", identifier, " has no title!");
+ }
+ if (description.empty()) {
+ Logger::warning("Event with ID ", identifier, " has no description!");
+ }
+ if (options.empty()) {
+ Logger::error("No options specified for event with ID ", identifier);
+ return false;
+ }
+ if (election && election_issue_group == nullptr) {
+ Logger::warning("Event with ID ", identifier, " is an election event but has no issue group!");
+ } else if (!election && election_issue_group != nullptr) {
+ Logger::warning(
+ "Event with ID ", identifier, " is not an election event but has issue group ",
+ election_issue_group->get_identifier(), "!"
+ );
+ }
+ if (news) {
+ if (news_desc_long.empty() || news_desc_medium.empty() || news_desc_short.empty()) {
+ Logger::warning(
+ "Event with ID ", identifier, " is a news event but doesn't have long, medium and short descriptions!"
+ );
+ }
+ } else {
+ if (!news_title.empty() || !news_desc_long.empty() || !news_desc_medium.empty() || !news_desc_short.empty()) {
+ Logger::warning("Event with ID ", identifier, " is not a news event but has news strings specified!");
+ }
+ }
+
+ // TODO - error if is_triggered_only with triggers or MTTH defined
+
+ return events.add_item({
+ identifier, title, description, image, type, triggered_only, major, fire_only_once, allows_multiple_instances, news,
+ news_title, news_desc_long, news_desc_medium, news_desc_short, election, election_issue_group, std::move(options)
+ }, duplicate_warning_callback);
+}
+
+bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeCPtr root) {
+ return expect_dictionary(
+ [this, &issue_manager](std::string_view key, ast::NodeCPtr value) -> bool {
+ Event::event_type_t type;
+ std::string_view identifier, title, description, image, news_title, news_desc_long, news_desc_medium,
+ news_desc_short;
+ bool triggered_only = false, major = false, fire_only_once = false, allows_multiple_instances = false,
+ news = false, election = false;
+ IssueGroup const* election_issue_group = nullptr;
+ std::vector<Event::EventOption> options;
+
+ if (key == "country_event") {
+ type = Event::event_type_t::COUNTRY;
+ } else if (key == "province_event") {
+ type = Event::event_type_t::PROVINCE;
+ } else {
+ Logger::error("Invalid event type: ", key);
+ return false;
+ }
+
+ bool ret = expect_dictionary_keys(
+ "id", ONE_EXACTLY, expect_identifier(assign_variable_callback(identifier)),
+ "title", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(title)),
+ "desc", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(description)),
+ "picture", ZERO_OR_ONE, expect_identifier_or_string(assign_variable_callback(image), true),
+ "is_triggered_only", ZERO_OR_ONE, expect_bool(assign_variable_callback(triggered_only)),
+ "major", ZERO_OR_ONE, expect_bool(assign_variable_callback(major)),
+ "fire_only_once", ZERO_OR_ONE, expect_bool(assign_variable_callback(fire_only_once)),
+ "allow_multiple_instances", ZERO_OR_ONE, expect_bool(assign_variable_callback(allows_multiple_instances)),
+ "news", ZERO_OR_ONE, expect_bool(assign_variable_callback(news)),
+ "news_title", ZERO_OR_ONE, expect_identifier_or_string(assign_variable_callback(news_title)),
+ "news_desc_long", ZERO_OR_ONE, expect_identifier_or_string(assign_variable_callback(news_desc_long)),
+ "news_desc_medium", ZERO_OR_ONE, expect_identifier_or_string(assign_variable_callback(news_desc_medium)),
+ "news_desc_short", ZERO_OR_ONE, expect_identifier_or_string(assign_variable_callback(news_desc_short)),
+ "election", ZERO_OR_ONE, expect_bool(assign_variable_callback(election)),
+ "issue_group", ZERO_OR_ONE,
+ issue_manager.expect_issue_group_identifier(assign_variable_callback_pointer(election_issue_group)),
+ "option", ONE_OR_MORE, [&options](ast::NodeCPtr node) -> bool {
+ std::string_view title;
+
+ bool ret = expect_dictionary_keys_and_default(
+ key_value_success_callback,
+ "name", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(title))
+ )(node);
+
+ // TODO: option effects
+
+ options.push_back({ title });
+ return ret;
+ },
+ "trigger", ZERO_OR_ONE, success_callback, // TODO - trigger condition
+ "mean_time_to_happen", ZERO_OR_ONE, success_callback, // TODO - MTTH weighted conditions
+ "immediate", ZERO_OR_MORE, success_callback // TODO - immediate effects
+ )(value);
+ ret &= register_event(
+ identifier, title, description, image, type, triggered_only, major, fire_only_once, allows_multiple_instances,
+ news, news_title, news_desc_long, news_desc_medium, news_desc_short, election, election_issue_group,
+ std::move(options)
+ );
+ return ret;
+ }
+ )(root);
+}
diff --git a/src/openvic-simulation/misc/Event.hpp b/src/openvic-simulation/misc/Event.hpp
new file mode 100644
index 0000000..6d0829e
--- /dev/null
+++ b/src/openvic-simulation/misc/Event.hpp
@@ -0,0 +1,84 @@
+#pragma once
+
+#include "openvic-simulation/types/IdentifierRegistry.hpp"
+
+namespace OpenVic {
+ struct EventManager;
+ struct IssueGroup;
+ struct IssueManager;
+
+ struct Event : HasIdentifier {
+ friend struct EventManager;
+
+ enum struct event_type_t : uint8_t { COUNTRY, PROVINCE };
+
+ struct EventOption {
+ friend struct EventManager;
+
+ private:
+ std::string PROPERTY(title);
+ // TODO: option effects
+
+ EventOption(std::string_view new_title);
+
+ public:
+ EventOption(EventOption const&) = delete;
+ EventOption(EventOption&&) = default;
+ EventOption& operator=(EventOption const&) = delete;
+ EventOption& operator=(EventOption&&) = delete;
+ };
+
+ private:
+ std::string PROPERTY(title);
+ std::string PROPERTY(description);
+ std::string PROPERTY(image);
+ event_type_t PROPERTY(type);
+ bool PROPERTY_CUSTOM_PREFIX(triggered_only, is);
+ bool PROPERTY_CUSTOM_PREFIX(major, is);
+ bool PROPERTY(fire_only_once);
+ bool PROPERTY(allows_multiple_instances);
+
+ bool PROPERTY_CUSTOM_PREFIX(news, is);
+ std::string PROPERTY(news_title);
+ std::string PROPERTY(news_desc_long);
+ std::string PROPERTY(news_desc_medium);
+ std::string PROPERTY(news_desc_short);
+
+ bool PROPERTY_CUSTOM_PREFIX(election, is);
+ IssueGroup const* PROPERTY(election_issue_group);
+
+ std::vector<EventOption> PROPERTY(options);
+
+ // TODO: triggers, MTTH, immediate effects
+
+ Event(
+ std::string_view new_identifier, std::string_view new_title, std::string_view new_description,
+ std::string_view new_image, event_type_t new_type, bool new_triggered_only, bool new_major,
+ bool new_fire_only_once, bool new_allows_multiple_instances, bool new_news, std::string_view new_news_title,
+ std::string_view new_news_desc_long, std::string_view new_news_desc_medium, std::string_view new_news_desc_short,
+ bool new_election, IssueGroup const* new_election_issue_group, std::vector<EventOption>&& new_options
+ );
+
+ public:
+ Event(Event&&) = default;
+ };
+
+ struct EventManager {
+ private:
+ IdentifierRegistry<Event> events;
+
+ public:
+ EventManager();
+
+ bool register_event(
+ std::string_view identifier, std::string_view title, std::string_view description, std::string_view image,
+ Event::event_type_t type, bool triggered_only, bool major, bool fire_only_once, bool allows_multiple_instances,
+ bool news, std::string_view news_title, std::string_view news_desc_long, std::string_view news_desc_medium,
+ std::string_view news_desc_short, bool election, IssueGroup const* election_issue_group,
+ std::vector<Event::EventOption>&& options
+ );
+ IDENTIFIER_REGISTRY_ACCESSORS(event);
+
+ bool load_event_file(IssueManager const& issue_manager, ast::NodeCPtr root);
+ };
+} // namespace OpenVic