UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cp_xvi.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2020 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 
26 #include "../../cl_shared.h"
27 #include "cp_campaign.h"
28 #include "cp_overlay.h"
29 #include "cp_geoscape.h"
30 #include "cp_xvi.h"
31 #include "cp_missions.h"
32 #include "save/save_xvi.h"
33 
36 
38 static bool xviNationInfectionNeedsUpdate = false;
39 
44 static const float XVI_FACTOR = 15.0f;
45 
47 static const int XVI_DECREASE_DAYS = 7;
48 
50 #define XVI_EVENT_NAME "rs_alien_xvi_event"
51 
56 void CP_SpreadXVIAtPos (const vec2_t pos)
57 {
58  if (!CP_IsXVIStarted())
59  return;
60 
62 
64 }
65 
71 {
72  if (!CP_IsXVIStarted())
73  return;
74 
75  /* Only decrease XVI if given days has passed */
77  return;
78 
80 
82 }
83 
89 {
90  /* No need to update XVI levels if the overlay didn't change */
92  return;
93 
94  /* width in pixel of the XVI overlay */
95  int width;
96  /* height in pixel of the XVI overlay */
97  int height;
98  CP_GetXVIMapDimensions(&width, &height);
99 
100  const float heightPerDegree = height / 180.0f;
101  const float widthPerDegree = width / 360.0f;
102  /* parameter used to normalize nation XVI level.
103  * decrease this factor to increase XVI level per nation */
104  const float AREA_FACTOR = 650.0f;
105  /* area used to normalized XVI infection level for each nation.
106  * depend on overlay size so that if we change resolution of
107  * overlay it doesn't impact nation XIInfection */
108  const float normalizingArea = width * height / AREA_FACTOR;
109 
110  /* temporary array to store the XVI levels */
111  float* xviInfection = Mem_PoolAllocTypeN(float, ccs.numNations, cp_campaignPool);
112  OBJZERO(*xviInfection);
113 
114  for (int y = 0; y < height; y++) {
115  const byte* previousNationColor;
116  const nation_t* nation;
117  /* current position (in latitude / longitude) */
118  vec2_t currentPos;
119 
121  OBJZERO(*sum);
122 
123  Vector2Set(currentPos, 180.0f, 90.0f - y / heightPerDegree);
124  previousNationColor = GEO_GetColor(currentPos, MAPTYPE_NATIONS, nullptr);
125  nation = GEO_GetNation(currentPos);
126 
127  for (int x = 0; x < width; x++) {
128  const byte* nationColor;
129  currentPos[0] = 180.0f - x / widthPerDegree;
130  nationColor = GEO_GetColor(currentPos, MAPTYPE_NATIONS, nullptr);
131  if (!VectorCompare(nationColor, previousNationColor)) {
132  previousNationColor = nationColor;
133  nation = GEO_GetNation(currentPos);
134  }
135  if (nation) {
136  const int xviLevel = CP_GetXVILevel(x, y);
137  if (xviLevel > 0)
138  sum[nation->idx] += xviLevel;
139  }
140  }
141  /* divide the total XVI infection by the area of a pixel
142  * because pixel are smaller as you go closer from the pole */
143  for (int nationIdx = 0; nationIdx < ccs.numNations; nationIdx++)
144  xviInfection[nationIdx] += ((float) sum[nationIdx]) / (cos(torad * currentPos[1]) * normalizingArea);
145  cgi->Free(sum);
146  }
147 
148  /* copy the new values of XVI infection level into nation array */
149  int nationIdx = 0;
150  NAT_Foreach(nation) {
151  nation->stats[0].xviInfection = ceil(xviInfection[nationIdx]);
152  nationIdx++;
153  }
154  cgi->Free(xviInfection);
155 
157 }
158 
164 {
165  assert(ccs.numNations);
166 
167  /* check for XVI infection rate */
168  int xviRate = 0;
169  NAT_Foreach(nation) {
170  const nationInfo_t* stats = NAT_GetCurrentMonthInfo(nation);
171  xviRate += stats->xviInfection;
172  }
173  xviRate /= ccs.numNations;
174  return xviRate;
175 }
176 
181 void CP_SpreadXVI (void)
182 {
183  /* don't check if XVI spreading didn't start yet */
184  if (!CP_IsXVIStarted())
185  return;
186 
187  MIS_Foreach(mission) {
188  if (mission->stage == STAGE_SPREAD_XVI)
189  CP_SpreadXVIAtPos(mission->pos);
190  }
191 }
192 
196 bool CP_IsXVIVisible (void)
197 {
198  return RS_IsResearched_ptr(rsAlienXVI);
199 }
200 
201 void CP_XVIInit (void)
202 {
203  rsAlienXVI = RS_GetTechByID(XVI_EVENT_NAME);
204  if (!rsAlienXVI)
205  cgi->Com_Error(ERR_DROP, "CP_XVIInit: Could not find tech definition for " XVI_EVENT_NAME);
206 }
207 
216 {
217  int width;
218  int height;
219 
220  CP_GetXVIMapDimensions(&width, &height);
221 
223  cgi->XML_AddInt(n, SAVE_XVI_WIDTH, width);
224  cgi->XML_AddInt(n, SAVE_XVI_HEIGHT, height);
225 
226  for (int y = 0; y < height; y++) {
227  for (int x = 0; x < width; x++) {
228  const int xviLevel = CP_GetXVILevel(x, y);
229  /* That saves many bytes in the savegame */
230  if (xviLevel > 0) {
232  cgi->XML_AddInt(s, SAVE_XVI_X, x);
233  cgi->XML_AddInt(s, SAVE_XVI_Y, y);
234  cgi->XML_AddInt(s, SAVE_XVI_LEVEL, xviLevel);
235  }
236  }
237  }
238  return true;
239 }
240 
248 {
249  int width, height;
250  xmlNode_t* s;
252  /* If there is no XVI, it will not be loaded */
253  if (!n) {
255  return true;
256  }
257 
258  width = cgi->XML_GetInt(n, SAVE_XVI_WIDTH, 0);
259  height = cgi->XML_GetInt(n, SAVE_XVI_HEIGHT, 0);
260 
261  for (s = cgi->XML_GetNode(n, SAVE_XVI_ENTRY); s; s = cgi->XML_GetNextNode(s, n, SAVE_XVI_ENTRY)) {
262  const int x = cgi->XML_GetInt(s, SAVE_XVI_X, 0);
263  const int y = cgi->XML_GetInt(s, SAVE_XVI_Y, 0);
264  const int level = cgi->XML_GetInt(s, SAVE_XVI_LEVEL, 0);
265 
266  if (x >= 0 && x < width && y >= 0 && y <= height)
267  CP_SetXVILevel(x, y, level);
268  }
269  return true;
270 }
271 
277 {
278  int numAlienBases;
279  const campaign_t* campaign = ccs.curCampaign;
280 
281  ccs.startXVI = true;
282 
283  /* Spawn a few alien bases depending on difficulty level */
284  if (campaign->difficulty > 0)
285  numAlienBases = 3;
286  else if (campaign->difficulty < 0)
287  numAlienBases = 1;
288  else
289  numAlienBases = 2;
290 
291  for (int i = 0; i < numAlienBases; i++)
293 }
294 
299 {
300  cgi->Cvar_SetValue("mn_xvimap", CP_IsXVIVisible());
301 }
int CP_GetAverageXVIRate(void)
Return the average XVI rate.
Definition: cp_xvi.cpp:163
const nationInfo_t * NAT_GetCurrentMonthInfo(const nation_t *const nation)
Get the current month nation stats.
Definition: cp_nation.cpp:132
Nation definition.
Definition: cp_nation.h:44
bool RS_IsResearched_ptr(const technology_t *tech)
Checks whether an item is already researched.
void CP_UpdateNationXVIInfection(void)
Update xviInfection value for each nation, using the XVI overlay.
Definition: cp_xvi.cpp:88
#define MIS_Foreach(var)
iterates through missions
Definition: cp_missions.h:118
bool XVI_SaveXML(xmlNode_t *p)
XVI map saving callback.
Definition: cp_xvi.cpp:215
void CP_SetXVILevel(int x, int y, int value)
Definition: cp_overlay.cpp:58
static bool xviNationInfectionNeedsUpdate
boolean used to know if each nation XVI level should be updated this day.
Definition: cp_xvi.cpp:38
int numNations
Definition: cp_campaign.h:296
int xviInfection
Definition: cp_nation.h:38
void CP_DecreaseXVILevelEverywhere(void)
Definition: cp_overlay.cpp:237
#define SAVE_XVI_ENTRY
Definition: save_xvi.h:31
static const int XVI_DECREASE_DAYS
Number of days between 2 XVI decrease (everywhere around the world).
Definition: cp_xvi.cpp:47
int day
Definition: common.h:291
date_t date
Definition: cp_campaign.h:245
static technology_t * rsAlienXVI
technology for XVI event
Definition: cp_xvi.cpp:35
const byte * GEO_GetColor(const vec2_t pos, mapType_t type, bool *coast)
Returns the color value from geoscape of a certain mask (terrain, culture or population) at a given p...
memPool_t * cp_campaignPool
Definition: cp_campaign.cpp:61
#define SAVE_XVI_Y
Definition: save_xvi.h:33
#define SAVE_XVI_LEVEL
Definition: save_xvi.h:34
Functions to generate and render overlay for geoscape.
#define xmlNode_t
Definition: xml.h:24
void CP_SpreadXVIAtPos(const vec2_t pos)
Spread XVI at a given position.
Definition: cp_xvi.cpp:56
Campaign XVI header.
#define ERR_DROP
Definition: common.h:211
#define NAT_Foreach(var)
iterates trough nations
Definition: cp_nation.h:80
#define OBJZERO(obj)
Definition: shared.h:178
#define Vector2Set(v, x, y)
Definition: vector.h:61
void CP_GetXVIMapDimensions(int *width, int *height)
Definition: cp_overlay.cpp:52
Campaign missions headers.
const cgame_import_t * cgi
#define SAVE_XVI_X
Definition: save_xvi.h:32
void CP_ReduceXVIEverywhere(void)
Reduce XVI everywhere.
Definition: cp_xvi.cpp:70
bool CP_IsXVIVisible(void)
Returns true if the XVI effect should be visible to the player.
Definition: cp_xvi.cpp:196
This is the technology parsed from research.ufo.
Definition: cp_research.h:137
ccs_t ccs
Definition: cp_campaign.cpp:62
#define SAVE_XVI_WIDTH
Definition: save_xvi.h:28
Header for Geoscape management.
technology_t * RS_GetTechByID(const char *id)
return a pointer to the technology identified by given id string
bool startXVI
Definition: cp_campaign.h:246
#define SAVE_XVI_XVI
Definition: save_xvi.h:27
void CP_XVIInit(void)
Definition: cp_xvi.cpp:201
int idx
Definition: cp_nation.h:47
static const float XVI_FACTOR
The factor that is used to determine XVI radius spreading. The higher this factor, the faster XVI will spread.
Definition: cp_xvi.cpp:44
#define VectorCompare(a, b)
Definition: vector.h:63
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
bool XVI_LoadXML(xmlNode_t *p)
Load the XVI map from the savegame.
Definition: cp_xvi.cpp:247
XML tag constants for savegame.
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
int CP_GetXVILevel(int x, int y)
Definition: cp_overlay.cpp:71
QGL_EXTERN GLint i
Definition: r_gl.h:113
void CP_StartXVISpreading_f(void)
Start XVI spreading in campaign.
Definition: cp_xvi.cpp:276
signed int difficulty
Definition: cp_campaign.h:185
xmlNode_t *IMPORT * XML_GetNextNode(xmlNode_t *current, xmlNode_t *parent, const char *name)
void CP_SpreadXVI(void)
Spread XVI for each mission that needs to be daily spread.
Definition: cp_xvi.cpp:181
#define torad
Definition: mathlib.h:50
void CP_InitializeXVIOverlay(void)
Initialize XVI overlay on geoscape.
Definition: cp_overlay.cpp:269
vec_t vec2_t[2]
Definition: ufotypes.h:38
Header file for single player campaign control.
xmlNode_t *IMPORT * XML_AddNode(xmlNode_t *parent, const char *name)
campaign_t * curCampaign
Definition: cp_campaign.h:377
void CP_ChangeXVILevel(const vec2_t pos, float factor)
Convert the pos into degrees and increase XVI there.
Definition: cp_overlay.cpp:257
uint8_t byte
Definition: ufotypes.h:34
void CP_UpdateXVIMapButton(void)
This will hide or show the geoscape button for handling the xvi overlay map.
Definition: cp_xvi.cpp:298
#define CP_IsXVIStarted()
Definition: cp_xvi.h:37
nation_t * GEO_GetNation(const vec2_t pos)
Translate nation map color to nation.
#define XVI_EVENT_NAME
Name of the technology for the XVI event.
Definition: cp_xvi.cpp:50
xmlNode_t *IMPORT * XML_GetNode(xmlNode_t *parent, const char *name)
#define SAVE_XVI_HEIGHT
Definition: save_xvi.h:29
level_locals_t level
Definition: g_main.cpp:38
mission_t * CP_CreateNewMission(interestCategory_t category, bool beginNow)
Create a new mission of given category.
Detailed information about the nation relationship (currently per month, but could be used elsewhere)...
Definition: cp_nation.h:33