Author: sapient
Date: Fri Dec 5 05:06:02 2008
New Revision: 31278
URL: http://svn.gna.org/viewcvs/wesnoth?rev=31278&view=rev
Log:
massive cleanup for the [role] code, including crash prevention for invalid
side numbers, consistent handling of precedence order, and removing excessive
config copy operations.
Modified:
trunk/src/config.hpp
trunk/src/game_events.cpp
Modified: trunk/src/config.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/config.hpp?rev=31278&r1=31277&r2=31278&view=diff
==============================================================================
--- trunk/src/config.hpp (original)
+++ trunk/src/config.hpp Fri Dec 5 05:06:02 2008
@@ -90,6 +90,7 @@
const t_string& get_attribute(const std::string& key) const;
bool has_attribute(const std::string& key) const {return
values.find(key) != values.end();}
+ void remove_attribute(const std::string& key) {values.erase(key);}
/**
* This should only be used if there is no mapping of the key already,
Modified: trunk/src/game_events.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/game_events.cpp?rev=31278&r1=31277&r2=31278&view=diff
==============================================================================
--- trunk/src/game_events.cpp (original)
+++ trunk/src/game_events.cpp Fri Dec 5 05:06:02 2008
@@ -1466,84 +1466,71 @@
WML_HANDLER_FUNCTION(role,/*handler*/,/*event_info*/,cfg)
{
-
- // Get a list of the types this unit can be
- std::vector<std::string> types = utils::split(cfg["type"]);
- if (types.size() == 0) types.push_back("");
-
- std::vector<std::string> sides = utils::split(cfg["side"]);
-
- // Iterate over all the types, and for each type,
- // try to find a unit that matches
- std::vector<std::string>::iterator ti;
- for(ti = types.begin(); ti != types.end(); ++ti) {
- config item = cfg.get_config();
- // Do not try to match an empty string
- if (!ti->empty()) {
+ bool found = false;
+
+ // role= represents the instruction, so we can't filter on it
+ config item = cfg.get_config();
+ item.remove_attribute("role");
+ vconfig filter(&item);
+
+ // try to match units on the gamemap before the recall lists
+ std::vector<std::string> types = utils::split(filter["type"]);
+ const bool has_any_types = !types.empty();
+ std::vector<std::string>::iterator ti = types.begin(),
+ ti_end = types.end();
+ // loop to give precendence based on type order
+ do {
+ if (has_any_types) {
item["type"] = *ti;
}
- item["role"] = "";
- vconfig filter(&item);
-
unit_map::iterator itor;
for(itor = units->begin(); itor != units->end();
++itor) {
if(game_events::unit_matches_filter(itor,
filter)) {
itor->second.assign_role(cfg["role"]);
+ found = true;
break;
}
}
-
- if(itor != units->end())
- break;
-
- bool found = false;
-
- if(sides.empty() == false) {
- std::vector<std::string>::const_iterator si;
- for(si = sides.begin(); si != sides.end();
++si) {
- int side_num =
lexical_cast_default<int>(*si,1);
- const std::string player_id =
(*teams)[side_num-1].save_id();
- player_info*
player=state_of_game->get_player(player_id);
-
- if(!player)
+ } while(!found && has_any_types && ++ti != ti_end);
+ if(!found) {
+ // next try to match units on the recall lists
+ std::set<std::string> player_ids;
+ std::vector<std::string> sides =
utils::split(cfg["side"]);
+ const bool has_any_sides = !sides.empty();
+ foreach(std::string const& side_str, sides) {
+ size_t side_num =
lexical_cast_default<size_t>(side_str,0);
+ if(side_num > 0 && side_num <= teams->size()) {
+
player_ids.insert((teams->begin()+(side_num-1))->save_id());
+ }
+ }
+ // loop to give precendence based on type order
+ std::vector<std::string>::iterator ti = types.begin();
+ do {
+ if (has_any_types) {
+ item["type"] = *ti;
+ }
+ std::map<std::string, player_info>::iterator pi,
+ pi_end = state_of_game->players.end();
+ for(pi=state_of_game->players.begin(); pi !=
pi_end; ++pi) {
+ std::string const& player_id =
pi->first;
+ player_info& p_info = pi->second;
+ // Verify the filter's side= includes
this player
+ if(has_any_sides &&
!player_ids.count(player_id)) {
continue;
-
- // Iterate over the units, and try to
find one that matches
- std::vector<unit>::iterator ui;
- for(ui =
player->available_units.begin();
- ui !=
player->available_units.end(); ++ui) {
-
ui->set_game_context(units,game_map,status_ptr,teams);
- scoped_recall_unit
auto_store("this_unit", player_id,
- (ui -
player->available_units.begin()));
-
if(game_events::unit_matches_filter(*ui, filter,map_location())) {
-
ui->assign_role(cfg["role"]);
+ }
+ // Iterate over the player's recall
list to find a match
+ for(size_t i=0; i <
p_info.available_units.size(); ++i) {
+ unit& u =
p_info.available_units[i];
+ u.set_game_context(units,
game_map, status_ptr, teams);
+ scoped_recall_unit
auto_store("this_unit", player_id, i);
+
if(game_events::unit_matches_filter(u, filter, map_location())) {
+
u.assign_role(cfg["role"]);
found=true;
break;
}
}
}
- } else {
- std::map<std::string, player_info>::iterator pi;
- for(pi=state_of_game->players.begin();
-
pi!=state_of_game->players.end(); ++pi) {
- std::vector<unit>::iterator ui;
- // Iterate over the units, and try to
find one that matches
- for(ui =
pi->second.available_units.begin();
- ui !=
pi->second.available_units.end(); ++ui) {
-
ui->set_game_context(units,game_map,status_ptr,teams);
- scoped_recall_unit
auto_store("this_unit", pi->first,
- (ui -
pi->second.available_units.begin()));
-
if(game_events::unit_matches_filter(*ui, filter,map_location())) {
-
ui->assign_role(cfg["role"]);
- found=true;
- break;
- }
- }
- }
- }
-
- // Stop searching if we found a unit:
- if (found) break;
+ } while(!found && has_any_types && ++ti != ti_end);
}
}
@@ -2914,7 +2901,7 @@
if(gui2::new_widgets && options.empty() &&
speaker != units->end()) {
// Get the portrait and if found
proceed to use the new dialog.
- const tportrait* portrait =
+ const tportrait* portrait =
speaker->second.portrait(400,
tportrait::LEFT);
if(portrait) {
gui2::twml_message_left (
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits