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
40 auto first_wg = state.crisis_attacker_wargoals.at(0);
42 text::add_to_substitution_map(m, text::variable_type::crisistaker_adj, state.world.national_identity_get_adjective(first_wg.wg_tag));
43 text::add_to_substitution_map(m, text::variable_type::crisistaker_capital, state.world.national_identity_get_capital(first_wg.wg_tag));
44 text::add_to_substitution_map(m, text::variable_type::crisistaker_continent, state.world.national_identity_get_capital(first_wg.wg_tag).get_continent().get_name());
46 text::add_to_substitution_map(m, text::variable_type::crisisattacker_capital, state.world.nation_get_capital(state.primary_crisis_attacker));
47 text::add_to_substitution_map(m, text::variable_type::crisisattacker_continent, state.world.nation_get_capital(state.primary_crisis_attacker).get_continent().get_name());
49 text::add_to_substitution_map(m, text::variable_type::crisisdefender_capital, state.world.nation_get_capital(state.primary_crisis_defender));
50 text::add_to_substitution_map(m, text::variable_type::crisisdefender_continent, state.world.nation_get_capital(state.primary_crisis_defender).get_continent().get_name());
55 // TODO: Is this correct? I remember in vanilla it could vary
56 auto pc = state.world.nation_get_primary_culture(n);
58 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());
59 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());
61 auto names_pair = rng::get_random_pair(state, uint32_t(n.index()) << 6, uint32_t(pc.id.index()));
62 auto first_names = state.world.culture_get_first_names(state.world.nation_get_primary_culture(n));
63 if(first_names.size() > 0) {
64 auto first_name = first_names.at(rng::reduce(uint32_t(names_pair.high), first_names.size()));
65 auto last_names = state.world.culture_get_last_names(state.world.nation_get_primary_culture(n));
66 if(last_names.size() > 0) {
67 auto last_name = last_names.at(rng::reduce(uint32_t(names_pair.high), last_names.size()));
70 }
71 }
72 text::add_to_substitution_map(m, text::variable_type::tech, state.world.nation_get_current_research(n).get_name());
74 if(auto plist = state.world.nation_get_province_ownership(n); plist.begin() != plist.end()) {
75 auto plist_size = uint32_t(plist.end() - plist.begin());
76 uint32_t index = rng::reduce(uint32_t(names_pair.high), plist_size);
77 text::add_to_substitution_map(m, text::variable_type::anyprovince, (*(plist.begin() + index)).get_province());
78 }
79}
80
82public:
85 }
86
87 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
88 auto id = retrieve<dcon::decision_id>(state, parent);
89 auto condition = state.world.decision_get_allow(id);
90 if(condition)
91 trigger_description(state, contents, condition, trigger::to_generic(state.local_player_nation), trigger::to_generic(state.local_player_nation), -1);
92 }
93};
94
96public:
99 }
100
101 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
102 auto id = retrieve<dcon::decision_id>(state, parent);
103 text::add_line(state, contents, "alice_ai_decision");
104 auto mkey = state.world.decision_get_ai_will_do(id);
105 if(mkey)
106 multiplicative_value_modifier_description(state, contents, mkey, trigger::to_generic(state.local_player_nation), trigger::to_generic(state.local_player_nation), -1);
107 }
108};
109
111public:
114 }
115
116 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
117 auto id = retrieve<dcon::decision_id>(state, parent);
118 auto potential = state.world.decision_get_potential(id);
119 if(potential)
120 trigger_description(state, contents, potential, trigger::to_generic(state.local_player_nation), trigger::to_generic(state.local_player_nation), -1);
121 }
122};
123
125public:
128 }
129
130 void button_action(sys::state& state) noexcept override {
131 auto content = retrieve<dcon::decision_id>(state, parent);
132 command::take_decision(state, state.local_player_nation, content);
133 }
134
135 void on_update(sys::state& state) noexcept override {
136 auto content = retrieve<dcon::decision_id>(state, parent);
137 disabled = !command::can_take_decision(state, state.local_player_nation, content);
138 }
139
142 }
143
144 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
145 auto id = retrieve<dcon::decision_id>(state, parent);
146
147 auto fat_id = dcon::fatten(state.world, id);
148 auto box = text::open_layout_box(contents);
150 produce_decision_substitutions(state, m, state.local_player_nation);
151 text::add_to_layout_box(state, contents, box, fat_id.get_name(), m);
152 text::close_layout_box(contents, box);
153
154 auto ef = fat_id.get_effect();
155 if(bool(ef))
156 effect_description(state, contents, ef, trigger::to_generic(state.local_player_nation),
157 trigger::to_generic(state.local_player_nation), -1, uint32_t(state.current_date.value),
158 uint32_t(state.local_player_nation.index() << 4 ^ id.index()));
159 }
160
161};
162
163// -------------
164// Decision Name
165// -------------
166
168public:
169 void on_update(sys::state& state) noexcept override {
170 auto id = retrieve<dcon::decision_id>(state, parent);
172 auto box = text::open_layout_box(contents);
174 produce_decision_substitutions(state, m, state.local_player_nation);
175 text::add_to_layout_box(state, contents, box, state.world.decision_get_name(id), m);
176 text::close_layout_box(contents, box);
177 }
178
181 }
182
183 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
184 auto const id = retrieve<dcon::decision_id>(state, parent);
185 if(state.cheat_data.show_province_id_tooltip) {
186 auto box = text::open_layout_box(contents);
187 text::add_to_layout_box(state, contents, box, std::string_view("Decision ID:"));
188 text::add_space_to_layout_box(state, contents, box);
189 text::add_to_layout_box(state, contents, box, std::to_string(id.value));
190 text::close_layout_box(contents, box);
191 }
192 auto const desc = state.world.decision_get_description(id);
193 if(state.key_is_localized(desc)) {
194 auto box = text::open_layout_box(contents);
196 produce_decision_substitutions(state, m, state.local_player_nation);
197 text::add_to_layout_box(state, contents, box, desc, m);
198 text::close_layout_box(contents, box);
199 }
200 }
201};
202
203// --------------
204// Decision Image
205// --------------
206
208public:
209 bool get_horizontal_flip(sys::state& state) noexcept override {
210 return false; //never flip
211 }
212 void on_update(sys::state& state) noexcept override {
213 auto id = retrieve<dcon::decision_id>(state, parent);
214 auto fat_id = dcon::fatten(state.world, id);
215 base_data.data.image.gfx_object = fat_id.get_image();
216 }
217};
218
219// --------------------
220// Decision Description
221// --------------------
222
224private:
225 dcon::text_key description;
226 void populate_layout(sys::state& state, text::endless_layout& contents) noexcept {
227 auto box = text::open_layout_box(contents);
229 produce_decision_substitutions(state, m, state.local_player_nation);
230 text::add_to_layout_box(state, contents, box, description, m);
231 text::close_layout_box(contents, box);
232 }
233
234public:
235 void on_create(sys::state& state) noexcept override {
236 base_data.size.y = 76;
238 }
239
240 void on_update(sys::state& state) noexcept override {
241 auto id = retrieve<dcon::decision_id>(state, parent);
242 auto fat_id = dcon::fatten(state.world, id);
243 description = fat_id.get_description();
245 text::layout_parameters{0, 0, static_cast<int16_t>(base_data.size.x), static_cast<int16_t>(base_data.size.y),
246 base_data.data.text.font_handle, 0, text::alignment::left,
247 text::is_black_from_font_id(base_data.data.text.font_handle) ? text::text_color::black : text::text_color::white,
248 false});
249 populate_layout(state, container);
251 }
252 message_result test_mouse(sys::state& state, int32_t x, int32_t y, mouse_probe_type type) noexcept override {
253 // Ignore mouse wheel scrolls so people DO NOT get confused!
257 }
258};
259
260// ---------------
261// Ignore Checkbox
262// ---------------
263
265public:
266 void button_action(sys::state& state) noexcept override {
267 auto id = retrieve<dcon::decision_id>(state, parent);
268 if(bool(id)) {
269 state.world.decision_set_hide_notification(id, !state.world.decision_get_hide_notification(id));
270 state.game_state_updated.store(true, std::memory_order_release);
271 }
272 }
273
274 bool is_active(sys::state& state) noexcept override {
275 auto id = retrieve<dcon::decision_id>(state, parent);
276 return !state.world.decision_get_hide_notification(id);
277 }
278
281 }
282
283 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
284 text::add_line(state, contents, "hide_decision");
285 }
286};
287
288// -------------
289// Decision Item
290// -------------
291
292class decision_item : public listbox_row_element_base<dcon::decision_id> {
293public:
294 std::unique_ptr<ui::element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
295 if(name == "decision_name") {
296 return make_element_by_type<decision_name>(state, id);
297 } else if(name == "decision_image") {
298 return make_element_by_type<decision_image>(state, id);
299 } else if(name == "decision_desc") {
300 return make_element_by_type<decision_desc>(state, id);
301 } else if(name == "requirements") {
302 // Extra button to tell if AI will do
303#ifndef NDebug
304 auto btn1 = make_element_by_type<decision_ai_will_do>(state, id);
305 btn1->base_data.position.x -= btn1->base_data.size.x * 2;
306 add_child_to_front(std::move(btn1));
307#endif
308 auto btn2 = make_element_by_type<decision_potential>(state, id);
309 btn2->base_data.position.x -= btn2->base_data.size.x;
310 add_child_to_front(std::move(btn2));
311 return make_element_by_type<decision_requirements>(state, id);
312 } else if(name == "ignore_checkbox") {
313 return make_element_by_type<ignore_checkbox>(state, id);
314 } else if(name == "make_decision") {
315 return make_element_by_type<make_decision>(state, id);
316 } else {
317 return nullptr;
318 }
319 }
320
321 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
322 if(payload.holds_type<dcon::decision_id>()) {
323 payload.emplace<dcon::decision_id>(content);
325 } else if(payload.holds_type<wrapped_listbox_row_content<dcon::decision_id>>()) {
327 } else {
329 }
330 }
331};
332
333// ----------------
334// Decision Listbox
335// ----------------
336
337class decision_listbox : public listbox_element_base<decision_item, dcon::decision_id> {
338protected:
339 std::string_view get_row_element_name() override {
340 return "decision_entry";
341 }
342private:
343 std::vector<dcon::decision_id> get_decisions(sys::state& state) {
344 std::vector<dcon::decision_id> list;
345 auto n = state.local_player_nation;
346 for(uint32_t i = state.world.decision_size(); i-- > 0;) {
347 dcon::decision_id did{ dcon::decision_id::value_base_t(i) };
348 if(!state.cheat_data.always_potential_decisions) {
349 auto lim = state.world.decision_get_potential(did);
350 if(!lim || trigger::evaluate(state, lim, trigger::to_generic(n), trigger::to_generic(n), 0)) {
351 list.push_back(did);
352 }
353 } else {
354 list.push_back(did);
355 }
356 }
357
358 std::sort(list.begin(), list.end(), [&](dcon::decision_id a, dcon::decision_id b) {
359 auto allow_a = state.world.decision_get_allow(a);
360 auto allow_b = state.world.decision_get_allow(b);
361 auto a_res = !allow_a || trigger::evaluate(state, allow_a, trigger::to_generic(n), trigger::to_generic(n), 0);
362 auto b_res = !allow_b || trigger::evaluate(state, allow_b, trigger::to_generic(n), trigger::to_generic(n), 0);
363 if(a_res != b_res)
364 return a_res;
365 else
366 return a.index() < b.index();
367 });
368
369 return list;
370 }
371public:
372 void on_update(sys::state& state) noexcept override {
373 row_contents = get_decisions(state);
374 update(state);
375 }
376};
377
378// ----------------
379// Decision Window
380// ----------------
381
383public:
384 void on_create(sys::state& state) noexcept override {
386 set_visible(state, false);
387 }
388
389 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
390 if(name == "decision_listbox") {
391 return make_element_by_type<decision_listbox>(state, id);
392 } else {
393 return nullptr;
394 }
395 }
396};
397
398} // 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:2052
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:1823
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:1923
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:797
void add_space_to_layout_box(sys::state &state, layout_base &dest, layout_box &box)
Definition: text.cpp:1812
void close_layout_box(columnar_layout &dest, layout_box &box)
Definition: text.cpp:1831
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
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
Holds important data about the game world, state, and other data regarding windowing,...
union ui::element_data::internal_data data
dcon::gfx_object_id gfx_object