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