aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author Hop311 <hop3114@gmail.com>2023-09-15 22:55:00 +0200
committer Hop311 <hop3114@gmail.com>2023-09-15 23:22:03 +0200
commit8add7c666455a8a4edd9e02ca5a33f78a25e8f2c (patch)
tree65b1f27aecea054bc708d2ee0d6eb4ae981b3fc3 /src
parent46bbbb038e5fa21e25fa33c4fee84e4b14690885 (diff)
First go at Modifiers
Diffstat (limited to 'src')
-rw-r--r--src/openvic-simulation/Modifier.cpp115
-rw-r--r--src/openvic-simulation/Modifier.hpp95
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp28
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.hpp7
-rw-r--r--src/openvic-simulation/economy/Good.cpp2
-rw-r--r--src/openvic-simulation/map/Map.cpp3
-rw-r--r--src/openvic-simulation/map/Province.cpp2
-rw-r--r--src/openvic-simulation/pop/Culture.cpp2
-rw-r--r--src/openvic-simulation/pop/Pop.cpp2
-rw-r--r--src/openvic-simulation/pop/Religion.cpp2
-rw-r--r--src/openvic-simulation/types/Colour.hpp14
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.cpp8
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp4
13 files changed, 247 insertions, 37 deletions
diff --git a/src/openvic-simulation/Modifier.cpp b/src/openvic-simulation/Modifier.cpp
new file mode 100644
index 0000000..ed32ee2
--- /dev/null
+++ b/src/openvic-simulation/Modifier.cpp
@@ -0,0 +1,115 @@
+#include "Modifier.hpp"
+
+using namespace OpenVic;
+
+ModifierEffect::ModifierEffect(const std::string_view new_identifier, bool new_positive_good)
+ : HasIdentifier { new_identifier }, positive_good { new_positive_good } {}
+
+bool ModifierEffect::get_positive_good() const {
+ return positive_good;
+}
+
+ModifierValue::ModifierValue() = default;
+ModifierValue::ModifierValue(ModifierValue const&) = default;
+ModifierValue::ModifierValue(ModifierValue&&) = default;
+
+void ModifierValue::trim() {
+ std::erase_if(values, [](effect_map_t::value_type const& value) -> bool {
+ return value.second == fixed_point_t::_0();
+ });
+}
+
+size_t ModifierValue::get_effect_count() const {
+ return values.size();
+}
+
+fixed_point_t ModifierValue::get_effect(ModifierEffect const* effect, bool* successful) {
+ const effect_map_t::const_iterator it = values.find(effect);
+ if (it != values.end()) {
+ if (successful != nullptr) *successful = true;
+ return it->second;
+ }
+ if (successful != nullptr) *successful = false;
+ return fixed_point_t::_0();
+}
+
+bool ModifierValue::has_effect(ModifierEffect const* effect) const {
+ return values.find(effect) != values.end();
+}
+
+ModifierValue& ModifierValue::operator+=(ModifierValue const& right) {
+ for (effect_map_t::value_type const& value : right.values) {
+ values[value.first] += value.second;
+ }
+ return *this;
+}
+
+ModifierValue ModifierValue::operator+(ModifierValue const& right) const {
+ ModifierValue ret = *this;
+ return ret += right;
+}
+
+ModifierValue ModifierValue::operator-() const {
+ ModifierValue ret = *this;
+ for (effect_map_t::value_type& value : ret.values) {
+ value.second = -value.second;
+ }
+ return ret;
+}
+
+ModifierValue& ModifierValue::operator-=(ModifierValue const& right) {
+ for (effect_map_t::value_type const& value : right.values) {
+ values[value.first] -= value.second;
+ }
+ return *this;
+}
+
+ModifierValue ModifierValue::operator-(ModifierValue const& right) const {
+ ModifierValue ret = *this;
+ return ret -= right;
+}
+
+std::ostream& OpenVic::operator<<(std::ostream& stream, ModifierValue const& value) {
+ for (ModifierValue::effect_map_t::value_type const& effect : value.values) {
+ stream << effect.first << ": " << effect.second << "\n";
+ }
+ return stream;
+}
+
+Modifier::Modifier(const std::string_view new_identifier, ModifierValue&& new_values, icon_t new_icon)
+ : HasIdentifier { new_identifier }, ModifierValue { std::move(new_values) }, icon { new_icon } {}
+
+Modifier::icon_t Modifier::get_icon() const {
+ return icon;
+}
+
+Modifier const& ModifierInstance::get_modifier() const {
+ return modifier;
+}
+
+Date const& ModifierInstance::get_expiry_date() const {
+ return expiry_date;
+}
+
+ModifierManager::ModifierManager()
+ : modifier_effects { "modifier effects"}, modifiers { "modifiers" } {}
+
+bool ModifierManager::add_modifier_effect(const std::string_view identifier, bool positive_good) {
+ if (identifier.empty()) {
+ Logger::error("Invalid modifier effect identifier - empty!");
+ return false;
+ }
+ return modifier_effects.add_item({ identifier, positive_good });
+}
+
+bool ModifierManager::add_modifier(const std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon) {
+ if (identifier.empty()) {
+ Logger::error("Invalid modifier effect identifier - empty!");
+ return false;
+ }
+ if (icon <= 0) {
+ Logger::error("Invalid modifier icon for ", identifier, ": ", icon);
+ return false;
+ }
+ return modifiers.add_item({ identifier, std::move(values), icon });
+}
diff --git a/src/openvic-simulation/Modifier.hpp b/src/openvic-simulation/Modifier.hpp
new file mode 100644
index 0000000..e8c4c8b
--- /dev/null
+++ b/src/openvic-simulation/Modifier.hpp
@@ -0,0 +1,95 @@
+#pragma once
+
+#include "openvic-simulation/types/IdentifierRegistry.hpp"
+
+namespace OpenVic {
+ struct ModifierManager;
+
+ struct ModifierEffect : HasIdentifier {
+ friend struct ModifierManager;
+
+ private:
+ /* If true, positive values will be green and negative values will be red.
+ * If false, the colours will be switced.
+ */
+ const bool positive_good;
+
+ // TODO - format/precision, e.g. 80% vs 0.8 vs 0.800, 2 vs 2.0 vs 200%
+
+ ModifierEffect(const std::string_view new_identifier, bool new_positive_good);
+
+ public:
+ ModifierEffect(ModifierEffect&&) = default;
+
+ bool get_positive_good() const;
+ };
+
+ struct ModifierValue {
+ using effect_map_t = std::map<ModifierEffect const*, fixed_point_t>;
+ private:
+ effect_map_t values;
+
+ public:
+ ModifierValue();
+ ModifierValue(ModifierValue const&);
+ ModifierValue(ModifierValue&&);
+
+ /* Removes effect entries with a value of zero. */
+ void trim();
+ size_t get_effect_count() const;
+
+ fixed_point_t get_effect(ModifierEffect const* effect, bool* successful = nullptr);
+ bool has_effect(ModifierEffect const* effect) const;
+
+ ModifierValue& operator+=(ModifierValue const& right);
+ ModifierValue operator+(ModifierValue const& right) const;
+ ModifierValue operator-() const;
+ ModifierValue& operator-=(ModifierValue const& right);
+ ModifierValue operator-(ModifierValue const& right) const;
+
+ friend std::ostream& operator<<(std::ostream& stream, ModifierValue const& value);
+ };
+
+ struct Modifier : HasIdentifier, ModifierValue {
+ friend struct ModifierManager;
+
+ using icon_t = uint8_t;
+
+ private:
+ const icon_t icon;
+
+ Modifier(const std::string_view new_identifier, ModifierValue&& new_values, icon_t new_icon);
+
+ public:
+ Modifier(Modifier&&) = default;
+
+ icon_t get_icon() const;
+ };
+
+ struct ModifierInstance {
+
+ private:
+ Modifier const& modifier;
+ Date expiry_date;
+
+ public:
+ Modifier const& get_modifier() const;
+ Date const& get_expiry_date() const;
+ };
+
+ struct ModifierManager {
+
+ private:
+ IdentifierRegistry<ModifierEffect> modifier_effects;
+ IdentifierRegistry<Modifier> modifiers;
+
+ public:
+ ModifierManager();
+
+ bool add_modifier_effect(const std::string_view identifier, bool province_good);
+ IDENTIFIER_REGISTRY_ACCESSORS(ModifierEffect, modifier_effect)
+
+ bool add_modifier(const std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon);
+ IDENTIFIER_REGISTRY_ACCESSORS(Modifier, modifier)
+ };
+}
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index c409e1d..e85f499 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -49,9 +49,6 @@ fs::path Dataloader::lookup_file(fs::path const& path) const {
return {};
}
-const fs::path Dataloader::TXT = ".txt";
-const fs::path Dataloader::CSV = ".csv";
-
static bool contains_file_with_name(Dataloader::path_vector_t const& paths, fs::path const& name) {
for (fs::path const& path : paths) {
@@ -60,8 +57,7 @@ static bool contains_file_with_name(Dataloader::path_vector_t const& paths, fs::
return false;
}
-Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path, fs::path const* extension) const {
-
+Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path, fs::path const& extension) const {
path_vector_t ret;
for (fs::path const& root : roots) {
const fs::path composed = root / path;
@@ -69,7 +65,7 @@ Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path,
for (fs::directory_entry const& entry : fs::directory_iterator { composed, ec }) {
if (entry.is_regular_file()) {
const fs::path file = entry;
- if (extension == nullptr || file.extension() == *extension) {
+ if (extension.empty() || file.extension() == extension) {
if (!contains_file_with_name(ret, file.filename())) {
ret.push_back(file);
}
@@ -80,7 +76,7 @@ Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path,
return ret;
}
-bool Dataloader::apply_to_files_in_dir(fs::path const& path, std::function<bool(fs::path const&)> callback, fs::path const* extension) const {
+bool Dataloader::apply_to_files_in_dir(fs::path const& path, fs::path const& extension, std::function<bool(fs::path const&)> callback) const {
bool ret = true;
for (fs::path const& file : lookup_files_in_dir(path, extension)) {
@@ -108,7 +104,7 @@ static Parser _run_ovdl_parser(fs::path const& path) {
parser.set_error_log_to(error_log_stream);
parser.load_from_file(path);
if (!buffer.empty()) {
- Logger::error("Parser load errors:\n\n", buffer, "\n");
+ Logger::error("Parser load errors for ", path, ":\n\n", buffer, "\n");
buffer.clear();
}
if (parser.has_fatal_error() || parser.has_error()) {
@@ -116,10 +112,10 @@ static Parser _run_ovdl_parser(fs::path const& path) {
return parser;
}
if (!parse_func(parser)) {
- Logger::error("Parse function returned false!");
+ Logger::error("Parse function returned false for ", path, "!");
}
if (!buffer.empty()) {
- Logger::error("Parser parse errors:\n\n", buffer, "\n");
+ Logger::error("Parser parse errors for ", path, ":\n\n", buffer, "\n");
buffer.clear();
}
if (parser.has_fatal_error() || parser.has_error()) {
@@ -145,7 +141,7 @@ static csv::Windows1252Parser _parse_csv(fs::path const& path) {
}
bool Dataloader::_load_pop_types(PopManager& pop_manager, fs::path const& pop_type_directory) const {
- const bool ret = apply_to_files_in_dir(pop_type_directory,
+ const bool ret = apply_to_files_in_dir(pop_type_directory, ".txt",
[&pop_manager](fs::path const& file) -> bool {
return pop_manager.load_pop_type_file(file.stem().string(), _parse_defines(file).get_file_node());
}
@@ -283,7 +279,7 @@ bool Dataloader::load_defines(GameManager& game_manager) const {
}
bool Dataloader::load_pop_history(GameManager& game_manager, fs::path const& path) const {
- return apply_to_files_in_dir(path,
+ return apply_to_files_in_dir(path, ".txt",
[&game_manager](fs::path const& file) -> bool {
return expect_dictionary(
[&game_manager](std::string_view province_key, ast::NodeCPtr province_node) -> bool {
@@ -317,7 +313,9 @@ static bool _load_localisation_file(Dataloader::localisation_callback_t callback
}
bool Dataloader::load_localisation_files(localisation_callback_t callback, fs::path const& localisation_dir) {
- return apply_to_files_in_dir(localisation_dir, [callback](fs::path path) -> bool {
- return _load_localisation_file(callback, _parse_csv(path).get_lines());
- }, &CSV);
+ return apply_to_files_in_dir(localisation_dir, ".csv",
+ [callback](fs::path path) -> bool {
+ return _load_localisation_file(callback, _parse_csv(path).get_lines());
+ }
+ );
}
diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp
index d93ca39..2b358b6 100644
--- a/src/openvic-simulation/dataloader/Dataloader.hpp
+++ b/src/openvic-simulation/dataloader/Dataloader.hpp
@@ -31,10 +31,9 @@ namespace OpenVic {
* DAT-24
*/
fs::path lookup_file(fs::path const& path) const;
- static const fs::path TXT, CSV;
- path_vector_t lookup_files_in_dir(fs::path const& path, fs::path const* extension = &TXT) const;
- bool apply_to_files_in_dir(fs::path const& path, std::function<bool(fs::path const&)> callback,
- fs::path const* extension = &TXT) const;
+ path_vector_t lookup_files_in_dir(fs::path const& path, fs::path const& extension) const;
+ bool apply_to_files_in_dir(fs::path const& path, fs::path const& extension,
+ std::function<bool(fs::path const&)> callback) const;
bool load_defines(GameManager& game_manager) const;
bool load_pop_history(GameManager& game_manager, fs::path const& path) const;
diff --git a/src/openvic-simulation/economy/Good.cpp b/src/openvic-simulation/economy/Good.cpp
index e3dbd3e..6edf631 100644
--- a/src/openvic-simulation/economy/Good.cpp
+++ b/src/openvic-simulation/economy/Good.cpp
@@ -9,7 +9,7 @@ GoodCategory::GoodCategory(const std::string_view new_identifier) : HasIdentifie
Good::Good(const std::string_view new_identifier, colour_t new_colour, GoodCategory const& new_category, price_t new_base_price,
bool new_available_from_start, bool new_tradeable, bool new_money, bool new_overseas_penalty)
- : HasIdentifierAndColour { new_identifier, new_colour, true },
+ : HasIdentifierAndColour { new_identifier, new_colour, true, false },
category { new_category },
base_price { new_base_price },
available_from_start { new_available_from_start },
diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp
index fa11f86..e8178e9 100644
--- a/src/openvic-simulation/map/Map.cpp
+++ b/src/openvic-simulation/map/Map.cpp
@@ -512,9 +512,6 @@ bool Map::load_province_definitions(std::vector<LineObject> const& lines) {
return ret;
}
-/* TODO - add support for non-state province groupings used by some mods
- * (currently they trigger "province already in other region" errors).
- */
bool Map::load_region_file(ast::NodeCPtr root) {
const bool ret = expect_dictionary_reserve_length(
regions,
diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp
index b4a80b5..49a9bfc 100644
--- a/src/openvic-simulation/map/Province.cpp
+++ b/src/openvic-simulation/map/Province.cpp
@@ -8,7 +8,7 @@ using namespace OpenVic;
using namespace OpenVic::NodeTools;
Province::Province(const std::string_view new_identifier, colour_t new_colour, index_t new_index)
- : HasIdentifierAndColour { new_identifier, new_colour, false },
+ : HasIdentifierAndColour { new_identifier, new_colour, false, false },
index { new_index },
buildings { "buildings", false } {
assert(index != NULL_INDEX);
diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp
index 709f305..bf14df9 100644
--- a/src/openvic-simulation/pop/Culture.cpp
+++ b/src/openvic-simulation/pop/Culture.cpp
@@ -27,7 +27,7 @@ bool CultureGroup::get_is_overseas() const {
Culture::Culture(const std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group,
std::vector<std::string> const& new_first_names, std::vector<std::string> const& new_last_names)
- : HasIdentifierAndColour { new_identifier, new_colour, true },
+ : HasIdentifierAndColour { new_identifier, new_colour, true, false },
group { new_group },
first_names { new_first_names },
last_names { new_last_names } {}
diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp
index f8e7254..1c11b80 100644
--- a/src/openvic-simulation/pop/Pop.cpp
+++ b/src/openvic-simulation/pop/Pop.cpp
@@ -53,7 +53,7 @@ PopType::PopType(const std::string_view new_identifier, colour_t new_colour,
strata_t new_strata, sprite_t new_sprite,
Pop::pop_size_t new_max_size, Pop::pop_size_t new_merge_max_size,
bool new_state_capital_only, bool new_demote_migrant, bool new_is_artisan, bool new_is_slave)
- : HasIdentifierAndColour { new_identifier, new_colour, true },
+ : HasIdentifierAndColour { new_identifier, new_colour, true, false },
strata { new_strata },
sprite { new_sprite },
max_size { new_max_size },
diff --git a/src/openvic-simulation/pop/Religion.cpp b/src/openvic-simulation/pop/Religion.cpp
index 0652eb2..ec919fe 100644
--- a/src/openvic-simulation/pop/Religion.cpp
+++ b/src/openvic-simulation/pop/Religion.cpp
@@ -9,7 +9,7 @@ ReligionGroup::ReligionGroup(const std::string_view new_identifier) : HasIdentif
Religion::Religion(const std::string_view new_identifier, colour_t new_colour,
ReligionGroup const& new_group, icon_t new_icon, bool new_pagan)
- : HasIdentifierAndColour { new_identifier, new_colour, true },
+ : HasIdentifierAndColour { new_identifier, new_colour, true, false },
group { new_group },
icon { new_icon },
pagan { new_pagan } {
diff --git a/src/openvic-simulation/types/Colour.hpp b/src/openvic-simulation/types/Colour.hpp
index 01f3852..15c574f 100644
--- a/src/openvic-simulation/types/Colour.hpp
+++ b/src/openvic-simulation/types/Colour.hpp
@@ -7,30 +7,36 @@
#include <string>
namespace OpenVic {
- // Represents a 24-bit RGB integer OR a 32-bit ARGB integer
+ /* Colour represented by an unsigned integer, either 24-bit RGB or 32-bit ARGB. */
using colour_t = uint32_t;
+
/* When colour_t is used as an identifier, NULL_COLOUR is disallowed
* and should be reserved as an error value.
* When colour_t is used in a purely graphical context, NULL_COLOUR
* should be allowed.
*/
- static constexpr colour_t NULL_COLOUR = 0, FULL_COLOUR = 0xFF, MAX_COLOUR_RGB = 0xFFFFFF;
+ static constexpr colour_t NULL_COLOUR = 0, FULL_COLOUR = 0xFF,
+ MAX_COLOUR_RGB = 0xFFFFFF, MAX_COLOUR_ARGB = 0xFFFFFFFF;
+
constexpr colour_t float_to_colour_byte(float f, float min = 0.0f, float max = 1.0f) {
return static_cast<colour_t>(std::clamp(min + f * (max - min), min, max) * 255.0f);
}
+
constexpr colour_t fraction_to_colour_byte(int n, int d, float min = 0.0f, float max = 1.0f) {
return float_to_colour_byte(static_cast<float>(n) / static_cast<float>(d), min, max);
}
+
constexpr colour_t float_to_alpha_value(float a) {
return float_to_colour_byte(a) << 24;
}
+
constexpr float colour_byte_to_float(colour_t colour) {
return std::clamp(static_cast<float>(colour) / 255.0f, 0.0f, 1.0f);
}
- inline std::string colour_to_hex_string(colour_t colour) {
+ inline std::string colour_to_hex_string(colour_t colour, bool alpha = false) {
std::ostringstream stream;
- stream << std::hex << std::setfill('0') << std::setw(6) << colour;
+ stream << std::uppercase << std::hex << std::setfill('0') << std::setw(!alpha ? 6 : 8) << colour;
return stream.str();
}
}
diff --git a/src/openvic-simulation/types/IdentifierRegistry.cpp b/src/openvic-simulation/types/IdentifierRegistry.cpp
index e33bc29..f284164 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.cpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.cpp
@@ -21,8 +21,8 @@ std::ostream& OpenVic::operator<<(std::ostream& stream, HasIdentifier const* obj
return obj != nullptr ? stream << *obj : stream << "<NULL>";
}
-HasColour::HasColour(colour_t const new_colour, bool can_be_null) : colour(new_colour) {
- assert((can_be_null || colour != NULL_COLOUR) && colour <= MAX_COLOUR_RGB);
+HasColour::HasColour(colour_t const new_colour, bool can_be_null, bool can_have_alpha) : colour(new_colour) {
+ assert((can_be_null || colour != NULL_COLOUR) && colour <= (!can_have_alpha ? MAX_COLOUR_RGB : MAX_COLOUR_ARGB));
}
colour_t HasColour::get_colour() const { return colour; }
@@ -32,9 +32,9 @@ std::string HasColour::colour_to_hex_string() const {
}
HasIdentifierAndColour::HasIdentifierAndColour(const std::string_view new_identifier,
- const colour_t new_colour, bool can_be_null)
+ const colour_t new_colour, bool can_be_null, bool can_have_alpha)
: HasIdentifier { new_identifier },
- HasColour { new_colour, can_be_null } {}
+ HasColour { new_colour, can_be_null, can_have_alpha } {}
distribution_t::value_type OpenVic::get_largest_item(distribution_t const& dist) {
const distribution_t::const_iterator result = std::max_element(dist.begin(), dist.end(),
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index 20eebb9..3f73a2c 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -37,7 +37,7 @@ namespace OpenVic {
const colour_t colour;
protected:
- HasColour(const colour_t new_colour, bool can_be_null);
+ HasColour(const colour_t new_colour, bool can_be_null, bool can_have_alpha);
public:
HasColour(HasColour const&) = delete;
@@ -55,7 +55,7 @@ namespace OpenVic {
*/
class HasIdentifierAndColour : public HasIdentifier, public HasColour {
protected:
- HasIdentifierAndColour(const std::string_view new_identifier, const colour_t new_colour, bool can_be_null);
+ HasIdentifierAndColour(const std::string_view new_identifier, const colour_t new_colour, bool can_be_null, bool can_have_alpha);
public:
HasIdentifierAndColour(HasIdentifierAndColour const&) = delete;