From abc184d9a934c02ae90732d942be4739f2b0ddc8 Mon Sep 17 00:00:00 2001 From: Pauli Nieminen Date: Mon, 9 Jun 2008 12:42:36 +0000 Subject: [PATCH] Idea how to use std::map to implement game_events handler calling. --- src/game_events.cpp | 252 ++++++++++++++++++++++++++++---------------- 1 file changed, 159 insertions(+), 93 deletions(-) diff --git a/src/game_events.cpp b/src/game_events.cpp index 2d74cd24c1c..1031c25572c 100644 --- a/src/game_events.cpp +++ b/src/game_events.cpp @@ -62,35 +62,45 @@ namespace { -game_display* screen = NULL; -soundsource::manager* soundsources = NULL; -gamemap* game_map = NULL; -unit_map* units = NULL; -std::vector* teams = NULL; -game_state* state_of_game = NULL; -gamestatus* status_ptr = NULL; -int floating_label = 0; -Uint32 unit_mutations = 0; + game_display* screen = NULL; + soundsource::manager* soundsources = NULL; + gamemap* game_map = NULL; + unit_map* units = NULL; + std::vector* teams = NULL; + game_state* state_of_game = NULL; + gamestatus* status_ptr = NULL; + int floating_label = 0; + Uint32 unit_mutations = 0; -class event_handler; -std::vector< event_handler > new_handlers; -typedef std::pair< std::string, config* > wmi_command_change; -std::vector< wmi_command_change > wmi_command_changes; + class queued_event; + class event_handler; + std::vector< event_handler > new_handlers; + typedef std::pair< std::string, config* > wmi_command_change; + std::vector< wmi_command_change > wmi_command_changes; -const gui::msecs prevent_misclick_duration = 10; -const gui::msecs average_frame_time = 30; + typedef void (*wml_handler_function)( + const queued_event& event_info, + const vconfig& cfg, + bool& skip_messages); -class wml_event_dialog : public gui::message_dialog { -public: - wml_event_dialog(game_display &disp, const std::string& title="", const std::string& message="", const gui::DIALOG_TYPE type=gui::MESSAGE) - : message_dialog(disp, title, message, type) - {} - void action(gui::dialog_process_info &info) { - if(result() == gui::CLOSE_DIALOG && !info.key_down && info.key[SDLK_ESCAPE]) { - set_result(gui::ESCAPE_DIALOG); - } - } -}; + typedef std::map call_map; + + static call_map function_call_map; + + const gui::msecs prevent_misclick_duration = 10; + const gui::msecs average_frame_time = 30; + + class wml_event_dialog : public gui::message_dialog { + public: + wml_event_dialog(game_display &disp, const std::string& title="", const std::string& message="", const gui::DIALOG_TYPE type=gui::MESSAGE) + : message_dialog(disp, title, message, type) + {} + void action(gui::dialog_process_info &info) { + if(result() == gui::CLOSE_DIALOG && !info.key_down && info.key[SDLK_ESCAPE]) { + set_result(gui::ESCAPE_DIALOG); + } + } + }; } // end anonymous namespace (1) @@ -455,52 +465,42 @@ namespace { std::multimap events_map; -//! Handles all the different types of actions that can be triggered by an event. -void event_handler::handle_event_command(const queued_event& event_info, - const std::string& cmd, const vconfig cfg, bool& mutated, bool& skip_messages) +static void toggle_shroud(const bool remove, const vconfig& cfg) { - log_scope2(engine, "handle_event_command"); - LOG_NG << "handling command: '" << cmd << "'\n"; - // Sub commands that need to be handled in a guaranteed ordering - if(cmd == "command") { - if(!handle_event(event_info, cfg)) { - mutated = false; - } - } + std::string side = cfg["side"]; + assert(state_of_game != NULL); + const int side_num = lexical_cast_default(side,1); + const size_t index = side_num-1; - // Allow undo sets the flag saying whether the event has mutated the game to false - else if(cmd == "allow_undo") { - mutated = false; - } - // Change shroud settings for portions of the map - else if(cmd == "remove_shroud" || cmd == "place_shroud") { - const bool remove = cmd == "remove_shroud"; - - std::string side = cfg["side"]; - assert(state_of_game != NULL); - const int side_num = lexical_cast_default(side,1); - const size_t index = side_num-1; - - if(index < teams->size()) { - const std::vector& locs = multiple_locs(cfg); - for(std::vector::const_iterator j = locs.begin(); j != locs.end(); ++j) { - if(remove) { - (*teams)[index].clear_shroud(*j); - } else { - (*teams)[index].place_shroud(*j); - } + if(index < teams->size()) { + const std::vector& locs = multiple_locs(cfg); + for(std::vector::const_iterator j = locs.begin(); j != locs.end(); ++j) { + if(remove) { + (*teams)[index].clear_shroud(*j); + } else { + (*teams)[index].place_shroud(*j); } } - - screen->labels().recalculate_shroud(); - screen->invalidate_all(); } + screen->labels().recalculate_shroud(); + screen->invalidate_all(); +} - // Teleport a unit from one location to another - else if(cmd == "teleport") { +static void wml_func_remove_shroud(const queued_event& event_info, const vconfig& cfg, bool&) +{ + toggle_shroud(true,cfg); +} + +static void wml_func_place_shroud(const queued_event& event_info, const vconfig& cfg, bool&) +{ + toggle_shroud(false,cfg ); +} + +static void wml_func_teleport(const queued_event& event_info, const vconfig& cfg, bool&) +{ unit_map::iterator u = units->find(event_info.loc1); // Search for a valid unit filter, and if we have one, look for the matching unit @@ -538,11 +538,11 @@ void event_handler::handle_event_command(const queued_event& event_info, } } } - } +} - // Remove units from being turned to stone - else if(cmd == "unstone") { - const vconfig filter = cfg.child("filter"); +static void wml_func_unstone(const queued_event& event_info, const vconfig& cfg, bool&) +{ + const vconfig filter = cfg.child("filter"); // Store which side will need a shroud/fog update std::vector clear_fog_side(teams->size(),false); @@ -560,10 +560,10 @@ void event_handler::handle_event_command(const queued_event& event_info, clear_shroud(*screen,*game_map,*units,*teams,side); } } - } +} - // Allow a side to recruit a new type of unit - else if(cmd == "allow_recruit") { +static void wml_func_allow_recruit(const queued_event& event_info, const vconfig& cfg, bool&) +{ std::string side = cfg["side"]; assert(state_of_game != NULL); const int side_num = lexical_cast_default(side,1); @@ -584,10 +584,10 @@ void event_handler::handle_event_command(const queued_event& event_info, player->can_recruit.insert(*i); } } - } +} - // Remove the ability to recruit a unit from a certain side - else if(cmd == "disallow_recruit") { +static void wml_func_disallow_recruit(const queued_event& event_info, const vconfig& cfg, bool&) +{ std::string side = cfg["side"]; assert(state_of_game != NULL); const int side_num = lexical_cast_default(side,1); @@ -606,10 +606,11 @@ void event_handler::handle_event_command(const queued_event& event_info, player->can_recruit.erase(*i); } } - } +} - else if(cmd == "set_recruit") { - std::string side = cfg["side"]; +static void wml_func_set_recruit(const queued_event& event_info, const vconfig& cfg, bool&) +{ + std::string side = cfg["side"]; assert(state_of_game != NULL); const int side_num = lexical_cast_default(side,1); const size_t index = side_num-1; @@ -629,20 +630,23 @@ void event_handler::handle_event_command(const queued_event& event_info, if(player) { player->can_recruit = can_recruit; } - } +} - else if(cmd == "music") { +static void wml_func_music(const queued_event& event_info, const vconfig& cfg, bool&) +{ sound::play_music_config(cfg.get_parsed_config()); - } +} - else if(cmd == "sound") { +static void wml_func_sound(const queued_event& event_info, const vconfig& cfg, bool&) +{ std::string sound = cfg["name"]; const int repeats = lexical_cast_default(cfg["repeat"], 0); assert(state_of_game != NULL); sound::play_sound(sound, sound::SOUND_FX, repeats); - } +} - else if(cmd == "colour_adjust") { +static void wml_func_colour_adjust(const queued_event& event_info, const vconfig& cfg, bool&) +{ std::string red = cfg["red"]; std::string green = cfg["green"]; std::string blue = cfg["blue"]; @@ -653,16 +657,18 @@ void event_handler::handle_event_command(const queued_event& event_info, screen->adjust_colours(r,g,b); screen->invalidate_all(); screen->draw(true,true); - } +} - else if(cmd == "delay") { +static void wml_func_delay(const queued_event& event_info, const vconfig& cfg, bool&) +{ std::string delay_string = cfg["time"]; assert(state_of_game != NULL); const int delay_time = atoi(delay_string.c_str()); screen->delay(delay_time); - } +} - else if(cmd == "scroll") { +static void wml_func_scroll(const queued_event& event_info, const vconfig& cfg, bool&) +{ std::string x = cfg["x"]; std::string y = cfg["y"]; assert(state_of_game != NULL); @@ -670,16 +676,18 @@ void event_handler::handle_event_command(const queued_event& event_info, const int yoff = atoi(y.c_str()); screen->scroll(xoff,yoff); screen->draw(true,true); - } +} - else if(cmd == "scroll_to") { +static void wml_func_scroll_to(const queued_event& event_info, const vconfig& cfg, bool&) +{ assert(state_of_game != NULL); const gamemap::location loc = cfg_to_loc(cfg); std::string check_fogged = cfg["check_fogged"]; screen->scroll_to_tile(loc,game_display::SCROLL,utils::string_bool(check_fogged,false)); - } +} - else if(cmd == "scroll_to_unit") { +static void wml_func_scroll_to_unit(const queued_event& event_info, const vconfig& cfg, bool&) +{ unit_map::const_iterator u; for(u = units->begin(); u != units->end(); ++u){ if(game_events::unit_matches_filter(u,cfg)) @@ -689,10 +697,10 @@ void event_handler::handle_event_command(const queued_event& event_info, if(u != units->end()) { screen->scroll_to_tile(u->first,game_display::SCROLL,utils::string_bool(check_fogged,false)); } - } +} - // An award of gold to a particular side - else if(cmd == "gold") { +static void wml_func_gold(const queued_event& event_info, const vconfig& cfg, bool&) +{ std::string side = cfg["side"]; std::string amount = cfg["amount"]; assert(state_of_game != NULL); @@ -702,6 +710,54 @@ void event_handler::handle_event_command(const queued_event& event_info, if(team_index < teams->size()) { (*teams)[team_index].spend_gold(-amount_num); } +} + +static void init_function_call_map() +{ + function_call_map.insert(std::pair("teleport", &wml_func_teleport)); + function_call_map.insert(std::pair("unstone", &wml_func_unstone)); + function_call_map.insert(std::pair("allow_recruit", &wml_func_allow_recruit)); + function_call_map.insert(std::pair("disallow_recruit", &wml_func_disallow_recruit)); + function_call_map.insert(std::pair("set_recruit", &wml_func_set_recruit)); + function_call_map.insert(std::pair("music", &wml_func_music)); + function_call_map.insert(std::pair("sound", &wml_func_sound)); + function_call_map.insert(std::pair("colour_adjust", &wml_func_colour_adjust)); + function_call_map.insert(std::pair("remove_shroud", &wml_func_remove_shroud)); + function_call_map.insert(std::pair("place_shroud", &wml_func_place_shroud)); + function_call_map.insert(std::pair("delay", &wml_func_delay)); + function_call_map.insert(std::pair("scroll", &wml_func_scroll)); + function_call_map.insert(std::pair("scroll_to", &wml_func_scroll_to)); + function_call_map.insert(std::pair("scroll_to_unit", &wml_func_scroll_to_unit)); + function_call_map.insert(std::pair("gold", &wml_func_gold)); +} + +//! Handles all the different types of actions that can be triggered by an event. +void event_handler::handle_event_command(const queued_event& event_info, + const std::string& cmd, const vconfig cfg, bool& mutated, bool& skip_messages) +{ + log_scope2(engine, "handle_event_command"); + LOG_NG << "handling command: '" << cmd << "'\n"; + + call_map::iterator func = function_call_map.find(cmd); + + if (func != function_call_map.end()) + { + DBG_NG << "Found command handling function\n"; + (*(*func->second))(event_info, cfg, skip_messages); + return; + } + + // Sub commands that need to be handled in a guaranteed ordering + if(cmd == "command") { + if(!handle_event(event_info, cfg)) { + mutated = false; + } + } + + + // Allow undo sets the flag saying whether the event has mutated the game to false + else if(cmd == "allow_undo") { + mutated = false; } // Modifications of some attributes of a side: gold, income, team name @@ -3070,6 +3126,13 @@ bool unit_matches_filter(unit_map::const_iterator itor, const vconfig filter) static config::child_list unit_wml_configs; static std::set unit_wml_ids; + +static void clear_function_call_map() +{ + function_call_map.clear(); +} + + manager::manager(const config& cfg, game_display& gui_, gamemap& map_, soundsource::manager& sndsources_, unit_map& units_, @@ -3077,6 +3140,7 @@ manager::manager(const config& cfg, game_display& gui_, gamemap& map_, game_state& state_of_game_, gamestatus& status) : variable_manager(&state_of_game_) { + init_function_call_map(); const config::child_list& events_list = cfg.get_children("event"); for(config::child_list::const_iterator i = events_list.begin(); i != events_list.end(); ++i) { @@ -3163,6 +3227,7 @@ void write_events(config& cfg) } manager::~manager() { + clear_function_call_map(); events_queue.clear(); events_map.clear(); screen = NULL; @@ -3295,3 +3360,4 @@ bool entity_location::requires_unit() const } // end namespace game_events (2) +