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-07-11 17:48:37 +00:00
# include "object/object_create_exception.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-11 17:48:37 +00:00
Gfx : : COldModelManager * oldModelManager ,
Gfx : : CModelManager * modelManager ,
2015-07-10 17:53:32 +00:00
Gfx : : CParticle * particle )
2015-07-11 17:48:37 +00:00
: m_objectFactory ( new CObjectFactory ( engine , terrain , oldModelManager , modelManager , particle ) )
2015-06-21 09:16:09 +00:00
, m_nextId ( 0 )
2015-07-12 11:16:07 +00:00
, m_shouldCleanRemovedObjects ( false )
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-07-12 11:16:07 +00:00
it - > second . reset ( ) ;
m_shouldCleanRemovedObjects = true ;
2015-06-21 09:16:09 +00:00
return true ;
}
return false ;
2013-03-31 08:21:22 +00:00
}
2015-07-12 11:16:07 +00:00
void CObjectManager : : CleanRemovedObjects ( )
{
auto it = m_objects . begin ( ) ;
if ( it ! = m_objects . end ( ) )
{
if ( it - > second = = nullptr )
it = m_objects . erase ( it ) ;
}
m_shouldCleanRemovedObjects = false ;
}
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-07-22 10:45:50 +00:00
CObject * CObjectManager : : CreateObject ( ObjectCreateParams params )
{
if ( params . id < 0 )
{
params . id = m_nextId ;
m_nextId + + ;
}
assert ( m_objects . find ( params . id ) = = m_objects . end ( ) ) ;
auto objectUPtr = m_objectFactory - > CreateObject ( params ) ;
if ( objectUPtr = = nullptr )
throw CObjectCreateException ( " Something went wrong in CObjectFactory " , params . type ) ;
CObject * objectPtr = objectUPtr . get ( ) ;
m_objects [ params . id ] = std : : move ( objectUPtr ) ;
return objectPtr ;
}
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 ,
2015-07-22 10:45:50 +00:00
int team ,
2015-06-21 09:16:09 +00:00
int id )
2014-12-20 19:36:09 +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 ;
2015-07-22 10:45:50 +00:00
params . team = team ;
2015-06-21 09:16:09 +00:00
params . id = id ;
2013-05-26 15:47:54 +00:00
2015-07-22 10:45:50 +00:00
return CreateObject ( params ) ;
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
{
2015-07-12 08:34:00 +00:00
iPos = pThis - > GetPosition ( ) ;
2015-07-14 19:29:13 +00:00
iAngle = pThis - > GetRotationY ( ) ;
2014-12-21 16:06:55 +00:00
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-07-12 18:49:00 +00:00
if ( pObj = = nullptr ) continue ;
2015-07-10 17:03:27 +00:00
if ( IsObjectBeingTransported ( pObj ) ) continue ;
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 ( ) ;
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-14 19:39:51 +00:00
if ( std : : find ( type . begin ( ) , type . end ( ) , oType ) = = type . end ( ) & & type . size ( ) > 0 ) continue ;
if ( ( oType = = OBJECT_TOTO | | oType = = OBJECT_CONTROLLER ) & & type . size ( ) = = 0 ) continue ; // allow OBJECT_TOTO and OBJECT_CONTROLLER only if explicitly asked in type parameter
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 ;
}
2015-07-12 08:34:00 +00:00
oPos = pObj - > GetPosition ( ) ;
2014-12-20 19:36:09 +00:00
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
}