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; |
|
} |
|
|
|
|