/**
 * @brief Set base attack mission, and go to base position.
 * @note Base attack mission -- Stage 1
 */
static void CP_BaseAttackGoToBase (mission_t *mission)
{
	base_t *base;

	mission->stage = STAGE_MISSION_GOTO;

	base = CP_BaseAttackChooseBase();
	if (!base) {
		Com_Printf("CP_BaseAttackGoToBase: no base found\n");
		CP_MissionRemove(mission);
		return;
	}
	mission->data.base = base;

	mission->mapDef = Com_GetMapDefinitionByID("baseattack");
	if (!mission->mapDef) {
		CP_MissionRemove(mission);
		Com_Error(ERR_DROP, "Could not find mapdef baseattack");
		return;
	}

	Vector2Copy(base->pos, mission->pos);
	mission->posAssigned = qtrue;

	Com_sprintf(mission->location, sizeof(mission->location), "%s", base->name);

	if (mission->ufo) {
		CP_MissionDisableTimeLimit(mission);
		UFO_SendToDestination(mission->ufo, mission->pos);
	} else {
		/* Go to next stage on next frame */
		mission->finalDate = ccs.date;
	}
}
/**
 * @brief Supply mission begins: UFO arrive on earth.
 * @note Supply mission -- Stage 0
 */
static void CP_SupplyMissionCreate (mission_t *mission)
{
	ufoType_t ufoType;

	mission->stage = STAGE_COME_FROM_ORBIT;

	/* Maybe base has been destroyed since mission creation ? */
	if (!AB_CheckSupplyMissionPossible()) {
		Com_DPrintf(DEBUG_CLIENT, "No base in game: removing supply mission.\n");
		CP_MissionRemove(mission);
		return;
	}

	ufoType = CP_MissionChooseUFO(mission);
	if (ufoType == UFO_MAX) {
		Com_DPrintf(DEBUG_CLIENT, "Supply mission can't be spawned without UFO: removing supply mission.\n");
		CP_MissionRemove(mission);
	} else {
		CP_MissionDisableTimeLimit(mission);
		mission->ufo = UFO_AddToGeoscape(ufoType, NULL, mission);
		if (!mission->ufo) {
			Com_Printf("CP_SupplyMissionCreate: Could not add UFO '%s', remove mission\n", Com_UFOTypeToShortName(ufoType));
			CP_MissionRemove(mission);
		}
	}
}
Exemple #3
0
/**
 * @brief Set ground mission, and go to ground mission pos.
 * @note Recon mission -- Stage 1
 * @note ground mission can be spawned without UFO
 * @sa CP_ReconMissionSelect
 */
void CP_ReconMissionGroundGo (mission_t *mission)
{
	const nation_t *nation;

	mission->stage = STAGE_MISSION_GOTO;

	/* maybe the UFO just finished a ground mission and starts a new one? */
	if (mission->ufo) {
		CP_MissionRemoveFromGeoscape(mission);
		mission->ufo->landed = false;
	}

	/* Choose a map */
	if (CP_ChooseMap(mission, NULL)) {
		int counter;
		for (counter = 0; counter < MAX_POS_LOOP; counter++) {
			if (!CP_GetRandomPosOnGeoscapeWithParameters(mission->pos, mission->mapDef->terrains, mission->mapDef->cultures, mission->mapDef->populations, NULL))
				continue;
			if (MAP_PositionCloseToBase(mission->pos))
				continue;
			mission->posAssigned = true;
			break;
		}
		if (counter >= MAX_POS_LOOP) {
			Com_Printf("CP_ReconMissionGroundGo: Error, could not set position.\n");
			CP_MissionRemove(mission);
			return;
		}
	} else {
		Com_Printf("CP_ReconMissionGroundGo: No map found, remove mission.\n");
		CP_MissionRemove(mission);
		return;
	}

	nation = MAP_GetNation(mission->pos);
	if (nation) {
		Com_sprintf(mission->location, sizeof(mission->location), "%s", _(nation->name));
	} else {
		Com_sprintf(mission->location, sizeof(mission->location), "%s", _("No nation"));
	}

	if (mission->ufo) {
		CP_MissionDisableTimeLimit(mission);
		UFO_SendToDestination(mission->ufo, mission->pos);
	} else {
		/* Go to next stage on next frame */
		mission->finalDate = ccs.date;
	}
}
/**
 * @brief Determine what action should be performed when a Base Attack mission stage ends.
 * @param[in] mission Pointer to the mission which stage ended.
 */
