Project Alice
Loading...
Searching...
No Matches
commands.cpp
Go to the documentation of this file.
1#include "commands.hpp"
2#include "demographics.hpp"
4#include "effects.hpp"
5#include "gui_event.hpp"
6#include "serialization.hpp"
7#include "system_state.hpp"
8#include "nations.hpp"
10#include "politics.hpp"
12#include "rebels.hpp"
13#include "triggers.hpp"
14#include "ai.hpp"
15#include "gui_console.hpp"
16
17namespace command {
18
20 return uint8_t(t) == 255;
21}
22
25
26 switch(p.type) {
39 // Notifications can be sent because it's an-always do thing
40 break;
41 default:
42 // Normal commands are discarded iff we are not in the game
43 if(!state.current_scene.game_in_progress)
44 return;
45 state.network_state.is_new_game = false;
46 break;
47 }
48
49 switch(state.network_mode) {
51 {
52 bool b = state.incoming_commands.try_push(p);
53 break;
54 }
57 {
59 break;
60 state.network_state.outgoing_commands.push(p);
61 break;
62 }
63 default:
64 break;
65 }
66}
67
68void set_rally_point(sys::state& state, dcon::nation_id source, dcon::province_id location, bool naval, bool enable) {
69 payload p;
70 memset(&p, 0, sizeof(payload));
72 p.source = source;
73 p.data.rally_point.location = location;
74 p.data.rally_point.naval = naval;
75 p.data.rally_point.enable = enable;
76 add_to_command_queue(state, p);
77}
78
79void execute_set_rally_point(sys::state& state, dcon::nation_id source, dcon::province_id location, bool naval, bool enable) {
80 if(state.world.province_get_nation_from_province_ownership(location) != source)
81 return;
82 if(naval) {
83 if(state.world.province_get_is_coast(location))
84 state.world.province_set_naval_rally_point(location, enable);
85 } else {
86 state.world.province_set_land_rally_point(location, enable);
87 }
88}
89
90void save_game(sys::state& state, dcon::nation_id source, bool and_quit) {
91 payload p;
92 memset(&p, 0, sizeof(payload));
94 p.source = source;
95 p.data.save_game.and_quit = and_quit;
96 add_to_command_queue(state, p);
97}
98
99void execute_save_game(sys::state& state, dcon::nation_id source, bool and_quit) {
101
102 if(and_quit) {
104 }
105}
106
107void set_national_focus(sys::state& state, dcon::nation_id source, dcon::state_instance_id target_state,
108 dcon::national_focus_id focus) {
109 payload p;
110 memset(&p, 0, sizeof(payload));
112 p.source = source;
113 p.data.nat_focus.focus = focus;
114 p.data.nat_focus.target_state = target_state;
115 add_to_command_queue(state, p);
116}
117
118bool can_set_national_focus(sys::state& state, dcon::nation_id source, dcon::state_instance_id target_state,
119 dcon::national_focus_id focus) {
120 if(!focus) {
121 return true;
122 } else {
123 auto num_focuses_set = nations::national_focuses_in_use(state, source);
124 auto num_focuses_total = nations::max_national_focuses(state, source);
125 auto state_owner = state.world.state_instance_get_nation_from_state_ownership(target_state);
126
127 if(state_owner == source) {
128 if(focus == state.national_definitions.flashpoint_focus)
129 return false;
130 if(auto ideo = state.world.national_focus_get_ideology(focus); ideo) {
131 if(state.world.ideology_get_enabled(ideo) == false ||
132 (state.world.ideology_get_is_civilized_only(ideo) && !state.world.nation_get_is_civilized(source))) {
133 return false;
134 }
135 }
136 auto prov = state.world.state_instance_get_capital(target_state);
137 auto k = state.world.national_focus_get_limit(focus);
138 if(k && !trigger::evaluate(state, k, trigger::to_generic(prov), trigger::to_generic(state_owner), -1))
139 return false;
140 return num_focuses_set < num_focuses_total || bool(state.world.state_instance_get_owner_focus(target_state));
141 } else {
142 auto pc = state.world.nation_get_primary_culture(source);
143 if(nations::nation_accepts_culture(state, state_owner, pc))
144 return false;
145
146 auto ident = state.world.nation_get_identity_from_identity_holder(source);
147 if(state.world.national_identity_get_is_not_releasable(ident))
148 return false;
149
150 bool state_contains_core = false;
151 province::for_each_province_in_state_instance(state, target_state, [&](dcon::province_id p) {
152 state_contains_core = state_contains_core || bool(state.world.get_core_by_prov_tag_key(p, ident));
153 });
154 bool rank_high = state.world.nation_get_rank(source) > uint16_t(state.defines.colonial_rank);
155 bool is_tension_focus = focus == state.national_definitions.flashpoint_focus;
156 return state_contains_core && rank_high && is_tension_focus &&
157 (num_focuses_set < num_focuses_total || bool(state.world.nation_get_state_from_flashpoint_focus(source))) &&
158 bool(state.world.state_instance_get_nation_from_flashpoint_focus(target_state)) == false;
159 }
160 }
161}
162
163void execute_set_national_focus(sys::state& state, dcon::nation_id source, dcon::state_instance_id target_state, dcon::national_focus_id focus) {
164 if(state.world.state_instance_get_nation_from_state_ownership(target_state) == source) {
165 state.world.state_instance_set_owner_focus(target_state, focus);
166 } else {
167 if(focus)
168 state.world.nation_set_state_from_flashpoint_focus(source, target_state);
169 else
170 state.world.nation_set_state_from_flashpoint_focus(source, dcon::state_instance_id{});
171 }
172}
173
174void start_research(sys::state& state, dcon::nation_id source, dcon::technology_id tech) {
175 payload p;
176 memset(&p, 0, sizeof(payload));
178 p.source = source;
179 p.data.start_research.tech = tech;
180 add_to_command_queue(state, p);
181}
182
183bool can_start_research(sys::state& state, dcon::nation_id source, dcon::technology_id tech) {
184 /* Nations can only start researching technologies if, they are not uncivilized, the tech
185 activation date is past by, and all the previous techs (if any) of the same folder index
186 are already researched fully. And they are not already researched. */
187 if(!tech)
188 return false;
189 if(state.world.nation_get_active_technologies(source, tech))
190 return false; // Already researched
191 if(nations::current_research(state, source) == tech)
192 return false; // Already being researched
193 if(!state.world.nation_get_is_civilized(source))
194 return false; // Must be civilized
195 if(state.current_date.to_ymd(state.start_date).year >= state.world.technology_get_year(tech)) {
196 // Find previous technology before this one
197 dcon::technology_id prev_tech = dcon::technology_id(dcon::technology_id::value_base_t(tech.index() - 1));
198 // Previous technology is from the same folder so we have to check that we have researched it beforehand
199 if(tech.index() != 0 && state.world.technology_get_folder_index(prev_tech) == state.world.technology_get_folder_index(tech)) {
200 // Only allow if all previously researched techs are researched
201 return state.world.nation_get_active_technologies(source, prev_tech);
202 }
203 return true; // First technology on folder can always be researched
204 }
205 return false;
206}
207
208void execute_start_research(sys::state& state, dcon::nation_id source, dcon::technology_id tech) {
209 if(state.world.nation_get_current_research(source))
210 state.world.nation_set_research_points(source, 0.0f);
211 state.world.nation_set_current_research(source, tech);
212}
213
214void make_leader(sys::state& state, dcon::nation_id source, bool general) {
215 payload p;
216 memset(&p, 0, sizeof(payload));
218 p.source = source;
219 p.data.make_leader.is_general = general;
220 add_to_command_queue(state, p);
221}
222bool can_make_leader(sys::state& state, dcon::nation_id source, bool general) {
223 return state.world.nation_get_leadership_points(source) >= state.defines.leader_recruit_cost;
224}
225void execute_make_leader(sys::state& state, dcon::nation_id source, bool general) {
226 military::make_new_leader(state, source, general);
227}
228
229
230void give_war_subsidies(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
231 payload p;
232 memset(&p, 0, sizeof(payload));
234 p.source = source;
235 p.data.diplo_action.target = target;
236 add_to_command_queue(state, p);
237}
238bool can_give_war_subsidies(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
239 /* Can only perform if, the nations are not at war, the nation isn't already being given war subsidies, and there is
240 * defines:WARSUBSIDY_DIPLOMATIC_COST diplomatic points available. And the target isn't equal to the sender. */
241 if(source == target)
242 return false; // Can't negotiate with self
243 if(military::are_at_war(state, source, target))
244 return false; // Can't be at war
245 if(!state.world.nation_get_is_at_war(target))
246 return false; // target must be at war
247 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, source);
248 if(rel && state.world.unilateral_relationship_get_war_subsidies(rel))
249 return false; // Can't already be giving war subsidies
250
251 if(state.world.nation_get_is_player_controlled(source))
252 return state.world.nation_get_diplomatic_points(source) >= state.defines.warsubsidy_diplomatic_cost; // Enough diplomatic points
253 return true;
254}
255void execute_give_war_subsidies(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
256 nations::adjust_relationship(state, source, target, state.defines.warsubsidy_relation_on_accept);
257 state.world.nation_get_diplomatic_points(source) -= state.defines.warsubsidy_diplomatic_cost;
258 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, source);
259 if(!rel)
260 rel = state.world.force_create_unilateral_relationship(target, source);
261
262 state.world.unilateral_relationship_set_war_subsidies(rel, true);
263
265 [source, target](sys::state& state, text::layout_base& contents) {
266 text::add_line(state, contents, "msg_wsub_start_1", text::variable_type::x, source, text::variable_type::y, target);
267 },
268 "msg_wsub_start_title",
269 source, target, dcon::nation_id{},
271 });
272}
273
274
275void cancel_war_subsidies(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
276 payload p;
277 memset(&p, 0, sizeof(payload));
279 p.source = source;
280 p.data.diplo_action.target = target;
281 add_to_command_queue(state, p);
282}
283bool can_cancel_war_subsidies(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
284 /* Can only perform if, the nations are not at war, the nation is already being given war subsidies, and there is
285 * defines:CANCELWARSUBSIDY_DIPLOMATIC_COST diplomatic points available. And the target isn't equal to the sender. */
286 if(source == target)
287 return false; // Can't negotiate with self
288 if(military::are_at_war(state, source, target))
289 return false; // Can't be at war
290 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, source);
291 if(rel && !state.world.unilateral_relationship_get_war_subsidies(rel))
292 return false; // Must already be giving war subsidies
293 if(state.world.nation_get_is_player_controlled(source))
294 return state.world.nation_get_diplomatic_points(source) >= state.defines.cancelwarsubsidy_diplomatic_cost; // Enough diplomatic points
295 return true;
296}
297void execute_cancel_war_subsidies(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
298 nations::adjust_relationship(state, source, target, state.defines.cancelwarsubsidy_relation_on_accept);
299 state.world.nation_get_diplomatic_points(source) -= state.defines.cancelwarsubsidy_diplomatic_cost;
300 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, source);
301 if(rel)
302 state.world.unilateral_relationship_set_war_subsidies(rel, false);
303
304 if(source != state.local_player_nation) {
306 [source, target](sys::state& state, text::layout_base& contents) {
307 text::add_line(state, contents, "msg_wsub_end_1", text::variable_type::x, source, text::variable_type::y, target);
308 },
309 "msg_wsub_end_title",
310 source, target, dcon::nation_id{},
312 });
313 }
314}
315
316
317void increase_relations(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
318 payload p;
319 memset(&p, 0, sizeof(payload));
321 p.source = source;
322 p.data.diplo_action.target = target;
323 add_to_command_queue(state, p);
324}
325bool can_increase_relations(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
326 /* Can only perform if, the nations are not at war, the relation value isn't maxed out at 200, and has
327 * defines:INCREASERELATION_DIPLOMATIC_COST diplomatic points. And the target can't be the same as the sender. */
328
329 if(source == target)
330 return false; // Can't negotiate with self
331
332 if(military::are_at_war(state, source, target))
333 return false; // Can't be at war
334
335 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(source, target);
336 if(state.world.diplomatic_relation_get_value(rel) >= 200.f)
337 return false; // Maxed out
338
339 if(state.world.nation_get_is_player_controlled(source))
340 return state.world.nation_get_diplomatic_points(source) >= state.defines.increaserelation_diplomatic_cost; // Enough diplomatic points
341 return true;
342}
343void execute_increase_relations(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
344 nations::adjust_relationship(state, source, target, state.defines.increaserelation_relation_on_accept);
345 state.world.nation_get_diplomatic_points(source) -= state.defines.increaserelation_diplomatic_cost;
346
348 [source, target](sys::state& state, text::layout_base& contents) {
349 text::add_line(state, contents, "msg_inc_rel_1", text::variable_type::x, source, text::variable_type::y, target);
350 },
351 "msg_inc_rel_title",
352 source, target, dcon::nation_id{},
354 });
355}
356
357void decrease_relations(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
358 payload p;
359 memset(&p, 0, sizeof(payload));
361 p.source = source;
362 p.data.diplo_action.target = target;
363 add_to_command_queue(state, p);
364}
365bool can_decrease_relations(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
366 /* Can only perform if, the nations are not at war, the relation value isn't maxxed out at -200, and has
367 * defines:DECREASERELATION_DIPLOMATIC_COST diplomatic points. And not done to self. */
368 if(source == target)
369 return false; // Can't negotiate with self
370 if(military::are_at_war(state, source, target))
371 return false; // Can't be at war
372 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(source, target);
373 if(rel && state.world.diplomatic_relation_get_value(rel) <= -200.f)
374 return false; // Maxxed out
375 if(state.world.nation_get_is_player_controlled(source))
376 return state.world.nation_get_diplomatic_points(source) >= state.defines.decreaserelation_diplomatic_cost; // Enough diplomatic points
377 return true;
378}
379void execute_decrease_relations(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
380 nations::adjust_relationship(state, source, target, state.defines.decreaserelation_relation_on_accept);
381 state.world.nation_get_diplomatic_points(source) -= state.defines.decreaserelation_diplomatic_cost;
382
384 [source, target](sys::state& state, text::layout_base& contents) {
385 text::add_line(state, contents, "msg_dec_rel_1", text::variable_type::x, source, text::variable_type::y, target);
386 },
387 "msg_dec_rel_title",
388 source, target, dcon::nation_id{},
390 });
391}
392
393void begin_province_building_construction(sys::state& state, dcon::nation_id source, dcon::province_id prov, economy::province_building_type type) {
394 payload p;
395 memset(&p, 0, sizeof(payload));
397 p.source = source;
400 add_to_command_queue(state, p);
401}
402bool can_begin_province_building_construction(sys::state& state, dcon::nation_id source, dcon::province_id p, economy::province_building_type type) {
403
404 switch(type) {
406 return province::can_build_railroads(state, p, source);
408 return province::can_build_fort(state, p, source);
410 return province::can_build_naval_base(state, p, source);
413 return province::can_build_province_building(state, p, source, type);
414 default:
415 return false;
416 }
417}
418void execute_begin_province_building_construction(sys::state& state, dcon::nation_id source, dcon::province_id p, economy::province_building_type type) {
420 auto si = state.world.province_get_state_membership(p);
421 if(si)
422 si.set_naval_base_is_taken(true);
423 }
424
425 if(type != economy::province_building_type::fort && type != economy::province_building_type::naval_base && source != state.world.province_get_nation_from_province_ownership(p)) {
426 float amount = 0.0f;
427 auto& base_cost = state.economy_definitions.building_definitions[int32_t(type)].cost;
428 for(uint32_t j = 0; j < economy::commodity_set::set_size; ++j) {
429 if(base_cost.commodity_type[j]) {
430 amount += base_cost.commodity_amounts[j] * state.world.commodity_get_cost(base_cost.commodity_type[j]); //base cost
431 } else {
432 break;
433 }
434 }
435 nations::adjust_foreign_investment(state, source, state.world.province_get_nation_from_province_ownership(p), amount);
436 }
437
438 auto new_rr = fatten(state.world, state.world.force_create_province_building_construction(p, source));
439 new_rr.set_is_pop_project(false);
440 new_rr.set_type(uint8_t(type));
441}
442
443
444void cancel_factory_building_construction(sys::state& state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type) {
445 payload p;
446 memset(&p, 0, sizeof(payload));
448 p.source = source;
451 add_to_command_queue(state, p);
452}
453bool can_cancel_factory_building_construction(sys::state& state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type) {
454 auto owner = state.world.state_instance_get_nation_from_state_ownership(location);
455 for(auto c : state.world.state_instance_get_state_building_construction(location)) {
456 if(c.get_type() == type) {
457 if(c.get_is_pop_project())
458 return false;
459 if(c.get_nation() != source)
460 return false;
461 return true;
462 }
463 }
464 return false;
465}
466void execute_cancel_factory_building_construction(sys::state& state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type) {
467 auto owner = state.world.state_instance_get_nation_from_state_ownership(location);
468 for(auto c : state.world.state_instance_get_state_building_construction(location)) {
469 if(c.get_type() == type) {
470 if(c.get_is_pop_project())
471 return;
472 if(c.get_nation() != source)
473 return;
474
475 state.world.delete_state_building_construction(c);
476 return;
477 }
478 }
479}
480void begin_factory_building_construction(sys::state& state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type, bool is_upgrade) {
481 payload p;
482 memset(&p, 0, sizeof(payload));
484 p.source = source;
488 add_to_command_queue(state, p);
489}
490
491bool can_begin_factory_building_construction(sys::state& state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type, bool is_upgrade) {
492
493 auto owner = state.world.state_instance_get_nation_from_state_ownership(location);
494
495 /*
496 The factory building must be unlocked by the nation.
497 Factories cannot be built in a colonial state.
498 */
499
500 if(state.world.nation_get_active_building(source, type) == false && !state.world.factory_type_get_is_available_from_start(type))
501 return false;
502 if(state.world.province_get_is_colonial(state.world.state_instance_get_capital(location)))
503 return false;
504
505 /* There can't be duplicate factories... */
506 if(!is_upgrade) {
507 // Check factories being built
508 bool has_dup = false;
509 economy::for_each_new_factory(state, location, [&](economy::new_factory const& nf) { has_dup = has_dup || nf.type == type; });
510 if(has_dup)
511 return false;
512
513 // Check actual factories
514 auto d = state.world.state_instance_get_definition(location);
515 for(auto p : state.world.state_definition_get_abstract_state_membership(d))
516 if(p.get_province().get_nation_from_province_ownership() == owner)
517 for(auto f : p.get_province().get_factory_location())
518 if(f.get_factory().get_building_type() == type)
519 return false;
520 }
521
522 if(state.world.nation_get_is_civilized(source) == false)
523 return false;
524
525 if(owner != source) {
526 /*
527 For foreign investment: the target nation must allow foreign investment, the nation doing the investing must be a great
528 power while the target is not a great power, and the nation doing the investing must not be at war with the target nation.
529 The nation being invested in must be civilized.
530 */
531 if(state.world.nation_get_is_great_power(source) == false || state.world.nation_get_is_great_power(owner) == true)
532 return false;
533 if(state.world.nation_get_is_civilized(owner) == false)
534 return false;
535
536 auto rules = state.world.nation_get_combined_issue_rules(owner);
537 if((rules & issue_rule::allow_foreign_investment) == 0)
538 return false;
539
540 if(military::are_at_war(state, source, owner))
541 return false;
542 } else {
543 /*
544 The nation must have the rule set to allow building / upgrading if this is a domestic target.
545 */
546
547 auto rules = state.world.nation_get_combined_issue_rules(owner);
548 if(is_upgrade) {
549 if((rules & issue_rule::expand_factory) == 0)
550 return false;
551 } else {
552 if((rules & issue_rule::build_factory) == 0)
553 return false;
554 }
555 }
556
557 if(is_upgrade) {
558 // no double upgrade
559 for(auto p : state.world.state_instance_get_state_building_construction(location)) {
560 if(p.get_type() == type)
561 return false;
562 }
563
564 // must already exist as a factory
565 // For upgrades: no upgrading past max level.
566 auto d = state.world.state_instance_get_definition(location);
567 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
568 if(p.get_province().get_nation_from_province_ownership() == owner) {
569 for(auto f : p.get_province().get_factory_location()) {
570 if(f.get_factory().get_building_type() == type && f.get_factory().get_level() < uint8_t(255)) {
571 return true;
572 }
573 }
574 }
575 }
576 return false;
577 } else {
578 // coastal factories must be built on coast
579 if(state.world.factory_type_get_is_coastal(type)) {
580 if(!province::state_is_coastal(state, location))
581 return false;
582 }
583
584 int32_t num_factories = economy::state_factory_count(state, location, owner);
585 return num_factories < int32_t(state.defines.factories_per_state);
586 }
587}
588
589void execute_begin_factory_building_construction(sys::state& state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type, bool is_upgrade) {
590 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(location, source));
591 new_up.set_is_pop_project(false);
592 new_up.set_is_upgrade(is_upgrade);
593 new_up.set_type(type);
594
595 if(source != state.world.state_instance_get_nation_from_state_ownership(location)) {
596 float amount = 0.0f;
597 auto& base_cost = state.world.factory_type_get_construction_costs(type);
598 for(uint32_t j = 0; j < economy::commodity_set::set_size; ++j) {
599 if(base_cost.commodity_type[j]) {
600 amount += base_cost.commodity_amounts[j] * state.world.commodity_get_cost(base_cost.commodity_type[j]); //base cost
601 } else {
602 break;
603 }
604 }
605 nations::adjust_foreign_investment(state, source, state.world.state_instance_get_nation_from_state_ownership(location), amount);
606 }
607}
608
609void start_naval_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type, dcon::province_id template_province) {
610 payload p;
611 memset(&p, 0, sizeof(payload));
613 p.source = source;
616 p.data.naval_unit_construction.template_province = template_province;
617 add_to_command_queue(state, p);
618}
619
620bool can_start_naval_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type, dcon::province_id template_province) {
621 /*
622 The province must be owned and controlled by the building nation, without an ongoing siege.
623 The unit type must be available from start / unlocked by the nation
624 */
625
626 if(state.world.province_get_nation_from_province_ownership(location) != source)
627 return false;
628 if(state.world.province_get_nation_from_province_control(location) != source)
629 return false;
630 if(state.world.nation_get_active_unit(source, type) == false &&
631 state.military_definitions.unit_base_definitions[type].active == false)
632 return false;
633 auto disarm = state.world.nation_get_disarmed_until(source);
634 if(disarm && state.current_date < disarm)
635 return false;
636
637 if(state.military_definitions.unit_base_definitions[type].is_land) {
638 return false;
639 } else {
640 /*
641 The province must be coastal
642 The province must have a naval base of sufficient level, depending on the unit type
643 The province may not be overseas for some unit types
644 Some units have a maximum number per port where they can built that must be respected
645 */
646 if(!state.world.province_get_is_coast(location))
647 return false;
648
649 auto overseas_allowed = state.military_definitions.unit_base_definitions[type].can_build_overseas;
650 auto level_req = state.military_definitions.unit_base_definitions[type].min_port_level;
651
652 if(state.world.province_get_building_level(location, uint8_t(economy::province_building_type::naval_base)) < level_req)
653 return false;
654
655 if(!overseas_allowed && province::is_overseas(state, location))
656 return false;
657
658 return true;
659 }
660}
661
662void execute_start_naval_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type, dcon::province_id template_province) {
663 auto c = fatten(state.world, state.world.try_create_province_naval_construction(location, source));
664 c.set_type(type);
665 c.set_template_province(template_province);
666}
667
668void start_land_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type, dcon::province_id template_province) {
669 payload p;
670 memset(&p, 0, sizeof(payload));
672 p.source = source;
675 p.data.land_unit_construction.pop_culture = soldier_culture;
676 p.data.land_unit_construction.template_province = template_province;
677 add_to_command_queue(state, p);
678}
679bool can_start_land_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type, dcon::province_id template_province) {
680 /*
681 The province must be owned and controlled by the building nation, without an ongoing siege.
682 The unit type must be available from start / unlocked by the nation
683 */
684
685 if(state.world.province_get_nation_from_province_ownership(location) != source)
686 return false;
687 if(state.world.province_get_nation_from_province_control(location) != source)
688 return false;
689 if(state.world.nation_get_active_unit(source, type) == false &&
690 state.military_definitions.unit_base_definitions[type].active == false)
691 return false;
692 if(state.military_definitions.unit_base_definitions[type].primary_culture && soldier_culture != state.world.nation_get_primary_culture(source) && state.world.nation_get_accepted_cultures(source, soldier_culture) == false) {
693 return false;
694 }
695 auto disarm = state.world.nation_get_disarmed_until(source);
696 if(disarm && state.current_date < disarm)
697 return false;
698
699 if(state.military_definitions.unit_base_definitions[type].is_land) {
700 /*
701 Each soldier pop can only support so many regiments (including under construction and rebel regiments)
702 If the unit is culturally restricted, there must be an available primary culture/accepted culture soldier pop with space
703 */
704 auto soldier = military::find_available_soldier(state, location, soldier_culture);
705 return bool(soldier);
706 } else {
707 return false;
708 }
709}
710void execute_start_land_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type, dcon::province_id template_province) {
711 auto soldier = military::find_available_soldier(state, location, soldier_culture);
712
713 auto c = fatten(state.world, state.world.try_create_province_land_construction(soldier, source));
714 c.set_type(type);
715 c.set_template_province(template_province);
716}
717
718void cancel_naval_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type) {
719 payload p;
720 memset(&p, 0, sizeof(payload));
722 p.source = source;
725 add_to_command_queue(state, p);
726}
727
728bool can_cancel_naval_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type) {
729 return state.world.province_get_nation_from_province_ownership(location) == source;
730}
731
732void execute_cancel_naval_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type) {
733 dcon::province_naval_construction_id c;
734 for(auto lc : state.world.province_get_province_naval_construction(location)) {
735 if(lc.get_type() == type) {
736 c = lc.id;
737 }
738 }
739 state.world.delete_province_naval_construction(c);
740}
741
742void cancel_land_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type) {
743 payload p;
744 memset(&p, 0, sizeof(payload));
746 p.source = source;
749 p.data.land_unit_construction.pop_culture = soldier_culture;
750 add_to_command_queue(state, p);
751}
752bool can_cancel_land_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type) {
753 return state.world.province_get_nation_from_province_ownership(location) == source;
754}
755void execute_cancel_land_unit_construction(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type) {
756 dcon::province_land_construction_id c;
757 for(auto pop : state.world.province_get_pop_location(location)) {
758 for(auto lc : pop.get_pop().get_province_land_construction()) {
759 if(lc.get_type() == type) {
760 c = lc.id;
761 }
762 }
763 }
764 state.world.delete_province_land_construction(c);
765}
766
767void delete_factory(sys::state& state, dcon::nation_id source, dcon::factory_id f) {
768 payload p;
769 memset(&p, 0, sizeof(payload));
771 p.source = source;
772 p.data.factory.location = state.world.factory_get_province_from_factory_location(f);
773 p.data.factory.type = state.world.factory_get_building_type(f);
774 add_to_command_queue(state, p);
775}
776bool can_delete_factory(sys::state& state, dcon::nation_id source, dcon::factory_id f) {
777 auto loc = state.world.factory_get_province_from_factory_location(f);
778 if(state.world.province_get_nation_from_province_ownership(loc) != source)
779 return false;
780 auto rules = state.world.nation_get_combined_issue_rules(source);
781 if((rules & issue_rule::destroy_factory) == 0)
782 return false;
783 return true;
784}
785void execute_delete_factory(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::factory_type_id type) {
786 if(state.world.province_get_nation_from_province_ownership(location) != source)
787 return;
788
789 auto rules = state.world.nation_get_combined_issue_rules(source);
790 if((rules & issue_rule::destroy_factory) == 0)
791 return;
792
793 for(auto sc : state.world.state_instance_get_state_building_construction(state.world.province_get_state_membership(location))) {
794 if(sc.get_type() == type) {
795 state.world.delete_state_building_construction(sc);
796 break;
797 }
798 }
799
800 for(auto f : state.world.province_get_factory_location(location)) {
801 if(f.get_factory().get_building_type() == type) {
802 state.world.delete_factory(f.get_factory());
803 return;
804 }
805 }
806}
807
808void change_factory_settings(sys::state& state, dcon::nation_id source, dcon::factory_id f, uint8_t priority, bool subsidized) {
809 payload p;
810 memset(&p, 0, sizeof(payload));
812 p.source = source;
813 p.data.factory.location = state.world.factory_get_province_from_factory_location(f);
814 p.data.factory.type = state.world.factory_get_building_type(f);
815 p.data.factory.priority = priority;
816 p.data.factory.subsidize = subsidized;
817 add_to_command_queue(state, p);
818}
819bool can_change_factory_settings(sys::state& state, dcon::nation_id source, dcon::factory_id f, uint8_t priority, bool subsidized) {
820 auto loc = state.world.factory_get_province_from_factory_location(f);
821 if(state.world.province_get_nation_from_province_ownership(loc) != source)
822 return false;
823
824 auto rules = state.world.nation_get_combined_issue_rules(source);
825
826 auto current_priority = economy::factory_priority(state, f);
827 if(priority >= 4)
828 return false;
829
830 if(current_priority != priority) {
831 if((rules & issue_rule::factory_priority) == 0)
832 return false;
833 }
834
835 if(subsidized && (rules & issue_rule::can_subsidise) == 0) {
836 return false;
837 }
838
839 return true;
840}
841void execute_change_factory_settings(sys::state& state, dcon::nation_id source, dcon::province_id location, dcon::factory_type_id type, uint8_t priority, bool subsidized) {
842
843 if(state.world.province_get_nation_from_province_ownership(location) != source)
844 return;
845
846 auto rules = state.world.nation_get_combined_issue_rules(source);
847
848 if(subsidized && (rules & issue_rule::can_subsidise) == 0) {
849 return;
850 }
851
852 for(auto f : state.world.province_get_factory_location(location)) {
853 if(f.get_factory().get_building_type() == type) {
854 auto current_priority = economy::factory_priority(state, f.get_factory());
855 if(current_priority != priority) {
856 if((rules & issue_rule::factory_priority) == 0)
857 return;
858 economy::set_factory_priority(state, f.get_factory(), priority);
859 }
860 if(subsidized && !f.get_factory().get_subsidized()) {
861 auto& scale = f.get_factory().get_production_scale();
862 scale = std::max(scale, 0.5f);
863 }
864 f.get_factory().set_subsidized(subsidized);
865 return;
866 }
867 }
868}
869
870void make_vassal(sys::state& state, dcon::nation_id source, dcon::national_identity_id t) {
871 payload p;
872 memset(&p, 0, sizeof(payload));
874 p.source = source;
875 p.data.tag_target.ident = t;
876 add_to_command_queue(state, p);
877}
878bool can_make_vassal(sys::state& state, dcon::nation_id source, dcon::national_identity_id t) {
879 return nations::can_release_as_vassal(state, source, t);
880}
881void execute_make_vassal(sys::state& state, dcon::nation_id source, dcon::national_identity_id t) {
882 nations::liberate_nation_from(state, t, source);
883 auto holder = state.world.national_identity_get_nation_from_identity_holder(t);
884 state.world.force_create_overlord(holder, source);
885 if(state.world.nation_get_is_great_power(source)) {
886 auto sr = state.world.force_create_gp_relationship(holder, source);
887 auto& flags = state.world.gp_relationship_get_status(sr);
889 state.world.nation_set_in_sphere_of(holder, source);
890 }
891 nations::remove_cores_from_owned(state, holder, state.world.nation_get_identity_from_identity_holder(source));
892 auto& inf = state.world.nation_get_infamy(source);
893 inf = std::max(0.0f, inf + state.defines.release_nation_infamy);
894 nations::adjust_prestige(state, source, state.defines.release_nation_prestige);
895}
896
897void release_and_play_as(sys::state& state, dcon::nation_id source, dcon::national_identity_id t) {
898 payload p;
899 memset(&p, 0, sizeof(payload));
901 p.source = source;
902 p.data.tag_target.ident = t;
903 add_to_command_queue(state, p);
904}
905bool can_release_and_play_as(sys::state& state, dcon::nation_id source, dcon::national_identity_id t) {
906 return nations::can_release_as_vassal(state, source, t);
907}
908void execute_release_and_play_as(sys::state& state, dcon::nation_id source, dcon::national_identity_id t) {
909 nations::liberate_nation_from(state, t, source);
910 auto holder = state.world.national_identity_get_nation_from_identity_holder(t);
911 nations::remove_cores_from_owned(state, holder, state.world.nation_get_identity_from_identity_holder(source));
912
913 if(state.world.nation_get_is_player_controlled(source)) {
914 network::switch_player(state, holder, source);
915 } else if(state.world.nation_get_is_player_controlled(holder)) {
916 network::switch_player(state, source, holder);
917 }
918
919 auto old_controller = state.world.nation_get_is_player_controlled(holder);
920 state.world.nation_set_is_player_controlled(holder, state.world.nation_get_is_player_controlled(source));
921 state.world.nation_set_is_player_controlled(source, old_controller);
922
923 if(state.world.nation_get_is_player_controlled(holder))
924 ai::remove_ai_data(state, holder);
925 if(state.world.nation_get_is_player_controlled(source))
926 ai::remove_ai_data(state, source);
927
928 if(state.local_player_nation == source) {
929 state.local_player_nation = holder;
930 } else if(state.local_player_nation == holder) {
931 state.local_player_nation = source;
932 }
933
934
935 for(auto p : state.world.nation_get_province_ownership(holder)) {
936 auto pid = p.get_province();
937 state.world.province_set_is_colonial(pid, false);
938 }
939}
940
941inline bool can_change_budget_settings(sys::state& state, dcon::nation_id source, budget_settings_data const& values) {
942 return true;
943}
944
945void change_budget_settings(sys::state& state, dcon::nation_id source, budget_settings_data const& values) {
946 payload p;
947 memset(&p, 0, sizeof(payload));
949 p.source = source;
950 p.data.budget_data = values;
951 add_to_command_queue(state, p);
952}
953void execute_change_budget_settings(sys::state& state, dcon::nation_id source, budget_settings_data const& values) {
954 if(values.administrative_spending != int8_t(-127)) {
955 state.world.nation_set_administrative_spending(source, std::clamp(values.administrative_spending, int8_t(0), int8_t(100)));
956 }
957 if(values.construction_spending != int8_t(-127)) {
958 state.world.nation_set_construction_spending(source, std::clamp(values.construction_spending, int8_t(0), int8_t(100)));
959 }
960 if(values.education_spending != int8_t(-127)) {
961 state.world.nation_set_education_spending(source, std::clamp(values.education_spending, int8_t(0), int8_t(100)));
962 }
963 if(values.land_spending != int8_t(-127)) {
964 state.world.nation_set_land_spending(source, std::clamp(values.land_spending, int8_t(0), int8_t(100)));
965 }
966 if(values.middle_tax != int8_t(-127)) {
967 state.world.nation_set_middle_tax(source, std::clamp(values.middle_tax, int8_t(0), int8_t(100)));
968 }
969 if(values.poor_tax != int8_t(-127)) {
970 state.world.nation_set_poor_tax(source, std::clamp(values.poor_tax, int8_t(0), int8_t(100)));
971 }
972 if(values.rich_tax != int8_t(-127)) {
973 state.world.nation_set_rich_tax(source, std::clamp(values.rich_tax, int8_t(0), int8_t(100)));
974 }
975 if(values.military_spending != int8_t(-127)) {
976 state.world.nation_set_military_spending(source, std::clamp(values.military_spending, int8_t(0), int8_t(100)));
977 }
978 if(values.naval_spending != int8_t(-127)) {
979 state.world.nation_set_naval_spending(source, std::clamp(values.naval_spending, int8_t(0), int8_t(100)));
980 }
981 if(values.social_spending != int8_t(-127)) {
982 state.world.nation_set_social_spending(source, std::clamp(values.social_spending, int8_t(0), int8_t(100)));
983 }
984 if(values.tariffs != int8_t(-127)) {
985 state.world.nation_set_tariffs(source, std::clamp(values.tariffs, int8_t(-100), int8_t(100)));
986 }
987 if(values.domestic_investment != int8_t(-127)) {
988 state.world.nation_set_domestic_investment_spending(source, std::clamp(values.domestic_investment, int8_t(0), int8_t(100)));
989 }
990 if(values.overseas != int8_t(-127)) {
991 state.world.nation_set_overseas_spending(source, std::clamp(values.overseas, int8_t(0), int8_t(100)));
992 }
993 economy::bound_budget_settings(state, source);
994}
995
996void start_election(sys::state& state, dcon::nation_id source) {
997 payload p;
998 memset(&p, 0, sizeof(payload));
1000 p.source = source;
1001 add_to_command_queue(state, p);
1002}
1003bool can_start_election(sys::state& state, dcon::nation_id source) {
1004 auto type = state.world.nation_get_government_type(source);
1005 return state.world.government_type_get_has_elections(type) && !politics::is_election_ongoing(state, source);
1006}
1007void execute_start_election(sys::state& state, dcon::nation_id source) {
1008 politics::start_election(state, source);
1009}
1010
1011void change_influence_priority(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, uint8_t priority) {
1012 payload p;
1013 memset(&p, 0, sizeof(payload));
1015 p.source = source;
1016 p.data.influence_priority.influence_target = influence_target;
1017 p.data.influence_priority.priority = priority;
1018 add_to_command_queue(state, p);
1019}
1020bool can_change_influence_priority(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, uint8_t priority) {
1021 // The source must be a great power, while the target must not be a great power.
1022 return state.world.nation_get_is_great_power(source) && !state.world.nation_get_is_great_power(influence_target);
1023}
1024void execute_change_influence_priority(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, uint8_t priority) {
1025 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1026 if(!rel) {
1027 rel = state.world.force_create_gp_relationship(influence_target, source);
1028 }
1029 auto& flags = state.world.gp_relationship_get_status(rel);
1030 switch(priority) {
1031 case 0:
1032 flags = (flags & ~nations::influence::priority_mask) | nations::influence::priority_zero;
1033 break;
1034 case 1:
1035 flags = (flags & ~nations::influence::priority_mask) | nations::influence::priority_one;
1036 break;
1037 case 2:
1038 flags = (flags & ~nations::influence::priority_mask) | nations::influence::priority_two;
1039 break;
1040 case 3:
1041 flags = (flags & ~nations::influence::priority_mask) | nations::influence::priority_three;
1042 break;
1043 default:
1044 break;
1045 }
1046}
1047
1048void discredit_advisors(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1049 payload p;
1050 memset(&p, 0, sizeof(payload));
1052 p.source = source;
1053 p.data.influence_action.influence_target = influence_target;
1054 p.data.influence_action.gp_target = affected_gp;
1055 add_to_command_queue(state, p);
1056}
1057bool can_discredit_advisors(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1058 /*
1059 The source must be a great power. The source must have define:DISCREDIT_INFLUENCE_COST influence points. The source may not be
1060 currently banned with the direct target or currently on the opposite side of a war involving them. Only a great power can be a
1061 secondary target for this action. To discredit a nation, you must have an opinion of at least "opposed" with the influenced
1062 nation and you must have a an equal or better opinion level with the influenced nation than the nation you are discrediting
1063 does.
1064 */
1065 if(!state.world.nation_get_is_great_power(source) || !state.world.nation_get_is_great_power(affected_gp) ||
1066 state.world.nation_get_is_great_power(influence_target))
1067 return false;
1068
1069 if(source == affected_gp)
1070 return false;
1071
1072 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1073 if(!rel)
1074 return false;
1075
1076 if(state.world.gp_relationship_get_influence(rel) < state.defines.discredit_influence_cost)
1077 return false;
1078
1079 if((state.world.gp_relationship_get_status(rel) & nations::influence::is_banned) != 0)
1080 return false;
1081
1082 if(military::are_at_war(state, source, influence_target))
1083 return false;
1084
1085 auto clevel = (nations::influence::level_mask & state.world.gp_relationship_get_status(rel));
1087 return false;
1088
1089 auto orel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, affected_gp);
1090 if((state.world.gp_relationship_get_status(orel) & nations::influence::is_banned) != 0)
1091 return false;
1092
1094 nations::influence::get_level(state, affected_gp, influence_target));
1095}
1096void execute_discredit_advisors(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1097 /*
1098 A nation is discredited for define:DISCREDIT_DAYS. Being discredited twice does not add these durations together; it just
1099 resets the timer from the current day. Discrediting a nation "increases" your relationship with them by
1100 define:DISCREDIT_RELATION_ON_ACCEPT. Discrediting costs define:DISCREDIT_INFLUENCE_COST influence points.
1101 */
1102 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1103 auto orel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, affected_gp);
1104 if(!orel)
1105 orel = state.world.force_create_gp_relationship(influence_target, affected_gp);
1106
1107 state.world.gp_relationship_get_influence(rel) -= state.defines.discredit_influence_cost;
1108 nations::adjust_relationship(state, source, affected_gp, state.defines.discredit_relation_on_accept);
1109 state.world.gp_relationship_get_status(orel) |= nations::influence::is_discredited;
1110 state.world.gp_relationship_set_penalty_expires_date(orel, state.current_date + int32_t(state.defines.discredit_days));
1111
1113 [source, influence_target, affected_gp, enddate = state.current_date + int32_t(state.defines.discredit_days)](sys::state& state, text::layout_base& contents) {
1114 text::add_line(state, contents, "msg_discredit_1", text::variable_type::x, source, text::variable_type::y, influence_target, text::variable_type::val, affected_gp);
1115 text::add_line(state, contents, "msg_discredit_2", text::variable_type::x, enddate);
1116 },
1117 "msg_discredit_title",
1118 source, affected_gp, influence_target,
1120 });
1121}
1122
1123void expel_advisors(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1124 payload p;
1125 memset(&p, 0, sizeof(payload));
1127 p.source = source;
1128 p.data.influence_action.influence_target = influence_target;
1129 p.data.influence_action.gp_target = affected_gp;
1130 add_to_command_queue(state, p);
1131}
1132bool can_expel_advisors(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1133 /*
1134 The source must be a great power. The source must have define:EXPELADVISORS_INFLUENCE_COST influence points. The source may
1135 not be currently banned with the direct target or currently on the opposite side of a war involving them. Only a great power
1136 can be a secondary target for this action. To expel advisors you must have at least neutral opinion with the influenced nation
1137 and an equal or better opinion level than that of the nation you are expelling.
1138 */
1139 if(!state.world.nation_get_is_great_power(source) || !state.world.nation_get_is_great_power(affected_gp) ||
1140 state.world.nation_get_is_great_power(influence_target))
1141 return false;
1142
1143 if(source == affected_gp)
1144 return false;
1145
1146 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1147 if(!rel)
1148 return false;
1149
1150 if(state.world.gp_relationship_get_influence(rel) < state.defines.expeladvisors_influence_cost)
1151 return false;
1152
1153 if((state.world.gp_relationship_get_status(rel) & nations::influence::is_banned) != 0)
1154 return false;
1155
1156 if(military::are_at_war(state, source, influence_target))
1157 return false;
1158
1159 auto clevel = (nations::influence::level_mask & state.world.gp_relationship_get_status(rel));
1161 return false;
1162
1164 nations::influence::get_level(state, affected_gp, influence_target));
1165}
1166void execute_expel_advisors(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1167 /*
1168 Expelling a nation's advisors "increases" your relationship with them by define:EXPELADVISORS_RELATION_ON_ACCEPT. This action
1169 costs define:EXPELADVISORS_INFLUENCE_COST influence points. Being expelled cancels any ongoing discredit effect. Being
1170 expelled reduces your influence to zero.
1171 */
1172 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1173 auto orel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, affected_gp);
1174
1175 state.world.gp_relationship_get_influence(rel) -= state.defines.expeladvisors_influence_cost;
1176 nations::adjust_relationship(state, source, affected_gp, state.defines.expeladvisors_relation_on_accept);
1177
1178 if(orel) {
1179 state.world.gp_relationship_set_influence(orel, 0.0f);
1180 state.world.gp_relationship_get_status(orel) &= ~nations::influence::is_discredited;
1181 }
1182
1184 [source, influence_target, affected_gp](sys::state& state, text::layout_base& contents) {
1185 text::add_line(state, contents, "msg_expel_1", text::variable_type::x, source, text::variable_type::y, influence_target, text::variable_type::val, affected_gp);
1186 },
1187 "msg_expel_title",
1188 source, affected_gp, influence_target,
1190 });
1191}
1192
1193void ban_embassy(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1194 payload p;
1195 memset(&p, 0, sizeof(payload));
1197 p.source = source;
1198 p.data.influence_action.influence_target = influence_target;
1199 p.data.influence_action.gp_target = affected_gp;
1200 add_to_command_queue(state, p);
1201}
1202bool can_ban_embassy(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1203 /*
1204 The source must be a great power. The source must have define:BANEMBASSY_INFLUENCE_COST influence points. The source may not
1205 be currently banned with the direct target or currently on the opposite side of a war involving them. Only a great power can
1206 be a secondary target for this action. To ban a nation you must be at least friendly with the influenced nation and have an
1207 equal or better opinion level than that of the nation you are expelling.
1208 */
1209
1210 if(!state.world.nation_get_is_great_power(source) || !state.world.nation_get_is_great_power(affected_gp) ||
1211 state.world.nation_get_is_great_power(influence_target))
1212 return false;
1213
1214 if(source == affected_gp)
1215 return false;
1216
1217 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1218 if(!rel)
1219 return false;
1220
1221 if(state.world.gp_relationship_get_influence(rel) < state.defines.banembassy_influence_cost)
1222 return false;
1223
1224 if((state.world.gp_relationship_get_status(rel) & nations::influence::is_banned) != 0)
1225 return false;
1226
1227 if(military::are_at_war(state, source, influence_target))
1228 return false;
1229
1230 auto clevel = (nations::influence::level_mask & state.world.gp_relationship_get_status(rel));
1232 return false;
1233
1235 nations::influence::get_level(state, affected_gp, influence_target));
1236}
1237void execute_ban_embassy(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1238 /*
1239 Banning a nation's embassy "increases" your relationship with them by define:BANEMBASSY_RELATION_ON_ACCEPT. This action costs
1240 define:BANEMBASSY_INFLUENCE_COST influence points. The ban embassy effect lasts for define:BANEMBASSY_DAYS. If you are already
1241 banned, being banned again simply restarts the timer. Being banned cancels out any ongoing discredit effect.
1242 */
1243 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1244 auto orel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, affected_gp);
1245 if(!orel)
1246 orel = state.world.force_create_gp_relationship(influence_target, affected_gp);
1247
1248 state.world.gp_relationship_get_influence(rel) -= state.defines.banembassy_influence_cost;
1249 nations::adjust_relationship(state, source, affected_gp, state.defines.banembassy_relation_on_accept);
1250 state.world.gp_relationship_get_status(orel) |= nations::influence::is_banned;
1251 state.world.gp_relationship_set_influence(orel, 0.0f);
1252 state.world.gp_relationship_set_penalty_expires_date(orel, state.current_date + int32_t(state.defines.banembassy_days));
1253
1255 [source, influence_target, affected_gp, enddate = state.current_date + int32_t(state.defines.banembassy_days)](sys::state& state, text::layout_base& contents) {
1256 text::add_line(state, contents, "msg_ban_1", text::variable_type::x, source, text::variable_type::y, influence_target, text::variable_type::val, affected_gp);
1257 text::add_line(state, contents, "msg_ban_2", text::variable_type::x, enddate);
1258 },
1259 "msg_ban_title",
1260 source, affected_gp, influence_target,
1262 });
1263}
1264
1265void increase_opinion(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target) {
1266 payload p;
1267 memset(&p, 0, sizeof(payload));
1269 p.source = source;
1270 p.data.influence_action.influence_target = influence_target;
1271 add_to_command_queue(state, p);
1272}
1273bool can_increase_opinion(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target) {
1274 /*
1275 The source must be a great power. The source must have define:INCREASEOPINION_INFLUENCE_COST influence points. The source may
1276 not be currently banned with the direct target or currently on the opposite side of a war involving them. Only a great power
1277 can be a secondary target for this action. Your current opinion must be less than friendly
1278 */
1279 if(!state.world.nation_get_is_great_power(source) || state.world.nation_get_is_great_power(influence_target))
1280 return false;
1281
1282 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1283 if(!rel)
1284 return false;
1285
1286 if(state.world.gp_relationship_get_influence(rel) < state.defines.increaseopinion_influence_cost)
1287 return false;
1288
1289 if((state.world.gp_relationship_get_status(rel) & nations::influence::is_banned) != 0)
1290 return false;
1291
1292 if(military::are_at_war(state, source, influence_target))
1293 return false;
1294
1295 auto clevel = (nations::influence::level_mask & state.world.gp_relationship_get_status(rel));
1297 return false;
1298
1299 return true;
1300}
1301void execute_increase_opinion(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target) {
1302 /*
1303 Increasing the opinion of a nation costs define:INCREASEOPINION_INFLUENCE_COST influence points. Opinion can be increased to a
1304 maximum of friendly.
1305 */
1306 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1307
1308 state.world.gp_relationship_get_influence(rel) -= state.defines.increaseopinion_influence_cost;
1309 auto& l = state.world.gp_relationship_get_status(rel);
1311
1313 [source, influence_target](sys::state& state, text::layout_base& contents) {
1314 text::add_line(state, contents, "msg_op_inc_1", text::variable_type::x, source, text::variable_type::y, influence_target);
1315 },
1316 "msg_op_inc_title",
1317 source, influence_target, dcon::nation_id{},
1319 });
1320}
1321
1322void decrease_opinion(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1323 payload p;
1324 memset(&p, 0, sizeof(payload));
1326 p.source = source;
1327 p.data.influence_action.influence_target = influence_target;
1328 p.data.influence_action.gp_target = affected_gp;
1329 add_to_command_queue(state, p);
1330}
1331bool can_decrease_opinion(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1332 /*
1333 The source must be a great power. The source must have define:DECREASEOPINION_INFLUENCE_COST influence points. The source may
1334 not be currently banned with the direct target or currently on the opposite side of a war involving them. Only a great power
1335 can be a secondary target for this action. Decreasing the opinion of another nation requires that you have an opinion of at
1336 least "opposed" with the influenced nation and you must have a an equal or better opinion level with the influenced nation
1337 than the nation you are lowering their opinion of does. The secondary target must neither have the influenced nation in sphere
1338 nor may it already be at hostile opinion with them.
1339 */
1340 if(!state.world.nation_get_is_great_power(source) || !state.world.nation_get_is_great_power(affected_gp) ||
1341 state.world.nation_get_is_great_power(influence_target))
1342 return false;
1343
1344 if(source == affected_gp)
1345 return false;
1346
1347 if(state.world.nation_get_in_sphere_of(influence_target) == affected_gp)
1348 return false;
1349
1350 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1351 if(!rel)
1352 return false;
1353
1354 if(state.world.gp_relationship_get_influence(rel) < state.defines.decreaseopinion_influence_cost)
1355 return false;
1356
1357 if((state.world.gp_relationship_get_status(rel) & nations::influence::is_banned) != 0)
1358 return false;
1359
1360 if(military::are_at_war(state, source, influence_target))
1361 return false;
1362
1363 auto clevel = (nations::influence::level_mask & state.world.gp_relationship_get_status(rel));
1365 return false;
1366
1368 state.world.gp_relationship_get_status(state.world.get_gp_relationship_by_gp_influence_pair(influence_target,
1369 affected_gp))) == nations::influence::level_hostile)
1370 return false;
1371
1373 nations::influence::get_level(state, affected_gp, influence_target));
1374}
1375void execute_decrease_opinion(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1376 /*
1377 Decreasing the opinion of a nation "increases" your relationship with them by define:DECREASEOPINION_RELATION_ON_ACCEPT. This
1378 actions costs define:DECREASEOPINION_INFLUENCE_COST influence points. Opinion of the influenced nation of the secondary target
1379 decreases by one step.
1380 */
1381 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1382 auto orel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, affected_gp);
1383 if(!orel)
1384 orel = state.world.force_create_gp_relationship(influence_target, affected_gp);
1385
1386 state.world.gp_relationship_get_influence(rel) -= state.defines.decreaseopinion_influence_cost;
1387 nations::adjust_relationship(state, source, affected_gp, state.defines.decreaseopinion_relation_on_accept);
1388
1389 auto& l = state.world.gp_relationship_get_status(orel);
1391
1393 [source, influence_target, affected_gp](sys::state& state, text::layout_base& contents) {
1394 text::add_line(state, contents, "msg_op_dec_1", text::variable_type::x, source, text::variable_type::y, influence_target, text::variable_type::val, affected_gp);
1395 },
1396 "msg_op_dec_title",
1397 source, affected_gp, influence_target,
1399 });
1400}
1401
1402void add_to_sphere(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target) {
1403 payload p;
1404 memset(&p, 0, sizeof(payload));
1406 p.source = source;
1407 p.data.influence_action.influence_target = influence_target;
1408 add_to_command_queue(state, p);
1409}
1410bool can_add_to_sphere(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target) {
1411 /*
1412 The source must be a great power. The source must have define:ADDTOSPHERE_INFLUENCE_COST influence points. The source may not
1413 be currently banned with the direct target or currently on the opposite side of a war involving them. Only a great power can
1414 be a secondary target for this action. The nation must have a friendly opinion of you and my not be in the sphere of another
1415 nation.
1416 */
1417 if(!state.world.nation_get_is_great_power(source) || state.world.nation_get_is_great_power(influence_target))
1418 return false;
1419
1420 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1421 if(!rel)
1422 return false;
1423
1424 if(state.world.gp_relationship_get_influence(rel) < state.defines.addtosphere_influence_cost)
1425 return false;
1426
1427 if((state.world.gp_relationship_get_status(rel) & nations::influence::is_banned) != 0)
1428 return false;
1429
1430 if(military::are_at_war(state, source, influence_target))
1431 return false;
1432
1433 auto clevel = (nations::influence::level_mask & state.world.gp_relationship_get_status(rel));
1435 return false;
1436
1437 if(state.world.nation_get_in_sphere_of(influence_target))
1438 return false;
1439
1440 return true;
1441}
1442void execute_add_to_sphere(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target) {
1443 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1444
1445 state.world.gp_relationship_get_influence(rel) -= state.defines.addtosphere_influence_cost;
1446 auto& l = state.world.gp_relationship_get_status(rel);
1448
1449 state.world.nation_set_in_sphere_of(influence_target, source);
1450
1452 [source, influence_target](sys::state& state, text::layout_base& contents) {
1453 text::add_line(state, contents, "msg_add_sphere_1", text::variable_type::x, source, text::variable_type::y, influence_target);
1454 },
1455 "msg_add_sphere_title",
1456 source, influence_target, dcon::nation_id{},
1458 });
1459}
1460
1461void remove_from_sphere(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1462 payload p;
1463 memset(&p, 0, sizeof(payload));
1465 p.source = source;
1466 p.data.influence_action.influence_target = influence_target;
1467 p.data.influence_action.gp_target = affected_gp;
1468 add_to_command_queue(state, p);
1469}
1470bool can_remove_from_sphere(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1471 /*
1472 The source must be a great power. The source must have define:REMOVEFROMSPHERE_INFLUENCE_COST influence points. The source may
1473 not be currently banned with the direct target or currently on the opposite side of a war involving them. Only a great power
1474 can be a secondary target for this action. To preform this action you must have an opinion level of friendly with the nation
1475 you are removing from a sphere.
1476 */
1477 if(!state.world.nation_get_is_great_power(source) || !state.world.nation_get_is_great_power(affected_gp) ||
1478 state.world.nation_get_is_great_power(influence_target))
1479 return false;
1480
1481 if(state.world.nation_get_in_sphere_of(influence_target) != affected_gp)
1482 return false;
1483
1484 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1485 if(!rel)
1486 return false;
1487
1488 if(source != affected_gp && state.world.gp_relationship_get_influence(rel) < state.defines.removefromsphere_influence_cost)
1489 return false;
1490
1491 if((state.world.gp_relationship_get_status(rel) & nations::influence::is_banned) != 0)
1492 return false;
1493
1494 if(military::are_at_war(state, source, influence_target))
1495 return false;
1496
1497 auto clevel = (nations::influence::level_mask & state.world.gp_relationship_get_status(rel));
1499 return false;
1500
1501 return true;
1502}
1503void execute_remove_from_sphere(sys::state& state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp) {
1504 /*
1505 Removing a nation from a sphere costs define:REMOVEFROMSPHERE_INFLUENCE_COST influence points. If you remove a nation from
1506 your own sphere you lose define:REMOVEFROMSPHERE_PRESTIGE_COST prestige and gain define:REMOVEFROMSPHERE_INFAMY_COST infamy.
1507 Removing a nation from the sphere of another nation "increases" your relationship with the former sphere leader by
1508 define:REMOVEFROMSPHERE_RELATION_ON_ACCEPT points. The removed nation then becomes friendly with its former sphere leader.
1509 */
1510 auto rel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, source);
1511
1512 state.world.nation_set_in_sphere_of(influence_target, dcon::nation_id{});
1513
1514 auto orel = state.world.get_gp_relationship_by_gp_influence_pair(influence_target, affected_gp);
1515 auto& l = state.world.gp_relationship_get_status(orel);
1517
1518 if(source != affected_gp) {
1519 state.world.gp_relationship_get_influence(rel) -= state.defines.removefromsphere_influence_cost;
1520 nations::adjust_relationship(state, source, affected_gp, state.defines.removefromsphere_relation_on_accept);
1521 } else {
1522 state.world.nation_get_infamy(source) += state.defines.removefromsphere_infamy_cost;
1523 nations::adjust_prestige(state, source, -state.defines.removefromsphere_prestige_cost);
1524 }
1525
1527 [source, influence_target, affected_gp](sys::state& state, text::layout_base& contents) {
1528 if(source == affected_gp)
1529 text::add_line(state, contents, "msg_rem_sphere_1", text::variable_type::x, source, text::variable_type::y, influence_target);
1530 else
1531 text::add_line(state, contents, "msg_rem_sphere_2", text::variable_type::x, source, text::variable_type::y, influence_target, text::variable_type::val, affected_gp);
1532 },
1533 "msg_rem_sphere_title",
1534 source, affected_gp, influence_target,
1536 });
1537}
1538
1539void upgrade_colony_to_state(sys::state& state, dcon::nation_id source, dcon::state_instance_id si) {
1540 payload p;
1541 memset(&p, 0, sizeof(payload));
1543 p.source = source;
1544 p.data.generic_location.prov = state.world.state_instance_get_capital(si);
1545 add_to_command_queue(state, p);
1546}
1547bool can_upgrade_colony_to_state(sys::state& state, dcon::nation_id source, dcon::state_instance_id si) {
1548 return state.world.state_instance_get_nation_from_state_ownership(si) == source && province::can_integrate_colony(state, si);
1549}
1550void execute_upgrade_colony_to_state(sys::state& state, dcon::nation_id source, dcon::state_instance_id si) {
1551 province::upgrade_colonial_state(state, source, si);
1552}
1553
1554void invest_in_colony(sys::state& state, dcon::nation_id source, dcon::province_id pr) {
1555 payload p;
1556 memset(&p, 0, sizeof(payload));
1558 p.source = source;
1559 p.data.generic_location.prov = pr;
1560 add_to_command_queue(state, p);
1561}
1562bool can_invest_in_colony(sys::state& state, dcon::nation_id source, dcon::province_id p) {
1563 auto state_def = state.world.province_get_state_from_abstract_state_membership(p);
1564 if(!province::is_colonizing(state, source, state_def))
1565 return province::can_start_colony(state, source, state_def);
1566 else
1567 return province::can_invest_in_colony(state, source, state_def);
1568}
1569void execute_invest_in_colony(sys::state& state, dcon::nation_id source, dcon::province_id pr) {
1570 auto state_def = state.world.province_get_state_from_abstract_state_membership(pr);
1571 if(province::is_colonizing(state, source, state_def)) {
1572 province::increase_colonial_investment(state, source, state_def);
1573 } else {
1574 bool adjacent = [&]() {
1575 for(auto p : state.world.state_definition_get_abstract_state_membership(state_def)) {
1576 if(!p.get_province().get_nation_from_province_ownership()) {
1577 for(auto adj : p.get_province().get_province_adjacency()) {
1578 auto indx = adj.get_connected_provinces(0) != p.get_province() ? 0 : 1;
1579 auto o = adj.get_connected_provinces(indx).get_nation_from_province_ownership();
1580 if(o == source)
1581 return true;
1582 if(o.get_overlord_as_subject().get_ruler() == source)
1583 return true;
1584 }
1585 }
1586 }
1587 return false;
1588 }();
1589
1590 auto new_rel = fatten(state.world, state.world.force_create_colonization(state_def, source));
1591 new_rel.set_level(uint8_t(1));
1592 new_rel.set_last_investment(state.current_date);
1593 new_rel.set_points_invested(uint16_t(state.defines.colonization_interest_cost_initial + (adjacent ? state.defines.colonization_interest_cost_neighbor_modifier : 0.0f)));
1594
1595 state.world.state_definition_set_colonization_stage(state_def, uint8_t(1));
1596 }
1597}
1598
1599void abandon_colony(sys::state& state, dcon::nation_id source, dcon::province_id pr) {
1600 payload p;
1601 memset(&p, 0, sizeof(payload));
1603 p.source = source;
1604 p.data.generic_location.prov = pr;
1605 add_to_command_queue(state, p);
1606}
1607
1608bool can_abandon_colony(sys::state& state, dcon::nation_id source, dcon::province_id pr) {
1609 auto state_def = state.world.province_get_state_from_abstract_state_membership(pr);
1610 return province::is_colonizing(state, source, state_def);
1611}
1612
1613void execute_abandon_colony(sys::state& state, dcon::nation_id source, dcon::province_id p) {
1614 auto state_def = state.world.province_get_state_from_abstract_state_membership(p);
1615
1616 for(auto rel : state.world.state_definition_get_colonization(state_def)) {
1617 if(rel.get_colonizer() == source) {
1618 state.world.delete_colonization(rel);
1619 }
1620 }
1621}
1622
1623void finish_colonization(sys::state& state, dcon::nation_id source, dcon::province_id pr) {
1624 payload p;
1625 memset(&p, 0, sizeof(payload));
1627 p.source = source;
1628 p.data.generic_location.prov = pr;
1629 add_to_command_queue(state, p);
1630}
1631bool can_finish_colonization(sys::state& state, dcon::nation_id source, dcon::province_id p) {
1632 auto state_def = state.world.province_get_state_from_abstract_state_membership(p);
1633 if(state.world.state_definition_get_colonization_stage(state_def) != 3)
1634 return false;
1635 auto rng = state.world.state_definition_get_colonization(state_def);
1636 if(rng.begin() == rng.end())
1637 return false;
1638 return (*rng.begin()).get_colonizer() == source;
1639}
1640void execute_finish_colonization(sys::state& state, dcon::nation_id source, dcon::province_id p) {
1641 auto state_def = state.world.province_get_state_from_abstract_state_membership(p);
1642
1643 for(auto pr : state.world.state_definition_get_abstract_state_membership(state_def)) {
1644 if(!pr.get_province().get_nation_from_province_ownership()) {
1645 province::change_province_owner(state, pr.get_province(), source);
1646 }
1647 }
1648
1649 state.world.state_definition_set_colonization_temperature(state_def, 0.0f);
1650 state.world.state_definition_set_colonization_stage(state_def, uint8_t(0));
1651
1652 auto rng = state.world.state_definition_get_colonization(state_def);
1653
1654 while(rng.begin() != rng.end()) {
1655 state.world.delete_colonization(*rng.begin());
1656 }
1657}
1658
1659void intervene_in_war(sys::state& state, dcon::nation_id source, dcon::war_id w, bool for_attacker) {
1660 payload p;
1661 memset(&p, 0, sizeof(payload));
1663 p.source = source;
1664 p.data.war_target.war = w;
1665 p.data.war_target.for_attacker = for_attacker;
1666 add_to_command_queue(state, p);
1667}
1668bool can_intervene_in_war(sys::state& state, dcon::nation_id source, dcon::war_id w, bool for_attacker) {
1669 /*
1670 Must be a great power. Must not be involved in or interested in a crisis. Must be at least define:MIN_MONTHS_TO_INTERVENE
1671 since the war started.
1672 */
1673 if(!nations::is_great_power(state, source))
1674 return false;
1675 if(nations::is_involved_in_crisis(state, source))
1676 return false;
1677 if(state.current_date < state.world.war_get_start_date(w) + int32_t(30.0f * state.defines.min_months_to_intervene))
1678 return false;
1679
1680 /*
1681 Standard war-joining conditions: can't join if you are already at war against any attacker or defender. Can't join a war
1682 against your sphere leader or overlord (doesn't apply here obviously). Can't join a crisis war prior to great wars being
1683 invented (i.e. you have to be in the crisis). Can't join as an attacker against someone you have a truce with.
1684 */
1685 if(!military::joining_war_does_not_violate_constraints(state, source, w, for_attacker))
1686 return false;
1687 if(state.world.war_get_is_crisis_war(w) && !state.world.war_get_is_great(w))
1688 return false;
1689 if(for_attacker && military::joining_as_attacker_would_break_truce(state, source, w))
1690 return false;
1691 if(!for_attacker && military::has_truce_with(state, source, state.world.war_get_primary_attacker(w)))
1692 return false;
1693
1694 if(!state.world.war_get_is_great(w)) {
1695 /*
1696 If it is not a great war:
1697 Must be at least friendly with the primary defender. May only join on the defender's side. Defenders must either have no
1698 wargoals or only status quo. Primary defender must be at defines:MIN_WARSCORE_TO_INTERVENE or less.
1699 */
1700
1701 if(for_attacker)
1702 return false;
1704 return false;
1705
1706 auto defender = state.world.war_get_primary_defender(w);
1707 auto rel_w_defender = state.world.get_gp_relationship_by_gp_influence_pair(defender, source);
1708 auto inf = state.world.gp_relationship_get_status(rel_w_defender) & nations::influence::level_mask;
1710 return false;
1711
1712 if(military::primary_warscore(state, w) < -state.defines.min_warscore_to_intervene)
1713 return false;
1714 } else {
1715 /*
1716 If the war is a great war:
1717 It is then possible to join the attacking side as well.
1718 Must have define:GW_INTERVENE_MIN_RELATIONS with the primary defender/attacker to intervene, must have at most
1719 define:GW_INTERVENE_MAX_EXHAUSTION war exhaustion. Can't join if any nation in your sphere is on the other side Can't join
1720 if you are allied to any allied to any nation on the other side Can't join if you have units within a nation on the other
1721 side
1722 */
1723 if(state.world.nation_get_war_exhaustion(source) >= state.defines.gw_intervene_max_exhaustion)
1724 return false;
1725
1726 auto primary_on_side = for_attacker ? state.world.war_get_primary_attacker(w) : state.world.war_get_primary_defender(w);
1727 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(primary_on_side, source);
1728 if(state.world.diplomatic_relation_get_value(rel) < state.defines.gw_intervene_min_relations)
1729 return false;
1730
1731 for(auto p : state.world.war_get_war_participant(w)) {
1732 if(p.get_is_attacker() != for_attacker) { // scan nations on other side
1733 if(p.get_nation().get_in_sphere_of() == source)
1734 return false;
1735
1736 auto irel = state.world.get_diplomatic_relation_by_diplomatic_pair(p.get_nation(), source);
1737 if(state.world.diplomatic_relation_get_are_allied(irel))
1738 return false;
1739
1740 for(auto prov : p.get_nation().get_province_ownership()) {
1741 for(auto arm : prov.get_province().get_army_location()) {
1742 if(arm.get_army().get_controller_from_army_control() == source)
1743 return false;
1744 }
1745 }
1746 }
1747 }
1748 }
1749 return true;
1750}
1751void execute_intervene_in_war(sys::state& state, dcon::nation_id source, dcon::war_id w, bool for_attacker) {
1752 if(!state.world.war_get_is_great(w)) {
1753 bool status_quo_added = false;
1754 for(auto wg : state.world.war_get_wargoals_attached(w)) {
1755 if(military::is_defender_wargoal(state, w, wg.get_wargoal()) &&
1756 (wg.get_wargoal().get_type().get_type_bits() & military::cb_flag::po_status_quo) != 0) {
1757 status_quo_added = true;
1758 break;
1759 }
1760 }
1761 if(!status_quo_added) {
1762 military::add_wargoal(state, w, source, state.world.war_get_primary_attacker(w), state.military_definitions.standard_status_quo, dcon::state_definition_id{},
1763 dcon::national_identity_id{}, dcon::nation_id{});
1764 }
1765 }
1766
1767 military::add_to_war(state, w, source, for_attacker);
1768}
1769
1770void suppress_movement(sys::state& state, dcon::nation_id source, dcon::movement_id m) {
1771 payload p;
1772 memset(&p, 0, sizeof(payload));
1774 p.source = source;
1775 p.data.movement.iopt = state.world.movement_get_associated_issue_option(m);
1776 p.data.movement.tag = state.world.movement_get_associated_independence(m);
1777 add_to_command_queue(state, p);
1778}
1779bool can_suppress_movement(sys::state& state, dcon::nation_id source, dcon::movement_id m) {
1780 if(state.world.movement_get_nation_from_movement_within(m) != source)
1781 return false;
1782 if(state.world.movement_get_pop_movement_membership(m).begin() == state.world.movement_get_pop_movement_membership(m).end())
1783 return false;
1784 return state.world.nation_get_suppression_points(source) >= rebel::get_suppression_point_cost(state, m);
1785}
1786void execute_suppress_movement(sys::state& state, dcon::nation_id source, dcon::issue_option_id iopt,
1787 dcon::national_identity_id tag) {
1788 dcon::movement_id m;
1789 if(iopt) {
1790 m = rebel::get_movement_by_position(state, source, iopt);
1791 } else if(tag) {
1792 m = rebel::get_movement_by_independence(state, source, tag);
1793 }
1794 if(!m)
1795 return;
1796 state.world.nation_get_suppression_points(source) -= rebel::get_suppression_point_cost(state, m);
1797 rebel::suppress_movement(state, source, m);
1798}
1799
1800void civilize_nation(sys::state& state, dcon::nation_id source) {
1801 payload p;
1802 memset(&p, 0, sizeof(payload));
1804 p.source = source;
1805 add_to_command_queue(state, p);
1806}
1807bool can_civilize_nation(sys::state& state, dcon::nation_id source) {
1808 return state.world.nation_get_modifier_values(source, sys::national_mod_offsets::civilization_progress_modifier) >= 1.0f && !state.world.nation_get_is_civilized(source);
1809}
1810void execute_civilize_nation(sys::state& state, dcon::nation_id source) {
1811 nations::make_civilized(state, source);
1812}
1813
1814void appoint_ruling_party(sys::state& state, dcon::nation_id source, dcon::political_party_id pa) {
1815 payload p;
1816 memset(&p, 0, sizeof(payload));
1818 p.source = source;
1819 p.data.political_party.p = pa;
1820 add_to_command_queue(state, p);
1821}
1822bool can_appoint_ruling_party(sys::state& state, dcon::nation_id source, dcon::political_party_id p) {
1823 /*
1824 The ideology of the ruling party must be permitted by the government form. There can't be an ongoing election. It can't be the
1825 current ruling party. The government must allow the player to set the ruling party. The ruling party can manually be changed
1826 at most once per year.
1827 */
1828 if(state.world.nation_get_ruling_party(source) == p)
1829 return false;
1830 if(!politics::political_party_is_active(state, source, p))
1831 return false;
1832 if(!politics::can_appoint_ruling_party(state, source))
1833 return false;
1834
1835 auto last_change = state.world.nation_get_ruling_party_last_appointed(source);
1836 if(last_change && state.current_date < last_change + 365)
1837 return false;
1838
1839 if(politics::is_election_ongoing(state, source))
1840 return false;
1841
1842 auto gov = state.world.nation_get_government_type(source);
1843 auto new_ideology = state.world.political_party_get_ideology(p);
1844 if((state.world.government_type_get_ideologies_allowed(gov) & ::culture::to_bits(new_ideology)) == 0) {
1845 return false;
1846 }
1847
1848 return true;
1849}
1850void execute_appoint_ruling_party(sys::state& state, dcon::nation_id source, dcon::political_party_id p) {
1851 politics::appoint_ruling_party(state, source, p);
1852}
1853
1854void enact_reform(sys::state& state, dcon::nation_id source, dcon::reform_option_id r) {
1855 payload p;
1856 memset(&p, 0, sizeof(payload));
1858 p.source = source;
1859 p.data.reform_selection.r = r;
1860 add_to_command_queue(state, p);
1861}
1862bool can_enact_reform(sys::state& state, dcon::nation_id source, dcon::reform_option_id r) {
1863 if(source == state.local_player_nation && state.cheat_data.always_allow_reforms)
1864 return true;
1865
1866 bool is_military = state.world.reform_get_reform_type(state.world.reform_option_get_parent_reform(r)) ==
1868 if(is_military)
1869 return politics::can_enact_military_reform(state, source, r);
1870 else
1871 return politics::can_enact_economic_reform(state, source, r);
1872}
1873void execute_enact_reform(sys::state& state, dcon::nation_id source, dcon::reform_option_id r) {
1874 nations::enact_reform(state, source, r);
1876}
1877
1878void enact_issue(sys::state& state, dcon::nation_id source, dcon::issue_option_id i) {
1879 payload p;
1880 memset(&p, 0, sizeof(payload));
1882 p.source = source;
1883 p.data.issue_selection.r = i;
1884 add_to_command_queue(state, p);
1885}
1886bool can_enact_issue(sys::state& state, dcon::nation_id source, dcon::issue_option_id i) {
1887 if(source == state.local_player_nation && state.cheat_data.always_allow_reforms)
1888 return true;
1889
1890 auto type = state.world.issue_get_issue_type(state.world.issue_option_get_parent_issue(i));
1892 return politics::can_enact_political_reform(state, source, i);
1893 else if(type == uint8_t(culture::issue_type::social))
1894 return politics::can_enact_social_reform(state, source, i);
1895 else
1896 return false;
1897}
1898void execute_enact_issue(sys::state& state, dcon::nation_id source, dcon::issue_option_id i) {
1899 nations::enact_issue(state, source, i);
1901}
1902
1903void become_interested_in_crisis(sys::state& state, dcon::nation_id source) {
1904 payload p;
1905 memset(&p, 0, sizeof(payload));
1907 p.source = source;
1908 add_to_command_queue(state, p);
1909}
1910bool can_become_interested_in_crisis(sys::state& state, dcon::nation_id source) {
1911 /*
1912 Not already interested in the crisis. Is a great power. Not at war. The crisis must have already gotten its initial backers.
1913 */
1914 if(!nations::is_great_power(state, source))
1915 return false;
1916
1917 if(state.world.nation_get_is_at_war(source))
1918 return false;
1919
1920 if(state.world.nation_get_disarmed_until(source) && state.current_date < state.world.nation_get_disarmed_until(source))
1921 return false;
1922
1923 if(state.current_crisis_mode != sys::crisis_mode::heating_up)
1924 return false;
1925
1926 for(auto& i : state.crisis_participants) {
1927 if(i.id == source)
1928 return false;
1929 if(!i.id)
1930 return true;
1931 }
1932
1933 return true;
1934}
1935void execute_become_interested_in_crisis(sys::state& state, dcon::nation_id source) {
1936 for(auto& i : state.crisis_participants) {
1937 if(!i.id) {
1938 i.id = source;
1939 i.merely_interested = true;
1940 return;
1941 }
1942 }
1943}
1944
1945void take_sides_in_crisis(sys::state& state, dcon::nation_id source, bool join_attacker) {
1946 payload p;
1947 memset(&p, 0, sizeof(payload));
1949 p.source = source;
1950 p.data.crisis_join.join_attackers = join_attacker;
1951 add_to_command_queue(state, p);
1952}
1953bool can_take_sides_in_crisis(sys::state& state, dcon::nation_id source, bool join_attacker) {
1954 /*
1955 Must not be involved in the crisis already. Must be interested in the crisis. Must be a great power. Must not be disarmed. The
1956 crisis must have already gotten its initial backers.
1957 */
1958
1959 if(state.current_crisis_mode != sys::crisis_mode::heating_up)
1960 return false;
1961
1962 for(auto& i : state.crisis_participants) {
1963 if(i.id == source)
1964 return i.merely_interested == true;
1965 if(!i.id)
1966 return false;
1967 }
1968 return false;
1969}
1970void execute_take_sides_in_crisis(sys::state& state, dcon::nation_id source, bool join_attacker) {
1971 for(auto& i : state.crisis_participants) {
1972 if(i.id == source) {
1973 i.merely_interested = false;
1974 i.supports_attacker = join_attacker;
1975
1977 [source, join_attacker](sys::state& state, text::layout_base& contents) {
1978 text::add_line(state, contents, join_attacker ? "msg_crisis_vol_join_1" : "msg_crisis_vol_join_2", text::variable_type::x, source);
1979 },
1980 "msg_crisis_vol_join_title",
1981 source, dcon::nation_id{}, dcon::nation_id{},
1983 });
1984
1985 return;
1986 }
1987 if(!i.id)
1988 return;
1989 }
1990}
1991
1992bool can_change_stockpile_settings(sys::state& state, dcon::nation_id source, dcon::commodity_id c, float target_amount,
1993 bool draw_on_stockpiles) {
1994 return true;
1995}
1996
1997void change_stockpile_settings(sys::state& state, dcon::nation_id source, dcon::commodity_id c, float target_amount,
1998 bool draw_on_stockpiles) {
1999 payload p;
2000 memset(&p, 0, sizeof(payload));
2002 p.source = source;
2003 p.data.stockpile_settings.amount = target_amount;
2005 p.data.stockpile_settings.draw_on_stockpiles = draw_on_stockpiles;
2006 add_to_command_queue(state, p);
2007}
2008
2009void execute_change_stockpile_settings(sys::state& state, dcon::nation_id source, dcon::commodity_id c, float target_amount,
2010 bool draw_on_stockpiles) {
2011 state.world.nation_set_stockpile_targets(source, c, target_amount);
2012 state.world.nation_set_drawing_on_stockpiles(source, c, draw_on_stockpiles);
2013}
2014
2015void take_decision(sys::state& state, dcon::nation_id source, dcon::decision_id d) {
2016 payload p;
2017 memset(&p, 0, sizeof(payload));
2019 p.source = source;
2020 p.data.decision.d = d;
2021 add_to_command_queue(state, p);
2022}
2023bool can_take_decision(sys::state& state, dcon::nation_id source, dcon::decision_id d) {
2024 if(!(state.world.nation_get_is_player_controlled(source) && state.cheat_data.always_potential_decisions)) {
2025 auto condition = state.world.decision_get_potential(d);
2026 if(condition && !trigger::evaluate(state, condition, trigger::to_generic(source), trigger::to_generic(source), 0))
2027 return false;
2028 }
2029 if(!(state.world.nation_get_is_player_controlled(source) && state.cheat_data.always_allow_decisions)) {
2030 auto condition = state.world.decision_get_allow(d);
2031 if(condition && !trigger::evaluate(state, condition, trigger::to_generic(source), trigger::to_generic(source), 0))
2032 return false;
2033 }
2034 return true;
2035}
2036void execute_take_decision(sys::state& state, dcon::nation_id source, dcon::decision_id d) {
2037 if(auto e = state.world.decision_get_effect(d); e) {
2038 effect::execute(state, e, trigger::to_generic(source), trigger::to_generic(source), 0, uint32_t(state.current_date.value),
2039 uint32_t(source.index() << 4 ^ d.index()));
2041 }
2042
2044 [source, d, when = state.current_date](sys::state& state, text::layout_base& contents) {
2045 text::add_line(state, contents, "msg_decision_1", text::variable_type::x, source, text::variable_type::y, state.world.decision_get_name(d));
2046 if(auto e = state.world.decision_get_effect(d); e) {
2047 text::add_line(state, contents, "msg_decision_2");
2048 ui::effect_description(state, contents, e, trigger::to_generic(source), trigger::to_generic(source), 0, uint32_t(when.value),
2049 uint32_t(source.index() << 4 ^ d.index()));
2050 }
2051 },
2052 "msg_decision_title",
2053 source, dcon::nation_id{}, dcon::nation_id{},
2055 });
2056}
2057
2059 payload p;
2060 memset(&p, 0, sizeof(payload));
2062 p.source = e.n;
2072 add_to_command_queue(state, p);
2073}
2075 payload p;
2076 memset(&p, 0, sizeof(payload));
2078 p.source = e.n;
2084 add_to_command_queue(state, p);
2085}
2087 payload p;
2088 memset(&p, 0, sizeof(payload));
2090 p.source = state.world.province_get_nation_from_province_ownership(e.p);
2099 add_to_command_queue(state, p);
2100}
2102 payload p;
2103 memset(&p, 0, sizeof(payload));
2105 p.source = state.world.province_get_nation_from_province_ownership(e.p);
2112 add_to_command_queue(state, p);
2113}
2114void execute_make_event_choice(sys::state& state, dcon::nation_id source, pending_human_n_event_data const& e) {
2115 event::take_option(state,
2116 event::pending_human_n_event {e.r_lo, e.r_hi, e.primary_slot, e.from_slot, e.date, e.e, source, e.pt, e.ft}, e.opt_choice);
2118}
2119void execute_make_event_choice(sys::state& state, dcon::nation_id source, pending_human_f_n_event_data const& e) {
2122}
2123void execute_make_event_choice(sys::state& state, dcon::nation_id source, pending_human_p_event_data const& e) {
2124 if(source != state.world.province_get_nation_from_province_ownership(e.p))
2125 return;
2126
2129}
2130void execute_make_event_choice(sys::state& state, dcon::nation_id source, pending_human_f_p_event_data const& e) {
2131 if(source != state.world.province_get_nation_from_province_ownership(e.p))
2132 return;
2133
2136}
2137
2138void fabricate_cb(sys::state& state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id type) {
2139 payload p;
2140 memset(&p, 0, sizeof(payload));
2142 p.source = source;
2143 p.data.cb_fabrication.target = target;
2144 p.data.cb_fabrication.type = type;
2145 add_to_command_queue(state, p);
2146}
2147bool can_fabricate_cb(sys::state& state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id type) {
2148 if(source == target)
2149 return false;
2150
2151 if(state.world.nation_get_constructing_cb_type(source))
2152 return false;
2153
2154 /*
2155 Can't fabricate on someone you are at war with. Requires
2156 defines:MAKE_CB_DIPLOMATIC_COST diplomatic points. Can't fabricate on your sphere members
2157 */
2158
2159 // Allow subjects to declare wars if can_use of CB definition allows for that as per Vanilla logic.
2160 auto ol = state.world.nation_get_overlord_as_subject(source);
2161 if(state.defines.alice_allow_subjects_declare_wars < 1 && state.world.overlord_get_ruler(ol) && state.world.overlord_get_ruler(ol) != target)
2162 return false;
2163
2164 if(state.world.nation_get_in_sphere_of(target) == source)
2165 return false;
2166
2167 if(state.world.nation_get_is_player_controlled(source) && state.world.nation_get_diplomatic_points(source) < state.defines.make_cb_diplomatic_cost)
2168 return false;
2169
2170 if(military::are_at_war(state, target, source))
2171 return false;
2172
2173 if(military::has_truce_with(state, source, target))
2174 return false;
2175
2176 /*
2177 must be able to fabricate cb
2178 */
2179
2180 auto bits = state.world.cb_type_get_type_bits(type);
2182 return false;
2183
2184 if(!military::cb_conditions_satisfied(state, source, target, type))
2185 return false;
2186
2187 return true;
2188}
2189
2190void execute_fabricate_cb(sys::state& state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id type) {
2191 state.world.nation_set_constructing_cb_target(source, target);
2192 state.world.nation_set_constructing_cb_type(source, type);
2193 state.world.nation_get_diplomatic_points(source) -= state.defines.make_cb_diplomatic_cost;
2194}
2195
2196bool can_cancel_cb_fabrication(sys::state& state, dcon::nation_id source) {
2197 return true;
2198}
2199
2200void cancel_cb_fabrication(sys::state& state, dcon::nation_id source) {
2201 payload p;
2202 memset(&p, 0, sizeof(payload));
2204 p.source = source;
2205 add_to_command_queue(state, p);
2206}
2207void execute_cancel_cb_fabrication(sys::state& state, dcon::nation_id source) {
2208 state.world.nation_set_constructing_cb_target(source, dcon::nation_id{});
2209 state.world.nation_set_constructing_cb_is_discovered(source, false);
2210 state.world.nation_set_constructing_cb_progress(source, 0.0f);
2211 state.world.nation_set_constructing_cb_type(source, dcon::cb_type_id{});
2212}
2213
2214void ask_for_military_access(sys::state& state, dcon::nation_id asker, dcon::nation_id target) {
2215 payload p;
2216 memset(&p, 0, sizeof(payload));
2218 p.source = asker;
2219 p.data.diplo_action.target = target;
2220 add_to_command_queue(state, p);
2221}
2222bool can_ask_for_access(sys::state& state, dcon::nation_id asker, dcon::nation_id target, bool ignore_cost) {
2223 /*
2224 Must have defines:ASKMILACCESS_DIPLOMATIC_COST diplomatic points. Must not be at war against each other. Must not already have
2225 military access.
2226 */
2227 if(asker == target)
2228 return false;
2229
2230 if(!ignore_cost && state.world.nation_get_is_player_controlled(asker) && state.world.nation_get_diplomatic_points(asker) < state.defines.askmilaccess_diplomatic_cost)
2231 return false;
2232
2233 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, asker);
2234 if(state.world.unilateral_relationship_get_military_access(rel))
2235 return false;
2236
2237 if(military::are_at_war(state, asker, target))
2238 return false;
2239
2240 return true;
2241}
2242void execute_ask_for_access(sys::state& state, dcon::nation_id asker, dcon::nation_id target) {
2243 state.world.nation_get_diplomatic_points(asker) -= state.defines.askmilaccess_diplomatic_cost;
2244
2246 memset(&m, 0, sizeof(diplomatic_message::message));
2247 m.to = target;
2248 m.from = asker;
2250
2251 diplomatic_message::post(state, m);
2252}
2253
2254void give_military_access(sys::state& state, dcon::nation_id asker, dcon::nation_id target) {
2255 payload p;
2256 memset(&p, 0, sizeof(payload));
2258 p.source = asker;
2259 p.data.diplo_action.target = target;
2260 add_to_command_queue(state, p);
2261}
2262bool can_give_military_access(sys::state& state, dcon::nation_id asker, dcon::nation_id target, bool ignore_cost) {
2263 if(asker == target)
2264 return false;
2265
2266 if(!ignore_cost && state.world.nation_get_is_player_controlled(asker) && state.world.nation_get_diplomatic_points(asker) < state.defines.givemilaccess_diplomatic_cost)
2267 return false;
2268
2269 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(asker, target);
2270 if(state.world.unilateral_relationship_get_military_access(rel))
2271 return false;
2272
2273 if(military::are_at_war(state, asker, target))
2274 return false;
2275
2276 return true;
2277}
2278void execute_give_military_access(sys::state& state, dcon::nation_id asker, dcon::nation_id target) {
2279 state.world.nation_get_diplomatic_points(asker) -= state.defines.givemilaccess_diplomatic_cost;
2280
2281 auto urel = state.world.get_unilateral_relationship_by_unilateral_pair(asker, target);
2282 if(!urel) {
2283 urel = state.world.force_create_unilateral_relationship(asker, target);
2284 }
2285 state.world.unilateral_relationship_set_military_access(urel, true);
2286 nations::adjust_relationship(state, asker, target, state.defines.givemilaccess_relation_on_accept);
2287}
2288
2289void ask_for_alliance(sys::state& state, dcon::nation_id asker, dcon::nation_id target) {
2290 payload p;
2291 memset(&p, 0, sizeof(payload));
2293 p.source = asker;
2294 p.data.diplo_action.target = target;
2295 add_to_command_queue(state, p);
2296}
2297bool can_ask_for_alliance(sys::state& state, dcon::nation_id asker, dcon::nation_id target, bool ignore_cost) {
2298 /*
2299 Must not have an alliance. Must not be in a war against each other. Costs defines:ALLIANCE_DIPLOMATIC_COST diplomatic points.
2300 Great powers may not form an alliance while there is an active crisis. Vassals and substates may only form an alliance with
2301 their overlords.
2302 */
2303 if(asker == target)
2304 return false;
2305
2306 if(!ignore_cost && state.world.nation_get_is_player_controlled(asker) && state.world.nation_get_diplomatic_points(asker) < state.defines.alliance_diplomatic_cost)
2307 return false;
2308
2309 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(target, asker);
2310 if(state.world.diplomatic_relation_get_are_allied(rel))
2311 return false;
2312
2313 if(state.world.nation_get_is_great_power(asker) && state.world.nation_get_is_great_power(target) &&
2314 state.current_crisis != sys::crisis_type::none) {
2315 return false;
2316 }
2317
2318 auto ol = state.world.nation_get_overlord_as_subject(asker);
2319 if(state.world.overlord_get_ruler(ol))
2320 return false;
2321 auto ol2 = state.world.nation_get_overlord_as_subject(target);
2322 if(state.world.overlord_get_ruler(ol2))
2323 return false;
2324
2325 if(military::are_at_war(state, asker, target))
2326 return false;
2327 return true;
2328}
2329void execute_ask_for_alliance(sys::state& state, dcon::nation_id asker, dcon::nation_id target) {
2330 if(!can_ask_for_alliance(state, asker, target))
2331 return;
2332
2333 state.world.nation_get_diplomatic_points(asker) -= state.defines.alliance_diplomatic_cost;
2334
2336 memset(&m, 0, sizeof(diplomatic_message::message));
2337 m.to = target;
2338 m.from = asker;
2340
2341 diplomatic_message::post(state, m);
2342}
2343
2344void toggle_interested_in_alliance(sys::state& state, dcon::nation_id asker, dcon::nation_id target) {
2345 payload p;
2346 memset(&p, 0, sizeof(payload));
2348 p.source = asker;
2349 p.data.diplo_action.target = target;
2350 add_to_command_queue(state, p);
2351}
2352bool can_toggle_interested_in_alliance(sys::state& state, dcon::nation_id asker, dcon::nation_id target) {
2353 if(asker == target)
2354 return false;
2355 return true;
2356}
2357void execute_toggle_interested_in_alliance(sys::state& state, dcon::nation_id asker, dcon::nation_id target) {
2358 if(!can_toggle_interested_in_alliance(state, asker, target))
2359 return;
2360 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, asker);
2361 if(!rel)
2362 rel = state.world.force_create_unilateral_relationship(target, asker);
2363 state.world.unilateral_relationship_set_interested_in_alliance(rel, !state.world.unilateral_relationship_get_interested_in_alliance(rel));
2364}
2365
2366void state_transfer(sys::state& state, dcon::nation_id asker, dcon::nation_id target, dcon::state_definition_id sid) {
2367 payload p;
2368 memset(&p, 0, sizeof(payload));
2370 p.source = asker;
2371 p.data.state_transfer.target = target;
2372 p.data.state_transfer.state = sid;
2373 add_to_command_queue(state, p);
2374}
2375bool can_state_transfer(sys::state& state, dcon::nation_id asker, dcon::nation_id target, dcon::state_definition_id sid) {
2376 /* (No state specified) To state transfer: Can't be same asker into target, both must be players. If any are great powers,
2377 they can't state transfer when a crisis occurs. They can't be subjects. They can't be in a state of war */
2378 if(asker == target)
2379 return false;
2380 if(!state.world.nation_get_is_player_controlled(asker) || !state.world.nation_get_is_player_controlled(target))
2381 return false;
2382 if(state.current_crisis != sys::crisis_type::none)
2383 return false;
2384 auto ol = state.world.nation_get_overlord_as_subject(asker);
2385 if(state.world.overlord_get_ruler(ol))
2386 return false;
2387 auto ol2 = state.world.nation_get_overlord_as_subject(target);
2388 if(state.world.overlord_get_ruler(ol2))
2389 return false;
2390 if(state.world.nation_get_is_at_war(asker) || state.world.nation_get_is_at_war(target))
2391 return false;
2392 //Redundant, if we're at war already, we will return false:
2393 //if(military::are_at_war(state, asker, target))
2394 // return false;
2395 // "Asker gives to target"
2396 for(const auto ab : state.world.state_definition_get_abstract_state_membership(sid)) {
2397 if(ab.get_province().get_province_ownership().get_nation() == asker) {
2398 // Must be controlled by us (if not, it means there are rebels, and we don't allow
2399 // state transfers on states with rebels)
2400 if(ab.get_province().get_province_control().get_nation() != asker)
2401 return false;
2402 }
2403 }
2404 if(state.world.nation_get_owned_state_count(asker) == 1)
2405 return false;
2406 return true;
2407}
2408void execute_state_transfer(sys::state& state, dcon::nation_id asker, dcon::nation_id target, dcon::state_definition_id sid) {
2409 if(!can_state_transfer(state, asker, target, sid))
2410 return;
2411
2413 memset(&m, 0, sizeof(diplomatic_message::message));
2414 m.to = target;
2415 m.from = asker;
2417 m.data.state = sid;
2418 diplomatic_message::post(state, m);
2419}
2420
2421void call_to_arms(sys::state& state, dcon::nation_id asker, dcon::nation_id target, dcon::war_id w) {
2422 payload p;
2423 memset(&p, 0, sizeof(payload));
2425 p.source = asker;
2426 p.data.call_to_arms.target = target;
2427 p.data.call_to_arms.war = w;
2428 add_to_command_queue(state, p);
2429}
2430bool can_call_to_arms(sys::state& state, dcon::nation_id asker, dcon::nation_id target, dcon::war_id w, bool ignore_cost) {
2431 if(asker == target)
2432 return false;
2433
2434 if(!ignore_cost && state.world.nation_get_is_player_controlled(asker) && state.world.nation_get_diplomatic_points(asker) < state.defines.callally_diplomatic_cost)
2435 return false;
2436
2437 if(!nations::are_allied(state, asker, target) && !(state.world.war_get_primary_defender(w) == asker && state.world.nation_get_in_sphere_of(asker) == target))
2438 return false;
2439
2440 if(military::is_civil_war(state, w))
2441 return false;
2442
2443 if(!military::standard_war_joining_is_possible(state, w, target, military::is_attacker(state, w, asker)))
2444 return false;
2445
2446 if(state.world.war_get_is_crisis_war(w) && !state.military_definitions.great_wars_enabled)
2447 return false;
2448
2449 return true;
2450}
2451void execute_call_to_arms(sys::state& state, dcon::nation_id asker, dcon::nation_id target, dcon::war_id w) {
2452 state.world.nation_get_diplomatic_points(asker) -= state.defines.callally_diplomatic_cost;
2453
2455 memset(&m, 0, sizeof(diplomatic_message::message));
2456 m.to = target;
2457 m.from = asker;
2458 m.data.war = w;
2460
2461 diplomatic_message::post(state, m);
2462}
2463
2464void respond_to_diplomatic_message(sys::state& state, dcon::nation_id source, dcon::nation_id from, diplomatic_message::type type,
2465 bool accept) {
2466 payload p;
2467 memset(&p, 0, sizeof(payload));
2469 p.source = source;
2470 p.data.message.accept = accept;
2471 p.data.message.from = from;
2472 p.data.message.type = type;
2473 add_to_command_queue(state, p);
2474}
2475void execute_respond_to_diplomatic_message(sys::state& state, dcon::nation_id source, dcon::nation_id from,
2476 diplomatic_message::type type, bool accept) {
2477 for(auto& m : state.pending_messages) {
2478 if(m.type == type && m.from == from && m.to == source) {
2479
2480 if(accept)
2482 else
2484
2486
2487 return;
2488 }
2489 }
2490}
2491
2492void cancel_military_access(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
2493 payload p;
2494 memset(&p, 0, sizeof(payload));
2496 p.source = source;
2497 p.data.diplo_action.target = target;
2498 add_to_command_queue(state, p);
2499}
2500bool can_cancel_military_access(sys::state& state, dcon::nation_id source, dcon::nation_id target, bool ignore_cost) {
2501 if(source == target)
2502 return false;
2503
2504 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, source);
2505 if(!ignore_cost && state.world.nation_get_is_player_controlled(source) && state.world.nation_get_diplomatic_points(source) < state.defines.cancelaskmilaccess_diplomatic_cost)
2506 return false;
2507
2508 if(state.world.unilateral_relationship_get_military_access(rel))
2509 return true;
2510 else
2511 return false;
2512}
2513void execute_cancel_military_access(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
2514 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, source);
2515 if(rel)
2516 state.world.unilateral_relationship_set_military_access(rel, false);
2517
2518 state.world.nation_get_diplomatic_points(source) -= state.defines.cancelaskmilaccess_diplomatic_cost;
2519 nations::adjust_relationship(state, source, target, state.defines.cancelaskmilaccess_relation_on_accept);
2520
2522 [source, target](sys::state& state, text::layout_base& contents) {
2523 text::add_line(state, contents, "msg_access_canceled_a_1", text::variable_type::x, source, text::variable_type::y, target);
2524 },
2525 "msg_access_canceled_a_title",
2526 source, target, dcon::nation_id{},
2528 });
2529}
2530
2531void cancel_given_military_access(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
2532 payload p;
2533 memset(&p, 0, sizeof(payload));
2535 p.source = source;
2536 p.data.diplo_action.target = target;
2537 add_to_command_queue(state, p);
2538}
2539bool can_cancel_given_military_access(sys::state& state, dcon::nation_id source, dcon::nation_id target, bool ignore_cost) {
2540 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(source, target);
2541
2542 if(!ignore_cost && state.world.nation_get_is_player_controlled(source) && state.world.nation_get_diplomatic_points(source) < state.defines.cancelgivemilaccess_diplomatic_cost)
2543 return false;
2544
2545 if(state.world.unilateral_relationship_get_military_access(rel))
2546 return true;
2547 else
2548 return false;
2549}
2550void execute_cancel_given_military_access(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
2551 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(source, target);
2552 if(rel)
2553 state.world.unilateral_relationship_set_military_access(rel, false);
2554
2555 state.world.nation_get_diplomatic_points(source) -= state.defines.cancelgivemilaccess_diplomatic_cost;
2556 nations::adjust_relationship(state, source, target, state.defines.cancelgivemilaccess_relation_on_accept);
2557
2558 if(source != state.local_player_nation) {
2560 [source, target](sys::state& state, text::layout_base& contents) {
2561 text::add_line(state, contents, "msg_access_canceled_b_1", text::variable_type::x, source, text::variable_type::y, target);
2562 },
2563 "msg_access_canceled_b_title",
2564 source, target, dcon::nation_id{},
2566 });
2567 }
2568}
2569
2570void cancel_alliance(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
2571 payload p;
2572 memset(&p, 0, sizeof(payload));
2574 p.source = source;
2575 p.data.diplo_action.target = target;
2576 add_to_command_queue(state, p);
2577}
2578bool can_cancel_alliance(sys::state& state, dcon::nation_id source, dcon::nation_id target, bool ignore_cost) {
2579 if(source == target)
2580 return false;
2581
2582 if(!ignore_cost && state.world.nation_get_is_player_controlled(source) && state.world.nation_get_diplomatic_points(source) < state.defines.cancelalliance_diplomatic_cost)
2583 return false;
2584
2585 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(target, source);
2586 if(!state.world.diplomatic_relation_get_are_allied(rel))
2587 return false;
2588
2589 //if(military::are_allied_in_war(state, source, target))
2590 // return false;
2591
2592 auto ol = state.world.nation_get_overlord_as_subject(source);
2593 if(state.world.overlord_get_ruler(ol) == target)
2594 return false;
2595
2596 return true;
2597}
2598void execute_cancel_alliance(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
2599 state.world.nation_get_diplomatic_points(source) -= state.defines.cancelalliance_diplomatic_cost;
2600 nations::adjust_relationship(state, source, target, state.defines.cancelalliance_relation_on_accept);
2601
2602 nations::break_alliance(state, source, target);
2603}
2604
2605void declare_war(sys::state& state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id primary_cb,
2606 dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation, bool call_attacker_allies) {
2607
2608 payload p;
2609 memset(&p, 0, sizeof(payload));
2611 p.source = source;
2612 p.data.new_war.target = target;
2613 p.data.new_war.primary_cb = primary_cb;
2614 p.data.new_war.cb_state = cb_state;
2615 p.data.new_war.cb_tag = cb_tag;
2616 p.data.new_war.cb_secondary_nation = cb_secondary_nation;
2617 p.data.new_war.call_attacker_allies = call_attacker_allies;
2618 add_to_command_queue(state, p);
2619}
2620
2621bool can_declare_war(sys::state& state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id primary_cb,
2622 dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation) {
2623 dcon::nation_id real_target = target;
2624
2625 auto target_ol_rel = state.world.nation_get_overlord_as_subject(target);
2626 if(state.world.overlord_get_ruler(target_ol_rel))
2627 real_target = state.world.overlord_get_ruler(target_ol_rel);
2628
2629 if(source == target || source == real_target)
2630 return false;
2631
2632 if(state.world.nation_get_owned_province_count(target) == 0 || state.world.nation_get_owned_province_count(real_target) == 0)
2633 return false;
2634
2635 if(military::are_allied_in_war(state, source, real_target) || military::are_at_war(state, source, real_target))
2636 return false;
2637
2638 if(nations::are_allied(state, real_target, source))
2639 return false;
2640
2641 auto source_ol_rel = state.world.nation_get_overlord_as_subject(source);
2642 if(state.world.overlord_get_ruler(source_ol_rel) && state.world.overlord_get_ruler(source_ol_rel) != real_target)
2643 return false;
2644
2645 if(state.world.nation_get_in_sphere_of(real_target) == source)
2646 return false;
2647
2648 if(state.world.nation_get_is_player_controlled(source) && state.world.nation_get_diplomatic_points(source) < state.defines.declarewar_diplomatic_cost)
2649 return false;
2650
2651 // check CB validity
2652 if(!military::cb_instance_conditions_satisfied(state, source, target, primary_cb, cb_state, cb_tag, cb_secondary_nation))
2653 return false;
2654
2655 return true;
2656}
2657
2658void execute_declare_war(sys::state& state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id primary_cb,
2659 dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation, bool call_attacker_allies) {
2660 state.world.nation_get_diplomatic_points(source) -= state.defines.declarewar_diplomatic_cost;
2661 nations::adjust_relationship(state, source, target, state.defines.declarewar_relation_on_accept);
2662
2663 dcon::nation_id real_target = target;
2664
2665 auto target_ol_rel = state.world.nation_get_overlord_as_subject(target);
2666 if(state.world.overlord_get_ruler(target_ol_rel))
2667 real_target = state.world.overlord_get_ruler(target_ol_rel);
2668
2669 if(military::has_truce_with(state, source, real_target)) {
2670 auto cb_infamy = military::truce_break_cb_infamy(state, primary_cb);
2671 auto cb_militancy = military::truce_break_cb_militancy(state, primary_cb);
2672 auto cb_prestige_loss = military::truce_break_cb_prestige_cost(state, primary_cb);
2673
2674 state.world.nation_get_infamy(source) += cb_infamy;
2675 nations::adjust_prestige(state, source, cb_prestige_loss);
2676
2677 for(auto prov : state.world.nation_get_province_ownership(source)) {
2678 for(auto pop : prov.get_province().get_pop_location()) {
2679 auto mil = pop_demographics::get_militancy(state, pop.get_pop());
2680 pop_demographics::set_militancy(state, pop.get_pop().id, std::min(mil + cb_militancy, 10.0f));
2681 }
2682 }
2683 }
2684
2685 // remove used cb
2686 auto current_cbs = state.world.nation_get_available_cbs(source);
2687 for(uint32_t i = current_cbs.size(); i-- > 0;) {
2688 if(current_cbs[i].cb_type == primary_cb && current_cbs[i].target == target) {
2689 current_cbs.remove_at(i);
2690 break;
2691 }
2692 }
2693
2694 auto war = military::create_war(state, source, target, primary_cb, cb_state, cb_tag, cb_secondary_nation);
2696 if(call_attacker_allies) {
2698 }
2699}
2700
2701void add_war_goal(sys::state& state, dcon::nation_id source, dcon::war_id w, dcon::nation_id target, dcon::cb_type_id cb_type,
2702 dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation) {
2703 payload p;
2704 memset(&p, 0, sizeof(payload));
2706 p.source = source;
2707 p.data.new_war_goal.target = target;
2708 p.data.new_war_goal.cb_type = cb_type;
2709 p.data.new_war_goal.cb_state = cb_state;
2710 p.data.new_war_goal.cb_tag = cb_tag;
2711 p.data.new_war_goal.cb_secondary_nation = cb_secondary_nation;
2712 p.data.new_war_goal.war = w;
2713 add_to_command_queue(state, p);
2714}
2715bool can_add_war_goal(sys::state& state, dcon::nation_id source, dcon::war_id w, dcon::nation_id target, dcon::cb_type_id cb_type,
2716 dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation) {
2717 /*
2718 The nation adding the war goal must have positive war score against the target of the war goal (see below). And the nation
2719 must be already able to use the CB in question (e.g. it as fabricated previously) or it must be a constructible CB and the
2720 nation adding the war goal must have overall jingoism support >= defines:WARGOAL_JINGOISM_REQUIREMENT (x
2721 defines:GW_JINGOISM_REQUIREMENT_MOD in a great war).
2722 */
2723 if(source == target)
2724 return false;
2725
2726 if(state.world.nation_get_is_player_controlled(source) && state.cheat_data.always_allow_wargoals)
2727 return true;
2728
2729 if(state.world.nation_get_is_player_controlled(source) && state.world.nation_get_diplomatic_points(source) < state.defines.addwargoal_diplomatic_cost)
2730 return false;
2731
2732 bool is_attacker = military::is_attacker(state, w, source);
2733 bool target_in_war = false;
2734
2735 for(auto par : state.world.war_get_war_participant(w)) {
2736 if(par.get_nation() == target) {
2737 if(par.get_is_attacker() == is_attacker)
2738 return false;
2739 target_in_war = true;
2740 break;
2741 }
2742 }
2743
2744 if(!is_attacker && military::defenders_have_status_quo_wargoal(state, w))
2745 return false;
2746
2747 if(!target_in_war)
2748 return false;
2749
2750 // prevent duplicate war goals
2751 if(military::war_goal_would_be_duplicate(state, source, w, target, cb_type, cb_state, cb_tag, cb_secondary_nation))
2752 return false;
2753
2754 if((state.world.cb_type_get_type_bits(cb_type) & military::cb_flag::always) == 0) {
2755 bool cb_fabbed = false;
2756 for(auto& fab_cb : state.world.nation_get_available_cbs(source)) {
2757 if(fab_cb.cb_type == cb_type && fab_cb.target == target) {
2758 cb_fabbed = true;
2759 break;
2760 }
2761 }
2762 if(!cb_fabbed) {
2763 if((state.world.cb_type_get_type_bits(cb_type) & military::cb_flag::is_not_constructing_cb) != 0)
2764 return false; // can only add a constructable cb this way
2765
2766 auto totalpop = state.world.nation_get_demographics(source, demographics::total);
2767 auto jingoism_perc = totalpop > 0 ? state.world.nation_get_demographics(source, demographics::to_key(state, state.culture_definitions.jingoism)) / totalpop : 0.0f;
2768
2769 if(state.world.war_get_is_great(w)) {
2770 if(jingoism_perc < state.defines.wargoal_jingoism_requirement * state.defines.gw_wargoal_jingoism_requirement_mod)
2771 return false;
2772 } else {
2773 if(jingoism_perc < state.defines.wargoal_jingoism_requirement)
2774 return false;
2775 }
2776 }
2777 }
2778 if(!military::cb_instance_conditions_satisfied(state, source, target, cb_type, cb_state, cb_tag, cb_secondary_nation))
2779 return false;
2780
2781 return true;
2782}
2783void execute_add_war_goal(sys::state& state, dcon::nation_id source, dcon::war_id w, dcon::nation_id target,
2784 dcon::cb_type_id cb_type, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag,
2785 dcon::nation_id cb_secondary_nation) {
2786
2787 if(!can_add_war_goal(state, source, w, target, cb_type, cb_state, cb_tag, cb_secondary_nation))
2788 return;
2789
2790 state.world.nation_get_diplomatic_points(source) -= state.defines.addwargoal_diplomatic_cost;
2791 nations::adjust_relationship(state, source, target, state.defines.addwargoal_relation_on_accept);
2792
2793 float infamy = military::cb_addition_infamy_cost(state, w, cb_type, source, target);
2794 state.world.nation_get_infamy(source) += infamy;
2795
2796 military::add_wargoal(state, w, source, target, cb_type, cb_state, cb_tag, cb_secondary_nation);
2797}
2798
2799void start_peace_offer(sys::state& state, dcon::nation_id source, dcon::nation_id target, dcon::war_id war, bool is_concession) {
2800 payload p;
2801 memset(&p, 0, sizeof(payload));
2803 p.source = source;
2804 p.data.new_offer.target = target;
2805 p.data.new_offer.war = war;
2806 p.data.new_offer.is_concession = is_concession;
2807 add_to_command_queue(state, p);
2808}
2809bool can_start_peace_offer(sys::state& state, dcon::nation_id source, dcon::nation_id target, dcon::war_id war, bool is_concession) {
2810 assert(source);
2811 assert(target);
2812 {
2813 auto ol = state.world.nation_get_overlord_as_subject(source);
2814 if(state.world.overlord_get_ruler(ol) && !(state.world.war_get_primary_attacker(war) == source || state.world.war_get_primary_defender(war) == source))
2815 return false;
2816 }
2817 {
2818 auto ol = state.world.nation_get_overlord_as_subject(target);
2819 if(state.world.overlord_get_ruler(ol) && !(state.world.war_get_primary_attacker(war) == target || state.world.war_get_primary_defender(war) == target))
2820 return false;
2821 }
2822
2823 if(state.world.war_get_primary_attacker(war) == source) {
2824 if(military::get_role(state, war, target) != military::war_role::defender)
2825 return false;
2826 } else if(state.world.war_get_primary_defender(war) == source) {
2827 if(military::get_role(state, war, target) != military::war_role::attacker)
2828 return false;
2829 } else if(state.world.war_get_primary_attacker(war) == target) {
2830 if(military::get_role(state, war, source) != military::war_role::defender)
2831 return false;
2832 } else if(state.world.war_get_primary_defender(war) == target) {
2833 if(military::get_role(state, war, source) != military::war_role::attacker)
2834 return false;
2835 } else {
2836 return false;
2837 }
2838
2839 if(state.world.war_get_is_crisis_war(war)) {
2840 if((state.world.war_get_primary_attacker(war) != source || state.world.war_get_primary_defender(war) != target) &&
2841 (state.world.war_get_primary_attacker(war) != target || state.world.war_get_primary_defender(war) != source)) {
2842
2843 return false; // no separate peace
2844 }
2845 }
2846
2847 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
2848 return !pending;
2849}
2850void execute_start_peace_offer(sys::state& state, dcon::nation_id source, dcon::nation_id target, dcon::war_id war, bool is_concession) {
2851 auto offer = fatten(state.world, state.world.create_peace_offer());
2852 offer.set_target(target);
2853 offer.set_war_from_war_settlement(war);
2854 offer.set_is_concession(is_concession);
2855 offer.set_nation_from_pending_peace_offer(source);
2856}
2857
2858void start_crisis_peace_offer(sys::state& state, dcon::nation_id source, bool is_concession) {
2859 payload p;
2860 memset(&p, 0, sizeof(payload));
2862 p.source = source;
2863 p.data.new_offer.is_concession = is_concession;
2864 add_to_command_queue(state, p);
2865}
2866bool can_start_crisis_peace_offer(sys::state& state, dcon::nation_id source, bool is_concession) {
2867 if(source != state.primary_crisis_attacker && source != state.primary_crisis_defender)
2868 return false;
2869 if(state.current_crisis_mode != sys::crisis_mode::heating_up)
2870 return false;
2871
2872 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
2873 return !pending;
2874}
2875void execute_start_crisis_peace_offer(sys::state& state, dcon::nation_id source, bool is_concession) {
2876 auto offer = fatten(state.world, state.world.create_peace_offer());
2877 offer.set_is_concession(is_concession);
2878 offer.set_nation_from_pending_peace_offer(source);
2879 offer.set_is_crisis_offer(true);
2880
2881 if(state.current_crisis == sys::crisis_type::liberation) {
2882 if((source == state.primary_crisis_attacker && !is_concession) ||
2883 (source != state.primary_crisis_attacker && is_concession)) {
2884 auto new_wg = fatten(state.world, state.world.create_wargoal());
2885 new_wg.set_added_by(state.primary_crisis_attacker);
2886 new_wg.set_associated_state(state.world.state_instance_get_definition(state.crisis_state));
2887 new_wg.set_associated_tag(state.crisis_liberation_tag);
2888 new_wg.set_peace_offer_from_peace_offer_item(offer);
2889 new_wg.set_target_nation(state.world.state_instance_get_nation_from_state_ownership(state.crisis_state));
2890 new_wg.set_type(state.military_definitions.crisis_liberate);
2891 }
2892 } else { // colonial
2893 auto colonizers = state.world.state_definition_get_colonization(state.crisis_colony);
2894
2895 if((colonizers.end() - colonizers.begin()) >= 2) {
2896 auto attacking_colonizer = (*colonizers.begin()).get_colonizer();
2897 auto defending_colonizer = (*(colonizers.begin() + 1)).get_colonizer();
2898
2899 if((source == state.primary_crisis_attacker && !is_concession) ||
2900 (source != state.primary_crisis_attacker && is_concession)) {
2901 auto new_wg = fatten(state.world, state.world.create_wargoal());
2902 new_wg.set_added_by(attacking_colonizer);
2903 new_wg.set_associated_state(state.crisis_colony);
2904 new_wg.set_peace_offer_from_peace_offer_item(offer);
2905 new_wg.set_target_nation(defending_colonizer);
2906 new_wg.set_type(state.military_definitions.crisis_colony);
2907 } else {
2908 auto new_wg = fatten(state.world, state.world.create_wargoal());
2909 new_wg.set_added_by(defending_colonizer);
2910 new_wg.set_associated_state(state.crisis_colony);
2911 new_wg.set_peace_offer_from_peace_offer_item(offer);
2912 new_wg.set_target_nation(attacking_colonizer);
2913 new_wg.set_type(state.military_definitions.crisis_colony);
2914 }
2915 }
2916 }
2917}
2918
2919void add_to_peace_offer(sys::state& state, dcon::nation_id source, dcon::wargoal_id goal) {
2920 payload p;
2921 memset(&p, 0, sizeof(payload));
2923 p.source = source;
2924 p.data.offer_wargoal.wg = goal;
2925 add_to_command_queue(state, p);
2926}
2927bool can_add_to_peace_offer(sys::state& state, dcon::nation_id source, dcon::wargoal_id goal) {
2928 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
2929 if(!pending)
2930 return false;
2931
2932 auto war = state.world.peace_offer_get_war_from_war_settlement(pending);
2933 auto wg = fatten(state.world, goal);
2934 auto target = state.world.peace_offer_get_target(pending);
2935
2936 if(!war)
2937 return false;
2938
2939 if(wg.get_war_from_wargoals_attached() != war)
2940 return false;
2941
2942 //int32_t total = military::cost_of_peace_offer(state, pending);
2943 //int32_t new_wg_cost = military::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());
2944
2945 //if(total + new_wg_cost > 100)
2946 // return false;
2947
2948 if(state.world.war_get_primary_attacker(war) == source && state.world.war_get_primary_defender(war) == target) {
2949 return true;
2950 }
2951 if(state.world.war_get_primary_attacker(war) == target && state.world.war_get_primary_defender(war) == source) {
2952 return true;
2953 }
2954
2955 if(state.world.peace_offer_get_is_concession(pending)) {
2956 if(state.world.war_get_primary_attacker(war) == source || state.world.war_get_primary_defender(war) == source) {
2957 if(wg.get_added_by() == target)
2958 return true;
2959 if(wg.get_added_by().get_overlord_as_subject().get_ruler() == target)
2960 return true;
2961 return false;
2962 } else {
2963 if(wg.get_target_nation() == source)
2964 return true;
2965 if(wg.get_target_nation().get_overlord_as_subject().get_ruler() == source)
2966 return true;
2967 return false;
2968 }
2969 } else {
2970 if(state.world.war_get_primary_attacker(war) == source || state.world.war_get_primary_defender(war) == source) {
2971 if(wg.get_target_nation() == target)
2972 return true;
2973 if(wg.get_target_nation().get_overlord_as_subject().get_ruler() == target)
2974 return true;
2975 return false;
2976 } else {
2977 if(wg.get_added_by() == target)
2978 return true;
2979 if(wg.get_added_by().get_overlord_as_subject().get_ruler() == target)
2980 return true;
2981 return false;
2982 }
2983 }
2984}
2985void execute_add_to_peace_offer(sys::state& state, dcon::nation_id source, dcon::wargoal_id goal) {
2986 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
2987 state.world.force_create_peace_offer_item(pending, goal);
2988}
2989
2990void add_to_crisis_peace_offer(sys::state& state, dcon::nation_id source, dcon::nation_id wargoal_from, dcon::nation_id target,
2991 dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag,
2992 dcon::nation_id cb_secondary_nation) {
2993 payload p;
2994 memset(&p, 0, sizeof(payload));
2996 p.source = source;
2997 p.data.crisis_invitation.invited = wargoal_from;
2998 p.data.crisis_invitation.target = target;
2999 p.data.crisis_invitation.cb_type = primary_cb;
3000 p.data.crisis_invitation.cb_state = cb_state;
3001 p.data.crisis_invitation.cb_tag = cb_tag;
3002 p.data.crisis_invitation.cb_secondary_nation = cb_secondary_nation;
3003 add_to_command_queue(state, p);
3004}
3005bool can_add_to_crisis_peace_offer(sys::state& state, dcon::nation_id source, dcon::nation_id wargoal_from,
3006 dcon::nation_id target, dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag,
3007 dcon::nation_id cb_secondary_nation) {
3008
3009 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
3010 if(!pending)
3011 return false;
3012
3013 auto war = state.world.peace_offer_get_war_from_war_settlement(pending);
3014 if(war)
3015 return false;
3016
3017 bool found = [&]() {
3018 for(auto& par : state.crisis_participants) {
3019 if(!par.id) {
3020 return false; // not in crisis
3021 }
3022 if(par.id == wargoal_from) {
3023 if(cb_state == par.joined_with_offer.wargoal_state && cb_tag == par.joined_with_offer.wargoal_tag &&
3024 cb_secondary_nation == par.joined_with_offer.wargoal_secondary_nation && target == par.joined_with_offer.target &&
3025 primary_cb == par.joined_with_offer.wargoal_type)
3026 return true;
3027 else
3028 return false;
3029 }
3030 }
3031 return false;
3032 }();
3033
3034 if(!found)
3035 return false;
3036
3037 // no duplicates
3038 for(auto wg : state.world.peace_offer_get_peace_offer_item(pending)) {
3039 if(wg.get_wargoal().get_added_by() == wargoal_from)
3040 return false;
3041 }
3042
3043 return true;
3044}
3045void execute_add_to_crisis_peace_offer(sys::state& state, dcon::nation_id source, crisis_invitation_data const& data) {
3046 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
3047
3048 auto wg = fatten(state.world, state.world.create_wargoal());
3049 wg.set_peace_offer_from_peace_offer_item(pending);
3050 wg.set_added_by(data.invited);
3051 wg.set_associated_state(data.cb_state);
3052 wg.set_associated_tag(data.cb_tag);
3053 wg.set_secondary_nation(data.cb_secondary_nation);
3054 wg.set_target_nation(data.target);
3055 wg.set_type(data.cb_type);
3056}
3057
3058void send_peace_offer(sys::state& state, dcon::nation_id source) {
3059 payload p;
3060 memset(&p, 0, sizeof(payload));
3062 p.source = source;
3063 add_to_command_queue(state, p);
3064}
3065bool can_send_peace_offer(sys::state& state, dcon::nation_id source) {
3066 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
3067 if(!pending || !state.world.peace_offer_get_war_from_war_settlement(pending))
3068 return false;
3069 return true;
3070}
3071void execute_send_peace_offer(sys::state& state, dcon::nation_id source) {
3072 auto pending_offer = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
3073 auto in_war = state.world.peace_offer_get_war_from_war_settlement(pending_offer);
3074
3075 if(!in_war) {
3076 return;
3077 }
3078
3079 auto target = state.world.peace_offer_get_target(pending_offer);
3080
3081 // A peace offer must be accepted when war score reaches 100.
3082 if(military::directed_warscore(state, in_war, source, target) >= 100.0f && (!target.get_is_player_controlled() || !state.world.peace_offer_get_is_concession(pending_offer)) && military::cost_of_peace_offer(state, pending_offer) <= 100) {
3083
3084 military::implement_peace_offer(state, pending_offer);
3085 } else {
3087 memset(&m, 0, sizeof(diplomatic_message::message));
3088 m.to = target;
3089 m.from = source;
3090 m.data.peace = pending_offer;
3092
3093 diplomatic_message::post(state, m);
3094 }
3095}
3096
3097void send_crisis_peace_offer(sys::state& state, dcon::nation_id source) {
3098 payload p;
3099 memset(&p, 0, sizeof(payload));
3101 p.source = source;
3102 add_to_command_queue(state, p);
3103}
3104bool can_send_crisis_peace_offer(sys::state& state, dcon::nation_id source) {
3105 auto pending = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
3106 if(!pending || state.world.peace_offer_get_war_from_war_settlement(pending))
3107 return false;
3108 if(source != state.primary_crisis_attacker && source != state.primary_crisis_defender)
3109 return false;
3110 if(state.current_crisis_mode != sys::crisis_mode::heating_up)
3111 return false;
3112
3113 return true;
3114}
3115void execute_send_crisis_peace_offer(sys::state& state, dcon::nation_id source) {
3116 auto pending_offer = state.world.nation_get_peace_offer_from_pending_peace_offer(source);
3117
3118 if(!can_send_crisis_peace_offer(state, source)) {
3119 if(pending_offer) {
3120 if(!state.world.peace_offer_get_war_from_war_settlement(pending_offer))
3121 nations::cleanup_crisis_peace_offer(state, pending_offer);
3122 else
3123 state.world.delete_peace_offer(pending_offer);
3124 }
3125 return;
3126 }
3127
3128 auto target = state.primary_crisis_attacker == source ? state.primary_crisis_defender : state.primary_crisis_attacker;
3129
3131 memset(&m, 0, sizeof(diplomatic_message::message));
3132 m.to = target;
3133 m.from = source;
3134 m.data.peace = pending_offer;
3136
3137 diplomatic_message::post(state, m);
3138}
3139
3140void move_army(sys::state& state, dcon::nation_id source, dcon::army_id a, dcon::province_id dest, bool reset) {
3141 payload p;
3142 memset(&p, 0, sizeof(payload));
3144 p.source = source;
3145 p.data.army_movement.a = a;
3146 p.data.army_movement.dest = dest;
3147 p.data.army_movement.reset = reset;
3148 add_to_command_queue(state, p);
3149}
3150
3151bool can_partial_retreat_from(sys::state& state, dcon::land_battle_id b) {
3152 if(!b)
3153 return true;
3155 return false;
3156 return state.network_mode != sys::network_mode_type::single_player;
3157}
3158bool can_partial_retreat_from(sys::state& state, dcon::naval_battle_id b) {
3159 if(!b)
3160 return true;
3162 return false;
3163 return state.network_mode != sys::network_mode_type::single_player;
3164}
3165
3166std::vector<dcon::province_id> can_move_army(sys::state& state, dcon::nation_id source, dcon::army_id a, dcon::province_id dest) {
3167 if(source != state.world.army_get_controller_from_army_control(a))
3168 return std::vector<dcon::province_id>{};
3169 if(state.world.army_get_is_retreating(a))
3170 return std::vector<dcon::province_id>{};
3171 if(!dest)
3172 return std::vector<dcon::province_id>{}; // stop movement
3173
3174 auto last_province = state.world.army_get_location_from_army_location(a);
3175 auto movement = state.world.army_get_path(a);
3176 if(movement.size() > 0) {
3177 last_province = movement.at(0);
3178 }
3179
3180 if(last_province == dest)
3181 return std::vector<dcon::province_id>{};
3182
3183 if(!can_partial_retreat_from(state, state.world.army_get_battle_from_army_battle_participation(a)))
3184 return std::vector<dcon::province_id>{};
3185
3186 if(dest.index() < state.province_definitions.first_sea_province.index()) {
3187 if(state.network_mode != sys::network_mode_type::single_player) {
3188 if(state.world.army_get_battle_from_army_battle_participation(a)) {
3189 // MP special ruleset (basically applies to most MP games)
3190 // Being able to withdraw:
3191 // extern - YOUR own territory
3192 // extern - Allied territory (this is in a state of war)
3193 // extern - Territory that you have military access to (this is regulated in MP)
3194 // handled 1.0 - Enemy territory that does not have troops at the time of withdrawal (regulated in mp)
3195 // handled 1.1 - Allied/your territory that is being occupied in a war
3196 // extern - To ships (including when a naval battle is in progress)
3197 // Not being able to withdraw:
3198 // handled 1.2 - When all provinces adjacent to a battle are surrounded by enemies
3199 // handled 1.3 - No more than 1 province, to avoid multiprovince
3200 // handled 1.4 - Where there are enemy troops (your territory / ally or enemy, it doesn't matter)
3201 bool b_10 = false; // Also handles 1-1, occupied territory of allies or yours
3202 // 1.0/1.1 - Enemy territory
3203 if(military::are_at_war(state, state.world.province_get_nation_from_province_control(dest), source)) {
3204 auto units = state.world.province_get_army_location_as_location(dest);
3205 b_10 = true; // Enemy territory with no enemy units -- can retreat
3206 for(const auto unit : units) {
3207 if(unit.get_army().get_controller_from_army_control() == source)
3208 continue;
3209 if(unit.get_army().get_controller_from_army_rebel_control()
3210 || military::are_at_war(state, unit.get_army().get_controller_from_army_control(), source)) {
3211 b_10 = false; // Enemy territory with enemy units -- CAN'T retreat
3212 break;
3213 }
3214 }
3215 }
3216 // 1.2 - Sorrounding/encirclement of land units
3217 bool b_12 = false;
3218 for(const auto adj : state.world.province_get_province_adjacency(dest)) {
3219 auto other = adj.get_connected_provinces(adj.get_connected_provinces(0) == dest ? 1 : 0);
3220 if(other.id.index() < state.province_definitions.first_sea_province.index()) {
3221 auto units = state.world.province_get_army_location_as_location(dest);
3222 bool has_enemy_units = false;
3223 for(const auto unit : units) {
3224 if(unit.get_army().get_controller_from_army_rebel_control()
3225 || military::are_at_war(state, unit.get_army().get_controller_from_army_control(), source)) {
3226 has_enemy_units = true;
3227 break;
3228 }
3229 }
3230 if(!has_enemy_units) { //Not a full encirclement -- can retreat
3231 b_12 = true;
3232 break;
3233 }
3234 }
3235 }
3236 // 1.3 - Not more than 1 province
3237 bool b_13 = false;
3238 for(const auto adj : state.world.province_get_province_adjacency(dest)) {
3239 auto other = adj.get_connected_provinces(adj.get_connected_provinces(0) == dest ? 1 : 0);
3240 if(last_province == other) {
3241 b_13 = true; //Is adjacent to destination, hence a single province retreat!?
3242 break;
3243 }
3244 }
3245
3246 if(state.world.army_get_black_flag(a)) {
3247 return province::make_unowned_land_path(state, last_province, dest);
3248 } else if(province::has_access_to_province(state, source, dest) && b_12 && b_13) {
3249 return province::make_land_path(state, last_province, dest, source, a);
3250 } else if(b_10) {
3251 return province::make_unowned_land_path(state, last_province, dest);
3252 } else {
3253 return std::vector<dcon::province_id>{};
3254 }
3255 } else {
3256 if(state.world.army_get_black_flag(a)) {
3257 return province::make_unowned_land_path(state, last_province, dest);
3258 } else if(province::has_access_to_province(state, source, dest)) {
3259 return province::make_land_path(state, last_province, dest, source, a);
3260 } else {
3261 return std::vector<dcon::province_id>{};
3262 }
3263 }
3264 } else {
3265 if(state.world.army_get_black_flag(a)) {
3266 return province::make_unowned_land_path(state, last_province, dest);
3267 } else if(province::has_access_to_province(state, source, dest)) {
3268 return province::make_land_path(state, last_province, dest, source, a);
3269 } else {
3270 return std::vector<dcon::province_id>{};
3271 }
3272 }
3273 } else {
3274 if(!military::can_embark_onto_sea_tile(state, source, dest, a))
3275 return std::vector<dcon::province_id>{};
3276
3277 if(state.world.army_get_black_flag(a)) {
3278 return province::make_unowned_land_path(state, last_province, dest);
3279 } else {
3280 return province::make_land_path(state, last_province, dest, source, a);
3281 }
3282 }
3283}
3284
3285void execute_move_army(sys::state& state, dcon::nation_id source, dcon::army_id a, dcon::province_id dest, bool reset) {
3286 if(source != state.world.army_get_controller_from_army_control(a))
3287 return;
3288 if(state.world.army_get_is_retreating(a))
3289 return;
3290
3291 auto battle = state.world.army_get_battle_from_army_battle_participation(a);
3292 if(dest.index() < state.province_definitions.first_sea_province.index()) {
3293 /* Case for land destinations */
3294 if(battle && !province::has_naval_access_to_province(state, source, dest)) {
3295 return;
3296 }
3297 } else {
3298 /* Case for naval destinations, we check the land province adjacent henceforth */
3299 if(battle && !military::can_embark_onto_sea_tile(state, source, dest, a)) {
3300 return;
3301 }
3302 }
3303
3304 auto existing_path = state.world.army_get_path(a);
3305
3306 if(!dest) {
3307 existing_path.clear();
3308 state.world.army_set_arrival_time(a, sys::date{});
3309 return;
3310 }
3311
3312 auto old_first_prov = existing_path.size() > 0 ? existing_path.at(existing_path.size() - 1) : dcon::province_id{};
3313 if(reset) {
3314 existing_path.clear();
3315 }
3316
3317 auto path = can_move_army(state, source, a, dest);
3318
3319 if(path.size() > 0) {
3320 auto append_size = uint32_t(path.size());
3321 auto old_size = existing_path.size();
3322 auto new_size = old_size + append_size;
3323 existing_path.resize(new_size);
3324
3325 for(uint32_t i = old_size; i-- > 0; ) {
3326 existing_path.at(append_size + i) = existing_path.at(i);
3327 }
3328 for(uint32_t i = 0; i < append_size; ++i) {
3329 existing_path.at(i) = path[i];
3330 }
3331
3332 if(existing_path.at(new_size - 1) != old_first_prov) {
3333 state.world.army_set_arrival_time(a, military::arrival_time_to(state, a, path.back()));
3334 }
3335 state.world.army_set_dig_in(a, 0);
3336 state.world.army_set_is_rebel_hunter(a, false);
3337 } else if(reset) {
3338 state.world.army_set_arrival_time(a, sys::date{});
3339 }
3340 state.world.army_set_moving_to_merge(a, false);
3341
3342 if(battle) {
3343 state.world.army_set_is_retreating(a, true);
3344 state.world.army_set_battle_from_army_battle_participation(a, dcon::land_battle_id{});
3345 for(auto reg : state.world.army_get_army_membership(a)) {
3346 {
3347 auto& line = state.world.land_battle_get_attacker_front_line(battle);
3348 for(auto& lr : line) {
3349 if(lr == reg.get_regiment())
3350 lr = dcon::regiment_id{};
3351 }
3352 }
3353 {
3354 auto& line = state.world.land_battle_get_attacker_back_line(battle);
3355 for(auto& lr : line) {
3356 if(lr == reg.get_regiment())
3357 lr = dcon::regiment_id{};
3358 }
3359 }
3360 {
3361 auto& line = state.world.land_battle_get_defender_front_line(battle);
3362 for(auto& lr : line) {
3363 if(lr == reg.get_regiment())
3364 lr = dcon::regiment_id{};
3365 }
3366 }
3367 {
3368 auto& line = state.world.land_battle_get_defender_back_line(battle);
3369 for(auto& lr : line) {
3370 if(lr == reg.get_regiment())
3371 lr = dcon::regiment_id{};
3372 }
3373 }
3374 auto res = state.world.land_battle_get_reserves(battle);
3375 for(uint32_t i = res.size(); i-- > 0;) {
3376 if(res[i].regiment == reg.get_regiment()) {
3377 res[i] = res[res.size() - 1];
3378 res.pop_back();
3379 }
3380 }
3381 }
3382
3383 //update leaders
3384 military::update_battle_leaders(state, battle);
3385 }
3386}
3387
3388void move_navy(sys::state& state, dcon::nation_id source, dcon::navy_id n, dcon::province_id dest, bool reset) {
3389 payload p;
3390 memset(&p, 0, sizeof(payload));
3392 p.source = source;
3393 p.data.navy_movement.n = n;
3394 p.data.navy_movement.dest = dest;
3395 p.data.navy_movement.reset = reset;
3396 add_to_command_queue(state, p);
3397}
3398std::vector<dcon::province_id> can_move_navy(sys::state& state, dcon::nation_id source, dcon::navy_id n, dcon::province_id dest) {
3399 if(source != state.world.navy_get_controller_from_navy_control(n))
3400 return std::vector<dcon::province_id>{};
3401 if(state.world.navy_get_is_retreating(n))
3402 return std::vector<dcon::province_id>{};
3403 if(!dest)
3404 return std::vector<dcon::province_id>{}; // stop movement
3405
3406 auto last_province = state.world.navy_get_location_from_navy_location(n);
3407 auto movement = state.world.navy_get_path(n);
3408 if(movement.size() > 0) {
3409 last_province = movement.at(0);
3410 }
3411
3412 if(last_province == dest)
3413 return std::vector<dcon::province_id>{};
3414
3415 if(!can_partial_retreat_from(state, state.world.navy_get_battle_from_navy_battle_participation(n)))
3416 return std::vector<dcon::province_id>{};
3417
3418 if(dest.index() >= state.province_definitions.first_sea_province.index()) {
3419 return province::make_naval_path(state, last_province, dest);
3420 } else {
3421 if(!state.world.province_get_is_coast(dest))
3422 return std::vector<dcon::province_id>{};
3423
3424 if(!province::has_naval_access_to_province(state, source, dest))
3425 return std::vector<dcon::province_id>{};
3426
3427 return province::make_naval_path(state, last_province, dest);
3428 }
3429}
3430void execute_move_navy(sys::state& state, dcon::nation_id source, dcon::navy_id n, dcon::province_id dest, bool reset) {
3431 if(source != state.world.navy_get_controller_from_navy_control(n))
3432 return;
3433 if(state.world.navy_get_is_retreating(n))
3434 return;
3435
3436 auto battle = state.world.navy_get_battle_from_navy_battle_participation(n);
3437 if(battle && dest.index() < state.province_definitions.first_sea_province.index() && !province::has_naval_access_to_province(state, source, dest)) {
3438 return;
3439 }
3440
3441 auto existing_path = state.world.navy_get_path(n);
3442
3443 if(!dest) {
3444 existing_path.clear();
3445 state.world.navy_set_arrival_time(n, sys::date{});
3446 return;
3447 }
3448
3449 auto old_first_prov = existing_path.size() > 0 ? existing_path.at(existing_path.size() - 1) : dcon::province_id{};
3450 if(reset) {
3451 existing_path.clear();
3452 }
3453
3454 auto path = can_move_navy(state, source, n, dest);
3455 if(path.size() > 0) {
3456 auto append_size = uint32_t(path.size());
3457 auto old_size = existing_path.size();
3458 auto new_size = old_size + append_size;
3459 existing_path.resize(new_size);
3460
3461 for(uint32_t i = old_size; i-- > 0; ) {
3462 existing_path.at(append_size + i) = existing_path.at(i);
3463 }
3464 for(uint32_t i = 0; i < append_size; ++i) {
3465 existing_path.at(i) = path[i];
3466 }
3467
3468 if(existing_path.at(new_size - 1) != old_first_prov) {
3469 state.world.navy_set_arrival_time(n, military::arrival_time_to(state, n, path.back()));
3470 }
3471 } else if(reset) {
3472 state.world.navy_set_arrival_time(n, sys::date{});
3473 }
3474 state.world.navy_set_moving_to_merge(n, false);
3475
3476 if(battle) {
3477 state.world.navy_set_is_retreating(n, true);
3478 state.world.navy_set_battle_from_navy_battle_participation(n, dcon::naval_battle_id{});
3479 for(auto shp : state.world.navy_get_navy_membership(n)) {
3480 for(auto& s : state.world.naval_battle_get_slots(battle)) {
3481 if(s.ship == shp.get_ship()) {
3482 s.ship = dcon::ship_id{};
3483 s.flags &= ~s.mode_mask;
3484 s.flags |= s.mode_retreated;
3485 }
3486 }
3487 }
3488 //update leaders
3489 military::update_battle_leaders(state, battle);
3490 }
3491}
3492
3493void embark_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3494 payload p;
3495 memset(&p, 0, sizeof(payload));
3497 p.source = source;
3498 p.data.army_movement.a = a;
3499 add_to_command_queue(state, p);
3500}
3501
3502bool can_embark_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3503 if(source != state.world.army_get_controller_from_army_control(a))
3504 return false;
3505 if(state.world.army_get_is_retreating(a))
3506 return false;
3507
3508 auto location = state.world.army_get_location_from_army_location(a);
3509 if(location.index() >= state.province_definitions.first_sea_province.index())
3510 return false;
3511
3512 if(state.world.army_get_battle_from_army_battle_participation(a))
3513 return false;
3514
3515 if(state.world.army_get_navy_from_army_transport(a)) {
3516 return true;
3517 } else {
3518 return military::can_embark_onto_sea_tile(state, source, location, a);
3519 }
3520}
3521
3522void execute_embark_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3523 if(source != state.world.army_get_controller_from_army_control(a))
3524 return;
3525 if(state.world.army_get_is_retreating(a))
3526 return;
3527
3528 if(state.world.army_get_battle_from_army_battle_participation(a))
3529 return;
3530
3531 auto location = state.world.army_get_location_from_army_location(a);
3532 if(location.index() >= state.province_definitions.first_sea_province.index())
3533 return;
3534
3535 if(state.world.army_get_navy_from_army_transport(a)) {
3536 state.world.army_set_navy_from_army_transport(a, dcon::navy_id{});
3538 } else {
3539 auto to_navy = military::find_embark_target(state, source, location, a);
3540 if(to_navy) {
3541 state.world.army_set_navy_from_army_transport(a, to_navy);
3542 state.world.army_set_black_flag(a, false);
3543 }
3544 }
3545 state.world.army_set_is_rebel_hunter(a, false);
3546 state.world.army_set_dig_in(a, 0);
3547}
3548
3549void merge_armies(sys::state& state, dcon::nation_id source, dcon::army_id a, dcon::army_id b) {
3550 payload p;
3551 memset(&p, 0, sizeof(payload));
3553 p.source = source;
3554 p.data.merge_army.a = a;
3555 p.data.merge_army.b = b;
3556 add_to_command_queue(state, p);
3557}
3558bool can_merge_armies(sys::state& state, dcon::nation_id source, dcon::army_id a, dcon::army_id b) {
3559 if(state.world.army_get_controller_from_army_control(a) != source)
3560 return false;
3561 if(state.world.army_get_controller_from_army_control(b) != source)
3562 return false;
3563 if(state.world.army_get_is_retreating(a) || state.world.army_get_is_retreating(b))
3564 return false;
3565 if(state.world.army_get_navy_from_army_transport(a))
3566 return false;
3567 if(state.world.army_get_navy_from_army_transport(b))
3568 return false;
3569
3570 if(state.world.army_get_location_from_army_location(a) != state.world.army_get_location_from_army_location(b))
3571 return false;
3572
3573 if(state.world.army_get_battle_from_army_battle_participation(a) ||
3574 state.world.army_get_battle_from_army_battle_participation(b))
3575 return false;
3576
3577 return true;
3578}
3579
3580void execute_merge_armies(sys::state& state, dcon::nation_id source, dcon::army_id a, dcon::army_id b) {
3581 // take leader
3582 auto a_leader = state.world.army_get_general_from_army_leadership(a);
3583 auto b_leader = state.world.army_get_general_from_army_leadership(b);
3584 if(!a_leader && b_leader) {
3585 state.world.army_set_general_from_army_leadership(a, b_leader);
3586 }
3587
3588 // stop movement
3589 state.world.army_get_path(a).clear();
3590 state.world.army_set_arrival_time(a, sys::date{});
3591
3592 auto regs = state.world.army_get_army_membership(b);
3593 while(regs.begin() != regs.end()) {
3594 auto reg = (*regs.begin()).get_regiment();
3595 reg.set_army_from_army_membership(a);
3596 }
3597
3598 if(source == state.local_player_nation) {
3599 state.deselect(b);
3600 }
3601 military::cleanup_army(state, b);
3602}
3603
3604void merge_navies(sys::state& state, dcon::nation_id source, dcon::navy_id a, dcon::navy_id b) {
3605 payload p;
3606 memset(&p, 0, sizeof(payload));
3608 p.source = source;
3609 p.data.merge_navy.a = a;
3610 p.data.merge_navy.b = b;
3611 add_to_command_queue(state, p);
3612}
3613bool can_merge_navies(sys::state& state, dcon::nation_id source, dcon::navy_id a, dcon::navy_id b) {
3614 if(state.world.navy_get_controller_from_navy_control(a) != source)
3615 return false;
3616 if(state.world.navy_get_controller_from_navy_control(b) != source)
3617 return false;
3618 if(state.world.navy_get_is_retreating(a) || state.world.navy_get_is_retreating(b))
3619 return false;
3620
3621 if(state.world.navy_get_location_from_navy_location(a) != state.world.navy_get_location_from_navy_location(b))
3622 return false;
3623
3624 if(state.world.navy_get_battle_from_navy_battle_participation(a) ||
3625 state.world.navy_get_battle_from_navy_battle_participation(b))
3626 return false;
3627
3628 return true;
3629}
3630void execute_merge_navies(sys::state& state, dcon::nation_id source, dcon::navy_id a, dcon::navy_id b) {
3631 // take leader
3632 auto a_leader = state.world.navy_get_admiral_from_navy_leadership(a);
3633 auto b_leader = state.world.navy_get_admiral_from_navy_leadership(b);
3634 if(!a_leader && b_leader) {
3635 state.world.navy_set_admiral_from_navy_leadership(a, b_leader);
3636 }
3637
3638 // stop movement
3639 state.world.navy_get_path(a).clear();
3640 state.world.navy_set_arrival_time(a, sys::date{});
3641
3642 auto regs = state.world.navy_get_navy_membership(b);
3643 while(regs.begin() != regs.end()) {
3644 auto reg = (*regs.begin()).get_ship();
3645 reg.set_navy_from_navy_membership(a);
3646 }
3647
3648 auto transported = state.world.navy_get_army_transport(b);
3649 while(transported.begin() != transported.end()) {
3650 auto arm = (*transported.begin()).get_army();
3651 arm.set_navy_from_army_transport(a);
3652 }
3653
3654 if(source == state.local_player_nation) {
3655 state.deselect(b);
3656 }
3657 military::cleanup_navy(state, b);
3658}
3659
3660void disband_undermanned_regiments(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3661 payload p;
3662 memset(&p, 0, sizeof(payload));
3664 p.source = source;
3665 p.data.army_movement.a = a;
3666 add_to_command_queue(state, p);
3667}
3668bool can_disband_undermanned_regiments(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3669 return state.world.army_get_controller_from_army_control(a) == source && !state.world.army_get_is_retreating(a) &&
3670 !bool(state.world.army_get_battle_from_army_battle_participation(a));
3671}
3672void execute_disband_undermanned_regiments(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3673 std::vector<dcon::regiment_id> regs;
3674 for(auto r : state.world.army_get_army_membership(a)) {
3675 auto pop = r.get_regiment().get_pop_from_regiment_source();
3676 if(!pop || pop.get_size() < state.defines.pop_min_size_for_regiment)
3677 regs.push_back(r.get_regiment());
3678 }
3679 for(auto r : regs)
3680 state.world.delete_regiment(r);
3681}
3682
3683void toggle_rebel_hunting(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3684 payload p;
3685 memset(&p, 0, sizeof(payload));
3687 p.source = source;
3688 p.data.army_movement.a = a;
3689 add_to_command_queue(state, p);
3690}
3691void execute_toggle_rebel_hunting(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3692 auto owner = state.world.army_get_controller_from_army_control(a);
3693 if(owner != source)
3694 return;
3695
3696 auto current_state = state.world.army_get_is_rebel_hunter(a);
3697 if(current_state) {
3698 state.world.army_set_is_rebel_hunter(a, false);
3699 } else {
3700 auto path = state.world.army_get_path(a);
3701 if(path.size() > 0) {
3702 state.world.army_set_ai_province(a, path.at(0));
3703 } else {
3704 state.world.army_set_ai_province(a, state.world.army_get_location_from_army_location(a));
3705 if(!state.world.army_get_battle_from_army_battle_participation(a)
3706 && !state.world.army_get_navy_from_army_transport(a)) {
3707
3708 military::send_rebel_hunter_to_next_province(state, a, state.world.army_get_location_from_army_location(a));
3709 }
3710 }
3711 state.world.army_set_is_rebel_hunter(a, true);
3712 }
3713}
3714
3715void toggle_unit_ai_control(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3716 payload p;
3717 memset(&p, 0, sizeof(payload));
3719 p.source = source;
3720 p.data.army_movement.a = a;
3721 add_to_command_queue(state, p);
3722}
3723void execute_toggle_unit_ai_control(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3724 auto owner = state.world.army_get_controller_from_army_control(a);
3725 if(owner != source)
3726 return;
3727 auto current_state = state.world.army_get_is_ai_controlled(a);
3728 if(current_state) {
3729 state.world.army_set_ai_activity(a, 0);
3730 state.world.army_set_is_ai_controlled(a, false);
3731 } else {
3732 //turn off rebel control
3733 state.world.army_set_is_rebel_hunter(a, false);
3734 auto path = state.world.army_get_path(a);
3735 if(path.size() > 0) {
3736 state.world.army_set_ai_province(a, path.at(0));
3737 } else {
3738 state.world.army_set_ai_province(a, state.world.army_get_location_from_army_location(a));
3739 if(!state.world.army_get_battle_from_army_battle_participation(a)
3740 && !state.world.army_get_navy_from_army_transport(a)) {
3741
3742 military::send_rebel_hunter_to_next_province(state, a, state.world.army_get_location_from_army_location(a));
3743 }
3744 }
3745 state.world.army_set_ai_activity(a, 0);
3746 state.world.army_set_is_ai_controlled(a, true);
3747 }
3748}
3749
3750void toggle_mobilized_is_ai_controlled(sys::state& state, dcon::nation_id source) {
3751 payload p;
3752 memset(&p, 0, sizeof(payload));
3754 p.source = source;
3755 add_to_command_queue(state, p);
3756}
3757void execute_toggle_mobilized_is_ai_controlled(sys::state& state, dcon::nation_id source) {
3758 state.world.nation_set_mobilized_is_ai_controlled(source, !state.world.nation_get_mobilized_is_ai_controlled(source));
3759}
3760
3761void toggle_select_province(sys::state& state, dcon::nation_id source, dcon::province_id prov) {
3762 payload p;
3763 memset(&p, 0, sizeof(payload));
3765 p.source = source;
3766 p.data.generic_location.prov = prov;
3767 add_to_command_queue(state, p);
3768}
3769bool can_toggle_select_province(sys::state& state, dcon::nation_id source, dcon::province_id prov) {
3770 if(state.world.province_get_nation_from_province_control(prov) != source)
3771 return false;
3772 if(state.world.province_get_nation_from_province_ownership(prov) != source)
3773 return false;
3774 return true;
3775}
3776void execute_toggle_select_province(sys::state& state, dcon::nation_id source, dcon::province_id prov) {
3777 sys::toggle_modifier_from_province(state, prov, state.economy_definitions.selector_modifier, sys::date{});
3778}
3779
3780void toggle_immigrator_province(sys::state& state, dcon::nation_id source, dcon::province_id prov) {
3781 payload p;
3782 memset(&p, 0, sizeof(payload));
3784 p.source = source;
3785 p.data.generic_location.prov = prov;
3786 add_to_command_queue(state, p);
3787}
3788bool can_toggle_immigrator_province(sys::state& state, dcon::nation_id source, dcon::province_id prov) {
3789 if(state.world.province_get_nation_from_province_control(prov) != source)
3790 return false;
3791 if(state.world.province_get_nation_from_province_ownership(prov) != source)
3792 return false;
3793 return true;
3794}
3795void execute_toggle_immigrator_province(sys::state& state, dcon::nation_id source, dcon::province_id prov) {
3796 sys::toggle_modifier_from_province(state, prov, state.economy_definitions.immigrator_modifier, sys::date{});
3797}
3798
3799void release_subject(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
3800 payload p;
3801 memset(&p, 0, sizeof(payload));
3803 p.source = source;
3804 p.data.diplo_action.target = target;
3805 add_to_command_queue(state, p);
3806}
3807bool can_release_subject(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
3808 return state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(target)) == source;
3809}
3810void execute_release_subject(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
3811 if(!can_release_subject(state, source, target))
3812 return;
3813 nations::release_vassal(state, state.world.nation_get_overlord_as_subject(target));
3814}
3815
3817 payload p;
3818 memset(&p, 0, sizeof(payload));
3820 p.source = state.local_player_nation;
3821 add_to_command_queue(state, p);
3822}
3823
3825 std::string command;
3826 {
3827 std::lock_guard lg{ state.lock_console_strings };
3828 command = state.console_command_pending;
3829 state.console_command_pending.clear();
3830 }
3831 if(command.length() > 0) {
3834 fif::run_fif_interpreter(*state.fif_environment, command, stack);
3835 if(state.fif_environment->mode == fif::fif_mode::error) {
3836 state.fif_environment->mode = fif::fif_mode::interpreting;
3837 std::lock_guard lg{ state.lock_console_strings };
3838 state.console_command_result += state.console_command_error;
3839 state.console_command_error.clear();
3840 } else {
3841 std::string temp_result;
3842 for(uint32_t i = 0; i < stack.main_size(); ++i) {
3843 temp_result += ui::format_fif_value(state, stack.main_data(i), stack.main_type(i));
3844 temp_result += " ";
3845 }
3846 if(stack.main_size() > 0) {
3847 state.fif_environment->source_stack.push_back("drop");
3848 state.fif_environment->compiler_stack.emplace_back(std::make_unique<fif::outer_interpreter>(*state.fif_environment));
3849 fif::outer_interpreter* o = static_cast<fif::outer_interpreter*>(state.fif_environment->compiler_stack.back().get());
3850 static_cast<fif::interpreter_stack*>(o->interpreter_state.get())->move_into(std::move(stack));
3851
3852 switch_compiler_stack_mode(*state.fif_environment, fif::fif_mode::interpreting);
3853 fif::mode_switch_scope* m = static_cast<fif::mode_switch_scope*>(state.fif_environment->compiler_stack.back().get());
3854 m->interpreted_link = o;
3855
3856 while(o->interpreter_state->main_size() > 0) {
3857 fif::execute_fif_word(fif::parse_result{ "drop", false }, *state.fif_environment, false);
3858 }
3859
3860 state.fif_environment->source_stack.pop_back();
3861 restore_compiler_stack_mode(*state.fif_environment);
3862
3863 state.fif_environment->compiler_stack.pop_back();
3864 }
3865 temp_result += "?Gok.?W\\n";
3866 {
3867 std::lock_guard lg{ state.lock_console_strings };
3868 state.console_command_result += temp_result;
3869 }
3870 state.fif_environment->mode = fif::fif_mode::interpreting;
3871 }
3872 }
3873}
3874
3875void evenly_split_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3876 payload p;
3877 memset(&p, 0, sizeof(payload));
3879 p.source = source;
3880 p.data.army_movement.a = a;
3881 add_to_command_queue(state, p);
3882}
3883bool can_evenly_split_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3884 return can_split_army(state, source, a);
3885}
3886void execute_evenly_split_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3887 bool inf_split = false;
3888 bool cav_split = false;
3889 bool art_split = false;
3890
3891 static std::vector<dcon::regiment_id> to_transfer;
3892 to_transfer.clear();
3893
3894 for(auto t : state.world.army_get_army_membership(a)) {
3895 auto type = state.military_definitions.unit_base_definitions[t.get_regiment().get_type()].type;
3896 if(type == military::unit_type::infantry) {
3897 if(inf_split) {
3898 to_transfer.push_back(t.get_regiment());
3899 }
3900 inf_split = !inf_split;
3901 } else if(type == military::unit_type::cavalry) {
3902 if(cav_split) {
3903 to_transfer.push_back(t.get_regiment());
3904 }
3905 cav_split = !cav_split;
3906 } else if(type == military::unit_type::support || type == military::unit_type::special) {
3907 if(art_split) {
3908 to_transfer.push_back(t.get_regiment());
3909 }
3910 art_split = !art_split;
3911 }
3912 }
3913
3914 if(to_transfer.size() > 0) {
3915 auto new_u = fatten(state.world, state.world.create_army());
3916 new_u.set_controller_from_army_control(source);
3917 new_u.set_location_from_army_location(state.world.army_get_location_from_army_location(a));
3918 new_u.set_black_flag(state.world.army_get_black_flag(a));
3919
3920 for(auto t : to_transfer) {
3921 state.world.regiment_set_army_from_army_membership(t, new_u);
3922 }
3923
3924 if(source == state.local_player_nation && state.is_selected(a)) {
3925 state.deselect(a);
3926 state.select(new_u);
3927 }
3928 }
3929}
3930
3931void evenly_split_navy(sys::state& state, dcon::nation_id source, dcon::navy_id a) {
3932 payload p;
3933 memset(&p, 0, sizeof(payload));
3935 p.source = source;
3936 p.data.navy_movement.n = a;
3937 add_to_command_queue(state, p);
3938}
3939bool can_evenly_split_navy(sys::state& state, dcon::nation_id source, dcon::navy_id a) {
3940 return can_split_navy(state, source, a);
3941}
3942void execute_evenly_split_navy(sys::state& state, dcon::nation_id source, dcon::navy_id a) {
3943 static std::vector<dcon::ship_id> to_transfer;
3944 to_transfer.clear();
3945
3946 bool big_split = false;
3947 bool sm_split = false;
3948 bool tra_split = false;
3949
3950 for(auto t : state.world.navy_get_navy_membership(a)) {
3951 auto type = state.military_definitions.unit_base_definitions[t.get_ship().get_type()].type;
3952 if(type == military::unit_type::big_ship) {
3953 if(big_split) {
3954 to_transfer.push_back(t.get_ship());
3955 }
3956 big_split = !big_split;
3957 } else if(type == military::unit_type::light_ship) {
3958 if(sm_split) {
3959 to_transfer.push_back(t.get_ship());
3960 }
3961 sm_split = !sm_split;
3962 } else if(type == military::unit_type::transport) {
3963 if(tra_split) {
3964 to_transfer.push_back(t.get_ship());
3965 }
3966 tra_split = !tra_split;
3967 }
3968 }
3969
3970 if(to_transfer.size() > 0) {
3971 auto new_u = fatten(state.world, state.world.create_navy());
3972 new_u.set_controller_from_navy_control(source);
3973 new_u.set_location_from_navy_location(state.world.navy_get_location_from_navy_location(a));
3974
3975 for(auto t : to_transfer) {
3976 state.world.ship_set_navy_from_navy_membership(t, new_u);
3977 }
3978
3979 if(source == state.local_player_nation && state.is_selected(a)) {
3980 state.deselect(a);
3981 state.select(new_u);
3982 }
3983 }
3984}
3985
3986void split_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3987 payload p;
3988 memset(&p, 0, sizeof(payload));
3990 p.source = source;
3991 p.data.army_movement.a = a;
3992 add_to_command_queue(state, p);
3993}
3994bool can_split_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3995 return state.world.army_get_controller_from_army_control(a) == source && !state.world.army_get_is_retreating(a) && !state.world.army_get_navy_from_army_transport(a) &&
3996 !bool(state.world.army_get_battle_from_army_battle_participation(a));
3997}
3998void execute_split_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
3999 static std::vector<dcon::regiment_id> to_transfer;
4000 to_transfer.clear();
4001
4002 for(auto t : state.world.army_get_army_membership(a)) {
4003 if(t.get_regiment().get_pending_split()) {
4004 t.get_regiment().set_pending_split(false);
4005 to_transfer.push_back(t.get_regiment().id);
4006 }
4007 }
4008
4009 if(to_transfer.size() > 0) {
4010 auto new_u = fatten(state.world, state.world.create_army());
4011 new_u.set_controller_from_army_control(source);
4012 new_u.set_location_from_army_location(state.world.army_get_location_from_army_location(a));
4013 new_u.set_black_flag(state.world.army_get_black_flag(a));
4014
4015 for(auto t : to_transfer) {
4016 state.world.regiment_set_army_from_army_membership(t, new_u);
4017 }
4018
4019 if(source == state.local_player_nation && state.is_selected(a))
4020 state.select(new_u);
4021
4022 auto old_regs = state.world.army_get_army_membership(a);
4023 if(old_regs.begin() == old_regs.end()) {
4024 state.world.leader_set_army_from_army_leadership(state.world.army_get_general_from_army_leadership(a), new_u);
4025
4026 if(source == state.local_player_nation) {
4027 state.deselect(a);
4028 }
4029 military::cleanup_army(state, a);
4030 }
4031 }
4032}
4033
4034void split_navy(sys::state& state, dcon::nation_id source, dcon::navy_id a) {
4035 payload p;
4036 memset(&p, 0, sizeof(payload));
4038 p.source = source;
4039 p.data.navy_movement.n = a;
4040 add_to_command_queue(state, p);
4041}
4042bool can_split_navy(sys::state& state, dcon::nation_id source, dcon::navy_id a) {
4043 auto embarked = state.world.navy_get_army_transport(a);
4044 return state.world.navy_get_controller_from_navy_control(a) == source && !state.world.navy_get_is_retreating(a) &&
4045 !bool(state.world.navy_get_battle_from_navy_battle_participation(a)) && embarked.begin() == embarked.end();
4046}
4047void execute_split_navy(sys::state& state, dcon::nation_id source, dcon::navy_id a) {
4048 static std::vector<dcon::ship_id> to_transfer;
4049 to_transfer.clear();
4050
4051 for(auto t : state.world.navy_get_navy_membership(a)) {
4052 if(t.get_ship().get_pending_split()) {
4053 t.get_ship().set_pending_split(false);
4054 to_transfer.push_back(t.get_ship().id);
4055 }
4056 }
4057
4058 if(to_transfer.size() > 0) {
4059 auto new_u = fatten(state.world, state.world.create_navy());
4060 new_u.set_controller_from_navy_control(source);
4061 new_u.set_location_from_navy_location(state.world.navy_get_location_from_navy_location(a));
4062
4063 for(auto t : to_transfer) {
4064 state.world.ship_set_navy_from_navy_membership(t, new_u);
4065 }
4066
4067 if(source == state.local_player_nation && state.is_selected(a))
4068 state.select(new_u);
4069
4070 auto old_regs = state.world.navy_get_navy_membership(a);
4071 if(old_regs.begin() == old_regs.end()) {
4072 state.world.leader_set_navy_from_navy_leadership(state.world.navy_get_admiral_from_navy_leadership(a), new_u);
4073 if(source == state.local_player_nation) {
4074 state.deselect(a);
4075 }
4076 military::cleanup_navy(state, a);
4077 }
4078 }
4079}
4080
4081void delete_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
4082 payload p;
4083 memset(&p, 0, sizeof(payload));
4085 p.source = source;
4086 p.data.army_movement.a = a;
4087 add_to_command_queue(state, p);
4088}
4089bool can_delete_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
4090 return state.world.army_get_controller_from_army_control(a) == source && !state.world.army_get_is_retreating(a) &&
4091 !bool(state.world.army_get_battle_from_army_battle_participation(a)) &&
4092 province::has_naval_access_to_province(state, source, state.world.army_get_location_from_army_location(a));
4093}
4094void execute_delete_army(sys::state& state, dcon::nation_id source, dcon::army_id a) {
4095 if(source == state.local_player_nation) {
4096 state.deselect(a);
4097 }
4098 military::cleanup_army(state, a);
4099}
4100
4101void delete_navy(sys::state& state, dcon::nation_id source, dcon::navy_id a) {
4102 payload p;
4103 memset(&p, 0, sizeof(payload));
4105 p.source = source;
4106 p.data.navy_movement.n = a;
4107 add_to_command_queue(state, p);
4108}
4109
4110bool can_delete_navy(sys::state& state, dcon::nation_id source, dcon::navy_id a) {
4111 auto embarked = state.world.navy_get_army_transport(a);
4112 return state.world.navy_get_controller_from_navy_control(a) == source && !state.world.navy_get_is_retreating(a) &&
4113 embarked.begin() == embarked.end() && !bool(state.world.navy_get_battle_from_navy_battle_participation(a)) &&
4114 province::has_naval_access_to_province(state, source, state.world.navy_get_location_from_navy_location(a));
4115}
4116void execute_delete_navy(sys::state& state, dcon::nation_id source, dcon::navy_id a) {
4117 if(source == state.local_player_nation) {
4118 state.deselect(a);
4119 }
4120 military::cleanup_navy(state, a);
4121}
4122
4123void change_general(sys::state& state, dcon::nation_id source, dcon::army_id a, dcon::leader_id l) {
4124 payload p;
4125 memset(&p, 0, sizeof(payload));
4127 p.source = source;
4128 p.data.new_general.a = a;
4129 p.data.new_general.l = l;
4130 add_to_command_queue(state, p);
4131}
4132bool can_change_general(sys::state& state, dcon::nation_id source, dcon::army_id a, dcon::leader_id l) {
4133 return state.world.army_get_controller_from_army_control(a) == source && !state.world.army_get_is_retreating(a) &&
4134 !bool(state.world.army_get_battle_from_army_battle_participation(a)) &&
4135 province::has_naval_access_to_province(state, source, state.world.army_get_location_from_army_location(a)) &&
4136 (!l || state.world.leader_get_nation_from_leader_loyalty(l) == source);
4137}
4138void execute_change_general(sys::state& state, dcon::nation_id source, dcon::army_id a, dcon::leader_id l) {
4139 state.world.army_set_general_from_army_leadership(a, l);
4140}
4141
4142void change_admiral(sys::state& state, dcon::nation_id source, dcon::navy_id a, dcon::leader_id l) {
4143 payload p;
4144 memset(&p, 0, sizeof(payload));
4146 p.source = source;
4147 p.data.new_admiral.a = a;
4148 p.data.new_admiral.l = l;
4149 add_to_command_queue(state, p);
4150}
4151bool can_change_admiral(sys::state& state, dcon::nation_id source, dcon::navy_id a, dcon::leader_id l) {
4152 return state.world.navy_get_controller_from_navy_control(a) == source && !state.world.navy_get_is_retreating(a) &&
4153 !bool(state.world.navy_get_battle_from_navy_battle_participation(a)) &&
4154 province::has_naval_access_to_province(state, source, state.world.navy_get_location_from_navy_location(a)) &&
4155 (!l || state.world.leader_get_nation_from_leader_loyalty(l) == source);
4156}
4157void execute_change_admiral(sys::state& state, dcon::nation_id source, dcon::navy_id a, dcon::leader_id l) {
4158 state.world.navy_set_admiral_from_navy_leadership(a, l);
4159}
4160
4161void mark_regiments_to_split(sys::state& state, dcon::nation_id source,
4162 std::array<dcon::regiment_id, num_packed_units> const& list) {
4163
4164 payload p;
4165 memset(&p, 0, sizeof(payload));
4167 p.source = source;
4168 std::copy_n(list.data(), num_packed_units, p.data.split_regiments.regs);
4169 add_to_command_queue(state, p);
4170}
4171void execute_mark_regiments_to_split(sys::state& state, dcon::nation_id source, dcon::regiment_id const* regs) {
4172 for(uint32_t i = 0; i < num_packed_units; ++i) {
4173 if(regs[i]) {
4174 if(source ==
4175 state.world.army_get_controller_from_army_control(state.world.regiment_get_army_from_army_membership(regs[i]))) {
4176 state.world.regiment_set_pending_split(regs[i], !state.world.regiment_get_pending_split(regs[i]));
4177 }
4178 }
4179 }
4180}
4181
4182void mark_ships_to_split(sys::state& state, dcon::nation_id source, std::array<dcon::ship_id, num_packed_units> const& list) {
4183 payload p;
4184 memset(&p, 0, sizeof(payload));
4186 p.source = source;
4187 std::copy_n(list.data(), num_packed_units, p.data.split_ships.ships);
4188 add_to_command_queue(state, p);
4189
4190}
4191void execute_mark_ships_to_split(sys::state& state, dcon::nation_id source, dcon::ship_id const* regs) {
4192 for(uint32_t i = 0; i < num_packed_units; ++i) {
4193 if(regs[i]) {
4194 if(source == state.world.navy_get_controller_from_navy_control(state.world.ship_get_navy_from_navy_membership(regs[i]))) {
4195 state.world.ship_set_pending_split(regs[i], !state.world.ship_get_pending_split(regs[i]));
4196 }
4197 }
4198 }
4199}
4200
4201void retreat_from_naval_battle(sys::state& state, dcon::nation_id source, dcon::naval_battle_id b) {
4202 payload p;
4203 memset(&p, 0, sizeof(payload));
4205 p.source = source;
4206 p.data.naval_battle.b = b;
4207 add_to_command_queue(state, p);
4208}
4209bool can_retreat_from_naval_battle(sys::state& state, dcon::nation_id source, dcon::naval_battle_id b) {
4211 return false;
4212 if(source != military::get_naval_battle_lead_attacker(state, b) && source != military::get_naval_battle_lead_defender(state, b))
4213 return false;
4214
4215 return true;
4216}
4217void execute_retreat_from_naval_battle(sys::state& state, dcon::nation_id source, dcon::naval_battle_id b) {
4219 return;
4220
4221 if(source == military::get_naval_battle_lead_attacker(state, b)) {
4223 } else if(source == military::get_naval_battle_lead_defender(state, b)) {
4225 }
4226}
4227
4228void retreat_from_land_battle(sys::state& state, dcon::nation_id source, dcon::land_battle_id b) {
4229 payload p;
4230 memset(&p, 0, sizeof(payload));
4232 p.source = source;
4233 p.data.land_battle.b = b;
4234 add_to_command_queue(state, p);
4235}
4236
4237bool can_retreat_from_land_battle(sys::state& state, dcon::nation_id source, dcon::land_battle_id b) {
4239 return false;
4240 if(source != military::get_land_battle_lead_attacker(state, b) && source != military::get_land_battle_lead_defender(state, b))
4241 return false;
4242
4243 return true;
4244}
4245void execute_retreat_from_land_battle(sys::state& state, dcon::nation_id source, dcon::land_battle_id b) {
4247 return;
4248
4249 if(source == military::get_land_battle_lead_attacker(state, b)) {
4251 } else if(source == military::get_land_battle_lead_defender(state, b)) {
4253 }
4254}
4255
4256void invite_to_crisis(sys::state& state, dcon::nation_id source, dcon::nation_id invitation_to, dcon::nation_id target,
4257 dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag,
4258 dcon::nation_id cb_secondary_nation) {
4259 payload p;
4260 memset(&p, 0, sizeof(payload));
4262 p.source = source;
4263 p.data.crisis_invitation.invited = invitation_to;
4264 p.data.crisis_invitation.target = target;
4265 p.data.crisis_invitation.cb_type = primary_cb;
4266 p.data.crisis_invitation.cb_state = cb_state;
4267 p.data.crisis_invitation.cb_tag = cb_tag;
4268 p.data.crisis_invitation.cb_secondary_nation = cb_secondary_nation;
4269 add_to_command_queue(state, p);
4270}
4271bool can_invite_to_crisis(sys::state& state, dcon::nation_id source, dcon::nation_id invitation_to, dcon::nation_id target,
4272 dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag,
4273 dcon::nation_id cb_secondary_nation) {
4274
4275 if(state.world.nation_get_is_player_controlled(source) && state.world.nation_get_diplomatic_points(source) < 1.0f)
4276 return false;
4277
4278 if(state.current_crisis_mode != sys::crisis_mode::heating_up)
4279 return false;
4280 if(source != state.primary_crisis_attacker && source != state.primary_crisis_defender)
4281 return false;
4282
4283 if(invitation_to == target || source == target)
4284 return false;
4285
4286 // to must be merely interested participant
4287 for(auto& par : state.crisis_participants) {
4288 if(!par.id) {
4289 return false; // not in crisis
4290 }
4291 if(par.id == invitation_to) {
4292 if(par.merely_interested == false)
4293 return false; // already in crisis
4294 break;
4295 }
4296 }
4297
4298 // target must be in crisis
4299 for(auto& par : state.crisis_participants) {
4300 if(!par.id) {
4301 return false; // not in crisis
4302 }
4303 if(par.id == target) {
4304 if(par.merely_interested)
4305 return false;
4306 if(par.supports_attacker && source == state.primary_crisis_attacker)
4307 return false;
4308 if(!par.supports_attacker && source == state.primary_crisis_defender)
4309 return false;
4310
4311 break;
4312 }
4313 }
4314
4315 auto cb_type = state.world.cb_type_get_type_bits(primary_cb);
4316 if((cb_type & military::cb_flag::always) == 0 && (cb_type & military::cb_flag::is_not_constructing_cb) != 0)
4317 return false;
4318
4319 if(!military::cb_instance_conditions_satisfied(state, invitation_to, target, primary_cb, cb_state, cb_tag, cb_secondary_nation)) {
4320 return false;
4321 }
4322
4323 return true;
4324}
4325void execute_invite_to_crisis(sys::state& state, dcon::nation_id source, crisis_invitation_data const& data) {
4326 if(state.world.nation_get_is_player_controlled(source) && state.world.nation_get_diplomatic_points(source) < 1.0f)
4327 return;
4328
4329 state.world.nation_get_diplomatic_points(source) -= 1.0f;
4330
4332 memset(&m, 0, sizeof(diplomatic_message::message));
4333 m.to = data.invited;
4334 m.from = source;
4335 m.data.crisis_offer.target = data.target;
4336 m.data.crisis_offer.wargoal_secondary_nation = data.cb_secondary_nation;
4337 m.data.crisis_offer.wargoal_state = data.cb_state;
4338 m.data.crisis_offer.wargoal_tag = data.cb_tag;
4339 m.data.crisis_offer.wargoal_type = data.cb_type;
4340
4342
4343 diplomatic_message::post(state, m);
4344}
4345
4346void toggle_mobilization(sys::state& state, dcon::nation_id source) {
4347 payload p;
4348 memset(&p, 0, sizeof(payload));
4350 p.source = source;
4351 add_to_command_queue(state, p);
4352}
4353
4354void execute_toggle_mobilization(sys::state& state, dcon::nation_id source) {
4355 if(state.world.nation_get_is_mobilized(source)) {
4356 military::end_mobilization(state, source);
4357 } else {
4358 military::start_mobilization(state, source);
4359 }
4360}
4361
4362void enable_debt(sys::state& state, dcon::nation_id source, bool debt_is_enabled) {
4363 payload p;
4364 memset(&p, 0, sizeof(payload));
4366 p.source = source;
4367 p.data.make_leader.is_general = debt_is_enabled;
4368 add_to_command_queue(state, p);
4369}
4370
4371void execute_enable_debt(sys::state& state, dcon::nation_id source, bool debt_is_enabled) {
4372 state.world.nation_set_is_debt_spending(source, debt_is_enabled);
4373}
4374
4375void move_capital(sys::state& state, dcon::nation_id source, dcon::province_id prov) {
4376 payload p;
4377 memset(&p, 0, sizeof(payload));
4379 p.source = source;
4380 p.data.generic_location.prov = prov;
4381 add_to_command_queue(state, p);
4382}
4383
4384bool can_move_capital(sys::state& state, dcon::nation_id source, dcon::province_id p) {
4385 if(state.current_crisis != sys::crisis_type::none)
4386 return false;
4387 if(state.world.nation_get_is_at_war(source))
4388 return false;
4389 if(state.world.nation_get_capital(source) == p)
4390 return false;
4391 if(state.world.province_get_is_colonial(p))
4392 return false;
4393 if(state.world.province_get_continent(state.world.nation_get_capital(source)) != state.world.province_get_continent(p))
4394 return false;
4395 if(nations::nation_accepts_culture(state, source, state.world.province_get_dominant_culture(p)) == false)
4396 return false;
4397 if(state.world.province_get_siege_progress(p) > 0.f)
4398 return false;
4399 if(state.world.province_get_siege_progress(state.world.nation_get_capital(source)) > 0.f)
4400 return false;
4401 if(state.world.province_get_nation_from_province_ownership(p) != source)
4402 return false;
4403 if(state.world.province_get_nation_from_province_control(p) != source)
4404 return false;
4405 if(state.world.province_get_is_owner_core(p) == false)
4406 return false;
4407 return true;
4408}
4409
4410void execute_move_capital(sys::state& state, dcon::nation_id source, dcon::province_id p) {
4411 state.world.nation_set_capital(source, p);
4412}
4413
4414void use_province_button(sys::state& state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id i) {
4415 payload p;
4416 memset(&p, 0, sizeof(payload));
4418 p.source = source;
4419 p.data.pbutton.button = d;
4420 p.data.pbutton.id = i;
4421 add_to_command_queue(state, p);
4422}
4423bool can_use_province_button(sys::state& state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id p) {
4424 auto& def = state.ui_defs.gui[d];
4425 if(def.get_element_type() != ui::element_type::button)
4426 return false;
4427 if(def.data.button.get_button_scripting() != ui::button_scripting::province)
4428 return false;
4429 if(!def.data.button.scriptable_enable)
4430 return true;
4431 return trigger::evaluate(state, def.data.button.scriptable_enable, trigger::to_generic(p), trigger::to_generic(p), trigger::to_generic(source));
4432}
4433void execute_use_province_button(sys::state& state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id p) {
4434 auto & def = state.ui_defs.gui[d];
4435 if(def.data.button.scriptable_effect)
4436 effect::execute(state, def.data.button.scriptable_effect, trigger::to_generic(p), trigger::to_generic(p), trigger::to_generic(source), uint32_t(state.current_date.value), uint32_t(p.index() ^ (d.index() << 4)));
4437}
4438
4439void use_nation_button(sys::state& state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n) {
4440 payload p;
4441 memset(&p, 0, sizeof(payload));
4443 p.source = source;
4444 p.data.nbutton.button = d;
4445 p.data.nbutton.id = n;
4446 add_to_command_queue(state, p);
4447}
4448bool can_use_nation_button(sys::state& state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n) {
4449 auto& def = state.ui_defs.gui[d];
4450 if(def.get_element_type() != ui::element_type::button)
4451 return false;
4452 if(def.data.button.get_button_scripting() != ui::button_scripting::nation)
4453 return false;
4454 if(!def.data.button.scriptable_enable)
4455 return true;
4456 return trigger::evaluate(state, def.data.button.scriptable_enable, trigger::to_generic(n), trigger::to_generic(n), trigger::to_generic(source));
4457}
4458void execute_use_nation_button(sys::state& state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n) {
4459 auto& def = state.ui_defs.gui[d];
4460 if(def.data.button.scriptable_effect)
4461 effect::execute(state, def.data.button.scriptable_effect, trigger::to_generic(n), trigger::to_generic(n), trigger::to_generic(source), uint32_t(state.current_date.value), uint32_t(n.index() ^ (d.index() << 4)));
4462}
4463
4464static void post_chat_message(sys::state& state, ui::chat_message& m) {
4465 // Private message
4466 bool can_see = true;
4467 if(bool(m.target)) {
4468 can_see = state.local_player_nation == m.source || state.local_player_nation == m.target;
4469 }
4470 if(can_see) {
4471 state.ui_state.chat_messages[state.ui_state.chat_messages_index++] = m;
4472 if(state.ui_state.chat_messages_index >= state.ui_state.chat_messages.size())
4473 state.ui_state.chat_messages_index = 0;
4475 [m](sys::state& state, text::layout_base& contents) {
4476 text::add_line(state, contents, "msg_chat_message_1", text::variable_type::x, m.source);
4477 text::add_line(state, contents, "msg_chat_message_2", text::variable_type::x, m.body);
4478 },
4479 "msg_chat_message_title",
4480 m.source, dcon::nation_id{}, dcon::nation_id{},
4482 });
4483 }
4484}
4485
4486void chat_message(sys::state& state, dcon::nation_id source, std::string_view body, dcon::nation_id target) {
4487 payload p;
4488 memset(&p, 0, sizeof(payload));
4490 p.source = source;
4491 p.data.chat_message.target = target;
4492 memcpy(p.data.chat_message.body, std::string(body).c_str(), std::min<size_t>(body.length() + 1, size_t(ui::max_chat_message_len)));
4494 add_to_command_queue(state, p);
4495}
4496bool can_chat_message(sys::state& state, dcon::nation_id source, std::string_view body, dcon::nation_id target) {
4497 // TODO: bans, kicks, mutes?
4498 return true;
4499}
4500void execute_chat_message(sys::state& state, dcon::nation_id source, std::string_view body, dcon::nation_id target) {
4501 ui::chat_message m{};
4502 m.source = source;
4503 m.target = target;
4504 m.body = std::string(body);
4505 post_chat_message(state, m);
4506}
4507
4508void notify_player_joins(sys::state& state, dcon::nation_id source, sys::player_name& name) {
4509 payload p;
4510 memset(&p, 0, sizeof(payload));
4512 p.source = source;
4513 p.data.player_name = name;
4514 add_to_command_queue(state, p);
4515}
4516bool can_notify_player_joins(sys::state& state, dcon::nation_id source, sys::player_name& name) {
4517 // TODO: bans, kicks, mutes?
4518 return true;
4519}
4520void execute_notify_player_joins(sys::state& state, dcon::nation_id source, sys::player_name& name) {
4521 state.world.nation_set_is_player_controlled(source, true);
4522 state.network_state.map_of_player_names.insert_or_assign(source.index(), name);
4523
4524 ui::chat_message m{};
4525 m.source = source;
4528 m.body = text::resolve_string_substitution(state, "chat_player_joins", sub);
4529 post_chat_message(state, m);
4530
4531 /* Hotjoin */
4532 if(state.current_scene.game_in_progress)
4533 ai::remove_ai_data(state, source);
4534}
4535
4536void notify_player_leaves(sys::state& state, dcon::nation_id source, bool make_ai) {
4537 payload p;
4538 memset(&p, 0, sizeof(payload));
4540 p.source = source;
4541 p.data.notify_leave.make_ai = make_ai;
4542 add_to_command_queue(state, p);
4543}
4544bool can_notify_player_leaves(sys::state& state, dcon::nation_id source, bool make_ai) {
4545 return state.world.nation_get_is_player_controlled(source);
4546}
4547void execute_notify_player_leaves(sys::state& state, dcon::nation_id source, bool make_ai) {
4548 if(make_ai) {
4549 state.world.nation_set_is_player_controlled(source, false);
4550 }
4551
4552 ui::chat_message m{};
4553 m.source = source;
4555 text::add_to_substitution_map(sub, text::variable_type::playername, state.network_state.map_of_player_names[source.index()].to_string_view());
4556 m.body = text::resolve_string_substitution(state, "chat_player_leaves", sub);
4557 post_chat_message(state, m);
4558}
4559
4560void notify_player_ban(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
4561 payload p;
4562 memset(&p, 0, sizeof(payload));
4564 p.source = source;
4565 p.data.nation_pick.target = target;
4566 add_to_command_queue(state, p);
4567}
4568bool can_notify_player_ban(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
4569 if(source == target) // can't perform on self
4570 return false;
4571 return true;
4572}
4573void execute_notify_player_ban(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
4574 if(state.network_mode == sys::network_mode_type::host) {
4575 for(auto& client : state.network_state.clients) {
4576 if(client.is_active() && client.playing_as == target) {
4577 network::ban_player(state, client);
4578 }
4579 }
4580 }
4581 state.world.nation_set_is_player_controlled(target, false);
4582
4583 ui::chat_message m{};
4584 m.source = source;
4586 text::add_to_substitution_map(sub, text::variable_type::playername, state.network_state.map_of_player_names[target.index()].to_string_view());
4587 m.body = text::resolve_string_substitution(state, "chat_player_ban", sub);
4588 post_chat_message(state, m);
4589}
4590
4591void notify_player_kick(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
4592 payload p;
4593 memset(&p, 0, sizeof(payload));
4595 p.source = source;
4596 p.data.nation_pick.target = target;
4597 add_to_command_queue(state, p);
4598}
4599bool can_notify_player_kick(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
4600 if(source == target) // can't perform on self
4601 return false;
4602 return true;
4603}
4604void execute_notify_player_kick(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
4605 if(state.network_mode == sys::network_mode_type::host) {
4606 for(auto& client : state.network_state.clients) {
4607 if(client.is_active() && client.playing_as == target) {
4608 network::kick_player(state, client);
4609 }
4610 }
4611 }
4612 state.world.nation_set_is_player_controlled(target, false);
4613
4614 ui::chat_message m{};
4615 m.source = source;
4617 text::add_to_substitution_map(sub, text::variable_type::playername, state.network_state.map_of_player_names[target.index()].to_string_view());
4618 m.body = text::resolve_string_substitution(state, "chat_player_kick", sub);
4619 post_chat_message(state, m);
4620}
4621
4622void notify_player_picks_nation(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
4623 payload p;
4624 memset(&p, 0, sizeof(payload));
4626 p.source = source;
4627 p.data.nation_pick.target = target;
4628 add_to_command_queue(state, p);
4629}
4630bool can_notify_player_picks_nation(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
4631 if(source == target) //redundant
4632 return false;
4633 if(!bool(target) || target == state.world.national_identity_get_nation_from_identity_holder(state.national_definitions.rebel_id)) //Invalid OR rebel nation
4634 return false;
4635 // TODO: Support Co-op (one day)
4636 return state.world.nation_get_is_player_controlled(target) == false;
4637}
4638void execute_notify_player_picks_nation(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
4639 assert(source && source != state.world.national_identity_get_nation_from_identity_holder(state.national_definitions.rebel_id));
4640 network::switch_player(state, target, source);
4641 state.world.nation_set_is_player_controlled(source, false);
4642 state.world.nation_set_is_player_controlled(target, true);
4643
4644 if(state.local_player_nation == source) {
4645 state.local_player_nation = target;
4646 }
4647 // We will also re-assign all chat messages from this nation to the new one
4648 for(auto& msg : state.ui_state.chat_messages)
4649 if(bool(msg.source) && msg.source == source)
4650 msg.source = target;
4651}
4652
4653void notify_player_oos(sys::state& state, dcon::nation_id source) {
4654 payload p;
4655 memset(&p, 0, sizeof(payload));
4657 p.source = source;
4658 add_to_command_queue(state, p);
4659}
4660void execute_notify_player_oos(sys::state& state, dcon::nation_id source) {
4661 state.actual_game_speed = 0; //pause host immediately
4662 state.debug_save_oos_dump();
4663
4664 ui::chat_message m{};
4665 m.source = source;
4667 text::add_to_substitution_map(sub, text::variable_type::playername, state.network_state.map_of_player_names[source.index()].to_string_view());
4668 m.body = text::resolve_string_substitution(state, "chat_player_oos", sub);
4669 post_chat_message(state, m);
4670}
4671
4672void advance_tick(sys::state& state, dcon::nation_id source) {
4673 payload p;
4674 memset(&p, 0, sizeof(payload));
4676 p.source = source;
4677 // Postponed until it is sent!
4678 //p.data.advance_tick.checksum = state.get_save_checksum();
4679 p.data.advance_tick.speed = state.actual_game_speed.load(std::memory_order::acquire);
4680 add_to_command_queue(state, p);
4681}
4682
4683void execute_advance_tick(sys::state& state, dcon::nation_id source, sys::checksum_key& k, int32_t speed) {
4684 if(state.network_mode == sys::network_mode_type::client) {
4685 if(!state.network_state.out_of_sync) {
4686 if(state.current_date.to_ymd(state.start_date).day == 1 || state.cheat_data.daily_oos_check) {
4687 sys::checksum_key current = state.get_save_checksum();
4688 if(!current.is_equal(k)) {
4689 state.network_state.out_of_sync = true;
4690 state.debug_save_oos_dump();
4691 }
4692 }
4693 }
4694 state.actual_game_speed = speed;
4695 }
4696 state.single_game_tick();
4697}
4698
4699void notify_save_loaded(sys::state& state, dcon::nation_id source) {
4700 payload p;
4701 memset(&p, 0, sizeof(payload));
4703 p.source = source;
4704 p.data.notify_save_loaded.target = dcon::nation_id{};
4705 add_to_command_queue(state, p);
4706}
4707void execute_notify_save_loaded(sys::state& state, dcon::nation_id source, sys::checksum_key& k) {
4708 state.session_host_checksum = k;
4709 /* Reset OOS state, and for host, advise new clients with a save stream so they can hotjoin!
4710 Additionally we will clear the new client sending queue, since the state is no longer
4711 "replayable" without heavy bandwidth costs */
4712 state.network_state.is_new_game = false;
4713 state.network_state.out_of_sync = false;
4714 state.network_state.reported_oos = false;
4715}
4716
4717void notify_reload(sys::state& state, dcon::nation_id source) {
4718 payload p;
4719 memset(&p, 0, sizeof(payload));
4721 p.source = source;
4722 add_to_command_queue(state, p);
4723}
4724void execute_notify_reload(sys::state& state, dcon::nation_id source, sys::checksum_key& k) {
4725 state.session_host_checksum = k;
4726 /* Reset OOS state, and for host, advise new clients with a save stream so they can hotjoin!
4727 Additionally we will clear the new client sending queue, since the state is no longer
4728 "replayable" without heavy bandwidth costs */
4729 state.network_state.is_new_game = false;
4730 state.network_state.out_of_sync = false;
4731 state.network_state.reported_oos = false;
4732
4733 std::vector<dcon::nation_id> players;
4734 for(const auto n : state.world.in_nation)
4735 if(state.world.nation_get_is_player_controlled(n))
4736 players.push_back(n);
4737 dcon::nation_id old_local_player_nation = state.local_player_nation;
4738 /* Save the buffer before we fill the unsaved data */
4739 size_t length = sizeof_save_section(state);
4740 auto save_buffer = std::unique_ptr<uint8_t[]>(new uint8_t[length]);
4741 sys::write_save_section(save_buffer.get(), state);
4742 /* Then reload as if we loaded the save data */
4743 state.preload();
4744 sys::read_save_section(save_buffer.get(), save_buffer.get() + length, state);
4745 state.local_player_nation = dcon::nation_id{ };
4746 for(const auto n : players)
4747 state.world.nation_set_is_player_controlled(n, true);
4748 state.local_player_nation = old_local_player_nation;
4749 assert(state.world.nation_get_is_player_controlled(state.local_player_nation));
4750 state.fill_unsaved_data();
4751 assert(state.session_host_checksum.is_equal(state.get_save_checksum()));
4752}
4753
4754void execute_notify_start_game(sys::state& state, dcon::nation_id source) {
4755 assert(state.world.nation_get_is_player_controlled(state.local_player_nation));
4756 state.selected_armies.clear();
4757 state.selected_navies.clear();
4758 for(auto& v : state.ctrl_armies) v.clear();
4759 for(auto& v : state.ctrl_navies) v.clear();
4760 /* And clear the save stuff */
4761 state.network_state.current_save_buffer.reset();
4762 state.network_state.current_save_length = 0;
4763 /* Clear AI data */
4764 for(const auto n : state.world.in_nation)
4765 if(state.world.nation_get_is_player_controlled(n))
4766 ai::remove_ai_data(state, n);
4768 state.map_state.set_selected_province(dcon::province_id{});
4769 state.map_state.unhandled_province_selection = true;
4770}
4771
4772void notify_start_game(sys::state& state, dcon::nation_id source) {
4773 payload p;
4774 memset(&p, 0, sizeof(payload));
4776 p.source = source;
4777 add_to_command_queue(state, p);
4778}
4779
4780void execute_notify_stop_game(sys::state& state, dcon::nation_id source) {
4782 state.map_state.set_selected_province(dcon::province_id{});
4783 state.map_state.unhandled_province_selection = true;
4784}
4785
4786void notify_stop_game(sys::state& state, dcon::nation_id source) {
4787 payload p;
4788 memset(&p, 0, sizeof(payload));
4790 p.source = source;
4791 add_to_command_queue(state, p);
4792}
4793
4794void execute_notify_pause_game(sys::state& state, dcon::nation_id source) {
4795 state.actual_game_speed = 0;
4796}
4797
4798void notify_pause_game(sys::state& state, dcon::nation_id source) {
4799 payload p;
4800 memset(&p, 0, sizeof(payload));
4802 p.source = source;
4803 add_to_command_queue(state, p);
4804}
4805
4807 switch(c.type) {
4809 std::abort(); // invalid command
4810 break;
4811
4814
4816 return can_start_research(state, c.source, c.data.start_research.tech);
4817
4819 return can_make_leader(state, c.source, c.data.make_leader.is_general);
4820
4824
4827
4830
4833
4836
4840
4844
4848
4852
4856
4858 return true; //can_delete_factory(state, c.source, c.data.factory.location, c.data.factory.type);
4859
4861 return true; //can_change_factory_settings(state, c.source, c.data.factory.location, c.data.factory.type, c.data.factory.priority, c.data.factory.subsidize);
4862
4864 return can_make_vassal(state, c.source, c.data.tag_target.ident);
4865
4868
4871
4873 return can_start_election(state, c.source);
4874
4878
4881
4884
4887
4890
4893
4896
4899
4901 return can_upgrade_colony_to_state(state, c.source, state.world.province_get_state_membership(c.data.generic_location.prov));
4902
4905
4908
4911
4914
4916 return true; //can_suppress_movement(state, c.source, c.data.movement.iopt);
4917
4919 return can_civilize_nation(state, c.source);
4920
4923
4925 return can_enact_issue(state, c.source, c.data.issue_selection.r);
4926
4928 return can_enact_reform(state, c.source, c.data.reform_selection.r);
4929
4931 return can_become_interested_in_crisis(state, c.source);
4932
4935
4939
4941 return can_take_decision(state, c.source, c.data.decision.d);
4942
4944 return true; //can_make_event_choice(state, c.source, c.data.pending_human_n_event);
4945
4947 return true; // can_make_event_choice(state, c.source, c.data.pending_human_f_n_event);
4948
4950 return true; // can_make_event_choice(state, c.source, c.data.pending_human_p_event);
4951
4953 return true; // can_make_event_choice(state, c.source, c.data.pending_human_f_p_event);
4954
4956 return can_cancel_cb_fabrication(state, c.source);
4957
4960
4962 return can_ask_for_access(state, c.source, c.data.diplo_action.target);
4963
4966
4969
4971 return true; //can_respond_to_diplomatic_message(state, c.source, c.data.message.from, c.data.message.type, c.data.message.accept);
4972
4975
4978
4981
4985
4989
4993
4996
4998 return can_send_peace_offer(state, c.source);
4999
5001 return can_move_army(state, c.source, c.data.army_movement.a, c.data.army_movement.dest).size() != 0;
5002
5004 return can_move_navy(state, c.source, c.data.navy_movement.n, c.data.navy_movement.dest).size() != 0;
5005
5007 return can_embark_army(state, c.source, c.data.army_movement.a);
5008
5010 return can_merge_armies(state, c.source, c.data.merge_army.a, c.data.merge_army.b);
5011
5013 return can_merge_navies(state, c.source, c.data.merge_navy.a, c.data.merge_navy.b);
5014
5016 return can_split_army(state, c.source, c.data.army_movement.a);
5017
5019 return can_split_navy(state, c.source, c.data.navy_movement.n);
5020
5022 return can_delete_army(state, c.source, c.data.army_movement.a);
5023
5025 return can_delete_navy(state, c.source, c.data.navy_movement.n);
5026
5028 return true; //can_mark_regiments_to_split(state, c.source, c.data.split_regiments.regs);
5029
5031 return true; //can_mark_ships_to_split(state, c.source, c.data.split_ships.ships);
5032
5035
5038
5041
5043 return true; // can_invite_to_crisis(state, c.source, c.data.crisis_invitation);
5044
5046 return true; // can_add_to_crisis_peace_offer(state, c.source, c.data.crisis_invitation);
5047
5049 return can_send_crisis_peace_offer(state, c.source);
5050
5053
5056
5058 return true; //can_toggle_mobilization(state, c.source);
5059
5062
5064 return true; //can_set_rally_point(state, c.source, c.data.rally_point.location, c.data.rally_point.naval, c.data.rally_point.enable);
5065
5067 return true; //can_save_game(state, c.source, c.data.save_game.and_quit);
5068
5071
5074
5076 return can_evenly_split_army(state, c.source, c.data.army_movement.a);
5077
5079 return can_evenly_split_navy(state, c.source, c.data.navy_movement.n);
5080
5082 return true; //can_toggle_rebel_hunting(state, c.source, c.data.army_movement.a);
5083
5086
5089
5092
5094 return true;
5095
5097 return can_move_capital(state, c.source, c.data.generic_location.prov);
5098
5100 return true;
5102 return true;
5109
5110 // common mp commands
5112 {
5113 size_t count = 0;
5114 for(count = 0; count < sizeof(c.data.chat_message.body); count++)
5115 if(c.data.chat_message.body[count] == '\0')
5116
5117 std::string_view sv(c.data.chat_message.body, c.data.chat_message.body + count);
5119
5120 }
5123
5126
5128 return can_notify_player_joins(state, c.source, c.data.player_name);
5129
5132
5135
5137 return true; //return can_notify_player_oos(state, c.source);
5139 return true; //return can_advance_tick(state, c.source, c.data.advance_tick.checksum, c.data.advance_tick.speed);
5141 return true; //return can_notify_save_loaded(state, c.source, c.data.notify_save_loaded.seed, c.data.notify_save_loaded.checksum);
5143 return true;
5145 return true; //return can_notify_start_game(state, c.source);
5147 return true; //return can_notify_stop_game(state, c.source);
5149 return true; //return can_notify_pause_game(state, c.source);
5153 return true;
5154 }
5155 return false;
5156}
5157
5159 if(!can_perform_command(state, c))
5160 return;
5161 switch(c.type) {
5163 std::abort(); // invalid command
5164 break;
5167 break;
5170 break;
5173 break;
5177 break;
5180 break;
5183 break;
5186 break;
5189 break;
5193 break;
5197 break;
5201 break;
5205 break;
5209 break;
5212 break;
5216 break;
5219 break;
5222 break;
5225 break;
5228 break;
5232 break;
5235 break;
5238 break;
5241 break;
5244 break;
5247 break;
5250 break;
5253 break;
5255 execute_upgrade_colony_to_state(state, c.source, state.world.province_get_state_membership(c.data.generic_location.prov));
5256 break;
5259 break;
5262 break;
5265 break;
5268 break;
5271 break;
5274 break;
5277 break;
5280 break;
5283 break;
5286 break;
5289 break;
5293 break;
5296 break;
5299 break;
5302 break;
5305 break;
5308 break;
5311 break;
5314 break;
5317 break;
5320 break;
5323 break;
5326 break;
5329 break;
5332 break;
5335 break;
5339 break;
5343 break;
5347 break;
5350 break;
5353 break;
5356 break;
5359 break;
5362 break;
5365 break;
5368 break;
5371 break;
5374 break;
5377 break;
5380 break;
5383 break;
5386 break;
5389 break;
5392 break;
5395 break;
5398 break;
5401 break;
5404 break;
5407 break;
5410 break;
5413 break;
5416 break;
5419 break;
5422 break;
5425 break;
5428 break;
5431 break;
5434 break;
5437 break;
5440 break;
5443 break;
5446 break;
5449 break;
5452 break;
5455 break;
5458 break;
5461 break;
5464 break;
5467 break;
5470 break;
5471 // common mp commands
5473 {
5474 size_t count = 0;
5475 for(count = 0; count < sizeof(c.data.chat_message.body); count++)
5476 if(c.data.chat_message.body[count] == '\0')
5477 break;
5478 std::string_view sv(c.data.chat_message.body, c.data.chat_message.body + count);
5480 break;
5481 }
5484 break;
5487 break;
5490 break;
5493 break;
5496 break;
5499 break;
5502 break;
5505 break;
5508 break;
5511 break;
5514 break;
5517 break;
5520 break;
5521 }
5522}
5523
5525 auto* c = state.incoming_commands.front();
5526 bool command_executed = false;
5527 while(c) {
5528 command_executed = true;
5529 execute_command(state, *c);
5530 state.incoming_commands.pop();
5531 c = state.incoming_commands.front();
5532 }
5533
5534 if(command_executed) {
5538 state.game_state_updated.store(true, std::memory_order::release);
5539 }
5540}
5541
5542} // namespace command
virtual int64_t main_data(size_t index) const override
Definition: fif.hpp:921
std::unique_ptr< state_stack > interpreter_state
Definition: fif.hpp:3029
size_t main_size() const
Definition: fif.hpp:142
int32_t main_type(size_t index) const
Definition: fif.hpp:148
#define assert(condition)
Definition: debug.h:74
void remove_ai_data(sys::state &state, dcon::nation_id n)
Definition: ai.cpp:3303
bool can_state_transfer(sys::state &state, dcon::nation_id asker, dcon::nation_id target, dcon::state_definition_id sid)
Definition: commands.cpp:2375
void execute_abandon_colony(sys::state &state, dcon::nation_id source, dcon::province_id p)
Definition: commands.cpp:1613
bool can_increase_opinion(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target)
Definition: commands.cpp:1273
void execute_send_peace_offer(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:3071
void execute_delete_army(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:4094
void execute_release_and_play_as(sys::state &state, dcon::nation_id source, dcon::national_identity_id t)
Definition: commands.cpp:908
bool can_cancel_military_access(sys::state &state, dcon::nation_id source, dcon::nation_id target, bool ignore_cost)
Definition: commands.cpp:2500
void mark_ships_to_split(sys::state &state, dcon::nation_id source, std::array< dcon::ship_id, num_packed_units > const &list)
Definition: commands.cpp:4182
constexpr size_t num_packed_units
Definition: commands.hpp:405
void execute_notify_player_oos(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:4660
void execute_retreat_from_naval_battle(sys::state &state, dcon::nation_id source, dcon::naval_battle_id b)
Definition: commands.cpp:4217
void execute_toggle_mobilization(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:4354
bool can_start_research(sys::state &state, dcon::nation_id source, dcon::technology_id tech)
Definition: commands.cpp:183
bool can_release_subject(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:3807
bool can_send_crisis_peace_offer(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:3104
void execute_notify_player_kick(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4604
bool can_expel_advisors(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1132
void execute_decrease_relations(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:379
void execute_use_nation_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n)
Definition: commands.cpp:4458
void execute_add_war_goal(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)
Definition: commands.cpp:2783
void start_land_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type, dcon::province_id template_province)
Definition: commands.cpp:668
void execute_take_sides_in_crisis(sys::state &state, dcon::nation_id source, bool join_attacker)
Definition: commands.cpp:1970
void enact_issue(sys::state &state, dcon::nation_id source, dcon::issue_option_id i)
Definition: commands.cpp:1878
void execute_expel_advisors(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1166
bool can_add_to_sphere(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target)
Definition: commands.cpp:1410
bool can_invite_to_crisis(sys::state &state, dcon::nation_id source, dcon::nation_id invitation_to, dcon::nation_id target, dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation)
Definition: commands.cpp:4271
bool can_give_war_subsidies(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:238
bool can_add_war_goal(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)
Definition: commands.cpp:2715
bool can_change_admiral(sys::state &state, dcon::nation_id source, dcon::navy_id a, dcon::leader_id l)
Definition: commands.cpp:4151
void execute_cancel_factory_building_construction(sys::state &state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type)
Definition: commands.cpp:466
bool is_console_command(command_type t)
Definition: commands.cpp:19
void execute_toggle_unit_ai_control(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3723
void execute_start_crisis_peace_offer(sys::state &state, dcon::nation_id source, bool is_concession)
Definition: commands.cpp:2875
bool can_give_military_access(sys::state &state, dcon::nation_id asker, dcon::nation_id target, bool ignore_cost)
Definition: commands.cpp:2262
void execute_ask_for_access(sys::state &state, dcon::nation_id asker, dcon::nation_id target)
Definition: commands.cpp:2242
void execute_make_leader(sys::state &state, dcon::nation_id source, bool general)
Definition: commands.cpp:225
void execute_call_to_arms(sys::state &state, dcon::nation_id asker, dcon::nation_id target, dcon::war_id w)
Definition: commands.cpp:2451
void execute_split_army(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3998
void toggle_rebel_hunting(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3683
void execute_state_transfer(sys::state &state, dcon::nation_id asker, dcon::nation_id target, dcon::state_definition_id sid)
Definition: commands.cpp:2408
void execute_change_general(sys::state &state, dcon::nation_id source, dcon::army_id a, dcon::leader_id l)
Definition: commands.cpp:4138
bool can_cancel_war_subsidies(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:283
void execute_toggle_interested_in_alliance(sys::state &state, dcon::nation_id asker, dcon::nation_id target)
Definition: commands.cpp:2357
void execute_change_stockpile_settings(sys::state &state, dcon::nation_id source, dcon::commodity_id c, float target_amount, bool draw_on_stockpiles)
Definition: commands.cpp:2009
bool can_cancel_factory_building_construction(sys::state &state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type)
Definition: commands.cpp:453
bool can_notify_player_joins(sys::state &state, dcon::nation_id source, sys::player_name &name)
Definition: commands.cpp:4516
bool can_change_general(sys::state &state, dcon::nation_id source, dcon::army_id a, dcon::leader_id l)
Definition: commands.cpp:4132
bool can_intervene_in_war(sys::state &state, dcon::nation_id source, dcon::war_id w, bool for_attacker)
Definition: commands.cpp:1668
bool can_release_and_play_as(sys::state &state, dcon::nation_id source, dcon::national_identity_id t)
Definition: commands.cpp:905
void execute_enable_debt(sys::state &state, dcon::nation_id source, bool debt_is_enabled)
Definition: commands.cpp:4371
bool can_delete_factory(sys::state &state, dcon::nation_id source, dcon::factory_id f)
Definition: commands.cpp:776
bool can_begin_factory_building_construction(sys::state &state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type, bool is_upgrade)
Definition: commands.cpp:491
void execute_toggle_immigrator_province(sys::state &state, dcon::nation_id source, dcon::province_id prov)
Definition: commands.cpp:3795
void give_war_subsidies(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:230
bool can_call_to_arms(sys::state &state, dcon::nation_id asker, dcon::nation_id target, dcon::war_id w, bool ignore_cost)
Definition: commands.cpp:2430
bool can_appoint_ruling_party(sys::state &state, dcon::nation_id source, dcon::political_party_id p)
Definition: commands.cpp:1822
void execute_begin_province_building_construction(sys::state &state, dcon::nation_id source, dcon::province_id p, economy::province_building_type type)
Definition: commands.cpp:418
bool can_begin_province_building_construction(sys::state &state, dcon::nation_id source, dcon::province_id p, economy::province_building_type type)
Definition: commands.cpp:402
bool can_start_election(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:1003
bool can_delete_army(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:4089
void change_budget_settings(sys::state &state, dcon::nation_id source, budget_settings_data const &values)
Definition: commands.cpp:945
bool can_start_crisis_peace_offer(sys::state &state, dcon::nation_id source, bool is_concession)
Definition: commands.cpp:2866
void execute_start_land_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type, dcon::province_id template_province)
Definition: commands.cpp:710
bool can_notify_player_leaves(sys::state &state, dcon::nation_id source, bool make_ai)
Definition: commands.cpp:4544
void execute_chat_message(sys::state &state, dcon::nation_id source, std::string_view body, dcon::nation_id target)
Definition: commands.cpp:4500
bool can_add_to_peace_offer(sys::state &state, dcon::nation_id source, dcon::wargoal_id goal)
Definition: commands.cpp:2927
bool can_ask_for_access(sys::state &state, dcon::nation_id asker, dcon::nation_id target, bool ignore_cost)
Definition: commands.cpp:2222
void execute_advance_tick(sys::state &state, dcon::nation_id source, sys::checksum_key &k, int32_t speed)
Definition: commands.cpp:4683
void execute_cancel_land_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type)
Definition: commands.cpp:755
void execute_appoint_ruling_party(sys::state &state, dcon::nation_id source, dcon::political_party_id p)
Definition: commands.cpp:1850
bool can_change_factory_settings(sys::state &state, dcon::nation_id source, dcon::factory_id f, uint8_t priority, bool subsidized)
Definition: commands.cpp:819
void execute_make_vassal(sys::state &state, dcon::nation_id source, dcon::national_identity_id t)
Definition: commands.cpp:881
void start_naval_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type, dcon::province_id template_province)
Definition: commands.cpp:609
void use_nation_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n)
Definition: commands.cpp:4439
void execute_mark_regiments_to_split(sys::state &state, dcon::nation_id source, dcon::regiment_id const *regs)
Definition: commands.cpp:4171
void execute_add_to_sphere(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target)
Definition: commands.cpp:1442
void execute_intervene_in_war(sys::state &state, dcon::nation_id source, dcon::war_id w, bool for_attacker)
Definition: commands.cpp:1751
bool can_increase_relations(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:325
bool can_cancel_cb_fabrication(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:2196
void retreat_from_land_battle(sys::state &state, dcon::nation_id source, dcon::land_battle_id b)
Definition: commands.cpp:4228
void mark_regiments_to_split(sys::state &state, dcon::nation_id source, std::array< dcon::regiment_id, num_packed_units > const &list)
Definition: commands.cpp:4161
bool can_upgrade_colony_to_state(sys::state &state, dcon::nation_id source, dcon::state_instance_id si)
Definition: commands.cpp:1547
bool can_civilize_nation(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:1807
bool can_set_national_focus(sys::state &state, dcon::nation_id source, dcon::state_instance_id target_state, dcon::national_focus_id focus)
Definition: commands.cpp:118
void evenly_split_army(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3875
bool can_retreat_from_land_battle(sys::state &state, dcon::nation_id source, dcon::land_battle_id b)
Definition: commands.cpp:4237
void execute_notify_player_picks_nation(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4638
bool can_use_province_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id p)
Definition: commands.cpp:4423
void release_and_play_as(sys::state &state, dcon::nation_id source, dcon::national_identity_id t)
Definition: commands.cpp:897
void execute_upgrade_colony_to_state(sys::state &state, dcon::nation_id source, dcon::state_instance_id si)
Definition: commands.cpp:1550
void execute_cancel_military_access(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:2513
bool can_enact_reform(sys::state &state, dcon::nation_id source, dcon::reform_option_id r)
Definition: commands.cpp:1862
void execute_change_factory_settings(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::factory_type_id type, uint8_t priority, bool subsidized)
Definition: commands.cpp:841
void execute_release_subject(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:3810
void execute_set_rally_point(sys::state &state, dcon::nation_id source, dcon::province_id location, bool naval, bool enable)
Definition: commands.cpp:79
void execute_make_event_choice(sys::state &state, dcon::nation_id source, pending_human_n_event_data const &e)
Definition: commands.cpp:2114
void execute_notify_player_leaves(sys::state &state, dcon::nation_id source, bool make_ai)
Definition: commands.cpp:4547
void execute_notify_player_ban(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4573
bool can_evenly_split_army(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3883
void execute_civilize_nation(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:1810
bool can_abandon_colony(sys::state &state, dcon::nation_id source, dcon::province_id pr)
Definition: commands.cpp:1608
bool can_ban_embassy(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1202
void execute_invite_to_crisis(sys::state &state, dcon::nation_id source, crisis_invitation_data const &data)
Definition: commands.cpp:4325
void execute_retreat_from_land_battle(sys::state &state, dcon::nation_id source, dcon::land_battle_id b)
Definition: commands.cpp:4245
void execute_start_peace_offer(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::war_id war, bool is_concession)
Definition: commands.cpp:2850
bool can_decrease_relations(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:365
bool can_move_capital(sys::state &state, dcon::nation_id source, dcon::province_id p)
Definition: commands.cpp:4384
void set_national_focus(sys::state &state, dcon::nation_id source, dcon::state_instance_id target_state, dcon::national_focus_id focus)
Definition: commands.cpp:107
void execute_give_war_subsidies(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:255
bool can_start_peace_offer(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::war_id war, bool is_concession)
Definition: commands.cpp:2809
void execute_notify_player_joins(sys::state &state, dcon::nation_id source, sys::player_name &name)
Definition: commands.cpp:4520
bool can_notify_player_kick(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4599
void execute_begin_factory_building_construction(sys::state &state, dcon::nation_id source, dcon::state_instance_id location, dcon::factory_type_id type, bool is_upgrade)
Definition: commands.cpp:589
bool can_toggle_select_province(sys::state &state, dcon::nation_id source, dcon::province_id prov)
Definition: commands.cpp:3769
bool can_start_land_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type, dcon::province_id template_province)
Definition: commands.cpp:679
void execute_finish_colonization(sys::state &state, dcon::nation_id source, dcon::province_id p)
Definition: commands.cpp:1640
void execute_console_command(sys::state &state)
Definition: commands.cpp:3824
void execute_change_admiral(sys::state &state, dcon::nation_id source, dcon::navy_id a, dcon::leader_id l)
Definition: commands.cpp:4157
void execute_remove_from_sphere(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1503
bool can_evenly_split_navy(sys::state &state, dcon::nation_id source, dcon::navy_id a)
Definition: commands.cpp:3939
void execute_evenly_split_navy(sys::state &state, dcon::nation_id source, dcon::navy_id a)
Definition: commands.cpp:3942
void execute_fabricate_cb(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id type)
Definition: commands.cpp:2190
void execute_respond_to_diplomatic_message(sys::state &state, dcon::nation_id source, dcon::nation_id from, diplomatic_message::type type, bool accept)
Definition: commands.cpp:2475
void execute_take_decision(sys::state &state, dcon::nation_id source, dcon::decision_id d)
Definition: commands.cpp:2036
void execute_notify_stop_game(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:4780
void execute_send_crisis_peace_offer(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:3115
void add_to_crisis_peace_offer(sys::state &state, dcon::nation_id source, dcon::nation_id wargoal_from, dcon::nation_id target, dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation)
Definition: commands.cpp:2990
void execute_start_research(sys::state &state, dcon::nation_id source, dcon::technology_id tech)
Definition: commands.cpp:208
void execute_enact_reform(sys::state &state, dcon::nation_id source, dcon::reform_option_id r)
Definition: commands.cpp:1873
void retreat_from_naval_battle(sys::state &state, dcon::nation_id source, dcon::naval_battle_id b)
Definition: commands.cpp:4201
void execute_embark_army(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3522
void execute_give_military_access(sys::state &state, dcon::nation_id asker, dcon::nation_id target)
Definition: commands.cpp:2278
void execute_increase_opinion(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target)
Definition: commands.cpp:1301
bool can_partial_retreat_from(sys::state &state, dcon::land_battle_id b)
Definition: commands.cpp:3151
bool can_disband_undermanned_regiments(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3668
void execute_set_national_focus(sys::state &state, dcon::nation_id source, dcon::state_instance_id target_state, dcon::national_focus_id focus)
Definition: commands.cpp:163
void execute_move_army(sys::state &state, dcon::nation_id source, dcon::army_id a, dcon::province_id dest, bool reset)
Definition: commands.cpp:3285
bool can_take_sides_in_crisis(sys::state &state, dcon::nation_id source, bool join_attacker)
Definition: commands.cpp:1953
void execute_evenly_split_army(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3886
void execute_mark_ships_to_split(sys::state &state, dcon::nation_id source, dcon::ship_id const *regs)
Definition: commands.cpp:4191
bool can_change_stockpile_settings(sys::state &state, dcon::nation_id source, dcon::commodity_id c, float target_amount, bool draw_on_stockpiles)
Definition: commands.cpp:1992
void disband_undermanned_regiments(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3660
bool can_take_decision(sys::state &state, dcon::nation_id source, dcon::decision_id d)
Definition: commands.cpp:2023
void enact_reform(sys::state &state, dcon::nation_id source, dcon::reform_option_id r)
Definition: commands.cpp:1854
bool can_make_leader(sys::state &state, dcon::nation_id source, bool general)
Definition: commands.cpp:222
void execute_change_budget_settings(sys::state &state, dcon::nation_id source, budget_settings_data const &values)
Definition: commands.cpp:953
bool can_send_peace_offer(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:3065
void execute_invest_in_colony(sys::state &state, dcon::nation_id source, dcon::province_id pr)
Definition: commands.cpp:1569
void execute_start_election(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:1007
bool can_cancel_land_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::culture_id soldier_culture, dcon::unit_type_id type)
Definition: commands.cpp:752
void execute_merge_navies(sys::state &state, dcon::nation_id source, dcon::navy_id a, dcon::navy_id b)
Definition: commands.cpp:3630
void execute_add_to_peace_offer(sys::state &state, dcon::nation_id source, dcon::wargoal_id goal)
Definition: commands.cpp:2985
bool can_make_vassal(sys::state &state, dcon::nation_id source, dcon::national_identity_id t)
Definition: commands.cpp:878
bool can_merge_navies(sys::state &state, dcon::nation_id source, dcon::navy_id a, dcon::navy_id b)
Definition: commands.cpp:3613
void notify_console_command(sys::state &state)
Definition: commands.cpp:3816
void execute_ban_embassy(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1237
bool can_discredit_advisors(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1057
void execute_notify_start_game(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:4754
void execute_change_influence_priority(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, uint8_t priority)
Definition: commands.cpp:1024
bool can_add_to_crisis_peace_offer(sys::state &state, dcon::nation_id source, dcon::nation_id wargoal_from, dcon::nation_id target, dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation)
Definition: commands.cpp:3005
bool can_cancel_naval_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type)
Definition: commands.cpp:728
void add_to_command_queue(sys::state &state, payload &p)
Definition: commands.cpp:23
void execute_merge_armies(sys::state &state, dcon::nation_id source, dcon::army_id a, dcon::army_id b)
Definition: commands.cpp:3580
void execute_increase_relations(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:343
void execute_enact_issue(sys::state &state, dcon::nation_id source, dcon::issue_option_id i)
Definition: commands.cpp:1898
bool can_remove_from_sphere(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1470
void execute_notify_reload(sys::state &state, dcon::nation_id source, sys::checksum_key &k)
Definition: commands.cpp:4724
void execute_cancel_alliance(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:2598
void execute_notify_pause_game(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:4794
bool can_retreat_from_naval_battle(sys::state &state, dcon::nation_id source, dcon::naval_battle_id b)
Definition: commands.cpp:4209
bool can_change_budget_settings(sys::state &state, dcon::nation_id source, budget_settings_data const &values)
Definition: commands.cpp:941
void execute_split_navy(sys::state &state, dcon::nation_id source, dcon::navy_id a)
Definition: commands.cpp:4047
void execute_toggle_mobilized_is_ai_controlled(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:3757
void execute_save_game(sys::state &state, dcon::nation_id source, bool and_quit)
Definition: commands.cpp:99
void execute_become_interested_in_crisis(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:1935
void execute_cancel_cb_fabrication(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:2207
bool can_become_interested_in_crisis(sys::state &state, dcon::nation_id source)
Definition: commands.cpp:1910
bool can_split_navy(sys::state &state, dcon::nation_id source, dcon::navy_id a)
Definition: commands.cpp:4042
void execute_discredit_advisors(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1096
bool can_decrease_opinion(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1331
command_type
Definition: commands.hpp:9
bool can_suppress_movement(sys::state &state, dcon::nation_id source, dcon::movement_id m)
Definition: commands.cpp:1779
void execute_use_province_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id p)
Definition: commands.cpp:4433
bool can_fabricate_cb(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id type)
Definition: commands.cpp:2147
bool can_delete_navy(sys::state &state, dcon::nation_id source, dcon::navy_id a)
Definition: commands.cpp:4110
void use_province_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id i)
Definition: commands.cpp:4414
bool can_split_army(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3994
bool can_invest_in_colony(sys::state &state, dcon::nation_id source, dcon::province_id p)
Definition: commands.cpp:1562
bool can_chat_message(sys::state &state, dcon::nation_id source, std::string_view body, dcon::nation_id target)
Definition: commands.cpp:4496
void execute_move_navy(sys::state &state, dcon::nation_id source, dcon::navy_id n, dcon::province_id dest, bool reset)
Definition: commands.cpp:3430
void execute_cancel_naval_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type)
Definition: commands.cpp:732
bool can_cancel_alliance(sys::state &state, dcon::nation_id source, dcon::nation_id target, bool ignore_cost)
Definition: commands.cpp:2578
bool can_notify_player_ban(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4568
void evenly_split_navy(sys::state &state, dcon::nation_id source, dcon::navy_id a)
Definition: commands.cpp:3931
bool can_declare_war(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation)
Definition: commands.cpp:2621
void execute_add_to_crisis_peace_offer(sys::state &state, dcon::nation_id source, crisis_invitation_data const &data)
Definition: commands.cpp:3045
void execute_notify_save_loaded(sys::state &state, dcon::nation_id source, sys::checksum_key &k)
Definition: commands.cpp:4707
bool can_embark_army(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3502
bool can_toggle_interested_in_alliance(sys::state &state, dcon::nation_id asker, dcon::nation_id target)
Definition: commands.cpp:2352
void execute_move_capital(sys::state &state, dcon::nation_id source, dcon::province_id p)
Definition: commands.cpp:4410
void execute_toggle_select_province(sys::state &state, dcon::nation_id source, dcon::province_id prov)
Definition: commands.cpp:3776
void add_to_peace_offer(sys::state &state, dcon::nation_id source, dcon::wargoal_id goal)
Definition: commands.cpp:2919
bool can_use_nation_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n)
Definition: commands.cpp:4448
void execute_cancel_war_subsidies(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:297
bool can_merge_armies(sys::state &state, dcon::nation_id source, dcon::army_id a, dcon::army_id b)
Definition: commands.cpp:3558
void execute_suppress_movement(sys::state &state, dcon::nation_id source, dcon::issue_option_id iopt, dcon::national_identity_id tag)
Definition: commands.cpp:1786
void execute_delete_factory(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::factory_type_id type)
Definition: commands.cpp:785
void execute_cancel_given_military_access(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:2550
bool can_finish_colonization(sys::state &state, dcon::nation_id source, dcon::province_id p)
Definition: commands.cpp:1631
void execute_declare_war(sys::state &state, dcon::nation_id source, dcon::nation_id target, dcon::cb_type_id primary_cb, dcon::state_definition_id cb_state, dcon::national_identity_id cb_tag, dcon::nation_id cb_secondary_nation, bool call_attacker_allies)
Definition: commands.cpp:2658
std::vector< dcon::province_id > can_move_navy(sys::state &state, dcon::nation_id source, dcon::navy_id n, dcon::province_id dest)
Definition: commands.cpp:3398
void make_event_choice(sys::state &state, event::pending_human_n_event const &e, uint8_t option_id)
Definition: commands.cpp:2058
bool can_notify_player_picks_nation(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4630
bool can_perform_command(sys::state &state, payload &c)
Definition: commands.cpp:4806
bool can_enact_issue(sys::state &state, dcon::nation_id source, dcon::issue_option_id i)
Definition: commands.cpp:1886
bool can_change_influence_priority(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, uint8_t priority)
Definition: commands.cpp:1020
bool can_cancel_given_military_access(sys::state &state, dcon::nation_id source, dcon::nation_id target, bool ignore_cost)
Definition: commands.cpp:2539
bool can_toggle_immigrator_province(sys::state &state, dcon::nation_id source, dcon::province_id prov)
Definition: commands.cpp:3788
void execute_disband_undermanned_regiments(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3672
void execute_pending_commands(sys::state &state)
Definition: commands.cpp:5524
void execute_decrease_opinion(sys::state &state, dcon::nation_id source, dcon::nation_id influence_target, dcon::nation_id affected_gp)
Definition: commands.cpp:1375
void execute_start_naval_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type, dcon::province_id template_province)
Definition: commands.cpp:662
bool can_ask_for_alliance(sys::state &state, dcon::nation_id asker, dcon::nation_id target, bool ignore_cost)
Definition: commands.cpp:2297
void execute_command(sys::state &state, payload &c)
Definition: commands.cpp:5158
void execute_delete_navy(sys::state &state, dcon::nation_id source, dcon::navy_id a)
Definition: commands.cpp:4116
bool can_start_naval_unit_construction(sys::state &state, dcon::nation_id source, dcon::province_id location, dcon::unit_type_id type, dcon::province_id template_province)
Definition: commands.cpp:620
void execute_toggle_rebel_hunting(sys::state &state, dcon::nation_id source, dcon::army_id a)
Definition: commands.cpp:3691
void execute_ask_for_alliance(sys::state &state, dcon::nation_id asker, dcon::nation_id target)
Definition: commands.cpp:2329
std::vector< dcon::province_id > can_move_army(sys::state &state, dcon::nation_id source, dcon::army_id a, dcon::province_id dest)
Definition: commands.cpp:3166
constexpr uint64_t to_bits(dcon::ideology_id id)
Definition: culture.hpp:92
constexpr dcon::demographics_key total(0)
dcon::demographics_key to_key(sys::state const &state, dcon::pop_type_id v)
void decline(sys::state &state, message const &m)
void accept(sys::state &state, message const &m)
void post(sys::state &state, message const &m)
void for_each_new_factory(sys::state &state, dcon::state_instance_id s, F &&func)
int32_t state_factory_count(sys::state &state, dcon::state_instance_id sid, dcon::nation_id n)
Definition: economy.cpp:4911
int32_t factory_priority(sys::state const &state, dcon::factory_id f)
Definition: economy.cpp:1004
void bound_budget_settings(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:5271
province_building_type
Definition: constants.hpp:578
void set_factory_priority(sys::state &state, dcon::factory_id f, int32_t priority)
Definition: economy.cpp:1007
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)
Definition: effects.cpp:5404
void take_option(sys::state &state, pending_human_n_event const &e, uint8_t opt)
Definition: events.cpp:14
void update_future_events(sys::state &state)
Definition: events.cpp:473
void execute_fif_word(interpreted_word_instance &wi, state_stack &ss, environment &env)
Definition: fif.hpp:2146
void run_fif_interpreter(environment &env, std::string_view on_text)
Definition: fif.hpp:5096
void switch_scene(sys::state &state, scene_id ui_scene)
Definition: game_scene.cpp:13
constexpr uint32_t build_factory
Definition: culture.hpp:8
constexpr uint32_t can_subsidise
Definition: culture.hpp:13
constexpr uint32_t destroy_factory
Definition: culture.hpp:11
constexpr uint32_t allow_foreign_investment
Definition: culture.hpp:26
constexpr uint32_t factory_priority
Definition: culture.hpp:12
constexpr uint32_t expand_factory
Definition: culture.hpp:9
constexpr uint32_t po_status_quo
Definition: military.hpp:27
constexpr uint32_t is_not_constructing_cb
Definition: military.hpp:12
constexpr uint32_t always
Definition: military.hpp:10
bool are_allied_in_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
Definition: military.cpp:486
float truce_break_cb_prestige_cost(sys::state &state, dcon::cb_type_id t)
Definition: military.cpp:1328
bool cb_conditions_satisfied(sys::state &state, dcon::nation_id actor, dcon::nation_id target, dcon::cb_type_id cb)
Definition: military.cpp:254
float primary_warscore(sys::state &state, dcon::war_id w)
Definition: military.cpp:3628
float truce_break_cb_infamy(sys::state &state, dcon::cb_type_id t)
Definition: military.cpp:1450
void send_rebel_hunter_to_next_province(sys::state &state, dcon::army_id ar, dcon::province_id prov)
Definition: military.cpp:6457
void army_arrives_in_province(sys::state &state, dcon::army_id a, dcon::province_id p, crossing_type crossing, dcon::land_battle_id from)
Definition: military.cpp:3992
void add_to_war(sys::state &state, dcon::war_id w, dcon::nation_id n, bool as_attacker, bool on_war_creation)
Definition: military.cpp:2109
float directed_warscore(sys::state &state, dcon::war_id w, dcon::nation_id primary, dcon::nation_id secondary)
Definition: military.cpp:3685
void end_battle(sys::state &state, dcon::land_battle_id b, battle_result result)
Definition: military.cpp:4523
dcon::pop_id find_available_soldier(sys::state &state, dcon::province_id p, dcon::culture_id pop_culture)
Definition: military.cpp:831
bool has_truce_with(sys::state &state, dcon::nation_id attacker, dcon::nation_id target)
Definition: military.cpp:2037
bool standard_war_joining_is_possible(sys::state &state, dcon::war_id wfor, dcon::nation_id n, bool as_attacker)
Definition: military.cpp:2344
dcon::nation_id get_naval_battle_lead_defender(sys::state &state, dcon::naval_battle_id b)
Definition: military.cpp:4259
war_role get_role(sys::state const &state, dcon::war_id w, dcon::nation_id n)
Definition: military.cpp:2242
bool can_retreat_from_battle(sys::state &state, dcon::naval_battle_id battle)
Definition: military.cpp:7203
void update_battle_leaders(sys::state &state, dcon::land_battle_id b)
Definition: military.cpp:4362
bool is_attacker(sys::state &state, dcon::war_id w, dcon::nation_id n)
Definition: military.cpp:2234
void cleanup_navy(sys::state &state, dcon::navy_id n)
Definition: military.cpp:4467
bool joining_as_attacker_would_break_truce(sys::state &state, dcon::nation_id a, dcon::war_id w)
Definition: military.cpp:607
bool is_defender_wargoal(sys::state const &state, dcon::war_id w, dcon::wargoal_id wg)
Definition: military.cpp:575
dcon::nation_id get_land_battle_lead_attacker(sys::state &state, dcon::land_battle_id b)
Definition: military.cpp:4279
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)
Definition: military.cpp:2409
bool can_embark_onto_sea_tile(sys::state &state, dcon::nation_id from, dcon::province_id p, dcon::army_id a)
Definition: military.cpp:3822
sys::date arrival_time_to(sys::state &state, dcon::army_id a, dcon::province_id p)
Definition: military.cpp:3889
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)
Definition: military.cpp:2250
dcon::nation_id get_naval_battle_lead_attacker(sys::state &state, dcon::naval_battle_id b)
Definition: military.cpp:4239
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)
Definition: military.cpp:321
float truce_break_cb_militancy(sys::state &state, dcon::cb_type_id t)
Definition: military.cpp:1389
void start_mobilization(sys::state &state, dcon::nation_id n)
Definition: military.cpp:7030
void call_attacker_allies(sys::state &state, dcon::war_id wfor)
Definition: military.cpp:2389
bool are_at_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
Definition: military.cpp:475
bool defenders_have_non_status_quo_wargoal(sys::state const &state, dcon::war_id w)
Definition: military.cpp:584
void end_mobilization(sys::state &state, dcon::nation_id n)
Definition: military.cpp:7101
dcon::leader_id make_new_leader(sys::state &state, dcon::nation_id n, bool is_general)
Definition: military.cpp:1857
void cleanup_army(sys::state &state, dcon::army_id n)
Definition: military.cpp:4417
bool joining_war_does_not_violate_constraints(sys::state const &state, dcon::nation_id a, dcon::war_id w, bool as_attacker)
Definition: military.cpp:546
void implement_peace_offer(sys::state &state, dcon::peace_offer_id offer)
Definition: military.cpp:3205
void call_defender_allies(sys::state &state, dcon::war_id wfor)
Definition: military.cpp:2358
bool is_civil_war(sys::state const &state, dcon::war_id w)
Definition: military.cpp:567
dcon::nation_id get_land_battle_lead_defender(sys::state &state, dcon::land_battle_id b)
Definition: military.cpp:4310
bool defenders_have_status_quo_wargoal(sys::state const &state, dcon::war_id w)
Definition: military.cpp:592
bool 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)
Definition: military.cpp:7251
int32_t cost_of_peace_offer(sys::state &state, dcon::peace_offer_id offer)
Definition: military.cpp:1665
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)
Definition: military.cpp:1779
dcon::navy_id find_embark_target(sys::state &state, dcon::nation_id from, dcon::province_id p, dcon::army_id a)
Definition: military.cpp:3834
constexpr uint8_t is_banned
Definition: nations.hpp:179
constexpr uint8_t level_friendly
Definition: nations.hpp:168
uint8_t decrease_level(uint8_t v)
Definition: nations.hpp:199
constexpr uint8_t is_discredited
Definition: nations.hpp:178
constexpr uint8_t priority_zero
Definition: nations.hpp:172
constexpr uint8_t level_opposed
Definition: nations.hpp:165
constexpr uint8_t level_hostile
Definition: nations.hpp:166
constexpr uint8_t priority_three
Definition: nations.hpp:175
uint8_t increase_level(uint8_t v)
Definition: nations.hpp:181
constexpr uint8_t priority_one
Definition: nations.hpp:173
constexpr uint8_t level_in_sphere
Definition: nations.hpp:169
constexpr uint8_t level_mask
Definition: nations.hpp:163
int32_t get_level(sys::state &state, dcon::nation_id gp, dcon::nation_id target)
Definition: nations.cpp:23
constexpr uint8_t priority_two
Definition: nations.hpp:174
bool is_influence_level_greater_or_equal(int32_t l, int32_t r)
Definition: nations.hpp:249
void remove_cores_from_owned(sys::state &state, dcon::nation_id n, dcon::national_identity_id tag)
Definition: nations.cpp:2650
void cleanup_crisis_peace_offer(sys::state &state, dcon::peace_offer_id peace)
Definition: nations.cpp:2009
bool is_great_power(sys::state const &state, dcon::nation_id id)
Definition: nations.cpp:503
void enact_reform(sys::state &state, dcon::nation_id source, dcon::reform_option_id r)
Definition: nations.cpp:2890
void break_alliance(sys::state &state, dcon::diplomatic_relation_id rel)
Definition: nations.cpp:1442
bool can_release_as_vassal(sys::state const &state, dcon::nation_id n, dcon::national_identity_id releasable)
Definition: nations.cpp:176
void adjust_prestige(sys::state &state, dcon::nation_id n, float delta)
Definition: nations.cpp:1330
bool is_involved_in_crisis(sys::state const &state, dcon::nation_id n)
Definition: nations.cpp:1066
void release_vassal(sys::state &state, dcon::overlord_id rel)
Definition: nations.cpp:1378
bool are_allied(sys::state &state, dcon::nation_id a, dcon::nation_id b)
Definition: nations.cpp:198
void adjust_foreign_investment(sys::state &state, dcon::nation_id great_power, dcon::nation_id target, float delta)
Definition: nations.cpp:2735
void liberate_nation_from(sys::state &state, dcon::national_identity_id liberated, dcon::nation_id from)
Definition: nations.cpp:2602
void enact_issue(sys::state &state, dcon::nation_id source, dcon::issue_option_id i)
Definition: nations.cpp:2935
void update_cached_values(sys::state &state)
Definition: nations.cpp:109
void make_civilized(sys::state &state, dcon::nation_id n)
Definition: nations.cpp:2758
void adjust_relationship(sys::state &state, dcon::nation_id a, dcon::nation_id b, float delta)
Definition: nations.cpp:1094
int32_t national_focuses_in_use(sys::state &state, dcon::nation_id n)
Definition: nations.cpp:634
dcon::technology_id current_research(sys::state const &state, dcon::nation_id n)
Definition: nations.cpp:606
int32_t max_national_focuses(sys::state &state, dcon::nation_id n)
Definition: nations.cpp:618
auto nation_accepts_culture(sys::state const &state, T ids, U cul_ids)
void kick_player(sys::state &state, client_data &client)
Definition: network.cpp:1145
void switch_player(sys::state &state, dcon::nation_id new_n, dcon::nation_id old_n)
Definition: network.cpp:1152
void ban_player(sys::state &state, client_data &client)
Definition: network.cpp:1131
void post(sys::state &state, message &&m)
bool can_enact_social_reform(sys::state &state, dcon::nation_id n, dcon::issue_option_id o)
Definition: politics.cpp:181
bool can_enact_political_reform(sys::state &state, dcon::nation_id nation, dcon::issue_option_id issue_option)
Definition: politics.cpp:107
bool can_appoint_ruling_party(sys::state &state, dcon::nation_id nation)
Definition: politics.cpp:51
bool political_party_is_active(sys::state &state, dcon::nation_id n, dcon::political_party_id p)
Definition: politics.cpp:323
bool can_enact_military_reform(sys::state &state, dcon::nation_id n, dcon::reform_option_id o)
Definition: politics.cpp:253
void appoint_ruling_party(sys::state &state, dcon::nation_id n, dcon::political_party_id p)
Definition: politics.cpp:364
void start_election(sys::state &state, dcon::nation_id n)
Definition: politics.cpp:732
bool is_election_ongoing(sys::state &state, dcon::nation_id nation)
Definition: politics.cpp:55
bool can_enact_economic_reform(sys::state &state, dcon::nation_id n, dcon::reform_option_id o)
Definition: politics.cpp:273
void set_militancy(sys::state &state, dcon::pop_id p, float v)
float get_militancy(sys::state const &state, dcon::pop_id p)
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)
Definition: province.cpp:1673
void upgrade_colonial_state(sys::state &state, dcon::nation_id source, dcon::state_instance_id si)
Definition: province.cpp:629
bool can_build_railroads(sys::state &state, dcon::province_id id, dcon::nation_id n)
Definition: province.cpp:330
void update_connected_regions(sys::state &state)
Definition: province.cpp:29
bool has_access_to_province(sys::state &state, dcon::nation_id nation_as, dcon::province_id prov)
Definition: province.cpp:1597
bool is_overseas(sys::state const &state, dcon::province_id ids)
Definition: province.cpp:18
bool is_colonizing(sys::state &state, dcon::nation_id n, dcon::state_definition_id d)
Definition: province.cpp:1014
void for_each_province_in_state_instance(sys::state &state, dcon::state_instance_id s, F const &func)
bool can_build_province_building(sys::state &state, dcon::province_id id, dcon::nation_id n, economy::province_building_type t)
Definition: province.cpp:418
bool can_integrate_colony(sys::state &state, dcon::state_instance_id id)
Definition: province.cpp:593
bool state_is_coastal(sys::state &state, dcon::state_instance_id s)
Definition: province.cpp:1476
bool can_build_fort(sys::state &state, dcon::province_id id, dcon::nation_id n)
Definition: province.cpp:370
bool can_start_colony(sys::state &state, dcon::nation_id n, dcon::state_definition_id d)
Definition: province.cpp:1097
void update_cached_values(sys::state &state)
Definition: province.cpp:255
std::vector< dcon::province_id > make_naval_path(sys::state &state, dcon::province_id start, dcon::province_id end)
Definition: province.cpp:1848
std::vector< dcon::province_id > make_unowned_land_path(sys::state &state, dcon::province_id start, dcon::province_id end)
Definition: province.cpp:1798
bool can_invest_in_colony(sys::state &state, dcon::nation_id n, dcon::state_definition_id d)
Definition: province.cpp:1023
bool has_naval_access_to_province(sys::state &state, dcon::nation_id nation_as, dcon::province_id prov)
Definition: province.cpp:1570
bool can_build_naval_base(sys::state &state, dcon::province_id id, dcon::nation_id n)
Definition: province.cpp:391
void change_province_owner(sys::state &state, dcon::province_id id, dcon::nation_id new_owner)
Definition: province.cpp:666
void increase_colonial_investment(sys::state &state, dcon::nation_id source, dcon::state_definition_id state_def)
Definition: province.cpp:1323
void suppress_movement(sys::state &state, dcon::nation_id n, dcon::movement_id m)
Definition: rebels.cpp:129
dcon::movement_id get_movement_by_independence(sys::state &state, dcon::nation_id n, dcon::national_identity_id i)
Definition: rebels.cpp:21
float get_suppression_point_cost(sys::state &state, dcon::movement_id m)
Definition: rebels.cpp:1168
dcon::movement_id get_movement_by_position(sys::state &state, dcon::nation_id n, dcon::issue_option_id o)
Definition: rebels.cpp:14
Definition: prng.cpp:6
void toggle_modifier_from_province(sys::state &state, dcon::province_id target_prov, dcon::modifier_id mod_id, sys::date expiration)
Definition: modifiers.cpp:109
uint8_t * write_save_section(uint8_t *ptr_in, sys::state &state)
uint8_t const * read_save_section(uint8_t const *ptr_in, uint8_t const *section_end, sys::state &state)
void write_save_file(sys::state &state, save_type type, std::string const &name)
std::string resolve_string_substitution(sys::state &state, dcon::text_key source_text, substitution_map const &mp)
Definition: text.cpp:2113
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
Definition: text.cpp:1899
void add_to_substitution_map(substitution_map &mp, variable_type key, substitution value)
Definition: text.cpp:1068
ankerl::unordered_dense::map< uint32_t, substitution > substitution_map
Definition: text.hpp:794
int32_t to_generic(dcon::province_id v)
Definition: triggers.hpp:12
bool evaluate(sys::state &state, dcon::trigger_key key, int32_t primary, int32_t this_slot, int32_t from_slot)
Definition: triggers.cpp:5865
std::string format_fif_value(sys::state &state, int64_t data, int32_t type)
void effect_description(sys::state &state, text::layout_base &layout, dcon::effect_key k, int32_t primary_slot, int32_t this_slot, int32_t from_slot, uint32_t r_lo, uint32_t r_hi)
constexpr uint32_t max_chat_message_len
Definition: constants.hpp:586
void initialize_console_fif_environment(sys::state &state)
void close_window(sys::state &game_state)
Definition: window_nix.cpp:101
uint uint32_t
uchar uint8_t
@ ident
sys::checksum_key checksum
Definition: commands.hpp:439
dcon::province_id dest
Definition: commands.hpp:367
dcon::nation_id target
Definition: commands.hpp:283
dcon::nation_id target
Definition: commands.hpp:431
char body[ui::max_chat_message_len]
Definition: commands.hpp:430
dcon::national_identity_id cb_tag
Definition: commands.hpp:351
dcon::state_definition_id cb_state
Definition: commands.hpp:350
dcon::nation_id cb_secondary_nation
Definition: commands.hpp:352
dcon::decision_id d
Definition: commands.hpp:268
dcon::nation_id target
Definition: commands.hpp:167
dcon::state_instance_id location
Definition: commands.hpp:161
dcon::factory_type_id type
Definition: commands.hpp:162
dcon::province_id location
Definition: commands.hpp:190
dcon::factory_type_id type
Definition: commands.hpp:191
dcon::nation_id influence_target
Definition: commands.hpp:201
dcon::nation_id influence_target
Definition: commands.hpp:206
dcon::issue_option_id r
Definition: commands.hpp:233
dcon::land_battle_id b
Definition: commands.hpp:402
dcon::nation_id from
Definition: commands.hpp:272
diplomatic_message::type type
Definition: commands.hpp:273
dcon::national_identity_id tag
Definition: commands.hpp:221
dcon::issue_option_id iopt
Definition: commands.hpp:220
dcon::nation_id target
Definition: commands.hpp:435
dcon::national_focus_id focus
Definition: commands.hpp:140
dcon::state_instance_id target_state
Definition: commands.hpp:139
dcon::naval_battle_id b
Definition: commands.hpp:398
dcon::province_id dest
Definition: commands.hpp:373
dcon::gui_def_id button
Definition: commands.hpp:134
dcon::nation_id id
Definition: commands.hpp:135
dcon::nation_id target
Definition: commands.hpp:357
dcon::nation_id target
Definition: commands.hpp:330
dcon::cb_type_id primary_cb
Definition: commands.hpp:334
dcon::state_definition_id cb_state
Definition: commands.hpp:331
dcon::national_identity_id cb_tag
Definition: commands.hpp:332
dcon::nation_id cb_secondary_nation
Definition: commands.hpp:333
dcon::cb_type_id cb_type
Definition: commands.hpp:344
dcon::state_definition_id cb_state
Definition: commands.hpp:340
dcon::nation_id target
Definition: commands.hpp:339
dcon::nation_id cb_secondary_nation
Definition: commands.hpp:342
dcon::national_identity_id cb_tag
Definition: commands.hpp:341
sys::checksum_key checksum
Definition: commands.hpp:449
command_type type
Definition: commands.hpp:521
union command::payload::dtype data
dcon::nation_id source
Definition: commands.hpp:520
dcon::gui_def_id button
Definition: commands.hpp:130
dcon::province_id id
Definition: commands.hpp:131
dcon::free_national_event_id e
Definition: commands.hpp:302
dcon::free_provincial_event_id e
Definition: commands.hpp:319
dcon::national_event_id e
Definition: commands.hpp:293
dcon::provincial_event_id e
Definition: commands.hpp:310
dcon::political_party_id p
Definition: commands.hpp:225
dcon::province_id location
Definition: commands.hpp:156
economy::province_building_type type
Definition: commands.hpp:157
dcon::province_id location
Definition: commands.hpp:177
dcon::reform_option_id r
Definition: commands.hpp:229
dcon::regiment_id regs[num_packed_units]
Definition: commands.hpp:408
dcon::ship_id ships[num_packed_units]
Definition: commands.hpp:411
dcon::technology_id tech
Definition: commands.hpp:144
dcon::state_definition_id state
Definition: commands.hpp:279
dcon::national_identity_id ident
Definition: commands.hpp:197
static constexpr uint32_t set_size
dcon::free_national_event_id e
Definition: events.hpp:38
dcon::province_id p
Definition: events.hpp:73
dcon::free_provincial_event_id e
Definition: events.hpp:72
dcon::national_event_id e
Definition: events.hpp:19
dcon::province_id p
Definition: events.hpp:55
dcon::provincial_event_id e
Definition: events.hpp:54
save_game_data save_game
Definition: commands.hpp:509
war_target_data war_target
Definition: commands.hpp:471
influence_priority_data influence_priority
Definition: commands.hpp:469
rally_point_data rally_point
Definition: commands.hpp:505
new_general_data new_general
Definition: commands.hpp:501
pending_human_p_event_data pending_human_p_event
Definition: commands.hpp:481
call_to_arms_data call_to_arms
Definition: commands.hpp:486
naval_battle_data naval_battle
Definition: commands.hpp:498
pending_human_f_p_event_data pending_human_f_p_event
Definition: commands.hpp:482
army_movement_data army_movement
Definition: commands.hpp:492
generic_location_data generic_location
Definition: commands.hpp:470
budget_settings_data budget_data
Definition: commands.hpp:467
split_regiments_data split_regiments
Definition: commands.hpp:496
new_admiral_data new_admiral
Definition: commands.hpp:502
split_ships_data split_ships
Definition: commands.hpp:497
land_battle_data land_battle
Definition: commands.hpp:499
nation_pick_data nation_pick
Definition: commands.hpp:503
state_transfer_data state_transfer
Definition: commands.hpp:485
national_focus_data nat_focus
Definition: commands.hpp:457
message_data message
Definition: commands.hpp:484
influence_action_data influence_action
Definition: commands.hpp:468
crisis_invitation_data crisis_invitation
Definition: commands.hpp:500
pending_human_f_n_event_data pending_human_f_n_event
Definition: commands.hpp:480
naval_unit_construction_data naval_unit_construction
Definition: commands.hpp:463
movement_data movement
Definition: commands.hpp:472
new_war_goal_data new_war_goal
Definition: commands.hpp:488
province_building_data start_province_building
Definition: commands.hpp:460
crisis_join_data crisis_join
Definition: commands.hpp:476
chat_message_data chat_message
Definition: commands.hpp:504
factory_data factory
Definition: commands.hpp:466
political_party_data political_party
Definition: commands.hpp:473
new_offer_data new_offer
Definition: commands.hpp:489
pending_human_n_event_data pending_human_n_event
Definition: commands.hpp:479
diplo_action_data diplo_action
Definition: commands.hpp:461
nbutton_data nbutton
Definition: commands.hpp:515
new_war_data new_war
Definition: commands.hpp:487
stockpile_settings_data stockpile_settings
Definition: commands.hpp:477
notify_reload_data notify_reload
Definition: commands.hpp:511
advance_tick_data advance_tick
Definition: commands.hpp:508
navy_movement_data navy_movement
Definition: commands.hpp:493
factory_building_data start_factory_building
Definition: commands.hpp:462
land_unit_construction_data land_unit_construction
Definition: commands.hpp:464
make_leader_data make_leader
Definition: commands.hpp:459
notify_save_loaded_data notify_save_loaded
Definition: commands.hpp:510
offer_wargoal_data offer_wargoal
Definition: commands.hpp:490
tag_target_data tag_target
Definition: commands.hpp:465
start_research_data start_research
Definition: commands.hpp:458
cb_fabrication_data cb_fabrication
Definition: commands.hpp:483
notify_leaves_data notify_leave
Definition: commands.hpp:514
decision_data decision
Definition: commands.hpp:478
merge_navy_data merge_navy
Definition: commands.hpp:495
reform_selection_data reform_selection
Definition: commands.hpp:474
sys::player_name player_name
Definition: commands.hpp:512
merge_army_data merge_army
Definition: commands.hpp:494
pbutton_data pbutton
Definition: commands.hpp:516
issue_selection_data issue_selection
Definition: commands.hpp:475