cp_radar.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "../cl_shared.h"
00027 #include "../cl_renderer.h" /* R_Color */
00028 #include "../renderer/r_image.h"
00029 #include "../renderer/r_draw.h" /* R_DrawLineStrip */
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 /* Define base radar range (can be modified by level of the radar) */
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     /* Initialise radar range (will be filled below) */
00060     CP_InitializeRadarOverlay(qtrue);
00061 
00062     /* Add base radar coverage */
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     /* Add installation coverage */
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     /* Smooth and bind radar overlay without aircraft (in case no aircraft is on geoscape:
00080      * RADAR_UpdateWholeRadarOverlay won't be called) */
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     /* Copy Base and installation radar overlay*/
00102     CP_InitializeRadarOverlay(qfalse);
00103 
00104     /* Add aircraft radar coverage */
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     /* Show radar range zones */
00146     RADAR_DrawLineCoverage(node, radar, pos);
00147 
00148     /* everything below is drawn only if there is at least one detected UFO */
00149     if (!radar->numUFOs)
00150         return;
00151 
00152     /* Set color */
00153     R_Color(color);
00154 
00155     /* Draw lines from radar to ufos sensored */
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     /* never deactivate radar if player wants it to be always turned on */
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--;    /* Allow the moved value to be checked */
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     /* Sanity check */
00405     if (!installation || !installation->installationTemplate)
00406         Com_Error(ERR_DROP, "RADAR_UpdateInstallationRadarCoverage: No installation or no template!\n");
00407 
00408     /* Do nothing if installation not founded */
00409     if (!installation->founded)
00410         return;
00411     /* Do nothing if installation not finished */
00412     if (installation->installationStatus != INSTALLATION_WORKING)
00413         return;
00414     /* Do nothing if this isn't a RadarTower */
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); /* Distance from radar to UFO */
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); /* Distance from radar to UFO */
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         /* No need to check installations without radar */
00464         if (!installation->radar.trackingRange)
00465             continue;
00466 
00467         if (!RADAR_IsUFOSensored(&installation->radar, ufo)) {
00468             const float dist = GetDistanceOnGlobe(ufo->pos, installation->pos); /* Distance from radar to UFO */
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);      /* Distance from base to position */
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);      /* Distance from base to position */
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     /* indice of ufo in radar list */
00534     ufoIsSensored = RADAR_IsUFOSensored(radar, ufo);
00535     /* Distance from radar to ufo */
00536     dist = GetDistanceOnGlobe(posRadar, ufo->pos);
00537 
00538     if ((detected ? radar->trackingRange : radar->range) > dist) {
00539         if (detected) {
00540             if (!ufoIsSensored) {
00541                 /* UFO was not sensored by this radar, but by another one
00542                  * (it just entered this radar zone) */
00543                 RADAR_AddUFO(radar, ufo);
00544             }
00545             return qtrue;
00546         } else {
00547             /* UFO is sensored by no radar, so it shouldn't be sensored
00548              * by this radar */
00549             assert(ufoIsSensored == qfalse);
00550             /* Check if UFO is detected */
00551             if (frand() <= ufoDetectionProbability) {
00552                 RADAR_AddDetectedUFOToEveryRadar(ufo);
00553                 return qtrue;
00554             }
00555             return qfalse;
00556         }
00557     }
00558 
00559     /* UFO is not in this sensor range any more (but maybe
00560      * in the range of another radar) */
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 }

Generated by  doxygen 1.6.2