void CP_BaseAttackMissionNextStage (mission_t *mission)
{
	switch (mission->stage) {
	case STAGE_NOT_ACTIVE:
		/* Create mission */
		CP_MissionBegin(mission);
		break;
	case STAGE_COME_FROM_ORBIT:
		/* Choose a base to attack and go to this base */
		CP_BaseAttackGoToBase(mission);
		break;
	case STAGE_MISSION_GOTO:
		/* just arrived on base location: attack it */
		CP_BaseAttackStartMission(mission);
		break;
	case STAGE_BASE_ATTACK:
		/* Leave earth */
		CP_BaseAttackMissionDestroyBase(mission);
		break;
	case STAGE_RETURN_TO_ORBIT:
		/* mission is over, remove mission */
		CP_BaseAttackMissionIsSuccess(mission);
		break;
	default:
		Com_Printf("CP_BaseAttackMissionNextStage: Unknown stage: %i, removing mission.\n", mission->stage);
		CP_MissionRemove(mission);
		break;
	}
}
/**
 * @brief Terror attack mission is over and is a success: change interest values.
 * @note Terror attack mission
 */
void CP_TerrorMissionIsSuccess (mission_t *mission)
{
	INT_ChangeIndividualInterest(-0.2f, INTERESTCATEGORY_BASE_ATTACK);
	INT_ChangeIndividualInterest(0.03f, INTERESTCATEGORY_HARVEST);

	CP_MissionRemove(mission);
}
Exemple #6
0
/**
 * @brief Determine what action should be performed when a Harvesting mission stage ends.
 * @param[in] mission Pointer to the mission which stage ended.
 */
void CP_HarvestMissionNextStage (mission_t* mission)
{
	switch (mission->stage) {
	case STAGE_NOT_ACTIVE:
		/* Create Harvesting mission */
		CP_MissionBegin(mission);
		break;
	case STAGE_COME_FROM_ORBIT:
		/* Go to mission */
		CP_HarvestMissionGo(mission);
		break;
	case STAGE_MISSION_GOTO:
		/* just arrived on a new Harvesting mission: start it */
		CP_HarvestMissionStart(mission);
		break;
	case STAGE_HARVEST:
		/* Leave earth */
		CP_ReconMissionLeave(mission);
		break;
	case STAGE_RETURN_TO_ORBIT:
		/* mission is over, remove mission */
		CP_HarvestMissionIsSuccess(mission);
		break;
	default:
		Com_Printf("CP_HarvestMissionNextStage: Unknown stage: %i, removing mission.\n", mission->stage);
		CP_MissionRemove(mission);
		break;
	}
}
/**
 * @brief Determine what action should be performed when a Intercept mission stage ends.
 * @param[in] mission Pointer to the mission which stage ended.
 */
