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 "SoldierInfoState.h"
20 #include <sstream>
21 #include "../Engine/Game.h"
22 #include "../Engine/Action.h"
23 #include "../Resource/ResourcePack.h"
24 #include "../Engine/Language.h"
25 #include "../Engine/Palette.h"
26 #include "../Engine/Options.h"
27 #include "../Interface/Bar.h"
28 #include "../Interface/TextButton.h"
29 #include "../Interface/Text.h"
30 #include "../Interface/TextEdit.h"
31 #include "../Engine/Surface.h"
32 #include "../Savegame/SavedGame.h"
33 #include "../Ruleset/Ruleset.h"
34 #include "../Savegame/Base.h"
35 #include "../Savegame/Craft.h"
36 #include "../Ruleset/RuleCraft.h"
37 #include "../Savegame/Soldier.h"
38 #include "../Savegame/ItemContainer.h"
39 #include "../Engine/SurfaceSet.h"
40 #include "../Ruleset/Armor.h"
41 #include "../Menu/ErrorMessageState.h"
42 #include "SellState.h"
43 #include "SoldierArmorState.h"
44 #include "SackSoldierState.h"
45 
46 namespace OpenXcom
47 {
48 
49 /**
50  * Initializes all the elements in the Soldier Info screen.
51  * @param game Pointer to the core game.
52  * @param base Pointer to the base to get info from. NULL to use the dead soldiers list.
53  * @param soldierId ID of the selected soldier.
54  */
SoldierInfoState(Game * game,Base * base,size_t soldierId)55 SoldierInfoState::SoldierInfoState(Game *game, Base *base, size_t soldierId) : State(game), _base(base), _soldierId(soldierId)
56 {
57 	if (_base == 0)
58 	{
59 		_list = _game->getSavedGame()->getDeadSoldiers();
60 		if (_soldierId >= _list->size())
61 		{
62 			_soldierId = 0;
63 		}
64 		else
65 		{
66 			_soldierId = _list->size() - (1 + _soldierId);
67 		}
68 	}
69 	else
70 	{
71 		_list = _base->getSoldiers();
72 	}
73 
74 	// Create objects
75 	_bg = new Surface(320, 200, 0, 0);
76 	_rank = new Surface(26, 23, 4, 4);
77 	_btnPrev = new TextButton(28, 14, 0, 33);
78 	_btnOk = new TextButton(48, 14, 30, 33);
79 	_btnNext = new TextButton(28, 14, 80, 33);
80 	_btnArmor = new TextButton(110, 14, 130, 33);
81 	_edtSoldier = new TextEdit(this, 210, 16, 40, 9);
82 	_btnSack = new TextButton(60, 14, 260, 33);
83 	_txtRank = new Text(130, 9, 0, 48);
84 	_txtMissions = new Text(100, 9, 130, 48);
85 	_txtKills = new Text(100, 9, 230, 48);
86 	_txtCraft = new Text(130, 9, 0, 56);
87 	_txtRecovery = new Text(180, 9, 130, 56);
88 	_txtPsionic = new Text(150, 9, 0, 66);
89 
90 	int yPos = 80;
91 	int step = 11;
92 
93 	_txtTimeUnits = new Text(120, 9, 6, yPos);
94 	_numTimeUnits = new Text(18, 9, 131, yPos);
95 	_barTimeUnits = new Bar(170, 7, 150, yPos);
96 	yPos += step;
97 
98 	_txtStamina = new Text(120, 9, 6, yPos);
99 	_numStamina = new Text(18, 9, 131, yPos);
100 	_barStamina = new Bar(170, 7, 150, yPos);
101 	yPos += step;
102 
103 	_txtHealth = new Text(120, 9, 6, yPos);
104 	_numHealth = new Text(18, 9, 131, yPos);
105 	_barHealth = new Bar(170, 7, 150, yPos);
106 	yPos += step;
107 
108 	_txtBravery = new Text(120, 9, 6, yPos);
109 	_numBravery = new Text(18, 9, 131, yPos);
110 	_barBravery = new Bar(170, 7, 150, yPos);
111 	yPos += step;
112 
113 	_txtReactions = new Text(120, 9, 6, yPos);
114 	_numReactions = new Text(18, 9, 131, yPos);
115 	_barReactions = new Bar(170, 7, 150, yPos);
116 	yPos += step;
117 
118 	_txtFiring = new Text(120, 9, 6, yPos);
119 	_numFiring = new Text(18, 9, 131, yPos);
120 	_barFiring = new Bar(170, 7, 150, yPos);
121 	yPos += step;
122 
123 	_txtThrowing = new Text(120, 9, 6, yPos);
124 	_numThrowing = new Text(18, 9, 131, yPos);
125 	_barThrowing = new Bar(170, 7, 150, yPos);
126 	yPos += step;
127 
128 	_txtMelee = new Text(120, 9, 6, yPos);
129 	_numMelee = new Text(18, 9, 131, yPos);
130 	_barMelee = new Bar(170, 7, 150, yPos);
131 	yPos += step;
132 
133 	_txtStrength = new Text(120, 9, 6, yPos);
134 	_numStrength = new Text(18, 9, 131, yPos);
135 	_barStrength = new Bar(170, 7, 150, yPos);
136 	yPos += step;
137 
138 	_txtPsiStrength = new Text(120, 9, 6, yPos);
139 	_numPsiStrength = new Text(18, 9, 131, yPos);
140 	_barPsiStrength = new Bar(170, 7, 150, yPos);
141 	yPos += step;
142 
143 	_txtPsiSkill = new Text(120, 9, 6, yPos);
144 	_numPsiSkill = new Text(18, 9, 131, yPos);
145 	_barPsiSkill = new Bar(170, 7, 150, yPos);
146 
147 	// Set palette
148 	setPalette("PAL_BASESCAPE");
149 
150 	add(_bg);
151 	add(_rank);
152 	add(_btnOk);
153 	add(_btnPrev);
154 	add(_btnNext);
155 	add(_btnArmor);
156 	add(_edtSoldier);
157 	add(_btnSack);
158 	add(_txtRank);
159 	add(_txtMissions);
160 	add(_txtKills);
161 	add(_txtCraft);
162 	add(_txtRecovery);
163 	add(_txtPsionic);
164 
165 	add(_txtTimeUnits);
166 	add(_numTimeUnits);
167 	add(_barTimeUnits);
168 
169 	add(_txtStamina);
170 	add(_numStamina);
171 	add(_barStamina);
172 
173 	add(_txtHealth);
174 	add(_numHealth);
175 	add(_barHealth);
176 
177 	add(_txtBravery);
178 	add(_numBravery);
179 	add(_barBravery);
180 
181 	add(_txtReactions);
182 	add(_numReactions);
183 	add(_barReactions);
184 
185 	add(_txtFiring);
186 	add(_numFiring);
187 	add(_barFiring);
188 
189 	add(_txtThrowing);
190 	add(_numThrowing);
191 	add(_barThrowing);
192 
193 	add(_txtMelee);
194 	add(_numMelee);
195 	add(_barMelee);
196 
197 	add(_txtStrength);
198 	add(_numStrength);
199 	add(_barStrength);
200 
201 	add(_txtPsiStrength);
202 	add(_numPsiStrength);
203 	add(_barPsiStrength);
204 
205 	add(_txtPsiSkill);
206 	add(_numPsiSkill);
207 	add(_barPsiSkill);
208 
209 	centerAllSurfaces();
210 
211 	// Set up objects
212 	_game->getResourcePack()->getSurface("BACK06.SCR")->blit(_bg);
213 
214 	_btnOk->setColor(Palette::blockOffset(15)+6);
215 	_btnOk->setText(tr("STR_OK"));
216 	_btnOk->onMouseClick((ActionHandler)&SoldierInfoState::btnOkClick);
217 	_btnOk->onKeyboardPress((ActionHandler)&SoldierInfoState::btnOkClick, Options::keyCancel);
218 
219 	_btnPrev->setColor(Palette::blockOffset(15)+6);
220 	_btnPrev->setText(L"<<");
221 	if (_base == 0)
222 	{
223 		_btnPrev->onMouseClick((ActionHandler)&SoldierInfoState::btnNextClick);
224 		_btnPrev->onKeyboardPress((ActionHandler)&SoldierInfoState::btnNextClick, Options::keyBattlePrevUnit);
225 	}
226 	else
227 	{
228 		_btnPrev->onMouseClick((ActionHandler)&SoldierInfoState::btnPrevClick);
229 		_btnPrev->onKeyboardPress((ActionHandler)&SoldierInfoState::btnPrevClick, Options::keyBattlePrevUnit);
230 	}
231 
232 	_btnNext->setColor(Palette::blockOffset(15)+6);
233 	_btnNext->setText(L">>");
234 	if (_base == 0)
235 	{
236 		_btnNext->onMouseClick((ActionHandler)&SoldierInfoState::btnPrevClick);
237 		_btnNext->onKeyboardPress((ActionHandler)&SoldierInfoState::btnPrevClick, Options::keyBattleNextUnit);
238 	}
239 	else
240 	{
241 		_btnNext->onMouseClick((ActionHandler)&SoldierInfoState::btnNextClick);
242 		_btnNext->onKeyboardPress((ActionHandler)&SoldierInfoState::btnNextClick, Options::keyBattleNextUnit);
243 	}
244 
245 	_btnArmor->setColor(Palette::blockOffset(15)+6);
246 	_btnArmor->setText(tr("STR_ARMOR"));
247 	_btnArmor->onMouseClick((ActionHandler)&SoldierInfoState::btnArmorClick);
248 
249 	_edtSoldier->setColor(Palette::blockOffset(13)+10);
250 	_edtSoldier->setBig();
251 	_edtSoldier->onChange((ActionHandler)&SoldierInfoState::edtSoldierChange);
252 	_edtSoldier->onMousePress((ActionHandler)&SoldierInfoState::edtSoldierPress);
253 
254 	_btnSack->setColor(Palette::blockOffset(15)+6);
255 	_btnSack->setText(tr("STR_SACK"));
256 	_btnSack->onMouseClick((ActionHandler)&SoldierInfoState::btnSackClick);
257 
258 	_txtRank->setColor(Palette::blockOffset(13)+10);
259 	_txtRank->setSecondaryColor(Palette::blockOffset(13));
260 
261 	_txtMissions->setColor(Palette::blockOffset(13)+10);
262 	_txtMissions->setSecondaryColor(Palette::blockOffset(13));
263 
264 	_txtKills->setColor(Palette::blockOffset(13)+10);
265 	_txtKills->setSecondaryColor(Palette::blockOffset(13));
266 
267 	_txtCraft->setColor(Palette::blockOffset(13)+10);
268 	_txtCraft->setSecondaryColor(Palette::blockOffset(13));
269 
270 	_txtRecovery->setColor(Palette::blockOffset(13)+10);
271 	_txtRecovery->setSecondaryColor(Palette::blockOffset(13));
272 
273 	_txtPsionic->setColor(Palette::blockOffset(15)+1);
274 	_txtPsionic->setText(tr("STR_IN_PSIONIC_TRAINING"));
275 
276 
277 	_txtTimeUnits->setColor(Palette::blockOffset(15)+1);
278 	_txtTimeUnits->setText(tr("STR_TIME_UNITS"));
279 
280 	_numTimeUnits->setColor(Palette::blockOffset(13));
281 
282 	_barTimeUnits->setColor(Palette::blockOffset(3));
283 	_barTimeUnits->setColor2(Palette::blockOffset(3)+4);
284 	_barTimeUnits->setScale(1.0);
285 	_barTimeUnits->setInvert(true);
286 
287 	_txtStamina->setColor(Palette::blockOffset(15)+1);
288 	_txtStamina->setText(tr("STR_STAMINA"));
289 
290 	_numStamina->setColor(Palette::blockOffset(13));
291 
292 	_barStamina->setColor(Palette::blockOffset(9));
293 	_barStamina->setColor2(Palette::blockOffset(9)+4);
294 	_barStamina->setScale(1.0);
295 	_barStamina->setInvert(true);
296 
297 	_txtHealth->setColor(Palette::blockOffset(15)+1);
298 	_txtHealth->setText(tr("STR_HEALTH"));
299 
300 	_numHealth->setColor(Palette::blockOffset(13));
301 
302 	_barHealth->setColor(Palette::blockOffset(2));
303 	_barHealth->setColor2(Palette::blockOffset(2)+4);
304 	_barHealth->setScale(1.0);
305 	_barHealth->setInvert(true);
306 
307 	_txtBravery->setColor(Palette::blockOffset(15)+1);
308 	_txtBravery->setText(tr("STR_BRAVERY"));
309 
310 	_numBravery->setColor(Palette::blockOffset(13));
311 
312 	_barBravery->setColor(Palette::blockOffset(4));
313 	_barBravery->setColor2(Palette::blockOffset(4)+4);
314 	_barBravery->setScale(1.0);
315 	_barBravery->setInvert(true);
316 
317 	_txtReactions->setColor(Palette::blockOffset(15)+1);
318 	_txtReactions->setText(tr("STR_REACTIONS"));
319 
320 	_numReactions->setColor(Palette::blockOffset(13));
321 
322 	_barReactions->setColor(Palette::blockOffset(1));
323 	_barReactions->setColor2(Palette::blockOffset(1)+4);
324 	_barReactions->setScale(1.0);
325 	_barReactions->setInvert(true);
326 
327 	_txtFiring->setColor(Palette::blockOffset(15)+1);
328 	_txtFiring->setText(tr("STR_FIRING_ACCURACY"));
329 
330 	_numFiring->setColor(Palette::blockOffset(13));
331 
332 	_barFiring->setColor(Palette::blockOffset(8));
333 	_barFiring->setColor2(Palette::blockOffset(8)+4);
334 	_barFiring->setScale(1.0);
335 	_barFiring->setInvert(true);
336 
337 	_txtThrowing->setColor(Palette::blockOffset(15)+1);
338 	_txtThrowing->setText(tr("STR_THROWING_ACCURACY"));
339 
340 	_numThrowing->setColor(Palette::blockOffset(13));
341 
342 	_barThrowing->setColor(Palette::blockOffset(10));
343 	_barThrowing->setColor2(Palette::blockOffset(10)+4);
344 	_barThrowing->setScale(1.0);
345 	_barThrowing->setInvert(true);
346 
347 	_txtMelee->setColor(Palette::blockOffset(15)+1);
348 	_txtMelee->setText(tr("STR_MELEE_ACCURACY"));
349 
350 	_numMelee->setColor(Palette::blockOffset(13));
351 
352 	_barMelee->setColor(Palette::blockOffset(4));
353 	_barMelee->setColor2(Palette::blockOffset(4)+4);
354 	_barMelee->setScale(1.0);
355 	_barMelee->setInvert(true);
356 
357 	_txtStrength->setColor(Palette::blockOffset(15)+1);
358 	_txtStrength->setText(tr("STR_STRENGTH"));
359 
360 	_numStrength->setColor(Palette::blockOffset(13));
361 
362 	_barStrength->setColor(Palette::blockOffset(5));
363 	_barStrength->setColor2(Palette::blockOffset(5)+4);
364 	_barStrength->setScale(1.0);
365 	_barStrength->setInvert(true);
366 
367 	_txtPsiStrength->setColor(Palette::blockOffset(15)+1);
368 	_txtPsiStrength->setText(tr("STR_PSIONIC_STRENGTH"));
369 
370 	_numPsiStrength->setColor(Palette::blockOffset(13));
371 
372 	_barPsiStrength->setColor(Palette::blockOffset(11));
373 	_barPsiStrength->setColor2(Palette::blockOffset(11)+4);
374 	_barPsiStrength->setScale(1.0);
375 	_barPsiStrength->setInvert(true);
376 
377 	_txtPsiSkill->setColor(Palette::blockOffset(15)+1);
378 	_txtPsiSkill->setText(tr("STR_PSIONIC_SKILL"));
379 
380 	_numPsiSkill->setColor(Palette::blockOffset(13));
381 
382 	_barPsiSkill->setColor(Palette::blockOffset(11));
383 	_barPsiSkill->setColor2(Palette::blockOffset(11)+4);
384 	_barPsiSkill->setScale(1.0);
385 	_barPsiSkill->setInvert(true);
386 }
387 
388 /**
389  *
390  */
~SoldierInfoState()391 SoldierInfoState::~SoldierInfoState()
392 {
393 
394 }
395 
396 /**
397  * Updates soldier stats when
398  * the soldier changes.
399  */
init()400 void SoldierInfoState::init()
401 {
402 	State::init();
403 	if (_list->empty())
404 	{
405 		_game->popState();
406 		return;
407 	}
408 	if (_soldierId >= _list->size())
409 	{
410 		_soldierId = 0;
411 	}
412 	_soldier = _list->at(_soldierId);
413 	_edtSoldier->setBig();
414 	_edtSoldier->setText(_soldier->getName());
415 	UnitStats *initial = _soldier->getInitStats();
416 	UnitStats *current = _soldier->getCurrentStats();
417 
418 	SurfaceSet *texture = _game->getResourcePack()->getSurfaceSet("BASEBITS.PCK");
419 	texture->getFrame(_soldier->getRankSprite())->setX(0);
420 	texture->getFrame(_soldier->getRankSprite())->setY(0);
421 	texture->getFrame(_soldier->getRankSprite())->blit(_rank);
422 
423 	std::wostringstream ss;
424 	ss << current->tu;
425 	_numTimeUnits->setText(ss.str());
426 	_barTimeUnits->setMax(current->tu);
427 	_barTimeUnits->setValue(current->tu);
428 	_barTimeUnits->setValue2(initial->tu);
429 
430 	std::wostringstream ss2;
431 	ss2 << current->stamina;
432 	_numStamina->setText(ss2.str());
433 	_barStamina->setMax(current->stamina);
434 	_barStamina->setValue(current->stamina);
435 	_barStamina->setValue2(initial->stamina);
436 
437 	std::wostringstream ss3;
438 	ss3 << current->health;
439 	_numHealth->setText(ss3.str());
440 	_barHealth->setMax(current->health);
441 	_barHealth->setValue(current->health);
442 	_barHealth->setValue2(initial->health);
443 
444 	std::wostringstream ss4;
445 	ss4 << current->bravery;
446 	_numBravery->setText(ss4.str());
447 	_barBravery->setMax(current->bravery);
448 	_barBravery->setValue(current->bravery);
449 	_barBravery->setValue2(initial->bravery);
450 
451 	std::wostringstream ss5;
452 	ss5 << current->reactions;
453 	_numReactions->setText(ss5.str());
454 	_barReactions->setMax(current->reactions);
455 	_barReactions->setValue(current->reactions);
456 	_barReactions->setValue2(initial->reactions);
457 
458 	std::wostringstream ss6;
459 	ss6 << current->firing;
460 	_numFiring->setText(ss6.str());
461 	_barFiring->setMax(current->firing);
462 	_barFiring->setValue(current->firing);
463 	_barFiring->setValue2(initial->firing);
464 
465 	std::wostringstream ss7;
466 	ss7 << current->throwing;
467 	_numThrowing->setText(ss7.str());
468 	_barThrowing->setMax(current->throwing);
469 	_barThrowing->setValue(current->throwing);
470 	_barThrowing->setValue2(initial->throwing);
471 
472 	std::wostringstream ss8;
473 	ss8 << current->melee;
474 	_numMelee->setText(ss8.str());
475 	_barMelee->setMax(current->melee);
476 	_barMelee->setValue(current->melee);
477 	_barMelee->setValue2(initial->melee);
478 
479 	std::wostringstream ss9;
480 	ss9 << current->strength;
481 	_numStrength->setText(ss9.str());
482 	_barStrength->setMax(current->strength);
483 	_barStrength->setValue(current->strength);
484 	_barStrength->setValue2(initial->strength);
485 
486 	std::wstring wsArmor;
487 	std::string armorType = _soldier->getArmor()->getType();
488 	if (armorType == "STR_NONE_UC")
489 	{
490 		wsArmor= tr("STR_ARMOR_").arg(tr(armorType));
491 	}
492 	else
493 	{
494 		wsArmor = tr(armorType);
495 	}
496 
497 	_btnArmor->setText(wsArmor);
498 
499 	_btnSack->setVisible(!(_soldier->getCraft() && _soldier->getCraft()->getStatus() == "STR_OUT"));
500 
501 	_txtRank->setText(tr("STR_RANK_").arg(tr(_soldier->getRankString())));
502 
503 	_txtMissions->setText(tr("STR_MISSIONS").arg(_soldier->getMissions()));
504 
505 	_txtKills->setText(tr("STR_KILLS").arg(_soldier->getKills()));
506 
507 	std::wstring craft;
508 	if (_soldier->getCraft() == 0)
509 	{
510 		craft = tr("STR_NONE_UC");
511 	}
512 	else
513 	{
514 		craft = _soldier->getCraft()->getName(_game->getLanguage());
515 	}
516 	_txtCraft->setText(tr("STR_CRAFT_").arg(craft));
517 
518 	if (_soldier->getWoundRecovery() > 0)
519 	{
520 		_txtRecovery->setText(tr("STR_WOUND_RECOVERY").arg(tr("STR_DAY", _soldier->getWoundRecovery())));
521 	}
522 	else
523 	{
524 		_txtRecovery->setText(L"");
525 	}
526 
527 	_txtPsionic->setVisible(_soldier->isInPsiTraining());
528 
529 	if (current->psiSkill > 0 || (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getRuleset()->getPsiRequirements())))
530 	{
531 		std::wostringstream ss14;
532 		ss14 << current->psiStrength;
533 		_numPsiStrength->setText(ss14.str());
534 		_barPsiStrength->setMax(current->psiStrength);
535 		_barPsiStrength->setValue(current->psiStrength);
536 		_barPsiStrength->setValue2(initial->psiStrength);
537 
538 		_txtPsiStrength->setVisible(true);
539 		_numPsiStrength->setVisible(true);
540 		_barPsiStrength->setVisible(true);
541 	}
542 	else
543 	{
544 		_txtPsiStrength->setVisible(false);
545 		_numPsiStrength->setVisible(false);
546 		_barPsiStrength->setVisible(false);
547 	}
548 
549 	if (current->psiSkill > 0)
550 	{
551 		std::wostringstream ss15;
552 		ss15 << current->psiSkill;
553 		_numPsiSkill->setText(ss15.str());
554 		_barPsiSkill->setMax(current->psiSkill);
555 		_barPsiSkill->setValue(current->psiSkill);
556 		_barPsiSkill->setValue2(current->psiSkill - _soldier->getImprovement());
557 
558 		_txtPsiSkill->setVisible(true);
559 		_numPsiSkill->setVisible(true);
560 		_barPsiSkill->setVisible(true);
561 	}
562 	else
563 	{
564 		_txtPsiSkill->setVisible(false);
565 		_numPsiSkill->setVisible(false);
566 		_barPsiSkill->setVisible(false);
567 	}
568 
569 	// Dead can't talk
570 	if (_base == 0)
571 	{
572 		_btnArmor->setVisible(false);
573 		_btnSack->setVisible(false);
574 		_txtCraft->setVisible(false);
575 	}
576 	else
577 	{
578 		_btnSack->setVisible(_game->getSavedGame()->getMonthsPassed() > -1);
579 	}
580 }
581 
582 /**
583  * Disables the soldier input.
584  * @param action Pointer to an action.
585  */
edtSoldierPress(Action * action)586 void SoldierInfoState::edtSoldierPress(Action *action)
587 {
588 	if (_base == 0)
589 	{
590 		_edtSoldier->setFocus(false);
591 	}
592 }
593 
594 /**
595  * Changes the soldier's name.
596  * @param action Pointer to an action.
597  */
edtSoldierChange(Action * action)598 void SoldierInfoState::edtSoldierChange(Action *action)
599 {
600 	_soldier->setName(_edtSoldier->getText());
601 }
602 
603 /**
604  * Returns to the previous screen.
605  * @param action Pointer to an action.
606  */
btnOkClick(Action *)607 void SoldierInfoState::btnOkClick(Action *)
608 {
609 	_game->popState();
610 	if (_game->getSavedGame()->getMonthsPassed() > -1 && Options::storageLimitsEnforced && _base != 0 && _base->storesOverfull())
611 	{
612 		_game->pushState(new SellState(_game, _base));
613 		_game->pushState(new ErrorMessageState(_game, tr("STR_STORAGE_EXCEEDED").arg(_base->getName()).c_str(), _palette, Palette::blockOffset(15)+1, "BACK01.SCR", 0));
614 	}
615 }
616 
617 /**
618  * Goes to the previous soldier.
619  * @param action Pointer to an action.
620  */
btnPrevClick(Action *)621 void SoldierInfoState::btnPrevClick(Action *)
622 {
623 	if (_soldierId == 0)
624 		_soldierId = _list->size() - 1;
625 	else
626 		_soldierId--;
627 	init();
628 }
629 
630 /**
631  * Goes to the next soldier.
632  * @param action Pointer to an action.
633  */
btnNextClick(Action *)634 void SoldierInfoState::btnNextClick(Action *)
635 {
636 	_soldierId++;
637 	if (_soldierId >= _list->size())
638 		_soldierId = 0;
639 	init();
640 }
641 
642 /**
643  * Shows the Select Armor window.
644  * @param action Pointer to an action.
645  */
btnArmorClick(Action *)646 void SoldierInfoState::btnArmorClick(Action *)
647 {
648 	if (!_soldier->getCraft() || (_soldier->getCraft() && _soldier->getCraft()->getStatus() != "STR_OUT"))
649 	{
650 		_game->pushState(new SoldierArmorState(_game, _base, _soldierId));
651 	}
652 }
653 
654 /**
655  * Shows the Sack Soldier window.
656  * @param action Pointer to an action.
657  */
btnSackClick(Action *)658 void SoldierInfoState::btnSackClick(Action *)
659 {
660 	_game->pushState(new SackSoldierState(_game, _base, _soldierId));
661 }
662 
663 }
664