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 "cp_campaign.h"
00028 #include "cp_overlay.h"
00029 #include "cp_map.h"
00030 #include "cp_xvi.h"
00031 #include "save/save_xvi.h"
00032
00034 static technology_t *rsAlienXVI;
00035
00037 static qboolean xviNationInfectionNeedsUpdate = qfalse;
00038
00043 static const float XVI_FACTOR = 15.0f;
00044
00046 static const int XVI_DECREASE_DAYS = 7;
00047
00049 #define XVI_EVENT_NAME "rs_alien_xvi_event"
00050
00055 void CP_SpreadXVIAtPos (const vec2_t pos)
00056 {
00057 if (!CP_IsXVIResearched())
00058 return;
00059
00060 CP_ChangeXVILevel(pos, XVI_FACTOR);
00061
00062 xviNationInfectionNeedsUpdate = qtrue;
00063 }
00064
00069 void CP_ReduceXVIEverywhere (void)
00070 {
00071 if (!CP_IsXVIResearched())
00072 return;
00073
00074
00075 if (ccs.date.day % XVI_DECREASE_DAYS)
00076 return;
00077
00078 CP_DecreaseXVILevelEverywhere();
00079
00080 xviNationInfectionNeedsUpdate = qtrue;
00081 }
00082
00087 void CP_UpdateNationXVIInfection (void)
00088 {
00089
00090 float xviInfection[MAX_NATIONS];
00091 int y;
00092 int nationIdx;
00093
00094 int width;
00095
00096 int height;
00097 float heightPerDegree;
00098 float widthPerDegree;
00099
00100 vec2_t currentPos;
00101
00102
00103 const float AREA_FACTOR = 650.0f;
00104
00105
00106
00107 float normalizingArea;
00108
00109
00110 if (!xviNationInfectionNeedsUpdate)
00111 return;
00112
00113
00114 for (nationIdx = 0; nationIdx < ccs.numNations; nationIdx++)
00115 xviInfection[nationIdx] = 0;
00116
00117 CP_GetXVIMapDimensions(&width, &height);
00118 heightPerDegree = height / 180.0f;
00119 widthPerDegree = width / 360.0f;
00120 normalizingArea = width * height / AREA_FACTOR;
00121
00122 for (y = 0; y < height; y++) {
00123 int x;
00124 int sum[MAX_NATIONS];
00125 const byte* previousNationColor;
00126 const nation_t* nation;
00127
00128 memset(sum, 0, sizeof(sum));
00129
00130 Vector2Set(currentPos, 180.0f, 90.0f - y / heightPerDegree);
00131 previousNationColor = MAP_GetColor(currentPos, MAPTYPE_NATIONS);
00132 nation = MAP_GetNation(currentPos);
00133
00134 for (x = 0; x < width; x++) {
00135 const byte* nationColor;
00136 currentPos[0] = 180.0f - x / widthPerDegree;
00137 nationColor = MAP_GetColor(currentPos, MAPTYPE_NATIONS);
00138 if (!VectorCompare(nationColor, previousNationColor)) {
00139 previousNationColor = nationColor;
00140 nation = MAP_GetNation(currentPos);
00141 }
00142 if (nation) {
00143 const int xviLevel = CP_GetXVILevel(x, y);
00144 if (xviLevel > 0)
00145 sum[nation->idx] += xviLevel;
00146 }
00147 }
00148
00149
00150 for (nationIdx = 0; nationIdx < ccs.numNations; nationIdx++)
00151 xviInfection[nationIdx] += ((float) sum[nationIdx]) / (cos(torad * currentPos[1]) * normalizingArea);
00152 }
00153
00154
00155 for (nationIdx = 0; nationIdx < ccs.numNations; nationIdx++) {
00156 nation_t* nation = &ccs.nations[nationIdx];
00157 nation->stats[0].xviInfection = ceil(xviInfection[nation->idx]);
00158 }
00159
00160 xviNationInfectionNeedsUpdate = qfalse;
00161 }
00162
00167 int CP_GetAverageXVIRate (void)
00168 {
00169 int XVIRate = 0;
00170 int i;
00171 nation_t* nation;
00172
00173 assert(ccs.numNations);
00174
00175
00176 for (i = 0, nation = ccs.nations; i < ccs.numNations; i++, nation++) {
00177 XVIRate += nation->stats[0].xviInfection;
00178 }
00179 XVIRate /= ccs.numNations;
00180 return XVIRate;
00181 }
00182
00187 void CP_SpreadXVI (void)
00188 {
00189 const linkedList_t *list = ccs.missions;
00190
00191
00192 if (!CP_IsXVIResearched())
00193 return;
00194
00195 for (;list; list = list->next) {
00196 const mission_t *mission = (mission_t *)list->data;
00197 if (mission->stage == STAGE_SPREAD_XVI)
00198 CP_SpreadXVIAtPos(mission->pos);
00199 }
00200 }
00201
00209 qboolean CP_IsXVIResearched (void)
00210 {
00211 return RS_IsResearched_ptr(rsAlienXVI);
00212 }
00213
00214 void CP_XVIInit (void)
00215 {
00216 rsAlienXVI = RS_GetTechByID(XVI_EVENT_NAME);
00217 if (!rsAlienXVI)
00218 Com_Error(ERR_DROP, "CP_XVIInit: Could not find tech definition for " XVI_EVENT_NAME);
00219 }
00220
00228 qboolean XVI_SaveXML (mxml_node_t *p)
00229 {
00230 int y;
00231 int width;
00232 int height;
00233 mxml_node_t *n;
00234
00235 CP_GetXVIMapDimensions(&width, &height);
00236
00237 n = mxml_AddNode(p, SAVE_XVI_XVI);
00238 mxml_AddInt(n, SAVE_XVI_WIDTH, width);
00239 mxml_AddInt(n, SAVE_XVI_HEIGHT, height);
00240
00241 for (y = 0; y < height; y++) {
00242 int x;
00243 for (x = 0; x < width; x++) {
00244 const int xviLevel = CP_GetXVILevel(x, y);
00245
00246 if (xviLevel > 0) {
00247 mxml_node_t *s = mxml_AddNode(n, SAVE_XVI_ENTRY);
00248 mxml_AddInt(s, SAVE_XVI_X, x);
00249 mxml_AddInt(s, SAVE_XVI_Y, y);
00250 mxml_AddInt(s, SAVE_XVI_LEVEL, xviLevel);
00251 }
00252 }
00253 }
00254 return qtrue;
00255 }
00256
00263 qboolean XVI_LoadXML (mxml_node_t *p)
00264 {
00265 int width, height;
00266 mxml_node_t *s;
00267 mxml_node_t *n = mxml_GetNode(p, SAVE_XVI_XVI);
00268
00269 if (!n) {
00270 CP_InitializeXVIOverlay(NULL);
00271 return qtrue;
00272 }
00273
00274 width = mxml_GetInt(n, SAVE_XVI_WIDTH, 0);
00275 height = mxml_GetInt(n, SAVE_XVI_HEIGHT, 0);
00276
00277 for (s = mxml_GetNode(n, SAVE_XVI_ENTRY); s; s = mxml_GetNextNode(s, n, SAVE_XVI_ENTRY)) {
00278 const int x = mxml_GetInt(s, SAVE_XVI_X, 0);
00279 const int y = mxml_GetInt(s, SAVE_XVI_Y, 0);
00280 const int level = mxml_GetInt(s, SAVE_XVI_LEVEL, 0);
00281
00282 if (x >= 0 && x < width && y >= 0 && y <= height)
00283 CP_SetXVILevel(x, y, level);
00284 }
00285 return qtrue;
00286 }
00287
00292 void CP_StartXVISpreading_f (void)
00293 {
00294 int i, numAlienBases;
00295
00300 ccs.XVIShowMap = qtrue;
00301
00302
00303 if (ccs.curCampaign->difficulty > 0)
00304 numAlienBases = 3;
00305 else if (ccs.curCampaign->difficulty < 0)
00306 numAlienBases = 1;
00307 else
00308 numAlienBases = 2;
00309
00310 for (i = 0; i < numAlienBases; i++)
00311 CP_CreateNewMission(INTERESTCATEGORY_BUILDING, qfalse);
00312 }
00313
00317 void CP_UpdateXVIMapButton (void)
00318 {
00319 Cvar_SetValue("mn_xvimap", ccs.XVIShowMap);
00320 }