Beispiel #1
0
int CVideo::set_help_string(const std::string& str)
{
	font::remove_floating_label(help_string_);

	const SDL_Color color = { 0, 0, 0, 0xbb };

	int size = font::SIZE_LARGE;

	while(size > 0) {
		if(font::line_width(str, size) > getx()) {
			size--;
		} else {
			break;
		}
	}

	const int border = 5;

	font::floating_label flabel(str);
	flabel.set_font_size(size);
	flabel.set_position(getx()/2, gety());
	flabel.set_bg_color(color);
	flabel.set_border_size(border);

	help_string_ = font::add_floating_label(flabel);

	const SDL_Rect& rect = font::get_floating_label_rect(help_string_);
	font::move_floating_label(help_string_,0.0,-double(rect.h));
	return help_string_;
}
Beispiel #2
0
void terrain_label::draw()
{
	if (text_.empty() && tooltip_.empty())
		return;
	clear();

	if ( !viewable(parent_->disp().get_disp_context()) )
		return;

	const map_location loc_nextx(loc_.x+1,loc_.y);
	const map_location loc_nexty(loc_.x,loc_.y+1);
	const int xloc = (parent_->disp().get_location_x(loc_) +
			parent_->disp().get_location_x(loc_nextx)*2)/3;
	const int yloc = parent_->disp().get_location_y(loc_nexty) - font::SIZE_NORMAL;

	// If a color is specified don't allow to override it with markup. (prevents faking map labels for example)
	// FIXME: @todo Better detect if it's team label and not provided by
	// the scenario.
	bool use_markup = color_ == font::LABEL_COLOR;

	font::floating_label flabel(text_.str());
	flabel.set_color(color_);
	flabel.set_position(xloc, yloc);
	flabel.set_clip_rect(parent_->disp().map_outside_area());
	flabel.set_width(font::SIZE_NORMAL * 13);
	flabel.set_height(font::SIZE_NORMAL * 4);
	flabel.set_scroll_mode(font::ANCHOR_LABEL_MAP);
	flabel.use_markup(use_markup);

	handle_ = font::add_floating_label(flabel);

	calculate_shroud();
}
	void floating_textbox::update_location(game_display& gui)
	{
		if (box_ == NULL)
			return;

		const SDL_Rect& area = gui.map_outside_area();

		const int border_size = 10;

		const int ypos = area.y+area.h-30 - (check_ != NULL ? check_->height() + border_size : 0);

		if (label_ != 0)
			font::remove_floating_label(label_);

		font::floating_label flabel(label_string_);
		flabel.set_color(font::YELLOW_COLOR);
		flabel.set_position(area.x + border_size, ypos);
		flabel.set_alignment(font::LEFT_ALIGN);
		flabel.set_clip_rect(area);

		label_ = font::add_floating_label(flabel);

		if (label_ == 0)
			return;

		const SDL_Rect& label_area = font::get_floating_label_rect(label_);
		const int textbox_width = area.w - label_area.w - border_size*3;

		if(textbox_width <= 0) {
			font::remove_floating_label(label_);
			return;
		}

		if(box_ != NULL) {
			box_->set_volatile(true);
			const SDL_Rect rect = create_rect(
				  area.x + label_area.w + border_size * 2
				, ypos
				, textbox_width
				, box_->height());

			box_->set_location(rect);
		}

		if(check_ != NULL) {
			check_->set_volatile(true);
			check_->set_location(box_->location().x,box_->location().y + box_->location().h + border_size);
		}
	}
