2014-10-14 13:11:37 +00:00
|
|
|
|
/*
|
|
|
|
|
* This file is part of the Colobot: Gold Edition source code
|
|
|
|
|
* Copyright (C) 2001-2014, 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
|
|
|
|
|
*/
|
2013-03-31 08:21:22 +00:00
|
|
|
|
|
2015-06-20 18:02:40 +00:00
|
|
|
|
#include "object/object_manager.h"
|
2014-12-20 19:36:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "math/all.h"
|
2013-03-31 08:21:22 +00:00
|
|
|
|
|
|
|
|
|
#include "object/object.h"
|
2015-06-27 21:22:55 +00:00
|
|
|
|
#include "object/object_create_params.h"
|
2015-06-20 17:27:43 +00:00
|
|
|
|
#include "object/object_factory.h"
|
2015-07-02 21:48:30 +00:00
|
|
|
|
#include "object/old_object.h"
|
2013-03-31 08:21:22 +00:00
|
|
|
|
#include "object/auto/auto.h"
|
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
#include "physics/physics.h"
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
2013-03-31 08:21:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<> CObjectManager* CSingleton<CObjectManager>::m_instance = nullptr;
|
|
|
|
|
|
|
|
|
|
|
2015-06-20 17:27:43 +00:00
|
|
|
|
CObjectManager::CObjectManager(Gfx::CEngine* engine,
|
|
|
|
|
Gfx::CTerrain* terrain,
|
2015-07-09 16:45:02 +00:00
|
|
|
|
Gfx::COldModelManager* modelManager,
|
2015-06-20 17:27:43 +00:00
|
|
|
|
Gfx::CParticle* particle,
|
|
|
|
|
CRobotMain* main)
|
|
|
|
|
: m_objectFactory(new CObjectFactory(engine, terrain, modelManager, particle, main))
|
2015-06-21 09:16:09 +00:00
|
|
|
|
, m_nextId(0)
|
2013-03-31 08:21:22 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CObjectManager::~CObjectManager()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-21 09:16:09 +00:00
|
|
|
|
bool CObjectManager::DeleteObject(CObject* instance)
|
2013-03-31 08:21:22 +00:00
|
|
|
|
{
|
2014-12-20 18:09:53 +00:00
|
|
|
|
assert(instance != nullptr);
|
2015-06-21 09:16:09 +00:00
|
|
|
|
|
2015-07-02 21:48:30 +00:00
|
|
|
|
// TODO: temporarily...
|
|
|
|
|
auto oldObj = dynamic_cast<COldObject*>(instance);
|
|
|
|
|
if (oldObj != nullptr)
|
|
|
|
|
oldObj->DeleteObject();
|
2015-06-21 09:16:09 +00:00
|
|
|
|
|
2015-06-21 14:22:09 +00:00
|
|
|
|
auto it = m_objects.find(instance->GetID());
|
|
|
|
|
if (it != m_objects.end())
|
2015-06-21 09:16:09 +00:00
|
|
|
|
{
|
2015-06-21 14:22:09 +00:00
|
|
|
|
m_objects.erase(it);
|
2015-06-21 09:16:09 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
2013-03-31 08:21:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-21 09:16:09 +00:00
|
|
|
|
void CObjectManager::DeleteAllObjects()
|
2013-03-31 08:21:22 +00:00
|
|
|
|
{
|
2015-06-21 14:22:09 +00:00
|
|
|
|
for (auto& it : m_objects)
|
2013-03-31 08:21:22 +00:00
|
|
|
|
{
|
2015-07-02 21:48:30 +00:00
|
|
|
|
// TODO: temporarily...
|
|
|
|
|
auto oldObj = dynamic_cast<COldObject*>(it.second.get());
|
|
|
|
|
if (oldObj != nullptr)
|
|
|
|
|
{
|
|
|
|
|
bool all = true;
|
|
|
|
|
oldObj->DeleteObject(all);
|
|
|
|
|
}
|
2013-03-31 08:21:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-21 14:22:09 +00:00
|
|
|
|
m_objects.clear();
|
2015-06-21 09:16:09 +00:00
|
|
|
|
|
|
|
|
|
m_nextId = 0;
|
2013-03-31 08:21:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-21 16:06:55 +00:00
|
|
|
|
CObject* CObjectManager::GetObjectById(unsigned int id)
|
2013-03-31 08:21:22 +00:00
|
|
|
|
{
|
2015-06-25 17:05:56 +00:00
|
|
|
|
if (m_objects.count(id) == 0) return nullptr;
|
2015-06-21 14:22:09 +00:00
|
|
|
|
return m_objects[id].get();
|
2013-03-31 08:21:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-12-21 16:06:55 +00:00
|
|
|
|
CObject* CObjectManager::GetObjectByRank(unsigned int id)
|
|
|
|
|
{
|
2015-06-25 17:05:56 +00:00
|
|
|
|
if (id >= m_objects.size()) return nullptr;
|
2015-06-21 14:22:09 +00:00
|
|
|
|
auto it = m_objects.begin();
|
2015-06-25 17:05:56 +00:00
|
|
|
|
for (unsigned int i = 0; i < id; i++, ++it);
|
2015-06-21 09:16:09 +00:00
|
|
|
|
return it->second.get();
|
2014-12-21 16:06:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-21 09:16:09 +00:00
|
|
|
|
CObject* CObjectManager::CreateObject(Math::Vector pos,
|
|
|
|
|
float angle,
|
|
|
|
|
ObjectType type,
|
|
|
|
|
float power,
|
|
|
|
|
float zoom,
|
|
|
|
|
float height,
|
|
|
|
|
bool trainer,
|
|
|
|
|
bool toy,
|
|
|
|
|
int option,
|
|
|
|
|
int id)
|
2014-12-20 19:36:09 +00:00
|
|
|
|
{
|
2015-06-21 09:16:09 +00:00
|
|
|
|
if (id < 0)
|
|
|
|
|
{
|
|
|
|
|
id = m_nextId;
|
|
|
|
|
m_nextId++;
|
|
|
|
|
}
|
2014-12-20 19:36:09 +00:00
|
|
|
|
|
2015-06-21 14:22:09 +00:00
|
|
|
|
assert(m_objects.find(id) == m_objects.end());
|
2014-12-20 18:09:53 +00:00
|
|
|
|
|
2015-06-21 09:16:09 +00:00
|
|
|
|
ObjectCreateParams params;
|
|
|
|
|
params.pos = pos;
|
|
|
|
|
params.angle = angle;
|
|
|
|
|
params.type = type;
|
|
|
|
|
params.power = power;
|
|
|
|
|
params.zoom = zoom;
|
|
|
|
|
params.height = height;
|
|
|
|
|
params.trainer = trainer;
|
|
|
|
|
params.toy = toy;
|
|
|
|
|
params.option = option;
|
|
|
|
|
params.id = id;
|
2013-05-26 15:47:54 +00:00
|
|
|
|
|
2015-06-21 09:16:09 +00:00
|
|
|
|
auto objectUPtr = m_objectFactory->CreateObject(params);
|
|
|
|
|
CObject* objectPtr = objectUPtr.get();
|
|
|
|
|
|
2015-06-21 14:22:09 +00:00
|
|
|
|
m_objects[id] = std::move(objectUPtr);
|
2015-06-21 09:16:09 +00:00
|
|
|
|
|
|
|
|
|
return objectPtr;
|
2014-12-20 19:36:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 20:07:55 +00:00
|
|
|
|
std::vector<CObject*> CObjectManager::GetObjectsOfTeam(int team)
|
|
|
|
|
{
|
|
|
|
|
std::vector<CObject*> result;
|
|
|
|
|
for (CObject* object : GetAllObjects())
|
|
|
|
|
{
|
|
|
|
|
if (object->GetTeam() == team)
|
|
|
|
|
{
|
|
|
|
|
result.push_back(object);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-07 15:48:49 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
CObject* CObjectManager::Radar(CObject* pThis, ObjectType type, float angle, float focus, float minDist, float maxDist, bool furthest, RadarFilter filter, bool cbotTypes)
|
|
|
|
|
{
|
2014-12-21 16:06:55 +00:00
|
|
|
|
std::vector<ObjectType> types;
|
2015-06-25 17:05:56 +00:00
|
|
|
|
if (type != OBJECT_NULL)
|
2014-12-21 16:06:55 +00:00
|
|
|
|
types.push_back(type);
|
|
|
|
|
return Radar(pThis, types, angle, focus, minDist, maxDist, furthest, filter, cbotTypes);
|
2014-12-20 19:36:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CObject* CObjectManager::Radar(CObject* pThis, std::vector<ObjectType> type, float angle, float focus, float minDist, float maxDist, bool furthest, RadarFilter filter, bool cbotTypes)
|
|
|
|
|
{
|
|
|
|
|
Math::Vector iPos;
|
|
|
|
|
float iAngle;
|
2015-06-25 17:05:56 +00:00
|
|
|
|
if (pThis != nullptr)
|
2014-12-21 16:06:55 +00:00
|
|
|
|
{
|
|
|
|
|
iPos = pThis->GetPosition(0);
|
|
|
|
|
iAngle = pThis->GetAngleY(0);
|
|
|
|
|
iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
|
2015-06-25 17:05:56 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-12-21 16:06:55 +00:00
|
|
|
|
iPos = Math::Vector();
|
|
|
|
|
iAngle = 0.0f;
|
|
|
|
|
}
|
2014-12-20 19:36:09 +00:00
|
|
|
|
return Radar(pThis, iPos, iAngle, type, angle, focus, minDist, maxDist, furthest, filter, cbotTypes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CObject* CObjectManager::Radar(CObject* pThis, Math::Vector thisPosition, float thisAngle, ObjectType type, float angle, float focus, float minDist, float maxDist, bool furthest, RadarFilter filter, bool cbotTypes)
|
|
|
|
|
{
|
2014-12-21 16:06:55 +00:00
|
|
|
|
std::vector<ObjectType> types;
|
2015-06-25 17:05:56 +00:00
|
|
|
|
if (type != OBJECT_NULL)
|
2014-12-21 16:06:55 +00:00
|
|
|
|
types.push_back(type);
|
|
|
|
|
return Radar(pThis, thisPosition, thisAngle, types, angle, focus, minDist, maxDist, furthest, filter, cbotTypes);
|
2014-12-20 19:36:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CObject* CObjectManager::Radar(CObject* pThis, Math::Vector thisPosition, float thisAngle, std::vector<ObjectType> type, float angle, float focus, float minDist, float maxDist, bool furthest, RadarFilter filter, bool cbotTypes)
|
|
|
|
|
{
|
|
|
|
|
CObject *pObj, *pBest;
|
|
|
|
|
CPhysics* physics;
|
|
|
|
|
Math::Vector iPos, oPos;
|
|
|
|
|
float best, iAngle, d, a;
|
|
|
|
|
ObjectType oType;
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
minDist *= g_unit;
|
|
|
|
|
maxDist *= g_unit;
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
iPos = thisPosition;
|
|
|
|
|
iAngle = thisAngle+angle;
|
|
|
|
|
iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2015-07-07 16:54:36 +00:00
|
|
|
|
int filter_team = filter & 0xFF;
|
|
|
|
|
RadarFilter filter_flying = static_cast<RadarFilter>(filter & (FILTER_ONLYLANDING | FILTER_ONLYFLYING));
|
|
|
|
|
RadarFilter filter_enemy = static_cast<RadarFilter>(filter & (FILTER_FRIENDLY | FILTER_ENEMY | FILTER_NEUTRAL));
|
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
if ( !furthest ) best = 100000.0f;
|
|
|
|
|
else best = 0.0f;
|
|
|
|
|
pBest = nullptr;
|
2015-06-21 14:22:09 +00:00
|
|
|
|
for ( auto it = m_objects.begin() ; it != m_objects.end() ; ++it )
|
2014-12-20 19:36:09 +00:00
|
|
|
|
{
|
2015-06-21 09:16:09 +00:00
|
|
|
|
pObj = it->second.get();
|
2014-12-21 16:06:55 +00:00
|
|
|
|
if ( pObj == pThis ) continue; // pThis may be nullptr but it doesn't matter
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2015-06-29 21:05:31 +00:00
|
|
|
|
if ( pObj->GetTransporter() != 0 ) continue; // object transported?
|
2015-06-25 17:05:56 +00:00
|
|
|
|
if ( !pObj->GetActive() ) continue;
|
2014-12-20 19:36:09 +00:00
|
|
|
|
if ( pObj->GetProxyActivate() ) continue;
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
oType = pObj->GetType();
|
|
|
|
|
if ( oType == OBJECT_TOTO || oType == OBJECT_CONTROLLER ) continue;
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
|
|
|
|
if (cbotTypes)
|
|
|
|
|
{
|
2014-12-20 19:36:09 +00:00
|
|
|
|
// TODO: handle this differently (new class describing types? CObjectType::GetBaseType()?)
|
|
|
|
|
if ( oType == OBJECT_RUINmobilew2 ||
|
|
|
|
|
oType == OBJECT_RUINmobilet1 ||
|
|
|
|
|
oType == OBJECT_RUINmobilet2 ||
|
|
|
|
|
oType == OBJECT_RUINmobiler1 ||
|
|
|
|
|
oType == OBJECT_RUINmobiler2 )
|
|
|
|
|
{
|
|
|
|
|
oType = OBJECT_RUINmobilew1; // any ruin
|
|
|
|
|
}
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
if ( oType == OBJECT_SCRAP2 ||
|
|
|
|
|
oType == OBJECT_SCRAP3 ||
|
|
|
|
|
oType == OBJECT_SCRAP4 ||
|
|
|
|
|
oType == OBJECT_SCRAP5 ) // wastes?
|
|
|
|
|
{
|
|
|
|
|
oType = OBJECT_SCRAP1; // any waste
|
|
|
|
|
}
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
if ( oType == OBJECT_BARRIER2 ||
|
|
|
|
|
oType == OBJECT_BARRIER3 ) // barriers?
|
|
|
|
|
{
|
|
|
|
|
oType = OBJECT_BARRIER1; // any barrier
|
|
|
|
|
}
|
|
|
|
|
// END OF TODO
|
|
|
|
|
}
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2015-07-07 16:54:36 +00:00
|
|
|
|
if ( filter_flying == FILTER_ONLYLANDING )
|
2014-12-20 19:36:09 +00:00
|
|
|
|
{
|
|
|
|
|
physics = pObj->GetPhysics();
|
|
|
|
|
if ( physics != nullptr && !physics->GetLand() ) continue;
|
|
|
|
|
}
|
2015-07-07 16:54:36 +00:00
|
|
|
|
if ( filter_flying == FILTER_ONLYFLYING )
|
2014-12-20 19:36:09 +00:00
|
|
|
|
{
|
|
|
|
|
physics = pObj->GetPhysics();
|
|
|
|
|
if ( physics != nullptr && physics->GetLand() ) continue;
|
|
|
|
|
}
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2015-07-07 16:54:36 +00:00
|
|
|
|
if ( filter_team != 0 && pObj->GetTeam() != filter_team )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if( pThis != nullptr )
|
|
|
|
|
{
|
|
|
|
|
RadarFilter enemy = FILTER_NONE;
|
|
|
|
|
if ( pObj->GetTeam() == 0 ) enemy = static_cast<RadarFilter>(enemy | FILTER_NEUTRAL);
|
2015-07-07 20:27:44 +00:00
|
|
|
|
if ( pObj->GetTeam() != 0 && pObj->GetTeam() == pThis->GetTeam() ) enemy = static_cast<RadarFilter>(enemy | FILTER_FRIENDLY);
|
|
|
|
|
if ( pObj->GetTeam() != 0 && pObj->GetTeam() != pThis->GetTeam() ) enemy = static_cast<RadarFilter>(enemy | FILTER_ENEMY);
|
2015-07-07 16:54:36 +00:00
|
|
|
|
if ( filter_enemy != 0 && (filter_enemy & enemy) == 0 ) continue;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
if ( std::find(type.begin(), type.end(), oType) == type.end() && type.size() > 0 ) continue;
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
oPos = pObj->GetPosition(0);
|
|
|
|
|
d = Math::DistanceProjected(iPos, oPos);
|
|
|
|
|
if ( d < minDist || d > maxDist ) continue; // too close or too far?
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
|
|
|
|
|
if ( Math::TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) || focus >= Math::PI*2.0f )
|
|
|
|
|
{
|
|
|
|
|
if ( (!furthest && d < best) ||
|
|
|
|
|
(furthest && d > best) )
|
|
|
|
|
{
|
|
|
|
|
best = d;
|
|
|
|
|
pBest = pObj;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-06-25 17:05:56 +00:00
|
|
|
|
|
2014-12-20 19:36:09 +00:00
|
|
|
|
return pBest;
|
2014-12-21 16:06:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CObject* CObjectManager::FindNearest(CObject* pThis, ObjectType type, float maxDist, bool cbotTypes)
|
|
|
|
|
{
|
|
|
|
|
return Radar(pThis, type, 0.0f, Math::PI*2.0f, 0.0f, maxDist, false, FILTER_NONE, cbotTypes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CObject* CObjectManager::FindNearest(CObject* pThis, std::vector<ObjectType> type, float maxDist, bool cbotTypes)
|
|
|
|
|
{
|
|
|
|
|
return Radar(pThis, type, 0.0f, Math::PI*2.0f, 0.0f, maxDist, false, FILTER_NONE, cbotTypes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CObject* CObjectManager::FindNearest(CObject* pThis, Math::Vector thisPosition, ObjectType type, float maxDist, bool cbotTypes)
|
|
|
|
|
{
|
|
|
|
|
return Radar(pThis, thisPosition, 0.0f, type, 0.0f, Math::PI*2.0f, 0.0f, maxDist, false, FILTER_NONE, cbotTypes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CObject* CObjectManager::FindNearest(CObject* pThis, Math::Vector thisPosition, std::vector<ObjectType> type, float maxDist, bool cbotTypes)
|
|
|
|
|
{
|
|
|
|
|
return Radar(pThis, thisPosition, 0.0f, type, 0.0f, Math::PI*2.0f, 0.0f, maxDist, false, FILTER_NONE, cbotTypes);
|
2015-06-21 09:16:09 +00:00
|
|
|
|
}
|