Freeciv-3.1
Loading...
Searching...
No Matches
action_dialog.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2005 - Freeciv Development Team
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <gtk/gtk.h>
19
20/* utility */
21#include "astring.h"
22#include "support.h"
23
24/* common */
25#include "actions.h"
26#include "game.h"
27#include "traderoutes.h"
28#include "movement.h"
29#include "research.h"
30#include "unit.h"
31#include "unitlist.h"
32
33/* client */
34#include "dialogs_g.h"
35#include "chatline.h"
36#include "choice_dialog.h"
37#include "client_main.h"
38#include "climisc.h"
39#include "connectdlg_common.h"
40#include "control.h"
41#include "gui_main.h"
42#include "gui_stuff.h"
43#include "mapview.h"
44#include "packhand.h"
45#include "text.h"
46
47/* client/gui-gtk-3.0 */
48#include "citydlg.h"
49#include "dialogs.h"
50#include "unitselextradlg.h"
51#include "unitselunitdlg.h"
52#include "wldlg.h"
53
54/* Locations for non action enabler controlled buttons. */
55#define BUTTON_NEW_UNIT_TGT (ACTION_COUNT + 1)
56#define BUTTON_NEW_EXTRA_TGT (BUTTON_NEW_UNIT_TGT + 1)
57#define BUTTON_LOCATION (BUTTON_NEW_EXTRA_TGT + 1)
58#define BUTTON_WAIT (BUTTON_LOCATION + 1)
59#define BUTTON_CANCEL (BUTTON_WAIT + 1)
60#define BUTTON_COUNT (BUTTON_CANCEL + 1)
61
62#define BUTTON_NOT_THERE -1
63
64
65static GtkWidget *act_sel_dialog;
67
68static int actor_unit_id;
69static int target_ids[ATK_COUNT];
70static int target_extra_id;
72static bool did_not_decide = FALSE;
74
75static GtkWidget *spy_tech_shell;
76
77static GtkWidget *spy_sabotage_shell;
78
79/* A structure to hold parameters for actions inside the GUI instead of
80 * storing the needed data in a global variable. */
91
92/* TODO: maybe this should be in the dialog itself? */
94
95/**********************************************************************/
100 int actor_id,
101 int target_city_id,
102 int target_unit_id,
103 int target_tile_id,
105 int target_tech_id,
106 int tgt_extra_id)
107{
108 struct action_data *data = fc_malloc(sizeof(*data));
109
110 data->act_id = act_id;
111 data->actor_unit_id = actor_id;
117 data->target_extra_id = tgt_extra_id;
118
119 return data;
120}
121
122/**********************************************************************/
127{
129 /* The client isn't waiting for information for any unanswered follow
130 * up questions. */
131
132 struct unit *actor_unit;
133
135 /* The action selection dialog wasn't closed because the actor unit
136 * was lost. */
137
138 /* The probabilities didn't just disappear, right? */
141
143 }
144
146 /* The action selection dialog was closed but only so it can be
147 * redrawn with fresh data. */
148
150 } else {
151 /* The action selection process is over, at least for now. */
153 }
154
155 if (did_not_decide) {
156 /* The action selection dialog was closed but the player didn't
157 * decide what the unit should do. */
158
159 /* Reset so the next action selection dialog does the right thing. */
161 } else {
162 /* An action, or no action at all, was selected. */
165 }
166 }
167}
168
169/**********************************************************************/
174{
175 /* Stop waiting. Move on to the next queued unit. */
178}
179
180/**********************************************************************/
187{
188 /* Stop assuming the answer to a follow up question will arrive. */
190}
191
192/**********************************************************************/
197{
198 /* Don't add an action mapping here unless the non targeted version is
199 * selectable in the targeted version's target selection dialog. */
200 switch ((enum gen_action)tgt_action_id) {
201 case ACTION_SPY_TARGETED_SABOTAGE_CITY:
202 return ACTION_SPY_SABOTAGE_CITY;
203 case ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC:
204 return ACTION_SPY_SABOTAGE_CITY_ESC;
205 case ACTION_SPY_TARGETED_STEAL_TECH:
206 return ACTION_SPY_STEAL_TECH;
207 case ACTION_SPY_TARGETED_STEAL_TECH_ESC:
208 return ACTION_SPY_STEAL_TECH_ESC;
209 default:
210 /* No non targeted version found. */
211 return ACTION_NONE;
212 }
213}
214
215/**********************************************************************/
220{
221 /* Don't add an action mapping here unless the non targeted version is
222 * selectable in the targeted version's target selection dialog. */
223 switch ((enum gen_action)tgt_action_id) {
224 case ACTION_SPY_TARGETED_SABOTAGE_CITY:
225 return ACTION_SPY_SABOTAGE_CITY_PRODUCTION;
226 case ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC:
227 return ACTION_SPY_SABOTAGE_CITY_PRODUCTION_ESC;
228 case ACTION_STRIKE_BUILDING:
229 return ACTION_STRIKE_PRODUCTION;
230 default:
231 /* No non targeted version found. */
232 return ACTION_NONE;
233 }
234}
235
236/**********************************************************************/
240static void simple_action_callback(GtkWidget *w, gpointer data)
241{
242 int actor_id, target_id, sub_target;
243 struct action *paction;
244
245 struct action_data *args = act_sel_dialog_data;
246
247 bool failed = FALSE;
248
249 /* Data */
250 args->act_id = GPOINTER_TO_INT(data);
251 paction = action_by_number(args->act_id);
252
253 /* Actor */
254 fc_assert(action_get_actor_kind(paction) == AAK_UNIT);
255 actor_id = args->actor_unit_id;
256 if (NULL == game_unit_by_number(actor_id)) {
257 /* Probably dead. */
258 failed = TRUE;
259 }
260
261 /* Target */
262 target_id = IDENTITY_NUMBER_ZERO;
263 switch (action_get_target_kind(paction)) {
264 case ATK_CITY:
265 target_id = args->target_city_id;
266 if (NULL == game_city_by_number(target_id)) {
267 /* Probably destroyed. */
268 failed = TRUE;
269 }
270 break;
271 case ATK_UNIT:
272 target_id = args->target_unit_id;
273 if (NULL == game_unit_by_number(target_id)) {
274 /* Probably dead. */
275 failed = TRUE;
276 }
277 break;
278 case ATK_UNITS:
279 case ATK_TILE:
280 case ATK_EXTRAS:
281 target_id = args->target_tile_id;
282 if (NULL == index_to_tile(&(wld.map), target_id)) {
283 /* TODO: Should this be possible at all? If not: add assertion. */
284 failed = TRUE;
285 }
286 break;
287 case ATK_SELF:
288 target_id = IDENTITY_NUMBER_ZERO;
289 break;
290 case ATK_COUNT:
291 fc_assert(action_get_target_kind(paction) != ATK_COUNT);
292 failed = TRUE;
293 }
294
295 /* Sub target. */
296 sub_target = NO_TARGET;
297 if (paction->target_complexity != ACT_TGT_COMPL_SIMPLE) {
298 switch (action_get_sub_target_kind(paction)) {
299 case ASTK_BUILDING:
300 sub_target = args->target_building_id;
301 if (NULL == improvement_by_number(sub_target)) {
302 /* Did the ruleset change? */
303 failed = TRUE;
304 }
305 break;
306 case ASTK_TECH:
307 sub_target = args->target_tech_id;
308 if (NULL == valid_advance_by_number(sub_target)) {
309 /* Did the ruleset change? */
310 failed = TRUE;
311 }
312 break;
313 case ASTK_EXTRA:
314 case ASTK_EXTRA_NOT_THERE:
315 /* TODO: validate if the extra is there? */
316 sub_target = args->target_extra_id;
317 if (NULL == extra_by_number(sub_target)) {
318 /* Did the ruleset change? */
319 failed = TRUE;
320 }
321 break;
322 case ASTK_NONE:
323 case ASTK_COUNT:
324 /* Shouldn't happen. */
325 fc_assert(action_get_sub_target_kind(paction) != ASTK_NONE);
326 failed = TRUE;
327 break;
328 }
329 }
330
331 /* Send request. */
332 if (!failed) {
333 request_do_action(paction->id, actor_id, target_id, sub_target, "");
334 }
335
336 /* Clean up. */
337 gtk_widget_destroy(act_sel_dialog);
338 /* No follow up questions. */
339 act_sel_dialog_data = NULL;
340 FC_FREE(args);
341}
342
343/**********************************************************************/
347static void request_action_details_callback(GtkWidget *w, gpointer data)
348{
349 int actor_id, target_id;
350 struct action *paction;
351
352 struct action_data *args = act_sel_dialog_data;
353
354 bool failed = FALSE;
355
356 /* Data */
357 args->act_id = GPOINTER_TO_INT(data);
358 paction = action_by_number(args->act_id);
359
360 /* Actor */
361 fc_assert(action_get_actor_kind(paction) == AAK_UNIT);
362 actor_id = args->actor_unit_id;
363 if (NULL == game_unit_by_number(actor_id)) {
364 /* Probably dead. */
365 failed = TRUE;
366 }
367
368 /* Target */
369 target_id = IDENTITY_NUMBER_ZERO;
370 switch (action_get_target_kind(paction)) {
371 case ATK_CITY:
372 target_id = args->target_city_id;
373 if (NULL == game_city_by_number(target_id)) {
374 /* Probably destroyed. */
375 failed = TRUE;
376 }
377 break;
378 case ATK_UNIT:
379 target_id = args->target_unit_id;
380 if (NULL == game_unit_by_number(target_id)) {
381 /* Probably dead. */
382 failed = TRUE;
383 }
384 break;
385 case ATK_UNITS:
386 case ATK_TILE:
387 case ATK_EXTRAS:
388 target_id = args->target_tile_id;
389 if (NULL == index_to_tile(&(wld.map), target_id)) {
390 /* TODO: Should this be possible at all? If not: add assertion. */
391 failed = TRUE;
392 }
393 break;
394 case ATK_SELF:
395 target_id = IDENTITY_NUMBER_ZERO;
396 break;
397 case ATK_COUNT:
398 fc_assert(action_get_target_kind(paction) != ATK_COUNT);
399 failed = TRUE;
400 }
401
402 /* Send request. */
403 if (!failed) {
404 request_action_details(paction->id, actor_id, target_id);
405 }
406
407 /* Wait for the server's reply before moving on to the next unit that
408 * needs to know what action to take. */
410
411 /* Clean up. */
412 gtk_widget_destroy(act_sel_dialog);
413 /* No client side follow up questions. */
414 act_sel_dialog_data = NULL;
415 FC_FREE(args);
416}
417
418/**********************************************************************/
421static void found_city_callback(GtkWidget *w, gpointer data)
422{
423 struct action_data *args = act_sel_dialog_data;
424
426 args->actor_unit_id,
427 args->actor_unit_id);
428
429 gtk_widget_destroy(act_sel_dialog);
430 free(args);
431}
432
433/**********************************************************************/
436static void upgrade_callback(GtkWidget *w, gpointer data)
437{
438 struct unit *punit;
439
440 struct action_data *args = act_sel_dialog_data;
441
443 && NULL != game_city_by_number(args->target_city_id)) {
444 struct unit_list *as_list;
445
446 as_list = unit_list_new();
447 unit_list_append(as_list, punit);
448 popup_upgrade_dialog(as_list);
449 unit_list_destroy(as_list);
450 }
451
452 gtk_widget_destroy(act_sel_dialog);
453 free(args);
454}
455
456/**********************************************************************/
459static void bribe_response(GtkWidget *w, gint response, gpointer data)
460{
461 struct action_data *args = (struct action_data *)data;
462
463 if (response == GTK_RESPONSE_YES) {
465 args->target_unit_id, 0, "");
466 }
467
468 gtk_widget_destroy(w);
469 free(args);
470
471 /* The user have answered the follow up question. Move on. */
473}
474
475/**********************************************************************/
478void popup_bribe_dialog(struct unit *actor, struct unit *punit, int cost,
479 const struct action *paction)
480{
481 GtkWidget *shell;
482 char buf[1024];
483
484 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
485 "Treasury contains %d gold.",
486 client_player()->economic.gold),
487 client_player()->economic.gold);
488
489 if (cost <= client_player()->economic.gold) {
490 shell = gtk_message_dialog_new(NULL, 0,
491 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
492 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
493 PL_("Bribe unit for %d gold?\n%s",
494 "Bribe unit for %d gold?\n%s", cost), cost, buf);
495 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
497 } else {
498 shell = gtk_message_dialog_new(NULL, 0,
499 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
500 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
501 PL_("Bribing the unit costs %d gold.\n%s",
502 "Bribing the unit costs %d gold.\n%s", cost), cost, buf);
503 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
505 }
506 gtk_window_present(GTK_WINDOW(shell));
507
508 g_signal_connect(shell, "response", G_CALLBACK(bribe_response),
509 act_data(paction->id, actor->id,
510 0, punit->id, 0,
511 0, 0, 0));
512}
513
514/**********************************************************************/
517static void spy_advances_response(GtkWidget *w, gint response,
518 gpointer data)
519{
520 struct action_data *args = (struct action_data *)data;
521
522 if (response == GTK_RESPONSE_ACCEPT && args->target_tech_id > 0) {
523 if (NULL != game_unit_by_number(args->actor_unit_id)
524 && NULL != game_city_by_number(args->target_city_id)) {
525 if (args->target_tech_id == A_UNSET) {
526 /* This is the untargeted version. */
528 args->actor_unit_id, args->target_city_id,
529 args->target_tech_id, "");
530 } else {
531 /* This is the targeted version. */
533 args->actor_unit_id, args->target_city_id,
534 args->target_tech_id, "");
535 }
536 }
537 }
538
539 gtk_widget_destroy(spy_tech_shell);
540 spy_tech_shell = NULL;
541 free(data);
542
543 /* The user have answered the follow up question. Move on. */
545}
546
547/**********************************************************************/
550static void spy_advances_callback(GtkTreeSelection *select,
551 gpointer data)
552{
553 struct action_data *args = (struct action_data *)data;
554
555 GtkTreeModel *model;
556 GtkTreeIter it;
557
558 if (gtk_tree_selection_get_selected(select, &model, &it)) {
559 gtk_tree_model_get(model, &it, 1, &(args->target_tech_id), -1);
560
561 gtk_dialog_set_response_sensitive(GTK_DIALOG(spy_tech_shell),
562 GTK_RESPONSE_ACCEPT, TRUE);
563 } else {
564 args->target_tech_id = 0;
565
566 gtk_dialog_set_response_sensitive(GTK_DIALOG(spy_tech_shell),
567 GTK_RESPONSE_ACCEPT, FALSE);
568 }
569}
570
571/**********************************************************************/
574static void create_advances_list(struct player *pplayer,
575 struct player *pvictim,
576 struct action_data *args)
577{
578 GtkWidget *sw, *label, *vbox, *view;
579 GtkListStore *store;
580 GtkCellRenderer *rend;
581 GtkTreeViewColumn *col;
582
584
585 spy_tech_shell = gtk_dialog_new_with_buttons(_("Steal Technology"),
586 NULL,
587 0,
588 GTK_STOCK_CANCEL,
589 GTK_RESPONSE_CANCEL,
590 _("_Steal"),
591 GTK_RESPONSE_ACCEPT,
592 NULL);
594 gtk_window_set_position(GTK_WINDOW(spy_tech_shell), GTK_WIN_POS_MOUSE);
595
596 gtk_dialog_set_default_response(GTK_DIALOG(spy_tech_shell),
597 GTK_RESPONSE_ACCEPT);
598
599 label = gtk_frame_new(_("Select Advance to Steal"));
600 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(spy_tech_shell))), label);
601
602 vbox = gtk_grid_new();
603 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
604 GTK_ORIENTATION_VERTICAL);
605 gtk_grid_set_row_spacing(GTK_GRID(vbox), 6);
606 gtk_container_add(GTK_CONTAINER(label), vbox);
607
608 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
609
610 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
611 gtk_widget_set_hexpand(view, TRUE);
612 gtk_widget_set_vexpand(view, TRUE);
613 g_object_unref(store);
614 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
615
616 rend = gtk_cell_renderer_text_new();
617 col = gtk_tree_view_column_new_with_attributes(NULL, rend,
618 "text", 0, NULL);
619 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
620
621 label = g_object_new(GTK_TYPE_LABEL,
622 "use-underline", TRUE,
623 "mnemonic-widget", view,
624 "label", _("_Advances:"),
625 "xalign", 0.0,
626 "yalign", 0.5,
627 NULL);
628 gtk_container_add(GTK_CONTAINER(vbox), label);
629
630 sw = gtk_scrolled_window_new(NULL, NULL);
631 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
632 GTK_SHADOW_ETCHED_IN);
633 gtk_container_add(GTK_CONTAINER(sw), view);
634
635 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
636 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
637 gtk_widget_set_size_request(sw, -1, 200);
638
639 gtk_container_add(GTK_CONTAINER(vbox), sw);
640
641 /* Now populate the list */
642 if (pvictim) { /* you don't want to know what lag can do -- Syela */
643 const struct research *presearch = research_get(pplayer);
644 const struct research *vresearch = research_get(pvictim);
645 GtkTreeIter it;
646 GValue value = { 0, };
647
649 if (research_invention_gettable(presearch, i,
651 && research_invention_state(vresearch, i) == TECH_KNOWN
652 && research_invention_state(presearch, i) != TECH_KNOWN) {
653 gtk_list_store_append(store, &it);
654
655 g_value_init(&value, G_TYPE_STRING);
656 g_value_set_static_string(&value, research_advance_name_translation
657 (presearch, i));
658 gtk_list_store_set_value(store, &it, 0, &value);
659 g_value_unset(&value);
660 gtk_list_store_set(store, &it, 1, i, -1);
661 }
663
666 gtk_list_store_append(store, &it);
667
668 g_value_init(&value, G_TYPE_STRING);
669 {
670 struct astring str = ASTRING_INIT;
671 /* TRANS: %s is a unit name, e.g., Spy */
672 astr_set(&str, _("At %s's Discretion"),
674 g_value_set_string(&value, astr_str(&str));
675 astr_free(&str);
676 }
677 gtk_list_store_set_value(store, &it, 0, &value);
678 g_value_unset(&value);
679 gtk_list_store_set(store, &it, 1, A_UNSET, -1);
680 }
681 }
682
683 gtk_dialog_set_response_sensitive(GTK_DIALOG(spy_tech_shell),
684 GTK_RESPONSE_ACCEPT, FALSE);
685
686 gtk_widget_show_all(gtk_dialog_get_content_area(GTK_DIALOG(spy_tech_shell)));
687
688 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), "changed",
689 G_CALLBACK(spy_advances_callback), args);
690 g_signal_connect(spy_tech_shell, "response",
691 G_CALLBACK(spy_advances_response), args);
692
693 args->target_tech_id = 0;
694
695 gtk_tree_view_focus(GTK_TREE_VIEW(view));
696}
697
698/**********************************************************************/
701static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
702{
703 struct action_data *args = (struct action_data *)data;
704
705 if (response == GTK_RESPONSE_ACCEPT && args->target_building_id > -2) {
706 if (NULL != game_unit_by_number(args->actor_unit_id)
707 && NULL != game_city_by_number(args->target_city_id)) {
708 if (args->target_building_id == B_LAST) {
709 /* This is the untargeted version. */
711 args->actor_unit_id,
712 args->target_city_id,
713 args->target_building_id, "");
714 } else if (args->target_building_id == -1) {
715 /* This is the city production version. */
717 args->actor_unit_id,
718 args->target_city_id,
719 args->target_building_id, "");
720 } else {
721 /* This is the targeted version. */
723 args->actor_unit_id,
724 args->target_city_id,
725 args->target_building_id, "");
726 }
727 }
728 }
729
730 gtk_widget_destroy(spy_sabotage_shell);
731 spy_sabotage_shell = NULL;
732 free(args);
733
734 /* The user have answered the follow up question. Move on. */
736}
737
738/**********************************************************************/
741static void spy_improvements_callback(GtkTreeSelection *select, gpointer data)
742{
743 struct action_data *args = (struct action_data *)data;
744
745 GtkTreeModel *model;
746 GtkTreeIter it;
747
748 if (gtk_tree_selection_get_selected(select, &model, &it)) {
749 gtk_tree_model_get(model, &it, 1, &(args->target_building_id), -1);
750
751 gtk_dialog_set_response_sensitive(GTK_DIALOG(spy_sabotage_shell),
752 GTK_RESPONSE_ACCEPT, TRUE);
753 } else {
754 args->target_building_id = -2;
755
756 gtk_dialog_set_response_sensitive(GTK_DIALOG(spy_sabotage_shell),
757 GTK_RESPONSE_ACCEPT, FALSE);
758 }
759}
760
761/**********************************************************************/
764static void create_improvements_list(struct player *pplayer,
765 struct city *pcity,
766 struct action_data *args)
767{
768 GtkWidget *sw, *label, *vbox, *view;
769 GtkListStore *store;
770 GtkCellRenderer *rend;
771 GtkTreeViewColumn *col;
772 GtkTreeIter it;
773
775
776 spy_sabotage_shell = gtk_dialog_new_with_buttons(_("Sabotage Improvements"),
777 NULL,
778 0,
779 GTK_STOCK_CANCEL,
780 GTK_RESPONSE_CANCEL,
781 _("_Sabotage"),
782 GTK_RESPONSE_ACCEPT,
783 NULL);
785 gtk_window_set_position(GTK_WINDOW(spy_sabotage_shell), GTK_WIN_POS_MOUSE);
786
787 gtk_dialog_set_default_response(GTK_DIALOG(spy_sabotage_shell),
788 GTK_RESPONSE_ACCEPT);
789
790 label = gtk_frame_new(_("Select Improvement to Sabotage"));
791 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(spy_sabotage_shell))), label);
792
793 vbox = gtk_grid_new();
794 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
795 GTK_ORIENTATION_VERTICAL);
796 gtk_grid_set_row_spacing(GTK_GRID(vbox), 6);
797 gtk_container_add(GTK_CONTAINER(label), vbox);
798
799 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
800
801 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
802 gtk_widget_set_hexpand(view, TRUE);
803 gtk_widget_set_vexpand(view, TRUE);
804 g_object_unref(store);
805 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
806
807 rend = gtk_cell_renderer_text_new();
808 col = gtk_tree_view_column_new_with_attributes(NULL, rend,
809 "text", 0, NULL);
810 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
811
812 label = g_object_new(GTK_TYPE_LABEL,
813 "use-underline", TRUE,
814 "mnemonic-widget", view,
815 "label", _("_Improvements:"),
816 "xalign", 0.0,
817 "yalign", 0.5,
818 NULL);
819 gtk_container_add(GTK_CONTAINER(vbox), label);
820
821 sw = gtk_scrolled_window_new(NULL, NULL);
822 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
823 GTK_SHADOW_ETCHED_IN);
824 gtk_container_add(GTK_CONTAINER(sw), view);
825
826 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
827 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
828 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(sw), 200);
829
830 gtk_container_add(GTK_CONTAINER(vbox), sw);
831
832 /* Now populate the list */
835 args->act_id)])) {
836 gtk_list_store_append(store, &it);
837 gtk_list_store_set(store, &it, 0, _("City Production"), 1, -1, -1);
838 }
839
840 city_built_iterate(pcity, pimprove) {
841 if (pimprove->sabotage > 0) {
842 gtk_list_store_append(store, &it);
843 gtk_list_store_set(store, &it,
844 0, city_improvement_name_translation(pcity, pimprove),
845 1, improvement_number(pimprove),
846 -1);
847 }
849
852 struct astring str = ASTRING_INIT;
853
854 gtk_list_store_append(store, &it);
855
856 /* TRANS: %s is a unit name, e.g., Spy */
857 astr_set(&str, _("At %s's Discretion"),
859 gtk_list_store_set(store, &it, 0, astr_str(&str), 1, B_LAST, -1);
860
861 astr_free(&str);
862 }
863
864 gtk_dialog_set_response_sensitive(GTK_DIALOG(spy_sabotage_shell),
865 GTK_RESPONSE_ACCEPT, FALSE);
866
867 gtk_widget_show_all(gtk_dialog_get_content_area(GTK_DIALOG(spy_sabotage_shell)));
868
869 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), "changed",
870 G_CALLBACK(spy_improvements_callback), args);
871 g_signal_connect(spy_sabotage_shell, "response",
872 G_CALLBACK(spy_improvements_response), args);
873
874 args->target_building_id = -2;
875
876 gtk_tree_view_focus(GTK_TREE_VIEW(view));
877}
878
879/**********************************************************************/
882static void spy_steal_popup_shared(GtkWidget *w, gpointer data)
883{
884 struct action_data *args = (struct action_data *)data;
885
886 args->act_id = args->act_id;
887
888 struct city *pvcity = game_city_by_number(args->target_city_id);
889 struct player *pvictim = NULL;
890
891 if (pvcity) {
892 pvictim = city_owner(pvcity);
893 }
894
895/* it is concievable that pvcity will not be found, because something
896has happened to the city during latency. Therefore we must initialize
897pvictim to NULL and account for !pvictim in create_advances_list. -- Syela */
898
899 /* FIXME: Don't discard the second tech choice dialog. */
900 if (!spy_tech_shell) {
901 create_advances_list(client.conn.playing, pvictim, args);
902 gtk_window_present(GTK_WINDOW(spy_tech_shell));
903 } else {
904 free(args);
905 }
906
907 /* Wait for the player's reply before moving on to the next unit that
908 * needs to know what action to take. */
910
911 gtk_widget_destroy(act_sel_dialog);
912}
913
914/**********************************************************************/
918static void spy_steal_popup(GtkWidget *w, gpointer data)
919{
920 act_sel_dialog_data->act_id = ACTION_SPY_TARGETED_STEAL_TECH;
922}
923
924/**********************************************************************/
928static void spy_steal_esc_popup(GtkWidget *w, gpointer data)
929{
930 act_sel_dialog_data->act_id = ACTION_SPY_TARGETED_STEAL_TECH_ESC;
932}
933
934/**********************************************************************/
938void popup_sabotage_dialog(struct unit *actor, struct city *pcity,
939 const struct action *paction)
940{
941 /* FIXME: Don't discard the second target choice dialog. */
942 if (!spy_sabotage_shell) {
944 act_data(paction->id,
945 actor->id, pcity->id, 0, 0,
946 0, 0, 0));
947 gtk_window_present(GTK_WINDOW(spy_sabotage_shell));
948 }
949}
950
951/**********************************************************************/
954static void incite_response(GtkWidget *w, gint response, gpointer data)
955{
956 struct action_data *args = (struct action_data *)data;
957
958 if (response == GTK_RESPONSE_YES) {
960 args->target_city_id, 0, "");
961 }
962
963 gtk_widget_destroy(w);
964 free(args);
965
966 /* The user have answered the follow up question. Move on. */
968}
969
970/**********************************************************************/
973void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost,
974 const struct action *paction)
975{
976 GtkWidget *shell;
977 char buf[1024];
978
979 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
980 "Treasury contains %d gold.",
981 client_player()->economic.gold),
982 client_player()->economic.gold);
983
985 shell = gtk_message_dialog_new(NULL, 0,
986 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
987 _("You can't incite a revolt in %s."),
988 city_name_get(pcity));
989 gtk_window_set_title(GTK_WINDOW(shell), _("City can't be incited!"));
991 } else if (cost <= client_player()->economic.gold) {
992 shell = gtk_message_dialog_new(NULL, 0,
993 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
994 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
995 PL_("Incite a revolt for %d gold?\n%s",
996 "Incite a revolt for %d gold?\n%s", cost), cost, buf);
997 gtk_window_set_title(GTK_WINDOW(shell), _("Incite a Revolt!"));
999 } else {
1000 shell = gtk_message_dialog_new(NULL,
1001 0,
1002 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
1003 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1004 PL_("Inciting a revolt costs %d gold.\n%s",
1005 "Inciting a revolt costs %d gold.\n%s", cost), cost, buf);
1006 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
1008 }
1009 gtk_window_present(GTK_WINDOW(shell));
1010
1011 g_signal_connect(shell, "response", G_CALLBACK(incite_response),
1012 act_data(paction->id, actor->id,
1013 pcity->id, 0, 0,
1014 0, 0, 0));
1015}
1016
1017/**********************************************************************/
1020static void tgt_unit_change_callback(GtkWidget *dlg, gint arg)
1021{
1022 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1023
1024 if (arg == GTK_RESPONSE_YES) {
1025 struct unit *actor = game_unit_by_number(au_id);
1026
1027 if (actor != NULL) {
1028 int tgt_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg),
1029 "target"));
1030 struct unit *tgt_unit = game_unit_by_number(tgt_id);
1031 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1032
1033 if (tgt_unit == NULL) {
1034 /* Make the action dialog pop up again. */
1036 actor->id, actor->id,
1037 /* Let the server choose the target
1038 * unit. */
1041 tgt_tile->index,
1044 } else {
1046 actor->id, actor->id,
1047 tgt_id, tgt_id,
1048 tgt_tile->index,
1051 }
1052 }
1053 } else {
1054 /* Dialog canceled. This ends the action selection process. */
1056 }
1057
1058 gtk_widget_destroy(dlg);
1059}
1060
1061/**********************************************************************/
1064static void act_sel_new_unit_tgt_callback(GtkWidget *w, gpointer data)
1065{
1066 struct action_data *args = act_sel_dialog_data;
1067
1068 struct unit *punit;
1069 struct unit *tunit;
1070 struct tile *ptile;
1071
1073 && (ptile = index_to_tile(&(wld.map), args->target_tile_id))
1074 && (tunit = game_unit_by_number(args->target_unit_id))) {
1075 select_tgt_unit(punit, ptile, ptile->units, tunit,
1076 _("Target unit selection"),
1077 _("Looking for target unit:"),
1078 _("Units at tile:"),
1079 _("Select"),
1080 G_CALLBACK(tgt_unit_change_callback));
1081 }
1082
1085 gtk_widget_destroy(act_sel_dialog);
1086 free(args);
1087}
1088
1089/**********************************************************************/
1092static void tgt_extra_change_callback(GtkWidget *dlg, gint arg)
1093{
1094 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1095
1096 if (arg == GTK_RESPONSE_YES) {
1097 struct unit *actor = game_unit_by_number(au_id);
1098
1099 if (actor != NULL) {
1100 int tgt_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg),
1101 "target"));
1102 struct extra_type *tgt_extra = extra_by_number(tgt_id);
1103 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1104 int tgt_unit = action_selection_target_unit();
1105
1106 if (tgt_extra == NULL) {
1107 /* Make the action dialog pop up again. */
1109 actor->id, actor->id,
1110 tgt_unit, tgt_unit,
1111 tgt_tile->index,
1112 /* Let the server choose the target
1113 * extra. */
1116 } else {
1118 actor->id, actor->id,
1119 tgt_unit, tgt_unit,
1120 tgt_tile->index,
1121 tgt_id,
1123 }
1124 }
1125 } else {
1126 /* Dialog canceled. This ends the action selection process. */
1128 }
1129
1130 gtk_widget_destroy(dlg);
1131}
1132
1133/**********************************************************************/
1136static void act_sel_new_extra_tgt_callback(GtkWidget *w, gpointer data)
1137{
1138 struct action_data *args = act_sel_dialog_data;
1139
1140 struct unit *act_unit;
1141 struct extra_type *tgt_extra;
1142 struct tile *tgt_tile;
1143
1144 if ((act_unit = game_unit_by_number(args->actor_unit_id))
1145 && (tgt_tile = index_to_tile(&(wld.map), args->target_tile_id))
1146 && (tgt_extra = extra_by_number(args->target_extra_id))) {
1147 bv_extras potential_targets;
1148
1149 /* Start with the extras at the tile */
1150 potential_targets = *tile_extras(tgt_tile);
1151
1153 if (BV_ISSET(potential_targets, extra_number(pextra))) {
1154 /* This extra is at the tile. Can anything be done to it? */
1156 pextra)) {
1157 BV_CLR(potential_targets, extra_number(pextra));
1158 }
1159 } else {
1160 /* This extra isn't at the tile yet. Can it be created? */
1162 pextra)) {
1163 BV_SET(potential_targets, extra_number(pextra));
1164 }
1165 }
1167
1168 select_tgt_extra(act_unit, tgt_tile, potential_targets, tgt_extra,
1169 /* TRANS: GTK action selection dialog extra target
1170 * selection dialog title. */
1171 _("Target extra selection"),
1172 /* TRANS: GTK action selection dialog extra target
1173 * selection dialog actor unit label. */
1174 _("Looking for target extra:"),
1175 /* TRANS: GTK action selection dialog extra target
1176 * selection dialog extra list label. */
1177 _("Extra targets:"),
1178 _("Select"),
1179 G_CALLBACK(tgt_extra_change_callback));
1180 }
1181
1184 gtk_widget_destroy(act_sel_dialog);
1185 free(args);
1186}
1187
1188/**********************************************************************/
1191static void act_sel_location_callback(GtkWidget *w, gpointer data)
1192{
1193 struct action_data *args = act_sel_dialog_data;
1194
1195 struct unit *punit;
1196
1197 if ((punit = game_unit_by_number(args->actor_unit_id))) {
1199 }
1200}
1201
1202/**********************************************************************/
1205static void act_sel_wait_callback(GtkWidget *w, gpointer data)
1206{
1207 struct action_data *args = act_sel_dialog_data;
1208
1209 key_unit_wait();
1210
1211 /* the dialog was destroyed when key_unit_wait() resulted in
1212 * action_selection_close() being called. */
1213
1214 free(args);
1215}
1216
1217/**********************************************************************/
1220static void act_sel_destroy_callback(GtkWidget *w, gpointer data)
1221{
1222 act_sel_dialog = NULL;
1224}
1225
1226/**********************************************************************/
1229static void act_sel_cancel_callback(GtkWidget *w, gpointer data)
1230{
1231 gtk_widget_destroy(act_sel_dialog);
1232 free(act_sel_dialog_data);
1233}
1234
1235/**********************************************************************/
1238static void act_sel_close_callback(GtkWidget *w,
1239 gint response_id,
1240 gpointer data)
1241{
1242 gtk_widget_destroy(act_sel_dialog);
1243 free(act_sel_dialog_data);
1244}
1245
1246/* Mapping from an action to the function to call when its button is
1247 * pushed. */
1248static const GCallback af_map[ACTION_COUNT] = {
1249 /* Unit acting against a city target. */
1250 [ACTION_SPY_TARGETED_SABOTAGE_CITY] =
1252 [ACTION_SPY_TARGETED_SABOTAGE_CITY_ESC] =
1254 [ACTION_SPY_TARGETED_STEAL_TECH] = (GCallback)spy_steal_popup,
1255 [ACTION_SPY_TARGETED_STEAL_TECH_ESC] = (GCallback)spy_steal_esc_popup,
1256 [ACTION_SPY_INCITE_CITY] = (GCallback)request_action_details_callback,
1257 [ACTION_SPY_INCITE_CITY_ESC] = (GCallback)request_action_details_callback,
1258 [ACTION_UPGRADE_UNIT] = (GCallback)upgrade_callback,
1259 [ACTION_STRIKE_BUILDING] = (GCallback)request_action_details_callback,
1260
1261 /* Unit acting against a unit target. */
1262 [ACTION_SPY_BRIBE_UNIT] = (GCallback)request_action_details_callback,
1263
1264 /* Unit acting against all units at a tile. */
1265 /* No special callback functions needed for any unit stack targeted
1266 * actions. */
1267
1268 /* Unit acting against a tile. */
1269 [ACTION_FOUND_CITY] = (GCallback)found_city_callback,
1270
1271 /* Unit acting with no target except itself. */
1272 /* No special callback functions needed for any self targeted actions. */
1273};
1274
1275/**********************************************************************/
1278static void action_entry(GtkWidget *shl,
1280 const struct act_prob *act_probs,
1281 const char *custom,
1282 action_id act_num)
1283{
1284 const gchar *label;
1285 const gchar *tooltip;
1286 GCallback cb;
1287
1288 if (af_map[act_id] == NULL) {
1289 /* No special call back function needed for this action. */
1290 cb = (GCallback)simple_action_callback;
1291 } else {
1292 /* Special action specific callback function specified. */
1293 cb = af_map[act_id];
1294 }
1295
1296 /* Don't show disabled actions. */
1297 if (!action_prob_possible(act_probs[act_id])) {
1298 return;
1299 }
1300
1301 label = action_prepare_ui_name(act_id, "_",
1302 act_probs[act_id],
1303 custom);
1304
1306 act_probs[act_id]);
1307
1309 choice_dialog_add(shl, label, cb, GINT_TO_POINTER(act_num),
1310 FALSE, tooltip);
1311}
1312
1313/**********************************************************************/
1316static void action_entry_update(GtkWidget *shl,
1318 const struct act_prob *act_probs,
1319 const char *custom,
1320 action_id act_num)
1321{
1322 const gchar *label;
1323 const gchar *tooltip;
1324
1325 /* An action that just became impossible has its button disabled.
1326 * An action that became possible again must be re-enabled. */
1329 action_prob_possible(act_probs[act_id]));
1330
1331 /* The probability may have changed. */
1332 label = action_prepare_ui_name(act_id, "_",
1333 act_probs[act_id], custom);
1334
1336 act_probs[act_id]);
1337
1340 label);
1343 tooltip);
1344}
1345
1346/**********************************************************************/
1351 struct city *target_city,
1352 struct unit *target_unit,
1353 struct tile *target_tile,
1354 struct extra_type *target_extra,
1355 const struct act_prob *act_probs)
1356{
1357 GtkWidget *shl;
1358 struct astring title = ASTRING_INIT, text = ASTRING_INIT;
1359 struct city *actor_homecity;
1360
1361 int button_id;
1362
1364 act_data(ACTION_ANY, /* Not decided yet */
1365 actor_unit->id,
1369 /* No target_building or target_tech supplied. (Dec 2019) */
1370 B_LAST, A_UNSET,
1372
1373 /* Could be caused by the server failing to reply to a request for more
1374 * information or a bug in the client code. */
1376 "Diplomat queue problem. Is another diplomat window open?");
1377
1378 /* No extra input is required as no action has been chosen yet. */
1380
1381 /* No buttons are added yet. */
1382 for (button_id = 0; button_id < BUTTON_COUNT; button_id++) {
1384 }
1385
1386 actor_homecity = game_city_by_number(actor_unit->homecity);
1387
1389 target_ids[ATK_SELF] = actor_unit_id;
1390 target_ids[ATK_CITY] = target_city ?
1391 target_city->id :
1393 target_ids[ATK_UNIT] = target_unit ?
1394 target_unit->id :
1396 target_ids[ATK_UNITS] = target_tile ?
1399 target_ids[ATK_TILE] = target_tile ?
1402 target_ids[ATK_EXTRAS] = target_tile ?
1407 EXTRA_NONE;
1408
1409 astr_set(&title,
1410 /* TRANS: %s is a unit name, e.g., Spy */
1411 _("Choose Your %s's Strategy"),
1413
1414 if (target_city && actor_homecity) {
1415 astr_set(&text,
1416 _("Your %s from %s reaches the city of %s.\nWhat now?"),
1418 city_name_get(actor_homecity),
1420 } else if (target_city) {
1421 astr_set(&text,
1422 _("Your %s has arrived at %s.\nWhat is your command?"),
1425 } else if (target_unit) {
1426 astr_set(&text,
1427 /* TRANS: Your Spy is ready to act against Roman Freight. */
1428 _("Your %s is ready to act against %s %s."),
1432 } else {
1434 "No target specified.");
1435 astr_set(&text,
1436 /* TRANS: %s is a unit name, e.g., Diplomat, Spy */
1437 _("Your %s is waiting for your command."),
1439 }
1440
1441 shl = choice_dialog_start(GTK_WINDOW(toplevel), astr_str(&title),
1442 astr_str(&text));
1443
1444 /* Unit acting against a city */
1445
1446 action_iterate(act) {
1447 if (action_id_get_actor_kind(act) == AAK_UNIT
1448 && action_id_get_target_kind(act) == ATK_CITY) {
1449 action_entry(shl, act, act_probs,
1451 act_probs[act],
1452 actor_unit,
1453 target_city),
1454 act);
1455 }
1457
1458 /* Unit acting against another unit */
1459
1460 action_iterate(act) {
1461 if (action_id_get_actor_kind(act) == AAK_UNIT
1462 && action_id_get_target_kind(act) == ATK_UNIT) {
1463 action_entry(shl, act, act_probs,
1465 act_probs[act],
1466 actor_unit,
1467 target_city),
1468 act);
1469 }
1471
1472 /* Unit acting against all units at a tile */
1473
1474 action_iterate(act) {
1475 if (action_id_get_actor_kind(act) == AAK_UNIT
1476 && action_id_get_target_kind(act) == ATK_UNITS) {
1477 action_entry(shl, act, act_probs,
1479 act_probs[act],
1480 actor_unit,
1481 target_city),
1482 act);
1483 }
1485
1486 /* Unit acting against a tile */
1487
1488 action_iterate(act) {
1489 if (action_id_get_actor_kind(act) == AAK_UNIT
1490 && action_id_get_target_kind(act) == ATK_TILE) {
1491 action_entry(shl, act, act_probs,
1493 act_probs[act],
1494 actor_unit,
1495 target_city),
1496 act);
1497 }
1499
1500 /* Unit acting against a tile's extras */
1501
1502 action_iterate(act) {
1503 if (action_id_get_actor_kind(act) == AAK_UNIT
1504 && action_id_get_target_kind(act) == ATK_EXTRAS) {
1505 action_entry(shl, act, act_probs,
1507 act_probs[act],
1508 actor_unit,
1509 target_city),
1510 act);
1511 }
1513
1514 /* Unit acting against itself. */
1515
1516 action_iterate(act) {
1517 if (action_id_get_actor_kind(act) == AAK_UNIT
1518 && action_id_get_target_kind(act) == ATK_SELF) {
1519 action_entry(shl, act, act_probs,
1521 act_probs[act],
1522 actor_unit,
1523 target_city),
1524 act);
1525 }
1527
1528 if (target_unit != NULL
1529 && unit_list_size(target_tile->units) > 1) {
1532 choice_dialog_add(shl, _("Change unit target"),
1534 GINT_TO_POINTER(ACTION_NONE), TRUE, NULL);
1535 }
1536
1537 if (target_extra != NULL) {
1540 choice_dialog_add(shl, _("Change extra target"),
1542 GINT_TO_POINTER(ACTION_NONE), TRUE, NULL);
1543 }
1544
1547 choice_dialog_add(shl, _("Show Location"),
1548 (GCallback)act_sel_location_callback,
1549 GINT_TO_POINTER(ACTION_NONE),
1550 TRUE, NULL);
1551
1554 choice_dialog_add(shl, _("_Wait"),
1555 (GCallback)act_sel_wait_callback,
1556 GINT_TO_POINTER(ACTION_NONE),
1557 TRUE, NULL);
1558
1561 choice_dialog_add(shl, GTK_STOCK_CANCEL,
1562 (GCallback)act_sel_cancel_callback,
1563 GINT_TO_POINTER(ACTION_NONE),
1564 FALSE, NULL);
1565
1566 choice_dialog_end(shl);
1567
1568 act_sel_dialog = shl;
1569
1571 g_signal_connect(shl, "destroy",
1572 G_CALLBACK(act_sel_destroy_callback), NULL);
1573 g_signal_connect(shl, "delete_event",
1574 G_CALLBACK(act_sel_close_callback),
1575 GINT_TO_POINTER(ACTION_NONE));
1576
1577 /* Give follow up questions access to action probabilities. */
1579 action_iterate(act) {
1580 actor_unit->client.act_prob_cache[act] = act_probs[act];
1582
1583 astr_free(&title);
1584 astr_free(&text);
1585}
1586
1587/**********************************************************************/
1593{
1594 if (act_sel_dialog == NULL) {
1595 return IDENTITY_NUMBER_ZERO;
1596 }
1597 return actor_unit_id;
1598}
1599
1600/**********************************************************************/
1607{
1608 if (act_sel_dialog == NULL) {
1609 return IDENTITY_NUMBER_ZERO;
1610 }
1611 return target_ids[ATK_CITY];
1612}
1613
1614/**********************************************************************/
1621{
1622 if (act_sel_dialog == NULL) {
1623 return IDENTITY_NUMBER_ZERO;
1624 }
1625
1626 return target_ids[ATK_UNIT];
1627}
1628
1629/**********************************************************************/
1636{
1637 if (act_sel_dialog == NULL) {
1638 return TILE_INDEX_NONE;
1639 }
1640
1641 return target_ids[ATK_TILE];
1642}
1643
1644/**********************************************************************/
1651{
1652 if (act_sel_dialog == NULL) {
1653 return EXTRA_NONE;
1654 }
1655
1656 return target_extra_id;
1657}
1658
1659/**********************************************************************/
1663 struct city *target_city,
1664 struct unit *target_unit,
1665 struct tile *target_tile,
1666 struct extra_type *target_extra,
1667 const struct act_prob *act_probs)
1668{
1669 if (act_sel_dialog == NULL) {
1671 "The action selection dialog should have been open");
1672 return;
1673 }
1674
1677 "The action selection dialog is for another actor unit.");
1678 return;
1679 }
1680
1681 /* A new target may have appeared. */
1682 if (target_city) {
1684 }
1685 if (target_unit) {
1687 }
1688 if (target_tile) {
1690 }
1691 /* No target_building or target_tech supplied. (Dec 2019) */
1692 if (target_extra) {
1694 }
1695
1696 action_iterate(act) {
1697 const char *custom;
1698
1699 if (action_id_get_actor_kind(act) != AAK_UNIT) {
1700 /* Not relevant. */
1701 continue;
1702 }
1703
1705 act_probs[act],
1706 actor_unit,
1707 target_city);
1708
1709 if (BUTTON_NOT_THERE == action_button_map[act]) {
1710 /* Add the button (unless its probability is 0). */
1711 action_entry(act_sel_dialog, act, act_probs, custom, act);
1712 } else {
1713 /* Update the existing button. */
1714 action_entry_update(act_sel_dialog, act, act_probs, custom, act);
1715 }
1717
1718 /* DO NOT change the action_button_map[] for any button to reflect its
1719 * new position. A button keeps its choice dialog internal name when its
1720 * position changes. A button's id number is therefore based on when
1721 * it was added, not on its current position. */
1722
1724 /* Move the wait button below the recently added button. */
1727 }
1728
1730 /* Move the cancel button below the recently added button. */
1733 }
1734
1736}
1737
1738/**********************************************************************/
1742{
1743 if (act_sel_dialog != NULL) {
1745 gtk_widget_destroy(act_sel_dialog);
1746 }
1747}
const char * action_prepare_ui_name(action_id act_id, const char *mnemonic, const struct act_prob prob, const char *custom)
Definition actions.c:1972
enum action_actor_kind action_get_actor_kind(const struct action *paction)
Definition actions.c:1730
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:6703
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1751
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1740
static struct action * action_by_number(action_id act_id)
Definition actions.h:638
#define action_iterate_end
Definition actions.h:472
#define action_id_get_actor_kind(act_id)
Definition actions.h:651
#define action_iterate(_act_)
Definition actions.h:467
#define ACTION_ANY
Definition actions.h:290
#define action_id_get_target_kind(act_id)
Definition actions.h:655
#define ACTION_NONE
Definition actions.h:293
void astr_free(struct astring *astr)
Definition astring.c:153
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:267
#define str
Definition astring.c:76
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
#define ASTRING_INIT
Definition astring.h:44
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:658
const char * city_name_get(const struct city *pcity)
Definition city.c:1115
#define INCITE_IMPOSSIBLE_COST
Definition city.h:88
#define city_owner(_pcity_)
Definition city.h:543
#define city_built_iterate(_pcity, _p)
Definition city.h:810
#define city_built_iterate_end
Definition city.h:816
struct civclient client
#define client_player()
void client_unit_init_act_prob_cache(struct unit *punit)
Definition climisc.c:1252
void action_selection_no_longer_in_progress(const int old_actor_id)
Definition control.c:1050
void request_do_action(action_id action, int actor_id, int target_id, int sub_tgt, const char *name)
Definition control.c:1701
void request_action_details(action_id action, int actor_id, int target_id)
Definition control.c:1721
void action_decision_clear_want(const int old_actor_id)
Definition control.c:1079
void key_unit_wait(void)
Definition control.c:3375
void action_selection_next_in_focus(const int old_actor_id)
Definition control.c:1091
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:55
popup_action_selection
Definition dialogs_g.h:54
struct unit * actor_unit
Definition dialogs_g.h:54
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id popup_bribe_dialog
Definition dialogs_g.h:72
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit * actor
Definition dialogs_g.h:72
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs action_selection_no_longer_in_progress_gui_specific
Definition dialogs_g.h:68
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:56
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct unit struct city * target_city
Definition dialogs_g.h:55
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int cost
Definition dialogs_g.h:73
struct unit struct city struct unit struct tile struct extra_type * target_extra
Definition dialogs_g.h:56
int extra_number(const struct extra_type *pextra)
Definition extras.c:153
struct extra_type * extra_by_number(int id)
Definition extras.c:175
#define EXTRA_NONE
Definition extras.h:82
#define extra_type_re_active_iterate_end
Definition extras.h:305
#define extra_type_re_active_iterate(_p)
Definition extras.h:301
#define NO_TARGET
Definition fc_types.h:324
int action_id
Definition fc_types.h:359
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:82
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:57
struct world wld
Definition game.c:58
struct unit * game_unit_by_number(int id)
Definition game.c:111
struct city * game_city_by_number(int id)
Definition game.c:102
static GtkWidget * spy_sabotage_shell
int action_selection_target_extra(void)
static void incite_response(GtkWidget *w, gint response, gpointer data)
static int action_button_map[BUTTON_COUNT]
static void spy_improvements_callback(GtkTreeSelection *select, gpointer data)
static int actor_unit_id
#define BUTTON_NEW_EXTRA_TGT
static void act_sel_new_extra_tgt_callback(GtkWidget *w, gpointer data)
int action_selection_target_tile(void)
static void create_improvements_list(struct player *pplayer, struct city *pcity, struct action_data *args)
static void act_sel_destroy_callback(GtkWidget *w, gpointer data)
int action_selection_actor_unit(void)
static void spy_advances_response(GtkWidget *w, gint response, gpointer data)
static void tgt_extra_change_callback(GtkWidget *dlg, gint arg)
static GtkWidget * act_sel_dialog
static void spy_steal_popup_shared(GtkWidget *w, gpointer data)
static void diplomat_queue_handle_primary(void)
void action_selection_close(void)
static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
int action_selection_target_city(void)
static void bribe_response(GtkWidget *w, gint response, gpointer data)
#define BUTTON_WAIT
static void action_entry(GtkWidget *shl, action_id act_id, const struct act_prob *act_probs, const char *custom, action_id act_num)
static void spy_steal_esc_popup(GtkWidget *w, gpointer data)
static void spy_steal_popup(GtkWidget *w, gpointer data)
static void act_sel_close_callback(GtkWidget *w, gint response_id, gpointer data)
static void diplomat_queue_handle_secondary(void)
static action_id get_non_targeted_action_id(action_id tgt_action_id)
static void request_action_details_callback(GtkWidget *w, gpointer data)
static bool action_selection_restart
#define BUTTON_NEW_UNIT_TGT
#define BUTTON_COUNT
static struct action_data * act_sel_dialog_data
static void found_city_callback(GtkWidget *w, gpointer data)
static void act_sel_location_callback(GtkWidget *w, gpointer data)
void action_selection_refresh(struct unit *actor_unit, struct city *target_city, struct unit *target_unit, struct tile *target_tile, struct extra_type *target_extra, const struct act_prob *act_probs)
static struct action_data * act_data(action_id act_id, int actor_id, int target_city_id, int target_unit_id, int target_tile_id, int target_building_id, int target_tech_id, int tgt_extra_id)
static void simple_action_callback(GtkWidget *w, gpointer data)
static void create_advances_list(struct player *pplayer, struct player *pvictim, struct action_data *args)
static bool is_more_user_input_needed
static int target_extra_id
static void act_sel_wait_callback(GtkWidget *w, gpointer data)
static void act_sel_new_unit_tgt_callback(GtkWidget *w, gpointer data)
static void tgt_unit_change_callback(GtkWidget *dlg, gint arg)
#define BUTTON_NOT_THERE
static action_id get_production_targeted_action_id(action_id tgt_action_id)
static bool did_not_decide
#define BUTTON_CANCEL
void popup_sabotage_dialog(struct unit *actor, struct city *pcity, const struct action *paction)
static GtkWidget * spy_tech_shell
static int target_ids[ATK_COUNT]
static void act_sel_cancel_callback(GtkWidget *w, gpointer data)
static void action_entry_update(GtkWidget *shl, action_id act_id, const struct act_prob *act_probs, const char *custom, action_id act_num)
int action_selection_target_unit(void)
void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost, const struct action *paction)
static const GCallback af_map[ACTION_COUNT]
static void upgrade_callback(GtkWidget *w, gpointer data)
static void spy_advances_callback(GtkTreeSelection *select, gpointer data)
#define BUTTON_LOCATION
GtkWidget * choice_dialog_start(GtkWindow *parent, const gchar *name, const gchar *text)
void choice_dialog_end(GtkWidget *dshell)
int choice_dialog_get_number_of_buttons(GtkWidget *cd)
void choice_dialog_button_set_tooltip(GtkWidget *cd, int number, const char *tool_tip)
void choice_dialog_button_move_to_the_end(GtkWidget *cd, const int number)
void choice_dialog_set_hide(GtkWidget *dshell, gboolean setting)
void choice_dialog_add(GtkWidget *dshell, const gchar *label, GCallback handler, gpointer data, bool meta, const gchar *tool_tip)
void choice_dialog_button_set_label(GtkWidget *cd, int number, const char *label)
void choice_dialog_button_set_sensitive(GtkWidget *cd, int button, gboolean state)
void popup_upgrade_dialog(struct unit_list *punits)
Definition dialogs.c:1444
GtkWidget * toplevel
Definition gui_main.c:124
void gtk_tree_view_focus(GtkTreeView *view)
Definition gui_stuff.c:230
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:281
static struct gui_dialog * shell
Definition messagedlg.c:39
const char * tooltip
Definition repodlgs.c:1314
const char * title
Definition repodlgs.c:1313
bool select_tgt_extra(struct unit *actor, struct tile *ptile, bv_extras potential_tgt_extras, struct extra_type *suggested_tgt_extra, const gchar *dlg_title, const gchar *actor_label, const gchar *tgt_label, const gchar *do_label, GCallback do_callback)
bool select_tgt_unit(struct unit *actor, struct tile *ptile, struct unit_list *potential_tgt_units, struct unit *suggested_tgt_unit, const gchar *dlg_title, const gchar *actor_label, const gchar *tgt_label, const gchar *do_label, GCallback do_callback)
struct impr_type * improvement_by_number(const Impr_type_id id)
Impr_type_id improvement_number(const struct impr_type *pimprove)
#define B_LAST
Definition improvement.h:42
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_action(condition, action)
Definition log.h:187
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:454
void center_tile_mapcanvas(const struct tile *ptile)
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:168
#define REQEST_PLAYER_INITIATED
Definition packets.h:70
int dsend_packet_unit_get_actions(struct connection *pc, int actor_unit_id16, int actor_unit_id32, int target_unit_id16, int target_unit_id32, int target_tile_id, int target_extra_id, int request_kind)
int dsend_packet_city_name_suggestion_req(struct connection *pc, int unit_id16, int unit_id32)
const char * research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Definition research.c:271
struct research * research_get(const struct player *pplayer)
Definition research.c:126
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:616
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:690
#define ARRAY_SIZE(x)
Definition shared.h:85
int target_building_id
action_id act_id
action_id id
Definition actions.h:380
enum act_tgt_compl target_complexity
Definition actions.h:390
Definition city.h:309
int id
Definition city.h:315
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
struct player * playing
Definition connection.h:156
bool tech_steal_allow_holes
Definition tile.h:49
int index
Definition tile.h:50
struct unit_list * units
Definition tile.h:57
Definition unit.h:138
int id
Definition unit.h:145
int index
Definition unit.h:195
struct unit::@80::@82 client
struct act_prob * act_prob_cache
Definition unit.h:225
int homecity
Definition unit.h:146
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
#define advance_index_iterate_end
Definition tech.h:248
#define A_FIRST
Definition tech.h:44
#define A_UNSET
Definition tech.h:48
#define advance_index_iterate(_start, _index)
Definition tech.h:244
const char * get_act_sel_action_custom_text(struct action *paction, const struct act_prob prob, const struct unit *actor_unit, const struct city *target_city)
Definition text.c:1743
const char * act_sel_action_tool_tip(const struct action *paction, const struct act_prob prob)
Definition text.c:1820
#define tile_index(_pt_)
Definition tile.h:87
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:119
#define TILE_INDEX_NONE
Definition tile.h:47
#define unit_tile(_pu)
Definition unit.h:395
#define unit_owner(_pu)
Definition unit.h:394
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
bool utype_can_remove_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:235
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1621
bool utype_can_create_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:211