Add a career mode. The contents of the spaceship are saved on liftoff and restored when loading a level. At the beginning, all levels are unlocked.
parent
4251873f49
commit
0fa486b9f0
|
@ -225,6 +225,7 @@ enum EventType
|
|||
EVENT_INTERFACE_SATCOM = 414,
|
||||
EVENT_INTERFACE_PLUS = 415,
|
||||
EVENT_INTERFACE_MODS = 416,
|
||||
EVENT_INTERFACE_CAREER = 417,
|
||||
|
||||
EVENT_INTERFACE_CHAP = 420,
|
||||
EVENT_INTERFACE_LIST = 421,
|
||||
|
|
|
@ -79,6 +79,7 @@ void InitializeRestext()
|
|||
stringsText[RT_TITLE_READ] = TR("Load a saved mission");
|
||||
stringsText[RT_TITLE_PLUS] = TR("Missions+");
|
||||
stringsText[RT_TITLE_MODS] = TR("Mods");
|
||||
stringsText[RT_TITLE_CAREER] = TR("Select destination");
|
||||
|
||||
stringsText[RT_PLAY_CHAP_CHAPTERS] = TR("Chapters:");
|
||||
stringsText[RT_PLAY_CHAP_PLANETS] = TR("Planets:");
|
||||
|
@ -190,6 +191,7 @@ void InitializeRestext()
|
|||
stringsEvent[EVENT_INTERFACE_FREE] = TR("Free game\\Free game without a specific goal");
|
||||
stringsEvent[EVENT_INTERFACE_CODE_BATTLES] = TR("Code battles\\Program your robot to be the best of them all!");
|
||||
stringsEvent[EVENT_INTERFACE_USER] = TR("Custom levels\\Levels from mods created by the users");
|
||||
stringsEvent[EVENT_INTERFACE_CAREER] = TR("Career mode");
|
||||
stringsEvent[EVENT_INTERFACE_SATCOM] = TR("SatCom");
|
||||
stringsEvent[EVENT_INTERFACE_MODS] = TR("Mods\\Mod manager");
|
||||
stringsEvent[EVENT_INTERFACE_NAME] = TR("Change player\\Change player");
|
||||
|
|
|
@ -73,6 +73,7 @@ enum ResTextType
|
|||
RT_TITLE_USER = 52,
|
||||
RT_TITLE_PLUS = 53,
|
||||
RT_TITLE_MODS = 54,
|
||||
RT_TITLE_CAREER = 55,
|
||||
|
||||
RT_PLAY_CHAP_CHAPTERS = 60,
|
||||
RT_PLAY_CHAP_PLANETS = 61,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <map>
|
||||
|
||||
// NOTE: Because of how save filenames are built, the first letter of category directories MUST be unique!!
|
||||
// Except career because it is a special case.
|
||||
// TODO: I'm not sure about "challenges" + "custom". It may be messing things up already right now.
|
||||
const std::map<LevelCategory, std::string> CATEGORY_DIR_MAP = {
|
||||
{ LevelCategory::Missions, "missions" },
|
||||
|
@ -31,6 +32,7 @@ const std::map<LevelCategory, std::string> CATEGORY_DIR_MAP = {
|
|||
{ LevelCategory::CodeBattles, "battles" },
|
||||
{ LevelCategory::GamePlus, "plus" },
|
||||
{ LevelCategory::CustomLevels, "custom" },
|
||||
{ LevelCategory::CareerMode, "career" },
|
||||
};
|
||||
|
||||
std::string GetLevelCategoryDir(LevelCategory category)
|
||||
|
|
|
@ -30,6 +30,7 @@ enum class LevelCategory
|
|||
CodeBattles,
|
||||
GamePlus,
|
||||
CustomLevels,
|
||||
CareerMode,
|
||||
Max,
|
||||
};
|
||||
|
||||
|
|
|
@ -3768,6 +3768,29 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
throw CLevelParserException("Unknown command: '" + line->GetCommand() + "' in " + line->GetLevelFilename() + ":" + StrUtils::ToString(line->GetLineNumber()));
|
||||
}
|
||||
|
||||
// Load the spaceship contents
|
||||
if (m_levelCategory == LevelCategory::CareerMode) {
|
||||
CObject* base = m_objMan->FindNearest(nullptr, OBJECT_BASE, 10000000.0f);
|
||||
if(base) {
|
||||
std::string saveDir = GetPlayerProfile()->GetSaveFile("__spaceship__"); // TODO: change save path?
|
||||
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
if (obj == base) continue;
|
||||
if (IsObjectBeingTransported(obj)) continue;
|
||||
|
||||
glm::vec3 oPos = obj->GetPosition();
|
||||
float dist = Math::DistanceProjected(base->GetPosition(), oPos);
|
||||
if ( dist < 32.0f )
|
||||
{
|
||||
m_objMan->DeleteObject(obj);
|
||||
}
|
||||
}
|
||||
|
||||
IOReadScene(saveDir+"/data.sav", saveDir+"/cbot.run", true, base->GetPosition());
|
||||
}
|
||||
}
|
||||
|
||||
// Do this here to prevent the first frame from taking a long time to render
|
||||
m_engine->UpdateGroundSpotTextures();
|
||||
|
||||
|
@ -4521,7 +4544,7 @@ void CRobotMain::SaveOneScript(CObject *obj)
|
|||
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
|
||||
char categoryChar = GetLevelCategoryDir(m_levelCategory)[0];
|
||||
char categoryChar = (m_levelCategory == LevelCategory::CareerMode ? 'X' : GetLevelCategoryDir(m_levelCategory)[0]);
|
||||
programStorage->SaveAllUserPrograms(m_playerProfile->GetSaveFile(StrUtils::Format("%c%.3d%.3d", categoryChar, m_levelChap, m_levelRank)));
|
||||
}
|
||||
|
||||
|
@ -4617,7 +4640,7 @@ bool CRobotMain::IOIsBusy()
|
|||
}
|
||||
|
||||
//! Writes an object into the backup file
|
||||
void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj, const std::string& programDir, int objRank)
|
||||
void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj, const std::string& programDir, int objRank, bool directProgramStorageIndex)
|
||||
{
|
||||
line->AddParam("type", std::make_unique<CLevelParserParam>(obj->GetType()));
|
||||
line->AddParam("id", std::make_unique<CLevelParserParam>(obj->GetID()));
|
||||
|
@ -4647,17 +4670,32 @@ void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj, const std::
|
|||
if (obj->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
if (programStorage->GetProgramStorageIndex() >= 0)
|
||||
|
||||
// directProgramStorageIndex=false: format for mission save files - pre-existing level objects have a unique index shared between levels, and non-pre-existing objects have 999-objIndex (maximum 999 and the last few may conflict with pre-existing objects)
|
||||
// directProgramStorageIndex=true: format for career save files, program storage index is just the object rank, and we save it to allow future versions to change the index allocation.
|
||||
|
||||
if (directProgramStorageIndex)
|
||||
{
|
||||
int oldIndex = programStorage->GetProgramStorageIndex();
|
||||
programStorage->SetProgramStorageIndex(objRank);
|
||||
programStorage->SaveAllProgramsForSavedScene(line, programDir);
|
||||
programStorage->SetProgramStorageIndex(oldIndex);
|
||||
line->AddParam("programStorageIndex", std::make_unique<CLevelParserParam>(objRank));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Probably an object created after the scene started, not loaded from level file
|
||||
// This means it doesn't normally store programs so it doesn't have program storage id assigned
|
||||
programStorage->SetProgramStorageIndex(999-objRank); // Set something that won't collide with normal programs
|
||||
programStorage->SaveAllProgramsForSavedScene(line, programDir);
|
||||
programStorage->SetProgramStorageIndex(-1); // Disable again
|
||||
if (programStorage->GetProgramStorageIndex() >= 0)
|
||||
{
|
||||
programStorage->SaveAllProgramsForSavedScene(line, programDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Probably an object created after the scene started, not loaded from level file
|
||||
// This means it doesn't normally store programs so it doesn't have program storage id assigned
|
||||
programStorage->SetProgramStorageIndex(999-objRank); // Set something that won't collide with normal programs
|
||||
programStorage->SaveAllProgramsForSavedScene(line, programDir);
|
||||
programStorage->SetProgramStorageIndex(-1); // Disable again
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable))
|
||||
|
@ -4671,6 +4709,39 @@ void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj, const std::
|
|||
}
|
||||
}
|
||||
|
||||
void CRobotMain::IOWriteObjectTree(CLevelParser& levelParser, CObject* obj, std::string const& dirname, int& objRank, bool directProgramStorageIndex)
|
||||
{
|
||||
if (obj->GetType() == OBJECT_TOTO) return;
|
||||
if (IsObjectBeingTransported(obj)) return;
|
||||
if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast<CDestroyableObject&>(*obj).IsDying()) return;
|
||||
|
||||
CLevelParserLineUPtr line;
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Slotted))
|
||||
{
|
||||
CSlottedObject* slotted = dynamic_cast<CSlottedObject*>(obj);
|
||||
for (int slot = slotted->GetNumSlots() - 1; slot >= 0; slot--)
|
||||
{
|
||||
if (CObject *sub = slotted->GetSlotContainedObject(slot))
|
||||
{
|
||||
if (slot == slotted->MapPseudoSlot(CSlottedObject::Pseudoslot::POWER))
|
||||
line = std::make_unique<CLevelParserLine>("CreatePower");
|
||||
else if (slot == slotted->MapPseudoSlot(CSlottedObject::Pseudoslot::CARRYING))
|
||||
line = std::make_unique<CLevelParserLine>("CreateFret");
|
||||
else
|
||||
line = std::make_unique<CLevelParserLine>("CreateSlotObject");
|
||||
line->AddParam("slotNum", std::make_unique<CLevelParserParam>(slot));
|
||||
IOWriteObject(line.get(), sub, dirname, objRank++, directProgramStorageIndex);
|
||||
levelParser.AddLine(std::move(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line = std::make_unique<CLevelParserLine>("CreateObject");
|
||||
IOWriteObject(line.get(), obj, dirname, objRank++, directProgramStorageIndex);
|
||||
levelParser.AddLine(std::move(line));
|
||||
}
|
||||
|
||||
//! Saves the current game
|
||||
bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::string filescreenshot, const std::string& info, bool emergencySave)
|
||||
{
|
||||
|
@ -4735,33 +4806,7 @@ bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::s
|
|||
int objRank = 0;
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
if (obj->GetType() == OBJECT_TOTO) continue;
|
||||
if (IsObjectBeingTransported(obj)) continue;
|
||||
if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast<CDestroyableObject&>(*obj).IsDying()) continue;
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Slotted))
|
||||
{
|
||||
CSlottedObject* slotted = dynamic_cast<CSlottedObject*>(obj);
|
||||
for (int slot = slotted->GetNumSlots() - 1; slot >= 0; slot--)
|
||||
{
|
||||
if (CObject *sub = slotted->GetSlotContainedObject(slot))
|
||||
{
|
||||
if (slot == slotted->MapPseudoSlot(CSlottedObject::Pseudoslot::POWER))
|
||||
line = std::make_unique<CLevelParserLine>("CreatePower");
|
||||
else if (slot == slotted->MapPseudoSlot(CSlottedObject::Pseudoslot::CARRYING))
|
||||
line = std::make_unique<CLevelParserLine>("CreateFret");
|
||||
else
|
||||
line = std::make_unique<CLevelParserLine>("CreateSlotObject");
|
||||
line->AddParam("slotNum", std::make_unique<CLevelParserParam>(slot));
|
||||
IOWriteObject(line.get(), sub, dirname, objRank++);
|
||||
levelParser.AddLine(std::move(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line = std::make_unique<CLevelParserLine>("CreateObject");
|
||||
IOWriteObject(line.get(), obj, dirname, objRank++);
|
||||
levelParser.AddLine(std::move(line));
|
||||
IOWriteObjectTree(levelParser, obj, dirname, objRank, false);
|
||||
}
|
||||
try
|
||||
{
|
||||
|
@ -4834,12 +4879,18 @@ void CRobotMain::IOWriteSceneFinished()
|
|||
}
|
||||
|
||||
//! Resumes the game
|
||||
CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const std::string& programDir, const std::string& objCounterText, float objectProgress, int objRank)
|
||||
CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const std::string& programDir, const std::string& objCounterText, float objectProgress, int objRank, glm::vec3 offsetPosition, bool isSpaceshipSave)
|
||||
{
|
||||
ObjectCreateParams params = CObject::ReadCreateParams(line);
|
||||
params.power = -1.0f;
|
||||
params.id = line->GetParam("id")->AsInt();
|
||||
|
||||
if(isSpaceshipSave)
|
||||
{
|
||||
// Ignore object ID in save file. It will conflict with existing objects in the world. Does it matter that the IDs change?
|
||||
params.id = -1;
|
||||
}
|
||||
|
||||
std::string details = objCounterText;
|
||||
|
||||
// Object categories may spoil the level a bit, so hide them in release builds
|
||||
|
@ -4855,7 +4906,7 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const std::string& pro
|
|||
if (obj->Implements(ObjectInterfaceType::Old))
|
||||
{
|
||||
COldObject* oldObj = dynamic_cast<COldObject*>(obj);
|
||||
oldObj->SetPosition(line->GetParam("pos")->AsPoint() * g_unit);
|
||||
oldObj->SetPosition(line->GetParam("pos")->AsPoint() * g_unit + offsetPosition);
|
||||
oldObj->SetRotation(line->GetParam("angle")->AsPoint() * Math::DEG_TO_RAD);
|
||||
}
|
||||
|
||||
|
@ -4874,7 +4925,7 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const std::string& pro
|
|||
if (obj->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
if (!line->GetParam("programStorageIndex")->IsDefined()) // Backwards compatibility
|
||||
if (!line->GetParam("programStorageIndex")->IsDefined()) // Backwards compatibility, also used for spaceship saves
|
||||
programStorage->SetProgramStorageIndex(objRank);
|
||||
programStorage->LoadAllProgramsForSavedScene(line, programDir);
|
||||
}
|
||||
|
@ -4883,7 +4934,7 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const std::string& pro
|
|||
}
|
||||
|
||||
//! Resumes some part of the game
|
||||
CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot)
|
||||
CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot, bool isSpaceshipSave, glm::vec3 offsetPosition)
|
||||
{
|
||||
std::string dirname = filename.substr(0, filename.find_last_of("/"));
|
||||
|
||||
|
@ -4902,40 +4953,43 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot)
|
|||
std::map<int, CObject*> slots;
|
||||
for (auto& line : levelParser.GetLines())
|
||||
{
|
||||
if (line->GetCommand() == "Mission")
|
||||
m_gameTime = line->GetParam("gametime")->AsFloat(0.0f);
|
||||
|
||||
if (line->GetCommand() == "Map")
|
||||
m_map->ZoomMap(line->GetParam("zoom")->AsFloat());
|
||||
|
||||
if (line->GetCommand() == "DoneResearch")
|
||||
m_researchDone[0] = line->GetParam("bits")->AsInt();
|
||||
|
||||
if (line->GetCommand() == "BlitzMode")
|
||||
if (!isSpaceshipSave)
|
||||
{
|
||||
float sleep = line->GetParam("sleep")->AsFloat();
|
||||
float delay = line->GetParam("delay")->AsFloat();
|
||||
float magnetic = line->GetParam("magnetic")->AsFloat()*g_unit;
|
||||
float progress = line->GetParam("progress")->AsFloat();
|
||||
m_lightning->SetStatus(sleep, delay, magnetic, progress);
|
||||
if (line->GetCommand() == "Mission")
|
||||
m_gameTime = line->GetParam("gametime")->AsFloat(0.0f);
|
||||
|
||||
if (line->GetCommand() == "Map")
|
||||
m_map->ZoomMap(line->GetParam("zoom")->AsFloat());
|
||||
|
||||
if (line->GetCommand() == "DoneResearch")
|
||||
m_researchDone[0] = line->GetParam("bits")->AsInt();
|
||||
|
||||
if (line->GetCommand() == "BlitzMode")
|
||||
{
|
||||
float sleep = line->GetParam("sleep")->AsFloat();
|
||||
float delay = line->GetParam("delay")->AsFloat();
|
||||
float magnetic = line->GetParam("magnetic")->AsFloat()*g_unit;
|
||||
float progress = line->GetParam("progress")->AsFloat();
|
||||
m_lightning->SetStatus(sleep, delay, magnetic, progress);
|
||||
}
|
||||
}
|
||||
|
||||
if (line->GetCommand() == "CreateFret")
|
||||
{
|
||||
cargo = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects));
|
||||
cargo = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects), -1, glm::vec3(0,0,0), isSpaceshipSave);
|
||||
objCounter++;
|
||||
}
|
||||
|
||||
if (line->GetCommand() == "CreatePower")
|
||||
{
|
||||
power = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects));
|
||||
power = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects), -1, glm::vec3(0,0,0), isSpaceshipSave);
|
||||
objCounter++;
|
||||
}
|
||||
|
||||
if (line->GetCommand() == "CreateSlotObject")
|
||||
{
|
||||
int slotNum = line->GetParam("slotNum")->AsInt();
|
||||
CObject *slotObject = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects));
|
||||
CObject *slotObject = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects), -1, offsetPosition, isSpaceshipSave);
|
||||
objCounter++;
|
||||
|
||||
assert(slots.find(slotNum) == slots.end());
|
||||
|
@ -4944,7 +4998,7 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot)
|
|||
|
||||
if (line->GetCommand() == "CreateObject")
|
||||
{
|
||||
CObject* obj = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects), objRank++);
|
||||
CObject* obj = IOReadObject(line.get(), dirname, StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects), static_cast<float>(objCounter) / static_cast<float>(numObjects), objRank++, offsetPosition, isSpaceshipSave);
|
||||
|
||||
if (line->GetParam("select")->AsBool(false))
|
||||
sel = obj;
|
||||
|
|
|
@ -87,6 +87,7 @@ bool IsMainMenuPhase(Phase phase);
|
|||
class CApplication;
|
||||
class CEventQueue;
|
||||
class CSoundInterface;
|
||||
class CLevelParser;
|
||||
class CLevelParserLine;
|
||||
class CInput;
|
||||
class CObjectManager;
|
||||
|
@ -336,9 +337,10 @@ public:
|
|||
bool IOIsBusy();
|
||||
bool IOWriteScene(std::string filename, std::string filecbot, std::string filescreenshot, const std::string& info, bool emergencySave = false);
|
||||
void IOWriteSceneFinished();
|
||||
CObject* IOReadScene(std::string filename, std::string filecbot);
|
||||
void IOWriteObject(CLevelParserLine *line, CObject* obj, const std::string& programDir, int objRank);
|
||||
CObject* IOReadObject(CLevelParserLine *line, const std::string& programDir, const std::string& objCounterText, float objectProgress, int objRank = -1);
|
||||
CObject* IOReadScene(std::string filename, std::string filecbot, bool isSpaceshipSave = false, glm::vec3 offsetPosition = glm::vec3(0,0,0));
|
||||
void IOWriteObject(CLevelParserLine *line, CObject* obj, const std::string& programDir, int objRank, bool directProgramStorageIndex);
|
||||
void IOWriteObjectTree(CLevelParser& levelParser, CObject* obj, std::string const& dirname, int& objRank, bool directProgramStorageIndex);
|
||||
CObject* IOReadObject(CLevelParserLine *line, const std::string& programDir, const std::string& objCounterText, float objectProgress, int objRank = -1, glm::vec3 offsetPosition = glm::vec3(0,0,0), bool isSpaceshipSave = false);
|
||||
//@}
|
||||
|
||||
int CreateSpot(glm::vec3 pos, Gfx::Color color);
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "object/auto/autobase.h"
|
||||
|
||||
#include "common/resources/resourcemanager.h"
|
||||
|
||||
#include "graphics/engine/cloud.h"
|
||||
#include "graphics/engine/engine.h"
|
||||
#include "graphics/engine/lightning.h"
|
||||
|
@ -27,6 +29,10 @@
|
|||
#include "graphics/engine/terrain.h"
|
||||
|
||||
#include "level/robotmain.h"
|
||||
#include "level/player_profile.h"
|
||||
|
||||
#include "level/parser/parser.h"
|
||||
#include "level/parser/parserline.h"
|
||||
|
||||
#include "math/geometry.h"
|
||||
|
||||
|
@ -1369,15 +1375,56 @@ Error CAutoBase::TakeOff(bool printMsg)
|
|||
return err;
|
||||
}
|
||||
|
||||
err = m_main->CheckEndMission(false);
|
||||
if (err != ERR_OK)
|
||||
// taking off in career mode doesn't have to complete the mission
|
||||
if (m_main->GetLevelCategory() != LevelCategory::CareerMode)
|
||||
{
|
||||
if (printMsg)
|
||||
m_main->DisplayError(err, m_object);
|
||||
return err;
|
||||
err = m_main->CheckEndMission(false);
|
||||
if (err != ERR_OK)
|
||||
{
|
||||
if (printMsg)
|
||||
m_main->DisplayError(err, m_object);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
FreezeCargo(true); // freeze whole cargo
|
||||
|
||||
if (m_main->GetLevelCategory() == LevelCategory::CareerMode)
|
||||
{
|
||||
// Note: we don't write a cbot.run file - running programs won't remain running when transferred to other worlds.
|
||||
// We still need a directory per save file, because programs are saved there.
|
||||
std::string saveDir = m_main->GetPlayerProfile()->GetSaveFile("__spaceship__"); // TODO: change save path?
|
||||
if (CResourceManager::DirectoryExists(saveDir))
|
||||
CResourceManager::RemoveExistingDirectory(saveDir);
|
||||
CResourceManager::CreateNewDirectory(saveDir);
|
||||
|
||||
CLevelParser levelFile(saveDir+"/data.sav");
|
||||
{
|
||||
CLevelParserLineUPtr line = std::make_unique<CLevelParserLine>("SpaceShipSave");
|
||||
line->AddParam("version", std::make_unique<CLevelParserParam>(1));
|
||||
levelFile.AddLine(std::move(line));
|
||||
}
|
||||
int objRank = 0;
|
||||
for(CObject* obj : m_cargoObjects)
|
||||
{
|
||||
glm::vec3 pos = obj->GetPosition();
|
||||
obj->SetPosition(pos - m_object->GetPosition());
|
||||
m_main->IOWriteObjectTree(levelFile, obj, saveDir, objRank, true);
|
||||
obj->SetPosition(pos);
|
||||
}
|
||||
try
|
||||
{
|
||||
levelFile.Save();
|
||||
}
|
||||
catch (CLevelParserException& e)
|
||||
{
|
||||
GetLogger()->Error("Failed to save level state - %s\n", e.what()); // TODO add visual error to notify user that save failed
|
||||
// return to normal gameplay - not tested at all, probably broken
|
||||
FreezeCargo(false);
|
||||
return ERR_UNKNOWN; // TODO: proper error code
|
||||
}
|
||||
}
|
||||
|
||||
m_main->SetMovieLock(true); // blocks everything until the end
|
||||
m_main->DeselectAll();
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ public:
|
|||
float angle = 0.0f,
|
||||
float focus = Math::PI*2.0f,
|
||||
float minDist = 0.0f,
|
||||
float maxDist = 1000.0f,
|
||||
float maxDist = 10000000.0f,
|
||||
bool furthest = false,
|
||||
RadarFilter filter = FILTER_NONE,
|
||||
bool cbotTypes = false);
|
||||
|
@ -222,7 +222,7 @@ public:
|
|||
float angle = 0.0f,
|
||||
float focus = Math::PI*2.0f,
|
||||
float minDist = 0.0f,
|
||||
float maxDist = 1000.0f,
|
||||
float maxDist = 10000000.0f,
|
||||
bool furthest = false,
|
||||
RadarFilter filter = FILTER_NONE,
|
||||
bool cbotTypes = false);
|
||||
|
@ -233,7 +233,7 @@ public:
|
|||
float angle = 0.0f,
|
||||
float focus = Math::PI*2.0f,
|
||||
float minDist = 0.0f,
|
||||
float maxDist = 1000.0f,
|
||||
float maxDist = 10000000.0f,
|
||||
bool furthest = false,
|
||||
RadarFilter filter = FILTER_NONE,
|
||||
bool cbotTypes = false);
|
||||
|
@ -245,7 +245,7 @@ public:
|
|||
float angle = 0.0f,
|
||||
float focus = Math::PI*2.0f,
|
||||
float minDist = 0.0f,
|
||||
float maxDist = 1000.0f,
|
||||
float maxDist = 10000000.0f,
|
||||
bool furthest = false,
|
||||
RadarFilter filter = FILTER_NONE,
|
||||
bool cbotTypes = false);
|
||||
|
|
|
@ -91,6 +91,7 @@ void CScreenLevelList::CreateInterface()
|
|||
if ( m_category == LevelCategory::CodeBattles ) res = RT_TITLE_CODE_BATTLES;
|
||||
if ( m_category == LevelCategory::GamePlus ) res = RT_TITLE_PLUS;
|
||||
if ( m_category == LevelCategory::CustomLevels ) res = RT_TITLE_USER;
|
||||
if ( m_category == LevelCategory::CareerMode ) res = RT_TITLE_CAREER;
|
||||
GetResource(RES_TEXT, res, name);
|
||||
pw->SetName(name);
|
||||
|
||||
|
@ -114,6 +115,7 @@ void CScreenLevelList::CreateInterface()
|
|||
if ( m_category == LevelCategory::Missions ) res = RT_PLAY_CHAP_PLANETS;
|
||||
if ( m_category == LevelCategory::FreeGame ) res = RT_PLAY_CHAP_PLANETS;
|
||||
if ( m_category == LevelCategory::GamePlus ) res = RT_PLAY_CHAP_PLANETS;
|
||||
if ( m_category == LevelCategory::CareerMode ) res = RT_PLAY_CHAP_PLANETS;
|
||||
if ( m_category == LevelCategory::CustomLevels ) res = RT_PLAY_CHAP_USERLVL;
|
||||
GetResource(RES_TEXT, res, name);
|
||||
pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name);
|
||||
|
@ -128,7 +130,8 @@ void CScreenLevelList::CreateInterface()
|
|||
UpdateSceneChap(m_chap[m_category]);
|
||||
if ( m_category != LevelCategory::FreeGame &&
|
||||
m_category != LevelCategory::CodeBattles &&
|
||||
m_category != LevelCategory::CustomLevels ) // Don't show completion marks in free game, code battles and userlevels
|
||||
m_category != LevelCategory::CustomLevels &&
|
||||
m_category != LevelCategory::CareerMode ) // Don't show completion marks in free game, code battles and userlevels
|
||||
{
|
||||
pli->SetState(STATE_EXTEND);
|
||||
}
|
||||
|
@ -144,6 +147,7 @@ void CScreenLevelList::CreateInterface()
|
|||
if ( m_category == LevelCategory::Missions ) res = RT_PLAY_LIST_MISSIONS;
|
||||
if ( m_category == LevelCategory::FreeGame ) res = RT_PLAY_LIST_FREEGAME;
|
||||
if ( m_category == LevelCategory::GamePlus ) res = RT_PLAY_LIST_MISSIONS;
|
||||
if ( m_category == LevelCategory::CareerMode ) res = RT_PLAY_LIST_MISSIONS;
|
||||
GetResource(RES_TEXT, res, name);
|
||||
pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name);
|
||||
pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT);
|
||||
|
@ -186,7 +190,8 @@ void CScreenLevelList::CreateInterface()
|
|||
// Button displays the "soluce":
|
||||
if ( m_category != LevelCategory::Exercises &&
|
||||
m_category != LevelCategory::GamePlus &&
|
||||
m_category != LevelCategory::FreeGame )
|
||||
m_category != LevelCategory::FreeGame &&
|
||||
m_category != LevelCategory::CareerMode )
|
||||
{
|
||||
pos.x = ox+sx*9.5f;
|
||||
pos.y = oy+sy*5.8f;
|
||||
|
|
|
@ -123,7 +123,7 @@ void CScreenMainMenu::CreateInterface()
|
|||
pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_CODE_BATTLES);
|
||||
pb->SetState(STATE_SHADOW);
|
||||
|
||||
pos.y = oy+sy*5.8f;
|
||||
pos.y = oy+sy*5.9f;
|
||||
pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_USER);
|
||||
pb->SetState(STATE_SHADOW);
|
||||
try
|
||||
|
@ -144,6 +144,12 @@ void CScreenMainMenu::CreateInterface()
|
|||
GetLogger()->Error("Failed loading userlevel button name: %s\n", e.what());
|
||||
}
|
||||
|
||||
|
||||
pos.y = oy+sy*5.0f;
|
||||
ddim.y = dim.y*0.4f;
|
||||
pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_CAREER);
|
||||
pb->SetState(STATE_SHADOW);
|
||||
|
||||
ddim.y = dim.y*0.5f;
|
||||
pos.y = oy+sy*4.35f;
|
||||
pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NAME);
|
||||
|
@ -243,6 +249,11 @@ bool CScreenMainMenu::EventProcess(const Event &event)
|
|||
m_main->ChangePhase(PHASE_LEVEL_LIST);
|
||||
break;
|
||||
|
||||
case EVENT_INTERFACE_CAREER:
|
||||
m_main->SetLevel(LevelCategory::CareerMode, 0, 0);
|
||||
m_main->ChangePhase(PHASE_LEVEL_LIST);
|
||||
break;
|
||||
|
||||
case EVENT_INTERFACE_SETUP:
|
||||
m_main->ChangePhase(CScreenSetup::GetTab());
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue