mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-10 10:49:35 +00:00
1
This commit is contained in:
@@ -0,0 +1,453 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Game-specific impact effect hooks
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "fx_impact.h"
|
||||
#include "decals.h"
|
||||
#include "IEffects.h"
|
||||
#include "c_breakableprop.h"
|
||||
#include "tempent.h"
|
||||
#include "c_te_legacytempents.h"
|
||||
#include "tf_shareddefs.h"
|
||||
#include "fx.h"
|
||||
|
||||
void ImpactCreateHurtShards( Vector &vecOrigin, trace_t &tr, Vector &shotDir, int iMaterial, bool bLarge, bool bBlood );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void MakeHurt( const CEffectData &data, bool bBlood )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecOrigin, vecStart, vecShotDir;
|
||||
int iMaterial, iDamageType, iHitbox;
|
||||
short nSurfaceProp;
|
||||
C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
|
||||
|
||||
if ( !pEntity )
|
||||
return;
|
||||
|
||||
// If we hit, perform our custom effects and play the sound
|
||||
if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr ) )
|
||||
{
|
||||
// Throw out shards to show the player he's hurting it
|
||||
ImpactCreateHurtShards( vecOrigin, tr, vecShotDir, iMaterial, false, bBlood );
|
||||
|
||||
// Check for custom effects based on the Decal index
|
||||
PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, 1.0 );
|
||||
}
|
||||
|
||||
PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Impact for:
|
||||
// Bullets hitting targets that CAN be hurt
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactCallback( const CEffectData &data )
|
||||
{
|
||||
MakeHurt( data, true );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "Impact", ImpactCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Bloodless Impact for:
|
||||
// Bullets hitting targets that CAN be hurt
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactNoBloodCallback( const CEffectData &data )
|
||||
{
|
||||
MakeHurt( data, false );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "ImpactNoBlood", ImpactNoBloodCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Impact for:
|
||||
// Bullets hitting targets that CANNOT be hurt
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactUnhurtCallback( const CEffectData &data )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecOrigin, vecStart, vecShotDir;
|
||||
int iMaterial, iDamageType, iHitbox;
|
||||
short nSurfaceProp;
|
||||
C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
|
||||
|
||||
if ( !pEntity )
|
||||
return;
|
||||
|
||||
// If we hit, perform our custom effects and play the sound
|
||||
// Don't decal team members, but decal everything else
|
||||
|
||||
bool bShouldDecal = !( pEntity && pEntity->IsPlayer() );
|
||||
if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr, bShouldDecal ? 0 : IMPACT_NODECAL ) )
|
||||
{
|
||||
// Check for custom effects based on the Decal index
|
||||
PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, 0 );
|
||||
}
|
||||
|
||||
PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "ImpactUnhurt", ImpactUnhurtCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Impact for:
|
||||
// Bullets hitting player's handheld shields
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactShieldCallback( const CEffectData &data )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecOrigin, vecStart, vecShotDir;
|
||||
int iMaterial, iDamageType, iHitbox;
|
||||
short nSurfaceProp;
|
||||
ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
|
||||
|
||||
// Don't call Impact() because we don't want to decal the player
|
||||
Vector reflect = -vecShotDir;
|
||||
reflect[0] += random->RandomFloat( -0.5f, 0.5f );
|
||||
reflect[1] += random->RandomFloat( -0.5f, 0.5f );
|
||||
reflect[2] += random->RandomFloat( 0, 0.5f );
|
||||
FX_MetalSpark( vecOrigin, reflect, -vecShotDir, 3 );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "ImpactShield", ImpactShieldCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void MakePlasmaHurt( const CEffectData &data, bool bBlood )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecOrigin, vecStart, vecShotDir;
|
||||
int iMaterial, iDamageType, iHitbox;
|
||||
short nSurfaceProp;
|
||||
C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
|
||||
|
||||
if ( !pEntity )
|
||||
return;
|
||||
|
||||
// If we hit, play our splash
|
||||
if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr ) )
|
||||
{
|
||||
// Throw out shards to show the player he's hurting it
|
||||
ImpactCreateHurtShards( vecOrigin, tr, vecShotDir, iMaterial, false, bBlood );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Impact for:
|
||||
// Plasma hitting targets that CAN be hurt
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactPlasmaCallback( const CEffectData &data )
|
||||
{
|
||||
MakePlasmaHurt( data, true );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "PlasmaHurt", ImpactPlasmaCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Impact for:
|
||||
// Plasma hitting targets that CAN be hurt
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactPlasmaNoBloodCallback( const CEffectData &data )
|
||||
{
|
||||
MakePlasmaHurt( data, false );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "PlasmaHurtNoBlood", ImpactPlasmaNoBloodCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Impact for:
|
||||
// Plasma hitting targets that CANNOT be hurt
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactPlasmaUnhurtCallback( const CEffectData &data )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecOrigin, vecStart, vecShotDir;
|
||||
int iMaterial, iDamageType, iHitbox;
|
||||
short nSurfaceProp;
|
||||
C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
|
||||
|
||||
if ( !pEntity )
|
||||
return;
|
||||
|
||||
// If we hit, play our splash
|
||||
|
||||
bool bShouldDecal = !( pEntity && pEntity->IsPlayer() );
|
||||
if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr, bShouldDecal ? 0 : IMPACT_NODECAL ) )
|
||||
{
|
||||
g_pEffects->EnergySplash( vecOrigin, tr.plane.normal, false );
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "PlasmaUnhurt", ImpactPlasmaUnhurtCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Impact for:
|
||||
// Plasma hitting player's handheld shields
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactPlasmaShieldCallback( const CEffectData &data )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecOrigin, vecStart, vecShotDir;
|
||||
int iMaterial, iDamageType, iHitbox;
|
||||
short nSurfaceProp;
|
||||
ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
|
||||
|
||||
// Bounce sparks away from the shield
|
||||
// Don't call Impact() because we don't want to decal the player
|
||||
Vector offset = vecOrigin - ( vecShotDir * 1.0f );
|
||||
Vector vecDir = -vecShotDir + Vector(0,0,1.5);
|
||||
g_pEffects->Sparks( offset, 2, 2, &vecDir );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "PlasmaShield", ImpactPlasmaShieldCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Impact for:
|
||||
// Strider hitting anything
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactStriderCallback( const CEffectData &data )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecOrigin, vecStart, vecShotDir;
|
||||
int iMaterial, iDamageType, iHitbox;
|
||||
short nSurfaceProp;
|
||||
C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
|
||||
|
||||
if ( !pEntity )
|
||||
return;
|
||||
|
||||
// If we hit, play our splash
|
||||
if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr ) )
|
||||
{
|
||||
PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, 5 );
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "Strider", ImpactStriderCallback );
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// SHARDS.
|
||||
// Models for small impact tempents (not vphysics simulated)
|
||||
//--------------------------------------------------------------------
|
||||
// WOOD
|
||||
//--------------------------------------------------------------------
|
||||
#define WOOD_SHARDS 5
|
||||
const char *ImpactHurtShards_Wood_Small_Models[ WOOD_SHARDS ] =
|
||||
{
|
||||
"models/props_debris/wood_shard_001.mdl",
|
||||
"models/props_debris/wood_shard_002.mdl",
|
||||
"models/props_debris/wood_shard_003.mdl",
|
||||
"models/props_debris/wood_shard_004.mdl",
|
||||
"models/props_debris/wood_shard_005.mdl",
|
||||
};
|
||||
// Model pointers for the above
|
||||
model_t *ImpactHurtShards_Wood_Small[ WOOD_SHARDS ];
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// FOLIAGE
|
||||
//--------------------------------------------------------------------
|
||||
#define FOLIAGE_SHARDS 5
|
||||
const char *ImpactHurtShards_Foliage_Small_Models[ FOLIAGE_SHARDS ] =
|
||||
{
|
||||
"models/props_debris/foliage_shard_001.mdl",
|
||||
"models/props_debris/foliage_shard_002.mdl",
|
||||
"models/props_debris/foliage_shard_003.mdl",
|
||||
"models/props_debris/foliage_shard_004.mdl",
|
||||
"models/props_debris/foliage_shard_005.mdl",
|
||||
};
|
||||
// Model pointers for the above
|
||||
model_t *ImpactHurtShards_Foliage_Small[ FOLIAGE_SHARDS ];
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// CONCRETE
|
||||
//--------------------------------------------------------------------
|
||||
#define CONCRETE_SHARDS 1
|
||||
const char *ImpactHurtShards_Concrete_Small_Models[ CONCRETE_SHARDS ] =
|
||||
{
|
||||
"models/props_debris/metal_shard_001.mdl",
|
||||
};
|
||||
// Model pointers for the above
|
||||
model_t *ImpactHurtShards_Concrete_Small[ CONCRETE_SHARDS ];
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// METAL
|
||||
//--------------------------------------------------------------------
|
||||
#define METAL_SHARDS 6
|
||||
const char *ImpactHurtShards_Metal_Small_Models[ METAL_SHARDS ] =
|
||||
{
|
||||
"models/props_debris/metal_shard_001.mdl",
|
||||
"models/props_debris/metal_shard_002.mdl",
|
||||
"models/props_debris/metal_shard_003.mdl",
|
||||
"models/props_debris/metal_shard_004.mdl",
|
||||
"models/props_debris/metal_shard_005.mdl",
|
||||
"models/props_debris/metal_shard_006.mdl",
|
||||
};
|
||||
// Model pointers for the above
|
||||
model_t *ImpactHurtShards_Metal_Small[ METAL_SHARDS ];
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Precache all our shards
|
||||
//-----------------------------------------------------------------------------
|
||||
void PrecacheImpactShards(void *pUser)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Wood
|
||||
for ( i = 0; i < WOOD_SHARDS; i++ )
|
||||
{
|
||||
const char *sFile = ImpactHurtShards_Wood_Small_Models[i];
|
||||
ImpactHurtShards_Wood_Small[i] = (model_t *)engine->LoadModel( sFile );
|
||||
}
|
||||
|
||||
// Foliage
|
||||
for ( i = 0; i < FOLIAGE_SHARDS; i++ )
|
||||
{
|
||||
const char *sFile = ImpactHurtShards_Foliage_Small_Models[i];
|
||||
ImpactHurtShards_Foliage_Small[i] = (model_t *)engine->LoadModel( sFile );
|
||||
}
|
||||
|
||||
// Concrete
|
||||
for ( i = 0; i < CONCRETE_SHARDS; i++ )
|
||||
{
|
||||
const char *sFile = ImpactHurtShards_Concrete_Small_Models[i];
|
||||
ImpactHurtShards_Concrete_Small[i] = (model_t *)engine->LoadModel( sFile );
|
||||
}
|
||||
|
||||
// Metal
|
||||
for ( i = 0; i < METAL_SHARDS; i++ )
|
||||
{
|
||||
const char *sFile = ImpactHurtShards_Metal_Small_Models[i];
|
||||
ImpactHurtShards_Metal_Small[i] = (model_t *)engine->LoadModel( sFile );
|
||||
}
|
||||
}
|
||||
PRECACHE_REGISTER_FN(PrecacheImpactShards);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Throw out shards from the impact point to show we can hurt the target
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactCreateHurtShards( Vector &vecOrigin, trace_t &tr, Vector &shotDir, int iMaterial, bool bLarge, bool bBlood )
|
||||
{
|
||||
// Throw out the effect if any of these are true
|
||||
if ( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) )
|
||||
return;
|
||||
|
||||
float flShardSpread = 0.5;
|
||||
|
||||
Vector vecSpawnOrigin = vecOrigin;
|
||||
|
||||
int iNumGibs = random->RandomInt( 1, 2 );
|
||||
for ( int i = 0; i < iNumGibs; i++ )
|
||||
{
|
||||
QAngle vecAngles;
|
||||
vecAngles[0] = random->RandomFloat(-255, 255);
|
||||
vecAngles[1] = random->RandomFloat(-255, 255);
|
||||
vecAngles[2] = random->RandomFloat(-255, 255);
|
||||
Vector vecForceDir;
|
||||
float spreadOfs = random->RandomFloat( 3.0f, 4.0f );
|
||||
vecForceDir[0] = -shotDir[0] + random->RandomFloat( -(flShardSpread*spreadOfs), (flShardSpread*spreadOfs) );
|
||||
vecForceDir[1] = -shotDir[1] + random->RandomFloat( -(flShardSpread*spreadOfs), (flShardSpread*spreadOfs) );
|
||||
vecForceDir[2] = -shotDir[2] + random->RandomFloat( -(flShardSpread*spreadOfs), (flShardSpread*spreadOfs) );
|
||||
// Add some extra vertical height
|
||||
vecForceDir[2] += random->RandomFloat( 0, 5 );
|
||||
vecForceDir *= random->RandomFloat( 30.0,60.0 );
|
||||
|
||||
model_t *pModel = NULL;
|
||||
int iFlags = ( FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY );
|
||||
|
||||
// Select the right chunk for the job
|
||||
switch ( iMaterial )
|
||||
{
|
||||
case CHAR_TEX_WOOD:
|
||||
iFlags |= FTENT_ROTATE;
|
||||
pModel = ImpactHurtShards_Wood_Small[ random->RandomInt(0,WOOD_SHARDS-1) ];
|
||||
break;
|
||||
|
||||
case CHAR_TEX_FOLIAGE:
|
||||
pModel = ImpactHurtShards_Foliage_Small[ random->RandomInt(0,FOLIAGE_SHARDS-1) ];
|
||||
break;
|
||||
|
||||
case CHAR_TEX_METAL:
|
||||
case CHAR_TEX_VENT:
|
||||
case CHAR_TEX_GRATE:
|
||||
|
||||
case CHAR_TEX_CONCRETE:
|
||||
default:
|
||||
pModel = ImpactHurtShards_Metal_Small[ random->RandomInt(0,METAL_SHARDS-1) ];
|
||||
break;
|
||||
|
||||
case CHAR_TEX_FLESH:
|
||||
// Spray some blood out
|
||||
if ( !bBlood )
|
||||
return;
|
||||
|
||||
CEffectData data;
|
||||
data.m_vOrigin = vecOrigin;
|
||||
data.m_vNormal = tr.plane.normal;
|
||||
data.m_flScale = 4;
|
||||
data.m_fFlags = FX_BLOODSPRAY_ALL;
|
||||
data.m_nEntIndex = tr.m_pEnt ? tr.m_pEnt->entindex() : 0;
|
||||
DispatchEffect( "tf2blood", data );
|
||||
return;
|
||||
break;
|
||||
/*
|
||||
case CHAR_TEX_CONCRETE:
|
||||
default:
|
||||
pModel = ImpactHurtShards_Concrete_Small[ random->RandomInt(0,CONCRETE_SHARDS-1) ];
|
||||
break;
|
||||
*/
|
||||
}
|
||||
Assert( pModel );
|
||||
|
||||
// ROBIN: Removed until optimized
|
||||
return;
|
||||
|
||||
// Throw it out
|
||||
tempents->SpawnTempModel( pModel, vecSpawnOrigin, vecAngles, vecForceDir, random->RandomFloat(0.5,1.5), iFlags );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Throw out breakable, vphysics gibs from the surface we hit
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactCreateHurtGibs( Vector &vecOrigin, trace_t &tr, Vector &shotDir, int iMaterial, bool bLarge )
|
||||
{
|
||||
// Throw out the effect if any of these are true
|
||||
if ( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) )
|
||||
return;
|
||||
|
||||
Vector vecSpawnOrigin = vecOrigin - (shotDir * 32);
|
||||
float flGibSpread = 0.8;
|
||||
|
||||
// Custom TF2 impact effects
|
||||
if ( iMaterial == CHAR_TEX_FOLIAGE )
|
||||
{
|
||||
int iNumGibs = random->RandomInt( 1, 2 );
|
||||
for ( int i = 0; i < iNumGibs; i++ )
|
||||
{
|
||||
AngularImpulse angVel;
|
||||
angVel.Random( -400.0f, 400.0f );
|
||||
Vector vecForceDir;
|
||||
float spreadOfs = random->RandomFloat( 3.0f, 4.0f );
|
||||
vecForceDir[0] = -shotDir[0] + random->RandomFloat( -(flGibSpread*spreadOfs), (flGibSpread*spreadOfs) );
|
||||
vecForceDir[1] = -shotDir[1] + random->RandomFloat( -(flGibSpread*spreadOfs), (flGibSpread*spreadOfs) );
|
||||
vecForceDir[2] = -shotDir[2] + random->RandomFloat( -(flGibSpread*spreadOfs), (flGibSpread*spreadOfs) );
|
||||
// Add some extra vertical height
|
||||
vecForceDir[2] += 5;
|
||||
vecForceDir *= random->RandomFloat( 10.0,30.0 );
|
||||
|
||||
//C_BreakableProp *pProp = new C_BreakableProp;
|
||||
//pProp->CreateClientsideProp( ImpactHurtGibs_Wood_Small[ random->RandomInt(0,NUM_WOOD_GIBS_SMALL-1) ], vecSpawnOrigin, vecForceDir, angVel );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PerformCustomEffects( vecOrigin, tr, shotDir, iMaterial, 1 );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user