nuclide/Source/gs-entbase/server/func_breakable.cpp

123 lines
2.7 KiB
C++
Executable file

/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
/*
Flags
Only Trigger (1) - Entity can only be activated (broken) by being triggered.
Touch (2) - Brush will break on touch.
Pressure (4) - Brush will break when pressured (e.g. player walking on it).
*/
enumflags
{
SF_TRIGGER,
SF_TOUCH,
SF_PRESSURE
};
class CFuncBreakable : CBaseTrigger
{
float m_iMaterial;
virtual void() Trigger;
virtual void() touch;
virtual void( entity eAttacker, int iType, int iDamage ) vPain;
virtual void( entity eAttacker, int iType, int iDamage ) vDeath;
};
void CFuncBreakable :: Respawn ( void )
{
if ( spawnflags & SF_TRIGGER ) {
takedamage = DAMAGE_NO;
} else {
takedamage = DAMAGE_YES;
}
}
void CFuncBreakable :: vPain ( entity attacker, int type, int damage )
{
if (serverkeyfloat("*bspversion") != 30) {
return;
}
switch ( m_iMaterial ) {
case MATERIAL_GLASS:
case MATERIAL_COMPUTER:
case MATERIAL_GLASS_UNBREAKABLE:
sound( self, CHAN_VOICE, sprintf( "debris/glass%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
break;
case MATERIAL_WOOD:
sound( self, CHAN_VOICE, sprintf( "debris/wood%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
break;
case MATERIAL_METAL:
sound( self, CHAN_VOICE, sprintf( "debris/metal%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
break;
case MATERIAL_FLESH:
float fRand = floor( random( 1, 8 ) );
if ( fRand == 4 ) { // sigh
fRand = 5;
}
sound( self, CHAN_VOICE, sprintf( "debris/flesh%d.wav", fRand ), 1.0, ATTN_NORM );
break;
case MATERIAL_CINDER:
case MATERIAL_ROCK:
sound( self, CHAN_VOICE, sprintf( "debris/concrete%d.wav", random( 1, 4 ) ), 1.0, ATTN_NORM );
break;
}
}
void CFuncBreakable :: vDeath ( entity attacker, int type, int damage )
{
health = 0;
Effect_BreakModel( absmin, absmax, '0 0 0', m_iMaterial );
CBaseTrigger::UseTargets();
CBaseEntity::Hide();
}
void CFuncBreakable :: Trigger ( void )
{
CFuncBreakable::vDeath( world, 0, 0 );
}
void CFuncBreakable :: touch ( void )
{
if ( other.classname == classname ) {
return;
}
if ( m_iMaterial == MATERIAL_GLASS ) {
if (vlen(other.velocity) > 200) {
vDeath( other, 0, 1 );
}
}
}
void CFuncBreakable :: CFuncBreakable( void )
{
precache_model( model );
angles = [0,0,0];
movetype = MOVETYPE_NONE;
solid = SOLID_BSP;
setmodel( this, model );
CBaseEntity::CBaseEntity();
CFuncBreakable::Respawn();
for ( int i = 1; i < ( tokenize( __fullspawndata ) - 1 ); i += 2 ) {
switch ( argv( i ) ) {
case "material":
m_iMaterial = stoi( argv( i + 1 ) );
break;
default:
break;
}
}
if ( !health ) {
health = 15;
}
}
CLASSEXPORT( func_breakable, CFuncBreakable )