1 /**
2 * @file
3 * @brief Campaign mission
4 */
5
6 /*
7 Copyright (C) 2002-2013 UFO: Alien Invasion.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18 See the GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 */
25
26 #include "../../../cl_shared.h"
27 #include "../cp_campaign.h"
28 #include "../cp_geoscape.h"
29 #include "../cp_ufo.h"
30 #include "../cp_missions.h"
31 #include "../cp_time.h"
32 #include "../cp_xvi.h"
33 #include "../cp_alien_interest.h"
34
35 /**
36 * @brief Harvesting mission is over and is a success: change interest values.
37 * @note Harvesting mission
38 */
CP_HarvestMissionIsSuccess(mission_t * mission)39 static void CP_HarvestMissionIsSuccess (mission_t* mission)
40 {
41 INT_ChangeIndividualInterest(-0.3f, INTERESTCATEGORY_HARVEST);
42 INT_ChangeIndividualInterest(0.2f, INTERESTCATEGORY_RECON);
43 INT_ChangeIndividualInterest(0.05f, INTERESTCATEGORY_BUILDING);
44 if (CP_IsXVIStarted())
45 INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_XVI);
46
47 CP_MissionRemove(mission);
48 }
49
50 /**
51 * @brief Harvesting mission is over and is a failure: change interest values.
52 * @note Harvesting mission
53 */
CP_HarvestMissionIsFailure(mission_t * mission)54 void CP_HarvestMissionIsFailure (mission_t* mission)
55 {
56 INT_ChangeIndividualInterest(0.1f, INTERESTCATEGORY_INTERCEPT);
57 INT_ChangeIndividualInterest(0.03f, INTERESTCATEGORY_BASE_ATTACK);
58 INT_ChangeIndividualInterest(0.03f, INTERESTCATEGORY_TERROR_ATTACK);
59
60 CP_MissionRemove(mission);
61 }
62
63 /**
64 * @brief Start Harvesting mission.
65 * @note Harvesting mission -- Stage 2
66 */
CP_HarvestMissionStart(mission_t * mission)67 static void CP_HarvestMissionStart (mission_t* mission)
68 {
69 const date_t minMissionDelay = {2, 0};
70 const date_t missionDelay = {3, 0};
71
72 mission->stage = STAGE_HARVEST;
73
74 if (mission->ufo) {
75 mission->finalDate = Date_Add(ccs.date, Date_Random(minMissionDelay, missionDelay));
76 /* ufo becomes invisible on geoscape, but don't remove it from ufo global array (may reappear)*/
77 CP_UFORemoveFromGeoscape(mission, false);
78 } else {
79 /* Go to next stage on next frame */
80 mission->finalDate = ccs.date;
81 }
82
83 /* mission appear on geoscape, player can go there */
84 CP_MissionAddToGeoscape(mission, false);
85 }
86
87 /**
88 * @brief Choose nation if needed for given mission.
89 * @param[in] mission Pointer to the mission we are creating.
90 * @param[out] nationList linkedList that will contain the name of the nation where the mission should take place.
91 * @note nationList should be empty if no nation should be favoured.
92 * @return True if nationList has been filled, false else.
93 */
CP_ChooseNation(const mission_t * mission,linkedList_t ** nationList)94 static bool CP_ChooseNation (const mission_t* mission, linkedList_t** nationList)
95 {
96 int randomNumber, max = 0;
97 /* Increase this factor to make probability to select non-infected nation higher
98 * Used to make sure that non-infected nation can still be attacked */
99 const int OFFSET = 1;
100 int i;
101
102 if (mission->ufo)
103 return false;
104
105 /* favour mission with higher XVI level */
106 for (i = 0; i < ccs.numNations; i++) {
107 const nation_t* nation = NAT_GetNationByIDX(i);
108 const nationInfo_t* stats = NAT_GetCurrentMonthInfo(nation);
109 max += OFFSET + stats->xviInfection;
110 }
111
112 randomNumber = (int) (frand() * (float) max);
113
114 /* Select the corresponding nation */
115 for (i = 0; i < ccs.numNations; i++) {
116 const nation_t* nation = NAT_GetNationByIDX(i);
117 const nationInfo_t* stats = NAT_GetCurrentMonthInfo(nation);
118 randomNumber -= OFFSET + stats->xviInfection;
119 if (randomNumber < 0) {
120 cgi->LIST_AddString(nationList, nation->id);
121 return true;
122 }
123 }
124
125 return false;
126 }
127
128 /**
129 * @brief Set Harvest mission, and go to mission pos.
130 * @note Harvesting attack mission -- Stage 1
131 * @todo Remove me when CP_XVIMissionGo will be implemented
132 * This function should take a location close to an XVI infection point
133 * see gameplay proposal on wiki
134 */
CP_HarvestMissionGo(mission_t * mission)135 void CP_HarvestMissionGo (mission_t* mission)
136 {
137 mission->stage = STAGE_MISSION_GOTO;
138
139 /* Choose a map */
140 if (CP_ChooseMap(mission, nullptr)) {
141 int counter;
142 linkedList_t* nationList = nullptr;
143 const bool nationTest = CP_ChooseNation(mission, &nationList);
144 for (counter = 0; counter < MAX_POS_LOOP; counter++) {
145 if (!CP_GetRandomPosOnGeoscapeWithParameters(mission->pos, mission->mapDef->terrains, mission->mapDef->cultures, mission->mapDef->populations, nationTest ? nationList : nullptr))
146 continue;
147 if (GEO_PositionCloseToBase(mission->pos))
148 continue;
149 mission->posAssigned = true;
150 break;
151 }
152 if (counter >= MAX_POS_LOOP) {
153 Com_Printf("CP_HarvestMissionGo: Error, could not set position.\n");
154 CP_MissionRemove(mission);
155 return;
156 }
157 cgi->LIST_Delete(&nationList);
158 } else {
159 Com_Printf("CP_HarvestMissionGo: No map found, remove mission.\n");
160 CP_MissionRemove(mission);
161 return;
162 }
163
164 if (mission->ufo) {
165 CP_MissionDisableTimeLimit(mission);
166 UFO_SendToDestination(mission->ufo, mission->pos);
167 } else {
168 /* Go to next stage on next frame */
169 mission->finalDate = ccs.date;
170 }
171 }
172
173 /**
174 * @brief Fill an array with available UFOs for Harvesting mission type.
175 * @param[in] mission Pointer to the mission we are currently creating.
176 * @param[out] ufoTypes Array of ufoType_t that may be used for this mission.
177 * @note Harvesting mission -- Stage 0
178 * @return number of elements written in @c ufoTypes
179 */
CP_HarvestMissionAvailableUFOs(const mission_t * mission,ufoType_t * ufoTypes)180 int CP_HarvestMissionAvailableUFOs (const mission_t* mission, ufoType_t* ufoTypes)
181 {
182 int num = 0;
183
184 if (UFO_ShouldAppearOnGeoscape(UFO_HARVESTER))
185 ufoTypes[num++] = UFO_HARVESTER;
186
187 return num;
188 }
189
190 /**
191 * @brief Determine what action should be performed when a Harvesting mission stage ends.
192 * @param[in] mission Pointer to the mission which stage ended.
193 */
CP_HarvestMissionNextStage(mission_t * mission)194 void CP_HarvestMissionNextStage (mission_t* mission)
195 {
196 switch (mission->stage) {
197 case STAGE_NOT_ACTIVE:
198 /* Create Harvesting mission */
199 CP_MissionBegin(mission);
200 break;
201 case STAGE_COME_FROM_ORBIT:
202 /* Go to mission */
203 CP_HarvestMissionGo(mission);
204 break;
205 case STAGE_MISSION_GOTO:
206 /* just arrived on a new Harvesting mission: start it */
207 CP_HarvestMissionStart(mission);
208 break;
209 case STAGE_HARVEST:
210 /* Leave earth */
211 CP_ReconMissionLeave(mission);
212 break;
213 case STAGE_RETURN_TO_ORBIT:
214 /* mission is over, remove mission */
215 CP_HarvestMissionIsSuccess(mission);
216 break;
217 default:
218 Com_Printf("CP_HarvestMissionNextStage: Unknown stage: %i, removing mission.\n", mission->stage);
219 CP_MissionRemove(mission);
220 break;
221 }
222 }
223