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 "CraftInfoState.h"
20 #include <cmath>
21 #include <sstream>
22 #include "../Engine/Game.h"
23 #include "../Resource/ResourcePack.h"
24 #include "../Engine/Language.h"
25 #include "../Engine/Palette.h"
26 #include "../Engine/Options.h"
27 #include "../Interface/TextButton.h"
28 #include "../Interface/Window.h"
29 #include "../Interface/Text.h"
30 #include "../Interface/TextEdit.h"
31 #include "../Engine/SurfaceSet.h"
32 #include "../Engine/Action.h"
33 #include "../Savegame/Craft.h"
34 #include "../Ruleset/RuleCraft.h"
35 #include "../Savegame/CraftWeapon.h"
36 #include "../Ruleset/RuleCraftWeapon.h"
37 #include "../Savegame/Base.h"
38 #include "../Savegame/SavedGame.h"
39 #include "CraftSoldiersState.h"
40 #include "CraftWeaponsState.h"
41 #include "CraftEquipmentState.h"
42 #include "CraftArmorState.h"
43
44 namespace OpenXcom
45 {
46
47 /**
48 * Initializes all the elements in the Craft Info screen.
49 * @param game Pointer to the core game.
50 * @param base Pointer to the base to get info from.
51 * @param craftId ID of the selected craft.
52 */
CraftInfoState(Game * game,Base * base,size_t craftId)53 CraftInfoState::CraftInfoState(Game *game, Base *base, size_t craftId) : State(game), _base(base), _craftId(craftId)
54 {
55 // Create objects
56 if (_game->getSavedGame()->getMonthsPassed() != -1)
57 {
58 _window = new Window(this, 320, 200, 0, 0, POPUP_BOTH);
59 }
60 else
61 {
62 _window = new Window(this, 320, 200, 0, 0, POPUP_NONE);
63 }
64 _btnOk = new TextButton(64, 24, 128, 168);
65 _btnW1 = new TextButton(24, 32, 14, 48);
66 _btnW2 = new TextButton(24, 32, 282, 48);
67 _btnCrew = new TextButton(64, 16, 14, 96);
68 _btnEquip = new TextButton(64, 16, 14, 120);
69 _btnArmor = new TextButton(64, 16, 14, 144);
70 _edtCraft = new TextEdit(this, 140, 16, 80, 8);
71 _txtDamage = new Text(100, 17, 14, 24);
72 _txtFuel = new Text(82, 17, 228, 24);
73 _txtW1Name = new Text(75, 16, 46, 48);
74 _txtW1Ammo = new Text(75, 24, 46, 64);
75 _txtW2Name = new Text(75, 16, 204, 48);
76 _txtW2Ammo = new Text(75, 24, 204, 64);
77 _sprite = new Surface(32, 40, 144, 52);
78 _weapon1 = new Surface(15, 17, 121, 63);
79 _weapon2 = new Surface(15, 17, 184, 63);
80 _crew = new Surface(220, 18, 85, 96);
81 _equip = new Surface(220, 18, 85, 121);
82
83 // Set palette
84 setPalette("PAL_BASESCAPE", 3);
85
86 add(_window);
87 add(_btnOk);
88 add(_btnW1);
89 add(_btnW2);
90 add(_btnCrew);
91 add(_btnEquip);
92 add(_btnArmor);
93 add(_edtCraft);
94 add(_txtDamage);
95 add(_txtFuel);
96 add(_txtW1Name);
97 add(_txtW1Ammo);
98 add(_txtW2Name);
99 add(_txtW2Ammo);
100 add(_sprite);
101 add(_weapon1);
102 add(_weapon2);
103 add(_crew);
104 add(_equip);
105
106 centerAllSurfaces();
107
108 // Set up objects
109 _window->setColor(Palette::blockOffset(13)+10);
110 _window->setBackground(_game->getResourcePack()->getSurface("BACK14.SCR"));
111
112 _btnOk->setColor(Palette::blockOffset(13)+10);
113 _btnOk->setText(tr("STR_OK"));
114 _btnOk->onMouseClick((ActionHandler)&CraftInfoState::btnOkClick);
115 _btnOk->onKeyboardPress((ActionHandler)&CraftInfoState::btnOkClick, Options::keyCancel);
116
117 _btnW1->setColor(Palette::blockOffset(13)+10);
118 _btnW1->setText(L"1");
119 _btnW1->onMouseClick((ActionHandler)&CraftInfoState::btnW1Click);
120
121 _btnW2->setColor(Palette::blockOffset(13)+10);
122 _btnW2->setText(L"2");
123 _btnW2->onMouseClick((ActionHandler)&CraftInfoState::btnW2Click);
124
125 _btnCrew->setColor(Palette::blockOffset(13)+10);
126 _btnCrew->setText(tr("STR_CREW"));
127 _btnCrew->onMouseClick((ActionHandler)&CraftInfoState::btnCrewClick);
128
129 _btnEquip->setColor(Palette::blockOffset(13)+10);
130 _btnEquip->setText(tr("STR_EQUIPMENT_UC"));
131 _btnEquip->onMouseClick((ActionHandler)&CraftInfoState::btnEquipClick);
132
133 _btnArmor->setColor(Palette::blockOffset(13)+10);
134 _btnArmor->setText(tr("STR_ARMOR"));
135 _btnArmor->onMouseClick((ActionHandler)&CraftInfoState::btnArmorClick);
136
137 _edtCraft->setColor(Palette::blockOffset(13)+10);
138 _edtCraft->setBig();
139 _edtCraft->setAlign(ALIGN_CENTER);
140 _edtCraft->onChange((ActionHandler)&CraftInfoState::edtCraftChange);
141
142 _txtDamage->setColor(Palette::blockOffset(13)+10);
143 _txtDamage->setSecondaryColor(Palette::blockOffset(13));
144
145 _txtFuel->setColor(Palette::blockOffset(13)+10);
146 _txtFuel->setSecondaryColor(Palette::blockOffset(13));
147
148 _txtW1Name->setColor(Palette::blockOffset(13)+5);
149 _txtW1Name->setWordWrap(true);
150
151 _txtW1Ammo->setColor(Palette::blockOffset(13)+10);
152 _txtW1Ammo->setSecondaryColor(Palette::blockOffset(13)+5);
153
154 _txtW2Name->setColor(Palette::blockOffset(13)+5);
155 _txtW2Name->setWordWrap(true);
156
157 _txtW2Ammo->setColor(Palette::blockOffset(13)+10);
158 _txtW2Ammo->setSecondaryColor(Palette::blockOffset(13)+5);
159 }
160
161 /**
162 *
163 */
~CraftInfoState()164 CraftInfoState::~CraftInfoState()
165 {
166
167 }
168
169 /**
170 * The craft info can change
171 * after going into other screens.
172 */
init()173 void CraftInfoState::init()
174 {
175 State::init();
176
177 _craft = _base->getCrafts()->at(_craftId);
178
179 _edtCraft->setText(_craft->getName(_game->getLanguage()));
180
181 SurfaceSet *texture = _game->getResourcePack()->getSurfaceSet("BASEBITS.PCK");
182 texture->getFrame(_craft->getRules()->getSprite() + 33)->setX(0);
183 texture->getFrame(_craft->getRules()->getSprite() + 33)->setY(0);
184 texture->getFrame(_craft->getRules()->getSprite() + 33)->blit(_sprite);
185
186 std::wostringstream ss;
187 ss << tr("STR_DAMAGE_UC_").arg(Text::formatPercentage(_craft->getDamagePercentage()));
188 if (_craft->getStatus() == "STR_REPAIRS" && _craft->getDamage() > 0)
189 {
190 int damageHours = (int)ceil((double)_craft->getDamage() / _craft->getRules()->getRepairRate());
191 ss << formatTime(damageHours);
192 }
193 _txtDamage->setText(ss.str());
194
195 std::wostringstream ss2;
196 ss2 << tr("STR_FUEL").arg(Text::formatPercentage(_craft->getFuelPercentage()));
197 if (_craft->getStatus() == "STR_REFUELLING" && _craft->getRules()->getMaxFuel() - _craft->getFuel() > 0)
198 {
199 int fuelHours = (int)ceil((double)(_craft->getRules()->getMaxFuel() - _craft->getFuel()) / _craft->getRules()->getRefuelRate() / 2.0);
200 ss2 << formatTime(fuelHours);
201 }
202 _txtFuel->setText(ss2.str());
203
204 if (_craft->getRules()->getSoldiers() > 0)
205 {
206 _crew->clear();
207 _equip->clear();
208
209 Surface *frame1 = texture->getFrame(38);
210 frame1->setY(0);
211 for (int i = 0, x = 0; i < _craft->getNumSoldiers(); ++i, x += 10)
212 {
213 frame1->setX(x);
214 frame1->blit(_crew);
215 }
216
217 Surface *frame2 = texture->getFrame(40);
218 frame2->setY(0);
219 int x = 0;
220 for (int i = 0; i < _craft->getNumVehicles(); ++i, x += 10)
221 {
222 frame2->setX(x);
223 frame2->blit(_equip);
224 }
225 Surface *frame3 = texture->getFrame(39);
226 for (int i = 0; i < _craft->getNumEquipment(); i += 4, x += 10)
227 {
228 frame3->setX(x);
229 frame3->blit(_equip);
230 }
231 }
232 else
233 {
234 _crew->setVisible(false);
235 _equip->setVisible(false);
236 _btnCrew->setVisible(false);
237 _btnEquip->setVisible(false);
238 _btnArmor->setVisible(false);
239 }
240
241 if (_craft->getRules()->getWeapons() > 0)
242 {
243 CraftWeapon *w1 = _craft->getWeapons()->at(0);
244
245 if (w1 != 0)
246 {
247 Surface *frame = texture->getFrame(w1->getRules()->getSprite() + 48);
248 frame->setX(0);
249 frame->setY(0);
250 frame->blit(_weapon1);
251
252 _txtW1Name->setText(tr(w1->getRules()->getType()));
253 std::wostringstream ss;
254 ss << tr("STR_AMMO_").arg(w1->getAmmo()) << L"\n\x01";
255 ss << tr("STR_MAX").arg(w1->getRules()->getAmmoMax());
256 if (_craft->getStatus() == "STR_REARMING" && w1->getAmmo() < w1->getRules()->getAmmoMax())
257 {
258 int rearmHours = (int)ceil((double)(w1->getRules()->getAmmoMax() - w1->getAmmo()) / w1->getRules()->getRearmRate());
259 ss << formatTime(rearmHours);
260 }
261 _txtW1Ammo->setText(ss.str());
262 }
263 else
264 {
265 _weapon1->clear();
266 _txtW1Name->setText(L"");
267 _txtW1Ammo->setText(L"");
268 }
269 }
270 else
271 {
272 _weapon1->setVisible(false);
273 _btnW1->setVisible(false);
274 _txtW1Name->setVisible(false);
275 _txtW1Ammo->setVisible(false);
276 }
277
278 if (_craft->getRules()->getWeapons() > 1)
279 {
280 CraftWeapon *w2 = _craft->getWeapons()->at(1);
281
282 if (w2 != 0)
283 {
284 Surface *frame = texture->getFrame(w2->getRules()->getSprite() + 48);
285 frame->setX(0);
286 frame->setY(0);
287 frame->blit(_weapon2);
288
289 _txtW2Name->setText(tr(w2->getRules()->getType()));
290 std::wostringstream ss;
291 ss << tr("STR_AMMO_").arg(w2->getAmmo()) << L"\n\x01";
292 ss << tr("STR_MAX").arg(w2->getRules()->getAmmoMax());
293 if (_craft->getStatus() == "STR_REARMING" && w2->getAmmo() < w2->getRules()->getAmmoMax())
294 {
295 int rearmHours = (int)ceil((double)(w2->getRules()->getAmmoMax() - w2->getAmmo()) / w2->getRules()->getRearmRate());
296 ss << formatTime(rearmHours);
297 }
298 _txtW2Ammo->setText(ss.str());
299 }
300 else
301 {
302 _weapon2->clear();
303 _txtW2Name->setText(L"");
304 _txtW2Ammo->setText(L"");
305 }
306 }
307 else
308 {
309 _weapon2->setVisible(false);
310 _btnW2->setVisible(false);
311 _txtW2Name->setVisible(false);
312 _txtW2Ammo->setVisible(false);
313 }
314 _defaultName = tr("STR_CRAFTNAME").arg(tr(_craft->getRules()->getType())).arg(_craft->getId());
315 }
316
317 /**
318 * Turns an amount of time into a
319 * day/hour string.
320 * @param total
321 */
formatTime(int total)322 std::wstring CraftInfoState::formatTime(int total)
323 {
324 std::wostringstream ss;
325 int days = total / 24;
326 int hours = total % 24;
327 ss << L"\n(";
328 if (days > 0)
329 {
330 ss << tr("STR_DAY", days) << L"/";
331 }
332 if (hours > 0)
333 {
334 ss << tr("STR_HOUR", hours);
335 }
336 ss << L")";
337 return ss.str();
338 }
339
340 /**
341 * Returns to the previous screen.
342 * @param action Pointer to an action.
343 */
btnOkClick(Action *)344 void CraftInfoState::btnOkClick(Action *)
345 {
346 _game->popState();
347 }
348
349 /**
350 * Goes to the Select Armament window for
351 * the first weapon.
352 * @param action Pointer to an action.
353 */
btnW1Click(Action *)354 void CraftInfoState::btnW1Click(Action *)
355 {
356 _game->pushState(new CraftWeaponsState(_game, _base, _craftId, 0));
357 }
358
359 /**
360 * Goes to the Select Armament window for
361 * the second weapon.
362 * @param action Pointer to an action.
363 */
btnW2Click(Action *)364 void CraftInfoState::btnW2Click(Action *)
365 {
366 _game->pushState(new CraftWeaponsState(_game, _base, _craftId, 1));
367 }
368
369 /**
370 * Goes to the Select Squad screen.
371 * @param action Pointer to an action.
372 */
btnCrewClick(Action *)373 void CraftInfoState::btnCrewClick(Action *)
374 {
375 _game->pushState(new CraftSoldiersState(_game, _base, _craftId));
376 }
377
378 /**
379 * Goes to the Select Equipment screen.
380 * @param action Pointer to an action.
381 */
btnEquipClick(Action *)382 void CraftInfoState::btnEquipClick(Action *)
383 {
384 _game->pushState(new CraftEquipmentState(_game, _base, _craftId));
385 }
386
387 /**
388 * Goes to the Select Armor screen.
389 * @param action Pointer to an action.
390 */
btnArmorClick(Action *)391 void CraftInfoState::btnArmorClick(Action *)
392 {
393 _game->pushState(new CraftArmorState(_game, _base, _craftId));
394 }
395
396 /**
397 * Changes the Craft name.
398 * @param action Pointer to an action.
399 */
edtCraftChange(Action * action)400 void CraftInfoState::edtCraftChange(Action *action)
401 {
402 _craft->setName(_edtCraft->getText());
403 if (_craft->getName(_game->getLanguage()) == _defaultName)
404 {
405 _craft->setName(L"");
406 }
407 if (action->getDetails()->key.keysym.sym == SDLK_RETURN ||
408 action->getDetails()->key.keysym.sym == SDLK_KP_ENTER)
409 {
410 _edtCraft->setText(_craft->getName(_game->getLanguage()));
411 }
412 }
413
414 }
415