void CP_InterceptNextStage (mission_t* mission)
{
	switch (mission->stage) {
	case STAGE_NOT_ACTIVE:
		/* Create Intercept mission */
		CP_MissionBegin(mission);
		break;
	case STAGE_COME_FROM_ORBIT:
		/* UFO start looking for target */
		CP_InterceptMissionSet(mission);
		break;
	case STAGE_MISSION_GOTO:
		CP_InterceptAttackInstallation(mission);
		break;
	case STAGE_INTERCEPT:
		assert(mission->ufo);
		/* Leave earth */
		if (AIRFIGHT_ChooseWeapon(mission->ufo->weapons, mission->ufo->maxWeapons, mission->ufo->pos, mission->ufo->pos) !=
			AIRFIGHT_WEAPON_CAN_NEVER_SHOOT && mission->ufo->status == AIR_UFO && !mission->data.installation) {
			/* UFO is fighting and has still ammo, wait a little bit before leaving (UFO is not attacking an installation) */
			const date_t AdditionalDelay = {0, 3600};	/* check every hour if there is still ammos */
			mission->finalDate = Date_Add(ccs.date, AdditionalDelay);
		} else
			CP_InterceptMissionLeave(mission, true);
		break;
	case STAGE_RETURN_TO_ORBIT:
		/* mission is over, remove mission */
		CP_InterceptMissionIsSuccess(mission);
		break;
	default:
		Com_Printf("CP_InterceptNextStage: Unknown stage: %i, removing mission.\n", mission->stage);
		CP_MissionRemove(mission);
		break;
	}
}
/**
 * @brief UFO arrived on new base destination: Supply base.
 * @param[in,out] mission Pointer to the mission
 * @note Supply mission -- Stage 2
 */
static void CP_SupplySetStayAtBase (mission_t *mission)
{
	const date_t minSupplyTime = {3, 0};
	const date_t supplyTime = {10, 0};	/**< Max time needed to supply base */

	assert(mission->ufo);
	/* there must be an alien base set */
	assert(mission->data.alienBase);

	mission->stage = STAGE_SUPPLY;

	/* Maybe base has been destroyed since mission creation ? */
	if (!AB_CheckSupplyMissionPossible()) {
		Com_DPrintf(DEBUG_CLIENT, "No base in game: removing supply mission.\n");
		CP_MissionRemove(mission);
		return;
	}

	mission->finalDate = Date_Add(ccs.date, Date_Random(minSupplyTime, supplyTime));

	AB_SupplyBase(mission->data.alienBase, mission->ufo->detected);

	/* ufo becomes invisible on geoscape */
	CP_UFORemoveFromGeoscape(mission, false);
}
/**
 * @brief Determine what action should be performed when a Recon mission stage ends.
 * @param[in] mission Pointer to the mission which stage ended.
 */
void CP_ReconMissionNextStage (mission_t *mission)
{
	switch (mission->stage) {
	case STAGE_NOT_ACTIVE:
		/* Create Recon mission */
		CP_MissionBegin(mission);
		break;
	case STAGE_COME_FROM_ORBIT:
	case STAGE_RECON_GROUND:
		/* Choose if a new ground mission should be started */
		CP_ReconMissionSelect(mission);
		break;
	case STAGE_MISSION_GOTO:
		/* just arrived on a new ground mission: start it */
		CP_ReconMissionGround(mission);
		break;
	case STAGE_RECON_AIR:
		/* Leave earth */
		CP_ReconMissionLeave(mission);
		break;
	case STAGE_RETURN_TO_ORBIT:
		/* mission is over, remove mission */
		CP_ReconMissionIsSuccess(mission);
		break;
	default:
		Com_Printf("CP_ReconMissionNextStage: Unknown stage: %i, removing mission.\n", mission->stage);
		CP_MissionRemove(mission);
		break;
	}
}
/**
 * @brief Determine what action should be performed when a Supply mission stage ends.
 * @param[in] mission Pointer to the mission which stage ended.
 */
