Author: sapient
Date: Mon Aug 25 02:08:59 2008
New Revision: 28951

URL: http://svn.gna.org/viewcvs/wesnoth?rev=28951&view=rev
Log:
clean up several bugs related to the attack filtering code

Modified:
    trunk/src/actions.cpp
    trunk/src/actions.hpp
    trunk/src/game_events.cpp

Modified: trunk/src/actions.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/actions.cpp?rev=28951&r1=28950&r2=28951&view=diff
==============================================================================
--- trunk/src/actions.cpp (original)
+++ trunk/src/actions.cpp Mon Aug 25 02:08:59 2008
@@ -115,7 +115,7 @@
 
        castle_cost_calculator calc(map);
        // The limit computed in the third argument is more than enough for
-       // any convex castle on the map. Strictly speaking it could be 
+       // any convex castle on the map. Strictly speaking it could be
        // reduced to sqrt(map.w()**2 + map.h()**2).
        const paths::route& rt = a_star_search(leader, loc, map.w()+map.h(), 
&calc, map.w(), map.h());
 
@@ -611,8 +611,7 @@
                weapon = &u.attacks()[attack_num];
        }
        if(u.hitpoints() < 0) {
-               /** @todo FIXME enable after 1.3.2 and find out why this 
happens -- Mordante */
-               //              LOG_STREAM(err, config) << "Unit with " << 
u.hitpoints() << " hitpoints found, set to 0 for damage calculations\n";
+               LOG_STREAM(err, config) << "Unit with " << u.hitpoints() << " 
hitpoints found, set to 0 for damage calculations\n";
                hp = 0;
        } else if(u.hitpoints() > u.max_hitpoints()) {
                // If a unit has more hp as it's maximum the engine will fail
@@ -760,63 +759,41 @@
 void attack::fire_event(const std::string& n)
 {
        LOG_NG << "firing " << n << " event\n";
+       //prepare the event data for weapon filtering
+       config ev_data;
+       bool is_defender_event = (n[0] == 'd');
+       config& a_weapon_cfg = ev_data.add_child(is_defender_event? "second" : 
"first");
+       config& d_weapon_cfg = ev_data.add_child(is_defender_event? "first" : 
"second");
+       if(a_stats_->weapon != NULL && units_.end() != a_) {
+               a_weapon_cfg = a_stats_->weapon->get_cfg();
+       }
+       if(d_stats_->weapon != NULL && units_.end() != d_) {
+               d_weapon_cfg = d_stats_->weapon->get_cfg();
+       }
+       if(a_weapon_cfg["name"].empty()) {
+               a_weapon_cfg["name"] = "none";
+       }
+       if(d_weapon_cfg["name"].empty()) {
+               d_weapon_cfg["name"] = "none";
+       }
        if(n == "attack_end") {
-               config dat;
-               config a_weapon_cfg = (a_stats_->weapon != NULL && units_.end() 
!= a_) ? a_stats_->weapon->get_cfg() : config();
-               config d_weapon_cfg = (d_stats_->weapon != NULL && units_.end() 
!= a_) ? a_stats_->weapon->get_cfg() : config();
-               if(a_weapon_cfg["name"].empty())
-                       a_weapon_cfg["name"] = "none";
-               if(d_weapon_cfg["name"].empty())
-                       d_weapon_cfg["name"] = "none";
-               dat.add_child("first", a_weapon_cfg);
-               dat.add_child("second", d_weapon_cfg);
-
-#if 0
-               if(d_ != units_.end()) {
-                       config *tempcfg = dat.child("second");
-                       t_string d_weap = "none";
-                       if(d_stats_->weapon != NULL) {
-                               d_weap = d_stats_->weapon->id();
-                       }
-                       std::pair<std::string,t_string> to_insert("weapon", 
d_weap);
-                       tempcfg->values.insert(to_insert);
-               }
-#endif
-
                // We want to fire attack_end event in any case! Even if one of 
units was removed by WML
                DELAY_END_LEVEL(delayed_exception, game_events::fire(n,
                                        attacker_,
-                                       defender_, dat));
+                                       defender_, ev_data));
                a_ = units_.find(attacker_);
                d_ = units_.find(defender_);
                return;
        }
        const int defender_side = d_->second.side();
        const int attacker_side = a_->second.side();
