You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
550 lines
16 KiB
550 lines
16 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "physics_prop_statue.h"
|
|
#include "baseanimating.h"
|
|
#include "studio.h"
|
|
#include "bone_setup.h"
|
|
#include "EntityFreezing.h"
|
|
//#include "particle_parse.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Networking
|
|
//-----------------------------------------------------------------------------
|
|
LINK_ENTITY_TO_CLASS( physics_prop_statue, CStatueProp );
|
|
|
|
IMPLEMENT_SERVERCLASS_ST( CStatueProp, DT_StatueProp )
|
|
SendPropEHandle( SENDINFO( m_hInitBaseAnimating ) ),
|
|
SendPropBool( SENDINFO( m_bShatter ) ),
|
|
SendPropInt( SENDINFO( m_nShatterFlags ), 3 ),
|
|
SendPropVector( SENDINFO( m_vShatterPosition ) ),
|
|
SendPropVector( SENDINFO( m_vShatterForce ) ),
|
|
END_SEND_TABLE()
|
|
|
|
BEGIN_DATADESC( CStatueProp )
|
|
DEFINE_FIELD( m_hInitBaseAnimating, FIELD_EHANDLE ),
|
|
DEFINE_FIELD( m_bShatter, FIELD_BOOLEAN ),
|
|
DEFINE_FIELD( m_nShatterFlags, FIELD_INTEGER ),
|
|
DEFINE_FIELD( m_vShatterPosition, FIELD_VECTOR ),
|
|
DEFINE_FIELD( m_vShatterForce, FIELD_VECTOR ),
|
|
|
|
DEFINE_THINKFUNC( CollisionPartnerThink ),
|
|
END_DATADESC()
|
|
|
|
ConVarRef *s_vcollide_wireframe = NULL;
|
|
|
|
|
|
CStatueProp::CStatueProp( void )
|
|
{
|
|
static ConVarRef vcollide_wireframe( "vcollide_wireframe" );
|
|
s_vcollide_wireframe = &vcollide_wireframe;
|
|
m_pInitOBBs = NULL;
|
|
}
|
|
|
|
void CStatueProp::Spawn( void )
|
|
{
|
|
// Make it breakable
|
|
SetBreakableModel( MAKE_STRING( "ConcreteChunks" ) );
|
|
SetBreakableCount( 6 );
|
|
SetHealth( 5 );
|
|
|
|
BaseClass::Spawn();
|
|
|
|
m_flFrozen = 1.0f;
|
|
}
|
|
|
|
void CStatueProp::Precache( void )
|
|
{
|
|
}
|
|
|
|
bool CStatueProp::CreateVPhysics( void )
|
|
{
|
|
if ( m_pInitOBBs )
|
|
{
|
|
return CreateVPhysicsFromOBBs( m_hInitBaseAnimating );
|
|
}
|
|
else
|
|
{
|
|
if ( !CreateVPhysicsFromHitBoxes( m_hInitBaseAnimating ) )
|
|
{
|
|
// Init model didn't work out, so just use our own
|
|
return CreateVPhysicsFromHitBoxes( this );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void CStatueProp::VPhysicsUpdate( IPhysicsObject *pPhysics )
|
|
{
|
|
BaseClass::VPhysicsUpdate( pPhysics );
|
|
|
|
if ( s_vcollide_wireframe->GetBool() )
|
|
{
|
|
const CPhysCollide *pCollide = pPhysics->GetCollide();
|
|
|
|
Vector vecOrigin;
|
|
QAngle angAngles;
|
|
|
|
pPhysics->GetPosition( &vecOrigin, &angAngles );
|
|
|
|
if ( pCollide )
|
|
{
|
|
Vector *outVerts;
|
|
int vertCount = physcollision->CreateDebugMesh( pCollide, &outVerts );
|
|
int triCount = vertCount / 3;
|
|
int vert = 0;
|
|
|
|
VMatrix tmp = SetupMatrixOrgAngles( vecOrigin, angAngles );
|
|
int i;
|
|
for ( i = 0; i < vertCount; i++ )
|
|
{
|
|
outVerts[i] = tmp.VMul4x3( outVerts[i] );
|
|
}
|
|
|
|
for ( i = 0; i < triCount; i++ )
|
|
{
|
|
NDebugOverlay::Line( outVerts[ vert + 0 ], outVerts[ vert + 1 ], 0, 255, 255, false, 0.0f );
|
|
NDebugOverlay::Line( outVerts[ vert + 1 ], outVerts[ vert + 2 ], 0, 255, 255, false, 0.0f );
|
|
NDebugOverlay::Line( outVerts[ vert + 2 ], outVerts[ vert + 0 ], 0, 255, 255, false, 0.0f );
|
|
vert += 3;
|
|
}
|
|
|
|
physcollision->DestroyDebugMesh( vertCount, outVerts );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStatueProp::ComputeWorldSpaceSurroundingBox( Vector *pMins, Vector *pMaxs )
|
|
{
|
|
CBaseAnimating *pBaseAnimating = m_hInitBaseAnimating;
|
|
|
|
if ( pBaseAnimating )
|
|
{
|
|
pBaseAnimating->CollisionProp()->WorldSpaceSurroundingBounds( pMins, pMaxs );
|
|
return;
|
|
}
|
|
|
|
CollisionProp()->WorldSpaceSurroundingBounds( pMins, pMaxs );
|
|
}
|
|
|
|
bool CStatueProp::TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr )
|
|
{
|
|
IPhysicsObject *pPhysObject = VPhysicsGetObject();
|
|
|
|
if ( pPhysObject )
|
|
{
|
|
Vector vecPosition;
|
|
QAngle vecAngles;
|
|
pPhysObject->GetPosition( &vecPosition, &vecAngles );
|
|
const CPhysCollide *pScaledCollide = pPhysObject->GetCollide();
|
|
physcollision->TraceBox( ray, pScaledCollide, vecPosition, vecAngles, &tr );
|
|
|
|
return tr.DidHit();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int CStatueProp::OnTakeDamage( const CTakeDamageInfo &info )
|
|
{
|
|
return BaseClass::OnTakeDamage( info );
|
|
}
|
|
|
|
void CStatueProp::Event_Killed( const CTakeDamageInfo &info )
|
|
{
|
|
IPhysicsObject *pPhysics = VPhysicsGetObject();
|
|
|
|
if ( pPhysics && !pPhysics->IsMoveable() )
|
|
{
|
|
pPhysics->EnableMotion( true );
|
|
VPhysicsTakeDamage( info );
|
|
}
|
|
|
|
m_nShatterFlags = 0; // If you have some flags to network for the shatter effect, put them here!
|
|
m_vShatterPosition = info.GetDamagePosition();
|
|
m_vShatterForce = info.GetDamageForce();
|
|
m_bShatter = true;
|
|
|
|
// Skip over breaking code!
|
|
//Break( info.GetInflictor(), info );
|
|
//BaseClass::Event_Killed( info );
|
|
|
|
// FIXME: Short delay before we actually remove so that the client statue gets a network update before we need it
|
|
// This isn't a reliable way to do this and needs to be rethought.
|
|
AddSolidFlags( FSOLID_NOT_SOLID );
|
|
|
|
SetNextThink( gpGlobals->curtime + 0.2f );
|
|
SetThink( &CBaseEntity::SUB_Remove );
|
|
}
|
|
|
|
void CStatueProp::Freeze( float flFreezeAmount, CBaseEntity *pFreezer, Ray_t *pFreezeRay )
|
|
{
|
|
// Can't freeze a statue
|
|
TakeDamage( CTakeDamageInfo( pFreezer, pFreezer, 1, DMG_GENERIC ) );
|
|
}
|
|
|
|
void CStatueProp::CollisionPartnerThink( void )
|
|
{
|
|
CBaseAnimating *pBaseAnimating = m_hInitBaseAnimating;
|
|
if ( !pBaseAnimating )
|
|
{
|
|
// Our partner died, I have no reason to live!
|
|
UTIL_Remove( this );
|
|
}
|
|
|
|
if ( GetHealth() <= 0 )
|
|
{
|
|
// Reset health here in case it was tweaked by the model parse
|
|
SetHealth( 5 );
|
|
m_takedamage = DAMAGE_YES;
|
|
}
|
|
|
|
SetNextThink( gpGlobals->curtime + 1.0f );
|
|
}
|
|
|
|
|
|
bool CStatueProp::CreateVPhysicsFromHitBoxes( CBaseAnimating *pInitBaseAnimating )
|
|
{
|
|
if ( !pInitBaseAnimating )
|
|
return false;
|
|
|
|
// Use the current animation sequence and cycle
|
|
CopyAnimationDataFrom( pInitBaseAnimating );
|
|
|
|
// Copy over any render color
|
|
color24 colorRender = pInitBaseAnimating->GetRenderColor();
|
|
SetRenderColor( colorRender.r, colorRender.g, colorRender.b );
|
|
SetRenderAlpha( pInitBaseAnimating->GetRenderAlpha() );
|
|
|
|
// Get hitbox data
|
|
CStudioHdr *pStudioHdr = GetModelPtr();
|
|
if ( !pStudioHdr )
|
|
return false;
|
|
|
|
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet );
|
|
if ( !set )
|
|
return false;
|
|
|
|
Vector position;
|
|
QAngle angles;
|
|
|
|
// Make enough pointers to convexes for each hitbox
|
|
CPhysConvex **ppConvex = new CPhysConvex*[ set->numhitboxes ];
|
|
|
|
float flTotalVolume = 0.0f;
|
|
float flTotalSurfaceArea = 0.0f;
|
|
|
|
for ( int i = 0; i < set->numhitboxes; i++ )
|
|
{
|
|
// Get the hitbox info
|
|
mstudiobbox_t *pbox = set->pHitbox( i );
|
|
GetBonePosition( pbox->bone, position, angles );
|
|
|
|
// Accumulate volume and area
|
|
Vector flDimentions = pbox->bbmax - pbox->bbmin;
|
|
flTotalVolume += flDimentions.x * flDimentions.y * flDimentions.z;
|
|
flTotalSurfaceArea += 2.0f * ( flDimentions.x * flDimentions.y + flDimentions.x * flDimentions.z + flDimentions.y * flDimentions.z );
|
|
|
|
// Get angled min and max extents
|
|
Vector vecMins, vecMaxs;
|
|
VectorRotate( pbox->bbmin, angles, vecMins );
|
|
VectorRotate( pbox->bbmax, angles, vecMaxs );
|
|
|
|
// Get the corners in world space
|
|
Vector vecMinCorner = position + vecMins;
|
|
Vector vecMaxCorner = position + vecMaxs;
|
|
|
|
// Get the normals of the hitbox in world space
|
|
Vector vecForward, vecRight, vecUp;
|
|
AngleVectors( angles, &vecForward, &vecRight, &vecUp );
|
|
vecRight = -vecRight;
|
|
|
|
// Convert corners and normals to local space
|
|
Vector vecCornerLocal[ 2 ];
|
|
Vector vecNormalLocal[ 3 ];
|
|
|
|
matrix3x4_t matToWorld = EntityToWorldTransform();
|
|
VectorITransform( vecMaxCorner, matToWorld, vecCornerLocal[ 0 ] );
|
|
VectorITransform( vecMinCorner, matToWorld, vecCornerLocal[ 1 ] );
|
|
VectorIRotate( vecForward, matToWorld, vecNormalLocal[ 0 ] );
|
|
VectorIRotate( vecRight, matToWorld, vecNormalLocal[ 1 ] );
|
|
VectorIRotate( vecUp, matToWorld, vecNormalLocal[ 2 ] );
|
|
|
|
// Create 6 planes from the local oriented hit box data
|
|
float pPlanes[ 4 * 6 ];
|
|
|
|
for ( int iPlane = 0; iPlane < 6; ++iPlane )
|
|
{
|
|
int iPlaneMod2 = iPlane % 2;
|
|
int iPlaneDiv2 = iPlane / 2;
|
|
bool bOdd = ( iPlaneMod2 == 1 );
|
|
|
|
// Plane Normal
|
|
pPlanes[ iPlane * 4 + 0 ] = vecNormalLocal[ iPlaneDiv2 ].x * ( bOdd ? -1.0f : 1.0f );
|
|
pPlanes[ iPlane * 4 + 1 ] = vecNormalLocal[ iPlaneDiv2 ].y * ( bOdd ? -1.0f : 1.0f );
|
|
pPlanes[ iPlane * 4 + 2 ] = vecNormalLocal[ iPlaneDiv2 ].z * ( bOdd ? -1.0f : 1.0f );
|
|
|
|
// Plane D
|
|
pPlanes[ iPlane * 4 + 3 ] = ( vecCornerLocal[ iPlaneMod2 ].x * vecNormalLocal[ iPlaneDiv2 ].x +
|
|
vecCornerLocal[ iPlaneMod2 ].y * vecNormalLocal[ iPlaneDiv2 ].y +
|
|
vecCornerLocal[ iPlaneMod2 ].z * vecNormalLocal[ iPlaneDiv2 ].z ) * ( bOdd ? -1.0f : 1.0f );
|
|
}
|
|
|
|
// Create convex from the intersection of these planes
|
|
ppConvex[ i ] = physcollision->ConvexFromPlanes( pPlanes, 6, 0.0f );
|
|
}
|
|
|
|
// Make a single collide out of the group of convex boxes
|
|
CPhysCollide *pPhysCollide = physcollision->ConvertConvexToCollide( ppConvex, set->numhitboxes );
|
|
|
|
delete[] ppConvex;
|
|
|
|
// Create the physics object
|
|
objectparams_t params = g_PhysDefaultObjectParams;
|
|
params.pGameData = static_cast<void *>( this );
|
|
|
|
int nMaterialIndex = physprops->GetSurfaceIndex( "ice" ); // use ice material
|
|
|
|
IPhysicsObject* p = physenv->CreatePolyObject( pPhysCollide, nMaterialIndex, GetAbsOrigin(), GetAbsAngles(), ¶ms );
|
|
Assert( p != NULL );
|
|
|
|
// Set velocity
|
|
Vector vecInitialVelocity = pInitBaseAnimating->GetAbsVelocity();
|
|
p->SetVelocity( &vecInitialVelocity, NULL );
|
|
|
|
// Compute mass
|
|
float flMass;
|
|
float flDensity, flThickness;
|
|
physprops->GetPhysicsProperties( nMaterialIndex, &flDensity, &flThickness, NULL, NULL );
|
|
|
|
// Make it more hollow
|
|
flThickness = MIN ( 1.0f, flThickness + 0.5f );
|
|
|
|
if ( flThickness > 0.0f )
|
|
{
|
|
flMass = flTotalSurfaceArea * flThickness * CUBIC_METERS_PER_CUBIC_INCH * flDensity;
|
|
}
|
|
else
|
|
{
|
|
// density is in kg/m^3, volume is in in^3
|
|
flMass = flTotalVolume * CUBIC_METERS_PER_CUBIC_INCH * flDensity;
|
|
}
|
|
|
|
// Mass is somewhere between the original and if it was all ice
|
|
p->SetMass( flMass );
|
|
|
|
// Yes, gravity
|
|
p->EnableGravity( true );
|
|
|
|
// Use this as our vphysics
|
|
VPhysicsSetObject( p );
|
|
|
|
SetSolid( SOLID_VPHYSICS );
|
|
AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST );
|
|
|
|
SetMoveType( MOVETYPE_VPHYSICS );
|
|
|
|
if ( pInitBaseAnimating != this )
|
|
{
|
|
// Transfer children from the init base animating
|
|
TransferChildren( pInitBaseAnimating, this );
|
|
|
|
CBaseEntity *pChild = FirstMoveChild();
|
|
|
|
while ( pChild )
|
|
{
|
|
CEntityFreezing *pFreezing = dynamic_cast<CEntityFreezing*>( pChild );
|
|
if ( pFreezing )
|
|
{
|
|
pFreezing->FinishFreezing();
|
|
}
|
|
|
|
pChild = pChild->NextMovePeer();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CStatueProp::CreateVPhysicsFromOBBs( CBaseAnimating *pInitBaseAnimating )
|
|
{
|
|
// Make enough pointers to convexes for each hitbox
|
|
CPhysConvex **ppConvex = new CPhysConvex*[ m_pInitOBBs->Count() ];
|
|
|
|
float flTotalVolume = 0.0f;
|
|
float flTotalSurfaceArea = 0.0f;
|
|
|
|
for ( int i = 0; i < m_pInitOBBs->Count(); i++ )
|
|
{
|
|
const outer_collision_obb_t *pOBB = &((*m_pInitOBBs)[ i ]);
|
|
|
|
// Accumulate volume and area
|
|
Vector flDimentions = pOBB->vecMaxs - pOBB->vecMins;
|
|
flTotalVolume += flDimentions.x * flDimentions.y * flDimentions.z;
|
|
flTotalSurfaceArea += 2.0f * ( flDimentions.x * flDimentions.y + flDimentions.x * flDimentions.z + flDimentions.y * flDimentions.z );
|
|
|
|
// Get angled min and max extents
|
|
Vector vecMins, vecMaxs;
|
|
VectorRotate( pOBB->vecMins, pOBB->angAngles, vecMins );
|
|
VectorRotate( pOBB->vecMaxs, pOBB->angAngles, vecMaxs );
|
|
|
|
// Get the corners in world space
|
|
Vector vecMinCorner = pOBB->vecPos + vecMins;
|
|
Vector vecMaxCorner = pOBB->vecPos + vecMaxs;
|
|
|
|
// Get the normals of the hitbox in world space
|
|
Vector vecForward, vecRight, vecUp;
|
|
AngleVectors( pOBB->angAngles, &vecForward, &vecRight, &vecUp );
|
|
vecRight = -vecRight;
|
|
|
|
// Convert corners and normals to local space
|
|
Vector vecCornerLocal[ 2 ];
|
|
Vector vecNormalLocal[ 3 ];
|
|
|
|
matrix3x4_t matToWorld = EntityToWorldTransform();
|
|
VectorITransform( vecMaxCorner, matToWorld, vecCornerLocal[ 0 ] );
|
|
VectorITransform( vecMinCorner, matToWorld, vecCornerLocal[ 1 ] );
|
|
VectorIRotate( vecForward, matToWorld, vecNormalLocal[ 0 ] );
|
|
VectorIRotate( vecRight, matToWorld, vecNormalLocal[ 1 ] );
|
|
VectorIRotate( vecUp, matToWorld, vecNormalLocal[ 2 ] );
|
|
|
|
// Create 6 planes from the local oriented hit box data
|
|
float pPlanes[ 4 * 6 ];
|
|
|
|
for ( int iPlane = 0; iPlane < 6; ++iPlane )
|
|
{
|
|
int iPlaneMod2 = iPlane % 2;
|
|
int iPlaneDiv2 = iPlane / 2;
|
|
bool bOdd = ( iPlaneMod2 == 1 );
|
|
|
|
// Plane Normal
|
|
pPlanes[ iPlane * 4 + 0 ] = vecNormalLocal[ iPlaneDiv2 ].x * ( bOdd ? -1.0f : 1.0f );
|
|
pPlanes[ iPlane * 4 + 1 ] = vecNormalLocal[ iPlaneDiv2 ].y * ( bOdd ? -1.0f : 1.0f );
|
|
pPlanes[ iPlane * 4 + 2 ] = vecNormalLocal[ iPlaneDiv2 ].z * ( bOdd ? -1.0f : 1.0f );
|
|
|
|
// Plane D
|
|
pPlanes[ iPlane * 4 + 3 ] = ( vecCornerLocal[ iPlaneMod2 ].x * vecNormalLocal[ iPlaneDiv2 ].x +
|
|
vecCornerLocal[ iPlaneMod2 ].y * vecNormalLocal[ iPlaneDiv2 ].y +
|
|
vecCornerLocal[ iPlaneMod2 ].z * vecNormalLocal[ iPlaneDiv2 ].z ) * ( bOdd ? -1.0f : 1.0f );
|
|
}
|
|
|
|
// Create convex from the intersection of these planes
|
|
ppConvex[ i ] = physcollision->ConvexFromPlanes( pPlanes, 6, 0.0f );
|
|
}
|
|
|
|
// Make a single collide out of the group of convex boxes
|
|
CPhysCollide *pPhysCollide = physcollision->ConvertConvexToCollide( ppConvex, m_pInitOBBs->Count() );
|
|
|
|
delete[] ppConvex;
|
|
|
|
// Create the physics object
|
|
objectparams_t params = g_PhysDefaultObjectParams;
|
|
params.pGameData = static_cast<void *>( this );
|
|
|
|
int nMaterialIndex = physprops->GetSurfaceIndex( "ice" ); // use ice material
|
|
|
|
IPhysicsObject* p = physenv->CreatePolyObject( pPhysCollide, nMaterialIndex, GetAbsOrigin(), GetAbsAngles(), ¶ms );
|
|
Assert( p != NULL );
|
|
|
|
// Set velocity
|
|
Vector vecInitialVelocity = pInitBaseAnimating->GetAbsVelocity();
|
|
p->SetVelocity( &vecInitialVelocity, NULL );
|
|
|
|
// Compute mass
|
|
float flMass;
|
|
float flDensity, flThickness;
|
|
physprops->GetPhysicsProperties( nMaterialIndex, &flDensity, &flThickness, NULL, NULL );
|
|
|
|
// Make it more hollow
|
|
flThickness = MIN ( 1.0f, flThickness + 0.5f );
|
|
|
|
if ( flThickness > 0.0f )
|
|
{
|
|
flMass = flTotalSurfaceArea * flThickness * CUBIC_METERS_PER_CUBIC_INCH * flDensity;
|
|
}
|
|
else
|
|
{
|
|
// density is in kg/m^3, volume is in in^3
|
|
flMass = flTotalVolume * CUBIC_METERS_PER_CUBIC_INCH * flDensity;
|
|
}
|
|
|
|
// Mass is somewhere between the original and if it was all ice
|
|
p->SetMass( flMass );
|
|
|
|
// Yes, gravity
|
|
p->EnableGravity( true );
|
|
|
|
// Use this as our vphysics
|
|
VPhysicsSetObject( p );
|
|
|
|
SetSolid( SOLID_VPHYSICS );
|
|
AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST );
|
|
|
|
SetMoveType( MOVETYPE_VPHYSICS );
|
|
|
|
m_pInitOBBs = NULL;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
CBaseEntity *CreateServerStatue( CBaseAnimating *pAnimating, int collisionGroup )
|
|
{
|
|
CStatueProp *pStatue = static_cast<CStatueProp *>( CreateEntityByName( "physics_prop_statue" ) );
|
|
|
|
if ( pStatue )
|
|
{
|
|
pStatue->m_hInitBaseAnimating = pAnimating;
|
|
pStatue->SetModelName( pAnimating->GetModelName() );
|
|
pStatue->SetAbsOrigin( pAnimating->GetAbsOrigin() );
|
|
pStatue->SetAbsAngles( pAnimating->GetAbsAngles() );
|
|
DispatchSpawn( pStatue );
|
|
pStatue->Activate();
|
|
}
|
|
|
|
return pStatue;
|
|
}
|
|
|
|
CBaseEntity *CreateServerStatueFromOBBs( const CUtlVector<outer_collision_obb_t> &vecSphereOrigins, CBaseAnimating *pAnimating )
|
|
{
|
|
Assert( vecSphereOrigins.Count() > 0 );
|
|
|
|
if ( vecSphereOrigins.Count() <= 0 )
|
|
return NULL;
|
|
|
|
CStatueProp *pStatue = static_cast<CStatueProp *>( CreateEntityByName( "physics_prop_statue" ) );
|
|
|
|
if ( pStatue )
|
|
{
|
|
pStatue->m_pInitOBBs = &vecSphereOrigins;
|
|
|
|
pStatue->m_hInitBaseAnimating = pAnimating;
|
|
pStatue->SetModelName( pAnimating->GetModelName() );
|
|
pStatue->SetAbsOrigin( pAnimating->GetAbsOrigin() );
|
|
pStatue->SetAbsAngles( pAnimating->GetAbsAngles() );
|
|
DispatchSpawn( pStatue );
|
|
pStatue->Activate();
|
|
|
|
pStatue->AddEffects( EF_NODRAW );
|
|
pStatue->CollisionProp()->SetSurroundingBoundsType( USE_GAME_CODE );
|
|
pStatue->AddSolidFlags( ( pAnimating->GetSolidFlags() & FSOLID_CUSTOMBOXTEST ) | ( pAnimating->GetSolidFlags() & FSOLID_CUSTOMRAYTEST ) );
|
|
|
|
pAnimating->SetParent( pStatue );
|
|
|
|
// You'll need to keep track of the child for collision rules
|
|
pStatue->SetThink( &CStatueProp::CollisionPartnerThink );
|
|
pStatue->SetNextThink( gpGlobals->curtime + 1.0f );
|
|
}
|
|
|
|
return pStatue;
|
|
}
|
|
|