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