Make status orb work with custom max/min_range (#9255)

This code sets orb color to can-still-make-an-action if unit has no moves left,
and has a visible enemy within max and min range of a weapon.  This also affects
if the unit is selectable with 'N' (units that can move or attack).

Currently, it doesn't affect the mainline much, as no unit has a weapon
max/min_range different from 1, most notice-able, it marks units with no attack
as incapable of action, after having no moves left.

The purpose of this is part of getting real-ranged attacks into the mainline.
This commit is contained in:
ZombieKnight 2024-09-14 19:07:54 +02:00 committed by GitHub
parent ed354c1d41
commit 4f7ae435dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -87,21 +87,47 @@ display_context::can_move_result display_context::unit_can_move(const unit& u) c
const team& current_team = get_team(u.side());
can_move_result result = {false, false};
for(const map_location& adj : get_adjacent_tiles(u.get_location())) {
if (map().on_board(adj)) {
if(!result.attack_here) {
const unit_map::const_iterator i = units().find(adj);
if (i.valid() && !i->incapacitated() && current_team.is_enemy(i->side())) {
result.attack_here = true;
if(u.attacks_left() > 0 && !u.attacks().empty()) {
const auto& attacks = u.attacks();
std::set<int> attackable_distances;
for (const auto& attack : attacks) {
for (int i = attack.min_range(); i <= attack.max_range(); ++i) {
attackable_distances.insert(i);
}
}
if(!attackable_distances.empty()) {
int max_distance = *std::prev(attackable_distances.end());
for (int dx = -max_distance; dx <= max_distance; ++dx) {
for (int dy = -max_distance; dy <= max_distance && !result.attack_here; ++dy) {
// Adjust for hex grid
int adjusted_dy = dy + floor(dx / 2.0);
map_location locs(u.get_location().x + dx, u.get_location().y + adjusted_dy);
int distance = distance_between(u.get_location(), locs);
if (attackable_distances.find(distance) == attackable_distances.end()) {
continue;
}
if (map().on_board(locs)) {
const unit_map::const_iterator i = units().find(locs);
if (i.valid() && !i->incapacitated() && current_team.is_enemy(i->side()) && i->is_visible_to_team(get_team(u.side()), false)) {
result.attack_here = true;
}
}
}
}
}
}
for(const map_location& adj : get_adjacent_tiles(u.get_location())) {
if (map().on_board(adj)) {
if (!result.move && u.movement_cost(map()[adj]) <= u.movement_left()) {
result.move = true;
}
}
}
// This should probably check if the unit can teleport too
return result;