mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-08 19:14:17 +00:00
fix crash on next scenario, thx to Rhuvaen
This commit is contained in:
parent
28deba32c1
commit
1a3b86cc6b
@ -6,6 +6,7 @@ Version 1.3.4+svn:
|
|||||||
* multiplayer:
|
* multiplayer:
|
||||||
* revised maps: Cynsaun Battlefield, Hamlets, Sablestone Delta, Silverhead
|
* revised maps: Cynsaun Battlefield, Hamlets, Sablestone Delta, Silverhead
|
||||||
Crossing, Sulla's Ruins
|
Crossing, Sulla's Ruins
|
||||||
|
* fix MP crash on next scenario thanks to Rhuvaen
|
||||||
* user interface:
|
* user interface:
|
||||||
* allow unfocused widgets to steal the focus instead of just borrowing it
|
* allow unfocused widgets to steal the focus instead of just borrowing it
|
||||||
* frequency of idle animations halved.
|
* frequency of idle animations halved.
|
||||||
|
@ -456,7 +456,7 @@ game_state::game_state(const game_data& data, const config& cfg)
|
|||||||
//backwards compatibility for 1.2 and 1.2.1,
|
//backwards compatibility for 1.2 and 1.2.1,
|
||||||
//------------------------------------------
|
//------------------------------------------
|
||||||
//add recall list units to the snapshot so they don't get lost
|
//add recall list units to the snapshot so they don't get lost
|
||||||
if (!snapshot->empty() && (version < "1.2.2") )
|
if ((snapshot!=NULL) && (!snapshot->empty() && (version < "1.2.2") ) )
|
||||||
{
|
{
|
||||||
//find the side of this player in the snapshot
|
//find the side of this player in the snapshot
|
||||||
config* current_side = NULL;
|
config* current_side = NULL;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "wassert.hpp"
|
#include "wassert.hpp"
|
||||||
#include "wml_separators.hpp"
|
#include "wml_separators.hpp"
|
||||||
#include "sdl_utils.hpp"
|
#include "sdl_utils.hpp"
|
||||||
|
#include "pathutils.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
@ -1088,7 +1089,7 @@ void mouse_handler::left_click(const SDL_MouseButtonEvent& event, const bool bro
|
|||||||
unit_map::iterator u = find_unit(selected_hex_);
|
unit_map::iterator u = find_unit(selected_hex_);
|
||||||
|
|
||||||
//if the unit is selected and then itself clicked on,
|
//if the unit is selected and then itself clicked on,
|
||||||
//any goto command is cancelled
|
//any goto command is canceled
|
||||||
if(u != units_.end() && !browse && selected_hex_ == hex && u->second.side() == team_num_) {
|
if(u != units_.end() && !browse && selected_hex_ == hex && u->second.side() == team_num_) {
|
||||||
u->second.set_goto(gamemap::location());
|
u->second.set_goto(gamemap::location());
|
||||||
}
|
}
|
||||||
@ -1114,7 +1115,7 @@ void mouse_handler::left_click(const SDL_MouseButtonEvent& event, const bool bro
|
|||||||
enemy = find_unit(hex);
|
enemy = find_unit(hex);
|
||||||
if(u != units_.end() && u->second.side() == team_num_ &&
|
if(u != units_.end() && u->second.side() == team_num_ &&
|
||||||
enemy != units_.end() && current_team().is_enemy(enemy->second.side()) && !enemy->second.incapacitated()) {
|
enemy != units_.end() && current_team().is_enemy(enemy->second.side()) && !enemy->second.incapacitated()) {
|
||||||
//if shroud or fog is active, rememember nits a and after attack check if someone isn`t seen
|
//if shroud or fog is active, remember nits a and after attack check if someone isn`t seen
|
||||||
std::set<gamemap::location> known_units;
|
std::set<gamemap::location> known_units;
|
||||||
|
|
||||||
if (teams_[team_num_-1].uses_shroud() || teams_[team_num_-1].uses_fog()){
|
if (teams_[team_num_-1].uses_shroud() || teams_[team_num_-1].uses_fog()){
|
||||||
@ -1429,7 +1430,7 @@ void mouse_handler::show_attack_options(unit_map::const_iterator u)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mouse_handler::unit_in_cycle(unit_map::const_iterator it)
|
bool mouse_handler::unit_is_cyclable(unit_map::const_iterator it)
|
||||||
{
|
{
|
||||||
if(it->second.side() == team_num_ && unit_can_move(it->first,units_,map_,teams_) && it->second.user_end_turn() == false && !gui_->fogged(it->first)) {
|
if(it->second.side() == team_num_ && unit_can_move(it->first,units_,map_,teams_) && it->second.user_end_turn() == false && !gui_->fogged(it->first)) {
|
||||||
bool is_enemy = current_team().is_enemy(int(gui_->viewing_team()+1));
|
bool is_enemy = current_team().is_enemy(int(gui_->viewing_team()+1));
|
||||||
@ -1437,46 +1438,117 @@ bool mouse_handler::unit_in_cycle(unit_map::const_iterator it)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOCAL_VARIABLES \
|
// Assign a label to any unlabeled units on our team by incrementally labeling
|
||||||
unit_map::const_iterator it = units_.find(next_unit_);\
|
// the unlabeled units closest to the max labeled unit.
|
||||||
const unit_map::const_iterator itx = it;\
|
void mouse_handler::put_uncycled_units_in_cycle() {
|
||||||
const unit_map::const_iterator begin = units_.begin();\
|
bool any_uncycled_units;
|
||||||
const unit_map::const_iterator end = units_.end()
|
|
||||||
|
|
||||||
void mouse_handler::cycle_units()
|
|
||||||
{
|
|
||||||
LOCAL_VARIABLES;
|
|
||||||
|
|
||||||
if (it == end) {
|
|
||||||
for (it = begin; it != end && !unit_in_cycle(it); ++it);
|
|
||||||
} else {
|
|
||||||
do {
|
do {
|
||||||
++it;
|
any_uncycled_units = false;
|
||||||
if (it == end) it = begin;
|
int max_cycle_number = 0;
|
||||||
} while (it != itx && !unit_in_cycle(it));
|
unit_map::const_iterator max_labelled_unit = units_.begin();
|
||||||
|
unit_map::iterator some_unlabelled_unit;
|
||||||
|
|
||||||
|
// See if any units are not in the cycle yet, and find one
|
||||||
|
// of them, as well as the maximum currently labeled unit.
|
||||||
|
for (unit_map::iterator it = units_.begin(); it != units_.end(); ++it) {
|
||||||
|
if (unit_is_cyclable(it)) {
|
||||||
|
if (it->second.get_cycle_number() == 0) {
|
||||||
|
any_uncycled_units = true;
|
||||||
|
some_unlabelled_unit = it;
|
||||||
|
} else if (it->second.get_cycle_number() > max_cycle_number) {
|
||||||
|
max_cycle_number = it->second.get_cycle_number();
|
||||||
|
max_labelled_unit = it;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
select_unit(it, itx);
|
// Assign new max label to the unit closest to the currently
|
||||||
|
// max labeled unit if such a unit exists, otherwise just
|
||||||
|
// label an arbitrary unlabeled unit.
|
||||||
|
if (any_uncycled_units) {
|
||||||
|
unit_map::iterator next_to_label;
|
||||||
|
if (max_labelled_unit != units_.end()) {
|
||||||
|
next_to_label = closest_friendly_unit(max_labelled_unit);
|
||||||
|
} else {
|
||||||
|
next_to_label = some_unlabelled_unit;
|
||||||
|
}
|
||||||
|
next_to_label->second.set_cycle_number(max_cycle_number + 1);
|
||||||
|
}
|
||||||
|
} while (any_uncycled_units);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouse_handler::cycle_back_units()
|
unit_map::iterator mouse_handler::closest_friendly_unit(unit_map::const_iterator prev) {
|
||||||
{
|
int min_dist = 10000;
|
||||||
LOCAL_VARIABLES;
|
unit_map::iterator ret;
|
||||||
|
for (unit_map::iterator it = units_.begin(); it != units_.end(); ++it) {
|
||||||
if (it == end) {
|
if (unit_is_cyclable(it) && it->second.get_cycle_number() == 0) {
|
||||||
while (it != begin && !unit_in_cycle(--it));
|
int cur_dist = distance_between(prev->first, it->first);
|
||||||
if (!unit_in_cycle(it)) it = itx;
|
if (cur_dist < min_dist) {
|
||||||
} else {
|
min_dist = cur_dist;
|
||||||
do {
|
ret = it;
|
||||||
if (it == begin) it = end;
|
}
|
||||||
--it;
|
}
|
||||||
} while (it != itx && !unit_in_cycle(it));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
select_unit(it, itx);
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can think of greater as using its intuitive meaning. When greater is
|
||||||
|
// actually referencing less_than, the logic is the same. The direction
|
||||||
|
// along the cycle that the selected unit is picked just moves the other way.
|
||||||
|
// greater(extreme_val, y) should be true for all reasonable y.
|
||||||
|
void mouse_handler::cycle_units_using_advance_func(int extreme_val, advances_func greater) {
|
||||||
|
put_uncycled_units_in_cycle();
|
||||||
|
unit_map::iterator itx = units_.find(next_unit_);
|
||||||
|
if (itx == units_.end()) {
|
||||||
|
// Nothing selected before.
|
||||||
|
itx = units_.begin();
|
||||||
|
}
|
||||||
|
unit_map::iterator next = units_.end();
|
||||||
|
int next_cyc_num = extreme_val;
|
||||||
|
int cur_cyc_num = itx->second.get_cycle_number();
|
||||||
|
// Find the next unit, that is probably going to be the unit that has
|
||||||
|
// minimum label amongst all those greater than cur_cyc_num.
|
||||||
|
for (unit_map::iterator it = units_.begin(); it != units_.end(); ++it) {
|
||||||
|
if (unit_is_cyclable(it) &&
|
||||||
|
greater(it->second.get_cycle_number(), cur_cyc_num) &&
|
||||||
|
greater(next_cyc_num, it->second.get_cycle_number())) {
|
||||||
|
next = it;
|
||||||
|
next_cyc_num = next->second.get_cycle_number();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Unless there are no units greater than cur_cyc_num, in which case the
|
||||||
|
// cycle should start from the minimum.
|
||||||
|
if (next == units_.end()) {
|
||||||
|
for (unit_map::iterator it = units_.begin(); it != units_.end(); ++it) {
|
||||||
|
if (unit_is_cyclable(it) &&
|
||||||
|
greater(next_cyc_num, it->second.get_cycle_number())) {
|
||||||
|
next = it;
|
||||||
|
next_cyc_num = next->second.get_cycle_number();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (next != units_.end()) {
|
||||||
|
select_unit(next, itx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool greater_than(int x, int y) {
|
||||||
|
return x > y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_handler::cycle_units() {
|
||||||
|
cycle_units_using_advance_func(1000000, greater_than);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool less_than(int x, int y) {
|
||||||
|
return x < y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_handler::cycle_back_units() {
|
||||||
|
cycle_units_using_advance_func(0, less_than);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mouse_handler::select_unit(const unit_map::const_iterator &it,
|
inline void mouse_handler::select_unit(const unit_map::const_iterator &it,
|
||||||
|
@ -81,7 +81,12 @@ private:
|
|||||||
gamemap::location current_unit_attacks_from(const gamemap::location& loc);
|
gamemap::location current_unit_attacks_from(const gamemap::location& loc);
|
||||||
unit_map::const_iterator find_unit(const gamemap::location& hex) const;
|
unit_map::const_iterator find_unit(const gamemap::location& hex) const;
|
||||||
unit_map::iterator find_unit(const gamemap::location& hex);
|
unit_map::iterator find_unit(const gamemap::location& hex);
|
||||||
bool unit_in_cycle(unit_map::const_iterator it);
|
bool unit_is_cyclable(unit_map::const_iterator it);
|
||||||
|
unit_map::iterator closest_friendly_unit(unit_map::const_iterator prev);
|
||||||
|
void put_uncycled_units_in_cycle();
|
||||||
|
typedef bool (*advances_func)(int, int);
|
||||||
|
|
||||||
|
void cycle_units_using_advance_func(int extreme_val, advances_func greater);
|
||||||
void select_unit(const unit_map::const_iterator &it, const unit_map::const_iterator &bound);
|
void select_unit(const unit_map::const_iterator &it, const unit_map::const_iterator &bound);
|
||||||
|
|
||||||
game_display* gui_;
|
game_display* gui_;
|
||||||
|
@ -175,6 +175,7 @@ unit::unit(const unit& o):
|
|||||||
draw_bars_(o.draw_bars_),
|
draw_bars_(o.draw_bars_),
|
||||||
|
|
||||||
modifications_(o.modifications_),
|
modifications_(o.modifications_),
|
||||||
|
cycle_number_(0),
|
||||||
gamedata_(o.gamedata_),
|
gamedata_(o.gamedata_),
|
||||||
units_(o.units_),
|
units_(o.units_),
|
||||||
map_(o.map_),
|
map_(o.map_),
|
||||||
@ -201,6 +202,7 @@ unit::unit(const game_data* gamedata, unit_map* unitmap, const gamemap* map,
|
|||||||
refreshing_ = false;
|
refreshing_ = false;
|
||||||
hidden_ = false;
|
hidden_ = false;
|
||||||
offset_ = 0;
|
offset_ = 0;
|
||||||
|
cycle_number_ = 0;
|
||||||
if(race_->not_living()) {
|
if(race_->not_living()) {
|
||||||
set_state("not_living","yes");
|
set_state("not_living","yes");
|
||||||
}
|
}
|
||||||
@ -220,6 +222,7 @@ unit::unit(const game_data& gamedata,const config& cfg) : movement_(0),
|
|||||||
refreshing_ = false;
|
refreshing_ = false;
|
||||||
hidden_ = false;
|
hidden_ = false;
|
||||||
offset_ = 0;
|
offset_ = 0;
|
||||||
|
cycle_number_ = 0;
|
||||||
if(race_->not_living()) {
|
if(race_->not_living()) {
|
||||||
set_state("not_living","yes");
|
set_state("not_living","yes");
|
||||||
}
|
}
|
||||||
@ -332,6 +335,7 @@ unit::unit(const unit_type* t, int side, bool use_traits, bool dummy_unit, unit_
|
|||||||
end_turn_ = false;
|
end_turn_ = false;
|
||||||
hold_position_ = false;
|
hold_position_ = false;
|
||||||
offset_ = 0;
|
offset_ = 0;
|
||||||
|
cycle_number_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unit::~unit()
|
unit::~unit()
|
||||||
|
@ -297,6 +297,9 @@ class unit
|
|||||||
unit_race::GENDER generate_gender(const unit_type& type, bool gen);
|
unit_race::GENDER generate_gender(const unit_type& type, bool gen);
|
||||||
std::string image_mods() const;
|
std::string image_mods() const;
|
||||||
|
|
||||||
|
void set_cycle_number(int cyc_no) { cycle_number_ = cyc_no; }
|
||||||
|
int get_cycle_number() const { return cycle_number_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool internal_matches_filter(const vconfig& cfg,const gamemap::location& loc,
|
bool internal_matches_filter(const vconfig& cfg,const gamemap::location& loc,
|
||||||
@ -405,6 +408,8 @@ class unit
|
|||||||
|
|
||||||
config modifications_;
|
config modifications_;
|
||||||
|
|
||||||
|
int cycle_number_;
|
||||||
|
|
||||||
friend void attack_type::set_specials_context(const gamemap::location& loc,const unit& un) const;
|
friend void attack_type::set_specials_context(const gamemap::location& loc,const unit& un) const;
|
||||||
const game_data* gamedata_;
|
const game_data* gamedata_;
|
||||||
const unit_map* units_;
|
const unit_map* units_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user