From a3726799c47f8db336bd88c296f7b45be86c46fd Mon Sep 17 00:00:00 2001 From: krzys-h Date: Tue, 7 Jul 2015 17:48:49 +0200 Subject: [PATCH] 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 --- src/object/level/parserparam.cpp | 2 +- src/object/object_manager.cpp | 26 ++++++++++ src/object/object_manager.h | 7 +++ src/object/robotmain.cpp | 82 +++++++++++++++++++++++++++++--- src/object/robotmain.h | 1 + src/object/scene_conditions.cpp | 6 +++ src/object/scene_conditions.h | 3 ++ 7 files changed, 119 insertions(+), 8 deletions(-) diff --git a/src/object/level/parserparam.cpp b/src/object/level/parserparam.cpp index f77d7295..516aa826 100644 --- a/src/object/level/parserparam.cpp +++ b/src/object/level/parserparam.cpp @@ -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; diff --git a/src/object/object_manager.cpp b/src/object/object_manager.cpp index d2cd6aa7..f22f1faa 100644 --- a/src/object/object_manager.cpp +++ b/src/object/object_manager.cpp @@ -153,6 +153,32 @@ std::vector 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 types; diff --git a/src/object/object_manager.h b/src/object/object_manager.h index 4b0b8def..67bd2d4a 100644 --- a/src/object/object_manager.h +++ b/src/object/object_manager.h @@ -148,6 +148,13 @@ public: //! Gets all objects of given team std::vector 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() { diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index 765e7483..db30df0a 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -5416,19 +5416,87 @@ void CRobotMain::SetEndMission(Error result, float delay) } } +Error CRobotMain::CheckEndMissionForGroup(std::vector& 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& endTake : m_endTake) - { - Error result = endTake->GetMissionResult(); - if(result != ERR_OK || endTake->immediat) { - m_missionResult = result; - break; + // Sort end conditions by teams + std::map> teams; + for (std::unique_ptr& 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(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(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; + } + } } } diff --git a/src/object/robotmain.h b/src/object/robotmain.h index 9afcc42b..fc1b9f10 100644 --- a/src/object/robotmain.h +++ b/src/object/robotmain.h @@ -200,6 +200,7 @@ public: void UpdateAudio(bool frame); void SetEndMission(Error result, float delay); Error CheckEndMission(bool frame); + Error CheckEndMissionForGroup(std::vector& endTakes); int GetObligatoryToken(); char* GetObligatoryToken(int i); int IsObligatoryToken(const char* token); diff --git a/src/object/scene_conditions.cpp b/src/object/scene_conditions.cpp index a415b0f6..66d72c6f 100644 --- a/src/object/scene_conditions.cpp +++ b/src/object/scene_conditions.cpp @@ -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); } diff --git a/src/object/scene_conditions.h b/src/object/scene_conditions.h index 9590d6c4..0b8f74bc 100644 --- a/src/object/scene_conditions.h +++ b/src/object/scene_conditions.h @@ -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;