The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
manager.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2016 by Gabriel Morin <gabrielmorin (at) gmail (dot) com>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13  */
14 
15 /**
16  * @file
17  */
18 
19 #include "manager.hpp"
20 
21 #include "action.hpp"
22 #include "highlighter.hpp"
23 #include "mapbuilder.hpp"
24 #include "move.hpp"
25 #include "attack.hpp"
26 #include "recall.hpp"
27 #include "recruit.hpp"
28 #include "side_actions.hpp"
29 #include "utility.hpp"
30 
31 #include "actions/create.hpp"
32 #include "actions/undo.hpp"
33 #include "arrow.hpp"
34 #include "chat_events.hpp"
35 #include "fake_unit_manager.hpp"
36 #include "fake_unit_ptr.hpp"
37 #include "formula/string_utils.hpp"
38 #include "game_board.hpp"
39 #include "game_preferences.hpp"
40 #include "game_state.hpp"
41 #include "gettext.hpp"
43 #include "key.hpp"
44 #include "pathfind/pathfind.hpp"
45 #include "play_controller.hpp"
46 #include "resources.hpp"
47 #include "team.hpp"
48 #include "units/unit.hpp"
50 #include "units/udisplay.hpp"
51 
52 #include <boost/lexical_cast.hpp>
53 #include "utils/functional.hpp"
54 
55 #include <sstream>
56 
57 namespace wb {
58 
60  active_(false),
61  inverted_behavior_(false),
62  self_activate_once_(true),
63 #if 0
64  print_help_once_(true),
65 #endif
66  wait_for_side_init_(true),
67  planned_unit_map_active_(false),
68  executing_actions_(false),
69  executing_all_actions_(false),
70  preparing_to_end_turn_(false),
71  gamestate_mutated_(false),
72  activation_state_lock_(new bool),
73  unit_map_lock_(new bool),
74  mapbuilder_(),
75  highlighter_(),
76  route_(),
77  move_arrows_(),
78  fake_units_(),
79  temp_move_unit_underlying_id_(0),
80  key_poller_(new CKey),
81  hidden_unit_hexes_(),
82  net_buffer_(resources::teams->size()),
83  team_plans_hidden_(resources::teams->size(),preferences::hide_whiteboard()),
84  units_owning_moves_()
85 {
86  LOG_WB << "Manager initialized.\n";
87 }
88 
90 {
91  LOG_WB << "Manager destroyed.\n";
92 }
93 
94 //Used for chat-spamming debug info
95 #if 0
96 static void print_to_chat(const std::string& title, const std::string& message)
97 {
98  resources::screen->add_chat_message(time(nullptr), title, 0, message,
100 }
101 #endif
102 
104 {
105 #if 0
106  if (!print_help_once_)
107  return;
108  else
109  print_help_once_ = false;
110 
111  print_to_chat("whiteboard", std::string("Type :wb to activate/deactivate planning mode.")
112  + " Hold TAB to temporarily deactivate/activate it.");
113  std::stringstream hotkeys;
114  const hotkey::hotkey_item& hk_execute = hotkey::get_hotkey(hotkey::HOTKEY_WB_EXECUTE_ACTION);
115  if(!hk_execute.null()) {
116  //print_to_chat("[execute action]", "'" + hk_execute.get_name() + "'");
117  hotkeys << "Execute: " << hk_execute.get_name() << ", ";
118  }
119  const hotkey::hotkey_item& hk_execute_all = hotkey::get_hotkey(hotkey::HOTKEY_WB_EXECUTE_ALL_ACTIONS);
120  if(!hk_execute_all.null()) {
121  //print_to_chat("[execute action]", "'" + hk_execute_all.get_name() + "'");
122  hotkeys << "Execute all: " << hk_execute_all.get_name() << ", ";
123  }
124  const hotkey::hotkey_item& hk_delete = hotkey::get_hotkey(hotkey::HOTKEY_WB_DELETE_ACTION);
125  if(!hk_delete.null()) {
126  //print_to_chat("[delete action]", "'" + hk_delete.get_name() + "'");
127  hotkeys << "Delete: " << hk_delete.get_name() << ", ";
128  }
129  const hotkey::hotkey_item& hk_bump_up = hotkey::get_hotkey(hotkey::HOTKEY_WB_BUMP_UP_ACTION);
130  if(!hk_bump_up.null()) {
131  //print_to_chat("[move action earlier in queue]", "'" + hk_bump_up.get_name() + "'");
132  hotkeys << "Move earlier: " << hk_bump_up.get_name() << ", ";
133  }
134  const hotkey::hotkey_item& hk_bump_down = hotkey::get_hotkey(hotkey::HOTKEY_WB_BUMP_DOWN_ACTION);
135  if(!hk_bump_down.null()) {
136  //print_to_chat("[move action later in queue]", "'" + hk_bump_down.get_name() + "'");
137  hotkeys << "Move later: " << hk_bump_down.get_name() << ", ";
138  }
139  print_to_chat("HOTKEYS:", hotkeys.str() + "\n");
140 #endif
141 }
142 
144 {
146  || resources::teams == nullptr
148  || resources::gameboard->is_observer()
149  || resources::controller->is_linger_mode())
150  {
151  return false;
152  }
153  else
154  {
155  return true;
156  }
157 }
158 
160 {
161  //any more than one reference means a lock on whiteboard state was requested
162  if(!activation_state_lock_.unique())
163  return false;
164 
165  return can_modify_game_state();
166 }
167 
168 void manager::set_active(bool active)
169 {
170  if(!can_activate())
171  {
172  active_ = false;
173  LOG_WB << "Whiteboard can't be activated now.\n";
174  }
175  else if (active != active_)
176  {
177  active_ = active;
178  erase_temp_move();
179 
180  if (active_)
181  {
182  if(should_clear_undo())
185  LOG_WB << "Whiteboard activated! " << *viewer_actions() << "\n";
187  } else {
188  LOG_WB << "Whiteboard deactivated!\n";
189  }
190  }
191 }
192 
194 {
195  //any more than one reference means a lock on whiteboard state was requested
196  if(!activation_state_lock_.unique())
197  return;
198 
199  bool block_whiteboard_activation = false;
200  if(!can_activate())
201  {
202  block_whiteboard_activation = true;
203  }
204 
205  if (invert)
206  {
207  if (!inverted_behavior_)
208  {
209  if (active_)
210  {
211  DBG_WB << "Whiteboard deactivated temporarily.\n";
212  inverted_behavior_ = true;
213  set_active(false);
214  }
215  else if (!block_whiteboard_activation)
216  {
217  DBG_WB << "Whiteboard activated temporarily.\n";
218  inverted_behavior_ = true;
219  set_active(true);
220  }
221  }
222  }
223  else
224  {
225  if (inverted_behavior_)
226  {
227  if (active_)
228  {
229  DBG_WB << "Whiteboard set back to deactivated status.\n";
230  inverted_behavior_ = false;
231  set_active(false);
232  }
233  else if (!block_whiteboard_activation)
234  {
235  DBG_WB << "Whiteboard set back to activated status.\n";
236  inverted_behavior_ = false;
237  set_active(true);
238  }
239  }
240  }
241 }
242 
244 {
246  && viewer_actions()->turn_size(0) > 0;
247 }
248 
250 {
251  return can_modify_game_state() && !viewer_actions()->empty();
252 }
253 
255 {
256  return can_enable_modifier_hotkeys() && highlighter_ && highlighter_->get_bump_target();
257 }
258 
259 bool manager::allow_leader_to_move(unit const& leader) const
260 {
261  if(!has_actions())
262  return true;
263 
264  //Look for another leader on another keep in the same castle
265  { wb::future_map future; // start planned unit map scope
266  if(!has_planned_unit_map()) {
267  WRN_WB << "Unable to build future map to determine whether leader's allowed to move." << std::endl;
268  }
269  if(find_backup_leader(leader))
270  return true;
271  } // end planned unit map scope
272 
273  if(viewer_actions()->empty()) {
274  return true;
275  }
276 
277  //Look for planned recruits that depend on this leader
279  {
280  recruit_const_ptr recruit = boost::dynamic_pointer_cast<class recruit const>(action);
281  recall_const_ptr recall = boost::dynamic_pointer_cast<class recall const>(action);
282  if(recruit || recall)
283  {
284  map_location const target_hex = recruit?recruit->get_recruit_hex():recall->get_recall_hex();
285  if ( dynamic_cast<game_state*>(resources::filter_con)->can_recruit_on(leader, target_hex) )
286  return false;
287  }
288  }
289  return true;
290 }
291 
293 {
294  //Turn should never start with action auto-execution already enabled!
296 
297  update_plan_hiding(); /* validates actions */
298  wait_for_side_init_ = false;
299  LOG_WB << "on_init_side()\n";
300 
302  {
303  self_activate_once_ = false;
304  set_active(true);
305  }
306 }
307 
309 {
310  preparing_to_end_turn_ = false;
311  wait_for_side_init_ = true;
312  if(side == viewer_side() && !viewer_actions()->empty()) {
313  viewer_actions()->synced_turn_shift();
314  }
315  highlighter_.reset();
316  erase_temp_move();
317  LOG_WB << "on_finish_side_turn()\n";
318 }
319 
321 {
322 }
323 
325 {
326  // The fake unit representing the destination of a chain of planned moves should have the regular animation.
327  // If the last remaining action of the unit that owned this move is a move as well,
328  // adjust its appearance accordingly.
329 
330  side_actions_ptr side_actions = resources::teams->at(action->team_index()).get_side_actions();
331 
332  unit_ptr actor = action->get_unit();
333  if(actor) { // The unit might have died following the execution of an attack
334  side_actions::iterator action_it = side_actions->find_last_action_of(*actor);
335  if(action_it != side_actions->end()) {
336  move_ptr move = boost::dynamic_pointer_cast<class move>(*action_it);
337  if(move && move->get_fake_unit()) {
338  move->get_fake_unit()->anim_comp().set_standing(true);
339  }
340  }
341  }
342 }
343 
344 static void hide_all_plans()
345 {
346  for(team& t : *resources::teams){
347  t.get_side_actions()->hide();
348  }
349 }
350 
351 /* private */
352 void manager::update_plan_hiding(size_t team_index)
353 {
354  //We don't control the "viewing" side ... we're probably an observer
355  if(!resources::teams->at(team_index).is_local_human())
356  hide_all_plans();
357  else // normal circumstance
358  {
359  for(team& t : *resources::teams)
360  {
361  //make sure only appropriate teams are hidden
362  if(!t.is_network_human())
363  team_plans_hidden_[t.side()-1] = false;
364 
365  if(t.is_enemy(team_index+1) || team_plans_hidden_[t.side()-1])
366  t.get_side_actions()->hide();
367  else
368  t.get_side_actions()->show();
369  }
370  }
372 }
375 
376 void manager::on_viewer_change(size_t team_index)
377 {
379  update_plan_hiding(team_index);
380 }
381 
382 void manager::on_change_controller(int side, const team& t)
383 {
385  if(t.is_local_human()) // we own this side now
386  {
387  //tell everyone to clear this side's actions -- we're starting anew
388  resources::whiteboard->queue_net_cmd(sa.team_index(),sa.make_net_cmd_clear());
389  sa.clear();
390  //refresh the hidden_ attribute of every team's side_actions
392  }
393  else if(t.is_local_ai() || t.is_network_ai()) // no one owns this side anymore
394  sa.clear(); // clear its plans away -- the ai doesn't plan ... yet
395  else if(t.is_network()) // Another client is taking control of the side
396  {
397  if(side==viewer_side()) // They're taking OUR side away!
398  hide_all_plans(); // give up knowledge of everyone's plans, in case we became an observer
399 
400  //tell them our plans -- they may not have received them up to this point
401  size_t num_teams = resources::teams->size();
402  for(size_t i=0; i<num_teams; ++i)
403  {
404  team& local_team = resources::teams->at(i);
405  if(local_team.is_local_human() && !local_team.is_enemy(side))
406  resources::whiteboard->queue_net_cmd(i,local_team.get_side_actions()->make_net_cmd_refresh());
407  }
408  }
409 }
410 
412 {
413  if(current_side_actions()->empty()) {
414  return false;
415  }
416 
418  return range.first != range.second; //non-empty range
419 }
420 
422 {
423  LOG_WB << "'gamestate_mutated_' flag dirty, validating actions.\n";
424  gamestate_mutated_ = false;
425  if(has_planned_unit_map()) {
426  real_map();
427  } else {
428  future_map();
429  }
430 }
431 
432 //helper fcn
433 static void draw_numbers(map_location const& hex, side_actions::numbers_t numbers)
434 {
435  std::vector<int>& numbers_to_draw = numbers.numbers_to_draw;
436  std::vector<size_t>& team_numbers = numbers.team_numbers;
437  int& main_number = numbers.main_number;
438  std::set<size_t>& secondary_numbers = numbers.secondary_numbers;
439 
440  const double x_offset_base = 0.0;
441  const double y_offset_base = 0.2;
442  //position 0,0 in the hex is the upper left corner
443  //0.8 = horizontal coord., close to the right side of the hex
444  const double x_origin = 0.8 - numbers_to_draw.size() * x_offset_base;
445  //0.5 = halfway in the hex vertically
446  const double y_origin = 0.5 - numbers_to_draw.size() * (y_offset_base / 2);
447  double x_offset = 0, y_offset = 0;
448 
449  size_t size = numbers_to_draw.size();
450  for(size_t i=0; i<size; ++i)
451  {
452  int number = numbers_to_draw[i];
453 
454  std::string number_text = std::to_string(number);
455  size_t font_size;
456  if (int(i) == main_number) font_size = 19;
457  else if (secondary_numbers.find(i)!=secondary_numbers.end()) font_size = 17;
458  else font_size = 15;
459 
460  SDL_Color color = team::get_side_color(static_cast<int>(team_numbers[i]+1));
461  const double x_in_hex = x_origin + x_offset;
462  const double y_in_hex = y_origin + y_offset;
464  number_text, font_size, color, x_in_hex, y_in_hex);
465  x_offset += x_offset_base;
466  y_offset += y_offset_base;
467  }
468 }
469 
470 
471 namespace
472 {
473  //Helper struct that finds all units teams whose planned actions are currently visible
474  //Only used by manager::pre_draw().
475  //Note that this structure is used as a functor.
476  struct move_owners_finder: public visitor
477  {
478 
479  public:
480  move_owners_finder(): move_owners_() { }
481 
482  void operator()(action* action) {
483  action->accept(*this);
484  }
485 
486  std::set<size_t> const& get_units_owning_moves() {
487  return move_owners_;
488  }
489 
490  virtual void visit(move_ptr move) {
491  if(size_t id = move->get_unit_id()) {
492  move_owners_.insert(id);
493  }
494  }
495 
496  virtual void visit(attack_ptr attack) {
497  //also add attacks if they have an associated move
498  if(attack->get_route().steps.size() >= 2) {
499  if(size_t id = attack->get_unit_id()) {
500  move_owners_.insert(id);
501  }
502  }
503  }
504  virtual void visit(recruit_ptr){}
505  virtual void visit(recall_ptr){}
506  virtual void visit(suppose_dead_ptr){}
507 
508  private:
509  std::set<size_t> move_owners_;
510  };
511 }
512 
514 {
515  if (can_modify_game_state() && has_actions() && unit_map_lock_.unique()) {
516  move_owners_finder move_finder;
517  for_each_action(std::ref(move_finder));
518  units_owning_moves_ = move_finder.get_units_owning_moves();
519 
520  for (size_t unit_id : units_owning_moves_) {
521  unit_map::iterator unit_iter = resources::units->find(unit_id);
522  assert(unit_iter.valid());
523  ghost_owner_unit(&*unit_iter);
524  }
525  }
526 }
527 
529 {
530  for (size_t unit_id : units_owning_moves_)
531  {
532  unit_map::iterator unit_iter = resources::units->find(unit_id);
533  if (unit_iter.valid()) {
534  unghost_owner_unit(&*unit_iter);
535  }
536  }
537  units_owning_moves_.clear();
538 }
539 
541 {
542  /**
543  * IMPORTANT: none of the code in this method can call anything which would
544  * cause a hex to be invalidated (i.e. by calling in turn any variant of display::invalidate()).
545  * Doing so messes up the iterator currently going over the list of invalidated hexes to draw.
546  */
547 
549  {
550  //call draw() for all actions
551  for_each_action(std::bind(&action::draw_hex, std::placeholders::_1, hex));
552 
553  //Info about the action numbers to be displayed on screen.
554  side_actions::numbers_t numbers;
555  for (team& t : *resources::teams)
556  {
557  side_actions& sa = *t.get_side_actions();
558  if(!sa.hidden())
559  sa.get_numbers(hex,numbers);
560  }
561  draw_numbers(hex,numbers); // helper fcn
562  }
563 
564 }
565 
567 {
568 
570  bool hex_has_unit;
571  { wb::future_map future; // start planned unit map scope
572  hex_has_unit = resources::units->find(selected_hex) != resources::units->end();
573  } // end planned unit map scope
574  if (!((selected_hex.valid() && hex_has_unit)
576  {
577  if (!highlighter_)
578  {
580  }
581  highlighter_->set_mouseover_hex(hex);
582  highlighter_->highlight();
583  }
584 }
585 
587 {
588  DBG_WB << "Manager received gamestate change notification.\n";
589  // if on_gamestate_change() is called while the future unit map is applied,
590  // it means that the future unit map scope is used where it shouldn't be.
591  assert(!planned_unit_map_active_);
592  // Set mutated flag so action queue gets validated on next future map build
593  gamestate_mutated_ = true;
594  //Clear exclusive draws that might not get a chance to be cleared the normal way
596 }
597 
599 {
600  size_t size = net_buffer_.size();
601  for(size_t team_index=0; team_index<size; ++team_index)
602  {
603  config& buf_cfg = net_buffer_[team_index];
604 
605  if(buf_cfg.empty())
606  continue;
607 
608  config packet;
609  config& wb_cfg = packet.add_child("whiteboard",buf_cfg);
610  wb_cfg["side"] = static_cast<int>(team_index+1);
611  wb_cfg["to_sides"] = resources::teams->at(team_index).allied_human_teams();
612 
613  buf_cfg = config();
614 
615  resources::controller->send_to_wesnothd(packet, "whiteboard");
616 
617  size_t count = wb_cfg.child_count("net_cmd");
618  LOG_WB << "Side " << (team_index+1) << " sent wb data (" << count << " cmds).\n";
619  }
620 }
621 
623 {
624  if(config const& wb_cfg = cfg.child("whiteboard"))
625  {
626  size_t count = wb_cfg.child_count("net_cmd");
627  LOG_WB << "Received wb data (" << count << ").\n";
628 
629  team& team_from = resources::teams->at(wb_cfg["side"]-1);
630  for(side_actions::net_cmd const& cmd : wb_cfg.child_range("net_cmd"))
631  team_from.get_side_actions()->execute_net_cmd(cmd);
632  }
633 }
634 
635 void manager::queue_net_cmd(size_t team_index, side_actions::net_cmd const& cmd)
636 {
637  assert(team_index < net_buffer_.size());
638  net_buffer_[team_index].add_child("net_cmd",cmd);
639 }
640 
642 {
643  route_.reset();
644 
645  /*
646  * CHECK PRE-CONDITIONS
647  * (This section has multiple return paths.)
648  */
649 
650  if ( !active_ || !can_modify_game_state() )
651  return;
652 
653  pathfind::marked_route const& route =
655 
656  if (route.steps.empty() || route.steps.size() < 2) return;
657 
658  unit* temp_moved_unit =
659  future_visible_unit(resources::controller->get_mouse_handler_base().get_selected_hex(), viewer_side());
660  if (!temp_moved_unit) temp_moved_unit =
661  future_visible_unit(resources::controller->get_mouse_handler_base().get_last_hex(), viewer_side());
662  if (!temp_moved_unit) return;
663  if (temp_moved_unit->side() != resources::screen->viewing_side()) return;
664 
665  /*
666  * DONE CHECKING PRE-CONDITIONS, CREATE THE TEMP MOVE
667  * (This section has only one return path.)
668  */
669 
670  temp_move_unit_underlying_id_ = temp_moved_unit->underlying_id();
671 
672  //@todo: May be appropriate to replace these separate components by a temporary
673  // wb::move object
674 
675  route_.reset(new pathfind::marked_route(route));
676  //NOTE: route_->steps.back() = dst, and route_->steps.front() = src
677 
678  size_t turn = 0;
679  std::vector<map_location>::iterator prev_itor = route.steps.begin();
680  std::vector<map_location>::iterator curr_itor = prev_itor;
681  std::vector<map_location>::iterator end_itor = route.steps.end();
682  for(; curr_itor!=end_itor; ++curr_itor)
683  {
684  const map_location& hex = *curr_itor;
685 
686  //search for end-of-turn marks
687  pathfind::marked_route::mark_map::const_iterator w =
688  route.marks.find(hex);
689  if(w != route.marks.end() && w->second.turns > 0)
690  {
691  turn = w->second.turns-1;
692 
693  if(turn >= move_arrows_.size())
694  move_arrows_.resize(turn+1);
695  if(turn >= fake_units_.size())
696  fake_units_.resize(turn+1);
697 
698  arrow_ptr& move_arrow = move_arrows_[turn];
699  fake_unit_ptr& fake_unit = fake_units_[turn];
700 
701  if(!move_arrow)
702  {
703  // Create temp arrow
704  move_arrow.reset(new arrow());
705  move_arrow->set_color(team::get_side_color_index(
706  viewer_side()));
707  move_arrow->set_style(arrow::STYLE_HIGHLIGHTED);
708  }
709 
710  arrow_path_t path(prev_itor,curr_itor+1);
711  move_arrow->set_path(path);
712 
713  if(path.size() >= 2)
714  {
715  // Bug #20299 demonstrates a situation where an incorrect fake/ghosted unit can be used.
716  // So before assuming that a pre-existing fake_unit can be re-used, check that its ID matches the unit being moved.
717  if(!fake_unit || fake_unit.get_unit_ptr()->id() != temp_moved_unit->id())
718  {
719  // Create temp ghost unit
720  fake_unit = fake_unit_ptr(unit_ptr (new unit(*temp_moved_unit)), resources::fake_units);
721  fake_unit->anim_comp().set_ghosted(true);
722  }
723 
724  unit_display::move_unit(path, fake_unit.get_unit_ptr(), false); //get facing right
725  fake_unit->anim_comp().invalidate(*game_display::get_singleton());
726  fake_unit->set_location(*curr_itor);
727  fake_unit->anim_comp().set_ghosted(true);
728  }
729  else //zero-hex path -- don't bother drawing a fake unit
730  fake_unit.reset();
731 
732  prev_itor = curr_itor;
733  }
734  }
735  //in case path shortens on next step and one ghosted unit has to be removed
736  int ind = fake_units_.size() - 1;
737  fake_units_[ind]->anim_comp().invalidate(*game_display::get_singleton());
738  //toss out old arrows and fake units
739  move_arrows_.resize(turn+1);
740  fake_units_.resize(turn+1);
741 }
742 
744 {
745  move_arrows_.clear();
746  for(fake_unit_ptr const& tmp : fake_units_) {
747  if(tmp) {
748  tmp->anim_comp().invalidate(*game_display::get_singleton());
749  }
750  }
751  fake_units_.clear();
752  route_.reset();
754 }
755 
757 {
758  if (has_temp_move() && !executing_actions_ && !resources::controller->is_linger_mode())
759  {
760  side_actions& sa = *viewer_actions();
761  unit* u = future_visible_unit(route_->steps.front());
762  assert(u);
763  size_t first_turn = sa.get_turn_num_of(*u);
764 
766 
767  assert(move_arrows_.size() == fake_units_.size());
768  size_t size = move_arrows_.size();
769  for(size_t i=0; i<size; ++i)
770  {
771  arrow_ptr move_arrow = move_arrows_[i];
772  if(!arrow::valid_path(move_arrow->get_path()))
773  continue;
774 
775  size_t turn = first_turn + i;
776  fake_unit_ptr fake_unit = fake_units_[i];
777 
778  //@todo Using a marked_route here is wrong, since right now it's not marked
779  //either switch over to a plain route for planned moves, or mark it correctly
781  route.steps = move_arrow->get_path();
782  route.move_cost = path_cost(route.steps,*u);
783 
784  sa.queue_move(turn,*u,route,move_arrow,fake_unit);
785  }
786  erase_temp_move();
787 
788  LOG_WB << *viewer_actions() << "\n";
789  print_help_once();
790  }
791 }
792 
794 {
796 }
797 
798 void manager::save_temp_attack(const map_location& attacker_loc, const map_location& defender_loc, int weapon_choice)
799 {
800  if (active_ && !executing_actions_ && !resources::controller->is_linger_mode())
801  {
802  assert(weapon_choice >= 0);
803 
804  arrow_ptr move_arrow;
805  fake_unit_ptr fake_unit;
806  map_location source_hex;
807 
808  if (route_ && !route_->steps.empty())
809  {
810  //attack-move
811  assert(move_arrows_.size() == 1);
812  assert(fake_units_.size() == 1);
813  move_arrow = move_arrows_.front();
814  fake_unit = fake_units_.front();
815 
816  assert(route_->steps.back() == attacker_loc);
817  source_hex = route_->steps.front();
818 
819  fake_unit->anim_comp().set_disabled_ghosted(true);
820  }
821  else
822  {
823  //simple attack
824  move_arrow.reset(new arrow);
825  source_hex = attacker_loc;
826  route_.reset(new pathfind::marked_route);
827  // We'll pass as parameter a one-hex route with no marks.
828  route_->steps.push_back(attacker_loc);
829  }
830 
831  unit* attacking_unit = future_visible_unit(source_hex);
832  assert(attacking_unit);
833 
835 
836  side_actions& sa = *viewer_actions();
837  sa.queue_attack(sa.get_turn_num_of(*attacking_unit),*attacking_unit,defender_loc,weapon_choice,*route_,move_arrow,fake_unit);
838 
839  print_help_once();
840 
841  resources::screen->invalidate(defender_loc);
842  resources::screen->invalidate(attacker_loc);
843  erase_temp_move();
844  LOG_WB << *viewer_actions() << "\n";
845  }
846 }
847 
848 bool manager::save_recruit(const std::string& name, int side_num, const map_location& recruit_hex)
849 {
850  bool created_planned_recruit = false;
851 
852  if (active_ && !executing_actions_ && !resources::controller->is_linger_mode()) {
853  if (side_num != resources::screen->viewing_side())
854  {
855  LOG_WB <<"manager::save_recruit called for a different side than viewing side.\n";
856  created_planned_recruit = false;
857  }
858  else
859  {
860  side_actions& sa = *viewer_actions();
861  unit* recruiter;
862  { wb::future_map raii;
863  recruiter = find_recruiter(side_num-1,recruit_hex);
864  } // end planned unit map scope
865  assert(recruiter);
866  size_t turn = sa.get_turn_num_of(*recruiter);
867  sa.queue_recruit(turn,name,recruit_hex);
868  created_planned_recruit = true;
869 
870  print_help_once();
871  }
872  }
873  return created_planned_recruit;
874 }
875 
876 bool manager::save_recall(const unit& unit, int side_num, const map_location& recall_hex)
877 {
878  bool created_planned_recall = false;
879 
880  if (active_ && !executing_actions_ && !resources::controller->is_linger_mode())
881  {
882  if (side_num != resources::screen->viewing_side())
883  {
884  LOG_WB <<"manager::save_recall called for a different side than viewing side.\n";
885  created_planned_recall = false;
886  }
887  else
888  {
889  side_actions& sa = *viewer_actions();
890  size_t turn = sa.num_turns();
891  if(turn > 0)
892  --turn;
893  sa.queue_recall(turn,unit,recall_hex);
894  created_planned_recall = true;
895 
896  print_help_once();
897  }
898  }
899  return created_planned_recall;
900 }
901 
902 void manager::save_suppose_dead(unit& curr_unit, map_location const& loc)
903 {
904  if(active_ && !executing_actions_ && !resources::controller->is_linger_mode())
905  {
907  side_actions& sa = *viewer_actions();
908  sa.queue_suppose_dead(sa.get_turn_num_of(curr_unit),curr_unit,loc);
909  }
910 }
911 
913 {
916  {
917  erase_temp_move();
918 
919  //For exception-safety, this struct sets executing_actions_ to false on destruction.
921 
922  action_ptr action;
924  unit const* selected_unit = future_visible_unit(resources::controller->get_mouse_handler_base().get_selected_hex(), viewer_side());
925  if (selected_unit &&
926  (it = viewer_actions()->find_first_action_of(*selected_unit)) != viewer_actions()->end())
927  {
928  executing_actions_ = true;
929  viewer_actions()->execute(it);
930  }
931  else if (highlighter_ && (action = highlighter_->get_execute_target()) &&
932  (it = viewer_actions()->get_position_of(action)) != viewer_actions()->end())
933  {
934  executing_actions_ = true;
935  viewer_actions()->execute(it);
936  }
937  else //we already check above for viewer_actions()->empty()
938  {
939  executing_actions_ = true;
940  viewer_actions()->execute_next();
941  }
942  } //Finalizer struct sets executing_actions_ to false
943 }
944 
946 {
947  preparing_to_end_turn_ = true;
948  return execute_all_actions();
949 }
950 
952 {
953  //exception-safety: finalizers set variables to false on destruction
954  //i.e. when method exits naturally or exception is thrown
955  variable_finalizer<bool> finalize_executing_actions(executing_actions_, false);
956  variable_finalizer<bool> finalize_executing_all_actions(executing_all_actions_, false);
957 
959  if(viewer_actions()->empty() || viewer_actions()->turn_size(0) == 0)
960  {
961  //No actions to execute, job done.
962  return true;
963  }
964 
966 
967  erase_temp_move();
968 
969  // Build unit map once to ensure spent gold and other calculations are refreshed
971  assert(has_planned_unit_map());
973 
974  executing_actions_ = true;
975  executing_all_actions_ = true;
976 
978 
980  {
981  ERR_WB << "Modifying action queue while temp modifiers are applied!!!" << std::endl;
982  }
983 
984  //LOG_WB << "Before executing all actions, " << *sa << "\n";
985 
986  while (sa->turn_begin(0) != sa->turn_end(0))
987  {
988  bool action_successful = sa->execute(sa->begin());
989 
990  // Interrupt on incomplete action
991  if (!action_successful)
992  {
993  return false;
994  }
995  }
996  return true;
997 }
998 
1000 {
1003  erase_temp_move();
1004 
1005  action_ptr action;
1006  side_actions::iterator it = viewer_actions()->end();
1007  unit const* selected_unit = future_visible_unit(resources::controller->get_mouse_handler_base().get_selected_hex(), viewer_side());
1008  if(selected_unit && (it = viewer_actions()->find_first_action_of(*selected_unit)) != viewer_actions()->end()) {
1009  ///@todo Shouldn't it be "find_last_action_of" instead of "find_first_action_of" above?
1010  viewer_actions()->remove_action(it);
1011  ///@todo Shouldn't we probably deselect the unit at this point?
1012  } else if(highlighter_ && (action = highlighter_->get_delete_target()) && (it = viewer_actions()->get_position_of(action)) != viewer_actions()->end()) {
1013  viewer_actions()->remove_action(it);
1015  highlighter_->set_mouseover_hex(highlighter_->get_mouseover_hex());
1016  highlighter_->highlight();
1017  } else { //we already check above for viewer_actions()->empty()
1018  it = (viewer_actions()->end() - 1);
1019  action = *it;
1020  viewer_actions()->remove_action(it);
1022  }
1023  }
1024 }
1025 
1027 {
1030  action_ptr action = highlighter_->get_bump_target();
1031  if(action) {
1032  viewer_actions()->bump_earlier(viewer_actions()->get_position_of(action));
1033  validate_viewer_actions(); // Redraw arrows
1034  }
1035  }
1036 }
1037 
1039 {
1042  action_ptr action = highlighter_->get_bump_target();
1043  if(action) {
1044  viewer_actions()->bump_later(viewer_actions()->get_position_of(action));
1045  validate_viewer_actions(); // Redraw arrows
1046  }
1047  }
1048 }
1049 
1051 {
1052  assert(resources::teams);
1053  return wb::has_actions();
1054 }
1055 
1057 {
1058  assert(unit != nullptr);
1059  assert(resources::teams);
1060  return viewer_actions()->unit_has_actions(*unit);
1061 }
1062 
1064 {
1066  return 0;
1067 
1068  return resources::teams->at(side - 1).get_side_actions()->get_gold_spent();
1069 }
1070 
1072 {
1073  int v_side = viewer_side();
1074 
1075  int selection = 0;
1076 
1077  std::vector<team*> allies;
1078  std::vector<std::string> options;
1079  utils::string_map t_vars;
1080 
1081  options.push_back(_("SHOW ALL allies’ plans"));
1082  options.push_back(_("HIDE ALL allies’ plans"));
1083 
1084  //populate list of networked allies
1085  for(team &t : *resources::teams)
1086  {
1087  //Exclude enemies, AIs, and local players
1088  if(t.is_enemy(v_side) || !t.is_network())
1089  continue;
1090 
1091  allies.push_back(&t);
1092 
1093  t_vars["player"] = t.current_player();
1094  size_t t_index = t.side()-1;
1095  if(team_plans_hidden_[t_index])
1096  options.push_back(vgettext("Show plans for $player", t_vars));
1097  else
1098  options.push_back(vgettext("Hide plans for $player", t_vars));
1099  }
1100 
1101  gui2::tsimple_item_selector dlg("", _("Whiteboard Options"), options);
1102  dlg.show(resources::screen->video());
1103  selection = dlg.selected_index();
1104 
1105  if(selection == -1)
1106  return;
1107 
1108  switch(selection)
1109  {
1110  case 0:
1111  for(team* t : allies) {
1112  team_plans_hidden_[t->side()-1]=false;
1113  }
1114  break;
1115  case 1:
1116  for(team* t : allies) {
1117  team_plans_hidden_[t->side()-1]=true;
1118  }
1119  break;
1120  default:
1121  if(selection > 1)
1122  {
1123  size_t t_index = allies[selection-2]->side()-1;
1124  //toggle ...
1125  bool hidden = team_plans_hidden_[t_index];
1126  team_plans_hidden_[t_index] = !hidden;
1127  }
1128  break;
1129  }
1131 }
1132 
1134 {
1135  if (!can_modify_game_state()) {
1136  LOG_WB << "Not building planned unit map: cannot modify game state now.\n";
1137  return;
1138  }
1139  //any more than one reference means a lock on unit map was requested
1140  if(!unit_map_lock_.unique()) {
1141  LOG_WB << "Not building planned unit map: unit map locked.\n";
1142  return;
1143  }
1145  WRN_WB << "Not building planned unit map: already set." << std::endl;
1146  return;
1147  }
1148 
1149  log_scope2("whiteboard", "Building planned unit map");
1151  mapbuilder_->build_map();
1152 
1153  planned_unit_map_active_ = true;
1154 }
1155 
1157 {
1159  {
1160  assert(!executing_actions_);
1161  assert(!wait_for_side_init_);
1162  if(mapbuilder_)
1163  {
1164  log_scope2("whiteboard", "Restoring regular unit map.");
1165  mapbuilder_.reset();
1166  }
1167  planned_unit_map_active_ = false;
1168  }
1169  else
1170  {
1171  LOG_WB << "Not disabling planned unit map: already disabled.\n";
1172  }
1173 }
1174 
1176 {
1177  if (gamestate_mutated_) {
1179  }
1180 }
1181 
1183  initial_planned_unit_map_(resources::whiteboard && resources::whiteboard->has_planned_unit_map())
1184 {
1185  if (!resources::whiteboard)
1186  return;
1188  resources::whiteboard->set_planned_unit_map();
1189  // check if if unit map was successfully applied
1190  if (!resources::whiteboard->has_planned_unit_map()) {
1191  DBG_WB << "Scoped future unit map failed to apply.\n";
1192  }
1193 }
1194 
1196 {
1197  try {
1198  if (!resources::whiteboard)
1199  return;
1200  if (!initial_planned_unit_map_ && resources::whiteboard->has_planned_unit_map())
1201  resources::whiteboard->set_real_unit_map();
1202  } catch (...) {}
1203 }
1204 
1206  initial_planned_unit_map_(resources::whiteboard && resources::whiteboard->has_planned_unit_map()),
1207  whiteboard_active_(resources::whiteboard && resources::whiteboard->is_active())
1208 {
1209  if (!resources::whiteboard)
1210  return;
1211  if (!whiteboard_active_)
1212  return;
1214  resources::whiteboard->set_planned_unit_map();
1215  // check if if unit map was successfully applied
1216  if (!resources::whiteboard->has_planned_unit_map()) {
1217  DBG_WB << "Scoped future unit map failed to apply.\n";
1218  }
1219 }
1220 
1222 {
1223  try {
1224  if (!resources::whiteboard)
1225  return;
1226  if (!initial_planned_unit_map_ && resources::whiteboard->has_planned_unit_map())
1227  resources::whiteboard->set_real_unit_map();
1228  } catch (...) {}
1229 }
1230 
1231 
1233  initial_planned_unit_map_(resources::whiteboard && resources::whiteboard->has_planned_unit_map()),
1234  unit_map_lock_(resources::whiteboard ? resources::whiteboard->unit_map_lock_ : boost::shared_ptr<bool>(new bool(false)))
1235 {
1236  if (!resources::whiteboard)
1237  return;
1239  resources::whiteboard->set_real_unit_map();
1240 }
1241 
1243 {
1244  if (!resources::whiteboard)
1245  return;
1246  assert(!resources::whiteboard->has_planned_unit_map());
1248  {
1249  resources::whiteboard->set_planned_unit_map();
1250  }
1251 }
1252 
1253 } // end namespace wb
void clear()
Clears the stack of undoable (and redoable) actions.
Definition: undo.cpp:226
bool self_activate_once_
Definition: manager.hpp:203
container::iterator iterator
bool initial_planned_unit_map_
Definition: manager.hpp:253
play_controller * controller
Definition: resources.cpp:21
#define WRN_WB
Definition: typedefs.hpp:27
bool is_local_ai() const
Definition: team.hpp:268
bool is_network() const
Definition: team.hpp:262
child_itors child_range(const std::string &key)
Definition: config.cpp:613
void reset()
Reset the internal unit pointer, and deregister from the manager. This fake_unit_ptr is now dissassoc...
int viewer_side()
Definition: utility.cpp:44
events::mouse_handler & get_mouse_handler_base()
Get a reference to a mouse handler member a derived class uses.
const std::string & id() const
Definition: unit.hpp:148
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
boost::shared_ptr< wb::side_actions > get_side_actions() const
get the whiteboard planned actions for this team
Definition: team.hpp:382
Arrows destined to be drawn on the map.
bool can_activate() const
Determine whether the whiteboard can be activated safely.
Definition: manager.cpp:159
void update_plan_hiding()
Definition: manager.cpp:373
unit_iterator end()
Definition: map.hpp:311
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition: display.cpp:3536
bool can_enable_modifier_hotkeys() const
Used to ask the whiteboard if hotkeys affecting the action queue should be available to the user...
Definition: manager.cpp:249
Definition: unit.hpp:95
size_t underlying_id() const
The unique internal ID of the unit.
Definition: unit.hpp:150
boost::shared_ptr< attack > attack_ptr
Definition: typedefs.hpp:78
void on_viewer_change(size_t team_index)
Definition: manager.cpp:376
void process_network_data(config const &)
Called by turn_info::process_network_data() when network data needs to be processed.
Definition: manager.cpp:622
GLenum GLint * range
Definition: glew.h:3025
bool can_enable_reorder_hotkeys() const
Used to ask the whiteboard if its action reordering hotkeys should be available to the user...
Definition: manager.cpp:254
bool initial_planned_unit_map_
Definition: manager.hpp:283
size_t viewer_team()
Definition: utility.cpp:39
internal_ptr get_unit_ptr()
Get a copy of the internal unit pointer.
bool show(CVideo &video, const unsigned auto_close_time=0)
Shows the window.
Definition: dialog.cpp:34
void clear_exclusive_draws()
Cancels all the exclusive draw requests.
Definition: display.hpp:120
std::vector< int > numbers_to_draw
std::vector< arrow_ptr > move_arrows_
Definition: manager.hpp:229
void set_invert_behavior(bool invert)
Called by the key that temporarily toggles the activated state when held.
Definition: manager.cpp:193
game_display * screen
Definition: resources.cpp:27
void contextual_delete()
Deletes last action in the queue for current side.
Definition: manager.cpp:999
whiteboard_lock activation_state_lock_
Reference counted "lock" to allow preventing whiteboard activation state changes. ...
Definition: manager.hpp:219
bool is_enemy(int n) const
Definition: team.hpp:247
unit * find_recruiter(size_t team_index, map_location const &hex)
Definition: utility.cpp:78
void validate_actions_if_needed()
Definition: manager.cpp:1175
bool has_actions()
Return whether the whiteboard has actions.
Definition: utility.cpp:153
const pathfind::marked_route & get_current_route() const
void post_delete_action(action_ptr action)
Handles various cleanup right after removing an action from the queue.
Definition: manager.cpp:324
boost::scoped_ptr< mapbuilder > mapbuilder_
Definition: manager.hpp:224
void save_suppose_dead(unit &curr_unit, map_location const &loc)
Creates a suppose-dead action for the current side.
Definition: manager.cpp:902
int path_cost(std::vector< map_location > const &path, unit const &u)
Computes the MP cost for u to travel path.
Definition: utility.cpp:112
boost::shared_ptr< highlighter > highlighter_
Definition: manager.hpp:225
int side() const
Definition: unit.hpp:201
void draw_text_in_hex(const map_location &loc, const tdrawing_layer layer, const std::string &text, size_t font_size, SDL_Color color, double x_in_hex=0.5, double y_in_hex=0.5)
Draw text on a hex.
Definition: display.cpp:1668
size_t temp_move_unit_underlying_id_
Definition: manager.hpp:231
const std::string number
template to number regex
bool executing_all_actions_
Track whether we're in the process of executing all actions.
Definition: manager.hpp:212
-file sdl_utils.hpp
void pre_draw()
Called from the display before drawing.
Definition: manager.cpp:513
bool empty() const
Definition: config.cpp:1105
iterator queue_suppose_dead(size_t turn_num, unit &curr_unit, map_location const &loc)
Queues a suppose_dead to be executed last.
GLdouble GLdouble t
Definition: glew.h:1366
void contextual_bump_down_action()
Moves the action determined by the UI toward the beginning of the queue.
Definition: manager.cpp:1038
map_location get_selected_hex() const
std::vector< map_location > arrow_path_t
Definition: arrow.hpp:25
std::set< size_t > secondary_numbers
void save_temp_move()
Creates a move action for the current side, and erases the temp move.
Definition: manager.cpp:756
void set_active(bool active)
Activates/Deactivates the whiteboard.
Definition: manager.cpp:168
std::vector< fake_unit_ptr > fake_units_
Definition: manager.hpp:230
void get_numbers(const map_location &hex, numbers_t &result)
Gets called when display is drawing a hex to determine which numbers to draw on it.
void unghost_owner_unit(unit *unit)
Definition: utility.cpp:147
boost::shared_ptr< suppose_dead > suppose_dead_ptr
Definition: typedefs.hpp:84
bool can_enable_execution_hotkeys() const
Used to ask the whiteboard if its action execution hotkeys should be available to the user...
Definition: manager.cpp:243
void save_temp_attack(const map_location &attacker_loc, const map_location &defender_loc, int weapon_choice)
Creates an attack or attack-move action for the current side.
Definition: manager.cpp:798
bool planned_unit_map_active_
Definition: manager.hpp:208
iterator queue_recruit(size_t turn_num, const std::string &unit_name, const map_location &recruit_hex)
Queues a recruit to be executed last.
void on_gamestate_change()
Definition: manager.cpp:586
void draw_hex(const map_location &hex)
Called from the display when drawing hexes, to allow the whiteboard to add visual elements...
Definition: manager.cpp:540
static std::vector< team > *& teams
Definition: team.cpp:50
const config & options()
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:50
static std::string at(const std::string &file, int line)
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:82
virtual void draw_hex(const map_location &hex)=0
Gets called by display when drawing a hex, to allow actions to draw to the screen.
std::vector< size_t > team_numbers
boost::scoped_ptr< pathfind::marked_route > route_
Definition: manager.hpp:227
GLsizei const char ** path
Definition: glew.h:4654
whiteboard_lock unit_map_lock_
Reference counted "lock" to prevent the building of the unit map at certain times.
Definition: manager.hpp:221
GLuint GLuint end
Definition: glew.h:1221
iterator queue_move(size_t turn_num, unit &mover, const pathfind::marked_route &route, arrow_ptr arrow, fake_unit_ptr fake_unit)
Queues a move to be executed last.
std::map< std::string, t_string > string_map
void queue_net_cmd(size_t team_index, side_actions::net_cmd const &)
Adds a side_actions::net_cmd to net_buffer_[team_index], whereupon it will (later) be sent to all all...
Definition: manager.cpp:635
size_t num_turns() const
Returns the number of turns that have plans.
void set_real_unit_map()
Restore the regular unit map.
Definition: manager.cpp:1156
int current_side() const
Returns the number of the side whose turn it is.
std::vector< team > * teams
Definition: resources.cpp:29
bool has_actions() const
Checks whether the whiteboard has any planned action on any team.
Definition: manager.cpp:1050
void options_dlg()
Displays the whiteboard options dialog.
Definition: manager.cpp:1071
Arrows destined to be drawn on the map.
Definition: arrow.hpp:30
bool valid() const
Definition: location.hpp:69
const hotkey_ptr get_hotkey(const SDL_Event &event)
Iterate through the list of hotkeys and return a hotkey that matches the SDL_Event and the current ke...
unit_map::iterator get_temp_move_unit() const
Definition: manager.cpp:793
Applies the planned unit map for the duration of the struct's life.
Definition: manager.hpp:249
filter_context * filter_con
Definition: resources.cpp:23
friend struct future_map
Definition: manager.hpp:45
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1858
void contextual_execute()
Executes first action in the queue for current side.
Definition: manager.cpp:912
static bool valid_path(arrow_path_t const &path)
Checks that the path is not of length 0 or 1.
Definition: arrow.cpp:148
game_board * gameboard
Definition: resources.cpp:20
iterator queue_recall(size_t turn_num, const unit &unit, const map_location &recall_hex)
Queues a recall to be executed last.
#define ERR_WB
Definition: typedefs.hpp:26
bool gamestate_mutated_
Track whether the gamestate changed and we need to validate actions.
Definition: manager.hpp:216
bool allow_end_turn()
@ return true if the whiteboard is ready to end turn.
Definition: manager.cpp:945
static std::string const STYLE_HIGHLIGHTED
Definition: arrow.hpp:66
Class that handles highlighting planned actions as you hover over them and determine the right target...
Definition: highlighter.hpp:38
int selected_index() const
Returns the selected item index after displaying.
config & add_child(const std::string &key)
Definition: config.cpp:743
fake_unit_manager * fake_units
Definition: resources.cpp:32
static bool current_side_has_actions()
Whether the current side has actions in the first turn of its planned actions queue.
Definition: manager.cpp:411
std::set< size_t > units_owning_moves_
used to keep track of units owning planned moves for visual ghosting/unghosting
Definition: manager.hpp:244
bool is_local_human() const
Definition: team.hpp:267
Modify, read and display user preferences.
#define log_scope2(domain, description)
Definition: log.hpp:186
iterator queue_attack(size_t turn_num, unit &mover, const map_location &target_hex, int weapon_choice, const pathfind::marked_route &route, arrow_ptr arrow, fake_unit_ptr fake_unit)
Queues an attack or attack-move to be executed last.
void ghost_owner_unit(unit *unit)
Definition: utility.cpp:141
Structure which holds a single route and marks for special events.
Definition: pathfind.hpp:141
bool preparing_to_end_turn_
true if we're in the process of executing all action and should end turn once finished.
Definition: manager.hpp:214
friend struct real_map
Definition: manager.hpp:47
bool active_
Tracks whether the whiteboard is active.
Definition: manager.hpp:201
static void hide_all_plans()
Definition: manager.cpp:344
void for_each_action(std::function< void(action *)> function, team_filter team_filter)
Apply a function to all the actions of the whiteboard.
Definition: utility.cpp:168
int viewing_side() const
Definition: display.hpp:103
void on_change_controller(int side, const team &t)
Definition: manager.cpp:382
GLuint GLuint GLsizei count
Definition: glew.h:1221
GLuint color
Definition: glew.h:5801
void on_finish_side_turn(int side)
Definition: manager.cpp:308
size_t get_turn_num_of(unit const &) const
Determines the appropriate turn number for the next action planned for this unit. ...
std::vector< bool > team_plans_hidden_
team_plans_hidden_[i] = whether or not to hide actions from teams[i].
Definition: manager.hpp:241
Encapsulates the map of the game.
Definition: location.hpp:38
bool save_recruit(const std::string &name, int side_num, const map_location &recruit_hex)
Creates a recruit action for the current side.
Definition: manager.cpp:848
bool wait_for_side_init_
Definition: manager.hpp:207
void post_draw()
Called from the display after drawing.
Definition: manager.cpp:528
Various functions related to the creation of units (recruits, recalls, and placed units)...
size_t team_index()
Returns the team index this action queue belongs to.
Move numbering for the whiteboard.
Definition: display.hpp:895
int get_spent_gold_for(int side)
Used to track gold spending per-side when building the planned unit map Is referenced by the top bar ...
Definition: manager.cpp:1063
void erase_temp_move()
Erase the temporary arrow.
Definition: manager.cpp:743
bool can_modify_game_state() const
Determine whether the game is initialized and the current side has control of the game i...
Definition: manager.cpp:143
std::vector< config > net_buffer_
net_buffer_[i] = whiteboard network data to be sent "from" teams[i].
Definition: manager.hpp:238
std::pair< iterator, iterator > range_t
size_t i
Definition: function.cpp:1057
GLboolean invert
Definition: glew.h:1390
static SDL_Color get_side_color(int side)
Definition: team.cpp:828
Class that collects and applies unit_map modifications from the actions it visits and reverts all cha...
Definition: mapbuilder.hpp:40
void create_temp_move()
Creates a temporary visual arrow, that follows the cursor, for move creation purposes.
Definition: manager.cpp:641
bool hidden() const
bool allow_leader_to_move(unit const &leader) const
Used to ask permission to the wb to move a leader, to avoid invalidating planned recruits.
Definition: manager.cpp:259
#define LOG_WB
Definition: typedefs.hpp:28
side_actions_ptr viewer_actions()
Definition: utility.cpp:49
unsigned child_count(const std::string &key) const
Definition: config.cpp:635
void contextual_bump_up_action()
Moves the action determined by the UI toward the beginning of the queue.
Definition: manager.cpp:1026
std::string vgettext(const char *msgid, const utils::string_map &symbols)
net_cmd make_net_cmd_clear() const
GLuint const GLchar * name
Definition: glew.h:1782
void on_init_side()
The on_* methods below inform the whiteboard of specific events.
Definition: manager.cpp:292
GLsizeiptr size
Definition: glew.h:1649
bool save_recall(const unit &unit, int side_num, const map_location &recall_hex)
Creates a recall action for the current side.
Definition: manager.cpp:876
GLenum GLint ref
Definition: glew.h:1813
void print_help_once()
Definition: manager.cpp:103
void send_network_data()
Called by replay_network_sender to add whiteboard data to the outgoing network packets.
Definition: manager.cpp:598
boost::shared_ptr< move > move_ptr
Definition: typedefs.hpp:76
static void draw_numbers(map_location const &hex, side_actions::numbers_t numbers)
Definition: manager.cpp:433
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
#define DBG_WB
Definition: typedefs.hpp:29
bool enable_whiteboard_mode_on_start()
Various functions that implement the undoing (and redoing) of in-game commands.
CALLABLE_WRAPPER_INPUT_END if(key=="terrain")
Finalizer class to help with exception safety sets variable to value on destruction.
Definition: utility.hpp:81
bool is_network_ai() const
Definition: team.hpp:270
unit_const_ptr find_backup_leader(const unit &leader)
For a given leader on a keep, find another leader on another keep in the same castle.
Definition: utility.cpp:63
GLsizei GLenum GLuint GLuint GLsizei char * message
Definition: glew.h:2499
static std::string get_side_color_index(int side)
Definition: team.cpp:840
unit * future_visible_unit(map_location hex, int viewer_side)
Applies the future unit map and.
Definition: utility.cpp:91
bool should_clear_undo() const
Determines whether or not the undo_stack should be cleared.
Definition: manager.hpp:183
boost::shared_ptr< wb::manager > whiteboard
Definition: resources.cpp:36
actions::undo_list * undo_stack
Definition: resources.cpp:34
bool has_temp_move() const
Informs whether an arrow is being displayed for move creation purposes.
Definition: manager.hpp:134
unit_iterator find(size_t id)
Definition: map.cpp:285
bool valid() const
Definition: map.hpp:229
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
boost::shared_ptr< recall > recall_ptr
Definition: typedefs.hpp:82
Abstract base class for all the whiteboard planned actions.
Definition: action.hpp:33
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
bool executing_actions_
Track whenever we're modifying actions, to avoid dual execution etc.
Definition: manager.hpp:210
Class that keeps track of all the keys on the keyboard.
Definition: key.hpp:27
const int font_size
bool inverted_behavior_
Definition: manager.hpp:202
bool execute_all_actions()
Executes all actions for the current turn in sequence.
Definition: manager.cpp:951
void on_mouseover_change(const map_location &hex)
Definition: manager.cpp:566
void validate_viewer_actions()
Validates all actions of the current viewing side.
Definition: manager.cpp:421
This module contains various pathfinding functions and utilities.
GLsizei const GLcharARB ** string
Definition: glew.h:4503
This internal whiteboard class holds the planned action queues for a team, and offers many utility me...
Holds a temporary unit that can be drawn on the map without being placed in the unit_map.
unit_map * units
Definition: resources.cpp:35
A planned move, represented on the map by an arrow and a ghosted unit in the destination hex...
Definition: move.hpp:33
Display units performing various actions: moving, attacking, and dying.
void move_unit(const std::vector< map_location > &path, unit_ptr u, bool animate, map_location::DIRECTION dir, bool force_scroll)
Display a unit moving along a given path.
Definition: udisplay.cpp:486
boost::shared_ptr< recruit > recruit_ptr
Definition: typedefs.hpp:80
std::vector< map_location > & steps
Definition: pathfind.hpp:187
Definition: display.hpp:47
bool unit_has_actions(unit const *unit) const
Checks whether the specified unit has at least one planned action.
Definition: manager.cpp:1056
bool has_planned_unit_map() const
Whether the planned unit map is currently applied.
Definition: manager.hpp:113
static game_display * get_singleton()
void set_planned_unit_map()
Transforms the unit map so that it now reflects the future state of things, i.e.
Definition: manager.cpp:1133
const std::vector< map_location > & route_
Definition: move.cpp:288
void clear()
Empties the action queue.
void pre_delete_action(action_ptr action)
Handles various cleanup right before removing an action from the queue.
Definition: manager.cpp:320
side_actions_ptr current_side_actions()
Definition: utility.cpp:56