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 "BaseDefenseState.h"
20 #include <sstream>
21 #include "../Engine/Game.h"
22 #include "../Resource/ResourcePack.h"
23 #include "../Engine/Language.h"
24 #include "../Engine/Palette.h"
25 #include "../Interface/TextButton.h"
26 #include "../Interface/Window.h"
27 #include "../Interface/Text.h"
28 #include "../Savegame/SavedGame.h"
29 #include "../Savegame/Base.h"
30 #include "../Savegame/BaseFacility.h"
31 #include "../Ruleset/Ruleset.h"
32 #include "../Ruleset/RuleBaseFacility.h"
33 #include "../Savegame/Ufo.h"
34 #include "../Interface/TextList.h"
35 #include "GeoscapeState.h"
36 #include "../Engine/Action.h"
37 #include "../Engine/RNG.h"
38 #include "../Battlescape/BriefingState.h"
39 #include "../Battlescape/BattlescapeGenerator.h"
40 #include "../Engine/Sound.h"
41 #include "BaseDestroyedState.h"
42 #include "../Engine/Timer.h"
43 #include "../Engine/Options.h"
44 
45 namespace OpenXcom
46 {
47 
48 /**
49  * Initializes all the elements in the Base Defense screen.
50  * @param game Pointer to the core game.
51  * @param base Pointer to the base being attacked.
52  * @param ufo Pointer to the attacking ufo.
53  * @param state Pointer to the Geoscape.
54  */
BaseDefenseState(Game * game,Base * base,Ufo * ufo,GeoscapeState * state)55 BaseDefenseState::BaseDefenseState(Game *game, Base *base, Ufo *ufo, GeoscapeState *state) : State(game), _state(state)
56 {
57 	_base = base;
58 	_action = BDA_NONE;
59 	_row = -1;
60 	_passes = 0;
61 	_attacks = 0;
62 	_thinkcycles = 0;
63 	_ufo = ufo;
64 	// Create objects
65 	_window = new Window(this, 320, 200, 0, 0);
66 	_txtTitle = new Text(300, 17, 16, 6);
67 	_txtInit = new Text(300, 10, 16, 24);
68 	_lstDefenses = new TextList(300, 130, 16, 40);
69 	_btnOk = new TextButton(120, 18, 100, 170);
70 
71 	// Set palette
72 	setPalette("PAL_BASESCAPE", 2);
73 
74 	add(_window);
75 	add(_btnOk);
76 	add(_txtTitle);
77 	add(_txtInit);
78 	add(_lstDefenses);
79 
80 	centerAllSurfaces();
81 
82 	// Set up objects
83 	_window->setColor(Palette::blockOffset(15)+6);
84 	_window->setBackground(_game->getResourcePack()->getSurface("BACK04.SCR"));
85 
86 	_btnOk->setColor(Palette::blockOffset(13)+10);
87 	_btnOk->setText(tr("STR_OK"));
88 	_btnOk->onMouseClick((ActionHandler)&BaseDefenseState::btnOkClick);
89 	_btnOk->onKeyboardPress((ActionHandler)&BaseDefenseState::btnOkClick, Options::keyOk);
90 	_btnOk->onKeyboardPress((ActionHandler)&BaseDefenseState::btnOkClick, Options::keyCancel);
91 	_btnOk->setVisible(false);
92 
93 	_txtTitle->setColor(Palette::blockOffset(13)+10);
94 	_txtTitle->setBig();
95 	_txtTitle->setText(tr("STR_BASE_UNDER_ATTACK").arg(_base->getName()));
96 	_txtInit->setVisible(false);
97 
98 	_txtInit->setColor(Palette::blockOffset(13)+10);
99 	_txtInit->setText(tr("STR_BASE_DEFENSES_INITIATED"));
100 
101 	_lstDefenses->setColor(Palette::blockOffset(13)+10);
102 	_lstDefenses->setColumns(3, 134, 70, 50);
103 	_gravShields = _base->getGravShields();
104 	_defenses = _base->getDefenses()->size();
105 	_timer = new Timer(750);
106 	_timer->onTimer((StateHandler)&BaseDefenseState::nextStep);
107 	_timer->start();
108 }
109 /**
110  *
111  */
~BaseDefenseState()112 BaseDefenseState::~BaseDefenseState()
113 {
114 	delete _timer;
115 }
116 
think()117 void BaseDefenseState::think()
118 {
119 	_timer->think(this, 0);
120 }
121 
nextStep()122 void BaseDefenseState::nextStep()
123 {
124 	if (_thinkcycles == -1)
125 		return;
126 
127 	++_thinkcycles;
128 
129 	if (_thinkcycles == 1)
130 	{
131 		_txtInit->setVisible(true);
132 		return;
133 	}
134 
135 	if (_thinkcycles > 1)
136 	{
137 		switch (_action)
138 		{
139 		case BDA_DESTROY:
140 			_lstDefenses->addRow(2, tr("STR_UFO_DESTROYED").c_str(),L" ",L" ");
141 			_game->getResourcePack()->getSound("GEO.CAT", 11)->play();
142 			_action = BDA_END;
143 			return;
144 		case BDA_END:
145 			_btnOk->setVisible(true);
146 			_thinkcycles = -1;
147 			return;
148 		default:
149 			break;
150 		}
151 		if (_attacks == _defenses && _passes == _gravShields)
152 		{
153 			_action = BDA_END;
154 			return;
155 		}
156 		else if (_attacks == _defenses && _passes < _gravShields)
157 		{
158 			_lstDefenses->addRow(3, tr("STR_GRAV_SHIELD_REPELS_UFO").c_str(),L" ",L" ");
159 			++_row;
160 			++_passes;
161 			_attacks = 0;
162 			return;
163 		}
164 
165 
166 
167 		BaseFacility* def = _base->getDefenses()->at(_attacks);
168 
169 		switch (_action)
170 		{
171 		case  BDA_NONE:
172 			_lstDefenses->addRow(3, tr((def)->getRules()->getType()).c_str(),L" ",L" ");
173 			++_row;
174 			_action = BDA_FIRE;
175 			return;
176 		case BDA_FIRE:
177 			_lstDefenses->setCellText(_row, 1, tr("STR_FIRING").c_str());
178 			_game->getResourcePack()->getSound("GEO.CAT", (def)->getRules()->getFireSound())->play();
179 			_action = BDA_RESOLVE;
180 			return;
181 		case BDA_RESOLVE:
182 			if (!RNG::percent((def)->getRules()->getHitRatio()))
183 			{
184 				_lstDefenses->setCellText(_row, 2, tr("STR_MISSED").c_str());
185 			}
186 			else
187 			{
188 				_lstDefenses->setCellText(_row, 2, tr("STR_HIT").c_str());
189 				_game->getResourcePack()->getSound("GEO.CAT", (def)->getRules()->getHitSound())->play();
190 				_ufo->setDamage(_ufo->getDamage() + (def)->getRules()->getDefenseValue());
191 			}
192 			if (_ufo->getStatus() == Ufo::DESTROYED)
193 				_action = BDA_DESTROY;
194 			else
195 				_action = BDA_NONE;
196 			++_attacks;
197 			return;
198 		default:
199 			break;
200 		}
201 	}
202 }
203 /**
204  * Returns to the previous screen.
205  * @param action Pointer to an action.
206  */
btnOkClick(Action *)207 void BaseDefenseState::btnOkClick(Action *)
208 {
209 	_timer->stop();
210 	_game->popState();
211 	if(_ufo->getStatus() != Ufo::DESTROYED)
212 	{
213 		// Whatever happens in the base defense, the UFO has finished its duty
214 		_ufo->setStatus(Ufo::DESTROYED);
215         _state->handleBaseDefense(_base, _ufo);
216 	}
217 }
218 }
219