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#define FC_TYPE_ACTION_ROW (fc_action_row_get_type())
96
98
106
111
113
114/**********************************************************************/
118{
120
121 free(row->name);
122 row->name = nullptr;
123
125}
126
127/**********************************************************************/
130static void
137
138/**********************************************************************/
141static void
143{
144 self->name = nullptr;
145}
146
147/**********************************************************************/
151{
152 FcActionRow *result;
153
154 result = g_object_new(FC_TYPE_ACTION_ROW, nullptr);
155
156 return result;
157}
158
159/**********************************************************************/
164 int actor_id,
165 int target_city_id,
166 int target_unit_id,
167 int target_tile_id,
169 int target_tech_id,
170 int tgt_extra_id)
171{
172 struct action_data *data = fc_malloc(sizeof(*data));
173
174 data->act_id = act_id;
175 data->actor_unit_id = actor_id;
182
183 return data;
184}
185
186/**********************************************************************/
191{
193 /* The client isn't waiting for information for any unanswered follow
194 * up questions. */
195
196 struct unit *actor_unit;
197
199 /* The action selection dialog wasn't closed because the actor unit
200 * was lost. */
201
202 /* The probabilities didn't just disappear, right? */
205
207 }
208
210 /* The action selection dialog was closed but only so it can be
211 * redrawn with fresh data. */
212
214 } else {
215 /* The action selection process is over, at least for now. */
217 }
218
219 if (did_not_decide) {
220 /* The action selection dialog was closed but the player didn't
221 * decide what the unit should do. */
222
223 /* Reset so the next action selection dialog does the right thing. */
225 } else {
226 /* An action, or no action at all, was selected. */
229 }
230 }
231}
232
233/**********************************************************************/
238{
239 /* Stop waiting. Move on to the next queued unit. */
242}
243
244/**********************************************************************/
251{
252 /* Stop assuming the answer to a follow up question will arrive. */
254}
255
256/**********************************************************************/
261{
262 /* Don't add an action mapping here unless the non targeted version is
263 * selectable in the targeted version's target selection dialog. */
264 switch ((enum gen_action)tgt_action_id) {
273 default:
274 /* No non targeted version found. */
275 return ACTION_NONE;
276 }
277}
278
279/**********************************************************************/
284{
285 /* Don't add an action mapping here unless the non targeted version is
286 * selectable in the targeted version's target selection dialog. */
287 switch ((enum gen_action)tgt_action_id) {
294 default:
295 /* No non targeted version found. */
296 return ACTION_NONE;
297 }
298}
299
300/**********************************************************************/
305{
306 int actor_id, target_id, sub_target;
307 struct action *paction;
308
309 struct action_data *args = act_sel_dialog_data;
310
311 bool failed = FALSE;
312
313 /* Data */
314 args->act_id = GPOINTER_TO_INT(data);
316
317 /* Actor */
319 actor_id = args->actor_unit_id;
320 if (NULL == game_unit_by_number(actor_id)) {
321 /* Probably dead. */
322 failed = TRUE;
323 }
324
325 /* Target */
326 target_id = IDENTITY_NUMBER_ZERO;
328 case ATK_CITY:
329 target_id = args->target_city_id;
330 if (NULL == game_city_by_number(target_id)) {
331 /* Probably destroyed. */
332 failed = TRUE;
333 }
334 break;
335 case ATK_UNIT:
336 target_id = args->target_unit_id;
337 if (NULL == game_unit_by_number(target_id)) {
338 /* Probably dead. */
339 failed = TRUE;
340 }
341 break;
342 case ATK_STACK:
343 case ATK_TILE:
344 case ATK_EXTRAS:
345 target_id = args->target_tile_id;
346 if (NULL == index_to_tile(&(wld.map), target_id)) {
347 /* TODO: Should this be possible at all? If not: add assertion. */
348 failed = TRUE;
349 }
350 break;
351 case ATK_SELF:
352 target_id = IDENTITY_NUMBER_ZERO;
353 break;
354 case ATK_COUNT:
356 failed = TRUE;
357 }
358
359 /* Sub target. */
360 sub_target = NO_TARGET;
361 if (paction->target_complexity != ACT_TGT_COMPL_SIMPLE) {
363 case ASTK_BUILDING:
364 sub_target = args->target_building_id;
365 if (NULL == improvement_by_number(sub_target)) {
366 /* Did the ruleset change? */
367 failed = TRUE;
368 }
369 break;
370 case ASTK_TECH:
371 sub_target = args->target_tech_id;
372 if (NULL == valid_advance_by_number(sub_target)) {
373 /* Did the ruleset change? */
374 failed = TRUE;
375 }
376 break;
377 case ASTK_EXTRA:
379 /* TODO: Validate if the extra is there? */
380 sub_target = args->target_extra_id;
381 if (NULL == extra_by_number(sub_target)) {
382 /* Did the ruleset change? */
383 failed = TRUE;
384 }
385 break;
386 case ASTK_NONE:
387 case ASTK_COUNT:
388 /* Shouldn't happen. */
390 failed = TRUE;
391 break;
392 }
393 }
394
395 /* Send request. */
396 if (!failed) {
397 request_do_action(paction->id, actor_id, target_id, sub_target, "");
398 }
399
400 /* Clean up. */
402 /* No follow up questions. */
404 FC_FREE(args);
405}
406
407/**********************************************************************/
412{
413 int actor_id, target_id;
414 struct action *paction;
415
416 struct action_data *args = act_sel_dialog_data;
417
418 bool failed = FALSE;
419
420 /* Data */
421 args->act_id = GPOINTER_TO_INT(data);
423
424 /* Actor */
426 actor_id = args->actor_unit_id;
427 if (NULL == game_unit_by_number(actor_id)) {
428 /* Probably dead. */
429 failed = TRUE;
430 }
431
432 /* Target */
433 target_id = IDENTITY_NUMBER_ZERO;
435 case ATK_CITY:
436 target_id = args->target_city_id;
437 if (NULL == game_city_by_number(target_id)) {
438 /* Probably destroyed. */
439 failed = TRUE;
440 }
441 break;
442 case ATK_UNIT:
443 target_id = args->target_unit_id;
444 if (NULL == game_unit_by_number(target_id)) {
445 /* Probably dead. */
446 failed = TRUE;
447 }
448 break;
449 case ATK_STACK:
450 case ATK_TILE:
451 case ATK_EXTRAS:
452 target_id = args->target_tile_id;
453 if (NULL == index_to_tile(&(wld.map), target_id)) {
454 /* TODO: Should this be possible at all? If not: add assertion. */
455 failed = TRUE;
456 }
457 break;
458 case ATK_SELF:
459 target_id = IDENTITY_NUMBER_ZERO;
460 break;
461 case ATK_COUNT:
463 failed = TRUE;
464 }
465
466 /* Send request. */
467 if (!failed) {
468 request_action_details(paction->id, actor_id, target_id);
469 }
470
471 /* Wait for the server's reply before moving on to the next unit that
472 * needs to know what action to take. */
474
475 /* Clean up. */
477 /* No client side follow up questions. */
479 FC_FREE(args);
480}
481
482/**********************************************************************/
495
496/**********************************************************************/
500{
501 struct unit *punit;
502 struct action_data *args = act_sel_dialog_data;
503
506 struct unit_list *as_list;
507
512 }
513
515 free(args);
516}
517
518/**********************************************************************/
521static void bribe_unit_response(GtkWidget *w, gint response, gpointer data)
522{
523 struct action_data *args = (struct action_data *)data;
524
525 if (response == GTK_RESPONSE_YES) {
527 args->target_unit_id, 0, "");
528 }
529
531 free(args);
532
533 /* The user have answered the follow up question. Move on. */
535}
536
537/**********************************************************************/
540static void bribe_stack_response(GtkWidget *w, gint response, gpointer data)
541{
542 struct action_data *args = (struct action_data *)data;
543
544 if (response == GTK_RESPONSE_YES) {
546 args->target_tile_id, 0, "");
547 }
548
550 free(args);
551
552 /* The user have answered the follow up question. Move on. */
554}
555
556/**********************************************************************/
559void popup_bribe_unit_dialog(struct unit *actor, struct unit *punit, int cost,
560 const struct action *paction)
561{
563 char buf[1024];
564
565 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
566 "Treasury contains %d gold.",
567 client_player()->economic.gold),
568 client_player()->economic.gold);
569
570 if (cost <= client_player()->economic.gold) {
573 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
574 PL_("Bribe unit for %d gold?\n%s",
575 "Bribe unit for %d gold?\n%s", cost), cost, buf);
576 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Unit"));
578 } else {
581 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
582 PL_("Bribing the unit costs %d gold.\n%s",
583 "Bribing the unit costs %d gold.\n%s", cost), cost, buf);
584 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
586 }
588
590 act_data(paction->id, actor->id,
591 0, punit->id, 0,
592 0, 0, 0));
593}
594
595/**********************************************************************/
598void popup_bribe_stack_dialog(struct unit *actor, struct tile *ptile, int cost,
599 const struct action *paction)
600{
602 char buf[1024];
603
604 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
605 "Treasury contains %d gold.",
606 client_player()->economic.gold),
607 client_player()->economic.gold);
608
609 if (cost <= client_player()->economic.gold) {
612 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
613 PL_("Bribe unit stack for %d gold?\n%s",
614 "Bribe unit stack for %d gold?\n%s", cost), cost, buf);
615 gtk_window_set_title(GTK_WINDOW(shell), _("Bribe Enemy Stack"));
617 } else {
620 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
621 PL_("Bribing units costs %d gold.\n%s",
622 "Bribing units costs %d gold.\n%s", cost), cost, buf);
623 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
625 }
627
629 act_data(paction->id, actor->id,
630 0, 0, ptile->index,
631 0, 0, 0));
632}
633
634/**********************************************************************/
637static void spy_advances_response(GtkWidget *w, gint response,
638 gpointer data)
639{
640 struct action_data *args = (struct action_data *)data;
641
642 if (response == GTK_RESPONSE_ACCEPT && args->target_tech_id > 0) {
645 if (args->target_tech_id == A_UNSET) {
646 /* This is the untargeted version. */
648 args->actor_unit_id, args->target_city_id,
649 args->target_tech_id, "");
650 } else {
651 /* This is the targeted version. */
653 args->actor_unit_id, args->target_city_id,
654 args->target_tech_id, "");
655 }
656 }
657 }
658
661 free(data);
662
663 /* The user have answered the follow up question. Move on. */
665}
666
667/**********************************************************************/
691
692/**********************************************************************/
706
707/**********************************************************************/
716
717/**********************************************************************/
720static void create_advances_list(struct player *pplayer,
721 struct player *pvictim,
722 struct action_data *args)
723{
724 GtkWidget *frame, *label, *vgrid;
725 GListStore *store;
729 GtkSingleSelection *selection;
730
732
733 spy_tech_shell = gtk_dialog_new_with_buttons(_("Steal Technology"),
734 NULL, 0,
735 _("_Cancel"), GTK_RESPONSE_CANCEL,
736 _("_Steal"), GTK_RESPONSE_ACCEPT,
737 NULL);
739
742
743 frame = gtk_frame_new(_("Select Advance to Steal"));
745
751
753
754 selection = gtk_single_selection_new(G_LIST_MODEL(store));
756
759 nullptr);
761 nullptr);
762
765
767 "use-underline", TRUE,
768 "mnemonic-widget", list,
769 "label", _("_Advances:"),
770 "xalign", 0.0,
771 "yalign", 0.5,
772 NULL);
773 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
774
775 gtk_grid_attach(GTK_GRID(vgrid), list, 0, 1, 1, 1);
776
777 /* Now populate the list */
778 if (pvictim) { /* You don't want to know what lag can do -- Syela */
779 const struct research *presearch = research_get(pplayer);
780 const struct research *vresearch = research_get(pvictim);
781 GValue value = { 0, };
782
789
791 row->id = i;
792
793 g_list_store_append(store, row);
795 }
797
801
802 {
803 struct astring str = ASTRING_INIT;
804
805 /* TRANS: %s is a unit name, e.g., Spy */
806 astr_set(&str, _("At %s's Discretion"),
809
810 row->name = fc_strdup(astr_str(&str));
811
812 astr_free(&str);
813 }
814
815 row->id = A_UNSET;
816
817 g_list_store_append(store, row);
819 }
820 }
821
824
826 TRUE);
827
828 g_signal_connect(selection, "selection-changed",
832
833 args->target_tech_id = 0;
834}
835
836/**********************************************************************/
839static void spy_improvements_response(GtkWidget *w, gint response, gpointer data)
840{
841 struct action_data *args = (struct action_data *)data;
842
843 if (response == GTK_RESPONSE_ACCEPT && args->target_building_id > -2) {
846 if (args->target_building_id == B_LAST) {
847 /* This is the untargeted version. */
849 args->actor_unit_id,
850 args->target_city_id,
851 args->target_building_id, "");
852 } else if (args->target_building_id == -1) {
853 /* This is the city production version. */
855 args->actor_unit_id,
856 args->target_city_id,
857 args->target_building_id, "");
858 } else {
859 /* This is the targeted version. */
861 args->actor_unit_id,
862 args->target_city_id,
863 args->target_building_id, "");
864 }
865 }
866 }
867
870 free(args);
871
872 /* The user have answered the follow up question. Move on. */
874}
875
876/**********************************************************************/
900
901/**********************************************************************/
904static void create_improvements_list(struct player *pplayer,
905 struct city *pcity,
906 struct action_data *args)
907{
908 GtkWidget *frame, *label, *vgrid;
909 GListStore *store;
913 GtkSingleSelection *selection;
914
916
917 spy_sabotage_shell = gtk_dialog_new_with_buttons(_("Sabotage Improvements"),
918 NULL, 0,
919 _("_Cancel"), GTK_RESPONSE_CANCEL,
920 _("_Sabotage"), GTK_RESPONSE_ACCEPT,
921 NULL);
923
926
927 frame = gtk_frame_new(_("Select Improvement to Sabotage"));
929
935
937
938 selection = gtk_single_selection_new(G_LIST_MODEL(store));
940
943 nullptr);
945 nullptr);
946
947 column = gtk_column_view_column_new(_("Improvement"), factory);
949
951 "use-underline", TRUE,
952 "mnemonic-widget", list,
953 "label", _("_Improvements:"),
954 "xalign", 0.0,
955 "yalign", 0.5,
956 NULL);
957 gtk_grid_attach(GTK_GRID(vgrid), label, 0, 0, 1, 1);
958 gtk_grid_attach(GTK_GRID(vgrid), list, 0, 1, 1, 1);
959
960 /* Now populate the list */
963 args->act_id)])) {
965
966 row->name = fc_strdup(_("City Production"));
967 row->id = -1;
968
969 g_list_store_append(store, row);
971 }
972
973 city_built_iterate(pcity, pimprove) {
974 if (pimprove->sabotage > 0) {
976
978 row->id = improvement_number(pimprove);
979
980 g_list_store_append(store, row);
982 }
984
987 struct astring str = ASTRING_INIT;
989
990 /* TRANS: %s is a unit name, e.g., Spy */
991 astr_set(&str, _("At %s's Discretion"),
993
994 row->name = fc_strdup(astr_str(&str));
995 row->id = B_LAST;
996
997 g_list_store_append(store, row);
999
1000 astr_free(&str);
1001 }
1002
1005
1007 TRUE);
1008
1009 g_signal_connect(selection, "selection-changed",
1013
1014 args->target_building_id = -2;
1015}
1016
1017/**********************************************************************/
1021{
1022 struct action_data *args = (struct action_data *)data;
1023
1024 args->act_id = args->act_id;
1025
1027 struct player *pvictim = NULL;
1028
1029 if (pvcity) {
1031 }
1032
1033/* It is concievable that pvcity will not be found, because something
1034 has happened to the city during latency. Therefore we must initialize
1035 pvictim to NULL and account for !pvictim in create_advances_list. -- Syela */
1036
1037 /* FIXME: Don't discard the second tech choice dialog. */
1038 if (!spy_tech_shell) {
1041 } else {
1042 free(args);
1043 }
1044
1045 /* Wait for the player's reply before moving on to the next unit that
1046 * needs to know what action to take. */
1048
1050}
1051
1052/**********************************************************************/
1061
1062/**********************************************************************/
1071
1072/**********************************************************************/
1077 const struct action *paction)
1078{
1079 /* FIXME: Don't discard the second target choice dialog. */
1080 if (!spy_sabotage_shell) {
1082 act_data(paction->id,
1083 actor->id, pcity->id, 0, 0,
1084 0, 0, 0));
1086 }
1087}
1088
1089/**********************************************************************/
1092static void incite_response(GtkWidget *w, gint response, gpointer data)
1093{
1094 struct action_data *args = (struct action_data *)data;
1095
1096 if (response == GTK_RESPONSE_YES) {
1098 args->target_city_id, 0, "");
1099 }
1100
1102 free(args);
1103
1104 /* The user have answered the follow up question. Move on. */
1106}
1107
1108/**********************************************************************/
1111void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost,
1112 const struct action *paction)
1113{
1115 char buf[1024];
1116
1117 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
1118 "Treasury contains %d gold.",
1119 client_player()->economic.gold),
1120 client_player()->economic.gold);
1121
1125 _("You can't incite a revolt in %s."),
1127 gtk_window_set_title(GTK_WINDOW(shell), _("City can't be incited!"));
1129 } else if (cost <= client_player()->economic.gold) {
1132 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1133 PL_("Incite a revolt for %d gold?\n%s",
1134 "Incite a revolt for %d gold?\n%s", cost), cost, buf);
1135 gtk_window_set_title(GTK_WINDOW(shell), _("Incite a Revolt!"));
1137 } else {
1139 0,
1141 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1142 PL_("Inciting a revolt costs %d gold.\n%s",
1143 "Inciting a revolt costs %d gold.\n%s", cost), cost, buf);
1144 gtk_window_set_title(GTK_WINDOW(shell), _("Traitors Demand Too Much!"));
1146 }
1148
1150 act_data(paction->id, actor->id,
1151 pcity->id, 0, 0,
1152 0, 0, 0));
1153}
1154
1155/**********************************************************************/
1159{
1160 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1161
1162 if (arg == GTK_RESPONSE_YES) {
1164
1165 if (actor != NULL) {
1167 "target"));
1169 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1170
1171 if (tgt_unit == NULL) {
1172 /* Make the action dialog pop up again. */
1174 actor->id,
1175 /* Let the server choose the target
1176 * unit. */
1178 tgt_tile->index,
1181 } else {
1183 actor->id,
1184 tgt_id,
1185 tgt_tile->index,
1188 }
1189 }
1190 } else {
1191 /* Dialog canceled. This ends the action selection process. */
1193 }
1194
1196}
1197
1198/**********************************************************************/
1202{
1203 struct action_data *args = act_sel_dialog_data;
1204
1205 struct unit *punit;
1206 struct unit *tunit;
1207 struct tile *ptile;
1208
1210 && (ptile = index_to_tile(&(wld.map), args->target_tile_id))
1211 && (tunit = game_unit_by_number(args->target_unit_id))) {
1212 select_tgt_unit(punit, ptile, ptile->units, tunit,
1213 _("Target unit selection"),
1214 _("Looking for target unit:"),
1215 _("Units at tile:"),
1216 _("Select"),
1218 }
1219
1223 free(args);
1224}
1225
1226/**********************************************************************/
1230{
1231 int au_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dlg), "actor"));
1232
1233 if (arg == GTK_RESPONSE_YES) {
1235
1236 if (actor != NULL) {
1238 "target"));
1240 struct tile *tgt_tile = g_object_get_data(G_OBJECT(dlg), "tile");
1241
1242 if (tgt_extra == NULL) {
1243 /* Make the action dialog pop up again. */
1245 actor->id,
1247 tgt_tile->index,
1248 /* Let the server choose the target
1249 * extra. */
1252 } else {
1254 actor->id,
1256 tgt_tile->index,
1257 tgt_id,
1259 }
1260 }
1261 } else {
1262 /* Dialog canceled. This ends the action selection process. */
1264 }
1265
1267}
1268
1269/**********************************************************************/
1273{
1274 struct action_data *args = act_sel_dialog_data;
1275
1276 struct unit *act_unit;
1277 struct extra_type *tgt_extra;
1278 struct tile *tgt_tile;
1279
1281 && (tgt_tile = index_to_tile(&(wld.map), args->target_tile_id))
1284
1285 /* Start with the extras at the tile */
1287
1289 if (BV_ISSET(potential_targets, extra_number(pextra))) {
1290 /* This extra is at the tile. Can anything be done to it? */
1292 pextra)) {
1294 }
1295 } else {
1296 /* This extra isn't at the tile yet. Can it be created? */
1298 pextra)) {
1300 }
1301 }
1303
1305 /* TRANS: GTK action selection dialog extra target
1306 * selection dialog title. */
1307 _("Target extra selection"),
1308 /* TRANS: GTK action selection dialog extra target
1309 * selection dialog actor unit label. */
1310 _("Looking for target extra:"),
1311 /* TRANS: GTK action selection dialog extra target
1312 * selection dialog extra list label. */
1313 _("Extra targets:"),
1314 _("Select"),
1316 }
1317
1321 free(args);
1322}
1323
1324/**********************************************************************/
1328{
1329 struct action_data *args = act_sel_dialog_data;
1330
1331 struct unit *punit;
1332
1333 if ((punit = game_unit_by_number(args->actor_unit_id))) {
1335 }
1336}
1337
1338/**********************************************************************/
1342{
1343 struct action_data *args = act_sel_dialog_data;
1344
1345 key_unit_wait();
1346
1347 /* The dialog was destroyed when key_unit_wait() resulted in
1348 * action_selection_close() being called. */
1349
1350 free(args);
1351}
1352
1353/**********************************************************************/
1361
1362/**********************************************************************/
1370
1371/**********************************************************************/
1379
1380/* Mapping from an action to the function to call when its button is
1381 * pushed. */
1383 /* Unit acting against a city target. */
1394
1395 /* Unit acting against a unit target. */
1397
1398 /* Unit acting against all units at a tile. */
1400
1401 /* Unit acting against a tile. */
1403
1404 /* Unit acting with no target except itself. */
1405 /* No special callback functions needed for any self targeted actions. */
1406};
1407
1408/**********************************************************************/
1413 const struct act_prob *act_probs,
1414 const char *custom,
1416{
1417 const gchar *label;
1418 const gchar *tooltip;
1419 GCallback cb;
1420
1421 if (af_map[act_id] == NULL) {
1422 /* No special call back function needed for this action. */
1424 } else {
1425 /* Special action specific callback function specified. */
1426 cb = af_map[act_id];
1427 }
1428
1429 /* Don't show disabled actions. */
1431 return;
1432 }
1433
1434 label = action_prepare_ui_name(act_id, "_",
1436 custom);
1437
1439 act_probs[act_id]);
1440
1443 FALSE, tooltip);
1444}
1445
1446/**********************************************************************/
1451 const struct act_prob *act_probs,
1452 const char *custom,
1454{
1455 const gchar *label;
1456 const gchar *tooltip;
1457
1458 /* An action that just became impossible has its button disabled.
1459 * An action that became possible again must be re-enabled. */
1463
1464 /* The probability may have changed. */
1465 label = action_prepare_ui_name(act_id, "_",
1467
1469 act_probs[act_id]);
1470
1473 label);
1476 tooltip);
1477}
1478
1479/**********************************************************************/
1484 struct city *target_city,
1485 struct unit *target_unit,
1486 struct tile *target_tile,
1487 struct extra_type *target_extra,
1488 const struct act_prob *act_probs)
1489{
1490 GtkWidget *shl;
1491 struct astring title = ASTRING_INIT, text = ASTRING_INIT;
1492 struct city *actor_homecity;
1493
1494 int button_id;
1495
1497 act_data(ACTION_ANY, /* Not decided yet */
1498 actor_unit->id,
1502 /* No target_building or target_tech supplied. (Dec 2019) */
1503 B_LAST, A_UNSET,
1505
1506 /* Could be caused by the server failing to reply to a request for more
1507 * information or a bug in the client code. */
1509 "Diplomat queue problem. Is another diplomat window open?");
1510
1511 /* No extra input is required as no action has been chosen yet. */
1513
1514 /* No buttons are added yet. */
1515 for (button_id = 0; button_id < BUTTON_COUNT; button_id++) {
1517 }
1518
1520
1524 target_city->id :
1527 target_unit->id :
1540 EXTRA_NONE;
1541
1542 astr_set(&title,
1543 /* TRANS: %s is a unit name, e.g., Spy */
1544 _("Choose Your %s's Strategy"),
1546
1547 if (target_city && actor_homecity) {
1548 astr_set(&text,
1549 _("Your %s from %s reaches the city of %s.\nWhat now?"),
1553 } else if (target_city) {
1554 astr_set(&text,
1555 _("Your %s has arrived at %s.\nWhat is your command?"),
1558 } else if (target_unit) {
1559 astr_set(&text,
1560 /* TRANS: Your Spy is ready to act against Roman Freight. */
1561 _("Your %s is ready to act against %s %s."),
1565 } else {
1567 "No target specified.");
1568 astr_set(&text,
1569 /* TRANS: %s is a unit name, e.g., Diplomat, Spy */
1570 _("Your %s is waiting for your command."),
1572 }
1573
1575 astr_str(&text));
1576
1577 /* Unit acting against a city */
1578
1579 action_iterate(act) {
1584 act_probs[act],
1585 actor_unit,
1586 target_city),
1587 act);
1588 }
1590
1591 /* Unit acting against another unit */
1592
1593 action_iterate(act) {
1598 act_probs[act],
1599 actor_unit,
1600 target_city),
1601 act);
1602 }
1604
1605 /* Unit acting against all units at a tile */
1606
1607 action_iterate(act) {
1612 act_probs[act],
1613 actor_unit,
1614 target_city),
1615 act);
1616 }
1618
1619 /* Unit acting against a tile */
1620
1621 action_iterate(act) {
1626 act_probs[act],
1627 actor_unit,
1628 target_city),
1629 act);
1630 }
1632
1633 /* Unit acting against a tile's extras */
1634
1635 action_iterate(act) {
1640 act_probs[act],
1641 actor_unit,
1642 target_city),
1643 act);
1644 }
1646
1647 /* Unit acting against itself. */
1648
1649 action_iterate(act) {
1654 act_probs[act],
1655 actor_unit,
1656 target_city),
1657 act);
1658 }
1660
1661 if (target_unit != NULL
1662 && unit_list_size(target_tile->units) > 1) {
1665 choice_dialog_add(shl, _("Change unit target"),
1668 }
1669
1670 if (target_extra != NULL) {
1673 choice_dialog_add(shl, _("Change extra target"),
1676 }
1677
1680 choice_dialog_add(shl, _("Show Location"),
1683 TRUE, NULL);
1684
1687 choice_dialog_add(shl, _("_Wait"),
1690 TRUE, NULL);
1691
1694 choice_dialog_add(shl, _("_Cancel"),
1697 FALSE, NULL);
1698
1700
1702
1704 g_signal_connect(shl, "destroy",
1706 g_signal_connect(shl, "close-request",
1709
1710 /* Give follow up questions access to action probabilities. */
1712 action_iterate(act) {
1715
1716 astr_free(&title);
1717 astr_free(&text);
1718}
1719
1720/**********************************************************************/
1726{
1727 if (act_sel_dialog == NULL) {
1728 return IDENTITY_NUMBER_ZERO;
1729 }
1730 return actor_unit_id;
1731}
1732
1733/**********************************************************************/
1740{
1741 if (act_sel_dialog == NULL) {
1742 return IDENTITY_NUMBER_ZERO;
1743 }
1744 return target_ids[ATK_CITY];
1745}
1746
1747/**********************************************************************/
1754{
1755 if (act_sel_dialog == NULL) {
1756 return IDENTITY_NUMBER_ZERO;
1757 }
1758
1759 return target_ids[ATK_UNIT];
1760}
1761
1762/**********************************************************************/
1769{
1770 if (act_sel_dialog == NULL) {
1771 return TILE_INDEX_NONE;
1772 }
1773
1774 return target_ids[ATK_TILE];
1775}
1776
1777/**********************************************************************/
1784{
1785 if (act_sel_dialog == NULL) {
1786 return EXTRA_NONE;
1787 }
1788
1789 return target_extra_id;
1790}
1791
1792/**********************************************************************/
1796 struct city *target_city,
1797 struct unit *target_unit,
1798 struct tile *target_tile,
1799 struct extra_type *target_extra,
1800 const struct act_prob *act_probs)
1801{
1802 if (act_sel_dialog == NULL) {
1804 "The action selection dialog should have been open");
1805 return;
1806 }
1807
1810 "The action selection dialog is for another actor unit.");
1811 return;
1812 }
1813
1814 /* A new target may have appeared. */
1815 if (target_city) {
1817 }
1818 if (target_unit) {
1820 }
1821 if (target_tile) {
1823 }
1824 /* No target_building or target_tech supplied. (Dec 2019) */
1825 if (target_extra) {
1827 }
1828
1829 action_iterate(act) {
1830 const char *custom;
1831
1832 if (action_id_get_actor_kind(act) != AAK_UNIT) {
1833 /* Not relevant. */
1834 continue;
1835 }
1836
1838 act_probs[act],
1839 actor_unit,
1840 target_city);
1841
1842 if (BUTTON_NOT_THERE == action_button_map[act]) {
1843 /* Add the button (unless its probability is 0). */
1845 } else {
1846 /* Update the existing button. */
1848 }
1850
1851 /* DO NOT change the action_button_map[] for any button to reflect its
1852 * new position. A button keeps its choice dialog internal name when its
1853 * position changes. A button's id number is therefore based on when
1854 * it was added, not on its current position. */
1855
1857 /* Move the wait button below the recently added button. */
1860 }
1861
1863 /* Move the cancel button below the recently added button. */
1866 }
1867
1869}
1870
1871/**********************************************************************/
1875{
1876 if (act_sel_dialog != NULL) {
1879 }
1880}
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
static struct ai_type * self
Definition classicai.c:46
struct civclient client
#define client_player()
void client_unit_init_act_prob_cache(struct unit *punit)
Definition climisc.c:1259
static struct fc_sockaddr_list * list
Definition clinet.c:102
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 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)
static void fc_action_row_class_init(FcActionRowClass *klass)
static void fc_action_row_init(FcActionRow *self)
static void fc_action_row_finalize(GObject *gobject)
#define FC_TYPE_ACTION_ROW
static void action_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
static FcActionRow * fc_action_row_new(void)
static void action_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
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_strdup(str)
Definition mem.h:43
#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
GObjectClass parent_class
GObject parent_instance
int target_building_id
action_id act_id
char name[MAX_LEN_NAME]
Definition ai.h:51
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