Added support for teams in EndMissionTake

Also fixed a bug in previous commit that caused lost= conditions to be skipped if previous min= max= condition was not met
master
krzys-h 2015-07-07 17:48:49 +02:00
parent a32efc09a2
commit a3726799c4
7 changed files with 119 additions and 8 deletions

View File

@ -303,7 +303,7 @@ Math::Vector CLevelParserParam::AsPoint(Math::Vector def)
ObjectType CLevelParserParam::ToObjectType(std::string value)
{
if (value == "All" ) return OBJECT_NULL;
if (value == "Any" ) return OBJECT_NULL; // For use in type= in ending conditions
if (value == "Portico" ) return OBJECT_PORTICO;
if (value == "SpaceShip" ) return OBJECT_BASE;
if (value == "PracticeBot" ) return OBJECT_MOBILEwt;

View File

@ -153,6 +153,32 @@ std::vector<CObject*> CObjectManager::GetObjectsOfTeam(int team)
return result;
}
bool CObjectManager::TeamExists(int team)
{
if(team == 0) return true;
for (CObject* object : GetAllObjects())
{
if (!object->GetActive())
continue;
if (object->GetTeam() == team)
return true;
}
return false;
}
void CObjectManager::DestroyTeam(int team)
{
assert(team != 0);
for (CObject* object : GetAllObjects())
{
if (object->GetTeam() == team)
object->ExplodeObject(ExplosionType::Bang, 1.0f);
}
}
CObject* CObjectManager::Radar(CObject* pThis, ObjectType type, float angle, float focus, float minDist, float maxDist, bool furthest, RadarFilter filter, bool cbotTypes)
{
std::vector<ObjectType> types;

View File

@ -148,6 +148,13 @@ public:
//! Gets all objects of given team
std::vector<CObject*> GetObjectsOfTeam(int team);
//! Checks if any of team's objects exist
bool TeamExists(int team);
//! Destroy all objects of team
// TODO: This should be probably moved to separate class
void DestroyTeam(int team);
//! Returns all objects
inline CObjectContainerProxy GetAllObjects()
{

View File

@ -5416,19 +5416,87 @@ void CRobotMain::SetEndMission(Error result, float delay)
}
}
Error CRobotMain::CheckEndMissionForGroup(std::vector<CSceneEndCondition*>& endTakes)
{
Error finalResult = ERR_OK;
for (CSceneEndCondition* endTake : endTakes)
{
Error result = endTake->GetMissionResult();
if(result != ERR_OK || endTake->immediat) {
if(finalResult != INFO_LOST && finalResult != INFO_LOSTq)
finalResult = result;
}
}
return finalResult;
}
//! Checks if the mission is over
Error CRobotMain::CheckEndMission(bool frame)
{
// Process EndMissionTake, unless we are using MissionController
if (m_controller == nullptr)
{
m_missionResult = ERR_OK;
for (std::unique_ptr<CSceneEndCondition>& endTake : m_endTake)
{
Error result = endTake->GetMissionResult();
if(result != ERR_OK || endTake->immediat) {
m_missionResult = result;
break;
// 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) {
int team = it.first;
if(team == 0) continue;
usesTeamConditions = true;
if(!m_objMan->TeamExists(team)) continue;
teamCount++;
}
if(!usesTeamConditions) {
m_missionResult = CheckEndMissionForGroup(teams[0]);
} else {
// Special handling for teams
m_missionResult = ERR_MISSION_NOTERM;
if(teamCount == 0) {
CLogger::GetInstancePointer()->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 = CheckEndMissionForGroup(it.second);
if(result == INFO_LOST || result == INFO_LOSTq) {
CLogger::GetInstancePointer()->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);
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)
{
CLogger::GetInstancePointer()->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)
{
CLogger::GetInstancePointer()->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;
if (m_exitAfterMission)
m_eventQueue->AddEvent(Event(EVENT_QUIT));
m_displayText->SetEnable(false);
}
m_missionResult = ERR_OK;
return ERR_OK;
}
}
}
}

View File

@ -200,6 +200,7 @@ public:
void UpdateAudio(bool frame);
void SetEndMission(Error result, float delay);
Error CheckEndMission(bool frame);
Error CheckEndMissionForGroup(std::vector<CSceneEndCondition*>& endTakes);
int GetObligatoryToken();
char* GetObligatoryToken(int i);
int IsObligatoryToken(const char* token);

View File

@ -36,6 +36,7 @@ void CSceneCondition::Read(CLevelParserLine* line)
this->tool = line->GetParam("tool")->AsToolType(ToolType::Other);
this->drive = line->GetParam("drive")->AsDriveType(DriveType::Other);
this->countTransported = line->GetParam("countTransported")->AsBool(true);
this->team = line->GetParam("team")->AsInt(0);
this->min = line->GetParam("min")->AsInt(1);
this->max = line->GetParam("max")->AsInt(9999);
@ -88,6 +89,10 @@ int CSceneCondition::CountObjects()
this->type != OBJECT_NULL)
continue;
if ((this->team > 0 && obj->GetTeam() != this->team) ||
(this->team < 0 && obj->GetTeam() == -(this->team)))
continue;
float energyLevel = -1;
CObject* power = obj->GetPower();
if (power != nullptr)
@ -128,6 +133,7 @@ bool CSceneCondition::Check()
void CSceneEndCondition::Read(CLevelParserLine* line)
{
CSceneCondition::Read(line);
this->winTeam = line->GetParam("winTeam")->AsInt(0);
this->lost = line->GetParam("lost")->AsInt(-1);
this->immediat = line->GetParam("immediat")->AsBool(false);
}

View File

@ -49,6 +49,7 @@ public:
ToolType tool = ToolType::Other;
DriveType drive = DriveType::Other;
bool countTransported = true;
int team = 0;
int min = 1; // wins if >
int max = 9999; // wins if <
@ -71,6 +72,8 @@ protected:
class CSceneEndCondition : public CSceneCondition
{
public:
int winTeam = 0;
int lost = -1; // lost if <=
bool immediat = false;