3#include "dcon_generated.hpp"
18template auto province_is_blockaded<ve::tagged_vector<dcon::province_id>>(
sys::state const&, ve::tagged_vector<dcon::province_id>);
19template auto province_is_under_siege<ve::tagged_vector<dcon::province_id>>(
sys::state const&, ve::tagged_vector<dcon::province_id>);
20template auto battle_is_ongoing_in_province<ve::tagged_vector<dcon::province_id>>(
sys::state const&, ve::tagged_vector<dcon::province_id>);
26 return state.world.nation_get_active_regiments(n);
30 for(
auto v : state.world.nation_get_navy_control(n)) {
31 auto srange = v.get_navy().get_navy_membership();
32 total += int32_t(srange.end() - srange.begin());
41 auto curbeststats = state.world.nation_get_unit_stats(n, best);
42 auto& curbestdef = (curbeststats.discipline_or_evasion) ? curbeststats : state.military_definitions.unit_base_definitions[best];
44 auto stats = state.world.nation_get_unit_stats(n, given);
45 auto& def = (stats.discipline_or_evasion) ? stats : state.military_definitions.unit_base_definitions[given];
47 if(def.defence_or_hull > curbestdef.defence_or_hull) {
49 }
else if(def.defence_or_hull == curbestdef.defence_or_hull && def.default_organisation > curbestdef.default_organisation) {
51 }
else if(def.defence_or_hull == curbestdef.defence_or_hull && def.default_organisation == curbestdef.default_organisation && def.attack_or_gun_power > curbestdef.attack_or_gun_power) {
61 auto& curbestdef = state.military_definitions.unit_base_definitions[best];
62 auto& def = state.military_definitions.unit_base_definitions[given];
64 if(def.support > curbestdef.support) {
66 }
else if(def.support == curbestdef.support && def.discipline_or_evasion > curbestdef.discipline_or_evasion) {
68 }
else if(def.support == curbestdef.support && def.discipline_or_evasion == curbestdef.discipline_or_evasion && def.siege_or_torpedo_attack > curbestdef.siege_or_torpedo_attack) {
78 auto curbeststats = state.world.nation_get_unit_stats(n, best);
79 auto& basedef = state.military_definitions.unit_base_definitions[best];
80 auto& curbestdef = (curbeststats.discipline_or_evasion) ? curbeststats : basedef;
82 auto stats = state.world.nation_get_unit_stats(n, given);
83 auto& newbasedef = state.military_definitions.unit_base_definitions[given];
84 auto& def = (stats.discipline_or_evasion) ? stats : newbasedef;
86 if(def.reconnaissance_or_fire_range > curbestdef.reconnaissance_or_fire_range) {
88 }
else if(def.reconnaissance_or_fire_range == curbestdef.reconnaissance_or_fire_range && def.attack_or_gun_power > curbestdef.attack_or_gun_power) {
90 }
else if(def.reconnaissance_or_fire_range == curbestdef.reconnaissance_or_fire_range && def.attack_or_gun_power == curbestdef.attack_or_gun_power && basedef.maneuver > newbasedef.maneuver) {
97 dcon::unit_type_id curbest;
99 auto ndef = state.world.nation_get_identity_from_identity_holder(n);
102 for(
uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
103 dcon::unit_type_id uid = dcon::unit_type_id{ dcon::unit_type_id::value_base_t(i) };
104 auto& def = state.military_definitions.unit_base_definitions[uid];
110 auto available = state.world.nation_get_active_unit(n, uid) || def.active;
116 if(def.primary_culture && !primary_culture) {
125 state.console_log(nationname +
" infantry type: " + std::to_string(curbest.index()));
131 dcon::unit_type_id curbest;
133 for(
uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
134 dcon::unit_type_id uid = dcon::unit_type_id{ dcon::unit_type_id::value_base_t(i) };
135 auto def = state.military_definitions.unit_base_definitions[uid];
141 auto available = state.world.nation_get_active_unit(n, uid) || def.active;
147 if(def.primary_culture && !primary_culture) {
159 dcon::unit_type_id curbest;
160 for(
uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
161 dcon::unit_type_id uid = dcon::unit_type_id{ dcon::unit_type_id::value_base_t(i) };
163 auto def = state.military_definitions.unit_base_definitions[uid];
169 auto available = state.world.nation_get_active_unit(n, uid) || def.active;
175 if(def.primary_culture && !primary_culture) {
187 for(
uint32_t i = 0; i < state.military_definitions.unit_base_definitions.size(); ++i) {
188 dcon::unit_type_id uid = dcon::unit_type_id{dcon::unit_type_id::value_base_t(i)};
189 state.world.for_each_nation([&](dcon::nation_id nid) {
190 state.world.nation_get_unit_stats(nid, uid) = state.military_definitions.unit_base_definitions[uid];
196 assert(state.military_definitions.base_army_unit.index() < 2);
197 assert(state.military_definitions.base_naval_unit.index() < 2);
198 assert(state.military_definitions.base_army_unit.index() != -1);
199 assert(state.military_definitions.base_naval_unit.index() != -1);
200 for(
uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
201 dcon::unit_type_id uid = dcon::unit_type_id{dcon::unit_type_id::value_base_t(i)};
202 auto base_id = state.military_definitions.unit_base_definitions[uid].is_land
203 ? state.military_definitions.base_army_unit
204 : state.military_definitions.base_naval_unit;
205 state.world.for_each_nation([&](dcon::nation_id nid) {
206 auto& base_stats = state.world.nation_get_unit_stats(nid, base_id);
207 auto& current_stats = state.world.nation_get_unit_stats(nid, uid);
208 current_stats += base_stats;
214 for(
auto wg : state.world.in_wargoal) {
215 if(wg.get_war_from_wargoals_attached()) {
216 auto s = wg.get_associated_state();
218 bool found_state =
false;
219 for(
auto si : wg.get_target_nation().get_state_ownership()) {
220 if(si.get_state().get_definition() == s) {
226 state.world.delete_wargoal(wg);
234 state.world.for_each_nation([&](dcon::nation_id n) {
235 auto w = state.world.nation_get_war_participant(n);
236 if(w.begin() != w.end()) {
237 state.world.nation_set_is_at_war(n, true);
246 auto other_cbs = state.world.nation_get_available_cbs(from);
247 for(
auto& cb : other_cbs) {
251 for(
auto cb : state.world.in_cb_type) {
262 auto can_use = state.world.cb_type_get_can_use(cb);
267 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
268 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
272 if(!allowed_countries && allowed_states) {
274 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
275 if(wg.get_wargoal().get_added_by() == actor
276 && wg.get_wargoal().get_type() == cb
277 && wg.get_wargoal().get_target_nation() == target) {
284 bool any_allowed =
false;
285 for(
auto si : state.world.nation_get_state_ownership(target)) {
291 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
292 if(wg.get_wargoal().get_added_by() == actor
293 && wg.get_wargoal().get_type() == cb
294 && wg.get_wargoal().get_associated_state() == si.get_state().get_definition()
295 && wg.get_wargoal().get_target_nation() == target) {
309 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
310 if(allowed_substates) {
311 bool any_allowed = [&]() {
312 for(
auto v : state.world.nation_get_overlord_as_ruler(target)) {
313 if(v.get_subject().get_is_substate()) {
314 for(
auto si : state.world.nation_get_state_ownership(target)) {
327 if(allowed_countries) {
328 bool any_allowed = [&]() {
329 for(
auto n : state.world.in_nation) {
334 bool found_dup =
false;
337 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
338 if(wg.get_wargoal().get_added_by() == actor
339 && wg.get_wargoal().get_type() == cb
340 && (wg.get_wargoal().get_associated_tag() == n.get_identity_from_identity_holder()
341 || wg.get_wargoal().get_secondary_nation() == n)
342 && wg.get_wargoal().get_target_nation() == target) {
350 for(
auto si : state.world.nation_get_state_ownership(target)) {
354 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
355 if(wg.get_wargoal().get_added_by() == actor
356 && wg.get_wargoal().get_type() == cb
357 && (wg.get_wargoal().get_associated_tag() == n.get_identity_from_identity_holder()
358 || wg.get_wargoal().get_secondary_nation() == n)
359 && wg.get_wargoal().get_associated_state() == si.get_state().get_definition()
360 && wg.get_wargoal().get_target_nation() == target) {
374 bool found_dup =
false;
376 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
377 if(wg.get_wargoal().get_added_by() == actor
378 && wg.get_wargoal().get_type() == cb
379 && (wg.get_wargoal().get_associated_tag() == n.get_identity_from_identity_holder()
380 || wg.get_wargoal().get_secondary_nation() == n)
381 && wg.get_wargoal().get_target_nation() == target) {
405 auto can_use = state.world.cb_type_get_can_use(cb);
410 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
411 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
413 if(!allowed_countries && allowed_states) {
414 bool any_allowed =
false;
415 for(
auto si : state.world.nation_get_state_ownership(target)) {
425 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
426 if(allowed_substates) {
427 bool any_allowed = [&]() {
428 for(
auto v : state.world.nation_get_overlord_as_ruler(target)) {
429 if(v.get_subject().get_is_substate()) {
430 for(
auto si : state.world.nation_get_state_ownership(target)) {
444 if(allowed_countries) {
445 bool any_allowed = [&]() {
446 for(
auto n : state.world.in_nation) {
450 for(
auto si : state.world.nation_get_state_ownership(target)) {
472 dcon::state_definition_id st, dcon::national_identity_id tag, dcon::nation_id secondary) {
474 auto can_use = state.world.cb_type_get_can_use(cb);
479 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
480 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
482 if(!allowed_countries && allowed_states) {
483 bool any_allowed =
false;
485 for(
auto si : state.world.nation_get_state_ownership(target)) {
486 if(si.get_state().get_definition() == st &&
494 for(
auto si : state.world.nation_get_state_ownership(target)) {
506 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
507 if(allowed_substates) {
508 bool any_allowed = [&]() {
509 for(
auto v : state.world.nation_get_overlord_as_ruler(target)) {
510 if(v.get_subject().get_is_substate()) {
512 for(
auto si : state.world.nation_get_state_ownership(target)) {
513 if(si.get_state().get_definition() == st &&
520 for(
auto si : state.world.nation_get_state_ownership(target)) {
535 if(allowed_countries) {
536 auto secondary_nation = secondary ? secondary : state.world.national_identity_get_nation_from_identity_holder(tag);
539 bool validity =
false;
542 for(
auto si : state.world.nation_get_state_ownership(target)) {
550 for(
auto si : state.world.nation_get_state_ownership(target)) {
551 if(si.get_state().get_definition() == st &&
573 return state.world.province_get_is_blockaded(ids);
577 auto controller = state.world.province_get_nation_from_province_control(p);
578 auto owner = state.world.province_get_nation_from_province_ownership(p);
581 if(controller != owner)
584 auto port_to = state.world.province_get_port_to(p);
588 for(
auto n : state.world.province_get_navy_location(port_to)) {
589 if(n.get_navy().get_is_retreating() ==
false && !n.get_navy().get_battle_from_navy_battle_participation()) {
604 return state.world.province_get_siege_progress(ids) > 0.0f;
608 auto current = float(state.world.nation_get_active_regiments(n));
609 auto maximum = float(state.world.nation_get_recruitable_regiments(n));
610 return maximum > 0.0f ? current / maximum : 1.0f;
614 auto owner = state.world.state_instance_get_nation_from_state_ownership(si);
615 auto def = state.world.state_instance_get_definition(si);
616 for(
auto p : state.world.state_definition_get_abstract_state_membership(def)) {
617 if(p.get_province().get_nation_from_province_ownership() == owner) {
627 auto owner = state.world.state_instance_get_nation_from_state_ownership(si);
628 auto def = state.world.state_instance_get_definition(si);
629 for(
auto p : state.world.state_definition_get_abstract_state_membership(def)) {
630 if(p.get_province().get_nation_from_province_ownership() == owner) {
639 auto owner = state.world.state_instance_get_nation_from_state_ownership(si);
640 auto def = state.world.state_instance_get_definition(si);
641 for(
auto p : state.world.state_definition_get_abstract_state_membership(def)) {
642 if(p.get_province().get_nation_from_province_ownership() == owner) {
650 if(!state.world.nation_get_is_at_war(a) || !state.world.nation_get_is_at_war(b))
652 for(
auto wa : state.world.nation_get_war_participant(a)) {
654 for(
auto o : wa.get_war().get_war_participant()) {
655 if(o.get_nation() == b)
663 for(
auto wa : state.world.nation_get_war_participant(a)) {
665 for(
auto o : wa.get_war().get_war_participant()) {
666 if(o.get_nation() == b)
674 for(
auto wa : state.world.nation_get_war_participant(a)) {
675 for(
auto o : wa.get_war().get_war_participant()) {
676 if(o.get_nation() == b)
684 std::vector<dcon::war_id> wars;
685 for(
auto wa : state.world.nation_get_war_participant(a)) {
686 for(
auto o : wa.get_war().get_war_participant()) {
687 if(o.get_nation() == b && o.get_is_attacker() == wa.get_is_attacker()) {
688 wars.push_back(wa.get_war());
692 for(
const auto w : wars) {
704 for(
auto wa : state.world.nation_get_war_participant(a)) {
706 for(
auto o : wa.get_war().get_war_participant()) {
707 if(o.get_nation() == b) {
723 auto target_war_participants = state.world.war_get_war_participant(w);
724 for(
auto wa : state.world.nation_get_war_participant(a)) {
725 for(
auto other_participants : wa.get_war().get_war_participant()) {
726 if(other_participants.get_is_attacker() ==
727 wa.get_is_attacker()) {
728 for(
auto tp : target_war_participants) {
729 if(tp.get_nation() == other_participants.get_nation() && tp.get_is_attacker() != as_attacker)
733 for(
auto tp : target_war_participants) {
734 if(tp.get_nation() == other_participants.get_nation())
744 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
752 auto from = state.world.wargoal_get_added_by(wg);
753 for(
auto p : state.world.war_get_war_participant(w)) {
754 if(p.get_nation() == from)
755 return !p.get_is_attacker();
761 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
769 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
776 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
784 for(
auto p : state.world.war_get_war_participant(w)) {
785 if(p.get_is_attacker() ==
false) {
800 float modifier = 1.0f;
801 auto prov_controller = state.world.province_get_nation_from_province_control(p);
802 auto self_controlled = prov_controller == n;
803 if(state.world.province_get_nation_from_province_ownership(p) == n && self_controlled) {
805 }
else if(self_controlled ||
806 bool(state.world.province_get_rebel_faction_from_province_rebel_control(p))) {
808 }
else if(
auto dip_rel = state.world.get_diplomatic_relation_by_diplomatic_pair(prov_controller, n);
809 state.world.diplomatic_relation_get_are_allied(dip_rel)) {
811 }
else if(
auto uni_rel = state.world.get_unilateral_relationship_by_unilateral_pair(prov_controller, n);
812 state.world.unilateral_relationship_get_military_access(uni_rel)) {
814 }
else if(
bool(state.world.get_core_by_prov_tag_key(p, state.world.nation_get_identity_from_identity_holder(n)))) {
816 }
else if(state.world.province_get_siege_progress(p) > 0.0f) {
819 auto base_supply_lim = (state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::supply_limit) + 1.0f);
820 auto national_supply_lim = (state.world.nation_get_modifier_values(n, sys::national_mod_offsets::supply_limit) + 1.0f);
821 return int32_t(base_supply_lim * modifier * national_supply_lim);
825 for(
auto pop : state.world.province_get_pop_location(p)) {
826 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
827 auto regs = pop.get_pop().get_regiment_source();
828 total += int32_t(regs.end() - regs.begin());
837 if(fatten(state.world, p).get_is_colonial())
841 for(
auto pop : state.world.province_get_pop_location(p)) {
842 if(pop.get_pop().get_poptype() != state.culture_definitions.soldiers &&
844 auto regs = pop.get_pop().get_regiment_source();
845 total += int32_t(regs.end() - regs.begin());
852 auto type = state.world.pop_get_poptype(p);
853 if(type == state.culture_definitions.soldiers) {
854 auto location = state.world.pop_get_province_from_pop_location(p);
855 if(state.world.province_get_is_colonial(location)) {
856 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
857 float minimum = state.defines.pop_min_size_for_regiment;
859 if(state.world.pop_get_size(p) >= minimum) {
860 return int32_t((state.world.pop_get_size(p) / divisor) + 1);
863 }
else if(!state.world.province_get_is_owner_core(location)) {
864 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
865 float minimum = state.defines.pop_min_size_for_regiment;
867 if(state.world.pop_get_size(p) >= minimum) {
868 return int32_t((state.world.pop_get_size(p) / divisor) + 1);
872 float divisor = state.defines.pop_size_per_regiment;
873 float minimum = state.defines.pop_min_size_for_regiment;
875 if(state.world.pop_get_size(p) >= minimum) {
876 return int32_t((state.world.pop_get_size(p) / divisor) + 1);
893 if(state.world.province_get_is_colonial(p)) {
894 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
895 float minimum = state.defines.pop_min_size_for_regiment;
897 for(
auto pop : state.world.province_get_pop_location(p)) {
898 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
899 if(pop.get_pop().get_size() >= minimum) {
900 total += int32_t((pop.get_pop().get_size() / divisor) + 1);
904 }
else if(!state.world.province_get_is_owner_core(p)) {
905 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
906 float minimum = state.defines.pop_min_size_for_regiment;
908 for(
auto pop : state.world.province_get_pop_location(p)) {
909 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
910 if(pop.get_pop().get_size() >= minimum) {
911 total += int32_t((pop.get_pop().get_size() / divisor) + 1);
916 float divisor = state.defines.pop_size_per_regiment;
917 float minimum = state.defines.pop_min_size_for_regiment;
919 for(
auto pop : state.world.province_get_pop_location(p)) {
920 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
921 if(pop.get_pop().get_size() >= minimum) {
922 total += int32_t((pop.get_pop().get_size() / divisor) + 1);
931 for(
auto pop : state.world.province_get_pop_location(p)) {
932 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers && pop.get_pop().get_is_primary_or_accepted_culture()) {
933 auto regs = pop.get_pop().get_regiment_source();
934 total += int32_t(regs.end() - regs.begin());
947 if(state.world.province_get_is_colonial(p)) {
948 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
949 float minimum = state.defines.pop_min_size_for_regiment;
951 for(
auto pop : state.world.province_get_pop_location(p)) {
952 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers &&
953 pop.get_pop().get_is_primary_or_accepted_culture()) {
954 if(pop.get_pop().get_size() >= minimum) {
955 total += int32_t((pop.get_pop().get_size() / divisor) + 1);
959 }
else if(!state.world.province_get_is_owner_core(p)) {
960 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
961 float minimum = state.defines.pop_min_size_for_regiment;
963 for(
auto pop : state.world.province_get_pop_location(p)) {
964 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers &&
965 pop.get_pop().get_is_primary_or_accepted_culture()) {
966 if(pop.get_pop().get_size() >= minimum) {
967 total += int32_t(pop.get_pop().get_size() / divisor);
972 float divisor = state.defines.pop_size_per_regiment;
973 float minimum = state.defines.pop_min_size_for_regiment;
975 for(
auto pop : state.world.province_get_pop_location(p)) {
976 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers &&
977 pop.get_pop().get_is_primary_or_accepted_culture()) {
978 if(pop.get_pop().get_size() >= minimum) {
979 total += int32_t(pop.get_pop().get_size() / divisor);
988 for(
auto pop : state.world.province_get_pop_location(p)) {
989 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
990 auto regs = pop.get_pop().get_province_land_construction();
991 total += int32_t(regs.end() - regs.begin());
998 for(
auto pop : state.world.province_get_pop_location(p)) {
999 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers && pop.get_pop().get_is_primary_or_accepted_culture()) {
1000 auto regs = pop.get_pop().get_province_land_construction();
1001 total += int32_t(regs.end() - regs.begin());
1010 if(state.world.province_get_is_colonial(p)) {
1011 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
1012 float minimum = state.defines.pop_min_size_for_regiment;
1014 for(
auto pop : state.world.province_get_pop_location(p)) {
1015 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
1016 if(pop.get_pop().get_size() >= minimum && pop.get_pop().get_culture() == pop_culture) {
1017 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
1018 auto regs = pop.get_pop().get_regiment_source();
1019 auto building = pop.get_pop().get_province_land_construction();
1021 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
1022 return pop.get_pop().id;
1027 return dcon::pop_id{};
1028 }
else if(!state.world.province_get_is_owner_core(p)) {
1029 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
1030 float minimum = state.defines.pop_min_size_for_regiment;
1032 for(
auto pop : state.world.province_get_pop_location(p)) {
1033 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
1034 if(pop.get_pop().get_size() >= minimum && pop.get_pop().get_culture() == pop_culture) {
1035 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
1036 auto regs = pop.get_pop().get_regiment_source();
1037 auto building = pop.get_pop().get_province_land_construction();
1039 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
1040 return pop.get_pop().id;
1045 return dcon::pop_id{};
1047 float divisor = state.defines.pop_size_per_regiment;
1048 float minimum = state.defines.pop_min_size_for_regiment;
1050 for(
auto pop : state.world.province_get_pop_location(p)) {
1051 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
1052 if(pop.get_pop().get_size() >= minimum && pop.get_pop().get_culture() == pop_culture) {
1053 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
1054 auto regs = pop.get_pop().get_regiment_source();
1055 auto building = pop.get_pop().get_province_land_construction();
1057 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
1058 return pop.get_pop().id;
1063 return dcon::pop_id{};
1068 if(state.world.province_get_is_colonial(p)) {
1069 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
1070 float minimum = state.defines.pop_min_size_for_regiment;
1072 dcon::pop_id non_preferred;
1073 for(
auto pop : state.world.province_get_pop_location(p)) {
1074 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
1075 if(pop.get_pop().get_size() >= minimum) {
1076 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
1077 auto regs = pop.get_pop().get_regiment_source();
1078 auto building = pop.get_pop().get_province_land_construction();
1080 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
1081 if(require_accepted == pop.get_pop().get_is_primary_or_accepted_culture())
1082 return pop.get_pop().id;
1084 non_preferred = pop.get_pop().id;
1089 return non_preferred;
1090 }
else if(!state.world.province_get_is_owner_core(p)) {
1091 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
1092 float minimum = state.defines.pop_min_size_for_regiment;
1094 dcon::pop_id non_preferred;
1095 for(
auto pop : state.world.province_get_pop_location(p)) {
1096 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
1097 if(pop.get_pop().get_size() >= minimum) {
1098 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
1099 auto regs = pop.get_pop().get_regiment_source();
1100 auto building = pop.get_pop().get_province_land_construction();
1102 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
1103 if(require_accepted == pop.get_pop().get_is_primary_or_accepted_culture())
1104 return pop.get_pop().id;
1106 non_preferred = pop.get_pop().id;
1111 return non_preferred;
1113 float divisor = state.defines.pop_size_per_regiment;
1114 float minimum = state.defines.pop_min_size_for_regiment;
1116 dcon::pop_id non_preferred;
1117 for(
auto pop : state.world.province_get_pop_location(p)) {
1118 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
1119 if(pop.get_pop().get_size() >= minimum) {
1120 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
1121 auto regs = pop.get_pop().get_regiment_source();
1122 auto building = pop.get_pop().get_province_land_construction();
1124 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
1125 if(require_accepted == pop.get_pop().get_is_primary_or_accepted_culture())
1126 return pop.get_pop().id;
1128 non_preferred = pop.get_pop().id;
1133 return non_preferred;
1141 auto fp = fatten(state.world, p);
1142 if(fp.get_is_colonial() || fp.get_nation_from_province_control() != fp.get_nation_from_province_ownership())
1148 std::max(0.0f, fp.get_nation_from_province_ownership().get_modifier_values(sys::national_mod_offsets::mobilization_size));
1150 for(
auto pop : state.world.province_get_pop_location(p)) {
1160 total += int32_t(pop.get_pop().get_size() *
mobilization_size / state.defines.pop_size_per_regiment);
1168 for(
auto p : state.world.nation_get_province_ownership(n)) {
1169 if(p.get_province().get_is_colonial() ==
false)
1176 state.world.nation_set_recruitable_regiments(n, uint16_t(0));
1177 for(
auto p : state.world.nation_get_province_ownership(n)) {
1182 state.world.execute_serial_over_nation([&](
auto ids) { state.world.nation_set_recruitable_regiments(ids, ve::int_vector(0)); });
1183 state.world.for_each_province([&](dcon::province_id p) {
1184 auto owner = state.world.province_get_nation_from_province_ownership(p);
1191 state.world.execute_serial_over_nation([&](
auto ids) { state.world.nation_set_active_regiments(ids, ve::int_vector(0)); });
1192 state.world.for_each_army([&](dcon::army_id a) {
1193 auto owner = state.world.army_get_controller_from_army_control(a);
1195 auto regs_range = state.world.army_get_army_membership(a);
1196 auto num_regs = regs_range.end() - regs_range.begin();
1197 state.world.nation_get_active_regiments(owner) += uint16_t(num_regs);
1207 auto const max = state.military_definitions.unit_base_definitions.size();
1208 state.world.for_each_nation([&](dcon::nation_id n) {
1212 auto lo_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_attack_modifier);
1213 auto ld_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_defense_modifier);
1215 for(
uint32_t i = 2; i < max; ++i) {
1216 dcon::unit_type_id u{dcon::unit_type_id::value_base_t(i)};
1217 if((state.world.nation_get_active_unit(n, u) || state.military_definitions.unit_base_definitions[u].active) && state.military_definitions.unit_base_definitions[u].is_land) {
1218 auto& reg_stats = state.world.nation_get_unit_stats(n, u);
1219 total += ((reg_stats.defence_or_hull + ld_mod) + (reg_stats.attack_or_gun_power + lo_mod)) *
1220 state.military_definitions.unit_base_definitions[u].discipline_or_evasion;
1224 state.world.nation_set_averge_land_unit_score(n, total / count);
1232 state.world.for_each_nation([&](dcon::nation_id n) {
1234 auto no_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::naval_attack_modifier);
1235 auto nd_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::naval_defense_modifier);
1237 for(
auto nv : state.world.nation_get_navy_control(n)) {
1238 for(auto shp : nv.get_navy().get_navy_membership()) {
1239 if(state.military_definitions.unit_base_definitions[shp.get_ship().get_type()].capital) {
1240 auto& ship_stats = state.world.nation_get_unit_stats(n, shp.get_ship().get_type());
1241 total += (ship_stats.defence_or_hull + nd_mod) * (ship_stats.attack_or_gun_power + no_mod);
1245 state.world.nation_set_capital_ship_score(n, total / 250.0f);
1250 return int32_t(state.world.nation_get_naval_supply_points(n));
1253 return int32_t(state.world.nation_get_used_naval_supply_points(n));
1261 for(
auto c :
dcon::fatten(state.world, prov).get_core()) {
1263 return uint32_t(state.defines.naval_base_supply_score_empty);
1267 return uint32_t(state.defines.naval_base_supply_score_empty * state.defines.naval_base_non_core_supply_score);
1269 return uint32_t(state.defines.naval_base_supply_score_empty);
1280 state.world.for_each_nation([&](dcon::nation_id n) {
1281 auto cap_region = state.world.province_get_connected_region_id(state.world.nation_get_capital(n));
1283 for(
auto si : state.world.nation_get_state_ownership(n)) {
1284 auto d = state.world.state_instance_get_definition(si.get_state());
1285 bool saw_coastal = false;
1286 bool nb_was_core = false;
1287 bool coast_was_core = false;
1288 int32_t nb_level = 0;
1289 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
1290 if(p.get_province().get_nation_from_province_ownership() == n) {
1291 if(p.get_province().get_is_coast()) {
1293 coast_was_core = coast_was_core || p.get_province().get_is_owner_core();
1295 nb_level = std::max(nb_level, int32_t(p.get_province().get_building_level(uint8_t(economy::province_building_type::naval_base))));
1297 nb_was_core = p.get_province().get_is_owner_core();
1300 bool connected = si.get_state().get_capital().get_connected_region_id() == cap_region;
1304 if(nb_was_core || connected)
1305 total += state.defines.naval_base_supply_score_base * float(1 << (nb_level - 1));
1307 total += state.defines.naval_base_supply_score_base * float(1 << (nb_level - 1)) * state.defines.naval_base_non_core_supply_score;
1309 if(coast_was_core || connected)
1310 total += state.defines.naval_base_supply_score_empty;
1316 state.world.nation_set_naval_supply_points(n, uint16_t(total));
1323 state.world.for_each_nation([&](dcon::nation_id n) {
1325 for(
auto nv :
state.world.nation_get_navy_control(n)) {
1326 for(auto shp : nv.get_navy().get_navy_membership()) {
1327 total += state.military_definitions.unit_base_definitions[shp.get_ship().get_type()].supply_consumption_score;
1330 state.world.nation_set_used_naval_supply_points(n, uint16_t(total));
1336 return state.world.nation_get_modifier_values(n, sys::national_mod_offsets::mobilization_size);
1341 return state.world.nation_get_modifier_values(
nations, sys::national_mod_offsets::mobilization_size);
1349 * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::mobilization_impact),
1357 auto impact = (1.f - size) * state.world.nation_get_modifier_values(
nations, sys::national_mod_offsets::mobilization_impact);
1358 return ve::min(ve::max(impact, 0.f), 1.f);
1362 for(
auto n : state.world.in_nation) {
1363 if(state.current_date == n.get_reparations_until()) {
1364 for(
auto urel : n.get_unilateral_relationship_as_source()) {
1365 urel.set_reparations(
false);
1368 auto current_cbs = n.get_available_cbs();
1369 for(
uint32_t i = current_cbs.size(); i-- > 0;) {
1370 if(current_cbs[i].expiration && current_cbs[i].expiration <= state.current_date) {
1371 current_cbs.remove_at(i);
1376 if(n.get_constructing_cb_type()) {
1381 auto target = n.get_constructing_cb_target();
1382 if(
military::are_at_war(state, n, target) || state.world.nation_get_owned_province_count(target) == 0 ||
1384 if(n == state.local_player_nation) {
1389 "msg_fab_canceled_title",
1390 n, dcon::nation_id{}, dcon::nation_id{},
1395 n.set_constructing_cb_is_discovered(
false);
1396 n.set_constructing_cb_progress(0.0f);
1397 n.set_constructing_cb_target(dcon::nation_id{});
1398 n.set_constructing_cb_type(dcon::cb_type_id{});
1399 n.set_constructing_cb_target_state(dcon::state_definition_id{});
1410 auto eff_speed = state.defines.cb_generation_base_speed * n.get_constructing_cb_type().get_construction_speed() * (n.get_modifier_values(sys::national_mod_offsets::cb_generation_speed_modifier) + 1.0f);
1412 n.get_constructing_cb_progress() += std::max(eff_speed, 0.0f);
1420 if(!n.get_constructing_cb_is_discovered() && eff_speed > 0.0f) {
1422 if(val <=
uint32_t(state.defines.cb_detection_chance_base)) {
1424 n.set_constructing_cb_is_discovered(
true);
1432 if(n.get_constructing_cb_progress() >= 100.0f) {
1433 add_cb(state, n, n.get_constructing_cb_type(), n.get_constructing_cb_target(), n.get_constructing_cb_target_state());
1435 if(n == state.local_player_nation) {
1438 text::add_line(state, contents,
"msg_fab_finished_1", text::variable_type::x, state.world.cb_type_get_name(c), text::variable_type::y, t);
1440 "msg_fab_finished_title",
1441 n, dcon::nation_id{}, dcon::nation_id{},
1446 n.set_constructing_cb_is_discovered(
false);
1447 n.set_constructing_cb_progress(0.0f);
1448 n.set_constructing_cb_target(dcon::nation_id{});
1449 n.set_constructing_cb_type(dcon::cb_type_id{});
1450 n.set_constructing_cb_target_state(dcon::state_definition_id{});
1456void add_cb(
sys::state& state, dcon::nation_id n, dcon::cb_type_id cb, dcon::nation_id target, dcon::state_definition_id target_state = dcon::state_definition_id{}) {
1457 auto current_cbs = state.world.nation_get_available_cbs(n);
1458 current_cbs.push_back(
military::available_cb{ state.current_date + int32_t(state.defines.created_cb_valid_time) * 30, target, cb, target_state });
1462 float total_population = 0.f;
1463 auto total_countries = 0;
1465 auto target_civilized = state.world.nation_get_is_civilized(target);
1467 for(
auto n : state.world.in_nation) {
1470 auto is_civilized = state.world.nation_get_is_civilized(n);
1472 if(target_civilized != is_civilized) {
1476 total_population += n_pop;
1477 total_countries += (n_pop > 0) ? 1 : 0;
1480 float country_population = state.world.nation_get_demographics(target,
demographics::total);
1482 return std::clamp(
math::sqrt(country_population / (total_population / total_countries)), 0.5f, 2.0f);
1486 if(cb_state == dcon::state_definition_id{}) {
1491 float total_population = 0.f;
1492 auto total_states = 0;
1493 float state_population = 0;
1495 auto target_civilized = state.world.nation_get_is_civilized(target);
1497 for(
auto s : state.world.in_state_instance) {
1500 auto n = state.world.state_instance_get_nation_from_state_ownership(s);
1501 auto is_civilized = state.world.nation_get_is_civilized(n);
1503 if(target_civilized != is_civilized) {
1508 total_population += s_pop;
1509 total_states += (s_pop > 0) ? 1 : 0;
1511 if(s.get_definition() == cb_state) {
1512 state_population = s_pop;
1516 return std::clamp(
math::sqrt(state_population / (total_population / total_states)), 0.5f, 2.0f);
1519float cb_infamy(
sys::state& state, dcon::cb_type_id t, dcon::nation_id target, dcon::state_definition_id cb_state) {
1521 auto bits = state.world.cb_type_get_type_bits(t);
1523 if((bits & cb_flag::po_remove_prestige) != 0) {
1524 total += state.defines.infamy_prestige;
1526 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1529 if((bits & cb_flag::po_gunboat) != 0) {
1532 if((bits & cb_flag::po_annex) != 0) {
1535 if((bits & cb_flag::po_make_puppet) != 0) {
1538 if((bits & cb_flag::po_release_puppet) != 0) {
1541 if((bits & cb_flag::po_status_quo) != 0) {
1542 total += state.defines.infamy_status_quo;
1544 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1547 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1550 if((bits & cb_flag::po_remove_cores) != 0) {
1553 if((bits & cb_flag::po_colony) != 0) {
1556 if((bits & cb_flag::po_destroy_forts) != 0) {
1559 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1562 if((bits & cb_flag::po_add_to_sphere) != 0) {
1565 if((bits & cb_flag::po_disarmament) != 0) {
1568 if((bits & cb_flag::po_reparations) != 0) {
1572 auto infamy_state_mod = 1.0f;
1577 if((bits & cb_flag::po_demand_state) != 0) {
1578 total += state.defines.infamy_demand_state * infamy_state_mod;
1580 if((bits & cb_flag::po_transfer_provinces) != 0) {
1581 total += state.defines.infamy_transfer_provinces * infamy_state_mod;
1584 return total * state.world.cb_type_get_badboy_factor(t);
1589 auto bits = state.world.cb_type_get_type_bits(t);
1591 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1592 total += state.defines.breaktruce_prestige_clear_union_sphere;
1594 if((bits & cb_flag::po_gunboat) != 0) {
1595 total += state.defines.breaktruce_prestige_gunboat;
1597 if((bits & cb_flag::po_annex) != 0) {
1598 total += state.defines.breaktruce_prestige_annex;
1600 if((bits & cb_flag::po_demand_state) != 0) {
1601 total += state.defines.breaktruce_prestige_demand_state;
1603 if((bits & cb_flag::po_add_to_sphere) != 0) {
1604 total += state.defines.breaktruce_prestige_add_to_sphere;
1606 if((bits & cb_flag::po_disarmament) != 0) {
1607 total += state.defines.breaktruce_prestige_disarmament;
1609 if((bits & cb_flag::po_reparations) != 0) {
1610 total += state.defines.breaktruce_prestige_reparations;
1612 if((bits & cb_flag::po_transfer_provinces) != 0) {
1613 total += state.defines.breaktruce_prestige_transfer_provinces;
1615 if((bits & cb_flag::po_remove_prestige) != 0) {
1616 total += state.defines.breaktruce_prestige_prestige;
1618 if((bits & cb_flag::po_make_puppet) != 0) {
1619 total += state.defines.breaktruce_prestige_make_puppet;
1621 if((bits & cb_flag::po_release_puppet) != 0) {
1622 total += state.defines.breaktruce_prestige_release_puppet;
1624 if((bits & cb_flag::po_status_quo) != 0) {
1625 total += state.defines.breaktruce_prestige_status_quo;
1627 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1628 total += state.defines.breaktruce_prestige_install_communist_gov_type;
1630 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1631 total += state.defines.breaktruce_prestige_uninstall_communist_gov_type;
1633 if((bits & cb_flag::po_remove_cores) != 0) {
1634 total += state.defines.breaktruce_prestige_remove_cores;
1636 if((bits & cb_flag::po_colony) != 0) {
1637 total += state.defines.breaktruce_prestige_colony;
1639 if((bits & cb_flag::po_destroy_forts) != 0) {
1640 total += state.defines.breaktruce_prestige_destroy_forts;
1642 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1643 total += state.defines.breaktruce_prestige_destroy_naval_bases;
1646 return total * state.world.cb_type_get_break_truce_prestige_factor(t);
1650 auto bits = state.world.cb_type_get_type_bits(t);
1652 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1653 total += state.defines.breaktruce_militancy_clear_union_sphere;
1655 if((bits & cb_flag::po_gunboat) != 0) {
1656 total += state.defines.breaktruce_militancy_gunboat;
1658 if((bits & cb_flag::po_annex) != 0) {
1659 total += state.defines.breaktruce_militancy_annex;
1661 if((bits & cb_flag::po_demand_state) != 0) {
1662 total += state.defines.breaktruce_militancy_demand_state;
1664 if((bits & cb_flag::po_add_to_sphere) != 0) {
1665 total += state.defines.breaktruce_militancy_add_to_sphere;
1667 if((bits & cb_flag::po_disarmament) != 0) {
1668 total += state.defines.breaktruce_militancy_disarmament;
1670 if((bits & cb_flag::po_reparations) != 0) {
1671 total += state.defines.breaktruce_militancy_reparations;
1673 if((bits & cb_flag::po_transfer_provinces) != 0) {
1674 total += state.defines.breaktruce_militancy_transfer_provinces;
1676 if((bits & cb_flag::po_remove_prestige) != 0) {
1677 total += state.defines.breaktruce_militancy_prestige;
1679 if((bits & cb_flag::po_make_puppet) != 0) {
1680 total += state.defines.breaktruce_militancy_make_puppet;
1682 if((bits & cb_flag::po_release_puppet) != 0) {
1683 total += state.defines.breaktruce_militancy_release_puppet;
1685 if((bits & cb_flag::po_status_quo) != 0) {
1686 total += state.defines.breaktruce_militancy_status_quo;
1688 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1689 total += state.defines.breaktruce_militancy_install_communist_gov_type;
1691 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1692 total += state.defines.breaktruce_militancy_uninstall_communist_gov_type;
1694 if((bits & cb_flag::po_remove_cores) != 0) {
1695 total += state.defines.breaktruce_militancy_remove_cores;
1697 if((bits & cb_flag::po_colony) != 0) {
1698 total += state.defines.breaktruce_militancy_colony;
1700 if((bits & cb_flag::po_destroy_forts) != 0) {
1701 total += state.defines.breaktruce_militancy_destroy_forts;
1703 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1704 total += state.defines.breaktruce_militancy_destroy_naval_bases;
1707 return total * state.world.cb_type_get_break_truce_militancy_factor(t);
1711 auto bits = state.world.cb_type_get_type_bits(t);
1713 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1716 if((bits & cb_flag::po_gunboat) != 0) {
1719 if((bits & cb_flag::po_annex) != 0) {
1722 if((bits & cb_flag::po_demand_state) != 0) {
1725 if((bits & cb_flag::po_add_to_sphere) != 0) {
1728 if((bits & cb_flag::po_disarmament) != 0) {
1731 if((bits & cb_flag::po_reparations) != 0) {
1734 if((bits & cb_flag::po_transfer_provinces) != 0) {
1737 if((bits & cb_flag::po_remove_prestige) != 0) {
1738 total += state.defines.breaktruce_infamy_prestige;
1740 if((bits & cb_flag::po_make_puppet) != 0) {
1743 if((bits & cb_flag::po_release_puppet) != 0) {
1746 if((bits & cb_flag::po_status_quo) != 0) {
1747 total += state.defines.breaktruce_infamy_status_quo;
1749 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1752 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1755 if((bits & cb_flag::po_remove_cores) != 0) {
1758 if((bits & cb_flag::po_colony) != 0) {
1761 if((bits & cb_flag::po_destroy_forts) != 0) {
1764 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1768 return total * state.world.cb_type_get_break_truce_infamy_factor(t);
1779 if(!state.world.province_get_is_colonial(p)) {
1782 auto fac_range = state.world.province_get_factory_location(p);
1783 total += int32_t(fac_range.end() - fac_range.begin());
1786 auto owner_cap = state.world.nation_get_capital(n);
1787 auto overseas = (state.world.province_get_continent(p) != state.world.province_get_continent(owner_cap)) &&
1788 (state.world.province_get_connected_region_id(p) != state.world.province_get_connected_region_id(owner_cap));
1790 if(state.world.province_get_is_owner_core(p) && !overseas) {
1793 if(state.world.nation_get_capital(n) == p) {
1799int32_t
peace_cost(
sys::state& state, dcon::war_id war, dcon::cb_type_id wargoal, dcon::nation_id from, dcon::nation_id target,
1800 dcon::nation_id secondary_nation, dcon::state_definition_id wargoal_state, dcon::national_identity_id wargoal_tag) {
1814 auto bits = state.world.cb_type_get_type_bits(wargoal);
1816 if((bits & cb_flag::great_war_obligatory) != 0) {
1820 if((bits & cb_flag::po_gunboat) != 0) {
1821 total += state.defines.peace_cost_gunboat;
1823 if((bits & cb_flag::po_annex) != 0) {
1824 total += state.defines.peace_cost_annex;
1826 if((bits & cb_flag::po_add_to_sphere) != 0) {
1827 total += state.defines.peace_cost_add_to_sphere;
1829 if((bits & cb_flag::po_disarmament) != 0) {
1830 total += state.defines.peace_cost_disarmament;
1832 if((bits & cb_flag::po_reparations) != 0) {
1833 total += state.defines.peace_cost_reparations;
1835 if((bits & cb_flag::po_remove_prestige) != 0) {
1836 total += state.defines.peace_cost_prestige;
1838 if((bits & cb_flag::po_make_puppet) != 0) {
1839 total += state.defines.peace_cost_make_puppet;
1841 if((bits & cb_flag::po_release_puppet) != 0) {
1842 total += state.defines.peace_cost_release_puppet;
1844 if((bits & cb_flag::po_status_quo) != 0) {
1845 total += state.defines.peace_cost_status_quo;
1847 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1848 total += state.defines.peace_cost_install_communist_gov_type;
1850 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1851 total += state.defines.peace_cost_uninstall_communist_gov_type;
1853 if((bits & cb_flag::po_remove_cores) != 0) {
1854 total += state.defines.peace_cost_remove_cores;
1856 if((bits & cb_flag::po_colony) != 0) {
1857 total += state.defines.peace_cost_colony;
1859 if((bits & cb_flag::po_destroy_forts) != 0) {
1860 total += state.defines.peace_cost_destroy_forts;
1862 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1863 total += state.defines.peace_cost_destroy_naval_bases;
1866 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1867 auto from_group = state.world.nation_get_primary_culture(from).get_group_from_culture_group_membership();
1868 for(
auto target_sphere : state.world.nation_get_gp_relationship_as_great_power(target)) {
1870 target_sphere.get_influence_target().get_primary_culture().get_group_from_culture_group_membership() == from_group) {
1872 total += state.defines.peace_cost_clear_union_sphere;
1876 if((bits & (cb_flag::po_transfer_provinces | cb_flag::po_demand_state)) != 0) {
1877 int32_t sum_target_prov_values = 0;
1878 for(
auto prv : state.world.nation_get_province_ownership(target)) {
1881 auto secondary = secondary_nation ? secondary_nation : state.world.national_identity_get_nation_from_identity_holder(wargoal_tag);
1882 bool is_lib = (bits & cb_flag::po_transfer_provinces) != 0;
1884 if(sum_target_prov_values > 0) {
1885 if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states && (bits & cb_flag::all_allowed_states) != 0) {
1886 for(
auto si : state.world.nation_get_state_ownership(target)) {
1891 total += 280.0f * float(province_point_cost(state, tprov, target)) / float(sum_target_prov_values);
1896 for(
auto tprov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
1897 if(tprov.get_province().get_nation_from_province_ownership() == target)
1898 total += 280.0f * float(
province_point_cost(state, tprov.get_province(), target)) / float(sum_target_prov_values);
1904 if(state.world.war_get_is_great(war)) {
1906 for(
auto par : state.world.war_get_war_participant(war)) {
1907 if(par.get_nation() == from) {
1912 if(state.military_definitions.world_wars_enabled &&
1915 total *= state.defines.gw_warscore_cost_mod_2;
1917 total *= state.defines.gw_warscore_cost_mod;
1921 return std::min(int32_t(total * state.world.cb_type_get_peace_cost_factor(wargoal)), 100);
1925 auto war = state.world.peace_offer_get_war_from_war_settlement(offer);
1927 for(
auto wg : state.world.peace_offer_get_peace_offer_item(offer)) {
1928 total +=
peace_cost(state, war, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(),
1929 wg.get_wargoal().get_target_nation(), wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(),
1930 wg.get_wargoal().get_associated_tag());
1935 int32_t max_months = 0;
1936 for(
auto wg : state.world.peace_offer_get_peace_offer_item(offer)) {
1937 max_months = std::max(max_months, int32_t(wg.get_wargoal().get_type().get_truce_months()));
1939 return max_months + int32_t(state.defines.base_truce_months);
1943 for(
auto wg : state.world.war_get_wargoals_attached(war)) {
1944 if(
is_attacker(state, war, wg.get_wargoal().get_added_by())) {
1945 total +=
peace_cost(state, war, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(),
1946 wg.get_wargoal().get_target_nation(), wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(),
1947 wg.get_wargoal().get_associated_tag());
1954 for(
auto wg : state.world.war_get_wargoals_attached(war)) {
1955 if(!
is_attacker(state, war, wg.get_wargoal().get_added_by())) {
1956 total +=
peace_cost(state, war, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(),
1957 wg.get_wargoal().get_target_nation(), wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(),
1958 wg.get_wargoal().get_associated_tag());
1966 auto bits = state.world.cb_type_get_type_bits(t);
1969 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1970 total += std::max(state.defines.prestige_clear_union_sphere * actor_prestige, state.defines.prestige_clear_union_sphere_base);
1972 if((bits & cb_flag::po_gunboat) != 0) {
1973 total += std::max(state.defines.prestige_gunboat * actor_prestige, state.defines.prestige_gunboat_base);
1975 if((bits & cb_flag::po_annex) != 0) {
1976 total += std::max(state.defines.prestige_annex * actor_prestige, state.defines.prestige_annex_base);
1978 if((bits & cb_flag::po_demand_state) != 0) {
1979 total += std::max(state.defines.prestige_demand_state * actor_prestige, state.defines.prestige_demand_state_base);
1981 if((bits & cb_flag::po_add_to_sphere) != 0) {
1982 total += std::max(state.defines.prestige_add_to_sphere * actor_prestige, state.defines.prestige_add_to_sphere_base);
1984 if((bits & cb_flag::po_disarmament) != 0) {
1985 total += std::max(state.defines.prestige_disarmament * actor_prestige, state.defines.prestige_disarmament_base);
1987 if((bits & cb_flag::po_reparations) != 0) {
1988 total += std::max(state.defines.prestige_reparations * actor_prestige, state.defines.prestige_reparations_base);
1990 if((bits & cb_flag::po_transfer_provinces) != 0) {
1991 total += std::max(state.defines.prestige_transfer_provinces * actor_prestige, state.defines.prestige_transfer_provinces_base);
1993 if((bits & cb_flag::po_remove_prestige) != 0) {
1994 total += std::max(state.defines.prestige_prestige * actor_prestige, state.defines.prestige_prestige_base);
1996 if((bits & cb_flag::po_make_puppet) != 0) {
1997 total += std::max(state.defines.prestige_make_puppet * actor_prestige, state.defines.prestige_make_puppet_base);
1999 if((bits & cb_flag::po_release_puppet) != 0) {
2000 total += std::max(state.defines.prestige_release_puppet * actor_prestige, state.defines.prestige_release_puppet_base);
2002 if((bits & cb_flag::po_status_quo) != 0) {
2003 total += std::max(state.defines.prestige_status_quo * actor_prestige, state.defines.prestige_status_quo_base);
2005 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
2006 total += std::max(state.defines.prestige_install_communist_gov_type * actor_prestige,
2007 state.defines.prestige_install_communist_gov_type_base);
2009 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
2010 total += std::max(state.defines.prestige_uninstall_communist_gov_type * actor_prestige,
2011 state.defines.prestige_uninstall_communist_gov_type_base);
2013 if((bits & cb_flag::po_remove_cores) != 0) {
2014 total += std::max(state.defines.prestige_remove_cores * actor_prestige, state.defines.prestige_remove_cores_base);
2016 if((bits & cb_flag::po_colony) != 0) {
2017 total += std::max(state.defines.prestige_colony * actor_prestige, state.defines.prestige_colony_base);
2019 if((bits & cb_flag::po_destroy_forts) != 0) {
2020 total += std::max(state.defines.prestige_destroy_forts * actor_prestige, state.defines.prestige_destroy_forts_base);
2022 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
2024 std::max(state.defines.prestige_destroy_naval_bases * actor_prestige, state.defines.prestige_destroy_naval_bases_base);
2027 return total * state.world.cb_type_get_prestige_factor(t);
2036 return cb_infamy(state, type, target, cb_state);
2039 dcon::nation_id target, dcon::state_definition_id cb_state) {
2045 auto other_cbs = state.world.nation_get_available_cbs(from);
2046 for(
auto& cb : other_cbs) {
2051 if(state.world.war_get_is_great(war))
2052 return cb_infamy(state, type, target, cb_state) * state.defines.gw_justify_cb_badboy_impact;
2054 return cb_infamy(state, type, target, cb_state);
2058 auto allowed_nation = state.world.cb_type_get_allowed_countries(t);
2059 return bool(allowed_nation);
2062 auto bits = state.world.cb_type_get_type_bits(t);
2063 return (bits & (cb_flag::po_transfer_provinces)) != 0;
2066 auto bits = state.world.cb_type_get_type_bits(t);
2067 return (bits & (cb_flag::po_demand_state | cb_flag::po_transfer_provinces | cb_flag::po_destroy_naval_bases | cb_flag::po_destroy_forts)) != 0
2068 && (bits & cb_flag::all_allowed_states) == 0;
2077 auto infamy =
cb_infamy(state, state.world.nation_get_constructing_cb_type(n), state.world.nation_get_constructing_cb_target(n), state.world.nation_get_constructing_cb_target_state(n));
2078 auto adj_infamy = std::max(0.0f, ((100.0f - state.world.nation_get_constructing_cb_progress(n)) / 100.0f) * infamy);
2079 state.world.nation_get_infamy(n) += adj_infamy;
2081 auto target = state.world.nation_get_constructing_cb_target(n);
2085 for(
auto si : state.world.nation_get_state_ownership(target)) {
2086 if(si.get_state().get_flashpoint_tag()) {
2087 si.get_state().set_flashpoint_tension(
2088 std::min(100.0f, si.get_state().get_flashpoint_tension() + state.defines.tension_on_cb_discovered));
2094 if(n == state.local_player_nation) {
2100 "msg_fab_discovered_title",
2101 n, target, dcon::nation_id{},
2107 auto army = state.world.leader_get_army_from_army_leadership(l);
2108 if(state.world.army_get_battle_from_army_battle_participation(army))
2110 auto navy = state.world.leader_get_navy_from_navy_leadership(l);
2111 if(state.world.navy_get_battle_from_navy_battle_participation(navy))
2117 auto l = fatten(state.world, state.world.create_leader());
2118 l.set_is_admiral(!is_general);
2122 auto num_personalities =
uint32_t(state.military_definitions.first_background_trait.index() - 1);
2123 auto num_backgrounds =
uint32_t((state.world.leader_trait_size() - num_personalities) - 2);
2127 l.set_personality(dcon::leader_trait_id{dcon::leader_trait_id::value_base_t(1 +
rng::reduce(
uint32_t(trait_pair.high), num_personalities))});
2128 l.set_background(dcon::leader_trait_id{dcon::leader_trait_id::value_base_t(state.military_definitions.first_background_trait.index() + 1 +
rng::reduce(
uint32_t(trait_pair.low), num_backgrounds))});
2132 auto names = state.world.culture_get_last_names(state.world.nation_get_primary_culture(n));
2133 if(names.size() > 0) {
2137 l.set_since(state.current_date);
2141 l.set_prestige(r_factor * state.defines.leader_max_random_prestige);
2143 state.world.try_create_leader_loyalty(n, l);
2145 state.world.nation_get_leadership_points(n) -= state.defines.leader_recruit_cost;
2155 if(state.world.leader_get_nation_from_leader_loyalty(l) == state.local_player_nation) {
2156 if(state.world.leader_get_army_from_army_leadership(l) || state.world.leader_get_navy_from_navy_leadership(l)) {
2157 dcon::nation_id n = state.local_player_nation;
2159 auto is_admiral = state.world.leader_get_is_admiral(l);
2160 auto location = is_admiral ? state.world.navy_get_location_from_navy_location(state.world.leader_get_navy_from_navy_leadership(l)) : state.world.army_get_location_from_army_location(state.world.leader_get_army_from_army_leadership(l));
2161 auto name = state.world.leader_get_name(l);
2170 "msg_leader_died_title",
2171 n, dcon::nation_id{}, dcon::nation_id{},
2177 state.world.delete_leader(l);
2181 int32_t admirals = 0;
2182 int32_t generals = 0;
2187 for(
auto l : state.world.nation_get_leader_loyalty(n)) {
2188 if(l.get_leader().get_is_admiral())
2196 auto x = state.world.nation_get_army_control(n);
2197 return int32_t(x.end() - x.begin());
2200 auto x = state.world.nation_get_navy_control(n);
2201 return int32_t(x.end() - x.begin());
2210 state.world.execute_serial_over_nation(
2211 [&, optimum_officers = state.world.pop_type_get_research_optimum(state.culture_definitions.officers)](
auto ids) {
2212 auto ofrac = state.world.nation_get_demographics(ids, demographics::to_key(state, state.culture_definitions.officers)) /
2213 ve::max(state.world.nation_get_demographics(ids, demographics::total), 1.0f);
2214 auto omod = ve::min(1.0f, ofrac / optimum_officers) * float(state.culture_definitions.officer_leadership_points);
2215 auto nmod = (state.world.nation_get_modifier_values(ids, sys::national_mod_offsets::leadership_modifier) + 1.0f) *
2216 state.world.nation_get_modifier_values(ids, sys::national_mod_offsets::leadership);
2218 state.world.nation_set_leadership_points(ids, ve::select(state.world.nation_get_owned_province_count(ids) != 0, state.world.nation_get_leadership_points(ids) + omod + nmod, 0.0f));
2221 for(
auto n : state.world.in_nation) {
2222 if(n.get_leadership_points() > state.defines.leader_recruit_cost * 3.0f) {
2224 auto new_l = [&]() {
2228 if(existing_leaders.generals < army_count) {
2230 }
else if(existing_leaders.admirals < navy_count) {
2233 auto too_many_generals =
2234 (existing_leaders.admirals > 0 && navy_count > 0)
2235 ?
float(existing_leaders.generals) / float(existing_leaders.admirals) > float(army_count) / float(navy_count)
2240 if(state.world.leader_get_is_admiral(new_l)) {
2241 for(
auto v : state.world.nation_get_navy_control(n)) {
2242 if(!v.get_navy().get_admiral_from_navy_leadership()) {
2243 state.world.try_create_navy_leadership(v.get_navy(), new_l);
2248 for(
auto a : state.world.nation_get_army_control(n)) {
2249 if(!a.get_army().get_general_from_army_leadership()) {
2250 state.world.try_create_army_leadership(a.get_army(), new_l);
2265 for(
uint32_t i = state.world.leader_size(); i-- > 0;) {
2266 dcon::leader_id l{dcon::leader_id::value_base_t(i)};
2267 if(!state.world.leader_is_valid(l))
2270 auto age_in_days = state.current_date.to_raw_value() - state.world.leader_get_since(l).to_raw_value();
2271 if(age_in_days > 365 * 26) {
2272 float age_in_years = float(age_in_days) / 365.0f;
2273 float death_chance =
2274 (age_in_years * (
leader_is_in_combat(state, l) ? 2.0f : 1.0f) / state.defines.leader_age_death_factor) / 11000.0f;
2287 auto int_chance =
uint32_t(death_chance *
float(0xFFFFFFFF));
2290 if(rvalue < int_chance)
2297 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(target,
attacker);
2299 auto truce_ends = state.world.diplomatic_relation_get_truce_until(rel);
2300 if(truce_ends && state.current_date < truce_ends)
2307 auto reg = fatten(state.world, state.world.create_regiment());
2310 auto exp = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_unit_start_experience) / 100.f;
2311 exp += state.world.nation_get_modifier_values(n, sys::national_mod_offsets::regular_experience_level) / 100.f;
2312 reg.set_experience(std::clamp(exp, 0.f, 1.f));
2313 reg.set_strength(1.f);
2318 auto shp = fatten(state.world, state.world.create_ship());
2321 auto exp = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::naval_unit_start_experience) / 100.f;
2322 exp += state.world.nation_get_modifier_values(n, sys::national_mod_offsets::regular_experience_level) / 100.f;
2323 shp.set_experience(std::clamp(exp, 0.f, 1.f));
2324 shp.set_strength(1.f);
2329void give_military_access(
sys::state& state, dcon::nation_id accessing_nation, dcon::nation_id target) {
2330 auto ur = state.world.get_unilateral_relationship_by_unilateral_pair(target, accessing_nation);
2332 ur = state.world.force_create_unilateral_relationship(target, accessing_nation);
2334 state.world.unilateral_relationship_set_military_access(ur,
true);
2337 auto ur = state.world.get_unilateral_relationship_by_unilateral_pair(target, accessing_nation);
2339 state.world.unilateral_relationship_set_military_access(ur,
false);
2353 auto war = fatten(state.world, w);
2355 dcon::nation_id primary_attacker = state.world.war_get_primary_attacker(war);
2356 dcon::nation_id primary_defender = state.world.war_get_original_target(war);
2370 if(state.world.nation_get_owned_province_count(n) == 0)
2373 auto participant = state.world.force_create_war_participant(w, n);
2374 state.world.war_participant_set_is_attacker(participant, as_attacker);
2375 state.world.nation_set_is_at_war(n,
true);
2376 state.world.nation_set_disarmed_until(n,
sys::date{});
2378 for(
auto dep : state.world.nation_get_overlord_as_ruler(n)) {
2379 add_to_war(state, w, dep.get_subject(), as_attacker);
2382 for(
auto wp : state.world.war_get_war_participant(w)) {
2383 if(wp.get_is_attacker() == !as_attacker &&
nations::are_allied(state, n, wp.get_nation()))
2387 if(!as_attacker && state.world.nation_get_rank(state.world.war_get_primary_defender(w)) > state.world.nation_get_rank(n)) {
2388 state.world.war_set_primary_defender(w, n);
2391 for(
auto ul : state.world.nation_get_unilateral_relationship_as_source(n)) {
2392 if(ul.get_war_subsidies()) {
2393 auto role =
get_role(state, w, ul.get_target());
2394 if(role != war_role::none) {
2395 if((as_attacker && role == war_role::defender) || (!as_attacker && role == war_role::attacker)) {
2396 ul.set_war_subsidies(
false);
2402 "msg_wsub_end_title",
2403 n, ul.get_target().id, dcon::nation_id{},
2410 for(
auto ul : state.world.nation_get_unilateral_relationship_as_target(n)) {
2411 if(ul.get_war_subsidies()) {
2412 auto role =
get_role(state, w, ul.get_source());
2413 if(role != war_role::none) {
2414 if((as_attacker && role == war_role::defender) || (!as_attacker && role == war_role::attacker)) {
2415 ul.set_war_subsidies(
false);
2421 "msg_wsub_end_title",
2422 n, ul.get_target().id, dcon::nation_id{},
2430 if(state.military_definitions.great_wars_enabled && !state.world.war_get_is_great(w)) {
2431 int32_t gp_attackers = 0;
2432 int32_t gp_defenders = 0;
2434 for(
auto par : state.world.war_get_war_participant(w)) {
2436 if(par.get_is_attacker())
2443 if(gp_attackers >= 2 && gp_defenders >= 2) {
2445 state.world.war_set_is_great(w,
true);
2446 auto it = state.lookup_key(std::string_view{
"great_war_name"});
2448 state.world.war_set_name(w, it);
2456 "msg_war_becomes_great_title",
2457 state.local_player_nation, dcon::nation_id{}, dcon::nation_id{},
2468 "msg_war_join_title",
2469 n,
get_role(state, w, state.local_player_nation) != war_role::none ? state.local_player_nation : dcon::nation_id{}, dcon::nation_id{ },
2473 if(!on_war_creation && state.world.nation_get_is_player_controlled(n) ==
false) {
2477 for(
auto o : state.world.nation_get_army_control(n)) {
2478 if(o.get_army().get_is_retreating() || o.get_army().get_black_flag() || o.get_army().get_navy_from_army_transport() || o.get_army().get_battle_from_army_battle_participation())
2481 army_arrives_in_province(state, o.get_army(), o.get_army().get_location_from_army_location(), crossing_type::none);
2483 for(
auto o : state.world.nation_get_navy_control(n)) {
2484 if(o.get_navy().get_is_retreating() || o.get_navy().get_battle_from_navy_battle_participation())
2487 auto loc = o.get_navy().get_location_from_navy_location();
2488 if(loc.id.index() >= state.province_definitions.first_sea_province.index())
2494 for(
auto p : state.world.war_get_war_participant(w)) {
2495 if(p.get_nation() == n)
2496 return p.get_is_attacker();
2502 for(
auto p : state.world.war_get_war_participant(w)) {
2503 if(p.get_nation() == n)
2504 return p.get_is_attacker() ? war_role::attacker : war_role::defender;
2506 return war_role::none;
2510 dcon::cb_type_id primary_wargoal, dcon::state_definition_id primary_wargoal_state,
2511 dcon::national_identity_id primary_wargoal_tag, dcon::nation_id primary_wargoal_secondary) {
2512 assert(primary_attacker);
2513 assert(primary_defender);
2514 auto new_war = fatten(state.world, state.world.create_war());
2518 auto ol_rel = state.world.nation_get_overlord_as_subject(primary_defender);
2519 if(
auto ol = state.world.overlord_get_ruler(ol_rel); ol && ol == primary_attacker)
2523 auto ol_rel = state.world.nation_get_overlord_as_subject(primary_attacker);
2524 if(
auto ol = state.world.overlord_get_ruler(ol_rel); ol && ol == primary_defender)
2528 auto real_target = primary_defender;
2529 auto target_ol_rel = state.world.nation_get_overlord_as_subject(primary_defender);
2530 if(
auto ol = state.world.overlord_get_ruler(target_ol_rel); ol && ol != primary_attacker)
2533 new_war.set_primary_attacker(primary_attacker);
2534 new_war.set_primary_defender(real_target);
2535 new_war.set_start_date(state.current_date);
2536 new_war.set_over_state(primary_wargoal_state);
2537 new_war.set_over_tag(primary_wargoal_tag);
2538 new_war.set_original_target(primary_defender);
2539 if(primary_wargoal_secondary) {
2540 new_war.set_over_tag(state.world.nation_get_identity_from_identity_holder(primary_wargoal_secondary));
2543 add_to_war(state, new_war, primary_attacker,
true,
true);
2544 add_to_war(state, new_war, real_target,
false,
true);
2546 if(primary_wargoal) {
2547 add_wargoal(state, new_war, primary_attacker, primary_defender, primary_wargoal, primary_wargoal_state, primary_wargoal_tag,
2548 primary_wargoal_secondary);
2549 new_war.set_name(state.world.cb_type_get_war_name(primary_wargoal));
2551 auto it = state.lookup_key(std::string_view{
"agression_war_name"});
2553 new_war.set_name(it);
2557 if(state.world.nation_get_is_player_controlled(primary_attacker) ==
false)
2559 if(state.world.nation_get_is_player_controlled(primary_defender) ==
false)
2564 std::string resolved_war_name =
get_war_name(state, w);
2568 primary_attacker, primary_defender, dcon::nation_id{},
2579 auto fat = fatten(state.world, war);
2580 auto attacker = state.world.nation_get_identity_from_identity_holder(fat.get_primary_attacker());
2581 auto defender = state.world.nation_get_identity_from_identity_holder(fat.get_primary_defender());
2584 auto war_name_sequence = fat.get_name();
2586 auto attacker_tag_key = attacker_tag;
2587 auto defender_tag_key = defender_tag;
2588 auto war_name_key = war_name_sequence;
2590 if(attacker_tag_key && defender_tag_key && war_name_key) {
2591 std::string war_name = std::string{ state.to_string_view(war_name_key) };
2592 auto attacker_name = state.to_string_view(attacker_tag_key);
2593 auto defender_name = state.to_string_view(defender_tag_key);
2594 auto combined_name = war_name + std::string(
"_") + std::string{attacker_name} + std::string(
"_") + std::string{ defender_name };
2595 std::string_view name = std::string_view(combined_name);
2596 if(
auto it = state.lookup_key(name); it)
2604 auto ol_relation = state.world.nation_get_overlord_as_subject(n);
2605 auto ol_nation = state.world.overlord_get_ruler(ol_relation);
2609 state.world.nation_get_in_sphere_of(n) != state.world.war_get_primary_attacker(wfor) &&
2610 ol_nation != state.world.war_get_primary_attacker(wfor);
2613 state.world.nation_get_in_sphere_of(n) != state.world.war_get_primary_attacker(wfor) &&
2614 ol_nation != state.world.war_get_primary_attacker(wfor);
2618 if(is_civil_war(state, wfor))
2621 auto n = state.world.war_get_primary_defender(wfor);
2622 for(
auto drel : state.world.nation_get_diplomatic_relation(n)) {
2623 auto other_nation = drel.get_related_nations(0) != n ? drel.get_related_nations(0) : drel.get_related_nations(1);
2627 std::memset(&m, 0,
sizeof(m));
2629 m.to = other_nation;
2635 if(state.world.nation_get_in_sphere_of(n)) {
2639 std::memset(&m, 0,
sizeof(m));
2641 m.to = state.world.nation_get_in_sphere_of(n);
2649 if(is_civil_war(state, wfor))
2652 auto n = state.world.war_get_primary_attacker(wfor);
2653 for(
auto drel : state.world.nation_get_diplomatic_relation(n)) {
2654 auto other_nation = drel.get_related_nations(0) != n ? drel.get_related_nations(0) : drel.get_related_nations(1);
2655 if(drel.get_are_allied() && !
has_truce_with(state, other_nation, state.world.war_get_primary_defender(wfor)) &&
2659 std::memset(&m, 0,
sizeof(m));
2661 m.to = other_nation;
2668void add_wargoal(
sys::state& state, dcon::war_id wfor, dcon::nation_id added_by, dcon::nation_id target, dcon::cb_type_id type,
2669 dcon::state_definition_id sd, dcon::national_identity_id tag, dcon::nation_id secondary_nation) {
2672 auto for_attacker =
is_attacker(state, wfor, added_by);
2673 std::vector<dcon::nation_id> targets;
2674 for(
auto p : state.world.state_definition_get_abstract_state_membership(sd)) {
2675 auto owner = p.get_province().get_nation_from_province_ownership();
2676 if(std::find(targets.begin(), targets.end(), owner) == targets.end()) {
2677 for(
auto par : state.world.war_get_war_participant(wfor)) {
2678 if(par.get_nation() == owner && par.get_is_attacker() != for_attacker) {
2679 auto new_wg = fatten(state.world, state.world.create_wargoal());
2680 new_wg.set_added_by(added_by);
2681 new_wg.set_associated_state(sd);
2682 new_wg.set_associated_tag(tag);
2683 new_wg.set_secondary_nation(secondary_nation);
2684 new_wg.set_target_nation(owner);
2685 new_wg.set_type(type);
2686 new_wg.set_war_from_wargoals_attached(wfor);
2687 targets.push_back(owner.id);
2693 bool is_colonial_claim = (state.world.cb_type_get_type_bits(type) & cb_flag::po_colony) != 0;
2694 if(targets.empty()) {
2695 if(!is_colonial_claim) {
2698 auto new_wg = fatten(state.world, state.world.create_wargoal());
2699 new_wg.set_added_by(added_by);
2700 new_wg.set_associated_state(sd);
2701 new_wg.set_associated_tag(tag);
2702 new_wg.set_secondary_nation(secondary_nation);
2703 new_wg.set_target_nation(target);
2704 new_wg.set_type(type);
2705 new_wg.set_war_from_wargoals_attached(wfor);
2709 auto new_wg = fatten(state.world, state.world.create_wargoal());
2710 new_wg.set_added_by(added_by);
2711 new_wg.set_associated_state(sd);
2712 new_wg.set_associated_tag(tag);
2713 new_wg.set_secondary_nation(secondary_nation);
2714 new_wg.set_target_nation(target);
2715 new_wg.set_type(type);
2716 new_wg.set_war_from_wargoals_attached(wfor);
2719 if(
auto on_add = state.world.cb_type_get_on_add(type); on_add) {
2721 uint32_t(state.current_date.value),
uint32_t((added_by.index() << 7) ^ target.index() ^ (type.index() << 3)));
2725 if((state.world.cb_type_get_type_bits(type) & cb_flag::always) == 0) {
2726 auto cb_set = state.world.nation_get_available_cbs(added_by);
2727 for(
uint32_t i = cb_set.size(); i-- > 0;) {
2728 if(cb_set.at(i).cb_type == type && cb_set.at(i).target == target) {
2729 cb_set.remove_at(i);
2734 if(added_by != state.local_player_nation &&
get_role(state, wfor, state.local_player_nation) != war_role::none) {
2742 if(secondary_nation)
2752 "msg_wargoal_title",
2753 added_by, target, state.local_player_nation,
2760 for(
auto vas : state.world.nation_get_overlord_as_ruler(n)) {
2764 dcon::war_participant_id par;
2765 for(
auto p : state.world.nation_get_war_participant(n)) {
2766 if(p.get_war() == w) {
2782 auto rp_ideology = state.world.nation_get_ruling_party(n).get_ideology();
2784 for(
auto prv : state.world.nation_get_province_ownership(n)) {
2785 prv.get_province().get_party_loyalty(rp_ideology) *= (1.0f - state.defines.party_loyalty_hit_on_war_loss);
2796 float pop_militancy = 0.0f;
2798 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
2799 if(wg.get_wargoal().get_added_by() == n) {
2800 float prestige_loss = std::min(state.defines.war_failed_goal_prestige_base, state.defines.war_failed_goal_prestige *
nations::prestige_score(state, n)) * wg.get_wargoal().get_type().get_penalty_factor();
2803 pop_militancy += state.defines.war_failed_goal_militancy * wg.get_wargoal().get_type().get_penalty_factor();
2807 if(pop_militancy > 0) {
2808 for(
auto prv : state.world.nation_get_province_ownership(n)) {
2809 for(
auto pop : prv.get_province().get_pop_location()) {
2816 state.world.delete_war_participant(par);
2817 auto rem_wars = state.world.nation_get_war_participant(n);
2818 if(rem_wars.begin() == rem_wars.end()) {
2819 state.world.nation_set_is_at_war(n,
false);
2823 for(
auto p : state.world.nation_get_province_ownership(n)) {
2824 if(
auto c = p.get_province().get_nation_from_province_control(); c && c != n) {
2826 state.world.province_set_siege_progress(p.get_province(), 0.0f);
2833 for(
auto p : state.world.nation_get_province_control(n)) {
2834 if(
auto c = p.get_province().get_nation_from_province_ownership(); c && c != n) {
2836 state.world.province_set_siege_progress(p.get_province(), 0.0f);
2844 state.world.nation_set_last_war_loss(n, state.current_date);
2849 auto par = state.world.war_get_war_participant(w);
2850 state.military_definitions.pending_blackflag_update =
true;
2852 if(state.world.war_get_is_crisis_war(w)) {
2856 while(par.begin() != par.end()) {
2857 if((*par.begin()).get_is_attacker()) {
2858 remove_from_war(state, w, (*par.begin()).get_nation(), result == war_result::defender_won);
2860 remove_from_war(state, w, (*par.begin()).get_nation(), result == war_result::attacker_won);
2864 auto nbattles = state.world.war_get_naval_battle_in_war(w);
2865 while(nbattles.begin() != nbattles.end()) {
2866 end_battle(state, (*nbattles.begin()).get_battle().id, battle_result::indecisive);
2869 auto lbattles = state.world.war_get_land_battle_in_war(w);
2870 while(lbattles.begin() != lbattles.end()) {
2871 end_battle(state, (*lbattles.begin()).get_battle().id, battle_result::indecisive);
2874 state.world.delete_war(w);
2878 for(
auto a : state.world.in_army) {
2879 if(!
bool(a.get_general_from_army_leadership())) {
2880 auto controller = a.get_controller_from_army_control();
2881 for(
auto l : controller.get_leader_loyalty()) {
2882 if(l.get_leader().get_is_admiral() ==
false && !
bool(l.get_leader().get_army_from_army_leadership())) {
2883 a.set_general_from_army_leadership(l.get_leader());
2889 for(
auto a : state.world.in_navy) {
2890 if(!
bool(a.get_admiral_from_navy_leadership())) {
2891 auto controller = a.get_controller_from_navy_control();
2892 for(
auto l : controller.get_leader_loyalty()) {
2893 if(l.get_leader().get_is_admiral() ==
true && !
bool(l.get_leader().get_navy_from_navy_leadership())) {
2894 a.set_admiral_from_navy_leadership(l.get_leader());
2903 auto existing_sphere_leader = state.world.nation_get_in_sphere_of(member);
2904 if(existing_sphere_leader) {
2905 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(member, existing_sphere_leader);
2907 state.world.gp_relationship_get_status(rel) &=
~nations::influence::level_mask;
2909 state.world.nation_set_in_sphere_of(member, dcon::nation_id{});
2914 if(state.world.nation_get_owned_province_count(member) == 0)
2917 auto nrel = state.world.get_gp_relationship_by_gp_influence_pair(member, new_gp);
2919 nrel = state.world.force_create_gp_relationship(member, new_gp);
2922 state.world.gp_relationship_get_status(nrel) &=
~nations::influence::level_mask;
2924 state.world.gp_relationship_set_influence(nrel, state.defines.max_influence);
2925 state.world.nation_set_in_sphere_of(member, new_gp);
2931 "msg_rem_sphere_title",
2932 new_gp, existing_sphere_leader, member,
2938 dcon::nation_id target, dcon::nation_id secondary_nation, dcon::state_definition_id wargoal_state,
2939 dcon::national_identity_id wargoal_t) {
2944 auto bits = state.world.cb_type_get_type_bits(wargoal);
2945 bool for_attacker =
is_attacker(state, war, from);
2949 if((bits & cb_flag::po_add_to_sphere) != 0) {
2950 if(secondary_nation) {
2951 if(secondary_nation != target) {
2952 if(state.world.nation_get_owned_province_count(secondary_nation) != 0)
2955 if(state.world.nation_get_owned_province_count(from) != 0)
2966 if((bits & cb_flag::po_clear_union_sphere) != 0) {
2967 auto from_cg = state.world.nation_get_primary_culture(from).get_group_from_culture_group_membership();
2968 for(
auto gprl : state.world.nation_get_gp_relationship_as_great_power(target)) {
2969 if(gprl.get_influence_target().get_in_sphere_of() == target &&
2970 gprl.get_influence_target().get_primary_culture().get_group_from_culture_group_membership() == from_cg) {
2978 if((bits & cb_flag::po_release_puppet) != 0) {
2979 assert(secondary_nation);
2980 if(secondary_nation != target) {
2981 auto ol = state.world.nation_get_overlord_as_subject(secondary_nation);
2986 auto ol = state.world.nation_get_overlord_as_subject(from);
2994 if((bits & cb_flag::po_make_puppet) != 0) {
2995 for(
auto sub : state.world.nation_get_overlord_as_ruler(target)) {
2998 if(state.world.nation_get_owned_province_count(target) > 0) {
3005 if((bits & cb_flag::po_destroy_forts) != 0) {
3006 if((bits & cb_flag::all_allowed_states) == 0) {
3007 for(
auto prov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
3008 if(prov.get_province().get_nation_from_province_ownership() == target) {
3012 }
else if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states) {
3013 for(
auto si : state.world.nation_get_state_ownership(target)) {
3017 [&](dcon::province_id prov) { state.world.province_set_building_level(prov, uint8_t(economy::province_building_type::fort), 0); });
3024 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
3025 if((bits & cb_flag::all_allowed_states) == 0) {
3026 for(
auto prov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
3027 if(prov.get_province().get_nation_from_province_ownership() == target) {
3031 }
else if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states) {
3032 for(
auto si : state.world.nation_get_state_ownership(target)) {
3036 [&](dcon::province_id prov) { state.world.province_set_building_level(prov, uint8_t(economy::province_building_type::naval_base), 0); });
3045 if((bits & cb_flag::po_disarmament) != 0) {
3046 if(state.world.nation_get_owned_province_count(target) > 0) {
3047 state.world.nation_set_disarmed_until(target, state.current_date + int32_t(state.defines.reparations_years) * 365);
3050 for(
const auto po : state.world.nation_get_province_ownership(target)) {
3051 auto lc = po.get_province().get_province_building_construction();
3052 while(lc.begin() != lc.end()) {
3053 state.world.delete_province_building_construction(*(lc.begin()));
3055 auto nc = po.get_province().get_province_naval_construction();
3056 while(nc.begin() != nc.end()) {
3057 state.world.delete_province_naval_construction(*(nc.begin()));
3060 auto uc = state.world.nation_get_province_land_construction(target);
3061 while(uc.begin() != uc.end()) {
3062 state.world.delete_province_land_construction(*(uc.begin()));
3065 if(state.defines.disarmament_army_hit > 0.f) {
3066 auto ar = state.world.nation_get_army_control(target);
3067 auto total = int32_t(ar.end() - ar.begin());
3068 auto rem = int32_t(
float(total) * state.defines.disarmament_army_hit);
3069 auto it = ar.begin();
3070 while(it != ar.end() && rem > 0) {
3071 if((*it).get_army().get_army_battle_participation()) {
3076 new (&it) dcon::internal::iterator_nation_foreach_army_control_as_controller(ar.begin());
3084 if((bits & cb_flag::po_reparations) != 0) {
3085 if(state.world.nation_get_owned_province_count(target) > 0) {
3086 state.world.nation_set_reparations_until(target, state.current_date + int32_t(state.defines.reparations_years) * 365);
3087 auto urel = state.world.get_unilateral_relationship_by_unilateral_pair(target, from);
3089 urel = state.world.force_create_unilateral_relationship(target, from);
3091 state.world.unilateral_relationship_set_reparations(urel,
true);
3097 if((bits & cb_flag::po_remove_prestige) != 0) {
3098 if(state.world.nation_get_owned_province_count(target) > 0) {
3100 -(state.defines.prestige_reduction *
nations::prestige_score(state, target) + state.defines.prestige_reduction_base));
3108 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
3109 if(state.world.nation_get_owned_province_count(target) > 0) {
3112 state.world.political_party_get_ideology(state.world.nation_get_ruling_party(from)));
3119 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
3120 if(state.world.nation_get_owned_province_count(target) > 0) {
3128 if((bits & cb_flag::po_colony) != 0) {
3129 std::vector<dcon::colonization_id> to_del;
3130 for(
auto c : state.world.state_definition_get_colonization(wargoal_state)) {
3131 if(c.get_colonizer() != from)
3132 to_del.push_back(c.id);
3134 for(
auto c : to_del) {
3135 state.world.delete_colonization(c);
3139 bool target_existed = state.world.nation_get_owned_province_count(target);
3147 if((bits & cb_flag::po_transfer_provinces) != 0) {
3148 auto target_tag = state.world.nation_get_identity_from_identity_holder(target);
3150 dcon::nation_id holder = from;
3152 holder = state.world.national_identity_get_nation_from_identity_holder(wargoal_t);
3154 holder = state.world.create_nation();
3155 state.world.nation_set_identity_from_identity_holder(holder, wargoal_t);
3157 if(
auto lprovs = state.world.nation_get_province_ownership(holder); lprovs.begin() == lprovs.end()) {
3162 if(!target_existed && state.world.nation_get_is_great_power(from)) {
3163 auto sr = state.world.force_create_gp_relationship(holder, from);
3164 auto& flags = state.world.gp_relationship_get_status(sr);
3166 state.world.nation_set_in_sphere_of(holder, from);
3168 add_truce(state, holder, target, int32_t(state.defines.base_truce_months) * 30);
3170 if((bits & cb_flag::all_allowed_states) == 0) {
3171 for(
auto prov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
3172 if(prov.get_province().get_nation_from_province_ownership() == target) {
3174 if((bits & cb_flag::po_remove_cores) != 0) {
3175 auto find_core = state.world.get_core_by_prov_tag_key(prov.get_province(), target_tag);
3177 state.world.delete_core(find_core);
3182 }
else if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states) {
3183 std::vector<dcon::state_instance_id> prior_states;
3184 for(
auto si : state.world.nation_get_state_ownership(target)) {
3186 prior_states.push_back(si.get_state());
3189 for(
auto si : prior_states) {
3190 for(
auto prov : state.world.state_definition_get_abstract_state_membership(state.world.state_instance_get_definition(si))) {
3191 if(prov.get_province().get_nation_from_province_ownership() == target) {
3193 if((bits & cb_flag::po_remove_cores) != 0) {
3194 auto find_core = state.world.get_core_by_prov_tag_key(prov.get_province(), target_tag);
3196 state.world.delete_core(find_core);
3206 if((bits & cb_flag::po_demand_state) != 0) {
3207 auto target_tag = state.world.nation_get_identity_from_identity_holder(target);
3209 if((bits & cb_flag::all_allowed_states) == 0) {
3210 for(
auto prov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
3211 if(prov.get_province().get_nation_from_province_ownership() == target) {
3213 if((bits & cb_flag::po_remove_cores) != 0) {
3214 auto find_core = state.world.get_core_by_prov_tag_key(prov.get_province(), target_tag);
3216 state.world.delete_core(find_core);
3221 }
else if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states) {
3222 std::vector<dcon::state_instance_id> prior_states;
3223 for(
auto si : state.world.nation_get_state_ownership(target)) {
3225 prior_states.push_back(si.get_state());
3228 for(
auto si : prior_states) {
3230 state.world.state_definition_get_abstract_state_membership(state.world.state_instance_get_definition(si))) {
3232 if(prov.get_province().get_nation_from_province_ownership() == target) {
3234 if((bits & cb_flag::po_remove_cores) != 0) {
3235 auto find_core = state.world.get_core_by_prov_tag_key(prov.get_province(), target_tag);
3237 state.world.delete_core(find_core);
3245 if(war && target_existed && state.world.nation_get_owned_province_count(target) == 0) {
3246 if(state.military_definitions.liberate) {
3247 auto counter_wg = fatten(state.world, state.world.create_wargoal());
3248 counter_wg.set_added_by(
3249 for_attacker ? state.world.war_get_primary_defender(war) : state.world.war_get_primary_attacker(war));
3250 counter_wg.set_target_nation(from);
3251 counter_wg.set_associated_tag(state.world.nation_get_identity_from_identity_holder(target));
3252 counter_wg.set_type(state.military_definitions.liberate);
3253 state.world.force_create_wargoals_attached(war, counter_wg);
3259 if((bits & cb_flag::po_annex) != 0 && target != from) {
3260 for(
auto n : state.world.in_nation) {
3261 auto rel = state.world.nation_get_overlord_as_subject(n);
3262 auto overlord = state.world.overlord_get_ruler(rel);
3264 if(overlord == target) {
3265 state.world.overlord_set_ruler(rel, from);
3269 auto target_tag = state.world.nation_get_identity_from_identity_holder(target);
3270 auto target_owns = state.world.nation_get_province_ownership(target);
3272 while(target_owns.begin() != target_owns.end()) {
3273 auto prov = (*target_owns.begin()).get_province();
3275 if((bits & cb_flag::po_remove_cores) != 0) {
3276 auto find_core = state.world.get_core_by_prov_tag_key(prov, target_tag);
3278 state.world.delete_core(find_core);
3283 if(target_existed) {
3284 if(war && state.military_definitions.liberate) {
3285 auto counter_wg = fatten(state.world, state.world.create_wargoal());
3286 counter_wg.set_added_by(
3287 for_attacker ? state.world.war_get_primary_defender(war) : state.world.war_get_primary_attacker(war));
3288 counter_wg.set_target_nation(from);
3289 counter_wg.set_associated_tag(state.world.nation_get_identity_from_identity_holder(target));
3290 counter_wg.set_type(state.military_definitions.liberate);
3291 state.world.force_create_wargoals_attached(war, counter_wg);
3298 auto accepted_effect = state.world.cb_type_get_on_po_accepted(wargoal);
3299 if(accepted_effect) {
3301 uint32_t((state.current_date.value << 8) ^ target.index()),
uint32_t(from.index() ^ (wargoal.index() << 3)));
3307 float prestige_gain =
successful_cb_prestige(state, wargoal, from) * (war ? 1.0f : state.defines.crisis_wargoal_prestige_mult);
3308 if(state.world.nation_get_owned_province_count(from) > 0)
3310 if(state.world.nation_get_owned_province_count(target) > 0)
3320 auto remove_pending_offer = [&](dcon::peace_offer_id id) {
3321 for(
auto& m : state.pending_messages) {
3328 for(
auto po : state.world.in_peace_offer) {
3329 if(!po.get_nation_from_pending_peace_offer()) {
3330 remove_pending_offer(po);
3331 state.world.delete_peace_offer(po);
3332 }
else if(!po.get_war_from_war_settlement() && !po.get_is_crisis_offer()) {
3333 remove_pending_offer(po);
3334 state.world.delete_peace_offer(po);
3336 remove_pending_offer(po);
3337 state.world.delete_peace_offer(po);
3345 static std::vector<dcon::wargoal_id> to_delete;
3347 for(
auto w : state.world.in_war) {
3348 for(
auto wg : w.get_wargoals_attached()) {
3349 if(
get_role(state, w, wg.get_wargoal().get_added_by()) == war_role::none ||
get_role(state, w, wg.get_wargoal().get_target_nation()) == war_role::none)
3350 to_delete.push_back(wg.get_wargoal());
3353 for(
auto g : to_delete)
3354 state.world.delete_wargoal(g);
3356 for(
auto w : state.world.in_war) {
3357 if(
get_role(state, w, w.get_primary_attacker()) != war_role::attacker || w.get_primary_attacker().get_overlord_as_subject().get_ruler()) {
3358 int32_t best_rank = 0;
3360 for(
auto par : w.get_war_participant()) {
3361 if(par.get_is_attacker() && !(par.get_nation().get_overlord_as_subject().get_ruler())) {
3362 if(!n || par.get_nation().get_rank() < best_rank) {
3363 best_rank = par.get_nation().get_rank();
3364 n = par.get_nation();
3372 w.set_primary_attacker(n);
3374 if(
get_role(state, w, w.get_primary_defender()) != war_role::defender || w.get_primary_defender().get_overlord_as_subject().get_ruler()) {
3375 int32_t best_rank = 0;
3377 for(
auto par : w.get_war_participant()) {
3378 if(!par.get_is_attacker() && !(par.get_nation().get_overlord_as_subject().get_ruler())) {
3379 if(!n || par.get_nation().get_rank() < best_rank) {
3380 best_rank = par.get_nation().get_rank();
3381 n = par.get_nation();
3389 w.set_primary_defender(n);
3391 bool non_sq_war_goal =
false;
3392 for(
auto wg : w.get_wargoals_attached()) {
3394 if(wg.get_wargoal().get_type().get_type_bits() == cb_flag::po_status_quo) {
3397 non_sq_war_goal =
true;
3401 if(!non_sq_war_goal)
3409 for(
auto wg : state.world.in_wargoal) {
3410 auto po = wg.get_peace_offer_from_peace_offer_item();
3411 auto wr = wg.get_war_from_wargoals_attached();
3413 state.world.delete_wargoal(wg);
3419 for(
uint32_t i = state.world.navy_size(); i-- > 0; ) {
3420 dcon::navy_id n{ dcon::navy_id::value_base_t(i) };
3421 if(state.world.navy_is_valid(n)) {
3422 auto rng = state.world.navy_get_navy_membership(n);
3423 if(!state.world.navy_get_battle_from_navy_battle_participation(n)) {
3424 if(
rng.begin() ==
rng.end() || !state.world.navy_get_controller_from_navy_control(n)) {
3430 for(
uint32_t i = state.world.army_size(); i-- > 0; ) {
3431 dcon::army_id n{ dcon::army_id::value_base_t(i) };
3432 if(state.world.army_is_valid(n)) {
3433 auto rng = state.world.army_get_army_membership(n);
3434 if(!state.world.army_get_battle_from_army_battle_participation(n)) {
3435 if(
rng.begin() ==
rng.end() || (!state.world.army_get_controller_from_army_rebel_control(n) && !state.world.army_get_controller_from_army_control(n))) {
3444 auto wpar = state.world.war_get_war_participant(w);
3445 auto num_par = int32_t(wpar.end() - wpar.begin());
3446 auto end_truce = state.current_date + months * 31;
3448 for(int32_t i = 0; i < num_par; ++i) {
3449 auto this_par = *(wpar.begin() + i);
3450 auto this_nation = this_par.get_nation();
3452 if(this_nation.get_overlord_as_subject().get_ruler())
3455 auto attacker = this_par.get_is_attacker();
3457 for(int32_t j = i + 1; j < num_par; ++j) {
3458 auto other_par = *(wpar.begin() + j);
3459 auto other_nation = other_par.get_nation();
3461 if(!other_nation.get_overlord_as_subject().get_ruler() &&
attacker != other_par.get_is_attacker()) {
3462 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(this_nation, other_nation);
3464 rel = state.world.force_create_diplomatic_relation(this_nation, other_nation);
3466 auto& current_truce = state.world.diplomatic_relation_get_truce_until(rel);
3467 if(!current_truce || current_truce < end_truce)
3468 current_truce = end_truce;
3474 auto end_truce = state.current_date + months * 31;
3477 for(
auto par : state.world.war_get_war_participant(w)) {
3478 auto other_nation = par.get_nation();
3479 if(other_nation.get_overlord_as_subject().get_ruler())
3483 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(n, other_nation);
3485 rel = state.world.force_create_diplomatic_relation(n, other_nation);
3487 auto& current_truce = state.world.diplomatic_relation_get_truce_until(rel);
3488 if(!current_truce || current_truce < end_truce)
3489 current_truce = end_truce;
3494 auto end_truce = state.current_date + days;
3496 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(a, b);
3498 rel = state.world.force_create_diplomatic_relation(a, b);
3500 auto& current_truce = state.world.diplomatic_relation_get_truce_until(rel);
3501 if(!current_truce || current_truce < end_truce)
3502 current_truce = end_truce;
3506 dcon::nation_id from = state.world.peace_offer_get_nation_from_pending_peace_offer(offer);
3507 dcon::nation_id target = state.world.peace_offer_get_target(offer);
3510 auto war = state.world.peace_offer_get_war_from_war_settlement(offer);
3515 [from, target, pa = state.world.war_get_primary_attacker(war), pd = state.world.war_get_primary_defender(war), name = state.world.war_get_name(war), tag = state.world.war_get_over_tag(war), st = state.world.war_get_over_state(war)](
sys::state& state,
text::layout_base& contents) {
3516 text::substitution_map sub;
3517 text::add_to_substitution_map(sub, text::variable_type::order, std::string_view(
""));
3518 text::add_to_substitution_map(sub, text::variable_type::second, text::get_adjective(state, pd));
3519 text::add_to_substitution_map(sub, text::variable_type::second_country, pd);
3520 text::add_to_substitution_map(sub, text::variable_type::first, text::get_adjective(state, pa));
3521 text::add_to_substitution_map(sub, text::variable_type::third, tag);
3522 text::add_to_substitution_map(sub, text::variable_type::state, st);
3524 std::string resolved_war_name = text::resolve_string_substitution(state, name, sub);
3525 text::add_line(state, contents,
"msg_peace_offer_accepted_1", text::variable_type::x, target, text::variable_type::y, from, text::variable_type::val, std::string_view{resolved_war_name});
3527 "msg_peace_offer_accepted_title",
3528 target, from, dcon::nation_id{},
3533 bool contains_sq =
false;
3535 for(
auto wg_offered : state.world.peace_offer_get_peace_offer_item(offer)) {
3536 auto wg = wg_offered.get_wargoal();
3537 implement_war_goal(state, state.world.peace_offer_get_war_from_war_settlement(offer), wg.get_type(),
3538 wg.get_added_by(), wg.get_target_nation(), wg.get_secondary_nation(), wg.get_associated_state(), wg.get_associated_tag());
3546 auto offer_range =
state.world.peace_offer_get_peace_offer_item(offer);
3547 while(offer_range.begin() != offer_range.end()) {
3548 state.world.delete_wargoal((*offer_range.begin()).get_wargoal());
3551 if((
state.world.war_get_primary_attacker(war) == from &&
state.world.war_get_primary_defender(war) == target)
3554 if(
state.world.war_get_is_great(war)) {
3555 if(
state.world.peace_offer_get_is_concession(offer) ==
false) {
3556 for(
auto par :
state.world.war_get_war_participant(war)) {
3557 if(par.get_is_attacker() ==
false) {
3559 dcon::nation_id{}, dcon::state_definition_id{}, dcon::national_identity_id{});
3563 for(
auto par :
state.world.war_get_war_participant(war)) {
3564 if(par.get_is_attacker() ==
true) {
3566 dcon::nation_id{}, dcon::state_definition_id{}, dcon::national_identity_id{});
3573 state.world.peace_offer_get_is_concession(offer) ? war_result::defender_won : war_result::attacker_won);
3575 }
else if((
state.world.war_get_primary_attacker(war) == target &&
state.world.war_get_primary_defender(war) == from)
3578 if(
state.world.war_get_is_great(war)) {
3579 if(
state.world.peace_offer_get_is_concession(offer) ==
false) {
3580 for(
auto par :
state.world.war_get_war_participant(war)) {
3581 if(par.get_is_attacker() ==
true) {
3583 dcon::nation_id{}, dcon::state_definition_id{}, dcon::national_identity_id{});
3587 for(
auto par :
state.world.war_get_war_participant(war)) {
3588 if(par.get_is_attacker() ==
false) {
3590 dcon::nation_id{}, dcon::state_definition_id{}, dcon::national_identity_id{});
3597 state.world.peace_offer_get_is_concession(offer) ? war_result::attacker_won : war_result::defender_won);
3599 }
else if(
state.world.war_get_primary_attacker(war) == from ||
state.world.war_get_primary_defender(war) == from) {
3601 if(
state.world.war_get_is_great(war) &&
state.world.peace_offer_get_is_concession(offer) ==
false) {
3602 implement_war_goal(state, war,
state.military_definitions.standard_great_war, from, target, dcon::nation_id{},
3603 dcon::state_definition_id{}, dcon::national_identity_id{});
3606 if(
state.world.nation_get_owned_province_count(
state.world.war_get_primary_attacker(war)) == 0) {
3608 cleanup_war(state, war, war_result::defender_won);
3609 }
else if(
state.world.nation_get_owned_province_count(
state.world.war_get_primary_defender(war)) == 0) {
3611 cleanup_war(state, war, war_result::attacker_won);
3614 remove_from_war(state, war, target,
state.world.peace_offer_get_is_concession(offer) ==
false);
3616 }
else if(
state.world.war_get_primary_attacker(war) == target ||
state.world.war_get_primary_defender(war) == target) {
3618 if(
state.world.war_get_is_great(war) &&
state.world.peace_offer_get_is_concession(offer) ==
true) {
3619 implement_war_goal(state, war,
state.military_definitions.standard_great_war, target, from, dcon::nation_id{},
3620 dcon::state_definition_id{}, dcon::national_identity_id{});
3623 if(
state.world.nation_get_owned_province_count(
state.world.war_get_primary_attacker(war)) == 0) {
3625 cleanup_war(state, war, war_result::defender_won);
3626 }
else if(
state.world.nation_get_owned_province_count(
state.world.war_get_primary_defender(war)) == 0) {
3628 cleanup_war(state, war, war_result::attacker_won);
3637 bool crisis_attackers_won = (
from ==
state.primary_crisis_attacker) == (
state.world.peace_offer_get_is_concession(offer) ==
false);
3641 for(
auto wg :
state.world.peace_offer_get_peace_offer_item(offer)) {
3642 add_truce(state, wg.get_wargoal().get_added_by(), wg.get_wargoal().get_target_nation(), truce_months * 31);
3645 for(
auto swg :
state.crisis_attacker_wargoals) {
3646 bool was_part_of_offer =
false;
3647 for(
auto wg :
state.world.peace_offer_get_peace_offer_item(offer)) {
3648 if(wg.get_wargoal().get_added_by() == swg.added_by)
3649 was_part_of_offer =
true;
3652 if(!was_part_of_offer) {
3653 float prestige_loss = std::min(
state.defines.war_failed_goal_prestige_base,
3654 state.defines.war_failed_goal_prestige *
state.defines.crisis_wargoal_prestige_mult *
3656 state.world.cb_type_get_penalty_factor(swg.cb);
3659 auto pop_militancy =
state.defines.war_failed_goal_militancy *
state.defines.crisis_wargoal_militancy_mult *
state.world.cb_type_get_penalty_factor(swg.cb);
3660 if(pop_militancy > 0) {
3661 for(
auto prv :
state.world.nation_get_province_ownership(swg.added_by)) {
3662 for(
auto pop : prv.get_province().get_pop_location()) {
3669 if(crisis_attackers_won) {
3672 -
state.defines.crisis_winner_relations_impact);
3677 -
state.defines.crisis_winner_relations_impact);
3680 if(crisis_attackers_won) {
3683 state.defines.crisis_winner_relations_impact);
3687 state.defines.crisis_winner_relations_impact);
3692 for(
auto swg :
state.crisis_attacker_wargoals) {
3693 bool was_part_of_offer =
false;
3694 for(
auto wg :
state.world.peace_offer_get_peace_offer_item(offer)) {
3695 if(wg.get_wargoal().get_added_by() == swg.added_by)
3696 was_part_of_offer =
true;
3699 if(!was_part_of_offer) {
3700 float prestige_loss = std::min(
state.defines.war_failed_goal_prestige_base,
3701 state.defines.war_failed_goal_prestige *
state.defines.crisis_wargoal_prestige_mult *
3703 state.world.cb_type_get_penalty_factor(swg.cb);
3706 auto pop_militancy =
state.defines.war_failed_goal_militancy *
state.defines.crisis_wargoal_militancy_mult *
state.world.cb_type_get_penalty_factor(swg.cb);
3707 if(pop_militancy > 0) {
3708 for(
auto prv :
state.world.nation_get_province_ownership(swg.added_by)) {
3709 for(
auto pop : prv.get_province().get_pop_location()) {
3716 if(crisis_attackers_won) {
3719 -
state.defines.crisis_winner_relations_impact);
3723 -
state.defines.crisis_winner_relations_impact);
3726 if(crisis_attackers_won) {
3729 state.defines.crisis_winner_relations_impact);
3733 state.defines.crisis_winner_relations_impact);
3738 for(
auto& par :
state.crisis_participants) {
3742 if(par.merely_interested ==
false && par.id !=
state.primary_crisis_attacker && par.id !=
state.primary_crisis_defender) {
3743 if(crisis_attackers_won != par.supports_attacker) {
3744 if(par.supports_attacker) {
3746 -
state.defines.crisis_winner_relations_impact);
3749 -
state.defines.crisis_winner_relations_impact);
3752 if(par.supports_attacker) {
3754 state.defines.crisis_winner_relations_impact);
3757 state.defines.crisis_winner_relations_impact);
3763 if(crisis_attackers_won) {
3765 float p_factor = 0.05f * (
state.defines.crisis_winner_prestige_factor_base +
3766 state.defines.crisis_winner_prestige_factor_year * float(
state.current_date.value) / float(365));
3773 auto rp_ideology =
state.world.nation_get_ruling_party(
state.primary_crisis_defender).get_ideology();
3775 for(
auto prv :
state.world.nation_get_province_ownership(
state.primary_crisis_defender)) {
3776 prv.get_province().get_party_loyalty(rp_ideology) *= (1.0f -
state.defines.party_loyalty_hit_on_war_loss);
3781 float p_factor = 0.05f * (
state.defines.crisis_winner_prestige_factor_base +
3782 state.defines.crisis_winner_prestige_factor_year * float(
state.current_date.value) / float(365));
3789 auto rp_ideology =
state.world.nation_get_ruling_party(
state.primary_crisis_attacker).get_ideology();
3791 for(
auto prv :
state.world.nation_get_province_ownership(
state.primary_crisis_attacker)) {
3792 prv.get_province().get_party_loyalty(rp_ideology) *= (1.0f -
state.defines.party_loyalty_hit_on_war_loss);
3798 state.world.peace_offer_set_war_from_war_settlement(offer, dcon::war_id{});
3799 state.world.peace_offer_set_is_crisis_offer(offer,
false);
3803 dcon::nation_id from = state.world.peace_offer_get_nation_from_pending_peace_offer(offer);
3804 dcon::nation_id target = state.world.peace_offer_get_target(offer);
3807 auto war = state.world.peace_offer_get_war_from_war_settlement(offer);
3811 [from, target, pa = state.world.war_get_primary_attacker(war), pd = state.world.war_get_primary_defender(war), name = state.world.war_get_name(war), tag = state.world.war_get_over_tag(war), st = state.world.war_get_over_state(war)](
sys::state& state,
text::layout_base& contents) {
3812 text::substitution_map sub;
3813 text::add_to_substitution_map(sub, text::variable_type::order, std::string_view(
""));
3814 text::add_to_substitution_map(sub, text::variable_type::second, text::get_adjective(state, pd));
3815 text::add_to_substitution_map(sub, text::variable_type::second_country, pd);
3816 text::add_to_substitution_map(sub, text::variable_type::first, text::get_adjective(state, pa));
3817 text::add_to_substitution_map(sub, text::variable_type::third, tag);
3818 text::add_to_substitution_map(sub, text::variable_type::state, st);
3820 std::string resolved_war_name = text::resolve_string_substitution(state, name, sub);
3821 text::add_line(state, contents,
"msg_peace_offer_rejected_1", text::variable_type::x, target, text::variable_type::y, from, text::variable_type::val, std::string_view{resolved_war_name});
3823 "msg_peace_offer_rejected_title",
3824 target, from, dcon::nation_id{},
3838 state.world.peace_offer_set_war_from_war_settlement(offer, dcon::war_id{});
3839 state.world.peace_offer_set_is_crisis_offer(offer,
false);
3843 for(
auto wg : state.world.in_wargoal) {
3844 auto war = wg.get_war_from_wargoals_attached();
3849 auto role = attacker_goal ? war_role::attacker : war_role::defender;
3860 auto bits = wg.get_type().get_type_bits();
3861 if((bits & (cb_flag::po_annex | cb_flag::po_transfer_provinces | cb_flag::po_demand_state)) != 0) {
3862 float total_count = 0.0f;
3863 float occupied = 0.0f;
3864 if(wg.get_associated_state()) {
3865 for(
auto prv : wg.get_associated_state().get_abstract_state_membership()) {
3866 if(prv.get_province().get_nation_from_province_ownership() == wg.get_target_nation()) {
3868 if(
get_role(state, war, prv.get_province().get_nation_from_province_control()) == role) {
3873 }
else if((bits & cb_flag::po_annex) != 0) {
3874 for(
auto prv : wg.get_target_nation().get_province_ownership()) {
3876 if(
get_role(state, war, prv.get_province().get_nation_from_province_control()) == role) {
3880 }
else if(
auto allowed_states = wg.get_type().get_allowed_states(); allowed_states) {
3881 auto from_slot = wg.get_secondary_nation().id ? wg.get_secondary_nation().id : wg.get_associated_tag().get_nation_from_identity_holder().id;
3882 bool is_lib = (bits & cb_flag::po_transfer_provinces) != 0;
3883 for(
auto st : wg.get_target_nation().get_state_ownership()) {
3888 if(get_role(state, war, state.world.province_get_nation_from_province_control(prv)) == role) {
3896 if(total_count > 0.0f) {
3897 float fraction = occupied / total_count;
3898 if(fraction >= state.defines.tws_fulfilled_idle_space || (wg.get_ticking_war_score() < 0 && occupied > 0.0f)) {
3899 wg.get_ticking_war_score() += state.defines.tws_fulfilled_speed * fraction;
3900 }
else if(occupied == 0.0f) {
3901 if(wg.get_ticking_war_score() > 0.0f || war.get_start_date() + int32_t(state.defines.tws_grace_period_days) <= state.current_date) {
3902 wg.get_ticking_war_score() -= state.defines.tws_not_fulfilled_speed;
3909 if((bits & cb_flag::po_make_puppet) != 0) {
3911 auto target = wg.get_target_nation().get_capital();
3913 if(
get_role(state, war, target.get_nation_from_province_control()) == role) {
3914 wg.get_ticking_war_score() += state.defines.tws_fulfilled_speed;
3916 else if(wg.get_ticking_war_score() > 0.0f || war.get_start_date() + int32_t(state.defines.tws_grace_period_days) <= state.current_date) {
3917 wg.get_ticking_war_score() -= state.defines.tws_not_fulfilled_speed;
3921 if(wg.get_type().get_tws_battle_factor() > 0) {
3934 if(war.get_number_of_battles() >= uint16_t(state.defines.tws_battle_min_count)) {
3938 ratio = war.get_defender_battle_score() > 0.0f ? war.get_attacker_battle_score() / war.get_defender_battle_score() : 10.0f;
3940 ratio = war.get_attacker_battle_score() > 0.0f ? war.get_defender_battle_score() / war.get_attacker_battle_score() : 10.0f;
3942 if(ratio >= wg.get_type().get_tws_battle_factor()) {
3943 auto effective_percentage = std::min(ratio / state.defines.tws_battle_max_aspect, 1.0f);
3944 wg.get_ticking_war_score() += state.defines.tws_fulfilled_speed * effective_percentage;
3945 }
else if(ratio <= 1.0f / wg.get_type().get_tws_battle_factor() && ratio > 0.0f) {
3946 auto effective_percentage = std::min(1.0f / (ratio * state.defines.tws_battle_max_aspect), 1.0f);
3947 wg.get_ticking_war_score() -= state.defines.tws_fulfilled_speed * effective_percentage;
3948 }
else if(ratio == 0.0f) {
3949 wg.get_ticking_war_score() -= state.defines.tws_fulfilled_speed;
3953 auto max_score =
peace_cost(state, war, wg.get_type(), wg.get_added_by(), wg.get_target_nation(), wg.get_secondary_nation(), wg.get_associated_state(), wg.get_associated_tag());
3955 wg.get_ticking_war_score() =
3956 std::clamp(wg.get_ticking_war_score(), -
float(max_score),
float(max_score));
3960float primary_warscore_from_blockades(
sys::state& state, dcon::war_id w) {
3961 auto pattacker = state.world.war_get_primary_attacker(w);
3962 auto pdefender = state.world.war_get_primary_defender(w);
3964 auto d_cpc = state.world.nation_get_central_ports(pdefender);
3965 int32_t d_blockaded_in_war = 0;
3966 for(
auto p : state.world.nation_get_province_ownership(pdefender)) {
3968 for(
auto v : state.world.province_get_navy_location(p.get_province().get_port_to())) {
3969 if(!v.get_navy().get_is_retreating() && !v.get_navy().get_battle_from_navy_battle_participation()) {
3971 ++d_blockaded_in_war;
3978 auto def_b_frac = std::clamp(d_cpc > 0 ?
float(d_blockaded_in_war) /
float(d_cpc) : 0.0f, 0.0f, 1.0f);
3980 int32_t a_blockaded_in_war = 0;
3981 for(
auto p :
state.world.nation_get_province_ownership(pattacker)) {
3983 for(
auto v :
state.world.province_get_navy_location(p.get_province().get_port_to())) {
3984 if(!v.get_navy().get_is_retreating() && !v.get_navy().get_battle_from_navy_battle_participation()) {
3986 ++a_blockaded_in_war;
3993 auto a_cpc =
state.world.nation_get_central_ports(pattacker);
3994 auto att_b_frac = std::clamp(a_cpc > 0 ?
float(a_blockaded_in_war) /
float(a_cpc) : 0.0f, 0.0f, 1.0f);
3996 return 25.0f * (def_b_frac - att_b_frac);
3999float primary_warscore(
sys::state& state, dcon::war_id w) {
4001 primary_warscore_from_occupation(state, w)
4002 + primary_warscore_from_battles(state, w)
4003 + primary_warscore_from_blockades(state, w)
4004 + primary_warscore_from_war_goals(state, w), -100.0f, 100.0f);
4007float primary_warscore_from_occupation(
sys::state& state, dcon::war_id w) {
4010 auto pattacker = state.world.war_get_primary_attacker(w);
4011 auto pdefender = state.world.war_get_primary_defender(w);
4013 int32_t sum_attacker_prov_values = 0;
4014 int32_t sum_attacker_occupied_values = 0;
4015 for(
auto prv : state.world.nation_get_province_ownership(pattacker)) {
4016 auto v = province_point_cost(state, prv.get_province(), pattacker);
4017 sum_attacker_prov_values += v;
4018 if(get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::defender)
4019 sum_attacker_occupied_values += v;
4022 int32_t sum_defender_prov_values = 0;
4023 int32_t sum_defender_occupied_values = 0;
4024 for(
auto prv :
state.world.nation_get_province_ownership(pdefender)) {
4026 sum_defender_prov_values += v;
4027 if(
get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::attacker)
4028 sum_defender_occupied_values += v;
4031 if(sum_defender_prov_values > 0)
4032 total += (float(sum_defender_occupied_values) * 100.0f) /
float(sum_defender_prov_values);
4033 if(sum_attacker_prov_values > 0)
4034 total -= (float(sum_attacker_occupied_values) * 100.0f) /
float(sum_attacker_prov_values);
4038float primary_warscore_from_battles(
sys::state& state, dcon::war_id w) {
4039 return std::clamp(state.world.war_get_attacker_battle_score(w) - state.world.war_get_defender_battle_score(w),
4040 -state.defines.max_warscore_from_battles, state.defines.max_warscore_from_battles);
4042float primary_warscore_from_war_goals(
sys::state& state, dcon::war_id w) {
4045 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
4046 if(is_attacker(state, w, wg.get_wargoal().get_added_by())) {
4047 total += wg.get_wargoal().get_ticking_war_score();
4049 total -= wg.get_wargoal().get_ticking_war_score();
4056float directed_warscore(
sys::state& state, dcon::war_id w, dcon::nation_id primary, dcon::nation_id secondary) {
4059 auto is_pattacker = state.world.war_get_primary_attacker(w) == primary;
4060 auto is_pdefender = state.world.war_get_primary_defender(w) == primary;
4062 auto is_tpattacker = state.world.war_get_primary_attacker(w) == secondary;
4063 auto is_tpdefender = state.world.war_get_primary_defender(w) == secondary;
4065 if(is_pattacker && is_tpdefender)
4066 return primary_warscore(state, w);
4067 if(is_pdefender && is_tpattacker)
4068 return -primary_warscore(state, w);
4070 int32_t sum_attacker_prov_values = 0;
4071 int32_t sum_attacker_occupied_values = 0;
4072 for(
auto prv : state.world.nation_get_province_ownership(primary)) {
4073 auto v = province_point_cost(state, prv.get_province(), primary);
4074 sum_attacker_prov_values += v;
4077 if(get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::attacker)
4078 sum_attacker_occupied_values += v;
4079 }
else if(is_tpdefender) {
4080 if(get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::defender)
4081 sum_attacker_occupied_values += v;
4083 if(prv.get_province().get_nation_from_province_control() == secondary)
4084 sum_attacker_occupied_values += v;
4088 int32_t sum_defender_prov_values = 0;
4089 int32_t sum_defender_occupied_values = 0;
4090 for(
auto prv :
state.world.nation_get_province_ownership(secondary)) {
4092 sum_defender_prov_values += v;
4095 if(
get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::attacker)
4096 sum_defender_occupied_values += v;
4097 }
else if(is_pdefender) {
4098 if(
get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::defender)
4099 sum_defender_occupied_values += v;
4101 if(prv.get_province().get_nation_from_province_control() == primary)
4102 sum_defender_occupied_values += v;
4106 if(sum_defender_prov_values > 0)
4107 total += (float(sum_defender_occupied_values) * 100.0f) /
float(sum_defender_prov_values);
4108 if(sum_attacker_prov_values > 0)
4109 total -= (float(sum_attacker_occupied_values) * 100.0f) /
float(sum_attacker_prov_values);
4111 for(
auto wg :
state.world.war_get_wargoals_attached(w)) {
4112 if((wg.get_wargoal().get_added_by() == primary || is_pattacker || is_pdefender)
4113 && wg.get_wargoal().get_target_nation() == secondary) {
4115 total += wg.get_wargoal().get_ticking_war_score();
4116 }
else if(wg.get_wargoal().get_added_by() == secondary
4117 && (wg.get_wargoal().get_target_nation() ==
primary || is_pattacker || is_pdefender)) {
4119 total -= wg.get_wargoal().get_ticking_war_score();
4120 }
else if(wg.get_wargoal().get_added_by() ==
primary
4121 && (wg.get_wargoal().get_target_nation() == secondary || is_tpattacker || is_tpdefender)) {
4123 total += wg.get_wargoal().get_ticking_war_score();
4124 }
else if((wg.get_wargoal().get_added_by() == secondary || is_tpattacker || is_tpdefender)
4125 && (wg.get_wargoal().get_target_nation() ==
primary)) {
4127 total -= wg.get_wargoal().get_ticking_war_score();
4131 auto d_cpc =
state.world.nation_get_central_ports(secondary);
4132 int32_t d_blockaded_in_war = 0;
4133 for(
auto p :
state.world.nation_get_province_ownership(secondary)) {
4135 for(
auto v :
state.world.province_get_navy_location(p.get_province().get_port_to())) {
4136 if(!v.get_navy().get_is_retreating() && !v.get_navy().get_battle_from_navy_battle_participation()) {
4139 if(
get_role(state, w, v.get_navy().get_controller_from_navy_control()) == war_role::attacker) {
4140 ++d_blockaded_in_war;
4143 }
else if(is_pdefender) {
4144 if(
get_role(state, w, v.get_navy().get_controller_from_navy_control()) == war_role::defender) {
4145 ++d_blockaded_in_war;
4149 if(v.get_navy().get_controller_from_navy_control() ==
primary) {
4150 ++d_blockaded_in_war;
4158 auto def_b_frac = std::clamp(d_cpc > 0 ?
float(d_blockaded_in_war) /
float(d_cpc) : 0.0f, 0.0f, 1.0f);
4160 int32_t a_blockaded_in_war = 0;
4161 for(
auto p :
state.world.nation_get_province_ownership(primary)) {
4163 for(
auto v :
state.world.province_get_navy_location(p.get_province().get_port_to())) {
4164 if(!v.get_navy().get_is_retreating() && !v.get_navy().get_battle_from_navy_battle_participation()) {
4166 if(
get_role(state, w, v.get_navy().get_controller_from_navy_control()) == war_role::attacker) {
4167 ++a_blockaded_in_war;
4170 }
else if(is_tpdefender) {
4171 if(
get_role(state, w, v.get_navy().get_controller_from_navy_control()) == war_role::defender) {
4172 ++a_blockaded_in_war;
4176 if(v.get_navy().get_controller_from_navy_control() == secondary) {
4177 ++a_blockaded_in_war;
4185 auto a_cpc =
state.world.nation_get_central_ports(primary);
4186 auto att_b_frac = std::clamp(a_cpc > 0 ?
float(a_blockaded_in_war) /
float(a_cpc) : 0.0f, 0.0f, 1.0f);
4188 total += 25.0f * (def_b_frac - att_b_frac);
4190 return std::clamp(total, 0.0f, 100.0f);
4193bool can_embark_onto_sea_tile(
sys::state& state, dcon::nation_id from, dcon::province_id p, dcon::army_id a) {
4194 int32_t max_cap = 0;
4195 for(
auto n : state.world.province_get_navy_location(p)) {
4196 if(n.get_navy().get_controller_from_navy_control() == from &&
4197 !
bool(n.get_navy().get_battle_from_navy_battle_participation())) {
4198 max_cap = std::max(free_transport_capacity(state, n.get_navy()), max_cap);
4201 auto regs =
state.world.army_get_army_membership(a);
4202 return int32_t(regs.end() - regs.begin()) <= max_cap;
4205dcon::navy_id find_embark_target(
sys::state& state, dcon::nation_id from, dcon::province_id p, dcon::army_id a) {
4206 auto regs = state.world.army_get_army_membership(a);
4207 int32_t count = int32_t(regs.end() - regs.begin());
4209 int32_t max_cap = 0;
4210 for(
auto n : state.world.province_get_navy_location(p)) {
4211 if(n.get_navy().get_controller_from_navy_control() == from) {
4212 if(free_transport_capacity(state, n.get_navy()) >= count)
4213 return n.get_navy();
4216 return dcon::navy_id{};
4219float effective_army_speed(
sys::state& state, dcon::army_id a) {
4220 auto owner = state.world.army_get_controller_from_army_control(a);
4222 owner = state.world.rebel_faction_get_ruler_from_rebellion_within(state.world.army_get_controller_from_army_rebel_control(a));
4224 float min_speed = 10000.0f;
4225 for(
auto reg : state.world.army_get_army_membership(a)) {
4226 auto reg_speed = state.world.nation_get_unit_stats(owner, reg.get_regiment().get_type()).maximum_speed;
4227 min_speed = std::min(min_speed, reg_speed);
4235 auto leader =
state.world.army_get_general_from_army_leadership(a);
4236 auto bg =
state.world.leader_get_background(leader);
4237 auto per =
state.world.leader_get_personality(leader);
4238 auto leader_move =
state.world.leader_trait_get_speed(bg) +
state.world.leader_trait_get_speed(per);
4239 return min_speed * (
state.world.army_get_is_retreating(a) ? 2.0f : 1.0f) *
4242 (leader_move + 1.0f);
4244float effective_navy_speed(
sys::state& state, dcon::navy_id n) {
4245 auto owner = state.world.navy_get_controller_from_navy_control(n);
4247 float min_speed = 10000.0f;
4248 for(
auto reg : state.world.navy_get_navy_membership(n)) {
4249 auto reg_speed = state.world.nation_get_unit_stats(owner, reg.get_ship().get_type()).maximum_speed;
4250 min_speed = std::min(min_speed, reg_speed);
4253 auto leader =
state.world.navy_get_admiral_from_navy_leadership(n);
4254 auto bg =
state.world.leader_get_background(leader);
4255 auto per =
state.world.leader_get_personality(leader);
4256 auto leader_move =
state.world.leader_trait_get_speed(bg) +
state.world.leader_trait_get_speed(per);
4257 return min_speed * (
state.world.navy_get_is_retreating(n) ? 2.0f : 1.0f) * (leader_move + 1.0f);
4260int32_t movement_time_from_to(
sys::state& state, dcon::army_id a, dcon::province_id from, dcon::province_id to) {
4261 auto adj = state.world.get_province_adjacency_by_province_pair(from, to);
4263 float sum_mods = state.world.province_get_modifier_values(to, sys::provincial_mod_offsets::movement_cost) +
4264 state.world.province_get_modifier_values(to, sys::provincial_mod_offsets::movement_cost);
4265 float effective_distance = std::max(0.1f, distance * (sum_mods + 1.0f));
4267 float effective_speed = effective_army_speed(state, a);
4269 int32_t days = effective_speed > 0.0f ? int32_t(std::ceil(effective_distance / effective_speed)) : 50;
4273int32_t movement_time_from_to(
sys::state& state, dcon::navy_id n, dcon::province_id from, dcon::province_id to) {
4274 auto adj = state.world.get_province_adjacency_by_province_pair(from, to);
4276 float sum_mods = state.world.province_get_modifier_values(to, sys::provincial_mod_offsets::movement_cost) +
4277 state.world.province_get_modifier_values(from, sys::provincial_mod_offsets::movement_cost);
4278 float effective_distance = std::max(0.1f, distance * (sum_mods + 1.0f));
4280 float effective_speed = effective_navy_speed(state, n);
4282 int32_t days = effective_speed > 0.0f ? int32_t(std::ceil(effective_distance / effective_speed)) : 50;
4287 auto current_location = state.world.army_get_location_from_army_location(a);
4288 auto adj = state.world.get_province_adjacency_by_province_pair(current_location, p);
4290 float sum_mods = state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::movement_cost) +
4291 state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::movement_cost);
4292 float effective_distance = std::max(0.1f, distance * (sum_mods + 1.0f));
4294 float effective_speed = effective_army_speed(state, a);
4296 int32_t days = effective_speed > 0.0f ? int32_t(std::ceil(effective_distance / effective_speed)) : 50;
4298 return state.current_date + days;
4301 auto current_location = state.world.navy_get_location_from_navy_location(n);
4302 auto adj = state.world.get_province_adjacency_by_province_pair(current_location, p);
4304 float sum_mods = state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::movement_cost) +
4305 state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::movement_cost);
4306 float effective_distance = std::max(0.1f, distance * (sum_mods + 1.0f));
4308 float effective_speed = effective_navy_speed(state, n);
4310 int32_t days = effective_speed > 0.0f ? int32_t(std::ceil(effective_distance / effective_speed)) : 50;
4311 return state.current_date + days;
4314void add_army_to_battle(
sys::state& state, dcon::army_id a, dcon::land_battle_id b, war_role r) {
4315 assert(state.world.army_is_valid(a));
4316 bool battle_attacker = (r == war_role::attacker) == state.world.land_battle_get_war_attacker_is_attacker(b);
4317 if(battle_attacker) {
4318 if(!state.world.land_battle_get_general_from_attacking_general(b)) {
4319 state.world.land_battle_set_general_from_attacking_general(b, state.world.army_get_general_from_army_leadership(a));
4322 auto reserves = state.world.land_battle_get_reserves(b);
4323 for(
auto reg : state.world.army_get_army_membership(a)) {
4324 if(reg.get_regiment().get_strength() <= 0.0f)
4327 auto type = state.military_definitions.unit_base_definitions[reg.get_regiment().get_type()].type;
4329 case unit_type::infantry:
4331 reserve_regiment{reg.get_regiment().id, reserve_regiment::is_attacking | reserve_regiment::type_infantry});
4332 state.world.land_battle_get_attacker_infantry(b) += reg.get_regiment().get_strength();
4334 case unit_type::cavalry:
4336 reserve_regiment{reg.get_regiment().id, reserve_regiment::is_attacking | reserve_regiment::type_cavalry});
4337 state.world.land_battle_get_attacker_cav(b) += reg.get_regiment().get_strength();
4339 case unit_type::special:
4340 case unit_type::support:
4342 reserve_regiment{reg.get_regiment().id, reserve_regiment::is_attacking | reserve_regiment::type_support});
4343 state.world.land_battle_get_attacker_support(b) += reg.get_regiment().get_strength();
4350 auto& def_bonus =
state.world.land_battle_get_defender_bonus(b);
4352 auto new_dig_in = std::min(prev_dig_in,
state.world.army_get_dig_in(a) & defender_bonus_dig_in_mask);
4353 def_bonus &= ~defender_bonus_dig_in_mask;
4354 def_bonus |= new_dig_in;
4356 if(!
state.world.land_battle_get_general_from_defending_general(b)) {
4357 state.world.land_battle_set_general_from_defending_general(b,
state.world.army_get_general_from_army_leadership(a));
4359 auto reserves =
state.world.land_battle_get_reserves(b);
4360 for(
auto reg :
state.world.army_get_army_membership(a)) {
4361 if(reg.get_regiment().get_strength() <= 0.0f)
4364 auto type =
state.military_definitions.unit_base_definitions[reg.get_regiment().get_type()].type;
4366 case unit_type::infantry:
4367 reserves.push_back(reserve_regiment{reg.get_regiment().
id, reserve_regiment::type_infantry});
4368 state.world.land_battle_get_defender_infantry(b) += reg.get_regiment().get_strength();
4370 case unit_type::cavalry:
4371 reserves.push_back(reserve_regiment{reg.get_regiment().
id, reserve_regiment::type_cavalry});
4372 state.world.land_battle_get_defender_cav(b) += reg.get_regiment().get_strength();
4374 case unit_type::special:
4375 case unit_type::support:
4376 reserves.push_back(reserve_regiment{reg.get_regiment().
id, reserve_regiment::type_support});
4377 state.world.land_battle_get_defender_support(b) += reg.get_regiment().get_strength();
4385 state.world.army_set_battle_from_army_battle_participation(a, b);
4389void army_arrives_in_province(
sys::state& state, dcon::army_id a, dcon::province_id p, crossing_type crossing, dcon::land_battle_id from) {
4390 assert(state.world.army_is_valid(a));
4391 assert(!state.world.army_get_battle_from_army_battle_participation(a));
4393 state.world.army_set_location_from_army_location(a, p);
4394 auto regs = state.world.army_get_army_membership(a);
4395 if(!state.world.army_get_black_flag(a) && !state.world.army_get_is_retreating(a) && regs.begin() != regs.end()) {
4396 auto owner_nation = state.world.army_get_controller_from_army_control(a);
4399 for(
auto b : state.world.province_get_land_battle_location(p)) {
4400 if(b.get_battle() != from) {
4401 auto battle_war = b.get_battle().get_war_from_land_battle_in_war();
4403 auto owner_role = get_role(state, battle_war, owner_nation);
4404 if(owner_role != war_role::none) {
4405 add_army_to_battle(state, a, b.get_battle(), owner_role);
4409 add_army_to_battle(state, a, b.get_battle(),
bool(owner_nation) ? war_role::defender : war_role::attacker);
4416 dcon::land_battle_id gather_to_battle;
4417 dcon::war_id battle_in_war;
4419 for(
auto o : state.world.province_get_army_location(p)) {
4420 if(o.get_army() == a)
4422 if(o.get_army().get_is_retreating() || o.get_army().get_black_flag() || o.get_army().get_navy_from_army_transport() || o.get_army().get_battle_from_army_battle_participation())
4425 auto other_nation = o.get_army().get_controller_from_army_control();
4427 if(
bool(owner_nation) !=
bool(other_nation)) {
4428 auto new_battle = fatten(state.world, state.world.create_land_battle());
4429 new_battle.set_war_attacker_is_attacker(!
bool(owner_nation));
4430 new_battle.set_start_date(state.current_date);
4431 new_battle.set_location_from_land_battle_location(p);
4432 new_battle.set_dice_rolls(make_dice_rolls(state,
uint32_t(new_battle.id.value)));
4434 uint8_t flags = defender_bonus_dig_in_mask;
4435 if(crossing == crossing_type::river)
4436 flags |= defender_bonus_crossing_river;
4437 if(crossing == crossing_type::sea)
4438 flags |= defender_bonus_crossing_sea;
4439 new_battle.set_defender_bonus(flags);
4441 auto cw_a = state.defines.base_combat_width +
4442 state.world.nation_get_modifier_values(owner_nation, sys::national_mod_offsets::combat_width);
4443 auto cw_b = state.defines.base_combat_width +
4444 state.world.nation_get_modifier_values(other_nation, sys::national_mod_offsets::combat_width);
4445 new_battle.set_combat_width(
uint8_t(
4446 std::clamp(int32_t(std::min(cw_a, cw_b) *
4447 (state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::combat_width) + 1.0f)),
4450 add_army_to_battle(state, a, new_battle, !
bool(owner_nation) ? war_role::attacker : war_role::defender);
4451 add_army_to_battle(state, o.get_army(), new_battle,
bool(owner_nation) ? war_role::attacker : war_role::defender);
4453 gather_to_battle = new_battle.id;
4455 }
else if(
auto par = internal_find_war_between(state, owner_nation, other_nation); par.
role != war_role::none) {
4456 auto new_battle = fatten(state.world, state.world.create_land_battle());
4457 new_battle.set_war_attacker_is_attacker(par.role == war_role::attacker);
4458 new_battle.set_start_date(state.current_date);
4459 new_battle.set_war_from_land_battle_in_war(par.w);
4460 new_battle.set_location_from_land_battle_location(p);
4461 new_battle.set_dice_rolls(make_dice_rolls(state,
uint32_t(new_battle.id.value)));
4463 uint8_t flags = defender_bonus_dig_in_mask;
4464 if(crossing == crossing_type::river)
4465 flags |= defender_bonus_crossing_river;
4466 if(crossing == crossing_type::sea)
4467 flags |= defender_bonus_crossing_sea;
4468 new_battle.set_defender_bonus(flags);
4470 auto cw_a = state.defines.base_combat_width +
4471 state.world.nation_get_modifier_values(owner_nation, sys::national_mod_offsets::combat_width);
4472 auto cw_b = state.defines.base_combat_width +
4473 state.world.nation_get_modifier_values(other_nation, sys::national_mod_offsets::combat_width);
4474 new_battle.set_combat_width(
uint8_t(
4475 std::clamp(int32_t(std::min(cw_a, cw_b) *
4476 (state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::combat_width) + 1.0f)),
4479 add_army_to_battle(state, a, new_battle, par.role);
4480 add_army_to_battle(state, o.get_army(), new_battle, par.role == war_role::attacker ? war_role::defender : war_role::attacker);
4482 gather_to_battle = new_battle.id;
4483 battle_in_war = par.w;
4489 if(gather_to_battle) {
4490 for(
auto o : state.world.province_get_army_location(p)) {
4491 if(o.get_army() == a)
4493 if(o.get_army().get_is_retreating() || o.get_army().get_black_flag() || o.get_army().get_navy_from_army_transport() || o.get_army().get_battle_from_army_battle_participation())
4496 auto other_nation = o.get_army().get_controller_from_army_control();
4498 if(
auto role = get_role(state, battle_in_war, other_nation); role != war_role::none) {
4499 add_army_to_battle(state, o.get_army(), gather_to_battle, role);
4502 add_army_to_battle(state, o.get_army(), gather_to_battle, !
bool(other_nation) ? war_role::attacker : war_role::defender);
4507 for(
auto par : state.world.war_get_war_participant(battle_in_war)) {
4508 if(par.get_nation().get_is_player_controlled() ==
false)
4511 }
else if(state.world.nation_get_is_player_controlled(owner_nation) ==
false) {
4518void add_navy_to_battle(
sys::state& state, dcon::navy_id n, dcon::naval_battle_id b, war_role r) {
4519 assert(state.world.navy_is_valid(n));
4520 bool battle_attacker = (r == war_role::attacker) == state.world.naval_battle_get_war_attacker_is_attacker(b);
4521 if(battle_attacker) {
4523 if(!state.world.naval_battle_get_admiral_from_attacking_admiral(b)) {
4524 state.world.naval_battle_set_admiral_from_attacking_admiral(b, state.world.navy_get_admiral_from_navy_leadership(n));
4527 auto slots = state.world.naval_battle_get_slots(b);
4528 for(
auto ship : state.world.navy_get_navy_membership(n)) {
4529 if(ship.get_ship().get_strength() <= 0.0f)
4532 auto type = state.military_definitions.unit_base_definitions[ship.get_ship().get_type()].type;
4534 case unit_type::big_ship:
4535 slots.push_back(ship_in_battle{ship.get_ship().id, 0,
4536 1000 | ship_in_battle::mode_seeking | ship_in_battle::is_attacking | ship_in_battle::type_big});
4537 state.world.naval_battle_get_attacker_big_ships(b)++;
4539 case unit_type::light_ship:
4540 slots.push_back(ship_in_battle{ship.get_ship().id, 0,
4541 1000 | ship_in_battle::mode_seeking | ship_in_battle::is_attacking | ship_in_battle::type_small});
4542 state.world.naval_battle_get_attacker_small_ships(b)++;
4544 case unit_type::transport:
4545 slots.push_back(ship_in_battle{ship.get_ship().id, 0,
4546 1000 | ship_in_battle::mode_seeking | ship_in_battle::is_attacking | ship_in_battle::type_transport});
4547 state.world.naval_battle_get_attacker_transport_ships(b)++;
4554 if(!
state.world.naval_battle_get_admiral_from_defending_admiral(b)) {
4555 state.world.naval_battle_set_admiral_from_defending_admiral(b,
state.world.navy_get_admiral_from_navy_leadership(n));
4557 auto slots =
state.world.naval_battle_get_slots(b);
4558 for(
auto ship :
state.world.navy_get_navy_membership(n)) {
4559 if(ship.get_ship().get_strength() <= 0.0f)
4562 auto type =
state.military_definitions.unit_base_definitions[ship.get_ship().get_type()].type;
4564 case unit_type::big_ship:
4565 slots.push_back(ship_in_battle{ship.get_ship().
id, 0, 1000 | ship_in_battle::mode_seeking | ship_in_battle::type_big});
4566 state.world.naval_battle_get_defender_big_ships(b)++;
4568 case unit_type::light_ship:
4569 slots.push_back(ship_in_battle{ship.get_ship().
id, 0, 1000 | ship_in_battle::mode_seeking | ship_in_battle::type_small});
4570 state.world.naval_battle_get_defender_small_ships(b)++;
4572 case unit_type::transport:
4574 ship_in_battle{ship.get_ship().
id, 0, 1000 | ship_in_battle::mode_seeking | ship_in_battle::type_transport});
4575 state.world.naval_battle_get_defender_transport_ships(b)++;
4583 state.world.navy_set_battle_from_navy_battle_participation(n, b);
4586 for(
auto em :
state.world.navy_get_army_transport(n)) {
4587 em.get_army().set_arrival_time(
sys::date{});
4591bool retreat(
sys::state& state, dcon::navy_id n) {
4592 auto province_start = state.world.navy_get_location_from_navy_location(n);
4593 auto nation_controller = state.world.navy_get_controller_from_navy_control(n);
4595 if(!nation_controller)
4599 if(retreat_path.size() > 0) {
4600 state.world.navy_set_is_retreating(n,
true);
4601 auto existing_path = state.world.navy_get_path(n);
4602 existing_path.load_range(retreat_path.data(), retreat_path.data() + retreat_path.size());
4604 state.world.navy_set_arrival_time(n, arrival_time_to(state, n, retreat_path.back()));
4606 for(
auto em : state.world.navy_get_army_transport(n)) {
4607 em.get_army().get_path().clear();
4615bool retreat(
sys::state& state, dcon::army_id n) {
4616 auto province_start = state.world.army_get_location_from_army_location(n);
4617 auto nation_controller = state.world.army_get_controller_from_army_control(n);
4619 if(!nation_controller)
4623 if(retreat_path.size() > 0) {
4624 state.world.army_set_is_retreating(n,
true);
4625 auto existing_path = state.world.army_get_path(n);
4626 existing_path.load_range(retreat_path.data(), retreat_path.data() + retreat_path.size());
4628 state.world.army_set_arrival_time(n, arrival_time_to(state, n, retreat_path.back()));
4629 state.world.army_set_dig_in(n, 0);
4636dcon::nation_id get_naval_battle_lead_attacker(
sys::state& state, dcon::naval_battle_id b) {
4638 state.world.leader_get_nation_from_leader_loyalty(state.world.naval_battle_get_admiral_from_attacking_admiral(b));
4642 auto war = state.world.naval_battle_get_war_from_naval_battle_in_war(b);
4643 bool war_attackers = state.world.naval_battle_get_war_attacker_is_attacker(b);
4645 for(
auto nbp : state.world.naval_battle_get_navy_battle_participation(b)) {
4646 if(war_attackers && is_attacker(state, war, nbp.get_navy().get_controller_from_navy_control())) {
4647 return nbp.get_navy().get_controller_from_navy_control();
4648 }
else if(!war_attackers && !is_attacker(state, war, nbp.get_navy().get_controller_from_navy_control())) {
4649 return nbp.get_navy().get_controller_from_navy_control();
4653 return dcon::nation_id{};
4656dcon::nation_id get_naval_battle_lead_defender(
sys::state& state, dcon::naval_battle_id b) {
4658 state.world.leader_get_nation_from_leader_loyalty(state.world.naval_battle_get_admiral_from_defending_admiral(b));
4662 auto war = state.world.naval_battle_get_war_from_naval_battle_in_war(b);
4663 bool war_attackers = state.world.naval_battle_get_war_attacker_is_attacker(b);
4665 for(
auto nbp : state.world.naval_battle_get_navy_battle_participation(b)) {
4666 if(!war_attackers && is_attacker(state, war, nbp.get_navy().get_controller_from_navy_control())) {
4667 return nbp.get_navy().get_controller_from_navy_control();
4668 }
else if(war_attackers && !is_attacker(state, war, nbp.get_navy().get_controller_from_navy_control())) {
4669 return nbp.get_navy().get_controller_from_navy_control();
4673 return dcon::nation_id{};
4676dcon::nation_id get_land_battle_lead_attacker(
sys::state& state, dcon::land_battle_id b) {
4678 state.world.leader_get_nation_from_leader_loyalty(state.world.land_battle_get_general_from_attacking_general(b));
4682 auto war = state.world.land_battle_get_war_from_land_battle_in_war(b);
4683 bool war_attackers = state.world.land_battle_get_war_attacker_is_attacker(b);
4687 return dcon::nation_id{};
4689 for(
auto nbp : state.world.land_battle_get_army_battle_participation(b)) {
4690 auto c = nbp.get_army().get_controller_from_army_control();
4696 for(
auto nbp :
state.world.land_battle_get_army_battle_participation(b)) {
4697 if(war_attackers &&
is_attacker(state, war, nbp.get_army().get_controller_from_army_control())) {
4698 return nbp.get_army().get_controller_from_army_control();
4699 }
else if(!war_attackers && !
is_attacker(state, war, nbp.get_army().get_controller_from_army_control())) {
4700 return nbp.get_army().get_controller_from_army_control();
4704 return dcon::nation_id{};
4707dcon::nation_id get_land_battle_lead_defender(
sys::state& state, dcon::land_battle_id b) {
4709 state.world.leader_get_nation_from_leader_loyalty(state.world.land_battle_get_general_from_defending_general(b));
4713 auto war = state.world.land_battle_get_war_from_land_battle_in_war(b);
4714 bool war_attackers = state.world.land_battle_get_war_attacker_is_attacker(b);
4718 return dcon::nation_id{};
4720 for(
auto nbp : state.world.land_battle_get_army_battle_participation(b)) {
4721 auto c = nbp.get_army().get_controller_from_army_control();
4727 for(
auto nbp :
state.world.land_battle_get_army_battle_participation(b)) {
4728 if(!war_attackers &&
is_attacker(state, war, nbp.get_army().get_controller_from_army_control())) {
4729 return nbp.get_army().get_controller_from_army_control();
4730 }
else if(war_attackers && !
is_attacker(state, war, nbp.get_army().get_controller_from_army_control())) {
4731 return nbp.get_army().get_controller_from_army_control();
4735 return dcon::nation_id{};
4738float get_leader_select_score(
sys::state& state, dcon::leader_id l) {
4744 auto per = state.world.leader_get_personality(l);
4745 auto bak = state.world.leader_get_background(l);
4747 auto org = state.world.leader_trait_get_organisation(per) + state.world.leader_trait_get_organisation(bak);
4748 auto atk = state.world.leader_trait_get_attack(per) + state.world.leader_trait_get_attack(bak);
4749 auto def = state.world.leader_trait_get_defense(per) + state.world.leader_trait_get_defense(bak);
4750 auto spd = state.world.leader_trait_get_speed(per) + state.world.leader_trait_get_speed(bak);
4751 auto mor = state.world.leader_trait_get_morale(per) + state.world.leader_trait_get_morale(bak);
4752 auto att = state.world.leader_trait_get_experience(per) + state.world.leader_trait_get_experience(bak);
4753 auto rel = state.world.leader_trait_get_reliability(per) + state.world.leader_trait_get_reliability(bak);
4754 auto exp = state.world.leader_trait_get_experience(per) + state.world.leader_trait_get_experience(bak);
4755 auto rec = state.world.leader_trait_get_reconnaissance(per) + state.world.leader_trait_get_reconnaissance(bak);
4756 auto lp = state.world.leader_get_prestige(l);
4757 return (org * 5.f + atk + def + mor + spd + att + exp / 2.f + rec / 5.f + rel / 5.f) * (lp + 1.f);
4759void update_battle_leaders(
sys::state& state, dcon::land_battle_id b) {
4760 auto la = get_land_battle_lead_attacker(state, b);
4761 dcon::leader_id a_lid;
4762 float a_score = 0.f;
4763 auto ld = get_land_battle_lead_defender(state, b);
4764 dcon::leader_id d_lid;
4765 float d_score = 0.f;
4766 for(
const auto a : state.world.land_battle_get_army_battle_participation(b)) {
4767 auto l = a.get_army().get_general_from_army_leadership();
4768 auto score = get_leader_select_score(state, l);
4769 if(a.get_army().get_controller_from_army_control() == la) {
4770 if(score > a_score) {
4774 }
else if(a.get_army().get_controller_from_army_control() == ld) {
4775 if(score > d_score) {
4781 auto aa =
state.world.land_battle_get_attacking_general(b);
4782 state.world.attacking_general_set_general(aa, a_lid);
4783 auto ab =
state.world.land_battle_get_defending_general(b);
4784 state.world.defending_general_set_general(ab, d_lid);
4786void update_battle_leaders(
sys::state& state, dcon::naval_battle_id b) {
4787 auto la = get_naval_battle_lead_attacker(state, b);
4788 dcon::leader_id a_lid;
4789 float a_score = 0.f;
4790 auto ld = get_naval_battle_lead_defender(state, b);
4791 dcon::leader_id d_lid;
4792 float d_score = 0.f;
4793 for(
const auto a : state.world.naval_battle_get_navy_battle_participation(b)) {
4794 auto l = a.get_navy().get_admiral_from_navy_leadership();
4795 auto score = get_leader_select_score(state, l);
4796 if(a.get_navy().get_controller_from_navy_control() == la) {
4797 if(score > a_score) {
4801 }
else if(a.get_navy().get_controller_from_navy_control() == ld) {
4802 if(score > d_score) {
4808 auto aa =
state.world.naval_battle_get_attacking_admiral(b);
4809 state.world.attacking_admiral_set_admiral(aa, a_lid);
4810 auto ab =
state.world.naval_battle_get_defending_admiral(b);
4811 state.world.defending_admiral_set_admiral(ab, d_lid);
4814void cleanup_army(
sys::state& state, dcon::army_id n) {
4815 assert(!state.world.army_get_battle_from_army_battle_participation(n));
4817 auto regs = state.world.army_get_army_membership(n);
4818 while(regs.begin() != regs.end()) {
4819 state.world.delete_regiment((*regs.begin()).get_regiment().id);
4822 auto b =
state.world.army_get_battle_from_army_battle_participation(n);
4824 state.world.army_set_is_retreating(n,
true);
4826 bool should_end =
true;
4827 auto controller =
state.world.army_get_controller_from_army_control(n);
4828 if(
bool(controller)) {
4830 bool has_other =
false;
4831 bool has_rebels =
false;
4832 for(
auto bp :
state.world.land_battle_get_army_battle_participation_as_battle(b)) {
4833 if(bp.get_army() != n) {
4835 if(
are_allied_in_war(state, controller, bp.get_army().get_controller_from_army_control())) {
4837 }
else if(bp.get_army().get_controller_from_army_rebel_control()) {
4843 if(has_other && has_rebels)
4845 }
else if(
state.world.army_get_controller_from_army_rebel_control(n)) {
4846 for(
auto bp :
state.world.land_battle_get_army_battle_participation_as_battle(b)) {
4847 if(bp.get_army() != n && bp.get_army().get_army_rebel_control()) {
4856 bool as_attacker =
state.world.land_battle_get_war_attacker_is_attacker(b);
4857 end_battle(state, b, as_attacker ? battle_result::defender_won : battle_result::attacker_won);
4861 state.world.delete_army(n);
4864void cleanup_navy(
sys::state& state, dcon::navy_id n) {
4865 assert(!state.world.navy_get_battle_from_navy_battle_participation(n));
4867 auto shps = state.world.navy_get_navy_membership(n);
4868 while(shps.begin() != shps.end()) {
4869 state.world.delete_ship((*shps.begin()).get_ship());
4871 auto em =
state.world.navy_get_army_transport(n);
4872 while(em.begin() != em.end()) {
4876 auto controller =
state.world.navy_get_controller_from_navy_control(n);
4877 auto b =
state.world.navy_get_battle_from_navy_battle_participation(n);
4879 state.world.navy_set_is_retreating(n,
true);
4880 if(b && controller) {
4881 bool should_end =
true;
4883 for(
auto bp :
state.world.naval_battle_get_navy_battle_participation_as_battle(b)) {
4884 if(bp.get_navy() != n &&
are_allied_in_war(state, controller,
state.world.navy_get_controller_from_navy_control(bp.get_navy()))) {
4889 bool as_attacker =
state.world.naval_battle_get_war_attacker_is_attacker(b);
4890 end_battle(state, b, as_attacker ? battle_result::defender_won : battle_result::attacker_won);
4894 state.world.delete_navy(n);
4897void adjust_leader_prestige(
sys::state& state, dcon::leader_id l,
float value) {
4898 auto v = state.world.leader_get_prestige(l);
4899 v = std::clamp(v + value, 0.f, 1.f);
4900 state.world.leader_set_prestige(l, v);
4902void adjust_regiment_experience(
sys::state& state, dcon::nation_id n, dcon::regiment_id l,
float value) {
4903 auto v = state.world.regiment_get_experience(l);
4905 auto min_exp = std::clamp(state.world.nation_get_modifier_values(n, sys::national_mod_offsets::regular_experience_level) / 100.f, 0.f, 1.f);
4907 v = std::clamp(v + value, min_exp, 1.f);
4909 state.world.regiment_set_experience(l, v);
4911void adjust_ship_experience(
sys::state& state, dcon::nation_id n, dcon::ship_id r,
float value) {
4912 auto v = state.world.ship_get_experience(r);
4914 auto min_exp = std::clamp(state.world.nation_get_modifier_values(n, sys::national_mod_offsets::regular_experience_level) / 100.f, 0.f, 1.f);
4916 v = std::clamp(v + value * state.defines.exp_gain_div, min_exp, 1.f);
4917 state.world.ship_set_experience(r, v);
4920void end_battle(
sys::state& state, dcon::land_battle_id b, battle_result result) {
4921 auto war = state.world.land_battle_get_war_from_land_battle_in_war(b);
4922 auto location = state.world.land_battle_get_location_from_land_battle_location(b);
4926 auto make_leaderless = [&](dcon::army_id a) {
4927 state.world.army_set_controller_from_army_control(a, dcon::nation_id{});
4928 state.world.army_set_controller_from_army_rebel_control(a, dcon::rebel_faction_id{});
4929 state.world.army_set_is_retreating(a,
true);
4935 for(
auto n :
state.world.land_battle_get_army_battle_participation(b)) {
4936 auto nation_owner =
state.world.army_get_controller_from_army_control(
n.get_army());
4938 auto role_in_war = bool(war)
4939 ?
get_role(state, war,
n.get_army().get_controller_from_army_control())
4942 bool battle_attacker = (role_in_war == war_role::attacker) ==
state.world.land_battle_get_war_attacker_is_attacker(b);
4945 if(battle_attacker && result == battle_result::defender_won) {
4947 make_leaderless(
n.get_army());
4950 make_leaderless(
n.get_army());
4952 }
else if(!battle_attacker && result == battle_result::attacker_won) {
4954 make_leaderless(
n.get_army());
4957 make_leaderless(
n.get_army());
4960 auto path =
n.get_army().get_path();
4961 if(path.size() > 0) {
4962 state.world.army_set_arrival_time(
n.get_army(),
arrival_time_to(state,
n.get_army(), path.at(path.size() - 1)));
4974 if(result != battle_result::indecisive) {
4976 state.world.war_get_number_of_battles(war)++;
4978 auto a_leader =
state.world.land_battle_get_general_from_attacking_general(b);
4979 auto b_leader =
state.world.land_battle_get_general_from_defending_general(b);
4981 if(result == battle_result::attacker_won) {
4982 auto total_def_loss =
state.world.land_battle_get_defender_cav_lost(b) +
state.world.land_battle_get_defender_infantry_lost(b) +
state.world.land_battle_get_defender_support_lost(b);
4983 auto total_att_loss =
state.world.land_battle_get_attacker_cav_lost(b) +
state.world.land_battle_get_attacker_infantry_lost(b) +
state.world.land_battle_get_attacker_support_lost(b);
4984 auto score = std::max(0.0f, 3.0f * (total_def_loss - total_att_loss) / 10.0f);
4987 if(
state.world.land_battle_get_war_attacker_is_attacker(b)) {
4988 state.world.war_get_attacker_battle_score(war) += score;
4990 state.world.war_get_defender_battle_score(war) += score;
4995 if(a_nation && d_nation) {
5004 if(
state.local_player_nation == a_nation ||
state.local_player_nation == d_nation) {
5005 land_battle_report rep;
5006 rep.attacker_infantry_losses =
state.world.land_battle_get_attacker_infantry_lost(b);
5007 rep.attacker_infantry =
state.world.land_battle_get_attacker_infantry(b);
5008 rep.attacker_cavalry_losses =
state.world.land_battle_get_attacker_cav_lost(b);
5009 rep.attacker_cavalry =
state.world.land_battle_get_attacker_cav(b);
5010 rep.attacker_support_losses =
state.world.land_battle_get_attacker_support_lost(b);
5011 rep.attacker_support =
state.world.land_battle_get_attacker_support(b);
5013 rep.defender_infantry_losses =
state.world.land_battle_get_defender_infantry_lost(b);
5014 rep.defender_infantry =
state.world.land_battle_get_defender_infantry(b);
5015 rep.defender_cavalry_losses =
state.world.land_battle_get_defender_cav_lost(b);
5016 rep.defender_cavalry =
state.world.land_battle_get_defender_cav(b);
5017 rep.defender_support_losses =
state.world.land_battle_get_defender_support_lost(b);
5018 rep.defender_support =
state.world.land_battle_get_defender_support(b);
5020 rep.attacker_won = (
result == battle_result::attacker_won);
5024 rep.attacking_general =
state.world.land_battle_get_general_from_attacking_general(b);
5025 rep.defending_general =
state.world.land_battle_get_general_from_defending_general(b);
5027 rep.location =
state.world.land_battle_get_location_from_land_battle_location(b);
5028 rep.player_on_winning_side = bool(war)
5029 ?
is_attacker(state, war,
state.local_player_nation) ==
state.world.land_battle_get_war_attacker_is_attacker(b)
5030 : !
state.world.land_battle_get_war_attacker_is_attacker(b);
5033 if(rep.player_on_winning_side) {
5034 rep.warscore_effect = score;
5035 rep.prestige_effect = score / 50.0f;
5037 rep.warscore_effect = -score;
5038 rep.prestige_effect = -score / 50.0f;
5042 auto discard =
state.land_battle_reports.try_push(rep);
5045 }
else if(result == battle_result::defender_won) {
5046 auto total_def_loss =
state.world.land_battle_get_defender_cav_lost(b) +
state.world.land_battle_get_defender_infantry_lost(b) +
state.world.land_battle_get_defender_support_lost(b);
5047 auto total_att_loss =
state.world.land_battle_get_attacker_cav_lost(b) +
state.world.land_battle_get_attacker_infantry_lost(b) +
state.world.land_battle_get_attacker_support_lost(b);
5048 auto score = std::max(0.0f, 3.0f * (total_att_loss - total_def_loss) / 10.0f);
5051 if(
state.world.land_battle_get_war_attacker_is_attacker(b)) {
5052 state.world.war_get_defender_battle_score(war) += score;
5054 state.world.war_get_attacker_battle_score(war) += score;
5058 if(a_nation && d_nation) {
5067 if(
state.local_player_nation == a_nation ||
state.local_player_nation == d_nation) {
5068 land_battle_report rep;
5069 rep.attacker_infantry_losses =
state.world.land_battle_get_attacker_infantry_lost(b);
5070 rep.attacker_infantry =
state.world.land_battle_get_attacker_infantry(b);
5071 rep.attacker_cavalry_losses =
state.world.land_battle_get_attacker_cav_lost(b);
5072 rep.attacker_cavalry =
state.world.land_battle_get_attacker_cav(b);
5073 rep.attacker_support_losses =
state.world.land_battle_get_attacker_support_lost(b);
5074 rep.attacker_support =
state.world.land_battle_get_attacker_support(b);
5076 rep.defender_infantry_losses =
state.world.land_battle_get_defender_infantry_lost(b);
5077 rep.defender_infantry =
state.world.land_battle_get_defender_infantry(b);
5078 rep.defender_cavalry_losses =
state.world.land_battle_get_defender_cav_lost(b);
5079 rep.defender_cavalry =
state.world.land_battle_get_defender_cav(b);
5080 rep.defender_support_losses =
state.world.land_battle_get_defender_support_lost(b);
5081 rep.defender_support =
state.world.land_battle_get_defender_support(b);
5083 rep.attacker_won = (
result == battle_result::attacker_won);
5087 rep.attacking_general =
state.world.land_battle_get_general_from_attacking_general(b);
5088 rep.defending_general =
state.world.land_battle_get_general_from_defending_general(b);
5090 rep.location =
state.world.land_battle_get_location_from_land_battle_location(b);
5091 rep.player_on_winning_side = bool(war)
5092 ?
is_attacker(state, war,
state.local_player_nation) !=
state.world.land_battle_get_war_attacker_is_attacker(b)
5093 :
state.world.land_battle_get_war_attacker_is_attacker(b);
5096 if(rep.player_on_winning_side) {
5097 rep.warscore_effect = score;
5098 rep.prestige_effect = score / 50.0f;
5100 rep.warscore_effect = -score;
5101 rep.prestige_effect = -score / 50.0f;
5104 auto discard =
state.land_battle_reports.try_push(rep);
5110 if(result != battle_result::indecisive) {
5111 auto par_range =
state.world.land_battle_get_army_battle_participation(b);
5112 while(par_range.begin() != par_range.end()) {
5113 auto n = (*par_range.begin()).get_army();
5114 n.set_battle_from_army_battle_participation(dcon::land_battle_id{});
5119 state.world.delete_land_battle(b);
5122void end_battle(
sys::state& state, dcon::naval_battle_id b, battle_result result) {
5123 auto war = state.world.naval_battle_get_war_from_naval_battle_in_war(b);
5124 auto location = state.world.naval_battle_get_location_from_naval_battle_location(b);
5129 auto a_nation = get_naval_battle_lead_attacker(state, b);
5130 auto d_nation = get_naval_battle_lead_defender(state, b);
5132 for(
auto n : state.world.naval_battle_get_navy_battle_participation(b)) {
5133 auto role_in_war = get_role(state, war, n.get_navy().get_controller_from_navy_control());
5134 bool battle_attacker = (role_in_war == war_role::attacker) == state.world.naval_battle_get_war_attacker_is_attacker(b);
5138 if(transport_cap < 0) {
5139 for(
auto em : n.get_navy().get_army_transport()) {
5140 auto em_regs = em.get_army().get_army_membership();
5141 while(em_regs.begin() != em_regs.end() && transport_cap < 0) {
5142 auto reg_id = (*em_regs.begin()).get_regiment();
5143 disband_regiment_w_pop_death(state, reg_id);
5146 if(transport_cap >= 0)
5151 if(battle_attacker && result == battle_result::defender_won) {
5152 if(!can_retreat_from_battle(state, b)) {
5153 n.get_navy().set_controller_from_navy_control(dcon::nation_id{});
5154 n.get_navy().set_is_retreating(
true);
5156 if(!retreat(state, n.get_navy())) {
5157 n.get_navy().set_controller_from_navy_control(dcon::nation_id{});
5158 n.get_navy().set_is_retreating(
true);
5161 }
else if(!battle_attacker && result == battle_result::attacker_won) {
5162 if(!can_retreat_from_battle(state, b)) {
5163 n.get_navy().set_controller_from_navy_control(dcon::nation_id{});
5164 n.get_navy().set_is_retreating(
true);
5166 if(!retreat(state, n.get_navy())) {
5167 n.get_navy().set_controller_from_navy_control(dcon::nation_id{});
5168 n.get_navy().set_is_retreating(
true);
5172 auto path = n.get_navy().get_path();
5173 if(path.size() > 0) {
5174 state.world.navy_set_arrival_time(n.get_navy(), arrival_time_to(state, n.get_navy(), path.at(path.size() - 1)));
5177 for(
auto em : n.get_navy().get_army_transport()) {
5178 auto apath = em.get_army().get_path();
5179 if(apath.size() > 0) {
5180 state.world.army_set_arrival_time(em.get_army(), arrival_time_to(state, em.get_army(), apath.at(apath.size() - 1)));
5199 if(result != battle_result::indecisive) {
5200 state.world.war_get_number_of_battles(war)++;
5202 auto a_leader =
state.world.naval_battle_get_admiral_from_attacking_admiral(b);
5203 auto b_leader =
state.world.naval_battle_get_admiral_from_defending_admiral(b);
5205 if(result == battle_result::attacker_won) {
5206 auto score = std::max(0.0f,
5207 (
state.world.naval_battle_get_defender_loss_value(b) -
state.world.naval_battle_get_attacker_loss_value(b)) / 10.0f);
5208 if(
state.world.naval_battle_get_war_attacker_is_attacker(b)) {
5209 state.world.war_get_attacker_battle_score(war) += score;
5211 state.world.war_get_defender_battle_score(war) += score;
5215 if(a_nation && d_nation) {
5222 if(
state.local_player_nation == a_nation ||
state.local_player_nation == d_nation) {
5223 naval_battle_report rep;
5224 rep.attacker_big_losses =
state.world.naval_battle_get_attacker_big_ships_lost(b);
5225 rep.attacker_big_ships =
state.world.naval_battle_get_attacker_big_ships(b);
5226 rep.attacker_small_losses =
state.world.naval_battle_get_attacker_small_ships_lost(b);
5227 rep.attacker_small_ships =
state.world.naval_battle_get_attacker_small_ships(b);
5228 rep.attacker_transport_losses =
state.world.naval_battle_get_attacker_transport_ships_lost(b);
5229 rep.attacker_transport_ships =
state.world.naval_battle_get_attacker_transport_ships(b);
5231 rep.defender_big_losses =
state.world.naval_battle_get_defender_big_ships_lost(b);
5232 rep.defender_big_ships =
state.world.naval_battle_get_defender_big_ships(b);
5233 rep.defender_small_losses =
state.world.naval_battle_get_defender_small_ships_lost(b);
5234 rep.defender_small_ships =
state.world.naval_battle_get_defender_small_ships(b);
5235 rep.defender_transport_losses =
state.world.naval_battle_get_defender_transport_ships_lost(b);
5236 rep.defender_transport_ships =
state.world.naval_battle_get_defender_transport_ships(b);
5238 rep.attacker_won = (
result == battle_result::attacker_won);
5242 rep.attacking_admiral =
state.world.naval_battle_get_admiral_from_attacking_admiral(b);
5243 rep.defending_admiral =
state.world.naval_battle_get_admiral_from_defending_admiral(b);
5245 rep.location =
state.world.naval_battle_get_location_from_naval_battle_location(b);
5246 rep.player_on_winning_side =
5247 is_attacker(state, war,
state.local_player_nation) ==
state.world.naval_battle_get_war_attacker_is_attacker(b);
5249 if(rep.player_on_winning_side) {
5250 rep.warscore_effect = score;
5251 rep.prestige_effect = score / 50.0f;
5253 rep.warscore_effect = -score;
5254 rep.prestige_effect = -score / 50.0f;
5256 auto discard =
state.naval_battle_reports.try_push(rep);
5259 }
else if(result == battle_result::defender_won) {
5260 auto score = std::max(0.0f,
5261 (
state.world.naval_battle_get_attacker_loss_value(b) -
state.world.naval_battle_get_defender_loss_value(b)) / 10.0f);
5262 if(
state.world.naval_battle_get_war_attacker_is_attacker(b)) {
5263 state.world.war_get_attacker_battle_score(war) += score;
5265 state.world.war_get_defender_battle_score(war) += score;
5268 if(a_nation && d_nation) {
5275 if(
state.local_player_nation == a_nation ||
state.local_player_nation == d_nation) {
5276 naval_battle_report rep;
5277 rep.attacker_big_losses =
state.world.naval_battle_get_attacker_big_ships_lost(b);
5278 rep.attacker_big_ships =
state.world.naval_battle_get_attacker_big_ships(b);
5279 rep.attacker_small_losses =
state.world.naval_battle_get_attacker_small_ships_lost(b);
5280 rep.attacker_small_ships =
state.world.naval_battle_get_attacker_small_ships(b);
5281 rep.attacker_transport_losses =
state.world.naval_battle_get_attacker_transport_ships_lost(b);
5282 rep.attacker_transport_ships =
state.world.naval_battle_get_attacker_transport_ships(b);
5284 rep.defender_big_losses =
state.world.naval_battle_get_defender_big_ships_lost(b);
5285 rep.defender_big_ships =
state.world.naval_battle_get_defender_big_ships(b);
5286 rep.defender_small_losses =
state.world.naval_battle_get_defender_small_ships_lost(b);
5287 rep.defender_small_ships =
state.world.naval_battle_get_defender_small_ships(b);
5288 rep.defender_transport_losses =
state.world.naval_battle_get_defender_transport_ships_lost(b);
5289 rep.defender_transport_ships =
state.world.naval_battle_get_defender_transport_ships(b);
5291 rep.attacker_won = (
result == battle_result::attacker_won);
5295 rep.attacking_admiral =
state.world.naval_battle_get_admiral_from_attacking_admiral(b);
5296 rep.defending_admiral =
state.world.naval_battle_get_admiral_from_defending_admiral(b);
5298 rep.location =
state.world.naval_battle_get_location_from_naval_battle_location(b);
5299 rep.player_on_winning_side =
5300 is_attacker(state, war,
state.local_player_nation) !=
state.world.naval_battle_get_war_attacker_is_attacker(b);
5302 if(rep.player_on_winning_side) {
5303 rep.warscore_effect = score;
5304 rep.prestige_effect = score / 50.0f;
5306 rep.warscore_effect = -score;
5307 rep.prestige_effect = -score / 50.0f;
5309 auto discard =
state.naval_battle_reports.try_push(rep);
5315 if(result != battle_result::indecisive) {
5316 auto par_range =
state.world.naval_battle_get_navy_battle_participation(b);
5317 while(par_range.begin() != par_range.end()) {
5318 auto n = (*par_range.begin()).get_navy();
5319 n.set_battle_from_navy_battle_participation(dcon::naval_battle_id{});
5324 state.world.delete_naval_battle(b);
5327inline constexpr float combat_modifier_table[] = {0.0f, 0.02f, 0.04f, 0.06f, 0.08f, 0.10f, 0.12f, 0.16f, 0.20f, 0.25f, 0.30f,
5328 0.35f, 0.40f, 0.45f, 0.50f, 0.60f, 0.70f, 0.80f, 0.90f};
5330dcon::nation_id tech_nation_for_regiment(
sys::state& state, dcon::regiment_id r) {
5331 auto army = state.world.regiment_get_army_from_army_membership(r);
5332 auto nation = state.world.army_get_controller_from_army_control(army);
5335 auto rf = state.world.army_get_controller_from_army_rebel_control(army);
5336 auto ruler = state.world.rebel_faction_get_ruler_from_rebellion_within(rf);
5339 return state.world.national_identity_get_nation_from_identity_holder(state.national_definitions.rebel_id);
5342bool will_recieve_attrition(
sys::state& state, dcon::navy_id a) {
5346float peacetime_attrition_limit(
sys::state& state, dcon::nation_id n, dcon::province_id prov) {
5347 auto supply_limit = supply_limit_in_province(state, n, prov);
5348 auto prov_attrition_mod = state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::attrition);
5349 auto attrition_mod = 1.0f + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_attrition);
5351 return (supply_limit + prov_attrition_mod) / (attrition_mod * 3.0f);
5354bool will_recieve_attrition(
sys::state& state, dcon::army_id a) {
5355 auto prov = state.world.army_get_location_from_army_location(a);
5357 if(state.world.province_get_siege_progress(prov) > 0.f)
5360 float total_army_weight = 0;
5361 for(
auto ar : state.world.province_get_army_location(prov)) {
5362 if(ar.get_army().get_black_flag() ==
false && ar.get_army().get_is_retreating() ==
false &&
5363 !
bool(ar.get_army().get_navy_from_army_transport())) {
5364 for(
auto rg : ar.get_army().get_army_membership()) {
5365 total_army_weight += 3.0f * rg.get_regiment().get_strength();
5370 auto prov_attrition_mod =
state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::attrition);
5373 auto army_controller = ar.get_controller_from_army_control();
5375 auto attrition_mod = 1.0f + army_controller.get_modifier_values(sys::national_mod_offsets::land_attrition);
5377 float greatest_hostile_fort = 0.0f;
5378 for(
auto adj :
state.world.province_get_province_adjacency(prov)) {
5380 auto other =
adj.get_connected_provinces(0) !=
prov ?
adj.get_connected_provinces(0) :
adj.get_connected_provinces(1);
5382 if(
are_at_war(state, army_controller,
other.get_nation_from_province_control())) {
5388 return total_army_weight * attrition_mod - (supply_limit + prov_attrition_mod + greatest_hostile_fort) > 0;
5391float relative_attrition_amount(
sys::state& state, dcon::navy_id a, dcon::province_id prov) {
5395float local_army_weight(
sys::state& state, dcon::province_id prov) {
5396 float total_army_weight = 0;
5397 for(
auto ar : state.world.province_get_army_location(prov)) {
5398 if(ar.get_army().get_black_flag() ==
false && ar.get_army().get_is_retreating() ==
false &&
5399 !
bool(ar.get_army().get_navy_from_army_transport())) {
5400 for(
auto rg : ar.get_army().get_army_membership()) {
5401 total_army_weight += 3.0f * rg.get_regiment().get_strength();
5405 return total_army_weight;
5407float local_army_weight_max(
sys::state& state, dcon::province_id prov) {
5408 float total_army_weight = 0;
5409 for(
auto ar : state.world.province_get_army_location(prov)) {
5410 if(ar.get_army().get_black_flag() ==
false && ar.get_army().get_is_retreating() ==
false &&
5411 !
bool(ar.get_army().get_navy_from_army_transport())) {
5412 for(
auto rg : ar.get_army().get_army_membership()) {
5413 total_army_weight += 3.0f;
5417 return total_army_weight;
5419float local_enemy_army_weight_max(
sys::state& state, dcon::province_id prov, dcon::nation_id nation) {
5420 float total_army_weight = 0;
5421 for(
auto ar : state.world.province_get_army_location(prov)) {
5423 ar.get_army().get_black_flag() ==
false
5424 && ar.get_army().get_is_retreating() ==
false
5425 && !
bool(ar.get_army().get_navy_from_army_transport())
5426 && are_at_war(state, nation, ar.get_army().get_controller_from_army_control())
5428 for(
auto rg : ar.get_army().get_army_membership()) {
5429 total_army_weight += 3.0f;
5433 return total_army_weight;
5436float relative_attrition_amount(
sys::state& state, dcon::army_id a, dcon::province_id prov) {
5437 float total_army_weight = 0;
5438 for(
auto ar : state.world.province_get_army_location(prov)) {
5439 if(ar.get_army().get_black_flag() ==
false && ar.get_army().get_is_retreating() ==
false &&
5440 !
bool(ar.get_army().get_navy_from_army_transport())) {
5442 for(
auto rg : ar.get_army().get_army_membership()) {
5443 total_army_weight += 3.0f * rg.get_regiment().get_strength();
5448 auto prov_attrition_mod =
state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::attrition);
5452 auto army_controller = ar.get_controller_from_army_control();
5454 auto attrition_mod = 1.0f + army_controller.get_modifier_values(sys::national_mod_offsets::land_attrition);
5456 float greatest_hostile_fort = 0.0f;
5458 for(
auto adj :
state.world.province_get_province_adjacency(prov)) {
5460 auto other =
adj.get_connected_provinces(0) !=
prov ?
adj.get_connected_provinces(0) :
adj.get_connected_provinces(1);
5462 if(
are_at_war(state, army_controller,
other.get_nation_from_province_control())) {
5469 auto value = std::clamp(total_army_weight * attrition_mod - (supply_limit + prov_attrition_mod + greatest_hostile_fort), 0.0f,
state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::max_attrition))
5470 +
state.world.province_get_siege_progress(prov) > 0.f ?
state.defines.siege_attrition : 0.0f;
5471 return value * 0.01f;
5473float attrition_amount(
sys::state& state, dcon::navy_id a) {
5476float attrition_amount(
sys::state& state, dcon::army_id a) {
5477 return relative_attrition_amount(state, a, state.world.army_get_location_from_army_location(a));
5481 concurrency::parallel_for(0, state.province_definitions.first_sea_province.index(), [&](int32_t i) {
5482 dcon::province_id prov{dcon::province_id::value_base_t(i)};
5483 float total_army_weight = 0;
5484 for(
auto ar : state.world.province_get_army_location(prov)) {
5485 if(ar.get_army().get_black_flag() == false && ar.get_army().get_is_retreating() == false &&
5486 !bool(ar.get_army().get_navy_from_army_transport()) && !bool(ar.get_army().get_battle_from_army_battle_participation())) {
5488 for(auto rg : ar.get_army().get_army_membership()) {
5489 total_army_weight += 3.0f * rg.get_regiment().get_strength();
5494 auto prov_attrition_mod =
state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::attrition);
5496 for(
auto ar :
state.world.province_get_army_location(prov)) {
5497 if(ar.get_army().get_black_flag() == false && ar.get_army().get_is_retreating() == false &&
5498 !bool(ar.get_army().get_navy_from_army_transport()) && !bool(ar.get_army().get_battle_from_army_battle_participation())) {
5500 auto army_controller = ar.get_army().get_controller_from_army_control();
5501 auto supply_limit = supply_limit_in_province(state, army_controller, prov);
5502 auto attrition_mod = 1.0f + army_controller.get_modifier_values(sys::national_mod_offsets::land_attrition);
5504 float greatest_hostile_fort = 0.0f;
5506 for(auto adj : state.world.province_get_province_adjacency(prov)) {
5507 if((adj.get_type() & (province::border::impassible_bit | province::border::coastal_bit)) == 0) {
5508 auto other = adj.get_connected_provinces(0) != prov ? adj.get_connected_provinces(0) : adj.get_connected_provinces(1);
5509 if(other.get_building_level(uint8_t(economy::province_building_type::fort)) > 0) {
5510 if(are_at_war(state, army_controller, other.get_nation_from_province_control())) {
5511 greatest_hostile_fort = std::max(greatest_hostile_fort, float(other.get_building_level(uint8_t(economy::province_building_type::fort))));
5526 float attrition_value =
5527 std::clamp(total_army_weight * attrition_mod - (supply_limit + prov_attrition_mod + greatest_hostile_fort), 0.0f, state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::max_attrition))
5528 + state.world.province_get_siege_progress(prov) > 0.f ? state.defines.siege_attrition : 0.0f;
5530 for(auto rg : ar.get_army().get_army_membership()) {
5531 rg.get_regiment().get_pending_damage() += attrition_value * 0.01f;
5532 rg.get_regiment().get_strength() -= attrition_value * 0.01f;
5539void apply_regiment_damage(
sys::state& state) {
5540 for(
uint32_t i = state.world.regiment_size(); i-- > 0;) {
5541 dcon::regiment_id s{ dcon::regiment_id::value_base_t(i) };
5542 if(state.world.regiment_is_valid(s)) {
5543 auto& pending_damage = state.world.regiment_get_pending_damage(s);
5544 auto& current_strength = state.world.regiment_get_strength(s);
5546 if(pending_damage > 0) {
5547 auto backing_pop = state.world.regiment_get_pop_from_regiment_source(s);
5548 auto tech_nation = tech_nation_for_regiment(state, s);
5551 auto& psize = state.world.pop_get_size(backing_pop);
5552 psize -= state.defines.pop_size_per_regiment * pending_damage * state.defines.soldier_to_pop_damage /
5553 (3.0f * (1.0f + state.world.nation_get_modifier_values(tech_nation,
5554 sys::national_mod_offsets::soldier_to_pop_loss)));
5556 state.world.delete_pop(backing_pop);
5559 pending_damage = 0.0f;
5561 if(current_strength <= 0.0f) {
5563 auto army = state.world.regiment_get_army_from_army_membership(s);
5564 auto controller = state.world.army_get_controller_from_army_control(army);
5565 auto pop_backer = state.world.regiment_get_pop_from_regiment_source(s);
5573 auto maxr = state.world.nation_get_recruitable_regiments(controller);
5574 if(maxr > 0 && pop_backer) {
5575 auto& wex = state.world.nation_get_war_exhaustion(controller);
5576 wex = std::min(wex + 0.5f /
float(maxr), state.world.nation_get_modifier_values(controller, sys::national_mod_offsets::max_war_exhaustion));
5580 if(
auto b = state.world.army_get_battle_from_army_battle_participation(army); b) {
5581 for(
auto& e : state.world.land_battle_get_attacker_back_line(b)) {
5583 e = dcon::regiment_id{};
5586 for(
auto& e : state.world.land_battle_get_attacker_front_line(b)) {
5588 e = dcon::regiment_id{};
5591 for(
auto& e : state.world.land_battle_get_defender_back_line(b)) {
5593 e = dcon::regiment_id{};
5596 for(
auto& e : state.world.land_battle_get_defender_front_line(b)) {
5598 e = dcon::regiment_id{};
5602 auto reserves = state.world.land_battle_get_reserves(b);
5604 for(
uint32_t j = reserves.size(); j-- > 0;) {
5605 if(reserves[j].regiment == s) {
5606 std::swap(reserves[j], reserves[reserves.size() - 1]);
5607 reserves.pop_back();
5612 if(!controller || state.world.pop_get_size(pop_backer) < 1000.0f)
5613 state.world.delete_regiment(s);
5615 current_strength = 0.0f;
5622 auto isize = state.world.land_battle_size();
5623 auto to_delete = ve::vectorizable_buffer<uint8_t, dcon::land_battle_id>(isize);
5625 concurrency::parallel_for(0, int32_t(isize), [&](int32_t index) {
5626 dcon::land_battle_id b{dcon::land_battle_id::value_base_t(index)};
5628 if(!state.world.land_battle_is_valid(b))
5632 auto combat_width = state.world.land_battle_get_combat_width(b);
5634 auto& att_back = state.world.land_battle_get_attacker_back_line(b);
5635 auto& def_back = state.world.land_battle_get_defender_back_line(b);
5636 auto& att_front = state.world.land_battle_get_attacker_front_line(b);
5637 auto& def_front = state.world.land_battle_get_defender_front_line(b);
5639 auto reserves = state.world.land_battle_get_reserves(b);
5641 if((state.current_date.value - state.world.land_battle_get_start_date(b).value) % 5 == 4) {
5642 state.world.land_battle_set_dice_rolls(b, make_dice_rolls(state,
uint32_t(index)));
5659 auto both_dice = state.world.land_battle_get_dice_rolls(b);
5660 auto defender_mods = state.world.land_battle_get_defender_bonus(b);
5661 auto dig_in_value = defender_mods & defender_bonus_dig_in_mask;
5662 auto crossing_value = defender_mods & defender_bonus_crossing_mask;
5664 auto attacking_nation = get_land_battle_lead_attacker(state, b);
5665 auto defending_nation = get_land_battle_lead_defender(state, b);
5668 state.world.nation_get_has_gas_attack(attacking_nation) && !state.world.nation_get_has_gas_defense(defending_nation);
5670 state.world.nation_get_has_gas_attack(defending_nation) && !state.world.nation_get_has_gas_defense(attacking_nation);
5672 int32_t crossing_adjustment =
5673 (crossing_value == defender_bonus_crossing_none ? 0 : (crossing_value == defender_bonus_crossing_river ? -1 : -2));
5675 auto attacker_dice = both_dice & 0x0F;
5676 auto defender_dice = (both_dice >> 4) & 0x0F;
5678 auto location = state.world.land_battle_get_location_from_land_battle_location(b);
5679 auto terrain_bonus = state.world.province_get_modifier_values(location, sys::provincial_mod_offsets::defense);
5681 auto attacker_per = state.world.leader_get_personality(state.world.land_battle_get_general_from_attacking_general(b));
5682 auto attacker_bg = state.world.leader_get_background(state.world.land_battle_get_general_from_attacking_general(b));
5685 int32_t(state.world.leader_trait_get_attack(attacker_per) + state.world.leader_trait_get_attack(attacker_bg));
5686 auto attacker_org_bonus =
5687 (1.0f + state.world.leader_trait_get_organisation(attacker_per) + state.world.leader_trait_get_organisation(attacker_bg))
5688 * (1.0f + state.world.leader_get_prestige(state.world.land_battle_get_general_from_attacking_general(b)) * state.defines.leader_prestige_to_max_org_factor);
5690 auto defender_per = state.world.leader_get_personality(state.world.land_battle_get_general_from_defending_general(b));
5691 auto defender_bg = state.world.leader_get_background(state.world.land_battle_get_general_from_defending_general(b));
5693 auto atk_leader_exp_mod = 1 + attacker_per.get_experience() + attacker_bg.get_experience();
5694 auto def_leader_exp_mod = 1 + defender_per.get_experience() + defender_per.get_experience();
5696 auto defence_bonus =
5697 int32_t(state.world.leader_trait_get_defense(defender_per) + state.world.leader_trait_get_defense(defender_bg));
5698 auto defender_org_bonus =
5699 (1.0f + state.world.leader_trait_get_organisation(defender_per) + state.world.leader_trait_get_organisation(defender_bg))
5700 * (1.0f + state.world.leader_get_prestige(state.world.land_battle_get_general_from_defending_general(b)) * state.defines.leader_prestige_to_max_org_factor);
5702 auto attacker_mod = combat_modifier_table[std::clamp(attacker_dice + attack_bonus + crossing_adjustment + int32_t(attacker_gas ? state.defines.gas_attack_modifier : 0.0f) + 3, 0, 18)];
5703 auto defender_mod = combat_modifier_table[std::clamp(defender_dice + defence_bonus + dig_in_value + int32_t(defender_gas ? state.defines.gas_attack_modifier : 0.0f) + int32_t(terrain_bonus) + 3, 0, 18)];
5705 float defender_fort = 1.0f;
5706 auto local_control = state.world.province_get_nation_from_province_control(location);
5707 if((!attacking_nation && local_control) ||
5708 (attacking_nation && (!
bool(local_control) ||
military::are_at_war(state, attacking_nation, local_control)))) {
5736 state.world.land_battle_set_attacker_casualties(b, 0);
5737 state.world.land_battle_set_defender_casualties(b, 0);
5739 float attacker_casualties = 0;
5740 float defender_casualties = 0;
5742 for(int32_t i = 0; i < combat_width; ++i) {
5744 if(att_back[i] && def_front[i]) {
5745 assert(state.world.regiment_is_valid(att_back[i]) && state.world.regiment_is_valid(def_front[i]));
5747 auto tech_att_nation = tech_nation_for_regiment(state, att_back[i]);
5748 auto tech_def_nation = tech_nation_for_regiment(state, def_front[i]);
5750 auto att_str = state.world.regiment_get_strength(att_back[i]);
5752 auto& att_stats = state.world.nation_get_unit_stats(tech_att_nation, state.world.regiment_get_type(att_back[i]));
5753 auto& def_stats = state.world.nation_get_unit_stats(tech_def_nation, state.world.regiment_get_type(def_front[i]));
5755 auto& def_exp = state.world.regiment_get_experience(def_front[i]);
5757 auto str_damage = att_str * str_dam_mul *
5758 (att_stats.attack_or_gun_power * 0.1f + 1.0f) * att_stats.support * attacker_mod /
5759 (defender_fort * (state.defines.base_military_tactics + state.world.nation_get_modifier_values(tech_def_nation, sys::national_mod_offsets::military_tactics))
5761 auto org_damage = att_str * org_dam_mul *
5762 (att_stats.attack_or_gun_power * 0.1f + 1.0f) * att_stats.support * attacker_mod /
5763 (defender_fort * defender_org_bonus * def_stats.discipline_or_evasion *
5764 (1.0f + state.world.nation_get_modifier_values(tech_def_nation, sys::national_mod_offsets::land_organisation))
5765 * (1.0f + def_exp));
5767 auto& cstr = state.world.regiment_get_strength(def_front[i]);
5768 str_damage = std::min(str_damage, cstr);
5769 state.world.regiment_get_pending_damage(def_front[i]) += str_damage;
5771 defender_casualties += str_damage;
5773 adjust_regiment_experience(state, attacking_nation, att_back[i], str_damage * 5.f * state.defines.exp_gain_div * atk_leader_exp_mod);
5775 auto& org = state.world.regiment_get_org(def_front[i]);
5776 org = std::max(0.0f, org - org_damage);
5777 switch(state.military_definitions.unit_base_definitions[state.world.regiment_get_type(def_front[i])].type) {
5778 case unit_type::infantry:
5779 state.world.land_battle_get_defender_infantry_lost(b) += str_damage;
5781 case unit_type::cavalry:
5782 state.world.land_battle_get_defender_cav_lost(b) += str_damage;
5784 case unit_type::support:
5786 case unit_type::special:
5787 state.world.land_battle_get_defender_support_lost(b) += str_damage;
5795 if(def_back[i] && att_front[i]) {
5796 assert(state.world.regiment_is_valid(def_back[i]) && state.world.regiment_is_valid(att_front[i]));
5798 auto tech_def_nation = tech_nation_for_regiment(state, def_back[i]);
5799 auto tech_att_nation = tech_nation_for_regiment(state, att_front[i]);
5801 auto& def_stats = state.world.nation_get_unit_stats(tech_def_nation, state.world.regiment_get_type(def_back[i]));
5802 auto& att_stats = state.world.nation_get_unit_stats(tech_att_nation, state.world.regiment_get_type(att_front[i]));
5804 auto& atk_exp = state.world.regiment_get_experience(att_front[i]);
5806 auto def_str = state.world.regiment_get_strength(def_back[i]);
5808 auto str_damage = def_str * str_dam_mul * (def_stats.attack_or_gun_power * 0.1f + 1.0f) * def_stats.support * defender_mod / ((state.defines.base_military_tactics + state.world.nation_get_modifier_values(tech_att_nation, sys::national_mod_offsets::military_tactics)) * (1.f + atk_exp));
5809 auto org_damage = def_str * org_dam_mul * (def_stats.attack_or_gun_power * 0.1f + 1.0f) * def_stats.support * defender_mod / (attacker_org_bonus * def_stats.discipline_or_evasion * (1.0f + state.world.nation_get_modifier_values(tech_att_nation, sys::national_mod_offsets::land_organisation)) * (1.f + atk_exp));
5811 auto& cstr = state.world.regiment_get_strength(att_front[i]);
5812 str_damage = std::min(str_damage, cstr);
5813 state.world.regiment_get_pending_damage(att_front[i]) += str_damage;
5815 attacker_casualties += str_damage;
5817 adjust_regiment_experience(state, defending_nation, def_back[i], str_damage * 5.f * state.defines.exp_gain_div * def_leader_exp_mod);
5819 auto& org = state.world.regiment_get_org(att_front[i]);
5820 org = std::max(0.0f, org - org_damage);
5821 switch(state.military_definitions.unit_base_definitions[state.world.regiment_get_type(att_front[i])].type) {
5822 case unit_type::infantry:
5823 state.world.land_battle_get_attacker_infantry_lost(b) += str_damage;
5825 case unit_type::cavalry:
5826 state.world.land_battle_get_attacker_cav_lost(b) += str_damage;
5828 case unit_type::support:
5830 case unit_type::special:
5831 state.world.land_battle_get_attacker_support_lost(b) += str_damage;
5840 assert(state.world.regiment_is_valid(att_front[i]));
5842 auto tech_att_nation = tech_nation_for_regiment(state, att_front[i]);
5843 auto& att_stats = state.world.nation_get_unit_stats(tech_att_nation, state.world.regiment_get_type(att_front[i]));
5845 auto att_front_target = def_front[i];
5846 if(
auto mv = state.military_definitions.unit_base_definitions[state.world.regiment_get_type(att_front[i])].maneuver; !att_front_target && mv > 0.0f) {
5847 for(int32_t cnt = 1; i - cnt * 2 >= 0 && cnt <= int32_t(mv); ++cnt) {
5848 if(def_front[i - cnt * 2]) {
5849 att_front_target = def_front[i - cnt * 2];
5855 if(att_front_target) {
5856 assert(state.world.regiment_is_valid(att_front_target));
5858 auto tech_def_nation = tech_nation_for_regiment(state, att_front_target);
5859 auto& def_stats = state.world.nation_get_unit_stats(tech_def_nation, state.world.regiment_get_type(att_front_target));
5861 auto& def_exp = state.world.regiment_get_experience(att_front_target);
5863 auto att_str = state.world.regiment_get_strength(att_front[i]);
5865 auto str_damage = att_str * str_dam_mul *
5866 (att_stats.attack_or_gun_power * 0.1f + 1.0f) * attacker_mod /
5867 (defender_fort * (state.defines.base_military_tactics + state.world.nation_get_modifier_values(tech_def_nation, sys::national_mod_offsets::military_tactics))
5869 auto org_damage = att_str * org_dam_mul *
5870 (att_stats.attack_or_gun_power * 0.1f + 1.0f) * attacker_mod /
5871 (defender_fort * def_stats.discipline_or_evasion * defender_org_bonus * (1.0f + state.world.nation_get_modifier_values(tech_def_nation, sys::national_mod_offsets::land_organisation))
5874 auto& cstr = state.world.regiment_get_strength(att_front_target);
5875 str_damage = std::min(str_damage, cstr);
5876 state.world.regiment_get_pending_damage(att_front_target) += str_damage;
5878 defender_casualties += str_damage;
5880 adjust_regiment_experience(state, attacking_nation, att_front[i], str_damage * 5.f * state.defines.exp_gain_div * atk_leader_exp_mod);
5882 auto& org = state.world.regiment_get_org(att_front_target);
5883 org = std::max(0.0f, org - org_damage);
5884 switch(state.military_definitions.unit_base_definitions[state.world.regiment_get_type(att_front_target)].type) {
5885 case unit_type::infantry:
5886 state.world.land_battle_get_defender_infantry_lost(b) += str_damage;
5888 case unit_type::cavalry:
5889 state.world.land_battle_get_defender_cav_lost(b) += str_damage;
5891 case unit_type::support:
5893 case unit_type::special:
5894 state.world.land_battle_get_defender_support_lost(b) += str_damage;
5904 assert(state.world.regiment_is_valid(def_front[i]));
5906 auto tech_def_nation = tech_nation_for_regiment(state, def_front[i]);
5907 auto& def_stats = state.world.nation_get_unit_stats(tech_def_nation, state.world.regiment_get_type(def_front[i]));
5909 auto def_front_target = att_front[i];
5911 if(
auto mv = state.military_definitions.unit_base_definitions[state.world.regiment_get_type(def_front[i])].maneuver; !def_front_target && mv > 0.0f) {
5912 for(int32_t cnt = 1; i - cnt * 2 >= 0 && cnt <= int32_t(mv); ++cnt) {
5913 if(att_front[i - cnt * 2]) {
5914 def_front_target = att_front[i - cnt * 2];
5920 if(def_front_target) {
5921 assert(state.world.regiment_is_valid(def_front_target));
5923 auto tech_att_nation = tech_nation_for_regiment(state, def_front_target);
5924 auto& att_stats = state.world.nation_get_unit_stats(tech_att_nation, state.world.regiment_get_type(def_front_target));
5926 auto& atk_exp = state.world.regiment_get_experience(def_front_target);
5928 auto def_str = state.world.regiment_get_strength(def_front[i]);
5930 auto str_damage = def_str * str_dam_mul * (def_stats.attack_or_gun_power * 0.1f + 1.0f) * defender_mod / ((state.defines.base_military_tactics + state.world.nation_get_modifier_values(tech_att_nation, sys::national_mod_offsets::military_tactics))
5932 auto org_damage = def_str * org_dam_mul * (def_stats.attack_or_gun_power * 0.1f + 1.0f) * defender_mod / (attacker_org_bonus * def_stats.discipline_or_evasion * (1.0f + state.world.nation_get_modifier_values(tech_att_nation, sys::national_mod_offsets::land_organisation))
5935 auto& cstr = state.world.regiment_get_strength(def_front_target);
5936 str_damage = std::min(str_damage, cstr);
5937 state.world.regiment_get_pending_damage(def_front_target) += str_damage;
5939 attacker_casualties += str_damage;
5941 adjust_regiment_experience(state, defending_nation, def_front[i], str_damage * 5.f * state.defines.exp_gain_div * def_leader_exp_mod);
5943 auto& org = state.world.regiment_get_org(def_front_target);
5944 org = std::max(0.0f, org - org_damage);
5945 switch(state.military_definitions.unit_base_definitions[state.world.regiment_get_type(def_front_target)].type) {
5946 case unit_type::infantry:
5947 state.world.land_battle_get_attacker_infantry_lost(b) += str_damage;
5949 case unit_type::cavalry:
5950 state.world.land_battle_get_attacker_cav_lost(b) += str_damage;
5952 case unit_type::support:
5954 case unit_type::special:
5955 state.world.land_battle_get_attacker_support_lost(b) += str_damage;
5964 state.world.land_battle_set_attacker_casualties(b, attacker_casualties);
5965 state.world.land_battle_set_defender_casualties(b, defender_casualties);
5970 for(int32_t i = 0; i < combat_width; ++i) {
5972 if(state.world.regiment_get_strength(def_back[i]) <= 0.0f) {
5973 def_back[i] = dcon::regiment_id{};
5974 }
else if(state.world.regiment_get_org(def_back[i]) < 0.1f) {
5975 def_back[i] = dcon::regiment_id{};
5979 if(state.world.regiment_get_strength(def_front[i]) <= 0.0f) {
5980 def_front[i] = dcon::regiment_id{};
5981 }
else if(state.world.regiment_get_org(def_front[i]) < 0.1f) {
5982 def_front[i] = dcon::regiment_id{};
5986 if(state.world.regiment_get_strength(att_back[i]) <= 0.0f) {
5987 att_back[i] = dcon::regiment_id{};
5988 }
else if(state.world.regiment_get_org(att_back[i]) < 0.1f) {
5989 att_back[i] = dcon::regiment_id{};
5993 if(state.world.regiment_get_strength(att_front[i]) <= 0.0f) {
5994 att_front[i] = dcon::regiment_id{};
5995 }
else if(state.world.regiment_get_org(att_front[i]) < 0.1f) {
5996 att_front[i] = dcon::regiment_id{};
6002 auto compact = [](std::array<dcon::regiment_id, 30>& a) {
6004 while(low < 30 && a[low]) {
6007 int32_t high = low + 2;
6008 while(high < 30 && !a[high])
6013 a[high] = dcon::regiment_id{};
6016 while(high < 30 && !a[high])
6023 while(low < 30 && a[low]) {
6027 while(high < 30 && !a[high])
6032 a[high] = dcon::regiment_id{};
6035 while(high < 30 && !a[high])
6061 for(int32_t i = 0; i < combat_width; ++i) {
6063 for(
uint32_t j = reserves.size(); j-- > 0;) {
6064 if(reserves[j].flags == (reserve_regiment::is_attacking | reserve_regiment::type_support)) {
6065 att_back[i] = reserves[j].regiment;
6066 std::swap(reserves[j], reserves[reserves.size() - 1]);
6067 reserves.pop_back();
6074 for(
uint32_t j = reserves.size(); j-- > 0;) {
6075 if(reserves[j].flags == (reserve_regiment::type_support)) {
6076 def_back[i] = reserves[j].regiment;
6077 std::swap(reserves[j], reserves[reserves.size() - 1]);
6078 reserves.pop_back();
6087 for(int32_t i = 0; i < combat_width; ++i) {
6090 for(
uint32_t j = reserves.size(); j-- > 0;) {
6091 if(reserves[j].flags == (reserve_regiment::is_attacking | reserve_regiment::type_infantry)) {
6092 att_front[i] = reserves[j].regiment;
6093 std::swap(reserves[j], reserves[reserves.size() - 1]);
6094 reserves.pop_back();
6100 for(
uint32_t j = reserves.size(); j-- > 0;) {
6101 if(reserves[j].flags == (reserve_regiment::is_attacking | reserve_regiment::type_cavalry)) {
6102 att_front[i] = reserves[j].regiment;
6103 std::swap(reserves[j], reserves[reserves.size() - 1]);
6104 reserves.pop_back();
6109 if(!att_front[i] && att_back[i]) {
6115 for(
uint32_t j = reserves.size(); j-- > 0;) {
6116 if(reserves[j].flags == (reserve_regiment::type_infantry)) {
6117 def_front[i] = reserves[j].regiment;
6118 std::swap(reserves[j], reserves[reserves.size() - 1]);
6119 reserves.pop_back();
6125 for(
uint32_t j = reserves.size(); j-- > 0;) {
6126 if(reserves[j].flags == (reserve_regiment::type_cavalry)) {
6127 def_front[i] = reserves[j].regiment;
6128 std::swap(reserves[j], reserves[reserves.size() - 1]);
6129 reserves.pop_back();
6134 if(!def_front[i] && def_back[i]) {
6143 }
else if(!att_front[0]) {
6149 for(
auto i = isize; i-- > 0;) {
6150 dcon::land_battle_id b{dcon::land_battle_id::value_base_t(i) };
6151 if(
state.world.land_battle_is_valid(b) && to_delete.get(b) != 0) {
6152 end_battle(state, b, to_delete.get(b) ==
uint8_t(1) ? battle_result::attacker_won : battle_result::defender_won);
6157void update_naval_battles(
sys::state& state) {
6158 auto isize = state.world.naval_battle_size();
6159 auto to_delete = ve::vectorizable_buffer<uint8_t, dcon::naval_battle_id>(isize);
6161 concurrency::parallel_for(0, int32_t(isize), [&](int32_t index) {
6162 dcon::naval_battle_id b{dcon::naval_battle_id::value_base_t(index)};
6164 if(!state.world.naval_battle_is_valid(b))
6167 int32_t attacker_ships = 0;
6168 int32_t defender_ships = 0;
6170 auto slots = state.world.naval_battle_get_slots(b);
6172 for(
uint32_t j = slots.size(); j-- > 0;) {
6173 switch(slots[j].flags & ship_in_battle::mode_mask) {
6174 case ship_in_battle::mode_seeking:
6175 case ship_in_battle::mode_approaching:
6176 case ship_in_battle::mode_retreating:
6177 case ship_in_battle::mode_engaged:
6178 if((slots[j].flags & ship_in_battle::is_attacking) != 0)
6188 if(defender_ships == 0) {
6191 }
else if(attacker_ships == 0) {
6196 if((state.current_date.value - state.world.naval_battle_get_start_date(b).value) % 5 == 4) {
6197 state.world.naval_battle_set_dice_rolls(b, make_dice_rolls(state,
uint32_t(index)));
6200 auto both_dice = state.world.naval_battle_get_dice_rolls(b);
6201 auto attacker_dice = both_dice & 0x0F;
6202 auto defender_dice = (both_dice >> 4) & 0x0F;
6204 auto attacker_per = state.world.leader_get_personality(state.world.naval_battle_get_admiral_from_attacking_admiral(b));
6205 auto attacker_bg = state.world.leader_get_background(state.world.naval_battle_get_admiral_from_attacking_admiral(b));
6208 int32_t(state.world.leader_trait_get_attack(attacker_per) + state.world.leader_trait_get_attack(attacker_bg));
6209 auto attacker_org_bonus =
6210 1.0f + state.world.leader_trait_get_organisation(attacker_per) + state.world.leader_trait_get_organisation(attacker_bg);
6212 auto defender_per = state.world.leader_get_personality(state.world.naval_battle_get_admiral_from_defending_admiral(b));
6213 auto defender_bg = state.world.leader_get_background(state.world.naval_battle_get_admiral_from_defending_admiral(b));
6215 auto atk_leader_exp_mod = 1 + attacker_per.get_experience() + attacker_bg.get_experience();
6216 auto def_leader_exp_mod = 1 + defender_per.get_experience() + defender_per.get_experience();
6218 auto defence_bonus =
6219 int32_t(state.world.leader_trait_get_defense(defender_per) + state.world.leader_trait_get_defense(defender_bg));
6220 auto defender_org_bonus =
6221 1.0f + state.world.leader_trait_get_organisation(defender_per) + state.world.leader_trait_get_organisation(defender_bg);
6223 auto attacker_mod = combat_modifier_table[std::clamp(attacker_dice + attack_bonus + 3, 0, 18)];
6224 auto defender_mod = combat_modifier_table[std::clamp(defender_dice + defence_bonus + 3, 0, 18)];
6226 for(
uint32_t j = slots.size(); j-- > 0;) {
6228 state.world.navy_get_controller_from_navy_control(state.world.ship_get_navy_from_navy_membership(slots[j].ship));
6229 auto ship_type = state.world.ship_get_type(slots[j].ship);
6231 assert((slots[j].flags & ship_in_battle::mode_mask) == ship_in_battle::mode_sunk || (slots[j].flags & ship_in_battle::mode_mask) == ship_in_battle::mode_retreated || ship_type);
6233 auto& ship_stats = state.world.nation_get_unit_stats(ship_owner, ship_type);
6235 auto aship = slots[j].ship;
6237 state.world.navy_get_controller_from_navy_control(state.world.ship_get_navy_from_navy_membership(aship));
6239 switch(slots[j].flags & ship_in_battle::mode_mask) {
6240 case ship_in_battle::mode_approaching: {
6241 auto target_mode = slots[slots[j].target_slot].flags & ship_in_battle::mode_mask;
6242 if(target_mode == ship_in_battle::mode_retreated || target_mode == ship_in_battle::mode_sunk) {
6243 slots[j].flags &= ~ship_in_battle::mode_mask;
6244 slots[j].flags |= ship_in_battle::mode_seeking;
6255 float speed = ship_stats.maximum_speed * 1000.0f * state.defines.naval_combat_speed_to_distance_factor *
6257 auto old_distance = slots[j].flags & ship_in_battle::distance_mask;
6258 int32_t adjust = std::clamp(int32_t(std::ceil(speed)), 0, old_distance);
6259 slots[j].flags &= ~ship_in_battle::distance_mask;
6260 slots[j].flags |= ship_in_battle::distance_mask & (old_distance - adjust);
6262 if(old_distance == adjust ||
6263 (old_distance - adjust) + (slots[slots[j].target_slot].flags & ship_in_battle::distance_mask) <
6264 int32_t(1000.0f * ship_stats.reconnaissance_or_fire_range)) {
6266 slots[j].flags &= ~ship_in_battle::mode_mask;
6267 slots[j].flags |= ship_in_battle::mode_engaged;
6272 case ship_in_battle::mode_engaged: {
6273 auto target_mode = slots[slots[j].target_slot].flags & ship_in_battle::mode_mask;
6274 if(target_mode == ship_in_battle::mode_retreated || target_mode == ship_in_battle::mode_sunk) {
6275 slots[j].flags &= ~ship_in_battle::mode_mask;
6276 slots[j].flags |= ship_in_battle::mode_seeking;
6279 bool target_is_big = (slots[slots[j].target_slot].flags & ship_in_battle::type_mask) == ship_in_battle::type_big;
6280 bool is_attacker = (slots[j].flags & ship_in_battle::is_attacking) != 0;
6281 auto tship = slots[slots[j].target_slot].ship;
6284 auto ship_target_owner =
6285 state.world.navy_get_controller_from_navy_control(state.world.ship_get_navy_from_navy_membership(tship));
6286 auto ttype = state.world.ship_get_type(tship);
6288 auto& ship_target_stats = state.world.nation_get_unit_stats(ship_target_owner, ttype);
6298 auto& targ_ship_exp = state.world.ship_get_experience(tship);
6300 float org_damage = org_dam_mul * (ship_stats.attack_or_gun_power + (target_is_big ? ship_stats.siege_or_torpedo_attack : 0.0f)) *
6301 (is_attacker ? attacker_mod : defender_mod) * state.defines.naval_combat_damage_org_mult /
6302 ((ship_target_stats.defence_or_hull + 1.0f) * (is_attacker ? defender_org_bonus : attacker_org_bonus) *
6303 (1.0f + state.world.nation_get_modifier_values(ship_target_owner,
6304 sys::national_mod_offsets::naval_organisation))
6305 * (1 + targ_ship_exp));
6306 float str_damage = str_dam_mul * (ship_stats.attack_or_gun_power + (target_is_big ? ship_stats.siege_or_torpedo_attack : 0.0f)) *
6307 (is_attacker ? attacker_mod : defender_mod) * state.defines.naval_combat_damage_str_mult /
6308 ((ship_target_stats.defence_or_hull + 1.0f) * (1 + targ_ship_exp));
6310 auto& torg = state.world.ship_get_org(tship);
6311 torg = std::max(0.0f, torg - org_damage);
6312 auto& tstr = state.world.ship_get_strength(tship);
6313 tstr = std::max(0.0f, tstr - str_damage);
6315 auto leader_exp_mod = (is_attacker ? atk_leader_exp_mod : def_leader_exp_mod);
6316 adjust_ship_experience(state, aship_owner, aship, str_damage * 5.f * state.defines.exp_gain_div * leader_exp_mod);
6320 case ship_in_battle::mode_retreating: {
6326 float speed = ship_stats.maximum_speed * 1000.0f * state.defines.naval_combat_retreat_speed_mod *
6327 state.defines.naval_combat_speed_to_distance_factor *
6330 auto old_distance = slots[j].flags & ship_in_battle::distance_mask;
6331 int32_t new_distance = std::min(int32_t(std::ceil(speed)) + old_distance, 1000);
6332 slots[j].flags &= ~ship_in_battle::distance_mask;
6333 slots[j].flags |= ship_in_battle::distance_mask & (new_distance);
6337 case ship_in_battle::mode_seeking: {
6344 if((slots[j].flags & ship_in_battle::is_attacking) != 0) {
6348 for(
uint32_t k = slots.size(); k-- > 0;) {
6349 switch(slots[k].flags & ship_in_battle::mode_mask) {
6351 case ship_in_battle::mode_seeking:
6352 case ship_in_battle::mode_approaching:
6353 case ship_in_battle::mode_retreating:
6354 case ship_in_battle::mode_engaged:
6355 if((slots[k].flags & ship_in_battle::is_attacking) == 0) {
6357 slots[j].target_slot = uint16_t(k);
6370 auto old_distance = slots[j].flags & ship_in_battle::distance_mask;
6371 int32_t new_distance = std::min(old_distance + 400, 1000);
6373 slots[j].flags &= ~ship_in_battle::mode_mask;
6374 slots[j].flags |= ship_in_battle::mode_approaching;
6375 slots[j].flags &= ~ship_in_battle::distance_mask;
6376 slots[j].flags |= ship_in_battle::distance_mask & new_distance;
6381 for(
uint32_t k = slots.size(); k-- > 0;) {
6382 switch(slots[k].flags & ship_in_battle::mode_mask) {
6384 case ship_in_battle::mode_seeking:
6385 case ship_in_battle::mode_approaching:
6386 case ship_in_battle::mode_retreating:
6387 case ship_in_battle::mode_engaged:
6388 if((slots[k].flags & ship_in_battle::is_attacking) != 0) {
6390 slots[j].target_slot = uint16_t(k);
6403 auto old_distance = slots[j].flags & ship_in_battle::distance_mask;
6404 int32_t new_distance = std::min(old_distance + 400, 1000);
6406 slots[j].flags &= ~ship_in_battle::mode_mask;
6407 slots[j].flags |= ship_in_battle::mode_approaching;
6408 slots[j].flags &= ~ship_in_battle::distance_mask;
6409 slots[j].flags |= ship_in_battle::distance_mask & new_distance;
6419 for(
uint32_t j = slots.size(); j-- > 0;) {
6421 state.world.navy_get_controller_from_navy_control(state.world.ship_get_navy_from_navy_membership(slots[j].ship));
6422 auto type = state.world.ship_get_type(slots[j].ship);
6424 switch(slots[j].flags & ship_in_battle::mode_mask) {
6425 case ship_in_battle::mode_seeking:
6426 case ship_in_battle::mode_approaching:
6427 case ship_in_battle::mode_engaged:
6428 if(state.world.ship_get_strength(slots[j].ship) <= 0) {
6429 if((slots[j].flags & ship_in_battle::is_attacking) != 0) {
6430 if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_big) {
6431 state.world.naval_battle_get_attacker_big_ships_lost(b)++;
6432 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_small) {
6433 state.world.naval_battle_get_attacker_small_ships_lost(b)++;
6434 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_transport) {
6435 state.world.naval_battle_get_attacker_transport_ships_lost(b)++;
6437 state.world.naval_battle_get_attacker_loss_value(b) += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
6439 if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_big) {
6440 state.world.naval_battle_get_defender_big_ships_lost(b)++;
6441 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_small) {
6442 state.world.naval_battle_get_defender_small_ships_lost(b)++;
6443 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_transport) {
6444 state.world.naval_battle_get_defender_transport_ships_lost(b)++;
6446 state.world.naval_battle_get_defender_loss_value(b) += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
6448 slots[j].flags &= ~ship_in_battle::mode_mask;
6449 slots[j].flags |= ship_in_battle::mode_sunk;
6452 if(state.world.ship_get_strength(slots[j].ship) <= state.defines.naval_combat_retreat_str_org_level ||
6453 state.world.ship_get_org(slots[j].ship) <= state.defines.naval_combat_retreat_str_org_level) {
6455 slots[j].flags &= ~ship_in_battle::mode_mask;
6456 slots[j].flags |= ship_in_battle::mode_retreating;
6459 case ship_in_battle::mode_retreating:
6460 if(state.world.ship_get_strength(slots[j].ship) <= 0) {
6461 if((slots[j].flags & ship_in_battle::is_attacking) != 0) {
6462 if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_big) {
6463 state.world.naval_battle_get_attacker_big_ships_lost(b)++;
6464 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_small) {
6465 state.world.naval_battle_get_attacker_small_ships_lost(b)++;
6466 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_transport) {
6467 state.world.naval_battle_get_attacker_transport_ships_lost(b)++;
6470 if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_big) {
6471 state.world.naval_battle_get_defender_big_ships_lost(b)++;
6472 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_small) {
6473 state.world.naval_battle_get_defender_small_ships_lost(b)++;
6474 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_transport) {
6475 state.world.naval_battle_get_defender_transport_ships_lost(b)++;
6478 slots[j].flags &= ~ship_in_battle::mode_mask;
6479 slots[j].flags |= ship_in_battle::mode_sunk;
6482 if((slots[j].flags & ship_in_battle::distance_mask) >= 1000) {
6483 slots[j].flags &= ~ship_in_battle::mode_mask;
6484 slots[j].flags |= ship_in_battle::mode_retreated;
6493 for(
auto i = isize; i-- > 0;) {
6494 dcon::naval_battle_id b{ dcon::naval_battle_id::value_base_t(i) };
6495 if(
state.world.naval_battle_is_valid(b) && to_delete.get(b) != 0) {
6496 end_battle(state, b, to_delete.get(b) ==
uint8_t(1) ? battle_result::attacker_won : battle_result::defender_won);
6501 dcon::ship_id s{dcon::ship_id::value_base_t(i)};
6502 if(
state.world.ship_is_valid(s)) {
6503 if(
state.world.ship_get_strength(s) <= 0.0f) {
6504 state.world.delete_ship(s);
6512 auto low_roll = rvals.low % 10;
6513 auto high_roll = rvals.high % 10;
6514 return uint8_t((high_roll << 4) | low_roll);
6517void navy_arrives_in_province(
sys::state& state, dcon::navy_id n, dcon::province_id p, dcon::naval_battle_id from) {
6518 assert(state.world.navy_is_valid(n));
6519 assert(!state.world.navy_get_battle_from_navy_battle_participation(n));
6521 state.world.navy_set_location_from_navy_location(n, p);
6522 auto ships = state.world.navy_get_navy_membership(n);
6523 if(!state.world.navy_get_is_retreating(n) && p.index() >= state.province_definitions.first_sea_province.index() && ships.begin() != ships.end()) {
6524 auto owner_nation = state.world.navy_get_controller_from_navy_control(n);
6527 for(
auto b : state.world.province_get_naval_battle_location(p)) {
6528 if(b.get_battle() != from) {
6529 auto battle_war = b.get_battle().get_war_from_naval_battle_in_war();
6530 auto owner_role = get_role(state, battle_war, owner_nation);
6531 if(owner_role != war_role::none) {
6532 add_navy_to_battle(state, n, b.get_battle(), owner_role);
6539 dcon::naval_battle_id gather_to_battle;
6540 dcon::war_id battle_in_war;
6542 for(
auto o : state.world.province_get_navy_location(p)) {
6543 if(o.get_navy() == n)
6545 if(o.get_navy().get_is_retreating() || o.get_navy().get_battle_from_navy_battle_participation())
6548 auto other_nation = o.get_navy().get_controller_from_navy_control();
6550 if(
auto par = internal_find_war_between(state, owner_nation, other_nation); par.
role != war_role::none) {
6551 auto new_battle = fatten(state.world, state.world.create_naval_battle());
6552 new_battle.set_war_attacker_is_attacker(par.role == war_role::attacker);
6553 new_battle.set_start_date(state.current_date);
6554 new_battle.set_war_from_naval_battle_in_war(par.w);
6555 new_battle.set_location_from_naval_battle_location(p);
6556 new_battle.set_dice_rolls(make_dice_rolls(state,
uint32_t(new_battle.id.value)));
6558 add_navy_to_battle(state, n, new_battle, par.role);
6559 add_navy_to_battle(state, o.get_navy(), new_battle,
6560 par.role == war_role::attacker ? war_role::defender : war_role::attacker);
6562 gather_to_battle = new_battle.id;
6563 battle_in_war = par.w;
6568 if(gather_to_battle) {
6569 for(
auto o : state.world.province_get_navy_location(p)) {
6570 if(o.get_navy() == n)
6572 if(o.get_navy().get_is_retreating() || o.get_navy().get_battle_from_navy_battle_participation())
6575 auto other_nation = o.get_navy().get_controller_from_navy_control();
6577 if(
auto role = get_role(state, battle_in_war, other_nation); role != war_role::none) {
6578 add_navy_to_battle(state, o.get_navy(), gather_to_battle, role);
6588 for(
auto a : state.world.in_army) {
6589 auto arrival = a.get_arrival_time();
6590 assert(!arrival || arrival >= state.current_date);
6591 if(
auto path = a.get_path(); arrival == state.current_date) {
6593 auto dest = path.at(path.size() - 1);
6595 auto from = state.world.army_get_location_from_army_location(a);
6597 if(dest.index() >= state.province_definitions.first_sea_province.index()) {
6599 auto to_navy = find_embark_target(state, a.get_controller_from_army_control(), dest, a);
6601 a.set_location_from_army_location(dest);
6602 a.set_navy_from_army_transport(to_navy);
6603 a.set_black_flag(
false);
6608 if(a.get_black_flag()) {
6609 auto n = state.world.province_get_nation_from_province_ownership(dest);
6612 if(n == a.get_controller_from_army_control().id) {
6613 a.set_black_flag(
false);
6615 army_arrives_in_province(state, a, dest,
6616 (state.world.province_adjacency_get_type(state.world.get_province_adjacency_by_province_pair(dest, from)) &
6620 a.set_navy_from_army_transport(dcon::navy_id{});
6622 if(
auto n = a.get_navy_from_army_transport()) {
6623 if(!n.get_battle_from_navy_battle_participation()) {
6625 a.set_navy_from_army_transport(dcon::navy_id{});
6630 auto path_bits = state.world.province_adjacency_get_type(state.world.get_province_adjacency_by_province_pair(dest, from));
6632 auto port = state.world.province_get_port_to(from);
6633 bool hostile_in_port =
false;
6634 auto controller = a.get_controller_from_army_control();
6635 for(
auto v : state.world.province_get_navy_location(port)) {
6637 hostile_in_port =
true;
6641 if(!hostile_in_port) {
6647 army_arrives_in_province(state, a, dest,
6658 if(a.get_battle_from_army_battle_participation()) {
6660 }
else if(path.size() > 0) {
6661 auto next_dest = path.at(path.size() - 1);
6662 a.set_arrival_time(arrival_time_to(state, a, next_dest));
6665 if(a.get_is_retreating()) {
6666 a.set_is_retreating(
false);
6667 army_arrives_in_province(state, a, dest,
6668 (state.world.province_adjacency_get_type(state.world.get_province_adjacency_by_province_pair(dest, from)) &
6673 if(a.get_moving_to_merge()) {
6674 a.set_moving_to_merge(
false);
6676 for(
auto ar : state.world.province_get_army_location(dest)) {
6677 if(ar.get_army().get_controller_from_army_control() == a.get_controller_from_army_control() && ar.get_army() != a && !ar.get_army().get_moving_to_merge()) {
6678 auto regs = state.world.army_get_army_membership(a);
6679 while(regs.begin() != regs.end()) {
6680 (*regs.begin()).set_army(ar.get_army());
6687 if(state.world.army_get_is_rebel_hunter(a)
6688 && state.world.province_get_nation_from_province_control(dest)
6689 && state.world.nation_get_is_player_controlled(state.world.army_get_controller_from_army_control(a))
6690 && !state.world.army_get_battle_from_army_battle_participation(a)
6691 && !state.world.army_get_navy_from_army_transport(a)) {
6699 for(
auto n :
state.world.in_navy) {
6700 auto arrival =
n.get_arrival_time();
6701 assert(!arrival || arrival >=
state.current_date);
6702 if(
auto path =
n.get_path(); arrival ==
state.current_date) {
6704 auto dest = path.at(path.size() - 1);
6707 if(
dest.index() <
state.province_definitions.first_sea_province.index()) {
6710 n.set_location_from_navy_location(dest);
6713 auto attached =
state.world.navy_get_army_transport(n);
6714 while(attached.begin() != attached.end()) {
6715 auto a = (*attached.begin()).get_army();
6717 a.set_navy_from_army_transport(dcon::navy_id{});
6718 a.get_path().clear();
6720 auto acontroller = a.get_controller_from_army_control();
6722 if(acontroller && !acontroller.get_is_player_controlled()) {
6723 auto army_dest = a.get_ai_province();
6724 a.set_location_from_army_location(dest);
6725 if(army_dest && army_dest != dest) {
6727 if(apath.size() > 0) {
6728 auto existing_path = a.get_path();
6729 auto new_size =
uint32_t(apath.size());
6730 existing_path.resize(new_size);
6732 for(
uint32_t i = 0; i < new_size; ++i) {
6733 existing_path[i] = apath[i];
6760 for(
auto a :
state.world.navy_get_army_transport(n)) {
6761 a.get_army().set_location_from_army_location(dest);
6762 a.get_army().get_path().clear();
6763 a.get_army().set_arrival_time(
sys::date{});
6767 if(
n.get_battle_from_navy_battle_participation()) {
6769 }
else if(path.size() > 0) {
6770 auto next_dest = path.at(path.size() - 1);
6774 if(
n.get_is_retreating()) {
6775 if(
dest.index() >=
state.province_definitions.first_sea_province.index())
6777 n.set_is_retreating(
false);
6779 if(
n.get_moving_to_merge()) {
6780 n.set_moving_to_merge(
false);
6782 for(
auto ar :
state.world.province_get_navy_location(dest)) {
6783 if(ar.get_navy().get_controller_from_navy_control() ==
n.get_controller_from_navy_control() && ar.get_navy() !=
n && !ar.get_navy().get_moving_to_merge()) {
6784 auto regs =
state.world.navy_get_navy_membership(n);
6785 while(regs.begin() != regs.end()) {
6786 (*regs.begin()).set_navy(ar.get_navy());
6788 auto a =
state.world.navy_get_army_transport(n);
6789 while(a.begin() != a.end()) {
6790 (*a.begin()).set_navy(ar.get_navy());
6802float fractional_distance_covered(
sys::state& state, dcon::army_id a) {
6803 auto date = state.world.army_get_arrival_time(a);
6806 auto p = state.world.army_get_path(a);
6809 if(state.world.army_get_battle_from_army_battle_participation(a))
6812 auto dest = *(p.end() - 1);
6813 auto full_time = arrival_time_to(state, a, dest);
6815 auto difference = full_time.value - state.current_date.value;
6816 auto covered = date.value - state.current_date.value;
6821 return 1.0f - float(covered) / float(difference);
6823float fractional_distance_covered(
sys::state& state, dcon::navy_id a) {
6824 auto date = state.world.navy_get_arrival_time(a);
6827 auto p = state.world.navy_get_path(a);
6830 if(state.world.navy_get_battle_from_navy_battle_participation(a))
6833 auto dest = *(p.end() - 1);
6834 auto full_time = arrival_time_to(state, a, dest);
6836 auto difference = full_time.value - state.current_date.value;
6837 auto covered = date.value - state.current_date.value;
6842 return 1.0f - float(covered) / float(difference);
6845int32_t transport_capacity(
sys::state& state, dcon::navy_id n) {
6847 for(
auto s : state.world.navy_get_navy_membership(n)) {
6848 if(state.military_definitions.unit_base_definitions[s.get_ship().get_type()].type == unit_type::transport)
6853int32_t free_transport_capacity(
sys::state& state, dcon::navy_id n) {
6854 int32_t used_total = 0;
6855 for(
auto a : state.world.navy_get_army_transport(n)) {
6856 auto regs = a.get_army().get_army_membership();
6857 used_total += int32_t(regs.end() - regs.begin());
6865 auto a = fatten(state.world, ar);
6866 auto controller = a.get_controller_from_army_control();
6867 static std::vector<rebel::impl::prov_str> rebel_provs;
6868 rebel_provs.clear();
6872 for(
auto& next_prov : rebel_provs) {
6873 if(prov == next_prov.p)
6877 if(path.size() > 0) {
6878 auto existing_path = state.world.army_get_path(a);
6880 auto new_size =
uint32_t(path.size());
6881 existing_path.resize(new_size);
6883 for(
uint32_t i = new_size; i-- > 0; ) {
6884 existing_path.at(i) = path[i];
6888 state.world.army_set_dig_in(a, 0);
6893 if(!a.get_arrival_time()) {
6894 auto home = a.get_ai_province();
6899 if(path.size() > 0) {
6900 auto existing_path = state.world.army_get_path(a);
6902 auto new_size =
uint32_t(path.size());
6903 existing_path.resize(new_size);
6905 for(
uint32_t i = new_size; i-- > 0; ) {
6906 existing_path.at(i) = path[i];
6910 state.world.army_set_dig_in(a, 0);
6915bool siege_potential(
sys::state& state, dcon::nation_id army_controller, dcon::nation_id province_controller) {
6916 bool will_siege =
false;
6917 if(!army_controller) {
6918 will_siege = bool(province_controller);
6920 if(!province_controller) {
6922 }
else if(
are_at_war(state, province_controller, army_controller)) {
6930void update_siege_progress(
sys::state& state) {
6931 static auto new_nation_controller = ve::vectorizable_buffer<dcon::nation_id, dcon::province_id>(state.world.province_size());
6932 static auto new_rebel_controller = ve::vectorizable_buffer<dcon::rebel_faction_id, dcon::province_id>(state.world.province_size());
6934 new_nation_controller.set(ids, dcon::nation_id{});
6935 new_rebel_controller.set(ids, dcon::rebel_faction_id{});
6938 concurrency::parallel_for(0,
state.province_definitions.first_sea_province.index(), [&](int32_t
id) {
6939 dcon::province_id prov{dcon::province_id::value_base_t(id)};
6941 auto controller =
state.world.province_get_nation_from_province_control(prov);
6942 auto owner =
state.world.province_get_nation_from_province_ownership(prov);
6947 float max_siege_value = 0.0f;
6948 float strength_siege_units = 0.0f;
6949 float max_recon_value = 0.0f;
6950 float strength_recon_units = 0.0f;
6951 float total_sieging_strength = 0.0f;
6952 bool owner_involved =
false;
6953 bool core_owner_involved =
false;
6955 dcon::army_id first_army;
6957 for(
auto ar :
state.world.province_get_army_location(prov)) {
6960 if(ar.get_army().get_battle_from_army_battle_participation() || ar.get_army().get_black_flag() ||
6961 ar.get_army().get_navy_from_army_transport() || ar.get_army().get_arrival_time()) {
6965 auto army_controller = ar.get_army().get_controller_from_army_control();
6967 if(siege_potential(state, army_controller, controller)) {
6969 first_army = ar.get_army();
6971 auto army_stats = army_controller ? army_controller : ar.get_army().get_army_rebel_control().get_controller().get_ruler_from_rebellion_within();
6973 owner_involved = owner_involved || owner == army_controller;
6974 core_owner_involved =
6975 core_owner_involved || bool(state.world.get_core_by_prov_tag_key(prov, state.world.nation_get_identity_from_identity_holder(army_controller)));
6977 for(auto r : ar.get_army().get_army_membership()) {
6978 auto reg_str = r.get_regiment().get_strength();
6979 if(reg_str > 0.001f) {
6980 auto type = r.get_regiment().get_type();
6981 auto& stats = state.world.nation_get_unit_stats(army_stats, type);
6983 total_sieging_strength += reg_str;
6985 if(stats.siege_or_torpedo_attack > 0.0f) {
6986 strength_siege_units += reg_str;
6987 max_siege_value = std::max(max_siege_value, stats.siege_or_torpedo_attack);
6989 if(stats.reconnaissance_or_fire_range > 0.0f) {
6990 strength_recon_units += reg_str;
6991 max_recon_value = std::max(max_recon_value, stats.reconnaissance_or_fire_range);
6999 if(total_sieging_strength == 0.0f) {
7002 auto local_battles =
state.world.province_get_land_battle_location(prov);
7003 if(local_battles.begin() != local_battles.end()) {
7006 auto& progress = state.world.province_get_siege_progress(prov);
7007 progress = std::max(0.0f, progress - 0.1f);
7010 assert(
bool(first_army));
7019 int32_t effective_fort_level =
7021 int32_t(max_siege_value *
7022 std::min(strength_siege_units / total_sieging_strength,
state.defines.engineer_unit_ratio) /
7023 state.defines.engineer_unit_ratio),
7032 float siege_speed_modifier =
7033 1.0f +
state.defines.recon_siege_effect * max_recon_value *
7034 std::min(strength_recon_units / total_sieging_strength,
state.defines.recon_unit_ratio) /
7035 state.defines.recon_unit_ratio;
7044 float num_brigades =
7045 std::min(
state.defines.siege_brigades_max, total_sieging_strength * 1000.0f /
state.defines.pop_size_per_regiment);
7046 float num_brigades_modifier =
7047 num_brigades >
state.defines.siege_brigades_min
7048 ? 1.0f + (num_brigades -
state.defines.siege_brigades_min) *
state.defines.siege_brigades_bonus
7049 : num_brigades /
state.defines.siege_brigades_min;
7057 static constexpr float siege_table[] = {0.25f, 1.0f, 2.0f, 2.8f, 3.4f, 3.8f, 4.2f, 4.5f, 4.8f, 5.0f, 5.2f};
7058 static constexpr float progress_table[] = {0.0f, 0.2f, 0.5f, 0.75f, 0.75f, 1, 1.1f, 1.1f, 1.25f, 1.25f};
7060 float added_progress = siege_speed_modifier * num_brigades_modifier *
7062 (owner_involved ? 1.25f : (core_owner_involved ? 1.1f : 1.0f)) / siege_table[effective_fort_level];
7064 auto&
progress =
state.world.province_get_siege_progress(prov);
7067 if(progress >= 1.0f) {
7076 auto old_rf =
state.world.province_get_rebel_faction_from_province_rebel_control(prov);
7078 for(
auto pop :
state.world.province_get_pop_location(prov)) {
7086 state.world.province_set_former_controller(prov, controller);
7087 state.world.province_set_former_rebel_controller(prov, old_rf);
7089 auto new_controller =
state.world.army_get_controller_from_army_control(first_army);
7090 auto rebel_controller =
state.world.army_get_controller_from_army_rebel_control(first_army);
7092 if((!new_controller && !rebel_controller) || (new_controller && !
are_at_war(state, new_controller, owner))) {
7093 new_controller =
owner;
7096 new_nation_controller.set(prov, new_controller);
7097 new_rebel_controller.set(prov, rebel_controller);
7103 if(
auto nc = new_nation_controller.get(prov); nc) {
7104 province::set_province_controller(state, prov, nc);
7105 eject_ships(state, prov);
7107 auto cc = state.world.province_get_nation_from_province_control(prov);
7108 auto oc = state.world.province_get_former_controller(prov);
7111 notification::post(state, notification::message{
7113 crc = state.world.province_get_rebel_faction_from_province_rebel_control(prov),
7114 orc = state.world.province_get_former_rebel_controller(prov)](sys::state& state, text::layout_base& contents) {
7116 text::add_line(state, contents,
"msg_siegeover_1", text::variable_type::x, prov);
7118 text::add_line(state, contents,
"msg_siegeover_2", text::variable_type::x, oc);
7120 text::add_line(state, contents,
"msg_siegeover_3", text::variable_type::x, state.world.rebel_type_get_title(state.world.rebel_faction_get_type(orc)));
7122 text::add_line(state, contents,
"msg_siegeover_4", text::variable_type::x, cc);
7124 text::add_line(state, contents,
"msg_siegeover_5", text::variable_type::x, state.world.rebel_type_get_title(state.world.rebel_faction_get_type(crc)));
7126 "msg_siegeover_title",
7127 cc, oc, dcon::nation_id{},
7128 sys::message_base_type::siegeover
7132 for(
auto ar :
state.world.province_get_army_location(prov)) {
7133 auto a = ar.get_army();
7135 if(a.get_is_rebel_hunter()
7136 && a.get_controller_from_army_control().get_is_player_controlled()
7137 && !a.get_battle_from_army_battle_participation()
7138 && !a.get_navy_from_army_transport()
7139 && !a.get_arrival_time()) {
7141 send_rebel_hunter_to_next_province(state, a, prov);
7153 if(
auto nr = new_rebel_controller.get(prov); nr) {
7154 province::set_province_controller(state, prov, nr);
7155 eject_ships(state, prov);
7157 auto cc = state.world.province_get_nation_from_province_control(prov);
7158 auto oc = state.world.province_get_former_controller(prov);
7159 auto within = state.world.rebel_faction_get_ruler_from_rebellion_within(nr);
7160 auto t = state.world.rebel_faction_get_type(nr);
7161 if(trigger::evaluate(state, state.world.rebel_type_get_siege_won_trigger(t), trigger::to_generic(prov), trigger::to_generic(prov), trigger::to_generic(nr))) {
7162 effect::execute(state, state.world.rebel_type_get_siege_won_effect(t), trigger::to_generic(prov), trigger::to_generic(prov), trigger::to_generic(nr), uint32_t(state.current_date.value), uint32_t(within.index() ^ (nr.index() << 4)));
7168void update_blackflag_status(
sys::state& state, dcon::province_id p) {
7169 for(
auto ar : state.world.province_get_army_location(p)) {
7170 if(!ar.get_army().get_battle_from_army_battle_participation() && !ar.get_army().get_navy_from_army_transport()) {
7171 auto controller = ar.get_army().get_controller_from_army_control();
7177void eject_ships(
sys::state& state, dcon::province_id p) {
7178 auto sea_zone = state.world.province_get_port_to(p);
7183 static std::vector<dcon::navy_id> to_eject;
7186 for(
auto n : state.world.province_get_navy_location(p)) {
7188 to_eject.push_back(n.get_navy().id);
7191 for(
auto n : to_eject) {
7194 for(
auto a :
state.world.navy_get_army_transport(n)) {
7195 a.get_army().set_location_from_army_location(sea_zone);
7196 a.get_army().get_path().clear();
7197 a.get_army().set_arrival_time(
sys::date{});
7203 if(state.current_date.value % int32_t(state.defines.dig_in_increase_each_days) == 0) {
7204 for(
auto ar : state.world.in_army) {
7205 if(ar.get_is_retreating() || ar.get_black_flag() ||
bool(ar.get_battle_from_army_battle_participation()) ||
7206 bool(ar.get_navy_from_army_transport()) ||
bool(ar.get_arrival_time())) {
7210 auto& current_dig_in = ar.get_dig_in();
7212 int32_t(ar.get_controller_from_army_control().get_modifier_values(sys::national_mod_offsets::dig_in_cap))) {
7220 uint32_t total_commodities = state.world.commodity_size();
7224 commodities.commodity_amounts[i] = 0.0f;
7227 for(
auto r :
state.world.army_get_army_membership(army)) {
7229 auto type =
state.world.regiment_get_type(r.get_regiment());
7231 auto o_sc_mod = std::max(0.01f,
state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::supply_consumption) + 1.0f);
7232 auto& supply_cost =
state.military_definitions.unit_base_definitions[
type].supply_cost;
7234 if(supply_cost.commodity_type[i]) {
7235 commodities.commodity_amounts[i] += supply_cost.commodity_amounts[i] *
state.world.nation_get_unit_stats(owner, type).supply_consumption * o_sc_mod;
7236 commodities.commodity_type[i] = supply_cost.commodity_type[i];
7249 float supply_amount = .0f;
7250 int32_t amount_of_units = 0;
7254 commodities.commodity_amounts[i] = 0.0f;
7257 for(
auto sh :
state.world.navy_get_navy_membership(navy)) {
7259 auto type =
state.world.ship_get_type(sh.get_ship());
7262 auto o_sc_mod = std::max(0.01f,
state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::supply_consumption) + 1.0f);
7263 auto& supply_cost =
state.military_definitions.unit_base_definitions[
type].supply_cost;
7265 if(supply_cost.commodity_type[i]) {
7267 supply_cost.commodity_amounts[i] *
state.world.nation_get_unit_stats(owner, type).supply_consumption *
7269 commodities.commodity_type[i] = supply_cost.commodity_type[i];
7290 for(
auto ar : state.world.in_army) {
7291 if(ar.get_army_battle_participation().get_battle() || ar.get_navy_from_army_transport())
7294 auto in_nation = ar.get_controller_from_army_control();
7295 auto tech_nation = in_nation ? in_nation : ar.get_controller_from_army_rebel_control().get_ruler_from_rebellion_within();
7297 auto leader = ar.get_general_from_army_leadership();
7298 auto regen_mod = tech_nation.get_modifier_values(sys::national_mod_offsets::org_regain)
7299 + leader.get_personality().get_morale() + leader.get_background().get_morale() + 1.0f
7300 + leader.get_prestige() * state.defines.leader_prestige_to_max_org_factor;
7301 auto spending_level = (in_nation ? in_nation.get_effective_land_spending() : 1.0f);
7302 auto modified_regen = regen_mod * spending_level / 150.f;
7303 auto max_org = 0.25f + 0.75f * spending_level;
7304 for(
auto reg : ar.get_army_membership()) {
7305 auto c_org = reg.get_regiment().get_org();
7306 reg.get_regiment().set_org(std::min(c_org + modified_regen, max_org));
7310 for(
auto ar :
state.world.in_navy) {
7311 if(ar.get_navy_battle_participation().get_battle())
7314 auto in_nation = ar.get_controller_from_navy_control();
7316 auto leader = ar.get_admiral_from_navy_leadership();
7317 auto regen_mod = in_nation.get_modifier_values(sys::national_mod_offsets::org_regain)
7318 +
leader.get_personality().get_morale() +
leader.get_background().get_morale() + 1.0f
7319 +
leader.get_prestige() *
state.defines.leader_prestige_to_morale_factor;
7320 float oversize_amount =
7321 in_nation.get_naval_supply_points() > 0
7322 ? std::min(
float(in_nation.get_used_naval_supply_points()) /
float(in_nation.get_naval_supply_points()), 1.75f)
7324 float over_size_penalty = oversize_amount > 1.0f ? 2.0f - oversize_amount : 1.0f;
7325 auto spending_level = in_nation.get_effective_naval_spending() * over_size_penalty;
7326 auto modified_regen = regen_mod * spending_level / 150.0f;
7327 auto max_org = 0.25f + 0.75f * spending_level;
7328 for(
auto reg : ar.get_navy_membership()) {
7329 auto c_org = reg.get_ship().get_org();
7330 reg.get_ship().set_org(std::min(c_org + modified_regen, max_org));
7337 return state.world.regiment_get_strength(regiment_id);
7340float unit_get_strength(
sys::state& state, dcon::ship_id ship_id) {
7341 return state.world.ship_get_strength(ship_id);
7346 auto ar = fatten(state.world, a);
7347 if(ar.get_battle_from_army_battle_participation() || ar.get_navy_from_army_transport() || ar.get_is_retreating())
7350 auto in_nation = ar.get_controller_from_army_control();
7351 auto tech_nation = in_nation ? in_nation : ar.get_controller_from_army_rebel_control().get_ruler_from_rebellion_within();
7353 auto spending_level = (in_nation ? in_nation.get_effective_land_spending() : 1.0f);
7355 float location_modifier = 1.0f;
7356 if(ar.get_location_from_army_location().get_nation_from_province_ownership() == in_nation) {
7357 location_modifier = 2.0f;
7358 }
else if(ar.get_location_from_army_location().get_nation_from_province_control() == in_nation) {
7359 location_modifier = 1.0f;
7361 location_modifier = 0.1f;
7364 auto combined = state.defines.reinforce_speed * spending_level * location_modifier *
7365 (1.0f + tech_nation.get_modifier_values(sys::national_mod_offsets::reinforce_speed)) *
7366 (1.0f + tech_nation.get_modifier_values(sys::national_mod_offsets::reinforce_rate));
7374 auto pop = reg.get_pop_from_regiment_source();
7375 auto pop_size = pop.get_size();
7376 auto limit_fraction = std::max(state.defines.alice_full_reinforce, std::min(1.0f, pop_size / state.defines.pop_size_per_regiment));
7377 auto curstr = reg.get_strength();
7378 auto newstr = std::min(curstr + combined, limit_fraction);
7380 return newstr - curstr;
7386 auto ar = reg.get_army_from_army_membership();
7401 for(
auto ar : state.world.in_army) {
7402 if(ar.get_battle_from_army_battle_participation() || ar.get_navy_from_army_transport() || ar.get_is_retreating())
7405 auto in_nation = ar.get_controller_from_army_control();
7406 auto combined = calculate_army_combined_reinforce(state, ar);
7408 for(
auto reg : ar.get_army_membership()) {
7409 auto reinforcement = regiment_calculate_reinforcement(state, reg.get_regiment(), combined);
7410 reg.get_regiment().get_strength() += reinforcement;
7411 adjust_regiment_experience(state, in_nation.id, reg.get_regiment(), reinforcement * 5.f * state.defines.exp_gain_div);
7420 auto in_nation = n.get_controller_from_navy_control();
7422 float oversize_amount =
7423 in_nation.get_naval_supply_points() > 0
7424 ? std::min(
float(in_nation.get_used_naval_supply_points()) /
float(in_nation.get_naval_supply_points()), 1.75f)
7426 float over_size_penalty = oversize_amount > 1.0f ? 2.0f - oversize_amount : 1.0f;
7427 auto spending_level = in_nation.get_effective_naval_spending() * over_size_penalty;
7429 auto rr_mod = n.get_location_from_navy_location().get_modifier_values(sys::provincial_mod_offsets::local_repair) + 1.0f;
7430 auto reinf_mod = in_nation.get_modifier_values(sys::national_mod_offsets::reinforce_speed) + 1.0f;
7431 auto combined = rr_mod * reinf_mod * spending_level;
7436float unit_calculate_reinforcement(
sys::state& state, dcon::ship_id ship_id) {
7437 auto combined = calculate_navy_combined_reinforce(state, state.world.ship_get_navy_from_navy_membership(ship_id));
7438 auto curstr = state.world.ship_get_strength(ship_id);
7439 auto newstr = std::min(curstr + combined, 1.0f);
7440 return newstr - curstr;
7446 auto curstr = state.world.ship_get_strength(ship_id);
7447 auto newstr = std::min(curstr + combined, 1.0f);
7448 return newstr - curstr;
7457 for(
auto n : state.world.in_navy) {
7459 if(!n.get_arrival_time() && nb_level > 0) {
7460 auto in_nation = n.get_controller_from_navy_control();
7461 auto combined = calculate_navy_combined_reinforce(state, n);
7463 for(
auto reg : n.get_navy_membership()) {
7464 auto ship = reg.get_ship();
7465 auto reinforcement = ship_calculate_reinforcement(state, ship, combined);
7466 ship.get_strength() += reinforcement;
7467 adjust_ship_experience(state, in_nation.id, reg.get_ship(), std::min(0.f, reinforcement * 5.f * state.defines.exp_gain_div));
7475 if(state.world.nation_get_is_mobilized(n))
7478 state.world.nation_set_is_mobilized(n,
true);
7483 auto real_regs = std::max(int32_t(state.world.nation_get_active_regiments(n)), int32_t(state.defines.min_mobilize_limit));
7484 state.world.nation_set_mobilization_remaining(n,
7485 uint16_t(real_regs * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::mobilization_impact)));
7487 auto schedule_array = state.world.nation_get_mobilization_schedule(n);
7488 schedule_array.clear();
7490 for(
auto pr : state.world.nation_get_province_ownership(n)) {
7491 if(pr.get_province().get_is_colonial())
7493 if(pr.get_province().get_nation_from_province_control() != n)
7501 std::sort(schedule_array.begin(), schedule_array.end(),
7503 auto a_dist = province::direct_distance(state, a.where, cap);
7504 auto b_dist = province::direct_distance(state, b.where, cap);
7505 if(a_dist != b_dist)
7506 return a_dist > b_dist;
7507 return a.where.value < b.where.value;
7512 for(
uint32_t count = schedule_array.size(); count-- > 0;) {
7517 auto province_speed = state.defines.mobilization_speed_base *
7518 float(1.0f + state.defines.mobilization_speed_rails_mult *
7520 auto days = std::max(1, int32_t(1.0f / province_speed));
7522 schedule_array[count].when = state.current_date + delay;
7529 for(
auto& par : state.crisis_participants) {
7533 state.crisis_temperature += state.defines.crisis_temperature_on_mobilize;
7540 "msg_mobilize_start_title",
7541 n, dcon::nation_id{}, dcon::nation_id{},
7546 if(!
state.world.nation_get_is_mobilized(
n))
7549 state.world.nation_set_is_mobilized(
n,
false);
7550 state.world.nation_set_mobilization_remaining(
n, 0);
7551 auto schedule_array =
state.world.nation_get_mobilization_schedule(
n);
7552 schedule_array.clear();
7554 for(
auto ar :
state.world.nation_get_army_control(
n)) {
7555 for(
auto rg : ar.get_army().get_army_membership()) {
7556 auto pop = rg.get_regiment().get_pop_from_regiment_source();
7557 if(!
pop ||
pop.get_poptype() !=
state.culture_definitions.soldiers) {
7558 rg.get_regiment().set_strength(0.0f);
7559 rg.get_regiment().set_pop_from_regiment_source(dcon::pop_id{});
7567 "msg_mobilize_end_title",
7568 n, dcon::nation_id{}, dcon::nation_id{},
7573 for(
auto n :
state.world.in_nation) {
7574 auto& to_mobilize =
n.get_mobilization_remaining();
7575 if(to_mobilize > 0) {
7576 auto schedule =
n.get_mobilization_schedule();
7577 auto s_size = schedule.size();
7579 auto back = schedule[s_size - 1];
7580 if(
state.current_date == back.when) {
7581 schedule.pop_back();
7586 if(
state.world.province_get_nation_from_province_control(back.where) ==
7587 state.world.province_get_nation_from_province_ownership(back.where)) {
7592 for(
auto pop :
state.world.province_get_pop_location(back.where)) {
7601 bool army_is_new =
false;
7604 for(
auto ar :
state.world.province_get_army_location(back.where)) {
7605 if(ar.get_army().get_controller_from_army_control() ==
n)
7606 return ar.get_army().id;
7609 new_army.set_controller_from_army_control(
n);
7610 new_army.set_is_ai_controlled(
n.get_mobilized_is_ai_controlled());
7616 while(available > 0 && to_mobilize > 0 && mob_infantry) {
7618 state.world.regiment_set_org(new_reg, 0.1f);
7619 state.world.regiment_set_experience(new_reg, std::clamp(
state.world.nation_get_modifier_values(
n, sys::national_mod_offsets::land_unit_start_experience), 0.f, 1.f));
7620 state.world.try_create_army_membership(new_reg, a);
7621 auto p =
pop.get_pop();
7623 state.world.try_create_regiment_source(new_reg, p);
7635 if(to_mobilize == 0)
7647bool can_retreat_from_battle(
sys::state& state, dcon::naval_battle_id battle) {
7648 return (state.world.naval_battle_get_start_date(battle) + days_before_retreat < state.current_date);
7650bool can_retreat_from_battle(
sys::state& state, dcon::land_battle_id battle) {
7651 return (state.world.land_battle_get_start_date(battle) + days_before_retreat < state.current_date);
7654bool state_claimed_in_war(
sys::state& state, dcon::war_id w, dcon::nation_id from, dcon::nation_id target, dcon::state_definition_id cb_state) {
7655 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
7656 if(wg.get_wargoal().get_target_nation() == target) {
7657 if(
auto bits = wg.get_wargoal().get_type().get_type_bits(); (bits & (cb_flag::po_transfer_provinces | cb_flag::po_demand_state)) != 0) {
7658 if((bits & cb_flag::all_allowed_states) != 0) {
7659 auto state_filter = wg.get_wargoal().get_type().get_allowed_states();
7661 if((bits & cb_flag::po_transfer_provinces) != 0) {
7662 auto holder = state.world.national_identity_get_nation_from_identity_holder(wg.get_wargoal().get_associated_tag());
7665 for(
auto si : state.world.nation_get_state_ownership(target)) {
7671 }
else if((bits & cb_flag::po_demand_state) != 0) {
7674 for(
auto si : state.world.nation_get_state_ownership(target)) {
7682 if(wg.get_wargoal().get_associated_state() == cb_state)
7686 if((wg.get_wargoal().get_type().get_type_bits() & cb_flag::po_annex) != 0) {
7695bool war_goal_would_be_duplicate(
sys::state& state, dcon::nation_id source, dcon::war_id w, dcon::nation_id target, dcon::cb_type_id cb_type, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation) {
7698 if(state_claimed_in_war(state, w, source, target, cb_state))
7703 for(
auto wg :
state.world.war_get_wargoals_attached(w)) {
7704 if(wg.get_wargoal().get_type() == cb_type && wg.get_wargoal().get_associated_state() == cb_state && wg.get_wargoal().get_associated_tag() == cb_tag && wg.get_wargoal().get_secondary_nation() == cb_secondary_nation && wg.get_wargoal().get_target_nation() == target) {
7710 if((
state.world.cb_type_get_type_bits(cb_type) & cb_flag::po_demand_state) != 0) {
7711 for(
auto wg :
state.world.war_get_wargoals_attached(w)) {
7712 if((wg.get_wargoal().get_type().get_type_bits() & cb_flag::po_annex) != 0 && wg.get_wargoal().get_target_nation() == target) {
7719 auto bits =
state.world.cb_type_get_type_bits(cb_type);
7720 if((bits & cb_flag::po_annex) != 0) {
7721 for(
auto si :
state.world.nation_get_state_ownership(target)) {
7727 if((bits & cb_flag::all_allowed_states) != 0) {
7728 auto state_filter =
state.world.cb_type_get_allowed_states(cb_type);
7729 if((bits & cb_flag::po_transfer_provinces) != 0) {
7730 auto target_tag =
state.world.nation_get_identity_from_identity_holder(target);
7731 auto holder =
state.world.national_identity_get_nation_from_identity_holder(cb_tag);
7734 for(
auto si :
state.world.nation_get_state_ownership(target)) {
7743 }
else if((bits & cb_flag::po_demand_state) != 0) {
7744 auto target_tag =
state.world.nation_get_identity_from_identity_holder(target);
7747 for(
auto si :
state.world.nation_get_state_ownership(target)) {
7764 if(state.military_definitions.pending_blackflag_update) {
7765 state.military_definitions.pending_blackflag_update =
false;
7767 for(
auto a : state.world.in_army) {
7768 if(a.get_controller_from_army_control() && !a.get_navy_from_army_transport() && !
province::has_access_to_province(state, a.get_controller_from_army_control(), a.get_location_from_army_location())) {
7769 a.set_black_flag(
true);
7771 a.set_black_flag(
false);
7777bool rebel_army_in_province(
sys::state& state, dcon::province_id p) {
7778 for(
auto ar : state.world.province_get_army_location(p)) {
7779 if(ar.get_army().get_controller_from_army_rebel_control())
7784dcon::province_id find_land_rally_pt(
sys::state& state, dcon::nation_id by, dcon::province_id start) {
7785 float distance = 2.0f;
7786 dcon::province_id closest;
7787 auto region = state.world.province_get_connected_region_id(start);
7789 for(
auto p : state.world.nation_get_province_ownership(by)) {
7790 if(!p.get_province().get_land_rally_point())
7792 if(p.get_province().get_connected_region_id() != region)
7794 if(p.get_province().get_nation_from_province_control() != by)
7798 closest = p.get_province();
7804dcon::province_id find_naval_rally_pt(
sys::state& state, dcon::nation_id by, dcon::province_id start) {
7805 float distance = 2.0f;
7806 dcon::province_id closest;
7808 for(
auto p : state.world.nation_get_province_ownership(by)) {
7809 if(!p.get_province().get_naval_rally_point())
7811 if(p.get_province().get_nation_from_province_control() != by)
7815 closest = p.get_province();
7821void move_land_to_merge(
sys::state& state, dcon::nation_id by, dcon::army_id a, dcon::province_id start, dcon::province_id dest) {
7822 if(state.world.nation_get_is_player_controlled(by) ==
false)
7825 dest = find_land_rally_pt(state, by, start);
7826 if(!dest || state.world.province_get_nation_from_province_control(dest) != by)
7828 if(state.world.army_get_battle_from_army_battle_participation(a))
7832 for(
auto ar : state.world.province_get_army_location(start)) {
7833 if(ar.get_army().get_controller_from_army_control() == by && ar.get_army() != a) {
7834 auto regs = state.world.army_get_army_membership(a);
7835 while(regs.begin() != regs.end()) {
7836 (*regs.begin()).set_army(ar.get_army());
7846 auto existing_path =
state.world.army_get_path(a);
7847 auto new_size =
uint32_t(path.size());
7848 existing_path.resize(new_size);
7850 for(
uint32_t k = 0; k < new_size; ++k) {
7852 existing_path[k] = path[k];
7855 state.world.army_set_moving_to_merge(a,
true);
7859 if(
state.world.nation_get_is_player_controlled(by) ==
false)
7863 if(!
dest ||
state.world.province_get_nation_from_province_control(
dest) != by)
7867 for(
auto ar :
state.world.province_get_navy_location(start)) {
7868 if(ar.get_navy().get_controller_from_navy_control() == by && ar.get_navy() != a) {
7869 auto regs =
state.world.navy_get_navy_membership(a);
7870 while(regs.begin() != regs.end()) {
7871 (*regs.begin()).set_navy(ar.get_navy());
7881 auto existing_path =
state.world.navy_get_path(a);
7882 auto new_size =
uint32_t(path.size());
7883 existing_path.resize(new_size);
7885 for(
uint32_t k = 0; k < new_size; ++k) {
7887 existing_path[k] = path[k];
7890 state.world.navy_set_moving_to_merge(a,
true);
7894bool pop_eligible_for_mobilization(
sys::state& state, dcon::pop_id p) {
7896 return pop.get_poptype() != state.culture_definitions.soldiers
7897 && pop.get_poptype() != state.culture_definitions.slaves
7898 && pop.get_is_primary_or_accepted_culture()
7902void disband_regiment_w_pop_death(
sys::state& state, dcon::regiment_id reg_id) {
7903 auto base_pop = state.world.regiment_get_pop_from_regiment_source(reg_id);
7904 demographics::reduce_pop_size_safe(state, base_pop, int32_t(state.world.regiment_get_strength(reg_id) * state.defines.pop_size_per_regiment * state.defines.soldier_to_pop_damage));
7905 state.world.delete_regiment(reg_id);
dcon::text_key get_name() noexcept
#define assert(condition)
void add_free_ai_cbs_to_war(sys::state &state, dcon::nation_id n, dcon::war_id w)
float estimate_army_offensive_strength(sys::state &state, dcon::army_id a)
void gather_to_battle(sys::state &state, dcon::nation_id n, dcon::province_id p)
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
void regenerate_jingoism_support(sys::state &state, dcon::nation_id n)
constexpr dcon::demographics_key total(0)
void reduce_pop_size_safe(sys::state &state, dcon::pop_id pop_id, int32_t amount)
@ value
the parser finished reading a JSON value
void post(sys::state &state, message const &m)
Pushes a diplomatic message to the list of pending diplomatic requests for the specified recipient (m...
void execute(sys::state &state, dcon::effect_key key, int32_t primary, int32_t this_slot, int32_t from_slot, uint32_t r_lo, uint32_t r_hi)
float sqrt(float x) noexcept
constexpr uint32_t all_allowed_states
constexpr uint32_t po_status_quo
constexpr uint32_t is_not_constructing_cb
constexpr uint32_t is_civil_war
constexpr uint32_t always
void execute_cb_discovery(sys::state &state, dcon::nation_id n)
bool province_is_under_siege(sys::state const &state, dcon::province_id ids)
bool are_allied_in_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
float truce_break_cb_prestige_cost(sys::state &state, dcon::cb_type_id t)
bool cb_conditions_satisfied(sys::state &state, dcon::nation_id actor, dcon::nation_id target, dcon::cb_type_id cb)
int32_t naval_supply_points_used(sys::state &state, dcon::nation_id n)
float primary_warscore(sys::state &state, dcon::war_id w)
int32_t province_point_cost(sys::state &state, dcon::province_id p, dcon::nation_id n)
float unit_calculate_reinforcement(sys::state &state, dcon::regiment_id reg_id)
float mobilization_size(sys::state const &state, dcon::nation_id n)
void run_gc(sys::state &state)
void update_naval_supply_points(sys::state &state)
void send_rebel_hunter_to_next_province(sys::state &state, dcon::army_id ar, dcon::province_id prov)
void army_arrives_in_province(sys::state &state, dcon::army_id a, dcon::province_id p, crossing_type crossing, dcon::land_battle_id from)
float crisis_cb_addition_infamy_cost(sys::state &state, dcon::cb_type_id type, dcon::nation_id from, dcon::nation_id target, dcon::state_definition_id cb_state)
void take_from_sphere(sys::state &state, dcon::nation_id member, dcon::nation_id new_gp)
int32_t free_transport_capacity(sys::state &state, dcon::navy_id n)
void add_to_war(sys::state &state, dcon::war_id w, dcon::nation_id n, bool as_attacker, bool on_war_creation)
float recruited_pop_fraction(sys::state const &state, dcon::nation_id n)
bool is_artillery_better(sys::state &state, dcon::nation_id n, dcon::unit_type_id best, dcon::unit_type_id given)
int32_t total_regiments(sys::state &state, dcon::nation_id n)
float calculate_navy_combined_reinforce(sys::state &state, dcon::navy_id navy_id)
void eject_ships(sys::state &state, dcon::province_id p)
int32_t defender_peace_cost(sys::state &state, dcon::war_id war)
void end_battle(sys::state &state, dcon::land_battle_id b, battle_result result)
bool can_use_cb_against(sys::state &state, dcon::nation_id from, dcon::nation_id target)
dcon::unit_type_id get_best_artillery(sys::state &state, dcon::nation_id n, bool primary_culture)
void remove_from_common_allied_wars(sys::state &state, dcon::nation_id a, dcon::nation_id b)
void navy_arrives_in_province(sys::state &state, dcon::navy_id n, dcon::province_id p, dcon::naval_battle_id from)
int32_t peace_offer_truce_months(sys::state &state, dcon::peace_offer_id offer)
dcon::pop_id find_available_soldier(sys::state &state, dcon::province_id p, dcon::culture_id pop_culture)
void apply_base_unit_stat_modifiers(sys::state &state)
float calculate_army_combined_reinforce(sys::state &state, dcon::army_id a)
void update_blockade_status(sys::state &state)
void end_wars_between(sys::state &state, dcon::nation_id a, dcon::nation_id b)
bool is_cavalry_better(sys::state &state, dcon::nation_id n, dcon::unit_type_id best, dcon::unit_type_id given)
bool has_truce_with(sys::state &state, dcon::nation_id attacker, dcon::nation_id target)
void populate_war_text_subsitutions(sys::state &state, dcon::war_id w, text::substitution_map &sub)
int32_t regiments_under_construction_in_province(sys::state &state, dcon::province_id p)
float mobilization_impact(sys::state const &state, dcon::nation_id n)
void reject_peace_offer(sys::state &state, dcon::peace_offer_id offer)
void update_ticking_war_score(sys::state &state)
float cb_addition_infamy_cost(sys::state &state, dcon::war_id war, dcon::cb_type_id type, dcon::nation_id from, dcon::nation_id target, dcon::state_definition_id cb_state)
bool standard_war_joining_is_possible(sys::state &state, dcon::war_id wfor, dcon::nation_id n, bool as_attacker)
dcon::nation_id get_naval_battle_lead_defender(sys::state &state, dcon::naval_battle_id b)
war_role get_role(sys::state const &state, dcon::war_id w, dcon::nation_id n)
constexpr uint8_t defender_bonus_dig_in_mask
int32_t main_culture_regiments_under_construction_in_province(sys::state &state, dcon::province_id p)
bool can_retreat_from_battle(sys::state &state, dcon::naval_battle_id battle)
uint32_t state_naval_base_level(sys::state const &state, dcon::state_instance_id si)
void reset_unit_stats(sys::state &state)
int32_t attacker_peace_cost(sys::state &state, dcon::war_id war)
void remove_from_war(sys::state &state, dcon::war_id w, dcon::nation_id n, bool as_loss)
void update_cbs(sys::state &state)
void cleanup_war(sys::state &state, dcon::war_id w, war_result result)
bool is_attacker(sys::state &state, dcon::war_id w, dcon::nation_id n)
uint32_t state_railroad_level(sys::state const &state, dcon::state_instance_id si)
dcon::ship_id create_new_ship(sys::state &state, dcon::nation_id n, dcon::unit_type_id t)
float truce_break_cb_infamy(sys::state &state, dcon::cb_type_id t, dcon::nation_id target, dcon::state_definition_id cb_state)
void cleanup_navy(sys::state &state, dcon::navy_id n)
int32_t count_navies(sys::state &state, dcon::nation_id n)
constexpr float org_dam_mul
bool joining_as_attacker_would_break_truce(sys::state &state, dcon::nation_id a, dcon::war_id w)
bool is_infantry_better(sys::state &state, dcon::nation_id n, dcon::unit_type_id best, dcon::unit_type_id given)
bool is_defender_wargoal(sys::state const &state, dcon::war_id w, dcon::wargoal_id wg)
void regenerate_land_unit_average(sys::state &state)
dcon::unit_type_id get_best_cavalry(sys::state &state, dcon::nation_id n, bool primary_culture)
dcon::nation_id get_land_battle_lead_attacker(sys::state &state, dcon::land_battle_id b)
void update_recruitable_regiments(sys::state &state, dcon::nation_id n)
constexpr float siege_speed_mul
void add_wargoal(sys::state &state, dcon::war_id wfor, dcon::nation_id added_by, dcon::nation_id target, dcon::cb_type_id type, dcon::state_definition_id sd, dcon::national_identity_id tag, dcon::nation_id secondary_nation)
bool cb_requires_selection_of_a_valid_nation(sys::state const &state, dcon::cb_type_id t)
constexpr float str_dam_mul
dcon::unit_type_id get_best_infantry(sys::state &state, dcon::nation_id n, bool primary_culture)
int32_t mobilized_regiments_created_from_province(sys::state &state, dcon::province_id p)
bool are_in_common_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
sys::date arrival_time_to(sys::state &state, dcon::army_id a, dcon::province_id p)
dcon::war_id find_war_between(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
void advance_mobilizations(sys::state &state)
void add_cb(sys::state &state, dcon::nation_id n, dcon::cb_type_id cb, dcon::nation_id target, dcon::state_definition_id target_state=dcon::state_definition_id{})
float ship_calculate_reinforcement(sys::state &state, dcon::ship_id ship_id, float combined)
uint32_t naval_supply_from_naval_base(sys::state &state, dcon::province_id prov, dcon::nation_id nation)
int32_t regiments_possible_from_pop(sys::state &state, dcon::pop_id p)
leader_counts count_leaders(sys::state &state, dcon::nation_id n)
dcon::war_id create_war(sys::state &state, dcon::nation_id primary_attacker, dcon::nation_id primary_defender, dcon::cb_type_id primary_wargoal, dcon::state_definition_id primary_wargoal_state, dcon::national_identity_id primary_wargoal_tag, dcon::nation_id primary_wargoal_secondary)
bool state_has_naval_base(sys::state const &state, dcon::state_instance_id si)
void move_land_to_merge(sys::state &state, dcon::nation_id by, dcon::army_id a, dcon::province_id start, dcon::province_id dest)
void add_truce(sys::state &state, dcon::nation_id a, dcon::nation_id b, int32_t days)
dcon::nation_id get_naval_battle_lead_attacker(sys::state &state, dcon::naval_battle_id b)
ve::fp_vector ve_mobilization_impact(sys::state const &state, ve::tagged_vector< dcon::nation_id > nations)
int32_t regiments_created_from_province(sys::state &state, dcon::province_id p)
void monthly_leaders_update(sys::state &state)
bool cb_instance_conditions_satisfied(sys::state &state, dcon::nation_id actor, dcon::nation_id target, dcon::cb_type_id cb, dcon::state_definition_id st, dcon::national_identity_id tag, dcon::nation_id secondary)
float truce_break_cb_militancy(sys::state &state, dcon::cb_type_id t)
float cb_infamy(sys::state &state, dcon::cb_type_id t, dcon::nation_id target, dcon::state_definition_id cb_state)
float cb_infamy_country_modifier(sys::state &state, dcon::nation_id target)
dcon::regiment_id create_new_regiment(sys::state &state, dcon::nation_id n, dcon::unit_type_id t)
void adjust_leader_prestige(sys::state &state, dcon::leader_id l, float value)
void add_truce_between_sides(sys::state &state, dcon::war_id w, int32_t months)
void move_navy_to_merge(sys::state &state, dcon::nation_id by, dcon::navy_id a, dcon::province_id start, dcon::province_id dest)
void start_mobilization(sys::state &state, dcon::nation_id n)
void update_all_recruitable_regiments(sys::state &state)
void call_attacker_allies(sys::state &state, dcon::war_id wfor)
bool leader_is_in_combat(sys::state &state, dcon::leader_id l)
float unit_get_strength(sys::state &state, dcon::regiment_id regiment_id)
participation internal_find_war_between(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
int32_t mobilized_regiments_possible_from_province(sys::state &state, dcon::province_id p)
void remove_military_access(sys::state &state, dcon::nation_id accessing_nation, dcon::nation_id target)
bool are_at_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
void set_initial_leaders(sys::state &state)
bool defenders_have_non_status_quo_wargoal(sys::state const &state, dcon::war_id w)
void invalidate_unowned_wargoals(sys::state &state)
int32_t main_culture_regiments_created_from_province(sys::state &state, dcon::province_id p)
ve::fp_vector ve_mobilization_size(sys::state const &state, ve::tagged_vector< dcon::nation_id > nations)
void regenerate_total_regiment_counts(sys::state &state)
int32_t supply_limit_in_province(sys::state &state, dcon::nation_id n, dcon::province_id p)
void end_mobilization(sys::state &state, dcon::nation_id n)
bool attackers_have_status_quo_wargoal(sys::state const &state, dcon::war_id w)
int32_t transport_capacity(sys::state &state, dcon::navy_id n)
dcon::leader_id make_new_leader(sys::state &state, dcon::nation_id n, bool is_general)
float cb_infamy_state_modifier(sys::state &state, dcon::nation_id target, dcon::state_definition_id cb_state)
void cleanup_army(sys::state &state, dcon::army_id n)
int32_t total_ships(sys::state &state, dcon::nation_id n)
void daily_leaders_update(sys::state &state)
void kill_leader(sys::state &state, dcon::leader_id l)
float regiment_calculate_reinforcement(sys::state &state, dcon::regiment_fat_id reg, float combined)
float relative_attrition_amount(sys::state &state, dcon::navy_id a, dcon::province_id prov)
bool joining_war_does_not_violate_constraints(sys::state const &state, dcon::nation_id a, dcon::war_id w, bool as_attacker)
void restore_unsaved_values(sys::state &state)
void implement_peace_offer(sys::state &state, dcon::peace_offer_id offer)
void call_defender_allies(sys::state &state, dcon::war_id wfor)
void implement_war_goal(sys::state &state, dcon::war_id war, dcon::cb_type_id wargoal, dcon::nation_id from, dcon::nation_id target, dcon::nation_id secondary_nation, dcon::state_definition_id wargoal_state, dcon::national_identity_id wargoal_t)
bool is_civil_war(sys::state const &state, dcon::war_id w)
int32_t count_armies(sys::state &state, dcon::nation_id n)
bool pop_eligible_for_mobilization(sys::state &state, dcon::pop_id p)
bool retreat(sys::state &state, dcon::navy_id n)
int32_t regiments_max_possible_from_province(sys::state &state, dcon::province_id p)
int32_t naval_supply_points(sys::state &state, dcon::nation_id n)
bool cb_requires_selection_of_a_liberatable_tag(sys::state const &state, dcon::cb_type_id t)
bool compute_blockade_status(sys::state &state, dcon::province_id p)
bool state_claimed_in_war(sys::state &state, dcon::war_id w, dcon::nation_id from, dcon::nation_id target, dcon::state_definition_id cb_state)
dcon::nation_id get_land_battle_lead_defender(sys::state &state, dcon::land_battle_id b)
dcon::province_id find_naval_rally_pt(sys::state &state, dcon::nation_id by, dcon::province_id start)
void regenerate_ship_scores(sys::state &state)
void update_blackflag_status(sys::state &state, dcon::province_id p)
int32_t peace_cost(sys::state &state, dcon::war_id war, dcon::cb_type_id wargoal, dcon::nation_id from, dcon::nation_id target, dcon::nation_id secondary_nation, dcon::state_definition_id wargoal_state, dcon::national_identity_id wargoal_tag)
std::string get_war_name(sys::state &, dcon::war_id)
int32_t main_culture_regiments_max_possible_from_province(sys::state &state, dcon::province_id p)
bool can_add_always_cb_to_war(sys::state &state, dcon::nation_id actor, dcon::nation_id target, dcon::cb_type_id cb, dcon::war_id w)
bool defenders_have_status_quo_wargoal(sys::state const &state, dcon::war_id w)
float successful_cb_prestige(sys::state &state, dcon::cb_type_id t, dcon::nation_id actor)
int32_t cost_of_peace_offer(sys::state &state, dcon::peace_offer_id offer)
bool province_is_blockaded(sys::state const &state, dcon::province_id ids)
void add_truce_from_nation(sys::state &state, dcon::war_id w, dcon::nation_id n, int32_t months)
bool cb_requires_selection_of_a_state(sys::state const &state, dcon::cb_type_id t)
int32_t mobilized_regiments_pop_limit(sys::state &state, dcon::nation_id n)
constexpr uint8_t level_hostile
constexpr uint8_t level_in_sphere
constexpr uint8_t level_mask
bool is_great_power(sys::state const &state, dcon::nation_id id)
void break_alliance(sys::state &state, dcon::diplomatic_relation_id rel)
void adjust_prestige(sys::state &state, dcon::nation_id n, float delta)
bool is_involved_in_crisis(sys::state const &state, dcon::nation_id n)
void make_vassal(sys::state &state, dcon::nation_id subject, dcon::nation_id overlord)
void release_vassal(sys::state &state, dcon::overlord_id rel)
bool are_allied(sys::state &state, dcon::nation_id a, dcon::nation_id b)
float prestige_score(sys::state const &state, dcon::nation_id n)
void adjust_relationship(sys::state &state, dcon::nation_id a, dcon::nation_id b, float delta)
void create_nation_based_on_template(sys::state &state, dcon::nation_id n, dcon::nation_id base)
void cleanup_crisis(sys::state &state)
dcon::nation_id owner_of_pop(sys::state const &state, dcon::pop_id pop_ids)
void post(sys::state &state, message &&m)
void force_ruling_party_ideology(sys::state &state, dcon::nation_id n, dcon::ideology_id id)
void change_government_type(sys::state &state, dcon::nation_id n, dcon::government_type_id new_type)
void set_militancy(sys::state &state, dcon::pop_id p, float v)
float get_militancy(sys::state const &state, dcon::pop_id p)
constexpr uint8_t impassible_bit
constexpr uint8_t non_adjacent_bit
constexpr uint8_t river_crossing_bit
constexpr uint8_t coastal_bit
std::vector< dcon::province_id > make_land_path(sys::state &state, dcon::province_id start, dcon::province_id end, dcon::nation_id nation_as, dcon::army_id a)
float sorting_distance(sys::state &state, dcon::province_id a, dcon::province_id b)
std::vector< dcon::province_id > make_naval_retreat_path(sys::state &state, dcon::nation_id nation_as, dcon::province_id start)
bool has_access_to_province(sys::state &state, dcon::nation_id nation_as, dcon::province_id prov)
bool is_overseas(sys::state const &state, dcon::province_id ids)
void ve_for_each_land_province(sys::state &state, F const &func)
void for_each_province_in_state_instance(sys::state &state, dcon::state_instance_id s, F const &func)
float distance(sys::state &state, dcon::province_adjacency_id pair)
std::vector< dcon::province_id > make_land_retreat_path(sys::state &state, dcon::nation_id nation_as, dcon::province_id start)
void for_each_land_province(sys::state &state, F const &func)
std::vector< dcon::province_id > make_naval_path(sys::state &state, dcon::province_id start, dcon::province_id end)
void set_province_controller(sys::state &state, dcon::province_id p, dcon::nation_id n)
bool has_naval_access_to_province(sys::state &state, dcon::nation_id nation_as, dcon::province_id prov)
void conquer_province(sys::state &state, dcon::province_id id, dcon::nation_id new_owner)
void get_hunting_targets(sys::state &state, dcon::nation_id n, std::vector< impl::prov_str > &rebel_provs)
void sort_hunting_targets(sys::state &state, impl::arm_str const &ar, std::vector< impl::prov_str > &rebel_provs)
random_pair get_random_pair(sys::state const &state, uint32_t value_in)
uint32_t reduce(uint32_t value_in, uint32_t upper_bound)
uint64_t get_random(sys::state const &state, uint32_t value_in)
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
void add_to_layout_box(sys::state &state, layout_base &dest, layout_box &box, embedded_flag ico)
std::string resolve_string_substitution(sys::state &state, dcon::text_key source_text, substitution_map const &mp)
layout_box open_layout_box(layout_base &dest, int32_t indent)
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
void add_to_substitution_map(substitution_map &mp, variable_type key, substitution value)
dcon::text_key get_adjective(sys::state &state, dcon::nation_id id)
ankerl::unordered_dense::map< uint32_t, substitution > substitution_map
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
void close_layout_box(columnar_layout &dest, layout_box &box)
int32_t to_generic(dcon::province_id v)
bool evaluate(sys::state &state, dcon::trigger_key key, int32_t primary, int32_t this_slot, int32_t from_slot)
Holds data regarding a diplomatic message between two specified nations at a certain date,...
static constexpr uint32_t set_size
Holds important data about the game world, state, and other data regarding windowing,...