-       config dat;
-       config a_weapon_cfg = (a_stats_->weapon != NULL && units_.end() != a_) 
? a_stats_->weapon->get_cfg() : config();
-       config d_weapon_cfg = (d_stats_->weapon != NULL && units_.end() != a_) 
? a_stats_->weapon->get_cfg() : config();
-       if(a_weapon_cfg["name"].empty())
-               a_weapon_cfg["name"] = "none";
-       if(d_weapon_cfg["name"].empty())
-               d_weapon_cfg["name"] = "none";
-       dat.add_child("first", a_weapon_cfg);
-       dat.add_child("second", d_weapon_cfg);
        DELAY_END_LEVEL(delayed_exception, game_events::fire(n,
                                                                
game_events::entity_location(attacker_,a_id_),
-                                                               
game_events::entity_location(defender_,d_id_),dat));
+                                                               
game_events::entity_location(defender_,d_id_),ev_data));
 
        // The event could have killed either the attacker or
        // defender, so we have to make sure they still exist
        refresh_bc();
-       /**
-        * @todo FIXME: If the event removes this attack, we should stop 
attacking.
-        * The previous code checked if 'attack_with' and 'defend_with'
-        * were still within the bounds of the attack arrays,
-        * or -1, but it was incorrect.
-        * The attack used could be removed and '*_with' variables
-        * could still be in bounds but point to a different attack.
-        */
        if(a_ == units_.end() || d_ == units_.end()) {
                if (update_display_){
                        recalculate_fog(map_,units_,teams_,attacker_side-1);
@@ -829,16 +806,52 @@
        }
 }
 
+namespace {
+       void refresh_weapon_index(int& weap_index, std::string const& weap_id, 
std::vector<attack_type> const& attacks) {
+               if(attacks.empty()) {
+                       //no attacks to choose from
+                       weap_index = -1;
+                       return;
+               }
+               if(weap_index >= 0 && weap_index < attacks.size() && 
attacks[weap_index].id() == weap_id) {
+                       //the currently selected attack fits
+                       return;
+               }
+               if(weap_id.empty() && (weap_index < 0 || weap_index > 
attacks.size())) {
+                       //don't attempt to lookup an empty id
+                       weap_index = -1;
+                       return;
+               }
+               //lookup the weapon by id
+               for(int i=0; i<attacks.size(); ++i) {
+                       if(attacks[i].id() == weap_id) {
+                               weap_index = i;
+                               return;
+                       }
+               }
+               //lookup has failed
+               weap_index = -1;
+               return;
+       }
+} //end anonymous namespace
+
 void attack::refresh_bc()
 {
        a_ = units_.find(attacker_);
        d_ = units_.find(defender_);
+       // Fix index of weapons
+       if (a_ != units_.end()) {
+               refresh_weapon_index(attack_with_, a_weap_id_, 
a_->second.attacks());
+       }
+       if (d_ != units_.end()) {
+               refresh_weapon_index(defend_with_, d_weap_id_, 
d_->second.attacks());
+       }
        if(a_ == units_.end() || d_ == units_.end()) {
-               // Fix pointers to weapons
-               if (a_ != units_.end())
+               // Fix pointer to weapons
+               if (a_ != units_.end() && attack_with_ >= 0)
                        
const_cast<battle_context::unit_stats*>(a_stats_)->weapon = 
&a_->second.attacks()[attack_with_];
 
-               if (d_ != units_.end())
+               if (d_ != units_.end() && defend_with_ >= 0)
                        
const_cast<battle_context::unit_stats*>(d_stats_)->weapon = 
&d_->second.attacks()[defend_with_];
                return;
        }
@@ -879,6 +892,8 @@
        d_(units_.find(defender)),
        a_id_(),
        d_id_(),
+       a_weap_id_(),
+       d_weap_id_(),
        errbuf_(),
        bc_(0),
        a_stats_(0),
@@ -925,6 +940,12 @@
        bc_ = new battle_context(map_, teams_, units_, state_, attacker_, 
defender_, attack_with_, defend_with_);
        a_stats_ = &bc_->get_attacker_stats();
        d_stats_ = &bc_->get_defender_stats();
+       if(a_stats_->weapon) {
+               a_weap_id_ = a_stats_->weapon->id();
+       }
+       if(d_stats_->weapon) {
+               d_weap_id_ = d_stats_->weapon->id();
+       }
 
        try {
                fire_event("attack");
@@ -2199,23 +2220,6 @@
                                }
                        }
                }
