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);
70 static struct diplomat_dialog
*pDiplomat_Dlg
= NULL
;
71 static bool is_more_user_input_needed
= FALSE
;
72 static bool did_not_decide
= FALSE
;
74 /**************************************************************************
75 The action selection is done.
76 **************************************************************************/
77 static void act_sel_done_primary(int actor_unit_id
)
79 if (!is_more_user_input_needed
) {
80 /* The client isn't waiting for information for any unanswered follow
83 struct unit
*actor_unit
;
85 if ((actor_unit
= game_unit_by_number(actor_unit_id
))) {
86 /* The action selection dialog wasn't closed because the actor unit
89 /* The probabilities didn't just disappear, right? */
90 fc_assert_action(actor_unit
->client
.act_prob_cache
,
91 client_unit_init_act_prob_cache(actor_unit
));
93 FC_FREE(actor_unit
->client
.act_prob_cache
);
96 /* The action selection process is over, at least for now. */
97 action_selection_no_longer_in_progress(actor_unit_id
);
100 /* The action selection dialog was closed but the player didn't
101 * decide what the unit should do. */
103 /* Reset so the next action selection dialog does the right thing. */
104 did_not_decide
= FALSE
;
106 /* An action, or no action at all, was selected. */
107 action_decision_clear_want(actor_unit_id
);
108 action_selection_next_in_focus(actor_unit_id
);
113 /**************************************************************************
114 A follow up question about the selected action is done.
115 **************************************************************************/
116 static void act_sel_done_secondary(int actor_unit_id
)
119 is_more_user_input_needed
= FALSE
;
120 act_sel_done_primary(actor_unit_id
);
123 /* ====================================================================== */
124 /* ============================ CARAVAN DIALOG ========================== */
125 /* ====================================================================== */
127 /****************************************************************
128 User selected that caravan should enter marketplace.
129 *****************************************************************/
130 static int caravan_marketplace_callback(struct widget
*pWidget
)
132 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
133 if (NULL
!= game_city_by_number(
134 pDiplomat_Dlg
->target_ids
[ATK_CITY
])
135 && NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)) {
136 request_do_action(ACTION_MARKETPLACE
,
137 pDiplomat_Dlg
->actor_unit_id
,
138 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
142 popdown_diplomat_dialog();
148 /****************************************************************
149 User selected that caravan should establish traderoute.
150 *****************************************************************/
151 static int caravan_establish_trade_callback(struct widget
*pWidget
)
153 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
154 if (NULL
!= game_city_by_number(
155 pDiplomat_Dlg
->target_ids
[ATK_CITY
])
156 && NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)) {
157 request_do_action(ACTION_TRADE_ROUTE
,
158 pDiplomat_Dlg
->actor_unit_id
,
159 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
163 popdown_diplomat_dialog();
169 /****************************************************************
170 User selected that caravan should help in wonder building.
171 *****************************************************************/
172 static int caravan_help_build_wonder_callback(struct widget
*pWidget
)
174 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
175 if (NULL
!= game_city_by_number(
176 pDiplomat_Dlg
->target_ids
[ATK_CITY
])
177 && NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)) {
178 request_do_action(ACTION_HELP_WONDER
,
179 pDiplomat_Dlg
->actor_unit_id
,
180 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
184 popdown_diplomat_dialog();
190 /* ====================================================================== */
191 /* ============================ DIPLOMAT DIALOG ========================= */
192 /* ====================================================================== */
194 /****************************************************************
195 User interacted with diplomat dialog.
196 *****************************************************************/
197 static int diplomat_dlg_window_callback(struct widget
*pWindow
)
199 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
200 move_window_group(pDiplomat_Dlg
->pdialog
->pBeginWidgetList
, pWindow
);
205 /****************************************************************
206 User clicked "Establish Embassy"
207 *****************************************************************/
208 static int diplomat_embassy_callback(struct widget
*pWidget
)
210 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
211 if (NULL
!= game_city_by_number(
212 pDiplomat_Dlg
->target_ids
[ATK_CITY
])
213 && NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)) {
214 request_do_action(ACTION_ESTABLISH_EMBASSY
,
215 pDiplomat_Dlg
->actor_unit_id
,
216 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
220 popdown_diplomat_dialog();
226 /****************************************************************
227 User clicked "Investigate City"
228 *****************************************************************/
229 static int diplomat_investigate_callback(struct widget
*pWidget
)
231 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
232 if (NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)
233 && NULL
!= game_city_by_number(
234 pDiplomat_Dlg
->target_ids
[ATK_CITY
])) {
235 request_do_action(ACTION_SPY_INVESTIGATE_CITY
,
236 pDiplomat_Dlg
->actor_unit_id
,
237 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
241 /* FIXME: Wait for the city display in stead? */
242 popdown_diplomat_dialog();
248 /****************************************************************
249 User clicked "Poison City"
250 *****************************************************************/
251 static int spy_poison_callback( struct widget
*pWidget
)
253 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
254 if (NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)
255 && NULL
!= game_city_by_number(
256 pDiplomat_Dlg
->target_ids
[ATK_CITY
])) {
257 request_do_action(ACTION_SPY_POISON
, pDiplomat_Dlg
->actor_unit_id
,
258 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
262 popdown_diplomat_dialog();
268 /********************************************************************
269 User clicked "Steal Gold"
270 ********************************************************************/
271 static int spy_steal_gold_callback(struct widget
*pWidget
)
273 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
274 if (NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)
275 && NULL
!= game_city_by_number(
276 pDiplomat_Dlg
->target_ids
[ATK_CITY
])) {
277 request_do_action(ACTION_SPY_STEAL_GOLD
,
278 pDiplomat_Dlg
->actor_unit_id
,
279 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
283 popdown_diplomat_dialog();
289 /****************************************************************
290 Requests up-to-date list of improvements, the return of
291 which will trigger the popup_sabotage_dialog() function.
292 *****************************************************************/
293 static int spy_sabotage_request(struct widget
*pWidget
)
295 if (NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)
296 && NULL
!= game_city_by_number(
297 pDiplomat_Dlg
->target_ids
[ATK_CITY
])) {
298 request_action_details(ACTION_SPY_TARGETED_SABOTAGE_CITY
,
299 pDiplomat_Dlg
->actor_unit_id
,
300 pDiplomat_Dlg
->target_ids
[ATK_CITY
]);
301 is_more_user_input_needed
= TRUE
;
302 popdown_diplomat_dialog();
304 popdown_diplomat_dialog();
310 /****************************************************************
311 User clicked "Sabotage City" for diplomat (not spy)
312 *****************************************************************/
313 static int diplomat_sabotage_callback(struct widget
*pWidget
)
315 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
316 if (NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)
317 && NULL
!= game_city_by_number(
318 pDiplomat_Dlg
->target_ids
[ATK_CITY
])) {
319 request_do_action(ACTION_SPY_SABOTAGE_CITY
,
320 pDiplomat_Dlg
->actor_unit_id
,
321 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
325 popdown_diplomat_dialog();
331 /* --------------------------------------------------------- */
333 /****************************************************************
334 User interacted with spy's steal dialog window.
335 *****************************************************************/
336 static int spy_steal_dlg_window_callback(struct widget
*pWindow
)
338 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
339 move_window_group(pDiplomat_Dlg
->pdialog
->pBeginWidgetList
, pWindow
);
344 /****************************************************************
345 Exit spy's steal or sabotage dialog.
346 *****************************************************************/
347 static int exit_spy_tgt_dlg_callback(struct widget
*pWidget
)
349 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
350 int actor_id
= pDiplomat_Dlg
->actor_unit_id
;
352 fc_assert(is_more_user_input_needed
);
353 popdown_diplomat_dialog();
354 act_sel_done_secondary(actor_id
);
360 /****************************************************************
361 User selected which tech spy steals.
362 *****************************************************************/
363 static int spy_steal_callback(struct widget
*pWidget
)
365 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
366 int steal_advance
= MAX_ID
- pWidget
->ID
;
367 int actor_id
= pDiplomat_Dlg
->actor_unit_id
;
369 if (NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)
370 && NULL
!= game_city_by_number(
371 pDiplomat_Dlg
->target_ids
[ATK_CITY
])) {
372 if (steal_advance
== A_UNSET
) {
373 /* This is the untargeted version. */
374 request_do_action(ACTION_SPY_STEAL_TECH
,
375 pDiplomat_Dlg
->actor_unit_id
,
376 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
379 /* This is the targeted version. */
380 request_do_action(ACTION_SPY_TARGETED_STEAL_TECH
,
381 pDiplomat_Dlg
->actor_unit_id
,
382 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
387 fc_assert(is_more_user_input_needed
);
388 popdown_diplomat_dialog();
389 act_sel_done_secondary(actor_id
);
395 /**************************************************************************
396 Popup spy tech stealing dialog.
397 **************************************************************************/
398 static int spy_steal_popup(struct widget
*pWidget
)
400 const struct research
*presearch
, *vresearch
;
401 struct city
*pVcity
= pWidget
->data
.city
;
402 int id
= MAX_ID
- pWidget
->ID
;
403 struct player
*pVictim
= NULL
;
404 struct CONTAINER
*pCont
;
405 struct widget
*pBuf
= NULL
;
406 struct widget
*pWindow
;
409 int max_col
, max_row
, col
, count
= 0;
413 struct unit
*actor_unit
= game_unit_by_number(id
);
415 is_more_user_input_needed
= TRUE
;
416 popdown_diplomat_dialog();
420 pVictim
= city_owner(pVcity
);
423 fc_assert_ret_val_msg(!pDiplomat_Dlg
, 1, "Diplomat dialog already open");
426 act_sel_done_secondary(id
);
431 presearch
= research_get(client_player());
432 vresearch
= research_get(pVictim
);
433 advance_index_iterate(A_FIRST
, i
) {
434 if (research_invention_gettable(presearch
, i
,
435 game
.info
.tech_steal_allow_holes
)
436 && TECH_KNOWN
== research_invention_state(vresearch
, i
)
437 && TECH_KNOWN
!= research_invention_state(presearch
, i
)) {
440 } advance_index_iterate_end
;
443 /* if there is no known tech to steal then
444 send steal order at Spy's Discretion */
445 int target_id
= pVcity
->id
;
447 request_do_action(ACTION_SPY_STEAL_TECH
,
448 id
, target_id
, A_UNSET
);
450 act_sel_done_secondary(id
);
455 pCont
= fc_calloc(1, sizeof(struct CONTAINER
));
456 pCont
->id0
= pVcity
->id
;
457 pCont
->id1
= id
;/* spy id */
459 pDiplomat_Dlg
= fc_calloc(1, sizeof(struct diplomat_dialog
));
460 pDiplomat_Dlg
->actor_unit_id
= id
;
461 pDiplomat_Dlg
->target_ids
[ATK_CITY
] = pVcity
->id
;
462 pDiplomat_Dlg
->pdialog
= fc_calloc(1, sizeof(struct ADVANCED_DLG
));
464 pStr
= create_str16_from_char(_("Select Advance to Steal"), adj_font(12));
465 pStr
->style
|= TTF_STYLE_BOLD
;
467 pWindow
= create_window_skeleton(NULL
, pStr
, 0);
469 pWindow
->action
= spy_steal_dlg_window_callback
;
470 set_wstate(pWindow
, FC_WS_NORMAL
);
472 add_to_gui_list(ID_DIPLOMAT_DLG_WINDOW
, pWindow
);
473 pDiplomat_Dlg
->pdialog
->pEndWidgetList
= pWindow
;
475 area
= pWindow
->area
;
476 area
.w
= MAX(area
.w
, adj_size(8));
478 /* ------------------ */
480 pBuf
= create_themeicon(current_theme
->Small_CANCEL_Icon
, pWindow
->dst
,
481 WF_WIDGET_HAS_INFO_LABEL
| WF_RESTORE_BACKGROUND
);
482 pBuf
->info_label
= create_str16_from_char(_("Close Dialog (Esc)"),
484 area
.w
+= pBuf
->size
.w
+ adj_size(10);
485 pBuf
->action
= exit_spy_tgt_dlg_callback
;
486 set_wstate(pBuf
, FC_WS_NORMAL
);
487 pBuf
->key
= SDLK_ESCAPE
;
489 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON
, pBuf
);
490 /* ------------------------- */
492 if (action_prob_possible(
493 actor_unit
->client
.act_prob_cache
[ACTION_SPY_STEAL_TECH
])) {
494 /* count + at Spy's Discretion */
498 /* max col - 104 is steal tech widget width */
499 max_col
= (Main
.screen
->w
- (pWindow
->size
.w
- pWindow
->area
.w
) - adj_size(2)) / adj_size(104);
500 /* max row - 204 is steal tech widget height */
501 max_row
= (Main
.screen
->h
- (pWindow
->size
.h
- pWindow
->area
.h
)) / adj_size(204);
503 /* make space on screen for scrollbar */
504 if (max_col
* max_row
< count
) {
508 if (count
< max_col
+ 1) {
511 if (count
< max_col
+ adj_size(3)) {
512 col
= max_col
- adj_size(2);
514 if (count
< max_col
+ adj_size(5)) {
522 pStr
= create_string16(NULL
, 0, adj_font(10));
523 pStr
->style
|= (TTF_STYLE_BOLD
| SF_CENTER
);
526 advance_index_iterate(A_FIRST
, i
) {
527 if (research_invention_gettable(presearch
, i
,
528 game
.info
.tech_steal_allow_holes
)
529 && TECH_KNOWN
== research_invention_state(vresearch
, i
)
530 && TECH_KNOWN
!= research_invention_state(presearch
, i
)) {
533 copy_chars_to_string16(pStr
, advance_name_translation(advance_by_number(i
)));
534 pSurf
= create_sellect_tech_icon(pStr
, i
, FULL_MODE
);
535 pBuf
= create_icon2(pSurf
, pWindow
->dst
,
536 WF_FREE_THEME
| WF_RESTORE_BACKGROUND
);
538 set_wstate(pBuf
, FC_WS_NORMAL
);
539 pBuf
->action
= spy_steal_callback
;
540 pBuf
->data
.cont
= pCont
;
542 add_to_gui_list(MAX_ID
- i
, pBuf
);
544 if (count
> (col
* max_row
)) {
545 set_wflag(pBuf
, WF_HIDDEN
);
548 } advance_index_iterate_end
;
550 /* Get Spy tech to use for "At Spy's Discretion" -- this will have the
551 * side effect of displaying the unit's icon */
552 tech
= advance_number(unit_type_get(actor_unit
)->require_advance
);
554 if (action_prob_possible(
555 actor_unit
->client
.act_prob_cache
[ACTION_SPY_STEAL_TECH
])) {
557 struct astring str
= ASTRING_INIT
;
559 /* TRANS: %s is a unit name, e.g., Spy */
560 astr_set(&str
, _("At %s's Discretion"),
561 unit_name_translation(actor_unit
));
562 copy_chars_to_string16(pStr
, astr_str(&str
));
565 pSurf
= create_sellect_tech_icon(pStr
, tech
, FULL_MODE
);
567 pBuf
= create_icon2(pSurf
, pWindow
->dst
,
568 (WF_FREE_THEME
| WF_RESTORE_BACKGROUND
570 set_wstate(pBuf
, FC_WS_NORMAL
);
571 pBuf
->action
= spy_steal_callback
;
572 pBuf
->data
.cont
= pCont
;
574 add_to_gui_list(MAX_ID
- A_UNSET
, pBuf
);
578 /* --------------------------------------------------------- */
580 pDiplomat_Dlg
->pdialog
->pBeginWidgetList
= pBuf
;
581 pDiplomat_Dlg
->pdialog
->pBeginActiveWidgetList
= pDiplomat_Dlg
->pdialog
->pBeginWidgetList
;
582 pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
= pDiplomat_Dlg
->pdialog
->pEndWidgetList
->prev
->prev
;
584 /* -------------------------------------------------------------- */
588 count
= (count
+ (col
- 1)) / col
;
589 if (count
> max_row
) {
590 pDiplomat_Dlg
->pdialog
->pActiveWidgetList
= pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
;
592 idx
= create_vertical_scrollbar(pDiplomat_Dlg
->pdialog
, col
, count
, TRUE
, TRUE
);
598 area
.w
= MAX(area
.w
, (col
* pBuf
->size
.w
+ adj_size(2) + idx
));
599 area
.h
= count
* pBuf
->size
.h
+ adj_size(2);
601 /* alloca window theme and win background buffer */
602 pSurf
= theme_get_background(theme
, BACKGROUND_SPYSTEALDLG
);
603 if (resize_window(pWindow
, pSurf
, NULL
,
604 (pWindow
->size
.w
- pWindow
->area
.w
) + area
.w
,
605 (pWindow
->size
.h
- pWindow
->area
.h
) + area
.h
))
610 area
= pWindow
->area
;
612 widget_set_position(pWindow
,
613 (Main
.screen
->w
- pWindow
->size
.w
) / 2,
614 (Main
.screen
->h
- pWindow
->size
.h
) / 2);
617 pBuf
= pWindow
->prev
;
618 pBuf
->size
.x
= area
.x
+ area
.w
- pBuf
->size
.w
- 1;
619 pBuf
->size
.y
= pWindow
->size
.y
+ adj_size(2);
621 setup_vertical_widgets_position(col
, area
.x
+ 1,
623 pDiplomat_Dlg
->pdialog
->pBeginActiveWidgetList
,
624 pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
);
626 if(pDiplomat_Dlg
->pdialog
->pScroll
) {
627 setup_vertical_scrollbar_area(pDiplomat_Dlg
->pdialog
->pScroll
,
628 area
.x
+ area
.w
, area
.y
,
632 redraw_group(pDiplomat_Dlg
->pdialog
->pBeginWidgetList
, pWindow
, FALSE
);
633 widget_mark_dirty(pWindow
);
638 /****************************************************************
639 Technology stealing dialog, diplomat (not spy) version
640 *****************************************************************/
641 static int diplomat_steal_callback(struct widget
*pWidget
)
643 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
644 if (NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)
645 && NULL
!= game_city_by_number(
646 pDiplomat_Dlg
->target_ids
[ATK_CITY
])) {
647 request_do_action(ACTION_SPY_STEAL_TECH
,
648 pDiplomat_Dlg
->actor_unit_id
,
649 pDiplomat_Dlg
->target_ids
[ATK_CITY
],
653 popdown_diplomat_dialog();
659 /****************************************************************
660 ... Ask the server how much the revolt is going to cost us
661 *****************************************************************/
662 static int diplomat_incite_callback(struct widget
*pWidget
)
664 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
665 if (NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)
666 && NULL
!= game_city_by_number(
667 pDiplomat_Dlg
->target_ids
[ATK_CITY
])) {
668 request_action_details(ACTION_SPY_INCITE_CITY
,
669 pDiplomat_Dlg
->actor_unit_id
,
670 pDiplomat_Dlg
->target_ids
[ATK_CITY
]);
671 is_more_user_input_needed
= TRUE
;
672 popdown_diplomat_dialog();
674 popdown_diplomat_dialog();
680 /********************************************************************
681 Callback from action selection dialog for "keep moving".
682 (This should only occur when entering a tile with an allied city
684 *********************************************************************/
685 static int act_sel_keep_moving_callback(struct widget
*pWidget
)
687 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
690 if ((punit
= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
))
691 && !same_pos(unit_tile(punit
), pWidget
->data
.tile
)) {
692 request_unit_non_action_move(punit
, pWidget
->data
.tile
);
695 popdown_diplomat_dialog();
700 /********************************************************************
701 Delay selection of what action to take.
702 *********************************************************************/
703 static int act_sel_wait_callback(struct widget
*pWidget
)
705 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
708 /* The dialog was popped down when key_unit_wait() resulted in
709 * action_selection_close() being called. */
715 /****************************************************************
716 ... Ask the server how much the bribe is
717 *****************************************************************/
718 static int diplomat_bribe_callback(struct widget
*pWidget
)
720 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
721 if (NULL
!= game_unit_by_number(pDiplomat_Dlg
->actor_unit_id
)
723 game_unit_by_number(pDiplomat_Dlg
->target_ids
[ATK_UNIT
])) {
724 request_action_details(ACTION_SPY_BRIBE_UNIT
,
725 pDiplomat_Dlg
->actor_unit_id
,
726 pDiplomat_Dlg
->target_ids
[ATK_UNIT
]);
727 is_more_user_input_needed
= TRUE
;
728 popdown_diplomat_dialog();
730 popdown_diplomat_dialog();
736 /****************************************************************
737 User clicked "Sabotage Unit"
738 *****************************************************************/
739 static int spy_sabotage_unit_callback(struct widget
*pWidget
)
741 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
742 int diplomat_id
= MAX_ID
- pWidget
->ID
;
743 int target_id
= pWidget
->data
.unit
->id
;
745 popdown_diplomat_dialog();
746 request_do_action(ACTION_SPY_SABOTAGE_UNIT
,
747 diplomat_id
, target_id
, 0);
753 /****************************************************************
754 Close diplomat dialog.
755 *****************************************************************/
756 static int diplomat_close_callback(struct widget
*pWidget
)
758 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
759 popdown_diplomat_dialog();
765 /**************************************************************************
766 Popdown a dialog giving a diplomatic unit some options when moving into
768 **************************************************************************/
769 void popdown_diplomat_dialog(void)
772 act_sel_done_primary(pDiplomat_Dlg
->actor_unit_id
);
774 is_unit_move_blocked
= FALSE
;
775 popdown_window_group_dialog(pDiplomat_Dlg
->pdialog
->pBeginWidgetList
,
776 pDiplomat_Dlg
->pdialog
->pEndWidgetList
);
777 FC_FREE(pDiplomat_Dlg
->pdialog
->pScroll
);
778 FC_FREE(pDiplomat_Dlg
->pdialog
);
779 FC_FREE(pDiplomat_Dlg
);
784 /* Mapping from an action to the function to call when its button is
786 static const act_func af_map
[ACTION_COUNT
] = {
787 /* Unit acting against a city target. */
788 [ACTION_ESTABLISH_EMBASSY
] = diplomat_embassy_callback
,
789 [ACTION_SPY_INVESTIGATE_CITY
] = diplomat_investigate_callback
,
790 [ACTION_SPY_POISON
] = spy_poison_callback
,
791 [ACTION_SPY_STEAL_GOLD
] = spy_steal_gold_callback
,
792 [ACTION_SPY_SABOTAGE_CITY
] = diplomat_sabotage_callback
,
793 [ACTION_SPY_TARGETED_SABOTAGE_CITY
] = spy_sabotage_request
,
794 [ACTION_SPY_STEAL_TECH
] = diplomat_steal_callback
,
795 [ACTION_SPY_TARGETED_STEAL_TECH
] = spy_steal_popup
,
796 [ACTION_SPY_INCITE_CITY
] = diplomat_incite_callback
,
797 [ACTION_TRADE_ROUTE
] = caravan_establish_trade_callback
,
798 [ACTION_MARKETPLACE
] = caravan_marketplace_callback
,
799 [ACTION_HELP_WONDER
] = caravan_help_build_wonder_callback
,
801 /* Unit acting against a unit target. */
802 [ACTION_SPY_BRIBE_UNIT
] = diplomat_bribe_callback
,
803 [ACTION_SPY_SABOTAGE_UNIT
] = spy_sabotage_unit_callback
806 /**************************************************************************
807 Add an entry for an action in the action choice dialog.
808 **************************************************************************/
809 static void action_entry(const enum gen_action act
,
810 const struct act_prob
*act_probs
,
812 struct unit
*act_unit
,
813 struct city
*tgt_city
,
814 struct unit
*tgt_unit
,
815 struct widget
*pWindow
,
822 if (act
== ACTION_SPY_SABOTAGE_CITY
823 && action_prob_possible(
824 act_probs
[ACTION_SPY_TARGETED_SABOTAGE_CITY
])) {
825 /* The player can select Sabotage City from the target selection dialog
826 * of Targeted Sabotage City. */
830 if (act
== ACTION_SPY_STEAL_TECH
831 && action_prob_possible(
832 act_probs
[ACTION_SPY_TARGETED_STEAL_TECH
])) {
833 /* The player can select Steal Tech from the target selection dialog of
834 * Targeted Steal Tech. */
838 /* Don't show disabled actions */
839 if (!action_prob_possible(act_probs
[act
])) {
843 ui_name
= action_prepare_ui_name(act
, "",
844 act_probs
[act
], custom
);
846 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
847 ui_name
, af_map
[act
]);
849 switch(action_id_get_target_kind(act
)) {
851 pBuf
->data
.city
= tgt_city
;
854 pBuf
->data
.unit
= tgt_unit
;
857 fc_assert_msg(FALSE
, "Unsupported target kind");
860 set_wstate(pBuf
, FC_WS_NORMAL
);
862 add_to_gui_list(MAX_ID
- act_unit
->id
, pBuf
);
864 area
->w
= MAX(area
->w
, pBuf
->size
.w
);
865 area
->h
+= pBuf
->size
.h
;
868 /**************************************************************************
869 Return custom text for the specified action (given that the aciton is
871 **************************************************************************/
872 static const char *action_custom_text(const int action_id
,
873 const struct act_prob prob
,
874 const struct city
*actor_homecity
,
875 const struct city
*target_city
)
877 static struct astring custom
= ASTRING_INIT
;
879 if (!action_prob_possible(prob
)) {
880 /* No info since impossible. */
885 case ACTION_TRADE_ROUTE
:
887 int revenue
= get_caravan_enter_city_trade_bonus(actor_homecity
,
892 /* TRANS: Estimated one time bonus and recurring revenue for
893 * the Establish Trade _Route action. */
894 _("%d one time bonus + %d trade"),
896 trade_between_cities(actor_homecity
, target_city
));
899 case ACTION_MARKETPLACE
:
901 int revenue
= get_caravan_enter_city_trade_bonus(actor_homecity
,
906 /* TRANS: Estimated one time bonus for the Enter Marketplace
908 _("%d one time bonus"), revenue
);
912 /* No info to add. */
916 return astr_str(&custom
);
919 /**************************************************************************
920 Popup a dialog that allows the player to select what action a unit
922 **************************************************************************/
923 void popup_action_selection(struct unit
*actor_unit
,
924 struct city
*target_city
,
925 struct unit
*target_unit
,
926 struct tile
*target_tile
,
927 const struct act_prob
*act_probs
)
929 struct widget
*pWindow
= NULL
, *pBuf
= NULL
;
932 struct city
*actor_homecity
;
934 fc_assert_ret_msg(!pDiplomat_Dlg
, "Diplomat dialog already open");
936 /* Could be caused by the server failing to reply to a request for more
937 * information or a bug in the client code. */
938 fc_assert_msg(!is_more_user_input_needed
,
939 "Diplomat queue problem. Is another diplomat window open?");
941 /* No extra input is required as no action has been chosen yet. */
942 is_more_user_input_needed
= FALSE
;
944 is_unit_move_blocked
= TRUE
;
946 actor_homecity
= game_city_by_number(actor_unit
->homecity
);
948 pDiplomat_Dlg
= fc_calloc(1, sizeof(struct diplomat_dialog
));
949 pDiplomat_Dlg
->actor_unit_id
= actor_unit
->id
;
950 pDiplomat_Dlg
->pdialog
= fc_calloc(1, sizeof(struct ADVANCED_DLG
));
954 struct astring title
= ASTRING_INIT
;
955 /* TRANS: %s is a unit name, e.g., Spy */
956 astr_set(&title
, _("Choose Your %s's Strategy"),
957 unit_name_translation(actor_unit
));
958 pStr
= create_str16_from_char(astr_str(&title
), adj_font(12));
961 pStr
= create_str16_from_char(_("Subvert Enemy Unit"), adj_font(12));
964 pStr
->style
|= TTF_STYLE_BOLD
;
966 pWindow
= create_window_skeleton(NULL
, pStr
, 0);
968 pWindow
->action
= diplomat_dlg_window_callback
;
969 set_wstate(pWindow
, FC_WS_NORMAL
);
971 add_to_gui_list(ID_CARAVAN_DLG_WINDOW
, pWindow
);
972 pDiplomat_Dlg
->pdialog
->pEndWidgetList
= pWindow
;
974 area
= pWindow
->area
;
975 area
.w
= MAX(area
.w
, adj_size(8));
976 area
.h
= MAX(area
.h
, adj_size(2));
979 pDiplomat_Dlg
->target_ids
[ATK_CITY
] = target_city
->id
;
981 pDiplomat_Dlg
->target_ids
[ATK_CITY
] = IDENTITY_NUMBER_ZERO
;
985 pDiplomat_Dlg
->target_ids
[ATK_UNIT
] = target_unit
->id
;
987 pDiplomat_Dlg
->target_ids
[ATK_UNIT
] = IDENTITY_NUMBER_ZERO
;
991 /* Unit acting against a city */
993 action_iterate(act
) {
994 if (action_id_get_actor_kind(act
) == AAK_UNIT
995 && action_id_get_target_kind(act
) == ATK_CITY
) {
996 action_entry(act
, act_probs
,
997 action_custom_text(act
, act_probs
[act
],
998 actor_homecity
, target_city
),
999 actor_unit
, target_city
, NULL
,
1002 } action_iterate_end
;
1004 /* Unit acting against another unit */
1006 action_iterate(act
) {
1007 if (action_id_get_actor_kind(act
) == AAK_UNIT
1008 && action_id_get_target_kind(act
) == ATK_UNIT
) {
1009 action_entry(act
, act_probs
,
1011 actor_unit
, NULL
, target_unit
,
1014 } action_iterate_end
;
1017 if (unit_can_move_to_tile(actor_unit
, target_tile
, FALSE
)
1018 || (is_military_unit(actor_unit
) || is_attack_unit(actor_unit
))
1019 || (can_unit_bombard(actor_unit
) && !is_ocean_tile(target_tile
))
1020 || (!target_city
&& unit_has_type_flag(actor_unit
, UTYF_CAPTURER
))) {
1021 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1023 act_sel_keep_moving_callback
);
1025 pBuf
->data
.tile
= target_tile
;
1027 set_wstate(pBuf
, FC_WS_NORMAL
);
1029 add_to_gui_list(MAX_ID
- actor_unit
->id
, pBuf
);
1031 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1032 area
.h
+= pBuf
->size
.h
;
1036 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1037 _("Wait"), act_sel_wait_callback
);
1039 pBuf
->data
.tile
= target_tile
;
1041 set_wstate(pBuf
, FC_WS_NORMAL
);
1043 add_to_gui_list(MAX_ID
- actor_unit
->id
, pBuf
);
1045 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1046 area
.h
+= pBuf
->size
.h
;
1049 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1050 _("Cancel"), diplomat_close_callback
);
1052 set_wstate(pBuf
, FC_WS_NORMAL
);
1053 pBuf
->key
= SDLK_ESCAPE
;
1055 add_to_gui_list(ID_LABEL
, pBuf
);
1057 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1058 area
.h
+= pBuf
->size
.h
;
1060 pDiplomat_Dlg
->pdialog
->pBeginWidgetList
= pBuf
;
1062 /* setup window size and start position */
1064 resize_window(pWindow
, NULL
, NULL
,
1065 (pWindow
->size
.w
- pWindow
->area
.w
) + area
.w
,
1066 (pWindow
->size
.h
- pWindow
->area
.h
) + area
.h
);
1068 area
= pWindow
->area
;
1070 auto_center_on_focus_unit();
1071 put_window_near_map_tile(pWindow
, pWindow
->size
.w
, pWindow
->size
.h
,
1072 unit_tile(actor_unit
));
1074 /* setup widget size and start position */
1076 pBuf
= pWindow
->prev
;
1077 setup_vertical_widgets_position(1,
1079 area
.y
+ 1, area
.w
, 0,
1080 pDiplomat_Dlg
->pdialog
->pBeginWidgetList
, pBuf
);
1082 /* --------------------- */
1084 redraw_group(pDiplomat_Dlg
->pdialog
->pBeginWidgetList
, pWindow
, 0);
1086 widget_flush(pWindow
);
1088 /* Give follow up questions access to action probabilities. */
1089 client_unit_init_act_prob_cache(actor_unit
);
1090 action_iterate(act
) {
1091 actor_unit
->client
.act_prob_cache
[act
] = act_probs
[act
];
1092 } action_iterate_end
;
1095 /**************************************************************************
1096 Returns the id of the actor unit currently handled in action selection
1097 dialog when the action selection dialog is open.
1098 Returns IDENTITY_NUMBER_ZERO if no action selection dialog is open.
1099 **************************************************************************/
1100 int action_selection_actor_unit(void)
1102 if (!pDiplomat_Dlg
) {
1103 return IDENTITY_NUMBER_ZERO
;
1106 return pDiplomat_Dlg
->actor_unit_id
;
1109 /**************************************************************************
1110 Returns id of the target city of the actions currently handled in action
1111 selection dialog when the action selection dialog is open and it has a
1112 city target. Returns IDENTITY_NUMBER_ZERO if no action selection dialog
1113 is open or no city target is present in the action selection dialog.
1114 **************************************************************************/
1115 int action_selection_target_city(void)
1117 if (!pDiplomat_Dlg
) {
1118 return IDENTITY_NUMBER_ZERO
;
1121 return pDiplomat_Dlg
->target_ids
[ATK_CITY
];
1124 /**************************************************************************
1125 Returns id of the target unit of the actions currently handled in action
1126 selection dialog when the action selection dialog is open and it has a
1127 unit target. Returns IDENTITY_NUMBER_ZERO if no action selection dialog
1128 is open or no unit target is present in the action selection dialog.
1129 **************************************************************************/
1130 int action_selection_target_unit(void)
1132 if (!pDiplomat_Dlg
) {
1133 return IDENTITY_NUMBER_ZERO
;
1136 return pDiplomat_Dlg
->target_ids
[ATK_UNIT
];
1139 /**************************************************************************
1140 Updates the action selection dialog with new information.
1141 **************************************************************************/
1142 void action_selection_refresh(struct unit
*actor_unit
,
1143 struct city
*target_city
,
1144 struct unit
*target_unit
,
1145 struct tile
*target_tile
,
1146 const struct act_prob
*act_probs
)
1148 /* TODO: port me. */
1151 /****************************************************************
1152 Closes the action selection dialog
1153 ****************************************************************/
1154 void action_selection_close(void)
1156 did_not_decide
= TRUE
;
1157 popdown_diplomat_dialog();
1160 /* ====================================================================== */
1161 /* ============================ SABOTAGE DIALOG ========================= */
1162 /* ====================================================================== */
1164 /****************************************************************
1165 User selected what to sabotage.
1166 ****************************************************************/
1167 static int sabotage_impr_callback(struct widget
*pWidget
)
1169 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
1170 int sabotage_improvement
= MAX_ID
- pWidget
->ID
;
1171 int diplomat_target_id
= pWidget
->data
.cont
->id0
;
1172 int diplomat_id
= pWidget
->data
.cont
->id1
;
1174 fc_assert(is_more_user_input_needed
);
1175 popdown_diplomat_dialog();
1177 if(sabotage_improvement
== 1000)
1179 sabotage_improvement
= -1;
1182 if (NULL
!= game_unit_by_number(diplomat_id
)
1183 && NULL
!= game_city_by_number(diplomat_target_id
)) {
1184 if (sabotage_improvement
== B_LAST
) {
1185 /* This is the untargeted version. */
1186 request_do_action(ACTION_SPY_SABOTAGE_CITY
, diplomat_id
,
1187 diplomat_target_id
, sabotage_improvement
+ 1);
1189 /* This is the targeted version. */
1190 request_do_action(ACTION_SPY_TARGETED_SABOTAGE_CITY
, diplomat_id
,
1191 diplomat_target_id
, sabotage_improvement
+ 1);
1195 act_sel_done_secondary(diplomat_id
);
1201 /*************************************************************************
1202 Pops-up the Spy sabotage dialog, upon return of list of
1203 available improvements requested by the above function.
1204 **************************************************************************/
1205 void popup_sabotage_dialog(struct unit
*actor
, struct city
*pCity
)
1207 struct widget
*pWindow
= NULL
, *pBuf
= NULL
, *pLast
= NULL
;
1208 struct CONTAINER
*pCont
;
1210 SDL_Rect area
, area2
;
1211 int n
, w
= 0, h
, imp_h
= 0, y
;
1213 fc_assert_ret_msg(!pDiplomat_Dlg
, "Diplomat dialog already open");
1215 /* Should be set before sending request to the server. */
1216 fc_assert(is_more_user_input_needed
);
1219 act_sel_done_secondary(IDENTITY_NUMBER_ZERO
);
1223 is_unit_move_blocked
= TRUE
;
1225 pDiplomat_Dlg
= fc_calloc(1, sizeof(struct diplomat_dialog
));
1226 pDiplomat_Dlg
->actor_unit_id
= actor
->id
;
1227 pDiplomat_Dlg
->target_ids
[ATK_CITY
] = pCity
->id
;
1228 pDiplomat_Dlg
->pdialog
= fc_calloc(1, sizeof(struct ADVANCED_DLG
));
1230 pCont
= fc_calloc(1, sizeof(struct CONTAINER
));
1231 pCont
->id0
= pCity
->id
;
1232 pCont
->id1
= actor
->id
; /* spy id */
1234 pStr
= create_str16_from_char(_("Select Improvement to Sabotage") , adj_font(12));
1235 pStr
->style
|= TTF_STYLE_BOLD
;
1237 pWindow
= create_window_skeleton(NULL
, pStr
, 0);
1239 pWindow
->action
= diplomat_dlg_window_callback
;
1240 set_wstate(pWindow
, FC_WS_NORMAL
);
1242 add_to_gui_list(ID_TERRAIN_ADV_DLG_WINDOW
, pWindow
);
1243 pDiplomat_Dlg
->pdialog
->pEndWidgetList
= pWindow
;
1245 area
= pWindow
->area
;
1246 area
.h
= MAX(area
.h
, adj_size(2));
1250 pBuf
= create_themeicon(current_theme
->Small_CANCEL_Icon
, pWindow
->dst
,
1251 WF_WIDGET_HAS_INFO_LABEL
| WF_RESTORE_BACKGROUND
);
1252 pBuf
->info_label
= create_str16_from_char(_("Close Dialog (Esc)"),
1254 area
.w
+= pBuf
->size
.w
+ adj_size(10);
1255 pBuf
->action
= exit_spy_tgt_dlg_callback
;
1256 set_wstate(pBuf
, FC_WS_NORMAL
);
1257 pBuf
->key
= SDLK_ESCAPE
;
1259 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON
, pBuf
);
1262 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1263 _("City Production"), sabotage_impr_callback
);
1264 pBuf
->data
.cont
= pCont
;
1265 set_wstate(pBuf
, FC_WS_NORMAL
);
1266 set_wflag(pBuf
, WF_FREE_DATA
);
1267 add_to_gui_list(MAX_ID
- 1000, pBuf
);
1269 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1270 area
.h
+= pBuf
->size
.h
;
1273 pBuf
= create_iconlabel(NULL
, pWindow
->dst
, NULL
, WF_FREE_THEME
);
1275 add_to_gui_list(ID_SEPARATOR
, pBuf
);
1276 area
.h
+= pBuf
->next
->size
.h
;
1278 pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
= pBuf
;
1280 /* ------------------ */
1282 city_built_iterate(pCity
, pImprove
) {
1283 if (pImprove
->sabotage
> 0) {
1285 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1286 (char *) city_improvement_name_translation(pCity
, pImprove
),
1287 sabotage_impr_callback
);
1288 pBuf
->data
.cont
= pCont
;
1289 set_wstate(pBuf
, FC_WS_NORMAL
);
1291 add_to_gui_list(MAX_ID
- improvement_number(pImprove
), pBuf
);
1293 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1294 imp_h
+= pBuf
->size
.h
;
1297 set_wflag(pBuf
, WF_HIDDEN
);
1303 } city_built_iterate_end
;
1305 pDiplomat_Dlg
->pdialog
->pBeginActiveWidgetList
= pBuf
;
1307 if (n
> 0 && action_prob_possible(
1308 actor
->client
.act_prob_cache
[ACTION_SPY_SABOTAGE_CITY
])) {
1310 pBuf
= create_iconlabel(NULL
, pWindow
->dst
, NULL
, WF_FREE_THEME
);
1312 add_to_gui_list(ID_SEPARATOR
, pBuf
);
1313 area
.h
+= pBuf
->next
->size
.h
;
1314 /* ------------------ */
1317 if (action_prob_possible(
1318 actor
->client
.act_prob_cache
[ACTION_SPY_SABOTAGE_CITY
])) {
1319 struct astring str
= ASTRING_INIT
;
1321 /* TRANS: %s is a unit name, e.g., Spy */
1322 astr_set(&str
, _("At %s's Discretion"), unit_name_translation(actor
));
1323 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
, astr_str(&str
),
1324 sabotage_impr_callback
);
1327 pBuf
->data
.cont
= pCont
;
1328 set_wstate(pBuf
, FC_WS_NORMAL
);
1330 add_to_gui_list(MAX_ID
- B_LAST
, pBuf
);
1332 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1333 area
.h
+= pBuf
->size
.h
;
1339 pDiplomat_Dlg
->pdialog
->pBeginWidgetList
= pLast
;
1340 pDiplomat_Dlg
->pdialog
->pActiveWidgetList
= pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
;
1345 imp_h
= 10 * pBuf
->size
.h
;
1347 n
= create_vertical_scrollbar(pDiplomat_Dlg
->pdialog
,
1358 resize_window(pWindow
, NULL
, NULL
,
1359 (pWindow
->size
.w
- pWindow
->area
.w
) + area
.w
,
1360 (pWindow
->size
.h
- pWindow
->area
.h
) + area
.h
);
1362 area
= pWindow
->area
;
1364 auto_center_on_focus_unit();
1365 put_window_near_map_tile(pWindow
, pWindow
->size
.w
, pWindow
->size
.h
,
1371 pBuf
= pWindow
->prev
;
1372 pBuf
->size
.x
= area
.x
+ area
.w
- pBuf
->size
.w
- 1;
1373 pBuf
->size
.y
= pWindow
->size
.y
+ adj_size(2);
1375 /* Production sabotage */
1378 pBuf
->size
.x
= area
.x
;
1379 pBuf
->size
.y
= y
= area
.y
+ 1;
1383 area2
.x
= adj_size(10);
1384 area2
.h
= adj_size(2);
1390 if (pBuf
== pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
) {
1395 pBuf
->size
.x
= pBuf
->next
->size
.x
;
1396 pBuf
->size
.y
= y
= y
+ pBuf
->next
->size
.h
;
1398 if (pBuf
->ID
== ID_SEPARATOR
)
1400 FREESURFACE(pBuf
->theme
);
1402 pBuf
->theme
= create_surf(w
, h
, SDL_SWSURFACE
);
1404 area2
.y
= pBuf
->size
.h
/ 2 - 1;
1405 area2
.w
= pBuf
->size
.w
- adj_size(20);
1407 SDL_FillRect(pBuf
->theme
, &area2
, map_rgba(pBuf
->theme
->format
, *get_theme_color(COLOR_THEME_SABOTAGEDLG_SEPARATOR
)));
1410 if (pBuf
== pLast
) {
1413 if (pBuf
== pDiplomat_Dlg
->pdialog
->pBeginActiveWidgetList
) {
1414 /* Reset to end of scrolling area */
1415 y
= MIN(y
, pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
->size
.y
1416 + 9 * pBuf
->size
.h
);
1422 if (pDiplomat_Dlg
->pdialog
->pScroll
)
1424 setup_vertical_scrollbar_area(pDiplomat_Dlg
->pdialog
->pScroll
,
1426 pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
->size
.y
,
1427 pDiplomat_Dlg
->pdialog
->pBeginActiveWidgetList
->prev
->size
.y
1428 - pDiplomat_Dlg
->pdialog
->pEndActiveWidgetList
->size
.y
,
1432 /* -------------------- */
1434 redraw_group(pDiplomat_Dlg
->pdialog
->pBeginWidgetList
, pWindow
, 0);
1436 widget_flush(pWindow
);
1440 /* ====================================================================== */
1441 /* ============================== INCITE DIALOG ========================= */
1442 /* ====================================================================== */
1443 static struct small_diplomat_dialog
*pIncite_Dlg
= NULL
;
1445 /****************************************************************
1446 User interacted with Incite Revolt dialog window.
1447 *****************************************************************/
1448 static int incite_dlg_window_callback(struct widget
*pWindow
)
1450 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
1451 move_window_group(pIncite_Dlg
->pdialog
->pBeginWidgetList
, pWindow
);
1456 /****************************************************************
1457 User confirmed incite
1458 *****************************************************************/
1459 static int diplomat_incite_yes_callback(struct widget
*pWidget
)
1461 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
1462 if (NULL
!= game_unit_by_number(pIncite_Dlg
->actor_unit_id
)
1463 && NULL
!= game_city_by_number(pIncite_Dlg
->target_id
)) {
1464 request_do_action(ACTION_SPY_INCITE_CITY
, pIncite_Dlg
->actor_unit_id
,
1465 pIncite_Dlg
->target_id
, 0);
1468 popdown_incite_dialog();
1473 /****************************************************************
1474 Close incite dialog.
1475 *****************************************************************/
1476 static int exit_incite_dlg_callback(struct widget
*pWidget
)
1478 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
1479 popdown_incite_dialog();
1484 /**************************************************************************
1485 Popdown a window asking a diplomatic unit if it wishes to incite the
1487 **************************************************************************/
1488 void popdown_incite_dialog(void)
1491 act_sel_done_secondary(pIncite_Dlg
->actor_unit_id
);
1493 is_unit_move_blocked
= FALSE
;
1494 popdown_window_group_dialog(pIncite_Dlg
->pdialog
->pBeginWidgetList
,
1495 pIncite_Dlg
->pdialog
->pEndWidgetList
);
1496 FC_FREE(pIncite_Dlg
->pdialog
);
1497 FC_FREE(pIncite_Dlg
);
1502 /**************************************************************************
1503 Popup a window asking a diplomatic unit if it wishes to incite the
1505 **************************************************************************/
1506 void popup_incite_dialog(struct unit
*actor
, struct city
*pCity
, int cost
)
1508 struct widget
*pWindow
= NULL
, *pBuf
= NULL
;
1510 char tBuf
[255], cBuf
[255];
1518 /* Should be set before sending request to the server. */
1519 fc_assert(is_more_user_input_needed
);
1521 if (!actor
|| !unit_can_do_action(actor
, ACTION_SPY_INCITE_CITY
)) {
1522 act_sel_done_secondary(actor
? actor
->id
: IDENTITY_NUMBER_ZERO
);
1526 is_unit_move_blocked
= TRUE
;
1528 pIncite_Dlg
= fc_calloc(1, sizeof(struct small_diplomat_dialog
));
1529 pIncite_Dlg
->actor_unit_id
= actor
->id
;
1530 pIncite_Dlg
->target_id
= pCity
->id
;
1531 pIncite_Dlg
->pdialog
= fc_calloc(1, sizeof(struct SMALL_DLG
));
1533 fc_snprintf(tBuf
, ARRAY_SIZE(tBuf
), PL_("Treasury contains %d gold.",
1534 "Treasury contains %d gold.",
1535 client_player()->economic
.gold
),
1536 client_player()->economic
.gold
);
1539 pStr
= create_str16_from_char(_("Incite a Revolt!"), adj_font(12));
1541 pStr
->style
|= TTF_STYLE_BOLD
;
1543 pWindow
= create_window_skeleton(NULL
, pStr
, 0);
1545 pWindow
->action
= incite_dlg_window_callback
;
1546 set_wstate(pWindow
, FC_WS_NORMAL
);
1548 add_to_gui_list(ID_INCITE_DLG_WINDOW
, pWindow
);
1549 pIncite_Dlg
->pdialog
->pEndWidgetList
= pWindow
;
1551 area
= pWindow
->area
;
1552 area
.w
=MAX(area
.w
, adj_size(8));
1553 area
.h
= MAX(area
.h
, adj_size(2));
1555 if (INCITE_IMPOSSIBLE_COST
== cost
) {
1558 pBuf
= create_themeicon(current_theme
->Small_CANCEL_Icon
, pWindow
->dst
,
1559 WF_WIDGET_HAS_INFO_LABEL
1560 | WF_RESTORE_BACKGROUND
);
1561 pBuf
->info_label
= create_str16_from_char(_("Close Dialog (Esc)"),
1563 area
.w
+= pBuf
->size
.w
+ adj_size(10);
1564 pBuf
->action
= exit_incite_dlg_callback
;
1565 set_wstate(pBuf
, FC_WS_NORMAL
);
1566 pBuf
->key
= SDLK_ESCAPE
;
1568 add_to_gui_list(ID_INCITE_DLG_EXIT_BUTTON
, pBuf
);
1570 /* --------------- */
1572 fc_snprintf(cBuf
, sizeof(cBuf
), _("You can't incite a revolt in %s."),
1573 city_name_get(pCity
));
1575 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
, cBuf
, NULL
);
1577 add_to_gui_list(ID_LABEL
, pBuf
);
1579 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1580 area
.h
+= pBuf
->size
.h
;
1582 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1583 _("City can't be incited!"), NULL
);
1585 add_to_gui_list(ID_LABEL
, pBuf
);
1587 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1588 area
.h
+= pBuf
->size
.h
;
1590 } else if (cost
<= client_player()->economic
.gold
) {
1591 fc_snprintf(cBuf
, sizeof(cBuf
),
1592 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1593 PL_("Incite a revolt for %d gold?\n%s",
1594 "Incite a revolt for %d gold?\n%s", cost
), cost
, tBuf
);
1596 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
, cBuf
, NULL
);
1599 add_to_gui_list(ID_LABEL
, pBuf
);
1601 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1602 area
.h
+= pBuf
->size
.h
;
1605 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1606 _("Yes") , diplomat_incite_yes_callback
);
1608 pBuf
->data
.city
= pCity
;
1609 set_wstate(pBuf
, FC_WS_NORMAL
);
1611 add_to_gui_list(MAX_ID
- actor
->id
, pBuf
);
1613 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1614 area
.h
+= pBuf
->size
.h
;
1616 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1617 _("No") , exit_incite_dlg_callback
);
1619 set_wstate(pBuf
, FC_WS_NORMAL
);
1620 pBuf
->key
= SDLK_ESCAPE
;
1622 add_to_gui_list(ID_LABEL
, pBuf
);
1624 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1625 area
.h
+= pBuf
->size
.h
;
1629 pBuf
= create_themeicon(current_theme
->Small_CANCEL_Icon
, pWindow
->dst
,
1630 WF_WIDGET_HAS_INFO_LABEL
1631 | WF_RESTORE_BACKGROUND
);
1632 pBuf
->info_label
= create_str16_from_char(_("Close Dialog (Esc)"),
1634 area
.w
+= pBuf
->size
.w
+ adj_size(10);
1635 pBuf
->action
= exit_incite_dlg_callback
;
1636 set_wstate(pBuf
, FC_WS_NORMAL
);
1637 pBuf
->key
= SDLK_ESCAPE
;
1639 add_to_gui_list(ID_INCITE_DLG_EXIT_BUTTON
, pBuf
);
1641 /* --------------- */
1643 fc_snprintf(cBuf
, sizeof(cBuf
),
1644 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1645 PL_("Inciting a revolt costs %d gold.\n%s",
1646 "Inciting a revolt costs %d gold.\n%s", cost
), cost
, tBuf
);
1648 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
, cBuf
, NULL
);
1651 add_to_gui_list(ID_LABEL
, pBuf
);
1653 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1654 area
.h
+= pBuf
->size
.h
;
1657 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1658 _("Traitors Demand Too Much!"), NULL
);
1660 add_to_gui_list(ID_LABEL
, pBuf
);
1662 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1663 area
.h
+= pBuf
->size
.h
;
1665 pIncite_Dlg
->pdialog
->pBeginWidgetList
= pBuf
;
1667 /* setup window size and start position */
1669 resize_window(pWindow
, NULL
, NULL
,
1670 (pWindow
->size
.w
- pWindow
->area
.w
) + area
.w
,
1671 (pWindow
->size
.h
- pWindow
->area
.h
) + area
.h
);
1673 area
= pWindow
->area
;
1675 auto_center_on_focus_unit();
1676 put_window_near_map_tile(pWindow
, pWindow
->size
.w
, pWindow
->size
.h
,
1679 /* setup widget size and start position */
1685 pBuf
->size
.x
= area
.x
+ area
.w
- pBuf
->size
.w
- 1;
1686 pBuf
->size
.y
= pWindow
->size
.y
+ adj_size(2);
1690 setup_vertical_widgets_position(1,
1692 area
.y
+ 1, area
.w
, 0,
1693 pIncite_Dlg
->pdialog
->pBeginWidgetList
, pBuf
);
1695 /* --------------------- */
1697 redraw_group(pIncite_Dlg
->pdialog
->pBeginWidgetList
, pWindow
, 0);
1699 widget_flush(pWindow
);
1703 /* ====================================================================== */
1704 /* ============================ BRIBE DIALOG ========================== */
1705 /* ====================================================================== */
1706 static struct small_diplomat_dialog
*pBribe_Dlg
= NULL
;
1708 /**************************************************************************
1709 User interacted with bribe dialog window.
1710 **************************************************************************/
1711 static int bribe_dlg_window_callback(struct widget
*pWindow
)
1713 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
1714 move_window_group(pBribe_Dlg
->pdialog
->pBeginWidgetList
, pWindow
);
1719 /**************************************************************************
1720 User confirmed bribe.
1721 **************************************************************************/
1722 static int diplomat_bribe_yes_callback(struct widget
*pWidget
)
1724 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
1725 if (NULL
!= game_unit_by_number(pBribe_Dlg
->actor_unit_id
)
1726 && NULL
!= game_unit_by_number(pBribe_Dlg
->target_id
)) {
1727 request_do_action(ACTION_SPY_BRIBE_UNIT
, pBribe_Dlg
->actor_unit_id
,
1728 pBribe_Dlg
->target_id
, 0);
1730 popdown_bribe_dialog();
1736 /**************************************************************************
1738 **************************************************************************/
1739 static int exit_bribe_dlg_callback(struct widget
*pWidget
)
1741 if (Main
.event
.button
.button
== SDL_BUTTON_LEFT
) {
1742 popdown_bribe_dialog();
1747 /**************************************************************************
1748 Popdown a dialog asking a diplomatic unit if it wishes to bribe the
1750 **************************************************************************/
1751 void popdown_bribe_dialog(void)
1754 act_sel_done_secondary(pBribe_Dlg
->actor_unit_id
);
1756 is_unit_move_blocked
= FALSE
;
1757 popdown_window_group_dialog(pBribe_Dlg
->pdialog
->pBeginWidgetList
,
1758 pBribe_Dlg
->pdialog
->pEndWidgetList
);
1759 FC_FREE(pBribe_Dlg
->pdialog
);
1760 FC_FREE(pBribe_Dlg
);
1765 /**************************************************************************
1766 Popup a dialog asking a diplomatic unit if it wishes to bribe the
1768 **************************************************************************/
1769 void popup_bribe_dialog(struct unit
*actor
, struct unit
*pUnit
, int cost
)
1771 struct widget
*pWindow
= NULL
, *pBuf
= NULL
;
1773 char tBuf
[255], cBuf
[255];
1781 /* Should be set before sending request to the server. */
1782 fc_assert(is_more_user_input_needed
);
1784 if (!actor
|| !unit_can_do_action(actor
, ACTION_SPY_BRIBE_UNIT
)) {
1785 act_sel_done_secondary(actor
? actor
->id
: IDENTITY_NUMBER_ZERO
);
1789 is_unit_move_blocked
= TRUE
;
1791 pBribe_Dlg
= fc_calloc(1, sizeof(struct small_diplomat_dialog
));
1792 pBribe_Dlg
->actor_unit_id
= actor
->id
;
1793 pBribe_Dlg
->target_id
= pUnit
->id
;
1794 pBribe_Dlg
->pdialog
= fc_calloc(1, sizeof(struct SMALL_DLG
));
1796 fc_snprintf(tBuf
, ARRAY_SIZE(tBuf
), PL_("Treasury contains %d gold.",
1797 "Treasury contains %d gold.",
1798 client_player()->economic
.gold
),
1799 client_player()->economic
.gold
);
1802 pStr
= create_str16_from_char(_("Bribe Enemy Unit"), adj_font(12));
1804 pStr
->style
|= TTF_STYLE_BOLD
;
1806 pWindow
= create_window_skeleton(NULL
, pStr
, 0);
1808 pWindow
->action
= bribe_dlg_window_callback
;
1809 set_wstate(pWindow
, FC_WS_NORMAL
);
1811 add_to_gui_list(ID_BRIBE_DLG_WINDOW
, pWindow
);
1812 pBribe_Dlg
->pdialog
->pEndWidgetList
= pWindow
;
1814 area
= pWindow
->area
;
1815 area
.w
= MAX(area
.w
, adj_size(8));
1816 area
.h
= MAX(area
.h
, adj_size(2));
1818 if (cost
<= client_player()->economic
.gold
) {
1819 fc_snprintf(cBuf
, sizeof(cBuf
),
1820 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1821 PL_("Bribe unit for %d gold?\n%s",
1822 "Bribe unit for %d gold?\n%s", cost
), cost
, tBuf
);
1824 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
, cBuf
, NULL
);
1826 add_to_gui_list(ID_LABEL
, pBuf
);
1828 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1829 area
.h
+= pBuf
->size
.h
;
1832 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1833 _("Yes"), diplomat_bribe_yes_callback
);
1834 pBuf
->data
.unit
= pUnit
;
1835 set_wstate(pBuf
, FC_WS_NORMAL
);
1837 add_to_gui_list(MAX_ID
- actor
->id
, pBuf
);
1839 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1840 area
.h
+= pBuf
->size
.h
;
1842 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1843 _("No") , exit_bribe_dlg_callback
);
1845 set_wstate(pBuf
, FC_WS_NORMAL
);
1846 pBuf
->key
= SDLK_ESCAPE
;
1848 add_to_gui_list(ID_LABEL
, pBuf
);
1850 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1851 area
.h
+= pBuf
->size
.h
;
1855 pBuf
= create_themeicon(current_theme
->Small_CANCEL_Icon
, pWindow
->dst
,
1856 WF_WIDGET_HAS_INFO_LABEL
1857 | WF_RESTORE_BACKGROUND
);
1858 pBuf
->info_label
= create_str16_from_char(_("Close Dialog (Esc)"),
1860 area
.w
+= pBuf
->size
.w
+ adj_size(10);
1861 pBuf
->action
= exit_bribe_dlg_callback
;
1862 set_wstate(pBuf
, FC_WS_NORMAL
);
1863 pBuf
->key
= SDLK_ESCAPE
;
1865 add_to_gui_list(ID_BRIBE_DLG_EXIT_BUTTON
, pBuf
);
1867 /* --------------- */
1869 fc_snprintf(cBuf
, sizeof(cBuf
),
1870 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1871 PL_("Bribing the unit costs %d gold.\n%s",
1872 "Bribing the unit costs %d gold.\n%s", cost
), cost
, tBuf
);
1874 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
, cBuf
, NULL
);
1876 add_to_gui_list(ID_LABEL
, pBuf
);
1878 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1879 area
.h
+= pBuf
->size
.h
;
1882 create_active_iconlabel(pBuf
, pWindow
->dst
, pStr
,
1883 _("Traitors Demand Too Much!"), NULL
);
1885 add_to_gui_list(ID_LABEL
, pBuf
);
1887 area
.w
= MAX(area
.w
, pBuf
->size
.w
);
1888 area
.h
+= pBuf
->size
.h
;
1890 pBribe_Dlg
->pdialog
->pBeginWidgetList
= pBuf
;
1892 /* setup window size and start position */
1894 resize_window(pWindow
, NULL
, NULL
,
1895 (pWindow
->size
.w
- pWindow
->area
.w
) + area
.w
,
1896 (pWindow
->size
.h
- pWindow
->area
.h
) + area
.h
);
1898 area
= pWindow
->area
;
1900 auto_center_on_focus_unit();
1901 put_window_near_map_tile(pWindow
, pWindow
->size
.w
, pWindow
->size
.h
,
1904 /* setup widget size and start position */
1910 pBuf
->size
.x
= area
.x
+ area
.w
- pBuf
->size
.w
- 1;
1911 pBuf
->size
.y
= pWindow
->size
.y
+ adj_size(2);
1915 setup_vertical_widgets_position(1,
1917 area
.y
+ 1, area
.w
, 0,
1918 pBribe_Dlg
->pdialog
->pBeginWidgetList
, pBuf
);
1920 /* --------------------- */
1922 redraw_group(pBribe_Dlg
->pdialog
->pBeginWidgetList
, pWindow
, 0);
1924 widget_flush(pWindow
);