Exemple #1
0
void recall::apply_temp_modifier(unit_map& unit_map)
{
	assert(valid());
	temp_unit_->set_location(recall_hex_);

	DBG_WB << "Inserting future recall " << temp_unit_->name() << " [" << temp_unit_->id()
			<< "] at position " << temp_unit_->get_location() << ".\n";

	//temporarily remove unit from recall list
	UnitPtr it = resources::teams->at(team_index()).recall_list().extract_if_matches_id(temp_unit_->id());
	assert(it);

	//Add cost to money spent on recruits.
	int cost = resources::teams->at(team_index()).recall_cost();
	if (it->recall_cost() > -1) {
		cost = it->recall_cost();
	}

	// Temporarily insert unit into unit_map
	//unit map takes ownership of temp_unit
	unit_map.insert(temp_unit_);

	resources::teams->at(team_index()).get_side_actions()->change_gold_spent_by(cost);
	// Update gold in top bar
	resources::screen->invalidate_game_status();
}
Exemple #2
0
void recall::apply_temp_modifier(unit_map& unit_map)
{
	assert(valid_);
	temp_unit_->set_location(recall_hex_);

	DBG_WB << "Inserting future recall " << temp_unit_->name() << " [" << temp_unit_->id()
			<< "] at position " << temp_unit_->get_location() << ".\n";

	//temporarily remove unit from recall list
	std::vector<unit>& recalls = resources::teams->at(team_index()).recall_list();
	std::vector<unit>::iterator it = std::find_if(recalls.begin(), recalls.end(),
					unit_comparator_predicate(*temp_unit_));
	assert(it != recalls.end());
	recalls.erase(it);

	// Temporarily insert unit into unit_map
	unit_map.insert(temp_unit_);
	//unit map takes ownership of temp_unit
	temp_unit_ = NULL;

	//Add cost to money spent on recruits.
	temp_cost_ = resources::teams->at(team_index()).recall_cost();
	resources::teams->at(team_index()).get_side_actions()->change_gold_spent_by(temp_cost_);

	// Update gold in top bar
	resources::screen->invalidate_game_status();
}
Exemple #3
0
void recruit::execute(bool& success, bool& complete)
{
	assert(valid());
	temporary_unit_hider const raii(*fake_unit_);
	const int side_num = team_index() + 1;
	//Give back the spent gold so we don't get "not enough gold" message
	resources::gameboard->teams().at(team_index()).get_side_actions()->change_gold_spent_by(-cost_);
	bool const result = resources::controller->get_menu_handler().do_recruit(unit_name_, side_num, recruit_hex_);
	//If it failed, take back the gold
	if (!result) {
		resources::gameboard->teams().at(team_index()).get_side_actions()->change_gold_spent_by(cost_);
	}
	success = complete = result;
}
Exemple #4
0
void recall::remove_temp_modifier(unit_map& unit_map)
{
	temp_unit_ = unit_map.extract(recall_hex_);
	assert(temp_unit_);

	//Put unit back into recall list
	resources::teams->at(team_index()).recall_list().push_back(*temp_unit_);

	/*
	 * Remove cost from money spent on recruits.
	 */
	resources::teams->at(team_index()).get_side_actions()->change_gold_spent_by(-temp_cost_);
	temp_cost_ = 0;
	resources::screen->invalidate_game_status();
}
Exemple #5
0
void recall::execute(bool& success, bool& complete)
{
	team & current_team = resources::teams->at(team_index());

	assert(valid());
	assert(temp_unit_.get());
	temporary_unit_hider const raii(*fake_unit_);
	//Give back the spent gold so we don't get "not enough gold" message
	int cost = current_team.recall_cost();
	if (temp_unit_->recall_cost() > -1) {
		cost=temp_unit_->recall_cost();
	}
	current_team.get_side_actions()->change_gold_spent_by(-cost);
	bool const result = synced_context::run_in_synced_context("recall",
		replay_helper::get_recall(temp_unit_->id(), recall_hex_, map_location::null_location()),
		true,
		true,
		true,
		synced_context::ignore_error_function);

	if (!result) {
		current_team.get_side_actions()->change_gold_spent_by(cost);
	}
	success = complete = result;
}
Exemple #6
0
void recall::draw_hex(map_location const& hex)
{
    if (hex == recall_hex_)
    {
        const double x_offset = 0.5;
        const double y_offset = 0.7;
        //position 0,0 in the hex is the upper left corner
        std::stringstream number_text;
        unit &it = *get_unit();
        int cost = statistics::un_recall_unit_cost(it);
        if (cost < 0) {
            number_text << utils::unicode_minus << resources::teams->at(team_index()).recall_cost();
        }
        else {
            number_text << utils::unicode_minus << cost;
        }
        size_t font_size = 16;
        SDL_Color color;
        color.r = 255;
        color.g = 0;
        color.b = 0; //red
        resources::screen->draw_text_in_hex(hex, display::LAYER_ACTIONS_NUMBERING,
                                            number_text.str(), font_size, color, x_offset, y_offset);
    }
}
Exemple #7
0
void recall::remove_temp_modifier(unit_map& unit_map)
{
	temp_unit_ = unit_map.extract(recall_hex_);
	assert(temp_unit_.get());

	//Put unit back into recall list
	resources::teams->at(team_index()).recall_list().add(temp_unit_);
}
Exemple #8
0
bool recruit::execute()
{
	assert(valid_);
	fake_unit_->set_hidden(true);
	int side_num = team_index() + 1;
	resources::controller->get_menu_handler().do_recruit(unit_name_, side_num, recruit_hex_);
	return true;
}
Exemple #9
0
unit* recruit::create_corresponding_unit()
{
	unit_type const* type = unit_types.find(unit_name_);
	assert(type);
	int side_num = team_index() + 1;
	//real_unit = false needed to avoid generating random traits and causing OOS
	bool real_unit = false;
	return new unit(type, side_num, real_unit);
}
Exemple #10
0
bool recall::execute()
{
	assert(valid_);
	assert(temp_unit_);
	fake_unit_->set_hidden(true);
	resources::controller->get_menu_handler().do_recall(*temp_unit_, team_index() + 1, recall_hex_);
	delete temp_unit_;
	temp_unit_ = NULL;
	return true;
}
Exemple #11
0
void move::init()
{
	// If a unit is invalid, return immediately to avoid crashes such as trying to plan a move for a planned recruit.
	// As per Bug #18637, this should be fixed so that planning moves on planned recruits work properly.
	// The alternative is to disable movement on planned recruits altogether,
	// possibly in select_or_action() where the fake unit is selected in the first place.
	if (get_unit() == NULL)
		return;

	assert(get_unit());
	unit_id_ = get_unit()->id();

	//This action defines the future position of the unit, make its fake unit more visible
	//than previous actions' fake units
	if (fake_unit_)
	{
		fake_unit_->anim_comp().set_ghosted(true);
	}
	side_actions_ptr side_actions = resources::teams->at(team_index()).get_side_actions();
	side_actions::iterator action = side_actions->find_last_action_of(*(get_unit()));
	if (action != side_actions->end())
	{
		if (move_ptr move = boost::dynamic_pointer_cast<class move>(*action))
		{
			if (move->fake_unit_)
				move->fake_unit_->anim_comp().set_disabled_ghosted(true);
		}
	}

	this->calculate_move_cost();

	// Initialize arrow_brightness_ and arrow_texture_ using arrow_->style_
	arrow::STYLE arrow_style = arrow_->get_style();
	if(arrow_style == arrow::STYLE_STANDARD)
	{
		arrow_brightness_ = ARROW_BRIGHTNESS_STANDARD;
		arrow_texture_ = ARROW_TEXTURE_VALID;
	}
	else if(arrow_style == arrow::STYLE_HIGHLIGHTED)
	{
		arrow_brightness_ = ARROW_BRIGHTNESS_HIGHLIGHTED;
		arrow_texture_ = ARROW_TEXTURE_VALID;
	}
	else if(arrow_style == arrow::STYLE_FOCUS)
	{
		arrow_brightness_ = ARROW_BRIGHTNESS_FOCUS;
		arrow_texture_ = ARROW_TEXTURE_VALID;
	}
	else if(arrow_style == arrow::STYLE_FOCUS_INVALID)
	{
		arrow_brightness_ = ARROW_BRIGHTNESS_STANDARD;
		arrow_texture_ = ARROW_TEXTURE_INVALID;
	}
}
Exemple #12
0
unit_ptr recruit::create_corresponding_unit()
{
	unit_type const* type = unit_types.find(unit_name_);
	assert(type);
	int side_num = team_index() + 1;
	//real_unit = false needed to avoid generating random traits and causing OOS
	bool real_unit = false;
	unit_ptr result(new unit(*type, side_num, real_unit));
	result->set_movement(0, true);
	result->set_attacks(0);
	return result; //ownership gets transferred to returned unique_ptr copy
}
Exemple #13
0
action::error recall::check_validity() const
{
	//Check that destination hex is still free
	if(resources::units->find(recall_hex_) != resources::units->end()) {
		return LOCATION_OCCUPIED;
	}
	//Check that unit to recall is still in side's recall list
	if( !(*resources::teams)[team_index()].recall_list().find_if_matches_id(temp_unit_->id()) ) {
		return UNIT_UNAVAILABLE;
	}
	//Check that there is still enough gold to recall this unit
	if((*resources::teams)[team_index()].recall_cost() > (*resources::teams)[team_index()].gold()) {
		return NOT_ENOUGH_GOLD;
	}
	//Check that there is a leader available to recall this unit
	if(!find_recruiter(team_index(),get_recall_hex())) {
		return NO_LEADER;
	}

	return OK;
}
Exemple #14
0
action::error recruit::check_validity() const
{
	//Check that destination hex is still free
	if(resources::units->find(recruit_hex_) != resources::units->end()) {
		return LOCATION_OCCUPIED;
	}
	//Check that unit to recruit is still in side's recruit list
	const std::set<std::string>& recruits = (*resources::teams)[team_index()].recruits();
	if(recruits.find(unit_name_) == recruits.end()) {
		return UNIT_UNAVAILABLE;
	}
	//Check that there is still enough gold to recruit this unit
	if(temp_unit_->cost() > (*resources::teams)[team_index()].gold()) {
		return NOT_ENOUGH_GOLD;
	}
	//Check that there is a leader available to recruit this unit
	if(!find_recruiter(team_index(),get_recruit_hex())) {
		return NO_LEADER;
	}

	return OK;
}
Exemple #15
0
bool move::calculate_new_route(const map_location& source_hex, const map_location& dest_hex)
{
	pathfind::plain_route new_plain_route;
	pathfind::shortest_path_calculator path_calc(*get_unit(),
						resources::teams->at(team_index()),
						*resources::teams, *resources::game_map);
	new_plain_route = pathfind::a_star_search(source_hex,
						dest_hex, 10000, &path_calc, resources::game_map->w(), resources::game_map->h());
	if (new_plain_route.move_cost >= path_calc.getNoPathValue()) return false;
	route_.reset(new pathfind::marked_route(pathfind::mark_route(new_plain_route)));
	calculate_move_cost();
	return true;
}
Exemple #16
0
void recall::draw_hex(map_location const& hex)
{
	if (hex == recall_hex_)
	{
		const double x_offset = 0.5;
		const double y_offset = 0.7;
		//position 0,0 in the hex is the upper left corner
		std::stringstream number_text;
		number_text << "-" << resources::teams->at(team_index()).recall_cost();
		size_t font_size = 16;
		SDL_Color color; color.r = 255; color.g = 0; color.b = 0; //red
		resources::screen->draw_text_in_hex(hex, display::LAYER_ACTIONS_NUMBERING,
						number_text.str(), font_size, color, x_offset, y_offset);
	}
}
Exemple #17
0
void recall::execute(bool& success, bool& complete)
{
	team & current_team = resources::teams->at(team_index());

	assert(valid());
	assert(temp_unit_.get());
	temporary_unit_hider const raii(*fake_unit_);
	//Give back the spent gold so we don't get "not enough gold" message
	int cost = current_team.recall_cost();
	current_team.get_side_actions()->change_gold_spent_by(-cost);
	bool const result = actions::recall_unit(temp_unit_->id(), current_team, recall_hex_, map_location::null_location);
	if (!result) {
		current_team.get_side_actions()->change_gold_spent_by(cost);
	}
	success = complete = result;
}
Exemple #18
0
void move::init()
{
	assert(get_unit());
	unit_id_ = get_unit()->id();

	//This action defines the future position of the unit, make its fake unit more visible
	//than previous actions' fake units
	if (fake_unit_)
	{
		fake_unit_->set_ghosted(true);
	}
	side_actions_ptr side_actions = resources::teams->at(team_index()).get_side_actions();
	side_actions::iterator action = side_actions->find_last_action_of(*(get_unit()));
	if (action != side_actions->end())
	{
		if (move_ptr move = boost::dynamic_pointer_cast<class move>(*action))
		{
			if (move->fake_unit_)
				move->fake_unit_->set_disabled_ghosted(true);
		}
	}

	this->calculate_move_cost();

	// Initialize arrow_brightness_ and arrow_texture_ using arrow_->style_
	arrow::STYLE arrow_style = arrow_->get_style();
	if(arrow_style == arrow::STYLE_STANDARD)
	{
		arrow_brightness_ = ARROW_BRIGHTNESS_STANDARD;
		arrow_texture_ = ARROW_TEXTURE_VALID;
	}
	else if(arrow_style == arrow::STYLE_HIGHLIGHTED)
	{
		arrow_brightness_ = ARROW_BRIGHTNESS_HIGHLIGHTED;
		arrow_texture_ = ARROW_TEXTURE_VALID;
	}
	else if(arrow_style == arrow::STYLE_FOCUS)
	{
		arrow_brightness_ = ARROW_BRIGHTNESS_FOCUS;
		arrow_texture_ = ARROW_TEXTURE_VALID;
	}
	else if(arrow_style == arrow::STYLE_FOCUS_INVALID)
	{
		arrow_brightness_ = ARROW_BRIGHTNESS_STANDARD;
		arrow_texture_ = ARROW_TEXTURE_INVALID;
	}
}
Exemple #19
0
void recruit::apply_temp_modifier(unit_map& unit_map)
{
	assert(valid());
	temp_unit_->set_location(recruit_hex_);

	DBG_WB << "Inserting future recruit [" << temp_unit_->id()
			<< "] at position " << temp_unit_->get_location() << ".\n";

	// Add cost to money spent on recruits.
	resources::gameboard->teams().at(team_index()).get_side_actions()->change_gold_spent_by(cost_);

	// Temporarily insert unit into unit_map
	// unit map takes ownership of temp_unit
	unit_map.insert(temp_unit_);

	// Update gold in the top bar
	game_display::get_singleton()->invalidate_game_status();
}
Exemple #20
0
void recruit::apply_temp_modifier(unit_map& unit_map)
{
	assert(valid_);
	temp_unit_->set_location(recruit_hex_);

	DBG_WB << "Inserting future recruit [" << temp_unit_->id()
			<< "] at position " << temp_unit_->get_location() << ".\n";

	temp_cost_ = temp_unit_->type()->cost();

	// Add cost to money spent on recruits.
	resources::teams->at(team_index()).get_side_actions()->change_gold_spent_by(temp_cost_);

	// Temporarily insert unit into unit_map
	unit_map.insert(temp_unit_);
	// unit map takes ownership of temp_unit
	temp_unit_ = NULL;

	// Update gold in the top bar
	resources::screen->invalidate_game_status();
}
Exemple #21
0
recall::recall(config const& cfg, bool hidden)
	: action(cfg,hidden)
	, temp_unit_()
	, recall_hex_(cfg.child("recall_hex_")["x"],cfg.child("recall_hex_")["y"])
	, fake_unit_()
{
	// Construct and validate temp_unit_
	size_t underlying_id = cfg["temp_unit_"];
	BOOST_FOREACH(const UnitConstPtr & recall_unit, resources::teams->at(team_index()).recall_list())
	{
		if(recall_unit->underlying_id()==underlying_id)
		{
			temp_unit_.reset(new class unit(*recall_unit)); //TODO: is it necessary to make a copy?
			break;
		}
	}
	if(!temp_unit_.get()) {
		throw action::ctor_err("recall: Invalid underlying_id");
	}

	fake_unit_.reset(UnitPtr(new class unit(*temp_unit_))); //makes copy of temp_unit_

	this->init();
}
Exemple #22
0
recall::recall(config const& cfg, bool hidden)
	: action(cfg,hidden)
	, temp_unit_()
	, recall_hex_(cfg.child("recall_hex_")["x"],cfg.child("recall_hex_")["y"])
	, fake_unit_()
{
	// Construct and validate temp_unit_
	size_t underlying_id = cfg["temp_unit_"];
	BOOST_FOREACH(unit const& recall_unit, resources::teams->at(team_index()).recall_list())
	{
		if(recall_unit.underlying_id()==underlying_id)
		{
			temp_unit_.reset(new unit(recall_unit));
			break;
		}
	}
	if(!temp_unit_.get()) {
		throw action::ctor_err("recall: Invalid underlying_id");
	}

	fake_unit_.reset(new game_display::fake_unit(*temp_unit_)); //makes copy of temp_unit_

	this->init();
}
Exemple #23
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();
	}
}