UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_radar.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, 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) */
39const float RADAR_BASERANGE = 24.0f;
40const float RADAR_BASETRACKINGRANGE = 34.0f;
41const float RADAR_INSTALLATIONLEVEL = 1.0f;
43static 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
80static 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 */
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
138static 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
150static 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
171static 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
195static 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
213void 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
239void 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
311void 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)
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}
Share stuff between the different cgame implementations.
#define REMOVE_ELEM(array, index, n)
Definition common.h:385
#define ERR_DROP
Definition common.h:211
bool AIR_IsAircraftOnGeoscape(const aircraft_t *aircraft)
Checks whether given aircraft is on geoscape.
#define AIR_Foreach(var)
iterates trough all aircraft
#define AIR_ForeachFromBase(var, base)
iterates trough all aircraft from a specific homebase
base_t * B_GetFoundedBaseByIDX(int baseIdx)
Array bound check for the base index.
Definition cp_base.cpp:326
base_t * B_GetNext(base_t *lastBase)
Iterates through founded bases.
Definition cp_base.cpp:286
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
#define MAX_BASES
Definition cp_base.h:32
@ B_RADAR
Definition cp_building.h:67
const int DETECTION_INTERVAL
delay between actions that must be executed independently of time scale
Header file for single player campaign control.
const cgame_import_t * cgi
void GEO_SetOverlay(const char *overlayID, int status)
Turn overlay on/off.
bool GEO_IsRadarOverlayActivated(void)
void GEO_UpdateGeoscapeDock(void)
Will add missions and UFOs to the geoscape dock panel.
Header for Geoscape management.
#define INS_Foreach(var)
@ INSTALLATION_WORKING
void CP_UpdateMissionVisibleOnGeoscape(void)
Update all mission visible on geoscape (in base radar range).
Campaign missions headers.
void CP_InitializeRadarOverlay(bool source)
Initialize radar overlay on geoscape.
void CP_UploadRadarCoverage(void)
Smooth radar coverage.
void CP_AddRadarCoverage(const vec2_t pos, float innerRadius, float outerRadius, bool source)
Add a radar coverage (base or aircraft) to radar overlay.
Functions to generate and render overlay for geoscape.
void RADAR_DeactivateRadarOverlay(void)
Deactivate Radar overlay if there is no more UFO on geoscape.
Definition cp_radar.cpp:106
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
static void RADAR_DrawCoverage(const radar_t *radar, const vec2_t pos)
Update map radar coverage with moving radar.
Definition cp_radar.cpp:80
void RADAR_UpdateWholeRadarOverlay(void)
Update radar overlay of base, installation and aircraft range.
Definition cp_radar.cpp:89
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
const float RADAR_BASETRACKINGRANGE
Definition cp_radar.cpp:40
const float RADAR_INSTALLATIONLEVEL
Definition cp_radar.cpp:41
const float RADAR_BASERANGE
Definition cp_radar.cpp:39
void RADAR_InitialiseUFOs(radar_t *radar)
Reset UFO sensored on radar.
Definition cp_radar.cpp:265
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't move: base and installation radar).
Definition cp_radar.cpp:49
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
bool RADAR_CheckRadarSensored(const vec2_t pos)
Check if the specified position is within base radar range.
Definition cp_radar.cpp:377
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
void RADAR_SetRadarAfterLoading(void)
Set radar to proper values after loading.
Definition cp_radar.cpp:453
bool radarOverlayWasSet
Definition cp_radar.cpp:36
static void RADAR_RemoveUFO(radar_t *radar, const aircraft_t *ufo)
UFO will no more be referenced by radar.
Definition cp_radar.cpp:171
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
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
void RADAR_AddDetectedUFOToEveryRadar(const aircraft_t *ufo)
Adds detected UFO to any radar in range (if not already detected).
Definition cp_radar.cpp:333
void RADAR_UpdateBaseRadarCoverage_f(void)
Update radar coverage when building/destroying new radar.
Definition cp_radar.cpp:277
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
#define MAX_UFOONGEOSCAPE
Definition cp_radar.h:27
aircraft_t * UFO_GetNext(aircraft_t *lastUFO)
Iterates through the UFOs.
Definition cp_ufo.cpp:41
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
float frand(void)
Return random values between 0 and 1.
Definition mathlib.cpp:506
QGL_EXTERN GLint i
Definition r_gl.h:113
#define OBJZERO(obj)
Definition shared.h:178
An aircraft with all it's data.
A base with all it's data.
Definition cp_base.h:84
struct radar_s radar
Definition cp_base.h:106
vec3_t pos
Definition cp_base.h:91
A installation with all it's data.
struct radar_s radar
const installationTemplate_t * installationTemplate
installationStatus_t installationStatus
vec_t vec2_t[2]
Definition ufotypes.h:38
static hudRadar_t radar
#define EQUAL(a, b)
Definition vector.h:37