/*
* 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 "BaseDefenseState.h"
#include "../Engine/Game.h"
#include "../Mod/Mod.h"
#include "../Engine/LocalizedText.h"
#include "../Interface/TextButton.h"
#include "../Interface/Window.h"
#include "../Interface/Text.h"
#include "../Savegame/Base.h"
#include "../Savegame/BaseFacility.h"
#include "../Mod/RuleBaseFacility.h"
#include "../Savegame/Ufo.h"
#include "../Interface/TextList.h"
#include "GeoscapeState.h"
#include "../Engine/Action.h"
#include "../Engine/RNG.h"
#include "../Engine/Sound.h"
#include "../Engine/Timer.h"
#include "../Engine/Options.h"
namespace OpenXcom
{
/**
* Initializes all the elements in the Base Defense screen.
* @param game Pointer to the core game.
* @param base Pointer to the base being attacked.
* @param ufo Pointer to the attacking ufo.
* @param state Pointer to the Geoscape.
*/
BaseDefenseState::BaseDefenseState(Base *base, Ufo *ufo, GeoscapeState *state) : _state(state)
{
_base = base;
_action = BDA_NONE;
_row = -1;
_passes = 0;
_attacks = 0;
_thinkcycles = 0;
_ufo = ufo;
// Create objects
_window = new Window(this, 320, 200, 0, 0);
_txtTitle = new Text(300, 17, 16, 6);
_txtInit = new Text(300, 10, 16, 24);
_lstDefenses = new TextList(300, 128, 16, 40);
_btnOk = new TextButton(120, 18, 100, 170);
// Set palette
setInterface("baseDefense");
add(_window, "window", "baseDefense");
add(_btnOk, "button", "baseDefense");
add(_txtTitle, "text", "baseDefense");
add(_txtInit, "text", "baseDefense");
add(_lstDefenses, "text", "baseDefense");
centerAllSurfaces();
// Set up objects
_window->setBackground(_game->getMod()->getSurface("BACK04.SCR"));
_btnOk->setText(tr("STR_OK"));
_btnOk->onMouseClick((ActionHandler)&BaseDefenseState::btnOkClick);
_btnOk->onKeyboardPress((ActionHandler)&BaseDefenseState::btnOkClick, Options::keyOk);
_btnOk->onKeyboardPress((ActionHandler)&BaseDefenseState::btnOkClick, Options::keyCancel);
_btnOk->setVisible(false);
_txtTitle->setBig();
_txtTitle->setText(tr("STR_BASE_UNDER_ATTACK").arg(_base->getName()));
_txtInit->setVisible(false);
_txtInit->setText(tr("STR_BASE_DEFENSES_INITIATED"));
_lstDefenses->setColumns(3, 134, 70, 50);
_gravShields = _base->getGravShields();
_defenses = _base->getDefenses()->size();
_timer = new Timer(250);
_timer->onTimer((StateHandler)&BaseDefenseState::nextStep);
_timer->start();
_explosionCount = 0;
}
/**
*
*/
BaseDefenseState::~BaseDefenseState()
{
delete _timer;
}
void BaseDefenseState::think()
{
_timer->think(this, 0);
}
void BaseDefenseState::nextStep()
{
if (_thinkcycles == -1)
return;
++_thinkcycles;
if (_thinkcycles == 1)
{
_txtInit->setVisible(true);
return;
}
if (_thinkcycles > 1)
{
switch (_action)
{
case BDA_DESTROY:
if (!_explosionCount)
{
_lstDefenses->addRow(2, tr("STR_UFO_DESTROYED").c_str(),L" ",L" ");
++_row;
if (_row > 14)
{
_lstDefenses->scrollDown(true);
}
}
_game->getMod()->getSound("GEO.CAT", Mod::UFO_EXPLODE)->play();
if (++_explosionCount == 3)
{
_action = BDA_END;
}
return;
case BDA_END:
_btnOk->setVisible(true);
_thinkcycles = -1;
return;
default:
break;
}
if (_attacks == _defenses && _passes == _gravShields)
{
_action = BDA_END;
return;
}
else if (_attacks == _defenses && _passes < _gravShields)
{
_lstDefenses->addRow(3, tr("STR_GRAV_SHIELD_REPELS_UFO").c_str(),L" ",L" ");
if (_row > 14)
{
_lstDefenses->scrollDown(true);
}
++_row;
++_passes;
_attacks = 0;
return;
}
BaseFacility* def = _base->getDefenses()->at(_attacks);
switch (_action)
{
case BDA_NONE:
_lstDefenses->addRow(3, tr((def)->getRules()->getType()).c_str(),L" ",L" ");
++_row;
_action = BDA_FIRE;
if (_row > 14)
{
_lstDefenses->scrollDown(true);
}
return;
case BDA_FIRE:
_lstDefenses->setCellText(_row, 1, tr("STR_FIRING"));
_game->getMod()->getSound("GEO.CAT", (def)->getRules()->getFireSound())->play();
_timer->setInterval(333);
_action = BDA_RESOLVE;
return;
case BDA_RESOLVE:
if (!RNG::percent((def)->getRules()->getHitRatio()))
{
_lstDefenses->setCellText(_row, 2, tr("STR_MISSED"));
}
else
{
_lstDefenses->setCellText(_row, 2, tr("STR_HIT"));
_game->getMod()->getSound("GEO.CAT", (def)->getRules()->getHitSound())->play();
int dmg = (def)->getRules()->getDefenseValue();
_ufo->setDamage(_ufo->getDamage() + (dmg / 2 + RNG::generate(0, dmg)));
}
if (_ufo->getStatus() == Ufo::DESTROYED)
_action = BDA_DESTROY;
else
_action = BDA_NONE;
++_attacks;
_timer->setInterval(250);
return;
default:
break;
}
}
}
/**
* Returns to the previous screen.
* @param action Pointer to an action.
*/
void BaseDefenseState::btnOkClick(Action *)
{
_timer->stop();
_game->popState();
if (_ufo->getStatus() != Ufo::DESTROYED)
{
_state->handleBaseDefense(_base, _ufo);
}
else
{
_base->cleanupDefenses(true);
}
}
}
↑ V807 Decreased performance. Consider creating a pointer to avoid using the '(def)->getRules()' expression repeatedly.