void CP_SupplyMissionNextStage (mission_t *mission)
{
	switch (mission->stage) {
	case STAGE_NOT_ACTIVE:
		/* Create mission */
		CP_SupplyMissionCreate(mission);
		break;
	case STAGE_COME_FROM_ORBIT:
		/* Go to base position */
		CP_SupplyGoToBase(mission);
		break;
	case STAGE_MISSION_GOTO:
		/* just arrived on base location: Supply base */
		CP_SupplySetStayAtBase(mission);
		break;
	case STAGE_SUPPLY:
		/* Leave earth */
		CP_SupplyMissionLeave(mission);
		break;
	case STAGE_RETURN_TO_ORBIT:
		/* mission is over, remove mission */
		CP_SupplyMissionIsSuccess(mission);
		break;
	default:
		Com_Printf("CP_SupplyMissionNextStage: Unknown stage: %i, removing mission.\n", mission->stage);
		CP_MissionRemove(mission);
		break;
	}
}
/**
 * @brief Supply mission is over and is a failure (from an alien point of view): change interest values.
 * @note Supply mission
 */
void CP_SupplyMissionIsFailure (mission_t *mission)
{
	INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_SUPPLY);
	INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_INTERCEPT);
	INT_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_BASE_ATTACK);

	CP_MissionRemove(mission);
}
/**
 * @brief Recon mission is over and is a failure: change interest values.
 * @note Recon mission
 */
void CP_ReconMissionIsFailure (mission_t *mission)
{
	INT_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_RECON);
	INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_INTERCEPT);
	INT_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_TERROR_ATTACK);

	CP_MissionRemove(mission);
}
/**
 * @brief Build Base mission is over and is a failure (from an alien point of view): change interest values.
 * @note Build Base mission
 */
void CP_BuildBaseMissionIsFailure (mission_t* mission)
{
	/* Restore some alien interest for build base that has been removed when mission has been created */
	INT_ChangeIndividualInterest(0.5f, INTERESTCATEGORY_BUILDING);
	INT_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_BASE_ATTACK);

	CP_MissionRemove(mission);
}
Exemple #14
0
/**
 * @brief Harvesting mission is over and is a failure: change interest values.
 * @note Harvesting mission
 */
void CP_HarvestMissionIsFailure (mission_t* mission)
{
	INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_INTERCEPT);
	INT_ChangeIndividualInterest(0.03f, INTERESTCATEGORY_BASE_ATTACK);
	INT_ChangeIndividualInterest(0.03f, INTERESTCATEGORY_TERROR_ATTACK);

	CP_MissionRemove(mission);
}
Exemple #15
0
/**
 * @brief Set Harvest mission, and go to mission pos.
 * @note Harvesting attack mission -- Stage 1
 * @todo Remove me when CP_XVIMissionGo will be implemented
 * This function should take a location close to an XVI infection point
 * see gameplay proposal on wiki
 */
void CP_HarvestMissionGo (mission_t *mission)
{
	const nation_t *nation;

	mission->stage = STAGE_MISSION_GOTO;

	/* Choose a map */
	if (CP_ChooseMap(mission, NULL)) {
		int counter;
		linkedList_t *nationList = NULL;
		const qboolean nationTest = CP_ChooseNation(mission, &nationList);
		for (counter = 0; counter < MAX_POS_LOOP; counter++) {
			if (!CP_GetRandomPosOnGeoscapeWithParameters(mission->pos, mission->mapDef->terrains, mission->mapDef->cultures, mission->mapDef->populations, nationTest ? nationList : NULL))
				continue;
			if (MAP_PositionCloseToBase(mission->pos))
				continue;
			mission->posAssigned = qtrue;
			break;
		}
		if (counter >= MAX_POS_LOOP) {
			Com_Printf("CP_HarvestMissionGo: Error, could not set position.\n");
			CP_MissionRemove(mission);
			return;
		}
		LIST_Delete(&nationList);
	} else {
		Com_Printf("CP_HarvestMissionGo: No map found, remove mission.\n");
		CP_MissionRemove(mission);
		return;
	}

	nation = MAP_GetNation(mission->pos);
	if (nation) {
		Com_sprintf(mission->location, sizeof(mission->location), "%s", _(nation->name));
	} else {
		Com_sprintf(mission->location, sizeof(mission->location), "%s", _("No nation"));
	}

	if (mission->ufo) {
		CP_MissionDisableTimeLimit(mission);
		UFO_SendToDestination(mission->ufo, mission->pos);
	} else {
		/* Go to next stage on next frame */
		mission->finalDate = ccs.date;
	}
}
/**
 * @brief XVI Spreading mission is over and is a success: change interest values.
 * @note XVI Spreading mission
 */
