Freeciv-3.3
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.22 */
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
67
68static int actor_unit_id;
70static int target_extra_id;
72static bool did_not_decide = FALSE;
74
76
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;
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) {
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) {
230 default:
231 /* No non targeted version found. */
232 return ACTION_NONE;
233 }
234}
235
236/**********************************************************************/
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);
252
253 /* Actor */
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;
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_STACK:
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:
292 failed = TRUE;
293 }
294
295 /* Sub target. */
296 sub_target = NO_TARGET;
297 if (paction->target_complexity != ACT_TGT_COMPL_SIMPLE) {
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:
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. */
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. */
338 /* No follow up questions. */
340 FC_FREE(args);
341}
342
343/**********************************************************************/
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);
359
360 /* Actor */
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;
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_STACK:
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:
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. */
413 /* No client side follow up questions. */
415 FC_FREE(args);
416}
417
418/**********************************************************************/
431
432/**********************************************************************/
436{
437 struct unit *punit;
438
439 struct action_data *args = act_sel_dialog_data;
440
443 struct unit_list *as_list;
444
449 }
450
452 free(args);
453}
454
455/**********************************************************************/
458static void bribe_unit_response(GtkWidget *w, gint response, gpointer data)
459{
460 struct action_data *args = (struct action_data *)data;
461
462 if (response == GTK_RESPONSE_YES) {
464 args->target_unit_id, 0, "");
465 }
466
468 free(args);
469
470 /* The user have answered the follow up question. Move on. */
472}
473
474/**********************************************************************/
477static void bribe_stack_response(GtkWidget *w, gint response, gpointer data)
478{
479 struct action_data *args = (struct action_data *)data;
480
481 if (response == GTK_RESPONSE_YES) {
483 args->target_tile_id, 0, "");
484 }
485
487 free(args);
488
489 /* The user have answered the follow up question. Move on. */
491}
492
493/**********************************************************************/
496void popup_bribe_unit_dialog(struct unit *actor, struct unit *punit, int cost,
497 const struct action *paction)
498{
500 char buf[1024];
501
502 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
503 "Treasury contains %d gold.",
504 client_player()->economic.gold),
505 client_player()->economic.gold);
506
507 if (cost <= client_player()->economic.gold) {
510 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
511 PL_("Bribe unit for %d gold?\n%s",
512 "Bribe unit for %d gold?\n%s", cost), cost, buf);
513 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
515 } else {
518 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
519 PL_("Bribing the unit costs %d gold.\n%s",
520 "Bribing the unit costs %d gold.\n%s", cost), cost, buf);
521 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
523 }
525
527 act_data(paction->id, actor->id,
528 0, punit->id, 0,
529 0, 0, 0));
530}
531
532/**********************************************************************/
535void popup_bribe_stack_dialog(struct unit *actor, struct tile *ptile, int cost,
536 const struct action *paction)
537{
539 char buf[1024];
540
541 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
542 "Treasury contains %d gold.",
543 client_player()->economic.gold),
544 client_player()->economic.gold);
545
546 if (cost <= client_player()->economic.gold) {
549 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
550 PL_("Bribe unit stack for %d gold?\n%s",
551 "Bribe unit stack for %d gold?\n%s", cost), cost, buf);
552 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
554 } else {
557 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
558 PL_("Bribing units costs %d gold.\n%s",
559 "Bribing units costs %d gold.\n%s", cost), cost, buf);
560 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
562 }
564
566 act_data(paction->id, actor->id,
567 0, 0, ptile->index,
568 0, 0, 0));
569}
570
571/**********************************************************************/
574static void spy_advances_response(GtkWidget *w, gint response,
575 gpointer data)
576{
577 struct action_data *args = (struct action_data *)data;
578
579 if (response == GTK_RESPONSE_ACCEPT && args->target_tech_id > 0) {
582 if (args->target_tech_id == A_UNSET) {
583 /* This is the untargeted version. */
585 args->actor_unit_id, args->target_city_id,
586 args->target_tech_id, "");
587 } else {
588 /* This is the targeted version. */
590 args->actor_unit_id, args->target_city_id,
591 args->target_tech_id, "");
592 }
593 }
594 }
595
598 free(data);
599
600 /* The user have answered the follow up question. Move on. */
602}
603
604/**********************************************************************/
608 gpointer data)
609{
610 struct action_data *args = (struct action_data *)data;
611
612 GtkTreeModel *model;
613 GtkTreeIter it;
614
615 if (gtk_tree_selection_get_selected(select, &model, &it)) {
616 gtk_tree_model_get(model, &it, 1, &(args->target_tech_id), -1);
617
620 } else {
621 args->target_tech_id = 0;
622
625 }
626}
627
628/**********************************************************************/
631static void create_advances_list(struct player *pplayer,
632 struct player *pvictim,
633 struct action_data *args)
634{
635 GtkWidget *sw, *label, *vbox, *view;
636 GtkListStore *store;
639
641
642 spy_tech_shell = gtk_dialog_new_with_buttons(_("Steal Technology"),
643 NULL, 0,
644 _("_Cancel"), GTK_RESPONSE_CANCEL,
645 _("_Steal"), GTK_RESPONSE_ACCEPT,
646 NULL);
649
652
653 label = gtk_frame_new(_("Select Advance to Steal"));
655
656 vbox = gtk_grid_new();
660 gtk_container_add(GTK_CONTAINER(label), vbox);
661
663
667 g_object_unref(store);
669
672 "text", 0, NULL);
674
676 "use-underline", TRUE,
677 "mnemonic-widget", view,
678 "label", _("_Advances:"),
679 "xalign", 0.0,
680 "yalign", 0.5,
681 NULL);
682 gtk_container_add(GTK_CONTAINER(vbox), label);
683
688
691 gtk_widget_set_size_request(sw, -1, 200);
692
694
695 /* Now populate the list */
696 if (pvictim) { /* you don't want to know what lag can do -- Syela */
697 const struct research *presearch = research_get(pplayer);
698 const struct research *vresearch = research_get(pvictim);
699 GtkTreeIter it;
700 GValue value = { 0, };
701
707 gtk_list_store_append(store, &it);
708
711 (presearch, i));
712 gtk_list_store_set_value(store, &it, 0, &value);
713 g_value_unset(&value);
714 gtk_list_store_set(store, &it, 1, i, -1);
715 }
717
720 gtk_list_store_append(store, &it);
721
723 {
724 struct astring str = ASTRING_INIT;
725 /* TRANS: %s is a unit name, e.g., Spy */
726 astr_set(&str, _("At %s's Discretion"),
729 astr_free(&str);
730 }
731 gtk_list_store_set_value(store, &it, 0, &value);
732 g_value_unset(&value);
733 gtk_list_store_set(store, &it, 1, A_UNSET, -1);
734 }
735 }
736
739
741
746
747 args->target_tech_id = 0;
748
750}
751
752/**********************************************************************/
755static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
756{
757 struct action_data *args = (struct action_data *)data;
758
759 if (response == GTK_RESPONSE_ACCEPT && args->target_building_id > -2) {
762 if (args->target_building_id == B_LAST) {
763 /* This is the untargeted version. */
765 args->actor_unit_id,
766 args->target_city_id,
767 args->target_building_id, "");
768 } else if (args->target_building_id == -1) {
769 /* This is the city production version. */
771 args->actor_unit_id,
772 args->target_city_id,
773 args->target_building_id, "");
774 } else {
775 /* This is the targeted version. */
777 args->actor_unit_id,
778 args->target_city_id,
779 args->target_building_id, "");
780 }
781 }
782 }
783
786 free(args);
787
788 /* The user have answered the follow up question. Move on. */
790}
791
792/**********************************************************************/
796{
797 struct action_data *args = (struct action_data *)data;
798
799 GtkTreeModel *model;
800 GtkTreeIter it;
801
802 if (gtk_tree_selection_get_selected(select, &model, &it)) {
803 gtk_tree_model_get(model, &it, 1, &(args->target_building_id), -1);
804
807 } else {
808 args->target_building_id = -2;
809
812 }
813}
814
815/**********************************************************************/
818static void create_improvements_list(struct player *pplayer,
819 struct city *pcity,
820 struct action_data *args)
821{
822 GtkWidget *sw, *label, *vbox, *view;
823 GtkListStore *store;
826 GtkTreeIter it;
827
829
830 spy_sabotage_shell = gtk_dialog_new_with_buttons(_("Sabotage Improvements"),
831 NULL, 0,
832 _("_Cancel"), GTK_RESPONSE_CANCEL,
833 _("_Sabotage"), GTK_RESPONSE_ACCEPT,
834 NULL);
837
840
841 label = gtk_frame_new(_("Select Improvement to Sabotage"));
843
844 vbox = gtk_grid_new();
848 gtk_container_add(GTK_CONTAINER(label), vbox);
849
851
855 g_object_unref(store);
857
860 "text", 0, NULL);
862
864 "use-underline", TRUE,
865 "mnemonic-widget", view,
866 "label", _("_Improvements:"),
867 "xalign", 0.0,
868 "yalign", 0.5,
869 NULL);
870 gtk_container_add(GTK_CONTAINER(vbox), label);
871
876
880
882
883 /* Now populate the list */
886 args->act_id)])) {
887 gtk_list_store_append(store, &it);
888 gtk_list_store_set(store, &it, 0, _("City Production"), 1, -1, -1);
889 }
890
891 city_built_iterate(pcity, pimprove) {
892 if (pimprove->sabotage > 0) {
893 gtk_list_store_append(store, &it);
894 gtk_list_store_set(store, &it,
896 1, improvement_number(pimprove),
897 -1);
898 }
900
903 struct astring str = ASTRING_INIT;
904
905 gtk_list_store_append(store, &it);
906
907 /* TRANS: %s is a unit name, e.g., Spy */
908 astr_set(&str, _("At %s's Discretion"),
910 gtk_list_store_set(store, &it, 0, astr_str(&str), 1, B_LAST, -1);
911
912 astr_free(&str);
913 }
914
917
919
924
925 args->target_building_id = -2;
926
928}
929
930/**********************************************************************/
934{
935 struct action_data *args = (struct action_data *)data;
936
937 args->act_id = args->act_id;
938
940 struct player *pvictim = NULL;
941
942 if (pvcity) {
944 }
945
946/* it is concievable that pvcity will not be found, because something
947has happened to the city during latency. Therefore we must initialize
948pvictim to NULL and account for !pvictim in create_advances_list. -- Syela */
949
950 /* FIXME: Don't discard the second tech choice dialog. */
951 if (!spy_tech_shell) {
954 } else {
955 free(args);
956 }
957
958 /* Wait for the player's reply before moving on to the next unit that
959 * needs to know what action to take. */
961
963}
964
965/**********************************************************************/
974
975/**********************************************************************/
984
985/**********************************************************************/
990 const struct action *paction)
991{
992 /* FIXME: Don't discard the second target choice dialog. */
993 if (!spy_sabotage_shell) {
995 act_data(paction->id,
996 actor->id, pcity->id, 0, 0,
997 0, 0, 0));
999 }
1000}
1001
1002/**********************************************************************/
1005static void incite_response(GtkWidget *w, gint response, gpointer data)
1006{
1007 struct action_data *args = (struct action_data *)data;
1008
1009 if (response == GTK_RESPONSE_YES) {
1011 args->target_city_id, 0, "");
1012 }
1013
1015 free(args);
1016
1017 /* The user have answered the follow up question. Move on. */
1019}
1020
1021/**********************************************************************/
1024void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost,
1025 const struct action *paction)
1026{
1028 char buf[1024];
1029
1030 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
1031 "Treasury contains %d gold.",
1032 client_player()->economic.gold),
1033 client_player()->economic.gold);
1034
1038 _("You can't incite a revolt in %s."),
1040 gtk_window_set_title(GTK_WINDOW(shell), _("City can't be incited!"));
1042 } else if (cost <= client_player()->economic.gold) {
1045 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1046 PL_("Incite a revolt for %d gold?\n%s",
1047 "Incite a revolt for %d gold?\n%s", cost), cost, buf);
1048 gtk_window_set_title(GTK_WINDOW(shell), _("Incite a Revolt!"));
1050 } else {
1052 0,
1054 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1055 PL_("Inciting a revolt costs %d gold.\n%s",
1056 "Inciting a revolt costs %d gold.\n%s", cost), cost, buf);
1057 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
1059 }
1061
1063 act_data(paction->id, actor->id,
1064 pcity->id, 0, 0,
1065 0, 0, 0));
1066}
1067
1068/**********************************************************************/
1072{
1073 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1074
1075 if (arg == GTK_RESPONSE_YES) {
1077
1078 if (actor != NULL) {
1080 "target"));
1082 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1083
1084 if (tgt_unit == NULL) {
1085 /* Make the action dialog pop up again. */
1087 actor->id,
1088 /* Let the server choose the target
1089 * unit. */
1091 tgt_tile->index,
1094 } else {
1096 actor->id,
1097 tgt_id,
1098 tgt_tile->index,
1101 }
1102 }
1103 } else {
1104 /* Dialog canceled. This ends the action selection process. */
1106 }
1107
1108 gtk_widget_destroy(dlg);
1109}
1110
1111/**********************************************************************/
1115{
1116 struct action_data *args = act_sel_dialog_data;
1117
1118 struct unit *punit;
1119 struct unit *tunit;
1120 struct tile *ptile;
1121
1123 && (ptile = index_to_tile(&(wld.map), args->target_tile_id))
1124 && (tunit = game_unit_by_number(args->target_unit_id))) {
1125 select_tgt_unit(punit, ptile, ptile->units, tunit,
1126 _("Target unit selection"),
1127 _("Looking for target unit:"),
1128 _("Units at tile:"),
1129 _("Select"),
1131 }
1132
1136 free(args);
1137}
1138
1139/**********************************************************************/
1143{
1144 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1145
1146 if (arg == GTK_RESPONSE_YES) {
1148
1149 if (actor != NULL) {
1151 "target"));
1153 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1154
1155 if (tgt_extra == NULL) {
1156 /* Make the action dialog pop up again. */
1158 actor->id,
1160 tgt_tile->index,
1161 /* Let the server choose the target
1162 * extra. */
1165 } else {
1167 actor->id,
1169 tgt_tile->index,
1170 tgt_id,
1172 }
1173 }
1174 } else {
1175 /* Dialog canceled. This ends the action selection process. */
1177 }
1178
1179 gtk_widget_destroy(dlg);
1180}
1181
1182/**********************************************************************/
1186{
1187 struct action_data *args = act_sel_dialog_data;
1188
1189 struct unit *act_unit;
1190 struct extra_type *tgt_extra;
1191 struct tile *tgt_tile;
1192
1194 && (tgt_tile = index_to_tile(&(wld.map), args->target_tile_id))
1197
1198 /* Start with the extras at the tile */
1200
1202 if (BV_ISSET(potential_targets, extra_number(pextra))) {
1203 /* This extra is at the tile. Can anything be done to it? */
1205 pextra)) {
1207 }
1208 } else {
1209 /* This extra isn't at the tile yet. Can it be created? */
1211 pextra)) {
1213 }
1214 }
1216
1218 /* TRANS: GTK action selection dialog extra target
1219 * selection dialog title. */
1220 _("Target extra selection"),
1221 /* TRANS: GTK action selection dialog extra target
1222 * selection dialog actor unit label. */
1223 _("Looking for target extra:"),
1224 /* TRANS: GTK action selection dialog extra target
1225 * selection dialog extra list label. */
1226 _("Extra targets:"),
1227 _("Select"),
1229 }
1230
1234 free(args);
1235}
1236
1237/**********************************************************************/
1241{
1242 struct action_data *args = act_sel_dialog_data;
1243
1244 struct unit *punit;
1245
1246 if ((punit = game_unit_by_number(args->actor_unit_id))) {
1248 }
1249}
1250
1251/**********************************************************************/
1255{
1256 struct action_data *args = act_sel_dialog_data;
1257
1258 key_unit_wait();
1259
1260 /* the dialog was destroyed when key_unit_wait() resulted in
1261 * action_selection_close() being called. */
1262
1263 free(args);
1264}
1265
1266/**********************************************************************/
1274
1275/**********************************************************************/
1283
1284/**********************************************************************/
1294
1295/* Mapping from an action to the function to call when its button is
1296 * pushed. */
1298 /* Unit acting against a city target. */
1309
1310 /* Unit acting against a unit target. */
1312
1313 /* Unit acting against all units at a tile. */
1315
1316 /* Unit acting against a tile. */
1318
1319 /* Unit acting with no target except itself. */
1320 /* No special callback functions needed for any self targeted actions. */
1321};
1322
1323/**********************************************************************/
1328 const struct act_prob *act_probs,
1329 const char *custom,
1331{
1332 const gchar *label;
1333 const gchar *tooltip;
1334 GCallback cb;
1335
1336 if (af_map[act_id] == NULL) {
1337 /* No special call back function needed for this action. */
1339 } else {
1340 /* Special action specific callback function specified. */
1341 cb = af_map[act_id];
1342 }
1343
1344 /* Don't show disabled actions. */
1346 return;
1347 }
1348
1349 label = action_prepare_ui_name(act_id, "_",
1351 custom);
1352
1354 act_probs[act_id]);
1355
1358 FALSE, tooltip);
1359}
1360
1361/**********************************************************************/
1366 const struct act_prob *act_probs,
1367 const char *custom,
1369{
1370 const gchar *label;
1371 const gchar *tooltip;
1372
1373 /* An action that just became impossible has its button disabled.
1374 * An action that became possible again must be re-enabled. */
1378
1379 /* The probability may have changed. */
1380 label = action_prepare_ui_name(act_id, "_",
1382
1384 act_probs[act_id]);
1385
1388 label);
1391 tooltip);
1392}
1393
1394/**********************************************************************/
1399 struct city *target_city,
1400 struct unit *target_unit,
1401 struct tile *target_tile,
1402 struct extra_type *target_extra,
1403 const struct act_prob *act_probs)
1404{
1405 GtkWidget *shl;
1406 struct astring title = ASTRING_INIT, text = ASTRING_INIT;
1407 struct city *actor_homecity;
1408
1409 int button_id;
1410
1412 act_data(ACTION_ANY, /* Not decided yet */
1413 actor_unit->id,
1417 /* No target_building or target_tech supplied. (Dec 2019) */
1418 B_LAST, A_UNSET,
1420
1421 /* Could be caused by the server failing to reply to a request for more
1422 * information or a bug in the client code. */
1424 "Diplomat queue problem. Is another diplomat window open?");
1425
1426 /* No extra input is required as no action has been chosen yet. */
1428
1429 /* No buttons are added yet. */
1430 for (button_id = 0; button_id < BUTTON_COUNT; button_id++) {
1432 }
1433
1435
1439 target_city->id :
1442 target_unit->id :
1455 EXTRA_NONE;
1456
1457 astr_set(&title,
1458 /* TRANS: %s is a unit name, e.g., Spy */
1459 _("Choose Your %s's Strategy"),
1461
1462 if (target_city && actor_homecity) {
1463 astr_set(&text,
1464 _("Your %s from %s reaches the city of %s.\nWhat now?"),
1468 } else if (target_city) {
1469 astr_set(&text,
1470 _("Your %s has arrived at %s.\nWhat is your command?"),
1473 } else if (target_unit) {
1474 astr_set(&text,
1475 /* TRANS: Your Spy is ready to act against Roman Freight. */
1476 _("Your %s is ready to act against %s %s."),
1480 } else {
1482 "No target specified.");
1483 astr_set(&text,
1484 /* TRANS: %s is a unit name, e.g., Diplomat, Spy */
1485 _("Your %s is waiting for your command."),
1487 }
1488
1490 astr_str(&text));
1491
1492 /* Unit acting against a city */
1493
1494 action_iterate(act) {
1499 act_probs[act],
1500 actor_unit,
1501 target_city),
1502 act);
1503 }
1505
1506 /* Unit acting against another unit */
1507
1508 action_iterate(act) {
1513 act_probs[act],
1514 actor_unit,
1515 target_city),
1516 act);
1517 }
1519
1520 /* Unit acting against all units at a tile */
1521
1522 action_iterate(act) {
1527 act_probs[act],
1528 actor_unit,
1529 target_city),
1530 act);
1531 }
1533
1534 /* Unit acting against a tile */
1535
1536 action_iterate(act) {
1541 act_probs[act],
1542 actor_unit,
1543 target_city),
1544 act);
1545 }
1547
1548 /* Unit acting against a tile's extras */
1549
1550 action_iterate(act) {
1555 act_probs[act],
1556 actor_unit,
1557 target_city),
1558 act);
1559 }
1561
1562 /* Unit acting against itself. */
1563
1564 action_iterate(act) {
1569 act_probs[act],
1570 actor_unit,
1571 target_city),
1572 act);
1573 }
1575
1576 if (target_unit != NULL
1577 && unit_list_size(target_tile->units) > 1) {
1580 choice_dialog_add(shl, _("Change unit target"),
1583 }
1584
1585 if (target_extra != NULL) {
1588 choice_dialog_add(shl, _("Change extra target"),
1591 }
1592
1595 choice_dialog_add(shl, _("Show Location"),
1598 TRUE, NULL);
1599
1602 choice_dialog_add(shl, _("_Wait"),
1605 TRUE, NULL);
1606
1609 choice_dialog_add(shl, _("_Cancel"),
1612 FALSE, NULL);
1613
1615
1617
1619 g_signal_connect(shl, "destroy",
1621 g_signal_connect(shl, "delete_event",
1624
1625 /* Give follow up questions access to action probabilities. */
1627 action_iterate(act) {
1630
1631 astr_free(&title);
1632 astr_free(&text);
1633}
1634
1635/**********************************************************************/
1641{
1642 if (act_sel_dialog == NULL) {
1643 return IDENTITY_NUMBER_ZERO;
1644 }
1645 return actor_unit_id;
1646}
1647
1648/**********************************************************************/
1655{
1656 if (act_sel_dialog == NULL) {
1657 return IDENTITY_NUMBER_ZERO;
1658 }
1659 return target_ids[ATK_CITY];
1660}
1661
1662/**********************************************************************/
1669{
1670 if (act_sel_dialog == NULL) {
1671 return IDENTITY_NUMBER_ZERO;
1672 }
1673
1674 return target_ids[ATK_UNIT];
1675}
1676
1677/**********************************************************************/
1684{
1685 if (act_sel_dialog == NULL) {
1686 return TILE_INDEX_NONE;
1687 }
1688
1689 return target_ids[ATK_TILE];
1690}
1691
1692/**********************************************************************/
1699{
1700 if (act_sel_dialog == NULL) {
1701 return EXTRA_NONE;
1702 }
1703
1704 return target_extra_id;
1705}
1706
1707/**********************************************************************/
1711 struct city *target_city,
1712 struct unit *target_unit,
1713 struct tile *target_tile,
1714 struct extra_type *target_extra,
1715 const struct act_prob *act_probs)
1716{
1717 if (act_sel_dialog == NULL) {
1719 "The action selection dialog should have been open");
1720 return;
1721 }
1722
1725 "The action selection dialog is for another actor unit.");
1726 return;
1727 }
1728
1729 /* A new target may have appeared. */
1730 if (target_city) {
1732 }
1733 if (target_unit) {
1735 }
1736 if (target_tile) {
1738 }
1739 /* No target_building or target_tech supplied. (Dec 2019) */
1740 if (target_extra) {
1742 }
1743
1744 action_iterate(act) {
1745 const char *custom;
1746
1747 if (action_id_get_actor_kind(act) != AAK_UNIT) {
1748 /* Not relevant. */
1749 continue;
1750 }
1751
1753 act_probs[act],
1754 actor_unit,
1755 target_city);
1756
1757 if (BUTTON_NOT_THERE == action_button_map[act]) {
1758 /* Add the button (unless its probability is 0). */
1760 } else {
1761 /* Update the existing button. */
1763 }
1765
1766 /* DO NOT change the action_button_map[] for any button to reflect its
1767 * new position. A button keeps its choice dialog internal name when its
1768 * position changes. A button's id number is therefore based on when
1769 * it was added, not on its current position. */
1770
1772 /* Move the wait button below the recently added button. */
1775 }
1776
1778 /* Move the cancel button below the recently added button. */
1781 }
1782
1784}
1785
1786/**********************************************************************/
1790{
1791 if (act_sel_dialog != NULL) {
1794 }
1795}
const char * action_prepare_ui_name(action_id act_id, const char *mnemonic, const struct act_prob prob, const char *custom)
Definition actions.c:1312
enum action_actor_kind action_get_actor_kind(const struct action *paction)
Definition actions.c:1098
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5091
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1119
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1108
static struct action * action_by_number(action_id act_id)
Definition actions.h:396
#define action_iterate_end
Definition actions.h:214
#define action_id_get_actor_kind(act_id)
Definition actions.h:409
#define action_iterate(_act_)
Definition actions.h:210
#define ACTION_ANY
Definition actions.h:52
#define action_id_get_target_kind(act_id)
Definition actions.h:413
#define ACTION_NONE
Definition actions.h:55
void astr_free(struct astring *astr)
Definition astring.c:148
void astr_set(struct astring *astr, const char *format,...)
Definition astring.c:251
#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:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:663
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
#define INCITE_IMPOSSIBLE_COST
Definition city.h:93
#define city_owner(_pcity_)
Definition city.h:560
#define city_built_iterate(_pcity, _p)
Definition city.h:831
#define city_built_iterate_end
Definition city.h:837
struct civclient client
#define client_player()
void client_unit_init_act_prob_cache(struct unit *punit)
Definition climisc.c:1259
char * incite_cost
Definition comments.c:76
void action_selection_no_longer_in_progress(const int old_actor_id)
Definition control.c:1051
void request_do_action(action_id action, int actor_id, int target_id, int sub_tgt, const char *name)
Definition control.c:1730
void request_action_details(action_id action, int actor_id, int target_id)
Definition control.c:1798
void action_decision_clear_want(const int old_actor_id)
Definition control.c:1080
void key_unit_wait(void)
Definition control.c:3542
void action_selection_next_in_focus(const int old_actor_id)
Definition control.c:1092
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id popup_bribe_unit_dialog
Definition dialogs_g.h:73
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 const struct action *paction popup_sabotage_dialog
Definition dialogs_g.h:77
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
popup_action_selection
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 * actor
Definition dialogs_g.h:73
struct unit * actor_unit
Definition dialogs_g.h:55
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:69
struct unit struct city struct unit struct tile * target_tile
Definition dialogs_g.h:57
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:74
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 const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
struct unit struct city * target_city
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 int cost
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type * target_extra
Definition dialogs_g.h:57
int extra_number(const struct extra_type *pextra)
Definition extras.c:161
struct extra_type * extra_by_number(int id)
Definition extras.c:183
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_re_active_iterate_end
Definition extras.h:329
#define extra_type_re_active_iterate(_p)
Definition extras.h:325
#define NO_TARGET
Definition fc_types.h:213
int action_id
Definition fc_types.h:248
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:92
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
struct unit * game_unit_by_number(int id)
Definition game.c:115
struct city * game_city_by_number(int id)
Definition game.c:106
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)
void popup_bribe_stack_dialog(struct unit *actor, struct tile *ptile, int cost, const struct action *paction)
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)
#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 bribe_stack_response(GtkWidget *w, gint response, 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
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 bribe_unit_response(GtkWidget *w, gint response, 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:1435
GtkWidget * toplevel
Definition gui_main.c:126
void gtk_tree_view_focus(GtkTreeView *view)
Definition gui_stuff.c:236
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
static struct gui_dialog * shell
Definition messagedlg.c:39
const char * tooltip
Definition repodlgs.c:1315
const char * title
Definition repodlgs.c:1314
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:182
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action(condition, action)
Definition log.h:188
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
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:169
#define REQEST_PLAYER_INITIATED
Definition packets.h:63
int dsend_packet_unit_get_actions(struct connection *pc, int actor_unit_id, int target_unit_id, int target_tile_id, int target_extra_id, int request_kind)
int dsend_packet_city_name_suggestion_req(struct connection *pc, int unit_id)
const char * research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Definition research.c:273
struct research * research_get(const struct player *pplayer)
Definition research.c:128
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:693
#define ARRAY_SIZE(x)
Definition shared.h:85
int target_building_id
action_id act_id
Definition city.h:317
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
struct player * playing
Definition connection.h:151
bool tech_steal_allow_holes
Definition tile.h:50
int index
Definition tile.h:51
struct unit_list * units
Definition tile.h:58
Definition unit.h:140
int id
Definition unit.h:147
int index
Definition unit.h:198
struct unit::@84::@86 client
struct act_prob * act_prob_cache
Definition unit.h:231
int homecity
Definition unit.h:148
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
#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:244
#define A_FIRST
Definition tech.h:44
#define A_UNSET
Definition tech.h:48
#define advance_index_iterate(_start, _index)
Definition tech.h:240
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:1757
const char * act_sel_action_tool_tip(const struct action *paction, const struct act_prob prob)
Definition text.c:1836
#define tile_index(_pt_)
Definition tile.h:89
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:121
#define TILE_INDEX_NONE
Definition tile.h:48
#define unit_tile(_pu)
Definition unit.h:404
#define unit_owner(_pu)
Definition unit.h:403
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:247
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1575
bool utype_can_create_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:223