Skip to content

Commit 9b86359

Browse files
committed
[feature] beam_spotlight support
entity from the l4d engine branch. was in alien swarm, but not ported to mapbase yet
1 parent 40b8d39 commit 9b86359

5 files changed

Lines changed: 632 additions & 0 deletions

File tree

sp/src/game/client/c_baseentity.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,6 +2317,14 @@ inline bool C_BaseEntity::IsEnabledInToolView() const
23172317
#endif
23182318
}
23192319

2320+
//-----------------------------------------------------------------------------
2321+
// Client version of UTIL_Remove
2322+
//-----------------------------------------------------------------------------
2323+
inline void UTIL_Remove(C_BaseEntity* pEntity)
2324+
{
2325+
pEntity->Remove();
2326+
}
2327+
23202328
//-----------------------------------------------------------------------------
23212329
// Purpose:
23222330
// Input : -
Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
2+
//
3+
// Purpose:
4+
//
5+
//===========================================================================//
6+
7+
#include "cbase.h"
8+
#include "dlight.h"
9+
#include "iefx.h"
10+
11+
#include "beam_shared.h"
12+
13+
// memdbgon must be the last include file in a .cpp file!!!
14+
#include "tier0/memdbgon.h"
15+
16+
//-----------------------------------------------------------------------------
17+
// Purpose:
18+
//-----------------------------------------------------------------------------
19+
class CSpotlightTraceCacheEntry
20+
{
21+
public:
22+
CSpotlightTraceCacheEntry()
23+
{
24+
m_origin.Init();
25+
m_radius = -1.0f;
26+
}
27+
bool IsValidFor( const Vector &origin )
28+
{
29+
if ( m_radius > 0 && m_origin.DistToSqr(origin) < 1.0f )
30+
return true;
31+
return false;
32+
}
33+
void Cache( const Vector &origin, const trace_t &tr )
34+
{
35+
m_radius = (tr.endpos - origin).Length();
36+
m_origin = origin;
37+
}
38+
39+
Vector m_origin;
40+
float m_radius;
41+
};
42+
43+
static const int NUM_CACHE_ENTRIES = 64;
44+
45+
class C_BeamSpotLight : public C_BaseEntity
46+
{
47+
public:
48+
DECLARE_CLASS( C_BeamSpotLight, C_BaseEntity );
49+
DECLARE_CLIENTCLASS();
50+
51+
C_BeamSpotLight();
52+
~C_BeamSpotLight();
53+
54+
bool ShouldDraw();
55+
void ClientThink( void );
56+
void OnDataChanged( DataUpdateType_t updateType );
57+
void Release( void );
58+
59+
private:
60+
61+
Vector SpotlightCurrentPos(void);
62+
void SpotlightCreate(void);
63+
void SpotlightDestroy(void);
64+
65+
// Computes render info for a spotlight
66+
void ComputeRenderInfo();
67+
68+
private:
69+
70+
int m_nHaloIndex;
71+
int m_nRotationAxis;
72+
float m_flRotationSpeed;
73+
74+
75+
bool m_bSpotlightOn;
76+
bool m_bHasDynamicLight;
77+
78+
float m_flSpotlightMaxLength;
79+
float m_flSpotlightGoalWidth;
80+
float m_flHDRColorScale;
81+
82+
Vector m_vSpotlightTargetPos;
83+
Vector m_vSpotlightCurrentPos;
84+
Vector m_vSpotlightDir;
85+
86+
CHandle<C_Beam> m_hSpotlight;
87+
// zb14 - adding this due to sdk differences :3
88+
//CHandle<C_SpotlightEnd> m_hSpotlightTarget;
89+
90+
float m_flSpotlightCurLength;
91+
92+
float m_flLightScale;
93+
94+
dlight_t* m_pDynamicLight;
95+
96+
float m_lastTime;
97+
CSpotlightTraceCacheEntry *m_pCache;
98+
};
99+
100+
LINK_ENTITY_TO_CLASS( beam_spotlight, C_BeamSpotLight );
101+
102+
IMPLEMENT_CLIENTCLASS_DT( C_BeamSpotLight, DT_BeamSpotlight, CBeamSpotlight )
103+
RecvPropInt( RECVINFO(m_nHaloIndex) ),
104+
RecvPropBool( RECVINFO(m_bSpotlightOn) ),
105+
RecvPropBool( RECVINFO(m_bHasDynamicLight) ),
106+
RecvPropFloat( RECVINFO(m_flSpotlightMaxLength) ),
107+
RecvPropFloat( RECVINFO(m_flSpotlightGoalWidth) ),
108+
RecvPropFloat( RECVINFO(m_flHDRColorScale) ),
109+
RecvPropInt( RECVINFO(m_nRotationAxis) ),
110+
RecvPropFloat( RECVINFO(m_flRotationSpeed) ),
111+
END_RECV_TABLE()
112+
113+
//-----------------------------------------------------------------------------
114+
C_BeamSpotLight::C_BeamSpotLight()
115+
: m_vSpotlightTargetPos( vec3_origin )
116+
, m_vSpotlightCurrentPos( vec3_origin )
117+
, m_vSpotlightDir( vec3_origin )
118+
, m_flSpotlightCurLength( 0.0f )
119+
, m_flLightScale( 100.0f )
120+
, m_pDynamicLight( NULL )
121+
, m_lastTime( 0.0f )
122+
, m_pCache(NULL)
123+
{
124+
}
125+
126+
C_BeamSpotLight::~C_BeamSpotLight()
127+
{
128+
delete[] m_pCache;
129+
}
130+
131+
132+
//-----------------------------------------------------------------------------
133+
bool C_BeamSpotLight::ShouldDraw()
134+
{
135+
return false;
136+
}
137+
138+
//-----------------------------------------------------------------------------
139+
void C_BeamSpotLight::ClientThink( void )
140+
{
141+
float dt = gpGlobals->curtime - m_lastTime;
142+
if ( !m_lastTime )
143+
{
144+
dt = 0.0f;
145+
}
146+
m_lastTime = gpGlobals->curtime;
147+
148+
// ---------------------------------------------------
149+
// If I don't have a spotlight attempt to create one
150+
// ---------------------------------------------------
151+
if ( !m_hSpotlight )
152+
{
153+
if ( m_bSpotlightOn )
154+
{
155+
// Make the spotlight
156+
SpotlightCreate();
157+
}
158+
else
159+
{
160+
SetNextClientThink( CLIENT_THINK_NEVER );
161+
return;
162+
}
163+
}
164+
else if ( !m_bSpotlightOn )
165+
{
166+
SpotlightDestroy();
167+
SetNextClientThink( CLIENT_THINK_NEVER );
168+
return;
169+
}
170+
171+
// update rotation
172+
if ( m_flRotationSpeed != 0.0f )
173+
{
174+
QAngle angles = GetAbsAngles();
175+
angles[m_nRotationAxis] += m_flRotationSpeed * dt;
176+
angles[m_nRotationAxis] = anglemod(angles[m_nRotationAxis]);
177+
if ( !m_pCache )
178+
{
179+
m_pCache = new CSpotlightTraceCacheEntry[NUM_CACHE_ENTRIES];
180+
}
181+
182+
SetAbsAngles( angles );
183+
}
184+
m_vSpotlightCurrentPos = SpotlightCurrentPos();
185+
186+
Assert( m_hSpotlight );
187+
188+
m_hSpotlight->SetStartPos( GetAbsOrigin() );
189+
m_hSpotlight->SetEndPos( m_vSpotlightCurrentPos );
190+
191+
// Avoid sudden change in where beam fades out when cross disconinuities
192+
Vector dir = m_vSpotlightCurrentPos - GetAbsOrigin();
193+
float flBeamLength = VectorNormalize( dir );
194+
m_flSpotlightCurLength = (0.60*m_flSpotlightCurLength) + (0.4*flBeamLength);
195+
196+
ComputeRenderInfo();
197+
198+
m_hSpotlight->RelinkBeam();
199+
200+
//NDebugOverlay::Cross3D(GetAbsOrigin(),Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1);
201+
//NDebugOverlay::Cross3D(m_vSpotlightCurrentPos,Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1);
202+
//NDebugOverlay::Cross3D(m_vSpotlightTargetPos,Vector(-5,-5,-5),Vector(5,5,5),255,0,0,true,0.1);
203+
204+
// Do we need to keep updating?
205+
if ( !GetMoveParent() && m_flRotationSpeed == 0 )
206+
{
207+
// No reason to think again, we're not going to move unless there's a data change
208+
SetNextClientThink( CLIENT_THINK_NEVER );
209+
}
210+
}
211+
212+
//-----------------------------------------------------------------------------
213+
void C_BeamSpotLight::OnDataChanged( DataUpdateType_t updateType )
214+
{
215+
BaseClass::OnDataChanged( updateType );
216+
if ( updateType == DATA_UPDATE_CREATED )
217+
{
218+
m_flSpotlightCurLength = m_flSpotlightMaxLength;
219+
}
220+
221+
// On a data change always think again
222+
SetNextClientThink( CLIENT_THINK_ALWAYS );
223+
}
224+
225+
//------------------------------------------------------------------------------
226+
void C_BeamSpotLight::Release()
227+
{
228+
SpotlightDestroy();
229+
BaseClass::Release();
230+
}
231+
232+
//------------------------------------------------------------------------------
233+
void C_BeamSpotLight::SpotlightCreate(void)
234+
{
235+
m_vSpotlightTargetPos = SpotlightCurrentPos();
236+
237+
{
238+
//C_Beam *beam = CBeam::BeamCreate( "sprites/spotlight.vmt", m_flSpotlightGoalWidth );
239+
C_Beam *beam = C_Beam::BeamCreate( "sprites/glow_test02.vmt", m_flSpotlightGoalWidth );
240+
// Beam only exists client side
241+
ClientEntityList().AddNonNetworkableEntity( beam );
242+
m_hSpotlight = beam;
243+
}
244+
245+
// Set the temporary spawnflag on the beam so it doesn't save (we'll recreate it on restore)
246+
m_hSpotlight->SetHDRColorScale( m_flHDRColorScale );
247+
//const color24 c = GetRenderColor();
248+
const color32 c = GetRenderColor();
249+
m_hSpotlight->SetColor( c.r, c.g, c.b );
250+
m_hSpotlight->SetHaloTexture(m_nHaloIndex);
251+
m_hSpotlight->SetHaloScale(60);
252+
m_hSpotlight->SetEndWidth(m_flSpotlightGoalWidth);
253+
m_hSpotlight->SetBeamFlags( (FBEAM_SHADEOUT|FBEAM_NOTILE) );
254+
m_hSpotlight->SetBrightness( 64 );
255+
m_hSpotlight->SetNoise( 0 );
256+
257+
m_hSpotlight->PointsInit( GetAbsOrigin(), m_vSpotlightTargetPos );
258+
}
259+
260+
//------------------------------------------------------------------------------
261+
void C_BeamSpotLight::SpotlightDestroy(void)
262+
{
263+
if ( m_hSpotlight )
264+
{
265+
UTIL_Remove( m_hSpotlight );
266+
m_hSpotlight.Term();
267+
}
268+
}
269+
270+
//------------------------------------------------------------------------------
271+
Vector C_BeamSpotLight::SpotlightCurrentPos(void)
272+
{
273+
QAngle angles = GetAbsAngles();
274+
GetVectors( &m_vSpotlightDir, NULL, NULL );
275+
Vector position = GetAbsOrigin();
276+
int cacheIndex = -1;
277+
if ( m_pCache )
278+
{
279+
cacheIndex = int( angles[m_nRotationAxis] * float(NUM_CACHE_ENTRIES) * (1.0f / 360.0f)) & (NUM_CACHE_ENTRIES - 1);
280+
if ( m_pCache[cacheIndex].IsValidFor(GetAbsOrigin()) )
281+
{
282+
return position + m_vSpotlightDir * m_pCache[cacheIndex].m_radius;
283+
}
284+
}
285+
286+
287+
// Get beam end point. Only collide with solid objects, not npcs
288+
trace_t tr;
289+
UTIL_TraceLine( position, position + (m_vSpotlightDir * 2 * m_flSpotlightMaxLength), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
290+
if ( cacheIndex >= 0 )
291+
{
292+
m_pCache[cacheIndex].Cache(position, tr);
293+
}
294+
295+
return tr.endpos;
296+
}
297+
298+
//-----------------------------------------------------------------------------
299+
// Computes render info for a spotlight
300+
//-----------------------------------------------------------------------------
301+
void C_BeamSpotLight::ComputeRenderInfo()
302+
{
303+
// Fade out spotlight end if past max length.
304+
if ( m_flSpotlightCurLength > 2*m_flSpotlightMaxLength )
305+
{
306+
//SetRenderAlpha( 0 );
307+
SetRenderColorA( 0 );
308+
m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength );
309+
}
310+
else if ( m_flSpotlightCurLength > m_flSpotlightMaxLength )
311+
{
312+
//SetRenderAlpha( (1-((m_flSpotlightCurLength-m_flSpotlightMaxLength)/m_flSpotlightMaxLength)) );
313+
SetRenderColorA( (1-((m_flSpotlightCurLength-m_flSpotlightMaxLength)/m_flSpotlightMaxLength)) );
314+
m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength );
315+
}
316+
else
317+
{
318+
//SetRenderAlpha( 1.0 );
319+
SetRenderColorA( 1.0 );
320+
m_hSpotlight->SetFadeLength( m_flSpotlightCurLength );
321+
}
322+
323+
// Adjust end width to keep beam width constant
324+
float flNewWidth = m_flSpotlightGoalWidth * (m_flSpotlightCurLength / m_flSpotlightMaxLength);
325+
flNewWidth = clamp(flNewWidth, 0, MAX_BEAM_WIDTH );
326+
m_hSpotlight->SetEndWidth(flNewWidth);
327+
328+
if ( m_bHasDynamicLight )
329+
{
330+
// <<TODO>> - magic number 1.8 depends on sprite size
331+
m_flLightScale = 1.8*flNewWidth;
332+
333+
if ( m_flLightScale > 0 )
334+
{
335+
//const color24 c = GetRenderColor();
336+
const color32 c = GetRenderColor();
337+
//float a = GetRenderAlpha() / 255.0f;
338+
float a = GetRenderColor().a / 255.0f;
339+
ColorRGBExp32 color;
340+
color.r = c.r * a;
341+
color.g = c.g * a;
342+
color.b = c.b * a;
343+
color.exponent = 0;
344+
if ( color.r == 0 && color.g == 0 && color.b == 0 )
345+
return;
346+
347+
// Deal with the environment light
348+
if ( !m_pDynamicLight || (m_pDynamicLight->key != index) )
349+
{
350+
m_pDynamicLight = effects->CL_AllocDlight( index );
351+
assert (m_pDynamicLight);
352+
}
353+
354+
//m_pDynamicLight->flags = DLIGHT_NO_MODEL_ILLUMINATION;
355+
m_pDynamicLight->radius = m_flLightScale*3.0f;
356+
m_pDynamicLight->origin = GetAbsOrigin() + Vector(0,0,5);
357+
m_pDynamicLight->die = gpGlobals->curtime + 0.05f;
358+
m_pDynamicLight->color = color;
359+
}
360+
}
361+
}
362+

sp/src/game/client/client_base.vpc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ $Project
228228
$File "c_baseplayer.cpp"
229229
$File "c_baseviewmodel.cpp"
230230
$File "c_breakableprop.cpp"
231+
$File "c_beamspotlight.cpp"
231232
$File "c_colorcorrection.cpp"
232233
$File "c_colorcorrectionvolume.cpp"
233234
$File "c_dynamiclight.cpp"

0 commit comments

Comments
 (0)