Beispiel #4
0
void game_display::float_label(const map_location& loc, const std::string& text, const SDL_Color& color)
{
	if(preferences::show_floating_labels() == false || fogged(loc)) {
		return;
	}

	font::floating_label flabel(text);
	flabel.set_font_size(font::SIZE_XLARGE);
	flabel.set_color(color);
	flabel.set_position(get_location_x(loc)+zoom_/2, get_location_y(loc));
	flabel.set_move(0, -2 * turbo_speed());
	flabel.set_lifetime(60/turbo_speed());
	flabel.set_scroll_mode(font::ANCHOR_LABEL_MAP);

	font::add_floating_label(flabel);
}
Beispiel #5
0
static void show_tooltip(const tooltip& tip)
{
	if(video_ == NULL) {
		return;
	}

	clear_tooltip();

	const SDL_Color bgcolor = {0,0,0,160};
#if defined(_KINGDOM_EXE) || !defined(_WIN32)
	SDL_Rect area = screen_area();
#else
	SDL_Rect area = create_rect(0, 0, 800, 600);
#endif

	unsigned int border = 10;

	font::floating_label flabel(tip.message);
	flabel.set_font_size(font_size);
	flabel.set_color(font::NORMAL_COLOR);
	flabel.set_clip_rect(area);
	flabel.set_width(text_width);
	flabel.set_bg_color(bgcolor);
	flabel.set_border_size(border);

	tooltip_handle = font::add_floating_label(flabel);

	SDL_Rect rect = font::get_floating_label_rect(tooltip_handle);

	//see if there is enough room to fit it above the tip area
	if(tip.rect.y > rect.h) {
		rect.y = tip.rect.y - rect.h;
	} else {
		rect.y = tip.rect.y + tip.rect.h;
	}

	rect.x = tip.rect.x;
	if(rect.x < 0) {
		rect.x = 0;
	} else if(rect.x + rect.w > area.w) {
		rect.x = area.w - rect.w;
	}

	font::move_floating_label(tooltip_handle,rect.x,rect.y);
}
Beispiel #6
0
static void show_tooltip(const tooltip& tip)
{
	if(video_ == NULL) {
		return;
	}

	clear_tooltip();

	const SDL_Color bgcolor = {0,0,0,160};
	SDL_Rect area = screen_area();

	unsigned int border = 10;

	font::floating_label flabel(tip.message, tip.foreground);
	flabel.use_markup(tip.markup);
	flabel.set_font_size(font_size);
	flabel.set_color(font::NORMAL_COLOR);
	flabel.set_clip_rect(area);
	flabel.set_width(text_width);
	flabel.set_alignment(font::LEFT_ALIGN);
	flabel.set_bg_color(bgcolor);
	flabel.set_border_size(border);

	tooltip_handle = font::add_floating_label(flabel);

	SDL_Rect rect = font::get_floating_label_rect(tooltip_handle);

	//see if there is enough room to fit it above the tip area
	if(tip.rect.y > rect.h) {
		rect.y = tip.rect.y - rect.h;
	} else {
		rect.y = tip.rect.y + tip.rect.h;
	}

	rect.x = tip.rect.x;
	if(rect.x < 0) {
		rect.x = 0;
	} else if(rect.x + rect.w > area.w) {
		rect.x = area.w - rect.w;
	}

	font::move_floating_label(tooltip_handle,rect.x,rect.y);
}
void playmp_controller::play_human_turn(){
	LOG_NG << "playmp::play_human_turn...\n";
	command_disabled_resetter reset_commands;
	int cur_ticks = SDL_GetTicks();
	show_turn_dialog();
	execute_gotos();

	if (!linger_ || is_host_) {
		end_turn_enable(true);
	}
	while(!end_turn_) {

		try {
			config cfg;
			const network::connection res = network::receive_data(cfg);
			std::deque<config> backlog;

			if(res != network::null_connection) {
				if (turn_data_->process_network_data(cfg, res, backlog, skip_replay_) == turn_info::PROCESS_RESTART_TURN)
				{
					// Clean undo stack if turn has to be restarted (losing control)
					if ( undo_stack_->can_undo() )
					{
						font::floating_label flabel(_("Undoing moves not yet transmitted to the server."));

						SDL_Color color = {255,255,255,255};
						flabel.set_color(color);
						SDL_Rect rect = gui_->map_area();
						flabel.set_position(rect.w/2, rect.h/2);
						flabel.set_lifetime(150);
						flabel.set_clip_rect(rect);

						font::add_floating_label(flabel);
					}

					while( undo_stack_->can_undo() )
						undo_stack_->undo();
					throw end_turn_exception(gui_->playing_side());
				}
			}

			play_slice();
			check_end_level();
			// give a chance to the whiteboard to continue an execute_all_actions
			resources::whiteboard->continue_execute_all();
		} catch(const end_level_exception&) {
			turn_data_->send_data();
			throw;
		}

		if (!linger_ && (current_team().countdown_time() > 0) && gamestate_.mp_settings().mp_countdown) {
			SDL_Delay(1);
			const int ticks = SDL_GetTicks();
			int new_time = current_team().countdown_time()-std::max<int>(1,(ticks - cur_ticks));
			if (new_time > 0 ){
				current_team().set_countdown_time(new_time);
				cur_ticks = ticks;
				if(current_team().is_human() && !beep_warning_time_) {
					beep_warning_time_ = new_time - WARNTIME + ticks;
				}
				if(counting_down()) {
					think_about_countdown(ticks);
				}
			} else {
				// Clock time ended
				// If no turn bonus or action bonus -> defeat
				const int action_increment = gamestate_.mp_settings().mp_countdown_action_bonus;
				if ( (gamestate_.mp_settings().mp_countdown_turn_bonus == 0 )
					&& (action_increment == 0 || current_team().action_bonus_count() == 0)) {
					// Not possible to end level in MP with throw end_level_exception(DEFEAT);
					// because remote players only notice network disconnection
					// Current solution end remaining turns automatically
					current_team().set_countdown_time(10);
				} else {
					const int maxtime = gamestate_.mp_settings().mp_countdown_reservoir_time;
					int secs = gamestate_.mp_settings().mp_countdown_turn_bonus;
					secs += action_increment  * current_team().action_bonus_count();
					current_team().set_action_bonus_count(0);
					secs = (secs > maxtime) ? maxtime : secs;
					current_team().set_countdown_time(1000 * secs);
				}
				turn_data_->send_data();

				if (!rand_rng::has_new_seed_callback()) {
					throw end_turn_exception();
				}
			}
		}

		gui_->draw();

		turn_data_->send_data();
	}
}
void playmp_controller::play_human_turn()
{
	LOG_NG << "playmp::play_human_turn...\n";
	assert(!linger_);
	assert(gamestate_->init_side_done());
	assert(gamestate().gamedata_.phase() == game_data::PLAY);

	mp_ui_alerts::turn_changed(current_team().current_player());

	LOG_NG << "events::commands_disabled=" << events::commands_disabled <<"\n";

	remove_blindfold();
	const std::unique_ptr<countdown_clock> timer(saved_game_.mp_settings().mp_countdown
        ? new countdown_clock(current_team())
        : nullptr);
	show_turn_dialog();
	if(undo_stack().can_undo()) {
		// If we reload a networked mp game we cannot undo moves made before the save
		// because other players already received them
		if(!current_team().auto_shroud_updates()) {
			synced_context::run_and_store("update_shroud", replay_helper::get_update_shroud());
		}
		undo_stack().clear();
	}
	if (!preferences::disable_auto_moves()) {
		execute_gotos();
	}

	end_turn_enable(true);
	while(!should_return_to_play_side()) {
		try {
			process_network_data();
			check_objectives();
			play_slice_catch();
			if (player_type_changed_)
			{
				// Clean undo stack if turn has to be restarted (losing control)
				if ( undo_stack().can_undo() )
				{
					font::floating_label flabel(_("Undoing moves not yet transmitted to the server."));

					color_t color {255,255,255,SDL_ALPHA_OPAQUE};
					flabel.set_color(color);
					SDL_Rect rect = gui_->map_area();
					flabel.set_position(rect.w/2, rect.h/2);
					flabel.set_lifetime(150);
					flabel.set_clip_rect(rect);

					font::add_floating_label(flabel);
				}

				while( undo_stack().can_undo() )
					undo_stack().undo();

			}
			if(timer)
			{
				bool time_left = timer->update();
				if(!time_left)
				{
					end_turn_ = END_TURN_REQUIRED;
				}
			}
		}
		catch(...)
		{
			turn_data_.send_data();
			throw;
		}
		turn_data_.send_data();
	}
}
Beispiel #9
0
possible_end_play_signal playmp_controller::play_human_turn(){
	LOG_NG << "playmp::play_human_turn...\n";

	remove_blindfold();
	int cur_ticks = SDL_GetTicks();
	show_turn_dialog();

	if (!preferences::disable_auto_moves()) {
		HANDLE_END_PLAY_SIGNAL(execute_gotos());
	}

	if (!linger_ || is_host()) {
		end_turn_enable(true);
	}
	while(!end_turn_) {
		turn_info_send send_safe(turn_data_);
			config cfg;

			if(network_reader_.read(cfg)) {
				turn_info::PROCESS_DATA_RESULT res;
				HANDLE_END_PLAY_SIGNAL( res = turn_data_.process_network_data(cfg, skip_replay_) );
				//PROCESS_RESTART_TURN_TEMPORARY_LOCAL should be impossible because that's means the currently active side (that's us) left.
				if (res == turn_info::PROCESS_RESTART_TURN || res == turn_info::PROCESS_RESTART_TURN_TEMPORARY_LOCAL)
				{
					// Clean undo stack if turn has to be restarted (losing control)
					if ( undo_stack_->can_undo() )
					{
						font::floating_label flabel(_("Undoing moves not yet transmitted to the server."));

						SDL_Color color = {255,255,255,255};
						flabel.set_color(color);
						SDL_Rect rect = gui_->map_area();
						flabel.set_position(rect.w/2, rect.h/2);
						flabel.set_lifetime(150);
						flabel.set_clip_rect(rect);

						font::add_floating_label(flabel);
					}

					while( undo_stack_->can_undo() )
						undo_stack_->undo();

					end_turn_struct ets = {static_cast<unsigned>(gui_->playing_side())};
					return possible_end_play_signal(ets);
					//throw end_turn_exception(gui_->playing_side());
				}
				else if(res == turn_info::PROCESS_END_LINGER)
				{
					if(!linger_)
						replay::process_error("Received unexpected next_scenario durign the game");
					else
					{
						//we end the turn immidiately to prevent receiving data of the next scenario while we are not playing it.
						end_turn();
					}
				}
			}

			HANDLE_END_PLAY_SIGNAL( play_slice() );
			HANDLE_END_PLAY_SIGNAL( check_end_level() );

		if (!linger_ && (current_team().countdown_time() > 0) && saved_game_.mp_settings().mp_countdown) {
			SDL_Delay(1);
			const int ticks = SDL_GetTicks();
			int new_time = current_team().countdown_time()-std::max<int>(1,(ticks - cur_ticks));
			if (new_time > 0 ){
				current_team().set_countdown_time(new_time);
				cur_ticks = ticks;
				if(current_team().is_human() && !beep_warning_time_) {
					beep_warning_time_ = new_time - WARNTIME + ticks;
				}
				if(counting_down()) {
					think_about_countdown(ticks);
				}
			} else {
				// Clock time ended
				// If no turn bonus or action bonus -> defeat
				const int action_increment = saved_game_.mp_settings().mp_countdown_action_bonus;
				if ( (saved_game_.mp_settings().mp_countdown_turn_bonus == 0 )
					&& (action_increment == 0 || current_team().action_bonus_count() == 0)) {
					// Not possible to end level in MP with throw end_level_exception(DEFEAT);
					// because remote players only notice network disconnection
					// Current solution end remaining turns automatically
					current_team().set_countdown_time(10);
				}

				return possible_end_play_signal(end_turn_exception().to_struct());
				//throw end_turn_exception();
			}
		}

		gui_->draw();
	}
	return boost::none;
}
Beispiel #10
0
void playmp_controller::play_human_turn()
{
	LOG_NG << "playmp::play_human_turn...\n";
	assert(!linger_);
	remove_blindfold();
	boost::scoped_ptr<countdown_clock> timer;
	if(saved_game_.mp_settings().mp_countdown) {
		timer.reset(new countdown_clock(current_team()));
	}
	show_turn_dialog();
	if(undo_stack_->can_undo()) {
		// If we reload a networked mp game we cannot undo moves made before the save
		// Becasue other players already received them
		if(!current_team().auto_shroud_updates()) {
			synced_context::run_and_store("update_shroud", replay_helper::get_update_shroud());
		}
		undo_stack_->clear();
	}
	if (!preferences::disable_auto_moves()) {
		execute_gotos();
	}

	end_turn_enable(true);
	while(!should_return_to_play_side()) {
		try {
			process_network_data();
			if (player_type_changed_)
			{
				// Clean undo stack if turn has to be restarted (losing control)
				if ( undo_stack_->can_undo() )
				{
					font::floating_label flabel(_("Undoing moves not yet transmitted to the server."));

					SDL_Color color = {255,255,255,255};
					flabel.set_color(color);
					SDL_Rect rect = gui_->map_area();
					flabel.set_position(rect.w/2, rect.h/2);
					flabel.set_lifetime(150);
					flabel.set_clip_rect(rect);

					font::add_floating_label(flabel);
				}

				while( undo_stack_->can_undo() )
					undo_stack_->undo();

			}
			check_objectives();
			play_slice_catch();
			if(timer)
			{
				bool time_left = timer->update();
				if(!time_left)
				{
					end_turn_ = END_TURN_REQUIRED;
				}
			}
		}
		catch(...)
		{
			turn_data_.send_data();
			throw;
		}
		turn_data_.send_data();

		gui_->draw();
	}
}
void playmp_controller::play_human_turn()
{
	command_disabled_resetter reset_commands;
	int cur_ticks = SDL_GetTicks();
	show_turn_dialog();
	execute_gotos();

	bool auto_end_turn = can_auto_end_turn(true);
	if (!auto_end_turn) {
		if (!unit::actor->is_city() && unit::actor->task() == unit::TASK_NONE) {
			gui_->scroll_to_tile(unit::actor->get_location(), game_display::ONSCREEN, true, true);
		}
	} else {
		return;
	}

	if ((!linger_) || (is_host_)) {
		gui_->set_theme_object_active("endturn", true);
	}

	while (!end_turn_ && !auto_end_turn) {
		try {
			play_slice();
			check_end_level();

			std::deque<config> backlog;
			std::vector<config> cfgs = received_data_cfg_;
			received_data_cfg_.clear();
			for (std::vector<config>::const_iterator it = cfgs.begin(); it != cfgs.end(); ++ it) {
				const config& cfg = *it;
				if (turn_data_->process_network_data(cfg, lobby->transit.conn(), backlog, skip_replay_) == turn_info::PROCESS_RESTART_TURN) {
					// Clean undo stack if turn has to be restarted (losing control)
					if (!undo_stack_.empty()) {
						font::floating_label flabel(_("Undoing moves not yet transmitted to the server."));

						SDL_Color color = {255,255,255,255};
						flabel.set_color(color);
						SDL_Rect rect = gui_->map_area();
						flabel.set_position(rect.w/2, rect.h/2);
						flabel.set_lifetime(150);
						flabel.set_clip_rect(rect);

						font::add_floating_label(flabel);
					}

					while(!undo_stack_.empty()) {
						menu_handler_.undo(gui_->get_playing_team() + 1);
					}
					throw end_turn_exception(gui_->get_playing_team() + 1);
				}
			}

		} catch (end_level_exception& e) {
			turn_data_->send_data();
			throw e;
		}

		if (!linger_ && (current_team().countdown_time() > 0) && gamestate_.mp_settings().mp_countdown) {
			SDL_Delay(1);
			const int ticks = SDL_GetTicks();
			int new_time = current_team().countdown_time()-std::max<int>(1,(ticks - cur_ticks));
			if (new_time > 0 ){
				current_team().set_countdown_time(new_time);
				cur_ticks = ticks;
				if(current_team().is_human() && !beep_warning_time_) {
					beep_warning_time_ = new_time - WARNTIME + ticks;
				}
				if(counting_down()) {
					think_about_countdown(ticks);
				}
			} else {
				// Clock time ended
				// If no turn bonus or action bonus -> defeat
				const int action_increment = gamestate_.mp_settings().mp_countdown_action_bonus;
				if ( (gamestate_.mp_settings().mp_countdown_turn_bonus == 0 )
					&& (action_increment == 0 || current_team().action_bonus_count() == 0)) {
					// Not possible to end level in MP with throw end_level_exception(DEFEAT);
					// because remote players only notice network disconnection
					// Current solution end remaining turns automatically
					current_team().set_countdown_time(10);
				} else {
					const int maxtime = gamestate_.mp_settings().mp_countdown_reservoir_time;
					int secs = gamestate_.mp_settings().mp_countdown_turn_bonus;
					secs += action_increment  * current_team().action_bonus_count();
					current_team().set_action_bonus_count(0);
					secs = (secs > maxtime) ? maxtime : secs;
					current_team().set_countdown_time(1000 * secs);
				}
				turn_data_->send_data();

				throw end_turn_exception();
			}
		}

		gui_->draw();

		turn_data_->send_data();

		auto_end_turn = can_auto_end_turn(false);
	}
	menu_handler_.clear_undo_stack(player_number_);
}