Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
CampaignPlanMission.cpp
Go to the documentation of this file.
1 /* Project Starshatter 4.5
2  Destroyer Studios LLC
3  Copyright © 1997-2006. All Rights Reserved.
4 
5  SUBSYSTEM: Stars.exe
6  FILE: CampaignPlanMission.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  CampaignPlanMission generates missions and mission
13  info for the player's combat group as part of a
14  dynamic campaign.
15 */
16 
17 #include "MemDebug.h"
18 #include "CampaignPlanMission.h"
19 #include "CampaignMissionRequest.h"
20 #include "CampaignMissionFighter.h"
22 #include "Campaign.h"
23 #include "Combatant.h"
24 #include "CombatAction.h"
25 #include "CombatAssignment.h"
26 #include "CombatGroup.h"
27 #include "CombatUnit.h"
28 #include "CombatZone.h"
29 #include "Mission.h"
30 #include "StarSystem.h"
31 #include "Random.h"
32 
33 
34 // +--------------------------------------------------------------------+
35 
36 void
38 {
39  if (campaign && campaign->IsActive()) {
41  if (!player_group) return;
42 
43  int missionCount = campaign->GetMissionList().size();
44 
45  if (missionCount > 0) {
46  // starships only get one mission to pick from:
48  return;
49 
50  // fighters get a maximum of five missions:
51  if (missionCount >= 5)
52  return;
53 
54  // otherwise, once every few seconds is plenty:
55  if (Campaign::Stardate() - exec_time < 1)
56  return;
57  }
58 
60 
62  slot++;
63  if (slot > 2) slot = 0;
64 
67  generator.CreateMission(request);
68  delete request;
69  }
70 
71  else if (player_group->IsStarshipGroup()) {
72  // starships should always check for campaign and strategic missions
73  slot = 0;
74 
77  generator.CreateMission(request);
78  delete request;
79  }
80 
82  }
83 }
84 
85 // +--------------------------------------------------------------------+
86 
87 void
89 {
90  const int HOUR = 3600; // 60 minutes
91  const int MISSION_DELAY = 1800; // 30 minutes
92  double base_time = 0;
93 
95 
96  if (info_list.size() > 0) {
97  MissionInfo* info = info_list[info_list.size()-1];
98  base_time = info->start;
99  }
100 
101  if (base_time == 0)
102  base_time = campaign->GetTime() + MISSION_DELAY;
103 
104  start = (int) base_time + MISSION_DELAY;
105  start -= start % MISSION_DELAY;
106 }
107 
108 // +--------------------------------------------------------------------+
109 
112 {
113  CampaignMissionRequest* request = 0;
114 
115  if (!request) request = PlanCampaignMission();
116  if (!request) request = PlanStrategicMission();
117  if (!request) request = PlanRandomStarshipMission();
118 
119  return request;
120 }
121 
122 // +--------------------------------------------------------------------+
123 
126 {
127  CampaignMissionRequest* request = 0;
128 
129  if (!request) request = PlanCampaignMission();
130  if (!request) request = PlanStrategicMission();
131  if (!request) request = PlanRandomFighterMission();
132 
133  return request;
134 }
135 
136 // +--------------------------------------------------------------------+
137 
140 {
141  CampaignMissionRequest* request = 0;
142 
144  while (++iter && !request) {
145  CombatAction* action = iter.value();
146 
147  if (action->Type() != CombatAction::MISSION_TEMPLATE)
148  continue;
149 
150  if (action->IsAvailable()) {
151 
152  // only fire each action once every two hours:
153  if (action->ExecTime() > 0 && campaign->GetTime() - action->ExecTime() < 7200)
154  continue;
155 
156  CombatGroup* g = campaign->FindGroup(action->GetIFF(),
157  action->AssetType(),
158  action->AssetId());
159 
160  if (g && (g == player_group ||
162  player_group->FindGroup(g->Type(), g->GetID())))) {
163 
164  request = new(__FILE__,__LINE__)
166  action->Subtype(),
167  start,
168  g);
169 
170  if (request) {
171  request->SetOpposingType(action->OpposingType());
172  request->SetScript(action->GetText());
173  }
174 
175  action->FireAction();
176  }
177  }
178  }
179 
180  return request;
181 }
182 
183 // +--------------------------------------------------------------------+
184 
187 {
188  CampaignMissionRequest* request = 0;
189 
190  if (slot > 1)
191  return request;
192 
193  // build list of assignments:
194  List<CombatAssignment> assignments;
195  assignments.append(player_group->GetAssignments());
196 
197  if (player_group->Type() == CombatGroup::WING) {
199  while (++iter) {
200  CombatGroup* g = iter.value();
201  assignments.append(g->GetAssignments());
202  }
203  }
204 
205  // pick next assignment as basis for mission:
206  static int assignment_index = 0;
207 
208  if (assignments.size()) {
209  if (assignment_index >= assignments.size())
210  assignment_index = 0;
211 
212  CombatAssignment* a = assignments[assignment_index++];
213 
214  request = new(__FILE__,__LINE__)
216  a->Type(),
217  start,
218  a->GetResource());
219 
220  if (request)
221  request->SetObjective(a->GetObjective());
222  }
223 
224  return request;
225 }
226 
227 // +--------------------------------------------------------------------+
228 
229 static int mission_type_index = -1;
230 static int mission_types[16] = {
246  Mission::PATROL
247 };
248 
249 // +--------------------------------------------------------------------+
250 
253 {
254  int type = Mission::PATROL;
255  int r = RandomIndex();
256  int ownside = player_group->GetIFF();
257 
258  if (mission_type_index < 0)
259  mission_type_index = r;
260 
261  else if (mission_type_index >= 16)
262  mission_type_index = 0;
263 
264  type = mission_types[mission_type_index++];
265 
266  if (type == Mission::ESCORT_FREIGHT) {
267  CombatGroup* freight = campaign->FindGroup(ownside, CombatGroup::FREIGHT);
268  if (!freight || freight->CountUnits() < 1)
269  type = Mission::PATROL;
270  }
271 
272  CampaignMissionRequest* request = 0;
273  request = new(__FILE__,__LINE__)
275 
276  return request;
277 }
278 
279 // +--------------------------------------------------------------------+
280 
281 static int fighter_mission_index = 0;
282 static int fighter_mission_types[16] = {
298  Mission::AIR_SWEEP
299 };
300 
303 {
304  CampaignMissionRequest* request = 0;
305  int type = fighter_mission_types[fighter_mission_index++];
306  int ownside = player_group->GetIFF();
307  CombatGroup* primary = player_group;
308  CombatGroup* obj = 0;
309 
310  if (fighter_mission_index > 15)
311  fighter_mission_index = 0;
312 
313  if (type == Mission::ESCORT_FREIGHT) {
314  CombatGroup* freight = campaign->FindGroup(ownside, CombatGroup::FREIGHT);
315  if (!freight || freight->CalcValue() < 1)
316  type = Mission::PATROL;
317  else
318  obj = freight;
319  }
320 
321  else if (type == Mission::ESCORT_SHUTTLE) {
323  if (!shuttle || shuttle->CalcValue() < 1)
324  type = Mission::PATROL;
325  else
326  obj = shuttle;
327  }
328 
329  else if (primary->Type() == CombatGroup::WING) {
330  if (RandomChance())
331  primary = primary->FindGroup(CombatGroup::INTERCEPT_SQUADRON);
332  else
333  primary = primary->FindGroup(CombatGroup::FIGHTER_SQUADRON);
334  }
335 
336  if (type >= Mission::AIR_PATROL && type <= Mission::AIR_INTERCEPT) {
337  CombatZone* zone = 0;
338  bool airborne = false;
339 
340  if (primary)
341  zone = primary->GetAssignedZone();
342 
343  if (zone && zone->GetRegions().size() > 1) {
344  Text air_region = *zone->GetRegions().at(1);
345  StarSystem* system = campaign->GetSystem(zone->System());
346 
347  if (system) {
348  OrbitalRegion* rgn = system->FindRegion(air_region);
349 
350  if (rgn && rgn->Type() == Orbital::TERRAIN)
351  airborne = true;
352  }
353  }
354 
355  if (!airborne) {
356  if (type == Mission::AIR_INTERCEPT)
357  type = Mission::INTERCEPT;
358 
359  else if (type == Mission::AIR_SWEEP)
360  type = Mission::SWEEP;
361 
362  else
363  type = Mission::PATROL;
364  }
365  }
366 
367  request = new(__FILE__,__LINE__)
368  CampaignMissionRequest(campaign, type, start, primary);
369 
370  if (request)
371  request->SetObjective(obj);
372 
373  return request;
374 }