-#if 0
-               // Check to see if the unit was deleted
-               // during a sighted event in clear_shroud_unit()
-               ui = units.find(route.front());
-               if(ui == units.end()) {
-                       /**
-                        * @todo FIXME: the correct behavior for sighted event 
would be
-                        * to halt movement, then fire "sighted" after firing 
"moveto" (see below).
-                        * However, since we have fired "sighted" during 
movement calculations
-                        * this is a workaround to prevent a crash.
-                        */
-                       if(move_recorder != NULL) {
-                               
move_recorder->add_movement(route.front(),*step);
-                       }
-                       return (step - route.begin());
-               }
-#endif
                // we also refreh its side, just in case if an event change it
                team_num = ui->second.side()-1;
                team = teams[team_num];

Modified: trunk/src/actions.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/actions.hpp?rev=28951&r1=28950&r2=28951&view=diff
==============================================================================
--- trunk/src/actions.hpp (original)
+++ trunk/src/actions.hpp Mon Aug 25 02:08:59 2008
@@ -62,7 +62,7 @@
  */
 std::string recruit_unit(const gamemap& map, const int side, unit_map& units,
                unit u, gamemap::location& recruit_location,const bool 
is_recall,
-               const bool show=false,const bool need_castle=true, 
+               const bool show=false,const bool need_castle=true,
                const bool full_movement=false,const bool wml_triggered=false);
 
 /** Computes the statistics of a battle between an attacker and a defender 
unit. */
@@ -82,9 +82,9 @@
                bool stones;                    /**< Attack turns opponent to 
stone when it hits. */
                bool plagues;                   /**< Attack turns opponent into 
a zombie when fatal. */
                bool poisons;                   /**< Attack poisons opponent 
when it hits. */
-               bool backstab_pos;              /**< 
-                                        * True if the attacker is in 
*position* to backstab the defender (this is used to 
-                                                                * determine 
whether to apply the backstab bonus in case the attacker has backstab). 
+               bool backstab_pos;              /**<
+                                        * True if the attacker is in 
*position* to backstab the defender (this is used to
+                                                                * determine 
whether to apply the backstab bonus in case the attacker has backstab).
                                                                 */
                bool swarm;                             /**< Attack has swarm 
special. */
                bool firststrike;               /**< Attack has firststrike 
special. */
@@ -199,6 +199,7 @@
                const gamestatus& state_;
                unit_map::iterator a_,d_; // attacker and defender
                std::string a_id_, d_id_;
+               std::string a_weap_id_, d_weap_id_;
                std::stringstream errbuf_;
                battle_context* bc_;
                const battle_context::unit_stats* a_stats_;

Modified: trunk/src/game_events.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/game_events.cpp?rev=28951&r1=28950&r2=28951&view=diff
==============================================================================
--- trunk/src/game_events.cpp (original)
+++ trunk/src/game_events.cpp Mon Aug 25 02:08:59 2008
@@ -3359,12 +3359,10 @@
 
                bool matches_special_filter(const config* cfg, const vconfig 
filter)
                {
-                       //! @todo FIXME: This filter should be deprecated and 
removed,
-                       // instead we should just auto-store $attacker_weapon 
and check it in a conditional
-                       //! @todo FIXME: ^ what?
-
                        if(!cfg) {
-                               return false; //! @todo FIXME: shouldn't this 
be true!?
+                               WRN_NG << "attempt to filter attack for an 
event with no attack data.\n";
+                               // better to not execute the event (so the 
problem is more obvious)
+                               return false;
                        }
                        const config& attack_cfg = *cfg;
                        const attack_type attack(attack_cfg);


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to