Project Alice
Loading...
Searching...
No Matches
gui_decision_window.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <vector>
4
6#include "triggers.hpp"
7#include "text.hpp"
8
9namespace ui {
10
18 text::add_to_substitution_map(m, text::variable_type::continentname, state.world.nation_get_capital(n).get_continent().get_name());
19 // Date
20 text::add_to_substitution_map(m, text::variable_type::year, int32_t(state.current_date.to_ymd(state.start_date).year));
21 //text::add_to_substitution_map(m, text::variable_type::month, text::localize_month(state, state.current_date.to_ymd(state.start_date).month));
22 text::add_to_substitution_map(m, text::variable_type::day, int32_t(state.current_date.to_ymd(state.start_date).day));
23 auto sm = state.world.nation_get_in_sphere_of(n);
26 auto smpc = state.world.nation_get_primary_culture(sm);
27 text::add_to_substitution_map(m, text::variable_type::spheremaster_union_adj, smpc.get_group_from_culture_group_membership().get_identity_from_cultural_union_of().get_adjective());
28
29 // Non-vanilla
30 text::add_to_substitution_map(m, text::variable_type::government, state.world.nation_get_government_type(n).get_name());
31 text::add_to_substitution_map(m, text::variable_type::ideology, state.world.nation_get_ruling_party(n).get_ideology().get_name());
32 text::add_to_substitution_map(m, text::variable_type::party, state.world.nation_get_ruling_party(n).get_name());
33 text::add_to_substitution_map(m, text::variable_type::religion, state.world.religion_get_name(state.world.nation_get_religion(n)));
36 text::add_to_substitution_map(m, text::variable_type::spheremaster, state.world.nation_get_in_sphere_of(n));
37 text::add_to_substitution_map(m, text::variable_type::overlord, state.world.overlord_get_ruler(state.world.nation_get_overlord_as_subject(n)));
38 text::add_to_substitution_map(m, text::variable_type::nationalvalue, state.world.nation_get_national_value(n).get_name());
39 // Crisis stuff
41 text::add_to_substitution_map(m, text::variable_type::crisistaker_adj, state.world.national_identity_get_adjective(state.crisis_liberation_tag));
42 text::add_to_substitution_map(m, text::variable_type::crisistaker_capital, state.world.national_identity_get_capital(state.crisis_liberation_tag));
43 text::add_to_substitution_map(m, text::variable_type::crisistaker_continent, state.world.national_identity_get_capital(state.crisis_liberation_tag).get_continent().get_name());
45 text::add_to_substitution_map(m, text::variable_type::crisisattacker_capital, state.world.nation_get_capital(state.primary_crisis_attacker));
46 text::add_to_substitution_map(m, text::variable_type::crisisattacker_continent, state.world.nation_get_capital(state.primary_crisis_attacker).get_continent().get_name());
48 text::add_to_substitution_map(m, text::variable_type::crisisdefender_capital, state.world.nation_get_capital(state.primary_crisis_defender));
49 text::add_to_substitution_map(m, text::variable_type::crisisdefender_continent, state.world.nation_get_capital(state.primary_crisis_defender).get_continent().get_name());
54 // TODO: Is this correct? I remember in vanilla it could vary
55 auto pc = state.world.nation_get_primary_culture(n);
57 text::add_to_substitution_map(m, text::variable_type::culture_group_union, pc.get_group_from_culture_group_membership().get_identity_from_cultural_union_of().get_nation_from_identity_holder());
58 text::add_to_substitution_map(m, text::variable_type::union_adj, pc.get_group_from_culture_group_membership().get_identity_from_cultural_union_of().get_adjective());
60 auto names_pair = rng::get_random_pair(state, uint32_t(n.index()) << 6, uint32_t(pc.id.index()));
61 auto first_names = state.world.culture_get_first_names(state.world.nation_get_primary_culture(n));
62 if(first_names.size() > 0) {
63 auto first_name = first_names.at(rng::reduce(uint32_t(names_pair.high), first_names.size()));
64 auto last_names = state.world.culture_get_last_names(state.world.nation_get_primary_culture(n));
65 if(last_names.size() > 0) {
66 auto last_name = last_names.at(rng::reduce(uint32_t(names_pair.high), last_names.size()));
69 }
70 }
71 text::add_to_substitution_map(m, text::variable_type::tech, state.world.nation_get_current_research(n).get_name());
73 if(auto plist = state.world.nation_get_province_ownership(n); plist.begin() != plist.end()) {
74 auto plist_size = uint32_t(plist.end() - plist.begin());
75 uint32_t index = rng::reduce(uint32_t(names_pair.high), plist_size);
76 text::add_to_substitution_map(m, text::variable_type::anyprovince, (*(plist.begin() + index)).get_province());
77 }
78}
79
81public:
84 }
85
86 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
87 auto id = retrieve<dcon::decision_id>(state, parent);
88 auto condition = state.world.decision_get_allow(id);
89 if(condition)
90 trigger_description(state, contents, condition, trigger::to_generic(state.local_player_nation), trigger::to_generic(state.local_player_nation), -1);
91 }
92};
93
95public:
98 }
99
100 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
101 auto id = retrieve<dcon::decision_id>(state, parent);
102 text::add_line(state, contents, "alice_ai_decision");
103 auto mkey = state.world.decision_get_ai_will_do(id);
104 if(mkey)
105 multiplicative_value_modifier_description(state, contents, mkey, trigger::to_generic(state.local_player_nation), trigger::to_generic(state.local_player_nation), -1);
106 }
107};
108
110public:
113 }
114
115 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
116 auto id = retrieve<dcon::decision_id>(state, parent);
117 auto potential = state.world.decision_get_potential(id);
118 if(potential)
119 trigger_description(state, contents, potential, trigger::to_generic(state.local_player_nation), trigger::to_generic(state.local_player_nation), -1);
120 }
121};
122
124public:
127 }
128
129 void button_action(sys::state& state) noexcept override {
130 auto content = retrieve<dcon::decision_id>(state, parent);
131 command::take_decision(state, state.local_player_nation, content);
132 }
133
134 void on_update(sys::state& state) noexcept override {
135 auto content = retrieve<dcon::decision_id>(state, parent);
136 disabled = !command::can_take_decision(state, state.local_player_nation, content);
137 }
138
141 }
142
143 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
144 auto id = retrieve<dcon::decision_id>(state, parent);
145
146 auto fat_id = dcon::fatten(state.world, id);
147 auto box = text::open_layout_box(contents);
149 produce_decision_substitutions(state, m, state.local_player_nation);
150 text::add_to_layout_box(state, contents, box, fat_id.get_name(), m);
151 text::close_layout_box(contents, box);
152
153 auto ef = fat_id.get_effect();
154 if(bool(ef))
155 effect_description(state, contents, ef, trigger::to_generic(state.local_player_nation),
156 trigger::to_generic(state.local_player_nation), -1, uint32_t(state.current_date.value),
157 uint32_t(state.local_player_nation.index() << 4 ^ id.index()));
158 }
159
160};
161
162// -------------
163// Decision Name
164// -------------
165
167public:
168 void on_update(sys::state& state) noexcept override {
169 auto id = retrieve<dcon::decision_id>(state, parent);
171 auto box = text::open_layout_box(contents);
173 produce_decision_substitutions(state, m, state.local_player_nation);
174 text::add_to_layout_box(state, contents, box, state.world.decision_get_name(id), m);
175 text::close_layout_box(contents, box);
176 }
177
180 }
181
182 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
183 auto const id = retrieve<dcon::decision_id>(state, parent);
184 if(state.cheat_data.show_province_id_tooltip) {
185 auto box = text::open_layout_box(contents);
186 text::add_to_layout_box(state, contents, box, std::string_view("Decision ID:"));
187 text::add_space_to_layout_box(state, contents, box);
188 text::add_to_layout_box(state, contents, box, std::to_string(id.value));
189 text::close_layout_box(contents, box);
190 }
191 auto const desc = state.world.decision_get_description(id);
192 if(state.key_is_localized(desc)) {
193 auto box = text::open_layout_box(contents);
195 produce_decision_substitutions(state, m, state.local_player_nation);
196 text::add_to_layout_box(state, contents, box, desc, m);
197 text::close_layout_box(contents, box);
198 }
199 }
200};
201
202// --------------
203// Decision Image
204// --------------
205
207public:
208 bool get_horizontal_flip(sys::state& state) noexcept override {
209 return false; //never flip
210 }
211 void on_update(sys::state& state) noexcept override {
212 auto id = retrieve<dcon::decision_id>(state, parent);
213 auto fat_id = dcon::fatten(state.world, id);
214 base_data.data.image.gfx_object = fat_id.get_image();
215 }
216};
217
218// --------------------
219// Decision Description
220// --------------------
221
223private:
224 dcon::text_key description;
225 void populate_layout(sys::state& state, text::endless_layout& contents) noexcept {
226 auto box = text::open_layout_box(contents);
228 produce_decision_substitutions(state, m, state.local_player_nation);
229 text::add_to_layout_box(state, contents, box, description, m);
230 text::close_layout_box(contents, box);
231 }
232
233public:
234 void on_create(sys::state& state) noexcept override {
235 base_data.size.y = 76;
237 }
238
239 void on_update(sys::state& state) noexcept override {
240 auto id = retrieve<dcon::decision_id>(state, parent);
241 auto fat_id = dcon::fatten(state.world, id);
242 description = fat_id.get_description();
244 text::layout_parameters{0, 0, static_cast<int16_t>(base_data.size.x), static_cast<int16_t>(base_data.size.y),
245 base_data.data.text.font_handle, 0, text::alignment::left,
246 text::is_black_from_font_id(base_data.data.text.font_handle) ? text::text_color::black : text::text_color::white,
247 false});
248 populate_layout(state, container);
250 }
251 message_result test_mouse(sys::state& state, int32_t x, int32_t y, mouse_probe_type type) noexcept override {
252 // Ignore mouse wheel scrolls so people DO NOT get confused!
256 }
257};
258
259// ---------------
260// Ignore Checkbox
261// ---------------
262
264public:
265 void button_action(sys::state& state) noexcept override {
266 auto id = retrieve<dcon::decision_id>(state, parent);
267 if(bool(id)) {
268 state.world.decision_set_hide_notification(id, !state.world.decision_get_hide_notification(id));
269 state.game_state_updated.store(true, std::memory_order_release);
270 }
271 }
272
273 bool is_active(sys::state& state) noexcept override {
274 auto id = retrieve<dcon::decision_id>(state, parent);
275 return !state.world.decision_get_hide_notification(id);
276 }
277
280 }
281
282 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
283 text::add_line(state, contents, "hide_decision");
284 }
285};
286
287// -------------
288// Decision Item
289// -------------
290
291class decision_item : public listbox_row_element_base<dcon::decision_id> {
292public:
293 std::unique_ptr<ui::element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
294 if(name == "decision_name") {
295 return make_element_by_type<decision_name>(state, id);
296 } else if(name == "decision_image") {
297 return make_element_by_type<decision_image>(state, id);
298 } else if(name == "decision_desc") {
299 return make_element_by_type<decision_desc>(state, id);
300 } else if(name == "requirements") {
301 // Extra button to tell if AI will do
302 auto btn1 = make_element_by_type<decision_ai_will_do>(state, id);
303 btn1->base_data.position.x -= btn1->base_data.size.x * 2;
304 add_child_to_front(std::move(btn1));
305 auto btn2 = make_element_by_type<decision_potential>(state, id);
306 btn2->base_data.position.x -= btn2->base_data.size.x;
307 add_child_to_front(std::move(btn2));
308 return make_element_by_type<decision_requirements>(state, id);
309 } else if(name == "ignore_checkbox") {
310 return make_element_by_type<ignore_checkbox>(state, id);
311 } else if(name == "make_decision") {
312 return make_element_by_type<make_decision>(state, id);
313 } else {
314 return nullptr;
315 }
316 }
317
318 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
319 if(payload.holds_type<dcon::decision_id>()) {
320 payload.emplace<dcon::decision_id>(content);
322 } else if(payload.holds_type<wrapped_listbox_row_content<dcon::decision_id>>()) {
324 } else {
326 }
327 }
328};
329
330// ----------------
331// Decision Listbox
332// ----------------
333
334class decision_listbox : public listbox_element_base<decision_item, dcon::decision_id> {
335protected:
336 std::string_view get_row_element_name() override {
337 return "decision_entry";
338 }
339private:
340 std::vector<dcon::decision_id> get_decisions(sys::state& state) {
341 std::vector<dcon::decision_id> list;
342 auto n = state.local_player_nation;
343 for(uint32_t i = state.world.decision_size(); i-- > 0;) {
344 dcon::decision_id did{ dcon::decision_id::value_base_t(i) };
345 if(!state.cheat_data.always_potential_decisions) {
346 auto lim = state.world.decision_get_potential(did);
347 if(!lim || trigger::evaluate(state, lim, trigger::to_generic(n), trigger::to_generic(n), 0)) {
348 list.push_back(did);
349 }
350 } else {
351 list.push_back(did);
352 }
353 }
354
355 std::sort(list.begin(), list.end(), [&](dcon::decision_id a, dcon::decision_id b) {
356 auto allow_a = state.world.decision_get_allow(a);
357 auto allow_b = state.world.decision_get_allow(b);
358 auto a_res = !allow_a || trigger::evaluate(state, allow_a, trigger::to_generic(n), trigger::to_generic(n), 0);
359 auto b_res = !allow_b || trigger::evaluate(state, allow_b, trigger::to_generic(n), trigger::to_generic(n), 0);
360 if(a_res != b_res)
361 return a_res;
362 else
363 return a.index() < b.index();
364 });
365
366 return list;
367 }
368public:
369 void on_update(sys::state& state) noexcept override {
370 row_contents = get_decisions(state);
371 update(state);
372 }
373};
374
375// ----------------
376// Decision Window
377// ----------------
378
380public:
381 void on_create(sys::state& state) noexcept override {
383 set_visible(state, false);
384 }
385
386 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
387 if(name == "decision_listbox") {
388 return make_element_by_type<decision_listbox>(state, id);
389 } else {
390 return nullptr;
391 }
392 }
393};
394
395} // namespace ui
void add_child_to_front(std::unique_ptr< element_base > child) noexcept final
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
message_result test_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
void on_create(sys::state &state) noexcept override
bool get_horizontal_flip(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
message_result get(sys::state &state, Cyto::Any &payload) noexcept override
std::unique_ptr< ui::element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
void on_update(sys::state &state) noexcept override
std::string_view get_row_element_name() override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
void on_create(sys::state &state) noexcept override
element_base * parent
element_data base_data
void set_visible(sys::state &state, bool vis)
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void button_action(sys::state &state) noexcept override
bool is_active(sys::state &state) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
message_result get(sys::state &state, Cyto::Any &payload) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
sound::audio_instance & get_click_sound(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void button_action(sys::state &state) noexcept override
void calibrate_scrollbar(sys::state &state) noexcept
message_result test_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
void on_create(sys::state &state) noexcept override
multiline_text_element_base * delegate
void on_create(sys::state &state) noexcept override
bool can_take_decision(sys::state &state, dcon::nation_id source, dcon::decision_id d)
Definition: commands.cpp:2023
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
random_pair get_random_pair(sys::state const &state, uint32_t value_in)
Definition: prng.cpp:26
uint32_t reduce(uint32_t value_in, uint32_t upper_bound)
Definition: prng.cpp:46
audio_instance & get_decision_sound(sys::state &state)
Definition: sound_nix.cpp:387
void add_to_layout_box(sys::state &state, layout_base &dest, layout_box &box, embedded_flag ico)
Definition: text.cpp:1165
layout_box open_layout_box(layout_base &dest, int32_t indent)
Definition: text.cpp:1799
endless_layout create_endless_layout(sys::state &state, layout &dest, layout_parameters const &params)
Definition: text.cpp:1100
dcon::text_key get_ruler_title(sys::state &state, dcon::nation_id n)
Definition: text.cpp:899
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
Definition: text.cpp:1899
void add_to_substitution_map(substitution_map &mp, variable_type key, substitution value)
Definition: text.cpp:1068
dcon::text_key get_adjective(sys::state &state, dcon::nation_id id)
Definition: text.cpp:890
ankerl::unordered_dense::map< uint32_t, substitution > substitution_map
Definition: text.hpp:794
void add_space_to_layout_box(sys::state &state, layout_base &dest, layout_box &box)
Definition: text.cpp:1788
void close_layout_box(columnar_layout &dest, layout_box &box)
Definition: text.cpp:1807
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:5810
void multiplicative_value_modifier_description(sys::state &state, text::layout_base &layout, dcon::value_modifier_key modifier, int32_t primary, int32_t this_slot, int32_t from_slot)
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)
tooltip_behavior
void produce_decision_substitutions(sys::state &state, text::substitution_map &m, dcon::nation_id n)
void trigger_description(sys::state &state, text::layout_base &layout, dcon::trigger_key k, int32_t primary_slot=-1, int32_t this_slot=-1, int32_t from_slot=-1)
message_result
uint uint32_t
union ui::element_data::internal_data data
dcon::gfx_object_id gfx_object