From 3e1fc06d6c9e221fee1cad2e4fdc30b54acd62ad Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sat, 18 Jul 2015 23:14:20 +0200 Subject: [PATCH] CPlayerProgress Extracted most operations on user profile from CRobotMain and CMainDialog to a dedicated class --- src/CMakeLists.txt | 1 + src/object/level_category.cpp | 6 +- src/object/player_progress.cpp | 425 +++++++++++++++++++++++++++ src/object/player_progress.h | 110 +++++++ src/object/robotmain.cpp | 145 ++++----- src/object/robotmain.h | 31 +- src/ui/maindialog.cpp | 519 ++++++--------------------------- src/ui/maindialog.h | 48 +-- src/ui/studio.cpp | 4 +- 9 files changed, 707 insertions(+), 582 deletions(-) create mode 100644 src/object/player_progress.cpp create mode 100644 src/object/player_progress.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6da268f5..60403812 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -170,6 +170,7 @@ set(BASE_SOURCES object/object_manager.cpp object/old_object.cpp object/old_object_interface.cpp + object/player_progress.cpp object/robotmain.cpp object/scene_conditions.cpp object/task/task.cpp diff --git a/src/object/level_category.cpp b/src/object/level_category.cpp index c9a2e99c..72de9141 100644 --- a/src/object/level_category.cpp +++ b/src/object/level_category.cpp @@ -20,7 +20,7 @@ #include -const std::map category_dir_map = { +const std::map CATEGORY_DIR_MAP = { { LevelCategory::Missions, "missions" }, { LevelCategory::FreeGame, "freemissions" }, { LevelCategory::Exercises, "exercises" }, @@ -34,12 +34,12 @@ const std::map category_dir_map = { std::string GetLevelCategoryDir(LevelCategory category) { - return category_dir_map.at(category); + return CATEGORY_DIR_MAP.at(category); } LevelCategory GetLevelCategoryFromDir(std::string dir) { - for(auto it = category_dir_map.begin(); it != category_dir_map.end(); ++it) + for(auto it = CATEGORY_DIR_MAP.begin(); it != CATEGORY_DIR_MAP.end(); ++it) { if(it->second == dir) { diff --git a/src/object/player_progress.cpp b/src/object/player_progress.cpp new file mode 100644 index 00000000..90c1c0c8 --- /dev/null +++ b/src/object/player_progress.cpp @@ -0,0 +1,425 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsiteс.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ +#include "object/player_progress.h" + +#include "common/logger.h" +#include "common/make_unique.h" +#include "common/profile.h" +#include "common/resources/resourcemanager.h" +#include "common/resources/inputstream.h" +#include "common/resources/outputstream.h" +#include "common/restext.h" + +#include "object/level/parser.h" +#include "object/robotmain.h" + +void PlayerApperance::DefPerso() +{ + this->colorCombi.r = 206.0f/256.0f; + this->colorCombi.g = 206.0f/256.0f; + this->colorCombi.b = 204.0f/256.0f; // ~white + this->colorBand.r = 255.0f/256.0f; + this->colorBand.g = 132.0f/256.0f; + this->colorBand.b = 1.0f/256.0f; // orange + + if ( this->face == 0 ) // normal ? + { + this->glasses = 0; + this->colorHair.r = 90.0f/256.0f; + this->colorHair.g = 95.0f/256.0f; + this->colorHair.b = 85.0f/256.0f; // black + } + if ( this->face == 1 ) // bald ? + { + this->glasses = 0; + this->colorHair.r = 83.0f/256.0f; + this->colorHair.g = 64.0f/256.0f; + this->colorHair.b = 51.0f/256.0f; // brown + } + if ( this->face == 2 ) // carlos ? + { + this->glasses = 1; + this->colorHair.r = 85.0f/256.0f; + this->colorHair.g = 48.0f/256.0f; + this->colorHair.b = 9.0f/256.0f; // brown + } + if ( this->face == 3 ) // blond ? + { + this->glasses = 4; + this->colorHair.r = 255.0f/256.0f; + this->colorHair.g = 255.0f/256.0f; + this->colorHair.b = 181.0f/256.0f; // yellow + } + + this->colorHair.a = 0.0f; + this->colorCombi.a = 0.0f; + this->colorBand.a = 0.0f; +} + +CPlayerProgress::CPlayerProgress(std::string playerName) +{ + m_playerName = playerName; + GetProfile().SetStringProperty("Gamer", "LastName", m_playerName); + + if (!CResourceManager::DirectoryExists(GetSaveDir())) + { + CResourceManager::CreateDirectory(GetSaveDir()); + } + + m_freegameLoaded = false; + + for(int i = 0; i < static_cast(LevelCategory::Max); i++) + { + m_levelInfoLoaded[static_cast(i)] = false; + } + + LoadApperance(); +} + +std::string CPlayerProgress::GetLastName() +{ + std::string name; + + if(!GetProfile().GetStringProperty("Gamer", "LastName", name)) + GetResource(RES_TEXT, RT_NAME_DEFAULT, name); + + return name; +} + +CPlayerProgress::~CPlayerProgress() +{ + +} + +bool CPlayerProgress::Delete() +{ + return CResourceManager::RemoveDirectory(GetSaveDir()); +} + +std::string CPlayerProgress::GetName() +{ + return m_playerName; +} + +std::string CPlayerProgress::GetSaveDir() +{ + return std::string(CRobotMain::GetInstancePointer()->GetSavegameDir()) + "/" + m_playerName; +} + +std::string CPlayerProgress::GetSaveFile(std::string filename) +{ + return GetSaveDir() + "/" + filename; +} + +// FINISHED LEVELS + +void CPlayerProgress::IncrementLevelTryCount(LevelCategory cat, int chap, int rank) +{ + m_levelInfo[cat][chap][rank].numTry ++; + SaveFinishedLevels(cat); +} + +int CPlayerProgress::GetLevelTryCount(LevelCategory cat, int chap, int rank) +{ + if(!m_levelInfoLoaded[cat]) + LoadFinishedLevels(cat); + return m_levelInfo[cat][chap][rank].numTry; +} + +void CPlayerProgress::SetLevelPassed(LevelCategory cat, int chap, int rank, bool bPassed) +{ + m_levelInfo[cat][chap][rank].bPassed = bPassed; + SaveFinishedLevels(cat); + + if (bPassed && rank != 0) + { + assert(cat == CRobotMain::GetInstancePointer()->GetLevelCategory() && chap == CRobotMain::GetInstancePointer()->GetLevelChap()); //TODO: Refactor UpdateChapterPassed + CRobotMain::GetInstancePointer()->UpdateChapterPassed(); + } +} + +bool CPlayerProgress::GetLevelPassed(LevelCategory cat, int chap, int rank) +{ + if(!m_levelInfoLoaded[cat]) + LoadFinishedLevels(cat); + return m_levelInfo[cat][chap][rank].bPassed; +} + +int CPlayerProgress::GetChapPassed(LevelCategory cat) +{ + if ( CRobotMain::GetInstancePointer()->GetShowAll() ) return MAXSCENE; + + for ( int j = 1; j <= MAXSCENE; j++ ) + { + if ( !GetLevelPassed(cat, j, 0) ) + { + return j; + } + } + return MAXSCENE; +} + +void CPlayerProgress::SetSelectedChap(LevelCategory category, int chap) +{ + m_selectChap[category] = chap; + SaveFinishedLevels(category); +} + +int CPlayerProgress::GetSelectedChap(LevelCategory category) +{ + if(!m_levelInfoLoaded[category]) + LoadFinishedLevels(category); + if(m_selectChap[category] < 1) return 1; + return m_selectChap[category]; +} + +void CPlayerProgress::SetSelectedRank(LevelCategory category, int rank) +{ + m_selectRank[category] = rank; + SaveFinishedLevels(category); +} + +int CPlayerProgress::GetSelectedRank(LevelCategory category) +{ + if(!m_levelInfoLoaded[category]) + LoadFinishedLevels(category); + if(m_selectRank[category] < 1) return 1; + return m_selectRank[category]; +} + +void CPlayerProgress::LoadFinishedLevels(LevelCategory category) +{ + m_levelInfo[category].clear(); + std::string filename = GetSaveFile(GetLevelCategoryDir(category)+".gam"); + + if (!CResourceManager::Exists(filename)) + return; + + CInputStream file; + file.open(filename); + if (!file.is_open()) + { + GetLogger()->Error("Unable to read list of finished levels from '%s'\n", filename.c_str()); + return; + } + + std::string line; + std::getline(file, line); + sscanf(line.c_str(), "CurrentChapter=%d CurrentSel=%d\n", &m_selectChap[category], &m_selectRank[category]); + + while (!file.eof()) + { + std::getline(file, line); + if (line == "") + { + break; + } + + int chap, rank, numTry, passed; + sscanf(line.c_str(), "Chapter %d: Scene %d: numTry=%d passed=%d\n", + &chap, &rank, &numTry, &passed); + + if ( chap < 0 || chap > MAXSCENE ) continue; + if ( rank < 0 || rank > MAXSCENE ) continue; + + m_levelInfo[category][chap][rank].numTry = numTry; + m_levelInfo[category][chap][rank].bPassed = passed; + } + + file.close(); + m_levelInfoLoaded[category] = true; +} + +void CPlayerProgress::SaveFinishedLevels(LevelCategory category) +{ + std::string filename = GetSaveFile(GetLevelCategoryDir(category)+".gam"); + COutputStream file; + file.open(filename); + if (!file.is_open()) + { + GetLogger()->Error("Unable to read list of finished missions from '%s'\n", filename.c_str()); + return; + } + + file << "CurrentChapter=" << m_selectChap[category] << " CurrentSel=" << m_selectRank[category] << "\n"; + + for (int chap = 0; chap <= MAXSCENE ; chap++) + { + if (m_levelInfo[category].find(chap) == m_levelInfo[category].end()) continue; + for(int rank = 0; rank <= MAXSCENE; rank++) + { + if (m_levelInfo[category][chap].find(rank) == m_levelInfo[category][chap].end()) continue; + if (m_levelInfo[category][chap][rank].numTry == 0 && !m_levelInfo[category][chap][rank].bPassed) continue; + + file << "Chapter " << chap << ": Scene " << rank << ": numTry=" << m_levelInfo[category][chap][rank].numTry << " passed=" << (m_levelInfo[category][chap][rank].bPassed ? "1" : "0") << "\n"; + } + } + + file.close(); +} + +// FREE GAME UNLOCK + +int CPlayerProgress::GetFreeGameBuildUnlock() +{ + if(!m_freegameLoaded) + LoadFreeGameUnlock(); + + return m_freegameBuild; +} + +void CPlayerProgress::SetFreeGameBuildUnlock(int freeBuild) +{ + m_freegameBuild = freeBuild; + SaveFreeGameUnlock(); +} + +int CPlayerProgress::GetFreeGameResearchUnlock() +{ + if(!m_freegameLoaded) + LoadFreeGameUnlock(); + return m_freegameResearch; +} + +void CPlayerProgress::SetFreeGameResearchUnlock(int freeResearch) +{ + m_freegameResearch = freeResearch; + SaveFreeGameUnlock(); +} + +void CPlayerProgress::LoadFreeGameUnlock() +{ + m_freegameResearch = 0; + m_freegameBuild = 0; + + std::string filename = GetSaveFile("research.gam"); + + if (!CResourceManager::Exists(filename)) + return; + + CInputStream file; + file.open(filename); + if (!file.is_open()) + { + GetLogger()->Error("Unable to read free game unlock state from '%s'\n", filename.c_str()); + return; + } + + std::string line; + std::getline(file, line); + sscanf(line.c_str(), "research=%d build=%d\n", &m_freegameResearch, &m_freegameBuild); + + file.close(); + + m_freegameLoaded = false; +} + +void CPlayerProgress::SaveFreeGameUnlock() +{ + std::string filename = GetSaveFile("research.gam"); + COutputStream file; + file.open(filename); + if (!file.is_open()) + { + GetLogger()->Error("Unable to write free game unlock state to '%s'\n", filename.c_str()); + return; + } + + file << "research=" << m_freegameResearch << " build=" << m_freegameBuild << "\n"; + + file.close(); +} + +// APPERANCE + +PlayerApperance& CPlayerProgress::GetApperance() +{ + return m_apperance; +} + +void CPlayerProgress::LoadApperance() +{ + m_apperance.face = 0; + m_apperance.DefPerso(); + + std::string filename = GetSaveFile("face.gam"); + if (!CResourceManager::Exists(filename)) + return; + + try + { + CLevelParser apperanceParser(filename); + apperanceParser.Load(); + CLevelParserLine* line; + + line = apperanceParser.Get("Head"); + m_apperance.face = line->GetParam("face")->AsInt(); + m_apperance.glasses = line->GetParam("glasses")->AsInt(); + m_apperance.colorHair = line->GetParam("hair")->AsColor(); + + line = apperanceParser.Get("Body"); + m_apperance.colorCombi = line->GetParam("combi")->AsColor(); + m_apperance.colorBand = line->GetParam("band")->AsColor(); + } + catch (CLevelParserException& e) + { + GetLogger()->Error("Unable to read personalized player apperance: %s\n", e.what()); + } +} + +void CPlayerProgress::SaveApperance() +{ + try + { + CLevelParser apperanceParser(GetSaveFile("face.gam")); + CLevelParserLineUPtr line; + + line = MakeUnique("Head"); + line->AddParam("face", MakeUnique(m_apperance.face)); + line->AddParam("glasses", MakeUnique(m_apperance.glasses)); + line->AddParam("hair", MakeUnique(m_apperance.colorHair)); + apperanceParser.AddLine(std::move(line)); + + line = MakeUnique("Body"); + line->AddParam("combi", MakeUnique(m_apperance.colorCombi)); + line->AddParam("band", MakeUnique(m_apperance.colorBand)); + apperanceParser.AddLine(std::move(line)); + + apperanceParser.Save(); + } + catch (CLevelParserException& e) + { + GetLogger()->Error("Unable to write personalized player apperance: %s\n", e.what()); + } +} + +// SAVE / LOAD SCENE + +void CPlayerProgress::SaveScene(std::string dir, std::string info) +{ + if (!CResourceManager::DirectoryExists(dir)) + { + CResourceManager::CreateDirectory(dir); + } + + std::string savegameFileName = dir + "/data.sav"; + std::string fileCBot = CResourceManager::GetSaveLocation() + "/" + dir + "/cbot.run"; + CRobotMain::GetInstancePointer()->IOWriteScene(savegameFileName.c_str(), fileCBot.c_str(), const_cast(info.c_str())); + CRobotMain::GetInstancePointer()->MakeSaveScreenshot(dir + "/screen.png"); +} diff --git a/src/object/player_progress.h b/src/object/player_progress.h new file mode 100644 index 00000000..d8cb1d7d --- /dev/null +++ b/src/object/player_progress.h @@ -0,0 +1,110 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsiteс.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ +#pragma once + +#include "graphics/core/color.h" + +#include "object/level_category.h" + +#include +#include + +struct LevelInfo +{ + int numTry; + bool bPassed; +}; + +struct PlayerApperance +{ + int face; // face + int glasses; // glasses + Gfx::Color colorHair; // hair color + Gfx::Color colorCombi; // spacesuit volor + Gfx::Color colorBand; // strips color + + void DefPerso(); +}; + +class CPlayerProgress +{ +public: + CPlayerProgress(std::string playerName); + static std::string GetLastName(); + ~CPlayerProgress(); + + bool Delete(); + + std::string GetName(); + + std::string GetSaveDir(); + std::string GetSaveFile(std::string filename); + + void IncrementLevelTryCount(LevelCategory cat, int chap, int rank); + int GetLevelTryCount(LevelCategory cat, int chap, int rank); + void SetLevelPassed(LevelCategory cat, int chap, int rank, bool bPassed); + bool GetLevelPassed(LevelCategory cat, int chap, int rank); + int GetChapPassed(LevelCategory cat); + + void SetSelectedChap(LevelCategory category, int chap); + int GetSelectedChap(LevelCategory category); + void SetSelectedRank(LevelCategory category, int rank); + int GetSelectedRank(LevelCategory category); + + int GetFreeGameBuildUnlock(); + void SetFreeGameBuildUnlock(int freeBuild); + int GetFreeGameResearchUnlock(); + void SetFreeGameResearchUnlock(int freeResearch); + + PlayerApperance& GetApperance(); + void LoadApperance(); + void SaveApperance(); + + void SaveScene(std::string dir, std::string info); + +protected: + void LoadFinishedLevels(LevelCategory category); + void SaveFinishedLevels(LevelCategory category); + + void LoadFreeGameUnlock(); + void SaveFreeGameUnlock(); + +protected: + //! Player name + std::string m_playerName; + + //! Is finished levels file loaded already? + std::map m_levelInfoLoaded; + //! Level completion info + std::map>> m_levelInfo; + //! Selected level chapter + std::map m_selectChap; + //! Selected level rank + std::map m_selectRank; + + //! Is freegame save file loaded already? + bool m_freegameLoaded; + //! Buildings unlocked for free game + int m_freegameBuild; + //! Researches unlocked for free game + int m_freegameResearch; + + //! Player apperance + PlayerApperance m_apperance; +}; diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index 18adfc93..b9335acb 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -67,6 +67,7 @@ #include "object/object.h" #include "object/object_create_exception.h" #include "object/object_manager.h" +#include "object/player_progress.h" #include "object/scene_conditions.h" #include "object/task/task.h" #include "object/task/taskbuild.h" @@ -238,8 +239,6 @@ CRobotMain::CRobotMain(CController* controller) m_researchEnable = 0; g_unit = UNIT; - m_gamerName = ""; - for (int i = 0; i < MAXSHOWLIMIT; i++) { m_showLimit[i].used = false; @@ -324,9 +323,7 @@ void CRobotMain::Create(bool loadProfile) m_engine->SetTracePrecision(1.0f); - if (loadProfile) GetProfile().GetStringProperty("Gamer", "LastName", m_gamerName); - SetGlobalGamerName(m_gamerName); - ReadFreeParam(); + SelectPlayer(CPlayerProgress::GetLastName()); CScriptFunctions::m_filesDir = CResourceManager::GetSaveLocation() + "/" + m_dialog->GetFilesDir(); //TODO: Refactor to PHYSFS while rewriting CBot engine CScriptFunctions::Init(); @@ -442,21 +439,20 @@ void CRobotMain::ChangePhase(Phase phase) if (m_gameTime > 10.0f) // did you play at least 10 seconds? { + LevelCategory cat = m_dialog->GetLevelCategory(); int chap = m_dialog->GetLevelChap(); int rank = m_dialog->GetLevelRank(); - int numTry = m_dialog->GetGamerInfoTry(chap, rank); - m_dialog->SetGamerInfoTry(chap, rank, numTry+1); - m_dialog->WriteGamerInfo(); + m_playerProgress->IncrementLevelTryCount(cat, chap, rank); } } if (phase == PHASE_WIN) // wins a simulation? { + LevelCategory cat = m_dialog->GetLevelCategory(); int chap = m_dialog->GetLevelChap(); int rank = m_dialog->GetLevelRank(); - m_dialog->SetGamerInfoPassed(chap, rank, true); + m_playerProgress->SetLevelPassed(cat, chap, rank, true); m_dialog->NextMission(); // passes to the next mission - m_dialog->WriteGamerInfo(); } m_app->SetLowCPU(true); // doesn't use much CPU in interface phases @@ -3898,13 +3894,16 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) CompileScript(soluce); // compiles all scripts if (category == LevelCategory::Missions && !resetObject) // mission? - WriteFreeParam(); + { + m_playerProgress->SetFreeGameResearchUnlock(m_playerProgress->GetFreeGameResearchUnlock() | m_researchDone[0]); + m_playerProgress->SetFreeGameBuildUnlock(m_playerProgress->GetFreeGameBuildUnlock() | m_build); + } if (category == LevelCategory::FreeGame && !resetObject) // free play? { - m_researchDone[0] = m_freeResearch; + m_researchDone[0] = m_playerProgress->GetFreeGameResearchUnlock(); - m_build = m_freeBuild; + m_build = m_playerProgress->GetFreeGameBuildUnlock(); m_build &= ~BUILD_RESEARCH; m_build &= ~BUILD_LABO; m_build |= BUILD_FACTORY; @@ -4035,11 +4034,11 @@ void CRobotMain::ChangeColor() colorRef1.r = 206.0f/256.0f; colorRef1.g = 206.0f/256.0f; colorRef1.b = 204.0f/256.0f; // ~white - colorNew1 = m_dialog->GetGamerColorCombi(); + colorNew1 = m_playerProgress->GetApperance().colorCombi; colorRef2.r = 255.0f/256.0f; colorRef2.g = 132.0f/256.0f; colorRef2.b = 1.0f/256.0f; // orange - colorNew2 = m_dialog->GetGamerColorBand(); + colorNew2 = m_playerProgress->GetApperance().colorBand; Math::Point exclu[6]; exclu[0] = Math::Point(192.0f/256.0f, 0.0f/256.0f); @@ -4081,7 +4080,7 @@ void CRobotMain::ChangeColor() colorRef1.b = 0.0f/256.0f; // yellow tolerance = 0.20f; } - colorNew1 = m_dialog->GetGamerColorHair(); + colorNew1 = m_playerProgress->GetApperance().colorHair; colorRef2.r = 0.0f; colorRef2.g = 0.0f; colorRef2.b = 0.0f; @@ -4611,14 +4610,14 @@ void CRobotMain::LoadOneScript(CObject *obj, int &nbError) { //? if (brain->GetCompile(i)) continue; - char filename[MAX_FNAME]; - sprintf(filename, "%s/%s/%c%.3d%.3d%.3d%.3d.txt", - GetSavegameDir(), m_gamerName.c_str(), categoryChar, chap, rank, objRank, i); + char file[MAX_FNAME]; + sprintf(file, "%c%.3d%.3d%.3d%.3d.txt", categoryChar, chap, rank, objRank, i); + std::string filename = m_playerProgress->GetSaveFile(file); if (CResourceManager::Exists(filename)) { Program* program = brain->GetOrAddProgram(i); - brain->ReadProgram(program, filename); + brain->ReadProgram(program, filename.c_str()); if (!brain->GetCompile(program)) nbError++; } } @@ -4686,12 +4685,13 @@ void CRobotMain::SaveOneScript(CObject *obj) // TODO: Find a better way to do that for (unsigned int i = 0; i <= 999; i++) { - char filename[MAX_FNAME]; - sprintf(filename, "%s/%s/%c%.3d%.3d%.3d%.3d.txt", - GetSavegameDir(), m_gamerName.c_str(), categoryChar, chap, rank, objRank, i); + char file[MAX_FNAME]; + sprintf(file, "%c%.3d%.3d%.3d%.3d.txt", categoryChar, chap, rank, objRank, i); + std::string filename = m_playerProgress->GetSaveFile(file); + if (i < programs.size()) { - brain->WriteProgram(programs[i].get(), filename); + brain->WriteProgram(programs[i].get(), filename.c_str()); } else { @@ -5240,52 +5240,18 @@ CObject* CRobotMain::IOReadScene(const char *filename, const char *filecbot) } -//! Writes the global parameters for free play -void CRobotMain::WriteFreeParam() +//! Changes current player +void CRobotMain::SelectPlayer(std::string playerName) { - m_freeResearch |= m_researchDone[0]; - m_freeBuild |= m_build; + assert(!playerName.empty()); - if (m_gamerName == "") return; - - COutputStream file; - file.open(std::string(GetSavegameDir()) + "/" + m_gamerName + "/research.gam"); - if (!file.is_open()) - { - GetLogger()->Error("Unable to write free game unlock state\n"); - return; - } - - file << "research=" << m_freeResearch << " build=" << m_freeBuild << "\n"; - - file.close(); + m_playerProgress = MakeUnique(playerName); + SetGlobalGamerName(playerName); } -//! Reads the global parameters for free play -void CRobotMain::ReadFreeParam() +CPlayerProgress* CRobotMain::GetPlayerProgress() { - m_freeResearch = 0; - m_freeBuild = 0; - - if (m_gamerName == "") return; - - if (!CResourceManager::Exists(std::string(GetSavegameDir()) + "/" + m_gamerName + "/research.gam")) - return; - - CInputStream file; - file.open(std::string(GetSavegameDir()) + "/" + m_gamerName + "/research.gam"); - if (!file.is_open()) - { - GetLogger()->Error("Unable to read free game unlock state\n"); - return; - } - - std::string line; - std::getline(file, line); - - sscanf(line.c_str(), "research=%d build=%d\n", &m_freeResearch, &m_freeBuild); - - file.close(); + return m_playerProgress.get(); } @@ -5704,31 +5670,17 @@ MissionType CRobotMain::GetMissionType() return m_missionType; } -//! Change the player's name -void CRobotMain::SetGamerName(const char *name) -{ - m_gamerName = std::string(name); - SetGlobalGamerName(m_gamerName); - ReadFreeParam(); -} - -//! Gets the player's name -char* CRobotMain::GetGamerName() -{ - return const_cast(m_gamerName.c_str()); -} - //! Returns the representation to use for the player int CRobotMain::GetGamerFace() { - return m_dialog->GetGamerFace(); + return m_playerProgress->GetApperance().face; } //! Returns the representation to use for the player int CRobotMain::GetGamerGlasses() { - return m_dialog->GetGamerGlasses(); + return m_playerProgress->GetApperance().glasses; } //! Returns the mode with just the head @@ -5758,6 +5710,16 @@ int CRobotMain::GetLevelRank() return m_dialog->GetLevelRank(); } +void CRobotMain::UpdateChapterPassed() +{ + return m_dialog->UpdateChapterPassed(); +} + +void CRobotMain::MakeSaveScreenshot(const std::string& name) +{ + return m_dialog->MakeSaveScreenshot(name); +} + //! Changes on the pause mode void CRobotMain::ChangePause(PauseType pause) @@ -6027,7 +5989,7 @@ int CRobotMain::AutosaveRotate(bool freeOne) { GetLogger()->Debug("Rotate autosaves...\n"); // Find autosave dirs - auto saveDirs = CResourceManager::ListDirectories(std::string(GetSavegameDir()) + "/" + GetGamerName()); + auto saveDirs = CResourceManager::ListDirectories(m_playerProgress->GetSaveDir()); std::map autosaveDirs; for (auto& dir : saveDirs) { @@ -6037,7 +5999,7 @@ int CRobotMain::AutosaveRotate(bool freeOne) if (dir.substr(0, autosavePrefix.length()) == "autosave") { int id = boost::lexical_cast(dir.substr(autosavePrefix.length())); - autosaveDirs[id] = std::string(GetSavegameDir()) + "/" + GetGamerName() + "/" + dir; + autosaveDirs[id] = m_playerProgress->GetSaveFile(dir); } } catch (...) @@ -6079,7 +6041,7 @@ int CRobotMain::AutosaveRotate(bool freeOne) { for (auto& save : autosavesToKeep) { - std::string newDir = std::string(GetSavegameDir()) + "/" + GetGamerName() + "/autosave" + boost::lexical_cast(save.first); + std::string newDir = m_playerProgress->GetSaveFile("autosave" + boost::lexical_cast(save.first)); GetLogger()->Trace("Rename %s -> %s\n", save.second.c_str(), newDir.c_str()); CResourceManager::Move(save.second, newDir); } @@ -6093,20 +6055,13 @@ void CRobotMain::Autosave() int id = AutosaveRotate(true); GetLogger()->Info("Autosave!\n"); - std::string dir = std::string(GetSavegameDir()) + "/" + GetGamerName() + "/autosave" + boost::lexical_cast(id); + std::string dir = m_playerProgress->GetSaveFile("autosave" + boost::lexical_cast(id)); - if (!CResourceManager::DirectoryExists(dir)) - { - CResourceManager::CreateDirectory(dir); - } - - std::string savegameFileName = dir + "/data.sav"; - std::string fileCBot = CResourceManager::GetSaveLocation() + "/" + dir + "/cbot.run"; char timestr[100]; TimeToAscii(time(NULL), timestr); - IOWriteScene(savegameFileName.c_str(), fileCBot.c_str(), const_cast((std::string("[AUTOSAVE] ")+timestr).c_str())); + std::string info = std::string("[AUTOSAVE] ")+timestr; - m_dialog->MakeSaveScreenshot(dir + "/screen.png"); + m_playerProgress->SaveScene(dir, info); } void CRobotMain::SetExitAfterMission(bool exit) @@ -6214,7 +6169,7 @@ void CRobotMain::MarkResearchDone(ResearchType type, int team) if(team == 0) { - WriteFreeParam(); + m_playerProgress->SetFreeGameResearchUnlock(m_playerProgress->GetFreeGameResearchUnlock() | m_researchDone[0]); } } diff --git a/src/object/robotmain.h b/src/object/robotmain.h index 25d03bed..3f33114f 100644 --- a/src/object/robotmain.h +++ b/src/object/robotmain.h @@ -86,6 +86,7 @@ class CInput; class CObjectManager; class CSceneEndCondition; class CAudioChangeCondition; +class CPlayerProgress; namespace Gfx { class CEngine; @@ -121,6 +122,8 @@ const int MAXSHOWLIMIT = 5; const int MAXSHOWPARTI = 200; const float SHOWLIMITTIME = 20.0f; +const int MAXSCENE = 999; + struct ShowLimit { bool used; @@ -227,16 +230,16 @@ public: void SetFontSize(float size); float GetFontSize(); void SetWindowPos(Math::Point pos); - Math::Point GetWindowPos(); + Math::Point GetWindowPos(); void SetWindowDim(Math::Point dim); - Math::Point GetWindowDim(); + Math::Point GetWindowDim(); void SetIOPublic(bool mode); bool GetIOPublic(); void SetIOPos(Math::Point pos); - Math::Point GetIOPos(); + Math::Point GetIOPos(); void SetIODim(Math::Point dim); - Math::Point GetIODim(); + Math::Point GetIODim(); char* GetTitle(); char* GetResume(); @@ -258,16 +261,16 @@ public: const char* GetFilesDir(); MissionType GetMissionType(); - void SetGamerName(const char *name); - char* GetGamerName(); int GetGamerFace(); int GetGamerGlasses(); bool GetGamerOnlyHead(); float GetPersoAngle(); - + LevelCategory GetLevelCategory(); int GetLevelChap(); int GetLevelRank(); + void UpdateChapterPassed(); + void MakeSaveScreenshot(const std::string& name); void StartMusic(); void StartPauseMusic(PauseType pause); @@ -299,8 +302,8 @@ public: bool AddNewScriptName(ObjectType type, char *name); char* GetNewScriptName(ObjectType type, int rank); - void WriteFreeParam(); - void ReadFreeParam(); + void SelectPlayer(std::string playerName); + CPlayerProgress* GetPlayerProgress(); bool IsBusy(); bool IOWriteScene(const char *filename, const char *filecbot, char *info); @@ -447,6 +450,9 @@ protected: CPauseManager* m_pause; CInput* m_input; + //! Progress of loaded player + std::unique_ptr m_playerProgress; + //! Time since level start, including pause and intro movie float m_time; @@ -560,8 +566,6 @@ protected: int m_prohibitedTotal; char m_prohibitedToken[100][20]; - std::string m_gamerName; - //! Enabled buildings int m_build; //! Available researches @@ -569,11 +573,6 @@ protected: //! Done researches for each team std::map m_researchDone; - //! Buildings unlocked for free game - int m_freeBuild; - //! Researches unlocked for free game - int m_freeResearch; - Error m_missionResult; ShowLimit m_showLimit[MAXSHOWLIMIT]; diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp index 5b7c65ab..2d7fa0f9 100644 --- a/src/ui/maindialog.cpp +++ b/src/ui/maindialog.cpp @@ -40,6 +40,7 @@ #include "object/level/parser.h" +#include "object/player_progress.h" #include "object/robotmain.h" #include "sound/sound.h" @@ -150,9 +151,6 @@ CMainDialog::CMainDialog() m_category = LevelCategory::Exercises; m_maxList = 0; - memset(&m_perso, 0, sizeof(GamerPerso)); - DefPerso(); - m_bTooltip = true; m_bGlint = true; m_bRain = true; @@ -228,7 +226,6 @@ void CMainDialog::ChangePhase(Phase phase) Math::Point pos, dim, ddim; float ox, oy, sx, sy; std::string name; - char* gamer; int res, i, j; m_camera->SetType(Gfx::CAM_TYPE_DIALOG); @@ -421,14 +418,13 @@ void CMainDialog::ChangePhase(Phase phase) ddim.y = 18.0f/480.0f; pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_NEDIT); pe->SetMaxChar(15); - gamer = m_main->GetGamerName(); - if ( gamer[0] == 0 ) + if(m_main->GetPlayerProgress() != nullptr) { - GetResource(RES_TEXT, RT_NAME_DEFAULT, name); + name = m_main->GetPlayerProgress()->GetName(); } else { - name = gamer; + name = CPlayerProgress::GetLastName(); } pe->SetText(name.c_str()); pe->SetCursor(name.length(), 0); @@ -475,7 +471,6 @@ void CMainDialog::ChangePhase(Phase phase) ReadNameList(); UpdateNameList(); UpdateNameControl(); - UpdateNameFace(); m_engine->SetBackground("interface/interface.png", Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), @@ -700,9 +695,9 @@ void CMainDialog::ChangePhase(Phase phase) pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PDEF); pb->SetState(STATE_SHADOW); - m_persoCopy = m_perso; - m_persoTab = 0; - m_persoAngle = -0.6f; + m_apperanceTab = 0; + m_apperanceAngle = -0.6f; + m_main->GetPlayerProgress()->LoadApperance(); UpdatePerso(); m_main->ScenePerso(); CameraPerso(); @@ -740,17 +735,9 @@ void CMainDialog::ChangePhase(Phase phase) if ( m_phase == PHASE_FREE ) { - LevelCategory temp = m_category; - - m_category = LevelCategory::Missions; - ReadGamerInfo(); - m_accessChap = GetChapPassed(); - - m_category = temp; + m_accessChap = m_main->GetPlayerProgress()->GetChapPassed(LevelCategory::Missions); } - ReadGamerInfo(); - pos.x = 0.10f; pos.y = 0.10f; ddim.x = 0.80f; @@ -795,6 +782,7 @@ void CMainDialog::ChangePhase(Phase phase) ddim.x = dim.x*6.5f; pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_CHAP); pli->SetState(STATE_SHADOW); + m_chap[m_category] = m_main->GetPlayerProgress()->GetSelectedChap(m_category)-1; UpdateSceneChap(m_chap[m_category]); if ( m_phase != PHASE_USER ) pli->SetState(STATE_EXTEND); @@ -817,6 +805,7 @@ void CMainDialog::ChangePhase(Phase phase) ddim.x = dim.x*6.5f; pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_LIST); pli->SetState(STATE_SHADOW); + m_sel[m_category] = m_main->GetPlayerProgress()->GetSelectedRank(m_category)-1; UpdateSceneList(m_chap[m_category], m_sel[m_category]); if ( m_phase != PHASE_USER ) pli->SetState(STATE_EXTEND); pos = pli->GetPos(); @@ -2089,6 +2078,7 @@ bool CMainDialog::EventProcess(const Event &event) if ( m_phase == PHASE_PERSO ) { + PlayerApperance& apperance = m_main->GetPlayerProgress()->GetApperance(); switch( event.type ) { case EVENT_KEY_DOWN: @@ -2103,13 +2093,13 @@ bool CMainDialog::EventProcess(const Event &event) break; case EVENT_INTERFACE_PHEAD: - m_persoTab = 0; + m_apperanceTab = 0; UpdatePerso(); m_main->ScenePerso(); CameraPerso(); break; case EVENT_INTERFACE_PBODY: - m_persoTab = 1; + m_apperanceTab = 1; UpdatePerso(); m_main->ScenePerso(); CameraPerso(); @@ -2119,8 +2109,7 @@ bool CMainDialog::EventProcess(const Event &event) case EVENT_INTERFACE_PFACE2: case EVENT_INTERFACE_PFACE3: case EVENT_INTERFACE_PFACE4: - m_perso.face = event.type-EVENT_INTERFACE_PFACE1; - WriteGamerPerso(m_main->GetGamerName()); + apperance.face = event.type-EVENT_INTERFACE_PFACE1; UpdatePerso(); m_main->ScenePerso(); break; @@ -2135,8 +2124,7 @@ bool CMainDialog::EventProcess(const Event &event) case EVENT_INTERFACE_PGLASS7: case EVENT_INTERFACE_PGLASS8: case EVENT_INTERFACE_PGLASS9: - m_perso.glasses = event.type-EVENT_INTERFACE_PGLASS0; - WriteGamerPerso(m_main->GetGamerName()); + apperance.glasses = event.type-EVENT_INTERFACE_PGLASS0; UpdatePerso(); m_main->ScenePerso(); break; @@ -2152,7 +2140,6 @@ bool CMainDialog::EventProcess(const Event &event) case EVENT_INTERFACE_PC8a: case EVENT_INTERFACE_PC9a: FixPerso(event.type-EVENT_INTERFACE_PC0a, 0); - WriteGamerPerso(m_main->GetGamerName()); UpdatePerso(); m_main->ScenePerso(); break; @@ -2168,7 +2155,6 @@ bool CMainDialog::EventProcess(const Event &event) case EVENT_INTERFACE_PC8b: case EVENT_INTERFACE_PC9b: FixPerso(event.type-EVENT_INTERFACE_PC0b, 1); - WriteGamerPerso(m_main->GetGamerName()); UpdatePerso(); m_main->ScenePerso(); break; @@ -2180,32 +2166,30 @@ bool CMainDialog::EventProcess(const Event &event) case EVENT_INTERFACE_PCGb: case EVENT_INTERFACE_PCBb: ColorPerso(); - WriteGamerPerso(m_main->GetGamerName()); UpdatePerso(); m_main->ScenePerso(); break; case EVENT_INTERFACE_PDEF: - DefPerso(); - WriteGamerPerso(m_main->GetGamerName()); + apperance.DefPerso(); UpdatePerso(); m_main->ScenePerso(); break; case EVENT_INTERFACE_PLROT: - m_persoAngle += 0.2f; + m_apperanceAngle += 0.2f; break; case EVENT_INTERFACE_PRROT: - m_persoAngle -= 0.2f; + m_apperanceAngle -= 0.2f; break; case EVENT_INTERFACE_POK: + m_main->GetPlayerProgress()->SaveApperance(); m_main->ChangePhase(PHASE_INIT); break; case EVENT_INTERFACE_PCANCEL: - m_perso = m_persoCopy; - WriteGamerPerso(m_main->GetGamerName()); + m_main->GetPlayerProgress()->LoadApperance(); // reload apperance from file m_main->ChangePhase(PHASE_NAME); break; @@ -2245,6 +2229,7 @@ bool CMainDialog::EventProcess(const Event &event) pl = static_cast(pw->SearchControl(EVENT_INTERFACE_CHAP)); if ( pl == 0 ) break; m_chap[m_category] = pl->GetSelect(); + m_main->GetPlayerProgress()->SetSelectedChap(m_category, m_chap[m_category]+1); UpdateSceneList(m_chap[m_category], m_sel[m_category]); UpdateSceneResume(m_chap[m_category]+1, m_sel[m_category]+1); break; @@ -2253,6 +2238,7 @@ bool CMainDialog::EventProcess(const Event &event) pl = static_cast(pw->SearchControl(EVENT_INTERFACE_LIST)); if ( pl == 0 ) break; m_sel[m_category] = pl->GetSelect(); + m_main->GetPlayerProgress()->SetSelectedRank(m_category, m_sel[m_category]+1); UpdateSceneResume(m_chap[m_category]+1, m_sel[m_category]+1); break; @@ -3394,7 +3380,6 @@ void CMainDialog::UpdateNameControl() CButton* pb; CEdit* pe; char name[100]; - char* gamer; int total, sel; pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); @@ -3404,7 +3389,7 @@ void CMainDialog::UpdateNameControl() pe = static_cast(pw->SearchControl(EVENT_INTERFACE_NEDIT)); if ( pe == 0 ) return; - gamer = m_main->GetGamerName(); + std::string gamer = m_main->GetPlayerProgress()->GetName(); total = pl->GetTotal(); sel = pl->GetSelect(); pe->GetText(name, 100); @@ -3412,7 +3397,7 @@ void CMainDialog::UpdateNameControl() pb = static_cast(pw->SearchControl(EVENT_INTERFACE_NCANCEL)); if ( pb != 0 ) { - pb->SetState(STATE_ENABLE, gamer[0]!=0); + pb->SetState(STATE_ENABLE, !gamer.empty()); } pb = static_cast(pw->SearchControl(EVENT_INTERFACE_NDELETE)); @@ -3501,27 +3486,6 @@ void CMainDialog::UpdateNameEdit() UpdateNameControl(); } -// Updates the representation of the player depending on the selected list. - -void CMainDialog::UpdateNameFace() -{ - CWindow* pw; - CList* pl; - char* name; - int sel; - - pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); - if ( pw == 0 ) return; - pl = static_cast(pw->SearchControl(EVENT_INTERFACE_NLIST)); - if ( pl == 0 ) return; - - sel = pl->GetSelect(); - if ( sel == -1 ) return; - name = pl->GetItemName(sel); - - ReadGamerPerso(name); -} - // Selects a player. void CMainDialog::NameSelect() @@ -3548,18 +3512,15 @@ void CMainDialog::NameSelect() } else { - m_main->SetGamerName(pl->GetItemName(sel)); - m_main->ChangePhase(PHASE_INIT); + m_main->SelectPlayer(pl->GetItemName(sel)); } - GetGamerFace(m_main->GetGamerName()); - - GetProfile().SetStringProperty("Gamer", "LastName", m_main->GetGamerName()); + m_main->ChangePhase(PHASE_INIT); } // Creates a new player. -void CMainDialog::NameCreate() +bool CMainDialog::NameCreate() { CWindow* pw; CEdit* pe; @@ -3569,15 +3530,15 @@ void CMainDialog::NameCreate() GetLogger()->Info("Creating new player\n"); pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); - if ( pw == 0 ) return; + if ( pw == 0 ) return false; pe = static_cast(pw->SearchControl(EVENT_INTERFACE_NEDIT)); - if ( pe == 0 ) return; + if ( pe == 0 ) return false; pe->GetText(name, 100); if ( name[0] == 0 ) { m_sound->Play(SOUND_TZOING); - return; + return false; } len = strlen(name); @@ -3601,27 +3562,12 @@ void CMainDialog::NameCreate() if ( j == 0 ) { m_sound->Play(SOUND_TZOING); - return; + return false; } - std::string userSaveDir = m_savegameDir + "/" + name; - if (!CResourceManager::DirectoryExists(userSaveDir)) - { - CResourceManager::CreateDirectory(userSaveDir); - } - else - { - m_sound->Play(SOUND_TZOING); - pe->SetText(name); - pe->SetCursor(strlen(name), 0); - m_interface->SetFocus(pe); - return; - } + m_main->SelectPlayer(name); - SetGamerFace(name, 0); - - m_main->SetGamerName(name); - m_main->ChangePhase(PHASE_INIT); + return true; } // Removes a player. @@ -3642,14 +3588,13 @@ void CMainDialog::NameDelete() char* gamer = pl->GetItemName(sel); - std::string userSaveDir = m_savegameDir + "/" + gamer; - if (!CResourceManager::RemoveDirectory(userSaveDir)) + m_main->SelectPlayer(gamer); + if (!m_main->GetPlayerProgress()->Delete()) { m_sound->Play(SOUND_TZOING); return; } - m_main->SetGamerName(""); pl->SetSelect(-1); ReadNameList(); @@ -3681,24 +3626,26 @@ void CMainDialog::UpdatePerso() std::string name; int i; + PlayerApperance& apperance = m_main->GetPlayerProgress()->GetApperance(); + pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == 0 ) return; pb = static_cast(pw->SearchControl(EVENT_INTERFACE_PHEAD)); if ( pb != 0 ) { - pb->SetState(STATE_CHECK, m_persoTab==0); + pb->SetState(STATE_CHECK, m_apperanceTab==0); } pb = static_cast(pw->SearchControl(EVENT_INTERFACE_PBODY)); if ( pb != 0 ) { - pb->SetState(STATE_CHECK, m_persoTab==1); + pb->SetState(STATE_CHECK, m_apperanceTab==1); } pl = static_cast(pw->SearchControl(EVENT_LABEL11)); if ( pl != 0 ) { - if ( m_persoTab == 0 ) + if ( m_apperanceTab == 0 ) { pl->SetState(STATE_VISIBLE); GetResource(RES_TEXT, RT_PERSO_FACE, name); @@ -3713,7 +3660,7 @@ void CMainDialog::UpdatePerso() pl = static_cast(pw->SearchControl(EVENT_LABEL12)); if ( pl != 0 ) { - if ( m_persoTab == 0 ) + if ( m_apperanceTab == 0 ) { pl->SetState(STATE_VISIBLE); GetResource(RES_TEXT, RT_PERSO_GLASSES, name); @@ -3728,7 +3675,7 @@ void CMainDialog::UpdatePerso() pl = static_cast(pw->SearchControl(EVENT_LABEL13)); if ( pl != 0 ) { - if ( m_persoTab == 0 ) GetResource(RES_TEXT, RT_PERSO_HAIR, name); + if ( m_apperanceTab == 0 ) GetResource(RES_TEXT, RT_PERSO_HAIR, name); else GetResource(RES_TEXT, RT_PERSO_BAND, name); pl->SetName(name); } @@ -3736,7 +3683,7 @@ void CMainDialog::UpdatePerso() pl = static_cast(pw->SearchControl(EVENT_LABEL14)); if ( pl != 0 ) { - if ( m_persoTab == 0 ) + if ( m_apperanceTab == 0 ) { pl->ClearState(STATE_VISIBLE); } @@ -3752,23 +3699,23 @@ void CMainDialog::UpdatePerso() { pb = static_cast(pw->SearchControl(static_cast(EVENT_INTERFACE_PFACE1+i))); if ( pb == 0 ) break; - pb->SetState(STATE_VISIBLE, m_persoTab==0); - pb->SetState(STATE_CHECK, i==m_perso.face); + pb->SetState(STATE_VISIBLE, m_apperanceTab==0); + pb->SetState(STATE_CHECK, i==apperance.face); } for ( i=0 ; i<10 ; i++ ) { pb = static_cast(pw->SearchControl(static_cast(EVENT_INTERFACE_PGLASS0+i))); if ( pb == 0 ) break; - pb->SetState(STATE_VISIBLE, m_persoTab==0); - pb->SetState(STATE_CHECK, i==m_perso.glasses); + pb->SetState(STATE_VISIBLE, m_apperanceTab==0); + pb->SetState(STATE_CHECK, i==apperance.glasses); } for ( i=0 ; i<3*3 ; i++ ) { pc = static_cast(pw->SearchControl(static_cast(EVENT_INTERFACE_PC0a+i))); if ( pc == 0 ) break; - if ( m_persoTab == 0 ) + if ( m_apperanceTab == 0 ) { pc->ClearState(STATE_VISIBLE); } @@ -3780,29 +3727,29 @@ void CMainDialog::UpdatePerso() color.b = perso_color[3*10*1+3*i+2]/255.0f; color.a = 0.0f; pc->SetColor(color); - pc->SetState(STATE_CHECK, EqColor(color, m_perso.colorCombi)); + pc->SetState(STATE_CHECK, EqColor(color, apperance.colorCombi)); } pc = static_cast(pw->SearchControl(static_cast(EVENT_INTERFACE_PC0b+i))); if ( pc == 0 ) break; - color.r = perso_color[3*10*2*m_persoTab+3*i+0]/255.0f; - color.g = perso_color[3*10*2*m_persoTab+3*i+1]/255.0f; - color.b = perso_color[3*10*2*m_persoTab+3*i+2]/255.0f; + color.r = perso_color[3*10*2*m_apperanceTab+3*i+0]/255.0f; + color.g = perso_color[3*10*2*m_apperanceTab+3*i+1]/255.0f; + color.b = perso_color[3*10*2*m_apperanceTab+3*i+2]/255.0f; color.a = 0.0f; pc->SetColor(color); - pc->SetState(STATE_CHECK, EqColor(color, m_persoTab?m_perso.colorBand:m_perso.colorHair)); + pc->SetState(STATE_CHECK, EqColor(color, m_apperanceTab?apperance.colorBand:apperance.colorHair)); } for ( i=0 ; i<3 ; i++ ) { ps = static_cast(pw->SearchControl(static_cast(EVENT_INTERFACE_PCRa+i))); if ( ps == 0 ) break; - ps->SetState(STATE_VISIBLE, m_persoTab==1); + ps->SetState(STATE_VISIBLE, m_apperanceTab==1); } - if ( m_persoTab == 1 ) + if ( m_apperanceTab == 1 ) { - color = m_perso.colorCombi; + color = apperance.colorCombi; ps = static_cast(pw->SearchControl(EVENT_INTERFACE_PCRa)); if ( ps != 0 ) ps->SetVisibleValue(color.r*255.0f); ps = static_cast(pw->SearchControl(EVENT_INTERFACE_PCGa)); @@ -3811,8 +3758,8 @@ void CMainDialog::UpdatePerso() if ( ps != 0 ) ps->SetVisibleValue(color.b*255.0f); } - if ( m_persoTab == 0 ) color = m_perso.colorHair; - else color = m_perso.colorBand; + if ( m_apperanceTab == 0 ) color = apperance.colorHair; + else color = apperance.colorBand; ps = static_cast(pw->SearchControl(EVENT_INTERFACE_PCRb)); if ( ps != 0 ) ps->SetVisibleValue(color.r*255.0f); ps = static_cast(pw->SearchControl(EVENT_INTERFACE_PCGb)); @@ -3825,7 +3772,7 @@ void CMainDialog::UpdatePerso() void CMainDialog::CameraPerso() { - if ( m_persoTab == 0 ) + if ( m_apperanceTab == 0 ) { //? m_camera->Init(Math::Vector(4.0f, 0.0f, 0.0f), //? Math::Vector(0.0f, 0.0f, 1.0f), 0.0f); @@ -3846,28 +3793,29 @@ void CMainDialog::CameraPerso() void CMainDialog::FixPerso(int rank, int index) { - if ( m_persoTab == 0 ) + PlayerApperance& apperance = m_main->GetPlayerProgress()->GetApperance(); + if ( m_apperanceTab == 0 ) { if ( index == 1 ) { - m_perso.colorHair.r = perso_color[3*10*0+rank*3+0]/255.0f; - m_perso.colorHair.g = perso_color[3*10*0+rank*3+1]/255.0f; - m_perso.colorHair.b = perso_color[3*10*0+rank*3+2]/255.0f; + apperance.colorHair.r = perso_color[3*10*0+rank*3+0]/255.0f; + apperance.colorHair.g = perso_color[3*10*0+rank*3+1]/255.0f; + apperance.colorHair.b = perso_color[3*10*0+rank*3+2]/255.0f; } } - if ( m_persoTab == 1 ) + if ( m_apperanceTab == 1 ) { if ( index == 0 ) { - m_perso.colorCombi.r = perso_color[3*10*1+rank*3+0]/255.0f; - m_perso.colorCombi.g = perso_color[3*10*1+rank*3+1]/255.0f; - m_perso.colorCombi.b = perso_color[3*10*1+rank*3+2]/255.0f; + apperance.colorCombi.r = perso_color[3*10*1+rank*3+0]/255.0f; + apperance.colorCombi.g = perso_color[3*10*1+rank*3+1]/255.0f; + apperance.colorCombi.b = perso_color[3*10*1+rank*3+2]/255.0f; } if ( index == 1 ) { - m_perso.colorBand.r = perso_color[3*10*2+rank*3+0]/255.0f; - m_perso.colorBand.g = perso_color[3*10*2+rank*3+1]/255.0f; - m_perso.colorBand.b = perso_color[3*10*2+rank*3+2]/255.0f; + apperance.colorBand.r = perso_color[3*10*2+rank*3+0]/255.0f; + apperance.colorBand.g = perso_color[3*10*2+rank*3+1]/255.0f; + apperance.colorBand.b = perso_color[3*10*2+rank*3+2]/255.0f; } } } @@ -3880,6 +3828,8 @@ void CMainDialog::ColorPerso() CSlider* ps; Gfx::Color color; + PlayerApperance& apperance = m_main->GetPlayerProgress()->GetApperance(); + pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == 0 ) return; @@ -3891,7 +3841,7 @@ void CMainDialog::ColorPerso() if ( ps != 0 ) color.g = ps->GetVisibleValue()/255.0f; ps = static_cast(pw->SearchControl(EVENT_INTERFACE_PCBa)); if ( ps != 0 ) color.b = ps->GetVisibleValue()/255.0f; - if ( m_persoTab == 1 ) m_perso.colorCombi = color; + if ( m_apperanceTab == 1 ) apperance.colorCombi = color; ps = static_cast(pw->SearchControl(EVENT_INTERFACE_PCRb)); if ( ps != 0 ) color.r = ps->GetVisibleValue()/255.0f; @@ -3899,53 +3849,8 @@ void CMainDialog::ColorPerso() if ( ps != 0 ) color.g = ps->GetVisibleValue()/255.0f; ps = static_cast(pw->SearchControl(EVENT_INTERFACE_PCBb)); if ( ps != 0 ) color.b = ps->GetVisibleValue()/255.0f; - if ( m_persoTab == 0 ) m_perso.colorHair = color; - else m_perso.colorBand = color; -} - -// Updates the default settings of the character. - -void CMainDialog::DefPerso() -{ - m_perso.colorCombi.r = 206.0f/256.0f; - m_perso.colorCombi.g = 206.0f/256.0f; - m_perso.colorCombi.b = 204.0f/256.0f; // ~white - m_perso.colorBand.r = 255.0f/256.0f; - m_perso.colorBand.g = 132.0f/256.0f; - m_perso.colorBand.b = 1.0f/256.0f; // orange - - if ( m_perso.face == 0 ) // normal ? - { - m_perso.glasses = 0; - m_perso.colorHair.r = 90.0f/256.0f; - m_perso.colorHair.g = 95.0f/256.0f; - m_perso.colorHair.b = 85.0f/256.0f; // black - } - if ( m_perso.face == 1 ) // bald ? - { - m_perso.glasses = 0; - m_perso.colorHair.r = 83.0f/256.0f; - m_perso.colorHair.g = 64.0f/256.0f; - m_perso.colorHair.b = 51.0f/256.0f; // brown - } - if ( m_perso.face == 2 ) // carlos ? - { - m_perso.glasses = 1; - m_perso.colorHair.r = 85.0f/256.0f; - m_perso.colorHair.g = 48.0f/256.0f; - m_perso.colorHair.b = 9.0f/256.0f; // brown - } - if ( m_perso.face == 3 ) // blond ? - { - m_perso.glasses = 4; - m_perso.colorHair.r = 255.0f/256.0f; - m_perso.colorHair.g = 255.0f/256.0f; - m_perso.colorHair.b = 181.0f/256.0f; // yellow - } - - m_perso.colorHair.a = 0.0f; - m_perso.colorCombi.a = 0.0f; - m_perso.colorBand.a = 0.0f; + if ( m_apperanceTab == 0 ) apperance.colorHair = color; + else apperance.colorBand = color; } @@ -3953,7 +3858,7 @@ void CMainDialog::DefPerso() bool CMainDialog::IsIOReadScene() { - std::string userSaveDir = m_savegameDir + "/" + m_main->GetGamerName(); + std::string userSaveDir = m_savegameDir + "/" + m_main->GetPlayerProgress()->GetName(); auto saveDirs = CResourceManager::ListDirectories(userSaveDir); for (auto dir : saveDirs) { @@ -4017,7 +3922,7 @@ void CMainDialog::IOReadList() m_saveList.clear(); - std::string userSaveDir = m_savegameDir + "/" + m_main->GetGamerName(); + std::string userSaveDir = m_savegameDir + "/" + m_main->GetPlayerProgress()->GetName(); auto saveDirs = CResourceManager::ListDirectories(userSaveDir); //std::sort(saveDirs.begin(), saveDirs.end()); @@ -4182,23 +4087,14 @@ bool CMainDialog::IOWriteScene() pe->GetText(info, 100); if (static_cast(sel) >= m_saveList.size()) { - dir = m_savegameDir + "/" + m_main->GetGamerName() + "/save" + clearName(info); + dir = m_savegameDir + "/" + m_main->GetPlayerProgress()->GetName() + "/save" + clearName(info); } else { dir = m_saveList.at(sel); } - if (!CResourceManager::DirectoryExists(dir)) - { - CResourceManager::CreateDirectory(dir); - } - - std::string savegameFileName = dir + "/data.sav"; - std::string fileCBot = CResourceManager::GetSaveLocation() + "/" + dir + "/cbot.run"; - m_main->IOWriteScene(savegameFileName.c_str(), fileCBot.c_str(), info); - - MakeSaveScreenshot(dir + "/screen.png"); + m_main->GetPlayerProgress()->SaveScene(dir, info); return true; } @@ -4278,23 +4174,6 @@ bool CMainDialog::IOReadScene() return true; } - -// Returns the number of accessible chapters. - -int CMainDialog::GetChapPassed() -{ - if ( m_main->GetShowAll() ) return MAXSCENE; - - for ( int j = 1; j <= MAXSCENE; j++ ) - { - if ( !GetGamerInfoPassed(j, 0) ) - { - return j; - } - } - return MAXSCENE; -} - // Updates the lists according to the cheat code. void CMainDialog::AllMissionUpdate() @@ -4370,7 +4249,7 @@ void CMainDialog::UpdateSceneChap(int &chap) sprintf(line, "%s", (std::string("[ERROR]: ")+e.what()).c_str()); } - bPassed = GetGamerInfoPassed(j+1, 0); + bPassed = m_main->GetPlayerProgress()->GetLevelPassed(m_category, j+1, 0); pl->SetItemName(j, line); pl->SetCheck(j, bPassed); pl->SetEnable(j, true); @@ -4441,7 +4320,7 @@ void CMainDialog::UpdateSceneList(int chap, int &sel) sprintf(line, "%s", (std::string("[ERROR]: ")+e.what()).c_str()); } - bPassed = GetGamerInfoPassed(chap+1, j+1); + bPassed = m_main->GetPlayerProgress()->GetLevelPassed(m_category, chap+1, j+1); pl->SetItemName(j, line); pl->SetCheck(j, bPassed); pl->SetEnable(j, true); @@ -4528,8 +4407,8 @@ void CMainDialog::UpdateSceneResume(int chap, int rank) } else { - numTry = GetGamerInfoTry(chap, rank); - bPassed = GetGamerInfoPassed(chap, rank); + numTry = m_main->GetPlayerProgress()->GetLevelTryCount(m_category, chap, rank); + bPassed = m_main->GetPlayerProgress()->GetLevelPassed(m_category, chap, rank); bVisible = ( numTry > 2 || bPassed || m_main->GetShowSoluce() ); if ( !GetSoluce4() ) bVisible = false; pc->SetState(STATE_VISIBLE, bVisible); @@ -5997,237 +5876,30 @@ bool CMainDialog::GetHimselfDamage() return m_bHimselfDamage; } - - -// Saves the personalized player. - -void CMainDialog::WriteGamerPerso(char *gamer) -{ - try - { - CLevelParser persoParser(GetSavegameDir()+"/"+gamer+"/face.gam"); - CLevelParserLineUPtr line; - - line = MakeUnique("Head"); - line->AddParam("face", MakeUnique(m_perso.face)); - line->AddParam("glasses", MakeUnique(m_perso.glasses)); - line->AddParam("hair", MakeUnique(m_perso.colorHair)); - persoParser.AddLine(std::move(line)); - - line = MakeUnique("Body"); - line->AddParam("combi", MakeUnique(m_perso.colorCombi)); - line->AddParam("band", MakeUnique(m_perso.colorBand)); - persoParser.AddLine(std::move(line)); - - persoParser.Save(); - } - catch (CLevelParserException& e) - { - GetLogger()->Error("Unable to write personalized player apperance: %s\n", e.what()); - } -} - -// Reads the personalized player. - -void CMainDialog::ReadGamerPerso(char *gamer) -{ - m_perso.face = 0; - DefPerso(); - - if (!CResourceManager::Exists(GetSavegameDir()+"/"+gamer+"/face.gam")) - return; - - try - { - CLevelParser persoParser(GetSavegameDir()+"/"+gamer+"/face.gam"); - persoParser.Load(); - CLevelParserLine* line; - - line = persoParser.Get("Head"); - m_perso.face = line->GetParam("face")->AsInt(); - m_perso.glasses = line->GetParam("glasses")->AsInt(); - m_perso.colorHair = line->GetParam("hair")->AsColor(); - - line = persoParser.Get("Body"); - m_perso.colorCombi = line->GetParam("combi")->AsColor(); - m_perso.colorBand = line->GetParam("band")->AsColor(); - } - catch (CLevelParserException& e) - { - GetLogger()->Error("Unable to read personalized player apperance: %s\n", e.what()); - } -} - -// Specifies the face of the player. - -void CMainDialog::SetGamerFace(char *gamer, int face) -{ - m_perso.face = face; - WriteGamerPerso(gamer); -} - -// Gives the face of the player. - -int CMainDialog::GetGamerFace(char *gamer) -{ - ReadGamerPerso(gamer); - return m_perso.face; -} - -// Gives the face of the player. - -int CMainDialog::GetGamerFace() -{ - return m_perso.face; -} - -int CMainDialog::GetGamerGlasses() -{ - return m_perso.glasses; -} - bool CMainDialog::GetGamerOnlyHead() { - return (m_phase == PHASE_PERSO && m_persoTab == 0); + return (m_phase == PHASE_PERSO && m_apperanceTab == 0); } float CMainDialog::GetPersoAngle() { - return m_persoAngle; + return m_apperanceAngle; } -Gfx::Color CMainDialog::GetGamerColorHair() +void CMainDialog::UpdateChapterPassed() { - return m_perso.colorHair; -} - -Gfx::Color CMainDialog::GetGamerColorCombi() -{ - return m_perso.colorCombi; -} - -Gfx::Color CMainDialog::GetGamerColorBand() -{ - return m_perso.colorBand; -} - - -// Reads the file of the player. - -bool CMainDialog::ReadGamerInfo() -{ - std::string line; - - m_sceneInfo.clear(); - - if (!CResourceManager::Exists(GetSavegameDir()+"/"+m_main->GetGamerName()+"/"+GetLevelCategoryDir(m_category)+".gam")) - return false; - - CInputStream file; - file.open(GetSavegameDir()+"/"+m_main->GetGamerName()+"/"+GetLevelCategoryDir(m_category)+".gam"); - if (!file.is_open()) + // TODO: CMainDialog is a bad place for this function + bool bAll = true; + for ( int i=0 ; iError("Unable to read list of finished missions\n"); - return false; - } - - std::getline(file, line); - int chap, rank; - sscanf(line.c_str(), "CurrentChapter=%d CurrentSel=%d\n", &chap, &rank); - m_chap[m_category] = chap-1; - m_sel[m_category] = rank-1; - - while (!file.eof()) - { - std::getline(file, line); - - if (line == "") + if (!m_main->GetPlayerProgress()->GetLevelPassed(m_category, m_chap[m_category]+1, i+1)) { + bAll = false; break; } - - int numTry, passed; - sscanf(line.c_str(), "Chapter %d: Scene %d: numTry=%d passed=%d\n", - &chap, &rank, &numTry, &passed); - - if ( chap < 0 || chap > MAXSCENE ) continue; - if ( rank < 0 || rank > MAXSCENE ) continue; - - m_sceneInfo[chap][rank].numTry = numTry; - m_sceneInfo[chap][rank].bPassed = passed; } - - file.close(); - return true; -} - -// Writes the file of the player. - -bool CMainDialog::WriteGamerInfo() -{ - COutputStream file; - file.open(GetSavegameDir()+"/"+m_main->GetGamerName()+"/"+GetLevelCategoryDir(m_category)+".gam"); - if (!file.is_open()) - { - GetLogger()->Error("Unable to read list of finished missions\n"); - return false; - } - - file << "CurrentChapter=" << m_chap[m_category]+1 << " CurrentSel=" << m_sel[m_category]+1 << "\n"; - - for ( int i=0 ; i MAXSCENE ) return; - if ( rank < 0 || rank > MAXSCENE ) return; - m_sceneInfo[chap][rank].numTry = numTry; -} - -int CMainDialog::GetGamerInfoTry(int chap, int rank) -{ - if ( chap < 0 || chap > MAXSCENE ) return 0; - if ( rank < 0 || rank > MAXSCENE ) return 0; - return m_sceneInfo[chap][rank].numTry; -} - -void CMainDialog::SetGamerInfoPassed(int chap, int rank, bool bPassed) -{ - if ( chap < 0 || chap > MAXSCENE ) return; - if ( rank < 0 || rank > MAXSCENE ) return; - m_sceneInfo[chap][rank].bPassed = bPassed; - - if ( bPassed ) - { - bool bAll = true; - for ( int i=0 ; i MAXSCENE ) return false; - if ( rank < 0 || rank > MAXSCENE ) return false; - return m_sceneInfo[chap][rank].bPassed; + m_main->GetPlayerProgress()->IncrementLevelTryCount(m_category, m_chap[m_category]+1, 0); + m_main->GetPlayerProgress()->SetLevelPassed(m_category, m_chap[m_category]+1, 0, bAll); } @@ -6243,6 +5915,9 @@ bool CMainDialog::NextMission() m_sel[m_category] = 0; // first mission } + m_main->GetPlayerProgress()->SetSelectedChap(m_category, m_chap[m_category]+1); + m_main->GetPlayerProgress()->SetSelectedRank(m_category, m_sel[m_category]+1); + return true; } diff --git a/src/ui/maindialog.h b/src/ui/maindialog.h index e6c095f3..88188243 100644 --- a/src/ui/maindialog.h +++ b/src/ui/maindialog.h @@ -45,26 +45,6 @@ class CWindow; class CControl; -const int USERLISTMAX = 100; -const int MAXSCENE = 999; - - -struct SceneInfo -{ - int numTry; - bool bPassed; -}; - -struct GamerPerso -{ - int face; // face - int glasses; // glasses - Gfx::Color colorHair; // hair color - Gfx::Color colorCombi; // spacesuit volor - Gfx::Color colorBand; // strips color -}; - - class CMainDialog { @@ -117,25 +97,11 @@ public: void SetupMemorize(); void SetupRecall(); - bool ReadGamerInfo(); - bool WriteGamerInfo(); - void SetGamerInfoTry(int chap, int rank, int numTry); - int GetGamerInfoTry(int chap, int rank); - void SetGamerInfoPassed(int chap, int rank, bool bPassed); - bool GetGamerInfoPassed(int chap, int rank); + void UpdateChapterPassed(); bool NextMission(); - void WriteGamerPerso(char *gamer); - void ReadGamerPerso(char *gamer); - void SetGamerFace(char *gamer, int face); - int GetGamerFace(char *gamer); - int GetGamerFace(); - int GetGamerGlasses(); bool GetGamerOnlyHead(); float GetPersoAngle(); - Gfx::Color GetGamerColorHair(); - Gfx::Color GetGamerColorCombi(); - Gfx::Color GetGamerColorBand(); void AllMissionUpdate(); void ShowSoluceUpdate(); @@ -152,15 +118,13 @@ protected: void UpdateNameList(); void UpdateNameEdit(); void UpdateNameControl(); - void UpdateNameFace(); void NameSelect(); - void NameCreate(); + bool NameCreate(); void NameDelete(); void UpdatePerso(); void CameraPerso(); void FixPerso(int rank, int index); void ColorPerso(); - void DefPerso(); bool IsIOReadScene(); void IOReadName(); void IOReadList(); @@ -197,10 +161,8 @@ protected: Phase m_phaseTerm; // phase trainer/scene/proto float m_phaseTime; - GamerPerso m_perso; // perso: description - GamerPerso m_persoCopy; // perso: copy for cancellation - int m_persoTab; // perso: tab selected - float m_persoAngle; // perso: angle of presentation + int m_apperanceTab; // perso: tab selected + float m_apperanceAngle; // perso: angle of presentation std::string m_savegameDir; // savegame folder std::string m_publicDir; // program folder @@ -263,8 +225,6 @@ protected: float m_partiTime[10]; Math::Point m_partiPos[10]; - std::map> m_sceneInfo; - std::vector m_saveList; }; diff --git a/src/ui/studio.cpp b/src/ui/studio.cpp index 13d69a14..78e846ca 100644 --- a/src/ui/studio.cpp +++ b/src/ui/studio.cpp @@ -35,6 +35,7 @@ #include "object/brain.h" #include "object/object.h" +#include "object/player_progress.h" #include "script/cbottoken.h" #include "script/script.h" @@ -1582,7 +1583,7 @@ std::string CStudio::SearchDirectory(bool bCreate) } else { - dir = std::string(m_main->GetSavegameDir()) + "/" + std::string(m_main->GetGamerName()) + "/program/"; + dir = m_main->GetPlayerProgress()->GetSaveFile("program/"); } if ( bCreate ) @@ -1669,4 +1670,3 @@ bool CStudio::WriteProgram() } } -