Project Alice
Loading...
Searching...
No Matches
diplomatic_messages.cpp
Go to the documentation of this file.
2#include "system_state.hpp"
3#include "commands.hpp"
4#include "nations.hpp"
5#include "ai.hpp"
6
8
9void decline(sys::state& state, message const& m) {
10 switch(m.type) {
11 case type::none:
12 break;
14 if(!command::can_ask_for_access(state, m.from, m.to))
15 return;
16
17 nations::adjust_relationship(state, m.from, m.to, state.defines.askmilaccess_relation_on_decline);
18
20 [source = m.from, target = m.to](sys::state& state, text::layout_base& contents) {
21 text::add_line(state, contents, "msg_access_refused_1", text::variable_type::x, target, text::variable_type::y, source);
22 },
23 "msg_access_refused_title",
24 m.to, m.from, dcon::nation_id{},
26 });
27 break;
29 if(!command::can_ask_for_alliance(state, m.from, m.to))
30 return;
31
32 nations::adjust_relationship(state, m.from, m.to, state.defines.alliance_relation_on_decline);
33
35 [from = m.from, to = m.to](sys::state& state, text::layout_base& contents) {
36 text::add_line(state, contents, "msg_alliance_declined_1", text::variable_type::x, to, text::variable_type::y, from);
37 },
38 "msg_alliance_declined_title",
39 m.to, m.from, dcon::nation_id{},
41 });
42 break;
44 if(!command::can_call_to_arms(state, m.from, m.to, m.data.war))
45 return;
46
47 nations::adjust_relationship(state, m.from, m.to, state.defines.callally_relation_on_decline);
48 auto was_defensive = false;
49 for(auto wp : state.world.war_get_war_participant(m.data.war)) {
50 if(wp.get_nation() == m.from) {
51 was_defensive = !wp.get_is_attacker();
52 break;
53 }
54 }
55 if(was_defensive) {
56 auto rel = state.world.get_diplomatic_relation_by_diplomatic_pair(m.from, m.to);
57 if(rel && state.world.diplomatic_relation_get_are_allied(rel)) {
58 state.world.diplomatic_relation_set_are_allied(rel, false);
59
61 [from = m.from, to = m.to](sys::state& state, text::layout_base& contents) {
62 text::add_line(state, contents, "msg_alliance_ends_1", text::variable_type::x, to, text::variable_type::y, from);
63 },
64 "msg_alliance_ends_title",
65 m.to, m.from, dcon::nation_id{},
67 });
68 }
69 }
70
72 [from = m.from, to = m.to, pa = state.world.war_get_primary_attacker(m.data.war), pd = state.world.war_get_primary_defender(m.data.war), name = state.world.war_get_name(m.data.war), tag = state.world.war_get_over_tag(m.data.war), st = state.world.war_get_over_state(m.data.war)](sys::state& state, text::layout_base& contents) {
73 text::substitution_map sub;
74 text::add_to_substitution_map(sub, text::variable_type::order, std::string_view(""));
75 text::add_to_substitution_map(sub, text::variable_type::second, text::get_adjective(state, pd));
76 text::add_to_substitution_map(sub, text::variable_type::second_country, pd);
77 text::add_to_substitution_map(sub, text::variable_type::first, text::get_adjective(state, pa));
78 text::add_to_substitution_map(sub, text::variable_type::third, tag);
79 text::add_to_substitution_map(sub, text::variable_type::state, st);
80
81 std::string resolved_war_name = text::resolve_string_substitution(state, name, sub);
82 text::add_line(state, contents, "msg_ally_call_decline_1", text::variable_type::x, to, text::variable_type::y, from, text::variable_type::val, std::string_view{resolved_war_name});
83 },
84 "msg_ally_call_declined_title",
85 m.to, m.from, dcon::nation_id{},
87 });
88
89 break;
90 }
93 break;
96 break;
98 military::reject_peace_offer(state, m.data.peace);
99 break;
102 [source = m.from, target = m.to](sys::state& state, text::layout_base& contents) {
103 text::add_line(state, contents, "msg_crisis_joffer_reject_1", text::variable_type::x, target, text::variable_type::y, source);
104
105 },
106 "msg_crisis_joffer_rejected",
107 m.to, m.from, dcon::nation_id{},
109 });
110 break;
112 // TODO: notify rejected
113 /*
114 Crisis resolution offers function much in the same way as peace offers. Every refused crisis offer increases the temperature
115 of the current crisis by define:CRISIS_TEMPERATURE_ON_OFFER_DECLINE.
116 */
117 state.crisis_temperature += state.defines.crisis_temperature_on_offer_decline;
118 nations::cleanup_crisis_peace_offer(state, m.data.peace);
119
121 [source = m.from, target = m.to](sys::state& state, text::layout_base& contents) {
122 text::add_line(state, contents, "msg_crisis_not_settled_1", text::variable_type::x, target, text::variable_type::y, source);
123
124 },
125 "msg_crisis_not_settled_title",
126 m.to, m.from, dcon::nation_id{},
128 });
129
130 break;
132 break;
133 }
134}
135
136bool can_accept_crisis_offer(sys::state& state, dcon::nation_id from, dcon::nation_id to, sys::crisis_join_offer const& offer) {
137 if(state.current_crisis_mode != sys::crisis_mode::heating_up)
138 return false;
139 if(from != state.primary_crisis_attacker && from != state.primary_crisis_defender)
140 return false;
141
142 if(to == offer.target || from == offer.target)
143 return false;
144
145 // to must be merely interested participant
146 for(auto& par : state.crisis_participants) {
147 if(!par.id) {
148 return false; // not in crisis
149 }
150 if(par.id == to) {
151 if(par.merely_interested == false)
152 return false; // already in crisis
153 break;
154 }
155 }
156
157 // target must be in crisis
158 for(auto& par : state.crisis_participants) {
159 if(!par.id) {
160 return false; // not in crisis
161 }
162 if(par.id == offer.target) {
163 if(par.merely_interested)
164 return false;
165 if(par.supports_attacker && from == state.primary_crisis_attacker)
166 return false;
167 if(!par.supports_attacker && from == state.primary_crisis_defender)
168 return false;
169
170 break;
171 }
172 }
173
174 auto cb_type = state.world.cb_type_get_type_bits(offer.wargoal_type);
175 if((cb_type & military::cb_flag::always) == 0 && (cb_type & military::cb_flag::is_not_constructing_cb) != 0)
176 return false;
177
180
181 return false;
182 }
183
184 return true;
185}
186
187void add_to_crisis_with_offer(sys::state& state, dcon::nation_id from, dcon::nation_id to, sys::crisis_join_offer const& offer) {
188
189 for(auto& par : state.crisis_participants) {
190 if(!par.id) {
191 return; // not in crisis
192 }
193 if(par.id == to) {
194 par.merely_interested = false;
195 par.supports_attacker = (from == state.primary_crisis_attacker);
196 par.joined_with_offer = offer;
197 break;
198 }
199 }
200
201 auto infamy = military::crisis_cb_addition_infamy_cost(state, offer.wargoal_type, to, offer.target) *
202 state.defines.crisis_wargoal_infamy_mult;
203 state.world.nation_get_infamy(from) += infamy;
204}
205
206bool can_accept_crisis_peace_offer(sys::state& state, dcon::nation_id from, dcon::nation_id to, dcon::peace_offer_id peace) {
207 if(state.current_crisis_mode != sys::crisis_mode::heating_up)
208 return false;
209 if(from != state.primary_crisis_attacker && from != state.primary_crisis_defender)
210 return false;
211 if(to != state.primary_crisis_attacker && to != state.primary_crisis_defender)
212 return false;
213 if(from == to)
214 return false;
215
216 // check: all goals in offer are part of the crisis
217 for(auto wg : state.world.peace_offer_get_peace_offer_item(peace)) {
218 bool found = [&]() {
219 for(auto& par : state.crisis_participants) {
220 if(!par.id) {
221 return false; // not in crisis
222 }
223 if(par.id == wg.get_wargoal().get_added_by()) {
224 if(wg.get_wargoal().get_associated_state() == par.joined_with_offer.wargoal_state &&
225 wg.get_wargoal().get_associated_tag() == par.joined_with_offer.wargoal_tag &&
226 wg.get_wargoal().get_secondary_nation() == par.joined_with_offer.wargoal_secondary_nation &&
227 wg.get_wargoal().get_target_nation() == par.joined_with_offer.target &&
228 wg.get_wargoal().get_type() == par.joined_with_offer.wargoal_type)
229 return true;
230 else
231 return false;
232 }
233 }
234 return false;
235 }();
236
237 if(!found) {
238 if(wg.get_wargoal().get_added_by() == state.primary_crisis_attacker) {
239 if(state.current_crisis == sys::crisis_type::colonial) {
240 auto colonizers = state.world.state_definition_get_colonization(state.crisis_colony);
241 auto num_colonizers = colonizers.end() - colonizers.begin();
242 if(num_colonizers >= 2) {
243 auto col_a = (*colonizers.begin()).get_colonizer();
244 auto col_b = (*(colonizers.begin() + 1)).get_colonizer();
245
246 if(wg.get_wargoal().get_associated_state() == state.crisis_colony &&
247 wg.get_wargoal().get_type() == state.military_definitions.crisis_colony &&
248 ((wg.get_wargoal().get_added_by() == col_a && wg.get_wargoal().get_target_nation() == col_b) ||
249 (wg.get_wargoal().get_added_by() == col_b && wg.get_wargoal().get_target_nation() == col_a))) {
250
251 found = true;
252 }
253 }
254 } else if(state.current_crisis == sys::crisis_type::liberation) {
255 if(wg.get_wargoal().get_associated_tag() == state.crisis_liberation_tag &&
256 wg.get_wargoal().get_associated_state() == state.world.state_instance_get_definition(state.crisis_state) &&
257 wg.get_wargoal().get_type() == state.military_definitions.crisis_liberate &&
258 wg.get_wargoal().get_target_nation() ==
259 state.world.state_instance_get_nation_from_state_ownership(state.crisis_state)) {
260
261 found = true;
262 }
263 }
264 }
265 }
266
267 if(!found)
268 return false;
269 }
270
271 return true;
272}
273
274bool can_accept(sys::state& state, message const& m) {
275 switch(m.type) {
276 case type::none:
277 return true;
278 case type::access_request:
279 return command::can_ask_for_access(state, m.from, m.to, true);
280 case type::alliance_request:
281 return command::can_ask_for_alliance(state, m.from, m.to, true);
282 case type::call_ally_request:
283 return command::can_call_to_arms(state, m.from, m.to, m.data.war, true);
284 case type::be_crisis_primary_attacker:
285 case type::be_crisis_primary_defender:
286 case type::peace_offer:
287 return true;
288 case type::take_crisis_side_offer:
289 return can_accept_crisis_offer(state, m.from, m.to, m.data.crisis_offer);
290 case type::crisis_peace_offer:
291 return can_accept_crisis_peace_offer(state, m.from, m.to, m.data.peace);
292 case type::state_transfer:
293 return command::can_state_transfer(state, m.from, m.to, m.data.state);
294 }
295 return true;
296}
297
298void accept(sys::state& state, message const& m) {
299 if(!can_accept(state, m))
300 return;
301
302 switch(m.type) {
303 case type::none:
304 break;
305 case type::access_request: {
306 nations::adjust_relationship(state, m.from, m.to, state.defines.askmilaccess_relation_on_accept);
307 auto rel = state.world.get_unilateral_relationship_by_unilateral_pair(m.to, m.from);
308 if(!rel) {
309 rel = state.world.force_create_unilateral_relationship(m.to, m.from);
310 }
311 state.world.unilateral_relationship_set_military_access(rel, true);
312
314 [source = m.from, target = m.to](sys::state& state, text::layout_base& contents) {
315 text::add_line(state, contents, "msg_access_granted_1", text::variable_type::x, target, text::variable_type::y, source);
316 },
317 "msg_access_granted_title",
318 m.to, m.from, dcon::nation_id{},
320 });
321 break;
322 }
323 case type::alliance_request: {
324 nations::adjust_relationship(state, m.from, m.to, state.defines.alliance_relation_on_accept);
325 nations::make_alliance(state, m.from, m.to);
326 break;
327 }
328 case type::call_ally_request: {
329 military::add_to_war(state, m.data.war, m.to, military::is_attacker(state, m.data.war, m.from));
330 nations::adjust_relationship(state, m.from, m.to, state.defines.callally_relation_on_accept);
332 [from = m.from, to = m.to, pa = state.world.war_get_primary_attacker(m.data.war), pd = state.world.war_get_primary_defender(m.data.war), name = state.world.war_get_name(m.data.war), tag = state.world.war_get_over_tag(m.data.war), st = state.world.war_get_over_state(m.data.war)](sys::state& state, text::layout_base& contents) {
333 text::substitution_map sub;
334 text::add_to_substitution_map(sub, text::variable_type::order, std::string_view(""));
335 text::add_to_substitution_map(sub, text::variable_type::second, text::get_adjective(state, pd));
336 text::add_to_substitution_map(sub, text::variable_type::second_country, pd);
337 text::add_to_substitution_map(sub, text::variable_type::first, text::get_adjective(state, pa));
338 text::add_to_substitution_map(sub, text::variable_type::third, tag);
339 text::add_to_substitution_map(sub, text::variable_type::state, st);
340
341 std::string resolved_war_name = text::resolve_string_substitution(state, name, sub);
342 text::add_line(state, contents, "msg_ally_call_accepted_1", text::variable_type::x, to, text::variable_type::y, from, text::variable_type::val, std::string_view{resolved_war_name});
343 },
344 "msg_ally_call_accepted_title",
345 m.to, m.from, dcon::nation_id{},
347 });
348
349 break;
350 }
351 case type::be_crisis_primary_attacker:
353 break;
354 case type::be_crisis_primary_defender:
356 break;
357 case type::peace_offer:
358 military::implement_peace_offer(state, m.data.peace);
359 break;
360 case type::take_crisis_side_offer:
361 add_to_crisis_with_offer(state, m.from, m.to, m.data.crisis_offer);
363 [source = m.from, target = m.to](sys::state& state, text::layout_base& contents) {
364 text::add_line(state, contents, "msg_crisis_joffer_accepted_1", text::variable_type::x, target, text::variable_type::y, source);
365
366 },
367 "msg_crisis_joffer_accepted",
368 m.to, m.from, dcon::nation_id{},
370 });
371 break;
372 case type::crisis_peace_offer:
373 nations::accept_crisis_peace_offer(state, m.from, m.to, m.data.peace);
375 [source = m.from, target = m.to](sys::state& state, text::layout_base& contents) {
376 text::add_line(state, contents, "msg_crisis_settled_1", text::variable_type::x, target, text::variable_type::y, source);
377 },
378 "msg_crisis_settled_title",
379 m.to, m.from, dcon::nation_id{},
381 });
382 break;
383 case type::state_transfer:
384 for(const auto ab : state.world.state_definition_get_abstract_state_membership(m.data.state)) {
385 if(ab.get_province().get_province_ownership().get_nation() == m.from) {
386 province::change_province_owner(state, ab.get_province(), m.to);
387 }
388 }
392 break;
393 }
394}
395
396bool ai_will_accept(sys::state& state, message const& m) {
397 if(state.world.nation_get_is_player_controlled(m.from) && state.cheat_data.always_accept_deals)
398 return true;
399
400 switch(m.type) {
401 case type::none:
402 std::abort();
403 break;
404 case type::access_request:
405 return ai::ai_will_grant_access(state, m.to, m.from);
406 case type::alliance_request:
407 return ai::ai_will_accept_alliance(state, m.to, m.from);
408 case type::call_ally_request:
409 if(!command::can_call_to_arms(state, m.from, m.to, m.data.war, true))
410 return false;
411 return ai::will_join_war(state, m.to, m.data.war, military::get_role(state, m.data.war, m.from) == military::war_role::attacker);
412 case type::be_crisis_primary_defender:
413 return ai::will_be_crisis_primary_defender(state, m.to);
414 case type::be_crisis_primary_attacker:
415 return ai::will_be_crisis_primary_attacker(state, m.to);
416 case type::peace_offer:
417 return ai::will_accept_peace_offer(state, m.to, m.from, m.data.peace);
418 case type::take_crisis_side_offer:
419 return ai::will_join_crisis_with_offer(state, m.to, m.data.crisis_offer);
420 case type::crisis_peace_offer:
421 return ai::will_accept_crisis_peace_offer(state, m.to, m.data.peace);
422 case type::state_transfer:
423 return false;
424 }
425 return false;
426}
427
428void post(sys::state& state, message const& m) {
429 if(state.world.nation_get_is_player_controlled(m.to) == false) {
430 if(ai_will_accept(state, m)) {
431 accept(state, m);
432 } else {
433 decline(state, m);
434 }
435 return;
436 }
437
438 for(auto& i : state.pending_messages) {
439 if(i.type == type::none) {
440 std::memcpy(&i, &m, sizeof(message));
441 i.when = state.current_date;
442
443 if(i.to == state.local_player_nation) {
444 state.new_requests.push(i);
445 }
446
447 return;
448 }
449 }
450}
451
453 for(auto& m : state.pending_messages) {
454 if(m.type != type::none && m.when + expiration_in_days <= state.current_date) {
455
456 decline(state, m);
457 m.type = type::none;
458 }
459 }
460}
461
462} // namespace diplomatic_message
bool ai_will_accept_alliance(sys::state &state, dcon::nation_id target, dcon::nation_id from)
Definition: ai.cpp:275
bool will_accept_peace_offer(sys::state &state, dcon::nation_id n, dcon::nation_id from, dcon::peace_offer_id p)
Definition: ai.cpp:2829
bool ai_will_grant_access(sys::state &state, dcon::nation_id target, dcon::nation_id from)
Definition: ai.cpp:343
bool will_be_crisis_primary_attacker(sys::state &state, dcon::nation_id n)
Definition: ai.cpp:1471
bool will_join_war(sys::state &state, dcon::nation_id n, dcon::war_id w, bool as_attacker)
Definition: ai.cpp:2190
bool will_join_crisis_with_offer(sys::state &state, dcon::nation_id n, sys::crisis_join_offer const &offer)
Definition: ai.cpp:1598
bool will_be_crisis_primary_defender(sys::state &state, dcon::nation_id n)
Definition: ai.cpp:1512
bool will_accept_crisis_peace_offer(sys::state &state, dcon::nation_id to, bool is_concession, bool missing_wg)
Definition: ai.cpp:1890
bool can_state_transfer(sys::state &state, dcon::nation_id asker, dcon::nation_id target, dcon::state_definition_id sid)
Definition: commands.cpp:2375
bool can_call_to_arms(sys::state &state, dcon::nation_id asker, dcon::nation_id target, dcon::war_id w, bool ignore_cost)
Definition: commands.cpp:2430
bool can_ask_for_access(sys::state &state, dcon::nation_id asker, dcon::nation_id target, bool ignore_cost)
Definition: commands.cpp:2222
bool can_ask_for_alliance(sys::state &state, dcon::nation_id asker, dcon::nation_id target, bool ignore_cost)
Definition: commands.cpp:2297
constexpr int32_t expiration_in_days
bool can_accept(sys::state &state, message const &m)
void add_to_crisis_with_offer(sys::state &state, dcon::nation_id from, dcon::nation_id to, sys::crisis_join_offer const &offer)
void decline(sys::state &state, message const &m)
void update_pending(sys::state &state)
void accept(sys::state &state, message const &m)
bool can_accept_crisis_offer(sys::state &state, dcon::nation_id from, dcon::nation_id to, sys::crisis_join_offer const &offer)
void post(sys::state &state, message const &m)
bool can_accept_crisis_peace_offer(sys::state &state, dcon::nation_id from, dcon::nation_id to, dcon::peace_offer_id peace)
bool ai_will_accept(sys::state &state, message const &m)
constexpr uint32_t is_not_constructing_cb
Definition: military.hpp:12
constexpr uint32_t always
Definition: military.hpp:10
void add_to_war(sys::state &state, dcon::war_id w, dcon::nation_id n, bool as_attacker, bool on_war_creation)
Definition: military.cpp:2109
void reject_peace_offer(sys::state &state, dcon::peace_offer_id offer)
Definition: military.cpp:3446
war_role get_role(sys::state const &state, dcon::war_id w, dcon::nation_id n)
Definition: military.cpp:2242
bool is_attacker(sys::state &state, dcon::war_id w, dcon::nation_id n)
Definition: military.cpp:2234
float crisis_cb_addition_infamy_cost(sys::state &state, dcon::cb_type_id type, dcon::nation_id from, dcon::nation_id target)
Definition: military.cpp:1771
bool cb_instance_conditions_satisfied(sys::state &state, dcon::nation_id actor, dcon::nation_id target, dcon::cb_type_id cb, dcon::state_definition_id st, dcon::national_identity_id tag, dcon::nation_id secondary)
Definition: military.cpp:321
void implement_peace_offer(sys::state &state, dcon::peace_offer_id offer)
Definition: military.cpp:3205
void cleanup_crisis_peace_offer(sys::state &state, dcon::peace_offer_id peace)
Definition: nations.cpp:2009
void accept_crisis_peace_offer(sys::state &state, dcon::nation_id from, dcon::nation_id to, dcon::peace_offer_id peace)
Definition: nations.cpp:2017
void reject_crisis_participation(sys::state &state)
Definition: nations.cpp:1948
void make_alliance(sys::state &state, dcon::nation_id a, dcon::nation_id b)
Definition: nations.cpp:1467
void add_as_primary_crisis_defender(sys::state &state, dcon::nation_id n)
Definition: nations.cpp:1890
void add_as_primary_crisis_attacker(sys::state &state, dcon::nation_id n)
Definition: nations.cpp:1904
void update_cached_values(sys::state &state)
Definition: nations.cpp:109
void adjust_relationship(sys::state &state, dcon::nation_id a, dcon::nation_id b, float delta)
Definition: nations.cpp:1094
void post(sys::state &state, message &&m)
void update_connected_regions(sys::state &state)
Definition: province.cpp:29
void update_cached_values(sys::state &state)
Definition: province.cpp:255
void change_province_owner(sys::state &state, dcon::province_id id, dcon::nation_id new_owner)
Definition: province.cpp:666
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
Definition: text.cpp:1899
dcon::national_identity_id wargoal_tag
dcon::state_definition_id wargoal_state
dcon::nation_id wargoal_secondary_nation
dcon::cb_type_id wargoal_type