quadrilateralcowboy/d3xp/qglass.cpp

200 lines
4.3 KiB
C++

#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
#ifdef STEAM
#include "steamstats.h"
#endif
//#define ROCKETSPEED 256
const idEventDef EV_glassreset( "glassreset" );
CLASS_DECLARATION( idEntity, idQGlass )
EVENT( EV_glassreset, idQGlass::Event_glassreset)
END_CLASS
void idQGlass::Save( idSaveGame *savefile ) const
{
savefile->WriteInt(state);
savefile->WriteInt(count);
savefile->WriteString(fxFracture);
}
void idQGlass::Restore( idRestoreGame *savefile )
{
savefile->ReadInt(state);
savefile->ReadInt(count);
savefile->ReadString(fxFracture);
}
void idQGlass::Spawn( void )
{
fxFracture = spawnArgs.GetString( "fx" );
count = spawnArgs.GetInt("count", "3");
this->GetPhysics()->SetContents( CONTENTS_SOLID );
renderEntity.noShadow = true;
renderEntity.noSelfShadow = true;
//precache.
common->Printf("\n------------- Caching glass debris -------------\n");
const idKeyValue *kv = spawnArgs.MatchPrefix( "def_debris" );
while ( kv )
{
const idDict *debris_args = gameLocal.FindEntityDefDict( kv->GetValue(), false );
if ( debris_args )
{
const idDeclEntityDef *debrisDef = gameLocal.FindEntityDef( kv->GetValue(), false );
if (debrisDef)
{
const char *clipModelName;
debrisDef->dict.GetString( "clipmodel", "", &clipModelName );
if ( !clipModelName[0] )
{
clipModelName = debrisDef->dict.GetString( "model" ); // use the visual model
}
// load the trace model
idTraceModel trm;
collisionModelManager->TrmFromModel( clipModelName, trm );
}
}
kv = spawnArgs.MatchPrefix( "def_debris", kv );
}
}
void idQGlass::Event_glassreset( void )
{
this->state = IDLE;
this->Show();
GetPhysics()->SetContents(CONTENTS_SOLID);
}
void idQGlass::AddForce( idEntity *ent, int id, const idVec3 &point, const idVec3 &force )
{
if (state == DESTROYED)
return;
//hide the brush.
this->Hide();
state = DESTROYED;
GetPhysics()->SetContents(0);
//audio.
StartSound( "snd_shatter", SND_CHANNEL_ANY, 0, false, NULL );
//particles.
if ( fxFracture.Length() )
{
idEntityFx::StartFx( fxFracture, &point, &GetPhysics()->GetAxis(), this, true );
}
idBounds bounds = this->GetPhysics()->GetAbsBounds();
idVec3 tmin;
idVec3 tmax;
tmin[0] = bounds[0][0] ;
tmin[1] = bounds[0][1] ;
tmin[2] = bounds[0][2] ;
tmax[0] = bounds[1][0] ;
tmax[1] = bounds[1][1] ;
tmax[2] = bounds[1][2] ;
int i;
//GetPhysics()->GetOrigin()
//gameRenderWorld->DebugSphere(idVec4(1,1,1,1), idSphere(tmin + GetPhysics()->GetOrigin(), 4), 10000);
//gameRenderWorld->DebugSphere(idVec4(1,0,0,1), idSphere(tmax + GetPhysics()->GetOrigin(), 4), 10000);
//facingAxis 0, 1 = wall panes. facingAxis 2 = ceiling/floor pane.
int facingAxis = 0;
for ( i = 1 ; i < 3 ; i++ )
{
if ( bounds[1][ i ] - bounds[0][ i ] < bounds[1][ facingAxis ] - bounds[0][ facingAxis ] )
{
facingAxis = i;
}
}
//debris shower.
const idKeyValue *kv = spawnArgs.MatchPrefix( "def_debris" );
while ( kv )
{
const idDict *debris_args = gameLocal.FindEntityDefDict( kv->GetValue(), false );
if ( debris_args )
{
idAngles dir = idAngles(0,0,0);
if (facingAxis == 0)
{
dir.yaw = 0;
}
else if (facingAxis == 1)
{
dir.yaw = 90;
}
else if (facingAxis == 2)
{
dir.pitch = 90;
}
for (i = 0; i < count; i++)
{
idVec3 pos;
idDebris *debris;
idEntity *ent;
dir.roll = gameLocal.random.RandomInt(360);
gameLocal.SpawnEntityDef( *debris_args, &ent, false );
if ( !ent || !ent->IsType( idDebris::Type ) )
{
gameLocal.Error( "'projectile_debris' is not an idDebris" );
}
pos.x = (gameLocal.random.CRandomFloat() * (tmax[0] - tmin[0])) / 2;
pos.y = (gameLocal.random.CRandomFloat() * (tmax[1] - tmin[1])) / 2;
pos.z = (gameLocal.random.CRandomFloat() * (tmax[2] - tmin[2])) / 2;
pos += GetPhysics()->GetOrigin();
debris = static_cast<idDebris *>(ent);
debris->Create( this, pos, dir.ToMat3() );
debris->Launch();
//debris->GetRenderEntity()->shaderParms[ SHADERPARM_TIME_OF_DEATH ] = ( gameLocal.time + 1500 ) * 0.001f;
debris->UpdateVisuals();
}
}
kv = spawnArgs.MatchPrefix( "def_debris", kv );
}
ActivateTargets( gameLocal.GetLocalPlayer() );
#ifdef STEAM
g_SteamStats->SetStatDelta("stat_glassbreaks", 1);
#endif
}