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