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-5.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
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. */
81struct action_data {
83 int actor_unit_id;
90};
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_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:
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_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:
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 struct action_data *args = act_sel_dialog_data;
439
442 struct unit_list *as_list;
443
448 }
449
451 free(args);
452}
453
454/**********************************************************************/
457static void bribe_response(GtkWidget *w, gint response, gpointer data)
458{
459 struct action_data *args = (struct action_data *)data;
460
461 if (response == GTK_RESPONSE_YES) {
463 args->target_unit_id, 0, "");
464 }
465
467 free(args);
468
469 /* The user have answered the follow up question. Move on. */
471}
472
473/**********************************************************************/
476void popup_bribe_dialog(struct unit *actor, struct unit *punit, int cost,
477 const struct action *paction)
478{
480 char buf[1024];
481
482 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
483 "Treasury contains %d gold.",
484 client_player()->economic.gold),
485 client_player()->economic.gold);
486
487 if (cost <= client_player()->economic.gold) {
490 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
491 PL_("Bribe unit for %d gold?\n%s",
492 "Bribe unit for %d gold?\n%s", cost), cost, buf);
493 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
495 } else {
498 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
499 PL_("Bribing the unit costs %d gold.\n%s",
500 "Bribing the unit costs %d gold.\n%s", cost), cost, buf);
501 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
503 }
505
507 act_data(paction->id, actor->id,
508 0, punit->id, 0,
509 0, 0, 0));
510}
511
512/**********************************************************************/
515static void spy_advances_response(GtkWidget *w, gint response,
516 gpointer data)
517{
518 struct action_data *args = (struct action_data *)data;
519
520 if (response == GTK_RESPONSE_ACCEPT && args->target_tech_id > 0) {
523 if (args->target_tech_id == A_UNSET) {
524 /* This is the untargeted version. */
526 args->actor_unit_id, args->target_city_id,
527 args->target_tech_id, "");
528 } else {
529 /* This is the targeted version. */
531 args->actor_unit_id, args->target_city_id,
532 args->target_tech_id, "");
533 }
534 }
535 }
536
539 free(data);
540
541 /* The user have answered the follow up question. Move on. */
543}
544
545/**********************************************************************/
549 gpointer data)
550{
551 struct action_data *args = (struct action_data *)data;
552
553 GtkTreeModel *model;
554 GtkTreeIter it;
555
556 if (gtk_tree_selection_get_selected(select, &model, &it)) {
557 gtk_tree_model_get(model, &it, 1, &(args->target_tech_id), -1);
558
561 } else {
562 args->target_tech_id = 0;
563
566 }
567}
568
569/**********************************************************************/
572static void create_advances_list(struct player *pplayer,
573 struct player *pvictim,
574 struct action_data *args)
575{
576 GtkWidget *sw, *frame, *label, *vgrid, *view;
577 GtkListStore *store;
580
582
583 spy_tech_shell = gtk_dialog_new_with_buttons(_("Steal Technology"),
584 NULL, 0,
585 _("_Cancel"), GTK_RESPONSE_CANCEL,
586 _("_Steal"), GTK_RESPONSE_ACCEPT,
587 NULL);
589
592
593 frame = gtk_frame_new(_("Select Advance to Steal"));
595
601
603
607 g_object_unref(store);
609
612 "text", 0, NULL);
614
616 "use-underline", TRUE,
617 "mnemonic-widget", view,
618 "label", _("_Advances:"),
619 "xalign", 0.0,
620 "yalign", 0.5,
621 NULL);
622 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
623
627
630 gtk_widget_set_size_request(sw, -1, 200);
631
632 gtk_grid_attach(GTK_GRID(vgrid), sw, 0, 1, 1, 1);
633
634 /* Now populate the list */
635 if (pvictim) { /* You don't want to know what lag can do -- Syela */
636 const struct research *presearch = research_get(pplayer);
637 const struct research *vresearch = research_get(pvictim);
638 GtkTreeIter it;
639 GValue value = { 0, };
640
646 gtk_list_store_append(store, &it);
647
650 (presearch, i));
651 gtk_list_store_set_value(store, &it, 0, &value);
652 g_value_unset(&value);
653 gtk_list_store_set(store, &it, 1, i, -1);
654 }
656
659 gtk_list_store_append(store, &it);
660
662 {
663 struct astring str = ASTRING_INIT;
664 /* TRANS: %s is a unit name, e.g., Spy */
665 astr_set(&str, _("At %s's Discretion"),
668 astr_free(&str);
669 }
670 gtk_list_store_set_value(store, &it, 0, &value);
671 g_value_unset(&value);
672 gtk_list_store_set(store, &it, 1, A_UNSET, -1);
673 }
674 }
675
678
680 TRUE);
681
686
687 args->target_tech_id = 0;
688
690}
691
692/**********************************************************************/
695static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
696{
697 struct action_data *args = (struct action_data *)data;
698
699 if (response == GTK_RESPONSE_ACCEPT && args->target_building_id > -2) {
702 if (args->target_building_id == B_LAST) {
703 /* This is the untargeted version. */
705 args->actor_unit_id,
706 args->target_city_id,
707 args->target_building_id, "");
708 } else if (args->target_building_id == -1) {
709 /* This is the city production version. */
711 args->actor_unit_id,
712 args->target_city_id,
713 args->target_building_id, "");
714 } else {
715 /* This is the targeted version. */
717 args->actor_unit_id,
718 args->target_city_id,
719 args->target_building_id, "");
720 }
721 }
722 }
723
726 free(args);
727
728 /* The user have answered the follow up question. Move on. */
730}
731
732/**********************************************************************/
736{
737 struct action_data *args = (struct action_data *)data;
738
739 GtkTreeModel *model;
740 GtkTreeIter it;
741
742 if (gtk_tree_selection_get_selected(select, &model, &it)) {
743 gtk_tree_model_get(model, &it, 1, &(args->target_building_id), -1);
744
747 } else {
748 args->target_building_id = -2;
749
752 }
753}
754
755/**********************************************************************/
758static void create_improvements_list(struct player *pplayer,
759 struct city *pcity,
760 struct action_data *args)
761{
762 GtkWidget *sw, *frame, *label, *vgrid, *view;
763 GtkListStore *store;
766 GtkTreeIter it;
767
769
770 spy_sabotage_shell = gtk_dialog_new_with_buttons(_("Sabotage Improvements"),
771 NULL, 0,
772 _("_Cancel"), GTK_RESPONSE_CANCEL,
773 _("_Sabotage"), GTK_RESPONSE_ACCEPT,
774 NULL);
776
779
780 frame = gtk_frame_new(_("Select Improvement to Sabotage"));
782
788
790
794 g_object_unref(store);
796
799 "text", 0, NULL);
801
803 "use-underline", TRUE,
804 "mnemonic-widget", view,
805 "label", _("_Improvements:"),
806 "xalign", 0.0,
807 "yalign", 0.5,
808 NULL);
809 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
810
814
818
819 gtk_grid_attach(GTK_GRID(vgrid), sw, 0, 1, 1, 1);
820
821 /* Now populate the list */
824 args->act_id)])) {
825 gtk_list_store_append(store, &it);
826 gtk_list_store_set(store, &it, 0, _("City Production"), 1, -1, -1);
827 }
828
829 city_built_iterate(pcity, pimprove) {
830 if (pimprove->sabotage > 0) {
831 gtk_list_store_append(store, &it);
832 gtk_list_store_set(store, &it,
833 0, city_improvement_name_translation(pcity, pimprove),
834 1, improvement_number(pimprove),
835 -1);
836 }
838
841 struct astring str = ASTRING_INIT;
842
843 gtk_list_store_append(store, &it);
844
845 /* TRANS: %s is a unit name, e.g., Spy */
846 astr_set(&str, _("At %s's Discretion"),
848 gtk_list_store_set(store, &it, 0, astr_str(&str), 1, B_LAST, -1);
849
850 astr_free(&str);
851 }
852
855
857 TRUE);
858
863
864 args->target_building_id = -2;
865
867}
868
869/**********************************************************************/
873{
874 struct action_data *args = (struct action_data *)data;
875
876 args->act_id = args->act_id;
877
879 struct player *pvictim = NULL;
880
881 if (pvcity) {
883 }
884
885/* It is concievable that pvcity will not be found, because something
886 has happened to the city during latency. Therefore we must initialize
887 pvictim to NULL and account for !pvictim in create_advances_list. -- Syela */
888
889 /* FIXME: Don't discard the second tech choice dialog. */
890 if (!spy_tech_shell) {
893 } else {
894 free(args);
895 }
896
897 /* Wait for the player's reply before moving on to the next unit that
898 * needs to know what action to take. */
900
902}
903
904/**********************************************************************/
913
914/**********************************************************************/
923
924/**********************************************************************/
928void popup_sabotage_dialog(struct unit *actor, struct city *pcity,
929 const struct action *paction)
930{
931 /* FIXME: Don't discard the second target choice dialog. */
932 if (!spy_sabotage_shell) {
934 act_data(paction->id,
935 actor->id, pcity->id, 0, 0,
936 0, 0, 0));
938 }
939}
940
941/**********************************************************************/
944static void incite_response(GtkWidget *w, gint response, gpointer data)
945{
946 struct action_data *args = (struct action_data *)data;
947
948 if (response == GTK_RESPONSE_YES) {
950 args->target_city_id, 0, "");
951 }
952
954 free(args);
955
956 /* The user have answered the follow up question. Move on. */
958}
959
960/**********************************************************************/
963void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost,
964 const struct action *paction)
965{
967 char buf[1024];
968
969 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
970 "Treasury contains %d gold.",
971 client_player()->economic.gold),
972 client_player()->economic.gold);
973
977 _("You can't incite a revolt in %s."),
978 city_name_get(pcity));
979 gtk_window_set_title(GTK_WINDOW(shell), _("City can't be incited!"));
981 } else if (cost <= client_player()->economic.gold) {
984 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
985 PL_("Incite a revolt for %d gold?\n%s",
986 "Incite a revolt for %d gold?\n%s", cost), cost, buf);
987 gtk_window_set_title(GTK_WINDOW(shell), _("Incite a Revolt!"));
989 } else {
991 0,
993 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
994 PL_("Inciting a revolt costs %d gold.\n%s",
995 "Inciting a revolt costs %d gold.\n%s", cost), cost, buf);
996 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
998 }
1000
1002 act_data(paction->id, actor->id,
1003 pcity->id, 0, 0,
1004 0, 0, 0));
1005}
1006
1007/**********************************************************************/
1011{
1012 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1013
1014 if (arg == GTK_RESPONSE_YES) {
1016
1017 if (actor != NULL) {
1019 "target"));
1021 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1022
1023 if (tgt_unit == NULL) {
1024 /* Make the action dialog pop up again. */
1026 actor->id,
1027 /* Let the server choose the target
1028 * unit. */
1030 tgt_tile->index,
1033 } else {
1035 actor->id,
1036 tgt_id,
1037 tgt_tile->index,
1040 }
1041 }
1042 } else {
1043 /* Dialog canceled. This ends the action selection process. */
1045 }
1046
1048}
1049
1050/**********************************************************************/
1054{
1055 struct action_data *args = act_sel_dialog_data;
1056
1057 struct unit *punit;
1058 struct unit *tunit;
1059 struct tile *ptile;
1060
1062 && (ptile = index_to_tile(&(wld.map), args->target_tile_id))
1063 && (tunit = game_unit_by_number(args->target_unit_id))) {
1064 select_tgt_unit(punit, ptile, ptile->units, tunit,
1065 _("Target unit selection"),
1066 _("Looking for target unit:"),
1067 _("Units at tile:"),
1068 _("Select"),
1070 }
1071
1075 free(args);
1076}
1077
1078/**********************************************************************/
1082{
1083 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1084
1085 if (arg == GTK_RESPONSE_YES) {
1087
1088 if (actor != NULL) {
1090 "target"));
1092 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1093
1094 if (tgt_extra == NULL) {
1095 /* Make the action dialog pop up again. */
1097 actor->id,
1099 tgt_tile->index,
1100 /* Let the server choose the target
1101 * extra. */
1104 } else {
1106 actor->id,
1108 tgt_tile->index,
1109 tgt_id,
1111 }
1112 }
1113 } else {
1114 /* Dialog canceled. This ends the action selection process. */
1116 }
1117
1119}
1120
1121/**********************************************************************/
1125{
1126 struct action_data *args = act_sel_dialog_data;
1127
1128 struct unit *act_unit;
1129 struct extra_type *tgt_extra;
1130 struct tile *tgt_tile;
1131
1133 && (tgt_tile = index_to_tile(&(wld.map), args->target_tile_id))
1136
1137 /* Start with the extras at the tile */
1139
1141 if (BV_ISSET(potential_targets, extra_number(pextra))) {
1142 /* This extra is at the tile. Can anything be done to it? */
1144 pextra)) {
1146 }
1147 } else {
1148 /* This extra isn't at the tile yet. Can it be created? */
1150 pextra)) {
1152 }
1153 }
1155
1157 /* TRANS: GTK action selection dialog extra target
1158 * selection dialog title. */
1159 _("Target extra selection"),
1160 /* TRANS: GTK action selection dialog extra target
1161 * selection dialog actor unit label. */
1162 _("Looking for target extra:"),
1163 /* TRANS: GTK action selection dialog extra target
1164 * selection dialog extra list label. */
1165 _("Extra targets:"),
1166 _("Select"),
1168 }
1169
1173 free(args);
1174}
1175
1176/**********************************************************************/
1180{
1181 struct action_data *args = act_sel_dialog_data;
1182
1183 struct unit *punit;
1184
1185 if ((punit = game_unit_by_number(args->actor_unit_id))) {
1187 }
1188}
1189
1190/**********************************************************************/
1194{
1195 struct action_data *args = act_sel_dialog_data;
1196
1197 key_unit_wait();
1198
1199 /* The dialog was destroyed when key_unit_wait() resulted in
1200 * action_selection_close() being called. */
1201
1202 free(args);
1203}
1204
1205/**********************************************************************/
1213
1214/**********************************************************************/
1222
1223/**********************************************************************/
1231
1232/* Mapping from an action to the function to call when its button is
1233 * pushed. */
1235 /* Unit acting against a city target. */
1246
1247 /* Unit acting against a unit target. */
1249
1250 /* Unit acting against all units at a tile. */
1251 /* No special callback functions needed for any unit stack targeted
1252 * actions. */
1253
1254 /* Unit acting against a tile. */
1256
1257 /* Unit acting with no target except itself. */
1258 /* No special callback functions needed for any self targeted actions. */
1259};
1260
1261/**********************************************************************/
1266 const struct act_prob *act_probs,
1267 const char *custom,
1269{
1270 const gchar *label;
1271 const gchar *tooltip;
1272 GCallback cb;
1273
1274 if (af_map[act_id] == NULL) {
1275 /* No special call back function needed for this action. */
1277 } else {
1278 /* Special action specific callback function specified. */
1279 cb = af_map[act_id];
1280 }
1281
1282 /* Don't show disabled actions. */
1284 return;
1285 }
1286
1287 label = action_prepare_ui_name(act_id, "_",
1289 custom);
1290
1292 act_probs[act_id]);
1293
1296 FALSE, tooltip);
1297}
1298
1299/**********************************************************************/
1304 const struct act_prob *act_probs,
1305 const char *custom,
1307{
1308 const gchar *label;
1309 const gchar *tooltip;
1310
1311 /* An action that just became impossible has its button disabled.
1312 * An action that became possible again must be re-enabled. */
1316
1317 /* The probability may have changed. */
1318 label = action_prepare_ui_name(act_id, "_",
1320
1322 act_probs[act_id]);
1323
1326 label);
1329 tooltip);
1330}
1331
1332/**********************************************************************/
1337 struct city *target_city,
1338 struct unit *target_unit,
1339 struct tile *target_tile,
1340 struct extra_type *target_extra,
1341 const struct act_prob *act_probs)
1342{
1343 GtkWidget *shl;
1344 struct astring title = ASTRING_INIT, text = ASTRING_INIT;
1345 struct city *actor_homecity;
1346
1347 int button_id;
1348
1350 act_data(ACTION_ANY, /* Not decided yet */
1351 actor_unit->id,
1355 /* No target_building or target_tech supplied. (Dec 2019) */
1356 B_LAST, A_UNSET,
1358
1359 /* Could be caused by the server failing to reply to a request for more
1360 * information or a bug in the client code. */
1362 "Diplomat queue problem. Is another diplomat window open?");
1363
1364 /* No extra input is required as no action has been chosen yet. */
1366
1367 /* No buttons are added yet. */
1368 for (button_id = 0; button_id < BUTTON_COUNT; button_id++) {
1370 }
1371
1373
1377 target_city->id :
1380 target_unit->id :
1393 EXTRA_NONE;
1394
1395 astr_set(&title,
1396 /* TRANS: %s is a unit name, e.g., Spy */
1397 _("Choose Your %s's Strategy"),
1399
1400 if (target_city && actor_homecity) {
1401 astr_set(&text,
1402 _("Your %s from %s reaches the city of %s.\nWhat now?"),
1406 } else if (target_city) {
1407 astr_set(&text,
1408 _("Your %s has arrived at %s.\nWhat is your command?"),
1411 } else if (target_unit) {
1412 astr_set(&text,
1413 /* TRANS: Your Spy is ready to act against Roman Freight. */
1414 _("Your %s is ready to act against %s %s."),
1418 } else {
1420 "No target specified.");
1421 astr_set(&text,
1422 /* TRANS: %s is a unit name, e.g., Diplomat, Spy */
1423 _("Your %s is waiting for your command."),
1425 }
1426
1428 astr_str(&text));
1429
1430 /* Unit acting against a city */
1431
1432 action_iterate(act) {
1437 act_probs[act],
1438 actor_unit,
1439 target_city),
1440 act);
1441 }
1443
1444 /* Unit acting against another unit */
1445
1446 action_iterate(act) {
1451 act_probs[act],
1452 actor_unit,
1453 target_city),
1454 act);
1455 }
1457
1458 /* Unit acting against all units at a tile */
1459
1460 action_iterate(act) {
1465 act_probs[act],
1466 actor_unit,
1467 target_city),
1468 act);
1469 }
1471
1472 /* Unit acting against a tile */
1473
1474 action_iterate(act) {
1479 act_probs[act],
1480 actor_unit,
1481 target_city),
1482 act);
1483 }
1485
1486 /* Unit acting against a tile's extras */
1487
1488 action_iterate(act) {
1493 act_probs[act],
1494 actor_unit,
1495 target_city),
1496 act);
1497 }
1499
1500 /* Unit acting against itself. */
1501
1502 action_iterate(act) {
1507 act_probs[act],
1508 actor_unit,
1509 target_city),
1510 act);
1511 }
1513
1514 if (target_unit != NULL
1515 && unit_list_size(target_tile->units) > 1) {
1518 choice_dialog_add(shl, _("Change unit target"),
1521 }
1522
1523 if (target_extra != NULL) {
1526 choice_dialog_add(shl, _("Change extra target"),
1529 }
1530
1533 choice_dialog_add(shl, _("Show Location"),
1536 TRUE, NULL);
1537
1540 choice_dialog_add(shl, _("_Wait"),
1543 TRUE, NULL);
1544
1547 choice_dialog_add(shl, _("_Cancel"),
1550 FALSE, NULL);
1551
1553
1555
1557 g_signal_connect(shl, "destroy",
1559 g_signal_connect(shl, "close-request",
1562
1563 /* Give follow up questions access to action probabilities. */
1565 action_iterate(act) {
1568
1569 astr_free(&title);
1570 astr_free(&text);
1571}
1572
1573/**********************************************************************/
1579{
1580 if (act_sel_dialog == NULL) {
1581 return IDENTITY_NUMBER_ZERO;
1582 }
1583 return actor_unit_id;
1584}
1585
1586/**********************************************************************/
1593{
1594 if (act_sel_dialog == NULL) {
1595 return IDENTITY_NUMBER_ZERO;
1596 }
1597 return target_ids[ATK_CITY];
1598}
1599
1600/**********************************************************************/
1607{
1608 if (act_sel_dialog == NULL) {
1609 return IDENTITY_NUMBER_ZERO;
1610 }
1611
1612 return target_ids[ATK_UNIT];
1613}
1614
1615/**********************************************************************/
1622{
1623 if (act_sel_dialog == NULL) {
1624 return TILE_INDEX_NONE;
1625 }
1626
1627 return target_ids[ATK_TILE];
1628}
1629
1630/**********************************************************************/
1637{
1638 if (act_sel_dialog == NULL) {
1639 return EXTRA_NONE;
1640 }
1641
1642 return target_extra_id;
1643}
1644
1645/**********************************************************************/
1649 struct city *target_city,
1650 struct unit *target_unit,
1651 struct tile *target_tile,
1652 struct extra_type *target_extra,
1653 const struct act_prob *act_probs)
1654{
1655 if (act_sel_dialog == NULL) {
1657 "The action selection dialog should have been open");
1658 return;
1659 }
1660
1663 "The action selection dialog is for another actor unit.");
1664 return;
1665 }
1666
1667 /* A new target may have appeared. */
1668 if (target_city) {
1670 }
1671 if (target_unit) {
1673 }
1674 if (target_tile) {
1676 }
1677 /* No target_building or target_tech supplied. (Dec 2019) */
1678 if (target_extra) {
1680 }
1681
1682 action_iterate(act) {
1683 const char *custom;
1684
1685 if (action_id_get_actor_kind(act) != AAK_UNIT) {
1686 /* Not relevant. */
1687 continue;
1688 }
1689
1691 act_probs[act],
1692 actor_unit,
1693 target_city);
1694
1695 if (BUTTON_NOT_THERE == action_button_map[act]) {
1696 /* Add the button (unless its probability is 0). */
1698 } else {
1699 /* Update the existing button. */
1701 }
1703
1704 /* DO NOT change the action_button_map[] for any button to reflect its
1705 * new position. A button keeps its choice dialog internal name when its
1706 * position changes. A button's id number is therefore based on when
1707 * it was added, not on its current position. */
1708
1710 /* Move the wait button below the recently added button. */
1713 }
1714
1716 /* Move the cancel button below the recently added button. */
1719 }
1720
1722}
1723
1724/**********************************************************************/
1728{
1729 if (act_sel_dialog != NULL) {
1732 }
1733}
const char * action_prepare_ui_name(action_id act_id, const char *mnemonic, const struct act_prob prob, const char *custom)
Definition actions.c:1287
enum action_actor_kind action_get_actor_kind(const struct action *paction)
Definition actions.c:1073
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5044
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1094
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1083
static struct action * action_by_number(action_id act_id)
Definition actions.h:390
#define action_iterate_end
Definition actions.h:209
#define action_id_get_actor_kind(act_id)
Definition actions.h:403
#define action_iterate(_act_)
Definition actions.h:205
#define ACTION_ANY
Definition actions.h:52
#define action_id_get_target_kind(act_id)
Definition actions.h:407
#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: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:663
const char * city_name_get(const struct city *pcity)
Definition city.c:1133
#define INCITE_IMPOSSIBLE_COST
Definition city.h:96
#define city_owner(_pcity_)
Definition city.h:563
#define city_built_iterate(_pcity, _p)
Definition city.h:825
#define city_built_iterate_end
Definition city.h:831
struct civclient client
#define client_player()
void client_unit_init_act_prob_cache(struct unit *punit)
Definition climisc.c:1248
char * incite_cost
Definition comments.c:74
void action_selection_no_longer_in_progress(const int old_actor_id)
Definition control.c:1033
void request_do_action(action_id action, int actor_id, int target_id, int sub_tgt, const char *name)
Definition control.c:1704
void request_action_details(action_id action, int actor_id, int target_id)
Definition control.c:1772
void action_decision_clear_want(const int old_actor_id)
Definition control.c:1054
void key_unit_wait(void)
Definition control.c:3515
void action_selection_next_in_focus(const int old_actor_id)
Definition control.c:1066
struct unit struct city struct unit * target_unit
Definition dialogs_g.h:56
popup_action_selection
Definition dialogs_g.h:55
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 int actor_unit_id popup_bribe_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 * actor
Definition dialogs_g.h:73
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 * 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:358
int action_id
Definition fc_types.h:393
#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)
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:1435
GtkWidget * toplevel
Definition gui_main.c:125
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)
void choice_dialog_destroy(GtkWidget *dlg)
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:462
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:320
int id
Definition city.h:326
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
struct unit_list * units
Definition tile.h:58
Definition unit.h:140
struct unit::@81::@83 client
int id
Definition unit.h:147
int index
Definition unit.h:198
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:249
#define A_FIRST
Definition tech.h:44
#define A_UNSET
Definition tech.h:48
#define advance_index_iterate(_start, _index)
Definition tech.h:245
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:1723
const char * act_sel_action_tool_tip(const struct action *paction, const struct act_prob prob)
Definition text.c:1802
#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:397
#define unit_owner(_pu)
Definition unit.h:396
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:241
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1569
bool utype_can_create_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:217