void CP_XVIMissionIsSuccess (mission_t *mission)
{
	INT_ChangeIndividualInterest(-0.3f, INTERESTCATEGORY_XVI);
	INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_HARVEST);
	INT_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_BUILDING);

	CP_MissionRemove(mission);
}
Exemple #17
0
/**
 * @brief Base attack mission is over and is a success (from an alien point of view): change interest values.
 * @note Base attack mission
 * @sa CP_BaseAttackMissionStart
 */
void CP_BaseAttackMissionIsSuccess (mission_t* mission)
{
	INT_ChangeIndividualInterest(0.3f, INTERESTCATEGORY_RECON);
	INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_HARVEST);
	INT_ChangeIndividualInterest(-0.5f, INTERESTCATEGORY_TERROR_ATTACK);
	INT_ChangeIndividualInterest(-0.5f, INTERESTCATEGORY_INTERCEPT);

	CP_MissionRemove(mission);
}
/**
 * @brief Terror attack mission is over and is a failure: change interest values.
 * @note Terror attack mission
 */
void CP_TerrorMissionIsFailure (mission_t *mission)
{
	INT_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_TERROR_ATTACK);
	INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_INTERCEPT);
	INT_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_BUILDING);
	INT_ChangeIndividualInterest(0.02f, INTERESTCATEGORY_BASE_ATTACK);

	CP_MissionRemove(mission);
}
static void SCP_CampaignAddMission (setState_t *set)
{
	actMis_t *mis;
	mission_t * mission;
	const nation_t *nation;

	/* add mission */
	if (scd->numActiveMissions >= MAX_ACTMISSIONS) {
		return;
	}

	mis = &scd->activeMissions[scd->numActiveMissions];
	OBJZERO(*mis);

	/* set relevant info */
	mis->def = SCP_GetMission(set);
	if (mis->def == NULL) {
		return;
	}
	mis->cause = set;

	if (set->def->expire.day)
		mis->expire = Date_Add(ccs.date, set->def->expire);

	/* prepare next event (if any) */
	set->num++;
	if (set->def->number && set->num >= set->def->number) {
		set->active = false;
	} else {
		const date_t minTime = {0, 0};
		set->event = Date_Add(ccs.date, Date_Random(minTime, set->def->frame));
	}

	mission = CP_CreateNewMission(INTERESTCATEGORY_TERROR_ATTACK, true);
	mission->mapDef = cgi->Com_GetMapDefinitionByID(mis->def->id);
	if (!mission->mapDef) {
		Com_Printf("SCP_CampaignAddMission: Could not get the mapdef '%s'\n", mis->def->id);
		CP_MissionRemove(mission);
		return;
	}
	Vector2Copy(mis->def->pos, mission->pos);
	mission->posAssigned = true;
	nation = MAP_GetNation(mission->pos);
	if (nation) {
		Com_sprintf(mission->location, sizeof(mission->location), "%s", _(nation->name));
	} else {
		Com_sprintf(mission->location, sizeof(mission->location), "%s", _("No nation"));
	}
	CP_TerrorMissionStart(mission);
	mission->finalDate = mis->expire;
	mis->mission = mission;

	Com_Printf("spawned map '%s'\n", mis->def->id);

	scd->numActiveMissions++;
}
Exemple #20
0
/**
 * @brief Harvesting mission is over and is a success: change interest values.
 * @note Harvesting mission
 */
