1 /***************************************************************************
2 * Mechanized Assault and Exploration Reloaded Projectfile *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20 /* Author: Paul Grathwohl */
21
22 #include "game/logic/upgradecalculator.h"
23 #include "utility/log.h"
24 #include "main.h"
25 #include "game/data/units/unitdata.h"
26 #include <sstream>
27
28 //--------------------------------------------------
instance()29 cUpgradeCalculator& cUpgradeCalculator::instance()
30 {
31 static cUpgradeCalculator _instance;
32 // do the setup on the first call, not on startup of the program
33 if (!_instance.setupDone)
34 _instance.setupLookupTables();
35 return _instance;
36 }
37
38 //--------------------------------------------------
cUpgradeCalculator()39 cUpgradeCalculator::cUpgradeCalculator()
40 : setupDone (false)
41 {}
42
43 //--------------------------------------------------
setupLookupTables()44 void cUpgradeCalculator::setupLookupTables()
45 {
46 // ------------------------------ HITPOINTS and ARMOR and AMMO
47 hitpointsArmorAmmo_2 [2] = 39;
48 hitpointsArmorAmmo_2 [3] = 321;
49
50 hitpointsArmorAmmo_4 [4] = 8;
51 hitpointsArmorAmmo_4 [5] = 31;
52 hitpointsArmorAmmo_4 [6] = 91;
53 hitpointsArmorAmmo_4 [7] = 230;
54 hitpointsArmorAmmo_4 [8] = 513;
55
56 hitpointsArmorAmmo_6 [6] = 4;
57 hitpointsArmorAmmo_6 [7] = 11;
58 hitpointsArmorAmmo_6 [8] = 24;
59 hitpointsArmorAmmo_6 [9] = 51;
60 hitpointsArmorAmmo_6 [10] = 96;
61 hitpointsArmorAmmo_6 [11] = 174;
62 hitpointsArmorAmmo_6 [12] = 297;
63 hitpointsArmorAmmo_6 [13] = 491;
64 hitpointsArmorAmmo_6 [14] = 780;
65
66 hitpointsArmorAmmo_7 [7] = 3;
67 hitpointsArmorAmmo_7 [8] = 8;
68 hitpointsArmorAmmo_7 [9] = 16;
69 hitpointsArmorAmmo_7 [10] = 30;
70 hitpointsArmorAmmo_7 [11] = 54;
71 hitpointsArmorAmmo_7 [12] = 94;
72 hitpointsArmorAmmo_7 [13] = 155;
73 hitpointsArmorAmmo_7 [14] = 245;
74 hitpointsArmorAmmo_7 [15] = 378;
75 hitpointsArmorAmmo_7 [16] = 567;
76
77 hitpointsArmorAmmo_8 [8] = 2;
78 hitpointsArmorAmmo_8 [9] = 6;
79 hitpointsArmorAmmo_8 [10] = 11;
80 hitpointsArmorAmmo_8 [11] = 20;
81 hitpointsArmorAmmo_8 [12] = 35;
82 hitpointsArmorAmmo_8 [13] = 56;
83 hitpointsArmorAmmo_8 [14] = 91;
84 hitpointsArmorAmmo_8 [15] = 139;
85 hitpointsArmorAmmo_8 [16] = 208;
86 hitpointsArmorAmmo_8 [17] = 305;
87 hitpointsArmorAmmo_8 [18] = 438;
88 hitpointsArmorAmmo_8 [19] = 617;
89
90 hitpointsArmorAmmo_9 [9] = 2;
91 hitpointsArmorAmmo_9 [10] = 5;
92 hitpointsArmorAmmo_9 [11] = 8;
93 hitpointsArmorAmmo_9 [12] = 14;
94 hitpointsArmorAmmo_9 [13] = 23;
95 hitpointsArmorAmmo_9 [14] = 38;
96 hitpointsArmorAmmo_9 [15] = 57;
97 hitpointsArmorAmmo_9 [16] = 86;
98 hitpointsArmorAmmo_9 [17] = 127;
99 hitpointsArmorAmmo_9 [18] = 181;
100 hitpointsArmorAmmo_9 [19] = 254;
101 hitpointsArmorAmmo_9 [20] = 353;
102 hitpointsArmorAmmo_9 [21] = 480;
103 hitpointsArmorAmmo_9 [22] = 645;
104
105 hitpointsArmorAmmo_10 [10] = 5;
106 hitpointsArmorAmmo_10 [12] = 17;
107 hitpointsArmorAmmo_10 [14] = 43;
108 hitpointsArmorAmmo_10 [16] = 97;
109 hitpointsArmorAmmo_10 [18] = 198;
110 hitpointsArmorAmmo_10 [20] = 377;
111 hitpointsArmorAmmo_10 [22] = 682;
112
113 hitpointsArmorAmmo_12 [12] = 4;
114 hitpointsArmorAmmo_12 [14] = 11;
115 hitpointsArmorAmmo_12 [16] = 24;
116 hitpointsArmorAmmo_12 [18] = 51;
117 hitpointsArmorAmmo_12 [20] = 96;
118 hitpointsArmorAmmo_12 [22] = 174;
119 hitpointsArmorAmmo_12 [24] = 297;
120 hitpointsArmorAmmo_12 [26] = 491;
121 hitpointsArmorAmmo_12 [28] = 780;
122
123 hitpointsArmorAmmo_14 [14] = 3;
124 hitpointsArmorAmmo_14 [16] = 8;
125 hitpointsArmorAmmo_14 [18] = 16;
126 hitpointsArmorAmmo_14 [20] = 30;
127 hitpointsArmorAmmo_14 [22] = 54;
128 hitpointsArmorAmmo_14 [24] = 94;
129 hitpointsArmorAmmo_14 [26] = 155;
130 hitpointsArmorAmmo_14 [28] = 245;
131 hitpointsArmorAmmo_14 [30] = 378;
132 hitpointsArmorAmmo_14 [32] = 567;
133
134 hitpointsArmorAmmo_16 [16] = 2;
135 hitpointsArmorAmmo_16 [18] = 6;
136 hitpointsArmorAmmo_16 [20] = 11;
137 hitpointsArmorAmmo_16 [22] = 20;
138 hitpointsArmorAmmo_16 [24] = 35;
139 hitpointsArmorAmmo_16 [26] = 56;
140 hitpointsArmorAmmo_16 [28] = 91;
141 hitpointsArmorAmmo_16 [30] = 139;
142 hitpointsArmorAmmo_16 [32] = 208;
143 hitpointsArmorAmmo_16 [34] = 305;
144 hitpointsArmorAmmo_16 [36] = 438;
145 hitpointsArmorAmmo_16 [38] = 617;
146
147 hitpointsArmorAmmo_18 [18] = 2;
148 hitpointsArmorAmmo_18 [20] = 5;
149 hitpointsArmorAmmo_18 [22] = 8;
150 hitpointsArmorAmmo_18 [24] = 14;
151 hitpointsArmorAmmo_18 [26] = 23;
152 hitpointsArmorAmmo_18 [28] = 38;
153 hitpointsArmorAmmo_18 [30] = 57;
154 hitpointsArmorAmmo_18 [32] = 86;
155 hitpointsArmorAmmo_18 [34] = 127;
156 hitpointsArmorAmmo_18 [36] = 181;
157 hitpointsArmorAmmo_18 [38] = 254;
158 hitpointsArmorAmmo_18 [40] = 353;
159 hitpointsArmorAmmo_18 [42] = 480;
160 hitpointsArmorAmmo_18 [44] = 645;
161
162 hitpointsArmorAmmo_20 [20] = 2;
163 hitpointsArmorAmmo_20 [22] = 3;
164 hitpointsArmorAmmo_20 [24] = 7;
165 hitpointsArmorAmmo_20 [26] = 10;
166 hitpointsArmorAmmo_20 [28] = 17;
167 hitpointsArmorAmmo_20 [30] = 26;
168 hitpointsArmorAmmo_20 [32] = 40;
169 hitpointsArmorAmmo_20 [34] = 57;
170 hitpointsArmorAmmo_20 [36] = 82;
171 hitpointsArmorAmmo_20 [38] = 116;
172 hitpointsArmorAmmo_20 [40] = 160;
173 hitpointsArmorAmmo_20 [42] = 217;
174 hitpointsArmorAmmo_20 [44] = 293;
175 hitpointsArmorAmmo_20 [46] = 389;
176 hitpointsArmorAmmo_20 [48] = 509;
177 hitpointsArmorAmmo_20 [50] = 660;
178
179 hitpointsArmorAmmo_24 [24] = 1;
180 hitpointsArmorAmmo_24 [26] = 3;
181 hitpointsArmorAmmo_24 [28] = 4;
182 hitpointsArmorAmmo_24 [30] = 7;
183 hitpointsArmorAmmo_24 [32] = 10;
184 hitpointsArmorAmmo_24 [34] = 14;
185 hitpointsArmorAmmo_24 [36] = 21;
186 hitpointsArmorAmmo_24 [38] = 30;
187 hitpointsArmorAmmo_24 [40] = 40;
188 hitpointsArmorAmmo_24 [42] = 56;
189 hitpointsArmorAmmo_24 [44] = 75;
190 hitpointsArmorAmmo_24 [46] = 99;
191 hitpointsArmorAmmo_24 [48] = 129;
192 hitpointsArmorAmmo_24 [50] = 168;
193 hitpointsArmorAmmo_24 [52] = 216;
194 hitpointsArmorAmmo_24 [54] = 275;
195 hitpointsArmorAmmo_24 [56] = 346;
196 hitpointsArmorAmmo_24 [58] = 434;
197 hitpointsArmorAmmo_24 [60] = 538;
198 hitpointsArmorAmmo_24 [62] = 663;
199
200 hitpointsArmorAmmo_26 [26] = 5;
201 hitpointsArmorAmmo_26 [31] = 15;
202 hitpointsArmorAmmo_26 [36] = 38;
203 hitpointsArmorAmmo_26 [41] = 84;
204 hitpointsArmorAmmo_26 [46] = 168;
205 hitpointsArmorAmmo_26 [51] = 319;
206 hitpointsArmorAmmo_26 [56] = 567;
207
208 hitpointsArmorAmmo_28 [28] = 4;
209 hitpointsArmorAmmo_28 [33] = 13;
210 hitpointsArmorAmmo_28 [38] = 30;
211 hitpointsArmorAmmo_28 [43] = 64;
212 hitpointsArmorAmmo_28 [48] = 126;
213 hitpointsArmorAmmo_28 [53] = 232;
214 hitpointsArmorAmmo_28 [58] = 404;
215 hitpointsArmorAmmo_28 [63] = 677;
216
217 hitpointsArmorAmmo_32 [32] = 3;
218 hitpointsArmorAmmo_32 [37] = 10;
219 hitpointsArmorAmmo_32 [42] = 20;
220 hitpointsArmorAmmo_32 [47] = 41;
221 hitpointsArmorAmmo_32 [52] = 75;
222 hitpointsArmorAmmo_32 [57] = 134;
223 hitpointsArmorAmmo_32 [62] = 225;
224 hitpointsArmorAmmo_32 [67] = 365;
225 hitpointsArmorAmmo_32 [72] = 574;
226
227 hitpointsArmorAmmo_36 [36] = 3;
228 hitpointsArmorAmmo_36 [41] = 7;
229 hitpointsArmorAmmo_36 [46] = 15;
230 hitpointsArmorAmmo_36 [51] = 27;
231 hitpointsArmorAmmo_36 [56] = 50;
232 hitpointsArmorAmmo_36 [61] = 84;
233 hitpointsArmorAmmo_36 [66] = 137;
234 hitpointsArmorAmmo_36 [71] = 218;
235 hitpointsArmorAmmo_36 [76] = 332;
236 hitpointsArmorAmmo_36 [81] = 497;
237 hitpointsArmorAmmo_36 [86] = 724;
238
239 hitpointsArmorAmmo_40 [40] = 2;
240 hitpointsArmorAmmo_40 [45] = 6;
241 hitpointsArmorAmmo_40 [50] = 11;
242 hitpointsArmorAmmo_40 [55] = 20;
243 hitpointsArmorAmmo_40 [60] = 35;
244 hitpointsArmorAmmo_40 [65] = 56;
245 hitpointsArmorAmmo_40 [70] = 91;
246 hitpointsArmorAmmo_40 [75] = 139;
247 hitpointsArmorAmmo_40 [80] = 208;
248 hitpointsArmorAmmo_40 [85] = 305;
249 hitpointsArmorAmmo_40 [90] = 438;
250 hitpointsArmorAmmo_40 [95] = 617;
251
252 hitpointsArmorAmmo_56 [56] = 4;
253 hitpointsArmorAmmo_56 [66] = 13;
254 hitpointsArmorAmmo_56 [76] = 30;
255 hitpointsArmorAmmo_56 [86] = 64;
256 hitpointsArmorAmmo_56 [96] = 126;
257 hitpointsArmorAmmo_56 [106] = 232;
258 hitpointsArmorAmmo_56 [116] = 404;
259 hitpointsArmorAmmo_56 [126] = 677;
260
261
262 // ------------------------------ ATTACK and SPEED
263 attackSpeed_5 [5] = 11;
264 attackSpeed_5 [6] = 34;
265 attackSpeed_5 [7] = 86;
266 attackSpeed_5 [8] = 193;
267 attackSpeed_5 [9] = 396;
268 attackSpeed_5 [10] = 755;
269
270 attackSpeed_6 [6] = 8;
271 attackSpeed_6 [7] = 22;
272 attackSpeed_6 [8] = 49;
273 attackSpeed_6 [9] = 101;
274 attackSpeed_6 [10] = 193;
275 attackSpeed_6 [11] = 347;
276 attackSpeed_6 [12] = 595;
277
278 attackSpeed_7 [7] = 6;
279 attackSpeed_7 [8] = 16;
280 attackSpeed_7 [9] = 32;
281 attackSpeed_7 [10] = 60;
282 attackSpeed_7 [11] = 109;
283 attackSpeed_7 [12] = 188;
284 attackSpeed_7 [13] = 309;
285 attackSpeed_7 [14] = 490;
286 attackSpeed_7 [15] = 757;
287
288 attackSpeed_8 [8] = 5;
289 attackSpeed_8 [9] = 12;
290 attackSpeed_8 [10] = 22;
291 attackSpeed_8 [11] = 40;
292 attackSpeed_8 [12] = 69;
293 attackSpeed_8 [13] = 113;
294 attackSpeed_8 [14] = 181;
295 attackSpeed_8 [15] = 278;
296 attackSpeed_8 [16] = 416;
297 attackSpeed_8 [17] = 611;
298
299 attackSpeed_9 [9] = 4;
300 attackSpeed_9 [10] = 10;
301 attackSpeed_9 [11] = 16;
302 attackSpeed_9 [12] = 29;
303 attackSpeed_9 [13] = 46;
304 attackSpeed_9 [14] = 75;
305 attackSpeed_9 [15] = 115;
306 attackSpeed_9 [16] = 172;
307 attackSpeed_9 [17] = 253;
308 attackSpeed_9 [18] = 362;
309 attackSpeed_9 [19] = 509;
310 attackSpeed_9 [20] = 705;
311
312 attackSpeed_10 [10] = 11;
313 attackSpeed_10 [12] = 34;
314 attackSpeed_10 [14] = 86;
315 attackSpeed_10 [16] = 193;
316 attackSpeed_10 [18] = 396;
317 attackSpeed_10 [20] = 755;
318
319 attackSpeed_11 [11] = 10;
320 attackSpeed_11 [13] = 26;
321 attackSpeed_11 [15] = 64;
322 attackSpeed_11 [17] = 137;
323 attackSpeed_11 [19] = 269;
324 attackSpeed_11 [21] = 500;
325
326 attackSpeed_12 [12] = 8;
327 attackSpeed_12 [14] = 22;
328 attackSpeed_12 [16] = 49;
329 attackSpeed_12 [18] = 101;
330 attackSpeed_12 [20] = 193;
331 attackSpeed_12 [22] = 347;
332 attackSpeed_12 [24] = 595;
333
334 attackSpeed_14 [14] = 6;
335 attackSpeed_14 [16] = 16;
336 attackSpeed_14 [18] = 32;
337 attackSpeed_14 [20] = 60;
338 attackSpeed_14 [22] = 109;
339 attackSpeed_14 [24] = 188;
340 attackSpeed_14 [26] = 309;
341 attackSpeed_14 [28] = 490;
342 attackSpeed_14 [30] = 757;
343
344 attackSpeed_15 [15] = 6;
345 attackSpeed_15 [17] = 13;
346 attackSpeed_15 [19] = 26;
347 attackSpeed_15 [21] = 49;
348 attackSpeed_15 [23] = 86;
349 attackSpeed_15 [25] = 144;
350 attackSpeed_15 [27] = 233;
351 attackSpeed_15 [29] = 364;
352 attackSpeed_15 [31] = 554;
353
354 attackSpeed_16 [16] = 5;
355 attackSpeed_16 [18] = 12;
356 attackSpeed_16 [20] = 22;
357 attackSpeed_16 [22] = 40;
358 attackSpeed_16 [24] = 69;
359 attackSpeed_16 [26] = 113;
360 attackSpeed_16 [28] = 181;
361 attackSpeed_16 [30] = 278;
362 attackSpeed_16 [32] = 416;
363 attackSpeed_16 [34] = 611;
364
365 attackSpeed_17 [17] = 5;
366 attackSpeed_17 [19] = 10;
367 attackSpeed_17 [21] = 19;
368 attackSpeed_17 [23] = 34;
369 attackSpeed_17 [25] = 56;
370 attackSpeed_17 [27] = 91;
371 attackSpeed_17 [29] = 143;
372 attackSpeed_17 [31] = 216;
373 attackSpeed_17 [33] = 321;
374 attackSpeed_17 [35] = 466;
375 attackSpeed_17 [37] = 661;
376
377 attackSpeed_18 [18] = 4;
378 attackSpeed_18 [20] = 10;
379 attackSpeed_18 [22] = 16;
380 attackSpeed_18 [24] = 29;
381 attackSpeed_18 [26] = 46;
382 attackSpeed_18 [28] = 75;
383 attackSpeed_18 [30] = 115;
384 attackSpeed_18 [32] = 172;
385 attackSpeed_18 [34] = 253;
386 attackSpeed_18 [36] = 362;
387 attackSpeed_18 [38] = 509;
388 attackSpeed_18 [40] = 705;
389
390 attackSpeed_20 [20] = 4;
391 attackSpeed_20 [22] = 7;
392 attackSpeed_20 [24] = 13;
393 attackSpeed_20 [26] = 21;
394 attackSpeed_20 [28] = 34;
395 attackSpeed_20 [30] = 52;
396 attackSpeed_20 [32] = 79;
397 attackSpeed_20 [34] = 114;
398 attackSpeed_20 [36] = 164;
399 attackSpeed_20 [38] = 232;
400 attackSpeed_20 [40] = 320;
401 attackSpeed_20 [42] = 435;
402 attackSpeed_20 [44] = 586;
403 attackSpeed_20 [46] = 777;
404
405 attackSpeed_22 [22] = 3;
406 attackSpeed_22 [24] = 7;
407 attackSpeed_22 [26] = 10;
408 attackSpeed_22 [28] = 16;
409 attackSpeed_22 [30] = 26;
410 attackSpeed_22 [32] = 38;
411 attackSpeed_22 [34] = 56;
412 attackSpeed_22 [36] = 81;
413 attackSpeed_22 [38] = 113;
414 attackSpeed_22 [40] = 156;
415 attackSpeed_22 [42] = 214;
416 attackSpeed_22 [44] = 286;
417 attackSpeed_22 [46] = 380;
418 attackSpeed_22 [48] = 498;
419 attackSpeed_22 [50] = 646;
420
421 attackSpeed_24 [24] = 3;
422 attackSpeed_24 [26] = 5;
423 attackSpeed_24 [28] = 9;
424 attackSpeed_24 [30] = 13;
425 attackSpeed_24 [32] = 20;
426 attackSpeed_24 [34] = 29;
427 attackSpeed_24 [36] = 42;
428 attackSpeed_24 [38] = 59;
429 attackSpeed_24 [40] = 81;
430 attackSpeed_24 [42] = 112;
431 attackSpeed_24 [44] = 149;
432 attackSpeed_24 [46] = 198;
433 attackSpeed_24 [48] = 259;
434 attackSpeed_24 [50] = 336;
435 attackSpeed_24 [52] = 432;
436 attackSpeed_24 [54] = 549;
437 attackSpeed_24 [56] = 693;
438
439 attackSpeed_28 [28] = 9;
440 attackSpeed_28 [33] = 26;
441 attackSpeed_28 [38] = 60;
442 attackSpeed_28 [43] = 128;
443 attackSpeed_28 [48] = 252;
444 attackSpeed_28 [53] = 463;
445
446 attackSpeed_30 [30] = 8;
447 attackSpeed_30 [35] = 22;
448 attackSpeed_30 [40] = 49;
449 attackSpeed_30 [45] = 101;
450 attackSpeed_30 [50] = 193;
451 attackSpeed_30 [55] = 347;
452 attackSpeed_30 [60] = 595;
453
454 attackSpeed_36 [36] = 6;
455 attackSpeed_36 [41] = 15;
456 attackSpeed_36 [46] = 29;
457 attackSpeed_36 [51] = 55;
458 attackSpeed_36 [56] = 99;
459 attackSpeed_36 [61] = 169;
460 attackSpeed_36 [66] = 274;
461 attackSpeed_36 [71] = 435;
462 attackSpeed_36 [76] = 665;
463
464
465 // ------------------------------ RANGE and SCAN
466 rangeScan_3 [3] = 61;
467 rangeScan_3 [4] = 299;
468
469 rangeScan_4 [4] = 34;
470 rangeScan_4 [5] = 125;
471 rangeScan_4 [6] = 364;
472
473 rangeScan_5 [5] = 23;
474 rangeScan_5 [6] = 68;
475 rangeScan_5 [7] = 172;
476 rangeScan_5 [8] = 386;
477 rangeScan_5 [9] = 791;
478
479 rangeScan_6 [6] = 17;
480 rangeScan_6 [7] = 44;
481 rangeScan_6 [8] = 98;
482 rangeScan_6 [9] = 201;
483 rangeScan_6 [10] = 386;
484 rangeScan_6 [11] = 694;
485
486 rangeScan_7 [7] = 13;
487 rangeScan_7 [8] = 31;
488 rangeScan_7 [9] = 64;
489 rangeScan_7 [10] = 121;
490 rangeScan_7 [11] = 218;
491 rangeScan_7 [12] = 375;
492 rangeScan_7 [13] = 618;
493
494 rangeScan_8 [8] = 11;
495 rangeScan_8 [9] = 23;
496 rangeScan_8 [10] = 45;
497 rangeScan_8 [11] = 80;
498 rangeScan_8 [12] = 138;
499 rangeScan_8 [13] = 226;
500 rangeScan_8 [14] = 361;
501 rangeScan_8 [15] = 556;
502
503 rangeScan_9 [9] = 9;
504 rangeScan_9 [10] = 19;
505 rangeScan_9 [11] = 33;
506 rangeScan_9 [12] = 57;
507 rangeScan_9 [13] = 93;
508 rangeScan_9 [14] = 149;
509 rangeScan_9 [15] = 230;
510 rangeScan_9 [16] = 345;
511 rangeScan_9 [17] = 505;
512 rangeScan_9 [18] = 724;
513
514 rangeScan_10 [10] = 23;
515 rangeScan_10 [12] = 68;
516 rangeScan_10 [14] = 172;
517 rangeScan_10 [16] = 386;
518 rangeScan_10 [18] = 791;
519
520 rangeScan_11 [11] = 20;
521 rangeScan_11 [13] = 53;
522 rangeScan_11 [15] = 128;
523 rangeScan_11 [17] = 273;
524 rangeScan_11 [19] = 539;
525
526 rangeScan_12 [12] = 17;
527 rangeScan_12 [14] = 44;
528 rangeScan_12 [16] = 98;
529 rangeScan_12 [18] = 201;
530 rangeScan_12 [20] = 386;
531 rangeScan_12 [22] = 694;
532
533 rangeScan_14 [14] = 13;
534 rangeScan_14 [16] = 31;
535 rangeScan_14 [18] = 64;
536 rangeScan_14 [20] = 121;
537 rangeScan_14 [22] = 218;
538 rangeScan_14 [24] = 375;
539 rangeScan_14 [26] = 618;
540
541 rangeScan_16 [16] = 11;
542 rangeScan_16 [18] = 23;
543 rangeScan_16 [20] = 45;
544 rangeScan_16 [22] = 80;
545 rangeScan_16 [24] = 138;
546 rangeScan_16 [26] = 226;
547 rangeScan_16 [28] = 361;
548 rangeScan_16 [30] = 556;
549
550 rangeScan_18 [18] = 9;
551 rangeScan_18 [20] = 19;
552 rangeScan_18 [22] = 33;
553 rangeScan_18 [24] = 57;
554 rangeScan_18 [26] = 93;
555 rangeScan_18 [28] = 149;
556 rangeScan_18 [30] = 230;
557 rangeScan_18 [32] = 345;
558 rangeScan_18 [34] = 505;
559 rangeScan_18 [36] = 724;
560
561 rangeScan_20 [20] = 8;
562 rangeScan_20 [22] = 15;
563 rangeScan_20 [24] = 26;
564 rangeScan_20 [26] = 42;
565 rangeScan_20 [28] = 68;
566 rangeScan_20 [30] = 104;
567 rangeScan_20 [32] = 157;
568 rangeScan_20 [34] = 229;
569 rangeScan_20 [36] = 328;
570 rangeScan_20 [38] = 463;
571 rangeScan_20 [40] = 640;
572
573 rangeScan_24 [24] = 6;
574 rangeScan_24 [26] = 11;
575 rangeScan_24 [28] = 17;
576 rangeScan_24 [30] = 27;
577 rangeScan_24 [32] = 40;
578 rangeScan_24 [34] = 58;
579 rangeScan_24 [36] = 84;
580 rangeScan_24 [38] = 117;
581 rangeScan_24 [40] = 163;
582 rangeScan_24 [42] = 223;
583 rangeScan_24 [44] = 298;
584 rangeScan_24 [46] = 396;
585 rangeScan_24 [48] = 518;
586 rangeScan_24 [50] = 673;
587
588 // ------------------------------ SHOTS
589 shots_1 [1] = 720;
590
591 shots_2 [2] = 79;
592 shots_2 [3] = 641;
593
594 // finished....
595 setupDone = true;
596 }
597
598 //--------------------------------------------------
lookupPrice(const PriceMap & prices,int value) const599 int cUpgradeCalculator::lookupPrice (const PriceMap& prices, int value) const
600 {
601 PriceMap::const_iterator it = prices.find (value);
602 if (it != prices.end())
603 return it->second; // the price
604 return kNoPriceAvailable;
605 }
606
607 //--------------------------------------------------
calcPrice(int curValue,int orgValue,int upgradeType,const cResearch & researchLevel) const608 int cUpgradeCalculator::calcPrice (int curValue, int orgValue, int upgradeType, const cResearch& researchLevel) const
609 {
610 int bonusByResearch = calcChangeByResearch (orgValue, researchLevel.getCurResearchLevel (researchLevel.getResearchArea (upgradeType)));
611 curValue -= bonusByResearch;
612
613 int price = kNoPriceAvailable;
614 switch (upgradeType)
615 {
616
617 case kHitpoints:
618 case kArmor:
619 case kAmmo:
620 {
621 switch (orgValue)
622 {
623 case 2: price = lookupPrice (hitpointsArmorAmmo_2, curValue); break;
624 case 4: price = lookupPrice (hitpointsArmorAmmo_4, curValue); break;
625 case 6: price = lookupPrice (hitpointsArmorAmmo_6, curValue); break;
626 case 7: price = lookupPrice (hitpointsArmorAmmo_7, curValue); break;
627 case 8: price = lookupPrice (hitpointsArmorAmmo_8, curValue); break;
628 case 9: price = lookupPrice (hitpointsArmorAmmo_9, curValue); break;
629 case 10: price = lookupPrice (hitpointsArmorAmmo_10, curValue); break;
630 case 12: price = lookupPrice (hitpointsArmorAmmo_12, curValue); break;
631 case 14: price = lookupPrice (hitpointsArmorAmmo_14, curValue); break;
632 case 16: price = lookupPrice (hitpointsArmorAmmo_16, curValue); break;
633 case 18: price = lookupPrice (hitpointsArmorAmmo_18, curValue); break;
634 case 20: price = lookupPrice (hitpointsArmorAmmo_20, curValue); break;
635 case 24: price = lookupPrice (hitpointsArmorAmmo_24, curValue); break;
636 case 26: price = lookupPrice (hitpointsArmorAmmo_26, curValue); break;
637 case 28: price = lookupPrice (hitpointsArmorAmmo_28, curValue); break;
638 case 32: price = lookupPrice (hitpointsArmorAmmo_32, curValue); break;
639 case 36: price = lookupPrice (hitpointsArmorAmmo_36, curValue); break;
640 case 40: price = lookupPrice (hitpointsArmorAmmo_40, curValue); break;
641 case 56: price = lookupPrice (hitpointsArmorAmmo_56, curValue); break;
642 default: break;
643 }
644 break;
645 }
646
647 case kAttack:
648 case kSpeed:
649 {
650 switch (orgValue)
651 {
652 case 5: price = lookupPrice (attackSpeed_5, curValue); break;
653 case 6: price = lookupPrice (attackSpeed_6, curValue); break;
654 case 7: price = lookupPrice (attackSpeed_7, curValue); break;
655 case 8: price = lookupPrice (attackSpeed_8, curValue); break;
656 case 9: price = lookupPrice (attackSpeed_9, curValue); break;
657 case 10: price = lookupPrice (attackSpeed_10, curValue); break;
658 case 11: price = lookupPrice (attackSpeed_11, curValue); break;
659 case 12: price = lookupPrice (attackSpeed_12, curValue); break;
660 case 14: price = lookupPrice (attackSpeed_14, curValue); break;
661 case 15: price = lookupPrice (attackSpeed_15, curValue); break;
662 case 16: price = lookupPrice (attackSpeed_16, curValue); break;
663 case 17: price = lookupPrice (attackSpeed_17, curValue); break;
664 case 18: price = lookupPrice (attackSpeed_18, curValue); break;
665 case 20: price = lookupPrice (attackSpeed_20, curValue); break;
666 case 22: price = lookupPrice (attackSpeed_22, curValue); break;
667 case 24: price = lookupPrice (attackSpeed_24, curValue); break;
668 case 28: price = lookupPrice (attackSpeed_28, curValue); break;
669 case 30: price = lookupPrice (attackSpeed_30, curValue); break;
670 case 36: price = lookupPrice (attackSpeed_36, curValue); break;
671 default: break;
672 }
673 break;
674 }
675
676 case kRange:
677 case kScan:
678 {
679 switch (orgValue)
680 {
681 case 3: price = lookupPrice (rangeScan_3, curValue); break;
682 case 4: price = lookupPrice (rangeScan_4, curValue); break;
683 case 5: price = lookupPrice (rangeScan_5, curValue); break;
684 case 6: price = lookupPrice (rangeScan_6, curValue); break;
685 case 7: price = lookupPrice (rangeScan_7, curValue); break;
686 case 8: price = lookupPrice (rangeScan_8, curValue); break;
687 case 9: price = lookupPrice (rangeScan_9, curValue); break;
688 case 10: price = lookupPrice (rangeScan_10, curValue); break;
689 case 11: price = lookupPrice (rangeScan_11, curValue); break;
690 case 12: price = lookupPrice (rangeScan_12, curValue); break;
691 case 14: price = lookupPrice (rangeScan_14, curValue); break;
692 case 16: price = lookupPrice (rangeScan_16, curValue); break;
693 case 18: price = lookupPrice (rangeScan_18, curValue); break;
694 case 20: price = lookupPrice (rangeScan_20, curValue); break;
695 case 24: price = lookupPrice (rangeScan_24, curValue); break;
696 default: break;
697 }
698 break;
699 }
700
701 case kShots:
702 {
703 switch (orgValue)
704 {
705 case 1: price = lookupPrice (shots_1, curValue); break;
706 case 2: price = lookupPrice (shots_2, curValue); break;
707 default: break;
708 }
709 break;
710 }
711
712 default: break;
713 }
714 return price;
715 }
716
717 //--------------------------------------------------
getCostForUpgrade(int orgValue,int curValue,int newValue,int upgradeType,cResearch & researchLevel) const718 int cUpgradeCalculator::getCostForUpgrade (int orgValue, int curValue, int newValue, int upgradeType, cResearch& researchLevel) const
719 {
720 int cost = 0;
721 if (orgValue <= curValue && curValue < newValue)
722 {
723 int upgradedValue = curValue;
724 while (upgradedValue < newValue)
725 {
726 int costsForThis = calcPrice (upgradedValue, orgValue, upgradeType, researchLevel);
727 if (costsForThis != kNoPriceAvailable)
728 {
729 cost += costsForThis;
730 upgradedValue += calcIncreaseByUpgrade (orgValue);
731 if (upgradedValue > newValue)
732 {
733 // it is not possible to reach the newValue with upgrading
734 return kNoPriceAvailable;
735 }
736 }
737 else
738 return kNoPriceAvailable;
739 }
740 }
741 return cost;
742 }
743
744 //--------------------------------------------------
calcResearchTurns(int curResearchLevel,int upgradeType) const745 int cUpgradeCalculator::calcResearchTurns (int curResearchLevel, int upgradeType) const
746 {
747 switch (upgradeType)
748 {
749 case kHitpoints:
750 case kArmor:
751 {
752 const unsigned int index = curResearchLevel / 10;
753 const int values[] =
754 {
755 8, 15, 25, 42, 67, 104, 156, 229, 328, 462,
756 639, 871, 1171, 1553, 2036, 2640, 3389, 4311, 5437, 6803,
757 8448
758 };
759
760 if (index < sizeof (values) / sizeof (*values))
761 return values[index];
762 break;
763 }
764
765 case kAttack:
766 case kSpeed:
767 case kShots:
768 {
769 const unsigned int index = curResearchLevel / 10;
770 const int values[] =
771 {
772 16, 30, 51, 85, 135, 208, 312, 458, 657, 924,
773 1278, 1742, 2342, 3106, 4072, 5280, 6778, 8622, 10874, 13606,
774 16896
775 };
776
777 if (index < sizeof (values) / sizeof (*values))
778 return values[index];
779 break;
780 }
781
782 case kRange:
783 case kScan:
784 case kCost:
785 {
786 const unsigned int index = curResearchLevel / 10;
787 const int values[] =
788 {
789 33, 60, 103, 170, 270, 416, 625, 916, 1314, 1849,
790 2559, 3487, 4684, 6213, 8144, 10560, 13556, 17244, 21748, 27212,
791 33792
792 };
793
794 if (index < sizeof (values) / sizeof (*values))
795 return values[index];
796 break;
797 }
798
799 // case kAmmo: <- There's no research possibility for Ammo in M.A.X.!
800 default: break;
801 }
802
803 return kNoResearchAvailable;
804 }
805
806 //--------------------------------------------------
calcIncreaseByUpgrade(int startValue) const807 int cUpgradeCalculator::calcIncreaseByUpgrade (int startValue) const
808 {
809 if (startValue < 10)
810 return 1;
811 if (startValue < 26)
812 return 2;
813 if (startValue < 56)
814 return 5;
815 return 10;
816 }
817
818 //--------------------------------------------------
calcChangeByResearch(int startValue,int curResearchLevel,int upgradeType,int unitType) const819 int cUpgradeCalculator::calcChangeByResearch (int startValue, int curResearchLevel,
820 int upgradeType, int unitType) const
821 {
822 if (curResearchLevel <= 0) // no research done yet...
823 return 0;
824
825 // standard research areas - all handled the same way
826 if (upgradeType == -1 || upgradeType != kCost)
827 {
828 // a simple integer division does the job
829 int newValue = (startValue * (100 + curResearchLevel)) / 100;
830 return newValue - startValue;
831 }
832 else if (upgradeType == kCost)
833 {
834 // cost makes a decrease based on the formula 1/x
835 // (where x is the research level)
836 float realCost = startValue / ((100.0f + curResearchLevel) / 100.0f);
837
838 // now the real cost is rounded to the next possible cost value
839 // (Unit factories: steps of 3,
840 // Building construction: steps of 2,
841 // Infantry training: steps of 1)
842 int costRounded = startValue;
843 if (unitType == kBuilding)
844 costRounded = getNearestPossibleCost (realCost, 2);
845 else if (unitType == kInfantry)
846 costRounded = getNearestPossibleCost (realCost, 1);
847 else if (unitType == kStandardUnit)
848 costRounded = getNearestPossibleCost (realCost, 3);
849
850 return costRounded - startValue;
851 }
852 else
853 return 0;
854 }
855
856 //--------------------------------------------------
getMaterialCostForUpgrading(int unitCost) const857 int cUpgradeCalculator::getMaterialCostForUpgrading (int unitCost) const
858 {
859 if (unitCost < 4)
860 return 0;
861 return unitCost / 4;
862 }
863
864 //--------------------------------------------------
getNearestPossibleCost(float realCost,int costDifference) const865 int cUpgradeCalculator::getNearestPossibleCost (float realCost, int costDifference) const
866 {
867 if (costDifference <= 0)
868 return (int) realCost;
869
870 int intCost = (int) realCost;
871 int nearestLowerCost = intCost - (intCost % costDifference);
872 int result;
873 if (realCost - nearestLowerCost < (costDifference / 2.0f))
874 result = nearestLowerCost;
875 else
876 result = nearestLowerCost + costDifference;
877 if (result <= 0) // a cost of zero or below is forbidden
878 result = costDifference;
879 return result;
880 }
881
882 //--------------------------------------------------
printAllToLog() const883 void cUpgradeCalculator::printAllToLog() const
884 {
885 printToLog ("CALC CHANGE BY RESEARCH TEST ---- CALC CHANGE BY RESEARCH TEST");
886
887 printToLog ("--------------- Cost-Research for Buildings ----------------");
888 printToLog ("Building-Cost: Start 40, Level 0 => Change: ", calcChangeByResearch (40, 0, kCost, kBuilding));
889 printToLog ("Building-Cost: Start 40, Level 10 => Change: ", calcChangeByResearch (40, 10, kCost, kBuilding));
890 printToLog ("Building-Cost: Start 40, Level 20 => Change: ", calcChangeByResearch (40, 20, kCost, kBuilding));
891 printToLog ("Building-Cost: Start 40, Level 30 => Change: ", calcChangeByResearch (40, 30, kCost, kBuilding));
892 printToLog ("Building-Cost: Start 40, Level 40 => Change: ", calcChangeByResearch (40, 40, kCost, kBuilding));
893 printToLog ("Building-Cost: Start 40, Level 50 => Change: ", calcChangeByResearch (40, 50, kCost, kBuilding));
894 printToLog ("Building-Cost: Start 40, Level 60 => Change: ", calcChangeByResearch (40, 60, kCost, kBuilding));
895 printToLog ("Building-Cost: Start 40, Level 70 => Change: ", calcChangeByResearch (40, 70, kCost, kBuilding));
896 printToLog ("Building-Cost: Start 40, Level 80 => Change: ", calcChangeByResearch (40, 80, kCost, kBuilding));
897 printToLog ("Building-Cost: Start 40, Level 90 => Change: ", calcChangeByResearch (40, 90, kCost, kBuilding));
898 printToLog ("Building-Cost: Start 40, Level 100 => Change: ", calcChangeByResearch (40, 100, kCost, kBuilding));
899 printToLog ("Building-Cost: Start 40, Level 110 => Change: ", calcChangeByResearch (40, 110, kCost, kBuilding));
900 printToLog ("Building-Cost: Start 40, Level 120 => Change: ", calcChangeByResearch (40, 120, kCost, kBuilding));
901 printToLog ("Building-Cost: Start 40, Level 130 => Change: ", calcChangeByResearch (40, 130, kCost, kBuilding));
902 printToLog ("Building-Cost: Start 40, Level 140 => Change: ", calcChangeByResearch (40, 140, kCost, kBuilding));
903 printToLog ("Building-Cost: Start 40, Level 150 => Change: ", calcChangeByResearch (40, 150, kCost, kBuilding));
904 printToLog ("Building-Cost: Start 40, Level 160 => Change: ", calcChangeByResearch (40, 160, kCost, kBuilding));
905 printToLog ("Building-Cost: Start 40, Level 170 => Change: ", calcChangeByResearch (40, 170, kCost, kBuilding));
906 printToLog ("Building-Cost: Start 40, Level 180 => Change: ", calcChangeByResearch (40, 180, kCost, kBuilding));
907 printToLog ("Building-Cost: Start 40, Level 190 => Change: ", calcChangeByResearch (40, 190, kCost, kBuilding));
908 printToLog ("Building-Cost: Start 40, Level 200 => Change: ", calcChangeByResearch (40, 200, kCost, kBuilding));
909 printToLog ("Building-Cost: Start 40, Level 210 => Change: ", calcChangeByResearch (40, 210, kCost, kBuilding));
910 printToLog ("Building-Cost: Start 40, Level 220 => Change: ", calcChangeByResearch (40, 220, kCost, kBuilding));
911
912 printToLog ("--------------- Cost-Research for Standard Units ----------------");
913 printToLog ("Unit-Cost: Start 24, Level 0 => Change: ", calcChangeByResearch (24, 0, kCost, kStandardUnit));
914 printToLog ("Unit-Cost: Start 24, Level 10 => Change: ", calcChangeByResearch (24, 10, kCost, kStandardUnit));
915 printToLog ("Unit-Cost: Start 24, Level 20 => Change: ", calcChangeByResearch (24, 20, kCost, kStandardUnit));
916 printToLog ("Unit-Cost: Start 24, Level 30 => Change: ", calcChangeByResearch (24, 30, kCost, kStandardUnit));
917 printToLog ("Unit-Cost: Start 24, Level 40 => Change: ", calcChangeByResearch (24, 40, kCost, kStandardUnit));
918 printToLog ("Unit-Cost: Start 24, Level 50 => Change: ", calcChangeByResearch (24, 50, kCost, kStandardUnit));
919 printToLog ("Unit-Cost: Start 24, Level 60 => Change: ", calcChangeByResearch (24, 60, kCost, kStandardUnit));
920 printToLog ("Unit-Cost: Start 24, Level 70 => Change: ", calcChangeByResearch (24, 70, kCost, kStandardUnit));
921 printToLog ("Unit-Cost: Start 24, Level 80 => Change: ", calcChangeByResearch (24, 80, kCost, kStandardUnit));
922 printToLog ("Unit-Cost: Start 24, Level 90 => Change: ", calcChangeByResearch (24, 90, kCost, kStandardUnit));
923 printToLog ("Unit-Cost: Start 24, Level 100 => Change: ", calcChangeByResearch (24, 100, kCost, kStandardUnit));
924 printToLog ("Unit-Cost: Start 24, Level 110 => Change: ", calcChangeByResearch (24, 110, kCost, kStandardUnit));
925 printToLog ("Unit-Cost: Start 24, Level 120 => Change: ", calcChangeByResearch (24, 120, kCost, kStandardUnit));
926 printToLog ("Unit-Cost: Start 24, Level 130 => Change: ", calcChangeByResearch (24, 130, kCost, kStandardUnit));
927 printToLog ("Unit-Cost: Start 24, Level 140 => Change: ", calcChangeByResearch (24, 140, kCost, kStandardUnit));
928 printToLog ("Unit-Cost: Start 24, Level 150 => Change: ", calcChangeByResearch (24, 150, kCost, kStandardUnit));
929 printToLog ("Unit-Cost: Start 24, Level 160 => Change: ", calcChangeByResearch (24, 160, kCost, kStandardUnit));
930 printToLog ("Unit-Cost: Start 24, Level 170 => Change: ", calcChangeByResearch (24, 170, kCost, kStandardUnit));
931 printToLog ("Unit-Cost: Start 24, Level 180 => Change: ", calcChangeByResearch (24, 180, kCost, kStandardUnit));
932 printToLog ("Unit-Cost: Start 24, Level 190 => Change: ", calcChangeByResearch (24, 190, kCost, kStandardUnit));
933 printToLog ("Unit-Cost: Start 24, Level 200 => Change: ", calcChangeByResearch (24, 200, kCost, kStandardUnit));
934 printToLog ("Unit-Cost: Start 24, Level 210 => Change: ", calcChangeByResearch (24, 210, kCost, kStandardUnit));
935 printToLog ("Unit-Cost: Start 24, Level 220 => Change: ", calcChangeByResearch (24, 220, kCost, kStandardUnit));
936
937 printToLog ("--------------- Cost-Research for Infantry ----------------");
938 printToLog ("Infantry-Cost: Start 9, Level 0 => Change: ", calcChangeByResearch (9, 0, kCost, kInfantry));
939 printToLog ("Infantry-Cost: Start 9, Level 10 => Change: ", calcChangeByResearch (9, 10, kCost, kInfantry));
940 printToLog ("Infantry-Cost: Start 9, Level 20 => Change: ", calcChangeByResearch (9, 20, kCost, kInfantry));
941 printToLog ("Infantry-Cost: Start 9, Level 30 => Change: ", calcChangeByResearch (9, 30, kCost, kInfantry));
942 printToLog ("Infantry-Cost: Start 9, Level 40 => Change: ", calcChangeByResearch (9, 40, kCost, kInfantry));
943 printToLog ("Infantry-Cost: Start 9, Level 50 => Change: ", calcChangeByResearch (9, 50, kCost, kInfantry));
944 printToLog ("Infantry-Cost: Start 9, Level 60 => Change: ", calcChangeByResearch (9, 60, kCost, kInfantry));
945 printToLog ("Infantry-Cost: Start 9, Level 70 => Change: ", calcChangeByResearch (9, 70, kCost, kInfantry));
946 printToLog ("Infantry-Cost: Start 9, Level 80 => Change: ", calcChangeByResearch (9, 80, kCost, kInfantry));
947 printToLog ("Infantry-Cost: Start 9, Level 90 => Change: ", calcChangeByResearch (9, 90, kCost, kInfantry));
948 printToLog ("Infantry-Cost: Start 9, Level 100 => Change: ", calcChangeByResearch (9, 100, kCost, kInfantry));
949 printToLog ("Infantry-Cost: Start 9, Level 110 => Change: ", calcChangeByResearch (9, 110, kCost, kInfantry));
950 printToLog ("Infantry-Cost: Start 9, Level 120 => Change: ", calcChangeByResearch (9, 120, kCost, kInfantry));
951 printToLog ("Infantry-Cost: Start 9, Level 130 => Change: ", calcChangeByResearch (9, 130, kCost, kInfantry));
952 printToLog ("Infantry-Cost: Start 9, Level 140 => Change: ", calcChangeByResearch (9, 140, kCost, kInfantry));
953 printToLog ("Infantry-Cost: Start 9, Level 150 => Change: ", calcChangeByResearch (9, 150, kCost, kInfantry));
954 printToLog ("Infantry-Cost: Start 9, Level 160 => Change: ", calcChangeByResearch (9, 160, kCost, kInfantry));
955 printToLog ("Infantry-Cost: Start 9, Level 170 => Change: ", calcChangeByResearch (9, 170, kCost, kInfantry));
956 printToLog ("Infantry-Cost: Start 9, Level 180 => Change: ", calcChangeByResearch (9, 180, kCost, kInfantry));
957 printToLog ("Infantry-Cost: Start 9, Level 190 => Change: ", calcChangeByResearch (9, 190, kCost, kInfantry));
958 printToLog ("Infantry-Cost: Start 9, Level 200 => Change: ", calcChangeByResearch (9, 200, kCost, kInfantry));
959 printToLog ("Infantry-Cost: Start 9, Level 210 => Change: ", calcChangeByResearch (9, 210, kCost, kInfantry));
960 printToLog ("Infantry-Cost: Start 9, Level 220 => Change: ", calcChangeByResearch (9, 220, kCost, kInfantry));
961
962 printToLog ("--------------- Upgrade-Research (e.g. Armor) ----------------");
963 printToLog ("Normal-Research: Start 12, Level 0 => Change: ", calcChangeByResearch (12, 0));
964 printToLog ("Normal-Research: Start 12, Level 10 => Change: ", calcChangeByResearch (12, 10));
965 printToLog ("Normal-Research: Start 12, Level 20 => Change: ", calcChangeByResearch (12, 20));
966 printToLog ("Normal-Research: Start 12, Level 30 => Change: ", calcChangeByResearch (12, 30));
967 printToLog ("Normal-Research: Start 12, Level 40 => Change: ", calcChangeByResearch (12, 40));
968 printToLog ("Normal-Research: Start 12, Level 50 => Change: ", calcChangeByResearch (12, 50));
969 printToLog ("Normal-Research: Start 12, Level 60 => Change: ", calcChangeByResearch (12, 60));
970 printToLog ("Normal-Research: Start 12, Level 70 => Change: ", calcChangeByResearch (12, 70));
971 printToLog ("Normal-Research: Start 12, Level 80 => Change: ", calcChangeByResearch (12, 80));
972 printToLog ("Normal-Research: Start 12, Level 90 => Change: ", calcChangeByResearch (12, 90));
973 printToLog ("Normal-Research: Start 12, Level 100 => Change: ", calcChangeByResearch (12, 100));
974 printToLog ("Normal-Research: Start 12, Level 110 => Change: ", calcChangeByResearch (12, 110));
975 printToLog ("Normal-Research: Start 12, Level 120 => Change: ", calcChangeByResearch (12, 120));
976 printToLog ("Normal-Research: Start 12, Level 130 => Change: ", calcChangeByResearch (12, 130));
977 printToLog ("Normal-Research: Start 12, Level 140 => Change: ", calcChangeByResearch (12, 140));
978 printToLog ("Normal-Research: Start 12, Level 150 => Change: ", calcChangeByResearch (12, 150));
979 printToLog ("Normal-Research: Start 12, Level 160 => Change: ", calcChangeByResearch (12, 160));
980 printToLog ("Normal-Research: Start 12, Level 170 => Change: ", calcChangeByResearch (12, 170));
981 printToLog ("Normal-Research: Start 12, Level 180 => Change: ", calcChangeByResearch (12, 180));
982 printToLog ("Normal-Research: Start 12, Level 190 => Change: ", calcChangeByResearch (12, 190));
983 printToLog ("Normal-Research: Start 12, Level 200 => Change: ", calcChangeByResearch (12, 200));
984 printToLog ("Normal-Research: Start 12, Level 210 => Change: ", calcChangeByResearch (12, 210));
985 printToLog ("Normal-Research: Start 12, Level 220 => Change: ", calcChangeByResearch (12, 220));
986 }
987
988 //--------------------------------------------------
printToLog(const char * str,int value) const989 void cUpgradeCalculator::printToLog (const char* str, int value) const
990 {
991 if (value != -1000)
992 {
993 std::stringstream ss;
994 std::string printStr;
995 ss << value;
996 ss >> printStr;
997 printStr.insert (0, str);
998 Log.write (printStr, cLog::eLOG_TYPE_INFO);
999 }
1000 else
1001 Log.write (str, cLog::eLOG_TYPE_INFO);
1002 }
1003
1004
1005 #if 0
1006 // This is the old code (from JCK?) for calculating the upgrade cost.
1007 // Interesting is the formula used for calculating (although it doesn't produce
1008 // the exact same results - but nearly).
1009 // Maybe the formula could be used for interpolating costs for "non M.A.X." upgrades,
1010 // which are introduced by mods of M.A.X. Reloaded.
1011 {
1012 int tmp;
1013 double a, b, c;
1014 switch (upgradeKind)
1015 {
1016 // Treffer, Panzerung, Munition & Angriff
1017 case 0:
1018 switch (org)
1019 {
1020 case 2:
1021 if (value == 2) return 39;
1022 else return 321;
1023 break;
1024 case 4:
1025 a = 0.0016091639;
1026 b = -0.073815318;
1027 c = 6.0672869;
1028 break;
1029 case 6:
1030 a = 0.000034548596;
1031 b = -0.27217472;
1032 c = 6.3695123;
1033 break;
1034 case 8:
1035 a = 0.00037219059;
1036 b = 2.5148748;
1037 c = 5.0938608;
1038 break;
1039 case 9:
1040 a = 0.000059941694;
1041 b = 1.3962889;
1042 c = 4.6045196;
1043 break;
1044 case 10:
1045 a = 0.000033736018;
1046 b = 1.4674423;
1047 c = 5.5606209;
1048 break;
1049 case 12:
1050 a = 0.0000011574058;
1051 b = 0.23439586;
1052 c = 6.113616;
1053 break;
1054 case 14:
1055 a = 0.0000012483447;
1056 b = 1.4562373;
1057 c = 5.8250952;
1058 break;
1059 case 15:
1060 a = 0.00000018548742;
1061 b = -0.33519669;
1062 c = 6.3333527;
1063 break;
1064 case 16:
1065 a = 0.000010898263;
1066 b = 5.0297434;
1067 c = 5.0938627;
1068 break;
1069 case 18:
1070 a = 0.00000017182818;
1071 b = 2.0009536;
1072 c = 5.8937153;
1073 break;
1074 case 20:
1075 a = 0.00000004065782;
1076 b = 1.6533066;
1077 c = 6.0601538;
1078 break;
1079 case 22:
1080 a = 0.0000000076942857;
1081 b = -0.45461813;
1082 c = 6.4148588;
1083 break;
1084 case 24:
1085 a = 0.00000076484313;
1086 b = 8.0505377;
1087 c = 5.1465019;
1088 break;
1089 case 28:
1090 a = 0.00000015199858;
1091 b = 5.1528048;
1092 c = 5.4700225;
1093 break;
1094 case 32:
1095 a = 0.00000030797077;
1096 b = 8.8830596;
1097 c = 5.1409486;
1098 break;
1099 case 56:
1100 a = 0.000000004477053;
1101 b = 11.454622;
1102 c = 5.4335099;
1103 break;
1104 default:
1105 return 0;
1106 break;
1107 }
1108 break;
1109 // Geschwindgigkeit
1110 case 1:
1111 org = org / 4;
1112 value = value / 4;
1113 switch (org)
1114 {
1115 case 5:
1116 a = 0.00040716128;
1117 b = -0.16662054;
1118 c = 6.2234362;
1119 break;
1120 case 6:
1121 a = 0.00038548127;
1122 b = 0.48236948;
1123 c = 5.827724;
1124 break;
1125 case 7:
1126 a = 0.000019798772;
1127 b = -0.31204765;
1128 c = 6.3982628;
1129 break;
1130 case 9:
1131 a = 0.0000030681294;
1132 b = -0.25372812;
1133 c = 6.3995668;
1134 break;
1135 case 10:
1136 a = 0.0000062019158;
1137 b = -0.23774407;
1138 c = 6.1901333;
1139 break;
1140 case 12:
1141 a = 0.0000064901101;
1142 b = 0.93320705;
1143 c = 5.8395847;
1144 break;
1145 case 14:
1146 a = 0.0000062601892;
1147 b = 2.1588132;
1148 c = 5.5866699;
1149 break;
1150 case 15:
1151 a = 0.00000027748628;
1152 b = -0.0031671959;
1153 c = 6.2349744;
1154 break;
1155 case 16:
1156 a = 0.0000011401659;
1157 b = 1.8660343;
1158 c = 5.7884287;
1159 break;
1160 case 18:
1161 a = 0.00000093928003;
1162 b = 2.9224069;
1163 c = 5.6503159;
1164 break;
1165 case 20:
1166 a = 0.00000003478867;
1167 b = 0.44735558;
1168 c = 6.2388156;
1169 break;
1170 case 24:
1171 a = 0.0000000038623391;
1172 b = -0.4486039;
1173 c = 6.4245686;
1174 break;
1175 case 28:
1176 a = 0.000000039660207;
1177 b = 1.6425505;
1178 c = 5.8842817;
1179 break;
1180 default:
1181 return 0;
1182 break;
1183 }
1184 break;
1185 // Shots
1186 case 2:
1187 switch (org)
1188 {
1189 case 1:
1190 return 720;
1191 break;
1192 case 2:
1193 if (value == 2) return 79;
1194 else return 641;
1195 break;
1196 default:
1197 return 0;
1198 break;
1199 }
1200 break;
1201 // Reichweite, Scan
1202 case 3:
1203 switch (org)
1204 {
1205 case 3:
1206 if (value == 3) return 61;
1207 else return 299;
1208 break;
1209 case 4:
1210 a = 0.010226741;
1211 b = -0.001141961;
1212 c = 5.8477272;
1213 break;
1214 case 5:
1215 a = 0.00074684696;
1216 b = -0.24064936;
1217 c = 6.2377712;
1218 break;
1219 case 6:
1220 a = 0.0000004205569;
1221 b = -2.5074874;
1222 c = 8.1868728;
1223 break;
1224 case 7:
1225 a = 0.00018753949;
1226 b = 0.42735532;
1227 c = 5.9259322;
1228 break;
1229 case 8:
1230 a = 0.000026278484;
1231 b = 0.0026600724;
1232 c = 6.2281618;
1233 break;
1234 case 9:
1235 a = 0.000017724816;
1236 b = 0.35087138;
1237 c = 6.1028354;
1238 break;
1239 case 10:
1240 a = 0.000011074461;
1241 b = -0.41358078;
1242 c = 6.2067919;
1243 break;
1244 case 11:
1245 a = 0.0000022011968;
1246 b = -0.97456761;
1247 c = 6.4502985;
1248 break;
1249 case 12:
1250 a = 0.0000000034515189;
1251 b = -4.4597674;
1252 c = 7.9715326;
1253 break;
1254 case 14:
1255 a = 0.0000028257552;
1256 b = 0.78730358;
1257 c = 5.9483863;
1258 break;
1259 case 18:
1260 a = 0.00000024289322;
1261 b = 0.64536566;
1262 c = 6.11706;
1263 break;
1264 default:
1265 return 0;
1266 break;
1267 }
1268 break;
1269 default:
1270 return 0;
1271 }
1272
1273 tmp = (int) Round ((a * pow ((value - b), c)), 0);
1274 return tmp;
1275 }
1276 #endif
1277
1278
1279
1280 //--------------------------------------------------
1281 // R E S E A R C H C L A S S ---------------------
1282 //--------------------------------------------------
1283
1284 //--------------------------------------------------
cResearch()1285 cResearch::cResearch()
1286 {
1287 init();
1288 }
1289
1290 //--------------------------------------------------
init()1291 void cResearch::init()
1292 {
1293 int oldCurResearchLevel[kNrResearchAreas];
1294 int oldCurResearchPoints[kNrResearchAreas];
1295 int oldNeededResearchPoints[kNrResearchAreas];
1296
1297 for (int i = 0; i < kNrResearchAreas; i++)
1298 {
1299 oldCurResearchLevel[i] = curResearchLevel[i];
1300 oldCurResearchPoints[i] = curResearchPoints[i];
1301 oldNeededResearchPoints[i] = neededResearchPoints[i];
1302
1303 curResearchLevel[i] = 0;
1304 curResearchPoints[i] = 0;
1305 neededResearchPoints[i] = cUpgradeCalculator::instance().calcResearchTurns (0, getUpgradeCalculatorUpgradeType (i));
1306 }
1307
1308 for (int i = 0; i < kNrResearchAreas; i++)
1309 {
1310 if (oldCurResearchLevel[i] != curResearchLevel[i]) currentResearchLevelChanged ((ResearchArea)i);
1311 if (oldCurResearchPoints[i] != curResearchPoints[i]) currentResearchPointsChanged ((ResearchArea)i);
1312 if (oldNeededResearchPoints[i] != neededResearchPoints[i]) neededResearchPointsChanged ((ResearchArea)i);
1313 }
1314 }
1315
1316 //--------------------------------------------------
getCurResearchLevel(int researchArea) const1317 int cResearch::getCurResearchLevel (int researchArea) const
1318 {
1319 if (0 <= researchArea && researchArea <= kNrResearchAreas)
1320 return curResearchLevel[researchArea];
1321 return 0;
1322 }
1323
1324 //--------------------------------------------------
getCurResearchPoints(int researchArea) const1325 int cResearch::getCurResearchPoints (int researchArea) const
1326 {
1327 if (0 <= researchArea && researchArea <= kNrResearchAreas)
1328 return curResearchPoints[researchArea];
1329 return 0;
1330 }
1331
1332 //--------------------------------------------------
getNeededResearchPoints(int researchArea) const1333 int cResearch::getNeededResearchPoints (int researchArea) const
1334 {
1335 if (0 <= researchArea && researchArea <= kNrResearchAreas)
1336 return neededResearchPoints[researchArea];
1337 return cUpgradeCalculator::kNoResearchAvailable;
1338 }
1339
1340 //--------------------------------------------------
getRemainingTurns(int researchArea,int centersWorkingOn) const1341 int cResearch::getRemainingTurns (int researchArea, int centersWorkingOn) const
1342 {
1343 if (0 <= researchArea && researchArea <= kNrResearchAreas && centersWorkingOn > 0)
1344 {
1345 int remainingPoints = getRemainingResearchPoints (researchArea);
1346 if (remainingPoints % centersWorkingOn == 0)
1347 return remainingPoints / centersWorkingOn;
1348 else
1349 return (remainingPoints / centersWorkingOn) + 1;
1350 }
1351 return 0;
1352 }
1353
1354 //--------------------------------------------------
setCurResearchLevel(int researchLevel,int researchArea)1355 void cResearch::setCurResearchLevel (int researchLevel, int researchArea)
1356 {
1357 if (0 <= researchArea && researchArea <= kNrResearchAreas && researchLevel >= 0 && researchLevel % 10 == 0)
1358 {
1359 const auto oldLevel = curResearchLevel[researchArea];
1360 const auto oldPoints = curResearchPoints[researchArea];
1361 const auto oldNeededPoints = neededResearchPoints[researchArea];
1362
1363 curResearchLevel[researchArea] = researchLevel;
1364 neededResearchPoints[researchArea] = cUpgradeCalculator::instance().calcResearchTurns (researchLevel, getUpgradeCalculatorUpgradeType (researchArea));
1365 if (curResearchPoints[researchArea] >= neededResearchPoints[researchArea])
1366 {
1367 curResearchPoints[researchArea] = 0;
1368 }
1369
1370 if (oldLevel != curResearchLevel[researchArea]) currentResearchLevelChanged ((ResearchArea)researchArea);
1371 if (oldPoints != curResearchPoints[researchArea]) currentResearchPointsChanged ((ResearchArea)researchArea);
1372 if (oldNeededPoints != neededResearchPoints[researchArea]) neededResearchPointsChanged ((ResearchArea)researchArea);
1373 }
1374 }
1375
1376 //--------------------------------------------------
setCurResearchPoints(int researchPoints,int researchArea)1377 void cResearch::setCurResearchPoints (int researchPoints, int researchArea)
1378 {
1379 if (0 <= researchArea && researchArea <= kNrResearchAreas && researchPoints >= 0 && researchPoints < neededResearchPoints[researchArea])
1380 {
1381 std::swap (curResearchPoints[researchArea], researchPoints);
1382
1383 if (researchPoints != curResearchPoints[researchArea]) currentResearchPointsChanged ((ResearchArea)researchArea);
1384 }
1385 }
1386
1387 //--------------------------------------------------
doResearch(int researchPoints,int researchArea)1388 bool cResearch::doResearch (int researchPoints, int researchArea)
1389 {
1390 if (0 <= researchArea && researchArea <= kNrResearchAreas && researchPoints > 0)
1391 {
1392 const auto oldPoints = curResearchPoints[researchArea];
1393
1394 curResearchPoints[researchArea] += researchPoints;
1395
1396 if (curResearchPoints[researchArea] >= neededResearchPoints [researchArea])
1397 {
1398 const auto oldLevel = curResearchLevel[researchArea];
1399 const auto oldNeededPoints = neededResearchPoints[researchArea];
1400
1401 curResearchPoints[researchArea] = 0;
1402 curResearchLevel[researchArea] += 10;
1403 neededResearchPoints[researchArea] = cUpgradeCalculator::instance().calcResearchTurns (curResearchLevel[researchArea],
1404 getUpgradeCalculatorUpgradeType (researchArea));
1405
1406 if (oldLevel != curResearchLevel[researchArea]) currentResearchLevelChanged ((ResearchArea)researchArea);
1407 if (oldPoints != curResearchPoints[researchArea]) currentResearchPointsChanged ((ResearchArea)researchArea);
1408 if (oldNeededPoints != neededResearchPoints[researchArea]) neededResearchPointsChanged ((ResearchArea)researchArea);
1409
1410 return true;
1411 }
1412
1413 if (oldPoints != curResearchPoints[researchArea]) currentResearchPointsChanged ((ResearchArea)researchArea);
1414 }
1415 return false;
1416 }
1417
1418 //--------------------------------------------------
getUpgradeCalculatorUpgradeType(int researchArea) const1419 int cResearch::getUpgradeCalculatorUpgradeType (int researchArea) const
1420 {
1421 switch (researchArea)
1422 {
1423 case kHitpointsResearch: return cUpgradeCalculator::kHitpoints;
1424 case kArmorResearch: return cUpgradeCalculator::kArmor;
1425 case kAttackResearch: return cUpgradeCalculator::kAttack;
1426 case kSpeedResearch: return cUpgradeCalculator::kSpeed;
1427 case kShotsResearch: return cUpgradeCalculator::kShots;
1428 case kRangeResearch: return cUpgradeCalculator::kRange;
1429 case kScanResearch: return cUpgradeCalculator::kScan;
1430 case kCostResearch: return cUpgradeCalculator::kCost;
1431 }
1432 return 0;
1433 }
1434
1435 //--------------------------------------------------
getResearchArea(int upgradeCalculatorType) const1436 int cResearch::getResearchArea (int upgradeCalculatorType) const
1437 {
1438 switch (upgradeCalculatorType)
1439 {
1440 case cUpgradeCalculator::kHitpoints: return kHitpointsResearch;
1441 case cUpgradeCalculator::kArmor: return kArmorResearch;
1442 case cUpgradeCalculator::kAmmo: return -1;
1443 case cUpgradeCalculator::kAttack: return kAttackResearch;
1444 case cUpgradeCalculator::kSpeed: return kSpeedResearch;
1445 case cUpgradeCalculator::kShots: return kShotsResearch;
1446 case cUpgradeCalculator::kRange: return kRangeResearch;
1447 case cUpgradeCalculator::kScan: return kScanResearch;
1448 case cUpgradeCalculator::kCost: return kCostResearch;
1449 }
1450 return 0;
1451 }
1452
1453 //--------------------------------------------------
1454 // sUnitUpgrade C L A S S ---------------------
1455 //--------------------------------------------------
1456
1457 //--------------------------------------------------
GetUpgradeType(const sUnitUpgrade & upgrade)1458 static cUpgradeCalculator::UpgradeTypes GetUpgradeType (const sUnitUpgrade& upgrade)
1459 {
1460 switch (upgrade.getType())
1461 {
1462 case sUnitUpgrade::UPGRADE_TYPE_DAMAGE: return cUpgradeCalculator::kAttack;
1463 case sUnitUpgrade::UPGRADE_TYPE_SHOTS: return cUpgradeCalculator::kShots;
1464 case sUnitUpgrade::UPGRADE_TYPE_RANGE: return cUpgradeCalculator::kRange;
1465 case sUnitUpgrade::UPGRADE_TYPE_AMMO: return cUpgradeCalculator::kAmmo;
1466 case sUnitUpgrade::UPGRADE_TYPE_ARMOR: return cUpgradeCalculator::kArmor;
1467 case sUnitUpgrade::UPGRADE_TYPE_HITS: return cUpgradeCalculator::kHitpoints;
1468 case sUnitUpgrade::UPGRADE_TYPE_SCAN: return cUpgradeCalculator::kScan;
1469 case sUnitUpgrade::UPGRADE_TYPE_SPEED: return cUpgradeCalculator::kSpeed;
1470 case sUnitUpgrade::UPGRADE_TYPE_NONE: // Follow next line
1471 default: return cUpgradeCalculator::kAttack;
1472 }
1473 }
1474
1475 //--------------------------------------------------
purchase(const cResearch & researchLevel)1476 int sUnitUpgrade::purchase (const cResearch& researchLevel)
1477 {
1478 cUpgradeCalculator::UpgradeTypes upgradeType = GetUpgradeType (*this);
1479 const cUpgradeCalculator& uc = cUpgradeCalculator::instance();
1480 const int cost = nextPrice;
1481
1482 if (upgradeType == cUpgradeCalculator::kSpeed)
1483 {
1484 curValue += 4 * uc.calcIncreaseByUpgrade (startValue / 4);
1485 nextPrice = uc.calcPrice (curValue / 4, startValue / 4, upgradeType, researchLevel);
1486 }
1487 else
1488 {
1489 curValue += uc.calcIncreaseByUpgrade (startValue);
1490 nextPrice = uc.calcPrice (curValue, startValue, upgradeType, researchLevel);
1491 }
1492 ++purchased;
1493 return cost;
1494 }
1495
1496 //--------------------------------------------------
cancelPurchase(const cResearch & researchLevel)1497 int sUnitUpgrade::cancelPurchase (const cResearch& researchLevel)
1498 {
1499 cUpgradeCalculator::UpgradeTypes upgradeType = GetUpgradeType (*this);
1500 const cUpgradeCalculator& uc = cUpgradeCalculator::instance();
1501
1502 if (upgradeType == cUpgradeCalculator::kSpeed)
1503 {
1504 curValue -= 4 * uc.calcIncreaseByUpgrade (startValue / 4);
1505 nextPrice = uc.calcPrice (curValue / 4, startValue / 4, upgradeType, researchLevel);
1506 }
1507 else
1508 {
1509 curValue -= uc.calcIncreaseByUpgrade (startValue);
1510 nextPrice = uc.calcPrice (curValue, startValue, upgradeType, researchLevel);
1511 }
1512 --purchased;
1513 return -nextPrice;
1514 }
1515
1516 //--------------------------------------------------
computedPurchasedCount(const cResearch & researchLevel)1517 int sUnitUpgrade::computedPurchasedCount (const cResearch& researchLevel)
1518 {
1519 if (type == sUnitUpgrade::UPGRADE_TYPE_NONE) return 0;
1520
1521 cUpgradeCalculator::UpgradeTypes upgradeType = GetUpgradeType (*this);
1522 const cUpgradeCalculator& uc = cUpgradeCalculator::instance();
1523 sUnitUpgrade other (*this);
1524 int cost = 0;
1525 const int bonusByResearch = uc.calcChangeByResearch (startValue, researchLevel.getCurResearchLevel (researchLevel.getResearchArea (upgradeType)));
1526
1527 other.purchased = 0;
1528 while (other.curValue != startValue + bonusByResearch)
1529 {
1530 cost += other.cancelPurchase (researchLevel);
1531 }
1532 purchased += -other.purchased;
1533 return -cost;
1534 }
1535
1536 //--------------------------------------------------
init(const sUnitData & origData,const sUnitData & curData,const cResearch & researchLevel)1537 void cUnitUpgrade::init (const sUnitData& origData, const sUnitData& curData, const cResearch& researchLevel)
1538 {
1539 int i = 0;
1540
1541 if (curData.canAttack)
1542 {
1543 // Damage:
1544 upgrades[i].startValue = origData.getDamage();
1545 upgrades[i].curValue = curData.getDamage();
1546 upgrades[i].nextPrice = cUpgradeCalculator::instance().calcPrice (curData.getDamage(), origData.getDamage(), cUpgradeCalculator::kAttack, researchLevel);
1547 upgrades[i].type = sUnitUpgrade::UPGRADE_TYPE_DAMAGE;
1548 i++;
1549 if (!curData.explodesOnContact)
1550 {
1551 // Shots:
1552 upgrades[i].startValue = origData.getShotsMax();
1553 upgrades[i].curValue = curData.getShotsMax();
1554 upgrades[i].nextPrice = cUpgradeCalculator::instance().calcPrice (curData.getShotsMax(), origData.getShotsMax(), cUpgradeCalculator::kShots, researchLevel);
1555 upgrades[i].type = sUnitUpgrade::UPGRADE_TYPE_SHOTS;
1556 i++;
1557 // Range:
1558 upgrades[i].startValue = origData.getRange();
1559 upgrades[i].curValue = curData.getRange();
1560 upgrades[i].nextPrice = cUpgradeCalculator::instance().calcPrice (curData.getRange(), origData.getRange(), cUpgradeCalculator::kRange, researchLevel);
1561 upgrades[i].type = sUnitUpgrade::UPGRADE_TYPE_RANGE;
1562 i++;
1563 // Ammo:
1564 upgrades[i].startValue = origData.getAmmoMax();
1565 upgrades[i].curValue = curData.getAmmoMax();
1566 upgrades[i].nextPrice = cUpgradeCalculator::instance().calcPrice (curData.getAmmoMax(), origData.getAmmoMax(), cUpgradeCalculator::kAmmo, researchLevel);
1567 upgrades[i].type = sUnitUpgrade::UPGRADE_TYPE_AMMO;
1568 i++;
1569 }
1570 }
1571
1572 if (curData.storeResType != sUnitData::STORE_RES_NONE)
1573 {
1574 i++;
1575 }
1576
1577 if (curData.produceEnergy) i += 2;
1578
1579 if (curData.produceHumans) i++;
1580
1581 // Armor:
1582 upgrades[i].startValue = origData.getArmor();
1583 upgrades[i].curValue = curData.getArmor();
1584 upgrades[i].nextPrice = cUpgradeCalculator::instance().calcPrice (curData.getArmor(), origData.getArmor(), cUpgradeCalculator::kArmor, researchLevel);
1585 upgrades[i].type = sUnitUpgrade::UPGRADE_TYPE_ARMOR;
1586 i++;
1587
1588 // Hitpoints:
1589 upgrades[i].startValue = origData.getHitpointsMax();
1590 upgrades[i].curValue = curData.getHitpointsMax();
1591 upgrades[i].nextPrice = cUpgradeCalculator::instance().calcPrice (curData.getHitpointsMax(), origData.getHitpointsMax(), cUpgradeCalculator::kHitpoints, researchLevel);
1592 upgrades[i].type = sUnitUpgrade::UPGRADE_TYPE_HITS;
1593 i++;
1594
1595 // Scan:
1596 if (curData.getScan())
1597 {
1598 upgrades[i].startValue = origData.getScan();
1599 upgrades[i].curValue = curData.getScan();
1600 upgrades[i].nextPrice = cUpgradeCalculator::instance().calcPrice (curData.getScan(), origData.getScan(), cUpgradeCalculator::kScan, researchLevel);
1601 upgrades[i].type = sUnitUpgrade::UPGRADE_TYPE_SCAN;
1602 i++;
1603 }
1604
1605 // Speed:
1606 if (curData.getSpeedMax())
1607 {
1608 upgrades[i].startValue = origData.getSpeedMax();
1609 upgrades[i].curValue = curData.getSpeedMax();
1610 upgrades[i].nextPrice = cUpgradeCalculator::instance().calcPrice (curData.getSpeedMax() / 4, origData.getSpeedMax() / 4, cUpgradeCalculator::kSpeed, researchLevel);
1611 upgrades[i].type = sUnitUpgrade::UPGRADE_TYPE_SPEED;
1612 i++;
1613 }
1614 }
1615
1616 //--------------------------------------------------
computedPurchasedCount(const cResearch & researchLevel)1617 int cUnitUpgrade::computedPurchasedCount (const cResearch& researchLevel)
1618 {
1619 int cost = 0;
1620
1621 for (int i = 0; i < 8; ++i)
1622 {
1623 cost += upgrades[i].computedPurchasedCount (researchLevel);
1624 }
1625 return cost;
1626 }
1627
1628 //--------------------------------------------------
getUpgrade(sUnitUpgrade::eUpgradeTypes type)1629 sUnitUpgrade* cUnitUpgrade::getUpgrade (sUnitUpgrade::eUpgradeTypes type)
1630 {
1631 for (int i = 0; i < 8; i++)
1632 {
1633 if (upgrades[i].type == type) return &upgrades[i];
1634 }
1635 return nullptr;
1636 }
1637
1638 //--------------------------------------------------
getUpgrade(sUnitUpgrade::eUpgradeTypes type) const1639 const sUnitUpgrade* cUnitUpgrade::getUpgrade (sUnitUpgrade::eUpgradeTypes type) const
1640 {
1641 for (int i = 0; i < 8; i++)
1642 {
1643 if (upgrades[i].type == type) return &upgrades[i];
1644 }
1645 return nullptr;
1646 }
1647
1648 //--------------------------------------------------
getValueOrDefault(sUnitUpgrade::eUpgradeTypes upgradeType,int defaultValue) const1649 int cUnitUpgrade::getValueOrDefault (sUnitUpgrade::eUpgradeTypes upgradeType, int defaultValue) const
1650 {
1651 for (int i = 0; i != 8; ++i)
1652 {
1653 if (upgrades[i].type == upgradeType)
1654 return upgrades[i].curValue;
1655 }
1656 return defaultValue; // the specified upgrade was not found...
1657 }
1658
1659 //--------------------------------------------------
hasBeenPurchased() const1660 bool cUnitUpgrade::hasBeenPurchased() const
1661 {
1662 for (int i = 0; i != 8; ++i)
1663 {
1664 if (upgrades[i].purchased)
1665 {
1666 return true;
1667 }
1668 }
1669 return false;
1670 }
1671
1672 //--------------------------------------------------
updateUnitData(sUnitData & data) const1673 void cUnitUpgrade::updateUnitData (sUnitData& data) const
1674 {
1675 for (int i = 0; i < 8; ++i)
1676 {
1677 switch (upgrades[i].getType())
1678 {
1679 case sUnitUpgrade::UPGRADE_TYPE_DAMAGE:
1680 data.setDamage (upgrades[i].curValue);
1681 break;
1682 case sUnitUpgrade::UPGRADE_TYPE_SHOTS:
1683 data.setShotsMax (upgrades[i].curValue);
1684 break;
1685 case sUnitUpgrade::UPGRADE_TYPE_RANGE:
1686 data.setRange (upgrades[i].curValue);
1687 break;
1688 case sUnitUpgrade::UPGRADE_TYPE_AMMO:
1689 data.setAmmoMax (upgrades[i].curValue);
1690 break;
1691 case sUnitUpgrade::UPGRADE_TYPE_ARMOR:
1692 data.setArmor (upgrades[i].curValue);
1693 break;
1694 case sUnitUpgrade::UPGRADE_TYPE_HITS:
1695 data.setHitpointsMax (upgrades[i].curValue);
1696 break;
1697 case sUnitUpgrade::UPGRADE_TYPE_SCAN:
1698 data.setScan (upgrades[i].curValue);
1699 break;
1700 case sUnitUpgrade::UPGRADE_TYPE_SPEED:
1701 data.setSpeedMax (upgrades[i].curValue);
1702 break;
1703 case sUnitUpgrade::UPGRADE_TYPE_NONE:
1704 break;
1705 }
1706 }
1707 }
1708