Add the ability to detect if any WML/Lua has been executed...

...(independent of [allow_undo]), and hook this ability into
move_unit().
This commit is contained in:
J. Tyne 2012-08-15 19:36:18 +00:00
parent 74472314d9
commit 1028d7fab8
3 changed files with 60 additions and 21 deletions

View file

@ -2697,6 +2697,7 @@ namespace { // Private helpers for move_unit()
team * current_team_; // Will default to the original team if the moving unit becomes invalid.
bool current_uses_fog_;
route_iterator move_loc_; // Will point to the last moved-to location (in case the moving unit disappears).
size_t do_move_track_; // Tracks whether or not do_move() needs to update the displayed (fake) unit. Should only be touched by do_move() and the constructor.
// Data accumulated while making the move.
map_location zoc_stop_;
@ -2747,6 +2748,7 @@ namespace { // Private helpers for move_unit()
current_uses_fog_(current_team_->fog_or_shroud() &&
current_team_->auto_shroud_updates()),
move_loc_(begin_),
do_move_track_(game_events::wml_tracking()),
// The remaining fields are set to some sort of "zero state".
zoc_stop_(map_location::null_location),
ambush_stop_(map_location::null_location),
@ -2892,7 +2894,10 @@ namespace { // Private helpers for move_unit()
move_loc_ = step_to;
// Show this move.
animator.proceed_to(*move_it_, step_to - begin_);
const size_t current_tracking = game_events::wml_tracking();
animator.proceed_to(*move_it_, step_to - begin_,
current_tracking != do_move_track_);
do_move_track_ = current_tracking;
disp.redraw_minimap();
}
}
@ -3100,11 +3105,15 @@ namespace { // Private helpers for move_unit()
const route_iterator & current,
const route_iterator & other)
{
const size_t track = game_events::wml_tracking();
bool valid = true;
const game_events::entity_location mover(*move_it_, *current);
const bool event = game_events::fire(event_name, mover, *other);
/// @todo: It would be nice to know if any WML was executed.
/// If not, we do not really need to call post_wml().
const bool valid = post_wml(current);
if ( track != game_events::wml_tracking() )
// Some WML fired, so update our status.
valid = post_wml(current);
if ( event || !valid )
event_mutated_ = true;
@ -3187,11 +3196,11 @@ namespace { // Private helpers for move_unit()
*
* @returns false if continuing is impossible (i.e. we lost the moving unit).
*/
bool unit_mover::post_wml(const route_iterator & /* step */)
bool unit_mover::post_wml(const route_iterator & step)
{
// Re-find the moving unit.
move_it_ = resources::units->find(*move_loc_);
bool found = move_it_ != resources::units->end();
const bool found = move_it_ != resources::units->end();
// Update the current unit data.
current_side_ = found ? move_it_->side() : orig_side_;
@ -3200,17 +3209,14 @@ namespace { // Private helpers for move_unit()
( current_side_ != orig_side_ ||
current_team_->auto_shroud_updates() );
// The following lines will only be useful if there comes a way to
// flag an event that makes changes without interrupting movement.
// (It's been suggested, but might be too complicated to implement.)
//if ( found && step != full_end_ ) {
// const route_iterator new_limit = plot_turn(step, expected_end_);
// cache_hidden_units(step, new_limit);
// // Just in case: length 0 paths become length 1 paths.
// if ( ambush_limit_ == step )
// ++ambush_limit_;
//}
// Also affected would be the call to animator.proceed_to in do_move().
// Update the path.
if ( found && step != full_end_ ) {
const route_iterator new_limit = plot_turn(step, expected_end_);
cache_hidden_units(step, new_limit);
// Just in case: length 0 paths become length 1 paths.
if ( ambush_limit_ == step )
++ambush_limit_;
}
return found;
}
@ -3225,10 +3231,14 @@ namespace { // Private helpers for move_unit()
*/
bool unit_mover::pump_sighted(const route_iterator & from)
{
const size_t track = game_events::wml_tracking();
bool valid = true;
const bool event = game_events::pump();
/// @todo: It would be nice to know if any WML was executed.
/// If not, we do not really need to call post_wml().
const bool valid = post_wml(from);
if ( track != game_events::wml_tracking() )
// Some WML fired, so update our status.
valid = post_wml(from);
if ( event || !valid )
event_mutated_ = true;

View file

@ -119,6 +119,8 @@ struct scoped_context
};
static bool screen_needs_rebuild;
// The value returned by wml_tracking();
static size_t internal_wml_tracking = 0;
namespace {
@ -3229,6 +3231,7 @@ static bool process_event(game_events::event_handler& handler, const game_events
return false;
// The event hasn't been filtered out, so execute the handler.
++internal_wml_tracking;
scoped_context evc;
handler.handle_event(ev);
@ -3574,7 +3577,8 @@ namespace game_events {
// due to status changes by WML. Every event will flush the cache.
unit::clear_status_caches();
/* bool lua_event_triggered = */ resources::lua_kernel->run_event(ev);
if ( resources::lua_kernel->run_event(ev) )
++internal_wml_tracking;
bool init_event_vars = true;
@ -3607,6 +3611,26 @@ namespace game_events {
return result;
}
/**
* This function can be used to detect when no WML/Lua has been executed.
*
* If two calls to this function return the same value, then one can
* assume that the usual game mechanics have been followed, and code does
* not have to account for all the things WML/Lua can do. If the return
* values are different, then something unusual might have happened between
* those calls.
*
* This is not intended as a precise metric. Rather, it is motivated by
* how large the number of fired WML events is, compared to the (typical)
* number of WML event handlers. It is intended for code that can benefit
* from caching some aspect of the game state and that cannot rely on
* [allow_undo] not being used when that state changes.
*/
size_t wml_tracking()
{
return internal_wml_tracking;
}
/**
* Constructor for when an event has a location but not necessarily a unit.
* Can also be used if the event has a unit and the caller already has the

View file

@ -172,6 +172,11 @@ namespace game_events
typedef void (*action_handler)(const game_events::queued_event &, const vconfig &);
/**
* This function can be used to detect when no WML/Lua has been executed.
*/
size_t wml_tracking();
} // end namespace game_events
#endif