#pragma once #include #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" #include "openvic-simulation/types/fixed_point/FixedPointMap.hpp" #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/types/Vector.hpp" namespace OpenVic { struct MapDefinition; struct Region; struct TerrainType; struct ProvinceSetModifier; using Climate = ProvinceSetModifier; using Continent = ProvinceSetModifier; struct BuildingType; struct BuildingTypeManager; /* REQUIREMENTS: * MAP-5, MAP-7, MAP-8, MAP-43, MAP-47 * POP-22 */ struct ProvinceDefinition : HasIdentifierAndColour { friend struct MapDefinition; using index_t = uint16_t; using distance_t = fixed_point_t; // should this go inside adjacency_t? struct adjacency_t { using data_t = uint8_t; static constexpr data_t NO_CANAL = 0; enum struct type_t : uint8_t { LAND, /* Between two land provinces */ WATER, /* Between two water provinces */ COASTAL, /* Between a land province and a water province */ IMPASSABLE, /* Between two land provinces (non-traversable) */ STRAIT, /* Between two land provinces with a water through province */ CANAL /* Between two water provinces with a land through province */ }; /* Type display name used for logging */ static std::string_view get_type_name(type_t type); private: ProvinceDefinition const* PROPERTY(to); ProvinceDefinition const* PROPERTY(through); distance_t PROPERTY(distance); type_t PROPERTY(type); data_t PROPERTY(data); // represents canal index, 0 for non-canal adjacencies public: adjacency_t( ProvinceDefinition const* new_to, distance_t new_distance, type_t new_type, ProvinceDefinition const* new_through, data_t new_data ); adjacency_t(adjacency_t const&) = delete; adjacency_t(adjacency_t&&) = default; adjacency_t& operator=(adjacency_t const&) = delete; adjacency_t& operator=(adjacency_t&&) = default; }; struct province_positions_t { /* Province name placement */ std::optional text_position; std::optional text_rotation; std::optional text_scale; /* Model positions */ std::optional unit; std::optional city; std::optional factory; std::optional building_construction; std::optional military_construction; ordered_map building_position; fixed_point_map_t building_rotation; }; static constexpr index_t NULL_INDEX = 0, MAX_INDEX = std::numeric_limits::max(); private: /* Immutable attributes (unchanged after initial game load) */ const index_t PROPERTY(index); Region const* PROPERTY(region); Climate const* PROPERTY(climate); Continent const* PROPERTY(continent); bool PROPERTY(on_map); bool PROPERTY_CUSTOM_PREFIX(water, is); bool PROPERTY_CUSTOM_PREFIX(coastal, is); bool PROPERTY_CUSTOM_PREFIX(port, has); ProvinceDefinition const* PROPERTY(port_adjacent_province); /* Terrain type calculated from terrain image */ TerrainType const* PROPERTY(default_terrain_type); std::vector PROPERTY(adjacencies); /* Calculated mean pixel position. */ fvec2_t PROPERTY(centre); province_positions_t positions; ProvinceDefinition(std::string_view new_identifier, colour_t new_colour, index_t new_index); public: ProvinceDefinition(ProvinceDefinition&&) = default; bool operator==(ProvinceDefinition const& other) const; std::string to_string() const; inline constexpr bool has_region() const { return region != nullptr; } /* The positions' y coordinates need to be inverted. */ bool load_positions( MapDefinition const& map_definition, BuildingTypeManager const& building_type_manager, ast::NodeCPtr root ); fvec2_t get_text_position() const; fixed_point_t get_text_rotation() const; fixed_point_t get_text_scale() const; /* This returns a pointer to the position of the specified building type, or nullptr if none exists. */ fvec2_t const* get_building_position(BuildingType const* building_type) const; fixed_point_t get_building_rotation(BuildingType const* building_type) const; adjacency_t const* get_adjacency_to(ProvinceDefinition const* province) const; bool is_adjacent_to(ProvinceDefinition const* province) const; std::vector get_adjacencies_going_through(ProvinceDefinition const* province) const; bool has_adjacency_going_through(ProvinceDefinition const* province) const; fvec2_t get_unit_position() const; }; }