-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Expand file tree
/
Copy pathtf_fx_impacts.cpp
More file actions
320 lines (277 loc) · 10 KB
/
tf_fx_impacts.cpp
File metadata and controls
320 lines (277 loc) · 10 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "fx_impact.h"
#include "engine/IEngineSound.h"
#include "c_tf_player.h"
#include "view.h"
#include "tf_gamerules.h"
#include "player_vs_environment/c_tf_tank_boss.h"
#include "decals.h"
#include "clientsideeffects.h"
#include "fx_quad.h"
//-----------------------------------------------------------------------------
// Purpose: Handle weapon impacts
//-----------------------------------------------------------------------------
static int g_MvMRobotImpactCount = 0;
static int g_MvMTankImpactCount = 0;
void ImpactCallback( 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;
bool bImpact = ( data.m_nDamageType != pEntity->GetTeamNumber() || pEntity->GetTeamNumber() < FIRST_GAME_TEAM );
if ( data.m_nDamageType != pEntity->GetTeamNumber() && pEntity->IsPlayer() )
{
C_TFPlayer *pPlayer = ToTFPlayer( pEntity );
// Don't impact spies disguised as the same team as this syringe/projectile
if ( pPlayer && pPlayer->m_Shared.InCond( TF_COND_DISGUISED ) )
{
if ( pPlayer->m_Shared.GetDisguiseTeam() == data.m_nDamageType )
{
bImpact = false;
}
}
}
if ( bImpact )
{
// We create lots of impact sounds, especially from Heavy's firing miniguns. To cut down on the number
// of active sounds, we precull impact sounds that are too far from the current viewpoint.
bool bIsMVM = TFGameRules() && TFGameRules()->IsMannVsMachineMode();
int nApparentTeam = pEntity->GetTeamNumber();
C_TFPlayer *pPlayer = ToTFPlayer( pEntity );
if ( pPlayer && pPlayer->m_Shared.InCond( TF_COND_DISGUISED ) )
{
nApparentTeam = pPlayer->m_Shared.GetDisguiseTeam();
}
bool bPlaySound = true;
bool bIsRobotImpact = false;
if ( ( pPlayer && IsRobotTeam( nApparentTeam ) ) || ( bIsMVM && pPlayer && nApparentTeam == TF_TEAM_PVE_INVADERS ) )
{
bPlaySound = true;
bIsRobotImpact = true;
}
else
{
bPlaySound = (MainViewOrigin() - vecOrigin).LengthSqr() < (1024*1024);
}
// If we hit, perform our custom effects and play the sound
if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr ) )
{
// Check for custom effects based on the Decal index
PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, 1 );
//Play a ricochet sound some of the time
if ( bPlaySound && random->RandomInt(1,10) <= 3 && (iDamageType == DMG_BULLET) )
{
CLocalPlayerFilter filter;
C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, "Bounce.Shrapnel", &vecOrigin );
}
}
if ( bPlaySound )
{
// every other one of the mvm impacts are emitted from the world to allow for ~2 impacts playing at a time
if ( bIsRobotImpact )
{
//pEntity->EmitSound( "MVM_Robot.BulletImpact" );
CLocalPlayerFilter filter;
if ( g_MvMRobotImpactCount % 4 == 0 )
{
if( pPlayer->IsMiniBoss() )
{
C_BaseEntity::EmitSound( filter, pEntity->entindex(), "MVM_Giant.BulletImpact", &vecOrigin );
}
else
{
C_BaseEntity::EmitSound( filter, pEntity->entindex(), "MVM_Robot.BulletImpact", &vecOrigin );
}
}
else
{
C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, "MVM_Robot.BulletImpact", &vecOrigin );
}
g_MvMRobotImpactCount++;
}
else if ( bIsMVM && dynamic_cast< C_TFTankBoss* >( pEntity ) )
{
//pEntity->EmitSound( "MVM_Robot.BulletImpact" );
CLocalPlayerFilter filter;
if ( g_MvMTankImpactCount % 4 == 0 )
{
C_BaseEntity::EmitSound( filter, pEntity->entindex(), "MVM_Tank.BulletImpact", &vecOrigin );
}
else
{
C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, "MVM_Tank.BulletImpact", &vecOrigin );
}
g_MvMTankImpactCount++;
}
else
{
PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp );
}
}
}
}
DECLARE_CLIENT_EFFECT( "Impact", ImpactCallback );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void TFSplashCallbackHelper( const CEffectData &data, const char *pszEffectName )
{
Vector normal;
AngleVectors( data.m_vAngles, &normal );
CSmartPtr<CNewParticleEffect> pEffect = CNewParticleEffect::Create( NULL, pszEffectName );
if ( pEffect->IsValid() )
{
pEffect->SetSortOrigin( data.m_vOrigin );
pEffect->SetControlPoint( 0, data.m_vOrigin );
pEffect->SetControlPointOrientation( 0, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) );
}
}
void TFSplashCallback( const CEffectData &data )
{
TFSplashCallbackHelper( data, "water_bulletsplash01" );
}
DECLARE_CLIENT_EFFECT( "tf_gunshotsplash", TFSplashCallback );
void TFSplashCallbackMinigun( const CEffectData &data )
{
TFSplashCallbackHelper( data, "water_bulletsplash01_minigun" );
}
DECLARE_CLIENT_EFFECT( "tf_gunshotsplash_minigun", TFSplashCallbackMinigun );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void TFPaintBombSplashCallback( const CEffectData &data )
{
C_BaseEntity *pEntity = data.GetEntity();
if ( !pEntity )
return;
trace_t tr;
// Get a color if it exists
Color cColor;
if ( data.m_bCustomColors )
{
cColor.SetColor( data.m_CustomColors.m_vecColor1.x * 255, data.m_CustomColors.m_vecColor1.y * 255, data.m_CustomColors.m_vecColor1.z * 255, 255 );
}
else
{
cColor.SetColor( 255, 255, 255, 255 );
}
CTFPlayer *pPlayer = ToTFPlayer( pEntity );
// Build out the decal name from nMaterial
int nPaintIndex = data.m_nMaterial;
// Decals
// Special case for world entity with hitbox:
if ( (pEntity->index == 0) && (data.m_nHitBox != 0) )
{
int nMaterial = decalsystem->GetDecalIndexForName( VarArgs( "%s%d%s", "TF_Paint_", nPaintIndex, "_Prop" ) );
staticpropmgr->AddColorDecalToStaticProp( data.m_vStart, data.m_vOrigin, data.m_nHitBox - 1, nMaterial, false, tr, true, cColor );
}
else
{
int nMaterial = 0;
if ( pEntity->index == 0 )
{
nMaterial = decalsystem->GetDecalIndexForName( VarArgs( "%s%d%s", "TF_Paint_", nPaintIndex, "_World" ) );
}
else if ( pPlayer )
{
nMaterial = decalsystem->GetDecalIndexForName( VarArgs( "%s%d%s", "TF_Paint_", nPaintIndex, "_Player" ) );
}
else
{
nMaterial = decalsystem->GetDecalIndexForName( VarArgs( "%s%d%s", "TF_Paint_", nPaintIndex, "_Prop" ) );
}
pEntity->AddColoredDecal( data.m_vStart, data.m_vOrigin, data.m_vOrigin, data.m_nHitBox, nMaterial, false, tr, cColor );
}
}
DECLARE_CLIENT_EFFECT( "tf_paint_bomb", TFPaintBombSplashCallback );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void TFEnergyShieldImpactCallback( const CEffectData &data )
{
// Customized EnergySplash
C_BaseEntity *pEntity = data.GetEntity();
if ( !pEntity )
return;
Vector vecPos = data.m_vOrigin;
Vector vecNormal = data.m_vNormal;
Vector vecOffset = vecPos + ( vecNormal * 2.f );
float flMagnitude = data.m_flMagnitude;
float flFlashAlpha = 0.25f * flMagnitude;
float flLingerAlpha = 0.2f * flMagnitude;
float flFlashLife = 0.1f * flMagnitude;
float flLingerLife = 0.2f * flMagnitude;
float flRed = random->RandomFloat( 0.7f, 1.f );
float flGreen = random->RandomFloat( 0.25f, 0.45f );
float flBlue = random->RandomFloat( 0.25f, 0.45f );
// Impact
FX_AddQuad( vecPos, // Origin
vecNormal, // Normal
16.f * flMagnitude, // Start size
0.f, // End size
0.5f, // Size bias
flFlashAlpha, // Start alpha
0.f, // End alpha
0.1f, // Alpha bias
random->RandomInt( 0, 360 ), // Yaw
0.f, // Delta Yaw
Vector( flRed, flGreen, flBlue ), // Color
flFlashLife, // Lifetime
"effects/circle_nocull",
(FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) );
// Burn
FX_AddQuad( vecPos, // Origin
vecNormal, // Normal
6.f * flMagnitude, // Start size
18.f * flMagnitude, // End size
0.75f, // Size bias
flLingerAlpha, // Start alpha
0.f, // End alpha
0.4f, // Alpha bias
random->RandomInt( 0, 360 ), // Yaw
0.f, // Delta Yaw
Vector( flRed, flGreen, flBlue ), // Color
flLingerLife, // Lifetime
"effects/circle_nocull",
(FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) );
CSmartPtr< CSimpleEmitter > pEmitter;
pEmitter = CSimpleEmitter::Create( "C_EntityDissolve" );
pEmitter->SetSortOrigin( vecPos );
PMaterialHandle pMaterialSpark = pEmitter->GetPMaterial( "effects/spark" );
if ( !pMaterialSpark )
return;
SimpleParticle *sParticle;
for ( int j = 0; j < 6; j++ )
{
vecOffset.x = random->RandomFloat( -8.f, 8.f );
vecOffset.y = random->RandomFloat( -8.f, 8.f );
vecOffset.z = random->RandomFloat( 0.f, 4.f );
vecOffset += vecPos;
sParticle = (SimpleParticle *) pEmitter->AddParticle( sizeof(SimpleParticle), pMaterialSpark, vecOffset );
if ( !sParticle )
return;
sParticle->m_vecVelocity = Vector( random->RandomFloat( -8.f, 8.f ), random->RandomFloat( -8.f, 8.f ), random->RandomFloat( 16.f, 64.f ) );
sParticle->m_uchStartSize = random->RandomFloat( 1.5f, 3.f );
sParticle->m_flDieTime = random->RandomFloat( 0.2f, 0.4f );
sParticle->m_flLifetime = 0.f;
sParticle->m_flRoll = random->RandomInt( 0, 360 );
float flAlpha = 255.f;
sParticle->m_flRollDelta = random->RandomFloat( -16.f, 16.f );
sParticle->m_uchColor[0] = random->RandomInt( 120, 150 );
sParticle->m_uchColor[1] = random->RandomInt( 40, 70 );
sParticle->m_uchColor[2] = random->RandomInt( 40, 70 );
sParticle->m_uchStartAlpha = flAlpha;
sParticle->m_uchEndAlpha = 0;
sParticle->m_uchEndSize = 0;
}
}
DECLARE_CLIENT_EFFECT( "EnergyShieldImpact", TFEnergyShieldImpactCallback );