コード例 #1
0
void move::apply_temp_modifier(unit_map& unit_map)
{
	if (get_source_hex() == get_dest_hex())
		return; //zero-hex move, used by attack subclass

	// Safety: Make sure the old temporary_unit_mover (if any) is destroyed
	// before creating a new one.
	mover_.reset();

	//@todo: deal with multi-turn moves, which may for instance end their first turn
	// by capturing a village

	//@todo: we may need to change unit status here and change it back in remove_temp_modifier
	unit* unit;
	{
		unit_map::iterator unit_it = unit_map.find(get_source_hex());
		assert(unit_it != unit_map.end());
		unit = &*unit_it;
	}

	//Modify movement points
	DBG_WB <<"Move: Changing movement points for unit " << unit->name() << " [" << unit->id()
			<< "] from " << unit->movement_left() << " to "
			<< unit->movement_left() - movement_cost_ << ".\n";
	// Move the unit
	DBG_WB << "Move: Temporarily moving unit " << unit->name() << " [" << unit->id()
			<< "] from (" << get_source_hex() << ") to (" << get_dest_hex() <<")\n";
	mover_.reset(new temporary_unit_mover(unit_map, get_source_hex(), get_dest_hex(),
	                                      unit->movement_left() - movement_cost_));

	//Update status of fake unit (not undone by remove_temp_modifiers)
	//@todo this contradicts the name "temp_modifiers"
	fake_unit_->set_movement(unit->movement_left(), true);
}
コード例 #2
0
void move::calculate_move_cost()
{
	assert(get_unit());
	assert(route_);
	if (get_source_hex().valid() && get_dest_hex().valid() && get_source_hex() != get_dest_hex())
	{

		// @todo: find a better treatment of movement points when defining moves out-of-turn
		if(get_unit()->movement_left() - route_->move_cost < 0
				&& resources::controller->current_side() == resources::screen->viewing_side()) {
			WRN_WB << "Move defined with insufficient movement left.\n";
		}

		// If unit finishes move in a village it captures, set the move cost to unit's movement_left()
		 if (route_->marks[get_dest_hex()].capture)
		 {
			 movement_cost_ = get_unit()->movement_left();
		 }
		 else
		 {
			 movement_cost_ = route_->move_cost;
		 }
	}
}
コード例 #3
0
ファイル: move.cpp プロジェクト: CliffsDover/wesnoth_ios
void move::remove_temp_modifier(unit_map&)
{
	if (get_source_hex() == get_dest_hex())
		return; //zero-hex move, probably used by attack subclass

	unit* unit;
	{
		unit_map::iterator unit_it = resources::units->find(get_dest_hex());
		assert(unit_it != resources::units->end());
		unit = &*unit_it;
	}

	// Restore movement points
	DBG_WB << "Move: Changing movement points for unit " << unit->name() << " [" << unit->id()
				<< "] from " << unit->movement_left() << " to "
				<< unit->movement_left() + movement_cost_ << ".\n";
	unit->set_movement(unit->movement_left() + movement_cost_);

	// Restore the unit to its original position
	mover_.reset();
}
コード例 #4
0
void move::remove_temp_modifier(unit_map&)
{
	if (get_source_hex() == get_dest_hex())
		return; //zero-hex move, probably used by attack subclass

	// Debug movement points
	if ( !lg::debug.dont_log(log_whiteboard) )
	{
		unit* unit;
		{
			unit_map::iterator unit_it = resources::units->find(get_dest_hex());
			assert(unit_it != resources::units->end());
			unit = &*unit_it;
		}
		DBG_WB << "Move: Movement points for unit " << unit->name() << " [" << unit->id()
					<< "] should get changed from " << unit->movement_left() << " to "
					<< unit->movement_left() + movement_cost_ << ".\n";
	}

	// Restore the unit to its original position and movement.
	mover_.reset();
}
コード例 #5
0
void move::redraw()
{
	resources::screen->invalidate(get_source_hex());
	resources::screen->invalidate(get_dest_hex());
	update_arrow_style();
}
コード例 #6
0
std::ostream& move::print(std::ostream &s) const
{
	s << "Move for unit " << get_unit()->name() << " [" << get_unit()->id() << "] "
			<< "from (" << get_source_hex() << ") to (" << get_dest_hex() << ")";
	return s;
}
コード例 #7
0
action::error move::check_validity() const
{
	// Used to deal with multiple return paths.
	class arrow_texture_setter {
	public:
		arrow_texture_setter(const move *target, move::ARROW_TEXTURE current_texture, move::ARROW_TEXTURE setting_texture):
			target(target),
			current_texture(current_texture),
			setting_texture(setting_texture) {}

		~arrow_texture_setter() {
			if(current_texture!=setting_texture) {
				target->set_arrow_texture(setting_texture);
			}
		}

		void set_texture(move::ARROW_TEXTURE texture) { setting_texture=texture; }

	private:
		const move *target;
		move::ARROW_TEXTURE current_texture, setting_texture;
	};

	arrow_texture_setter setter(this, arrow_texture_, ARROW_TEXTURE_INVALID);

	if(!(get_source_hex().valid() && get_dest_hex().valid())) {
		return INVALID_LOCATION;
	}

	//Check that the unit still exists in the source hex
	unit_map::iterator unit_it;
	unit_it = resources::units->find(get_source_hex());
	if(unit_it == resources::units->end()) {
		return NO_UNIT;
	}

	//check if the unit in the source hex has the same unit id as before,
	//i.e. that it's the same unit
	if(unit_id_ != unit_it->id() || unit_underlying_id_ != unit_it->underlying_id()) {
		return UNIT_CHANGED;
	}

	//If the path has at least two hexes (it can have less with the attack subclass), ensure destination hex is free
	if(get_route().steps.size() >= 2 && get_visible_unit(get_dest_hex(),resources::teams->at(viewer_team())) != NULL) {
		return LOCATION_OCCUPIED;
	}

	//check that the path is good
	if(get_source_hex() != get_dest_hex()) { //skip zero-hex move used by attack subclass
		// Mark the plain route to see if the move can still be done in one turn,
		// which is always the case for planned moves
		pathfind::marked_route checked_route = pathfind::mark_route(get_route().route);

		if(checked_route.marks[checked_route.steps.back()].turns != 1) {
			return TOO_FAR;
		}
	}

	// The move is valid, so correct the setter.
	setter.set_texture(ARROW_TEXTURE_VALID);

	return OK;
}
コード例 #8
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();
	}
}
コード例 #9
0
ファイル: move.cpp プロジェクト: CliffsDover/wesnoth_ios
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();
	}
}