3#include "dcon_generated.hpp"
17template auto province_is_blockaded<ve::tagged_vector<dcon::province_id>>(
sys::state const&, ve::tagged_vector<dcon::province_id>);
18template auto province_is_under_siege<ve::tagged_vector<dcon::province_id>>(
sys::state const&, ve::tagged_vector<dcon::province_id>);
19template auto battle_is_ongoing_in_province<ve::tagged_vector<dcon::province_id>>(
sys::state const&, ve::tagged_vector<dcon::province_id>);
25 return state.world.nation_get_active_regiments(n);
29 for(
auto v : state.world.nation_get_navy_control(n)) {
30 auto srange = v.get_navy().get_navy_membership();
31 total += int32_t(srange.end() - srange.begin());
37 for(
uint32_t i = 0; i < state.military_definitions.unit_base_definitions.size(); ++i) {
38 dcon::unit_type_id uid = dcon::unit_type_id{dcon::unit_type_id::value_base_t(i)};
39 state.world.for_each_nation([&](dcon::nation_id nid) {
40 state.world.nation_get_unit_stats(nid, uid) = state.military_definitions.unit_base_definitions[uid];
46 assert(state.military_definitions.base_army_unit.index() < 2);
47 assert(state.military_definitions.base_naval_unit.index() < 2);
48 assert(state.military_definitions.base_army_unit.index() != -1);
49 assert(state.military_definitions.base_naval_unit.index() != -1);
50 for(
uint32_t i = 2; i < state.military_definitions.unit_base_definitions.size(); ++i) {
51 dcon::unit_type_id uid = dcon::unit_type_id{dcon::unit_type_id::value_base_t(i)};
52 auto base_id = state.military_definitions.unit_base_definitions[uid].is_land
53 ? state.military_definitions.base_army_unit
54 : state.military_definitions.base_naval_unit;
55 state.world.for_each_nation([&](dcon::nation_id nid) {
56 auto& base_stats = state.world.nation_get_unit_stats(nid, base_id);
57 auto& current_stats = state.world.nation_get_unit_stats(nid, uid);
58 current_stats += base_stats;
64 for(
auto wg : state.world.in_wargoal) {
65 if(wg.get_war_from_wargoals_attached()) {
66 auto s = wg.get_associated_state();
68 bool found_state =
false;
69 for(
auto si : wg.get_target_nation().get_state_ownership()) {
70 if(si.get_state().get_definition() == s) {
76 state.world.delete_wargoal(wg);
84 state.world.for_each_nation([&](dcon::nation_id n) {
85 auto w = state.world.nation_get_war_participant(n);
86 if(w.begin() != w.end()) {
87 state.world.nation_set_is_at_war(n, true);
96 auto other_cbs = state.world.nation_get_available_cbs(from);
97 for(
auto& cb : other_cbs) {
101 for(
auto cb : state.world.in_cb_type) {
112 auto can_use = state.world.cb_type_get_can_use(cb);
117 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
118 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
122 if(!allowed_countries && allowed_states) {
124 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
125 if(wg.get_wargoal().get_added_by() == actor
126 && wg.get_wargoal().get_type() == cb
127 && wg.get_wargoal().get_target_nation() == target) {
134 bool any_allowed =
false;
135 for(
auto si : state.world.nation_get_state_ownership(target)) {
141 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
142 if(wg.get_wargoal().get_added_by() == actor
143 && wg.get_wargoal().get_type() == cb
144 && wg.get_wargoal().get_associated_state() == si.get_state().get_definition()
145 && wg.get_wargoal().get_target_nation() == target) {
159 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
160 if(allowed_substates) {
161 bool any_allowed = [&]() {
162 for(
auto v : state.world.nation_get_overlord_as_ruler(target)) {
163 if(v.get_subject().get_is_substate()) {
164 for(
auto si : state.world.nation_get_state_ownership(target)) {
177 if(allowed_countries) {
178 bool any_allowed = [&]() {
179 for(
auto n : state.world.in_nation) {
184 bool found_dup =
false;
187 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
188 if(wg.get_wargoal().get_added_by() == actor
189 && wg.get_wargoal().get_type() == cb
190 && (wg.get_wargoal().get_associated_tag() == n.get_identity_from_identity_holder()
191 || wg.get_wargoal().get_secondary_nation() == n)
192 && wg.get_wargoal().get_target_nation() == target) {
200 for(
auto si : state.world.nation_get_state_ownership(target)) {
204 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
205 if(wg.get_wargoal().get_added_by() == actor
206 && wg.get_wargoal().get_type() == cb
207 && (wg.get_wargoal().get_associated_tag() == n.get_identity_from_identity_holder()
208 || wg.get_wargoal().get_secondary_nation() == n)
209 && wg.get_wargoal().get_associated_state() == si.get_state().get_definition()
210 && wg.get_wargoal().get_target_nation() == target) {
224 bool found_dup =
false;
226 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
227 if(wg.get_wargoal().get_added_by() == actor
228 && wg.get_wargoal().get_type() == cb
229 && (wg.get_wargoal().get_associated_tag() == n.get_identity_from_identity_holder()
230 || wg.get_wargoal().get_secondary_nation() == n)
231 && wg.get_wargoal().get_target_nation() == target) {
255 auto can_use = state.world.cb_type_get_can_use(cb);
260 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
261 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
263 if(!allowed_countries && allowed_states) {
264 bool any_allowed =
false;
265 for(
auto si : state.world.nation_get_state_ownership(target)) {
275 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
276 if(allowed_substates) {
277 bool any_allowed = [&]() {
278 for(
auto v : state.world.nation_get_overlord_as_ruler(target)) {
279 if(v.get_subject().get_is_substate()) {
280 for(
auto si : state.world.nation_get_state_ownership(target)) {
294 if(allowed_countries) {
295 bool any_allowed = [&]() {
296 for(
auto n : state.world.in_nation) {
300 for(
auto si : state.world.nation_get_state_ownership(target)) {
322 dcon::state_definition_id st, dcon::national_identity_id tag, dcon::nation_id secondary) {
324 auto can_use = state.world.cb_type_get_can_use(cb);
329 auto allowed_countries = state.world.cb_type_get_allowed_countries(cb);
330 auto allowed_states = state.world.cb_type_get_allowed_states(cb);
332 if(!allowed_countries && allowed_states) {
333 bool any_allowed =
false;
335 for(
auto si : state.world.nation_get_state_ownership(target)) {
336 if(si.get_state().get_definition() == st &&
344 for(
auto si : state.world.nation_get_state_ownership(target)) {
356 auto allowed_substates = state.world.cb_type_get_allowed_substate_regions(cb);
357 if(allowed_substates) {
358 bool any_allowed = [&]() {
359 for(
auto v : state.world.nation_get_overlord_as_ruler(target)) {
360 if(v.get_subject().get_is_substate()) {
362 for(
auto si : state.world.nation_get_state_ownership(target)) {
363 if(si.get_state().get_definition() == st &&
370 for(
auto si : state.world.nation_get_state_ownership(target)) {
385 if(allowed_countries) {
386 auto secondary_nation = secondary ? secondary : state.world.national_identity_get_nation_from_identity_holder(tag);
389 bool validity =
false;
392 for(
auto si : state.world.nation_get_state_ownership(target)) {
400 for(
auto si : state.world.nation_get_state_ownership(target)) {
401 if(si.get_state().get_definition() == st &&
423 return state.world.province_get_is_blockaded(ids);
427 auto controller = state.world.province_get_nation_from_province_control(p);
428 auto owner = state.world.province_get_nation_from_province_ownership(p);
431 if(controller != owner)
434 auto port_to = state.world.province_get_port_to(p);
438 for(
auto n : state.world.province_get_navy_location(port_to)) {
439 if(n.get_navy().get_is_retreating() ==
false && !n.get_navy().get_battle_from_navy_battle_participation()) {
454 return state.world.province_get_siege_progress(ids) > 0.0f;
458 auto current = float(state.world.nation_get_active_regiments(n));
459 auto maximum = float(state.world.nation_get_recruitable_regiments(n));
460 return maximum > 0.0f ? current / maximum : 1.0f;
464 auto owner = state.world.state_instance_get_nation_from_state_ownership(si);
465 auto def = state.world.state_instance_get_definition(si);
466 for(
auto p : state.world.state_definition_get_abstract_state_membership(def)) {
467 if(p.get_province().get_nation_from_province_ownership() == owner) {
476 for(
auto wa : state.world.nation_get_war_participant(a)) {
478 for(
auto o : wa.get_war().get_war_participant()) {
479 if(o.get_nation() == b)
487 for(
auto wa : state.world.nation_get_war_participant(a)) {
489 for(
auto o : wa.get_war().get_war_participant()) {
490 if(o.get_nation() == b)
498 for(
auto wa : state.world.nation_get_war_participant(a)) {
499 for(
auto o : wa.get_war().get_war_participant()) {
500 if(o.get_nation() == b)
508 std::vector<dcon::war_id> wars;
509 for(
auto wa : state.world.nation_get_war_participant(a)) {
510 for(
auto o : wa.get_war().get_war_participant()) {
511 if(o.get_nation() == b && o.get_is_attacker() == wa.get_is_attacker()) {
512 wars.push_back(wa.get_war());
516 for(
const auto w : wars) {
528 for(
auto wa : state.world.nation_get_war_participant(a)) {
530 for(
auto o : wa.get_war().get_war_participant()) {
531 if(o.get_nation() == b) {
547 auto target_war_participants = state.world.war_get_war_participant(w);
548 for(
auto wa : state.world.nation_get_war_participant(a)) {
549 for(
auto other_participants : wa.get_war().get_war_participant()) {
550 if(other_participants.get_is_attacker() ==
551 wa.get_is_attacker()) {
552 for(
auto tp : target_war_participants) {
553 if(tp.get_nation() == other_participants.get_nation() && tp.get_is_attacker() != as_attacker)
557 for(
auto tp : target_war_participants) {
558 if(tp.get_nation() == other_participants.get_nation())
568 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
576 auto from = state.world.wargoal_get_added_by(wg);
577 for(
auto p : state.world.war_get_war_participant(w)) {
578 if(p.get_nation() == from)
579 return !p.get_is_attacker();
585 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
593 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
600 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
608 for(
auto p : state.world.war_get_war_participant(w)) {
609 if(p.get_is_attacker() ==
false) {
624 float modifier = 1.0f;
625 auto prov_controller = state.world.province_get_nation_from_province_control(p);
626 auto self_controlled = prov_controller == n;
627 if(state.world.province_get_nation_from_province_ownership(p) == n && self_controlled) {
629 }
else if(self_controlled ||
630 bool(state.world.province_get_rebel_faction_from_province_rebel_control(p))) {
632 }
else if(
auto dip_rel = state.world.get_diplomatic_relation_by_diplomatic_pair(prov_controller, n);
633 state.world.diplomatic_relation_get_are_allied(dip_rel)) {
635 }
else if(
auto uni_rel = state.world.get_unilateral_relationship_by_unilateral_pair(prov_controller, n);
636 state.world.unilateral_relationship_get_military_access(uni_rel)) {
638 }
else if(
bool(state.world.get_core_by_prov_tag_key(p, state.world.nation_get_identity_from_identity_holder(n)))) {
640 }
else if(state.world.province_get_siege_progress(p) > 0.0f) {
643 auto base_supply_lim = (state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::supply_limit) + 1.0f);
644 auto national_supply_lim = (state.world.nation_get_modifier_values(n, sys::national_mod_offsets::supply_limit) + 1.0f);
645 return int32_t(base_supply_lim * modifier * national_supply_lim);
649 for(
auto pop : state.world.province_get_pop_location(p)) {
650 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
651 auto regs = pop.get_pop().get_regiment_source();
652 total += int32_t(regs.end() - regs.begin());
661 if(fatten(state.world, p).get_is_colonial())
665 for(
auto pop : state.world.province_get_pop_location(p)) {
666 if(pop.get_pop().get_poptype() != state.culture_definitions.soldiers &&
668 auto regs = pop.get_pop().get_regiment_source();
669 total += int32_t(regs.end() - regs.begin());
676 auto type = state.world.pop_get_poptype(p);
677 if(type == state.culture_definitions.soldiers) {
678 auto location = state.world.pop_get_province_from_pop_location(p);
679 if(state.world.province_get_is_colonial(location)) {
680 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
681 float minimum = state.defines.pop_min_size_for_regiment;
683 if(state.world.pop_get_size(p) >= minimum) {
684 return int32_t((state.world.pop_get_size(p) / divisor) + 1);
687 }
else if(!state.world.province_get_is_owner_core(location)) {
688 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
689 float minimum = state.defines.pop_min_size_for_regiment;
691 if(state.world.pop_get_size(p) >= minimum) {
692 return int32_t((state.world.pop_get_size(p) / divisor) + 1);
696 float divisor = state.defines.pop_size_per_regiment;
697 float minimum = state.defines.pop_min_size_for_regiment;
699 if(state.world.pop_get_size(p) >= minimum) {
700 return int32_t((state.world.pop_get_size(p) / divisor) + 1);
717 if(state.world.province_get_is_colonial(p)) {
718 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
719 float minimum = state.defines.pop_min_size_for_regiment;
721 for(
auto pop : state.world.province_get_pop_location(p)) {
722 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
723 if(pop.get_pop().get_size() >= minimum) {
724 total += int32_t((pop.get_pop().get_size() / divisor) + 1);
728 }
else if(!state.world.province_get_is_owner_core(p)) {
729 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
730 float minimum = state.defines.pop_min_size_for_regiment;
732 for(
auto pop : state.world.province_get_pop_location(p)) {
733 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
734 if(pop.get_pop().get_size() >= minimum) {
735 total += int32_t((pop.get_pop().get_size() / divisor) + 1);
740 float divisor = state.defines.pop_size_per_regiment;
741 float minimum = state.defines.pop_min_size_for_regiment;
743 for(
auto pop : state.world.province_get_pop_location(p)) {
744 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
745 if(pop.get_pop().get_size() >= minimum) {
746 total += int32_t((pop.get_pop().get_size() / divisor) + 1);
755 for(
auto pop : state.world.province_get_pop_location(p)) {
756 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers && pop.get_pop().get_is_primary_or_accepted_culture()) {
757 auto regs = pop.get_pop().get_regiment_source();
758 total += int32_t(regs.end() - regs.begin());
771 if(state.world.province_get_is_colonial(p)) {
772 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
773 float minimum = state.defines.pop_min_size_for_regiment;
775 for(
auto pop : state.world.province_get_pop_location(p)) {
776 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers &&
777 pop.get_pop().get_is_primary_or_accepted_culture()) {
778 if(pop.get_pop().get_size() >= minimum) {
779 total += int32_t((pop.get_pop().get_size() / divisor) + 1);
783 }
else if(!state.world.province_get_is_owner_core(p)) {
784 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
785 float minimum = state.defines.pop_min_size_for_regiment;
787 for(
auto pop : state.world.province_get_pop_location(p)) {
788 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers &&
789 pop.get_pop().get_is_primary_or_accepted_culture()) {
790 if(pop.get_pop().get_size() >= minimum) {
791 total += int32_t(pop.get_pop().get_size() / divisor);
796 float divisor = state.defines.pop_size_per_regiment;
797 float minimum = state.defines.pop_min_size_for_regiment;
799 for(
auto pop : state.world.province_get_pop_location(p)) {
800 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers &&
801 pop.get_pop().get_is_primary_or_accepted_culture()) {
802 if(pop.get_pop().get_size() >= minimum) {
803 total += int32_t(pop.get_pop().get_size() / divisor);
812 for(
auto pop : state.world.province_get_pop_location(p)) {
813 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
814 auto regs = pop.get_pop().get_province_land_construction();
815 total += int32_t(regs.end() - regs.begin());
822 for(
auto pop : state.world.province_get_pop_location(p)) {
823 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers && pop.get_pop().get_is_primary_or_accepted_culture()) {
824 auto regs = pop.get_pop().get_province_land_construction();
825 total += int32_t(regs.end() - regs.begin());
832 if(state.world.province_get_is_colonial(p)) {
833 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
834 float minimum = state.defines.pop_min_size_for_regiment;
836 for(
auto pop : state.world.province_get_pop_location(p)) {
837 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
838 if(pop.get_pop().get_size() >= minimum && pop.get_pop().get_culture() == pop_culture) {
839 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
840 auto regs = pop.get_pop().get_regiment_source();
841 auto building = pop.get_pop().get_province_land_construction();
843 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
844 return pop.get_pop().id;
849 return dcon::pop_id{};
850 }
else if(!state.world.province_get_is_owner_core(p)) {
851 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
852 float minimum = state.defines.pop_min_size_for_regiment;
854 for(
auto pop : state.world.province_get_pop_location(p)) {
855 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
856 if(pop.get_pop().get_size() >= minimum && pop.get_pop().get_culture() == pop_culture) {
857 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
858 auto regs = pop.get_pop().get_regiment_source();
859 auto building = pop.get_pop().get_province_land_construction();
861 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
862 return pop.get_pop().id;
867 return dcon::pop_id{};
869 float divisor = state.defines.pop_size_per_regiment;
870 float minimum = state.defines.pop_min_size_for_regiment;
872 for(
auto pop : state.world.province_get_pop_location(p)) {
873 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
874 if(pop.get_pop().get_size() >= minimum && pop.get_pop().get_culture() == pop_culture) {
875 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
876 auto regs = pop.get_pop().get_regiment_source();
877 auto building = pop.get_pop().get_province_land_construction();
879 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
880 return pop.get_pop().id;
885 return dcon::pop_id{};
890 if(state.world.province_get_is_colonial(p)) {
891 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_colony_multiplier;
892 float minimum = state.defines.pop_min_size_for_regiment;
894 dcon::pop_id non_preferred;
895 for(
auto pop : state.world.province_get_pop_location(p)) {
896 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
897 if(pop.get_pop().get_size() >= minimum) {
898 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
899 auto regs = pop.get_pop().get_regiment_source();
900 auto building = pop.get_pop().get_province_land_construction();
902 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
903 if(require_accepted == pop.get_pop().get_is_primary_or_accepted_culture())
904 return pop.get_pop().id;
906 non_preferred = pop.get_pop().id;
911 return non_preferred;
912 }
else if(!state.world.province_get_is_owner_core(p)) {
913 float divisor = state.defines.pop_size_per_regiment * state.defines.pop_min_size_for_regiment_noncore_multiplier;
914 float minimum = state.defines.pop_min_size_for_regiment;
916 dcon::pop_id non_preferred;
917 for(
auto pop : state.world.province_get_pop_location(p)) {
918 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
919 if(pop.get_pop().get_size() >= minimum) {
920 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
921 auto regs = pop.get_pop().get_regiment_source();
922 auto building = pop.get_pop().get_province_land_construction();
924 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
925 if(require_accepted == pop.get_pop().get_is_primary_or_accepted_culture())
926 return pop.get_pop().id;
928 non_preferred = pop.get_pop().id;
933 return non_preferred;
935 float divisor = state.defines.pop_size_per_regiment;
936 float minimum = state.defines.pop_min_size_for_regiment;
938 dcon::pop_id non_preferred;
939 for(
auto pop : state.world.province_get_pop_location(p)) {
940 if(pop.get_pop().get_poptype() == state.culture_definitions.soldiers) {
941 if(pop.get_pop().get_size() >= minimum) {
942 auto amount = int32_t((pop.get_pop().get_size() / divisor) + 1);
943 auto regs = pop.get_pop().get_regiment_source();
944 auto building = pop.get_pop().get_province_land_construction();
946 if(amount > ((regs.end() - regs.begin()) + (building.end() - building.begin()))) {
947 if(require_accepted == pop.get_pop().get_is_primary_or_accepted_culture())
948 return pop.get_pop().id;
950 non_preferred = pop.get_pop().id;
955 return non_preferred;
963 auto fp = fatten(state.world, p);
964 if(fp.get_is_colonial() || fp.get_nation_from_province_control() != fp.get_nation_from_province_ownership())
970 std::max(0.0f, fp.get_nation_from_province_ownership().get_modifier_values(sys::national_mod_offsets::mobilization_size));
972 for(
auto pop : state.world.province_get_pop_location(p)) {
982 total += int32_t(pop.get_pop().get_size() *
mobilization_size / state.defines.pop_size_per_regiment);
990 for(
auto p : state.world.nation_get_province_ownership(n)) {
991 if(p.get_province().get_is_colonial() ==
false)
998 state.world.nation_set_recruitable_regiments(n, uint16_t(0));
999 for(
auto p : state.world.nation_get_province_ownership(n)) {
1004 state.world.execute_serial_over_nation([&](
auto ids) { state.world.nation_set_recruitable_regiments(ids, ve::int_vector(0)); });
1005 state.world.for_each_province([&](dcon::province_id p) {
1006 auto owner = state.world.province_get_nation_from_province_ownership(p);
1013 state.world.execute_serial_over_nation([&](
auto ids) { state.world.nation_set_active_regiments(ids, ve::int_vector(0)); });
1014 state.world.for_each_army([&](dcon::army_id a) {
1015 auto owner = state.world.army_get_controller_from_army_control(a);
1017 auto regs_range = state.world.army_get_army_membership(a);
1018 auto num_regs = regs_range.end() - regs_range.begin();
1019 state.world.nation_get_active_regiments(owner) += uint16_t(num_regs);
1029 auto const max = state.military_definitions.unit_base_definitions.size();
1030 state.world.for_each_nation([&](dcon::nation_id n) {
1034 auto lo_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_attack_modifier);
1035 auto ld_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_defense_modifier);
1037 for(
uint32_t i = 2; i < max; ++i) {
1038 dcon::unit_type_id u{dcon::unit_type_id::value_base_t(i)};
1039 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) {
1040 auto& reg_stats = state.world.nation_get_unit_stats(n, u);
1041 total += ((reg_stats.defence_or_hull + ld_mod) + (reg_stats.attack_or_gun_power + lo_mod)) *
1042 state.military_definitions.unit_base_definitions[u].discipline_or_evasion;
1046 state.world.nation_set_averge_land_unit_score(n, total / count);
1054 state.world.for_each_nation([&](dcon::nation_id n) {
1056 auto no_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::naval_attack_modifier);
1057 auto nd_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::naval_defense_modifier);
1059 for(
auto nv : state.world.nation_get_navy_control(n)) {
1060 for(auto shp : nv.get_navy().get_navy_membership()) {
1061 if(state.military_definitions.unit_base_definitions[shp.get_ship().get_type()].capital) {
1062 auto& ship_stats = state.world.nation_get_unit_stats(n, shp.get_ship().get_type());
1063 total += (ship_stats.defence_or_hull + nd_mod) * (ship_stats.attack_or_gun_power + no_mod);
1067 state.world.nation_set_capital_ship_score(n, total / 250.0f);
1072 return int32_t(state.world.nation_get_naval_supply_points(n));
1075 return int32_t(state.world.nation_get_used_naval_supply_points(n));
1083 for(
auto c :
dcon::fatten(state.world, prov).get_core()) {
1085 return uint32_t(state.defines.naval_base_supply_score_empty);
1089 return uint32_t(state.defines.naval_base_supply_score_empty * state.defines.naval_base_non_core_supply_score);
1091 return uint32_t(state.defines.naval_base_supply_score_empty);
1102 state.world.for_each_nation([&](dcon::nation_id n) {
1103 auto cap_region = state.world.province_get_connected_region_id(state.world.nation_get_capital(n));
1105 for(
auto si : state.world.nation_get_state_ownership(n)) {
1106 auto d = state.world.state_instance_get_definition(si.get_state());
1107 bool saw_coastal = false;
1108 bool nb_was_core = false;
1109 bool coast_was_core = false;
1110 int32_t nb_level = 0;
1111 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
1112 if(p.get_province().get_nation_from_province_ownership() == n) {
1113 if(p.get_province().get_is_coast()) {
1115 coast_was_core = coast_was_core || p.get_province().get_is_owner_core();
1117 nb_level = std::max(nb_level, int32_t(p.get_province().get_building_level(uint8_t(economy::province_building_type::naval_base))));
1119 nb_was_core = p.get_province().get_is_owner_core();
1122 bool connected = si.get_state().get_capital().get_connected_region_id() == cap_region;
1126 if(nb_was_core || connected)
1127 total += state.defines.naval_base_supply_score_base * float(1 << (nb_level - 1));
1129 total += state.defines.naval_base_supply_score_base * float(1 << (nb_level - 1)) * state.defines.naval_base_non_core_supply_score;
1131 if(coast_was_core || connected)
1132 total += state.defines.naval_base_supply_score_empty;
1138 state.world.nation_set_naval_supply_points(n, uint16_t(total));
1145 state.world.for_each_nation([&](dcon::nation_id n) {
1147 for(
auto nv :
state.world.nation_get_navy_control(n)) {
1148 for(auto shp : nv.get_navy().get_navy_membership()) {
1149 total += state.military_definitions.unit_base_definitions[shp.get_ship().get_type()].supply_consumption_score;
1152 state.world.nation_set_used_naval_supply_points(n, uint16_t(total));
1158 return state.world.nation_get_modifier_values(n, sys::national_mod_offsets::mobilization_size);
1164 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::mobilization_impact),
1169 for(
auto n : state.world.in_nation) {
1170 if(state.current_date == n.get_reparations_until()) {
1171 for(
auto urel : n.get_unilateral_relationship_as_source()) {
1172 urel.set_reparations(
false);
1175 auto current_cbs = n.get_available_cbs();
1176 for(
uint32_t i = current_cbs.size(); i-- > 0;) {
1177 if(current_cbs[i].expiration && current_cbs[i].expiration <= state.current_date) {
1178 current_cbs.remove_at(i);
1183 if(n.get_constructing_cb_type()) {
1188 auto target = n.get_constructing_cb_target();
1189 if(
military::are_at_war(state, n, target) || state.world.nation_get_owned_province_count(target) == 0 ||
1191 if(n == state.local_player_nation) {
1196 "msg_fab_canceled_title",
1197 n, dcon::nation_id{}, dcon::nation_id{},
1202 n.set_constructing_cb_is_discovered(
false);
1203 n.set_constructing_cb_progress(0.0f);
1204 n.set_constructing_cb_target(dcon::nation_id{});
1205 n.set_constructing_cb_type(dcon::cb_type_id{});
1216 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);
1218 n.get_constructing_cb_progress() += std::max(eff_speed, 0.0f);
1226 if(!n.get_constructing_cb_is_discovered() && eff_speed > 0.0f) {
1228 if(val <=
uint32_t(state.defines.cb_detection_chance_base)) {
1230 n.set_constructing_cb_is_discovered(
true);
1238 if(n.get_constructing_cb_progress() >= 100.0f) {
1239 add_cb(state, n, n.get_constructing_cb_type(), n.get_constructing_cb_target());
1241 if(n == state.local_player_nation) {
1244 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);
1246 "msg_fab_finished_title",
1247 n, dcon::nation_id{}, dcon::nation_id{},
1252 n.set_constructing_cb_is_discovered(
false);
1253 n.set_constructing_cb_progress(0.0f);
1254 n.set_constructing_cb_target(dcon::nation_id{});
1255 n.set_constructing_cb_type(dcon::cb_type_id{});
1261void add_cb(
sys::state& state, dcon::nation_id n, dcon::cb_type_id cb, dcon::nation_id target) {
1262 auto current_cbs = state.world.nation_get_available_cbs(n);
1263 current_cbs.push_back(
military::available_cb{ state.current_date + int32_t(state.defines.created_cb_valid_time) * 30, target, cb });
1268 auto bits = state.world.cb_type_get_type_bits(t);
1270 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1271 total += state.defines.infamy_clear_union_sphere;
1273 if((bits & cb_flag::po_gunboat) != 0) {
1274 total += state.defines.infamy_gunboat;
1276 if((bits & cb_flag::po_annex) != 0) {
1277 total += state.defines.infamy_annex;
1279 if((bits & cb_flag::po_demand_state) != 0) {
1280 total += state.defines.infamy_demand_state;
1282 if((bits & cb_flag::po_add_to_sphere) != 0) {
1283 total += state.defines.infamy_add_to_sphere;
1285 if((bits & cb_flag::po_disarmament) != 0) {
1286 total += state.defines.infamy_disarmament;
1288 if((bits & cb_flag::po_reparations) != 0) {
1289 total += state.defines.infamy_reparations;
1291 if((bits & cb_flag::po_transfer_provinces) != 0) {
1292 total += state.defines.infamy_transfer_provinces;
1294 if((bits & cb_flag::po_remove_prestige) != 0) {
1295 total += state.defines.infamy_prestige;
1297 if((bits & cb_flag::po_make_puppet) != 0) {
1298 total += state.defines.infamy_make_puppet;
1300 if((bits & cb_flag::po_release_puppet) != 0) {
1301 total += state.defines.infamy_release_puppet;
1303 if((bits & cb_flag::po_status_quo) != 0) {
1304 total += state.defines.infamy_status_quo;
1306 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1307 total += state.defines.infamy_install_communist_gov_type;
1309 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1310 total += state.defines.infamy_uninstall_communist_gov_type;
1312 if((bits & cb_flag::po_remove_cores) != 0) {
1313 total += state.defines.infamy_remove_cores;
1315 if((bits & cb_flag::po_colony) != 0) {
1316 total += state.defines.infamy_colony;
1318 if((bits & cb_flag::po_destroy_forts) != 0) {
1319 total += state.defines.infamy_destroy_forts;
1321 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1322 total += state.defines.infamy_destroy_naval_bases;
1325 return total * state.world.cb_type_get_badboy_factor(t);
1330 auto bits = state.world.cb_type_get_type_bits(t);
1332 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1333 total += state.defines.breaktruce_prestige_clear_union_sphere;
1335 if((bits & cb_flag::po_gunboat) != 0) {
1336 total += state.defines.breaktruce_prestige_gunboat;
1338 if((bits & cb_flag::po_annex) != 0) {
1339 total += state.defines.breaktruce_prestige_annex;
1341 if((bits & cb_flag::po_demand_state) != 0) {
1342 total += state.defines.breaktruce_prestige_demand_state;
1344 if((bits & cb_flag::po_add_to_sphere) != 0) {
1345 total += state.defines.breaktruce_prestige_add_to_sphere;
1347 if((bits & cb_flag::po_disarmament) != 0) {
1348 total += state.defines.breaktruce_prestige_disarmament;
1350 if((bits & cb_flag::po_reparations) != 0) {
1351 total += state.defines.breaktruce_prestige_reparations;
1353 if((bits & cb_flag::po_transfer_provinces) != 0) {
1354 total += state.defines.breaktruce_prestige_transfer_provinces;
1356 if((bits & cb_flag::po_remove_prestige) != 0) {
1357 total += state.defines.breaktruce_prestige_prestige;
1359 if((bits & cb_flag::po_make_puppet) != 0) {
1360 total += state.defines.breaktruce_prestige_make_puppet;
1362 if((bits & cb_flag::po_release_puppet) != 0) {
1363 total += state.defines.breaktruce_prestige_release_puppet;
1365 if((bits & cb_flag::po_status_quo) != 0) {
1366 total += state.defines.breaktruce_prestige_status_quo;
1368 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1369 total += state.defines.breaktruce_prestige_install_communist_gov_type;
1371 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1372 total += state.defines.breaktruce_prestige_uninstall_communist_gov_type;
1374 if((bits & cb_flag::po_remove_cores) != 0) {
1375 total += state.defines.breaktruce_prestige_remove_cores;
1377 if((bits & cb_flag::po_colony) != 0) {
1378 total += state.defines.breaktruce_prestige_colony;
1380 if((bits & cb_flag::po_destroy_forts) != 0) {
1381 total += state.defines.breaktruce_prestige_destroy_forts;
1383 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1384 total += state.defines.breaktruce_prestige_destroy_naval_bases;
1387 return total * state.world.cb_type_get_break_truce_prestige_factor(t);
1391 auto bits = state.world.cb_type_get_type_bits(t);
1393 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1394 total += state.defines.breaktruce_militancy_clear_union_sphere;
1396 if((bits & cb_flag::po_gunboat) != 0) {
1397 total += state.defines.breaktruce_militancy_gunboat;
1399 if((bits & cb_flag::po_annex) != 0) {
1400 total += state.defines.breaktruce_militancy_annex;
1402 if((bits & cb_flag::po_demand_state) != 0) {
1403 total += state.defines.breaktruce_militancy_demand_state;
1405 if((bits & cb_flag::po_add_to_sphere) != 0) {
1406 total += state.defines.breaktruce_militancy_add_to_sphere;
1408 if((bits & cb_flag::po_disarmament) != 0) {
1409 total += state.defines.breaktruce_militancy_disarmament;
1411 if((bits & cb_flag::po_reparations) != 0) {
1412 total += state.defines.breaktruce_militancy_reparations;
1414 if((bits & cb_flag::po_transfer_provinces) != 0) {
1415 total += state.defines.breaktruce_militancy_transfer_provinces;
1417 if((bits & cb_flag::po_remove_prestige) != 0) {
1418 total += state.defines.breaktruce_militancy_prestige;
1420 if((bits & cb_flag::po_make_puppet) != 0) {
1421 total += state.defines.breaktruce_militancy_make_puppet;
1423 if((bits & cb_flag::po_release_puppet) != 0) {
1424 total += state.defines.breaktruce_militancy_release_puppet;
1426 if((bits & cb_flag::po_status_quo) != 0) {
1427 total += state.defines.breaktruce_militancy_status_quo;
1429 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1430 total += state.defines.breaktruce_militancy_install_communist_gov_type;
1432 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1433 total += state.defines.breaktruce_militancy_uninstall_communist_gov_type;
1435 if((bits & cb_flag::po_remove_cores) != 0) {
1436 total += state.defines.breaktruce_militancy_remove_cores;
1438 if((bits & cb_flag::po_colony) != 0) {
1439 total += state.defines.breaktruce_militancy_colony;
1441 if((bits & cb_flag::po_destroy_forts) != 0) {
1442 total += state.defines.breaktruce_militancy_destroy_forts;
1444 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1445 total += state.defines.breaktruce_militancy_destroy_naval_bases;
1448 return total * state.world.cb_type_get_break_truce_militancy_factor(t);
1452 auto bits = state.world.cb_type_get_type_bits(t);
1454 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1455 total += state.defines.breaktruce_infamy_clear_union_sphere;
1457 if((bits & cb_flag::po_gunboat) != 0) {
1458 total += state.defines.breaktruce_infamy_gunboat;
1460 if((bits & cb_flag::po_annex) != 0) {
1461 total += state.defines.breaktruce_infamy_annex;
1463 if((bits & cb_flag::po_demand_state) != 0) {
1464 total += state.defines.breaktruce_infamy_demand_state;
1466 if((bits & cb_flag::po_add_to_sphere) != 0) {
1467 total += state.defines.breaktruce_infamy_add_to_sphere;
1469 if((bits & cb_flag::po_disarmament) != 0) {
1470 total += state.defines.breaktruce_infamy_disarmament;
1472 if((bits & cb_flag::po_reparations) != 0) {
1473 total += state.defines.breaktruce_infamy_reparations;
1475 if((bits & cb_flag::po_transfer_provinces) != 0) {
1476 total += state.defines.breaktruce_infamy_transfer_provinces;
1478 if((bits & cb_flag::po_remove_prestige) != 0) {
1479 total += state.defines.breaktruce_infamy_prestige;
1481 if((bits & cb_flag::po_make_puppet) != 0) {
1482 total += state.defines.breaktruce_infamy_make_puppet;
1484 if((bits & cb_flag::po_release_puppet) != 0) {
1485 total += state.defines.breaktruce_infamy_release_puppet;
1487 if((bits & cb_flag::po_status_quo) != 0) {
1488 total += state.defines.breaktruce_infamy_status_quo;
1490 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1491 total += state.defines.breaktruce_infamy_install_communist_gov_type;
1493 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1494 total += state.defines.breaktruce_infamy_uninstall_communist_gov_type;
1496 if((bits & cb_flag::po_remove_cores) != 0) {
1497 total += state.defines.breaktruce_infamy_remove_cores;
1499 if((bits & cb_flag::po_colony) != 0) {
1500 total += state.defines.breaktruce_infamy_colony;
1502 if((bits & cb_flag::po_destroy_forts) != 0) {
1503 total += state.defines.breaktruce_infamy_destroy_forts;
1505 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1506 total += state.defines.breaktruce_infamy_destroy_naval_bases;
1509 return total * state.world.cb_type_get_break_truce_infamy_factor(t);
1520 if(!state.world.province_get_is_colonial(p)) {
1523 auto fac_range = state.world.province_get_factory_location(p);
1524 total += int32_t(fac_range.end() - fac_range.begin());
1527 auto owner_cap = state.world.nation_get_capital(n);
1528 auto overseas = (state.world.province_get_continent(p) != state.world.province_get_continent(owner_cap)) &&
1529 (state.world.province_get_connected_region_id(p) != state.world.province_get_connected_region_id(owner_cap));
1531 if(state.world.province_get_is_owner_core(p) && !overseas) {
1534 if(state.world.nation_get_capital(n) == p) {
1540int32_t
peace_cost(
sys::state& state, dcon::war_id war, dcon::cb_type_id wargoal, dcon::nation_id from, dcon::nation_id target,
1541 dcon::nation_id secondary_nation, dcon::state_definition_id wargoal_state, dcon::national_identity_id wargoal_tag) {
1555 auto bits = state.world.cb_type_get_type_bits(wargoal);
1557 if((bits & cb_flag::great_war_obligatory) != 0) {
1561 if((bits & cb_flag::po_gunboat) != 0) {
1562 total += state.defines.peace_cost_gunboat;
1564 if((bits & cb_flag::po_annex) != 0) {
1565 total += state.defines.peace_cost_annex;
1567 if((bits & cb_flag::po_add_to_sphere) != 0) {
1568 total += state.defines.peace_cost_add_to_sphere;
1570 if((bits & cb_flag::po_disarmament) != 0) {
1571 total += state.defines.peace_cost_disarmament;
1573 if((bits & cb_flag::po_reparations) != 0) {
1574 total += state.defines.peace_cost_reparations;
1576 if((bits & cb_flag::po_remove_prestige) != 0) {
1577 total += state.defines.peace_cost_prestige;
1579 if((bits & cb_flag::po_make_puppet) != 0) {
1580 total += state.defines.peace_cost_make_puppet;
1582 if((bits & cb_flag::po_release_puppet) != 0) {
1583 total += state.defines.peace_cost_release_puppet;
1585 if((bits & cb_flag::po_status_quo) != 0) {
1586 total += state.defines.peace_cost_status_quo;
1588 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1589 total += state.defines.peace_cost_install_communist_gov_type;
1591 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1592 total += state.defines.peace_cost_uninstall_communist_gov_type;
1594 if((bits & cb_flag::po_remove_cores) != 0) {
1595 total += state.defines.peace_cost_remove_cores;
1597 if((bits & cb_flag::po_colony) != 0) {
1598 total += state.defines.peace_cost_colony;
1600 if((bits & cb_flag::po_destroy_forts) != 0) {
1601 total += state.defines.peace_cost_destroy_forts;
1603 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1604 total += state.defines.peace_cost_destroy_naval_bases;
1607 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1608 auto from_group = state.world.nation_get_primary_culture(from).get_group_from_culture_group_membership();
1609 for(
auto target_sphere : state.world.nation_get_gp_relationship_as_great_power(target)) {
1611 target_sphere.get_influence_target().get_primary_culture().get_group_from_culture_group_membership() == from_group) {
1613 total += state.defines.peace_cost_clear_union_sphere;
1617 if((bits & (cb_flag::po_transfer_provinces | cb_flag::po_demand_state)) != 0) {
1618 int32_t sum_target_prov_values = 0;
1619 for(
auto prv : state.world.nation_get_province_ownership(target)) {
1622 auto secondary = secondary_nation ? secondary_nation : state.world.national_identity_get_nation_from_identity_holder(wargoal_tag);
1623 bool is_lib = (bits & cb_flag::po_transfer_provinces) != 0;
1625 if(sum_target_prov_values > 0) {
1626 if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states && (bits & cb_flag::all_allowed_states) != 0) {
1627 for(
auto si : state.world.nation_get_state_ownership(target)) {
1632 total += 280.0f * float(province_point_cost(state, tprov, target)) / float(sum_target_prov_values);
1637 for(
auto tprov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
1638 if(tprov.get_province().get_nation_from_province_ownership() == target)
1639 total += 280.0f * float(
province_point_cost(state, tprov.get_province(), target)) / float(sum_target_prov_values);
1645 if(state.world.war_get_is_great(war)) {
1647 for(
auto par : state.world.war_get_war_participant(war)) {
1648 if(par.get_nation() == from) {
1653 if(state.military_definitions.world_wars_enabled &&
1656 total *= state.defines.gw_warscore_cost_mod_2;
1658 total *= state.defines.gw_warscore_cost_mod;
1662 return std::min(int32_t(total * state.world.cb_type_get_peace_cost_factor(wargoal)), 100);
1666 auto war = state.world.peace_offer_get_war_from_war_settlement(offer);
1668 for(
auto wg : state.world.peace_offer_get_peace_offer_item(offer)) {
1669 total +=
peace_cost(state, war, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(),
1670 wg.get_wargoal().get_target_nation(), wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(),
1671 wg.get_wargoal().get_associated_tag());
1676 int32_t max_months = 0;
1677 for(
auto wg : state.world.peace_offer_get_peace_offer_item(offer)) {
1678 max_months = std::max(max_months, int32_t(wg.get_wargoal().get_type().get_truce_months()));
1680 return max_months + int32_t(state.defines.base_truce_months);
1684 for(
auto wg : state.world.war_get_wargoals_attached(war)) {
1685 if(
is_attacker(state, war, wg.get_wargoal().get_added_by())) {
1686 total +=
peace_cost(state, war, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(),
1687 wg.get_wargoal().get_target_nation(), wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(),
1688 wg.get_wargoal().get_associated_tag());
1695 for(
auto wg : state.world.war_get_wargoals_attached(war)) {
1696 if(!
is_attacker(state, war, wg.get_wargoal().get_added_by())) {
1697 total +=
peace_cost(state, war, wg.get_wargoal().get_type(), wg.get_wargoal().get_added_by(),
1698 wg.get_wargoal().get_target_nation(), wg.get_wargoal().get_secondary_nation(), wg.get_wargoal().get_associated_state(),
1699 wg.get_wargoal().get_associated_tag());
1707 auto bits = state.world.cb_type_get_type_bits(t);
1710 if((bits & cb_flag::po_clear_union_sphere) != 0) {
1711 total += std::max(state.defines.prestige_clear_union_sphere * actor_prestige, state.defines.prestige_clear_union_sphere_base);
1713 if((bits & cb_flag::po_gunboat) != 0) {
1714 total += std::max(state.defines.prestige_gunboat * actor_prestige, state.defines.prestige_gunboat_base);
1716 if((bits & cb_flag::po_annex) != 0) {
1717 total += std::max(state.defines.prestige_annex * actor_prestige, state.defines.prestige_annex_base);
1719 if((bits & cb_flag::po_demand_state) != 0) {
1720 total += std::max(state.defines.prestige_demand_state * actor_prestige, state.defines.prestige_demand_state_base);
1722 if((bits & cb_flag::po_add_to_sphere) != 0) {
1723 total += std::max(state.defines.prestige_add_to_sphere * actor_prestige, state.defines.prestige_add_to_sphere_base);
1725 if((bits & cb_flag::po_disarmament) != 0) {
1726 total += std::max(state.defines.prestige_disarmament * actor_prestige, state.defines.prestige_disarmament_base);
1728 if((bits & cb_flag::po_reparations) != 0) {
1729 total += std::max(state.defines.prestige_reparations * actor_prestige, state.defines.prestige_reparations_base);
1731 if((bits & cb_flag::po_transfer_provinces) != 0) {
1732 total += std::max(state.defines.prestige_transfer_provinces * actor_prestige, state.defines.prestige_transfer_provinces_base);
1734 if((bits & cb_flag::po_remove_prestige) != 0) {
1735 total += std::max(state.defines.prestige_prestige * actor_prestige, state.defines.prestige_prestige_base);
1737 if((bits & cb_flag::po_make_puppet) != 0) {
1738 total += std::max(state.defines.prestige_make_puppet * actor_prestige, state.defines.prestige_make_puppet_base);
1740 if((bits & cb_flag::po_release_puppet) != 0) {
1741 total += std::max(state.defines.prestige_release_puppet * actor_prestige, state.defines.prestige_release_puppet_base);
1743 if((bits & cb_flag::po_status_quo) != 0) {
1744 total += std::max(state.defines.prestige_status_quo * actor_prestige, state.defines.prestige_status_quo_base);
1746 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
1747 total += std::max(state.defines.prestige_install_communist_gov_type * actor_prestige,
1748 state.defines.prestige_install_communist_gov_type_base);
1750 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
1751 total += std::max(state.defines.prestige_uninstall_communist_gov_type * actor_prestige,
1752 state.defines.prestige_uninstall_communist_gov_type_base);
1754 if((bits & cb_flag::po_remove_cores) != 0) {
1755 total += std::max(state.defines.prestige_remove_cores * actor_prestige, state.defines.prestige_remove_cores_base);
1757 if((bits & cb_flag::po_colony) != 0) {
1758 total += std::max(state.defines.prestige_colony * actor_prestige, state.defines.prestige_colony_base);
1760 if((bits & cb_flag::po_destroy_forts) != 0) {
1761 total += std::max(state.defines.prestige_destroy_forts * actor_prestige, state.defines.prestige_destroy_forts_base);
1763 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
1765 std::max(state.defines.prestige_destroy_naval_bases * actor_prestige, state.defines.prestige_destroy_naval_bases_base);
1768 return total * state.world.cb_type_get_prestige_factor(t);
1780 dcon::nation_id target) {
1786 auto other_cbs = state.world.nation_get_available_cbs(from);
1787 for(
auto& cb : other_cbs) {
1792 if(state.world.war_get_is_great(war))
1793 return cb_infamy(state, type) * state.defines.gw_justify_cb_badboy_impact;
1799 auto allowed_nation = state.world.cb_type_get_allowed_countries(t);
1800 return bool(allowed_nation);
1803 auto bits = state.world.cb_type_get_type_bits(t);
1804 return (bits & (cb_flag::po_transfer_provinces)) != 0;
1807 auto bits = state.world.cb_type_get_type_bits(t);
1808 return (bits & (cb_flag::po_demand_state | cb_flag::po_transfer_provinces | cb_flag::po_destroy_naval_bases | cb_flag::po_destroy_forts)) != 0
1809 && (bits & cb_flag::all_allowed_states) == 0;
1818 auto infamy =
cb_infamy(state, state.world.nation_get_constructing_cb_type(n));
1819 auto adj_infamy = std::max(0.0f, ((100.0f - state.world.nation_get_constructing_cb_progress(n)) / 100.0f) * infamy);
1820 state.world.nation_get_infamy(n) += adj_infamy;
1822 auto target = state.world.nation_get_constructing_cb_target(n);
1826 for(
auto si : state.world.nation_get_state_ownership(target)) {
1827 if(si.get_state().get_flashpoint_tag()) {
1828 si.get_state().set_flashpoint_tension(
1829 std::min(100.0f, si.get_state().get_flashpoint_tension() + state.defines.tension_on_cb_discovered));
1835 if(n == state.local_player_nation) {
1841 "msg_fab_discovered_title",
1842 n, target, dcon::nation_id{},
1848 auto army = state.world.leader_get_army_from_army_leadership(l);
1849 if(state.world.army_get_battle_from_army_battle_participation(army))
1851 auto navy = state.world.leader_get_navy_from_navy_leadership(l);
1852 if(state.world.navy_get_battle_from_navy_battle_participation(navy))
1858 auto l = fatten(state.world, state.world.create_leader());
1859 l.set_is_admiral(!is_general);
1863 auto num_personalities =
uint32_t(state.military_definitions.first_background_trait.index() - 1);
1864 auto num_backgrounds =
uint32_t((state.world.leader_trait_size() - num_personalities) - 2);
1868 l.set_personality(dcon::leader_trait_id{dcon::leader_trait_id::value_base_t(1 +
rng::reduce(
uint32_t(trait_pair.high), num_personalities))});
1869 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))});
1873 auto names = state.world.culture_get_last_names(state.world.nation_get_primary_culture(n));
1874 if(names.size() > 0) {
1878 l.set_since(state.current_date);
1882 l.set_prestige(r_factor * state.defines.leader_max_random_prestige);
1884 state.world.try_create_leader_loyalty(n, l);
1886 state.world.nation_get_leadership_points(n) -= state.defines.leader_recruit_cost;
1896 if(state.world.leader_get_nation_from_leader_loyalty(l) == state.local_player_nation) {
1897 if(state.world.leader_get_army_from_army_leadership(l) || state.world.leader_get_navy_from_navy_leadership(l)) {
1898 dcon::nation_id n = state.local_player_nation;
1900 auto is_admiral = state.world.leader_get_is_admiral(l);
1901 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));
1902 auto name = state.world.leader_get_name(l);
1911 "msg_leader_died_title",
1912 n, dcon::nation_id{}, dcon::nation_id{},
1918 state.world.delete_leader(l);
1922 int32_t admirals = 0;
1923 int32_t generals = 0;
1928 for(
auto l : state.world.nation_get_leader_loyalty(n)) {
1929 if(l.get_leader().get_is_admiral())
1937 auto x = state.world.nation_get_army_control(n);
1938 return int32_t(x.end() - x.begin());
1941 auto x = state.world.nation_get_navy_control(n);
1942 return int32_t(x.end() - x.begin());
1951 state.world.execute_serial_over_nation(
1952 [&, optimum_officers = state.world.pop_type_get_research_optimum(state.culture_definitions.officers)](
auto ids) {
1953 auto ofrac = state.world.nation_get_demographics(ids, demographics::to_key(state, state.culture_definitions.officers)) /
1954 ve::max(state.world.nation_get_demographics(ids, demographics::total), 1.0f);
1955 auto omod = ve::min(1.0f, ofrac / optimum_officers) * float(state.culture_definitions.officer_leadership_points);
1956 auto nmod = (state.world.nation_get_modifier_values(ids, sys::national_mod_offsets::leadership_modifier) + 1.0f) *
1957 state.world.nation_get_modifier_values(ids, sys::national_mod_offsets::leadership);
1959 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));
1962 for(
auto n : state.world.in_nation) {
1963 if(n.get_leadership_points() > state.defines.leader_recruit_cost * 3.0f) {
1965 auto new_l = [&]() {
1969 if(existing_leaders.generals < army_count) {
1971 }
else if(existing_leaders.admirals < navy_count) {
1974 auto too_many_generals =
1975 (existing_leaders.admirals > 0 && navy_count > 0)
1976 ?
float(existing_leaders.generals) / float(existing_leaders.admirals) > float(army_count) / float(navy_count)
1981 if(state.world.leader_get_is_admiral(new_l)) {
1982 for(
auto v : state.world.nation_get_navy_control(n)) {
1983 if(!v.get_navy().get_admiral_from_navy_leadership()) {
1984 state.world.try_create_navy_leadership(v.get_navy(), new_l);
1989 for(
auto a : state.world.nation_get_army_control(n)) {
1990 if(!a.get_army().get_general_from_army_leadership()) {
1991 state.world.try_create_army_leadership(a.get_army(), new_l);
2006 for(
uint32_t i = state.world.leader_size(); i-- > 0;) {
2007 dcon::leader_id l{dcon::leader_id::value_base_t(i)};
2008 if(!state.world.leader_is_valid(l))
2011 auto age_in_days = state.current_date.to_raw_value() - state.world.leader_get_since(l).to_raw_value();
2012 if(age_in_days > 365 * 26) {
2013 float age_in_years = float(age_in_days) / 365.0f;
2014 float death_chance =
2015 (age_in_years * (
leader_is_in_combat(state, l) ? 2.0f : 1.0f) / state.defines.leader_age_death_factor) / 11000.0f;
2028 auto int_chance =
uint32_t(death_chance *
float(0xFFFFFFFF));
2031 if(rvalue < int_chance)
2038 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(target,
attacker);
2040 auto truce_ends = state.world.diplomatic_relation_get_truce_until(rel);
2041 if(truce_ends && state.current_date < truce_ends)
2048 auto reg = fatten(state.world, state.world.create_regiment());
2051 auto exp = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_unit_start_experience);
2052 exp += state.world.nation_get_modifier_values(n, sys::national_mod_offsets::regular_experience_level) / 100.f;
2053 reg.set_experience(std::clamp(exp, 0.f, 1.f));
2054 reg.set_strength(1.f);
2059 auto shp = fatten(state.world, state.world.create_ship());
2062 auto exp = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::naval_unit_start_experience);
2063 exp += state.world.nation_get_modifier_values(n, sys::national_mod_offsets::regular_experience_level) / 100.f;
2064 shp.set_experience(std::clamp(exp, 0.f, 1.f));
2065 shp.set_strength(1.f);
2070void give_military_access(
sys::state& state, dcon::nation_id accessing_nation, dcon::nation_id target) {
2071 auto ur = state.world.get_unilateral_relationship_by_unilateral_pair(target, accessing_nation);
2073 ur = state.world.force_create_unilateral_relationship(target, accessing_nation);
2075 state.world.unilateral_relationship_set_military_access(ur,
true);
2078 auto ur = state.world.get_unilateral_relationship_by_unilateral_pair(target, accessing_nation);
2080 state.world.unilateral_relationship_set_military_access(ur,
false);
2094 auto war = fatten(state.world, w);
2096 dcon::nation_id primary_attacker = state.world.war_get_primary_attacker(war);
2097 dcon::nation_id primary_defender = state.world.war_get_original_target(war);
2111 if(state.world.nation_get_owned_province_count(n) == 0)
2114 auto participant = state.world.force_create_war_participant(w, n);
2115 state.world.war_participant_set_is_attacker(participant, as_attacker);
2116 state.world.nation_set_is_at_war(n,
true);
2117 state.world.nation_set_disarmed_until(n,
sys::date{});
2119 for(
auto dep : state.world.nation_get_overlord_as_ruler(n)) {
2120 add_to_war(state, w, dep.get_subject(), as_attacker);
2123 for(
auto wp : state.world.war_get_war_participant(w)) {
2124 if(wp.get_is_attacker() == !as_attacker &&
nations::are_allied(state, n, wp.get_nation()))
2128 if(!as_attacker && state.world.nation_get_rank(state.world.war_get_primary_defender(w)) > state.world.nation_get_rank(n)) {
2129 state.world.war_set_primary_defender(w, n);
2132 for(
auto ul : state.world.nation_get_unilateral_relationship_as_source(n)) {
2133 if(ul.get_war_subsidies()) {
2134 auto role =
get_role(state, w, ul.get_target());
2135 if(role != war_role::none) {
2136 if((as_attacker && role == war_role::defender) || (!as_attacker && role == war_role::attacker)) {
2137 ul.set_war_subsidies(
false);
2143 "msg_wsub_end_title",
2144 n, ul.get_target().id, dcon::nation_id{},
2151 for(
auto ul : state.world.nation_get_unilateral_relationship_as_target(n)) {
2152 if(ul.get_war_subsidies()) {
2153 auto role =
get_role(state, w, ul.get_source());
2154 if(role != war_role::none) {
2155 if((as_attacker && role == war_role::defender) || (!as_attacker && role == war_role::attacker)) {
2156 ul.set_war_subsidies(
false);
2162 "msg_wsub_end_title",
2163 n, ul.get_target().id, dcon::nation_id{},
2171 if(state.military_definitions.great_wars_enabled && !state.world.war_get_is_great(w)) {
2172 int32_t gp_attackers = 0;
2173 int32_t gp_defenders = 0;
2175 for(
auto par : state.world.war_get_war_participant(w)) {
2177 if(par.get_is_attacker())
2184 if(gp_attackers >= 2 && gp_defenders >= 2) {
2186 state.world.war_set_is_great(w,
true);
2187 auto it = state.lookup_key(std::string_view{
"great_war_name"});
2189 state.world.war_set_name(w, it);
2197 "msg_war_becomes_great_title",
2198 state.local_player_nation, dcon::nation_id{}, dcon::nation_id{},
2209 "msg_war_join_title",
2210 n,
get_role(state, w, state.local_player_nation) != war_role::none ? state.local_player_nation : dcon::nation_id{}, dcon::nation_id{ },
2214 if(!on_war_creation && state.world.nation_get_is_player_controlled(n) ==
false) {
2218 for(
auto o : state.world.nation_get_army_control(n)) {
2219 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())
2222 army_arrives_in_province(state, o.get_army(), o.get_army().get_location_from_army_location(), crossing_type::none);
2224 for(
auto o : state.world.nation_get_navy_control(n)) {
2225 if(o.get_navy().get_is_retreating() || o.get_navy().get_battle_from_navy_battle_participation())
2228 auto loc = o.get_navy().get_location_from_navy_location();
2229 if(loc.id.index() >= state.province_definitions.first_sea_province.index())
2235 for(
auto p : state.world.war_get_war_participant(w)) {
2236 if(p.get_nation() == n)
2237 return p.get_is_attacker();
2243 for(
auto p : state.world.war_get_war_participant(w)) {
2244 if(p.get_nation() == n)
2245 return p.get_is_attacker() ? war_role::attacker : war_role::defender;
2247 return war_role::none;
2251 dcon::cb_type_id primary_wargoal, dcon::state_definition_id primary_wargoal_state,
2252 dcon::national_identity_id primary_wargoal_tag, dcon::nation_id primary_wargoal_secondary) {
2253 assert(primary_attacker);
2254 assert(primary_defender);
2255 auto new_war = fatten(state.world, state.world.create_war());
2259 auto ol_rel = state.world.nation_get_overlord_as_subject(primary_defender);
2260 if(
auto ol = state.world.overlord_get_ruler(ol_rel); ol && ol == primary_attacker)
2264 auto ol_rel = state.world.nation_get_overlord_as_subject(primary_attacker);
2265 if(
auto ol = state.world.overlord_get_ruler(ol_rel); ol && ol == primary_defender)
2269 auto real_target = primary_defender;
2270 auto target_ol_rel = state.world.nation_get_overlord_as_subject(primary_defender);
2271 if(
auto ol = state.world.overlord_get_ruler(target_ol_rel); ol && ol != primary_attacker)
2274 new_war.set_primary_attacker(primary_attacker);
2275 new_war.set_primary_defender(real_target);
2276 new_war.set_start_date(state.current_date);
2277 new_war.set_over_state(primary_wargoal_state);
2278 new_war.set_over_tag(primary_wargoal_tag);
2279 new_war.set_original_target(primary_defender);
2280 if(primary_wargoal_secondary) {
2281 new_war.set_over_tag(state.world.nation_get_identity_from_identity_holder(primary_wargoal_secondary));
2284 add_to_war(state, new_war, primary_attacker,
true,
true);
2285 add_to_war(state, new_war, real_target,
false,
true);
2287 if(primary_wargoal) {
2288 add_wargoal(state, new_war, primary_attacker, primary_defender, primary_wargoal, primary_wargoal_state, primary_wargoal_tag,
2289 primary_wargoal_secondary);
2290 new_war.set_name(state.world.cb_type_get_war_name(primary_wargoal));
2292 auto it = state.lookup_key(std::string_view{
"agression_war_name"});
2294 new_war.set_name(it);
2298 if(state.world.nation_get_is_player_controlled(primary_attacker) ==
false)
2300 if(state.world.nation_get_is_player_controlled(primary_defender) ==
false)
2305 std::string resolved_war_name =
get_war_name(state, w);
2309 primary_attacker, primary_defender, dcon::nation_id{},
2320 auto fat = fatten(state.world, war);
2321 auto attacker = state.world.nation_get_identity_from_identity_holder(fat.get_primary_attacker());
2322 auto defender = state.world.nation_get_identity_from_identity_holder(fat.get_primary_defender());
2325 auto war_name_sequence = fat.get_name();
2327 auto attacker_tag_key = attacker_tag;
2328 auto defender_tag_key = defender_tag;
2329 auto war_name_key = war_name_sequence;
2331 if(attacker_tag_key && defender_tag_key && war_name_key) {
2332 std::string war_name = std::string{ state.to_string_view(war_name_key) };
2333 auto attacker_name = state.to_string_view(attacker_tag_key);
2334 auto defender_name = state.to_string_view(defender_tag_key);
2335 auto combined_name = war_name + std::string(
"_") + std::string{attacker_name} + std::string(
"_") + std::string{ defender_name };
2336 std::string_view name = std::string_view(combined_name);
2337 if(
auto it = state.lookup_key(name); it)
2345 auto ol_relation = state.world.nation_get_overlord_as_subject(n);
2346 auto ol_nation = state.world.overlord_get_ruler(ol_relation);
2350 state.world.nation_get_in_sphere_of(n) != state.world.war_get_primary_attacker(wfor) &&
2351 ol_nation != state.world.war_get_primary_attacker(wfor);
2354 state.world.nation_get_in_sphere_of(n) != state.world.war_get_primary_attacker(wfor) &&
2355 ol_nation != state.world.war_get_primary_attacker(wfor);
2359 if(is_civil_war(state, wfor))
2362 auto n = state.world.war_get_primary_defender(wfor);
2363 for(
auto drel : state.world.nation_get_diplomatic_relation(n)) {
2364 auto other_nation = drel.get_related_nations(0) != n ? drel.get_related_nations(0) : drel.get_related_nations(1);
2368 std::memset(&m, 0,
sizeof(m));
2370 m.to = other_nation;
2376 if(state.world.nation_get_in_sphere_of(n)) {
2380 std::memset(&m, 0,
sizeof(m));
2382 m.to = state.world.nation_get_in_sphere_of(n);
2390 if(is_civil_war(state, wfor))
2393 auto n = state.world.war_get_primary_attacker(wfor);
2394 for(
auto drel : state.world.nation_get_diplomatic_relation(n)) {
2395 auto other_nation = drel.get_related_nations(0) != n ? drel.get_related_nations(0) : drel.get_related_nations(1);
2396 if(drel.get_are_allied() && !
has_truce_with(state, other_nation, state.world.war_get_primary_defender(wfor)) &&
2400 std::memset(&m, 0,
sizeof(m));
2402 m.to = other_nation;
2409void add_wargoal(
sys::state& state, dcon::war_id wfor, dcon::nation_id added_by, dcon::nation_id target, dcon::cb_type_id type,
2410 dcon::state_definition_id sd, dcon::national_identity_id tag, dcon::nation_id secondary_nation) {
2413 auto for_attacker =
is_attacker(state, wfor, added_by);
2414 std::vector<dcon::nation_id> targets;
2415 for(
auto p : state.world.state_definition_get_abstract_state_membership(sd)) {
2416 auto owner = p.get_province().get_nation_from_province_ownership();
2417 if(std::find(targets.begin(), targets.end(), owner) == targets.end()) {
2418 for(
auto par : state.world.war_get_war_participant(wfor)) {
2419 if(par.get_nation() == owner && par.get_is_attacker() != for_attacker) {
2420 auto new_wg = fatten(state.world, state.world.create_wargoal());
2421 new_wg.set_added_by(added_by);
2422 new_wg.set_associated_state(sd);
2423 new_wg.set_associated_tag(tag);
2424 new_wg.set_secondary_nation(secondary_nation);
2425 new_wg.set_target_nation(owner);
2426 new_wg.set_type(type);
2427 new_wg.set_war_from_wargoals_attached(wfor);
2428 targets.push_back(owner.id);
2434 bool is_colonial_claim = (state.world.cb_type_get_type_bits(type) & cb_flag::po_colony) != 0;
2435 if(targets.empty()) {
2436 if(!is_colonial_claim) {
2439 auto new_wg = fatten(state.world, state.world.create_wargoal());
2440 new_wg.set_added_by(added_by);
2441 new_wg.set_associated_state(sd);
2442 new_wg.set_associated_tag(tag);
2443 new_wg.set_secondary_nation(secondary_nation);
2444 new_wg.set_target_nation(target);
2445 new_wg.set_type(type);
2446 new_wg.set_war_from_wargoals_attached(wfor);
2450 auto new_wg = fatten(state.world, state.world.create_wargoal());
2451 new_wg.set_added_by(added_by);
2452 new_wg.set_associated_state(sd);
2453 new_wg.set_associated_tag(tag);
2454 new_wg.set_secondary_nation(secondary_nation);
2455 new_wg.set_target_nation(target);
2456 new_wg.set_type(type);
2457 new_wg.set_war_from_wargoals_attached(wfor);
2460 if(
auto on_add = state.world.cb_type_get_on_add(type); on_add) {
2462 uint32_t(state.current_date.value),
uint32_t((added_by.index() << 7) ^ target.index() ^ (type.index() << 3)));
2466 if((state.world.cb_type_get_type_bits(type) & cb_flag::always) == 0) {
2467 auto cb_set = state.world.nation_get_available_cbs(added_by);
2468 for(
uint32_t i = cb_set.size(); i-- > 0;) {
2469 if(cb_set.at(i).cb_type == type && cb_set.at(i).target == target) {
2470 cb_set.remove_at(i);
2475 if(added_by != state.local_player_nation &&
get_role(state, wfor, state.local_player_nation) != war_role::none) {
2483 if(secondary_nation)
2493 "msg_wargoal_title",
2494 added_by, target, state.local_player_nation,
2501 for(
auto vas : state.world.nation_get_overlord_as_ruler(n)) {
2505 dcon::war_participant_id par;
2506 for(
auto p : state.world.nation_get_war_participant(n)) {
2507 if(p.get_war() == w) {
2523 auto rp_ideology = state.world.nation_get_ruling_party(n).get_ideology();
2525 for(
auto prv : state.world.nation_get_province_ownership(n)) {
2526 prv.get_province().get_party_loyalty(rp_ideology) *= (1.0f - state.defines.party_loyalty_hit_on_war_loss);
2537 float pop_militancy = 0.0f;
2539 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
2540 if(wg.get_wargoal().get_added_by() == n) {
2541 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();
2544 pop_militancy += state.defines.war_failed_goal_militancy * wg.get_wargoal().get_type().get_penalty_factor();
2548 if(pop_militancy > 0) {
2549 for(
auto prv : state.world.nation_get_province_ownership(n)) {
2550 for(
auto pop : prv.get_province().get_pop_location()) {
2551 auto& mil = pop.get_pop().get_militancy();
2552 mil = std::min(mil + pop_militancy, 10.0f);
2557 state.world.delete_war_participant(par);
2558 auto rem_wars = state.world.nation_get_war_participant(n);
2559 if(rem_wars.begin() == rem_wars.end()) {
2560 state.world.nation_set_is_at_war(n,
false);
2564 for(
auto p : state.world.nation_get_province_ownership(n)) {
2565 if(
auto c = p.get_province().get_nation_from_province_control(); c && c != n) {
2567 state.world.province_set_siege_progress(p.get_province(), 0.0f);
2574 for(
auto p : state.world.nation_get_province_control(n)) {
2575 if(
auto c = p.get_province().get_nation_from_province_ownership(); c && c != n) {
2577 state.world.province_set_siege_progress(p.get_province(), 0.0f);
2585 state.world.nation_set_last_war_loss(n, state.current_date);
2590 auto par = state.world.war_get_war_participant(w);
2591 state.military_definitions.pending_blackflag_update =
true;
2593 if(state.world.war_get_is_crisis_war(w)) {
2597 while(par.begin() != par.end()) {
2598 if((*par.begin()).get_is_attacker()) {
2599 remove_from_war(state, w, (*par.begin()).get_nation(), result == war_result::defender_won);
2601 remove_from_war(state, w, (*par.begin()).get_nation(), result == war_result::attacker_won);
2605 auto nbattles = state.world.war_get_naval_battle_in_war(w);
2606 while(nbattles.begin() != nbattles.end()) {
2607 end_battle(state, (*nbattles.begin()).get_battle().id, battle_result::indecisive);
2610 auto lbattles = state.world.war_get_land_battle_in_war(w);
2611 while(lbattles.begin() != lbattles.end()) {
2612 end_battle(state, (*lbattles.begin()).get_battle().id, battle_result::indecisive);
2615 state.world.delete_war(w);
2619 for(
auto a : state.world.in_army) {
2620 if(!
bool(a.get_general_from_army_leadership())) {
2621 auto controller = a.get_controller_from_army_control();
2622 for(
auto l : controller.get_leader_loyalty()) {
2623 if(l.get_leader().get_is_admiral() ==
false && !
bool(l.get_leader().get_army_from_army_leadership())) {
2624 a.set_general_from_army_leadership(l.get_leader());
2630 for(
auto a : state.world.in_navy) {
2631 if(!
bool(a.get_admiral_from_navy_leadership())) {
2632 auto controller = a.get_controller_from_navy_control();
2633 for(
auto l : controller.get_leader_loyalty()) {
2634 if(l.get_leader().get_is_admiral() ==
true && !
bool(l.get_leader().get_navy_from_navy_leadership())) {
2635 a.set_admiral_from_navy_leadership(l.get_leader());
2644 auto existing_sphere_leader = state.world.nation_get_in_sphere_of(member);
2645 if(existing_sphere_leader) {
2646 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(member, existing_sphere_leader);
2648 state.world.gp_relationship_get_status(rel) &=
~nations::influence::level_mask;
2650 state.world.nation_set_in_sphere_of(member, dcon::nation_id{});
2655 if(state.world.nation_get_owned_province_count(member) == 0)
2658 auto nrel = state.world.get_gp_relationship_by_gp_influence_pair(member, new_gp);
2660 nrel = state.world.force_create_gp_relationship(member, new_gp);
2663 state.world.gp_relationship_get_status(nrel) &=
~nations::influence::level_mask;
2665 state.world.gp_relationship_set_influence(nrel, state.defines.max_influence);
2666 state.world.nation_set_in_sphere_of(member, new_gp);
2672 "msg_rem_sphere_title",
2673 new_gp, existing_sphere_leader, member,
2679 dcon::nation_id target, dcon::nation_id secondary_nation, dcon::state_definition_id wargoal_state,
2680 dcon::national_identity_id wargoal_t) {
2685 auto bits = state.world.cb_type_get_type_bits(wargoal);
2686 bool for_attacker =
is_attacker(state, war, from);
2690 if((bits & cb_flag::po_add_to_sphere) != 0) {
2691 if(secondary_nation) {
2692 if(secondary_nation != target) {
2693 if(state.world.nation_get_owned_province_count(secondary_nation) != 0)
2696 if(state.world.nation_get_owned_province_count(from) != 0)
2707 if((bits & cb_flag::po_clear_union_sphere) != 0) {
2708 auto from_cg = state.world.nation_get_primary_culture(from).get_group_from_culture_group_membership();
2709 for(
auto gprl : state.world.nation_get_gp_relationship_as_great_power(target)) {
2710 if(gprl.get_influence_target().get_in_sphere_of() == target &&
2711 gprl.get_influence_target().get_primary_culture().get_group_from_culture_group_membership() == from_cg) {
2719 if((bits & cb_flag::po_release_puppet) != 0) {
2720 assert(secondary_nation);
2721 if(secondary_nation != target) {
2722 auto ol = state.world.nation_get_overlord_as_subject(secondary_nation);
2727 auto ol = state.world.nation_get_overlord_as_subject(from);
2735 if((bits & cb_flag::po_make_puppet) != 0) {
2736 for(
auto sub : state.world.nation_get_overlord_as_ruler(target)) {
2739 if(state.world.nation_get_owned_province_count(target) > 0) {
2746 if((bits & cb_flag::po_destroy_forts) != 0) {
2747 if((bits & cb_flag::all_allowed_states) == 0) {
2748 for(
auto prov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
2749 if(prov.get_province().get_nation_from_province_ownership() == target) {
2753 }
else if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states) {
2754 for(
auto si : state.world.nation_get_state_ownership(target)) {
2758 [&](dcon::province_id prov) { state.world.province_set_building_level(prov, uint8_t(economy::province_building_type::fort), 0); });
2765 if((bits & cb_flag::po_destroy_naval_bases) != 0) {
2766 if((bits & cb_flag::all_allowed_states) == 0) {
2767 for(
auto prov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
2768 if(prov.get_province().get_nation_from_province_ownership() == target) {
2772 }
else if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states) {
2773 for(
auto si : state.world.nation_get_state_ownership(target)) {
2777 [&](dcon::province_id prov) { state.world.province_set_building_level(prov, uint8_t(economy::province_building_type::naval_base), 0); });
2786 if((bits & cb_flag::po_disarmament) != 0) {
2788 if(state.world.nation_get_owned_province_count(target) > 0)
2789 state.world.nation_set_disarmed_until(target, state.current_date + int32_t(state.defines.reparations_years) * 365);
2793 if((bits & cb_flag::po_reparations) != 0) {
2794 if(state.world.nation_get_owned_province_count(target) > 0) {
2795 state.world.nation_set_reparations_until(target, state.current_date + int32_t(state.defines.reparations_years) * 365);
2796 auto urel = state.world.get_unilateral_relationship_by_unilateral_pair(target, from);
2798 urel = state.world.force_create_unilateral_relationship(target, from);
2800 state.world.unilateral_relationship_set_reparations(urel,
true);
2806 if((bits & cb_flag::po_remove_prestige) != 0) {
2807 if(state.world.nation_get_owned_province_count(target) > 0) {
2809 -(state.defines.prestige_reduction *
nations::prestige_score(state, target) + state.defines.prestige_reduction_base));
2817 if((bits & cb_flag::po_install_communist_gov_type) != 0) {
2818 if(state.world.nation_get_owned_province_count(target) > 0) {
2821 state.world.political_party_get_ideology(state.world.nation_get_ruling_party(from)));
2828 if((bits & cb_flag::po_uninstall_communist_gov_type) != 0) {
2829 if(state.world.nation_get_owned_province_count(target) > 0) {
2837 if((bits & cb_flag::po_colony) != 0) {
2838 std::vector<dcon::colonization_id> to_del;
2839 for(
auto c : state.world.state_definition_get_colonization(wargoal_state)) {
2840 if(c.get_colonizer() != from)
2841 to_del.push_back(c.id);
2843 for(
auto c : to_del) {
2844 state.world.delete_colonization(c);
2848 bool target_existed = state.world.nation_get_owned_province_count(target);
2856 if((bits & cb_flag::po_transfer_provinces) != 0) {
2857 auto target_tag = state.world.nation_get_identity_from_identity_holder(target);
2859 dcon::nation_id holder = from;
2861 holder = state.world.national_identity_get_nation_from_identity_holder(wargoal_t);
2863 holder = state.world.create_nation();
2864 state.world.nation_set_identity_from_identity_holder(holder, wargoal_t);
2866 if(
auto lprovs = state.world.nation_get_province_ownership(holder); lprovs.begin() == lprovs.end()) {
2871 if(!target_existed && state.world.nation_get_is_great_power(from)) {
2872 auto sr = state.world.force_create_gp_relationship(holder, from);
2873 auto& flags = state.world.gp_relationship_get_status(sr);
2875 state.world.nation_set_in_sphere_of(holder, from);
2877 add_truce(state, holder, target, int32_t(state.defines.base_truce_months) * 30);
2879 if((bits & cb_flag::all_allowed_states) == 0) {
2880 for(
auto prov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
2881 if(prov.get_province().get_nation_from_province_ownership() == target) {
2883 if((bits & cb_flag::po_remove_cores) != 0) {
2884 auto find_core = state.world.get_core_by_prov_tag_key(prov.get_province(), target_tag);
2886 state.world.delete_core(find_core);
2891 }
else if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states) {
2892 std::vector<dcon::state_instance_id> prior_states;
2893 for(
auto si : state.world.nation_get_state_ownership(target)) {
2895 prior_states.push_back(si.get_state());
2898 for(
auto si : prior_states) {
2899 for(
auto prov : state.world.state_definition_get_abstract_state_membership(state.world.state_instance_get_definition(si))) {
2900 if(prov.get_province().get_nation_from_province_ownership() == target) {
2902 if((bits & cb_flag::po_remove_cores) != 0) {
2903 auto find_core = state.world.get_core_by_prov_tag_key(prov.get_province(), target_tag);
2905 state.world.delete_core(find_core);
2915 if((bits & cb_flag::po_demand_state) != 0) {
2916 auto target_tag = state.world.nation_get_identity_from_identity_holder(target);
2918 if((bits & cb_flag::all_allowed_states) == 0) {
2919 for(
auto prov : state.world.state_definition_get_abstract_state_membership(wargoal_state)) {
2920 if(prov.get_province().get_nation_from_province_ownership() == target) {
2922 if((bits & cb_flag::po_remove_cores) != 0) {
2923 auto find_core = state.world.get_core_by_prov_tag_key(prov.get_province(), target_tag);
2925 state.world.delete_core(find_core);
2930 }
else if(
auto allowed_states = state.world.cb_type_get_allowed_states(wargoal); allowed_states) {
2931 std::vector<dcon::state_instance_id> prior_states;
2932 for(
auto si : state.world.nation_get_state_ownership(target)) {
2934 prior_states.push_back(si.get_state());
2937 for(
auto si : prior_states) {
2939 state.world.state_definition_get_abstract_state_membership(state.world.state_instance_get_definition(si))) {
2941 if(prov.get_province().get_nation_from_province_ownership() == target) {
2943 if((bits & cb_flag::po_remove_cores) != 0) {
2944 auto find_core = state.world.get_core_by_prov_tag_key(prov.get_province(), target_tag);
2946 state.world.delete_core(find_core);
2954 if(war && target_existed && state.world.nation_get_owned_province_count(target) == 0) {
2955 if(state.military_definitions.liberate) {
2956 auto counter_wg = fatten(state.world, state.world.create_wargoal());
2957 counter_wg.set_added_by(
2958 for_attacker ? state.world.war_get_primary_defender(war) : state.world.war_get_primary_attacker(war));
2959 counter_wg.set_target_nation(from);
2960 counter_wg.set_associated_tag(state.world.nation_get_identity_from_identity_holder(target));
2961 counter_wg.set_type(state.military_definitions.liberate);
2962 state.world.force_create_wargoals_attached(war, counter_wg);
2968 if((bits & cb_flag::po_annex) != 0 && target != from) {
2969 auto target_tag = state.world.nation_get_identity_from_identity_holder(target);
2970 auto target_owns = state.world.nation_get_province_ownership(target);
2972 while(target_owns.begin() != target_owns.end()) {
2973 auto prov = (*target_owns.begin()).get_province();
2975 if((bits & cb_flag::po_remove_cores) != 0) {
2976 auto find_core = state.world.get_core_by_prov_tag_key(prov, target_tag);
2978 state.world.delete_core(find_core);
2983 if(target_existed) {
2984 if(war && state.military_definitions.liberate) {
2985 auto counter_wg = fatten(state.world, state.world.create_wargoal());
2986 counter_wg.set_added_by(
2987 for_attacker ? state.world.war_get_primary_defender(war) : state.world.war_get_primary_attacker(war));
2988 counter_wg.set_target_nation(from);
2989 counter_wg.set_associated_tag(state.world.nation_get_identity_from_identity_holder(target));
2990 counter_wg.set_type(state.military_definitions.liberate);
2991 state.world.force_create_wargoals_attached(war, counter_wg);
2998 auto accepted_effect = state.world.cb_type_get_on_po_accepted(wargoal);
2999 if(accepted_effect) {
3001 uint32_t((state.current_date.value << 8) ^ target.index()),
uint32_t(from.index() ^ (wargoal.index() << 3)));
3007 float prestige_gain =
successful_cb_prestige(state, wargoal, from) * (war ? 1.0f : state.defines.crisis_wargoal_prestige_mult);
3008 if(state.world.nation_get_owned_province_count(from) > 0)
3010 if(state.world.nation_get_owned_province_count(target) > 0)
3020 auto remove_pending_offer = [&](dcon::peace_offer_id id) {
3021 for(
auto& m : state.pending_messages) {
3028 for(
auto po : state.world.in_peace_offer) {
3029 if(!po.get_nation_from_pending_peace_offer()) {
3030 remove_pending_offer(po);
3031 state.world.delete_peace_offer(po);
3032 }
else if(!po.get_war_from_war_settlement() && !po.get_is_crisis_offer()) {
3033 remove_pending_offer(po);
3034 state.world.delete_peace_offer(po);
3036 remove_pending_offer(po);
3037 state.world.delete_peace_offer(po);
3045 static std::vector<dcon::wargoal_id> to_delete;
3047 for(
auto w : state.world.in_war) {
3048 for(
auto wg : w.get_wargoals_attached()) {
3049 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)
3050 to_delete.push_back(wg.get_wargoal());
3053 for(
auto g : to_delete)
3054 state.world.delete_wargoal(g);
3056 for(
auto w : state.world.in_war) {
3057 if(
get_role(state, w, w.get_primary_attacker()) != war_role::attacker || w.get_primary_attacker().get_overlord_as_subject().get_ruler()) {
3058 int32_t best_rank = 0;
3060 for(
auto par : w.get_war_participant()) {
3061 if(par.get_is_attacker() && !(par.get_nation().get_overlord_as_subject().get_ruler())) {
3062 if(!n || par.get_nation().get_rank() < best_rank) {
3063 best_rank = par.get_nation().get_rank();
3064 n = par.get_nation();
3072 w.set_primary_attacker(n);
3074 if(
get_role(state, w, w.get_primary_defender()) != war_role::defender || w.get_primary_defender().get_overlord_as_subject().get_ruler()) {
3075 int32_t best_rank = 0;
3077 for(
auto par : w.get_war_participant()) {
3078 if(!par.get_is_attacker() && !(par.get_nation().get_overlord_as_subject().get_ruler())) {
3079 if(!n || par.get_nation().get_rank() < best_rank) {
3080 best_rank = par.get_nation().get_rank();
3081 n = par.get_nation();
3089 w.set_primary_defender(n);
3091 bool non_sq_war_goal =
false;
3092 for(
auto wg : w.get_wargoals_attached()) {
3094 if(wg.get_wargoal().get_type().get_type_bits() == cb_flag::po_status_quo) {
3097 non_sq_war_goal =
true;
3101 if(!non_sq_war_goal)
3109 for(
auto wg : state.world.in_wargoal) {
3110 auto po = wg.get_peace_offer_from_peace_offer_item();
3111 auto wr = wg.get_war_from_wargoals_attached();
3113 state.world.delete_wargoal(wg);
3119 for(
uint32_t i = state.world.navy_size(); i-- > 0; ) {
3120 dcon::navy_id n{ dcon::navy_id::value_base_t(i) };
3121 if(state.world.navy_is_valid(n)) {
3122 auto rng = state.world.navy_get_navy_membership(n);
3123 if(!state.world.navy_get_battle_from_navy_battle_participation(n)) {
3124 if(
rng.begin() ==
rng.end() || !state.world.navy_get_controller_from_navy_control(n)) {
3130 for(
uint32_t i = state.world.army_size(); i-- > 0; ) {
3131 dcon::army_id n{ dcon::army_id::value_base_t(i) };
3132 if(state.world.army_is_valid(n)) {
3133 auto rng = state.world.army_get_army_membership(n);
3134 if(!state.world.army_get_battle_from_army_battle_participation(n)) {
3135 if(
rng.begin() ==
rng.end() || (!state.world.army_get_controller_from_army_rebel_control(n) && !state.world.army_get_controller_from_army_control(n))) {
3144 auto wpar = state.world.war_get_war_participant(w);
3145 auto num_par = int32_t(wpar.end() - wpar.begin());
3146 auto end_truce = state.current_date + months * 31;
3148 for(int32_t i = 0; i < num_par; ++i) {
3149 auto this_par = *(wpar.begin() + i);
3150 auto this_nation = this_par.get_nation();
3152 if(this_nation.get_overlord_as_subject().get_ruler())
3155 auto attacker = this_par.get_is_attacker();
3157 for(int32_t j = i + 1; j < num_par; ++j) {
3158 auto other_par = *(wpar.begin() + j);
3159 auto other_nation = other_par.get_nation();
3161 if(!other_nation.get_overlord_as_subject().get_ruler() &&
attacker != other_par.get_is_attacker()) {
3162 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(this_nation, other_nation);
3164 rel = state.world.force_create_diplomatic_relation(this_nation, other_nation);
3166 auto& current_truce = state.world.diplomatic_relation_get_truce_until(rel);
3167 if(!current_truce || current_truce < end_truce)
3168 current_truce = end_truce;
3174 auto end_truce = state.current_date + months * 31;
3177 for(
auto par : state.world.war_get_war_participant(w)) {
3178 auto other_nation = par.get_nation();
3179 if(other_nation.get_overlord_as_subject().get_ruler())
3183 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(n, other_nation);
3185 rel = state.world.force_create_diplomatic_relation(n, other_nation);
3187 auto& current_truce = state.world.diplomatic_relation_get_truce_until(rel);
3188 if(!current_truce || current_truce < end_truce)
3189 current_truce = end_truce;
3194 auto end_truce = state.current_date + days;
3196 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(a, b);
3198 rel = state.world.force_create_diplomatic_relation(a, b);
3200 auto& current_truce = state.world.diplomatic_relation_get_truce_until(rel);
3201 if(!current_truce || current_truce < end_truce)
3202 current_truce = end_truce;
3206 dcon::nation_id from = state.world.peace_offer_get_nation_from_pending_peace_offer(offer);
3207 dcon::nation_id target = state.world.peace_offer_get_target(offer);
3210 auto war = state.world.peace_offer_get_war_from_war_settlement(offer);
3215 [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) {
3216 text::substitution_map sub;
3217 text::add_to_substitution_map(sub, text::variable_type::order, std::string_view(
""));
3218 text::add_to_substitution_map(sub, text::variable_type::second, text::get_adjective(state, pd));
3219 text::add_to_substitution_map(sub, text::variable_type::second_country, pd);
3220 text::add_to_substitution_map(sub, text::variable_type::first, text::get_adjective(state, pa));
3221 text::add_to_substitution_map(sub, text::variable_type::third, tag);
3222 text::add_to_substitution_map(sub, text::variable_type::state, st);
3224 std::string resolved_war_name = text::resolve_string_substitution(state, name, sub);
3225 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});
3227 "msg_peace_offer_accepted_title",
3228 target, from, dcon::nation_id{},
3233 bool contains_sq =
false;
3235 for(
auto wg_offered : state.world.peace_offer_get_peace_offer_item(offer)) {
3236 auto wg = wg_offered.get_wargoal();
3237 implement_war_goal(state, state.world.peace_offer_get_war_from_war_settlement(offer), wg.get_type(),
3238 wg.get_added_by(), wg.get_target_nation(), wg.get_secondary_nation(), wg.get_associated_state(), wg.get_associated_tag());
3245 auto offer_range =
state.world.peace_offer_get_peace_offer_item(offer);
3246 while(offer_range.begin() != offer_range.end()) {
3247 state.world.delete_wargoal((*offer_range.begin()).get_wargoal());
3252 if((
state.world.war_get_primary_attacker(war) == from &&
state.world.war_get_primary_defender(war) == target)
3255 if(
state.world.war_get_is_great(war)) {
3256 if(
state.world.peace_offer_get_is_concession(offer) ==
false) {
3257 for(
auto par :
state.world.war_get_war_participant(war)) {
3258 if(par.get_is_attacker() ==
false) {
3260 dcon::nation_id{}, dcon::state_definition_id{}, dcon::national_identity_id{});
3264 for(
auto par :
state.world.war_get_war_participant(war)) {
3265 if(par.get_is_attacker() ==
true) {
3267 dcon::nation_id{}, dcon::state_definition_id{}, dcon::national_identity_id{});
3274 state.world.peace_offer_get_is_concession(offer) ? war_result::defender_won : war_result::attacker_won);
3276 }
else if((
state.world.war_get_primary_attacker(war) == target &&
state.world.war_get_primary_defender(war) == from)
3279 if(
state.world.war_get_is_great(war)) {
3280 if(
state.world.peace_offer_get_is_concession(offer) ==
false) {
3281 for(
auto par :
state.world.war_get_war_participant(war)) {
3282 if(par.get_is_attacker() ==
true) {
3284 dcon::nation_id{}, dcon::state_definition_id{}, dcon::national_identity_id{});
3288 for(
auto par :
state.world.war_get_war_participant(war)) {
3289 if(par.get_is_attacker() ==
false) {
3291 dcon::nation_id{}, dcon::state_definition_id{}, dcon::national_identity_id{});
3298 state.world.peace_offer_get_is_concession(offer) ? war_result::attacker_won : war_result::defender_won);
3300 }
else if(
state.world.war_get_primary_attacker(war) == from ||
state.world.war_get_primary_defender(war) == from) {
3302 if(
state.world.war_get_is_great(war) &&
state.world.peace_offer_get_is_concession(offer) ==
false) {
3303 implement_war_goal(state, war,
state.military_definitions.standard_great_war, from, target, dcon::nation_id{},
3304 dcon::state_definition_id{}, dcon::national_identity_id{});
3307 if(
state.world.nation_get_owned_province_count(
state.world.war_get_primary_attacker(war)) == 0) {
3309 cleanup_war(state, war, war_result::defender_won);
3310 }
else if(
state.world.nation_get_owned_province_count(
state.world.war_get_primary_defender(war)) == 0) {
3312 cleanup_war(state, war, war_result::attacker_won);
3315 remove_from_war(state, war, target,
state.world.peace_offer_get_is_concession(offer) ==
false);
3317 }
else if(
state.world.war_get_primary_attacker(war) == target ||
state.world.war_get_primary_defender(war) == target) {
3319 if(
state.world.war_get_is_great(war) &&
state.world.peace_offer_get_is_concession(offer) ==
true) {
3320 implement_war_goal(state, war,
state.military_definitions.standard_great_war, target, from, dcon::nation_id{},
3321 dcon::state_definition_id{}, dcon::national_identity_id{});
3324 if(
state.world.nation_get_owned_province_count(
state.world.war_get_primary_attacker(war)) == 0) {
3326 cleanup_war(state, war, war_result::defender_won);
3327 }
else if(
state.world.nation_get_owned_province_count(
state.world.war_get_primary_defender(war)) == 0) {
3329 cleanup_war(state, war, war_result::attacker_won);
3338 bool crisis_attackers_won = (
from ==
state.primary_crisis_attacker) == (
state.world.peace_offer_get_is_concession(offer) ==
false);
3340 for(
auto& par :
state.crisis_participants) {
3344 if(par.merely_interested ==
false && par.id !=
state.primary_crisis_attacker && par.id !=
state.primary_crisis_defender) {
3345 if(par.joined_with_offer.wargoal_type) {
3347 bool was_part_of_offer =
false;
3348 for(
auto wg :
state.world.peace_offer_get_peace_offer_item(offer)) {
3349 if(wg.get_wargoal().get_added_by() == par.id)
3350 was_part_of_offer =
true;
3352 if(!was_part_of_offer) {
3353 float prestige_loss = std::min(
state.defines.war_failed_goal_prestige_base,
3354 state.defines.war_failed_goal_prestige *
state.defines.crisis_wargoal_prestige_mult *
3356 state.world.cb_type_get_penalty_factor(par.joined_with_offer.wargoal_type);
3359 auto pop_militancy =
state.defines.war_failed_goal_militancy *
state.defines.crisis_wargoal_militancy_mult *
3360 state.world.cb_type_get_penalty_factor(par.joined_with_offer.wargoal_type);
3361 if(pop_militancy > 0) {
3362 for(
auto prv :
state.world.nation_get_province_ownership(par.id)) {
3363 for(
auto pop : prv.get_province().get_pop_location()) {
3364 auto&
mil =
pop.get_pop().get_militancy();
3365 mil = std::min(mil + pop_militancy, 10.0f);
3370 if(par.supports_attacker) {
3372 -
state.defines.crisis_winner_relations_impact);
3375 -
state.defines.crisis_winner_relations_impact);
3378 if(par.supports_attacker) {
3380 state.defines.crisis_winner_relations_impact);
3383 state.defines.crisis_winner_relations_impact);
3387 if(crisis_attackers_won != par.supports_attacker) {
3388 if(par.supports_attacker) {
3390 -
state.defines.crisis_winner_relations_impact);
3393 -
state.defines.crisis_winner_relations_impact);
3396 if(par.supports_attacker) {
3398 state.defines.crisis_winner_relations_impact);
3401 state.defines.crisis_winner_relations_impact);
3408 if(crisis_attackers_won) {
3410 float p_factor = 0.05f * (
state.defines.crisis_winner_prestige_factor_base +
3411 state.defines.crisis_winner_prestige_factor_year * float(
state.current_date.value) / float(365));
3418 auto rp_ideology =
state.world.nation_get_ruling_party(
state.primary_crisis_defender).get_ideology();
3420 for(
auto prv :
state.world.nation_get_province_ownership(
state.primary_crisis_defender)) {
3421 prv.get_province().get_party_loyalty(rp_ideology) *= (1.0f -
state.defines.party_loyalty_hit_on_war_loss);
3426 float p_factor = 0.05f * (
state.defines.crisis_winner_prestige_factor_base +
3427 state.defines.crisis_winner_prestige_factor_year * float(
state.current_date.value) / float(365));
3434 auto rp_ideology =
state.world.nation_get_ruling_party(
state.primary_crisis_attacker).get_ideology();
3436 for(
auto prv :
state.world.nation_get_province_ownership(
state.primary_crisis_attacker)) {
3437 prv.get_province().get_party_loyalty(rp_ideology) *= (1.0f -
state.defines.party_loyalty_hit_on_war_loss);
3443 state.world.peace_offer_set_war_from_war_settlement(offer, dcon::war_id{});
3444 state.world.peace_offer_set_is_crisis_offer(offer,
false);
3448 dcon::nation_id from = state.world.peace_offer_get_nation_from_pending_peace_offer(offer);
3449 dcon::nation_id target = state.world.peace_offer_get_target(offer);
3452 auto war = state.world.peace_offer_get_war_from_war_settlement(offer);
3456 [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) {
3457 text::substitution_map sub;
3458 text::add_to_substitution_map(sub, text::variable_type::order, std::string_view(
""));
3459 text::add_to_substitution_map(sub, text::variable_type::second, text::get_adjective(state, pd));
3460 text::add_to_substitution_map(sub, text::variable_type::second_country, pd);
3461 text::add_to_substitution_map(sub, text::variable_type::first, text::get_adjective(state, pa));
3462 text::add_to_substitution_map(sub, text::variable_type::third, tag);
3463 text::add_to_substitution_map(sub, text::variable_type::state, st);
3465 std::string resolved_war_name = text::resolve_string_substitution(state, name, sub);
3466 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});
3468 "msg_peace_offer_rejected_title",
3469 target, from, dcon::nation_id{},
3483 state.world.peace_offer_set_war_from_war_settlement(offer, dcon::war_id{});
3484 state.world.peace_offer_set_is_crisis_offer(offer,
false);
3488 for(
auto wg : state.world.in_wargoal) {
3489 auto war = wg.get_war_from_wargoals_attached();
3494 auto role = attacker_goal ? war_role::attacker : war_role::defender;
3505 auto bits = wg.get_type().get_type_bits();
3506 if((bits & (cb_flag::po_annex | cb_flag::po_transfer_provinces | cb_flag::po_demand_state)) != 0) {
3507 float total_count = 0.0f;
3508 float occupied = 0.0f;
3509 if(wg.get_associated_state()) {
3510 for(
auto prv : wg.get_associated_state().get_abstract_state_membership()) {
3511 if(prv.get_province().get_nation_from_province_ownership() == wg.get_target_nation()) {
3513 if(
get_role(state, war, prv.get_province().get_nation_from_province_control()) == role) {
3518 }
else if((bits & cb_flag::po_annex) != 0) {
3519 for(
auto prv : wg.get_target_nation().get_province_ownership()) {
3521 if(
get_role(state, war, prv.get_province().get_nation_from_province_control()) == role) {
3525 }
else if(
auto allowed_states = wg.get_type().get_allowed_states(); allowed_states) {
3526 auto from_slot = wg.get_secondary_nation().id ? wg.get_secondary_nation().id : wg.get_associated_tag().get_nation_from_identity_holder().id;
3527 bool is_lib = (bits & cb_flag::po_transfer_provinces) != 0;
3528 for(
auto st : wg.get_target_nation().get_state_ownership()) {
3533 if(get_role(state, war, state.world.province_get_nation_from_province_control(prv)) == role) {
3541 if(total_count > 0.0f) {
3542 float fraction = occupied / total_count;
3543 if(fraction >= state.defines.tws_fulfilled_idle_space || (wg.get_ticking_war_score() < 0 && occupied > 0.0f)) {
3544 wg.get_ticking_war_score() += state.defines.tws_fulfilled_speed * fraction;
3545 }
else if(occupied == 0.0f) {
3546 if(wg.get_ticking_war_score() > 0.0f || war.get_start_date() + int32_t(state.defines.tws_grace_period_days) <= state.current_date) {
3547 wg.get_ticking_war_score() -= state.defines.tws_not_fulfilled_speed;
3553 if(wg.get_type().get_tws_battle_factor() > 0) {
3566 if(war.get_number_of_battles() >= uint16_t(state.defines.tws_battle_min_count)) {
3570 ratio = war.get_defender_battle_score() > 0.0f ? war.get_attacker_battle_score() / war.get_defender_battle_score() : 10.0f;
3572 ratio = war.get_attacker_battle_score() > 0.0f ? war.get_defender_battle_score() / war.get_attacker_battle_score() : 10.0f;
3574 if(ratio >= wg.get_type().get_tws_battle_factor()) {
3575 auto effective_percentage = std::min(ratio / state.defines.tws_battle_max_aspect, 1.0f);
3576 wg.get_ticking_war_score() += state.defines.tws_fulfilled_speed * effective_percentage;
3577 }
else if(ratio <= 1.0f / wg.get_type().get_tws_battle_factor() && ratio > 0.0f) {
3578 auto effective_percentage = std::min(1.0f / (ratio * state.defines.tws_battle_max_aspect), 1.0f);
3579 wg.get_ticking_war_score() -= state.defines.tws_fulfilled_speed * effective_percentage;
3580 }
else if(ratio == 0.0f) {
3581 wg.get_ticking_war_score() -= state.defines.tws_fulfilled_speed;
3585 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());
3587 wg.get_ticking_war_score() =
3588 std::clamp(wg.get_ticking_war_score(), -
float(max_score),
float(max_score));
3592float primary_warscore_from_blockades(
sys::state& state, dcon::war_id w) {
3593 auto pattacker = state.world.war_get_primary_attacker(w);
3594 auto pdefender = state.world.war_get_primary_defender(w);
3596 auto d_cpc = state.world.nation_get_central_ports(pdefender);
3597 int32_t d_blockaded_in_war = 0;
3598 for(
auto p : state.world.nation_get_province_ownership(pdefender)) {
3600 for(
auto v : state.world.province_get_navy_location(p.get_province().get_port_to())) {
3601 if(!v.get_navy().get_is_retreating() && !v.get_navy().get_battle_from_navy_battle_participation()) {
3603 ++d_blockaded_in_war;
3610 auto def_b_frac = std::clamp(d_cpc > 0 ?
float(d_blockaded_in_war) /
float(d_cpc) : 0.0f, 0.0f, 1.0f);
3612 int32_t a_blockaded_in_war = 0;
3613 for(
auto p :
state.world.nation_get_province_ownership(pattacker)) {
3615 for(
auto v :
state.world.province_get_navy_location(p.get_province().get_port_to())) {
3616 if(!v.get_navy().get_is_retreating() && !v.get_navy().get_battle_from_navy_battle_participation()) {
3618 ++a_blockaded_in_war;
3625 auto a_cpc =
state.world.nation_get_central_ports(pattacker);
3626 auto att_b_frac = std::clamp(a_cpc > 0 ?
float(a_blockaded_in_war) /
float(a_cpc) : 0.0f, 0.0f, 1.0f);
3628 return 25.0f * (def_b_frac - att_b_frac);
3631float primary_warscore(
sys::state& state, dcon::war_id w) {
3633 primary_warscore_from_occupation(state, w)
3634 + primary_warscore_from_battles(state, w)
3635 + primary_warscore_from_blockades(state, w)
3636 + primary_warscore_from_war_goals(state, w), -100.0f, 100.0f);
3639float primary_warscore_from_occupation(
sys::state& state, dcon::war_id w) {
3642 auto pattacker = state.world.war_get_primary_attacker(w);
3643 auto pdefender = state.world.war_get_primary_defender(w);
3645 int32_t sum_attacker_prov_values = 0;
3646 int32_t sum_attacker_occupied_values = 0;
3647 for(
auto prv : state.world.nation_get_province_ownership(pattacker)) {
3648 auto v = province_point_cost(state, prv.get_province(), pattacker);
3649 sum_attacker_prov_values += v;
3650 if(get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::defender)
3651 sum_attacker_occupied_values += v;
3654 int32_t sum_defender_prov_values = 0;
3655 int32_t sum_defender_occupied_values = 0;
3656 for(
auto prv :
state.world.nation_get_province_ownership(pdefender)) {
3658 sum_defender_prov_values += v;
3659 if(
get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::attacker)
3660 sum_defender_occupied_values += v;
3663 if(sum_defender_prov_values > 0)
3664 total += (float(sum_defender_occupied_values) * 100.0f) /
float(sum_defender_prov_values);
3665 if(sum_attacker_prov_values > 0)
3666 total -= (float(sum_attacker_occupied_values) * 100.0f) /
float(sum_attacker_prov_values);
3670float primary_warscore_from_battles(
sys::state& state, dcon::war_id w) {
3671 return std::clamp(state.world.war_get_attacker_battle_score(w) - state.world.war_get_defender_battle_score(w),
3672 -state.defines.max_warscore_from_battles, state.defines.max_warscore_from_battles);
3674float primary_warscore_from_war_goals(
sys::state& state, dcon::war_id w) {
3677 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
3678 if(is_attacker(state, w, wg.get_wargoal().get_added_by())) {
3679 total += wg.get_wargoal().get_ticking_war_score();
3681 total -= wg.get_wargoal().get_ticking_war_score();
3688float directed_warscore(
sys::state& state, dcon::war_id w, dcon::nation_id primary, dcon::nation_id secondary) {
3691 auto is_pattacker = state.world.war_get_primary_attacker(w) == primary;
3692 auto is_pdefender = state.world.war_get_primary_defender(w) == primary;
3694 auto is_tpattacker = state.world.war_get_primary_attacker(w) == secondary;
3695 auto is_tpdefender = state.world.war_get_primary_defender(w) == secondary;
3697 if(is_pattacker && is_tpdefender)
3698 return primary_warscore(state, w);
3699 if(is_pdefender && is_tpattacker)
3700 return -primary_warscore(state, w);
3702 int32_t sum_attacker_prov_values = 0;
3703 int32_t sum_attacker_occupied_values = 0;
3704 for(
auto prv : state.world.nation_get_province_ownership(primary)) {
3705 auto v = province_point_cost(state, prv.get_province(), primary);
3706 sum_attacker_prov_values += v;
3709 if(get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::attacker)
3710 sum_attacker_occupied_values += v;
3711 }
else if(is_tpdefender) {
3712 if(get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::defender)
3713 sum_attacker_occupied_values += v;
3715 if(prv.get_province().get_nation_from_province_control() == secondary)
3716 sum_attacker_occupied_values += v;
3720 int32_t sum_defender_prov_values = 0;
3721 int32_t sum_defender_occupied_values = 0;
3722 for(
auto prv :
state.world.nation_get_province_ownership(secondary)) {
3724 sum_defender_prov_values += v;
3727 if(
get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::attacker)
3728 sum_defender_occupied_values += v;
3729 }
else if(is_pdefender) {
3730 if(
get_role(state, w, prv.get_province().get_nation_from_province_control()) == war_role::defender)
3731 sum_defender_occupied_values += v;
3733 if(prv.get_province().get_nation_from_province_control() == primary)
3734 sum_defender_occupied_values += v;
3738 if(sum_defender_prov_values > 0)
3739 total += (float(sum_defender_occupied_values) * 100.0f) /
float(sum_defender_prov_values);
3740 if(sum_attacker_prov_values > 0)
3741 total -= (float(sum_attacker_occupied_values) * 100.0f) /
float(sum_attacker_prov_values);
3743 for(
auto wg :
state.world.war_get_wargoals_attached(w)) {
3744 if((wg.get_wargoal().get_added_by() == primary || is_pattacker || is_pdefender)
3745 && wg.get_wargoal().get_target_nation() == secondary) {
3747 total += wg.get_wargoal().get_ticking_war_score();
3748 }
else if(wg.get_wargoal().get_added_by() == secondary
3749 && (wg.get_wargoal().get_target_nation() ==
primary || is_pattacker || is_pdefender)) {
3751 total -= wg.get_wargoal().get_ticking_war_score();
3752 }
else if(wg.get_wargoal().get_added_by() ==
primary
3753 && (wg.get_wargoal().get_target_nation() == secondary || is_tpattacker || is_tpdefender)) {
3755 total += wg.get_wargoal().get_ticking_war_score();
3756 }
else if((wg.get_wargoal().get_added_by() == secondary || is_tpattacker || is_tpdefender)
3757 && (wg.get_wargoal().get_target_nation() ==
primary)) {
3759 total -= wg.get_wargoal().get_ticking_war_score();
3763 auto d_cpc =
state.world.nation_get_central_ports(secondary);
3764 int32_t d_blockaded_in_war = 0;
3765 for(
auto p :
state.world.nation_get_province_ownership(secondary)) {
3767 for(
auto v :
state.world.province_get_navy_location(p.get_province().get_port_to())) {
3768 if(!v.get_navy().get_is_retreating() && !v.get_navy().get_battle_from_navy_battle_participation()) {
3771 if(
get_role(state, w, v.get_navy().get_controller_from_navy_control()) == war_role::attacker) {
3772 ++d_blockaded_in_war;
3775 }
else if(is_pdefender) {
3776 if(
get_role(state, w, v.get_navy().get_controller_from_navy_control()) == war_role::defender) {
3777 ++d_blockaded_in_war;
3781 if(v.get_navy().get_controller_from_navy_control() ==
primary) {
3782 ++d_blockaded_in_war;
3790 auto def_b_frac = std::clamp(d_cpc > 0 ?
float(d_blockaded_in_war) /
float(d_cpc) : 0.0f, 0.0f, 1.0f);
3792 int32_t a_blockaded_in_war = 0;
3793 for(
auto p :
state.world.nation_get_province_ownership(primary)) {
3795 for(
auto v :
state.world.province_get_navy_location(p.get_province().get_port_to())) {
3796 if(!v.get_navy().get_is_retreating() && !v.get_navy().get_battle_from_navy_battle_participation()) {
3798 if(
get_role(state, w, v.get_navy().get_controller_from_navy_control()) == war_role::attacker) {
3799 ++a_blockaded_in_war;
3802 }
else if(is_tpdefender) {
3803 if(
get_role(state, w, v.get_navy().get_controller_from_navy_control()) == war_role::defender) {
3804 ++a_blockaded_in_war;
3808 if(v.get_navy().get_controller_from_navy_control() == secondary) {
3809 ++a_blockaded_in_war;
3817 auto a_cpc =
state.world.nation_get_central_ports(primary);
3818 auto att_b_frac = std::clamp(a_cpc > 0 ?
float(a_blockaded_in_war) /
float(a_cpc) : 0.0f, 0.0f, 1.0f);
3820 total += 25.0f * (def_b_frac - att_b_frac);
3822 return std::clamp(total, 0.0f, 100.0f);
3825bool can_embark_onto_sea_tile(
sys::state& state, dcon::nation_id from, dcon::province_id p, dcon::army_id a) {
3826 int32_t max_cap = 0;
3827 for(
auto n : state.world.province_get_navy_location(p)) {
3828 if(n.get_navy().get_controller_from_navy_control() == from &&
3829 !
bool(n.get_navy().get_battle_from_navy_battle_participation())) {
3830 max_cap = std::max(free_transport_capacity(state, n.get_navy()), max_cap);
3833 auto regs =
state.world.army_get_army_membership(a);
3834 return int32_t(regs.end() - regs.begin()) <= max_cap;
3837dcon::navy_id find_embark_target(
sys::state& state, dcon::nation_id from, dcon::province_id p, dcon::army_id a) {
3838 auto regs = state.world.army_get_army_membership(a);
3839 int32_t count = int32_t(regs.end() - regs.begin());
3841 int32_t max_cap = 0;
3842 for(
auto n : state.world.province_get_navy_location(p)) {
3843 if(n.get_navy().get_controller_from_navy_control() == from) {
3844 if(free_transport_capacity(state, n.get_navy()) >= count)
3845 return n.get_navy();
3848 return dcon::navy_id{};
3851float effective_army_speed(
sys::state& state, dcon::army_id a) {
3852 auto owner = state.world.army_get_controller_from_army_control(a);
3854 owner = state.world.rebel_faction_get_ruler_from_rebellion_within(state.world.army_get_controller_from_army_rebel_control(a));
3856 float min_speed = 10000.0f;
3857 for(
auto reg : state.world.army_get_army_membership(a)) {
3858 auto reg_speed = state.world.nation_get_unit_stats(owner, reg.get_regiment().get_type()).maximum_speed;
3859 min_speed = std::min(min_speed, reg_speed);
3867 auto leader =
state.world.army_get_general_from_army_leadership(a);
3868 auto bg =
state.world.leader_get_background(leader);
3869 auto per =
state.world.leader_get_personality(leader);
3870 auto leader_move =
state.world.leader_trait_get_speed(bg) +
state.world.leader_trait_get_speed(per);
3871 return min_speed * (
state.world.army_get_is_retreating(a) ? 2.0f : 1.0f) *
3874 (leader_move + 1.0f);
3876float effective_navy_speed(
sys::state& state, dcon::navy_id n) {
3877 auto owner = state.world.navy_get_controller_from_navy_control(n);
3879 float min_speed = 10000.0f;
3880 for(
auto reg : state.world.navy_get_navy_membership(n)) {
3881 auto reg_speed = state.world.nation_get_unit_stats(owner, reg.get_ship().get_type()).maximum_speed;
3882 min_speed = std::min(min_speed, reg_speed);
3885 auto leader =
state.world.navy_get_admiral_from_navy_leadership(n);
3886 auto bg =
state.world.leader_get_background(leader);
3887 auto per =
state.world.leader_get_personality(leader);
3888 auto leader_move =
state.world.leader_trait_get_speed(bg) +
state.world.leader_trait_get_speed(per);
3889 return min_speed * (
state.world.navy_get_is_retreating(n) ? 2.0f : 1.0f) * (leader_move + 1.0f);
3893 auto current_location = state.world.army_get_location_from_army_location(a);
3894 auto adj = state.world.get_province_adjacency_by_province_pair(current_location, p);
3896 float sum_mods = state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::movement_cost) +
3897 state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::movement_cost);
3898 float effective_distance = std::max(0.1f, distance * (sum_mods + 1.0f));
3900 float effective_speed = effective_army_speed(state, a);
3902 int32_t days = effective_speed > 0.0f ? int32_t(std::ceil(effective_distance / effective_speed)) : 50;
3904 return state.current_date + days;
3907 auto current_location = state.world.navy_get_location_from_navy_location(n);
3908 auto adj = state.world.get_province_adjacency_by_province_pair(current_location, p);
3910 float sum_mods = state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::movement_cost) +
3911 state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::movement_cost);
3912 float effective_distance = std::max(0.1f, distance * (sum_mods + 1.0f));
3914 float effective_speed = effective_navy_speed(state, n);
3916 int32_t days = effective_speed > 0.0f ? int32_t(std::ceil(effective_distance / effective_speed)) : 50;
3917 return state.current_date + days;
3920void add_army_to_battle(
sys::state& state, dcon::army_id a, dcon::land_battle_id b, war_role r) {
3921 assert(state.world.army_is_valid(a));
3922 bool battle_attacker = (r == war_role::attacker) == state.world.land_battle_get_war_attacker_is_attacker(b);
3923 if(battle_attacker) {
3924 if(!state.world.land_battle_get_general_from_attacking_general(b)) {
3925 state.world.land_battle_set_general_from_attacking_general(b, state.world.army_get_general_from_army_leadership(a));
3928 auto reserves = state.world.land_battle_get_reserves(b);
3929 for(
auto reg : state.world.army_get_army_membership(a)) {
3930 if(reg.get_regiment().get_strength() <= 0.0f)
3933 auto type = state.military_definitions.unit_base_definitions[reg.get_regiment().get_type()].type;
3935 case unit_type::infantry:
3937 reserve_regiment{reg.get_regiment().id, reserve_regiment::is_attacking | reserve_regiment::type_infantry});
3938 state.world.land_battle_get_attacker_infantry(b) += reg.get_regiment().get_strength();
3940 case unit_type::cavalry:
3942 reserve_regiment{reg.get_regiment().id, reserve_regiment::is_attacking | reserve_regiment::type_cavalry});
3943 state.world.land_battle_get_attacker_cav(b) += reg.get_regiment().get_strength();
3945 case unit_type::special:
3946 case unit_type::support:
3948 reserve_regiment{reg.get_regiment().id, reserve_regiment::is_attacking | reserve_regiment::type_support});
3949 state.world.land_battle_get_attacker_support(b) += reg.get_regiment().get_strength();
3956 auto& def_bonus =
state.world.land_battle_get_defender_bonus(b);
3958 auto new_dig_in = std::min(prev_dig_in,
state.world.army_get_dig_in(a) & defender_bonus_dig_in_mask);
3959 def_bonus &= ~defender_bonus_dig_in_mask;
3960 def_bonus |= new_dig_in;
3962 if(!
state.world.land_battle_get_general_from_defending_general(b)) {
3963 state.world.land_battle_set_general_from_defending_general(b,
state.world.army_get_general_from_army_leadership(a));
3965 auto reserves =
state.world.land_battle_get_reserves(b);
3966 for(
auto reg :
state.world.army_get_army_membership(a)) {
3967 if(reg.get_regiment().get_strength() <= 0.0f)
3970 auto type =
state.military_definitions.unit_base_definitions[reg.get_regiment().get_type()].type;
3972 case unit_type::infantry:
3973 reserves.push_back(reserve_regiment{reg.get_regiment().
id, reserve_regiment::type_infantry});
3974 state.world.land_battle_get_defender_infantry(b) += reg.get_regiment().get_strength();
3976 case unit_type::cavalry:
3977 reserves.push_back(reserve_regiment{reg.get_regiment().
id, reserve_regiment::type_cavalry});
3978 state.world.land_battle_get_defender_cav(b) += reg.get_regiment().get_strength();
3980 case unit_type::special:
3981 case unit_type::support:
3982 reserves.push_back(reserve_regiment{reg.get_regiment().
id, reserve_regiment::type_support});
3983 state.world.land_battle_get_defender_support(b) += reg.get_regiment().get_strength();
3991 state.world.army_set_battle_from_army_battle_participation(a, b);
3995void army_arrives_in_province(
sys::state& state, dcon::army_id a, dcon::province_id p, crossing_type crossing, dcon::land_battle_id from) {
3996 assert(state.world.army_is_valid(a));
3997 assert(!state.world.army_get_battle_from_army_battle_participation(a));
3999 state.world.army_set_location_from_army_location(a, p);
4000 auto regs = state.world.army_get_army_membership(a);
4001 if(!state.world.army_get_black_flag(a) && !state.world.army_get_is_retreating(a) && regs.begin() != regs.end()) {
4002 auto owner_nation = state.world.army_get_controller_from_army_control(a);
4005 for(
auto b : state.world.province_get_land_battle_location(p)) {
4006 if(b.get_battle() != from) {
4007 auto battle_war = b.get_battle().get_war_from_land_battle_in_war();
4009 auto owner_role = get_role(state, battle_war, owner_nation);
4010 if(owner_role != war_role::none) {
4011 add_army_to_battle(state, a, b.get_battle(), owner_role);
4015 add_army_to_battle(state, a, b.get_battle(),
bool(owner_nation) ? war_role::defender : war_role::attacker);
4022 dcon::land_battle_id gather_to_battle;
4023 dcon::war_id battle_in_war;
4025 for(
auto o : state.world.province_get_army_location(p)) {
4026 if(o.get_army() == a)
4028 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())
4031 auto other_nation = o.get_army().get_controller_from_army_control();
4033 if(
bool(owner_nation) !=
bool(other_nation)) {
4034 auto new_battle = fatten(state.world, state.world.create_land_battle());
4035 new_battle.set_war_attacker_is_attacker(!
bool(owner_nation));
4036 new_battle.set_start_date(state.current_date);
4037 new_battle.set_location_from_land_battle_location(p);
4038 new_battle.set_dice_rolls(make_dice_rolls(state,
uint32_t(new_battle.id.value)));
4040 uint8_t flags = defender_bonus_dig_in_mask;
4041 if(crossing == crossing_type::river)
4042 flags |= defender_bonus_crossing_river;
4043 if(crossing == crossing_type::sea)
4044 flags |= defender_bonus_crossing_sea;
4045 new_battle.set_defender_bonus(flags);
4047 auto cw_a = state.defines.base_combat_width +
4048 state.world.nation_get_modifier_values(owner_nation, sys::national_mod_offsets::combat_width);
4049 auto cw_b = state.defines.base_combat_width +
4050 state.world.nation_get_modifier_values(other_nation, sys::national_mod_offsets::combat_width);
4051 new_battle.set_combat_width(
uint8_t(
4052 std::clamp(int32_t(std::min(cw_a, cw_b) *
4053 (state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::combat_width) + 1.0f)),
4056 add_army_to_battle(state, a, new_battle, !
bool(owner_nation) ? war_role::attacker : war_role::defender);
4057 add_army_to_battle(state, o.get_army(), new_battle,
bool(owner_nation) ? war_role::attacker : war_role::defender);
4059 gather_to_battle = new_battle.id;
4061 }
else if(
auto par = internal_find_war_between(state, owner_nation, other_nation); par.
role != war_role::none) {
4062 auto new_battle = fatten(state.world, state.world.create_land_battle());
4063 new_battle.set_war_attacker_is_attacker(par.role == war_role::attacker);
4064 new_battle.set_start_date(state.current_date);
4065 new_battle.set_war_from_land_battle_in_war(par.w);
4066 new_battle.set_location_from_land_battle_location(p);
4067 new_battle.set_dice_rolls(make_dice_rolls(state,
uint32_t(new_battle.id.value)));
4069 uint8_t flags = defender_bonus_dig_in_mask;
4070 if(crossing == crossing_type::river)
4071 flags |= defender_bonus_crossing_river;
4072 if(crossing == crossing_type::sea)
4073 flags |= defender_bonus_crossing_sea;
4074 new_battle.set_defender_bonus(flags);
4076 auto cw_a = state.defines.base_combat_width +
4077 state.world.nation_get_modifier_values(owner_nation, sys::national_mod_offsets::combat_width);
4078 auto cw_b = state.defines.base_combat_width +
4079 state.world.nation_get_modifier_values(other_nation, sys::national_mod_offsets::combat_width);
4080 new_battle.set_combat_width(
uint8_t(
4081 std::clamp(int32_t(std::min(cw_a, cw_b) *
4082 (state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::combat_width) + 1.0f)),
4085 add_army_to_battle(state, a, new_battle, par.role);
4086 add_army_to_battle(state, o.get_army(), new_battle, par.role == war_role::attacker ? war_role::defender : war_role::attacker);
4088 gather_to_battle = new_battle.id;
4089 battle_in_war = par.w;
4095 if(gather_to_battle) {
4096 for(
auto o : state.world.province_get_army_location(p)) {
4097 if(o.get_army() == a)
4099 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())
4102 auto other_nation = o.get_army().get_controller_from_army_control();
4104 if(
auto role = get_role(state, battle_in_war, other_nation); role != war_role::none) {
4105 add_army_to_battle(state, o.get_army(), gather_to_battle, role);
4108 add_army_to_battle(state, o.get_army(), gather_to_battle, !
bool(other_nation) ? war_role::attacker : war_role::defender);
4113 for(
auto par : state.world.war_get_war_participant(battle_in_war)) {
4114 if(par.get_nation().get_is_player_controlled() ==
false)
4117 }
else if(state.world.nation_get_is_player_controlled(owner_nation) ==
false) {
4124void add_navy_to_battle(
sys::state& state, dcon::navy_id n, dcon::naval_battle_id b, war_role r) {
4125 assert(state.world.navy_is_valid(n));
4126 bool battle_attacker = (r == war_role::attacker) == state.world.naval_battle_get_war_attacker_is_attacker(b);
4127 if(battle_attacker) {
4129 if(!state.world.naval_battle_get_admiral_from_attacking_admiral(b)) {
4130 state.world.naval_battle_set_admiral_from_attacking_admiral(b, state.world.navy_get_admiral_from_navy_leadership(n));
4133 auto slots = state.world.naval_battle_get_slots(b);
4134 for(
auto ship : state.world.navy_get_navy_membership(n)) {
4135 if(ship.get_ship().get_strength() <= 0.0f)
4138 auto type = state.military_definitions.unit_base_definitions[ship.get_ship().get_type()].type;
4140 case unit_type::big_ship:
4141 slots.push_back(ship_in_battle{ship.get_ship().id, 0,
4142 1000 | ship_in_battle::mode_seeking | ship_in_battle::is_attacking | ship_in_battle::type_big});
4143 state.world.naval_battle_get_attacker_big_ships(b)++;
4145 case unit_type::light_ship:
4146 slots.push_back(ship_in_battle{ship.get_ship().id, 0,
4147 1000 | ship_in_battle::mode_seeking | ship_in_battle::is_attacking | ship_in_battle::type_small});
4148 state.world.naval_battle_get_attacker_small_ships(b)++;
4150 case unit_type::transport:
4151 slots.push_back(ship_in_battle{ship.get_ship().id, 0,
4152 1000 | ship_in_battle::mode_seeking | ship_in_battle::is_attacking | ship_in_battle::type_transport});
4153 state.world.naval_battle_get_attacker_transport_ships(b)++;
4160 if(!
state.world.naval_battle_get_admiral_from_defending_admiral(b)) {
4161 state.world.naval_battle_set_admiral_from_defending_admiral(b,
state.world.navy_get_admiral_from_navy_leadership(n));
4163 auto slots =
state.world.naval_battle_get_slots(b);
4164 for(
auto ship :
state.world.navy_get_navy_membership(n)) {
4165 if(ship.get_ship().get_strength() <= 0.0f)
4168 auto type =
state.military_definitions.unit_base_definitions[ship.get_ship().get_type()].type;
4170 case unit_type::big_ship:
4171 slots.push_back(ship_in_battle{ship.get_ship().
id, 0, 1000 | ship_in_battle::mode_seeking | ship_in_battle::type_big});
4172 state.world.naval_battle_get_defender_big_ships(b)++;
4174 case unit_type::light_ship:
4175 slots.push_back(ship_in_battle{ship.get_ship().
id, 0, 1000 | ship_in_battle::mode_seeking | ship_in_battle::type_small});
4176 state.world.naval_battle_get_defender_small_ships(b)++;
4178 case unit_type::transport:
4180 ship_in_battle{ship.get_ship().
id, 0, 1000 | ship_in_battle::mode_seeking | ship_in_battle::type_transport});
4181 state.world.naval_battle_get_defender_transport_ships(b)++;
4189 state.world.navy_set_battle_from_navy_battle_participation(n, b);
4192 for(
auto em :
state.world.navy_get_army_transport(n)) {
4193 em.get_army().set_arrival_time(
sys::date{});
4197bool retreat(
sys::state& state, dcon::navy_id n) {
4198 auto province_start = state.world.navy_get_location_from_navy_location(n);
4199 auto nation_controller = state.world.navy_get_controller_from_navy_control(n);
4201 if(!nation_controller)
4205 if(retreat_path.size() > 0) {
4206 state.world.navy_set_is_retreating(n,
true);
4207 auto existing_path = state.world.navy_get_path(n);
4208 existing_path.load_range(retreat_path.data(), retreat_path.data() + retreat_path.size());
4210 state.world.navy_set_arrival_time(n, arrival_time_to(state, n, retreat_path.back()));
4212 for(
auto em : state.world.navy_get_army_transport(n)) {
4213 em.get_army().get_path().clear();
4221bool retreat(
sys::state& state, dcon::army_id n) {
4222 auto province_start = state.world.army_get_location_from_army_location(n);
4223 auto nation_controller = state.world.army_get_controller_from_army_control(n);
4225 if(!nation_controller)
4229 if(retreat_path.size() > 0) {
4230 state.world.army_set_is_retreating(n,
true);
4231 auto existing_path = state.world.army_get_path(n);
4232 existing_path.load_range(retreat_path.data(), retreat_path.data() + retreat_path.size());
4234 state.world.army_set_arrival_time(n, arrival_time_to(state, n, retreat_path.back()));
4235 state.world.army_set_dig_in(n, 0);
4242dcon::nation_id get_naval_battle_lead_attacker(
sys::state& state, dcon::naval_battle_id b) {
4244 state.world.leader_get_nation_from_leader_loyalty(state.world.naval_battle_get_admiral_from_attacking_admiral(b));
4248 auto war = state.world.naval_battle_get_war_from_naval_battle_in_war(b);
4249 bool war_attackers = state.world.naval_battle_get_war_attacker_is_attacker(b);
4251 for(
auto nbp : state.world.naval_battle_get_navy_battle_participation(b)) {
4252 if(war_attackers && is_attacker(state, war, nbp.get_navy().get_controller_from_navy_control())) {
4253 return nbp.get_navy().get_controller_from_navy_control();
4254 }
else if(!war_attackers && !is_attacker(state, war, nbp.get_navy().get_controller_from_navy_control())) {
4255 return nbp.get_navy().get_controller_from_navy_control();
4259 return dcon::nation_id{};
4262dcon::nation_id get_naval_battle_lead_defender(
sys::state& state, dcon::naval_battle_id b) {
4264 state.world.leader_get_nation_from_leader_loyalty(state.world.naval_battle_get_admiral_from_defending_admiral(b));
4268 auto war = state.world.naval_battle_get_war_from_naval_battle_in_war(b);
4269 bool war_attackers = state.world.naval_battle_get_war_attacker_is_attacker(b);
4271 for(
auto nbp : state.world.naval_battle_get_navy_battle_participation(b)) {
4272 if(!war_attackers && is_attacker(state, war, nbp.get_navy().get_controller_from_navy_control())) {
4273 return nbp.get_navy().get_controller_from_navy_control();
4274 }
else if(war_attackers && !is_attacker(state, war, nbp.get_navy().get_controller_from_navy_control())) {
4275 return nbp.get_navy().get_controller_from_navy_control();
4279 return dcon::nation_id{};
4282dcon::nation_id get_land_battle_lead_attacker(
sys::state& state, dcon::land_battle_id b) {
4284 state.world.leader_get_nation_from_leader_loyalty(state.world.land_battle_get_general_from_attacking_general(b));
4288 auto war = state.world.land_battle_get_war_from_land_battle_in_war(b);
4289 bool war_attackers = state.world.land_battle_get_war_attacker_is_attacker(b);
4293 return dcon::nation_id{};
4295 for(
auto nbp : state.world.land_battle_get_army_battle_participation(b)) {
4296 auto c = nbp.get_army().get_controller_from_army_control();
4302 for(
auto nbp :
state.world.land_battle_get_army_battle_participation(b)) {
4303 if(war_attackers &&
is_attacker(state, war, nbp.get_army().get_controller_from_army_control())) {
4304 return nbp.get_army().get_controller_from_army_control();
4305 }
else if(!war_attackers && !
is_attacker(state, war, nbp.get_army().get_controller_from_army_control())) {
4306 return nbp.get_army().get_controller_from_army_control();
4310 return dcon::nation_id{};
4313dcon::nation_id get_land_battle_lead_defender(
sys::state& state, dcon::land_battle_id b) {
4315 state.world.leader_get_nation_from_leader_loyalty(state.world.land_battle_get_general_from_defending_general(b));
4319 auto war = state.world.land_battle_get_war_from_land_battle_in_war(b);
4320 bool war_attackers = state.world.land_battle_get_war_attacker_is_attacker(b);
4324 return dcon::nation_id{};
4326 for(
auto nbp : state.world.land_battle_get_army_battle_participation(b)) {
4327 auto c = nbp.get_army().get_controller_from_army_control();
4333 for(
auto nbp :
state.world.land_battle_get_army_battle_participation(b)) {
4334 if(!war_attackers &&
is_attacker(state, war, nbp.get_army().get_controller_from_army_control())) {
4335 return nbp.get_army().get_controller_from_army_control();
4336 }
else if(war_attackers && !
is_attacker(state, war, nbp.get_army().get_controller_from_army_control())) {
4337 return nbp.get_army().get_controller_from_army_control();
4341 return dcon::nation_id{};
4344float get_leader_select_score(
sys::state& state, dcon::leader_id l) {
4350 auto per = state.world.leader_get_personality(l);
4351 auto bak = state.world.leader_get_background(l);
4353 auto org = state.world.leader_trait_get_organisation(per) + state.world.leader_trait_get_organisation(bak);
4354 auto atk = state.world.leader_trait_get_attack(per) + state.world.leader_trait_get_attack(bak);
4355 auto def = state.world.leader_trait_get_defense(per) + state.world.leader_trait_get_defense(bak);
4356 auto spd = state.world.leader_trait_get_speed(per) + state.world.leader_trait_get_speed(bak);
4357 auto mor = state.world.leader_trait_get_morale(per) + state.world.leader_trait_get_morale(bak);
4358 auto att = state.world.leader_trait_get_experience(per) + state.world.leader_trait_get_experience(bak);
4359 auto rel = state.world.leader_trait_get_reliability(per) + state.world.leader_trait_get_reliability(bak);
4360 auto exp = state.world.leader_trait_get_experience(per) + state.world.leader_trait_get_experience(bak);
4361 auto rec = state.world.leader_trait_get_reconnaissance(per) + state.world.leader_trait_get_reconnaissance(bak);
4362 auto lp = state.world.leader_get_prestige(l);
4363 return (org * 5.f + atk + def + mor + spd + att + exp / 2.f + rec / 5.f + rel / 5.f) * (lp + 1.f);
4365void update_battle_leaders(
sys::state& state, dcon::land_battle_id b) {
4366 auto la = get_land_battle_lead_attacker(state, b);
4367 dcon::leader_id a_lid;
4368 float a_score = 0.f;
4369 auto ld = get_land_battle_lead_defender(state, b);
4370 dcon::leader_id d_lid;
4371 float d_score = 0.f;
4372 for(
const auto a : state.world.land_battle_get_army_battle_participation(b)) {
4373 auto l = a.get_army().get_general_from_army_leadership();
4374 auto score = get_leader_select_score(state, l);
4375 if(a.get_army().get_controller_from_army_control() == la) {
4376 if(score > a_score) {
4380 }
else if(a.get_army().get_controller_from_army_control() == ld) {
4381 if(score > d_score) {
4387 auto aa =
state.world.land_battle_get_attacking_general(b);
4388 state.world.attacking_general_set_general(aa, a_lid);
4389 auto ab =
state.world.land_battle_get_defending_general(b);
4390 state.world.defending_general_set_general(ab, d_lid);
4392void update_battle_leaders(
sys::state& state, dcon::naval_battle_id b) {
4393 auto la = get_naval_battle_lead_attacker(state, b);
4394 dcon::leader_id a_lid;
4395 float a_score = 0.f;
4396 auto ld = get_naval_battle_lead_defender(state, b);
4397 dcon::leader_id d_lid;
4398 float d_score = 0.f;
4399 for(
const auto a : state.world.naval_battle_get_navy_battle_participation(b)) {
4400 auto l = a.get_navy().get_admiral_from_navy_leadership();
4401 auto score = get_leader_select_score(state, l);
4402 if(a.get_navy().get_controller_from_navy_control() == la) {
4403 if(score > a_score) {
4407 }
else if(a.get_navy().get_controller_from_navy_control() == ld) {
4408 if(score > d_score) {
4414 auto aa =
state.world.naval_battle_get_attacking_admiral(b);
4415 state.world.attacking_admiral_set_admiral(aa, a_lid);
4416 auto ab =
state.world.naval_battle_get_defending_admiral(b);
4417 state.world.defending_admiral_set_admiral(ab, d_lid);
4420void cleanup_army(
sys::state& state, dcon::army_id n) {
4421 assert(!state.world.army_get_battle_from_army_battle_participation(n));
4423 auto regs = state.world.army_get_army_membership(n);
4424 while(regs.begin() != regs.end()) {
4425 state.world.delete_regiment((*regs.begin()).get_regiment().id);
4428 auto b =
state.world.army_get_battle_from_army_battle_participation(n);
4430 state.world.army_set_is_retreating(n,
true);
4432 bool should_end =
true;
4433 auto controller =
state.world.army_get_controller_from_army_control(n);
4434 if(
bool(controller)) {
4436 bool has_other =
false;
4437 bool has_rebels =
false;
4438 for(
auto bp :
state.world.land_battle_get_army_battle_participation_as_battle(b)) {
4439 if(bp.get_army() != n) {
4441 if(
are_allied_in_war(state, controller, bp.get_army().get_controller_from_army_control())) {
4443 }
else if(bp.get_army().get_controller_from_army_rebel_control()) {
4449 if(has_other && has_rebels)
4451 }
else if(
state.world.army_get_controller_from_army_rebel_control(n)) {
4452 for(
auto bp :
state.world.land_battle_get_army_battle_participation_as_battle(b)) {
4453 if(bp.get_army() != n && bp.get_army().get_army_rebel_control()) {
4462 bool as_attacker =
state.world.land_battle_get_war_attacker_is_attacker(b);
4463 end_battle(state, b, as_attacker ? battle_result::defender_won : battle_result::attacker_won);
4467 state.world.delete_army(n);
4470void cleanup_navy(
sys::state& state, dcon::navy_id n) {
4471 assert(!state.world.navy_get_battle_from_navy_battle_participation(n));
4473 auto shps = state.world.navy_get_navy_membership(n);
4474 while(shps.begin() != shps.end()) {
4475 state.world.delete_ship((*shps.begin()).get_ship());
4477 auto em =
state.world.navy_get_army_transport(n);
4478 while(em.begin() != em.end()) {
4482 auto controller =
state.world.navy_get_controller_from_navy_control(n);
4483 auto b =
state.world.navy_get_battle_from_navy_battle_participation(n);
4485 state.world.navy_set_is_retreating(n,
true);
4486 if(b && controller) {
4487 bool should_end =
true;
4489 for(
auto bp :
state.world.naval_battle_get_navy_battle_participation_as_battle(b)) {
4490 if(bp.get_navy() != n &&
are_allied_in_war(state, controller,
state.world.navy_get_controller_from_navy_control(bp.get_navy()))) {
4495 bool as_attacker =
state.world.naval_battle_get_war_attacker_is_attacker(b);
4496 end_battle(state, b, as_attacker ? battle_result::defender_won : battle_result::attacker_won);
4500 state.world.delete_navy(n);
4503void adjust_leader_prestige(
sys::state& state, dcon::leader_id l,
float value) {
4504 auto v = state.world.leader_get_prestige(l);
4505 v = std::clamp(v + value, 0.f, 1.f);
4506 state.world.leader_set_prestige(l, v);
4508void adjust_regiment_experience(
sys::state& state, dcon::nation_id n, dcon::regiment_id l,
float value) {
4509 auto v = state.world.regiment_get_experience(l);
4511 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);
4513 v = std::clamp(v + value, min_exp, 1.f);
4515 state.world.regiment_set_experience(l, v);
4517void adjust_ship_experience(
sys::state& state, dcon::nation_id n, dcon::ship_id r,
float value) {
4518 auto v = state.world.ship_get_experience(r);
4520 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);
4522 v = std::clamp(v + value * state.defines.exp_gain_div, min_exp, 1.f);
4523 state.world.ship_set_experience(r, v);
4526void end_battle(
sys::state& state, dcon::land_battle_id b, battle_result result) {
4527 auto war = state.world.land_battle_get_war_from_land_battle_in_war(b);
4528 auto location = state.world.land_battle_get_location_from_land_battle_location(b);
4532 auto make_leaderless = [&](dcon::army_id a) {
4533 state.world.army_set_controller_from_army_control(a, dcon::nation_id{});
4534 state.world.army_set_controller_from_army_rebel_control(a, dcon::rebel_faction_id{});
4535 state.world.army_set_is_retreating(a,
true);
4541 for(
auto n :
state.world.land_battle_get_army_battle_participation(b)) {
4542 auto nation_owner =
state.world.army_get_controller_from_army_control(
n.get_army());
4544 auto role_in_war = bool(war)
4545 ?
get_role(state, war,
n.get_army().get_controller_from_army_control())
4548 bool battle_attacker = (role_in_war == war_role::attacker) ==
state.world.land_battle_get_war_attacker_is_attacker(b);
4551 if(battle_attacker && result == battle_result::defender_won) {
4553 make_leaderless(
n.get_army());
4556 make_leaderless(
n.get_army());
4558 }
else if(!battle_attacker && result == battle_result::attacker_won) {
4560 make_leaderless(
n.get_army());
4563 make_leaderless(
n.get_army());
4566 auto path =
n.get_army().get_path();
4567 if(path.size() > 0) {
4568 state.world.army_set_arrival_time(
n.get_army(),
arrival_time_to(state,
n.get_army(), path.at(path.size() - 1)));
4580 if(result != battle_result::indecisive) {
4582 state.world.war_get_number_of_battles(war)++;
4584 auto a_leader =
state.world.land_battle_get_general_from_attacking_general(b);
4585 auto b_leader =
state.world.land_battle_get_general_from_defending_general(b);
4587 if(result == battle_result::attacker_won) {
4588 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);
4589 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);
4590 auto score = std::max(0.0f, 3.0f * (total_def_loss - total_att_loss) / 10.0f);
4593 if(
state.world.land_battle_get_war_attacker_is_attacker(b)) {
4594 state.world.war_get_attacker_battle_score(war) += score;
4596 state.world.war_get_defender_battle_score(war) += score;
4601 if(a_nation && d_nation) {
4610 if(
state.local_player_nation == a_nation ||
state.local_player_nation == d_nation) {
4611 land_battle_report rep;
4612 rep.attacker_infantry_losses =
state.world.land_battle_get_attacker_infantry_lost(b);
4613 rep.attacker_infantry =
state.world.land_battle_get_attacker_infantry(b);
4614 rep.attacker_cavalry_losses =
state.world.land_battle_get_attacker_cav_lost(b);
4615 rep.attacker_cavalry =
state.world.land_battle_get_attacker_cav(b);
4616 rep.attacker_support_losses =
state.world.land_battle_get_attacker_support_lost(b);
4617 rep.attacker_support =
state.world.land_battle_get_attacker_support(b);
4619 rep.defender_infantry_losses =
state.world.land_battle_get_defender_infantry_lost(b);
4620 rep.defender_infantry =
state.world.land_battle_get_defender_infantry(b);
4621 rep.defender_cavalry_losses =
state.world.land_battle_get_defender_cav_lost(b);
4622 rep.defender_cavalry =
state.world.land_battle_get_defender_cav(b);
4623 rep.defender_support_losses =
state.world.land_battle_get_defender_support_lost(b);
4624 rep.defender_support =
state.world.land_battle_get_defender_support(b);
4626 rep.attacker_won = (
result == battle_result::attacker_won);
4630 rep.attacking_general =
state.world.land_battle_get_general_from_attacking_general(b);
4631 rep.defending_general =
state.world.land_battle_get_general_from_defending_general(b);
4633 rep.location =
state.world.land_battle_get_location_from_land_battle_location(b);
4634 rep.player_on_winning_side = bool(war)
4635 ?
is_attacker(state, war,
state.local_player_nation) ==
state.world.land_battle_get_war_attacker_is_attacker(b)
4636 : !
state.world.land_battle_get_war_attacker_is_attacker(b);
4639 if(rep.player_on_winning_side) {
4640 rep.warscore_effect = score;
4641 rep.prestige_effect = score / 50.0f;
4643 rep.warscore_effect = -score;
4644 rep.prestige_effect = -score / 50.0f;
4648 auto discard =
state.land_battle_reports.try_push(rep);
4651 }
else if(result == battle_result::defender_won) {
4652 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);
4653 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);
4654 auto score = std::max(0.0f, 3.0f * (total_att_loss - total_def_loss) / 10.0f);
4657 if(
state.world.land_battle_get_war_attacker_is_attacker(b)) {
4658 state.world.war_get_defender_battle_score(war) += score;
4660 state.world.war_get_attacker_battle_score(war) += score;
4664 if(a_nation && d_nation) {
4673 if(
state.local_player_nation == a_nation ||
state.local_player_nation == d_nation) {
4674 land_battle_report rep;
4675 rep.attacker_infantry_losses =
state.world.land_battle_get_attacker_infantry_lost(b);
4676 rep.attacker_infantry =
state.world.land_battle_get_attacker_infantry(b);
4677 rep.attacker_cavalry_losses =
state.world.land_battle_get_attacker_cav_lost(b);
4678 rep.attacker_cavalry =
state.world.land_battle_get_attacker_cav(b);
4679 rep.attacker_support_losses =
state.world.land_battle_get_attacker_support_lost(b);
4680 rep.attacker_support =
state.world.land_battle_get_attacker_support(b);
4682 rep.defender_infantry_losses =
state.world.land_battle_get_defender_infantry_lost(b);
4683 rep.defender_infantry =
state.world.land_battle_get_defender_infantry(b);
4684 rep.defender_cavalry_losses =
state.world.land_battle_get_defender_cav_lost(b);
4685 rep.defender_cavalry =
state.world.land_battle_get_defender_cav(b);
4686 rep.defender_support_losses =
state.world.land_battle_get_defender_support_lost(b);
4687 rep.defender_support =
state.world.land_battle_get_defender_support(b);
4689 rep.attacker_won = (
result == battle_result::attacker_won);
4693 rep.attacking_general =
state.world.land_battle_get_general_from_attacking_general(b);
4694 rep.defending_general =
state.world.land_battle_get_general_from_defending_general(b);
4696 rep.location =
state.world.land_battle_get_location_from_land_battle_location(b);
4697 rep.player_on_winning_side = bool(war)
4698 ?
is_attacker(state, war,
state.local_player_nation) !=
state.world.land_battle_get_war_attacker_is_attacker(b)
4699 :
state.world.land_battle_get_war_attacker_is_attacker(b);
4702 if(rep.player_on_winning_side) {
4703 rep.warscore_effect = score;
4704 rep.prestige_effect = score / 50.0f;
4706 rep.warscore_effect = -score;
4707 rep.prestige_effect = -score / 50.0f;
4710 auto discard =
state.land_battle_reports.try_push(rep);
4716 if(result != battle_result::indecisive) {
4717 auto par_range =
state.world.land_battle_get_army_battle_participation(b);
4718 while(par_range.begin() != par_range.end()) {
4719 auto n = (*par_range.begin()).get_army();
4720 n.set_battle_from_army_battle_participation(dcon::land_battle_id{});
4725 state.world.delete_land_battle(b);
4728void end_battle(
sys::state& state, dcon::naval_battle_id b, battle_result result) {
4729 auto war = state.world.naval_battle_get_war_from_naval_battle_in_war(b);
4730 auto location = state.world.naval_battle_get_location_from_naval_battle_location(b);
4735 auto a_nation = get_naval_battle_lead_attacker(state, b);
4736 auto d_nation = get_naval_battle_lead_defender(state, b);
4738 for(
auto n : state.world.naval_battle_get_navy_battle_participation(b)) {
4739 auto role_in_war = get_role(state, war, n.get_navy().get_controller_from_navy_control());
4740 bool battle_attacker = (role_in_war == war_role::attacker) == state.world.naval_battle_get_war_attacker_is_attacker(b);
4744 if(transport_cap < 0) {
4745 for(
auto em : n.get_navy().get_army_transport()) {
4746 auto em_regs = em.get_army().get_army_membership();
4747 while(em_regs.begin() != em_regs.end() && transport_cap < 0) {
4748 auto reg_id = (*em_regs.begin()).get_regiment();
4749 disband_regiment_w_pop_death(state, reg_id);
4752 if(transport_cap >= 0)
4757 if(battle_attacker && result == battle_result::defender_won) {
4758 if(!can_retreat_from_battle(state, b)) {
4759 n.get_navy().set_controller_from_navy_control(dcon::nation_id{});
4760 n.get_navy().set_is_retreating(
true);
4762 if(!retreat(state, n.get_navy())) {
4763 n.get_navy().set_controller_from_navy_control(dcon::nation_id{});
4764 n.get_navy().set_is_retreating(
true);
4767 }
else if(!battle_attacker && result == battle_result::attacker_won) {
4768 if(!can_retreat_from_battle(state, b)) {
4769 n.get_navy().set_controller_from_navy_control(dcon::nation_id{});
4770 n.get_navy().set_is_retreating(
true);
4772 if(!retreat(state, n.get_navy())) {
4773 n.get_navy().set_controller_from_navy_control(dcon::nation_id{});
4774 n.get_navy().set_is_retreating(
true);
4778 auto path = n.get_navy().get_path();
4779 if(path.size() > 0) {
4780 state.world.navy_set_arrival_time(n.get_navy(), arrival_time_to(state, n.get_navy(), path.at(path.size() - 1)));
4783 for(
auto em : n.get_navy().get_army_transport()) {
4784 auto apath = em.get_army().get_path();
4785 if(apath.size() > 0) {
4786 state.world.army_set_arrival_time(em.get_army(), arrival_time_to(state, em.get_army(), apath.at(apath.size() - 1)));
4805 if(result != battle_result::indecisive) {
4806 state.world.war_get_number_of_battles(war)++;
4808 auto a_leader =
state.world.naval_battle_get_admiral_from_attacking_admiral(b);
4809 auto b_leader =
state.world.naval_battle_get_admiral_from_defending_admiral(b);
4811 if(result == battle_result::attacker_won) {
4812 auto score = std::max(0.0f,
4813 (
state.world.naval_battle_get_defender_loss_value(b) -
state.world.naval_battle_get_attacker_loss_value(b)) / 10.0f);
4814 if(
state.world.naval_battle_get_war_attacker_is_attacker(b)) {
4815 state.world.war_get_attacker_battle_score(war) += score;
4817 state.world.war_get_defender_battle_score(war) += score;
4821 if(a_nation && d_nation) {
4828 if(
state.local_player_nation == a_nation ||
state.local_player_nation == d_nation) {
4829 naval_battle_report rep;
4830 rep.attacker_big_losses =
state.world.naval_battle_get_attacker_big_ships_lost(b);
4831 rep.attacker_big_ships =
state.world.naval_battle_get_attacker_big_ships(b);
4832 rep.attacker_small_losses =
state.world.naval_battle_get_attacker_small_ships_lost(b);
4833 rep.attacker_small_ships =
state.world.naval_battle_get_attacker_small_ships(b);
4834 rep.attacker_transport_losses =
state.world.naval_battle_get_attacker_transport_ships_lost(b);
4835 rep.attacker_transport_ships =
state.world.naval_battle_get_attacker_transport_ships(b);
4837 rep.defender_big_losses =
state.world.naval_battle_get_defender_big_ships_lost(b);
4838 rep.defender_big_ships =
state.world.naval_battle_get_defender_big_ships(b);
4839 rep.defender_small_losses =
state.world.naval_battle_get_defender_small_ships_lost(b);
4840 rep.defender_small_ships =
state.world.naval_battle_get_defender_small_ships(b);
4841 rep.defender_transport_losses =
state.world.naval_battle_get_defender_transport_ships_lost(b);
4842 rep.defender_transport_ships =
state.world.naval_battle_get_defender_transport_ships(b);
4844 rep.attacker_won = (
result == battle_result::attacker_won);
4848 rep.attacking_admiral =
state.world.naval_battle_get_admiral_from_attacking_admiral(b);
4849 rep.defending_admiral =
state.world.naval_battle_get_admiral_from_defending_admiral(b);
4851 rep.location =
state.world.naval_battle_get_location_from_naval_battle_location(b);
4852 rep.player_on_winning_side =
4853 is_attacker(state, war,
state.local_player_nation) ==
state.world.naval_battle_get_war_attacker_is_attacker(b);
4855 if(rep.player_on_winning_side) {
4856 rep.warscore_effect = score;
4857 rep.prestige_effect = score / 50.0f;
4859 rep.warscore_effect = -score;
4860 rep.prestige_effect = -score / 50.0f;
4862 auto discard =
state.naval_battle_reports.try_push(rep);
4865 }
else if(result == battle_result::defender_won) {
4866 auto score = std::max(0.0f,
4867 (
state.world.naval_battle_get_attacker_loss_value(b) -
state.world.naval_battle_get_defender_loss_value(b)) / 10.0f);
4868 if(
state.world.naval_battle_get_war_attacker_is_attacker(b)) {
4869 state.world.war_get_attacker_battle_score(war) += score;
4871 state.world.war_get_defender_battle_score(war) += score;
4874 if(a_nation && d_nation) {
4881 if(
state.local_player_nation == a_nation ||
state.local_player_nation == d_nation) {
4882 naval_battle_report rep;
4883 rep.attacker_big_losses =
state.world.naval_battle_get_attacker_big_ships_lost(b);
4884 rep.attacker_big_ships =
state.world.naval_battle_get_attacker_big_ships(b);
4885 rep.attacker_small_losses =
state.world.naval_battle_get_attacker_small_ships_lost(b);
4886 rep.attacker_small_ships =
state.world.naval_battle_get_attacker_small_ships(b);
4887 rep.attacker_transport_losses =
state.world.naval_battle_get_attacker_transport_ships_lost(b);
4888 rep.attacker_transport_ships =
state.world.naval_battle_get_attacker_transport_ships(b);
4890 rep.defender_big_losses =
state.world.naval_battle_get_defender_big_ships_lost(b);
4891 rep.defender_big_ships =
state.world.naval_battle_get_defender_big_ships(b);
4892 rep.defender_small_losses =
state.world.naval_battle_get_defender_small_ships_lost(b);
4893 rep.defender_small_ships =
state.world.naval_battle_get_defender_small_ships(b);
4894 rep.defender_transport_losses =
state.world.naval_battle_get_defender_transport_ships_lost(b);
4895 rep.defender_transport_ships =
state.world.naval_battle_get_defender_transport_ships(b);
4897 rep.attacker_won = (
result == battle_result::attacker_won);
4901 rep.attacking_admiral =
state.world.naval_battle_get_admiral_from_attacking_admiral(b);
4902 rep.defending_admiral =
state.world.naval_battle_get_admiral_from_defending_admiral(b);
4904 rep.location =
state.world.naval_battle_get_location_from_naval_battle_location(b);
4905 rep.player_on_winning_side =
4906 is_attacker(state, war,
state.local_player_nation) !=
state.world.naval_battle_get_war_attacker_is_attacker(b);
4908 if(rep.player_on_winning_side) {
4909 rep.warscore_effect = score;
4910 rep.prestige_effect = score / 50.0f;
4912 rep.warscore_effect = -score;
4913 rep.prestige_effect = -score / 50.0f;
4915 auto discard =
state.naval_battle_reports.try_push(rep);
4921 if(result != battle_result::indecisive) {
4922 auto par_range =
state.world.naval_battle_get_navy_battle_participation(b);
4923 while(par_range.begin() != par_range.end()) {
4924 auto n = (*par_range.begin()).get_navy();
4925 n.set_battle_from_navy_battle_participation(dcon::naval_battle_id{});
4930 state.world.delete_naval_battle(b);
4933inline 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,
4934 0.35f, 0.40f, 0.45f, 0.50f, 0.60f, 0.70f, 0.80f, 0.90f};
4936dcon::nation_id tech_nation_for_regiment(
sys::state& state, dcon::regiment_id r) {
4937 auto army = state.world.regiment_get_army_from_army_membership(r);
4938 auto nation = state.world.army_get_controller_from_army_control(army);
4941 auto rf = state.world.army_get_controller_from_army_rebel_control(army);
4942 auto ruler = state.world.rebel_faction_get_ruler_from_rebellion_within(rf);
4945 return state.world.national_identity_get_nation_from_identity_holder(state.national_definitions.rebel_id);
4948bool will_recieve_attrition(
sys::state& state, dcon::navy_id a) {
4952float peacetime_attrition_limit(
sys::state& state, dcon::nation_id n, dcon::province_id prov) {
4953 auto supply_limit = supply_limit_in_province(state, n, prov);
4954 auto prov_attrition_mod = state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::attrition);
4955 auto attrition_mod = 1.0f + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::land_attrition);
4957 return (supply_limit + prov_attrition_mod) / (attrition_mod * 3.0f);
4960bool will_recieve_attrition(
sys::state& state, dcon::army_id a) {
4961 auto prov = state.world.army_get_location_from_army_location(a);
4963 if(state.world.province_get_siege_progress(prov) > 0.f)
4966 float total_army_weight = 0;
4967 for(
auto ar : state.world.province_get_army_location(prov)) {
4968 if(ar.get_army().get_black_flag() ==
false && ar.get_army().get_is_retreating() ==
false &&
4969 !
bool(ar.get_army().get_navy_from_army_transport())) {
4970 for(
auto rg : ar.get_army().get_army_membership()) {
4971 total_army_weight += 3.0f * rg.get_regiment().get_strength();
4976 auto prov_attrition_mod =
state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::attrition);
4979 auto army_controller = ar.get_controller_from_army_control();
4981 auto attrition_mod = 1.0f + army_controller.get_modifier_values(sys::national_mod_offsets::land_attrition);
4983 float greatest_hostile_fort = 0.0f;
4984 for(
auto adj :
state.world.province_get_province_adjacency(prov)) {
4986 auto other =
adj.get_connected_provinces(0) !=
prov ?
adj.get_connected_provinces(0) :
adj.get_connected_provinces(1);
4988 if(
are_at_war(state, army_controller,
other.get_nation_from_province_control())) {
4994 return total_army_weight * attrition_mod - (supply_limit + prov_attrition_mod + greatest_hostile_fort) > 0;
4997float relative_attrition_amount(
sys::state& state, dcon::navy_id a, dcon::province_id prov) {
5001float local_army_weight(
sys::state& state, dcon::province_id prov) {
5002 float total_army_weight = 0;
5003 for(
auto ar : state.world.province_get_army_location(prov)) {
5004 if(ar.get_army().get_black_flag() ==
false && ar.get_army().get_is_retreating() ==
false &&
5005 !
bool(ar.get_army().get_navy_from_army_transport())) {
5006 for(
auto rg : ar.get_army().get_army_membership()) {
5007 total_army_weight += 3.0f * rg.get_regiment().get_strength();
5011 return total_army_weight;
5013float local_army_weight_max(
sys::state& state, dcon::province_id prov) {
5014 float total_army_weight = 0;
5015 for(
auto ar : state.world.province_get_army_location(prov)) {
5016 if(ar.get_army().get_black_flag() ==
false && ar.get_army().get_is_retreating() ==
false &&
5017 !
bool(ar.get_army().get_navy_from_army_transport())) {
5018 for(
auto rg : ar.get_army().get_army_membership()) {
5019 total_army_weight += 3.0f;
5023 return total_army_weight;
5025float local_enemy_army_weight_max(
sys::state& state, dcon::province_id prov, dcon::nation_id nation) {
5026 float total_army_weight = 0;
5027 for(
auto ar : state.world.province_get_army_location(prov)) {
5029 ar.get_army().get_black_flag() ==
false
5030 && ar.get_army().get_is_retreating() ==
false
5031 && !
bool(ar.get_army().get_navy_from_army_transport())
5032 && are_at_war(state, nation, ar.get_army().get_controller_from_army_control())
5034 for(
auto rg : ar.get_army().get_army_membership()) {
5035 total_army_weight += 3.0f;
5039 return total_army_weight;
5042float relative_attrition_amount(
sys::state& state, dcon::army_id a, dcon::province_id prov) {
5043 float total_army_weight = 0;
5044 for(
auto ar : state.world.province_get_army_location(prov)) {
5045 if(ar.get_army().get_black_flag() ==
false && ar.get_army().get_is_retreating() ==
false &&
5046 !
bool(ar.get_army().get_navy_from_army_transport())) {
5048 for(
auto rg : ar.get_army().get_army_membership()) {
5049 total_army_weight += 3.0f * rg.get_regiment().get_strength();
5054 auto prov_attrition_mod =
state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::attrition);
5058 auto army_controller = ar.get_controller_from_army_control();
5060 auto attrition_mod = 1.0f + army_controller.get_modifier_values(sys::national_mod_offsets::land_attrition);
5062 float greatest_hostile_fort = 0.0f;
5064 for(
auto adj :
state.world.province_get_province_adjacency(prov)) {
5066 auto other =
adj.get_connected_provinces(0) !=
prov ?
adj.get_connected_provinces(0) :
adj.get_connected_provinces(1);
5068 if(
are_at_war(state, army_controller,
other.get_nation_from_province_control())) {
5075 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))
5076 +
state.world.province_get_siege_progress(prov) > 0.f ?
state.defines.siege_attrition : 0.0f;
5077 return value * 0.01f;
5079float attrition_amount(
sys::state& state, dcon::navy_id a) {
5082float attrition_amount(
sys::state& state, dcon::army_id a) {
5083 return relative_attrition_amount(state, a, state.world.army_get_location_from_army_location(a));
5087 concurrency::parallel_for(0, state.province_definitions.first_sea_province.index(), [&](int32_t i) {
5088 dcon::province_id prov{dcon::province_id::value_base_t(i)};
5089 float total_army_weight = 0;
5090 for(
auto ar : state.world.province_get_army_location(prov)) {
5091 if(ar.get_army().get_black_flag() == false && ar.get_army().get_is_retreating() == false &&
5092 !bool(ar.get_army().get_navy_from_army_transport()) && !bool(ar.get_army().get_battle_from_army_battle_participation())) {
5094 for(auto rg : ar.get_army().get_army_membership()) {
5095 total_army_weight += 3.0f * rg.get_regiment().get_strength();
5100 auto prov_attrition_mod =
state.world.province_get_modifier_values(prov, sys::provincial_mod_offsets::attrition);
5102 for(
auto ar :
state.world.province_get_army_location(prov)) {
5103 if(ar.get_army().get_black_flag() == false && ar.get_army().get_is_retreating() == false &&
5104 !bool(ar.get_army().get_navy_from_army_transport()) && !bool(ar.get_army().get_battle_from_army_battle_participation())) {
5106 auto army_controller = ar.get_army().get_controller_from_army_control();
5107 auto supply_limit = supply_limit_in_province(state, army_controller, prov);
5108 auto attrition_mod = 1.0f + army_controller.get_modifier_values(sys::national_mod_offsets::land_attrition);
5110 float greatest_hostile_fort = 0.0f;
5112 for(auto adj : state.world.province_get_province_adjacency(prov)) {
5113 if((adj.get_type() & (province::border::impassible_bit | province::border::coastal_bit)) == 0) {
5114 auto other = adj.get_connected_provinces(0) != prov ? adj.get_connected_provinces(0) : adj.get_connected_provinces(1);
5115 if(other.get_building_level(uint8_t(economy::province_building_type::fort)) > 0) {
5116 if(are_at_war(state, army_controller, other.get_nation_from_province_control())) {
5117 greatest_hostile_fort = std::max(greatest_hostile_fort, float(other.get_building_level(uint8_t(economy::province_building_type::fort))));
5132 float attrition_value =
5133 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))
5134 + state.world.province_get_siege_progress(prov) > 0.f ? state.defines.siege_attrition : 0.0f;
5136 for(auto rg : ar.get_army().get_army_membership()) {
5137 rg.get_regiment().get_pending_damage() += attrition_value * 0.01f;
5138 rg.get_regiment().get_strength() -= attrition_value * 0.01f;
5145void apply_regiment_damage(
sys::state& state) {
5146 for(
uint32_t i = state.world.regiment_size(); i-- > 0;) {
5147 dcon::regiment_id s{ dcon::regiment_id::value_base_t(i) };
5148 if(state.world.regiment_is_valid(s)) {
5149 auto& pending_damage = state.world.regiment_get_pending_damage(s);
5150 auto& current_strength = state.world.regiment_get_strength(s);
5152 if(pending_damage > 0) {
5153 auto backing_pop = state.world.regiment_get_pop_from_regiment_source(s);
5154 auto tech_nation = tech_nation_for_regiment(state, s);
5157 auto& psize = state.world.pop_get_size(backing_pop);
5158 psize -= state.defines.pop_size_per_regiment * pending_damage * state.defines.soldier_to_pop_damage /
5159 (3.0f * (1.0f + state.world.nation_get_modifier_values(tech_nation,
5160 sys::national_mod_offsets::soldier_to_pop_loss)));
5162 state.world.delete_pop(backing_pop);
5165 pending_damage = 0.0f;
5167 if(current_strength <= 0.0f) {
5169 auto army = state.world.regiment_get_army_from_army_membership(s);
5170 auto controller = state.world.army_get_controller_from_army_control(army);
5171 auto pop_backer = state.world.regiment_get_pop_from_regiment_source(s);
5175 state.world.pop_get_militancy(pop_backer) /= state.defines.reduction_after_defeat;
5178 auto maxr = state.world.nation_get_recruitable_regiments(controller);
5179 if(maxr > 0 && pop_backer) {
5180 auto& wex = state.world.nation_get_war_exhaustion(controller);
5181 wex = std::min(wex + 0.5f /
float(maxr), state.world.nation_get_modifier_values(controller, sys::national_mod_offsets::max_war_exhaustion));
5185 if(
auto b = state.world.army_get_battle_from_army_battle_participation(army); b) {
5187 for(
auto e : state.world.land_battle_get_attacker_back_line(b))
5189 for(
auto e : state.world.land_battle_get_attacker_front_line(b))
5191 for(
auto e : state.world.land_battle_get_defender_back_line(b))
5193 for(
auto e : state.world.land_battle_get_defender_front_line(b))
5196 auto reserves = state.world.land_battle_get_reserves(b);
5201 for(
uint32_t j = reserves.size(); j-- > 0;) {
5202 assert(reserves[j].regiment != s);
5203 if(reserves[j].regiment == s) {
5204 std::swap(reserves[j], reserves[reserves.size() - 1]);
5205 reserves.pop_back();
5210 if(!controller || state.world.pop_get_size(pop_backer) < 1000.0f)
5211 state.world.delete_regiment(s);
5213 current_strength = 0.0f;
5220 auto isize = state.world.land_battle_size();
5221 auto to_delete = ve::vectorizable_buffer<uint8_t, dcon::land_battle_id>(isize);
5223 concurrency::parallel_for(0, int32_t(isize), [&](int32_t index) {
5224 dcon::land_battle_id b{dcon::land_battle_id::value_base_t(index)};
5226 if(!state.world.land_battle_is_valid(b))
5230 auto combat_width = state.world.land_battle_get_combat_width(b);
5232 auto& att_back = state.world.land_battle_get_attacker_back_line(b);
5233 auto& def_back = state.world.land_battle_get_defender_back_line(b);
5234 auto& att_front = state.world.land_battle_get_attacker_front_line(b);
5235 auto& def_front = state.world.land_battle_get_defender_front_line(b);
5237 auto reserves = state.world.land_battle_get_reserves(b);
5239 if((state.current_date.value - state.world.land_battle_get_start_date(b).value) % 5 == 4) {
5240 state.world.land_battle_set_dice_rolls(b, make_dice_rolls(state,
uint32_t(index)));
5257 auto both_dice = state.world.land_battle_get_dice_rolls(b);
5258 auto defender_mods = state.world.land_battle_get_defender_bonus(b);
5259 auto dig_in_value = defender_mods & defender_bonus_dig_in_mask;
5260 auto crossing_value = defender_mods & defender_bonus_crossing_mask;
5262 auto attacking_nation = get_land_battle_lead_attacker(state, b);
5263 auto defending_nation = get_land_battle_lead_defender(state, b);
5266 state.world.nation_get_has_gas_attack(attacking_nation) && !state.world.nation_get_has_gas_defense(defending_nation);
5268 state.world.nation_get_has_gas_attack(defending_nation) && !state.world.nation_get_has_gas_defense(attacking_nation);
5270 int32_t crossing_adjustment =
5271 (crossing_value == defender_bonus_crossing_none ? 0 : (crossing_value == defender_bonus_crossing_river ? -1 : -2));
5273 auto attacker_dice = both_dice & 0x0F;
5274 auto defender_dice = (both_dice >> 4) & 0x0F;
5276 auto location = state.world.land_battle_get_location_from_land_battle_location(b);
5277 auto terrain_bonus = state.world.province_get_modifier_values(location, sys::provincial_mod_offsets::defense);
5279 auto attacker_per = state.world.leader_get_personality(state.world.land_battle_get_general_from_attacking_general(b));
5280 auto attacker_bg = state.world.leader_get_background(state.world.land_battle_get_general_from_attacking_general(b));
5283 int32_t(state.world.leader_trait_get_attack(attacker_per) + state.world.leader_trait_get_attack(attacker_bg));
5284 auto attacker_org_bonus =
5285 (1.0f + state.world.leader_trait_get_organisation(attacker_per) + state.world.leader_trait_get_organisation(attacker_bg))
5286 * (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);
5288 auto defender_per = state.world.leader_get_personality(state.world.land_battle_get_general_from_defending_general(b));
5289 auto defender_bg = state.world.leader_get_background(state.world.land_battle_get_general_from_defending_general(b));
5291 auto atk_leader_exp_mod = 1 + attacker_per.get_experience() + attacker_bg.get_experience();
5292 auto def_leader_exp_mod = 1 + defender_per.get_experience() + defender_per.get_experience();
5294 auto defence_bonus =
5295 int32_t(state.world.leader_trait_get_defense(defender_per) + state.world.leader_trait_get_defense(defender_bg));
5296 auto defender_org_bonus =
5297 (1.0f + state.world.leader_trait_get_organisation(defender_per) + state.world.leader_trait_get_organisation(defender_bg))
5298 * (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);
5300 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)];
5301 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)];
5303 float defender_fort = 1.0f;
5304 auto local_control = state.world.province_get_nation_from_province_control(location);
5305 if((!attacking_nation && local_control) ||
5306 (attacking_nation && (!
bool(local_control) ||
military::are_at_war(state, attacking_nation, local_control)))) {
5334 state.world.land_battle_set_attacker_casualties(b, 0);
5335 state.world.land_battle_set_defender_casualties(b, 0);
5337 float attacker_casualties = 0;
5338 float defender_casualties = 0;
5340 for(int32_t i = 0; i < combat_width; ++i) {
5342 if(att_back[i] && def_front[i]) {
5343 assert(state.world.regiment_is_valid(att_back[i]) && state.world.regiment_is_valid(def_front[i]));
5345 auto tech_att_nation = tech_nation_for_regiment(state, att_back[i]);
5346 auto tech_def_nation = tech_nation_for_regiment(state, def_front[i]);
5348 auto att_str = state.world.regiment_get_strength(att_back[i]);
5350 auto& att_stats = state.world.nation_get_unit_stats(tech_att_nation, state.world.regiment_get_type(att_back[i]));
5351 auto& def_stats = state.world.nation_get_unit_stats(tech_def_nation, state.world.regiment_get_type(def_front[i]));
5353 auto& def_exp = state.world.regiment_get_experience(def_front[i]);
5355 auto str_damage = att_str * str_dam_mul *
5356 (att_stats.attack_or_gun_power * 0.1f + 1.0f) * att_stats.support * attacker_mod /
5357 (defender_fort * (state.defines.base_military_tactics + state.world.nation_get_modifier_values(tech_def_nation, sys::national_mod_offsets::military_tactics))
5359 auto org_damage = att_str * org_dam_mul *
5360 (att_stats.attack_or_gun_power * 0.1f + 1.0f) * att_stats.support * attacker_mod /
5361 (defender_fort * defender_org_bonus * def_stats.discipline_or_evasion *
5362 (1.0f + state.world.nation_get_modifier_values(tech_def_nation, sys::national_mod_offsets::land_organisation))
5363 * (1.0f + def_exp));
5365 auto& cstr = state.world.regiment_get_strength(def_front[i]);
5366 str_damage = std::min(str_damage, cstr);
5367 state.world.regiment_get_pending_damage(def_front[i]) += str_damage;
5369 defender_casualties += str_damage;
5371 adjust_regiment_experience(state, attacking_nation, att_back[i], str_damage * 5.f * state.defines.exp_gain_div * atk_leader_exp_mod);
5373 auto& org = state.world.regiment_get_org(def_front[i]);
5374 org = std::max(0.0f, org - org_damage);
5375 switch(state.military_definitions.unit_base_definitions[state.world.regiment_get_type(def_front[i])].type) {
5376 case unit_type::infantry:
5377 state.world.land_battle_get_defender_infantry_lost(b) += str_damage;
5379 case unit_type::cavalry:
5380 state.world.land_battle_get_defender_cav_lost(b) += str_damage;
5382 case unit_type::support:
5384 case unit_type::special:
5385 state.world.land_battle_get_defender_support_lost(b) += str_damage;
5393 if(def_back[i] && att_front[i]) {
5394 assert(state.world.regiment_is_valid(def_back[i]) && state.world.regiment_is_valid(att_front[i]));
5396 auto tech_def_nation = tech_nation_for_regiment(state, def_back[i]);
5397 auto tech_att_nation = tech_nation_for_regiment(state, att_front[i]);
5399 auto& def_stats = state.world.nation_get_unit_stats(tech_def_nation, state.world.regiment_get_type(def_back[i]));
5400 auto& att_stats = state.world.nation_get_unit_stats(tech_att_nation, state.world.regiment_get_type(att_front[i]));
5402 auto& atk_exp = state.world.regiment_get_experience(att_front[i]);
5404 auto def_str = state.world.regiment_get_strength(def_back[i]);
5406 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));
5407 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));
5409 auto& cstr = state.world.regiment_get_strength(att_front[i]);
5410 str_damage = std::min(str_damage, cstr);
5411 state.world.regiment_get_pending_damage(att_front[i]) += str_damage;
5413 attacker_casualties += str_damage;
5415 adjust_regiment_experience(state, defending_nation, def_back[i], str_damage * 5.f * state.defines.exp_gain_div * def_leader_exp_mod);
5417 auto& org = state.world.regiment_get_org(att_front[i]);
5418 org = std::max(0.0f, org - org_damage);
5419 switch(state.military_definitions.unit_base_definitions[state.world.regiment_get_type(att_front[i])].type) {
5420 case unit_type::infantry:
5421 state.world.land_battle_get_attacker_infantry_lost(b) += str_damage;
5423 case unit_type::cavalry:
5424 state.world.land_battle_get_attacker_cav_lost(b) += str_damage;
5426 case unit_type::support:
5428 case unit_type::special:
5429 state.world.land_battle_get_attacker_support_lost(b) += str_damage;
5438 assert(state.world.regiment_is_valid(att_front[i]));
5440 auto tech_att_nation = tech_nation_for_regiment(state, att_front[i]);
5441 auto& att_stats = state.world.nation_get_unit_stats(tech_att_nation, state.world.regiment_get_type(att_front[i]));
5443 auto att_front_target = def_front[i];
5444 if(
auto mv = state.military_definitions.unit_base_definitions[state.world.regiment_get_type(att_front[i])].maneuver; !att_front_target && mv > 0.0f) {
5445 for(int32_t cnt = 1; i - cnt * 2 >= 0 && cnt <= int32_t(mv); ++cnt) {
5446 if(def_front[i - cnt * 2]) {
5447 att_front_target = def_front[i - cnt * 2];
5453 if(att_front_target) {
5454 assert(state.world.regiment_is_valid(att_front_target));
5456 auto tech_def_nation = tech_nation_for_regiment(state, att_front_target);
5457 auto& def_stats = state.world.nation_get_unit_stats(tech_def_nation, state.world.regiment_get_type(att_front_target));
5459 auto& def_exp = state.world.regiment_get_experience(att_front_target);
5461 auto att_str = state.world.regiment_get_strength(att_front[i]);
5463 auto str_damage = att_str * str_dam_mul *
5464 (att_stats.attack_or_gun_power * 0.1f + 1.0f) * attacker_mod /
5465 (defender_fort * (state.defines.base_military_tactics + state.world.nation_get_modifier_values(tech_def_nation, sys::national_mod_offsets::military_tactics))
5467 auto org_damage = att_str * org_dam_mul *
5468 (att_stats.attack_or_gun_power * 0.1f + 1.0f) * attacker_mod /
5469 (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))
5472 auto& cstr = state.world.regiment_get_strength(att_front_target);
5473 str_damage = std::min(str_damage, cstr);
5474 state.world.regiment_get_pending_damage(att_front_target) += str_damage;
5476 defender_casualties += str_damage;
5478 adjust_regiment_experience(state, attacking_nation, att_front[i], str_damage * 5.f * state.defines.exp_gain_div * atk_leader_exp_mod);
5480 auto& org = state.world.regiment_get_org(att_front_target);
5481 org = std::max(0.0f, org - org_damage);
5482 switch(state.military_definitions.unit_base_definitions[state.world.regiment_get_type(att_front_target)].type) {
5483 case unit_type::infantry:
5484 state.world.land_battle_get_defender_infantry_lost(b) += str_damage;
5486 case unit_type::cavalry:
5487 state.world.land_battle_get_defender_cav_lost(b) += str_damage;
5489 case unit_type::support:
5491 case unit_type::special:
5492 state.world.land_battle_get_defender_support_lost(b) += str_damage;
5502 assert(state.world.regiment_is_valid(def_front[i]));
5504 auto tech_def_nation = tech_nation_for_regiment(state, def_front[i]);
5505 auto& def_stats = state.world.nation_get_unit_stats(tech_def_nation, state.world.regiment_get_type(def_front[i]));
5507 auto def_front_target = att_front[i];
5509 if(
auto mv = state.military_definitions.unit_base_definitions[state.world.regiment_get_type(def_front[i])].maneuver; !def_front_target && mv > 0.0f) {
5510 for(int32_t cnt = 1; i - cnt * 2 >= 0 && cnt <= int32_t(mv); ++cnt) {
5511 if(att_front[i - cnt * 2]) {
5512 def_front_target = att_front[i - cnt * 2];
5518 if(def_front_target) {
5519 assert(state.world.regiment_is_valid(def_front_target));
5521 auto tech_att_nation = tech_nation_for_regiment(state, def_front_target);
5522 auto& att_stats = state.world.nation_get_unit_stats(tech_att_nation, state.world.regiment_get_type(def_front_target));
5524 auto& atk_exp = state.world.regiment_get_experience(def_front_target);
5526 auto def_str = state.world.regiment_get_strength(def_front[i]);
5528 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))
5530 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))
5533 auto& cstr = state.world.regiment_get_strength(def_front_target);
5534 str_damage = std::min(str_damage, cstr);
5535 state.world.regiment_get_pending_damage(def_front_target) += str_damage;
5537 attacker_casualties += str_damage;
5539 adjust_regiment_experience(state, defending_nation, def_front[i], str_damage * 5.f * state.defines.exp_gain_div * def_leader_exp_mod);
5541 auto& org = state.world.regiment_get_org(def_front_target);
5542 org = std::max(0.0f, org - org_damage);
5543 switch(state.military_definitions.unit_base_definitions[state.world.regiment_get_type(def_front_target)].type) {
5544 case unit_type::infantry:
5545 state.world.land_battle_get_attacker_infantry_lost(b) += str_damage;
5547 case unit_type::cavalry:
5548 state.world.land_battle_get_attacker_cav_lost(b) += str_damage;
5550 case unit_type::support:
5552 case unit_type::special:
5553 state.world.land_battle_get_attacker_support_lost(b) += str_damage;
5562 state.world.land_battle_set_attacker_casualties(b, attacker_casualties);
5563 state.world.land_battle_set_defender_casualties(b, defender_casualties);
5568 for(int32_t i = 0; i < combat_width; ++i) {
5570 if(state.world.regiment_get_strength(def_back[i]) <= 0.0f) {
5571 def_back[i] = dcon::regiment_id{};
5572 }
else if(state.world.regiment_get_org(def_back[i]) < 0.1f) {
5573 def_back[i] = dcon::regiment_id{};
5577 if(state.world.regiment_get_strength(def_front[i]) <= 0.0f) {
5578 def_front[i] = dcon::regiment_id{};
5579 }
else if(state.world.regiment_get_org(def_front[i]) < 0.1f) {
5580 def_front[i] = dcon::regiment_id{};
5584 if(state.world.regiment_get_strength(att_back[i]) <= 0.0f) {
5585 att_back[i] = dcon::regiment_id{};
5586 }
else if(state.world.regiment_get_org(att_back[i]) < 0.1f) {
5587 att_back[i] = dcon::regiment_id{};
5591 if(state.world.regiment_get_strength(att_front[i]) <= 0.0f) {
5592 att_front[i] = dcon::regiment_id{};
5593 }
else if(state.world.regiment_get_org(att_front[i]) < 0.1f) {
5594 att_front[i] = dcon::regiment_id{};
5600 auto compact = [](std::array<dcon::regiment_id, 30>& a) {
5602 while(low < 30 && a[low]) {
5605 int32_t high = low + 2;
5606 while(high < 30 && !a[high])
5611 a[high] = dcon::regiment_id{};
5614 while(high < 30 && !a[high])
5621 while(low < 30 && a[low]) {
5625 while(high < 30 && !a[high])
5630 a[high] = dcon::regiment_id{};
5633 while(high < 30 && !a[high])
5647 std::swap(att_back[0], att_back[1]);
5650 std::swap(def_back[0], def_back[1]);
5653 std::swap(att_front[0], att_front[1]);
5656 std::swap(def_front[0], def_front[1]);
5659 for(int32_t i = 0; i < combat_width; ++i) {
5661 for(
uint32_t j = reserves.size(); j-- > 0;) {
5662 if(reserves[j].flags == (reserve_regiment::is_attacking | reserve_regiment::type_support)) {
5663 att_back[i] = reserves[j].regiment;
5664 std::swap(reserves[j], reserves[reserves.size() - 1]);
5665 reserves.pop_back();
5672 for(
uint32_t j = reserves.size(); j-- > 0;) {
5673 if(reserves[j].flags == (reserve_regiment::type_support)) {
5674 def_back[i] = reserves[j].regiment;
5675 std::swap(reserves[j], reserves[reserves.size() - 1]);
5676 reserves.pop_back();
5685 for(int32_t i = 0; i < combat_width; ++i) {
5688 for(
uint32_t j = reserves.size(); j-- > 0;) {
5689 if(reserves[j].flags == (reserve_regiment::is_attacking | reserve_regiment::type_infantry)) {
5690 att_front[i] = reserves[j].regiment;
5691 std::swap(reserves[j], reserves[reserves.size() - 1]);
5692 reserves.pop_back();
5698 for(
uint32_t j = reserves.size(); j-- > 0;) {
5699 if(reserves[j].flags == (reserve_regiment::is_attacking | reserve_regiment::type_cavalry)) {
5700 att_front[i] = reserves[j].regiment;
5701 std::swap(reserves[j], reserves[reserves.size() - 1]);
5702 reserves.pop_back();
5707 if(!att_front[i] && att_back[i]) {
5708 std::swap(att_front[i], att_back[i]);
5713 for(
uint32_t j = reserves.size(); j-- > 0;) {
5714 if(reserves[j].flags == (reserve_regiment::type_infantry)) {
5715 def_front[i] = reserves[j].regiment;
5716 std::swap(reserves[j], reserves[reserves.size() - 1]);
5717 reserves.pop_back();
5723 for(
uint32_t j = reserves.size(); j-- > 0;) {
5724 if(reserves[j].flags == (reserve_regiment::type_cavalry)) {
5725 def_front[i] = reserves[j].regiment;
5726 std::swap(reserves[j], reserves[reserves.size() - 1]);
5727 reserves.pop_back();
5732 if(!def_front[i] && def_back[i]) {
5733 std::swap(def_front[i], def_back[i]);
5741 }
else if(!att_front[0]) {
5747 for(
auto i = isize; i-- > 0;) {
5748 dcon::land_battle_id b{dcon::land_battle_id::value_base_t(i) };
5749 if(
state.world.land_battle_is_valid(b) && to_delete.get(b) != 0) {
5750 end_battle(state, b, to_delete.get(b) ==
uint8_t(1) ? battle_result::attacker_won : battle_result::defender_won);
5755void update_naval_battles(
sys::state& state) {
5756 auto isize = state.world.naval_battle_size();
5757 auto to_delete = ve::vectorizable_buffer<uint8_t, dcon::naval_battle_id>(isize);
5759 concurrency::parallel_for(0, int32_t(isize), [&](int32_t index) {
5760 dcon::naval_battle_id b{dcon::naval_battle_id::value_base_t(index)};
5762 if(!state.world.naval_battle_is_valid(b))
5765 int32_t attacker_ships = 0;
5766 int32_t defender_ships = 0;
5768 auto slots = state.world.naval_battle_get_slots(b);
5770 for(
uint32_t j = slots.size(); j-- > 0;) {
5771 switch(slots[j].flags & ship_in_battle::mode_mask) {
5772 case ship_in_battle::mode_seeking:
5773 case ship_in_battle::mode_approaching:
5774 case ship_in_battle::mode_retreating:
5775 case ship_in_battle::mode_engaged:
5776 if((slots[j].flags & ship_in_battle::is_attacking) != 0)
5786 if(defender_ships == 0) {
5789 }
else if(attacker_ships == 0) {
5794 if((state.current_date.value - state.world.naval_battle_get_start_date(b).value) % 5 == 4) {
5795 state.world.naval_battle_set_dice_rolls(b, make_dice_rolls(state,
uint32_t(index)));
5798 auto both_dice = state.world.naval_battle_get_dice_rolls(b);
5799 auto attacker_dice = both_dice & 0x0F;
5800 auto defender_dice = (both_dice >> 4) & 0x0F;
5802 auto attacker_per = state.world.leader_get_personality(state.world.naval_battle_get_admiral_from_attacking_admiral(b));
5803 auto attacker_bg = state.world.leader_get_background(state.world.naval_battle_get_admiral_from_attacking_admiral(b));
5806 int32_t(state.world.leader_trait_get_attack(attacker_per) + state.world.leader_trait_get_attack(attacker_bg));
5807 auto attacker_org_bonus =
5808 1.0f + state.world.leader_trait_get_organisation(attacker_per) + state.world.leader_trait_get_organisation(attacker_bg);
5810 auto defender_per = state.world.leader_get_personality(state.world.naval_battle_get_admiral_from_defending_admiral(b));
5811 auto defender_bg = state.world.leader_get_background(state.world.naval_battle_get_admiral_from_defending_admiral(b));
5813 auto atk_leader_exp_mod = 1 + attacker_per.get_experience() + attacker_bg.get_experience();
5814 auto def_leader_exp_mod = 1 + defender_per.get_experience() + defender_per.get_experience();
5816 auto defence_bonus =
5817 int32_t(state.world.leader_trait_get_defense(defender_per) + state.world.leader_trait_get_defense(defender_bg));
5818 auto defender_org_bonus =
5819 1.0f + state.world.leader_trait_get_organisation(defender_per) + state.world.leader_trait_get_organisation(defender_bg);
5821 auto attacker_mod = combat_modifier_table[std::clamp(attacker_dice + attack_bonus + 3, 0, 18)];
5822 auto defender_mod = combat_modifier_table[std::clamp(defender_dice + defence_bonus + 3, 0, 18)];
5824 for(
uint32_t j = slots.size(); j-- > 0;) {
5826 state.world.navy_get_controller_from_navy_control(state.world.ship_get_navy_from_navy_membership(slots[j].ship));
5827 auto ship_type = state.world.ship_get_type(slots[j].ship);
5829 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);
5831 auto& ship_stats = state.world.nation_get_unit_stats(ship_owner, ship_type);
5833 auto aship = slots[j].ship;
5835 state.world.navy_get_controller_from_navy_control(state.world.ship_get_navy_from_navy_membership(aship));
5837 switch(slots[j].flags & ship_in_battle::mode_mask) {
5838 case ship_in_battle::mode_approaching: {
5839 auto target_mode = slots[slots[j].target_slot].flags & ship_in_battle::mode_mask;
5840 if(target_mode == ship_in_battle::mode_retreated || target_mode == ship_in_battle::mode_sunk) {
5841 slots[j].flags &= ~ship_in_battle::mode_mask;
5842 slots[j].flags |= ship_in_battle::mode_seeking;
5853 float speed = ship_stats.maximum_speed * 1000.0f * state.defines.naval_combat_speed_to_distance_factor *
5855 auto old_distance = slots[j].flags & ship_in_battle::distance_mask;
5856 int32_t adjust = std::clamp(int32_t(std::ceil(speed)), 0, old_distance);
5857 slots[j].flags &= ~ship_in_battle::distance_mask;
5858 slots[j].flags |= ship_in_battle::distance_mask & (old_distance - adjust);
5860 if(old_distance == adjust ||
5861 (old_distance - adjust) + (slots[slots[j].target_slot].flags & ship_in_battle::distance_mask) <
5862 int32_t(1000.0f * ship_stats.reconnaissance_or_fire_range)) {
5864 slots[j].flags &= ~ship_in_battle::mode_mask;
5865 slots[j].flags |= ship_in_battle::mode_engaged;
5870 case ship_in_battle::mode_engaged: {
5871 auto target_mode = slots[slots[j].target_slot].flags & ship_in_battle::mode_mask;
5872 if(target_mode == ship_in_battle::mode_retreated || target_mode == ship_in_battle::mode_sunk) {
5873 slots[j].flags &= ~ship_in_battle::mode_mask;
5874 slots[j].flags |= ship_in_battle::mode_seeking;
5877 bool target_is_big = (slots[slots[j].target_slot].flags & ship_in_battle::type_mask) == ship_in_battle::type_big;
5878 bool is_attacker = (slots[j].flags & ship_in_battle::is_attacking) != 0;
5879 auto tship = slots[slots[j].target_slot].ship;
5882 auto ship_target_owner =
5883 state.world.navy_get_controller_from_navy_control(state.world.ship_get_navy_from_navy_membership(tship));
5884 auto ttype = state.world.ship_get_type(tship);
5886 auto& ship_target_stats = state.world.nation_get_unit_stats(ship_target_owner, ttype);
5896 auto& targ_ship_exp = state.world.ship_get_experience(tship);
5898 float org_damage = org_dam_mul * (ship_stats.attack_or_gun_power + (target_is_big ? ship_stats.siege_or_torpedo_attack : 0.0f)) *
5899 (is_attacker ? attacker_mod : defender_mod) * state.defines.naval_combat_damage_org_mult /
5900 ((ship_target_stats.defence_or_hull + 1.0f) * (is_attacker ? defender_org_bonus : attacker_org_bonus) *
5901 (1.0f + state.world.nation_get_modifier_values(ship_target_owner,
5902 sys::national_mod_offsets::naval_organisation))
5903 * (1 + targ_ship_exp));
5904 float str_damage = str_dam_mul * (ship_stats.attack_or_gun_power + (target_is_big ? ship_stats.siege_or_torpedo_attack : 0.0f)) *
5905 (is_attacker ? attacker_mod : defender_mod) * state.defines.naval_combat_damage_str_mult /
5906 ((ship_target_stats.defence_or_hull + 1.0f) * (1 + targ_ship_exp));
5908 auto& torg = state.world.ship_get_org(tship);
5909 torg = std::max(0.0f, torg - org_damage);
5910 auto& tstr = state.world.ship_get_strength(tship);
5911 tstr = std::max(0.0f, tstr - str_damage);
5913 auto leader_exp_mod = (is_attacker ? atk_leader_exp_mod : def_leader_exp_mod);
5914 adjust_ship_experience(state, aship_owner, aship, str_damage * 5.f * state.defines.exp_gain_div * leader_exp_mod);
5918 case ship_in_battle::mode_retreating: {
5924 float speed = ship_stats.maximum_speed * 1000.0f * state.defines.naval_combat_retreat_speed_mod *
5925 state.defines.naval_combat_speed_to_distance_factor *
5928 auto old_distance = slots[j].flags & ship_in_battle::distance_mask;
5929 int32_t new_distance = std::min(int32_t(std::ceil(speed)) + old_distance, 1000);
5930 slots[j].flags &= ~ship_in_battle::distance_mask;
5931 slots[j].flags |= ship_in_battle::distance_mask & (new_distance);
5935 case ship_in_battle::mode_seeking: {
5942 if((slots[j].flags & ship_in_battle::is_attacking) != 0) {
5946 for(
uint32_t k = slots.size(); k-- > 0;) {
5947 switch(slots[k].flags & ship_in_battle::mode_mask) {
5949 case ship_in_battle::mode_seeking:
5950 case ship_in_battle::mode_approaching:
5951 case ship_in_battle::mode_retreating:
5952 case ship_in_battle::mode_engaged:
5953 if((slots[k].flags & ship_in_battle::is_attacking) == 0) {
5955 slots[j].target_slot = uint16_t(k);
5968 auto old_distance = slots[j].flags & ship_in_battle::distance_mask;
5969 int32_t new_distance = std::min(old_distance + 400, 1000);
5971 slots[j].flags &= ~ship_in_battle::mode_mask;
5972 slots[j].flags |= ship_in_battle::mode_approaching;
5973 slots[j].flags &= ~ship_in_battle::distance_mask;
5974 slots[j].flags |= ship_in_battle::distance_mask & new_distance;
5979 for(
uint32_t k = slots.size(); k-- > 0;) {
5980 switch(slots[k].flags & ship_in_battle::mode_mask) {
5982 case ship_in_battle::mode_seeking:
5983 case ship_in_battle::mode_approaching:
5984 case ship_in_battle::mode_retreating:
5985 case ship_in_battle::mode_engaged:
5986 if((slots[k].flags & ship_in_battle::is_attacking) != 0) {
5988 slots[j].target_slot = uint16_t(k);
6001 auto old_distance = slots[j].flags & ship_in_battle::distance_mask;
6002 int32_t new_distance = std::min(old_distance + 400, 1000);
6004 slots[j].flags &= ~ship_in_battle::mode_mask;
6005 slots[j].flags |= ship_in_battle::mode_approaching;
6006 slots[j].flags &= ~ship_in_battle::distance_mask;
6007 slots[j].flags |= ship_in_battle::distance_mask & new_distance;
6017 for(
uint32_t j = slots.size(); j-- > 0;) {
6019 state.world.navy_get_controller_from_navy_control(state.world.ship_get_navy_from_navy_membership(slots[j].ship));
6020 auto type = state.world.ship_get_type(slots[j].ship);
6022 switch(slots[j].flags & ship_in_battle::mode_mask) {
6023 case ship_in_battle::mode_seeking:
6024 case ship_in_battle::mode_approaching:
6025 case ship_in_battle::mode_engaged:
6026 if(state.world.ship_get_strength(slots[j].ship) <= 0) {
6027 if((slots[j].flags & ship_in_battle::is_attacking) != 0) {
6028 if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_big) {
6029 state.world.naval_battle_get_attacker_big_ships_lost(b)++;
6030 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_small) {
6031 state.world.naval_battle_get_attacker_small_ships_lost(b)++;
6032 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_transport) {
6033 state.world.naval_battle_get_attacker_transport_ships_lost(b)++;
6035 state.world.naval_battle_get_attacker_loss_value(b) += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
6037 if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_big) {
6038 state.world.naval_battle_get_defender_big_ships_lost(b)++;
6039 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_small) {
6040 state.world.naval_battle_get_defender_small_ships_lost(b)++;
6041 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_transport) {
6042 state.world.naval_battle_get_defender_transport_ships_lost(b)++;
6044 state.world.naval_battle_get_defender_loss_value(b) += state.military_definitions.unit_base_definitions[type].supply_consumption_score;
6046 slots[j].flags &= ~ship_in_battle::mode_mask;
6047 slots[j].flags |= ship_in_battle::mode_sunk;
6050 if(state.world.ship_get_strength(slots[j].ship) <= state.defines.naval_combat_retreat_str_org_level ||
6051 state.world.ship_get_org(slots[j].ship) <= state.defines.naval_combat_retreat_str_org_level) {
6053 slots[j].flags &= ~ship_in_battle::mode_mask;
6054 slots[j].flags |= ship_in_battle::mode_retreating;
6057 case ship_in_battle::mode_retreating:
6058 if(state.world.ship_get_strength(slots[j].ship) <= 0) {
6059 if((slots[j].flags & ship_in_battle::is_attacking) != 0) {
6060 if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_big) {
6061 state.world.naval_battle_get_attacker_big_ships_lost(b)++;
6062 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_small) {
6063 state.world.naval_battle_get_attacker_small_ships_lost(b)++;
6064 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_transport) {
6065 state.world.naval_battle_get_attacker_transport_ships_lost(b)++;
6068 if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_big) {
6069 state.world.naval_battle_get_defender_big_ships_lost(b)++;
6070 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_small) {
6071 state.world.naval_battle_get_defender_small_ships_lost(b)++;
6072 }
else if((slots[j].flags & ship_in_battle::type_mask) == ship_in_battle::type_transport) {
6073 state.world.naval_battle_get_defender_transport_ships_lost(b)++;
6076 slots[j].flags &= ~ship_in_battle::mode_mask;
6077 slots[j].flags |= ship_in_battle::mode_sunk;
6080 if((slots[j].flags & ship_in_battle::distance_mask) >= 1000) {
6081 slots[j].flags &= ~ship_in_battle::mode_mask;
6082 slots[j].flags |= ship_in_battle::mode_retreated;
6091 for(
auto i = isize; i-- > 0;) {
6092 dcon::naval_battle_id b{ dcon::naval_battle_id::value_base_t(i) };
6093 if(
state.world.naval_battle_is_valid(b) && to_delete.get(b) != 0) {
6094 end_battle(state, b, to_delete.get(b) ==
uint8_t(1) ? battle_result::attacker_won : battle_result::defender_won);
6099 dcon::ship_id s{dcon::ship_id::value_base_t(i)};
6100 if(
state.world.ship_is_valid(s)) {
6101 if(
state.world.ship_get_strength(s) <= 0.0f) {
6102 state.world.delete_ship(s);
6110 auto low_roll = rvals.low % 10;
6111 auto high_roll = rvals.high % 10;
6112 return uint8_t((high_roll << 4) | low_roll);
6115void navy_arrives_in_province(
sys::state& state, dcon::navy_id n, dcon::province_id p, dcon::naval_battle_id from) {
6116 assert(state.world.navy_is_valid(n));
6117 assert(!state.world.navy_get_battle_from_navy_battle_participation(n));
6119 state.world.navy_set_location_from_navy_location(n, p);
6120 auto ships = state.world.navy_get_navy_membership(n);
6121 if(!state.world.navy_get_is_retreating(n) && p.index() >= state.province_definitions.first_sea_province.index() && ships.begin() != ships.end()) {
6122 auto owner_nation = state.world.navy_get_controller_from_navy_control(n);
6125 for(
auto b : state.world.province_get_naval_battle_location(p)) {
6126 if(b.get_battle() != from) {
6127 auto battle_war = b.get_battle().get_war_from_naval_battle_in_war();
6128 auto owner_role = get_role(state, battle_war, owner_nation);
6129 if(owner_role != war_role::none) {
6130 add_navy_to_battle(state, n, b.get_battle(), owner_role);
6137 dcon::naval_battle_id gather_to_battle;
6138 dcon::war_id battle_in_war;
6140 for(
auto o : state.world.province_get_navy_location(p)) {
6141 if(o.get_navy() == n)
6143 if(o.get_navy().get_is_retreating() || o.get_navy().get_battle_from_navy_battle_participation())
6146 auto other_nation = o.get_navy().get_controller_from_navy_control();
6148 if(
auto par = internal_find_war_between(state, owner_nation, other_nation); par.
role != war_role::none) {
6149 auto new_battle = fatten(state.world, state.world.create_naval_battle());
6150 new_battle.set_war_attacker_is_attacker(par.role == war_role::attacker);
6151 new_battle.set_start_date(state.current_date);
6152 new_battle.set_war_from_naval_battle_in_war(par.w);
6153 new_battle.set_location_from_naval_battle_location(p);
6154 new_battle.set_dice_rolls(make_dice_rolls(state,
uint32_t(new_battle.id.value)));
6156 add_navy_to_battle(state, n, new_battle, par.role);
6157 add_navy_to_battle(state, o.get_navy(), new_battle,
6158 par.role == war_role::attacker ? war_role::defender : war_role::attacker);
6160 gather_to_battle = new_battle.id;
6161 battle_in_war = par.w;
6166 if(gather_to_battle) {
6167 for(
auto o : state.world.province_get_navy_location(p)) {
6168 if(o.get_navy() == n)
6170 if(o.get_navy().get_is_retreating() || o.get_navy().get_battle_from_navy_battle_participation())
6173 auto other_nation = o.get_navy().get_controller_from_navy_control();
6175 if(
auto role = get_role(state, battle_in_war, other_nation); role != war_role::none) {
6176 add_navy_to_battle(state, o.get_navy(), gather_to_battle, role);
6186 for(
auto a : state.world.in_army) {
6187 auto arrival = a.get_arrival_time();
6188 assert(!arrival || arrival >= state.current_date);
6189 if(
auto path = a.get_path(); arrival == state.current_date) {
6191 auto dest = path.at(path.size() - 1);
6193 auto from = state.world.army_get_location_from_army_location(a);
6195 if(dest.index() >= state.province_definitions.first_sea_province.index()) {
6197 auto to_navy = find_embark_target(state, a.get_controller_from_army_control(), dest, a);
6199 a.set_location_from_army_location(dest);
6200 a.set_navy_from_army_transport(to_navy);
6201 a.set_black_flag(
false);
6206 if(a.get_black_flag()) {
6208 a.set_black_flag(
false);
6210 army_arrives_in_province(state, a, dest,
6211 (state.world.province_adjacency_get_type(state.world.get_province_adjacency_by_province_pair(dest, from)) &
6215 a.set_navy_from_army_transport(dcon::navy_id{});
6217 if(
auto n = a.get_navy_from_army_transport()) {
6218 if(!n.get_battle_from_navy_battle_participation()) {
6220 a.set_navy_from_army_transport(dcon::navy_id{});
6225 auto path_bits = state.world.province_adjacency_get_type(state.world.get_province_adjacency_by_province_pair(dest, from));
6227 auto port = state.world.province_get_port_to(from);
6228 bool hostile_in_port =
false;
6229 auto controller = a.get_controller_from_army_control();
6230 for(
auto v : state.world.province_get_navy_location(port)) {
6232 hostile_in_port =
true;
6236 if(!hostile_in_port) {
6242 army_arrives_in_province(state, a, dest,
6253 if(a.get_battle_from_army_battle_participation()) {
6255 }
else if(path.size() > 0) {
6256 auto next_dest = path.at(path.size() - 1);
6257 a.set_arrival_time(arrival_time_to(state, a, next_dest));
6260 if(a.get_is_retreating()) {
6261 a.set_is_retreating(
false);
6262 army_arrives_in_province(state, a, dest,
6263 (state.world.province_adjacency_get_type(state.world.get_province_adjacency_by_province_pair(dest, from)) &
6268 if(a.get_moving_to_merge()) {
6269 a.set_moving_to_merge(
false);
6271 for(
auto ar : state.world.province_get_army_location(dest)) {
6272 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()) {
6273 auto regs = state.world.army_get_army_membership(a);
6274 while(regs.begin() != regs.end()) {
6275 (*regs.begin()).set_army(ar.get_army());
6282 if(state.world.army_get_is_rebel_hunter(a)
6283 && state.world.province_get_nation_from_province_control(dest)
6284 && state.world.nation_get_is_player_controlled(state.world.army_get_controller_from_army_control(a))
6285 && !state.world.army_get_battle_from_army_battle_participation(a)
6286 && !state.world.army_get_navy_from_army_transport(a)) {
6294 for(
auto n :
state.world.in_navy) {
6295 auto arrival =
n.get_arrival_time();
6296 assert(!arrival || arrival >=
state.current_date);
6297 if(
auto path =
n.get_path(); arrival ==
state.current_date) {
6299 auto dest = path.at(path.size() - 1);
6302 if(
dest.index() <
state.province_definitions.first_sea_province.index()) {
6305 n.set_location_from_navy_location(dest);
6308 auto attached =
state.world.navy_get_army_transport(n);
6309 while(attached.begin() != attached.end()) {
6310 auto a = (*attached.begin()).get_army();
6312 a.set_navy_from_army_transport(dcon::navy_id{});
6313 a.get_path().clear();
6315 auto acontroller = a.get_controller_from_army_control();
6317 if(acontroller && !acontroller.get_is_player_controlled()) {
6318 auto army_dest = a.get_ai_province();
6319 a.set_location_from_army_location(dest);
6320 if(army_dest && army_dest != dest) {
6322 if(apath.size() > 0) {
6323 auto existing_path = a.get_path();
6324 auto new_size =
uint32_t(apath.size());
6325 existing_path.resize(new_size);
6327 for(
uint32_t i = 0; i < new_size; ++i) {
6328 existing_path[i] = apath[i];
6355 for(
auto a :
state.world.navy_get_army_transport(n)) {
6356 a.get_army().set_location_from_army_location(dest);
6357 a.get_army().get_path().clear();
6358 a.get_army().set_arrival_time(
sys::date{});
6362 if(
n.get_battle_from_navy_battle_participation()) {
6364 }
else if(path.size() > 0) {
6365 auto next_dest = path.at(path.size() - 1);
6369 if(
n.get_is_retreating()) {
6370 if(
dest.index() >=
state.province_definitions.first_sea_province.index())
6372 n.set_is_retreating(
false);
6374 if(
n.get_moving_to_merge()) {
6375 n.set_moving_to_merge(
false);
6377 for(
auto ar :
state.world.province_get_navy_location(dest)) {
6378 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()) {
6379 auto regs =
state.world.navy_get_navy_membership(n);
6380 while(regs.begin() != regs.end()) {
6381 (*regs.begin()).set_navy(ar.get_navy());
6383 auto a =
state.world.navy_get_army_transport(n);
6384 while(a.begin() != a.end()) {
6385 (*a.begin()).set_navy(ar.get_navy());
6397float fractional_distance_covered(
sys::state& state, dcon::army_id a) {
6398 auto date = state.world.army_get_arrival_time(a);
6401 auto p = state.world.army_get_path(a);
6404 if(state.world.army_get_battle_from_army_battle_participation(a))
6407 auto dest = *(p.end() - 1);
6408 auto full_time = arrival_time_to(state, a, dest);
6410 auto difference = full_time.value - state.current_date.value;
6411 auto covered = date.value - state.current_date.value;
6416 return 1.0f - float(covered) / float(difference);
6418float fractional_distance_covered(
sys::state& state, dcon::navy_id a) {
6419 auto date = state.world.navy_get_arrival_time(a);
6422 auto p = state.world.navy_get_path(a);
6425 if(state.world.navy_get_battle_from_navy_battle_participation(a))
6428 auto dest = *(p.end() - 1);
6429 auto full_time = arrival_time_to(state, a, dest);
6431 auto difference = full_time.value - state.current_date.value;
6432 auto covered = date.value - state.current_date.value;
6437 return 1.0f - float(covered) / float(difference);
6440int32_t transport_capacity(
sys::state& state, dcon::navy_id n) {
6442 for(
auto s : state.world.navy_get_navy_membership(n)) {
6443 if(state.military_definitions.unit_base_definitions[s.get_ship().get_type()].type == unit_type::transport)
6448int32_t free_transport_capacity(
sys::state& state, dcon::navy_id n) {
6449 int32_t used_total = 0;
6450 for(
auto a : state.world.navy_get_army_transport(n)) {
6451 auto regs = a.get_army().get_army_membership();
6452 used_total += int32_t(regs.end() - regs.begin());
6460 auto a = fatten(state.world, ar);
6461 auto controller = a.get_controller_from_army_control();
6462 static std::vector<rebel::impl::prov_str> rebel_provs;
6463 rebel_provs.clear();
6467 for(
auto& next_prov : rebel_provs) {
6468 if(prov == next_prov.p)
6472 if(path.size() > 0) {
6473 auto existing_path = state.world.army_get_path(a);
6475 auto new_size =
uint32_t(path.size());
6476 existing_path.resize(new_size);
6478 for(
uint32_t i = new_size; i-- > 0; ) {
6479 existing_path.at(i) = path[i];
6483 state.world.army_set_dig_in(a, 0);
6488 if(!a.get_arrival_time()) {
6489 auto home = a.get_ai_province();
6494 if(path.size() > 0) {
6495 auto existing_path = state.world.army_get_path(a);
6497 auto new_size =
uint32_t(path.size());
6498 existing_path.resize(new_size);
6500 for(
uint32_t i = new_size; i-- > 0; ) {
6501 existing_path.at(i) = path[i];
6505 state.world.army_set_dig_in(a, 0);
6510bool siege_potential(
sys::state& state, dcon::nation_id army_controller, dcon::nation_id province_controller) {
6511 bool will_siege =
false;
6512 if(!army_controller) {
6513 will_siege = bool(province_controller);
6515 if(!province_controller) {
6517 }
else if(
are_at_war(state, province_controller, army_controller)) {
6525void update_siege_progress(
sys::state& state) {
6526 static auto new_nation_controller = ve::vectorizable_buffer<dcon::nation_id, dcon::province_id>(state.world.province_size());
6527 static auto new_rebel_controller = ve::vectorizable_buffer<dcon::rebel_faction_id, dcon::province_id>(state.world.province_size());
6529 new_nation_controller.set(ids, dcon::nation_id{});
6530 new_rebel_controller.set(ids, dcon::rebel_faction_id{});
6533 concurrency::parallel_for(0,
state.province_definitions.first_sea_province.index(), [&](int32_t
id) {
6534 dcon::province_id prov{dcon::province_id::value_base_t(id)};
6536 auto controller =
state.world.province_get_nation_from_province_control(prov);
6537 auto owner =
state.world.province_get_nation_from_province_ownership(prov);
6542 float max_siege_value = 0.0f;
6543 float strength_siege_units = 0.0f;
6544 float max_recon_value = 0.0f;
6545 float strength_recon_units = 0.0f;
6546 float total_sieging_strength = 0.0f;
6547 bool owner_involved =
false;
6548 bool core_owner_involved =
false;
6550 dcon::army_id first_army;
6552 for(
auto ar :
state.world.province_get_army_location(prov)) {
6555 if(ar.get_army().get_battle_from_army_battle_participation() || ar.get_army().get_black_flag() ||
6556 ar.get_army().get_navy_from_army_transport() || ar.get_army().get_arrival_time()) {
6560 auto army_controller = ar.get_army().get_controller_from_army_control();
6562 if(siege_potential(state, army_controller, controller)) {
6564 first_army = ar.get_army();
6566 auto army_stats = army_controller ? army_controller : ar.get_army().get_army_rebel_control().get_controller().get_ruler_from_rebellion_within();
6568 owner_involved = owner_involved || owner == army_controller;
6569 core_owner_involved =
6570 core_owner_involved || bool(state.world.get_core_by_prov_tag_key(prov, state.world.nation_get_identity_from_identity_holder(army_controller)));
6572 for(auto r : ar.get_army().get_army_membership()) {
6573 auto reg_str = r.get_regiment().get_strength();
6574 if(reg_str > 0.001f) {
6575 auto type = r.get_regiment().get_type();
6576 auto& stats = state.world.nation_get_unit_stats(army_stats, type);
6578 total_sieging_strength += reg_str;
6580 if(stats.siege_or_torpedo_attack > 0.0f) {
6581 strength_siege_units += reg_str;
6582 max_siege_value = std::max(max_siege_value, stats.siege_or_torpedo_attack);
6584 if(stats.reconnaissance_or_fire_range > 0.0f) {
6585 strength_recon_units += reg_str;
6586 max_recon_value = std::max(max_recon_value, stats.reconnaissance_or_fire_range);
6594 if(total_sieging_strength == 0.0f) {
6597 auto local_battles =
state.world.province_get_land_battle_location(prov);
6598 if(local_battles.begin() != local_battles.end()) {
6601 auto& progress = state.world.province_get_siege_progress(prov);
6602 progress = std::max(0.0f, progress - 0.1f);
6605 assert(
bool(first_army));
6614 int32_t effective_fort_level =
6616 int32_t(max_siege_value *
6617 std::min(strength_siege_units / total_sieging_strength,
state.defines.engineer_unit_ratio) /
6618 state.defines.engineer_unit_ratio),
6627 float siege_speed_modifier =
6628 1.0f +
state.defines.recon_siege_effect * max_recon_value *
6629 std::min(strength_recon_units / total_sieging_strength,
state.defines.recon_unit_ratio) /
6630 state.defines.recon_unit_ratio;
6639 float num_brigades =
6640 std::min(
state.defines.siege_brigades_max, total_sieging_strength * 1000.0f /
state.defines.pop_size_per_regiment);
6641 float num_brigades_modifier =
6642 num_brigades >
state.defines.siege_brigades_min
6643 ? 1.0f + (num_brigades -
state.defines.siege_brigades_min) *
state.defines.siege_brigades_bonus
6644 : num_brigades /
state.defines.siege_brigades_min;
6652 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};
6653 static constexpr float progress_table[] = {0.0f, 0.2f, 0.5f, 0.75f, 0.75f, 1, 1.1f, 1.1f, 1.25f, 1.25f};
6655 float added_progress = siege_speed_modifier * num_brigades_modifier *
6657 (owner_involved ? 1.25f : (core_owner_involved ? 1.1f : 1.0f)) / siege_table[effective_fort_level];
6659 auto&
progress =
state.world.province_get_siege_progress(prov);
6662 if(progress >= 1.0f) {
6671 auto old_rf =
state.world.province_get_rebel_faction_from_province_rebel_control(prov);
6673 for(
auto pop :
state.world.province_get_pop_location(prov)) {
6675 pop.get_pop().get_militancy() /=
state.defines.reduction_after_defeat;
6680 state.world.province_set_former_controller(prov, controller);
6681 state.world.province_set_former_rebel_controller(prov, old_rf);
6683 auto new_controller =
state.world.army_get_controller_from_army_control(first_army);
6684 if(new_controller && !
are_at_war(state, new_controller, owner)) {
6685 new_controller =
owner;
6688 auto rebel_controller =
state.world.army_get_controller_from_army_rebel_control(first_army);
6689 assert(
bool(new_controller) !=
bool(rebel_controller));
6691 new_nation_controller.set(prov, new_controller);
6692 new_rebel_controller.set(prov, rebel_controller);
6698 if(
auto nc = new_nation_controller.get(prov); nc) {
6699 province::set_province_controller(state, prov, nc);
6700 eject_ships(state, prov);
6702 auto cc = state.world.province_get_nation_from_province_control(prov);
6703 auto oc = state.world.province_get_former_controller(prov);
6706 notification::post(state, notification::message{
6708 crc = state.world.province_get_rebel_faction_from_province_rebel_control(prov),
6709 orc = state.world.province_get_former_rebel_controller(prov)](sys::state& state, text::layout_base& contents) {
6711 text::add_line(state, contents,
"msg_siegeover_1", text::variable_type::x, prov);
6713 text::add_line(state, contents,
"msg_siegeover_2", text::variable_type::x, oc);
6715 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)));
6717 text::add_line(state, contents,
"msg_siegeover_4", text::variable_type::x, cc);
6719 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)));
6721 "msg_siegeover_title",
6722 cc, oc, dcon::nation_id{},
6723 sys::message_base_type::siegeover
6727 for(
auto ar :
state.world.province_get_army_location(prov)) {
6728 auto a = ar.get_army();
6730 if(a.get_is_rebel_hunter()
6731 && a.get_controller_from_army_control().get_is_player_controlled()
6732 && !a.get_battle_from_army_battle_participation()
6733 && !a.get_navy_from_army_transport()
6734 && !a.get_arrival_time()) {
6736 send_rebel_hunter_to_next_province(state, a, prov);
6748 if(
auto nr = new_rebel_controller.get(prov); nr) {
6749 province::set_province_controller(state, prov, nr);
6750 eject_ships(state, prov);
6752 auto cc = state.world.province_get_nation_from_province_control(prov);
6753 auto oc = state.world.province_get_former_controller(prov);
6754 auto within = state.world.rebel_faction_get_ruler_from_rebellion_within(nr);
6755 auto t = state.world.rebel_faction_get_type(nr);
6756 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))) {
6757 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)));
6763void update_blackflag_status(
sys::state& state, dcon::province_id p) {
6764 for(
auto ar : state.world.province_get_army_location(p)) {
6765 if(!ar.get_army().get_battle_from_army_battle_participation() && !ar.get_army().get_navy_from_army_transport()) {
6766 auto controller = ar.get_army().get_controller_from_army_control();
6772void eject_ships(
sys::state& state, dcon::province_id p) {
6773 auto sea_zone = state.world.province_get_port_to(p);
6778 static std::vector<dcon::navy_id> to_eject;
6781 for(
auto n : state.world.province_get_navy_location(p)) {
6783 to_eject.push_back(n.get_navy().id);
6786 for(
auto n : to_eject) {
6789 for(
auto a :
state.world.navy_get_army_transport(n)) {
6790 a.get_army().set_location_from_army_location(sea_zone);
6791 a.get_army().get_path().clear();
6792 a.get_army().set_arrival_time(
sys::date{});
6798 if(state.current_date.value % int32_t(state.defines.dig_in_increase_each_days) == 0) {
6799 for(
auto ar : state.world.in_army) {
6800 if(ar.get_is_retreating() || ar.get_black_flag() ||
bool(ar.get_battle_from_army_battle_participation()) ||
6801 bool(ar.get_navy_from_army_transport()) ||
bool(ar.get_arrival_time())) {
6805 auto& current_dig_in = ar.get_dig_in();
6807 int32_t(ar.get_controller_from_army_control().get_modifier_values(sys::national_mod_offsets::dig_in_cap))) {
6815 uint32_t total_commodities = state.world.commodity_size();
6822 for(
auto r :
state.world.army_get_army_membership(army)) {
6824 auto type =
state.world.regiment_get_type(r.get_regiment());
6826 auto o_sc_mod = std::max(0.01f,
state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::supply_consumption) + 1.0f);
6827 auto& supply_cost =
state.military_definitions.unit_base_definitions[
type].supply_cost;
6829 if(supply_cost.commodity_type[i]) {
6830 commodities.
commodity_amounts[i] += supply_cost.commodity_amounts[i] *
state.world.nation_get_unit_stats(owner, type).supply_consumption * o_sc_mod;
6844 float supply_amount = .0f;
6845 int32_t amount_of_units = 0;
6852 for(
auto sh :
state.world.navy_get_navy_membership(navy)) {
6854 auto type =
state.world.ship_get_type(sh.get_ship());
6857 auto o_sc_mod = std::max(0.01f,
state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::supply_consumption) + 1.0f);
6858 auto& supply_cost =
state.military_definitions.unit_base_definitions[
type].supply_cost;
6860 if(supply_cost.commodity_type[i]) {
6862 supply_cost.commodity_amounts[i] *
state.world.nation_get_unit_stats(owner, type).supply_consumption *
6884 for(
auto ar : state.world.in_army) {
6885 if(ar.get_army_battle_participation().get_battle() || ar.get_navy_from_army_transport())
6888 auto in_nation = ar.get_controller_from_army_control();
6889 auto tech_nation = in_nation ? in_nation : ar.get_controller_from_army_rebel_control().get_ruler_from_rebellion_within();
6891 auto leader = ar.get_general_from_army_leadership();
6892 auto regen_mod = tech_nation.get_modifier_values(sys::national_mod_offsets::org_regain) +
6893 leader.get_personality().get_morale() + leader.get_background().get_morale() + 1.0f
6894 + leader.get_prestige() * state.defines.leader_prestige_to_morale_factor;
6895 auto spending_level = (in_nation ? in_nation.get_effective_land_spending() : 1.0f);
6896 auto modified_regen = regen_mod * spending_level / 150.0f;
6898 for(
auto reg : ar.get_army_membership()) {
6899 auto c_org = reg.get_regiment().get_org();
6900 reg.get_regiment().set_org(std::min(c_org + modified_regen, std::max(c_org, 0.25f + 0.75f * spending_level)));
6904 for(
auto ar :
state.world.in_navy) {
6905 if(ar.get_navy_battle_participation().get_battle())
6908 auto in_nation = ar.get_controller_from_navy_control();
6910 auto leader = ar.get_admiral_from_navy_leadership();
6911 auto regen_mod = in_nation.get_modifier_values(sys::national_mod_offsets::org_regain) +
6912 leader.get_personality().get_morale() +
leader.get_background().get_morale() + 1.0f
6913 +
leader.get_prestige() *
state.defines.leader_prestige_to_morale_factor;
6914 float oversize_amount =
6915 in_nation.get_naval_supply_points() > 0
6916 ? std::min(
float(in_nation.get_used_naval_supply_points()) /
float(in_nation.get_naval_supply_points()), 1.75f)
6918 float over_size_penalty = oversize_amount > 1.0f ? 2.0f - oversize_amount : 1.0f;
6919 auto spending_level = in_nation.get_effective_naval_spending() * over_size_penalty;
6920 auto modified_regen = regen_mod * spending_level / 150.0f;
6922 for(
auto reg : ar.get_navy_membership()) {
6923 auto c_org = reg.get_ship().get_org();
6924 reg.get_ship().set_org(std::min(c_org + modified_regen, std::max(c_org, 0.25f + 0.75f * spending_level)));
6929float reinforce_amount(
sys::state& state, dcon::army_id a) {
6930 auto ar = fatten(state.world, a);
6931 if(ar.get_battle_from_army_battle_participation() || ar.get_navy_from_army_transport() || ar.get_is_retreating())
6934 auto in_nation = ar.get_controller_from_army_control();
6935 auto tech_nation = in_nation ? in_nation : ar.get_controller_from_army_rebel_control().get_ruler_from_rebellion_within();
6937 auto spending_level = (in_nation ? in_nation.get_effective_land_spending() : 1.0f);
6939 float location_modifier = 1.0f;
6940 if(ar.get_location_from_army_location().get_nation_from_province_ownership() == in_nation) {
6941 location_modifier = 2.0f;
6942 }
else if(ar.get_location_from_army_location().get_nation_from_province_control() == in_nation) {
6943 location_modifier = 1.0f;
6945 location_modifier = 0.1f;
6948 auto combined =
state.defines.reinforce_speed * spending_level * location_modifier *
6949 (1.0f + tech_nation.get_modifier_values(sys::national_mod_offsets::reinforce_speed)) *
6950 (1.0f + tech_nation.get_modifier_values(sys::national_mod_offsets::reinforce_rate));
6964 for(
auto ar : state.world.in_army) {
6965 if(ar.get_battle_from_army_battle_participation() || ar.get_navy_from_army_transport() || ar.get_is_retreating())
6968 auto in_nation = ar.get_controller_from_army_control();
6969 auto tech_nation = in_nation ? in_nation : ar.get_controller_from_army_rebel_control().get_ruler_from_rebellion_within();
6971 auto spending_level = (in_nation ? in_nation.get_effective_land_spending() : 1.0f);
6973 float location_modifier = 1.0f;
6974 if(ar.get_location_from_army_location().get_nation_from_province_ownership() == in_nation) {
6975 location_modifier = 2.0f;
6976 }
else if(ar.get_location_from_army_location().get_nation_from_province_control() == in_nation) {
6977 location_modifier = 1.0f;
6979 location_modifier = 0.1f;
6982 auto combined = state.defines.reinforce_speed * spending_level * location_modifier *
6983 (1.0f + tech_nation.get_modifier_values(sys::national_mod_offsets::reinforce_speed)) *
6984 (1.0f + tech_nation.get_modifier_values(sys::national_mod_offsets::reinforce_rate));
6986 for(
auto reg : ar.get_army_membership()) {
6987 auto pop = reg.get_regiment().get_pop_from_regiment_source();
6988 auto pop_size = pop.get_size();
6989 auto limit_fraction = std::max(state.defines.alice_full_reinforce, std::min(1.0f, pop_size / state.defines.pop_size_per_regiment));
6990 auto curstr = reg.get_regiment().get_strength();
6991 auto newstr = std::min(curstr + combined, limit_fraction);
6992 reg.get_regiment().set_strength(newstr);
6993 adjust_regiment_experience(state, in_nation.id, reg.get_regiment(), std::min(0.f, (newstr - curstr) * 5.f * state.defines.exp_gain_div));
7004 for(
auto n : state.world.in_navy) {
7006 if(!n.get_arrival_time() && nb_level > 0) {
7008 auto in_nation = n.get_controller_from_navy_control();
7010 float oversize_amount =
7011 in_nation.get_naval_supply_points() > 0
7012 ? std::min(
float(in_nation.get_used_naval_supply_points()) /
float(in_nation.get_naval_supply_points()), 1.75f)
7014 float over_size_penalty = oversize_amount > 1.0f ? 2.0f - oversize_amount : 1.0f;
7015 auto spending_level = in_nation.get_effective_naval_spending() * over_size_penalty;
7017 auto rr_mod = n.get_location_from_navy_location().get_modifier_values(sys::provincial_mod_offsets::local_repair) + 1.0f;
7018 auto reinf_mod = in_nation.get_modifier_values(sys::national_mod_offsets::reinforce_speed) + 1.0f;
7019 auto repair_val = rr_mod * reinf_mod * spending_level;
7021 for(
auto reg : n.get_navy_membership()) {
7022 auto curstr = reg.get_ship().get_strength();
7023 auto newstr = std::min(curstr + repair_val, 1.0f);
7024 reg.get_ship().set_strength(newstr);
7025 adjust_ship_experience(state, in_nation.id, reg.get_ship(), std::min(0.f, (newstr - curstr) * 5.f * state.defines.exp_gain_div));
7031void start_mobilization(
sys::state& state, dcon::nation_id n) {
7032 if(state.world.nation_get_is_mobilized(n))
7035 state.world.nation_set_is_mobilized(n,
true);
7040 auto real_regs = std::max(int32_t(state.world.nation_get_active_regiments(n)), int32_t(state.defines.min_mobilize_limit));
7041 state.world.nation_set_mobilization_remaining(n,
7042 uint16_t(real_regs * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::mobilization_impact)));
7044 auto schedule_array = state.world.nation_get_mobilization_schedule(n);
7045 schedule_array.clear();
7047 for(
auto pr : state.world.nation_get_province_ownership(n)) {
7048 if(pr.get_province().get_is_colonial())
7050 if(pr.get_province().get_nation_from_province_control() != n)
7052 if(mobilized_regiments_possible_from_province(state, pr.get_province()) <= 0)
7055 schedule_array.push_back(mobilization_order{
sys::date{}, pr.get_province().
id });
7058 std::sort(schedule_array.begin(), schedule_array.end(),
7059 [&, cap =
state.world.nation_get_capital(n)](mobilization_order
const& a, mobilization_order
const& b) {
7060 auto a_dist = province::direct_distance(state, a.where, cap);
7061 auto b_dist = province::direct_distance(state, b.where, cap);
7062 if(a_dist != b_dist)
7063 return a_dist > b_dist;
7064 return a.where.value < b.where.value;
7069 for(
uint32_t count = schedule_array.size(); count-- > 0;) {
7074 auto province_speed =
state.defines.mobilization_speed_base *
7075 float(1.0f +
state.defines.mobilization_speed_rails_mult *
7077 auto days = std::max(1, int32_t(1.0f / province_speed));
7079 schedule_array[
count].when =
state.current_date + delay;
7086 for(
auto& par :
state.crisis_participants) {
7090 state.crisis_temperature +=
state.defines.crisis_temperature_on_mobilize;
7097 "msg_mobilize_start_title",
7098 n, dcon::nation_id{}, dcon::nation_id{},
7103 if(!
state.world.nation_get_is_mobilized(
n))
7106 state.world.nation_set_is_mobilized(
n,
false);
7107 state.world.nation_set_mobilization_remaining(
n, 0);
7108 auto schedule_array =
state.world.nation_get_mobilization_schedule(
n);
7109 schedule_array.clear();
7111 for(
auto ar :
state.world.nation_get_army_control(
n)) {
7112 for(
auto rg : ar.get_army().get_army_membership()) {
7113 auto pop = rg.get_regiment().get_pop_from_regiment_source();
7114 if(!
pop ||
pop.get_poptype() !=
state.culture_definitions.soldiers) {
7115 rg.get_regiment().set_strength(0.0f);
7116 rg.get_regiment().set_pop_from_regiment_source(dcon::pop_id{});
7124 "msg_mobilize_end_title",
7125 n, dcon::nation_id{}, dcon::nation_id{},
7130 for(
auto n :
state.world.in_nation) {
7131 auto& to_mobilize =
n.get_mobilization_remaining();
7132 if(to_mobilize > 0) {
7133 auto schedule =
n.get_mobilization_schedule();
7134 auto s_size = schedule.size();
7136 auto back = schedule[s_size - 1];
7137 if(
state.current_date == back.when) {
7138 schedule.pop_back();
7139 bool mob_infantry =
state.world.nation_get_active_unit(
n,
state.military_definitions.infantry);
7143 if(
state.world.province_get_nation_from_province_control(back.where) ==
7144 state.world.province_get_nation_from_province_ownership(back.where)) {
7149 for(
auto pop :
state.world.province_get_pop_location(back.where)) {
7158 bool army_is_new =
false;
7161 for(
auto ar :
state.world.province_get_army_location(back.where)) {
7162 if(ar.get_army().get_controller_from_army_control() ==
n)
7163 return ar.get_army().id;
7166 new_army.set_controller_from_army_control(
n);
7167 new_army.set_is_ai_controlled(
n.get_mobilized_is_ai_controlled());
7173 while(available > 0 && to_mobilize > 0) {
7175 state.world.regiment_set_org(new_reg, 0.1f);
7176 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));
7177 state.world.try_create_army_membership(new_reg, a);
7178 auto p =
pop.get_pop();
7180 state.world.try_create_regiment_source(new_reg, p);
7192 if(to_mobilize == 0)
7204bool can_retreat_from_battle(
sys::state& state, dcon::naval_battle_id battle) {
7205 return (state.world.naval_battle_get_start_date(battle) + days_before_retreat < state.current_date);
7207bool can_retreat_from_battle(
sys::state& state, dcon::land_battle_id battle) {
7208 return (state.world.land_battle_get_start_date(battle) + days_before_retreat < state.current_date);
7211bool 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) {
7212 for(
auto wg : state.world.war_get_wargoals_attached(w)) {
7213 if(wg.get_wargoal().get_target_nation() == target) {
7214 if(
auto bits = wg.get_wargoal().get_type().get_type_bits(); (bits & (cb_flag::po_transfer_provinces | cb_flag::po_demand_state)) != 0) {
7215 if((bits & cb_flag::all_allowed_states) != 0) {
7216 auto state_filter = wg.get_wargoal().get_type().get_allowed_states();
7218 if((bits & cb_flag::po_transfer_provinces) != 0) {
7219 auto holder = state.world.national_identity_get_nation_from_identity_holder(wg.get_wargoal().get_associated_tag());
7222 for(
auto si : state.world.nation_get_state_ownership(target)) {
7228 }
else if((bits & cb_flag::po_demand_state) != 0) {
7231 for(
auto si : state.world.nation_get_state_ownership(target)) {
7239 if(wg.get_wargoal().get_associated_state() == cb_state)
7243 if((wg.get_wargoal().get_type().get_type_bits() & cb_flag::po_annex) != 0) {
7252bool 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) {
7255 if(state_claimed_in_war(state, w, source, target, cb_state))
7260 for(
auto wg :
state.world.war_get_wargoals_attached(w)) {
7261 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) {
7267 if((
state.world.cb_type_get_type_bits(cb_type) & cb_flag::po_demand_state) != 0) {
7268 for(
auto wg :
state.world.war_get_wargoals_attached(w)) {
7269 if((wg.get_wargoal().get_type().get_type_bits() & cb_flag::po_annex) != 0 && wg.get_wargoal().get_target_nation() == target) {
7276 auto bits =
state.world.cb_type_get_type_bits(cb_type);
7277 if((bits & cb_flag::po_annex) != 0) {
7278 for(
auto si :
state.world.nation_get_state_ownership(target)) {
7284 if((bits & cb_flag::all_allowed_states) != 0) {
7285 auto state_filter =
state.world.cb_type_get_allowed_states(cb_type);
7286 if((bits & cb_flag::po_transfer_provinces) != 0) {
7287 auto target_tag =
state.world.nation_get_identity_from_identity_holder(target);
7288 auto holder =
state.world.national_identity_get_nation_from_identity_holder(cb_tag);
7291 for(
auto si :
state.world.nation_get_state_ownership(target)) {
7300 }
else if((bits & cb_flag::po_demand_state) != 0) {
7301 auto target_tag =
state.world.nation_get_identity_from_identity_holder(target);
7304 for(
auto si :
state.world.nation_get_state_ownership(target)) {
7321 if(state.military_definitions.pending_blackflag_update) {
7322 state.military_definitions.pending_blackflag_update =
false;
7324 for(
auto a : state.world.in_army) {
7325 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())) {
7326 a.set_black_flag(
true);
7328 a.set_black_flag(
false);
7334bool rebel_army_in_province(
sys::state& state, dcon::province_id p) {
7335 for(
auto ar : state.world.province_get_army_location(p)) {
7336 if(ar.get_army().get_controller_from_army_rebel_control())
7341dcon::province_id find_land_rally_pt(
sys::state& state, dcon::nation_id by, dcon::province_id start) {
7342 float distance = 2.0f;
7343 dcon::province_id closest;
7344 auto region = state.world.province_get_connected_region_id(start);
7346 for(
auto p : state.world.nation_get_province_ownership(by)) {
7347 if(!p.get_province().get_land_rally_point())
7349 if(p.get_province().get_connected_region_id() != region)
7351 if(p.get_province().get_nation_from_province_control() != by)
7355 closest = p.get_province();
7361dcon::province_id find_naval_rally_pt(
sys::state& state, dcon::nation_id by, dcon::province_id start) {
7362 float distance = 2.0f;
7363 dcon::province_id closest;
7365 for(
auto p : state.world.nation_get_province_ownership(by)) {
7366 if(!p.get_province().get_naval_rally_point())
7368 if(p.get_province().get_nation_from_province_control() != by)
7372 closest = p.get_province();
7378void move_land_to_merge(
sys::state& state, dcon::nation_id by, dcon::army_id a, dcon::province_id start, dcon::province_id dest) {
7379 if(state.world.nation_get_is_player_controlled(by) ==
false)
7382 dest = find_land_rally_pt(state, by, start);
7383 if(!dest || state.world.province_get_nation_from_province_control(dest) != by)
7385 if(state.world.army_get_battle_from_army_battle_participation(a))
7389 for(
auto ar : state.world.province_get_army_location(start)) {
7390 if(ar.get_army().get_controller_from_army_control() == by && ar.get_army() != a) {
7391 auto regs = state.world.army_get_army_membership(a);
7392 while(regs.begin() != regs.end()) {
7393 (*regs.begin()).set_army(ar.get_army());
7403 auto existing_path =
state.world.army_get_path(a);
7404 auto new_size =
uint32_t(path.size());
7405 existing_path.resize(new_size);
7407 for(
uint32_t k = 0; k < new_size; ++k) {
7409 existing_path[k] = path[k];
7412 state.world.army_set_moving_to_merge(a,
true);
7416 if(
state.world.nation_get_is_player_controlled(by) ==
false)
7420 if(!
dest ||
state.world.province_get_nation_from_province_control(
dest) != by)
7424 for(
auto ar :
state.world.province_get_navy_location(start)) {
7425 if(ar.get_navy().get_controller_from_navy_control() == by && ar.get_navy() != a) {
7426 auto regs =
state.world.navy_get_navy_membership(a);
7427 while(regs.begin() != regs.end()) {
7428 (*regs.begin()).set_navy(ar.get_navy());
7438 auto existing_path =
state.world.navy_get_path(a);
7439 auto new_size =
uint32_t(path.size());
7440 existing_path.resize(new_size);
7442 for(
uint32_t k = 0; k < new_size; ++k) {
7444 existing_path[k] = path[k];
7447 state.world.navy_set_moving_to_merge(a,
true);
7451bool pop_eligible_for_mobilization(
sys::state& state, dcon::pop_id p) {
7453 return pop.get_poptype() != state.culture_definitions.soldiers
7454 && pop.get_poptype() != state.culture_definitions.slaves
7455 && pop.get_is_primary_or_accepted_culture()
7459void disband_regiment_w_pop_death(
sys::state& state, dcon::regiment_id reg_id) {
7460 auto base_pop = state.world.regiment_get_pop_from_regiment_source(reg_id);
7461 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));
7462 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)
void post(sys::state &state, message const &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)
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 mobilization_size(sys::state const &state, dcon::nation_id n)
void run_gc(sys::state &state)
float truce_break_cb_infamy(sys::state &state, dcon::cb_type_id t)
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)
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)
int32_t total_regiments(sys::state &state, dcon::nation_id n)
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)
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)
void update_blockade_status(sys::state &state)
void end_wars_between(sys::state &state, dcon::nation_id a, dcon::nation_id b)
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)
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)
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)
dcon::ship_id create_new_ship(sys::state &state, dcon::nation_id n, dcon::unit_type_id t)
void cleanup_navy(sys::state &state, dcon::navy_id n)
void add_cb(sys::state &state, dcon::nation_id n, dcon::cb_type_id cb, dcon::nation_id target)
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_defender_wargoal(sys::state const &state, dcon::war_id w, dcon::wargoal_id wg)
void regenerate_land_unit_average(sys::state &state)
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)
float cb_infamy(sys::state const &state, dcon::cb_type_id t)
bool cb_requires_selection_of_a_valid_nation(sys::state const &state, dcon::cb_type_id t)
constexpr float str_dam_mul
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)
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)
float crisis_cb_addition_infamy_cost(sys::state &state, dcon::cb_type_id type, dcon::nation_id from, dcon::nation_id target)
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)
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)
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 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)
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)
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)
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 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)
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)
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)
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)
MOD_PROV_LIST constexpr uint32_t count
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
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)
float commodity_amounts[set_size]
dcon::commodity_id commodity_type[set_size]
static constexpr uint32_t set_size