00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "../cl_shared.h"
00027 #include "../cl_renderer.h"
00028 #include "../renderer/r_image.h"
00029 #include "../renderer/r_draw.h"
00030 #include "../ui/ui_nodes.h"
00031 #include "cp_campaign.h"
00032 #include "cp_overlay.h"
00033 #include "cp_map.h"
00034 #include "cp_ufo.h"
00035
00040 qboolean radarOverlayWasSet;
00041
00042
00043 const float RADAR_BASERANGE = 24.0f;
00044 const float RADAR_BASETRACKINGRANGE = 34.0f;
00045 const float RADAR_AIRCRAFTRANGE = 10.0f;
00046 const float RADAR_AIRCRAFTTRACKINGRANGE = 14.0f;
00047 const float RADAR_INSTALLATIONLEVEL = 1.0f;
00049 static const float RADAR_UPGRADE_MULTIPLIER = 0.4f;
00050
00055 void RADAR_UpdateStaticRadarCoverage (void)
00056 {
00057 int baseIdx, installationIdx;
00058
00059
00060 CP_InitializeRadarOverlay(qtrue);
00061
00062
00063 for (baseIdx = 0; baseIdx < MAX_BASES; baseIdx++) {
00064 const base_t const *base = B_GetFoundedBaseByIDX(baseIdx);
00065 if (base && base->radar.range) {
00066 CP_AddRadarCoverage(base->pos, base->radar.range, base->radar.trackingRange, qtrue);
00067 }
00068 }
00069
00070
00071 for (installationIdx = 0; installationIdx < MAX_INSTALLATIONS; installationIdx++) {
00072 const installation_t const *installation = INS_GetFoundedInstallationByIDX(installationIdx);
00073 if (installation && installation->founded &&
00074 installation->installationStatus == INSTALLATION_WORKING && installation->radar.range) {
00075 CP_AddRadarCoverage(installation->pos, installation->radar.range, installation->radar.trackingRange, qtrue);
00076 }
00077 }
00078
00079
00080
00081 CP_InitializeRadarOverlay(qfalse);
00082 CP_UploadRadarCoverage();
00083 }
00084
00089 static inline void RADAR_DrawCoverage (const radar_t* radar, const vec2_t pos)
00090 {
00091 CP_AddRadarCoverage(pos, radar->range, radar->trackingRange, qfalse);
00092 }
00093
00097 void RADAR_UpdateWholeRadarOverlay (void)
00098 {
00099 int baseIdx;
00100
00101
00102 CP_InitializeRadarOverlay(qfalse);
00103
00104
00105 for (baseIdx = 0; baseIdx < MAX_BASES; baseIdx++) {
00106 base_t *base = B_GetFoundedBaseByIDX(baseIdx);
00107 aircraft_t *aircraft;
00108
00109 aircraft = NULL;
00110 while ((aircraft = AIR_GetNextFromBase(base, aircraft)) != NULL) {
00111 if (AIR_IsAircraftOnGeoscape(aircraft))
00112 RADAR_DrawCoverage(&aircraft->radar, aircraft->pos);
00113 }
00114 }
00115
00116 CP_UploadRadarCoverage();
00117 }
00118
00126 static void RADAR_DrawLineCoverage (const uiNode_t* node, const radar_t* radar, const vec2_t pos)
00127 {
00128 const vec4_t color = {1., 1., 1., .4};
00129 MAP_MapDrawEquidistantPoints(node, pos, radar->range, color);
00130 MAP_MapDrawEquidistantPoints(node, pos, radar->trackingRange, color);
00131 }
00132
00139 void RADAR_DrawInMap (const uiNode_t *node, const radar_t *radar, const vec2_t pos)
00140 {
00141 int x, y;
00142 const vec4_t color = {1., 1., 1., .3};
00143 qboolean display;
00144
00145
00146 RADAR_DrawLineCoverage(node, radar, pos);
00147
00148
00149 if (!radar->numUFOs)
00150 return;
00151
00152
00153 R_Color(color);
00154
00155
00156 display = MAP_AllMapToScreen(node, pos, &x, &y, NULL);
00157 if (display) {
00158 int i;
00159 screenPoint_t pts[2];
00160
00161 pts[0].x = x;
00162 pts[0].y = y;
00163
00164 for (i = 0; i < radar->numUFOs; i++) {
00165 const aircraft_t *ufo = radar->ufos[i];
00166 if (UFO_IsUFOSeenOnGeoscape(ufo) && MAP_AllMapToScreen(node, ufo->pos, &x, &y, NULL)) {
00167 pts[1].x = x;
00168 pts[1].y = y;
00169 R_DrawLineStrip(2, (int*)pts);
00170 }
00171 }
00172 }
00173
00174 R_Color(NULL);
00175 }
00176
00180 void RADAR_DeactivateRadarOverlay (void)
00181 {
00182 int idx;
00183
00184
00185 if (radarOverlayWasSet)
00186 return;
00187
00188 for (idx = 0; idx < MAX_BASES; idx++) {
00189 base_t *base = B_GetFoundedBaseByIDX(idx);
00190 aircraft_t *aircraft;
00191 if (!base)
00192 continue;
00193
00194 if (base->radar.numUFOs)
00195 return;
00196
00197 aircraft = NULL;
00198 while ((aircraft = AIR_GetNextFromBase(base, aircraft)) != NULL)
00199 if (aircraft->radar.numUFOs)
00200 return;
00201 }
00202
00203 for (idx = 0; idx < MAX_INSTALLATIONS; idx++) {
00204 const installation_t const *installation = INS_GetFoundedInstallationByIDX(idx);
00205 if (!installation)
00206 continue;
00207
00208 if (installation->radar.numUFOs)
00209 return;
00210 }
00211
00212 if (MAP_IsRadarOverlayActivated())
00213 MAP_SetOverlay("radar");
00214 }
00215
00219 static qboolean RADAR_IsUFOSensored (const radar_t* radar, const aircraft_t* ufo)
00220 {
00221 int i;
00222
00223 for (i = 0; i < radar->numUFOs; i++)
00224 if (radar->ufos[i] == ufo)
00225 return qtrue;
00226
00227 return qfalse;
00228 }
00229
00233 static qboolean RADAR_AddUFO (radar_t* radar, const aircraft_t* ufo)
00234 {
00235 #ifdef DEBUG
00236 if (RADAR_IsUFOSensored(radar, ufo)) {
00237 Com_Printf("RADAR_AddUFO: Aircraft already in radar range\n");
00238 return qfalse;
00239 }
00240 #endif
00241
00242 if (radar->numUFOs >= MAX_UFOONGEOSCAPE)
00243 return qfalse;
00244
00245 radar->ufos[radar->numUFOs] = ufo;
00246 radar->numUFOs++;
00247
00248 return qtrue;
00249 }
00250
00254 static void RADAR_RemoveUFO (radar_t* radar, const aircraft_t* ufo)
00255 {
00256 int i;
00257
00258 assert(radar->numUFOs < MAX_UFOONGEOSCAPE && radar->numUFOs > 0);
00259
00260 for (i = 0; i < radar->numUFOs; i++)
00261 if (radar->ufos[i] == ufo)
00262 break;
00263
00264 if (i == radar->numUFOs)
00265 return;
00266
00267 REMOVE_ELEM(radar->ufos, i, radar->numUFOs);
00268
00269 RADAR_DeactivateRadarOverlay();
00270 }
00271
00278 static void RADAR_NotifyUFORemovedFromOneRadar (radar_t* radar, const aircraft_t* ufo, qboolean destroyed)
00279 {
00280 int i;
00281
00282 for (i = 0; i < radar->numUFOs; i++)
00283 if (radar->ufos[i] == ufo) {
00284 radar->numUFOs--;
00285 radar->ufos[i] = radar->ufos[radar->numUFOs];
00286 i--;
00287 } else if (destroyed && (radar->ufos[i] > ufo))
00288 radar->ufos[i]--;
00289
00290 RADAR_DeactivateRadarOverlay();
00291 }
00292
00298 void RADAR_NotifyUFORemoved (const aircraft_t* ufo, qboolean destroyed)
00299 {
00300 int baseIdx;
00301 int installationIdx;
00302
00303 for (baseIdx = 0; baseIdx < MAX_BASES; baseIdx++) {
00304 base_t *base = B_GetFoundedBaseByIDX(baseIdx);
00305 aircraft_t *aircraft;
00306 if (!base)
00307 continue;
00308
00309 RADAR_NotifyUFORemovedFromOneRadar(&base->radar, ufo, destroyed);
00310
00311 aircraft = NULL;
00312 while ((aircraft = AIR_GetNextFromBase(base, aircraft)) != NULL)
00313 RADAR_NotifyUFORemovedFromOneRadar(&aircraft->radar, ufo, destroyed);
00314 }
00315
00316 for (installationIdx = 0; installationIdx < MAX_INSTALLATIONS; installationIdx++) {
00317 installation_t *installation = INS_GetFoundedInstallationByIDX(installationIdx);
00318 if (installation && installation->founded && installation->installationStatus == INSTALLATION_WORKING) {
00319 RADAR_NotifyUFORemovedFromOneRadar(&installation->radar, ufo, destroyed);
00320 }
00321 }
00322 }
00323
00332 void RADAR_Initialise (radar_t *radar, float range, float trackingRange, float level, qboolean updateSourceRadarMap)
00333 {
00334 const int oldrange = radar->range;
00335
00336 if (!level) {
00337 radar->range = 0.0f;
00338 radar->trackingRange = 0.0f;
00339 } else {
00340 radar->range = range * (1 + (level - 1) * RADAR_UPGRADE_MULTIPLIER);
00341 radar->trackingRange = trackingRange * (1 + (level - 1) * RADAR_UPGRADE_MULTIPLIER);
00342 }
00343
00344 assert(radar->numUFOs >= 0);
00345
00346 if (updateSourceRadarMap && !equal(radar->range, oldrange)) {
00347 RADAR_UpdateStaticRadarCoverage();
00348 RADAR_UpdateWholeRadarOverlay();
00349 }
00350 }
00351
00356 void RADAR_InitialiseUFOs (radar_t *radar)
00357 {
00358 radar->numUFOs = 0;
00359 memset(radar->ufos, 0, sizeof(radar->ufos));
00360 }
00361
00368 void RADAR_UpdateBaseRadarCoverage_f (void)
00369 {
00370 int baseIdx;
00371 base_t *base;
00372 float level;
00373
00374 if (Cmd_Argc() < 2) {
00375 Com_Printf("Usage: %s <baseIdx> <buildingType>\n", Cmd_Argv(0));
00376 return;
00377 }
00378
00379 baseIdx = atoi(Cmd_Argv(1));
00380
00381 if (baseIdx < 0 || baseIdx >= MAX_BASES) {
00382 Com_Printf("RADAR_UpdateBaseRadarCoverage_f: %i is outside bounds\n", baseIdx);
00383 return;
00384 }
00385
00386 base = B_GetFoundedBaseByIDX(baseIdx);
00387
00388 if (!base)
00389 return;
00390
00391 level = B_GetMaxBuildingLevel(base, B_RADAR);
00392 RADAR_Initialise(&base->radar, RADAR_BASERANGE, RADAR_BASETRACKINGRANGE, level, qtrue);
00393 CP_UpdateMissionVisibleOnGeoscape();
00394 }
00395
00402 void RADAR_UpdateInstallationRadarCoverage (installation_t *installation, const float radarRange, const float trackingRadarRange)
00403 {
00404
00405 if (!installation || !installation->installationTemplate)
00406 Com_Error(ERR_DROP, "RADAR_UpdateInstallationRadarCoverage: No installation or no template!\n");
00407
00408
00409 if (!installation->founded)
00410 return;
00411
00412 if (installation->installationStatus != INSTALLATION_WORKING)
00413 return;
00414
00415 if (installation->installationTemplate->radarRange <= 0
00416 || installation->installationTemplate->trackingRange <= 0)
00417 return;
00418
00419 RADAR_Initialise(&installation->radar, radarRange, trackingRadarRange, RADAR_INSTALLATIONLEVEL, qtrue);
00420 CP_UpdateMissionVisibleOnGeoscape();
00421 }
00422
00427 void RADAR_AddDetectedUFOToEveryRadar (const aircraft_t const *ufo)
00428 {
00429 int idx;
00430
00431 for (idx = 0; idx < MAX_BASES; idx++) {
00432 base_t *base = B_GetFoundedBaseByIDX(idx);
00433 aircraft_t *aircraft;
00434
00435 if (!base)
00436 continue;
00437
00438 if (!RADAR_IsUFOSensored(&base->radar, ufo)) {
00439 const float dist = GetDistanceOnGlobe(ufo->pos, base->pos);
00440 if (dist <= base->radar.trackingRange)
00441 RADAR_AddUFO(&base->radar, ufo);
00442 }
00443
00444 aircraft = NULL;
00445 while ((aircraft = AIR_GetNextFromBase(base, aircraft)) != NULL) {
00446 if (!AIR_IsAircraftOnGeoscape(aircraft))
00447 continue;
00448
00449 if (!RADAR_IsUFOSensored(&aircraft->radar, ufo)) {
00450 const float dist = GetDistanceOnGlobe(ufo->pos, aircraft->pos);
00451 if (dist <= aircraft->radar.trackingRange)
00452 RADAR_AddUFO(&aircraft->radar, ufo);
00453 }
00454 }
00455 }
00456
00457 for (idx = 0; idx < MAX_INSTALLATIONS; idx++) {
00458 installation_t *installation = INS_GetFoundedInstallationByIDX(idx);
00459
00460 if (!installation)
00461 continue;
00462
00463
00464 if (!installation->radar.trackingRange)
00465 continue;
00466
00467 if (!RADAR_IsUFOSensored(&installation->radar, ufo)) {
00468 const float dist = GetDistanceOnGlobe(ufo->pos, installation->pos);
00469 if (dist <= ufo->radar.trackingRange)
00470 RADAR_AddUFO(&installation->radar, ufo);
00471 }
00472 }
00473 }
00474
00480 qboolean RADAR_CheckRadarSensored (const vec2_t pos)
00481 {
00482 int idx;
00483
00484 for (idx = 0; idx < MAX_BASES; idx++) {
00485 const base_t const *base = B_GetFoundedBaseByIDX(idx);
00486 float dist;
00487 if (!base)
00488 continue;
00489
00490 dist = GetDistanceOnGlobe(pos, base->pos);
00491 if (dist <= base->radar.range)
00492 return qtrue;
00493 }
00494
00495 for (idx = 0; idx < MAX_INSTALLATIONS; idx++) {
00496 const installation_t const *installation = INS_GetFoundedInstallationByIDX(idx);
00497 float dist;
00498 if (!installation)
00499 continue;
00500
00501 dist = GetDistanceOnGlobe(pos, installation->pos);
00502 if (dist <= installation->radar.range)
00503 return qtrue;
00504 }
00505
00506 return qfalse;
00507 }
00508
00519 qboolean RADAR_CheckUFOSensored (radar_t *radar, const vec2_t posRadar,
00520 const aircraft_t *ufo, qboolean detected)
00521 {
00528 const float ufoDetectionProbability = 0.000125f * DETECTION_INTERVAL;
00529
00530 int dist;
00531 qboolean ufoIsSensored;
00532
00533
00534 ufoIsSensored = RADAR_IsUFOSensored(radar, ufo);
00535
00536 dist = GetDistanceOnGlobe(posRadar, ufo->pos);
00537
00538 if ((detected ? radar->trackingRange : radar->range) > dist) {
00539 if (detected) {
00540 if (!ufoIsSensored) {
00541
00542
00543 RADAR_AddUFO(radar, ufo);
00544 }
00545 return qtrue;
00546 } else {
00547
00548
00549 assert(ufoIsSensored == qfalse);
00550
00551 if (frand() <= ufoDetectionProbability) {
00552 RADAR_AddDetectedUFOToEveryRadar(ufo);
00553 return qtrue;
00554 }
00555 return qfalse;
00556 }
00557 }
00558
00559
00560
00561 if (ufoIsSensored)
00562 RADAR_RemoveUFO(radar, ufo);
00563
00564 return qfalse;
00565 }
00566
00572 void RADAR_SetRadarAfterLoading (void)
00573 {
00574 int ufoIdx;
00575
00576 for (ufoIdx = 0; ufoIdx < ccs.numUFOs; ufoIdx++) {
00577 const aircraft_t const *ufo = UFO_GetByIDX(ufoIdx);
00578
00579 if (!ufo->detected)
00580 continue;
00581
00582 RADAR_AddDetectedUFOToEveryRadar(ufo);
00583 }
00584
00585 MAP_UpdateGeoscapeDock();
00586 }