Refactored EndMissionTake and AudioChange

master
krzys-h 2015-07-07 16:17:19 +02:00
parent c190a671b5
commit a32efc09a2
7 changed files with 357 additions and 348 deletions

View File

@ -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

View File

@ -109,7 +109,7 @@ private:
};
/**
* \class ObjectManager
* \class CObjectManager
* \brief Manages CObject instances
*/
class CObjectManager : public CSingleton<CObjectManager>

View File

@ -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;
}
}

View File

@ -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];

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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;
}