mirror of
https://github.com/wesnoth/wesnoth
synced 2025-04-18 19:26:11 +00:00
741 lines
20 KiB
C++
741 lines
20 KiB
C++
/* $Id$ */
|
|
/*
|
|
Copyright (C) 2003 by David White <davidnwhite@optusnet.com.au>
|
|
Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
|
|
See the COPYING file for more details.
|
|
*/
|
|
#include "game_events.hpp"
|
|
#include "menu.hpp"
|
|
#include "language.hpp"
|
|
#include "playlevel.hpp"
|
|
#include "replay.hpp"
|
|
|
|
#include <cstdlib>
|
|
#include <deque>
|
|
#include <iostream>
|
|
#include <set>
|
|
#include <string>
|
|
|
|
namespace game_events {
|
|
|
|
bool conditional_passed(game_state& state_of_game,
|
|
const std::map<gamemap::location,unit>* units,
|
|
config& cond)
|
|
{
|
|
//if the if statement requires we have a certain unit, then
|
|
//check for that.
|
|
std::vector<config*>& have_unit = cond.children["have_unit"];
|
|
|
|
for(std::vector<config*>::iterator u = have_unit.begin();
|
|
u != have_unit.end(); ++u) {
|
|
|
|
if(units == NULL)
|
|
return false;
|
|
|
|
std::map<gamemap::location,unit>::const_iterator itor;
|
|
for(itor = units->begin(); itor != units->end(); ++itor) {
|
|
if(itor->second.matches_filter(**u)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(itor == units->end()) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//check against each variable statement to see if the variable
|
|
//matches the conditions or not
|
|
std::vector<config*>& variables = cond.children["variable"];
|
|
for(std::vector<config*>::iterator var = variables.begin();
|
|
var != variables.end(); ++var) {
|
|
std::map<std::string,std::string>& values = (*var)->values;
|
|
std::map<std::string,std::string>& vars = state_of_game.variables;
|
|
const std::string& name = values["name"];
|
|
|
|
//if we don't have a record of the variable, then the statement
|
|
//is not true, unless it's a not equals statement, in which it's
|
|
//automatically true
|
|
if(vars.find(name) == vars.end()) {
|
|
if(values.find("not_equals") == values.end() &&
|
|
values.find("numerical_not_equals") == values.end()) {
|
|
return false;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
const std::string& value = vars[name];
|
|
const double num_value = atof(value.c_str());
|
|
|
|
std::map<std::string,std::string>::iterator itor;
|
|
|
|
itor = values.find("equals");
|
|
if(itor != values.end() && itor->second != value) {
|
|
return false;
|
|
}
|
|
|
|
itor = values.find("numerical_equals");
|
|
if(itor != values.end() && atof(itor->second.c_str()) != num_value){
|
|
return false;
|
|
}
|
|
|
|
itor = values.find("not_equals");
|
|
if(itor != values.end() && itor->second == value) {
|
|
return false;
|
|
}
|
|
|
|
itor = values.find("numerical_not_equals");
|
|
if(itor != values.end() && atof(itor->second.c_str()) == num_value){
|
|
return false;
|
|
}
|
|
|
|
itor = values.find("greater_than");
|
|
if(itor != values.end() && atof(itor->second.c_str()) >= num_value){
|
|
return false;
|
|
}
|
|
|
|
itor = values.find("less_than");
|
|
if(itor != values.end() && atof(itor->second.c_str()) <= num_value){
|
|
return false;
|
|
}
|
|
|
|
itor = values.find("greater_than_equal_to");
|
|
if(itor != values.end() && atof(itor->second.c_str()) > num_value){
|
|
return false;
|
|
}
|
|
|
|
itor = values.find("less_than_equal_to");
|
|
if(itor != values.end() && atof(itor->second.c_str()) < num_value){
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} //end namespace game_events
|
|
|
|
namespace {
|
|
|
|
display* screen = NULL;
|
|
gamemap* game_map = NULL;
|
|
std::map<gamemap::location,unit>* units = NULL;
|
|
game_state* state_of_game = NULL;
|
|
game_data* game_data_ptr = NULL;
|
|
|
|
bool events_init() { return screen != NULL; }
|
|
|
|
struct queued_event {
|
|
queued_event(const std::string& name, const gamemap::location& loc1,
|
|
const gamemap::location& loc2)
|
|
: name(name), loc1(loc1), loc2(loc2) {}
|
|
|
|
std::string name;
|
|
gamemap::location loc1;
|
|
gamemap::location loc2;
|
|
};
|
|
|
|
std::deque<queued_event> events_queue;
|
|
|
|
class event_handler
|
|
{
|
|
public:
|
|
event_handler(config* cfg) : name_(cfg->values["name"]),
|
|
first_time_only_(cfg->values["first_time_only"] != "no"),
|
|
disabled_(false),
|
|
cfg_(cfg)
|
|
{}
|
|
|
|
const std::string& name() const { return name_; }
|
|
|
|
bool first_time_only() const { return first_time_only_; }
|
|
|
|
void disable() { disabled_ = true; }
|
|
bool disabled() const { return disabled_; }
|
|
|
|
std::vector<config*>& first_arg_filters() {
|
|
return cfg_->children["filter"];
|
|
}
|
|
|
|
std::vector<config*>& second_arg_filters() {
|
|
return cfg_->children["filter_second"];
|
|
}
|
|
|
|
void handle_event(const queued_event& event_info, config* cfg=NULL);
|
|
|
|
private:
|
|
std::string name_;
|
|
bool first_time_only_;
|
|
bool disabled_;
|
|
config* cfg_;
|
|
};
|
|
|
|
std::multimap<std::string,event_handler> events_map;
|
|
|
|
void event_handler::handle_event(const queued_event& event_info, config* cfg)
|
|
{
|
|
if(cfg == NULL)
|
|
cfg = cfg_;
|
|
|
|
//sub commands that need to be handled in a guaranteed ordering
|
|
std::vector<config*>& commands = cfg->children["command"];
|
|
for(std::vector<config*>::iterator cmd = commands.begin();
|
|
cmd != commands.end(); ++cmd) {
|
|
handle_event(event_info,*cmd);
|
|
}
|
|
|
|
//setting a variable
|
|
std::vector<config*>& set_vars = cfg->children["set_variable"];
|
|
for(std::vector<config*>::iterator var = set_vars.begin();
|
|
var != set_vars.end(); ++var) {
|
|
std::map<std::string,std::string>& vals = (*var)->values;
|
|
const std::string& name = vals["name"];
|
|
const std::string& value = vals["value"];
|
|
if(value.empty() == false) {
|
|
state_of_game->variables[name] = value;
|
|
}
|
|
|
|
const std::string& add = vals["add"];
|
|
if(add.empty() == false) {
|
|
double value = atof(state_of_game->variables[name].c_str());
|
|
value += atof(add.c_str());
|
|
char buf[50];
|
|
sprintf(buf,"%f",value);
|
|
state_of_game->variables[name] = buf;
|
|
}
|
|
|
|
const std::string& multiply = vals["multiply"];
|
|
if(multiply.empty() == false) {
|
|
double value = atof(state_of_game->variables[name].c_str());
|
|
value *= atof(multiply.c_str());
|
|
char buf[50];
|
|
sprintf(buf,"%f",value);
|
|
state_of_game->variables[name] = buf;
|
|
}
|
|
}
|
|
|
|
//conditional statements
|
|
std::vector<config*>& conditionals = cfg->children["if"];
|
|
for(std::vector<config*>::iterator cond = conditionals.begin();
|
|
cond != conditionals.end(); ++cond) {
|
|
const std::string type = game_events::conditional_passed(
|
|
*state_of_game,units,**cond) ? "then":"else";
|
|
|
|
//if the if statement passed, then execute all 'then' statements,
|
|
//otherwise execute 'else' statements
|
|
std::vector<config*>& commands = cfg->children[type];
|
|
for(std::vector<config*>::iterator cmd = commands.begin();
|
|
cmd != commands.end(); ++cmd) {
|
|
handle_event(event_info,*cmd);
|
|
}
|
|
}
|
|
|
|
//if we are assigning a role to a unit from the available units list
|
|
std::vector<config*>& assign_role = cfg->children["role"];
|
|
for(std::vector<config*>::iterator rl = assign_role.begin();
|
|
rl != assign_role.end(); ++rl) {
|
|
|
|
//get a list of the types this unit can be
|
|
std::vector<std::string> types = config::split((*rl)->values["type"]);
|
|
|
|
//iterate over all the types, and for each type, try to find
|
|
//a unit that matches
|
|
std::vector<std::string>::iterator ti;
|
|
for(ti = types.begin(); ti != types.end(); ++ti) {
|
|
config cfg;
|
|
cfg.values["type"] = *ti;
|
|
|
|
std::map<gamemap::location,unit>::iterator itor;
|
|
for(itor = units->begin(); itor != units->end(); ++itor) {
|
|
if(itor->second.matches_filter(cfg)) {
|
|
itor->second.assign_role((*rl)->values["role"]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(itor != units->end())
|
|
break;
|
|
|
|
std::vector<unit>::iterator ui;
|
|
//iterate over the units, and try to find one that matches
|
|
for(ui = state_of_game->available_units.begin();
|
|
ui != state_of_game->available_units.end(); ++ui) {
|
|
if(ui->matches_filter(cfg)) {
|
|
ui->assign_role((*rl)->values["role"]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//if we found a unit, we don't have to keep going.
|
|
if(ui != state_of_game->available_units.end())
|
|
break;
|
|
}
|
|
|
|
//if we found a unit in the current type, we don't have to
|
|
//look through any more types
|
|
if(ti != types.end())
|
|
break;
|
|
}
|
|
|
|
std::vector<config*>& remove_overlays = cfg->children["removeitem"];
|
|
for(std::vector<config*>::iterator rm = remove_overlays.begin();
|
|
rm != remove_overlays.end(); ++rm) {
|
|
gamemap::location loc(**rm);
|
|
if(!loc.valid()) {
|
|
loc = event_info.loc1;
|
|
}
|
|
|
|
screen->remove_overlay(loc);
|
|
}
|
|
|
|
//adding new items
|
|
std::vector<config*>& add_overlays = cfg->children["item"];
|
|
for(std::vector<config*>::iterator ni = add_overlays.begin();
|
|
ni != add_overlays.end(); ++ni) {
|
|
gamemap::location loc(**ni);
|
|
const std::string& img = (*ni)->values["image"];
|
|
if(!img.empty())
|
|
screen->add_overlay(loc,img);
|
|
}
|
|
|
|
//changing the terrain
|
|
std::vector<config*>& terrain_changes = cfg->children["terrain"];
|
|
for(std::vector<config*>::iterator tc = terrain_changes.begin();
|
|
tc != terrain_changes.end(); ++tc) {
|
|
gamemap::location loc(**tc);
|
|
const std::string& terrain_type = (*tc)->values["letter"];
|
|
if(terrain_type.size() > 0) {
|
|
game_map->set_terrain(loc,terrain_type[0]);
|
|
screen->recalculate_minimap();
|
|
screen->invalidate_all();
|
|
}
|
|
}
|
|
|
|
//if we should spawn a new unit on the map somewhere
|
|
std::vector<config*>& new_units = cfg->children["unit"];
|
|
for(std::vector<config*>::iterator ui = new_units.begin();
|
|
ui != new_units.end(); ++ui) {
|
|
unit new_unit(*game_data_ptr,**ui);
|
|
gamemap::location loc(**ui);
|
|
|
|
if(game_map->on_board(loc)) {
|
|
loc = find_vacant_tile(*game_map,*units,loc);
|
|
units->insert(std::pair<gamemap::location,unit>(loc,new_unit));
|
|
} else {
|
|
state_of_game->available_units.push_back(new_unit);
|
|
}
|
|
}
|
|
|
|
//if we should recall units that match a certain description
|
|
std::vector<config*>& recalls = cfg->children["recall"];
|
|
for(std::vector<config*>::iterator ir = recalls.begin();
|
|
ir != recalls.end(); ++ir) {
|
|
std::vector<unit>& avail = state_of_game->available_units;
|
|
for(std::vector<unit>::iterator u = avail.begin();
|
|
u != avail.end(); ++u) {
|
|
if(u->matches_filter(**ir)) {
|
|
recruit_unit(*game_map,1,*units,*u,gamemap::location(),screen);
|
|
u = avail.erase(u);
|
|
if(u == avail.end())
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<config*>& objects = cfg->children["object"];
|
|
for(std::vector<config*>::iterator obj = objects.begin();
|
|
obj != objects.end(); ++obj) {
|
|
std::map<std::string,std::string>& values = (*obj)->values;
|
|
|
|
//if this item has already been used
|
|
if(values["used"].empty() == false)
|
|
continue;
|
|
|
|
const std::string& id = values["id"];
|
|
|
|
const std::string image = values["image"];
|
|
std::string caption = values["name"];
|
|
|
|
const std::string& caption_lang = string_table[id + "_name"];
|
|
if(caption_lang.empty() == false)
|
|
caption = caption_lang;
|
|
|
|
const std::map<gamemap::location,unit>::iterator u =
|
|
units->find(event_info.loc1);
|
|
|
|
if(u == units->end())
|
|
continue;
|
|
|
|
std::string text;
|
|
|
|
std::vector<config*>& filters = (*obj)->children["filter"];
|
|
|
|
if(filters.empty() || u->second.matches_filter(*filters[0])) {
|
|
const std::string& lang = string_table[id];
|
|
if(!lang.empty())
|
|
text = lang;
|
|
else
|
|
text = values["description"];
|
|
|
|
u->second.add_modification("object",**obj);
|
|
screen->remove_overlay(event_info.loc1);
|
|
screen->select_hex(event_info.loc1);
|
|
screen->invalidate_unit();
|
|
|
|
//mark that this item won't be used again
|
|
values["used"] = "true";
|
|
} else {
|
|
const std::string& lang = string_table[id + "_cannot_use"];
|
|
if(!lang.empty())
|
|
text = lang;
|
|
else
|
|
text = values["cannot_use_message"];
|
|
}
|
|
|
|
|
|
SDL_Surface* surface = NULL;
|
|
if(image.empty() == false) {
|
|
surface = screen->getImage(image,display::UNSCALED);
|
|
}
|
|
|
|
gui::show_dialog(*screen,surface,caption,text);
|
|
|
|
//this will redraw the unit, with its new stats
|
|
screen->draw();
|
|
}
|
|
|
|
std::vector<config*>& messages = cfg->children["message"];
|
|
for(std::vector<config*>::iterator msg = messages.begin();
|
|
msg != messages.end(); ++msg) {
|
|
std::map<std::string,std::string>& values = (*msg)->values;
|
|
std::map<gamemap::location,unit>::iterator speaker = units->end();
|
|
if(values["speaker"] == "unit") {
|
|
speaker = units->find(event_info.loc1);
|
|
} else if(values["speaker"] == "second_unit") {
|
|
speaker = units->find(event_info.loc2);
|
|
} else if(values["speaker"] != "narrator") {
|
|
for(speaker = units->begin(); speaker != units->end();
|
|
++speaker){
|
|
if(speaker->second.matches_filter(**msg))
|
|
break;
|
|
}
|
|
|
|
if(speaker == units->end()) {
|
|
//no matching unit found, so the dialog can't come up
|
|
//continue onto the next message
|
|
continue;
|
|
}
|
|
}
|
|
|
|
const std::string& id = values["id"];
|
|
|
|
std::string image = (*msg)->values["image"];
|
|
std::string caption;
|
|
|
|
const std::string& lang_caption = string_table[id + "_caption"];
|
|
if(!lang_caption.empty())
|
|
caption = lang_caption;
|
|
else
|
|
caption = (*msg)->values["caption"];
|
|
|
|
if(speaker != units->end()) {
|
|
screen->highlight_hex(speaker->first);
|
|
screen->scroll_to_tile(speaker->first.x,speaker->first.y);
|
|
|
|
if(image.empty()) {
|
|
image = speaker->second.type().image_profile();
|
|
}
|
|
|
|
if(caption.empty()) {
|
|
caption = speaker->second.description();
|
|
if(caption.empty()) {
|
|
caption = speaker->second.type().language_name();
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> options;
|
|
std::vector<std::vector<config*>*> option_events;
|
|
|
|
std::vector<config*>& menu_items = (*msg)->children["option"];
|
|
for(std::vector<config*>::iterator mi = menu_items.begin();
|
|
mi != menu_items.end(); ++mi) {
|
|
const std::string& lang_msg = string_table[(*mi)->values["id"]];
|
|
const std::string& msg = lang_msg.empty() ?
|
|
(*mi)->values["message"] : lang_msg;
|
|
options.push_back(msg);
|
|
option_events.push_back(&(*mi)->children["command"]);
|
|
}
|
|
|
|
SDL_Surface* surface = NULL;
|
|
if(image.empty() == false) {
|
|
surface = screen->getImage(image,display::UNSCALED);
|
|
}
|
|
|
|
const std::string& lang_message = string_table[id];
|
|
int option_chosen = gui::show_dialog(*screen,surface,caption,
|
|
lang_message.empty() ? values["message"] : lang_message,
|
|
options.empty() ? gui::MESSAGE : gui::OK_ONLY,
|
|
options.empty() ? NULL : &options);
|
|
|
|
if(screen->update_locked() && options.empty() == false) {
|
|
config* const cfg = recorder.get_next_action();
|
|
if(cfg == NULL || cfg->children["choose"].empty()) {
|
|
std::cerr << "choice expected but none found\n";
|
|
throw replay::error();
|
|
}
|
|
|
|
const std::string& val =
|
|
cfg->children["choose"].front()->values["value"];
|
|
option_chosen = atol(val.c_str());
|
|
|
|
} else if(options.empty() == false) {
|
|
recorder.choose_option(option_chosen);
|
|
}
|
|
|
|
if(options.empty() == false) {
|
|
assert(size_t(option_chosen) < menu_items.size());
|
|
std::vector<config*>& events = *option_events[option_chosen];
|
|
for(std::vector<config*>::iterator ev = events.begin();
|
|
ev != events.end(); ++ev) {
|
|
handle_event(event_info,*ev);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<config*>& dead_units = cfg->children["kill"];
|
|
for(std::vector<config*>::iterator du = dead_units.begin();
|
|
du != dead_units.end(); ++du) {
|
|
|
|
for(std::map<gamemap::location,unit>::iterator i = units->begin();
|
|
i != units->end(); ++i) {
|
|
while(i->second.matches_filter(**du) && i != units->end()) {
|
|
units->erase(i);
|
|
i = units->begin();
|
|
}
|
|
}
|
|
|
|
std::vector<unit>& avail_units = state_of_game->available_units;
|
|
for(std::vector<unit>::iterator j = avail_units.begin();
|
|
j != avail_units.end(); ++j) {
|
|
while(j->matches_filter(**du) && j != avail_units.end()) {
|
|
j = avail_units.erase(j);
|
|
}
|
|
}
|
|
}
|
|
|
|
//adding of new events
|
|
std::vector<config*>& new_events = cfg->children["event"];
|
|
for(std::vector<config*>::iterator ne = new_events.begin();
|
|
ne != new_events.end(); ++ne) {
|
|
event_handler new_handler(*ne);
|
|
events_map.insert(std::pair<std::string,event_handler>(
|
|
new_handler.name(),new_handler));
|
|
}
|
|
|
|
std::vector<config*>& end_level = cfg->children["endlevel"];
|
|
if(end_level.empty() == false) {
|
|
config* const end_info = end_level[0];
|
|
const std::string& result = end_info->values["result"];
|
|
if(result.size() == 0 || result == "victory") {
|
|
const bool bonus = (end_info->values["bonus"] == "yes");
|
|
throw end_level_exception(VICTORY,bonus);
|
|
} else {
|
|
throw end_level_exception(DEFEAT);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool filter_loc_impl(const gamemap::location& loc, const std::string& xloc,
|
|
const std::string& yloc)
|
|
{
|
|
if(std::find(xloc.begin(),xloc.end(),',') != xloc.end()) {
|
|
std::vector<std::string> xlocs = config::split(xloc);
|
|
std::vector<std::string> ylocs = config::split(yloc);
|
|
|
|
const int size = xlocs.size() < ylocs.size()?xlocs.size():ylocs.size();
|
|
for(int i = 0; i != size; ++i) {
|
|
if(filter_loc_impl(loc,xlocs[i],ylocs[i]))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if(!xloc.empty()) {
|
|
const std::string::const_iterator dash =
|
|
std::find(xloc.begin(),xloc.end(),'-');
|
|
|
|
if(dash != xloc.end()) {
|
|
const std::string beg(xloc.begin(),dash);
|
|
const std::string end(dash+1,xloc.end());
|
|
|
|
const int bot = atoi(beg.c_str()) - 1;
|
|
const int top = atoi(end.c_str()) - 1;
|
|
|
|
if(loc.x < bot || loc.x > top)
|
|
return false;
|
|
} else {
|
|
const int xval = atoi(xloc.c_str()) - 1;
|
|
if(xval != loc.x)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if(!yloc.empty()) {
|
|
const std::string::const_iterator dash =
|
|
std::find(yloc.begin(),yloc.end(),'-');
|
|
|
|
if(dash != yloc.end()) {
|
|
const std::string beg(yloc.begin(),dash);
|
|
const std::string end(dash+1,yloc.end());
|
|
|
|
const int bot = atoi(beg.c_str()) - 1;
|
|
const int top = atoi(end.c_str()) - 1;
|
|
|
|
if(loc.y < bot || loc.y > top)
|
|
return false;
|
|
} else {
|
|
const int yval = atoi(yloc.c_str()) - 1;
|
|
if(yval != loc.y)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool filter_loc(const gamemap::location& loc, config& cfg)
|
|
{
|
|
const std::string& xloc = cfg.values["x"];
|
|
const std::string& yloc = cfg.values["y"];
|
|
|
|
return filter_loc_impl(loc,xloc,yloc);
|
|
}
|
|
|
|
bool process_event(event_handler& handler, const queued_event& ev)
|
|
{
|
|
if(handler.disabled())
|
|
return false;
|
|
|
|
std::map<gamemap::location,unit>::iterator unit1 = units->find(ev.loc1);
|
|
std::map<gamemap::location,unit>::iterator unit2 = units->find(ev.loc2);
|
|
|
|
std::vector<config*>& first_filters = handler.first_arg_filters();
|
|
for(std::vector<config*>::iterator ffi = first_filters.begin();
|
|
ffi != first_filters.end(); ++ffi) {
|
|
if(!filter_loc(ev.loc1,**ffi))
|
|
return false;
|
|
|
|
if(unit1 != units->end() && !unit1->second.matches_filter(**ffi)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
std::vector<config*>& second_filters = handler.second_arg_filters();
|
|
for(std::vector<config*>::iterator sfi = second_filters.begin();
|
|
sfi != second_filters.end(); ++sfi) {
|
|
if(!filter_loc(ev.loc2,**sfi))
|
|
return false;
|
|
|
|
if(unit2 != units->end() && !unit2->second.matches_filter(**sfi)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//the event hasn't been filtered out, so execute the handler
|
|
handler.handle_event(ev);
|
|
|
|
if(handler.first_time_only())
|
|
handler.disable();
|
|
|
|
return true;
|
|
}
|
|
|
|
} //end anonymous namespace
|
|
|
|
namespace game_events {
|
|
|
|
manager::manager(config& cfg, display& gui_, gamemap& map_,
|
|
std::map<gamemap::location,unit>& units_,
|
|
game_state& state_of_game_, game_data& game_data_)
|
|
{
|
|
std::vector<config*>& events_list = cfg.children["event"];
|
|
for(std::vector<config*>::iterator i = events_list.begin();
|
|
i != events_list.end(); ++i) {
|
|
event_handler new_handler(*i);
|
|
events_map.insert(std::pair<std::string,event_handler>(
|
|
new_handler.name(), new_handler));
|
|
}
|
|
|
|
screen = &gui_;
|
|
game_map = &map_;
|
|
units = &units_;
|
|
state_of_game = &state_of_game_;
|
|
game_data_ptr = &game_data_;
|
|
}
|
|
|
|
manager::~manager() {
|
|
events_queue.clear();
|
|
events_map.clear();
|
|
screen = NULL;
|
|
game_map = NULL;
|
|
units = NULL;
|
|
state_of_game = NULL;
|
|
game_data_ptr = NULL;
|
|
}
|
|
|
|
void raise(const std::string& event,
|
|
const gamemap::location& loc1,
|
|
const gamemap::location& loc2)
|
|
{
|
|
if(!events_init())
|
|
return;
|
|
|
|
events_queue.push_back(queued_event(event,loc1,loc2));
|
|
}
|
|
|
|
bool fire(const std::string& event,
|
|
const gamemap::location& loc1,
|
|
const gamemap::location& loc2)
|
|
{
|
|
raise(event,loc1,loc2);
|
|
return pump();
|
|
}
|
|
|
|
bool pump()
|
|
{
|
|
if(!events_init())
|
|
return false;
|
|
|
|
bool result = false;
|
|
|
|
while(events_queue.empty() == false) {
|
|
queued_event ev = events_queue.front();
|
|
events_queue.pop_front(); //pop now for exception safety
|
|
const std::string& event_name = ev.name;
|
|
typedef std::multimap<std::string,event_handler>::iterator itor;
|
|
|
|
//find all handlers for this event in the map
|
|
std::pair<itor,itor> i = events_map.equal_range(event_name);
|
|
|
|
while(i.first != i.second) {
|
|
event_handler& handler = i.first->second;
|
|
if(process_event(handler, ev))
|
|
result = true;
|
|
++i.first;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
} //end namespace game_events
|