1 /*
2 * Copyright 2010-2014 OpenXcom Developers.
3 *
4 * This file is part of OpenXcom.
5 *
6 * OpenXcom is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * OpenXcom is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with OpenXcom. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "BaseInfoState.h"
20 #include <cmath>
21 #include <sstream>
22 #include "../Engine/Game.h"
23 #include "../Engine/Action.h"
24 #include "../Resource/ResourcePack.h"
25 #include "../Engine/Language.h"
26 #include "../Engine/Palette.h"
27 #include "../Engine/Options.h"
28 #include "../Interface/Bar.h"
29 #include "../Interface/TextButton.h"
30 #include "../Interface/Text.h"
31 #include "../Interface/TextEdit.h"
32 #include "../Engine/Surface.h"
33 #include "MiniBaseView.h"
34 #include "../Savegame/SavedGame.h"
35 #include "../Savegame/Base.h"
36 #include "MonthlyCostsState.h"
37 #include "TransfersState.h"
38 #include "StoresState.h"
39 #include "BasescapeState.h"
40
41 namespace OpenXcom
42 {
43
44 /**
45 * Initializes all the elements in the Base Info screen.
46 * @param game Pointer to the core game.
47 * @param base Pointer to the base to get info from.
48 * @param state Pointer to the Basescape state.
49 */
BaseInfoState(Game * game,Base * base,BasescapeState * state)50 BaseInfoState::BaseInfoState(Game *game, Base *base, BasescapeState *state) : State(game), _base(base), _state(state)
51 {
52 // Create objects
53 _bg = new Surface(320, 200, 0, 0);
54 _mini = new MiniBaseView(128, 16, 182, 8);
55 _btnOk = new TextButton(30, 14, 10, 180);
56 _btnTransfers = new TextButton(80, 14, 46, 180);
57 _btnStores = new TextButton(80, 14, 132, 180);
58 _btnMonthlyCosts = new TextButton(92, 14, 218, 180);
59 _edtBase = new TextEdit(this, 127, 16, 8, 8);
60
61 _txtPersonnel = new Text(300, 9, 8, 30);
62 _txtSoldiers = new Text(114, 9, 8, 41);
63 _numSoldiers = new Text(40, 9, 126, 41);
64 _barSoldiers = new Bar(150, 5, 166, 43);
65 _txtEngineers = new Text(114, 9, 8, 51);
66 _numEngineers = new Text(40, 9, 126, 51);
67 _barEngineers = new Bar(150, 5, 166, 53);
68 _txtScientists = new Text(114, 9, 8, 61);
69 _numScientists = new Text(40, 9, 126, 61);
70 _barScientists = new Bar(150, 5, 166, 63);
71
72 _txtSpace = new Text(300, 9, 8, 72);
73 _txtQuarters = new Text(114, 9, 8, 83);
74 _numQuarters = new Text(40, 9, 126, 83);
75 _barQuarters = new Bar(150, 5, 166, 85);
76 _txtStores = new Text(114, 9, 8, 93);
77 _numStores = new Text(40, 9, 126, 93);
78 _barStores = new Bar(150, 5, 166, 95);
79 _txtLaboratories = new Text(114, 9, 8, 103);
80 _numLaboratories = new Text(40, 9, 126, 103);
81 _barLaboratories = new Bar(150, 5, 166, 105);
82 _txtWorkshops = new Text(114, 9, 8, 113);
83 _numWorkshops = new Text(40, 9, 126, 113);
84 _barWorkshops = new Bar(150, 5, 166, 115);
85 if (Options::storageLimitsEnforced)
86 {
87 _txtContainment = new Text(114, 9, 8, 123);
88 _numContainment = new Text(40, 9, 126, 123);
89 _barContainment = new Bar(150, 5, 166, 125);
90 }
91 _txtHangars = new Text(114, 9, 8, Options::storageLimitsEnforced ? 133 : 123);
92 _numHangars = new Text(40, 9, 126, Options::storageLimitsEnforced ? 133 : 123);
93 _barHangars = new Bar(150, 5, 166, Options::storageLimitsEnforced ? 135 : 125);
94
95 _txtDefense = new Text(114, 9, 8, Options::storageLimitsEnforced ? 147 : 138);
96 _numDefense = new Text(40, 9, 126, Options::storageLimitsEnforced ? 147 : 138);
97 _barDefense = new Bar(150, 5, 166, Options::storageLimitsEnforced ? 149 : 140);
98 _txtShortRange = new Text(114, 9, 8, Options::storageLimitsEnforced ? 157 : 153);
99 _numShortRange = new Text(40, 9, 126, Options::storageLimitsEnforced ? 157 : 153);
100 _barShortRange = new Bar(150, 5, 166, Options::storageLimitsEnforced ? 159 : 155);
101 _txtLongRange = new Text(114, 9, 8, Options::storageLimitsEnforced ? 167 : 163);
102 _numLongRange = new Text(40, 9, 126, Options::storageLimitsEnforced ? 167 : 163);
103 _barLongRange = new Bar(150, 5, 166, Options::storageLimitsEnforced ? 169 : 165);
104
105 // Set palette
106 setPalette("PAL_BASESCAPE");
107
108 add(_bg);
109 add(_mini);
110 add(_btnOk);
111 add(_btnTransfers);
112 add(_btnStores);
113 add(_btnMonthlyCosts);
114 add(_edtBase);
115
116 add(_txtPersonnel);
117 add(_txtSoldiers);
118 add(_numSoldiers);
119 add(_barSoldiers);
120 add(_txtEngineers);
121 add(_numEngineers);
122 add(_barEngineers);
123 add(_txtScientists);
124 add(_numScientists);
125 add(_barScientists);
126
127 add(_txtSpace);
128 add(_txtQuarters);
129 add(_numQuarters);
130 add(_barQuarters);
131 add(_txtStores);
132 add(_numStores);
133 add(_barStores);
134 add(_txtLaboratories);
135 add(_numLaboratories);
136 add(_barLaboratories);
137 add(_txtWorkshops);
138 add(_numWorkshops);
139 add(_barWorkshops);
140 if (Options::storageLimitsEnforced)
141 {
142 add(_txtContainment);
143 add(_numContainment);
144 add(_barContainment);
145 }
146 add(_txtHangars);
147 add(_numHangars);
148 add(_barHangars);
149
150 add(_txtDefense);
151 add(_numDefense);
152 add(_barDefense);
153 add(_txtShortRange);
154 add(_numShortRange);
155 add(_barShortRange);
156 add(_txtLongRange);
157 add(_numLongRange);
158 add(_barLongRange);
159
160 centerAllSurfaces();
161
162 // Set up objects
163 std::ostringstream ss;
164 if (Options::storageLimitsEnforced)
165 {
166 ss << "ALT";
167 }
168 ss << "BACK07.SCR";
169 _game->getResourcePack()->getSurface(ss.str())->blit(_bg);
170
171 _mini->setTexture(_game->getResourcePack()->getSurfaceSet("BASEBITS.PCK"));
172 _mini->setBases(_game->getSavedGame()->getBases());
173 for (size_t i = 0; i < _game->getSavedGame()->getBases()->size(); ++i)
174 {
175 if (_game->getSavedGame()->getBases()->at(i) == _base)
176 {
177 _mini->setSelectedBase(i);
178 break;
179 }
180 }
181 _mini->onMouseClick((ActionHandler)&BaseInfoState::miniClick);
182 _mini->onKeyboardPress((ActionHandler)&BaseInfoState::handleKeyPress);
183
184 _btnOk->setColor(Palette::blockOffset(15)+6);
185 _btnOk->setText(tr("STR_OK"));
186 _btnOk->onMouseClick((ActionHandler)&BaseInfoState::btnOkClick);
187 _btnOk->onKeyboardPress((ActionHandler)&BaseInfoState::btnOkClick, Options::keyCancel);
188
189 _btnTransfers->setColor(Palette::blockOffset(15)+6);
190 _btnTransfers->setText(tr("STR_TRANSFERS_UC"));
191 _btnTransfers->onMouseClick((ActionHandler)&BaseInfoState::btnTransfersClick);
192
193 _btnStores->setColor(Palette::blockOffset(15)+6);
194 _btnStores->setText(tr("STR_STORES_UC"));
195 _btnStores->onMouseClick((ActionHandler)&BaseInfoState::btnStoresClick);
196
197 _btnMonthlyCosts->setColor(Palette::blockOffset(15)+6);
198 _btnMonthlyCosts->setText(tr("STR_MONTHLY_COSTS"));
199 _btnMonthlyCosts->onMouseClick((ActionHandler)&BaseInfoState::btnMonthlyCostsClick);
200
201 _edtBase->setColor(Palette::blockOffset(15)+1);
202 _edtBase->setBig();
203 _edtBase->onChange((ActionHandler)&BaseInfoState::edtBaseChange);
204
205 _txtPersonnel->setColor(Palette::blockOffset(15)+1);
206 _txtPersonnel->setText(tr("STR_PERSONNEL_AVAILABLE_PERSONNEL_TOTAL"));
207
208 _txtSoldiers->setColor(Palette::blockOffset(13)+5);
209 _txtSoldiers->setText(tr("STR_SOLDIERS"));
210
211 _numSoldiers->setColor(Palette::blockOffset(13));
212
213 _barSoldiers->setColor(Palette::blockOffset(1));
214 _barSoldiers->setScale(1.0);
215
216 _txtEngineers->setColor(Palette::blockOffset(13)+5);
217 _txtEngineers->setText(tr("STR_ENGINEERS"));
218
219 _numEngineers->setColor(Palette::blockOffset(13));
220
221 _barEngineers->setColor(Palette::blockOffset(1));
222 _barEngineers->setScale(1.0);
223
224 _txtScientists->setColor(Palette::blockOffset(13)+5);
225 _txtScientists->setText(tr("STR_SCIENTISTS"));
226
227 _numScientists->setColor(Palette::blockOffset(13));
228
229 _barScientists->setColor(Palette::blockOffset(1));
230 _barScientists->setScale(1.0);
231
232
233 _txtSpace->setColor(Palette::blockOffset(15)+1);
234 _txtSpace->setText(tr("STR_SPACE_USED_SPACE_AVAILABLE"));
235
236 _txtQuarters->setColor(Palette::blockOffset(13)+5);
237 _txtQuarters->setText(tr("STR_LIVING_QUARTERS_PLURAL"));
238
239 _numQuarters->setColor(Palette::blockOffset(13));
240
241 _barQuarters->setColor(Palette::blockOffset(3));
242 _barQuarters->setScale(0.5);
243
244 _txtStores->setColor(Palette::blockOffset(13)+5);
245 _txtStores->setText(tr("STR_STORES"));
246
247 _numStores->setColor(Palette::blockOffset(13));
248
249 _barStores->setColor(Palette::blockOffset(3));
250 _barStores->setScale(0.5);
251
252 _txtLaboratories->setColor(Palette::blockOffset(13)+5);
253 _txtLaboratories->setText(tr("STR_LABORATORIES"));
254
255 _numLaboratories->setColor(Palette::blockOffset(13));
256
257 _barLaboratories->setColor(Palette::blockOffset(3));
258 _barLaboratories->setScale(0.5);
259
260 _txtWorkshops->setColor(Palette::blockOffset(13)+5);
261 _txtWorkshops->setText(tr("STR_WORK_SHOPS"));
262
263 _numWorkshops->setColor(Palette::blockOffset(13));
264
265 _barWorkshops->setColor(Palette::blockOffset(3));
266 _barWorkshops->setScale(0.5);
267
268 if (Options::storageLimitsEnforced)
269 {
270 _txtContainment->setColor(Palette::blockOffset(13)+5);
271 _txtContainment->setText(tr("STR_ALIEN_CONTAINMENT"));
272
273 _numContainment->setColor(Palette::blockOffset(13));
274
275 _barContainment->setColor(Palette::blockOffset(3));
276 _barContainment->setScale(0.5);
277 }
278
279 _txtHangars->setColor(Palette::blockOffset(13)+5);
280 _txtHangars->setText(tr("STR_HANGARS"));
281
282 _numHangars->setColor(Palette::blockOffset(13));
283
284 _barHangars->setColor(Palette::blockOffset(3));
285 _barHangars->setScale(18.0);
286
287
288 _txtDefense->setColor(Palette::blockOffset(13)+5);
289 _txtDefense->setText(tr("STR_DEFENSE_STRENGTH"));
290
291 _numDefense->setColor(Palette::blockOffset(13));
292
293 _barDefense->setColor(Palette::blockOffset(2));
294 _barDefense->setScale(0.125);
295
296 _txtShortRange->setColor(Palette::blockOffset(13)+5);
297 _txtShortRange->setText(tr("STR_SHORT_RANGE_DETECTION"));
298
299 _numShortRange->setColor(Palette::blockOffset(13));
300
301 _barShortRange->setColor(Palette::blockOffset(8));
302 _barShortRange->setScale(25.0);
303
304 _txtLongRange->setColor(Palette::blockOffset(13)+5);
305 _txtLongRange->setText(tr("STR_LONG_RANGE_DETECTION"));
306
307 _numLongRange->setColor(Palette::blockOffset(13));
308
309 _barLongRange->setColor(Palette::blockOffset(8));
310 _barLongRange->setScale(25.0);
311 }
312
313 /**
314 *
315 */
~BaseInfoState()316 BaseInfoState::~BaseInfoState()
317 {
318
319 }
320
321 /**
322 * The player can change the selected base.
323 */
init()324 void BaseInfoState::init()
325 {
326 State::init();
327 _edtBase->setText(_base->getName());
328
329 std::wostringstream ss;
330 ss << _base->getAvailableSoldiers() << ":" << _base->getTotalSoldiers();
331 _numSoldiers->setText(ss.str());
332
333 _barSoldiers->setMax(_base->getTotalSoldiers());
334 _barSoldiers->setValue(_base->getAvailableSoldiers());
335
336 std::wostringstream ss2;
337 ss2 << _base->getAvailableEngineers() << ":" << _base->getTotalEngineers();
338 _numEngineers->setText(ss2.str());
339
340 _barEngineers->setMax(_base->getTotalEngineers());
341 _barEngineers->setValue(_base->getAvailableEngineers());
342
343 std::wostringstream ss3;
344 ss3 << _base->getAvailableScientists() << ":" << _base->getTotalScientists();
345 _numScientists->setText(ss3.str());
346
347 _barScientists->setMax(_base->getTotalScientists());
348 _barScientists->setValue(_base->getAvailableScientists());
349
350
351 std::wostringstream ss4;
352 ss4 << _base->getUsedQuarters() << ":" << _base->getAvailableQuarters();
353 _numQuarters->setText(ss4.str());
354
355 _barQuarters->setMax(_base->getAvailableQuarters());
356 _barQuarters->setValue(_base->getUsedQuarters());
357
358 std::wostringstream ss5;
359 ss5 << (int)floor(_base->getUsedStores() + 0.05) << ":" << _base->getAvailableStores();
360 _numStores->setText(ss5.str());
361
362 _barStores->setMax(_base->getAvailableStores());
363 _barStores->setValue((int)floor(_base->getUsedStores() + 0.05));
364
365 std::wostringstream ss6;
366 ss6 << _base->getUsedLaboratories() << ":" << _base->getAvailableLaboratories();
367 _numLaboratories->setText(ss6.str());
368
369 _barLaboratories->setMax(_base->getAvailableLaboratories());
370 _barLaboratories->setValue(_base->getUsedLaboratories());
371
372 std::wostringstream ss7;
373 ss7 << _base->getUsedWorkshops() << ":" << _base->getAvailableWorkshops();
374 _numWorkshops->setText(ss7.str());
375
376 _barWorkshops->setMax(_base->getAvailableWorkshops());
377 _barWorkshops->setValue(_base->getUsedWorkshops());
378
379 if (Options::storageLimitsEnforced)
380 {
381 std::wostringstream ss72;
382 ss72 << _base->getUsedContainment() << ":" << _base->getAvailableContainment();
383 _numContainment->setText(ss72.str());
384
385 _barContainment->setMax(_base->getAvailableContainment());
386 _barContainment->setValue(_base->getUsedContainment());
387 }
388
389 std::wostringstream ss8;
390 ss8 << _base->getUsedHangars() << ":" << _base->getAvailableHangars();
391 _numHangars->setText(ss8.str());
392
393 _barHangars->setMax(_base->getAvailableHangars());
394 _barHangars->setValue(_base->getUsedHangars());
395
396
397 std::wostringstream ss9;
398 ss9 << _base->getDefenseValue();
399 _numDefense->setText(ss9.str());
400
401 _barDefense->setMax(_base->getDefenseValue());
402 _barDefense->setValue(_base->getDefenseValue());
403
404 std::wostringstream ss10;
405 ss10 << _base->getShortRangeDetection();
406 _numShortRange->setText(ss10.str());
407
408 _barShortRange->setMax(_base->getShortRangeDetection());
409 _barShortRange->setValue(_base->getShortRangeDetection());
410
411 std::wostringstream ss11;
412 ss11 << _base->getLongRangeDetection();
413 _numLongRange->setText(ss11.str());
414
415 _barLongRange->setMax(_base->getLongRangeDetection());
416 _barLongRange->setValue(_base->getLongRangeDetection());
417 }
418
419 /**
420 * Changes the base name.
421 * @param action Pointer to an action.
422 */
edtBaseChange(Action * action)423 void BaseInfoState::edtBaseChange(Action *action)
424 {
425 _base->setName(_edtBase->getText());
426 }
427
428 /**
429 * Selects a new base to display.
430 * @param action Pointer to an action.
431 */
miniClick(Action *)432 void BaseInfoState::miniClick(Action *)
433 {
434 size_t base = _mini->getHoveredBase();
435 if (base < _game->getSavedGame()->getBases()->size())
436 {
437 _mini->setSelectedBase(base);
438 _base = _game->getSavedGame()->getBases()->at(base);
439 _state->setBase(_base);
440 init();
441 }
442 }
443
444 /**
445 * Selects a new base to display.
446 * @param action Pointer to an action.
447 */
handleKeyPress(Action * action)448 void BaseInfoState::handleKeyPress(Action *action)
449 {
450 if (action->getDetails()->type == SDL_KEYDOWN)
451 {
452 SDLKey baseKeys[] = {Options::keyBaseSelect1,
453 Options::keyBaseSelect2,
454 Options::keyBaseSelect3,
455 Options::keyBaseSelect4,
456 Options::keyBaseSelect5,
457 Options::keyBaseSelect6,
458 Options::keyBaseSelect7,
459 Options::keyBaseSelect8};
460 int key = action->getDetails()->key.keysym.sym;
461 for (size_t i = 0; i < _game->getSavedGame()->getBases()->size(); ++i)
462 {
463 if (key == baseKeys[i])
464 {
465 _base = _game->getSavedGame()->getBases()->at(i);
466 init();
467 break;
468 }
469 }
470 }
471 }
472
473 /**
474 * Returns to the previous screen.
475 * @param action Pointer to an action.
476 */
btnOkClick(Action *)477 void BaseInfoState::btnOkClick(Action *)
478 {
479 _game->popState();
480 }
481
482 /**
483 * Goes to the Transfers window.
484 * @param action Pointer to an action.
485 */
btnTransfersClick(Action *)486 void BaseInfoState::btnTransfersClick(Action *)
487 {
488 _game->pushState(new TransfersState(_game, _base));
489 }
490
491 /**
492 * Goes to the Stores screen.
493 * @param action Pointer to an action.
494 */
btnStoresClick(Action *)495 void BaseInfoState::btnStoresClick(Action *)
496 {
497 _game->pushState(new StoresState(_game, _base));
498 }
499
500 /**
501 * Goes to the Monthly Costs screen.
502 * @param action Pointer to an action.
503 */
btnMonthlyCostsClick(Action *)504 void BaseInfoState::btnMonthlyCostsClick(Action *)
505 {
506 _game->pushState(new MonthlyCostsState(_game, _base));
507 }
508
509 }
510