1 //  Copyright (C) 2007, 2008, Ole Laursen
2 //  Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2014, 2015, 2016, 2017,
3 //  2020 Ben Asselstine
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU Library General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 //  02110-1301, USA.
19 
20 #include <config.h>
21 
22 #include <iomanip>
23 #include <queue>
24 #include <assert.h>
25 #include <string.h>
26 
27 #include <sigc++/functors/mem_fun.h>
28 #include <sigc++/functors/ptr_fun.h>
29 #include <sigc++/adaptors/hide.h>
30 
31 #include <gtkmm.h>
32 #include <glib.h>
33 #include <gtk/gtk.h>
34 
35 #include "game-window.h"
36 
37 #include "input-helpers.h"
38 #include "driver.h"
39 #include "fight-window.h"
40 #include "city-window.h"
41 #include "army-gains-level-dialog.h"
42 #include "hero-dialog.h"
43 #include "SightMap.h"
44 #include "sage-dialog.h"
45 #include "ruin-rewarded-dialog.h"
46 #include "hero-offer-dialog.h"
47 #include "surrender-dialog.h"
48 #include "surrender-refused-dialog.h"
49 #include "quest-report-dialog.h"
50 #include "quest-assigned-dialog.h"
51 #include "quest-completed-dialog.h"
52 #include "preferences-dialog.h"
53 #include "fight-order-dialog.h"
54 #include "hero-levels-dialog.h"
55 #include "ruin-report-dialog.h"
56 #include "army-bonus-dialog.h"
57 #include "item-bonus-dialog.h"
58 #include "history-report-dialog.h"
59 #include "report-dialog.h"
60 #include "triumphs-dialog.h"
61 #include "diplomacy-report-dialog.h"
62 #include "diplomacy-dialog.h"
63 #include "stack-info-dialog.h"
64 #include "timed-message-dialog.h"
65 #include "destination-dialog.h"
66 #include "item-report-dialog.h"
67 #include "use-item-dialog.h"
68 #include "use-item-on-player-dialog.h"
69 #include "use-item-on-city-dialog.h"
70 #include "game-button-box.h"
71 #include "status-box.h"
72 #include "ucompose.hpp"
73 #include "defs.h"
74 #include "snd.h"
75 #include "File.h"
76 #include "game.h"
77 #include "gamebigmap.h"
78 #include "smallmap.h"
79 #include "GameScenarioOptions.h"
80 #include "army.h"
81 #include "ruin.h"
82 #include "ruinlist.h"
83 #include "path.h"
84 #include "player.h"
85 #include "signpostlist.h"
86 #include "playerlist.h"
87 #include "citylist.h"
88 #include "hero.h"
89 #include "heroproto.h"
90 #include "temple.h"
91 #include "templelist.h"
92 #include "city.h"
93 #include "cityset.h"
94 #include "Quest.h"
95 #include "stack.h"
96 #include "ImageCache.h"
97 #include "QuestsManager.h"
98 #include "QCitySack.h"
99 #include "QCityRaze.h"
100 #include "QCityOccupy.h"
101 #include "QPillageGold.h"
102 #include "counter.h"
103 #include "armysetlist.h"
104 #include "tilesetlist.h"
105 #include "CreateScenario.h"
106 #include "reward.h"
107 #include "Configuration.h"
108 #include "GameMap.h"
109 #include "Item.h"
110 #include "shieldsetlist.h"
111 #include "game-server.h"
112 #include "game-client.h"
113 #include "NextTurnHotseat.h"
114 #include "NextTurnNetworked.h"
115 #include "network_player.h"
116 #include "stacktile.h"
117 #include "MapBackpack.h"
118 #include "select-city-map.h"
119 #include "shield.h"
120 #include "lw-dialog.h"
121 #include "builder-cache.h"
122 #include "new-network-game-dialog.h"
123 #include "rnd.h"
124 #include "font-size.h"
125 #include "keeper.h"
126 #include "load-progress-window.h"
127 
128 #define method(x) sigc::mem_fun(*this, &GameWindow::x)
129 
130 double GameWindow::minimum_zoom_scale = 0.4;
131 double GameWindow::maximum_zoom_scale = 3.0;
132 
GameWindow()133 GameWindow::GameWindow()
134 {
135   game_winner = NULL;
136   stack_info_tip = NULL;
137   city_info_tip = NULL;
138   map_tip = NULL;
139   stack_tip = NULL;
140   game = NULL;
141   game_button_box = NULL;
142   last_box = Gtk::Allocation(0,0,1,1);
143   unmaximized_box = Gtk::Allocation(0,0,1,1);
144 
145   Glib::RefPtr<Gtk::Builder> xml = BuilderCache::get("game-window.ui");
146 
147   Gtk::Window *w = 0;
148   xml->get_widget("window", w);
149   window = w;
150   w->set_icon_from_file(File::getVariousFile("castle_icon.png"));
151 
152   w->signal_window_state_event().connect (method(on_window_state_event));
153   w->signal_delete_event().connect (sigc::hide(method(on_delete_event)));
154   w->signal_configure_event().connect(method(on_configure_event));
155 
156   xml->get_widget("menubar", menubar);
157   xml->get_widget("bigmap_image", bigmap_image);
158   bigmap_image->signal_size_allocate().connect (method(on_bigmap_surface_changed));
159   bigmap_image->grab_focus();
160   xml->get_widget("bigmap_eventbox", bigmap_eventbox);
161   bigmap_eventbox->add_events(Gdk::KEY_PRESS_MASK | Gdk::BUTTON_PRESS_MASK |
162                               Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK |
163                               Gdk::SMOOTH_SCROLL_MASK | Gdk::LEAVE_NOTIFY_MASK);
164   bigmap_eventbox->signal_key_press_event().connect (method(on_bigmap_key_event));
165   bigmap_eventbox->signal_key_release_event().connect (method(on_bigmap_key_event));
166   bigmap_eventbox->signal_button_press_event().connect
167     (method(on_bigmap_mouse_button_event));
168   bigmap_eventbox->signal_button_release_event().connect
169     (method(on_bigmap_mouse_button_event));
170   bigmap_eventbox->signal_motion_notify_event().connect
171     (method(on_bigmap_mouse_motion_event));
172   bigmap_eventbox->signal_scroll_event().connect (method(on_bigmap_scrolled));
173   bigmap_eventbox->signal_leave_notify_event().connect
174     (sigc::hide(method(hide_map_tip)));
175 
176   xml->get_widget("status_box_container", status_box_container);
177 
178   status_box = StatusBox::create();
179   status_box->reparent(*status_box_container);
180   status_box->property_hexpand() = true;
181 
182   // the map image
183   xml->get_widget("smallmap_image", smallmap_image);
184   xml->get_widget("map_eventbox", map_eventbox);
185   xml->get_widget("map_container", map_container);
186   map_eventbox->add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
187                            Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK);
188   map_eventbox->signal_button_press_event().connect
189     (method(on_smallmap_mouse_button_event));
190   map_eventbox->signal_button_release_event().connect
191     (method(on_smallmap_mouse_button_event));
192   map_eventbox->signal_motion_notify_event().connect
193     (method(on_smallmap_mouse_motion_event));
194   map_eventbox->signal_enter_notify_event().connect
195     (sigc::hide(method(on_mouse_entered_smallmap)));
196   xml->get_widget("control_panel_viewport", control_panel_viewport);
197   game_button_box = GameButtonBox::create();
198   game_button_box->reparent(*control_panel_viewport);
199   game_button_box->property_halign() = Gtk::ALIGN_CENTER;
200 
201   // the stats
202   xml->get_widget("turn_label", turn_label);
203   xml->get_widget("turn_hbox", turn_hbox);
204   xml->get_widget("shield_image_0", shield_image[0]);
205   xml->get_widget("shield_image_1", shield_image[1]);
206   xml->get_widget("shield_image_2", shield_image[2]);
207   xml->get_widget("shield_image_3", shield_image[3]);
208   xml->get_widget("shield_image_4", shield_image[4]);
209   xml->get_widget("shield_image_5", shield_image[5]);
210   xml->get_widget("shield_image_6", shield_image[6]);
211   xml->get_widget("shield_image_7", shield_image[7]);
212 
213   // connect callbacks for the menu
214   xml->get_widget("new_game_menuitem", new_game_menuitem);
215   new_game_menuitem->signal_activate().connect (method(on_new_game_activated));
216   xml->get_widget("load_game_menuitem", load_game_menuitem);
217   load_game_menuitem->signal_activate().connect (method(on_load_game_activated));
218   xml->get_widget("save_game_menuitem", save_game_menuitem);
219   save_game_menuitem->signal_activate().connect (method(on_save_game_activated));
220   xml->get_widget("save_game_as_menuitem", save_game_as_menuitem);
221   save_game_as_menuitem->signal_activate().connect
222     (method(on_save_game_as_activated));
223   xml->get_widget("quit_menuitem", quit_menuitem);
224   quit_menuitem->signal_activate().connect (method(on_quit_activated));
225   xml->get_widget("toggle_grid_menuitem", toggle_grid_menuitem);
226   toggle_grid_menuitem->signal_activate().connect (method(on_grid_toggled));
227   xml->get_widget("army_report_menuitem", army_report_menuitem);
228   army_report_menuitem->signal_activate().connect
229     (method(on_army_report_activated));
230   xml->get_widget("item_report_menuitem", item_report_menuitem);
231   item_report_menuitem->signal_activate().connect
232     (method(on_item_report_activated));
233   xml->get_widget("city_report_menuitem", city_report_menuitem);
234   city_report_menuitem->signal_activate().connect
235     (method(on_city_report_activated));
236   xml->get_widget("gold_report_menuitem", gold_report_menuitem);
237   gold_report_menuitem->signal_activate().connect
238     (method(on_gold_report_activated));
239   xml->get_widget("winning_report_menuitem", winning_report_menuitem);
240   winning_report_menuitem->signal_activate().connect
241     (method(on_winning_report_activated));
242   xml->get_widget("diplomacy_report_menuitem", diplomacy_report_menuitem);
243   xml->get_widget("quests_menuitem", quests_menuitem);
244   quests_menuitem->signal_activate().connect (method(on_quests_activated));
245   xml->get_widget("fullscreen_menuitem", fullscreen_menuitem);
246   fullscreen_menuitem->signal_activate().connect (method(on_fullscreen_activated));
247   xml->get_widget("preferences_menuitem", preferences_menuitem);
248   preferences_menuitem->signal_activate().connect
249     (method(on_preferences_activated));
250   xml->get_widget("zoom_in_menuitem", zoom_in_menuitem);
251   zoom_in_menuitem->signal_activate().connect (method(on_zoom_in_activated));
252   xml->get_widget("zoom_out_menuitem", zoom_out_menuitem);
253   zoom_out_menuitem->signal_activate().connect (method(on_zoom_out_activated));
254   xml->get_widget("best_fit_menuitem", best_fit_menuitem);
255   best_fit_menuitem->signal_activate().connect (method(on_best_fit_activated));
256 
257   xml->get_widget("show_lobby_menuitem", show_lobby_menuitem);
258   show_lobby_menuitem->signal_activate().connect (method(on_show_lobby_activated));
259   xml->get_widget("end_turn_menuitem", end_turn_menuitem);
260   xml->get_widget("move_all_menuitem", move_all_menuitem);
261   xml->get_widget("disband_menuitem", disband_menuitem);
262   xml->get_widget("stack_info_menuitem", stack_info_menuitem);
263   xml->get_widget("signpost_menuitem", signpost_menuitem);
264   xml->get_widget("search_menuitem", search_menuitem);
265   xml->get_widget("use_menuitem", use_menuitem);
266   xml->get_widget("inspect_menuitem", inspect_menuitem);
267   xml->get_widget("plant_standard_menuitem", plant_standard_menuitem);
268   xml->get_widget("city_history_menuitem", city_history_menuitem);
269   xml->get_widget("ruin_history_menuitem", ruin_history_menuitem);
270   xml->get_widget("event_history_menuitem", event_history_menuitem);
271   xml->get_widget("gold_history_menuitem", gold_history_menuitem);
272   xml->get_widget("winner_history_menuitem", winner_history_menuitem);
273   xml->get_widget("group_ungroup_menuitem", group_ungroup_menuitem);
274   xml->get_widget("leave_menuitem", leave_menuitem);
275   xml->get_widget("next_menuitem", next_menuitem);
276 
277   xml->get_widget("fight_order_menuitem", fight_order_menuitem);
278   fight_order_menuitem->signal_activate().connect
279     (method(on_fight_order_activated));
280   xml->get_widget("resign_menuitem", resign_menuitem);
281   resign_menuitem->signal_activate().connect (method(on_resign_activated));
282   xml->get_widget("production_menuitem", production_menuitem);
283   production_menuitem->signal_activate().connect (method(on_production_activated));
284   xml->get_widget("cities_menuitem", cities_menuitem);
285   cities_menuitem->signal_activate().connect (method(on_production_activated));
286   xml->get_widget("build_menuitem", build_menuitem);
287   build_menuitem->signal_activate().connect (method(on_production_activated));
288   xml->get_widget("vectoring_menuitem", vectoring_menuitem);
289   vectoring_menuitem->signal_activate().connect (method(on_vectoring_activated));
290   xml->get_widget("levels_menuitem", levels_menuitem);
291   xml->get_widget("inspect_menuitem", inspect_menuitem);
292   xml->get_widget("ruin_report_menuitem", ruin_report_menuitem);
293   ruin_report_menuitem->signal_activate().connect
294     (method(on_ruin_report_activated));
295   xml->get_widget("army_bonus_menuitem", army_bonus_menuitem);
296   army_bonus_menuitem->signal_activate().connect (method(on_army_bonus_activated));
297   xml->get_widget("item_bonus_menuitem", item_bonus_menuitem);
298   item_bonus_menuitem->signal_activate().connect (method(on_item_bonus_activated));
299   xml->get_widget("production_report_menuitem", production_report_menuitem);
300   production_report_menuitem->signal_activate().connect
301     (method(on_production_report_activated));
302   xml->get_widget("triumphs_menuitem", triumphs_menuitem);
303   triumphs_menuitem->signal_activate().connect (method(on_triumphs_activated));
304   xml->get_widget("help_about_menuitem", help_about_menuitem);
305   help_about_menuitem->signal_activate().connect (method(on_help_about_activated));
306   xml->get_widget ("tutorial_menuitem", tutorial_menuitem);
307   tutorial_menuitem->signal_activate().connect (method(on_tutorial_activated));
308   xml->get_widget("online_help_menuitem", online_help_menuitem);
309   online_help_menuitem->signal_activate().connect
310     (method(on_online_help_activated));
311   xml->get_widget("quick_help_menuitem", quick_help_menuitem);
312   quick_help_menuitem->signal_activate().connect (method(on_quick_help_activated));
313   xml->get_widget("pos_label", pos_label);
314   d_quick_fights = false;
315 }
316 
~GameWindow()317 GameWindow::~GameWindow()
318 {
319   std::list<sigc::connection>::iterator it = connections.begin();
320   for (; it != connections.end(); it++)
321     (*it).disconnect();
322   connections.clear();
323   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
324     shield_image[i]->clear();
325   if (city_info_tip)
326     {
327       delete city_info_tip;
328       city_info_tip = NULL;
329     }
330   if (stack_info_tip)
331     {
332       delete stack_info_tip;
333       stack_info_tip = NULL;
334     }
335   if (game)
336     {
337       delete game;
338       game = NULL;
339     }
340   if (game_button_box)
341     {
342       delete game_button_box;
343       game_button_box = NULL;
344     }
345   if (status_box)
346     {
347       delete status_box;
348       status_box = NULL;
349     }
350   delete window;
351 }
352 
show()353 void GameWindow::show()
354 {
355   if (game_button_box)
356     {
357       control_panel_viewport->show_all();
358       game_button_box->show_all();
359     }
360 
361     bigmap_image->show_all();
362     window->show();
363     if (status_box)
364       {
365         status_box->setHeightFudgeFactor(turn_label->get_height());
366         status_box->enforce_height();
367         status_box->show_stats();
368       }
369 
370     on_bigmap_surface_changed(bigmap_image->get_allocation());
371     if (getenv ("LORDSAWAR_GUI_TEST") != NULL)
372       {
373         window->set_position(Gtk::WIN_POS_NONE);
374         window->move(0, 0);
375       }
376   Gdk::EventMask event_mask = window->get_window()->get_events ();
377   event_mask |= Gdk::STRUCTURE_MASK;
378   window->get_window()->set_events (event_mask);
379 }
380 
set_default_bigmap_zoom()381 void GameWindow::set_default_bigmap_zoom ()
382 {
383   Glib::RefPtr<Gdk::Display> d = Gdk::Display::get_default ();
384   zoom (BigMap::get_default_zoom_scale
385         (d->get_default_screen ()->get_height ()));
386 }
387 
init(int width,int height)388 void GameWindow::init(int width, int height)
389 {
390     bigmap_image->set_size_request(width, height);
391 
392     Vector<int> d = SmallMap::calculate_smallmap_size();
393     smallmap_image->set_size_request(d.x, d.y);
394 }
395 
new_network_game(GameScenario * game_scenario,NextTurn * next_turn)396 void GameWindow::new_network_game(GameScenario *game_scenario, NextTurn *next_turn)
397 {
398   if (GameServer::getInstance()->isListening() == true)
399     GameServer::getInstance()->round_begins.connect(method(on_remote_next_player_turn));
400   else
401     GameClient::getInstance()->playerlist_reorder_received.connect(method(on_remote_next_player_turn));
402   bool success = false;
403   //stop_game();
404   success = setup_game(game_scenario, next_turn);
405   if (!success)
406     return;
407   setup_signals(game_scenario);
408   game->redraw();
409   while (g_main_context_iteration(NULL, FALSE)); //doEvents fixes temporary 40x40 smallmap
410   game->startGame();
411   if (Playerlist::getActiveplayer() && GameServer::getInstance()->isListening() == false)
412     if (Playerlist::getActiveplayer()->getType() != Player::NETWORKED)
413       {
414         dynamic_cast<NextTurnNetworked*>(next_turn)->start_player(Playerlist::getActiveplayer());
415       }
416 }
417 
continue_network_game(NextTurn * next_turn)418 void GameWindow::continue_network_game(NextTurn *next_turn)
419 {
420   next_turn->start();
421 }
422 
new_game(GameScenario * game_scenario,NextTurn * next_turn)423 void GameWindow::new_game(GameScenario *game_scenario, NextTurn *next_turn)
424 {
425   bool success = false;
426   success = setup_game(game_scenario, next_turn);
427   if (!success)
428     return;
429   setup_signals(game_scenario);
430   game->startGame();
431   //we don't get here until the game ends.
432 }
433 
load_game(GameScenario * game_scenario,NextTurn * next_turn)434 void GameWindow::load_game(GameScenario *game_scenario, NextTurn *next_turn)
435 {
436   bool success = false;
437   success = setup_game(game_scenario, next_turn);
438   if (!success)
439     return;
440 
441   game->get_bigmap().screen_size_changed(bigmap_image->get_allocation());
442   setup_signals(game_scenario);
443   game->loadGame();
444   //we don't get here until the game ends, or a human player ends a turn.
445   if (Playerlist::getInstance()->countPlayersAlive())
446     game->redraw();
447 }
448 
setup_menuitem(Gtk::MenuItem * item,sigc::slot<void> slot,sigc::signal<void,bool> & game_signal)449 void GameWindow::setup_menuitem(Gtk::MenuItem *item,
450 				sigc::slot<void> slot,
451 				sigc::signal<void, bool> &game_signal)
452 {
453   connections.push_back (item->signal_activate().connect(slot));
454   connections.push_back
455     (game_signal.connect(sigc::mem_fun(item, &Gtk::Widget::set_sensitive)));
456 }
457 
setup_signals(GameScenario * game_scenario)458 void GameWindow::setup_signals(GameScenario *game_scenario)
459 {
460   // get rid of the connections that might be still around from last time
461   std::list<sigc::connection>::iterator it = connections.begin();
462   for (; it != connections.end(); it++)
463     (*it).disconnect();
464   connections.clear();
465 
466   connections.push_back (game_button_box->diplomacy_clicked.connect
467    (method (on_diplomacy_button_clicked)));
468   connections.push_back
469     (game->city_too_poor_to_produce.connect (method(show_city_production_report)));
470   connections.push_back
471     (game->commentator_comments.connect (method(on_commentator_comments)));
472 
473   setup_menuitem(move_all_menuitem, sigc::mem_fun(game, &Game::move_all_stacks),
474 		 game->can_move_all_stacks);
475   setup_menuitem(end_turn_menuitem, sigc::mem_fun(game, &Game::end_turn),
476 		 game->can_end_turn);
477   if (game_scenario->getPlayMode() == GameScenario::NETWORKED)
478     {
479       load_game_menuitem->set_sensitive(false);
480       if (GameServer::getInstance()->isListening() == false)
481 	{
482 	  save_game_menuitem->set_sensitive(false);
483 	  save_game_as_menuitem->set_sensitive(false);
484 	}
485     }
486   else
487     show_lobby_menuitem->set_sensitive(false);
488 
489   setup_menuitem(disband_menuitem, method(on_disband_activated),
490                  game->can_disband_stack);
491   setup_menuitem(stack_info_menuitem, method(on_stack_info_activated),
492 		 game->can_deselect_selected_stack);
493   setup_menuitem(signpost_menuitem, method(on_signpost_activated),
494 		 game->can_change_signpost);
495   setup_menuitem(search_menuitem,
496                  sigc::mem_fun(game, &Game::search_selected_stack),
497 		 game->can_search_selected_stack);
498   setup_menuitem(use_menuitem,
499 		 sigc::mem_fun(game, &Game::select_item_to_use),
500 		 game->can_use_item);
501   setup_menuitem(inspect_menuitem, method(on_inspect_activated),
502 		 game->can_inspect);
503   setup_menuitem(levels_menuitem, method(on_levels_activated),
504 		 game->can_see_hero_levels);
505   setup_menuitem(plant_standard_menuitem, method(on_plant_standard_activated),
506 		 game->can_plant_standard_selected_stack);
507   setup_menuitem(city_history_menuitem, method(on_city_history_activated),
508 		 game->can_see_history);
509   setup_menuitem(ruin_history_menuitem, method(on_ruin_history_activated),
510 		 game->can_see_history);
511   setup_menuitem(gold_history_menuitem, method(on_gold_history_activated),
512 		 game->can_see_history);
513   setup_menuitem(event_history_menuitem, method(on_event_history_activated),
514 		 game->can_see_history);
515   setup_menuitem(winner_history_menuitem, method(on_winner_history_activated),
516 		 game->can_see_history);
517   setup_menuitem(diplomacy_report_menuitem, method(on_diplomacy_report_activated),
518 		 game->can_see_diplomacy);
519   setup_menuitem(group_ungroup_menuitem, method(on_group_ungroup_activated),
520 		 game->can_group_ungroup_selected_stack);
521   setup_menuitem(leave_menuitem,
522 		 sigc::mem_fun(game, &Game::park_selected_stack),
523 		 game->can_park_selected_stack);
524   setup_menuitem(next_menuitem,
525 		 sigc::mem_fun(game, &Game::select_next_movable_stack),
526 		 game->can_select_next_movable_stack);
527 
528   // setup game callbacks
529   connections.push_back (game->game_stopped.connect (method(on_game_stopped)));
530   connections.push_back (game->sidebar_stats_changed.connect
531                          (method(on_sidebar_stats_changed)));
532   connections.push_back (game->progress_status_changed.connect
533                          (method(on_progress_status_changed)));
534   connections.push_back (game->progress_changed.connect
535                          (method(on_progress_changed)));
536   connections.push_back (game->bigmap_changed.connect (method(on_bigmap_changed)));
537   connections.push_back (game->smallmap_changed.connect
538                          (sigc::hide(method(on_smallmap_changed))));
539   connections.push_back (game->get_smallmap().view_slid.connect
540                          (sigc::hide(method(on_smallmap_slid))));
541   connections.push_back
542     (game->stack_info_changed.connect
543      (sigc::mem_fun(*status_box, &StatusBox::on_stack_info_changed)));
544   connections.push_back (game->map_tip_changed.connect
545                          (method(on_bigmap_tip_changed)));
546   connections.push_back (game->stack_tip_changed.connect
547                          (method(on_stack_tip_changed)));
548   connections.push_back (game->city_tip_changed.connect
549                          (method(on_city_tip_changed)));
550   connections.push_back (game->ruin_searched.connect (method(on_ruin_searched)));
551   connections.push_back (game->sage_visited.connect (method(on_sage_visited)));
552   connections.push_back (game->fight_started.connect (method(on_fight_started)));
553   connections.push_back (game->abbreviated_fight_started.connect
554                          (method(on_abbreviated_fight_started)));
555   connections.push_back (game->ruinfight_started.connect
556                          (method(on_ruinfight_started)));
557   connections.push_back (game->ruinfight_finished.connect
558                          (method(on_ruinfight_finished)));
559   connections.push_back (game->hero_offers_service.connect
560                          (method(on_hero_offers_service)));
561   connections.push_back (game->enemy_offers_surrender.connect
562                          (method(on_enemy_offers_surrender)));
563   connections.push_back (game->surrender_answered.connect
564                          (method(on_surrender_answered)));
565   connections.push_back
566     (game->stack_considers_treachery.connect
567      (sigc::hide(sigc::hide<0>(method(on_stack_considers_treachery)))));
568   connections.push_back (game->temple_searched.connect
569                          (method(on_temple_searched)));
570   connections.push_back (game->quest_assigned.connect (method(on_quest_assigned)));
571   connections.push_back (game->city_defeated.connect (method(on_city_defeated)));
572   connections.push_back (game->city_pillaged.connect (method(on_city_pillaged)));
573   connections.push_back (game->city_sacked.connect (method(on_city_sacked)));
574   connections.push_back (game->city_razed.connect (method(on_city_razed)));
575   connections.push_back (game->city_visited.connect (method(on_city_visited)));
576   connections.push_back (game->ruin_visited.connect (method(on_ruin_visited)));
577   connections.push_back (game->temple_visited.connect (method(on_temple_visited)));
578   connections.push_back (game->next_player_turn.connect
579                          (method(on_next_player_turn)));
580   connections.push_back (game->hero_arrives.connect
581                          (method(on_hero_brings_allies)));
582   connections.push_back (game->medal_awarded_to_army.connect
583                          (method(on_medal_awarded_to_army)));
584   connections.push_back (game->hero_gains_level.connect
585                          (method(on_hero_gains_level)));
586   connections.push_back (game->game_loaded.connect (method(on_game_loaded)));
587   connections.push_back (game->game_over.connect (method(on_game_over)));
588   connections.push_back (game->player_died.connect (method(on_player_died)));
589   connections.push_back (game->advice_asked.connect (method(on_advice_asked)));
590   connections.push_back (game->sunk_ships.connect
591                          (sigc::hide<0>(method(on_ships_sunk))));
592   connections.push_back (game->bags_picked_up.connect (method(on_bags_picked_up)));
593   connections.push_back (game->mp_added_to_hero_stack.connect
594                          (method(on_mp_added_to_hero_stack)));
595   connections.push_back (game->worms_killed.connect (method(on_worms_killed)));
596   connections.push_back (game->bridge_burned.connect (method(on_bridge_burned)));
597   connections.push_back (game->keeper_captured.connect
598                          (method(on_keeper_captured)));
599   connections.push_back (game->monster_summoned.connect
600                          (method(on_monster_summoned)));
601   connections.push_back (game->stole_gold.connect (method(on_gold_stolen)));
602   connections.push_back (game->stack_moves.connect (method(on_stack_moves)));
603   connections.push_back (game->select_item.connect (method(on_select_item)));
604   connections.push_back (game->select_item_victim_player.connect
605                          (method(on_select_item_victim_player)));
606   connections.push_back (game->select_city_to_use_item_on.connect
607                          (method(on_select_city_to_use_item_on)));
608   connections.push_back (game->city_diseased.connect
609                          (sigc::hide<0>(method(on_city_diseased))));
610   connections.push_back (game->city_defended.connect
611                          (sigc::hide<0>(method(on_city_defended))));
612   connections.push_back (game->city_persuaded.connect
613                          (sigc::hide<0>(method(on_city_persuaded))));
614   connections.push_back (game->stack_teleported.connect
615                          (method(on_stack_teleported)));
616   connections.push_back (game->popup_stack_actions_menu.connect
617                          (method(on_popup_stack_menu)));
618 
619   // misc callbacks
620   QuestsManager *q = QuestsManager::getInstance();
621   connections.push_back (q->quest_completed.connect (method(on_quest_completed)));
622   connections.push_back (q->quest_expired.connect (method(on_quest_expired)));
623   if (game)
624     connections.push_back (game->get_bigmap().cursor_changed.connect
625                            (method(on_bigmap_cursor_changed)));
626 
627   connections.push_back (game->remote_next_player_turn.connect
628                          (method(on_remote_next_player_turn)));
629   connections.push_back (game->pointing_at_new_tile.connect (method(on_pointing_at_new_tile)));
630 }
631 
show_city_production_report(bool destitute)632 void GameWindow::show_city_production_report (bool destitute)
633 {
634   if (!destitute)
635     return;
636   ReportDialog d(*window, Playerlist::getActiveplayer(), ReportDialog::PRODUCTION);
637   d.run();
638   d.hide();
639 }
640 
setup_game(GameScenario * game_scenario,NextTurn * nextTurn)641 bool GameWindow::setup_game(GameScenario *game_scenario, NextTurn *nextTurn)
642 {
643   status_box->clear_selected_stack();
644 
645   Snd::getInstance()->halt(true);
646   Snd::getInstance()->enableBackground();
647 
648   if (game)
649     delete game;
650   game = new Game(game_scenario, nextTurn);
651 
652   set_default_bigmap_zoom ();
653 
654   game_button_box->setup_signals(game);
655 
656   status_box->stack_composition_modified.connect
657       (sigc::mem_fun(game, &Game::recalculate_moves_for_stack));
658   status_box->stack_tile_group_toggle.connect (method(on_group_stack_toggled));
659   show_shield_turn();
660       smallmap_image->set_size_request(game->get_smallmap().get_width(),
661                                        game->get_smallmap().get_height());
662   while (g_main_context_iteration(NULL, FALSE)); //doEvents
663 
664   return true;
665 }
666 
on_group_stack_toggled(bool lock)667 void GameWindow::on_group_stack_toggled(bool lock)
668 {
669   game->get_bigmap().set_input_locked(lock);
670 }
671 
on_delete_event()672 bool GameWindow::on_delete_event()
673 {
674   on_quit_activated();
675 
676   return true;
677 }
678 
on_bigmap_mouse_button_event(GdkEventButton * e)679 bool GameWindow::on_bigmap_mouse_button_event(GdkEventButton *e)
680 {
681   if (e->type != GDK_BUTTON_PRESS && e->type != GDK_BUTTON_RELEASE)
682     return true;	// useless event
683 
684   if (game)
685     {
686       button_event = e;
687       game->get_bigmap().mouse_button_event(to_input_event(e));
688     }
689 
690   return true;
691 }
692 
on_bigmap_mouse_motion_event(GdkEventMotion * e)693 bool GameWindow::on_bigmap_mouse_motion_event(GdkEventMotion *e)
694 {
695   static guint prev = 0;
696   if (game)
697     {
698       gint delta = e->time - prev;
699       if (delta > 40 || delta < 0)
700 	{
701 	  game->get_bigmap().mouse_motion_event(to_input_event(e));
702 	  bigmap_image->grab_focus();
703 	  prev = e->time;
704 	}
705     }
706   return true;
707 }
708 
on_bigmap_cursor_changed(ImageCache::CursorType cursor)709 void GameWindow::on_bigmap_cursor_changed(ImageCache::CursorType cursor)
710 {
711   if (cursor == ImageCache::POINTER)
712       bigmap_image->get_window()->set_cursor ();
713   else
714     {
715       bigmap_image->get_window()->set_cursor
716         (Gdk::Cursor::create
717          (Gdk::Display::get_default(),
718           ImageCache::getInstance()->getCursorPic
719           (cursor,
720            FontSize::getInstance ()->get_height ())->to_pixbuf(), 4, 4));
721     }
722 }
723 
on_bigmap_key_event(GdkEventKey * e)724 bool GameWindow::on_bigmap_key_event(GdkEventKey *e)
725 {
726   if (e->keyval == GDK_KEY_Shift_L || e->keyval == GDK_KEY_Shift_R)
727     game->get_bigmap().set_shift_key_down (e->type == GDK_KEY_PRESS);
728   if (e->keyval == GDK_KEY_Control_L || e->keyval == GDK_KEY_Control_R)
729     game->get_bigmap().set_control_key_down (e->type == GDK_KEY_PRESS);
730 
731   return true;
732 }
733 
on_smallmap_mouse_button_event(GdkEventButton * e)734 bool GameWindow::on_smallmap_mouse_button_event(GdkEventButton *e)
735 {
736   if (e->type != GDK_BUTTON_PRESS && e->type != GDK_BUTTON_RELEASE)
737     return true;	// useless event
738 
739   if (game)
740     game->get_smallmap().mouse_button_event(to_input_event(e));
741 
742   return true;
743 }
744 
on_smallmap_mouse_motion_event(GdkEventMotion * e)745 bool GameWindow::on_smallmap_mouse_motion_event(GdkEventMotion *e)
746 {
747   static guint prev = 0;
748   if (game)
749     {
750       gint delta = e->time - prev;
751       if (delta > 100 || delta < 0)
752 	{
753 	  game->get_smallmap().mouse_motion_event(to_input_event(e));
754 	  prev = e->time;
755 	}
756 
757     }
758 
759   return true;
760 }
761 
get_default_magnifying_glass_hotspot(int * hotspot_x,int * hotspot_y)762 void GameWindow::get_default_magnifying_glass_hotspot (int *hotspot_x, int *hotspot_y)
763 {
764   PixMask *p =
765     ImageCache::getInstance()->getCursorPic
766     (ImageCache::MAGNIFYING_GLASS,
767      FontSize::getInstance ()->get_height ());
768 
769   double x = p->get_width () * (8.0/11.0);
770   double y = p->get_height () * (5.0/11.0);
771 
772   *hotspot_x = int(x);
773   *hotspot_y = int(y);
774 }
775 
on_mouse_entered_smallmap()776 bool GameWindow::on_mouse_entered_smallmap()
777 {
778   static int hotspot_x = -1, hotspot_y = -1;
779   if (hotspot_x == -1 && hotspot_y == -1)
780     get_default_magnifying_glass_hotspot (&hotspot_x, &hotspot_y);
781   map_eventbox->get_window()->set_cursor
782     (Gdk::Cursor::create (Gdk::Display::get_default(),
783                           ImageCache::getInstance()->getCursorPic
784                           (ImageCache::MAGNIFYING_GLASS,
785                            FontSize::getInstance ()->get_height ())->to_pixbuf(),
786                           hotspot_x, hotspot_y));
787   return true;
788 }
789 
on_bigmap_surface_changed(Gtk::Allocation box)790 void GameWindow::on_bigmap_surface_changed(Gtk::Allocation box)
791 {
792   if (game)
793     {
794       if (box.get_width() != last_box.get_width() ||
795           box.get_height() != last_box.get_height())
796         {
797           game->get_bigmap().screen_size_changed(bigmap_image->get_allocation());
798           game->redraw();
799         }
800       last_box = box;
801     }
802 }
803 
on_load_game_activated()804 void GameWindow::on_load_game_activated()
805 {
806   Gtk::FileChooserDialog chooser(*window, _("Choose Game to Load"));
807   Glib::RefPtr<Gtk::FileFilter> sav_filter = Gtk::FileFilter::create();
808   sav_filter->set_name(_("LordsAWar Saved Games (*.sav)"));
809   sav_filter->add_pattern("*" + SAVE_EXT);
810   chooser.add_filter(sav_filter);
811   chooser.set_current_folder(Configuration::s_savePath);
812 
813   chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
814   chooser.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
815   chooser.set_default_response(Gtk::RESPONSE_ACCEPT);
816 
817   chooser.show_all();
818   int res = chooser.run();
819   chooser.hide();
820   while (g_main_context_iteration(NULL, FALSE)); //doEvents
821 
822   if (res == Gtk::RESPONSE_ACCEPT)
823     {
824       Glib::ustring filename = chooser.get_filename();
825       current_save_filename = filename;
826       if (filename == File::getSaveFile("autosave" + SAVE_EXT))
827 	game->inhibitAutosaveRemoval(true);
828       d_load_filename = filename;
829       stop_game("load-game");
830       //now look at on_game_stopped.
831     }
832 }
833 
on_save_game_activated()834 void GameWindow::on_save_game_activated()
835 {
836   if (current_save_filename.empty())
837     on_save_game_as_activated();
838   else
839     {
840       if (game)
841 	{
842 	  bool success = game->saveGame(current_save_filename);
843 	  if (!success)
844             {
845               TimedMessageDialog dialog(*window, _("Game was not saved!"), 0);
846               dialog.run_and_hide();
847             }
848 	}
849     }
850 }
851 
on_save_game_as_activated()852 void GameWindow::on_save_game_as_activated()
853 {
854   Gtk::FileChooserDialog chooser(*window, _("Choose a Name"),
855 				 Gtk::FILE_CHOOSER_ACTION_SAVE);
856   Glib::RefPtr<Gtk::FileFilter> sav_filter = Gtk::FileFilter::create();
857   sav_filter->set_name(_("LordsAWar Saved Games (*.sav)"));
858   sav_filter->add_pattern("*" + SAVE_EXT);
859   chooser.add_filter(sav_filter);
860   chooser.set_current_folder(Configuration::s_savePath);
861 
862   chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
863   chooser.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
864   chooser.set_default_response(Gtk::RESPONSE_ACCEPT);
865 
866   chooser.show_all();
867   int res = chooser.run();
868   chooser.hide();
869 
870   if (res == Gtk::RESPONSE_ACCEPT)
871     {
872       Glib::ustring filename = chooser.get_filename();
873 
874       current_save_filename = filename;
875 
876       if (game)
877 	{
878 	  bool success = game->saveGame(current_save_filename);
879 	  if (!success)
880             {
881               TimedMessageDialog dialog(*window, _("Error saving game!"), 0);
882               dialog.run_and_hide();
883             }
884 	}
885     }
886 }
887 
on_new_game_activated()888 void GameWindow::on_new_game_activated()
889 {
890   LwDialog dialog(*window, "game-quit-dialog.ui");
891   int response = dialog.run_and_hide();
892   if (response == Gtk::RESPONSE_ACCEPT) //end the game
893     stop_game("new");
894 }
895 
on_quit_activated()896 void GameWindow::on_quit_activated()
897 {
898   if (fullscreen_menuitem->get_active())
899     {
900       window->unfullscreen ();
901       window->resize (unmaximized_box.get_width (),
902                       unmaximized_box.get_height ());
903     }
904   if (window->is_maximized ())
905     window->unmaximize ();
906   LwDialog dialog(*window, "game-quit-dialog.ui");
907   int response = dialog.run_and_hide();
908   if (response == Gtk::RESPONSE_ACCEPT) //end the game
909     stop_game("quit");
910 }
911 
on_game_stopped()912 void GameWindow::on_game_stopped()
913 {
914   if (stop_action == "quit")
915     {
916       if (game)
917 	{
918 	  delete game;
919 	  game = NULL;
920 	}
921       game_ended.emit();
922     }
923   else if (stop_action == "new")
924     {
925       if (game)
926 	{
927 	  delete game;
928 	  game = NULL;
929 	}
930       game_ended_start_new.emit();
931     }
932   else if (stop_action == "game-over")
933     {
934       if (game_winner)
935         {
936           if (game_winner->getType() != Player::HUMAN)
937             {
938               if (game)
939                 {
940                   delete game;
941                   game = NULL;
942                 }
943               game_ended.emit();
944             }
945           else
946             {
947               //we need to keep the game object around
948               //so that we can give out some cheese
949               give_some_cheese(game_winner);
950             }
951         }
952       else
953         {
954           if (game)
955             {
956               delete game;
957               game = NULL;
958             }
959           game_ended.emit();
960         }
961     }
962   else if (stop_action == "load-game")
963     {
964       if (game)
965 	{
966 	  delete game;
967 	  game = NULL;
968 	}
969       bool broken = false;
970 
971       LoadProgressWindow *p = new LoadProgressWindow (window);
972       GameScenario::load_tick.connect
973         (sigc::mem_fun (p, &LoadProgressWindow::tick_progress));
974       GameScenario::load_finish.connect
975         (sigc::mem_fun (p, &LoadProgressWindow::finish_progress));
976       p->run ();
977       GameScenario* game_scenario = new GameScenario(d_load_filename, broken);
978       p->hide ();
979 
980       if (broken)
981 	{
982 	  on_message_requested(_("Corrupted saved game file."));
983 	  game_ended.emit();
984 	  return;
985 	}
986       if (game_scenario->getPlayMode() == GameScenario::HOTSEAT)
987 	load_game(game_scenario, new NextTurnHotseat());
988       else if (game_scenario->getPlayMode() == GameScenario::NETWORKED)
989         {
990           NewNetworkGameDialog nngd(*get_window(), true);
991           bool retval = nngd.run();
992           nngd.hide();
993           hide();
994           if (retval)
995             {
996              load_hosted_network_game.emit
997                 (d_load_filename, LORDSAWAR_PORT, nngd.getProfile(),
998                  nngd.isAdvertised(), nngd.isRemotelyHosted());
999             }
1000         }
1001     }
1002 }
1003 
on_quests_activated()1004 void GameWindow::on_quests_activated()
1005 {
1006   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1007     return;
1008   Player *player = Playerlist::getActiveplayer();
1009   std::vector<Quest*> quests
1010     = QuestsManager::getInstance()->getPlayerQuests(player);
1011   Stack *s = player->getActivestack();
1012   Hero *hero = NULL;
1013   if (s)
1014     hero = s->getFirstHeroWithAQuest();
1015   QuestReportDialog d(*window, quests, hero);
1016   d.run();
1017   d.hide();
1018   return;
1019 }
1020 
on_fullscreen_activated()1021 void GameWindow::on_fullscreen_activated()
1022 {
1023   if (fullscreen_menuitem->get_active())
1024     window->fullscreen();
1025   else
1026     {
1027       window->unfullscreen();
1028       window->resize (unmaximized_box.get_width (),
1029                       unmaximized_box.get_height ());
1030     }
1031 }
1032 
on_signpost_activated()1033 void GameWindow::on_signpost_activated()
1034 {
1035   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1036     return;
1037   Stack *stack = Playerlist::getActiveplayer()->getActivestack();
1038   if (!stack)
1039     return;
1040   Signpost *s = GameMap::getSignpost(stack->getPos());
1041   if (!s)
1042     return;
1043   LwDialog dialog(*window, "signpost-change-dialog.ui");
1044   dialog.set_title(_("Signpost"));
1045   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1046   Gtk::Label *l;
1047   xml->get_widget("label", l);
1048   l->set_text(_("Change the message on this sign:"));
1049   Gtk::Entry *e;
1050   xml->get_widget("message_entry", e);
1051   e->set_text(s->getName());
1052   e->set_activates_default(true);
1053   int response = dialog.run_and_hide();
1054 
1055   if (response == Gtk::RESPONSE_ACCEPT)
1056     Playerlist::getActiveplayer()->signpostChange(s,
1057                                                   String::utrim(e->get_text()));
1058   return;
1059 }
1060 
1061 
on_stack_info_activated()1062 void GameWindow::on_stack_info_activated()
1063 {
1064   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1065     return;
1066   StackInfoDialog d(*window, status_box->get_currently_selected_stack()->getPos());
1067   d.run_and_hide();
1068   Stack *s = d.get_selected_stack();
1069   status_box->on_stack_info_changed(s);
1070 }
1071 
on_disband_activated()1072 void GameWindow::on_disband_activated()
1073 {
1074   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1075     return;
1076   Stack *stack = Playerlist::getActiveplayer()->getActivestack();
1077   LwDialog dialog(*window, "disband-stack-dialog.ui");
1078   dialog.set_title(_("Disband"));
1079   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1080   Gtk::Label *l;
1081   xml->get_widget("label", l);
1082 
1083   std::vector<guint32> heroes;
1084   stack->getHeroes(heroes);
1085   Glib::ustring s = _("Are you sure you want to disband this group?");
1086   if (heroes.size() > 0)
1087     {
1088       s += "\n";
1089       s += String::ucompose( ngettext("(It contains %1 hero).",
1090 				      "(It contains %1 heroes).",
1091 				      heroes.size()), heroes.size());
1092     }
1093   l->set_text(s);
1094   int response = dialog.run_and_hide();
1095 
1096   if (response == Gtk::RESPONSE_ACCEPT) //disband the active stack
1097     Playerlist::getActiveplayer()->stackDisband(NULL);
1098 
1099   return;
1100 }
1101 
on_resignation_completed()1102 void GameWindow::on_resignation_completed()
1103 {
1104   LwDialog dialog(*window, "player-resign-completed-dialog.ui");
1105   dialog.run_and_hide();
1106   return;
1107 }
1108 
on_resign_activated()1109 void GameWindow::on_resign_activated()
1110 {
1111   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1112     return;
1113 
1114   LwDialog dialog(*window, "player-resign-dialog.ui");
1115   dialog.set_title(_("Resign"));
1116   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1117   Gtk::Label *l;
1118   xml->get_widget("label", l);
1119   l->set_text(_("Are you sure you want to resign?"));
1120   int response = dialog.run_and_hide();
1121   if (response == Gtk::RESPONSE_ACCEPT) //disband all stacks, raze all cities
1122     {
1123       Playerlist::getActiveplayer()->resign();
1124       on_resignation_completed();
1125     }
1126   return;
1127 }
1128 
on_vectoring_activated()1129 void GameWindow::on_vectoring_activated()
1130 {
1131   City *city;
1132   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1133     return;
1134 
1135   if (status_box->get_currently_selected_stack())
1136     {
1137       Vector<int> pos = status_box->get_currently_selected_stack()->getPos();
1138       city = Citylist::getInstance()->getNearestVisibleFriendlyCity(pos);
1139     }
1140   else
1141     city = Playerlist::getActiveplayer()->getFirstCity();
1142 
1143   if (!city)
1144     return;
1145   bool see_all = true;
1146   DestinationDialog d(*window, city, &see_all);
1147   d.run();
1148   d.hide();
1149   return;
1150 }
1151 
on_production_activated()1152 void GameWindow::on_production_activated()
1153 {
1154   City *city;
1155   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1156     return;
1157 
1158   if (status_box->get_currently_selected_stack())
1159     {
1160       Vector<int> pos = status_box->get_currently_selected_stack()->getPos();
1161       city = Citylist::getInstance()->getNearestVisibleFriendlyCity(pos);
1162     }
1163   else
1164     city = Playerlist::getActiveplayer()->getFirstCity();
1165 
1166   if (!city)
1167     return;
1168 
1169   on_city_visited(city);
1170   return;
1171 }
1172 
zoom(double scale)1173 void GameWindow::zoom (double scale)
1174 {
1175   if (scale < minimum_zoom_scale)
1176     scale = minimum_zoom_scale;
1177   zoom_in_menuitem->set_sensitive (scale > minimum_zoom_scale);
1178   if (scale > maximum_zoom_scale)
1179     scale = maximum_zoom_scale;
1180   zoom_out_menuitem->set_sensitive (scale < maximum_zoom_scale);
1181   GameMap::getInstance()->getTileset()->set_scale (scale);
1182   GameMap::getInstance()->getCityset()->set_scale (scale);
1183   for (auto& i : *Playerlist::getInstance())
1184     Armysetlist::getInstance()->get((*i).getArmyset())->set_scale (scale);
1185   game->get_bigmap().screen_size_changed(bigmap_image->get_allocation());
1186   game->redraw();
1187 }
1188 
on_zoom_in_activated()1189 void GameWindow::on_zoom_in_activated()
1190 {
1191   zoom (GameMap::getInstance()->getTileset()->get_scale () + ZOOM_STEP);
1192 }
1193 
on_zoom_out_activated()1194 void GameWindow::on_zoom_out_activated()
1195 {
1196   zoom (GameMap::getInstance()->getTileset()->get_scale () - ZOOM_STEP);
1197 }
1198 
on_preferences_activated()1199 void GameWindow::on_preferences_activated()
1200 {
1201   Player *current = Playerlist::getInstance()->getActiveplayer();
1202   bool readonly = false;
1203   if (game->getScenario()->getPlayMode() == GameScenario::NETWORKED)
1204     readonly = true;
1205   PreferencesDialog d(*window, readonly);
1206   d.run(game);
1207   d.hide();
1208   game->get_bigmap().set_control_key_down (false);
1209   if (current != Playerlist::getInstance()->getActiveplayer())
1210     game->end_turn();
1211 }
1212 
on_group_ungroup_activated()1213 void GameWindow::on_group_ungroup_activated()
1214 {
1215   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1216     return;
1217   status_box->toggle_group_ungroup();
1218 }
1219 
on_fight_order_activated()1220 void GameWindow::on_fight_order_activated()
1221 {
1222   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1223     return;
1224   FightOrderDialog d(*window, Playerlist::getActiveplayer());
1225   d.run();
1226   d.hide();
1227 }
1228 
on_levels_activated()1229 void GameWindow::on_levels_activated()
1230 {
1231   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1232     return;
1233   HeroLevelsDialog d(*window, Playerlist::getActiveplayer());
1234   d.run_and_hide();
1235 }
1236 
on_ruin_report_activated()1237 void GameWindow::on_ruin_report_activated()
1238 {
1239   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1240     return;
1241   Vector<int> pos;
1242   pos.x = 0;
1243   pos.y = 0;
1244   if (status_box->get_currently_selected_stack())
1245     pos = status_box->get_currently_selected_stack()->getPos();
1246 
1247   if (Templelist::getInstance()->size() == 0 &&
1248       Ruinlist::getInstance()->size() == 0)
1249     {
1250       TimedMessageDialog dialog(*window, _("No ruins or temples to show!"), 30);
1251       dialog.run_and_hide();
1252       return;
1253     }
1254   RuinReportDialog d(*window, pos);
1255   d.run();
1256   d.hide();
1257 }
1258 
on_army_bonus_activated()1259 void GameWindow::on_army_bonus_activated()
1260 {
1261   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1262     return;
1263   ArmyBonusDialog d(*window, Playerlist::getActiveplayer());
1264   d.run_and_hide();
1265 }
1266 
on_item_bonus_activated()1267 void GameWindow::on_item_bonus_activated()
1268 {
1269   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1270     return;
1271   ItemBonusDialog d(*window);
1272   d.run_and_hide();
1273 }
1274 
on_army_report_activated()1275 void GameWindow::on_army_report_activated()
1276 {
1277   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1278     return;
1279   ReportDialog d(*window, Playerlist::getActiveplayer(), ReportDialog::ARMY);
1280   d.run();
1281   d.hide();
1282 }
1283 
on_item_report_activated()1284 void GameWindow::on_item_report_activated()
1285 {
1286   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1287     return;
1288   std::list<Stack*> stacks = Playerlist::getActiveplayer()->getStacksWithItems();
1289   std::list<MapBackpack*> bags = GameMap::getInstance()->getBackpacks();
1290   ItemReportDialog d(*window, stacks, bags);
1291   d.run();
1292   d.hide();
1293 }
1294 
on_city_report_activated()1295 void GameWindow::on_city_report_activated()
1296 {
1297   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1298     return;
1299   ReportDialog d(*window, Playerlist::getActiveplayer(), ReportDialog::CITY);
1300   d.run();
1301   d.hide();
1302 }
1303 
on_gold_report_activated()1304 void GameWindow::on_gold_report_activated()
1305 {
1306   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1307     return;
1308   ReportDialog d(*window, Playerlist::getActiveplayer(), ReportDialog::GOLD);
1309   d.run();
1310   d.hide();
1311 }
1312 
on_production_report_activated()1313 void GameWindow::on_production_report_activated()
1314 {
1315   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1316     return;
1317   ReportDialog d(*window, Playerlist::getActiveplayer(), ReportDialog::PRODUCTION);
1318   d.run();
1319   d.hide();
1320 }
1321 
on_winning_report_activated()1322 void GameWindow::on_winning_report_activated()
1323 {
1324   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN &&
1325       !Playerlist::getInstance()->getWinningPlayer())
1326     return;
1327   ReportDialog d(*window, Playerlist::getActiveplayer(), ReportDialog::WINNING);
1328   d.run();
1329   d.hide();
1330 }
1331 
on_city_history_activated()1332 void GameWindow::on_city_history_activated()
1333 {
1334   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN &&
1335       !Playerlist::getInstance()->getWinningPlayer())
1336     return;
1337   HistoryReportDialog d(*window, Playerlist::getActiveplayer(),
1338 			HistoryReportDialog::CITY);
1339   d.run();
1340   d.hide();
1341 }
1342 
on_ruin_history_activated()1343 void GameWindow::on_ruin_history_activated()
1344 {
1345   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN &&
1346       !Playerlist::getInstance()->getWinningPlayer())
1347     return;
1348   HistoryReportDialog d(*window, Playerlist::getActiveplayer(),
1349 			HistoryReportDialog::RUIN);
1350   d.run();
1351   d.hide();
1352 }
1353 
on_event_history_activated()1354 void GameWindow::on_event_history_activated()
1355 {
1356   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN &&
1357       !Playerlist::getInstance()->getWinningPlayer())
1358     return;
1359   HistoryReportDialog d(*window, Playerlist::getActiveplayer(),
1360 			HistoryReportDialog::EVENTS);
1361   d.run();
1362   d.hide();
1363 }
1364 
on_gold_history_activated()1365 void GameWindow::on_gold_history_activated()
1366 {
1367   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN &&
1368       !Playerlist::getInstance()->getWinningPlayer())
1369     return;
1370   HistoryReportDialog d(*window ,Playerlist::getActiveplayer(),
1371 			HistoryReportDialog::GOLD);
1372   d.run();
1373   d.hide();
1374 }
1375 
on_winner_history_activated()1376 void GameWindow::on_winner_history_activated()
1377 {
1378   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN &&
1379       !Playerlist::getInstance()->getWinningPlayer())
1380     return;
1381   HistoryReportDialog d(*window, Playerlist::getActiveplayer(),
1382 			HistoryReportDialog::WINNING);
1383   d.run();
1384   d.hide();
1385 }
1386 
on_triumphs_activated()1387 void GameWindow::on_triumphs_activated()
1388 {
1389   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1390     return;
1391   TriumphsDialog d(*window, Playerlist::getActiveplayer());
1392   d.run_and_hide();
1393 }
1394 
on_help_about_activated()1395 void GameWindow::on_help_about_activated()
1396 {
1397   Gtk::AboutDialog* dialog;
1398 
1399   Glib::RefPtr<Gtk::Builder> xml
1400     = Gtk::Builder::create_from_file (File::getGladeFile("about-dialog.ui"));
1401 
1402   xml->get_widget("dialog", dialog);
1403   dialog->set_icon_from_file(File::getVariousFile("castle_icon.png"));
1404   dialog->set_version(PACKAGE_VERSION);
1405   dialog->set_logo(ImageCache::loadMiscImage("castle_icon.png")->to_pixbuf());
1406   dialog->set_transient_for(*window);
1407   dialog->show_all();
1408   dialog->run();
1409   dialog->hide();
1410   delete dialog;
1411 
1412   return;
1413 }
1414 
on_diplomacy_report_activated()1415 void GameWindow::on_diplomacy_report_activated()
1416 {
1417   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1418     return;
1419   if (GameScenario::s_diplomacy == false)
1420     return;
1421   DiplomacyReportDialog d(*window, Playerlist::getActiveplayer());
1422   d.run_and_hide();
1423 }
1424 
on_diplomacy_button_clicked()1425 void GameWindow::on_diplomacy_button_clicked()
1426 {
1427   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1428     return;
1429   DiplomacyDialog d(*window, Playerlist::getActiveplayer());
1430   d.run_and_hide();
1431 }
1432 
stop_game(Glib::ustring action)1433 void GameWindow::stop_game(Glib::ustring action)
1434 {
1435   stop_action = action;
1436   Snd::getInstance()->disableBackground();
1437   if (game)
1438     {
1439       current_save_filename = "";
1440       if (action == "game-over" && game->getScenario()->getPlayMode() == GameScenario::NETWORKED)
1441         give_some_cheese(game_winner);
1442       else
1443         game->stopGame();
1444     }
1445 }
1446 
on_game_over(Player * winner)1447 void GameWindow::on_game_over(Player *winner)
1448 {
1449   LwDialog dialog(*window, "game-over-dialog.ui");
1450   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1451   Gtk::Image *image;
1452   xml->get_widget("image", image);
1453 
1454   image->property_pixbuf() =
1455     ImageCache::getInstance()->getDialogPic
1456     (ImageCache::DIALOG_WINNING,
1457      FontSize::getInstance ()->get_height ())->to_pixbuf();
1458 
1459   Gtk::Label *label;
1460   xml->get_widget("label", label);
1461   Glib::ustring s;
1462   s += String::ucompose(_("Congratulations to %1 for conquering the world!"),
1463 	winner->getName());
1464   label->set_markup("<b>" + s + "</b>");
1465 
1466   dialog.run_and_hide();
1467 
1468   game_winner = winner;
1469   stop_game("game-over");
1470 }
1471 
on_player_died(Player * player)1472 void GameWindow::on_player_died(Player *player)
1473 {
1474   assert(player);
1475 
1476   Glib::ustring s;
1477   s += String::ucompose(_("The rule of %1 has permanently ended!"),
1478 			player->getName());
1479   if (Playerlist::getInstance()->countHumanPlayersAlive() == 0 &&
1480       player->getType() == Player::HUMAN)
1481     {
1482       s += "\n";
1483       s += _("No further human resistance is possible\nbut the battle will continue!");
1484       s += "\n";
1485       s += _("Press `CTRL-P' to stop the war\nand visit the sites of thy old battles.");
1486     }
1487 
1488   TimedMessageDialog dialog(*window, s, FightWindow::s_quick_all ? 3: 30);
1489   dialog.run_and_hide();
1490 }
1491 
on_message_requested(Glib::ustring msg)1492 void GameWindow::on_message_requested(Glib::ustring msg)
1493 {
1494   TimedMessageDialog dialog(*window, msg, 0);
1495   dialog.run_and_hide ();
1496 }
1497 
on_progress_status_changed(Glib::ustring string)1498 void GameWindow::on_progress_status_changed(Glib::ustring string)
1499 {
1500   status_box->set_progress_label(string);
1501 }
1502 
on_progress_changed()1503 void GameWindow::on_progress_changed()
1504 {
1505   status_box->pulse();
1506 }
1507 
on_sidebar_stats_changed(SidebarStats s)1508 void GameWindow::on_sidebar_stats_changed(SidebarStats s)
1509 {
1510   status_box->update_sidebar_stats(s);
1511 
1512   turn_label->set_markup(String::ucompose("<b>%1 %2</b>",
1513                                           _("Turn"), s.turns));
1514 }
1515 
on_bigmap_changed(Cairo::RefPtr<Cairo::Surface> map)1516 void GameWindow::on_bigmap_changed(Cairo::RefPtr<Cairo::Surface> map)
1517 {
1518   Gtk::Allocation old = game->get_bigmap().get_allocation();
1519   int width = bigmap_image->get_allocated_width();
1520   int height = bigmap_image->get_allocated_height();
1521   Glib::RefPtr<Gdk::Pixbuf> pixbuf =
1522     Gdk::Pixbuf::create(map, 0, 0, std::min(width, old.get_width()), std::min(height, old.get_height()));
1523   bigmap_image->property_pixbuf() = pixbuf;
1524   bigmap_image->queue_draw();
1525   //while (g_main_context_iteration(NULL, FALSE)); //doEvents
1526   //enabling this makes dragging the smallmap freeze
1527 }
1528 
on_smallmap_changed(Cairo::RefPtr<Cairo::Surface> map)1529 void GameWindow::on_smallmap_changed(Cairo::RefPtr<Cairo::Surface> map)
1530 {
1531   Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(map);
1532   double x1, x2, y1, y2;
1533   cr->get_clip_extents (x1, y1, x2, y2);
1534   int width = x2 - x1;
1535   int height = y2 - y1;
1536 
1537   if (smallmap_image->get_allocated_width() != width ||
1538       smallmap_image->get_allocated_height() != height)
1539     smallmap_image->set_size_request(width, height);
1540   Glib::RefPtr<Gdk::Pixbuf> pixbuf =
1541     Gdk::Pixbuf::create(map, 0, 0,
1542                         smallmap_image->get_allocated_width(),
1543                         smallmap_image->get_allocated_height());
1544   smallmap_image->property_pixbuf() = pixbuf;
1545 }
1546 
on_smallmap_slid()1547 void GameWindow::on_smallmap_slid ()
1548 {
1549   on_smallmap_changed(game->get_smallmap().get_surface());
1550   while (g_main_context_iteration(NULL, FALSE)); //doEvents
1551 }
1552 
on_city_tip_changed(City * city,MapTipPosition mpos)1553 void GameWindow::on_city_tip_changed(City *city, MapTipPosition mpos)
1554 {
1555   if (city == NULL)
1556     {
1557       delete city_info_tip;
1558       city_info_tip = NULL;
1559     }
1560   else
1561     {
1562       city_info_tip = new CityInfoTip(bigmap_image, mpos, city);
1563     }
1564 }
1565 
on_stack_tip_changed(StackTile * stile,MapTipPosition mpos)1566 void GameWindow::on_stack_tip_changed(StackTile *stile, MapTipPosition mpos)
1567 {
1568   if (stile == NULL)
1569     {
1570       delete stack_info_tip;
1571       stack_info_tip = NULL;
1572     }
1573   else
1574     {
1575       stack_info_tip = new StackInfoTip(bigmap_image, mpos, stile);
1576     }
1577 }
1578 
on_bigmap_tip_changed(Glib::ustring tip,MapTipPosition pos,bool timeout)1579 void GameWindow::on_bigmap_tip_changed(Glib::ustring tip, MapTipPosition pos, bool timeout)
1580 {
1581   if (tip.empty())
1582     hide_map_tip();
1583   else
1584     show_map_tip(tip, pos, timeout);
1585 }
1586 
show_map_tip(Glib::ustring msg,MapTipPosition pos,bool timeout)1587 void GameWindow::show_map_tip(Glib::ustring msg, MapTipPosition pos, bool timeout)
1588 {
1589   map_tip_timer.disconnect ();
1590   // init the map tip
1591   if (map_tip != NULL)
1592     delete map_tip;
1593   map_tip = new Gtk::Window(Gtk::WINDOW_POPUP);
1594 
1595   map_tip->add_events (Gdk::POINTER_MOTION_MASK);
1596   map_tip->signal_motion_notify_event().connect (sigc::hide(method(hide_map_tip)));
1597   map_tip->set_transient_for (*window);
1598   Gtk::Frame *f = manage(new Gtk::Frame);
1599   f->property_shadow_type() = Gtk::SHADOW_ETCHED_OUT;
1600 
1601   Gtk::Label *l = manage(new Gtk::Label);
1602   l->set_justify(Gtk::JUSTIFY_CENTER);
1603   l->set_padding(6, 6);
1604   l->set_text(msg);
1605   f->add(*l);
1606 
1607   map_tip->add(*f);
1608   f->show_all();
1609 
1610   // get screen position
1611   Vector<int> p;
1612   bigmap_image->get_window()->get_origin(p.x, p.y);
1613   p += pos.pos;
1614 
1615   Vector<int> size(0, 0);
1616   map_tip->get_size(size.x, size.y);
1617 
1618   switch (pos.justification)
1619     {
1620     case MapTipPosition::LEFT:
1621       map_tip->set_gravity(Gdk::GRAVITY_NORTH_WEST);
1622       break;
1623     case MapTipPosition::RIGHT:
1624       map_tip->set_gravity(Gdk::GRAVITY_NORTH_EAST);
1625       p.x -= size.x;
1626       break;
1627     case MapTipPosition::TOP:
1628       map_tip->set_gravity(Gdk::GRAVITY_NORTH_WEST);
1629       break;
1630     case MapTipPosition::BOTTOM:
1631       map_tip->set_gravity(Gdk::GRAVITY_SOUTH_WEST);
1632       p.y -= size.y;
1633       break;
1634     }
1635 
1636   // and action
1637   map_tip->move(p.x, p.y);
1638   map_tip->show();
1639   if (timeout)
1640     {
1641       map_tip_timer = Glib::signal_timeout().connect (method(hide_map_tip), 1400);
1642     }
1643 }
1644 
hide_map_tip()1645 bool GameWindow::hide_map_tip()
1646 {
1647   map_tip_timer.disconnect ();
1648   if (map_tip != NULL)
1649     {
1650       delete map_tip;
1651       map_tip = NULL;
1652     }
1653   return true;
1654 }
1655 
on_sage_visited(Ruin * ruin,Sage * sage,Stack * stack)1656 Reward* GameWindow::on_sage_visited (Ruin *ruin, Sage *sage, Stack *stack)
1657 {
1658   SageDialog d(*window, sage, static_cast<Hero*>(stack->getFirstHero()), ruin);
1659   Reward *reward = d.run();
1660   d.hide();
1661   return reward;
1662 }
1663 
on_ruin_rewarded(Reward_Ruin * reward)1664 void GameWindow::on_ruin_rewarded (Reward_Ruin *reward)
1665 {
1666   RuinRewardedDialog d(*window, reward);
1667   d.run();
1668   d.hide();
1669 }
1670 
on_ruin_searched(Ruin * ruin,Stack * stack,Reward * reward)1671 void GameWindow::on_ruin_searched(Ruin *ruin, Stack *stack, Reward *reward)
1672 {
1673   if (reward->getType() == Reward::RUIN && ruin->getType() == Ruin::SAGE)
1674     return on_ruin_rewarded(static_cast<Reward_Ruin*>(reward));
1675   LwDialog dialog(*window, "ruin-searched-dialog.ui");
1676   dialog.set_title(ruin->getName());
1677   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1678 
1679   Gtk::Label *label;
1680   xml->get_widget("label", label);
1681 
1682   Glib::ustring s = label->get_text();
1683   s += "\n\n";
1684   Glib::ustring hero = stack->getFirstHero()->getName();
1685   switch (reward->getType())
1686     {
1687     case Reward::GOLD:
1688         {
1689           Reward_Gold *gold = dynamic_cast<Reward_Gold*>(reward);
1690           if (ruin->hasSage())
1691             s += String::ucompose(_("%1 is given %2 gold pieces."), hero,
1692                                   gold->getGold());
1693           else
1694             s += String::ucompose(_("%1 finds %2 gold pieces."), hero,
1695                                   gold->getGold());
1696         }
1697       break;
1698     case Reward::ALLIES:
1699         {
1700           Reward_Allies *allies = dynamic_cast<Reward_Allies*>(reward);
1701           if (ruin->hasSage())
1702             s += String::ucompose(_("%1 is given %2 allies!"), hero,
1703                                   allies->getNoOfAllies());
1704           else
1705             s += String::ucompose(_("%1 finds %2 allies!"), hero,
1706                                   allies->getNoOfAllies());
1707         }
1708       break;
1709     case Reward::ITEM:
1710         {
1711           Reward_Item *item = dynamic_cast<Reward_Item*>(reward);
1712           if (ruin->hasSage())
1713             s += String::ucompose(_("%1 is given the %2!"), hero,
1714                                   item->getItem()->getName());
1715           else
1716             s += String::ucompose(_("%1 finds the %2!"), hero,
1717                                   item->getItem()->getName());
1718         }
1719       break;
1720     case Reward::MAP:
1721         {
1722           Reward_Map *map = dynamic_cast<Reward_Map*>(reward);
1723           if (ruin->hasSage())
1724             s += String::ucompose(_("%1 is given a %2!"), hero, map->getName());
1725           else
1726             s += String::ucompose(_("%1 finds a %2!"), hero, map->getName());
1727         }
1728       break;
1729     case Reward::RUIN:
1730       //ruins are not populated with ruin-rewards.
1731       break;
1732     }
1733 
1734   label->set_text(s);
1735   dialog.run_and_hide();
1736 }
1737 
on_ruinfight_started(Stack * attackers,Keeper * keeper)1738 void GameWindow::on_ruinfight_started(Stack *attackers, Keeper *keeper)
1739 {
1740   LwDialog dialog(*window, "ruinfight-started-dialog.ui");
1741   //so and so encounters a wolf...
1742   dialog.set_title(_("Searching"));
1743   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1744   Gtk::Label *label;
1745   xml->get_widget("label", label);
1746   Glib::ustring s = label->get_text();
1747   s = "\n\n";
1748   s += String::ucompose(_("%1 encounters %2..."),
1749                         attackers->getFirstHero()->getName(),
1750                         keeper->getName());
1751   label->set_text(s);
1752   dialog.run_and_hide();
1753 }
1754 
on_ruinfight_finished(Fight::Result result)1755 void GameWindow::on_ruinfight_finished(Fight::Result result)
1756 {
1757   LwDialog dialog(*window, "ruinfight-finished-dialog.ui");
1758   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1759   if (result == Fight::ATTACKER_WON)
1760     dialog.set_title(_("Hero Victorious"));
1761   else
1762     dialog.set_title(_("Hero Defeated"));
1763 
1764   Gtk::Label *label;
1765   xml->get_widget("label", label);
1766   Glib::ustring s = label->get_text();
1767   s = "\n\n";
1768   if (result == Fight::ATTACKER_WON)
1769     s += _("...and is victorious!");
1770   else
1771     s += _("...and is slain by it!");
1772   label->set_text(s);
1773 
1774   Gtk::Image *image;
1775   xml->get_widget("image", image);
1776   if (result == Fight::ATTACKER_WON)
1777     image->property_pixbuf() =
1778       ImageCache::getInstance()->getDialogPic
1779       (ImageCache::DIALOG_RUIN_SUCCESS,
1780        FontSize::getInstance ()->get_height ())->to_pixbuf();
1781   else
1782     image->property_pixbuf() =
1783       ImageCache::getInstance()->getDialogPic
1784       (ImageCache::DIALOG_RUIN_DEFEAT,
1785        FontSize::getInstance ()->get_height ())->to_pixbuf();
1786   image->show();
1787 
1788   dialog.run_and_hide();
1789 }
1790 
on_fight_started(LocationBox box,Fight & fight)1791 void GameWindow::on_fight_started(LocationBox box, Fight &fight)
1792 {
1793   game->get_bigmap().setFighting(box);
1794   game->get_bigmap().draw();
1795   FightWindow d(*window, fight);
1796 
1797   while (g_main_context_iteration(NULL, FALSE)); //doEvents
1798   Glib::usleep (TIMER_BIGMAP_EXPLOSION_DELAY);
1799   d.run(&d_quick_fights);
1800   d.hide();
1801   game->get_bigmap().setFighting(LocationBox(Vector<int>(-1,-1)));
1802   game->get_bigmap().draw();
1803   if (Playerlist::getActiveplayer()->getType() == Player::HUMAN)
1804     d_quick_fights = false;
1805 }
1806 
on_hero_brings_allies(int numAllies)1807 void GameWindow::on_hero_brings_allies (int numAllies)
1808 {
1809   LwDialog dialog(*window, "hero-brings-allies-dialog.ui");
1810   dialog.set_title(_("Hero brings allies!"));
1811   Gtk::Label *label;
1812   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1813   xml->get_widget("label", label);
1814   Glib::ustring s = String::ucompose
1815     (ngettext("The hero brings %1 ally!",
1816               "The hero brings %1 allies!", numAllies), numAllies);
1817   label->set_text(s);
1818   dialog.run_and_hide();
1819 }
1820 
on_hero_offers_service(Player * player,HeroProto * hero,City * city,int gold)1821 bool GameWindow::on_hero_offers_service(Player *player, HeroProto *hero, City *city, int gold)
1822 {
1823   HeroOfferDialog d(*window, player, hero, city, gold);
1824   bool retval = d.run();
1825   d.hide();
1826   return retval;
1827 }
1828 
on_enemy_offers_surrender(int numPlayers)1829 bool GameWindow::on_enemy_offers_surrender(int numPlayers)
1830 {
1831   SurrenderDialog d(*window, numPlayers);
1832   return d.run_and_hide() == Gtk::RESPONSE_ACCEPT;
1833 }
1834 
on_surrender_answered(bool accepted)1835 void GameWindow::on_surrender_answered (bool accepted)
1836 {
1837   if (accepted)
1838     on_message_requested
1839       (_("You graciously and benevolently accept their offer."));
1840   else
1841     {
1842       SurrenderRefusedDialog d(*window);
1843       d.run_and_hide();
1844     }
1845 }
1846 
on_stack_considers_treachery(Player * them)1847 bool GameWindow::on_stack_considers_treachery (Player *them)
1848 {
1849   LwDialog dialog(*window, "treachery-dialog.ui");
1850   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1851   Gtk::Label *label;
1852   xml->get_widget("label", label);
1853   Glib::ustring s = String::ucompose(_("Are you sure you want to attack %1?"),
1854                                      them->getName());
1855   s += "\n";
1856   s += _("Other players may not like this!");
1857   label->set_text(s);
1858   int response = dialog.run_and_hide();
1859   if (response == Gtk::RESPONSE_DELETE_EVENT)
1860     return false;
1861   else if (response == Gtk::RESPONSE_ACCEPT)
1862     return true;
1863   else
1864     return false;
1865 }
1866 
1867 
on_temple_visited(Temple * temple)1868 void GameWindow::on_temple_visited(Temple *temple)
1869 {
1870   RuinReportDialog d(*window, temple->getPos());
1871   d.run();
1872   d.hide();
1873 }
1874 
on_temple_searched(Hero * hero,Temple * temple,int blessCount)1875 bool GameWindow::on_temple_searched(Hero *hero, Temple *temple, int blessCount)
1876 {
1877   QuestsManager *qm = QuestsManager::getInstance();
1878   bool hasHero = hero != NULL;
1879   bool ask_quest = false;
1880 
1881   LwDialog dialog(*window, "temple-visit-dialog.ui");
1882   dialog.set_title(temple->getName());
1883   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
1884   Gtk::Label *l;
1885   Gtk::Button *close_button;
1886   Gtk::Button *accept_button;
1887   xml->get_widget("label", l);
1888   xml->get_widget("close_button", close_button);
1889   xml->get_widget("accept_button", accept_button);
1890 
1891   if (GameScenarioOptions::s_play_with_quests ==
1892       GameParameters::ONE_QUEST_PER_PLAYER)
1893     {
1894       if (qm->getPlayerQuests(Playerlist::getActiveplayer()).size() == 0 &&
1895           hasHero)
1896         ask_quest = true;
1897     }
1898   else if (GameScenarioOptions::s_play_with_quests == GameParameters::ONE_QUEST_PER_HERO)
1899     {
1900       if (hasHero && hero->hasQuest() == false)
1901         ask_quest = true;
1902     }
1903 
1904   Glib::ustring s;
1905   if (blessCount > 0)
1906     s += String::ucompose(
1907 			  ngettext("%1 army has been blessed!",
1908 				   "%1 armies have been blessed!", blessCount), blessCount);
1909   else
1910     s += _("We have already blessed thee!");
1911 
1912   l->set_text(s);
1913   s = l->get_text() + "\n" + _("Seek more blessings in far temples!");
1914   l->set_text(s);
1915   if (ask_quest)
1916     {
1917       s = l->get_text() + "\n\n" + _("Do you seek a quest?");
1918       l->set_text(s);
1919     }
1920 
1921   if (ask_quest == false)
1922     {
1923       close_button->hide();
1924       close_button->set_no_show_all(true);
1925       s = _("_Close");
1926       accept_button->set_label(s);
1927     }
1928 
1929   if (blessCount > 0)
1930     Snd::getInstance()->play("bless", 1);
1931 
1932   int response = dialog.run_and_hide();
1933 
1934   if (ask_quest == false)
1935     response = Gtk::RESPONSE_CANCEL;
1936 
1937   if (response == Gtk::RESPONSE_ACCEPT)		// accepted a quest
1938     return true;
1939   else
1940     return false;
1941 }
1942 
on_quest_assigned(Hero * hero,Quest * quest)1943 void GameWindow::on_quest_assigned(Hero *hero, Quest *quest)
1944 {
1945   QuestAssignedDialog d(*window, hero, quest);
1946   d.run();
1947   d.hide();
1948 }
1949 
1950 static bool
hero_has_quest_here(Stack * s,City * c,bool * pillage,bool * sack,bool * raze,bool * occupy)1951 hero_has_quest_here (Stack *s, City *c, bool *pillage, bool *sack, bool *raze, bool *occupy)
1952 {
1953   Player *p = Playerlist::getActiveplayer();
1954   std::vector<Quest*> questlist;
1955   *pillage = false;
1956   *sack = false;
1957   *raze = false;
1958   *occupy = false;
1959 
1960   QuestsManager *q_mgr = QuestsManager::getInstance();
1961   questlist = q_mgr->getPlayerQuests(p);
1962   /* loop over all quests */
1963   /* for each quest, check the quest type */
1964   for (std::vector<Quest*>::iterator i = questlist.begin();
1965        i != questlist.end(); ++i)
1966     {
1967       if ((*i) == NULL)
1968 	continue;
1969       if ((*i)->isPendingDeletion() == true)
1970 	continue;
1971       switch ((*i)->getType())
1972 	{
1973 	case Quest::CITYSACK:
1974 	case Quest::CITYRAZE:
1975 	case Quest::CITYOCCUPY:
1976 	  if ((*i)->getType() == Quest::CITYSACK)
1977 	    {
1978 	      if (dynamic_cast<QuestCitySack*>((*i))->getCity() != c)
1979 		continue;
1980 	    }
1981 	  else if ((*i)->getType() == Quest::CITYOCCUPY)
1982 	    {
1983 	      if (dynamic_cast<QuestCityOccupy*>((*i))->getCity() != c)
1984 		continue;
1985 	    }
1986 	  else if ((*i)->getType() == Quest::CITYRAZE)
1987 	    {
1988 	      if (dynamic_cast<QuestCityRaze*>((*i))->getCity() != c)
1989 		continue;
1990 	    }
1991 	  /* now check if the quest's hero is in our stack */
1992 	  for (Stack::iterator it = s->begin(); it != s->end(); ++it)
1993 	    {
1994 	      if ((*it)->isHero())
1995 		{
1996 		  if ((*it)->getId() == (*i)->getHeroId())
1997 		    {
1998 		      /* hey we found one, set the corresponding boolean */
1999 		      if ((*i)->getType() == Quest::CITYSACK)
2000 			*sack = true;
2001 		      else if ((*i)->getType() == Quest::CITYRAZE)
2002 			*raze = true;
2003 		      else if ((*i)->getType() == Quest::CITYOCCUPY)
2004 			*occupy = true;
2005 		    }
2006 		}
2007 	    }
2008 	  break;
2009 	case Quest::PILLAGEGOLD:
2010 	  *pillage = true;
2011 	  *sack = true;
2012 	  break;
2013 	}
2014     }
2015   if ((*raze) || (*sack) || (*occupy))
2016     return true;
2017   else
2018     return false;
2019 }
2020 
on_city_defeated(City * city,int gold)2021 CityDefeatedAction GameWindow::on_city_defeated(City *city, int gold)
2022 {
2023   LwDialog dialog(*window, "city-defeated-dialog.ui");
2024   CityDefeatedAction retval = CITY_DEFEATED_OCCUPY;
2025   Gtk::Button *raze_button;
2026   Gtk::Button *sack_button;
2027   Gtk::Button *pillage_button;
2028   Gtk::Button *occupy_button;
2029   if (gold)
2030     on_city_looted (city, gold);
2031 
2032   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2033   Gtk::Image *image;
2034   xml->get_widget("city_image", image);
2035   image->property_pixbuf() =
2036     ImageCache::getInstance()->getDialogPic
2037     (ImageCache::DIALOG_CONQUERED_CITY,
2038      FontSize::getInstance ()->get_height ())->to_pixbuf();
2039   image->show();
2040 
2041   Gtk::Label *label;
2042   xml->get_widget("label", label);
2043   int width = 0, height = 0;
2044   image->get_size_request(width, height);
2045   label->set_size_request(width, height);
2046 
2047   Glib::ustring name;
2048   Player *p = Playerlist::getActiveplayer();
2049   Army *h = NULL;
2050   if (p->getActivestack())
2051     h = p->getActivestack()->getFirstHero();
2052   if (h)
2053     name = h->getName();
2054   else
2055     name = p->getName();
2056 
2057   Glib::ustring s;
2058   switch (Rnd::rand() % 4)
2059     {
2060     case 0: s = _("%1, you have triumphed in the battle of %2."); break;
2061     case 1: s = _("%1, you have claimed victory in the battle of %2."); break;
2062     case 2: s = _("%1, you have shown no mercy in the battle of %2."); break;
2063     case 3: s = _("%1, you have slain the foe in the battle of %2."); break;
2064     }
2065 
2066   s = String::ucompose(s, name, city->getName());
2067   s += "\n\n";
2068   s += label->get_text();
2069   label->set_text(s);
2070 
2071   xml->get_widget("raze_button", raze_button);
2072   xml->get_widget("sack_button", sack_button);
2073   xml->get_widget("pillage_button", pillage_button);
2074   xml->get_widget("occupy_button", occupy_button);
2075 
2076   switch (GameScenarioOptions::s_sacking_mode)
2077     {
2078     case GameParameters::SACKING_ALWAYS:
2079     case GameParameters::SACKING_ON_CAPTURE:
2080       sack_button->set_sensitive(true);
2081       pillage_button->set_sensitive(true);
2082       break;
2083     case GameParameters::SACKING_ON_QUEST:
2084     case GameParameters::SACKING_NEVER:
2085       sack_button->set_sensitive(false);
2086       pillage_button->set_sensitive(false);
2087       break;
2088     }
2089   raze_button->set_sensitive
2090     (GameScenarioOptions::s_razing_cities == GameParameters::ON_CAPTURE ||
2091      GameScenarioOptions::s_razing_cities == GameParameters::ALWAYS);
2092 
2093   bool quest_default = false;
2094   if (h) /* if there was a hero in the stack */
2095     {
2096       bool pillage, sack, raze, occupy;
2097       if (hero_has_quest_here (p->getActivestack(), city,
2098 			       &pillage, &sack, &raze, &occupy))
2099 	{
2100 	  if (pillage)
2101 	    {
2102               quest_default = true;
2103               pillage_button->set_sensitive(true);
2104               pillage_button->property_can_focus() = true;
2105               pillage_button->property_has_focus() = true;
2106               pillage_button->property_can_default() = true;
2107               pillage_button->property_receives_default() = true;
2108               pillage_button->property_has_default() = true;
2109 	      pillage_button->grab_default();
2110 	    }
2111 	  if (sack)
2112 	    {
2113               quest_default = true;
2114               sack_button->set_sensitive(true);
2115               sack_button->property_can_focus() = true;
2116               sack_button->property_has_focus() = true;
2117               sack_button->property_can_default() = true;
2118               sack_button->property_receives_default() = true;
2119               sack_button->property_has_default() = true;
2120 	      sack_button->grab_default();
2121 	    }
2122 	  if (raze)
2123 	    {
2124               quest_default = true;
2125               raze_button->property_can_focus() = true;
2126               raze_button->property_has_focus() = true;
2127               raze_button->property_can_default() = true;
2128               raze_button->property_receives_default() = true;
2129               raze_button->property_has_default() = true;
2130 	      raze_button->grab_default();
2131 	    }
2132 	  if (occupy)
2133 	    {
2134               quest_default = true;
2135               occupy_button->property_can_focus() = true;
2136               occupy_button->property_has_focus() = true;
2137               occupy_button->property_can_default() = true;
2138               occupy_button->property_has_default() = true;
2139               occupy_button->property_receives_default() = true;
2140 	      occupy_button->grab_default();
2141 	    }
2142 	}
2143     }
2144 
2145   if (city->getNoOfProductionBases() <= 0)
2146     pillage_button->hide();
2147 
2148   if (city->getNoOfProductionBases() <= 1)
2149     sack_button->hide();
2150 
2151   dialog.get()->show();
2152 
2153   if (quest_default == false)
2154     {
2155       occupy_button->property_can_focus() = true;
2156       occupy_button->property_has_focus() = true;
2157       occupy_button->property_can_default() = true;
2158       occupy_button->property_has_default() = true;
2159       occupy_button->property_receives_default() = true;
2160       occupy_button->grab_default();
2161     }
2162 
2163   while (1)
2164     {
2165       int response = dialog.get()->run();
2166       switch (response)
2167 	{
2168 	case 1: retval = CITY_DEFEATED_OCCUPY; break;
2169 	case 2:
2170 		{
2171 		  bool razed = CityWindow::on_raze_clicked(city, dialog.get());
2172 		  if (razed == false)
2173 		    continue;
2174 		  retval = CITY_DEFEATED_RAZE;
2175 		  break;
2176 		}
2177 	case 3: retval = CITY_DEFEATED_PILLAGE; break;
2178 	case 4: retval = CITY_DEFEATED_SACK; break;
2179 	default: break;
2180 	}
2181       if (retval)
2182 	break;
2183     }
2184   dialog.get()->hide();
2185   return retval;
2186 }
2187 
on_city_looted(City * city,int gold)2188 void GameWindow::on_city_looted (City *city, int gold)
2189 {
2190   LwDialog dialog(*window, "city-looted-dialog.ui");
2191   dialog.set_title(String::ucompose(_("%1 Looted"), city->getName()));
2192   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2193   Gtk::Label *label;
2194   xml->get_widget("label", label);
2195   Glib::ustring s = label->get_text();
2196   s += "\n\n";
2197   s += String::ucompose(
2198 			ngettext("Your armies loot %1 gold piece.",
2199 				 "Your armies loot %1 gold pieces.", gold), gold);
2200   label->set_text(s);
2201   dialog.run_and_hide();
2202 }
2203 
on_city_pillaged(City * city,int gold,int pillaged_army_type)2204 void GameWindow::on_city_pillaged(City *city, int gold, int pillaged_army_type)
2205 {
2206   LwDialog dialog(*window, "city-pillaged-dialog.ui");
2207   ImageCache *gc = ImageCache::getInstance();
2208   Player *player = city->getOwner();
2209   unsigned int as = player->getArmyset();
2210 
2211   dialog.set_title(String::ucompose(_("Pillaged %1"), city->getName()));
2212   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2213   Gtk::Image *pillaged_army_type_image;
2214   Gtk::Label *pillaged_army_type_cost_label;
2215   xml->get_widget("pillaged_army_type_cost_label", pillaged_army_type_cost_label);
2216   xml->get_widget("pillaged_army_type_image", pillaged_army_type_image);
2217   if (gold == 0)
2218     {
2219       Glib::RefPtr<Gdk::Pixbuf> empty_pic =
2220         gc->getCircledArmyPic(as, 0, player, NULL, false, Shield::NEUTRAL,
2221                               false,
2222                               FontSize::getInstance()->get_height ())->to_pixbuf();
2223       pillaged_army_type_image->set(empty_pic);
2224       pillaged_army_type_cost_label->set_text("");
2225     }
2226   else
2227     {
2228       Glib::RefPtr<Gdk::Pixbuf> pic;
2229       pic = gc->getCircledArmyPic(as, pillaged_army_type, player, NULL, false,
2230                                   Shield::NEUTRAL, true,
2231                                   FontSize::getInstance()->get_height ())->to_pixbuf();
2232       pillaged_army_type_image->property_pixbuf() = pic;
2233       pillaged_army_type_cost_label->set_text(String::ucompose("%1 gp", gold));
2234     }
2235   Gtk::Label *label;
2236   xml->get_widget("label", label);
2237   Glib::ustring s = label->get_text();
2238   s += "\n\n";
2239   s += String::ucompose(
2240 			ngettext("The loot is worth %1 gold piece.",
2241 				 "The loot is worth %1 gold pieces.",
2242 				 gold), gold);
2243   label->set_text(s);
2244 
2245   dialog.run_and_hide();
2246 }
2247 
on_city_sacked(City * city,int gold,std::list<guint32> sacked_types)2248 void GameWindow::on_city_sacked(City *city, int gold, std::list<guint32> sacked_types)
2249 {
2250   LwDialog dialog(*window, "city-sacked-dialog.ui");
2251   ImageCache *gc = ImageCache::getInstance();
2252   Player *player = city->getOwner();
2253   unsigned int as = player->getArmyset();
2254 
2255   dialog.set_title(String::ucompose(_("Sacked %1"), city->getName()));
2256 
2257   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2258   Gtk::Label *label;
2259   xml->get_widget("label", label);
2260   Glib::ustring s;
2261   s = String::ucompose(_("The city of %1 is sacked\nfor %2 gold!\n\n"),
2262 		       city->getName(), gold);
2263   s += String::ucompose(
2264 			ngettext("Ability to produce %1 unit has been lost\nand only 1 unit remains",
2265 				 "Ability to produce %1 units has been lost\nand only 1 unit remains",
2266 				 sacked_types.size()), sacked_types.size());
2267   label->set_text(s);
2268 
2269   Gtk::Image *sacked_army_1_image;
2270   Gtk::Image *sacked_army_2_image;
2271   Gtk::Image *sacked_army_3_image;
2272   Gtk::Label *sacked_army_1_cost_label;
2273   Gtk::Label *sacked_army_2_cost_label;
2274   Gtk::Label *sacked_army_3_cost_label;
2275   xml->get_widget("sacked_army_1_image", sacked_army_1_image);
2276   xml->get_widget("sacked_army_2_image", sacked_army_2_image);
2277   xml->get_widget("sacked_army_3_image", sacked_army_3_image);
2278   xml->get_widget("sacked_army_1_cost_label", sacked_army_1_cost_label);
2279   xml->get_widget("sacked_army_2_cost_label", sacked_army_2_cost_label);
2280   xml->get_widget("sacked_army_3_cost_label", sacked_army_3_cost_label);
2281 
2282   Glib::RefPtr<Gdk::Pixbuf> pic;
2283   Glib::RefPtr<Gdk::Pixbuf> empty_pic =
2284     gc->getCircledArmyPic(as, 0, player, NULL, false, Shield::NEUTRAL,
2285                           false,
2286                           FontSize::getInstance()->get_height ())->to_pixbuf();
2287   int i = 0;
2288   Gtk::Label *sack_label = NULL;
2289   Gtk::Image *sack_image = NULL;
2290   for (std::list<guint32>::iterator it = sacked_types.begin(); it != sacked_types.end(); it++)
2291     {
2292       switch (i)
2293 	{
2294 	case 0:
2295 	  sack_label = sacked_army_1_cost_label;
2296 	  sack_image = sacked_army_1_image;
2297 	  break;
2298 	case 1:
2299 	  sack_label = sacked_army_2_cost_label;
2300 	  sack_image = sacked_army_2_image;
2301 	  break;
2302 	case 2:
2303 	  sack_label = sacked_army_3_cost_label;
2304 	  sack_image = sacked_army_3_image;
2305 	  break;
2306 	}
2307       pic = gc->getCircledArmyPic(as, *it, player, NULL, false,
2308                                   Shield::NEUTRAL, true,
2309                                   FontSize::getInstance()->get_height ())->to_pixbuf();
2310       sack_image->property_pixbuf() = pic;
2311       const ArmyProto *a =
2312 	Armysetlist::getInstance()->getArmy (player->getArmyset(), *it);
2313       s = String::ucompose(_("%1 gp"), a->getNewProductionCost() / 2);
2314       sack_label->set_text(s);
2315       i++;
2316     }
2317   for (i = sacked_types.size(); i < 3; i++)
2318     {
2319       switch (i)
2320 	{
2321 	case 0:
2322 	  sack_label = sacked_army_1_cost_label;
2323 	  sack_image = sacked_army_1_image;
2324 	  break;
2325 	case 1:
2326 	  sack_label = sacked_army_2_cost_label;
2327 	  sack_image = sacked_army_2_image;
2328 	  break;
2329 	case 2:
2330 	  sack_label = sacked_army_3_cost_label;
2331 	  sack_image = sacked_army_3_image;
2332 	  break;
2333 	}
2334       sack_image->set(empty_pic);
2335       sack_label->set_text("");
2336     }
2337   dialog.run_and_hide();
2338 }
2339 
on_city_razed(City * city)2340 void GameWindow::on_city_razed (City *city)
2341 {
2342   LwDialog dialog(*window, "city-razed-dialog.ui");
2343   dialog.set_title(String::ucompose(_("Razed %1"), city->getName()));
2344   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2345   Gtk::Label *label;
2346   xml->get_widget("label", label);
2347   Glib::ustring s =
2348     String::ucompose(_("The city of %1 is in ruins!"), city->getName());
2349   label->set_text(s);
2350   dialog.run_and_hide();
2351 }
2352 
on_city_visited(City * city)2353 void GameWindow::on_city_visited(City *city)
2354 {
2355   CityWindow d(*window, city,
2356 	       GameScenarioOptions::s_razing_cities == GameParameters::ALWAYS,
2357 	       GameScenarioOptions::s_see_opponents_production);
2358 
2359   d.run();
2360   d.hide();
2361 }
2362 
on_ruin_visited(Ruin * ruin)2363 void GameWindow::on_ruin_visited(Ruin *ruin)
2364 {
2365   RuinReportDialog d(*window, ruin->getPos());
2366   d.run();
2367   d.hide();
2368 }
2369 
show_shield_turn()2370 void GameWindow::show_shield_turn() //show turn indicator
2371 {
2372   Playerlist* pl = Playerlist::getInstance();
2373   ImageCache *gc = ImageCache::getInstance();
2374   unsigned int c = 0;
2375   for (Playerlist::iterator i = pl->begin(); i != pl->end(); ++i)
2376     {
2377       if (pl->getNeutral() == (*i))
2378 	continue;
2379       if ((*i)->isDead())
2380 	{
2381 	  shield_image[c]->clear();
2382 	  turn_hbox->remove(dynamic_cast<Gtk::Widget&>(*shield_image[c]));
2383           turn_hbox->queue_resize();
2384 	  continue;
2385 	}
2386       if (*i == pl->getActiveplayer())
2387         {
2388           PixMask *s =
2389             gc->getShieldPic (1, (*i), false,
2390                               FontSize::getInstance ()->get_height ())->copy ();
2391           ImageCache::add_underline (&s, pl->getActiveplayer()->getColor (),
2392                                      FontSize::getInstance ()->get_height ());
2393           shield_image[c]->property_pixbuf() = s->to_pixbuf();
2394           delete s;
2395         }
2396       else
2397         shield_image[c]->property_pixbuf() =
2398           gc->getShieldPic(1, (*i), false,
2399                            FontSize::getInstance()->get_height ())->to_pixbuf();
2400       if (*i == pl->getActiveplayer())
2401         shield_image[c]->property_margin_top() = 0;
2402       else
2403         shield_image[c]->property_margin_top() =
2404           FontSize::getInstance ()->get_height () / 3;
2405       shield_image[c]->property_tooltip_text() = (*i)->getName();
2406       c++;
2407     }
2408   for (unsigned int i = c; i < MAX_PLAYERS; i++)
2409     shield_image[i]->clear();
2410 }
2411 
on_remote_next_player_turn()2412 void GameWindow::on_remote_next_player_turn()
2413 {
2414   status_box->reset_progress();
2415   status_box->on_stack_info_changed(NULL);
2416   while (g_main_context_iteration(NULL, FALSE)); //doEvents
2417 
2418   d_quick_fights = false;
2419   show_shield_turn();
2420   turn_label->set_markup(String::ucompose("<b>%1 %2</b>", _("Turn"),
2421                                           GameScenarioOptions::s_round));
2422 }
2423 
on_next_player_turn(Player * player,unsigned int turn_number)2424 void GameWindow::on_next_player_turn(Player *player, unsigned int turn_number)
2425 {
2426   status_box->reset_progress();
2427   status_box->on_stack_info_changed(NULL);
2428   while (g_main_context_iteration(NULL, FALSE)); //doEvents
2429 
2430   d_quick_fights = false;
2431   show_shield_turn();
2432   if (player->getType() != Player::HUMAN)
2433     return;
2434 
2435   LwDialog dialog (*window, "next-player-turn-dialog.ui");
2436 
2437   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2438   Gtk::Image *image;
2439   xml->get_widget("image", image);
2440   image->property_pixbuf() =
2441     ImageCache::getInstance()->getDialogPic
2442     (ImageCache::DIALOG_NEXT_TURN,
2443      FontSize::getInstance ()->get_height ())->to_pixbuf();
2444 
2445   Gtk::Label *label;
2446   xml->get_widget("label", label);
2447   Glib::ustring s = String::ucompose(_("%1\nTurn %2"), player->getName(),
2448                                      turn_number);
2449   label->set_text(s);
2450 
2451   dialog.run_and_hide();
2452   show();
2453 }
2454 
on_medal_awarded_to_army(Army * army,int medaltype)2455 void GameWindow::on_medal_awarded_to_army(Army *army, int medaltype)
2456 {
2457   ImageCache *gc = ImageCache::getInstance();
2458   LwDialog dialog(*window, "medal-awarded-dialog.ui");
2459   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2460   Gtk::Image *image;
2461   xml->get_widget("image", image);
2462   Player *active = Playerlist::getInstance()->getActiveplayer();
2463   image->property_pixbuf() =
2464     gc->getCircledArmyPic(active->getArmyset(), army->getTypeId(), active,
2465 		   army->getMedalBonuses(), false, Shield::NEUTRAL,
2466                    true,
2467                    FontSize::getInstance ()->get_height ())->to_pixbuf();
2468   Gtk::Image *medal_image;
2469   xml->get_widget("medal_image", medal_image);
2470   medal_image->property_pixbuf() =
2471     gc->getMedalPic(true, medaltype,
2472                     FontSize::getInstance ()->get_height ())->to_pixbuf();
2473 
2474   Gtk::Label *label;
2475   xml->get_widget("label", label);
2476   Glib::ustring s;
2477   if (medaltype == 0)
2478     s += String::ucompose(_("Your unit of %1 is awarded the avenger's medal of valour!"), army->getName());
2479   else if (medaltype == 1)
2480     s += String::ucompose(_("Your unit of %1 is awarded the defender's medal of bravery!"), army->getName());
2481   else if (medaltype == 2)
2482     s += String::ucompose(_("Your unit of %1 is awarded the veteran's medal!"), army->getName());
2483   else
2484     s += String::ucompose(_("Your unit of %1 is awarded a medal!"), army->getName());
2485   label->set_text(s);
2486 
2487   dialog.run_and_hide();
2488 }
2489 
on_hero_gains_level(Hero * hero)2490 Army::Stat GameWindow::on_hero_gains_level(Hero *hero)
2491 {
2492   ArmyGainsLevelDialog d(*window, hero, GameScenario::s_hidden_map);
2493   d.run_and_hide();
2494   return d.get_selected_stat();
2495 }
2496 
on_game_loaded(Player * player)2497 void GameWindow::on_game_loaded(Player *player)
2498 {
2499   LwDialog dialog(*window, "game-loaded-dialog.ui");
2500   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2501   Gtk::Label *label;
2502   xml->get_widget("label", label);
2503   Glib::ustring s = String::ucompose(_("%1, your turn continues."),
2504                                      player->getName());
2505   label->set_text(s);
2506   dialog.run_and_hide();
2507 }
2508 
on_quest_completed(Quest * quest,Reward * reward)2509 void GameWindow::on_quest_completed(Quest *quest, Reward *reward)
2510 {
2511   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
2512     return;
2513   QuestCompletedDialog d(*window, quest, reward);
2514   d.run();
2515   d.hide();
2516 }
2517 
on_quest_expired(Quest * quest)2518 void GameWindow::on_quest_expired(Quest *quest)
2519 {
2520   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
2521     return;
2522   LwDialog dialog(*window, "quest-expired-dialog.ui");
2523 
2524   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2525   Gtk::Label *label;
2526   xml->get_widget("label", label);
2527   Glib::ustring s = String::ucompose(_("%1 did not complete the quest."),
2528                                      quest->getHeroName());
2529   s += "\n\n";
2530 
2531   // add messages from the quest
2532   std::queue<Glib::ustring> msgs;
2533   quest->getExpiredMsg(msgs);
2534   while (!msgs.empty())
2535     {
2536       s += msgs.front();
2537       msgs.pop();
2538       if (!msgs.empty())
2539 	s += "\n\n";
2540     }
2541 
2542   label->set_text(s);
2543 
2544   dialog.run_and_hide();
2545 }
2546 
on_inspect_activated()2547 void GameWindow::on_inspect_activated ()
2548 {
2549   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
2550     return;
2551   if (Playerlist::getActiveplayer()->getHeroes().size() == 0)
2552     return;
2553   Hero *hero = NULL;
2554   Vector<int> pos = Vector<int>(-1,-1);
2555   if (status_box->get_currently_selected_stack() != NULL)
2556     {
2557       hero = dynamic_cast<Hero*>(status_box->get_currently_selected_stack()->getFirstHero());
2558       pos = status_box->get_currently_selected_stack()->getPos();
2559     }
2560 
2561   HeroDialog d(*window, hero, pos);
2562   d.run();
2563   d.hide();
2564 }
on_plant_standard_activated()2565 void GameWindow::on_plant_standard_activated ()
2566 {
2567   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
2568     return;
2569   Playerlist::getActiveplayer()->heroPlantStandard(NULL);
2570 }
2571 
on_stack_moves(Stack * stack,Vector<int> pos)2572 void GameWindow::on_stack_moves(Stack *stack, Vector<int> pos)
2573 {
2574   Player *active = Playerlist::getInstance()->getActiveplayer();
2575   if (!active)
2576     return;
2577   if (active->getActivestack() != stack)
2578     return;
2579   if (GameMap::getEnemyCity(pos))
2580     return;
2581   if (GameMap::getEnemyStack(pos))
2582     return;
2583   int step = TIMER_BIGMAP_SELECTOR * 1000;
2584   for (int i = 0; i < Configuration::s_displaySpeedDelay; i += step)
2585     {
2586       game->get_bigmap().draw();
2587       while (g_main_context_iteration(NULL, FALSE)); //doEvents
2588       if (i + step > Configuration::s_displaySpeedDelay)
2589         step = Configuration::s_displaySpeedDelay - i;
2590       Glib::usleep(step);
2591     }
2592 }
2593 
on_advice_asked(float percent)2594 void GameWindow::on_advice_asked(float percent)
2595 {
2596   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
2597     return;
2598   //we asked for advice on a fight, and we're being told that we
2599   //have a PERCENT chance of winning the fight
2600   LwDialog dialog(*window, "military-advisor-dialog.ui");
2601 
2602   dialog.set_title(_("Advisor!"));
2603 
2604   Glib::RefPtr<Gtk::Builder> xml = dialog.get_builder();
2605   Gtk::Label *label;
2606   xml->get_widget("label", label);
2607   Glib::ustring s;
2608 
2609   int num = Rnd::rand() % 5;
2610   if (num == 0)
2611     s += _("My Good Lord!");
2612   else if (num == 1)
2613     s += _("Great and Worthy Lord!");
2614   else if (num == 2)
2615     s += _("O Champion of Justice!");
2616   else if (num == 3)
2617     s += _("O Mighty Leader!");
2618   else if (num == 4)
2619     s += _("O Great Warlord!");
2620   s += "\n";
2621 
2622   num = Rnd::rand() % 7;
2623   num = Rnd::rand() % 7;
2624   if (percent >= 90.0)
2625     {
2626       if (num == 0)
2627 	s += _("This battle will surely be as simple as butchering sleeping cattle!");
2628       else if (num == 1)
2629 	s += _("A battle here would be as simple as butchering sleeping cattle!");
2630       else if (num == 2)
2631 	s += _("I believe this battle will surely be as simple as butchering sleeping cattle!");
2632       else if (num == 3)
2633 	s += _("This battle would be as simple as butchering sleeping cattle!");
2634       else if (num == 4)
2635 	s += _("A battle here would be as simple as butchering sleeping cattle!");
2636       else if (num == 5)
2637 	s += _("I believe this battle will be as simple as butchering sleeping cattle!");
2638       else if (num == 6)
2639 	s += _("This battle shall be as simple as butchering sleeping cattle!");
2640     }
2641   else if (percent >= 80.0)
2642     {
2643       if (num == 0)
2644 	s += _("This battle will surely be an easy victory!  We cannot lose!");
2645       else if (num == 1)
2646 	s += _("A battle here would be an easy victory!  We cannot lose!");
2647       else if (num == 2)
2648 	s += _("I believe this battle will surely be an easy victory!  We cannot lose!");
2649       else if (num == 3)
2650 	s += _("This battle would be an easy victory!  We cannot lose!");
2651       else if (num == 4)
2652 	s += _("A battle here would be an easy victory!  We cannot lose!");
2653       else if (num == 5)
2654 	s += _("I believe this battle will be an easy victory!  We cannot lose!");
2655       else if (num == 6)
2656 	s += _("This battle shall be an easy victory!  We cannot lose!");
2657     }
2658   else if (percent >= 70.0)
2659     {
2660       if (num == 0)
2661 	s += _("This battle will surely be a comfortable victory!");
2662       else if (num == 1)
2663 	s += _("A battle here would be a comfortable victory!");
2664       else if (num == 2)
2665 	s += _("I believe this battle will surely be a comfortable victory!");
2666       else if (num == 3)
2667 	s += _("This battle would be a comfortable victory!");
2668       else if (num == 4)
2669 	s += _("A battle here would be a comfortable victory!");
2670       else if (num == 5)
2671 	s += _("I believe this battle will be a comfortable victory!");
2672       else if (num == 6)
2673 	s += _("This battle shall be a comfortable victory!");
2674     }
2675   else if (percent >= 60.0)
2676     {
2677       if (num == 0)
2678 	s += _("This battle will surely be a hard fought victory! But we shall win!");
2679       else if (num == 1)
2680 	s += _("A battle here would be a hard fought victory! But we shall win!");
2681       else if (num == 2)
2682 	s += _("I believe this battle will surely be a hard fought victory! But we shall win!");
2683       else if (num == 3)
2684 	s += _("This battle would be a hard fought victory! But we shall win!");
2685       else if (num == 4)
2686 	s += _("A battle here would be a hard fought victory! But we shall win!");
2687       else if (num == 5)
2688 	s += _("I believe this battle will be a hard fought victory! But we shall win!");
2689       else if (num == 6)
2690 	s += _("This battle shall be a hard fought victory! But we shall win!");
2691     }
2692   else if (percent >= 50.0)
2693     {
2694       if (num == 0)
2695 	s += _("This battle will surely be very evenly matched!");
2696       else if (num == 1)
2697 	s += _("A battle here would be very evenly matched!");
2698       else if (num == 2)
2699 	s += _("I believe this battle will surely be very evenly matched!");
2700       else if (num == 3)
2701 	s += _("This battle would be very evenly matched!");
2702       else if (num == 4)
2703 	s += _("A battle here would be very evenly matched!");
2704       else if (num == 5)
2705 	s += _("I believe this battle will be very evenly matched!");
2706       else if (num == 6)
2707 	s += _("This battle shall be very evenly matched!");
2708     }
2709   else if (percent >= 40.0)
2710     {
2711       if (num == 0)
2712 	s += _("This battle will surely be difficult but not impossible to win!");
2713       else if (num == 1)
2714 	s += _("A battle here would be difficult but not impossible to win!");
2715       else if (num == 2)
2716 	s += _("I believe this battle will surely be difficult but not impossible to win!");
2717       else if (num == 3)
2718 	s += _("This battle would be difficult but not impossible to win!");
2719       else if (num == 4)
2720 	s += _("A battle here would be difficult but not impossible to win!");
2721       else if (num == 5)
2722 	s += _("I believe this battle will be difficult but not impossible to win!");
2723       else if (num == 6)
2724 	s += _("This battle shall be difficult but not impossible to win!");
2725     }
2726   else if (percent >= 30.0)
2727     {
2728       if (num == 0)
2729 	s += _("This battle will surely be a brave choice! I leave it to thee!");
2730       else if (num == 1)
2731 	s += _("A battle here would be a brave choice! I leave it to thee!");
2732       else if (num == 2)
2733 	s += _("I believe this battle will surely be a brave choice! I leave it to thee!");
2734       else if (num == 3)
2735 	s += _("This battle would be a brave choice! I leave it to thee!");
2736       else if (num == 4)
2737 	s += _("A battle here would be a brave choice! I leave it to thee!");
2738       else if (num == 5)
2739 	s += _("I believe this battle will be a brave choice! I leave it to thee!");
2740       else if (num == 6)
2741 	s += _("This battle shall be a brave choice! I leave it to thee!");
2742     }
2743   else if (percent >= 20.0)
2744     {
2745       if (num == 0)
2746 	s += _("This battle will surely be a foolish decision!");
2747       else if (num == 1)
2748 	s += _("A battle here would be a foolish decision!");
2749       else if (num == 2)
2750 	s += _("I believe this battle will surely be a foolish decision!");
2751       else if (num == 3)
2752 	s += _("This battle would be a foolish decision!");
2753       else if (num == 4)
2754 	s += _("A battle here would be a foolish decision!");
2755       else if (num == 5)
2756 	s += _("I believe this battle will be a foolish decision!");
2757       else if (num == 6)
2758 	s += _("This battle shall be a foolish decision!");
2759     }
2760   else if (percent >= 10.0)
2761     {
2762       if (num == 0)
2763 	s += _("This battle will surely be sheerest folly!  Thou shouldst not attack!");
2764       else if (num == 1)
2765 	s += _("A battle here would be sheerest folly!  Thou shouldst not attack!");
2766       else if (num == 2)
2767 	s += _("I believe this battle will surely be sheerest folly!  Thou shouldst not attack!");
2768       else if (num == 3)
2769 	s += _("This battle would be sheerest folly!  Thou shouldst not attack!");
2770       else if (num == 4)
2771 	s += _("A battle here would be sheerest folly!  Thou shouldst not attack!");
2772       else if (num == 5)
2773 	s += _("I believe this battle will be sheerest folly!  Thou shouldst not attack!");
2774       else if (num == 6)
2775 	s += _("This battle shall be sheerest folly!  Thou shouldst not attack!");
2776     }
2777   else
2778     {
2779       if (num == 0)
2780 	s += _("This battle will surely be complete and utter suicide!");
2781       else if (num == 1)
2782 	s += _("A battle here would be complete and utter suicide!");
2783       else if (num == 2)
2784 	s += _("I believe this battle will surely be complete and utter suicide!");
2785       else if (num == 3)
2786 	s += _("This battle would be complete and utter suicide!");
2787       else if (num == 4)
2788 	s += _("A battle here would be complete and utter suicide!");
2789       else if (num == 5)
2790 	s += _("I believe this battle will be complete and utter suicide!");
2791       else if (num == 6)
2792 	s += _("This battle shall be complete and utter suicide!");
2793     }
2794   label->set_text(s);
2795 
2796   dialog.run_and_hide();
2797   return;
2798 }
2799 
on_show_lobby_activated()2800 void GameWindow::on_show_lobby_activated()
2801 {
2802   show_lobby.emit();
2803 }
2804 
on_online_help_activated()2805 void GameWindow::on_online_help_activated()
2806 {
2807   GError *errs = NULL;
2808   gtk_show_uri(window->get_screen()->gobj(),
2809                "http://www.nongnu.org/lordsawar/manual/" PACKAGE_VERSION "/lordsawar.html", 0, &errs);
2810 
2811   return;
2812 }
2813 
on_player_replaced(Player * p)2814 void GameWindow::on_player_replaced(Player *p)
2815 {
2816   if (game)
2817     game->addPlayer(p);
2818 }
2819 
on_grid_toggled()2820 void GameWindow::on_grid_toggled()
2821 {
2822   game->get_bigmap().toggle_grid();
2823   if (game->get_bigmap().get_toggled() == false)
2824     pos_label->set_text("");
2825 }
2826 
give_some_cheese(Player * winner)2827 void GameWindow::give_some_cheese(Player *winner)
2828 {
2829   //this is so we only give cheese once
2830   if (save_game_as_menuitem->property_sensitive() == true)
2831     {
2832       game->endOfGameRoaming(winner);
2833       game_button_box->give_some_cheese();
2834       end_turn_menuitem->set_sensitive(false);
2835       save_game_menuitem->set_sensitive(false);
2836       save_game_as_menuitem->set_sensitive(false);
2837       Playerlist::getActiveplayer()->clearFogMap();
2838       show_shield_turn();
2839       game->redraw();
2840       city_history_menuitem->activate();
2841     }
2842 }
2843 
on_commentator_comments(Glib::ustring comment)2844 void GameWindow::on_commentator_comments(Glib::ustring comment)
2845 {
2846   TimedMessageDialog dialog (*window, comment, 0);
2847   dialog.set_title(_("The Warlord Says..."));
2848 
2849   dialog.set_image (ImageCache::getInstance()->getDialogPic
2850                     (ImageCache::DIALOG_COMMENTATOR,
2851                      FontSize::getInstance ()->get_height ())->to_pixbuf());
2852   dialog.run_and_hide();
2853 }
2854 
on_abbreviated_fight_started(LocationBox box)2855 void GameWindow::on_abbreviated_fight_started(LocationBox box)
2856 {
2857   game->get_bigmap().setFighting(box);
2858   game->get_bigmap().draw();
2859   while (g_main_context_iteration(NULL, FALSE)); //doEvents
2860   Glib::usleep (TIMER_BIGMAP_SELECTOR * 10000);
2861   game->get_bigmap().setFighting(LocationBox(Vector<int>(-1,-1)));
2862   game->get_bigmap().draw();
2863 }
2864 
on_select_item(std::list<Item * > items)2865 Item* GameWindow::on_select_item(std::list<Item*> items)
2866 {
2867   Item *item = NULL;
2868   UseItemDialog d(*window, items);
2869   d.run();
2870   item = d.get_selected_item();
2871   d.hide();
2872   return item;
2873 }
2874 
on_select_item_victim_player()2875 Player *GameWindow::on_select_item_victim_player()
2876 {
2877   Player *player = NULL;
2878   UseItemOnPlayerDialog d(*window);
2879   player = d.run();
2880   d.hide();
2881   return player;
2882 }
2883 
on_select_city_to_use_item_on(SelectCityMap::Type type)2884 City *GameWindow::on_select_city_to_use_item_on(SelectCityMap::Type type)
2885 {
2886   UseItemOnCityDialog d(*window, type);
2887   City *city = d.run();
2888   d.hide();
2889   return city;
2890 }
2891 
on_gold_stolen(Player * victim,guint32 gold_pieces)2892 void GameWindow::on_gold_stolen(Player *victim, guint32 gold_pieces)
2893 {
2894   Glib::ustring s =
2895     String::ucompose(ngettext("%1 gold piece was stolen from %2!",
2896                               "%1 gold pieces were stolen from %2!",
2897                               gold_pieces), gold_pieces, victim->getName());
2898   TimedMessageDialog dialog(*window, s, 30);
2899   dialog.run_and_hide();
2900   return;
2901 }
2902 
on_ships_sunk(guint32 num_armies)2903 void GameWindow::on_ships_sunk(guint32 num_armies)
2904 {
2905   Glib::ustring s =
2906     String::ucompose(ngettext("%1 army unit was sunk to the watery depths!",
2907                               "%1 army units were sunk to the watery depths!",
2908                               num_armies), num_armies);
2909   TimedMessageDialog dialog(*window, s, 30);
2910   dialog.run_and_hide();
2911   return;
2912 }
2913 
on_bags_picked_up(Hero * hero,guint32 num_bags)2914 void GameWindow::on_bags_picked_up(Hero *hero, guint32 num_bags)
2915 {
2916   Glib::ustring s =
2917     String::ucompose(ngettext("%1 bag was retrieved by %2!",
2918                               "%1 bags were retrieved by %2!",
2919                               num_bags), num_bags, hero->getName());
2920   TimedMessageDialog dialog(*window, s, 30);
2921   dialog.run_and_hide();
2922   return;
2923 }
2924 
on_bridge_burned(Hero * hero)2925 void GameWindow::on_bridge_burned(Hero *hero)
2926 {
2927   Glib::ustring s =
2928     String::ucompose(_("%1 has burned a bridge!  None shall pass this way again!"), hero->getName());
2929   TimedMessageDialog dialog(*window, s, 30);
2930   dialog.run_and_hide();
2931   return;
2932 }
2933 
on_keeper_captured(Hero * hero,Ruin * ruin,Glib::ustring name)2934 void GameWindow::on_keeper_captured(Hero *hero, Ruin *ruin, Glib::ustring name)
2935 {
2936   Glib::ustring s =
2937     String::ucompose(_("%1 has turned %2 from %3!"),
2938                      hero->getName(), name, ruin->getName());
2939   TimedMessageDialog dialog(*window, s, 30);
2940   dialog.run_and_hide();
2941   return;
2942 }
2943 
on_city_diseased(Glib::ustring name,guint32 num_armies)2944 void GameWindow::on_city_diseased(Glib::ustring name, guint32 num_armies)
2945 {
2946   Glib::ustring s =
2947     String::ucompose(ngettext("%1 unit in %2 have perished!",
2948                               "%1 units in %2 have perished!", num_armies),
2949                      num_armies, name);
2950   TimedMessageDialog dialog(*window, s, 30);
2951   dialog.run_and_hide();
2952   return;
2953 }
2954 
on_city_defended(Glib::ustring city_name,Glib::ustring army_name,guint32 num_armies)2955 void GameWindow::on_city_defended(Glib::ustring city_name, Glib::ustring army_name, guint32 num_armies)
2956 {
2957   Glib::ustring s =
2958     String::ucompose(ngettext("%1 unit of %2 have been raised in %3!",
2959                               "%1 units of %2 have been raised in %3!",
2960                               num_armies), num_armies, army_name, city_name);
2961   TimedMessageDialog dialog(*window, s, 30);
2962   dialog.run_and_hide();
2963   return;
2964 }
2965 
on_city_persuaded(Glib::ustring city_name,guint32 num_armies)2966 void GameWindow::on_city_persuaded(Glib::ustring city_name, guint32 num_armies)
2967 {
2968   if (game)
2969     game->redraw();
2970   Glib::ustring s;
2971   if (num_armies != 0)
2972     s = String::ucompose
2973       (ngettext("%1 unit in %2 have been persuaded to fly your flag!",
2974                 "%1 units in %2 have been persuaded to fly your flag!",
2975                 num_armies),
2976        num_armies, city_name);
2977   else
2978     s = String::ucompose
2979       (_("The citizens of %1 have been persuaded to fly your flag!"),
2980        city_name);
2981   TimedMessageDialog dialog(*window, s, 30);
2982   dialog.run_and_hide();
2983   return;
2984 }
2985 
on_stack_teleported(Hero * hero,Glib::ustring city_name)2986 void GameWindow::on_stack_teleported(Hero *hero, Glib::ustring city_name)
2987 {
2988   Glib::ustring s = String::ucompose(_("%1 has teleported to %2!"),
2989                                      hero->getName(), city_name);
2990   TimedMessageDialog dialog(*window, s, 30);
2991 
2992   dialog.run_and_hide();
2993   return;
2994 }
2995 
on_monster_summoned(Hero * hero,Glib::ustring name)2996 void GameWindow::on_monster_summoned(Hero *hero, Glib::ustring name)
2997 {
2998   Glib::ustring s = String::ucompose
2999     (_("A unit of %1 has come to the aid of %2!"), name, hero->getName());
3000   TimedMessageDialog dialog(*window, s, 30);
3001   dialog.run_and_hide();
3002   return;
3003 }
3004 
on_worms_killed(Hero * hero,Glib::ustring name,guint32 num_killed)3005 void GameWindow::on_worms_killed(Hero *hero, Glib::ustring name, guint32 num_killed)
3006 {
3007   Glib::ustring s =
3008     String::ucompose(ngettext("%1 unit of %2 was banished by %3!",
3009                               "%1 units of %2 were banished by %3!",
3010                               num_killed), num_killed, name, hero->getName());
3011   TimedMessageDialog dialog(*window, s, 30);
3012   dialog.run_and_hide();
3013   return;
3014 }
3015 
on_mp_added_to_hero_stack(Hero * hero,guint32 mp)3016 void GameWindow::on_mp_added_to_hero_stack(Hero *hero, guint32 mp)
3017 {
3018   Glib::ustring s =
3019     String::ucompose(ngettext("%1 movement point was added to %2 and accompanying units!",
3020                               "%1 movement points were added to %2 and accompanying units!",
3021                               mp), mp, hero->getName());
3022   TimedMessageDialog dialog(*window, s, 30);
3023   dialog.run_and_hide();
3024   return;
3025 }
3026 
on_bigmap_scrolled(GdkEventScroll * event)3027 bool GameWindow::on_bigmap_scrolled(GdkEventScroll* event)
3028 {
3029   if (!game)
3030     return true;
3031   bool ret = game->get_bigmap().scroll(event);
3032   game->get_bigmap().update_mouse_cursor();
3033   return ret;
3034 }
3035 
on_popup_stack_menu(Stack * stack)3036 void GameWindow::on_popup_stack_menu (Stack *stack)
3037 {
3038   Gtk::Menu *menu = manage(new Gtk::Menu);
3039   Glib::ustring s = _("Info...");
3040   Gtk::MenuItem *item = manage(new Gtk::MenuItem(s));
3041   item->signal_activate().connect (method(on_stack_info_activated));
3042   item->show();
3043   menu->add(*item);
3044 
3045   s = _("Search");
3046   item = manage(new Gtk::MenuItem(s));
3047   item->signal_activate().connect
3048     (sigc::mem_fun(game, &Game::search_selected_stack));
3049   item->set_sensitive(GameMap::can_search (stack));
3050   item->show();
3051   menu->add(*item);
3052 
3053   StackTile *st = GameMap::getStacks (stack->getPos());
3054   if (st->size () > 1)
3055     s = _("Group");
3056   else
3057     s = _("Ungroup");
3058   item = manage(new Gtk::MenuItem(s));
3059   item->signal_activate().connect (method(on_group_ungroup_activated));
3060   item->show();
3061   menu->add(*item);
3062   if (stack->hasPath() && stack->enoughMoves())
3063     {
3064       s = _("Travel Along Path");
3065       item = manage(new Gtk::MenuItem(s));
3066       item->signal_activate().connect
3067         (sigc::mem_fun(game, &Game::move_selected_stack_along_path));
3068       item->show();
3069       menu->add(*item);
3070     }
3071 
3072    s = _("Stay Here");
3073    item = manage(new Gtk::MenuItem(s));
3074    item->signal_activate().connect
3075      (sigc::mem_fun(game, &Game::park_selected_stack));
3076    item->show();
3077    menu->add(*item);
3078 
3079   s = _("Defend");
3080   item = manage(new Gtk::MenuItem(s));
3081   item->signal_activate().connect
3082     (sigc::mem_fun(game, &Game::defend_selected_stack));
3083   item->show();
3084   menu->add(*item);
3085 
3086   s = _("Disband...");
3087   item = manage(new Gtk::MenuItem(s));
3088   item->signal_activate().connect (method(on_disband_activated));
3089   item->show();
3090   menu->add(*item);
3091   menu->accelerate (*window);
3092   menu->popup_at_pointer (reinterpret_cast<const GdkEvent*>(button_event));
3093 }
3094 
on_pointing_at_new_tile(Vector<int> tile)3095 void GameWindow::on_pointing_at_new_tile(Vector<int> tile)
3096 {
3097   pos_label->set_text(String::ucompose("(%1, %2)", tile.x, tile.y));
3098 }
3099 
on_window_state_event(GdkEventWindowState * e)3100 bool GameWindow::on_window_state_event (GdkEventWindowState *e)
3101 {
3102   if (e->window == window->get_window ()->gobj ())
3103     {
3104       if (e->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
3105         {
3106           if (e->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
3107             ; //maximized
3108           else
3109             window->resize (unmaximized_box.get_width (),
3110                             unmaximized_box.get_height ());
3111         }
3112     }
3113   return false;
3114 }
3115 
on_configure_event(GdkEventConfigure * e)3116 bool GameWindow::on_configure_event (GdkEventConfigure *e)
3117 {
3118   if (unmaximized_box.get_width () == 0)
3119     {
3120       unmaximized_box.set_width (e->width);
3121       unmaximized_box.set_height (e->height);
3122     }
3123   return false;
3124 }
3125 
on_quick_help_activated()3126 void GameWindow::on_quick_help_activated()
3127 {
3128   show_quick_help.emit();
3129 }
3130 
on_best_fit_activated()3131 void GameWindow::on_best_fit_activated ()
3132 {
3133   set_default_bigmap_zoom();
3134 }
3135 
on_tutorial_activated()3136 void GameWindow::on_tutorial_activated ()
3137 {
3138   GError *errs = NULL;
3139   gtk_show_uri(window->get_screen()->gobj(),
3140                "https://vimeo.com/409439854", 0, &errs);
3141   return;
3142 }
3143