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.

colobot2
immibis 2023-11-18 19:06:37 +01:00
parent 4251873f49
commit 0fa486b9f0
11 changed files with 199 additions and 73 deletions

View File

@ -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,

View File

@ -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");

View File

@ -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,

View File

@ -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)

View File

@ -30,6 +30,7 @@ enum class LevelCategory
CodeBattles,
GamePlus,
CustomLevels,
CareerMode,
Max,
};

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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;