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-4.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_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 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_unit_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/**********************************************************************/
476static void bribe_stack_response(GtkWidget *w, gint response, gpointer data)
477{
478 struct action_data *args = (struct action_data *)data;
479
480 if (response == GTK_RESPONSE_YES) {
482 args->target_tile_id, 0, "");
483 }
484
486 free(args);
487
488 /* The user have answered the follow up question. Move on. */
490}
491
492/**********************************************************************/
495void popup_bribe_unit_dialog(struct unit *actor, struct unit *punit, int cost,
496 const struct action *paction)
497{
499 char buf[1024];
500
501 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
502 "Treasury contains %d gold.",
503 client_player()->economic.gold),
504 client_player()->economic.gold);
505
506 if (cost <= client_player()->economic.gold) {
509 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
510 PL_("Bribe unit for %d gold?\n%s",
511 "Bribe unit for %d gold?\n%s", cost), cost, buf);
512 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
514 } else {
517 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
518 PL_("Bribing the unit costs %d gold.\n%s",
519 "Bribing the unit costs %d gold.\n%s", cost), cost, buf);
520 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
522 }
524
526 act_data(paction->id, actor->id,
527 0, punit->id, 0,
528 0, 0, 0));
529}
530
531/**********************************************************************/
534void popup_bribe_stack_dialog(struct unit *actor, struct tile *ptile, int cost,
535 const struct action *paction)
536{
538 char buf[1024];
539
540 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
541 "Treasury contains %d gold.",
542 client_player()->economic.gold),
543 client_player()->economic.gold);
544
545 if (cost <= client_player()->economic.gold) {
548 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
549 PL_("Bribe unit stack for %d gold?\n%s",
550 "Bribe unit stack for %d gold?\n%s", cost), cost, buf);
551 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
553 } else {
556 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
557 PL_("Bribing units costs %d gold.\n%s",
558 "Bribing units costs %d gold.\n%s", cost), cost, buf);
559 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
561 }
563
565 act_data(paction->id, actor->id,
566 0, 0, ptile->index,
567 0, 0, 0));
568}
569
570/**********************************************************************/
573static void spy_advances_response(GtkWidget *w, gint response,
574 gpointer data)
575{
576 struct action_data *args = (struct action_data *)data;
577
578 if (response == GTK_RESPONSE_ACCEPT && args->target_tech_id > 0) {
581 if (args->target_tech_id == A_UNSET) {
582 /* This is the untargeted version. */
584 args->actor_unit_id, args->target_city_id,
585 args->target_tech_id, "");
586 } else {
587 /* This is the targeted version. */
589 args->actor_unit_id, args->target_city_id,
590 args->target_tech_id, "");
591 }
592 }
593 }
594
597 free(data);
598
599 /* The user have answered the follow up question. Move on. */
601}
602
603/**********************************************************************/
607 gpointer data)
608{
609 struct action_data *args = (struct action_data *)data;
610
611 GtkTreeModel *model;
612 GtkTreeIter it;
613
614 if (gtk_tree_selection_get_selected(select, &model, &it)) {
615 gtk_tree_model_get(model, &it, 1, &(args->target_tech_id), -1);
616
619 } else {
620 args->target_tech_id = 0;
621
624 }
625}
626
627/**********************************************************************/
630static void create_advances_list(struct player *pplayer,
631 struct player *pvictim,
632 struct action_data *args)
633{
634 GtkWidget *sw, *frame, *label, *vgrid, *view;
635 GtkListStore *store;
638
640
641 spy_tech_shell = gtk_dialog_new_with_buttons(_("Steal Technology"),
642 NULL, 0,
643 _("_Cancel"), GTK_RESPONSE_CANCEL,
644 _("_Steal"), GTK_RESPONSE_ACCEPT,
645 NULL);
647
650
651 frame = gtk_frame_new(_("Select Advance to Steal"));
653
659
661
665 g_object_unref(store);
667
670 "text", 0, NULL);
672
674 "use-underline", TRUE,
675 "mnemonic-widget", view,
676 "label", _("_Advances:"),
677 "xalign", 0.0,
678 "yalign", 0.5,
679 NULL);
680 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
681
685
688 gtk_widget_set_size_request(sw, -1, 200);
689
690 gtk_grid_attach(GTK_GRID(vgrid), sw, 0, 1, 1, 1);
691
692 /* Now populate the list */
693 if (pvictim) { /* You don't want to know what lag can do -- Syela */
694 const struct research *presearch = research_get(pplayer);
695 const struct research *vresearch = research_get(pvictim);
696 GtkTreeIter it;
697 GValue value = { 0, };
698
704 gtk_list_store_append(store, &it);
705
708 (presearch, i));
709 gtk_list_store_set_value(store, &it, 0, &value);
710 g_value_unset(&value);
711 gtk_list_store_set(store, &it, 1, i, -1);
712 }
714
717 gtk_list_store_append(store, &it);
718
720 {
721 struct astring str = ASTRING_INIT;
722 /* TRANS: %s is a unit name, e.g., Spy */
723 astr_set(&str, _("At %s's Discretion"),
726 astr_free(&str);
727 }
728 gtk_list_store_set_value(store, &it, 0, &value);
729 g_value_unset(&value);
730 gtk_list_store_set(store, &it, 1, A_UNSET, -1);
731 }
732 }
733
736
738 TRUE);
739
744
745 args->target_tech_id = 0;
746
748}
749
750/**********************************************************************/
753static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
754{
755 struct action_data *args = (struct action_data *)data;
756
757 if (response == GTK_RESPONSE_ACCEPT && args->target_building_id > -2) {
760 if (args->target_building_id == B_LAST) {
761 /* This is the untargeted version. */
763 args->actor_unit_id,
764 args->target_city_id,
765 args->target_building_id, "");
766 } else if (args->target_building_id == -1) {
767 /* This is the city production version. */
769 args->actor_unit_id,
770 args->target_city_id,
771 args->target_building_id, "");
772 } else {
773 /* This is the targeted version. */
775 args->actor_unit_id,
776 args->target_city_id,
777 args->target_building_id, "");
778 }
779 }
780 }
781
784 free(args);
785
786 /* The user have answered the follow up question. Move on. */
788}
789
790/**********************************************************************/
794{
795 struct action_data *args = (struct action_data *)data;
796
797 GtkTreeModel *model;
798 GtkTreeIter it;
799
800 if (gtk_tree_selection_get_selected(select, &model, &it)) {
801 gtk_tree_model_get(model, &it, 1, &(args->target_building_id), -1);
802
805 } else {
806 args->target_building_id = -2;
807
810 }
811}
812
813/**********************************************************************/
816static void create_improvements_list(struct player *pplayer,
817 struct city *pcity,
818 struct action_data *args)
819{
820 GtkWidget *sw, *frame, *label, *vgrid, *view;
821 GtkListStore *store;
824 GtkTreeIter it;
825
827
828 spy_sabotage_shell = gtk_dialog_new_with_buttons(_("Sabotage Improvements"),
829 NULL, 0,
830 _("_Cancel"), GTK_RESPONSE_CANCEL,
831 _("_Sabotage"), GTK_RESPONSE_ACCEPT,
832 NULL);
834
837
838 frame = gtk_frame_new(_("Select Improvement to Sabotage"));
840
846
848
852 g_object_unref(store);
854
857 "text", 0, NULL);
859
861 "use-underline", TRUE,
862 "mnemonic-widget", view,
863 "label", _("_Improvements:"),
864 "xalign", 0.0,
865 "yalign", 0.5,
866 NULL);
867 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
868
872
876
877 gtk_grid_attach(GTK_GRID(vgrid), sw, 0, 1, 1, 1);
878
879 /* Now populate the list */
882 args->act_id)])) {
883 gtk_list_store_append(store, &it);
884 gtk_list_store_set(store, &it, 0, _("City Production"), 1, -1, -1);
885 }
886
887 city_built_iterate(pcity, pimprove) {
888 if (pimprove->sabotage > 0) {
889 gtk_list_store_append(store, &it);
890 gtk_list_store_set(store, &it,
892 1, improvement_number(pimprove),
893 -1);
894 }
896
899 struct astring str = ASTRING_INIT;
900
901 gtk_list_store_append(store, &it);
902
903 /* TRANS: %s is a unit name, e.g., Spy */
904 astr_set(&str, _("At %s's Discretion"),
906 gtk_list_store_set(store, &it, 0, astr_str(&str), 1, B_LAST, -1);
907
908 astr_free(&str);
909 }
910
913
915 TRUE);
916
921
922 args->target_building_id = -2;
923
925}
926
927/**********************************************************************/
931{
932 struct action_data *args = (struct action_data *)data;
933
934 args->act_id = args->act_id;
935
937 struct player *pvictim = NULL;
938
939 if (pvcity) {
941 }
942
943/* It is concievable that pvcity will not be found, because something
944 has happened to the city during latency. Therefore we must initialize
945 pvictim to NULL and account for !pvictim in create_advances_list. -- Syela */
946
947 /* FIXME: Don't discard the second tech choice dialog. */
948 if (!spy_tech_shell) {
951 } else {
952 free(args);
953 }
954
955 /* Wait for the player's reply before moving on to the next unit that
956 * needs to know what action to take. */
958
960}
961
962/**********************************************************************/
971
972/**********************************************************************/
981
982/**********************************************************************/
987 const struct action *paction)
988{
989 /* FIXME: Don't discard the second target choice dialog. */
990 if (!spy_sabotage_shell) {
992 act_data(paction->id,
993 actor->id, pcity->id, 0, 0,
994 0, 0, 0));
996 }
997}
998
999/**********************************************************************/
1002static void incite_response(GtkWidget *w, gint response, gpointer data)
1003{
1004 struct action_data *args = (struct action_data *)data;
1005
1006 if (response == GTK_RESPONSE_YES) {
1008 args->target_city_id, 0, "");
1009 }
1010
1012 free(args);
1013
1014 /* The user have answered the follow up question. Move on. */
1016}
1017
1018/**********************************************************************/
1021void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost,
1022 const struct action *paction)
1023{
1025 char buf[1024];
1026
1027 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
1028 "Treasury contains %d gold.",
1029 client_player()->economic.gold),
1030 client_player()->economic.gold);
1031
1035 _("You can't incite a revolt in %s."),
1037 gtk_window_set_title(GTK_WINDOW(shell), _("City can't be incited!"));
1039 } else if (cost <= client_player()->economic.gold) {
1042 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1043 PL_("Incite a revolt for %d gold?\n%s",
1044 "Incite a revolt for %d gold?\n%s", cost), cost, buf);
1045 gtk_window_set_title(GTK_WINDOW(shell), _("Incite a Revolt!"));
1047 } else {
1049 0,
1051 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1052 PL_("Inciting a revolt costs %d gold.\n%s",
1053 "Inciting a revolt costs %d gold.\n%s", cost), cost, buf);
1054 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
1056 }
1058
1060 act_data(paction->id, actor->id,
1061 pcity->id, 0, 0,
1062 0, 0, 0));
1063}
1064
1065/**********************************************************************/
1069{
1070 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1071
1072 if (arg == GTK_RESPONSE_YES) {
1074
1075 if (actor != NULL) {
1077 "target"));
1079 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1080
1081 if (tgt_unit == NULL) {
1082 /* Make the action dialog pop up again. */
1084 actor->id,
1085 /* Let the server choose the target
1086 * unit. */
1088 tgt_tile->index,
1091 } else {
1093 actor->id,
1094 tgt_id,
1095 tgt_tile->index,
1098 }
1099 }
1100 } else {
1101 /* Dialog canceled. This ends the action selection process. */
1103 }
1104
1106}
1107
1108/**********************************************************************/
1112{
1113 struct action_data *args = act_sel_dialog_data;
1114
1115 struct unit *punit;
1116 struct unit *tunit;
1117 struct tile *ptile;
1118
1120 && (ptile = index_to_tile(&(wld.map), args->target_tile_id))
1121 && (tunit = game_unit_by_number(args->target_unit_id))) {
1122 select_tgt_unit(punit, ptile, ptile->units, tunit,
1123 _("Target unit selection"),
1124 _("Looking for target unit:"),
1125 _("Units at tile:"),
1126 _("Select"),
1128 }
1129
1133 free(args);
1134}
1135
1136/**********************************************************************/
1140{
1141 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1142
1143 if (arg == GTK_RESPONSE_YES) {
1145
1146 if (actor != NULL) {
1148 "target"));
1150 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1151
1152 if (tgt_extra == NULL) {
1153 /* Make the action dialog pop up again. */
1155 actor->id,
1157 tgt_tile->index,
1158 /* Let the server choose the target
1159 * extra. */
1162 } else {
1164 actor->id,
1166 tgt_tile->index,
1167 tgt_id,
1169 }
1170 }
1171 } else {
1172 /* Dialog canceled. This ends the action selection process. */
1174 }
1175
1177}
1178
1179/**********************************************************************/
1183{
1184 struct action_data *args = act_sel_dialog_data;
1185
1186 struct unit *act_unit;
1187 struct extra_type *tgt_extra;
1188 struct tile *tgt_tile;
1189
1191 && (tgt_tile = index_to_tile(&(wld.map), args->target_tile_id))
1194
1195 /* Start with the extras at the tile */
1197
1199 if (BV_ISSET(potential_targets, extra_number(pextra))) {
1200 /* This extra is at the tile. Can anything be done to it? */
1202 pextra)) {
1204 }
1205 } else {
1206 /* This extra isn't at the tile yet. Can it be created? */
1208 pextra)) {
1210 }
1211 }
1213
1215 /* TRANS: GTK action selection dialog extra target
1216 * selection dialog title. */
1217 _("Target extra selection"),
1218 /* TRANS: GTK action selection dialog extra target
1219 * selection dialog actor unit label. */
1220 _("Looking for target extra:"),
1221 /* TRANS: GTK action selection dialog extra target
1222 * selection dialog extra list label. */
1223 _("Extra targets:"),
1224 _("Select"),
1226 }
1227
1231 free(args);
1232}
1233
1234/**********************************************************************/
1238{
1239 struct action_data *args = act_sel_dialog_data;
1240
1241 struct unit *punit;
1242
1243 if ((punit = game_unit_by_number(args->actor_unit_id))) {
1245 }
1246}
1247
1248/**********************************************************************/
1252{
1253 struct action_data *args = act_sel_dialog_data;
1254
1255 key_unit_wait();
1256
1257 /* The dialog was destroyed when key_unit_wait() resulted in
1258 * action_selection_close() being called. */
1259
1260 free(args);
1261}
1262
1263/**********************************************************************/
1271
1272/**********************************************************************/
1280
1281/**********************************************************************/
1289
1290/* Mapping from an action to the function to call when its button is
1291 * pushed. */
1293 /* Unit acting against a city target. */
1304
1305 /* Unit acting against a unit target. */
1307
1308 /* Unit acting against all units at a tile. */
1310
1311 /* Unit acting against a tile. */
1313
1314 /* Unit acting with no target except itself. */
1315 /* No special callback functions needed for any self targeted actions. */
1316};
1317
1318/**********************************************************************/
1323 const struct act_prob *act_probs,
1324 const char *custom,
1326{
1327 const gchar *label;
1328 const gchar *tooltip;
1329 GCallback cb;
1330
1331 if (af_map[act_id] == NULL) {
1332 /* No special call back function needed for this action. */
1334 } else {
1335 /* Special action specific callback function specified. */
1336 cb = af_map[act_id];
1337 }
1338
1339 /* Don't show disabled actions. */
1341 return;
1342 }
1343
1344 label = action_prepare_ui_name(act_id, "_",
1346 custom);
1347
1349 act_probs[act_id]);
1350
1353 FALSE, tooltip);
1354}
1355
1356/**********************************************************************/
1361 const struct act_prob *act_probs,
1362 const char *custom,
1364{
1365 const gchar *label;
1366 const gchar *tooltip;
1367
1368 /* An action that just became impossible has its button disabled.
1369 * An action that became possible again must be re-enabled. */
1373
1374 /* The probability may have changed. */
1375 label = action_prepare_ui_name(act_id, "_",
1377
1379 act_probs[act_id]);
1380
1383 label);
1386 tooltip);
1387}
1388
1389/**********************************************************************/
1394 struct city *target_city,
1395 struct unit *target_unit,
1396 struct tile *target_tile,
1397 struct extra_type *target_extra,
1398 const struct act_prob *act_probs)
1399{
1400 GtkWidget *shl;
1401 struct astring title = ASTRING_INIT, text = ASTRING_INIT;
1402 struct city *actor_homecity;
1403
1404 int button_id;
1405
1407 act_data(ACTION_ANY, /* Not decided yet */
1408 actor_unit->id,
1412 /* No target_building or target_tech supplied. (Dec 2019) */
1413 B_LAST, A_UNSET,
1415
1416 /* Could be caused by the server failing to reply to a request for more
1417 * information or a bug in the client code. */
1419 "Diplomat queue problem. Is another diplomat window open?");
1420
1421 /* No extra input is required as no action has been chosen yet. */
1423
1424 /* No buttons are added yet. */
1425 for (button_id = 0; button_id < BUTTON_COUNT; button_id++) {
1427 }
1428
1430
1434 target_city->id :
1437 target_unit->id :
1450 EXTRA_NONE;
1451
1452 astr_set(&title,
1453 /* TRANS: %s is a unit name, e.g., Spy */
1454 _("Choose Your %s's Strategy"),
1456
1457 if (target_city && actor_homecity) {
1458 astr_set(&text,
1459 _("Your %s from %s reaches the city of %s.\nWhat now?"),
1463 } else if (target_city) {
1464 astr_set(&text,
1465 _("Your %s has arrived at %s.\nWhat is your command?"),
1468 } else if (target_unit) {
1469 astr_set(&text,
1470 /* TRANS: Your Spy is ready to act against Roman Freight. */
1471 _("Your %s is ready to act against %s %s."),
1475 } else {
1477 "No target specified.");
1478 astr_set(&text,
1479 /* TRANS: %s is a unit name, e.g., Diplomat, Spy */
1480 _("Your %s is waiting for your command."),
1482 }
1483
1485 astr_str(&text));
1486
1487 /* Unit acting against a city */
1488
1489 action_iterate(act) {
1494 act_probs[act],
1495 actor_unit,
1496 target_city),
1497 act);
1498 }
1500
1501 /* Unit acting against another unit */
1502
1503 action_iterate(act) {
1508 act_probs[act],
1509 actor_unit,
1510 target_city),
1511 act);
1512 }
1514
1515 /* Unit acting against all units at a tile */
1516
1517 action_iterate(act) {
1522 act_probs[act],
1523 actor_unit,
1524 target_city),
1525 act);
1526 }
1528
1529 /* Unit acting against a tile */
1530
1531 action_iterate(act) {
1536 act_probs[act],
1537 actor_unit,
1538 target_city),
1539 act);
1540 }
1542
1543 /* Unit acting against a tile's extras */
1544
1545 action_iterate(act) {
1550 act_probs[act],
1551 actor_unit,
1552 target_city),
1553 act);
1554 }
1556
1557 /* Unit acting against itself. */
1558
1559 action_iterate(act) {
1564 act_probs[act],
1565 actor_unit,
1566 target_city),
1567 act);
1568 }
1570
1571 if (target_unit != NULL
1572 && unit_list_size(target_tile->units) > 1) {
1575 choice_dialog_add(shl, _("Change unit target"),
1578 }
1579
1580 if (target_extra != NULL) {
1583 choice_dialog_add(shl, _("Change extra target"),
1586 }
1587
1590 choice_dialog_add(shl, _("Show Location"),
1593 TRUE, NULL);
1594
1597 choice_dialog_add(shl, _("_Wait"),
1600 TRUE, NULL);
1601
1604 choice_dialog_add(shl, _("_Cancel"),
1607 FALSE, NULL);
1608
1610
1612
1614 g_signal_connect(shl, "destroy",
1616 g_signal_connect(shl, "close-request",
1619
1620 /* Give follow up questions access to action probabilities. */
1622 action_iterate(act) {
1625
1626 astr_free(&title);
1627 astr_free(&text);
1628}
1629
1630/**********************************************************************/
1636{
1637 if (act_sel_dialog == NULL) {
1638 return IDENTITY_NUMBER_ZERO;
1639 }
1640 return actor_unit_id;
1641}
1642
1643/**********************************************************************/
1650{
1651 if (act_sel_dialog == NULL) {
1652 return IDENTITY_NUMBER_ZERO;
1653 }
1654 return target_ids[ATK_CITY];
1655}
1656
1657/**********************************************************************/
1664{
1665 if (act_sel_dialog == NULL) {
1666 return IDENTITY_NUMBER_ZERO;
1667 }
1668
1669 return target_ids[ATK_UNIT];
1670}
1671
1672/**********************************************************************/
1679{
1680 if (act_sel_dialog == NULL) {
1681 return TILE_INDEX_NONE;
1682 }
1683
1684 return target_ids[ATK_TILE];
1685}
1686
1687/**********************************************************************/
1694{
1695 if (act_sel_dialog == NULL) {
1696 return EXTRA_NONE;
1697 }
1698
1699 return target_extra_id;
1700}
1701
1702/**********************************************************************/
1706 struct city *target_city,
1707 struct unit *target_unit,
1708 struct tile *target_tile,
1709 struct extra_type *target_extra,
1710 const struct act_prob *act_probs)
1711{
1712 if (act_sel_dialog == NULL) {
1714 "The action selection dialog should have been open");
1715 return;
1716 }
1717
1720 "The action selection dialog is for another actor unit.");
1721 return;
1722 }
1723
1724 /* A new target may have appeared. */
1725 if (target_city) {
1727 }
1728 if (target_unit) {
1730 }
1731 if (target_tile) {
1733 }
1734 /* No target_building or target_tech supplied. (Dec 2019) */
1735 if (target_extra) {
1737 }
1738
1739 action_iterate(act) {
1740 const char *custom;
1741
1742 if (action_id_get_actor_kind(act) != AAK_UNIT) {
1743 /* Not relevant. */
1744 continue;
1745 }
1746
1748 act_probs[act],
1749 actor_unit,
1750 target_city);
1751
1752 if (BUTTON_NOT_THERE == action_button_map[act]) {
1753 /* Add the button (unless its probability is 0). */
1755 } else {
1756 /* Update the existing button. */
1758 }
1760
1761 /* DO NOT change the action_button_map[] for any button to reflect its
1762 * new position. A button keeps its choice dialog internal name when its
1763 * position changes. A button's id number is therefore based on when
1764 * it was added, not on its current position. */
1765
1767 /* Move the wait button below the recently added button. */
1770 }
1771
1773 /* Move the cancel button below the recently added button. */
1776 }
1777
1779}
1780
1781/**********************************************************************/
1785{
1786 if (act_sel_dialog != NULL) {
1789 }
1790}
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)
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: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