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