static void CP_HarvestMissionIsSuccess (mission_t* mission)
{
	INT_ChangeIndividualInterest(-0.3f, INTERESTCATEGORY_HARVEST);
	INT_ChangeIndividualInterest(0.2f, INTERESTCATEGORY_RECON);
	INT_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_BUILDING);
	if (CP_IsXVIStarted())
		INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_XVI);

	CP_MissionRemove(mission);
}
/**
 * @brief Intercept mission is over and is a success: change interest values.
 * @note Intercept mission
 */
void CP_InterceptMissionIsSuccess (mission_t* mission)
{
	INT_ChangeIndividualInterest(0.3f, INTERESTCATEGORY_RECON);
	INT_ChangeIndividualInterest(-0.3f, INTERESTCATEGORY_INTERCEPT);
	INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_HARVEST);
	if (CP_IsXVIStarted())
		INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_XVI);

	CP_MissionRemove(mission);
}
/**
 * @brief Recon mission is over and is a success: change interest values.
 * @note Recon mission
 */
static void CP_ReconMissionIsSuccess (mission_t *mission)
{
	INT_ChangeIndividualInterest(-0.2f, INTERESTCATEGORY_RECON);
	INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_HARVEST);
	if (AB_GetAlienBaseNumber())
		INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_SUPPLY);
	if (CP_IsXVIStarted())
		INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_XVI);

	CP_MissionRemove(mission);
}
/**
 * @brief Supply mission is over and is a success (from an alien point of view): change interest values.
 * @note Supply mission
 */
void CP_SupplyMissionIsSuccess (mission_t *mission)
{
	alienBase_t *base;
	INT_ChangeIndividualInterest(-0.2f, INTERESTCATEGORY_SUPPLY);

	/* Spread XVI */
	base = mission->data.alienBase;
	assert(base);
	CP_SpreadXVIAtPos(base->pos);

	CP_MissionRemove(mission);
}
/**
 * @brief Alien base has been destroyed: change interest values.
 * @note Build Base mission
 */
void CP_BuildBaseMissionBaseDestroyed (mission_t* mission)
{
	/* An alien base has been built */
	alienBase_t* base = mission->data.alienBase;
	assert(base);

	INT_ChangeIndividualInterest(+0.1f, INTERESTCATEGORY_BUILDING);
	INT_ChangeIndividualInterest(+0.3f, INTERESTCATEGORY_INTERCEPT);

	AB_DestroyBase(base);
	mission->data.alienBase = nullptr;
	CP_MissionRemove(mission);
}
/**
 * @brief Build Base mission is over and is a success (from an alien point of view): change interest values.
 * @note Build Base mission
 */
void CP_BuildBaseMissionIsSuccess (mission_t *mission)
{
	if (CP_BasemissionIsSubvertingGovernmentMission(mission)) {
		/* This is a subverting government mission */
		CL_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_TERROR_ATTACK);
	} else {
		/* An alien base has been built */
		const alienBase_t *base = mission->data.alienBase;
		assert(base);
		CP_SpreadXVIAtPos(base->pos);

		CL_ChangeIndividualInterest(0.4f, INTERESTCATEGORY_XVI);
		CL_ChangeIndividualInterest(0.4f, INTERESTCATEGORY_SUPPLY);
		CL_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_HARVEST);
	}

	CP_MissionRemove(mission);
}
/**
 * @brief Set Terror attack mission, and go to Terror attack mission pos.
 * @note Terror attack mission -- Stage 1
 * @note Terror missions can only take place in city: pick one in ccs.cities.
 */
