The Battle for Wesnoth  1.17.23+dev
hotkey_handler_sp.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2023
3  by Chris Beck <render787@gmail.com>
4  Part of the Battle for Wesnoth Project https://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 
17 
18 #include "filesystem.hpp" // for get_saves_dir()
19 #include "font/standard_colors.hpp"
20 #include "formula/string_utils.hpp"
21 #include "gui/dialogs/message.hpp"
23 #include "hotkey/hotkey_item.hpp"
24 #include "map/label.hpp"
25 #include "play_controller.hpp"
27 #include "whiteboard/manager.hpp"
30 #include "map/map.hpp"
31 #include "save_index.hpp"
32 #include "saved_game.hpp"
33 #include "resources.hpp"
34 #include "replay.hpp"
35 
36 #include "units/unit.hpp"
37 
38 #include <boost/algorithm/string/predicate.hpp>
39 
40 namespace balg = boost::algorithm;
41 
44  , playsingle_controller_(pc)
45  , whiteboard_manager_(pc.get_whiteboard())
46 {}
47 
49 
50 bool playsingle_controller::hotkey_handler::is_observer() const { return playsingle_controller_.is_observer(); }
51 
53  if (!browse())
54  menu_handler_.recruit(play_controller_.current_side(), mouse_handler_.get_last_hex());
55  else if (whiteboard_manager_->is_active())
56  menu_handler_.recruit(gui()->viewing_side(), mouse_handler_.get_last_hex());
57 }
58 
60  if (!browse())
61  menu_handler_.repeat_recruit(play_controller_.current_side(), mouse_handler_.get_last_hex());
62  else if (whiteboard_manager_->is_active())
64 }
65 
67  if (!browse())
68  menu_handler_.recall(play_controller_.current_side(), mouse_handler_.get_last_hex());
69  else if (whiteboard_manager_->is_active())
70  menu_handler_.recall(gui()->viewing_side(), mouse_handler_.get_last_hex());
71 }
72 
74  menu_handler_.toggle_shroud_updates(gui()->viewing_team()+1);
75 }
76 
78  menu_handler_.update_shroud_now(gui()->viewing_team()+1);
79 }
80 
82  playsingle_controller_.end_turn();
83 }
84 
87 }
88 
91 }
92 
95 }
96 
99 }
100 
103 }
104 
107 }
108 
110  menu_handler_.continue_move(mouse_handler_, play_controller_.current_side());
111 }
112 
114  if (!browse())
115  menu_handler_.unit_hold_position(mouse_handler_, play_controller_.current_side());
116 }
117 
119  if (!browse())
120  menu_handler_.end_unit_turn(mouse_handler_, play_controller_.current_side());
121 }
122 
125 }
126 
129 }
130 
133 }
134 
137 }
138 
141 }
142 
144  whiteboard_manager_->set_active(!whiteboard_manager_->is_active());
145 
146  if (whiteboard_manager_->is_active()) {
148  utils::string_map symbols;
149  symbols["hotkey"] = hk;
150 
151  gui()->announce(_("Planning mode activated!") + std::string("\n") + VGETTEXT("(press $hotkey to deactivate)", symbols), font::NORMAL_COLOR);
152  } else {
153  gui()->announce(_("Planning mode deactivated!"), font::NORMAL_COLOR);
154  }
155  //@todo Stop printing whiteboard help in the chat once we have better documentation/help
156  whiteboard_manager_->print_help_once();
157 }
158 
160  whiteboard_manager_->contextual_execute();
161 }
162 
164  whiteboard_manager_->execute_all_actions();
165 }
166 
168  whiteboard_manager_->contextual_delete();
169 }
170 
172 {
173  whiteboard_manager_->contextual_bump_up_action();
174 }
175 
177 {
178  whiteboard_manager_->contextual_bump_down_action();
179 }
180 
182 {
183  unit* curr_unit;
184  map_location loc;
185  { wb::future_map future; //start planned unit map scope
186  curr_unit = &*menu_handler_.current_unit();
187  loc = curr_unit->get_location();
188  } // end planned unit map scope
189  whiteboard_manager_->save_suppose_dead(*curr_unit,loc);
190 }
191 
193 {
194  switch(cmd.hotkey_command) {
197  default:
199  }
200 }
201 
203 {
205  bool res = true;
206  int prefixlen = wml_menu_hotkey_prefix.length();
207  switch (command){
208  case hotkey::HOTKEY_NULL:
209  case hotkey::HOTKEY_WML:
210  {
211  if(cmd.id.compare(0, prefixlen, wml_menu_hotkey_prefix) == 0) {
212  game_events::wmi_manager::item_ptr item = gamestate().get_wml_menu_items().get_item(std::string(cmd.id.substr(prefixlen)));
213  if(!item) {
214  return false;
215  }
216  return !item->is_synced() || play_controller_.can_use_synced_wml_menu();
217  }
219 
220  }
222  return !events::commands_disabled || (playsingle_controller_.is_replay() && events::commands_disabled < 2);
225  return !browse() && !linger() && !events::commands_disabled;
229  return (!browse() || whiteboard_manager_->is_active()) && !linger() && !events::commands_disabled;
231  //TODO: Its unclear to me under which cirumstances the other clients can remain in linger mode
232  // when the host pressed scenario, some codes suggest that tha can be the case some don't.
233  return (!browse() || (linger() && playsingle_controller_.is_host())) && !events::commands_disabled;
234 
236  return !linger()
237  && (viewing_team().uses_fog() || viewing_team().uses_shroud())
238  && viewing_team_is_playing()
239  && viewing_team().is_local_human()
242  return !linger()
243  && viewing_team_is_playing()
244  && viewing_team().is_local_human()
246  && viewing_team().auto_shroud_updates() == false;
247 
248  // Commands we can only do if in debug mode
252  return !events::commands_disabled && game_config::debug && play_controller_.get_map().on_board(mouse_handler_.get_last_hex()) && play_controller_.current_team().is_local();
253 
255  res = !is_observer();
256  break;
259  const terrain_label *label = gui()->labels().get_label(mouse_handler_.get_last_hex());
260  res = !events::commands_disabled && play_controller_.get_map().on_board(mouse_handler_.get_last_hex())
261  && !gui()->shrouded(mouse_handler_.get_last_hex())
262  && !is_observer()
263  && (!label || !label->immutable());
264  break;
265  }
267  if(browse() || events::commands_disabled)
268  return false;
269 
271  && (menu_handler_.current_unit()->move_interrupted()))
272  return true;
273  const unit_map::const_iterator i = play_controller_.get_units().find(mouse_handler_.get_selected_hex());
274  if (!i.valid()) return false;
275  return i->move_interrupted();
276  }
278  return !is_observer();
281  return whiteboard_manager_->can_enable_execution_hotkeys() && !events::commands_disabled && !browse();
283  return whiteboard_manager_->can_enable_modifier_hotkeys();
286  return whiteboard_manager_->can_enable_reorder_hotkeys();
288  {
289  //@todo re-enable this once we figure out a decent UI for suppose_dead
290  //@todo when re-enabling this, change 'true' to 'false' in master_hotkey_list for this hotkey
291  return false;
292  }
293 
304  return playsingle_controller_.get_replay_controller() && playsingle_controller_.get_replay_controller()->can_execute_command(cmd);
306  return playsingle_controller_.is_replay() && (!playsingle_controller_.is_networked_mp() || resources::recorder->at_end());
307  default:
309  }
310  return res;
311 }
312 
313 void playsingle_controller::hotkey_handler::load_autosave(const std::string& filename, bool start_replay)
314 {
315  if(!start_replay) {
317  }
318  auto invalid_save_file = [this, filename](std::string msg){
319  if(playsingle_controller_.is_networked_mp()) {
321  } else {
322  const int res = gui2::show_message("", msg + _("Do you want to load it anyway?"), gui2::dialogs::message::yes_no_buttons);
323  if(res != gui2::retval::CANCEL) {
325  }
326  }
327  };
328 
330  std::string error_log;
332 
333  if(!error_log.empty()) {
334  invalid_save_file(_("The file you have tried to load is corrupt: '") + error_log);
335  return;
336  }
337  if(savegame.child_or_empty("snapshot")["replay_pos"].to_int(-1) < 0 ) {
338  invalid_save_file(_("The file you have tried to load has no replay information. "));
339  return;
340  }
341  if(!playsingle_controller_.get_saved_game().get_replay().is_ancestor(savegame.child_or_empty("replay"))) {
342  invalid_save_file(_("The file you have tried to load is not from the current session."));
343  return;
344  }
345 
346  auto res = std::make_shared<config>(savegame.child_or_empty("snapshot"));
347  auto stats = std::make_shared<config>(savegame.child_or_empty("statistics"));
348  throw reset_gamestate_exception(res, stats, false);
349 }
350 
352 {
353  if(!playsingle_controller_.is_networked_mp()) {
355  }
356  playsingle_controller_.set_player_type_changed();
357 }
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:161
void label_terrain(mouse_handler &mousehandler, bool team_only)
void update_shroud_now(int side_num)
virtual void clear_messages() override
void recall(int side_num, const map_location &last_hex)
void create_unit(mouse_handler &mousehandler)
Creates a unit (in debug mode via hotkey or context menu).
void unit_hold_position(mouse_handler &mousehandler, int side_num)
void end_unit_turn(mouse_handler &mousehandler, int side_num)
void change_side(mouse_handler &mousehandler)
void toggle_shroud_updates(int side_num)
void recruit(int side_num, const map_location &last_hex)
void continue_move(mouse_handler &mousehandler, int side_num)
void repeat_recruit(int side_num, const map_location &last_hex)
void kill_unit(mouse_handler &mousehandler)
unit_map::iterator current_unit()
map_location get_selected_hex() const
const map_location & get_last_hex() const
std::shared_ptr< wml_menu_item > item_ptr
wml_menu_item pointers
Definition: wmi_manager.hpp:44
item_ptr get_item(const std::string &id) const
Gets the menu item with the specified ID.
game_events::wmi_manager & get_wml_menu_items()
Definition: game_state.cpp:383
@ yes_no_buttons
Shows a yes and no button.
Definition: message.hpp:81
virtual void load_autosave(const std::string &filename, bool start_replay=false)
virtual hotkey::ACTION_STATE get_action_state(const hotkey::ui_command &) const override
virtual bool can_execute_command(const hotkey::ui_command &command) const override
Check if a command can be executed.
events::menu_handler menu_handler_
bool is_observer() const
game_state & gamestate()
events::mouse_handler mouse_handler_
std::shared_ptr< wb::manager > whiteboard_manager_
virtual void toggle_shroud_updates() override
virtual void whiteboard_suppose_dead() override
hotkey_handler(playsingle_controller &, saved_game &)
virtual bool can_execute_command(const hotkey::ui_command &cmd) const override
Check if a command can be executed.
virtual void whiteboard_delete_action() override
virtual void whiteboard_execute_action() override
virtual void label_terrain(bool) override
virtual void load_autosave(const std::string &filename, bool start_replay=false) override
virtual void whiteboard_bump_up_action() override
virtual hotkey::ACTION_STATE get_action_state(const hotkey::ui_command &) const override
virtual void whiteboard_bump_down_action() override
virtual void whiteboard_execute_all_actions() override
bool at_end() const
Definition: replay.cpp:633
void delete_upcoming_commands()
Definition: replay.cpp:188
To store label data Class implements logic for rendering.
Definition: label.hpp:111
This class represents a single unit of a specific type.
Definition: unit.hpp:135
Declarations for File-IO.
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
std::size_t i
Definition: function.cpp:968
static std::string _(const char *str)
Definition: gettext.hpp:93
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1359
std::string label
What to show in the filter's drop-down list.
Definition: manager.cpp:217
An extension of play_controller::hotkey_handler, which has support for SP wesnoth features like white...
Declarations for a class that implements WML-defined (right-click) menu items.
std::string get_saves_dir()
const color_t NORMAL_COLOR
const bool & debug
Definition: game_config.cpp:91
void show_error_message(const std::string &msg, bool message_use_markup)
Shows an error message to the user.
Definition: message.cpp:204
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:151
@ CANCEL
Dialog was closed with the CANCEL button.
Definition: retval.hpp:38
General purpose widgets.
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:414
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
@ HOTKEY_END_UNIT_TURN
@ HOTKEY_WB_EXECUTE_ALL_ACTIONS
@ HOTKEY_WB_SUPPOSE_DEAD
@ HOTKEY_REPLAY_PLAY
@ HOTKEY_SAVE_GAME
@ HOTKEY_UPDATE_SHROUD
@ HOTKEY_REPEAT_RECRUIT
@ HOTKEY_REPLAY_STOP
@ HOTKEY_KILL_UNIT
@ HOTKEY_LABEL_TEAM_TERRAIN
@ HOTKEY_UNIT_HOLD_POSITION
@ HOTKEY_REPLAY_NEXT_TURN
@ HOTKEY_REPLAY_SHOW_EVERYTHING
@ HOTKEY_REPLAY_SHOW_TEAM1
@ HOTKEY_LABEL_TERRAIN
@ HOTKEY_CLEAR_LABELS
@ HOTKEY_CONTINUE_MOVE
@ HOTKEY_WB_EXECUTE_ACTION
@ HOTKEY_CHANGE_SIDE
@ HOTKEY_DELAY_SHROUD
@ HOTKEY_WB_BUMP_UP_ACTION
@ HOTKEY_CREATE_UNIT
@ HOTKEY_REPLAY_EXIT
@ HOTKEY_REPLAY_NEXT_SIDE
@ HOTKEY_REPLAY_NEXT_MOVE
@ HOTKEY_REPLAY_RESET
@ HOTKEY_WB_TOGGLE
@ HOTKEY_REPLAY_SKIP_ANIMATION
@ HOTKEY_WB_BUMP_DOWN_ACTION
@ HOTKEY_REPLAY_SHOW_EACH
@ HOTKEY_WB_DELETE_ACTION
replay * recorder
Definition: resources.cpp:29
void read_save_file(const std::string &dir, const std::string &name, config &cfg, std::string *error_log)
Read the complete config information out of a savefile.
Definition: save_index.cpp:314
std::map< std::string, t_string > string_map
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
Replay control code.
static const hotkey_command & get_command_by_command(HOTKEY_COMMAND command)
the execute_command argument was changed from HOTKEY_COMMAND to hotkey_command, to be able to call it...
Used as the main paramneter for can_execute_command/do_execute_command These functions are used to ex...
hotkey::HOTKEY_COMMAND hotkey_command
The hotkey::HOTKEY_COMMAND associated with this action, HOTKEY_NULL for actions that don't allow hotk...
std::string id
The string command, never empty, describes the action uniquely. when the action is the result of a me...
Encapsulates the map of the game.
Definition: location.hpp:38
bool valid() const
Definition: map.hpp:274
Applies the planned unit map for the duration of the struct's life.
Definition: manager.hpp:253
Declarations for a container for wml_menu_item.