2019-09-20 00:45:55 -07:00
/* Copyright (C) 2019 Wildfire Games.
2010-01-29 13:13:18 -08:00
* This file is part of 0 A . D .
*
* 0 A . D . 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 2 of the License , or
* ( at your option ) any later version .
*
* 0 A . D . 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 0 A . D . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "precompiled.h"
# include "simulation2/system/Component.h"
# include "ICmpObstruction.h"
2012-05-05 12:22:22 -07:00
# include "ps/CLogger.h"
# include "simulation2/MessageTypes.h"
2011-08-06 01:11:05 -07:00
# include "simulation2/components/ICmpObstructionManager.h"
2018-01-21 18:34:46 -08:00
# include "simulation2/components/ICmpTerrain.h"
2015-07-18 01:37:49 -07:00
# include "simulation2/components/ICmpUnitMotion.h"
2018-01-21 18:34:46 -08:00
# include "simulation2/components/ICmpWaterManager.h"
2012-07-08 09:25:33 -07:00
# include "simulation2/serialization/SerializeTemplates.h"
2010-01-29 13:13:18 -08:00
/**
* Obstruction implementation . This keeps the ICmpPathfinder ' s model of the world updated when the
* entities move and die , with shapes derived from ICmpFootprint .
*/
class CCmpObstruction : public ICmpObstruction
{
public :
static void ClassInit ( CComponentManager & componentManager )
{
componentManager . SubscribeToMessageType ( MT_PositionChanged ) ;
componentManager . SubscribeToMessageType ( MT_Destroy ) ;
}
DEFAULT_COMPONENT_ALLOCATOR ( Obstruction )
2011-08-16 04:18:32 -07:00
typedef ICmpObstructionManager : : tag_t tag_t ;
typedef ICmpObstructionManager : : flags_t flags_t ;
2010-04-29 16:36:05 -07:00
// Template state:
2019-09-20 00:45:55 -07:00
EObstructionType m_Type ;
2012-05-05 12:22:22 -07:00
2010-04-29 16:36:05 -07:00
entity_pos_t m_Size0 ; // radius or width
entity_pos_t m_Size1 ; // radius or depth
2011-08-16 04:18:32 -07:00
flags_t m_TemplateFlags ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
entity_pos_t m_Clearance ;
2010-03-17 16:13:21 -07:00
2012-07-08 09:25:33 -07:00
typedef struct {
entity_pos_t dx , dz ;
2016-11-23 06:09:58 -08:00
entity_angle_t da ;
2012-07-08 09:25:33 -07:00
entity_pos_t size0 , size1 ;
flags_t flags ;
} Shape ;
std : : vector < Shape > m_Shapes ;
2010-04-29 16:36:05 -07:00
// Dynamic state:
2012-05-05 16:10:25 -07:00
/// Whether the obstruction is actively obstructing or just an inactive placeholder.
bool m_Active ;
/// Whether the entity associated with this obstruction is currently moving. Only applicable for
/// UNIT-type obstructions.
2010-04-29 16:36:05 -07:00
bool m_Moving ;
2012-08-01 14:38:13 -07:00
/// Whether an obstruction's control group should be kept consistent and
/// used to set control groups for entities that collide with it.
bool m_ControlPersist ;
2012-05-05 12:22:22 -07:00
/**
2012-05-05 16:10:25 -07:00
* Primary control group identifier . Indicates to which control group this entity ' s shape belongs .
* Typically used in combination with obstruction test filters to have member shapes ignore each
* other during obstruction tests . Defaults to the entity ' s ID . Must never be set to INVALID_ENTITY .
2012-05-05 12:22:22 -07:00
*/
2010-09-03 02:55:14 -07:00
entity_id_t m_ControlGroup ;
2012-05-05 16:10:25 -07:00
/**
* Optional secondary control group identifier . Similar to m_ControlGroup ; if set to a valid value ,
* then this field identifies an additional , secondary control group to which this entity ' s shape
* belongs . Set to INVALID_ENTITY to not assign any secondary group . Defaults to INVALID_ENTITY .
2016-11-23 05:02:58 -08:00
*
2012-05-05 16:10:25 -07:00
* These are only necessary in case it is not sufficient for an entity to belong to only one control
* group . Otherwise , they can be ignored .
*/
2012-05-05 12:22:22 -07:00
entity_id_t m_ControlGroup2 ;
2012-05-05 16:10:25 -07:00
/// Identifier of this entity's obstruction shape, as registered in the obstruction manager. Contains
/// structure, but should be treated as opaque here.
2011-08-16 04:18:32 -07:00
tag_t m_Tag ;
2012-07-08 09:25:33 -07:00
std : : vector < tag_t > m_ClusterTags ;
2012-05-05 16:10:25 -07:00
2012-05-05 12:22:22 -07:00
/// Set of flags affecting the behaviour of this entity's obstruction shape.
2011-08-16 04:18:32 -07:00
flags_t m_Flags ;
2010-03-17 16:13:21 -07:00
2010-04-09 12:02:39 -07:00
static std : : string GetSchema ( )
{
return
2010-04-23 09:09:03 -07:00
" <a:example/> "
2011-02-10 08:06:28 -08:00
" <a:help>Causes this entity to obstruct the motion of other units.</a:help> "
2010-04-29 16:36:05 -07:00
" <choice> "
" <element name='Static'> "
" <attribute name='width'> "
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
" <data type='decimal'> "
" <param name='minInclusive'>1.5</param> "
" </data> "
2010-04-29 16:36:05 -07:00
" </attribute> "
" <attribute name='depth'> "
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
" <data type='decimal'> "
" <param name='minInclusive'>1.5</param> "
" </data> "
2010-04-29 16:36:05 -07:00
" </attribute> "
" </element> "
" <element name='Unit'> "
2015-07-18 01:37:49 -07:00
" <empty/> "
2010-04-29 16:36:05 -07:00
" </element> "
2012-07-12 13:00:38 -07:00
" <element name='Obstructions'> "
2012-07-08 09:25:33 -07:00
" <zeroOrMore> "
" <element> "
" <anyName/> "
2012-07-12 13:00:38 -07:00
" <optional> "
" <attribute name='x'> "
" <data type='decimal'/> "
" </attribute> "
" </optional> "
" <optional> "
" <attribute name='z'> "
" <data type='decimal'/> "
" </attribute> "
" </optional> "
2012-07-08 09:25:33 -07:00
" <attribute name='width'> "
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
" <data type='decimal'> "
" <param name='minInclusive'>1.5</param> "
" </data> "
2012-07-08 09:25:33 -07:00
" </attribute> "
" <attribute name='depth'> "
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
" <data type='decimal'> "
" <param name='minInclusive'>1.5</param> "
" </data> "
2012-07-08 09:25:33 -07:00
" </attribute> "
" </element> "
" </zeroOrMore> "
" </element> "
2010-04-29 16:36:05 -07:00
" </choice> "
2011-02-10 08:06:28 -08:00
" <element name='Active' a:help='If false, this entity will be ignored in collision tests by other units but can still perform its own collision tests'> "
" <data type='boolean'/> "
" </element> "
" <element name='BlockMovement' a:help='Whether units should be allowed to walk through this entity'> "
" <data type='boolean'/> "
" </element> "
" <element name='BlockPathfinding' a:help='Whether the long-distance pathfinder should avoid paths through this entity. This should only be set for large stationary obstructions'> "
" <data type='boolean'/> "
" </element> "
" <element name='BlockFoundation' a:help='Whether players should be unable to place building foundations on top of this entity. If true, BlockConstruction should be true too'> "
" <data type='boolean'/> "
" </element> "
" <element name='BlockConstruction' a:help='Whether players should be unable to begin constructing buildings placed on top of this entity'> "
" <data type='boolean'/> "
2011-02-24 13:49:24 -08:00
" </element> "
2018-03-26 08:18:53 -07:00
" <element name='DeleteUponConstruction' a:help='Whether this entity should be deleted when construction on a buildings placed on top of this entity is started.'> "
" <data type='boolean'/> "
" </element> "
2011-02-24 13:49:24 -08:00
" <element name='DisableBlockMovement' a:help='If true, BlockMovement will be overridden and treated as false. (This is a special case to handle foundations)'> "
" <data type='boolean'/> "
" </element> "
" <element name='DisableBlockPathfinding' a:help='If true, BlockPathfinding will be overridden and treated as false. (This is a special case to handle foundations)'> "
" <data type='boolean'/> "
2012-08-01 14:38:13 -07:00
" </element> "
" <optional> "
" <element name='ControlPersist' a:help='If present, the control group of this entity will be given to entities that are colliding with it.'> "
" <empty/> "
" </element> "
" </optional> " ;
2010-04-09 12:02:39 -07:00
}
2010-04-23 09:09:03 -07:00
2011-01-16 06:08:38 -08:00
virtual void Init ( const CParamNode & paramNode )
2010-01-29 13:13:18 -08:00
{
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
// The minimum obstruction size is the navcell size * sqrt(2)
// This is enforced in the schema as a minimum of 1.5
fixed minObstruction = ( Pathfinding : : NAVCELL_SIZE . Square ( ) * 2 ) . Sqrt ( ) ;
2011-02-24 13:49:24 -08:00
m_TemplateFlags = 0 ;
2011-02-10 08:06:28 -08:00
if ( paramNode . GetChild ( " BlockMovement " ) . ToBool ( ) )
2011-02-24 13:49:24 -08:00
m_TemplateFlags | = ICmpObstructionManager : : FLAG_BLOCK_MOVEMENT ;
2011-02-10 08:06:28 -08:00
if ( paramNode . GetChild ( " BlockPathfinding " ) . ToBool ( ) )
2011-02-24 13:49:24 -08:00
m_TemplateFlags | = ICmpObstructionManager : : FLAG_BLOCK_PATHFINDING ;
2011-02-10 08:06:28 -08:00
if ( paramNode . GetChild ( " BlockFoundation " ) . ToBool ( ) )
2011-02-24 13:49:24 -08:00
m_TemplateFlags | = ICmpObstructionManager : : FLAG_BLOCK_FOUNDATION ;
2011-02-10 08:06:28 -08:00
if ( paramNode . GetChild ( " BlockConstruction " ) . ToBool ( ) )
2011-02-24 13:49:24 -08:00
m_TemplateFlags | = ICmpObstructionManager : : FLAG_BLOCK_CONSTRUCTION ;
2018-03-26 08:18:53 -07:00
if ( paramNode . GetChild ( " DeleteUponConstruction " ) . ToBool ( ) )
m_TemplateFlags | = ICmpObstructionManager : : FLAG_DELETE_UPON_CONSTRUCTION ;
2011-02-24 13:49:24 -08:00
m_Flags = m_TemplateFlags ;
if ( paramNode . GetChild ( " DisableBlockMovement " ) . ToBool ( ) )
2011-08-16 04:18:32 -07:00
m_Flags & = ( flags_t ) ( ~ ICmpObstructionManager : : FLAG_BLOCK_MOVEMENT ) ;
2011-02-24 13:49:24 -08:00
if ( paramNode . GetChild ( " DisableBlockPathfinding " ) . ToBool ( ) )
2011-08-16 04:18:32 -07:00
m_Flags & = ( flags_t ) ( ~ ICmpObstructionManager : : FLAG_BLOCK_PATHFINDING ) ;
2011-02-10 08:06:28 -08:00
2012-07-08 09:25:33 -07:00
if ( paramNode . GetChild ( " Unit " ) . IsOk ( ) )
{
m_Type = UNIT ;
2015-07-18 01:37:49 -07:00
CmpPtr < ICmpUnitMotion > cmpUnitMotion ( GetEntityHandle ( ) ) ;
if ( cmpUnitMotion )
m_Clearance = cmpUnitMotion - > GetUnitClearance ( ) ;
2012-07-08 09:25:33 -07:00
}
else if ( paramNode . GetChild ( " Static " ) . IsOk ( ) )
{
m_Type = STATIC ;
m_Size0 = paramNode . GetChild ( " Static " ) . GetChild ( " @width " ) . ToFixed ( ) ;
m_Size1 = paramNode . GetChild ( " Static " ) . GetChild ( " @depth " ) . ToFixed ( ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
ENSURE ( m_Size0 > minObstruction ) ;
ENSURE ( m_Size1 > minObstruction ) ;
2012-07-08 09:25:33 -07:00
}
else
{
m_Type = CLUSTER ;
CFixedVector2D max = CFixedVector2D ( fixed : : FromInt ( 0 ) , fixed : : FromInt ( 0 ) ) ;
CFixedVector2D min = CFixedVector2D ( fixed : : FromInt ( 0 ) , fixed : : FromInt ( 0 ) ) ;
2012-07-12 13:00:38 -07:00
const CParamNode : : ChildrenMap & clusterMap = paramNode . GetChild ( " Obstructions " ) . GetChildren ( ) ;
2012-07-08 09:25:33 -07:00
for ( CParamNode : : ChildrenMap : : const_iterator it = clusterMap . begin ( ) ; it ! = clusterMap . end ( ) ; + + it )
{
Shape b ;
b . size0 = it - > second . GetChild ( " @width " ) . ToFixed ( ) ;
b . size1 = it - > second . GetChild ( " @depth " ) . ToFixed ( ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
ENSURE ( b . size0 > minObstruction ) ;
ENSURE ( b . size1 > minObstruction ) ;
2012-07-12 13:00:38 -07:00
b . dx = it - > second . GetChild ( " @x " ) . ToFixed ( ) ;
b . dz = it - > second . GetChild ( " @z " ) . ToFixed ( ) ;
2012-07-08 09:25:33 -07:00
b . da = entity_angle_t : : FromInt ( 0 ) ;
b . flags = m_Flags ;
m_Shapes . push_back ( b ) ;
2017-01-19 18:25:19 -08:00
max . X = std : : max ( max . X , b . dx + b . size0 / 2 ) ;
max . Y = std : : max ( max . Y , b . dz + b . size1 / 2 ) ;
min . X = std : : min ( min . X , b . dx - b . size0 / 2 ) ;
min . Y = std : : min ( min . Y , b . dz - b . size1 / 2 ) ;
2012-07-08 09:25:33 -07:00
}
2017-01-19 18:25:19 -08:00
m_Size0 = fixed : : FromInt ( 2 ) . Multiply ( std : : max ( max . X , - min . X ) ) ;
m_Size1 = fixed : : FromInt ( 2 ) . Multiply ( std : : max ( max . Y , - min . Y ) ) ;
2012-07-08 09:25:33 -07:00
}
2011-02-10 08:06:28 -08:00
m_Active = paramNode . GetChild ( " Active " ) . ToBool ( ) ;
2012-08-01 14:38:13 -07:00
m_ControlPersist = paramNode . GetChild ( " ControlPersist " ) . IsOk ( ) ;
2010-03-17 16:13:21 -07:00
2011-08-16 04:18:32 -07:00
m_Tag = tag_t ( ) ;
2012-07-08 09:25:33 -07:00
if ( m_Type = = CLUSTER )
m_ClusterTags . clear ( ) ;
2010-04-29 16:36:05 -07:00
m_Moving = false ;
2010-09-03 02:55:14 -07:00
m_ControlGroup = GetEntityId ( ) ;
2012-05-05 12:22:22 -07:00
m_ControlGroup2 = INVALID_ENTITY ;
2010-01-29 13:13:18 -08:00
}
2011-01-16 06:08:38 -08:00
virtual void Deinit ( )
2010-01-29 13:13:18 -08:00
{
}
2012-07-08 09:25:33 -07:00
struct SerializeTag
{
template < typename S >
void operator ( ) ( S & serialize , const char * UNUSED ( name ) , tag_t & value )
{
serialize . NumberU32_Unbounded ( " tag " , value . n ) ;
}
} ;
2010-10-23 12:59:40 -07:00
template < typename S >
void SerializeCommon ( S & serialize )
2010-01-29 13:13:18 -08:00
{
2011-02-10 08:06:28 -08:00
serialize . Bool ( " active " , m_Active ) ;
2010-10-23 12:59:40 -07:00
serialize . Bool ( " moving " , m_Moving ) ;
serialize . NumberU32_Unbounded ( " control group " , m_ControlGroup ) ;
2012-05-05 12:22:22 -07:00
serialize . NumberU32_Unbounded ( " control group 2 " , m_ControlGroup2 ) ;
2010-10-23 12:59:40 -07:00
serialize . NumberU32_Unbounded ( " tag " , m_Tag . n ) ;
2011-02-24 13:49:24 -08:00
serialize . NumberU8_Unbounded ( " flags " , m_Flags ) ;
2012-07-08 09:25:33 -07:00
if ( m_Type = = CLUSTER )
SerializeVector < SerializeTag > ( ) ( serialize , " cluster tags " , m_ClusterTags ) ;
2015-07-18 01:37:49 -07:00
if ( m_Type = = UNIT )
serialize . NumberFixed_Unbounded ( " clearance " , m_Clearance ) ;
2010-01-29 13:13:18 -08:00
}
2010-10-23 12:59:40 -07:00
virtual void Serialize ( ISerializer & serialize )
{
SerializeCommon ( serialize ) ;
}
2011-01-16 06:08:38 -08:00
virtual void Deserialize ( const CParamNode & paramNode , IDeserializer & deserialize )
2010-01-29 13:13:18 -08:00
{
2011-01-16 06:08:38 -08:00
Init ( paramNode ) ;
2010-01-29 13:13:18 -08:00
2010-10-23 12:59:40 -07:00
SerializeCommon ( deserialize ) ;
2010-01-29 13:13:18 -08:00
}
2011-01-16 06:08:38 -08:00
virtual void HandleMessage ( const CMessage & msg , bool UNUSED ( global ) )
2010-01-29 13:13:18 -08:00
{
switch ( msg . GetType ( ) )
{
case MT_PositionChanged :
{
2010-03-17 16:13:21 -07:00
if ( ! m_Active )
break ;
2010-01-29 13:13:18 -08:00
const CMessagePositionChanged & data = static_cast < const CMessagePositionChanged & > ( msg ) ;
2010-07-04 10:19:38 -07:00
if ( ! data . inWorld & & ! m_Tag . valid ( ) )
2010-03-17 16:13:21 -07:00
break ; // nothing needs to change
2010-01-29 13:13:18 -08:00
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpObstructionManager )
2011-02-10 08:06:28 -08:00
break ; // error
2010-01-29 13:13:18 -08:00
2010-07-04 10:19:38 -07:00
if ( data . inWorld & & m_Tag . valid ( ) )
2010-01-29 13:13:18 -08:00
{
2010-03-17 16:13:21 -07:00
cmpObstructionManager - > MoveShape ( m_Tag , data . x , data . z , data . a ) ;
2012-07-08 09:25:33 -07:00
2015-07-18 01:37:49 -07:00
if ( m_Type = = CLUSTER )
2012-07-08 09:25:33 -07:00
{
for ( size_t i = 0 ; i < m_Shapes . size ( ) ; + + i )
{
Shape & b = m_Shapes [ i ] ;
fixed s , c ;
sincos_approx ( data . a , s , c ) ;
cmpObstructionManager - > MoveShape ( m_ClusterTags [ i ] , data . x + b . dx . Multiply ( c ) + b . dz . Multiply ( s ) , data . z + b . dz . Multiply ( c ) - b . dx . Multiply ( s ) , data . a + b . da ) ;
}
}
2010-01-29 13:13:18 -08:00
}
2010-07-04 10:19:38 -07:00
else if ( data . inWorld & & ! m_Tag . valid ( ) )
2010-01-29 13:13:18 -08:00
{
// Need to create a new pathfinder shape:
2010-04-29 16:36:05 -07:00
if ( m_Type = = STATIC )
2011-02-10 08:06:28 -08:00
m_Tag = cmpObstructionManager - > AddStaticShape ( GetEntityId ( ) ,
2012-05-05 12:22:22 -07:00
data . x , data . z , data . a , m_Size0 , m_Size1 , m_Flags , m_ControlGroup , m_ControlGroup2 ) ;
2012-07-08 09:25:33 -07:00
else if ( m_Type = = UNIT )
2011-02-10 08:06:28 -08:00
m_Tag = cmpObstructionManager - > AddUnitShape ( GetEntityId ( ) ,
2015-07-18 01:37:49 -07:00
data . x , data . z , m_Clearance , ( flags_t ) ( m_Flags | ( m_Moving ? ICmpObstructionManager : : FLAG_MOVING : 0 ) ) , m_ControlGroup ) ;
2012-07-08 09:25:33 -07:00
else
AddClusterShapes ( data . x , data . x , data . a ) ;
2010-01-29 13:13:18 -08:00
}
2010-07-04 10:19:38 -07:00
else if ( ! data . inWorld & & m_Tag . valid ( ) )
2010-01-29 13:13:18 -08:00
{
2010-03-17 16:13:21 -07:00
cmpObstructionManager - > RemoveShape ( m_Tag ) ;
2011-08-16 04:18:32 -07:00
m_Tag = tag_t ( ) ;
2012-07-08 09:25:33 -07:00
if ( m_Type = = CLUSTER )
RemoveClusterShapes ( ) ;
2010-01-29 13:13:18 -08:00
}
break ;
}
case MT_Destroy :
{
2010-07-04 10:19:38 -07:00
if ( m_Tag . valid ( ) )
2010-01-29 13:13:18 -08:00
{
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpObstructionManager )
2011-02-10 08:06:28 -08:00
break ; // error
2010-01-29 13:13:18 -08:00
2019-07-10 11:43:21 -07:00
// Deactivate the obstruction in case PositionChanged messages are sent after this.
m_Active = false ;
2010-03-17 16:13:21 -07:00
cmpObstructionManager - > RemoveShape ( m_Tag ) ;
2011-08-16 04:18:32 -07:00
m_Tag = tag_t ( ) ;
2012-07-08 09:25:33 -07:00
if ( m_Type = = CLUSTER )
RemoveClusterShapes ( ) ;
2010-01-29 13:13:18 -08:00
}
break ;
}
}
}
2010-03-17 16:13:21 -07:00
2011-02-10 08:06:28 -08:00
virtual void SetActive ( bool active )
{
if ( active & & ! m_Active )
{
m_Active = true ;
// Construct the obstruction shape
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpObstructionManager )
2011-02-10 08:06:28 -08:00
return ; // error
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpPosition > cmpPosition ( GetEntityHandle ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpPosition )
2011-02-10 08:06:28 -08:00
return ; // error
if ( ! cmpPosition - > IsInWorld ( ) )
return ; // don't need an obstruction
2012-05-05 12:22:22 -07:00
// TODO: code duplication from message handlers
2011-02-10 08:06:28 -08:00
CFixedVector2D pos = cmpPosition - > GetPosition2D ( ) ;
if ( m_Type = = STATIC )
m_Tag = cmpObstructionManager - > AddStaticShape ( GetEntityId ( ) ,
2012-05-05 12:22:22 -07:00
pos . X , pos . Y , cmpPosition - > GetRotation ( ) . Y , m_Size0 , m_Size1 , m_Flags , m_ControlGroup , m_ControlGroup2 ) ;
2012-07-08 09:25:33 -07:00
else if ( m_Type = = UNIT )
2011-02-10 08:06:28 -08:00
m_Tag = cmpObstructionManager - > AddUnitShape ( GetEntityId ( ) ,
2015-07-18 01:37:49 -07:00
pos . X , pos . Y , m_Clearance , ( flags_t ) ( m_Flags | ( m_Moving ? ICmpObstructionManager : : FLAG_MOVING : 0 ) ) , m_ControlGroup ) ;
2016-11-23 05:02:58 -08:00
else
2012-07-08 09:25:33 -07:00
AddClusterShapes ( pos . X , pos . Y , cmpPosition - > GetRotation ( ) . Y ) ;
2011-02-10 08:06:28 -08:00
}
else if ( ! active & & m_Active )
{
m_Active = false ;
// Delete the obstruction shape
2012-05-05 12:22:22 -07:00
// TODO: code duplication from message handlers
2011-02-10 08:06:28 -08:00
if ( m_Tag . valid ( ) )
{
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpObstructionManager )
2011-02-10 08:06:28 -08:00
return ; // error
cmpObstructionManager - > RemoveShape ( m_Tag ) ;
2011-08-16 04:18:32 -07:00
m_Tag = tag_t ( ) ;
2012-07-08 09:25:33 -07:00
if ( m_Type = = CLUSTER )
RemoveClusterShapes ( ) ;
2011-02-10 08:06:28 -08:00
}
}
// else we didn't change the active status
}
2012-07-08 09:25:33 -07:00
virtual void SetDisableBlockMovementPathfinding ( bool movementDisabled , bool pathfindingDisabled , int32_t shape )
2011-02-24 13:49:24 -08:00
{
2012-07-08 09:25:33 -07:00
flags_t * flags = NULL ;
if ( shape = = - 1 )
flags = & m_Flags ;
else if ( m_Type = = CLUSTER & & shape < ( int32_t ) m_Shapes . size ( ) )
flags = & m_Shapes [ shape ] . flags ;
2011-02-24 13:49:24 -08:00
else
2012-07-08 09:25:33 -07:00
return ; // error
// Remove the blocking / pathfinding flags or
// Add the blocking / pathfinding flags if the template had enabled them
if ( movementDisabled )
* flags & = ( flags_t ) ( ~ ICmpObstructionManager : : FLAG_BLOCK_MOVEMENT ) ;
else
* flags | = ( flags_t ) ( m_TemplateFlags & ICmpObstructionManager : : FLAG_BLOCK_MOVEMENT ) ;
if ( pathfindingDisabled )
* flags & = ( flags_t ) ( ~ ICmpObstructionManager : : FLAG_BLOCK_PATHFINDING ) ;
else
* flags | = ( flags_t ) ( m_TemplateFlags & ICmpObstructionManager : : FLAG_BLOCK_PATHFINDING ) ;
2011-02-24 13:49:24 -08:00
// Reset the shape with the new flags (kind of inefficiently - we
// should have a ICmpObstructionManager::SetFlags function or something)
if ( m_Active )
{
SetActive ( false ) ;
SetActive ( true ) ;
}
}
2017-01-19 18:25:19 -08:00
virtual bool GetBlockMovementFlag ( ) const
2011-05-13 13:32:41 -07:00
{
return ( m_TemplateFlags & ICmpObstructionManager : : FLAG_BLOCK_MOVEMENT ) ! = 0 ;
}
2019-09-20 00:45:55 -07:00
virtual EObstructionType GetObstructionType ( ) const
{
return m_Type ;
}
2017-01-19 18:25:19 -08:00
virtual ICmpObstructionManager : : tag_t GetObstruction ( ) const
2010-03-17 16:13:21 -07:00
{
2010-04-29 16:36:05 -07:00
return m_Tag ;
}
2010-03-17 16:13:21 -07:00
2017-01-19 18:25:19 -08:00
virtual bool GetPreviousObstructionSquare ( ICmpObstructionManager : : ObstructionSquare & out ) const
2013-12-30 08:07:19 -08:00
{
return GetObstructionSquare ( out , true ) ;
}
2017-01-19 18:25:19 -08:00
virtual bool GetObstructionSquare ( ICmpObstructionManager : : ObstructionSquare & out ) const
2013-12-30 08:07:19 -08:00
{
return GetObstructionSquare ( out , false ) ;
}
2017-01-19 18:25:19 -08:00
virtual bool GetObstructionSquare ( ICmpObstructionManager : : ObstructionSquare & out , bool previousPosition ) const
2011-02-10 08:06:28 -08:00
{
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpPosition > cmpPosition ( GetEntityHandle ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpPosition )
2011-02-10 08:06:28 -08:00
return false ; // error
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpObstructionManager )
2011-02-10 08:06:28 -08:00
return false ; // error
if ( ! cmpPosition - > IsInWorld ( ) )
return false ; // no obstruction square
2013-12-30 08:07:19 -08:00
CFixedVector2D pos ;
if ( previousPosition )
pos = cmpPosition - > GetPreviousPosition2D ( ) ;
else
pos = cmpPosition - > GetPosition2D ( ) ;
2015-04-14 14:33:43 -07:00
if ( m_Type = = UNIT )
2015-07-18 01:37:49 -07:00
out = cmpObstructionManager - > GetUnitShapeObstruction ( pos . X , pos . Y , m_Clearance ) ;
2012-07-08 09:25:33 -07:00
else
out = cmpObstructionManager - > GetStaticShapeObstruction ( pos . X , pos . Y , cmpPosition - > GetRotation ( ) . Y , m_Size0 , m_Size1 ) ;
2011-02-10 08:06:28 -08:00
return true ;
}
2017-01-19 18:25:19 -08:00
virtual entity_pos_t GetUnitRadius ( ) const
2010-04-29 16:36:05 -07:00
{
if ( m_Type = = UNIT )
2015-07-18 01:37:49 -07:00
return m_Clearance ;
2010-04-29 16:36:05 -07:00
else
return entity_pos_t : : Zero ( ) ;
}
2017-01-19 18:25:19 -08:00
virtual entity_pos_t GetSize ( ) const
2015-04-14 14:33:43 -07:00
{
if ( m_Type = = UNIT )
2015-07-18 01:37:49 -07:00
return m_Clearance ;
2015-04-14 14:33:43 -07:00
else
return CFixedVector2D ( m_Size0 / 2 , m_Size1 / 2 ) . Length ( ) ;
}
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
virtual void SetUnitClearance ( const entity_pos_t & clearance )
{
if ( m_Type = = UNIT )
m_Clearance = clearance ;
}
2017-01-19 18:25:19 -08:00
virtual bool IsControlPersistent ( ) const
2012-08-01 14:38:13 -07:00
{
return m_ControlPersist ;
}
2016-11-23 06:09:58 -08:00
2018-01-21 18:34:46 -08:00
virtual bool CheckShorePlacement ( ) const
{
ICmpObstructionManager : : ObstructionSquare s ;
if ( ! GetObstructionSquare ( s ) )
return false ;
CFixedVector2D front = CFixedVector2D ( s . x , s . z ) + s . v . Multiply ( s . hh ) ;
CFixedVector2D back = CFixedVector2D ( s . x , s . z ) - s . v . Multiply ( s . hh ) ;
CmpPtr < ICmpTerrain > cmpTerrain ( GetSystemEntity ( ) ) ;
CmpPtr < ICmpWaterManager > cmpWaterManager ( GetSystemEntity ( ) ) ;
if ( ! cmpTerrain | | ! cmpWaterManager )
return false ;
// Keep these constants in agreement with the pathfinder.
return cmpWaterManager - > GetWaterLevel ( front . X , front . Y ) - cmpTerrain - > GetGroundLevel ( front . X , front . Y ) > fixed : : FromInt ( 1 ) & &
cmpWaterManager - > GetWaterLevel ( back . X , back . Y ) - cmpTerrain - > GetGroundLevel ( back . X , back . Y ) < fixed : : FromInt ( 2 ) ;
}
2017-01-19 18:25:19 -08:00
virtual EFoundationCheck CheckFoundation ( const std : : string & className ) const
2013-07-07 15:44:47 -07:00
{
return CheckFoundation ( className , false ) ;
}
2017-01-19 18:25:19 -08:00
virtual EFoundationCheck CheckFoundation ( const std : : string & className , bool onlyCenterPoint ) const
2011-02-10 08:06:28 -08:00
{
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpPosition > cmpPosition ( GetEntityHandle ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpPosition )
2013-02-23 16:12:41 -08:00
return FOUNDATION_CHECK_FAIL_ERROR ; // error
2011-02-10 08:06:28 -08:00
if ( ! cmpPosition - > IsInWorld ( ) )
2013-02-23 16:12:41 -08:00
return FOUNDATION_CHECK_FAIL_NO_OBSTRUCTION ; // no obstruction
2011-02-10 08:06:28 -08:00
CFixedVector2D pos = cmpPosition - > GetPosition2D ( ) ;
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpPathfinder > cmpPathfinder ( GetSystemEntity ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpPathfinder )
2013-02-23 16:12:41 -08:00
return FOUNDATION_CHECK_FAIL_ERROR ; // error
2011-02-10 08:06:28 -08:00
2012-05-05 12:22:22 -07:00
// required precondition to use SkipControlGroupsRequireFlagObstructionFilter
if ( m_ControlGroup = = INVALID_ENTITY )
{
2015-01-22 12:31:30 -08:00
LOGERROR ( " [CmpObstruction] Cannot test for foundation obstructions; primary control group must be valid " ) ;
2013-02-23 16:12:41 -08:00
return FOUNDATION_CHECK_FAIL_ERROR ;
2012-05-05 12:22:22 -07:00
}
2011-08-06 01:11:05 -07:00
// Get passability class
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
pass_class_t passClass = cmpPathfinder - > GetPassabilityClass ( className ) ;
2011-08-06 01:11:05 -07:00
2012-05-05 12:22:22 -07:00
// Ignore collisions within the same control group, or with other non-foundation-blocking shapes.
2016-11-23 05:02:58 -08:00
// Note that, since the control group for each entity defaults to the entity's ID, this is typically
2012-05-05 12:22:22 -07:00
// equivalent to only ignoring the entity's own shape and other non-foundation-blocking shapes.
SkipControlGroupsRequireFlagObstructionFilter filter ( m_ControlGroup , m_ControlGroup2 ,
ICmpObstructionManager : : FLAG_BLOCK_FOUNDATION ) ;
2011-02-10 08:06:28 -08:00
2013-02-23 16:12:41 -08:00
if ( m_Type = = UNIT )
2015-07-18 01:37:49 -07:00
return cmpPathfinder - > CheckUnitPlacement ( filter , pos . X , pos . Y , m_Clearance , passClass , onlyCenterPoint ) ;
2013-02-23 16:12:41 -08:00
else
2013-07-07 15:44:47 -07:00
return cmpPathfinder - > CheckBuildingPlacement ( filter , pos . X , pos . Y , cmpPosition - > GetRotation ( ) . Y , m_Size0 , m_Size1 , GetEntityId ( ) , passClass , onlyCenterPoint ) ;
2011-02-10 08:06:28 -08:00
}
2017-01-19 18:25:19 -08:00
virtual bool CheckDuplicateFoundation ( ) const
2012-08-03 09:36:40 -07:00
{
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpPosition > cmpPosition ( GetEntityHandle ( ) ) ;
2012-08-03 09:36:40 -07:00
if ( ! cmpPosition )
return false ; // error
if ( ! cmpPosition - > IsInWorld ( ) )
return false ; // no obstruction
CFixedVector2D pos = cmpPosition - > GetPosition2D ( ) ;
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-08-03 09:36:40 -07:00
if ( ! cmpObstructionManager )
return false ; // error
// required precondition to use SkipControlGroupsRequireFlagObstructionFilter
if ( m_ControlGroup = = INVALID_ENTITY )
{
2015-01-22 12:31:30 -08:00
LOGERROR ( " [CmpObstruction] Cannot test for foundation obstructions; primary control group must be valid " ) ;
2012-08-03 09:36:40 -07:00
return false ;
}
// Ignore collisions with entities unless they block foundations and match both control groups.
SkipTagRequireControlGroupsAndFlagObstructionFilter filter ( m_Tag , m_ControlGroup , m_ControlGroup2 ,
ICmpObstructionManager : : FLAG_BLOCK_FOUNDATION ) ;
if ( m_Type = = UNIT )
2015-07-18 01:37:49 -07:00
return ! cmpObstructionManager - > TestUnitShape ( filter , pos . X , pos . Y , m_Clearance , NULL ) ;
2012-08-03 09:36:40 -07:00
else
2013-07-07 15:44:47 -07:00
return ! cmpObstructionManager - > TestStaticShape ( filter , pos . X , pos . Y , cmpPosition - > GetRotation ( ) . Y , m_Size0 , m_Size1 , NULL ) ;
2016-11-23 05:02:58 -08:00
}
2012-08-03 09:36:40 -07:00
2018-03-26 08:18:53 -07:00
virtual std : : vector < entity_id_t > GetEntitiesByFlags ( flags_t flags ) const
2010-04-29 16:36:05 -07:00
{
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
std : : vector < entity_id_t > ret ;
2010-03-17 16:13:21 -07:00
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( ! cmpObstructionManager )
2011-02-10 08:06:28 -08:00
return ret ; // error
2010-03-17 16:13:21 -07:00
2012-08-09 12:06:01 -07:00
// Ignore collisions within the same control group, or with other shapes that don't match the filter.
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
// Note that, since the control group for each entity defaults to the entity's ID, this is typically
2012-08-09 12:06:01 -07:00
// equivalent to only ignoring the entity's own shape and other shapes that don't match the filter.
2016-04-06 10:36:47 -07:00
SkipControlGroupsRequireFlagObstructionFilter filter ( false , m_ControlGroup , m_ControlGroup2 , flags ) ;
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 11:58:24 -07:00
ICmpObstructionManager : : ObstructionSquare square ;
if ( ! GetObstructionSquare ( square ) )
return ret ; // error
2018-03-26 08:18:53 -07:00
cmpObstructionManager - > GetUnitsOnObstruction ( square , ret , filter , false ) ;
cmpObstructionManager - > GetStaticObstructionsOnObstruction ( square , ret , filter ) ;
2010-03-17 16:13:21 -07:00
2011-02-10 08:06:28 -08:00
return ret ;
2010-03-17 16:13:21 -07:00
}
2010-09-03 02:55:14 -07:00
2018-03-26 08:18:53 -07:00
virtual std : : vector < entity_id_t > GetEntitiesBlockingConstruction ( ) const
2018-03-20 18:44:15 -07:00
{
2018-03-26 08:18:53 -07:00
return GetEntitiesByFlags ( ICmpObstructionManager : : FLAG_BLOCK_CONSTRUCTION ) ;
}
2018-03-20 18:44:15 -07:00
2018-03-26 08:18:53 -07:00
virtual std : : vector < entity_id_t > GetEntitiesDeletedUponConstruction ( ) const
{
return GetEntitiesByFlags ( ICmpObstructionManager : : FLAG_DELETE_UPON_CONSTRUCTION ) ;
2018-03-20 18:44:15 -07:00
}
2010-09-03 02:55:14 -07:00
virtual void SetMovingFlag ( bool enabled )
{
m_Moving = enabled ;
if ( m_Tag . valid ( ) & & m_Type = = UNIT )
{
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( cmpObstructionManager )
2010-09-03 02:55:14 -07:00
cmpObstructionManager - > SetUnitMovingFlag ( m_Tag , m_Moving ) ;
}
}
virtual void SetControlGroup ( entity_id_t group )
{
m_ControlGroup = group ;
2012-05-05 12:22:22 -07:00
UpdateControlGroups ( ) ;
}
2010-09-03 02:55:14 -07:00
2012-05-05 12:22:22 -07:00
virtual void SetControlGroup2 ( entity_id_t group2 )
{
m_ControlGroup2 = group2 ;
UpdateControlGroups ( ) ;
}
2017-01-19 18:25:19 -08:00
virtual entity_id_t GetControlGroup ( ) const
2012-05-05 12:22:22 -07:00
{
return m_ControlGroup ;
}
2017-01-19 18:25:19 -08:00
virtual entity_id_t GetControlGroup2 ( ) const
2012-05-05 12:22:22 -07:00
{
return m_ControlGroup2 ;
}
void UpdateControlGroups ( )
{
if ( m_Tag . valid ( ) )
2010-09-03 02:55:14 -07:00
{
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-02-07 18:46:15 -08:00
if ( cmpObstructionManager )
2012-05-05 12:22:22 -07:00
{
if ( m_Type = = UNIT )
{
cmpObstructionManager - > SetUnitControlGroup ( m_Tag , m_ControlGroup ) ;
}
else if ( m_Type = = STATIC )
{
cmpObstructionManager - > SetStaticControlGroup ( m_Tag , m_ControlGroup , m_ControlGroup2 ) ;
}
2012-07-08 09:25:33 -07:00
else
{
cmpObstructionManager - > SetStaticControlGroup ( m_Tag , m_ControlGroup , m_ControlGroup2 ) ;
for ( size_t i = 0 ; i < m_ClusterTags . size ( ) ; + + i )
{
cmpObstructionManager - > SetStaticControlGroup ( m_ClusterTags [ i ] , m_ControlGroup , m_ControlGroup2 ) ;
}
}
}
}
}
2017-01-19 18:25:19 -08:00
void ResolveFoundationCollisions ( ) const
2012-08-01 14:38:13 -07:00
{
if ( m_Type = = UNIT )
return ;
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-08-01 14:38:13 -07:00
if ( ! cmpObstructionManager )
return ;
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpPosition > cmpPosition ( GetEntityHandle ( ) ) ;
2012-08-01 14:38:13 -07:00
if ( ! cmpPosition )
return ; // error
if ( ! cmpPosition - > IsInWorld ( ) )
return ; // no obstruction
CFixedVector2D pos = cmpPosition - > GetPosition2D ( ) ;
// Ignore collisions within the same control group, or with other non-foundation-blocking shapes.
2016-11-23 05:02:58 -08:00
// Note that, since the control group for each entity defaults to the entity's ID, this is typically
2012-08-01 14:38:13 -07:00
// equivalent to only ignoring the entity's own shape and other non-foundation-blocking shapes.
SkipControlGroupsRequireFlagObstructionFilter filter ( m_ControlGroup , m_ControlGroup2 ,
ICmpObstructionManager : : FLAG_BLOCK_FOUNDATION ) ;
std : : vector < entity_id_t > collisions ;
if ( cmpObstructionManager - > TestStaticShape ( filter , pos . X , pos . Y , cmpPosition - > GetRotation ( ) . Y , m_Size0 , m_Size1 , & collisions ) )
{
std : : vector < entity_id_t > persistentEnts , normalEnts ;
if ( m_ControlPersist )
persistentEnts . push_back ( m_ControlGroup ) ;
else
normalEnts . push_back ( GetEntityId ( ) ) ;
for ( std : : vector < entity_id_t > : : iterator it = collisions . begin ( ) ; it ! = collisions . end ( ) ; + + it )
{
entity_id_t ent = * it ;
if ( ent = = INVALID_ENTITY )
continue ;
CmpPtr < ICmpObstruction > cmpObstruction ( GetSimContext ( ) , ent ) ;
if ( ! cmpObstruction - > IsControlPersistent ( ) )
normalEnts . push_back ( ent ) ;
else
persistentEnts . push_back ( cmpObstruction - > GetControlGroup ( ) ) ;
}
// The collision can't be resolved without usable persistent control groups.
2013-05-21 15:11:47 -07:00
if ( persistentEnts . empty ( ) )
2012-08-01 14:38:13 -07:00
return ;
// Attempt to replace colliding entities' control groups with a persistent one.
for ( std : : vector < entity_id_t > : : iterator it = normalEnts . begin ( ) ; it ! = normalEnts . end ( ) ; + + it )
{
entity_id_t ent = * it ;
CmpPtr < ICmpObstruction > cmpObstruction ( GetSimContext ( ) , ent ) ;
for ( std : : vector < entity_id_t > : : iterator it = persistentEnts . begin ( ) ; it ! = persistentEnts . end ( ) ; + + it )
{
entity_id_t persistent = * it ;
entity_id_t group = cmpObstruction - > GetControlGroup ( ) ;
// Only clobber 'default' control groups.
if ( group = = ent )
cmpObstruction - > SetControlGroup ( persistent ) ;
else if ( cmpObstruction - > GetControlGroup2 ( ) = = INVALID_ENTITY & & group ! = persistent )
cmpObstruction - > SetControlGroup2 ( persistent ) ;
}
}
}
}
2012-07-08 09:25:33 -07:00
protected :
inline void AddClusterShapes ( entity_pos_t x , entity_pos_t z , entity_angle_t a )
{
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-07-08 09:25:33 -07:00
if ( ! cmpObstructionManager )
return ; // error
flags_t flags = m_Flags ;
// Disable block movement and block pathfinding for the obstruction shape
flags & = ( flags_t ) ( ~ ICmpObstructionManager : : FLAG_BLOCK_MOVEMENT ) ;
flags & = ( flags_t ) ( ~ ICmpObstructionManager : : FLAG_BLOCK_PATHFINDING ) ;
2016-11-23 06:09:58 -08:00
2012-07-08 09:25:33 -07:00
m_Tag = cmpObstructionManager - > AddStaticShape ( GetEntityId ( ) ,
x , z , a , m_Size0 , m_Size1 , flags , m_ControlGroup , m_ControlGroup2 ) ;
fixed s , c ;
sincos_approx ( a , s , c ) ;
for ( size_t i = 0 ; i < m_Shapes . size ( ) ; + + i )
{
Shape & b = m_Shapes [ i ] ;
tag_t tag = cmpObstructionManager - > AddStaticShape ( GetEntityId ( ) ,
x + b . dx . Multiply ( c ) + b . dz . Multiply ( s ) , z + b . dz . Multiply ( c ) - b . dx . Multiply ( s ) , a + b . da , b . size0 , b . size1 , b . flags , m_ControlGroup , m_ControlGroup2 ) ;
2016-11-23 06:09:58 -08:00
m_ClusterTags . push_back ( tag ) ;
2012-07-08 09:25:33 -07:00
}
}
inline void RemoveClusterShapes ( )
{
2013-09-11 13:41:53 -07:00
CmpPtr < ICmpObstructionManager > cmpObstructionManager ( GetSystemEntity ( ) ) ;
2012-07-08 09:25:33 -07:00
if ( ! cmpObstructionManager )
return ; // error
for ( size_t i = 0 ; i < m_ClusterTags . size ( ) ; + + i )
{
if ( m_ClusterTags [ i ] . valid ( ) )
{
cmpObstructionManager - > RemoveShape ( m_ClusterTags [ i ] ) ;
2012-05-05 12:22:22 -07:00
}
2010-09-03 02:55:14 -07:00
}
2012-07-08 09:25:33 -07:00
m_ClusterTags . clear ( ) ;
2010-09-03 02:55:14 -07:00
}
2010-01-29 13:13:18 -08:00
} ;
REGISTER_COMPONENT_TYPE ( Obstruction )