/** * Returns to the previous screen. * @param action Pointer to an action. */ void NewGameState::btnOkClick(Action *) { GameDifficulty diff = DIFF_BEGINNER; if (_difficulty == _btnBeginner) { diff = DIFF_BEGINNER; } else if (_difficulty == _btnExperienced) { diff = DIFF_EXPERIENCED; } else if (_difficulty == _btnVeteran) { diff = DIFF_VETERAN; } else if (_difficulty == _btnGenius) { diff = DIFF_GENIUS; } else if (_difficulty == _btnSuperhuman) { diff = DIFF_SUPERHUMAN; } SavedGame *save = _game->getMod()->newSave(); save->setDifficulty(diff); save->setIronman(_btnIronman->getPressed()); _game->setSavedGame(save); GeoscapeState *gs = new GeoscapeState; _game->setState(gs); gs->init(); _game->pushState(new BuildNewBaseState(_game->getSavedGame()->getBases()->back(), gs->getGlobe(), true)); }
/** * Loads the selected save. * @param action Pointer to an action. */ void LoadGameState::lstSavesClick(Action *action) { try { _game->setRuleset(new XcomRuleset()); SavedGame *s = new SavedGame(DIFF_BEGINNER); s->load(Language::wstrToUtf8(_lstSaves->getCell(_lstSaves->getSelectedRow(), 0)->getText()), _game->getRuleset()); _game->setSavedGame(s); if (_game->getSavedGame()->getBattleGame() == 0) { _game->setState(new GeoscapeState(_game)); } else { _game->setState(new BattlescapeState(_game)); } } catch (Exception &e) { std::cerr << "ERROR: " << e.what() << std::endl; _game->pushState(new GeoscapeErrorState(_game, "STR_LOAD_UNSUCCESSFUL")); } catch (YAML::Exception &e) { std::cerr << "ERROR: " << e.what() << std::endl; _game->pushState(new GeoscapeErrorState(_game, "STR_LOAD_UNSUCCESSFUL")); } }
/** * Loads the selected save. * @param action Pointer to an action. */ void LoadState::lstSavesPress(Action *action) { if (action->getDetails()->button.button == SDL_BUTTON_LEFT) { updateStatus("STR_LOADING_GAME"); SavedGame *s = new SavedGame(); try { #ifdef _WIN32 std::string filename = Language::wstrToCp(_lstSaves->getCellText(_lstSaves->getSelectedRow(), 0)); #else std::string filename = Language::wstrToUtf8(_lstSaves->getCellText(_lstSaves->getSelectedRow(), 0)); #endif s->load(filename, _game->getRuleset()); _game->setSavedGame(s); _game->setState(new GeoscapeState(_game)); if (_game->getSavedGame()->getBattleGame() != 0) { _game->getSavedGame()->getBattleGame()->loadMapResources(_game->getResourcePack()); BattlescapeState *bs = new BattlescapeState(_game); _game->pushState(bs); _game->getSavedGame()->getBattleGame()->setBattleState(bs); } } catch (Exception &e) { Log(LOG_ERROR) << e.what(); std::wstringstream error; error << _game->getLanguage()->getString("STR_LOAD_UNSUCCESSFUL") << L'\x02' << Language::utf8ToWstr(e.what()); if (_geo) _game->pushState(new ErrorMessageState(_game, error.str(), Palette::blockOffset(8)+10, "BACK01.SCR", 6)); else _game->pushState(new ErrorMessageState(_game, error.str(), Palette::blockOffset(0), "TAC00.SCR", -1)); delete s; _game->setSavedGame(0); } catch (YAML::Exception &e) { Log(LOG_ERROR) << e.what(); std::wstringstream error; error << _game->getLanguage()->getString("STR_LOAD_UNSUCCESSFUL") << L'\x02' << Language::utf8ToWstr(e.what()); if (_geo) _game->pushState(new ErrorMessageState(_game, error.str(), Palette::blockOffset(8)+10, "BACK01.SCR", 6)); else _game->pushState(new ErrorMessageState(_game, error.str(), Palette::blockOffset(0), "TAC00.SCR", -1)); delete s; _game->setSavedGame(0); } } else if (action->getDetails()->button.button == SDL_BUTTON_RIGHT) { if(_geo) _game->pushState(new DeleteGameState(_game, _lstSaves->getCellText(_lstSaves->getSelectedRow(),0), Palette::blockOffset(8)+10, "BACK01.SCR", 6, this)); else _game->pushState(new DeleteGameState(_game, _lstSaves->getCellText(_lstSaves->getSelectedRow(),0), Palette::blockOffset(0), "TAC00.SCR", -1, this)); } }
/** * Quick load game. * @param filename16 name of file without ".sav" */ void LoadState::quickLoad(const std::wstring &filename16) { if (_showMsg) updateStatus("STR_LOADING_GAME"); #ifdef _WIN32 std::string filename = Language::wstrToCp(filename16); #else std::string filename = Language::wstrToUtf8(filename16); #endif SavedGame *s = new SavedGame(); try { s->load(filename, _game->getRuleset()); _game->setSavedGame(s); _game->setState(new GeoscapeState(_game)); if (_game->getSavedGame()->getSavedBattle() != 0) { _game->getSavedGame()->getSavedBattle()->loadMapResources(_game); BattlescapeState *bs = new BattlescapeState(_game); _game->pushState(bs); _game->getSavedGame()->getSavedBattle()->setBattleState(bs); } } catch (Exception &e) { Log(LOG_ERROR) << e.what(); std::wstringstream error; error << tr("STR_LOAD_UNSUCCESSFUL") << L'\x02' << Language::utf8ToWstr(e.what()); if (_geo) _game->pushState(new ErrorMessageState(_game, error.str(), Palette::blockOffset(8)+10, "BACK01.SCR", 6)); else _game->pushState(new ErrorMessageState(_game, error.str(), Palette::blockOffset(0), "TAC00.SCR", -1)); if (_game->getSavedGame() == s) _game->setSavedGame(0); else delete s; } catch (YAML::Exception &e) { Log(LOG_ERROR) << e.what(); std::wstringstream error; error << tr("STR_LOAD_UNSUCCESSFUL") << L'\x02' << Language::utf8ToWstr(e.what()); if (_geo) _game->pushState(new ErrorMessageState(_game, error.str(), Palette::blockOffset(8)+10, "BACK01.SCR", 6)); else _game->pushState(new ErrorMessageState(_game, error.str(), Palette::blockOffset(0), "TAC00.SCR", -1)); if (_game->getSavedGame() == s) _game->setSavedGame(0); else delete s; } }
/** * Loads the specified save. */ void LoadGameState::think() { State::think(); // Make sure it gets drawn properly if (_firstRun < 10) { _firstRun++; } else { _game->popState(); // Load the game SavedGame *s = new SavedGame(); try { s->load(_filename, _game->getMod()); _game->setSavedGame(s); if (_game->getSavedGame()->getEnding() != END_NONE) { Options::baseXResolution = Screen::ORIGINAL_WIDTH; Options::baseYResolution = Screen::ORIGINAL_HEIGHT; _game->getScreen()->resetDisplay(false); _game->setState(new StatisticsState); } else { Options::baseXResolution = Options::baseXGeoscape; Options::baseYResolution = Options::baseYGeoscape; _game->getScreen()->resetDisplay(false); _game->setState(new GeoscapeState); if (_game->getSavedGame()->getSavedBattle() != 0) { _game->getSavedGame()->getSavedBattle()->loadMapResources(_game->getMod()); Options::baseXResolution = Options::baseXBattlescape; Options::baseYResolution = Options::baseYBattlescape; _game->getScreen()->resetDisplay(false); BattlescapeState *bs = new BattlescapeState; _game->pushState(bs); _game->getSavedGame()->getSavedBattle()->setBattleState(bs); } } } catch (Exception &e) { error(e.what(), s); } catch (YAML::Exception &e) { error(e.what(), s); } CrossPlatform::flashWindow(); } }
/** * Loads the UFO from a YAML file. * @param node YAML node. * @param ruleset The game rules. Use to access the trajectory rules. * @param game The game data. Used to find the UFO's mission. */ void Ufo::load(const YAML::Node &node, const Ruleset &ruleset, SavedGame &game) { MovingTarget::load(node); node["id"] >> _id; node["damage"] >> _damage; node["altitude"] >> _altitude; node["direction"] >> _direction; node["detected"] >> _detected; node["hyperDetected"] >> _hyperDetected; node["secondsRemaining"] >> _secondsRemaining; node["inBattlescape"] >> _inBattlescape; double lon, lat; node["dest"]["lon"] >> lon; node["dest"]["lat"] >> lat; _dest = new Waypoint(); _dest->setLongitude(lon); _dest->setLatitude(lat); if (_altitude == "STR_GROUND") { _status = LANDED; } else { _status = FLYING; } if (_damage >= _rules->getMaxDamage()) { _status = DESTROYED; } else if (_damage >= _rules->getMaxDamage() / 2) { _status = CRASHED; } int missionID; node["mission"] >> missionID; std::vector<AlienMission *>::const_iterator found = std::find_if(game.getAlienMissions().begin(), game.getAlienMissions().end(), matchMissionID(missionID)); if (found == game.getAlienMissions().end()) { // Corrupt save file. throw Exception("Unknown mission, save file is corrupt."); } _mission = *found; std::string tid; node["trajectory"] >> tid; _trajectory = ruleset.getUfoTrajectory(tid); node["trajectoryPoint"] >> _trajectoryPoint; if (_inBattlescape) setSpeed(0); }
/** * Loads the selected save. * @param action Pointer to an action. */ void LoadGameState::lstSavesClick(Action *action) { //Ruleset *r = new XcomRuleset(); SavedGame *s = new SavedGame(); try { //_game->setRuleset(r); s->load(Language::wstrToUtf8(_lstSaves->getCellText(_lstSaves->getSelectedRow(), 0)), _game->getRuleset()); _game->setSavedGame(s); _game->setState(new GeoscapeState(_game)); if (_game->getSavedGame()->getBattleGame() != 0) { _game->getSavedGame()->getBattleGame()->loadMapResources(_game->getResourcePack()); _game->pushState(new BattlescapeState(_game)); } } catch (Exception &e) { std::cerr << "ERROR: " << e.what() << std::endl; std::wstring error = _game->getLanguage()->getString("STR_LOAD_UNSUCCESSFUL") + L'\x02' + Language::utf8ToWstr(e.what()); if (_geo) _game->pushState(new ErrorMessageState(_game, error, Palette::blockOffset(8)+10, "BACK01.SCR", 6)); else _game->pushState(new ErrorMessageState(_game, error, Palette::blockOffset(0), "TAC00.SCR", -1)); //delete r; delete s; //_game->setRuleset(0); _game->setSavedGame(0); } catch (YAML::Exception &e) { std::cerr << "ERROR: " << e.what() << std::endl; std::wstring error = _game->getLanguage()->getString("STR_LOAD_UNSUCCESSFUL") + L'\x02' + Language::utf8ToWstr(e.what()); if (_geo) _game->pushState(new ErrorMessageState(_game, error, Palette::blockOffset(8)+10, "BACK01.SCR", 6)); else _game->pushState(new ErrorMessageState(_game, error, Palette::blockOffset(0), "TAC00.SCR", -1)); //delete r; delete s; //_game->setRuleset(0); _game->setSavedGame(0); } }
/** * Add alien points to the country and region at the coordinates given. * @param lon Longitudinal coordinates to check. * @param lat Latitudinal coordinates to check. * @param game The saved game information. */ void AlienMission::addScore(const double lon, const double lat, SavedGame &game) { for (std::vector<Region *>::iterator region = game.getRegions()->begin(); region != game.getRegions()->end(); ++region) { if ((*region)->getRules()->insideRegion(lon, lat)) { (*region)->addActivityAlien(_rule.getPoints()); break; } } for (std::vector<Country *>::iterator country = game.getCountries()->begin(); country != game.getCountries()->end(); ++country) { if ((*country)->getRules()->insideCountry(lon, lat)) { (*country)->addActivityAlien(_rule.getPoints()); break; } } }
/** * Shows the Select Armor window. * @param action Pointer to an action. */ void CraftArmorState::lstSoldiersClick(Action *action) { Soldier *s = _base->getSoldiers()->at(_lstSoldiers->getSelectedRow()); if (!(s->getCraft() && s->getCraft()->getStatus() == "STR_OUT")) { if (action->getDetails()->button.button == SDL_BUTTON_LEFT) { _game->pushState(new SoldierArmorState(_base, _lstSoldiers->getSelectedRow())); } else if (action->getDetails()->button.button == SDL_BUTTON_RIGHT) { SavedGame *save; save = _game->getSavedGame(); Armor *a = _game->getMod()->getArmor(save->getLastSelectedArmor()); if (a && (a->getUnits().empty() || std::find(a->getUnits().begin(), a->getUnits().end(), s->getRules()->getType()) != a->getUnits().end())) { if (save->getMonthsPassed() != -1) { if (_base->getStorageItems()->getItem(a->getStoreItem()) > 0 || a->getStoreItem() == Armor::NONE) { if (s->getArmor()->getStoreItem() != Armor::NONE) { _base->getStorageItems()->addItem(s->getArmor()->getStoreItem()); } if (a->getStoreItem() != Armor::NONE) { _base->getStorageItems()->removeItem(a->getStoreItem()); } s->setArmor(a); _lstSoldiers->setCellText(_lstSoldiers->getSelectedRow(), 2, tr(a->getType())); } } else { s->setArmor(a); _lstSoldiers->setCellText(_lstSoldiers->getSelectedRow(), 2, tr(a->getType())); } } } } }
/** * @param node The YAML node containing the data. * @param game The game data, required to locate the alien base. */ void AlienMission::load(const YAML::Node& node, SavedGame &game) { _region = node["region"].as<std::string>(_region); _race = node["race"].as<std::string>(_race); _nextWave = node["nextWave"].as<unsigned>(_nextWave); _nextUfoCounter = node["nextUfoCounter"].as<unsigned>(_nextUfoCounter); _spawnCountdown = node["spawnCountdown"].as<unsigned>(_spawnCountdown); _liveUfos = node["liveUfos"].as<unsigned>(_liveUfos); _uniqueID = node["uniqueID"].as<int>(_uniqueID); if (const YAML::Node &base = node["alienBase"]) { int id = base.as<int>(); std::vector<AlienBase*>::const_iterator found = std::find_if(game.getAlienBases()->begin(), game.getAlienBases()->end(), matchById(id)); if (found == game.getAlienBases()->end()) { throw Exception("Corrupted save: Invalid base for mission."); } _base = *found; } }
void SaveLoadMenu::addSavedGameItems(WidgetListBox *listBox) { Common::FileList dirs; Common::UString savesDir = Common::FilePath::normalize(ConfigMan.getString("path") + "/saves"); dirs.addSubDirectories(savesDir); Common::UString slotTextFormat = TalkMan.getString(1594); dirs.sort(true); for (Common::FileList::const_iterator it = dirs.begin(); it != dirs.end(); ++it) { Common::UString saveDir = *it; Common::UString baseName; try { baseName = getBaseNameFromDirectory(saveDir); } catch (Common::Exception &e) { e.add("Failed to get save base name from directory \"%s\"", saveDir.c_str()); printException(e, "WARNING: "); continue; } if (_type == kSaveLoadMenuTypeSave && !baseName.contains("Game")) continue; _saveDirs.push_back(saveDir); SavedGame *save = SavedGame::load(saveDir); uint32 timePlayed = save->getTimePlayed(); Common::UString slotText(slotTextFormat); slotText.replaceAll("Game <CUSTOM0>", baseName); slotText.replaceAll("<CUSTOM1>", Common::composeString(timePlayed / 3600)); slotText.replaceAll("<CUSTOM2>", Common::composeString(timePlayed % 3600 / 60)); if (baseName.contains("Game")) slotText += "\r\n" + save->getName(); delete save; listBox->addItem(slotText); } }
/** * Loads the specified save. */ void LoadGameState::think() { State::think(); // Make sure it gets drawn properly if (_firstRun < 10) { _firstRun++; } else { _game->popState(); // Load the game SavedGame *s = new SavedGame(); try { s->load(_filename, _game->getMod()); _game->setSavedGame(s); Options::baseXResolution = Options::baseXGeoscape; Options::baseYResolution = Options::baseYGeoscape; _game->getScreen()->resetDisplay(false); _game->setState(new GeoscapeState); if (_game->getSavedGame()->getSavedBattle() != 0) { _game->getSavedGame()->getSavedBattle()->loadMapResources(_game->getMod()); Options::baseXResolution = Options::baseXBattlescape; Options::baseYResolution = Options::baseYBattlescape; _game->getScreen()->resetDisplay(false); BattlescapeState *bs = new BattlescapeState; _game->pushState(bs); _game->getSavedGame()->getSavedBattle()->setBattleState(bs); } } catch (Exception &e) { Log(LOG_ERROR) << e.what(); std::wostringstream error; error << tr("STR_LOAD_UNSUCCESSFUL") << L'\x02' << Language::fsToWstr(e.what()); if (_origin != OPT_BATTLESCAPE) _game->pushState(new ErrorMessageState(error.str(), _palette, _game->getMod()->getInterface("errorMessages")->getElement("geoscapeColor")->color, "BACK01.SCR", _game->getMod()->getInterface("errorMessages")->getElement("geoscapePalette")->color)); else _game->pushState(new ErrorMessageState(error.str(), _palette, _game->getMod()->getInterface("errorMessages")->getElement("battlescapeColor")->color, "TAC00.SCR", _game->getMod()->getInterface("errorMessages")->getElement("battlescapePalette")->color)); if (_game->getSavedGame() == s) _game->setSavedGame(0); else delete s; } catch (YAML::Exception &e) { Log(LOG_ERROR) << e.what(); std::wostringstream error; error << tr("STR_LOAD_UNSUCCESSFUL") << L'\x02' << Language::fsToWstr(e.what()); if (_origin != OPT_BATTLESCAPE) _game->pushState(new ErrorMessageState(error.str(), _palette, _game->getMod()->getInterface("errorMessages")->getElement("geoscapeColor")->color, "BACK01.SCR", _game->getMod()->getInterface("errorMessages")->getElement("geoscapePalette")->color)); else _game->pushState(new ErrorMessageState(error.str(), _palette, _game->getMod()->getInterface("errorMessages")->getElement("battlescapeColor")->color, "TAC00.SCR", _game->getMod()->getInterface("errorMessages")->getElement("battlescapePalette")->color)); if (_game->getSavedGame() == s) _game->setSavedGame(0); else delete s; } CrossPlatform::flashWindow(); } }
/** * Loads the UFO from a YAML file. * @param node YAML node. * @param ruleset The game rules. Use to access the trajectory rules. * @param game The game data. Used to find the UFO's mission. */ void Ufo::load(const YAML::Node &node, const Ruleset &ruleset, SavedGame &game) { MovingTarget::load(node); _id = node["id"].as<int>(_id); _crashId = node["crashId"].as<int>(_crashId); _landId = node["landId"].as<int>(_landId); _damage = node["damage"].as<int>(_damage); _altitude = node["altitude"].as<std::string>(_altitude); _direction = node["direction"].as<std::string>(_direction); _detected = node["detected"].as<bool>(_detected); _hyperDetected = node["hyperDetected"].as<bool>(_hyperDetected); _secondsRemaining = node["secondsRemaining"].as<size_t>(_secondsRemaining); _inBattlescape = node["inBattlescape"].as<bool>(_inBattlescape); double lon = _lon; double lat = _lat; if (const YAML::Node &dest = node["dest"]) { lon = dest["lon"].as<double>(); lat = dest["lat"].as<double>(); } _dest = new Waypoint(); _dest->setLongitude(lon); _dest->setLatitude(lat); if (const YAML::Node &status = node["status"]) { _status = (UfoStatus)status.as<int>(); } else { if (_damage >= _rules->getMaxDamage()) { _status = DESTROYED; } else if (_damage >= _rules->getMaxDamage() / 2) { _status = CRASHED; } else if (_altitude == "STR_GROUND") { _status = LANDED; } else { _status = FLYING; } } if (game.getMonthsPassed() != -1) { int missionID = node["mission"].as<int>(); std::vector<AlienMission *>::const_iterator found = std::find_if (game.getAlienMissions().begin(), game.getAlienMissions().end(), matchMissionID(missionID)); if (found == game.getAlienMissions().end()) { // Corrupt save file. throw Exception("Unknown mission, save file is corrupt."); } _mission = *found; std::string tid = node["trajectory"].as<std::string>(); _trajectory = ruleset.getUfoTrajectory(tid); _trajectoryPoint = node["trajectoryPoint"].as<size_t>(_trajectoryPoint); } _fireCountdown = node["fireCountdown"].as<int>(_fireCountdown); _escapeCountdown = node["escapeCountdown"].as<int>(_escapeCountdown); if (_inBattlescape) setSpeed(0); }
/** * Prepares debriefing: gathers Aliens, Corpses, Artefacts, UFO Components. * Adds the items to the craft. * Also calculates the soldiers experience, and possible promotions. * If aborted, only the things on the exit area are recovered. */ void DebriefingState::prepareDebriefing() { _stats.push_back(new DebriefingStat("STR_ALIENS_KILLED", false)); _stats.push_back(new DebriefingStat("STR_ALIEN_CORPSES_RECOVERED", false)); _stats.push_back(new DebriefingStat("STR_LIVE_ALIENS_RECOVERED", false)); _stats.push_back(new DebriefingStat("STR_ALIEN_ARTIFACTS_RECOVERED", false)); _stats.push_back(new DebriefingStat("STR_ALIEN_BASE_CONTROL_DESTROYED", false)); _stats.push_back(new DebriefingStat("STR_CIVILIANS_KILLED_BY_ALIENS", false)); _stats.push_back(new DebriefingStat("STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES", false)); _stats.push_back(new DebriefingStat("STR_CIVILIANS_SAVED", false)); _stats.push_back(new DebriefingStat("STR_XCOM_OPERATIVES_KILLED", false)); //_stats.push_back(new DebriefingStat("STR_XCOM_OPERATIVES_RETIRED_THROUGH_INJURY", false)); _stats.push_back(new DebriefingStat("STR_XCOM_OPERATIVES_MISSING_IN_ACTION", false)); _stats.push_back(new DebriefingStat("STR_TANKS_DESTROYED", false)); _stats.push_back(new DebriefingStat("STR_XCOM_CRAFT_LOST", false)); _stats.push_back(new DebriefingStat("STR_UFO_POWER_SOURCE", true)); _stats.push_back(new DebriefingStat("STR_UFO_NAVIGATION", true)); _stats.push_back(new DebriefingStat("STR_UFO_CONSTRUCTION", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_FOOD", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_REPRODUCTION", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_ENTERTAINMENT", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_SURGERY", true)); _stats.push_back(new DebriefingStat("STR_EXAMINATION_ROOM", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_ALLOYS", true)); _stats.push_back(new DebriefingStat("STR_ELERIUM_115", true)); SavedGame *save = _game->getSavedGame(); SavedBattleGame *battle = save->getBattleGame(); bool aborted = battle->isAborted(); Craft* craft = 0; std::vector<Craft*>::iterator craftIterator; Base* base = 0; int playerInExitArea = 0; // if this stays 0 the craft is lost... int playersSurvived = 0; // if this stays 0 the craft is lost... for (std::vector<Base*>::iterator i = save->getBases()->begin(); i != save->getBases()->end(); ++i) { // in case we have a craft - check which craft it is about for (std::vector<Craft*>::iterator j = (*i)->getCrafts()->begin(); j != (*i)->getCrafts()->end(); ++j) { if ((*j)->isInBattlescape()) { craft = (*j); base = (*i); craftIterator = j; craft->returnToBase(); craft->setLowFuel(true); craft->setInBattlescape(false); } } } // UFO crash/landing site disappears for (std::vector<Ufo*>::iterator i = save->getUfos()->begin(); i != save->getUfos()->end(); ++i) { if ((*i)->isInBattlescape()) { delete *i; save->getUfos()->erase(i); break; } } // lets see what happens with units for (std::vector<BattleUnit*>::iterator j = battle->getUnits()->begin(); j != battle->getUnits()->end(); ++j) { UnitStatus status = (*j)->getStatus(); UnitFaction faction = (*j)->getFaction(); int value = (*j)->getValue(); Soldier *soldier = save->getSoldier((*j)->getId()); if (status == STATUS_DEAD) { if (faction == FACTION_HOSTILE) { addStat("STR_ALIENS_KILLED", 1, value); } if (faction == FACTION_PLAYER) { if (soldier != 0) { addStat("STR_XCOM_OPERATIVES_KILLED", 1, -value); for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end(); ++i) { if ((*i) == soldier) { delete (*i); base->getSoldiers()->erase(i); break; } } } else { // non soldier player = tank addStat("STR_TANKS_DESTROYED", 1, -value); } } } else if (status == STATUS_UNCONSCIOUS) { if (faction == FACTION_HOSTILE && (!aborted || (*j)->isInExitArea())) { addStat("STR_LIVE_ALIENS_RECOVERED", 1, value); } } else if (faction == FACTION_PLAYER) { playersSurvived++; if ((*j)->isInExitArea() || !aborted) { playerInExitArea++; (*j)->postMissionProcedures(save); } else { addStat("STR_XCOM_OPERATIVES_MISSING_IN_ACTION", 1, -value); for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end(); ++i) { if ((*i) == soldier) { delete (*i); base->getSoldiers()->erase(i); break; } } } } } if (((playerInExitArea == 0 && aborted) || (playersSurvived == 0)) && craft != 0) { addStat("STR_XCOM_CRAFT_LOST", 1, -200); delete craft; base->getCrafts()->erase(craftIterator); for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end();) { if ((*i)->getCraft() == craft) { delete (*i); i = base->getSoldiers()->erase(i); } else { ++i; } } _txtTitle->setText(_game->getLanguage()->getString("STR_CRAFT_IS_LOST")); return; } if (!aborted && playersSurvived > 0) // RECOVER UFO : run through all tiles to recover UFO components and items { if (battle->getMissionType() == "STR_BASE_DEFENCE") { _txtTitle->setText(_game->getLanguage()->getString("STR_BASE_IS_SAVED")); } else { _txtTitle->setText(_game->getLanguage()->getString("STR_UFO_IS_RECOVERED")); } for (int i = 0; i < battle->getHeight() * battle->getLength() * battle->getWidth(); ++i) { for (int part = 0; part < 4; part++) { if (battle->getTiles()[i]->getMapData(part)) { switch (battle->getTiles()[i]->getMapData(part)->getSpecialType()) { case UFO_POWER_SOURCE: addStat("STR_UFO_POWER_SOURCE", 1, 1); break; case DESTROY_OBJECTIVE:break; // this is the brain case UFO_NAVIGATION: addStat("STR_UFO_NAVIGATION", 1, 1); break; case ALIEN_FOOD: addStat("STR_ALIEN_FOOD", 1, 1); break; case ALIEN_REPRODUCTION: addStat("STR_ALIEN_REPRODUCTION", 1, 1); break; case ALIEN_ENTERTAINMENT: addStat("STR_ALIEN_ENTERTAINMENT", 1, 1); break; case ALIEN_SURGERY: addStat("STR_ALIEN_SURGERY", 1, 1); break; case UNKNOWN09: addStat("STR_UFO_CONSTRUCTION", 1, 1); break; case ALIEN_ALLOYS: addStat("STR_ALIEN_ALLOYS", 1, 1); break; case EXAM_ROOM: addStat("STR_EXAMINATION_ROOM", 1, 1); break; } } } } // alien alloys recovery values are divided by 10 or divided by 150 in case of an alien base int divider = battle->getMissionType()=="STR_ALIEN_BASE_ASSAULT"?150:10; for (std::vector<DebriefingStat*>::iterator i = _stats.begin(); i != _stats.end(); ++i) { if ((*i)->item == "STR_ALIEN_ALLOYS") { (*i)->qty = (*i)->qty / divider; (*i)->score = (*i)->score / divider; break; } /*if ((*i)->recovery && (*i)->qty > 0) { base->getItems()->addItem((*i)->item, (*i)->qty); }*/ } } else { if (battle->getMissionType() == "STR_BASE_DEFENCE") { _txtTitle->setText(_game->getLanguage()->getString("STR_BASE_IS_LOST")); } else { _txtTitle->setText(_game->getLanguage()->getString("STR_UFO_IS_NOT_RECOVERED")); } } }
void StatisticsState::listStats() { SavedGame *save = _game->getSavedGame(); std::ostringstream ss; GameTime *time = save->getTime(); if (save->getEnding() == END_WIN) { ss << tr("STR_VICTORY"); } else if (save->getEnding() == END_LOSE) { ss << tr("STR_DEFEAT"); } else { ss << tr("STR_STATISTICS"); } ss << Unicode::TOK_NL_SMALL << time->getDayString(_game->getLanguage()) << " " << tr(time->getMonthString()) << " " << time->getYear(); _txtTitle->setText(ss.str()); int monthlyScore = sumVector(save->getResearchScores()) / save->getResearchScores().size(); int64_t totalIncome = sumVector(save->getIncomes()); int64_t totalExpenses = sumVector(save->getExpenditures()); int alienBasesDestroyed = 0, xcomBasesLost = 0; int missionsWin = 0, missionsLoss = 0, nightMissions = 0; int bestScore = -9999, worstScore = 9999; for (std::vector<MissionStatistics*>::const_iterator i = save->getMissionStatistics()->begin(); i != save->getMissionStatistics()->end(); ++i) { if ((*i)->success) { missionsWin++; } else { missionsLoss++; } bestScore = std::max(bestScore, (*i)->score); worstScore = std::min(worstScore, (*i)->score); if ((*i)->daylight > 5) { nightMissions++; } if ((*i)->isAlienBase() && (*i)->success) { alienBasesDestroyed++; } if ((*i)->isBaseDefense() && !(*i)->success) { xcomBasesLost++; } } // Make sure dummy values aren't left in bestScore = (bestScore == -9999) ? 0 : bestScore; worstScore = (worstScore == 9999) ? 0 : worstScore; std::vector<Soldier*> allSoldiers; for (std::vector<Base*>::const_iterator i = save->getBases()->begin(); i != save->getBases()->end(); ++i) { allSoldiers.insert(allSoldiers.end(), (*i)->getSoldiers()->begin(), (*i)->getSoldiers()->end()); } allSoldiers.insert(allSoldiers.end(), save->getDeadSoldiers()->begin(), save->getDeadSoldiers()->end()); int soldiersRecruited = allSoldiers.size(); int soldiersLost = save->getDeadSoldiers()->size(); int aliensKilled = 0, aliensCaptured = 0, friendlyKills = 0; int daysWounded = 0, longestMonths = 0; int shotsFired = 0, shotsLanded = 0; std::map<std::string, int> weaponKills, alienKills; for (std::vector<Soldier*>::iterator i = allSoldiers.begin(); i != allSoldiers.end(); ++i) { SoldierDiary *diary = (*i)->getDiary(); aliensKilled += diary->getKillTotal(); aliensCaptured += diary->getStunTotal(); daysWounded += diary->getDaysWoundedTotal(); longestMonths = std::max(longestMonths, diary->getMonthsService()); std::map<std::string, int> weaponTotal = diary->getWeaponTotal(); shotsFired += diary->getShotsFiredTotal(); shotsLanded += diary->getShotsLandedTotal(); for (std::map<std::string, int>::const_iterator j = weaponTotal.begin(); j != weaponTotal.end(); ++j) { if (weaponKills.find(j->first) == weaponKills.end()) { weaponKills[j->first] = j->second; } else { weaponKills[j->first] += j->second; } } if ((*i)->getDeath() != 0 && (*i)->getDeath()->getCause() != 0) { const BattleUnitKills *kills = (*i)->getDeath()->getCause(); if (kills->faction == FACTION_PLAYER) { friendlyKills++; } if (!kills->race.empty()) { if (alienKills.find(kills->race) == alienKills.end()) { alienKills[kills->race] = 1; } else { alienKills[kills->race] += 1; } } } } int accuracy = 0; if (shotsFired > 0) { accuracy = 100 * shotsLanded / shotsFired; } int maxWeapon = 0; std::string highestWeapon = "STR_NONE"; for (std::map<std::string, int>::const_iterator i = weaponKills.begin(); i != weaponKills.end(); ++i) { if (i->second > maxWeapon) { maxWeapon = i->second; highestWeapon = i->first; } } int maxAlien = 0; std::string highestAlien = "STR_NONE"; for (std::map<std::string, int>::const_iterator i = alienKills.begin(); i != alienKills.end(); ++i) { if (i->second > maxAlien) { maxAlien = i->second; highestAlien = i->first; } } std::map<std::string, int> ids = save->getAllIds(); int alienBases = alienBasesDestroyed; for (std::vector<AlienBase*>::iterator i = save->getAlienBases()->begin(); i != save->getAlienBases()->end(); ++i) { if ((*i)->isDiscovered()) { alienBases++; } } int ufosDetected = std::max(0, ids["STR_UFO"] - 1); int terrorSites = std::max(0, ids["STR_TERROR_SITE"] - 1); int totalCrafts = 0; for (std::vector<std::string>::const_iterator i = _game->getMod()->getCraftsList().begin(); i != _game->getMod()->getCraftsList().end(); ++i) { totalCrafts += std::max(0, ids[*i] - 1); } int xcomBases = save->getBases()->size() + xcomBasesLost; int currentScientists = 0, currentEngineers = 0; for (std::vector<Base*>::const_iterator i = save->getBases()->begin(); i != save->getBases()->end(); ++i) { currentScientists += (*i)->getTotalScientists(); currentEngineers += (*i)->getTotalEngineers(); } int countriesLost = 0; for (std::vector<Country*>::const_iterator i = save->getCountries()->begin(); i != save->getCountries()->end(); ++i) { if ((*i)->getPact()) { countriesLost++; } } int researchDone = save->getDiscoveredResearch().size(); std::string difficulty[] = { "STR_1_BEGINNER", "STR_2_EXPERIENCED", "STR_3_VETERAN", "STR_4_GENIUS", "STR_5_SUPERHUMAN" }; _lstStats->addRow(2, tr("STR_DIFFICULTY").c_str(), tr(difficulty[save->getDifficulty()]).c_str()); _lstStats->addRow(2, tr("STR_AVERAGE_MONTHLY_RATING").c_str(), Unicode::formatNumber(monthlyScore).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_INCOME").c_str(), Unicode::formatFunding(totalIncome).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_EXPENDITURE").c_str(), Unicode::formatFunding(totalExpenses).c_str()); _lstStats->addRow(2, tr("STR_MISSIONS_WON").c_str(), Unicode::formatNumber(missionsWin).c_str()); _lstStats->addRow(2, tr("STR_MISSIONS_LOST").c_str(), Unicode::formatNumber(missionsLoss).c_str()); _lstStats->addRow(2, tr("STR_NIGHT_MISSIONS").c_str(), Unicode::formatNumber(nightMissions).c_str()); _lstStats->addRow(2, tr("STR_BEST_RATING").c_str(), Unicode::formatNumber(bestScore).c_str()); _lstStats->addRow(2, tr("STR_WORST_RATING").c_str(), Unicode::formatNumber(worstScore).c_str()); _lstStats->addRow(2, tr("STR_SOLDIERS_RECRUITED").c_str(), Unicode::formatNumber(soldiersRecruited).c_str()); _lstStats->addRow(2, tr("STR_SOLDIERS_LOST").c_str(), Unicode::formatNumber(soldiersLost).c_str()); _lstStats->addRow(2, tr("STR_ALIEN_KILLS").c_str(), Unicode::formatNumber(aliensKilled).c_str()); _lstStats->addRow(2, tr("STR_ALIEN_CAPTURES").c_str(), Unicode::formatNumber(aliensCaptured).c_str()); _lstStats->addRow(2, tr("STR_FRIENDLY_KILLS").c_str(), Unicode::formatNumber(friendlyKills).c_str()); _lstStats->addRow(2, tr("STR_AVERAGE_ACCURACY").c_str(), Unicode::formatPercentage(accuracy).c_str()); _lstStats->addRow(2, tr("STR_WEAPON_MOST_KILLS").c_str(), tr(highestWeapon).c_str()); _lstStats->addRow(2, tr("STR_ALIEN_MOST_KILLS").c_str(), tr(highestAlien).c_str()); _lstStats->addRow(2, tr("STR_LONGEST_SERVICE").c_str(), Unicode::formatNumber(longestMonths).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_DAYS_WOUNDED").c_str(), Unicode::formatNumber(daysWounded).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_UFOS").c_str(), Unicode::formatNumber(ufosDetected).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_ALIEN_BASES").c_str(), Unicode::formatNumber(alienBases).c_str()); _lstStats->addRow(2, tr("STR_COUNTRIES_LOST").c_str(), Unicode::formatNumber(countriesLost).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_TERROR_SITES").c_str(), Unicode::formatNumber(terrorSites).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_BASES").c_str(), Unicode::formatNumber(xcomBases).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_CRAFT").c_str(), Unicode::formatNumber(totalCrafts).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_SCIENTISTS").c_str(), Unicode::formatNumber(currentScientists).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_ENGINEERS").c_str(), Unicode::formatNumber(currentEngineers).c_str()); _lstStats->addRow(2, tr("STR_TOTAL_RESEARCH").c_str(), Unicode::formatNumber(researchDone).c_str()); }
/** * Loads the specified save. */ void LoadGameState::init() { State::init(); // Ignore quick loads without a save available if (_filename == SavedGame::QUICKSAVE && !CrossPlatform::fileExists(Options::getUserFolder() + _filename)) { _game->popState(); return; } // Make sure message is shown (if any) blit(); _game->getScreen()->flip(); _game->popState(); // Load the game SavedGame *s = new SavedGame(); try { s->load(_filename, _game->getRuleset()); _game->setSavedGame(s); Options::baseXResolution = Options::baseXGeoscape; Options::baseYResolution = Options::baseYGeoscape; _game->getScreen()->resetDisplay(false); _game->setState(new GeoscapeState(_game)); if (_game->getSavedGame()->getSavedBattle() != 0) { _game->getSavedGame()->getSavedBattle()->loadMapResources(_game); Options::baseXResolution = Options::baseXBattlescape; Options::baseYResolution = Options::baseYBattlescape; _game->getScreen()->resetDisplay(false); BattlescapeState *bs = new BattlescapeState(_game); _game->pushState(bs); _game->getSavedGame()->getSavedBattle()->setBattleState(bs); } } catch (Exception &e) { Log(LOG_ERROR) << e.what(); std::wostringstream error; error << tr("STR_LOAD_UNSUCCESSFUL") << L'\x02' << Language::fsToWstr(e.what()); if (_origin != OPT_BATTLESCAPE) _game->pushState(new ErrorMessageState(_game, error.str(), _palette, Palette::blockOffset(8) + 10, "BACK01.SCR", 6)); else _game->pushState(new ErrorMessageState(_game, error.str(), _palette, Palette::blockOffset(0), "TAC00.SCR", -1)); if (_game->getSavedGame() == s) _game->setSavedGame(0); else delete s; } catch (YAML::Exception &e) { Log(LOG_ERROR) << e.what(); std::wostringstream error; error << tr("STR_LOAD_UNSUCCESSFUL") << L'\x02' << Language::fsToWstr(e.what()); if (_origin != OPT_BATTLESCAPE) _game->pushState(new ErrorMessageState(_game, error.str(), _palette, Palette::blockOffset(8) + 10, "BACK01.SCR", 6)); else _game->pushState(new ErrorMessageState(_game, error.str(), _palette, Palette::blockOffset(0), "TAC00.SCR", -1)); if (_game->getSavedGame() == s) _game->setSavedGame(0); else delete s; } CrossPlatform::flashWindow(); }
/** * Generates a brand new saved game with starting data. * @return A new saved game. */ SavedGame *Ruleset::newSave() const { SavedGame *save = new SavedGame(); // Add countries for (std::vector<std::string>::const_iterator i = _countriesIndex.begin(); i != _countriesIndex.end(); ++i) { save->getCountries()->push_back(new Country(getCountry(*i))); } // Adjust funding to total $6M int missing = ((6000 - save->getCountryFunding()/1000) / (int)save->getCountries()->size()) * 1000; for (std::vector<Country*>::iterator i = save->getCountries()->begin(); i != save->getCountries()->end(); ++i) { (*i)->setFunding((*i)->getFunding().back() + missing); } save->setFunds(save->getCountryFunding()); // Add regions for (std::vector<std::string>::const_iterator i = _regionsIndex.begin(); i != _regionsIndex.end(); ++i) { save->getRegions()->push_back(new Region(getRegion(*i))); } // Set up IDs std::map<std::string, int> ids; for (std::vector<std::string>::const_iterator i = _craftsIndex.begin(); i != _craftsIndex.end(); ++i) { ids[*i] = 1; } save->initIds(ids); // Set up starting base Base *base = new Base(this); base->load(_startingBase, save, true); // Correct IDs for (std::vector<Craft*>::const_iterator i = base->getCrafts()->begin(); i != base->getCrafts()->end(); ++i) { save->getId((*i)->getRules()->getType()); } // Generate soldiers int soldiers = _startingBase["randomSoldiers"].as<int>(0); for (int i = 0; i < soldiers; ++i) { Soldier *soldier = new Soldier(getSoldier("XCOM"), getArmor("STR_NONE_UC"), &_names, save->getId("STR_SOLDIER")); soldier->setCraft(base->getCrafts()->front()); base->getSoldiers()->push_back(soldier); } save->getBases()->push_back(base); // Setup alien strategy save->getAlienStrategy().init(this); save->setTime(_startingTime); return save; }
/** * Initializes a new savegame with * everything available. */ void NewBattleState::initSave() { const Mod *mod = _game->getMod(); SavedGame *save = new SavedGame(); Base *base = new Base(mod); const YAML::Node &starter = _game->getMod()->getStartingBase(); base->load(starter, save, true, true); save->getBases()->push_back(base); // Kill everything we don't want in this base for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end(); ++i) delete (*i); base->getSoldiers()->clear(); for (std::vector<Craft*>::iterator i = base->getCrafts()->begin(); i != base->getCrafts()->end(); ++i) delete (*i); base->getCrafts()->clear(); base->getStorageItems()->getContents()->clear(); _craft = new Craft(mod->getCraft(_crafts[_cbxCraft->getSelected()]), base, 1); base->getCrafts()->push_back(_craft); // Generate soldiers for (int i = 0; i < 30; ++i) { int randomType = RNG::generate(0, _game->getMod()->getSoldiersList().size() - 1); Soldier *soldier = mod->genSoldier(save, _game->getMod()->getSoldiersList().at(randomType)); for (int n = 0; n < 5; ++n) { if (RNG::percent(70)) continue; soldier->promoteRank(); UnitStats* stats = soldier->getCurrentStats(); stats->tu += RNG::generate(0, 5); stats->stamina += RNG::generate(0, 5); stats->health += RNG::generate(0, 5); stats->bravery += RNG::generate(0, 5); stats->reactions += RNG::generate(0, 5); stats->firing += RNG::generate(0, 5); stats->throwing += RNG::generate(0, 5); stats->strength += RNG::generate(0, 5); stats->psiStrength += RNG::generate(0, 5); stats->melee += RNG::generate(0, 5); stats->psiSkill += RNG::generate(0, 20); } UnitStats* stats = soldier->getCurrentStats(); stats->bravery = (int)ceil(stats->bravery / 10.0) * 10; // keep it a multiple of 10 base->getSoldiers()->push_back(soldier); if (i < _craft->getRules()->getSoldiers()) soldier->setCraft(_craft); } // Generate items const std::vector<std::string> &items = mod->getItemsList(); for (std::vector<std::string>::const_iterator i = items.begin(); i != items.end(); ++i) { RuleItem *rule = _game->getMod()->getItem(*i); if (rule->getBattleType() != BT_CORPSE && rule->isRecoverable()) { base->getStorageItems()->addItem(*i, 1); if (rule->getBattleType() != BT_NONE && !rule->isFixed() && rule->getBigSprite() > -1) { _craft->getItems()->addItem(*i, 1); } } } // Add research const std::vector<std::string> &research = mod->getResearchList(); for (std::vector<std::string>::const_iterator i = research.begin(); i != research.end(); ++i) { save->addFinishedResearchSimple(mod->getResearch(*i)); } _game->setSavedGame(save); cbxMissionChange(0); }
/** * Loads new battle data from a YAML file. * @param filename YAML filename. */ void NewBattleState::load(const std::string &filename) { std::string s = Options::getMasterUserFolder() + filename + ".cfg"; if (!CrossPlatform::fileExists(s)) { initSave(); } else { try { YAML::Node doc = YAML::LoadFile(s); _cbxMission->setSelected(std::min(doc["mission"].as<size_t>(0), _missionTypes.size() - 1)); cbxMissionChange(0); _cbxCraft->setSelected(std::min(doc["craft"].as<size_t>(0), _crafts.size() - 1)); _slrDarkness->setValue(doc["darkness"].as<size_t>(0)); _cbxTerrain->setSelected(std::min(doc["terrain"].as<size_t>(0), _terrainTypes.size() - 1)); cbxTerrainChange(0); _cbxAlienRace->setSelected(std::min(doc["alienRace"].as<size_t>(0), _alienRaces.size() - 1)); _cbxDifficulty->setSelected(doc["difficulty"].as<size_t>(0)); _slrAlienTech->setValue(doc["alienTech"].as<size_t>(0)); if (doc["base"]) { const Mod *mod = _game->getMod(); SavedGame *save = new SavedGame(); Base *base = new Base(mod); base->load(doc["base"], save, false); save->getBases()->push_back(base); // Add research const std::vector<std::string> &research = mod->getResearchList(); for (std::vector<std::string>::const_iterator i = research.begin(); i != research.end(); ++i) { save->addFinishedResearchSimple(mod->getResearch(*i)); } // Generate items base->getStorageItems()->getContents()->clear(); const std::vector<std::string> &items = mod->getItemsList(); for (std::vector<std::string>::const_iterator i = items.begin(); i != items.end(); ++i) { RuleItem *rule = _game->getMod()->getItem(*i); if (rule->getBattleType() != BT_CORPSE && rule->isRecoverable()) { base->getStorageItems()->addItem(*i, 1); } } // Fix invalid contents if (base->getCrafts()->empty()) { std::string craftType = _crafts[_cbxCraft->getSelected()]; _craft = new Craft(_game->getMod()->getCraft(craftType), base, save->getId(craftType)); base->getCrafts()->push_back(_craft); } else { _craft = base->getCrafts()->front(); for (std::map<std::string, int>::iterator i = _craft->getItems()->getContents()->begin(); i != _craft->getItems()->getContents()->end(); ++i) { RuleItem *rule = _game->getMod()->getItem(i->first); if (!rule) { i->second = 0; } } } _game->setSavedGame(save); } else { initSave(); } } catch (YAML::Exception &e) { Log(LOG_WARNING) << e.what(); initSave(); } } }