doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Weapon.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "Game_local.h"
33 
34 /***********************************************************************
35 
36  idWeapon
37 
38 ***********************************************************************/
39 
40 //
41 // event defs
42 //
43 const idEventDef EV_Weapon_Clear( "<clear>" );
44 const idEventDef EV_Weapon_GetOwner( "getOwner", NULL, 'e' );
45 const idEventDef EV_Weapon_Next( "nextWeapon" );
46 const idEventDef EV_Weapon_State( "weaponState", "sd" );
47 const idEventDef EV_Weapon_UseAmmo( "useAmmo", "d" );
48 const idEventDef EV_Weapon_AddToClip( "addToClip", "d" );
49 const idEventDef EV_Weapon_AmmoInClip( "ammoInClip", NULL, 'f' );
50 const idEventDef EV_Weapon_AmmoAvailable( "ammoAvailable", NULL, 'f' );
51 const idEventDef EV_Weapon_TotalAmmoCount( "totalAmmoCount", NULL, 'f' );
52 const idEventDef EV_Weapon_ClipSize( "clipSize", NULL, 'f' );
53 const idEventDef EV_Weapon_WeaponOutOfAmmo( "weaponOutOfAmmo" );
54 const idEventDef EV_Weapon_WeaponReady( "weaponReady" );
55 const idEventDef EV_Weapon_WeaponReloading( "weaponReloading" );
56 const idEventDef EV_Weapon_WeaponHolstered( "weaponHolstered" );
57 const idEventDef EV_Weapon_WeaponRising( "weaponRising" );
58 const idEventDef EV_Weapon_WeaponLowering( "weaponLowering" );
59 const idEventDef EV_Weapon_Flashlight( "flashlight", "d" );
60 const idEventDef EV_Weapon_LaunchProjectiles( "launchProjectiles", "dffff" );
61 const idEventDef EV_Weapon_CreateProjectile( "createProjectile", NULL, 'e' );
62 const idEventDef EV_Weapon_EjectBrass( "ejectBrass" );
63 const idEventDef EV_Weapon_Melee( "melee", NULL, 'd' );
64 const idEventDef EV_Weapon_GetWorldModel( "getWorldModel", NULL, 'e' );
65 const idEventDef EV_Weapon_AllowDrop( "allowDrop", "d" );
66 const idEventDef EV_Weapon_AutoReload( "autoReload", NULL, 'f' );
67 const idEventDef EV_Weapon_NetReload( "netReload" );
68 const idEventDef EV_Weapon_IsInvisible( "isInvisible", NULL, 'f' );
69 const idEventDef EV_Weapon_NetEndReload( "netEndReload" );
70 #ifdef _D3XP
71 const idEventDef EV_Weapon_GrabberHasTarget( "grabberHasTarget", NULL, 'd' );
72 const idEventDef EV_Weapon_Grabber( "grabber", "d" );
73 const idEventDef EV_Weapon_Grabber_SetGrabDistance( "grabberGrabDistance", "f" );
74 const idEventDef EV_Weapon_LaunchProjectilesEllipse( "launchProjectilesEllipse", "dffff" );
75 const idEventDef EV_Weapon_LaunchPowerup( "launchPowerup", "sfd" );
76 const idEventDef EV_Weapon_StartWeaponSmoke( "startWeaponSmoke" );
77 const idEventDef EV_Weapon_StopWeaponSmoke( "stopWeaponSmoke" );
78 const idEventDef EV_Weapon_StartWeaponParticle( "startWeaponParticle", "s" );
79 const idEventDef EV_Weapon_StopWeaponParticle( "stopWeaponParticle", "s" );
80 const idEventDef EV_Weapon_StartWeaponLight( "startWeaponLight", "s" );
81 const idEventDef EV_Weapon_StopWeaponLight( "stopWeaponLight", "s" );
82 #endif
83 
84 //
85 // class def
86 //
88  EVENT( EV_Weapon_Clear, idWeapon::Event_Clear )
89  EVENT( EV_Weapon_GetOwner, idWeapon::Event_GetOwner )
90  EVENT( EV_Weapon_State, idWeapon::Event_WeaponState )
91  EVENT( EV_Weapon_WeaponReady, idWeapon::Event_WeaponReady )
92  EVENT( EV_Weapon_WeaponOutOfAmmo, idWeapon::Event_WeaponOutOfAmmo )
93  EVENT( EV_Weapon_WeaponReloading, idWeapon::Event_WeaponReloading )
94  EVENT( EV_Weapon_WeaponHolstered, idWeapon::Event_WeaponHolstered )
95  EVENT( EV_Weapon_WeaponRising, idWeapon::Event_WeaponRising )
96  EVENT( EV_Weapon_WeaponLowering, idWeapon::Event_WeaponLowering )
97  EVENT( EV_Weapon_UseAmmo, idWeapon::Event_UseAmmo )
98  EVENT( EV_Weapon_AddToClip, idWeapon::Event_AddToClip )
99  EVENT( EV_Weapon_AmmoInClip, idWeapon::Event_AmmoInClip )
100  EVENT( EV_Weapon_AmmoAvailable, idWeapon::Event_AmmoAvailable )
101  EVENT( EV_Weapon_TotalAmmoCount, idWeapon::Event_TotalAmmoCount )
102  EVENT( EV_Weapon_ClipSize, idWeapon::Event_ClipSize )
103  EVENT( AI_PlayAnim, idWeapon::Event_PlayAnim )
104  EVENT( AI_PlayCycle, idWeapon::Event_PlayCycle )
105  EVENT( AI_SetBlendFrames, idWeapon::Event_SetBlendFrames )
106  EVENT( AI_GetBlendFrames, idWeapon::Event_GetBlendFrames )
107  EVENT( AI_AnimDone, idWeapon::Event_AnimDone )
108  EVENT( EV_Weapon_Next, idWeapon::Event_Next )
109  EVENT( EV_SetSkin, idWeapon::Event_SetSkin )
110  EVENT( EV_Weapon_Flashlight, idWeapon::Event_Flashlight )
111  EVENT( EV_Light_GetLightParm, idWeapon::Event_GetLightParm )
112  EVENT( EV_Light_SetLightParm, idWeapon::Event_SetLightParm )
113  EVENT( EV_Light_SetLightParms, idWeapon::Event_SetLightParms )
114  EVENT( EV_Weapon_LaunchProjectiles, idWeapon::Event_LaunchProjectiles )
115  EVENT( EV_Weapon_CreateProjectile, idWeapon::Event_CreateProjectile )
116  EVENT( EV_Weapon_EjectBrass, idWeapon::Event_EjectBrass )
117  EVENT( EV_Weapon_Melee, idWeapon::Event_Melee )
118  EVENT( EV_Weapon_GetWorldModel, idWeapon::Event_GetWorldModel )
119  EVENT( EV_Weapon_AllowDrop, idWeapon::Event_AllowDrop )
120  EVENT( EV_Weapon_AutoReload, idWeapon::Event_AutoReload )
121  EVENT( EV_Weapon_NetReload, idWeapon::Event_NetReload )
122  EVENT( EV_Weapon_IsInvisible, idWeapon::Event_IsInvisible )
123  EVENT( EV_Weapon_NetEndReload, idWeapon::Event_NetEndReload )
124 #ifdef _D3XP
125  EVENT( EV_Weapon_Grabber, idWeapon::Event_Grabber )
126  EVENT( EV_Weapon_GrabberHasTarget, idWeapon::Event_GrabberHasTarget )
127  EVENT( EV_Weapon_Grabber_SetGrabDistance, idWeapon::Event_GrabberSetGrabDistance )
128  EVENT( EV_Weapon_LaunchProjectilesEllipse, idWeapon::Event_LaunchProjectilesEllipse )
129  EVENT( EV_Weapon_LaunchPowerup, idWeapon::Event_LaunchPowerup )
130  EVENT( EV_Weapon_StartWeaponSmoke, idWeapon::Event_StartWeaponSmoke )
131  EVENT( EV_Weapon_StopWeaponSmoke, idWeapon::Event_StopWeaponSmoke )
132  EVENT( EV_Weapon_StartWeaponParticle, idWeapon::Event_StartWeaponParticle )
133  EVENT( EV_Weapon_StopWeaponParticle, idWeapon::Event_StopWeaponParticle )
134  EVENT( EV_Weapon_StartWeaponLight, idWeapon::Event_StartWeaponLight )
135  EVENT( EV_Weapon_StopWeaponLight, idWeapon::Event_StopWeaponLight )
136 #endif
137 END_CLASS
138 
139 /***********************************************************************
140 
141  init
142 
143 ***********************************************************************/
144 
145 /*
146 ================
147 idWeapon::idWeapon()
148 ================
149 */
151  owner = NULL;
152  worldModel = NULL;
153  weaponDef = NULL;
154  thread = NULL;
155 
156  memset( &guiLight, 0, sizeof( guiLight ) );
157  memset( &muzzleFlash, 0, sizeof( muzzleFlash ) );
158  memset( &worldMuzzleFlash, 0, sizeof( worldMuzzleFlash ) );
159  memset( &nozzleGlow, 0, sizeof( nozzleGlow ) );
160 
161  muzzleFlashEnd = 0;
163  muzzleFlashHandle = -1;
165  guiLightHandle = -1;
166  nozzleGlowHandle = -1;
167  modelDefHandle = -1;
168 #ifdef _D3XP
169  grabberState = -1;
170 #endif
171 
172  berserk = 2;
173  brassDelay = 0;
174 
175  allowDrop = true;
176 
177  Clear();
178 
179  fl.networkSync = true;
180 }
181 
182 /*
183 ================
184 idWeapon::~idWeapon()
185 ================
186 */
188  Clear();
189  delete worldModel.GetEntity();
190 }
191 
192 
193 /*
194 ================
195 idWeapon::Spawn
196 ================
197 */
198 void idWeapon::Spawn( void ) {
199  if ( !gameLocal.isClient ) {
200  // setup the world model
201  worldModel = static_cast< idAnimatedEntity * >( gameLocal.SpawnEntityType( idAnimatedEntity::Type, NULL ) );
203  }
204 
205 #ifdef _D3XP
206  if ( 1 ) {
207  grabber.Initialize();
208  }
209 #endif
210 
211  thread = new idThread();
212  thread->ManualDelete();
214 }
215 
216 /*
217 ================
218 idWeapon::SetOwner
219 
220 Only called at player spawn time, not each weapon switch
221 ================
222 */
223 void idWeapon::SetOwner( idPlayer *_owner ) {
224  assert( !owner );
225  owner = _owner;
226  SetName( va( "%s_weapon", owner->name.c_str() ) );
227 
228  if ( worldModel.GetEntity() ) {
229  worldModel.GetEntity()->SetName( va( "%s_weapon_worldmodel", owner->name.c_str() ) );
230  }
231 }
232 
233 /*
234 ================
235 idWeapon::ShouldConstructScriptObjectAtSpawn
236 
237 Called during idEntity::Spawn to see if it should construct the script object or not.
238 Overridden by subclasses that need to spawn the script object themselves.
239 ================
240 */
242  return false;
243 }
244 
245 /*
246 ================
247 idWeapon::CacheWeapon
248 ================
249 */
250 void idWeapon::CacheWeapon( const char *weaponName ) {
251  const idDeclEntityDef *weaponDef;
252  const char *brassDefName;
253  const char *clipModelName;
254  idTraceModel trm;
255  const char *guiName;
256 
257  weaponDef = gameLocal.FindEntityDef( weaponName, false );
258  if ( !weaponDef ) {
259  return;
260  }
261 
262  // precache the brass collision model
263  brassDefName = weaponDef->dict.GetString( "def_ejectBrass" );
264  if ( brassDefName[0] ) {
265  const idDeclEntityDef *brassDef = gameLocal.FindEntityDef( brassDefName, false );
266  if ( brassDef ) {
267  brassDef->dict.GetString( "clipmodel", "", &clipModelName );
268  if ( !clipModelName[0] ) {
269  clipModelName = brassDef->dict.GetString( "model" ); // use the visual model
270  }
271  // load the trace model
272  collisionModelManager->TrmFromModel( clipModelName, trm );
273  }
274  }
275 
276  guiName = weaponDef->dict.GetString( "gui" );
277  if ( guiName[0] ) {
278  uiManager->FindGui( guiName, true, false, true );
279  }
280 }
281 
282 /*
283 ================
284 idWeapon::Save
285 ================
286 */
287 void idWeapon::Save( idSaveGame *savefile ) const {
288 
289  savefile->WriteInt( status );
290  savefile->WriteObject( thread );
291  savefile->WriteString( state );
292  savefile->WriteString( idealState );
293  savefile->WriteInt( animBlendFrames );
294  savefile->WriteInt( animDoneTime );
295  savefile->WriteBool( isLinked );
296 
297  savefile->WriteObject( owner );
298  worldModel.Save( savefile );
299 
300  savefile->WriteInt( hideTime );
301  savefile->WriteFloat( hideDistance );
302  savefile->WriteInt( hideStartTime );
303  savefile->WriteFloat( hideStart );
304  savefile->WriteFloat( hideEnd );
305  savefile->WriteFloat( hideOffset );
306  savefile->WriteBool( hide );
307  savefile->WriteBool( disabled );
308 
309  savefile->WriteInt( berserk );
310 
311  savefile->WriteVec3( playerViewOrigin );
312  savefile->WriteMat3( playerViewAxis );
313 
314  savefile->WriteVec3( viewWeaponOrigin );
315  savefile->WriteMat3( viewWeaponAxis );
316 
317  savefile->WriteVec3( muzzleOrigin );
318  savefile->WriteMat3( muzzleAxis );
319 
320  savefile->WriteVec3( pushVelocity );
321 
322  savefile->WriteString( weaponDef->GetName() );
323  savefile->WriteFloat( meleeDistance );
324  savefile->WriteString( meleeDefName );
325  savefile->WriteInt( brassDelay );
326  savefile->WriteString( icon );
327 
328  savefile->WriteInt( guiLightHandle );
329  savefile->WriteRenderLight( guiLight );
330 
331  savefile->WriteInt( muzzleFlashHandle );
332  savefile->WriteRenderLight( muzzleFlash );
333 
334  savefile->WriteInt( worldMuzzleFlashHandle );
335  savefile->WriteRenderLight( worldMuzzleFlash );
336 
337  savefile->WriteVec3( flashColor );
338  savefile->WriteInt( muzzleFlashEnd );
339  savefile->WriteInt( flashTime );
340 
341  savefile->WriteBool( lightOn );
342  savefile->WriteBool( silent_fire );
343 
344  savefile->WriteInt( kick_endtime );
345  savefile->WriteInt( muzzle_kick_time );
346  savefile->WriteInt( muzzle_kick_maxtime );
347  savefile->WriteAngles( muzzle_kick_angles );
348  savefile->WriteVec3( muzzle_kick_offset );
349 
350  savefile->WriteInt( ammoType );
351  savefile->WriteInt( ammoRequired );
352  savefile->WriteInt( clipSize );
353  savefile->WriteInt( ammoClip );
354  savefile->WriteInt( lowAmmo );
355  savefile->WriteBool( powerAmmo );
356 
357  // savegames <= 17
358  savefile->WriteInt( 0 );
359 
360  savefile->WriteInt( zoomFov );
361 
362  savefile->WriteJoint( barrelJointView );
363  savefile->WriteJoint( flashJointView );
364  savefile->WriteJoint( ejectJointView );
365  savefile->WriteJoint( guiLightJointView );
366  savefile->WriteJoint( ventLightJointView );
367 
368  savefile->WriteJoint( flashJointWorld );
369  savefile->WriteJoint( barrelJointWorld );
370  savefile->WriteJoint( ejectJointWorld );
371 
372  savefile->WriteBool( hasBloodSplat );
373 
374  savefile->WriteSoundShader( sndHum );
375 
376  savefile->WriteParticle( weaponSmoke );
377  savefile->WriteInt( weaponSmokeStartTime );
378  savefile->WriteBool( continuousSmoke );
379  savefile->WriteParticle( strikeSmoke );
380  savefile->WriteInt( strikeSmokeStartTime );
381  savefile->WriteVec3( strikePos );
382  savefile->WriteMat3( strikeAxis );
383  savefile->WriteInt( nextStrikeFx );
384 
385  savefile->WriteBool( nozzleFx );
386  savefile->WriteInt( nozzleFxFade );
387 
388  savefile->WriteInt( lastAttack );
389 
390  savefile->WriteInt( nozzleGlowHandle );
391  savefile->WriteRenderLight( nozzleGlow );
392 
393  savefile->WriteVec3( nozzleGlowColor );
394  savefile->WriteMaterial( nozzleGlowShader );
395  savefile->WriteFloat( nozzleGlowRadius );
396 
397  savefile->WriteInt( weaponAngleOffsetAverages );
398  savefile->WriteFloat( weaponAngleOffsetScale );
399  savefile->WriteFloat( weaponAngleOffsetMax );
400  savefile->WriteFloat( weaponOffsetTime );
401  savefile->WriteFloat( weaponOffsetScale );
402 
403  savefile->WriteBool( allowDrop );
404  savefile->WriteObject( projectileEnt );
405 
406 #ifdef _D3XP
407  savefile->WriteStaticObject( grabber );
408  savefile->WriteInt( grabberState );
409 
410  savefile->WriteJoint ( smokeJointView );
411 
412  savefile->WriteInt(weaponParticles.Num());
413  for(int i = 0; i < weaponParticles.Num(); i++) {
414  WeaponParticle_t* part = weaponParticles.GetIndex(i);
415  savefile->WriteString( part->name );
416  savefile->WriteString( part->particlename );
417  savefile->WriteBool( part->active );
418  savefile->WriteInt( part->startTime );
419  savefile->WriteJoint( part->joint );
420  savefile->WriteBool( part->smoke );
421  if(!part->smoke) {
422  savefile->WriteObject(part->emitter);
423  }
424  }
425  savefile->WriteInt(weaponLights.Num());
426  for(int i = 0; i < weaponLights.Num(); i++) {
427  WeaponLight_t* light = weaponLights.GetIndex(i);
428  savefile->WriteString( light->name );
429  savefile->WriteBool( light->active );
430  savefile->WriteInt( light->startTime );
431  savefile->WriteJoint( light->joint );
432  savefile->WriteInt( light->lightHandle );
433  savefile->WriteRenderLight( light->light );
434  }
435 #endif
436 
437 }
438 
439 /*
440 ================
441 idWeapon::Restore
442 ================
443 */
444 void idWeapon::Restore( idRestoreGame *savefile ) {
445 
446  savefile->ReadInt( (int &)status );
447  savefile->ReadObject( reinterpret_cast<idClass *&>( thread ) );
448  savefile->ReadString( state );
449  savefile->ReadString( idealState );
450  savefile->ReadInt( animBlendFrames );
451  savefile->ReadInt( animDoneTime );
452  savefile->ReadBool( isLinked );
453 
454  // Re-link script fields
455  WEAPON_ATTACK.LinkTo( scriptObject, "WEAPON_ATTACK" );
456  WEAPON_RELOAD.LinkTo( scriptObject, "WEAPON_RELOAD" );
457  WEAPON_NETRELOAD.LinkTo( scriptObject, "WEAPON_NETRELOAD" );
458  WEAPON_NETENDRELOAD.LinkTo( scriptObject, "WEAPON_NETENDRELOAD" );
459  WEAPON_NETFIRING.LinkTo( scriptObject, "WEAPON_NETFIRING" );
460  WEAPON_RAISEWEAPON.LinkTo( scriptObject, "WEAPON_RAISEWEAPON" );
461  WEAPON_LOWERWEAPON.LinkTo( scriptObject, "WEAPON_LOWERWEAPON" );
462 
463  savefile->ReadObject( reinterpret_cast<idClass *&>( owner ) );
464  worldModel.Restore( savefile );
465 
466  savefile->ReadInt( hideTime );
467  savefile->ReadFloat( hideDistance );
468  savefile->ReadInt( hideStartTime );
469  savefile->ReadFloat( hideStart );
470  savefile->ReadFloat( hideEnd );
471  savefile->ReadFloat( hideOffset );
472  savefile->ReadBool( hide );
473  savefile->ReadBool( disabled );
474 
475  savefile->ReadInt( berserk );
476 
477  savefile->ReadVec3( playerViewOrigin );
478  savefile->ReadMat3( playerViewAxis );
479 
480  savefile->ReadVec3( viewWeaponOrigin );
481  savefile->ReadMat3( viewWeaponAxis );
482 
483  savefile->ReadVec3( muzzleOrigin );
484  savefile->ReadMat3( muzzleAxis );
485 
486  savefile->ReadVec3( pushVelocity );
487 
488  idStr objectname;
489  savefile->ReadString( objectname );
490  weaponDef = gameLocal.FindEntityDef( objectname );
491  meleeDef = gameLocal.FindEntityDef( weaponDef->dict.GetString( "def_melee" ), false );
492 
493  const idDeclEntityDef *projectileDef = gameLocal.FindEntityDef( weaponDef->dict.GetString( "def_projectile" ), false );
494  if ( projectileDef ) {
495  projectileDict = projectileDef->dict;
496  } else {
498  }
499 
500  const idDeclEntityDef *brassDef = gameLocal.FindEntityDef( weaponDef->dict.GetString( "def_ejectBrass" ), false );
501  if ( brassDef ) {
502  brassDict = brassDef->dict;
503  } else {
504  brassDict.Clear();
505  }
506 
507  savefile->ReadFloat( meleeDistance );
508  savefile->ReadString( meleeDefName );
509  savefile->ReadInt( brassDelay );
510  savefile->ReadString( icon );
511 
512  savefile->ReadInt( guiLightHandle );
513  savefile->ReadRenderLight( guiLight );
514 #ifdef _D3XP
515  if ( guiLightHandle >= 0 ) {
517  }
518 #endif
519 
520  savefile->ReadInt( muzzleFlashHandle );
521  savefile->ReadRenderLight( muzzleFlash );
522 #ifdef _D3XP
523  if ( muzzleFlashHandle >= 0 ) {
525  }
526 #endif
527 
528  savefile->ReadInt( worldMuzzleFlashHandle );
529  savefile->ReadRenderLight( worldMuzzleFlash );
530 #ifdef _D3XP
531  if ( worldMuzzleFlashHandle >= 0 ) {
533  }
534 #endif
535 
536  savefile->ReadVec3( flashColor );
537  savefile->ReadInt( muzzleFlashEnd );
538  savefile->ReadInt( flashTime );
539 
540  savefile->ReadBool( lightOn );
541  savefile->ReadBool( silent_fire );
542 
543  savefile->ReadInt( kick_endtime );
544  savefile->ReadInt( muzzle_kick_time );
545  savefile->ReadInt( muzzle_kick_maxtime );
546  savefile->ReadAngles( muzzle_kick_angles );
547  savefile->ReadVec3( muzzle_kick_offset );
548 
549  savefile->ReadInt( (int &)ammoType );
550  savefile->ReadInt( ammoRequired );
551  savefile->ReadInt( clipSize );
552  savefile->ReadInt( ammoClip );
553  savefile->ReadInt( lowAmmo );
554  savefile->ReadBool( powerAmmo );
555 
556  // savegame versions <= 17
557  int foo;
558  savefile->ReadInt( foo );
559 
560  savefile->ReadInt( zoomFov );
561 
562  savefile->ReadJoint( barrelJointView );
563  savefile->ReadJoint( flashJointView );
564  savefile->ReadJoint( ejectJointView );
565  savefile->ReadJoint( guiLightJointView );
566  savefile->ReadJoint( ventLightJointView );
567 
568  savefile->ReadJoint( flashJointWorld );
569  savefile->ReadJoint( barrelJointWorld );
570  savefile->ReadJoint( ejectJointWorld );
571 
572  savefile->ReadBool( hasBloodSplat );
573 
574  savefile->ReadSoundShader( sndHum );
575 
576  savefile->ReadParticle( weaponSmoke );
577  savefile->ReadInt( weaponSmokeStartTime );
578  savefile->ReadBool( continuousSmoke );
579  savefile->ReadParticle( strikeSmoke );
580  savefile->ReadInt( strikeSmokeStartTime );
581  savefile->ReadVec3( strikePos );
582  savefile->ReadMat3( strikeAxis );
583  savefile->ReadInt( nextStrikeFx );
584 
585  savefile->ReadBool( nozzleFx );
586  savefile->ReadInt( nozzleFxFade );
587 
588  savefile->ReadInt( lastAttack );
589 
590  savefile->ReadInt( nozzleGlowHandle );
591  savefile->ReadRenderLight( nozzleGlow );
592 #ifdef _D3XP
593  if ( nozzleGlowHandle >= 0 ) {
595  }
596 #endif
597 
598  savefile->ReadVec3( nozzleGlowColor );
599  savefile->ReadMaterial( nozzleGlowShader );
600  savefile->ReadFloat( nozzleGlowRadius );
601 
602  savefile->ReadInt( weaponAngleOffsetAverages );
603  savefile->ReadFloat( weaponAngleOffsetScale );
604  savefile->ReadFloat( weaponAngleOffsetMax );
605  savefile->ReadFloat( weaponOffsetTime );
606  savefile->ReadFloat( weaponOffsetScale );
607 
608  savefile->ReadBool( allowDrop );
609  savefile->ReadObject( reinterpret_cast<idClass *&>( projectileEnt ) );
610 
611 #ifdef _D3XP
612  savefile->ReadStaticObject( grabber );
613  savefile->ReadInt( grabberState );
614 
615  savefile->ReadJoint ( smokeJointView );
616 
617  int particleCount;
618  savefile->ReadInt( particleCount );
619  for(int i = 0; i < particleCount; i++) {
620  WeaponParticle_t newParticle;
621  memset(&newParticle, 0, sizeof(newParticle));
622 
623  idStr name, particlename;
624  savefile->ReadString( name );
625  savefile->ReadString( particlename );
626 
627  strcpy( newParticle.name, name.c_str() );
628  strcpy( newParticle.particlename, particlename.c_str() );
629 
630  savefile->ReadBool( newParticle.active );
631  savefile->ReadInt( newParticle.startTime );
632  savefile->ReadJoint( newParticle.joint );
633  savefile->ReadBool( newParticle.smoke );
634  if(newParticle.smoke) {
635  newParticle.particle = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, particlename, false ) );
636  } else {
637  savefile->ReadObject(reinterpret_cast<idClass *&>(newParticle.emitter));
638  }
639 
640  weaponParticles.Set(newParticle.name, newParticle);
641  }
642 
643  int lightCount;
644  savefile->ReadInt( lightCount );
645  for(int i = 0; i < lightCount; i++) {
646  WeaponLight_t newLight;
647  memset(&newLight, 0, sizeof(newLight));
648 
649  idStr name;
650  savefile->ReadString( name );
651  strcpy( newLight.name, name.c_str() );
652 
653  savefile->ReadBool( newLight.active );
654  savefile->ReadInt( newLight.startTime );
655  savefile->ReadJoint( newLight.joint );
656  savefile->ReadInt( newLight.lightHandle );
657  savefile->ReadRenderLight( newLight.light );
658  if ( newLight.lightHandle >= 0 ) {
659  newLight.lightHandle = gameRenderWorld->AddLightDef( &newLight.light );
660  }
661  weaponLights.Set(newLight.name, newLight);
662  }
663 #endif
664 }
665 
666 /***********************************************************************
667 
668  Weapon definition management
669 
670 ***********************************************************************/
671 
672 /*
673 ================
674 idWeapon::Clear
675 ================
676 */
677 void idWeapon::Clear( void ) {
678  CancelEvents( &EV_Weapon_Clear );
679 
681  scriptObject.Free();
682 
690 
691  if ( muzzleFlashHandle != -1 ) {
693  muzzleFlashHandle = -1;
694  }
695  if ( muzzleFlashHandle != -1 ) {
697  muzzleFlashHandle = -1;
698  }
699  if ( worldMuzzleFlashHandle != -1 ) {
702  }
703  if ( guiLightHandle != -1 ) {
705  guiLightHandle = -1;
706  }
707  if ( nozzleGlowHandle != -1 ) {
709  nozzleGlowHandle = -1;
710  }
711 
712  memset( &renderEntity, 0, sizeof( renderEntity ) );
714 
715  renderEntity.noShadow = true;
716  renderEntity.noSelfShadow = true;
718 
719  // set default shader parms
723  renderEntity.shaderParms[3] = 1.0f;
725  renderEntity.shaderParms[5] = 0.0f;
726  renderEntity.shaderParms[6] = 0.0f;
727  renderEntity.shaderParms[7] = 0.0f;
728 
729  if ( refSound.referenceSound ) {
730  refSound.referenceSound->Free( true );
731  }
732  memset( &refSound, 0, sizeof( refSound_t ) );
733 
734  // setting diversity to 0 results in no random sound. -1 indicates random.
735  refSound.diversity = -1.0f;
736 
737  if ( owner ) {
738  // don't spatialize the weapon sounds
740  }
741 
742  // clear out the sounds from our spawnargs since we'll copy them from the weapon def
743  const idKeyValue *kv = spawnArgs.MatchPrefix( "snd_" );
744  while( kv ) {
745  spawnArgs.Delete( kv->GetKey() );
746  kv = spawnArgs.MatchPrefix( "snd_" );
747  }
748 
749  hideTime = 300;
750  hideDistance = -15.0f;
752  hideStart = 0.0f;
753  hideEnd = 0.0f;
754  hideOffset = 0.0f;
755  hide = false;
756  disabled = false;
757 
758  weaponSmoke = NULL;
760  continuousSmoke = false;
761  strikeSmoke = NULL;
763  strikePos.Zero();
765  nextStrikeFx = 0;
766 
767  icon = "";
768 
774  muzzleOrigin.Zero();
775  pushVelocity.Zero();
776 
778  state = "";
779  idealState = "";
780  animBlendFrames = 0;
781  animDoneTime = 0;
782 
784  meleeDef = NULL;
785  meleeDefName = "";
786  meleeDistance = 0.0f;
787  brassDict.Clear();
788 
789  flashTime = 250;
790  lightOn = false;
791  silent_fire = false;
792 
793 #ifdef _D3XP
794  grabberState = -1;
795  grabber.Update( owner, true );
796 #endif
797 
798  ammoType = 0;
799  ammoRequired = 0;
800  ammoClip = 0;
801  clipSize = 0;
802  lowAmmo = 0;
803  powerAmmo = false;
804 
805  kick_endtime = 0;
806  muzzle_kick_time = 0;
810 
811  zoomFov = 90;
812 
818 
822 
823 #ifdef _D3XP
824  smokeJointView = INVALID_JOINT;
825 
826  //Clean up the weapon particles
827  for(int i = 0; i < weaponParticles.Num(); i++) {
828  WeaponParticle_t* part = weaponParticles.GetIndex(i);
829  if(!part->smoke) {
830  //Destroy the emitters
831  part->emitter->PostEventMS(&EV_Remove, 0 );
832  }
833  }
834  weaponParticles.Clear();
835 
836  //Clean up the weapon lights
837  for(int i = 0; i < weaponLights.Num(); i++) {
838  WeaponLight_t* light = weaponLights.GetIndex(i);
839  if ( light->lightHandle != -1 ) {
840  gameRenderWorld->FreeLightDef( light->lightHandle );
841  }
842  }
843  weaponLights.Clear();
844 #endif
845 
846  hasBloodSplat = false;
847  nozzleFx = false;
848  nozzleFxFade = 1500;
849  lastAttack = 0;
850  nozzleGlowHandle = -1;
852  nozzleGlowRadius = 10;
854 
856  weaponAngleOffsetScale = 0.0f;
857  weaponAngleOffsetMax = 0.0f;
858  weaponOffsetTime = 0.0f;
859  weaponOffsetScale = 0.0f;
860 
861  allowDrop = true;
862 
864  FreeModelDef();
865 
866  sndHum = NULL;
867 
868  isLinked = false;
870 
871  isFiring = false;
872 }
873 
874 /*
875 ================
876 idWeapon::InitWorldModel
877 ================
878 */
880  idEntity *ent;
881 
882  ent = worldModel.GetEntity();
883 
884  assert( ent );
885  assert( def );
886 
887  const char *model = def->dict.GetString( "model_world" );
888  const char *attach = def->dict.GetString( "joint_attach" );
889 
890  ent->SetSkin( NULL );
891  if ( model[0] && attach[0] ) {
892  ent->Show();
893  ent->SetModel( model );
894  if ( ent->GetAnimator()->ModelDef() ) {
895  ent->SetSkin( ent->GetAnimator()->ModelDef()->GetDefaultSkin() );
896  }
897  ent->GetPhysics()->SetContents( 0 );
898  ent->GetPhysics()->SetClipModel( NULL, 1.0f );
899  ent->BindToJoint( owner, attach, true );
900  ent->GetPhysics()->SetOrigin( vec3_origin );
901  ent->GetPhysics()->SetAxis( mat3_identity );
902 
903  // supress model in player views, but allow it in mirrors and remote views
904  renderEntity_t *worldModelRenderEntity = ent->GetRenderEntity();
905  if ( worldModelRenderEntity ) {
906  worldModelRenderEntity->suppressSurfaceInViewID = owner->entityNumber+1;
907  worldModelRenderEntity->suppressShadowInViewID = owner->entityNumber+1;
908  worldModelRenderEntity->suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + owner->entityNumber;
909  }
910  } else {
911  ent->SetModel( "" );
912  ent->Hide();
913  }
914 
915  flashJointWorld = ent->GetAnimator()->GetJointHandle( "flash" );
916  barrelJointWorld = ent->GetAnimator()->GetJointHandle( "muzzle" );
917  ejectJointWorld = ent->GetAnimator()->GetJointHandle( "eject" );
918 }
919 
920 /*
921 ================
922 idWeapon::GetWeaponDef
923 ================
924 */
925 void idWeapon::GetWeaponDef( const char *objectname, int ammoinclip ) {
926  const char *shader;
927  const char *objectType;
928  const char *vmodel;
929  const char *guiName;
930  const char *projectileName;
931  const char *brassDefName;
932  const char *smokeName;
933  int ammoAvail;
934 
935  Clear();
936 
937  if ( !objectname || !objectname[ 0 ] ) {
938  return;
939  }
940 
941  assert( owner );
942 
943  weaponDef = gameLocal.FindEntityDef( objectname );
944 
945  ammoType = GetAmmoNumForName( weaponDef->dict.GetString( "ammoType" ) );
946  ammoRequired = weaponDef->dict.GetInt( "ammoRequired" );
947  clipSize = weaponDef->dict.GetInt( "clipSize" );
948  lowAmmo = weaponDef->dict.GetInt( "lowAmmo" );
949 
950  icon = weaponDef->dict.GetString( "icon" );
951  silent_fire = weaponDef->dict.GetBool( "silent_fire" );
952  powerAmmo = weaponDef->dict.GetBool( "powerAmmo" );
953 
954  muzzle_kick_time = SEC2MS( weaponDef->dict.GetFloat( "muzzle_kick_time" ) );
955  muzzle_kick_maxtime = SEC2MS( weaponDef->dict.GetFloat( "muzzle_kick_maxtime" ) );
956  muzzle_kick_angles = weaponDef->dict.GetAngles( "muzzle_kick_angles" );
957  muzzle_kick_offset = weaponDef->dict.GetVector( "muzzle_kick_offset" );
958 
959  hideTime = SEC2MS( weaponDef->dict.GetFloat( "hide_time", "0.3" ) );
960  hideDistance = weaponDef->dict.GetFloat( "hide_distance", "-15" );
961 
962  // muzzle smoke
963  smokeName = weaponDef->dict.GetString( "smoke_muzzle" );
964  if ( *smokeName != '\0' ) {
965  weaponSmoke = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, smokeName ) );
966  } else {
967  weaponSmoke = NULL;
968  }
969  continuousSmoke = weaponDef->dict.GetBool( "continuousSmoke" );
971 
972  smokeName = weaponDef->dict.GetString( "smoke_strike" );
973  if ( *smokeName != '\0' ) {
974  strikeSmoke = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, smokeName ) );
975  } else {
976  strikeSmoke = NULL;
977  }
979  strikePos.Zero();
981  nextStrikeFx = 0;
982 
983  // setup gui light
984  memset( &guiLight, 0, sizeof( guiLight ) );
985  const char *guiLightShader = weaponDef->dict.GetString( "mtr_guiLightShader" );
986  if ( *guiLightShader != '\0' ) {
987  guiLight.shader = declManager->FindMaterial( guiLightShader, false );
989  guiLight.pointLight = true;
990  }
991 
992  // setup the view model
993  vmodel = weaponDef->dict.GetString( "model_view" );
994  SetModel( vmodel );
995 
996  // setup the world model
998 
999  // copy the sounds from the weapon view model def into out spawnargs
1000  const idKeyValue *kv = weaponDef->dict.MatchPrefix( "snd_" );
1001  while( kv ) {
1002  spawnArgs.Set( kv->GetKey(), kv->GetValue() );
1003  kv = weaponDef->dict.MatchPrefix( "snd_", kv );
1004  }
1005 
1006  // find some joints in the model for locating effects
1007  barrelJointView = animator.GetJointHandle( "barrel" );
1008  flashJointView = animator.GetJointHandle( "flash" );
1009  ejectJointView = animator.GetJointHandle( "eject" );
1010  guiLightJointView = animator.GetJointHandle( "guiLight" );
1011  ventLightJointView = animator.GetJointHandle( "ventLight" );
1012 
1013 #ifdef _D3XP
1014  idStr smokeJoint = weaponDef->dict.GetString("smoke_joint");
1015  if(smokeJoint.Length() > 0) {
1016  smokeJointView = animator.GetJointHandle( smokeJoint );
1017  } else {
1018  smokeJointView = INVALID_JOINT;
1019  }
1020 #endif
1021 
1022  // get the projectile
1024 
1025  projectileName = weaponDef->dict.GetString( "def_projectile" );
1026  if ( projectileName[0] != '\0' ) {
1027  const idDeclEntityDef *projectileDef = gameLocal.FindEntityDef( projectileName, false );
1028  if ( !projectileDef ) {
1029  gameLocal.Warning( "Unknown projectile '%s' in weapon '%s'", projectileName, objectname );
1030  } else {
1031  const char *spawnclass = projectileDef->dict.GetString( "spawnclass" );
1032  idTypeInfo *cls = idClass::GetClass( spawnclass );
1033  if ( !cls || !cls->IsType( idProjectile::Type ) ) {
1034  gameLocal.Warning( "Invalid spawnclass '%s' on projectile '%s' (used by weapon '%s')", spawnclass, projectileName, objectname );
1035  } else {
1036  projectileDict = projectileDef->dict;
1037  }
1038  }
1039  }
1040 
1041  // set up muzzleflash render light
1042  const idMaterial*flashShader;
1043  idVec3 flashTarget;
1044  idVec3 flashUp;
1045  idVec3 flashRight;
1046  float flashRadius;
1047  bool flashPointLight;
1048 
1049  weaponDef->dict.GetString( "mtr_flashShader", "", &shader );
1050  flashShader = declManager->FindMaterial( shader, false );
1051  flashPointLight = weaponDef->dict.GetBool( "flashPointLight", "1" );
1052  weaponDef->dict.GetVector( "flashColor", "0 0 0", flashColor );
1053  flashRadius = (float)weaponDef->dict.GetInt( "flashRadius" ); // if 0, no light will spawn
1054  flashTime = SEC2MS( weaponDef->dict.GetFloat( "flashTime", "0.25" ) );
1055  flashTarget = weaponDef->dict.GetVector( "flashTarget" );
1056  flashUp = weaponDef->dict.GetVector( "flashUp" );
1057  flashRight = weaponDef->dict.GetVector( "flashRight" );
1058 
1059  memset( &muzzleFlash, 0, sizeof( muzzleFlash ) );
1060  muzzleFlash.lightId = LIGHTID_VIEW_MUZZLE_FLASH + owner->entityNumber;
1062 
1063  // the weapon lights will only be in first person
1066 
1067  muzzleFlash.pointLight = flashPointLight;
1068  muzzleFlash.shader = flashShader;
1073 
1074  muzzleFlash.lightRadius[0] = flashRadius;
1075  muzzleFlash.lightRadius[1] = flashRadius;
1076  muzzleFlash.lightRadius[2] = flashRadius;
1077 
1078  if ( !flashPointLight ) {
1079  muzzleFlash.target = flashTarget;
1080  muzzleFlash.up = flashUp;
1081  muzzleFlash.right = flashRight;
1082  muzzleFlash.end = flashTarget;
1083  }
1084 
1085  // the world muzzle flash is the same, just positioned differently
1089  worldMuzzleFlash.lightId = LIGHTID_WORLD_MUZZLE_FLASH + owner->entityNumber;
1090 
1091  //-----------------------------------
1092 
1093  nozzleFx = weaponDef->dict.GetBool("nozzleFx");
1094  nozzleFxFade = weaponDef->dict.GetInt("nozzleFxFade", "1500");
1095  nozzleGlowColor = weaponDef->dict.GetVector("nozzleGlowColor", "1 1 1");
1096  nozzleGlowRadius = weaponDef->dict.GetFloat("nozzleGlowRadius", "10");
1097  weaponDef->dict.GetString( "mtr_nozzleGlowShader", "", &shader );
1098  nozzleGlowShader = declManager->FindMaterial( shader, false );
1099 
1100  // get the melee damage def
1101  meleeDistance = weaponDef->dict.GetFloat( "melee_distance" );
1102  meleeDefName = weaponDef->dict.GetString( "def_melee" );
1103  if ( meleeDefName.Length() ) {
1105  if ( !meleeDef ) {
1106  gameLocal.Error( "Unknown melee '%s'", meleeDefName.c_str() );
1107  }
1108  }
1109 
1110  // get the brass def
1111  brassDict.Clear();
1112  brassDelay = weaponDef->dict.GetInt( "ejectBrassDelay", "0" );
1113  brassDefName = weaponDef->dict.GetString( "def_ejectBrass" );
1114 
1115  if ( brassDefName[0] ) {
1116  const idDeclEntityDef *brassDef = gameLocal.FindEntityDef( brassDefName, false );
1117  if ( !brassDef ) {
1118  gameLocal.Warning( "Unknown brass '%s'", brassDefName );
1119  } else {
1120  brassDict = brassDef->dict;
1121  }
1122  }
1123 
1124  if ( ( ammoType < 0 ) || ( ammoType >= AMMO_NUMTYPES ) ) {
1125  gameLocal.Warning( "Unknown ammotype in object '%s'", objectname );
1126  }
1127 
1128  ammoClip = ammoinclip;
1129  if ( ( ammoClip < 0 ) || ( ammoClip > clipSize ) ) {
1130  // first time using this weapon so have it fully loaded to start
1131  ammoClip = clipSize;
1132  ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
1133  if ( ammoClip > ammoAvail ) {
1134  ammoClip = ammoAvail;
1135  }
1136 #ifdef _D3XP
1137  //In D3XP we use ammo as soon as it is moved into the clip. This allows for weapons that share ammo
1139 #endif
1140  }
1141 
1142  renderEntity.gui[ 0 ] = NULL;
1143  guiName = weaponDef->dict.GetString( "gui" );
1144  if ( guiName[0] ) {
1145  renderEntity.gui[ 0 ] = uiManager->FindGui( guiName, true, false, true );
1146  }
1147 
1148  zoomFov = weaponDef->dict.GetInt( "zoomFov", "70" );
1149  berserk = weaponDef->dict.GetInt( "berserk", "2" );
1150 
1151  weaponAngleOffsetAverages = weaponDef->dict.GetInt( "weaponAngleOffsetAverages", "10" );
1152  weaponAngleOffsetScale = weaponDef->dict.GetFloat( "weaponAngleOffsetScale", "0.25" );
1153  weaponAngleOffsetMax = weaponDef->dict.GetFloat( "weaponAngleOffsetMax", "10" );
1154 
1155  weaponOffsetTime = weaponDef->dict.GetFloat( "weaponOffsetTime", "400" );
1156  weaponOffsetScale = weaponDef->dict.GetFloat( "weaponOffsetScale", "0.005" );
1157 
1158  if ( !weaponDef->dict.GetString( "weapon_scriptobject", NULL, &objectType ) ) {
1159  gameLocal.Error( "No 'weapon_scriptobject' set on '%s'.", objectname );
1160  }
1161 
1162  // setup script object
1163  if ( !scriptObject.SetType( objectType ) ) {
1164  gameLocal.Error( "Script object '%s' not found on weapon '%s'.", objectType, objectname );
1165  }
1166 
1167  WEAPON_ATTACK.LinkTo( scriptObject, "WEAPON_ATTACK" );
1168  WEAPON_RELOAD.LinkTo( scriptObject, "WEAPON_RELOAD" );
1169  WEAPON_NETRELOAD.LinkTo( scriptObject, "WEAPON_NETRELOAD" );
1170  WEAPON_NETENDRELOAD.LinkTo( scriptObject, "WEAPON_NETENDRELOAD" );
1171  WEAPON_NETFIRING.LinkTo( scriptObject, "WEAPON_NETFIRING" );
1172  WEAPON_RAISEWEAPON.LinkTo( scriptObject, "WEAPON_RAISEWEAPON" );
1173  WEAPON_LOWERWEAPON.LinkTo( scriptObject, "WEAPON_LOWERWEAPON" );
1174 
1176 
1177  shader = spawnArgs.GetString( "snd_hum" );
1178  if ( shader && *shader ) {
1179  sndHum = declManager->FindSound( shader );
1181  }
1182 
1183  isLinked = true;
1184 
1185  // call script object's constructor
1187 
1188  // make sure we have the correct skin
1189  UpdateSkin();
1190 
1191 #ifdef _D3XP
1192  idEntity *ent = worldModel.GetEntity();
1193  DetermineTimeGroup( weaponDef->dict.GetBool( "slowmo", "0" ) );
1194  if ( ent ) {
1195  ent->DetermineTimeGroup( weaponDef->dict.GetBool( "slowmo", "0" ) );
1196  }
1197 
1198  //Initialize the particles
1199  if ( !gameLocal.isMultiplayer ) {
1200 
1201  const idKeyValue *pkv = weaponDef->dict.MatchPrefix( "weapon_particle", NULL );
1202  while( pkv ) {
1203  WeaponParticle_t newParticle;
1204  memset( &newParticle, 0, sizeof( newParticle ) );
1205 
1206  idStr name = pkv->GetValue();
1207 
1208  strcpy(newParticle.name, name.c_str());
1209 
1210  idStr jointName = weaponDef->dict.GetString(va("%s_joint", name.c_str()));
1211  newParticle.joint = animator.GetJointHandle(jointName.c_str());
1212  newParticle.smoke = weaponDef->dict.GetBool(va("%s_smoke", name.c_str()));
1213  newParticle.active = false;
1214  newParticle.startTime = 0;
1215 
1216  idStr particle = weaponDef->dict.GetString(va("%s_particle", name.c_str()));
1217  strcpy(newParticle.particlename, particle.c_str());
1218 
1219  if(newParticle.smoke) {
1220  newParticle.particle = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, particle, false ) );
1221  } else {
1222  idDict args;
1223 
1224  const idDeclEntityDef *emitterDef = gameLocal.FindEntityDef( "func_emitter", false );
1225  args = emitterDef->dict;
1226  args.Set("model", particle.c_str());
1227  args.SetBool("start_off", true);
1228 
1229  idEntity* ent;
1230  gameLocal.SpawnEntityDef(args, &ent, false);
1231  newParticle.emitter = (idFuncEmitter*)ent;
1232 
1233  newParticle.emitter->BecomeActive(TH_THINK);
1234  }
1235 
1236  weaponParticles.Set(name.c_str(), newParticle);
1237 
1238  pkv = weaponDef->dict.MatchPrefix( "weapon_particle", pkv );
1239  }
1240 
1241  const idKeyValue *lkv = weaponDef->dict.MatchPrefix( "weapon_light", NULL );
1242  while( lkv ) {
1243  WeaponLight_t newLight;
1244  memset( &newLight, 0, sizeof( newLight ) );
1245 
1246  newLight.lightHandle = -1;
1247  newLight.active = false;
1248  newLight.startTime = 0;
1249 
1250  idStr name = lkv->GetValue();
1251  strcpy(newLight.name, name.c_str());
1252 
1253  idStr jointName = weaponDef->dict.GetString(va("%s_joint", name.c_str()));
1254  newLight.joint = animator.GetJointHandle(jointName.c_str());
1255 
1256  idStr shader = weaponDef->dict.GetString(va("%s_shader", name.c_str()));
1257  newLight.light.shader = declManager->FindMaterial( shader, false );
1258 
1259  float radius = weaponDef->dict.GetFloat(va("%s_radius", name.c_str()));
1260  newLight.light.lightRadius[0] = newLight.light.lightRadius[1] = newLight.light.lightRadius[2] = radius;
1261  newLight.light.pointLight = true;
1262  newLight.light.noShadows = true;
1263 
1264  newLight.light.allowLightInViewID = owner->entityNumber+1;
1265 
1266  weaponLights.Set(name.c_str(), newLight);
1267 
1268  lkv = weaponDef->dict.MatchPrefix( "weapon_light", lkv );
1269  }
1270  }
1271 #endif
1272 }
1273 
1274 /***********************************************************************
1275 
1276  GUIs
1277 
1278 ***********************************************************************/
1279 
1280 /*
1281 ================
1282 idWeapon::Icon
1283 ================
1284 */
1285 const char *idWeapon::Icon( void ) const {
1286  return icon;
1287 }
1288 
1289 /*
1290 ================
1291 idWeapon::UpdateGUI
1292 ================
1293 */
1294 void idWeapon::UpdateGUI( void ) {
1295  if ( !renderEntity.gui[ 0 ] ) {
1296  return;
1297  }
1298 
1299  if ( status == WP_HOLSTERED ) {
1300  return;
1301  }
1302 
1303  if ( owner->weaponGone ) {
1304  // dropping weapons was implemented wierd, so we have to not update the gui when it happens or we'll get a negative ammo count
1305  return;
1306  }
1307 
1309  // if updating the hud for a followed client
1311  idPlayer *p = static_cast< idPlayer * >( gameLocal.entities[ gameLocal.localClientNum ] );
1312  if ( !p->spectating || p->spectator != owner->entityNumber ) {
1313  return;
1314  }
1315  } else {
1316  return;
1317  }
1318  }
1319 
1320  int inclip = AmmoInClip();
1321  int ammoamount = AmmoAvailable();
1322 
1323  if ( ammoamount < 0 ) {
1324  // show infinite ammo
1325  renderEntity.gui[ 0 ]->SetStateString( "player_ammo", "" );
1326  } else {
1327  // show remaining ammo
1328 #ifdef _D3XP
1329  renderEntity.gui[ 0 ]->SetStateString( "player_totalammo", va( "%i", ammoamount) );
1330 #else
1331  renderEntity.gui[ 0 ]->SetStateString( "player_totalammo", va( "%i", ammoamount - inclip) );
1332 #endif
1333  renderEntity.gui[ 0 ]->SetStateString( "player_ammo", ClipSize() ? va( "%i", inclip ) : "--" );
1334  renderEntity.gui[ 0 ]->SetStateString( "player_clips", ClipSize() ? va("%i", ammoamount / ClipSize()) : "--" );
1335 
1336 #ifdef _D3XP
1337  renderEntity.gui[ 0 ]->SetStateString( "player_allammo", va( "%i/%i", inclip, ammoamount ) );
1338 #else
1339  renderEntity.gui[ 0 ]->SetStateString( "player_allammo", va( "%i/%i", inclip, ammoamount - inclip ) );
1340 #endif
1341  }
1342  renderEntity.gui[ 0 ]->SetStateBool( "player_ammo_empty", ( ammoamount == 0 ) );
1343  renderEntity.gui[ 0 ]->SetStateBool( "player_clip_empty", ( inclip == 0 ) );
1344  renderEntity.gui[ 0 ]->SetStateBool( "player_clip_low", ( inclip <= lowAmmo ) );
1345 
1346 #ifdef _D3XP
1347  //Let the HUD know the total amount of ammo regardless of the ammo required value
1348  renderEntity.gui[ 0 ]->SetStateString( "player_ammo_count", va("%i", AmmoCount()));
1349 
1350  //Grabber Gui Info
1351  renderEntity.gui[ 0 ]->SetStateString( "grabber_state", va("%i", grabberState));
1352 #endif
1353 }
1354 
1355 /***********************************************************************
1356 
1357  Model and muzzleflash
1358 
1359 ***********************************************************************/
1360 
1361 /*
1362 ================
1363 idWeapon::UpdateFlashPosition
1364 ================
1365 */
1367  // the flash has an explicit joint for locating it
1369 
1370  // if the desired point is inside or very close to a wall, back it up until it is clear
1373  trace_t tr;
1374  gameLocal.clip.TracePoint( tr, start, end, MASK_SHOT_RENDERMODEL, owner );
1375  // be at least 8 units away from a solid
1376  muzzleFlash.origin = tr.endpos - playerViewAxis[0] * 8;
1377 
1378  // put the world muzzle flash on the end of the joint, no matter what
1380 }
1381 
1382 /*
1383 ================
1384 idWeapon::MuzzleFlashLight
1385 ================
1386 */
1388 
1389  if ( !lightOn && ( !g_muzzleFlash.GetBool() || !muzzleFlash.lightRadius[0] ) ) {
1390  return;
1391  }
1392 
1393  if ( flashJointView == INVALID_JOINT ) {
1394  return;
1395  }
1396 
1398 
1399  // these will be different each fire
1402 
1405 
1406  // the light will be removed at this time
1408 
1409  if ( muzzleFlashHandle != -1 ) {
1412  } else {
1415  }
1416 }
1417 
1418 /*
1419 ================
1420 idWeapon::UpdateSkin
1421 ================
1422 */
1423 bool idWeapon::UpdateSkin( void ) {
1424  const function_t *func;
1425 
1426  if ( !isLinked ) {
1427  return false;
1428  }
1429 
1430  func = scriptObject.GetFunction( "UpdateSkin" );
1431  if ( !func ) {
1432  common->Warning( "Can't find function 'UpdateSkin' in object '%s'", scriptObject.GetTypeName() );
1433  return false;
1434  }
1435 
1436  // use the frameCommandThread since it's safe to use outside of framecommands
1437  gameLocal.frameCommandThread->CallFunction( this, func, true );
1439 
1440  return true;
1441 }
1442 
1443 /*
1444 ================
1445 idWeapon::SetModel
1446 ================
1447 */
1448 void idWeapon::SetModel( const char *modelname ) {
1449  assert( modelname );
1450 
1451  if ( modelDefHandle >= 0 ) {
1453  }
1454 
1455  renderEntity.hModel = animator.SetModel( modelname );
1456  if ( renderEntity.hModel ) {
1459  } else {
1462  renderEntity.numJoints = 0;
1464  }
1465 
1466  // hide the model until an animation is played
1467  Hide();
1468 }
1469 
1470 /*
1471 ================
1472 idWeapon::GetGlobalJointTransform
1473 
1474 This returns the offset and axis of a weapon bone in world space, suitable for attaching models or lights
1475 ================
1476 */
1477 bool idWeapon::GetGlobalJointTransform( bool viewModel, const jointHandle_t jointHandle, idVec3 &offset, idMat3 &axis ) {
1478  if ( viewModel ) {
1479  // view model
1480  if ( animator.GetJointTransform( jointHandle, gameLocal.time, offset, axis ) ) {
1481  offset = offset * viewWeaponAxis + viewWeaponOrigin;
1482  axis = axis * viewWeaponAxis;
1483  return true;
1484  }
1485  } else {
1486  // world model
1487  if ( worldModel.GetEntity() && worldModel.GetEntity()->GetAnimator()->GetJointTransform( jointHandle, gameLocal.time, offset, axis ) ) {
1488  offset = worldModel.GetEntity()->GetPhysics()->GetOrigin() + offset * worldModel.GetEntity()->GetPhysics()->GetAxis();
1489  axis = axis * worldModel.GetEntity()->GetPhysics()->GetAxis();
1490  return true;
1491  }
1492  }
1493  offset = viewWeaponOrigin;
1494  axis = viewWeaponAxis;
1495  return false;
1496 }
1497 
1498 /*
1499 ================
1500 idWeapon::SetPushVelocity
1501 ================
1502 */
1503 void idWeapon::SetPushVelocity( const idVec3 &pushVelocity ) {
1504  this->pushVelocity = pushVelocity;
1505 }
1506 
1507 
1508 /***********************************************************************
1509 
1510  State control/player interface
1511 
1512 ***********************************************************************/
1513 
1514 /*
1515 ================
1516 idWeapon::Think
1517 ================
1518 */
1519 void idWeapon::Think( void ) {
1520  // do nothing because the present is called from the player through PresentWeapon
1521 }
1522 
1523 /*
1524 ================
1525 idWeapon::Raise
1526 ================
1527 */
1528 void idWeapon::Raise( void ) {
1529  if ( isLinked ) {
1530  WEAPON_RAISEWEAPON = true;
1531  }
1532 }
1533 
1534 /*
1535 ================
1536 idWeapon::PutAway
1537 ================
1538 */
1539 void idWeapon::PutAway( void ) {
1540  hasBloodSplat = false;
1541  if ( isLinked ) {
1542  WEAPON_LOWERWEAPON = true;
1543  }
1544 }
1545 
1546 /*
1547 ================
1548 idWeapon::Reload
1549 NOTE: this is only for impulse-triggered reload, auto reload is scripted
1550 ================
1551 */
1552 void idWeapon::Reload( void ) {
1553  if ( isLinked ) {
1554  WEAPON_RELOAD = true;
1555  }
1556 }
1557 
1558 /*
1559 ================
1560 idWeapon::LowerWeapon
1561 ================
1562 */
1564  if ( !hide ) {
1565  hideStart = 0.0f;
1567  if ( gameLocal.time - hideStartTime < hideTime ) {
1569  } else {
1571  }
1572  hide = true;
1573  }
1574 }
1575 
1576 /*
1577 ================
1578 idWeapon::RaiseWeapon
1579 ================
1580 */
1582  Show();
1583 
1584  if ( hide ) {
1586  hideEnd = 0.0f;
1587  if ( gameLocal.time - hideStartTime < hideTime ) {
1589  } else {
1591  }
1592  hide = false;
1593  }
1594 }
1595 
1596 /*
1597 ================
1598 idWeapon::HideWeapon
1599 ================
1600 */
1601 void idWeapon::HideWeapon( void ) {
1602  Hide();
1603  if ( worldModel.GetEntity() ) {
1604  worldModel.GetEntity()->Hide();
1605  }
1606  muzzleFlashEnd = 0;
1607 }
1608 
1609 /*
1610 ================
1611 idWeapon::ShowWeapon
1612 ================
1613 */
1614 void idWeapon::ShowWeapon( void ) {
1615  Show();
1616  if ( worldModel.GetEntity() ) {
1617  worldModel.GetEntity()->Show();
1618  }
1619  if ( lightOn ) {
1620  MuzzleFlashLight();
1621  }
1622 }
1623 
1624 /*
1625 ================
1626 idWeapon::HideWorldModel
1627 ================
1628 */
1630  if ( worldModel.GetEntity() ) {
1631  worldModel.GetEntity()->Hide();
1632  }
1633 }
1634 
1635 /*
1636 ================
1637 idWeapon::ShowWorldModel
1638 ================
1639 */
1641  if ( worldModel.GetEntity() ) {
1642  worldModel.GetEntity()->Show();
1643  }
1644 }
1645 
1646 /*
1647 ================
1648 idWeapon::OwnerDied
1649 ================
1650 */
1651 void idWeapon::OwnerDied( void ) {
1652  if ( isLinked ) {
1653  SetState( "OwnerDied", 0 );
1654  thread->Execute();
1655 
1656 #ifdef _D3XP
1657  // Update the grabber effects
1658  if ( grabberState != -1 ) {
1659  grabber.Update( owner, hide );
1660  }
1661 #endif
1662  }
1663 
1664  Hide();
1665  if ( worldModel.GetEntity() ) {
1666  worldModel.GetEntity()->Hide();
1667  }
1668 
1669  // don't clear the weapon immediately since the owner might have killed himself by firing the weapon
1670  // within the current stack frame
1671  PostEventMS( &EV_Weapon_Clear, 0 );
1672 }
1673 
1674 /*
1675 ================
1676 idWeapon::BeginAttack
1677 ================
1678 */
1679 void idWeapon::BeginAttack( void ) {
1680  if ( status != WP_OUTOFAMMO ) {
1682  }
1683 
1684  if ( !isLinked ) {
1685  return;
1686  }
1687 
1688  if ( !WEAPON_ATTACK ) {
1689  if ( sndHum && grabberState == -1 ) { // _D3XP :: don't stop grabber hum
1690  StopSound( SND_CHANNEL_BODY, false );
1691  }
1692  }
1693  WEAPON_ATTACK = true;
1694 }
1695 
1696 /*
1697 ================
1698 idWeapon::EndAttack
1699 ================
1700 */
1701 void idWeapon::EndAttack( void ) {
1702  if ( !WEAPON_ATTACK.IsLinked() ) {
1703  return;
1704  }
1705  if ( WEAPON_ATTACK ) {
1706  WEAPON_ATTACK = false;
1707  if ( sndHum && grabberState == -1 ) { // _D3XP :: don't stop grabber hum
1709  }
1710  }
1711 }
1712 
1713 /*
1714 ================
1715 idWeapon::isReady
1716 ================
1717 */
1718 bool idWeapon::IsReady( void ) const {
1719  return !hide && !IsHidden() && ( ( status == WP_RELOAD ) || ( status == WP_READY ) || ( status == WP_OUTOFAMMO ) );
1720 }
1721 
1722 /*
1723 ================
1724 idWeapon::IsReloading
1725 ================
1726 */
1727 bool idWeapon::IsReloading( void ) const {
1728  return ( status == WP_RELOAD );
1729 }
1730 
1731 /*
1732 ================
1733 idWeapon::IsHolstered
1734 ================
1735 */
1736 bool idWeapon::IsHolstered( void ) const {
1737  return ( status == WP_HOLSTERED );
1738 }
1739 
1740 /*
1741 ================
1742 idWeapon::ShowCrosshair
1743 ================
1744 */
1745 bool idWeapon::ShowCrosshair( void ) const {
1746  return !( state == idStr( WP_RISING ) || state == idStr( WP_LOWERING ) || state == idStr( WP_HOLSTERED ) );
1747 }
1748 
1749 /*
1750 =====================
1751 idWeapon::CanDrop
1752 =====================
1753 */
1754 bool idWeapon::CanDrop( void ) const {
1755  if ( !weaponDef || !worldModel.GetEntity() ) {
1756  return false;
1757  }
1758  const char *classname = weaponDef->dict.GetString( "def_dropItem" );
1759  if ( !classname[ 0 ] ) {
1760  return false;
1761  }
1762  return true;
1763 }
1764 
1765 /*
1766 ================
1767 idWeapon::WeaponStolen
1768 ================
1769 */
1772  if ( projectileEnt ) {
1773  if ( isLinked ) {
1774  SetState( "WeaponStolen", 0 );
1775  thread->Execute();
1776  }
1777  projectileEnt = NULL;
1778  }
1779 
1780  // set to holstered so we can switch weapons right away
1781  status = WP_HOLSTERED;
1782 
1783  HideWeapon();
1784 }
1785 
1786 /*
1787 =====================
1788 idWeapon::DropItem
1789 =====================
1790 */
1791 idEntity * idWeapon::DropItem( const idVec3 &velocity, int activateDelay, int removeDelay, bool died ) {
1792  if ( !weaponDef || !worldModel.GetEntity() ) {
1793  return NULL;
1794  }
1795  if ( !allowDrop ) {
1796  return NULL;
1797  }
1798  const char *classname = weaponDef->dict.GetString( "def_dropItem" );
1799  if ( !classname[0] ) {
1800  return NULL;
1801  }
1802  StopSound( SND_CHANNEL_BODY, true );
1803  StopSound( SND_CHANNEL_BODY3, true );
1804 
1805  return idMoveableItem::DropItem( classname, worldModel.GetEntity()->GetPhysics()->GetOrigin(), worldModel.GetEntity()->GetPhysics()->GetAxis(), velocity, activateDelay, removeDelay );
1806 }
1807 
1808 /***********************************************************************
1809 
1810  Script state management
1811 
1812 ***********************************************************************/
1813 
1814 /*
1815 =====================
1816 idWeapon::SetState
1817 =====================
1818 */
1819 void idWeapon::SetState( const char *statename, int blendFrames ) {
1820  const function_t *func;
1821 
1822  if ( !isLinked ) {
1823  return;
1824  }
1825 
1826  func = scriptObject.GetFunction( statename );
1827  if ( !func ) {
1828  assert( 0 );
1829  gameLocal.Error( "Can't find function '%s' in object '%s'", statename, scriptObject.GetTypeName() );
1830  }
1831 
1832  thread->CallFunction( this, func, true );
1833  state = statename;
1834 
1835  animBlendFrames = blendFrames;
1836  if ( g_debugWeapon.GetBool() ) {
1837  gameLocal.Printf( "%d: weapon state : %s\n", gameLocal.time, statename );
1838  }
1839 
1840  idealState = "";
1841 }
1842 
1843 
1844 /***********************************************************************
1845 
1846  Particles/Effects
1847 
1848 ***********************************************************************/
1849 
1850 /*
1851 ================
1852 idWeapon::UpdateNozzelFx
1853 ================
1854 */
1856  if ( !nozzleFx ) {
1857  return;
1858  }
1859 
1860  //
1861  // shader parms
1862  //
1863  int la = gameLocal.time - lastAttack + 1;
1864  float s = 1.0f;
1865  float l = 0.0f;
1866  if ( la < nozzleFxFade ) {
1867  s = ((float)la / nozzleFxFade);
1868  l = 1.0f - s;
1869  }
1870  renderEntity.shaderParms[5] = s;
1871  renderEntity.shaderParms[6] = l;
1872 
1873  if ( ventLightJointView == INVALID_JOINT ) {
1874  return;
1875  }
1876 
1877  //
1878  // vent light
1879  //
1880  if ( nozzleGlowHandle == -1 ) {
1881  memset(&nozzleGlow, 0, sizeof(nozzleGlow));
1882  if ( owner ) {
1884  }
1885  nozzleGlow.pointLight = true;
1886  nozzleGlow.noShadows = true;
1895  }
1896 
1898 
1903 }
1904 
1905 
1906 /*
1907 ================
1908 idWeapon::BloodSplat
1909 ================
1910 */
1912  float s, c;
1913  idMat3 localAxis, axistemp;
1914  idVec3 localOrigin, normal;
1915 
1916  if ( hasBloodSplat ) {
1917  return true;
1918  }
1919 
1920  hasBloodSplat = true;
1921 
1922  if ( modelDefHandle < 0 ) {
1923  return false;
1924  }
1925 
1926  if ( !GetGlobalJointTransform( true, ejectJointView, localOrigin, localAxis ) ) {
1927  return false;
1928  }
1929 
1930  localOrigin[0] += gameLocal.random.RandomFloat() * -10.0f;
1931  localOrigin[1] += gameLocal.random.RandomFloat() * 1.0f;
1932  localOrigin[2] += gameLocal.random.RandomFloat() * -2.0f;
1933 
1935  normal.Normalize();
1936 
1938 
1939  localAxis[2] = -normal;
1940  localAxis[2].NormalVectors( axistemp[0], axistemp[1] );
1941  localAxis[0] = axistemp[ 0 ] * c + axistemp[ 1 ] * -s;
1942  localAxis[1] = axistemp[ 0 ] * -s + axistemp[ 1 ] * -c;
1943 
1944  localAxis[0] *= 1.0f / size;
1945  localAxis[1] *= 1.0f / size;
1946 
1947  idPlane localPlane[2];
1948 
1949  localPlane[0] = localAxis[0];
1950  localPlane[0][3] = -(localOrigin * localAxis[0]) + 0.5f;
1951 
1952  localPlane[1] = localAxis[1];
1953  localPlane[1][3] = -(localOrigin * localAxis[1]) + 0.5f;
1954 
1955  const idMaterial *mtr = declManager->FindMaterial( "textures/decals/duffysplatgun" );
1956 
1957  gameRenderWorld->ProjectOverlay( modelDefHandle, localPlane, mtr );
1958 
1959  return true;
1960 }
1961 
1962 
1963 /***********************************************************************
1964 
1965  Visual presentation
1966 
1967 ***********************************************************************/
1968 
1969 /*
1970 ================
1971 idWeapon::MuzzleRise
1972 
1973 The machinegun and chaingun will incrementally back up as they are being fired
1974 ================
1975 */
1976 void idWeapon::MuzzleRise( idVec3 &origin, idMat3 &axis ) {
1977  int time;
1978  float amount;
1979  idAngles ang;
1980  idVec3 offset;
1981 
1982  time = kick_endtime - gameLocal.time;
1983  if ( time <= 0 ) {
1984  return;
1985  }
1986 
1987  if ( muzzle_kick_maxtime <= 0 ) {
1988  return;
1989  }
1990 
1991  if ( time > muzzle_kick_maxtime ) {
1992  time = muzzle_kick_maxtime;
1993  }
1994 
1995  amount = ( float )time / ( float )muzzle_kick_maxtime;
1996  ang = muzzle_kick_angles * amount;
1997  offset = muzzle_kick_offset * amount;
1998 
1999  origin = origin - axis * offset;
2000  axis = ang.ToMat3() * axis;
2001 }
2002 
2003 /*
2004 ================
2005 idWeapon::ConstructScriptObject
2006 
2007 Called during idEntity::Spawn. Calls the constructor on the script object.
2008 Can be overridden by subclasses when a thread doesn't need to be allocated.
2009 ================
2010 */
2012  const function_t *constructor;
2013 
2014  thread->EndThread();
2015 
2016  // call script object's constructor
2017  constructor = scriptObject.GetConstructor();
2018  if ( !constructor ) {
2019  gameLocal.Error( "Missing constructor on '%s' for weapon", scriptObject.GetTypeName() );
2020  }
2021 
2022  // init the script object's data
2024  thread->CallFunction( this, constructor, true );
2025  thread->Execute();
2026 
2027  return thread;
2028 }
2029 
2030 /*
2031 ================
2032 idWeapon::DeconstructScriptObject
2033 
2034 Called during idEntity::~idEntity. Calls the destructor on the script object.
2035 Can be overridden by subclasses when a thread doesn't need to be allocated.
2036 Not called during idGameLocal::MapShutdown.
2037 ================
2038 */
2040  const function_t *destructor;
2041 
2042  if ( !thread ) {
2043  return;
2044  }
2045 
2046  // don't bother calling the script object's destructor on map shutdown
2047  if ( gameLocal.GameState() == GAMESTATE_SHUTDOWN ) {
2048  return;
2049  }
2050 
2051  thread->EndThread();
2052 
2053  // call script object's destructor
2054  destructor = scriptObject.GetDestructor();
2055  if ( destructor ) {
2056  // start a thread that will run immediately and end
2057  thread->CallFunction( this, destructor, true );
2058  thread->Execute();
2059  thread->EndThread();
2060  }
2061 
2062  // clear out the object's memory
2064 }
2065 
2066 /*
2067 ================
2068 idWeapon::UpdateScript
2069 ================
2070 */
2072  int count;
2073 
2074  if ( !isLinked ) {
2075  return;
2076  }
2077 
2078  // only update the script on new frames
2079  if ( !gameLocal.isNewFrame ) {
2080  return;
2081  }
2082 
2083  if ( idealState.Length() ) {
2085  }
2086 
2087  // update script state, which may call Event_LaunchProjectiles, among other things
2088  count = 10;
2089  while( ( thread->Execute() || idealState.Length() ) && count-- ) {
2090  // happens for weapons with no clip (like grenades)
2091  if ( idealState.Length() ) {
2093  }
2094  }
2095 
2096  WEAPON_RELOAD = false;
2097 }
2098 
2099 /*
2100 ================
2101 idWeapon::AlertMonsters
2102 ================
2103 */
2105  trace_t tr;
2106  idEntity *ent;
2108 
2110  if ( g_debugWeapon.GetBool() ) {
2113  }
2114 
2115  if ( tr.fraction < 1.0f ) {
2116  ent = gameLocal.GetTraceEntity( tr );
2117  if ( ent->IsType( idAI::Type ) ) {
2118  static_cast<idAI *>( ent )->TouchedByFlashlight( owner );
2119  } else if ( ent->IsType( idTrigger::Type ) ) {
2120  ent->Signal( SIG_TOUCH );
2121  ent->ProcessEvent( &EV_Touch, owner, &tr );
2122  }
2123  }
2124 
2125  // jitter the trace to try to catch cases where a trace down the center doesn't hit the monster
2126  end += muzzleFlash.axis * muzzleFlash.right * idMath::Sin16( MS2SEC( gameLocal.time ) * 31.34f );
2127  end += muzzleFlash.axis * muzzleFlash.up * idMath::Sin16( MS2SEC( gameLocal.time ) * 12.17f );
2129  if ( g_debugWeapon.GetBool() ) {
2132  }
2133 
2134  if ( tr.fraction < 1.0f ) {
2135  ent = gameLocal.GetTraceEntity( tr );
2136  if ( ent->IsType( idAI::Type ) ) {
2137  static_cast<idAI *>( ent )->TouchedByFlashlight( owner );
2138  } else if ( ent->IsType( idTrigger::Type ) ) {
2139  ent->Signal( SIG_TOUCH );
2140  ent->ProcessEvent( &EV_Touch, owner, &tr );
2141  }
2142  }
2143 }
2144 
2145 /*
2146 ================
2147 idWeapon::PresentWeapon
2148 ================
2149 */
2150 void idWeapon::PresentWeapon( bool showViewModel ) {
2153 
2154  // calculate weapon position based on player movement bobbing
2156 
2157  // hide offset is for dropping the gun when approaching a GUI or NPC
2158  // This is simpler to manage than doing the weapon put-away animation
2159  if ( gameLocal.time - hideStartTime < hideTime ) {
2160  float frac = ( float )( gameLocal.time - hideStartTime ) / ( float )hideTime;
2161  if ( hideStart < hideEnd ) {
2162  frac = 1.0f - frac;
2163  frac = 1.0f - frac * frac;
2164  } else {
2165  frac = frac * frac;
2166  }
2167  hideOffset = hideStart + ( hideEnd - hideStart ) * frac;
2168  } else {
2169  hideOffset = hideEnd;
2170  if ( hide && disabled ) {
2171  Hide();
2172  }
2173  }
2175 
2176  // kick up based on repeat firing
2177  MuzzleRise( viewWeaponOrigin, viewWeaponAxis );
2178 
2179  // set the physics position and orientation
2181  GetPhysics()->SetAxis( viewWeaponAxis );
2182  UpdateVisuals();
2183 
2184  // update the weapon script
2185  UpdateScript();
2186 
2187  UpdateGUI();
2188 
2189  // update animation
2190  UpdateAnimation();
2191 
2192  // only show the surface in player view
2194 
2195  // crunch the depth range so it never pokes into walls this breaks the machine gun gui
2197 
2198  // present the model
2199  if ( showViewModel ) {
2200  Present();
2201  } else {
2202  FreeModelDef();
2203  }
2204 
2206  // deal with the third-person visible world model
2207  // don't show shadows of the world model in first person
2210  } else {
2212  worldModel.GetEntity()->GetRenderEntity()->suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + owner->entityNumber;
2213  }
2214  }
2215 
2216  if ( nozzleFx ) {
2217  UpdateNozzleFx();
2218  }
2219 
2220  // muzzle smoke
2221  if ( showViewModel && !disabled && weaponSmoke && ( weaponSmokeStartTime != 0 ) ) {
2222  // use the barrel joint if available
2223 
2224 #ifdef _D3XP
2225  if(smokeJointView != INVALID_JOINT) {
2226  GetGlobalJointTransform( true, smokeJointView, muzzleOrigin, muzzleAxis );
2227  } else if (barrelJointView != INVALID_JOINT) {
2229 #else
2230  if ( barrelJointView ) {
2232 #endif
2233  } else {
2234  // default to going straight out the view
2237  }
2238  // spit out a particle
2241  }
2242  }
2243 
2244  if ( showViewModel && strikeSmoke && strikeSmokeStartTime != 0 ) {
2245  // spit out a particle
2248  }
2249  }
2250 
2251 #ifdef _D3XP
2252  if ( showViewModel && !hide ) {
2253 
2254  for( int i = 0; i < weaponParticles.Num(); i++ ) {
2255  WeaponParticle_t* part = weaponParticles.GetIndex(i);
2256 
2257  if(part->active) {
2258  if(part->smoke) {
2259  if(part->joint != INVALID_JOINT) {
2260  GetGlobalJointTransform( true, part->joint, muzzleOrigin, muzzleAxis );
2261  } else {
2262  // default to going straight out the view
2265  }
2266  if ( !gameLocal.smokeParticles->EmitSmoke( part->particle, part->startTime, gameLocal.random.RandomFloat(), muzzleOrigin, muzzleAxis, timeGroup /*_D3XP*/ ) ) {
2267  part->active = false; // all done
2268  part->startTime = 0;
2269  }
2270  } else {
2271  //Manually update the position of the emitter so it follows the weapon
2272  renderEntity_t* rendEnt = part->emitter->GetRenderEntity();
2273  GetGlobalJointTransform( true, part->joint, rendEnt->origin, rendEnt->axis );
2274 
2275  if ( part->emitter->GetModelDefHandle() != -1 ) {
2276  gameRenderWorld->UpdateEntityDef( part->emitter->GetModelDefHandle(), rendEnt );
2277  }
2278  }
2279  }
2280  }
2281 
2282  for(int i = 0; i < weaponLights.Num(); i++) {
2283  WeaponLight_t* light = weaponLights.GetIndex(i);
2284 
2285  if(light->active) {
2286 
2287  GetGlobalJointTransform( true, light->joint, light->light.origin, light->light.axis );
2288  if ( ( light->lightHandle != -1 ) ) {
2289  gameRenderWorld->UpdateLightDef( light->lightHandle, &light->light );
2290  } else {
2291  light->lightHandle = gameRenderWorld->AddLightDef( &light->light );
2292  }
2293  }
2294  }
2295  }
2296 
2297  // Update the grabber effects
2298  if ( grabberState != -1 ) {
2299  grabberState = grabber.Update( owner, hide );
2300  }
2301 #endif
2302 
2303  // remove the muzzle flash light when it's done
2304  if ( ( !lightOn && ( gameLocal.time >= muzzleFlashEnd ) ) || IsHidden() ) {
2305  if ( muzzleFlashHandle != -1 ) {
2307  muzzleFlashHandle = -1;
2308  }
2309  if ( worldMuzzleFlashHandle != -1 ) {
2312  }
2313  }
2314 
2315  // update the muzzle flash light, so it moves with the gun
2316  if ( muzzleFlashHandle != -1 ) {
2320 
2321  // wake up monsters with the flashlight
2322  if ( !gameLocal.isMultiplayer && lightOn && !owner->fl.notarget ) {
2323  AlertMonsters();
2324  }
2325  }
2326 
2327  // update the gui light
2330 
2331  if ( ( guiLightHandle != -1 ) ) {
2333  } else {
2335  }
2336  }
2337 
2338  if ( status != WP_READY && sndHum ) {
2339  StopSound( SND_CHANNEL_BODY, false );
2340  }
2341 
2342  UpdateSound();
2343 }
2344 
2345 /*
2346 ================
2347 idWeapon::EnterCinematic
2348 ================
2349 */
2351  StopSound( SND_CHANNEL_ANY, false );
2352 
2353  if ( isLinked ) {
2354  SetState( "EnterCinematic", 0 );
2355  thread->Execute();
2356 
2357  WEAPON_ATTACK = false;
2358  WEAPON_RELOAD = false;
2359  WEAPON_NETRELOAD = false;
2360  WEAPON_NETENDRELOAD = false;
2361  WEAPON_NETFIRING = false;
2362  WEAPON_RAISEWEAPON = false;
2363  WEAPON_LOWERWEAPON = false;
2364 
2365 #ifdef _D3XP
2366  grabber.Update( this->GetOwner(), true );
2367 #endif
2368  }
2369 
2370  disabled = true;
2371 
2372  LowerWeapon();
2373 }
2374 
2375 /*
2376 ================
2377 idWeapon::ExitCinematic
2378 ================
2379 */
2381  disabled = false;
2382 
2383  if ( isLinked ) {
2384  SetState( "ExitCinematic", 0 );
2385  thread->Execute();
2386  }
2387 
2388  RaiseWeapon();
2389 }
2390 
2391 /*
2392 ================
2393 idWeapon::NetCatchup
2394 ================
2395 */
2396 void idWeapon::NetCatchup( void ) {
2397  if ( isLinked ) {
2398  SetState( "NetCatchup", 0 );
2399  thread->Execute();
2400  }
2401 }
2402 
2403 /*
2404 ================
2405 idWeapon::GetZoomFov
2406 ================
2407 */
2409  return zoomFov;
2410 }
2411 
2412 /*
2413 ================
2414 idWeapon::GetWeaponAngleOffsets
2415 ================
2416 */
2417 void idWeapon::GetWeaponAngleOffsets( int *average, float *scale, float *max ) {
2418  *average = weaponAngleOffsetAverages;
2419  *scale = weaponAngleOffsetScale;
2420  *max = weaponAngleOffsetMax;
2421 }
2422 
2423 /*
2424 ================
2425 idWeapon::GetWeaponTimeOffsets
2426 ================
2427 */
2428 void idWeapon::GetWeaponTimeOffsets( float *time, float *scale ) {
2429  *time = weaponOffsetTime;
2430  *scale = weaponOffsetScale;
2431 }
2432 
2433 
2434 /***********************************************************************
2435 
2436  Ammo
2437 
2438 ***********************************************************************/
2439 
2440 /*
2441 ================
2442 idWeapon::GetAmmoNumForName
2443 ================
2444 */
2445 ammo_t idWeapon::GetAmmoNumForName( const char *ammoname ) {
2446  int num;
2447  const idDict *ammoDict;
2448 
2449  assert( ammoname );
2450 
2451  ammoDict = gameLocal.FindEntityDefDict( "ammo_types", false );
2452  if ( !ammoDict ) {
2453  gameLocal.Error( "Could not find entity definition for 'ammo_types'\n" );
2454  }
2455 
2456  if ( !ammoname[ 0 ] ) {
2457  return 0;
2458  }
2459 
2460  if ( !ammoDict->GetInt( ammoname, "-1", num ) ) {
2461 #ifdef _D3XP
2462  //Lets look in a game specific ammo type definition for the weapon
2463  idStr gamedir;
2464  int i;
2465  for ( i = 0; i < 2; i++ ) {
2466  if ( i == 0 ) {
2467  gamedir = cvarSystem->GetCVarString( "fs_game_base" );
2468  } else if ( i == 1 ) {
2469  gamedir = cvarSystem->GetCVarString( "fs_game" );
2470  }
2471  if ( gamedir.Length() > 0 ) {
2472  ammoDict = gameLocal.FindEntityDefDict( va("ammo_types_%s", gamedir.c_str()), false );
2473  if ( ammoDict ) {
2474  if ( ammoDict->GetInt( ammoname, "-1", num ) ) {
2475  break;
2476  }
2477  }
2478  }
2479  }
2480  if ( i == 2 ) {
2481  gameLocal.Error( "Unknown ammo type '%s'", ammoname );
2482  }
2483 #endif
2484  }
2485 
2486  if ( ( num < 0 ) || ( num >= AMMO_NUMTYPES ) ) {
2487  gameLocal.Error( "Ammo type '%s' value out of range. Maximum ammo types is %d.\n", ammoname, AMMO_NUMTYPES );
2488  }
2489 
2490  return ( ammo_t )num;
2491 }
2492 
2493 /*
2494 ================
2495 idWeapon::GetAmmoNameForNum
2496 ================
2497 */
2498 const char *idWeapon::GetAmmoNameForNum( ammo_t ammonum ) {
2499  int i;
2500  int num;
2501  const idDict *ammoDict;
2502  const idKeyValue *kv;
2503  char text[ 32 ];
2504 
2505  ammoDict = gameLocal.FindEntityDefDict( "ammo_types", false );
2506  if ( !ammoDict ) {
2507  gameLocal.Error( "Could not find entity definition for 'ammo_types'\n" );
2508  }
2509 
2510  sprintf( text, "%d", ammonum );
2511 
2512  num = ammoDict->GetNumKeyVals();
2513  for( i = 0; i < num; i++ ) {
2514  kv = ammoDict->GetKeyVal( i );
2515  if ( kv->GetValue() == text ) {
2516  return kv->GetKey();
2517  }
2518  }
2519 
2520 #ifdef _D3XP
2521  // Look in the game specific ammo types
2522  idStr gamedir;
2523  for ( i = 0; i < 2; i++ ) {
2524  if ( i == 0 ) {
2525  gamedir = cvarSystem->GetCVarString( "fs_game_base" );
2526  } else if ( i == 1 ) {
2527  gamedir = cvarSystem->GetCVarString( "fs_game" );
2528  }
2529  if ( gamedir.Length() > 0 ) {
2530  ammoDict = gameLocal.FindEntityDefDict( va("ammo_types_%s", gamedir.c_str()), false );
2531  if ( ammoDict ) {
2532  num = ammoDict->GetNumKeyVals();
2533  for( i = 0; i < num; i++ ) {
2534  kv = ammoDict->GetKeyVal( i );
2535  if ( kv->GetValue() == text ) {
2536  return kv->GetKey();
2537  }
2538  }
2539  }
2540  }
2541  }
2542 #endif
2543 
2544  return NULL;
2545 }
2546 
2547 /*
2548 ================
2549 idWeapon::GetAmmoPickupNameForNum
2550 ================
2551 */
2553  int i;
2554  int num;
2555  const idDict *ammoDict;
2556  const idKeyValue *kv;
2557 
2558  ammoDict = gameLocal.FindEntityDefDict( "ammo_names", false );
2559  if ( !ammoDict ) {
2560  gameLocal.Error( "Could not find entity definition for 'ammo_names'\n" );
2561  }
2562 
2563  const char *name = GetAmmoNameForNum( ammonum );
2564 
2565  if ( name && *name ) {
2566  num = ammoDict->GetNumKeyVals();
2567  for( i = 0; i < num; i++ ) {
2568  kv = ammoDict->GetKeyVal( i );
2569  if ( idStr::Icmp( kv->GetKey(), name) == 0 ) {
2570  return kv->GetValue();
2571  }
2572  }
2573  }
2574 
2575  return "";
2576 }
2577 
2578 /*
2579 ================
2580 idWeapon::AmmoAvailable
2581 ================
2582 */
2583 int idWeapon::AmmoAvailable( void ) const {
2584  if ( owner ) {
2586  } else {
2587  return 0;
2588  }
2589 }
2590 
2591 /*
2592 ================
2593 idWeapon::AmmoInClip
2594 ================
2595 */
2596 int idWeapon::AmmoInClip( void ) const {
2597  return ammoClip;
2598 }
2599 
2600 /*
2601 ================
2602 idWeapon::ResetAmmoClip
2603 ================
2604 */
2606  ammoClip = -1;
2607 }
2608 
2609 /*
2610 ================
2611 idWeapon::GetAmmoType
2612 ================
2613 */
2615  return ammoType;
2616 }
2617 
2618 /*
2619 ================
2620 idWeapon::ClipSize
2621 ================
2622 */
2623 int idWeapon::ClipSize( void ) const {
2624  return clipSize;
2625 }
2626 
2627 /*
2628 ================
2629 idWeapon::LowAmmo
2630 ================
2631 */
2632 int idWeapon::LowAmmo() const {
2633  return lowAmmo;
2634 }
2635 
2636 /*
2637 ================
2638 idWeapon::AmmoRequired
2639 ================
2640 */
2641 int idWeapon::AmmoRequired( void ) const {
2642  return ammoRequired;
2643 }
2644 
2645 #ifdef _D3XP
2646 /*
2647 ================
2648 idWeapon::GetGrabberState
2649 
2650 Returns the current grabberState
2651 ================
2652 */
2653 int idWeapon::GetGrabberState() const {
2654 
2655  return grabberState;
2656 }
2657 
2658 /*
2659 ================
2660 idWeapon::AmmoCount
2661 
2662 Returns the total number of rounds regardless of the required ammo
2663 ================
2664 */
2665 int idWeapon::AmmoCount() const {
2666 
2667  if ( owner ) {
2668  return owner->inventory.HasAmmo( ammoType, 1 );
2669  } else {
2670  return 0;
2671  }
2672 }
2673 #endif
2674 
2675 /*
2676 ================
2677 idWeapon::WriteToSnapshot
2678 ================
2679 */
2682  msg.WriteBits( worldModel.GetSpawnId(), 32 );
2683  msg.WriteBits( lightOn, 1 );
2684  msg.WriteBits( isFiring ? 1 : 0, 1 );
2685 }
2686 
2687 /*
2688 ================
2689 idWeapon::ReadFromSnapshot
2690 ================
2691 */
2694  worldModel.SetSpawnId( msg.ReadBits( 32 ) );
2695  bool snapLight = msg.ReadBits( 1 ) != 0;
2696  isFiring = msg.ReadBits( 1 ) != 0;
2697 
2698  // WEAPON_NETFIRING is only turned on for other clients we're predicting. not for local client
2700 
2701  // immediately go to the firing state so we don't skip fire animations
2702  if ( !WEAPON_NETFIRING && isFiring ) {
2703  idealState = "Fire";
2704  }
2705 
2706  // immediately switch back to idle
2707  if ( WEAPON_NETFIRING && !isFiring ) {
2708  idealState = "Idle";
2709  }
2710 
2712  }
2713 
2714  if ( snapLight != lightOn ) {
2715  Reload();
2716  }
2717 }
2718 
2719 /*
2720 ================
2721 idWeapon::ClientReceiveEvent
2722 ================
2723 */
2724 bool idWeapon::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
2725 
2726  switch( event ) {
2727  case EVENT_RELOAD: {
2728  if ( gameLocal.time - time < 1000 ) {
2729  if ( WEAPON_NETRELOAD.IsLinked() ) {
2730  WEAPON_NETRELOAD = true;
2731  WEAPON_NETENDRELOAD = false;
2732  }
2733  }
2734  return true;
2735  }
2736  case EVENT_ENDRELOAD: {
2737  if ( WEAPON_NETENDRELOAD.IsLinked() ) {
2738  WEAPON_NETENDRELOAD = true;
2739  }
2740  return true;
2741  }
2742  case EVENT_CHANGESKIN: {
2744  renderEntity.customSkin = ( index != -1 ) ? static_cast<const idDeclSkin *>( declManager->DeclByIndex( DECL_SKIN, index ) ) : NULL;
2745  UpdateVisuals();
2746  if ( worldModel.GetEntity() ) {
2748  }
2749  return true;
2750  }
2751  default: {
2752  return idEntity::ClientReceiveEvent( event, time, msg );
2753  }
2754  }
2755  return false;
2756 }
2757 
2758 /***********************************************************************
2759 
2760  Script events
2761 
2762 ***********************************************************************/
2763 
2764 /*
2765 ===============
2766 idWeapon::Event_Clear
2767 ===============
2768 */
2770  Clear();
2771 }
2772 
2773 /*
2774 ===============
2775 idWeapon::Event_GetOwner
2776 ===============
2777 */
2780 }
2781 
2782 /*
2783 ===============
2784 idWeapon::Event_WeaponState
2785 ===============
2786 */
2787 void idWeapon::Event_WeaponState( const char *statename, int blendFrames ) {
2788  const function_t *func;
2789 
2790  func = scriptObject.GetFunction( statename );
2791  if ( !func ) {
2792  assert( 0 );
2793  gameLocal.Error( "Can't find function '%s' in object '%s'", statename, scriptObject.GetTypeName() );
2794  }
2795 
2796  idealState = statename;
2797 
2798  if ( !idealState.Icmp( "Fire" ) ) {
2799  isFiring = true;
2800  } else {
2801  isFiring = false;
2802  }
2803 
2804  animBlendFrames = blendFrames;
2806 }
2807 
2808 /*
2809 ===============
2810 idWeapon::Event_WeaponReady
2811 ===============
2812 */
2814  status = WP_READY;
2815  if ( isLinked ) {
2816  WEAPON_RAISEWEAPON = false;
2817  }
2818  if ( sndHum ) {
2820  }
2821 
2822 }
2823 
2824 /*
2825 ===============
2826 idWeapon::Event_WeaponOutOfAmmo
2827 ===============
2828 */
2830  status = WP_OUTOFAMMO;
2831  if ( isLinked ) {
2832  WEAPON_RAISEWEAPON = false;
2833  }
2834 }
2835 
2836 /*
2837 ===============
2838 idWeapon::Event_WeaponReloading
2839 ===============
2840 */
2842  status = WP_RELOAD;
2843 }
2844 
2845 /*
2846 ===============
2847 idWeapon::Event_WeaponHolstered
2848 ===============
2849 */
2851  status = WP_HOLSTERED;
2852  if ( isLinked ) {
2853  WEAPON_LOWERWEAPON = false;
2854  }
2855 }
2856 
2857 /*
2858 ===============
2859 idWeapon::Event_WeaponRising
2860 ===============
2861 */
2863  status = WP_RISING;
2864  if ( isLinked ) {
2865  WEAPON_LOWERWEAPON = false;
2866  }
2868 }
2869 
2870 /*
2871 ===============
2872 idWeapon::Event_WeaponLowering
2873 ===============
2874 */
2876  status = WP_LOWERING;
2877  if ( isLinked ) {
2878  WEAPON_RAISEWEAPON = false;
2879  }
2881 }
2882 
2883 /*
2884 ===============
2885 idWeapon::Event_UseAmmo
2886 ===============
2887 */
2888 void idWeapon::Event_UseAmmo( int amount ) {
2889  if ( gameLocal.isClient ) {
2890  return;
2891  }
2892 
2893  owner->inventory.UseAmmo( ammoType, ( powerAmmo ) ? amount : ( amount * ammoRequired ) );
2894  if ( clipSize && ammoRequired ) {
2895  ammoClip -= powerAmmo ? amount : ( amount * ammoRequired );
2896  if ( ammoClip < 0 ) {
2897  ammoClip = 0;
2898  }
2899  }
2900 }
2901 
2902 /*
2903 ===============
2904 idWeapon::Event_AddToClip
2905 ===============
2906 */
2907 void idWeapon::Event_AddToClip( int amount ) {
2908  int ammoAvail;
2909 
2910  if ( gameLocal.isClient ) {
2911  return;
2912  }
2913 
2914 #ifdef _D3XP
2915  int oldAmmo = ammoClip;
2916  ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired ) + AmmoInClip();
2917 #endif
2918 
2919  ammoClip += amount;
2920  if ( ammoClip > clipSize ) {
2921  ammoClip = clipSize;
2922  }
2923 
2924 #ifdef _D3XP
2925 #else
2926  ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
2927 #endif
2928 
2929  if ( ammoClip > ammoAvail ) {
2930  ammoClip = ammoAvail;
2931  }
2932 
2933 #ifdef _D3XP
2934  // for shared ammo we need to use the ammo when it is moved into the clip
2935  int usedAmmo = ammoClip - oldAmmo;
2936  owner->inventory.UseAmmo(ammoType, usedAmmo);
2937 #endif
2938 }
2939 
2940 /*
2941 ===============
2942 idWeapon::Event_AmmoInClip
2943 ===============
2944 */
2946  int ammo = AmmoInClip();
2947  idThread::ReturnFloat( ammo );
2948 }
2949 
2950 /*
2951 ===============
2952 idWeapon::Event_AmmoAvailable
2953 ===============
2954 */
2956 #ifdef _D3XP
2957  int ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
2958  ammoAvail += AmmoInClip();
2959 #else
2960  int ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
2961 #endif
2962 
2963  idThread::ReturnFloat( ammoAvail );
2964 }
2965 
2966 /*
2967 ===============
2968 idWeapon::Event_TotalAmmoCount
2969 ===============
2970 */
2972  int ammoAvail = owner->inventory.HasAmmo( ammoType, 1 );
2973  idThread::ReturnFloat( ammoAvail );
2974 }
2975 
2976 /*
2977 ===============
2978 idWeapon::Event_ClipSize
2979 ===============
2980 */
2983 }
2984 
2985 /*
2986 ===============
2987 idWeapon::Event_AutoReload
2988 ===============
2989 */
2991  assert( owner );
2992  if ( gameLocal.isClient ) {
2993  idThread::ReturnFloat( 0.0f );
2994  return;
2995  }
2997 }
2998 
2999 /*
3000 ===============
3001 idWeapon::Event_NetReload
3002 ===============
3003 */
3005  assert( owner );
3006  if ( gameLocal.isServer ) {
3007  ServerSendEvent( EVENT_RELOAD, NULL, false, -1 );
3008  }
3009 }
3010 
3011 /*
3012 ===============
3013 idWeapon::Event_NetEndReload
3014 ===============
3015 */
3017  assert( owner );
3018  if ( gameLocal.isServer ) {
3019  ServerSendEvent( EVENT_ENDRELOAD, NULL, false, -1 );
3020  }
3021 }
3022 
3023 /*
3024 ===============
3025 idWeapon::Event_PlayAnim
3026 ===============
3027 */
3028 void idWeapon::Event_PlayAnim( int channel, const char *animname ) {
3029  int anim;
3030 
3031  anim = animator.GetAnim( animname );
3032  if ( !anim ) {
3033  gameLocal.Warning( "missing '%s' animation on '%s' (%s)", animname, name.c_str(), GetEntityDefName() );
3035  animDoneTime = 0;
3036  } else {
3037  if ( !( owner && owner->GetInfluenceLevel() ) ) {
3038  Show();
3039  }
3040  animator.PlayAnim( channel, anim, gameLocal.time, FRAME2MS( animBlendFrames ) );
3041  animDoneTime = animator.CurrentAnim( channel )->GetEndTime();
3042  if ( worldModel.GetEntity() ) {
3043  anim = worldModel.GetEntity()->GetAnimator()->GetAnim( animname );
3044  if ( anim ) {
3046  }
3047  }
3048  }
3049  animBlendFrames = 0;
3050  idThread::ReturnInt( 0 );
3051 }
3052 
3053 /*
3054 ===============
3055 idWeapon::Event_PlayCycle
3056 ===============
3057 */
3058 void idWeapon::Event_PlayCycle( int channel, const char *animname ) {
3059  int anim;
3060 
3061  anim = animator.GetAnim( animname );
3062  if ( !anim ) {
3063  gameLocal.Warning( "missing '%s' animation on '%s' (%s)", animname, name.c_str(), GetEntityDefName() );
3065  animDoneTime = 0;
3066  } else {
3067  if ( !( owner && owner->GetInfluenceLevel() ) ) {
3068  Show();
3069  }
3070  animator.CycleAnim( channel, anim, gameLocal.time, FRAME2MS( animBlendFrames ) );
3071  animDoneTime = animator.CurrentAnim( channel )->GetEndTime();
3072  if ( worldModel.GetEntity() ) {
3073  anim = worldModel.GetEntity()->GetAnimator()->GetAnim( animname );
3075  }
3076  }
3077  animBlendFrames = 0;
3078  idThread::ReturnInt( 0 );
3079 }
3080 
3081 /*
3082 ===============
3083 idWeapon::Event_AnimDone
3084 ===============
3085 */
3086 void idWeapon::Event_AnimDone( int channel, int blendFrames ) {
3087  if ( animDoneTime - FRAME2MS( blendFrames ) <= gameLocal.time ) {
3088  idThread::ReturnInt( true );
3089  } else {
3090  idThread::ReturnInt( false );
3091  }
3092 }
3093 
3094 /*
3095 ===============
3096 idWeapon::Event_SetBlendFrames
3097 ===============
3098 */
3099 void idWeapon::Event_SetBlendFrames( int channel, int blendFrames ) {
3100  animBlendFrames = blendFrames;
3101 }
3102 
3103 /*
3104 ===============
3105 idWeapon::Event_GetBlendFrames
3106 ===============
3107 */
3108 void idWeapon::Event_GetBlendFrames( int channel ) {
3110 }
3111 
3112 /*
3113 ================
3114 idWeapon::Event_Next
3115 ================
3116 */
3117 void idWeapon::Event_Next( void ) {
3118  // change to another weapon if possible
3119  owner->NextBestWeapon();
3120 }
3121 
3122 /*
3123 ================
3124 idWeapon::Event_SetSkin
3125 ================
3126 */
3127 void idWeapon::Event_SetSkin( const char *skinname ) {
3128  const idDeclSkin *skinDecl;
3129 
3130  if ( !skinname || !skinname[ 0 ] ) {
3131  skinDecl = NULL;
3132  } else {
3133  skinDecl = declManager->FindSkin( skinname );
3134  }
3135 
3136  renderEntity.customSkin = skinDecl;
3137  UpdateVisuals();
3138 
3139  if ( worldModel.GetEntity() ) {
3140  worldModel.GetEntity()->SetSkin( skinDecl );
3141  }
3142 
3143  if ( gameLocal.isServer ) {
3144  idBitMsg msg;
3145  byte msgBuf[MAX_EVENT_PARAM_SIZE];
3146 
3147  msg.Init( msgBuf, sizeof( msgBuf ) );
3148  msg.WriteLong( ( skinDecl != NULL ) ? gameLocal.ServerRemapDecl( -1, DECL_SKIN, skinDecl->Index() ) : -1 );
3149  ServerSendEvent( EVENT_CHANGESKIN, &msg, false, -1 );
3150  }
3151 }
3152 
3153 /*
3154 ================
3155 idWeapon::Event_Flashlight
3156 ================
3157 */
3158 void idWeapon::Event_Flashlight( int enable ) {
3159  if ( enable ) {
3160  lightOn = true;
3161  MuzzleFlashLight();
3162  } else {
3163  lightOn = false;
3164  muzzleFlashEnd = 0;
3165  }
3166 }
3167 
3168 /*
3169 ================
3170 idWeapon::Event_GetLightParm
3171 ================
3172 */
3173 void idWeapon::Event_GetLightParm( int parmnum ) {
3174  if ( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) ) {
3175  gameLocal.Error( "shader parm index (%d) out of range", parmnum );
3176  }
3177 
3179 }
3180 
3181 /*
3182 ================
3183 idWeapon::Event_SetLightParm
3184 ================
3185 */
3186 void idWeapon::Event_SetLightParm( int parmnum, float value ) {
3187  if ( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) ) {
3188  gameLocal.Error( "shader parm index (%d) out of range", parmnum );
3189  }
3190 
3191  muzzleFlash.shaderParms[ parmnum ] = value;
3192  worldMuzzleFlash.shaderParms[ parmnum ] = value;
3193  UpdateVisuals();
3194 }
3195 
3196 /*
3197 ================
3198 idWeapon::Event_SetLightParms
3199 ================
3200 */
3201 void idWeapon::Event_SetLightParms( float parm0, float parm1, float parm2, float parm3 ) {
3206 
3211 
3212  UpdateVisuals();
3213 }
3214 
3215 #ifdef _D3XP
3216 /*
3217 ================
3218 idWeapon::Event_Grabber
3219 ================
3220 */
3221 void idWeapon::Event_Grabber( int enable ) {
3222  if ( enable ) {
3223  grabberState = 0;
3224  } else {
3225  grabberState = -1;
3226  }
3227 }
3228 
3229 /*
3230 ================
3231 idWeapon::Event_GrabberHasTarget
3232 ================
3233 */
3234 void idWeapon::Event_GrabberHasTarget() {
3235  idThread::ReturnInt( grabberState );
3236 }
3237 
3238 /*
3239 ================
3240 idWeapon::Event_GrabberSetGrabDistance
3241 ================
3242 */
3243 void idWeapon::Event_GrabberSetGrabDistance( float dist ) {
3244 
3245  grabber.SetDragDistance( dist );
3246 }
3247 #endif
3248 
3249 /*
3250 ================
3251 idWeapon::Event_CreateProjectile
3252 ================
3253 */
3255  if ( !gameLocal.isClient ) {
3256  projectileEnt = NULL;
3258  if ( projectileEnt ) {
3259  projectileEnt->SetOrigin( GetPhysics()->GetOrigin() );
3260  projectileEnt->Bind( owner, false );
3261  projectileEnt->Hide();
3262  }
3264  } else {
3266  }
3267 }
3268 
3269 /*
3270 ================
3271 idWeapon::Event_LaunchProjectiles
3272 ================
3273 */
3274 void idWeapon::Event_LaunchProjectiles( int num_projectiles, float spread, float fuseOffset, float launchPower, float dmgPower ) {
3275  idProjectile *proj;
3276  idEntity *ent;
3277  int i;
3278  idVec3 dir;
3279  float ang;
3280  float spin;
3281  float distance;
3282  trace_t tr;
3283  idVec3 start;
3284  idVec3 muzzle_pos;
3285  idBounds ownerBounds, projBounds;
3286 
3287  if ( IsHidden() ) {
3288  return;
3289  }
3290 
3291  if ( !projectileDict.GetNumKeyVals() ) {
3292  const char *classname = weaponDef->dict.GetString( "classname" );
3293  gameLocal.Warning( "No projectile defined on '%s'", classname );
3294  return;
3295  }
3296 
3297  // avoid all ammo considerations on an MP client
3298  if ( !gameLocal.isClient ) {
3299 
3300 #ifdef _D3XP
3301 
3302  int ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
3303  if ( ( clipSize != 0 ) && ( ammoClip <= 0 ) ) {
3304  return;
3305  }
3306 
3307 #else
3308  // check if we're out of ammo or the clip is empty
3309  int ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
3310  if ( !ammoAvail || ( ( clipSize != 0 ) && ( ammoClip <= 0 ) ) ) {
3311  return;
3312  }
3313 #endif
3314  // if this is a power ammo weapon ( currently only the bfg ) then make sure
3315  // we only fire as much power as available in each clip
3316  if ( powerAmmo ) {
3317  // power comes in as a float from zero to max
3318  // if we use this on more than the bfg will need to define the max
3319  // in the .def as opposed to just in the script so proper calcs
3320  // can be done here.
3321  dmgPower = ( int )dmgPower + 1;
3322  if ( dmgPower > ammoClip ) {
3323  dmgPower = ammoClip;
3324  }
3325  }
3326 
3327 #ifdef _D3XP
3328  if(clipSize == 0) {
3329  //Weapons with a clip size of 0 launch strait from inventory without moving to a clip
3330 #endif
3331  //In D3XP we used the ammo when the ammo was moved into the clip so we don't want to
3332  //use it now.
3333  owner->inventory.UseAmmo( ammoType, ( powerAmmo ) ? dmgPower : ammoRequired );
3334 
3335 #ifdef _D3XP
3336  }
3337 #endif
3338 
3339  if ( clipSize && ammoRequired ) {
3340 #ifdef _D3XP
3341  ammoClip -= powerAmmo ? dmgPower : ammoRequired;
3342 #else
3343  ammoClip -= powerAmmo ? dmgPower : 1;
3344 #endif
3345  }
3346 
3347  }
3348 
3349  if ( !silent_fire ) {
3350  // wake up nearby monsters
3351  gameLocal.AlertAI( owner );
3352  }
3353 
3354  // set the shader parm to the time of last projectile firing,
3355  // which the gun material shaders can reference for single shot barrel glows, etc
3358 
3359  if ( worldModel.GetEntity() ) {
3362  }
3363 
3364  // calculate the muzzle position
3365  if ( barrelJointView != INVALID_JOINT && projectileDict.GetBool( "launchFromBarrel" ) ) {
3366  // there is an explicit joint for the muzzle
3368  } else {
3369  // go straight out of the view
3372  }
3373 
3374  // add some to the kick time, incrementally moving repeat firing weapons back
3377  }
3381  }
3382 
3383  if ( gameLocal.isClient ) {
3384 
3385  // predict instant hit projectiles
3386  if ( projectileDict.GetBool( "net_instanthit" ) ) {
3387  float spreadRad = DEG2RAD( spread );
3388  muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
3389  for( i = 0; i < num_projectiles; i++ ) {
3390  ang = idMath::Sin( spreadRad * gameLocal.random.RandomFloat() );
3391  spin = (float)DEG2RAD( 360.0f ) * gameLocal.random.RandomFloat();
3392  dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( ang * idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( ang * idMath::Cos( spin ) );
3393  dir.Normalize();
3394  gameLocal.clip.Translation( tr, muzzle_pos, muzzle_pos + dir * 4096.0f, NULL, mat3_identity, MASK_SHOT_RENDERMODEL, owner );
3395  if ( tr.fraction < 1.0f ) {
3397  }
3398  }
3399  }
3400 
3401  } else {
3402 
3403  ownerBounds = owner->GetPhysics()->GetAbsBounds();
3404 
3405  owner->AddProjectilesFired( num_projectiles );
3406 
3407  float spreadRad = DEG2RAD( spread );
3408  for( i = 0; i < num_projectiles; i++ ) {
3409  ang = idMath::Sin( spreadRad * gameLocal.random.RandomFloat() );
3410  spin = (float)DEG2RAD( 360.0f ) * gameLocal.random.RandomFloat();
3411  dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( ang * idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( ang * idMath::Cos( spin ) );
3412  dir.Normalize();
3413 
3414  if ( projectileEnt ) {
3415  ent = projectileEnt;
3416  ent->Show();
3417  ent->Unbind();
3418  projectileEnt = NULL;
3419  } else {
3420  gameLocal.SpawnEntityDef( projectileDict, &ent, false );
3421  }
3422 
3423  if ( !ent || !ent->IsType( idProjectile::Type ) ) {
3424  const char *projectileName = weaponDef->dict.GetString( "def_projectile" );
3425  gameLocal.Error( "'%s' is not an idProjectile", projectileName );
3426  }
3427 
3428  if ( projectileDict.GetBool( "net_instanthit" ) ) {
3429  // don't synchronize this on top of the already predicted effect
3430  ent->fl.networkSync = false;
3431  }
3432 
3433  proj = static_cast<idProjectile *>(ent);
3434  proj->Create( owner, muzzleOrigin, dir );
3435 
3436  projBounds = proj->GetPhysics()->GetBounds().Rotate( proj->GetPhysics()->GetAxis() );
3437 
3438  // make sure the projectile starts inside the bounding box of the owner
3439  if ( i == 0 ) {
3440  muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
3441  if ( ( ownerBounds - projBounds).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
3442  start = muzzle_pos + distance * playerViewAxis[0];
3443  } else {
3444  start = ownerBounds.GetCenter();
3445  }
3446  gameLocal.clip.Translation( tr, start, muzzle_pos, proj->GetPhysics()->GetClipModel(), proj->GetPhysics()->GetClipModel()->GetAxis(), MASK_SHOT_RENDERMODEL, owner );
3447  muzzle_pos = tr.endpos;
3448  }
3449 
3450  proj->Launch( muzzle_pos, dir, pushVelocity, fuseOffset, launchPower, dmgPower );
3451  }
3452 
3453  // toss the brass
3454 #ifdef _D3XP
3455  if(brassDelay >= 0)
3456 #endif
3457  PostEventMS( &EV_Weapon_EjectBrass, brassDelay );
3458  }
3459 
3460  // add the light for the muzzleflash
3461  if ( !lightOn ) {
3462  MuzzleFlashLight();
3463  }
3464 
3466 
3467  // reset muzzle smoke
3469 }
3470 
3471 #ifdef _D3XP
3472 /*
3473 ================
3474 idWeapon::Event_LaunchProjectilesEllipse
3475 ================
3476 */
3477 void idWeapon::Event_LaunchProjectilesEllipse( int num_projectiles, float spreada, float spreadb, float fuseOffset, float power ) {
3478  idProjectile *proj;
3479  idEntity *ent;
3480  int i;
3481  idVec3 dir;
3482  float anga, angb;
3483  float spin;
3484  float distance;
3485  trace_t tr;
3486  idVec3 start;
3487  idVec3 muzzle_pos;
3488  idBounds ownerBounds, projBounds;
3489 
3490  if ( IsHidden() ) {
3491  return;
3492  }
3493 
3494  if ( !projectileDict.GetNumKeyVals() ) {
3495  const char *classname = weaponDef->dict.GetString( "classname" );
3496  gameLocal.Warning( "No projectile defined on '%s'", classname );
3497  return;
3498  }
3499 
3500  // avoid all ammo considerations on a client
3501  if ( !gameLocal.isClient ) {
3502 
3503  int ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
3504  if ( ( clipSize != 0 ) && ( ammoClip <= 0 ) ) {
3505  return;
3506  }
3507 
3508  if( clipSize == 0 ) {
3509  //Weapons with a clip size of 0 launch strait from inventory without moving to a clip
3511  }
3512 
3513  if ( clipSize && ammoRequired ) {
3515  }
3516 
3517  if ( !silent_fire ) {
3518  // wake up nearby monsters
3519  gameLocal.AlertAI( owner );
3520  }
3521 
3522  }
3523 
3524  // set the shader parm to the time of last projectile firing,
3525  // which the gun material shaders can reference for single shot barrel glows, etc
3528 
3529  if ( worldModel.GetEntity() ) {
3532  }
3533 
3534  // calculate the muzzle position
3535  if ( barrelJointView != INVALID_JOINT && projectileDict.GetBool( "launchFromBarrel" ) ) {
3536  // there is an explicit joint for the muzzle
3538  } else {
3539  // go straight out of the view
3542  }
3543 
3544  // add some to the kick time, incrementally moving repeat firing weapons back
3545  if ( kick_endtime < gameLocal.time ) {
3547  }
3551  }
3552 
3553  if ( !gameLocal.isClient ) {
3554  ownerBounds = owner->GetPhysics()->GetAbsBounds();
3555 
3556  owner->AddProjectilesFired( num_projectiles );
3557 
3558  float spreadRadA = DEG2RAD( spreada );
3559  float spreadRadB = DEG2RAD( spreadb );
3560 
3561  for( i = 0; i < num_projectiles; i++ ) {
3562  //Ellipse Form
3563  spin = (float)DEG2RAD( 360.0f ) * gameLocal.random.RandomFloat();
3564  anga = idMath::Sin(spreadRadA * gameLocal.random.RandomFloat());
3565  angb = idMath::Sin(spreadRadB * gameLocal.random.RandomFloat());
3566  dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( angb*idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( anga*idMath::Cos( spin ) );
3567  dir.Normalize();
3568 
3570  if ( !ent || !ent->IsType( idProjectile::Type ) ) {
3571  const char *projectileName = weaponDef->dict.GetString( "def_projectile" );
3572  gameLocal.Error( "'%s' is not an idProjectile", projectileName );
3573  }
3574 
3575  proj = static_cast<idProjectile *>(ent);
3576  proj->Create( owner, muzzleOrigin, dir );
3577 
3578  projBounds = proj->GetPhysics()->GetBounds().Rotate( proj->GetPhysics()->GetAxis() );
3579 
3580  // make sure the projectile starts inside the bounding box of the owner
3581  if ( i == 0 ) {
3582  muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
3583  if ( ( ownerBounds - projBounds).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
3584  start = muzzle_pos + distance * playerViewAxis[0];
3585  }
3586  else {
3587  start = ownerBounds.GetCenter();
3588  }
3589  gameLocal.clip.Translation( tr, start, muzzle_pos, proj->GetPhysics()->GetClipModel(), proj->GetPhysics()->GetClipModel()->GetAxis(), MASK_SHOT_RENDERMODEL, owner );
3590  muzzle_pos = tr.endpos;
3591  }
3592 
3593  proj->Launch( muzzle_pos, dir, pushVelocity, fuseOffset, power );
3594  }
3595 
3596  // toss the brass
3597  if( brassDelay >= 0 ) {
3598  PostEventMS( &EV_Weapon_EjectBrass, brassDelay );
3599  }
3600  }
3601 
3602  // add the light for the muzzleflash
3603  if ( !lightOn ) {
3604  MuzzleFlashLight();
3605  }
3606 
3608 
3609  // reset muzzle smoke
3611 
3612 }
3613 
3618 void idWeapon::Event_LaunchPowerup( const char* powerup, float duration, int useAmmo ) {
3619 
3620  if ( IsHidden() ) {
3621  return;
3622  }
3623 
3624  // check if we're out of ammo
3625  if(useAmmo) {
3626  int ammoAvail = owner->inventory.HasAmmo( ammoType, ammoRequired );
3627  if ( !ammoAvail ) {
3628  return;
3629  }
3631  }
3632 
3633  // set the shader parm to the time of last projectile firing,
3634  // which the gun material shaders can reference for single shot barrel glows, etc
3637 
3638  if ( worldModel.GetEntity() ) {
3641  }
3642 
3643  // add the light for the muzzleflash
3644  if ( !lightOn ) {
3645  MuzzleFlashLight();
3646  }
3647 
3648  owner->Give(powerup, va("%f", duration));
3649 
3650 
3651 }
3652 
3653 void idWeapon::Event_StartWeaponSmoke() {
3654 
3655  // reset muzzle smoke
3657 }
3658 
3659 void idWeapon::Event_StopWeaponSmoke() {
3660 
3661  // reset muzzle smoke
3663 }
3664 
3665 void idWeapon::Event_StartWeaponParticle( const char* name) {
3666  WeaponParticle_t* part;
3667  weaponParticles.Get(name, &part);
3668  if(part) {
3669  part->active = true;
3670  part->startTime = gameLocal.time;
3671 
3672  //Toggle the emitter
3673  if(!part->smoke) {
3674  part->emitter->Show();
3675  part->emitter->PostEventMS(&EV_Activate, 0, this);
3676  }
3677  }
3678 }
3679 
3680 void idWeapon::Event_StopWeaponParticle( const char* name) {
3681  WeaponParticle_t* part;
3682  weaponParticles.Get(name, &part);
3683  if(part) {
3684  part->active = false;
3685  part->startTime = 0;
3686 
3687  //Toggle the emitter
3688  if(!part->smoke) {
3689  part->emitter->Hide();
3690  part->emitter->PostEventMS(&EV_Activate, 0, this);
3691  }
3692  }
3693 }
3694 
3695 void idWeapon::Event_StartWeaponLight( const char* name) {
3696  WeaponLight_t* light;
3697  weaponLights.Get(name, &light);
3698  if(light) {
3699  light->active = true;
3700  light->startTime = gameLocal.time;
3701  }
3702 }
3703 
3704 void idWeapon::Event_StopWeaponLight( const char* name) {
3705  WeaponLight_t* light;
3706  weaponLights.Get(name, &light);
3707  if(light) {
3708  light->active = false;
3709  light->startTime = 0;
3710  if(light->lightHandle != -1) {
3711  gameRenderWorld->FreeLightDef( light->lightHandle );
3712  light->lightHandle = -1;
3713  }
3714  }
3715 }
3716 #endif
3717 /*
3718 =====================
3719 idWeapon::Event_Melee
3720 =====================
3721 */
3723  idEntity *ent;
3724  trace_t tr;
3725 
3726  if ( !meleeDef ) {
3727  gameLocal.Error( "No meleeDef on '%s'", weaponDef->dict.GetString( "classname" ) );
3728  }
3729 
3730  if ( !gameLocal.isClient ) {
3731  idVec3 start = playerViewOrigin;
3733  gameLocal.clip.TracePoint( tr, start, end, MASK_SHOT_RENDERMODEL, owner );
3734  if ( tr.fraction < 1.0f ) {
3735  ent = gameLocal.GetTraceEntity( tr );
3736  } else {
3737  ent = NULL;
3738  }
3739 
3740  if ( g_debugWeapon.GetBool() ) {
3741  gameRenderWorld->DebugLine( colorYellow, start, end, 100 );
3742  if ( ent ) {
3744  }
3745  }
3746 
3747  bool hit = false;
3748  const char *hitSound = meleeDef->dict.GetString( "snd_miss" );
3749 
3750  if ( ent ) {
3751 
3752  float push = meleeDef->dict.GetFloat( "push" );
3753  idVec3 impulse = -push * owner->PowerUpModifier( SPEED ) * tr.c.normal;
3754 
3755  if ( gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) && ( ent->IsType( idActor::Type ) || ent->IsType( idAFAttachment::Type) ) ) {
3756  idThread::ReturnInt( 0 );
3757  return;
3758  }
3759 
3760  ent->ApplyImpulse( this, tr.c.id, tr.c.point, impulse );
3761 
3762  // weapon stealing - do this before damaging so weapons are not dropped twice
3764  && weaponDef && weaponDef->dict.GetBool( "stealing" )
3765  && ent->IsType( idPlayer::Type )
3766  && !owner->PowerUpActive( BERSERK )
3767  && ( (gameLocal.gameType != GAME_TDM ) || gameLocal.serverInfo.GetBool( "si_teamDamage" ) || ( owner->team != static_cast< idPlayer * >( ent )->team ) )
3768  ) {
3769 
3770 #ifdef CTF /* Code is formed oddly for easy merge */
3771 
3773  { /* Do nothing ... */ }
3774  else
3775 #endif
3776  owner->StealWeapon( static_cast< idPlayer * >( ent ) );
3777  }
3778 
3779  if ( ent->fl.takedamage ) {
3780  idVec3 kickDir, globalKickDir;
3781  meleeDef->dict.GetVector( "kickDir", "0 0 0", kickDir );
3782  globalKickDir = muzzleAxis * kickDir;
3783 #ifdef _D3XP
3784  //Adjust the melee powerup modifier for the invulnerability boss fight
3785  float mod = owner->PowerUpModifier( MELEE_DAMAGE );
3786  if(!strcmp(ent->GetEntityDefName(), "monster_hunter_invul")) {
3787  //Only do a quater of the damage mod
3788  mod *= 0.25f;
3789  }
3790  ent->Damage( owner, owner, globalKickDir, meleeDefName, mod, tr.c.id );
3791 #else
3792  ent->Damage( owner, owner, globalKickDir, meleeDefName, owner->PowerUpModifier( MELEE_DAMAGE ), tr.c.id );
3793 #endif
3794  hit = true;
3795  }
3796 
3797  if ( weaponDef->dict.GetBool( "impact_damage_effect" ) ) {
3798 
3799  if ( ent->spawnArgs.GetBool( "bleed" ) ) {
3800 
3801  hitSound = meleeDef->dict.GetString( owner->PowerUpActive( BERSERK ) ? "snd_hit_berserk" : "snd_hit" );
3802 
3803  ent->AddDamageEffect( tr, impulse, meleeDef->dict.GetString( "classname" ) );
3804 
3805  } else {
3806 
3807  int type = tr.c.material->GetSurfaceType();
3808  if ( type == SURFTYPE_NONE ) {
3809  type = GetDefaultSurfaceType();
3810  }
3811 
3812  const char *materialType = gameLocal.sufaceTypeNames[ type ];
3813 
3814  // start impact sound based on material type
3815  hitSound = meleeDef->dict.GetString( va( "snd_%s", materialType ) );
3816  if ( *hitSound == '\0' ) {
3817  hitSound = meleeDef->dict.GetString( "snd_metal" );
3818  }
3819 
3820  if ( gameLocal.time > nextStrikeFx ) {
3821  const char *decal;
3822  // project decal
3823  decal = weaponDef->dict.GetString( "mtr_strike" );
3824  if ( decal && *decal ) {
3825  gameLocal.ProjectDecal( tr.c.point, -tr.c.normal, 8.0f, true, 6.0, decal );
3826  }
3827  nextStrikeFx = gameLocal.time + 200;
3828  } else {
3829  hitSound = "";
3830  }
3831 
3833  strikePos = tr.c.point;
3834  strikeAxis = -tr.endAxis;
3835  }
3836  }
3837  }
3838 
3839  if ( *hitSound != '\0' ) {
3840  const idSoundShader *snd = declManager->FindSound( hitSound );
3841  StartSoundShader( snd, SND_CHANNEL_BODY2, 0, true, NULL );
3842  }
3843 
3844  idThread::ReturnInt( hit );
3846  return;
3847  }
3848 
3849  idThread::ReturnInt( 0 );
3851 }
3852 
3853 /*
3854 =====================
3855 idWeapon::Event_GetWorldModel
3856 =====================
3857 */
3860 }
3861 
3862 /*
3863 =====================
3864 idWeapon::Event_AllowDrop
3865 =====================
3866 */
3867 void idWeapon::Event_AllowDrop( int allow ) {
3868  if ( allow ) {
3869  allowDrop = true;
3870  } else {
3871  allowDrop = false;
3872  }
3873 }
3874 
3875 /*
3876 ================
3877 idWeapon::Event_EjectBrass
3878 
3879 Toss a shell model out from the breach if the bone is present
3880 ================
3881 */
3883  if ( !g_showBrass.GetBool() || !owner->CanShowWeaponViewmodel() ) {
3884  return;
3885  }
3886 
3888  return;
3889  }
3890 
3891  if ( gameLocal.isClient ) {
3892  return;
3893  }
3894 
3895  idMat3 axis;
3896  idVec3 origin, linear_velocity, angular_velocity;
3897  idEntity *ent;
3898 
3899  if ( !GetGlobalJointTransform( true, ejectJointView, origin, axis ) ) {
3900  return;
3901  }
3902 
3903  gameLocal.SpawnEntityDef( brassDict, &ent, false );
3904  if ( !ent || !ent->IsType( idDebris::Type ) ) {
3905  gameLocal.Error( "'%s' is not an idDebris", weaponDef ? weaponDef->dict.GetString( "def_ejectBrass" ) : "def_ejectBrass" );
3906  }
3907  idDebris *debris = static_cast<idDebris *>(ent);
3908  debris->Create( owner, origin, axis );
3909  debris->Launch();
3910 
3911  linear_velocity = 40 * ( playerViewAxis[0] + playerViewAxis[1] + playerViewAxis[2] );
3912  angular_velocity.Set( 10 * gameLocal.random.CRandomFloat(), 10 * gameLocal.random.CRandomFloat(), 10 * gameLocal.random.CRandomFloat() );
3913 
3914  debris->GetPhysics()->SetLinearVelocity( linear_velocity );
3915  debris->GetPhysics()->SetAngularVelocity( angular_velocity );
3916 }
3917 
3918 /*
3919 ===============
3920 idWeapon::Event_IsInvisible
3921 ===============
3922 */
3924  if ( !owner ) {
3925  idThread::ReturnFloat( 0 );
3926  return;
3927  }
3929 }
3930 
3931 /*
3932 ===============
3933 idWeapon::ClientPredictionThink
3934 ===============
3935 */
3937  UpdateAnimation();
3938 }
virtual const idVec3 & GetOrigin(int id=0) const =0
jointHandle_t
Definition: Model.h:156
void Event_IsInvisible(void)
Definition: Weapon.cpp:3923
virtual ~idWeapon()
Definition: Weapon.cpp:187
idMat3 muzzleAxis
Definition: Weapon.h:237
bool disabled
Definition: Weapon.h:222
const idEventDef AI_PlayCycle("playCycle","ds", 'd')
renderEntity_t renderEntity
Definition: Entity.h:371
bool TracePoint(trace_t &results, const idVec3 &start, const idVec3 &end, int contentMask, const idEntity *passEntity)
Definition: Clip.h:333
#define strcmp
Definition: Str.h:41
idVec3 pushVelocity
Definition: Weapon.h:239
int nozzleGlowHandle
Definition: Weapon.h:332
float GetFloat(const char *key, const char *defaultString="0") const
Definition: Dict.h:248
virtual bool TrmFromModel(const char *modelName, idTraceModel &trm)=0
bool GetJointTransform(jointHandle_t jointHandle, int currenttime, idVec3 &offset, idMat3 &axis)
GLsizei const GLfloat * value
Definition: glext.h:3614
void WriteString(const char *string)
Definition: SaveGame.cpp:231
float Normalize(void)
Definition: Vector.h:646
idVec4 colorGreen
Definition: Lib.cpp:118
bool EmitSmoke(const idDeclParticle *smoke, const int startTime, const float diversity, const idVec3 &origin, const idMat3 &axis, int timeGroup)
const idDeclEntityDef * weaponDef
Definition: Weapon.h:244
int GetInt(const char *key, const char *defaultString="0") const
Definition: Dict.h:252
int berserk
Definition: Weapon.h:225
void WeaponFireFeedback(const idDict *weaponDef)
idVec3 strikePos
Definition: Weapon.h:322
void ReadSoundShader(const idSoundShader *&shader)
Definition: SaveGame.cpp:1196
jointHandle_t barrelJointWorld
Definition: Weapon.h:303
assert(prefInfo.fullscreenBtn)
void SetOwner(idPlayer *owner)
Definition: Weapon.cpp:223
virtual const idSoundShader * FindSound(const char *name, bool makeDefault=true)=0
int allowSurfaceInViewID
Definition: RenderWorld.h:113
const idDict * FindEntityDefDict(const char *name, bool makeDefault=true) const
void Event_Flashlight(int enable)
Definition: Weapon.cpp:3158
void ReadParticle(const idDeclParticle *&particle)
Definition: SaveGame.cpp:1164
void Restore(idRestoreGame *savefile)
Definition: Game_local.h:661
void EndThread(void)
const int SHADERPARM_DIVERSITY
Definition: RenderWorld.h:52
idCVarSystem * cvarSystem
Definition: CVarSystem.cpp:487
virtual void FreeLightDef(qhandle_t lightHandle)=0
void HideWeapon(void)
Definition: Weapon.cpp:1601
idMat3 mat3_identity(idVec3(1, 0, 0), idVec3(0, 1, 0), idVec3(0, 0, 1))
void Delete(const char *key)
Definition: Dict.cpp:496
virtual void SetContents(int contents, int id=-1)=0
virtual idAnimator * GetAnimator(void)
Definition: Entity.cpp:1566
void ReadMaterial(const idMaterial *&material)
Definition: SaveGame.cpp:1132
void CallFunction(const function_t *func, bool clearStack)
void WriteObject(const idClass *obj)
Definition: SaveGame.cpp:329
void Think(void)
Definition: Weapon.cpp:1519
virtual void DebugArrow(const idVec4 &color, const idVec3 &start, const idVec3 &end, int size, const int lifetime=0)=0
idVec3 GetCenter(void) const
Definition: Bounds.h:211
void Event_UseAmmo(int amount)
Definition: Weapon.cpp:2888
void ExitCinematic(void)
Definition: Weapon.cpp:2380
void Event_GetLightParm(int parmnum)
Definition: Weapon.cpp:3173
static bool ClientPredictionCollide(idEntity *soundEnt, const idDict &projectileDef, const trace_t &collision, const idVec3 &velocity, bool addDamageEffect)
idClip clip
Definition: Game_local.h:296
const idEventDef EV_Weapon_IsInvisible("isInvisible", NULL, 'f')
void Event_PlayAnim(int channel, const char *animname)
Definition: Weapon.cpp:3028
virtual void Launch(const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire=0.0f, const float launchPower=1.0f, const float dmgPower=1.0f)
Definition: Projectile.cpp:306
const idEventDef EV_Weapon_NetEndReload("netEndReload")
void Printf(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:699
bool BloodSplat(float size)
Definition: Weapon.cpp:1911
virtual void SetStateString(const char *varName, const char *value)=0
int nextStrikeFx
Definition: Weapon.h:324
struct idEntity::entityFlags_s fl
void BindToJoint(idEntity *master, const char *jointname, bool orientated)
Definition: Entity.cpp:1921
float hideEnd
Definition: Weapon.h:219
Definition: Player.h:110
void Bind(idEntity *master, bool orientated)
Definition: Entity.cpp:1896
int muzzleFlashHandle
Definition: Weapon.h:259
type * GetEntity(void) const
Definition: Game_local.h:695
const int MAX_EVENT_PARAM_SIZE
Definition: Game_local.h:132
bool SetType(const char *typeName)
void SetShaderParm(int parmnum, float value)
Definition: Entity.cpp:1067
const char * GetTypeName(void) const
idSmokeParticles * smokeParticles
Definition: Game_local.h:307
int ammoClip
Definition: Weapon.h:285
const idStr & GetKey(void) const
Definition: Dict.h:52
void Event_LaunchProjectiles(int num_projectiles, float spread, float fuseOffset, float launchPower, float dmgPower)
Definition: Weapon.cpp:3274
void RaiseWeapon(void)
Definition: Weapon.cpp:1581
const idEventDef EV_Activate("activate","e")
static void CacheWeapon(const char *weaponName)
Definition: Weapon.cpp:250
idScriptBool WEAPON_ATTACK
Definition: Weapon.h:193
const idEventDef AI_GetBlendFrames("getBlendFrames","d", 'd')
bool isNewFrame
Definition: Game_local.h:333
float weaponAngleOffsetScale
Definition: Weapon.h:340
const idEventDef EV_Light_GetLightParm("getLightParm","d", 'f')
void ManualDelete(void)
void Event_PlayCycle(int channel, const char *animname)
Definition: Weapon.cpp:3058
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:4804
idRandom random
Definition: Game_local.h:291
int Length(void) const
Definition: Str.h:702
void Event_EjectBrass(void)
Definition: Weapon.cpp:3882
void void void void void Error(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:783
void SetPushVelocity(const idVec3 &pushVelocity)
Definition: Weapon.cpp:1503
bool isMultiplayer
Definition: Game_local.h:325
idCVar g_showPlayerShadow("g_showPlayerShadow","0", CVAR_GAME|CVAR_ARCHIVE|CVAR_BOOL,"enables shadow of player model")
idScriptObject scriptObject
Definition: Entity.h:123
bool isFiring
Definition: Weapon.h:290
idAngles GetAngles(const char *key, const char *defaultString=NULL) const
Definition: Dict.h:278
weaponStatus_t status
Definition: Weapon.h:200
idAngles muzzle_kick_angles
Definition: Weapon.h:278
bool IsType(const idTypeInfo &c) const
Definition: Class.h:337
void Event_NetReload(void)
Definition: Weapon.cpp:3004
jointHandle_t ejectJointWorld
Definition: Weapon.h:304
void Set(const float x, const float y, const float z)
Definition: Vector.h:409
int GetInfluenceLevel(void)
Definition: Player.h:535
int ClientRemapDecl(declType_t type, int index)
int LowAmmo(void) const
Definition: Weapon.cpp:2632
float hideOffset
Definition: Weapon.h:220
void InitWorldModel(const idDeclEntityDef *def)
Definition: Weapon.cpp:879
const idMat3 & GetAxis(void) const
Definition: Clip.h:210
idInventory inventory
Definition: Player.h:290
int ReadLong(void) const
Definition: BitMsg.h:375
virtual void WriteToSnapshot(idBitMsgDelta &msg) const
Definition: Weapon.cpp:2680
virtual void DeconstructScriptObject(void)
Definition: Weapon.cpp:2039
int weaponAngleOffsetAverages
Definition: Weapon.h:339
float z
Definition: Vector.h:320
bool UpdateSkin(void)
Definition: Weapon.cpp:1423
const idKeyValue * MatchPrefix(const char *prefix, const idKeyValue *lastMatch=NULL) const
Definition: Dict.cpp:523
case const int
Definition: Callbacks.cpp:52
float PowerUpModifier(int type)
bool ProcessEvent(const idEventDef *ev)
Definition: Class.cpp:858
void Event_NetEndReload(void)
Definition: Weapon.cpp:3016
void PlayAnim(int channelNum, int animnum, int currenttime, int blendTime)
void WriteBits(int value, int numBits)
Definition: BitMsg.cpp:648
const idSoundShader * sndHum
Definition: Weapon.h:314
idMat3 strikeAxis
Definition: Weapon.h:323
void Event_WeaponState(const char *statename, int blendFrames)
Definition: Weapon.cpp:2787
void Event_AllowDrop(int allow)
Definition: Weapon.cpp:3867
jointHandle_t GetJointHandle(const char *name) const
bool silent_fire
Definition: Weapon.h:268
int suppressShadowInViewID
Definition: RenderWorld.h:105
jointHandle_t flashJointWorld
Definition: Weapon.h:302
jointHandle_t barrelJointView
Definition: Weapon.h:296
bool hasBloodSplat
Definition: Weapon.h:272
idScriptBool WEAPON_RELOAD
Definition: Weapon.h:194
bool isClient
Definition: Game_local.h:327
jointHandle_t ventLightJointView
Definition: Weapon.h:300
const char * GetName(void) const
Definition: DeclManager.h:140
idStr state
Definition: Weapon.h:202
Definition: Vector.h:316
void ReadJoint(jointHandle_t &value)
Definition: SaveGame.cpp:931
case const float
Definition: Callbacks.cpp:62
void ReadBool(bool &value)
Definition: SaveGame.cpp:976
bool isServer
Definition: Game_local.h:326
void WriteStaticObject(const idClass &obj)
Definition: SaveGame.cpp:348
void Event_CreateProjectile(void)
Definition: Weapon.cpp:3254
const int SHADERPARM_GREEN
Definition: RenderWorld.h:47
int team
Definition: Actor.h:115
virtual void FreeModelDef(void)
Definition: Entity.cpp:1197
float weaponOffsetTime
Definition: Weapon.h:342
bool SetSpawnId(int id)
Definition: Game_local.h:676
void Event_SetLightParm(int parmnum, float value)
Definition: Weapon.cpp:3186
virtual void SetLinearVelocity(const idVec3 &newLinearVelocity, int id=0)=0
int listenerId
Definition: Game.h:212
void Event_ClipSize(void)
Definition: Weapon.cpp:2981
idVec3 viewWeaponOrigin
Definition: Weapon.h:232
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
void EnterCinematic(void)
Definition: Weapon.cpp:2350
void Create(idEntity *owner, const idVec3 &start, const idVec3 &dir)
Definition: Projectile.cpp:218
const idEventDef EV_Weapon_WeaponHolstered("weaponHolstered")
virtual qhandle_t AddLightDef(const renderLight_t *rlight)=0
virtual const idMaterial * FindMaterial(const char *name, bool makeDefault=true)=0
GLdouble s
Definition: glext.h:2935
void Set(const char *key, const char *value)
Definition: Dict.cpp:275
virtual void ApplyImpulse(idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse)
Definition: Entity.cpp:2887
bool ShowCrosshair(void) const
Definition: Weapon.cpp:1745
jointHandle_t ejectJointView
Definition: Weapon.h:298
int ReadBits(int numBits) const
Definition: BitMsg.cpp:709
void Identity(void)
Definition: Matrix.h:591
int animDoneTime
Definition: Weapon.h:205
float x
Definition: Vector.h:318
virtual void Free(bool immediate)=0
idDict spawnArgs
Definition: Entity.h:122
static const char * GetAmmoPickupNameForNum(ammo_t ammonum)
Definition: Weapon.cpp:2552
idEntity * projectileEnt
Definition: Weapon.h:209
idUserInterfaceManager * uiManager
bool IsReloading(void) const
Definition: Weapon.cpp:1727
int i
Definition: process.py:33
GLintptr offset
Definition: glext.h:3113
idStr idealState
Definition: Weapon.h:203
contactInfo_t c
deferredEntityCallback_t callback
Definition: RenderWorld.h:96
GLuint GLuint num
Definition: glext.h:5390
void WriteVec3(const idVec3 &vec)
Definition: SaveGame.cpp:253
const idEventDef EV_Weapon_AmmoInClip("ammoInClip", NULL, 'f')
idAngles & Zero(void)
Definition: Angles.h:126
const idEventDef EV_Weapon_CreateProjectile("createProjectile", NULL, 'e')
const idEventDef EV_Weapon_AddToClip("addToClip","d")
int muzzle_kick_maxtime
Definition: Weapon.h:277
virtual void SetModel(const char *modelname)
Definition: Entity.cpp:1150
void GetWeaponTimeOffsets(float *time, float *scale)
Definition: Weapon.cpp:2428
int Icmp(const char *text) const
Definition: Str.h:667
const idEventDef EV_Weapon_AutoReload("autoReload", NULL, 'f')
void SetName(const char *name)
Definition: Entity.cpp:854
virtual bool ClientReceiveEvent(int event, int time, const idBitMsg &msg)
Definition: Weapon.cpp:2724
const idDeclEntityDef * meleeDef
Definition: Weapon.h:245
bool Give(const char *statname, const char *value)
void WriteSoundShader(const idSoundShader *shader)
Definition: SaveGame.cpp:445
void WriteMaterial(const idMaterial *material)
Definition: SaveGame.cpp:380
const int SHADERPARM_ALPHA
Definition: RenderWorld.h:49
renderLight_t guiLight
Definition: Weapon.h:254
#define EVENT(event, function)
Definition: Class.h:53
virtual void SetStateBool(const char *varName, const bool value)=0
void Init(byte *data, int length)
Definition: BitMsg.h:155
const int MAX_ENTITY_SHADER_PARMS
Definition: Material.h:258
float fraction
virtual void ClientPredictionThink(void)
Definition: Weapon.cpp:3936
idVec3 endpos
void WriteJoint(const jointHandle_t value)
Definition: SaveGame.cpp:177
int kick_endtime
Definition: Weapon.h:275
idVec3 playerViewOrigin
Definition: Weapon.h:228
void ClearObject(void)
int animBlendFrames
Definition: Weapon.h:204
list l
Definition: prepare.py:17
void WriteBool(const bool value)
Definition: SaveGame.cpp:222
virtual idUserInterface * FindGui(const char *qpath, bool autoLoad=false, bool needUnique=false, bool forceUnique=false)=0
idVec4 colorRed
Definition: Lib.cpp:117
void SetState(const char *statename, int blendFrames)
Definition: Weapon.cpp:1819
int suppressLightInViewID
Definition: RenderWorld.h:164
float shaderParms[MAX_ENTITY_SHADER_PARMS]
Definition: RenderWorld.h:201
void CalculateViewWeaponPos(idVec3 &origin, idMat3 &axis)
void Event_Next(void)
Definition: Weapon.cpp:3117
idAnimator animator
Definition: Entity.h:534
void ManualControl(void)
bool IsHidden(void) const
Definition: Entity.cpp:1217
static float Sin16(float a)
Definition: Math.h:314
const int SHADERPARM_TIMESCALE
Definition: RenderWorld.h:50
idEntity * SpawnEntityType(const idTypeInfo &classdef, const idDict *args=NULL, bool bIsClientReadSnapshot=false)
const idMaterial * nozzleGlowShader
Definition: Weapon.h:335
const idEventDef EV_Weapon_EjectBrass("ejectBrass")
void void void Warning(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:735
const idEventDef EV_Weapon_WeaponOutOfAmmo("weaponOutOfAmmo")
virtual const idBounds & GetBounds(int id=-1) const =0
const idEventDef EV_Weapon_WeaponRising("weaponRising")
int suppressShadowInLightID
Definition: RenderWorld.h:109
bool StartSoundShader(const idSoundShader *shader, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length)
Definition: Entity.cpp:1656
int nozzleFxFade
Definition: Weapon.h:329
float meleeDistance
Definition: Weapon.h:247
const int SHADERPARM_BLUE
Definition: RenderWorld.h:48
bool hide
Definition: Weapon.h:221
static ammo_t GetAmmoNumForName(const char *ammoname)
Definition: Weapon.cpp:2445
int ServerRemapDecl(int clientNum, declType_t type, int index)
idRenderModel * SetModel(const char *modelname)
int muzzleFlashEnd
Definition: Weapon.h:265
const idEventDef AI_SetBlendFrames("setBlendFrames","dd")
idStr icon
Definition: Weapon.h:251
virtual void Show(void)
Definition: Entity.cpp:1239
idWeapon()
Definition: Weapon.cpp:150
const idMaterial * material
void AlertMonsters(void)
Definition: Weapon.cpp:2104
virtual void AddDamageEffect(const trace_t &collision, const idVec3 &velocity, const char *damageDefName)
Definition: Entity.cpp:3108
bool UseAmmo(ammo_t type, int amount)
GLuint GLuint GLsizei count
Definition: glext.h:2845
void NextBestWeapon(void)
int guiLightHandle
Definition: Weapon.h:255
idVec4 colorYellow
Definition: Lib.cpp:120
bool continuousSmoke
Definition: Weapon.h:319
int Index(void) const
Definition: DeclManager.h:165
idScriptBool WEAPON_RAISEWEAPON
Definition: Weapon.h:198
idPhysics * GetPhysics(void) const
Definition: Entity.cpp:2607
virtual void DebugLine(const idVec4 &color, const idVec3 &start, const idVec3 &end, const int lifetime=0, const bool depthTest=false)=0
renderLight_t worldMuzzleFlash
Definition: Weapon.h:261
void Event_Melee(void)
Definition: Weapon.cpp:3722
GLuint index
Definition: glext.h:3476
void SetSkin(const idDeclSkin *skin)
Definition: Entity.cpp:1178
const GLubyte * c
Definition: glext.h:4677
const char * GetString(const char *key, const char *defaultString="") const
Definition: Dict.h:240
bool SpawnEntityDef(const idDict &args, idEntity **ent=NULL, bool setDefaults=true)
void ReadFloat(float &value)
Definition: SaveGame.cpp:967
void Spawn(void)
Definition: Weapon.cpp:198
idVec3 lightRadius
Definition: RenderWorld.h:178
idWorldspawn * world
Definition: Game_local.h:280
bool IsType(const idTypeInfo &superclass) const
Definition: Class.h:310
int flashTime
Definition: Weapon.h:266
float RandomFloat(void)
Definition: Random.h:82
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
idVec3 muzzle_kick_offset
Definition: Weapon.h:279
idSoundEmitter * referenceSound
Definition: Game.h:209
void ReadRenderLight(renderLight_t &renderLight)
Definition: SaveGame.cpp:1333
virtual renderEntity_t * GetRenderEntity(void)
Definition: Entity.cpp:1506
int muzzle_kick_time
Definition: Weapon.h:276
void UpdateSound(void)
Definition: Entity.cpp:1749
void DoneProcessing(void)
void Unbind(void)
Definition: Entity.cpp:2011
void Launch(void)
void Raise(void)
Definition: Weapon.cpp:1528
void WriteLong(int c)
Definition: BitMsg.h:295
GLuint GLuint end
Definition: glext.h:2845
static float Sin(float a)
Definition: Math.h:310
void UpdateNozzleFx(void)
Definition: Weapon.cpp:1855
void WriteFloat(const float value)
Definition: SaveGame.cpp:213
idMat3 viewWeaponAxis
Definition: Weapon.h:233
idCommon * common
Definition: Common.cpp:206
int GetZoomFov(void)
Definition: Weapon.cpp:2408
static const char * sufaceTypeNames[MAX_SURFACE_TYPES]
Definition: Game_local.h:337
renderLight_t muzzleFlash
Definition: Weapon.h:258
idJointMat * joints
Definition: RenderWorld.h:135
idThread * frameCommandThread
Definition: Game_local.h:294
void ClearAllAnims(int currentTime, int cleartime)
bool weaponDepthHack
Definition: RenderWorld.h:149
bool GetBool(const char *key, const char *defaultString="0") const
Definition: Dict.h:256
Definition: Dict.h:65
idVec3 firstPersonViewOrigin
Definition: Player.h:370
void ResetAmmoClip(void)
Definition: Weapon.cpp:2605
#define NULL
Definition: Lib.h:88
idCVar g_muzzleFlash("g_muzzleFlash","1", CVAR_GAME|CVAR_ARCHIVE|CVAR_BOOL,"show muzzle flashes")
virtual const char * GetCVarString(const char *name) const =0
ammo_t GetAmmoType(void) const
Definition: Weapon.cpp:2614
idAnimBlend * CurrentAnim(int channelNum)
const idDeclSkin * customSkin
Definition: RenderWorld.h:125
void Clear(void)
Definition: Dict.cpp:201
virtual const idDecl * FindType(declType_t type, const char *name, bool makeDefault=true)=0
float y
Definition: Vector.h:319
int GetSpawnId(void) const
Definition: Game_local.h:231
int AmmoAvailable(void) const
Definition: Weapon.cpp:2583
idVec3 GetVector(const char *key, const char *defaultString=NULL) const
Definition: Dict.h:260
const idDeclParticle * weaponSmoke
Definition: Weapon.h:317
bool IsReady(void) const
Definition: Weapon.cpp:1718
void ServerSendEvent(int eventId, const idBitMsg *msg, bool saveEvent, int excludeClient) const
Definition: Entity.cpp:4897
static idTypeInfo * GetClass(const char *name)
Definition: Class.cpp:530
virtual void SetOrigin(const idVec3 &newOrigin, int id=-1)=0
void CancelEvents(const idEventDef *ev)
Definition: Class.cpp:619
const idAnim * GetAnim(int index) const
const idEventDef AI_PlayAnim("playAnim","ds", 'd')
Definition: Plane.h:71
bool PowerUpActive(int powerup) const
void CycleAnim(int channelNum, int animnum, int currenttime, int blendtime)
float hideStart
Definition: Weapon.h:218
static void ReturnFloat(float value)
void ShowWeapon(void)
Definition: Weapon.cpp:1614
idDict brassDict
Definition: Weapon.h:249
int lastAttack
Definition: Weapon.h:330
idMat3 endAxis
bool CanShowWeaponViewmodel(void) const
float weaponAngleOffsetMax
Definition: Weapon.h:341
const idEventDef EV_Weapon_TotalAmmoCount("totalAmmoCount", NULL, 'f')
int allowLightInViewID
Definition: RenderWorld.h:168
const idStr & GetValue(void) const
Definition: Dict.h:53
virtual const idMat3 & GetAxis(int id=0) const =0
virtual idAnimator * GetAnimator(void)
Definition: Entity.cpp:5213
virtual void UpdateEntityDef(qhandle_t entityHandle, const renderEntity_t *re)=0
const idEventDef EV_Weapon_State("weaponState","sd")
const idDeclModelDef * ModelDef(void) const
bool IsLinked(void) const
const idEventDef EV_Weapon_AllowDrop("allowDrop","d")
int ammo_t
Definition: Weapon.h:53
const function_t * GetConstructor(void) const
idBounds Rotate(const idMat3 &rotation) const
Definition: Bounds.h:342
void Event_WeaponRising(void)
Definition: Weapon.cpp:2862
#define MASK_SHOT_RENDERMODEL
Definition: Game_local.h:741
gameState_t GameState(void) const
const idEventDef EV_Weapon_WeaponReloading("weaponReloading")
idGameLocal gameLocal
Definition: Game_local.cpp:64
void SetBool(const char *key, bool val)
Definition: Dict.h:196
const int SHADERPARM_TIMEOFFSET
Definition: RenderWorld.h:51
void AlertAI(idEntity *ent)
virtual void Damage(idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location)
Definition: Entity.cpp:3061
#define END_CLASS
Definition: Class.h:54
void Reload(void)
Definition: Weapon.cpp:1552
idRenderModel * hModel
Definition: RenderWorld.h:81
int ammoRequired
Definition: Weapon.h:283
void GetJoints(int *numJoints, idJointMat **jointsPtr)
static void SinCos16(float a, float &s, float &c)
Definition: Math.h:406
virtual void UpdateLightDef(qhandle_t lightHandle, const renderLight_t *rlight)=0
const idDeclSkin * GetDefaultSkin(void) const
void Event_WeaponReloading(void)
Definition: Weapon.cpp:2841
#define DEG2RAD(a)
Definition: Math.h:56
void Restore(idRestoreGame *savefile)
Definition: Weapon.cpp:444
idEntityPtr< idAnimatedEntity > worldModel
Definition: Weapon.h:212
int hideTime
Definition: Weapon.h:215
virtual void Hide(void)
Definition: Entity.cpp:1226
const surfTypes_t GetSurfaceType(void) const
Definition: Material.h:503
void OwnerDied(void)
Definition: Weapon.cpp:1651
void NetCatchup(void)
Definition: Weapon.cpp:2396
virtual idClipModel * GetClipModel(int id=0) const =0
idDict projectileDict
Definition: Weapon.h:246
idMat3 firstPersonViewAxis
Definition: Player.h:371
void WriteInt(const int value)
Definition: SaveGame.cpp:168
virtual void Present(void)
Definition: Entity.cpp:1471
bool GetGlobalJointTransform(bool viewModel, const jointHandle_t jointHandle, idVec3 &offset, idMat3 &axis)
Definition: Weapon.cpp:1477
static idEntity * DropItem(const char *classname, const idVec3 &origin, const idMat3 &axis, const idVec3 &velocity, int activateDelay, int removeDelay)
Definition: Item.cpp:1822
virtual idThread * ConstructScriptObject(void)
Definition: Weapon.cpp:2011
void Event_GetWorldModel(void)
Definition: Weapon.cpp:3858
idDeclManager * declManager
const idEventDef EV_Light_SetLightParms("setLightParms","ffff")
void WriteMat3(const idMat3 &mat)
Definition: SaveGame.cpp:309
#define SEC2MS(t)
Definition: Math.h:59
void Clear(void)
Definition: Weapon.cpp:677
void ReadMat3(idMat3 &mat)
Definition: SaveGame.cpp:1064
idEntity * entities[MAX_GENTITIES]
Definition: Game_local.h:275
idDict userInfo[MAX_CLIENTS]
Definition: Game_local.h:272
idCVar g_debugWeapon("g_debugWeapon","0", CVAR_GAME|CVAR_BOOL,"")
int strikeSmokeStartTime
Definition: Weapon.h:321
virtual bool ClientReceiveEvent(int event, int time, const idBitMsg &msg)
Definition: Entity.cpp:4988
static const float TWO_PI
Definition: Math.h:206
void MuzzleFlashLight(void)
Definition: Weapon.cpp:1387
void Event_GetBlendFrames(int channel)
Definition: Weapon.cpp:3108
void GetWeaponDef(const char *objectname, int ammoinclip)
Definition: Weapon.cpp:925
idEntity * DropItem(const idVec3 &velocity, int activateDelay, int removeDelay, bool died)
Definition: Weapon.cpp:1791
const idDeclParticle * strikeSmoke
Definition: Weapon.h:320
const char * Icon(void) const
Definition: Weapon.cpp:1285
int localClientNum
Definition: Game_local.h:330
void LinkTo(idScriptObject &obj, const char *name)
idEntity * GetTraceEntity(const trace_t &trace) const
void UpdateGUI(void)
Definition: Weapon.cpp:1294
const idEventDef EV_Weapon_Next("nextWeapon")
void ReadStaticObject(idClass &obj)
Definition: SaveGame.cpp:1098
idPlayer * owner
Definition: Weapon.h:211
void UpdateFlashPosition(void)
Definition: Weapon.cpp:1366
idDict serverInfo
Definition: Game_local.h:270
Definition: Player.h:94
void Event_WeaponReady(void)
Definition: Weapon.cpp:2813
const idEventDef EV_Weapon_Flashlight("flashlight","d")
void WeaponLoweringCallback(void)
Definition: Matrix.h:333
const int SHADERPARM_RED
Definition: RenderWorld.h:46
idVec3 flashColor
Definition: Weapon.h:264
void Event_GetOwner(void)
Definition: Weapon.cpp:2778
void WriteAngles(const idAngles &angles)
Definition: SaveGame.cpp:318
bool CanDrop(void) const
Definition: Weapon.cpp:1754
int HasAmmo(ammo_t type, int amount)
void WeaponRisingCallback(void)
void UpdateVisuals(void)
Definition: Entity.cpp:1310
virtual void RemoveDecals(qhandle_t entityHandle)=0
bool GetBool(void) const
Definition: CVarSystem.h:142
virtual const idDecl * DeclByIndex(declType_t type, int index, bool forceParse=true)=0
void Event_TotalAmmoCount(void)
Definition: Weapon.cpp:2971
int hideStartTime
Definition: Weapon.h:217
void GetWeaponAngleOffsets(int *average, float *scale, float *max)
Definition: Weapon.cpp:2417
int GetListenerId(void) const
Definition: Entity.cpp:1769
tuple f
Definition: idal.py:89
float weaponOffsetScale
Definition: Weapon.h:343
idThread * thread
Definition: Weapon.h:201
float hideDistance
Definition: Weapon.h:216
void ProjectDecal(const idVec3 &origin, const idVec3 &dir, float depth, bool parallel, float size, const char *material, float angle=0)
bool IsGametypeFlagBased(void)
const idEventDef EV_Weapon_UseAmmo("useAmmo","d")
void Event_WeaponOutOfAmmo(void)
Definition: Weapon.cpp:2829
idMat3 ToMat3(void) const
Definition: Angles.cpp:199
unsigned char byte
Definition: Lib.h:75
const idEventDef EV_Weapon_Melee("melee", NULL, 'd')
virtual const idBounds & GetAbsBounds(int id=-1) const =0
int modelDefHandle
Definition: Entity.h:372
void StealWeapon(idPlayer *player)
const GLcharARB * name
Definition: glext.h:3629
virtual int GetDefaultSurfaceType(void) const
Definition: Entity.cpp:5349
idVec3 nozzleGlowColor
Definition: Weapon.h:334
void Create(idEntity *owner, const idVec3 &start, const idMat3 &axis)
GLsizeiptr size
Definition: glext.h:3112
const function_t * GetFunction(const char *name) const
void Signal(signalNum_t signalnum)
Definition: Entity.cpp:3352
idCVar pm_thirdPerson("pm_thirdPerson","0", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_BOOL,"enables third person view")
idCVar g_showBrass("g_showBrass","1", CVAR_GAME|CVAR_ARCHIVE|CVAR_BOOL,"enables ejected shells from weapon")
const function_t * GetDestructor(void) const
const idEventDef EV_Weapon_AmmoAvailable("ammoAvailable", NULL, 'f')
void Event_SetLightParms(float parm0, float parm1, float parm2, float parm3)
Definition: Weapon.cpp:3201
#define CLASS_DECLARATION(nameofsuperclass, nameofclass)
Definition: Class.h:110
Definition: Str.h:116
const idEventDef EV_Weapon_WeaponLowering("weaponLowering")
virtual void SetAngularVelocity(const idVec3 &newAngularVelocity, int id=0)=0
const idEventDef EV_Weapon_Clear("<clear>")
virtual void SetClipModel(idClipModel *model, float density, int id=0, bool freeOld=true)=0
virtual void ReadFromSnapshot(const idBitMsgDelta &msg)
Definition: Weapon.cpp:2692
bool lightOn
Definition: Weapon.h:267
int worldMuzzleFlashHandle
Definition: Weapon.h:262
void UpdateAnimation(void)
Definition: Entity.cpp:5172
void EndAttack(void)
Definition: Weapon.cpp:1701
void Save(idSaveGame *savefile) const
Definition: Game_local.h:656
void ReadVec3(idVec3 &vec)
Definition: SaveGame.cpp:1011
int suppressSurfaceInViewID
Definition: RenderWorld.h:104
int clipSize
Definition: Weapon.h:284
static void ReturnEntity(idEntity *ent)
class idUserInterface * gui[MAX_RENDERENTITY_GUI]
Definition: RenderWorld.h:130
ammo_t ammoType
Definition: Weapon.h:282
idScriptBool WEAPON_NETENDRELOAD
Definition: Weapon.h:196
void Event_AddToClip(int amount)
Definition: Weapon.cpp:2907
void BeginAttack(void)
Definition: Weapon.cpp:1679
const char * c_str(void) const
Definition: Str.h:487
void Event_SetSkin(const char *skinname)
Definition: Weapon.cpp:3127
void Clear(int channelNum, int currentTime, int cleartime)
int AmmoInClip(void) const
Definition: Weapon.cpp:2596
const idEventDef EV_Weapon_ClipSize("clipSize", NULL, 'f')
const idEventDef EV_Weapon_WeaponReady("weaponReady")
void ReadAngles(idAngles &angles)
Definition: SaveGame.cpp:1073
ID_INLINE int FRAME2MS(int framenum)
Definition: Anim.h:48
void BecomeActive(int flags)
Definition: Entity.cpp:995
idRenderSystemLocal tr
static const char * GetAmmoNameForNum(ammo_t ammonum)
Definition: Weapon.cpp:2498
const idEventDef EV_Weapon_GetOwner("getOwner", NULL, 'e')
refSound_t refSound
Definition: Entity.h:373
int lowAmmo
Definition: Weapon.h:286
bool allowDrop
Definition: Weapon.h:269
const idEventDef EV_Light_SetLightParm("setLightParm","df")
const idKeyValue * GetKeyVal(int index) const
Definition: Dict.h:294
renderLight_t nozzleGlow
Definition: Weapon.h:331
const idEventDef EV_Remove("<immediateremove>", NULL)
void Event_AmmoInClip(void)
Definition: Weapon.cpp:2945
void Event_SetBlendFrames(int channel, int blendFrames)
Definition: Weapon.cpp:3099
const int ASYNC_PLAYER_INV_CLIP_BITS
Definition: Player.h:74
float nozzleGlowRadius
Definition: Weapon.h:336
int GetEndTime(void) const
virtual void ProjectOverlay(qhandle_t entityHandle, const idPlane localTextureAxis[2], const idMaterial *material)=0
idStr meleeDefName
Definition: Weapon.h:248
virtual const idDeclSkin * FindSkin(const char *name, bool makeDefault=true)=0
int weaponSmokeStartTime
Definition: Weapon.h:318
void Event_AutoReload(void)
Definition: Weapon.cpp:2990
int ClipSize(void) const
Definition: Weapon.cpp:2623
int realClientTime
Definition: Game_local.h:332
void PresentWeapon(bool showViewModel)
Definition: Weapon.cpp:2150
virtual void DebugBounds(const idVec4 &color, const idBounds &bounds, const idVec3 &org=vec3_origin, const int lifetime=0)=0
void WeaponStolen(void)
Definition: Weapon.cpp:1770
int AmmoRequired(void) const
Definition: Weapon.cpp:2641
idPlayer * GetOwner(void)
Definition: Weapon.h:423
const char * GetEntityDefName(void) const
Definition: Entity.cpp:842
void MuzzleRise(idVec3 &origin, idMat3 &axis)
Definition: Weapon.cpp:1976
float diversity
Definition: Game.h:215
const idDeclEntityDef * FindEntityDef(const char *name, bool makeDefault=true) const
idRenderWorld * gameRenderWorld
Definition: Game_local.cpp:55
char * va(const char *fmt,...)
Definition: Str.cpp:1568
bool isLinked
Definition: Weapon.h:206
bool Translation(trace_t &results, const idVec3 &start, const idVec3 &end, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity)
Definition: Clip.cpp:1056
void PutAway(void)
Definition: Weapon.cpp:1539
idScriptBool WEAPON_LOWERWEAPON
Definition: Weapon.h:199
void SetOrigin(const idVec3 &org)
Definition: Entity.cpp:2784
bool PostEventMS(const idEventDef *ev, int time)
Definition: Class.cpp:666
#define max(x, y)
Definition: os.h:70
jointHandle_t guiLightJointView
Definition: Weapon.h:299
idMultiplayerGame mpGame
Definition: Game_local.h:305
const idEventDef EV_Weapon_LaunchProjectiles("launchProjectiles","dffff")
int entityNumber
Definition: Entity.h:111
void HideWorldModel(void)
Definition: Weapon.cpp:1629
GLfloat GLfloat p
Definition: glext.h:4674
const idMaterial * shader
Definition: RenderWorld.h:200
idStr name
Definition: Entity.h:121
bool nozzleFx
Definition: Weapon.h:327
idVec3 muzzleOrigin
Definition: Weapon.h:236
void Save(idSaveGame *savefile) const
Definition: Weapon.cpp:287
int zoomFov
Definition: Weapon.h:293
void Event_Clear(void)
Definition: Weapon.cpp:2769
const idEventDef EV_Touch("<touch>","et")
void WriteParticle(const idDeclParticle *particle)
Definition: SaveGame.cpp:406
void Event_WeaponHolstered(void)
Definition: Weapon.cpp:2850
int GetNumKeyVals(void) const
Definition: Dict.h:290
idScriptBool WEAPON_NETRELOAD
Definition: Weapon.h:195
void Zero(void)
Definition: Vector.h:415
int spectator
Definition: Player.h:334
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
float shaderParms[MAX_ENTITY_SHADER_PARMS]
Definition: RenderWorld.h:127
void ReadString(idStr &string)
Definition: SaveGame.cpp:985
bool Execute(void)
const idEventDef EV_SetSkin("setSkin","s")
const idEventDef EV_Weapon_NetReload("netReload")
void Event_WeaponLowering(void)
Definition: Weapon.cpp:2875
void WriteRenderLight(const renderLight_t &renderLight)
Definition: SaveGame.cpp:555
jointHandle_t flashJointView
Definition: Weapon.h:297
bool spectating
Definition: Player.h:340
static void ReturnInt(int value)
gameType_t gameType
Definition: Game_local.h:324
int brassDelay
Definition: Weapon.h:250
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
void ReadInt(int &value)
Definition: SaveGame.cpp:922
float CRandomFloat(void)
Definition: Random.h:86
void NormalVectors(idVec3 &left, idVec3 &down) const
Definition: Vector.h:727
void Event_AmmoAvailable(void)
Definition: Weapon.cpp:2955
const idEventDef AI_AnimDone("animDone","dd", 'd')
virtual bool ShouldConstructScriptObjectAtSpawn(void) const
Definition: Weapon.cpp:241
void ShowWorldModel(void)
Definition: Weapon.cpp:1640
idCollisionModelManager * collisionModelManager
void UpdateScript(void)
Definition: Weapon.cpp:2071
GLuint start
Definition: glext.h:2845
void StopSound(const s_channelType channel, bool broadcast)
Definition: Entity.cpp:1713
Definition: AI.h:253
const idEventDef EV_Weapon_GetWorldModel("getWorldModel", NULL, 'e')
void Event_AnimDone(int channel, int blendFrames)
Definition: Weapon.cpp:3086
bool IsHolstered(void) const
Definition: Weapon.cpp:1736
#define MS2SEC(t)
Definition: Math.h:60
void ReadObject(idClass *&obj)
Definition: SaveGame.cpp:1083
void LowerWeapon(void)
Definition: Weapon.cpp:1563
virtual void SetModel(const char *modelname)
Definition: Weapon.cpp:1448
virtual void SetAxis(const idMat3 &newAxis, int id=-1)=0
bool weaponGone
Definition: Player.h:345
static float Cos(float a)
Definition: Math.h:346
idScriptBool WEAPON_NETFIRING
Definition: Weapon.h:197
bool powerAmmo
Definition: Weapon.h:287
idMat3 playerViewAxis
Definition: Weapon.h:229
void AddProjectilesFired(int count)