etqw-sdk/source/game/client/ClientMoveable.cpp
2008-05-29 00:00:00 +00:00

246 lines
7 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
//----------------------------------------------------------------
// ClientMoveable.cpp
//----------------------------------------------------------------
#include "../precompiled.h"
#pragma hdrstop
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "ClientMoveable.h"
#include "../ContentMask.h"
#include "../demos/DemoManager.h"
/*
===============================================================================
rvClientMoveable
===============================================================================
*/
const idEventDefInternal CL_FadeOut( "internal_fadeOut", "d" );
static const float BOUNCE_SOUND_MIN_VELOCITY = 100.0f;
static const float BOUNCE_SOUND_MAX_VELOCITY = 200.0f;
static const int BOUNCE_SOUND_DELAY = 200;
CLASS_DECLARATION( rvClientEntity, rvClientMoveable )
EVENT( CL_FadeOut, rvClientMoveable::Event_FadeOut )
END_CLASS
/*
================
rvClientMoveable::rvClientMoveable
================
*/
rvClientMoveable::rvClientMoveable ( void ) {
memset ( &renderEntity, 0, sizeof(renderEntity) );
entityDefHandle = -1;
aorLayout = NULL;
}
/*
================
rvClientMoveable::~rvClientMoveable
================
*/
rvClientMoveable::~rvClientMoveable ( void ) {
FreeEntityDef ( );
gameEdit->DestroyRenderEntity( renderEntity );
// Remove any trail effect if there is one
if ( trailEffect ) {
trailEffect->Stop ( );
}
}
/*
================
rvClientMoveable::FreeEntityDef
================
*/
void rvClientMoveable::FreeEntityDef ( void ) {
if ( entityDefHandle >= 0 ) {
gameRenderWorld->FreeEntityDef ( entityDefHandle );
entityDefHandle = -1;
}
}
/*
================
rvClientMoveable::Spawn
================
*/
void rvClientMoveable::Spawn( const idDict* args, int _effectSet ) {
float bouncyness = 0.5f;
float density = 0.5f;
spawnArgs = args;
assert( spawnArgs );
effectSet = _effectSet;
// parse static models the same way the editor display does
gameEdit->ParseSpawnArgsToRenderEntity( *spawnArgs, renderEntity );
idTraceModel trm;
int clipShrink;
const char* clipModelName = spawnArgs->GetString( "cm_model" );
if ( !gameLocal.clip.LoadTraceModel( clipModelName, trm ) ) {
gameLocal.Error( "rvClientMoveable '%d': cannot load collision model %s", entityNumber, clipModelName );
return;
}
// if the model should be shrunk
clipShrink = spawnArgs->GetInt( "clipshrink" );
if ( clipShrink != 0 ) {
trm.Shrink( clipShrink * CM_CLIP_EPSILON );
}
physicsObj.SetSelf( gameLocal.entities[ENTITYNUM_CLIENT] );
physicsObj.SetClipModel( new idClipModel( trm, false ), spawnArgs->GetFloat ( "density", "0.5" ), 0 );
physicsObj.SetOrigin( worldOrigin );
physicsObj.SetAxis( worldAxis );
physicsObj.SetBouncyness( spawnArgs->GetFloat( "bouncyness", "0.6" ) );
physicsObj.SetBuoyancy( spawnArgs->GetFloat( "buoyancy", "0.3" ) );
aorLayout = gameLocal.declAORType[ spawnArgs->GetString( "aor_layout", "missile" ) ];
float friction = spawnArgs->GetFloat( "friction", "0.05" );
physicsObj.SetFriction( 0.6f, 0.6f, friction );
float gravity;
if ( spawnArgs->GetFloat( "gravity", "0", gravity ) ) {
physicsObj.SetGravity( idVec3( 0.0f, 0.0f, -gravity ) );
} else {
physicsObj.SetGravity( gameLocal.GetGravity() );
}
physicsObj.SetContents( 0, 0 );
// TODO: These contents flags can surely be done using masks....
physicsObj.SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_SLIDEMOVER | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP | CONTENTS_WATER | CONTENTS_FORCEFIELD, 0 );
physicsObj.Activate();
idVec3 center = physicsObj.GetBounds().GetCenter() * worldAxis + worldOrigin;
const char* trailEffectName = "fx_trail";
if ( effectSet != 0 ) {
trailEffectName = va( "fx_trail_%i", effectSet );
}
trailEffect = gameLocal.PlayEffect( *spawnArgs, colorWhite.ToVec3(), trailEffectName, NULL, center, worldAxis, true );
trailAttenuateSpeed = spawnArgs->GetFloat ( "trailAttenuateSpeed", "200" );
bounceSoundShader = gameLocal.declSoundShaderType[ spawnArgs->GetString( "snd_bounce" ) ];
bounceSoundTime = 0;
firstBounce = true;
}
/*
================
rvClientMoveable::Think
================
*/
void rvClientMoveable::Think ( void ) {
bool runPhysics = true;
if ( gameLocal.SetupClientAoR() ) {
int aorFlags = gameLocal.aorManager.GetFlagsForPoint( aorLayout, worldOrigin );
if ( ( aorFlags & AOR_INHIBIT_PHYSICS ) != 0 ) {
runPhysics = false;
}
}
if ( runPhysics ) {
RunPhysics();
}
// Special case the sound update to use the center mass since the origin may be in an odd place
if ( refSound.referenceSound ) {
refSound.origin = worldOrigin;
refSound.referenceSound->UpdateEmitter( refSound.origin, refSound.listenerId, &refSound.parms );
}
renderEntity.origin = worldOrigin;
renderEntity.axis = worldAxis;
// Keep the trail effect following
if ( trailEffect ) {
float speed;
speed = idMath::ClampFloat ( 0, trailAttenuateSpeed, physicsObj.GetLinearVelocity ( ).LengthFast ( ) );
if ( physicsObj.IsAtRest ( ) ) {
trailEffect->Stop ( );
trailEffect = NULL;
} else {
idVec3 center = physicsObj.GetBounds().GetCenter() * worldAxis + worldOrigin;
trailEffect->SetOrigin ( center );
trailEffect->SetAxis ( worldAxis );
trailEffect->Attenuate ( speed / trailAttenuateSpeed );
}
}
// add to refresh list
if ( entityDefHandle == -1 ) {
entityDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
} else {
gameRenderWorld->UpdateEntityDef( entityDefHandle, &renderEntity );
}
}
/*
================
rvClientMoveable::GetPhysics
================
*/
idPhysics* rvClientMoveable::GetPhysics ( void ) const {
return (idPhysics*)&physicsObj;
}
/*
================
rvClientMoveable::Collide
================
*/
bool rvClientMoveable::Collide ( const trace_t &collision, const idVec3 &velocity ) {
if ( firstBounce ) {
// first bounce, play effect
const char* bounceEffectName = "fx_firstbounce";
if ( effectSet != 0 ) {
bounceEffectName = va( "fx_firstbounce_%i", effectSet );
}
const idVec3& origin = physicsObj.GetOrigin();
idMat3 axis = ( idVec3( 0.0f, 0.0f, 1.0f ) ).ToMat3();
gameLocal.PlayEffect( *spawnArgs, colorWhite.ToVec3(), bounceEffectName, NULL, origin, axis );
firstBounce = false;
}
if ( bounceSoundShader && gameLocal.time > bounceSoundTime ) {
float speed;
speed = velocity.LengthFast ( );
if ( speed > BOUNCE_SOUND_MIN_VELOCITY ) {
StartSoundShader ( bounceSoundShader, SND_ANY, 0 );
bounceSoundTime = BOUNCE_SOUND_DELAY;
}
}
return false;
}
/*
================
rvClientMoveable::Event_FadeOut
================
*/
void rvClientMoveable::Event_FadeOut ( int duration ) {
renderEntity.flags.noShadow = true;
renderEntity.shaderParms[ SHADERPARM_TIME_OF_DEATH ] = gameLocal.time * 0.001f;
PostEventMS ( &EV_Remove, duration );
}