UFO: Alien Invasion
cp_radar.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2022 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 #include "../../cl_shared.h"
26 #include "cp_campaign.h"
27 #include "cp_overlay.h"
28 #include "cp_geoscape.h"
29 #include "cp_ufo.h"
30 #include "cp_missions.h"
31 
37 
38 /* Define base radar range (can be modified by level of the radar) */
39 const float RADAR_BASERANGE = 24.0f;
40 const float RADAR_BASETRACKINGRANGE = 34.0f;
41 const float RADAR_INSTALLATIONLEVEL = 1.0f;
43 static const float RADAR_UPGRADE_MULTIPLIER = 0.4f;
44 
50 {
51  base_t* base;
52 
53  /* Initialise radar range (will be filled below) */
55 
56  /* Add base radar coverage */
57  base = nullptr;
58  while ((base = B_GetNext(base)) != nullptr) {
59  if (base->radar.range) {
60  CP_AddRadarCoverage(base->pos, base->radar.range, base->radar.trackingRange, true);
61  }
62  }
63 
64  /* Add installation coverage */
65  INS_Foreach(installation) {
66  if (installation->installationStatus == INSTALLATION_WORKING && installation->radar.range)
67  CP_AddRadarCoverage(installation->pos, installation->radar.range, installation->radar.trackingRange, true);
68  }
69 
70  /* Smooth and bind radar overlay without aircraft (in case no aircraft is on geoscape:
71  * RADAR_UpdateWholeRadarOverlay won't be called) */
74 }
75 
80 static inline void RADAR_DrawCoverage (const radar_t* radar, const vec2_t pos)
81 {
82  if (radar && radar->range)
83  CP_AddRadarCoverage(pos, radar->range, radar->trackingRange, false);
84 }
85 
90 {
91  /* Copy Base and installation radar overlay*/
93 
94  /* Add aircraft radar coverage */
95  AIR_Foreach(aircraft) {
96  if (AIR_IsAircraftOnGeoscape(aircraft))
97  RADAR_DrawCoverage(&aircraft->radar, aircraft->pos);
98  }
99 
101 }
102 
107 {
108  base_t* base;
109 
110  /* never deactivate radar if player wants it to be always turned on */
111  if (radarOverlayWasSet)
112  return;
113 
114  AIR_Foreach(aircraft) {
116  if (aircraft->radar.numUFOs)
117  return;
118  }
119 
120  base = nullptr;
121  while ((base = B_GetNext(base)) != nullptr) {
122  if (base->radar.numUFOs)
123  return;
124  }
125 
126  INS_Foreach(installation) {
127  if (installation->radar.numUFOs)
128  return;
129  }
130 
132  GEO_SetOverlay("radar", 0);
133 }
134 
138 static bool RADAR_IsUFOSensored (const radar_t* radar, const aircraft_t* ufo)
139 {
140  for (int i = 0; i < radar->numUFOs; i++)
141  if (radar->ufos[i] == ufo)
142  return true;
143 
144  return false;
145 }
146 
150 static bool RADAR_AddUFO (radar_t* radar, const aircraft_t* ufo)
151 {
152 #ifdef DEBUG
153  if (RADAR_IsUFOSensored(radar, ufo)) {
154  cgi->Com_Printf("RADAR_AddUFO: Aircraft already in radar range\n");
155  return false;
156  }
157 #endif
158 
159  if (radar->numUFOs >= MAX_UFOONGEOSCAPE)
160  return false;
161 
162  radar->ufos[radar->numUFOs] = ufo;
163  radar->numUFOs++;
164 
165  return true;
166 }
167 
171 static void RADAR_RemoveUFO (radar_t* radar, const aircraft_t* ufo)
172 {
173  int i;
174 
175  assert(radar->numUFOs < MAX_UFOONGEOSCAPE && radar->numUFOs > 0);
176 
177  for (i = 0; i < radar->numUFOs; i++)
178  if (radar->ufos[i] == ufo)
179  break;
180 
181  if (i == radar->numUFOs)
182  return;
183 
184  REMOVE_ELEM(radar->ufos, i, radar->numUFOs);
185 
187 }
188 
195 static void RADAR_NotifyUFORemovedFromOneRadar (radar_t* radar, const aircraft_t* ufo, bool destroyed)
196 {
197  for (int i = 0; i < radar->numUFOs; i++)
198  if (radar->ufos[i] == ufo) {
199  radar->numUFOs--;
200  radar->ufos[i] = radar->ufos[radar->numUFOs];
201  i--; /* Allow the moved value to be checked */
202  } else if (destroyed && (radar->ufos[i] > ufo))
203  radar->ufos[i]--;
204 
206 }
207 
213 void RADAR_NotifyUFORemoved (const aircraft_t* ufo, bool destroyed)
214 {
215  base_t* base;
216 
217  base = nullptr;
218  while ((base = B_GetNext(base)) != nullptr) {
219  RADAR_NotifyUFORemovedFromOneRadar(&base->radar, ufo, destroyed);
220 
221  AIR_ForeachFromBase(aircraft, base)
222  RADAR_NotifyUFORemovedFromOneRadar(&aircraft->radar, ufo, destroyed);
223  }
224 
225  INS_Foreach(installation) {
226  if (installation->installationStatus == INSTALLATION_WORKING)
227  RADAR_NotifyUFORemovedFromOneRadar(&installation->radar, ufo, destroyed);
228  }
229 }
230 
239 void RADAR_Initialise (radar_t* radar, float range, float trackingRange, float level, bool updateSourceRadarMap)
240 {
241  const int oldrange = radar->range;
242 
243  if (EQUAL(level, 0.0)) {
244  radar->range = 0.0f;
245  radar->trackingRange = 0.0f;
246  } else {
247  radar->range = range * (1 + (level - 1) * RADAR_UPGRADE_MULTIPLIER);
248  radar->trackingRange = trackingRange * (1 + (level - 1) * RADAR_UPGRADE_MULTIPLIER);
249  }
250 
251  radar->ufoDetectionProbability = 0.000125f * DETECTION_INTERVAL;
252 
253  assert(radar->numUFOs >= 0);
254 
255  if (updateSourceRadarMap && !EQUAL(radar->range, oldrange)) {
258  }
259 }
260 
266 {
267  radar->numUFOs = 0;
268  OBJZERO(radar->ufos);
269 }
270 
278 {
279  int baseIdx;
280  base_t* base;
281  float level;
282 
283  if (cgi->Cmd_Argc() < 2) {
284  cgi->Com_Printf("Usage: %s <baseIdx> <buildingType>\n", cgi->Cmd_Argv(0));
285  return;
286  }
287 
288  baseIdx = atoi(cgi->Cmd_Argv(1));
289 
290  if (baseIdx < 0 || baseIdx >= MAX_BASES) {
291  cgi->Com_Printf("RADAR_UpdateBaseRadarCoverage_f: %i is outside bounds\n", baseIdx);
292  return;
293  }
294 
295  base = B_GetFoundedBaseByIDX(baseIdx);
296 
297  if (!base)
298  return;
299 
303 }
304 
311 void RADAR_UpdateInstallationRadarCoverage (installation_t* installation, const float radarRange, const float trackingRadarRange)
312 {
313  /* Sanity check */
314  if (!installation || !installation->installationTemplate)
315  cgi->Com_Error(ERR_DROP, "RADAR_UpdateInstallationRadarCoverage: No installation or no template!\n");
316 
317  /* Do nothing if installation not finished */
318  if (installation->installationStatus != INSTALLATION_WORKING)
319  return;
320  /* Do nothing if this isn't a RadarTower */
321  if (installation->installationTemplate->radarRange <= 0
322  || installation->installationTemplate->trackingRange <= 0)
323  return;
324 
325  RADAR_Initialise(&installation->radar, radarRange, trackingRadarRange, RADAR_INSTALLATIONLEVEL, true);
327 }
328 
334 {
335  base_t* base = nullptr;
336 
337  AIR_Foreach(aircraft) {
338  if (!AIR_IsAircraftOnGeoscape(aircraft))
339  continue;
340 
341  if (!RADAR_IsUFOSensored(&aircraft->radar, ufo)) {
342  /* Distance from radar to UFO */
343  const float dist = GetDistanceOnGlobe(ufo->pos, aircraft->pos);
344  if (dist <= aircraft->radar.trackingRange)
345  RADAR_AddUFO(&aircraft->radar, ufo);
346  }
347  }
348 
349  while ((base = B_GetNext(base)) != nullptr) {
350  if (!RADAR_IsUFOSensored(&base->radar, ufo)) {
351  /* Distance from radar to UFO */
352  const float dist = GetDistanceOnGlobe(ufo->pos, base->pos);
353  if (dist <= base->radar.trackingRange)
354  RADAR_AddUFO(&base->radar, ufo);
355  }
356  }
357 
358  INS_Foreach(installation) {
359  /* No need to check installations without radar */
360  if (!installation->radar.trackingRange)
361  continue;
362 
363  if (!RADAR_IsUFOSensored(&installation->radar, ufo)) {
364  /* Distance from radar to UFO */
365  const float dist = GetDistanceOnGlobe(ufo->pos, installation->pos);
366  if (dist <= ufo->radar.trackingRange)
367  RADAR_AddUFO(&installation->radar, ufo);
368  }
369  }
370 }
371 
378 {
379  base_t* base = nullptr;
380 
381  while ((base = B_GetNext(base)) != nullptr) {
382  const float dist = GetDistanceOnGlobe(pos, base->pos); /* Distance from base to position */
383  if (dist <= base->radar.range)
384  return true;
385  }
386 
387  INS_Foreach(installation) {
388  float dist;
389 
390  dist = GetDistanceOnGlobe(pos, installation->pos); /* Distance from base to position */
391  if (dist <= installation->radar.range)
392  return true;
393  }
394 
395  return false;
396 }
397 
409  const aircraft_t* ufo, bool detected)
410 {
411  int dist;
412  bool ufoIsSensored;
413 
414  /* indice of ufo in radar list */
415  ufoIsSensored = RADAR_IsUFOSensored(radar, ufo);
416  /* Distance from radar to ufo */
417  dist = GetDistanceOnGlobe(posRadar, ufo->pos);
418 
419  if ((detected ? radar->trackingRange : radar->range) > dist) {
420  if (detected) {
421  if (!ufoIsSensored) {
422  /* UFO was not sensored by this radar, but by another one
423  * (it just entered this radar zone) */
424  RADAR_AddUFO(radar, ufo);
425  }
426  return true;
427  } else {
428  /* UFO is sensored by no radar, so it shouldn't be sensored
429  * by this radar */
430  assert(ufoIsSensored == false);
431  /* Check if UFO is detected */
432  if (frand() <= radar->ufoDetectionProbability) {
434  return true;
435  }
436  return false;
437  }
438  }
439 
440  /* UFO is not in this sensor range any more (but maybe
441  * in the range of another radar) */
442  if (ufoIsSensored)
443  RADAR_RemoveUFO(radar, ufo);
444 
445  return false;
446 }
447 
454 {
455  aircraft_t* ufo;
456 
457  ufo = nullptr;
458  while ((ufo = UFO_GetNext(ufo)) != nullptr) {
459  if (!ufo->detected)
460  continue;
461 
463  }
464 
466 }
void GEO_UpdateGeoscapeDock(void)
Will add missions and UFOs to the geoscape dock panel.
void RADAR_SetRadarAfterLoading(void)
Set radar to proper values after loading.
Definition: cp_radar.cpp:453
const float RADAR_BASERANGE
Definition: cp_radar.cpp:39
#define MAX_UFOONGEOSCAPE
Definition: cp_radar.h:27
void RADAR_Initialise(radar_t *radar, float range, float trackingRange, float level, bool updateSourceRadarMap)
Set radar range to new value.
Definition: cp_radar.cpp:239
A base with all it&#39;s data.
Definition: cp_base.h:84
static void RADAR_DrawCoverage(const radar_t *radar, const vec2_t pos)
Update map radar coverage with moving radar.
Definition: cp_radar.cpp:80
aircraft_t * UFO_GetNext(aircraft_t *lastUFO)
Iterates through the UFOs.
Definition: cp_ufo.cpp:41
float B_GetMaxBuildingLevel(const base_t *base, const buildingType_t type)
Get the maximum level of a building type in a base.
Definition: cp_base.cpp:519
void CP_InitializeRadarOverlay(bool source)
Initialize radar overlay on geoscape.
Definition: cp_overlay.cpp:292
installationStatus_t installationStatus
#define EQUAL(a, b)
Definition: vector.h:37
static const float RADAR_UPGRADE_MULTIPLIER
this is the multiplier applied to the radar range when the radar levels up
Definition: cp_radar.cpp:43
const float RADAR_BASETRACKINGRANGE
Definition: cp_radar.cpp:40
void CP_UploadRadarCoverage(void)
Smooth radar coverage.
Definition: cp_overlay.cpp:422
bool GEO_IsRadarOverlayActivated(void)
Definition: cp_geoscape.cpp:85
const char *IMPORT * Cmd_Argv(int n)
void RADAR_UpdateInstallationRadarCoverage(installation_t *installation, const float radarRange, const float trackingRadarRange)
Update radar coverage when building/destroying new radar.
Definition: cp_radar.cpp:311
A installation with all it&#39;s data.
bool RADAR_CheckRadarSensored(const vec2_t pos)
Check if the specified position is within base radar range.
Definition: cp_radar.cpp:377
base_t * B_GetFoundedBaseByIDX(int baseIdx)
Array bound check for the base index.
Definition: cp_base.cpp:326
bool radarOverlayWasSet
Definition: cp_radar.cpp:36
#define INS_Foreach(var)
Functions to generate and render overlay for geoscape.
void RADAR_InitialiseUFOs(radar_t *radar)
Reset UFO sensored on radar.
Definition: cp_radar.cpp:265
#define REMOVE_ELEM(array, index, n)
Definition: common.h:384
struct radar_s radar
Definition: cp_base.h:106
#define ERR_DROP
Definition: common.h:211
#define OBJZERO(obj)
Definition: shared.h:178
static void RADAR_NotifyUFORemovedFromOneRadar(radar_t *radar, const aircraft_t *ufo, bool destroyed)
Notify that the specified ufo has been removed from geoscape to one radar.
Definition: cp_radar.cpp:195
static bool RADAR_AddUFO(radar_t *radar, const aircraft_t *ufo)
Add a UFO in the list of sensored UFOs.
Definition: cp_radar.cpp:150
Campaign missions headers.
base_t * B_GetNext(base_t *lastBase)
Iterates through founded bases.
Definition: cp_base.cpp:286
const cgame_import_t * cgi
void RADAR_NotifyUFORemoved(const aircraft_t *ufo, bool destroyed)
Notify to every radar that the specified ufo has been removed from geoscape.
Definition: cp_radar.cpp:213
void RADAR_UpdateStaticRadarCoverage(void)
Update every static radar drawing (radar that don&#39;t move: base and installation radar).
Definition: cp_radar.cpp:49
vec3_t pos
Definition: cp_aircraft.h:132
Header for Geoscape management.
void CP_UpdateMissionVisibleOnGeoscape(void)
Update all mission visible on geoscape (in base radar range).
bool AIR_IsAircraftOnGeoscape(const aircraft_t *aircraft)
Checks whether given aircraft is on geoscape.
void RADAR_UpdateBaseRadarCoverage_f(void)
Update radar coverage when building/destroying new radar.
Definition: cp_radar.cpp:277
#define AIR_ForeachFromBase(var, base)
iterates trough all aircraft from a specific homebase
Definition: cp_aircraft.h:202
static void RADAR_RemoveUFO(radar_t *radar, const aircraft_t *ufo)
UFO will no more be referenced by radar.
Definition: cp_radar.cpp:171
An aircraft with all it&#39;s data.
Definition: cp_aircraft.h:115
float frand(void)
Return random values between 0 and 1.
Definition: mathlib.cpp:506
void CP_AddRadarCoverage(const vec2_t pos, float innerRadius, float outerRadius, bool source)
Add a radar coverage (base or aircraft) to radar overlay.
Definition: cp_overlay.cpp:367
QGL_EXTERN GLint i
Definition: r_gl.h:113
static hudRadar_t radar
void RADAR_AddDetectedUFOToEveryRadar(const aircraft_t *ufo)
Adds detected UFO to any radar in range (if not already detected).
Definition: cp_radar.cpp:333
bool RADAR_CheckUFOSensored(radar_t *radar, const vec2_t posRadar, const aircraft_t *ufo, bool detected)
Check if the specified UFO is inside the sensor range of the given radar.
Definition: cp_radar.cpp:408
const int DETECTION_INTERVAL
delay between actions that must be executed independently of time scale
Definition: cp_campaign.cpp:75
vec_t vec2_t[2]
Definition: ufotypes.h:38
Header file for single player campaign control.
void RADAR_UpdateWholeRadarOverlay(void)
Update radar overlay of base, installation and aircraft range.
Definition: cp_radar.cpp:89
static bool RADAR_IsUFOSensored(const radar_t *radar, const aircraft_t *ufo)
Check if UFO is in the sensored list.
Definition: cp_radar.cpp:138
struct radar_s radar
#define AIR_Foreach(var)
iterates trough all aircraft
Definition: cp_aircraft.h:193
const float RADAR_INSTALLATIONLEVEL
Definition: cp_radar.cpp:41
#define MAX_BASES
Definition: cp_base.h:32
void GEO_SetOverlay(const char *overlayID, int status)
Turn overlay on/off.
vec3_t pos
Definition: cp_base.h:91
const installationTemplate_t * installationTemplate
level_locals_t level
Definition: g_main.cpp:38
double GetDistanceOnGlobe(const vec2_t pos1, const vec2_t pos2)
Calculate distance on the geoscape.
Definition: mathlib.cpp:171
void RADAR_DeactivateRadarOverlay(void)
Deactivate Radar overlay if there is no more UFO on geoscape.
Definition: cp_radar.cpp:106
bool detected
Definition: cp_aircraft.h:167