Refactored EndMissionTake and AudioChange
parent
c190a671b5
commit
a32efc09a2
|
@ -164,6 +164,7 @@ set(BASE_SOURCES
|
||||||
object/object_manager.cpp
|
object/object_manager.cpp
|
||||||
object/old_object.cpp
|
object/old_object.cpp
|
||||||
object/robotmain.cpp
|
object/robotmain.cpp
|
||||||
|
object/scene_conditions.cpp
|
||||||
object/task/task.cpp
|
object/task/task.cpp
|
||||||
object/task/taskadvance.cpp
|
object/task/taskadvance.cpp
|
||||||
object/task/taskbuild.cpp
|
object/task/taskbuild.cpp
|
||||||
|
|
|
@ -109,7 +109,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class ObjectManager
|
* \class CObjectManager
|
||||||
* \brief Manages CObject instances
|
* \brief Manages CObject instances
|
||||||
*/
|
*/
|
||||||
class CObjectManager : public CSingleton<CObjectManager>
|
class CObjectManager : public CSingleton<CObjectManager>
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "object/motion/motiontoto.h"
|
#include "object/motion/motiontoto.h"
|
||||||
#include "object/object.h"
|
#include "object/object.h"
|
||||||
#include "object/object_manager.h"
|
#include "object/object_manager.h"
|
||||||
|
#include "object/scene_conditions.h"
|
||||||
#include "object/task/task.h"
|
#include "object/task/task.h"
|
||||||
#include "object/task/taskbuild.h"
|
#include "object/task/taskbuild.h"
|
||||||
#include "object/task/taskmanip.h"
|
#include "object/task/taskmanip.h"
|
||||||
|
@ -2894,8 +2895,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
||||||
m_lockedSatCom = false;
|
m_lockedSatCom = false;
|
||||||
m_endingWinRank = 0;
|
m_endingWinRank = 0;
|
||||||
m_endingLostRank = 0;
|
m_endingLostRank = 0;
|
||||||
m_audioChangeTotal = 0;
|
m_audioChange.clear();
|
||||||
m_endTakeTotal = 0;
|
m_endTake.clear();
|
||||||
m_endTakeResearch = 0;
|
m_endTakeResearch = 0;
|
||||||
m_endTakeNever = false;
|
m_endTakeNever = false;
|
||||||
m_endTakeWinDelay = 2.0f;
|
m_endTakeWinDelay = 2.0f;
|
||||||
|
@ -3067,24 +3068,10 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
||||||
|
|
||||||
if (line->GetCommand() == "AudioChange" && !resetObject && m_controller == nullptr)
|
if (line->GetCommand() == "AudioChange" && !resetObject && m_controller == nullptr)
|
||||||
{
|
{
|
||||||
int i = m_audioChangeTotal;
|
auto audioChange = std::unique_ptr<CAudioChangeCondition>{new CAudioChangeCondition()};
|
||||||
if (i < 10)
|
audioChange->Read(line.get());
|
||||||
{
|
m_sound->CacheMusic(audioChange->music);
|
||||||
m_audioChange[i].pos = line->GetParam("pos")->AsPoint(Math::Vector(0.0f, 0.0f, 0.0f))*g_unit;
|
m_audioChange.push_back(std::move(audioChange));
|
||||||
m_audioChange[i].dist = line->GetParam("dist")->AsFloat(1000.0f)*g_unit;
|
|
||||||
m_audioChange[i].type = line->GetParam("type")->AsObjectType(OBJECT_NULL);
|
|
||||||
m_audioChange[i].min = line->GetParam("min")->AsInt(1);
|
|
||||||
m_audioChange[i].max = line->GetParam("max")->AsInt(9999);
|
|
||||||
m_audioChange[i].powermin = line->GetParam("powermin")->AsFloat(-1);
|
|
||||||
m_audioChange[i].powermax = line->GetParam("powermax")->AsFloat(100);
|
|
||||||
m_audioChange[i].tool = line->GetParam("tool")->AsToolType(ToolType::Other);
|
|
||||||
m_audioChange[i].drive = line->GetParam("drive")->AsDriveType(DriveType::Other);
|
|
||||||
strcpy(m_audioChange[i].music, (std::string("../")+line->GetParam("filename")->AsPath("music")).c_str());
|
|
||||||
m_audioChange[i].repeat = line->GetParam("repeat")->AsBool(true);
|
|
||||||
m_audioChange[i].changed = false;
|
|
||||||
m_sound->CacheMusic(m_audioChange[i].music);
|
|
||||||
m_audioChangeTotal ++;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3818,24 +3805,9 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
||||||
|
|
||||||
if (line->GetCommand() == "EndMissionTake" && !resetObject && m_controller == nullptr)
|
if (line->GetCommand() == "EndMissionTake" && !resetObject && m_controller == nullptr)
|
||||||
{
|
{
|
||||||
int i = m_endTakeTotal;
|
auto endTake = std::unique_ptr<CSceneEndCondition>{new CSceneEndCondition()};
|
||||||
if (i < 10)
|
endTake->Read(line.get());
|
||||||
{
|
m_endTake.push_back(std::move(endTake));
|
||||||
m_endTake[i].pos = line->GetParam("pos")->AsPoint(Math::Vector(0.0f, 0.0f, 0.0f))*g_unit;
|
|
||||||
m_endTake[i].dist = line->GetParam("dist")->AsFloat(8.0f)*g_unit;
|
|
||||||
m_endTake[i].type = line->GetParam("type")->AsObjectType(OBJECT_NULL);
|
|
||||||
m_endTake[i].min = line->GetParam("min")->AsInt(1);
|
|
||||||
m_endTake[i].max = line->GetParam("max")->AsInt(9999);
|
|
||||||
m_endTake[i].powermin = line->GetParam("powermin")->AsFloat(-1);
|
|
||||||
m_endTake[i].powermax = line->GetParam("powermax")->AsFloat(100);
|
|
||||||
m_endTake[i].tool = line->GetParam("tool")->AsToolType(ToolType::Other);
|
|
||||||
m_endTake[i].drive = line->GetParam("drive")->AsDriveType(DriveType::Other);
|
|
||||||
m_endTake[i].lost = line->GetParam("lost")->AsInt(-1);
|
|
||||||
m_endTake[i].immediat = line->GetParam("immediat")->AsBool(false);
|
|
||||||
m_endTake[i].countTransported = line->GetParam("countTransported")->AsBool(true);
|
|
||||||
strcpy(m_endTake[i].message, line->GetParam("message")->AsString("").c_str()); //TODO: Really, ending mission on message()? Is this used anywhere? Do we need that?
|
|
||||||
m_endTakeTotal ++;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (line->GetCommand() == "EndMissionDelay" && !resetObject && m_controller == nullptr)
|
if (line->GetCommand() == "EndMissionDelay" && !resetObject && m_controller == nullptr)
|
||||||
|
@ -5421,82 +5393,15 @@ void CRobotMain::ResetCreate()
|
||||||
//! Updates the audiotracks
|
//! Updates the audiotracks
|
||||||
void CRobotMain::UpdateAudio(bool frame)
|
void CRobotMain::UpdateAudio(bool frame)
|
||||||
{
|
{
|
||||||
for (int t = 0; t < m_audioChangeTotal; t++)
|
for(std::unique_ptr<CAudioChangeCondition>& audioChange : m_audioChange)
|
||||||
{
|
{
|
||||||
if (m_audioChange[t].changed) continue;
|
if (audioChange->changed) continue;
|
||||||
|
|
||||||
Math::Vector bPos = m_audioChange[t].pos;
|
if (audioChange->Check())
|
||||||
bPos.y = 0.0f;
|
|
||||||
|
|
||||||
Math::Vector oPos;
|
|
||||||
|
|
||||||
int nb = 0;
|
|
||||||
for (CObject* obj : m_objMan->GetAllObjects())
|
|
||||||
{
|
{
|
||||||
// Do not use GetActive () because an invisible worm (underground)
|
CLogger::GetInstancePointer()->Info("Changing music to \"%s\"\n", audioChange->music.c_str());
|
||||||
// should be regarded as existing here!
|
m_sound->PlayMusic(audioChange->music, audioChange->repeat);
|
||||||
if (obj->GetLock()) continue;
|
audioChange->changed = true;
|
||||||
if (obj->GetRuin()) continue;
|
|
||||||
if (!obj->GetEnable()) continue;
|
|
||||||
|
|
||||||
ObjectType type = obj->GetType();
|
|
||||||
if (type == OBJECT_SCRAP2 ||
|
|
||||||
type == OBJECT_SCRAP3 ||
|
|
||||||
type == OBJECT_SCRAP4 ||
|
|
||||||
type == OBJECT_SCRAP5) // wastes?
|
|
||||||
{
|
|
||||||
type = OBJECT_SCRAP1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolType tool = GetToolFromObject(type);
|
|
||||||
DriveType drive = GetDriveFromObject(type);
|
|
||||||
if (m_audioChange[t].tool != ToolType::Other &&
|
|
||||||
tool != m_audioChange[t].tool)
|
|
||||||
continue;
|
|
||||||
if (m_audioChange[t].drive != DriveType::Other &&
|
|
||||||
drive != m_audioChange[t].drive)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_audioChange[t].tool == ToolType::Other &&
|
|
||||||
m_audioChange[t].drive == DriveType::Other &&
|
|
||||||
type != m_audioChange[t].type)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
float energyLevel = -1;
|
|
||||||
CObject* power = obj->GetPower();
|
|
||||||
if (power != nullptr)
|
|
||||||
{
|
|
||||||
energyLevel = power->GetEnergy();
|
|
||||||
if (power->GetType() == OBJECT_ATOMIC) energyLevel *= 100;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (obj->GetType() == OBJECT_POWER || obj->GetType() == OBJECT_ATOMIC)
|
|
||||||
{
|
|
||||||
energyLevel = obj->GetEnergy();
|
|
||||||
if (obj->GetType() == OBJECT_ATOMIC) energyLevel *= 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (energyLevel < m_audioChange[t].powermin || energyLevel > m_audioChange[t].powermax)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (obj->GetTransporter() == 0)
|
|
||||||
oPos = obj->GetPosition(0);
|
|
||||||
else
|
|
||||||
oPos = obj->GetTransporter()->GetPosition(0);
|
|
||||||
|
|
||||||
oPos.y = 0.0f;
|
|
||||||
|
|
||||||
if (Math::DistanceProjected(oPos, bPos) <= m_audioChange[t].dist)
|
|
||||||
nb ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nb >= m_audioChange[t].min &&
|
|
||||||
nb <= m_audioChange[t].max)
|
|
||||||
{
|
|
||||||
CLogger::GetInstancePointer()->Info("Changing music to \"%s\"\n", m_audioChange[t].music);
|
|
||||||
m_sound->PlayMusic(std::string(m_audioChange[t].music), m_audioChange[t].repeat);
|
|
||||||
m_audioChange[t].changed = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5514,29 +5419,80 @@ void CRobotMain::SetEndMission(Error result, float delay)
|
||||||
//! Checks if the mission is over
|
//! Checks if the mission is over
|
||||||
Error CRobotMain::CheckEndMission(bool frame)
|
Error CRobotMain::CheckEndMission(bool frame)
|
||||||
{
|
{
|
||||||
if (m_controller != nullptr)
|
// Process EndMissionTake, unless we are using MissionController
|
||||||
|
if (m_controller == nullptr)
|
||||||
{
|
{
|
||||||
if (m_missionResult == INFO_LOST) //mission lost?
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_missionResult != INFO_LOST && m_missionResult != INFO_LOSTq)
|
||||||
|
{
|
||||||
|
if (m_endTakeResearch != 0)
|
||||||
|
{
|
||||||
|
if (m_endTakeResearch != (m_endTakeResearch&g_researchDone))
|
||||||
|
{
|
||||||
|
m_missionResult = ERR_MISSION_NOTERM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_missionResult == ERR_OK && m_endTakeNever) m_missionResult = ERR_MISSION_NOTERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take action depending on m_missionResult
|
||||||
|
|
||||||
|
if(m_missionResult == INFO_LOSTq)
|
||||||
|
{
|
||||||
|
if (m_lostDelay == 0.0f)
|
||||||
|
{
|
||||||
|
m_lostDelay = 0.1f; // lost immediately
|
||||||
|
m_winDelay = 0.0f;
|
||||||
|
}
|
||||||
|
m_missionTimerEnabled = m_missionTimerStarted = false;
|
||||||
|
m_displayText->SetEnable(false);
|
||||||
|
if (m_exitAfterMission)
|
||||||
|
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
||||||
|
return INFO_LOSTq;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_missionResult == INFO_LOST)
|
||||||
|
{
|
||||||
|
if (m_lostDelay == 0.0f)
|
||||||
{
|
{
|
||||||
m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f));
|
m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f));
|
||||||
m_missionTimerEnabled = m_missionTimerStarted = false;
|
m_lostDelay = m_endTakeLostDelay; // lost in 6 seconds
|
||||||
m_winDelay = 0.0f;
|
m_winDelay = 0.0f;
|
||||||
if (m_lostDelay == 0) m_lostDelay = m_endTakeLostDelay;
|
|
||||||
m_displayText->SetEnable(false);
|
|
||||||
if (m_exitAfterMission)
|
|
||||||
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
|
||||||
}
|
}
|
||||||
if (m_missionResult == INFO_LOSTq) //mission lost?
|
m_missionTimerEnabled = m_missionTimerStarted = false;
|
||||||
|
m_displayText->SetEnable(false);
|
||||||
|
if (m_exitAfterMission)
|
||||||
|
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
||||||
|
return INFO_LOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_missionResult == ERR_OK)
|
||||||
|
{
|
||||||
|
if (m_endTakeWinDelay == -1.0f)
|
||||||
{
|
{
|
||||||
|
m_winDelay = 1.0f; // wins in one second
|
||||||
|
m_lostDelay = 0.0f;
|
||||||
m_missionTimerEnabled = m_missionTimerStarted = false;
|
m_missionTimerEnabled = m_missionTimerStarted = false;
|
||||||
m_winDelay = 0.0f;
|
|
||||||
if (m_lostDelay == 0) m_lostDelay = 0.1f;
|
|
||||||
m_displayText->SetEnable(false);
|
m_displayText->SetEnable(false);
|
||||||
if (m_exitAfterMission)
|
if (m_exitAfterMission)
|
||||||
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
||||||
|
return ERR_OK; // mission ended
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame && m_base != nullptr && m_base->GetSelectable()) return ERR_MISSION_NOTERM;
|
if (frame && m_base != nullptr && m_base->GetSelectable()) return ERR_MISSION_NOTERM;
|
||||||
if (m_missionResult == ERR_OK) //mission win?
|
|
||||||
|
if (m_winDelay == 0.0f)
|
||||||
{
|
{
|
||||||
m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
|
m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
|
||||||
if (m_missionTimerEnabled && m_missionTimerStarted)
|
if (m_missionTimerEnabled && m_missionTimerStarted)
|
||||||
|
@ -5545,196 +5501,18 @@ Error CRobotMain::CheckEndMission(bool frame)
|
||||||
m_displayText->DisplayText(("Time: " + TimeFormat(m_missionTimer)).c_str(), Math::Vector(0.0f,0.0f,0.0f));
|
m_displayText->DisplayText(("Time: " + TimeFormat(m_missionTimer)).c_str(), Math::Vector(0.0f,0.0f,0.0f));
|
||||||
}
|
}
|
||||||
m_missionTimerEnabled = m_missionTimerStarted = false;
|
m_missionTimerEnabled = m_missionTimerStarted = false;
|
||||||
if (m_winDelay == 0) m_winDelay = m_endTakeWinDelay;
|
m_winDelay = m_endTakeWinDelay; // wins in two seconds
|
||||||
m_lostDelay = 0.0f;
|
m_lostDelay = 0.0f;
|
||||||
m_displayText->SetEnable(false);
|
|
||||||
if (m_exitAfterMission)
|
|
||||||
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
|
||||||
}
|
}
|
||||||
if (m_missionResult == ERR_MISSION_NOTERM) m_displayText->SetEnable(true);
|
|
||||||
return m_missionResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int t = 0; t < m_endTakeTotal; t++)
|
|
||||||
{
|
|
||||||
if (m_endTake[t].message[0] != 0) continue;
|
|
||||||
|
|
||||||
Math::Vector bPos = m_endTake[t].pos;
|
|
||||||
bPos.y = 0.0f;
|
|
||||||
|
|
||||||
Math::Vector oPos;
|
|
||||||
|
|
||||||
int nb = 0;
|
|
||||||
for (CObject* obj : m_objMan->GetAllObjects())
|
|
||||||
{
|
|
||||||
// Do not use GetActive () because an invisible worm (underground)
|
|
||||||
// should be regarded as existing here!
|
|
||||||
if (obj->GetLock()) continue;
|
|
||||||
if (obj->GetRuin()) continue;
|
|
||||||
if (!obj->GetEnable()) continue;
|
|
||||||
|
|
||||||
if (!m_endTake[t].countTransported)
|
|
||||||
{
|
|
||||||
if (obj->GetTransporter() != nullptr) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectType type = obj->GetType();
|
|
||||||
if (type == OBJECT_SCRAP2 ||
|
|
||||||
type == OBJECT_SCRAP3 ||
|
|
||||||
type == OBJECT_SCRAP4 ||
|
|
||||||
type == OBJECT_SCRAP5) // wastes?
|
|
||||||
{
|
|
||||||
type = OBJECT_SCRAP1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolType tool = GetToolFromObject(type);
|
|
||||||
DriveType drive = GetDriveFromObject(type);
|
|
||||||
if (m_endTake[t].tool != ToolType::Other &&
|
|
||||||
tool != m_endTake[t].tool)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_endTake[t].drive != DriveType::Other &&
|
|
||||||
drive != m_endTake[t].drive)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_endTake[t].tool == ToolType::Other &&
|
|
||||||
m_endTake[t].drive == DriveType::Other &&
|
|
||||||
type != m_endTake[t].type)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
float energyLevel = -1;
|
|
||||||
CObject* power = obj->GetPower();
|
|
||||||
if (power != nullptr)
|
|
||||||
{
|
|
||||||
energyLevel = power->GetEnergy();
|
|
||||||
if (power->GetType() == OBJECT_ATOMIC) energyLevel *= 100;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (obj->GetType() == OBJECT_POWER || obj->GetType() == OBJECT_ATOMIC)
|
|
||||||
{
|
|
||||||
energyLevel = obj->GetEnergy();
|
|
||||||
if (obj->GetType() == OBJECT_ATOMIC) energyLevel *= 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (energyLevel < m_endTake[t].powermin || energyLevel > m_endTake[t].powermax) continue;
|
|
||||||
|
|
||||||
if (obj->GetTransporter() == 0)
|
|
||||||
oPos = obj->GetPosition(0);
|
|
||||||
else
|
|
||||||
oPos = obj->GetTransporter()->GetPosition(0);
|
|
||||||
|
|
||||||
oPos.y = 0.0f;
|
|
||||||
|
|
||||||
if (Math::DistanceProjected(oPos, bPos) <= m_endTake[t].dist)
|
|
||||||
nb ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nb <= m_endTake[t].lost)
|
|
||||||
{
|
|
||||||
if (m_endTake[t].type == OBJECT_HUMAN)
|
|
||||||
{
|
|
||||||
if (m_lostDelay == 0.0f)
|
|
||||||
{
|
|
||||||
m_lostDelay = 0.1f; // lost immediately
|
|
||||||
m_winDelay = 0.0f;
|
|
||||||
}
|
|
||||||
m_missionTimerEnabled = m_missionTimerStarted = false;
|
|
||||||
m_displayText->SetEnable(false);
|
|
||||||
if (m_exitAfterMission)
|
|
||||||
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
|
||||||
return INFO_LOSTq;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_lostDelay == 0.0f)
|
|
||||||
{
|
|
||||||
m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f));
|
|
||||||
m_lostDelay = m_endTakeLostDelay; // lost in 6 seconds
|
|
||||||
m_winDelay = 0.0f;
|
|
||||||
}
|
|
||||||
m_missionTimerEnabled = m_missionTimerStarted = false;
|
|
||||||
m_displayText->SetEnable(false);
|
|
||||||
if (m_exitAfterMission)
|
|
||||||
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
|
||||||
return INFO_LOST;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nb < m_endTake[t].min ||
|
|
||||||
nb > m_endTake[t].max ||
|
|
||||||
m_endTakeNever )
|
|
||||||
{
|
|
||||||
m_displayText->SetEnable(true);
|
|
||||||
return ERR_MISSION_NOTERM;
|
|
||||||
}
|
|
||||||
if (m_endTake[t].immediat)
|
|
||||||
{
|
|
||||||
if (m_winDelay == 0.0f)
|
|
||||||
{
|
|
||||||
m_winDelay = m_endTakeWinDelay; // wins in x seconds
|
|
||||||
m_lostDelay = 0.0f;
|
|
||||||
}
|
|
||||||
m_missionTimerEnabled = m_missionTimerStarted = false;
|
|
||||||
m_displayText->SetEnable(false);
|
|
||||||
if (m_exitAfterMission)
|
|
||||||
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
|
||||||
return ERR_OK; // mission ended
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_endTakeResearch != 0)
|
|
||||||
{
|
|
||||||
if (m_endTakeResearch != (m_endTakeResearch&g_researchDone))
|
|
||||||
{
|
|
||||||
m_displayText->SetEnable(true);
|
|
||||||
return ERR_MISSION_NOTERM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_endTakeWinDelay == -1.0f)
|
|
||||||
{
|
|
||||||
m_winDelay = 1.0f; // wins in one second
|
|
||||||
m_lostDelay = 0.0f;
|
|
||||||
m_missionTimerEnabled = m_missionTimerStarted = false;
|
|
||||||
m_displayText->SetEnable(false);
|
|
||||||
if (m_exitAfterMission)
|
if (m_exitAfterMission)
|
||||||
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
||||||
|
m_displayText->SetEnable(false);
|
||||||
return ERR_OK; // mission ended
|
return ERR_OK; // mission ended
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (frame && m_base != nullptr && m_base->GetSelectable()) return ERR_MISSION_NOTERM;
|
|
||||||
|
|
||||||
if (m_winDelay == 0.0f)
|
|
||||||
{
|
{
|
||||||
m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
|
m_displayText->SetEnable(true);
|
||||||
if (m_missionTimerEnabled && m_missionTimerStarted)
|
return ERR_MISSION_NOTERM;
|
||||||
{
|
|
||||||
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);
|
|
||||||
return ERR_OK; // mission ended
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Checks if the mission is finished after displaying a message
|
|
||||||
void CRobotMain::CheckEndMessage(const char* message)
|
|
||||||
{
|
|
||||||
for (int t = 0; t < m_endTakeTotal; t++)
|
|
||||||
{
|
|
||||||
if (m_endTake[t].message[0] == 0) continue;
|
|
||||||
|
|
||||||
if (strcmp(m_endTake[t].message, message) == 0)
|
|
||||||
{
|
|
||||||
m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
|
|
||||||
m_winDelay = m_endTakeWinDelay; // wins in 2 seconds
|
|
||||||
m_lostDelay = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,8 @@ class CSoundInterface;
|
||||||
class CLevelParserLine;
|
class CLevelParserLine;
|
||||||
class CInput;
|
class CInput;
|
||||||
class CObjectManager;
|
class CObjectManager;
|
||||||
|
class CSceneEndCondition;
|
||||||
|
class CAudioChangeCondition;
|
||||||
|
|
||||||
namespace Gfx {
|
namespace Gfx {
|
||||||
class CEngine;
|
class CEngine;
|
||||||
|
@ -103,41 +105,6 @@ class CDisplayText;
|
||||||
class CDisplayInfo;
|
class CDisplayInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct EndTake
|
|
||||||
{
|
|
||||||
Math::Vector pos;
|
|
||||||
float dist;
|
|
||||||
ObjectType type;
|
|
||||||
int min; // wins if >
|
|
||||||
int max; // wins if <
|
|
||||||
int lost; // lost if <=
|
|
||||||
float powermin; // wins if energy cell >=
|
|
||||||
float powermax; // wins if energy cell <=
|
|
||||||
ToolType tool;
|
|
||||||
DriveType drive;
|
|
||||||
bool immediat;
|
|
||||||
bool countTransported;
|
|
||||||
char message[100];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AudioChange
|
|
||||||
{
|
|
||||||
Math::Vector pos;
|
|
||||||
float dist;
|
|
||||||
ObjectType type;
|
|
||||||
int min; // change if >
|
|
||||||
int max; // change if <
|
|
||||||
float powermin; // change if energy cell >=
|
|
||||||
float powermax; // change if energy cell <=
|
|
||||||
ToolType tool;
|
|
||||||
DriveType drive;
|
|
||||||
char music[100];
|
|
||||||
bool repeat;
|
|
||||||
bool changed;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const int MAXNEWSCRIPTNAME = 20;
|
const int MAXNEWSCRIPTNAME = 20;
|
||||||
|
|
||||||
struct NewScriptName
|
struct NewScriptName
|
||||||
|
@ -233,7 +200,6 @@ public:
|
||||||
void UpdateAudio(bool frame);
|
void UpdateAudio(bool frame);
|
||||||
void SetEndMission(Error result, float delay);
|
void SetEndMission(Error result, float delay);
|
||||||
Error CheckEndMission(bool frame);
|
Error CheckEndMission(bool frame);
|
||||||
void CheckEndMessage(const char* message);
|
|
||||||
int GetObligatoryToken();
|
int GetObligatoryToken();
|
||||||
char* GetObligatoryToken(int i);
|
char* GetObligatoryToken(int i);
|
||||||
int IsObligatoryToken(const char* token);
|
int IsObligatoryToken(const char* token);
|
||||||
|
@ -517,15 +483,13 @@ protected:
|
||||||
Math::Vector m_visitPos;
|
Math::Vector m_visitPos;
|
||||||
Math::Vector m_visitPosArrow;
|
Math::Vector m_visitPosArrow;
|
||||||
|
|
||||||
int m_endTakeTotal;
|
std::vector<std::unique_ptr<CSceneEndCondition>> m_endTake;
|
||||||
EndTake m_endTake[10];
|
|
||||||
long m_endTakeResearch;
|
long m_endTakeResearch;
|
||||||
bool m_endTakeNever;
|
bool m_endTakeNever;
|
||||||
float m_endTakeWinDelay;
|
float m_endTakeWinDelay;
|
||||||
float m_endTakeLostDelay;
|
float m_endTakeLostDelay;
|
||||||
|
|
||||||
int m_audioChangeTotal;
|
std::vector<std::unique_ptr<CAudioChangeCondition>> m_audioChange;
|
||||||
AudioChange m_audioChange[10];
|
|
||||||
|
|
||||||
int m_obligatoryTotal;
|
int m_obligatoryTotal;
|
||||||
char m_obligatoryToken[100][20];
|
char m_obligatoryToken[100][20];
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "object/scene_conditions.h"
|
||||||
|
|
||||||
|
#include "math/geometry.h"
|
||||||
|
|
||||||
|
#include "object/level/parserline.h"
|
||||||
|
#include "object/object_manager.h"
|
||||||
|
#include "object/object.h"
|
||||||
|
|
||||||
|
void CSceneCondition::Read(CLevelParserLine* line)
|
||||||
|
{
|
||||||
|
this->pos = line->GetParam("pos")->AsPoint(Math::Vector(0.0f, 0.0f, 0.0f))*g_unit;
|
||||||
|
this->dist = line->GetParam("dist")->AsFloat(8.0f)*g_unit;
|
||||||
|
this->type = line->GetParam("type")->AsObjectType(OBJECT_NULL);
|
||||||
|
this->powermin = line->GetParam("powermin")->AsFloat(-1);
|
||||||
|
this->powermax = line->GetParam("powermax")->AsFloat(100);
|
||||||
|
this->tool = line->GetParam("tool")->AsToolType(ToolType::Other);
|
||||||
|
this->drive = line->GetParam("drive")->AsDriveType(DriveType::Other);
|
||||||
|
this->countTransported = line->GetParam("countTransported")->AsBool(true);
|
||||||
|
|
||||||
|
this->min = line->GetParam("min")->AsInt(1);
|
||||||
|
this->max = line->GetParam("max")->AsInt(9999);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSceneCondition::CountObjects()
|
||||||
|
{
|
||||||
|
Math::Vector bPos = this->pos;
|
||||||
|
bPos.y = 0.0f;
|
||||||
|
|
||||||
|
Math::Vector oPos;
|
||||||
|
|
||||||
|
int nb = 0;
|
||||||
|
for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects())
|
||||||
|
{
|
||||||
|
// Do not use GetActive () because an invisible worm (underground)
|
||||||
|
// should be regarded as existing here!
|
||||||
|
if (obj->GetLock()) continue;
|
||||||
|
if (obj->GetRuin()) continue;
|
||||||
|
if (!obj->GetEnable()) continue;
|
||||||
|
|
||||||
|
if (!this->countTransported)
|
||||||
|
{
|
||||||
|
if (obj->GetTransporter() != nullptr) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: I really hate those fragments that hardcode subcategories into one in random places in code, we should refactor that at some point
|
||||||
|
ObjectType type = obj->GetType();
|
||||||
|
if (type == OBJECT_SCRAP2 ||
|
||||||
|
type == OBJECT_SCRAP3 ||
|
||||||
|
type == OBJECT_SCRAP4 ||
|
||||||
|
type == OBJECT_SCRAP5) // wastes?
|
||||||
|
{
|
||||||
|
type = OBJECT_SCRAP1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolType tool = GetToolFromObject(type);
|
||||||
|
DriveType drive = GetDriveFromObject(type);
|
||||||
|
if (this->tool != ToolType::Other &&
|
||||||
|
tool != this->tool)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (this->drive != DriveType::Other &&
|
||||||
|
drive != this->drive)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (this->tool == ToolType::Other &&
|
||||||
|
this->drive == DriveType::Other &&
|
||||||
|
type != this->type &&
|
||||||
|
this->type != OBJECT_NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float energyLevel = -1;
|
||||||
|
CObject* power = obj->GetPower();
|
||||||
|
if (power != nullptr)
|
||||||
|
{
|
||||||
|
energyLevel = power->GetEnergy();
|
||||||
|
if (power->GetType() == OBJECT_ATOMIC) energyLevel *= 100;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (obj->GetType() == OBJECT_POWER || obj->GetType() == OBJECT_ATOMIC)
|
||||||
|
{
|
||||||
|
energyLevel = obj->GetEnergy();
|
||||||
|
if (obj->GetType() == OBJECT_ATOMIC) energyLevel *= 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (energyLevel < this->powermin || energyLevel > this->powermax) continue;
|
||||||
|
|
||||||
|
if (obj->GetTransporter() == 0)
|
||||||
|
oPos = obj->GetPosition(0);
|
||||||
|
else
|
||||||
|
oPos = obj->GetTransporter()->GetPosition(0);
|
||||||
|
|
||||||
|
oPos.y = 0.0f;
|
||||||
|
|
||||||
|
if (Math::DistanceProjected(oPos, bPos) <= this->dist)
|
||||||
|
nb ++;
|
||||||
|
}
|
||||||
|
return nb;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSceneCondition::Check()
|
||||||
|
{
|
||||||
|
int nb = CountObjects();
|
||||||
|
return nb >= this->min && nb <= this->max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CSceneEndCondition::Read(CLevelParserLine* line)
|
||||||
|
{
|
||||||
|
CSceneCondition::Read(line);
|
||||||
|
this->lost = line->GetParam("lost")->AsInt(-1);
|
||||||
|
this->immediat = line->GetParam("immediat")->AsBool(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSceneEndCondition::CheckLost()
|
||||||
|
{
|
||||||
|
int nb = CountObjects();
|
||||||
|
return nb <= this->lost;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error CSceneEndCondition::GetMissionResult()
|
||||||
|
{
|
||||||
|
if (CheckLost())
|
||||||
|
{
|
||||||
|
if (this->type == OBJECT_HUMAN)
|
||||||
|
return INFO_LOSTq;
|
||||||
|
else
|
||||||
|
return INFO_LOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Check())
|
||||||
|
{
|
||||||
|
return ERR_MISSION_NOTERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAudioChangeCondition::Read(CLevelParserLine* line)
|
||||||
|
{
|
||||||
|
CSceneCondition::Read(line);
|
||||||
|
this->music = std::string("../")+line->GetParam("filename")->AsPath("music");
|
||||||
|
this->repeat = line->GetParam("repeat")->AsBool(true);
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file object/scene_conditions.h
|
||||||
|
* \brief Classes for managing conditions in scene files
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/global.h"
|
||||||
|
|
||||||
|
#include "math/vector.h"
|
||||||
|
|
||||||
|
#include "object/object_type.h"
|
||||||
|
#include "object/tool_type.h"
|
||||||
|
#include "object/drive_type.h"
|
||||||
|
|
||||||
|
class CLevelParserLine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CSceneCondition
|
||||||
|
* \brief Base scene condition structure
|
||||||
|
*/
|
||||||
|
class CSceneCondition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Math::Vector pos = Math::Vector(0.0f, 0.0f, 0.0f)*g_unit;
|
||||||
|
float dist = 8.0f*g_unit;
|
||||||
|
ObjectType type = OBJECT_NULL;
|
||||||
|
float powermin = -1; // wins if energy cell >=
|
||||||
|
float powermax = 100; // wins if energy cell <=
|
||||||
|
ToolType tool = ToolType::Other;
|
||||||
|
DriveType drive = DriveType::Other;
|
||||||
|
bool countTransported = true;
|
||||||
|
|
||||||
|
int min = 1; // wins if >
|
||||||
|
int max = 9999; // wins if <
|
||||||
|
|
||||||
|
//! Read from line in scene file
|
||||||
|
virtual void Read(CLevelParserLine* line);
|
||||||
|
|
||||||
|
//! Checks if this condition is met
|
||||||
|
bool Check();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//! Count all object matching the conditions
|
||||||
|
int CountObjects();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CSceneEndCondition
|
||||||
|
* \brief Scene end condition
|
||||||
|
*/
|
||||||
|
class CSceneEndCondition : public CSceneCondition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int lost = -1; // lost if <=
|
||||||
|
|
||||||
|
bool immediat = false;
|
||||||
|
|
||||||
|
//! Read from line in scene file
|
||||||
|
virtual void Read(CLevelParserLine* line);
|
||||||
|
|
||||||
|
//! Checks if lost condition is met
|
||||||
|
bool CheckLost();
|
||||||
|
|
||||||
|
//! Get mission result
|
||||||
|
Error GetMissionResult();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CAudioChangeCondition
|
||||||
|
* \brief Audio change condition
|
||||||
|
*/
|
||||||
|
class CAudioChangeCondition : public CSceneCondition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string music = "";
|
||||||
|
bool repeat = true;
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
//! Read from line in scene file
|
||||||
|
virtual void Read(CLevelParserLine* line);
|
||||||
|
};
|
|
@ -2902,7 +2902,6 @@ bool CScriptFunctions::rMessage(CBotVar* var, CBotVar* result, int& exception, v
|
||||||
}
|
}
|
||||||
|
|
||||||
script->m_main->GetDisplayText()->DisplayText(p, script->m_object, 10.0f, type);
|
script->m_main->GetDisplayText()->DisplayText(p, script->m_object, 10.0f, type);
|
||||||
script->m_main->CheckEndMessage(p);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue