1 // Copyright (C) 2007, 2008, Ole Laursen
2 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Library General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 #include <sigc++/functors/mem_fun.h>
27 #include <sigc++/functors/ptr_fun.h>
28 #include <sigc++/adaptors/hide.h>
33 #include "game-window.h"
35 #include "glade-helpers.h"
36 #include "image-helpers.h"
37 #include "input-helpers.h"
38 #include "error-utils.h"
42 #include "fight-window.h"
43 #include "city-window.h"
44 #include "army-gains-level-dialog.h"
45 #include "hero-dialog.h"
46 #include "sage-dialog.h"
47 #include "ruin-rewarded-dialog.h"
48 #include "hero-offer-dialog.h"
49 #include "surrender-dialog.h"
50 #include "surrender-refused-dialog.h"
51 #include "quest-report-dialog.h"
52 #include "quest-assigned-dialog.h"
53 #include "quest-completed-dialog.h"
54 #include "preferences-dialog.h"
55 #include "fight-order-dialog.h"
56 #include "hero-levels-dialog.h"
57 #include "ruin-report-dialog.h"
58 #include "army-bonus-dialog.h"
59 #include "item-bonus-dialog.h"
60 #include "history-report-dialog.h"
61 #include "report-dialog.h"
62 #include "triumphs-dialog.h"
63 #include "diplomacy-report-dialog.h"
64 #include "diplomacy-dialog.h"
65 #include "stack-info-dialog.h"
66 #include "timed-message-dialog.h"
67 #include "destination-dialog.h"
68 #include "decorated.h"
70 #include "ucompose.hpp"
75 #include "gamebigmap.h"
77 #include "GameScenarioOptions.h"
83 #include "signpostlist.h"
84 #include "playerlist.h"
87 #include "heroproto.h"
89 #include "templelist.h"
92 #include "QuestsManager.h"
94 #include "GraphicsCache.h"
95 #include "QuestsManager.h"
97 #include "QCitySack.h"
98 #include "QCityRaze.h"
99 #include "QCityOccupy.h"
100 #include "QPillageGold.h"
102 #include "armysetlist.h"
103 #include "tilesetlist.h"
104 #include "CreateScenario.h"
106 #include "Configuration.h"
109 #include "shieldsetlist.h"
110 #include "game-server.h"
111 #include "game-client.h"
112 #include "NextTurnHotseat.h"
113 #include "NextTurnPbm.h"
114 #include "NextTurnNetworked.h"
115 #include "pbm-game-server.h"
116 #include "network_player.h"
117 #include "stacktile.h"
120 GameWindow::GameWindow()
122 stack_info_button_table = NULL;
124 stack_info_tip = NULL;
125 army_info_tip = NULL;
126 city_info_tip = NULL;
132 Glib::RefPtr<Gtk::Builder> xml
133 = Gtk::Builder::create_from_file(get_glade_path() + "/game-window.ui");
136 xml->get_widget("window", w);
138 w->set_icon_from_file(File::getMiscFile("various/castle_icon.png"));
139 decorate(window, File::getMiscFile("various/back.bmp"));
141 window_closed.connect
142 (sigc::mem_fun(*this, &GameWindow::on_quit_activated));
144 w->signal_delete_event().connect
145 (sigc::mem_fun(*this, &GameWindow::on_delete_event));
147 xml->get_widget("menubar", menubar);
148 xml->get_widget("bigmap_drawingarea", bigmap_drawingarea);
149 //bigmap_drawingarea->set_double_buffered(false);
150 bigmap_drawingarea->signal_expose_event().connect
151 (sigc::mem_fun(*this, &GameWindow::on_bigmap_exposed));
152 bigmap_drawingarea->signal_size_allocate().connect
153 (sigc::mem_fun(*this, &GameWindow::on_bigmap_surface_changed));
154 bigmap_drawingarea->grab_focus();
155 xml->get_widget("bigmap_eventbox", bigmap_eventbox);
156 bigmap_eventbox->add_events(Gdk::KEY_PRESS_MASK |
157 Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
158 Gdk::POINTER_MOTION_MASK);
159 bigmap_eventbox->signal_key_press_event().connect(
160 sigc::mem_fun(*this, &GameWindow::on_bigmap_key_event));
161 bigmap_eventbox->signal_key_release_event().connect(
162 sigc::mem_fun(*this, &GameWindow::on_bigmap_key_event));
163 bigmap_eventbox->signal_button_press_event().connect
164 (sigc::mem_fun(*this, &GameWindow::on_bigmap_mouse_button_event));
165 bigmap_eventbox->signal_button_release_event().connect
166 (sigc::mem_fun(*this, &GameWindow::on_bigmap_mouse_button_event));
167 bigmap_eventbox->signal_motion_notify_event().connect
168 (sigc::mem_fun(*this, &GameWindow::on_bigmap_mouse_motion_event));
169 bigmap_eventbox->signal_scroll_event().connect
170 (sigc::mem_fun(*this, &GameWindow::on_bigmap_scroll_event));
171 xml->get_widget("stack_info_box", stack_info_box);
172 xml->get_widget("stack_info_container", stack_info_container);
174 xml->get_widget("bigmap_viewport", vp);
175 decorate_border(vp, 175);
176 xml->get_widget("group_moves_label", group_moves_label);
177 xml->get_widget("group_togglebutton", group_ungroup_toggle);
178 group_ungroup_toggle->signal_toggled().connect
179 (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_group_toggled),
180 group_ungroup_toggle));
181 xml->get_widget("terrain_image", terrain_image);
182 xml->get_widget("stats_box", stats_box);
183 xml->get_widget("progress_box", progress_box);
184 xml->get_widget("turn_progressbar", turn_progressbar);
185 xml->get_widget("progress_status_label", progress_status_label);
186 stack_info_box->hide();
188 progress_box->show();
191 xml->get_widget("map_drawingarea", map_drawingarea);
192 //map_drawingarea->set_double_buffered(false);
193 map_drawingarea->signal_expose_event().connect
194 (sigc::mem_fun(*this, &GameWindow::on_smallmap_exposed));
195 xml->get_widget("map_eventbox", map_eventbox);
196 xml->get_widget("map_container", map_container);
197 map_eventbox->add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
198 Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK);
199 map_eventbox->signal_button_press_event().connect
200 (sigc::mem_fun(*this, &GameWindow::on_smallmap_mouse_button_event));
201 map_eventbox->signal_button_release_event().connect
202 (sigc::mem_fun(*this, &GameWindow::on_smallmap_mouse_button_event));
203 map_eventbox->signal_motion_notify_event().connect
204 (sigc::mem_fun(*this, &GameWindow::on_smallmap_mouse_motion_event));
206 xml->get_widget("map_viewport", mvp);
207 decorate_border(mvp, 175);
208 xml->get_widget("control_panel_viewport", vp);
209 decorate_border(vp, 175);
212 xml->get_widget("cities_stats_image", cities_stats_image);
213 cities_stats_image->property_file() = File::getMiscFile("various/smallcity.png");
214 xml->get_widget("gold_stats_image", gold_stats_image);
215 gold_stats_image->property_file() = File::getMiscFile("various/smalltreasury.png");
216 xml->get_widget("income_stats_image", income_stats_image);
217 income_stats_image->property_file() = File::getMiscFile("various/smallincome.png");
218 xml->get_widget("upkeep_stats_image", upkeep_stats_image);
219 upkeep_stats_image->property_file() = File::getMiscFile("various/smallupkeep.png");
221 xml->get_widget("cities_stats_label", cities_stats_label);
222 xml->get_widget("gold_stats_label", gold_stats_label);
223 xml->get_widget("income_stats_label", income_stats_label);
224 xml->get_widget("upkeep_stats_label", upkeep_stats_label);
225 xml->get_widget("turn_label", turn_label);
226 xml->get_widget("turn_hbox", turn_hbox);
227 xml->get_widget("shield_image_0", shield_image[0]);
228 xml->get_widget("shield_image_1", shield_image[1]);
229 xml->get_widget("shield_image_2", shield_image[2]);
230 xml->get_widget("shield_image_3", shield_image[3]);
231 xml->get_widget("shield_image_4", shield_image[4]);
232 xml->get_widget("shield_image_5", shield_image[5]);
233 xml->get_widget("shield_image_6", shield_image[6]);
234 xml->get_widget("shield_image_7", shield_image[7]);
237 xml->get_widget("next_movable_button", next_movable_button);
238 xml->get_widget("center_button", center_button);
239 xml->get_widget("diplomacy_button", diplomacy_button);
240 xml->get_widget("defend_button", defend_button);
241 xml->get_widget("park_button", park_button);
242 xml->get_widget("deselect_button", deselect_button);
243 xml->get_widget("search_button", search_button);
244 xml->get_widget("move_button", move_button);
245 xml->get_widget("move_all_button", move_all_button);
246 xml->get_widget("end_turn_button", end_turn_button);
247 /* xml->get_widget("nw_keypad_button", nw_keypad_button);
248 xml->get_widget("n_keypad_button", n_keypad_button);
249 xml->get_widget("ne_keypad_button", ne_keypad_button);
250 xml->get_widget("e_keypad_button", e_keypad_button);
251 xml->get_widget("w_keypad_button", w_keypad_button);
252 xml->get_widget("sw_keypad_button", sw_keypad_button);
253 xml->get_widget("s_keypad_button", s_keypad_button);
254 xml->get_widget("se_keypad_button", se_keypad_button); */
257 d_button_images = disassemble_row(File::getMiscFile("various/buttons.png"), 11);
258 Gtk::Image *button_image2 = new Gtk::Image();
259 button_image2->property_pixbuf() = d_button_images[2]->to_pixbuf();
260 next_movable_button->add(*manage(button_image2));
261 Gtk::Image *button_image5 = new Gtk::Image();
262 button_image5->property_pixbuf() = d_button_images[5]->to_pixbuf();
263 center_button->add(*manage(button_image5));
264 Gtk::Image *button_image0 = new Gtk::Image();
265 button_image0->property_pixbuf() = d_button_images[0]->to_pixbuf();
266 diplomacy_button->add(*manage(button_image0));
267 Gtk::Image *button_image6 = new Gtk::Image();
268 button_image6->property_pixbuf() = d_button_images[6]->to_pixbuf();
269 defend_button->add(*manage(button_image6));
270 Gtk::Image * button_image1 = new Gtk::Image();
271 button_image1->property_pixbuf() = d_button_images[1]->to_pixbuf();
272 park_button->add(*manage(button_image1));
273 Gtk::Image * button_image7 = new Gtk::Image();
274 button_image7->property_pixbuf() = d_button_images[7]->to_pixbuf();
275 deselect_button->add(*manage(button_image7));
276 Gtk::Image * button_image9 = new Gtk::Image();
277 button_image9->property_pixbuf() = d_button_images[9]->to_pixbuf();
278 search_button->add(*manage(button_image9));
279 Gtk::Image * button_image3 = new Gtk::Image();
280 button_image3->property_pixbuf() = d_button_images[3]->to_pixbuf();
281 move_button->add(*manage(button_image3));
282 Gtk::Image * button_image4 = new Gtk::Image();
283 button_image4->property_pixbuf() = d_button_images[4]->to_pixbuf();
284 move_all_button->add(*manage(button_image4));
285 Gtk::Image * button_image10 = new Gtk::Image();
286 button_image10->property_pixbuf() = d_button_images[10]->to_pixbuf();
287 end_turn_button->add(*manage(button_image10));
289 /* d_arrow_images = disassemble_row(File::getMiscFile("various/arrows.png"),
291 Gtk::Image * arrow_image0 = new Gtk::Image();
292 arrow_image0->property_pixbuf() = d_arrow_images[0]->to_pixbuf();
293 nw_keypad_button->add(*manage(arrow_image0));
294 Gtk::Image * arrow_image1 = new Gtk::Image();
295 arrow_image1->property_pixbuf() = d_arrow_images[1]->to_pixbuf();
296 n_keypad_button->add(*manage(arrow_image1));
297 Gtk::Image * arrow_image2 = new Gtk::Image();
298 arrow_image2->property_pixbuf() = d_arrow_images[2]->to_pixbuf();
299 ne_keypad_button->add(*manage(arrow_image2));
300 Gtk::Image * arrow_image3 = new Gtk::Image();
301 arrow_image3->property_pixbuf() = d_arrow_images[3]->to_pixbuf();
302 e_keypad_button->add(*manage(arrow_image3));
303 Gtk::Image * arrow_image4 = new Gtk::Image();
304 arrow_image4->property_pixbuf() = d_arrow_images[4]->to_pixbuf();
305 w_keypad_button->add(*manage(arrow_image4));
306 Gtk::Image * arrow_image5 = new Gtk::Image();
307 arrow_image5->property_pixbuf() = d_arrow_images[5]->to_pixbuf();
308 sw_keypad_button->add(*manage(arrow_image5));
309 Gtk::Image * arrow_image6 = new Gtk::Image();
310 arrow_image6->property_pixbuf() = d_arrow_images[6]->to_pixbuf();
311 s_keypad_button->add(*manage(arrow_image6));
312 Gtk::Image * arrow_image7 = new Gtk::Image();
313 arrow_image7->property_pixbuf() = d_arrow_images[7]->to_pixbuf();
314 se_keypad_button->add(*manage(arrow_image7)); */
316 // connect callbacks for the menu
317 xml->get_widget("new_game_menuitem", new_game_menuitem);
318 new_game_menuitem->signal_activate().connect
319 (sigc::mem_fun(*this, &GameWindow::on_quit_activated));
320 xml->get_widget("load_game_menuitem", load_game_menuitem);
321 load_game_menuitem->signal_activate().connect
322 (sigc::mem_fun(*this, &GameWindow::on_load_game_activated));
323 xml->get_widget("save_game_menuitem", save_game_menuitem);
324 save_game_menuitem->signal_activate().connect
325 (sigc::mem_fun(*this, &GameWindow::on_save_game_activated));
326 xml->get_widget("save_game_as_menuitem", save_game_as_menuitem);
327 save_game_as_menuitem->signal_activate().connect
328 (sigc::mem_fun(*this, &GameWindow::on_save_game_as_activated));
329 xml->get_widget("quit_menuitem", quit_menuitem);
330 quit_menuitem->signal_activate().connect
331 (sigc::mem_fun(*this, &GameWindow::on_quit_activated));
332 xml->get_widget("toggle_grid_menuitem", toggle_grid_menuitem);
333 toggle_grid_menuitem->signal_activate().connect
334 (sigc::mem_fun(*this, &GameWindow::on_grid_toggled));
335 xml->get_widget("army_report_menuitem", army_report_menuitem);
336 army_report_menuitem->signal_activate().connect
337 (sigc::mem_fun(*this, &GameWindow::on_army_report_activated));
338 xml->get_widget("city_report_menuitem", city_report_menuitem);
339 city_report_menuitem->signal_activate().connect
340 (sigc::mem_fun(*this, &GameWindow::on_city_report_activated));
341 xml->get_widget("gold_report_menuitem", gold_report_menuitem);
342 gold_report_menuitem->signal_activate().connect
343 (sigc::mem_fun(*this, &GameWindow::on_gold_report_activated));
344 xml->get_widget("winning_report_menuitem", winning_report_menuitem);
345 winning_report_menuitem->signal_activate().connect
346 (sigc::mem_fun(*this, &GameWindow::on_winning_report_activated));
347 xml->get_widget("diplomacy_report_menuitem", diplomacy_report_menuitem);
348 xml->get_widget("quests_menuitem", quests_menuitem);
349 quests_menuitem->signal_activate().connect
350 (sigc::mem_fun(*this, &GameWindow::on_quests_activated));
351 xml->get_widget("fullscreen_menuitem", fullscreen_menuitem);
352 fullscreen_menuitem->signal_activate().connect
353 (sigc::mem_fun(*this, &GameWindow::on_fullscreen_activated));
354 xml->get_widget("preferences_menuitem", preferences_menuitem);
355 preferences_menuitem->signal_activate().connect
356 (sigc::mem_fun(*this, &GameWindow::on_preferences_activated));
358 xml->get_widget("show_lobby_menuitem", show_lobby_menuitem);
359 show_lobby_menuitem->signal_activate().connect
360 (sigc::mem_fun(*this, &GameWindow::on_show_lobby_activated));
361 xml->get_widget("end_turn_menuitem", end_turn_menuitem);
362 xml->get_widget("move_all_menuitem", move_all_menuitem);
363 xml->get_widget("disband_menuitem", disband_menuitem);
364 xml->get_widget("stack_info_menuitem", stack_info_menuitem);
365 xml->get_widget("signpost_menuitem", signpost_menuitem);
366 xml->get_widget("search_menuitem", search_menuitem);
367 xml->get_widget("inspect_menuitem", inspect_menuitem);
368 xml->get_widget("plant_standard_menuitem", plant_standard_menuitem);
369 xml->get_widget("city_history_menuitem", city_history_menuitem);
370 xml->get_widget("ruin_history_menuitem", ruin_history_menuitem);
371 xml->get_widget("event_history_menuitem", event_history_menuitem);
372 xml->get_widget("gold_history_menuitem", gold_history_menuitem);
373 xml->get_widget("winner_history_menuitem", winner_history_menuitem);
374 xml->get_widget("group_ungroup_menuitem", group_ungroup_menuitem);
375 xml->get_widget("leave_menuitem", leave_menuitem);
376 xml->get_widget("next_menuitem", next_menuitem);
378 xml->get_widget("fight_order_menuitem", fight_order_menuitem);
379 fight_order_menuitem->signal_activate().connect
380 (sigc::mem_fun(*this, &GameWindow::on_fight_order_activated));
381 xml->get_widget("resign_menuitem", resign_menuitem);
382 resign_menuitem->signal_activate().connect
383 (sigc::mem_fun(*this, &GameWindow::on_resign_activated));
384 xml->get_widget("production_menuitem", production_menuitem);
385 production_menuitem->signal_activate().connect
386 (sigc::mem_fun(*this, &GameWindow::on_production_activated));
387 xml->get_widget("cities_menuitem", cities_menuitem);
388 cities_menuitem->signal_activate().connect
389 (sigc::mem_fun(*this, &GameWindow::on_production_activated));
390 xml->get_widget("build_menuitem", build_menuitem);
391 build_menuitem->signal_activate().connect
392 (sigc::mem_fun(*this, &GameWindow::on_production_activated));
393 xml->get_widget("vectoring_menuitem", vectoring_menuitem);
394 vectoring_menuitem->signal_activate().connect
395 (sigc::mem_fun(*this, &GameWindow::on_vectoring_activated));
396 xml->get_widget("levels_menuitem", levels_menuitem);
397 levels_menuitem->signal_activate().connect
398 (sigc::mem_fun(*this, &GameWindow::on_levels_activated));
399 xml->get_widget("inspect_menuitem", inspect_menuitem);
400 inspect_menuitem->signal_activate().connect
401 (sigc::mem_fun(*this, &GameWindow::on_inspect_activated));
402 xml->get_widget("ruin_report_menuitem", ruin_report_menuitem);
403 ruin_report_menuitem->signal_activate().connect
404 (sigc::mem_fun(*this, &GameWindow::on_ruin_report_activated));
405 xml->get_widget("army_bonus_menuitem", army_bonus_menuitem);
406 army_bonus_menuitem->signal_activate().connect
407 (sigc::mem_fun(*this, &GameWindow::on_army_bonus_activated));
408 xml->get_widget("item_bonus_menuitem", item_bonus_menuitem);
409 item_bonus_menuitem->signal_activate().connect
410 (sigc::mem_fun(*this, &GameWindow::on_item_bonus_activated));
411 xml->get_widget("production_report_menuitem", production_report_menuitem);
412 production_report_menuitem->signal_activate().connect
413 (sigc::mem_fun(*this, &GameWindow::on_production_report_activated));
414 xml->get_widget("triumphs_menuitem", triumphs_menuitem);
415 triumphs_menuitem->signal_activate().connect
416 (sigc::mem_fun(*this, &GameWindow::on_triumphs_activated));
417 xml->get_widget("help_about_menuitem", help_about_menuitem);
418 help_about_menuitem->signal_activate().connect
419 (sigc::mem_fun(*this, &GameWindow::on_help_about_activated));
420 xml->get_widget("online_help_menuitem", online_help_menuitem);
421 online_help_menuitem->signal_activate().connect
422 (sigc::mem_fun(*this, &GameWindow::on_online_help_activated));
423 d_quick_fights = false;
425 if (Configuration::s_decorated == true)
428 Glib::RefPtr<Gtk::Style> copy;
429 Glib::RefPtr<Gdk::Pixbuf> back;
430 Glib::RefPtr<Gdk::Pixmap> pixmap;
431 Glib::RefPtr<Gdk::Bitmap> bitmap;
432 copy = menubar->get_style()->copy();
433 back = Gdk::Pixbuf::create_from_file(File::getMiscFile("various/back.bmp"));
434 pixmap = Gdk::Pixmap::create
435 (window->get_window(), back->get_width(), back->get_height());
436 back->composite_color(back, 0, 0,
437 back->get_width(), back->get_height(),
438 0.0, 0.0, 1.0, 1.0, Gdk::INTERP_NEAREST, 127,
440 back->render_pixmap_and_mask(pixmap, bitmap, 10);
441 copy->set_bg_pixmap(Gtk::STATE_NORMAL, pixmap);
442 menubar->set_style(copy);
447 GameWindow::~GameWindow()
449 std::list<sigc::connection>::iterator it = connections.begin();
450 for (; it != connections.end(); it++)
453 clear_army_buttons();
456 delete army_info_tip;
457 army_info_tip = NULL;
461 delete city_info_tip;
462 city_info_tip = NULL;
466 delete stack_info_tip;
467 stack_info_tip = NULL;
474 if (stack_info_button_table != NULL)
475 delete stack_info_button_table;
479 void GameWindow::show()
481 next_movable_button->show_all();
482 center_button->show_all();
483 diplomacy_button->show_all();
484 defend_button->show_all();
485 park_button->show_all();
486 deselect_button->show_all();
487 search_button->show_all();
488 move_button->show_all();
489 move_all_button->show_all();
490 end_turn_button->show_all();
491 /* nw_keypad_button->show_all();
492 n_keypad_button->show_all();
493 ne_keypad_button->show_all();
494 e_keypad_button->show_all();
495 w_keypad_button->show_all();
496 sw_keypad_button->show_all();
497 s_keypad_button->show_all();
498 se_keypad_button->show_all(); */
500 bigmap_drawingarea->show_all();
503 //seems unnecessary, but this is for starting up a second game after
504 //closing the first game window.
505 //fixme: find out why this line is necessary
506 on_bigmap_surface_changed(bigmap_drawingarea->get_allocation());
509 void GameWindow::hide()
514 void GameWindow::init(int width, int height)
518 void GameWindow::new_network_game(GameScenario *game_scenario, NextTurn *next_turn)
520 if (GameServer::getInstance()->isListening() == true)
521 GameServer::getInstance()->round_begins.connect(sigc::mem_fun(this, &GameWindow::on_remote_next_player_turn));
523 GameClient::getInstance()->round_begins.connect(sigc::mem_fun(this, &GameWindow::on_remote_next_player_turn));
524 bool success = false;
526 success = setup_game(game_scenario, next_turn);
529 setup_signals(game_scenario);
534 void GameWindow::continue_network_game(NextTurn *next_turn)
539 void GameWindow::new_game(GameScenario *game_scenario, NextTurn *next_turn)
541 bool success = false;
542 success = setup_game(game_scenario, next_turn);
545 setup_signals(game_scenario);
547 //we don't get here until the game ends.
550 void GameWindow::load_game(GameScenario *game_scenario, NextTurn *next_turn)
552 bool success = false;
553 success = setup_game(game_scenario, next_turn);
557 game->get_bigmap().screen_size_changed(bigmap_drawingarea->get_allocation());
558 setup_signals(game_scenario);
560 //we don't get here until the game ends, or a human player ends a turn.
561 if (Playerlist::getInstance()->countPlayersAlive())
565 void GameWindow::setup_button(Gtk::Button *button,
566 sigc::slot<void> slot,
567 sigc::signal<void, bool> &game_signal)
569 connections.push_back (button->signal_clicked().connect(slot));
570 connections.push_back
571 (game_signal.connect(sigc::mem_fun(button, &Gtk::Widget::set_sensitive)));
574 void GameWindow::setup_menuitem(Gtk::MenuItem *item,
575 sigc::slot<void> slot,
576 sigc::signal<void, bool> &game_signal)
578 connections.push_back (item->signal_activate().connect(slot));
579 connections.push_back
580 (game_signal.connect(sigc::mem_fun(item, &Gtk::Widget::set_sensitive)));
583 void GameWindow::setup_signals(GameScenario *game_scenario)
585 // get rid of the connections that might be still around from last time
586 std::list<sigc::connection>::iterator it = connections.begin();
587 for (; it != connections.end(); it++)
591 setup_button(next_movable_button,
592 sigc::mem_fun(game, &Game::select_next_movable_stack),
593 game->can_select_next_movable_stack);
594 setup_button(center_button,
595 sigc::mem_fun(game, &Game::center_selected_stack),
596 game->can_center_selected_stack);
598 connections.push_back (diplomacy_button->signal_clicked().connect
599 (sigc::mem_fun (*this, &GameWindow::on_diplomacy_button_clicked)));
600 connections.push_back
601 (game->received_diplomatic_proposal.connect
602 (sigc::mem_fun(*this, &GameWindow::change_diplomacy_button_image)));
603 connections.push_back
604 (game->city_too_poor_to_produce.connect
605 (sigc::mem_fun(*this, &GameWindow::show_city_production_report)));
606 connections.push_back
607 (game->commentator_comments.connect
608 (sigc::mem_fun(*this, &GameWindow::on_commentator_comments)));
609 connections.push_back
610 (game->can_end_turn.connect
611 (sigc::mem_fun(*this, &GameWindow::update_diplomacy_button)));
613 setup_button(defend_button,
614 sigc::mem_fun(game, &Game::defend_selected_stack),
615 game->can_defend_selected_stack);
616 setup_button(park_button,
617 sigc::mem_fun(game, &Game::park_selected_stack),
618 game->can_park_selected_stack);
619 setup_button(deselect_button,
620 sigc::mem_fun(game, &Game::deselect_selected_stack),
621 game->can_deselect_selected_stack);
622 setup_button(search_button,
623 sigc::mem_fun(game, &Game::search_selected_stack),
624 game->can_search_selected_stack);
625 setup_button(move_button,
626 sigc::mem_fun(game, &Game::move_selected_stack_along_path),
627 game->can_move_selected_stack_along_path);
628 setup_button(move_all_button,
629 sigc::mem_fun(game, &Game::move_all_stacks),
630 game->can_move_all_stacks);
631 setup_button(end_turn_button,
632 sigc::mem_fun(game, &Game::end_turn),
634 if (game_scenario->getPlayMode() == GameScenario::PLAY_BY_MAIL)
635 setup_button(end_turn_button,
636 sigc::mem_fun(*this, &GameWindow::end_turn_play_by_mail),
638 /* setup_button(nw_keypad_button,
639 sigc::mem_fun(game, &Game::move_selected_stack_northwest),
641 setup_button(n_keypad_button,
642 sigc::mem_fun(game, &Game::move_selected_stack_north),
644 setup_button(ne_keypad_button,
645 sigc::mem_fun(game, &Game::move_selected_stack_northeast),
647 setup_button(e_keypad_button,
648 sigc::mem_fun(game, &Game::move_selected_stack_east),
650 setup_button(w_keypad_button,
651 sigc::mem_fun(game, &Game::move_selected_stack_west),
653 setup_button(sw_keypad_button,
654 sigc::mem_fun(game, &Game::move_selected_stack_southwest),
656 setup_button(s_keypad_button,
657 sigc::mem_fun(game, &Game::move_selected_stack_south),
659 setup_button(se_keypad_button,
660 sigc::mem_fun(game, &Game::move_selected_stack_southeast),
661 game->can_end_turn); */
662 setup_menuitem(move_all_menuitem,
663 sigc::mem_fun(game, &Game::move_all_stacks),
664 game->can_move_all_stacks);
665 setup_menuitem(end_turn_menuitem,
666 sigc::mem_fun(game, &Game::end_turn),
668 if (game_scenario->getPlayMode() == GameScenario::PLAY_BY_MAIL)
669 setup_menuitem(end_turn_menuitem,
670 sigc::mem_fun(*this, &GameWindow::end_turn_play_by_mail),
672 if (game_scenario->getPlayMode() == GameScenario::NETWORKED)
674 load_game_menuitem->set_sensitive(false);
675 if (GameServer::getInstance()->isListening() == false)
677 save_game_menuitem->set_sensitive(false);
678 save_game_as_menuitem->set_sensitive(false);
682 show_lobby_menuitem->set_sensitive(false);
684 setup_menuitem(disband_menuitem,
685 sigc::mem_fun(*this, &GameWindow::on_disband_activated),
686 game->can_disband_stack);
687 setup_menuitem(stack_info_menuitem,
688 sigc::mem_fun(*this, &GameWindow::on_stack_info_activated),
689 game->can_deselect_selected_stack);
690 setup_menuitem(signpost_menuitem,
691 sigc::mem_fun(*this, &GameWindow::on_signpost_activated),
692 game->can_change_signpost);
693 setup_menuitem(search_menuitem,
694 sigc::mem_fun(game, &Game::search_selected_stack),
695 game->can_search_selected_stack);
696 setup_menuitem(plant_standard_menuitem,
698 &GameWindow::on_plant_standard_activated),
699 game->can_plant_standard_selected_stack);
700 setup_menuitem(city_history_menuitem,
701 sigc::mem_fun(*this, &GameWindow::on_city_history_activated),
702 game->can_see_history);
703 setup_menuitem(ruin_history_menuitem,
704 sigc::mem_fun(*this, &GameWindow::on_ruin_history_activated),
705 game->can_see_history);
706 setup_menuitem(gold_history_menuitem,
707 sigc::mem_fun(*this, &GameWindow::on_gold_history_activated),
708 game->can_see_history);
709 setup_menuitem(event_history_menuitem,
710 sigc::mem_fun(*this, &GameWindow::on_event_history_activated),
711 game->can_see_history);
712 setup_menuitem(winner_history_menuitem,
713 sigc::mem_fun(*this, &GameWindow::on_winner_history_activated),
714 game->can_see_history);
715 setup_menuitem(diplomacy_report_menuitem,
717 &GameWindow::on_diplomacy_report_activated),
718 game->can_see_diplomacy);
719 setup_menuitem(group_ungroup_menuitem,
720 sigc::mem_fun(*this, &GameWindow::on_group_ungroup_activated),
721 game->can_group_ungroup_selected_stack);
722 setup_menuitem(leave_menuitem,
723 sigc::mem_fun(game, &Game::park_selected_stack),
724 game->can_park_selected_stack);
725 setup_menuitem(next_menuitem,
726 sigc::mem_fun(game, &Game::select_next_movable_stack),
727 game->can_select_next_movable_stack);
729 // setup game callbacks
730 connections.push_back
731 (game->game_stopped.connect
732 (sigc::mem_fun(*this, &GameWindow::on_game_stopped)));
733 connections.push_back
734 (game->sidebar_stats_changed.connect
735 (sigc::mem_fun(*this, &GameWindow::on_sidebar_stats_changed)));
736 connections.push_back
737 (game->progress_status_changed.connect
738 (sigc::mem_fun(*this, &GameWindow::on_progress_status_changed)));
739 connections.push_back
740 (game->progress_changed.connect
741 (sigc::mem_fun(*this, &GameWindow::on_progress_changed)));
742 connections.push_back
743 (game->bigmap_changed.connect
744 (sigc::mem_fun(*this, &GameWindow::on_bigmap_changed)));
745 connections.push_back
746 (game->smallmap_changed.connect
747 (sigc::mem_fun(*this, &GameWindow::on_smallmap_changed)));
748 connections.push_back
749 (game->get_smallmap().view_slid.connect
750 (sigc::mem_fun(*this, &GameWindow::on_smallmap_slid)));
751 connections.push_back
752 (game->stack_info_changed.connect
753 (sigc::mem_fun(*this, &GameWindow::on_stack_info_changed)));
754 connections.push_back
755 (game->map_tip_changed.connect
756 (sigc::mem_fun(*this, &GameWindow::on_bigmap_tip_changed)));
757 connections.push_back
758 (game->stack_tip_changed.connect
759 (sigc::mem_fun(*this, &GameWindow::on_stack_tip_changed)));
760 connections.push_back
761 (game->city_tip_changed.connect
762 (sigc::mem_fun(*this, &GameWindow::on_city_tip_changed)));
763 connections.push_back
764 (game->ruin_searched.connect
765 (sigc::mem_fun(*this, &GameWindow::on_ruin_searched)));
766 connections.push_back
767 (game->sage_visited.connect
768 (sigc::mem_fun(*this, &GameWindow::on_sage_visited)));
769 connections.push_back
770 (game->fight_started.connect
771 (sigc::mem_fun(*this, &GameWindow::on_fight_started)));
772 connections.push_back
773 (game->abbreviated_fight_started.connect
774 (sigc::mem_fun(*this, &GameWindow::on_abbreviated_fight_started)));
775 connections.push_back
776 (game->ruinfight_started.connect
777 (sigc::mem_fun(*this, &GameWindow::on_ruinfight_started)));
778 connections.push_back
779 (game->ruinfight_finished.connect
780 (sigc::mem_fun(*this, &GameWindow::on_ruinfight_finished)));
781 connections.push_back
782 (game->hero_offers_service.connect
783 (sigc::mem_fun(*this, &GameWindow::on_hero_offers_service)));
784 connections.push_back
785 (game->enemy_offers_surrender.connect
786 (sigc::mem_fun(*this, &GameWindow::on_enemy_offers_surrender)));
787 connections.push_back
788 (game->surrender_answered.connect
789 (sigc::mem_fun(*this, &GameWindow::on_surrender_answered)));
790 connections.push_back
791 (game->stack_considers_treachery.connect
792 (sigc::mem_fun(*this, &GameWindow::on_stack_considers_treachery)));
793 connections.push_back
794 (game->temple_searched.connect
795 (sigc::mem_fun(*this, &GameWindow::on_temple_searched)));
796 connections.push_back
797 (game->quest_assigned.connect
798 (sigc::mem_fun(*this, &GameWindow::on_quest_assigned)));
799 connections.push_back
800 (game->city_defeated.connect
801 (sigc::mem_fun(*this, &GameWindow::on_city_defeated)));
802 connections.push_back
803 (game->city_pillaged.connect
804 (sigc::mem_fun(*this, &GameWindow::on_city_pillaged)));
805 connections.push_back
806 (game->city_sacked.connect
807 (sigc::mem_fun(*this, &GameWindow::on_city_sacked)));
808 connections.push_back
809 (game->city_razed.connect
810 (sigc::mem_fun(*this, &GameWindow::on_city_razed)));
811 connections.push_back
812 (game->city_visited.connect
813 (sigc::mem_fun(*this, &GameWindow::on_city_visited)));
814 connections.push_back
815 (game->ruin_visited.connect
816 (sigc::mem_fun(*this, &GameWindow::on_ruin_visited)));
817 connections.push_back
818 (game->temple_visited.connect
819 (sigc::mem_fun(*this, &GameWindow::on_temple_visited)));
820 connections.push_back
821 (game->next_player_turn.connect
822 (sigc::mem_fun(*this, &GameWindow::on_next_player_turn)));
823 connections.push_back
824 (game->hero_arrives.connect
825 (sigc::mem_fun(*this, &GameWindow::on_hero_brings_allies)));
826 connections.push_back
827 (game->medal_awarded_to_army.connect
828 (sigc::mem_fun(*this, &GameWindow::on_medal_awarded_to_army)));
829 connections.push_back
830 (game->hero_gains_level.connect
831 (sigc::mem_fun(*this, &GameWindow::on_hero_gains_level)));
832 connections.push_back
833 (game->game_loaded.connect
834 (sigc::mem_fun(*this, &GameWindow::on_game_loaded)));
835 connections.push_back
836 (game->game_over.connect
837 (sigc::mem_fun(*this, &GameWindow::on_game_over)));
838 connections.push_back
839 (game->player_died.connect
840 (sigc::mem_fun(*this, &GameWindow::on_player_died)));
841 connections.push_back
842 (game->advice_asked.connect
843 (sigc::mem_fun(*this, &GameWindow::on_advice_asked)));
844 connections.push_back
845 (game->stack_moves.connect
846 (sigc::mem_fun(*this, &GameWindow::on_stack_moves)));
849 QuestsManager *q = QuestsManager::getInstance();
850 connections.push_back
851 (q->quest_completed.connect
852 (sigc::mem_fun(this, &GameWindow::on_quest_completed)));
853 connections.push_back
854 (q->quest_expired.connect
855 (sigc::mem_fun(this, &GameWindow::on_quest_expired)));
858 connections.push_back
859 (game->get_bigmap().cursor_changed.connect
860 (sigc::mem_fun(*this, &GameWindow::on_bigmap_cursor_changed)));
863 connections.push_back
864 (game->remote_next_player_turn.connect
865 (sigc::mem_fun(*this, &GameWindow::on_remote_next_player_turn)));
868 void GameWindow::show_city_production_report (bool destitute)
872 ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::PRODUCTION);
873 d.set_parent_window(*window);
878 void GameWindow::change_diplomacy_button_image (bool proposals_present)
880 /* switch up the image. */
881 if (proposals_present)
883 Gtk::Image *proposals_present_image = new Gtk::Image();
884 proposals_present_image->property_pixbuf() = d_button_images[8]->to_pixbuf();
885 diplomacy_button->property_image() = proposals_present_image;
889 Gtk::Image *proposals_not_present_image = new Gtk::Image();
890 proposals_not_present_image->property_pixbuf() = d_button_images[0]->to_pixbuf();
891 diplomacy_button->property_image() = proposals_not_present_image;
895 void GameWindow::end_turn_play_by_mail ()
897 //prompt to save the turn file!
898 Gtk::FileChooserDialog chooser(*window, _("Save your Turn file and mail it back"),
899 Gtk::FILE_CHOOSER_ACTION_SAVE);
900 Gtk::FileFilter trn_filter;
901 trn_filter.add_pattern("*.trn");
902 chooser.set_filter(trn_filter);
903 chooser.set_current_folder(Glib::get_home_dir());
905 chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
906 chooser.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
907 chooser.set_default_response(Gtk::RESPONSE_ACCEPT);
910 int res = chooser.run();
913 if (res == Gtk::RESPONSE_ACCEPT)
915 std::string filename = chooser.get_filename();
917 game->saveTurnFile(filename);
918 TimedMessageDialog dialog
919 (*window, ("Now send the turn file back to the game master."), 0);
926 void GameWindow::update_diplomacy_button (bool sensitive)
928 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
930 diplomacy_button->set_sensitive (false);
933 if (GameScenario::s_diplomacy == false)
935 diplomacy_button->set_sensitive (false);
938 diplomacy_button->set_sensitive(sensitive);
941 bool GameWindow::setup_game(GameScenario *game_scenario, NextTurn *nextTurn)
943 currently_selected_stack = NULL;
945 * this is done in GameScenario now.
946 Playerlist *pl = Playerlist::getInstance();
947 Armysetlist *al = Armysetlist::getInstance();
948 for (Playerlist::iterator i = pl->begin(); i != pl->end(); i++)
949 if ((*i)->getType() != Player::NETWORKED)
950 al->getArmyset((*i)->getArmyset())->instantiateImages();
952 GameMap::getInstance()->getTileset()->instantiateImages();
953 GameMap::getInstance()->getShieldset()->instantiateImages();
954 GameMap::getInstance()->getCityset()->instantiateImages();
957 Sound::getInstance()->haltMusic(false);
958 Sound::getInstance()->enableBackground();
962 game = new Game(game_scenario, nextTurn);
968 bool GameWindow::on_delete_event(GdkEventAny *e)
975 bool GameWindow::on_bigmap_mouse_button_event(GdkEventButton *e)
977 if (e->type != GDK_BUTTON_PRESS && e->type != GDK_BUTTON_RELEASE)
978 return true; // useless event
981 game->get_bigmap().mouse_button_event(to_input_event(e));
986 bool GameWindow::on_bigmap_mouse_motion_event(GdkEventMotion *e)
988 static guint prev = 0;
991 guint delta = e->time - prev;
992 if (delta > 40 || delta < 0)
994 game->get_bigmap().mouse_motion_event(to_input_event(e));
995 bigmap_drawingarea->grab_focus();
1002 bool GameWindow::on_bigmap_scroll_event(GdkEventScroll* event)
1004 switch (event->direction)
1006 case GDK_SCROLL_LEFT:
1007 case GDK_SCROLL_RIGHT:
1010 //game->get_bigmap().zoom_in();
1012 case GDK_SCROLL_DOWN:
1013 //game->get_bigmap().zoom_out();
1019 void GameWindow::on_bigmap_cursor_changed(GraphicsCache::CursorType cursor)
1021 bigmap_drawingarea->get_window()->set_cursor
1023 (Gdk::Display::get_default(),
1024 GraphicsCache::getInstance()->getCursorPic (cursor)->to_pixbuf(), 4, 4));
1027 bool GameWindow::on_bigmap_key_event(GdkEventKey *e)
1029 if (e->keyval == GDK_Shift_L || e->keyval == GDK_Shift_R)
1030 game->get_bigmap().set_shift_key_down (e->type == GDK_KEY_PRESS);
1031 if (e->keyval == GDK_Control_L || e->keyval == GDK_Control_R)
1032 game->get_bigmap().set_control_key_down (e->type == GDK_KEY_PRESS);
1037 bool GameWindow::on_smallmap_mouse_button_event(GdkEventButton *e)
1039 if (e->type != GDK_BUTTON_PRESS && e->type != GDK_BUTTON_RELEASE)
1040 return true; // useless event
1043 game->get_smallmap().mouse_button_event(to_input_event(e));
1048 bool GameWindow::on_smallmap_mouse_motion_event(GdkEventMotion *e)
1050 static guint prev = 0;
1053 guint delta = e->time - prev;
1054 if (delta > 100 || delta < 0)
1056 game->get_smallmap().mouse_motion_event(to_input_event(e));
1060 map_eventbox->get_window()->set_cursor
1062 (Gdk::Display::get_default(),
1063 GraphicsCache::getInstance()->getCursorPic
1064 (GraphicsCache::MAGNIFYING_GLASS)->to_pixbuf(), 8, 5));
1070 bool GameWindow::on_smallmap_exposed(GdkEventExpose *event)
1072 Glib::RefPtr<Gdk::Window> window = map_drawingarea->get_window();
1075 Glib::RefPtr<Gdk::Pixmap> surface = game->get_smallmap().get_surface();
1076 window->draw_drawable(map_drawingarea->get_style()->get_white_gc(),
1077 surface, event->area.x, event->area.y,
1078 event->area.x, event->area.y,
1079 event->area.width, event->area.height);
1083 bool GameWindow::on_bigmap_exposed(GdkEventExpose *event)
1085 Glib::RefPtr<Gdk::Window> window = bigmap_drawingarea->get_window();
1088 Glib::RefPtr<Gdk::Pixmap> surface = game->get_bigmap().get_surface();
1089 int width = 0, height = 0;
1090 surface->get_size(width, height);
1092 window->draw_drawable(bigmap_drawingarea->get_style()->get_white_gc(),
1093 surface, event->area.x, event->area.y,
1094 event->area.x, event->area.y,
1095 event->area.width, event->area.height);
1099 void GameWindow::on_bigmap_surface_changed(Gtk::Allocation box)
1101 static Gtk::Allocation last_box = Gtk::Allocation(0,0,1,1);
1104 sdl_initialized.emit();
1108 if (box.get_width() != last_box.get_width() || box.get_height() != last_box.get_height())
1110 //bigmap_drawingarea->set_allocation(box);
1111 game->get_bigmap().screen_size_changed(bigmap_drawingarea->get_allocation());
1118 void GameWindow::on_load_game_activated()
1120 Gtk::FileChooserDialog chooser(*window, _("Choose Game to Load"));
1121 Gtk::FileFilter sav_filter;
1122 sav_filter.add_pattern("*.sav");
1123 chooser.set_filter(sav_filter);
1124 chooser.set_current_folder(Configuration::s_savePath);
1126 chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1127 chooser.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1128 chooser.set_default_response(Gtk::RESPONSE_ACCEPT);
1131 int res = chooser.run();
1134 if (res == Gtk::RESPONSE_ACCEPT)
1136 std::string filename = chooser.get_filename();
1137 current_save_filename = filename;
1138 if (filename == (File::getSavePath() + "autosave.sav"))
1139 game->inhibitAutosaveRemoval(true);
1140 d_load_filename = filename;
1141 stop_game("load-game");
1142 //now look at on_game_stopped.
1146 void GameWindow::on_save_game_activated()
1148 if (current_save_filename.empty())
1149 on_save_game_as_activated();
1154 bool success = game->saveGame(current_save_filename);
1156 show_error(_("Game was not saved!"));
1161 void GameWindow::on_save_game_as_activated()
1163 Gtk::FileChooserDialog chooser(*window, _("Choose a Name"),
1164 Gtk::FILE_CHOOSER_ACTION_SAVE);
1165 Gtk::FileFilter sav_filter;
1166 sav_filter.add_pattern("*.sav");
1167 chooser.set_filter(sav_filter);
1168 chooser.set_current_folder(Configuration::s_savePath);
1170 chooser.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1171 chooser.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1172 chooser.set_default_response(Gtk::RESPONSE_ACCEPT);
1175 int res = chooser.run();
1178 if (res == Gtk::RESPONSE_ACCEPT)
1180 std::string filename = chooser.get_filename();
1182 current_save_filename = filename;
1186 bool success = game->saveGame(current_save_filename);
1188 show_error(_("Error saving game!"));
1193 void GameWindow::on_quit_activated()
1195 Gtk::Dialog* dialog;
1196 Glib::RefPtr<Gtk::Builder> xml
1197 = Gtk::Builder::create_from_file(get_glade_path() + "/game-quit-dialog.ui");
1198 xml->get_widget("dialog", dialog);
1199 Decorated decorator;
1200 decorator.decorate(dialog);
1201 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1203 dialog->set_transient_for(*window);
1205 int response = dialog->run();
1208 if (response == Gtk::RESPONSE_ACCEPT) //end the game
1215 void GameWindow::on_game_stopped()
1217 if (stop_action == "quit")
1226 else if (stop_action == "game-over")
1230 if (game_winner->getType() != Player::HUMAN)
1241 //we need to keep the game object around
1242 //so that we can give out some cheese
1243 give_some_cheese(game_winner);
1256 else if (stop_action == "load-game")
1263 bool broken = false;
1264 GameScenario* game_scenario = new GameScenario(d_load_filename, broken);
1268 on_message_requested(_("Corrupted saved game file."));
1272 if (game_scenario->getPlayMode() == GameScenario::HOTSEAT)
1273 load_game(game_scenario,
1274 new NextTurnHotseat(game_scenario->getTurnmode(),
1275 game_scenario->s_random_turns));
1276 else if (game_scenario->getPlayMode() == GameScenario::PLAY_BY_MAIL)
1278 PbmGameServer::getInstance()->start();
1279 load_game(game_scenario,
1280 new NextTurnPbm(game_scenario->getTurnmode(),
1281 game_scenario->s_random_turns));
1283 else if (game_scenario->getPlayMode() == GameScenario::NETWORKED)
1284 load_game(game_scenario,
1285 new NextTurnNetworked(game_scenario->getTurnmode(),
1286 game_scenario->s_random_turns));
1290 void GameWindow::on_quests_activated()
1292 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1294 Player *player = Playerlist::getActiveplayer();
1295 std::vector<Quest*> quests
1296 = QuestsManager::getInstance()->getPlayerQuests(player);
1297 Stack *s = player->getActivestack();
1300 hero = s->getFirstHeroWithAQuest();
1301 QuestReportDialog d(quests, hero);
1302 d.set_parent_window(*window);
1308 void GameWindow::on_fullscreen_activated()
1310 if (fullscreen_menuitem->get_active())
1311 window->fullscreen();
1313 window->unfullscreen();
1316 void GameWindow::on_signpost_activated()
1318 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1320 Gtk::Dialog* dialog;
1322 Glib::RefPtr<Gtk::Builder> xml
1323 = Gtk::Builder::create_from_file(get_glade_path() + "/signpost-change-dialog.ui");
1325 xml->get_widget("dialog", dialog);
1326 Decorated decorator;
1327 decorator.decorate(dialog);
1328 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1329 dialog->set_transient_for(*window);
1331 decorator.set_title(_("Signpost"));
1333 Stack *stack = Playerlist::getActiveplayer()->getActivestack();
1336 Signpost *s = GameMap::getSignpost(stack->getPos());
1340 xml->get_widget("label", l);
1341 l->set_text(_("Change the message on this sign:"));
1343 xml->get_widget("message_entry", e);
1344 e->set_text(s->getName());
1345 e->set_activates_default(true);
1347 int response = dialog->run();
1350 if (response == Gtk::RESPONSE_ACCEPT)
1351 Playerlist::getActiveplayer()->signpostChange(s, e->get_text());
1358 void GameWindow::on_stack_info_activated()
1360 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1362 StackInfoDialog d(currently_selected_stack->getPos());
1363 d.set_parent_window(*window);
1365 Stack *s = d.get_selected_stack();
1367 on_stack_info_changed(s);
1368 //FIXME, armies don't stay selected in the right way. to reproduce:
1369 //go in with all three selected. deselect middle one in stackinfodialog,
1373 void GameWindow::on_disband_activated()
1375 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1377 Stack *stack = Playerlist::getActiveplayer()->getActivestack();
1378 Gtk::Dialog* dialog;
1380 Glib::RefPtr<Gtk::Builder> xml
1381 = Gtk::Builder::create_from_file(get_glade_path() + "/disband-stack-dialog.ui");
1383 xml->get_widget("dialog", dialog);
1384 Decorated decorator;
1385 decorator.decorate(dialog);
1386 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1387 dialog->set_transient_for(*window);
1389 decorator.set_title(_("Disband"));
1392 xml->get_widget("label", l);
1394 std::vector<guint32> heroes;
1395 stack->getHeroes(heroes);
1396 Glib::ustring s = _("Are you sure you want to disband this group?");
1397 if (heroes.size() > 0)
1400 s += String::ucompose( ngettext("(It contains %1 hero).",
1401 "(It contains %1 heroes).",
1402 heroes.size()), heroes.size());
1406 int response = dialog->run();
1409 if (response == Gtk::RESPONSE_ACCEPT) //disband the active stack
1410 Playerlist::getActiveplayer()->stackDisband(NULL);
1415 void GameWindow::on_resignation_completed()
1417 Gtk::Dialog* dialog;
1419 Glib::RefPtr<Gtk::Builder> xml
1420 = Gtk::Builder::create_from_file(get_glade_path() +
1421 "/player-resign-completed-dialog.ui");
1423 xml->get_widget("dialog", dialog);
1424 Decorated decorator;
1425 decorator.decorate(dialog);
1426 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1427 dialog->set_transient_for(*window);
1437 void GameWindow::on_resign_activated()
1439 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1442 Gtk::Dialog* dialog;
1444 Glib::RefPtr<Gtk::Builder> xml
1445 = Gtk::Builder::create_from_file(get_glade_path() + "/player-resign-dialog.ui");
1447 xml->get_widget("dialog", dialog);
1448 Decorated decorator;
1449 decorator.decorate(dialog);
1450 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1451 dialog->set_transient_for(*window);
1453 decorator.set_title(_("Resign"));
1456 xml->get_widget("label", l);
1458 l->set_text(_("Are you sure you want to resign?"));
1460 int response = dialog->run();
1462 if (response == Gtk::RESPONSE_ACCEPT) //disband all stacks, raze all cities
1464 Playerlist::getActiveplayer()->resign();
1466 on_resignation_completed();
1473 void GameWindow::on_vectoring_activated()
1476 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1479 if (currently_selected_stack)
1481 Vector<int> pos = currently_selected_stack->getPos();
1482 city = Citylist::getInstance()->getNearestVisibleFriendlyCity(pos);
1485 city = Citylist::getInstance()->getFirstCity(Playerlist::getActiveplayer());
1489 bool see_all = true;
1490 DestinationDialog d(city, &see_all);
1492 d.set_parent_window(*window);
1498 void GameWindow::on_production_activated()
1501 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1504 if (currently_selected_stack)
1506 Vector<int> pos = currently_selected_stack->getPos();
1507 city = Citylist::getInstance()->getNearestVisibleFriendlyCity(pos);
1510 city = Citylist::getInstance()->getFirstCity(Playerlist::getActiveplayer());
1515 on_city_visited(city);
1519 void GameWindow::on_preferences_activated()
1521 Player *current = Playerlist::getInstance()->getActiveplayer();
1522 PreferencesDialog d(false);
1523 d.set_parent_window(*window);
1526 game->get_bigmap().set_control_key_down (false);
1527 if (current != Playerlist::getInstance()->getActiveplayer())
1531 void GameWindow::on_group_ungroup_activated()
1533 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1535 group_ungroup_toggle->set_active(!group_ungroup_toggle->get_active());
1538 void GameWindow::on_fight_order_activated()
1540 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1542 FightOrderDialog d(Playerlist::getActiveplayer());
1543 d.set_parent_window(*window);
1548 void GameWindow::on_levels_activated()
1550 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1552 HeroLevelsDialog d(Playerlist::getActiveplayer());
1553 d.set_parent_window(*window);
1558 void GameWindow::on_ruin_report_activated()
1560 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1565 if (currently_selected_stack)
1566 pos = currently_selected_stack->getPos();
1568 if (Templelist::getInstance()->size() == 0 &&
1569 Ruinlist::getInstance()->size() == 0)
1571 std::string s = _("No ruins or temples to show!");
1572 TimedMessageDialog dialog(*window, s, 30);
1579 RuinReportDialog d(pos);
1580 d.set_parent_window(*window);
1585 void GameWindow::on_army_bonus_activated()
1587 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1589 ArmyBonusDialog d(Playerlist::getActiveplayer());
1590 d.set_parent_window(*window);
1595 void GameWindow::on_item_bonus_activated()
1597 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1600 d.set_parent_window(*window);
1605 void GameWindow::on_army_report_activated()
1607 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1609 ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::ARMY);
1610 d.set_parent_window(*window);
1615 void GameWindow::on_city_report_activated()
1617 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1619 ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::CITY);
1620 d.set_parent_window(*window);
1625 void GameWindow::on_gold_report_activated()
1627 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1629 ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::GOLD);
1630 d.set_parent_window(*window);
1635 void GameWindow::on_production_report_activated()
1637 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1639 ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::PRODUCTION);
1640 d.set_parent_window(*window);
1645 void GameWindow::on_winning_report_activated()
1647 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1649 ReportDialog d(Playerlist::getActiveplayer(), ReportDialog::WINNING);
1650 d.set_parent_window(*window);
1655 void GameWindow::on_city_history_activated()
1657 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1659 HistoryReportDialog d(Playerlist::getActiveplayer(),
1660 HistoryReportDialog::CITY);
1661 d.set_parent_window(*window);
1666 void GameWindow::on_ruin_history_activated()
1668 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1670 HistoryReportDialog d(Playerlist::getActiveplayer(),
1671 HistoryReportDialog::RUIN);
1672 d.set_parent_window(*window);
1677 void GameWindow::on_event_history_activated()
1679 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1681 HistoryReportDialog d(Playerlist::getActiveplayer(),
1682 HistoryReportDialog::EVENTS);
1683 d.set_parent_window(*window);
1688 void GameWindow::on_gold_history_activated()
1690 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1692 HistoryReportDialog d(Playerlist::getActiveplayer(),
1693 HistoryReportDialog::GOLD);
1694 d.set_parent_window(*window);
1699 void GameWindow::on_winner_history_activated()
1701 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1703 HistoryReportDialog d(Playerlist::getActiveplayer(),
1704 HistoryReportDialog::WINNING);
1705 d.set_parent_window(*window);
1710 void GameWindow::on_triumphs_activated()
1712 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1714 TriumphsDialog d(Playerlist::getActiveplayer());
1715 d.set_parent_window(*window);
1720 void GameWindow::on_help_about_activated()
1722 Gtk::AboutDialog* dialog;
1724 Glib::RefPtr<Gtk::Builder> xml
1725 = Gtk::Builder::create_from_file(get_glade_path() + "/about-dialog.ui");
1727 xml->get_widget("dialog", dialog);
1728 dialog->set_icon_from_file(File::getMiscFile("various/castle_icon.png"));
1729 Decorated decorator;
1730 decorator.decorate(dialog);
1731 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1732 dialog->set_transient_for(*window);
1734 dialog->set_version(PACKAGE_VERSION);
1735 dialog->set_logo(GraphicsCache::getMiscPicture("castle_icon.png")->to_pixbuf());
1744 void GameWindow::on_diplomacy_report_activated()
1746 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1748 if (GameScenario::s_diplomacy == false)
1750 DiplomacyReportDialog d(Playerlist::getActiveplayer());
1751 d.set_parent_window(*window);
1756 void GameWindow::on_diplomacy_button_clicked()
1758 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1760 DiplomacyDialog d(Playerlist::getActiveplayer());
1761 d.set_parent_window(*window);
1766 void GameWindow::stop_game(std::string action)
1768 stop_action = action;
1769 Sound::getInstance()->disableBackground();
1773 current_save_filename = "";
1777 void GameWindow::on_game_over(Player *winner)
1780 Gtk::Dialog* dialog;
1782 Glib::RefPtr<Gtk::Builder> xml
1783 = Gtk::Builder::create_from_file(get_glade_path() + "/game-over-dialog.ui");
1785 xml->get_widget("dialog", dialog);
1786 Decorated decorator;
1787 decorator.decorate(dialog);
1788 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
1789 dialog->set_transient_for(*window);
1792 xml->get_widget("image", image);
1794 image->property_pixbuf() = GraphicsCache::getMiscPicture("win.png", false)->to_pixbuf();
1797 xml->get_widget("label", label);
1799 s += String::ucompose(_("Congratulations to %1 for conquering the world!"),
1801 label->set_markup("<b>" + s + "</b>");
1807 game_winner = winner;
1808 stop_game("game-over");
1812 void GameWindow::on_player_died(Player *player)
1817 s += String::ucompose(_("The rule of %1 has permanently ended!"),
1819 if (Playerlist::getInstance()->countHumanPlayersAlive() == 0 &&
1820 player->getType() == Player::HUMAN)
1823 s += _("No further human resistance is possible\nbut the battle will continue!");
1825 s += _("Press `CTRL-P' to stop the war\nand visit the sites of thy old battles.");
1828 TimedMessageDialog dialog(*window, s, 30);
1835 void GameWindow::on_message_requested(std::string msg)
1837 // FIXME: this is a bit crude, maybe beef it up
1838 Gtk::MessageDialog dialog(*window, msg);
1839 Decorated decorator;
1840 decorator.decorate(dynamic_cast<Gtk::Dialog*>(&dialog));
1841 //TimedMessageDialog dialog(*window, msg, 30, 5);
1847 void GameWindow::on_stack_toggled(Gtk::RadioButton *radio, Stack *stack)
1849 if (radio->get_active() == true)
1851 if (stack == currently_selected_stack)
1853 currently_selected_stack = stack;
1854 Playerlist::getActiveplayer()->setActivestack(stack);
1855 on_stack_info_changed(stack);
1856 game->recalculate_moves_for_stack(stack);
1860 void GameWindow::on_army_toggled(Gtk::ToggleButton *toggle, Stack *stack, Army *army)
1862 Player *p = Playerlist::getActiveplayer();
1863 Stack *s = p->getActivestack();
1864 group_ungroup_toggle->set_sensitive(false);
1865 if (toggle->get_active() == true)
1867 printf("split army %d from stack %d, and put it into current stack %d.\n", army->getId(), stack->getId(), currently_selected_stack->getId());
1869 if (stack->size() > 1)
1871 Stack *new_stack = p->stackSplitArmy(stack, army);
1873 p->stackJoin(currently_selected_stack, new_stack);
1876 p->stackJoin(currently_selected_stack, stack);
1877 currently_selected_stack->sortForViewing(true);
1881 //printf("split army %d from stack %d, and make a new stack.\n", army->getId(), stack->getId());
1882 p->stackSplitArmy(stack, army);
1883 stack->sortForViewing(true);
1885 on_stack_info_changed(s);
1886 group_ungroup_toggle->set_sensitive(true);
1887 game->recalculate_moves_for_stack(s);
1890 void GameWindow::on_group_toggled(Gtk::ToggleButton *toggle)
1892 if (toggle->sensitive() == false)
1894 printf("group/ungroup was clicked\n");
1895 bool active = toggle->get_active();
1897 printf("active is %d so it means we are %s\n",
1898 active, active ? "grouped, and going to ungrouped" :
1899 "ungrouped, and going to group");
1900 clear_army_buttons();
1902 StackTile *s = GameMap::getStacks(currently_selected_stack->getPos());
1905 s->group(Playerlist::getActiveplayer(), currently_selected_stack);
1906 currently_selected_stack->sortForViewing(true);
1909 s->ungroup(Playerlist::getActiveplayer());
1910 //Stack *stack = s->getFriendlyStacks(Playerlist::getActiveplayer()).front();
1911 //currently_selected_stack = stack;
1912 //Playerlist::getActiveplayer()->setActivestack(stack);
1914 on_stack_info_changed(currently_selected_stack);
1915 game->recalculate_moves_for_stack(currently_selected_stack);
1918 bool GameWindow::on_army_button_event(GdkEventButton *e,
1919 Gtk::ToggleButton *toggle, Army *army)
1921 // if a hero is right-clicked, pop up the hero dialog, otherwise show the
1923 MouseButtonEvent event = to_input_event(e);
1924 if (event.button == MouseButtonEvent::RIGHT_BUTTON
1925 && event.state == MouseButtonEvent::PRESSED) {
1928 delete army_info_tip;
1929 army_info_tip = new ArmyInfoTip(toggle, army);
1933 else if (event.button == MouseButtonEvent::RIGHT_BUTTON
1934 && event.state == MouseButtonEvent::RELEASED) {
1938 delete army_info_tip;
1939 army_info_tip = NULL;
1948 void GameWindow::clear_army_buttons()
1950 for (army_buttons_type::iterator i = army_buttons.begin(),
1951 end = army_buttons.end(); i != end; ++i)
1953 army_buttons.clear();
1954 for (stack_buttons_type::iterator i = stack_buttons.begin(),
1955 end = stack_buttons.end(); i != end; ++i)
1957 stack_buttons.clear();
1958 delete stack_info_button_table;
1959 stack_info_button_table = NULL;
1962 void GameWindow::on_progress_status_changed(std::string string)
1964 progress_status_label->set_markup("<b>" + string + "</b>");
1967 void GameWindow::on_progress_changed()
1969 turn_progressbar->pulse();
1972 void GameWindow::on_sidebar_stats_changed(SidebarStats s)
1974 if (Configuration::s_decorated)
1976 cities_stats_label->set_markup(String::ucompose("<b>%1</b>", s.cities));
1977 gold_stats_label->set_markup(String::ucompose("<b>%1</b>", s.gold));
1978 income_stats_label->set_markup(String::ucompose("<b>%1</b>", s.income));
1979 upkeep_stats_label->set_markup(String::ucompose("<b>%1</b>", s.upkeep));
1980 turn_label->set_markup(String::ucompose("<b>Turn %1</b>", s.turns));
1984 cities_stats_label->set_markup(String::ucompose("%1", s.cities));
1985 gold_stats_label->set_markup(String::ucompose("%1", s.gold));
1986 income_stats_label->set_markup(String::ucompose("%1", s.income));
1987 upkeep_stats_label->set_markup(String::ucompose("%1", s.upkeep));
1988 turn_label->set_markup(String::ucompose("Turn %1", s.turns));
1991 tip = String::ucompose(
1992 ngettext("You have %1 city!",
1993 "You have %1 cities!", s.cities), s.cities);
1994 cities_stats_image->set_tooltip_text(tip);
1995 cities_stats_label->set_tooltip_text(tip);
1996 tip = String::ucompose(
1997 ngettext("You have %1 gold piece in your treasury!",
1998 "You have %1 gold pieces in your treasury!", s.gold), s.gold);
1999 gold_stats_image->set_tooltip_text(tip);
2000 gold_stats_label->set_tooltip_text(tip);
2001 tip = String::ucompose(
2002 ngettext("You earn %1 gold piece in income!",
2003 "You earn %1 gold pieces in income!", s.income), s.income);
2004 income_stats_image->set_tooltip_text(tip);
2005 income_stats_label->set_tooltip_text(tip);
2006 tip = String::ucompose(
2007 ngettext("You pay %1 gold piece in upkeep!",
2008 "You pay %1 gold pieces in upkeep!", s.upkeep), s.upkeep);
2009 upkeep_stats_image->set_tooltip_text(tip);
2010 upkeep_stats_label->set_tooltip_text(tip);
2013 void GameWindow::on_bigmap_changed(Glib::RefPtr<Gdk::Pixmap> map)
2017 map->get_size(width, height);
2018 Glib::RefPtr<Gdk::Window> window = bigmap_drawingarea->get_window();
2021 Gdk::Rectangle r = Gdk::Rectangle(0, 0, width, height);
2022 window->invalidate_rect(r, true);
2025 void GameWindow::on_smallmap_changed(Glib::RefPtr<Gdk::Pixmap> map, Gdk::Rectangle r)
2029 map->get_size(width, height);
2030 map_container->property_width_request() = width;
2031 map_container->property_height_request() = height;
2033 Glib::RefPtr<Gdk::Window> window = map_drawingarea->get_window();
2035 window->invalidate_rect(r, true);
2036 //map_image->property_pixbuf() = map;
2038 //still resides at smallmap->get_surface()
2041 void GameWindow::on_smallmap_slid(Rectangle view)
2043 on_smallmap_changed(game->get_smallmap().get_surface(),
2044 Gdk::Rectangle(view.x, view.y, view.w, view.h));
2045 while (g_main_context_iteration(NULL, FALSE)); //doEvents
2048 void GameWindow::on_stack_info_changed(Stack *s)
2050 clear_army_buttons();
2052 currently_selected_stack = s;
2056 if (Playerlist::getActiveplayer()->getType() == Player::HUMAN)
2063 if (s->getOwner()->getType() == Player::HUMAN)
2065 StackTile *stile = GameMap::getStacks(s->getPos());
2066 stile->setDefending(s->getOwner(), false);
2067 stile->setParked(s->getOwner(), false);
2077 void GameWindow::show_stats()
2079 Armysetlist *al = Armysetlist::getInstance();
2080 int height = al->getTileSize(Playerlist::getActiveplayer()->getArmyset());
2081 height += turn_label->get_height();
2083 stack_info_box->get_parent()->property_height_request() = height;
2084 stats_box->get_parent()->property_height_request() = height;
2085 stack_info_container->hide();
2086 progress_box->hide();
2090 void GameWindow::show_progress()
2092 turn_progressbar->property_fraction() = 0.0;
2093 if (Playerlist::getActiveplayer() == Playerlist::getInstance()->getNeutral())
2094 progress_status_label->set_text("");
2096 progress_status_label->set_markup("<b>" + Playerlist::getActiveplayer()->getName() + "</b>");
2098 stack_info_container->hide();
2099 progress_box->show();
2102 void GameWindow::fill_in_group_info (StackTile *stile, Stack *s)
2104 guint32 bonus = s->calculateMoveBonus();
2105 GraphicsCache *gc = GraphicsCache::getInstance();
2106 terrain_image->property_pixbuf() = gc->getMoveBonusPic(bonus, s->hasShip())->to_pixbuf();
2107 if (Configuration::s_decorated == true)
2108 group_moves_label->set_markup(String::ucompose("<b>%1</b>",
2111 group_moves_label->set_markup(String::ucompose("%1",
2113 //printf ("toggling group/ungroup!\n");
2114 group_ungroup_toggle->set_sensitive(false);
2115 if (stile->getFriendlyStacks(s->getOwner()).size() != 1)
2116 group_ungroup_toggle->set_active(false);
2118 group_ungroup_toggle->set_active(true);
2119 if (group_ungroup_toggle->get_active() == true)
2120 group_ungroup_toggle->set_label(_("UnGrp"));
2122 group_ungroup_toggle->set_label(_("Grp"));
2123 group_ungroup_toggle->set_sensitive(true);
2126 void GameWindow::show_stack(StackTile *s)
2128 Gtk::RadioButton *first_radio = NULL;
2129 GraphicsCache *gc = GraphicsCache::getInstance();
2130 //s->sortForViewing (true);
2132 progress_box->hide();
2134 army_buttons.clear();
2135 stack_buttons.clear();
2138 std::list<Stack *> stks;
2139 stks = s->getFriendlyStacks(Playerlist::getActiveplayer());
2140 unsigned int count= 0;
2141 if (stack_info_button_table != NULL)
2142 delete stack_info_button_table;
2143 stack_info_button_table = new Gtk::Table(2, MAX_ARMIES_ON_A_SINGLE_TILE);
2145 for (std::list<Stack *>::iterator j = stks.begin(); j != stks.end(); j++)
2148 for (Stack::iterator i = (*j)->begin(); i != (*j)->end(); ++i)
2150 // construct a toggle button
2152 Gtk::VBox *toggle_box = manage(new Gtk::VBox);
2155 Gtk::Image *army_image = new Gtk::Image();
2156 bool greyed_out = (*j)->getId() != currently_selected_stack->getId();
2157 Glib::RefPtr<Gdk::Pixbuf> army_icon =
2158 gc->getArmyPic((*j)->getOwner()->getArmyset(), army->getTypeId(),
2159 (*j)->getOwner(), army->getMedalBonuses(),
2160 greyed_out)->to_pixbuf();
2161 army_image->property_pixbuf() = army_icon;
2162 width = army_icon->get_width();
2163 height = army_icon->get_height();
2164 toggle_box->add(*manage(army_image));
2166 Glib::ustring moves_str = String::ucompose("%1", army->getMoves());
2167 toggle_box->add(*manage(new Gtk::Label(moves_str,
2168 Gtk::ALIGN_CENTER, Gtk::ALIGN_TOP)));
2170 // the button itself
2171 Gtk::ToggleButton *toggle = new Gtk::ToggleButton;
2172 toggle->add(*toggle_box);
2173 toggle->set_active((*j)->getId() == currently_selected_stack->getId());
2174 toggle->signal_toggled().connect
2175 (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_army_toggled),
2177 toggle->add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
2178 toggle->signal_button_press_event().connect
2179 (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_army_button_event),
2180 toggle, army), false);
2181 toggle->signal_button_release_event().connect
2182 (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_army_button_event),
2183 toggle, army), false);
2188 Gtk::RadioButton *radio;
2191 Gtk::RadioButtonGroup g = first_radio->get_group();
2192 radio = new Gtk::RadioButton(g);
2195 radio = new Gtk::RadioButton;
2196 radio->property_can_focus() = false;
2197 radio->set_active(currently_selected_stack->getId() == (*j)->getId());
2198 radio->signal_toggled().connect
2199 (sigc::bind(sigc::mem_fun(*this, &GameWindow::on_stack_toggled),
2201 stack_info_button_table->attach(*toggle, count, count + 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
2202 stack_info_button_table->attach(*radio, count, count + 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
2203 stack_buttons.push_back(radio);
2204 if (first_radio == NULL)
2205 first_radio = radio;
2209 stack_info_button_table->attach(*toggle, count, count + 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
2211 army_buttons.push_back(toggle);
2216 for (unsigned int i = count ; i < MAX_ARMIES_ON_A_SINGLE_TILE; i++)
2218 // construct a toggle button
2219 Gtk::VBox *toggle_box = manage(new Gtk::VBox);
2222 Gtk::Image *army_image = new Gtk::Image();
2223 Glib::RefPtr<Gdk::Pixbuf> empty_pic
2224 = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, width, height);
2225 empty_pic->fill(0x00000000);
2226 army_image->property_pixbuf() = empty_pic;
2227 toggle_box->add(*manage(army_image));
2229 toggle_box->add(*manage
2230 (new Gtk::Label(" ", Gtk::ALIGN_CENTER, Gtk::ALIGN_TOP)));
2232 // the button itself
2233 Gtk::ToggleButton *toggle = new Gtk::ToggleButton;
2234 toggle->add(*toggle_box);
2235 toggle->set_sensitive(false);
2236 // clicking on this button does nothing.
2238 //stack_info_box->pack_start(*toggle, Gtk::PACK_SHRINK);
2239 stack_info_button_table->attach(*toggle, i, i + 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
2240 army_buttons.push_back(toggle);
2242 stack_info_box->pack_start(*manage(stack_info_button_table), Gtk::PACK_SHRINK);
2244 fill_in_group_info(s, currently_selected_stack);
2245 //ensure_one_army_button_active();
2246 stack_info_container->show_all();
2249 void GameWindow::on_city_tip_changed(City *city, MapTipPosition mpos)
2253 delete city_info_tip;
2254 city_info_tip = NULL;
2258 city_info_tip = new CityInfoTip(bigmap_drawingarea, mpos, city);
2262 void GameWindow::on_stack_tip_changed(StackTile *stile, MapTipPosition mpos)
2266 delete stack_info_tip;
2267 stack_info_tip = NULL;
2271 stack_info_tip = new StackInfoTip(bigmap_drawingarea, mpos, stile);
2275 void GameWindow::on_bigmap_tip_changed(Glib::ustring tip, MapTipPosition pos)
2280 show_map_tip(tip, pos);
2283 void GameWindow::show_map_tip(Glib::ustring msg, MapTipPosition pos)
2286 if (map_tip != NULL)
2288 map_tip = new Gtk::Window(Gtk::WINDOW_POPUP);
2290 Gtk::Frame *f = manage(new Gtk::Frame);
2291 f->property_shadow_type() = Gtk::SHADOW_ETCHED_OUT;
2293 Gtk::Label *l = manage(new Gtk::Label);
2294 l->set_padding(6, 6);
2299 Decorated decorator;
2300 decorator.decorate(map_tip,File::getMiscFile("various/background.png"), 200);
2303 // get screen position
2305 bigmap_drawingarea->get_window()->get_origin(p.x, p.y);
2308 Vector<int> size(0, 0);
2309 map_tip->get_size(size.x, size.y);
2311 switch (pos.justification)
2313 case MapTipPosition::LEFT:
2314 map_tip->set_gravity(Gdk::GRAVITY_NORTH_WEST);
2316 case MapTipPosition::RIGHT:
2317 map_tip->set_gravity(Gdk::GRAVITY_NORTH_EAST);
2320 case MapTipPosition::TOP:
2321 map_tip->set_gravity(Gdk::GRAVITY_NORTH_WEST);
2323 case MapTipPosition::BOTTOM:
2324 map_tip->set_gravity(Gdk::GRAVITY_SOUTH_WEST);
2330 map_tip->move(p.x, p.y);
2334 void GameWindow::hide_map_tip()
2336 if (map_tip != NULL)
2343 Reward* GameWindow::on_sage_visited (Ruin *ruin, Sage *sage, Stack *stack)
2345 SageDialog d(sage, stack->getFirstHero()->getOwner(),
2346 static_cast<Hero*>(stack->getFirstHero()), ruin);
2347 d.set_parent_window(*window);
2348 Reward *reward = d.run();
2353 void GameWindow::on_ruin_rewarded (Reward_Ruin *reward)
2355 RuinRewardedDialog d(reward);
2356 d.set_parent_window(*window);
2361 void GameWindow::on_ruin_searched(Ruin *ruin, Stack *stack, Reward *reward)
2363 Gtk::Dialog* dialog;
2364 if (ruin->hasSage())
2366 if (reward->getType() == Reward::RUIN)
2367 return on_ruin_rewarded(static_cast<Reward_Ruin*>(reward));
2370 Glib::RefPtr<Gtk::Builder> xml
2371 = Gtk::Builder::create_from_file(get_glade_path() + "/ruin-searched-dialog.ui");
2374 xml->get_widget("dialog", dialog);
2375 Decorated decorator;
2376 decorator.decorate(dialog);
2377 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2378 dialog->set_transient_for(*window);
2380 decorator.set_title(ruin->getName());
2383 xml->get_widget("label", label);
2385 Glib::ustring s = label->get_text();
2387 s += String::ucompose(_("%1 finds "), stack->getFirstHero()->getName());
2388 if (reward->getType() == Reward::GOLD)
2390 Reward_Gold *gold = dynamic_cast<Reward_Gold*>(reward);
2391 s += String::ucompose(_("%1 gold pieces."), gold->getGold());
2393 else if (reward->getType() == Reward::ALLIES)
2395 Reward_Allies *allies = dynamic_cast<Reward_Allies*>(reward);
2396 s += String::ucompose(_("%1 allies!"), allies->getNoOfAllies());
2398 else if (reward->getType() == Reward::ITEM)
2400 Reward_Item *item = dynamic_cast<Reward_Item*>(reward);
2401 s += String::ucompose(_("the %1!"), item->getItem()->getName());
2403 else if (reward->getType() == Reward::MAP)
2405 Reward_Map *map = dynamic_cast<Reward_Map*>(reward);
2406 s += String::ucompose(_("a map!"), map->getName());
2417 void GameWindow::on_ruinfight_started(Stack *attackers, Stack *defenders)
2419 //so and so encounters a wolf...
2420 Gtk::Dialog* dialog;
2422 Glib::RefPtr<Gtk::Builder> xml
2423 = Gtk::Builder::create_from_file(get_glade_path() + "/ruinfight-started-dialog.ui");
2425 xml->get_widget("dialog", dialog);
2426 Decorated decorator;
2427 decorator.decorate(dialog);
2428 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2429 dialog->set_transient_for(*window);
2431 decorator.set_title(_("Searching"));
2434 xml->get_widget("label", label);
2435 Glib::ustring s = label->get_text();
2437 s += attackers->getFirstHero()->getName() + " encounters some ";
2438 s += defenders->getStrongestArmy()->getName() + "...";
2446 void GameWindow::on_ruinfight_finished(Fight::Result result)
2448 Gtk::Dialog* dialog;
2450 Glib::RefPtr<Gtk::Builder> xml
2451 = Gtk::Builder::create_from_file(get_glade_path() + "/ruinfight-finished-dialog.ui");
2453 xml->get_widget("dialog", dialog);
2454 Decorated decorator;
2455 decorator.decorate(dialog);
2456 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2457 dialog->set_transient_for(*window);
2459 if (result == Fight::ATTACKER_WON)
2460 decorator.set_title(_("Hero Victorious"));
2462 decorator.set_title(_("Hero Defeated"));
2465 xml->get_widget("label", label);
2466 Glib::ustring s = label->get_text();
2468 if (result == Fight::ATTACKER_WON)
2469 s += _("...and is victorious!");
2471 s += _("...and is slain by it!");
2475 xml->get_widget("image", image);
2476 if (result == Fight::ATTACKER_WON)
2477 image->property_file() = File::getMiscFile("various/ruin_2.png");
2479 image->property_file() = File::getMiscFile("various/ruin_1.png");
2487 void GameWindow::on_fight_started(LocationBox box, Fight &fight)
2489 FightWindow d(fight);
2491 game->get_bigmap().setFighting(box);
2492 game->get_bigmap().draw(Playerlist::getViewingplayer());
2493 d.set_parent_window(*window);
2494 d.run(&d_quick_fights);
2496 game->get_bigmap().setFighting(LocationBox(Vector<int>(-1,-1)));
2497 game->get_bigmap().draw(Playerlist::getViewingplayer());
2498 if (Playerlist::getActiveplayer()->getType() == Player::HUMAN)
2499 d_quick_fights = false;
2502 void GameWindow::on_hero_brings_allies (int numAllies)
2504 Gtk::Dialog* dialog;
2506 Glib::RefPtr<Gtk::Builder> xml
2507 = Gtk::Builder::create_from_file(get_glade_path() + "/hero-brings-allies-dialog.ui");
2509 xml->get_widget("dialog", dialog);
2510 Decorated decorator;
2511 decorator.decorate(dialog);
2512 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2513 dialog->set_transient_for(*window);
2515 decorator.set_title(_("Hero brings allies!"));
2518 xml->get_widget("label", label);
2520 s = String::ucompose(
2521 ngettext("The hero brings %1 ally!",
2522 "The hero brings %1 allies!", numAllies), numAllies);
2531 bool GameWindow::on_hero_offers_service(Player *player, HeroProto *hero, City *city, int gold)
2533 HeroOfferDialog d(player, hero, city, gold);
2534 d.set_parent_window(*window);
2535 bool retval = d.run();
2540 bool GameWindow::on_enemy_offers_surrender(int numPlayers)
2542 SurrenderDialog d(numPlayers);
2543 d.set_parent_window(*window);
2544 bool retval = d.run();
2549 void GameWindow::on_surrender_answered (bool accepted)
2552 on_message_requested
2553 (_("You graciously and benevolently accept their offer."));
2556 SurrenderRefusedDialog d;
2557 d.set_parent_window(*window);
2563 bool GameWindow::on_stack_considers_treachery (Player *me, Stack *stack,
2564 Player *them, Vector<int> pos)
2566 Gtk::Dialog* dialog;
2568 Glib::RefPtr<Gtk::Builder> xml
2569 = Gtk::Builder::create_from_file(get_glade_path() + "/treachery-dialog.ui");
2571 xml->get_widget("dialog", dialog);
2572 Decorated decorator;
2573 decorator.decorate(dialog);
2574 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2575 dialog->set_transient_for(*window);
2577 xml->get_widget("label", label);
2579 s = String::ucompose(_("Are you sure you want to attack %1?"),
2582 s += _("Other players may not like this!");
2585 int response = dialog->run();
2588 if (response == Gtk::RESPONSE_DELETE_EVENT)
2590 else if (response == Gtk::RESPONSE_ACCEPT)
2597 void GameWindow::on_temple_visited(Temple *temple)
2599 RuinReportDialog d(temple->getPos());
2600 d.set_parent_window(*window);
2605 bool GameWindow::on_temple_searched(Hero *hero, Temple *temple, int blessCount)
2607 QuestsManager *qm = QuestsManager::getInstance();
2608 Gtk::Dialog* dialog;
2609 bool hasHero = hero != NULL;
2610 bool ask_quest = false;
2612 Glib::RefPtr<Gtk::Builder> xml
2613 = Gtk::Builder::create_from_file(get_glade_path() + "/temple-visit-dialog.ui");
2615 xml->get_widget("dialog", dialog);
2616 Decorated decorator;
2617 decorator.decorate(dialog);
2618 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2619 dialog->set_transient_for(*window);
2621 decorator.set_title(temple->getName());
2624 Gtk::Button *close_button;
2625 Gtk::Button *accept_button;
2626 xml->get_widget("label", l);
2627 xml->get_widget("close_button", close_button);
2628 xml->get_widget("accept_button", accept_button);
2630 if (GameScenarioOptions::s_play_with_quests ==
2631 GameParameters::ONE_QUEST_PER_PLAYER)
2633 if (qm->getPlayerQuests(Playerlist::getActiveplayer()).size() == 0 &&
2637 else if (GameScenarioOptions::s_play_with_quests == GameParameters::ONE_QUEST_PER_HERO)
2639 if (hasHero && hero->hasQuest() == false)
2645 s += String::ucompose(
2646 ngettext("%1 army has been blessed!",
2647 "%1 armies have been blessed!", blessCount), blessCount);
2649 s += _("We have already blessed thee!");
2652 s = l->get_text() + "\n" + _("Seek more blessings in far temples!");
2656 s = l->get_text() + "\n\n" + _("Do you seek a quest?");
2662 if (ask_quest == false)
2664 close_button->hide();
2666 accept_button->set_label(s);
2669 int response = dialog->run();
2673 if (ask_quest == false)
2674 response = Gtk::RESPONSE_ACCEPT;
2676 if (response == Gtk::RESPONSE_ACCEPT) // accepted a quest
2682 void GameWindow::on_quest_assigned(Hero *hero, Quest *quest)
2684 QuestAssignedDialog d(hero, quest);
2685 d.set_parent_window(*window);
2691 hero_has_quest_here (Stack *s, City *c, bool *pillage, bool *sack, bool *raze, bool *occupy)
2693 Player *p = Playerlist::getActiveplayer();
2694 std::vector<Quest*> questlist;
2700 QuestsManager *q_mgr = QuestsManager::getInstance();
2701 questlist = q_mgr->getPlayerQuests(p);
2702 /* loop over all quests */
2703 /* for each quest, check the quest type */
2704 for (std::vector<Quest*>::iterator i = questlist.begin();
2705 i != questlist.end(); ++i)
2709 if ((*i)->isPendingDeletion() == true)
2711 switch ((*i)->getType())
2713 case Quest::CITYSACK:
2714 case Quest::CITYRAZE:
2715 case Quest::CITYOCCUPY:
2716 if ((*i)->getType() == Quest::CITYSACK)
2718 if (dynamic_cast<QuestCitySack*>((*i))->getCity() != c)
2721 else if ((*i)->getType() == Quest::CITYOCCUPY)
2723 if (dynamic_cast<QuestCityOccupy*>((*i))->getCity() != c)
2726 else if ((*i)->getType() == Quest::CITYRAZE)
2728 if (dynamic_cast<QuestCityRaze*>((*i))->getCity() != c)
2731 /* now check if the quest's hero is in our stack */
2732 for (Stack::iterator it = s->begin(); it != s->end(); ++it)
2734 if ((*it)->isHero())
2736 if ((*it)->getId() == (*i)->getHeroId())
2738 /* hey we found one, set the corresponding boolean */
2739 if ((*i)->getType() == Quest::CITYSACK)
2741 else if ((*i)->getType() == Quest::CITYRAZE)
2743 else if ((*i)->getType() == Quest::CITYOCCUPY)
2749 case Quest::PILLAGEGOLD:
2755 if ((*raze) || (*sack) || (*occupy))
2761 CityDefeatedAction GameWindow::on_city_defeated(City *city, int gold)
2763 CityDefeatedAction retval = CITY_DEFEATED_OCCUPY;
2764 Gtk::Button *raze_button;
2765 Gtk::Dialog* dialog;
2767 on_city_looted (city, gold);
2768 Glib::RefPtr<Gtk::Builder> xml
2769 = Gtk::Builder::create_from_file(get_glade_path() + "/city-defeated-dialog.ui");
2771 xml->get_widget("dialog", dialog);
2772 Decorated decorator;
2773 decorator.decorate(dialog);
2774 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2775 dialog->set_transient_for(*window);
2778 xml->get_widget("city_image", image);
2779 image->property_file() = File::getMiscFile("various/city_occupied.png");
2783 xml->get_widget("label", label);
2784 Gtk::Requisition req = image->size_request();
2785 label->set_size_request(req.width);
2788 Player *p = Playerlist::getActiveplayer();
2789 Army *h = p->getActivestack()->getFirstHero();
2791 name = h->getName();
2793 name = p->getName(false);
2798 case 0: s = _("%1, you have triumphed in the battle of %2."); break;
2799 case 1: s = _("%1, you have claimed victory in the battle of %2."); break;
2800 case 2: s = _("%1, you have shown no mercy in the battle of %2."); break;
2801 case 3: s = _("%1, you have slain the foe in the battle of %2."); break;
2804 s = String::ucompose(s, name, city->getName());
2806 s += label->get_text();
2809 xml->get_widget("raze_button", raze_button);
2811 raze_button->set_sensitive
2812 (GameScenarioOptions::s_razing_cities == GameParameters::ON_CAPTURE ||
2813 GameScenarioOptions::s_razing_cities == GameParameters::ALWAYS);
2815 if (h) /* if there was a hero in the stack */
2817 bool pillage, sack, raze, occupy;
2818 if (hero_has_quest_here (p->getActivestack(), city,
2819 &pillage, &sack, &raze, &occupy))
2821 Gtk::Button *button;
2824 xml->get_widget("pillage_button", button);
2825 button->set_focus_on_click(true);
2826 // button->set_can_focus(true);
2827 // button->set_can_default(true);
2828 button->grab_default();
2832 xml->get_widget("sack_button", button);
2833 button->set_focus_on_click(true);
2834 // button->set_can_focus(true);
2835 // button->set_can_default(true);
2836 button->grab_default();
2840 xml->get_widget("raze_button", button);
2841 button->set_focus_on_click(true);
2842 // button->set_can_focus(true);
2843 // button->set_can_default(true);
2844 button->grab_default();
2848 xml->get_widget("occupy_button", button);
2849 button->set_focus_on_click(true);
2850 // button->set_can_focus(true);
2851 // button->set_can_default(true);
2852 button->grab_default();
2857 if (city->getNoOfProductionBases() <= 0) {
2859 xml->get_widget("pillage_button", b);
2863 if (city->getNoOfProductionBases() <= 1) {
2865 xml->get_widget("sack_button", b);
2873 int response = dialog->run();
2876 case 1: retval = CITY_DEFEATED_OCCUPY; break;
2879 bool razed = CityWindow::on_raze_clicked(city, dialog);
2882 retval = CITY_DEFEATED_RAZE;
2885 case 3: retval = CITY_DEFEATED_PILLAGE; break;
2886 case 4: retval = CITY_DEFEATED_SACK; break;
2897 void GameWindow::on_city_looted (City *city, int gold)
2899 Gtk::Dialog* dialog;
2901 Glib::RefPtr<Gtk::Builder> xml
2902 = Gtk::Builder::create_from_file(get_glade_path() + "/city-looted-dialog.ui");
2904 xml->get_widget("dialog", dialog);
2905 Decorated decorator;
2906 decorator.decorate(dialog);
2907 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2908 dialog->set_transient_for(*window);
2910 decorator.set_title(String::ucompose(_("%1 Looted"), city->getName()));
2913 xml->get_widget("label", label);
2914 Glib::ustring s = label->get_text();
2916 s += String::ucompose(
2917 ngettext("Your armies loot %1 gold piece.",
2918 "Your armies loot %1 gold pieces.", gold), gold);
2926 void GameWindow::on_city_pillaged(City *city, int gold, int pillaged_army_type)
2928 GraphicsCache *gc = GraphicsCache::getInstance();
2929 Gtk::Dialog* dialog;
2930 Player *player = city->getOwner();
2931 unsigned int as = player->getArmyset();
2933 Glib::RefPtr<Gtk::Builder> xml
2934 = Gtk::Builder::create_from_file(get_glade_path() + "/city-pillaged-dialog.ui");
2936 Gtk::Image *pillaged_army_type_image;
2937 xml->get_widget("dialog", dialog);
2938 Decorated decorator;
2939 decorator.decorate(dialog);
2940 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2941 dialog->set_transient_for(*window);
2943 decorator.set_title(String::ucompose(_("Pillaged %1"), city->getName()));
2945 Gtk::Label *pillaged_army_type_cost_label;
2946 xml->get_widget("pillaged_army_type_cost_label", pillaged_army_type_cost_label);
2947 xml->get_widget("pillaged_army_type_image", pillaged_army_type_image);
2950 Glib::RefPtr<Gdk::Pixbuf> s
2951 = GraphicsCache::getInstance()->getArmyPic(as, 0, player, NULL)->to_pixbuf();
2952 Glib::RefPtr<Gdk::Pixbuf> empty_pic
2953 = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, s->get_width(), s->get_height());
2954 empty_pic->fill(0x00000000);
2955 pillaged_army_type_image->set(empty_pic);
2956 pillaged_army_type_cost_label->set_text("");
2960 Glib::RefPtr<Gdk::Pixbuf> pic;
2961 pic = gc->getArmyPic(as, pillaged_army_type, player, NULL)->to_pixbuf();
2962 pillaged_army_type_image->property_pixbuf() = pic;
2963 pillaged_army_type_cost_label->set_text(String::ucompose("%1 gp", gold));
2966 xml->get_widget("label", label);
2967 Glib::ustring s = label->get_text();
2969 s += String::ucompose(
2970 ngettext("The loot is worth %1 gold piece.",
2971 "The loot is worth %1 gold pieces.",
2981 void GameWindow::on_city_sacked(City *city, int gold, std::list<guint32> sacked_types)
2983 GraphicsCache *gc = GraphicsCache::getInstance();
2984 Player *player = city->getOwner();
2985 unsigned int as = player->getArmyset();
2986 Gtk::Dialog* dialog;
2988 Glib::RefPtr<Gtk::Builder> xml
2989 = Gtk::Builder::create_from_file(get_glade_path() + "/city-sacked-dialog.ui");
2991 xml->get_widget("dialog", dialog);
2992 Decorated decorator;
2993 decorator.decorate(dialog);
2994 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
2995 dialog->set_transient_for(*window);
2997 decorator.set_title(String::ucompose(_("Sacked %1"), city->getName()));
3000 xml->get_widget("label", label);
3001 Glib::ustring s = label->get_text();
3002 s = String::ucompose("The city of %1 is sacked\nfor %2 gold!\n\n",
3003 city->getName(), gold);
3004 s += String::ucompose(
3005 ngettext("Ability to produce %1 unit has been lost",
3006 "Ability to produce %1 units has been lost",
3007 sacked_types.size()), sacked_types.size());
3008 s += "\nand only 1 unit remains";
3011 Gtk::Image *sacked_army_1_image;
3012 Gtk::Image *sacked_army_2_image;
3013 Gtk::Image *sacked_army_3_image;
3014 Gtk::Label *sacked_army_1_cost_label;
3015 Gtk::Label *sacked_army_2_cost_label;
3016 Gtk::Label *sacked_army_3_cost_label;
3017 xml->get_widget("sacked_army_1_image", sacked_army_1_image);
3018 xml->get_widget("sacked_army_2_image", sacked_army_2_image);
3019 xml->get_widget("sacked_army_3_image", sacked_army_3_image);
3020 xml->get_widget("sacked_army_1_cost_label", sacked_army_1_cost_label);
3021 xml->get_widget("sacked_army_2_cost_label", sacked_army_2_cost_label);
3022 xml->get_widget("sacked_army_3_cost_label", sacked_army_3_cost_label);
3024 Glib::RefPtr<Gdk::Pixbuf> pic;
3025 Glib::RefPtr<Gdk::Pixbuf> surf
3026 = GraphicsCache::getInstance()->getArmyPic(as, 0, player, NULL)->to_pixbuf();
3027 Glib::RefPtr<Gdk::Pixbuf> empty_pic
3028 = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, surf->get_width(), surf->get_height());
3029 empty_pic->fill(0x00000000);
3031 Gtk::Label *sack_label = NULL;
3032 Gtk::Image *sack_image = NULL;
3033 for (std::list<guint32>::iterator it = sacked_types.begin(); it != sacked_types.end(); it++)
3038 sack_label = sacked_army_1_cost_label;
3039 sack_image = sacked_army_1_image;
3042 sack_label = sacked_army_2_cost_label;
3043 sack_image = sacked_army_2_image;
3046 sack_label = sacked_army_3_cost_label;
3047 sack_image = sacked_army_3_image;
3050 pic = gc->getArmyPic(as, *it, player, NULL)->to_pixbuf();
3051 sack_image->property_pixbuf() = pic;
3052 const ArmyProto *a =
3053 Armysetlist::getInstance()->getArmy (player->getArmyset(), *it);
3054 s = String::ucompose("%1 gp", a->getNewProductionCost() / 2);
3055 sack_label->set_text(s);
3058 for (i = sacked_types.size(); i < 3; i++)
3063 sack_label = sacked_army_1_cost_label;
3064 sack_image = sacked_army_1_image;
3067 sack_label = sacked_army_2_cost_label;
3068 sack_image = sacked_army_2_image;
3071 sack_label = sacked_army_3_cost_label;
3072 sack_image = sacked_army_3_image;
3075 sack_image->set(empty_pic);
3076 sack_label->set_text("");
3084 void GameWindow::on_city_razed (City *city)
3086 Gtk::Dialog* dialog;
3088 Glib::RefPtr<Gtk::Builder> xml
3089 = Gtk::Builder::create_from_file(get_glade_path() + "/city-razed-dialog.ui");
3091 xml->get_widget("dialog", dialog);
3092 Decorated decorator;
3093 decorator.decorate(dialog);
3094 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3095 dialog->set_transient_for(*window);
3097 decorator.set_title(String::ucompose(_("Razed %1"), city->getName()));
3100 xml->get_widget("label", label);
3102 s = String::ucompose(_("The city of %1 is in ruins!"), city->getName());
3111 void GameWindow::on_city_visited(City *city)
3114 GameScenarioOptions::s_razing_cities == GameParameters::ALWAYS,
3115 GameScenarioOptions::s_see_opponents_production);
3117 d.set_parent_window(*window);
3122 void GameWindow::on_ruin_visited(Ruin *ruin)
3124 RuinReportDialog d(ruin->getPos());
3125 d.set_parent_window(*window);
3130 void GameWindow::show_shield_turn() //show turn indicator
3132 Playerlist* pl = Playerlist::getInstance();
3133 GraphicsCache *gc = GraphicsCache::getInstance();
3135 for (Playerlist::iterator i = pl->begin(); i != pl->end(); ++i)
3137 if (pl->getNeutral() == (*i))
3141 shield_image[c]->clear();
3142 turn_hbox->remove(dynamic_cast<Gtk::Widget&>(*shield_image[c]));
3143 turn_hbox->resize_children();
3146 if (*i == pl->getActiveplayer())
3147 shield_image[c]->property_pixbuf()=gc->getShieldPic(1,(*i))->to_pixbuf();
3149 shield_image[c]->property_pixbuf()=gc->getShieldPic(0,(*i))->to_pixbuf();
3150 shield_image[c]->property_tooltip_text() = (*i)->getName();
3153 for (unsigned int i = c; i < MAX_PLAYERS; i++)
3154 shield_image[i]->clear();
3157 void GameWindow::on_remote_next_player_turn()
3159 on_stack_info_changed(NULL);
3160 while (g_main_context_iteration(NULL, FALSE)); //doEvents
3162 d_quick_fights = false;
3164 turn_label->set_markup(String::ucompose("Turn %1",
3165 GameScenarioOptions::s_round));
3168 void GameWindow::on_next_player_turn(Player *player, unsigned int turn_number)
3170 Gtk::Dialog* dialog;
3172 on_stack_info_changed(NULL);
3173 while (g_main_context_iteration(NULL, FALSE)); //doEvents
3175 d_quick_fights = false;
3177 if (player->getType() != Player::HUMAN)
3180 if (Configuration::s_showNextPlayer == true)
3182 Glib::RefPtr<Gtk::Builder> xml
3183 = Gtk::Builder::create_from_file(get_glade_path() +
3184 "/next-player-turn-dialog.ui");
3186 xml->get_widget("dialog", dialog);
3187 dialog->set_transient_for(*window);
3189 Decorated decorator;
3190 decorator.decorate(dialog);
3191 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3193 xml->get_widget("image", image);
3194 image->property_file() = File::getMiscFile("various/ship.png");
3197 xml->get_widget("label", label);
3198 Glib::ustring s = String::ucompose(_("%1\nTurn %2"), player->getName(),
3211 void GameWindow::on_medal_awarded_to_army(Army *army, int medaltype)
3213 GraphicsCache *gc = GraphicsCache::getInstance();
3214 Gtk::Dialog* dialog;
3216 Glib::RefPtr<Gtk::Builder> xml
3217 = Gtk::Builder::create_from_file(get_glade_path() + "/medal-awarded-dialog.ui");
3219 xml->get_widget("dialog", dialog);
3220 Decorated decorator;
3221 decorator.decorate(dialog);
3222 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3223 dialog->set_transient_for(*window);
3226 xml->get_widget("image", image);
3227 Player *active = Playerlist::getInstance()->getActiveplayer();
3228 image->property_pixbuf() =
3229 gc->getArmyPic(active->getArmyset(), army->getTypeId(), active,
3230 army->getMedalBonuses())->to_pixbuf();
3231 Gtk::Image *medal_image;
3232 xml->get_widget("medal_image", medal_image);
3233 medal_image->property_pixbuf() =
3234 gc->getMedalPic(true, medaltype)->to_pixbuf();
3237 xml->get_widget("label", label);
3240 s += String::ucompose(_("Your unit of %1 is awarded the avenger's medal of valour!"), army->getName());
3241 else if (medaltype == 1)
3242 s += String::ucompose(_("Your unit of %1 is awarded the defender's medal of bravery!"), army->getName());
3243 else if (medaltype == 2)
3244 s += String::ucompose(_("Your unit of %1 is awarded the veteran's medal!"), army->getName());
3246 s += String::ucompose(_("Your unit of %1 is awarded a medal!"), army->getName());
3255 Army::Stat GameWindow::on_hero_gains_level(Hero *hero)
3257 ArmyGainsLevelDialog d(hero, GameScenario::s_hidden_map);
3259 d.set_parent_window(*window);
3263 return d.get_selected_stat();
3266 void GameWindow::on_game_loaded(Player *player)
3268 Gtk::Dialog* dialog;
3270 Glib::RefPtr<Gtk::Builder> xml
3271 = Gtk::Builder::create_from_file(get_glade_path() + "/game-loaded-dialog.ui");
3273 xml->get_widget("dialog", dialog);
3274 Decorated decorator;
3275 decorator.decorate(dialog);
3276 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3277 dialog->set_transient_for(*window);
3280 xml->get_widget("label", label);
3282 s += String::ucompose(_("%1, your turn continues."), player->getName());
3291 void GameWindow::on_quest_completed(Quest *quest, Reward *reward)
3293 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3295 QuestCompletedDialog d(quest, reward);
3296 d.set_parent_window(*window);
3301 void GameWindow::on_quest_expired(Quest *quest)
3303 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3305 Gtk::Dialog* dialog;
3307 Glib::RefPtr<Gtk::Builder> xml
3308 = Gtk::Builder::create_from_file(get_glade_path() + "/quest-expired-dialog.ui");
3310 xml->get_widget("dialog", dialog);
3311 Decorated decorator;
3312 decorator.decorate(dialog);
3313 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3314 dialog->set_transient_for(*window);
3317 xml->get_widget("label", label);
3319 s += String::ucompose(_("%1 did not complete the quest."),
3320 quest->getHeroName());
3323 // add messages from the quest
3324 std::queue<std::string> msgs;
3325 quest->getExpiredMsg(msgs);
3326 while (!msgs.empty())
3342 void GameWindow::on_inspect_activated ()
3344 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3346 if (Playerlist::getActiveplayer()->getHeroes().size() == 0)
3349 Vector<int> pos = Vector<int>(-1,-1);
3350 if (currently_selected_stack != NULL)
3352 hero = dynamic_cast<Hero*>(currently_selected_stack->getFirstHero());
3353 pos = currently_selected_stack->getPos();
3356 HeroDialog d(hero, pos);
3357 d.set_parent_window(*window);
3361 void GameWindow::on_plant_standard_activated ()
3363 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3365 Playerlist::getActiveplayer()->heroPlantStandard(NULL);
3368 void GameWindow::on_stack_moves(Stack *stack, Vector<int> pos)
3370 if (GameMap::getEnemyCity(pos))
3372 if (GameMap::getEnemyStack(pos))
3374 //assert (stack == Playerlist::getInstance()->getActiveplayer()->getActivestack());
3375 Player *active = Playerlist::getInstance()->getActiveplayer();
3376 Stack *old = active->getActivestack();
3377 active->setActivestack(stack);
3378 game->get_smallmap().center_view_on_tile (pos, true);
3379 // sleep for a specified amount of time
3380 int step = TIMER_BIGMAP_SELECTOR * 1000;
3381 for (int i = 0; i < Configuration::s_displaySpeedDelay; i += step)
3383 game->get_bigmap().draw(Playerlist::getViewingplayer());
3384 while (g_main_context_iteration(NULL, FALSE)); //doEvents
3387 active->setActivestack(old);
3390 void GameWindow::on_advice_asked(float percent)
3392 if (Playerlist::getActiveplayer()->getType() != Player::HUMAN)
3394 //we asked for advice on a fight, and we're being told that we
3395 //have a PERCENT chance of winning the fight
3396 Gtk::Dialog* dialog;
3398 Glib::RefPtr<Gtk::Builder> xml
3399 = Gtk::Builder::create_from_file(get_glade_path() + "/military-advisor-dialog.ui");
3401 xml->get_widget("dialog", dialog);
3402 Decorated decorator;
3403 decorator.decorate(dialog);
3404 decorator.window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
3405 dialog->set_transient_for(*window);
3407 decorator.set_title(_("Advisor!"));
3410 xml->get_widget("label", label);
3413 int num = rand() % 5;
3415 s += _("My Good Lord!");
3417 s += _("Great and Worthy Lord!");
3419 s += _("O Champion of Justice!");
3421 s += _("O Mighty Leader!");
3423 s += _("O Great Warlord!");
3428 if (percent >= 90.0)
3431 s += _("This battle will surely be as simple as butchering sleeping cattle!");
3433 s += _("A battle here would be as simple as butchering sleeping cattle!");
3435 s += _("I believe this battle will surely be as simple as butchering sleeping cattle!");
3437 s += _("This battle would be as simple as butchering sleeping cattle!");
3439 s += _("A battle here would be as simple as butchering sleeping cattle!");
3441 s += _("I believe this battle will be as simple as butchering sleeping cattle!");
3443 s += _("This battle shall be as simple as butchering sleeping cattle!");
3445 else if (percent >= 80.0)
3448 s += _("This battle will surely be an easy victory! We cannot lose!");
3450 s += _("A battle here would be an easy victory! We cannot lose!");
3452 s += _("I believe this battle will surely be an easy victory! We cannot lose!");
3454 s += _("This battle would be an easy victory! We cannot lose!");
3456 s += _("A battle here would be an easy victory! We cannot lose!");
3458 s += _("I believe this battle will be an easy victory! We cannot lose!");
3460 s += _("This battle shall be an easy victory! We cannot lose!");
3462 else if (percent >= 70.0)
3465 s += _("This battle will surely be a comfortable victory");
3467 s += _("A battle here would be a comfortable victory");
3469 s += _("I believe this battle will surely be a comfortable victory");
3471 s += _("This battle would be a comfortable victory");
3473 s += _("A battle here would be a comfortable victory");
3475 s += _("I believe this battle will be a comfortable victory");
3477 s += _("This battle shall be a comfortable victory");
3479 else if (percent >= 60.0)
3482 s += _("This battle will surely be a hard fought victory! But we shall win!");
3484 s += _("A battle here would be a hard fought victory! But we shall win!");
3486 s += _("I believe this battle will surely be a hard fought victory! But we shall win!");
3488 s += _("This battle would be a hard fought victory! But we shall win!");
3490 s += _("A battle here would be a hard fought victory! But we shall win!");
3492 s += _("I believe this battle will be a hard fought victory! But we shall win!");
3494 s += _("This battle shall be a hard fought victory! But we shall win!");
3496 else if (percent >= 50.0)
3499 s += _("This battle will surely be very evenly matched!");
3501 s += _("A battle here would be very evenly matched!");
3503 s += _("I believe this battle will surely be very evenly matched!");
3505 s += _("This battle would be very evenly matched!");
3507 s += _("A battle here would be very evenly matched!");
3509 s += _("I believe this battle will be very evenly matched!");
3511 s += _("This battle shall be very evenly matched!");
3513 else if (percent >= 40.0)
3516 s += _("This battle will surely be difficult but not impossible to win!");
3518 s += _("A battle here would be difficult but not impossible to win!");
3520 s += _("I believe this battle will surely be difficult but not impossible to win!");
3522 s += _("This battle would be difficult but not impossible to win!");
3524 s += _("A battle here would be difficult but not impossible to win!");
3526 s += _("I believe this battle will be difficult but not impossible to win!");
3528 s += _("This battle shall be difficult but not impossible to win!");
3530 else if (percent >= 30.0)
3533 s += _("This battle will surely be a brave choice! I leave it to thee!");
3535 s += _("A battle here would be a brave choice! I leave it to thee!");
3537 s += _("I believe this battle will surely be a brave choice! I leave it to thee!");
3539 s += _("This battle would be a brave choice! I leave it to thee!");
3541 s += _("A battle here would be a brave choice! I leave it to thee!");
3543 s += _("I believe this battle will be a brave choice! I leave it to thee!");
3545 s += _("This battle shall be a brave choice! I leave it to thee!");
3547 else if (percent >= 20.0)
3550 s += _("This battle will surely be a foolish decision!");
3552 s += _("A battle here would be a foolish decision!");
3554 s += _("I believe this battle will surely be a foolish decision!");
3556 s += _("This battle would be a foolish decision!");
3558 s += _("A battle here would be a foolish decision!");
3560 s += _("I believe this battle will be a foolish decision!");
3562 s += _("This battle shall be a foolish decision!");
3564 else if (percent >= 10.0)
3567 s += _("This battle will surely be sheerest folly! Thou shouldst not attack!");
3569 s += _("A battle here would be sheerest folly! Thou shouldst not attack!");
3571 s += _("I believe this battle will surely be sheerest folly! Thou shouldst not attack!");
3573 s += _("This battle would be sheerest folly! Thou shouldst not attack!");
3575 s += _("A battle here would be sheerest folly! Thou shouldst not attack!");
3577 s += _("I believe this battle will be sheerest folly! Thou shouldst not attack!");
3579 s += _("This battle shall be sheerest folly! Thou shouldst not attack!");
3584 s += _("This battle will surely be complete and utter suicide!");
3586 s += _("A battle here would be complete and utter suicide!");
3588 s += _("I believe this battle will surely be complete and utter suicide!");
3590 s += _("This battle would be complete and utter suicide!");
3592 s += _("A battle here would be complete and utter suicide!");
3594 s += _("I believe this battle will be complete and utter suicide!");
3596 s += _("This battle shall be complete and utter suicide!");
3607 void GameWindow::on_show_lobby_activated()
3612 //taken from go-file.c of gnucash 2.0.4
3614 check_program (char const *prog)
3618 if (g_path_is_absolute (prog)) {
3619 if (!g_file_test (prog, G_FILE_TEST_IS_EXECUTABLE))
3621 } else if (!g_find_program_in_path (prog))
3623 return g_strdup (prog);
3626 //taken from go-file.c of gnucash 2.0.4
3628 go_url_show (gchar const *url)
3631 char *browser = NULL;
3632 char *clean_url = NULL;
3634 /* 1) Check BROWSER env var */
3635 browser = check_program (getenv ("BROWSER"));
3637 if (browser == NULL) {
3638 static char const * const browsers[] = {
3639 "sensible-browser", /* debian */
3640 "htmlview", /* fedora */
3652 for (i = 0 ; i < G_N_ELEMENTS (browsers) ; i++)
3653 if (NULL != (browser = check_program (browsers[i])))
3657 if (browser != NULL) {
3659 gchar **argv = NULL;
3660 char *cmd_line = g_strconcat (browser, " %1", NULL);
3662 if (g_shell_parse_argv (cmd_line, &argc, &argv, &err)) {
3663 /* check for '%1' in an argument and substitute the url
3664 * * otherwise append it */
3668 for (i = 1 ; i < argc ; i++)
3669 if (NULL != (tmp = strstr (argv[i], "%1"))) {
3671 tmp = g_strconcat (argv[i],
3672 (clean_url != NULL) ? (char const *)clean_url : url,
3679 /* there was actually a %1, drop the one we added */
3681 g_free (argv[argc-1]);
3682 argv[argc-1] = NULL;
3684 g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
3685 NULL, NULL, NULL, &err);
3695 void GameWindow::on_online_help_activated()
3697 go_url_show ("http://www.nongnu.org/lordsawar/manual/" PACKAGE_VERSION "/lordsawar.html");
3701 void GameWindow::on_player_replaced(Player *p)
3706 void GameWindow::on_grid_toggled()
3708 game->get_bigmap().toggle_grid();
3711 void GameWindow::give_some_cheese(Player *winner)
3713 game->endOfGameRoaming(winner);
3714 end_turn_button->set_sensitive(false);
3715 end_turn_menuitem->set_sensitive(false);
3716 save_game_menuitem->set_sensitive(false);
3717 save_game_as_menuitem->set_sensitive(false);
3718 Playerlist::getActiveplayer()->clearFogMap();
3721 on_city_history_activated();
3724 void GameWindow::on_commentator_comments(std::string comment)
3726 TimedMessageDialog dialog (*window, comment, 0);
3727 dialog.set_title(_("The Warlord Says..."));
3729 std::vector<PixMask* > buttons;
3730 buttons = disassemble_row(File::getMiscFile("various/buttons.png"), 11);
3731 PixMask::scale(buttons[0], 60, 60);
3732 dialog.set_image(buttons[0]->to_pixbuf());
3737 void GameWindow::on_abbreviated_fight_started(LocationBox box)
3739 game->get_bigmap().setFighting(box);
3740 game->get_bigmap().draw(Playerlist::getViewingplayer());
3741 while (g_main_context_iteration(NULL, FALSE)); //doEvents
3742 Glib::usleep(TIMER_BIGMAP_SELECTOR * 1000);
3743 game->get_bigmap().setFighting(LocationBox(Vector<int>(-1,-1)));
3744 game->get_bigmap().draw(Playerlist::getViewingplayer());