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 "CraftSoldiersState.h"
20 #include <string>
21 #include <sstream>
22 #include <climits>
23 #include "../Engine/Action.h"
24 #include "../Engine/Game.h"
25 #include "../Resource/ResourcePack.h"
26 #include "../Engine/Language.h"
27 #include "../Engine/Palette.h"
28 #include "../Engine/Options.h"
29 #include "../Interface/TextButton.h"
30 #include "../Interface/Window.h"
31 #include "../Interface/Text.h"
32 #include "../Interface/TextList.h"
33 #include "../Savegame/Base.h"
34 #include "../Savegame/Soldier.h"
35 #include "../Savegame/Craft.h"
36 #include "../Ruleset/RuleCraft.h"
37 #include "../Engine/LocalizedText.h"
38 #include "SoldierInfoState.h"
39
40 namespace OpenXcom
41 {
42
43 /**
44 * Initializes all the elements in the Craft Soldiers screen.
45 * @param game Pointer to the core game.
46 * @param base Pointer to the base to get info from.
47 * @param craft ID of the selected craft.
48 */
CraftSoldiersState(Game * game,Base * base,size_t craft)49 CraftSoldiersState::CraftSoldiersState(Game *game, Base *base, size_t craft) : State(game), _base(base), _craft(craft)
50 {
51 // Create objects
52 _window = new Window(this, 320, 200, 0, 0);
53 _btnOk = new TextButton(288, 16, 16, 176);
54 _txtTitle = new Text(300, 17, 16, 7);
55 _txtName = new Text(114, 9, 16, 32);
56 _txtRank = new Text(102, 9, 122, 32);
57 _txtCraft = new Text(84, 9, 224, 32);
58 _txtAvailable = new Text(110, 9, 16, 24);
59 _txtUsed = new Text(110, 9, 122, 24);
60 _lstSoldiers = new TextList(288, 128, 8, 40);
61
62 // Set palette
63 setPalette("PAL_BASESCAPE", 2);
64
65 add(_window);
66 add(_btnOk);
67 add(_txtTitle);
68 add(_txtName);
69 add(_txtRank);
70 add(_txtCraft);
71 add(_txtAvailable);
72 add(_txtUsed);
73 add(_lstSoldiers);
74
75 centerAllSurfaces();
76
77 // Set up objects
78 _window->setColor(Palette::blockOffset(15)+6);
79 _window->setBackground(_game->getResourcePack()->getSurface("BACK02.SCR"));
80
81 _btnOk->setColor(Palette::blockOffset(13)+10);
82 _btnOk->setText(tr("STR_OK"));
83 _btnOk->onMouseClick((ActionHandler)&CraftSoldiersState::btnOkClick);
84 _btnOk->onKeyboardPress((ActionHandler)&CraftSoldiersState::btnOkClick, Options::keyCancel);
85
86 _txtTitle->setColor(Palette::blockOffset(15)+6);
87 _txtTitle->setBig();
88 Craft *c = _base->getCrafts()->at(_craft);
89 _txtTitle->setText(tr("STR_SELECT_SQUAD_FOR_CRAFT").arg(c->getName(_game->getLanguage())));
90
91 _txtName->setColor(Palette::blockOffset(15)+6);
92 _txtName->setText(tr("STR_NAME_UC"));
93
94 _txtRank->setColor(Palette::blockOffset(15)+6);
95 _txtRank->setText(tr("STR_RANK"));
96
97 _txtCraft->setColor(Palette::blockOffset(15)+6);
98 _txtCraft->setText(tr("STR_CRAFT"));
99
100 _txtAvailable->setColor(Palette::blockOffset(15)+6);
101 _txtAvailable->setSecondaryColor(Palette::blockOffset(13));
102
103 _txtUsed->setColor(Palette::blockOffset(15)+6);
104 _txtUsed->setSecondaryColor(Palette::blockOffset(13));
105
106 _lstSoldiers->setColor(Palette::blockOffset(13)+10);
107 _lstSoldiers->setArrowColor(Palette::blockOffset(15)+6);
108 _lstSoldiers->setArrowColumn(192, ARROW_VERTICAL);
109 _lstSoldiers->setColumns(3, 106, 102, 72);
110 _lstSoldiers->setSelectable(true);
111 _lstSoldiers->setBackground(_window);
112 _lstSoldiers->setMargin(8);
113 _lstSoldiers->onLeftArrowClick((ActionHandler)&CraftSoldiersState::lstItemsLeftArrowClick);
114 _lstSoldiers->onRightArrowClick((ActionHandler)&CraftSoldiersState::lstItemsRightArrowClick);
115 _lstSoldiers->onMouseClick((ActionHandler)&CraftSoldiersState::lstSoldiersClick, 0);
116 _lstSoldiers->onMousePress((ActionHandler)&CraftSoldiersState::lstSoldiersMousePress);
117 }
118
119 /**
120 *
121 */
~CraftSoldiersState()122 CraftSoldiersState::~CraftSoldiersState()
123 {
124 }
125
126 /**
127 * Returns to the previous screen.
128 * @param action Pointer to an action.
129 */
btnOkClick(Action *)130 void CraftSoldiersState::btnOkClick(Action *)
131 {
132 _game->popState();
133 }
134
135 /**
136 * Shows the soldiers in a list.
137 */
init()138 void CraftSoldiersState::init()
139 {
140 State::init();
141 Craft *c = _base->getCrafts()->at(_craft);
142 _lstSoldiers->clearList();
143
144 int row = 0;
145 for (std::vector<Soldier*>::iterator i = _base->getSoldiers()->begin(); i != _base->getSoldiers()->end(); ++i)
146 {
147 _lstSoldiers->addRow(3, (*i)->getName(true, 19).c_str(), tr((*i)->getRankString()).c_str(), (*i)->getCraftString(_game->getLanguage()).c_str());
148
149 Uint8 color;
150 if ((*i)->getCraft() == c)
151 {
152 color = Palette::blockOffset(13);
153 }
154 else if ((*i)->getCraft() != 0)
155 {
156 color = Palette::blockOffset(15)+6;
157 }
158 else
159 {
160 color = Palette::blockOffset(13)+10;
161 }
162 _lstSoldiers->setRowColor(row, color);
163 row++;
164 }
165 _lstSoldiers->draw();
166
167 _txtAvailable->setText(tr("STR_SPACE_AVAILABLE").arg(c->getSpaceAvailable()));
168 _txtUsed->setText(tr("STR_SPACE_USED").arg(c->getSpaceUsed()));
169
170 }
171
172 /**
173 * Reorders a soldier up.
174 * @param action Pointer to an action.
175 */
lstItemsLeftArrowClick(Action * action)176 void CraftSoldiersState::lstItemsLeftArrowClick(Action *action)
177 {
178 int row = _lstSoldiers->getSelectedRow();
179 if (row > 0)
180 {
181 if (action->getDetails()->button.button == SDL_BUTTON_LEFT)
182 {
183 moveSoldierUp(action, row);
184 }
185 else if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)
186 {
187 moveSoldierUp(action, row, true);
188 }
189 }
190 }
191
192 /**
193 * Moves a soldier up on the list.
194 * @param action Pointer to an action.
195 * @param row Selected soldier row.
196 * @param max Move the soldier to the top?
197 */
moveSoldierUp(Action * action,int row,bool max)198 void CraftSoldiersState::moveSoldierUp(Action *action, int row, bool max)
199 {
200 Soldier *s = _base->getSoldiers()->at(row);
201 if (max)
202 {
203 _base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);
204 _base->getSoldiers()->insert(_base->getSoldiers()->begin(), s);
205 }
206 else
207 {
208 _base->getSoldiers()->at(row) = _base->getSoldiers()->at(row - 1);
209 _base->getSoldiers()->at(row - 1) = s;
210 if (row != _lstSoldiers->getScroll())
211 {
212 SDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() - static_cast<Uint16>(8 * action->getYScale()));
213 }
214 else
215 {
216 _lstSoldiers->scrollUp(false);
217 }
218 }
219 init();
220 }
221
222 /**
223 * Reorders a soldier down.
224 * @param action Pointer to an action.
225 */
lstItemsRightArrowClick(Action * action)226 void CraftSoldiersState::lstItemsRightArrowClick(Action *action)
227 {
228 int row = _lstSoldiers->getSelectedRow();
229 size_t numSoldiers = _base->getSoldiers()->size();
230 if (0 < numSoldiers && INT_MAX >= numSoldiers && row < (int)numSoldiers - 1)
231 {
232 if (action->getDetails()->button.button == SDL_BUTTON_LEFT)
233 {
234 moveSoldierDown(action, row);
235 }
236 else if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)
237 {
238 moveSoldierDown(action, row, true);
239 }
240 }
241 }
242
243 /**
244 * Moves a soldier down on the list.
245 * @param action Pointer to an action.
246 * @param row Selected soldier row.
247 * @param max Move the soldier to the bottom?
248 */
moveSoldierDown(Action * action,int row,bool max)249 void CraftSoldiersState::moveSoldierDown(Action *action, int row, bool max)
250 {
251 Soldier *s = _base->getSoldiers()->at(row);
252 if (max)
253 {
254 _base->getSoldiers()->erase(_base->getSoldiers()->begin() + row);
255 _base->getSoldiers()->insert(_base->getSoldiers()->end(), s);
256 }
257 else
258 {
259 _base->getSoldiers()->at(row) = _base->getSoldiers()->at(row + 1);
260 _base->getSoldiers()->at(row + 1) = s;
261 if (row != _lstSoldiers->getVisibleRows() - 1 + _lstSoldiers->getScroll())
262 {
263 SDL_WarpMouse(action->getLeftBlackBand() + action->getXMouse(), action->getTopBlackBand() + action->getYMouse() + static_cast<Uint16>(8 * action->getYScale()));
264 }
265 else
266 {
267 _lstSoldiers->scrollDown(false);
268 }
269 }
270 init();
271 }
272
273 /**
274 * Shows the selected soldier's info.
275 * @param action Pointer to an action.
276 */
lstSoldiersClick(Action * action)277 void CraftSoldiersState::lstSoldiersClick(Action *action)
278 {
279 double mx = action->getAbsoluteXMouse();
280 if (mx >= _lstSoldiers->getArrowsLeftEdge() && mx < _lstSoldiers->getArrowsRightEdge())
281 {
282 return;
283 }
284 int row = _lstSoldiers->getSelectedRow();
285 if (action->getDetails()->button.button == SDL_BUTTON_LEFT)
286 {
287 Craft *c = _base->getCrafts()->at(_craft);
288 Soldier *s = _base->getSoldiers()->at(_lstSoldiers->getSelectedRow());
289 Uint8 color = Palette::blockOffset(13)+10;
290 if (s->getCraft() == c)
291 {
292 s->setCraft(0);
293 _lstSoldiers->setCellText(row, 2, tr("STR_NONE_UC"));
294 color = Palette::blockOffset(13)+10;
295 }
296 else if (s->getCraft() && s->getCraft()->getStatus() == "STR_OUT")
297 {
298 color = Palette::blockOffset(15)+6;
299 }
300 else if (c->getSpaceAvailable() > 0 && s->getWoundRecovery() == 0)
301 {
302 s->setCraft(c);
303 _lstSoldiers->setCellText(row, 2, c->getName(_game->getLanguage()));
304 color = Palette::blockOffset(13);
305 }
306 _lstSoldiers->setRowColor(row, color);
307
308 _txtAvailable->setText(tr("STR_SPACE_AVAILABLE").arg(c->getSpaceAvailable()));
309 _txtUsed->setText(tr("STR_SPACE_USED").arg(c->getSpaceUsed()));
310 }
311 else if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)
312 {
313 _game->pushState(new SoldierInfoState(_game, _base, row));
314 }
315 }
316
317 /**
318 * Handles the mouse-wheels on the arrow-buttons.
319 * @param action Pointer to an action.
320 */
lstSoldiersMousePress(Action * action)321 void CraftSoldiersState::lstSoldiersMousePress(Action *action)
322 {
323 if (Options::changeValueByMouseWheel == 0)
324 return;
325 int row = _lstSoldiers->getSelectedRow();
326 size_t numSoldiers = _base->getSoldiers()->size();
327 if (action->getDetails()->button.button == SDL_BUTTON_WHEELUP &&
328 row > 0)
329 {
330 if (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&
331 action->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())
332 {
333 moveSoldierUp(action, row);
334 }
335 }
336 else if (action->getDetails()->button.button == SDL_BUTTON_WHEELDOWN &&
337 0 < numSoldiers && INT_MAX >= numSoldiers && row < (int)numSoldiers - 1)
338 {
339 if (action->getAbsoluteXMouse() >= _lstSoldiers->getArrowsLeftEdge() &&
340 action->getAbsoluteXMouse() <= _lstSoldiers->getArrowsRightEdge())
341 {
342 moveSoldierDown(action, row);
343 }
344 }
345 }
346
347 }