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;
}
예제 #2
0
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;
}
예제 #3
0
파일: main.c 프로젝트: h4xxel/birdie26
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;
}
예제 #4
0
파일: game.c 프로젝트: slaeshjag/Muon
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;
			}
		}
	}
예제 #5
0
static void button_callback(UI_WIDGET *widget, unsigned int type, UI_EVENT *e) {
	if(widget == character_room.button.back) {
		game_state(GAME_STATE_MENU);
	}
}
예제 #6
0
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);
		}

	}