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 }