Example #1
0
void advance_unit(const map_location &loc, bool automatic, bool add_replay_event, const ai::unit_advancements_aspect& advancements)
{
	unit_map::iterator u = resources::units->find(loc);
	if(!unit_helper::will_certainly_advance(u)) {
		return;
	}

	LOG_DP << "advance_unit: " << u->type_id() << " (advances: " << u->advances()
		<< " XP: " <<u->experience() << '/' << u->max_experience() << ")\n";

	int res;

	if (automatic) {

		//if the advancements are empty or don't match any option
		//choose random instead.
		res = rand() % unit_helper::number_of_possible_advances(*u);

		const std::vector<std::string>& options = u->advances_to();
		const std::vector<std::string>& allowed = advancements.get_advancements(u);

		for(std::vector<std::string>::const_iterator a = options.begin(); a != options.end(); ++a) {
			if (std::find(allowed.begin(), allowed.end(), *a) != allowed.end()){
				res = a - options.begin();
				break;
			}
		}
	} else {
		res = advance_unit_dialog(loc);
	}
	if(add_replay_event) {
		recorder.add_advancement(loc);
	}

	config choice_cfg;
	choice_cfg["value"] = res;
	recorder.user_input("choose", choice_cfg);

	LOG_DP << "animating advancement...\n";
	animate_unit_advancement(loc, size_t(res));

	// In some rare cases the unit can have enough XP to advance again,
	// so try to do that.
	// Make sure that we don't enter an infinite level loop.
	u = resources::units->find(loc);
	if (u != resources::units->end()) {
		// Level 10 unit gives 80 XP and the highest mainline is level 5
		if (u->experience() < 81) {
			// For all leveling up we have to add advancement to replay here because replay
			// doesn't handle cascading advancement since it just calls animate_unit_advancement().
			advance_unit(loc, automatic, true, advancements);
		} else {
			ERR_CF << "Unit has too many (" << u->experience()
				<< ") XP left; cascade leveling disabled.\n";
		}
	} else {
		ERR_NG << "Unit advanced no longer exists.\n";
	}
}
Example #2
0
void advance_unit(const map_location &loc, bool random_choice, bool add_replay_event)
{
	unit_map::iterator u = resources::units->find(loc);
	if(!unit_helper::will_certainly_advance(u)) {
		return;
	}

	LOG_DP << "advance_unit: " << u->type_id() << " (advances: " << u->advances()
		<< " XP: " <<u->experience() << '/' << u->max_experience() << ")\n";

	int res;

	if (random_choice) {
		res = rand() % unit_helper::number_of_possible_advances(*u);
	} else {
		res = advance_unit_dialog(loc);
	}

	if(add_replay_event) {
		recorder.add_advancement(loc);
	}

	config choice_cfg;
	choice_cfg["value"] = res;
	recorder.user_input("choose", choice_cfg);

	LOG_DP << "animating advancement...\n";
	animate_unit_advancement(loc, size_t(res));

	// In some rare cases the unit can have enough XP to advance again,
	// so try to do that.
	// Make sure that we don't enter an infinite level loop.
	u = resources::units->find(loc);
	if (u != resources::units->end()) {
		// Level 10 unit gives 80 XP and the highest mainline is level 5
		if (u->experience() < 81) {
			// For all leveling up we have to add advancement to replay here because replay
			// doesn't handle cascading advancement since it just calls animate_unit_advancement().
			advance_unit(loc, random_choice, true);
		} else {
			ERR_CF << "Unit has an too high amount of " << u->experience()
				<< " XP left, cascade leveling disabled\n";
		}
	} else {
		ERR_NG << "Unit advanced no longer exists\n";
	}
}
Example #3
0
/*
advances the unit and stores data in the replay (or reads data from replay).
*/
void advance_unit_at(const advance_unit_params& params)
{
	//i just don't want infinite loops...
	// the 20 is picked rather randomly.
	for(int advacment_number = 0; advacment_number < 20; advacment_number++)
	{
		unit_map::iterator u = resources::gameboard->units().find(params.loc_);
		//this implies u.valid()
		if(!unit_helper::will_certainly_advance(u)) {
			return;
		}

		if(params.fire_events_)
		{
			LOG_NG << "Firing pre advance event at " << params.loc_ <<".\n";
			resources::game_events->pump().fire("pre_advance", params.loc_);
			//TODO: maybe use id instead of location here ?.
			u = resources::gameboard->units().find(params.loc_);
			if(!unit_helper::will_certainly_advance(u))
			{
				LOG_NG << "pre advance event aborted advancing.\n";
				return;
			}
		}
		//we don't want to let side 1 decide it during start/prestart.
		int side_for = resources::gamedata->phase() == game_data::PLAY ? 0: u->side();
		config selected = mp_sync::get_user_choice("choose",
			unit_advancement_choice(params.loc_, unit_helper::number_of_possible_advances(*u), u->side(), params.ai_advancements_, params.force_dialog_), side_for);
		//calls actions::advance_unit.
		bool result = animate_unit_advancement(params.loc_, selected["value"], params.fire_events_, params.animate_);

		DBG_NG << "animate_unit_advancement result = " << result << std::endl;
		u = resources::gameboard->units().find(params.loc_);
		// level 10 unit gives 80 XP and the highest mainline is level 5
		if (u.valid() && u->experience() > 80)
		{
			WRN_NG << "Unit has too many (" << u->experience() << ") XP left; cascade leveling goes on still." << std::endl;
		}
	}
	ERR_NG << "unit at " << params.loc_ << "tried to advance more than 20 times. Advancing was aborted" << std::endl;
}