/*
* Copyright 2010-2016 OpenXcom Developers.
*
* This file is part of OpenXcom.
*
* OpenXcom is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenXcom is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenXcom. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UnitInfoState.h"
#include <sstream>
#include "../Savegame/BattleUnit.h"
#include "../Savegame/SavedGame.h"
#include "../Savegame/SavedBattleGame.h"
#include "../Engine/Game.h"
#include "../Engine/Action.h"
#include "../Engine/Screen.h"
#include "../Mod/Mod.h"
#include "../Engine/LocalizedText.h"
#include "../Interface/Bar.h"
#include "../Interface/Text.h"
#include "../Interface/TextButton.h"
#include "../Engine/InteractiveSurface.h"
#include "../Mod/Unit.h"
#include "../Engine/Options.h"
#include "BattlescapeGame.h"
#include "BattlescapeState.h"
#include "../Mod/RuleInterface.h"
namespace OpenXcom
{
/**
* Initializes all the elements in the Unit Info screen.
* @param game Pointer to the core game.
* @param unit Pointer to the selected unit.
* @param parent Pointer to parent Battlescape.
* @param fromInventory Is player coming from the inventory?
* @param mindProbe Is player using a Mind Probe?
*/
UnitInfoState::UnitInfoState(BattleUnit *unit, BattlescapeState *parent, bool fromInventory, bool mindProbe) : _unit(unit), _parent(parent), _fromInventory(fromInventory), _mindProbe(mindProbe)
{
if (Options::maximizeInfoScreens)
{
Options::baseXResolution = Screen::ORIGINAL_WIDTH;
Options::baseYResolution = Screen::ORIGINAL_HEIGHT;
_game->getScreen()->resetDisplay(false);
}
_battleGame = _game->getSavedGame()->getSavedBattle();
// Create objects
_bg = new Surface(320, 200, 0, 0);
_exit = new InteractiveSurface(320, 180, 0, 20);
_txtName = new Text(288, 17, 16, 4);
int yPos = 38;
int step = 9;
_txtTimeUnits = new Text(140, 9, 8, yPos);
_numTimeUnits = new Text(18, 9, 150, yPos);
_barTimeUnits = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtEnergy = new Text(140, 9, 8, yPos);
_numEnergy = new Text(18, 9, 150, yPos);
_barEnergy = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtHealth = new Text(140, 9, 8, yPos);
_numHealth = new Text(18, 9, 150, yPos);
_barHealth = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtFatalWounds = new Text(140, 9, 8, yPos);
_numFatalWounds = new Text(18, 9, 150, yPos);
_barFatalWounds = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtBravery = new Text(140, 9, 8, yPos);
_numBravery = new Text(18, 9, 150, yPos);
_barBravery = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtMorale = new Text(140, 9, 8, yPos);
_numMorale = new Text(18, 9, 150, yPos);
_barMorale = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtReactions = new Text(140, 9, 8, yPos);
_numReactions = new Text(18, 9, 150, yPos);
_barReactions = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtFiring = new Text(140, 9, 8, yPos);
_numFiring = new Text(18, 9, 150, yPos);
_barFiring = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtThrowing = new Text(140, 9, 8, yPos);
_numThrowing = new Text(18, 9, 150, yPos);
_barThrowing = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtMelee = new Text(140, 9, 8, yPos);
_numMelee = new Text(18, 9, 150, yPos);
_barMelee = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtStrength = new Text(140, 9, 8, yPos);
_numStrength = new Text(18, 9, 150, yPos);
_barStrength = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtPsiStrength = new Text(140, 9, 8, yPos);
_numPsiStrength = new Text(18, 9, 150, yPos);
_barPsiStrength = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtPsiSkill = new Text(140, 9, 8, yPos);
_numPsiSkill = new Text(18, 9, 150, yPos);
_barPsiSkill = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtFrontArmor = new Text(140, 9, 8, yPos);
_numFrontArmor= new Text(18, 9, 150, yPos);
_barFrontArmor = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtLeftArmor = new Text(140, 9, 8, yPos);
_numLeftArmor = new Text(18, 9, 150, yPos);
_barLeftArmor = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtRightArmor = new Text(140, 9, 8, yPos);
_numRightArmor = new Text(18, 9, 150, yPos);
_barRightArmor = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtRearArmor = new Text(140, 9, 8, yPos);
_numRearArmor = new Text(18, 9, 150, yPos);
_barRearArmor = new Bar(150, 5, 170, yPos + 1);
yPos += step;
_txtUnderArmor = new Text(140, 9, 8, yPos);
_numUnderArmor = new Text(18, 9, 150, yPos);
_barUnderArmor = new Bar(150, 5, 170, yPos + 1);
if (!_mindProbe)
{
_btnPrev = new TextButton(14, 18, 2, 2);
_btnNext = new TextButton(14, 18, 304, 2);
}
// Set palette
setPalette("PAL_BATTLESCAPE");
add(_bg);
add(_exit);
add(_txtName, "textName", "stats", 0);
add(_txtTimeUnits);
add(_numTimeUnits);
add(_barTimeUnits, "barTUs", "stats", 0);
add(_txtEnergy);
add(_numEnergy);
add(_barEnergy, "barEnergy", "stats", 0);
add(_txtHealth);
add(_numHealth);
add(_barHealth, "barHealth", "stats", 0);
add(_txtFatalWounds);
add(_numFatalWounds);
add(_barFatalWounds, "barWounds", "stats", 0);
add(_txtBravery);
add(_numBravery);
add(_barBravery, "barBravery", "stats", 0);
add(_txtMorale);
add(_numMorale);
add(_barMorale, "barMorale", "stats", 0);
add(_txtReactions);
add(_numReactions);
add(_barReactions, "barReactions", "stats", 0);
add(_txtFiring);
add(_numFiring);
add(_barFiring, "barFiring", "stats", 0);
add(_txtThrowing);
add(_numThrowing);
add(_barThrowing, "barThrowing", "stats", 0);
add(_txtMelee);
add(_numMelee);
add(_barMelee, "barMelee", "stats", 0);
add(_txtStrength);
add(_numStrength);
add(_barStrength, "barStrength", "stats", 0);
add(_txtPsiStrength);
add(_numPsiStrength);
add(_barPsiStrength, "barPsiStrength", "stats", 0);
add(_txtPsiSkill);
add(_numPsiSkill);
add(_barPsiSkill, "barPsiSkill", "stats", 0);
add(_txtFrontArmor);
add(_numFrontArmor);
add(_barFrontArmor, "barFrontArmor", "stats", 0);
add(_txtLeftArmor);
add(_numLeftArmor);
add(_barLeftArmor, "barLeftArmor", "stats", 0);
add(_txtRightArmor);
add(_numRightArmor);
add(_barRightArmor, "barRightArmor", "stats", 0);
add(_txtRearArmor);
add(_numRearArmor);
add(_barRearArmor, "barRearArmor", "stats", 0);
add(_txtUnderArmor);
add(_numUnderArmor);
add(_barUnderArmor, "barUnderArmor", "stats", 0);
if (!_mindProbe)
{
add(_btnPrev, "button", "stats");
add(_btnNext, "button", "stats");
}
centerAllSurfaces();
// Set up objects
_game->getMod()->getSurface("UNIBORD.PCK")->blit(_bg);
_exit->onMouseClick((ActionHandler)&UnitInfoState::exitClick);
_exit->onKeyboardPress((ActionHandler)&UnitInfoState::exitClick, Options::keyCancel);
_exit->onKeyboardPress((ActionHandler)&UnitInfoState::exitClick, Options::keyBattleStats);
Uint8 color = _game->getMod()->getInterface("stats")->getElement("text")->color;
Uint8 color2 = _game->getMod()->getInterface("stats")->getElement("text")->color2;
_txtName->setAlign(ALIGN_CENTER);
_txtName->setBig();
_txtName->setHighContrast(true);
_txtTimeUnits->setColor(color);
_txtTimeUnits->setHighContrast(true);
_txtTimeUnits->setText(tr("STR_TIME_UNITS"));
_numTimeUnits->setColor(color2);
_numTimeUnits->setHighContrast(true);
_barTimeUnits->setScale(1.0);
_txtEnergy->setColor(color);
_txtEnergy->setHighContrast(true);
_txtEnergy->setText(tr("STR_ENERGY"));
_numEnergy->setColor(color2);
_numEnergy->setHighContrast(true);
_barEnergy->setScale(1.0);
_txtHealth->setColor(color);
_txtHealth->setHighContrast(true);
_txtHealth->setText(tr("STR_HEALTH"));
_numHealth->setColor(color2);
_numHealth->setHighContrast(true);
_barHealth->setScale(1.0);
_txtFatalWounds->setColor(color);
_txtFatalWounds->setHighContrast(true);
_txtFatalWounds->setText(tr("STR_FATAL_WOUNDS"));
_numFatalWounds->setColor(color2);
_numFatalWounds->setHighContrast(true);
_barFatalWounds->setScale(1.0);
_txtBravery->setColor(color);
_txtBravery->setHighContrast(true);
_txtBravery->setText(tr("STR_BRAVERY"));
_numBravery->setColor(color2);
_numBravery->setHighContrast(true);
_barBravery->setScale(1.0);
_txtMorale->setColor(color);
_txtMorale->setHighContrast(true);
_txtMorale->setText(tr("STR_MORALE"));
_numMorale->setColor(color2);
_numMorale->setHighContrast(true);
_barMorale->setScale(1.0);
_txtReactions->setColor(color);
_txtReactions->setHighContrast(true);
_txtReactions->setText(tr("STR_REACTIONS"));
_numReactions->setColor(color2);
_numReactions->setHighContrast(true);
_barReactions->setScale(1.0);
_txtFiring->setColor(color);
_txtFiring->setHighContrast(true);
_txtFiring->setText(tr("STR_FIRING_ACCURACY"));
_numFiring->setColor(color2);
_numFiring->setHighContrast(true);
_barFiring->setScale(1.0);
_txtThrowing->setColor(color);
_txtThrowing->setHighContrast(true);
_txtThrowing->setText(tr("STR_THROWING_ACCURACY"));
_numThrowing->setColor(color2);
_numThrowing->setHighContrast(true);
_barThrowing->setScale(1.0);
_txtMelee->setColor(color);
_txtMelee->setHighContrast(true);
_txtMelee->setText(tr("STR_MELEE_ACCURACY"));
_numMelee->setColor(color2);
_numMelee->setHighContrast(true);
_barMelee->setScale(1.0);
_txtStrength->setColor(color);
_txtStrength->setHighContrast(true);
_txtStrength->setText(tr("STR_STRENGTH"));
_numStrength->setColor(color2);
_numStrength->setHighContrast(true);
_barStrength->setScale(1.0);
_txtPsiStrength->setColor(color);
_txtPsiStrength->setHighContrast(true);
_txtPsiStrength->setText(tr("STR_PSIONIC_STRENGTH"));
_numPsiStrength->setColor(color2);
_numPsiStrength->setHighContrast(true);
_barPsiStrength->setScale(1.0);
_txtPsiSkill->setColor(color);
_txtPsiSkill->setHighContrast(true);
_txtPsiSkill->setText(tr("STR_PSIONIC_SKILL"));
_numPsiSkill->setColor(color2);
_numPsiSkill->setHighContrast(true);
_barPsiSkill->setScale(1.0);
_txtFrontArmor->setColor(color);
_txtFrontArmor->setHighContrast(true);
_txtFrontArmor->setText(tr("STR_FRONT_ARMOR_UC"));
_numFrontArmor->setColor(color2);
_numFrontArmor->setHighContrast(true);
_barFrontArmor->setScale(1.0);
_txtLeftArmor->setColor(color);
_txtLeftArmor->setHighContrast(true);
_txtLeftArmor->setText(tr("STR_LEFT_ARMOR_UC"));
_numLeftArmor->setColor(color2);
_numLeftArmor->setHighContrast(true);
_barLeftArmor->setScale(1.0);
_txtRightArmor->setColor(color);
_txtRightArmor->setHighContrast(true);
_txtRightArmor->setText(tr("STR_RIGHT_ARMOR_UC"));
_numRightArmor->setColor(color2);
_numRightArmor->setHighContrast(true);
_barRightArmor->setScale(1.0);
_txtRearArmor->setColor(color);
_txtRearArmor->setHighContrast(true);
_txtRearArmor->setText(tr("STR_REAR_ARMOR_UC"));
_numRearArmor->setColor(color2);
_numRearArmor->setHighContrast(true);
_barRearArmor->setScale(1.0);
_txtUnderArmor->setColor(color);
_txtUnderArmor->setHighContrast(true);
_txtUnderArmor->setText(tr("STR_UNDER_ARMOR_UC"));
_numUnderArmor->setColor(color2);
_numUnderArmor->setHighContrast(true);
_barUnderArmor->setScale(1.0);
if (!_mindProbe)
{
_btnPrev->setText("<<");
_btnPrev->onMouseClick((ActionHandler)&UnitInfoState::btnPrevClick);
_btnPrev->onKeyboardPress((ActionHandler)&UnitInfoState::btnPrevClick, Options::keyBattlePrevUnit);
_btnNext->setText(">>");
_btnNext->onMouseClick((ActionHandler)&UnitInfoState::btnNextClick);
_btnNext->onKeyboardPress((ActionHandler)&UnitInfoState::btnNextClick, Options::keyBattleNextUnit);
}
}
/**
*
*/
UnitInfoState::~UnitInfoState()
{
}
/**
* Updates unit info which can change
* after going into other screens.
*/
void UnitInfoState::init()
{
State::init();
std::ostringstream ss;
ss << _unit->getTimeUnits();
_numTimeUnits->setText(ss.str());
_barTimeUnits->setMax(_unit->getBaseStats()->tu);
_barTimeUnits->setValue(_unit->getTimeUnits());
ss.str("");
// aliens have their rank in their "name", soldiers don't
if (_unit->getType() == "SOLDIER")
{
ss << tr(_unit->getRankString());
ss << " ";
}
ss << _unit->getName(_game->getLanguage(), BattlescapeGame::_debugPlay);
_txtName->setBig();
_txtName->setText(ss.str());
ss.str("");
ss << _unit->getEnergy();
_numEnergy->setText(ss.str());
_barEnergy->setMax(_unit->getBaseStats()->stamina);
_barEnergy->setValue(_unit->getEnergy());
ss.str("");
ss << _unit->getHealth();
_numHealth->setText(ss.str());
_barHealth->setMax(_unit->getBaseStats()->health);
_barHealth->setValue(_unit->getHealth());
_barHealth->setValue2(_unit->getStunlevel());
ss.str("");
ss << _unit->getFatalWounds();
_numFatalWounds->setText(ss.str());
_barFatalWounds->setMax(_unit->getFatalWounds());
_barFatalWounds->setValue(_unit->getFatalWounds());
ss.str("");
ss << _unit->getBaseStats()->bravery;
_numBravery->setText(ss.str());
_barBravery->setMax(_unit->getBaseStats()->bravery);
_barBravery->setValue(_unit->getBaseStats()->bravery);
ss.str("");
ss << _unit->getMorale();
_numMorale->setText(ss.str());
_barMorale->setMax(100);
_barMorale->setValue(_unit->getMorale());
ss.str("");
ss << _unit->getBaseStats()->reactions;
_numReactions->setText(ss.str());
_barReactions->setMax(_unit->getBaseStats()->reactions);
_barReactions->setValue(_unit->getBaseStats()->reactions);
ss.str("");
ss << ((_unit->getBaseStats()->firing * _unit->getHealth()) / _unit->getBaseStats()->health);
_numFiring->setText(ss.str());
_barFiring->setMax(_unit->getBaseStats()->firing);
_barFiring->setValue((_unit->getBaseStats()->firing * _unit->getHealth()) / _unit->getBaseStats()->health);
ss.str("");
ss << ((_unit->getBaseStats()->throwing * _unit->getHealth()) / _unit->getBaseStats()->health);
_numThrowing->setText(ss.str());
_barThrowing->setMax(_unit->getBaseStats()->throwing);
_barThrowing->setValue((_unit->getBaseStats()->throwing * _unit->getHealth()) / _unit->getBaseStats()->health);
ss.str("");
ss << ((_unit->getBaseStats()->melee * _unit->getHealth()) / _unit->getBaseStats()->health);
_numMelee->setText(ss.str());
_barMelee->setMax(_unit->getBaseStats()->melee);
_barMelee->setValue((_unit->getBaseStats()->melee * _unit->getHealth()) / _unit->getBaseStats()->health);
ss.str("");
ss << _unit->getBaseStats()->strength;
_numStrength->setText(ss.str());
_barStrength->setMax(_unit->getBaseStats()->strength);
_barStrength->setValue(_unit->getBaseStats()->strength);
if (_unit->getBaseStats()->psiSkill > 0 || (Options::psiStrengthEval && _game->getSavedGame()->isResearched(_game->getMod()->getPsiRequirements())))
{
ss.str("");
ss << _unit->getBaseStats()->psiStrength;
_numPsiStrength->setText(ss.str());
_barPsiStrength->setMax(_unit->getBaseStats()->psiStrength);
_barPsiStrength->setValue(_unit->getBaseStats()->psiStrength);
_txtPsiStrength->setVisible(true);
_numPsiStrength->setVisible(true);
_barPsiStrength->setVisible(true);
}
else
{
_txtPsiStrength->setVisible(false);
_numPsiStrength->setVisible(false);
_barPsiStrength->setVisible(false);
}
if (_unit->getBaseStats()->psiSkill > 0)
{
ss.str("");
ss << _unit->getBaseStats()->psiSkill;
_numPsiSkill->setText(ss.str());
_barPsiSkill->setMax(_unit->getBaseStats()->psiSkill);
_barPsiSkill->setValue(_unit->getBaseStats()->psiSkill);
_txtPsiSkill->setVisible(true);
_numPsiSkill->setVisible(true);
_barPsiSkill->setVisible(true);
}
else
{
_txtPsiSkill->setVisible(false);
_numPsiSkill->setVisible(false);
_barPsiSkill->setVisible(false);
}
ss.str("");
ss << _unit->getArmor(SIDE_FRONT);
_numFrontArmor->setText(ss.str());
_barFrontArmor->setMax(_unit->getMaxArmor(SIDE_FRONT));
_barFrontArmor->setValue(_unit->getArmor(SIDE_FRONT));
ss.str("");
ss << _unit->getArmor(SIDE_LEFT);
_numLeftArmor->setText(ss.str());
_barLeftArmor->setMax(_unit->getMaxArmor(SIDE_LEFT));
_barLeftArmor->setValue(_unit->getArmor(SIDE_LEFT));
ss.str("");
ss << _unit->getArmor(SIDE_RIGHT);
_numRightArmor->setText(ss.str());
_barRightArmor->setMax(_unit->getMaxArmor(SIDE_RIGHT));
_barRightArmor->setValue(_unit->getArmor(SIDE_RIGHT));
ss.str("");
ss << _unit->getArmor(SIDE_REAR);
_numRearArmor->setText(ss.str());
_barRearArmor->setMax(_unit->getMaxArmor(SIDE_REAR));
_barRearArmor->setValue(_unit->getArmor(SIDE_REAR));
ss.str("");
ss << _unit->getArmor(SIDE_UNDER);
_numUnderArmor->setText(ss.str());
_barUnderArmor->setMax(_unit->getMaxArmor(SIDE_UNDER));
_barUnderArmor->setValue(_unit->getArmor(SIDE_UNDER));
}
/**
* Closes the window on right-click.
* @param action Pointer to an action.
*/
void UnitInfoState::handle(Action *action)
{
State::handle(action);
if (action->getDetails()->type == SDL_MOUSEBUTTONDOWN)
{
if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)
{
exitClick(action);
}
else if (action->getDetails()->button.button == SDL_BUTTON_X1)
{
if (!_mindProbe) btnNextClick(action);
}
else if (action->getDetails()->button.button == SDL_BUTTON_X2)
{
if (!_mindProbe) btnPrevClick(action);
}
}
}
/**
* Selects the previous unit.
* @param action Pointer to an action.
*/
void UnitInfoState::btnPrevClick(Action *action)
{
if (_parent)
{ // so we are here from a Battlescape Game
_parent->selectPreviousPlayerUnit(false, false, _fromInventory);
}
else
{ // so we are here from the Craft Equipment screen
_battleGame->selectPreviousPlayerUnit(false, false, true);
}
_unit = _battleGame->getSelectedUnit();
if (_unit != 0)
{
init();
}
else
{
exitClick(action);
}
}
/**
* Selects the next unit.
* @param action Pointer to an action.
*/
void UnitInfoState::btnNextClick(Action *action)
{
if (_parent)
{ // so we are here from a Battlescape Game
_parent->selectNextPlayerUnit(false, false, _fromInventory);
}
else
{ // so we are here from the Craft Equipment screen
_battleGame->selectNextPlayerUnit(false, false, true);
}
_unit = _battleGame->getSelectedUnit();
if (_unit != 0)
{
init();
}
else
{
exitClick(action);
}
}
/**
* Exits the screen.
* @param action Pointer to an action.
*/
void UnitInfoState::exitClick(Action *)
{
if (!_fromInventory && Options::maximizeInfoScreens)
{
Screen::updateScale(Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, true);
_game->getScreen()->resetDisplay(false);
}
_game->popState();
}
}
↑ V807 Decreased performance. Consider creating a pointer to avoid using the '_unit->getBaseStats()' expression repeatedly.
↑ V807 Decreased performance. Consider creating a pointer to avoid using the '_game->getMod()' expression repeatedly.
↑ V807 Decreased performance. Consider creating a pointer to avoid using the 'action->getDetails()' expression repeatedly.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'action->getDetails()->button' expression repeatedly.