The Battle for Wesnoth  1.13.11+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
menu_events.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 - 2018 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
3  wesnoth playturn Copyright (C) 2003 by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * Operations activated from menus/hotkeys while playing a game.
19  * E.g. Unitlist, status_table, save_game, save_map, chat, show_help, etc.
20  */
21 
22 #include "menu_events.hpp"
23 
24 #include "actions/attack.hpp"
25 #include "actions/create.hpp"
26 #include "actions/move.hpp"
27 #include "actions/undo.hpp"
28 #include "actions/vision.hpp"
29 #include "ai/manager.hpp"
30 #include "chat_command_handler.hpp"
31 #include "color.hpp"
32 #include "display_chat_manager.hpp"
33 #include "font/standard_colors.hpp"
34 #include "formatter.hpp"
35 #include "formula/string_utils.hpp"
36 #include "game_board.hpp"
37 #include "game_config_manager.hpp"
38 #include "game_end_exceptions.hpp"
39 #include "game_events/pump.hpp"
40 #include "preferences/game.hpp"
41 #include "game_state.hpp"
42 #include "gettext.hpp"
43 #include "gui/dialogs/chat_log.hpp"
50 #include "gui/dialogs/message.hpp"
61 #include "gui/widgets/settings.hpp"
62 #include "gui/widgets/window.hpp"
63 #include "help/help.hpp"
64 #include "log.hpp"
65 #include "map/label.hpp"
66 #include "map/map.hpp"
67 #include "map_command_handler.hpp"
68 #include "mouse_events.hpp"
69 #include "play_controller.hpp"
72 #include "preferences/display.hpp"
73 #include "replay.hpp"
74 #include "replay_helper.hpp"
75 #include "resources.hpp"
76 #include "save_index.hpp"
77 #include "savegame.hpp"
80 #include "sound.hpp"
81 #include "synced_context.hpp"
82 #include "terrain/builder.hpp"
83 #include "units/udisplay.hpp"
84 #include "units/unit.hpp"
85 #include "whiteboard/manager.hpp"
86 
87 static lg::log_domain log_engine("engine");
88 #define ERR_NG LOG_STREAM(err, log_engine)
89 #define LOG_NG LOG_STREAM(info, log_engine)
90 
91 namespace events
92 {
94  : gui_(gui)
95  , pc_(pc)
96  , game_config_(game_config)
97  , textbox_info_()
98  , last_search_()
99  , last_search_hit_()
100 {
101 }
102 
104 {
105 }
106 
108 {
109  return pc_.gamestate();
110 }
111 
113 {
114  return gamestate().gamedata_;
115 }
116 
118 {
119  return gamestate().board_;
120 }
121 
123 {
124  return gamestate().board_.units_;
125 }
126 
127 std::vector<team>& menu_handler::teams() const
128 {
129  return gamestate().board_.teams_;
130 }
131 
133 {
134  return gamestate().board_.map();
135 }
136 
138 {
139  return textbox_info_;
140 }
141 
143 {
144  if(!gamestate().lua_kernel_) {
145  return;
146  }
147 
148  config cfg;
149  cfg["side"] = gui_->viewing_side();
150  gamestate().lua_kernel_->run_wml_action("show_objectives", vconfig(cfg),
151  game_events::queued_event("_from_interface", "", map_location(), map_location(), config()));
153 }
154 
156 {
157  gui2::dialogs::statistics_dialog::display(board().get_team(side_num));
158 }
159 
161 {
163 }
164 
166 {
167  int selected_index;
168 
169  if(gui2::dialogs::game_stats::execute(board(), gui_->viewing_team(), selected_index)) {
170  gui_->scroll_to_leader(teams()[selected_index].side());
171  }
172 }
173 
175 {
176  const std::string& input_name
178 
180 
181  dlg.set_title(_("Save Map As"))
182  .set_save_mode(true)
183  .set_path(input_name)
184  .set_extension(".map");
185 
186  if(!dlg.show()) {
187  return;
188  }
189 
190  try {
191  filesystem::write_file(dlg.path(), map().write());
192  gui2::show_transient_message("", _("Map saved."));
193  } catch(filesystem::io_exception& e) {
194  utils::string_map symbols;
195  symbols["msg"] = e.what();
196  const std::string msg = vgettext("Could not save the map: $msg", symbols);
198  }
199 }
200 
202 {
204  // Needed after changing fullscreen/windowed mode or display resolution
206 }
207 
209 {
210  config c;
211  c["name"] = "prototype of chat log";
213  chat_log_dialog.show();
214  // std::string text = resources::recorder->build_chat_log();
215  // gui::show_dialog(*gui_,nullptr,_("Chat Log"),"",gui::CLOSE_ONLY,nullptr,nullptr,"",&text);
216 }
217 
219 {
220  help::show_help();
221 }
222 
224 {
226  ? board().is_observer()
227  ? _("Send to observers only")
228  : _("Send to allies only")
230 }
231 
233 {
235  speak();
236 }
237 
239 {
241  speak();
242 }
243 
245 {
246  if(board().is_observer()) {
247  return !gui_->observers().empty();
248  }
249 
250  for(size_t n = 0; n != teams().size(); ++n) {
251  if(n != gui_->viewing_team() && teams()[gui_->viewing_team()].team_name() == teams()[n].team_name()
252  && teams()[n].is_network()) {
253  return true;
254  }
255  }
256 
257  return false;
258 }
259 
260 void menu_handler::recruit(int side_num, const map_location& last_hex)
261 {
262  std::vector<const unit_type*> sample_units;
263 
264  std::set<std::string> recruits = actions::get_recruits(side_num, last_hex);
265 
266  for(const auto& recruit : recruits) {
268  if(!type) {
269  ERR_NG << "could not find unit '" << recruit << "'" << std::endl;
270  return;
271  }
272 
273  sample_units.push_back(type);
274  }
275 
276  if(sample_units.empty()) {
277  gui2::show_transient_message("", _("You have no units available to recruit."));
278  return;
279  }
280 
281  gui2::dialogs::unit_recruit dlg(sample_units, board().get_team(side_num));
282 
283  dlg.show();
284 
285  if(dlg.get_retval() == gui2::window::OK) {
286  do_recruit(sample_units[dlg.get_selected_index()]->id(), side_num, last_hex);
287  }
288 }
289 
290 void menu_handler::repeat_recruit(int side_num, const map_location& last_hex)
291 {
292  const std::string& last_recruit = board().get_team(side_num).last_recruit();
293  if(last_recruit.empty() == false) {
294  do_recruit(last_recruit, side_num, last_hex);
295  }
296 }
297 
298 bool menu_handler::do_recruit(const std::string& name, int side_num, const map_location& last_hex)
299 {
300  team& current_team = board().get_team(side_num);
301 
302  // search for the unit to be recruited in recruits
303  if(!utils::contains(actions::get_recruits(side_num, last_hex), name)) {
304  return false;
305  }
306 
307  const unit_type* u_type = unit_types.find(name);
308  assert(u_type);
309 
310  if(u_type->cost() > current_team.gold() - (pc_.get_whiteboard()
311  ? pc_.get_whiteboard()->get_spent_gold_for(side_num)
312  : 0))
313  {
314  gui2::show_transient_message("", _("You do not have enough gold to recruit that unit"));
315  return false;
316  }
317 
318  current_team.last_recruit(name);
319  const events::command_disabler disable_commands;
320 
321  map_location loc = last_hex;
322  map_location recruited_from = map_location::null_location();
323 
325  {
326  wb::future_map_if_active future; /* start planned unit map scope if in planning mode */
327  msg = actions::find_recruit_location(side_num, loc, recruited_from, name);
328  } // end planned unit map scope
329 
330  if(!msg.empty()) {
332  return false;
333  }
334 
335  if(!pc_.get_whiteboard() || !pc_.get_whiteboard()->save_recruit(name, side_num, loc)) {
336  // MP_COUNTDOWN grant time bonus for recruiting
337  current_team.set_action_bonus_count(1 + current_team.action_bonus_count());
338 
339  // Do the recruiting.
340 
341  synced_context::run_and_throw("recruit", replay_helper::get_recruit(u_type->id(), loc, recruited_from));
342  return true;
343  }
344 
345  return false;
346 }
347 
348 void menu_handler::recall(int side_num, const map_location& last_hex)
349 {
350  if(pc_.get_disallow_recall()) {
351  gui2::show_transient_message("", _("You are separated from your soldiers and may not recall them"));
352  return;
353  }
354 
355  team& current_team = board().get_team(side_num);
356 
357  std::vector<unit_const_ptr> recall_list_team;
358  {
359  wb::future_map future; // ensures recall list has planned recalls removed
360  recall_list_team = actions::get_recalls(side_num, last_hex);
361  }
362 
363  DBG_WB << "menu_handler::recall: Contents of wb-modified recall list:\n";
364  for(const unit_const_ptr& unit : recall_list_team) {
365  DBG_WB << unit->name() << " [" << unit->id() << "]\n";
366  }
367 
368  if(current_team.recall_list().empty()) {
370  _("There are no troops available to recall\n(You must have veteran survivors from a previous scenario)"));
371  return;
372  }
373  if(recall_list_team.empty()) {
374  gui2::show_transient_message("", _("You currently can't recall at the highlighted location"));
375  return;
376  }
377 
378  gui2::dialogs::unit_recall dlg(recall_list_team, current_team);
379 
380  dlg.show();
381 
382  if(dlg.get_retval() != gui2::window::OK) {
383  return;
384  }
385 
386  int res = dlg.get_selected_index();
387  int unit_cost = current_team.recall_cost();
388 
389  // we need to check if unit has a specific recall cost
390  // if it does we use it elsewise we use the team.recall_cost()
391  // the magic number -1 is what it gets set to if the unit doesn't
392  // have a special recall_cost of its own.
393  if(recall_list_team[res]->recall_cost() > -1) {
394  unit_cost = recall_list_team[res]->recall_cost();
395  }
396 
397  int wb_gold = pc_.get_whiteboard() ? pc_.get_whiteboard()->get_spent_gold_for(side_num) : 0;
398  if(current_team.gold() - wb_gold < unit_cost) {
399  utils::string_map i18n_symbols;
400  i18n_symbols["cost"] = std::to_string(unit_cost);
401  std::string msg = VNGETTEXT("You must have at least 1 gold piece to recall a unit",
402  "You must have at least $cost gold pieces to recall this unit", unit_cost, i18n_symbols);
404  return;
405  }
406 
407  LOG_NG << "recall index: " << res << "\n";
408  const events::command_disabler disable_commands;
409 
410  map_location recall_location = last_hex;
413  {
415  future; // future unit map removes invisible units from map, don't do this outside of planning mode
416  err = actions::find_recall_location(side_num, recall_location, recall_from, *recall_list_team[res].get());
417  } // end planned unit map scope
418 
419  if(!err.empty()) {
421  return;
422  }
423 
424  if(!pc_.get_whiteboard()
425  || !pc_.get_whiteboard()->save_recall(*recall_list_team[res].get(), side_num, recall_location)) {
426  bool success = synced_context::run_and_throw("recall",
427  replay_helper::get_recall(recall_list_team[res]->id(), recall_location, recall_from), true, true,
429 
430  if(!success) {
431  ERR_NG << "menu_handler::recall(): Unit does not exist in the recall list." << std::endl;
432  }
433  }
434 }
435 
436 // Highlights squares that an enemy could move to on their turn, showing how many can reach each square.
437 void menu_handler::show_enemy_moves(bool ignore_units, int side_num)
438 {
439  wb::future_map future; // use unit positions as if all planned actions were executed
440 
442 
443  // Compute enemy movement positions
444  for(auto& u : units()) {
445  bool invisible = u.invisible(u.get_location(), gui_->get_disp_context());
446 
447  if(board().get_team(side_num).is_enemy(u.side()) && !gui_->fogged(u.get_location()) && !u.incapacitated()
448  && !invisible) {
449  const unit_movement_resetter move_reset(u);
450  const pathfind::paths& path
451  = pathfind::paths(u, false, true, teams()[gui_->viewing_team()], 0, false, ignore_units);
452 
454  }
455  }
456 
457  // Find possible unit (no matter whether friend or foe) under the
458  // mouse cursor.
460  const map_location& hex_under_mouse = mh.hovered_hex();
461  const bool selected_hex_has_unit = mh.hex_hosts_unit(hex_under_mouse);
462 
463  if(selected_hex_has_unit) {
464  // At this point, a single pixel move would remove the enemy
465  // [best possible] movements hex tiles highlights, so some
466  // prevention on normal unit mouseover movement highlight
467  // has to be toggled temporarily.
469  }
470 }
471 
473 {
474  team& current_team = board().get_team(side_num);
475  bool auto_shroud = current_team.auto_shroud_updates();
476  // If we're turning automatic shroud updates on, then commit all moves
477  if(!auto_shroud) {
478  update_shroud_now(side_num);
479  }
480 
481  // Toggle the setting and record this.
483 }
484 
485 void menu_handler::update_shroud_now(int /* side_num */)
486 {
488 }
489 
490 // Helpers for menu_handler::end_turn()
491 namespace
492 {
493 /** Returns true if @a side_num has at least one living unit. */
494 bool units_alive(int side_num, const unit_map& units)
495 {
496  for(auto& unit : units) {
497  if(unit.side() == side_num) {
498  return true;
499  }
500  }
501  return false;
502 }
503 
504 /** Returns true if @a side_num has at least one unit that can still move. */
505 bool partmoved_units(
506  int side_num, const unit_map& units, const game_board& board, const std::shared_ptr<wb::manager>& whiteb)
507 {
508  for(auto& unit : units) {
509  if(unit.side() == side_num) {
510  // @todo whiteboard should take into consideration units that have
511  // a planned move but can still plan more movement in the same turn
512  if(board.unit_can_move(unit) && !unit.user_end_turn() && (!whiteb || !whiteb->unit_has_actions(&unit)))
513  return true;
514  }
515  }
516  return false;
517 }
518 
519 /**
520  * Returns true if @a side_num has at least one unit that (can but) has not moved.
521  */
522 bool unmoved_units(
523  int side_num, const unit_map& units, const game_board& board, const std::shared_ptr<wb::manager>& whiteb)
524 {
525  for(auto& unit : units) {
526  if(unit.side() == side_num) {
527  if(board.unit_can_move(unit) && !unit.has_moved() && !unit.user_end_turn()
528  && (!whiteb || !whiteb->unit_has_actions(&unit))) {
529  return true;
530  }
531  }
532  }
533  return false;
534 }
535 
536 } // end anon namespace
537 
538 bool menu_handler::end_turn(int side_num)
539 {
540  if(!gamedata().allow_end_turn()) {
541  gui2::show_transient_message("", _("You cannot end your turn yet!"));
542  return false;
543  }
544 
545  size_t team_num = static_cast<size_t>(side_num - 1);
546  if(team_num < teams().size() && teams()[team_num].no_turn_confirmation()) {
547  // Skip the confirmations that follow.
548  }
549  // Ask for confirmation if the player hasn't made any moves.
551  && (!pc_.get_whiteboard() || !pc_.get_whiteboard()->current_side_has_actions())
552  && units_alive(side_num, units())) {
553  const int res = gui2::show_message("",
554  _("You have not started your turn yet. Do you really want to end your turn?"),
556  if(res == gui2::window::CANCEL) {
557  return false;
558  }
559  }
560  // Ask for confirmation if units still have some movement left.
561  else if(preferences::yellow_confirm() && partmoved_units(side_num, units(), board(), pc_.get_whiteboard())) {
562  const int res = gui2::show_message("",
563  _("Some units have movement left. Do you really want to end your turn?"),
565  if(res == gui2::window::CANCEL) {
566  return false;
567  }
568  }
569  // Ask for confirmation if units still have all movement left.
570  else if(preferences::green_confirm() && unmoved_units(side_num, units(), board(), pc_.get_whiteboard())) {
571  const int res = gui2::show_message("",
572  _("Some units have not moved. Do you really want to end your turn?"),
574  if(res == gui2::window::CANCEL) {
575  return false;
576  }
577  }
578 
579  // Auto-execute remaining whiteboard planned actions
580  // Only finish turn if they all execute successfully, i.e. no ambush, etc.
581  if(pc_.get_whiteboard() && !pc_.get_whiteboard()->allow_end_turn()) {
582  return false;
583  }
584 
585  return true;
586 }
587 
588 void menu_handler::goto_leader(int side_num)
589 {
591  if(i != units().end()) {
592  gui_->scroll_to_tile(i->get_location(), game_display::WARP);
593  }
594 }
595 
597 {
599  if(un != units().end()) {
601  }
602 }
603 
605 {
606  const map_location& loc = mousehandler.get_last_hex();
607  if(map().on_board(loc) == false || gui_->shrouded(loc)) {
608  return;
609  }
610 
611  const terrain_type& type = map().get_terrain_info(loc);
612  // const terrain_type& info = board().map().get_terrain_info(terrain);
614 }
615 
617 {
618  const unit_map::iterator un = current_unit();
619  if(un == units().end() || gui_->viewing_side() != un->side()) {
620  return;
621  }
622 
623  if(un->unrenamable()) {
624  return;
625  }
626 
627  std::string name = un->name();
628  const std::string title(N_("Rename Unit"));
629  const std::string label(N_("Name:"));
630 
631  if(gui2::dialogs::edit_text::execute(title, label, name)) {
632  resources::recorder->add_rename(name, un->get_location());
633  un->rename(name);
635  }
636 }
637 
639 {
640  const mouse_handler& mousehandler = pc_.get_mouse_handler_base();
641 
643  if(res != units().end()) {
644  return res;
645  }
646 
647  return board().find_visible_unit(mousehandler.get_selected_hex(), teams()[gui_->viewing_team()]);
648 }
649 
650 // Helpers for create_unit()
651 namespace
652 {
653 /// Allows a function to return both a type and a gender.
654 typedef std::pair<const unit_type*, unit_race::GENDER> type_and_gender;
655 
656 /**
657  * Allows the user to select a type of unit, using GUI2.
658  * (Intended for use when a unit is created in debug mode via hotkey or
659  * context menu.)
660  * @returns the selected type and gender. If this is canceled, the
661  * returned type is nullptr.
662  */
663 type_and_gender choose_unit()
664 {
665  //
666  // The unit creation dialog makes sure unit types
667  // are properly cached.
668  //
669  gui2::dialogs::unit_create create_dlg;
670  create_dlg.show();
671 
672  if(create_dlg.no_choice()) {
673  return type_and_gender(nullptr, unit_race::NUM_GENDERS);
674  }
675 
676  const std::string& ut_id = create_dlg.choice();
677  const unit_type* utp = unit_types.find(ut_id);
678  if(!utp) {
679  ERR_NG << "Create unit dialog returned nonexistent or unusable unit_type id '" << ut_id << "'." << std::endl;
680  return type_and_gender(static_cast<const unit_type*>(nullptr), unit_race::NUM_GENDERS);
681  }
682  const unit_type& ut = *utp;
683 
684  unit_race::GENDER gender = create_dlg.gender();
685  // Do not try to set bad genders, may mess up l10n
686  /// @todo Is this actually necessary?
687  /// (Maybe create_dlg can enforce proper gender selection?)
688  if(ut.genders().end() == std::find(ut.genders().begin(), ut.genders().end(), gender)) {
689  gender = ut.genders().front();
690  }
691 
692  return type_and_gender(utp, gender);
693 }
694 
695 /**
696  * Creates a unit and places it on the board.
697  * (Intended for use with any units created via debug mode.)
698  */
699 void create_and_place(game_display&,
700  const gamemap&,
701  unit_map&,
702  const map_location& loc,
703  const unit_type& u_type,
705 {
706  synced_context::run_and_throw("debug_create_unit",
707  config {
708  "x", loc.wml_x(),
709  "y", loc.wml_y(),
710  "type", u_type.id(),
711  "gender", gender_string(gender),
712  }
713  );
714 }
715 
716 } // Anonymous namespace
717 
718 /**
719  * Creates a unit (in debug mode via hotkey or context menu).
720  */
722 {
723  // Save the current mouse location before popping up the choice menu (which
724  // gives time for the mouse to move, changing the location).
725  const map_location destination = mousehandler.get_last_hex();
726  assert(gui_ != nullptr);
727 
728  // Let the user select the kind of unit to create.
729  type_and_gender selection = choose_unit();
730  if(selection.first != nullptr) {
731  // Make it so.
732  create_and_place(*gui_, map(), units(), destination, *selection.first, selection.second);
733  }
734 }
735 
737 {
738  const map_location& loc = mousehandler.get_last_hex();
739  const unit_map::iterator i = units().find(loc);
740  if(i == units().end()) {
741  if(!map().is_village(loc)) {
742  return;
743  }
744 
745  // village_owner returns -1 for free village, so team 0 will get it
746  int team = board().village_owner(loc) + 1;
747  // team is 0-based so team=team::nteams() is not a team
748  // but this will make get_village free it
749  if(team > static_cast<int>(teams().size())) {
750  team = 0;
751  }
752  actions::get_village(loc, team + 1);
753  } else {
754  int side = i->side();
755  ++side;
756  if(side > static_cast<int>(teams().size())) {
757  side = 1;
758  }
759  i->set_side(side);
760 
761  if(map().is_village(loc)) {
762  actions::get_village(loc, side);
763  }
764  }
765 }
766 
768 {
769  const map_location loc = mousehandler.get_last_hex();
770  synced_context::run_and_throw("debug_kill", config {"x", loc.wml_x(), "y", loc.wml_y()});
771 }
772 
773 void menu_handler::label_terrain(mouse_handler& mousehandler, bool team_only)
774 {
775  const map_location& loc = mousehandler.get_last_hex();
776  if(map().on_board(loc) == false) {
777  return;
778  }
779 
780  const terrain_label* old_label = gui_->labels().get_label(loc);
781  std::string label = old_label ? old_label->text() : "";
782 
783  if(gui2::dialogs::edit_label::execute(label, team_only)) {
784  std::string team_name;
785  color_t color = font::LABEL_COLOR;
786 
787  if(team_only) {
788  team_name = gui_->labels().team_name();
789  } else {
791  }
792  const terrain_label* res = gui_->labels().set_label(loc, label, gui_->viewing_team(), team_name, color);
793  if(res) {
795  }
796  }
797 }
798 
800 {
801  if(gui_->team_valid() && !board().is_observer()) {
802  const int res = gui2::show_message(
803  _("Clear Labels"),
804  _("Are you sure you want to clear map labels?"),
806  );
807 
808  if(res == gui2::window::OK) {
809  gui_->labels().clear(gui_->current_team_name(), false);
811  }
812  }
813 }
814 
816 {
819  }
820 }
821 
822 void menu_handler::continue_move(mouse_handler& mousehandler, int side_num)
823 {
825  if(i == units().end() || !i->move_interrupted()) {
826  i = units().find(mousehandler.get_selected_hex());
827  if(i == units().end() || !i->move_interrupted()) {
828  return;
829  }
830  }
831  move_unit_to_loc(i, i->get_interrupted_move(), true, side_num, mousehandler);
832 }
833 
835  const map_location& target,
836  bool continue_move,
837  int side_num,
838  mouse_handler& mousehandler)
839 {
840  assert(ui != units().end());
841 
842  pathfind::marked_route route = mousehandler.get_route(&*ui, target, board().get_team(side_num));
843 
844  if(route.steps.empty()) {
845  return;
846  }
847 
848  assert(route.steps.front() == ui->get_location());
849 
850  gui_->set_route(&route);
852 
853  {
854  LOG_NG << "move_unit_to_loc " << route.steps.front() << " to " << route.steps.back() << "\n";
856  }
857 
858  gui_->set_route(nullptr);
860 }
861 
862 void menu_handler::execute_gotos(mouse_handler& mousehandler, int side)
863 {
864  // we will loop on all gotos and try to fully move a maximum of them,
865  // but we want to avoid multiple blocking of the same unit,
866  // so, if possible, it's better to first wait that the blocker move
867 
868  bool wait_blocker_move = true;
869  std::set<map_location> fully_moved;
870 
871  bool change = false;
872  bool blocked_unit = false;
873  do {
874  change = false;
875  blocked_unit = false;
876  for(auto& unit : units()) {
877  if(unit.side() != side || unit.movement_left() == 0) {
878  continue;
879  }
880 
881  const map_location& current_loc = unit.get_location();
882  const map_location& goto_loc = unit.get_goto();
883 
884  if(goto_loc == current_loc) {
886  continue;
887  }
888 
889  if(!map().on_board(goto_loc)) {
890  continue;
891  }
892 
893  // avoid pathfinding calls for finished units
894  if(fully_moved.count(current_loc)) {
895  continue;
896  }
897 
898  pathfind::marked_route route = mousehandler.get_route(&unit, goto_loc, board().get_team(side));
899 
900  if(route.steps.size() <= 1) { // invalid path
901  fully_moved.insert(current_loc);
902  continue;
903  }
904 
905  // look where we will stop this turn (turn_1 waypoint or goto)
906  map_location next_stop = goto_loc;
907  pathfind::marked_route::mark_map::const_iterator w = route.marks.begin();
908  for(; w != route.marks.end(); ++w) {
909  if(w->second.turns == 1) {
910  next_stop = w->first;
911  break;
912  }
913  }
914 
915  if(next_stop == current_loc) {
916  fully_moved.insert(current_loc);
917  continue;
918  }
919 
920  // we delay each blocked move because some other change
921  // may open a another not blocked path
922  if(units().count(next_stop)) {
923  blocked_unit = true;
924  if(wait_blocker_move)
925  continue;
926  }
927 
928  gui_->set_route(&route);
929 
930  {
931  LOG_NG << "execute goto from " << route.steps.front() << " to " << route.steps.back() << "\n";
932  int moves = actions::move_unit_and_record(route.steps, &pc_.get_undo_stack());
933  change = moves > 0;
934  }
935 
936  if(change) {
937  // something changed, resume waiting blocker (maybe one can move now)
938  wait_blocker_move = true;
939  }
940  }
941 
942  if(!change && wait_blocker_move) {
943  // no change when waiting, stop waiting and retry
944  wait_blocker_move = false;
945  change = true;
946  }
947  } while(change && blocked_unit);
948 
949  // erase the footsteps after movement
950  gui_->set_route(nullptr);
952 }
953 
955 {
957  gui_->invalidate_all();
958 }
959 
961 {
963  gui_->invalidate_all();
964 }
965 
966 void menu_handler::unit_hold_position(mouse_handler& mousehandler, int side_num)
967 {
968  const unit_map::iterator un = units().find(mousehandler.get_selected_hex());
969  if(un != units().end() && un->side() == side_num && un->movement_left() >= 0) {
970  un->toggle_hold_position();
971  gui_->invalidate(mousehandler.get_selected_hex());
972 
973  mousehandler.set_current_paths(pathfind::paths());
974 
975  if(un->hold_position()) {
976  mousehandler.cycle_units(false);
977  }
978  }
979 }
980 
981 void menu_handler::end_unit_turn(mouse_handler& mousehandler, int side_num)
982 {
983  const unit_map::iterator un = units().find(mousehandler.get_selected_hex());
984  if(un != units().end() && un->side() == side_num && un->movement_left() >= 0) {
985  un->toggle_user_end_turn();
986  gui_->invalidate(mousehandler.get_selected_hex());
987 
988  mousehandler.set_current_paths(pathfind::paths());
989 
990  if(un->user_end_turn()) {
991  mousehandler.cycle_units(false);
992  }
993  }
994 }
995 
997 {
998  std::ostringstream msg;
999  msg << _("Search");
1000  if(last_search_hit_.valid()) {
1001  msg << " [" << last_search_ << "]";
1002  }
1003  msg << ':';
1004  textbox_info_.show(gui::TEXTBOX_SEARCH, msg.str(), "", false, *gui_);
1005 }
1006 
1008 {
1009  // None of the two parameters really needs to be passed since the information belong to members of the class.
1010  // But since it makes the called method more generic, it is done anyway.
1012  textbox_info_.box()->text(), textbox_info_.check() != nullptr ? textbox_info_.check()->checked() : false);
1013 }
1014 
1015 void menu_handler::add_chat_message(const time_t& time,
1016  const std::string& speaker,
1017  int side,
1018  const std::string& message,
1020 {
1021  gui_->get_chat_manager().add_chat_message(time, speaker, side, message, type, false);
1022 
1024  config {
1025  "sender", preferences::login(),
1026  "message", message,
1027  "whisper", type == events::chat_handler::MESSAGE_PRIVATE,
1028  }
1029  );
1030 }
1031 
1032 // command handler for user :commands. Also understands all chat commands
1033 // via inheritance. This complicates some things a bit.
1034 class console_handler : public map_command_handler<console_handler>, private chat_command_handler
1035 {
1036 public:
1037  // convenience typedef
1040  : chmap()
1041  , chat_command_handler(menu_handler, true)
1042  , menu_handler_(menu_handler)
1043  , team_num_(menu_handler.pc_.current_side())
1044  {
1045  }
1046 
1047  using chmap::dispatch; // disambiguate
1049  using chmap::command_failed;
1050 
1051 protected:
1052  // chat_command_handler's init_map() and handlers will end up calling these.
1053  // this makes sure the commands end up in our map
1054  virtual void register_command(const std::string& cmd,
1056  const std::string& help = "",
1057  const std::string& usage = "",
1058  const std::string& flags = "")
1059  {
1060  chmap::register_command(cmd, h, help, usage, flags + "N"); // add chat commands as network_only
1061  }
1062 
1063  virtual void register_alias(const std::string& to_cmd, const std::string& cmd)
1064  {
1065  chmap::register_alias(to_cmd, cmd);
1066  }
1067 
1068  virtual std::string get_arg(unsigned i) const
1069  {
1070  return chmap::get_arg(i);
1071  }
1072 
1073  virtual std::string get_cmd() const
1074  {
1075  return chmap::get_cmd();
1076  }
1077 
1078  virtual std::string get_data(unsigned n = 1) const
1079  {
1080  return chmap::get_data(n);
1081  }
1082 
1083  // these are needed to avoid ambiguities introduced by inheriting from console_command_handler
1085  using chmap::register_alias;
1086  using chmap::help;
1087  using chmap::is_enabled;
1089 
1090  void do_refresh();
1091  void do_droid();
1092  void do_idle();
1093  void do_theme();
1094  void do_control();
1095  void do_controller();
1096  void do_clear();
1097  void do_foreground();
1098  void do_layers();
1099  void do_fps();
1100  void do_benchmark();
1101  void do_save();
1102  void do_save_quit();
1103  void do_quit();
1104  void do_ignore_replay_errors();
1105  void do_nosaves();
1106  void do_next_level();
1107  void do_choose_level();
1108  void do_turn();
1109  void do_turn_limit();
1110  void do_debug();
1111  void do_nodebug();
1112  void do_lua();
1113  void do_unsafe_lua();
1114  void do_custom();
1115  void do_set_alias();
1116  void do_set_var();
1117  void do_show_var();
1118  void do_inspect();
1119  void do_control_dialog();
1120  void do_unit();
1121  // void do_buff();
1122  // void do_unbuff();
1123  void do_discover();
1124  void do_undiscover();
1125  void do_create();
1126  void do_fog();
1127  void do_shroud();
1128  void do_gold();
1129  void do_event();
1133  void do_toggle_whiteboard();
1134  void do_whiteboard_options();
1135 
1137  {
1138  return _("(D) — debug only, (N) — network only, (A) — admin only");
1139  }
1140 
1141  using chat_command_handler::get_command_flags_description; // silence a warning
1142  std::string get_command_flags_description(const chmap::command& c) const
1143  {
1144  std::string space(" ");
1145  return (c.has_flag('D') ? space + _("(debug command)") : "")
1146  + (c.has_flag('N') ? space + _("(network only)") : "")
1147  + (c.has_flag('A') ? space + _("(admin only)") : "")
1148  + (c.has_flag('S') ? space + _("(not during other events)") : "");
1149  }
1150 
1151  using map::is_enabled;
1152  bool is_enabled(const chmap::command& c) const
1153  {
1154  return !((c.has_flag('D') && !game_config::debug) || (c.has_flag('N') && !menu_handler_.pc_.is_networked_mp())
1155  || (c.has_flag('A') && !preferences::is_authenticated())
1156  || (c.has_flag('S') && (synced_context::get_synced_state() != synced_context::UNSYNCED)));
1157  }
1158 
1159  void print(const std::string& title, const std::string& message)
1160  {
1161  menu_handler_.add_chat_message(time(nullptr), title, 0, message);
1162  }
1163 
1164  void init_map()
1165  {
1166  chat_command_handler::init_map(); // grab chat_ /command handlers
1167 
1168  chmap::get_command("log")->flags = ""; // clear network-only flag from log
1169  chmap::get_command("version")->flags = ""; // clear network-only flag
1170  chmap::get_command("ignore")->flags = ""; // clear network-only flag
1171  chmap::get_command("friend")->flags = ""; // clear network-only flag
1172  chmap::get_command("remove")->flags = ""; // clear network-only flag
1173 
1174  chmap::set_cmd_prefix(":");
1175 
1176  register_command("refresh", &console_handler::do_refresh, _("Refresh gui."));
1177  register_command("droid", &console_handler::do_droid, _("Switch a side to/from AI control."),
1178  _("do not translate the on/off^[<side> [on/off]]"));
1179  register_command("idle", &console_handler::do_idle, _("Switch a side to/from idle state."),
1180  _("do not translate the on/off^[<side> [on/off]]"));
1183  _("Assign control of a side to a different player or observer."), _("<side> <nickname>"), "N");
1184  register_command("controller", &console_handler::do_controller, _("Query the controller status of a side."),
1185  _("<side>"));
1186  register_command("clear", &console_handler::do_clear, _("Clear chat history."));
1187  register_command("foreground", &console_handler::do_foreground, _("Debug foreground terrain."), "", "D");
1189  "layers", &console_handler::do_layers, _("Debug layers from terrain under the mouse."), "", "D");
1190  register_command("fps", &console_handler::do_fps, _("Show fps."));
1192  register_command("save", &console_handler::do_save, _("Save game."));
1193  register_alias("save", "w");
1194  register_command("quit", &console_handler::do_quit, _("Quit game."));
1195  // Note the next value is used hardcoded in the init tests.
1196  register_alias("quit", "q!");
1197  register_command("save_quit", &console_handler::do_save_quit, _("Save and quit."));
1198  register_alias("save_quit", "wq");
1199  register_command("ignore_replay_errors", &console_handler::do_ignore_replay_errors, _("Ignore replay errors."));
1200  register_command("nosaves", &console_handler::do_nosaves, _("Disable autosaves."));
1202  _("Advance to the next scenario, or scenario identified by 'id'"), _("<id>"), "DS");
1203  register_alias("next_level", "n");
1204  register_command("choose_level", &console_handler::do_choose_level, _("Choose next scenario"), "", "DS");
1205  register_alias("choose_level", "cl");
1207  _("Change turn number (and time of day), or increase by one if no number is specified."), _("[turn]"),
1208  "DS");
1210  _("Change turn limit, or turn the turn limit off if no number is specified or it’s −1."), _("[limit]"),
1211  "DS");
1212  register_command("debug", &console_handler::do_debug, _("Turn debug mode on."));
1213  register_command("nodebug", &console_handler::do_nodebug, _("Turn debug mode off."), "", "D");
1215  "lua", &console_handler::do_lua, _("Execute a Lua statement."), _("<command>[;<command>...]"), "DS");
1217  "unsafe_lua", &console_handler::do_unsafe_lua, _("Grant higher privileges to Lua scripts."), "", "D");
1218  register_command("custom", &console_handler::do_custom, _("Set the command used by the custom command hotkey"),
1219  _("<command>[;<command>...]"));
1221  _("Invoke a dialog allowing changing control of MP sides."), "", "N");
1222  register_command("inspect", &console_handler::do_inspect, _("Launch the gamestate inspector"), "", "D");
1224  "alias", &console_handler::do_set_alias, _("Set or show alias to a command"), _("<name>[=<command>]"));
1226  "set_var", &console_handler::do_set_var, _("Set a scenario variable."), _("<var>=<value>"), "DS");
1227  register_command("show_var", &console_handler::do_show_var, _("Show a scenario variable."), _("<var>"), "D");
1229  _("Modify a unit variable. (Only top level keys are supported.)"), "", "DS");
1230 
1231  // register_command("buff", &console_handler::do_buff,
1232  // _("Add a trait to a unit."), "", "D");
1233  // register_command("unbuff", &console_handler::do_unbuff,
1234  // _("Remove a trait from a unit. (Does not work yet.)"), "", "D");
1235  register_command("discover", &console_handler::do_discover, _("Discover all units in help."), "");
1236  register_command("undiscover", &console_handler::do_undiscover, _("'Undiscover' all units in help."), "");
1237  register_command("create", &console_handler::do_create, _("Create a unit."), "", "DS");
1238  register_command("fog", &console_handler::do_fog, _("Toggle fog for the current player."), "", "DS");
1239  register_command("shroud", &console_handler::do_shroud, _("Toggle shroud for the current player."), "", "DS");
1240  register_command("gold", &console_handler::do_gold, _("Give gold to the current player."), "", "DS");
1241  register_command("throw", &console_handler::do_event, _("Fire a game event."), "", "DS");
1242  register_alias("throw", "fire");
1244  _("Toggle overlaying of x,y coordinates on hexes."));
1245  register_alias("show_coordinates", "sc");
1247  _("Toggle overlaying of terrain codes on hexes."));
1248  register_alias("show_terrain_codes", "tc");
1250  _("Toggle overlaying of number of bitmaps on hexes."));
1251  register_alias("show_num_of_bitmaps", "bn");
1252  register_command("whiteboard", &console_handler::do_toggle_whiteboard, _("Toggle planning mode."));
1253  register_alias("whiteboard", "wb");
1255  "whiteboard_options", &console_handler::do_whiteboard_options, _("Access whiteboard options dialog."));
1256  register_alias("whiteboard_options", "wbo");
1257 
1258  if(const config& alias_list = preferences::get_alias()) {
1259  for(const config::attribute& a : alias_list.attribute_range()) {
1260  register_alias(a.second, a.first);
1261  }
1262  }
1263  }
1264 
1265 private:
1267  const unsigned int team_num_;
1268 };
1269 
1270 void menu_handler::send_chat_message(const std::string& message, bool allies_only)
1271 {
1272  config cfg;
1273  cfg["id"] = preferences::login();
1274  cfg["message"] = message;
1275  const time_t time = ::time(nullptr);
1276  std::stringstream ss;
1277  ss << time;
1278  cfg["time"] = ss.str();
1279 
1280  const int side = board().is_observer() ? 0 : gui_->viewing_side();
1281  if(!board().is_observer()) {
1282  cfg["side"] = side;
1283  }
1284 
1285  bool private_message = has_friends() && allies_only;
1286 
1287  if(private_message) {
1288  if(board().is_observer()) {
1289  cfg["to_sides"] = game_config::observer_team_name;
1290  } else {
1291  cfg["to_sides"] = teams()[gui_->viewing_team()].allied_human_teams();
1292  }
1293  }
1294 
1295  resources::recorder->speak(cfg);
1296 
1297  add_chat_message(time, cfg["id"], side, message,
1299 }
1300 
1301 void menu_handler::do_search(const std::string& new_search)
1302 {
1303  if(new_search.empty() == false && new_search != last_search_)
1304  last_search_ = new_search;
1305 
1306  if(last_search_.empty())
1307  return;
1308 
1309  bool found = false;
1311  // If this is a location search, just center on that location.
1312  std::vector<std::string> args = utils::split(last_search_, ',');
1313  if(args.size() == 2) {
1314  int x, y;
1315  x = lexical_cast_default<int>(args[0], 0) - 1;
1316  y = lexical_cast_default<int>(args[1], 0) - 1;
1317  if(x >= 0 && x < map().w() && y >= 0 && y < map().h()) {
1318  loc = map_location(x, y);
1319  found = true;
1320  }
1321  }
1322  // Start scanning the game map
1323  if(loc.valid() == false) {
1324  loc = map_location(map().w() - 1, map().h() - 1);
1325  }
1326 
1327  map_location start = loc;
1328  while(!found) {
1329  // Move to the next location
1330  loc.x = (loc.x + 1) % map().w();
1331  if(loc.x == 0)
1332  loc.y = (loc.y + 1) % map().h();
1333 
1334  // Search label
1335  if(!gui_->shrouded(loc)) {
1336  const terrain_label* label = gui_->labels().get_label(loc);
1337  if(label) {
1338  std::string label_text = label->text().str();
1339  if(std::search(label_text.begin(), label_text.end(), last_search_.begin(), last_search_.end(),
1341  != label_text.end()) {
1342  found = true;
1343  }
1344  }
1345  }
1346  // Search unit name
1347  if(!gui_->fogged(loc)) {
1348  unit_map::const_iterator ui = units().find(loc);
1349  if(ui != units().end()) {
1350  const std::string name = ui->name();
1351  if(std::search(
1352  name.begin(), name.end(), last_search_.begin(), last_search_.end(), chars_equal_insensitive)
1353  != name.end()) {
1354  if(!teams()[gui_->viewing_team()].is_enemy(ui->side())
1355  || !ui->invisible(ui->get_location(), gui_->get_disp_context())) {
1356  found = true;
1357  }
1358  }
1359  }
1360  }
1361 
1362  if(loc == start)
1363  break;
1364  }
1365 
1366  if(found) {
1367  last_search_hit_ = loc;
1369  gui_->highlight_hex(loc);
1370  } else {
1372  // Not found, inform the player
1373  utils::string_map symbols;
1374  symbols["search"] = last_search_;
1375  const std::string msg = vgettext("Could not find label or unit "
1376  "containing the string ‘$search’.",
1377  symbols);
1379  }
1380 }
1381 
1383 {
1384  console_handler ch(*this);
1385  ch.dispatch(str);
1386 }
1387 
1388 std::vector<std::string> menu_handler::get_commands_list()
1389 {
1390  console_handler ch(*this);
1391  // HACK: we need to call dispatch() at least once to get the
1392  // command list populated *at all*. Terrible design.
1393  // An empty command is silently ignored and has negligible
1394  // overhead, so we use that for this purpose here.
1395  ch.dispatch("");
1396  return ch.get_commands_list();
1397 }
1398 
1400 {
1402 
1405 }
1406 
1408 {
1409  // :droid [<side> [on/off]]
1410  const std::string side_s = get_arg(1);
1411  const std::string action = get_arg(2);
1412  // default to the current side if empty
1413  const unsigned int side = side_s.empty() ? team_num_ : lexical_cast_default<unsigned int>(side_s);
1414 
1415  if(side < 1 || side > menu_handler_.teams().size()) {
1416  utils::string_map symbols;
1417  symbols["side"] = side_s;
1418  command_failed(vgettext("Can't droid invalid side: '$side'.", symbols));
1419  return;
1420  } else if(menu_handler_.board().get_team(side).is_network()) {
1421  utils::string_map symbols;
1422  symbols["side"] = std::to_string(side);
1423  command_failed(vgettext("Can't droid networked side: '$side'.", symbols));
1424  return;
1425  } else if(menu_handler_.board().get_team(side).is_local_human()) {
1426  if(menu_handler_.board().get_team(side).is_droid() ? action == " on" : action == " off") {
1427  return;
1428  }
1430  if(team_num_ == side) {
1431  if(playsingle_controller* psc = dynamic_cast<playsingle_controller*>(&menu_handler_.pc_)) {
1432  psc->set_player_type_changed();
1433  }
1434  }
1435  } else if(menu_handler_.board().get_team(side).is_local_ai()) {
1436  // menu_handler_.board().get_team(side).make_human();
1437  // menu_handler_.change_controller(std::to_string(side),"human");
1438 
1439  utils::string_map symbols;
1440  symbols["side"] = side_s;
1441  command_failed(vgettext("Can't droid a local ai side: '$side'.", symbols));
1442  }
1444 }
1445 
1447 {
1448  // :idle [<side> [on/off]]
1449  const std::string side_s = get_arg(1);
1450  const std::string action = get_arg(2);
1451  // default to the current side if empty
1452  const unsigned int side = side_s.empty() ? team_num_ : lexical_cast_default<unsigned int>(side_s);
1453 
1454  if(side < 1 || side > menu_handler_.teams().size()) {
1455  utils::string_map symbols;
1456  symbols["side"] = side_s;
1457  command_failed(vgettext("Can't idle invalid side: '$side'.", symbols));
1458  return;
1459  } else if(menu_handler_.board().get_team(side).is_network()) {
1460  utils::string_map symbols;
1461  symbols["side"] = std::to_string(side);
1462  command_failed(vgettext("Can't idle networked side: '$side'.", symbols));
1463  return;
1464  } else if(menu_handler_.board().get_team(side).is_local_ai()) {
1465  utils::string_map symbols;
1466  symbols["side"] = std::to_string(side);
1467  command_failed(vgettext("Can't idle local ai side: '$side'.", symbols));
1468  return;
1469  } else if(menu_handler_.board().get_team(side).is_local_human()) {
1470  if(menu_handler_.board().get_team(side).is_idle() ? action == " on" : action == " off") {
1471  return;
1472  }
1473  // toggle the proxy controller between idle / non idle
1475  if(team_num_ == side) {
1476  if(playsingle_controller* psc = dynamic_cast<playsingle_controller*>(&menu_handler_.pc_)) {
1477  psc->set_player_type_changed();
1478  }
1479  }
1480  }
1482 }
1483 
1485 {
1487 }
1488 
1490 {
1492  : save_id_(save_id)
1493  {
1494  }
1495 
1496  bool operator()(const team& t) const
1497  {
1498  return t.save_id() == save_id_;
1499  }
1500 
1502 };
1503 
1505 {
1506  // :control <side> <nick>
1508  return;
1509  }
1510 
1511  const std::string side = get_arg(1);
1512  const std::string player = get_arg(2);
1513  if(player.empty()) {
1515  return;
1516  }
1517 
1518  unsigned int side_num;
1519  try {
1520  side_num = lexical_cast<unsigned int>(side);
1521  } catch(bad_lexical_cast&) {
1522  const auto it_t = std::find_if(
1523  resources::gameboard->teams().begin(), resources::gameboard->teams().end(), save_id_matches(side));
1524  if(it_t == resources::gameboard->teams().end()) {
1525  utils::string_map symbols;
1526  symbols["side"] = side;
1527  command_failed(vgettext("Can't change control of invalid side: '$side'.", symbols));
1528  return;
1529  } else {
1530  side_num = it_t->side();
1531  }
1532  }
1533 
1534  if(side_num < 1 || side_num > menu_handler_.teams().size()) {
1535  utils::string_map symbols;
1536  symbols["side"] = side;
1537  command_failed(vgettext("Can't change control of out-of-bounds side: '$side'.", symbols));
1538  return;
1539  }
1540 
1541  menu_handler_.request_control_change(side_num, player);
1543 }
1544 
1546 {
1547  const std::string side = get_arg(1);
1548  unsigned int side_num;
1549  try {
1550  side_num = lexical_cast<unsigned int>(side);
1551  } catch(bad_lexical_cast&) {
1552  utils::string_map symbols;
1553  symbols["side"] = side;
1554  command_failed(vgettext("Can't query control of invalid side: '$side'.", symbols));
1555  return;
1556  }
1557 
1558  if(side_num < 1 || side_num > menu_handler_.teams().size()) {
1559  utils::string_map symbols;
1560  symbols["side"] = side;
1561  command_failed(vgettext("Can't query control of out-of-bounds side: '$side'.", symbols));
1562  return;
1563  }
1564 
1565  std::string report = menu_handler_.board().get_team(side_num).controller().to_string();
1566  if(!menu_handler_.board().get_team(side_num).is_proxy_human()) {
1567  report += " (" + menu_handler_.board().get_team(side_num).proxy_controller().to_string() + ")";
1568  }
1569 
1570  if(menu_handler_.board().get_team(side_num).is_network()) {
1571  report += " (networked)";
1572  }
1573 
1574  print(get_cmd(), report);
1575 }
1576 
1578 {
1580 }
1581 
1583 {
1585 }
1586 
1588 {
1589  display& disp = *(menu_handler_.gui_);
1590 
1591  const mouse_handler& mousehandler = menu_handler_.pc_.get_mouse_handler_base();
1592  const map_location& loc = mousehandler.get_last_hex();
1593 
1594  //
1595  // It's possible to invoke this dialog even if loc isn't a valid hex. I'm not sure
1596  // exactly how that happens, but it does seem to occur when moving the mouse outside
1597  // the window to the menu bar. Not sure if there's a bug when the set-last-hex code
1598  // in that case, but this check at least ensures the dialog is only ever shown for a
1599  // valid, on-map location. Otherwise, an assertion gets thrown.
1600  //
1601  // -- vultraz, 2017-09-21
1602  //
1603  if(disp.get_map().on_board_with_border(loc)) {
1604  gui2::dialogs::terrain_layers::display(disp, loc);
1605  }
1606 }
1607 
1609 {
1611 }
1612 
1614 {
1616 }
1617 
1619 {
1621 }
1622 
1624 {
1625  do_save();
1626  do_quit();
1627 }
1628 
1630 {
1632 }
1633 
1635 {
1636  game_config::ignore_replay_errors = (get_data() != "off") ? true : false;
1637 }
1638 
1640 {
1641  game_config::disable_autosave = (get_data() != "off") ? true : false;
1642 }
1643 
1645 {
1646  synced_context::run_and_throw("debug_next_level", config {"next_level", get_data()});
1647 }
1648 
1650 {
1652  std::vector<std::string> options;
1653  std::string next;
1654  if(tag != "multiplayer") {
1655  for(const config& sc : menu_handler_.game_config_.child_range(tag)) {
1656  const std::string& id = sc["id"];
1657  options.push_back(id);
1658  if(id == menu_handler_.gamedata().next_scenario()) {
1659  next = id;
1660  }
1661  }
1662  } else {
1663  // find scenarios of multiplayer campaigns
1664  // (assumes that scenarios are ordered properly in the game_config)
1666  for(const config& mp : menu_handler_.game_config_.child_range("multiplayer")) {
1667  if(mp["id"] == scenario) {
1668  const std::string& id = mp["id"];
1669  options.push_back(id);
1670  if(id == menu_handler_.gamedata().next_scenario())
1671  next = id;
1672  scenario = mp["next_scenario"].str();
1673  }
1674  }
1675  }
1676  std::sort(options.begin(), options.end());
1677  int choice = std::distance(options.begin(), std::lower_bound(options.begin(), options.end(), next));
1678  {
1679  gui2::dialogs::simple_item_selector dlg(_("Choose Scenario (Debug!)"), "", options);
1680  dlg.set_selected_index(choice);
1681  dlg.show();
1682  choice = dlg.selected_index();
1683  }
1684 
1685  if(choice == -1) {
1686  return;
1687  }
1688 
1689  if(size_t(choice) < options.size()) {
1690  synced_context::run_and_throw("debug_next_level", config {"next_level", options[choice]});
1691  }
1692 }
1693 
1695 {
1697 
1698  int turn = tod_man.turn() + 1;
1699  const std::string& data = get_data();
1700  if(!data.empty()) {
1701  turn = lexical_cast_default<int>(data, 1);
1702  }
1703  synced_context::run_and_throw("debug_turn", config {"turn", turn});
1704 }
1705 
1707 {
1708  int limit = get_data().empty() ? -1 : lexical_cast_default<int>(get_data(), 1);
1709  synced_context::run_and_throw("debug_turn_limit", config {"turn_limit", limit});
1710 }
1711 
1713 {
1715  print(get_cmd(), _("Debug mode activated!"));
1716  game_config::debug = true;
1717  } else {
1718  command_failed(_("Debug mode not available in network games"));
1719  }
1720 }
1721 
1723 {
1724  if(game_config::debug) {
1725  print(get_cmd(), _("Debug mode deactivated!"));
1726  game_config::debug = false;
1727  }
1728 }
1729 
1731 {
1733  return;
1734  }
1735 
1736  synced_context::run_and_throw("debug_lua", config {"code", get_data()});
1737 }
1738 
1740 {
1742  return;
1743  }
1744 
1745  const int retval = gui2::show_message(_("WARNING! Unsafe Lua Mode"),
1746  _("Executing Lua code in in this manner opens your computer to potential security breaches from any "
1747  "malicious add-ons or other programs you may have installed.\n\n"
1748  "Do not continue unless you really know what you are doing."), gui2::dialogs::message::ok_cancel_buttons);
1749 
1750  if(retval == gui2::window::OK) {
1751  print(get_cmd(), _("Unsafe mode enabled!"));
1752  menu_handler_.gamestate().lua_kernel_->load_package();
1753  }
1754 }
1755 
1757 {
1759 }
1760 
1762 {
1763  const std::string data = get_data();
1764  const std::string::const_iterator j = std::find(data.begin(), data.end(), '=');
1765  const std::string alias(data.begin(), j);
1766  if(j != data.end()) {
1767  const std::string command(j + 1, data.end());
1768  if(!command.empty()) {
1769  register_alias(command, alias);
1770  } else {
1771  // "alias something=" deactivate this alias. We just set it
1772  // equal to itself here. Later preferences will filter empty alias.
1773  register_alias(alias, alias);
1774  }
1775  preferences::add_alias(alias, command);
1776  // directly save it for the moment, but will slow commands sequence
1778  } else {
1779  // "alias something" display its value
1780  // if no alias, will be "'something' = 'something'"
1781  const std::string command = chmap::get_actual_cmd(alias);
1782  print(get_cmd(), "'" + alias + "'" + " = " + "'" + command + "'");
1783  }
1784 }
1785 
1787 {
1788  const std::string data = get_data();
1789  if(data.empty()) {
1791  return;
1792  }
1793 
1794  const std::string::const_iterator j = std::find(data.begin(), data.end(), '=');
1795  if(j != data.end()) {
1796  const std::string name(data.begin(), j);
1797  const std::string value(j + 1, data.end());
1798  synced_context::run_and_throw("debug_set_var", config {"name", name, "value", value});
1799  } else {
1800  command_failed(_("Variable not found"));
1801  }
1802 }
1803 
1805 {
1807 }
1808 
1810 {
1812  gui2::dialogs::gamestate_inspector inspect_dialog(
1814  inspect_dialog.show();
1815 }
1816 
1818 {
1820  mp_change_control.show();
1821 }
1822 
1824 {
1825  // prevent SIGSEGV due to attempt to set HP during a fight
1826  if(events::commands_disabled > 0) {
1827  return;
1828  }
1829 
1831  if(i == menu_handler_.units().end()) {
1832  return;
1833  }
1834 
1835  const map_location loc = i->get_location();
1836  const std::string data = get_data(1);
1837  std::vector<std::string> parameters = utils::split(data, '=', utils::STRIP_SPACES);
1838  if(parameters.size() < 2) {
1839  return;
1840  }
1841 
1842  if(parameters[0] == "alignment") {
1843  unit_type::ALIGNMENT alignment;
1844  if(!alignment.parse(parameters[1])) {
1845  utils::string_map symbols;
1846  symbols["alignment"] = get_arg(1);
1848  "Invalid alignment: '$alignment', needs to be one of lawful, neutral, chaotic, or liminal.",
1849  symbols));
1850  return;
1851  }
1852  }
1853 
1854  synced_context::run_and_throw("debug_unit",
1855  config {
1856  "x", loc.wml_x(),
1857  "y", loc.wml_y(),
1858  "name", parameters[0],
1859  "value", parameters[1],
1860  }
1861  );
1862 }
1863 
1865 {
1866  for(const unit_type_data::unit_type_map::value_type& i : unit_types.types()) {
1867  preferences::encountered_units().insert(i.second.id());
1868  }
1869 }
1870 
1872 {
1873  const int res = gui2::show_message("Undiscover",
1874  _("Do you wish to clear all of your discovered units from help?"), gui2::dialogs::message::yes_no_buttons);
1875  if(res != gui2::window::CANCEL) {
1877  }
1878 }
1879 
1880 /** Implements the (debug mode) console command that creates a unit. */
1882 {
1883  const mouse_handler& mousehandler = menu_handler_.pc_.get_mouse_handler_base();
1884  const map_location& loc = mousehandler.get_last_hex();
1885  if(menu_handler_.map().on_board(loc)) {
1886  const unit_type* ut = unit_types.find(get_data());
1887  if(!ut) {
1888  command_failed(_("Invalid unit type"));
1889  return;
1890  }
1891 
1892  // Create the unit.
1893  create_and_place(*menu_handler_.gui_, menu_handler_.map(), menu_handler_.units(), loc, *ut);
1894  } else {
1895  command_failed(_("Invalid location"));
1896  }
1897 }
1898 
1900 {
1901  synced_context::run_and_throw("debug_fog", config());
1902 }
1903 
1905 {
1906  synced_context::run_and_throw("debug_shroud", config());
1907 }
1908 
1910 {
1911  synced_context::run_and_throw("debug_gold", config {"gold", lexical_cast_default<int>(get_data(), 1000)});
1912 }
1913 
1915 {
1916  synced_context::run_and_throw("debug_event", config {"eventname", get_data()});
1917 }
1918 
1920 {
1923 }
1925 {
1928 }
1929 
1931 {
1934 }
1935 
1937 {
1938  if(const std::shared_ptr<wb::manager>& whiteb = menu_handler_.pc_.get_whiteboard()) {
1939  whiteb->set_active(!whiteb->is_active());
1940  if(whiteb->is_active()) {
1941  print(get_cmd(), _("Planning mode activated!"));
1942  whiteb->print_help_once();
1943  } else {
1944  print(get_cmd(), _("Planning mode deactivated!"));
1945  }
1946  }
1947 }
1948 
1950 {
1952  menu_handler_.pc_.get_whiteboard()->options_dlg();
1953  }
1954 }
1955 
1956 void menu_handler::do_ai_formula(const std::string& str, int side_num, mouse_handler& /*mousehandler*/)
1957 {
1958  try {
1959  add_chat_message(time(nullptr), "wfl", 0, ai::manager::get_singleton().evaluate_command(side_num, str));
1960  } catch(wfl::formula_error&) {
1961  } catch(...) {
1962  add_chat_message(time(nullptr), "wfl", 0, "UNKNOWN ERROR IN FORMULA");
1963  }
1964 }
1965 
1967 {
1968  textbox_info_.show(gui::TEXTBOX_COMMAND, translation::sgettext("prompt^Command:"), "", false, *gui_);
1969 }
1970 
1971 void menu_handler::request_control_change(int side_num, const std::string& player)
1972 {
1973  std::string side = std::to_string(side_num);
1974  if(board().get_team(side_num).is_local_human() && player == preferences::login()) {
1975  // this is already our side.
1976  return;
1977  } else {
1978  // The server will (or won't because we aren't allowed to change the controller)
1979  // send us a [change_controller] back, which we then handle in playturn.cpp
1980  pc_.send_to_wesnothd(config {"change_controller", config {"side", side, "player", player}});
1981  }
1982 }
1983 
1985 {
1986  for(const std::string& command : utils::split(preferences::custom_command(), ';')) {
1987  do_command(command);
1988  }
1989 }
1990 
1992 {
1993  if(!pc_.is_networked_mp()) {
1994  textbox_info_.show(gui::TEXTBOX_AI, translation::sgettext("prompt^Command:"), "", false, *gui_);
1995  }
1996 }
1997 
1999 {
2000  gui_->get_chat_manager().clear_chat_messages(); // also clear debug-messages and WML-error-messages
2001 }
2002 
2004 {
2005  pc_.send_to_wesnothd(cfg);
2006 }
2007 
2008 } // end namespace events
void command_failed(const std::string &message, bool=false)
bool show_theme_dialog()
Definition: display.cpp:118
void label_terrain(mouse_handler &mousehandler, bool team_only)
bool has_moved() const
Checks if this unit has moved.
Definition: unit.hpp:1097
boost::intrusive_ptr< const unit > unit_const_ptr
Definition: ptr.hpp:30
bool is_enabled(const chmap::command &c) const
bool is_local_ai() const
Definition: team.hpp:265
bool on_board_with_border(const map_location &loc) const
Definition: map.cpp:374
bool is_network() const
Definition: team.hpp:259
menu_handler & menu_handler_
void do_search(const std::string &new_search)
void set_current_paths(const pathfind::paths &new_paths)
Game board class.
Definition: game_board.hpp:50
game_data & gamedata()
bool fogged(const map_location &loc) const
Returns true if location (x,y) is covered in fog.
Definition: display.cpp:726
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
Definition: message.cpp:152
void set_grid(bool ison)
Definition: display.cpp:72
Dialog is closed with ok button.
Definition: window.hpp:101
void goto_leader(int side_num)
void set_draw_num_of_bitmaps(bool value)
Setter for the terrain code debug overlay on tiles.
Definition: display.hpp:361
std::string mp_scenario
unit_iterator end()
Definition: map.hpp:415
const char * what() const NOEXCEPT
Definition: exceptions.hpp:37
void show_help(const std::string &show_topic, int xloc, int yloc)
Open the help browser, show topic with id show_topic.
Definition: help.cpp:116
std::vector< char_t > string
bool show_fps()
Definition: general.cpp:965
void invalidate_game_status()
Function to invalidate the game status displayed on the sidebar.
Definition: display.hpp:287
bool message_private()
Definition: game.cpp:852
std::map< std::string, t_string > string_map
void write_preferences()
Definition: general.cpp:156
std::unique_ptr< game_lua_kernel > lua_kernel_
Definition: game_state.hpp:50
void set_draw_terrain_codes(bool value)
Setter for the terrain code debug overlay on tiles.
Definition: display.hpp:356
void toggle_droid()
Definition: team.hpp:291
size_t move_unit_and_record(const std::vector< map_location > &steps, undo_list *undo_stack, bool continued_move, bool show_move, bool *interrupted, move_unit_spectator *move_spectator)
Moves a unit across the board.
Definition: move.cpp:1252
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition: display.cpp:3020
map_location last_search_hit_
file_dialog & set_extension(const std::string &value)
Sets the default file extension for file names in save mode.
This class represents a single unit of a specific type.
Definition: unit.hpp:100
std::string get_tagname() const
void show_terrain_description(const terrain_type &t)
Definition: help.cpp:63
bool get_draw_terrain_codes() const
Getter for the terrain code debug overlay on tiles.
Definition: display.hpp:354
bool operator()(const team &t) const
static void toggle_benchmark()
Toggle to continuously redraw the screen.
Definition: display.cpp:1340
Various functions implementing vision (through fog of war and shroud).
const mp_game_settings & get_mp_settings()
void send_chat_message(const std::string &message, bool allies_only=false) override
file_dialog & set_path(const std::string &value)
Sets the initial file selection.
bool is_authenticated()
Definition: game.cpp:181
void speak(const config &cfg)
Definition: replay.cpp:344
const gamemap & map() const
static manager & get_singleton()
Definition: manager.hpp:152
menu_handler(game_display *gui, play_controller &pc, const config &game_config)
Definition: menu_events.cpp:93
Various functions that implement attacks and attack calculations.
bool team_valid() const
Definition: display.cpp:716
void add_chat_message(const time_t &time, const std::string &speaker, int side, const std::string &message, events::chat_handler::MESSAGE_TYPE type=events::chat_handler::MESSAGE_PRIVATE) override
map_command_handler< console_handler > chmap
std::string current_team_name() const
unit_iterator find_leader(int side)
Definition: map.cpp:329
static config get_recall(const std::string &unit_id, const map_location &loc, const map_location &from)
const std::string & choice() const
Unit type choice from the user.
Definition: unit_create.hpp:41
#define a
pathfind::marked_route get_route(const unit *un, map_location go_to, team &team) const
unit_race::GENDER gender()
Gender choice from the user.
Definition: unit_create.hpp:53
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
Definition: unit.hpp:1067
Shows an ok and cancel button.
Definition: message.hpp:75
bool user_end_turn() const
Check whether the user ended their turn.
Definition: unit.hpp:652
std::string private_message
bool is_enemy(int n) const
Definition: team.hpp:241
This file contains the window object, this object is a top level container which has the event manage...
child_itors child_range(config_key_type key)
Definition: config.cpp:362
void show_unit_list(display &gui)
Definition: unit_list.cpp:198
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup, const bool restore_background)
Shows a transient message to the user.
void do_command(const std::string &str)
attribute_map::value_type attribute
Definition: config.hpp:257
void redraw_everything()
Invalidates entire screen, including all tiles and sidebar.
Definition: display.cpp:2412
gui::floating_textbox & get_textbox()
General purpose widgets.
void request_control_change(int side_num, const std::string &player)
void invalidate_unit()
Function to invalidate that unit status displayed on the sidebar.
PROXY_CONTROLLER proxy_controller() const
Definition: team.hpp:279
virtual const gamemap & map() const override
Definition: game_board.hpp:109
std::string get_flags_description() const
static config get_auto_shroud(bool turned_on)
Records that the player has toggled automatic shroud updates.
unit_type_data unit_types
Definition: types.cpp:1453
void print(const std::string &title, const std::string &message)
const color_t LABEL_COLOR
file_dialog & set_save_mode(bool value)
Sets the dialog's behavior on non-existent file name inputs.
void update_shroud_now(int side_num)
int village_owner(const map_location &loc) const
Given the location of a village, will return the 0-based index of the team that currently owns it...
#define VNGETTEXT(msgid, msgid_plural, count,...)
Replay control code.
#define h
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
int wml_y() const
Definition: location.hpp:118
static bool execute(game_board &board, const int viewing_team, int &selected_index)
Definition: game_stats.hpp:40
virtual bool is_enabled(const command &) const
std::string path() const
Gets the current file selection.
bool chars_equal_insensitive(char a, char b)
Definition: general.hpp:21
const map_location & get_last_hex() const
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
virtual std::string get_arg(unsigned i) const
bool get_disallow_recall() const
std::shared_ptr< wb::manager > get_whiteboard() const
bool is_proxy_human() const
Definition: team.hpp:280
To lexical_cast(From value)
Lexical cast converts one type to another.
bool show(const unsigned auto_close_time=0)
Shows the window.
void create_unit(mouse_handler &mousehandler)
Creates a unit (in debug mode via hotkey or context menu).
bool unit_can_move(const unit &u) const
Will return true iff the unit u has any possible moves it can do (including attacking etc)...
int get_selected_index() const
Definition: unit_recall.hpp:43
save_id_matches(const std::string &save_id)
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
bool yellow_confirm()
Definition: game.cpp:977
bool ellipses()
Definition: general.cpp:497
static synced_state get_synced_state()
map_location get_selected_hex() const
std::vector< unit_const_ptr > get_recalls(int side, const map_location &recall_loc)
Gets the recallable units for a side, restricted by that side's leaders' personal abilities to recall...
Definition: create.cpp:158
std::vector< std::string > get_commands_list() const
static config get_update_shroud()
Records that the player has manually updated fog/shroud.
void show_statistics(int side_num)
const std::string & last_recruit() const
Definition: team.hpp:227
A single unit type that the player may recruit.
Definition: types.hpp:42
game_data * gamedata
Definition: resources.cpp:22
void flush_cache()
Definition: image.cpp:211
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:78
void do_consolesave(const std::string &filename)
Pubic entry points for the MP workflow.
Definition: lobby_data.cpp:47
bool confirm_no_moves()
Definition: game.cpp:982
unit_map units_
Definition: game_board.hpp:58
const config & options()
Definition: game.cpp:570
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:44
bool end_turn(int side_num)
game_display * gui_
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:89
console_handler(menu_handler &menu_handler)
virtual void register_alias(const std::string &to_cmd, const std::string &cmd)
void toggle_shroud_updates(int side_num)
const t_string & text() const
Definition: label.hpp:136
team & get_team(int i)
Definition: game_board.hpp:104
void set_custom_command(const std::string &command)
Definition: game.cpp:954
int recall_cost() const
Definition: team.hpp:192
void throw_quit_game_exception()
static color_t get_side_rgb(int side)
Definition: team.hpp:367
void scroll_to_leader(int side, SCROLL_TYPE scroll_type=ONSCREEN, bool force=true)
Scrolls to the leader of a certain side.
int selected_index() const
Returns the selected item index after displaying.
bool auto_shroud_updates() const
Definition: team.hpp:334
int wml_x() const
Definition: location.hpp:117
virtual void register_alias(const std::string &to_cmd, const std::string &cmd)
void disable_units_highlight()
Use this to disable hovering an unit from highlighting its movement range.
This file contains the settings handling of the widget library.
game_board & board() const
std::vector< team > teams_
Definition: game_board.hpp:53
const unit_type_map & types() const
Definition: types.hpp:359
virtual config::attribute_value get_variable_const(const std::string &varname) const
returns a blank attribute value if varname is no valid variable name.
Definition: game_data.cpp:67
bool valid() const
Definition: location.hpp:74
const std::set< std::string > get_recruits(int side, const map_location &recruit_loc)
Gets the recruitable units from a side's leaders' personal recruit lists who can recruit on or from a...
Definition: create.cpp:58
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1141
const terrain_label * set_label(const map_location &loc, const t_string &text, const int creator=-1, const std::string &team="", const color_t color=font::NORMAL_COLOR, const bool visible_in_fog=true, const bool visible_in_shroud=false, const bool immutable=false, const std::string &category="", const t_string &tooltip="")
Definition: label.cpp:146
void do_create()
Implements the (debug mode) console command that creates a unit.
Applies the planned unit map for the duration of the struct's life.
Definition: manager.hpp:251
const std::string & id() const
Gets this unit's id.
Definition: unit.hpp:284
std::string get_user_data_dir()
void clear(const std::string &, bool force)
Definition: label.cpp:210
bool disable_autosave
void write_file(const std::string &fname, const std::string &data)
Throws io_exception if an error occurs.
static void ignore_error_function(const std::string &message, bool heavy)
a function to be passed to run_in_synced_context to ignore the error.
bool hex_hosts_unit(const map_location &hex) const
Unit exists on the hex, no matter if friend or foe.
bool get_draw_coordinates() const
Getter for the x,y debug overlay on tiles.
Definition: display.hpp:349
bool ignore_replay_errors
void set_draw_coordinates(bool value)
Setter for the x,y debug overlay on tiles.
Definition: display.hpp:351
int w() const
Effective map width.
Definition: map.hpp:90
void recall(int side_num, const map_location &last_hex)
game_board * gameboard
Definition: resources.cpp:20
REMOVE_EMPTY: remove empty elements.
const config & game_config_
bool empty() const
Is it empty?
const t_string & name() const
Gets this unit's translatable display name.
Definition: unit.hpp:307
void end_unit_turn(mouse_handler &mousehandler, int side_num)
void set_show_fps(bool value)
Definition: general.cpp:970
Encapsulates the map of the game.
Definition: map.hpp:34
const std::vector< unit_race::GENDER > & genders() const
The returned vector will not be empty, provided this has been built to the HELP_INDEXED status...
Definition: types.hpp:239
virtual const std::set< std::string > & observers() const override
void recruit(int side_num, const map_location &last_hex)
std::vector< team > & teams() const
void do_speak(const std::string &message, bool allies_only=false)
tod_manager tod_manager_
Definition: game_state.hpp:47
bool is_local_human() const
Definition: team.hpp:264
Object which temporarily resets a unit's movement.
Definition: unit.hpp:1723
std::string path
Definition: game_config.cpp:56
void add_rename(const std::string &name, const map_location &loc)
Definition: replay.cpp:289
Shows a yes and no button.
Definition: message.hpp:79
void highlight_another_reach(const pathfind::paths &paths_list)
Add more paths to highlight.
const std::string & team_name() const
Definition: label.cpp:128
const terrain_label * get_label(const map_location &loc, const std::string &team_name) const
Definition: label.hpp:47
Managing the AIs lifecycle - headers.
virtual std::string get_cmd() const
replay * recorder
Definition: resources.cpp:28
void create_buttons()
Definition: display.cpp:891
Structure which holds a single route and marks for special events.
Definition: pathfind.hpp:140
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:98
std::string get_command_flags_description(const map_command_handler< chat_command_handler >::command &c) const
game_state & gamestate() const
static const map_location & null_location()
Definition: location.hpp:224
void invalidate_all()
Function to invalidate all tiles.
Definition: display.cpp:3010
int viewing_side() const
Definition: display.hpp:102
std::string get_dir(const std::string &dir)
void set_message_private(bool value)
Definition: game.cpp:857
game_events::manager * game_events
Definition: resources.cpp:24
void show_unit_description(const unit &u)
Definition: help.cpp:58
const std::string & save_id() const
Definition: team.hpp:230
const std::string & gender_string(unit_race::GENDER gender)
Definition: race.cpp:131
bool do_recruit(const std::string &name, int side_num, const map_location &last_hex)
int cost() const
Definition: types.hpp:158
Encapsulates the map of the game.
Definition: location.hpp:42
Various functions related to moving units.
std::string login()
Various functions related to the creation of units (recruits, recalls, and placed units)...
size_t size(const utf8::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
actions::undo_list & get_undo_stack()
std::string write() const
Definition: map.cpp:206
void recalculate_labels()
Definition: label.cpp:244
static void display(const config &game_cfg, const preferences::PREFERENCE_VIEW initial_view=preferences::VIEW_DEFAULT)
The display function – see modal_dialog for more information.
static bool execute(display_context &dc)
The execute function.
void continue_move(mouse_handler &mousehandler, int side_num)
void add_alias(const std::string &alias, const std::string &command)
Definition: general.cpp:1011
logger & err()
Definition: log.cpp:79
int h() const
Effective map height.
Definition: map.hpp:93
void scroll_to_tile(const map_location &loc, SCROLL_TYPE scroll_type=ONSCREEN, bool check_fogged=true, bool force=true)
Scroll such that location loc is on-screen.
Definition: display.cpp:2196
bool no_choice() const
Whether the user actually chose a unit type or not.
Definition: unit_create.hpp:47
void execute_gotos(mouse_handler &mousehandler, int side_num)
virtual void highlight_hex(map_location hex) override
Function to highlight a location.
std::string last_search_
Game configuration data as global variables.
Definition: build_info.cpp:53
bool shrouded(const map_location &loc) const
Returns true if location (x,y) is covered in shroud.
Definition: display.cpp:721
EXIT_STATUS start(const config &game_conf, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:28
An exception object used when an IO error occurs.
Definition: filesystem.hpp:46
const std::string & next_scenario() const
Definition: game_data.hpp:87
int turn() const
void terrain_description(mouse_handler &mousehandler)
Define the game's event mechanism.
std::string find_recall_location(const int side, map_location &recall_location, map_location &recall_from, const unit &unit_recall)
Finds a location on which to recall unit_recall.
Definition: create.cpp:328
size_t i
Definition: function.cpp:933
ONLY IF whiteboard is currently active, applies the planned unit map for the duration of the struct's...
Definition: manager.hpp:272
void unit_hold_position(mouse_handler &mousehandler, int side_num)
virtual std::string get_arg(unsigned argn) const
void change_side(mouse_handler &mousehandler)
virtual std::string get_data(unsigned n=1) const
game_data gamedata_
Definition: game_state.hpp:45
int w
std::set< std::string > & encountered_units()
Definition: game.cpp:942
const std::unique_ptr< gui::textbox > & box() const
#define N_(String)
Definition: gettext.hpp:97
Definitions for the terrain builder.
void show(gui::TEXTBOX_MODE mode, const std::string &label, const std::string &check_label, bool checked, game_display &gui)
static int sort(lua_State *L)
Definition: ltablib.cpp:411
void set_goto(const map_location &new_goto)
Sets this unit's long term destination.
Definition: unit.hpp:1178
#define VGETTEXT(msgid,...)
void set_ellipses(bool ison)
Definition: general.cpp:502
void cycle_units(const bool browse, const bool reverse=false)
void kill_unit(mouse_handler &mousehandler)
const std::unique_ptr< gui::button > & check() const
void toggle_idle()
Definition: team.hpp:292
const command * get_command(const std::string &cmd) const
std::string vgettext(const char *msgid, const utils::string_map &symbols)
Handling of system events.
Definition: manager.hpp:41
CONTROLLER controller() const
Definition: team.hpp:253
bool grid()
Definition: general.cpp:507
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:369
#define next(ls)
Definition: llex.cpp:32
display_chat_manager & get_chat_manager()
const map_location & get_goto() const
The map location to which this unit is moving over multiple turns, if any.
Definition: unit.hpp:1172
const map_location hovered_hex() const
Uses SDL and game_display::hex_clicked_on to fetch the hex the mouse is hovering, if applicable...
static bool run_and_throw(const std::string &commandname, const config &data, bool use_undo=true, bool show=true, synced_command::error_handler_function error_handler=default_error_function)
bool has_friends() const
void show_transient_error_message(const std::string &message, const std::string &image, const bool message_use_markup)
Shows a transient error message to the user.
bool green_confirm()
Definition: game.cpp:968
int gold() const
Definition: team.hpp:188
game_events::pump_result_t get_village(const map_location &loc, int side, bool *action_timebonus, bool fire_event)
Makes it so the village at the given location is owned by the given side.
Definition: move.cpp:139
To store label data Class implements logic for rendering.
Definition: label.hpp:107
events::mouse_handler & get_mouse_handler_base() override
Get a reference to a mouse handler member a derived class uses.
unit_map::iterator current_unit()
game_state & gamestate()
double t
Definition: astarsearch.cpp:64
bool unhighlight_reach()
Reset highlighting of paths.
const gamemap & get_map() const
Definition: display.hpp:91
bool find(E event, F functor)
Tests whether an event handler is available.
void show_objectives() const
bool player_acted() const
Returns true if the player has performed any actions this turn.
Definition: undo.hpp:83
void show_enemy_moves(bool ignore_units, int side_num)
static UNUSEDNOWARN std::string sgettext(const char *str)
Definition: gettext.hpp:66
void set_selected_index(int index)
Sets the initially selected item index (-1 by default).
game_board board_
Definition: game_state.hpp:46
#define DBG_WB
Definition: typedefs.hpp:27
A variable-expanding proxy for the config class.
Definition: variable.hpp:42
Various functions that implement the undoing (and redoing) of in-game commands.
bool is_idle() const
Definition: team.hpp:282
std::string find_recruit_location(const int side, map_location &recruit_location, map_location &recruited_from, const std::string &unit_type)
Finds a location on which to place a unit.
Definition: create.cpp:464
void set_action_bonus_count(const int count)
Definition: team.hpp:213
Standard logging facilities (interface).
Object which contains all the possible locations a unit can move to, with associated best routes to t...
Definition: pathfind.hpp:70
recall_list_manager & recall_list()
Definition: team.hpp:214
bool is_observer() const
Check if we are an observer in this game.
Container associating units to locations.
Definition: map.hpp:99
static const char * name(const std::vector< SDL_Joystick * > &joysticks, const size_t index)
Definition: joystick.cpp:48
static vconfig empty_vconfig()
Definition: variable.cpp:105
const display_context & get_disp_context() const
Definition: display.hpp:167
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
Definition: types.cpp:1276
static config get_recruit(const std::string &type_id, const map_location &loc, const map_location &from)
map_labels & labels()
Definition: display.cpp:2531
virtual std::string get_data(unsigned argn=1) const
#define e
Definition: help.cpp:56
unit_iterator find(size_t id)
Definition: map.cpp:311
size_t viewing_team() const
The viewing team is the team currently viewing the game.
Definition: display.hpp:101
virtual bool is_networked_mp() const
const std::string & str() const
Definition: tstring.hpp:186
virtual void register_command(const std::string &cmd, command_handler h, const std::string &help="", const std::string &usage="", const std::string &flags="")
gui::floating_textbox textbox_info_
std::string get_command_flags_description(const chmap::command &c) const
void send_to_server(const config &cfg) override
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
void add_chat_message(const time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
game_classification & get_classification()
void notify_event(const std::string &name, const config &data)
Definition: manager.cpp:144
mock_char c
const config & get_alias()
Definition: general.cpp:1018
int action_bonus_count() const
Definition: team.hpp:212
void set_route(const pathfind::marked_route *route)
Sets the route along which footsteps are drawn to show movement of a unit.
Enables auto close.
Definition: message.hpp:69
std::string custom_command()
Definition: game.cpp:950
std::vector< std::string > get_commands_list()
static map_location::DIRECTION n
void repeat_recruit(int side_num, const map_location &last_hex)
void move_unit_to_loc(const unit_map::iterator &ui, const map_location &target, bool continue_move, int side_num, mouse_handler &mousehandler)
Thrown when a lexical_cast fails.
void close(game_display &gui)
void clear_labels(const std::string &, bool)
Definition: replay.cpp:279
static void toggle_debug_foreground()
Toggle to debug foreground terrain.
Definition: display.cpp:1345
Dialog is closed with the cancel button.
Definition: window.hpp:102
bool get_draw_num_of_bitmaps() const
Getter for the number of bitmaps debug overlay on tiles.
Definition: display.hpp:359
const unsigned int team_num_
int side() const
The side this unit belongs to.
Definition: unit.hpp:244
unit_map::iterator find_visible_unit(const map_location &loc, const team &current_team, bool see_all=false)
Definition: game_board.cpp:168
Display units performing various actions: moving, attacking, and dying.
virtual void register_command(const std::string &cmd, chat_command_handler::command_handler h, const std::string &help="", const std::string &usage="", const std::string &flags="")
play_controller & pc_
std::vector< map_location > & steps
Definition: pathfind.hpp:186
const std::string & id() const
The id for this unit_type.
Definition: types.hpp:139
bool is_droid() const
Definition: team.hpp:281
static plugins_manager * get()
Definition: manager.cpp:58
void add_label(const terrain_label *)
Definition: replay.cpp:268
const std::string observer_team_name
observer team name used for observer team chat
std::string get_actual_cmd(const std::string &cmd) const
void do_ai_formula(const std::string &str, int side_num, mouse_handler &mousehandler)
file_dialog & set_title(const std::string &value)
Sets the current dialog title text.
Definition: file_dialog.hpp:56