51 #define ERR_NG LOG_STREAM(err, log_engine)
52 #define LOG_NG LOG_STREAM(info, log_engine)
55 #define ERR_WML LOG_STREAM(err, log_wml)
64 , previous_free_hex_()
69 , unselected_paths_(false)
70 , unselected_reach_(false)
74 , reachmap_invalid_(false)
75 , show_partial_move_(false)
76 , teleport_selected_(false)
77 , preventing_units_highlight_(false)
96 const unsigned threshold_1080p = 14;
98 const double scale_factor = threshold_1080p / std::hypot(1080,1920);
99 return static_cast<int>(screen_diagonal * scale_factor);
117 if(mini_loc.
valid()) {
135 const double drag_distance =
136 std::pow(
static_cast<double>(
drag_from_.x - pos.x), 2) +
137 std::pow(
static_cast<double>(
drag_from_.y - pos.y), 2);
147 bool selected_hex_has_my_unit = found_unit.valid() && found_unit.get_shared_ptr()->side() ==
side_num_;
193 selected_hex_has_my_unit = found_unit.valid();
247 if (attack_from.
valid()) {
250 else if (!mouseover_unit &&
263 && mouseover_unit->side() ==
side_num_ ) {
288 if (attack_from.
valid()) {
318 && mouseover_unit.
valid()
345 !
gui().fogged(un->get_location()))
351 if(!
gui().viewing_team().is_enemy(un->side()) && !
pc_.
get_teams()[un->side() - 1].is_ai()) {
370 std::unique_ptr<unit_movement_resetter> move_reset;
372 move_reset = std::make_unique<unit_movement_resetter>(*un);
411 lk->mouse_over_hex_callback(new_hex);
444 bool selected_hex_has_unit;
499 if(attack_from.
valid()) {
536 if(attack_from.
valid()) {
605 static const std::array<const std::string, 6> buttons = {
614 if (
gui().view_locked() || button < SDL_BUTTON_LEFT || button > buttons.size()) {
621 lk->mouse_button_callback(loc, buttons[button], (event.state == SDL_RELEASED ?
"up" :
"down"));
630 return lk->mouse_button_callback(loc, buttons[button],
"click");
664 return it.
valid() ? &*it :
nullptr;
670 return it.
valid() ? &*it :
nullptr;
698 bool source_eligible = source_unit.
valid();
699 if(!source_eligible) {
705 if(!source_eligible) {
714 if(!source_eligible) {
720 source_eligible &= source_unit->attacks_left() != 0;
721 if(!source_eligible) {
732 bool target_eligible = target_unit.
valid();
733 if(!target_eligible) {
738 target_eligible &= viewer.
is_enemy(target_unit->side());
739 if(!target_eligible) {
744 assert(source_unit->side() != target_unit->side());
746 target_eligible &= !target_unit->incapacitated();
747 if(!target_eligible) {
755 int best_rating = 100;
760 for(std::size_t
n = 0;
n < adj.size(); ++
n) {
772 unsigned int difference = std::abs(
static_cast<int>(
static_cast<int>(preferred) -
n));
773 if(difference > ndirections / 2) {
774 difference = ndirections - difference;
777 unsigned int second_difference = std::abs(
static_cast<int>(
static_cast<int>(second_preferred) -
n));
778 if(second_difference > ndirections / 2) {
779 second_difference = ndirections - second_difference;
782 const int rating = difference * 2 + (second_difference > difference);
783 if(rating < best_rating || res.
valid() ==
false) {
784 best_rating = rating;
805 un->
get_location(), go_to, 10000.0, calc, board.
map().
w(), board.
map().
h(), &allowed_teleports);
832 if(clicked_u && (!selected_u || selected_u->side() !=
side_num_ ||
833 (clicked_u->side() ==
side_num_ && clicked_u->id() != selected_u->id()))
878 if(clicked_u && (!selected_u || selected_u->side() !=
side_num_ ||
879 (clicked_u->side() ==
side_num_ && clicked_u->id() != selected_u->id()))
907 const unit* clicked_u =
nullptr;
1158 bool invisible = u->invisible(u->get_location());
1160 if(!
gui_->
fogged(u->get_location()) && !u->incapacitated() && !invisible) {
1164 if(
path.destinations.find(hex) !=
path.destinations.end()) {
1210 bool interrupted =
false;
1211 if(steps.size() > 1) {
1214 interrupted = interrupted || num_moves + 1 < steps.size();
1222 return !interrupted;
1246 interrupted =
false;
1258 if(u && u->can_recruit() && u->side() ==
gui().viewing_team().side()
1261 _(
"You cannot move your leader away from the keep with some planned recruits or recalls left."));
1266 LOG_NG <<
"move unit along route from " << steps.front() <<
" to " << steps.back();
1275 if(interrupted && moves + 1 < steps.size()) {
1277 select_hex(steps[moves],
false,
false,
false);
1311 pc_.
get_whiteboard()->save_temp_attack(attacker_loc, defender_loc, weapon_choice);
1318 for(
unsigned int i = 0;
i < attacker->attacks().
size();
i++) {
1320 if(attacker->attacks()[
i].attack_weight() > 0) {
1328 if(!bc_vector.empty() && bc.
better_attack(bc_vector[best], 0.5)) {
1330 best = bc_vector.size();
1333 bc_vector.emplace_back(std::move(bc));
1347 if(!attacker || !defender) {
1348 ERR_NG <<
"One fighter is missing, can't attack";
1352 std::vector<battle_context> bc_vector;
1355 if(bc_vector.empty()) {
1374 }
catch(
const std::bad_alloc&) {
1375 lg::log_to_chat() <<
"Memory exhausted a unit has either a lot hitpoints or a negative amount.\n";
1376 ERR_WML <<
"Memory exhausted a unit has either a lot hitpoints or a negative amount.";
1388 unit* attacker =
nullptr;
1389 const unit* defender =
nullptr;
1390 std::vector<battle_context> bc_vector;
1394 if(!attacker_it || attacker_it->side() !=
side_num_ || attacker_it->incapacitated()) {
1399 if(!defender_it ||
current_team().is_enemy(defender_it->side()) ==
false || defender_it->incapacitated()) {
1405 attacker = &*attacker_it;
1406 defender = &*defender_it;
1409 if(std::size_t(choice) >= bc_vector.size()) {
1453 std::set<map_location> res;
1477 if(u->attacks_left() == 0) {
1494 if(!
i || !
i->is_visible_to_team(cur_team,
false)) {
1498 const unit& target = *
i;
1519 if(
current_team().is_enemy(
gui().viewing_team().side()) && it->invisible(it->get_location())) {
1523 if(it->get_hidden()) {
1547 if(it == units.
begin()) {
1553 if(it == units.
end()) {
Various functions that implement attacks and attack calculations.
Various functions related to moving units.
Computes the statistics of a battle between an attacker and a defender unit.
const battle_context_unit_stats & get_attacker_stats() const
This method returns the statistics of the attacker.
bool better_attack(class battle_context &that, double harm_weight)
Given this harm_weight, is this attack better than that?
can_move_result unit_can_move(const unit &u) const
Work out what u can do - this does not check which player's turn is currently active,...
const team & viewing_team() const
void invalidate_game_status()
Function to invalidate the game status displayed on the sidebar.
void scroll_to_tile(const map_location &loc, SCROLL_TYPE scroll_type=ONSCREEN, bool check_fogged=true, bool force=true)
Scroll such that location loc is on-screen.
bool fogged(const map_location &loc) const
Returns true if location (x,y) is covered in fog.
void invalidate_all()
Function to invalidate all tiles.
map_location minimap_location_on(int x, int y)
given x,y co-ordinates of the mouse, will return the location of the hex in the minimap that the mous...
rect map_area() const
Returns the area used for the map.
map_location hex_clicked_on(int x, int y) const
given x,y co-ordinates of an onscreen pixel, will return the location of the hex that this pixel corr...
bool scroll(const point &amount, bool force=false)
Scrolls the display by amount pixels.
bool minimap_scrolling_
minimap scrolling (scroll-drag) state flag
map_location last_hex_
last highlighted hex
map_location drag_from_hex_
Drag start or mouse-down map location.
bool simple_warp_
MMB click (on game map) state flag.
bool mouse_motion_default(int x, int y, bool update)
This handles minimap scrolling and click-drag.
bool dragging_started_
Actual drag flag.
bool dragging_touch_
Finger drag init flag.
point drag_from_
Drag start position.
void disable_units_highlight()
Use this to disable hovering an unit from highlighting its movement range.
bool move_unit_along_current_route()
Moves a unit along the currently cached route.
bool mouse_button_event(const SDL_MouseButtonEvent &event, uint8_t button, map_location loc, bool click=false) override
int show_attack_dialog(const map_location &attacker_loc, const map_location &defender_loc)
map_location previous_hex_
void show_reach_for_unit(const unit_ptr &un)
Highlight the hexes that a unit can move to.
game_display & gui() override
Due to the way this class is constructed we can assume that the display* gui_ member actually points ...
void select_or_action(bool browse)
void attack_enemy_(const map_location &attacker_loc, const map_location &defender_loc, int choice)
void save_whiteboard_attack(const map_location &attacker_loc, const map_location &defender_loc, int weapon_choice)
void set_current_paths(const pathfind::paths &new_paths)
pathfind::marked_route get_route(const unit *un, map_location go_to, const team &team) const
unit_map::iterator selected_unit()
static mouse_handler * singleton_
int fill_weapon_choices(std::vector< battle_context > &bc_vector, unit_map::iterator attacker, unit_map::iterator defender)
void enable_units_highlight()
When unit highlighting is disabled, call this when the mouse no longer hovers any unit to enable high...
void touch_motion(int x, int y, const bool browse, bool update=false, map_location loc=map_location::null_location()) override
void attack_enemy(const map_location &attacker_loc, const map_location &defender_loc, int choice)
std::set< map_location > get_adj_enemies(const map_location &loc, int side) const
map_location previous_free_hex_
void select_hex(const map_location &hex, const bool browse, const bool highlight=true, const bool fire_event=true, const bool force_unhighlight=false)
unit_map::const_iterator find_unit(const map_location &hex) const
map_location current_unit_attacks_from(const map_location &loc) const
mouse_handler(game_display *gui, play_controller &pc)
bool right_click_show_menu(int x, int y, const bool browse) override
Called in the default right_click when the context menu is about to be shown, can be used for preproc...
map_location selected_hex_
pathfind::marked_route current_route_
const map_location hovered_hex() const
Uses SDL and game_display::hex_clicked_on to fetch the hex the mouse is hovering, if applicable.
void touch_action(const map_location hex, bool browse) override
bool unit_in_cycle(unit_map::const_iterator it)
void set_side(int side_number)
void move_action(bool browse) override
Overridden in derived class.
pathfind::paths current_paths_
If non-empty, current_paths_.destinations contains a cache of highlighted hexes, likely the movement ...
bool hex_hosts_unit(const map_location &hex) const
Unit exists on the hex, no matter if friend or foe.
int drag_threshold() const override
Minimum dragging distance to fire the drag&drop.
unit * find_unit_nonowning(const map_location &hex)
bool preventing_units_highlight_
void cycle_units(const bool browse, const bool reverse=false)
std::size_t move_unit_along_route(const std::vector< map_location > &steps, bool &interrupted)
Moves a unit across the board for a player.
void show_attack_options(const unit_map::const_iterator &u)
Causes attackable hexes to be highlighted.
void mouse_motion(int x, int y, const bool browse, bool update=false, map_location loc=map_location::null_location()) override
Use update to force an update of the mouse state.
virtual const std::vector< team > & teams() const override
unit_map::iterator find_visible_unit(const map_location &loc, const team ¤t_team, bool see_all=false)
virtual const unit_map & units() const override
virtual const gamemap & map() const override
void display_unit_hex(map_location hex)
Change the unit to be displayed in the sidebar.
virtual void highlight_hex(map_location hex) override
Function to highlight a location.
void set_attack_indicator(const map_location &src, const map_location &dst)
Set the attack direction indicator.
void set_route(const pathfind::marked_route *route)
Sets the route along which footsteps are drawn to show movement of a unit.
virtual void select_hex(map_location hex) override
Function to display a location as selected.
void highlight_reach(const pathfind::paths &paths_list)
Sets the paths that are currently displayed as available for the unit to move along.
void clear_attack_indicator()
void highlight_another_reach(const pathfind::paths &paths_list, const map_location &goal=map_location::null_location())
Add more paths to highlight.
bool unhighlight_reach()
Reset highlighting of paths.
pump_result_t fire(const std::string &event, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Function to fire an event.
std::unique_ptr< game_lua_kernel > lua_kernel_
int w() const
Effective map width.
int h() const
Effective map height.
bool on_board(const map_location &loc) const
Tell if a location is on the map.
bool is_keep(const map_location &loc) const
bool show(const unsigned auto_close_time=0)
Shows the window.
int get_selected_weapon() const
std::vector< team > & get_teams()
const unit_map & get_units() const
const tod_manager & get_tod_manager() const
int current_side() const
Returns the number of the side whose turn it is.
std::shared_ptr< wb::manager > get_whiteboard() const
const gamemap & get_map() const
game_events::wml_event_pump & pump()
static config get_attack(const map_location &a, const map_location &b, int att_weapon, int def_weapon, const std::string &attacker_type_id, const std::string &defender_type_id, int attacker_lvl, int defender_lvl, const std::size_t turn, const time_of_day &t)
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 is_enemy(int n) const
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
void set_selecting()
Sets the animation state to that when the unit is selected.
Container associating units to locations.
unit_iterator find(std::size_t id)
This class represents a single unit of a specific type.
Definitions for the interface to Wesnoth Markup Language (WML).
static std::string _(const char *str)
bool incapacitated() const
Check if the unit has been petrified.
const std::string & type_id() const
The id of this unit's type.
bool get_hidden() const
Gets whether this unit is currently hidden on the map.
int side() const
The side this unit belongs to.
unit_animation_component & anim_comp() const
const map_location & get_location() const
The current map location this unit is at.
void set_goto(const map_location &new_goto)
Sets this unit's long term destination.
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Standard logging facilities (interface).
static lg::log_domain log_engine("engine")
static lg::log_domain log_wml("wml")
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.
std::size_t move_unit_and_record(const std::vector< map_location > &steps, bool continued_move, bool *interrupted)
Wrapper around the other overload.
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Handling of system events.
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.
unsigned screen_width
The screen resolution and pixel pitch should be available for all widgets since their drawing method ...
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator &calc, const std::size_t width, const std::size_t height, const teleport_map *teleports, bool border)
marked_route mark_route(const plain_route &rt, bool update_move_cost)
Add marks on a route rt assuming that the unit located at the first hex of rt travels along it.
const teleport_map get_teleport_locations(const unit &u, const team &viewing_team, bool see_all, bool ignore_units, bool check_vision)
uint32_t get_mouse_state(int *x, int *y)
A wrapper for SDL_GetMouseState that gives coordinates in draw space.
point get_mouse_location()
Returns the current mouse location in draw space.
void play_UI_sound(const std::string &files)
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
std::shared_ptr< bool > whiteboard_lock
std::shared_ptr< unit > unit_ptr
Define the game's event mechanism.
This file contains the settings handling of the widget library.
rect src
Non-transparent portion of the surface to compose.
Structure describing the statistics of a unit involved in the battle.
bool disable
Attack has disable special.
int attack_num
Index into unit->attacks() or -1 for none.
Encapsulates the map of the game.
direction
Valid directions which can be moved in our hexagonal world.
direction get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
static const map_location & null_location()
Structure which holds a single route and marks for special events.
std::vector< map_location > & steps
void insert(const map_location &)
bool contains(const map_location &) const
const_iterator find(const map_location &) const
Object which contains all the possible locations a unit can move to, with associated best routes to t...
Structure which holds a single route between one location and another.
bool contains(int x, int y) const
Whether the given point lies within the rectangle.
This object is used to temporary move a unit in the unit map, swapping out any unit that is already t...
pointer get_shared_ptr() const
This is exactly the same as operator-> but it's slightly more readable, and can replace &*iter syntax...
ONLY IF whiteboard is currently active, applies the planned unit map for the duration of the struct's...
Ensures that the real unit map is active for the duration of the struct's life.
static map_location::direction n
Contains typedefs for the whiteboard.