Skip to content

Commit

Permalink
Mouse events: don't keep around references to fighting units
Browse files Browse the repository at this point in the history
Keeping references is bad if a unit dies and the dying unit has a halo
and a long-running listener for the "last breath" event, like in AtS E2
S10. In that case keeping the reference means that the halo will remain
as long as the event runs.

Closes #3673.
  • Loading branch information
jyrkive committed Nov 2, 2018
1 parent a0cc8cb commit 53126f6
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 14 deletions.
48 changes: 34 additions & 14 deletions src/mouse_events.cpp
Expand Up @@ -633,6 +633,18 @@ unit_map::const_iterator mouse_handler::find_unit(const map_location& hex) const
return pc_.gamestate().board_.find_visible_unit(hex, viewing_team());
}

unit* mouse_handler::find_unit_nonowning(const map_location& hex)
{
unit_map::iterator it = pc_.gamestate().board_.find_visible_unit(hex, viewing_team());
return it.valid() ? &*it : nullptr;
}

const unit* mouse_handler::find_unit_nonowning(const map_location& hex) const
{
unit_map::const_iterator it = pc_.gamestate().board_.find_visible_unit(hex, viewing_team());
return it.valid() ? &*it : nullptr;
}

const map_location mouse_handler::hovered_hex() const
{
int x = -1;
Expand Down Expand Up @@ -833,7 +845,7 @@ void mouse_handler::move_action(bool browse)
// }

unit_map::iterator u;
unit_map::iterator clicked_u;
const unit* clicked_u = nullptr;

map_location src;
pathfind::paths orig_paths;
Expand All @@ -849,7 +861,7 @@ void mouse_handler::move_action(bool browse)
u->set_goto(map_location());
}

clicked_u = find_unit(hex);
clicked_u = find_unit_nonowning(hex);

src = selected_hex_;
orig_paths = current_paths_;
Expand All @@ -863,7 +875,7 @@ void mouse_handler::move_action(bool browse)
return;
}

if(((u.valid() && u->side() == side_num_) || pc_.get_whiteboard()->is_active()) && clicked_u.valid()) {
if(((u.valid() && u->side() == side_num_) || pc_.get_whiteboard()->is_active()) && clicked_u != nullptr) {
if(attack_from == selected_hex_) { // no move needed
int choice = -1;
{
Expand Down Expand Up @@ -988,7 +1000,7 @@ void mouse_handler::move_action(bool browse)
} else {
// Don't move if the unit already has actions
// from the whiteboard.
if(pc_.get_whiteboard()->unit_has_actions(u ? &*u : &*clicked_u)) {
if(pc_.get_whiteboard()->unit_has_actions(u ? &*u : clicked_u)) {
return;
}

Expand Down Expand Up @@ -1307,18 +1319,26 @@ void mouse_handler::attack_enemy_(const map_location& att_loc, const map_locatio
const map_location attacker_loc = att_loc;
const map_location defender_loc = def_loc;

unit_map::iterator attacker = find_unit(attacker_loc);
if(!attacker || attacker->side() != side_num_ || attacker->incapacitated()) {
return;
}
unit* attacker = nullptr;
const unit* defender = nullptr;
std::vector<battle_context> bc_vector;

unit_map::iterator defender = find_unit(defender_loc);
if(!defender || current_team().is_enemy(defender->side()) == false || defender->incapacitated()) {
return;
}
{
unit_map::iterator attacker_it = find_unit(attacker_loc);
if(!attacker_it || attacker_it->side() != side_num_ || attacker_it->incapacitated()) {
return;
}

std::vector<battle_context> bc_vector;
fill_weapon_choices(bc_vector, attacker, defender);
unit_map::iterator defender_it = find_unit(defender_loc);
if(!defender_it || current_team().is_enemy(defender_it->side()) == false || defender_it->incapacitated()) {
return;
}

fill_weapon_choices(bc_vector, attacker_it, defender_it);

attacker = &*attacker_it;
defender = &*defender_it;
}

if(size_t(choice) >= bc_vector.size()) {
return;
Expand Down
6 changes: 6 additions & 0 deletions src/mouse_events.hpp
Expand Up @@ -148,6 +148,12 @@ class mouse_handler : public mouse_handler_base {
void show_attack_options(const unit_map::const_iterator &u);
unit_map::const_iterator find_unit(const map_location& hex) const;
unit_map::iterator find_unit(const map_location& hex);
/*
* These return raw pointers instead of smart pointers.
* Useful if you don't want to increase the unit reference count.
*/
unit* find_unit_nonowning(const map_location& hex);
const unit* find_unit_nonowning(const map_location& hex) const;
bool unit_in_cycle(unit_map::const_iterator it);
private:
team& viewing_team();
Expand Down

0 comments on commit 53126f6

Please sign in to comment.