Split game_events.cpp.
VC and XCode projects still need to be updated.
This commit is contained in:
parent
72920fe01c
commit
c0435769bd
40 changed files with 3515 additions and 3149 deletions
|
@ -228,8 +228,16 @@
|
|||
<Unit filename="../../src/game_display.hpp" />
|
||||
<Unit filename="../../src/game_end_exceptions.hpp" />
|
||||
<Unit filename="../../src/game_errors.hpp" />
|
||||
<Unit filename="../../src/game_events.cpp" />
|
||||
<Unit filename="../../src/game_events.hpp" />
|
||||
<Unit filename="../../src/game_events/action_wml.cpp" />
|
||||
<Unit filename="../../src/game_events/action_wml.hpp" />
|
||||
<Unit filename="../../src/game_events/conditional_wml.cpp" />
|
||||
<Unit filename="../../src/game_events/conditional_wml.hpp" />
|
||||
<Unit filename="../../src/game_events/entity_location.cpp" />
|
||||
<Unit filename="../../src/game_events/entity_location.hpp" />
|
||||
<Unit filename="../../src/game_events/handlers.cpp" />
|
||||
<Unit filename="../../src/game_events/handlers.hpp" />
|
||||
<Unit filename="../../src/game_events/pump.cpp" />
|
||||
<Unit filename="../../src/game_events/pump.hpp" />
|
||||
<Unit filename="../../src/game_preferences.cpp" />
|
||||
<Unit filename="../../src/game_preferences.hpp" />
|
||||
<Unit filename="../../src/game_preferences_display.cpp" />
|
||||
|
|
|
@ -315,8 +315,16 @@
|
|||
<Unit filename="..\..\src\game_end_exceptions.hpp" />
|
||||
<Unit filename="..\..\src\game_errors.cpp" />
|
||||
<Unit filename="..\..\src\game_errors.hpp" />
|
||||
<Unit filename="..\..\src\game_events.cpp" />
|
||||
<Unit filename="..\..\src\game_events.hpp" />
|
||||
<Unit filename="..\..\src\game_events\action_wml.cpp" />
|
||||
<Unit filename="..\..\src\game_events\action_wml.hpp" />
|
||||
<Unit filename="..\..\src\game_events\conditional_wml.cpp" />
|
||||
<Unit filename="..\..\src\game_events\conditional_wml.hpp" />
|
||||
<Unit filename="..\..\src\game_events\entity_location.cpp" />
|
||||
<Unit filename="..\..\src\game_events\entity_location.hpp" />
|
||||
<Unit filename="..\..\src\game_events\handlers.cpp" />
|
||||
<Unit filename="..\..\src\game_events\handlers.hpp" />
|
||||
<Unit filename="..\..\src\game_events\pump.cpp" />
|
||||
<Unit filename="..\..\src\game_events\pump.hpp" />
|
||||
<Unit filename="..\..\src\game_instance.cpp" />
|
||||
<Unit filename="..\..\src\game_instance.hpp" />
|
||||
<Unit filename="..\..\src\game_preferences.cpp" />
|
||||
|
|
|
@ -3390,6 +3390,18 @@
|
|||
<File Name="../../src/ai/configuration.hpp"/>
|
||||
<File Name="../../src/ai/testing.cpp"/>
|
||||
</VirtualDirectory>
|
||||
<VirtualDirectory Name="game_events">
|
||||
<File Name="../../src/game_events/action_wml.cpp" />
|
||||
<File Name="../../src/game_events/action_wml.hpp" />
|
||||
<File Name="../../src/game_events/conditional_wml.cpp" />
|
||||
<File Name="../../src/game_events/conditional_wml.hpp" />
|
||||
<File Name="../../src/game_events/entity_location.cpp" />
|
||||
<File Name="../../src/game_events/entity_location.hpp" />
|
||||
<File Name="../../src/game_events/handlers.cpp" />
|
||||
<File Name="../../src/game_events/handlers.hpp" />
|
||||
<File Name="../../src/game_events/pump.cpp" />
|
||||
<File Name="../../src/game_events/pump.hpp" />
|
||||
</VirtualDirectory>
|
||||
<VirtualDirectory Name="gui">
|
||||
<VirtualDirectory Name="lib">
|
||||
<VirtualDirectory Name="types">
|
||||
|
@ -4227,7 +4239,6 @@
|
|||
<File Name="../../src/playsingle_controller.hpp"/>
|
||||
<File Name="../../src/color_range.cpp"/>
|
||||
<File Name="../../src/log.cpp"/>
|
||||
<File Name="../../src/game_events.hpp"/>
|
||||
<File Name="../../src/joystick.hpp"/>
|
||||
<File Name="../../src/font.cpp"/>
|
||||
<File Name="../../src/marked-up_text.cpp"/>
|
||||
|
@ -4380,7 +4391,6 @@
|
|||
<File Name="../../src/color_range.hpp"/>
|
||||
<File Name="../../src/config_cache.cpp"/>
|
||||
<File Name="../../src/wml_separators.hpp"/>
|
||||
<File Name="../../src/game_events.cpp"/>
|
||||
<File Name="../../src/network.cpp"/>
|
||||
<File Name="../../src/playmp_controller.cpp"/>
|
||||
<File Name="../../src/Makefile"/>
|
||||
|
|
|
@ -690,7 +690,11 @@ set(wesnoth-main_SRC
|
|||
game_controller.cpp
|
||||
game_display.cpp
|
||||
game_errors.cpp
|
||||
game_events.cpp
|
||||
game_events/action_wml.cpp
|
||||
game_events/conditional_wml.cpp
|
||||
game_events/entity_location.cpp
|
||||
game_events/handlers.cpp
|
||||
game_events/pump.cpp
|
||||
game_instance.cpp
|
||||
game_preferences.cpp
|
||||
game_preferences_display.cpp
|
||||
|
|
|
@ -266,7 +266,11 @@ wesnoth_sources = Split("""
|
|||
game_controller.cpp
|
||||
game_display.cpp
|
||||
game_errors.cpp
|
||||
game_events.cpp
|
||||
game_events/action_wml.cpp
|
||||
game_events/conditional_wml.cpp
|
||||
game_events/entity_location.cpp
|
||||
game_events/handlers.cpp
|
||||
game_events/pump.cpp
|
||||
game_instance.cpp
|
||||
game_preferences.cpp
|
||||
gamestatus.cpp
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "../attack_prediction.hpp"
|
||||
#include "../game_config.hpp"
|
||||
#include "../game_display.hpp"
|
||||
#include "../game_events.hpp"
|
||||
#include "../game_events/pump.hpp"
|
||||
#include "../game_preferences.hpp"
|
||||
#include "../gamestatus.hpp"
|
||||
#include "../gettext.hpp"
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include "../config.hpp"
|
||||
#include "../game_display.hpp"
|
||||
#include "../game_events.hpp"
|
||||
#include "../game_events/pump.hpp"
|
||||
#include "../game_preferences.hpp"
|
||||
#include "../gamestatus.hpp"
|
||||
#include "../gettext.hpp"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "vision.hpp"
|
||||
|
||||
#include "../game_display.hpp"
|
||||
#include "../game_events.hpp"
|
||||
#include "../game_events/pump.hpp"
|
||||
#include "../game_preferences.hpp"
|
||||
#include "../gettext.hpp"
|
||||
#include "../hotkeys.hpp"
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "move.hpp"
|
||||
|
||||
#include "../game_display.hpp"
|
||||
#include "../game_events.hpp"
|
||||
#include "../log.hpp"
|
||||
#include "../play_controller.hpp"
|
||||
#include "../replay.hpp"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "../config.hpp"
|
||||
#include "../game_display.hpp"
|
||||
#include "../game_events.hpp"
|
||||
#include "../game_events/pump.hpp"
|
||||
#include "../log.hpp"
|
||||
#include "../map.hpp"
|
||||
#include "../map_label.hpp"
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
#include "../formula_function.hpp"
|
||||
#include "../formula_fwd.hpp"
|
||||
#include "../game_display.hpp"
|
||||
#include "../game_events.hpp"
|
||||
#include "../log.hpp"
|
||||
#include "../map.hpp"
|
||||
#include "../mouse_handler_base.hpp"
|
||||
#include "../resources.hpp"
|
||||
#include "../tod_manager.hpp"
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include "../../array.hpp"
|
||||
#include "../../dialogs.hpp"
|
||||
#include "../../game_events.hpp"
|
||||
#include "../../game_events/pump.hpp"
|
||||
#include "../../gamestatus.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include "../../mouse_handler_base.hpp"
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "manager.hpp"
|
||||
#include "formula/ai.hpp"
|
||||
#include "registry.hpp"
|
||||
#include "../game_events.hpp"
|
||||
#include "../game_events/pump.hpp"
|
||||
#include "../log.hpp"
|
||||
#include "../serialization/string_utils.hpp"
|
||||
#include "composite/component.hpp"
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "actions/attack.hpp"
|
||||
#include "actions/undo.hpp"
|
||||
#include "dialogs.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_display.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "gui/dialogs/game_delete.hpp"
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#ifndef GAME_EVENTS_H_INCLUDED
|
||||
#define GAME_EVENTS_H_INCLUDED
|
||||
|
||||
#include "map.hpp"
|
||||
#include "unit_map.hpp"
|
||||
#include "variable.hpp"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Define the game's events mechanism.
|
||||
*
|
||||
* Events might be units moving or fighting, or when victory or defeat occurs.
|
||||
* A scenario's configuration file will define actions to take when certain events occur.
|
||||
* This module is responsible for making sure that when the events occur, the actions take place.
|
||||
*
|
||||
* Note that game events have nothing to do with SDL events,
|
||||
* like mouse movement, keyboard events, etc.
|
||||
* See events.hpp for how they are handled.
|
||||
*/
|
||||
|
||||
class unit;
|
||||
|
||||
namespace game_events
|
||||
{
|
||||
class event_handler;
|
||||
|
||||
/**
|
||||
* Changes a terrain location.
|
||||
* Ensures that villages are properly lost and that new terrains are discovered.
|
||||
*/
|
||||
void change_terrain(const map_location &loc, const t_translation::t_terrain &t,
|
||||
gamemap::tmerge_mode mode, bool replace_if_failed);
|
||||
|
||||
// The game event manager loads the scenario configuration object,
|
||||
// and ensures that events are handled according to the
|
||||
// scenario configuration for its lifetime.
|
||||
//
|
||||
// Thus, a manager object should be created when a scenario is played,
|
||||
// and destroyed at the end of the scenario.
|
||||
struct manager {
|
||||
/// Note that references will be maintained,
|
||||
/// and must remain valid for the life of the object.
|
||||
manager(const config& scenario_cfg);
|
||||
~manager();
|
||||
|
||||
// Allow iterating over the active handlers.
|
||||
typedef std::vector<event_handler> t_active;
|
||||
typedef t_active::iterator iterator;
|
||||
static iterator begin();
|
||||
static iterator end();
|
||||
|
||||
/// Starts buffering event handler creation.
|
||||
static void start_buffering();
|
||||
/// Ends buffering event handler creation.
|
||||
static void stop_buffering();
|
||||
/// Commits the event handlers that were buffered.
|
||||
static void commit_buffer();
|
||||
|
||||
/// Returns true when a manager exists, so events can be processed.
|
||||
static bool running() { return running_; }
|
||||
|
||||
private:
|
||||
variable::manager variable_manager;
|
||||
|
||||
static bool running_;
|
||||
};
|
||||
|
||||
struct entity_location : public map_location {
|
||||
entity_location(const map_location &loc, size_t id = 0);
|
||||
entity_location(const map_location &loc, size_t id,
|
||||
const map_location &filter_loc);
|
||||
explicit entity_location(const unit &);
|
||||
entity_location(const unit &u, const map_location &filter_loc);
|
||||
|
||||
int filter_x() const { return filter_loc_.x; }
|
||||
int filter_y() const { return filter_loc_.y; }
|
||||
bool matches_unit(const unit_map::const_iterator & un_it) const;
|
||||
bool matches_unit_filter(const unit_map::const_iterator & un_it,
|
||||
const vconfig & filter) const;
|
||||
|
||||
static const entity_location null_entity;
|
||||
|
||||
private:
|
||||
/// The underlying ID of the unit associated with this.
|
||||
/// Set to 0 if there is no associated unit.
|
||||
size_t id_;
|
||||
|
||||
/// This map_location allows a unit to be filtered as if it were
|
||||
/// somewhere other than where it is. (Use the parent struct if
|
||||
/// you want to locate the unit.)
|
||||
map_location filter_loc_;
|
||||
};
|
||||
|
||||
|
||||
struct queued_event {
|
||||
queued_event(const std::string& name, const entity_location& loc1,
|
||||
const entity_location& loc2,
|
||||
const config& data)
|
||||
: name(name), loc1(loc1), loc2(loc2),data(data) {}
|
||||
|
||||
std::string name;
|
||||
entity_location loc1;
|
||||
entity_location loc2;
|
||||
config data;
|
||||
};
|
||||
|
||||
class event_handler
|
||||
{
|
||||
public:
|
||||
event_handler(const config &cfg, bool is_menu_item = false);
|
||||
|
||||
bool matches_name(const std::string& name) const;
|
||||
|
||||
bool disabled() const { return disabled_; }
|
||||
bool is_menu_item() const { return is_menu_item_; }
|
||||
|
||||
void handle_event(const queued_event& event_info);
|
||||
|
||||
const config &get_config() const { return cfg_; }
|
||||
private:
|
||||
bool first_time_only_;
|
||||
bool disabled_;
|
||||
bool is_menu_item_;
|
||||
config cfg_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs the action handler associated to the command sequence @a cfg.
|
||||
*/
|
||||
void handle_event_commands(const queued_event &event_info, const vconfig &cfg);
|
||||
|
||||
/**
|
||||
* Runs the action handler associated to @a cmd with parameters @a cfg.
|
||||
*/
|
||||
void handle_event_command(const std::string &cmd,
|
||||
const queued_event &event_info, const vconfig &cfg);
|
||||
|
||||
void write_events(config& cfg);
|
||||
void add_events(
|
||||
const config::const_child_itors &cfgs,
|
||||
const std::string& type = std::string());
|
||||
|
||||
/** Used for [wml_message]. */
|
||||
void handle_wml_log_message(const config& cfg);
|
||||
/** Used for [deprecated_message]. */
|
||||
void handle_deprecated_message(const config& cfg);
|
||||
|
||||
/**
|
||||
* Function to fire an event.
|
||||
*
|
||||
* Events may have up to two arguments, both of which must be locations.
|
||||
*/
|
||||
bool 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());
|
||||
|
||||
void raise(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 conditional_passed(const vconfig& cond, bool backwards_compat=true);
|
||||
|
||||
/**
|
||||
* Handles newly-created handlers. Flushes WML messages and errors.
|
||||
*/
|
||||
void commit();
|
||||
|
||||
bool pump();
|
||||
|
||||
typedef void (*action_handler)(const queued_event &, const vconfig &);
|
||||
|
||||
/**
|
||||
* This function can be used to detect when no WML/Lua has been executed.
|
||||
*/
|
||||
size_t wml_tracking();
|
||||
|
||||
|
||||
// Declarations that will be more useful after the split:
|
||||
|
||||
typedef void (*wml_handler_function)(const queued_event &event_info,
|
||||
const vconfig &cfg);
|
||||
|
||||
/// Create an event handler.
|
||||
void add_event_handler(const config & event);
|
||||
/// Add a pending menu item command change.
|
||||
void add_wmi_change(const std::string & id, const config & new_command);
|
||||
/// Removes an event handler.
|
||||
void remove_event_handler(const std::string & id);
|
||||
/// Removes a pending menu item command change.
|
||||
void remove_wmi_change(const std::string & id);
|
||||
|
||||
/// Handles all the different types of actions that can be triggered by an event.
|
||||
void commit_wmi_commands();
|
||||
bool matches_special_filter(const config &cfg, const vconfig& filter);
|
||||
/// Helper function which determines whether a wml_message text can
|
||||
/// really be pushed into the wml_messages_stream, and does it.
|
||||
void put_wml_message(const std::string& logger, const std::string& message);
|
||||
|
||||
/// Registers a standard action handler.
|
||||
void register_action(const std::string & tag, wml_handler_function handler);
|
||||
|
||||
/// Checks if an item has been used.
|
||||
bool item_used(const std::string & id);
|
||||
/// Records if an item has been used.
|
||||
void item_used(const std::string & id, bool used);
|
||||
/// Returns whether or not we are skipping messages.
|
||||
bool skip_messages();
|
||||
/// Sets whether or not we are skipping messages.
|
||||
void skip_messages(bool skip);
|
||||
/// Returns whether or not the screen (map visuals) needs to be rebuilt.
|
||||
bool screen_needs_rebuild();
|
||||
/// Sets whether or not the screen (map visuals) needs to be rebuilt.
|
||||
void screen_needs_rebuild(bool rebuild);
|
||||
/// Returns whether or not we believe WML might have changed something.
|
||||
bool context_mutated();
|
||||
/// Sets whether or not we believe WML might have changed something.
|
||||
void context_mutated(bool mutated);
|
||||
|
||||
/// Clears all events tha have been raised (and not pumped).
|
||||
void clear_events();
|
||||
} // end namespace game_events
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
57
src/game_events/action_wml.hpp
Normal file
57
src/game_events/action_wml.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Define actions for the game's events mechanism.
|
||||
*
|
||||
* Events might be units moving or fighting, or when victory or defeat occurs.
|
||||
* A scenario's configuration file will define actions to take when certain events occur.
|
||||
* This module is responsible for implementing some of those actions (i.e. Action WML).
|
||||
* The actions not implemented in this module are implemented in Lua.
|
||||
*/
|
||||
|
||||
#ifndef GAME_EVENTS_ACTION_WML_H_INCLUDED
|
||||
#define GAME_EVENTS_ACTION_WML_H_INCLUDED
|
||||
|
||||
#include "../map.hpp"
|
||||
|
||||
class config;
|
||||
struct map_location;
|
||||
|
||||
namespace t_translation {
|
||||
struct t_terrain;
|
||||
}
|
||||
|
||||
|
||||
namespace game_events
|
||||
{
|
||||
// Most of the functionality in the source file is accessed via callbacks,
|
||||
// registered with register_action().
|
||||
|
||||
/**
|
||||
* Changes a terrain location.
|
||||
* Ensures that villages are properly lost and that new terrains are discovered.
|
||||
*/
|
||||
void change_terrain(const map_location &loc, const t_translation::t_terrain &t,
|
||||
gamemap::tmerge_mode mode, bool replace_if_failed);
|
||||
|
||||
/** Used for [deprecated_message]. */
|
||||
void handle_deprecated_message(const config& cfg);
|
||||
/** Used for [wml_message]. */
|
||||
void handle_wml_log_message(const config& cfg);
|
||||
}
|
||||
|
||||
#endif // GAME_EVENTS_ACTION_WML_H_INCLUDED
|
||||
|
236
src/game_events/conditional_wml.cpp
Normal file
236
src/game_events/conditional_wml.cpp
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implementations of conditional action WML tags.
|
||||
*/
|
||||
|
||||
#include "../global.hpp"
|
||||
#include "conditional_wml.hpp"
|
||||
|
||||
#include "../config.hpp"
|
||||
#include "../gamestatus.hpp"
|
||||
#include "../log.hpp"
|
||||
#include "../resources.hpp"
|
||||
#include "../serialization/string_utils.hpp"
|
||||
#include "../team.hpp"
|
||||
#include "../terrain_filter.hpp"
|
||||
#include "../unit.hpp"
|
||||
#include "../unit_map.hpp"
|
||||
#include "../unit_types.hpp"
|
||||
#include "../util.hpp"
|
||||
#include "../variable.hpp"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
|
||||
static lg::log_domain log_engine("engine");
|
||||
#define WRN_NG LOG_STREAM(warn, log_engine)
|
||||
|
||||
|
||||
// This file is in the game_events namespace.
|
||||
namespace game_events {
|
||||
|
||||
namespace { // Support functions
|
||||
|
||||
bool internal_conditional_passed(const vconfig& cond, bool& backwards_compat)
|
||||
{
|
||||
static std::vector<std::pair<int,int> > default_counts = utils::parse_ranges("1-99999");
|
||||
|
||||
// If the if statement requires we have a certain unit,
|
||||
// then check for that.
|
||||
const vconfig::child_list& have_unit = cond.get_children("have_unit");
|
||||
backwards_compat = backwards_compat && have_unit.empty();
|
||||
for(vconfig::child_list::const_iterator u = have_unit.begin(); u != have_unit.end(); ++u) {
|
||||
if(resources::units == NULL)
|
||||
return false;
|
||||
std::vector<std::pair<int,int> > counts = (*u).has_attribute("count")
|
||||
? utils::parse_ranges((*u)["count"]) : default_counts;
|
||||
int match_count = 0;
|
||||
BOOST_FOREACH(const unit &i, *resources::units)
|
||||
{
|
||||
if ( i.hitpoints() > 0 && i.matches_filter(*u) ) {
|
||||
++match_count;
|
||||
if(counts == default_counts) {
|
||||
// by default a single match is enough, so avoid extra work
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((*u)["search_recall_list"].to_bool())
|
||||
{
|
||||
for(std::vector<team>::iterator team = resources::teams->begin();
|
||||
team!=resources::teams->end(); ++team)
|
||||
{
|
||||
if(counts == default_counts && match_count) {
|
||||
break;
|
||||
}
|
||||
const std::vector<unit>& avail_units = team->recall_list();
|
||||
for(std::vector<unit>::const_iterator unit = avail_units.begin(); unit!=avail_units.end(); ++unit) {
|
||||
if(counts == default_counts && match_count) {
|
||||
break;
|
||||
}
|
||||
scoped_recall_unit auto_store("this_unit", team->save_id(), unit - avail_units.begin());
|
||||
if ( unit->matches_filter(*u) ) {
|
||||
++match_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!in_ranges(match_count, counts)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the if statement requires we have a certain location,
|
||||
// then check for that.
|
||||
const vconfig::child_list& have_location = cond.get_children("have_location");
|
||||
backwards_compat = backwards_compat && have_location.empty();
|
||||
for(vconfig::child_list::const_iterator v = have_location.begin(); v != have_location.end(); ++v) {
|
||||
std::set<map_location> res;
|
||||
terrain_filter(*v, *resources::units).get_locations(res);
|
||||
|
||||
std::vector<std::pair<int,int> > counts = (*v).has_attribute("count")
|
||||
? utils::parse_ranges((*v)["count"]) : default_counts;
|
||||
if(!in_ranges<int>(res.size(), counts)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check against each variable statement,
|
||||
// to see if the variable matches the conditions or not.
|
||||
const vconfig::child_list& variables = cond.get_children("variable");
|
||||
backwards_compat = backwards_compat && variables.empty();
|
||||
|
||||
BOOST_FOREACH(const vconfig &values, variables)
|
||||
{
|
||||
const std::string name = values["name"];
|
||||
config::attribute_value value = resources::gamedata->get_variable_const(name);
|
||||
|
||||
#define TEST_STR_ATTR(name, test) do { \
|
||||
if (values.has_attribute(name)) { \
|
||||
std::string attr_str = values[name].str(); \
|
||||
std::string str_value = value.str(); \
|
||||
if (!(test)) return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TEST_NUM_ATTR(name, test) do { \
|
||||
if (values.has_attribute(name)) { \
|
||||
double attr_num = values[name].to_double(); \
|
||||
double num_value = value.to_double(); \
|
||||
if (!(test)) return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TEST_BOL_ATTR(name, test) do { \
|
||||
if (values.has_attribute(name)) { \
|
||||
bool attr_bool = values[name].to_bool(); \
|
||||
bool bool_value = value.to_bool(); \
|
||||
if (!(test)) return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
TEST_STR_ATTR("equals", str_value == attr_str);
|
||||
TEST_STR_ATTR("not_equals", str_value != attr_str);
|
||||
TEST_NUM_ATTR("numerical_equals", num_value == attr_num);
|
||||
TEST_NUM_ATTR("numerical_not_equals", num_value != attr_num);
|
||||
TEST_NUM_ATTR("greater_than", num_value > attr_num);
|
||||
TEST_NUM_ATTR("less_than", num_value < attr_num);
|
||||
TEST_NUM_ATTR("greater_than_equal_to", num_value >= attr_num);
|
||||
TEST_NUM_ATTR("less_than_equal_to", num_value <= attr_num);
|
||||
TEST_BOL_ATTR("boolean_equals", bool_value == attr_bool);
|
||||
TEST_BOL_ATTR("boolean_not_equals", bool_value != attr_bool);
|
||||
TEST_STR_ATTR("contains", str_value.find(attr_str) != std::string::npos);
|
||||
|
||||
#undef TEST_STR_ATTR
|
||||
#undef TEST_NUM_ATTR
|
||||
#undef TEST_BOL_ATTR
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end anonymous namespace (support functions)
|
||||
|
||||
|
||||
bool conditional_passed(const vconfig& cond, bool backwards_compat)
|
||||
{
|
||||
bool allow_backwards_compat = backwards_compat = backwards_compat &&
|
||||
cond["backwards_compat"].to_bool(true);
|
||||
bool matches = internal_conditional_passed(cond, allow_backwards_compat);
|
||||
|
||||
// Handle [and], [or], and [not] with in-order precedence
|
||||
int or_count = 0;
|
||||
vconfig::all_children_iterator cond_i = cond.ordered_begin();
|
||||
vconfig::all_children_iterator cond_end = cond.ordered_end();
|
||||
while(cond_i != cond_end)
|
||||
{
|
||||
const std::string& cond_name = cond_i.get_key();
|
||||
const vconfig& cond_filter = cond_i.get_child();
|
||||
|
||||
// Handle [and]
|
||||
if(cond_name == "and")
|
||||
{
|
||||
matches = matches && conditional_passed(cond_filter, backwards_compat);
|
||||
backwards_compat = false;
|
||||
}
|
||||
// Handle [or]
|
||||
else if(cond_name == "or")
|
||||
{
|
||||
matches = matches || conditional_passed(cond_filter, backwards_compat);
|
||||
++or_count;
|
||||
}
|
||||
// Handle [not]
|
||||
else if(cond_name == "not")
|
||||
{
|
||||
matches = matches && !conditional_passed(cond_filter, backwards_compat);
|
||||
backwards_compat = false;
|
||||
}
|
||||
++cond_i;
|
||||
}
|
||||
// Check for deprecated [or] syntax
|
||||
if(matches && or_count > 1 && allow_backwards_compat)
|
||||
{
|
||||
///@deprecated r18803 [or] syntax
|
||||
lg::wml_error << "possible deprecated [or] syntax: now forcing re-interpretation\n";
|
||||
/**
|
||||
* @todo For now we will re-interpret it according to the old
|
||||
* rules, but this should be later to prevent re-interpretation
|
||||
* errors.
|
||||
*/
|
||||
const vconfig::child_list& orcfgs = cond.get_children("or");
|
||||
for(unsigned int i=0; i < orcfgs.size(); ++i) {
|
||||
if(conditional_passed(orcfgs[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
bool matches_special_filter(const config &cfg, const vconfig& filter)
|
||||
{
|
||||
if (!cfg) {
|
||||
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 attack_type attack(cfg);
|
||||
return attack.matches_filter(filter.get_parsed_config());
|
||||
}
|
||||
|
||||
} // end namespace game_events
|
||||
|
35
src/game_events/conditional_wml.hpp
Normal file
35
src/game_events/conditional_wml.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Define conditionals for the game's events mechanism,
|
||||
* a.k.a. conditional actions WML.
|
||||
*/
|
||||
|
||||
#ifndef GAME_EVENTS_CONDITIONAL_WML_H_INCLUDED
|
||||
#define GAME_EVENTS_CONDITIONAL_WML_H_INCLUDED
|
||||
|
||||
class config;
|
||||
class vconfig;
|
||||
|
||||
|
||||
namespace game_events
|
||||
{
|
||||
bool conditional_passed(const vconfig& cond, bool backwards_compat=true);
|
||||
bool matches_special_filter(const config &cfg, const vconfig& filter);
|
||||
}
|
||||
|
||||
#endif // GAME_EVENTS_CONDITIONAL_WML_H_INCLUDED
|
||||
|
106
src/game_events/entity_location.cpp
Normal file
106
src/game_events/entity_location.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The structure that tracks WML event locations.
|
||||
*/
|
||||
|
||||
#include "global.hpp"
|
||||
#include "entity_location.hpp"
|
||||
|
||||
#include "../unit.hpp"
|
||||
#include "../variable.hpp"
|
||||
|
||||
|
||||
// This file is in the game_events namespace.
|
||||
namespace game_events {
|
||||
|
||||
const entity_location entity_location::null_entity(map_location::null_location);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* unit's location and underlying ID.
|
||||
*/
|
||||
entity_location::entity_location(const map_location &loc, size_t id)
|
||||
: map_location(loc), id_(id), filter_loc_(loc)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor for when an event has a unit that needs to be filtered as if
|
||||
* it was in a different location.
|
||||
*/
|
||||
entity_location::entity_location(const map_location &loc, size_t id,
|
||||
const map_location & filter_loc)
|
||||
: map_location(loc), id_(id), filter_loc_(filter_loc)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Convenience constructor for when an event has a unit, saving the caller
|
||||
* the need to explicitly get the location and underlying ID.
|
||||
*/
|
||||
entity_location::entity_location(const unit &u)
|
||||
: map_location(u.get_location())
|
||||
, id_(u.underlying_id())
|
||||
, filter_loc_(*this)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Convenience constructor for when an event has a unit that needs to be
|
||||
* filtered as if it was in a different location, and the caller does not
|
||||
* want to explicitly get the unit's location and underlying ID.
|
||||
*/
|
||||
entity_location::entity_location(const unit &u, const map_location & filter_loc)
|
||||
: map_location(u.get_location())
|
||||
, id_(u.underlying_id())
|
||||
, filter_loc_(filter_loc)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if @a un_it matches (using underlying ID) the unit that was
|
||||
* supplied when this was constructed.
|
||||
* If no unit was supplied, then all units (including non-existent units)
|
||||
* match.
|
||||
*/
|
||||
bool entity_location::matches_unit(const unit_map::const_iterator & un_it) const
|
||||
{
|
||||
return id_ == 0 || ( un_it.valid() && id_ == un_it->underlying_id() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if @a un_it matches @a filter. If the filter is not empty,
|
||||
* the unit is required to additionally match the unit that was supplied
|
||||
* when this was constructed.
|
||||
*/
|
||||
bool entity_location::matches_unit_filter(const unit_map::const_iterator & un_it,
|
||||
const vconfig & filter) const
|
||||
{
|
||||
if ( !un_it.valid() )
|
||||
return false;
|
||||
|
||||
if ( filter.empty() )
|
||||
// Skip the check for un_it matching *this.
|
||||
return true;
|
||||
|
||||
// Filter the unit at the filter location (should be the unit's
|
||||
// location if no special filter location was specified).
|
||||
return un_it->matches_filter(filter, filter_loc_) &&
|
||||
matches_unit(un_it);
|
||||
}
|
||||
|
||||
} // end namespace game_events
|
||||
|
60
src/game_events/entity_location.hpp
Normal file
60
src/game_events/entity_location.hpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Define locations as used by the game's events mechanism.
|
||||
*/
|
||||
|
||||
#ifndef GAME_EVENTS_ENTITY_LOCATION_H_INCLUDED
|
||||
#define GAME_EVENTS_ENTITY_LOCATION_H_INCLUDED
|
||||
|
||||
#include "../map_location.hpp"
|
||||
#include "../unit_map.hpp"
|
||||
|
||||
class unit;
|
||||
class vconfig;
|
||||
|
||||
|
||||
namespace game_events
|
||||
{
|
||||
struct entity_location : public map_location {
|
||||
entity_location(const map_location &loc, size_t id = 0);
|
||||
entity_location(const map_location &loc, size_t id,
|
||||
const map_location &filter_loc);
|
||||
explicit entity_location(const unit &);
|
||||
entity_location(const unit &u, const map_location &filter_loc);
|
||||
|
||||
int filter_x() const { return filter_loc_.x; }
|
||||
int filter_y() const { return filter_loc_.y; }
|
||||
bool matches_unit(const unit_map::const_iterator & un_it) const;
|
||||
bool matches_unit_filter(const unit_map::const_iterator & un_it,
|
||||
const vconfig & filter) const;
|
||||
|
||||
static const entity_location null_entity;
|
||||
|
||||
private:
|
||||
/// The underlying ID of the unit associated with this.
|
||||
/// Set to 0 if there is no associated unit.
|
||||
size_t id_;
|
||||
|
||||
/// This map_location allows a unit to be filtered as if it were
|
||||
/// somewhere other than where it is. (Use the parent struct if
|
||||
/// you want to locate the unit.)
|
||||
map_location filter_loc_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // GAME_EVENTS_ENTITY_LOCATION_H_INCLUDED
|
||||
|
541
src/game_events/handlers.cpp
Normal file
541
src/game_events/handlers.cpp
Normal file
|
@ -0,0 +1,541 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The structure that tracks WML event handlers.
|
||||
* (Typically, handlers are defined by [event] tags.)
|
||||
*/
|
||||
|
||||
#include "global.hpp"
|
||||
#include "handlers.hpp"
|
||||
#include "pump.hpp"
|
||||
|
||||
#include "../formula_string_utils.hpp"
|
||||
#include "../gamestatus.hpp"
|
||||
#include "../log.hpp"
|
||||
#include "../reports.hpp"
|
||||
#include "../resources.hpp"
|
||||
#include "../scripting/lua.hpp"
|
||||
#include "../serialization/string_utils.hpp"
|
||||
#include "../soundsource.hpp"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
static lg::log_domain log_engine("engine");
|
||||
#define DBG_NG LOG_STREAM(debug, log_engine)
|
||||
#define LOG_NG LOG_STREAM(info, log_engine)
|
||||
#define WRN_NG LOG_STREAM(warn, log_engine)
|
||||
|
||||
static lg::log_domain log_event_handler("event_handler");
|
||||
#define DBG_EH LOG_STREAM(debug, log_event_handler)
|
||||
|
||||
|
||||
// This file is in the game_events namespace.
|
||||
namespace game_events {
|
||||
|
||||
namespace { // Types
|
||||
typedef std::map<std::string, wml_handler_function> static_wml_action_map;
|
||||
typedef std::pair< std::string, config* > wmi_command_change;
|
||||
|
||||
class t_event_handlers {
|
||||
typedef manager::t_active t_active;
|
||||
public:
|
||||
typedef t_active::iterator iterator;
|
||||
typedef t_active::const_iterator const_iterator;
|
||||
|
||||
private:
|
||||
t_active active_; ///Active event handlers
|
||||
t_active insert_buffer_; ///Event handlers added while pumping events
|
||||
std::set<std::string> remove_buffer_; ///Event handlers removed while pumping events
|
||||
bool buffering_;
|
||||
|
||||
|
||||
void log_handler(std::stringstream& ss,
|
||||
const std::vector<event_handler>& handlers,
|
||||
const std::string& msg)
|
||||
{
|
||||
BOOST_FOREACH(const event_handler& h, handlers){
|
||||
const config& cfg = h.get_config();
|
||||
ss << "name=" << cfg["name"] << ", with id=" << cfg["id"] << "; ";
|
||||
}
|
||||
DBG_EH << msg << " handlers are now " << ss.str() << "\n";
|
||||
ss.str(std::string());
|
||||
}
|
||||
|
||||
void log_handlers()
|
||||
{
|
||||
if(lg::debug.dont_log("event_handler")) return;
|
||||
|
||||
std::stringstream ss;
|
||||
log_handler(ss, active_, "active");
|
||||
log_handler(ss, insert_buffer_, "insert buffered");
|
||||
BOOST_FOREACH(const std::string& h, remove_buffer_){
|
||||
ss << "id=" << h << "; ";
|
||||
}
|
||||
DBG_EH << "remove buffered handlers are now " << ss.str() << "\n";
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
t_event_handlers()
|
||||
: active_(), insert_buffer_(), remove_buffer_(), buffering_(false)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Adds an event handler. An event with a nonempty ID will not
|
||||
* be added if an event with that ID already exists. This method
|
||||
* respects this class's buffering functionality.
|
||||
*/
|
||||
void add_event_handler(event_handler const & new_handler)
|
||||
{
|
||||
if(buffering_) {
|
||||
DBG_EH << "buffering event handler for name=" << new_handler.get_config()["name"] <<
|
||||
" with id " << new_handler.get_config()["id"] << "\n";
|
||||
insert_buffer_.push_back(new_handler);
|
||||
log_handlers();
|
||||
}
|
||||
else {
|
||||
const config & cfg = new_handler.get_config();
|
||||
std::string id = cfg["id"];
|
||||
if(!id.empty()) {
|
||||
BOOST_FOREACH( event_handler const & eh, active_ ) {
|
||||
config const & temp_config(eh.get_config());
|
||||
if(id == temp_config["id"]) {
|
||||
DBG_EH << "ignoring event handler for name=" << cfg["name"] <<
|
||||
" with id " << id << "\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
DBG_EH << "inserting event handler for name=" << cfg["name"] <<
|
||||
" with id=" << id << "\n";
|
||||
active_.push_back(new_handler);
|
||||
log_handlers();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an event handler, identified by its ID. Events with
|
||||
* empty IDs cannot be removed. This method respects this class's
|
||||
* buffering functionality.
|
||||
*/
|
||||
void remove_event_handler(std::string const & id)
|
||||
{
|
||||
if(id == "") { return; }
|
||||
|
||||
DBG_EH << "removing event handler with id " << id << "\n";
|
||||
|
||||
if(buffering_) { remove_buffer_.insert(id); }
|
||||
|
||||
t_active &temp = buffering_ ? insert_buffer_ : active_;
|
||||
|
||||
t_active::iterator i = temp.begin();
|
||||
while(i < temp.end()) {
|
||||
config const & temp_config = (*i).get_config();
|
||||
std::string event_id = temp_config["id"];
|
||||
if(event_id != "" && event_id == id) {
|
||||
i = temp.erase(i); }
|
||||
else {
|
||||
++i; }
|
||||
}
|
||||
log_handlers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts buffering. While buffering, any calls to add_event_handler
|
||||
* and remove_event_handler will not take effect until commit_buffer
|
||||
* is called. This function is idempotent - starting a buffer
|
||||
* when already buffering will not start a second buffer.
|
||||
*/
|
||||
void start_buffering()
|
||||
{
|
||||
buffering_ = true;
|
||||
DBG_EH << "starting buffering...\n";
|
||||
}
|
||||
|
||||
void stop_buffering()
|
||||
{
|
||||
DBG_EH << "stopping buffering...\n";
|
||||
buffering_ = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits all buffered events
|
||||
*/
|
||||
void commit_buffer()
|
||||
{
|
||||
DBG_EH << "committing buffered event handlers, buffering: " << buffering_ << "\n";
|
||||
if(buffering_)
|
||||
return;
|
||||
|
||||
// Commit any event removals
|
||||
BOOST_FOREACH( std::string const & i, remove_buffer_ ){
|
||||
remove_event_handler(i); }
|
||||
remove_buffer_.clear();
|
||||
|
||||
// Commit any spawned events-within-events
|
||||
BOOST_FOREACH( event_handler const & i, insert_buffer_ ){
|
||||
add_event_handler(i); }
|
||||
insert_buffer_.clear();
|
||||
|
||||
log_handlers();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
active_.clear();
|
||||
insert_buffer_.clear();
|
||||
remove_buffer_.clear();
|
||||
buffering_ = false;
|
||||
}
|
||||
|
||||
|
||||
iterator begin() { return active_.begin(); }
|
||||
const_iterator begin() const { return active_.begin(); }
|
||||
|
||||
iterator end() { return active_.end(); }
|
||||
const_iterator end() const { return active_.end(); }
|
||||
};
|
||||
}
|
||||
|
||||
namespace { // Variables
|
||||
t_event_handlers event_handlers;
|
||||
/** Map of the default action handlers known of the engine. */
|
||||
static_wml_action_map static_wml_actions;
|
||||
std::set<std::string> unit_wml_ids;
|
||||
std::set<std::string> used_items;
|
||||
std::vector< wmi_command_change > wmi_command_changes;
|
||||
} // end anonymous namespace (variables)
|
||||
|
||||
|
||||
/** Create an event handler. */
|
||||
void add_event_handler(const config & handler)
|
||||
{
|
||||
event_handlers.add_event_handler(event_handler(handler));
|
||||
}
|
||||
|
||||
/** Add a pending menu item command change. */
|
||||
void add_wmi_change(const std::string & id, const config & new_command)
|
||||
{
|
||||
wmi_command_changes.push_back(wmi_command_change(id, new config(new_command)));
|
||||
}
|
||||
|
||||
/** Handles all the different types of actions that can be triggered by an event. */
|
||||
void commit_wmi_commands()
|
||||
{
|
||||
// Commit WML Menu Item command changes
|
||||
while(wmi_command_changes.size() > 0) {
|
||||
wmi_command_change wcc = wmi_command_changes.front();
|
||||
const bool is_empty_command = wcc.second->empty();
|
||||
|
||||
wml_menu_item*& mref = resources::gamedata->get_wml_menu_items().get_item(wcc.first);
|
||||
const bool has_current_handler = !mref->command.empty();
|
||||
|
||||
config::attribute_value event_id = (*wcc.second)["id"];
|
||||
if(event_id.empty()) {
|
||||
event_id = mref->event_id;
|
||||
if(!event_id.empty())
|
||||
(*wcc.second)["id"] = event_id;
|
||||
}
|
||||
mref->command = *(wcc.second);
|
||||
mref->command["name"] = mref->name;
|
||||
mref->command["first_time_only"] = false;
|
||||
|
||||
if(has_current_handler) {
|
||||
BOOST_FOREACH(event_handler& hand, event_handlers) {
|
||||
if(hand.is_menu_item() && hand.matches_name(mref->name)) {
|
||||
LOG_NG << "changing command for " << mref->name << " to:\n" << *wcc.second;
|
||||
hand = event_handler(mref->command, true);
|
||||
}
|
||||
}
|
||||
} else if(!is_empty_command) {
|
||||
LOG_NG << "setting command for " << mref->name << " to:\n" << *wcc.second;
|
||||
event_handlers.add_event_handler(event_handler(mref->command, true));
|
||||
}
|
||||
|
||||
delete wcc.second;
|
||||
wmi_command_changes.erase(wmi_command_changes.begin());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an item has been used.
|
||||
* (An empty id will never be considered used.)
|
||||
*/
|
||||
bool item_used(const std::string & id)
|
||||
{
|
||||
return !id.empty() && used_items.count(id) > 0;
|
||||
}
|
||||
|
||||
/** Records if an item has been used. */
|
||||
void item_used(const std::string & id, bool used)
|
||||
{
|
||||
// Empty IDs are not tracked.
|
||||
if ( id.empty() )
|
||||
return;
|
||||
|
||||
if ( used )
|
||||
used_items.insert(id);
|
||||
else
|
||||
used_items.erase(id);
|
||||
}
|
||||
|
||||
/** Registers a standard action handler. */
|
||||
void register_action(const std::string & tag, wml_handler_function handler)
|
||||
{
|
||||
static_wml_actions[tag] = handler;
|
||||
}
|
||||
|
||||
/** Removes a pending menu item command change. */
|
||||
void remove_wmi_change(const std::string & id)
|
||||
{
|
||||
std::vector<wmi_command_change>::iterator wcc = wmi_command_changes.begin();
|
||||
while ( wcc != wmi_command_changes.end() ) {
|
||||
if ( wcc->first != id ) {
|
||||
++wcc;
|
||||
continue;
|
||||
}
|
||||
delete wcc->second;
|
||||
wcc->second = NULL;
|
||||
wcc = wmi_command_changes.erase(wcc);
|
||||
}
|
||||
}
|
||||
|
||||
/** Removes an event handler. */
|
||||
void remove_event_handler(const std::string & id)
|
||||
{
|
||||
event_handlers.remove_event_handler(id);
|
||||
}
|
||||
|
||||
|
||||
bool manager::running_ = false;
|
||||
|
||||
manager::manager(const config& cfg)
|
||||
: variable_manager()
|
||||
{
|
||||
assert(!running_);
|
||||
BOOST_FOREACH(const config &ev, cfg.child_range("event")) {
|
||||
add_event_handler(ev);
|
||||
}
|
||||
BOOST_FOREACH(const std::string &id, utils::split(cfg["unit_wml_ids"])) {
|
||||
unit_wml_ids.insert(id);
|
||||
}
|
||||
|
||||
resources::lua_kernel = new LuaKernel(cfg);
|
||||
running_ = true;
|
||||
|
||||
BOOST_FOREACH(static_wml_action_map::value_type &action, static_wml_actions) {
|
||||
resources::lua_kernel->set_wml_action(action.first, action.second);
|
||||
}
|
||||
|
||||
const std::string used = cfg["used_items"];
|
||||
if(!used.empty()) {
|
||||
const std::vector<std::string>& v = utils::split(used);
|
||||
for(std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||
item_used(*i, true);
|
||||
}
|
||||
}
|
||||
int wmi_count = 0;
|
||||
typedef std::pair<std::string, wml_menu_item *> item;
|
||||
BOOST_FOREACH(const item &itor, resources::gamedata->get_wml_menu_items().get_menu_items()) {
|
||||
if (!itor.second->command.empty()) {
|
||||
event_handlers.add_event_handler(event_handler(itor.second->command, true));
|
||||
}
|
||||
++wmi_count;
|
||||
}
|
||||
if(wmi_count > 0) {
|
||||
LOG_NG << wmi_count << " WML menu items found, loaded." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
manager::~manager() {
|
||||
assert(running_);
|
||||
running_ = false;
|
||||
clear_events();
|
||||
event_handlers.clear();
|
||||
reports::reset_generators();
|
||||
delete resources::lua_kernel;
|
||||
resources::lua_kernel = NULL;
|
||||
unit_wml_ids.clear();
|
||||
used_items.clear();
|
||||
}
|
||||
|
||||
/** Returns an iterator to the first event handler. */
|
||||
manager::iterator manager::begin()
|
||||
{
|
||||
return event_handlers.begin();
|
||||
}
|
||||
|
||||
/** Returns an iterator to one past the last event handler. */
|
||||
manager::iterator manager::end()
|
||||
{
|
||||
return event_handlers.end();
|
||||
}
|
||||
|
||||
/** Starts buffering event handler creation. */
|
||||
void manager::start_buffering()
|
||||
{
|
||||
event_handlers.start_buffering();
|
||||
}
|
||||
|
||||
/** Ends buffering event handler creation. */
|
||||
void manager::stop_buffering()
|
||||
{
|
||||
event_handlers.stop_buffering();
|
||||
}
|
||||
|
||||
/** Commits the event handlers that were buffered. */
|
||||
void manager::commit_buffer()
|
||||
{
|
||||
event_handlers.commit_buffer();
|
||||
}
|
||||
|
||||
|
||||
event_handler::event_handler(const config &cfg, bool imi) :
|
||||
first_time_only_(cfg["first_time_only"].to_bool(true)),
|
||||
disabled_(false), is_menu_item_(imi), cfg_(cfg)
|
||||
{}
|
||||
|
||||
void event_handler::handle_event(const queued_event& event_info)
|
||||
{
|
||||
if (first_time_only_)
|
||||
{
|
||||
disabled_ = true;
|
||||
}
|
||||
|
||||
if (is_menu_item_) {
|
||||
DBG_NG << cfg_["name"] << " will now invoke the following command(s):\n" << cfg_;
|
||||
}
|
||||
|
||||
handle_event_commands(event_info, vconfig(cfg_));
|
||||
}
|
||||
|
||||
bool event_handler::matches_name(const std::string &name) const
|
||||
{
|
||||
const std::string my_names =
|
||||
utils::interpolate_variables_into_string(cfg_["name"], *(resources::gamedata));
|
||||
std::string::const_iterator itor,
|
||||
it_begin = my_names.begin(),
|
||||
it_end = my_names.end(),
|
||||
match_it = name.begin(),
|
||||
match_begin = name.begin(),
|
||||
match_end = name.end();
|
||||
int skip_count = 0;
|
||||
for(itor = it_begin; itor != it_end; ++itor) {
|
||||
bool do_eat = false,
|
||||
do_skip = false;
|
||||
switch(*itor) {
|
||||
case ',':
|
||||
if(itor - it_begin - skip_count == match_it - match_begin && match_it == match_end) {
|
||||
return true;
|
||||
}
|
||||
it_begin = itor + 1;
|
||||
match_it = match_begin;
|
||||
skip_count = 0;
|
||||
continue;
|
||||
case '\f':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case '\v':
|
||||
do_skip = (match_it == match_begin || match_it == match_end);
|
||||
break;
|
||||
case ' ':
|
||||
do_skip = (match_it == match_begin || match_it == match_end);
|
||||
// fall through to case '_'
|
||||
case '_':
|
||||
do_eat = (match_it != match_end && (*match_it == ' ' || *match_it == '_'));
|
||||
break;
|
||||
default:
|
||||
do_eat = (match_it != match_end && *match_it == *itor);
|
||||
break;
|
||||
}
|
||||
if(do_eat) {
|
||||
++match_it;
|
||||
} else if(do_skip) {
|
||||
++skip_count;
|
||||
} else {
|
||||
itor = std::find(itor, it_end, ',');
|
||||
if(itor == it_end) {
|
||||
return false;
|
||||
}
|
||||
it_begin = itor + 1;
|
||||
match_it = match_begin;
|
||||
skip_count = 0;
|
||||
}
|
||||
}
|
||||
if(itor - it_begin - skip_count == match_it - match_begin && match_it == match_end) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void add_events(const config::const_child_itors &cfgs, const std::string& type)
|
||||
{
|
||||
if(!type.empty()) {
|
||||
if(std::find(unit_wml_ids.begin(),unit_wml_ids.end(),type) != unit_wml_ids.end()) return;
|
||||
unit_wml_ids.insert(type);
|
||||
}
|
||||
BOOST_FOREACH(const config &new_ev, cfgs) {
|
||||
if(type.empty() && new_ev["id"].empty())
|
||||
{
|
||||
WRN_NG << "attempt to add an [event] with empty id=, ignoring \n";
|
||||
continue;
|
||||
}
|
||||
add_event_handler(new_ev);
|
||||
}
|
||||
}
|
||||
|
||||
void write_events(config& cfg)
|
||||
{
|
||||
assert(manager::running());
|
||||
BOOST_FOREACH(const event_handler &eh, event_handlers) {
|
||||
if ( eh.disabled() || eh.is_menu_item() ) {
|
||||
continue;
|
||||
}
|
||||
cfg.add_child("event", eh.get_config());
|
||||
}
|
||||
|
||||
std::stringstream used;
|
||||
std::set<std::string>::const_iterator u;
|
||||
for(u = used_items.begin(); u != used_items.end(); ++u) {
|
||||
if(u != used_items.begin())
|
||||
used << ",";
|
||||
|
||||
used << *u;
|
||||
}
|
||||
|
||||
cfg["used_items"] = used.str();
|
||||
std::stringstream ids;
|
||||
for(u = unit_wml_ids.begin(); u != unit_wml_ids.end(); ++u) {
|
||||
if(u != unit_wml_ids.begin())
|
||||
ids << ",";
|
||||
|
||||
ids << *u;
|
||||
}
|
||||
|
||||
cfg["unit_wml_ids"] = ids.str();
|
||||
|
||||
if (resources::soundsources)
|
||||
resources::soundsources->write_sourcespecs(cfg);
|
||||
|
||||
resources::lua_kernel->save_game(cfg);
|
||||
}
|
||||
|
||||
} // end namespace game_events
|
||||
|
120
src/game_events/handlers.hpp
Normal file
120
src/game_events/handlers.hpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Define the handlers for the game's events mechanism.
|
||||
*
|
||||
* Events might be units moving or fighting, or when victory or defeat occurs.
|
||||
* A scenario's configuration file will define actions to take when certain events occur.
|
||||
* This module is responsible for tracking these definitions.
|
||||
*/
|
||||
|
||||
#ifndef GAME_EVENTS_HANDLERS_H_INCLUDED
|
||||
#define GAME_EVENTS_HANDLERS_H_INCLUDED
|
||||
|
||||
#include "../config.hpp"
|
||||
#include "../variable.hpp"
|
||||
|
||||
class vconfig;
|
||||
|
||||
|
||||
namespace game_events
|
||||
{
|
||||
struct queued_event;
|
||||
|
||||
|
||||
typedef void (*wml_handler_function)(const queued_event &event_info,
|
||||
const vconfig &cfg);
|
||||
typedef void (*action_handler)(const queued_event &, const vconfig &);
|
||||
|
||||
class event_handler
|
||||
{
|
||||
public:
|
||||
event_handler(const config &cfg, bool is_menu_item = false);
|
||||
|
||||
bool matches_name(const std::string& name) const;
|
||||
|
||||
bool disabled() const { return disabled_; }
|
||||
bool is_menu_item() const { return is_menu_item_; }
|
||||
|
||||
void handle_event(const queued_event& event_info);
|
||||
|
||||
const config &get_config() const { return cfg_; }
|
||||
|
||||
private:
|
||||
bool first_time_only_;
|
||||
bool disabled_;
|
||||
bool is_menu_item_;
|
||||
config cfg_;
|
||||
};
|
||||
|
||||
// The game event manager loads the scenario configuration object,
|
||||
// and ensures that events are handled according to the
|
||||
// scenario configuration for its lifetime.
|
||||
//
|
||||
// Thus, a manager object should be created when a scenario is played,
|
||||
// and destroyed at the end of the scenario.
|
||||
struct manager {
|
||||
/// Note that references will be maintained,
|
||||
/// and must remain valid for the life of the object.
|
||||
manager(const config& scenario_cfg);
|
||||
~manager();
|
||||
|
||||
// Allow iterating over the active handlers.
|
||||
typedef std::vector<event_handler> t_active;
|
||||
typedef t_active::iterator iterator;
|
||||
static iterator begin();
|
||||
static iterator end();
|
||||
|
||||
/// Starts buffering event handler creation.
|
||||
static void start_buffering();
|
||||
/// Ends buffering event handler creation.
|
||||
static void stop_buffering();
|
||||
/// Commits the event handlers that were buffered.
|
||||
static void commit_buffer();
|
||||
|
||||
/// Returns true when a manager exists, so events can be processed.
|
||||
static bool running() { return running_; }
|
||||
|
||||
private:
|
||||
variable::manager variable_manager;
|
||||
|
||||
static bool running_;
|
||||
};
|
||||
|
||||
/// Create an event handler.
|
||||
void add_event_handler(const config & event);
|
||||
/// Add a pending menu item command change.
|
||||
void add_wmi_change(const std::string & id, const config & new_command);
|
||||
/// Handles all the different types of actions that can be triggered by an event.
|
||||
void commit_wmi_commands();
|
||||
/// Checks if an item has been used.
|
||||
bool item_used(const std::string & id);
|
||||
/// Records if an item has been used.
|
||||
void item_used(const std::string & id, bool used);
|
||||
/// Registers a standard action handler.
|
||||
void register_action(const std::string & tag, wml_handler_function handler);
|
||||
/// Removes an event handler.
|
||||
void remove_event_handler(const std::string & id);
|
||||
/// Removes a pending menu item command change.
|
||||
void remove_wmi_change(const std::string & id);
|
||||
|
||||
void add_events(const config::const_child_itors &cfgs,
|
||||
const std::string& type = std::string());
|
||||
void write_events(config& cfg);
|
||||
}
|
||||
|
||||
#endif // GAME_EVENTS_HANDLERS_H_INCLUDED
|
||||
|
584
src/game_events/pump.cpp
Normal file
584
src/game_events/pump.cpp
Normal file
|
@ -0,0 +1,584 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Handles the current state of WML-events. This includes raising and firing,
|
||||
* as well as tracking the context for event firing.
|
||||
*/
|
||||
|
||||
#include "../global.hpp"
|
||||
#include "pump.hpp"
|
||||
#include "conditional_wml.hpp"
|
||||
|
||||
#include "../game_config.hpp"
|
||||
#include "../game_display.hpp"
|
||||
#include "../gamestatus.hpp"
|
||||
#include "../gettext.hpp"
|
||||
#include "../log.hpp"
|
||||
#include "../play_controller.hpp"
|
||||
#include "../resources.hpp"
|
||||
#include "../scripting/lua.hpp"
|
||||
#include "../side_filter.hpp"
|
||||
#include "../unit.hpp"
|
||||
#include "../unit_map.hpp"
|
||||
#include "../whiteboard/manager.hpp"
|
||||
#include "../variable.hpp"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
static lg::log_domain log_engine("engine");
|
||||
#define DBG_NG LOG_STREAM(debug, log_engine)
|
||||
#define LOG_NG LOG_STREAM(info, log_engine)
|
||||
#define ERR_NG LOG_STREAM(err, log_engine)
|
||||
|
||||
static lg::log_domain log_wml("wml");
|
||||
#define DBG_WML LOG_STREAM(debug, log_wml)
|
||||
#define LOG_WML LOG_STREAM(info, log_wml)
|
||||
#define WRN_WML LOG_STREAM(warn, log_wml)
|
||||
#define ERR_WML LOG_STREAM(err, log_wml)
|
||||
|
||||
static lg::log_domain log_event_handler("event_handler");
|
||||
#define DBG_EH LOG_STREAM(debug, log_event_handler)
|
||||
|
||||
// std::getline might be broken in Visual Studio so show a warning
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER < 1300
|
||||
#ifndef GETLINE_PATCHED
|
||||
#pragma message("warning: the std::getline implementation in your compiler might be broken.")
|
||||
#pragma message(" http://support.microsoft.com/default.aspx?scid=kb;EN-US;q240015")
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// This file is in the game_events namespace.
|
||||
namespace game_events {
|
||||
|
||||
namespace { // Types
|
||||
/**
|
||||
* State when processing a flight of events or commands.
|
||||
*/
|
||||
struct event_context
|
||||
{
|
||||
bool mutated;
|
||||
bool skip_messages;
|
||||
event_context(bool s): mutated(true), skip_messages(s) {}
|
||||
};
|
||||
event_context default_context(false);
|
||||
event_context *current_context = &default_context;
|
||||
|
||||
/**
|
||||
* Context state with automatic lifetime handling.
|
||||
*/
|
||||
struct scoped_context
|
||||
{
|
||||
event_context *old_context;
|
||||
event_context new_context;
|
||||
|
||||
scoped_context()
|
||||
: old_context(current_context)
|
||||
, new_context(old_context != &default_context && old_context->skip_messages)
|
||||
{
|
||||
current_context = &new_context;
|
||||
}
|
||||
|
||||
~scoped_context()
|
||||
{
|
||||
old_context->mutated |= new_context.mutated;
|
||||
current_context = old_context;
|
||||
}
|
||||
};
|
||||
|
||||
class pump_manager {
|
||||
public:
|
||||
pump_manager() :
|
||||
x1_(resources::gamedata->get_variable("x1")),
|
||||
x2_(resources::gamedata->get_variable("x2")),
|
||||
y1_(resources::gamedata->get_variable("y1")),
|
||||
y2_(resources::gamedata->get_variable("y2"))
|
||||
{
|
||||
++instance_count;
|
||||
}
|
||||
~pump_manager() {
|
||||
resources::gamedata->get_variable("x1") = x1_;
|
||||
resources::gamedata->get_variable("x2") = x2_;
|
||||
resources::gamedata->get_variable("y1") = y1_;
|
||||
resources::gamedata->get_variable("y2") = y2_;
|
||||
--instance_count;
|
||||
}
|
||||
static unsigned count() {
|
||||
return instance_count;
|
||||
}
|
||||
private:
|
||||
static unsigned instance_count;
|
||||
int x1_, x2_, y1_, y2_;
|
||||
};
|
||||
unsigned pump_manager::instance_count=0;
|
||||
} // end anonymous namespace (types)
|
||||
|
||||
namespace { // Variables
|
||||
std::deque<queued_event> events_queue;
|
||||
|
||||
bool does_screen_need_rebuild = false;
|
||||
/// The value returned by wml_tracking();
|
||||
size_t internal_wml_tracking = 0;
|
||||
|
||||
std::stringstream wml_messages_stream;
|
||||
} // end anonymous namespace (variables)
|
||||
|
||||
namespace { // Support functions
|
||||
|
||||
inline bool events_init()
|
||||
{
|
||||
return resources::screen != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff the given event passes all its filters.
|
||||
*/
|
||||
bool filter_event(const event_handler& handler, const queued_event& ev)
|
||||
{
|
||||
const unit_map *units = resources::units;
|
||||
unit_map::const_iterator unit1 = units->find(ev.loc1);
|
||||
unit_map::const_iterator unit2 = units->find(ev.loc2);
|
||||
vconfig filters(handler.get_config());
|
||||
|
||||
BOOST_FOREACH(const vconfig &condition, filters.get_children("filter_condition"))
|
||||
{
|
||||
if (!conditional_passed(condition)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const vconfig &f, filters.get_children("filter_side"))
|
||||
{
|
||||
side_filter ssf(f);
|
||||
if ( !ssf.match(resources::controller->current_side()) )
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const vconfig &f, filters.get_children("filter"))
|
||||
{
|
||||
if ( !ev.loc1.matches_unit_filter(unit1, f) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
vconfig::child_list special_filters = filters.get_children("filter_attack");
|
||||
bool special_matches = special_filters.empty();
|
||||
if ( !special_matches && unit1 != units->end() )
|
||||
{
|
||||
const bool matches_unit = ev.loc1.matches_unit(unit1);
|
||||
const config & attack = ev.data.child("first");
|
||||
BOOST_FOREACH(const vconfig &f, special_filters)
|
||||
{
|
||||
if ( f.empty() )
|
||||
special_matches = true;
|
||||
else if ( !matches_unit )
|
||||
return false;
|
||||
|
||||
special_matches = special_matches ||
|
||||
matches_special_filter(attack, f);
|
||||
}
|
||||
}
|
||||
if(!special_matches) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const vconfig &f, filters.get_children("filter_second"))
|
||||
{
|
||||
if ( !ev.loc2.matches_unit_filter(unit2, f) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
special_filters = filters.get_children("filter_second_attack");
|
||||
special_matches = special_filters.empty();
|
||||
if ( !special_matches && unit2 != units->end() )
|
||||
{
|
||||
const bool matches_unit = ev.loc2.matches_unit(unit2);
|
||||
const config & attack = ev.data.child("second");
|
||||
BOOST_FOREACH(const vconfig &f, special_filters)
|
||||
{
|
||||
if ( f.empty() )
|
||||
special_matches = true;
|
||||
else if ( !matches_unit )
|
||||
return false;
|
||||
|
||||
special_matches = special_matches ||
|
||||
matches_special_filter(attack, f);
|
||||
}
|
||||
}
|
||||
if(!special_matches) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All filters passed.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_event(event_handler& handler, const queued_event& ev)
|
||||
{
|
||||
if(handler.disabled())
|
||||
return false;
|
||||
|
||||
unit_map *units = resources::units;
|
||||
scoped_xy_unit first_unit("unit", ev.loc1.x, ev.loc1.y, *units);
|
||||
scoped_xy_unit second_unit("second_unit", ev.loc2.x, ev.loc2.y, *units);
|
||||
scoped_weapon_info first_weapon("weapon", ev.data.child("first"));
|
||||
scoped_weapon_info second_weapon("second_weapon", ev.data.child("second"));
|
||||
|
||||
if ( !filter_event(handler, ev) )
|
||||
return false;
|
||||
|
||||
// The event hasn't been filtered out, so execute the handler.
|
||||
++internal_wml_tracking;
|
||||
scoped_context evc;
|
||||
handler.handle_event(ev);
|
||||
|
||||
if(ev.name == "select") {
|
||||
resources::gamedata->last_selected = ev.loc1;
|
||||
}
|
||||
|
||||
if ( screen_needs_rebuild() ) {
|
||||
screen_needs_rebuild(false);
|
||||
game_display *screen = resources::screen;
|
||||
screen->recalculate_minimap();
|
||||
screen->invalidate_all();
|
||||
screen->rebuild_all();
|
||||
}
|
||||
|
||||
return context_mutated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for show_wml_errors(), which gathers
|
||||
* the messages from a stringstream.
|
||||
*/
|
||||
void fill_wml_messages_map(std::map<std::string, int>& msg_map, std::stringstream& source)
|
||||
{
|
||||
while(true) {
|
||||
std::string msg;
|
||||
std::getline(source, msg);
|
||||
|
||||
if(source.eof()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(msg == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(msg_map.find(msg) == msg_map.end()) {
|
||||
msg_map[msg] = 1;
|
||||
} else {
|
||||
msg_map[msg]++;
|
||||
}
|
||||
}
|
||||
// Make sure the eof flag is cleared otherwise no new messages are shown
|
||||
source.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a summary of the errors encountered in WML so far,
|
||||
* to avoid a lot of the same messages to be shown.
|
||||
* Identical messages are shown once, with (between braces)
|
||||
* the number of times that message was encountered.
|
||||
* The order in which the messages are shown does not need
|
||||
* to be the order in which these messages are encountered.
|
||||
* Messages are always written to std::cerr.
|
||||
*/
|
||||
void show_wml_errors()
|
||||
{
|
||||
// Get all unique messages in messages,
|
||||
// with the number of encounters for these messages
|
||||
std::map<std::string, int> messages;
|
||||
fill_wml_messages_map(messages, lg::wml_error);
|
||||
|
||||
// Show the messages collected
|
||||
const std::string caption = "Invalid WML found";
|
||||
for(std::map<std::string, int>::const_iterator itor = messages.begin();
|
||||
itor != messages.end(); ++itor) {
|
||||
|
||||
std::stringstream msg;
|
||||
msg << itor->first;
|
||||
if(itor->second > 1) {
|
||||
msg << " (" << itor->second << ")";
|
||||
}
|
||||
|
||||
resources::screen->add_chat_message(time(NULL), caption, 0, msg.str(),
|
||||
events::chat_handler::MESSAGE_PUBLIC, false);
|
||||
std::cerr << caption << ": " << msg.str() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void show_wml_messages()
|
||||
{
|
||||
// Get all unique messages in messages,
|
||||
// with the number of encounters for these messages
|
||||
std::map<std::string, int> messages;
|
||||
fill_wml_messages_map(messages, wml_messages_stream);
|
||||
|
||||
// Show the messages collected
|
||||
const std::string caption = "WML";
|
||||
for(std::map<std::string, int>::const_iterator itor = messages.begin();
|
||||
itor != messages.end(); ++itor) {
|
||||
|
||||
std::stringstream msg;
|
||||
msg << itor->first;
|
||||
if(itor->second > 1) {
|
||||
msg << " (" << itor->second << ")";
|
||||
}
|
||||
|
||||
resources::screen->add_chat_message(time(NULL), caption, 0, msg.str(),
|
||||
events::chat_handler::MESSAGE_PUBLIC, false);
|
||||
}
|
||||
}
|
||||
|
||||
} // end anonymous namespace (support functions)
|
||||
|
||||
|
||||
/** Returns whether or not we believe WML might have changed something. */
|
||||
bool context_mutated()
|
||||
{
|
||||
return current_context->mutated;
|
||||
}
|
||||
|
||||
/** Sets whether or not we believe WML might have changed something. */
|
||||
void context_mutated(bool mutated)
|
||||
{
|
||||
current_context->mutated = mutated;
|
||||
}
|
||||
|
||||
/** Returns whether or not the screen (map visuals) needs to be rebuilt. */
|
||||
bool screen_needs_rebuild()
|
||||
{
|
||||
return does_screen_need_rebuild;
|
||||
}
|
||||
|
||||
/** Sets whether or not the screen (map visuals) needs to be rebuilt. */
|
||||
void screen_needs_rebuild(bool rebuild)
|
||||
{
|
||||
does_screen_need_rebuild = rebuild;
|
||||
}
|
||||
|
||||
/** Returns whether or not we are skipping messages. */
|
||||
bool skip_messages()
|
||||
{
|
||||
return current_context->skip_messages;
|
||||
}
|
||||
|
||||
/** Sets whether or not we are skipping messages. */
|
||||
void skip_messages(bool skip)
|
||||
{
|
||||
current_context->skip_messages = skip;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function which determines whether a wml_message text can
|
||||
* really be pushed into the wml_messages_stream, and does it.
|
||||
*/
|
||||
void put_wml_message(const std::string& logger, const std::string& message)
|
||||
{
|
||||
if (logger == "err" || logger == "error") {
|
||||
ERR_WML << message << "\n";
|
||||
wml_messages_stream << _("Error: ") << message << "\n";
|
||||
} else if (logger == "warn" || logger == "wrn" || logger == "warning") {
|
||||
WRN_WML << message << "\n";
|
||||
wml_messages_stream << _("Warning: ") << message << "\n";
|
||||
} else if ((logger == "debug" || logger == "dbg") && !lg::debug.dont_log(log_wml)) {
|
||||
DBG_WML << message << "\n";
|
||||
wml_messages_stream << _("Debug: ") << message << "\n";
|
||||
} else if (!lg::info.dont_log(log_wml)) {
|
||||
LOG_WML << message << "\n";
|
||||
wml_messages_stream << _("Info: ") << message << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handle_event_commands(const queued_event& event_info, const vconfig &cfg)
|
||||
{
|
||||
resources::lua_kernel->run_wml_action("command", cfg, event_info);
|
||||
}
|
||||
|
||||
void handle_event_command(const std::string &cmd,
|
||||
const queued_event &event_info, const vconfig &cfg)
|
||||
{
|
||||
log_scope2(log_engine, "handle_event_command");
|
||||
LOG_NG << "handling command '" << cmd << "' from "
|
||||
<< (cfg.is_volatile()?"volatile ":"") << "cfg 0x"
|
||||
<< std::hex << std::setiosflags(std::ios::uppercase)
|
||||
<< reinterpret_cast<uintptr_t>(&cfg.get_config()) << std::dec << "\n";
|
||||
|
||||
if (!resources::lua_kernel->run_wml_action(cmd, cfg, event_info))
|
||||
{
|
||||
ERR_NG << "Couldn't find function for wml tag: "<< cmd <<"\n";
|
||||
}
|
||||
|
||||
DBG_NG << "done handling command...\n";
|
||||
}
|
||||
|
||||
|
||||
bool fire(const std::string& event,
|
||||
const entity_location& loc1,
|
||||
const entity_location& loc2,
|
||||
const config& data)
|
||||
{
|
||||
assert(manager::running());
|
||||
raise(event,loc1,loc2,data);
|
||||
return pump();
|
||||
}
|
||||
|
||||
void raise(const std::string& event,
|
||||
const entity_location& loc1,
|
||||
const entity_location& loc2,
|
||||
const config& data)
|
||||
{
|
||||
assert(manager::running());
|
||||
if(!events_init())
|
||||
return;
|
||||
|
||||
DBG_EH << "raising event: " << event << "\n";
|
||||
|
||||
events_queue.push_back(queued_event(event, loc1, loc2, data));
|
||||
}
|
||||
|
||||
bool pump()
|
||||
{
|
||||
//ensure the whiteboard doesn't attempt to build its future unit map
|
||||
//for the duration of this method
|
||||
wb::real_map real_unit_map;
|
||||
|
||||
assert(manager::running());
|
||||
if(!events_init())
|
||||
return false;
|
||||
|
||||
pump_manager pump_instance;
|
||||
if(pump_manager::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;
|
||||
}
|
||||
|
||||
if(!lg::debug.dont_log("event_handler")) {
|
||||
std::stringstream ss;
|
||||
BOOST_FOREACH(const queued_event& ev, events_queue) {
|
||||
ss << "name=" << ev.name << "; ";
|
||||
}
|
||||
DBG_EH << "processing queued events: " << ss.str() << "\n";
|
||||
}
|
||||
|
||||
const size_t old_wml_track = internal_wml_tracking;
|
||||
|
||||
bool result = false;
|
||||
while(events_queue.empty() == false) {
|
||||
if(pump_manager::count() <= 1)
|
||||
manager::start_buffering();
|
||||
queued_event ev = events_queue.front();
|
||||
events_queue.pop_front(); // pop now for exception safety
|
||||
const std::string& event_name = ev.name;
|
||||
|
||||
// Clear the unit cache, since the best clearing time is hard to figure out
|
||||
// due to status changes by WML. Every event will flush the cache.
|
||||
unit::clear_status_caches();
|
||||
|
||||
if ( resources::lua_kernel->run_event(ev) )
|
||||
++internal_wml_tracking;
|
||||
|
||||
bool init_event_vars = true;
|
||||
|
||||
manager::iterator end_handler = manager::end();
|
||||
manager::iterator cur_handler = manager::begin();
|
||||
for ( ; cur_handler != end_handler; ++cur_handler ) {
|
||||
event_handler & handler = *cur_handler;
|
||||
if(!handler.matches_name(event_name))
|
||||
continue;
|
||||
// Set the variables for the event
|
||||
if (init_event_vars) {
|
||||
resources::gamedata->get_variable("x1") = ev.loc1.filter_x() + 1;
|
||||
resources::gamedata->get_variable("y1") = ev.loc1.filter_y() + 1;
|
||||
resources::gamedata->get_variable("x2") = ev.loc2.filter_x() + 1;
|
||||
resources::gamedata->get_variable("y2") = ev.loc2.filter_y() + 1;
|
||||
init_event_vars = false;
|
||||
}
|
||||
|
||||
DBG_EH << "processing event " << event_name << " with id="<<
|
||||
handler.get_config()["id"] << "\n";
|
||||
if(process_event(handler, ev))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(pump_manager::count() <= 1)
|
||||
manager::stop_buffering();
|
||||
// Only commit new handlers when finished iterating over event_handlers.
|
||||
commit();
|
||||
}
|
||||
|
||||
if ( old_wml_track != internal_wml_tracking )
|
||||
// Notify the whiteboard of any event.
|
||||
// This is used to track when moves, recruits, etc. happen.
|
||||
resources::whiteboard->on_gamestate_change();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Clears all events tha have been raised (and not pumped). */
|
||||
void clear_events()
|
||||
{
|
||||
events_queue.clear();
|
||||
}
|
||||
|
||||
void commit()
|
||||
{
|
||||
DBG_EH << "committing new event handlers, number of pump_instances: " <<
|
||||
pump_manager::count() << "\n";
|
||||
manager::commit_buffer();
|
||||
commit_wmi_commands();
|
||||
// Dialogs can only be shown if the display is not locked
|
||||
if (!resources::screen->video().update_locked()) {
|
||||
show_wml_errors();
|
||||
show_wml_messages();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
} // end namespace game_events
|
||||
|
114
src/game_events/pump.hpp
Normal file
114
src/game_events/pump.hpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Define the game's event mechanism.
|
||||
*
|
||||
* Events might be units moving or fighting, or when victory or defeat occurs.
|
||||
* A scenario's configuration file will define actions to take when certain events occur.
|
||||
* This module is responsible for the processing of events.
|
||||
*
|
||||
* Note that game events have nothing to do with SDL events,
|
||||
* like mouse movement, keyboard events, etc.
|
||||
* See events.hpp for how they are handled.
|
||||
*/
|
||||
|
||||
#ifndef GAME_EVENTS_PUMP_H_INCLUDED
|
||||
#define GAME_EVENTS_PUMP_H_INCLUDED
|
||||
|
||||
#include "entity_location.hpp"
|
||||
#include "../config.hpp"
|
||||
|
||||
class vconfig;
|
||||
|
||||
|
||||
namespace game_events
|
||||
{
|
||||
struct queued_event {
|
||||
queued_event(const std::string& name, const entity_location& loc1,
|
||||
const entity_location& loc2, const config& data)
|
||||
: name(name), loc1(loc1), loc2(loc2), data(data)
|
||||
{}
|
||||
|
||||
std::string name;
|
||||
entity_location loc1;
|
||||
entity_location loc2;
|
||||
config data;
|
||||
};
|
||||
|
||||
|
||||
/// Returns whether or not we believe WML might have changed something.
|
||||
bool context_mutated();
|
||||
/// Sets whether or not we believe WML might have changed something.
|
||||
void context_mutated(bool mutated);
|
||||
/// Returns whether or not the screen (map visuals) needs to be rebuilt.
|
||||
bool screen_needs_rebuild();
|
||||
/// Sets whether or not the screen (map visuals) needs to be rebuilt.
|
||||
void screen_needs_rebuild(bool rebuild);
|
||||
/// Returns whether or not we are skipping messages.
|
||||
bool skip_messages();
|
||||
/// Sets whether or not we are skipping messages.
|
||||
void skip_messages(bool skip);
|
||||
|
||||
/// Helper function which determines whether a wml_message text can
|
||||
/// really be pushed into the wml_messages_stream, and does it.
|
||||
void put_wml_message(const std::string& logger, const std::string& message);
|
||||
|
||||
/**
|
||||
* Runs the action handler associated to the command sequence @a cfg.
|
||||
*/
|
||||
void handle_event_commands(const queued_event &event_info, const vconfig &cfg);
|
||||
|
||||
/**
|
||||
* Runs the action handler associated to @a cmd with parameters @a cfg.
|
||||
*/
|
||||
void handle_event_command(const std::string &cmd,
|
||||
const queued_event &event_info, const vconfig &cfg);
|
||||
|
||||
|
||||
/**
|
||||
* Function to fire an event.
|
||||
*
|
||||
* Events may have up to two arguments, both of which must be locations.
|
||||
*/
|
||||
bool 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());
|
||||
|
||||
void raise(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 pump();
|
||||
|
||||
/// Clears all events tha have been raised (and not pumped).
|
||||
void clear_events();
|
||||
|
||||
/**
|
||||
* Handles newly-created handlers. Flushes WML messages and errors.
|
||||
*/
|
||||
void commit();
|
||||
|
||||
/**
|
||||
* This function can be used to detect when no WML/Lua has been executed.
|
||||
*/
|
||||
size_t wml_tracking();
|
||||
|
||||
}
|
||||
|
||||
#endif // GAME_EVENTS_PUMP_H_INCLUDED
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "actions/create.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "game_events/handlers.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "log.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
|
@ -43,7 +44,6 @@
|
|||
#include "whiteboard/side_actions.hpp"
|
||||
#include "sound.hpp"
|
||||
#include "soundsource.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "map_label.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "formatter.hpp"
|
||||
#include "filechooser.hpp"
|
||||
#include "game_end_exceptions.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/pump.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "gui/dialogs/chat_log.hpp"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "attack_prediction_display.hpp"
|
||||
#include "dialogs.hpp"
|
||||
#include "game_end_exceptions.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/pump.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "gui/dialogs/unit_attack.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
#include "actions/undo.hpp"
|
||||
#include "actions/vision.hpp"
|
||||
#include "dialogs.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/conditional_wml.hpp"
|
||||
#include "game_events/handlers.hpp"
|
||||
#include "game_events/pump.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "halo.hpp"
|
||||
#include "loadscreen.hpp"
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
Copyright (C) 2006 - 2013 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
|
||||
wesnoth playlevel Copyright (C) 2003 by David White <dave@whitevine.net>
|
||||
|
@ -27,7 +26,7 @@
|
|||
#include "ai/testing.hpp"
|
||||
#include "dialogs.hpp"
|
||||
#include "game_end_exceptions.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/pump.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "gui/dialogs/transient_message.hpp"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "dialogs.hpp"
|
||||
#include "game_display.hpp"
|
||||
#include "game_end_exceptions.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/pump.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "log.hpp"
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "actions/vision.hpp"
|
||||
#include "game_end_exceptions.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/handlers.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "log.hpp"
|
||||
#include "map_label.hpp"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "sound.hpp"
|
||||
#include "soundsource.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/handlers.hpp"
|
||||
|
||||
namespace savegame {
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
#include "attack_prediction.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "game_display.hpp"
|
||||
#include "game_events/action_wml.hpp"
|
||||
#include "game_events/conditional_wml.hpp"
|
||||
#include "game_events/pump.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "log.hpp"
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
#ifndef SCRIPTING_LUA_HPP
|
||||
#define SCRIPTING_LUA_HPP
|
||||
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/handlers.hpp"
|
||||
|
||||
class unit;
|
||||
struct lua_State;
|
||||
|
||||
namespace ai {
|
||||
|
@ -25,6 +26,10 @@ class lua_ai_context;
|
|||
class engine_lua;
|
||||
} // of namespace ai
|
||||
|
||||
namespace game_events {
|
||||
struct queued_event;
|
||||
}
|
||||
|
||||
void extract_preload_scripts(config const &);
|
||||
|
||||
class LuaKernel
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include "variable.hpp"
|
||||
|
||||
#include "display.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/action_wml.hpp"
|
||||
#include "game_events/conditional_wml.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "intro.hpp"
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "storyscreen/controller.hpp"
|
||||
|
||||
#include "display.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "intro.hpp"
|
||||
#include "language.hpp"
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
#include "config.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/action_wml.hpp"
|
||||
#include "game_events/conditional_wml.hpp"
|
||||
#include "image.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
#include "util.hpp"
|
||||
|
|
|
@ -20,8 +20,9 @@
|
|||
#include "team.hpp"
|
||||
|
||||
#include "ai/manager.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "game_events/pump.hpp"
|
||||
#include "gamestatus.hpp"
|
||||
#include "map.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "whiteboard/side_actions.hpp"
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "unit_display.hpp"
|
||||
|
||||
#include "game_preferences.hpp"
|
||||
#include "game_events.hpp"
|
||||
#include "log.hpp"
|
||||
#include "mouse_events.hpp"
|
||||
#include "resources.hpp"
|
||||
|
|
Loading…
Add table
Reference in a new issue