add [cancel_action] implements #1427
this adds a new tag [cancel_action], it currently only has an effect in move actions. It can be used in enter_hex/exit_hex events to abort the current movement. It can also be used in moveto events where is cancels possible following attacks (if the user issued a move+attack action). This also changes the behaviour of moveto and enter/exit_hex event so that they now no longer cancel the movement automatically, also [allow_undo] no longer has an effect on whether the move is cancelled, it now only allows undoing of the move.
This commit is contained in:
parent
974f09178c
commit
821e27c34f
15 changed files with 142 additions and 91 deletions
|
@ -940,3 +940,7 @@ function wesnoth.wml_conditionals.proceed_to_next_scenario(cfg)
|
|||
return endlevel_data.proceed_to_next_level
|
||||
end
|
||||
end
|
||||
|
||||
function wesnoth.wml_actions.cancel_action(cfg)
|
||||
wesnoth.cancel_action()
|
||||
end
|
||||
|
|
|
@ -648,7 +648,7 @@ place_recruit_result place_recruit(unit_ptr u, const map_location &recruit_locat
|
|||
const std::string event_name = is_recall ? "prerecall" : "prerecruit";
|
||||
LOG_NG << "firing " << event_name << " event\n";
|
||||
{
|
||||
std::get<0>(res) |= resources::game_events->pump().fire(event_name, current_loc, recruited_from);
|
||||
std::get<0>(res) |= std::get<0>(resources::game_events->pump().fire(event_name, current_loc, recruited_from));
|
||||
}
|
||||
if ( !validate_recruit_iterator(new_unit_itor, current_loc) )
|
||||
return std::make_tuple(true, 0, false);
|
||||
|
@ -670,7 +670,7 @@ place_recruit_result place_recruit(unit_ptr u, const map_location &recruit_locat
|
|||
// Village capturing.
|
||||
if ( resources::gameboard->map().is_village(current_loc) ) {
|
||||
std::get<1>(res) = resources::gameboard->village_owner(current_loc) + 1;
|
||||
std::get<0>(res) |= actions::get_village(current_loc, new_unit_itor->side(), &std::get<2>(res));
|
||||
std::get<0>(res) |= std::get<0>(actions::get_village(current_loc, new_unit_itor->side(), &std::get<2>(res)));
|
||||
if ( !validate_recruit_iterator(new_unit_itor, current_loc) )
|
||||
return std::make_tuple(true, 0, false);
|
||||
}
|
||||
|
@ -684,14 +684,14 @@ place_recruit_result place_recruit(unit_ptr u, const map_location &recruit_locat
|
|||
const std::string event_name = is_recall ? "recall" : "recruit";
|
||||
LOG_NG << "firing " << event_name << " event\n";
|
||||
{
|
||||
std::get<0>(res) |= resources::game_events->pump().fire(event_name, current_loc, recruited_from);
|
||||
std::get<0>(res) |= std::get<0>(resources::game_events->pump().fire(event_name, current_loc, recruited_from));
|
||||
}
|
||||
}
|
||||
|
||||
// "sighted" event(s).
|
||||
std::get<0>(res) |= clearer.fire_events();
|
||||
std::get<0>(res) |= std::get<0>(clearer.fire_events());
|
||||
if ( new_unit_itor.valid() )
|
||||
std::get<0>(res) |= actions::actor_sighted(*new_unit_itor);
|
||||
std::get<0>(res) |= std::get<0>(actions::actor_sighted(*new_unit_itor));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -136,12 +136,12 @@ void move_unit_spectator::set_unit(const unit_map::const_iterator &u)
|
|||
}
|
||||
|
||||
|
||||
bool get_village(const map_location& loc, int side, bool *action_timebonus, bool fire_event)
|
||||
game_events::pump_result_t get_village(const map_location& loc, int side, bool *action_timebonus, bool fire_event)
|
||||
{
|
||||
std::vector<team> &teams = resources::gameboard->teams();
|
||||
team *t = unsigned(side - 1) < teams.size() ? &teams[side - 1] : nullptr;
|
||||
if (t && t->owns_village(loc)) {
|
||||
return false;
|
||||
return game_events::pump_result_t();
|
||||
}
|
||||
|
||||
bool not_defeated = t && !resources::gameboard->team_is_defeated(*t);
|
||||
|
@ -164,8 +164,10 @@ bool get_village(const map_location& loc, int side, bool *action_timebonus, bool
|
|||
}
|
||||
}
|
||||
|
||||
if (!t) return false;
|
||||
|
||||
if (!t) {
|
||||
return game_events::pump_result_t();
|
||||
}
|
||||
|
||||
if(grants_timebonus) {
|
||||
t->set_action_bonus_count(1 + t->action_bonus_count());
|
||||
*action_timebonus = true;
|
||||
|
@ -178,7 +180,7 @@ bool get_village(const map_location& loc, int side, bool *action_timebonus, bool
|
|||
return t->get_village(loc, old_owner_side, fire_event ? resources::gamedata : nullptr);
|
||||
}
|
||||
|
||||
return false;
|
||||
return game_events::pump_result_t();
|
||||
}
|
||||
|
||||
|
||||
|
@ -222,7 +224,7 @@ namespace { // Private helpers for move_unit()
|
|||
bool interrupted(bool include_end_of_move_events=true) const
|
||||
{
|
||||
return ambushed_ || blocked() || sighted_ || teleport_failed_ ||
|
||||
(include_end_of_move_events ? event_mutated_ : event_mutated_mid_move_ ) ||
|
||||
(include_end_of_move_events ? (wml_removed_unit_ || wml_move_aborted_): event_mutated_mid_move_ ) ||
|
||||
!move_it_.valid();
|
||||
}
|
||||
|
||||
|
@ -233,7 +235,7 @@ namespace { // Private helpers for move_unit()
|
|||
void cache_hidden_units(const route_iterator & start,
|
||||
const route_iterator & stop);
|
||||
/// Fires the enter_hex or exit_hex event and updates our data as needed.
|
||||
bool fire_hex_event(const std::string & event_name,
|
||||
void fire_hex_event(const std::string & event_name,
|
||||
const route_iterator & current,
|
||||
const route_iterator & other);
|
||||
/// AI moves are supposed to not change the "goto" order.
|
||||
|
@ -242,8 +244,8 @@ namespace { // Private helpers for move_unit()
|
|||
route_iterator plot_turn(const route_iterator & start,
|
||||
const route_iterator & stop);
|
||||
/// Updates our stored info after a WML event might have changed something.
|
||||
bool post_wml(const route_iterator & step);
|
||||
bool post_wml() { return post_wml(full_end_); }
|
||||
void post_wml(game_events::pump_result_t pump_res, const route_iterator & step);
|
||||
void post_wml(game_events::pump_result_t pump_res) { return post_wml(pump_res, full_end_); }
|
||||
/// Fires the sighted events that were raised earlier.
|
||||
void pump_sighted(const route_iterator & from);
|
||||
/// Returns the ambush alert (if any) for the given unit.
|
||||
|
@ -253,7 +255,7 @@ namespace { // Private helpers for move_unit()
|
|||
|
||||
/// Returns whether or not undoing this move should be blocked.
|
||||
bool undo_blocked() const
|
||||
{ return ambushed_ || blocked() || event_mutated_ || fog_changed_ ||
|
||||
{ return ambushed_ || blocked() || wml_removed_unit_ || wml_undo_disabled_ || fog_changed_ ||
|
||||
teleport_failed_; }
|
||||
|
||||
// The remaining private functions are suggested to be inlined because
|
||||
|
@ -319,8 +321,10 @@ namespace { // Private helpers for move_unit()
|
|||
map_location blocked_loc_; // Location of a blocking, enemy, non-ambusher unit.
|
||||
bool ambushed_;
|
||||
bool show_ambush_alert_;
|
||||
bool event_mutated_;
|
||||
bool event_mutated_mid_move_; // Cache of event_mutated_ from just before the end-of-move handling.
|
||||
bool wml_removed_unit_;
|
||||
bool wml_undo_disabled_;
|
||||
bool wml_move_aborted_;
|
||||
bool event_mutated_mid_move_; // Cache of wml_removed_unit_ || wml_move_aborted_ from just before the end-of-move handling.
|
||||
bool fog_changed_;
|
||||
bool sighted_; // Records if sightings were made that could interrupt movement.
|
||||
bool sighted_stop_; // Records if sightings were made that did interrupt movement (the same as sighted_ unless movement ended for another reason).
|
||||
|
@ -375,7 +379,9 @@ namespace { // Private helpers for move_unit()
|
|||
blocked_loc_(map_location::null_location()),
|
||||
ambushed_(false),
|
||||
show_ambush_alert_(false),
|
||||
event_mutated_(false),
|
||||
wml_removed_unit_(false),
|
||||
wml_undo_disabled_(false),
|
||||
wml_move_aborted_(false),
|
||||
event_mutated_mid_move_(false),
|
||||
fog_changed_(false),
|
||||
sighted_(false),
|
||||
|
@ -718,27 +724,15 @@ namespace { // Private helpers for move_unit()
|
|||
* @param[in] current The currently occupied hex.
|
||||
* @param[in] other The secondary hex to provide to the event.
|
||||
*
|
||||
* @return true if this event should interrupt movement.
|
||||
* (This is also stored in event_mutated_.)
|
||||
*/
|
||||
bool unit_mover::fire_hex_event(const std::string & event_name,
|
||||
void unit_mover::fire_hex_event(const std::string & event_name,
|
||||
const route_iterator & current,
|
||||
const route_iterator & other)
|
||||
{
|
||||
const size_t track = resources::game_events->pump().wml_tracking();
|
||||
bool valid = true;
|
||||
|
||||
const game_events::entity_location mover(*move_it_, *current);
|
||||
const bool event = resources::game_events->pump().fire(event_name, mover, *other);
|
||||
|
||||
if (track != resources::game_events->pump().wml_tracking()) {
|
||||
// Some WML fired, so update our status.
|
||||
valid = post_wml(current);
|
||||
}
|
||||
if (event || !valid) {
|
||||
event_mutated_ = true;
|
||||
}
|
||||
return event || !valid;
|
||||
post_wml(resources::game_events->pump().fire(event_name, mover, *other), current);
|
||||
}
|
||||
|
||||
|
||||
|
@ -814,8 +808,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)
|
||||
void unit_mover::post_wml(game_events::pump_result_t pump_res, const route_iterator & step)
|
||||
{
|
||||
wml_move_aborted_ |= std::get<1>(pump_res);
|
||||
wml_undo_disabled_ |= std::get<0>(pump_res);
|
||||
|
||||
// Re-find the moving unit.
|
||||
move_it_ = resources::gameboard->units().find(*move_loc_);
|
||||
const bool found = move_it_ != resources::gameboard->units().end();
|
||||
|
@ -837,7 +834,7 @@ namespace { // Private helpers for move_unit()
|
|||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
wml_removed_unit_ |= !found;
|
||||
}
|
||||
|
||||
|
||||
|
@ -846,22 +843,18 @@ namespace { // Private helpers for move_unit()
|
|||
*
|
||||
* @param[in] from Points to the hex the sighting unit currently occupies.
|
||||
*
|
||||
* @return sets event_mutated_ to true if this event should interrupt movement.
|
||||
* @return sets event_mutated_ || wml_move_aborted_ to true if this event should interrupt movement.
|
||||
*/
|
||||
void unit_mover::pump_sighted(const route_iterator & from)
|
||||
{
|
||||
const size_t track = resources::game_events->pump().wml_tracking();
|
||||
bool valid = true;
|
||||
|
||||
const bool non_undoable_events_happened = clearer_.fire_events();
|
||||
auto pump_res = clearer_.fire_events();
|
||||
|
||||
if (track != resources::game_events->pump().wml_tracking()) {
|
||||
// Some WML fired, so update our status.
|
||||
valid = post_wml(from);
|
||||
}
|
||||
if (non_undoable_events_happened || !valid) {
|
||||
event_mutated_ = true;
|
||||
}
|
||||
post_wml(pump_res, from);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -922,8 +915,14 @@ namespace { // Private helpers for move_unit()
|
|||
// Make sure this hex is drawn correctly.
|
||||
disp.invalidate(hex);
|
||||
// Fire sighted events.
|
||||
event_mutated_ |= actor_sighted(*ambusher, &sight_cache);
|
||||
post_wml();
|
||||
|
||||
bool wml_undo_blocked = false;
|
||||
bool wml_move_aborted = false;
|
||||
|
||||
std::tie(wml_undo_blocked, wml_move_aborted) = actor_sighted(*ambusher, &sight_cache);
|
||||
// TODO: should we call post_wml ?
|
||||
wml_move_aborted_ |= wml_move_aborted;
|
||||
wml_undo_disabled_ |= wml_undo_blocked;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -931,7 +930,7 @@ namespace { // Private helpers for move_unit()
|
|||
// Public interface:
|
||||
|
||||
/**
|
||||
* Determines how far along the route the unit can expect to move this turn.
|
||||
* Determines how far along the route the unit can expect to move this turn.
|
||||
* This is based solely on data known to the player, and will not plot a move
|
||||
* that ends on another (known) unit.
|
||||
* (For example, this prevents a player from plotting a multi-turn move that
|
||||
|
@ -981,18 +980,17 @@ namespace { // Private helpers for move_unit()
|
|||
|
||||
// See if we can leave *step_from.
|
||||
// Already accounted for: ambusher
|
||||
if ( event_mutated_ )
|
||||
{
|
||||
if ( wml_removed_unit_ || wml_move_aborted_) {
|
||||
break;
|
||||
}
|
||||
if ( sighted_ && is_reasonable_stop(*step_from) )
|
||||
{
|
||||
if ( sighted_ && is_reasonable_stop(*step_from) ) {
|
||||
sighted_stop_ = true;
|
||||
break;
|
||||
}
|
||||
// Already accounted for: ZoC
|
||||
// Already accounted for: movement cost
|
||||
if ( fire_hex_event(exit_hex_str, step_from, real_end_) ) {
|
||||
fire_hex_event(exit_hex_str, step_from, real_end_);
|
||||
if (wml_removed_unit_ || wml_move_aborted_) {
|
||||
break;
|
||||
}
|
||||
if ( real_end_ == obstructed_ ) {
|
||||
|
@ -1011,7 +1009,7 @@ namespace { // Private helpers for move_unit()
|
|||
|
||||
// Fire the events for this step.
|
||||
// (These return values are not checked since real_end_ still
|
||||
// needs to be incremented. The event_mutated_ check will break
|
||||
// needs to be incremented. The wml_move_aborted_ check will break
|
||||
// us out of the loop if needed.)
|
||||
fire_hex_event(enter_hex_str, real_end_, step_from);
|
||||
// Sighted events only fire if we could stop due to sighting.
|
||||
|
@ -1026,7 +1024,14 @@ namespace { // Private helpers for move_unit()
|
|||
// Finish animating.
|
||||
animator.finish(move_it_.get_shared_ptr());
|
||||
// Check for the moving unit being seen.
|
||||
event_mutated_ |= actor_sighted(*move_it_, ¬_seeing);
|
||||
|
||||
bool wml_undo_blocked = false;
|
||||
bool wml_move_aborted = false;
|
||||
|
||||
std::tie(wml_undo_blocked, wml_move_aborted) = actor_sighted(*move_it_, ¬_seeing);
|
||||
// TODO: should we call post_wml ?
|
||||
wml_move_aborted_ |= wml_move_aborted;
|
||||
wml_undo_disabled_ |= wml_undo_blocked;
|
||||
}
|
||||
}//if
|
||||
|
||||
|
@ -1039,7 +1044,7 @@ namespace { // Private helpers for move_unit()
|
|||
teleport_failed_ = teleport_failed_ && obstructed_stop;
|
||||
// event_mutated_ does not get unset, regardless of other reasons
|
||||
// for stopping, but we do save its current value.
|
||||
event_mutated_mid_move_ = event_mutated_;
|
||||
event_mutated_mid_move_ = wml_removed_unit_ || wml_move_aborted_;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1080,15 +1085,13 @@ namespace { // Private helpers for move_unit()
|
|||
if ( orig_village_owner != current_side_) {
|
||||
// Captured. Zap movement and take over the village.
|
||||
move_it_->set_movement(0, true);
|
||||
event_mutated_ |= get_village(final_loc, current_side_, &action_time_bonus);
|
||||
post_wml();
|
||||
post_wml(get_village(final_loc, current_side_, &action_time_bonus));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, the moveto event.
|
||||
event_mutated_ |= resources::game_events->pump().fire("moveto", final_loc, *begin_);
|
||||
post_wml();
|
||||
post_wml(resources::game_events->pump().fire("moveto", final_loc, *begin_));
|
||||
|
||||
// Record keeping.
|
||||
if (spectator_) {
|
||||
|
|
|
@ -24,6 +24,7 @@ class replay;
|
|||
class unit;
|
||||
|
||||
#include "units/map.hpp"
|
||||
#include "game_events/fwd.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -96,7 +97,7 @@ private:
|
|||
* Returns true if getting the village triggered a mutating event.
|
||||
* side can be 0 to make teh village uncaptured.
|
||||
*/
|
||||
bool get_village(const map_location& loc, int side, bool *time_bonus = nullptr, bool fire_event = true);
|
||||
game_events::pump_result_t get_village(const map_location& loc, int side, bool *time_bonus = nullptr, bool fire_event = true);
|
||||
|
||||
/// Moves a unit across the board.
|
||||
/// And enters the synced context.
|
||||
|
|
|
@ -487,7 +487,7 @@ bool undo_list::apply_shroud_changes() const
|
|||
disp.draw();
|
||||
|
||||
// Fire sighted events
|
||||
if ( clearer.fire_events() ) {
|
||||
if ( std::get<0>(clearer.fire_events() )) {
|
||||
// Fix up the display in case WML changed stuff.
|
||||
clear_shroud(side_);
|
||||
disp.invalidate_unit();
|
||||
|
|
|
@ -543,13 +543,13 @@ void shroud_clearer::drop_events()
|
|||
* Fires the sighted events that were recorded by earlier fog/shroud clearing.
|
||||
* @return true if the events have mutated the game state.
|
||||
*/
|
||||
bool shroud_clearer::fire_events()
|
||||
game_events::pump_result_t shroud_clearer::fire_events()
|
||||
{
|
||||
const unit_map & units = resources::gameboard->units();
|
||||
|
||||
// Possible/probable quick abort.
|
||||
if ( sightings_.empty() )
|
||||
return false;
|
||||
return game_events::pump_result_t();
|
||||
|
||||
// In case of exceptions, clear sightings_ before processing events.
|
||||
std::vector<sight_data> sight_list;
|
||||
|
@ -619,7 +619,7 @@ std::vector<int> get_sides_not_seeing(const unit & target)
|
|||
*
|
||||
* @returns true if an event has mutated the game state.
|
||||
*/
|
||||
bool actor_sighted(const unit & target, const std::vector<int> * cache)
|
||||
game_events::pump_result_t actor_sighted(const unit & target, const std::vector<int> * cache)
|
||||
/* Current logic:
|
||||
* 1) One event is fired per side that can see the target.
|
||||
* 2) The second unit for the event is one that can see the target, if possible.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "movetype.hpp"
|
||||
#include "game_events/fwd.hpp"
|
||||
|
||||
struct map_location;
|
||||
class team;
|
||||
|
@ -111,7 +112,7 @@ public:
|
|||
void drop_events();
|
||||
|
||||
/// Fires the sighted events that were earlier recorded by fog/shroud clearing.
|
||||
bool fire_events();
|
||||
game_events::pump_result_t fire_events();
|
||||
|
||||
/// The invalidations that should occur after invoking clear_unit().
|
||||
void invalidate_after_clear();
|
||||
|
@ -144,7 +145,7 @@ private: // data
|
|||
/// Returns the sides that cannot currently see @a target.
|
||||
std::vector<int> get_sides_not_seeing(const unit & target);
|
||||
/// Fires sighted events for the sides that can see @a target.
|
||||
bool actor_sighted(const unit & target, const std::vector<int> * cache = nullptr);
|
||||
game_events::pump_result_t actor_sighted(const unit & target, const std::vector<int> * cache = nullptr);
|
||||
|
||||
|
||||
/// Function that recalculates the fog of war.
|
||||
|
|
8
src/game_events/fwd.hpp
Normal file
8
src/game_events/fwd.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace game_events
|
||||
{
|
||||
using pump_result_t = std::tuple<bool /* undo_disabled*/, bool /* action_aborted */>;
|
||||
}
|
|
@ -63,10 +63,12 @@ namespace context
|
|||
struct state
|
||||
{
|
||||
bool undo_disabled;
|
||||
bool action_canceled;
|
||||
bool skip_messages;
|
||||
|
||||
explicit state(bool s, bool m = true)
|
||||
: undo_disabled(m)
|
||||
, action_canceled(false)
|
||||
, skip_messages(s)
|
||||
{
|
||||
}
|
||||
|
@ -279,14 +281,14 @@ bool wml_event_pump::filter_event(const event_handler& handler, const queued_eve
|
|||
*
|
||||
* @returns true if the game state changed.
|
||||
*/
|
||||
bool wml_event_pump::process_event(handler_ptr& handler_p, const queued_event& ev)
|
||||
void wml_event_pump::process_event(handler_ptr& handler_p, const queued_event& ev)
|
||||
{
|
||||
DBG_EH << "processing event " << ev.name << " with id=" << ev.id << "\n";
|
||||
|
||||
// We currently never pass a null pointer to this function, but to
|
||||
// guard against future modifications:
|
||||
if(!handler_p) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
unit_map& units = resources::gameboard->units();
|
||||
|
@ -296,7 +298,7 @@ bool wml_event_pump::process_event(handler_ptr& handler_p, const queued_event& e
|
|||
scoped_weapon_info second_weapon("second_weapon", ev.data.child("second"));
|
||||
|
||||
if(!filter_event(*handler_p, ev)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// The event hasn't been filtered out, so execute the handler.
|
||||
|
@ -313,8 +315,6 @@ bool wml_event_pump::process_event(handler_ptr& handler_p, const queued_event& e
|
|||
if(resources::screen != nullptr) {
|
||||
resources::screen->maybe_rebuild();
|
||||
}
|
||||
|
||||
return undo_disabled();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -431,8 +431,11 @@ context::scoped::~scoped()
|
|||
{
|
||||
assert(contexts_.size() > 1);
|
||||
bool undo_disabled = contexts_.top().undo_disabled;
|
||||
bool action_canceled = contexts_.top().action_canceled;
|
||||
|
||||
contexts_.pop();
|
||||
contexts_.top().undo_disabled |= undo_disabled;
|
||||
contexts_.top().action_canceled |= action_canceled;
|
||||
}
|
||||
|
||||
bool wml_event_pump::undo_disabled()
|
||||
|
@ -447,6 +450,19 @@ void wml_event_pump::set_undo_disabled(bool b)
|
|||
impl_->contexts_.top().undo_disabled = b;
|
||||
}
|
||||
|
||||
bool wml_event_pump::action_canceled()
|
||||
{
|
||||
assert(impl_->contexts_.size() > 0);
|
||||
return impl_->contexts_.top().action_canceled;
|
||||
}
|
||||
|
||||
void wml_event_pump::set_action_canceled()
|
||||
{
|
||||
assert(impl_->contexts_.size() > 0);
|
||||
impl_->contexts_.top().action_canceled = true;
|
||||
}
|
||||
|
||||
|
||||
bool wml_event_pump::context_skip_messages()
|
||||
{
|
||||
assert(impl_->contexts_.size() > 0);
|
||||
|
@ -476,14 +492,14 @@ void wml_event_pump::put_wml_message(const std::string& logger, const std::strin
|
|||
}
|
||||
}
|
||||
|
||||
bool wml_event_pump::fire(
|
||||
pump_result_t wml_event_pump::fire(
|
||||
const std::string& event, const entity_location& loc1, const entity_location& loc2, const config& data)
|
||||
{
|
||||
raise(event, loc1, loc2, data);
|
||||
return (*this)();
|
||||
}
|
||||
|
||||
bool wml_event_pump::fire(const std::string& event,
|
||||
pump_result_t wml_event_pump::fire(const std::string& event,
|
||||
const std::string& id,
|
||||
const entity_location& loc1,
|
||||
const entity_location& loc2,
|
||||
|
@ -507,23 +523,23 @@ void wml_event_pump::raise(const std::string& event,
|
|||
impl_->events_queue.emplace_back(event, id, loc1, loc2, data);
|
||||
}
|
||||
|
||||
bool wml_event_pump::operator()()
|
||||
pump_result_t wml_event_pump::operator()()
|
||||
{
|
||||
// Quick aborts:
|
||||
if(resources::screen == nullptr) {
|
||||
return false;
|
||||
return pump_result_t();
|
||||
}
|
||||
|
||||
assert(resources::lua_kernel != nullptr);
|
||||
if(impl_->events_queue.empty()) {
|
||||
DBG_EH << "Processing queued events, but none found.\n";
|
||||
return false;
|
||||
return pump_result_t();
|
||||
}
|
||||
|
||||
if(impl_->instance_count >= game_config::max_loop) {
|
||||
ERR_NG << "game_events pump waiting to process new events because "
|
||||
<< "recursion level would exceed maximum: " << game_config::max_loop << '\n';
|
||||
return false;
|
||||
return pump_result_t();
|
||||
}
|
||||
|
||||
if(!lg::debug().dont_log("event_handler")) {
|
||||
|
@ -605,7 +621,7 @@ bool wml_event_pump::operator()()
|
|||
resources::whiteboard->on_gamestate_change();
|
||||
}
|
||||
|
||||
return undo_disabled();
|
||||
return std::make_tuple(undo_disabled(), action_canceled());
|
||||
}
|
||||
|
||||
void wml_event_pump::flush_messages()
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "game_events/fwd.hpp"
|
||||
#include "game_events/entity_location.hpp"
|
||||
#include "game_events/handlers.hpp"
|
||||
#include "game_events/manager.hpp"
|
||||
|
@ -82,13 +83,21 @@ public:
|
|||
|
||||
/**
|
||||
* Context: The general environment within which events are processed.
|
||||
* Returns whether or not we believe WML might have changed something.
|
||||
* Returns whether or not audoing is impossible due to wml.
|
||||
*/
|
||||
bool undo_disabled();
|
||||
|
||||
/** Sets whether or not we believe WML might have changed something. */
|
||||
/** [allow_undo] implementation */
|
||||
void set_undo_disabled(bool mutated);
|
||||
|
||||
/**
|
||||
* Returns whether or not wml wants to abort the currently executed user action.
|
||||
*/
|
||||
bool action_canceled();
|
||||
|
||||
/** Sets whether or not wml wants to abort the currently executed user action. */
|
||||
void set_action_canceled();
|
||||
|
||||
/** Returns whether or not we are skipping messages. */
|
||||
bool context_skip_messages();
|
||||
|
||||
|
@ -106,12 +115,12 @@ public:
|
|||
*
|
||||
* Events may have up to two arguments, both of which must be locations.
|
||||
*/
|
||||
bool fire(const std::string& event,
|
||||
pump_result_t fire(const std::string& event,
|
||||
const entity_location& loc1 = entity_location::null_entity,
|
||||
const entity_location& loc2 = entity_location::null_entity,
|
||||
const config& data = config());
|
||||
|
||||
bool fire(const std::string& event,
|
||||
pump_result_t fire(const std::string& event,
|
||||
const std::string& id,
|
||||
const entity_location& loc1 = entity_location::null_entity,
|
||||
const entity_location& loc2 = entity_location::null_entity,
|
||||
|
@ -131,7 +140,7 @@ public:
|
|||
raise(event, "", loc1, loc2, data);
|
||||
}
|
||||
|
||||
bool operator()();
|
||||
pump_result_t operator()();
|
||||
|
||||
/** Flushes WML messages and errors. */
|
||||
void flush_messages();
|
||||
|
@ -142,7 +151,7 @@ public:
|
|||
private:
|
||||
bool filter_event(const event_handler& handler, const queued_event& ev);
|
||||
|
||||
bool process_event(handler_ptr& handler_p, const queued_event& ev);
|
||||
void process_event(handler_ptr& handler_p, const queued_event& ev);
|
||||
|
||||
void fill_wml_messages_map(std::map<std::string, int>& msg_map, std::stringstream& source);
|
||||
|
||||
|
|
|
@ -712,10 +712,10 @@ int game_lua_kernel::intf_fire_event(lua_State *L, const bool by_id)
|
|||
bool b = false;
|
||||
|
||||
if (by_id) {
|
||||
b = play_controller_.pump().fire("", m, l1, l2, data);
|
||||
b = std::get<0>(play_controller_.pump().fire("", m, l1, l2, data));
|
||||
}
|
||||
else {
|
||||
b = play_controller_.pump().fire(m, l1, l2, data);
|
||||
b = std::get<0>(play_controller_.pump().fire(m, l1, l2, data));
|
||||
}
|
||||
lua_pushboolean(L, b);
|
||||
return 1;
|
||||
|
@ -3536,6 +3536,12 @@ int game_lua_kernel::intf_allow_undo(lua_State * L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int game_lua_kernel::intf_cancel_action(lua_State*)
|
||||
{
|
||||
play_controller_.pump().action_canceled();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Adding new time_areas dynamically with Standard Location Filters.
|
||||
int game_lua_kernel::intf_add_time_area(lua_State * L)
|
||||
{
|
||||
|
@ -3997,6 +4003,7 @@ game_lua_kernel::game_lua_kernel(game_state & gs, play_controller & pc, reports
|
|||
{ "allow_end_turn", &dispatch<&game_lua_kernel::intf_allow_end_turn > },
|
||||
{ "allow_undo", &dispatch<&game_lua_kernel::intf_allow_undo > },
|
||||
{ "append_ai", &intf_append_ai },
|
||||
{ "cancel_action", &dispatch<&game_lua_kernel::intf_cancel_action > },
|
||||
{ "clear_menu_item", &dispatch<&game_lua_kernel::intf_clear_menu_item > },
|
||||
{ "clear_messages", &dispatch<&game_lua_kernel::intf_clear_messages > },
|
||||
{ "color_adjust", &dispatch<&game_lua_kernel::intf_color_adjust > },
|
||||
|
|
|
@ -71,6 +71,7 @@ class game_lua_kernel : public lua_kernel_base
|
|||
// Private lua callbacks
|
||||
int intf_allow_end_turn(lua_State *);
|
||||
int intf_allow_undo(lua_State *);
|
||||
int intf_cancel_action(lua_State *);
|
||||
int intf_add_time_area(lua_State *);
|
||||
int intf_remove_time_area(lua_State *);
|
||||
int intf_animate_unit(lua_State *);
|
||||
|
|
|
@ -327,9 +327,9 @@ SYNCED_COMMAND_HANDLER_FUNCTION(fire_event, child, use_undo, /*show*/, /*error_
|
|||
}
|
||||
const std::string &event_name = child["raise"];
|
||||
if (const config &source = child.child("source")) {
|
||||
undoable = undoable & !resources::game_events->pump().fire(event_name, map_location(source, resources::gamedata));
|
||||
undoable = undoable & !std::get<0>(resources::game_events->pump().fire(event_name, map_location(source, resources::gamedata)));
|
||||
} else {
|
||||
undoable = undoable & !resources::game_events->pump().fire(event_name);
|
||||
undoable = undoable & !std::get<0>(resources::game_events->pump().fire(event_name));
|
||||
}
|
||||
|
||||
// Not clearing the undo stack here casues OOS because we added an entry to the replay but no entry to the undo stack.
|
||||
|
|
|
@ -374,10 +374,10 @@ void team::write(config& cfg) const
|
|||
cfg["action_bonus_count"] = action_bonus_count_;
|
||||
}
|
||||
|
||||
bool team::get_village(const map_location& loc, const int owner_side, game_data * gamedata)
|
||||
game_events::pump_result_t team::get_village(const map_location& loc, const int owner_side, game_data * gamedata)
|
||||
{
|
||||
villages_.insert(loc);
|
||||
bool gamestate_changed = false;
|
||||
game_events::pump_result_t res;
|
||||
if(gamedata) {
|
||||
config::attribute_value& var = gamedata->get_variable("owner_side");
|
||||
const config::attribute_value old_value = var;
|
||||
|
@ -385,7 +385,7 @@ bool team::get_village(const map_location& loc, const int owner_side, game_data
|
|||
|
||||
// During team building, game_events pump is not guaranteed to exist yet. (At current revision.) We skip capture events in this case.
|
||||
if (resources::game_events) {
|
||||
gamestate_changed = resources::game_events->pump().fire("capture",loc);
|
||||
res = resources::game_events->pump().fire("capture", loc);
|
||||
}
|
||||
|
||||
if(old_value.blank())
|
||||
|
@ -393,7 +393,7 @@ bool team::get_village(const map_location& loc, const int owner_side, game_data
|
|||
else
|
||||
var = old_value;
|
||||
}
|
||||
return gamestate_changed;
|
||||
return res;
|
||||
}
|
||||
|
||||
void team::lose_village(const map_location& loc)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "color_range.hpp"
|
||||
#include "game_config.hpp"
|
||||
#include "game_events/fwd.hpp"
|
||||
#include "utils/make_enum.hpp"
|
||||
#include "map/location.hpp"
|
||||
#include "recall_list_manager.hpp"
|
||||
|
@ -176,7 +177,7 @@ public:
|
|||
|
||||
void write(config& cfg) const;
|
||||
|
||||
bool get_village(const map_location&, const int owner_side, game_data * fire_event); //!< Acquires a village from owner_side. Pointer fire_event should be the game_data for the game if it is desired to fire an event -- a "capture" event with owner_side variable scoped in will be fired. For no event, pass it nullptr. Default is the resources::gamedata pointer
|
||||
game_events::pump_result_t get_village(const map_location&, const int owner_side, game_data * fire_event); //!< Acquires a village from owner_side. Pointer fire_event should be the game_data for the game if it is desired to fire an event -- a "capture" event with owner_side variable scoped in will be fired. For no event, pass it nullptr. Default is the resources::gamedata pointer
|
||||
void lose_village(const map_location&);
|
||||
void clear_villages() { villages_.clear(); }
|
||||
const std::set<map_location>& villages() const { return villages_; }
|
||||
|
|
Loading…
Add table
Reference in a new issue