Source code
Revision control
1
/***
2
*
3
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
4
*
5
* This product contains software technology licensed from Id
6
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
7
* All Rights Reserved.
8
*
9
* Use, distribution, and modification of this source code and/or resulting
10
* object code is restricted to non-commercial enhancements to products from
11
* Valve LLC. All other use, distribution, or modification is prohibited
12
* without written permission from Valve LLC.
13
*
14
****/
15
#include "extdll.h"
16
#include "util.h"
17
#include "cbase.h"
18
#include "monsters.h"
19
#include "customentity.h"
20
#include "effects.h"
21
#include "weapons.h"
22
#include "decals.h"
23
#include "func_break.h"
24
#include "shake.h"
25
26
#define SF_GIBSHOOTER_REPEATABLE 1 // allows a gibshooter to be refired
27
28
#define SF_FUNNEL_REVERSE 1 // funnel effect repels particles instead of attracting them.
29
30
31
// Lightning target, just alias landmark
32
LINK_ENTITY_TO_CLASS( info_target, CPointEntity );
33
34
35
class CBubbling : public CBaseEntity
36
{
37
public:
38
void Spawn( void );
39
void Precache( void );
40
void KeyValue( KeyValueData *pkvd );
41
42
void EXPORT FizzThink( void );
43
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
44
45
virtual int Save( CSave &save );
46
virtual int Restore( CRestore &restore );
47
virtual int ObjectCaps( void ) { return CBaseEntity::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
48
static TYPEDESCRIPTION m_SaveData[];
49
50
int m_density;
51
int m_frequency;
52
int m_bubbleModel;
53
int m_state;
54
};
55
56
LINK_ENTITY_TO_CLASS( env_bubbles, CBubbling );
57
58
TYPEDESCRIPTION CBubbling::m_SaveData[] =
59
{
60
DEFINE_FIELD( CBubbling, m_density, FIELD_INTEGER ),
61
DEFINE_FIELD( CBubbling, m_frequency, FIELD_INTEGER ),
62
DEFINE_FIELD( CBubbling, m_state, FIELD_INTEGER ),
63
// Let spawn restore this!
64
// DEFINE_FIELD( CBubbling, m_bubbleModel, FIELD_INTEGER ),
65
};
66
67
IMPLEMENT_SAVERESTORE( CBubbling, CBaseEntity );
68
69
70
#define SF_BUBBLES_STARTOFF 0x0001
71
72
void CBubbling::Spawn( void )
73
{
74
Precache( );
75
SET_MODEL( ENT(pev), STRING(pev->model) ); // Set size
76
77
pev->solid = SOLID_NOT; // Remove model & collisions
78
pev->renderamt = 0; // The engine won't draw this model if this is set to 0 and blending is on
79
pev->rendermode = kRenderTransTexture;
80
int speed = pev->speed > 0 ? static_cast<int>(pev->speed) : static_cast<int>(-pev->speed);
81
82
// HACKHACK!!! - Speed in rendercolor
83
pev->rendercolor.x = speed >> 8;
84
pev->rendercolor.y = speed & 255;
85
pev->rendercolor.z = (pev->speed < 0) ? 1 : 0;
86
87
88
if ( !(pev->spawnflags & SF_BUBBLES_STARTOFF) )
89
{
90
SetThink( &CBubbling::FizzThink );
91
pev->nextthink = gpGlobals->time + 2.0;
92
m_state = 1;
93
}
94
else
95
m_state = 0;
96
}
97
98
void CBubbling::Precache( void )
99
{
100
m_bubbleModel = PRECACHE_MODEL("sprites/bubble.spr"); // Precache bubble sprite
101
}
102
103
104
void CBubbling::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
105
{
106
if ( ShouldToggle( useType, m_state ) )
107
m_state = !m_state;
108
109
if ( m_state )
110
{
111
SetThink( &CBubbling::FizzThink );
112
pev->nextthink = gpGlobals->time + 0.1;
113
}
114
else
115
{
116
SetThink( NULL );
117
pev->nextthink = 0;
118
}
119
}
120
121
122
void CBubbling::KeyValue( KeyValueData *pkvd )
123
{
124
if (FStrEq(pkvd->szKeyName, "density"))
125
{
126
m_density = atoi(pkvd->szValue);
127
pkvd->fHandled = TRUE;
128
}
129
else if (FStrEq(pkvd->szKeyName, "frequency"))
130
{
131
m_frequency = atoi(pkvd->szValue);
132
pkvd->fHandled = TRUE;
133
}
134
else if (FStrEq(pkvd->szKeyName, "current"))
135
{
136
pev->speed = atoi(pkvd->szValue);
137
pkvd->fHandled = TRUE;
138
}
139
else
140
CBaseEntity::KeyValue( pkvd );
141
}
142
143
144
void CBubbling::FizzThink( void )
145
{
146
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, VecBModelOrigin(pev) );
147
WRITE_BYTE( TE_FIZZ );
148
WRITE_SHORT( (short)ENTINDEX( edict() ) );
149
WRITE_SHORT( (short)m_bubbleModel );
150
WRITE_BYTE( m_density );
151
MESSAGE_END();
152
153
if ( m_frequency > 19 )
154
pev->nextthink = gpGlobals->time + 0.5;
155
else
156
pev->nextthink = gpGlobals->time + 2.5 - (0.1 * m_frequency);
157
}
158
159
// --------------------------------------------------
160
//
161
// Beams
162
//
163
// --------------------------------------------------
164
165
LINK_ENTITY_TO_CLASS( beam, CBeam );
166
167
void CBeam::Spawn( void )
168
{
169
pev->solid = SOLID_NOT; // Remove model & collisions
170
Precache( );
171
}
172
173
void CBeam::Precache( void )
174
{
175
if ( pev->owner )
176
SetStartEntity( ENTINDEX( pev->owner ) );
177
if ( pev->aiment )
178
SetEndEntity( ENTINDEX( pev->aiment ) );
179
}
180
181
void CBeam::SetStartEntity( int entityIndex )
182
{
183
pev->sequence = (entityIndex & 0x0FFF) | ((pev->sequence&0xF000)<<12);
184
pev->owner = g_engfuncs.pfnPEntityOfEntIndex( entityIndex );
185
}
186
187
void CBeam::SetEndEntity( int entityIndex )
188
{
189
pev->skin = (entityIndex & 0x0FFF) | ((pev->skin&0xF000)<<12);
190
pev->aiment = g_engfuncs.pfnPEntityOfEntIndex( entityIndex );
191
}
192
193
194
// These don't take attachments into account
195
const Vector &CBeam::GetStartPos( void )
196
{
197
if ( GetType() == BEAM_ENTS )
198
{
199
edict_t *pent = g_engfuncs.pfnPEntityOfEntIndex( GetStartEntity() );
200
return pent->v.origin;
201
}
202
return pev->origin;
203
}
204
205
206
const Vector &CBeam::GetEndPos( void )
207
{
208
int type = GetType();
209
if ( type == BEAM_POINTS || type == BEAM_HOSE )
210
{
211
return pev->angles;
212
}
213
214
edict_t *pent = g_engfuncs.pfnPEntityOfEntIndex( GetEndEntity() );
215
if ( pent )
216
return pent->v.origin;
217
return pev->angles;
218
}
219
220
221
CBeam *CBeam::BeamCreate( const char *pSpriteName, int width )
222
{
223
// Create a new entity with CBeam private data
224
CBeam *pBeam = GetClassPtr( (CBeam *)NULL );
225
pBeam->pev->classname = MAKE_STRING("beam");
226
227
pBeam->BeamInit( pSpriteName, width );
228
229
return pBeam;
230
}
231
232
233
void CBeam::BeamInit( const char *pSpriteName, int width )
234
{
235
pev->flags |= FL_CUSTOMENTITY;
236
SetColor( 255, 255, 255 );
237
SetBrightness( 255 );
238
SetNoise( 0 );
239
SetFrame( 0 );
240
SetScrollRate( 0 );
241
pev->model = MAKE_STRING( pSpriteName );
242
SetTexture( PRECACHE_MODEL( (char *)pSpriteName ) );
243
SetWidth( width );
244
pev->skin = 0;
245
pev->sequence = 0;
246
pev->rendermode = 0;
247
}
248
249
250
void CBeam::PointsInit( const Vector &start, const Vector &end )
251
{
252
SetType( BEAM_POINTS );
253
SetStartPos( start );
254
SetEndPos( end );
255
SetStartAttachment( 0 );
256
SetEndAttachment( 0 );
257
RelinkBeam();
258
}
259
260
261
void CBeam::HoseInit( const Vector &start, const Vector &direction )
262
{
263
SetType( BEAM_HOSE );
264
SetStartPos( start );
265
SetEndPos( direction );
266
SetStartAttachment( 0 );
267
SetEndAttachment( 0 );
268
RelinkBeam();
269
}
270
271
272
void CBeam::PointEntInit( const Vector &start, int endIndex )
273
{
274
SetType( BEAM_ENTPOINT );
275
SetStartPos( start );
276
SetEndEntity( endIndex );
277
SetStartAttachment( 0 );
278
SetEndAttachment( 0 );
279
RelinkBeam();
280
}
281
282
void CBeam::EntsInit( int startIndex, int endIndex )
283
{
284
SetType( BEAM_ENTS );
285
SetStartEntity( startIndex );
286
SetEndEntity( endIndex );
287
SetStartAttachment( 0 );
288
SetEndAttachment( 0 );
289
RelinkBeam();
290
}
291
292
293
void CBeam::RelinkBeam( void )
294
{
295
const Vector &startPos = GetStartPos(), &endPos = GetEndPos();
296
297
pev->mins.x = min( startPos.x, endPos.x );
298
pev->mins.y = min( startPos.y, endPos.y );
299
pev->mins.z = min( startPos.z, endPos.z );
300
pev->maxs.x = max( startPos.x, endPos.x );
301
pev->maxs.y = max( startPos.y, endPos.y );
302
pev->maxs.z = max( startPos.z, endPos.z );
303
pev->mins = pev->mins - pev->origin;
304
pev->maxs = pev->maxs - pev->origin;
305
306
UTIL_SetSize( pev, pev->mins, pev->maxs );
307
UTIL_SetOrigin( pev, pev->origin );
308
}
309
310
#if 0
311
void CBeam::SetObjectCollisionBox( void )
312
{
313
const Vector &startPos = GetStartPos(), &endPos = GetEndPos();
314
315
pev->absmin.x = min( startPos.x, endPos.x );
316
pev->absmin.y = min( startPos.y, endPos.y );
317
pev->absmin.z = min( startPos.z, endPos.z );
318
pev->absmax.x = max( startPos.x, endPos.x );
319
pev->absmax.y = max( startPos.y, endPos.y );
320
pev->absmax.z = max( startPos.z, endPos.z );
321
}
322
#endif
323
324
325
void CBeam::TriggerTouch( CBaseEntity *pOther )
326
{
327
if ( pOther->pev->flags & (FL_CLIENT | FL_MONSTER) )
328
{
329
if ( pev->owner )
330
{
331
CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner);
332
pOwner->Use( pOther, this, USE_TOGGLE, 0 );
333
}
334
ALERT( at_console, "Firing targets!!!\n" );
335
}
336
}
337
338
339
CBaseEntity *CBeam::RandomTargetname( const char *szName )
340
{
341
int total = 0;
342
343
CBaseEntity *pEntity = NULL;
344
CBaseEntity *pNewEntity = NULL;
345
while ((pNewEntity = UTIL_FindEntityByTargetname( pNewEntity, szName )) != NULL)
346
{
347
total++;
348
if (RANDOM_LONG(0,total-1) < 1)
349
pEntity = pNewEntity;
350
}
351
return pEntity;
352
}
353
354
355
void CBeam::DoSparks( const Vector &start, const Vector &end )
356
{
357
if ( pev->spawnflags & (SF_BEAM_SPARKSTART|SF_BEAM_SPARKEND) )
358
{
359
if ( pev->spawnflags & SF_BEAM_SPARKSTART )
360
{
361
UTIL_Sparks( start );
362
}
363
if ( pev->spawnflags & SF_BEAM_SPARKEND )
364
{
365
UTIL_Sparks( end );
366
}
367
}
368
}
369
370
371
class CLightning : public CBeam
372
{
373
public:
374
void Spawn( void );
375
void Precache( void );
376
void KeyValue( KeyValueData *pkvd );
377
void Activate( void );
378
379
void EXPORT StrikeThink( void );
380
void EXPORT DamageThink( void );
381
void RandomArea( void );
382
void RandomPoint( Vector &vecSrc );
383
void Zap( const Vector &vecSrc, const Vector &vecDest );
384
void EXPORT StrikeUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
385
void EXPORT ToggleUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
386
387
inline BOOL ServerSide( void )
388
{
389
if ( m_life == 0 && !(pev->spawnflags & SF_BEAM_RING) )
390
return TRUE;
391
return FALSE;
392
}
393
394
virtual int Save( CSave &save );
395
virtual int Restore( CRestore &restore );
396
static TYPEDESCRIPTION m_SaveData[];
397
398
void BeamUpdateVars( void );
399
400
int m_active;
401
int m_iszStartEntity;
402
int m_iszEndEntity;
403
float m_life;
404
int m_boltWidth;
405
int m_noiseAmplitude;
406
int m_brightness;
407
int m_speed;
408
float m_restrike;
409
int m_spriteTexture;
410
int m_iszSpriteName;
411
int m_frameStart;
412
413
float m_radius;
414
};
415
416
LINK_ENTITY_TO_CLASS( env_lightning, CLightning );
417
LINK_ENTITY_TO_CLASS( env_beam, CLightning );
418
419
// UNDONE: Jay -- This is only a test
420
#if _DEBUG
421
class CTripBeam : public CLightning
422
{
423
void Spawn( void );
424
};
425
LINK_ENTITY_TO_CLASS( trip_beam, CTripBeam );
426
427
void CTripBeam::Spawn( void )
428
{
429
CLightning::Spawn();
430
SetTouch( &CBeam::TriggerTouch );
431
pev->solid = SOLID_TRIGGER;
432
RelinkBeam();
433
}
434
#endif
435
436
437
438
TYPEDESCRIPTION CLightning::m_SaveData[] =
439
{
440
DEFINE_FIELD( CLightning, m_active, FIELD_INTEGER ),
441
DEFINE_FIELD( CLightning, m_iszStartEntity, FIELD_STRING ),
442
DEFINE_FIELD( CLightning, m_iszEndEntity, FIELD_STRING ),
443
DEFINE_FIELD( CLightning, m_life, FIELD_FLOAT ),
444
DEFINE_FIELD( CLightning, m_boltWidth, FIELD_INTEGER ),
445
DEFINE_FIELD( CLightning, m_noiseAmplitude, FIELD_INTEGER ),
446
DEFINE_FIELD( CLightning, m_brightness, FIELD_INTEGER ),
447
DEFINE_FIELD( CLightning, m_speed, FIELD_INTEGER ),
448
DEFINE_FIELD( CLightning, m_restrike, FIELD_FLOAT ),
449
DEFINE_FIELD( CLightning, m_spriteTexture, FIELD_INTEGER ),
450
DEFINE_FIELD( CLightning, m_iszSpriteName, FIELD_STRING ),
451
DEFINE_FIELD( CLightning, m_frameStart, FIELD_INTEGER ),
452
DEFINE_FIELD( CLightning, m_radius, FIELD_FLOAT ),
453
};
454
455
IMPLEMENT_SAVERESTORE( CLightning, CBeam );
456
457
458
void CLightning::Spawn( void )
459
{
460
if ( FStringNull( m_iszSpriteName ) )
461
{
462
SetThink( &CLightning::SUB_Remove );
463
return;
464
}
465
pev->solid = SOLID_NOT; // Remove model & collisions
466
Precache( );
467
468
pev->dmgtime = gpGlobals->time;
469
470
if ( ServerSide() )
471
{
472
SetThink( NULL );
473
if ( pev->dmg > 0 )
474
{
475
SetThink( &CLightning::DamageThink );
476
pev->nextthink = gpGlobals->time + 0.1;
477
}
478
if ( pev->targetname )
479
{
480
if ( !(pev->spawnflags & SF_BEAM_STARTON) )
481
{
482
pev->effects = EF_NODRAW;
483
m_active = 0;
484
pev->nextthink = 0;
485
}
486
else
487
m_active = 1;
488
489
SetUse( &CLightning::ToggleUse );
490
}
491
}
492
else
493
{
494
m_active = 0;
495
if ( !FStringNull(pev->targetname) )
496
{
497
SetUse( &CLightning::StrikeUse );
498
}
499
if ( FStringNull(pev->targetname) || FBitSet(pev->spawnflags, SF_BEAM_STARTON) )
500
{
501
SetThink( &CLightning::StrikeThink );
502
pev->nextthink = gpGlobals->time + 1.0;
503
}
504
}
505
}
506
507
void CLightning::Precache( void )
508
{
509
m_spriteTexture = PRECACHE_MODEL( (char *)STRING(m_iszSpriteName) );
510
CBeam::Precache();
511
}
512
513
514
void CLightning::Activate( void )
515
{
516
if ( ServerSide() )
517
BeamUpdateVars();
518
}
519
520
521
void CLightning::KeyValue( KeyValueData *pkvd )
522
{
523
if (FStrEq(pkvd->szKeyName, "LightningStart"))
524
{
525
m_iszStartEntity = ALLOC_STRING( pkvd->szValue );
526
pkvd->fHandled = TRUE;
527
}
528
else if (FStrEq(pkvd->szKeyName, "LightningEnd"))
529
{
530
m_iszEndEntity = ALLOC_STRING( pkvd->szValue );
531
pkvd->fHandled = TRUE;
532
}
533
else if (FStrEq(pkvd->szKeyName, "life"))
534
{
535
m_life = atof(pkvd->szValue);
536
pkvd->fHandled = TRUE;
537
}
538
else if (FStrEq(pkvd->szKeyName, "BoltWidth"))
539
{
540
m_boltWidth = atoi(pkvd->szValue);
541
pkvd->fHandled = TRUE;
542
}
543
else if (FStrEq(pkvd->szKeyName, "NoiseAmplitude"))
544
{
545
m_noiseAmplitude = atoi(pkvd->szValue);
546
pkvd->fHandled = TRUE;
547
}
548
else if (FStrEq(pkvd->szKeyName, "TextureScroll"))
549
{
550
m_speed = atoi(pkvd->szValue);
551
pkvd->fHandled = TRUE;
552
}
553
else if (FStrEq(pkvd->szKeyName, "StrikeTime"))
554
{
555
m_restrike = atof(pkvd->szValue);
556
pkvd->fHandled = TRUE;
557
}
558
else if (FStrEq(pkvd->szKeyName, "texture"))
559
{
560
m_iszSpriteName = ALLOC_STRING(pkvd->szValue);
561
pkvd->fHandled = TRUE;
562
}
563
else if (FStrEq(pkvd->szKeyName, "framestart"))
564
{
565
m_frameStart = atoi(pkvd->szValue);
566
pkvd->fHandled = TRUE;
567
}
568
else if (FStrEq(pkvd->szKeyName, "Radius"))
569
{
570
m_radius = atof( pkvd->szValue );
571
pkvd->fHandled = TRUE;
572
}
573
else if (FStrEq(pkvd->szKeyName, "damage"))
574
{
575
pev->dmg = atof(pkvd->szValue);
576
pkvd->fHandled = TRUE;
577
}
578
else
579
CBeam::KeyValue( pkvd );
580
}
581
582
583
void CLightning::ToggleUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
584
{
585
if ( !ShouldToggle( useType, m_active ) )
586
return;
587
if ( m_active )
588
{
589
m_active = 0;
590
pev->effects |= EF_NODRAW;
591
pev->nextthink = 0;
592
}
593
else
594
{
595
m_active = 1;
596
pev->effects &= ~EF_NODRAW;
597
DoSparks( GetStartPos(), GetEndPos() );
598
if ( pev->dmg > 0 )
599
{
600
pev->nextthink = gpGlobals->time;
601
pev->dmgtime = gpGlobals->time;
602
}
603
}
604
}
605
606
607
void CLightning::StrikeUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
608
{
609
if ( !ShouldToggle( useType, m_active ) )
610
return;
611
612
if ( m_active )
613
{
614
m_active = 0;
615
SetThink( NULL );
616
}
617
else
618
{
619
SetThink( &CLightning::StrikeThink );
620
pev->nextthink = gpGlobals->time + 0.1;
621
}
622
623
if ( !FBitSet( pev->spawnflags, SF_BEAM_TOGGLE ) )
624
SetUse( NULL );
625
}
626
627
628
int IsPointEntity( CBaseEntity *pEnt )
629
{
630
if ( !pEnt->pev->modelindex )
631
return 1;
632
if ( FClassnameIs( pEnt->pev, "info_target" ) || FClassnameIs( pEnt->pev, "info_landmark" ) || FClassnameIs( pEnt->pev, "path_corner" ) )
633
return 1;
634
635
return 0;
636
}
637
638
639
void CLightning::StrikeThink( void )
640
{
641
if ( m_life != 0 )
642
{
643
if ( pev->spawnflags & SF_BEAM_RANDOM )
644
pev->nextthink = gpGlobals->time + m_life + RANDOM_FLOAT( 0, m_restrike );
645
else
646
pev->nextthink = gpGlobals->time + m_life + m_restrike;
647
}
648
m_active = 1;
649
650
if (FStringNull(m_iszEndEntity))
651
{
652
if (FStringNull(m_iszStartEntity))
653
{
654
RandomArea( );
655
}
656
else
657
{
658
CBaseEntity *pStart = RandomTargetname( STRING(m_iszStartEntity) );
659
if (pStart != NULL)
660
RandomPoint( pStart->pev->origin );
661
else
662
ALERT( at_console, "env_beam: unknown entity \"%s\"\n", STRING(m_iszStartEntity) );
663
}
664
return;
665
}
666
667
CBaseEntity *pStart = RandomTargetname( STRING(m_iszStartEntity) );
668
CBaseEntity *pEnd = RandomTargetname( STRING(m_iszEndEntity) );
669
670
if ( pStart != NULL && pEnd != NULL )
671
{
672
if ( IsPointEntity( pStart ) || IsPointEntity( pEnd ) )
673
{
674
if ( pev->spawnflags & SF_BEAM_RING)
675
{
676
// don't work
677
return;
678
}
679
}
680
681
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
682
if ( IsPointEntity( pStart ) || IsPointEntity( pEnd ) )
683
{
684
if ( !IsPointEntity( pEnd ) ) // One point entity must be in pEnd
685
{
686
CBaseEntity *pTemp;
687
pTemp = pStart;
688
pStart = pEnd;
689
pEnd = pTemp;
690
}
691
if ( !IsPointEntity( pStart ) ) // One sided
692
{
693
WRITE_BYTE( TE_BEAMENTPOINT );
694
WRITE_SHORT( pStart->entindex() );
695
WRITE_COORD( pEnd->pev->origin.x);
696
WRITE_COORD( pEnd->pev->origin.y);
697
WRITE_COORD( pEnd->pev->origin.z);
698
}
699
else
700
{
701
WRITE_BYTE( TE_BEAMPOINTS);
702
WRITE_COORD( pStart->pev->origin.x);
703
WRITE_COORD( pStart->pev->origin.y);
704
WRITE_COORD( pStart->pev->origin.z);
705
WRITE_COORD( pEnd->pev->origin.x);
706
WRITE_COORD( pEnd->pev->origin.y);
707
WRITE_COORD( pEnd->pev->origin.z);
708
}
709
710
711
}
712
else
713
{
714
if ( pev->spawnflags & SF_BEAM_RING)
715
WRITE_BYTE( TE_BEAMRING );
716
else
717
WRITE_BYTE( TE_BEAMENTS );
718
WRITE_SHORT( pStart->entindex() );
719
WRITE_SHORT( pEnd->entindex() );
720
}
721
722
WRITE_SHORT( m_spriteTexture );
723
WRITE_BYTE( m_frameStart ); // framestart
724
WRITE_BYTE( (int)pev->framerate); // framerate
725
WRITE_BYTE( (int)(m_life*10.0) ); // life
726
WRITE_BYTE( m_boltWidth ); // width
727
WRITE_BYTE( m_noiseAmplitude ); // noise
728
WRITE_BYTE( (int)pev->rendercolor.x ); // r, g, b
729
WRITE_BYTE( (int)pev->rendercolor.y ); // r, g, b
730
WRITE_BYTE( (int)pev->rendercolor.z ); // r, g, b
731
WRITE_BYTE( (int)pev->renderamt ); // brightness
732
WRITE_BYTE( m_speed ); // speed
733
MESSAGE_END();
734
DoSparks( pStart->pev->origin, pEnd->pev->origin );
735
if ( pev->dmg > 0 )
736
{
737
TraceResult tr;
738
UTIL_TraceLine( pStart->pev->origin, pEnd->pev->origin, dont_ignore_monsters, NULL, &tr );
739
BeamDamageInstant( &tr, pev->dmg );
740
}
741
}
742
}
743
744
745
void CBeam::BeamDamage( TraceResult *ptr )
746
{
747
RelinkBeam();
748
if ( ptr->flFraction != 1.0 && ptr->pHit != NULL )
749
{
750
CBaseEntity *pHit = CBaseEntity::Instance(ptr->pHit);
751
if ( pHit )
752
{
753
ClearMultiDamage();
754
pHit->TraceAttack( pev, pev->dmg * (gpGlobals->time - pev->dmgtime), (ptr->vecEndPos - pev->origin).Normalize(), ptr, DMG_ENERGYBEAM );
755
ApplyMultiDamage( pev, pev );
756
if ( pev->spawnflags & SF_BEAM_DECALS )
757
{
758
if ( pHit->IsBSPModel() )
759
UTIL_DecalTrace( ptr, DECAL_BIGSHOT1 + RANDOM_LONG(0,4) );
760
}
761
}
762
}
763
pev->dmgtime = gpGlobals->time;
764
}
765
766
767
void CLightning::DamageThink( void )
768
{
769
pev->nextthink = gpGlobals->time + 0.1;
770
TraceResult tr;
771
UTIL_TraceLine( GetStartPos(), GetEndPos(), dont_ignore_monsters, NULL, &tr );
772
BeamDamage( &tr );
773
}
774
775
776
777
void CLightning::Zap( const Vector &vecSrc, const Vector &vecDest )
778
{
779
#if 1
780
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
781
WRITE_BYTE( TE_BEAMPOINTS);
782
WRITE_COORD(vecSrc.x);
783
WRITE_COORD(vecSrc.y);
784
WRITE_COORD(vecSrc.z);
785
WRITE_COORD(vecDest.x);
786
WRITE_COORD(vecDest.y);
787
WRITE_COORD(vecDest.z);
788
WRITE_SHORT( m_spriteTexture );
789
WRITE_BYTE( m_frameStart ); // framestart
790
WRITE_BYTE( (int)pev->framerate); // framerate
791
WRITE_BYTE( (int)(m_life*10.0) ); // life
792
WRITE_BYTE( m_boltWidth ); // width
793
WRITE_BYTE( m_noiseAmplitude ); // noise
794
WRITE_BYTE( (int)pev->rendercolor.x ); // r, g, b
795
WRITE_BYTE( (int)pev->rendercolor.y ); // r, g, b
796
WRITE_BYTE( (int)pev->rendercolor.z ); // r, g, b
797
WRITE_BYTE( (int)pev->renderamt ); // brightness
798
WRITE_BYTE( m_speed ); // speed
799
MESSAGE_END();
800
#else
801
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
802
WRITE_BYTE(TE_LIGHTNING);
803
WRITE_COORD(vecSrc.x);
804
WRITE_COORD(vecSrc.y);
805
WRITE_COORD(vecSrc.z);
806
WRITE_COORD(vecDest.x);
807
WRITE_COORD(vecDest.y);
808
WRITE_COORD(vecDest.z);
809
WRITE_BYTE(10);
810
WRITE_BYTE(50);
811
WRITE_BYTE(40);
812
WRITE_SHORT(m_spriteTexture);
813
MESSAGE_END();
814
#endif
815
DoSparks( vecSrc, vecDest );
816
}
817
818
void CLightning::RandomArea( void )
819
{
820
int iLoops = 0;
821
822
for (iLoops = 0; iLoops < 10; iLoops++)
823
{
824
Vector vecSrc = pev->origin;
825
826
Vector vecDir1 = Vector( RANDOM_FLOAT( -1.0, 1.0 ), RANDOM_FLOAT( -1.0, 1.0 ),RANDOM_FLOAT( -1.0, 1.0 ) );
827
vecDir1 = vecDir1.Normalize();
828
TraceResult tr1;
829
UTIL_TraceLine( vecSrc, vecSrc + vecDir1 * m_radius, ignore_monsters, ENT(pev), &tr1 );
830
831
if (tr1.flFraction == 1.0)
832
continue;
833
834
Vector vecDir2;
835
do {
836
vecDir2 = Vector( RANDOM_FLOAT( -1.0, 1.0 ), RANDOM_FLOAT( -1.0, 1.0 ),RANDOM_FLOAT( -1.0, 1.0 ) );
837
} while (DotProduct(vecDir1, vecDir2 ) > 0);
838
vecDir2 = vecDir2.Normalize();
839
TraceResult tr2;
840
UTIL_TraceLine( vecSrc, vecSrc + vecDir2 * m_radius, ignore_monsters, ENT(pev), &tr2 );
841
842
if (tr2.flFraction == 1.0)
843
continue;
844
845
if ((tr1.vecEndPos - tr2.vecEndPos).Length() < m_radius * 0.1)
846
continue;
847
848
UTIL_TraceLine( tr1.vecEndPos, tr2.vecEndPos, ignore_monsters, ENT(pev), &tr2 );
849
850
if (tr2.flFraction != 1.0)
851
continue;
852
853
Zap( tr1.vecEndPos, tr2.vecEndPos );
854
855
break;
856
}
857
}
858
859
860
void CLightning::RandomPoint( Vector &vecSrc )
861
{
862
int iLoops = 0;
863
864
for (iLoops = 0; iLoops < 10; iLoops++)
865
{
866
Vector vecDir1 = Vector( RANDOM_FLOAT( -1.0, 1.0 ), RANDOM_FLOAT( -1.0, 1.0 ),RANDOM_FLOAT( -1.0, 1.0 ) );
867
vecDir1 = vecDir1.Normalize();
868
TraceResult tr1;
869
UTIL_TraceLine( vecSrc, vecSrc + vecDir1 * m_radius, ignore_monsters, ENT(pev), &tr1 );
870
871
if ((tr1.vecEndPos - vecSrc).Length() < m_radius * 0.1)
872
continue;
873
874
if (tr1.flFraction == 1.0)
875
continue;
876
877
Zap( vecSrc, tr1.vecEndPos );
878
break;
879
}
880
}
881
882
883
884
void CLightning::BeamUpdateVars( void )
885
{
886
int beamType;
887
int pointStart, pointEnd;
888
889
edict_t *pStart = FIND_ENTITY_BY_TARGETNAME ( NULL, STRING(m_iszStartEntity) );
890
edict_t *pEnd = FIND_ENTITY_BY_TARGETNAME ( NULL, STRING(m_iszEndEntity) );
891
pointStart = IsPointEntity( CBaseEntity::Instance(pStart) );
892
pointEnd = IsPointEntity( CBaseEntity::Instance(pEnd) );
893
894
pev->skin = 0;
895
pev->sequence = 0;
896
pev->rendermode = 0;
897
pev->flags |= FL_CUSTOMENTITY;
898
pev->model = m_iszSpriteName;
899
SetTexture( m_spriteTexture );
900
901
beamType = BEAM_ENTS;
902
if ( pointStart || pointEnd )
903
{
904
if ( !pointStart ) // One point entity must be in pStart
905
{
906
edict_t *pTemp;
907
// Swap start & end
908
pTemp = pStart;
909
pStart = pEnd;
910
pEnd = pTemp;
911
int swap = pointStart;
912
pointStart = pointEnd;
913
pointEnd = swap;
914
}
915
if ( !pointEnd )
916
beamType = BEAM_ENTPOINT;
917
else
918
beamType = BEAM_POINTS;
919
}
920
921
SetType( beamType );
922
if ( beamType == BEAM_POINTS || beamType == BEAM_ENTPOINT || beamType == BEAM_HOSE )
923
{
924
SetStartPos( pStart->v.origin );
925
if ( beamType == BEAM_POINTS || beamType == BEAM_HOSE )
926
SetEndPos( pEnd->v.origin );
927
else
928
SetEndEntity( ENTINDEX(pEnd) );
929
}
930
else
931
{
932
SetStartEntity( ENTINDEX(pStart) );
933
SetEndEntity( ENTINDEX(pEnd) );
934
}
935
936
RelinkBeam();
937
938
SetWidth( m_boltWidth );
939
SetNoise( m_noiseAmplitude );
940
SetFrame( m_frameStart );
941
SetScrollRate( m_speed );
942
if ( pev->spawnflags & SF_BEAM_SHADEIN )
943
SetFlags( BEAM_FSHADEIN );
944
else if ( pev->spawnflags & SF_BEAM_SHADEOUT )
945
SetFlags( BEAM_FSHADEOUT );
946
}
947
948
949
LINK_ENTITY_TO_CLASS( env_laser, CLaser );
950
951
TYPEDESCRIPTION CLaser::m_SaveData[] =
952
{
953
DEFINE_FIELD( CLaser, m_pSprite, FIELD_CLASSPTR ),
954
DEFINE_FIELD( CLaser, m_iszSpriteName, FIELD_STRING ),
955
DEFINE_FIELD( CLaser, m_firePosition, FIELD_POSITION_VECTOR ),
956
};
957
958
IMPLEMENT_SAVERESTORE( CLaser, CBeam );
959
960
void CLaser::Spawn( void )
961
{
962
if ( FStringNull( pev->model ) )
963
{
964
SetThink( &CLaser::SUB_Remove );
965
return;
966
}
967
pev->solid = SOLID_NOT; // Remove model & collisions
968
Precache( );
969
970
SetThink( &CLaser::StrikeThink );
971
pev->flags |= FL_CUSTOMENTITY;
972
973
PointsInit( pev->origin, pev->origin );
974
975
if ( !m_pSprite && m_iszSpriteName )
976
m_pSprite = CSprite::SpriteCreate( STRING(m_iszSpriteName), pev->origin, TRUE );
977
else
978
m_pSprite = NULL;
979
980
if ( m_pSprite )
981
m_pSprite->SetTransparency( kRenderGlow, static_cast<int>(pev->rendercolor.x), static_cast<int>(pev->rendercolor.y), static_cast<int>(pev->rendercolor.z), static_cast<int>(pev->renderamt), static_cast<int>(pev->renderfx) );
982
983
if ( pev->targetname && !(pev->spawnflags & SF_BEAM_STARTON) )
984
TurnOff();
985
else
986
TurnOn();
987
}
988
989
void CLaser::Precache( void )
990
{
991
pev->modelindex = PRECACHE_MODEL( (char *)STRING(pev->model) );
992
if ( m_iszSpriteName )
993
PRECACHE_MODEL( (char *)STRING(m_iszSpriteName) );
994
}
995
996
997
void CLaser::KeyValue( KeyValueData *pkvd )
998
{
999
if (FStrEq(pkvd->szKeyName, "LaserTarget"))
1000
{
1001
pev->message = ALLOC_STRING( pkvd->szValue );
1002
pkvd->fHandled = TRUE;
1003
}
1004
else if (FStrEq(pkvd->szKeyName, "width"))
1005
{
1006
SetWidth( (int) atof(pkvd->szValue) );
1007
pkvd->fHandled = TRUE;
1008
}
1009
else if (FStrEq(pkvd->szKeyName, "NoiseAmplitude"))
1010
{
1011
SetNoise( atoi(pkvd->szValue) );
1012
pkvd->fHandled = TRUE;
1013
}
1014
else if (FStrEq(pkvd->szKeyName, "TextureScroll"))
1015
{
1016
SetScrollRate( atoi(pkvd->szValue) );
1017
pkvd->fHandled = TRUE;
1018
}
1019
else if (FStrEq(pkvd->szKeyName, "texture"))
1020
{
1021
pev->model = ALLOC_STRING(pkvd->szValue);
1022
pkvd->fHandled = TRUE;
1023
}
1024
else if (FStrEq(pkvd->szKeyName, "EndSprite"))
1025
{
1026
m_iszSpriteName = ALLOC_STRING(pkvd->szValue);
1027
pkvd->fHandled = TRUE;
1028
}
1029
else if (FStrEq(pkvd->szKeyName, "framestart"))
1030
{
1031
pev->frame = atoi(pkvd->szValue);
1032
pkvd->fHandled = TRUE;
1033
}
1034
else if (FStrEq(pkvd->szKeyName, "damage"))
1035
{
1036
pev->dmg = atof(pkvd->szValue);
1037
pkvd->fHandled = TRUE;
1038
}
1039
else
1040
CBeam::KeyValue( pkvd );
1041
}
1042
1043
1044
int CLaser::IsOn( void )
1045
{
1046
if (pev->effects & EF_NODRAW)
1047
return 0;
1048
return 1;
1049
}
1050
1051
1052
void CLaser::TurnOff( void )
1053
{
1054
pev->effects |= EF_NODRAW;
1055
pev->nextthink = 0;
1056
if ( m_pSprite )
1057
m_pSprite->TurnOff();
1058
}
1059
1060
1061
void CLaser::TurnOn( void )
1062
{
1063
pev->effects &= ~EF_NODRAW;
1064
if ( m_pSprite )
1065
m_pSprite->TurnOn();
1066
pev->dmgtime = gpGlobals->time;
1067
pev->nextthink = gpGlobals->time;
1068
}
1069
1070
1071
void CLaser::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
1072
{
1073
int active = IsOn();
1074
1075
if ( !ShouldToggle( useType, active ) )
1076
return;
1077
if ( active )
1078
{
1079
TurnOff();
1080
}
1081
else
1082
{
1083
TurnOn();
1084
}
1085
}
1086
1087
1088
void CLaser::FireAtPoint( TraceResult &tr )
1089
{
1090
SetEndPos( tr.vecEndPos );
1091
if ( m_pSprite )
1092
UTIL_SetOrigin( m_pSprite->pev, tr.vecEndPos );
1093
1094
BeamDamage( &tr );
1095
DoSparks( GetStartPos(), tr.vecEndPos );
1096
}
1097
1098
void CLaser::StrikeThink( void )
1099
{
1100
CBaseEntity *pEnd = RandomTargetname( STRING(pev->message) );
1101
1102
if ( pEnd )
1103
m_firePosition = pEnd->pev->origin;
1104
1105
TraceResult tr;
1106
1107
UTIL_TraceLine( pev->origin, m_firePosition, dont_ignore_monsters, NULL, &tr );
1108
FireAtPoint( tr );
1109
pev->nextthink = gpGlobals->time + 0.1;
1110
}
1111
1112
1113
1114
class CGlow : public CPointEntity
1115
{
1116
public:
1117
void Spawn( void );
1118
void Think( void );
1119
void Animate( float frames );
1120
virtual int Save( CSave &save );
1121
virtual int Restore( CRestore &restore );
1122
static TYPEDESCRIPTION m_SaveData[];
1123
1124
float m_lastTime;
1125
float m_maxFrame;
1126
};
1127
1128
LINK_ENTITY_TO_CLASS( env_glow, CGlow );
1129
1130
TYPEDESCRIPTION CGlow::m_SaveData[] =
1131
{
1132
DEFINE_FIELD( CGlow, m_lastTime, FIELD_TIME ),
1133
DEFINE_FIELD( CGlow, m_maxFrame, FIELD_FLOAT ),
1134
};
1135
1136
IMPLEMENT_SAVERESTORE( CGlow, CPointEntity );
1137
1138
void CGlow::Spawn( void )
1139
{
1140
pev->solid = SOLID_NOT;
1141
pev->movetype = MOVETYPE_NONE;
1142
pev->effects = 0;
1143
pev->frame = 0;
1144
1145
PRECACHE_MODEL( (char *)STRING(pev->model) );
1146
SET_MODEL( ENT(pev), STRING(pev->model) );
1147
1148
m_maxFrame = (float) MODEL_FRAMES( pev->modelindex ) - 1;
1149
if ( m_maxFrame > 1.0 && pev->framerate != 0 )
1150
pev->nextthink = gpGlobals->time + 0.1;
1151
1152
m_lastTime = gpGlobals->time;
1153
}
1154
1155
1156
void CGlow::Think( void )
1157
{
1158
Animate( pev->framerate * (gpGlobals->time - m_lastTime) );
1159
1160
pev->nextthink = gpGlobals->time + 0.1;
1161
m_lastTime = gpGlobals->time;
1162
}
1163
1164
1165
void CGlow::Animate( float frames )
1166
{
1167
if ( m_maxFrame > 0 )
1168
pev->frame = fmod( pev->frame + frames, m_maxFrame );
1169
}
1170
1171
1172
LINK_ENTITY_TO_CLASS( env_sprite, CSprite );
1173
1174
TYPEDESCRIPTION CSprite::m_SaveData[] =
1175
{
1176
DEFINE_FIELD( CSprite, m_lastTime, FIELD_TIME ),
1177
DEFINE_FIELD( CSprite, m_maxFrame, FIELD_FLOAT ),
1178
};
1179
1180
IMPLEMENT_SAVERESTORE( CSprite, CPointEntity );
1181
1182
void CSprite::Spawn( void )
1183
{
1184
pev->solid = SOLID_NOT;
1185
pev->movetype = MOVETYPE_NONE;
1186
pev->effects = 0;
1187
pev->frame = 0;
1188
1189
Precache();
1190
SET_MODEL( ENT(pev), STRING(pev->model) );
1191
1192
m_maxFrame = (float) MODEL_FRAMES( pev->modelindex ) - 1;
1193
if ( pev->targetname && !(pev->spawnflags & SF_SPRITE_STARTON) )
1194
TurnOff();
1195
else
1196
TurnOn();
1197
1198
// Worldcraft only sets y rotation, copy to Z
1199
if ( pev->angles.y != 0 && pev->angles.z == 0 )
1200
{
1201
pev->angles.z = pev->angles.y;
1202
pev->angles.y = 0;
1203
}
1204
}
1205
1206
1207
void CSprite::Precache( void )
1208
{
1209
PRECACHE_MODEL( (char *)STRING(pev->model) );
1210
1211
// Reset attachment after save/restore
1212
if ( pev->aiment )
1213
SetAttachment( pev->aiment, pev->body );
1214
else
1215
{
1216
// Clear attachment
1217
pev->skin = 0;
1218
pev->body = 0;
1219
}
1220
}
1221
1222
1223
void CSprite::SpriteInit( const char *pSpriteName, const Vector &origin )
1224
{
1225
pev->model = MAKE_STRING(pSpriteName);
1226
pev->origin = origin;
1227
Spawn();
1228
}
1229
1230
CSprite *CSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate )
1231
{
1232
CSprite *pSprite = GetClassPtr( (CSprite *)NULL );
1233
pSprite->SpriteInit( pSpriteName, origin );
1234
pSprite->pev->classname = MAKE_STRING("env_sprite");
1235
pSprite->pev->solid = SOLID_NOT;
1236
pSprite->pev->movetype = MOVETYPE_NOCLIP;
1237
if ( animate )
1238
pSprite->TurnOn();
1239
1240
return pSprite;
1241
}
1242
1243
1244
void CSprite::AnimateThink( void )
1245
{
1246
Animate( pev->framerate * (gpGlobals->time - m_lastTime) );
1247
1248
pev->nextthink = gpGlobals->time + 0.1;
1249
m_lastTime = gpGlobals->time;
1250
}
1251
1252
void CSprite::AnimateUntilDead( void )
1253
{
1254
if ( gpGlobals->time > pev->dmgtime )
1255
UTIL_Remove(this);
1256
else
1257
{
1258
AnimateThink();
1259
pev->nextthink = gpGlobals->time;
1260
}
1261
}
1262
1263
void CSprite::Expand( float scaleSpeed, float fadeSpeed )
1264
{
1265
pev->speed = scaleSpeed;
1266
pev->health = fadeSpeed;
1267
SetThink( &CSprite::ExpandThink );
1268
1269
pev->nextthink = gpGlobals->time;
1270
m_lastTime = gpGlobals->time;
1271
}
1272
1273
1274
void CSprite::ExpandThink( void )
1275
{
1276
float frametime = gpGlobals->time - m_lastTime;
1277
pev->scale += pev->speed * frametime;
1278
pev->renderamt -= pev->health * frametime;
1279
if ( pev->renderamt <= 0 )
1280
{
1281
pev->renderamt = 0;
1282
UTIL_Remove( this );
1283
}
1284
else
1285
{
1286
pev->nextthink = gpGlobals->time + 0.1;
1287
m_lastTime = gpGlobals->time;
1288
}
1289
}
1290
1291
1292
void CSprite::Animate( float frames )
1293
{
1294
pev->frame += frames;
1295
if ( pev->frame > m_maxFrame )
1296
{
1297
if ( pev->spawnflags & SF_SPRITE_ONCE )
1298
{
1299
TurnOff();
1300
}
1301
else
1302
{
1303
if ( m_maxFrame > 0 )
1304
pev->frame = fmod( pev->frame, m_maxFrame );
1305
}
1306
}
1307
}
1308
1309
1310
void CSprite::TurnOff( void )
1311
{
1312
pev->effects = EF_NODRAW;
1313
pev->nextthink = 0;
1314
}
1315
1316
1317
void CSprite::TurnOn( void )
1318
{
1319
pev->effects = 0;
1320
if ( (pev->framerate && m_maxFrame > 1.0) || (pev->spawnflags & SF_SPRITE_ONCE) )
1321
{
1322
SetThink( &CSprite::AnimateThink );
1323
pev->nextthink = gpGlobals->time;
1324
m_lastTime = gpGlobals->time;
1325
}
1326
pev->frame = 0;
1327
}
1328
1329
1330
void CSprite::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
1331
{
1332
int on = pev->effects != EF_NODRAW;
1333
if ( ShouldToggle( useType, on ) )
1334
{
1335
if ( on )
1336
{
1337
TurnOff();
1338
}
1339
else
1340
{
1341
TurnOn();
1342
}
1343
}
1344
}
1345
1346
1347
class CGibShooter : public CBaseDelay
1348
{
1349
public:
1350
void Spawn( void );
1351
void Precache( void );
1352
void KeyValue( KeyValueData *pkvd );
1353
void EXPORT ShootThink( void );
1354
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
1355
1356
virtual CGib *CreateGib( void );
1357
1358
virtual int Save( CSave &save );
1359
virtual int Restore( CRestore &restore );
1360
static TYPEDESCRIPTION m_SaveData[];
1361
1362
int m_iGibs;
1363
int m_iGibCapacity;
1364
int m_iGibMaterial;
1365
int m_iGibModelIndex;
1366
float m_flGibVelocity;
1367
float m_flVariance;
1368
float m_flGibLife;
1369
};
1370
1371
TYPEDESCRIPTION CGibShooter::m_SaveData[] =
1372
{
1373
DEFINE_FIELD( CGibShooter, m_iGibs, FIELD_INTEGER ),
1374
DEFINE_FIELD( CGibShooter, m_iGibCapacity, FIELD_INTEGER ),
1375
DEFINE_FIELD( CGibShooter, m_iGibMaterial, FIELD_INTEGER ),
1376
DEFINE_FIELD( CGibShooter, m_iGibModelIndex, FIELD_INTEGER ),
1377
DEFINE_FIELD( CGibShooter, m_flGibVelocity, FIELD_FLOAT ),
1378
DEFINE_FIELD( CGibShooter, m_flVariance, FIELD_FLOAT ),
1379
DEFINE_FIELD( CGibShooter, m_flGibLife, FIELD_FLOAT ),
1380
};
1381
1382
IMPLEMENT_SAVERESTORE( CGibShooter, CBaseDelay );
1383
LINK_ENTITY_TO_CLASS( gibshooter, CGibShooter );
1384
1385
1386
void CGibShooter :: Precache ( void )
1387
{
1388
if ( g_Language == LANGUAGE_GERMAN )
1389
{
1390
m_iGibModelIndex = PRECACHE_MODEL ("models/germanygibs.mdl");
1391
}
1392
else
1393
{
1394
m_iGibModelIndex = PRECACHE_MODEL ("models/hgibs.mdl");
1395
}
1396
}
1397
1398
1399
void CGibShooter::KeyValue( KeyValueData *pkvd )
1400
{
1401
if (FStrEq(pkvd->szKeyName, "m_iGibs"))
1402
{
1403
m_iGibs = m_iGibCapacity = atoi(pkvd->szValue);
1404
pkvd->fHandled = TRUE;
1405
}
1406
else if (FStrEq(pkvd->szKeyName, "m_flVelocity"))
1407
{
1408
m_flGibVelocity = atof(pkvd->szValue);
1409
pkvd->fHandled = TRUE;
1410
}
1411
else if (FStrEq(pkvd->szKeyName, "m_flVariance"))
1412
{
1413
m_flVariance = atof(pkvd->szValue);
1414
pkvd->fHandled = TRUE;
1415
}
1416
else if (FStrEq(pkvd->szKeyName, "m_flGibLife"))
1417
{
1418
m_flGibLife = atof(pkvd->szValue);
1419
pkvd->fHandled = TRUE;
1420
}
1421
else
1422
{
1423
CBaseDelay::KeyValue( pkvd );
1424
}
1425
}
1426
1427
void CGibShooter::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
1428
{
1429
SetThink( &CGibShooter::ShootThink );
1430
pev->nextthink = gpGlobals->time;
1431
}
1432
1433
void CGibShooter::Spawn( void )
1434
{
1435
Precache();
1436
1437
pev->solid = SOLID_NOT;
1438
pev->effects = EF_NODRAW;
1439
1440
if ( m_flDelay == 0 )
1441
{
1442
m_flDelay = 0.1;
1443
}
1444
1445
if ( m_flGibLife == 0 )
1446
{
1447
m_flGibLife = 25;
1448
}
1449
1450
SetMovedir ( pev );
1451
pev->body = MODEL_FRAMES( m_iGibModelIndex );
1452
}
1453
1454
1455
CGib *CGibShooter :: CreateGib ( void )
1456
{
1457
if ( CVAR_GET_FLOAT("violence_hgibs") == 0 )
1458
return NULL;
1459
1460
CGib *pGib = GetClassPtr( (CGib *)NULL );
1461
pGib->Spawn( "models/hgibs.mdl" );
1462
pGib->m_bloodColor = BLOOD_COLOR_RED;
1463
1464
if ( pev->body <= 1 )
1465
{
1466
ALERT ( at_aiconsole, "GibShooter Body is <= 1!\n" );
1467
}
1468
1469
pGib->pev->body = RANDOM_LONG ( 1, pev->body - 1 );// avoid throwing random amounts of the 0th gib. (skull).
1470
1471
return pGib;
1472
}
1473
1474
1475
void CGibShooter :: ShootThink ( void )
1476
{
1477
pev->nextthink = gpGlobals->time + m_flDelay;
1478
1479
Vector vecShootDir;
1480
1481
vecShootDir = pev->movedir;
1482
1483
vecShootDir = vecShootDir + gpGlobals->v_right * RANDOM_FLOAT( -1, 1) * m_flVariance;;
1484
vecShootDir = vecShootDir + gpGlobals->v_forward * RANDOM_FLOAT( -1, 1) * m_flVariance;;
1485
vecShootDir = vecShootDir + gpGlobals->v_up * RANDOM_FLOAT( -1, 1) * m_flVariance;;
1486
1487
vecShootDir = vecShootDir.Normalize();
1488
CGib *pGib = CreateGib();
1489
1490
if ( pGib )
1491
{
1492
pGib->pev->origin = pev->origin;
1493
pGib->pev->velocity = vecShootDir * m_flGibVelocity;
1494
1495
pGib->pev->avelocity.x = RANDOM_FLOAT ( 100, 200 );
1496
pGib->pev->avelocity.y = RANDOM_FLOAT ( 100, 300 );
1497
1498
float thinkTime = pGib->pev->nextthink - gpGlobals->time;
1499
1500
pGib->m_lifeTime = (m_flGibLife * RANDOM_FLOAT( 0.95, 1.05 )); // +/- 5%
1501
if ( pGib->m_lifeTime < thinkTime )
1502
{
1503
pGib->pev->nextthink = gpGlobals->time + pGib->m_lifeTime;
1504
pGib->m_lifeTime = 0;
1505
}
1506
1507
}
1508
1509
if ( --m_iGibs <= 0 )
1510
{
1511
if ( pev->spawnflags & SF_GIBSHOOTER_REPEATABLE )
1512
{
1513
m_iGibs = m_iGibCapacity;
1514
SetThink ( NULL );
1515
pev->nextthink = gpGlobals->time;
1516
}
1517
else
1518
{
1519
SetThink ( &CGibShooter::SUB_Remove );
1520
pev->nextthink = gpGlobals->time;
1521
}
1522
}
1523
}
1524
1525
1526
class CEnvShooter : public CGibShooter
1527
{
1528
void Precache( void );
1529
void KeyValue( KeyValueData *pkvd );
1530
1531
CGib *CreateGib( void );
1532
};
1533
1534
LINK_ENTITY_TO_CLASS( env_shooter, CEnvShooter );
1535
1536
void CEnvShooter :: KeyValue( KeyValueData *pkvd )
1537
{
1538
if (FStrEq(pkvd->szKeyName, "shootmodel"))
1539
{
1540
pev->model = ALLOC_STRING(pkvd->szValue);
1541
pkvd->fHandled = TRUE;
1542
}
1543
else if (FStrEq(pkvd->szKeyName, "shootsounds"))
1544
{
1545
int iNoise = atoi(pkvd->szValue);
1546
pkvd->fHandled = TRUE;
1547
switch( iNoise )
1548
{
1549
case 0:
1550
m_iGibMaterial = matGlass;
1551
break;
1552
case 1:
1553
m_iGibMaterial = matWood;
1554
break;
1555
case 2:
1556
m_iGibMaterial = matMetal;
1557
break;
1558
case 3:
1559
m_iGibMaterial = matFlesh;
1560
break;
1561
case 4:
1562
m_iGibMaterial = matRocks;
1563
break;
1564
1565
default:
1566
case -1:
1567
m_iGibMaterial = matNone;
1568
break;
1569
}
1570
}
1571
else
1572
{
1573
CGibShooter::KeyValue( pkvd );
1574
}
1575
}
1576
1577
1578
void CEnvShooter :: Precache ( void )
1579
{
1580
m_iGibModelIndex = PRECACHE_MODEL( (char *)STRING(pev->model) );
1581
CBreakable::MaterialSoundPrecache( (Materials)m_iGibMaterial );
1582
}
1583
1584
1585
CGib *CEnvShooter :: CreateGib ( void )
1586
{
1587
CGib *pGib = GetClassPtr( (CGib *)NULL );
1588
1589
pGib->Spawn( STRING(pev->model) );
1590
1591
int bodyPart = 0;
1592
1593
if ( pev->body > 1 )
1594
bodyPart = RANDOM_LONG( 0, pev->body-1 );
1595
1596
pGib->pev->body = bodyPart;
1597
pGib->m_bloodColor = DONT_BLEED;
1598
pGib->m_material = m_iGibMaterial;
1599
1600
pGib->pev->rendermode = pev->rendermode;
1601
pGib->pev->renderamt = pev->renderamt;
1602
pGib->pev->rendercolor = pev->rendercolor;
1603
pGib->pev->renderfx = pev->renderfx;
1604
pGib->pev->scale = pev->scale;
1605
pGib->pev->skin = pev->skin;
1606
1607
return pGib;
1608
}
1609
1610
1611
1612
1613
class CTestEffect : public CBaseDelay
1614
{
1615
public:
1616
void Spawn( void );
1617
void Precache( void );
1618
// void KeyValue( KeyValueData *pkvd );
1619
void EXPORT TestThink( void );
1620
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
1621
1622
int m_iLoop;
1623
int m_iBeam;
1624
CBeam *m_pBeam[24];
1625
float m_flBeamTime[24];
1626
float m_flStartTime;
1627
};
1628
1629
1630
LINK_ENTITY_TO_CLASS( test_effect, CTestEffect );
1631
1632
void CTestEffect::Spawn( void )
1633
{
1634
Precache( );
1635
}
1636
1637
void CTestEffect::Precache( void )
1638
{
1639
PRECACHE_MODEL( "sprites/lgtning.spr" );
1640
}
1641
1642
void CTestEffect::TestThink( void )
1643
{
1644
int i;
1645
float t = (gpGlobals->time - m_flStartTime);
1646
1647
if (m_iBeam < 24)
1648
{
1649
CBeam *pbeam = CBeam::BeamCreate( "sprites/lgtning.spr", 100 );
1650
1651
TraceResult tr;
1652
1653
Vector vecSrc = pev->origin;
1654
Vector vecDir = Vector( RANDOM_FLOAT( -1.0, 1.0 ), RANDOM_FLOAT( -1.0, 1.0 ),RANDOM_FLOAT( -1.0, 1.0 ) );
1655
vecDir = vecDir.Normalize();
1656
UTIL_TraceLine( vecSrc, vecSrc + vecDir * 128, ignore_monsters, ENT(pev), &tr);
1657
1658
pbeam->PointsInit( vecSrc, tr.vecEndPos );
1659
// pbeam->SetColor( 80, 100, 255 );
1660
pbeam->SetColor( 255, 180, 100 );
1661
pbeam->SetWidth( 100 );
1662
pbeam->SetScrollRate( 12 );
1663
1664
m_flBeamTime[m_iBeam] = gpGlobals->time;
1665
m_pBeam[m_iBeam] = pbeam;
1666
m_iBeam++;
1667
1668
#if 0
1669
Vector vecMid = (vecSrc + tr.vecEndPos) * 0.5;
1670
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
1671
WRITE_BYTE(TE_DLIGHT);
1672
WRITE_COORD(vecMid.x); // X
1673
WRITE_COORD(vecMid.y); // Y
1674
WRITE_COORD(vecMid.z); // Z
1675
WRITE_BYTE( 20 ); // radius * 0.1
1676
WRITE_BYTE( 255 ); // r
1677
WRITE_BYTE( 180 ); // g
1678
WRITE_BYTE( 100 ); // b
1679
WRITE_BYTE( 20 ); // time * 10
1680
WRITE_BYTE( 0 ); // decay * 0.1
1681
MESSAGE_END( );
1682
#endif
1683
}
1684
1685
if (t < 3.0)
1686
{
1687
for (i = 0; i < m_iBeam; i++)
1688
{
1689
t = (gpGlobals->time - m_flBeamTime[i]) / ( 3 + m_flStartTime - m_flBeamTime[i]);
1690
m_pBeam[i]->SetBrightness( static_cast<int>(255 * t) );
1691
// m_pBeam[i]->SetScrollRate( 20 * t );
1692
}
1693
pev->nextthink = gpGlobals->time + 0.1;
1694
}
1695
else
1696
{
1697
for (i = 0; i < m_iBeam; i++)
1698
{
1699
UTIL_Remove( m_pBeam[i] );
1700
}
1701
m_flStartTime = gpGlobals->time;
1702
m_iBeam = 0;
1703
// pev->nextthink = gpGlobals->time;
1704
SetThink( NULL );
1705
}
1706
}
1707
1708
1709
void CTestEffect::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
1710
{
1711
SetThink( &CTestEffect::TestThink );
1712
pev->nextthink = gpGlobals->time + 0.1;
1713
m_flStartTime = gpGlobals->time;
1714
}
1715
1716
1717
1718
// Blood effects
1719
class CBlood : public CPointEntity
1720
{
1721
public:
1722
void Spawn( void );
1723
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
1724
void KeyValue( KeyValueData *pkvd );
1725
1726
inline int Color( void ) { return pev->impulse; }
1727
inline float BloodAmount( void ) { return pev->dmg; }
1728
1729
inline void SetColor( int color ) { pev->impulse = color; }
1730
inline void SetBloodAmount( float amount ) { pev->dmg = amount; }
1731
1732
Vector Direction( void );
1733
Vector BloodPosition( CBaseEntity *pActivator );
1734
1735
private:
1736
};
1737
1738
LINK_ENTITY_TO_CLASS( env_blood, CBlood );
1739
1740
1741
1742
#define SF_BLOOD_RANDOM 0x0001
1743
#define SF_BLOOD_STREAM 0x0002
1744
#define SF_BLOOD_PLAYER 0x0004
1745
#define SF_BLOOD_DECAL 0x0008
1746
1747
void CBlood::Spawn( void )
1748
{
1749
pev->solid = SOLID_NOT;
1750
pev->movetype = MOVETYPE_NONE;
1751
pev->effects = 0;
1752
pev->frame = 0;
1753
SetMovedir( pev );
1754
}
1755
1756
1757
void CBlood::KeyValue( KeyValueData *pkvd )
1758
{
1759
if (FStrEq(pkvd->szKeyName, "color"))
1760
{
1761
int color = atoi(pkvd->szValue);
1762
switch( color )
1763
{
1764
case 1:
1765
SetColor( BLOOD_COLOR_YELLOW );
1766
break;
1767
default:
1768
SetColor( BLOOD_COLOR_RED );
1769
break;
1770
}
1771
1772
pkvd->fHandled = TRUE;
1773
}
1774
else if (FStrEq(pkvd->szKeyName, "amount"))
1775
{
1776
SetBloodAmount( atof(pkvd->szValue) );
1777
pkvd->fHandled = TRUE;
1778
}
1779
else
1780
CPointEntity::KeyValue( pkvd );
1781
}
1782
1783
1784
Vector CBlood::Direction( void )
1785
{
1786
if ( pev->spawnflags & SF_BLOOD_RANDOM )
1787
return UTIL_RandomBloodVector();
1788
1789
return pev->movedir;
1790
}
1791
1792
1793
Vector CBlood::BloodPosition( CBaseEntity *pActivator )
1794
{
1795
if ( pev->spawnflags & SF_BLOOD_PLAYER )
1796
{
1797
edict_t *pPlayer;
1798
1799
if ( pActivator && pActivator->IsPlayer() )
1800
{
1801
pPlayer = pActivator->edict();
1802
}
1803
else
1804
pPlayer = g_engfuncs.pfnPEntityOfEntIndex( 1 );
1805
if ( pPlayer )
1806
return (pPlayer->v.origin + pPlayer->v.view_ofs) + Vector( RANDOM_FLOAT(-10,10), RANDOM_FLOAT(-10,10), RANDOM_FLOAT(-10,10) );
1807
}
1808
1809
return pev->origin;
1810
}
1811
1812
1813
void CBlood::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
1814
{
1815
if ( pev->spawnflags & SF_BLOOD_STREAM )
1816
UTIL_BloodStream( BloodPosition(pActivator), Direction(), (Color() == BLOOD_COLOR_RED) ? 70 : Color(), static_cast<int>(BloodAmount()) );
1817
else
1818
UTIL_BloodDrips( BloodPosition(pActivator), Direction(), Color(), static_cast<int>(BloodAmount()) );
1819
1820
if ( pev->spawnflags & SF_BLOOD_DECAL )
1821
{
1822
Vector forward = Direction();
1823
Vector start = BloodPosition( pActivator );
1824
TraceResult tr;
1825
1826
UTIL_TraceLine( start, start + forward * BloodAmount() * 2, ignore_monsters, NULL, &tr );
1827
if ( tr.flFraction != 1.0 )
1828
UTIL_BloodDecalTrace( &tr, Color() );
1829
}
1830
}
1831
1832
1833
1834
// Screen shake
1835
class CShake : public CPointEntity
1836
{
1837
public:
1838
void Spawn( void );
1839
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
1840
void KeyValue( KeyValueData *pkvd );
1841
1842
inline float Amplitude( void ) { return pev->scale; }
1843
inline float Frequency( void ) { return pev->dmg_save; }
1844
inline float Duration( void ) { return pev->dmg_take; }
1845
inline float Radius( void ) { return pev->dmg; }
1846
1847
inline void SetAmplitude( float amplitude ) { pev->scale = amplitude; }
1848
inline void SetFrequency( float frequency ) { pev->dmg_save = frequency; }
1849
inline void SetDuration( float duration ) { pev->dmg_take = duration; }
1850
inline void SetRadius( float radius ) { pev->dmg = radius; }
1851
private:
1852
};
1853
1854
LINK_ENTITY_TO_CLASS( env_shake, CShake );
1855
1856
// pev->scale is amplitude
1857
// pev->dmg_save is frequency
1858
// pev->dmg_take is duration
1859
// pev->dmg is radius
1860
// radius of 0 means all players
1861
// NOTE: UTIL_ScreenShake() will only shake players who are on the ground
1862
1863
#define SF_SHAKE_EVERYONE 0x0001 // Don't check radius
1864
// UNDONE: These don't work yet
1865
#define SF_SHAKE_DISRUPT 0x0002 // Disrupt controls
1866
#define SF_SHAKE_INAIR 0x0004 // Shake players in air
1867
1868
void CShake::Spawn( void )
1869
{
1870
pev->solid = SOLID_NOT;
1871
pev->movetype = MOVETYPE_NONE;
1872
pev->effects = 0;
1873
pev->frame = 0;
1874
1875
if ( pev->spawnflags & SF_SHAKE_EVERYONE )
1876
pev->dmg = 0;
1877
}
1878
1879
1880
void CShake::KeyValue( KeyValueData *pkvd )
1881
{
1882
if (FStrEq(pkvd->szKeyName, "amplitude"))
1883
{
1884
SetAmplitude( atof(pkvd->szValue) );
1885
pkvd->fHandled = TRUE;
1886
}
1887
else if (FStrEq(pkvd->szKeyName, "frequency"))
1888
{
1889
SetFrequency( atof(pkvd->szValue) );
1890
pkvd->fHandled = TRUE;
1891
}
1892
else if (FStrEq(pkvd->szKeyName, "duration"))
1893
{
1894
SetDuration( atof(pkvd->szValue) );
1895
pkvd->fHandled = TRUE;
1896
}
1897
else if (FStrEq(pkvd->szKeyName, "radius"))
1898
{
1899
SetRadius( atof(pkvd->szValue) );
1900
pkvd->fHandled = TRUE;
1901
}
1902
else
1903
CPointEntity::KeyValue( pkvd );
1904
}
1905
1906
1907
void CShake::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
1908
{
1909
UTIL_ScreenShake( pev->origin, Amplitude(), Frequency(), Duration(), Radius() );
1910
}
1911
1912
1913
class CFade : public CPointEntity
1914
{
1915
public:
1916
void Spawn( void );
1917
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
1918
void KeyValue( KeyValueData *pkvd );
1919
1920
inline float Duration( void ) { return pev->dmg_take; }
1921
inline float HoldTime( void ) { return pev->dmg_save; }
1922
1923
inline void SetDuration( float duration ) { pev->dmg_take = duration; }
1924
inline void SetHoldTime( float hold ) { pev->dmg_save = hold; }
1925
private:
1926
};
1927
1928
LINK_ENTITY_TO_CLASS( env_fade, CFade );
1929
1930
// pev->dmg_take is duration
1931
// pev->dmg_save is hold duration
1932
#define SF_FADE_IN 0x0001 // Fade in, not out
1933
#define SF_FADE_MODULATE 0x0002 // Modulate, don't blend
1934
#define SF_FADE_ONLYONE 0x0004
1935
1936
void CFade::Spawn( void )
1937
{
1938
pev->solid = SOLID_NOT;
1939
pev->movetype = MOVETYPE_NONE;
1940
pev->effects = 0;
1941
pev->frame = 0;
1942
}
1943
1944
1945
void CFade::KeyValue( KeyValueData *pkvd )
1946
{
1947
if (FStrEq(pkvd->szKeyName, "duration"))
1948
{
1949
SetDuration( atof(pkvd->szValue) );
1950
pkvd->fHandled = TRUE;
1951
}
1952
else if (FStrEq(pkvd->szKeyName, "holdtime"))
1953
{
1954
SetHoldTime( atof(pkvd->szValue) );
1955
pkvd->fHandled = TRUE;
1956
}
1957
else
1958
CPointEntity::KeyValue( pkvd );
1959
}
1960
1961
1962
void CFade::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
1963
{
1964
int fadeFlags = 0;
1965
1966
if ( !(pev->spawnflags & SF_FADE_IN) )
1967
fadeFlags |= FFADE_OUT;
1968
1969
if ( pev->spawnflags & SF_FADE_MODULATE )
1970
fadeFlags |= FFADE_MODULATE;
1971
1972
if ( pev->spawnflags & SF_FADE_ONLYONE )
1973
{
1974
if ( pActivator->IsNetClient() )
1975
{
1976
UTIL_ScreenFade( pActivator, pev->rendercolor, Duration(), HoldTime(), static_cast<int>(pev->renderamt), fadeFlags );
1977
}
1978
}
1979
else
1980
{
1981
UTIL_ScreenFadeAll( pev->rendercolor, Duration(), HoldTime(), static_cast<int>(pev->renderamt), fadeFlags );
1982
}
1983
SUB_UseTargets( this, USE_TOGGLE, 0 );
1984
}
1985
1986
1987
class CMessage : public CPointEntity
1988
{
1989
public:
1990
void Spawn( void );
1991
void Precache( void );
1992
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
1993
void KeyValue( KeyValueData *pkvd );
1994
private:
1995
};
1996
1997
LINK_ENTITY_TO_CLASS( env_message, CMessage );
1998
1999
2000
void CMessage::Spawn( void )
2001
{
2002
Precache();
2003
2004
pev->solid = SOLID_NOT;
2005
pev->movetype = MOVETYPE_NONE;
2006
2007
switch( pev->impulse )
2008
{
2009
case 1: // Medium radius
2010
pev->speed = ATTN_STATIC;
2011
break;
2012
2013
case 2: // Large radius
2014
pev->speed = ATTN_NORM;
2015
break;
2016
2017
case 3: //EVERYWHERE
2018
pev->speed = ATTN_NONE;
2019
break;
2020
2021
default:
2022
case 0: // Small radius
2023
pev->speed = ATTN_IDLE;
2024
break;
2025
}
2026
pev->impulse = 0;
2027
2028
// No volume, use normal
2029
if ( pev->scale <= 0 )
2030
pev->scale = 1.0;
2031
}
2032
2033
2034
void CMessage::Precache( void )
2035
{
2036
if ( pev->noise )
2037
PRECACHE_SOUND( (char *)STRING(pev->noise) );
2038
}
2039
2040
void CMessage::KeyValue( KeyValueData *pkvd )
2041
{
2042
if (FStrEq(pkvd->szKeyName, "messagesound"))
2043
{
2044
pev->noise = ALLOC_STRING(pkvd->szValue);
2045
pkvd->fHandled = TRUE;
2046
}
2047
else if (FStrEq(pkvd->szKeyName, "messagevolume"))
2048
{
2049
pev->scale = atof(pkvd->szValue) * 0.1;
2050
pkvd->fHandled = TRUE;
2051
}
2052
else if (FStrEq(pkvd->szKeyName, "messageattenuation"))
2053
{
2054
pev->impulse = atoi(pkvd->szValue);
2055
pkvd->fHandled = TRUE;
2056
}
2057
else
2058
CPointEntity::KeyValue( pkvd );
2059
}
2060
2061
2062
void CMessage::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
2063
{
2064
CBaseEntity *pPlayer = NULL;
2065
2066
if ( pev->spawnflags & SF_MESSAGE_ALL )
2067
UTIL_ShowMessageAll( STRING(pev->message) );
2068
else
2069
{
2070
if ( pActivator && pActivator->IsPlayer() )
2071
pPlayer = pActivator;
2072
else
2073
{
2074
pPlayer = CBaseEntity::Instance( g_engfuncs.pfnPEntityOfEntIndex( 1 ) );
2075
}
2076
if ( pPlayer )
2077
UTIL_ShowMessage( STRING(pev->message), pPlayer );
2078
}
2079
if ( pev->noise )
2080
{
2081
EMIT_SOUND( edict(), CHAN_BODY, STRING(pev->noise), pev->scale, pev->speed );
2082
}
2083
if ( pev->spawnflags & SF_MESSAGE_ONCE )
2084
UTIL_Remove( this );
2085
2086
SUB_UseTargets( this, USE_TOGGLE, 0 );
2087
}
2088
2089
2090
2091
//=========================================================
2092
// FunnelEffect
2093
//=========================================================
2094
class CEnvFunnel : public CBaseDelay
2095
{
2096
public:
2097
void Spawn( void );
2098
void Precache( void );
2099
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
2100
2101
int m_iSprite; // Don't save, precache
2102
};
2103
2104
void CEnvFunnel :: Precache ( void )
2105
{
2106
m_iSprite = PRECACHE_MODEL ( "sprites/flare6.spr" );
2107
}
2108
2109
LINK_ENTITY_TO_CLASS( env_funnel, CEnvFunnel );
2110
2111
void CEnvFunnel::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
2112
{
2113
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
2114
WRITE_BYTE( TE_LARGEFUNNEL );
2115
WRITE_COORD( pev->origin.x );
2116
WRITE_COORD( pev->origin.y );
2117
WRITE_COORD( pev->origin.z );
2118
WRITE_SHORT( m_iSprite );
2119
2120
if ( pev->spawnflags & SF_FUNNEL_REVERSE )// funnel flows in reverse?
2121
{
2122
WRITE_SHORT( 1 );
2123
}
2124
else
2125
{
2126
WRITE_SHORT( 0 );
2127
}
2128
2129
2130
MESSAGE_END();
2131
2132
SetThink( &CEnvFunnel::SUB_Remove );
2133
pev->nextthink = gpGlobals->time;
2134
}
2135
2136
void CEnvFunnel::Spawn( void )
2137
{
2138
Precache();
2139
pev->solid = SOLID_NOT;
2140
pev->effects = EF_NODRAW;
2141
}
2142
2143
//=========================================================
2144
// Beverage Dispenser
2145
// overloaded pev->frags, is now a flag for whether or not a can is stuck in the dispenser.
2146
// overloaded pev->health, is now how many cans remain in the machine.
2147
//=========================================================
2148
class CEnvBeverage : public CBaseDelay
2149
{
2150
public:
2151
void Spawn( void );
2152
void Precache( void );
2153
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
2154
};
2155
2156
void CEnvBeverage :: Precache ( void )
2157
{
2158
PRECACHE_MODEL( "models/can.mdl" );
2159
PRECACHE_SOUND( "weapons/g_bounce3.wav" );
2160
}
2161
2162
LINK_ENTITY_TO_CLASS( env_beverage, CEnvBeverage );
2163
2164
void CEnvBeverage::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
2165
{
2166
if ( pev->frags != 0 || pev->health <= 0 )
2167
{
2168
// no more cans while one is waiting in the dispenser, or if I'm out of cans.
2169
return;
2170
}
2171
2172
CBaseEntity *pCan = CBaseEntity::Create( "item_sodacan", pev->origin, pev->angles, edict() );
2173
2174
if ( pev->skin == 6 )
2175
{
2176
// random
2177
pCan->pev->skin = RANDOM_LONG( 0, 5 );
2178
}
2179
else
2180
{
2181
pCan->pev->skin = pev->skin;
2182
}
2183
2184
pev->frags = 1;
2185
pev->health--;
2186
2187
//SetThink (SUB_Remove);
2188
//pev->nextthink = gpGlobals->time;
2189
}
2190
2191
void CEnvBeverage::Spawn( void )
2192
{
2193
Precache();
2194
pev->solid = SOLID_NOT;
2195
pev->effects = EF_NODRAW;
2196
pev->frags = 0;
2197
2198
if ( pev->health == 0 )
2199
{
2200
pev->health = 10;
2201
}
2202
}
2203
2204
//=========================================================
2205
// Soda can
2206
//=========================================================
2207
class CItemSoda : public CBaseEntity
2208
{
2209
public:
2210
void Spawn( void );
2211
void Precache( void );
2212
void EXPORT CanThink ( void );
2213
void EXPORT CanTouch ( CBaseEntity *pOther );
2214
};
2215
2216
void CItemSoda :: Precache ( void )
2217
{
2218
}
2219
2220
LINK_ENTITY_TO_CLASS( item_sodacan, CItemSoda );
2221
2222
void CItemSoda::Spawn( void )
2223
{
2224
Precache();
2225
pev->solid = SOLID_NOT;
2226
pev->movetype = MOVETYPE_TOSS;
2227
2228
SET_MODEL ( ENT(pev), "models/can.mdl" );
2229
UTIL_SetSize ( pev, Vector ( 0, 0, 0 ), Vector ( 0, 0, 0 ) );
2230
2231
SetThink (&CItemSoda::CanThink);
2232
pev->nextthink = gpGlobals->time + 0.5;
2233
}
2234
2235
void CItemSoda::CanThink ( void )
2236
{
2237
EMIT_SOUND (ENT(pev), CHAN_WEAPON, "weapons/g_bounce3.wav", 1, ATTN_NORM );
2238
2239
pev->solid = SOLID_TRIGGER;
2240
UTIL_SetSize ( pev, Vector ( -8, -8, 0 ), Vector ( 8, 8, 8 ) );
2241
SetThink ( NULL );
2242
SetTouch ( &CItemSoda::CanTouch );
2243
}
2244
2245
void CItemSoda::CanTouch ( CBaseEntity *pOther )
2246
{
2247
if ( !pOther->IsPlayer() )
2248
{
2249
return;
2250
}
2251
2252
// spoit sound here
2253
2254
pOther->TakeHealth( 1, DMG_GENERIC );// a bit of health.
2255
2256
if ( !FNullEnt( pev->owner ) )
2257
{
2258
// tell the machine the can was taken
2259
pev->owner->v.frags = 0;
2260
}
2261
2262
pev->solid = SOLID_NOT;
2263
pev->movetype = MOVETYPE_NONE;
2264
pev->effects = EF_NODRAW;
2265
SetTouch ( NULL );
2266
SetThink ( &CItemSoda::SUB_Remove );
2267
pev->nextthink = gpGlobals->time;
2268
}