Author: anonymissimus
Date: Fri Mar  4 17:49:44 2011
New Revision: 48737

URL: http://svn.gna.org/viewcvs/wesnoth?rev=48737&view=rev
Log:
Changes to apply_shroud_changes which are supposed to fix some sighted event 
problems (fix for bug #17815).
Biggest problem in previous code was that when hitting the hex where the 
unit_itor actually is the temp_unit's moves weren't resetted, resulting in the 
bug.
Fixes test cases:
-delay shroud disabled: doing a move+attack (since the attack code calls 
apply_shroud_changes)
-delay shroud enabled: doing a move without attack, "then update shroud now" or 
disable delay shroud
-delay shroud enabled: doing a move without attack, then attack with delay 
shroud enabled
I'm also attaching the most useful test save I used since further bugs are 
likely.

Modified:
    trunk/src/actions.cpp

Modified: trunk/src/actions.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/actions.cpp?rev=48737&r1=48736&r2=48737&view=diff
==============================================================================
--- trunk/src/actions.cpp (original)
+++ trunk/src/actions.cpp Fri Mar  4 17:49:44 2011
@@ -2660,40 +2660,38 @@
        for(undo_list::iterator un = undos.begin(); un != undos.end(); ++un) {
                LOG_NG << "Turning an undo...\n";
                //NOTE: for the moment shroud cleared during recall seems never 
delayed
-               if(un->is_recall() || un->is_recruit()) continue;
+               //Shroud update during recall can be delayed, during recruit as 
well
+               //if we have a non-random recruit (e.g. undead)
+               //if(un->is_recall() || un->is_recruit()) continue;
 
                // Make a temporary unit move in map and hide the original
-               unit_map::iterator unit_itor = 
units.find(un->affected_unit.underlying_id());
+               const unit_map::const_unit_iterator unit_itor = 
units.find(un->affected_unit.underlying_id());
                // check if the unit is still existing (maybe killed by an 
event)
                // FIXME: A wml-killed unit will not update the shroud explored 
before its death
                if(unit_itor == units.end())
                        continue;
 
-               unit temporary_unit(*unit_itor);
-               // We're not really going to mutate the unit, just temporarily
-               // set its moves to maximum, but then switch them back.
-               const unit_movement_resetter move_resetter(temporary_unit);
+               //copy the actual unit and reset the copy's current moves
+               //to calculate the visible area correctly
+               unit temp_unit(*unit_itor);
+               const unit_movement_resetter move_resetter(temp_unit);
+               //store the unit's current actual location for raising the 
sighted events since
+               //unit_itor will be invalid during that step of the loop when 
we hit this location
+               const map_location actual_location = unit_itor->get_location();
 
                std::vector<map_location>::const_iterator step;
                for(step = un->route.begin(); step != un->route.end(); ++step) {
-                       // we skip places where
-
-                       if (*step != unit_itor->get_location()
-                               && units.find(*step) != units.end())
-                               continue;
+
+                       // we skip places where there is now a unit on the path 
we moved
+                       //Doing this skip is critical since it may miss some 
situations in which
+                       //shroud would have been updated.
+                       //Doing it not is also problematic since any units 
there gets replaced with the
+                       //temp_unit for the cause of that loop step - we'll see
+                       //if (*step != unit_itor->get_location() && 
units.find(*step) != units.end()) continue;
+                       
                        // We have to swap out any unit that is already in the 
hex,
                        // so we can put our unit there, then we'll swap back 
at the end.
-                       boost::scoped_ptr<temporary_unit_placer> unit_placer;
-                       if (*step != unit_itor->get_location())
-                       {
-                               unit_placer.reset(new 
temporary_unit_placer(units,*step, temporary_unit));
-                       }
-
-                       // In theory we don't know this clone, but
-                       // - he can't be in newly cleared locations
-                       // - clear_shroud_unit skip "self-detection"
-                       // so we normaly don't need to flood known_units with 
temporary stuff
-                       // known_units.insert(*step);
+                       const temporary_unit_placer unit_placer(units, *step, 
temp_unit);
 
                        // Clear the shroud, and collect new seen_units
                        std::set<map_location> seen_units;
@@ -2711,7 +2709,7 @@
                                assert(new_unit != units.end());
                                tm.see(new_unit->side() - 1);
 
-                               game_events::raise("sighted", *sight_it, 
unit_itor->get_location());
+                               game_events::raise("sighted", *sight_it, 
actual_location);
                                sighted_event = true;
                        }
                        for (std::set<map_location>::iterator sight_it = 
petrified_units.begin();
@@ -2721,7 +2719,7 @@
                                assert(new_unit != units.end());
                                tm.see(new_unit->side() - 1);
 
-                               game_events::raise("sighted", *sight_it, 
unit_itor->get_location());
+                               game_events::raise("sighted", *sight_it, 
actual_location);
                                sighted_event = true;
                        }
                }


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

Reply via email to