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)
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 ***********************************************************************/
15 #include <fc_config.h>
28 #include "traderoutes.h"
32 #include "client_main.h"
42 #include "gui_tilespec.h"
45 #include "themespec.h"
48 #include "dialogs_g.h"
50 typedef int (*act_func
)(struct widget
*);
52 struct diplomat_dialog
{
54 int target_ids
[ATK_COUNT
];
55 struct ADVANCED_DLG
*pdialog
;
58 struct small_diplomat_dialog
{
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
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
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
;
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
)
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
],
143 popdown_diplomat_dialog();
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
],
164 popdown_diplomat_dialog();
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
],
185 popdown_diplomat_dialog();
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
],
206 popdown_diplomat_dialog();
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
);
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
],
243 popdown_diplomat_dialog();
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
],
264 /* FIXME: Wait for the city display in stead? */
265 popdown_diplomat_dialog();
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
],
285 popdown_diplomat_dialog();
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
],
305 popdown_diplomat_dialog();
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
],
325 popdown_diplomat_dialog();
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
],
346 popdown_diplomat_dialog();
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
],
367 popdown_diplomat_dialog();
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();
388 popdown_diplomat_dialog();
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
],
409 popdown_diplomat_dialog();
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
);
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
);
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
],
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
],
472 fc_assert(is_more_user_input_needed
);
473 popdown_diplomat_dialog();
474 act_sel_done_secondary(actor_id
);
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
;
494 int max_col
, max_row
, col
, count
= 0;
498 struct unit
*actor_unit
= game_unit_by_number(id
);
500 is_more_user_input_needed
= TRUE
;
501 popdown_diplomat_dialog();
504 pVictim
= city_owner(pVcity
);
507 fc_assert_ret_val_msg(!pDiplomat_Dlg
, 1, "Diplomat dialog already open");
510 act_sel_done_secondary(id
);
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
)) {
524 } advance_index_iterate_end
;
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
);
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 /* ------------------ */
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)"),
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 */
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
) {
592 if (count
< max_col
+ 1) {
595 if (count
< max_col
+ adj_size(3)) {
596 col
= max_col
- adj_size(2);
598 if (count
< max_col
+ adj_size(5)) {
606 pstr
= create_utf8_str(NULL
, 0, adj_font(10));
607 pstr
->style
|= (TTF_STYLE_BOLD
| SF_CENTER
);
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
)) {
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
));
648 pSurf
= create_select_tech_icon(pstr
, tech
, FULL_MODE
);
650 pBuf
= create_icon2(pSurf
, pWindow
->dst
,
651 (WF_FREE_THEME
| WF_RESTORE_BACKGROUND
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
);
661 /* --------------------------------------------------------- */
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 /* -------------------------------------------------------------- */
671 count
= (count
+ (col
- 1)) / col
;
672 if (count
> max_row
) {
673 pDiplomat_Dlg
->pdialog
->pActiveWidgetList
= pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
;
675 idx
= create_vertical_scrollbar(pDiplomat_Dlg
->pdialog
, col
, count
, TRUE
, TRUE
);
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
)) {
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);
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,
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
,
714 redraw_group(pDiplomat_Dlg
->pdialog
->pBeginWidgetList
, pWindow
, FALSE
);
715 widget_mark_dirty(pWindow
);
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
],
735 popdown_diplomat_dialog();
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();
756 popdown_diplomat_dialog();
763 /********************************************************************
764 Callback from action selection dialog for "keep moving".
765 (This should only occur when entering a tile with an allied city
767 *********************************************************************/
768 static int act_sel_keep_moving_callback(struct widget
*pWidget
)
770 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
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();
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
) {
792 /* The dialog was popped down when key_unit_wait() resulted in
793 * action_selection_close() being called. */
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
)
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();
814 popdown_diplomat_dialog();
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, "");
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, "");
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, "");
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, "");
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, "");
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
],
921 popdown_diplomat_dialog();
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
,
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, "");
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, "");
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, "");
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, "");
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
],
1026 popdown_diplomat_dialog();
1032 /****************************************************************
1033 User clicked "Upgrade Unit"
1034 *****************************************************************/
1035 static int upgrade_callback(struct widget
*pWidget
)
1037 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
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();
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
],
1067 popdown_diplomat_dialog();
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
],
1088 popdown_diplomat_dialog();
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();
1106 /**************************************************************************
1107 Popdown a dialog giving a diplomatic unit some options when moving into
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
);
1125 /* Mapping from an action to the function to call when its button is
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
,
1177 struct unit
*act_unit
,
1178 struct tile
*tgt_tile
,
1179 struct city
*tgt_city
,
1180 struct unit
*tgt_unit
,
1181 struct widget
*pWindow
,
1184 struct widget
*pBuf
;
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. */
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. */
1204 if (af_map
[act
] == NULL
) {
1205 /* This client doesn't support ordering this action from the
1206 * action selection dialog. */
1210 /* Don't show disabled actions */
1211 if (!action_prob_possible(act_probs
[act
])) {
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
)) {
1223 pBuf
->data
.city
= tgt_city
;
1226 pBuf
->data
.unit
= tgt_unit
;
1230 pBuf
->data
.tile
= tgt_tile
;
1233 pBuf
->data
.unit
= act_unit
;
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
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. */
1263 switch (action_id
) {
1264 case ACTION_TRADE_ROUTE
:
1266 int revenue
= get_caravan_enter_city_trade_bonus(actor_homecity
,
1271 /* TRANS: Estimated one time bonus and recurring revenue for
1272 * the Establish Trade _Route action. */
1273 _("%d one time bonus + %d trade"),
1275 trade_base_between_cities(actor_homecity
, target_city
));
1278 case ACTION_MARKETPLACE
:
1280 int revenue
= get_caravan_enter_city_trade_bonus(actor_homecity
,
1285 /* TRANS: Estimated one time bonus for the Enter Marketplace
1287 _("%d one time bonus"), revenue
);
1291 /* No info to add. */
1295 return astr_str(&custom
);
1298 /**************************************************************************
1299 Popup a dialog that allows the player to select what action a unit
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
;
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
));
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));
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));
1359 pDiplomat_Dlg
->target_ids
[ATK_CITY
] = target_city
->id
;
1361 pDiplomat_Dlg
->target_ids
[ATK_CITY
] = IDENTITY_NUMBER_ZERO
;
1365 pDiplomat_Dlg
->target_ids
[ATK_UNIT
] = target_unit
->id
;
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
;
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
,
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
,
1395 actor_unit
, NULL
, NULL
, target_unit
,
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
,
1407 actor_unit
, target_tile
, NULL
, NULL
,
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
,
1419 actor_unit
, target_tile
, NULL
, NULL
,
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
,
1431 actor_unit
, NULL
, NULL
, target_unit
,
1434 } action_iterate_end
;
1437 if (unit_can_move_to_tile(actor_unit
, target_tile
, FALSE
, FALSE
)) {
1438 create_active_iconlabel(pBuf
, pWindow
->dst
, pstr
,
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
;
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
;
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
;
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,
1496 area
.y
+ 1, area
.w
, 0,
1497 pDiplomat_Dlg
->pdialog
->pBeginWidgetList
, pBuf
);
1499 /* --------------------- */
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, "");
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
);
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
;
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
);
1637 act_sel_done_secondary(IDENTITY_NUMBER_ZERO
);
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));
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)"),
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
);
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
;
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 /* ------------------ */
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
;
1714 set_wflag(pBuf
, WF_HIDDEN
);
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
])) {
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
);
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
;
1756 pDiplomat_Dlg
->pdialog
->pBeginWidgetList
= pLast
;
1757 pDiplomat_Dlg
->pdialog
->pActiveWidgetList
= pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
;
1761 imp_h
= 10 * pBuf
->size
.h
;
1763 n
= create_vertical_scrollbar(pDiplomat_Dlg
->pdialog
,
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
,
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 */
1793 pBuf
->size
.x
= area
.x
;
1794 pBuf
->size
.y
= y
= area
.y
+ 1;
1798 area2
.x
= adj_size(10);
1799 area2
.h
= adj_size(2);
1803 if (pBuf
== pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
) {
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
);
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
) {
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
);
1835 if (pDiplomat_Dlg
->pdialog
->pScroll
) {
1836 setup_vertical_scrollbar_area(pDiplomat_Dlg
->pdialog
->pScroll
,
1838 pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
->size
.y
,
1839 pDiplomat_Dlg
->pdialog
->pBeginActiveWidgetList
->prev
->size
.y
1840 - pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
->size
.y
,
1844 /* -------------------- */
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
);
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();
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();
1898 /**************************************************************************
1899 Popdown a window asking a diplomatic unit if it wishes to incite the
1901 **************************************************************************/
1902 void popdown_incite_dialog(void)
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
);
1916 /**************************************************************************
1917 Popup a window asking a diplomatic unit if it wishes to incite the
1919 **************************************************************************/
1920 void popup_incite_dialog(struct unit
*actor
, struct city
*pCity
, int cost
)
1922 struct widget
*pWindow
= NULL
, *pBuf
= NULL
;
1924 char tBuf
[255], cBuf
[255];
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
);
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
);
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
) {
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)"),
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
);
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
;
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
;
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
;
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
;
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)"),
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
);
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
;
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
,
2090 /* setup widget size and start position */
2096 pBuf
->size
.x
= area
.x
+ area
.w
- pBuf
->size
.w
- 1;
2097 pBuf
->size
.y
= pWindow
->size
.y
+ adj_size(2);
2101 setup_vertical_widgets_position(1,
2103 area
.y
+ 1, area
.w
, 0,
2104 pIncite_Dlg
->pdialog
->pBeginWidgetList
, pBuf
);
2106 /* --------------------- */
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
);
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();
2147 /**************************************************************************
2149 **************************************************************************/
2150 static int exit_bribe_dlg_callback(struct widget
*pWidget
)
2152 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
2153 popdown_bribe_dialog();
2159 /**************************************************************************
2160 Popdown a dialog asking a diplomatic unit if it wishes to bribe the
2162 **************************************************************************/
2163 void popdown_bribe_dialog(void)
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
);
2177 /**************************************************************************
2178 Popup a dialog asking a diplomatic unit if it wishes to bribe the
2180 **************************************************************************/
2181 void popup_bribe_dialog(struct unit
*actor
, struct unit
*pUnit
, int cost
)
2183 struct widget
*pWindow
= NULL
, *pBuf
= NULL
;
2185 char tBuf
[255], cBuf
[255];
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
);
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
);
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
;
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
;
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
;
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)"),
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
);
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
;
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
,
2316 /* setup widget size and start position */
2322 pBuf
->size
.x
= area
.x
+ area
.w
- pBuf
->size
.w
- 1;
2323 pBuf
->size
.y
= pWindow
->size
.y
+ adj_size(2);
2327 setup_vertical_widgets_position(1,
2329 area
.y
+ 1, area
.w
, 0,
2330 pBribe_Dlg
->pdialog
->pBeginWidgetList
, pBuf
);
2332 /* --------------------- */
2334 redraw_group(pBribe_Dlg
->pdialog
->pBeginWidgetList
, pWindow
, 0);
2336 widget_flush(pWindow
);