File: | client/cgame/campaign/cp_xvi.cpp |
Location: | line 151, column 4 |
Description: | The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage |
1 | /** | ||
2 | * @file | ||
3 | * @brief Campaign XVI code | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | Copyright (C) 2002-2011 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_map.h" | ||
30 | #include "cp_xvi.h" | ||
31 | #include "save/save_xvi.h" | ||
32 | |||
33 | /** @brief technology for XVI event */ | ||
34 | static technology_t *rsAlienXVI; | ||
35 | |||
36 | /** @brief boolean used to know if each nation XVI level should be updated this day. */ | ||
37 | static bool xviNationInfectionNeedsUpdate = false; | ||
38 | |||
39 | /** | ||
40 | * @brief The factor that is used to determine XVI radius spreading. | ||
41 | * The higher this factor, the faster XVI will spread. | ||
42 | */ | ||
43 | static const float XVI_FACTOR = 15.0f; | ||
44 | |||
45 | /** @brief Number of days between 2 XVI decrease (everywhere around the world). */ | ||
46 | static const int XVI_DECREASE_DAYS = 7; | ||
47 | |||
48 | /** @brief Name of the technology for the XVI event */ | ||
49 | #define XVI_EVENT_NAME"rs_alien_xvi_event" "rs_alien_xvi_event" | ||
50 | |||
51 | /** | ||
52 | * @brief Spread XVI at a given position. | ||
53 | * @param[in] pos Position where XVI should be spread. | ||
54 | */ | ||
55 | void CP_SpreadXVIAtPos (const vec2_t pos) | ||
56 | { | ||
57 | if (!CP_IsXVIResearched()) | ||
58 | return; | ||
59 | |||
60 | CP_ChangeXVILevel(pos, XVI_FACTOR); | ||
61 | |||
62 | xviNationInfectionNeedsUpdate = true; | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * @brief Reduce XVI everywhere. | ||
67 | * @note This is called daily. | ||
68 | */ | ||
69 | void CP_ReduceXVIEverywhere (void) | ||
70 | { | ||
71 | if (!CP_IsXVIResearched()) | ||
72 | return; | ||
73 | |||
74 | /* Only decrease XVI if given days has passed */ | ||
75 | if (ccs.date.day % XVI_DECREASE_DAYS) | ||
76 | return; | ||
77 | |||
78 | CP_DecreaseXVILevelEverywhere(); | ||
79 | |||
80 | xviNationInfectionNeedsUpdate = true; | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * @brief Update xviInfection value for each nation, using the XVI overlay. | ||
85 | * @note should be executed after all daily event that could change XVI overlay | ||
86 | */ | ||
87 | void CP_UpdateNationXVIInfection (void) | ||
88 | { | ||
89 | /* temporary array to store the XVI levels */ | ||
90 | float xviInfection[MAX_NATIONS8]; | ||
91 | int y; | ||
92 | int nationIdx; | ||
93 | /* width in pixel of the XVI overlay */ | ||
94 | int width; | ||
95 | /* height in pixel of the XVI overlay */ | ||
96 | int height; | ||
97 | float heightPerDegree; | ||
98 | float widthPerDegree; | ||
99 | /* current position (in latitude / longitude) */ | ||
100 | vec2_t currentPos; | ||
101 | /* parameter used to normalize nation XVI level. | ||
102 | * decrease this factor to increase XVI level per nation */ | ||
103 | const float AREA_FACTOR = 650.0f; | ||
104 | /* area used to normalized XVI infection level for each nation. | ||
105 | * depend on overlay size so that if we change resolution of | ||
106 | * overlay it doesn't impact nation XIInfection */ | ||
107 | float normalizingArea; | ||
108 | |||
109 | /* No need to update XVI levels if the overlay didn't change */ | ||
110 | if (!xviNationInfectionNeedsUpdate) | ||
| |||
| |||
111 | return; | ||
112 | |||
113 | /* Initialize array */ | ||
114 | for (nationIdx = 0; nationIdx < ccs.numNations; nationIdx++) | ||
| |||
115 | xviInfection[nationIdx] = 0; | ||
116 | |||
117 | CP_GetXVIMapDimensions(&width, &height); | ||
118 | heightPerDegree = height / 180.0f; | ||
119 | widthPerDegree = width / 360.0f; | ||
120 | normalizingArea = width * height / AREA_FACTOR; | ||
121 | |||
122 | for (y = 0; y < height; y++) { | ||
| |||
| |||
123 | int x; | ||
124 | int sum[MAX_NATIONS8]; | ||
125 | const byte* previousNationColor; | ||
126 | const nation_t* nation; | ||
127 | |||
128 | OBJZERO(sum)(memset(&((sum)), (0), sizeof((sum)))); | ||
129 | |||
130 | Vector2Set(currentPos, 180.0f, 90.0f - y / heightPerDegree)((currentPos)[0]=(180.0f), (currentPos)[1]=(90.0f - y / heightPerDegree )); | ||
131 | previousNationColor = MAP_GetColor(currentPos, MAPTYPE_NATIONS, NULL__null); | ||
132 | nation = MAP_GetNation(currentPos); | ||
133 | |||
134 | for (x = 0; x < width; x++) { | ||
| |||
| |||
135 | const byte* nationColor; | ||
136 | currentPos[0] = 180.0f - x / widthPerDegree; | ||
137 | nationColor = MAP_GetColor(currentPos, MAPTYPE_NATIONS, NULL__null); | ||
138 | if (!VectorCompare(nationColor, previousNationColor)((nationColor)[0]==(previousNationColor)[0]?(nationColor)[1]== (previousNationColor)[1]?(nationColor)[2]==(previousNationColor )[2]?1:0:0:0)) { | ||
139 | previousNationColor = nationColor; | ||
140 | nation = MAP_GetNation(currentPos); | ||
141 | } | ||
142 | if (nation) { | ||
143 | const int xviLevel = CP_GetXVILevel(x, y); | ||
144 | if (xviLevel > 0) | ||
145 | sum[nation->idx] += xviLevel; | ||
146 | } | ||
147 | } | ||
148 | /* divide the total XVI infection by the area of a pixel | ||
149 | * because pixel are smaller as you go closer from the pole */ | ||
150 | for (nationIdx = 0; nationIdx < ccs.numNations; nationIdx++) | ||
| |||
151 | xviInfection[nationIdx] += ((float) sum[nationIdx]) / (cos(torad(3.14159265358979323846264338327950288/180.0f) * currentPos[1]) * normalizingArea); | ||
| |||
152 | } | ||
153 | |||
154 | /* copy the new values of XVI infection level into nation array */ | ||
155 | for (nationIdx = 0; nationIdx < ccs.numNations; nationIdx++) { | ||
156 | nation_t* nation = NAT_GetNationByIDX(nationIdx); | ||
157 | nation->stats[0].xviInfection = ceil(xviInfection[nation->idx]); | ||
158 | } | ||
159 | |||
160 | xviNationInfectionNeedsUpdate = false; | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * @brief Return the average XVI rate | ||
165 | * @note XVI = eXtraterrestial Viral Infection | ||
166 | */ | ||
167 | int CP_GetAverageXVIRate (void) | ||
168 | { | ||
169 | int XVIRate = 0; | ||
170 | int i; | ||
171 | |||
172 | assert(ccs.numNations)(__builtin_expect(!(ccs.numNations), 0) ? __assert_rtn(__func__ , "src/client/cgame/campaign/cp_xvi.cpp", 172, "ccs.numNations" ) : (void)0); | ||
173 | |||
174 | /* check for XVI infection rate */ | ||
175 | for (i = 0; i < ccs.numNations; i++) { | ||
176 | const nation_t *nation = NAT_GetNationByIDX(i); | ||
177 | const nationInfo_t *stats = NAT_GetCurrentMonthInfo(nation); | ||
178 | XVIRate += stats->xviInfection; | ||
179 | } | ||
180 | XVIRate /= ccs.numNations; | ||
181 | return XVIRate; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * @brief Spread XVI for each mission that needs to be daily spread. | ||
186 | * @note Daily called | ||
187 | */ | ||
188 | void CP_SpreadXVI (void) | ||
189 | { | ||
190 | /* don't check if XVI spreading didn't start yet */ | ||
191 | if (!CP_IsXVIResearched()) | ||
192 | return; | ||
193 | |||
194 | MIS_Foreach(mission)for (bool mission__break = false, mission__once = true; mission__once ; mission__once = false) for (linkedList_t const* mission__iter = (ccs.missions); ! mission__break && mission__iter; ) for (mission_t* const mission = ( mission__break = mission__once = true, (mission_t*) mission__iter->data); mission__once; mission__break = mission__once = false) if ( mission__iter = mission__iter->next, false) {} else { | ||
195 | if (mission->stage == STAGE_SPREAD_XVI) | ||
196 | CP_SpreadXVIAtPos(mission->pos); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | /** | ||
201 | * @brief Returns @c true if the tech for the xvi event is already researched. | ||
202 | * If this tech is already researched the aliens will spread their XVI - but it | ||
203 | * does not mean that the Phalanx can also do anything against it or is even | ||
204 | * able to the map of XVI | ||
205 | * @see css.XVIShowMap | ||
206 | */ | ||
207 | bool CP_IsXVIResearched (void) | ||
208 | { | ||
209 | return RS_IsResearched_ptr(rsAlienXVI); | ||
210 | } | ||
211 | |||
212 | void CP_XVIInit (void) | ||
213 | { | ||
214 | rsAlienXVI = RS_GetTechByID(XVI_EVENT_NAME"rs_alien_xvi_event"); | ||
215 | if (!rsAlienXVI) | ||
216 | Com_Error(ERR_DROP1, "CP_XVIInit: Could not find tech definition for " XVI_EVENT_NAME"rs_alien_xvi_event"); | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * @brief XVI map saving callback | ||
221 | * @note Only save transparency | ||
222 | * @sa Savegame callback | ||
223 | * @sa SAV_InitXML | ||
224 | * @sa XVI_LoadXML | ||
225 | */ | ||
226 | bool XVI_SaveXML (xmlNode_tmxml_node_t *p) | ||
227 | { | ||
228 | int y; | ||
229 | int width; | ||
230 | int height; | ||
231 | xmlNode_tmxml_node_t *n; | ||
232 | |||
233 | CP_GetXVIMapDimensions(&width, &height); | ||
234 | |||
235 | n = XML_AddNode(p, SAVE_XVI_XVI"XVI"); | ||
236 | XML_AddInt(n, SAVE_XVI_WIDTH"width", width); | ||
237 | XML_AddInt(n, SAVE_XVI_HEIGHT"height", height); | ||
238 | |||
239 | for (y = 0; y < height; y++) { | ||
240 | int x; | ||
241 | for (x = 0; x < width; x++) { | ||
242 | const int xviLevel = CP_GetXVILevel(x, y); | ||
243 | /* That saves many bytes in the savegame */ | ||
244 | if (xviLevel > 0) { | ||
245 | xmlNode_tmxml_node_t *s = XML_AddNode(n, SAVE_XVI_ENTRY"entry"); | ||
246 | XML_AddInt(s, SAVE_XVI_X"x", x); | ||
247 | XML_AddInt(s, SAVE_XVI_Y"y", y); | ||
248 | XML_AddInt(s, SAVE_XVI_LEVEL"level", xviLevel); | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | return true; | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * @brief Load the XVI map from the savegame. | ||
257 | * @sa Savegame callback | ||
258 | * @sa SAV_InitXML | ||
259 | * @sa XVI_SaveXML | ||
260 | */ | ||
261 | bool XVI_LoadXML (xmlNode_tmxml_node_t *p) | ||
262 | { | ||
263 | int width, height; | ||
264 | xmlNode_tmxml_node_t *s; | ||
265 | xmlNode_tmxml_node_t *n = XML_GetNode(p, SAVE_XVI_XVI"XVI"); | ||
266 | /* If there is no XVI, it will not be loaded */ | ||
267 | if (!n) { | ||
268 | CP_InitializeXVIOverlay(NULL__null); | ||
269 | return true; | ||
270 | } | ||
271 | |||
272 | width = XML_GetInt(n, SAVE_XVI_WIDTH"width", 0); | ||
273 | height = XML_GetInt(n, SAVE_XVI_HEIGHT"height", 0); | ||
274 | |||
275 | for (s = XML_GetNode(n, SAVE_XVI_ENTRY"entry"); s; s = XML_GetNextNode(s, n, SAVE_XVI_ENTRY"entry")) { | ||
276 | const int x = XML_GetInt(s, SAVE_XVI_X"x", 0); | ||
277 | const int y = XML_GetInt(s, SAVE_XVI_Y"y", 0); | ||
278 | const int level = XML_GetInt(s, SAVE_XVI_LEVEL"level", 0); | ||
279 | |||
280 | if (x >= 0 && x < width && y >= 0 && y <= height) | ||
281 | CP_SetXVILevel(x, y, level); | ||
282 | } | ||
283 | return true; | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * @brief Start XVI spreading in campaign. | ||
288 | * @note This is called when 'a new twist' technology is discovered. | ||
289 | */ | ||
290 | void CP_StartXVISpreading_f (void) | ||
291 | { | ||
292 | int i, numAlienBases; | ||
293 | const campaign_t *campaign = ccs.curCampaign; | ||
294 | |||
295 | /** @todo ccs.XVIShowMap should not be enabled at the same time than | ||
296 | * CP_IsXVIResearched(): ccs.XVIShowMap means that PHALANX has a map of | ||
297 | * XVI, whereas CP_IsXVIResearched() means that aliens started | ||
298 | * spreading XVI */ | ||
299 | ccs.XVIShowMap = true; | ||
300 | |||
301 | /* Spawn a few alien bases depending on difficulty level */ | ||
302 | if (campaign->difficulty > 0) | ||
303 | numAlienBases = 3; | ||
304 | else if (campaign->difficulty < 0) | ||
305 | numAlienBases = 1; | ||
306 | else | ||
307 | numAlienBases = 2; | ||
308 | |||
309 | for (i = 0; i < numAlienBases; i++) | ||
310 | CP_CreateNewMission(INTERESTCATEGORY_BUILDING, false); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * @brief This will hide or show the geoscape button for handling the xvi overlay map | ||
315 | */ | ||
316 | void CP_UpdateXVIMapButton (void) | ||
317 | { | ||
318 | Cvar_SetValue("mn_xvimap", ccs.XVIShowMap); | ||
319 | } |