├── qml.qrc ├── .gitignore ├── game ├── tick_period.h └── game_speed.h ├── util ├── image_util.h ├── number_util.cpp ├── set_util.h ├── vector_random_util.h ├── point_util.cpp ├── point_container.cpp ├── exception_util.h ├── point_container.h ├── geocoordinate_util.cpp ├── empty_image_provider.h ├── random.cpp ├── qunique_ptr.h ├── polygon_util.h ├── polygon_util.cpp ├── image_util.cpp ├── type_traits.h ├── singleton.h ├── map_util.h ├── filesystem_util.h ├── random.h ├── vector_util.h ├── rect_util.h ├── container_util.h ├── translator.h └── parse_util.h ├── technology ├── technology_compare.h ├── technology_set.h ├── technology_area_compare.h ├── technology_map.h ├── technology_area_compare.cpp ├── technology_compare.cpp ├── technology_category.h ├── technology_area.h └── technology_area.cpp ├── landed_title └── landed_title_tier.h ├── script ├── event │ ├── event.h │ ├── event_instance.cpp │ ├── event_trigger.cpp │ ├── event_option.h │ ├── scoped_event_base.h │ ├── character_event.h │ ├── event_instance.h │ ├── event_trigger.h │ └── event_option.cpp ├── decision │ ├── decision.cpp │ ├── decision.h │ ├── filter │ │ ├── decision_filter.cpp │ │ └── decision_filter.h │ ├── scoped_decision.h │ ├── holding_decision.h │ └── holding_decision.cpp ├── flag │ └── scoped_flag.h ├── effect │ ├── location_effect.h │ ├── source_effect.h │ ├── effect_list.h │ ├── holding_type_effect.h │ ├── flags_effect.h │ ├── items_effect.h │ ├── scripted_effect_effect.h │ ├── traits_effect.h │ ├── tooltip_effect.h │ ├── event_effect.h │ ├── wealth_effect.h │ ├── for_effect.h │ ├── if_effect.h │ ├── scripted_effect.h │ └── effect_list.cpp ├── context.h ├── modifier_effect │ ├── modifier_effect.h │ ├── prowess_modifier_effect.h │ ├── levy_modifier_effect.h │ ├── troop_attack_modifier_effect.h │ ├── troop_defense_modifier_effect.h │ ├── population_growth_modifier_effect.h │ ├── population_capacity_modifier_effect.h │ └── population_capacity_modifier_modifier_effect.h ├── province_modifier.h ├── condition │ ├── location_condition.h │ ├── has_flag_condition.h │ ├── region_condition.h │ ├── condition_check_base.h │ ├── coastal_condition.h │ ├── has_law_condition.h │ ├── hidden_condition.h │ ├── has_item_condition.h │ ├── alive_condition.h │ ├── has_trait_condition.h │ ├── has_technology_condition.h │ ├── condition_check.h │ ├── borders_water_condition.h │ ├── has_any_trade_route_condition.h │ ├── has_building_condition.h │ ├── ai_condition.h │ ├── culture_condition.h │ ├── world_condition.h │ ├── holding_type_condition.h │ ├── terrain_condition.h │ ├── commodity_condition.h │ ├── has_any_active_trade_route_condition.h │ ├── has_technology_condition.cpp │ └── has_any_trade_route_land_connection_condition.h ├── chance_factor.h ├── modifier.h ├── factor_modifier.h ├── chance_util.h ├── holding_modifier.h ├── scope_util.h ├── modifier.cpp ├── factor_modifier.cpp └── chance_factor.cpp ├── character ├── enemy.cpp ├── trait.cpp ├── enemy.h ├── dynasty.h ├── item.cpp └── dynasty.cpp ├── religion ├── religion_group.cpp ├── religion.cpp ├── religion_group.h └── religion.h ├── database ├── gsml_operator.h ├── data_type_base.h ├── csv_data.h ├── module.cpp ├── gsml_data_visitor.h ├── gsml_parser.h ├── gsml_property_visitor.h ├── gsml_property.cpp ├── gsml_element_visitor.h ├── simple_data_type.h ├── gsml_property.h ├── defines.cpp ├── csv_data.cpp └── gsml_data.cpp ├── map ├── world_type.cpp ├── map_mode.h ├── pathfinder.h ├── province_profile.h ├── world_type.h ├── terrain_type.cpp ├── map.h └── province_profile.cpp ├── warfare ├── troop_type_map.h ├── troop_type_map.cpp └── troop_type.cpp ├── population ├── population_unit_base.cpp └── population_type.cpp ├── species ├── species.cpp └── wildlife_unit.h ├── politics ├── law_group.h ├── law.h ├── government_type.cpp ├── government_type_group.h └── government_type.h ├── culture ├── culture_supergroup.h ├── culture_group.h ├── culture_group.cpp ├── culture.h └── culture_base.cpp ├── qml_code_style.xml ├── economy ├── employment_owner.cpp ├── employee.cpp ├── commodity.cpp ├── employee.h ├── employment_owner.h └── employment.h ├── README.md ├── LICENSE ├── history ├── history.h ├── timeline.h └── calendar.h ├── holding └── holding_type.cpp ├── pch.h ├── third_party └── maskedmousearea │ └── LICENSE └── Coding Guidelines.txt /qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | Metternich.pro.user 3 | Metternich.pro.user.4.10-pre1 4 | *.autosave.* -------------------------------------------------------------------------------- /game/tick_period.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | enum class tick_period 6 | { 7 | millenium, 8 | day 9 | }; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /util/image_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich::image { 7 | 8 | extern std::set get_rgbs(const QImage &image); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /technology/technology_compare.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | class technology; 6 | 7 | struct technology_compare 8 | { 9 | bool operator()(technology *a, technology *b) const; 10 | }; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /technology/technology_set.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "technology/technology_compare.h" 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | using technology_set = std::set; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /technology/technology_area_compare.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | class technology_area; 6 | 7 | struct technology_area_compare 8 | { 9 | bool operator()(technology_area *a, technology_area *b) const; 10 | }; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /technology/technology_map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "technology/technology_compare.h" 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | template 10 | using technology_map = std::map; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /landed_title/landed_title_tier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | enum class landed_title_tier 6 | { 7 | barony, //holding 8 | county, //province or world 9 | duchy, //star system in the cosmic map 10 | kingdom, 11 | empire 12 | }; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /script/event/event.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | 5 | namespace metternich { 6 | 7 | class event : public data_entry 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | event(const std::string &identifier) : data_entry(identifier) {} 13 | }; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /character/enemy.cpp: -------------------------------------------------------------------------------- 1 | #include "character/enemy.h" 2 | 3 | #include "util/translator.h" 4 | 5 | namespace metternich { 6 | 7 | std::string enemy::get_name_plural() const 8 | { 9 | return translator::get()->translate(this->get_identifier_with_aliases(), {{"plural"}}); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /script/decision/decision.cpp: -------------------------------------------------------------------------------- 1 | #include "script/decision/decision.h" 2 | 3 | #include "util/translator.h" 4 | 5 | namespace metternich { 6 | 7 | std::string decision::get_description() const 8 | { 9 | return translator::get()->translate(this->get_identifier() + "_desc"); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /util/number_util.cpp: -------------------------------------------------------------------------------- 1 | #include "util/number_util.h" 2 | 3 | #include 4 | 5 | namespace metternich::number { 6 | 7 | double degree_to_radian(const double degree) 8 | { 9 | return degree * boost::math::constants::pi() / 180.; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /util/set_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich::set { 6 | 7 | template 8 | void merge(T &set, const U &other_container) 9 | { 10 | for (const typename U::value_type &element : other_container) { 11 | set.insert(element); 12 | } 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /religion/religion_group.cpp: -------------------------------------------------------------------------------- 1 | #include "religion/religion_group.h" 2 | 3 | namespace metternich { 4 | 5 | void religion_group::check() const 6 | { 7 | if (!this->get_color().isValid()) { 8 | throw std::runtime_error("Religion group \"" + this->get_identifier() + "\" has no valid color."); 9 | } 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /database/gsml_operator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | enum class gsml_operator 6 | { 7 | none, 8 | assignment, 9 | addition, 10 | subtraction, 11 | equality, 12 | inequality, 13 | less_than, 14 | less_than_or_equality, 15 | greater_than, 16 | greater_than_or_equality 17 | }; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /util/vector_random_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "util/random.h" 4 | 5 | #include 6 | 7 | namespace metternich::vector { 8 | 9 | template 10 | inline const typename T::value_type &get_random(const T &vector) 11 | { 12 | return vector[random::generate(vector.size())]; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /util/point_util.cpp: -------------------------------------------------------------------------------- 1 | #include "util/point_util.h" 2 | 3 | #include "util/number_util.h" 4 | 5 | namespace metternich::point { 6 | 7 | QPointF get_degree_angle_direction(const double angle) 8 | { 9 | const double radian_angle = number::degree_to_radian(angle); 10 | return point::get_radian_angle_direction(radian_angle); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /util/point_container.cpp: -------------------------------------------------------------------------------- 1 | #include "util/point_container.h" 2 | 3 | namespace metternich { 4 | 5 | bool point_compare::operator()(const QPoint &point, const QPoint &other_point) const 6 | { 7 | if (point.x() != other_point.x()) { 8 | return point.x() < other_point.x(); 9 | } 10 | 11 | return point.y() < other_point.y(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /map/world_type.cpp: -------------------------------------------------------------------------------- 1 | #include "map/world_type.h" 2 | 3 | #include "database/database.h" 4 | 5 | namespace metternich { 6 | 7 | const std::filesystem::path &world_type::get_texture_path() const 8 | { 9 | //returns a random texture for the world type 10 | return database::get()->get_tagged_texture_path(this->get_texture_tag()); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /warfare/troop_type_map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich { 6 | 7 | class troop_type; 8 | 9 | struct troop_type_compare 10 | { 11 | bool operator()(troop_type *a, troop_type *b) const; 12 | }; 13 | 14 | template 15 | using troop_type_map = std::map; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /map/map_mode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | enum class map_mode 6 | { 7 | none, 8 | country, 9 | de_jure_empire, 10 | de_jure_kingdom, 11 | de_jure_duchy, 12 | culture, 13 | culture_group, 14 | religion, 15 | religion_group, 16 | trade_node, 17 | trade_zone //the map mode detailing which countries control trading posts where 18 | }; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /util/exception_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich::exception { 6 | 7 | inline void report(const std::exception &exception) 8 | { 9 | try { 10 | std::rethrow_if_nested(exception); 11 | } catch (const std::exception &nested_exception) { 12 | exception::report(nested_exception); 13 | } 14 | 15 | qCritical() << exception.what(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /util/point_container.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | struct point_compare 10 | { 11 | bool operator()(const QPoint &point, const QPoint &other_point) const; 12 | }; 13 | 14 | using point_set = std::set; 15 | 16 | template 17 | using point_map = std::map; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /warfare/troop_type_map.cpp: -------------------------------------------------------------------------------- 1 | #include "warfare/troop_type_map.h" 2 | 3 | #include "warfare/troop_type.h" 4 | 5 | namespace metternich { 6 | 7 | bool troop_type_compare::operator()(troop_type *a, troop_type *b) const 8 | { 9 | if (a->get_category() != b->get_category()) { 10 | return a->get_category() < b->get_category(); 11 | } 12 | 13 | return a->get_identifier() < b->get_identifier(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /database/data_type_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/gsml_data.h" 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | /** 10 | ** @brief The base class for the data type class per se, and for simpler data type classes which don't use identifiers 11 | */ 12 | template 13 | class data_type_base 14 | { 15 | protected: 16 | static inline std::vector gsml_history_data_to_process; 17 | }; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /population/population_unit_base.cpp: -------------------------------------------------------------------------------- 1 | #include "population/population_unit_base.h" 2 | 3 | #include "map/province.h" 4 | #include "map/world.h" 5 | 6 | namespace metternich { 7 | 8 | territory *population_unit_base::get_territory() const 9 | { 10 | if (this->get_province() != nullptr) { 11 | return this->get_province(); 12 | } else if (this->get_world() != nullptr) { 13 | return this->get_world(); 14 | } 15 | 16 | return nullptr; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /species/species.cpp: -------------------------------------------------------------------------------- 1 | #include "species/species.h" 2 | 3 | #include "util/container_util.h" 4 | #include "util/translator.h" 5 | 6 | namespace metternich { 7 | 8 | std::string species::get_name_plural() const 9 | { 10 | return translator::get()->translate(this->get_identifier_with_aliases(), {{"plural"}}); 11 | } 12 | 13 | QVariantList species::get_evolutions_qvariant_list() const 14 | { 15 | return container::to_qvariant_list(this->get_evolutions()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /util/geocoordinate_util.cpp: -------------------------------------------------------------------------------- 1 | #include "util/geocoordinate_util.h" 2 | 3 | #include "util/point_util.h" 4 | 5 | namespace metternich::geocoordinate { 6 | 7 | QPointF to_circle_edge_point(const QGeoCoordinate &coordinate) 8 | { 9 | const QPointF circle_point = geocoordinate::to_circle_point(coordinate); 10 | const QPointF circle_edge_point = point::get_nearest_circle_edge_point(circle_point, 180.); 11 | return point::get_circle_point(circle_edge_point, 180., 1.); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /religion/religion.cpp: -------------------------------------------------------------------------------- 1 | #include "religion/religion.h" 2 | 3 | #include "religion/religion_group.h" 4 | 5 | namespace metternich { 6 | 7 | void religion::check() const 8 | { 9 | if (this->get_group() == nullptr) { 10 | throw std::runtime_error("Religion \"" + this->get_identifier() + "\" has no religion group."); 11 | } 12 | 13 | if (!this->get_color().isValid()) { 14 | throw std::runtime_error("Religion \"" + this->get_identifier() + "\" has no valid color."); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /database/csv_data.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace metternich { 8 | 9 | class csv_data 10 | { 11 | public: 12 | static constexpr char delimiter = ';'; 13 | 14 | static csv_data parse_file(const std::filesystem::path &filepath); 15 | 16 | const std::vector> &get_values() const 17 | { 18 | return this->values; 19 | } 20 | 21 | private: 22 | std::vector> values; 23 | }; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /politics/law_group.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | #include 7 | 8 | namespace metternich { 9 | 10 | class law_group final : public data_entry, public data_type 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | law_group(const std::string &identifier) : data_entry(identifier) {} 16 | 17 | static constexpr const char *class_identifier = "law_group"; 18 | static constexpr const char *database_folder = "law_groups"; 19 | }; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /util/empty_image_provider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich { 6 | 7 | class empty_image_provider final : public QQuickImageProvider 8 | { 9 | public: 10 | empty_image_provider() : QQuickImageProvider(QQuickImageProvider::Image) {} 11 | 12 | virtual QImage requestImage(const QString &, QSize *, const QSize &) override 13 | { 14 | QImage image(QSize(1, 1), QImage::Format_ARGB32); 15 | image.fill(qRgba(0, 0, 0, 0)); 16 | return image; 17 | } 18 | }; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /util/random.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "util/random.h" 4 | 5 | #include "util/point_util.h" 6 | 7 | #include 8 | 9 | namespace metternich { 10 | 11 | double random::generate_radian_angle() 12 | { 13 | return random::generate_in_range(0., 1.) * 2. * boost::math::constants::pi(); 14 | } 15 | 16 | QPointF random::generate_circle_position() 17 | { 18 | const double angle = random::generate_radian_angle(); 19 | return point::get_radian_angle_direction(angle); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /culture/culture_supergroup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "culture/culture_base.h" 4 | #include "database/data_type.h" 5 | 6 | namespace metternich { 7 | 8 | class culture_supergroup final : public culture_base, public data_type 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | static constexpr const char *class_identifier = "culture_supergroup"; 14 | static constexpr const char *database_folder = "culture_supergroups"; 15 | 16 | culture_supergroup(const std::string &identifier) : culture_base(identifier) {} 17 | }; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /script/decision/decision.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | class decision : public data_entry 10 | { 11 | Q_OBJECT 12 | 13 | Q_PROPERTY(QString description READ get_description_qstring CONSTANT) 14 | 15 | public: 16 | decision(const std::string &identifier) : data_entry(identifier) {} 17 | 18 | std::string get_description() const; 19 | 20 | QString get_description_qstring() const 21 | { 22 | return QString::fromStdString(this->get_description()); 23 | } 24 | }; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /util/qunique_ptr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | struct qobject_deleter 10 | { 11 | void operator()(QObject *object) 12 | { 13 | object->deleteLater(); 14 | } 15 | }; 16 | 17 | //unique pointer that calls QObject::deleteLater 18 | template 19 | using qunique_ptr = std::unique_ptr; 20 | 21 | template 22 | inline qunique_ptr make_qunique(ARGS&&... args) 23 | { 24 | return qunique_ptr(new T(std::forward(args)...)); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /database/module.cpp: -------------------------------------------------------------------------------- 1 | #include "database/module.h" 2 | 3 | #include "database/database.h" 4 | #include "util/container_util.h" 5 | #include "util/translator.h" 6 | 7 | namespace metternich { 8 | 9 | std::string module::get_name() const 10 | { 11 | return translator::get()->translate(this->get_identifier()); 12 | } 13 | 14 | void module::process_gsml_property(const gsml_property &property) 15 | { 16 | database::process_gsml_property_for_object(this, property); 17 | } 18 | 19 | QVariantList module::get_dependencies_qvariant_list() const 20 | { 21 | return container::to_qvariant_list(this->dependencies); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /util/polygon_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich::polygon { 6 | 7 | inline double get_area(const QPolygonF &polygon) 8 | { 9 | double area = 0.; 10 | 11 | for (int i = 0; i < polygon.size(); ++i) { 12 | const QPointF &point = polygon[i]; 13 | const int j = (i + 1) % polygon.size(); 14 | const QPointF &other_point = polygon[j]; 15 | area += 0.5 * (point.x() * other_point.y() - other_point.x() * point.y()); 16 | } 17 | 18 | return area; 19 | } 20 | 21 | extern QPolygonF from_radius(const double radius, const int angle_per_point, const QPointF &offset = QPointF(0, 0)); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /technology/technology_area_compare.cpp: -------------------------------------------------------------------------------- 1 | #include "technology/technology_area_compare.h" 2 | 3 | #include "technology/technology_area.h" 4 | 5 | namespace metternich { 6 | 7 | bool technology_area_compare::operator()(technology_area *a, technology_area *b) const 8 | { 9 | if (a->get_category() != b->get_category()) { 10 | return a->get_category() < b->get_category(); 11 | } 12 | 13 | const int a_min_level = a->get_min_level(); 14 | const int b_min_level = b->get_min_level(); 15 | 16 | if (a_min_level != b_min_level) { 17 | return a_min_level < b_min_level; 18 | } 19 | 20 | return a->get_identifier() < b->get_identifier(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /technology/technology_compare.cpp: -------------------------------------------------------------------------------- 1 | #include "technology/technology_compare.h" 2 | 3 | #include "technology/technology.h" 4 | #include "technology/technology_area_compare.h" 5 | 6 | namespace metternich { 7 | 8 | bool technology_compare::operator()(technology *a, technology *b) const 9 | { 10 | if (a->get_area() != b->get_area()) { 11 | return technology_area_compare()(a->get_area(), b->get_area()); 12 | } 13 | 14 | const int a_level = a->get_level(); 15 | const int b_level = b->get_level(); 16 | 17 | if (a_level != b_level) { 18 | return a_level < b_level; 19 | } 20 | 21 | return a->get_identifier() < b->get_identifier(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /qml_code_style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CodeStyleData 7 | 8 | false 9 | 4 10 | 2 11 | false 12 | 4 13 | 14 | 15 | 16 | DisplayName 17 | Metternich 18 | 19 | 20 | -------------------------------------------------------------------------------- /util/polygon_util.cpp: -------------------------------------------------------------------------------- 1 | #include "util/polygon_util.h" 2 | 3 | #include "util/point_util.h" 4 | 5 | namespace metternich::polygon { 6 | 7 | QPolygonF from_radius(const double radius, const int angle_per_point, const QPointF &offset) 8 | { 9 | //create a circle polygon from a given radius 10 | QPolygonF circle_polygon; 11 | for (int angle = 0; angle < 360; angle += angle_per_point) { 12 | const QPointF direction = point::get_degree_angle_direction(angle); 13 | circle_polygon.append(direction * radius); 14 | } 15 | 16 | circle_polygon.append(circle_polygon.back()); //close the polygon 17 | circle_polygon.translate(offset); //apply the offset to it 18 | return circle_polygon; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /database/gsml_data_visitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | class gsml_data; 6 | class gsml_property; 7 | 8 | //a visitor that only does an action when visiting GSML data 9 | template 10 | class gsml_data_visitor 11 | { 12 | public: 13 | gsml_data_visitor(const function_type &function) : function(function) 14 | { 15 | } 16 | 17 | gsml_data_visitor(function_type &&function) = delete; 18 | 19 | void operator()(const gsml_property &property) const 20 | { 21 | Q_UNUSED(property) 22 | } 23 | 24 | void operator()(const gsml_data &scope) const 25 | { 26 | this->function(scope); 27 | } 28 | 29 | private: 30 | const function_type &function; 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /population/population_type.cpp: -------------------------------------------------------------------------------- 1 | #include "population/population_type.h" 2 | 3 | #include "holding/holding_type.h" 4 | #include "util/container_util.h" 5 | 6 | namespace metternich { 7 | 8 | void population_type::check() const 9 | { 10 | if (!this->get_color().isValid()) { 11 | throw std::runtime_error("Population type \"" + this->get_identifier() + "\" has no valid color."); 12 | } 13 | } 14 | 15 | QVariantList population_type::get_equivalent_types_qvariant_list() const 16 | { 17 | return container::to_qvariant_list(this->get_equivalent_types()); 18 | } 19 | 20 | QVariantList population_type::get_holding_types_qvariant_list() const 21 | { 22 | return container::to_qvariant_list(this->get_holding_types()); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /database/gsml_parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich { 7 | 8 | class gsml_data; 9 | enum class gsml_operator; 10 | 11 | class gsml_parser 12 | { 13 | public: 14 | gsml_parser(const std::filesystem::path &filepath); 15 | 16 | gsml_data parse(); 17 | 18 | private: 19 | void parse_line(const std::string &line); 20 | bool parse_escaped_character(std::string ¤t_string, const char c); 21 | void parse_tokens(); 22 | void reset(); 23 | 24 | private: 25 | std::filesystem::path filepath; 26 | std::vector tokens; 27 | gsml_data *current_gsml_data = nullptr; 28 | std::string current_key; 29 | gsml_operator current_property_operator; 30 | }; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /database/gsml_property_visitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | class gsml_data; 6 | class gsml_property; 7 | 8 | //a visitor that only does an action when visiting GSML properties 9 | template 10 | class gsml_property_visitor 11 | { 12 | public: 13 | gsml_property_visitor(const function_type &function) : function(function) 14 | { 15 | } 16 | 17 | gsml_property_visitor(function_type &&function) = delete; 18 | 19 | void operator()(const gsml_property &property) const 20 | { 21 | this->function(property); 22 | } 23 | 24 | void operator()(const gsml_data &scope) const 25 | { 26 | Q_UNUSED(scope) 27 | } 28 | 29 | private: 30 | const function_type &function; 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /politics/law.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | #include 7 | 8 | namespace metternich { 9 | 10 | class law_group; 11 | 12 | class law final : public data_entry, public data_type 13 | { 14 | Q_OBJECT 15 | 16 | Q_PROPERTY(metternich::law_group* group MEMBER group READ get_group) 17 | 18 | public: 19 | law(const std::string &identifier) : data_entry(identifier) {} 20 | 21 | static constexpr const char *class_identifier = "law"; 22 | static constexpr const char *database_folder = "laws"; 23 | 24 | metternich::law_group *get_group() const 25 | { 26 | return this->group; 27 | } 28 | 29 | private: 30 | metternich::law_group *group = nullptr; 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /util/image_util.cpp: -------------------------------------------------------------------------------- 1 | #include "util/image_util.h" 2 | 3 | #include "util/container_util.h" 4 | 5 | namespace metternich::image { 6 | 7 | /** 8 | ** @brief Get the RGBs present in an image 9 | ** 10 | ** @param image The image 11 | ** 12 | ** @return The set of RGB values 13 | */ 14 | std::set get_rgbs(const QImage &image) 15 | { 16 | if (!image.colorTable().empty()) { 17 | return container::to_set(image.colorTable()); 18 | } 19 | 20 | std::set rgb_set; 21 | 22 | const int pixel_count = image.width() * image.height(); 23 | const QRgb *rgb_data = reinterpret_cast(image.constBits()); 24 | 25 | for (int i = 0; i < pixel_count; ++i) { 26 | rgb_set.insert(rgb_data[i]); 27 | } 28 | 29 | return rgb_set; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /religion/religion_group.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | namespace metternich { 7 | 8 | class religion_group final : public data_entry, public data_type 9 | { 10 | Q_OBJECT 11 | 12 | Q_PROPERTY(QColor color MEMBER color READ get_color) 13 | 14 | public: 15 | static constexpr const char *class_identifier = "religion_group"; 16 | static constexpr const char *database_folder = "religion_groups"; 17 | 18 | religion_group(const std::string &identifier) : data_entry(identifier) {} 19 | 20 | virtual void check() const override; 21 | 22 | const QColor &get_color() const 23 | { 24 | return this->color; 25 | } 26 | 27 | private: 28 | QColor color; 29 | }; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /util/type_traits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | template class T2> 6 | struct is_specialization_of : std::false_type {}; 7 | 8 | template class T, typename ...A> 9 | struct is_specialization_of, T> : std::true_type {}; 10 | 11 | template class T2> 12 | inline constexpr bool is_specialization_of_v = is_specialization_of::value; 13 | 14 | template 15 | struct contained_element 16 | { 17 | using type = T; 18 | }; 19 | 20 | template 21 | struct contained_element> 22 | { 23 | using type = T; 24 | }; 25 | 26 | template 27 | using contained_element_t = typename contained_element::type; 28 | -------------------------------------------------------------------------------- /database/gsml_property.cpp: -------------------------------------------------------------------------------- 1 | #include "database/gsml_property.h" 2 | 3 | #include "database/gsml_operator.h" 4 | 5 | namespace metternich { 6 | 7 | void gsml_property::print(std::ofstream &ofstream, const size_t indentation) const 8 | { 9 | ofstream << std::string(indentation, '\t') << this->get_key() << " "; 10 | 11 | switch (this->get_operator()) { 12 | case gsml_operator::assignment: 13 | ofstream << "="; 14 | break; 15 | case gsml_operator::addition: 16 | ofstream << "+="; 17 | break; 18 | case gsml_operator::subtraction: 19 | ofstream << "-="; 20 | break; 21 | case gsml_operator::none: 22 | throw std::runtime_error("Cannot print the GSML \"none\" operator."); 23 | } 24 | 25 | ofstream << " " << this->get_value() << "\n"; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /economy/employment_owner.cpp: -------------------------------------------------------------------------------- 1 | #include "economy/employment_owner.h" 2 | 3 | #include "database/database.h" 4 | #include "database/gsml_data.h" 5 | #include "database/gsml_property.h" 6 | #include "population/population_type.h" 7 | #include "util/filesystem_util.h" 8 | 9 | namespace metternich { 10 | 11 | qunique_ptr employment_owner::from_gsml_scope(const gsml_data &scope) 12 | { 13 | auto owner = make_qunique(); 14 | owner->population_type = population_type::get(scope.get_tag()); 15 | 16 | database::process_gsml_data(owner, scope); 17 | 18 | return owner; 19 | } 20 | 21 | void employment_owner::process_gsml_property(const gsml_property &property) 22 | { 23 | database::process_gsml_property_for_object(this, property); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /script/flag/scoped_flag.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/identifiable_type.h" 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | class scoped_flag_base 10 | { 11 | public: 12 | scoped_flag_base(const std::string &identifier) : identifier(identifier) 13 | { 14 | } 15 | 16 | const std::string &get_identifier() const 17 | { 18 | return this->identifier; 19 | } 20 | 21 | private: 22 | std::string identifier; 23 | }; 24 | 25 | template 26 | class scoped_flag final : public scoped_flag_base, public identifiable_type> 27 | { 28 | public: 29 | static constexpr const char *class_identifier = "scoped_flag"; 30 | 31 | scoped_flag(const std::string &identifier) : scoped_flag_base(identifier) 32 | { 33 | } 34 | }; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /map/pathfinder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich { 7 | 8 | class pathfinder_implementation; 9 | class province; 10 | 11 | struct find_trade_path_result 12 | { 13 | find_trade_path_result(const bool success) : success(success) 14 | {} 15 | 16 | bool success = false; 17 | int trade_cost = 0; //the resulting trade cost 18 | std::vector path; //the resulting trade path 19 | }; 20 | 21 | class pathfinder 22 | { 23 | class impl; 24 | 25 | public: 26 | pathfinder(const std::set &provinces); 27 | ~pathfinder(); 28 | 29 | find_trade_path_result find_trade_path(const province *start_province, const province *goal_province) const; 30 | 31 | private: 32 | std::unique_ptr implementation; 33 | }; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /script/effect/location_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/effect/scope_effect.h" 4 | 5 | namespace metternich { 6 | 7 | class province; 8 | 9 | template 10 | class location_effect final : public scope_effect 11 | { 12 | public: 13 | location_effect(const gsml_operator effect_operator) : scope_effect(effect_operator) 14 | { 15 | } 16 | 17 | virtual const std::string &get_identifier() const override 18 | { 19 | static const std::string identifier = "location"; 20 | return identifier; 21 | } 22 | 23 | virtual province *get_scope(T *scope) const override 24 | { 25 | return scope->get_location(); 26 | } 27 | 28 | virtual const province *get_scope(const T *scope) const override 29 | { 30 | return scope->get_location(); 31 | } 32 | }; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /script/context.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich { 6 | 7 | class character; 8 | 9 | //script context for e.g. events and decisions 10 | template 11 | struct context_base 12 | { 13 | using character_ptr = std::conditional_t; 14 | 15 | character_ptr source_character = nullptr; 16 | character_ptr current_character = nullptr; 17 | }; 18 | 19 | struct context final : context_base 20 | { 21 | }; 22 | 23 | struct read_only_context final : context_base 24 | { 25 | public: 26 | read_only_context() 27 | { 28 | } 29 | 30 | read_only_context(const context &ctx) 31 | { 32 | this->source_character = ctx.source_character; 33 | this->current_character = ctx.current_character; 34 | } 35 | }; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /script/modifier_effect/modifier_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | class character; 6 | class gsml_property; 7 | class holding; 8 | class province; 9 | class territory; 10 | 11 | template 12 | class modifier_effect 13 | { 14 | public: 15 | static std::unique_ptr from_gsml_property(const gsml_property &property); 16 | 17 | virtual ~modifier_effect() {} 18 | 19 | virtual const std::string &get_identifier() const = 0; 20 | virtual void apply(T *scope, const int change) const = 0; 21 | virtual std::string get_string() const = 0; 22 | }; 23 | 24 | extern template class modifier_effect; 25 | extern template class modifier_effect; 26 | extern template class modifier_effect; 27 | extern template class modifier_effect; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /economy/employee.cpp: -------------------------------------------------------------------------------- 1 | #include "economy/employee.h" 2 | 3 | #include "database/database.h" 4 | #include "database/gsml_data.h" 5 | #include "database/gsml_property.h" 6 | #include "population/population_type.h" 7 | #include "util/filesystem_util.h" 8 | 9 | namespace metternich { 10 | 11 | qunique_ptr employee::from_gsml_scope(const gsml_data &scope) 12 | { 13 | auto employee = make_qunique(); 14 | metternich::population_type *population_type = population_type::get(scope.get_tag()); 15 | population_type->set_employable(true); 16 | employee->population_type = population_type; 17 | 18 | database::process_gsml_data(employee, scope); 19 | 20 | return employee; 21 | } 22 | 23 | void employee::process_gsml_property(const gsml_property &property) 24 | { 25 | database::process_gsml_property_for_object(this, property); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /culture/culture_group.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "culture/culture_base.h" 4 | #include "database/data_type.h" 5 | 6 | namespace metternich { 7 | 8 | class culture_supergroup; 9 | 10 | class culture_group final : public culture_base, public data_type 11 | { 12 | Q_OBJECT 13 | 14 | Q_PROPERTY(metternich::culture_supergroup* supergroup MEMBER supergroup READ get_supergroup) 15 | 16 | public: 17 | static constexpr const char *class_identifier = "culture_group"; 18 | static constexpr const char *database_folder = "culture_groups"; 19 | 20 | culture_group(const std::string &identifier) : culture_base(identifier) {} 21 | 22 | virtual void initialize() override; 23 | 24 | culture_supergroup *get_supergroup() const 25 | { 26 | return this->supergroup; 27 | } 28 | 29 | private: 30 | culture_supergroup *supergroup = nullptr; 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /script/modifier_effect/prowess_modifier_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/modifier_effect/modifier_effect.h" 4 | #include "util/number_util.h" 5 | 6 | namespace metternich { 7 | 8 | template 9 | class prowess_modifier_effect final : public modifier_effect 10 | { 11 | public: 12 | prowess_modifier_effect(const int prowess) 13 | : prowess(prowess) {} 14 | 15 | virtual const std::string &get_identifier() const override 16 | { 17 | static const std::string identifier = "prowess"; 18 | return identifier; 19 | } 20 | 21 | virtual void apply(T *scope, const int change) const override 22 | { 23 | scope->change_prowess(this->prowess * change); 24 | } 25 | 26 | virtual std::string get_string() const override 27 | { 28 | return "Prowess: " + number::to_signed_string(this->prowess); 29 | } 30 | 31 | private: 32 | int prowess = 0; 33 | }; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /script/event/event_instance.cpp: -------------------------------------------------------------------------------- 1 | #include "script/event/event_instance.h" 2 | 3 | #include "game/game.h" 4 | #include "util/container_util.h" 5 | 6 | namespace metternich { 7 | 8 | event_instance::event_instance(const QString &name, const QString &description, std::vector> &&options) 9 | : name(name), description(description), options(std::move(options)) 10 | { 11 | } 12 | 13 | event_instance::~event_instance() 14 | { 15 | } 16 | 17 | QVariantList event_instance::get_options() const 18 | { 19 | std::vector options; 20 | 21 | for (const qunique_ptr &option : this->options) { 22 | options.push_back(option.get()); 23 | } 24 | 25 | return container::to_qvariant_list(options); 26 | } 27 | 28 | void event_option_instance::do_effects() const 29 | { 30 | game::get()->post_order(this->option_effects); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /politics/government_type.cpp: -------------------------------------------------------------------------------- 1 | #include "politics/government_type.h" 2 | 3 | #include "holding/holding_type.h" 4 | #include "script/condition/and_condition.h" 5 | #include "util/container_util.h" 6 | 7 | namespace metternich { 8 | 9 | government_type::government_type(const std::string &identifier) : data_entry(identifier) 10 | { 11 | } 12 | 13 | government_type::~government_type() 14 | { 15 | } 16 | 17 | void government_type::process_gsml_scope(const gsml_data &scope) 18 | { 19 | if (scope.get_tag() == "conditions") { 20 | this->conditions = std::make_unique>(); 21 | database::process_gsml_data(this->conditions.get(), scope); 22 | } else { 23 | data_entry_base::process_gsml_scope(scope); 24 | } 25 | } 26 | 27 | QVariantList government_type::get_allowed_holding_types_qvariant_list() const 28 | { 29 | return container::to_qvariant_list(this->get_allowed_holding_types()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /util/singleton.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace metternich { 12 | 13 | template 14 | class singleton 15 | { 16 | public: 17 | static T *get() 18 | { 19 | std::call_once(singleton::once_flag, [](){ 20 | T::create(); 21 | }); 22 | 23 | return singleton::instance.get(); 24 | } 25 | 26 | private: 27 | static void create() 28 | { 29 | singleton::instance = std::make_unique(); 30 | 31 | if constexpr (std::is_base_of_v) { 32 | if (QApplication::instance()->thread() != QThread::currentThread()) { 33 | singleton::instance->moveToThread(QApplication::instance()->thread()); 34 | } 35 | } 36 | } 37 | 38 | private: 39 | static inline std::unique_ptr instance; 40 | static inline std::once_flag once_flag; 41 | }; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /script/effect/source_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/context.h" 4 | #include "script/effect/scope_effect.h" 5 | 6 | namespace metternich { 7 | 8 | class character; 9 | 10 | template 11 | class source_effect final : public scope_effect 12 | { 13 | public: 14 | source_effect(const gsml_operator effect_operator) : scope_effect(effect_operator) 15 | { 16 | } 17 | 18 | virtual const std::string &get_identifier() const override 19 | { 20 | static const std::string identifier = "source"; 21 | return identifier; 22 | } 23 | 24 | virtual character *get_scope(T *scope, const context &ctx) const override 25 | { 26 | Q_UNUSED(scope) 27 | 28 | return ctx.source_character; 29 | } 30 | 31 | virtual const character *get_scope(const T *scope, const read_only_context &ctx) const override 32 | { 33 | Q_UNUSED(scope) 34 | 35 | return ctx.source_character; 36 | } 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Metternich 2 | Grand strategy game engine 3 | 4 | Build instructions: 5 | 1. Download Qt. The open source version is available from their website, at: https://www.qt.io/download. You will likely need 5.12 or later. 6 | 2. Install Qt. Besides the framework itself, the Qt Creator will also be necessary to compile Metternich. Note that the download + install process may take a few hours. 7 | 3. Once the installation is done, start the Qt Creator. 8 | 4. Click on "Open Project", and select the Metternich.pro file. 9 | 5. Click on the "Build" menu item on the top bar, and then on the "Build Project 'Metternich'" sub-item. 10 | 11 | For the data repository holding the actual game content, see: 12 | https://github.com/Andrettin/Iron-Barons 13 | 14 | To play it, compile the engine and run it with the Iron Barons root directory as the engine's working directory. 15 | 16 | The engine is licensed under the MIT license, see the LICENSE file for details. -------------------------------------------------------------------------------- /database/gsml_element_visitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | class gsml_data; 6 | class gsml_property; 7 | 8 | template 9 | class gsml_element_visitor 10 | { 11 | public: 12 | gsml_element_visitor(const property_function_type &property_function, const data_function_type &data_function) 13 | : property_function(property_function), data_function(data_function) 14 | { 15 | } 16 | 17 | gsml_element_visitor(property_function_type &&property_function, data_function_type &&data_function) = delete; 18 | 19 | void operator()(const gsml_property &property) const 20 | { 21 | this->property_function(property); 22 | } 23 | 24 | void operator()(const gsml_data &scope) const 25 | { 26 | this->data_function(scope); 27 | } 28 | 29 | private: 30 | const property_function_type &property_function; 31 | const data_function_type &data_function; 32 | }; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /util/map_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich::map_container { 7 | 8 | template 9 | inline std::set get_keys(const T &map) 10 | { 11 | std::set set; 12 | 13 | for (const auto &kv_pair : map) { 14 | set.insert(kv_pair.first); 15 | } 16 | 17 | return set; 18 | } 19 | 20 | template 21 | inline std::vector get_key_vector(const T &map) 22 | { 23 | std::vector vector; 24 | vector.reserve(map.size()); 25 | 26 | for (const auto &kv_pair : map) { 27 | vector.push_back(kv_pair.first); 28 | } 29 | 30 | return vector; 31 | } 32 | 33 | template 34 | inline std::vector get_values(const T &map) 35 | { 36 | std::vector vector; 37 | 38 | for (const auto &kv_pair : map) { 39 | vector.push_back(kv_pair.second); 40 | } 41 | 42 | return vector; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /economy/commodity.cpp: -------------------------------------------------------------------------------- 1 | #include "economy/commodity.h" 2 | 3 | #include "database/database.h" 4 | #include "database/gsml_data.h" 5 | #include "database/gsml_property.h" 6 | #include "script/chance_factor.h" 7 | 8 | namespace metternich { 9 | 10 | commodity::commodity(const std::string &identifier) : data_entry(identifier) 11 | { 12 | } 13 | 14 | commodity::~commodity() 15 | { 16 | } 17 | 18 | void commodity::process_gsml_scope(const gsml_data &scope) 19 | { 20 | const std::string &tag = scope.get_tag(); 21 | 22 | if (tag == "chance") { 23 | this->chance = std::make_unique>(); 24 | database::process_gsml_data(this->chance, scope); 25 | } else { 26 | data_entry_base::process_gsml_scope(scope); 27 | } 28 | } 29 | 30 | const std::filesystem::path &commodity::get_icon_path() const 31 | { 32 | std::string base_tag = this->get_icon_tag(); 33 | const std::filesystem::path &icon_path = database::get()->get_tagged_icon_path(base_tag); 34 | return icon_path; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /script/effect/effect_list.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace metternich { 8 | 9 | class character; 10 | class gsml_data; 11 | class gsml_property; 12 | class holding; 13 | class province; 14 | struct context; 15 | struct read_only_context; 16 | 17 | template 18 | class effect; 19 | 20 | template 21 | class effect_list 22 | { 23 | public: 24 | effect_list(); 25 | ~effect_list(); 26 | 27 | void process_gsml_property(const gsml_property &property); 28 | void process_gsml_scope(const gsml_data &scope); 29 | void do_effects(T *scope, const context &ctx) const; 30 | std::string get_effects_string(const T *scope, const read_only_context &ctx, const size_t indent = 0) const; 31 | 32 | private: 33 | std::vector>> effects; 34 | }; 35 | 36 | extern template class effect_list; 37 | extern template class effect_list; 38 | extern template class effect_list; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /warfare/troop_type.cpp: -------------------------------------------------------------------------------- 1 | #include "warfare/troop_type.h" 2 | 3 | #include "util/translator.h" 4 | #include "warfare/troop_category.h" 5 | 6 | namespace metternich { 7 | 8 | troop_type::troop_type(const std::string &identifier) 9 | : data_entry(identifier), category(troop_category::none) 10 | { 11 | } 12 | 13 | void troop_type::check() const 14 | { 15 | if (this->get_category() == troop_category::none) { 16 | throw std::runtime_error("Troop type \"" + this->get_identifier() + "\" has no category."); 17 | } 18 | 19 | this->get_icon_path(); //throws an exception if the icon isn't found 20 | } 21 | 22 | std::string troop_type::get_category_name() const 23 | { 24 | return translator::get()->translate(troop_category_to_string(this->get_category())); 25 | } 26 | 27 | const std::filesystem::path &troop_type::get_icon_path() const 28 | { 29 | std::string base_tag = this->get_icon_tag(); 30 | const std::filesystem::path &icon_path = database::get()->get_tagged_icon_path(base_tag); 31 | return icon_path; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /script/effect/holding_type_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "holding/holding_type.h" 4 | #include "script/effect/effect.h" 5 | #include "util/string_util.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | class holding_type_effect final : public effect 11 | { 12 | public: 13 | holding_type_effect(const std::string &value, const gsml_operator effect_operator) 14 | : effect(effect_operator) 15 | { 16 | this->holding_type = holding_type::get(value); 17 | } 18 | 19 | virtual const std::string &get_identifier() const override 20 | { 21 | static const std::string identifier = "holding_type"; 22 | return identifier; 23 | } 24 | 25 | virtual void do_assignment_effect(T *scope) const override 26 | { 27 | scope->set_type(this->holding_type); 28 | } 29 | 30 | virtual std::string get_assignment_string() const override 31 | { 32 | return "Set holding type to " + string::highlight(this->holding_type->get_name()); 33 | } 34 | 35 | private: 36 | holding_type *holding_type = nullptr; 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /script/effect/flags_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/effect/effect.h" 4 | #include "script/flag/scoped_flag.h" 5 | 6 | namespace metternich { 7 | 8 | class trait; 9 | 10 | template 11 | class flags_effect final : public effect 12 | { 13 | public: 14 | flags_effect(const std::string &flag_identifier, const gsml_operator effect_operator) 15 | : effect(effect_operator) 16 | { 17 | this->flag = scoped_flag::get_or_add(flag_identifier); 18 | } 19 | 20 | virtual const std::string &get_identifier() const override 21 | { 22 | static const std::string identifier = "flags"; 23 | return identifier; 24 | } 25 | 26 | virtual void do_addition_effect(T *scope) const override 27 | { 28 | scope->add_flag(this->flag); 29 | } 30 | 31 | virtual void do_subtraction_effect(T *scope) const override 32 | { 33 | scope->remove_flag(this->flag); 34 | } 35 | 36 | virtual bool is_hidden() const override 37 | { 38 | return true; 39 | } 40 | 41 | private: 42 | const scoped_flag *flag = nullptr; 43 | }; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /database/simple_data_type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/database.h" 4 | #include "database/data_type_base.h" 5 | #include "database/gsml_data.h" 6 | #include "database/gsml_parser.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace metternich { 13 | 14 | /** 15 | ** @brief The class for simple data types, which don't use identifiers 16 | */ 17 | template 18 | class simple_data_type : public data_type_base 19 | { 20 | public: 21 | /** 22 | ** @brief Parse the history database for the class 23 | */ 24 | static void parse_history_database() 25 | { 26 | if (std::string(T::database_folder).empty()) { 27 | return; 28 | } 29 | 30 | for (const std::filesystem::path &path : database::get()->get_history_paths()) { 31 | std::filesystem::path history_path(path / T::database_folder); 32 | 33 | if (!std::filesystem::exists(history_path)) { 34 | continue; 35 | } 36 | 37 | database::parse_folder(history_path, T::gsml_history_data_to_process); 38 | } 39 | } 40 | }; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /script/modifier_effect/levy_modifier_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/modifier_effect/modifier_effect.h" 4 | #include "util/number_util.h" 5 | #include "warfare/troop_type.h" 6 | 7 | namespace metternich { 8 | 9 | class troop_type; 10 | 11 | template 12 | class levy_modifier_effect final : public modifier_effect 13 | { 14 | public: 15 | levy_modifier_effect(troop_type *troop_type, const int levy) 16 | : troop_type(troop_type), levy(levy) 17 | { 18 | } 19 | 20 | virtual const std::string &get_identifier() const override 21 | { 22 | static const std::string identifier = "levy"; 23 | return identifier; 24 | } 25 | 26 | virtual void apply(T *scope, const int change) const override 27 | { 28 | scope->change_levy(this->troop_type, this->levy * change); 29 | } 30 | 31 | virtual std::string get_string() const override 32 | { 33 | return this->troop_type->get_name() + " Levy: " + number::to_signed_string(this->levy); 34 | } 35 | 36 | private: 37 | troop_type *troop_type = nullptr; 38 | int levy = 0; 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /culture/culture_group.cpp: -------------------------------------------------------------------------------- 1 | #include "culture/culture_group.h" 2 | 3 | #include "culture/culture_supergroup.h" 4 | 5 | namespace metternich { 6 | 7 | void culture_group::initialize() 8 | { 9 | if (this->get_supergroup() == nullptr) { 10 | throw std::runtime_error("Culture group \"" + this->get_identifier() + "\" has no culture supergroup."); 11 | } 12 | 13 | if (this->get_species() == nullptr) { 14 | this->set_species(this->get_supergroup()->get_species()); 15 | } 16 | 17 | if (this->get_default_phenotype() == nullptr) { 18 | this->set_default_phenotype(this->get_supergroup()->get_default_phenotype()); 19 | } 20 | 21 | if (!this->get_male_names().empty()) { 22 | this->get_supergroup()->add_male_names(this->get_male_names()); 23 | } 24 | 25 | if (!this->get_female_names().empty()) { 26 | this->get_supergroup()->add_female_names(this->get_female_names()); 27 | } 28 | 29 | if (!this->get_dynasty_names().empty()) { 30 | this->get_supergroup()->add_dynasty_names(this->get_dynasty_names()); 31 | } 32 | 33 | data_entry_base::initialize(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /database/gsml_property.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich { 7 | 8 | enum class gsml_operator; 9 | 10 | class gsml_property 11 | { 12 | public: 13 | gsml_property(std::string &&key, const gsml_operator property_operator, std::string &&value) 14 | : key(std::move(key)), property_operator(property_operator), value(std::move(value)) 15 | { 16 | } 17 | 18 | gsml_property(const std::string &key, const gsml_operator property_operator, const std::string &value) 19 | : key(key), property_operator(property_operator), value(value) 20 | { 21 | } 22 | 23 | const std::string &get_key() const 24 | { 25 | return this->key; 26 | } 27 | 28 | gsml_operator get_operator() const 29 | { 30 | return this->property_operator; 31 | } 32 | 33 | const std::string &get_value() const 34 | { 35 | return this->value; 36 | } 37 | 38 | void print(std::ofstream &ofstream, const size_t indentation) const; 39 | 40 | private: 41 | std::string key; 42 | gsml_operator property_operator; 43 | std::string value; 44 | }; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /religion/religion.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace metternich { 11 | 12 | class religion_group; 13 | 14 | class religion final : public data_entry, public data_type 15 | { 16 | Q_OBJECT 17 | 18 | Q_PROPERTY(metternich::religion_group* group MEMBER group READ get_group NOTIFY group_changed) 19 | Q_PROPERTY(QColor color MEMBER color READ get_color) 20 | 21 | public: 22 | religion(const std::string &identifier) : data_entry(identifier) {} 23 | 24 | static constexpr const char *class_identifier = "religion"; 25 | static constexpr const char *database_folder = "religions"; 26 | 27 | virtual void check() const override; 28 | 29 | religion_group *get_group() const 30 | { 31 | return this->group; 32 | } 33 | 34 | const QColor &get_color() const 35 | { 36 | return this->color; 37 | } 38 | 39 | signals: 40 | void group_changed(); 41 | 42 | private: 43 | religion_group *group = nullptr; 44 | QColor color; 45 | }; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /util/filesystem_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace metternich::filesystem { 9 | 10 | /** 11 | ** @brief Add the files in a directory to a checksum 12 | ** 13 | ** @param hash The checksum hash 14 | ** @param dir_path The path to the directory 15 | */ 16 | inline void add_files_to_checksum(QCryptographicHash &hash, const std::filesystem::path &dir_path) 17 | { 18 | std::filesystem::recursive_directory_iterator dir_iterator(dir_path); 19 | 20 | for (const std::filesystem::directory_entry &dir_entry : dir_iterator) { 21 | if (!dir_entry.is_regular_file()) { 22 | continue; 23 | } 24 | 25 | QFile file(QString::fromStdString(dir_entry.path().string())); 26 | 27 | if (!file.open(QIODevice::ReadOnly)) { 28 | throw std::runtime_error("Failed to open file: " + dir_entry.path().string() + "."); 29 | } 30 | 31 | if (!hash.addData(&file)) { 32 | throw std::runtime_error("Failed to hash file: " + dir_entry.path().string() + "."); 33 | } 34 | 35 | file.close(); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /script/decision/filter/decision_filter.cpp: -------------------------------------------------------------------------------- 1 | #include "script/decision/filter/decision_filter.h" 2 | 3 | #include "script/context.h" 4 | #include "script/decision/scoped_decision.h" 5 | #include "util/random.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | void decision_filter::do_ai_decisions(const std::vector &scopes, character *source_character) const 11 | { 12 | for (const auto *decision : this->decisions) { 13 | if (!decision->check_source_conditions(source_character)) { 14 | continue; 15 | } 16 | 17 | for (T *scope : scopes) { 18 | if (!decision->check_conditions(scope)) { 19 | continue; 20 | } 21 | 22 | if (random::generate(100) >= decision->calculate_ai_chance(scope, source_character)) { 23 | continue; 24 | } 25 | 26 | decision->do_effects(scope, source_character); 27 | 28 | //check if the source conditions are still valid after applying the effects 29 | if (!decision->check_source_conditions(source_character)) { 30 | break; 31 | } 32 | } 33 | } 34 | } 35 | 36 | template class decision_filter; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /script/province_modifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | #include "script/modifier.h" 6 | 7 | namespace metternich { 8 | 9 | class gsml_property; 10 | class province; 11 | 12 | class province_modifier final : public data_entry, public data_type, public modifier 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | static constexpr const char *class_identifier = "province_modifier"; 18 | static constexpr const char *database_folder = "province_modifiers"; 19 | 20 | public: 21 | province_modifier(const std::string &identifier) : data_entry(identifier) {} 22 | 23 | void process_gsml_property(const gsml_property &property) 24 | { 25 | modifier::process_gsml_property(property); 26 | } 27 | 28 | void process_gsml_scope(const gsml_data &scope) 29 | { 30 | modifier::process_gsml_scope(scope); 31 | } 32 | 33 | //to prevent ambiguity for name lookup between modifier::remove and data_type::remove 34 | void remove(province *province) const 35 | { 36 | this->modifier::remove(province); 37 | } 38 | }; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /database/defines.cpp: -------------------------------------------------------------------------------- 1 | #include "database/defines.h" 2 | 3 | #include "database/database.h" 4 | #include "database/gsml_data.h" 5 | #include "database/gsml_parser.h" 6 | #include "game/game_speed.h" 7 | #include "history/history.h" 8 | 9 | namespace metternich { 10 | 11 | defines::defines() : default_game_speed(game_speed::normal) 12 | { 13 | } 14 | 15 | void defines::load(const std::filesystem::path &data_path) 16 | { 17 | std::filesystem::path defines_path(data_path / "common" / "defines.txt"); 18 | 19 | if (!std::filesystem::exists(defines_path)) { 20 | return; 21 | } 22 | 23 | gsml_parser parser(defines_path); 24 | const gsml_data gsml_data = parser.parse(); 25 | 26 | gsml_data.for_each_property([&](const gsml_property &property) { 27 | this->process_gsml_property(property); 28 | }); 29 | } 30 | 31 | void defines::process_gsml_property(const gsml_property &property) 32 | { 33 | if (property.get_key() == "default_game_speed") { 34 | this->default_game_speed = string_to_game_speed(property.get_value()); 35 | } else { 36 | database::process_gsml_property_for_object(this, property); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /character/trait.cpp: -------------------------------------------------------------------------------- 1 | #include "character/trait.h" 2 | 3 | #include "script/modifier.h" 4 | #include "util/string_util.h" 5 | 6 | namespace metternich { 7 | 8 | trait::trait(const std::string &identifier) : data_entry(identifier) 9 | { 10 | } 11 | 12 | trait::~trait() 13 | { 14 | } 15 | 16 | void trait::process_gsml_scope(const gsml_data &scope) 17 | { 18 | const std::string &tag = scope.get_tag(); 19 | 20 | if (tag == "modifier") { 21 | this->modifier = std::make_unique>(); 22 | database::process_gsml_data(this->modifier, scope); 23 | } else { 24 | data_entry_base::process_gsml_scope(scope); 25 | } 26 | } 27 | 28 | const std::filesystem::path &trait::get_icon_path() const 29 | { 30 | std::string base_tag = this->get_icon_tag(); 31 | const std::filesystem::path &icon_path = database::get()->get_tagged_icon_path(base_tag); 32 | return icon_path; 33 | } 34 | 35 | QString trait::get_modifier_effects_string() const 36 | { 37 | if (this->get_modifier() == nullptr) { 38 | return QString(); 39 | } 40 | 41 | return string::to_tooltip(this->get_modifier()->get_string()); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /script/modifier_effect/troop_attack_modifier_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/modifier_effect/modifier_effect.h" 4 | #include "util/number_util.h" 5 | #include "warfare/troop_type.h" 6 | 7 | namespace metternich { 8 | 9 | class troop_type; 10 | 11 | template 12 | class troop_attack_modifier_effect final : public modifier_effect 13 | { 14 | public: 15 | troop_attack_modifier_effect(troop_type *troop_type, const int attack) 16 | : troop_type(troop_type), attack(attack) 17 | { 18 | } 19 | 20 | virtual const std::string &get_identifier() const override 21 | { 22 | static const std::string identifier = "troop_attack"; 23 | return identifier; 24 | } 25 | 26 | virtual void apply(T *scope, const int change) const override 27 | { 28 | scope->change_troop_attack_modifier(this->troop_type, this->attack * change); 29 | } 30 | 31 | virtual std::string get_string() const override 32 | { 33 | return this->troop_type->get_name() + " Attack: " + number::to_signed_centesimal_string(this->attack); 34 | } 35 | 36 | private: 37 | troop_type *troop_type = nullptr; 38 | int attack = 0; 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /character/enemy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | namespace metternich { 7 | 8 | class enemy final : public data_entry, public data_type 9 | { 10 | Q_OBJECT 11 | 12 | Q_PROPERTY(QString name_plural READ get_name_plural_qstring CONSTANT) 13 | Q_PROPERTY(int prowess MEMBER prowess READ get_prowess) 14 | 15 | public: 16 | static constexpr const char *class_identifier = "enemy"; 17 | static constexpr const char *database_folder = "enemies"; 18 | 19 | public: 20 | enemy(const std::string &identifier) : data_entry(identifier) {} 21 | 22 | virtual void check() const override 23 | { 24 | if (this->get_prowess() <= 0) { 25 | throw std::runtime_error("Enemy \"" + this->get_identifier() + "\" does not have a Prowess greater than 0."); 26 | } 27 | } 28 | 29 | std::string get_name_plural() const; 30 | 31 | QString get_name_plural_qstring() const 32 | { 33 | return QString::fromStdString(this->get_name_plural()); 34 | } 35 | 36 | int get_prowess() const 37 | { 38 | return this->prowess; 39 | } 40 | 41 | private: 42 | int prowess = 0; 43 | }; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2020 Andrettin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /script/modifier_effect/troop_defense_modifier_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/modifier_effect/modifier_effect.h" 4 | #include "util/number_util.h" 5 | #include "warfare/troop_type.h" 6 | 7 | namespace metternich { 8 | 9 | class troop_type; 10 | 11 | template 12 | class troop_defense_modifier_effect final : public modifier_effect 13 | { 14 | public: 15 | troop_defense_modifier_effect(troop_type *troop_type, const int defense) 16 | : troop_type(troop_type), defense(defense) 17 | { 18 | } 19 | 20 | virtual const std::string &get_identifier() const override 21 | { 22 | static const std::string identifier = "troop_defense"; 23 | return identifier; 24 | } 25 | 26 | virtual void apply(T *scope, const int change) const override 27 | { 28 | scope->change_troop_defense_modifier(this->troop_type, this->defense * change); 29 | } 30 | 31 | virtual std::string get_string() const override 32 | { 33 | return this->troop_type->get_name() + " Defense: " + number::to_signed_centesimal_string(this->defense); 34 | } 35 | 36 | private: 37 | troop_type *troop_type = nullptr; 38 | int defense = 0; 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /util/random.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | class random 10 | { 11 | public: 12 | template 13 | static T generate(const T modulo) 14 | { 15 | return random::generate_in_range(static_cast(0), modulo - static_cast(1)); 16 | } 17 | 18 | template 19 | static T generate_in_range(const T min_value, const T max_value) 20 | { 21 | if constexpr (std::is_integral_v) { 22 | std::uniform_int_distribution distribution(min_value, max_value); 23 | return distribution(random::engine); 24 | } else { 25 | std::uniform_real_distribution distribution(min_value, max_value); 26 | return distribution(random::engine); 27 | } 28 | } 29 | 30 | static double generate_degree_angle() 31 | { 32 | return random::generate(360.); 33 | } 34 | 35 | static double generate_radian_angle(); 36 | static QPointF generate_circle_position(); 37 | 38 | private: 39 | static inline std::random_device random_device = std::random_device(); 40 | static inline std::mt19937 engine = std::mt19937(random::random_device()); 41 | }; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /util/vector_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich::vector { 6 | 7 | template 8 | bool contains(const std::vector &vector, const U &value) 9 | { 10 | return std::find(vector.begin(), vector.end(), value) != vector.end(); 11 | } 12 | 13 | template 14 | void merge(std::vector &vector, const U &other_container) 15 | { 16 | for (const typename U::value_type &element : other_container) { 17 | vector.push_back(element); 18 | } 19 | } 20 | 21 | template 22 | void merge(std::vector &vector, U &&other_container) 23 | { 24 | for (typename U::value_type &element : other_container) { 25 | vector.push_back(std::move(element)); 26 | } 27 | } 28 | 29 | template 30 | inline void remove(T &vector, const typename T::value_type &element) 31 | { 32 | vector.erase(std::remove(vector.begin(), vector.end(), element), vector.end()); 33 | } 34 | 35 | template 36 | inline void remove_one(T &vector, const typename T::value_type &element) 37 | { 38 | vector.erase(std::find(vector.begin(), vector.end(), element)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /script/condition/location_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map/province.h" 4 | #include "script/condition/condition_check_base.h" 5 | #include "script/condition/scope_condition.h" 6 | #include "util/string_util.h" 7 | 8 | namespace metternich { 9 | 10 | class province; 11 | 12 | template 13 | class location_condition final : public scope_condition 14 | { 15 | public: 16 | location_condition(const gsml_operator effect_operator) : scope_condition(effect_operator) 17 | { 18 | } 19 | 20 | virtual const std::string &get_identifier() const override 21 | { 22 | static const std::string identifier = "location"; 23 | return identifier; 24 | } 25 | 26 | virtual province *get_scope(const T *scope) const override 27 | { 28 | return scope->get_location(); 29 | } 30 | 31 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 32 | { 33 | scope->connect(scope, &T::location_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 34 | 35 | scope_condition::bind_condition_check(check, scope); 36 | } 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /script/chance_factor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich { 7 | 8 | class character; 9 | class gsml_data; 10 | class gsml_property; 11 | class holding; 12 | class holding_slot; 13 | struct read_only_context; 14 | 15 | template 16 | class factor_modifier; 17 | 18 | /** 19 | ** @brief A chance factor, used e.g. for determining the probability of a settlement holding having a particular resource 20 | */ 21 | template 22 | class chance_factor 23 | { 24 | public: 25 | chance_factor(); 26 | chance_factor(const int factor); 27 | ~chance_factor(); 28 | 29 | void process_gsml_property(const gsml_property &property); 30 | void process_gsml_scope(const gsml_data &scope); 31 | 32 | int calculate(const T *scope, const read_only_context &ctx) const; 33 | 34 | private: 35 | int factor = 0; //the base factor for the random chance 36 | std::vector>> modifiers; //modifiers for the chance factor 37 | }; 38 | 39 | extern template class chance_factor; 40 | extern template class chance_factor; 41 | extern template class chance_factor; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /game/game_speed.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | enum class game_speed 6 | { 7 | slowest, 8 | slow, 9 | normal, 10 | fast, 11 | fastest 12 | }; 13 | 14 | inline game_speed string_to_game_speed(const std::string &str) 15 | { 16 | if (str == "slowest") { 17 | return game_speed::slowest; 18 | } else if (str == "slow") { 19 | return game_speed::slow; 20 | } else if (str == "normal") { 21 | return game_speed::normal; 22 | } else if (str == "fast") { 23 | return game_speed::fast; 24 | } else if (str == "fastest") { 25 | return game_speed::fastest; 26 | } 27 | 28 | throw std::runtime_error("Invalid game speed: \"" + str + "\"."); 29 | } 30 | 31 | inline std::string game_speed_to_string(const game_speed speed) 32 | { 33 | switch (speed) { 34 | case game_speed::slowest: 35 | return "slowest"; 36 | case game_speed::slow: 37 | return "slow"; 38 | case game_speed::normal: 39 | return "normal"; 40 | case game_speed::fast: 41 | return "fast"; 42 | case game_speed::fastest: 43 | return "fastest"; 44 | } 45 | 46 | throw std::runtime_error("Invalid game speed: \"" + std::to_string(static_cast(speed)) + "\"."); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /script/event/event_trigger.cpp: -------------------------------------------------------------------------------- 1 | #include "script/event/event_trigger.h" 2 | 3 | #include "script/context.h" 4 | #include "script/event/scoped_event_base.h" 5 | #include "util/vector_random_util.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | void event_trigger::do_events(T *scope, const context &ctx) const 11 | { 12 | for (const auto *event : this->events) { 13 | if (event->check_conditions(scope, ctx)) { 14 | event->do_event(scope, ctx); 15 | } 16 | } 17 | 18 | std::vector *> random_events; 19 | random_events.reserve(this->random_events.size()); 20 | for (const auto *event : this->random_events) { 21 | if (event->check_conditions(scope, ctx)) { 22 | random_events.push_back(event); 23 | } 24 | } 25 | if (!random_events.empty()) { 26 | vector::get_random(random_events)->do_event(scope, ctx); 27 | } 28 | } 29 | 30 | template 31 | void event_trigger::do_events(T *scope) const 32 | { 33 | context ctx; 34 | if constexpr (std::is_same_v) { 35 | ctx.current_character = scope; 36 | } 37 | this->do_events(scope, ctx); 38 | } 39 | 40 | template class event_trigger; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /script/modifier_effect/population_growth_modifier_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/modifier_effect/modifier_effect.h" 4 | #include "util/number_util.h" 5 | 6 | namespace metternich { 7 | 8 | template 9 | class population_growth_modifier_effect final : public modifier_effect 10 | { 11 | public: 12 | population_growth_modifier_effect(const int population_growth) 13 | : population_growth(population_growth) {} 14 | 15 | virtual const std::string &get_identifier() const override 16 | { 17 | static const std::string identifier = "population_growth"; 18 | return identifier; 19 | } 20 | 21 | virtual void apply(T *scope, const int change) const override 22 | { 23 | if constexpr (std::is_same_v) { 24 | scope->change_base_population_growth(this->population_growth * change); 25 | } else { 26 | scope->change_population_growth_modifier(this->population_growth * change); 27 | } 28 | } 29 | 30 | virtual std::string get_string() const override 31 | { 32 | return "Population Growth: " + number::to_signed_centesimal_string(this->population_growth) + "%"; 33 | } 34 | 35 | private: 36 | int population_growth = 0; 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /database/csv_data.cpp: -------------------------------------------------------------------------------- 1 | #include "database/csv_data.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich { 7 | 8 | csv_data csv_data::parse_file(const std::filesystem::path &filepath) 9 | { 10 | if (!std::filesystem::exists(filepath)) { 11 | throw std::runtime_error("File \"" + filepath.string() + "\" not found."); 12 | } 13 | 14 | std::ifstream ifstream(filepath); 15 | 16 | if (!ifstream) { 17 | throw std::runtime_error("Failed to open file: " + filepath.string()); 18 | } 19 | 20 | csv_data csv_data; 21 | 22 | std::string line; 23 | while (std::getline(ifstream, line)) { 24 | std::vector line_values; 25 | 26 | size_t token_pos = 0; 27 | size_t delimiter_pos = 0; 28 | while ((delimiter_pos = line.find(csv_data::delimiter, token_pos)) != std::string::npos) { 29 | std::string token = line.substr(token_pos, delimiter_pos - token_pos); 30 | line_values.push_back(token); 31 | token_pos = delimiter_pos + 1; 32 | } 33 | std::string token = line.substr(token_pos, line.length() - token_pos); 34 | line_values.push_back(token); 35 | 36 | csv_data.values.push_back(line_values); 37 | } 38 | 39 | return csv_data; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /map/province_profile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace metternich { 11 | 12 | class province; 13 | 14 | template 15 | class condition; 16 | 17 | class province_profile final : public data_entry, public data_type 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | static constexpr const char *class_identifier = "province_profile"; 23 | static constexpr const char *database_folder = "province_profiles"; 24 | 25 | static std::set get_database_dependencies(); 26 | 27 | public: 28 | province_profile(const std::string &identifier); 29 | virtual ~province_profile() override; 30 | 31 | virtual void process_gsml_scope(const gsml_data &scope) override; 32 | virtual void process_gsml_dated_property(const gsml_property &property, const QDateTime &date) override; 33 | virtual void process_gsml_dated_scope(const gsml_data &scope, const QDateTime &date) override; 34 | 35 | province *get_province(); 36 | 37 | private: 38 | province *province = nullptr; 39 | std::unique_ptr> conditions; 40 | }; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /history/history.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "util/singleton.h" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace metternich { 12 | 13 | class timeline; 14 | 15 | class history final : public singleton 16 | { 17 | public: 18 | static void generate_population_units(); 19 | static void generate_wildlife_units(); 20 | 21 | static QDateTime string_to_date(const std::string &date_str); 22 | 23 | public: 24 | void load(); 25 | 26 | bool is_loading() const 27 | { 28 | return this->loading; 29 | } 30 | 31 | const timeline *get_timeline() const 32 | { 33 | return this->timeline; 34 | } 35 | 36 | void set_timeline(const timeline *timeline) 37 | { 38 | this->timeline = timeline; 39 | } 40 | 41 | const QDateTime &get_start_date() const 42 | { 43 | return this->start_date; 44 | } 45 | 46 | void set_start_date(const QDateTime &date) 47 | { 48 | this->start_date = date; 49 | } 50 | 51 | bool contains_timeline_date(const timeline *timeline, const QDateTime &date) const; 52 | 53 | private: 54 | bool loading = false; 55 | const timeline *timeline = nullptr; 56 | QDateTime start_date; 57 | }; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /script/modifier_effect/population_capacity_modifier_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/modifier_effect/modifier_effect.h" 4 | #include "util/number_util.h" 5 | 6 | namespace metternich { 7 | 8 | template 9 | class population_capacity_modifier_effect final : public modifier_effect 10 | { 11 | public: 12 | population_capacity_modifier_effect(const int population_capacity) 13 | : population_capacity(population_capacity) {} 14 | 15 | virtual const std::string &get_identifier() const override 16 | { 17 | static const std::string identifier = "population_capacity"; 18 | return identifier; 19 | } 20 | 21 | virtual void apply(T *scope, const int change) const override 22 | { 23 | if constexpr (std::is_same_v) { 24 | scope->change_base_population_capacity(this->population_capacity * change); 25 | } else { 26 | scope->change_population_capacity_additive_modifier(this->population_capacity * change); 27 | } 28 | } 29 | 30 | virtual std::string get_string() const override 31 | { 32 | return "Population Capacity: " + number::to_signed_string(this->population_capacity); 33 | } 34 | 35 | private: 36 | int population_capacity = 0; 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /script/event/event_option.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich { 7 | 8 | class character; 9 | class gsml_data; 10 | class gsml_property; 11 | struct context; 12 | struct read_only_context; 13 | 14 | template 15 | class chance_factor; 16 | 17 | template 18 | class effect; 19 | 20 | template 21 | class effect_list; 22 | 23 | template 24 | class event_option 25 | { 26 | public: 27 | event_option(); 28 | ~event_option(); 29 | 30 | void process_gsml_property(const gsml_property &property); 31 | void process_gsml_scope(const gsml_data &scope); 32 | 33 | std::string get_name() const; 34 | 35 | const chance_factor *get_ai_chance_factor() const 36 | { 37 | return this->ai_chance.get(); 38 | } 39 | 40 | void do_effects(T *scope, const context &ctx) const; 41 | std::string get_effects_string(const T *scope, const read_only_context &ctx) const; 42 | 43 | private: 44 | std::string name_tag; 45 | std::unique_ptr> ai_chance; //the chance of the option being picked by the AI 46 | std::unique_ptr> effects; 47 | }; 48 | 49 | extern template class event_option; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /script/modifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich { 7 | 8 | class character; 9 | class gsml_data; 10 | class gsml_property; 11 | class holding; 12 | class province; 13 | class territory; 14 | 15 | template 16 | class modifier_effect; 17 | 18 | /** 19 | ** @brief A modifier (i.e. a collection of modifier effects) 20 | */ 21 | template 22 | class modifier 23 | { 24 | public: 25 | modifier(); 26 | virtual ~modifier(); 27 | 28 | void process_gsml_property(const gsml_property &property); 29 | 30 | void process_gsml_scope(const gsml_data &scope) 31 | { 32 | Q_UNUSED(scope) 33 | } 34 | 35 | void apply(T *scope, const int multiplier = 1) const; 36 | void remove(T *scope, const int multiplier = 1) const; 37 | std::string get_string(const size_t indent = 0) const; 38 | 39 | private: 40 | void add_modifier_effect(std::unique_ptr> &&modifier_effect); 41 | 42 | private: 43 | std::vector>> modifier_effects; 44 | }; 45 | 46 | extern template class modifier; 47 | extern template class modifier; 48 | extern template class modifier; 49 | extern template class modifier; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /character/dynasty.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | #include 7 | 8 | namespace metternich { 9 | 10 | class culture; 11 | 12 | class dynasty final : public data_entry, public data_type 13 | { 14 | Q_OBJECT 15 | 16 | Q_PROPERTY(metternich::culture* culture MEMBER culture READ get_culture) 17 | 18 | public: 19 | dynasty(const std::string &identifier) : data_entry(identifier) {} 20 | 21 | static constexpr const char *class_identifier = "dynasty"; 22 | static constexpr const char *database_folder = "dynasties"; 23 | 24 | static dynasty *generate(culture *culture); 25 | 26 | virtual void initialize() override; 27 | 28 | virtual std::string get_name() const override 29 | { 30 | if (!this->name.empty()) { 31 | return this->name; 32 | } 33 | 34 | return data_entry::get_name(); 35 | } 36 | 37 | void set_name(const std::string &name) 38 | { 39 | if (name == this->name) { 40 | return; 41 | } 42 | 43 | this->name = name; 44 | emit name_changed(); 45 | } 46 | 47 | metternich::culture *get_culture() const 48 | { 49 | return this->culture; 50 | } 51 | 52 | private: 53 | std::string name; 54 | metternich::culture *culture = nullptr; 55 | }; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /script/condition/has_flag_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/condition/condition.h" 4 | #include "script/condition/condition_check_base.h" 5 | #include "script/flag/scoped_flag.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | class has_flag_condition final : public condition 11 | { 12 | public: 13 | has_flag_condition(const std::string &flag_identifier, const gsml_operator effect_operator) 14 | : condition(effect_operator) 15 | { 16 | this->flag = scoped_flag::get_or_add(flag_identifier); 17 | } 18 | 19 | virtual const std::string &get_identifier() const override 20 | { 21 | static const std::string identifier = "has_flag"; 22 | return identifier; 23 | } 24 | 25 | virtual bool check_assignment(const T *scope) const override 26 | { 27 | return scope->has_flag(this->flag); 28 | } 29 | 30 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 31 | { 32 | scope->connect(scope, &T::flags_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 33 | } 34 | 35 | virtual bool is_hidden() const override 36 | { 37 | return true; 38 | } 39 | 40 | private: 41 | const scoped_flag *flag = nullptr; 42 | }; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /util/rect_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich::rect { 7 | 8 | template 9 | inline void for_each_perimeter_point(const QRect &rect, const function_type &function) 10 | { 11 | //call a function for each point in the rect's perimeter 12 | for (int x = rect.x(); x <= rect.right(); ++x) { 13 | function(QPoint(x, rect.y())); 14 | function(QPoint(x, rect.bottom())); 15 | } 16 | 17 | for (int y = rect.y(); y <= rect.bottom(); ++y) { 18 | function(QPoint(rect.x(), y)); 19 | function(QPoint(rect.right(), y)); 20 | } 21 | } 22 | 23 | template 24 | inline void for_each_perimeter_point_until(const QRect &rect, const function_type &function) 25 | { 26 | //call a function for each point in the rect's perimeter, until it returns true 27 | for (int x = rect.x(); x <= rect.right(); ++x) { 28 | if (function(QPoint(x, rect.y()))) { 29 | return; 30 | } 31 | 32 | if (function(QPoint(x, rect.bottom()))) { 33 | return; 34 | } 35 | } 36 | 37 | for (int y = rect.y(); y <= rect.bottom(); ++y) { 38 | if (function(QPoint(rect.x(), y))) { 39 | return; 40 | } 41 | 42 | if (function(QPoint(rect.right(), y))) { 43 | return; 44 | } 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /script/effect/items_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "character/item.h" 4 | #include "script/effect/effect.h" 5 | #include "util/string_util.h" 6 | 7 | namespace metternich { 8 | 9 | class item; 10 | 11 | template 12 | class items_effect final : public effect 13 | { 14 | public: 15 | items_effect(const std::string &item_identifier, const gsml_operator effect_operator) 16 | : effect(effect_operator) 17 | { 18 | this->item = item::get(item_identifier); 19 | } 20 | 21 | virtual const std::string &get_identifier() const override 22 | { 23 | static const std::string identifier = "items"; 24 | return identifier; 25 | } 26 | 27 | virtual void do_addition_effect(T *scope) const override 28 | { 29 | scope->add_item(this->item); 30 | } 31 | 32 | virtual void do_subtraction_effect(T *scope) const override 33 | { 34 | scope->remove_item(this->item); 35 | } 36 | 37 | virtual std::string get_addition_string() const override 38 | { 39 | return "Gain the " + string::highlight(this->item->get_name()) + " item"; 40 | } 41 | 42 | virtual std::string get_subtraction_string() const override 43 | { 44 | return "Lose the " + string::highlight(this->item->get_name()) + " item"; 45 | } 46 | 47 | private: 48 | item *item = nullptr; 49 | }; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /character/item.cpp: -------------------------------------------------------------------------------- 1 | #include "character/item.h" 2 | 3 | #include "script/modifier.h" 4 | #include "util/string_util.h" 5 | #include "util/translator.h" 6 | 7 | namespace metternich { 8 | 9 | item::item(const std::string &identifier) : data_entry(identifier) 10 | { 11 | } 12 | 13 | item::~item() 14 | { 15 | } 16 | 17 | void item::process_gsml_scope(const gsml_data &scope) 18 | { 19 | const std::string &tag = scope.get_tag(); 20 | 21 | if (tag == "modifier") { 22 | this->modifier = std::make_unique>(); 23 | database::process_gsml_data(this->modifier, scope); 24 | } else { 25 | data_entry_base::process_gsml_scope(scope); 26 | } 27 | } 28 | 29 | std::string item::get_description() const 30 | { 31 | return translator::get()->translate(this->get_identifier() + "_desc"); 32 | } 33 | 34 | const std::filesystem::path &item::get_icon_path() const 35 | { 36 | std::string base_tag = this->get_icon_tag(); 37 | const std::filesystem::path &icon_path = database::get()->get_tagged_icon_path(base_tag); 38 | return icon_path; 39 | } 40 | 41 | QString item::get_modifier_effects_string() const 42 | { 43 | if (this->get_modifier() == nullptr) { 44 | return QString(); 45 | } 46 | 47 | return string::to_tooltip(this->get_modifier()->get_string()); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /character/dynasty.cpp: -------------------------------------------------------------------------------- 1 | #include "character/dynasty.h" 2 | 3 | #include "culture/culture.h" 4 | #include "culture/culture_group.h" 5 | #include "culture/culture_supergroup.h" 6 | #include "history/history.h" 7 | 8 | namespace metternich { 9 | 10 | dynasty *dynasty::generate(metternich::culture *culture) 11 | { 12 | if (culture == nullptr) { 13 | throw std::runtime_error("Tried to generate a dynasty with no culture."); 14 | } 15 | 16 | const std::string identifier = dynasty::generate_identifier(); 17 | dynasty *dynasty = dynasty::add(identifier); 18 | dynasty->name = culture->generate_dynasty_name(); 19 | dynasty->culture = culture; 20 | 21 | return dynasty; 22 | } 23 | 24 | void dynasty::initialize() 25 | { 26 | if (this->get_culture() != nullptr) { 27 | if (!this->get_culture()->is_initialized()) { 28 | this->get_culture()->initialize(); //ensure the culture and its culture group are initialized, so that they don't add the dynasty name upwards again during initialization 29 | } 30 | 31 | const std::string name = this->get_name(); 32 | this->get_culture()->add_dynasty_name(name); 33 | this->get_culture()->get_group()->add_dynasty_name(name); 34 | this->get_culture()->get_supergroup()->add_dynasty_name(name); 35 | } 36 | 37 | data_entry_base::initialize(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /script/effect/scripted_effect_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/gsml_data.h" 4 | #include "database/gsml_property.h" 5 | #include "script/effect/effect.h" 6 | #include "script/effect/scripted_effect.h" 7 | 8 | namespace metternich { 9 | 10 | template 11 | class scripted_effect_effect final : public effect 12 | { 13 | public: 14 | scripted_effect_effect(const std::string &effect_identifier, const gsml_operator effect_operator) 15 | : effect(effect_operator) 16 | { 17 | if constexpr (std::is_same_v) { 18 | this->scripted_effect = character_scripted_effect::get(effect_identifier); 19 | } 20 | } 21 | 22 | virtual const std::string &get_identifier() const override 23 | { 24 | static const std::string identifier = "scripted_effect"; 25 | return identifier; 26 | } 27 | 28 | virtual void do_assignment_effect(T *scope, const context &ctx) const override 29 | { 30 | this->scripted_effect->do_effects(scope, ctx); 31 | } 32 | 33 | virtual std::string get_assignment_string(const T *scope, const read_only_context &ctx, const size_t indent) const override 34 | { 35 | return this->scripted_effect->get_effects_string(scope, ctx, indent); 36 | } 37 | 38 | private: 39 | const scripted_effect *scripted_effect = nullptr; 40 | }; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /script/effect/traits_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "character/trait.h" 4 | #include "script/effect/effect.h" 5 | #include "util/string_util.h" 6 | 7 | namespace metternich { 8 | 9 | class trait; 10 | 11 | template 12 | class traits_effect final : public effect 13 | { 14 | public: 15 | traits_effect(const std::string &trait_identifier, const gsml_operator effect_operator) 16 | : effect(effect_operator) 17 | { 18 | this->trait = trait::get(trait_identifier); 19 | } 20 | 21 | virtual const std::string &get_identifier() const override 22 | { 23 | static const std::string identifier = "traits"; 24 | return identifier; 25 | } 26 | 27 | virtual void do_addition_effect(T *scope) const override 28 | { 29 | scope->add_trait(this->trait); 30 | } 31 | 32 | virtual void do_subtraction_effect(T *scope) const override 33 | { 34 | scope->remove_trait(this->trait); 35 | } 36 | 37 | virtual std::string get_addition_string() const override 38 | { 39 | return "Gain the " + string::highlight(this->trait->get_name()) + " trait"; 40 | } 41 | 42 | virtual std::string get_subtraction_string() const override 43 | { 44 | return "Lose the " + string::highlight(this->trait->get_name()) + " trait"; 45 | } 46 | 47 | private: 48 | trait *trait = nullptr; 49 | }; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /script/modifier_effect/population_capacity_modifier_modifier_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/modifier_effect/modifier_effect.h" 4 | #include "util/number_util.h" 5 | 6 | namespace metternich { 7 | 8 | template 9 | class population_capacity_modifier_modifier_effect final : public modifier_effect 10 | { 11 | public: 12 | population_capacity_modifier_modifier_effect(const int population_capacity_modifier) 13 | : population_capacity_modifier(population_capacity_modifier) {} 14 | 15 | virtual const std::string &get_identifier() const override 16 | { 17 | static const std::string identifier = "population_capacity_modifier"; 18 | return identifier; 19 | } 20 | 21 | virtual void apply(T *scope, const int change) const override 22 | { 23 | if constexpr (std::is_same_v) { 24 | scope->change_population_capacity_modifier(this->population_capacity_modifier * change); 25 | } else { 26 | scope->change_population_capacity_modifier(this->population_capacity_modifier * change); 27 | } 28 | } 29 | 30 | virtual std::string get_string() const override 31 | { 32 | return "Population Capacity Modifier: " + number::to_signed_string(this->population_capacity_modifier) + "%"; 33 | } 34 | 35 | private: 36 | int population_capacity_modifier = 0; 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /util/container_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace metternich::container { 9 | 10 | template 11 | inline QVariantList to_qvariant_list(const T &container) 12 | { 13 | QVariantList list; 14 | 15 | for (const typename T::value_type &element : container) { 16 | list.append(QVariant::fromValue(element)); 17 | } 18 | 19 | return list; 20 | } 21 | 22 | template 23 | inline QObjectList to_qobject_list(const T &container) 24 | { 25 | QObjectList object_list; 26 | for (QObject *element : container) { 27 | object_list.append(element); 28 | } 29 | return object_list; 30 | } 31 | 32 | template 33 | inline std::set to_set(const T &container) 34 | { 35 | std::set set; 36 | 37 | for (const typename T::value_type &element : container) { 38 | set.insert(element); 39 | } 40 | 41 | return set; 42 | } 43 | 44 | template 45 | inline std::vector to_vector(const T &container) 46 | { 47 | std::vector vector; 48 | vector.reserve(container.size()); 49 | 50 | for (const typename T::value_type &element : container) { 51 | vector.push_back(element); 52 | } 53 | 54 | return vector; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /politics/government_type_group.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | enum class government_type_group 6 | { 7 | monarchy, 8 | republic, 9 | theocracy, 10 | tribe 11 | }; 12 | 13 | inline government_type_group string_to_government_type_group(const std::string &str) 14 | { 15 | if (str == "monarchy") { 16 | return government_type_group::monarchy; 17 | } else if (str == "republic") { 18 | return government_type_group::republic; 19 | } else if (str == "theocracy") { 20 | return government_type_group::theocracy; 21 | } else if (str == "tribe") { 22 | return government_type_group::tribe; 23 | } 24 | 25 | throw std::runtime_error("Invalid government type group: \"" + str + "\"."); 26 | } 27 | 28 | inline std::string government_type_group_to_string(const government_type_group group) 29 | { 30 | switch (group) { 31 | case government_type_group::monarchy: 32 | return "monarchy"; 33 | case government_type_group::republic: 34 | return "republic"; 35 | case government_type_group::theocracy: 36 | return "theocracy"; 37 | case government_type_group::tribe: 38 | return "tribe"; 39 | } 40 | 41 | throw std::runtime_error("Invalid government type group: \"" + std::to_string(static_cast(group)) + "\"."); 42 | } 43 | 44 | } 45 | 46 | Q_DECLARE_METATYPE(metternich::government_type_group) 47 | -------------------------------------------------------------------------------- /script/condition/region_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map/province.h" 4 | #include "map/region.h" 5 | #include "script/condition/condition.h" 6 | #include "script/scope_util.h" 7 | 8 | namespace metternich { 9 | 10 | class region; 11 | 12 | template 13 | class region_condition final : public condition 14 | { 15 | public: 16 | region_condition(const std::string ®ion_identifier, const gsml_operator effect_operator) 17 | : condition(effect_operator) 18 | { 19 | this->region = region::get(region_identifier); 20 | } 21 | 22 | virtual const std::string &get_identifier() const override 23 | { 24 | static const std::string identifier = "region"; 25 | return identifier; 26 | } 27 | 28 | virtual bool check_assignment(const T *scope) const override 29 | { 30 | const territory *territory = get_scope_territory(scope); 31 | return territory != nullptr && territory->is_in_region(this->region); 32 | } 33 | 34 | virtual std::string get_assignment_string() const override 35 | { 36 | return this->get_equality_string(); 37 | } 38 | 39 | virtual std::string get_equality_string() const override 40 | { 41 | return "Is in the " + this->region->get_name() + " region"; 42 | } 43 | 44 | virtual std::string get_inequality_string() const override 45 | { 46 | return "Is not in the " + this->region->get_name() + " region"; 47 | } 48 | 49 | private: 50 | region *region = nullptr; 51 | }; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /script/condition/condition_check_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | class condition_check_base 6 | { 7 | public: 8 | static void recalculate_pending_checks() 9 | { 10 | for (condition_check_base *check : condition_check_base::checks_to_recalculate) { 11 | check->calculate_result(); 12 | check->result_recalculation_needed = false; 13 | } 14 | 15 | condition_check_base::checks_to_recalculate.clear(); 16 | } 17 | 18 | private: 19 | static inline std::set checks_to_recalculate; 20 | 21 | protected: 22 | condition_check_base(const std::function &result_setter) : result_setter(result_setter) 23 | { 24 | } 25 | 26 | virtual ~condition_check_base() 27 | { 28 | if (condition_check_base::checks_to_recalculate.contains(this)) { 29 | condition_check_base::checks_to_recalculate.erase(this); 30 | } 31 | } 32 | 33 | public: 34 | void set_result(const bool result) 35 | { 36 | this->result_setter(result); 37 | } 38 | 39 | void set_result_recalculation_needed() 40 | { 41 | if (this->result_recalculation_needed) { 42 | return; 43 | } 44 | 45 | this->result_recalculation_needed = true; 46 | condition_check_base::checks_to_recalculate.insert(this); 47 | } 48 | 49 | virtual void calculate_result() = 0; 50 | 51 | private: 52 | std::function result_setter; //setter for the result 53 | bool result_recalculation_needed = false; 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /script/factor_modifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace metternich { 7 | 8 | class character; 9 | class gsml_data; 10 | class gsml_property; 11 | class holding; 12 | class holding_slot; 13 | class province; 14 | struct read_only_context; 15 | 16 | template 17 | class and_condition; 18 | 19 | /** 20 | ** @brief A modifier for a factor, e.g. a random chance, weight or mean-time-to-happen 21 | */ 22 | template 23 | class factor_modifier 24 | { 25 | public: 26 | factor_modifier(); 27 | ~factor_modifier(); 28 | 29 | void process_gsml_property(const gsml_property &property); 30 | void process_gsml_scope(const gsml_data &scope); 31 | 32 | int get_factor() const 33 | { 34 | return this->factor; 35 | } 36 | 37 | bool is_additive() const 38 | { 39 | return this->additive; 40 | } 41 | 42 | bool check_conditions(const T *scope, const read_only_context &ctx) const; 43 | 44 | private: 45 | int factor = 0; //the factor of the modifier itself 46 | bool additive = false; //whether the modifier is additive instead of multiplicative 47 | std::unique_ptr> conditions; //conditions for whether the modifier is to be applied 48 | }; 49 | 50 | extern template class factor_modifier; 51 | extern template class factor_modifier; 52 | extern template class factor_modifier; 53 | extern template class factor_modifier; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /holding/holding_type.cpp: -------------------------------------------------------------------------------- 1 | #include "holding/holding_type.h" 2 | 3 | #include "database/gsml_data.h" 4 | #include "politics/law.h" 5 | #include "script/modifier.h" 6 | #include "util/container_util.h" 7 | #include "util/map_util.h" 8 | 9 | namespace metternich { 10 | 11 | std::set holding_type::get_database_dependencies() 12 | { 13 | return { 14 | //so that laws will have their groups when added to the default laws map 15 | law::class_identifier 16 | }; 17 | } 18 | 19 | holding_type::holding_type(const std::string &identifier) : data_entry(identifier) 20 | { 21 | } 22 | 23 | holding_type::~holding_type() 24 | { 25 | } 26 | 27 | void holding_type::process_gsml_scope(const gsml_data &scope) 28 | { 29 | const std::string &tag = scope.get_tag(); 30 | 31 | if (tag == "modifier") { 32 | this->modifier = std::make_unique>(); 33 | database::process_gsml_data(this->modifier, scope); 34 | } else { 35 | data_entry_base::process_gsml_scope(scope); 36 | } 37 | } 38 | 39 | QVariantList holding_type::get_default_laws_qvariant_list() const 40 | { 41 | return container::to_qvariant_list(map_container::get_values(this->default_laws)); 42 | } 43 | 44 | Q_INVOKABLE void holding_type::add_default_law(law *law) 45 | { 46 | this->default_laws[law->get_group()] = law; 47 | } 48 | 49 | Q_INVOKABLE void holding_type::remove_default_law(law *law) 50 | { 51 | this->default_laws.erase(law->get_group()); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /script/decision/filter/decision_filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/identifiable_type.h" 4 | 5 | namespace metternich { 6 | 7 | class character; 8 | class holding; 9 | struct context; 10 | 11 | template 12 | class scoped_decision; 13 | 14 | class decision_filter_base 15 | { 16 | public: 17 | decision_filter_base(const std::string &identifier) : identifier(identifier) 18 | { 19 | } 20 | 21 | const std::string &get_identifier() const 22 | { 23 | return this->identifier; 24 | } 25 | 26 | private: 27 | std::string identifier; 28 | }; 29 | 30 | template 31 | class decision_filter : public decision_filter_base, public identifiable_type> 32 | { 33 | public: 34 | static constexpr const char *class_identifier = "event_trigger"; 35 | 36 | decision_filter(const std::string &identifier) : decision_filter_base(identifier) 37 | { 38 | } 39 | 40 | void add_decision(const scoped_decision *decision) 41 | { 42 | this->decisions.push_back(decision); 43 | } 44 | 45 | void do_ai_decisions(const std::vector &scopes, character *source_character) const; 46 | 47 | private: 48 | std::vector *> decisions; 49 | }; 50 | 51 | extern template class decision_filter; 52 | 53 | class holding_decision_filter final : public decision_filter 54 | { 55 | public: 56 | static inline const decision_filter *owned = decision_filter::add("owned"); 57 | }; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /script/chance_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/chance_factor.h" 4 | #include "script/context.h" 5 | #include "util/random.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace metternich { 11 | 12 | template 13 | class chance_factor; 14 | 15 | template 16 | inline T calculate_chance_list_result(const std::map *> &chance_map, V *scope) 17 | { 18 | std::map> chance_ranges; 19 | 20 | read_only_context ctx; 21 | if constexpr (std::is_same_v) { 22 | ctx.current_character = scope; 23 | } 24 | 25 | int total_chance_factor = 0; 26 | for (const auto &kv_pair : chance_map) { 27 | const chance_factor *chance_factor = kv_pair.second; 28 | const int chance = chance_factor->calculate(scope, ctx); 29 | if (chance > 0) { 30 | chance_ranges[kv_pair.first] = std::pair(total_chance_factor, total_chance_factor + chance); 31 | total_chance_factor += chance; 32 | } 33 | } 34 | 35 | const int random_number = random::generate(total_chance_factor); 36 | for (const auto &kv_pair : chance_ranges) { 37 | const T &value = kv_pair.first; 38 | const std::pair range = kv_pair.second; 39 | if (random_number >= range.first && random_number < range.second) { 40 | return value; 41 | } 42 | } 43 | 44 | throw std::runtime_error("No valid chance value when calculating the result of a chance list."); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /technology/technology_category.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich { 6 | 7 | enum class technology_category 8 | { 9 | none, 10 | army, 11 | commerce, 12 | culture, 13 | industry, 14 | navy 15 | }; 16 | 17 | inline technology_category string_to_technology_category(const std::string &str) 18 | { 19 | if (str == "army") { 20 | return technology_category::army; 21 | } else if (str == "commerce") { 22 | return technology_category::commerce; 23 | } else if (str == "culture") { 24 | return technology_category::culture; 25 | } else if (str == "industry") { 26 | return technology_category::industry; 27 | } else if (str == "navy") { 28 | return technology_category::navy; 29 | } 30 | 31 | throw std::runtime_error("Invalid technology category: \"" + str + "\"."); 32 | } 33 | 34 | inline std::string technology_category_to_string(const technology_category category) 35 | { 36 | switch (category) { 37 | case technology_category::army: 38 | return "army"; 39 | case technology_category::commerce: 40 | return "commerce"; 41 | case technology_category::culture: 42 | return "culture"; 43 | case technology_category::industry: 44 | return "industry"; 45 | case technology_category::navy: 46 | return "navy"; 47 | default: 48 | break; 49 | } 50 | 51 | throw std::runtime_error("Invalid technology category: \"" + std::to_string(static_cast(category)) + "\"."); 52 | } 53 | 54 | } 55 | 56 | Q_DECLARE_METATYPE(metternich::technology_category) 57 | -------------------------------------------------------------------------------- /map/world_type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | namespace metternich { 7 | 8 | class world_type final : public data_entry, public data_type 9 | { 10 | Q_OBJECT 11 | 12 | Q_PROPERTY(QString texture_tag READ get_texture_tag_qstring WRITE set_texture_tag_qstring) 13 | Q_PROPERTY(bool star MEMBER star READ is_star) 14 | 15 | public: 16 | static constexpr const char *class_identifier = "world_type"; 17 | static constexpr const char *database_folder = "world_types"; 18 | 19 | world_type(const std::string &identifier) : data_entry(identifier) 20 | { 21 | } 22 | 23 | const std::string &get_texture_tag() const 24 | { 25 | if (this->texture_tag.empty()) { 26 | return this->get_identifier(); 27 | } 28 | 29 | return this->texture_tag; 30 | } 31 | 32 | void set_texture_tag(const std::string &texture_tag) 33 | { 34 | if (texture_tag == this->get_texture_tag()) { 35 | return; 36 | } 37 | 38 | this->texture_tag = texture_tag; 39 | } 40 | 41 | QString get_texture_tag_qstring() const 42 | { 43 | return QString::fromStdString(this->get_texture_tag()); 44 | } 45 | 46 | void set_texture_tag_qstring(const QString &texture_tag) 47 | { 48 | this->set_texture_tag(texture_tag.toStdString()); 49 | } 50 | 51 | const std::filesystem::path &get_texture_path() const; 52 | 53 | bool is_star() const 54 | { 55 | return this->star; 56 | } 57 | 58 | private: 59 | std::string texture_tag; 60 | bool star = false; 61 | }; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /script/effect/tooltip_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/database.h" 4 | #include "database/gsml_data.h" 5 | #include "database/gsml_property.h" 6 | #include "script/effect/effect.h" 7 | #include "script/effect/effect_list.h" 8 | #include "util/translator.h" 9 | 10 | namespace metternich { 11 | 12 | //a scripted effect which displays a custom tooltip for the effects it encloses 13 | template 14 | class tooltip_effect final : public effect 15 | { 16 | public: 17 | tooltip_effect(const gsml_operator effect_operator) : effect(effect_operator) 18 | { 19 | } 20 | 21 | virtual const std::string &get_identifier() const override 22 | { 23 | static const std::string identifier = "tooltip"; 24 | return identifier; 25 | } 26 | 27 | virtual void process_gsml_property(const gsml_property &property) override 28 | { 29 | if (property.get_key() == "text") { 30 | this->text = property.get_value(); 31 | } else { 32 | this->effects.process_gsml_property(property); 33 | } 34 | } 35 | 36 | virtual void process_gsml_scope(const gsml_data &scope) override 37 | { 38 | this->effects.process_gsml_scope(scope); 39 | } 40 | 41 | virtual void do_assignment_effect(T *scope, const context &ctx) const override 42 | { 43 | this->effects.do_effects(scope, ctx); 44 | } 45 | 46 | virtual std::string get_assignment_string() const override 47 | { 48 | return translator::get()->translate(this->text); 49 | } 50 | 51 | private: 52 | std::string text; 53 | effect_list effects; 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /script/event/scoped_event_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace metternich { 8 | 9 | class character; 10 | class gsml_data; 11 | class gsml_property; 12 | struct context; 13 | struct read_only_context; 14 | 15 | template 16 | class condition; 17 | 18 | template 19 | class effect; 20 | 21 | template 22 | class effect_list; 23 | 24 | template 25 | class event_option; 26 | 27 | template 28 | class event_trigger; 29 | 30 | template 31 | class scoped_event_base 32 | { 33 | public: 34 | scoped_event_base(); 35 | virtual ~scoped_event_base(); 36 | 37 | void initialize(); 38 | 39 | void process_gsml_property(const gsml_property &property); 40 | void process_gsml_scope(const gsml_data &scope); 41 | 42 | virtual const std::string &get_tag() const = 0; 43 | std::string get_title() const; 44 | std::string get_description() const; 45 | 46 | bool check_conditions(const T *scope, const read_only_context &ctx) const; 47 | void do_event(T *scope, const context &ctx) const; 48 | void pick_option(T *scope, const context &ctx) const; 49 | 50 | private: 51 | std::set *> triggers; 52 | bool random = false; 53 | bool hidden = false; 54 | std::unique_ptr> conditions; 55 | std::unique_ptr> immediate_effects; 56 | std::vector>> options; 57 | }; 58 | 59 | extern template class scoped_event_base; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /script/condition/coastal_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map/province.h" 4 | #include "script/condition/condition.h" 5 | #include "script/scope_util.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | class coastal_condition final : public condition 11 | { 12 | public: 13 | coastal_condition(const bool coastal, const gsml_operator effect_operator) 14 | : condition(effect_operator), coastal(coastal) 15 | { 16 | } 17 | 18 | virtual const std::string &get_identifier() const override 19 | { 20 | static const std::string identifier = "coastal"; 21 | return identifier; 22 | } 23 | 24 | virtual bool check_assignment(const T *scope) const override 25 | { 26 | return this->check_equality(scope); 27 | } 28 | 29 | virtual bool check_equality(const T *scope) const override 30 | { 31 | const province *province = get_scope_province(scope); 32 | return province != nullptr && province->is_coastal() == this->coastal; 33 | } 34 | 35 | virtual std::string get_assignment_string() const override 36 | { 37 | return this->get_equality_string(); 38 | } 39 | 40 | virtual std::string get_equality_string() const override 41 | { 42 | if (this->coastal) { 43 | return "Coastal"; 44 | } else { 45 | return "Not coastal"; 46 | } 47 | } 48 | 49 | virtual std::string get_inequality_string() const override 50 | { 51 | if (!this->coastal) { 52 | return "Coastal"; 53 | } else { 54 | return "Not coastal"; 55 | } 56 | } 57 | 58 | private: 59 | bool coastal = false; 60 | }; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /script/condition/has_law_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "politics/law.h" 4 | #include "script/condition/condition.h" 5 | #include "script/condition/condition_check_base.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | class has_law_condition final : public condition 11 | { 12 | public: 13 | has_law_condition(const std::string &law_identifier, const gsml_operator effect_operator) 14 | : condition(effect_operator) 15 | { 16 | this->law = law::get(law_identifier); 17 | } 18 | 19 | virtual const std::string &get_identifier() const override 20 | { 21 | static const std::string identifier = "has_law"; 22 | return identifier; 23 | } 24 | 25 | virtual bool check_assignment(const T *scope) const override 26 | { 27 | return scope->has_law(this->law); 28 | } 29 | 30 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 31 | { 32 | scope->connect(scope, &T::laws_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 33 | } 34 | 35 | virtual std::string get_assignment_string() const override 36 | { 37 | return this->get_equality_string(); 38 | } 39 | 40 | virtual std::string get_equality_string() const override 41 | { 42 | return "Has the " + this->law->get_name() + " law"; 43 | } 44 | 45 | virtual std::string get_inequality_string() const override 46 | { 47 | return "Does not have the " + this->law->get_name() + " law"; 48 | } 49 | 50 | private: 51 | law *law = nullptr; 52 | }; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /script/effect/event_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/context.h" 4 | #include "script/effect/effect.h" 5 | #include "script/event/character_event.h" 6 | #include "util/string_util.h" 7 | 8 | #include 9 | 10 | namespace metternich { 11 | 12 | class character; 13 | class event; 14 | 15 | template 16 | class event_effect final : public effect 17 | { 18 | public: 19 | event_effect(const std::string &event_identifier, const gsml_operator effect_operator) 20 | : effect(effect_operator) 21 | { 22 | if constexpr (std::is_same_v) { 23 | this->event = character_event::get(event_identifier); 24 | } 25 | } 26 | 27 | virtual const std::string &get_identifier() const override 28 | { 29 | static const std::string identifier = "event"; 30 | return identifier; 31 | } 32 | 33 | virtual void do_assignment_effect(T *scope, const context &ctx) const override 34 | { 35 | context new_ctx; 36 | new_ctx.source_character = ctx.current_character; 37 | 38 | if constexpr (std::is_same_v) { 39 | new_ctx.current_character = scope; 40 | const character_event *event = static_cast(this->event); 41 | if (event->check_conditions(scope, ctx)) { 42 | event->do_event(scope, new_ctx); 43 | } 44 | } 45 | } 46 | 47 | virtual std::string get_assignment_string() const override 48 | { 49 | return "Receive the " + string::highlight(this->event->get_name()) + " event"; 50 | } 51 | 52 | private: 53 | const event *event = nullptr; 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /script/effect/wealth_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/effect/effect.h" 4 | #include "util/number_util.h" 5 | #include "util/parse_util.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | class wealth_effect final : public effect 11 | { 12 | public: 13 | wealth_effect(const std::string &value, const gsml_operator effect_operator) 14 | : effect(effect_operator) 15 | { 16 | this->wealth = parse::centesimal_number_string_to_int(value); 17 | } 18 | 19 | virtual const std::string &get_identifier() const override 20 | { 21 | static const std::string identifier = "wealth"; 22 | return identifier; 23 | } 24 | 25 | virtual void do_assignment_effect(T *scope) const override 26 | { 27 | scope->set_wealth(this->wealth); 28 | } 29 | 30 | virtual void do_addition_effect(T *scope) const override 31 | { 32 | scope->change_wealth(this->wealth); 33 | } 34 | 35 | virtual void do_subtraction_effect(T *scope) const override 36 | { 37 | scope->change_wealth(-this->wealth); 38 | } 39 | 40 | virtual std::string get_assignment_string() const override 41 | { 42 | return "Set Wealth to " + number::to_centesimal_string(this->wealth); 43 | } 44 | 45 | virtual std::string get_addition_string() const override 46 | { 47 | return number::to_signed_centesimal_string(this->wealth) + " Wealth"; 48 | } 49 | 50 | virtual std::string get_subtraction_string() const override 51 | { 52 | return number::to_signed_centesimal_string(-this->wealth) + " Wealth"; 53 | } 54 | 55 | private: 56 | int wealth = 0; 57 | }; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /script/condition/hidden_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/condition/and_condition.h" 4 | #include "script/condition/condition.h" 5 | #include "script/condition/condition_check_base.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | class hidden_condition final : public condition 11 | { 12 | public: 13 | hidden_condition(const gsml_operator effect_operator = gsml_operator::assignment) : condition(effect_operator) 14 | { 15 | } 16 | 17 | virtual const std::string &get_identifier() const override 18 | { 19 | static const std::string identifier = "hidden"; 20 | return identifier; 21 | } 22 | 23 | virtual void process_gsml_property(const gsml_property &property) override 24 | { 25 | this->conditions.process_gsml_property(property); 26 | } 27 | 28 | virtual void process_gsml_scope(const gsml_data &scope) override 29 | { 30 | this->conditions.process_gsml_scope(scope); 31 | } 32 | 33 | void add_condition(std::unique_ptr> &&condition) 34 | { 35 | this->conditions.add_condition(std::move(condition)); 36 | } 37 | 38 | virtual bool check_assignment(const T *scope, const read_only_context &ctx) const override 39 | { 40 | return this->conditions.check(scope, ctx); 41 | } 42 | 43 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 44 | { 45 | this->conditions.bind_condition_check(check, scope); 46 | } 47 | 48 | virtual bool is_hidden() const override 49 | { 50 | return true; 51 | } 52 | 53 | private: 54 | and_condition conditions; 55 | }; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | namespace std { 5 | template 6 | using result_of = invoke_result; 7 | } 8 | 9 | #include "maskedmousearea/maskedmousearea.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | -------------------------------------------------------------------------------- /script/condition/has_item_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "character/item.h" 4 | #include "script/condition/condition.h" 5 | #include "script/condition/condition_check_base.h" 6 | 7 | namespace metternich { 8 | 9 | class item; 10 | 11 | template 12 | class has_item_condition final : public condition 13 | { 14 | public: 15 | has_item_condition(const std::string &item_identifier, const gsml_operator effect_operator) 16 | : condition(effect_operator) 17 | { 18 | this->item = item::get(item_identifier); 19 | } 20 | 21 | virtual const std::string &get_identifier() const override 22 | { 23 | static const std::string identifier = "has_item"; 24 | return identifier; 25 | } 26 | 27 | virtual bool check_assignment(const T *scope) const override 28 | { 29 | return scope->has_item(this->item); 30 | } 31 | 32 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 33 | { 34 | scope->connect(scope, &T::items_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 35 | } 36 | 37 | virtual std::string get_assignment_string() const override 38 | { 39 | return this->get_equality_string(); 40 | } 41 | 42 | virtual std::string get_equality_string() const override 43 | { 44 | return "Has the " + this->item->get_name() + " item"; 45 | } 46 | 47 | virtual std::string get_inequality_string() const override 48 | { 49 | return "Does not have the " + this->item->get_name() + " item"; 50 | } 51 | 52 | private: 53 | const item *item = nullptr; 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /technology/technology_area.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | namespace metternich { 7 | 8 | class technology; 9 | enum class technology_category; 10 | 11 | class technology_area final : public data_entry, public data_type 12 | { 13 | Q_OBJECT 14 | 15 | Q_PROPERTY(metternich::technology_category category MEMBER category READ get_category) 16 | Q_PROPERTY(QString category_name READ get_category_name_qstring CONSTANT) 17 | Q_PROPERTY(QVariantList technologies READ get_technologies_qvariant_list CONSTANT) 18 | 19 | public: 20 | static constexpr const char *class_identifier = "technology_area"; 21 | static constexpr const char *database_folder = "technology_areas"; 22 | 23 | static std::vector get_all_sorted(); 24 | 25 | technology_area(const std::string &identifier); 26 | 27 | virtual void check() const override; 28 | 29 | technology_category get_category() const 30 | { 31 | return this->category; 32 | } 33 | 34 | std::string get_category_name() const; 35 | 36 | QString get_category_name_qstring() const 37 | { 38 | return QString::fromStdString(this->get_category_name()); 39 | } 40 | 41 | QVariantList get_technologies_qvariant_list() const; 42 | 43 | void add_technology(technology *technology) 44 | { 45 | this->technologies.push_back(technology); 46 | } 47 | 48 | void remove_technology(technology *technology); 49 | 50 | int get_min_level() const; 51 | 52 | private: 53 | technology_category category; 54 | std::vector technologies; 55 | }; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /util/translator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "util/singleton.h" 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace metternich { 14 | 15 | class translator final : public QTranslator, public singleton 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | const std::string &get_locale() const 21 | { 22 | return this->locale; 23 | } 24 | 25 | void set_locale(const std::string &locale) 26 | { 27 | this->locale = locale; 28 | } 29 | 30 | void load(); 31 | void load_file(const std::filesystem::path &filepath); 32 | std::string translate(const std::vector &base_tags, const std::vector> &suffix_list_with_fallbacks = std::vector>(), const std::string &final_suffix = std::string()) const; 33 | 34 | std::string translate(const std::string &base_tag, const std::vector> &suffix_list_with_fallbacks = std::vector>()) const 35 | { 36 | return this->translate(std::vector{base_tag}, suffix_list_with_fallbacks); 37 | } 38 | 39 | virtual QString translate(const char *context, const char *source_text, const char *disambiguation = nullptr, int n = -1) const override; 40 | 41 | private: 42 | void add_translation(const std::string &source_text, const std::string &translation) 43 | { 44 | this->translations[source_text] = translation; 45 | } 46 | 47 | private: 48 | std::map translations; 49 | std::string locale; 50 | }; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /script/holding_modifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | #include "script/modifier.h" 6 | 7 | namespace metternich { 8 | 9 | class gsml_property; 10 | class holding; 11 | 12 | class holding_modifier final : public data_entry, public data_type, public modifier 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | static constexpr const char *class_identifier = "holding_modifier"; 18 | static constexpr const char *database_folder = "holding_modifiers"; 19 | 20 | static void initialize_all() 21 | { 22 | data_type::initialize_all(); 23 | 24 | //store pointers to the hardcoded modifiers 25 | holding_modifier::overpopulation_modifier = holding_modifier::get("overpopulation"); 26 | } 27 | 28 | static holding_modifier *get_overpopulation_modifier() 29 | { 30 | return holding_modifier::overpopulation_modifier; 31 | } 32 | 33 | private: 34 | static inline holding_modifier *overpopulation_modifier = nullptr; 35 | 36 | public: 37 | holding_modifier(const std::string &identifier) : data_entry(identifier) {} 38 | 39 | virtual void process_gsml_property(const gsml_property &property) override 40 | { 41 | modifier::process_gsml_property(property); 42 | } 43 | 44 | virtual void process_gsml_scope(const gsml_data &scope) override 45 | { 46 | modifier::process_gsml_scope(scope); 47 | } 48 | 49 | //to prevent ambiguity for name lookup between modifier::remove and data_type::remove 50 | void remove(holding *holding) const 51 | { 52 | this->modifier::remove(holding); 53 | } 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /script/condition/alive_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/condition/condition.h" 4 | #include "script/condition/condition_check_base.h" 5 | 6 | namespace metternich { 7 | 8 | template 9 | class alive_condition final : public condition 10 | { 11 | public: 12 | alive_condition(const bool alive, const gsml_operator effect_operator) : condition(effect_operator), alive(alive) 13 | { 14 | } 15 | 16 | virtual const std::string &get_identifier() const override 17 | { 18 | static const std::string identifier = "alive"; 19 | return identifier; 20 | } 21 | 22 | virtual bool check_assignment(const T *scope) const override 23 | { 24 | return this->check_equality(scope); 25 | } 26 | 27 | virtual bool check_equality(const T *scope) const override 28 | { 29 | return scope->is_alive() == this->alive; 30 | } 31 | 32 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 33 | { 34 | scope->connect(scope, &T::alive_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 35 | } 36 | 37 | virtual std::string get_assignment_string() const override 38 | { 39 | return this->get_equality_string(); 40 | } 41 | 42 | virtual std::string get_equality_string() const override 43 | { 44 | return "Is " + std::string(this->alive ? "" : "not") + " alive"; 45 | } 46 | 47 | virtual std::string get_inequality_string() const override 48 | { 49 | return "Is " + std::string(!this->alive ? "" : "not") + " alive"; 50 | } 51 | 52 | private: 53 | bool alive = true; 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /script/condition/has_trait_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "character/trait.h" 4 | #include "script/condition/condition.h" 5 | #include "script/condition/condition_check_base.h" 6 | 7 | namespace metternich { 8 | 9 | class trait; 10 | 11 | template 12 | class has_trait_condition final : public condition 13 | { 14 | public: 15 | has_trait_condition(const std::string &trait_identifier, const gsml_operator effect_operator) 16 | : condition(effect_operator) 17 | { 18 | this->trait = trait::get(trait_identifier); 19 | } 20 | 21 | virtual const std::string &get_identifier() const override 22 | { 23 | static const std::string identifier = "trait"; 24 | return identifier; 25 | } 26 | 27 | virtual bool check_assignment(const T *scope) const override 28 | { 29 | return scope->has_trait(this->trait); 30 | } 31 | 32 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 33 | { 34 | scope->connect(scope, &T::traits_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 35 | } 36 | 37 | virtual std::string get_assignment_string() const override 38 | { 39 | return this->get_equality_string(); 40 | } 41 | 42 | virtual std::string get_equality_string() const override 43 | { 44 | return "Has the " + this->trait->get_name() + " trait"; 45 | } 46 | 47 | virtual std::string get_inequality_string() const override 48 | { 49 | return "Does not have the " + this->trait->get_name() + " trait"; 50 | } 51 | 52 | private: 53 | const trait *trait = nullptr; 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /script/effect/for_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/gsml_data.h" 4 | #include "database/gsml_property.h" 5 | #include "script/effect/effect.h" 6 | #include "script/effect/effect_list.h" 7 | 8 | namespace metternich { 9 | 10 | template 11 | class for_effect final : public effect 12 | { 13 | public: 14 | for_effect(const gsml_operator effect_operator) : effect(effect_operator) 15 | { 16 | } 17 | 18 | virtual const std::string &get_identifier() const override 19 | { 20 | static const std::string identifier = "for"; 21 | return identifier; 22 | } 23 | 24 | virtual void process_gsml_property(const gsml_property &property) override 25 | { 26 | if (property.get_key() == "count") { 27 | this->count = std::stoi(property.get_value()); 28 | } else { 29 | this->effects.process_gsml_property(property); 30 | } 31 | } 32 | 33 | virtual void process_gsml_scope(const gsml_data &scope) override 34 | { 35 | this->effects.process_gsml_scope(scope); 36 | } 37 | 38 | virtual void do_assignment_effect(T *scope, const context &ctx) const override 39 | { 40 | for (int i = 0; i < this->count; ++i) { 41 | this->effects.do_effects(scope, ctx); 42 | } 43 | } 44 | 45 | virtual std::string get_assignment_string(const T *scope, const read_only_context &ctx, const size_t indent) const override 46 | { 47 | std::string str = "This will occur " + std::to_string(this->count) + " times:\n"; 48 | str += this->effects.get_effects_string(scope, ctx, indent + 1); 49 | return str; 50 | } 51 | 52 | private: 53 | int count = 0; 54 | effect_list effects; 55 | }; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /script/condition/has_technology_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/gsml_operator.h" 4 | #include "script/condition/condition.h" 5 | 6 | namespace metternich { 7 | 8 | class technology; 9 | 10 | template 11 | class has_technology_condition final : public condition 12 | { 13 | public: 14 | has_technology_condition(const std::string &technology_identifier, const gsml_operator effect_operator); 15 | 16 | has_technology_condition(technology *technology, const gsml_operator effect_operator = gsml_operator::assignment) : condition(effect_operator), technology(technology) 17 | { 18 | } 19 | 20 | virtual const std::string &get_identifier() const override 21 | { 22 | static const std::string identifier = "has_technology"; 23 | return identifier; 24 | } 25 | 26 | virtual bool check_assignment(const T *scope) const override; 27 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override; 28 | 29 | virtual std::string get_assignment_string() const override 30 | { 31 | return this->get_equality_string(); 32 | } 33 | 34 | virtual std::string get_equality_string() const override; 35 | virtual std::string get_inequality_string() const override; 36 | 37 | private: 38 | technology *technology = nullptr; 39 | }; 40 | 41 | extern template class has_technology_condition; 42 | extern template class has_technology_condition; 43 | extern template class has_technology_condition; 44 | extern template class has_technology_condition; 45 | extern template class has_technology_condition; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /util/parse_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich::parse { 6 | 7 | /** 8 | ** @brief Convert a fractional number string (i.e. a number with up to two decimal places) to an integer, multiplying it by 10 ^ the number of decimal places; the template argument is the number of decimal places 9 | ** 10 | ** @param str The string 11 | ** 12 | ** @return The integer 13 | */ 14 | template 15 | inline int fractional_number_string_to_int(const std::string &str) 16 | { 17 | size_t decimal_point_pos = str.find('.'); 18 | int integer = 0; 19 | int fraction = 0; 20 | if (decimal_point_pos != std::string::npos) { 21 | integer = std::stoi(str.substr(0, decimal_point_pos)); 22 | const size_t decimal_pos = decimal_point_pos + 1; 23 | const size_t decimal_places = str.length() - decimal_pos; 24 | fraction = std::stoi(str.substr(decimal_pos, decimal_places)); 25 | if (decimal_places < N) { 26 | for (int i = static_cast(decimal_places); i < N; ++i) { 27 | fraction *= 10; 28 | } 29 | } 30 | const bool negative = str.front() == '-'; 31 | if (negative) { 32 | fraction *= -1; 33 | } 34 | } else { 35 | integer = std::stoi(str); 36 | } 37 | 38 | for (int i = 0; i < N; ++i) { 39 | integer *= 10; 40 | } 41 | integer += fraction; 42 | 43 | return integer; 44 | } 45 | 46 | inline int centesimal_number_string_to_int(const std::string &str) 47 | { 48 | return fractional_number_string_to_int<2>(str); 49 | } 50 | 51 | inline int millesimal_number_string_to_int(const std::string &str) 52 | { 53 | return fractional_number_string_to_int<3>(str); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /script/event/character_event.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_type.h" 4 | #include "script/event/event.h" 5 | #include "script/event/scoped_event_base.h" 6 | 7 | namespace metternich { 8 | 9 | class character; 10 | 11 | class character_event final : public event, public data_type, public scoped_event_base 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | static constexpr const char *class_identifier = "character_event"; 17 | static constexpr const char *database_base_folder = "events"; 18 | static constexpr const char *database_folder = "character_events"; 19 | 20 | character_event(const std::string &identifier) : event(identifier) {} 21 | 22 | virtual void initialize() override 23 | { 24 | scoped_event_base::initialize(); 25 | } 26 | 27 | virtual void process_gsml_property(const gsml_property &property) override 28 | { 29 | const std::string &key = property.get_key(); 30 | 31 | if (key == "triggers" || key == "random" || key == "hidden") { 32 | scoped_event_base::process_gsml_property(property); 33 | } else { 34 | data_entry_base::process_gsml_property(property); 35 | } 36 | } 37 | 38 | virtual void process_gsml_scope(const gsml_data &scope) override 39 | { 40 | const std::string &tag = scope.get_tag(); 41 | 42 | if (tag == "conditions" || tag == "immediate_effects" || tag == "option") { 43 | scoped_event_base::process_gsml_scope(scope); 44 | } else { 45 | data_entry_base::process_gsml_scope(scope); 46 | } 47 | } 48 | 49 | virtual const std::string &get_tag() const override 50 | { 51 | return this->get_identifier(); 52 | } 53 | }; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /script/condition/condition_check.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/condition/condition.h" 4 | #include "script/condition/condition_check_base.h" 5 | #include "script/context.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | class condition; 11 | 12 | /** 13 | ** @brief A check for a scripted condition 14 | */ 15 | template 16 | class condition_check final : public condition_check_base 17 | { 18 | public: 19 | condition_check(const metternich::condition *condition, const T *checked_instance, const std::function &result_setter) 20 | : condition_check_base(result_setter), condition(condition), checked_instance(checked_instance) 21 | { 22 | if (this->get_condition() != nullptr) { 23 | this->get_condition()->bind_condition_check(*this, this->checked_instance); 24 | } 25 | 26 | this->calculate_result(); //calculate initial result 27 | } 28 | 29 | virtual ~condition_check() override {} 30 | 31 | virtual void calculate_result() override 32 | { 33 | if (this->get_condition() != nullptr) { 34 | read_only_context ctx; 35 | 36 | if constexpr (std::is_same_v) { 37 | ctx.current_character = this->checked_instance; 38 | } 39 | 40 | this->set_result(this->get_condition()->check(this->checked_instance, ctx)); 41 | } else { 42 | this->set_result(true); //always true if there are no conditions 43 | } 44 | } 45 | 46 | private: 47 | const condition *get_condition() const 48 | { 49 | return this->condition; 50 | } 51 | 52 | private: 53 | const condition *condition = nullptr; 54 | const T *checked_instance = nullptr; 55 | }; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /script/condition/borders_water_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map/province.h" 4 | #include "script/condition/condition.h" 5 | #include "script/scope_util.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | class borders_water_condition final : public condition 11 | { 12 | public: 13 | borders_water_condition(const bool borders_water, const gsml_operator effect_operator) 14 | : condition(effect_operator), borders_water(borders_water) 15 | { 16 | } 17 | 18 | virtual const std::string &get_identifier() const override 19 | { 20 | static const std::string identifier = "borders_water"; 21 | return identifier; 22 | } 23 | 24 | virtual bool check_assignment(const T *scope) const override 25 | { 26 | return this->check_equality(scope); 27 | } 28 | 29 | virtual bool check_equality(const T *scope) const override 30 | { 31 | const province *province = get_scope_province(scope); 32 | return province != nullptr && province->borders_water() == this->borders_water; 33 | } 34 | 35 | virtual std::string get_assignment_string() const override 36 | { 37 | return this->get_equality_string(); 38 | } 39 | 40 | virtual std::string get_equality_string() const override 41 | { 42 | if (this->borders_water) { 43 | return "Borders water"; 44 | } else { 45 | return "Does not border water"; 46 | } 47 | } 48 | 49 | virtual std::string get_inequality_string() const override 50 | { 51 | if (!this->borders_water) { 52 | return "Borders water"; 53 | } else { 54 | return "Does not border water"; 55 | } 56 | } 57 | 58 | private: 59 | bool borders_water = false; 60 | }; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /script/event/event_instance.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "util/qunique_ptr.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace metternich { 13 | 14 | class event_option_instance; 15 | 16 | //an instance of an event to be shown to the player 17 | class event_instance final : public QObject 18 | { 19 | Q_OBJECT 20 | 21 | Q_PROPERTY(QString name MEMBER name CONSTANT) 22 | Q_PROPERTY(QString description MEMBER description CONSTANT) 23 | Q_PROPERTY(QVariantList options READ get_options CONSTANT) 24 | 25 | public: 26 | event_instance(const QString &name, const QString &description, std::vector> &&options); 27 | ~event_instance(); 28 | 29 | QVariantList get_options() const; 30 | 31 | private: 32 | QString name; 33 | QString description; 34 | std::vector> options; 35 | }; 36 | 37 | //an instance of an event option to be shown to the player 38 | class event_option_instance final : public QObject 39 | { 40 | Q_OBJECT 41 | 42 | Q_PROPERTY(QString name MEMBER name CONSTANT) 43 | Q_PROPERTY(QString effects_string MEMBER effects_string CONSTANT) 44 | 45 | public: 46 | event_option_instance(const QString &name, const QString &effects_string, const std::function &option_effects) 47 | : name(name), effects_string(effects_string), option_effects(option_effects) 48 | { 49 | } 50 | 51 | Q_INVOKABLE void do_effects() const; 52 | 53 | private: 54 | QString name; 55 | QString effects_string; 56 | std::function option_effects; 57 | }; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /script/condition/has_any_trade_route_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map/province.h" 4 | #include "script/condition/condition.h" 5 | #include "script/scope_util.h" 6 | 7 | namespace metternich { 8 | 9 | template 10 | class has_any_trade_route_condition final : public condition 11 | { 12 | public: 13 | has_any_trade_route_condition(const bool has_any_trade_route, const gsml_operator effect_operator) 14 | : condition(effect_operator), has_any_trade_route(has_any_trade_route) 15 | { 16 | } 17 | 18 | virtual const std::string &get_identifier() const override 19 | { 20 | static const std::string identifier = "has_any_trade_route"; 21 | return identifier; 22 | } 23 | 24 | virtual bool check_assignment(const T *scope) const override 25 | { 26 | return this->check_equality(scope); 27 | } 28 | 29 | virtual bool check_equality(const T *scope) const override 30 | { 31 | return scope->has_any_trade_route() == this->has_any_trade_route; 32 | } 33 | 34 | virtual std::string get_assignment_string() const override 35 | { 36 | return this->get_equality_string(); 37 | } 38 | 39 | virtual std::string get_equality_string() const override 40 | { 41 | if (this->has_any_trade_route) { 42 | return "Has any trade route"; 43 | } else { 44 | return "Does have any trade route"; 45 | } 46 | } 47 | 48 | virtual std::string get_inequality_string() const override 49 | { 50 | if (!this->has_any_trade_route) { 51 | return "Has any trade route"; 52 | } else { 53 | return "Does have any trade route"; 54 | } 55 | } 56 | 57 | private: 58 | bool has_any_trade_route = false; 59 | }; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /script/condition/has_building_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "holding/building.h" 4 | #include "holding/holding.h" 5 | #include "script/condition/condition.h" 6 | #include "script/condition/condition_check_base.h" 7 | 8 | namespace metternich { 9 | 10 | template 11 | class has_building_condition final : public condition 12 | { 13 | public: 14 | has_building_condition(const std::string &building_identifier, const gsml_operator effect_operator) 15 | : condition(effect_operator) 16 | { 17 | this->building = building::get(building_identifier); 18 | } 19 | 20 | virtual const std::string &get_identifier() const override 21 | { 22 | static const std::string identifier = "has_building"; 23 | return identifier; 24 | } 25 | 26 | virtual bool check_assignment(const T *scope) const override 27 | { 28 | return scope->has_building(this->building); 29 | } 30 | 31 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 32 | { 33 | scope->connect(scope, &T::buildings_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 34 | } 35 | 36 | virtual std::string get_assignment_string() const override 37 | { 38 | return this->get_equality_string(); 39 | } 40 | 41 | virtual std::string get_equality_string() const override 42 | { 43 | return "Has the " + this->building->get_name() + " building"; 44 | } 45 | 46 | virtual std::string get_inequality_string() const override 47 | { 48 | return "Does not have the " + this->building->get_name() + " building"; 49 | } 50 | 51 | private: 52 | building *building = nullptr; 53 | }; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /script/condition/ai_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/condition/condition.h" 4 | #include "script/condition/condition_check_base.h" 5 | 6 | namespace metternich { 7 | 8 | template 9 | class ai_condition final : public condition 10 | { 11 | public: 12 | ai_condition(const bool ai, const gsml_operator effect_operator) : condition(effect_operator), ai(ai) 13 | { 14 | } 15 | 16 | virtual const std::string &get_identifier() const override 17 | { 18 | static const std::string identifier = "ai"; 19 | return identifier; 20 | } 21 | 22 | virtual bool check_assignment(const T *scope) const override 23 | { 24 | return this->check_equality(scope); 25 | } 26 | 27 | virtual bool check_equality(const T *scope) const override 28 | { 29 | return scope->is_ai() == this->ai; 30 | } 31 | 32 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 33 | { 34 | scope->connect(scope, &T::ai_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 35 | } 36 | 37 | virtual std::string get_assignment_string() const override 38 | { 39 | return this->get_equality_string(); 40 | } 41 | 42 | virtual std::string get_equality_string() const override 43 | { 44 | return "Is " + std::string(this->ai ? "" : "not") + " AI-controlled"; 45 | } 46 | 47 | virtual std::string get_inequality_string() const override 48 | { 49 | return "Is " + std::string(!this->ai ? "" : "not") + " AI-controlled"; 50 | } 51 | 52 | virtual bool is_hidden() const override 53 | { 54 | return true; 55 | } 56 | 57 | private: 58 | bool ai = true; 59 | }; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /third_party/maskedmousearea/LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | Copyright (C) 2017 The Qt Company Ltd. 4 | Contact: https://www.qt.io/licensing/ 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the 14 | distribution. 15 | * Neither the name of The Qt Company Ltd nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /map/terrain_type.cpp: -------------------------------------------------------------------------------- 1 | #include "map/terrain_type.h" 2 | 3 | #include "database/gsml_data.h" 4 | #include "game/engine_interface.h" 5 | #include "script/modifier.h" 6 | #include "util/geocoordinate_util.h" 7 | #include "util/point_util.h" 8 | 9 | namespace metternich { 10 | 11 | terrain_type *terrain_type::get_by_rgb(const QRgb &rgb, const bool should_find) 12 | { 13 | if (rgb == terrain_type::empty_rgb) { 14 | return nullptr; 15 | } 16 | 17 | typename std::map::const_iterator find_iterator = terrain_type::instances_by_rgb.find(rgb); 18 | 19 | if (find_iterator != terrain_type::instances_by_rgb.end()) { 20 | return find_iterator->second; 21 | } 22 | 23 | if (should_find) { 24 | throw std::runtime_error("No terrain found for RGB value: " + std::to_string(rgb) + "."); 25 | } 26 | 27 | return nullptr; 28 | } 29 | 30 | terrain_type::terrain_type(const std::string &identifier) : data_entry(identifier) 31 | { 32 | } 33 | 34 | terrain_type::~terrain_type() 35 | { 36 | } 37 | 38 | void terrain_type::process_gsml_scope(const gsml_data &scope) 39 | { 40 | const std::string &tag = scope.get_tag(); 41 | 42 | if (tag == "color") { 43 | this->color = scope.to_color(); 44 | terrain_type::instances_by_rgb[this->color.rgb()] = this; 45 | } else if (tag == "holding_modifier") { 46 | this->holding_modifier = std::make_unique>(); 47 | database::process_gsml_data(this->holding_modifier, scope); 48 | } else if (tag == "province_modifier") { 49 | this->province_modifier = std::make_unique>(); 50 | database::process_gsml_data(this->province_modifier, scope); 51 | } else { 52 | data_entry_base::process_gsml_scope(scope); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /species/wildlife_unit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/simple_data_type.h" 4 | #include "population/population_unit_base.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace metternich { 11 | 12 | class species; 13 | 14 | class wildlife_unit final : public population_unit_base, public simple_data_type 15 | { 16 | Q_OBJECT 17 | 18 | Q_PROPERTY(metternich::species* species MEMBER species READ get_species NOTIFY species_changed) 19 | Q_PROPERTY(int biomass READ get_biomass NOTIFY biomass_changed) 20 | 21 | public: 22 | static constexpr const char *database_folder = "wildlife_units"; 23 | 24 | static void process_history_database(); 25 | 26 | wildlife_unit(species *species) : species(species) 27 | { 28 | connect(this, &wildlife_unit::species_changed, this, &population_unit_base::icon_path_changed); 29 | connect(this, &wildlife_unit::size_changed, this, &wildlife_unit::biomass_changed); 30 | } 31 | 32 | void do_month(); 33 | 34 | species *get_species() const 35 | { 36 | return this->species; 37 | } 38 | 39 | int get_biomass() const; 40 | 41 | void subtract_existing_sizes(); 42 | void subtract_existing_sizes_in_province(const metternich::province *province); 43 | void subtract_existing_sizes_in_provinces(const std::set &provinces); 44 | bool can_distribute_to_province(const metternich::province *province) const; 45 | void distribute_to_provinces(const std::set &provinces); 46 | 47 | virtual const std::filesystem::path &get_icon_path() const override; 48 | 49 | signals: 50 | void species_changed(); 51 | void biomass_changed(); 52 | 53 | private: 54 | species *species = nullptr; 55 | }; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /script/effect/if_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/database.h" 4 | #include "database/gsml_data.h" 5 | #include "database/gsml_property.h" 6 | #include "script/condition/and_condition.h" 7 | #include "script/effect/effect.h" 8 | #include "script/effect/effect_list.h" 9 | 10 | namespace metternich { 11 | 12 | template 13 | class if_effect final : public effect 14 | { 15 | public: 16 | if_effect(const gsml_operator effect_operator) : effect(effect_operator) 17 | { 18 | } 19 | 20 | virtual const std::string &get_identifier() const override 21 | { 22 | static const std::string identifier = "if"; 23 | return identifier; 24 | } 25 | 26 | virtual void process_gsml_property(const gsml_property &property) override 27 | { 28 | this->effects.process_gsml_property(property); 29 | } 30 | 31 | virtual void process_gsml_scope(const gsml_data &scope) override 32 | { 33 | if (scope.get_tag() == "conditions") { 34 | database::process_gsml_data(this->conditions, scope); 35 | } else { 36 | this->effects.process_gsml_scope(scope); 37 | } 38 | } 39 | 40 | virtual void do_assignment_effect(T *scope, const context &ctx) const override 41 | { 42 | if (!this->conditions.check(scope, ctx)) { 43 | return; 44 | } 45 | 46 | this->effects.do_effects(scope, ctx); 47 | } 48 | 49 | virtual std::string get_assignment_string(const T *scope, const read_only_context &ctx, const size_t indent) const override 50 | { 51 | if (!this->conditions.check(scope, ctx)) { 52 | return std::string(); 53 | } 54 | 55 | return this->effects.get_effects_string(scope, ctx, indent); 56 | } 57 | 58 | private: 59 | and_condition conditions; 60 | effect_list effects; 61 | }; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /script/condition/culture_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "culture/culture.h" 4 | #include "script/condition/condition.h" 5 | #include "script/condition/condition_check_base.h" 6 | 7 | namespace metternich { 8 | 9 | class culture; 10 | 11 | template 12 | class culture_condition final : public condition 13 | { 14 | public: 15 | culture_condition(const std::string &culture_identifier, const gsml_operator effect_operator) 16 | : condition(effect_operator) 17 | { 18 | this->culture = culture::get(culture_identifier); 19 | } 20 | 21 | virtual const std::string &get_identifier() const override 22 | { 23 | static const std::string identifier = "culture"; 24 | return identifier; 25 | } 26 | 27 | virtual bool check_assignment(const T *scope) const override 28 | { 29 | return this->check_equality(scope); 30 | } 31 | 32 | virtual bool check_equality(const T *scope) const override 33 | { 34 | return scope->get_culture() == this->culture; 35 | } 36 | 37 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 38 | { 39 | scope->connect(scope, &T::culture_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 40 | } 41 | 42 | virtual std::string get_assignment_string() const override 43 | { 44 | return this->get_equality_string(); 45 | } 46 | 47 | virtual std::string get_equality_string() const override 48 | { 49 | return "Culture is " + this->culture->get_name(); 50 | } 51 | 52 | virtual std::string get_inequality_string() const override 53 | { 54 | return "Culture is not " + this->culture->get_name(); 55 | } 56 | 57 | private: 58 | const culture *culture = nullptr; 59 | }; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /script/condition/world_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "holding/holding.h" 4 | #include "holding/holding_slot.h" 5 | #include "map/province.h" 6 | #include "map/world.h" 7 | #include "script/condition/condition.h" 8 | #include "script/scope_util.h" 9 | 10 | namespace metternich { 11 | 12 | class world; 13 | 14 | template 15 | class world_condition final : public condition 16 | { 17 | public: 18 | world_condition(const std::string &world_identifier, const gsml_operator effect_operator) 19 | : condition(effect_operator) 20 | { 21 | this->world = world::get(world_identifier); 22 | } 23 | 24 | virtual const std::string &get_identifier() const override 25 | { 26 | static const std::string identifier = "world"; 27 | return identifier; 28 | } 29 | 30 | virtual bool check_assignment(const T *scope) const override 31 | { 32 | return this->check_equality(scope); 33 | } 34 | 35 | virtual bool check_equality(const T *scope) const override 36 | { 37 | const metternich::world *world = get_scope_world(scope); 38 | if (world != nullptr) { 39 | return world == this->world; 40 | } 41 | 42 | const province *province = get_scope_province(scope); 43 | if (province != nullptr) { 44 | return province->get_world() == this->world; 45 | } 46 | 47 | return false; 48 | } 49 | 50 | virtual std::string get_assignment_string() const override 51 | { 52 | return this->get_equality_string(); 53 | } 54 | 55 | virtual std::string get_equality_string() const override 56 | { 57 | return "World is " + this->world->get_name(); 58 | } 59 | 60 | virtual std::string get_inequality_string() const override 61 | { 62 | return "World is not " + this->world->get_name(); 63 | } 64 | 65 | private: 66 | const world *world = nullptr; 67 | }; 68 | 69 | } 70 | -------------------------------------------------------------------------------- /database/gsml_data.cpp: -------------------------------------------------------------------------------- 1 | #include "database/gsml_data.h" 2 | 3 | #include "database/gsml_operator.h" 4 | #include "database/gsml_property_visitor.h" 5 | 6 | namespace metternich { 7 | 8 | gsml_data::gsml_data(std::string &&tag) 9 | : tag(std::move(tag)), scope_operator(gsml_operator::assignment) 10 | { 11 | } 12 | 13 | void gsml_data::add_property(const std::string &key, const std::string &value) 14 | { 15 | this->elements.push_back(gsml_property(key, gsml_operator::assignment, value)); 16 | } 17 | 18 | void gsml_data::add_property(std::string &&key, const gsml_operator gsml_operator, std::string &&value) 19 | { 20 | this->elements.push_back(gsml_property(std::move(key), gsml_operator, std::move(value))); 21 | } 22 | 23 | void gsml_data::print(std::ofstream &ofstream, const size_t indentation, const bool new_line) const 24 | { 25 | if (new_line) { 26 | ofstream << std::string(indentation, '\t'); 27 | } else { 28 | ofstream << " "; 29 | } 30 | if (!this->get_tag().empty()) { 31 | ofstream << this->get_tag() << " "; 32 | switch (this->get_operator()) { 33 | case gsml_operator::assignment: 34 | ofstream << "="; 35 | break; 36 | case gsml_operator::addition: 37 | ofstream << "+="; 38 | break; 39 | case gsml_operator::subtraction: 40 | ofstream << "-="; 41 | break; 42 | case gsml_operator::none: 43 | throw std::runtime_error("Cannot print the GSML \"none\" operator."); 44 | } 45 | ofstream << " "; 46 | } 47 | ofstream << "{"; 48 | if (!this->is_minor()) { 49 | ofstream << "\n"; 50 | } 51 | 52 | this->print_components(ofstream, indentation + 1); 53 | 54 | if (!this->is_minor()) { 55 | ofstream << std::string(indentation, '\t'); 56 | } 57 | ofstream << "}"; 58 | if (!this->is_minor()) { 59 | ofstream << "\n"; 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /script/effect/scripted_effect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | #include "script/effect/effect_list.h" 6 | 7 | #include 8 | 9 | namespace metternich { 10 | 11 | class character; 12 | struct context; 13 | 14 | //the class for a predefined, reusable scripted effect 15 | template 16 | class scripted_effect 17 | { 18 | public: 19 | void process_gsml_property(const gsml_property &property) 20 | { 21 | this->effects.process_gsml_property(property); 22 | } 23 | 24 | void process_gsml_scope(const gsml_data &scope) 25 | { 26 | this->effects.process_gsml_scope(scope); 27 | } 28 | 29 | void do_effects(T *scope, const context &ctx) const 30 | { 31 | this->effects.do_effects(scope, ctx); 32 | } 33 | 34 | std::string get_effects_string(const T *scope, const read_only_context &ctx, const size_t indent) const 35 | { 36 | return this->effects.get_effects_string(scope, ctx, indent); 37 | } 38 | 39 | private: 40 | effect_list effects; 41 | }; 42 | 43 | class character_scripted_effect final : public data_entry, public data_type, public scripted_effect 44 | { 45 | Q_OBJECT 46 | 47 | public: 48 | static constexpr const char *class_identifier = "character_scripted_effect"; 49 | static constexpr const char *database_folder = "character_scripted_effects"; 50 | 51 | public: 52 | character_scripted_effect(const std::string &identifier) : data_entry(identifier) 53 | { 54 | } 55 | 56 | virtual void process_gsml_property(const gsml_property &property) override 57 | { 58 | scripted_effect::process_gsml_property(property); 59 | } 60 | 61 | virtual void process_gsml_scope(const gsml_data &scope) override 62 | { 63 | scripted_effect::process_gsml_scope(scope); 64 | } 65 | }; 66 | 67 | } 68 | -------------------------------------------------------------------------------- /script/condition/holding_type_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "holding/holding.h" 4 | #include "holding/holding_type.h" 5 | #include "script/condition/condition.h" 6 | #include "script/condition/condition_check_base.h" 7 | 8 | namespace metternich { 9 | 10 | template 11 | class holding_type_condition final : public condition 12 | { 13 | public: 14 | holding_type_condition(const std::string &holding_type_identifier, const gsml_operator effect_operator) 15 | : condition(effect_operator) 16 | { 17 | this->holding_type = holding_type::get(holding_type_identifier); 18 | } 19 | 20 | virtual const std::string &get_identifier() const override 21 | { 22 | static const std::string identifier = "holding_type"; 23 | return identifier; 24 | } 25 | 26 | virtual bool check_assignment(const T *scope) const override 27 | { 28 | return this->check_equality(scope); 29 | } 30 | 31 | virtual bool check_equality(const T *scope) const override 32 | { 33 | return scope->get_type() == this->holding_type; 34 | } 35 | 36 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 37 | { 38 | scope->connect(scope, &T::type_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 39 | } 40 | 41 | virtual std::string get_assignment_string() const override 42 | { 43 | return this->get_equality_string(); 44 | } 45 | 46 | virtual std::string get_equality_string() const override 47 | { 48 | return "Holding type is " + this->holding_type->get_name(); 49 | } 50 | 51 | virtual std::string get_inequality_string() const override 52 | { 53 | return "Holding type is not " + this->holding_type->get_name(); 54 | } 55 | 56 | private: 57 | const holding_type *holding_type = nullptr; 58 | }; 59 | 60 | } 61 | -------------------------------------------------------------------------------- /script/condition/terrain_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map/province.h" 4 | #include "map/terrain_type.h" 5 | #include "script/condition/condition.h" 6 | #include "script/condition/condition_check_base.h" 7 | #include "script/scope_util.h" 8 | 9 | namespace metternich { 10 | 11 | class terrain_type; 12 | 13 | template 14 | class terrain_condition final : public condition 15 | { 16 | public: 17 | terrain_condition(const std::string &terrain_identifier, const gsml_operator effect_operator) 18 | : condition(effect_operator) 19 | { 20 | this->terrain = terrain_type::get(terrain_identifier); 21 | } 22 | 23 | virtual const std::string &get_identifier() const override 24 | { 25 | static const std::string identifier = "terrain"; 26 | return identifier; 27 | } 28 | 29 | virtual bool check_assignment(const T *scope) const override 30 | { 31 | return this->check_equality(scope); 32 | } 33 | 34 | virtual bool check_equality(const T *scope) const override 35 | { 36 | return scope->get_terrain() == this->terrain; 37 | } 38 | 39 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 40 | { 41 | scope->connect(scope, &T::terrain_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 42 | } 43 | 44 | virtual std::string get_assignment_string() const override 45 | { 46 | return this->get_equality_string(); 47 | } 48 | 49 | virtual std::string get_equality_string() const override 50 | { 51 | return "Terrain is " + this->terrain->get_name(); 52 | } 53 | 54 | virtual std::string get_inequality_string() const override 55 | { 56 | return "Terrain is not " + this->terrain->get_name(); 57 | } 58 | 59 | private: 60 | const terrain_type *terrain = nullptr; 61 | }; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /script/scope_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich { 6 | 7 | class holding; 8 | class holding_slot; 9 | class landed_title; 10 | class population_unit; 11 | class province; 12 | class territory; 13 | class world; 14 | 15 | template 16 | const territory *get_scope_territory(const T *scope) 17 | { 18 | const territory *territory = nullptr; 19 | if constexpr (std::is_base_of_v) { 20 | territory = scope; 21 | } else { 22 | territory = scope->get_territory(); 23 | } 24 | return territory; 25 | } 26 | 27 | template 28 | const province *get_scope_province(const T *scope) 29 | { 30 | const province *province = nullptr; 31 | if constexpr (std::is_same_v) { 32 | province = scope; 33 | } else { 34 | province = scope->get_province(); 35 | } 36 | return province; 37 | } 38 | 39 | template 40 | const world *get_scope_world(const T *scope) 41 | { 42 | const world *world = nullptr; 43 | if constexpr (std::is_same_v) { 44 | world = scope; 45 | } else { 46 | world = scope->get_world(); 47 | } 48 | return world; 49 | } 50 | 51 | template 52 | const landed_title *get_scope_landed_title(const T *scope) 53 | { 54 | const landed_title *title = nullptr; 55 | if constexpr (std::is_same_v || std::is_base_of_v) { 56 | title = scope->get_county(); 57 | } else if constexpr (std::is_same_v || std::is_same_v) { 58 | title = scope->get_barony(); 59 | } else if constexpr (std::is_same_v) { 60 | title = scope->get_holding()->get_barony(); 61 | } else { 62 | title = scope; 63 | } 64 | return title; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /politics/government_type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | namespace metternich { 7 | 8 | class character; 9 | class holding_type; 10 | enum class government_type_group; 11 | 12 | template 13 | class condition; 14 | 15 | class government_type final : public data_entry, public data_type 16 | { 17 | Q_OBJECT 18 | 19 | Q_PROPERTY(metternich::government_type_group group MEMBER group READ get_group) 20 | Q_PROPERTY(QVariantList allowed_holding_types READ get_allowed_holding_types_qvariant_list) 21 | 22 | public: 23 | static constexpr const char *class_identifier = "government_type"; 24 | static constexpr const char *database_folder = "government_types"; 25 | 26 | government_type(const std::string &identifier); 27 | virtual ~government_type() override; 28 | 29 | virtual void process_gsml_scope(const gsml_data &scope) override; 30 | 31 | government_type_group get_group() const 32 | { 33 | return this->group; 34 | } 35 | 36 | const std::set &get_allowed_holding_types() const 37 | { 38 | return this->allowed_holding_types; 39 | } 40 | 41 | QVariantList get_allowed_holding_types_qvariant_list() const; 42 | 43 | Q_INVOKABLE void add_allowed_holding_type(holding_type *holding_type) 44 | { 45 | this->allowed_holding_types.insert(holding_type); 46 | } 47 | 48 | Q_INVOKABLE void remove_allowed_holding_type(holding_type *holding_type) 49 | { 50 | this->allowed_holding_types.erase(holding_type); 51 | } 52 | 53 | const condition *get_conditions() const 54 | { 55 | return this->conditions.get(); 56 | } 57 | 58 | private: 59 | government_type_group group; 60 | std::set allowed_holding_types; 61 | std::unique_ptr> conditions; 62 | }; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /script/condition/commodity_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "economy/commodity.h" 4 | #include "script/condition/condition.h" 5 | #include "script/condition/condition_check_base.h" 6 | 7 | namespace metternich { 8 | 9 | class commodity; 10 | 11 | template 12 | class commodity_condition final : public condition 13 | { 14 | public: 15 | commodity_condition(const std::string &commodity_identifier, const gsml_operator effect_operator) 16 | : condition(effect_operator) 17 | { 18 | this->commodity = commodity::get(commodity_identifier); 19 | } 20 | 21 | virtual const std::string &get_identifier() const override 22 | { 23 | static const std::string identifier = "commodity"; 24 | return identifier; 25 | } 26 | 27 | virtual bool check_assignment(const T *scope) const override 28 | { 29 | return this->check_equality(scope); 30 | } 31 | 32 | virtual bool check_equality(const T *scope) const override 33 | { 34 | //check whether the scope's commodity is the same as that for this condition 35 | return scope->get_commodity() == this->commodity; 36 | } 37 | 38 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 39 | { 40 | scope->connect(scope, &T::commodity_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 41 | } 42 | 43 | virtual std::string get_assignment_string() const override 44 | { 45 | return this->get_equality_string(); 46 | } 47 | 48 | virtual std::string get_equality_string() const override 49 | { 50 | return "Commodity is " + this->commodity->get_name(); 51 | } 52 | 53 | virtual std::string get_inequality_string() const override 54 | { 55 | return "Commodity is not " + this->commodity->get_name(); 56 | } 57 | 58 | private: 59 | const metternich::commodity *commodity = nullptr; 60 | }; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /economy/employee.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "util/qunique_ptr.h" 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | class gsml_data; 10 | class gsml_property; 11 | class population_type; 12 | 13 | class employee final : public QObject 14 | { 15 | Q_OBJECT 16 | 17 | Q_PROPERTY(int efficiency MEMBER efficiency READ get_efficiency) 18 | Q_PROPERTY(int workforce_proportion MEMBER workforce_proportion READ get_workforce_proportion) 19 | Q_PROPERTY(int income_share MEMBER income_share READ get_income_share) 20 | 21 | public: 22 | static qunique_ptr from_gsml_scope(const gsml_data &scope); 23 | 24 | void process_gsml_property(const gsml_property &property); 25 | void process_gsml_scope(const gsml_data &scope) { Q_UNUSED(scope) } 26 | 27 | qunique_ptr duplicate() const 28 | { 29 | auto employee = make_qunique(); 30 | employee->population_type = this->get_population_type(); 31 | employee->efficiency = this->get_efficiency(); 32 | employee->workforce_proportion = this->get_workforce_proportion(); 33 | employee->income_share = this->get_income_share(); 34 | return employee; 35 | } 36 | 37 | const metternich::population_type *get_population_type() const 38 | { 39 | return this->population_type; 40 | } 41 | 42 | int get_efficiency() const 43 | { 44 | return this->efficiency; 45 | } 46 | 47 | int get_workforce_proportion() const 48 | { 49 | return this->workforce_proportion; 50 | } 51 | 52 | int get_income_share() const 53 | { 54 | return this->income_share; 55 | } 56 | 57 | private: 58 | const metternich::population_type *population_type = nullptr; 59 | int efficiency = 100; //the employee's efficiency, as a percentage 60 | int workforce_proportion = 100; //the proportion that the employee can make of the workforce, as a percentage 61 | int income_share = 50; //the share of income for the employee 62 | }; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /script/effect/effect_list.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "script/effect/effect_list.h" 4 | 5 | #include "database/gsml_data.h" 6 | #include "database/gsml_property.h" 7 | #include "script/effect/effect.h" 8 | 9 | namespace metternich { 10 | 11 | template 12 | effect_list::effect_list() 13 | { 14 | } 15 | 16 | template 17 | effect_list::~effect_list() 18 | { 19 | } 20 | 21 | template 22 | void effect_list::process_gsml_property(const gsml_property &property) 23 | { 24 | this->effects.push_back(effect::from_gsml_property(property)); 25 | } 26 | 27 | template 28 | void effect_list::process_gsml_scope(const gsml_data &scope) 29 | { 30 | this->effects.push_back(effect::from_gsml_scope(scope)); 31 | } 32 | 33 | template 34 | void effect_list::do_effects(T *scope, const context &ctx) const 35 | { 36 | for (const std::unique_ptr> &effect : this->effects) { 37 | effect->do_effect(scope, ctx); 38 | } 39 | } 40 | 41 | template 42 | std::string effect_list::get_effects_string(const T *scope, const read_only_context &ctx, const size_t indent) const 43 | { 44 | std::string effects_string; 45 | bool first = true; 46 | for (const std::unique_ptr> &effect : this->effects) { 47 | if (effect->is_hidden()) { 48 | continue; 49 | } 50 | 51 | const std::string effect_string = effect->get_string(scope, ctx, indent); 52 | if (effect_string.empty()) { 53 | continue; 54 | } 55 | 56 | if (first) { 57 | first = false; 58 | } else { 59 | effects_string += "\n"; 60 | } 61 | 62 | if (indent > 0) { 63 | effects_string += std::string(indent, '\t'); 64 | } 65 | 66 | effects_string += effect_string; 67 | } 68 | return effects_string; 69 | } 70 | 71 | template class effect_list; 72 | template class effect_list; 73 | template class effect_list; 74 | 75 | } 76 | -------------------------------------------------------------------------------- /script/modifier.cpp: -------------------------------------------------------------------------------- 1 | #include "script/modifier.h" 2 | 3 | #include "database/gsml_property.h" 4 | #include "script/modifier_effect/modifier_effect.h" 5 | 6 | namespace metternich { 7 | 8 | template 9 | modifier::modifier() 10 | { 11 | } 12 | 13 | template 14 | modifier::~modifier() 15 | { 16 | } 17 | 18 | template 19 | void modifier::process_gsml_property(const gsml_property &property) 20 | { 21 | std::unique_ptr> effect = modifier_effect::from_gsml_property(property); 22 | this->add_modifier_effect(std::move(effect)); 23 | } 24 | 25 | template 26 | void modifier::apply(T *scope, const int multiplier) const 27 | { 28 | for (const std::unique_ptr> &modifier_effect : this->modifier_effects) { 29 | modifier_effect->apply(scope, 1 * multiplier); 30 | } 31 | } 32 | 33 | template 34 | void modifier::remove(T *scope, const int multiplier) const 35 | { 36 | for (const std::unique_ptr> &modifier_effect : this->modifier_effects) { 37 | modifier_effect->apply(scope, -1 * multiplier); 38 | } 39 | } 40 | 41 | template 42 | std::string modifier::get_string(const size_t indent) const 43 | { 44 | std::string str; 45 | for (size_t i = 0; i < this->modifier_effects.size(); ++i) { 46 | if (i > 0) { 47 | str += "\n"; 48 | } 49 | 50 | if (indent > 0) { 51 | str += std::string(indent, '\t'); 52 | } 53 | 54 | str += this->modifier_effects[i]->get_string(); 55 | } 56 | return str; 57 | } 58 | 59 | template 60 | void modifier::add_modifier_effect(std::unique_ptr> &&modifier_effect) 61 | { 62 | this->modifier_effects.push_back(std::move(modifier_effect)); 63 | } 64 | 65 | template class modifier; 66 | template class modifier; 67 | template class modifier; 68 | template class modifier; 69 | 70 | } 71 | -------------------------------------------------------------------------------- /script/factor_modifier.cpp: -------------------------------------------------------------------------------- 1 | #include "factor_modifier.h" 2 | 3 | #include "database/gsml_data.h" 4 | #include "database/gsml_operator.h" 5 | #include "database/gsml_property.h" 6 | #include "script/condition/and_condition.h" 7 | #include "util/parse_util.h" 8 | 9 | namespace metternich { 10 | 11 | template 12 | factor_modifier::factor_modifier() 13 | { 14 | this->conditions = std::make_unique>(); 15 | } 16 | 17 | template 18 | factor_modifier::~factor_modifier() 19 | { 20 | } 21 | 22 | template 23 | void factor_modifier::process_gsml_property(const gsml_property &property) 24 | { 25 | const std::string &key = property.get_key(); 26 | const gsml_operator gsml_operator = property.get_operator(); 27 | const std::string &value = property.get_value(); 28 | 29 | if (key == "factor") { 30 | if (gsml_operator == gsml_operator::assignment) { 31 | this->factor = parse::centesimal_number_string_to_int(value); 32 | } else { 33 | throw std::runtime_error("Invalid operator for property (\"" + property.get_key() + "\")."); 34 | } 35 | } else { 36 | std::unique_ptr> condition = metternich::condition::from_gsml_property(property); 37 | this->conditions->add_condition(std::move(condition)); 38 | } 39 | } 40 | 41 | template 42 | void factor_modifier::process_gsml_scope(const gsml_data &scope) 43 | { 44 | std::unique_ptr> condition = metternich::condition::from_gsml_scope(scope); 45 | this->conditions->add_condition(std::move(condition)); 46 | } 47 | 48 | 49 | template 50 | bool factor_modifier::check_conditions(const T *scope, const read_only_context &ctx) const 51 | { 52 | return this->conditions->check(scope, ctx); 53 | } 54 | 55 | template class factor_modifier; 56 | template class factor_modifier; 57 | template class factor_modifier; 58 | template class factor_modifier; 59 | 60 | } 61 | -------------------------------------------------------------------------------- /script/decision/scoped_decision.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace metternich { 6 | 7 | class character; 8 | class gsml_data; 9 | class gsml_property; 10 | class holding; 11 | 12 | template 13 | class and_condition; 14 | 15 | template 16 | class chance_factor; 17 | 18 | template 19 | class decision_filter; 20 | 21 | template 22 | class effect_list; 23 | 24 | template 25 | class scoped_decision 26 | { 27 | public: 28 | scoped_decision(); 29 | virtual ~scoped_decision(); 30 | 31 | void initialize(); 32 | 33 | void process_gsml_property(const gsml_property &property); 34 | void process_gsml_scope(const gsml_data &scope); 35 | 36 | bool check_filter(const T *scope, const character *source) const; 37 | bool check_preconditions(const T *scope) const; 38 | bool check_preconditions(const T *scope, const character *source) const; 39 | bool check_conditions(const T *scope) const; 40 | bool check_conditions(const T *scope, const character *source) const; 41 | bool check_source_preconditions(const character *source) const; 42 | bool check_source_conditions(const character *source) const; 43 | void do_effects(T *scope, character *source) const; 44 | QString get_string(const T *scope, character *source) const; 45 | int calculate_ai_chance(const T *scope, character *source) const; 46 | 47 | private: 48 | decision_filter *filter = nullptr; 49 | bool ai = true; //whether the decision is allowed for the AI 50 | std::unique_ptr> preconditions; 51 | std::unique_ptr> conditions; 52 | std::unique_ptr> source_preconditions; 53 | std::unique_ptr> source_conditions; 54 | std::unique_ptr> effects; 55 | std::unique_ptr> ai_chance; //the chance of the AI doing the decision each time it is checked 56 | }; 57 | 58 | extern template class scoped_decision; 59 | 60 | } 61 | -------------------------------------------------------------------------------- /script/decision/holding_decision.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_type.h" 4 | #include "script/decision/decision.h" 5 | #include "script/decision/scoped_decision.h" 6 | 7 | namespace metternich { 8 | 9 | class holding; 10 | 11 | class holding_decision final : public decision, public data_type, public scoped_decision 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | static constexpr const char *class_identifier = "holding_decision"; 17 | static constexpr const char *database_base_folder = "decisions"; 18 | static constexpr const char *database_folder = "holding_decisions"; 19 | 20 | holding_decision(const std::string &identifier) : decision(identifier) {} 21 | 22 | virtual void initialize() override 23 | { 24 | scoped_decision::initialize(); 25 | } 26 | 27 | virtual void process_gsml_property(const gsml_property &property) override 28 | { 29 | const std::string &key = property.get_key(); 30 | 31 | if (key == "filter" || key == "ai") { 32 | scoped_decision::process_gsml_property(property); 33 | } else { 34 | data_entry_base::process_gsml_property(property); 35 | } 36 | } 37 | 38 | virtual void process_gsml_scope(const gsml_data &scope) override 39 | { 40 | const std::string &tag = scope.get_tag(); 41 | 42 | if (tag == "preconditions" || tag == "conditions" || tag == "source_preconditions" || tag == "source_conditions" || tag == "effects" || tag == "ai_chance") { 43 | scoped_decision::process_gsml_scope(scope); 44 | } else { 45 | data_entry_base::process_gsml_scope(scope); 46 | } 47 | } 48 | 49 | bool check_conditions(const holding *holding, const character *source) const; 50 | Q_INVOKABLE bool check_conditions(const QVariant &holding_variant, const QVariant &source_variant) const; 51 | Q_INVOKABLE void do_effects(const QVariant &holding_variant, const QVariant &source_variant) const; 52 | Q_INVOKABLE QString get_string(const QVariant &holding_variant, const QVariant &source_variant) const; 53 | }; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /history/timeline.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace metternich { 12 | 13 | class timeline final : public data_entry, public data_type 14 | { 15 | Q_OBJECT 16 | 17 | Q_PROPERTY(metternich::timeline* parent_timeline MEMBER parent_timeline READ get_parent_timeline) 18 | Q_PROPERTY(QDateTime point_of_divergence MEMBER point_of_divergence READ get_point_of_divergence) 19 | 20 | public: 21 | static constexpr const char *class_identifier = "timeline"; 22 | static constexpr const char *database_folder = "timelines"; 23 | 24 | timeline(const std::string &identifier) : data_entry(identifier) {} 25 | 26 | timeline *get_parent_timeline() const 27 | { 28 | return this->parent_timeline; 29 | } 30 | 31 | const QDateTime &get_point_of_divergence() const 32 | { 33 | return this->point_of_divergence; 34 | } 35 | 36 | bool derives_from_timeline(const timeline *timeline) const 37 | { 38 | if (this->get_parent_timeline() == nullptr) { 39 | return false; 40 | } 41 | 42 | if (timeline == this->get_parent_timeline()) { 43 | return true; 44 | } 45 | 46 | return this->get_parent_timeline()->derives_from_timeline(timeline); 47 | } 48 | 49 | bool contains_timeline_date(const timeline *timeline, const QDateTime &date) const 50 | { 51 | if (timeline == this) { 52 | return true; 53 | } else if (this->get_parent_timeline() == nullptr && timeline != nullptr) { 54 | return false; 55 | } 56 | 57 | if (timeline == this->get_parent_timeline()) { 58 | return date < this->point_of_divergence; 59 | } 60 | 61 | return this->get_parent_timeline()->contains_timeline_date(timeline, date); 62 | } 63 | 64 | private: 65 | timeline *parent_timeline = nullptr; //the timeline from which this one derives (null means the default timeline) 66 | QDateTime point_of_divergence; //the point of divergence from the parent timeline 67 | }; 68 | 69 | } 70 | -------------------------------------------------------------------------------- /script/event/event_trigger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/identifiable_type.h" 4 | 5 | namespace metternich { 6 | 7 | class character; 8 | struct context; 9 | 10 | template 11 | class scoped_event_base; 12 | 13 | class event_trigger_base 14 | { 15 | public: 16 | event_trigger_base(const std::string &identifier) : identifier(identifier) 17 | { 18 | } 19 | 20 | const std::string &get_identifier() const 21 | { 22 | return this->identifier; 23 | } 24 | 25 | private: 26 | std::string identifier; 27 | }; 28 | 29 | template 30 | class event_trigger : public event_trigger_base, public identifiable_type> 31 | { 32 | public: 33 | static constexpr const char *class_identifier = "event_trigger"; 34 | 35 | event_trigger(const std::string &identifier) : event_trigger_base(identifier) 36 | { 37 | } 38 | 39 | void add_event(const scoped_event_base *event) 40 | { 41 | this->events.push_back(event); 42 | } 43 | 44 | void add_random_event(const scoped_event_base *event) 45 | { 46 | this->random_events.push_back(event); 47 | } 48 | 49 | void do_events(T *scope, const context &ctx) const; 50 | void do_events(T *scope) const; 51 | 52 | private: 53 | std::vector *> events; 54 | std::vector *> random_events; 55 | }; 56 | 57 | extern template class event_trigger; 58 | 59 | class character_event_trigger final : public event_trigger 60 | { 61 | public: 62 | static inline const event_trigger *game_start = event_trigger::add("game_start"); 63 | static inline const event_trigger *monthly_pulse = event_trigger::add("monthly_pulse"); 64 | static inline const event_trigger *yearly_pulse = event_trigger::add("yearly_pulse"); 65 | static inline const event_trigger *landed_monthly_pulse = event_trigger::add("landed_monthly_pulse"); 66 | static inline const event_trigger *landed_yearly_pulse = event_trigger::add("landed_yearly_pulse"); 67 | }; 68 | 69 | } 70 | -------------------------------------------------------------------------------- /script/condition/has_any_active_trade_route_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map/province.h" 4 | #include "script/condition/condition.h" 5 | #include "script/condition/condition_check_base.h" 6 | #include "script/scope_util.h" 7 | 8 | namespace metternich { 9 | 10 | template 11 | class has_any_active_trade_route_condition final : public condition 12 | { 13 | public: 14 | has_any_active_trade_route_condition(const bool has_any_active_trade_route, const gsml_operator effect_operator) 15 | : condition(effect_operator), has_any_active_trade_route(has_any_active_trade_route) 16 | { 17 | } 18 | 19 | virtual const std::string &get_identifier() const override 20 | { 21 | static const std::string identifier = "has_any_active_trade_route"; 22 | return identifier; 23 | } 24 | 25 | virtual bool check_assignment(const T *scope) const override 26 | { 27 | return this->check_equality(scope); 28 | } 29 | 30 | virtual bool check_equality(const T *scope) const override 31 | { 32 | return scope->has_any_active_trade_route(); 33 | } 34 | 35 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 36 | { 37 | scope->connect(scope, &T::active_trade_routes_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 38 | } 39 | 40 | virtual std::string get_assignment_string() const override 41 | { 42 | return this->get_equality_string(); 43 | } 44 | 45 | virtual std::string get_equality_string() const override 46 | { 47 | if (this->has_any_active_trade_route) { 48 | return "Has any active trade route"; 49 | } else { 50 | return "Does have any active trade route"; 51 | } 52 | } 53 | 54 | virtual std::string get_inequality_string() const override 55 | { 56 | if (!this->has_any_active_trade_route) { 57 | return "Has any active trade route"; 58 | } else { 59 | return "Does have any active trade route"; 60 | } 61 | } 62 | 63 | private: 64 | bool has_any_active_trade_route = false; 65 | }; 66 | 67 | } 68 | -------------------------------------------------------------------------------- /script/condition/has_technology_condition.cpp: -------------------------------------------------------------------------------- 1 | #include "script/condition/has_technology_condition.h" 2 | 3 | #include "holding/holding.h" 4 | #include "holding/holding_slot.h" 5 | #include "map/province.h" 6 | #include "population/population_unit.h" 7 | #include "script/condition/condition_check_base.h" 8 | #include "script/scope_util.h" 9 | #include "technology/technology.h" 10 | 11 | namespace metternich { 12 | 13 | template 14 | has_technology_condition::has_technology_condition(const std::string &technology_identifier, const gsml_operator effect_operator) 15 | : condition(effect_operator) 16 | { 17 | this->technology = technology::get(technology_identifier); 18 | } 19 | 20 | template 21 | bool has_technology_condition::check_assignment(const T *scope) const 22 | { 23 | const territory *territory = get_scope_territory(scope); 24 | return territory != nullptr && territory->has_technology(this->technology); 25 | } 26 | 27 | template 28 | void has_technology_condition::bind_condition_check(condition_check_base &check, const T *scope) const { 29 | const territory *territory = get_scope_territory(scope); 30 | if (territory != nullptr) { 31 | scope->connect(territory, &territory::technologies_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 32 | } 33 | } 34 | 35 | template 36 | std::string has_technology_condition::get_equality_string() const 37 | { 38 | return "Has the " + this->technology->get_name() + " technology"; 39 | } 40 | 41 | template 42 | std::string has_technology_condition::get_inequality_string() const 43 | { 44 | return "Does not have the " + this->technology->get_name() + " technology"; 45 | } 46 | 47 | template class has_technology_condition; 48 | template class has_technology_condition; 49 | template class has_technology_condition; 50 | template class has_technology_condition; 51 | template class has_technology_condition; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /technology/technology_area.cpp: -------------------------------------------------------------------------------- 1 | #include "technology/technology_area.h" 2 | 3 | #include "technology/technology.h" 4 | #include "technology/technology_area_compare.h" 5 | #include "technology/technology_category.h" 6 | #include "technology/technology_compare.h" 7 | #include "util/container_util.h" 8 | #include "util/translator.h" 9 | #include "util/vector_util.h" 10 | 11 | namespace metternich { 12 | 13 | std::vector technology_area::get_all_sorted() 14 | { 15 | std::vector technology_areas = technology_area::get_all(); 16 | std::sort(technology_areas.begin(), technology_areas.end(), technology_area_compare()); 17 | return technology_areas; 18 | } 19 | 20 | technology_area::technology_area(const std::string &identifier) 21 | : data_entry(identifier), category(technology_category::none) 22 | { 23 | } 24 | 25 | void technology_area::check() const 26 | { 27 | if (this->get_category() == technology_category::none) { 28 | throw std::runtime_error("Technology area \"" + this->get_identifier() + "\" has no category."); 29 | } 30 | } 31 | 32 | std::string technology_area::get_category_name() const 33 | { 34 | return translator::get()->translate(technology_category_to_string(this->get_category())); 35 | } 36 | 37 | QVariantList technology_area::get_technologies_qvariant_list() const 38 | { 39 | std::vector technologies = this->technologies; 40 | std::sort(technologies.begin(), technologies.end(), technology_compare()); 41 | return container::to_qvariant_list(technologies); 42 | } 43 | 44 | void technology_area::remove_technology(technology *technology) 45 | { 46 | vector::remove(this->technologies, technology); 47 | } 48 | 49 | 50 | int technology_area::get_min_level() const 51 | { 52 | if (this->technologies.empty()) { 53 | return 0; 54 | } 55 | 56 | //get the lowest level amongst the technologies for the area 57 | int level = std::numeric_limits::max(); 58 | 59 | for (technology *technology : this->technologies) { 60 | level = std::min(level, technology->get_level()); 61 | } 62 | 63 | return level; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /economy/employment_owner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "util/qunique_ptr.h" 4 | 5 | #include 6 | 7 | namespace metternich { 8 | 9 | class gsml_data; 10 | class gsml_property; 11 | class population_type; 12 | 13 | class employment_owner final : public QObject 14 | { 15 | Q_OBJECT 16 | 17 | Q_PROPERTY(int output_modifier MEMBER output_modifier READ get_output_modifier) 18 | Q_PROPERTY(int proportion_to_workforce MEMBER proportion_to_workforce READ get_proportion_to_workforce) 19 | Q_PROPERTY(int income_share MEMBER income_share READ get_income_share) 20 | 21 | public: 22 | static qunique_ptr from_gsml_scope(const gsml_data &scope); 23 | 24 | void process_gsml_property(const gsml_property &property); 25 | void process_gsml_scope(const gsml_data &scope) { Q_UNUSED(scope) } 26 | 27 | qunique_ptr duplicate() const 28 | { 29 | auto owner = make_qunique(); 30 | owner->population_type = this->get_population_type(); 31 | owner->output_modifier = this->get_output_modifier(); 32 | owner->proportion_to_workforce = this->get_proportion_to_workforce(); 33 | owner->income_share = this->get_income_share(); 34 | return owner; 35 | } 36 | 37 | const metternich::population_type *get_population_type() const 38 | { 39 | return this->population_type; 40 | } 41 | 42 | int get_output_modifier() const 43 | { 44 | return this->output_modifier; 45 | } 46 | 47 | int get_proportion_to_workforce() const 48 | { 49 | return this->proportion_to_workforce; 50 | } 51 | 52 | int get_income_share() const 53 | { 54 | return this->income_share; 55 | } 56 | 57 | private: 58 | const metternich::population_type *population_type = nullptr; 59 | int output_modifier = 100; //the owner's output modifier in ideal conditions (i.e. the proportion of owners to workforce being exactly as in ProportionToWorkforce) 60 | int proportion_to_workforce = 1; //the proportion (in percent) that the owners should have to the workforce to grant the output modifier in full 61 | int income_share = 50; //the share of income for the employment owner 62 | }; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /culture/culture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "culture/culture_base.h" 4 | #include "database/data_type.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace metternich { 11 | 12 | class culture_group; 13 | class culture_supergroup; 14 | class dynasty; 15 | class population_unit; 16 | 17 | template 18 | class condition; 19 | 20 | class culture final : public culture_base, public data_type 21 | { 22 | Q_OBJECT 23 | 24 | Q_PROPERTY(metternich::culture_group* group MEMBER group READ get_group NOTIFY group_changed) 25 | Q_PROPERTY(QVariantList derived_cultures READ get_derived_cultures_qvariant_list) 26 | 27 | public: 28 | static constexpr const char *class_identifier = "culture"; 29 | static constexpr const char *database_folder = "cultures"; 30 | 31 | culture(const std::string &identifier); 32 | ~culture() override; 33 | 34 | virtual void process_gsml_scope(const gsml_data &scope) override; 35 | virtual void initialize() override; 36 | virtual void check() const override; 37 | 38 | culture_group *get_group() const 39 | { 40 | return this->group; 41 | } 42 | 43 | culture_supergroup *get_supergroup() const; 44 | 45 | const std::set &get_derived_cultures() const 46 | { 47 | return this->derived_cultures; 48 | } 49 | 50 | QVariantList get_derived_cultures_qvariant_list() const; 51 | 52 | Q_INVOKABLE void add_derived_culture(culture *culture) 53 | { 54 | this->derived_cultures.insert(culture); 55 | } 56 | 57 | Q_INVOKABLE void remove_derived_culture(culture *culture) 58 | { 59 | this->derived_cultures.erase(culture); 60 | } 61 | 62 | const condition *get_derivation_conditions() const 63 | { 64 | return this->derivation_conditions.get(); 65 | } 66 | 67 | std::string generate_male_name() const; 68 | std::string generate_female_name() const; 69 | std::string generate_dynasty_name() const; 70 | 71 | signals: 72 | void group_changed(); 73 | 74 | private: 75 | culture_group *group = nullptr; 76 | std::set derived_cultures; 77 | std::unique_ptr> derivation_conditions; 78 | }; 79 | 80 | } 81 | -------------------------------------------------------------------------------- /script/decision/holding_decision.cpp: -------------------------------------------------------------------------------- 1 | #include "script/decision/holding_decision.h" 2 | 3 | #include "character/character.h" 4 | #include "game/game.h" 5 | #include "holding/holding.h" 6 | 7 | namespace metternich { 8 | 9 | bool holding_decision::check_conditions(const holding *holding, const character *source) const 10 | { 11 | return scoped_decision::check_conditions(holding, source); 12 | } 13 | 14 | Q_INVOKABLE bool holding_decision::check_conditions(const QVariant &holding_variant, const QVariant &source_variant) const 15 | { 16 | QObject *holding_object = qvariant_cast(holding_variant); 17 | const holding *holding = static_cast(holding_object); 18 | 19 | QObject *source_object = qvariant_cast(source_variant); 20 | const character *source = static_cast(source_object); 21 | 22 | return this->check_conditions(holding, source); 23 | } 24 | 25 | Q_INVOKABLE void holding_decision::do_effects(const QVariant &holding_variant, const QVariant &source_variant) const 26 | { 27 | QObject *holding_object = qvariant_cast(holding_variant); 28 | holding *holding = static_cast(holding_object); 29 | 30 | QObject *source_object = qvariant_cast(source_variant); 31 | character *source = static_cast(source_object); 32 | 33 | game::get()->post_order([this, holding, source]() { 34 | //check again as the UI may have been in an old state, and allowed clicking on a now-invalid decision 35 | if (scoped_decision::check_conditions(holding, source)) { 36 | scoped_decision::do_effects(holding, source); 37 | } 38 | }); 39 | } 40 | 41 | Q_INVOKABLE QString holding_decision::get_string(const QVariant &holding_variant, const QVariant &source_variant) const 42 | { 43 | QObject *holding_object = qvariant_cast(holding_variant); 44 | const holding *holding = static_cast(holding_object); 45 | 46 | QObject *source_object = qvariant_cast(source_variant); 47 | character *source = static_cast(source_object); 48 | 49 | return scoped_decision::get_string(holding, source); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /Coding Guidelines.txt: -------------------------------------------------------------------------------- 1 | Coding Guidelines for Metternich 2 | 3 | 1. Namespace, class, variable and function names are in snake_case. 4 | 5 | 2. Function names generally begin with a verb in the imperative, for example: DoSomething(). 6 | 7 | 3. Prefer defining functions in headers if they don't require any external includes (which aren't already in the precompiled headers), so that the compiler is able to inline the functions if it deems optimal to do so, thus providing performance improvements. 8 | 9 | 4. Braces are always used for "if" statements. 10 | 11 | 5. Header files are included in the following order: first the header which corresponds to the current source file, then the other Metternich headers, then headers for third-party libraries, then Qt headers, and finally standard library headers. 12 | 13 | 6. Documentation headers for functions are located where the function definition is, regardless of whether that is in a header or source file. 14 | 15 | 7. Class definitions should be ordered in the following fashion: first, any macros which define a portion of the class (e.g. the Q_OBJECT macro). Then, typedefs, followed by enumerations, constant expressions, static methods, static variables, instance methods and finally instance variables. Within each of these, public ones are to be followed by protected members, and finally private ones. 16 | 17 | 8. The precompiled headers should include all library/third party headers used by the engine, but no headers belonging to Metternich itself. This way, compile times are reduced substantially, without 18 | 19 | 9. Using classes from the standard C++ library is to be preferred to Qt-specific ones. 20 | 21 | 10. Include Metternich headers in other Metternich headers only in the following circumstances: 1. if a class defined in the header derives from a class defined in the other header, 2. if a template class defined in the header requires the inclusion of the other header or 3. if the header pertains to a small derived class of e.g. a scripted condition, and is itself only included in a source file with a factory function (in such a case the header of the small derived class should have no source file, so that compilation and linking times are kept in check). -------------------------------------------------------------------------------- /culture/culture_base.cpp: -------------------------------------------------------------------------------- 1 | #include "culture/culture_base.h" 2 | 3 | #include "database/gsml_data.h" 4 | #include "database/gsml_operator.h" 5 | #include "util/vector_util.h" 6 | 7 | namespace metternich { 8 | 9 | void culture_base::process_gsml_scope(const gsml_data &scope) 10 | { 11 | const std::string &tag = scope.get_tag(); 12 | const std::vector &values = scope.get_values(); 13 | 14 | if (tag == "male_names") { 15 | switch (scope.get_operator()) { 16 | case gsml_operator::assignment: 17 | this->male_names = values; 18 | break; 19 | case gsml_operator::addition: 20 | this->add_male_names(values); 21 | break; 22 | default: 23 | throw std::runtime_error("Invalid operator for scope (\"" + tag + "\")."); 24 | } 25 | } else if (tag == "female_names") { 26 | switch (scope.get_operator()) { 27 | case gsml_operator::assignment: 28 | this->female_names = values; 29 | break; 30 | case gsml_operator::addition: 31 | this->add_female_names(values); 32 | break; 33 | default: 34 | throw std::runtime_error("Invalid operator for scope (\"" + tag + "\")."); 35 | } 36 | } else if (tag == "dynasty_names") { 37 | switch (scope.get_operator()) { 38 | case gsml_operator::assignment: 39 | this->dynasty_names = values; 40 | break; 41 | case gsml_operator::addition: 42 | this->add_dynasty_names(values); 43 | break; 44 | default: 45 | throw std::runtime_error("Invalid operator for scope (\"" + tag + "\")."); 46 | } 47 | } else { 48 | data_entry_base::process_gsml_scope(scope); 49 | } 50 | } 51 | 52 | void culture_base::check() const 53 | { 54 | if (!this->get_color().isValid()) { 55 | throw std::runtime_error("Culture \"" + this->get_identifier() + "\" has no valid color."); 56 | } 57 | } 58 | 59 | void culture_base::add_male_names(const std::vector &names) 60 | { 61 | vector::merge(this->male_names, names); 62 | } 63 | 64 | void culture_base::add_female_names(const std::vector &names) 65 | { 66 | vector::merge(this->female_names, names); 67 | } 68 | 69 | void culture_base::add_dynasty_names(const std::vector &names) 70 | { 71 | vector::merge(this->dynasty_names, names); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /map/map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/gsml_data.h" 4 | #include "util/singleton.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | namespace metternich { 14 | 15 | class province; 16 | class terrain_type; 17 | class world; 18 | enum class map_mode; 19 | 20 | class map final : public singleton 21 | { 22 | public: 23 | static std::vector parse_geojson_folder(const std::filesystem::path &path); 24 | 25 | private: 26 | static std::vector parse_world_geojson_database(); 27 | static void process_world_geojson_database(); 28 | 29 | static constexpr int geocoordinate_precision = 17; 30 | static constexpr int cosmic_map_boundary_offset = 128; //the offset from the celestial body at the cosmic map's boundary for determining its bounding rect 31 | 32 | public: 33 | map(); 34 | void load(); 35 | 36 | map_mode get_mode() const 37 | { 38 | return this->mode; 39 | } 40 | 41 | void set_mode(const map_mode mode); 42 | 43 | const QRectF &get_cosmic_map_bounding_rect() const 44 | { 45 | return this->cosmic_map_bounding_rect; 46 | } 47 | 48 | void calculate_cosmic_map_bounding_rect(); 49 | 50 | private: 51 | void load_geojson_files(); 52 | void process_geojson_data(const QVariantMap &geojson_data); 53 | void process_geojson_features(const QVariantList &features); 54 | void process_geojson_polygon(const std::string &feature_name, const QVariantList &coordinate_group); 55 | void process_geojson_line(const std::string &feature_name, const QVariantList &coordinates); 56 | void process_geojson_coordinates(const QVariantList &coordinates, gsml_data &coordinate_list_data); 57 | void save_geojson_data_to_gsml(); 58 | bool check_cache(); 59 | void save_cache(); 60 | 61 | private: 62 | std::map> geojson_polygon_data; //GeoJSON geopolygon coordinates, mapped to the name of the corresponding feature 63 | std::map> geojson_path_data; //GeoJSON geopath coordinates, mapped to the name of the corresponding feature 64 | std::string checksum; 65 | map_mode mode; 66 | QRectF cosmic_map_bounding_rect; 67 | }; 68 | 69 | } 70 | -------------------------------------------------------------------------------- /script/condition/has_any_trade_route_land_connection_condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "map/province.h" 4 | #include "script/condition/condition.h" 5 | #include "script/condition/condition_check_base.h" 6 | #include "script/scope_util.h" 7 | 8 | namespace metternich { 9 | 10 | template 11 | class has_any_trade_route_land_connection_condition final : public condition 12 | { 13 | public: 14 | has_any_trade_route_land_connection_condition(const bool has_any_trade_route_land_connection, const gsml_operator effect_operator) 15 | : condition(effect_operator), has_any_trade_route_land_connection(has_any_trade_route_land_connection) 16 | { 17 | } 18 | 19 | virtual const std::string &get_identifier() const override 20 | { 21 | static const std::string identifier = "has_any_trade_route_land_connection"; 22 | return identifier; 23 | } 24 | 25 | virtual bool check_assignment(const T *scope) const override 26 | { 27 | return this->check_equality(scope); 28 | } 29 | 30 | virtual bool check_equality(const T *scope) const override 31 | { 32 | return scope->has_any_trade_route_land_connection() == this->has_any_trade_route_land_connection; 33 | } 34 | 35 | virtual void bind_condition_check(condition_check_base &check, const T *scope) const override 36 | { 37 | scope->connect(scope, &T::active_trade_routes_changed, scope, [&check](){ check.set_result_recalculation_needed(); }, Qt::ConnectionType::DirectConnection); 38 | } 39 | 40 | virtual std::string get_assignment_string() const override 41 | { 42 | return this->get_equality_string(); 43 | } 44 | 45 | virtual std::string get_equality_string() const override 46 | { 47 | if (this->has_any_trade_route_land_connection) { 48 | return "Has any trade route land connection"; 49 | } else { 50 | return "Does have any trade route land connection"; 51 | } 52 | } 53 | 54 | virtual std::string get_inequality_string() const override 55 | { 56 | if (!this->has_any_trade_route_land_connection) { 57 | return "Has any trade route land connection"; 58 | } else { 59 | return "Does have any trade route land connection"; 60 | } 61 | } 62 | 63 | private: 64 | bool has_any_trade_route_land_connection = false; 65 | }; 66 | 67 | } 68 | -------------------------------------------------------------------------------- /map/province_profile.cpp: -------------------------------------------------------------------------------- 1 | #include "map/province_profile.h" 2 | 3 | #include "map/province.h" 4 | #include "script/condition/and_condition.h" 5 | #include "script/context.h" 6 | #include "util/random.h" 7 | #include "util/vector_random_util.h" 8 | 9 | namespace metternich { 10 | 11 | province_profile::province_profile(const std::string &identifier) : data_entry(identifier) 12 | { 13 | } 14 | 15 | province_profile::~province_profile() 16 | { 17 | } 18 | 19 | std::set province_profile::get_database_dependencies() 20 | { 21 | return { 22 | province::class_identifier, 23 | }; 24 | } 25 | 26 | void province_profile::process_gsml_scope(const gsml_data &scope) 27 | { 28 | if (scope.get_tag() == "conditions") { 29 | this->conditions = std::make_unique>(); 30 | database::process_gsml_data(this->conditions.get(), scope); 31 | } else { 32 | data_entry_base::process_gsml_scope(scope); 33 | } 34 | } 35 | 36 | void province_profile::process_gsml_dated_property(const gsml_property &property, const QDateTime &date) 37 | { 38 | this->get_province()->process_gsml_dated_property(property, date); 39 | } 40 | 41 | void province_profile::process_gsml_dated_scope(const gsml_data &scope, const QDateTime &date) 42 | { 43 | this->get_province()->process_gsml_dated_scope(scope, date); 44 | } 45 | 46 | /** 47 | ** @brief Get the profile's province, resolving it if that hasn't been done yet 48 | */ 49 | province *province_profile::get_province() 50 | { 51 | if (this->province != nullptr) { 52 | return this->province; 53 | } 54 | 55 | read_only_context ctx; 56 | 57 | std::vector potential_provinces; 58 | for (metternich::province *province : province::get_all()) { 59 | if (province->get_county() == nullptr) { 60 | continue; //only take into account provinces that belong to counties 61 | } 62 | 63 | if (!this->conditions || this->conditions->check(province, ctx)) { 64 | potential_provinces.push_back(province); 65 | } 66 | } 67 | 68 | if (potential_provinces.empty()) { 69 | throw std::runtime_error("No provinces fulfill the condition for province profile \"" + this->get_identifier() + "\"."); 70 | } 71 | 72 | this->province = vector::get_random(potential_provinces); 73 | return this->province; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /script/chance_factor.cpp: -------------------------------------------------------------------------------- 1 | #include "script/chance_factor.h" 2 | 3 | #include "database/database.h" 4 | #include "database/gsml_data.h" 5 | #include "database/gsml_operator.h" 6 | #include "database/gsml_property.h" 7 | #include "factor_modifier.h" 8 | #include "util/parse_util.h" 9 | 10 | namespace metternich { 11 | 12 | template 13 | chance_factor::chance_factor() 14 | { 15 | } 16 | 17 | template 18 | chance_factor::chance_factor(const int factor) : factor(factor) 19 | { 20 | } 21 | 22 | template 23 | chance_factor::~chance_factor() 24 | { 25 | } 26 | 27 | template 28 | void chance_factor::process_gsml_property(const gsml_property &property) 29 | { 30 | const std::string &key = property.get_key(); 31 | const gsml_operator gsml_operator = property.get_operator(); 32 | const std::string &value = property.get_value(); 33 | 34 | if (key == "factor") { 35 | if (gsml_operator == gsml_operator::assignment) { 36 | this->factor = parse::centesimal_number_string_to_int(value); 37 | } else { 38 | throw std::runtime_error("Invalid operator for property (\"" + property.get_key() + "\")."); 39 | } 40 | } else { 41 | throw std::runtime_error("Invalid chance factor property: \"" + property.get_key() + "\"."); 42 | } 43 | } 44 | 45 | template 46 | void chance_factor::process_gsml_scope(const gsml_data &scope) 47 | { 48 | if (scope.get_tag() == "modifier") { 49 | auto modifier = std::make_unique>(); 50 | database::process_gsml_data(modifier, scope); 51 | this->modifiers.push_back(std::move(modifier)); 52 | } else { 53 | throw std::runtime_error("Invalid chance scope: " + scope.get_tag() + "."); 54 | } 55 | } 56 | 57 | template 58 | int chance_factor::calculate(const T *scope, const read_only_context &ctx) const 59 | { 60 | //get the resulting chance factor after taking into account all modifiers 61 | int result = this->factor; 62 | 63 | for (const std::unique_ptr> &modifier : this->modifiers) { 64 | if (modifier->check_conditions(scope, ctx)) { 65 | result *= modifier->get_factor(); 66 | result /= 100; 67 | } 68 | } 69 | 70 | return result; 71 | } 72 | 73 | template class chance_factor; 74 | template class chance_factor; 75 | template class chance_factor; 76 | 77 | } 78 | -------------------------------------------------------------------------------- /economy/employment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace metternich { 4 | 5 | class building_slot; 6 | class employment_type; 7 | class holding; 8 | class population_unit; 9 | 10 | class employment 11 | { 12 | public: 13 | employment(const employment_type *type, building_slot *building_slot) 14 | : type(type), building_slot(building_slot) 15 | { 16 | } 17 | 18 | ~employment(); 19 | 20 | void do_day(); 21 | 22 | const employment_type *get_type() const 23 | { 24 | return type; 25 | } 26 | 27 | holding *get_holding() const; 28 | 29 | int get_workforce() const 30 | { 31 | return this->workforce; 32 | } 33 | 34 | void set_workforce(const int workforce); 35 | 36 | void change_workforce(const int change) 37 | { 38 | this->set_workforce(this->get_workforce() + change); 39 | } 40 | 41 | int get_workforce_capacity() const 42 | { 43 | return this->workforce_capacity; 44 | } 45 | 46 | void set_workforce_capacity(const int capacity); 47 | 48 | int get_unused_workforce_capacity() const 49 | { 50 | return this->get_workforce_capacity() - this->get_workforce(); 51 | } 52 | 53 | int get_employee_size(population_unit *employee) const 54 | { 55 | auto find_iterator = this->employee_sizes.find(employee); 56 | if (find_iterator == this->employee_sizes.end()) { 57 | return 0; 58 | } 59 | 60 | return find_iterator->second; 61 | } 62 | 63 | void set_employee_size(population_unit *employee, const int size); 64 | 65 | void change_employee_size(population_unit *employee, const int change) 66 | { 67 | this->set_employee_size(employee, this->get_employee_size(employee) + change); 68 | } 69 | 70 | bool can_employ_population_unit(const population_unit *population_unit) const; 71 | void remove_excess_employees(); 72 | 73 | void set_modifier_multiplier(const int multiplier); 74 | void calculate_modifier_multiplier(); 75 | 76 | private: 77 | const employment_type *type = nullptr; //the employment type 78 | building_slot *building_slot = nullptr; //the building slot to which the employment pertains 79 | int workforce = 0; //the current workforce for the employment 80 | int workforce_capacity = 0; //the maximum workforce for the employment 81 | std::map employee_sizes; //the employed population units, mapped to the quantity of people each of them has assigned for this employment 82 | int modifier_multiplier = 0; 83 | }; 84 | 85 | } 86 | -------------------------------------------------------------------------------- /script/event/event_option.cpp: -------------------------------------------------------------------------------- 1 | #include "script/event/event_option.h" 2 | 3 | #include "database/database.h" 4 | #include "database/gsml_data.h" 5 | #include "database/gsml_property.h" 6 | #include "script/chance_factor.h" 7 | #include "script/effect/effect.h" 8 | #include "script/effect/effect_list.h" 9 | #include "util/translator.h" 10 | 11 | namespace metternich { 12 | 13 | template 14 | event_option::event_option() 15 | { 16 | //the default AI chance for event options is a simple factor of 1 17 | this->ai_chance = std::make_unique>(1); 18 | } 19 | 20 | template 21 | event_option::~event_option() 22 | { 23 | } 24 | 25 | template 26 | std::string event_option::get_name() const 27 | { 28 | return translator::get()->translate(this->name_tag); 29 | } 30 | 31 | template 32 | void event_option::process_gsml_property(const gsml_property &property) 33 | { 34 | if (property.get_key() == "name") { 35 | this->name_tag = property.get_value(); 36 | } else { 37 | throw std::runtime_error("Invalid event option property: \"" + property.get_key() + "\"."); 38 | } 39 | } 40 | 41 | template 42 | void event_option::process_gsml_scope(const gsml_data &scope) 43 | { 44 | const std::string &tag = scope.get_tag(); 45 | 46 | if (tag == "ai_chance") { 47 | this->ai_chance = std::make_unique>(); 48 | database::process_gsml_data(this->ai_chance, scope); 49 | } else if (tag == "effects") { 50 | this->effects = std::make_unique>(); 51 | database::process_gsml_data(this->effects, scope); 52 | } else { 53 | throw std::runtime_error("Invalid event option scope: \"" + scope.get_tag() + "\"."); 54 | } 55 | } 56 | 57 | template 58 | void event_option::do_effects(T *scope, const context &ctx) const 59 | { 60 | if (this->effects == nullptr) { 61 | return; 62 | } 63 | 64 | this->effects->do_effects(scope, ctx); 65 | } 66 | 67 | template 68 | std::string event_option::get_effects_string(const T *scope, const read_only_context &ctx) const 69 | { 70 | if (this->effects != nullptr) { 71 | std::string effects_string = this->effects->get_effects_string(scope, ctx); 72 | if (!effects_string.empty()) { 73 | return effects_string; 74 | } 75 | } 76 | 77 | return no_effect_string; 78 | } 79 | 80 | template class event_option; 81 | 82 | } 83 | -------------------------------------------------------------------------------- /history/calendar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "database/data_entry.h" 4 | #include "database/data_type.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace metternich { 12 | 13 | class calendar final : public data_entry, public data_type 14 | { 15 | Q_OBJECT 16 | 17 | Q_PROPERTY(metternich::calendar* base_calendar MEMBER base_calendar WRITE set_base_calendar) 18 | Q_PROPERTY(int year_offset MEMBER year_offset READ get_year_offset) 19 | 20 | public: 21 | static constexpr const char *class_identifier = "calendar"; 22 | static constexpr const char *database_folder = "calendars"; 23 | 24 | calendar(const std::string &identifier) : data_entry(identifier) {} 25 | 26 | virtual void initialize() override 27 | { 28 | if (this->base_calendar != nullptr) { 29 | if (!this->base_calendar->is_initialized()) { 30 | this->base_calendar->initialize(); 31 | } 32 | 33 | //calculate the year offset to the Gregorian calendar based on the offset to the base calendar 34 | this->year_offset += this->base_calendar->get_year_offset(); 35 | this->base_calendar = nullptr; 36 | } 37 | 38 | data_entry_base::initialize(); 39 | } 40 | 41 | void set_base_calendar(calendar *base_calendar) 42 | { 43 | if (base_calendar == this->base_calendar) { 44 | return; 45 | } 46 | 47 | if (base_calendar == this) { 48 | throw std::runtime_error("Tried to set the base calendar of \"" + this->get_identifier() + "\" to itself."); 49 | } 50 | 51 | if (base_calendar->is_any_base_calendar(this)) { 52 | throw std::runtime_error("Tried to set the base calendar of \"" + this->get_identifier() + "\" to \"" + base_calendar->get_identifier() + "\", but that would create a circular dependency."); 53 | } 54 | 55 | this->base_calendar = base_calendar; 56 | } 57 | 58 | bool is_any_base_calendar(calendar *calendar) const 59 | { 60 | if (this->base_calendar == nullptr) { 61 | return false; 62 | } 63 | 64 | if (this->base_calendar == calendar) { 65 | return true; 66 | } 67 | 68 | return this->base_calendar->is_any_base_calendar(calendar); 69 | } 70 | 71 | int get_year_offset() const 72 | { 73 | return this->year_offset; 74 | } 75 | 76 | private: 77 | calendar *base_calendar = nullptr; //the base calendar, used to ultimately calculate the year offset to the Gregorian calendar from 78 | int year_offset = 0; //the offset from the Gregorian calendar, in years 79 | }; 80 | 81 | } 82 | --------------------------------------------------------------------------------