LEVEL_RESULT playsingle_controller::play_scenario( const config::const_child_itors &story, bool skip_replay) { uint32_t start = SDL_GetTicks(); // level_ // save game: [snapshort] in save file // new game: [scenario] in <scenarios>.cfg // Start music. BOOST_FOREACH (const config &m, level_.child_range("music")) { sound::play_music_config(m); } sound::commit_music_changes(); if(!skip_replay) { // show_story(*gui_, level_["name"], story); // gui2::show_story(*gui_, level_["name"], story); } gui_->labels().read(level_); // Read sound sources assert(soundsources_manager_ != NULL); BOOST_FOREACH (const config &s, level_.child_range("sound_source")) { soundsource::sourcespec spec(s); soundsources_manager_->add(spec); } uint32_t end_sound_sources = SDL_GetTicks(); posix_print("playsingle_controller::play_scenario, sound sources, used time: %u ms\n", end_sound_sources - start); set_victory_when_enemy_no_city(level_["victory_when_enemy_no_city"].to_bool(true)); end_level_data &end_level = get_end_level_data(); end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage); end_level.carryover_add = level_["carryover_add"].to_bool(); try { uint32_t end_entering_try = SDL_GetTicks(); posix_print("playsingle_controller::play_scenario, entering try, used time: %u ms\n", end_entering_try - end_sound_sources); fire_prestart(!loading_game_); uint32_t end_fire_prestart = SDL_GetTicks(); posix_print("playsingle_controller::play_scenario, fire_prestrt, used time: %u ms\n", end_fire_prestart - end_entering_try); init_gui(); fire_start(!loading_game_); gui_->recalculate_minimap(); // replaying_ = (recorder.at_end() == false); // Initialize countdown clock. std::vector<team>::iterator t; for(t = teams_.begin(); t != teams_.end(); ++t) { if (gamestate_.mp_settings().mp_countdown && !loading_game_ ){ t->set_countdown_time(1000 * gamestate_.mp_settings().mp_countdown_init_time); } } // if we loaded a save file in linger mode, skip to it. if (linger_) { //determine the bonus gold handling for this scenario const config end_cfg = level_.child_or_empty("endlevel"); end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage); end_level.carryover_add = level_["carr`yover_add"].to_bool(); end_level.gold_bonus = end_cfg["bonus"].to_bool(true); end_level.carryover_report = false; throw end_level_exception(SKIP_TO_LINGER); } // Avoid autosaving after loading, but still // allow the first turn to have an autosave. bool save = !loading_game_; for(; ; first_player_ = 1) { play_turn(save); save = true; } //end for loop } catch(game::load_game_exception& lge) { // Loading a new game is effectively a quit. // if (lge.game != "") { gamestate_ = game_state(); } throw lge; } catch (end_level_exception &end_level_exn) { LEVEL_RESULT end_level_result = end_level_exn.result; if (!end_level.custom_endlevel_music.empty()) { if (end_level_result == DEFEAT) { set_defeat_music_list(end_level.custom_endlevel_music); } else { set_victory_music_list(end_level.custom_endlevel_music); } } if (teams_.empty()) { //store persistent teams gamestate_.snapshot = config(); return VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event } const bool obs = is_observer(); if (end_level_result == DEFEAT || end_level_result == VICTORY) { gamestate_.classification().completion = (end_level_exn.result == VICTORY) ? "victory" : "defeat"; // If we're a player, and the result is victory/defeat, then send // a message to notify the server of the reason for the game ending. if (!obs) { config cfg; config& info = cfg.add_child("info"); info["type"] = "termination"; info["condition"] = "game over"; info["result"] = gamestate_.classification().completion; network::send_data(cfg, 0); } else { gui2::show_transient_message(gui_->video(),_("Game Over"), _("The game is over.")); return OBSERVER_END; } } if (end_level_result == QUIT) { return QUIT; } else if (end_level_result == DEFEAT) { gamestate_.classification().completion = "defeat"; game_events::fire("defeat"); if (!obs) { const std::string& defeat_music = select_defeat_music(); if(defeat_music.empty() != true) sound::play_music_once(defeat_music); return DEFEAT; } else { return QUIT; } } else if (end_level_result == VICTORY) { gamestate_.classification().completion = !end_level.linger_mode ? "running" : "victory"; game_events::fire("victory"); // // Play victory music once all victory events // are finished, if we aren't observers. // // Some scenario authors may use 'continue' // result for something that is not story-wise // a victory, so let them use [music] tags // instead should they want special music. // if (!obs && end_level.linger_mode) { const std::string& victory_music = select_victory_music(); if(victory_music.empty() != true) sound::play_music_once(victory_music); } // Add all the units that survived the scenario. LOG_NG << "Add units that survived the scenario to the recall list.\n"; //store all units that survived (recall list for the next scenario) in snapshot gamestate_.snapshot = config(); //store gold and report victory store_gold(obs); return VICTORY; } else if (end_level_result == SKIP_TO_LINGER) { LOG_NG << "resuming from loaded linger state...\n"; //as carryover information is stored in the snapshot, we have to re-store it after loading a linger state gamestate_.snapshot = config(); store_gold(); return VICTORY; } } // end catch catch(network::error& e) { bool disconnect = false; if(e.socket) { e.disconnect(); disconnect = true; } config snapshot; to_config(snapshot); savegame::game_savegame save(heros_, heros_start_, gamestate_, *gui_, snapshot); save.save_game_interactive(gui_->video(), _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), gui::YES_NO); if(disconnect) { throw network::error(); } else { return QUIT; } } return QUIT; }
LEVEL_RESULT playsingle_controller::play_scenario( const config::const_child_itors &story, bool skip_replay) { LOG_NG << "in playsingle_controller::play_scenario()...\n"; // Start music. foreach (const config &m, level_.child_range("music")) { sound::play_music_config(m); } sound::commit_music_changes(); if(!skip_replay) { show_story(*gui_, level_["name"], story); } gui_->labels().read(level_); // Read sound sources assert(soundsources_manager_ != NULL); foreach (const config &s, level_.child_range("sound_source")) { soundsource::sourcespec spec(s); soundsources_manager_->add(spec); } set_victory_when_enemies_defeated(level_["victory_when_enemies_defeated"].to_bool(true)); end_level_data &end_level = get_end_level_data(); end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage); end_level.carryover_add = level_["carryover_add"].to_bool(); bool past_prestart = false; LOG_NG << "entering try... " << (SDL_GetTicks() - ticks_) << "\n"; try { fire_prestart(!loading_game_); init_gui(); past_prestart = true; LOG_NG << "first_time..." << (recorder.is_skipping() ? "skipping" : "no skip") << "\n"; events::raise_draw_event(); fire_start(!loading_game_); gui_->recalculate_minimap(); replaying_ = (recorder.at_end() == false); LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks_) << "\n"; // Initialize countdown clock. std::vector<team>::iterator t; for(t = teams_.begin(); t != teams_.end(); ++t) { if (gamestate_.mp_settings().mp_countdown && !loading_game_ ){ t->set_countdown_time(1000 * gamestate_.mp_settings().mp_countdown_init_time); } } // if we loaded a save file in linger mode, skip to it. if (linger_) { //determine the bonus gold handling for this scenario end_level.read(level_.child_or_empty("endlevel")); end_level.carryover_report = false; end_level.disabled = true; throw end_level_exception(SKIP_TO_LINGER); } // Avoid autosaving after loading, but still // allow the first turn to have an autosave. bool save = !loading_game_; ai_testing::log_game_start(); for(; ; first_player_ = 1) { play_turn(save); save = true; } //end for loop #ifdef _MSC_VER //MSVC claims that const game::load_game_exception& lge would be unreferenced... #pragma warning (push) #pragma warning (disable : 4101) #endif } catch(const game::load_game_exception& lge) { // Loading a new game is effectively a quit. // if (lge.game != "") { gamestate_ = game_state(); } throw; } catch (end_level_exception &end_level_exn) { if(!past_prestart) { draw_solid_tinted_rectangle( 0, 0, gui_->video().getx(), gui_->video().gety(), 0, 0, 0, 1.0, gui_->video().getSurface() ); update_rect(0, 0, gui_->video().getx(), gui_->video().gety()); } ai_testing::log_game_end(); LEVEL_RESULT end_level_result = end_level_exn.result; if (!end_level.custom_endlevel_music.empty()) { if (end_level_result == DEFEAT) { set_defeat_music_list(end_level.custom_endlevel_music); } else { set_victory_music_list(end_level.custom_endlevel_music); } } if (teams_.empty()) { //store persistent teams gamestate_.snapshot = config(); store_recalls(); return VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event } const bool obs = is_observer(); if (game_config::exit_at_end) { exit(0); } if (end_level_result == DEFEAT || end_level_result == VICTORY) { gamestate_.classification().completion = (end_level_exn.result == VICTORY) ? "victory" : "defeat"; // If we're a player, and the result is victory/defeat, then send // a message to notify the server of the reason for the game ending. if (!obs) { config cfg; config& info = cfg.add_child("info"); info["type"] = "termination"; info["condition"] = "game over"; info["result"] = gamestate_.classification().completion; network::send_data(cfg, 0); } else { gui2::show_transient_message(gui_->video(),_("Game Over"), _("The game is over.")); return OBSERVER_END; } } if (end_level_result == QUIT) { return QUIT; } else if (end_level_result == DEFEAT) { gamestate_.classification().completion = "defeat"; game_events::fire("defeat"); if (!obs) { const std::string& defeat_music = select_defeat_music(); if(defeat_music.empty() != true) sound::play_music_once(defeat_music); return DEFEAT; } else { return QUIT; } } else if (end_level_result == VICTORY) { gamestate_.classification().completion = !end_level.linger_mode ? "running" : "victory"; game_events::fire("victory"); // // Play victory music once all victory events // are finished, if we aren't observers. // // Some scenario authors may use 'continue' // result for something that is not story-wise // a victory, so let them use [music] tags // instead should they want special music. // if (!obs && end_level.linger_mode) { const std::string& victory_music = select_victory_music(); if(victory_music.empty() != true) sound::play_music_once(victory_music); } // Add all the units that survived the scenario. LOG_NG << "Add units that survived the scenario to the recall list.\n"; for(unit_map::iterator un = units_.begin(); un != units_.end(); ++un) { if (teams_[un->side() - 1].persistent()) { LOG_NG << "Added unit " << un->id() << ", " << un->name() << "\n"; un->new_turn(); un->new_scenario(); teams_[un->side() - 1].recall_list().push_back(*un); } } //store all units that survived (recall list for the next scenario) in snapshot gamestate_.snapshot = config(); store_recalls(); //store gold and report victory store_gold(obs); return VICTORY; } else if (end_level_result == SKIP_TO_LINGER) { LOG_NG << "resuming from loaded linger state...\n"; //as carryover information is stored in the snapshot, we have to re-store it after loading a linger state gamestate_.snapshot = config(); store_recalls(); store_gold(); return VICTORY; } } // end catch catch(network::error& e) { bool disconnect = false; if(e.socket) { e.disconnect(); disconnect = true; } savegame::game_savegame save(gamestate_, *gui_, to_config(), preferences::compress_saves()); save.save_game_interactive(gui_->video(), _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), gui::YES_NO); if(disconnect) { throw network::error(); } else { return QUIT; } } return QUIT; }
int main(int argc, char **argv) { char font_path[512]; char *tmp; bool fullscreen = false; if (argc >= 2 && !strcmp(argv[1], "-fs")) fullscreen = true; d_init_custom("Fascister i grönsakslandet ~ //achtung fulkod", DISPLAY_WIDTH, DISPLAY_HEIGHT, fullscreen, "birdie26", NULL); sprintf(font_path, "%s", d_fs_exec_path()); chdir(tmp = dirname(font_path)); sprintf(font_path, "%s/res/font.ttf", tmp); gfx.font.large = d_font_load(font_path, 36, 256, 256); gfx.font.small = d_font_load(font_path, 16, 256, 256); s = malloc(sizeof(*s)); ui_init(4); menu_init(); gameroom_init(); lobby_init(); character_room_init(); game_over_init(); gamestate_pane[GAME_STATE_MENU] = &menu.pane; gamestate_pane[GAME_STATE_SELECT_NAME] = &select_name.pane; gamestate_pane[GAME_STATE_CHARACTERS] = &character_room.pane; gamestate_pane[GAME_STATE_LOBBY] = &lobby.pane; gamestate_pane[GAME_STATE_ENTER_IP] = &enter_ip.pane; gamestate_pane[GAME_STATE_GAMEROOM] = &gameroom.pane; gamestate_pane[GAME_STATE_GAME_OVER] = &game_over.pane; signal(SIGINT, d_quit); //lol network_init(PORT); d_cursor_show(1); d_render_clearcolor_set(0x7F, 0x7F, 0x7F); if(argc > 1) { snprintf(player_name, NAME_LEN_MAX, "%s", argv[1]); game_state(GAME_STATE_MENU); } else game_state(GAME_STATE_SELECT_NAME); while(gamestate!=GAME_STATE_QUIT) { if(state_network_handler[gamestate]) state_network_handler[gamestate](); d_render_begin(); d_render_blend_enable(); d_render_tint(20, 20, 20, 255); if(gamestate_pane[gamestate]) ui_events(gamestate_pane[gamestate], 1); d_render_tint(255, 255, 255, 255); if(state_render[gamestate]) state_render[gamestate](); if(state_network_handler[gamestate]) state_network_handler[gamestate](); d_render_end(); d_loop(); } d_quit(); return 0; }
void game_view_buttons(UI_WIDGET *widget, unsigned int type, UI_EVENT *e) { int scroll_x=0, scroll_y=0; int screen_w=platform.screen_w, screen_h=platform.screen_h; //darnit buttons have no press or release events, we have to handle this ourselves //View movement if(!chat_is_visible(&panelist_game_sidebar)) { if(e->buttons->left&&map->cam_x>-((screen_w-sidebar_width)/2)) scroll_x=-SCROLL_SPEED; else if(e->buttons->right&&map->cam_x<map_w-(screen_w-sidebar_width)/2) scroll_x=SCROLL_SPEED; if(e->buttons->up&&map->cam_y>-(screen_h)/2) scroll_y=-SCROLL_SPEED; else if(e->buttons->down&&map->cam_y<map_h-screen_h/2) scroll_y=SCROLL_SPEED; if(e->buttons->l) { scroll_x*=2; scroll_y*=2; } if(scroll_x||scroll_y) { d_map_camera_move(map, map->cam_x+scroll_x, map->cam_y+scroll_y); map_minimap_update_viewport(); } } if(!(platform.platform&DARNIT_PLATFORM_MAEMO)||e->buttons->select) { //Interaction keys if(e->buttons->start&&!prevbuttons.start) game_state(GAME_STATE_GAME_MENU); if(e->buttons->a&&!prevbuttons.a) chat_toggle(&panelist_game_sidebar); if(e->buttons->b&&!prevbuttons.b) { if(building_place>-1) { building_place=-1; } else if(map_selected_building()) { client_message_send(player_id, MSG_SEND_PLACE_BUILDING, BUILDING_NONE, map_selected_index(), NULL); map_select_nothing(); } } if(e->buttons->x&&!prevbuttons.x) { DARNIT_MOUSE m=d_mouse_get(); UI_EVENT_MOUSE e_m={ 0, 0, UI_EVENT_MOUSE_BUTTON_LEFT, 0, }; e_m.x=m.x; e_m.y=m.y; UI_EVENT e={.mouse=&e_m}; ui_event_global_send(UI_EVENT_TYPE_MOUSE_PRESS, &e); } if(e->buttons->y&&!prevbuttons.y) { if(building_place==-1&&ability_place==0) { int selected_building=map_selected_building(); if(attacker_target) attacker_target=0; else if(map_selected_owner()==player_id&&(selected_building==BUILDING_ATTACKER||selected_building==BUILDING_SCOUT)) attacker_target=1; } } }
static void button_callback(UI_WIDGET *widget, unsigned int type, UI_EVENT *e) { if(widget == character_room.button.back) { game_state(GAME_STATE_MENU); } }
void wait::join_game(bool observe) { const bool download_res = download_level_data(); if (!download_res) { set_result(QUIT); return; } else if (!level_["allow_new_game"].to_bool(true)) { set_result(PLAY); return; } if (first_scenario_) { state_ = game_state(); state_.classification().campaign_type = "multiplayer"; const config* campaign = &resources::config_manager-> game_config().find_child("campaign", "id", level_.child("multiplayer")["mp_campaign"]); if (*campaign) { state_.classification().difficulty = level_.child("multiplayer")["difficulty_define"].str(); state_.classification().campaign_define = (*campaign)["define"].str(); state_.classification().campaign_xtra_defines = utils::split((*campaign)["extra_defines"]); } // Make sure that we have the same config as host, if possible. resources::config_manager-> load_game_config_for_game(state_.classification()); } // Add the map name to the title. append_to_title(": " + level_["name"].t_str()); if (!observe) { //search for an appropriate vacant slot. If a description is set //(i.e. we're loading from a saved game), then prefer to get the side //with the same description as our login. Otherwise just choose the first //available side. const config *side_choice = NULL; int side_num = -1, nb_sides = 0; BOOST_FOREACH(const config &sd, level_.child_range("side")) { if (sd["controller"] == "reserved" && sd["current_player"] == preferences::login()) { side_choice = &sd; side_num = nb_sides; break; } if (sd["controller"] == "network" && sd["player_id"].empty()) { if (!side_choice) { // found the first empty side side_choice = &sd; side_num = nb_sides; } if (sd["current_player"] == preferences::login()) { side_choice = &sd; side_num = nb_sides; break; // found the preferred one } } ++nb_sides; } if (!side_choice) { set_result(QUIT); return; } bool allow_changes = (*side_choice)["allow_changes"].to_bool(true); //if the client is allowed to choose their team, instead of having //it set by the server, do that here. if(allow_changes) { events::event_context context; const config &era = level_.child("era"); /** @todo Check whether we have the era. If we don't inform the user. */ if (!era) throw config::error(_("No era information found.")); config::const_child_itors possible_sides = era.child_range("multiplayer_side"); if (possible_sides.first == possible_sides.second) { set_result(QUIT); throw config::error(_("No multiplayer sides found")); } int color = side_num; const std::string color_str = (*side_choice)["color"]; if (!color_str.empty()) color = game_config::color_info(color_str).index() - 1; std::vector<const config*> era_factions; BOOST_FOREACH(const config &side, possible_sides) { era_factions.push_back(&side); } const bool map_settings = level_.child("multiplayer")["mp_use_map_settings"].to_bool(); const bool saved_game = level_.child("multiplayer")["savegame"].to_bool(); flg_manager flg(era_factions, *side_choice, map_settings, saved_game, color); std::vector<std::string> choices; BOOST_FOREACH(const config *s, flg.choosable_factions()) { const config &side = *s; const std::string &name = side["name"]; const std::string &icon = side["image"]; if (!icon.empty()) { std::string rgb = side["flag_rgb"]; if (rgb.empty()) rgb = "magenta"; choices.push_back(IMAGE_PREFIX + icon + "~RC(" + rgb + ">" + lexical_cast<std::string>(color+1) + ")" + COLUMN_SEPARATOR + name); } else { choices.push_back(name); } } std::vector<gui::preview_pane* > preview_panes; leader_preview_pane leader_selector(disp(), flg, color); preview_panes.push_back(&leader_selector); const int faction_choice = gui::show_dialog(disp(), NULL, _("Choose your faction:"), _("Starting position: ") + lexical_cast<std::string>(side_num + 1), gui::OK_CANCEL, &choices, &preview_panes); if(faction_choice < 0) { set_result(QUIT); return; } config faction; config& change = faction.add_child("change_faction"); change["change_faction"] = true; change["name"] = preferences::login(); change["faction"] = flg.current_faction()["id"]; change["leader"] = flg.current_leader(); change["gender"] = flg.current_gender(); network::send_data(faction, 0); } }