/** * 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; }
/** * 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")); } } }
/** * 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(); } } }
/** * 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); }
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()); }