예제 #1
0
void move::execute(bool& success, bool& complete)
{
	if(!valid()) {
		success = false;
		//Setting complete to true signifies to side_actions to delete the planned action.
		complete = true;
		return;
	}

	if(get_source_hex() == get_dest_hex()) {
		//zero-hex move, used by attack subclass
		success = complete = true;
		return;
	}

	LOG_WB << "Executing: " << shared_from_this() << "\n";

	// Copy the current route to ensure it remains valid throughout the animation.
	const std::vector<map_location> steps = route_->steps;

	set_arrow_brightness(ARROW_BRIGHTNESS_HIGHLIGHTED);
	hide_fake_unit();

	size_t num_steps;
	bool interrupted;
	try {
		events::mouse_handler& mouse_handler = resources::controller->get_mouse_handler_base();
		num_steps = mouse_handler.move_unit_along_route(steps, interrupted);
	} catch (end_turn_exception&) {
		set_arrow_brightness(ARROW_BRIGHTNESS_STANDARD);
		throw; // we rely on the caller to delete this action
	}
	const map_location & final_location = steps[num_steps];
	unit_map::const_iterator unit_it = resources::units->find(final_location);

	if ( num_steps == 0 )
	{
		LOG_WB << "Move execution resulted in zero movement.\n";
		success = false;
		complete = true;
	}
	else if ( unit_it == resources::units->end()  ||  unit_it->id() != unit_id_ )
	{
		WRN_WB << "Unit disappeared from map during move execution.\n";
		success = false;
		complete = true;
	}
	else
	{
		complete = num_steps + 1 == steps.size();
		success = complete && !interrupted;

		if ( !success )
		{
			if ( complete )
			{
				LOG_WB << "Move completed, but interrupted on final hex. Halting.\n";
				//reset to a single-hex path, just in case *this is a wb::attack
				route_->steps = std::vector<map_location>(1, final_location);
				arrow_.reset();
			}
			else
			{
				LOG_WB << "Move finished at (" << final_location << ") instead of at (" << get_dest_hex() << "). Setting new path.\n";
				route_->steps = std::vector<map_location>(steps.begin() + num_steps, steps.end());
				//FIXME: probably better to use the new calculate_new_route() instead of the above:
				//calculate_new_route(final_location, steps.back());
				// Of course, "better" would need to be verified.
				arrow_->set_path(route_->steps);
			}
		}
	}

	if(!complete)
	{
		set_arrow_brightness(ARROW_BRIGHTNESS_STANDARD);
		show_fake_unit();
	}
}
예제 #2
0
void move::execute(bool& success, bool& complete)
{
	if (!valid_) {
		success = false;
		//Setting complete to true signifies to side_actions to delete the planned action.
		complete = true;
		return;
	}

	if (get_source_hex() == get_dest_hex()) {
		//zero-hex move, used by attack subclass
		success = complete = true;
		return;
	}

	LOG_WB << "Executing: " << shared_from_this() << "\n";

	set_arrow_brightness(ARROW_BRIGHTNESS_HIGHLIGHTED);
	hide_fake_unit();

	events::mouse_handler& mouse_handler = resources::controller->get_mouse_handler_base();
	std::set<map_location> adj_enemies = mouse_handler.get_adj_enemies(get_dest_hex(), side_number());

	map_location final_location;
	bool steps_finished;
	bool enemy_sighted;
	{
		team const& owner_team = resources::teams->at(team_index());
		try {
			steps_finished = mouse_handler.move_unit_along_route(*route_, &final_location, owner_team.auto_shroud_updates(), &enemy_sighted);
		} catch (end_turn_exception&) {
			set_arrow_brightness(ARROW_BRIGHTNESS_STANDARD);
			throw; // we rely on the caller to delete this action
		}
		// final_location now contains the final unit location
		// if that isn't needed, pass NULL rather than &final_location
		// Also, enemy_sighted now tells whether a unit was sighted during the move
	}
	if(mouse_handler.get_adj_enemies(final_location,side_number()) != adj_enemies)
		enemy_sighted = true; //< "ambushed" on last hex

	unit_map::const_iterator unit_it;

	if (final_location == route_->steps.front())
	{
		LOG_WB << "Move execution resulted in zero movement.\n";
		success = false;
		complete = true;
	}
	else if (final_location.valid() &&
			(unit_it = resources::units->find(final_location)) != resources::units->end()
			&& unit_it->id() == unit_id_)
	{
		if (steps_finished && route_->steps.back() == final_location) //reached destination
		{
			complete = true;

			//check if new enemies are now visible
			if(enemy_sighted)
			{
				LOG_WB << "Move completed, but interrupted on final hex. Halting.\n";
				//reset to a single-hex path, just in case *this is a wb::attack
				arrow_.reset();
				route_->steps = std::vector<map_location>(1,route_->steps.back());
				success = false;
			}
			else // Everything went smoothly
				success = true;
		}
		else // Move was interrupted, probably by enemy unit sighted
		{
			success = false;

			LOG_WB << "Move finished at (" << final_location << ") instead of at (" << get_dest_hex() << "), analyzing\n";
			std::vector<map_location>::iterator start_new_path;
			bool found = false;
			for (start_new_path = route_->steps.begin(); ((start_new_path != route_->steps.end()) && !found); ++start_new_path)
			{
				if (*start_new_path == final_location)
				{
					found = true;
				}
			}
			if (found)
			{
				--start_new_path; //since the for loop incremented the iterator once after we found the right one.
				std::vector<map_location> new_path(start_new_path, route_->steps.end());
				LOG_WB << "Setting new path for this move from (" << new_path.front()
						<< ") to (" << new_path.back() << ").\n";
				//FIXME: probably better to use the new calculate_new_route instead of doing this
				route_->steps = new_path;
				arrow_->set_path(new_path);
				complete = false;
			}
			else //Unit ended up in location outside path, likely due to a WML event
			{
				WRN_WB << "Unit ended up in location outside path during move execution.\n";
				complete = true;
			}
		}
	}
	else //Unit disappeared from the map, likely due to a WML event
	{
		WRN_WB << "Unit disappeared from map during move execution.\n";
		success = false;
		complete = true;
	}

	if(!complete)
	{
		set_arrow_brightness(ARROW_BRIGHTNESS_STANDARD);
		show_fake_unit();
	}
}