cp_mission_intercept.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "../../cl_shared.h"
00027 #include "../cp_campaign.h"
00028 #include "../cp_ufo.h"
00029 #include "../cp_missions.h"
00030 #include "../cp_time.h"
00031 #include "../cp_alien_interest.h"
00032 #include "../cp_xvi.h"
00033 
00038 void CP_InterceptMissionIsSuccess (mission_t *mission)
00039 {
00040     CL_ChangeIndividualInterest(0.3f, INTERESTCATEGORY_RECON);
00041     CL_ChangeIndividualInterest(-0.3f, INTERESTCATEGORY_INTERCEPT);
00042     CL_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_HARVEST);
00043     if (CP_IsXVIResearched())
00044         CL_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_XVI);
00045 
00046     CP_MissionRemove(mission);
00047 }
00048 
00053 void CP_InterceptMissionIsFailure (mission_t *mission)
00054 {
00055     CL_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_INTERCEPT);
00056     CL_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_BUILDING);
00057     CL_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_BASE_ATTACK);
00058     CL_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_TERROR_ATTACK);
00059 
00060     CP_MissionRemove(mission);
00061 }
00062 
00069 void CP_InterceptMissionLeave (mission_t *mission, qboolean destroyed)
00070 {
00071     installation_t *installation;
00072 
00073     assert(mission->ufo);
00074 
00075     mission->stage = STAGE_RETURN_TO_ORBIT;
00076 
00077     /* if the mission was an attack of an installation, destroy it */
00078     installation = (installation_t *)mission->data;
00079     if (destroyed && installation && installation->founded && VectorCompareEps(mission->pos, installation->pos, UFO_EPSILON)) {
00080         INS_DestroyInstallation(installation);
00081     }
00082 
00083     CP_MissionDisableTimeLimit(mission);
00084     UFO_SetRandomDest(mission->ufo);
00085     CP_MissionRemoveFromGeoscape(mission);
00086     /* Display UFO on geoscape if it is detected */
00087     mission->ufo->landed = qfalse;
00088 }
00089 
00094 static void CP_InterceptAttackInstallation (mission_t *mission)
00095 {
00096     const date_t minAttackDelay = {0, 3600};
00097     const date_t attackDelay = {0, 21600};      /* How long the UFO should stay on earth */
00098     installation_t *installation;
00099 
00100     mission->stage = STAGE_INTERCEPT;
00101 
00102     /* Check that installation is not already destroyed */
00103     installation = (installation_t *)mission->data;
00104     if (!installation->founded) {
00105         mission->finalDate = ccs.date;
00106         return;
00107     }
00108 
00109     /* Maybe installation has been destroyed, but rebuild somewhere else? */
00110     if (!VectorCompareEps(mission->pos, installation->pos, UFO_EPSILON)) {
00111         mission->finalDate = ccs.date;
00112         return;
00113     }
00114 
00115     /* Make round around the position of the mission */
00116     UFO_SetRandomDestAround(mission->ufo, mission->pos);
00117     mission->finalDate = Date_Add(ccs.date, Date_Random(minAttackDelay, attackDelay));
00118 }
00119 
00124 void CP_InterceptAircraftMissionSet (mission_t *mission)
00125 {
00126     const date_t minReconDelay = {3, 0};
00127     const date_t reconDelay = {6, 0};       /* How long the UFO should stay on earth */
00128 
00129     mission->stage = STAGE_INTERCEPT;
00130     mission->finalDate = Date_Add(ccs.date, Date_Random(minReconDelay, reconDelay));
00131 }
00132 
00138 static installation_t* CP_InterceptChooseInstallation (const mission_t *mission)
00139 {
00140     float randomNumber, sum = 0.0f;
00141     int installationIdx;
00142     installation_t *installation = NULL;
00143 
00144     assert(mission);
00145 
00146     /* Choose randomly a base depending on alienInterest values for those bases */
00147     for (installationIdx = 0; installationIdx < MAX_INSTALLATIONS; installationIdx++) {
00148         installation = INS_GetFoundedInstallationByIDX(installationIdx);
00149         if (!installation)
00150             continue;
00151         sum += installation->alienInterest;
00152     }
00153     randomNumber = frand() * sum;
00154     for (installationIdx = 0; installationIdx < MAX_INSTALLATIONS; installationIdx++) {
00155         installation = INS_GetFoundedInstallationByIDX(installationIdx);
00156         if (!installation)
00157             continue;
00158         randomNumber -= installation->alienInterest;
00159         if (randomNumber < 0)
00160             break;
00161     }
00162 
00163     /* Make sure we have a base */
00164     assert(installation && (randomNumber < 0));
00165 
00166     return installation;
00167 }
00168 
00173 void CP_InterceptGoToInstallation (mission_t *mission)
00174 {
00175     installation_t *installation;
00176     assert(mission->ufo);
00177 
00178     mission->stage = STAGE_MISSION_GOTO;
00179 
00180     installation = CP_InterceptChooseInstallation(mission);
00181     if (!installation) {
00182         Com_Printf("CP_InterceptGoToInstallation: no installation found\n");
00183         CP_MissionRemove(mission);
00184         return;
00185     }
00186     mission->data = (void *)installation;
00187 
00188     Vector2Copy(installation->pos, mission->pos);
00189     mission->posAssigned = qtrue;
00190 
00191     Com_sprintf(mission->location, sizeof(mission->location), "%s", installation->name);
00192 
00193     CP_MissionDisableTimeLimit(mission);
00194     UFO_SendToDestination(mission->ufo, mission->pos);
00195 }
00196 
00201 static void CP_InterceptMissionSet (mission_t *mission)
00202 {
00203     assert(mission->ufo);
00204 
00205     /* Only harvesters can attack installations -- if there are installations to attack */
00206     if (mission->ufo->ufotype == UFO_HARVESTER && ccs.numInstallations) {
00207         CP_InterceptGoToInstallation(mission);
00208     }
00209 
00210     CP_InterceptAircraftMissionSet(mission);
00211 }
00212 
00220 int CP_InterceptMissionAvailableUFOs (const mission_t const *mission, ufoType_t *ufoTypes)
00221 {
00222     int num = 0;
00223     /* Probability to get a harvester. Note that the probability
00224      * to get a corrupter among all possible UFO is this number
00225      * divided by the number of possible UFO */
00226     const float HARVESTER_PROBABILITY = 0.25;
00227 
00228     ufoTypes[num++] = UFO_FIGHTER;
00229 
00230     /* don't make attack on installation happens too often */
00231     if (frand() < HARVESTER_PROBABILITY)
00232         ufoTypes[num++] = UFO_HARVESTER;
00233 
00234     return num;
00235 }
00236 
00241 void CP_InterceptNextStage (mission_t *mission)
00242 {
00243     switch (mission->stage) {
00244     case STAGE_NOT_ACTIVE:
00245         /* Create Intercept mission */
00246         CP_MissionBegin(mission);
00247         break;
00248     case STAGE_COME_FROM_ORBIT:
00249         /* UFO start looking for target */
00250         CP_InterceptMissionSet(mission);
00251         break;
00252     case STAGE_MISSION_GOTO:
00253         CP_InterceptAttackInstallation(mission);
00254         break;
00255     case STAGE_INTERCEPT:
00256         assert(mission->ufo);
00257         /* Leave earth */
00258         if (AIRFIGHT_ChooseWeapon(mission->ufo->weapons, mission->ufo->maxWeapons, mission->ufo->pos, mission->ufo->pos) !=
00259             AIRFIGHT_WEAPON_CAN_NEVER_SHOOT && mission->ufo->status == AIR_UFO && !mission->data) {
00260             /* UFO is fighting and has still ammo, wait a little bit before leaving (UFO is not attacking an installation) */
00261             const date_t AdditionalDelay = {0, 3600};   /* check every hour if there is still ammos */
00262             mission->finalDate = Date_Add(ccs.date, AdditionalDelay);
00263         } else
00264             CP_InterceptMissionLeave(mission, qtrue);
00265         break;
00266     case STAGE_RETURN_TO_ORBIT:
00267         /* mission is over, remove mission */
00268         CP_InterceptMissionIsSuccess(mission);
00269         break;
00270     default:
00271         Com_Printf("CP_InterceptNextStage: Unknown stage: %i, removing mission.\n", mission->stage);
00272         CP_MissionRemove(mission);
00273         break;
00274     }
00275 }

Generated by  doxygen 1.6.2