53 #define ERR_NG LOG_STREAM(err, log_engine)
54 #define DBG_NG LOG_STREAM(debug, log_engine)
103 : ambusher_(units.end())
104 , failed_teleport_(units.end())
109 , interrupted_(false)
120 , interrupted_(false)
182 take_village_step(
const config& cfg)
189 static const char* get_type_impl() {
return "take_village"; }
190 virtual const char* get_type()
const {
return get_type_impl(); }
192 virtual ~take_village_step() { }
204 virtual bool undo(
int)
218 static auto reg_undo_take_village_step = undo_action_container::subaction_factory<take_village_step>();
224 team *
t =
static_cast<unsigned>(side - 1) < teams.size() ? &teams[side - 1] :
nullptr;
225 if (
t &&
t->owns_village(
loc)) {
231 bool grants_timebonus =
false;
233 int old_owner_side = 0;
236 for(
team& tm : teams) {
237 int i_side = tm.side();
238 if (!
t || not_defeated ||
t->is_enemy(i_side)) {
239 if(tm.owns_village(
loc)) {
240 old_owner_side = i_side;
241 tm.lose_village(
loc);
243 if (side != i_side && action_timebonus) {
244 grants_timebonus =
true;
253 if(grants_timebonus) {
254 t->set_action_bonus_count(1 +
t->action_bonus_count());
255 *action_timebonus =
true;
274 typedef std::vector<map_location>::const_iterator route_iterator;
277 unit_mover(
const unit_mover&) =
delete;
278 unit_mover& operator=(
const unit_mover&) =
delete;
280 unit_mover(
const std::vector<map_location> & route,
281 move_unit_spectator *move_spectator,
282 bool skip_sightings,
bool skip_ally_sightings);
286 bool check_expected_movement();
288 void try_actual_movement(
bool show);
292 void feedback()
const;
294 void try_teleport(
bool show);
297 std::vector<map_location> expected_path()
const
303 std::size_t steps_travelled()
const
311 bool interrupted(
bool include_end_of_move_events=
true)
const
322 void cache_hidden_units(
const route_iterator &
start,
323 const route_iterator & stop);
325 void fire_hex_event(
const std::string & event_name,
326 const route_iterator & current,
327 const route_iterator & other);
329 bool is_ai_move()
const
334 route_iterator plot_turn(
const route_iterator &
start,
335 const route_iterator & stop);
340 void pump_sighted(
const route_iterator & from);
342 static std::string read_ambush_string(
const unit & ambusher);
344 void reveal_ambusher(
const map_location & hex,
bool update_alert=
true);
347 bool undo_blocked()
const
356 inline void check_for_ambushers(
const map_location & hex);
358 inline bool check_for_obstructing_unit(
const map_location & hex,
361 inline bool do_move(
const route_iterator & step_from,
362 const route_iterator & step_to,
369 inline void handle_fog(
const map_location & hex,
bool new_animation);
370 inline bool is_reasonable_stop(
const map_location & hex)
const;
372 inline void reveal_ambushers();
374 inline void validate_ambushers();
386 const std::vector<map_location> &
route_;
441 unit_mover::unit_mover(
const std::vector<map_location> & route,
442 move_unit_spectator *move_spectator,
443 bool skip_sightings,
bool skip_ally_sightings)
460 ,
goto_( is_ai_move() ?
move_it_->get_goto() : route.back() )
493 unit_mover::~unit_mover()
514 inline void unit_mover::check_for_ambushers(
const map_location & hex)
522 if ( neighbor_it != units.
end() &&
524 neighbor_it->invisible(
loc) )
541 inline bool unit_mover::check_for_obstructing_unit(
const map_location & hex,
564 const auto allowed_teleports = teleports.
get_adjacents(prev_hex);
566 if(allowed_teleports.count(hex) == 0) {
592 inline bool unit_mover::do_move(
const route_iterator & step_from,
593 const route_iterator & step_to,
606 move_it_->anim_comp().invalidate(disp);
617 move_it_->set_facing(step_from->get_relative_dir(*step_to));
621 move_it_->anim_comp().set_standing(
false);
628 move_it_->appearance_changed(),
false);
629 move_it_->set_appearance_changed(
false);
644 const route_iterator step_to =
begin_ + 1;
647 move_it_->anim_comp().invalidate(disp);
657 move_it_->anim_comp().set_standing(
false);
665 move_it_->set_appearance_changed(
false);
677 inline void unit_mover::handle_fog(
const map_location & hex,
705 inline bool unit_mover::is_reasonable_stop(
const map_location & hex)
const
726 inline void unit_mover::reveal_ambushers()
734 reveal_ambusher(reveal,
true);
747 inline void unit_mover::validate_ambushers()
778 void unit_mover::cache_hidden_units(
const route_iterator &
start,
779 const route_iterator & stop)
789 validate_ambushers();
802 if (
start == stop ) {
836 void unit_mover::fire_hex_event(
const std::string & event_name,
837 const route_iterator & current,
838 const route_iterator & other)
855 unit_mover::route_iterator unit_mover::plot_turn(
const route_iterator &
start,
856 const route_iterator & stop)
865 int remaining_moves =
move_it_->movement_left();
879 for ( ;
end != stop; ++
end )
885 remaining_moves -=
move_it_->movement_cost(map[*end]);
886 if ( remaining_moves < 0 ) {
894 if (!
move_it_->get_ability_bool(
"skirmisher", *end) &&
937 const route_iterator new_limit = plot_turn(step,
expected_end_);
938 cache_hidden_units(step, new_limit);
956 void unit_mover::pump_sighted(
const route_iterator & from)
959 post_wml(pump_res, from);
966 std::string unit_mover::read_ambush_string(
const unit & ambusher)
970 const std::string & ambush_string = (*
hide.ability_cfg)[
"alert"].str();
971 if (!ambush_string.empty()) {
972 return ambush_string;
977 return std::string();
986 void unit_mover::reveal_ambusher(
const map_location & hex,
bool update_alert)
994 if ( ambusher != units.
end() ) {
1006 if ( update_alert ) {
1020 auto [wml_undo_blocked, wml_move_aborted] =
actor_sighted(*ambusher, &sight_cache);
1040 bool unit_mover::check_expected_movement()
1053 void unit_mover::try_actual_movement(
bool show)
1055 static const std::string enter_hex_str(
"enter hex");
1056 static const std::string exit_hex_str(
"exit hex");
1059 bool obstructed_stop =
false;
1077 const route_iterator step_from =
real_end_ - 1;
1084 if (
sighted_ && is_reasonable_stop(*step_from) ) {
1090 fire_hex_event(exit_hex_str, step_from,
real_end_);
1097 obstructed_stop =
true;
1102 bool new_animation = do_move(step_from,
real_end_, animator);
1112 fire_hex_event(enter_hex_str,
real_end_, step_from);
1135 if (!obstructed_stop) {
1149 void unit_mover::try_teleport(
bool show)
1151 const route_iterator step_from =
real_end_ - 1;
1158 fire_hex_event(
"exit hex", step_from,
begin_);
1160 bool new_animation = do_teleport(animator);
1163 handle_fog(*(
begin_ + 1), new_animation);
1167 fire_hex_event(
"enter hex",
begin_, step_from);
1169 if(is_reasonable_stop(*step_from)) {
1170 pump_sighted(step_from);
1173 pump_sighted(step_from);
1193 void unit_mover::post_move()
1197 int orig_village_owner = 0;
1198 bool action_time_bonus =
false;
1238 spectator_->set_tiles_entered(steps_travelled());
1244 if(!mover_valid || undo_blocked()) {
1261 void unit_mover::feedback()
const
1268 std::string message_prefix =
"";
1273 message_prefix +=
" \n";
1281 std::string teleport_string =
_(
"Failed teleport! Exit not empty");
1283 message_prefix +=
" \n";
1297 symbols[
"friendphrase"] =
VNGETTEXT(
"Part of 'Units sighted! (...)' sentence^1 friendly",
"$friends friendly",
friend_count_, symbols);
1299 symbols[
"enemyphrase"] =
VNGETTEXT(
"Part of 'Units sighted! (...)' sentence^1 enemy",
"$enemies enemy",
enemy_count_, symbols);
1302 message =
VGETTEXT(
"Units sighted! ($friendphrase, $enemyphrase)", symbols);
1316 disp.
announce(message_prefix + message, msg_color, announce_options);
1317 message_prefix +=
" \n";
1324 if ( !name.empty() ) {
1326 symbols[
"hotkey"] = name;
1327 std::string
message =
VGETTEXT(
"(press $hotkey to keep moving)", symbols);
1329 message_prefix +=
" \n";
1343 mover.try_actual_movement(show_move);
1347 "stopped_early", mover.stopped_early(),
1348 "final_hex_x", mover.final_hex().wml_x(),
1349 "final_hex_y", mover.final_hex().wml_y(),
1354 replay::process_error(
"calculated movement destination (x="+ cn[
"final_hex_x"].str() +
" y=" + cn[
"final_hex_y"].str() +
1355 ") didn't match the original destination(x="+ co[
"final_hex_x"].str() +
" y=" + co[
"final_hex_y"].str() +
")\n");
1385 bool continued_move,
1386 bool skip_ally_sighted,
1390 unit_mover mover(steps, move_spectator, continued_move, skip_ally_sighted);
1391 if(!mover.check_expected_movement()) {
1392 DBG_NG <<
"found expected empty move, aborting";
1404 config{
"teleport_from_x", teleport_from.
wml_x(),
"teleport_from_y", teleport_from.
wml_y(),
"teleport_to_x",
1405 teleport_to.
wml_x(),
"teleport_to_y", teleport_to.
wml_y()});
1409 bool continued_move,
bool skip_ally_sighted,
bool show_move)
1411 unit_mover mover(steps,
nullptr, continued_move, skip_ally_sighted);
1412 mover.try_teleport(show_move);
1432 const std::vector<map_location>& steps,
bool continued_move,
bool* interrupted)
1437 *interrupted = move_spectator.get_interrupted();
1439 return move_spectator.get_tiles_entered();
1456 const std::vector<map_location>& steps,
bool continued_move,
move_unit_spectator& move_spectator)
1460 if ( steps.size() < 2 || (steps.size() == 2 && steps.front() == steps.back()) ) {
1461 DBG_NG <<
"Ignoring a unit trying to jump on its hex at " <<
1472 const bool skip_ally_sighted = !
prefs::get().ally_sighted_interrupts();
std::string ambush_string_
bool event_mutated_mid_move_
std::vector< map_location > ambushers_
std::size_t friend_count_
unit_map::iterator move_it_
route_iterator expected_end_
map_location blocked_loc_
int original_village_owner
static lg::log_domain log_engine("engine")
const std::vector< map_location > & route_
map_location ambush_stop_
bool take_village_timebonus
const bool playing_team_is_viewing_
route_iterator obstructed_
const map_location::direction orig_dir_
std::deque< int > moves_left_
route_iterator ambush_limit_
move_unit_spectator *const spectator_
const route_iterator begin_
const bool skip_sighting_
const route_iterator full_end_
const bool skip_ally_sighting_
Various functions related to moving units.
void set_ambusher(const unit_map::const_iterator &u)
set the location of an ambusher
void add_seen_friend(const unit_map::const_iterator &u)
add a location of a seen friend
const std::vector< unit_map::const_iterator > & get_seen_enemies() const
get the locations of seen enemies
const unit_map::const_iterator & get_ambusher() const
get the location of an ambusher
void error(const std::string &message) override
ingerited from action_spectator
void add_seen_enemy(const unit_map::const_iterator &u)
add the location of new seen enemy
const unit_map::const_iterator & get_unit() const
get new location of moved unit
unit_map::const_iterator ambusher_
unit_map::const_iterator unit_
void reset(const unit_map &units)
reset all locations to empty values
void set_unit(const unit_map::const_iterator &u)
set the iterator to moved unit
std::vector< unit_map::const_iterator > seen_enemies_
void set_failed_teleport(const unit_map::const_iterator &u)
set the location of a failed teleport
std::vector< unit_map::const_iterator > seen_friends_
virtual ~move_unit_spectator()
destructor
const std::vector< unit_map::const_iterator > & get_seen_friends() const
get the locations of seen friends
std::size_t tiles_entered_
const unit_map::const_iterator & get_failed_teleport() const
get the location of a failed teleport
unit_map::const_iterator failed_teleport_
void add_custom(Args &&... args)
void add_move(const unit_const_ptr &u, const std::vector< map_location >::const_iterator &begin, const std::vector< map_location >::const_iterator &end, int start_moves, const map_location::direction dir=map_location::direction::indeterminate)
Adds a move to the undo stack.
virtual bool local_checkup(const config &expected_data, config &real_data)=0
Compares data to the results calculated during the original game.
A config object defines a single node in a WML file, with access to child nodes.
int village_owner(const map_location &loc) const
Given the location of a village, will return the 1-based number of the team that currently owns it,...
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
void redraw_minimap()
Schedule the minimap to be redrawn.
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
void announce(const std::string &msg, const color_t &color=font::GOOD_COLOR, const announce_options &options=announce_options())
Announce a message prominently.
bool fogged(const map_location &loc) const
Returns true if location (x,y) is covered in fog.
static display * get_singleton()
Returns the display object if a display object exists.
virtual const std::vector< team > & teams() const override
bool team_is_defeated(const team &t) const
Calculates whether a team is defeated.
virtual const unit_map & units() const override
virtual const gamemap & map() const override
void invalidate_unit_after_move(const map_location &src, const map_location &dst)
Same as invalidate_unit() if moving the displayed unit.
static game_display * get_singleton()
Encapsulates the map of the game.
bool is_village(const map_location &loc) const
const std::unordered_set< map_location > & get_adjacents(map_location loc) const
bool is_skipping_actions() const
bool is_skipping_replay() const
static config get_movement(const std::vector< map_location > &steps, bool skip_sighted, bool skip_ally_sighted)
Records a move that follows the provided steps.
static void process_error(const std::string &msg)
static void block_undo(bool do_block=true, bool clear_undo=true)
set this to false to prevent clearing the undo stack, this is important when we cannot change the gam...
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).
void set_action_bonus_count(const int count)
bool fog_or_shroud() const
bool auto_shroud_updates() const
bool is_enemy(int n) const
int action_bonus_count() const
bool owns_village(const map_location &loc) const
A class to encapsulate the steps of drawing a unit's move.
void finish(const unit_ptr &u, map_location::direction dir=map_location::direction::indeterminate)
Finishes the display of movement for the supplied unit.
void wait_for_anims()
Waits for the final animation of the most recent proceed_to() to finish.
void proceed_to(const unit_ptr &u, std::size_t path_index, bool update=false, bool wait=true)
Visually moves a unit from the last hex we drew to the one specified by path_index.
void start(const unit_ptr &u)
Initiates the display of movement for the supplied unit.
Container associating units to locations.
std::size_t count(const map_location &loc) const
unit_iterator find(std::size_t id)
umap_retval_pair_t move(const map_location &src, const map_location &dst)
Moves a unit from location src to location dst.
This class represents a single unit of a specific type.
static void clear_status_caches()
Clear this unit status cache for all units.
static std::string _(const char *str)
unit_ability_list get_abilities(const std::string &tag_name, const map_location &loc) const
Gets the unit's active abilities of a particular type if it were on a specified location.
@ STATE_UNCOVERED
The unit is petrified - it cannot move or be attacked.
T end(const std::pair< T, T > &p)
T begin(const std::pair< T, T > &p)
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Standard logging facilities (interface).
std::vector< int > get_sides_not_seeing(const unit &target)
Returns the sides that cannot currently see target.
void teleport_unit_from_replay(const std::vector< map_location > &steps, bool continued_move, bool skip_ally_sighted, bool show_move)
Teleports a unit across the board.
game_events::pump_result_t actor_sighted(const unit &target, const std::vector< int > *cache)
Fires sighted events for the sides that can see target.
void teleport_unit_and_record(const map_location &teleport_from, const map_location &teleport_to, move_unit_spectator *)
Teleports a unit across the board and enters the synced context.
void move_unit_and_record(const std::vector< map_location > &steps, bool continued_move, move_unit_spectator &move_spectator)
Moves a unit across the board.
game_events::pump_result_t get_village(const map_location &loc, int side, bool *action_timebonus, bool fire_event)
Makes it so the village at the given location is owned by the given side.
static void move_unit_internal(unit_mover &mover)
void execute_move_unit(const std::vector< map_location > &steps, bool continued_move, bool skip_ally_sighted, move_unit_spectator *move_spectator)
Moves a unit across the board.
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
void pump()
Process all events currently in the queue.
const color_t NORMAL_COLOR
std::tuple< bool, bool > pump_result_t
void show(const gui2::tracked_drawable &target)
Displays the fps report popup for the given tracked_drawable.
void hide()
Hides the fps report popup.
bool fire_event(const ui_event event, const std::vector< std::pair< widget *, ui_event >> &event_chain, widget *dispatcher, widget *w, F &&... params)
Helper function for fire_event.
static bool is_active(const widget *wgt)
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
void write(std::ostream &out, const configr_of &cfg, unsigned int level)
bool enemy_zoc(const team ¤t_team, const map_location &loc, const team &viewing_team, bool see_all)
Determines if a given location is in an enemy zone of control.
const teleport_map get_teleport_locations(const unit &u, const team &viewing_team, bool see_all, bool ignore_units, bool check_vision)
game_events::manager * game_events
actions::undo_list * undo_stack
play_controller * controller
std::shared_ptr< wb::manager > whiteboard
std::map< std::string, t_string > string_map
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
This module contains various pathfinding functions and utilities.
Define the game's event mechanism.
Records information to be able to undo an action.
virtual void write(config &cfg) const
Writes this into the provided config.
The basic class for representing 8-bit RGB or RGBA colour values.
Holds options for calls to function 'announce' (announce).
bool discard_previous
An announcement according these options should replace the previous announce (typical of fast announc...
static const hotkey_command & get_command_by_command(HOTKEY_COMMAND command)
the execute_command argument was changed from HOTKEY_COMMAND to hotkey_command, to be able to call it...
Encapsulates the map of the game.
direction
Valid directions which can be moved in our hexagonal world.
static const map_location & null_location()
void write(config &cfg) const
Data typedef for unit_ability_list.
pointer get_shared_ptr() const
This is exactly the same as operator-> but it's slightly more readable, and can replace &*iter syntax...
checkup * checkup_instance
Display units performing various actions: moving, attacking, and dying.
Various functions that implement the undoing (and redoing) of in-game commands.
Various functions implementing vision (through fog of war and shroud).