diff options
Diffstat (limited to 'src/openvic-simulation/map/Province.cpp')
-rw-r--r-- | src/openvic-simulation/map/Province.cpp | 130 |
1 files changed, 113 insertions, 17 deletions
diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp index d1183f5..89ddd39 100644 --- a/src/openvic-simulation/map/Province.cpp +++ b/src/openvic-simulation/map/Province.cpp @@ -1,6 +1,8 @@ #include "Province.hpp" #include "openvic-simulation/history/ProvinceHistory.hpp" +#include "openvic-simulation/map/Map.hpp" +#include "openvic-simulation/military/UnitInstance.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -9,9 +11,10 @@ Province::Province( std::string_view new_identifier, colour_t new_colour, index_t new_index ) : HasIdentifierAndColour { new_identifier, new_colour, true }, index { new_index }, region { nullptr }, climate { nullptr }, continent { nullptr }, on_map { false }, has_region { false }, water { false }, coastal { false }, - port { false }, default_terrain_type { nullptr }, positions {}, terrain_type { nullptr }, life_rating { 0 }, - colony_status { colony_status_t::STATE }, state { nullptr }, owner { nullptr }, controller { nullptr }, slave { false }, - crime { nullptr }, rgo { nullptr }, buildings { "buildings", false }, total_population { 0 } { + port { false }, port_adjacent_province { nullptr }, default_terrain_type { nullptr }, positions {}, + terrain_type { nullptr }, life_rating { 0 }, colony_status { colony_status_t::STATE }, state { nullptr }, + owner { nullptr }, controller { nullptr }, slave { false }, crime { nullptr }, rgo { nullptr }, + buildings { "buildings", false }, total_population { 0 } { assert(index != NULL_INDEX); } @@ -25,33 +28,68 @@ std::string Province::to_string() const { return stream.str(); } -bool Province::load_positions(BuildingTypeManager const& building_type_manager, ast::NodeCPtr root) { +bool Province::load_positions(Map const& map, BuildingTypeManager const& building_type_manager, ast::NodeCPtr root) { + const fixed_point_t map_height = map.get_height(); + const bool ret = expect_dictionary_keys( - "text_position", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.text)), - "text_rotation", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(positions.text_rotation)), + "text_position", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.text), map_height)), + "text_rotation", ZERO_OR_ONE, + expect_fixed_point(negate_callback<fixed_point_t>(assign_variable_callback(positions.text_rotation))), "text_scale", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(positions.text_scale)), - "unit", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.unit)), - "town", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.city)), - "city", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.city)), - "factory", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.factory)), - "building_construction", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.building_construction)), - "military_construction", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.military_construction)), + + "unit", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.unit), map_height)), + "town", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.city), map_height)), + "city", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.city), map_height)), + "factory", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.factory), map_height)), + + "building_construction", ZERO_OR_ONE, + expect_fvec2(flip_y_callback(assign_variable_callback(positions.building_construction), map_height)), + "military_construction", ZERO_OR_ONE, + expect_fvec2(flip_y_callback(assign_variable_callback(positions.military_construction), map_height)), + "building_position", ZERO_OR_ONE, building_type_manager.expect_building_type_dictionary_reserve_length( positions.building_position, - [this](BuildingType const& type, ast::NodeCPtr value) -> bool { - return expect_fvec2(map_callback(positions.building_position, &type))(value); + [this, map_height](BuildingType const& type, ast::NodeCPtr value) -> bool { + return expect_fvec2(flip_y_callback(map_callback(positions.building_position, &type), map_height))(value); } ), "building_rotation", ZERO_OR_ONE, building_type_manager.expect_building_type_decimal_map( - move_variable_callback(positions.building_rotation) + move_variable_callback(positions.building_rotation), std::negate {} ), + /* the below are esoteric clausewitz leftovers that either have no impact or whose functionality is lost to time */ "spawn_railway_track", ZERO_OR_ONE, success_callback, "railroad_visibility", ZERO_OR_ONE, success_callback, "building_nudge", ZERO_OR_ONE, success_callback )(root); - port = coastal && positions.building_position.contains(building_type_manager.get_port_building_type()); + if (coastal) { + fvec2_t const* port_position = get_building_position(building_type_manager.get_port_building_type()); + if (port_position != nullptr) { + const fixed_point_t rotation = get_building_rotation(building_type_manager.get_port_building_type()); + + /* At 0 rotation the port faces west, as rotation increases the port rotates anti-clockwise. */ + const fvec2_t port_dir { -rotation.cos(), rotation.sin() }; + const ivec2_t port_facing_position = static_cast<ivec2_t>(*port_position + port_dir / 4); + + Province const* province = map.get_province_at(port_facing_position); + + if (province != nullptr) { + if (province->is_water() && is_adjacent_to(province)) { + port = true; + port_adjacent_province = province; + } else { + /* Expected provinces with invalid ports: 39, 296, 1047, 1406, 2044 */ + Logger::warning( + "Invalid port for province ", get_identifier(), ": facing province ", province, + " which has: water = ", province->is_water(), ", adjacent = ", is_adjacent_to(province) + ); + } + } else { + Logger::warning("Invalid port for province ", get_identifier(), ": facing null province!"); + } + } + } return ret; } @@ -65,6 +103,28 @@ bool Province::expand_building(size_t building_index) { return building->expand(); } +fvec2_t const* Province::get_building_position(BuildingType const* building_type) const { + if (building_type != nullptr) { + const decltype(positions.building_position)::const_iterator it = positions.building_position.find(building_type); + + if (it != positions.building_position.end()) { + return &it->second; + } + } + return nullptr; +} + +fixed_point_t Province::get_building_rotation(BuildingType const* building_type) const { + if (building_type != nullptr) { + const decltype(positions.building_rotation)::const_iterator it = positions.building_rotation.find(building_type); + + if (it != positions.building_rotation.end()) { + return it->second; + } + } + return 0; +} + void Province::_add_pop(Pop pop) { pop.set_location(this); pops.push_back(std::move(pop)); @@ -178,7 +238,43 @@ bool Province::has_adjacency_going_through(Province const* province) const { } fvec2_t Province::get_unit_position() const { - return positions.unit.value_or(positions.centre); + return positions.unit.value_or(centre); +} + +bool Province::add_army(ArmyInstance& army) { + if (armies.emplace(&army).second) { + return true; + } else { + Logger::error("Trying to add already-existing army ", army.get_name(), " to province ", get_identifier()); + return false; + } +} + +bool Province::remove_army(ArmyInstance& army) { + if (armies.erase(&army) > 0) { + return true; + } else { + Logger::error("Trying to remove non-existent army ", army.get_name(), " from province ", get_identifier()); + return false; + } +} + +bool Province::add_navy(NavyInstance& navy) { + if (navies.emplace(&navy).second) { + return true; + } else { + Logger::error("Trying to add already-existing navy ", navy.get_name(), " to province ", get_identifier()); + return false; + } +} + +bool Province::remove_navy(NavyInstance& navy) { + if (navies.erase(&navy) > 0) { + return true; + } else { + Logger::error("Trying to remove non-existent navy ", navy.get_name(), " from province ", get_identifier()); + return false; + } } bool Province::reset(BuildingTypeManager const& building_type_manager) { |