static void CP_TerrorMissionGo (mission_t *mission)
{
	int counter;

	mission->stage = STAGE_MISSION_GOTO;

	/* Choose a map */
	for (counter = 0; counter < MAX_POS_LOOP; counter++) {
		city_t *city = CP_ChooseCity();

		if (!city)
			continue;

		if (GEO_PositionCloseToBase(city->pos))
			continue;

		if (!CP_ChooseMap(mission, city->pos))
			continue;

		if (CP_TerrorInCity(city))
			continue;

		Vector2Copy(city->pos, mission->pos);
		mission->data.city = city;
		mission->posAssigned = true;
		break;
	}
	if (counter >= MAX_POS_LOOP) {
		Com_DPrintf(DEBUG_CLIENT, "CP_TerrorMissionGo: Could not set position.\n");
		CP_MissionRemove(mission);
		return;
	}

	if (mission->ufo) {
		CP_MissionDisableTimeLimit(mission);
		UFO_SendToDestination(mission->ufo, mission->pos);
	} else {
		/* Go to next stage on next frame */
		mission->finalDate = ccs.date;
	}
}
/**
 * @brief Set Intercept mission: UFO chooses an installation an flies to it.
 * @note Intercept mission -- Stage 1
 */
void CP_InterceptGoToInstallation (mission_t* mission)
{
	installation_t* installation;
	assert(mission->ufo);

	mission->stage = STAGE_MISSION_GOTO;

	installation = CP_InterceptChooseInstallation(mission);
	if (!installation) {
		Com_Printf("CP_InterceptGoToInstallation: no installation found\n");
		CP_MissionRemove(mission);
		return;
	}
	mission->data.installation = installation;

	Vector2Copy(installation->pos, mission->pos);
	mission->posAssigned = true;

	CP_MissionDisableTimeLimit(mission);
	UFO_SendToDestination(mission->ufo, mission->pos);
}
/**
 * @brief Base attack mission is over and is a failure (from an alien point of view): change interest values.
 */
void CP_BaseAttackMissionIsFailure (mission_t *mission)
{
	base_t *base = mission->data.base;

	if (base)
		base->baseStatus = BASE_WORKING;
	ccs.mapAction = MA_NONE;

	/* we really don't want to use the fake aircraft anywhere */
	if (base)
		base->aircraftCurrent = AIR_GetFirstFromBase(base);
	MAP_SetMissionAircraft(NULL);

	CL_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_BUILDING);
	CL_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_BASE_ATTACK);

	/* reset current selected mission */
	MAP_NotifyMissionRemoved(mission);

	CP_MissionRemove(mission);
}
/**
 * @brief Go to base position.
 * @param[in,out] mission Pointer to the mission
 * @note Supply mission -- Stage 1
 */
static void CP_SupplyGoToBase (mission_t *mission)
{
	alienBase_t *alienBase;

	assert(mission->ufo);

	mission->stage = STAGE_MISSION_GOTO;

	/* Maybe base has been destroyed since mission creation ? */
	if (!AB_CheckSupplyMissionPossible()) {
		Com_DPrintf(DEBUG_CLIENT, "No base in game: removing supply mission.\n");
		CP_MissionRemove(mission);
		return;
	}

	alienBase = AB_ChooseBaseToSupply();
	assert(alienBase);
	mission->data.alienBase = alienBase;
	Vector2Copy(alienBase->pos, mission->pos);

	UFO_SendToDestination(mission->ufo, mission->pos);
}
/**
 * @brief UFO arrived on new base destination: build base.
 * @param[in,out] mission Pointer to the mission
 * @note Build Base mission -- Stage 2
 */
static void CP_BuildBaseSetUpBase (mission_t* mission)
{
	alienBase_t* base;
	const date_t minBuildingTime = {5, 0};	/**< Minimum time needed to start a new base construction */
	const date_t buildingTime = {10, 0};	/**< Maximum time needed to start a new base construction */

	assert(mission->ufo);

	mission->stage = STAGE_BUILD_BASE;

	mission->finalDate = Date_Add(ccs.date, Date_Random(minBuildingTime, buildingTime));

	base = AB_BuildBase(mission->pos);
	if (!base) {
		Com_DPrintf(DEBUG_CLIENT, "CP_BuildBaseSetUpBase: could not create alien base\n");
		CP_MissionRemove(mission);
		return;
	}
	mission->data.alienBase = base;

	/* ufo becomes invisible on geoscape */
	CP_UFORemoveFromGeoscape(mission, false);
}