webperimental: Mountain vision bonus.
[freeciv.git] / client / gui-sdl2 / action_dialog.c
blob1eab773f69347888f112f317924ebfe668769c7f
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996-2006 - 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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* utility */
19 #include "astring.h"
20 #include "fcintl.h"
21 #include "log.h"
23 /* common */
24 #include "actions.h"
25 #include "game.h"
26 #include "movement.h"
27 #include "research.h"
28 #include "traderoutes.h"
29 #include "unitlist.h"
31 /* client */
32 #include "client_main.h"
33 #include "climisc.h"
34 #include "control.h"
36 /* client/gui-sdl2 */
37 #include "citydlg.h"
38 #include "colors.h"
39 #include "dialogs.h"
40 #include "graphics.h"
41 #include "gui_id.h"
42 #include "gui_tilespec.h"
43 #include "mapview.h"
44 #include "repodlgs.h"
45 #include "themespec.h"
46 #include "widget.h"
48 #include "dialogs_g.h"
50 typedef int (*act_func)(struct widget *);
52 struct diplomat_dialog {
53 int actor_unit_id;
54 int target_ids[ATK_COUNT];
55 struct ADVANCED_DLG *pdialog;
58 struct small_diplomat_dialog {
59 int actor_unit_id;
60 int target_id;
61 struct SMALL_DLG *pdialog;
64 extern bool is_unit_move_blocked;
66 void popdown_diplomat_dialog(void);
67 void popdown_incite_dialog(void);
68 void popdown_bribe_dialog(void);
71 static struct diplomat_dialog *pDiplomat_Dlg = NULL;
72 static bool is_more_user_input_needed = FALSE;
73 static bool did_not_decide = FALSE;
75 /**************************************************************************
76 The action selection is done.
77 **************************************************************************/
78 static void act_sel_done_primary(int actor_unit_id)
80 if (!is_more_user_input_needed) {
81 /* The client isn't waiting for information for any unanswered follow
82 * up questions. */
84 struct unit *actor_unit;
86 if ((actor_unit = game_unit_by_number(actor_unit_id))) {
87 /* The action selection dialog wasn't closed because the actor unit
88 * was lost. */
90 /* The probabilities didn't just disappear, right? */
91 fc_assert_action(actor_unit->client.act_prob_cache,
92 client_unit_init_act_prob_cache(actor_unit));
94 FC_FREE(actor_unit->client.act_prob_cache);
97 /* The action selection process is over, at least for now. */
98 action_selection_no_longer_in_progress(actor_unit_id);
100 if (did_not_decide) {
101 /* The action selection dialog was closed but the player didn't
102 * decide what the unit should do. */
104 /* Reset so the next action selection dialog does the right thing. */
105 did_not_decide = FALSE;
106 } else {
107 /* An action, or no action at all, was selected. */
108 action_decision_clear_want(actor_unit_id);
109 action_selection_next_in_focus(actor_unit_id);
114 /**************************************************************************
115 A follow up question about the selected action is done.
116 **************************************************************************/
117 static void act_sel_done_secondary(int actor_unit_id)
119 /* Stop blocking. */
120 is_more_user_input_needed = FALSE;
121 act_sel_done_primary(actor_unit_id);
124 /* ====================================================================== */
125 /* ============================ CARAVAN DIALOG ========================== */
126 /* ====================================================================== */
128 /****************************************************************
129 User selected that caravan should enter marketplace.
130 *****************************************************************/
131 static int caravan_marketplace_callback(struct widget *pWidget)
133 if (Main.event.button.button == SDL_BUTTON_LEFT) {
134 if (NULL != game_city_by_number(
135 pDiplomat_Dlg->target_ids[ATK_CITY])
136 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
137 request_do_action(ACTION_MARKETPLACE,
138 pDiplomat_Dlg->actor_unit_id,
139 pDiplomat_Dlg->target_ids[ATK_CITY],
140 0, "");
143 popdown_diplomat_dialog();
146 return -1;
149 /****************************************************************
150 User selected that caravan should establish traderoute.
151 *****************************************************************/
152 static int caravan_establish_trade_callback(struct widget *pWidget)
154 if (Main.event.button.button == SDL_BUTTON_LEFT) {
155 if (NULL != game_city_by_number(
156 pDiplomat_Dlg->target_ids[ATK_CITY])
157 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
158 request_do_action(ACTION_TRADE_ROUTE,
159 pDiplomat_Dlg->actor_unit_id,
160 pDiplomat_Dlg->target_ids[ATK_CITY],
161 0, "");
164 popdown_diplomat_dialog();
167 return -1;
170 /****************************************************************
171 User selected that caravan should help in wonder building.
172 *****************************************************************/
173 static int caravan_help_build_wonder_callback(struct widget *pWidget)
175 if (Main.event.button.button == SDL_BUTTON_LEFT) {
176 if (NULL != game_city_by_number(
177 pDiplomat_Dlg->target_ids[ATK_CITY])
178 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
179 request_do_action(ACTION_HELP_WONDER,
180 pDiplomat_Dlg->actor_unit_id,
181 pDiplomat_Dlg->target_ids[ATK_CITY],
182 0, "");
185 popdown_diplomat_dialog();
188 return -1;
191 /****************************************************************
192 User selected to Recycle Unit to help city production.
193 *****************************************************************/
194 static int unit_recycle_callback(struct widget *pWidget)
196 if (Main.event.button.button == SDL_BUTTON_LEFT) {
197 if (NULL != game_city_by_number(
198 pDiplomat_Dlg->target_ids[ATK_CITY])
199 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
200 request_do_action(ACTION_RECYCLE_UNIT,
201 pDiplomat_Dlg->actor_unit_id,
202 pDiplomat_Dlg->target_ids[ATK_CITY],
203 0, "");
206 popdown_diplomat_dialog();
209 return -1;
212 /* ====================================================================== */
213 /* ============================ DIPLOMAT DIALOG ========================= */
214 /* ====================================================================== */
216 /****************************************************************
217 User interacted with diplomat dialog.
218 *****************************************************************/
219 static int diplomat_dlg_window_callback(struct widget *pWindow)
221 if (Main.event.button.button == SDL_BUTTON_LEFT) {
222 move_window_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow);
225 return -1;
228 /****************************************************************
229 User clicked "Establish Embassy"
230 *****************************************************************/
231 static int diplomat_embassy_callback(struct widget *pWidget)
233 if (Main.event.button.button == SDL_BUTTON_LEFT) {
234 if (NULL != game_city_by_number(
235 pDiplomat_Dlg->target_ids[ATK_CITY])
236 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
237 request_do_action(ACTION_ESTABLISH_EMBASSY,
238 pDiplomat_Dlg->actor_unit_id,
239 pDiplomat_Dlg->target_ids[ATK_CITY],
240 0, "");
243 popdown_diplomat_dialog();
246 return -1;
249 /****************************************************************
250 User clicked "Investigate City"
251 *****************************************************************/
252 static int diplomat_investigate_callback(struct widget *pWidget)
254 if (Main.event.button.button == SDL_BUTTON_LEFT) {
255 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
256 && NULL != game_city_by_number(
257 pDiplomat_Dlg->target_ids[ATK_CITY])) {
258 request_do_action(ACTION_SPY_INVESTIGATE_CITY,
259 pDiplomat_Dlg->actor_unit_id,
260 pDiplomat_Dlg->target_ids[ATK_CITY],
261 0, "");
264 /* FIXME: Wait for the city display in stead? */
265 popdown_diplomat_dialog();
268 return -1;
271 /****************************************************************
272 User clicked "Poison City"
273 *****************************************************************/
274 static int spy_poison_callback(struct widget *pWidget)
276 if (Main.event.button.button == SDL_BUTTON_LEFT) {
277 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
278 && NULL != game_city_by_number(
279 pDiplomat_Dlg->target_ids[ATK_CITY])) {
280 request_do_action(ACTION_SPY_POISON, pDiplomat_Dlg->actor_unit_id,
281 pDiplomat_Dlg->target_ids[ATK_CITY],
282 0, "");
285 popdown_diplomat_dialog();
288 return -1;
291 /****************************************************************
292 User clicked "Suitcase Nuke"
293 *****************************************************************/
294 static int spy_nuke_city_callback(struct widget *pWidget)
296 if (Main.event.button.button == SDL_BUTTON_LEFT) {
297 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
298 && NULL != game_city_by_number(
299 pDiplomat_Dlg->target_ids[ATK_CITY])) {
300 request_do_action(ACTION_SPY_NUKE, pDiplomat_Dlg->actor_unit_id,
301 pDiplomat_Dlg->target_ids[ATK_CITY],
302 0, "");
305 popdown_diplomat_dialog();
308 return -1;
311 /****************************************************************
312 User clicked "Destroy City"
313 *****************************************************************/
314 static int destroy_city_callback(struct widget *pWidget)
316 if (Main.event.button.button == SDL_BUTTON_LEFT) {
317 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
318 && NULL != game_city_by_number(
319 pDiplomat_Dlg->target_ids[ATK_CITY])) {
320 request_do_action(ACTION_DESTROY_CITY, pDiplomat_Dlg->actor_unit_id,
321 pDiplomat_Dlg->target_ids[ATK_CITY],
322 0, "");
325 popdown_diplomat_dialog();
328 return -1;
331 /********************************************************************
332 User clicked "Steal Gold"
333 ********************************************************************/
334 static int spy_steal_gold_callback(struct widget *pWidget)
336 if (Main.event.button.button == SDL_BUTTON_LEFT) {
337 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
338 && NULL != game_city_by_number(
339 pDiplomat_Dlg->target_ids[ATK_CITY])) {
340 request_do_action(ACTION_SPY_STEAL_GOLD,
341 pDiplomat_Dlg->actor_unit_id,
342 pDiplomat_Dlg->target_ids[ATK_CITY],
343 0, "");
346 popdown_diplomat_dialog();
349 return -1;
352 /********************************************************************
353 User clicked "Steal Maps"
354 ********************************************************************/
355 static int spy_steal_maps_callback(struct widget *pWidget)
357 if (Main.event.button.button == SDL_BUTTON_LEFT) {
358 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
359 && NULL != game_city_by_number(
360 pDiplomat_Dlg->target_ids[ATK_CITY])) {
361 request_do_action(ACTION_STEAL_MAPS,
362 pDiplomat_Dlg->actor_unit_id,
363 pDiplomat_Dlg->target_ids[ATK_CITY],
364 0, "");
367 popdown_diplomat_dialog();
370 return -1;
373 /****************************************************************
374 Requests up-to-date list of improvements, the return of
375 which will trigger the popup_sabotage_dialog() function.
376 *****************************************************************/
377 static int spy_sabotage_request(struct widget *pWidget)
379 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
380 && NULL != game_city_by_number(
381 pDiplomat_Dlg->target_ids[ATK_CITY])) {
382 request_action_details(ACTION_SPY_TARGETED_SABOTAGE_CITY,
383 pDiplomat_Dlg->actor_unit_id,
384 pDiplomat_Dlg->target_ids[ATK_CITY]);
385 is_more_user_input_needed = TRUE;
386 popdown_diplomat_dialog();
387 } else {
388 popdown_diplomat_dialog();
391 return -1;
394 /****************************************************************
395 User clicked "Sabotage City" for diplomat (not spy)
396 *****************************************************************/
397 static int diplomat_sabotage_callback(struct widget *pWidget)
399 if (Main.event.button.button == SDL_BUTTON_LEFT) {
400 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
401 && NULL != game_city_by_number(
402 pDiplomat_Dlg->target_ids[ATK_CITY])) {
403 request_do_action(ACTION_SPY_SABOTAGE_CITY,
404 pDiplomat_Dlg->actor_unit_id,
405 pDiplomat_Dlg->target_ids[ATK_CITY],
406 B_LAST + 1, "");
409 popdown_diplomat_dialog();
412 return -1;
415 /* --------------------------------------------------------- */
417 /****************************************************************
418 User interacted with spy's steal dialog window.
419 *****************************************************************/
420 static int spy_steal_dlg_window_callback(struct widget *pWindow)
422 if (Main.event.button.button == SDL_BUTTON_LEFT) {
423 move_window_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow);
426 return -1;
429 /****************************************************************
430 Exit spy's steal or sabotage dialog.
431 *****************************************************************/
432 static int exit_spy_tgt_dlg_callback(struct widget *pWidget)
434 if (Main.event.button.button == SDL_BUTTON_LEFT) {
435 int actor_id = pDiplomat_Dlg->actor_unit_id;
437 fc_assert(is_more_user_input_needed);
438 popdown_diplomat_dialog();
439 act_sel_done_secondary(actor_id);
442 return -1;
445 /****************************************************************
446 User selected which tech spy steals.
447 *****************************************************************/
448 static int spy_steal_callback(struct widget *pWidget)
450 if (Main.event.button.button == SDL_BUTTON_LEFT) {
451 int steal_advance = MAX_ID - pWidget->ID;
452 int actor_id = pDiplomat_Dlg->actor_unit_id;
454 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
455 && NULL != game_city_by_number(
456 pDiplomat_Dlg->target_ids[ATK_CITY])) {
457 if (steal_advance == A_UNSET) {
458 /* This is the untargeted version. */
459 request_do_action(ACTION_SPY_STEAL_TECH,
460 pDiplomat_Dlg->actor_unit_id,
461 pDiplomat_Dlg->target_ids[ATK_CITY],
462 steal_advance, "");
463 } else {
464 /* This is the targeted version. */
465 request_do_action(ACTION_SPY_TARGETED_STEAL_TECH,
466 pDiplomat_Dlg->actor_unit_id,
467 pDiplomat_Dlg->target_ids[ATK_CITY],
468 steal_advance, "");
472 fc_assert(is_more_user_input_needed);
473 popdown_diplomat_dialog();
474 act_sel_done_secondary(actor_id);
477 return -1;
480 /**************************************************************************
481 Popup spy tech stealing dialog.
482 **************************************************************************/
483 static int spy_steal_popup(struct widget *pWidget)
485 const struct research *presearch, *vresearch;
486 struct city *pVcity = pWidget->data.city;
487 int id = MAX_ID - pWidget->ID;
488 struct player *pVictim = NULL;
489 struct CONTAINER *pCont;
490 struct widget *pBuf = NULL;
491 struct widget *pWindow;
492 utf8_str *pstr;
493 SDL_Surface *pSurf;
494 int max_col, max_row, col, count = 0;
495 int tech, idx;
496 SDL_Rect area;
498 struct unit *actor_unit = game_unit_by_number(id);
500 is_more_user_input_needed = TRUE;
501 popdown_diplomat_dialog();
503 if (pVcity) {
504 pVictim = city_owner(pVcity);
507 fc_assert_ret_val_msg(!pDiplomat_Dlg, 1, "Diplomat dialog already open");
509 if (!pVictim) {
510 act_sel_done_secondary(id);
511 return 1;
514 count = 0;
515 presearch = research_get(client_player());
516 vresearch = research_get(pVictim);
517 advance_index_iterate(A_FIRST, i) {
518 if (research_invention_gettable(presearch, i,
519 game.info.tech_steal_allow_holes)
520 && TECH_KNOWN == research_invention_state(vresearch, i)
521 && TECH_KNOWN != research_invention_state(presearch, i)) {
522 count++;
524 } advance_index_iterate_end;
526 if (!count) {
527 /* if there is no known tech to steal then
528 * send steal order at Spy's Discretion */
529 int target_id = pVcity->id;
531 request_do_action(ACTION_SPY_STEAL_TECH,
532 id, target_id, A_UNSET, "");
534 act_sel_done_secondary(id);
536 return -1;
539 pCont = fc_calloc(1, sizeof(struct CONTAINER));
540 pCont->id0 = pVcity->id;
541 pCont->id1 = id;/* spy id */
543 pDiplomat_Dlg = fc_calloc(1, sizeof(struct diplomat_dialog));
544 pDiplomat_Dlg->actor_unit_id = id;
545 pDiplomat_Dlg->target_ids[ATK_CITY] = pVcity->id;
546 pDiplomat_Dlg->pdialog = fc_calloc(1, sizeof(struct ADVANCED_DLG));
548 pstr = create_utf8_from_char(_("Select Advance to Steal"), adj_font(12));
549 pstr->style |= TTF_STYLE_BOLD;
551 pWindow = create_window_skeleton(NULL, pstr, 0);
553 pWindow->action = spy_steal_dlg_window_callback;
554 set_wstate(pWindow , FC_WS_NORMAL);
556 add_to_gui_list(ID_DIPLOMAT_DLG_WINDOW, pWindow);
557 pDiplomat_Dlg->pdialog->pEndWidgetList = pWindow;
559 area = pWindow->area;
560 area.w = MAX(area.w, adj_size(8));
562 /* ------------------ */
563 /* exit button */
564 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
565 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
566 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
567 adj_font(12));
568 area.w += pBuf->size.w + adj_size(10);
569 pBuf->action = exit_spy_tgt_dlg_callback;
570 set_wstate(pBuf, FC_WS_NORMAL);
571 pBuf->key = SDLK_ESCAPE;
573 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf);
574 /* ------------------------- */
576 if (action_prob_possible(
577 actor_unit->client.act_prob_cache[ACTION_SPY_STEAL_TECH])) {
578 /* count + at Spy's Discretion */
579 count++;
582 /* max col - 104 is steal tech widget width */
583 max_col = (main_window_width() - (pWindow->size.w - pWindow->area.w) - adj_size(2)) / adj_size(104);
584 /* max row - 204 is steal tech widget height */
585 max_row = (main_window_height() - (pWindow->size.h - pWindow->area.h)) / adj_size(204);
587 /* make space on screen for scrollbar */
588 if (max_col * max_row < count) {
589 max_col--;
592 if (count < max_col + 1) {
593 col = count;
594 } else {
595 if (count < max_col + adj_size(3)) {
596 col = max_col - adj_size(2);
597 } else {
598 if (count < max_col + adj_size(5)) {
599 col = max_col - 1;
600 } else {
601 col = max_col;
606 pstr = create_utf8_str(NULL, 0, adj_font(10));
607 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
609 count = 0;
610 advance_index_iterate(A_FIRST, i) {
611 if (research_invention_gettable(presearch, i,
612 game.info.tech_steal_allow_holes)
613 && TECH_KNOWN == research_invention_state(vresearch, i)
614 && TECH_KNOWN != research_invention_state(presearch, i)) {
615 count++;
617 copy_chars_to_utf8_str(pstr, advance_name_translation(advance_by_number(i)));
618 pSurf = create_select_tech_icon(pstr, i, FULL_MODE);
619 pBuf = create_icon2(pSurf, pWindow->dst,
620 WF_FREE_THEME | WF_RESTORE_BACKGROUND);
622 set_wstate(pBuf, FC_WS_NORMAL);
623 pBuf->action = spy_steal_callback;
624 pBuf->data.cont = pCont;
626 add_to_gui_list(MAX_ID - i, pBuf);
628 if (count > (col * max_row)) {
629 set_wflag(pBuf, WF_HIDDEN);
632 } advance_index_iterate_end;
634 /* Get Spy tech to use for "At Spy's Discretion" -- this will have the
635 * side effect of displaying the unit's icon */
636 tech = advance_number(unit_type_get(actor_unit)->require_advance);
638 if (action_prob_possible(
639 actor_unit->client.act_prob_cache[ACTION_SPY_STEAL_TECH])) {
640 struct astring str = ASTRING_INIT;
642 /* TRANS: %s is a unit name, e.g., Spy */
643 astr_set(&str, _("At %s's Discretion"),
644 unit_name_translation(actor_unit));
645 copy_chars_to_utf8_str(pstr, astr_str(&str));
646 astr_free(&str);
648 pSurf = create_select_tech_icon(pstr, tech, FULL_MODE);
650 pBuf = create_icon2(pSurf, pWindow->dst,
651 (WF_FREE_THEME | WF_RESTORE_BACKGROUND
652 | WF_FREE_DATA));
653 set_wstate(pBuf, FC_WS_NORMAL);
654 pBuf->action = spy_steal_callback;
655 pBuf->data.cont = pCont;
657 add_to_gui_list(MAX_ID - A_UNSET, pBuf);
658 count++;
661 /* --------------------------------------------------------- */
662 FREEUTF8STR(pstr);
663 pDiplomat_Dlg->pdialog->pBeginWidgetList = pBuf;
664 pDiplomat_Dlg->pdialog->pBeginActiveWidgetList = pDiplomat_Dlg->pdialog->pBeginWidgetList;
665 pDiplomat_Dlg->pdialog->pEndActiveWidgetList = pDiplomat_Dlg->pdialog->pEndWidgetList->prev->prev;
667 /* -------------------------------------------------------------- */
669 idx = 0;
670 if (count > col) {
671 count = (count + (col - 1)) / col;
672 if (count > max_row) {
673 pDiplomat_Dlg->pdialog->pActiveWidgetList = pDiplomat_Dlg->pdialog->pEndActiveWidgetList;
674 count = max_row;
675 idx = create_vertical_scrollbar(pDiplomat_Dlg->pdialog, col, count, TRUE, TRUE);
677 } else {
678 count = 1;
681 area.w = MAX(area.w, (col * pBuf->size.w + adj_size(2) + idx));
682 area.h = count * pBuf->size.h + adj_size(2);
684 /* alloca window theme and win background buffer */
685 pSurf = theme_get_background(theme, BACKGROUND_SPYSTEALDLG);
686 if (resize_window(pWindow, pSurf, NULL,
687 (pWindow->size.w - pWindow->area.w) + area.w,
688 (pWindow->size.h - pWindow->area.h) + area.h)) {
689 FREESURFACE(pSurf);
692 area = pWindow->area;
694 widget_set_position(pWindow,
695 (main_window_width() - pWindow->size.w) / 2,
696 (main_window_height() - pWindow->size.h) / 2);
698 /* exit button */
699 pBuf = pWindow->prev;
700 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
701 pBuf->size.y = pWindow->size.y + adj_size(2);
703 setup_vertical_widgets_position(col, area.x + 1,
704 area.y, 0, 0,
705 pDiplomat_Dlg->pdialog->pBeginActiveWidgetList,
706 pDiplomat_Dlg->pdialog->pEndActiveWidgetList);
708 if (pDiplomat_Dlg->pdialog->pScroll) {
709 setup_vertical_scrollbar_area(pDiplomat_Dlg->pdialog->pScroll,
710 area.x + area.w, area.y,
711 area.h, TRUE);
714 redraw_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow, FALSE);
715 widget_mark_dirty(pWindow);
717 return -1;
720 /****************************************************************
721 Technology stealing dialog, diplomat (not spy) version
722 *****************************************************************/
723 static int diplomat_steal_callback(struct widget *pWidget)
725 if (Main.event.button.button == SDL_BUTTON_LEFT) {
726 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
727 && NULL != game_city_by_number(
728 pDiplomat_Dlg->target_ids[ATK_CITY])) {
729 request_do_action(ACTION_SPY_STEAL_TECH,
730 pDiplomat_Dlg->actor_unit_id,
731 pDiplomat_Dlg->target_ids[ATK_CITY],
732 A_UNSET, "");
735 popdown_diplomat_dialog();
738 return -1;
741 /****************************************************************
742 ... Ask the server how much the revolt is going to cost us
743 *****************************************************************/
744 static int diplomat_incite_callback(struct widget *pWidget)
746 if (Main.event.button.button == SDL_BUTTON_LEFT) {
747 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
748 && NULL != game_city_by_number(
749 pDiplomat_Dlg->target_ids[ATK_CITY])) {
750 request_action_details(ACTION_SPY_INCITE_CITY,
751 pDiplomat_Dlg->actor_unit_id,
752 pDiplomat_Dlg->target_ids[ATK_CITY]);
753 is_more_user_input_needed = TRUE;
754 popdown_diplomat_dialog();
755 } else {
756 popdown_diplomat_dialog();
760 return -1;
763 /********************************************************************
764 Callback from action selection dialog for "keep moving".
765 (This should only occur when entering a tile with an allied city
766 or an allied unit.)
767 *********************************************************************/
768 static int act_sel_keep_moving_callback(struct widget *pWidget)
770 if (Main.event.button.button == SDL_BUTTON_LEFT) {
771 struct unit *punit;
773 if ((punit = game_unit_by_number(pDiplomat_Dlg->actor_unit_id))
774 && !same_pos(unit_tile(punit), pWidget->data.tile)) {
775 request_unit_non_action_move(punit, pWidget->data.tile);
778 popdown_diplomat_dialog();
781 return -1;
784 /********************************************************************
785 Delay selection of what action to take.
786 *********************************************************************/
787 static int act_sel_wait_callback(struct widget *pWidget)
789 if (Main.event.button.button == SDL_BUTTON_LEFT) {
790 key_unit_wait();
792 /* The dialog was popped down when key_unit_wait() resulted in
793 * action_selection_close() being called. */
796 return -1;
799 /****************************************************************
800 ... Ask the server how much the bribe is
801 *****************************************************************/
802 static int diplomat_bribe_callback(struct widget *pWidget)
804 if (Main.event.button.button == SDL_BUTTON_LEFT) {
805 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
806 && NULL !=
807 game_unit_by_number(pDiplomat_Dlg->target_ids[ATK_UNIT])) {
808 request_action_details(ACTION_SPY_BRIBE_UNIT,
809 pDiplomat_Dlg->actor_unit_id,
810 pDiplomat_Dlg->target_ids[ATK_UNIT]);
811 is_more_user_input_needed = TRUE;
812 popdown_diplomat_dialog();
813 } else {
814 popdown_diplomat_dialog();
818 return -1;
821 /****************************************************************
822 User clicked "Sabotage Unit"
823 *****************************************************************/
824 static int spy_sabotage_unit_callback(struct widget *pWidget)
826 if (Main.event.button.button == SDL_BUTTON_LEFT) {
827 int diplomat_id = MAX_ID - pWidget->ID;
828 int target_id = pWidget->data.unit->id;
830 popdown_diplomat_dialog();
831 request_do_action(ACTION_SPY_SABOTAGE_UNIT,
832 diplomat_id, target_id, 0, "");
835 return -1;
838 /****************************************************************
839 User clicked "Heal Unit"
840 *****************************************************************/
841 static int heal_unit_callback(struct widget *pWidget)
843 if (Main.event.button.button == SDL_BUTTON_LEFT) {
844 int actor_id = MAX_ID - pWidget->ID;
845 int target_id = pWidget->data.unit->id;
847 popdown_diplomat_dialog();
848 request_do_action(ACTION_HEAL_UNIT,
849 actor_id, target_id, 0, "");
852 return -1;
855 /****************************************************************
856 User clicked "Capture Units"
857 *****************************************************************/
858 static int capture_units_callback(struct widget *pWidget)
860 if (Main.event.button.button == SDL_BUTTON_LEFT) {
861 int actor_id = MAX_ID - pWidget->ID;
862 int target_id = tile_index(pWidget->data.tile);
864 popdown_diplomat_dialog();
865 request_do_action(ACTION_CAPTURE_UNITS,
866 actor_id, target_id, 0, "");
869 return -1;
872 /****************************************************************
873 User clicked "Expel Unit"
874 *****************************************************************/
875 static int expel_unit_callback(struct widget *pWidget)
877 if (Main.event.button.button == SDL_BUTTON_LEFT) {
878 int actor_id = MAX_ID - pWidget->ID;
879 int target_id = pWidget->data.unit->id;
881 popdown_diplomat_dialog();
882 request_do_action(ACTION_EXPEL_UNIT,
883 actor_id, target_id, 0, "");
886 return -1;
889 /****************************************************************
890 User clicked "Bombard"
891 *****************************************************************/
892 static int bombard_callback(struct widget *pWidget)
894 if (Main.event.button.button == SDL_BUTTON_LEFT) {
895 int actor_id = MAX_ID - pWidget->ID;
896 int target_id = tile_index(pWidget->data.tile);
898 popdown_diplomat_dialog();
899 request_do_action(ACTION_BOMBARD,
900 actor_id, target_id, 0, "");
903 return -1;
906 /****************************************************************
907 User clicked "Join City"
908 *****************************************************************/
909 static int join_city_callback(struct widget *pWidget)
911 if (Main.event.button.button == SDL_BUTTON_LEFT) {
912 if (NULL != game_city_by_number(
913 pDiplomat_Dlg->target_ids[ATK_CITY])
914 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
915 request_do_action(ACTION_JOIN_CITY,
916 pDiplomat_Dlg->actor_unit_id,
917 pDiplomat_Dlg->target_ids[ATK_CITY],
918 0, "");
921 popdown_diplomat_dialog();
924 return -1;
927 /****************************************************************
928 User clicked "Found City"
929 *****************************************************************/
930 static int found_city_callback(struct widget *pWidget)
932 if (Main.event.button.button == SDL_BUTTON_LEFT) {
933 int actor_id = MAX_ID - pWidget->ID;
935 popdown_diplomat_dialog();
936 dsend_packet_city_name_suggestion_req(&client.conn,
937 actor_id);
940 return -1;
943 /****************************************************************
944 User clicked "Explode Nuclear"
945 *****************************************************************/
946 static int nuke_callback(struct widget *pWidget)
948 if (Main.event.button.button == SDL_BUTTON_LEFT) {
949 int actor_id = MAX_ID - pWidget->ID;
950 int target_id = pWidget->data.tile->index;
952 popdown_diplomat_dialog();
953 request_do_action(ACTION_NUKE,
954 actor_id, target_id, 0, "");
957 return -1;
960 /****************************************************************
961 User clicked "Attack"
962 *****************************************************************/
963 static int attack_callback(struct widget *pWidget)
965 if (Main.event.button.button == SDL_BUTTON_LEFT) {
966 int actor_id = MAX_ID - pWidget->ID;
967 int target_id = pWidget->data.tile->index;
969 popdown_diplomat_dialog();
970 request_do_action(ACTION_ATTACK,
971 actor_id, target_id, 0, "");
974 return -1;
977 /****************************************************************
978 User clicked "Paradrop Unit"
979 *****************************************************************/
980 static int paradrop_callback(struct widget *pWidget)
982 if (Main.event.button.button == SDL_BUTTON_LEFT) {
983 int actor_id = MAX_ID - pWidget->ID;
984 int target_id = pWidget->data.tile->index;
986 popdown_diplomat_dialog();
987 request_do_action(ACTION_PARADROP,
988 actor_id, target_id, 0, "");
991 return -1;
994 /****************************************************************
995 User clicked "Disband Unit"
996 *****************************************************************/
997 static int disband_unit_callback(struct widget *pWidget)
999 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1000 int actor_id = MAX_ID - pWidget->ID;
1001 int target_id = pWidget->data.unit->id;
1003 popdown_diplomat_dialog();
1004 request_do_action(ACTION_DISBAND_UNIT,
1005 actor_id, target_id, 0, "");
1008 return -1;
1011 /****************************************************************
1012 User clicked "Set Home City"
1013 *****************************************************************/
1014 static int home_city_callback(struct widget *pWidget)
1016 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1017 if (NULL != game_city_by_number(
1018 pDiplomat_Dlg->target_ids[ATK_CITY])
1019 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
1020 request_do_action(ACTION_HOME_CITY,
1021 pDiplomat_Dlg->actor_unit_id,
1022 pDiplomat_Dlg->target_ids[ATK_CITY],
1023 0, "");
1026 popdown_diplomat_dialog();
1029 return -1;
1032 /****************************************************************
1033 User clicked "Upgrade Unit"
1034 *****************************************************************/
1035 static int upgrade_callback(struct widget *pWidget)
1037 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1038 struct unit *punit;
1039 struct city *pcity;
1041 if ((pcity = game_city_by_number(pDiplomat_Dlg->target_ids[ATK_CITY]))
1042 && (punit = game_unit_by_number(pDiplomat_Dlg->actor_unit_id))) {
1043 popup_unit_upgrade_dlg(punit, pcity);
1046 popdown_diplomat_dialog();
1049 return -1;
1052 /****************************************************************
1053 User clicked "Airlift Unit"
1054 *****************************************************************/
1055 static int airlift_callback(struct widget *pWidget)
1057 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1058 if (NULL != game_city_by_number(
1059 pDiplomat_Dlg->target_ids[ATK_CITY])
1060 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
1061 request_do_action(ACTION_AIRLIFT,
1062 pDiplomat_Dlg->actor_unit_id,
1063 pDiplomat_Dlg->target_ids[ATK_CITY],
1064 0, "");
1067 popdown_diplomat_dialog();
1070 return -1;
1073 /****************************************************************
1074 User clicked "Conquer City"
1075 *****************************************************************/
1076 static int conquer_city_callback(struct widget *pWidget)
1078 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1079 if (NULL != game_city_by_number(
1080 pDiplomat_Dlg->target_ids[ATK_CITY])
1081 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
1082 request_do_action(ACTION_CONQUER_CITY,
1083 pDiplomat_Dlg->actor_unit_id,
1084 pDiplomat_Dlg->target_ids[ATK_CITY],
1085 0, "");
1088 popdown_diplomat_dialog();
1091 return -1;
1094 /****************************************************************
1095 Close diplomat dialog.
1096 *****************************************************************/
1097 static int diplomat_close_callback(struct widget *pWidget)
1099 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1100 popdown_diplomat_dialog();
1103 return -1;
1106 /**************************************************************************
1107 Popdown a dialog giving a diplomatic unit some options when moving into
1108 the target tile.
1109 **************************************************************************/
1110 void popdown_diplomat_dialog(void)
1112 if (pDiplomat_Dlg) {
1113 act_sel_done_primary(pDiplomat_Dlg->actor_unit_id);
1115 is_unit_move_blocked = FALSE;
1116 popdown_window_group_dialog(pDiplomat_Dlg->pdialog->pBeginWidgetList,
1117 pDiplomat_Dlg->pdialog->pEndWidgetList);
1118 FC_FREE(pDiplomat_Dlg->pdialog->pScroll);
1119 FC_FREE(pDiplomat_Dlg->pdialog);
1120 FC_FREE(pDiplomat_Dlg);
1121 queue_flush();
1125 /* Mapping from an action to the function to call when its button is
1126 * pushed. */
1127 static const act_func af_map[ACTION_COUNT] = {
1128 /* Unit acting against a city target. */
1129 [ACTION_ESTABLISH_EMBASSY] = diplomat_embassy_callback,
1130 [ACTION_SPY_INVESTIGATE_CITY] = diplomat_investigate_callback,
1131 [ACTION_SPY_POISON] = spy_poison_callback,
1132 [ACTION_SPY_STEAL_GOLD] = spy_steal_gold_callback,
1133 [ACTION_STEAL_MAPS] = spy_steal_maps_callback,
1134 [ACTION_SPY_SABOTAGE_CITY] = diplomat_sabotage_callback,
1135 [ACTION_SPY_TARGETED_SABOTAGE_CITY] = spy_sabotage_request,
1136 [ACTION_SPY_STEAL_TECH] = diplomat_steal_callback,
1137 [ACTION_SPY_TARGETED_STEAL_TECH] = spy_steal_popup,
1138 [ACTION_SPY_INCITE_CITY] = diplomat_incite_callback,
1139 [ACTION_TRADE_ROUTE] = caravan_establish_trade_callback,
1140 [ACTION_MARKETPLACE] = caravan_marketplace_callback,
1141 [ACTION_HELP_WONDER] = caravan_help_build_wonder_callback,
1142 [ACTION_JOIN_CITY] = join_city_callback,
1143 [ACTION_SPY_NUKE] = spy_nuke_city_callback,
1144 [ACTION_DESTROY_CITY] = destroy_city_callback,
1145 [ACTION_RECYCLE_UNIT] = unit_recycle_callback,
1146 [ACTION_HOME_CITY] = home_city_callback,
1147 [ACTION_UPGRADE_UNIT] = upgrade_callback,
1148 [ACTION_AIRLIFT] = airlift_callback,
1149 [ACTION_CONQUER_CITY] = conquer_city_callback,
1151 /* Unit acting against a unit target. */
1152 [ACTION_SPY_BRIBE_UNIT] = diplomat_bribe_callback,
1153 [ACTION_SPY_SABOTAGE_UNIT] = spy_sabotage_unit_callback,
1154 [ACTION_HEAL_UNIT] = heal_unit_callback,
1155 [ACTION_EXPEL_UNIT] = expel_unit_callback,
1157 /* Unit acting against all units at a tile. */
1158 [ACTION_CAPTURE_UNITS] = capture_units_callback,
1159 [ACTION_BOMBARD] = bombard_callback,
1161 /* Unit acting against a tile. */
1162 [ACTION_FOUND_CITY] = found_city_callback,
1163 [ACTION_NUKE] = nuke_callback,
1164 [ACTION_PARADROP] = paradrop_callback,
1165 [ACTION_ATTACK] = attack_callback,
1167 /* Unit acting with no target except itself. */
1168 [ACTION_DISBAND_UNIT] = disband_unit_callback,
1171 /**************************************************************************
1172 Add an entry for an action in the action choice dialog.
1173 **************************************************************************/
1174 static void action_entry(const enum gen_action act,
1175 const struct act_prob *act_probs,
1176 const char *custom,
1177 struct unit *act_unit,
1178 struct tile *tgt_tile,
1179 struct city *tgt_city,
1180 struct unit *tgt_unit,
1181 struct widget *pWindow,
1182 SDL_Rect *area)
1184 struct widget *pBuf;
1185 utf8_str *pstr;
1186 const char *ui_name;
1188 if (act == ACTION_SPY_SABOTAGE_CITY
1189 && action_prob_possible(
1190 act_probs[ACTION_SPY_TARGETED_SABOTAGE_CITY])) {
1191 /* The player can select Sabotage City from the target selection dialog
1192 * of Targeted Sabotage City. */
1193 return;
1196 if (act == ACTION_SPY_STEAL_TECH
1197 && action_prob_possible(
1198 act_probs[ACTION_SPY_TARGETED_STEAL_TECH])) {
1199 /* The player can select Steal Tech from the target selection dialog of
1200 * Targeted Steal Tech. */
1201 return;
1204 if (af_map[act] == NULL) {
1205 /* This client doesn't support ordering this action from the
1206 * action selection dialog. */
1207 return;
1210 /* Don't show disabled actions */
1211 if (!action_prob_possible(act_probs[act])) {
1212 return;
1215 ui_name = action_prepare_ui_name(act, "",
1216 act_probs[act], custom);
1218 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1219 ui_name, af_map[act]);
1221 switch(action_id_get_target_kind(act)) {
1222 case ATK_CITY:
1223 pBuf->data.city = tgt_city;
1224 break;
1225 case ATK_UNIT:
1226 pBuf->data.unit = tgt_unit;
1227 break;
1228 case ATK_TILE:
1229 case ATK_UNITS:
1230 pBuf->data.tile = tgt_tile;
1231 break;
1232 case ATK_SELF:
1233 pBuf->data.unit = act_unit;
1234 break;
1235 case ATK_COUNT:
1236 fc_assert_msg(FALSE, "Unsupported target kind");
1239 set_wstate(pBuf, FC_WS_NORMAL);
1241 add_to_gui_list(MAX_ID - act_unit->id, pBuf);
1243 area->w = MAX(area->w, pBuf->size.w);
1244 area->h += pBuf->size.h;
1247 /**************************************************************************
1248 Return custom text for the specified action (given that the aciton is
1249 possible).
1250 **************************************************************************/
1251 static const char *action_custom_text(const int action_id,
1252 const struct act_prob prob,
1253 const struct city *actor_homecity,
1254 const struct city *target_city)
1256 static struct astring custom = ASTRING_INIT;
1258 if (!action_prob_possible(prob)) {
1259 /* No info since impossible. */
1260 return NULL;
1263 switch (action_id) {
1264 case ACTION_TRADE_ROUTE:
1266 int revenue = get_caravan_enter_city_trade_bonus(actor_homecity,
1267 target_city,
1268 TRUE);
1270 astr_set(&custom,
1271 /* TRANS: Estimated one time bonus and recurring revenue for
1272 * the Establish Trade _Route action. */
1273 _("%d one time bonus + %d trade"),
1274 revenue,
1275 trade_base_between_cities(actor_homecity, target_city));
1276 break;
1278 case ACTION_MARKETPLACE:
1280 int revenue = get_caravan_enter_city_trade_bonus(actor_homecity,
1281 target_city,
1282 FALSE);
1284 astr_set(&custom,
1285 /* TRANS: Estimated one time bonus for the Enter Marketplace
1286 * action. */
1287 _("%d one time bonus"), revenue);
1288 break;
1290 default:
1291 /* No info to add. */
1292 return NULL;
1295 return astr_str(&custom);
1298 /**************************************************************************
1299 Popup a dialog that allows the player to select what action a unit
1300 should take.
1301 **************************************************************************/
1302 void popup_action_selection(struct unit *actor_unit,
1303 struct city *target_city,
1304 struct unit *target_unit,
1305 struct tile *target_tile,
1306 const struct act_prob *act_probs)
1308 struct widget *pWindow = NULL, *pBuf = NULL;
1309 utf8_str *pstr;
1310 SDL_Rect area;
1311 struct city *actor_homecity;
1313 fc_assert_ret_msg(!pDiplomat_Dlg, "Diplomat dialog already open");
1315 /* Could be caused by the server failing to reply to a request for more
1316 * information or a bug in the client code. */
1317 fc_assert_msg(!is_more_user_input_needed,
1318 "Diplomat queue problem. Is another diplomat window open?");
1320 /* No extra input is required as no action has been chosen yet. */
1321 is_more_user_input_needed = FALSE;
1323 is_unit_move_blocked = TRUE;
1325 actor_homecity = game_city_by_number(actor_unit->homecity);
1327 pDiplomat_Dlg = fc_calloc(1, sizeof(struct diplomat_dialog));
1328 pDiplomat_Dlg->actor_unit_id = actor_unit->id;
1329 pDiplomat_Dlg->pdialog = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1331 /* window */
1332 if (target_city) {
1333 struct astring title = ASTRING_INIT;
1335 /* TRANS: %s is a unit name, e.g., Spy */
1336 astr_set(&title, _("Choose Your %s's Strategy"),
1337 unit_name_translation(actor_unit));
1338 pstr = create_utf8_from_char(astr_str(&title), adj_font(12));
1339 astr_free(&title);
1340 } else {
1341 pstr = create_utf8_from_char(_("Subvert Enemy Unit"), adj_font(12));
1344 pstr->style |= TTF_STYLE_BOLD;
1346 pWindow = create_window_skeleton(NULL, pstr, 0);
1348 pWindow->action = diplomat_dlg_window_callback;
1349 set_wstate(pWindow, FC_WS_NORMAL);
1351 add_to_gui_list(ID_CARAVAN_DLG_WINDOW, pWindow);
1352 pDiplomat_Dlg->pdialog->pEndWidgetList = pWindow;
1354 area = pWindow->area;
1355 area.w = MAX(area.w, adj_size(8));
1356 area.h = MAX(area.h, adj_size(2));
1358 if (target_city) {
1359 pDiplomat_Dlg->target_ids[ATK_CITY] = target_city->id;
1360 } else {
1361 pDiplomat_Dlg->target_ids[ATK_CITY] = IDENTITY_NUMBER_ZERO;
1364 if (target_unit) {
1365 pDiplomat_Dlg->target_ids[ATK_UNIT] = target_unit->id;
1366 } else {
1367 pDiplomat_Dlg->target_ids[ATK_UNIT] = IDENTITY_NUMBER_ZERO;
1370 pDiplomat_Dlg->target_ids[ATK_TILE] = tile_index(target_tile);
1372 pDiplomat_Dlg->target_ids[ATK_SELF] = actor_unit->id;
1374 /* ---------- */
1375 /* Unit acting against a city */
1377 action_iterate(act) {
1378 if (action_id_get_actor_kind(act) == AAK_UNIT
1379 && action_id_get_target_kind(act) == ATK_CITY) {
1380 action_entry(act, act_probs,
1381 action_custom_text(act, act_probs[act],
1382 actor_homecity, target_city),
1383 actor_unit, NULL, target_city, NULL,
1384 pWindow, &area);
1386 } action_iterate_end;
1388 /* Unit acting against another unit */
1390 action_iterate(act) {
1391 if (action_id_get_actor_kind(act) == AAK_UNIT
1392 && action_id_get_target_kind(act) == ATK_UNIT) {
1393 action_entry(act, act_probs,
1394 NULL,
1395 actor_unit, NULL, NULL, target_unit,
1396 pWindow, &area);
1398 } action_iterate_end;
1400 /* Unit acting against all units at a tile */
1402 action_iterate(act) {
1403 if (action_id_get_actor_kind(act) == AAK_UNIT
1404 && action_id_get_target_kind(act) == ATK_UNITS) {
1405 action_entry(act, act_probs,
1406 NULL,
1407 actor_unit, target_tile, NULL, NULL,
1408 pWindow, &area);
1410 } action_iterate_end;
1412 /* Unit acting against a tile. */
1414 action_iterate(act) {
1415 if (action_id_get_actor_kind(act) == AAK_UNIT
1416 && action_id_get_target_kind(act) == ATK_TILE) {
1417 action_entry(act, act_probs,
1418 NULL,
1419 actor_unit, target_tile, NULL, NULL,
1420 pWindow, &area);
1422 } action_iterate_end;
1424 /* Unit acting against itself. */
1426 action_iterate(act) {
1427 if (action_id_get_actor_kind(act) == AAK_UNIT
1428 && action_id_get_target_kind(act) == ATK_SELF) {
1429 action_entry(act, act_probs,
1430 NULL,
1431 actor_unit, NULL, NULL, target_unit,
1432 pWindow, &area);
1434 } action_iterate_end;
1436 /* ---------- */
1437 if (unit_can_move_to_tile(actor_unit, target_tile, FALSE, FALSE)) {
1438 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1439 _("Keep moving"),
1440 act_sel_keep_moving_callback);
1442 pBuf->data.tile = target_tile;
1444 set_wstate(pBuf, FC_WS_NORMAL);
1446 add_to_gui_list(MAX_ID - actor_unit->id, pBuf);
1448 area.w = MAX(area.w, pBuf->size.w);
1449 area.h += pBuf->size.h;
1452 /* ---------- */
1453 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1454 _("Wait"), act_sel_wait_callback);
1456 pBuf->data.tile = target_tile;
1458 set_wstate(pBuf, FC_WS_NORMAL);
1460 add_to_gui_list(MAX_ID - actor_unit->id, pBuf);
1462 area.w = MAX(area.w, pBuf->size.w);
1463 area.h += pBuf->size.h;
1465 /* ---------- */
1466 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1467 _("Cancel"), diplomat_close_callback);
1469 set_wstate(pBuf , FC_WS_NORMAL);
1470 pBuf->key = SDLK_ESCAPE;
1472 add_to_gui_list(ID_LABEL , pBuf);
1474 area.w = MAX(area.w, pBuf->size.w);
1475 area.h += pBuf->size.h;
1476 /* ---------- */
1477 pDiplomat_Dlg->pdialog->pBeginWidgetList = pBuf;
1479 /* setup window size and start position */
1481 resize_window(pWindow, NULL, NULL,
1482 (pWindow->size.w - pWindow->area.w) + area.w,
1483 (pWindow->size.h - pWindow->area.h) + area.h);
1485 area = pWindow->area;
1487 auto_center_on_focus_unit();
1488 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
1489 unit_tile(actor_unit));
1491 /* setup widget size and start position */
1493 pBuf = pWindow->prev;
1494 setup_vertical_widgets_position(1,
1495 area.x,
1496 area.y + 1, area.w, 0,
1497 pDiplomat_Dlg->pdialog->pBeginWidgetList, pBuf);
1499 /* --------------------- */
1500 /* redraw */
1501 redraw_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow, 0);
1503 widget_flush(pWindow);
1505 /* Give follow up questions access to action probabilities. */
1506 client_unit_init_act_prob_cache(actor_unit);
1507 action_iterate(act) {
1508 actor_unit->client.act_prob_cache[act] = act_probs[act];
1509 } action_iterate_end;
1512 /**************************************************************************
1513 Returns the id of the actor unit currently handled in action selection
1514 dialog when the action selection dialog is open.
1515 Returns IDENTITY_NUMBER_ZERO if no action selection dialog is open.
1516 **************************************************************************/
1517 int action_selection_actor_unit(void)
1519 if (!pDiplomat_Dlg) {
1520 return IDENTITY_NUMBER_ZERO;
1523 return pDiplomat_Dlg->actor_unit_id;
1526 /**************************************************************************
1527 Returns id of the target city of the actions currently handled in action
1528 selection dialog when the action selection dialog is open and it has a
1529 city target. Returns IDENTITY_NUMBER_ZERO if no action selection dialog
1530 is open or no city target is present in the action selection dialog.
1531 **************************************************************************/
1532 int action_selection_target_city(void)
1534 if (!pDiplomat_Dlg) {
1535 return IDENTITY_NUMBER_ZERO;
1538 return pDiplomat_Dlg->target_ids[ATK_CITY];
1541 /**************************************************************************
1542 Returns id of the target unit of the actions currently handled in action
1543 selection dialog when the action selection dialog is open and it has a
1544 unit target. Returns IDENTITY_NUMBER_ZERO if no action selection dialog
1545 is open or no unit target is present in the action selection dialog.
1546 **************************************************************************/
1547 int action_selection_target_unit(void)
1549 if (!pDiplomat_Dlg) {
1550 return IDENTITY_NUMBER_ZERO;
1553 return pDiplomat_Dlg->target_ids[ATK_UNIT];
1556 /**************************************************************************
1557 Updates the action selection dialog with new information.
1558 **************************************************************************/
1559 void action_selection_refresh(struct unit *actor_unit,
1560 struct city *target_city,
1561 struct unit *target_unit,
1562 struct tile *target_tile,
1563 const struct act_prob *act_probs)
1565 /* TODO: port me. */
1568 /****************************************************************
1569 Closes the action selection dialog
1570 ****************************************************************/
1571 void action_selection_close(void)
1573 did_not_decide = TRUE;
1574 popdown_diplomat_dialog();
1577 /* ====================================================================== */
1578 /* ============================ SABOTAGE DIALOG ========================= */
1579 /* ====================================================================== */
1581 /****************************************************************
1582 User selected what to sabotage.
1583 ****************************************************************/
1584 static int sabotage_impr_callback(struct widget *pWidget)
1586 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1587 int sabotage_improvement = MAX_ID - pWidget->ID;
1588 int diplomat_target_id = pWidget->data.cont->id0;
1589 int diplomat_id = pWidget->data.cont->id1;
1591 fc_assert(is_more_user_input_needed);
1592 popdown_diplomat_dialog();
1594 if (sabotage_improvement == 1000) {
1595 sabotage_improvement = -1;
1598 if (NULL != game_unit_by_number(diplomat_id)
1599 && NULL != game_city_by_number(diplomat_target_id)) {
1600 if (sabotage_improvement == B_LAST) {
1601 /* This is the untargeted version. */
1602 request_do_action(ACTION_SPY_SABOTAGE_CITY,
1603 diplomat_id, diplomat_target_id,
1604 sabotage_improvement + 1, "");
1605 } else {
1606 /* This is the targeted version. */
1607 request_do_action(ACTION_SPY_TARGETED_SABOTAGE_CITY,
1608 diplomat_id, diplomat_target_id,
1609 sabotage_improvement + 1, "");
1613 act_sel_done_secondary(diplomat_id);
1616 return -1;
1619 /*************************************************************************
1620 Pops-up the Spy sabotage dialog, upon return of list of
1621 available improvements requested by the above function.
1622 **************************************************************************/
1623 void popup_sabotage_dialog(struct unit *actor, struct city *pCity)
1625 struct widget *pWindow = NULL, *pBuf = NULL , *pLast = NULL;
1626 struct CONTAINER *pCont;
1627 utf8_str *pstr;
1628 SDL_Rect area, area2;
1629 int n, w = 0, h, imp_h = 0, y;
1631 fc_assert_ret_msg(!pDiplomat_Dlg, "Diplomat dialog already open");
1633 /* Should be set before sending request to the server. */
1634 fc_assert(is_more_user_input_needed);
1636 if (!actor) {
1637 act_sel_done_secondary(IDENTITY_NUMBER_ZERO);
1638 return;
1641 is_unit_move_blocked = TRUE;
1643 pDiplomat_Dlg = fc_calloc(1, sizeof(struct diplomat_dialog));
1644 pDiplomat_Dlg->actor_unit_id = actor->id;
1645 pDiplomat_Dlg->target_ids[ATK_CITY] = pCity->id;
1646 pDiplomat_Dlg->pdialog = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1648 pCont = fc_calloc(1, sizeof(struct CONTAINER));
1649 pCont->id0 = pCity->id;
1650 pCont->id1 = actor->id; /* spy id */
1652 pstr = create_utf8_from_char(_("Select Improvement to Sabotage") , adj_font(12));
1653 pstr->style |= TTF_STYLE_BOLD;
1655 pWindow = create_window_skeleton(NULL, pstr, 0);
1657 pWindow->action = diplomat_dlg_window_callback;
1658 set_wstate(pWindow, FC_WS_NORMAL);
1660 add_to_gui_list(ID_TERRAIN_ADV_DLG_WINDOW, pWindow);
1661 pDiplomat_Dlg->pdialog->pEndWidgetList = pWindow;
1663 area = pWindow->area;
1664 area.h = MAX(area.h, adj_size(2));
1666 /* ---------- */
1667 /* exit button */
1668 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1669 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1670 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1671 adj_font(12));
1672 area.w += pBuf->size.w + adj_size(10);
1673 pBuf->action = exit_spy_tgt_dlg_callback;
1674 set_wstate(pBuf, FC_WS_NORMAL);
1675 pBuf->key = SDLK_ESCAPE;
1677 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf);
1678 /* ---------- */
1680 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1681 _("City Production"), sabotage_impr_callback);
1682 pBuf->data.cont = pCont;
1683 set_wstate(pBuf, FC_WS_NORMAL);
1684 set_wflag(pBuf, WF_FREE_DATA);
1685 add_to_gui_list(MAX_ID - 1000, pBuf);
1687 area.w = MAX(area.w, pBuf->size.w);
1688 area.h += pBuf->size.h;
1690 /* separator */
1691 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1693 add_to_gui_list(ID_SEPARATOR, pBuf);
1694 area.h += pBuf->next->size.h;
1696 pDiplomat_Dlg->pdialog->pEndActiveWidgetList = pBuf;
1698 /* ------------------ */
1699 n = 0;
1700 city_built_iterate(pCity, pImprove) {
1701 if (pImprove->sabotage > 0) {
1702 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1703 (char *) city_improvement_name_translation(pCity, pImprove),
1704 sabotage_impr_callback);
1705 pBuf->data.cont = pCont;
1706 set_wstate(pBuf, FC_WS_NORMAL);
1708 add_to_gui_list(MAX_ID - improvement_number(pImprove), pBuf);
1710 area.w = MAX(area.w , pBuf->size.w);
1711 imp_h += pBuf->size.h;
1713 if (n > 9) {
1714 set_wflag(pBuf, WF_HIDDEN);
1717 n++;
1718 /* ----------- */
1720 } city_built_iterate_end;
1722 pDiplomat_Dlg->pdialog->pBeginActiveWidgetList = pBuf;
1724 if (n > 0 && action_prob_possible(
1725 actor->client.act_prob_cache[ACTION_SPY_SABOTAGE_CITY])) {
1726 /* separator */
1727 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1729 add_to_gui_list(ID_SEPARATOR, pBuf);
1730 area.h += pBuf->next->size.h;
1731 /* ------------------ */
1734 if (action_prob_possible(
1735 actor->client.act_prob_cache[ACTION_SPY_SABOTAGE_CITY])) {
1736 struct astring str = ASTRING_INIT;
1738 /* TRANS: %s is a unit name, e.g., Spy */
1739 astr_set(&str, _("At %s's Discretion"), unit_name_translation(actor));
1740 create_active_iconlabel(pBuf, pWindow->dst, pstr, astr_str(&str),
1741 sabotage_impr_callback);
1742 astr_free(&str);
1744 pBuf->data.cont = pCont;
1745 set_wstate(pBuf, FC_WS_NORMAL);
1747 add_to_gui_list(MAX_ID - B_LAST, pBuf);
1749 area.w = MAX(area.w, pBuf->size.w);
1750 area.h += pBuf->size.h;
1753 /* ----------- */
1755 pLast = pBuf;
1756 pDiplomat_Dlg->pdialog->pBeginWidgetList = pLast;
1757 pDiplomat_Dlg->pdialog->pActiveWidgetList = pDiplomat_Dlg->pdialog->pEndActiveWidgetList;
1759 /* ---------- */
1760 if (n > 10) {
1761 imp_h = 10 * pBuf->size.h;
1763 n = create_vertical_scrollbar(pDiplomat_Dlg->pdialog,
1764 1, 10, TRUE, TRUE);
1765 area.w += n;
1766 } else {
1767 n = 0;
1769 /* ---------- */
1771 area.h += imp_h;
1773 resize_window(pWindow, NULL, NULL,
1774 (pWindow->size.w - pWindow->area.w) + area.w,
1775 (pWindow->size.h - pWindow->area.h) + area.h);
1777 area = pWindow->area;
1779 auto_center_on_focus_unit();
1780 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
1781 unit_tile(actor));
1783 w = area.w;
1785 /* exit button */
1786 pBuf = pWindow->prev;
1787 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1788 pBuf->size.y = pWindow->size.y + adj_size(2);
1790 /* Production sabotage */
1791 pBuf = pBuf->prev;
1793 pBuf->size.x = area.x;
1794 pBuf->size.y = y = area.y + 1;
1795 pBuf->size.w = w;
1796 h = pBuf->size.h;
1798 area2.x = adj_size(10);
1799 area2.h = adj_size(2);
1801 pBuf = pBuf->prev;
1802 while (pBuf) {
1803 if (pBuf == pDiplomat_Dlg->pdialog->pEndActiveWidgetList) {
1804 w -= n;
1807 pBuf->size.w = w;
1808 pBuf->size.x = pBuf->next->size.x;
1809 pBuf->size.y = y = y + pBuf->next->size.h;
1811 if (pBuf->ID == ID_SEPARATOR) {
1812 FREESURFACE(pBuf->theme);
1813 pBuf->size.h = h;
1814 pBuf->theme = create_surf(w, h, SDL_SWSURFACE);
1816 area2.y = pBuf->size.h / 2 - 1;
1817 area2.w = pBuf->size.w - adj_size(20);
1819 SDL_FillRect(pBuf->theme , &area2, map_rgba(pBuf->theme->format, *get_theme_color(COLOR_THEME_SABOTAGEDLG_SEPARATOR)));
1822 if (pBuf == pLast) {
1823 break;
1826 if (pBuf == pDiplomat_Dlg->pdialog->pBeginActiveWidgetList) {
1827 /* Reset to end of scrolling area */
1828 y = MIN(y, pDiplomat_Dlg->pdialog->pEndActiveWidgetList->size.y
1829 + 9 * pBuf->size.h);
1830 w += n;
1832 pBuf = pBuf->prev;
1835 if (pDiplomat_Dlg->pdialog->pScroll) {
1836 setup_vertical_scrollbar_area(pDiplomat_Dlg->pdialog->pScroll,
1837 area.x + area.w,
1838 pDiplomat_Dlg->pdialog->pEndActiveWidgetList->size.y,
1839 pDiplomat_Dlg->pdialog->pBeginActiveWidgetList->prev->size.y
1840 - pDiplomat_Dlg->pdialog->pEndActiveWidgetList->size.y,
1841 TRUE);
1844 /* -------------------- */
1845 /* redraw */
1846 redraw_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow, 0);
1848 widget_flush(pWindow);
1851 /* ====================================================================== */
1852 /* ============================== INCITE DIALOG ========================= */
1853 /* ====================================================================== */
1854 static struct small_diplomat_dialog *pIncite_Dlg = NULL;
1856 /****************************************************************
1857 User interacted with Incite Revolt dialog window.
1858 *****************************************************************/
1859 static int incite_dlg_window_callback(struct widget *pWindow)
1861 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1862 move_window_group(pIncite_Dlg->pdialog->pBeginWidgetList, pWindow);
1865 return -1;
1868 /****************************************************************
1869 User confirmed incite
1870 *****************************************************************/
1871 static int diplomat_incite_yes_callback(struct widget *pWidget)
1873 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1874 if (NULL != game_unit_by_number(pIncite_Dlg->actor_unit_id)
1875 && NULL != game_city_by_number(pIncite_Dlg->target_id)) {
1876 request_do_action(ACTION_SPY_INCITE_CITY, pIncite_Dlg->actor_unit_id,
1877 pIncite_Dlg->target_id, 0, "");
1880 popdown_incite_dialog();
1883 return -1;
1886 /****************************************************************
1887 Close incite dialog.
1888 *****************************************************************/
1889 static int exit_incite_dlg_callback(struct widget *pWidget)
1891 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1892 popdown_incite_dialog();
1895 return -1;
1898 /**************************************************************************
1899 Popdown a window asking a diplomatic unit if it wishes to incite the
1900 given enemy city.
1901 **************************************************************************/
1902 void popdown_incite_dialog(void)
1904 if (pIncite_Dlg) {
1905 act_sel_done_secondary(pIncite_Dlg->actor_unit_id);
1907 is_unit_move_blocked = FALSE;
1908 popdown_window_group_dialog(pIncite_Dlg->pdialog->pBeginWidgetList,
1909 pIncite_Dlg->pdialog->pEndWidgetList);
1910 FC_FREE(pIncite_Dlg->pdialog);
1911 FC_FREE(pIncite_Dlg);
1912 flush_dirty();
1916 /**************************************************************************
1917 Popup a window asking a diplomatic unit if it wishes to incite the
1918 given enemy city.
1919 **************************************************************************/
1920 void popup_incite_dialog(struct unit *actor, struct city *pCity, int cost)
1922 struct widget *pWindow = NULL, *pBuf = NULL;
1923 utf8_str *pstr;
1924 char tBuf[255], cBuf[255];
1925 bool exit = FALSE;
1926 SDL_Rect area;
1928 if (pIncite_Dlg) {
1929 return;
1932 /* Should be set before sending request to the server. */
1933 fc_assert(is_more_user_input_needed);
1935 if (!actor || !unit_can_do_action(actor, ACTION_SPY_INCITE_CITY)) {
1936 act_sel_done_secondary(actor ? actor->id : IDENTITY_NUMBER_ZERO);
1937 return;
1940 is_unit_move_blocked = TRUE;
1942 pIncite_Dlg = fc_calloc(1, sizeof(struct small_diplomat_dialog));
1943 pIncite_Dlg->actor_unit_id = actor->id;
1944 pIncite_Dlg->target_id = pCity->id;
1945 pIncite_Dlg->pdialog = fc_calloc(1, sizeof(struct SMALL_DLG));
1947 fc_snprintf(tBuf, ARRAY_SIZE(tBuf), PL_("Treasury contains %d gold.",
1948 "Treasury contains %d gold.",
1949 client_player()->economic.gold),
1950 client_player()->economic.gold);
1952 /* window */
1953 pstr = create_utf8_from_char(_("Incite a Revolt!"), adj_font(12));
1955 pstr->style |= TTF_STYLE_BOLD;
1957 pWindow = create_window_skeleton(NULL, pstr, 0);
1959 pWindow->action = incite_dlg_window_callback;
1960 set_wstate(pWindow, FC_WS_NORMAL);
1962 add_to_gui_list(ID_INCITE_DLG_WINDOW, pWindow);
1963 pIncite_Dlg->pdialog->pEndWidgetList = pWindow;
1965 area = pWindow->area;
1966 area.w =MAX(area.w, adj_size(8));
1967 area.h = MAX(area.h, adj_size(2));
1969 if (INCITE_IMPOSSIBLE_COST == cost) {
1970 /* exit button */
1971 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1972 WF_WIDGET_HAS_INFO_LABEL
1973 | WF_RESTORE_BACKGROUND);
1974 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1975 adj_font(12));
1976 area.w += pBuf->size.w + adj_size(10);
1977 pBuf->action = exit_incite_dlg_callback;
1978 set_wstate(pBuf, FC_WS_NORMAL);
1979 pBuf->key = SDLK_ESCAPE;
1981 add_to_gui_list(ID_INCITE_DLG_EXIT_BUTTON, pBuf);
1982 exit = TRUE;
1983 /* --------------- */
1985 fc_snprintf(cBuf, sizeof(cBuf), _("You can't incite a revolt in %s."),
1986 city_name_get(pCity));
1988 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
1990 add_to_gui_list(ID_LABEL , pBuf);
1992 area.w = MAX(area.w , pBuf->size.w);
1993 area.h += pBuf->size.h;
1994 /*------------*/
1995 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1996 _("City can't be incited!"), NULL);
1998 add_to_gui_list(ID_LABEL, pBuf);
2000 area.w = MAX(area.w, pBuf->size.w);
2001 area.h += pBuf->size.h;
2003 } else if (cost <= client_player()->economic.gold) {
2004 fc_snprintf(cBuf, sizeof(cBuf),
2005 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
2006 PL_("Incite a revolt for %d gold?\n%s",
2007 "Incite a revolt for %d gold?\n%s", cost), cost, tBuf);
2009 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
2011 add_to_gui_list(ID_LABEL, pBuf);
2013 area.w = MAX(area.w, pBuf->size.w);
2014 area.h += pBuf->size.h;
2016 /*------------*/
2017 create_active_iconlabel(pBuf, pWindow->dst, pstr,
2018 _("Yes") , diplomat_incite_yes_callback);
2020 pBuf->data.city = pCity;
2021 set_wstate(pBuf, FC_WS_NORMAL);
2023 add_to_gui_list(MAX_ID - actor->id, pBuf);
2025 area.w = MAX(area.w, pBuf->size.w);
2026 area.h += pBuf->size.h;
2027 /* ------- */
2028 create_active_iconlabel(pBuf, pWindow->dst, pstr,
2029 _("No") , exit_incite_dlg_callback);
2031 set_wstate(pBuf, FC_WS_NORMAL);
2032 pBuf->key = SDLK_ESCAPE;
2034 add_to_gui_list(ID_LABEL, pBuf);
2036 area.w = MAX(area.w, pBuf->size.w);
2037 area.h += pBuf->size.h;
2039 } else {
2040 /* exit button */
2041 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
2042 WF_WIDGET_HAS_INFO_LABEL
2043 | WF_RESTORE_BACKGROUND);
2044 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
2045 adj_font(12));
2046 area.w += pBuf->size.w + adj_size(10);
2047 pBuf->action = exit_incite_dlg_callback;
2048 set_wstate(pBuf, FC_WS_NORMAL);
2049 pBuf->key = SDLK_ESCAPE;
2051 add_to_gui_list(ID_INCITE_DLG_EXIT_BUTTON, pBuf);
2052 exit = TRUE;
2053 /* --------------- */
2055 fc_snprintf(cBuf, sizeof(cBuf),
2056 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
2057 PL_("Inciting a revolt costs %d gold.\n%s",
2058 "Inciting a revolt costs %d gold.\n%s", cost), cost, tBuf);
2060 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
2062 add_to_gui_list(ID_LABEL, pBuf);
2064 area.w = MAX(area.w, pBuf->size.w);
2065 area.h += pBuf->size.h;
2067 /*------------*/
2068 create_active_iconlabel(pBuf, pWindow->dst, pstr,
2069 _("Traitors Demand Too Much!"), NULL);
2071 add_to_gui_list(ID_LABEL, pBuf);
2073 area.w = MAX(area.w, pBuf->size.w);
2074 area.h += pBuf->size.h;
2076 pIncite_Dlg->pdialog->pBeginWidgetList = pBuf;
2078 /* setup window size and start position */
2080 resize_window(pWindow, NULL, NULL,
2081 (pWindow->size.w - pWindow->area.w) + area.w,
2082 (pWindow->size.h - pWindow->area.h) + area.h);
2084 area = pWindow->area;
2086 auto_center_on_focus_unit();
2087 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
2088 pCity->tile);
2090 /* setup widget size and start position */
2091 pBuf = pWindow;
2093 if (exit) {
2094 /* exit button */
2095 pBuf = pBuf->prev;
2096 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2097 pBuf->size.y = pWindow->size.y + adj_size(2);
2100 pBuf = pBuf->prev;
2101 setup_vertical_widgets_position(1,
2102 area.x,
2103 area.y + 1, area.w, 0,
2104 pIncite_Dlg->pdialog->pBeginWidgetList, pBuf);
2106 /* --------------------- */
2107 /* redraw */
2108 redraw_group(pIncite_Dlg->pdialog->pBeginWidgetList, pWindow, 0);
2110 widget_flush(pWindow);
2113 /* ====================================================================== */
2114 /* ============================ BRIBE DIALOG ========================== */
2115 /* ====================================================================== */
2116 static struct small_diplomat_dialog *pBribe_Dlg = NULL;
2118 /**************************************************************************
2119 User interacted with bribe dialog window.
2120 **************************************************************************/
2121 static int bribe_dlg_window_callback(struct widget *pWindow)
2123 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2124 move_window_group(pBribe_Dlg->pdialog->pBeginWidgetList, pWindow);
2127 return -1;
2130 /**************************************************************************
2131 User confirmed bribe.
2132 **************************************************************************/
2133 static int diplomat_bribe_yes_callback(struct widget *pWidget)
2135 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2136 if (NULL != game_unit_by_number(pBribe_Dlg->actor_unit_id)
2137 && NULL != game_unit_by_number(pBribe_Dlg->target_id)) {
2138 request_do_action(ACTION_SPY_BRIBE_UNIT, pBribe_Dlg->actor_unit_id,
2139 pBribe_Dlg->target_id, 0, "");
2141 popdown_bribe_dialog();
2144 return -1;
2147 /**************************************************************************
2148 Close bribe dialog.
2149 **************************************************************************/
2150 static int exit_bribe_dlg_callback(struct widget *pWidget)
2152 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2153 popdown_bribe_dialog();
2156 return -1;
2159 /**************************************************************************
2160 Popdown a dialog asking a diplomatic unit if it wishes to bribe the
2161 given enemy unit.
2162 **************************************************************************/
2163 void popdown_bribe_dialog(void)
2165 if (pBribe_Dlg) {
2166 act_sel_done_secondary(pBribe_Dlg->actor_unit_id);
2168 is_unit_move_blocked = FALSE;
2169 popdown_window_group_dialog(pBribe_Dlg->pdialog->pBeginWidgetList,
2170 pBribe_Dlg->pdialog->pEndWidgetList);
2171 FC_FREE(pBribe_Dlg->pdialog);
2172 FC_FREE(pBribe_Dlg);
2173 flush_dirty();
2177 /**************************************************************************
2178 Popup a dialog asking a diplomatic unit if it wishes to bribe the
2179 given enemy unit.
2180 **************************************************************************/
2181 void popup_bribe_dialog(struct unit *actor, struct unit *pUnit, int cost)
2183 struct widget *pWindow = NULL, *pBuf = NULL;
2184 utf8_str *pstr;
2185 char tBuf[255], cBuf[255];
2186 bool exit = FALSE;
2187 SDL_Rect area;
2189 if (pBribe_Dlg) {
2190 return;
2193 /* Should be set before sending request to the server. */
2194 fc_assert(is_more_user_input_needed);
2196 if (!actor || !unit_can_do_action(actor, ACTION_SPY_BRIBE_UNIT)) {
2197 act_sel_done_secondary(actor ? actor->id : IDENTITY_NUMBER_ZERO);
2198 return;
2201 is_unit_move_blocked = TRUE;
2203 pBribe_Dlg = fc_calloc(1, sizeof(struct small_diplomat_dialog));
2204 pBribe_Dlg->actor_unit_id = actor->id;
2205 pBribe_Dlg->target_id = pUnit->id;
2206 pBribe_Dlg->pdialog = fc_calloc(1, sizeof(struct SMALL_DLG));
2208 fc_snprintf(tBuf, ARRAY_SIZE(tBuf), PL_("Treasury contains %d gold.",
2209 "Treasury contains %d gold.",
2210 client_player()->economic.gold),
2211 client_player()->economic.gold);
2213 /* window */
2214 pstr = create_utf8_from_char(_("Bribe Enemy Unit"), adj_font(12));
2216 pstr->style |= TTF_STYLE_BOLD;
2218 pWindow = create_window_skeleton(NULL, pstr, 0);
2220 pWindow->action = bribe_dlg_window_callback;
2221 set_wstate(pWindow, FC_WS_NORMAL);
2223 add_to_gui_list(ID_BRIBE_DLG_WINDOW, pWindow);
2224 pBribe_Dlg->pdialog->pEndWidgetList = pWindow;
2226 area = pWindow->area;
2227 area.w = MAX(area.w, adj_size(8));
2228 area.h = MAX(area.h, adj_size(2));
2230 if (cost <= client_player()->economic.gold) {
2231 fc_snprintf(cBuf, sizeof(cBuf),
2232 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
2233 PL_("Bribe unit for %d gold?\n%s",
2234 "Bribe unit for %d gold?\n%s", cost), cost, tBuf);
2236 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
2238 add_to_gui_list(ID_LABEL, pBuf);
2240 area.w = MAX(area.w, pBuf->size.w);
2241 area.h += pBuf->size.h;
2243 /*------------*/
2244 create_active_iconlabel(pBuf, pWindow->dst, pstr,
2245 _("Yes"), diplomat_bribe_yes_callback);
2246 pBuf->data.unit = pUnit;
2247 set_wstate(pBuf, FC_WS_NORMAL);
2249 add_to_gui_list(MAX_ID - actor->id, pBuf);
2251 area.w = MAX(area.w, pBuf->size.w);
2252 area.h += pBuf->size.h;
2253 /* ------- */
2254 create_active_iconlabel(pBuf, pWindow->dst, pstr,
2255 _("No") , exit_bribe_dlg_callback);
2257 set_wstate(pBuf, FC_WS_NORMAL);
2258 pBuf->key = SDLK_ESCAPE;
2260 add_to_gui_list(ID_LABEL, pBuf);
2262 area.w = MAX(area.w, pBuf->size.w);
2263 area.h += pBuf->size.h;
2265 } else {
2266 /* exit button */
2267 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
2268 WF_WIDGET_HAS_INFO_LABEL
2269 | WF_RESTORE_BACKGROUND);
2270 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
2271 adj_font(12));
2272 area.w += pBuf->size.w + adj_size(10);
2273 pBuf->action = exit_bribe_dlg_callback;
2274 set_wstate(pBuf, FC_WS_NORMAL);
2275 pBuf->key = SDLK_ESCAPE;
2277 add_to_gui_list(ID_BRIBE_DLG_EXIT_BUTTON, pBuf);
2278 exit = TRUE;
2279 /* --------------- */
2281 fc_snprintf(cBuf, sizeof(cBuf),
2282 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
2283 PL_("Bribing the unit costs %d gold.\n%s",
2284 "Bribing the unit costs %d gold.\n%s", cost), cost, tBuf);
2286 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
2288 add_to_gui_list(ID_LABEL, pBuf);
2290 area.w = MAX(area.w, pBuf->size.w);
2291 area.h += pBuf->size.h;
2293 /*------------*/
2294 create_active_iconlabel(pBuf, pWindow->dst, pstr,
2295 _("Traitors Demand Too Much!"), NULL);
2297 add_to_gui_list(ID_LABEL, pBuf);
2299 area.w = MAX(area.w, pBuf->size.w);
2300 area.h += pBuf->size.h;
2302 pBribe_Dlg->pdialog->pBeginWidgetList = pBuf;
2304 /* setup window size and start position */
2306 resize_window(pWindow, NULL, NULL,
2307 (pWindow->size.w - pWindow->area.w) + area.w,
2308 (pWindow->size.h - pWindow->area.h) + area.h);
2310 area = pWindow->area;
2312 auto_center_on_focus_unit();
2313 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
2314 unit_tile(actor));
2316 /* setup widget size and start position */
2317 pBuf = pWindow;
2319 if (exit) {
2320 /* exit button */
2321 pBuf = pBuf->prev;
2322 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2323 pBuf->size.y = pWindow->size.y + adj_size(2);
2326 pBuf = pBuf->prev;
2327 setup_vertical_widgets_position(1,
2328 area.x,
2329 area.y + 1, area.w, 0,
2330 pBribe_Dlg->pdialog->pBeginWidgetList, pBuf);
2332 /* --------------------- */
2333 /* redraw */
2334 redraw_group(pBribe_Dlg->pdialog->pBeginWidgetList, pWindow, 0);
2336 widget_flush(pWindow);