made it so that click-to-attack makes the unit move...
....to the nearest hex to the cursor
This commit is contained in:
parent
c970105ae4
commit
a469fc31fb
13 changed files with 70 additions and 80 deletions
|
@ -194,10 +194,6 @@ battle_stats evaluate_battle_stats(const gamemap& map,
|
|||
gamemap::TERRAIN attacker_terrain_override,
|
||||
battle_stats_strings *strings)
|
||||
{
|
||||
//if these are both genuine positions, work out the range
|
||||
//combat is taking place at
|
||||
const int combat_range = attacker_terrain_override == 0 ? distance_between(attacker,defender) : 1;
|
||||
|
||||
battle_stats res;
|
||||
|
||||
res.attack_with = attack_with;
|
||||
|
@ -280,8 +276,7 @@ battle_stats evaluate_battle_stats(const gamemap& map,
|
|||
int defend_with = -1;
|
||||
res.ndefends = 0;
|
||||
for(int defend_option = 0; defend_option != int(defender_attacks.size()); ++defend_option) {
|
||||
if(defender_attacks[defend_option].range() == attack.range() &&
|
||||
defender_attacks[defend_option].hexes() >= combat_range) {
|
||||
if(defender_attacks[defend_option].range() == attack.range()) {
|
||||
const double rating = a->second.damage_against(defender_attacks[defend_option])
|
||||
*defender_attacks[defend_option].damage()
|
||||
*defender_attacks[defend_option].num_attacks()
|
||||
|
|
|
@ -66,12 +66,13 @@ struct preproc_define {
|
|||
: value(val), arguments(args) {}
|
||||
std::string value;
|
||||
std::vector<std::string> arguments;
|
||||
bool operator==(preproc_define const &p) const
|
||||
{ return value == p.value && arguments == p.arguments; }
|
||||
};
|
||||
|
||||
typedef std::map<std::string,preproc_define> preproc_map;
|
||||
|
||||
inline bool operator==(const preproc_define& a, const preproc_define& b) { return a.value == b.value && a.arguments == b.arguments; }
|
||||
inline bool operator!=(const preproc_define& a, const preproc_define& b) { return !operator==(a,b); }
|
||||
|
||||
//function to use the WML preprocessor on a file, and returns the resulting
|
||||
//preprocessed file data. defines is a map of symbols defined. src is used
|
||||
//internally and should be set to NULL
|
||||
|
|
|
@ -690,10 +690,6 @@ void unit_preview_pane::draw_contents()
|
|||
details << "\n"
|
||||
<< at_it->damage() << "-" << at_it->num_attacks() << " -- "
|
||||
<< (at_it->range() == attack_type::SHORT_RANGE ? _("melee") : _("ranged"));
|
||||
|
||||
if(at_it->hexes() > 1) {
|
||||
details << " (" << at_it->hexes() << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ void display::highlight_hex(gamemap::location hex)
|
|||
invalidate_unit();
|
||||
}
|
||||
|
||||
gamemap::location display::hex_clicked_on(int xclick, int yclick)
|
||||
gamemap::location display::hex_clicked_on(int xclick, int yclick, gamemap::location::DIRECTION* nearest_hex)
|
||||
{
|
||||
const SDL_Rect& rect = map_area();
|
||||
if(point_in_rect(xclick,yclick,rect) == false) {
|
||||
|
@ -247,10 +247,10 @@ gamemap::location display::hex_clicked_on(int xclick, int yclick)
|
|||
xclick -= rect.x;
|
||||
yclick -= rect.y;
|
||||
|
||||
return pixel_position_to_hex(xpos_ + xclick, ypos_ + yclick);
|
||||
return pixel_position_to_hex(xpos_ + xclick, ypos_ + yclick, nearest_hex);
|
||||
}
|
||||
|
||||
gamemap::location display::pixel_position_to_hex(int x, int y)
|
||||
gamemap::location display::pixel_position_to_hex(int x, int y, gamemap::location::DIRECTION* nearest_hex)
|
||||
{
|
||||
const int s = hex_size();
|
||||
const int tesselation_x_size = s * 3 / 2;
|
||||
|
@ -260,8 +260,8 @@ gamemap::location display::pixel_position_to_hex(int x, int y)
|
|||
const int y_base = y / tesselation_y_size;
|
||||
const int y_mod = y % tesselation_y_size;
|
||||
|
||||
int x_modifier;
|
||||
int y_modifier;
|
||||
int x_modifier = 0;
|
||||
int y_modifier = 0;
|
||||
|
||||
if (y_mod < tesselation_y_size / 2) {
|
||||
if ((x_mod * 2 + y_mod) < (s / 2)) {
|
||||
|
@ -288,7 +288,33 @@ gamemap::location display::pixel_position_to_hex(int x, int y)
|
|||
}
|
||||
}
|
||||
|
||||
return gamemap::location(x_base + x_modifier, y_base + y_modifier);
|
||||
const gamemap::location res(x_base + x_modifier, y_base + y_modifier);
|
||||
|
||||
if(nearest_hex != NULL) {
|
||||
const int westx = (get_location_x(res) - map_area().x + xpos_) + hex_size()/3;
|
||||
const int eastx = westx + hex_size()/3;
|
||||
const int centery = (get_location_y(res) - map_area().y + ypos_) + hex_size()/2;
|
||||
|
||||
const bool west = x < westx;
|
||||
const bool east = x > eastx;
|
||||
const bool north = y < centery;
|
||||
|
||||
if(north && west) {
|
||||
*nearest_hex = gamemap::location::NORTH_WEST;
|
||||
} else if(north && east) {
|
||||
*nearest_hex = gamemap::location::NORTH_EAST;
|
||||
} else if(north) {
|
||||
*nearest_hex = gamemap::location::NORTH;
|
||||
} else if(west) {
|
||||
*nearest_hex = gamemap::location::SOUTH_WEST;
|
||||
} else if(east) {
|
||||
*nearest_hex = gamemap::location::SOUTH_EAST;
|
||||
} else {
|
||||
*nearest_hex = gamemap::location::SOUTH;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int display::get_location_x(const gamemap::location& loc) const
|
||||
|
@ -952,11 +978,7 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
|
|||
<< (at_it->range() == attack_type::SHORT_RANGE ?
|
||||
_("melee") :
|
||||
_("ranged"));
|
||||
|
||||
if(at_it->hexes() > 1) {
|
||||
details << " (" << at_it->hexes() << ")";
|
||||
}
|
||||
|
||||
|
||||
details << "\n\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -138,12 +138,12 @@ public:
|
|||
//given x,y co-ordinates of an onscreen pixel, will return the
|
||||
//location of the hex that this pixel corresponds to. Returns an
|
||||
//invalid location is the mouse isn't over any valid location.
|
||||
gamemap::location hex_clicked_on(int x, int y);
|
||||
gamemap::location hex_clicked_on(int x, int y, gamemap::location::DIRECTION* nearest_hex);
|
||||
|
||||
//given x,y co-ordinates of a pixel on the map, will return the
|
||||
//location of the hex that this pixel corresponds to. Returns an
|
||||
//invalid location is the mouse isn't over any valid location.
|
||||
gamemap::location pixel_position_to_hex(int x, int y);
|
||||
gamemap::location pixel_position_to_hex(int x, int y, gamemap::location::DIRECTION* nearest_hex);
|
||||
|
||||
//given x,y co-ordinates of the mouse, will return the location of the
|
||||
//hex in the minimap that the mouse is currently over, or an invalid
|
||||
|
|
|
@ -1549,7 +1549,7 @@ void help_menu::select_topic(const topic &t) {
|
|||
}
|
||||
|
||||
int help_menu::process() {
|
||||
int res = gui::menu::process();
|
||||
int res = menu::process();
|
||||
if (double_clicked())
|
||||
res = selection();
|
||||
if (!visible_items_.empty() && (unsigned)res < visible_items_.size()) {
|
||||
|
|
|
@ -133,7 +133,7 @@ height_map generate_height_map(size_t width, size_t height,
|
|||
if(island_size != 0) {
|
||||
const size_t diffx = abs(x1 - int(center_x));
|
||||
const size_t diffy = abs(y1 - int(center_y));
|
||||
const size_t dist = size_t(std::sqrt(double(diffx*diffx + diffy*diffy)));
|
||||
const size_t dist = size_t(sqrt(double(diffx*diffx + diffy*diffy)));
|
||||
is_valley = dist > island_size;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ height_map generate_height_map(size_t width, size_t height,
|
|||
const int xdiff = (x2-x1);
|
||||
const int ydiff = (y2-y1);
|
||||
|
||||
const int height = radius - int(std::sqrt(double(xdiff*xdiff + ydiff*ydiff)));
|
||||
const int height = radius - int(sqrt(double(xdiff*xdiff + ydiff*ydiff)));
|
||||
|
||||
if(height > 0) {
|
||||
if(is_valley) {
|
||||
|
|
|
@ -145,7 +145,7 @@ turn_info::turn_info(game_data& gameinfo, game_state& state_of_game,
|
|||
key_(key), gui_(gui), map_(map), teams_(teams), team_num_(team_num),
|
||||
units_(units), browse_(mode != PLAY_TURN), allow_network_commands_(mode == BROWSE_NETWORKED),
|
||||
left_button_(false), right_button_(false), middle_button_(false),
|
||||
minimap_scrolling_(false), enemy_paths_(false),
|
||||
minimap_scrolling_(false), enemy_paths_(false), last_nearest_(gamemap::location::NORTH),
|
||||
path_turns_(0), end_turn_(false), start_ncmd_(-1), textbox_(textbox), replay_sender_(replay_sender)
|
||||
{
|
||||
enemies_visible_ = enemies_visible();
|
||||
|
@ -285,10 +285,11 @@ void turn_info::mouse_motion(const SDL_MouseMotionEvent& event)
|
|||
if(minimap_scrolling_) return;
|
||||
}
|
||||
|
||||
gamemap::location::DIRECTION nearest_hex;
|
||||
const team& current_team = teams_[team_num_-1];
|
||||
const gamemap::location new_hex = gui_.hex_clicked_on(event.x,event.y);
|
||||
const gamemap::location new_hex = gui_.hex_clicked_on(event.x,event.y,&nearest_hex);
|
||||
|
||||
if(new_hex != last_hex_) {
|
||||
if(new_hex != last_hex_ || nearest_hex != last_nearest_) {
|
||||
if(new_hex.valid() == false) {
|
||||
current_route_.steps.clear();
|
||||
gui_.set_route(NULL);
|
||||
|
@ -305,7 +306,8 @@ void turn_info::mouse_motion(const SDL_MouseMotionEvent& event)
|
|||
|
||||
gamemap::location attack_from;
|
||||
if(selected_unit != units_.end() && mouseover_unit != units_.end()) {
|
||||
attack_from = current_unit_attacks_from(new_hex);
|
||||
const gamemap::location preferred = new_hex.get_direction(nearest_hex);
|
||||
attack_from = current_unit_attacks_from(new_hex,&preferred);
|
||||
}
|
||||
|
||||
if(selected_unit != units_.end() && (current_paths_.routes.count(new_hex) ||
|
||||
|
@ -330,8 +332,7 @@ void turn_info::mouse_motion(const SDL_MouseMotionEvent& event)
|
|||
if(new_hex == selected_hex_) {
|
||||
current_route_.steps.clear();
|
||||
gui_.set_route(NULL);
|
||||
} else if(new_hex != last_hex_ &&
|
||||
!current_paths_.routes.empty() && map_.on_board(selected_hex_) &&
|
||||
} else if(!current_paths_.routes.empty() && map_.on_board(selected_hex_) &&
|
||||
map_.on_board(new_hex)) {
|
||||
|
||||
const gamemap::location& dest = attack_from.valid() ? attack_from : new_hex;
|
||||
|
@ -339,7 +340,7 @@ void turn_info::mouse_motion(const SDL_MouseMotionEvent& event)
|
|||
unit_map::const_iterator un = find_unit(selected_hex_);
|
||||
const unit_map::const_iterator dest_un = find_unit(dest);
|
||||
|
||||
if(un != units_.end() && dest_un == units_.end()) {
|
||||
if((new_hex != last_hex_ || attack_from.valid()) && un != units_.end() && dest_un == units_.end()) {
|
||||
const shortest_path_calculator calc(un->second,current_team,
|
||||
visible_units(),teams_,map_,status_);
|
||||
const bool can_teleport = un->second.type().teleports();
|
||||
|
@ -380,6 +381,7 @@ void turn_info::mouse_motion(const SDL_MouseMotionEvent& event)
|
|||
}
|
||||
|
||||
last_hex_ = new_hex;
|
||||
last_nearest_ = nearest_hex;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -575,7 +577,6 @@ bool turn_info::attack_enemy(unit_map::iterator attacker, unit_map::iterator def
|
|||
std::vector<std::string> items;
|
||||
|
||||
const int range = distance_between(attacker->first,defender->first);
|
||||
std::vector<int> attacks_in_range;
|
||||
|
||||
int best_weapon_index = -1;
|
||||
simple_attack_rating best_weapon_rating;
|
||||
|
@ -583,10 +584,6 @@ bool turn_info::attack_enemy(unit_map::iterator attacker, unit_map::iterator def
|
|||
attack_calculations_displayer::stats_vector stats;
|
||||
|
||||
for(size_t a = 0; a != attacks.size(); ++a) {
|
||||
if(attacks[a].hexes() < range)
|
||||
continue;
|
||||
|
||||
attacks_in_range.push_back(a);
|
||||
|
||||
battle_stats_strings sts;
|
||||
battle_stats st = evaluate_battle_stats(map_, attacker_loc, defender_loc,
|
||||
|
@ -650,8 +647,7 @@ bool turn_info::attack_enemy(unit_map::iterator attacker, unit_map::iterator def
|
|||
|
||||
cursor::set(cursor::NORMAL);
|
||||
|
||||
if(size_t(res) < attacks_in_range.size()) {
|
||||
res = attacks_in_range[res];
|
||||
if(size_t(res) < attacks.size()) {
|
||||
|
||||
attacker->second.set_goto(gamemap::location());
|
||||
clear_undo_stack();
|
||||
|
@ -770,7 +766,8 @@ void turn_info::left_click(const SDL_MouseButtonEvent& event)
|
|||
return;
|
||||
}
|
||||
|
||||
gamemap::location hex = gui_.hex_clicked_on(event.x,event.y);
|
||||
gamemap::location::DIRECTION nearest_hex;
|
||||
gamemap::location hex = gui_.hex_clicked_on(event.x,event.y,&nearest_hex);
|
||||
|
||||
unit_map::iterator u = find_unit(selected_hex_);
|
||||
|
||||
|
@ -787,9 +784,13 @@ void turn_info::left_click(const SDL_MouseButtonEvent& event)
|
|||
|
||||
unit_map::iterator enemy = find_unit(hex);
|
||||
|
||||
const gamemap::location src = selected_hex_;
|
||||
paths orig_paths = current_paths_;
|
||||
|
||||
//see if we're trying to do a move-and-attack
|
||||
if(!browse_ && u != units_.end() && enemy != units_.end()) {
|
||||
const gamemap::location& attack_from = current_unit_attacks_from(hex);
|
||||
const gamemap::location preferred = hex.get_direction(nearest_hex);
|
||||
const gamemap::location& attack_from = current_unit_attacks_from(hex,&preferred);
|
||||
if(attack_from.valid()) {
|
||||
if(move_unit_along_current_route(false)) { //move the unit without updating shroud
|
||||
u = find_unit(attack_from);
|
||||
|
@ -798,6 +799,10 @@ void turn_info::left_click(const SDL_MouseButtonEvent& event)
|
|||
enemy != units_.end() && current_team().is_enemy(enemy->second.side())) {
|
||||
if(attack_enemy(u,enemy) == false) {
|
||||
undo();
|
||||
selected_hex_ = src;
|
||||
gui_.select_hex(src);
|
||||
current_paths_ = orig_paths;
|
||||
gui_.set_paths(¤t_paths_);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -883,16 +888,15 @@ void turn_info::show_attack_options(unit_map::const_iterator u)
|
|||
if(u == units_.end() || u->second.can_attack() == false)
|
||||
return;
|
||||
|
||||
const int range = u->second.longest_range();
|
||||
for(unit_map::const_iterator target = units_.begin(); target != units_.end(); ++target) {
|
||||
if(current_team.is_enemy(target->second.side()) &&
|
||||
distance_between(target->first,u->first) <= range && !target->second.stone()) {
|
||||
distance_between(target->first,u->first) == 1 && !target->second.stone()) {
|
||||
current_paths_.routes[target->first] = paths::route();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gamemap::location turn_info::current_unit_attacks_from(const gamemap::location& loc) const
|
||||
gamemap::location turn_info::current_unit_attacks_from(const gamemap::location& loc, const gamemap::location* preferred) const
|
||||
{
|
||||
const unit_map::const_iterator current = find_unit(selected_hex_);
|
||||
if(current == units_.end() || current->second.side() != team_num_) {
|
||||
|
@ -922,7 +926,7 @@ gamemap::location turn_info::current_unit_attacks_from(const gamemap::location&
|
|||
}
|
||||
|
||||
if(current_paths_.routes.count(adj[n])) {
|
||||
const int defense = current->second.defense_modifier(map_,map_.get_terrain(loc));
|
||||
const int defense = preferred != NULL && *preferred == adj[n] ? 0 : current->second.defense_modifier(map_,map_.get_terrain(loc));
|
||||
if(defense < best_defense || res.valid() == false) {
|
||||
best_defense = defense;
|
||||
res = adj[n];
|
||||
|
|
|
@ -189,7 +189,7 @@ private:
|
|||
//function which, given the location of a potential enemy to attack, will return the location
|
||||
//that the currently selected unit would move to and attack it from this turn. Returns an
|
||||
//invalid location if not possible.
|
||||
gamemap::location current_unit_attacks_from(const gamemap::location& loc) const;
|
||||
gamemap::location current_unit_attacks_from(const gamemap::location& loc, const gamemap::location* preferred) const;
|
||||
|
||||
bool attack_enemy(unit_map::iterator attacker, unit_map::iterator defender);
|
||||
bool move_unit_along_current_route(bool check_shroud=true);
|
||||
|
@ -227,6 +227,7 @@ private:
|
|||
paths::route current_route_;
|
||||
bool enemy_paths_;
|
||||
gamemap::location last_hex_;
|
||||
gamemap::location::DIRECTION last_nearest_;
|
||||
gamemap::location selected_hex_;
|
||||
undo_list undo_stack_;
|
||||
undo_list redo_stack_;
|
||||
|
|
|
@ -233,10 +233,6 @@ Units cannot be killed by poison alone. The poison will not reduce it below 1 HP
|
|||
tooltip << at_it->damage() << " " << _("damage") << ", "
|
||||
<< at_it->num_attacks() << " " << _("attacks");
|
||||
|
||||
if(at_it->hexes() > 1) {
|
||||
str << " (" << at_it->hexes() << ")";
|
||||
tooltip << ", " << at_it->hexes() << " " << _("hexes");
|
||||
}
|
||||
str << "\n";
|
||||
res.add_text(str,tooltip);
|
||||
}
|
||||
|
|
|
@ -186,12 +186,12 @@ surface scale_surface_blended(surface surf, int w, int h)
|
|||
//we now have a rectangle, (xsrc,ysrc,xratio,yratio) which we
|
||||
//want to derive the pixel from
|
||||
for(double xloc = xsrc; xloc < xsrc+xratio; xloc += 1.0) {
|
||||
const double xsize = minimum<double>(std::floor(xloc+1.0)-xloc,xsrc+xratio-xloc);
|
||||
const double xsize = minimum<double>(floor(xloc+1.0)-xloc,xsrc+xratio-xloc);
|
||||
for(double yloc = ysrc; yloc < ysrc+yratio; yloc += 1.0) {
|
||||
const int xsrcint = maximum<int>(0,minimum<int>(src->w-1,static_cast<int>(xsrc)));
|
||||
const int ysrcint = maximum<int>(0,minimum<int>(src->h-1,static_cast<int>(ysrc)));
|
||||
|
||||
const double ysize = minimum<double>(std::floor(yloc+1.0)-yloc,ysrc+yratio-yloc);
|
||||
const double ysize = minimum<double>(floor(yloc+1.0)-yloc,ysrc+yratio-yloc);
|
||||
|
||||
Uint8 r,g,b,a;
|
||||
|
||||
|
|
23
src/unit.cpp
23
src/unit.cpp
|
@ -800,29 +800,6 @@ const std::vector<attack_type>& unit::attacks() const
|
|||
return attacks_;
|
||||
}
|
||||
|
||||
int unit::longest_range() const
|
||||
{
|
||||
int res = 0;
|
||||
for(std::vector<attack_type>::const_iterator i = attacks_.begin(); i != attacks_.end(); ++i) {
|
||||
if(i->hexes() >= res) {
|
||||
res = i->hexes();
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<attack_type> unit::attacks_at_range(int range) const
|
||||
{
|
||||
std::vector<attack_type> res;
|
||||
for(std::vector<attack_type>::const_iterator i = attacks_.begin(); i != attacks_.end(); ++i) {
|
||||
if(i->hexes() >= range)
|
||||
res.push_back(*i);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unit::movement_cost(const gamemap& map, gamemap::TERRAIN terrain) const
|
||||
{
|
||||
//don't allow level 0 units to take villages - removed until AI
|
||||
|
|
|
@ -106,8 +106,6 @@ public:
|
|||
void assign_role(const std::string& role);
|
||||
|
||||
const std::vector<attack_type>& attacks() const;
|
||||
int longest_range() const;
|
||||
std::vector<attack_type> attacks_at_range(int range) const;
|
||||
|
||||
int movement_cost(const gamemap& map, gamemap::TERRAIN terrain) const;
|
||||
int defense_modifier(const gamemap& map, gamemap::TERRAIN terrain) const;
|
||||
|
|
Loading…
Add table
Reference in a new issue