Freeciv-3.4
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 "specialist.h"
31#include "unit.h"
32#include "unitlist.h"
33
34/* client */
35#include "dialogs_g.h"
36#include "chatline.h"
37#include "choice_dialog.h"
38#include "client_main.h"
39#include "climisc.h"
40#include "connectdlg_common.h"
41#include "control.h"
42#include "gui_main.h"
43#include "gui_stuff.h"
44#include "mapview.h"
45#include "packhand.h"
46#include "text.h"
47
48/* client/gui-gtk-4.0 */
49#include "citydlg.h"
50#include "dialogs.h"
51#include "unitselextradlg.h"
52#include "unitselunitdlg.h"
53#include "wldlg.h"
54
55/* Locations for non action enabler controlled buttons. */
56#define BUTTON_NEW_UNIT_TGT (ACTION_COUNT + 1)
57#define BUTTON_NEW_EXTRA_TGT (BUTTON_NEW_UNIT_TGT + 1)
58#define BUTTON_LOCATION (BUTTON_NEW_EXTRA_TGT + 1)
59#define BUTTON_WAIT (BUTTON_LOCATION + 1)
60#define BUTTON_CANCEL (BUTTON_WAIT + 1)
61#define BUTTON_COUNT (BUTTON_CANCEL + 1)
62
63#define BUTTON_NOT_THERE -1
64
65
68
69static int actor_unit_id;
71static int target_extra_id;
73static bool did_not_decide = FALSE;
75
77
79
80/* A structure to hold parameters for actions inside the GUI instead of
81 * storing the needed data in a global variable. */
82struct action_data {
84 int actor_unit_id;
92};
93
94/* TODO: Maybe this should be in the dialog itself? */
96
97/**********************************************************************/
102 int actor_id,
103 int target_city_id,
104 int target_unit_id,
105 int target_tile_id,
107 int target_tech_id,
109 int tgt_extra_id)
110{
111 struct action_data *data = fc_malloc(sizeof(*data));
112
113 data->act_id = act_id;
114 data->actor_unit_id = actor_id;
122
123 return data;
124}
125
126/**********************************************************************/
131{
133 /* The client isn't waiting for information for any unanswered follow
134 * up questions. */
135
136 struct unit *actor_unit;
137
139 /* The action selection dialog wasn't closed because the actor unit
140 * was lost. */
141
142 /* The probabilities didn't just disappear, right? */
145
147 }
148
150 /* The action selection dialog was closed but only so it can be
151 * redrawn with fresh data. */
152
154 } else {
155 /* The action selection process is over, at least for now. */
157 }
158
159 if (did_not_decide) {
160 /* The action selection dialog was closed but the player didn't
161 * decide what the unit should do. */
162
163 /* Reset so the next action selection dialog does the right thing. */
165 } else {
166 /* An action, or no action at all, was selected. */
169 }
170 }
171}
172
173/**********************************************************************/
178{
179 /* Stop waiting. Move on to the next queued unit. */
182}
183
184/**********************************************************************/
191{
192 /* Stop assuming the answer to a follow up question will arrive. */
194}
195
196/**********************************************************************/
201{
202 /* Don't add an action mapping here unless the non targeted version is
203 * selectable in the targeted version's target selection dialog. */
204 switch ((enum gen_action)tgt_action_id) {
213 default:
214 /* No non targeted version found. */
215 return ACTION_NONE;
216 }
217}
218
219/**********************************************************************/
224{
225 /* Don't add an action mapping here unless the non targeted version is
226 * selectable in the targeted version's target selection dialog. */
227 switch ((enum gen_action)tgt_action_id) {
234 default:
235 /* No non targeted version found. */
236 return ACTION_NONE;
237 }
238}
239
240/**********************************************************************/
245{
246 int actor_id, target_id, sub_target;
247 struct action *paction;
248
249 struct action_data *args = act_sel_dialog_data;
250
251 bool failed = FALSE;
252
253 /* Data */
254 args->act_id = GPOINTER_TO_INT(data);
256
257 /* Actor */
259 actor_id = args->actor_unit_id;
260 if (NULL == game_unit_by_number(actor_id)) {
261 /* Probably dead. */
262 failed = TRUE;
263 }
264
265 /* Target */
266 target_id = IDENTITY_NUMBER_ZERO;
268 case ATK_CITY:
269 target_id = args->target_city_id;
270 if (NULL == game_city_by_number(target_id)) {
271 /* Probably destroyed. */
272 failed = TRUE;
273 }
274 break;
275 case ATK_UNIT:
276 target_id = args->target_unit_id;
277 if (NULL == game_unit_by_number(target_id)) {
278 /* Probably dead. */
279 failed = TRUE;
280 }
281 break;
282 case ATK_STACK:
283 case ATK_TILE:
284 case ATK_EXTRAS:
285 target_id = args->target_tile_id;
286 if (NULL == index_to_tile(&(wld.map), target_id)) {
287 /* TODO: Should this be possible at all? If not: add assertion. */
288 failed = TRUE;
289 }
290 break;
291 case ATK_SELF:
292 target_id = IDENTITY_NUMBER_ZERO;
293 break;
294 case ATK_COUNT:
296 failed = TRUE;
297 }
298
299 /* Sub target. */
300 sub_target = NO_TARGET;
301 if (paction->target_complexity != ACT_TGT_COMPL_SIMPLE) {
303 case ASTK_BUILDING:
304 sub_target = args->target_building_id;
305 if (NULL == improvement_by_number(sub_target)) {
306 /* Did the ruleset change? */
307 failed = TRUE;
308 }
309 break;
310 case ASTK_TECH:
311 sub_target = args->target_tech_id;
312 if (NULL == valid_advance_by_number(sub_target)) {
313 /* Did the ruleset change? */
314 failed = TRUE;
315 }
316 break;
317 case ASTK_EXTRA:
319 /* TODO: Validate if the extra is there? */
320 sub_target = args->target_extra_id;
321 if (NULL == extra_by_number(sub_target)) {
322 /* Did the ruleset change? */
323 failed = TRUE;
324 }
325 break;
326 case ASTK_SPECIALIST:
327 sub_target = args->target_specialist_id;
328 if (nullptr == specialist_by_number(sub_target)) {
329 /* Did the ruleset change? */
330 failed = TRUE;
331 }
332 break;
333 case ASTK_NONE:
334 case ASTK_COUNT:
335 /* Shouldn't happen. */
337 failed = TRUE;
338 break;
339 }
340 }
341
342 /* Send request. */
343 if (!failed) {
344 request_do_action(paction->id, actor_id, target_id, sub_target, "");
345 }
346
347 /* Clean up. */
349 /* No follow up questions. */
351 FC_FREE(args);
352}
353
354/**********************************************************************/
359{
360 int actor_id, target_id;
361 struct action *paction;
362
363 struct action_data *args = act_sel_dialog_data;
364
365 bool failed = FALSE;
366
367 /* Data */
368 args->act_id = GPOINTER_TO_INT(data);
370
371 /* Actor */
373 actor_id = args->actor_unit_id;
374 if (NULL == game_unit_by_number(actor_id)) {
375 /* Probably dead. */
376 failed = TRUE;
377 }
378
379 /* Target */
380 target_id = IDENTITY_NUMBER_ZERO;
382 case ATK_CITY:
383 target_id = args->target_city_id;
384 if (NULL == game_city_by_number(target_id)) {
385 /* Probably destroyed. */
386 failed = TRUE;
387 }
388 break;
389 case ATK_UNIT:
390 target_id = args->target_unit_id;
391 if (NULL == game_unit_by_number(target_id)) {
392 /* Probably dead. */
393 failed = TRUE;
394 }
395 break;
396 case ATK_STACK:
397 case ATK_TILE:
398 case ATK_EXTRAS:
399 target_id = args->target_tile_id;
400 if (NULL == index_to_tile(&(wld.map), target_id)) {
401 /* TODO: Should this be possible at all? If not: add assertion. */
402 failed = TRUE;
403 }
404 break;
405 case ATK_SELF:
406 target_id = IDENTITY_NUMBER_ZERO;
407 break;
408 case ATK_COUNT:
410 failed = TRUE;
411 }
412
413 /* Send request. */
414 if (!failed) {
415 request_action_details(paction->id, actor_id, target_id);
416 }
417
418 /* Wait for the server's reply before moving on to the next unit that
419 * needs to know what action to take. */
421
422 /* Clean up. */
424 /* No client side follow up questions. */
426 FC_FREE(args);
427}
428
429/**********************************************************************/
442
443/**********************************************************************/
447{
448 struct unit *punit;
449 struct action_data *args = act_sel_dialog_data;
450
453 struct unit_list *as_list;
454
459 }
460
462 free(args);
463}
464
465/**********************************************************************/
468static void bribe_unit_response(GtkWidget *w, gint response, gpointer data)
469{
470 struct action_data *args = (struct action_data *)data;
471
472 if (response == GTK_RESPONSE_YES) {
474 args->target_unit_id, 0, "");
475 }
476
478 free(args);
479
480 /* The user have answered the follow up question. Move on. */
482}
483
484/**********************************************************************/
487static void bribe_stack_response(GtkWidget *w, gint response, gpointer data)
488{
489 struct action_data *args = (struct action_data *)data;
490
491 if (response == GTK_RESPONSE_YES) {
493 args->target_tile_id, 0, "");
494 }
495
497 free(args);
498
499 /* The user have answered the follow up question. Move on. */
501}
502
503/**********************************************************************/
506void popup_bribe_unit_dialog(struct unit *actor, struct unit *punit, int cost,
507 const struct action *paction)
508{
510 char buf[1024];
511
512 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
513 "Treasury contains %d gold.",
514 client_player()->economic.gold),
515 client_player()->economic.gold);
516
517 if (cost <= client_player()->economic.gold) {
520 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
521 PL_("Bribe unit for %d gold?\n%s",
522 "Bribe unit for %d gold?\n%s", cost), cost, buf);
523 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
525 } else {
528 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
529 PL_("Bribing the unit costs %d gold.\n%s",
530 "Bribing the unit costs %d gold.\n%s", cost), cost, buf);
531 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
533 }
535
537 act_data(paction->id, actor->id,
538 0, punit->id, 0,
539 0, 0, 0, 0));
540}
541
542/**********************************************************************/
545void popup_bribe_stack_dialog(struct unit *actor, struct tile *ptile, int cost,
546 const struct action *paction)
547{
549 char buf[1024];
550
551 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
552 "Treasury contains %d gold.",
553 client_player()->economic.gold),
554 client_player()->economic.gold);
555
556 if (cost <= client_player()->economic.gold) {
559 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
560 PL_("Bribe unit stack for %d gold?\n%s",
561 "Bribe unit stack for %d gold?\n%s", cost), cost, buf);
562 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
564 } else {
567 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
568 PL_("Bribing units costs %d gold.\n%s",
569 "Bribing units costs %d gold.\n%s", cost), cost, buf);
570 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
572 }
574
576 act_data(paction->id, actor->id,
577 0, 0, ptile->index,
578 0, 0, 0, 0));
579}
580
581/**********************************************************************/
584static void spy_advances_response(GtkWidget *w, gint response,
585 gpointer data)
586{
587 struct action_data *args = (struct action_data *)data;
588
589 if (response == GTK_RESPONSE_ACCEPT && args->target_tech_id > 0) {
592 if (args->target_tech_id == A_UNSET) {
593 /* This is the untargeted version. */
595 args->actor_unit_id, args->target_city_id,
596 args->target_tech_id, "");
597 } else {
598 /* This is the targeted version. */
600 args->actor_unit_id, args->target_city_id,
601 args->target_tech_id, "");
602 }
603 }
604 }
605
608 free(data);
609
610 /* The user have answered the follow up question. Move on. */
612}
613
614/**********************************************************************/
618 gpointer data)
619{
620 struct action_data *args = (struct action_data *)data;
621
622 GtkTreeModel *model;
623 GtkTreeIter it;
624
625 if (gtk_tree_selection_get_selected(select, &model, &it)) {
626 gtk_tree_model_get(model, &it, 1, &(args->target_tech_id), -1);
627
630 } else {
631 args->target_tech_id = 0;
632
635 }
636}
637
638/**********************************************************************/
641static void create_advances_list(struct player *pplayer,
642 struct player *pvictim,
643 struct action_data *args)
644{
645 GtkWidget *sw, *frame, *label, *vgrid, *view;
646 GtkListStore *store;
649
651
652 spy_tech_shell = gtk_dialog_new_with_buttons(_("Steal Technology"),
653 NULL, 0,
654 _("_Cancel"), GTK_RESPONSE_CANCEL,
655 _("_Steal"), GTK_RESPONSE_ACCEPT,
656 NULL);
658
661
662 frame = gtk_frame_new(_("Select Advance to Steal"));
664
670
672
676 g_object_unref(store);
678
681 "text", 0, NULL);
683
685 "use-underline", TRUE,
686 "mnemonic-widget", view,
687 "label", _("_Advances:"),
688 "xalign", 0.0,
689 "yalign", 0.5,
690 NULL);
691 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
692
696
699 gtk_widget_set_size_request(sw, -1, 200);
700
701 gtk_grid_attach(GTK_GRID(vgrid), sw, 0, 1, 1, 1);
702
703 /* Now populate the list */
704 if (pvictim) { /* You don't want to know what lag can do -- Syela */
705 const struct research *presearch = research_get(pplayer);
706 const struct research *vresearch = research_get(pvictim);
707 GtkTreeIter it;
708 GValue value = { 0, };
709
715 gtk_list_store_append(store, &it);
716
719 (presearch, i));
720 gtk_list_store_set_value(store, &it, 0, &value);
721 g_value_unset(&value);
722 gtk_list_store_set(store, &it, 1, i, -1);
723 }
725
728 gtk_list_store_append(store, &it);
729
731 {
732 struct astring str = ASTRING_INIT;
733 /* TRANS: %s is a unit name, e.g., Spy */
734 astr_set(&str, _("At %s's Discretion"),
737 astr_free(&str);
738 }
739 gtk_list_store_set_value(store, &it, 0, &value);
740 g_value_unset(&value);
741 gtk_list_store_set(store, &it, 1, A_UNSET, -1);
742 }
743 }
744
747
749 TRUE);
750
755
756 args->target_tech_id = 0;
757
759}
760
761/**********************************************************************/
764static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
765{
766 struct action_data *args = (struct action_data *)data;
767
768 if (response == GTK_RESPONSE_ACCEPT && args->target_building_id > -2) {
771 if (args->target_building_id == B_LAST) {
772 /* This is the untargeted version. */
774 args->actor_unit_id,
775 args->target_city_id,
776 args->target_building_id, "");
777 } else if (args->target_building_id == -1) {
778 /* This is the city production version. */
780 args->actor_unit_id,
781 args->target_city_id,
782 args->target_building_id, "");
783 } else {
784 /* This is the targeted version. */
786 args->actor_unit_id,
787 args->target_city_id,
788 args->target_building_id, "");
789 }
790 }
791 }
792
795 free(args);
796
797 /* The user have answered the follow up question. Move on. */
799}
800
801/**********************************************************************/
805{
806 struct action_data *args = (struct action_data *)data;
807
808 GtkTreeModel *model;
809 GtkTreeIter it;
810
811 if (gtk_tree_selection_get_selected(select, &model, &it)) {
812 gtk_tree_model_get(model, &it, 1, &(args->target_building_id), -1);
813
816 } else {
817 args->target_building_id = -2;
818
821 }
822}
823
824/**********************************************************************/
827static void create_improvements_list(struct player *pplayer,
828 struct city *pcity,
829 struct action_data *args)
830{
831 GtkWidget *sw, *frame, *label, *vgrid, *view;
832 GtkListStore *store;
835 GtkTreeIter it;
836
838
839 spy_sabotage_shell = gtk_dialog_new_with_buttons(_("Sabotage Improvements"),
840 NULL, 0,
841 _("_Cancel"), GTK_RESPONSE_CANCEL,
842 _("_Sabotage"), GTK_RESPONSE_ACCEPT,
843 NULL);
845
848
849 frame = gtk_frame_new(_("Select Improvement to Sabotage"));
851
857
859
863 g_object_unref(store);
865
868 "text", 0, NULL);
870
872 "use-underline", TRUE,
873 "mnemonic-widget", view,
874 "label", _("_Improvements:"),
875 "xalign", 0.0,
876 "yalign", 0.5,
877 NULL);
878 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
879
883
887
888 gtk_grid_attach(GTK_GRID(vgrid), sw, 0, 1, 1, 1);
889
890 /* Now populate the list */
893 args->act_id)])) {
894 gtk_list_store_append(store, &it);
895 gtk_list_store_set(store, &it, 0, _("City Production"), 1, -1, -1);
896 }
897
898 city_built_iterate(pcity, pimprove) {
899 if (pimprove->sabotage > 0) {
900 gtk_list_store_append(store, &it);
901 gtk_list_store_set(store, &it,
903 1, improvement_number(pimprove),
904 -1);
905 }
907
910 struct astring str = ASTRING_INIT;
911
912 gtk_list_store_append(store, &it);
913
914 /* TRANS: %s is a unit name, e.g., Spy */
915 astr_set(&str, _("At %s's Discretion"),
917 gtk_list_store_set(store, &it, 0, astr_str(&str), 1, B_LAST, -1);
918
919 astr_free(&str);
920 }
921
924
926 TRUE);
927
932
933 args->target_building_id = -2;
934
936}
937
938/**********************************************************************/
942{
943 struct action_data *args = (struct action_data *)data;
944
945 args->act_id = args->act_id;
946
948 struct player *pvictim = NULL;
949
950 if (pvcity) {
952 }
953
954/* It is concievable that pvcity will not be found, because something
955 has happened to the city during latency. Therefore we must initialize
956 pvictim to NULL and account for !pvictim in create_advances_list. -- Syela */
957
958 /* FIXME: Don't discard the second tech choice dialog. */
959 if (!spy_tech_shell) {
962 } else {
963 free(args);
964 }
965
966 /* Wait for the player's reply before moving on to the next unit that
967 * needs to know what action to take. */
969
971}
972
973/**********************************************************************/
982
983/**********************************************************************/
992
993/**********************************************************************/
998 const struct action *paction)
999{
1000 /* FIXME: Don't discard the second target choice dialog. */
1001 if (!spy_sabotage_shell) {
1003 act_data(paction->id,
1004 actor->id, pcity->id, 0, 0,
1005 0, 0, 0, 0));
1007 }
1008}
1009
1010/**********************************************************************/
1013static void incite_response(GtkWidget *w, gint response, gpointer data)
1014{
1015 struct action_data *args = (struct action_data *)data;
1016
1017 if (response == GTK_RESPONSE_YES) {
1019 args->target_city_id, 0, "");
1020 }
1021
1023 free(args);
1024
1025 /* The user have answered the follow up question. Move on. */
1027}
1028
1029/**********************************************************************/
1032void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost,
1033 const struct action *paction)
1034{
1036 char buf[1024];
1037
1038 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
1039 "Treasury contains %d gold.",
1040 client_player()->economic.gold),
1041 client_player()->economic.gold);
1042
1046 _("You can't incite a revolt in %s."),
1048 gtk_window_set_title(GTK_WINDOW(shell), _("City can't be incited!"));
1050 } else if (cost <= client_player()->economic.gold) {
1053 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1054 PL_("Incite a revolt for %d gold?\n%s",
1055 "Incite a revolt for %d gold?\n%s", cost), cost, buf);
1056 gtk_window_set_title(GTK_WINDOW(shell), _("Incite a Revolt!"));
1058 } else {
1060 0,
1062 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1063 PL_("Inciting a revolt costs %d gold.\n%s",
1064 "Inciting a revolt costs %d gold.\n%s", cost), cost, buf);
1065 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
1067 }
1069
1071 act_data(paction->id, actor->id,
1072 pcity->id, 0, 0,
1073 0, 0, 0, 0));
1074}
1075
1076/**********************************************************************/
1080{
1081 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1082
1083 if (arg == GTK_RESPONSE_YES) {
1085
1086 if (actor != NULL) {
1088 "target"));
1090 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1091
1092 if (tgt_unit == NULL) {
1093 /* Make the action dialog pop up again. */
1095 actor->id,
1096 /* Let the server choose the target
1097 * unit. */
1099 tgt_tile->index,
1102 } else {
1104 actor->id,
1105 tgt_id,
1106 tgt_tile->index,
1109 }
1110 }
1111 } else {
1112 /* Dialog canceled. This ends the action selection process. */
1114 }
1115
1117}
1118
1119/**********************************************************************/
1123{
1124 struct action_data *args = act_sel_dialog_data;
1125
1126 struct unit *punit;
1127 struct unit *tunit;
1128 struct tile *ptile;
1129
1131 && (ptile = index_to_tile(&(wld.map), args->target_tile_id))
1132 && (tunit = game_unit_by_number(args->target_unit_id))) {
1133 select_tgt_unit(punit, ptile, ptile->units, tunit,
1134 _("Target unit selection"),
1135 _("Looking for target unit:"),
1136 _("Units at tile:"),
1137 _("Select"),
1139 }
1140
1144 free(args);
1145}
1146
1147/**********************************************************************/
1151{
1152 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1153
1154 if (arg == GTK_RESPONSE_YES) {
1156
1157 if (actor != NULL) {
1159 "target"));
1161 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1162
1163 if (tgt_extra == NULL) {
1164 /* Make the action dialog pop up again. */
1166 actor->id,
1168 tgt_tile->index,
1169 /* Let the server choose the target
1170 * extra. */
1173 } else {
1175 actor->id,
1177 tgt_tile->index,
1178 tgt_id,
1180 }
1181 }
1182 } else {
1183 /* Dialog canceled. This ends the action selection process. */
1185 }
1186
1188}
1189
1190/**********************************************************************/
1194{
1195 struct action_data *args = act_sel_dialog_data;
1196
1197 struct unit *act_unit;
1198 struct extra_type *tgt_extra;
1199 struct tile *tgt_tile;
1200
1202 && (tgt_tile = index_to_tile(&(wld.map), args->target_tile_id))
1205
1206 /* Start with the extras at the tile */
1208
1210 if (BV_ISSET(potential_targets, extra_number(pextra))) {
1211 /* This extra is at the tile. Can anything be done to it? */
1213 pextra)) {
1215 }
1216 } else {
1217 /* This extra isn't at the tile yet. Can it be created? */
1219 pextra)) {
1221 }
1222 }
1224
1226 /* TRANS: GTK action selection dialog extra target
1227 * selection dialog title. */
1228 _("Target extra selection"),
1229 /* TRANS: GTK action selection dialog extra target
1230 * selection dialog actor unit label. */
1231 _("Looking for target extra:"),
1232 /* TRANS: GTK action selection dialog extra target
1233 * selection dialog extra list label. */
1234 _("Extra targets:"),
1235 _("Select"),
1237 }
1238
1242 free(args);
1243}
1244
1245/**********************************************************************/
1249{
1250 struct action_data *args = act_sel_dialog_data;
1251
1252 struct unit *punit;
1253
1254 if ((punit = game_unit_by_number(args->actor_unit_id))) {
1256 }
1257}
1258
1259/**********************************************************************/
1263{
1264 struct action_data *args = act_sel_dialog_data;
1265
1266 key_unit_wait();
1267
1268 /* The dialog was destroyed when key_unit_wait() resulted in
1269 * action_selection_close() being called. */
1270
1271 free(args);
1272}
1273
1274/**********************************************************************/
1282
1283/**********************************************************************/
1291
1292/**********************************************************************/
1300
1301/* Mapping from an action to the function to call when its button is
1302 * pushed. */
1304 /* Unit acting against a city target. */
1315
1316 /* Unit acting against a unit target. */
1318
1319 /* Unit acting against all units at a tile. */
1321
1322 /* Unit acting against a tile. */
1324
1325 /* Unit acting with no target except itself. */
1326 /* No special callback functions needed for any self targeted actions. */
1327};
1328
1329/**********************************************************************/
1334 const struct act_prob *act_probs,
1335 const char *custom,
1337{
1338 const gchar *label;
1339 const gchar *tooltip;
1340 GCallback cb;
1341
1342 if (af_map[act_id] == NULL) {
1343 /* No special call back function needed for this action. */
1345 } else {
1346 /* Special action specific callback function specified. */
1347 cb = af_map[act_id];
1348 }
1349
1350 /* Don't show disabled actions. */
1352 return;
1353 }
1354
1355 label = action_prepare_ui_name(act_id, "_",
1357 custom);
1358
1360 act_probs[act_id]);
1361
1364 FALSE, tooltip);
1365}
1366
1367/**********************************************************************/
1372 const struct act_prob *act_probs,
1373 const char *custom,
1375{
1376 const gchar *label;
1377 const gchar *tooltip;
1378
1379 /* An action that just became impossible has its button disabled.
1380 * An action that became possible again must be re-enabled. */
1384
1385 /* The probability may have changed. */
1386 label = action_prepare_ui_name(act_id, "_",
1388
1390 act_probs[act_id]);
1391
1394 label);
1397 tooltip);
1398}
1399
1400/**********************************************************************/
1405 struct city *target_city,
1406 struct unit *target_unit,
1407 struct tile *target_tile,
1408 struct extra_type *target_extra,
1409 const struct act_prob *act_probs)
1410{
1411 GtkWidget *shl;
1412 struct astring title = ASTRING_INIT, text = ASTRING_INIT;
1413 struct city *actor_homecity;
1414
1415 int button_id;
1416
1418 act_data(ACTION_ANY, /* Not decided yet */
1419 actor_unit->id,
1423 /* No target_building or target_tech supplied. (Dec 2019) */
1424 B_LAST, A_UNSET, -1,
1426
1427 /* Could be caused by the server failing to reply to a request for more
1428 * information or a bug in the client code. */
1430 "Diplomat queue problem. Is another diplomat window open?");
1431
1432 /* No extra input is required as no action has been chosen yet. */
1434
1435 /* No buttons are added yet. */
1436 for (button_id = 0; button_id < BUTTON_COUNT; button_id++) {
1438 }
1439
1441
1445 target_city->id :
1448 target_unit->id :
1461 EXTRA_NONE;
1462
1463 astr_set(&title,
1464 /* TRANS: %s is a unit name, e.g., Spy */
1465 _("Choose Your %s's Strategy"),
1467
1468 if (target_city && actor_homecity) {
1469 astr_set(&text,
1470 _("Your %s from %s reaches the city of %s.\nWhat now?"),
1474 } else if (target_city) {
1475 astr_set(&text,
1476 _("Your %s has arrived at %s.\nWhat is your command?"),
1479 } else if (target_unit) {
1480 astr_set(&text,
1481 /* TRANS: Your Spy is ready to act against Roman Freight. */
1482 _("Your %s is ready to act against %s %s."),
1486 } else {
1488 "No target specified.");
1489 astr_set(&text,
1490 /* TRANS: %s is a unit name, e.g., Diplomat, Spy */
1491 _("Your %s is waiting for your command."),
1493 }
1494
1496 astr_str(&text));
1497
1498 /* Unit acting against a city */
1499
1500 action_iterate(act) {
1505 act_probs[act],
1506 actor_unit,
1507 target_city),
1508 act);
1509 }
1511
1512 /* Unit acting against another unit */
1513
1514 action_iterate(act) {
1519 act_probs[act],
1520 actor_unit,
1521 target_city),
1522 act);
1523 }
1525
1526 /* Unit acting against all units at a tile */
1527
1528 action_iterate(act) {
1533 act_probs[act],
1534 actor_unit,
1535 target_city),
1536 act);
1537 }
1539
1540 /* Unit acting against a tile */
1541
1542 action_iterate(act) {
1547 act_probs[act],
1548 actor_unit,
1549 target_city),
1550 act);
1551 }
1553
1554 /* Unit acting against a tile's extras */
1555
1556 action_iterate(act) {
1561 act_probs[act],
1562 actor_unit,
1563 target_city),
1564 act);
1565 }
1567
1568 /* Unit acting against itself. */
1569
1570 action_iterate(act) {
1575 act_probs[act],
1576 actor_unit,
1577 target_city),
1578 act);
1579 }
1581
1582 if (target_unit != NULL
1583 && unit_list_size(target_tile->units) > 1) {
1586 choice_dialog_add(shl, _("Change unit target"),
1589 }
1590
1591 if (target_extra != NULL) {
1594 choice_dialog_add(shl, _("Change extra target"),
1597 }
1598
1601 choice_dialog_add(shl, _("Show Location"),
1604 TRUE, NULL);
1605
1608 choice_dialog_add(shl, _("_Wait"),
1611 TRUE, NULL);
1612
1615 choice_dialog_add(shl, _("_Cancel"),
1618 FALSE, NULL);
1619
1621
1623
1625 g_signal_connect(shl, "destroy",
1627 g_signal_connect(shl, "close-request",
1630
1631 /* Give follow up questions access to action probabilities. */
1633 action_iterate(act) {
1636
1637 astr_free(&title);
1638 astr_free(&text);
1639}
1640
1641/**********************************************************************/
1647{
1648 if (act_sel_dialog == NULL) {
1649 return IDENTITY_NUMBER_ZERO;
1650 }
1651 return actor_unit_id;
1652}
1653
1654/**********************************************************************/
1661{
1662 if (act_sel_dialog == NULL) {
1663 return IDENTITY_NUMBER_ZERO;
1664 }
1665 return target_ids[ATK_CITY];
1666}
1667
1668/**********************************************************************/
1675{
1676 if (act_sel_dialog == NULL) {
1677 return IDENTITY_NUMBER_ZERO;
1678 }
1679
1680 return target_ids[ATK_UNIT];
1681}
1682
1683/**********************************************************************/
1690{
1691 if (act_sel_dialog == NULL) {
1692 return TILE_INDEX_NONE;
1693 }
1694
1695 return target_ids[ATK_TILE];
1696}
1697
1698/**********************************************************************/
1705{
1706 if (act_sel_dialog == NULL) {
1707 return EXTRA_NONE;
1708 }
1709
1710 return target_extra_id;
1711}
1712
1713/**********************************************************************/
1717 struct city *target_city,
1718 struct unit *target_unit,
1719 struct tile *target_tile,
1720 struct extra_type *target_extra,
1721 const struct act_prob *act_probs)
1722{
1723 if (act_sel_dialog == NULL) {
1725 "The action selection dialog should have been open");
1726 return;
1727 }
1728
1731 "The action selection dialog is for another actor unit.");
1732 return;
1733 }
1734
1735 /* A new target may have appeared. */
1736 if (target_city) {
1738 }
1739 if (target_unit) {
1741 }
1742 if (target_tile) {
1744 }
1745 /* No target_building or target_tech supplied. (Dec 2019) */
1746 if (target_extra) {
1748 }
1749
1750 action_iterate(act) {
1751 const char *custom;
1752
1753 if (action_id_get_actor_kind(act) != AAK_UNIT) {
1754 /* Not relevant. */
1755 continue;
1756 }
1757
1759 act_probs[act],
1760 actor_unit,
1761 target_city);
1762
1763 if (BUTTON_NOT_THERE == action_button_map[act]) {
1764 /* Add the button (unless its probability is 0). */
1766 } else {
1767 /* Update the existing button. */
1769 }
1771
1772 /* DO NOT change the action_button_map[] for any button to reflect its
1773 * new position. A button keeps its choice dialog internal name when its
1774 * position changes. A button's id number is therefore based on when
1775 * it was added, not on its current position. */
1776
1778 /* Move the wait button below the recently added button. */
1781 }
1782
1784 /* Move the cancel button below the recently added button. */
1787 }
1788
1790}
1791
1792/**********************************************************************/
1796{
1797 if (act_sel_dialog != NULL) {
1800 }
1801}
const char * action_prepare_ui_name(action_id act_id, const char *mnemonic, const struct act_prob prob, const char *custom)
Definition actions.c:1333
enum action_actor_kind action_get_actor_kind(const struct action *paction)
Definition actions.c:1119
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5306
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1140
enum action_target_kind action_get_target_kind(const struct action *paction)
Definition actions.c:1129
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define action_iterate_end
Definition actions.h:218
#define action_id_get_actor_kind(act_id)
Definition actions.h:413
#define action_iterate(_act_)
Definition actions.h:214
#define ACTION_ANY
Definition actions.h:56
#define action_id_get_target_kind(act_id)
Definition actions.h:417
#define ACTION_NONE
Definition actions.h:59
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:94
#define city_owner(_pcity_)
Definition city.h:563
#define city_built_iterate(_pcity, _p)
Definition city.h:835
#define city_built_iterate_end
Definition city.h:841
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:214
int action_id
Definition fc_types.h:249
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:93
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct unit * game_unit_by_number(int id)
Definition game.c:116
struct city * game_city_by_number(int id)
Definition game.c:107
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 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 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 target_specialist_id, int tgt_extra_id)
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
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)
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
const char * research_advance_name_translation(const struct research *presearch, Tech_type_id tech)
Definition research.c:276
struct research * research_get(const struct player *pplayer)
Definition research.c:130
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
bool research_invention_gettable(const struct research *presearch, const Tech_type_id tech, bool allow_holes)
Definition research.c:696
#define ARRAY_SIZE(x)
Definition shared.h:85
struct specialist * specialist_by_number(const Specialist_type_id id)
Definition specialist.c:110
int target_building_id
int target_specialist_id
action_id act_id
Definition city.h:318
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:246
#define A_FIRST
Definition tech.h:44
#define A_UNSET
Definition tech.h:48
#define advance_index_iterate(_start, _index)
Definition tech.h:242
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:1763
const char * act_sel_action_tool_tip(const struct action *paction, const struct act_prob prob)
Definition text.c:1842
#define tile_index(_pt_)
Definition tile.h:89
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:125
#define TILE_INDEX_NONE
Definition tile.h:48
#define unit_tile(_pu)
Definition unit.h:407
#define unit_owner(_pu)
Definition unit.h:406
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
bool utype_can_remove_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:266
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1595
bool utype_can_create_extra(const struct unit_type *putype, const struct extra_type *pextra)
Definition unittype.c:242