[colobot] 56/145: LevelController improvements; minor EndMissionTake cleanup
Didier Raboud
odyx at moszumanska.debian.org
Mon Jul 11 12:56:17 UTC 2016
This is an automated email from the git hooks/post-receive script.
odyx pushed a commit to branch debian/master
in repository colobot.
commit 4c8da2c5036fc8a9ab0123b7f0a29a2a15eb260d
Author: krzys-h <krzys_h at interia.pl>
Date: Fri Apr 8 20:56:09 2016 +0200
LevelController improvements; minor EndMissionTake cleanup
* using LevelController script in the level doesn't forcefully disable EndMissionTake and AudioChange anymore
* cleaned up some code related to processing EndMissionTake commands
---
src/level/robotmain.cpp | 202 ++++++++++++++++++++++---------------------
src/level/robotmain.h | 9 +-
src/level/scene_conditions.h | 1 +
src/script/scriptfunc.cpp | 2 +-
4 files changed, 114 insertions(+), 100 deletions(-)
diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp
index 274118b..b3c34de 100644
--- a/src/level/robotmain.cpp
+++ b/src/level/robotmain.cpp
@@ -1236,19 +1236,22 @@ void CRobotMain::ExecuteCmd(const std::string& cmd)
if (cmd == "controller")
{
- if (m_controller != nullptr)
+ if (m_controller == nullptr)
{
- // Don't use SelectObject because it checks if the object is selectable
- if (m_camera->GetType() == Gfx::CAM_TYPE_VISIT)
- StopDisplayVisit();
+ GetLogger()->Error("No LevelController on the map to select\n");
+ return;
+ }
- CObject* prev = DeselectAll();
- if (prev != nullptr && prev != m_controller)
- PushToSelectionHistory(prev);
+ // Don't use SelectObject because it checks if the object is selectable
+ if (m_camera->GetType() == Gfx::CAM_TYPE_VISIT)
+ StopDisplayVisit();
- SelectOneObject(m_controller, true);
- m_short->UpdateShortcuts();
- }
+ CObject* prev = DeselectAll();
+ if (prev != nullptr && prev != m_controller)
+ PushToSelectionHistory(prev);
+
+ SelectOneObject(m_controller, true);
+ m_short->UpdateShortcuts();
return;
}
@@ -2831,6 +2834,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_endingLostRank = 0;
m_audioChange.clear();
m_endTake.clear();
+ m_endTakeImmediat = false;
m_endTakeResearch = 0;
m_endTakeWinDelay = 2.0f;
m_endTakeLostDelay = 2.0f;
@@ -2870,6 +2874,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_teamNames.clear();
m_missionResult = ERR_MISSION_NOTERM;
+ m_missionResultFromScript = false;
}
//NOTE: Reset timer always, even when only resetting object positions
@@ -2999,7 +3004,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
continue;
}
- if (line->GetCommand() == "AudioChange" && !resetObject && m_controller == nullptr)
+ if (line->GetCommand() == "AudioChange" && !resetObject)
{
auto audioChange = MakeUnique<CAudioChangeCondition>();
audioChange->Read(line.get());
@@ -3009,7 +3014,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
continue;
}
- if (line->GetCommand() == "Audio" && !resetObject && m_controller == nullptr)
+ if (line->GetCommand() == "Audio" && !resetObject)
{
if (line->GetParam("track")->IsDefined())
{
@@ -3410,6 +3415,11 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
if (line->GetCommand() == "LevelController" && m_sceneReadPath.empty())
{
+ if (m_controller != nullptr)
+ {
+ throw CLevelParserException("There can be only one LevelController in the level");
+ }
+
m_controller = m_objMan->CreateObject(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f, OBJECT_CONTROLLER);
assert(m_controller->Implements(ObjectInterfaceType::Programmable));
assert(m_controller->Implements(ObjectInterfaceType::ProgramStorage));
@@ -3625,26 +3635,28 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
continue;
}
- if (line->GetCommand() == "EndMissionTake" && !resetObject && m_controller == nullptr)
+ if (line->GetCommand() == "EndMissionTake" && !resetObject)
{
auto endTake = MakeUnique<CSceneEndCondition>();
endTake->Read(line.get());
+ if (endTake->immediat)
+ m_endTakeImmediat = true;
m_endTake.push_back(std::move(endTake));
continue;
}
- if (line->GetCommand() == "EndMissionDelay" && !resetObject && m_controller == nullptr)
+ if (line->GetCommand() == "EndMissionDelay" && !resetObject)
{
m_endTakeWinDelay = line->GetParam("win")->AsFloat(2.0f);
m_endTakeLostDelay = line->GetParam("lost")->AsFloat(2.0f);
continue;
}
- if (line->GetCommand() == "EndMissionResearch" && !resetObject && m_controller == nullptr) //TODO: Is this used anywhere?
+ if (line->GetCommand() == "EndMissionResearch" && !resetObject) // This is not used in any original Colobot levels, but we'll keep it for userlevel creators
{
m_endTakeResearch |= line->GetParam("type")->AsResearchFlag();
continue;
}
- if (line->GetCommand() == "ObligatoryToken" && !resetObject) //NOTE: This was used only in CeeBot, maybe we should add this to some Colobot exercises?
+ if (line->GetCommand() == "ObligatoryToken" && !resetObject) // NOTE: This was used only in CeeBot, maybe we should add this to some Colobot exercises?
{
int i = m_obligatoryTotal;
if (i < 100) //TODO: remove the limit
@@ -3655,7 +3667,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
continue;
}
- if (line->GetCommand() == "ProhibitedToken" && !resetObject) //NOTE: This was used only in CeeBot, maybe we should add this to some Colobot exercises?
+ if (line->GetCommand() == "ProhibitedToken" && !resetObject) // NOTE: This was used only in CeeBot, maybe we should add this to some Colobot exercises?
{
int i = m_prohibitedTotal;
if (i < 100) //TODO: remove the limit
@@ -5008,17 +5020,16 @@ void CRobotMain::UpdateAudio(bool frame)
}
}
-void CRobotMain::SetEndMission(Error result, float delay)
+//! Set mission result from LevelController script
+void CRobotMain::SetMissionResultFromScript(Error result, float delay)
{
- if (m_controller != nullptr)
- {
- m_endTakeWinDelay = delay;
- m_endTakeLostDelay = delay;
- m_missionResult = result;
- }
+ m_endTakeWinDelay = delay;
+ m_endTakeLostDelay = delay;
+ m_missionResult = result;
+ m_missionResultFromScript = true;
}
-Error CRobotMain::CheckEndMissionForGroup(std::vector<CSceneEndCondition*>& endTakes)
+Error CRobotMain::ProcessEndMissionTakeForGroup(std::vector<CSceneEndCondition*>& endTakes)
{
Error finalResult = ERR_OK;
bool hasWinningConditions = false;
@@ -5045,104 +5056,101 @@ Error CRobotMain::CheckEndMissionForGroup(std::vector<CSceneEndCondition*>& endT
return finalResult;
}
-//! Checks if the mission is over
-Error CRobotMain::CheckEndMission(bool frame)
+Error CRobotMain::ProcessEndMissionTake()
{
- bool isImmediat = false;
- // Process EndMissionTake, unless we are using MissionController
- if (m_controller == nullptr)
+ // Sort end conditions by teams
+ std::map<int, std::vector<CSceneEndCondition*>> teams;
+ for (std::unique_ptr<CSceneEndCondition>& endTake : m_endTake)
+ teams[endTake->winTeam].push_back(endTake.get());
+
+ int teamCount = 0;
+ bool usesTeamConditions = false;
+ for (auto it : teams)
{
- // Sort end conditions by teams
- std::map<int, std::vector<CSceneEndCondition*>> teams;
- for (std::unique_ptr<CSceneEndCondition>& endTake : m_endTake)
- {
- teams[endTake->winTeam].push_back(endTake.get());
- if(endTake->immediat)
- isImmediat = true;
- }
+ int team = it.first;
+ if (team == 0) continue;
+ usesTeamConditions = true;
+ if (!m_objMan->TeamExists(team)) continue;
+ teamCount++;
+ }
- int teamCount = 0;
- bool usesTeamConditions = false;
- for (auto it : teams)
- {
- int team = it.first;
- if(team == 0) continue;
- usesTeamConditions = true;
- if(!m_objMan->TeamExists(team)) continue;
- teamCount++;
- }
+ if (!usesTeamConditions)
+ {
+ m_missionResult = ProcessEndMissionTakeForGroup(teams[0]);
+ }
+ else
+ {
+ // Special handling for teams
+ m_missionResult = ERR_MISSION_NOTERM;
- if (!usesTeamConditions)
+ if (teamCount == 0)
{
- m_missionResult = CheckEndMissionForGroup(teams[0]);
+ GetLogger()->Info("All teams died, mission ended with failure\n");
+ m_missionResult = INFO_LOST;
}
else
{
- // Special handling for teams
- m_missionResult = ERR_MISSION_NOTERM;
-
- if (teamCount == 0)
+ for (auto it : teams)
{
- GetLogger()->Info("All teams died, mission ended with failure\n");
- m_missionResult = INFO_LOST;
- }
- else
- {
- for (auto it : teams)
+ int team = it.first;
+ if (team == 0) continue;
+ if (!m_objMan->TeamExists(team)) continue;
+
+ Error result = ProcessEndMissionTakeForGroup(it.second);
+ if (result == INFO_LOST || result == INFO_LOSTq)
{
- int team = it.first;
- if (team == 0) continue;
- if (!m_objMan->TeamExists(team)) continue;
+ GetLogger()->Info("Team %d lost\n", team);
+ m_displayText->DisplayText(("<<< Team "+boost::lexical_cast<std::string>(team)+" lost! >>>").c_str(), Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 10.0f, Ui::TT_ERROR);
- Error result = CheckEndMissionForGroup(it.second);
- if (result == INFO_LOST || result == INFO_LOSTq)
+ m_displayText->SetEnable(false); // To prevent "bot destroyed" messages
+ m_objMan->DestroyTeam(team);
+ m_displayText->SetEnable(true);
+ }
+ else if (result == ERR_OK)
+ {
+ if (m_winDelay == 0.0f)
{
- GetLogger()->Info("Team %d lost\n", team);
- m_displayText->DisplayText(("<<< Team "+boost::lexical_cast<std::string>(team)+" lost! >>>").c_str(), Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 10.0f, Ui::TT_ERROR);
+ GetLogger()->Info("Team %d won\n", team);
- m_displayText->SetEnable(false); // To prevent "bot destroyed" messages
- m_objMan->DestroyTeam(team);
- m_displayText->SetEnable(true);
- }
- else if(result == ERR_OK)
- {
- if (m_winDelay == 0.0f)
+ m_displayText->DisplayText(("<<< Team "+boost::lexical_cast<std::string>(team)+" won the game >>>").c_str(), Math::Vector(0.0f,0.0f,0.0f));
+ if (m_missionTimerEnabled && m_missionTimerStarted)
{
- GetLogger()->Info("Team %d won\n", team);
-
- m_displayText->DisplayText(("<<< Team "+boost::lexical_cast<std::string>(team)+" won the game >>>").c_str(), Math::Vector(0.0f,0.0f,0.0f));
- if (m_missionTimerEnabled && m_missionTimerStarted)
- {
- GetLogger()->Info("Mission time: %s\n", TimeFormat(m_missionTimer).c_str());
- m_displayText->DisplayText(("Time: " + TimeFormat(m_missionTimer)).c_str(), Math::Vector(0.0f,0.0f,0.0f));
- }
- m_missionTimerEnabled = m_missionTimerStarted = false;
- m_winDelay = m_endTakeWinDelay; // wins in two seconds
- m_lostDelay = 0.0f;
- m_displayText->SetEnable(false);
+ GetLogger()->Info("Mission time: %s\n", TimeFormat(m_missionTimer).c_str());
+ m_displayText->DisplayText(("Time: " + TimeFormat(m_missionTimer)).c_str(), Math::Vector(0.0f,0.0f,0.0f));
}
- m_missionResult = ERR_OK;
- return ERR_OK;
+ m_missionTimerEnabled = m_missionTimerStarted = false;
+ m_winDelay = m_endTakeWinDelay; // wins in two seconds
+ m_lostDelay = 0.0f;
+ m_displayText->SetEnable(false);
}
+ m_missionResult = ERR_OK;
+ return ERR_OK;
}
}
}
+ }
- if (m_missionResult != INFO_LOST && m_missionResult != INFO_LOSTq)
+ if (m_missionResult != INFO_LOST && m_missionResult != INFO_LOSTq)
+ {
+ if (m_endTakeResearch != 0)
{
- if (m_endTakeResearch != 0)
+ if (m_endTakeResearch != (m_endTakeResearch&m_researchDone[0]))
{
- if (m_endTakeResearch != (m_endTakeResearch&m_researchDone[0]))
- {
- m_missionResult = ERR_MISSION_NOTERM;
- }
+ m_missionResult = ERR_MISSION_NOTERM;
}
}
}
+}
+
+//! Checks if the mission is over
+Error CRobotMain::CheckEndMission(bool frame)
+{
+ // Process EndMissionTake, unless we are using LevelController script for processing ending conditions
+ if (!m_missionResultFromScript) ProcessEndMissionTake();
// Take action depending on m_missionResult
- if(m_missionResult == INFO_LOSTq)
+ if (m_missionResult == INFO_LOSTq)
{
if (m_lostDelay == 0.0f)
{
@@ -5154,7 +5162,7 @@ Error CRobotMain::CheckEndMission(bool frame)
return INFO_LOSTq;
}
- if(m_missionResult == INFO_LOST)
+ if (m_missionResult == INFO_LOST)
{
if (m_lostDelay == 0.0f)
{
@@ -5180,7 +5188,7 @@ Error CRobotMain::CheckEndMission(bool frame)
if (frame)
{
- if(m_base != nullptr && !isImmediat)
+ if (m_base != nullptr && !m_endTakeImmediat)
{
assert(m_base->Implements(ObjectInterfaceType::Controllable));
if(dynamic_cast<CControllableObject*>(m_base)->GetSelectable())
diff --git a/src/level/robotmain.h b/src/level/robotmain.h
index deea9e8..4f78df3 100644
--- a/src/level/robotmain.h
+++ b/src/level/robotmain.h
@@ -195,9 +195,10 @@ public:
void ResetObject();
void UpdateAudio(bool frame);
- void SetEndMission(Error result, float delay);
+ void SetMissionResultFromScript(Error result, float delay);
Error CheckEndMission(bool frame);
- Error CheckEndMissionForGroup(std::vector<CSceneEndCondition*>& endTakes);
+ Error ProcessEndMissionTake();
+ Error ProcessEndMissionTakeForGroup(std::vector<CSceneEndCondition*>& endTakes);
int GetObligatoryToken();
char* GetObligatoryToken(int i);
int IsObligatoryToken(const char* token);
@@ -543,6 +544,8 @@ protected:
ActivePause* m_visitPause = nullptr;
std::vector<std::unique_ptr<CSceneEndCondition>> m_endTake;
+ //! If true, the mission ends immediately after completing the requirements without requiring SpaceShip takeoff
+ bool m_endTakeImmediat = false;
long m_endTakeResearch = 0;
float m_endTakeWinDelay = 0.0f;
float m_endTakeLostDelay = 0.0f;
@@ -562,6 +565,8 @@ protected:
std::map<int, int> m_researchDone;
Error m_missionResult = ERR_OK;
+ //! true if m_missionResult has been set by LevelController script, this disables normal EndMissionTake processing
+ bool m_missionResultFromScript = false;
ShowLimit m_showLimit[MAXSHOWLIMIT];
diff --git a/src/level/scene_conditions.h b/src/level/scene_conditions.h
index 33a6508..258cc7e 100644
--- a/src/level/scene_conditions.h
+++ b/src/level/scene_conditions.h
@@ -77,6 +77,7 @@ public:
int lost = -1; // lost if <=
+ //! If this is true, the mission ends as soon as this requirement is met, without having to complete the others
bool immediat = false;
//! Read from line in scene file
diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp
index d072c79..e4da1f1 100644
--- a/src/script/scriptfunc.cpp
+++ b/src/script/scriptfunc.cpp
@@ -204,7 +204,7 @@ bool CScriptFunctions::rEndMission(CBotVar* var, CBotVar* result, int& exception
delay = var->GetValFloat();
- CRobotMain::GetInstancePointer()->SetEndMission(ended, delay);
+ CRobotMain::GetInstancePointer()->SetMissionResultFromScript(ended, delay);
return true;
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/colobot.git
More information about the Pkg-games-commits
mailing list