181 lines
5.1 KiB
C++
181 lines
5.1 KiB
C++
/*
|
|
* This file is part of the Colobot: Gold Edition source code
|
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
|
* http://epsitec.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 "level/scene_conditions.h"
|
|
|
|
#include "level/parser/parserline.h"
|
|
|
|
#include "math/geometry.h"
|
|
|
|
#include "object/object.h"
|
|
#include "object/object_manager.h"
|
|
|
|
#include "object/interface/power_container_object.h"
|
|
#include "object/interface/slotted_object.h"
|
|
#include "object/interface/transportable_object.h"
|
|
|
|
#include <limits>
|
|
|
|
|
|
void CObjectCondition::Read(CLevelParserLine* line)
|
|
{
|
|
this->pos = line->GetParam("pos")->AsPoint(glm::vec3(0.0f, 0.0f, 0.0f))*g_unit;
|
|
this->dist = line->GetParam("dist")->AsFloat(std::numeric_limits<float>::infinity())*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->team = line->GetParam("team")->AsInt(0);
|
|
}
|
|
|
|
bool CObjectCondition::CheckForObject(CObject* obj)
|
|
{
|
|
if (!this->countTransported)
|
|
{
|
|
if (IsObjectBeingTransported(obj)) return false;
|
|
}
|
|
|
|
ObjectType type = obj->GetType();
|
|
|
|
ToolType tool = GetToolFromObject(type);
|
|
DriveType drive = GetDriveFromObject(type);
|
|
if (this->tool != ToolType::Other &&
|
|
tool != this->tool)
|
|
return false;
|
|
|
|
if (this->drive != DriveType::Other &&
|
|
drive != this->drive)
|
|
return false;
|
|
|
|
if (this->tool == ToolType::Other &&
|
|
this->drive == DriveType::Other &&
|
|
type != this->type &&
|
|
this->type != OBJECT_NULL)
|
|
return false;
|
|
|
|
if ((this->team > 0 && obj->GetTeam() != this->team) ||
|
|
(this->team < 0 && (obj->GetTeam() == -(this->team) || obj->GetTeam() == 0)))
|
|
return false;
|
|
|
|
float energyLevel = -1;
|
|
CPowerContainerObject* power = nullptr;
|
|
if (obj->Implements(ObjectInterfaceType::PowerContainer))
|
|
{
|
|
power = dynamic_cast<CPowerContainerObject*>(obj);
|
|
}
|
|
else
|
|
{
|
|
power = GetObjectPowerCell(obj);
|
|
}
|
|
|
|
if (power != nullptr)
|
|
{
|
|
energyLevel = power->GetEnergy();
|
|
if (power->GetCapacity() > 1.0f) energyLevel *= 10; // TODO: Who designed it like that ?!?!
|
|
}
|
|
if (energyLevel < this->powermin || energyLevel > this->powermax) return false;
|
|
|
|
glm::vec3 oPos{};
|
|
if (IsObjectBeingTransported(obj))
|
|
oPos = dynamic_cast<CTransportableObject&>(*obj).GetTransporter()->GetPosition();
|
|
else
|
|
oPos = obj->GetPosition();
|
|
oPos.y = 0.0f;
|
|
|
|
glm::vec3 bPos = this->pos;
|
|
bPos.y = 0.0f;
|
|
|
|
if (Math::DistanceProjected(oPos, bPos) <= this->dist)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
int CObjectCondition::CountObjects()
|
|
{
|
|
int nb = 0;
|
|
for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects())
|
|
{
|
|
if (!obj->GetActive()) continue;
|
|
if (!CheckForObject(obj)) continue;
|
|
nb ++;
|
|
}
|
|
return nb;
|
|
}
|
|
|
|
void CSceneCondition::Read(CLevelParserLine* line)
|
|
{
|
|
CObjectCondition::Read(line);
|
|
|
|
// Scene conditions STILL use a different default value
|
|
// See issue #759
|
|
this->dist = line->GetParam("dist")->AsFloat(8.0f)*g_unit;
|
|
|
|
this->min = line->GetParam("min")->AsInt(1);
|
|
this->max = line->GetParam("max")->AsInt(9999);
|
|
}
|
|
|
|
bool CSceneCondition::Check()
|
|
{
|
|
int nb = CountObjects();
|
|
return nb >= this->min && nb <= this->max;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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 = line->GetParam("filename")->AsPath("music");
|
|
this->repeat = line->GetParam("repeat")->AsBool(true);
|
|
}
|