Refactored EndMissionTake and AudioChange
parent
c190a671b5
commit
a32efc09a2
|
@ -164,6 +164,7 @@ set(BASE_SOURCES
|
|||
object/object_manager.cpp
|
||||
object/old_object.cpp
|
||||
object/robotmain.cpp
|
||||
object/scene_conditions.cpp
|
||||
object/task/task.cpp
|
||||
object/task/taskadvance.cpp
|
||||
object/task/taskbuild.cpp
|
||||
|
|
|
@ -109,7 +109,7 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* \class ObjectManager
|
||||
* \class CObjectManager
|
||||
* \brief Manages CObject instances
|
||||
*/
|
||||
class CObjectManager : public CSingleton<CObjectManager>
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "object/motion/motiontoto.h"
|
||||
#include "object/object.h"
|
||||
#include "object/object_manager.h"
|
||||
#include "object/scene_conditions.h"
|
||||
#include "object/task/task.h"
|
||||
#include "object/task/taskbuild.h"
|
||||
#include "object/task/taskmanip.h"
|
||||
|
@ -2894,8 +2895,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
m_lockedSatCom = false;
|
||||
m_endingWinRank = 0;
|
||||
m_endingLostRank = 0;
|
||||
m_audioChangeTotal = 0;
|
||||
m_endTakeTotal = 0;
|
||||
m_audioChange.clear();
|
||||
m_endTake.clear();
|
||||
m_endTakeResearch = 0;
|
||||
m_endTakeNever = false;
|
||||
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)
|
||||
{
|
||||
int i = m_audioChangeTotal;
|
||||
if (i < 10)
|
||||
{
|
||||
m_audioChange[i].pos = line->GetParam("pos")->AsPoint(Math::Vector(0.0f, 0.0f, 0.0f))*g_unit;
|
||||
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 ++;
|
||||
}
|
||||
auto audioChange = std::unique_ptr<CAudioChangeCondition>{new CAudioChangeCondition()};
|
||||
audioChange->Read(line.get());
|
||||
m_sound->CacheMusic(audioChange->music);
|
||||
m_audioChange.push_back(std::move(audioChange));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3818,24 +3805,9 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
|
||||
if (line->GetCommand() == "EndMissionTake" && !resetObject && m_controller == nullptr)
|
||||
{
|
||||
int i = m_endTakeTotal;
|
||||
if (i < 10)
|
||||
{
|
||||
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 ++;
|
||||
}
|
||||
auto endTake = std::unique_ptr<CSceneEndCondition>{new CSceneEndCondition()};
|
||||
endTake->Read(line.get());
|
||||
m_endTake.push_back(std::move(endTake));
|
||||
continue;
|
||||
}
|
||||
if (line->GetCommand() == "EndMissionDelay" && !resetObject && m_controller == nullptr)
|
||||
|
@ -5421,82 +5393,15 @@ void CRobotMain::ResetCreate()
|
|||
//! Updates the audiotracks
|
||||
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;
|
||||
bPos.y = 0.0f;
|
||||
|
||||
Math::Vector oPos;
|
||||
|
||||
int nb = 0;
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
if (audioChange->Check())
|
||||
{
|
||||
// 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;
|
||||
|
||||
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;
|
||||
CLogger::GetInstancePointer()->Info("Changing music to \"%s\"\n", audioChange->music.c_str());
|
||||
m_sound->PlayMusic(audioChange->music, audioChange->repeat);
|
||||
audioChange->changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5514,29 +5419,80 @@ void CRobotMain::SetEndMission(Error result, float delay)
|
|||
//! Checks if the mission is over
|
||||
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_missionTimerEnabled = m_missionTimerStarted = false;
|
||||
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));
|
||||
m_lostDelay = m_endTakeLostDelay; // lost in 6 seconds
|
||||
m_winDelay = 0.0f;
|
||||
}
|
||||
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_winDelay = 0.0f;
|
||||
if (m_lostDelay == 0) m_lostDelay = 0.1f;
|
||||
m_displayText->SetEnable(false);
|
||||
if (m_exitAfterMission)
|
||||
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
||||
return ERR_OK; // mission ended
|
||||
}
|
||||
|
||||
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));
|
||||
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_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_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)
|
||||
m_eventQueue->AddEvent(Event(EVENT_QUIT));
|
||||
m_displayText->SetEnable(false);
|
||||
return ERR_OK; // mission ended
|
||||
}
|
||||
|
||||
if (frame && m_base != nullptr && m_base->GetSelectable()) return ERR_MISSION_NOTERM;
|
||||
|
||||
if (m_winDelay == 0.0f)
|
||||
else
|
||||
{
|
||||
m_displayText->DisplayError(INFO_WIN, 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);
|
||||
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;
|
||||
}
|
||||
m_displayText->SetEnable(true);
|
||||
return ERR_MISSION_NOTERM;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,8 @@ class CSoundInterface;
|
|||
class CLevelParserLine;
|
||||
class CInput;
|
||||
class CObjectManager;
|
||||
class CSceneEndCondition;
|
||||
class CAudioChangeCondition;
|
||||
|
||||
namespace Gfx {
|
||||
class CEngine;
|
||||
|
@ -103,41 +105,6 @@ class CDisplayText;
|
|||
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;
|
||||
|
||||
struct NewScriptName
|
||||
|
@ -233,7 +200,6 @@ public:
|
|||
void UpdateAudio(bool frame);
|
||||
void SetEndMission(Error result, float delay);
|
||||
Error CheckEndMission(bool frame);
|
||||
void CheckEndMessage(const char* message);
|
||||
int GetObligatoryToken();
|
||||
char* GetObligatoryToken(int i);
|
||||
int IsObligatoryToken(const char* token);
|
||||
|
@ -517,15 +483,13 @@ protected:
|
|||
Math::Vector m_visitPos;
|
||||
Math::Vector m_visitPosArrow;
|
||||
|
||||
int m_endTakeTotal;
|
||||
EndTake m_endTake[10];
|
||||
std::vector<std::unique_ptr<CSceneEndCondition>> m_endTake;
|
||||
long m_endTakeResearch;
|
||||
bool m_endTakeNever;
|
||||
float m_endTakeWinDelay;
|
||||
float m_endTakeLostDelay;
|
||||
|
||||
int m_audioChangeTotal;
|
||||
AudioChange m_audioChange[10];
|
||||
std::vector<std::unique_ptr<CAudioChangeCondition>> m_audioChange;
|
||||
|
||||
int m_obligatoryTotal;
|
||||
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->CheckEndMessage(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue