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 "NewBattleState.h"
20 #include <cmath>
21 #include <fstream>
22 #include <algorithm>
23 #include <yaml-cpp/yaml.h>
24 #include "../Engine/Game.h"
25 #include "../Resource/ResourcePack.h"
26 #include "../Ruleset/RuleItem.h"
27 #include "../Ruleset/Ruleset.h"
28 #include "../Engine/Language.h"
29 #include "../Engine/Palette.h"
30 #include "../Interface/TextButton.h"
31 #include "../Interface/Window.h"
32 #include "../Interface/Text.h"
33 #include "../Interface/ComboBox.h"
34 #include "../Interface/Slider.h"
35 #include "../Interface/Frame.h"
36 #include "../Savegame/SavedBattleGame.h"
37 #include "../Savegame/SavedGame.h"
38 #include "../Savegame/Base.h"
39 #include "../Savegame/Craft.h"
40 #include "../Savegame/ItemContainer.h"
41 #include "../Battlescape/BattlescapeGenerator.h"
42 #include "../Battlescape/BattlescapeState.h"
43 #include "../Battlescape/BriefingState.h"
44 #include "../Savegame/Ufo.h"
45 #include "../Savegame/TerrorSite.h"
46 #include "../Savegame/AlienBase.h"
47 #include "../Ruleset/RuleCraft.h"
48 #include "../Ruleset/RuleTerrain.h"
49 #include "../Ruleset/AlienDeployment.h"
50 #include "../Engine/Music.h"
51 #include "../Engine/RNG.h"
52 #include "../Engine/Action.h"
53 #include "../Engine/Options.h"
54 #include "../Engine/Logger.h"
55 #include "../Basescape/CraftInfoState.h"
56 
57 namespace OpenXcom
58 {
59 
60 /**
61  * Initializes all the elements in the New Battle window.
62  * @param game Pointer to the core game.
63  */
NewBattleState(Game * game)64 NewBattleState::NewBattleState(Game *game) : State(game), _craft(0)
65 {
66 	// Create objects
67 	_window = new Window(this, 320, 200, 0, 0, POPUP_BOTH);
68 	_txtTitle = new Text(320, 17, 0, 9);
69 
70 	_txtMapOptions = new Text(148, 9, 8, 68);
71 	_frameLeft = new Frame(148, 96, 8, 78);
72 	_txtAlienOptions = new Text(148, 9, 164, 68);
73 	_frameRight = new Frame(148, 96, 164, 78);
74 
75 	_txtMission = new Text(100, 9, 8, 30);
76 	_cbxMission = new ComboBox(this, 214, 16, 98, 26);
77 
78 	_txtCraft = new Text(100, 9, 8, 50);
79 	_cbxCraft = new ComboBox(this, 106, 16, 98, 46);
80 	_btnEquip = new TextButton(106, 16, 206, 46);
81 
82 	_txtDarkness = new Text(120, 9, 22, 83);
83 	_slrDarkness = new Slider(120, 16, 22, 93);
84 
85 	_txtTerrain = new Text(120, 9, 22, 113);
86 	_cbxTerrain = new ComboBox(this, 120, 16, 22, 123);
87 
88 	_txtDifficulty = new Text(120, 9, 178, 83);
89 	_cbxDifficulty = new ComboBox(this, 120, 16, 178, 93);
90 
91 	_txtAlienRace = new Text(120, 9, 178, 113);
92 	_cbxAlienRace = new ComboBox(this, 120, 16, 178, 123);
93 
94 	_txtAlienTech = new Text(120, 9, 178, 143);
95 	_slrAlienTech = new Slider(120, 16, 178, 153);
96 
97 	_btnOk = new TextButton(100, 16, 8, 176);
98 	_btnCancel = new TextButton(100, 16, 110, 176);
99 	_btnRandom = new TextButton(100, 16, 212, 176);
100 
101 	// Set palette
102 	setPalette("PAL_GEOSCAPE", 0);
103 
104 	add(_window);
105 	add(_txtTitle);
106 	add(_txtMapOptions);
107 	add(_frameLeft);
108 	add(_txtAlienOptions);
109 	add(_frameRight);
110 
111 	add(_txtMission);
112 	add(_txtCraft);
113 	add(_btnEquip);
114 
115 	add(_txtDarkness);
116 	add(_slrDarkness);
117 	add(_txtTerrain);
118 	add(_txtDifficulty);
119 	add(_txtAlienRace);
120 	add(_txtAlienTech);
121 	add(_slrAlienTech);
122 
123 	add(_btnOk);
124 	add(_btnCancel);
125 	add(_btnRandom);
126 
127 	add(_cbxTerrain);
128 	add(_cbxAlienRace);
129 	add(_cbxDifficulty);
130 	add(_cbxCraft);
131 	add(_cbxMission);
132 
133 	centerAllSurfaces();
134 
135 	// Set up objects
136 	_window->setColor(Palette::blockOffset(8)+5);
137 	_window->setBackground(_game->getResourcePack()->getSurface("BACK01.SCR"));
138 
139 	_txtTitle->setColor(Palette::blockOffset(15)-1);
140 	_txtTitle->setAlign(ALIGN_CENTER);
141 	_txtTitle->setBig();
142 	_txtTitle->setText(tr("STR_MISSION_GENERATOR"));
143 
144 	_txtMapOptions->setColor(Palette::blockOffset(15)-1);
145 	_txtMapOptions->setText(tr("STR_MAP_OPTIONS"));
146 
147 	_frameLeft->setThickness(3);
148 	_frameLeft->setColor(Palette::blockOffset(15)-1);
149 
150 	_txtAlienOptions->setColor(Palette::blockOffset(15)-1);
151 	_txtAlienOptions->setText(tr("STR_ALIEN_OPTIONS"));
152 
153 	_frameRight->setThickness(3);
154 	_frameRight->setColor(Palette::blockOffset(15)-1);
155 
156 	_txtMission->setColor(Palette::blockOffset(8)+10);
157 	_txtMission->setText(tr("STR_MISSION"));
158 
159 	_txtCraft->setColor(Palette::blockOffset(8)+10);
160 	_txtCraft->setText(tr("STR_CRAFT"));
161 
162 	_txtDarkness->setColor(Palette::blockOffset(8)+10);
163 	_txtDarkness->setText(tr("STR_MAP_DARKNESS"));
164 
165 	_txtTerrain->setColor(Palette::blockOffset(8)+10);
166 	_txtTerrain->setText(tr("STR_MAP_TERRAIN"));
167 
168 	_txtDifficulty->setColor(Palette::blockOffset(8)+10);
169 	_txtDifficulty->setText(tr("STR_ALIEN_DIFFICULTY"));
170 
171 	_txtAlienRace->setColor(Palette::blockOffset(8)+10);
172 	_txtAlienRace->setText(tr("STR_ALIEN_RACE"));
173 
174 	_txtAlienTech->setColor(Palette::blockOffset(8)+10);
175 	_txtAlienTech->setText(tr("STR_ALIEN_TECH_LEVEL"));
176 
177 	_missionTypes = _game->getRuleset()->getDeploymentsList();
178 
179 	const std::vector<std::string> &terrainTypes = _game->getRuleset()->getTerrainList();
180 	std::vector<std::string> terrainStrings;
181 	for (std::vector<std::string>::const_iterator i = terrainTypes.begin(); i != terrainTypes.end(); ++i)
182 	{
183 		if (!_game->getRuleset()->getTerrain(*i)->getTextures()->empty())
184 		{
185 			_terrainTypes.push_back(*i);
186 			terrainStrings.push_back("STR_" + *i);
187 			_textures.push_back(_game->getRuleset()->getTerrain(*i)->getTextures()->at(0));
188 		}
189 	}
190 
191 	_alienRaces = _game->getRuleset()->getAlienRacesList();
192 
193 	std::vector<std::string> difficulty;
194 	difficulty.push_back("STR_1_BEGINNER");
195 	difficulty.push_back("STR_2_EXPERIENCED");
196 	difficulty.push_back("STR_3_VETERAN");
197 	difficulty.push_back("STR_4_GENIUS");
198 	difficulty.push_back("STR_5_SUPERHUMAN");
199 
200 	const std::vector<std::string> &crafts = _game->getRuleset()->getCraftsList();
201 	for (std::vector<std::string>::const_iterator i = crafts.begin(); i != crafts.end(); ++i)
202 	{
203 		RuleCraft *rule = _game->getRuleset()->getCraft(*i);
204 		if (rule->getSoldiers() > 0)
205 		{
206 			_crafts.push_back(*i);
207 		}
208 	}
209 
210 	_cbxMission->setColor(Palette::blockOffset(15)-1);
211 	_cbxMission->setOptions(_missionTypes);
212 	_cbxMission->onChange((ActionHandler)&NewBattleState::cbxMissionChange);
213 
214 	_cbxCraft->setColor(Palette::blockOffset(15)-1);
215 	_cbxCraft->setOptions(_crafts);
216 	_cbxCraft->onChange((ActionHandler)&NewBattleState::cbxCraftChange);
217 
218 	_slrDarkness->setColor(Palette::blockOffset(15)-1);
219 	_slrDarkness->setRange(0, 15);
220 
221 	_cbxTerrain->setColor(Palette::blockOffset(15)-1);
222 	_cbxTerrain->setOptions(terrainStrings);
223 
224 	_cbxDifficulty->setColor(Palette::blockOffset(15)-1);
225 	_cbxDifficulty->setOptions(difficulty);
226 
227 	_cbxAlienRace->setColor(Palette::blockOffset(15)-1);
228 	_cbxAlienRace->setOptions(_alienRaces);
229 
230 	_slrAlienTech->setColor(Palette::blockOffset(15)-1);
231 	_slrAlienTech->setRange(0, _game->getRuleset()->getAlienItemLevels().size()-1);
232 
233 	_btnEquip->setColor(Palette::blockOffset(15)-1);
234 	_btnEquip->setText(tr("STR_EQUIP_CRAFT"));
235 	_btnEquip->onMouseClick((ActionHandler)&NewBattleState::btnEquipClick);
236 
237 	_btnRandom->setColor(Palette::blockOffset(8)+5);
238 	_btnRandom->setText(tr("STR_RANDOMIZE"));
239 	_btnRandom->onMouseClick((ActionHandler)&NewBattleState::btnRandomClick);
240 
241 	_btnOk->setColor(Palette::blockOffset(8)+5);
242 	_btnOk->setText(tr("STR_OK"));
243 	_btnOk->onMouseClick((ActionHandler)&NewBattleState::btnOkClick);
244 	_btnOk->onKeyboardPress((ActionHandler)&NewBattleState::btnOkClick, Options::keyOk);
245 
246 	_btnCancel->setColor(Palette::blockOffset(8)+5);
247 	_btnCancel->setText(tr("STR_CANCEL"));
248 	_btnCancel->onMouseClick((ActionHandler)&NewBattleState::btnCancelClick);
249 	_btnCancel->onKeyboardPress((ActionHandler)&NewBattleState::btnCancelClick, Options::keyCancel);
250 
251 	load();
252 }
253 
254 /**
255  *
256  */
~NewBattleState()257 NewBattleState::~NewBattleState()
258 {
259 
260 }
261 
262 /**
263  * Resets the menu music and savegame
264  * when coming back from the battlescape.
265  */
init()266 void NewBattleState::init()
267 {
268 	State::init();
269 
270 	if (_craft == 0)
271 	{
272 		load();
273 	}
274 }
275 
276 /**
277  * Loads new battle data from a YAML file.
278  * @param filename YAML filename.
279  */
load(const std::string & filename)280 void NewBattleState::load(const std::string &filename)
281 {
282 	std::string s = Options::getConfigFolder() + filename + ".cfg";
283 	try
284 	{
285 		YAML::Node doc = YAML::LoadFile(s);
286 		_cbxMission->setSelected(std::min(doc["mission"].as<size_t>(0), _missionTypes.size()-1));
287 		_cbxCraft->setSelected(std::min(doc["craft"].as<size_t>(0), _crafts.size()-1));
288 		_slrDarkness->setValue(doc["darkness"].as<size_t>(0));
289 		_cbxTerrain->setSelected(std::min(doc["terrain"].as<size_t>(0), _terrainTypes.size()-1));
290 		_cbxAlienRace->setSelected(std::min(doc["alienRace"].as<size_t>(0), _alienRaces.size()-1));
291 		_cbxDifficulty->setSelected(doc["difficulty"].as<size_t>(0));
292 		_slrAlienTech->setValue(doc["alienTech"].as<size_t>(0));
293 		cbxMissionChange(NULL);
294 
295 		if (doc["base"])
296 		{
297 			const Ruleset *rule = _game->getRuleset();
298 			SavedGame *save = new SavedGame();
299 
300 			Base *base = new Base(rule);
301 			base->load(doc["base"], save, false);
302 			save->getBases()->push_back(base);
303 
304 			// Add research
305 			const std::vector<std::string> &research = rule->getResearchList();
306 			for (std::vector<std::string>::const_iterator i = research.begin(); i != research.end(); ++i)
307 			{
308 				save->addFinishedResearch(rule->getResearch(*i));
309 			}
310 
311 			// Generate items
312 			base->getItems()->getContents()->clear();
313 			const std::vector<std::string> &items = rule->getItemsList();
314 			for (std::vector<std::string>::const_iterator i = items.begin(); i != items.end(); ++i)
315 			{
316 				RuleItem *rule = _game->getRuleset()->getItem(*i);
317 				if (rule->getBattleType() != BT_CORPSE && rule->isRecoverable())
318 				{
319 					base->getItems()->addItem(*i, 1);
320 				}
321 			}
322 
323 			// Clear invalid contents
324 			_craft = base->getCrafts()->front();
325 			for (std::map<std::string, int>::iterator i = _craft->getItems()->getContents()->begin(); i != _craft->getItems()->getContents()->end(); ++i)
326 			{
327 				RuleItem *rule = _game->getRuleset()->getItem(i->first);
328 				if (!rule)
329 				{
330 					i->second = 0;
331 				}
332 			}
333 
334 			_game->setSavedGame(save);
335 		}
336 		else
337 		{
338 			initSave();
339 		}
340 	}
341 	catch (YAML::Exception e)
342 	{
343 		Log(LOG_WARNING) << e.what();
344 		initSave();
345 	}
346 }
347 
348 /**
349  * Saves new battle data to a YAML file.
350  * @param filename YAML filename.
351  */
save(const std::string & filename)352 void NewBattleState::save(const std::string &filename)
353 {
354 	std::string s = Options::getConfigFolder() + filename + ".cfg";
355 	std::ofstream sav(s.c_str());
356 	if (!sav)
357 	{
358 		Log(LOG_WARNING) << "Failed to save " << filename << ".cfg";
359 		return;
360 	}
361 	YAML::Emitter out;
362 
363 	YAML::Node node;
364 	node["mission"] = _cbxMission->getSelected();
365 	node["craft"] = _cbxCraft->getSelected();
366 	node["darkness"] = _slrDarkness->getValue();
367 	node["terrain"] = _cbxTerrain->getSelected();
368 	node["alienRace"] = _cbxAlienRace->getSelected();
369 	node["difficulty"] = _cbxDifficulty->getSelected();
370 	node["alienTech"] = _slrAlienTech->getValue();
371 	node["base"] = _game->getSavedGame()->getBases()->front()->save();
372 	out << node;
373 
374 	sav << out.c_str();
375 	sav.close();
376 }
377 
378 /**
379  * Initializes a new savegame with
380  * everything available.
381  */
initSave()382 void NewBattleState::initSave()
383 {
384 	const Ruleset *rule = _game->getRuleset();
385 	SavedGame *save = new SavedGame();
386 	Base *base = new Base(rule);
387 	const YAML::Node &starter = _game->getRuleset()->getStartingBase();
388 	base->load(starter, save, true, true);
389 	save->getBases()->push_back(base);
390 
391 	// kill everything we don't want in this base
392 	for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end(); ++i) delete (*i);
393 	base->getSoldiers()->clear();
394 	for (std::vector<Craft*>::iterator i = base->getCrafts()->begin(); i != base->getCrafts()->end(); ++i) delete (*i);
395 	base->getCrafts()->clear();
396 	base->getItems()->getContents()->clear();
397 
398 	_craft = new Craft(rule->getCraft(_crafts[_cbxCraft->getSelected()]), base, 1);
399 	base->getCrafts()->push_back(_craft);
400 
401 	// Generate soldiers
402 	for (int i = 0; i < 30; ++i)
403 	{
404 		Soldier *soldier = rule->genSoldier(save);
405 
406         for (int n = 0; n < 5; ++n)
407         {
408             if (RNG::percent(70))
409                 continue;
410             soldier->promoteRank();
411 
412             UnitStats* stats = soldier->getCurrentStats();
413             stats->tu          += RNG::generate(0, 5);
414             stats->stamina     += RNG::generate(0, 5);
415             stats->health      += RNG::generate(0, 5);
416 			stats->bravery     += RNG::generate(0, 5);
417             stats->reactions   += RNG::generate(0, 5);
418             stats->firing      += RNG::generate(0, 5);
419             stats->throwing    += RNG::generate(0, 5);
420             stats->strength    += RNG::generate(0, 5);
421             stats->psiStrength += RNG::generate(0, 5);
422             stats->melee       += RNG::generate(0, 5);
423             stats->psiSkill    += RNG::generate(0, 20);
424         }
425 		UnitStats* stats = soldier->getCurrentStats();
426 		stats->bravery = (int)ceil(stats->bravery / 10.0) * 10; // keep it a multiple of 10
427 
428 		base->getSoldiers()->push_back(soldier);
429 		if (i < _craft->getRules()->getSoldiers())
430 			soldier->setCraft(_craft);
431 	}
432 
433 	// Generate items
434 	const std::vector<std::string> &items = rule->getItemsList();
435 	for (std::vector<std::string>::const_iterator i = items.begin(); i != items.end(); ++i)
436 	{
437 		RuleItem *rule = _game->getRuleset()->getItem(*i);
438 		if (rule->getBattleType() != BT_CORPSE && rule->isRecoverable())
439 		{
440 			base->getItems()->addItem(*i, 1);
441 			if (rule->getBattleType() != BT_NONE && !rule->isFixed() && rule->getBigSprite() > -1)
442 			{
443 				_craft->getItems()->addItem(*i, 1);
444 			}
445 		}
446 	}
447 
448 	// Add research
449 	const std::vector<std::string> &research = rule->getResearchList();
450 	for (std::vector<std::string>::const_iterator i = research.begin(); i != research.end(); ++i)
451 	{
452 		save->addFinishedResearch(rule->getResearch(*i));
453 	}
454 
455 	_game->setSavedGame(save);
456 }
457 
458 /**
459  * Starts the battle.
460  * @param action Pointer to an action.
461  */
btnOkClick(Action *)462 void NewBattleState::btnOkClick(Action *)
463 {
464 	save();
465 	if (_missionTypes[_cbxMission->getSelected()] != "STR_BASE_DEFENSE" && _craft->getNumSoldiers() == 0 && _craft->getNumVehicles() == 0)
466 	{
467 		return;
468 	}
469 
470 	SavedBattleGame *bgame = new SavedBattleGame();
471 	_game->getSavedGame()->setBattleGame(bgame);
472 	bgame->setMissionType(_missionTypes[_cbxMission->getSelected()]);
473 	BattlescapeGenerator bgen = BattlescapeGenerator(_game);
474 
475 	bgen.setWorldTexture(_textures[_cbxTerrain->getSelected()]);
476 
477 	if (_missionTypes[_cbxMission->getSelected()] == "STR_TERROR_MISSION")
478 	{
479 		TerrorSite *t = new TerrorSite();
480 		t->setId(1);
481 		_craft->setDestination(t);
482 		bgen.setTerrorSite(t);
483 		bgen.setCraft(_craft);
484 		_game->getSavedGame()->getTerrorSites()->push_back(t);
485 	}
486 	else if (_missionTypes[_cbxMission->getSelected()] == "STR_BASE_DEFENSE")
487 	{
488 		bgen.setBase(_craft->getBase());
489 	}
490 	else if (_missionTypes[_cbxMission->getSelected()] == "STR_ALIEN_BASE_ASSAULT")
491 	{
492 		AlienBase *b = new AlienBase();
493 		b->setId(1);
494 		_craft->setDestination(b);
495 		bgen.setAlienBase(b);
496 		bgen.setCraft(_craft);
497 		_game->getSavedGame()->getAlienBases()->push_back(b);
498 	}
499 	else if (_missionTypes[_cbxMission->getSelected()] == "STR_MARS_CYDONIA_LANDING" || _missionTypes[_cbxMission->getSelected()] == "STR_MARS_THE_FINAL_ASSAULT")
500 	{
501 		bgen.setCraft(_craft);
502 	}
503 	else if (_craft)
504 	{
505 		Ufo *u = new Ufo(_game->getRuleset()->getUfo(_missionTypes[_cbxMission->getSelected()]));
506 		u->setId(1);
507 		_craft->setDestination(u);
508 		bgen.setUfo(u);
509 		bgen.setCraft(_craft);
510 		if (_terrainTypes[_cbxTerrain->getSelected()] == "FOREST")
511 		{
512 			u->setLatitude(-0.5);
513 		}
514 		// either ground assault or ufo crash
515 		if (RNG::generate(0,1) == 1)
516 			bgame->setMissionType("STR_UFO_GROUND_ASSAULT");
517 		else
518 			bgame->setMissionType("STR_UFO_CRASH_RECOVERY");
519 		_game->getSavedGame()->getUfos()->push_back(u);
520 	}
521 	if (_craft)
522 		_craft->setSpeed(0);
523 	_game->getSavedGame()->setDifficulty((GameDifficulty)_cbxDifficulty->getSelected());
524 
525 	bgen.setWorldShade(_slrDarkness->getValue());
526 	bgen.setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]);
527 	bgen.setAlienItemlevel(_slrAlienTech->getValue());
528 
529 	bgen.run();
530 	//_game->pushState(new BattlescapeState(_game));
531 	Base *base = 0;
532 	if (_missionTypes[_cbxMission->getSelected()] == "STR_BASE_DEFENSE")
533 	{
534 		base = _craft->getBase();
535 		_craft = 0;
536 	}
537 	_game->popState();
538 	_game->popState();
539 	_game->pushState(new BriefingState(_game, _craft, base));
540 	_craft = 0;
541 }
542 
543 /**
544  * Returns to the previous screen.
545  * @param action Pointer to an action.
546  */
btnCancelClick(Action *)547 void NewBattleState::btnCancelClick(Action *)
548 {
549 	save();
550 	_game->setSavedGame(0);
551 	_game->popState();
552 }
553 
554 /**
555  * Randomize the state
556  * @param action Pointer to an action.
557  */
btnRandomClick(Action *)558 void NewBattleState::btnRandomClick(Action *)
559 {
560 	_cbxMission->setSelected(RNG::generate(0, _missionTypes.size()-1));
561 	_cbxCraft->setSelected(RNG::generate(0, _crafts.size()-1));
562 	_slrDarkness->setValue(RNG::generate(0, 15));
563 	_cbxTerrain->setSelected(RNG::generate(0, _terrainTypes.size()-1));
564 	_cbxAlienRace->setSelected(RNG::generate(0, _alienRaces.size()-1));
565 	_cbxDifficulty->setSelected(RNG::generate(0, 4));
566 	_slrAlienTech->setValue(RNG::generate(0, _game->getRuleset()->getAlienItemLevels().size()-1));
567 	cbxMissionChange(0);
568 	cbxCraftChange(0);
569 
570 	initSave();
571 }
572 
573 /**
574  * Shows the Craft Info screen.
575  * @param action Pointer to an action.
576  */
btnEquipClick(Action *)577 void NewBattleState::btnEquipClick(Action *)
578 {
579 	_game->pushState(new CraftInfoState(_game, _game->getSavedGame()->getBases()->front(), 0));
580 }
581 
582 /**
583  * Updates Map Options based on the
584  * current Mission type.
585  * @param action Pointer to an action.
586  */
cbxMissionChange(Action *)587 void NewBattleState::cbxMissionChange(Action *)
588 {
589 	AlienDeployment *ruleDeploy = _game->getRuleset()->getDeployment(_missionTypes[_cbxMission->getSelected()]);
590 	_txtDarkness->setVisible(ruleDeploy->getShade() == -1);
591 	_slrDarkness->setVisible(ruleDeploy->getShade() == -1);
592 	_txtTerrain->setVisible(ruleDeploy->getTerrains().empty());
593 	_cbxTerrain->setVisible(ruleDeploy->getTerrains().empty());
594 }
595 
596 /**
597  * Updates craft accordingly.
598  * @param action Pointer to an action.
599  */
cbxCraftChange(Action *)600 void NewBattleState::cbxCraftChange(Action *)
601 {
602 	_craft->setRules(_game->getRuleset()->getCraft(_crafts[_cbxCraft->getSelected()]));
603 	int current = _craft->getNumSoldiers();
604 	int max = _craft->getRules()->getSoldiers();
605 	if (current > max)
606 	{
607 		for (std::vector<Soldier*>::reverse_iterator i = _craft->getBase()->getSoldiers()->rbegin(); i != _craft->getBase()->getSoldiers()->rend() && current > max; ++i)
608 		{
609 			if ((*i)->getCraft() == _craft)
610 			{
611 				(*i)->setCraft(0);
612 				current--;
613 			}
614 		}
615 	}
616 }
617 
618 }
619