doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Player.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 
37  Player control of the Doom Marine.
38  This object handles all player movement and world interaction.
39 
40 ===============================================================================
41 */
42 
43 // distance between ladder rungs (actually is half that distance, but this sounds better)
44 const int LADDER_RUNG_DISTANCE = 32;
45 
46 // amount of health per dose from the health station
47 const int HEALTH_PER_DOSE = 10;
48 
49 // time before a weapon dropped to the floor disappears
50 const int WEAPON_DROP_TIME = 20 * 1000;
51 
52 // time before a next or prev weapon switch happens
53 const int WEAPON_SWITCH_DELAY = 150;
54 
55 // how many units to raise spectator above default view height so it's in the head of someone
56 const int SPECTATE_RAISE = 25;
57 
58 const int HEALTHPULSE_TIME = 333;
59 
60 // minimum speed to bob and play run/walk animations at
61 const float MIN_BOB_SPEED = 5.0f;
62 
63 const idEventDef EV_Player_GetButtons( "getButtons", NULL, 'd' );
64 const idEventDef EV_Player_GetMove( "getMove", NULL, 'v' );
65 const idEventDef EV_Player_GetViewAngles( "getViewAngles", NULL, 'v' );
66 const idEventDef EV_Player_StopFxFov( "stopFxFov" );
67 const idEventDef EV_Player_EnableWeapon( "enableWeapon" );
68 const idEventDef EV_Player_DisableWeapon( "disableWeapon" );
69 const idEventDef EV_Player_GetCurrentWeapon( "getCurrentWeapon", NULL, 's' );
70 const idEventDef EV_Player_GetPreviousWeapon( "getPreviousWeapon", NULL, 's' );
71 const idEventDef EV_Player_SelectWeapon( "selectWeapon", "s" );
72 const idEventDef EV_Player_GetWeaponEntity( "getWeaponEntity", NULL, 'e' );
73 const idEventDef EV_Player_OpenPDA( "openPDA" );
74 const idEventDef EV_Player_InPDA( "inPDA", NULL, 'd' );
75 const idEventDef EV_Player_ExitTeleporter( "exitTeleporter" );
76 const idEventDef EV_Player_StopAudioLog( "stopAudioLog" );
77 const idEventDef EV_Player_HideTip( "hideTip" );
78 const idEventDef EV_Player_LevelTrigger( "levelTrigger" );
79 const idEventDef EV_SpectatorTouch( "spectatorTouch", "et" );
80 #ifdef _D3XP
81 const idEventDef EV_Player_GiveInventoryItem( "giveInventoryItem", "s" );
82 const idEventDef EV_Player_RemoveInventoryItem( "removeInventoryItem", "s" );
83 const idEventDef EV_Player_GetIdealWeapon( "getIdealWeapon", NULL, 's' );
84 const idEventDef EV_Player_SetPowerupTime( "setPowerupTime", "dd" );
85 const idEventDef EV_Player_IsPowerupActive( "isPowerupActive", "d", 'd' );
86 const idEventDef EV_Player_WeaponAvailable( "weaponAvailable", "s", 'd');
87 const idEventDef EV_Player_StartWarp( "startWarp" );
88 const idEventDef EV_Player_StopHelltime( "stopHelltime", "d" );
89 const idEventDef EV_Player_ToggleBloom( "toggleBloom", "d" );
90 const idEventDef EV_Player_SetBloomParms( "setBloomParms", "ff" );
91 #endif
92 
94  EVENT( EV_Player_GetButtons, idPlayer::Event_GetButtons )
95  EVENT( EV_Player_GetMove, idPlayer::Event_GetMove )
96  EVENT( EV_Player_GetViewAngles, idPlayer::Event_GetViewAngles )
97  EVENT( EV_Player_StopFxFov, idPlayer::Event_StopFxFov )
98  EVENT( EV_Player_EnableWeapon, idPlayer::Event_EnableWeapon )
99  EVENT( EV_Player_DisableWeapon, idPlayer::Event_DisableWeapon )
100  EVENT( EV_Player_GetCurrentWeapon, idPlayer::Event_GetCurrentWeapon )
101  EVENT( EV_Player_GetPreviousWeapon, idPlayer::Event_GetPreviousWeapon )
102  EVENT( EV_Player_SelectWeapon, idPlayer::Event_SelectWeapon )
103  EVENT( EV_Player_GetWeaponEntity, idPlayer::Event_GetWeaponEntity )
104  EVENT( EV_Player_OpenPDA, idPlayer::Event_OpenPDA )
105  EVENT( EV_Player_InPDA, idPlayer::Event_InPDA )
106  EVENT( EV_Player_ExitTeleporter, idPlayer::Event_ExitTeleporter )
107  EVENT( EV_Player_StopAudioLog, idPlayer::Event_StopAudioLog )
108  EVENT( EV_Player_HideTip, idPlayer::Event_HideTip )
109  EVENT( EV_Player_LevelTrigger, idPlayer::Event_LevelTrigger )
110  EVENT( EV_Gibbed, idPlayer::Event_Gibbed )
111 #ifdef _D3XP
112  EVENT( EV_Player_GiveInventoryItem, idPlayer::Event_GiveInventoryItem )
113  EVENT( EV_Player_RemoveInventoryItem, idPlayer::Event_RemoveInventoryItem )
114  EVENT( EV_Player_GetIdealWeapon, idPlayer::Event_GetIdealWeapon )
115  EVENT( EV_Player_WeaponAvailable, idPlayer::Event_WeaponAvailable )
116  EVENT( EV_Player_SetPowerupTime, idPlayer::Event_SetPowerupTime )
117  EVENT( EV_Player_IsPowerupActive, idPlayer::Event_IsPowerupActive )
118  EVENT( EV_Player_StartWarp, idPlayer::Event_StartWarp )
119  EVENT( EV_Player_StopHelltime, idPlayer::Event_StopHelltime )
120  EVENT( EV_Player_ToggleBloom, idPlayer::Event_ToggleBloom )
121  EVENT( EV_Player_SetBloomParms, idPlayer::Event_SetBloomParms )
122 #endif
123 END_CLASS
124 
125 const int MAX_RESPAWN_TIME = 10000;
126 const int RAGDOLL_DEATH_TIME = 3000;
127 const int MAX_PDAS = 64;
128 const int MAX_PDA_ITEMS = 128;
129 const int STEPUP_TIME = 200;
130 const int MAX_INVENTORY_ITEMS = 20;
131 
132 
133 #ifdef _D3XP
135 #else
136 idVec3 idPlayer::colorBarTable[ 5 ] = {
137 #endif
138  idVec3( 0.25f, 0.25f, 0.25f ),
139  idVec3( 1.00f, 0.00f, 0.00f ),
140  idVec3( 0.00f, 0.80f, 0.10f ),
141  idVec3( 0.20f, 0.50f, 0.80f ),
142  idVec3( 1.00f, 0.80f, 0.10f )
143 #ifdef _D3XP
144  ,idVec3( 0.425f, 0.484f, 0.445f ),
145  idVec3( 0.39f, 0.199f, 0.3f ),
146  idVec3( 0.484f, 0.312f, 0.074f)
147 #endif
148 };
149 
150 /*
151 ==============
152 idInventory::Clear
153 ==============
154 */
155 void idInventory::Clear( void ) {
156  maxHealth = 0;
157  weapons = 0;
158  powerups = 0;
159  armor = 0;
160  maxarmor = 0;
161  deplete_armor = 0;
162  deplete_rate = 0.0f;
163  deplete_ammount = 0;
165 
166  memset( ammo, 0, sizeof( ammo ) );
167 
168  ClearPowerUps();
169 
170  // set to -1 so that the gun knows to have a full clip the first time we get it and at the start of the level
171  memset( clip, -1, sizeof( clip ) );
172 
173  items.DeleteContents( true );
174  memset(pdasViewed, 0, 4 * sizeof( pdasViewed[0] ) );
175  pdas.Clear();
176  videos.Clear();
177  emails.Clear();
178  selVideo = 0;
179  selEMail = 0;
180  selPDA = 0;
181  selAudio = 0;
182  pdaOpened = false;
183  turkeyScore = false;
184 
186 
187  nextItemPickup = 0;
188  nextItemNum = 1;
189  onePickupTime = 0;
192 
193  ammoPredictTime = 0;
194 
195  lastGiveTime = 0;
196 
197  ammoPulse = false;
198  weaponPulse = false;
199  armorPulse = false;
200 }
201 
202 /*
203 ==============
204 idInventory::GivePowerUp
205 ==============
206 */
207 void idInventory::GivePowerUp( idPlayer *player, int powerup, int msec ) {
208  if ( !msec ) {
209  // get the duration from the .def files
210  const idDeclEntityDef *def = NULL;
211  switch ( powerup ) {
212  case BERSERK:
213  def = gameLocal.FindEntityDef( "powerup_berserk", false );
214  break;
215  case INVISIBILITY:
216  def = gameLocal.FindEntityDef( "powerup_invisibility", false );
217  break;
218  case MEGAHEALTH:
219  def = gameLocal.FindEntityDef( "powerup_megahealth", false );
220  break;
221  case ADRENALINE:
222  def = gameLocal.FindEntityDef( "powerup_adrenaline", false );
223  break;
224 #ifdef _D3XP
225  case INVULNERABILITY:
226  def = gameLocal.FindEntityDef( "powerup_invulnerability", false );
227  break;
228  /*case HASTE:
229  def = gameLocal.FindEntityDef( "powerup_haste", false );
230  break;*/
231 #endif
232  }
233  assert( def );
234  msec = def->dict.GetInt( "time" ) * 1000;
235  }
236  powerups |= 1 << powerup;
237  powerupEndTime[ powerup ] = gameLocal.time + msec;
238 }
239 
240 /*
241 ==============
242 idInventory::ClearPowerUps
243 ==============
244 */
246  int i;
247  for ( i = 0; i < MAX_POWERUPS; i++ ) {
248  powerupEndTime[ i ] = 0;
249  }
250  powerups = 0;
251 }
252 
253 /*
254 ==============
255 idInventory::GetPersistantData
256 ==============
257 */
259  int i;
260  int num;
261  idDict *item;
262  idStr key;
263  const idKeyValue *kv;
264  const char *name;
265 
266  // armor
267  dict.SetInt( "armor", armor );
268 
269  // don't bother with powerups, maxhealth, maxarmor, or the clip
270 
271  // ammo
272  for( i = 0; i < AMMO_NUMTYPES; i++ ) {
273  name = idWeapon::GetAmmoNameForNum( ( ammo_t )i );
274  if ( name ) {
275  dict.SetInt( name, ammo[ i ] );
276  }
277  }
278 
279 #ifdef _D3XP
280  //Save the clip data
281  for( i = 0; i < MAX_WEAPONS; i++ ) {
282  dict.SetInt( va("clip%i", i), clip[ i ] );
283  }
284 #endif
285 
286  // items
287  num = 0;
288  for( i = 0; i < items.Num(); i++ ) {
289  item = items[ i ];
290 
291  // copy all keys with "inv_"
292  kv = item->MatchPrefix( "inv_" );
293  if ( kv ) {
294  while( kv ) {
295  sprintf( key, "item_%i %s", num, kv->GetKey().c_str() );
296  dict.Set( key, kv->GetValue() );
297  kv = item->MatchPrefix( "inv_", kv );
298  }
299  num++;
300  }
301  }
302  dict.SetInt( "items", num );
303 
304  // pdas viewed
305  for ( i = 0; i < 4; i++ ) {
306  dict.SetInt( va("pdasViewed_%i", i), pdasViewed[i] );
307  }
308 
309  dict.SetInt( "selPDA", selPDA );
310  dict.SetInt( "selVideo", selVideo );
311  dict.SetInt( "selEmail", selEMail );
312  dict.SetInt( "selAudio", selAudio );
313  dict.SetInt( "pdaOpened", pdaOpened );
314  dict.SetInt( "turkeyScore", turkeyScore );
315 
316  // pdas
317  for ( i = 0; i < pdas.Num(); i++ ) {
318  sprintf( key, "pda_%i", i );
319  dict.Set( key, pdas[ i ] );
320  }
321  dict.SetInt( "pdas", pdas.Num() );
322 
323  // video cds
324  for ( i = 0; i < videos.Num(); i++ ) {
325  sprintf( key, "video_%i", i );
326  dict.Set( key, videos[ i ].c_str() );
327  }
328  dict.SetInt( "videos", videos.Num() );
329 
330  // emails
331  for ( i = 0; i < emails.Num(); i++ ) {
332  sprintf( key, "email_%i", i );
333  dict.Set( key, emails[ i ].c_str() );
334  }
335  dict.SetInt( "emails", emails.Num() );
336 
337  // weapons
338  dict.SetInt( "weapon_bits", weapons );
339 
340  dict.SetInt( "levelTriggers", levelTriggers.Num() );
341  for ( i = 0; i < levelTriggers.Num(); i++ ) {
342  sprintf( key, "levelTrigger_Level_%i", i );
343  dict.Set( key, levelTriggers[i].levelName );
344  sprintf( key, "levelTrigger_Trigger_%i", i );
345  dict.Set( key, levelTriggers[i].triggerName );
346  }
347 }
348 
349 /*
350 ==============
351 idInventory::RestoreInventory
352 ==============
353 */
354 void idInventory::RestoreInventory( idPlayer *owner, const idDict &dict ) {
355  int i;
356  int num;
357  idDict *item;
358  idStr key;
359  idStr itemname;
360  const idKeyValue *kv;
361  const char *name;
362 
363  Clear();
364 
365  // health/armor
366  maxHealth = dict.GetInt( "maxhealth", "100" );
367  armor = dict.GetInt( "armor", "50" );
368  maxarmor = dict.GetInt( "maxarmor", "100" );
369  deplete_armor = dict.GetInt( "deplete_armor", "0" );
370  deplete_rate = dict.GetFloat( "deplete_rate", "2.0" );
371  deplete_ammount = dict.GetInt( "deplete_ammount", "1" );
372 
373  // the clip and powerups aren't restored
374 
375  // ammo
376  for( i = 0; i < AMMO_NUMTYPES; i++ ) {
377  name = idWeapon::GetAmmoNameForNum( ( ammo_t )i );
378  if ( name ) {
379  ammo[ i ] = dict.GetInt( name );
380  }
381  }
382 
383 #ifdef _D3XP
384  //Restore the clip data
385  for( i = 0; i < MAX_WEAPONS; i++ ) {
386  clip[i] = dict.GetInt(va("clip%i", i), "-1");
387  }
388 #endif
389 
390  // items
391  num = dict.GetInt( "items" );
392  items.SetNum( num );
393  for( i = 0; i < num; i++ ) {
394  item = new idDict();
395  items[ i ] = item;
396  sprintf( itemname, "item_%i ", i );
397  kv = dict.MatchPrefix( itemname );
398  while( kv ) {
399  key = kv->GetKey();
400  key.Strip( itemname );
401  item->Set( key, kv->GetValue() );
402  kv = dict.MatchPrefix( itemname, kv );
403  }
404  }
405 
406  // pdas viewed
407  for ( i = 0; i < 4; i++ ) {
408  pdasViewed[i] = dict.GetInt(va("pdasViewed_%i", i));
409  }
410 
411  selPDA = dict.GetInt( "selPDA" );
412  selEMail = dict.GetInt( "selEmail" );
413  selVideo = dict.GetInt( "selVideo" );
414  selAudio = dict.GetInt( "selAudio" );
415  pdaOpened = dict.GetBool( "pdaOpened" );
416  turkeyScore = dict.GetBool( "turkeyScore" );
417 
418  // pdas
419  num = dict.GetInt( "pdas" );
420  pdas.SetNum( num );
421  for ( i = 0; i < num; i++ ) {
422  sprintf( itemname, "pda_%i", i );
423  pdas[i] = dict.GetString( itemname, "default" );
424  }
425 
426  // videos
427  num = dict.GetInt( "videos" );
428  videos.SetNum( num );
429  for ( i = 0; i < num; i++ ) {
430  sprintf( itemname, "video_%i", i );
431  videos[i] = dict.GetString( itemname, "default" );
432  }
433 
434  // emails
435  num = dict.GetInt( "emails" );
436  emails.SetNum( num );
437  for ( i = 0; i < num; i++ ) {
438  sprintf( itemname, "email_%i", i );
439  emails[i] = dict.GetString( itemname, "default" );
440  }
441 
442  // weapons are stored as a number for persistant data, but as strings in the entityDef
443  weapons = dict.GetInt( "weapon_bits", "0" );
444 
445 #ifdef ID_DEMO_BUILD
446  Give( owner, dict, "weapon", dict.GetString( "weapon" ), NULL, false );
447 #else
448  if ( g_skill.GetInteger() >= 3 ) {
449  Give( owner, dict, "weapon", dict.GetString( "weapon_nightmare" ), NULL, false );
450  } else {
451  Give( owner, dict, "weapon", dict.GetString( "weapon" ), NULL, false );
452  }
453 #endif
454 
455  num = dict.GetInt( "levelTriggers" );
456  for ( i = 0; i < num; i++ ) {
457  sprintf( itemname, "levelTrigger_Level_%i", i );
458  idLevelTriggerInfo lti;
459  lti.levelName = dict.GetString( itemname );
460  sprintf( itemname, "levelTrigger_Trigger_%i", i );
461  lti.triggerName = dict.GetString( itemname );
462  levelTriggers.Append( lti );
463  }
464 
465 }
466 
467 /*
468 ==============
469 idInventory::Save
470 ==============
471 */
472 void idInventory::Save( idSaveGame *savefile ) const {
473  int i;
474 
475  savefile->WriteInt( maxHealth );
476  savefile->WriteInt( weapons );
477  savefile->WriteInt( powerups );
478  savefile->WriteInt( armor );
479  savefile->WriteInt( maxarmor );
480  savefile->WriteInt( ammoPredictTime );
481  savefile->WriteInt( deplete_armor );
482  savefile->WriteFloat( deplete_rate );
483  savefile->WriteInt( deplete_ammount );
484  savefile->WriteInt( nextArmorDepleteTime );
485 
486  for( i = 0; i < AMMO_NUMTYPES; i++ ) {
487  savefile->WriteInt( ammo[ i ] );
488  }
489  for( i = 0; i < MAX_WEAPONS; i++ ) {
490  savefile->WriteInt( clip[ i ] );
491  }
492  for( i = 0; i < MAX_POWERUPS; i++ ) {
493  savefile->WriteInt( powerupEndTime[ i ] );
494  }
495 
496  savefile->WriteInt( items.Num() );
497  for( i = 0; i < items.Num(); i++ ) {
498  savefile->WriteDict( items[ i ] );
499  }
500 
501  savefile->WriteInt( pdasViewed[0] );
502  savefile->WriteInt( pdasViewed[1] );
503  savefile->WriteInt( pdasViewed[2] );
504  savefile->WriteInt( pdasViewed[3] );
505 
506  savefile->WriteInt( selPDA );
507  savefile->WriteInt( selVideo );
508  savefile->WriteInt( selEMail );
509  savefile->WriteInt( selAudio );
510  savefile->WriteBool( pdaOpened );
511  savefile->WriteBool( turkeyScore );
512 
513  savefile->WriteInt( pdas.Num() );
514  for( i = 0; i < pdas.Num(); i++ ) {
515  savefile->WriteString( pdas[ i ] );
516  }
517 
518  savefile->WriteInt( pdaSecurity.Num() );
519  for( i=0; i < pdaSecurity.Num(); i++ ) {
520  savefile->WriteString( pdaSecurity[ i ] );
521  }
522 
523  savefile->WriteInt( videos.Num() );
524  for( i = 0; i < videos.Num(); i++ ) {
525  savefile->WriteString( videos[ i ] );
526  }
527 
528  savefile->WriteInt( emails.Num() );
529  for ( i = 0; i < emails.Num(); i++ ) {
530  savefile->WriteString( emails[ i ] );
531  }
532 
533  savefile->WriteInt( nextItemPickup );
534  savefile->WriteInt( nextItemNum );
535  savefile->WriteInt( onePickupTime );
536 
537  savefile->WriteInt( pickupItemNames.Num() );
538  for( i = 0; i < pickupItemNames.Num(); i++ ) {
539  savefile->WriteString( pickupItemNames[i].icon );
540  savefile->WriteString( pickupItemNames[i].name );
541  }
542 
543  savefile->WriteInt( objectiveNames.Num() );
544  for( i = 0; i < objectiveNames.Num(); i++ ) {
545  savefile->WriteString( objectiveNames[i].screenshot );
546  savefile->WriteString( objectiveNames[i].text );
547  savefile->WriteString( objectiveNames[i].title );
548  }
549 
550  savefile->WriteInt( levelTriggers.Num() );
551  for ( i = 0; i < levelTriggers.Num(); i++ ) {
552  savefile->WriteString( levelTriggers[i].levelName );
553  savefile->WriteString( levelTriggers[i].triggerName );
554  }
555 
556  savefile->WriteBool( ammoPulse );
557  savefile->WriteBool( weaponPulse );
558  savefile->WriteBool( armorPulse );
559 
560  savefile->WriteInt( lastGiveTime );
561 
562 #ifdef _D3XP
563  for(i = 0; i < AMMO_NUMTYPES; i++) {
564  savefile->WriteInt(rechargeAmmo[i].ammo);
565  savefile->WriteInt(rechargeAmmo[i].rechargeTime);
566  savefile->WriteString(rechargeAmmo[i].ammoName);
567  }
568 #endif
569 }
570 
571 /*
572 ==============
573 idInventory::Restore
574 ==============
575 */
577  int i, num;
578 
579  savefile->ReadInt( maxHealth );
580  savefile->ReadInt( weapons );
581  savefile->ReadInt( powerups );
582  savefile->ReadInt( armor );
583  savefile->ReadInt( maxarmor );
584  savefile->ReadInt( ammoPredictTime );
585  savefile->ReadInt( deplete_armor );
586  savefile->ReadFloat( deplete_rate );
587  savefile->ReadInt( deplete_ammount );
588  savefile->ReadInt( nextArmorDepleteTime );
589 
590  for( i = 0; i < AMMO_NUMTYPES; i++ ) {
591  savefile->ReadInt( ammo[ i ] );
592  }
593  for( i = 0; i < MAX_WEAPONS; i++ ) {
594  savefile->ReadInt( clip[ i ] );
595  }
596  for( i = 0; i < MAX_POWERUPS; i++ ) {
597  savefile->ReadInt( powerupEndTime[ i ] );
598  }
599 
600  savefile->ReadInt( num );
601  for( i = 0; i < num; i++ ) {
602  idDict *itemdict = new idDict;
603 
604  savefile->ReadDict( itemdict );
605  items.Append( itemdict );
606  }
607 
608  // pdas
609  savefile->ReadInt( pdasViewed[0] );
610  savefile->ReadInt( pdasViewed[1] );
611  savefile->ReadInt( pdasViewed[2] );
612  savefile->ReadInt( pdasViewed[3] );
613 
614  savefile->ReadInt( selPDA );
615  savefile->ReadInt( selVideo );
616  savefile->ReadInt( selEMail );
617  savefile->ReadInt( selAudio );
618  savefile->ReadBool( pdaOpened );
619  savefile->ReadBool( turkeyScore );
620 
621  savefile->ReadInt( num );
622  for( i = 0; i < num; i++ ) {
623  idStr strPda;
624  savefile->ReadString( strPda );
625  pdas.Append( strPda );
626  }
627 
628  // pda security clearances
629  savefile->ReadInt( num );
630  for ( i = 0; i < num; i++ ) {
631  idStr invName;
632  savefile->ReadString( invName );
633  pdaSecurity.Append( invName );
634  }
635 
636  // videos
637  savefile->ReadInt( num );
638  for( i = 0; i < num; i++ ) {
639  idStr strVideo;
640  savefile->ReadString( strVideo );
641  videos.Append( strVideo );
642  }
643 
644  // email
645  savefile->ReadInt( num );
646  for( i = 0; i < num; i++ ) {
647  idStr strEmail;
648  savefile->ReadString( strEmail );
649  emails.Append( strEmail );
650  }
651 
652  savefile->ReadInt( nextItemPickup );
653  savefile->ReadInt( nextItemNum );
654  savefile->ReadInt( onePickupTime );
655  savefile->ReadInt( num );
656  for( i = 0; i < num; i++ ) {
657  idItemInfo info;
658 
659  savefile->ReadString( info.icon );
660  savefile->ReadString( info.name );
661 
662  pickupItemNames.Append( info );
663  }
664 
665  savefile->ReadInt( num );
666  for( i = 0; i < num; i++ ) {
668 
669  savefile->ReadString( obj.screenshot );
670  savefile->ReadString( obj.text );
671  savefile->ReadString( obj.title );
672 
673  objectiveNames.Append( obj );
674  }
675 
676  savefile->ReadInt( num );
677  for ( i = 0; i < num; i++ ) {
678  idLevelTriggerInfo lti;
679  savefile->ReadString( lti.levelName );
680  savefile->ReadString( lti.triggerName );
681  levelTriggers.Append( lti );
682  }
683 
684  savefile->ReadBool( ammoPulse );
685  savefile->ReadBool( weaponPulse );
686  savefile->ReadBool( armorPulse );
687 
688  savefile->ReadInt( lastGiveTime );
689 
690 #ifdef _D3XP
691  for(i = 0; i < AMMO_NUMTYPES; i++) {
692  savefile->ReadInt(rechargeAmmo[i].ammo);
693  savefile->ReadInt(rechargeAmmo[i].rechargeTime);
694 
695  idStr name;
696  savefile->ReadString(name);
697  strcpy(rechargeAmmo[i].ammoName, name);
698  }
699 #endif
700 }
701 
702 /*
703 ==============
704 idInventory::AmmoIndexForAmmoClass
705 ==============
706 */
707 ammo_t idInventory::AmmoIndexForAmmoClass( const char *ammo_classname ) const {
708  return idWeapon::GetAmmoNumForName( ammo_classname );
709 }
710 
711 /*
712 ==============
713 idInventory::AmmoIndexForAmmoClass
714 ==============
715 */
716 int idInventory::MaxAmmoForAmmoClass( idPlayer *owner, const char *ammo_classname ) const {
717  return owner->spawnArgs.GetInt( va( "max_%s", ammo_classname ), "0" );
718 }
719 
720 /*
721 ==============
722 idInventory::AmmoPickupNameForIndex
723 ==============
724 */
725 const char *idInventory::AmmoPickupNameForIndex( ammo_t ammonum ) const {
726  return idWeapon::GetAmmoPickupNameForNum( ammonum );
727 }
728 
729 /*
730 ==============
731 idInventory::WeaponIndexForAmmoClass
732 mapping could be prepared in the constructor
733 ==============
734 */
735 int idInventory::WeaponIndexForAmmoClass( const idDict & spawnArgs, const char *ammo_classname ) const {
736  int i;
737  const char *weapon_classname;
738  for( i = 0; i < MAX_WEAPONS; i++ ) {
739  weapon_classname = spawnArgs.GetString( va( "def_weapon%d", i ) );
740  if ( !weapon_classname ) {
741  continue;
742  }
743  const idDeclEntityDef *decl = gameLocal.FindEntityDef( weapon_classname, false );
744  if ( !decl ) {
745  continue;
746  }
747  if ( !idStr::Icmp( ammo_classname, decl->dict.GetString( "ammoType" ) ) ) {
748  return i;
749  }
750  }
751  return -1;
752 }
753 
754 /*
755 ==============
756 idInventory::AmmoIndexForWeaponClass
757 ==============
758 */
759 ammo_t idInventory::AmmoIndexForWeaponClass( const char *weapon_classname, int *ammoRequired ) {
760  const idDeclEntityDef *decl = gameLocal.FindEntityDef( weapon_classname, false );
761  if ( !decl ) {
762  gameLocal.Error( "Unknown weapon in decl '%s'", weapon_classname );
763  }
764  if ( ammoRequired ) {
765  *ammoRequired = decl->dict.GetInt( "ammoRequired" );
766  }
767  ammo_t ammo_i = AmmoIndexForAmmoClass( decl->dict.GetString( "ammoType" ) );
768  return ammo_i;
769 }
770 
771 /*
772 ==============
773 idInventory::AddPickupName
774 ==============
775 */
776 void idInventory::AddPickupName( const char *name, const char *icon, idPlayer* owner ) { //_D3XP
777  int num;
778 
779  num = pickupItemNames.Num();
780  if ( ( num == 0 ) || ( pickupItemNames[ num - 1 ].name.Icmp( name ) != 0 ) ) {
781  idItemInfo &info = pickupItemNames.Alloc();
782 
783  if ( idStr::Cmpn( name, STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 ) {
784  info.name = common->GetLanguageDict()->GetString( name );
785  } else {
786  info.name = name;
787  }
788  info.icon = icon;
789 
790 #ifdef _D3XP
791  if ( gameLocal.isServer ) {
792  idBitMsg msg;
793  byte msgBuf[MAX_EVENT_PARAM_SIZE];
794 
795  msg.Init( msgBuf, sizeof( msgBuf ) );
796  msg.WriteString( name, MAX_EVENT_PARAM_SIZE );
797  owner->ServerSendEvent( idPlayer::EVENT_PICKUPNAME, &msg, false, -1 );
798  }
799  }
800 #endif
801 }
802 
803 /*
804 ==============
805 idInventory::Give
806 ==============
807 */
808 bool idInventory::Give( idPlayer *owner, const idDict &spawnArgs, const char *statname, const char *value, int *idealWeapon, bool updateHud ) {
809  int i;
810  const char *pos;
811  const char *end;
812  int len;
813  idStr weaponString;
814  int max;
815  const idDeclEntityDef *weaponDecl;
816  bool tookWeapon;
817  int amount;
818  idItemInfo info;
819  const char *name;
820 
821 #ifdef _D3XP
822  if ( !idStr::Icmp( statname, "ammo_bloodstone" ) ) {
823  i = AmmoIndexForAmmoClass( statname );
824  max = MaxAmmoForAmmoClass( owner, statname );
825 
826  if(max <= 0) {
827  //No Max
828  ammo[ i ] += atoi( value );
829  } else {
830  //Already at or above the max so don't allow the give
831  if(ammo[ i ] >= max) {
832  ammo[ i ] = max;
833  return false;
834  }
835  //We were below the max so accept the give but cap it at the max
836  ammo[ i ] += atoi( value );
837  if(ammo[ i ] > max) {
838  ammo[ i ] = max;
839  }
840  }
841  } else
842 #endif
843 
844  if ( !idStr::Icmpn( statname, "ammo_", 5 ) ) {
845  i = AmmoIndexForAmmoClass( statname );
846  max = MaxAmmoForAmmoClass( owner, statname );
847  if ( ammo[ i ] >= max ) {
848  return false;
849  }
850  amount = atoi( value );
851  if ( amount ) {
852  ammo[ i ] += amount;
853  if ( ( max > 0 ) && ( ammo[ i ] > max ) ) {
854  ammo[ i ] = max;
855  }
856  ammoPulse = true;
857 
858  name = AmmoPickupNameForIndex( i );
859  if ( idStr::Length( name ) ) {
860  AddPickupName( name, "", owner ); //_D3XP
861  }
862  }
863  } else if ( !idStr::Icmp( statname, "armor" ) ) {
864  if ( armor >= maxarmor ) {
865  return false; // can't hold any more, so leave the item
866  }
867  amount = atoi( value );
868  if ( amount ) {
869  armor += amount;
870  if ( armor > maxarmor ) {
871  armor = maxarmor;
872  }
874  armorPulse = true;
875  }
876  } else if ( idStr::FindText( statname, "inclip_" ) == 0 ) {
877 #ifdef _D3XP
878  idStr temp = statname;
879  i = atoi(temp.Mid(7, 2));
880 #else
881  i = WeaponIndexForAmmoClass( spawnArgs, statname + 7 );
882 #endif
883  if ( i != -1 ) {
884  // set, don't add. not going over the clip size limit.
885 #ifndef _D3XP
886  clip[ i ] = atoi( value );
887 #endif
888  }
889 #ifdef _D3XP
890  } else if ( !idStr::Icmp( statname, "invulnerability" ) ) {
891  owner->GivePowerUp( INVULNERABILITY, SEC2MS( atof( value ) ) );
892  } else if ( !idStr::Icmp( statname, "helltime" ) ) {
893  owner->GivePowerUp( HELLTIME, SEC2MS( atof( value ) ) );
894  } else if ( !idStr::Icmp( statname, "envirosuit" ) ) {
895  owner->GivePowerUp( ENVIROSUIT, SEC2MS( atof( value ) ) );
896  owner->GivePowerUp( ENVIROTIME, SEC2MS( atof( value ) ) );
897  } else if ( !idStr::Icmp( statname, "berserk" ) ) {
898  owner->GivePowerUp( BERSERK, SEC2MS( atof( value ) ) );
899  //} else if ( !idStr::Icmp( statname, "haste" ) ) {
900  // owner->GivePowerUp( HASTE, SEC2MS( atof( value ) ) );
901 #else
902  } else if ( !idStr::Icmp( statname, "berserk" ) ) {
903  GivePowerUp( owner, BERSERK, SEC2MS( atof( value ) ) );
904 #endif
905  } else if ( !idStr::Icmp( statname, "mega" ) ) {
906  GivePowerUp( owner, MEGAHEALTH, SEC2MS( atof( value ) ) );
907  } else if ( !idStr::Icmp( statname, "weapon" ) ) {
908  tookWeapon = false;
909  for( pos = value; pos != NULL; pos = end ) {
910  end = strchr( pos, ',' );
911  if ( end ) {
912  len = end - pos;
913  end++;
914  } else {
915  len = strlen( pos );
916  }
917 
918  idStr weaponName( pos, 0, len );
919 
920  // find the number of the matching weapon name
921  for( i = 0; i < MAX_WEAPONS; i++ ) {
922  if ( weaponName == spawnArgs.GetString( va( "def_weapon%d", i ) ) ) {
923  break;
924  }
925  }
926 
927  if ( i >= MAX_WEAPONS ) {
928 #ifdef _D3XP
929  gameLocal.Warning( "Unknown weapon '%s'", weaponName.c_str() );
930  continue;
931 #else
932  gameLocal.Error( "Unknown weapon '%s'", weaponName.c_str() );
933 #endif
934  }
935 
936  // cache the media for this weapon
937  weaponDecl = gameLocal.FindEntityDef( weaponName, false );
938 
939  // don't pickup "no ammo" weapon types twice
940  // not for D3 SP .. there is only one case in the game where you can get a no ammo
941  // weapon when you might already have it, in that case it is more conistent to pick it up
942  if ( gameLocal.isMultiplayer && weaponDecl && ( weapons & ( 1 << i ) ) && !weaponDecl->dict.GetInt( "ammoRequired" ) ) {
943  continue;
944  }
945 
946  if ( !gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) || ( weaponName == "weapon_fists" ) || ( weaponName == "weapon_soulcube" ) ) {
947  if ( ( weapons & ( 1 << i ) ) == 0 || gameLocal.isMultiplayer ) {
948  if ( owner->GetUserInfo()->GetBool( "ui_autoSwitch" ) && idealWeapon && i != owner->weapon_bloodstone_active1 && i != owner->weapon_bloodstone_active2 && i != owner->weapon_bloodstone_active3) {
950  *idealWeapon = i;
951  }
952  if ( owner->hud && updateHud && lastGiveTime + 1000 < gameLocal.time ) {
953  owner->hud->SetStateInt( "newWeapon", i );
954  owner->hud->HandleNamedEvent( "newWeapon" );
956  }
957  weaponPulse = true;
958  weapons |= ( 1 << i );
959  tookWeapon = true;
960  }
961  }
962  }
963  return tookWeapon;
964  } else if ( !idStr::Icmp( statname, "item" ) || !idStr::Icmp( statname, "icon" ) || !idStr::Icmp( statname, "name" ) ) {
965  // ignore these as they're handled elsewhere
966  return false;
967  } else {
968  // unknown item
969  gameLocal.Warning( "Unknown stat '%s' added to player's inventory", statname );
970  return false;
971  }
972 
973  return true;
974 }
975 
976 /*
977 ===============
978 idInventoy::Drop
979 ===============
980 */
981 void idInventory::Drop( const idDict &spawnArgs, const char *weapon_classname, int weapon_index ) {
982  // remove the weapon bit
983  // also remove the ammo associated with the weapon as we pushed it in the item
984  assert( weapon_index != -1 || weapon_classname );
985  if ( weapon_index == -1 ) {
986  for( weapon_index = 0; weapon_index < MAX_WEAPONS; weapon_index++ ) {
987  if ( !idStr::Icmp( weapon_classname, spawnArgs.GetString( va( "def_weapon%d", weapon_index ) ) ) ) {
988  break;
989  }
990  }
991  if ( weapon_index >= MAX_WEAPONS ) {
992  gameLocal.Error( "Unknown weapon '%s'", weapon_classname );
993  }
994  } else if ( !weapon_classname ) {
995  weapon_classname = spawnArgs.GetString( va( "def_weapon%d", weapon_index ) );
996  }
997  weapons &= ( 0xffffffff ^ ( 1 << weapon_index ) );
998  ammo_t ammo_i = AmmoIndexForWeaponClass( weapon_classname, NULL );
999  if ( ammo_i ) {
1000  clip[ weapon_index ] = -1;
1001  ammo[ ammo_i ] = 0;
1002  }
1003 }
1004 
1005 /*
1006 ===============
1007 idInventory::HasAmmo
1008 ===============
1009 */
1010 int idInventory::HasAmmo( ammo_t type, int amount ) {
1011  if ( ( type == 0 ) || !amount ) {
1012  // always allow weapons that don't use ammo to fire
1013  return -1;
1014  }
1015 
1016  // check if we have infinite ammo
1017  if ( ammo[ type ] < 0 ) {
1018  return -1;
1019  }
1020 
1021  // return how many shots we can fire
1022  return ammo[ type ] / amount;
1023 
1024 }
1025 
1026 /*
1027 ===============
1028 idInventory::HasAmmo
1029 ===============
1030 */
1031 int idInventory::HasAmmo( const char *weapon_classname, bool includeClip, idPlayer* owner ) { //_D3XP
1032  int ammoRequired;
1033  ammo_t ammo_i = AmmoIndexForWeaponClass( weapon_classname, &ammoRequired );
1034 
1035 #ifdef _D3XP
1036  int ammoCount = HasAmmo( ammo_i, ammoRequired );
1037  if(includeClip && owner) {
1038  ammoCount += clip[owner->SlotForWeapon(weapon_classname)];
1039  }
1040  return ammoCount;
1041 #else
1042  return HasAmmo( ammo_i, ammoRequired );
1043 #endif
1044 
1045 }
1046 
1047 #ifdef _D3XP
1048 /*
1049 ===============
1050 idInventory::HasEmptyClipCannotRefill
1051 ===============
1052 */
1053 bool idInventory::HasEmptyClipCannotRefill(const char *weapon_classname, idPlayer* owner) {
1054 
1055  int clipSize = clip[owner->SlotForWeapon(weapon_classname)];
1056  if(clipSize) {
1057  return false;
1058  }
1059 
1060  const idDeclEntityDef *decl = gameLocal.FindEntityDef( weapon_classname, false );
1061  if ( !decl ) {
1062  gameLocal.Error( "Unknown weapon in decl '%s'", weapon_classname );
1063  }
1064  int minclip = decl->dict.GetInt("minclipsize");
1065  if(!minclip) {
1066  return false;
1067  }
1068 
1069  ammo_t ammo_i = AmmoIndexForAmmoClass( decl->dict.GetString( "ammoType" ) );
1070  int ammoRequired = decl->dict.GetInt( "ammoRequired" );
1071  int ammoCount = HasAmmo( ammo_i, ammoRequired );
1072  if(ammoCount < minclip) {
1073  return true;
1074  }
1075  return false;
1076 }
1077 #endif
1078 
1079 /*
1080 ===============
1081 idInventory::UseAmmo
1082 ===============
1083 */
1084 bool idInventory::UseAmmo( ammo_t type, int amount ) {
1085  if ( !HasAmmo( type, amount ) ) {
1086  return false;
1087  }
1088 
1089  // take an ammo away if not infinite
1090  if ( ammo[ type ] >= 0 ) {
1091  ammo[ type ] -= amount;
1092  ammoPredictTime = gameLocal.time; // mp client: we predict this. mark time so we're not confused by snapshots
1093  }
1094 
1095  return true;
1096 }
1097 
1098 /*
1099 ===============
1100 idInventory::UpdateArmor
1101 ===============
1102 */
1103 void idInventory::UpdateArmor( void ) {
1104  if ( deplete_armor != 0.0f && deplete_armor < armor ) {
1105  if ( !nextArmorDepleteTime ) {
1107  } else if ( gameLocal.time > nextArmorDepleteTime ) {
1109  if ( armor < deplete_armor ) {
1110  armor = deplete_armor;
1111  }
1113  }
1114  }
1115 }
1116 
1117 #ifdef _D3XP
1118 /*
1119 ===============
1120 idInventory::InitRechargeAmmo
1121 ===============
1122 * Loads any recharge ammo definitions from the ammo_types entity definitions.
1123 */
1124 void idInventory::InitRechargeAmmo(idPlayer *owner) {
1125 
1126  memset (rechargeAmmo, 0, sizeof(rechargeAmmo));
1127 
1128  const idKeyValue *kv = owner->spawnArgs.MatchPrefix( "ammorecharge_" );
1129  while( kv ) {
1130  idStr key = kv->GetKey();
1131  idStr ammoname = key.Right(key.Length()- strlen("ammorecharge_"));
1132  int ammoType = AmmoIndexForAmmoClass(ammoname);
1133  rechargeAmmo[ammoType].ammo = (atof(kv->GetValue().c_str())*1000);
1134  strcpy(rechargeAmmo[ammoType].ammoName, ammoname);
1135  kv = owner->spawnArgs.MatchPrefix( "ammorecharge_", kv );
1136  }
1137 }
1138 
1139 /*
1140 ===============
1141 idInventory::RechargeAmmo
1142 ===============
1143 * Called once per frame to update any ammo amount for ammo types that recharge.
1144 */
1145 void idInventory::RechargeAmmo(idPlayer *owner) {
1146 
1147  for(int i = 0; i < AMMO_NUMTYPES; i++) {
1148  if(rechargeAmmo[i].ammo > 0) {
1149  if(!rechargeAmmo[i].rechargeTime) {
1150  //Initialize the recharge timer.
1151  rechargeAmmo[i].rechargeTime = gameLocal.time;
1152  }
1153  int elapsed = gameLocal.time - rechargeAmmo[i].rechargeTime;
1154  if(elapsed >= rechargeAmmo[i].ammo) {
1155  int intervals = (gameLocal.time - rechargeAmmo[i].rechargeTime)/rechargeAmmo[i].ammo;
1156  ammo[i] += intervals;
1157 
1158  int max = MaxAmmoForAmmoClass(owner, rechargeAmmo[i].ammoName);
1159  if(max > 0) {
1160  if(ammo[i] > max) {
1161  ammo[i] = max;
1162  }
1163  }
1164  rechargeAmmo[i].rechargeTime += intervals*rechargeAmmo[i].ammo;
1165  }
1166  }
1167  }
1168 }
1169 
1170 /*
1171 ===============
1172 idInventory::CanGive
1173 ===============
1174 */
1175 bool idInventory::CanGive( idPlayer *owner, const idDict &spawnArgs, const char *statname, const char *value, int *idealWeapon ) {
1176 
1177  if ( !idStr::Icmp( statname, "ammo_bloodstone" ) ) {
1178  int max = MaxAmmoForAmmoClass(owner, statname);
1179  int i = AmmoIndexForAmmoClass(statname);
1180 
1181  if(max <= 0) {
1182  //No Max
1183  return true;
1184  } else {
1185  //Already at or above the max so don't allow the give
1186  if(ammo[ i ] >= max) {
1187  ammo[ i ] = max;
1188  return false;
1189  }
1190  return true;
1191  }
1192  } else if ( !idStr::Icmp( statname, "item" ) || !idStr::Icmp( statname, "icon" ) || !idStr::Icmp( statname, "name" ) ) {
1193  // ignore these as they're handled elsewhere
1194  //These items should not be considered as succesful gives because it messes up the max ammo items
1195  return false;
1196  }
1197  return true;
1198 }
1199 #endif
1200 
1201 /*
1202 ==============
1203 idPlayer::idPlayer
1204 ==============
1205 */
1207  memset( &usercmd, 0, sizeof( usercmd ) );
1208 
1209  noclip = false;
1210  godmode = false;
1211 
1212  spawnAnglesSet = false;
1214  viewAngles = ang_zero;
1215  cmdAngles = ang_zero;
1216 
1217  oldButtons = 0;
1218  buttonMask = 0;
1219  oldFlags = 0;
1220 
1221  lastHitTime = 0;
1222  lastSndHitTime = 0;
1223  lastSavingThrowTime = 0;
1224 
1225  weapon = NULL;
1226 
1227  hud = NULL;
1229  objectiveSystemOpen = false;
1230 
1231 #ifdef _D3XP
1232  mountedObject = NULL;
1233  enviroSuitLight = NULL;
1234 #endif
1235 
1237  heartInfo.Init( 0, 0, 0, 0 );
1238  lastHeartAdjust = 0;
1239  lastHeartBeat = 0;
1240  lastDmgTime = 0;
1242  lastArmorPulse = -10000;
1243  stamina = 0.0f;
1244  healthPool = 0.0f;
1245  nextHealthPulse = 0;
1246  healthPulse = false;
1247  nextHealthTake = 0;
1248  healthTake = false;
1249 
1250  scoreBoardOpen = false;
1251  forceScoreBoard = false;
1252  forceRespawn = false;
1253  spectating = false;
1254  spectator = 0;
1255  colorBar = vec3_zero;
1256  colorBarIndex = 0;
1257  forcedReady = false;
1258  wantSpectate = false;
1259 
1260 #ifdef CTF
1261  carryingFlag = false;
1262 #endif
1263 
1264  lastHitToggle = false;
1265 
1266  minRespawnTime = 0;
1267  maxRespawnTime = 0;
1268 
1271 
1275 
1276  bobFoot = 0;
1277  bobFrac = 0.0f;
1278  bobfracsin = 0.0f;
1279  bobCycle = 0;
1280  xyspeed = 0.0f;
1281  stepUpTime = 0;
1282  stepUpDelta = 0.0f;
1283  idealLegsYaw = 0.0f;
1284  legsYaw = 0.0f;
1285  legsForward = true;
1286  oldViewYaw = 0.0f;
1288  viewBob = vec3_zero;
1289  landChange = 0;
1290  landTime = 0;
1291 
1292  currentWeapon = -1;
1293  idealWeapon = -1;
1294  previousWeapon = -1;
1295  weaponSwitchTime = 0;
1296  weaponEnabled = true;
1297  weapon_soulcube = -1;
1298  weapon_pda = -1;
1299  weapon_fists = -1;
1300 #ifdef _D3XP
1301  weapon_bloodstone = -1;
1302  weapon_bloodstone_active1 = -1;
1303  weapon_bloodstone_active2 = -1;
1304  weapon_bloodstone_active3 = -1;
1305  harvest_lock = false;
1306 
1307  hudPowerup = -1;
1308  lastHudPowerup = -1;
1309  hudPowerupDuration = 0;
1310 #endif
1311  showWeaponViewModel = true;
1312 
1313  skin = NULL;
1314  powerUpSkin = NULL;
1315  baseSkinName = "";
1316 
1317  numProjectilesFired = 0;
1318  numProjectileHits = 0;
1319 
1320  airless = false;
1321  airTics = 0;
1322  lastAirDamage = 0;
1323 
1324  gibDeath = false;
1325  gibsLaunched = false;
1326  gibsDir = vec3_zero;
1327 
1328  zoomFov.Init( 0, 0, 0, 0 );
1329  centerView.Init( 0, 0, 0, 0 );
1330  fxFov = false;
1331 
1332  influenceFov = 0;
1333  influenceActive = 0;
1334  influenceRadius = 0.0f;
1337  influenceSkin = NULL;
1338 
1340 
1341  memset( loggedViewAngles, 0, sizeof( loggedViewAngles ) );
1342  memset( loggedAccel, 0, sizeof( loggedAccel ) );
1343  currentLoggedAccel = 0;
1344 
1345  focusTime = 0;
1346  focusGUIent = NULL;
1347  focusUI = NULL;
1348  focusCharacter = NULL;
1349  talkCursor = 0;
1350  focusVehicle = NULL;
1351  cursor = NULL;
1352 
1353  oldMouseX = 0;
1354  oldMouseY = 0;
1355 
1356  pdaAudio = "";
1357  pdaVideo = "";
1358  pdaVideoWave = "";
1359 
1360  lastDamageDef = 0;
1362  lastDamageLocation = 0;
1363  smoothedFrame = 0;
1364  smoothedOriginUpdated = false;
1367 
1368  fl.networkSync = true;
1369 
1370  latchedTeam = -1;
1371  doingDeathSkin = false;
1372  weaponGone = false;
1373  useInitialSpawns = false;
1374  tourneyRank = 0;
1376  tourneyLine = 0;
1377  hiddenWeapon = false;
1378  tipUp = false;
1379  objectiveUp = false;
1380  teleportEntity = NULL;
1381  teleportKiller = -1;
1382  respawning = false;
1383  ready = false;
1384  leader = false;
1385  lastSpectateChange = 0;
1386  lastTeleFX = -9999;
1387  weaponCatchup = false;
1389 
1390  MPAim = -1;
1391  lastMPAim = -1;
1392  lastMPAimTime = 0;
1393  MPAimFadeTime = 0;
1394  MPAimHighlight = false;
1395 
1396  spawnedTime = 0;
1397  lastManOver = false;
1398  lastManPlayAgain = false;
1399  lastManPresent = false;
1400 
1401  isTelefragged = false;
1402 
1403  isLagged = false;
1404  isChatting = false;
1405 
1406  selfSmooth = false;
1407 }
1408 
1409 /*
1410 ==============
1411 idPlayer::LinkScriptVariables
1412 
1413 set up conditions for animation
1414 ==============
1415 */
1416 void idPlayer::LinkScriptVariables( void ) {
1417  AI_FORWARD.LinkTo( scriptObject, "AI_FORWARD" );
1418  AI_BACKWARD.LinkTo( scriptObject, "AI_BACKWARD" );
1419  AI_STRAFE_LEFT.LinkTo( scriptObject, "AI_STRAFE_LEFT" );
1420  AI_STRAFE_RIGHT.LinkTo( scriptObject, "AI_STRAFE_RIGHT" );
1421  AI_ATTACK_HELD.LinkTo( scriptObject, "AI_ATTACK_HELD" );
1422  AI_WEAPON_FIRED.LinkTo( scriptObject, "AI_WEAPON_FIRED" );
1423  AI_JUMP.LinkTo( scriptObject, "AI_JUMP" );
1424  AI_DEAD.LinkTo( scriptObject, "AI_DEAD" );
1425  AI_CROUCH.LinkTo( scriptObject, "AI_CROUCH" );
1426  AI_ONGROUND.LinkTo( scriptObject, "AI_ONGROUND" );
1427  AI_ONLADDER.LinkTo( scriptObject, "AI_ONLADDER" );
1428  AI_HARDLANDING.LinkTo( scriptObject, "AI_HARDLANDING" );
1429  AI_SOFTLANDING.LinkTo( scriptObject, "AI_SOFTLANDING" );
1430  AI_RUN.LinkTo( scriptObject, "AI_RUN" );
1431  AI_PAIN.LinkTo( scriptObject, "AI_PAIN" );
1432  AI_RELOAD.LinkTo( scriptObject, "AI_RELOAD" );
1433  AI_TELEPORT.LinkTo( scriptObject, "AI_TELEPORT" );
1434  AI_TURN_LEFT.LinkTo( scriptObject, "AI_TURN_LEFT" );
1435  AI_TURN_RIGHT.LinkTo( scriptObject, "AI_TURN_RIGHT" );
1436 }
1437 
1438 /*
1439 ==============
1440 idPlayer::SetupWeaponEntity
1441 ==============
1442 */
1443 void idPlayer::SetupWeaponEntity( void ) {
1444  int w;
1445  const char *weap;
1446 
1447  if ( weapon.GetEntity() ) {
1448  // get rid of old weapon
1449  weapon.GetEntity()->Clear();
1450  currentWeapon = -1;
1451  } else if ( !gameLocal.isClient ) {
1452  weapon = static_cast<idWeapon *>( gameLocal.SpawnEntityType( idWeapon::Type, NULL ) );
1453  weapon.GetEntity()->SetOwner( this );
1454  currentWeapon = -1;
1455  }
1456 
1457  for( w = 0; w < MAX_WEAPONS; w++ ) {
1458  weap = spawnArgs.GetString( va( "def_weapon%d", w ) );
1459  if ( weap && *weap ) {
1460  idWeapon::CacheWeapon( weap );
1461  }
1462  }
1463 }
1464 
1465 /*
1466 ==============
1467 idPlayer::Init
1468 ==============
1469 */
1470 void idPlayer::Init( void ) {
1471  const char *value;
1472  const idKeyValue *kv;
1473 
1474  noclip = false;
1475  godmode = false;
1476 
1477  oldButtons = 0;
1478  oldFlags = 0;
1479 
1480  currentWeapon = -1;
1481  idealWeapon = -1;
1482  previousWeapon = -1;
1483  weaponSwitchTime = 0;
1484  weaponEnabled = true;
1485  weapon_soulcube = SlotForWeapon( "weapon_soulcube" );
1486  weapon_pda = SlotForWeapon( "weapon_pda" );
1487  weapon_fists = SlotForWeapon( "weapon_fists" );
1488 #ifdef _D3XP
1489  weapon_bloodstone = SlotForWeapon( "weapon_bloodstone_passive" );
1490  weapon_bloodstone_active1 = SlotForWeapon( "weapon_bloodstone_active1" );
1491  weapon_bloodstone_active2 = SlotForWeapon( "weapon_bloodstone_active2" );
1492  weapon_bloodstone_active3 = SlotForWeapon( "weapon_bloodstone_active3" );
1493  harvest_lock = false;
1494 #endif
1495  showWeaponViewModel = GetUserInfo()->GetBool( "ui_showGun" );
1496 
1497 
1498  lastDmgTime = 0;
1499  lastArmorPulse = -10000;
1500  lastHeartAdjust = 0;
1501  lastHeartBeat = 0;
1502  heartInfo.Init( 0, 0, 0, 0 );
1503 
1504  bobCycle = 0;
1505  bobFrac = 0.0f;
1506  landChange = 0;
1507  landTime = 0;
1508  zoomFov.Init( 0, 0, 0, 0 );
1509  centerView.Init( 0, 0, 0, 0 );
1510  fxFov = false;
1511 
1512  influenceFov = 0;
1513  influenceActive = 0;
1514  influenceRadius = 0.0f;
1517  influenceSkin = NULL;
1518 
1519 #ifdef _D3XP
1520  mountedObject = NULL;
1521  if( enviroSuitLight.IsValid() ) {
1522  enviroSuitLight.GetEntity()->PostEventMS( &EV_Remove, 0 );
1523  }
1524  enviroSuitLight = NULL;
1525  healthRecharge = false;
1526  lastHealthRechargeTime = 0;
1527  rechargeSpeed = 500;
1528  new_g_damageScale = 1.f;
1529  bloomEnabled = false;
1530  bloomSpeed = 1.f;
1531  bloomIntensity = -0.01f;
1532  inventory.InitRechargeAmmo(this);
1533  hudPowerup = -1;
1534  lastHudPowerup = -1;
1535  hudPowerupDuration = 0;
1536 #endif
1537 
1538  currentLoggedAccel = 0;
1539 
1540  focusTime = 0;
1541  focusGUIent = NULL;
1542  focusUI = NULL;
1543  focusCharacter = NULL;
1544  talkCursor = 0;
1545  focusVehicle = NULL;
1546 
1547  // remove any damage effects
1549 
1550  // damage values
1551  fl.takedamage = true;
1552  ClearPain();
1553 
1554  // restore persistent data
1556 
1557  bobCycle = 0;
1558  stamina = 0.0f;
1559  healthPool = 0.0f;
1560  nextHealthPulse = 0;
1561  healthPulse = false;
1562  nextHealthTake = 0;
1563  healthTake = false;
1564 
1566  currentWeapon = -1;
1567  previousWeapon = -1;
1568 
1570  AdjustHeartRate( BASE_HEARTRATE, 0.0f, 0.0f, true );
1571 
1572  idealLegsYaw = 0.0f;
1573  legsYaw = 0.0f;
1574  legsForward = true;
1575  oldViewYaw = 0.0f;
1576 
1577  // set the pm_ cvars
1579  kv = spawnArgs.MatchPrefix( "pm_", NULL );
1580  while( kv ) {
1581  cvarSystem->SetCVarString( kv->GetKey(), kv->GetValue() );
1582  kv = spawnArgs.MatchPrefix( "pm_", kv );
1583  }
1584  }
1585 
1586  // disable stamina on hell levels
1587  if ( gameLocal.world && gameLocal.world->spawnArgs.GetBool( "no_stamina" ) ) {
1588  pm_stamina.SetFloat( 0.0f );
1589  }
1590 
1591  // stamina always initialized to maximum
1593 
1594  // air always initialized to maximum too
1596  airless = false;
1597 
1598  gibDeath = false;
1599  gibsLaunched = false;
1600  gibsDir.Zero();
1601 
1602  // set the gravity
1604 
1605  // start out standing
1607 
1608  stepUpTime = 0;
1609  stepUpDelta = 0.0f;
1610  viewBobAngles.Zero();
1611  viewBob.Zero();
1612 
1613  value = spawnArgs.GetString( "model" );
1614  if ( value && ( *value != 0 ) ) {
1615  SetModel( value );
1616  }
1617 
1618  if ( cursor ) {
1619  cursor->SetStateInt( "talkcursor", 0 );
1620  cursor->SetStateString( "combatcursor", "1" );
1621  cursor->SetStateString( "itemcursor", "0" );
1622  cursor->SetStateString( "guicursor", "0" );
1623 #ifdef _D3XP
1624  cursor->SetStateString( "grabbercursor", "0" );
1625 #endif
1626  }
1627 
1628  if ( ( gameLocal.isMultiplayer || g_testDeath.GetBool() ) && skin ) {
1629  SetSkin( skin );
1630  renderEntity.shaderParms[6] = 0.0f;
1631  } else if ( spawnArgs.GetString( "spawn_skin", NULL, &value ) ) {
1632  skin = declManager->FindSkin( value );
1633  SetSkin( skin );
1634  renderEntity.shaderParms[6] = 0.0f;
1635  }
1636 
1637  value = spawnArgs.GetString( "bone_hips", "" );
1638  hipJoint = animator.GetJointHandle( value );
1639  if ( hipJoint == INVALID_JOINT ) {
1640  gameLocal.Error( "Joint '%s' not found for 'bone_hips' on '%s'", value, name.c_str() );
1641  }
1642 
1643  value = spawnArgs.GetString( "bone_chest", "" );
1644  chestJoint = animator.GetJointHandle( value );
1645  if ( chestJoint == INVALID_JOINT ) {
1646  gameLocal.Error( "Joint '%s' not found for 'bone_chest' on '%s'", value, name.c_str() );
1647  }
1648 
1649  value = spawnArgs.GetString( "bone_head", "" );
1650  headJoint = animator.GetJointHandle( value );
1651  if ( headJoint == INVALID_JOINT ) {
1652  gameLocal.Error( "Joint '%s' not found for 'bone_head' on '%s'", value, name.c_str() );
1653  }
1654 
1655  // initialize the script variables
1656  AI_FORWARD = false;
1657  AI_BACKWARD = false;
1658  AI_STRAFE_LEFT = false;
1659  AI_STRAFE_RIGHT = false;
1660  AI_ATTACK_HELD = false;
1661  AI_WEAPON_FIRED = false;
1662  AI_JUMP = false;
1663  AI_DEAD = false;
1664  AI_CROUCH = false;
1665  AI_ONGROUND = true;
1666  AI_ONLADDER = false;
1667  AI_HARDLANDING = false;
1668  AI_SOFTLANDING = false;
1669  AI_RUN = false;
1670  AI_PAIN = false;
1671  AI_RELOAD = false;
1672  AI_TELEPORT = false;
1673  AI_TURN_LEFT = false;
1674  AI_TURN_RIGHT = false;
1675 
1676  // reset the script object
1678 
1679  // execute the script so the script object's constructor takes effect immediately
1680  scriptThread->Execute();
1681 
1682  forceScoreBoard = false;
1683  forcedReady = false;
1684 
1686 
1687  lastSpectateChange = 0;
1688  lastTeleFX = -9999;
1689 
1690  hiddenWeapon = false;
1691  tipUp = false;
1692  objectiveUp = false;
1693  teleportEntity = NULL;
1694  teleportKiller = -1;
1695  leader = false;
1696 
1698 
1700 
1701  MPAim = -1;
1702  lastMPAim = -1;
1703  lastMPAimTime = 0;
1704  MPAimFadeTime = 0;
1705  MPAimHighlight = false;
1706 
1707  if ( hud ) {
1708  hud->HandleNamedEvent( "aim_clear" );
1709  }
1710 
1711  //isChatting = false;
1712  cvarSystem->SetCVarBool("ui_chat", false);
1713 }
1714 
1715 /*
1716 ==============
1717 idPlayer::Spawn
1718 
1719 Prepare any resources used by the player.
1720 ==============
1721 */
1722 void idPlayer::Spawn( void ) {
1723  idStr temp;
1724  idBounds bounds;
1725 
1726  if ( entityNumber >= MAX_CLIENTS ) {
1727  gameLocal.Error( "entityNum > MAX_CLIENTS for player. Player may only be spawned with a client." );
1728  }
1729 
1730  // allow thinking during cinematics
1731  cinematic = true;
1732 
1733  if ( gameLocal.isMultiplayer ) {
1734  // always start in spectating state waiting to be spawned in
1735  // do this before SetClipModel to get the right bounding box
1736  spectating = true;
1737  }
1738 
1739  // set our collision model
1740  physicsObj.SetSelf( this );
1741  SetClipModel();
1742  physicsObj.SetMass( spawnArgs.GetFloat( "mass", "100" ) );
1745  SetPhysics( &physicsObj );
1746  InitAASLocation();
1747 
1749 
1750  // only the local player needs guis
1752 
1753  // load HUD
1754  if ( gameLocal.isMultiplayer ) {
1755  hud = uiManager->FindGui( "guis/mphud.gui", true, false, true );
1756  } else if ( spawnArgs.GetString( "hud", "", temp ) ) {
1757  hud = uiManager->FindGui( temp, true, false, true );
1758  }
1759  if ( hud ) {
1760  hud->Activate( true, gameLocal.time );
1761 #ifdef CTF
1763  hud->SetStateInt( "red_team_score", gameLocal.mpGame.GetFlagPoints(0) );
1764  hud->SetStateInt( "blue_team_score", gameLocal.mpGame.GetFlagPoints(1) );
1765  }
1766 #endif
1767  }
1768 
1769  // load cursor
1770  if ( spawnArgs.GetString( "cursor", "", temp ) ) {
1772  }
1773  if ( cursor ) {
1774  cursor->Activate( true, gameLocal.time );
1775  }
1776 
1777  objectiveSystem = uiManager->FindGui( "guis/pda.gui", true, false, true );
1778  objectiveSystemOpen = false;
1779  }
1780 
1781  SetLastHitTime( 0 );
1782 
1783  // load the armor sound feedback
1784  declManager->FindSound( "player_sounds_hitArmor" );
1785 
1786  // set up conditions for animation
1788 
1789  animator.RemoveOriginOffset( true );
1790 
1791  // initialize user info related settings
1792  // on server, we wait for the userinfo broadcast, as this controls when the player is initially spawned in game
1794  UserInfoChanged( false );
1795  }
1796 
1797  // create combat collision hull for exact collision detection
1798  SetCombatModel();
1799 
1800  // init the damage effects
1801  playerView.SetPlayerEntity( this );
1802 
1803  // supress model in non-player views, but allow it in mirrors and remote views
1805 
1806  // don't project shadow on self or weapon
1807  renderEntity.noSelfShadow = true;
1808 
1809  idAFAttachment *headEnt = head.GetEntity();
1810  if ( headEnt ) {
1812  headEnt->GetRenderEntity()->noSelfShadow = true;
1813  }
1814 
1815  if ( gameLocal.isMultiplayer ) {
1816  Init();
1817  Hide(); // properly hidden if starting as a spectator
1818  if ( !gameLocal.isClient ) {
1819  // set yourself ready to spawn. idMultiplayerGame will decide when/if appropriate and call SpawnFromSpawnSpot
1822  forceRespawn = true;
1823  assert( spectating );
1824  }
1825  } else {
1828  }
1829 
1830  // trigger playtesting item gives, if we didn't get here from a previous level
1831  // the devmap key will be set on the first devmap, but cleared on any level
1832  // transitions
1833  if ( !gameLocal.isMultiplayer && gameLocal.serverInfo.FindKey( "devmap" ) ) {
1834  // fire a trigger with the name "devmap"
1835  idEntity *ent = gameLocal.FindEntity( "devmap" );
1836  if ( ent ) {
1837  ent->ActivateTargets( this );
1838  }
1839  }
1840  if ( hud ) {
1841  // We can spawn with a full soul cube, so we need to make sure the hud knows this
1842 #ifndef _D3XP
1843  if ( weapon_soulcube > 0 && ( inventory.weapons & ( 1 << weapon_soulcube ) ) ) {
1844  int max_souls = inventory.MaxAmmoForAmmoClass( this, "ammo_souls" );
1845  if ( inventory.ammo[ idWeapon::GetAmmoNumForName( "ammo_souls" ) ] >= max_souls ) {
1846  hud->HandleNamedEvent( "soulCubeReady" );
1847  }
1848  }
1849 #endif
1850 #ifdef _D3XP
1851  //We can spawn with a full bloodstone, so make sure the hud knows
1852  if ( weapon_bloodstone > 0 && ( inventory.weapons & ( 1 << weapon_bloodstone ) ) ) {
1853  //int max_blood = inventory.MaxAmmoForAmmoClass( this, "ammo_bloodstone" );
1854  //if ( inventory.ammo[ idWeapon::GetAmmoNumForName( "ammo_bloodstone" ) ] >= max_blood ) {
1855  hud->HandleNamedEvent( "bloodstoneReady" );
1856  //}
1857  }
1858 #endif
1859  hud->HandleNamedEvent( "itemPickup" );
1860  }
1861 
1862  if ( GetPDA() ) {
1863  // Add any emails from the inventory
1864  for ( int i = 0; i < inventory.emails.Num(); i++ ) {
1865  GetPDA()->AddEmail( inventory.emails[i] );
1866  }
1867  GetPDA()->SetSecurity( common->GetLanguageDict()->GetString( "#str_00066" ) );
1868  }
1869 
1870  if ( gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) ) {
1871  hiddenWeapon = true;
1872  if ( weapon.GetEntity() ) {
1874  }
1875  idealWeapon = 0;
1876  } else {
1877  hiddenWeapon = false;
1878  }
1879 
1880  if ( hud ) {
1881  UpdateHudWeapon();
1883  }
1884 
1885  tipUp = false;
1886  objectiveUp = false;
1887 
1888  if ( inventory.levelTriggers.Num() ) {
1889  PostEventMS( &EV_Player_LevelTrigger, 0 );
1890  }
1891 
1892  inventory.pdaOpened = false;
1893  inventory.selPDA = 0;
1894 
1895  if ( !gameLocal.isMultiplayer ) {
1896  if ( g_skill.GetInteger() < 2 ) {
1897  if ( health < 25 ) {
1898  health = 25;
1899  }
1900  if ( g_useDynamicProtection.GetBool() ) {
1901 #ifdef _D3XP
1902  new_g_damageScale = 1.0f;
1903 #else
1904  g_damageScale.SetFloat( 1.0f );
1905 #endif
1906  }
1907  } else {
1908 #ifdef _D3XP
1909  new_g_damageScale = 1.0f;
1910 #else
1911  g_damageScale.SetFloat( 1.0f );
1912 #endif
1913  g_armorProtection.SetFloat( ( g_skill.GetInteger() < 2 ) ? 0.4f : 0.2f );
1914 #ifndef ID_DEMO_BUILD
1915  if ( g_skill.GetInteger() == 3 ) {
1916  healthTake = true;
1918  }
1919 #endif
1920  }
1921  }
1922 
1923 #ifdef _D3XP
1924  //Setup the weapon toggle lists
1925  const idKeyValue *kv;
1926  kv = spawnArgs.MatchPrefix( "weapontoggle", NULL );
1927  while( kv ) {
1928  WeaponToggle_t newToggle;
1929  strcpy(newToggle.name, kv->GetKey().c_str());
1930 
1931  idStr toggleData = kv->GetValue();
1932 
1933  idLexer src;
1934  idToken token;
1935  src.LoadMemory(toggleData, toggleData.Length(), "toggleData");
1936  while(1) {
1937  if(!src.ReadToken(&token)) {
1938  break;
1939  }
1940  int index = atoi(token.c_str());
1941  newToggle.toggleList.Append(index);
1942 
1943  //Skip the ,
1944  src.ReadToken(&token);
1945  }
1946  weaponToggles.Set(newToggle.name, newToggle);
1947 
1948  kv = spawnArgs.MatchPrefix( "weapontoggle", kv );
1949  }
1950 #endif
1951 
1952 #ifdef _D3XP
1953  if(g_skill.GetInteger() >= 3) {
1954  if(!WeaponAvailable("weapon_bloodstone_passive")) {
1955  GiveInventoryItem("weapon_bloodstone_passive");
1956  }
1957  if(!WeaponAvailable("weapon_bloodstone_active1")) {
1958  GiveInventoryItem("weapon_bloodstone_active1");
1959  }
1960  if(!WeaponAvailable("weapon_bloodstone_active2")) {
1961  GiveInventoryItem("weapon_bloodstone_active2");
1962  }
1963  if(!WeaponAvailable("weapon_bloodstone_active3")) {
1964  GiveInventoryItem("weapon_bloodstone_active3");
1965  }
1966  }
1967 
1968  bloomEnabled = false;
1969  bloomSpeed = 1;
1970  bloomIntensity = -0.01f;
1971 #endif
1972 }
1973 
1974 /*
1975 ==============
1976 idPlayer::~idPlayer()
1977 
1978 Release any resources used by the player.
1979 ==============
1980 */
1982  delete weapon.GetEntity();
1983  weapon = NULL;
1984 #ifdef CTF
1985  if ( enviroSuitLight.IsValid() ) {
1986  enviroSuitLight.GetEntity()->ProcessEvent( &EV_Remove );
1987  }
1988  // have to do this here, idMultiplayerGame::DisconnectClient() is too late
1990  ReturnFlag();
1991  }
1992 #endif
1993 }
1994 
1995 /*
1996 ===========
1997 idPlayer::Save
1998 ===========
1999 */
2000 void idPlayer::Save( idSaveGame *savefile ) const {
2001  int i;
2002 
2003  savefile->WriteUsercmd( usercmd );
2004  playerView.Save( savefile );
2005 
2006  savefile->WriteBool( noclip );
2007  savefile->WriteBool( godmode );
2008 
2009  // don't save spawnAnglesSet, since we'll have to reset them after loading the savegame
2010  savefile->WriteAngles( spawnAngles );
2011  savefile->WriteAngles( viewAngles );
2012  savefile->WriteAngles( cmdAngles );
2013 
2014  savefile->WriteInt( buttonMask );
2015  savefile->WriteInt( oldButtons );
2016  savefile->WriteInt( oldFlags );
2017 
2018  savefile->WriteInt( lastHitTime );
2019  savefile->WriteInt( lastSndHitTime );
2020  savefile->WriteInt( lastSavingThrowTime );
2021 
2022  // idBoolFields don't need to be saved, just re-linked in Restore
2023 
2024  inventory.Save( savefile );
2025  weapon.Save( savefile );
2026 
2027  savefile->WriteUserInterface( hud, false );
2028  savefile->WriteUserInterface( objectiveSystem, false );
2029  savefile->WriteBool( objectiveSystemOpen );
2030 
2031  savefile->WriteInt( weapon_soulcube );
2032  savefile->WriteInt( weapon_pda );
2033  savefile->WriteInt( weapon_fists );
2034 #ifdef _D3XP
2035  savefile->WriteInt( weapon_bloodstone );
2036  savefile->WriteInt( weapon_bloodstone_active1 );
2037  savefile->WriteInt( weapon_bloodstone_active2 );
2038  savefile->WriteInt( weapon_bloodstone_active3 );
2039  savefile->WriteBool( harvest_lock );
2040  savefile->WriteInt( hudPowerup );
2041  savefile->WriteInt( lastHudPowerup );
2042  savefile->WriteInt( hudPowerupDuration );
2043 
2044 
2045 #endif
2046 
2047  savefile->WriteInt( heartRate );
2048 
2049  savefile->WriteFloat( heartInfo.GetStartTime() );
2050  savefile->WriteFloat( heartInfo.GetDuration() );
2051  savefile->WriteFloat( heartInfo.GetStartValue() );
2052  savefile->WriteFloat( heartInfo.GetEndValue() );
2053 
2054  savefile->WriteInt( lastHeartAdjust );
2055  savefile->WriteInt( lastHeartBeat );
2056  savefile->WriteInt( lastDmgTime );
2057  savefile->WriteInt( deathClearContentsTime );
2058  savefile->WriteBool( doingDeathSkin );
2059  savefile->WriteInt( lastArmorPulse );
2060  savefile->WriteFloat( stamina );
2061  savefile->WriteFloat( healthPool );
2062  savefile->WriteInt( nextHealthPulse );
2063  savefile->WriteBool( healthPulse );
2064  savefile->WriteInt( nextHealthTake );
2065  savefile->WriteBool( healthTake );
2066 
2067  savefile->WriteBool( hiddenWeapon );
2068  soulCubeProjectile.Save( savefile );
2069 
2070  savefile->WriteInt( spectator );
2071  savefile->WriteVec3( colorBar );
2072  savefile->WriteInt( colorBarIndex );
2073  savefile->WriteBool( scoreBoardOpen );
2074  savefile->WriteBool( forceScoreBoard );
2075  savefile->WriteBool( forceRespawn );
2076  savefile->WriteBool( spectating );
2077  savefile->WriteInt( lastSpectateTeleport );
2078  savefile->WriteBool( lastHitToggle );
2079  savefile->WriteBool( forcedReady );
2080  savefile->WriteBool( wantSpectate );
2081  savefile->WriteBool( weaponGone );
2082  savefile->WriteBool( useInitialSpawns );
2083  savefile->WriteInt( latchedTeam );
2084  savefile->WriteInt( tourneyRank );
2085  savefile->WriteInt( tourneyLine );
2086 
2087  teleportEntity.Save( savefile );
2088  savefile->WriteInt( teleportKiller );
2089 
2090  savefile->WriteInt( minRespawnTime );
2091  savefile->WriteInt( maxRespawnTime );
2092 
2093  savefile->WriteVec3( firstPersonViewOrigin );
2094  savefile->WriteMat3( firstPersonViewAxis );
2095 
2096  // don't bother saving dragEntity since it's a dev tool
2097 
2098  savefile->WriteJoint( hipJoint );
2099  savefile->WriteJoint( chestJoint );
2100  savefile->WriteJoint( headJoint );
2101 
2102  savefile->WriteStaticObject( physicsObj );
2103 
2104  savefile->WriteInt( aasLocation.Num() );
2105  for( i = 0; i < aasLocation.Num(); i++ ) {
2106  savefile->WriteInt( aasLocation[ i ].areaNum );
2107  savefile->WriteVec3( aasLocation[ i ].pos );
2108  }
2109 
2110  savefile->WriteInt( bobFoot );
2111  savefile->WriteFloat( bobFrac );
2112  savefile->WriteFloat( bobfracsin );
2113  savefile->WriteInt( bobCycle );
2114  savefile->WriteFloat( xyspeed );
2115  savefile->WriteInt( stepUpTime );
2116  savefile->WriteFloat( stepUpDelta );
2117  savefile->WriteFloat( idealLegsYaw );
2118  savefile->WriteFloat( legsYaw );
2119  savefile->WriteBool( legsForward );
2120  savefile->WriteFloat( oldViewYaw );
2121  savefile->WriteAngles( viewBobAngles );
2122  savefile->WriteVec3( viewBob );
2123  savefile->WriteInt( landChange );
2124  savefile->WriteInt( landTime );
2125 
2126  savefile->WriteInt( currentWeapon );
2127  savefile->WriteInt( idealWeapon );
2128  savefile->WriteInt( previousWeapon );
2129  savefile->WriteInt( weaponSwitchTime );
2130  savefile->WriteBool( weaponEnabled );
2131  savefile->WriteBool( showWeaponViewModel );
2132 
2133  savefile->WriteSkin( skin );
2134  savefile->WriteSkin( powerUpSkin );
2135  savefile->WriteString( baseSkinName );
2136 
2137  savefile->WriteInt( numProjectilesFired );
2138  savefile->WriteInt( numProjectileHits );
2139 
2140  savefile->WriteBool( airless );
2141  savefile->WriteInt( airTics );
2142  savefile->WriteInt( lastAirDamage );
2143 
2144  savefile->WriteBool( gibDeath );
2145  savefile->WriteBool( gibsLaunched );
2146  savefile->WriteVec3( gibsDir );
2147 
2148  savefile->WriteFloat( zoomFov.GetStartTime() );
2149  savefile->WriteFloat( zoomFov.GetDuration() );
2150  savefile->WriteFloat( zoomFov.GetStartValue() );
2151  savefile->WriteFloat( zoomFov.GetEndValue() );
2152 
2153  savefile->WriteFloat( centerView.GetStartTime() );
2154  savefile->WriteFloat( centerView.GetDuration() );
2155  savefile->WriteFloat( centerView.GetStartValue() );
2156  savefile->WriteFloat( centerView.GetEndValue() );
2157 
2158  savefile->WriteBool( fxFov );
2159 
2160  savefile->WriteFloat( influenceFov );
2161  savefile->WriteInt( influenceActive );
2162  savefile->WriteFloat( influenceRadius );
2163  savefile->WriteObject( influenceEntity );
2164  savefile->WriteMaterial( influenceMaterial );
2165  savefile->WriteSkin( influenceSkin );
2166 
2167  savefile->WriteObject( privateCameraView );
2168 
2169  for( i = 0; i < NUM_LOGGED_VIEW_ANGLES; i++ ) {
2170  savefile->WriteAngles( loggedViewAngles[ i ] );
2171  }
2172  for( i = 0; i < NUM_LOGGED_ACCELS; i++ ) {
2173  savefile->WriteInt( loggedAccel[ i ].time );
2174  savefile->WriteVec3( loggedAccel[ i ].dir );
2175  }
2176  savefile->WriteInt( currentLoggedAccel );
2177 
2178  savefile->WriteObject( focusGUIent );
2179  // can't save focusUI
2180  savefile->WriteObject( focusCharacter );
2181  savefile->WriteInt( talkCursor );
2182  savefile->WriteInt( focusTime );
2183  savefile->WriteObject( focusVehicle );
2184  savefile->WriteUserInterface( cursor, false );
2185 
2186  savefile->WriteInt( oldMouseX );
2187  savefile->WriteInt( oldMouseY );
2188 
2189  savefile->WriteString( pdaAudio );
2190  savefile->WriteString( pdaVideo );
2191  savefile->WriteString( pdaVideoWave );
2192 
2193  savefile->WriteBool( tipUp );
2194  savefile->WriteBool( objectiveUp );
2195 
2196  savefile->WriteInt( lastDamageDef );
2197  savefile->WriteVec3( lastDamageDir );
2198  savefile->WriteInt( lastDamageLocation );
2199  savefile->WriteInt( smoothedFrame );
2200  savefile->WriteBool( smoothedOriginUpdated );
2201  savefile->WriteVec3( smoothedOrigin );
2202  savefile->WriteAngles( smoothedAngles );
2203 
2204  savefile->WriteBool( ready );
2205  savefile->WriteBool( respawning );
2206  savefile->WriteBool( leader );
2207  savefile->WriteInt( lastSpectateChange );
2208  savefile->WriteInt( lastTeleFX );
2209 
2210  savefile->WriteFloat( pm_stamina.GetFloat() );
2211 
2212  if ( hud ) {
2213  hud->SetStateString( "message", common->GetLanguageDict()->GetString( "#str_02916" ) );
2214  hud->HandleNamedEvent( "Message" );
2215  }
2216 
2217 #ifdef _D3XP
2218  savefile->WriteInt(weaponToggles.Num());
2219  for(i = 0; i < weaponToggles.Num(); i++) {
2220  WeaponToggle_t* weaponToggle = weaponToggles.GetIndex(i);
2221  savefile->WriteString(weaponToggle->name);
2222  savefile->WriteInt(weaponToggle->toggleList.Num());
2223  for(int j = 0; j < weaponToggle->toggleList.Num(); j++) {
2224  savefile->WriteInt(weaponToggle->toggleList[j]);
2225  }
2226  }
2227  savefile->WriteObject( mountedObject );
2228  enviroSuitLight.Save( savefile );
2229  savefile->WriteBool( healthRecharge );
2230  savefile->WriteInt( lastHealthRechargeTime );
2231  savefile->WriteInt( rechargeSpeed );
2232  savefile->WriteFloat( new_g_damageScale );
2233 
2234  savefile->WriteBool( bloomEnabled );
2235  savefile->WriteFloat( bloomSpeed );
2236  savefile->WriteFloat( bloomIntensity );
2237 
2238 #endif
2239 }
2240 
2241 /*
2242 ===========
2243 idPlayer::Restore
2244 ===========
2245 */
2246 void idPlayer::Restore( idRestoreGame *savefile ) {
2247  int i;
2248  int num;
2249  float set;
2250 
2251  savefile->ReadUsercmd( usercmd );
2252  playerView.Restore( savefile );
2253 
2254  savefile->ReadBool( noclip );
2255  savefile->ReadBool( godmode );
2256 
2257  savefile->ReadAngles( spawnAngles );
2258  savefile->ReadAngles( viewAngles );
2259  savefile->ReadAngles( cmdAngles );
2260 
2261  memset( usercmd.angles, 0, sizeof( usercmd.angles ) );
2263  spawnAnglesSet = true;
2264 
2265  savefile->ReadInt( buttonMask );
2266  savefile->ReadInt( oldButtons );
2267  savefile->ReadInt( oldFlags );
2268 
2269  usercmd.flags = 0;
2270  oldFlags = 0;
2271 
2272  savefile->ReadInt( lastHitTime );
2273  savefile->ReadInt( lastSndHitTime );
2274  savefile->ReadInt( lastSavingThrowTime );
2275 
2276  // Re-link idBoolFields to the scriptObject, values will be restored in scriptObject's restore
2278 
2279  inventory.Restore( savefile );
2280  weapon.Restore( savefile );
2281 
2282  for ( i = 0; i < inventory.emails.Num(); i++ ) {
2283  GetPDA()->AddEmail( inventory.emails[i] );
2284  }
2285 
2286  savefile->ReadUserInterface( hud );
2287  savefile->ReadUserInterface( objectiveSystem );
2288  savefile->ReadBool( objectiveSystemOpen );
2289 
2290  savefile->ReadInt( weapon_soulcube );
2291  savefile->ReadInt( weapon_pda );
2292  savefile->ReadInt( weapon_fists );
2293 #ifdef _D3XP
2294  savefile->ReadInt( weapon_bloodstone );
2295  savefile->ReadInt( weapon_bloodstone_active1 );
2296  savefile->ReadInt( weapon_bloodstone_active2 );
2297  savefile->ReadInt( weapon_bloodstone_active3 );
2298 
2299  savefile->ReadBool( harvest_lock );
2300  savefile->ReadInt( hudPowerup );
2301  savefile->ReadInt( lastHudPowerup );
2302  savefile->ReadInt( hudPowerupDuration );
2303 
2304 
2305 #endif
2306 
2307  savefile->ReadInt( heartRate );
2308 
2309  savefile->ReadFloat( set );
2310  heartInfo.SetStartTime( set );
2311  savefile->ReadFloat( set );
2312  heartInfo.SetDuration( set );
2313  savefile->ReadFloat( set );
2314  heartInfo.SetStartValue( set );
2315  savefile->ReadFloat( set );
2316  heartInfo.SetEndValue( set );
2317 
2318  savefile->ReadInt( lastHeartAdjust );
2319  savefile->ReadInt( lastHeartBeat );
2320  savefile->ReadInt( lastDmgTime );
2321  savefile->ReadInt( deathClearContentsTime );
2322  savefile->ReadBool( doingDeathSkin );
2323  savefile->ReadInt( lastArmorPulse );
2324  savefile->ReadFloat( stamina );
2325  savefile->ReadFloat( healthPool );
2326  savefile->ReadInt( nextHealthPulse );
2327  savefile->ReadBool( healthPulse );
2328  savefile->ReadInt( nextHealthTake );
2329  savefile->ReadBool( healthTake );
2330 
2331  savefile->ReadBool( hiddenWeapon );
2332  soulCubeProjectile.Restore( savefile );
2333 
2334  savefile->ReadInt( spectator );
2335  savefile->ReadVec3( colorBar );
2336  savefile->ReadInt( colorBarIndex );
2337  savefile->ReadBool( scoreBoardOpen );
2338  savefile->ReadBool( forceScoreBoard );
2339  savefile->ReadBool( forceRespawn );
2340  savefile->ReadBool( spectating );
2341  savefile->ReadInt( lastSpectateTeleport );
2342  savefile->ReadBool( lastHitToggle );
2343  savefile->ReadBool( forcedReady );
2344  savefile->ReadBool( wantSpectate );
2345  savefile->ReadBool( weaponGone );
2346  savefile->ReadBool( useInitialSpawns );
2347  savefile->ReadInt( latchedTeam );
2348  savefile->ReadInt( tourneyRank );
2349  savefile->ReadInt( tourneyLine );
2350 
2351  teleportEntity.Restore( savefile );
2352  savefile->ReadInt( teleportKiller );
2353 
2354  savefile->ReadInt( minRespawnTime );
2355  savefile->ReadInt( maxRespawnTime );
2356 
2357  savefile->ReadVec3( firstPersonViewOrigin );
2358  savefile->ReadMat3( firstPersonViewAxis );
2359 
2360  // don't bother saving dragEntity since it's a dev tool
2361  dragEntity.Clear();
2362 
2363  savefile->ReadJoint( hipJoint );
2364  savefile->ReadJoint( chestJoint );
2365  savefile->ReadJoint( headJoint );
2366 
2367  savefile->ReadStaticObject( physicsObj );
2369 
2370  savefile->ReadInt( num );
2372  aasLocation.SetNum( num );
2373  for( i = 0; i < num; i++ ) {
2374  savefile->ReadInt( aasLocation[ i ].areaNum );
2375  savefile->ReadVec3( aasLocation[ i ].pos );
2376  }
2377 
2378  savefile->ReadInt( bobFoot );
2379  savefile->ReadFloat( bobFrac );
2380  savefile->ReadFloat( bobfracsin );
2381  savefile->ReadInt( bobCycle );
2382  savefile->ReadFloat( xyspeed );
2383  savefile->ReadInt( stepUpTime );
2384  savefile->ReadFloat( stepUpDelta );
2385  savefile->ReadFloat( idealLegsYaw );
2386  savefile->ReadFloat( legsYaw );
2387  savefile->ReadBool( legsForward );
2388  savefile->ReadFloat( oldViewYaw );
2389  savefile->ReadAngles( viewBobAngles );
2390  savefile->ReadVec3( viewBob );
2391  savefile->ReadInt( landChange );
2392  savefile->ReadInt( landTime );
2393 
2394  savefile->ReadInt( currentWeapon );
2395  savefile->ReadInt( idealWeapon );
2396  savefile->ReadInt( previousWeapon );
2397  savefile->ReadInt( weaponSwitchTime );
2398  savefile->ReadBool( weaponEnabled );
2399  savefile->ReadBool( showWeaponViewModel );
2400 
2401  savefile->ReadSkin( skin );
2402  savefile->ReadSkin( powerUpSkin );
2403  savefile->ReadString( baseSkinName );
2404 
2405  savefile->ReadInt( numProjectilesFired );
2406  savefile->ReadInt( numProjectileHits );
2407 
2408  savefile->ReadBool( airless );
2409  savefile->ReadInt( airTics );
2410  savefile->ReadInt( lastAirDamage );
2411 
2412  savefile->ReadBool( gibDeath );
2413  savefile->ReadBool( gibsLaunched );
2414  savefile->ReadVec3( gibsDir );
2415 
2416  savefile->ReadFloat( set );
2417  zoomFov.SetStartTime( set );
2418  savefile->ReadFloat( set );
2419  zoomFov.SetDuration( set );
2420  savefile->ReadFloat( set );
2421  zoomFov.SetStartValue( set );
2422  savefile->ReadFloat( set );
2423  zoomFov.SetEndValue( set );
2424 
2425  savefile->ReadFloat( set );
2426  centerView.SetStartTime( set );
2427  savefile->ReadFloat( set );
2428  centerView.SetDuration( set );
2429  savefile->ReadFloat( set );
2430  centerView.SetStartValue( set );
2431  savefile->ReadFloat( set );
2432  centerView.SetEndValue( set );
2433 
2434  savefile->ReadBool( fxFov );
2435 
2436  savefile->ReadFloat( influenceFov );
2437  savefile->ReadInt( influenceActive );
2438  savefile->ReadFloat( influenceRadius );
2439  savefile->ReadObject( reinterpret_cast<idClass *&>( influenceEntity ) );
2440  savefile->ReadMaterial( influenceMaterial );
2441  savefile->ReadSkin( influenceSkin );
2442 
2443  savefile->ReadObject( reinterpret_cast<idClass *&>( privateCameraView ) );
2444 
2445  for( i = 0; i < NUM_LOGGED_VIEW_ANGLES; i++ ) {
2446  savefile->ReadAngles( loggedViewAngles[ i ] );
2447  }
2448  for( i = 0; i < NUM_LOGGED_ACCELS; i++ ) {
2449  savefile->ReadInt( loggedAccel[ i ].time );
2450  savefile->ReadVec3( loggedAccel[ i ].dir );
2451  }
2452  savefile->ReadInt( currentLoggedAccel );
2453 
2454  savefile->ReadObject( reinterpret_cast<idClass *&>( focusGUIent ) );
2455  // can't save focusUI
2456  focusUI = NULL;
2457  savefile->ReadObject( reinterpret_cast<idClass *&>( focusCharacter ) );
2458  savefile->ReadInt( talkCursor );
2459  savefile->ReadInt( focusTime );
2460  savefile->ReadObject( reinterpret_cast<idClass *&>( focusVehicle ) );
2461  savefile->ReadUserInterface( cursor );
2462 
2463  savefile->ReadInt( oldMouseX );
2464  savefile->ReadInt( oldMouseY );
2465 
2466  savefile->ReadString( pdaAudio );
2467  savefile->ReadString( pdaVideo );
2468  savefile->ReadString( pdaVideoWave );
2469 
2470  savefile->ReadBool( tipUp );
2471  savefile->ReadBool( objectiveUp );
2472 
2473  savefile->ReadInt( lastDamageDef );
2474  savefile->ReadVec3( lastDamageDir );
2475  savefile->ReadInt( lastDamageLocation );
2476  savefile->ReadInt( smoothedFrame );
2477  savefile->ReadBool( smoothedOriginUpdated );
2478  savefile->ReadVec3( smoothedOrigin );
2479  savefile->ReadAngles( smoothedAngles );
2480 
2481  savefile->ReadBool( ready );
2482  savefile->ReadBool( respawning );
2483  savefile->ReadBool( leader );
2484  savefile->ReadInt( lastSpectateChange );
2485  savefile->ReadInt( lastTeleFX );
2486 
2487  // set the pm_ cvars
2488  const idKeyValue *kv;
2489  kv = spawnArgs.MatchPrefix( "pm_", NULL );
2490  while( kv ) {
2491  cvarSystem->SetCVarString( kv->GetKey(), kv->GetValue() );
2492  kv = spawnArgs.MatchPrefix( "pm_", kv );
2493  }
2494 
2495  savefile->ReadFloat( set );
2496  pm_stamina.SetFloat( set );
2497 
2498  // create combat collision hull for exact collision detection
2499  SetCombatModel();
2500 
2501 #ifdef _D3XP
2502  int weaponToggleCount;
2503  savefile->ReadInt(weaponToggleCount);
2504  for(i = 0; i < weaponToggleCount; i++) {
2505  WeaponToggle_t newToggle;
2506  memset(&newToggle, 0, sizeof(newToggle));
2507 
2508  idStr name;
2509  savefile->ReadString(name);
2510  strcpy(newToggle.name, name.c_str());
2511 
2512  int indexCount;
2513  savefile->ReadInt(indexCount);
2514  for(int j = 0; j < indexCount; j++) {
2515  int temp;
2516  savefile->ReadInt(temp);
2517  newToggle.toggleList.Append(temp);
2518  }
2519  weaponToggles.Set(newToggle.name, newToggle);
2520  }
2521  savefile->ReadObject(reinterpret_cast<idClass *&>(mountedObject));
2522  enviroSuitLight.Restore( savefile );
2523  savefile->ReadBool( healthRecharge );
2524  savefile->ReadInt( lastHealthRechargeTime );
2525  savefile->ReadInt( rechargeSpeed );
2526  savefile->ReadFloat( new_g_damageScale );
2527 
2528  savefile->ReadBool( bloomEnabled );
2529  savefile->ReadFloat( bloomSpeed );
2530  savefile->ReadFloat( bloomIntensity );
2531 #endif
2532 }
2533 
2534 /*
2535 ===============
2536 idPlayer::PrepareForRestart
2537 ================
2538 */
2539 void idPlayer::PrepareForRestart( void ) {
2540  ClearPowerUps();
2541  Spectate( true );
2542  forceRespawn = true;
2543 
2544 #ifdef CTF
2545  // Confirm reset hud states
2546  DropFlag();
2547 
2548  if ( hud ) {
2549  hud->SetStateInt( "red_flagstatus", 0 );
2550  hud->SetStateInt( "blue_flagstatus", 0 );
2551  }
2552 #endif
2553 
2554  // we will be restarting program, clear the client entities from program-related things first
2555  ShutdownThreads();
2556 
2557  // the sound world is going to be cleared, don't keep references to emitters
2558  FreeSoundEmitter( false );
2559 }
2560 
2561 /*
2562 ===============
2563 idPlayer::Restart
2564 ================
2565 */
2566 void idPlayer::Restart( void ) {
2567  idActor::Restart();
2568 
2569  // client needs to setup the animation script object again
2570  if ( gameLocal.isClient ) {
2571  Init();
2572  } else {
2573  // choose a random spot and prepare the point of view in case player is left spectating
2574  assert( spectating );
2576  }
2577 
2578  useInitialSpawns = true;
2579  UpdateSkinSetup( true );
2580 }
2581 
2582 /*
2583 ===============
2584 idPlayer::ServerSpectate
2585 ================
2586 */
2587 void idPlayer::ServerSpectate( bool spectate ) {
2589 
2590  if ( spectating != spectate ) {
2591  Spectate( spectate );
2592  if ( spectate ) {
2594  } else {
2595  if ( gameLocal.gameType == GAME_DM ) {
2596  // make sure the scores are reset so you can't exploit by spectating and entering the game back
2597  // other game types don't matter, as you either can't join back, or it's team scores
2599  }
2600  }
2601  }
2602  if ( !spectate ) {
2604  }
2605 #ifdef CTF
2606  // drop the flag if player was carrying it
2607  if ( spectate && gameLocal.isMultiplayer && gameLocal.mpGame.IsGametypeFlagBased() &&
2608  carryingFlag )
2609  {
2610  DropFlag();
2611  }
2612 #endif
2613 }
2614 
2615 /*
2616 ===========
2617 idPlayer::SelectInitialSpawnPoint
2618 
2619 Try to find a spawn point marked 'initial', otherwise
2620 use normal spawn selection.
2621 ============
2622 */
2623 void idPlayer::SelectInitialSpawnPoint( idVec3 &origin, idAngles &angles ) {
2624  idEntity *spot;
2625  idStr skin;
2626 
2627  spot = gameLocal.SelectInitialSpawnPoint( this );
2628 
2629  // set the player skin from the spawn location
2630  if ( spot->spawnArgs.GetString( "skin", NULL, skin ) ) {
2631  spawnArgs.Set( "spawn_skin", skin );
2632  }
2633 
2634  // activate the spawn locations targets
2635  spot->PostEventMS( &EV_ActivateTargets, 0, this );
2636 
2637  origin = spot->GetPhysics()->GetOrigin();
2638  origin[2] += 4.0f + CM_BOX_EPSILON; // move up to make sure the player is at least an epsilon above the floor
2639  angles = spot->GetPhysics()->GetAxis().ToAngles();
2640 }
2641 
2642 /*
2643 ===========
2644 idPlayer::SpawnFromSpawnSpot
2645 
2646 Chooses a spawn location and spawns the player
2647 ============
2648 */
2649 void idPlayer::SpawnFromSpawnSpot( void ) {
2650  idVec3 spawn_origin;
2651  idAngles spawn_angles;
2652 
2653  SelectInitialSpawnPoint( spawn_origin, spawn_angles );
2654  SpawnToPoint( spawn_origin, spawn_angles );
2655 }
2656 
2657 /*
2658 ===========
2659 idPlayer::SpawnToPoint
2660 
2661 Called every time a client is placed fresh in the world:
2662 after the first ClientBegin, and after each respawn
2663 Initializes all non-persistant parts of playerState
2664 
2665 when called here with spectating set to true, just place yourself and init
2666 ============
2667 */
2668 void idPlayer::SpawnToPoint( const idVec3 &spawn_origin, const idAngles &spawn_angles ) {
2669  idVec3 spec_origin;
2670 
2672 
2673  respawning = true;
2674 
2675  Init();
2676 
2677  fl.noknockback = false;
2678 
2679  // stop any ragdolls being used
2680  StopRagdoll();
2681 
2682  // set back the player physics
2683  SetPhysics( &physicsObj );
2684 
2687 
2688  if ( !spectating ) {
2689  SetCombatContents( true );
2690  }
2691 
2693 
2694  // setup our initial view
2695  if ( !spectating ) {
2696  SetOrigin( spawn_origin );
2697  } else {
2698  spec_origin = spawn_origin;
2699  spec_origin[ 2 ] += pm_normalheight.GetFloat();
2700  spec_origin[ 2 ] += SPECTATE_RAISE;
2701  SetOrigin( spec_origin );
2702  }
2703 
2704  // if this is the first spawn of the map, we don't have a usercmd yet,
2705  // so the delta angles won't be correct. This will be fixed on the first think.
2706  viewAngles = ang_zero;
2708  SetViewAngles( spawn_angles );
2709  spawnAngles = spawn_angles;
2710  spawnAnglesSet = false;
2711 
2712  legsForward = true;
2713  legsYaw = 0.0f;
2714  idealLegsYaw = 0.0f;
2716 
2717  if ( spectating ) {
2718  Hide();
2719  } else {
2720  Show();
2721  }
2722 
2723  if ( gameLocal.isMultiplayer ) {
2724  if ( !spectating ) {
2725  // we may be called twice in a row in some situations. avoid a double fx and 'fly to the roof'
2726  if ( lastTeleFX < gameLocal.time - 1000 ) {
2727  idEntityFx::StartFx( spawnArgs.GetString( "fx_spawn" ), &spawn_origin, NULL, this, true );
2729  }
2730  }
2731  AI_TELEPORT = true;
2732  } else {
2733  AI_TELEPORT = false;
2734  }
2735 
2736  // kill anything at the new position
2737  if ( !spectating ) {
2738  physicsObj.SetClipMask( MASK_PLAYERSOLID ); // the clip mask is usually maintained in Move(), but KillBox requires it
2739  gameLocal.KillBox( this );
2740  }
2741 
2742  // don't allow full run speed for a bit
2743  physicsObj.SetKnockBack( 100 );
2744 
2745  // set our respawn time and buttons so that if we're killed we don't respawn immediately
2748  if ( !spectating ) {
2749  forceRespawn = false;
2750  }
2751 
2753 
2755 
2756  // run a client frame to drop exactly to the floor,
2757  // initialize animations and other things
2758  Think();
2759 
2760  respawning = false;
2761  lastManOver = false;
2762  lastManPlayAgain = false;
2763  isTelefragged = false;
2764 }
2765 
2766 /*
2767 ===============
2768 idPlayer::SavePersistantInfo
2769 
2770 Saves any inventory and player stats when changing levels.
2771 ===============
2772 */
2773 void idPlayer::SavePersistantInfo( void ) {
2775 
2776  playerInfo.Clear();
2777  inventory.GetPersistantData( playerInfo );
2778  playerInfo.SetInt( "health", health );
2779  playerInfo.SetInt( "current_weapon", currentWeapon );
2780 }
2781 
2782 /*
2783 ===============
2784 idPlayer::RestorePersistantInfo
2785 
2786 Restores any inventory and player stats when changing levels.
2787 ===============
2788 */
2789 void idPlayer::RestorePersistantInfo( void ) {
2790  if ( gameLocal.isMultiplayer ) {
2792  }
2793 
2795 
2796  inventory.RestoreInventory( this, spawnArgs );
2797  health = spawnArgs.GetInt( "health", "100" );
2798  if ( !gameLocal.isClient ) {
2799  idealWeapon = spawnArgs.GetInt( "current_weapon", "1" );
2800  }
2801 }
2802 
2803 /*
2804 ================
2805 idPlayer::GetUserInfo
2806 ================
2807 */
2808 idDict *idPlayer::GetUserInfo( void ) {
2809  return &gameLocal.userInfo[ entityNumber ];
2810 }
2811 
2812 /*
2813 ==============
2814 idPlayer::UpdateSkinSetup
2815 ==============
2816 */
2817 void idPlayer::UpdateSkinSetup( bool restart ) {
2818  if ( restart ) {
2819  team = ( idStr::Icmp( GetUserInfo()->GetString( "ui_team" ), "Blue" ) == 0 );
2820  }
2821  if ( gameLocal.mpGame.IsGametypeTeamBased() ) { /* CTF */
2822  if ( team ) {
2823  baseSkinName = "skins/characters/player/marine_mp_blue";
2824  } else {
2825  baseSkinName = "skins/characters/player/marine_mp_red";
2826  }
2827  if ( !gameLocal.isClient && team != latchedTeam ) {
2829  }
2830  latchedTeam = team;
2831  } else {
2832  baseSkinName = GetUserInfo()->GetString( "ui_skin" );
2833  }
2834  if ( !baseSkinName.Length() ) {
2835  baseSkinName = "skins/characters/player/marine_mp";
2836  }
2837  skin = declManager->FindSkin( baseSkinName, false );
2838  assert( skin );
2839  // match the skin to a color band for scoreboard
2840  if ( baseSkinName.Find( "red" ) != -1 ) {
2841  colorBarIndex = 1;
2842  } else if ( baseSkinName.Find( "green" ) != -1 ) {
2843  colorBarIndex = 2;
2844  } else if ( baseSkinName.Find( "blue" ) != -1 ) {
2845  colorBarIndex = 3;
2846  } else if ( baseSkinName.Find( "yellow" ) != -1 ) {
2847  colorBarIndex = 4;
2848  } else if ( baseSkinName.Find( "grey" ) != -1 ) {
2849  colorBarIndex = 5;
2850  } else if ( baseSkinName.Find( "purple" ) != -1 ) {
2851  colorBarIndex = 6;
2852  } else if ( baseSkinName.Find( "orange" ) != -1 ) {
2853  colorBarIndex = 7;
2854  } else {
2855  colorBarIndex = 0;
2856  }
2858  if ( PowerUpActive( BERSERK ) ) {
2859  powerUpSkin = declManager->FindSkin( baseSkinName + "_berserk" );
2860  }
2861 #ifdef _D3XP
2862  else if ( PowerUpActive( INVULNERABILITY ) ) {
2863  powerUpSkin = declManager->FindSkin( baseSkinName + "_invuln" );
2864  //} else if ( PowerUpActive( HASTE ) ) {
2865  // powerUpSkin = declManager->FindSkin( baseSkinName + "_haste" );
2866  }
2867 #endif
2868 }
2869 
2870 /*
2871 ==============
2872 idPlayer::BalanceTDM
2873 ==============
2874 */
2875 bool idPlayer::BalanceTDM( void ) {
2876  int i, balanceTeam, teamCount[2];
2877  idEntity *ent;
2878 
2879  teamCount[ 0 ] = teamCount[ 1 ] = 0;
2880  for( i = 0; i < gameLocal.numClients; i++ ) {
2881  ent = gameLocal.entities[ i ];
2882  if ( ent && ent->IsType( idPlayer::Type ) ) {
2883  teamCount[ static_cast< idPlayer * >( ent )->team ]++;
2884  }
2885  }
2886  balanceTeam = -1;
2887  if ( teamCount[ 0 ] < teamCount[ 1 ] ) {
2888  balanceTeam = 0;
2889  } else if ( teamCount[ 0 ] > teamCount[ 1 ] ) {
2890  balanceTeam = 1;
2891  }
2892  if ( balanceTeam != -1 && team != balanceTeam ) {
2893  common->DPrintf( "team balance: forcing player %d to %s team\n", entityNumber, balanceTeam ? "blue" : "red" );
2894  team = balanceTeam;
2895  GetUserInfo()->Set( "ui_team", team ? "Blue" : "Red" );
2896  return true;
2897  }
2898  return false;
2899 }
2900 
2901 /*
2902 ==============
2903 idPlayer::UserInfoChanged
2904 ==============
2905 */
2906 bool idPlayer::UserInfoChanged( bool canModify ) {
2907  idDict *userInfo;
2908  bool modifiedInfo;
2909  bool spec;
2910  bool newready;
2911 
2912  userInfo = GetUserInfo();
2913  showWeaponViewModel = userInfo->GetBool( "ui_showGun" );
2914 
2915  if ( !gameLocal.isMultiplayer ) {
2916  return false;
2917  }
2918 
2919  modifiedInfo = false;
2920 
2921  spec = ( idStr::Icmp( userInfo->GetString( "ui_spectate" ), "Spectate" ) == 0 );
2922  if ( gameLocal.serverInfo.GetBool( "si_spectators" ) ) {
2923  // never let spectators go back to game while sudden death is on
2924  if ( canModify && gameLocal.mpGame.GetGameState() == idMultiplayerGame::SUDDENDEATH && !spec && wantSpectate == true ) {
2925  userInfo->Set( "ui_spectate", "Spectate" );
2926  modifiedInfo |= true;
2927  } else {
2928  if ( spec != wantSpectate && !spec ) {
2929  // returning from spectate, set forceRespawn so we don't get stuck in spectate forever
2930  forceRespawn = true;
2931  }
2932  wantSpectate = spec;
2933  }
2934  } else {
2935  if ( canModify && spec ) {
2936  userInfo->Set( "ui_spectate", "Play" );
2937  modifiedInfo |= true;
2938  } else if ( spectating ) {
2939  // allow player to leaving spectator mode if they were in it when si_spectators got turned off
2940  forceRespawn = true;
2941  }
2942  wantSpectate = false;
2943  }
2944 
2945  newready = ( idStr::Icmp( userInfo->GetString( "ui_ready" ), "Ready" ) == 0 );
2946  if ( ready != newready && gameLocal.mpGame.GetGameState() == idMultiplayerGame::WARMUP && !wantSpectate ) {
2947  gameLocal.mpGame.AddChatLine( common->GetLanguageDict()->GetString( "#str_07180" ), userInfo->GetString( "ui_name" ), newready ? common->GetLanguageDict()->GetString( "#str_04300" ) : common->GetLanguageDict()->GetString( "#str_04301" ) );
2948  }
2949  ready = newready;
2950  team = ( idStr::Icmp( userInfo->GetString( "ui_team" ), "Blue" ) == 0 );
2951  // server maintains TDM balance
2952  if ( canModify && gameLocal.mpGame.IsGametypeTeamBased() && !gameLocal.mpGame.IsInGame( entityNumber ) && g_balanceTDM.GetBool() ) { /* CTF */
2953  modifiedInfo |= BalanceTDM( );
2954  }
2955  UpdateSkinSetup( false );
2956 
2957  isChatting = userInfo->GetBool( "ui_chat", "0" );
2958  if ( canModify && isChatting && AI_DEAD ) {
2959  // if dead, always force chat icon off.
2960  isChatting = false;
2961  userInfo->SetBool( "ui_chat", false );
2962  modifiedInfo |= true;
2963  }
2964 
2965  return modifiedInfo;
2966 }
2967 
2968 /*
2969 ===============
2970 idPlayer::UpdateHudAmmo
2971 ===============
2972 */
2974  int inclip;
2975  int ammoamount;
2976 
2977  assert( weapon.GetEntity() );
2978  assert( _hud );
2979 
2980  inclip = weapon.GetEntity()->AmmoInClip();
2981  ammoamount = weapon.GetEntity()->AmmoAvailable();
2982 
2983 #ifdef _D3XP
2984  //Hack to stop the bloodstone ammo to display when it is being activated
2985  if ( ammoamount < 0 || !weapon.GetEntity()->IsReady() || currentWeapon == weapon_bloodstone) {
2986 #else
2987  if ( ammoamount < 0 || !weapon.GetEntity()->IsReady() ) {
2988 #endif
2989  // show infinite ammo
2990  _hud->SetStateString( "player_ammo", "" );
2991  _hud->SetStateString( "player_totalammo", "" );
2992  } else {
2993  // show remaining ammo
2994 #ifdef _D3XP
2995  _hud->SetStateString( "player_totalammo", va( "%i", ammoamount ) );
2996 #else
2997  _hud->SetStateString( "player_totalammo", va( "%i", ammoamount - inclip ) );
2998 #endif
2999  _hud->SetStateString( "player_ammo", weapon.GetEntity()->ClipSize() ? va( "%i", inclip ) : "--" ); // how much in the current clip
3000  _hud->SetStateString( "player_clips", weapon.GetEntity()->ClipSize() ? va( "%i", ammoamount / weapon.GetEntity()->ClipSize() ) : "--" );
3001 
3002 #ifdef _D3XP
3003  _hud->SetStateString( "player_allammo", va( "%i/%i", inclip, ammoamount ) );
3004 #else
3005  _hud->SetStateString( "player_allammo", va( "%i/%i", inclip, ammoamount - inclip ) );
3006 #endif
3007  }
3008 
3009  _hud->SetStateBool( "player_ammo_empty", ( ammoamount == 0 ) );
3010  _hud->SetStateBool( "player_clip_empty", ( weapon.GetEntity()->ClipSize() ? inclip == 0 : false ) );
3011  _hud->SetStateBool( "player_clip_low", ( weapon.GetEntity()->ClipSize() ? inclip <= weapon.GetEntity()->LowAmmo() : false ) );
3012 
3013 #ifdef _D3XP
3014  //Hack to stop the bloodstone ammo to display when it is being activated
3015  if(currentWeapon == weapon_bloodstone) {
3016  _hud->SetStateBool( "player_ammo_empty", false );
3017  _hud->SetStateBool( "player_clip_empty", false );
3018  _hud->SetStateBool( "player_clip_low", false );
3019  }
3020 #endif
3021 
3022 #ifdef _D3XP
3023  //Let the HUD know the total amount of ammo regardless of the ammo required value
3024  _hud->SetStateString( "player_ammo_count", va("%i", weapon.GetEntity()->AmmoCount()));
3025 #endif
3026 
3027 #ifdef _D3XP
3028  //Make sure the hud always knows how many bloodstone charges there are
3029  int ammoRequired;
3030  ammo_t ammo_i = inventory.AmmoIndexForWeaponClass( "weapon_bloodstone_passive", &ammoRequired );
3031  int bloodstoneAmmo = inventory.HasAmmo( ammo_i, ammoRequired );
3032  _hud->SetStateString("player_bloodstone_ammo", va("%i", bloodstoneAmmo));
3033  _hud->HandleNamedEvent( "bloodstoneAmmoUpdate" );
3034 #endif
3035 
3036  _hud->HandleNamedEvent( "updateAmmo" );
3037 }
3038 
3039 /*
3040 ===============
3041 idPlayer::UpdateHudStats
3042 ===============
3043 */
3045  int staminapercentage;
3046  float max_stamina;
3047 
3048  assert( _hud );
3049 
3050  max_stamina = pm_stamina.GetFloat();
3051  if ( !max_stamina ) {
3052  // stamina disabled, so show full stamina bar
3053  staminapercentage = 100.0f;
3054  } else {
3055  staminapercentage = idMath::FtoiFast( 100.0f * stamina / max_stamina );
3056  }
3057 
3058  _hud->SetStateInt( "player_health", health );
3059  _hud->SetStateInt( "player_stamina", staminapercentage );
3060  _hud->SetStateInt( "player_armor", inventory.armor );
3061  _hud->SetStateInt( "player_hr", heartRate );
3062 
3063  _hud->SetStateInt( "player_nostamina", ( max_stamina == 0 ) ? 1 : 0 );
3064 
3065  _hud->HandleNamedEvent( "updateArmorHealthAir" );
3066 
3067 #ifdef _D3XP
3068  _hud->HandleNamedEvent( "updatePowerup" );
3069 #endif
3070 
3071  if ( healthPulse ) {
3072  _hud->HandleNamedEvent( "healthPulse" );
3073  StartSound( "snd_healthpulse", SND_CHANNEL_ITEM, 0, false, NULL );
3074  healthPulse = false;
3075  }
3076 
3077  if ( healthTake ) {
3078  _hud->HandleNamedEvent( "healthPulse" );
3079  StartSound( "snd_healthtake", SND_CHANNEL_ITEM, 0, false, NULL );
3080  healthTake = false;
3081  }
3082 
3083  if ( inventory.ammoPulse ) {
3084  _hud->HandleNamedEvent( "ammoPulse" );
3085  inventory.ammoPulse = false;
3086  }
3087  if ( inventory.weaponPulse ) {
3088  // We need to update the weapon hud manually, but not
3089  // the armor/ammo/health because they are updated every
3090  // frame no matter what
3091  UpdateHudWeapon();
3092  _hud->HandleNamedEvent( "weaponPulse" );
3093  inventory.weaponPulse = false;
3094  }
3095  if ( inventory.armorPulse ) {
3096  _hud->HandleNamedEvent( "armorPulse" );
3097  inventory.armorPulse = false;
3098  }
3099 
3100 #ifdef CTF
3101  if ( gameLocal.mpGame.IsGametypeFlagBased() && _hud )
3102  {
3103  _hud->SetStateInt( "red_flagstatus", gameLocal.mpGame.GetFlagStatus( 0 ) );
3104  _hud->SetStateInt( "blue_flagstatus", gameLocal.mpGame.GetFlagStatus( 1 ) );
3105 
3106  _hud->SetStateInt( "red_team_score", gameLocal.mpGame.GetFlagPoints( 0 ) );
3107  _hud->SetStateInt( "blue_team_score", gameLocal.mpGame.GetFlagPoints( 1 ) );
3108 
3109  _hud->HandleNamedEvent( "RedFlagStatusChange" );
3110  _hud->HandleNamedEvent( "BlueFlagStatusChange" );
3111  }
3112 
3113  _hud->HandleNamedEvent( "selfTeam" );
3114 
3115 #endif
3116 
3117 
3118  UpdateHudAmmo( _hud );
3119 }
3120 
3121 /*
3122 ===============
3123 idPlayer::UpdateHudWeapon
3124 ===============
3125 */
3126 void idPlayer::UpdateHudWeapon( bool flashWeapon ) {
3128 
3129  // if updating the hud of a followed client
3131  idPlayer *p = static_cast< idPlayer * >( gameLocal.entities[ gameLocal.localClientNum ] );
3132  if ( p->spectating && p->spectator == entityNumber ) {
3133  assert( p->hud );
3134  hud = p->hud;
3135  }
3136  }
3137 
3138  if ( !hud ) {
3139  return;
3140  }
3141 
3142  for ( int i = 0; i < MAX_WEAPONS; i++ ) {
3143  const char *weapnum = va( "def_weapon%d", i );
3144  const char *hudWeap = va( "weapon%d", i );
3145  int weapstate = 0;
3146  if ( inventory.weapons & ( 1 << i ) ) {
3147  const char *weap = spawnArgs.GetString( weapnum );
3148  if ( weap && *weap ) {
3149  weapstate++;
3150  }
3151  if ( idealWeapon == i ) {
3152  weapstate++;
3153  }
3154  }
3155  hud->SetStateInt( hudWeap, weapstate );
3156  }
3157  if ( flashWeapon ) {
3158 
3159 /*#ifdef _D3XP
3160  //Clear all hud weapon varaibles for the weapon change
3161  hud->SetStateString( "player_ammo", "" );
3162  hud->SetStateString( "player_totalammo", "" );
3163  hud->SetStateString( "player_clips", "" );
3164  hud->SetStateString( "player_allammo", "" );
3165  hud->SetStateBool( "player_ammo_empty", false );
3166  hud->SetStateBool( "player_clip_empty", false );
3167  hud->SetStateBool( "player_clip_low", false );
3168  hud->SetStateString( "player_ammo_count", "");
3169 #endif*/
3170 
3171  hud->HandleNamedEvent( "weaponChange" );
3172  }
3173 }
3174 
3175 /*
3176 ===============
3177 idPlayer::DrawHUD
3178 ===============
3179 */
3180 void idPlayer::DrawHUD( idUserInterface *_hud ) {
3181 
3183  return;
3184  }
3185 
3186  UpdateHudStats( _hud );
3187 
3188  _hud->SetStateString( "weapicon", weapon.GetEntity()->Icon() );
3189 
3190  // FIXME: this is temp to allow the sound meter to show up in the hud
3191  // it should be commented out before shipping but the code can remain
3192  // for mod developers to enable for the same functionality
3193  _hud->SetStateInt( "s_debug", cvarSystem->GetCVarInteger( "s_showLevelMeter" ) );
3194 
3195  weapon.GetEntity()->UpdateGUI();
3196 
3197  _hud->Redraw( gameLocal.realClientTime );
3198 
3199  // weapon targeting crosshair
3200  if ( !GuiActive() ) {
3201  if ( cursor && weapon.GetEntity()->ShowCrosshair() ) {
3202 
3203 #ifdef _D3XP
3204  if ( weapon.GetEntity()->GetGrabberState() == 1 || weapon.GetEntity()->GetGrabberState() == 2 ) {
3205  cursor->SetStateString( "grabbercursor", "1" );
3206  cursor->SetStateString( "combatcursor", "0" );
3207  } else {
3208  cursor->SetStateString( "grabbercursor", "0" );
3209  cursor->SetStateString( "combatcursor", "1" );
3210  }
3211 #endif
3212 
3214  }
3215  }
3216 }
3217 
3218 /*
3219 ===============
3220 idPlayer::EnterCinematic
3221 ===============
3222 */
3223 void idPlayer::EnterCinematic( void ) {
3224 #ifdef _D3XP
3225  if ( PowerUpActive( HELLTIME ) ) {
3226  StopHelltime();
3227  }
3228 #endif
3229 
3230  Hide();
3231  StopAudioLog();
3232  StopSound( SND_CHANNEL_PDA, false );
3233  if ( hud ) {
3234  hud->HandleNamedEvent( "radioChatterDown" );
3235  }
3236 
3238 
3239  SetState( "EnterCinematic" );
3240  UpdateScript();
3241 
3242  if ( weaponEnabled && weapon.GetEntity() ) {
3244  }
3245 
3246  AI_FORWARD = false;
3247  AI_BACKWARD = false;
3248  AI_STRAFE_LEFT = false;
3249  AI_STRAFE_RIGHT = false;
3250  AI_RUN = false;
3251  AI_ATTACK_HELD = false;
3252  AI_WEAPON_FIRED = false;
3253  AI_JUMP = false;
3254  AI_CROUCH = false;
3255  AI_ONGROUND = true;
3256  AI_ONLADDER = false;
3257  AI_DEAD = ( health <= 0 );
3258  AI_RUN = false;
3259  AI_PAIN = false;
3260  AI_HARDLANDING = false;
3261  AI_SOFTLANDING = false;
3262  AI_RELOAD = false;
3263  AI_TELEPORT = false;
3264  AI_TURN_LEFT = false;
3265  AI_TURN_RIGHT = false;
3266 }
3267 
3268 /*
3269 ===============
3270 idPlayer::ExitCinematic
3271 ===============
3272 */
3273 void idPlayer::ExitCinematic( void ) {
3274  Show();
3275 
3276  if ( weaponEnabled && weapon.GetEntity() ) {
3278  }
3279 
3280  SetState( "ExitCinematic" );
3281  UpdateScript();
3282 }
3283 
3284 /*
3285 =====================
3286 idPlayer::UpdateConditions
3287 =====================
3288 */
3289 void idPlayer::UpdateConditions( void ) {
3290  idVec3 velocity;
3291  float fallspeed;
3292  float forwardspeed;
3293  float sidespeed;
3294 
3295  // minus the push velocity to avoid playing the walking animation and sounds when riding a mover
3297  fallspeed = velocity * physicsObj.GetGravityNormal();
3298 
3299  if ( influenceActive ) {
3300  AI_FORWARD = false;
3301  AI_BACKWARD = false;
3302  AI_STRAFE_LEFT = false;
3303  AI_STRAFE_RIGHT = false;
3304  } else if ( gameLocal.time - lastDmgTime < 500 ) {
3305  forwardspeed = velocity * viewAxis[ 0 ];
3306  sidespeed = velocity * viewAxis[ 1 ];
3307  AI_FORWARD = AI_ONGROUND && ( forwardspeed > 20.01f );
3308  AI_BACKWARD = AI_ONGROUND && ( forwardspeed < -20.01f );
3309  AI_STRAFE_LEFT = AI_ONGROUND && ( sidespeed > 20.01f );
3310  AI_STRAFE_RIGHT = AI_ONGROUND && ( sidespeed < -20.01f );
3311  } else if ( xyspeed > MIN_BOB_SPEED ) {
3316  } else {
3317  AI_FORWARD = false;
3318  AI_BACKWARD = false;
3319  AI_STRAFE_LEFT = false;
3320  AI_STRAFE_RIGHT = false;
3321  }
3322 
3324  AI_DEAD = ( health <= 0 );
3325 }
3326 
3327 /*
3328 ==================
3329 WeaponFireFeedback
3330 
3331 Called when a weapon fires, generates head twitches, etc
3332 ==================
3333 */
3334 void idPlayer::WeaponFireFeedback( const idDict *weaponDef ) {
3335  // force a blink
3336  blink_time = 0;
3337 
3338  // play the fire animation
3339  AI_WEAPON_FIRED = true;
3340 
3341  // update view feedback
3342  playerView.WeaponFireFeedback( weaponDef );
3343 }
3344 
3345 /*
3346 ===============
3347 idPlayer::StopFiring
3348 ===============
3349 */
3350 void idPlayer::StopFiring( void ) {
3351  AI_ATTACK_HELD = false;
3352  AI_WEAPON_FIRED = false;
3353  AI_RELOAD = false;
3354  if ( weapon.GetEntity() ) {
3355  weapon.GetEntity()->EndAttack();
3356  }
3357 }
3358 
3359 /*
3360 ===============
3361 idPlayer::FireWeapon
3362 ===============
3363 */
3364 void idPlayer::FireWeapon( void ) {
3365  idMat3 axis;
3366  idVec3 muzzle;
3367 
3368  if ( privateCameraView ) {
3369  return;
3370  }
3371 
3372  if ( g_editEntityMode.GetInteger() ) {
3373  GetViewPos( muzzle, axis );
3374  if ( gameLocal.editEntities->SelectEntity( muzzle, axis[0], this ) ) {
3375  return;
3376  }
3377  }
3378 
3379  if ( !hiddenWeapon && weapon.GetEntity()->IsReady() ) {
3381  AI_ATTACK_HELD = true;
3383  if ( ( weapon_soulcube >= 0 ) && ( currentWeapon == weapon_soulcube ) ) {
3384  if ( hud ) {
3385  hud->HandleNamedEvent( "soulCubeNotReady" );
3386  }
3387  SelectWeapon( previousWeapon, false );
3388  }
3389 #ifdef _D3XP
3390  if( (weapon_bloodstone >= 0) && (currentWeapon == weapon_bloodstone) && inventory.weapons & ( 1 << weapon_bloodstone_active1 ) && weapon.GetEntity()->GetStatus() == WP_READY) {
3391  // tell it to switch to the previous weapon. Only do this once to prevent
3392  // weapon toggling messing up the previous weapon
3393  if(idealWeapon == weapon_bloodstone) {
3394  if(previousWeapon == weapon_bloodstone || previousWeapon == -1) {
3395  NextBestWeapon();
3396  } else {
3397  //Since this is a toggle weapon just select itself and it will toggle to the last weapon
3398  SelectWeapon( weapon_bloodstone, false );
3399  }
3400  }
3401  }
3402 #endif
3403  } else {
3404  NextBestWeapon();
3405  }
3406  }
3407 
3408  if ( hud ) {
3409  if ( tipUp ) {
3410  HideTip();
3411  }
3412  // may want to track with with a bool as well
3413  // keep from looking up named events so often
3414  if ( objectiveUp ) {
3415  HideObjective();
3416  }
3417  }
3418 }
3419 
3420 /*
3421 ===============
3422 idPlayer::CacheWeapons
3423 ===============
3424 */
3425 void idPlayer::CacheWeapons( void ) {
3426  idStr weap;
3427  int w;
3428 
3429  // check if we have any weapons
3430  if ( !inventory.weapons ) {
3431  return;
3432  }
3433 
3434  for( w = 0; w < MAX_WEAPONS; w++ ) {
3435  if ( inventory.weapons & ( 1 << w ) ) {
3436  weap = spawnArgs.GetString( va( "def_weapon%d", w ) );
3437  if ( weap != "" ) {
3438  idWeapon::CacheWeapon( weap );
3439  } else {
3440  inventory.weapons &= ~( 1 << w );
3441  }
3442  }
3443  }
3444 }
3445 
3446 /*
3447 ===============
3448 idPlayer::Give
3449 ===============
3450 */
3451 bool idPlayer::Give( const char *statname, const char *value ) {
3452  int amount;
3453 
3454  if ( AI_DEAD ) {
3455  return false;
3456  }
3457 
3458  if ( !idStr::Icmp( statname, "health" ) ) {
3459  if ( health >= inventory.maxHealth ) {
3460  return false;
3461  }
3462  amount = atoi( value );
3463  if ( amount ) {
3464  health += amount;
3465  if ( health > inventory.maxHealth ) {
3467  }
3468  if ( hud ) {
3469  hud->HandleNamedEvent( "healthPulse" );
3470  }
3471  }
3472 
3473  } else if ( !idStr::Icmp( statname, "stamina" ) ) {
3474  if ( stamina >= 100 ) {
3475  return false;
3476  }
3477  stamina += atof( value );
3478  if ( stamina > 100 ) {
3479  stamina = 100;
3480  }
3481 
3482  } else if ( !idStr::Icmp( statname, "heartRate" ) ) {
3483  heartRate += atoi( value );
3484  if ( heartRate > MAX_HEARTRATE ) {
3486  }
3487 
3488  } else if ( !idStr::Icmp( statname, "air" ) ) {
3489  if ( airTics >= pm_airTics.GetInteger() ) {
3490  return false;
3491  }
3492  airTics += atoi( value ) / 100.0 * pm_airTics.GetInteger();
3493  if ( airTics > pm_airTics.GetInteger() ) {
3495  }
3496 #ifdef _D3XP
3497  } else if ( !idStr::Icmp( statname, "enviroTime" ) ) {
3498  if ( PowerUpActive( ENVIROTIME ) ) {
3499  inventory.powerupEndTime[ ENVIROTIME ] += (atof(value) * 1000);
3500  } else {
3501  GivePowerUp( ENVIROTIME, atoi(value)*1000 );
3502  }
3503  } else {
3504  bool ret = inventory.Give( this, spawnArgs, statname, value, &idealWeapon, true );
3505  if(!idStr::Icmp( statname, "ammo_bloodstone" ) ) {
3506  //int i = inventory.AmmoIndexForAmmoClass( statname );
3507  //int max = inventory.MaxAmmoForAmmoClass( this, statname );
3508  //if(hud && inventory.ammo[ i ] >= max) {
3509  if(hud) {
3510 
3511  //Force an update of the bloodstone ammount
3512  int ammoRequired;
3513  ammo_t ammo_i = inventory.AmmoIndexForWeaponClass( "weapon_bloodstone_passive", &ammoRequired );
3514  int bloodstoneAmmo = inventory.HasAmmo( ammo_i, ammoRequired );
3515  hud->SetStateString("player_bloodstone_ammo", va("%i", bloodstoneAmmo));
3516 
3517  hud->HandleNamedEvent("bloodstoneReady");
3518  //Make sure we unlock the ability to harvest
3519  harvest_lock = false;
3520  }
3521  }
3522  return ret;
3523 #else
3524  return inventory.Give( this, spawnArgs, statname, value, &idealWeapon, true );
3525 #endif
3526  }
3527  return true;
3528 }
3529 
3530 
3531 /*
3532 ===============
3533 idPlayer::GiveHealthPool
3534 
3535 adds health to the player health pool
3536 ===============
3537 */
3538 void idPlayer::GiveHealthPool( float amt ) {
3539 
3540  if ( AI_DEAD ) {
3541  return;
3542  }
3543 
3544  if ( health > 0 ) {
3545  healthPool += amt;
3546  if ( healthPool > inventory.maxHealth - health ) {
3548  }
3550  }
3551 }
3552 
3553 /*
3554 ===============
3555 idPlayer::GiveItem
3556 
3557 Returns false if the item shouldn't be picked up
3558 ===============
3559 */
3560 bool idPlayer::GiveItem( idItem *item ) {
3561  int i;
3562  const idKeyValue *arg;
3563  idDict attr;
3564  bool gave;
3565  int numPickup;
3566 
3567  if ( gameLocal.isMultiplayer && spectating ) {
3568  return false;
3569  }
3570 
3571  item->GetAttributes( attr );
3572 
3573  gave = false;
3574  numPickup = inventory.pickupItemNames.Num();
3575  for( i = 0; i < attr.GetNumKeyVals(); i++ ) {
3576  arg = attr.GetKeyVal( i );
3577  if ( Give( arg->GetKey(), arg->GetValue() ) ) {
3578  gave = true;
3579  }
3580  }
3581 
3582  arg = item->spawnArgs.MatchPrefix( "inv_weapon", NULL );
3583  if ( arg && hud ) {
3584  // We need to update the weapon hud manually, but not
3585  // the armor/ammo/health because they are updated every
3586  // frame no matter what
3587  UpdateHudWeapon( false );
3588  hud->HandleNamedEvent( "weaponPulse" );
3589  }
3590 
3591  // display the pickup feedback on the hud
3592  if ( gave && ( numPickup == inventory.pickupItemNames.Num() ) ) {
3593  inventory.AddPickupName( item->spawnArgs.GetString( "inv_name" ), item->spawnArgs.GetString( "inv_icon" ), this ); //_D3XP
3594  }
3595 
3596  return gave;
3597 }
3598 
3599 /*
3600 ===============
3601 idPlayer::PowerUpModifier
3602 ===============
3603 */
3604 float idPlayer::PowerUpModifier( int type ) {
3605  float mod = 1.0f;
3606 
3607  if ( PowerUpActive( BERSERK ) ) {
3608  switch( type ) {
3609  case SPEED: {
3610  mod *= 1.7f;
3611  break;
3612  }
3613  case PROJECTILE_DAMAGE: {
3614  mod *= 2.0f;
3615  break;
3616  }
3617  case MELEE_DAMAGE: {
3618  mod *= 30.0f;
3619  break;
3620  }
3621  case MELEE_DISTANCE: {
3622  mod *= 2.0f;
3623  break;
3624  }
3625  }
3626  }
3627 
3629  if ( PowerUpActive( MEGAHEALTH ) ) {
3630  if ( healthPool <= 0 ) {
3631  GiveHealthPool( 100 );
3632  }
3633  } else {
3634  healthPool = 0;
3635  }
3636 
3637 #ifdef _D3XP
3638  /*if( PowerUpActive( HASTE ) ) {
3639  switch( type ) {
3640  case SPEED: {
3641  mod = 1.7f;
3642  break;
3643  }
3644  }
3645  }*/
3646 #endif
3647  }
3648 
3649  return mod;
3650 }
3651 
3652 /*
3653 ===============
3654 idPlayer::PowerUpActive
3655 ===============
3656 */
3657 bool idPlayer::PowerUpActive( int powerup ) const {
3658  return ( inventory.powerups & ( 1 << powerup ) ) != 0;
3659 }
3660 
3661 /*
3662 ===============
3663 idPlayer::GivePowerUp
3664 ===============
3665 */
3666 bool idPlayer::GivePowerUp( int powerup, int time ) {
3667  const char *sound;
3668  const char *skin;
3669 
3670  if ( powerup >= 0 && powerup < MAX_POWERUPS ) {
3671 
3672  if ( gameLocal.isServer ) {
3673  idBitMsg msg;
3674  byte msgBuf[MAX_EVENT_PARAM_SIZE];
3675 
3676  msg.Init( msgBuf, sizeof( msgBuf ) );
3677  msg.WriteShort( powerup );
3678  msg.WriteBits( 1, 1 );
3679  ServerSendEvent( EVENT_POWERUP, &msg, false, -1 );
3680  }
3681 
3682  if ( powerup != MEGAHEALTH ) {
3683  inventory.GivePowerUp( this, powerup, time );
3684  }
3685 
3686  const idDeclEntityDef *def = NULL;
3687 
3688  switch( powerup ) {
3689  case BERSERK: {
3691  inventory.AddPickupName("#str_00100627", "", this);
3692  }
3693 
3694  if(gameLocal.isMultiplayer) {
3695  if ( spawnArgs.GetString( "snd_berserk_third", "", &sound ) ) {
3697  }
3698  }
3699 
3700 
3701  if ( baseSkinName.Length() ) {
3702  powerUpSkin = declManager->FindSkin( baseSkinName + "_berserk" );
3703  }
3704  if ( !gameLocal.isClient ) {
3705 #ifdef _D3XP
3706  if( !gameLocal.isMultiplayer ) {
3707  // Trying it out without the health boost (1/3/05)
3708  // Give the player full health in single-player
3709  // health = 100;
3710  } else {
3711  // Switch to fists in multiplayer
3712  idealWeapon = 1;
3713  }
3714 #else
3715  idealWeapon = 0;
3716 #endif
3717  }
3718  break;
3719  }
3720  case INVISIBILITY: {
3722  inventory.AddPickupName("#str_00100628", "", this);
3723  }
3724  spawnArgs.GetString( "skin_invisibility", "", &skin );
3725  powerUpSkin = declManager->FindSkin( skin );
3726  // remove any decals from the model
3727  if ( modelDefHandle != -1 ) {
3729  }
3730  if ( weapon.GetEntity() ) {
3732  }
3733 /* if ( spawnArgs.GetString( "snd_invisibility", "", &sound ) ) {
3734  StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_ANY, 0, false, NULL );
3735  } */
3736  break;
3737  }
3738  case ADRENALINE: {
3739 #ifdef _D3XP
3740  inventory.AddPickupName("#str_00100799", "", this);
3741 #endif
3742  stamina = 100.0f;
3743  break;
3744  }
3745  case MEGAHEALTH: {
3747  inventory.AddPickupName("#str_00100629", "", this);
3748  }
3749  if ( spawnArgs.GetString( "snd_megahealth", "", &sound ) ) {
3750  StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_ANY, 0, false, NULL );
3751  }
3752  def = gameLocal.FindEntityDef( "powerup_megahealth", false );
3753  if ( def ) {
3754  health = def->dict.GetInt( "inv_health" );
3755  }
3756  break;
3757  }
3758 #ifdef _D3XP
3759  case HELLTIME: {
3760  if ( spawnArgs.GetString( "snd_helltime_start", "", &sound ) ) {
3762  }
3763  if ( spawnArgs.GetString( "snd_helltime_loop", "", &sound ) ) {
3765  }
3766  break;
3767  }
3768  case ENVIROSUIT: {
3769  // Turn on the envirosuit sound
3770  if ( gameSoundWorld ) {
3771  gameSoundWorld->SetEnviroSuit( true );
3772  }
3773 
3774  // Put the helmet and lights on the player
3775  idDict args;
3776 
3777  // Light
3778  const idDict *lightDef = gameLocal.FindEntityDefDict( "envirosuit_light", false );
3779  if ( lightDef ) {
3780  idEntity *temp;
3781  gameLocal.SpawnEntityDef( *lightDef, &temp, false );
3782 
3783  idLight *eLight = static_cast<idLight *>(temp);
3785  eLight->UpdateVisuals();
3786  eLight->Present();
3787 
3788  enviroSuitLight = eLight;
3789  }
3790  break;
3791  }
3792  case ENVIROTIME: {
3793  hudPowerup = ENVIROTIME;
3794  // The HUD display bar is fixed at 60 seconds
3795  hudPowerupDuration = 60000;
3796  break;
3797  }
3798  case INVULNERABILITY: {
3800  inventory.AddPickupName("#str_00100630", "", this);
3801  }
3802  if(gameLocal.isMultiplayer) {
3803  /*if ( spawnArgs.GetString( "snd_invulnerable", "", &sound ) ) {
3804  StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_DEMONIC, 0, false, NULL );
3805  }*/
3806  if ( baseSkinName.Length() ) {
3807  powerUpSkin = declManager->FindSkin( baseSkinName + "_invuln" );
3808  }
3809  }
3810  break;
3811  }
3812  /*case HASTE: {
3813  if(gameLocal.isMultiplayer && !gameLocal.isClient) {
3814  inventory.AddPickupName("#str_00100631", "", this);
3815  }
3816 
3817  if ( baseSkinName.Length() ) {
3818  powerUpSkin = declManager->FindSkin( baseSkinName + "_haste" );
3819  }
3820  break;
3821  }*/
3822 #endif
3823  }
3824 
3825  if ( hud ) {
3826  hud->HandleNamedEvent( "itemPickup" );
3827  }
3828 
3829  return true;
3830  } else {
3831  gameLocal.Warning( "Player given power up %i\n which is out of range", powerup );
3832  }
3833  return false;
3834 }
3835 
3836 /*
3837 ==============
3838 idPlayer::ClearPowerup
3839 ==============
3840 */
3841 void idPlayer::ClearPowerup( int i ) {
3842 
3843  if ( gameLocal.isServer ) {
3844  idBitMsg msg;
3845  byte msgBuf[MAX_EVENT_PARAM_SIZE];
3846 
3847  msg.Init( msgBuf, sizeof( msgBuf ) );
3848  msg.WriteShort( i );
3849  msg.WriteBits( 0, 1 );
3850  ServerSendEvent( EVENT_POWERUP, &msg, false, -1 );
3851  }
3852 
3853  powerUpSkin = NULL;
3854  inventory.powerups &= ~( 1 << i );
3855  inventory.powerupEndTime[ i ] = 0;
3856  switch( i ) {
3857  case BERSERK: {
3858  if(gameLocal.isMultiplayer) {
3859  StopSound( SND_CHANNEL_DEMONIC, false );
3860  }
3861 #ifdef _D3XP
3862  if(!gameLocal.isMultiplayer) {
3863  StopHealthRecharge();
3864  }
3865 #endif
3866  break;
3867  }
3868  case INVISIBILITY: {
3869  if ( weapon.GetEntity() ) {
3871  }
3872  break;
3873  }
3874 #ifdef _D3XP
3875  case HELLTIME: {
3876  StopSound( SND_CHANNEL_DEMONIC, false );
3877  break;
3878  }
3879  case ENVIROSUIT: {
3880 
3881  hudPowerup = -1;
3882 
3883  // Turn off the envirosuit sound
3884  if ( gameSoundWorld ) {
3885  gameSoundWorld->SetEnviroSuit( false );
3886  }
3887 
3888  // Take off the helmet and lights
3889  if ( enviroSuitLight.IsValid() ) {
3890  enviroSuitLight.GetEntity()->PostEventMS( &EV_Remove, 0 );
3891  }
3892  enviroSuitLight = NULL;
3893  break;
3894  }
3895  case INVULNERABILITY: {
3896  if(gameLocal.isMultiplayer) {
3897  StopSound( SND_CHANNEL_DEMONIC, false );
3898  }
3899  }
3900  /*case HASTE: {
3901  if(gameLocal.isMultiplayer) {
3902  StopSound( SND_CHANNEL_DEMONIC, false );
3903  }
3904  }*/
3905 #endif
3906  }
3907 }
3908 
3909 /*
3910 ==============
3911 idPlayer::UpdatePowerUps
3912 ==============
3913 */
3914 void idPlayer::UpdatePowerUps( void ) {
3915  int i;
3916 
3917  if ( !gameLocal.isClient ) {
3918  for ( i = 0; i < MAX_POWERUPS; i++ ) {
3919 #ifdef _D3XP
3920  if ( ( inventory.powerups & ( 1 << i ) ) && inventory.powerupEndTime[i] > gameLocal.time ) {
3921  switch( i ) {
3922  case ENVIROSUIT: {
3923  if ( enviroSuitLight.IsValid() ) {
3924  idAngles lightAng = firstPersonViewAxis.ToAngles();
3925  idVec3 lightOrg = firstPersonViewOrigin;
3926  const idDict *lightDef = gameLocal.FindEntityDefDict( "envirosuit_light", false );
3927 
3928  idVec3 enviroOffset = lightDef->GetVector( "enviro_offset" );
3929  idVec3 enviroAngleOffset = lightDef->GetVector( "enviro_angle_offset" );
3930 
3931  lightOrg += (enviroOffset.x * firstPersonViewAxis[0]);
3932  lightOrg += (enviroOffset.y * firstPersonViewAxis[1]);
3933  lightOrg += (enviroOffset.z * firstPersonViewAxis[2]);
3934  lightAng.pitch += enviroAngleOffset.x;
3935  lightAng.yaw += enviroAngleOffset.y;
3936  lightAng.roll += enviroAngleOffset.z;
3937 
3938  enviroSuitLight.GetEntity()->GetPhysics()->SetOrigin( lightOrg );
3939  enviroSuitLight.GetEntity()->GetPhysics()->SetAxis( lightAng.ToMat3() );
3940  enviroSuitLight.GetEntity()->UpdateVisuals();
3941  enviroSuitLight.GetEntity()->Present();
3942  }
3943  break;
3944  }
3945  default: {
3946  break;
3947  }
3948  }
3949  }
3950 #endif
3951  if ( PowerUpActive( i ) && inventory.powerupEndTime[i] <= gameLocal.time ) {
3952  ClearPowerup( i );
3953  }
3954  }
3955  }
3956 
3957  if ( health > 0 ) {
3958  if ( powerUpSkin ) {
3960  } else {
3962  }
3963  }
3964 
3965  if ( healthPool && gameLocal.time > nextHealthPulse && !AI_DEAD && health > 0 ) {
3966  assert( !gameLocal.isClient ); // healthPool never be set on client
3967  int amt = ( healthPool > 5 ) ? 5 : healthPool;
3968  health += amt;
3969  if ( health > inventory.maxHealth ) {
3971  healthPool = 0;
3972  } else {
3973  healthPool -= amt;
3974  }
3976  healthPulse = true;
3977  }
3978 #ifndef ID_DEMO_BUILD
3980  assert( !gameLocal.isClient ); // healthPool never be set on client
3981 
3982 #ifdef _D3XP
3983  if(!PowerUpActive(INVULNERABILITY)) {
3984 #endif
3986  if ( health < g_healthTakeLimit.GetInteger() ) {
3988  }
3989 #ifdef _D3XP
3990  }
3991 #endif
3993  healthTake = true;
3994  }
3995 #endif
3996 }
3997 
3998 /*
3999 ===============
4000 idPlayer::ClearPowerUps
4001 ===============
4002 */
4003 void idPlayer::ClearPowerUps( void ) {
4004  int i;
4005  for ( i = 0; i < MAX_POWERUPS; i++ ) {
4006  if ( PowerUpActive( i ) ) {
4007  ClearPowerup( i );
4008  }
4009  }
4011 
4012 #ifdef _D3XP
4013  if ( gameLocal.isMultiplayer ) {
4014  if ( enviroSuitLight.IsValid() ) {
4015  enviroSuitLight.GetEntity()->PostEventMS( &EV_Remove, 0 );
4016  }
4017  }
4018 #endif
4019 }
4020 
4021 /*
4022 ===============
4023 idPlayer::GiveInventoryItem
4024 ===============
4025 */
4026 bool idPlayer::GiveInventoryItem( idDict *item ) {
4027  if ( gameLocal.isMultiplayer && spectating ) {
4028  return false;
4029  }
4030  inventory.items.Append( new idDict( *item ) );
4031  idItemInfo info;
4032  const char* itemName = item->GetString( "inv_name" );
4033  if ( idStr::Cmpn( itemName, STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 ) {
4034  info.name = common->GetLanguageDict()->GetString( itemName );
4035  } else {
4036  info.name = itemName;
4037  }
4038  info.icon = item->GetString( "inv_icon" );
4040  if ( hud ) {
4041  hud->SetStateString( "itemicon", info.icon );
4042  hud->HandleNamedEvent( "invPickup" );
4043  }
4044 
4045 #ifdef _D3XP //Added to support powercells
4046  if(item->GetInt("inv_powercell") && focusUI) {
4047  //Reset the powercell count
4048  int powerCellCount = 0;
4049  for ( int j = 0; j < inventory.items.Num(); j++ ) {
4050  idDict *item = inventory.items[ j ];
4051  if(item->GetInt("inv_powercell")) {
4052  powerCellCount++;
4053  }
4054  }
4055  focusUI->SetStateInt( "powercell_count", powerCellCount );
4056  }
4057 #endif
4058 
4059  return true;
4060 }
4061 
4062 #ifdef _D3XP //BSM: Implementing this defined function for scripted give inventory items
4063 /*
4064 ==============
4065 idPlayer::GiveInventoryItem
4066 ==============
4067 */
4068 bool idPlayer::GiveInventoryItem( const char *name ) {
4069  idDict args;
4070 
4071  args.Set( "classname", name );
4072  args.Set( "owner", this->name.c_str() );
4073  gameLocal.SpawnEntityDef( args);
4074  return true;
4075 }
4076 #endif
4077 
4078 /*
4079 ==============
4080 idPlayer::UpdateObjectiveInfo
4081 ==============
4082  */
4083 void idPlayer::UpdateObjectiveInfo( void ) {
4084  if ( objectiveSystem == NULL ) {
4085  return;
4086  }
4087  objectiveSystem->SetStateString( "objective1", "" );
4088  objectiveSystem->SetStateString( "objective2", "" );
4089  objectiveSystem->SetStateString( "objective3", "" );
4090  for ( int i = 0; i < inventory.objectiveNames.Num(); i++ ) {
4091  objectiveSystem->SetStateString( va( "objective%i", i+1 ), "1" );
4092  objectiveSystem->SetStateString( va( "objectivetitle%i", i+1 ), inventory.objectiveNames[i].title.c_str() );
4093  objectiveSystem->SetStateString( va( "objectivetext%i", i+1 ), inventory.objectiveNames[i].text.c_str() );
4094  objectiveSystem->SetStateString( va( "objectiveshot%i", i+1 ), inventory.objectiveNames[i].screenshot.c_str() );
4095  }
4097 }
4098 
4099 /*
4100 ===============
4101 idPlayer::GiveObjective
4102 ===============
4103 */
4104 void idPlayer::GiveObjective( const char *title, const char *text, const char *screenshot ) {
4105  idObjectiveInfo info;
4106  info.title = title;
4107  info.text = text;
4108  info.screenshot = screenshot;
4110  ShowObjective( "newObjective" );
4111  if ( hud ) {
4112  hud->HandleNamedEvent( "newObjective" );
4113  }
4114 }
4115 
4116 /*
4117 ===============
4118 idPlayer::CompleteObjective
4119 ===============
4120 */
4121 void idPlayer::CompleteObjective( const char *title ) {
4122  int c = inventory.objectiveNames.Num();
4123  for ( int i = 0; i < c; i++ ) {
4124  if ( idStr::Icmp(inventory.objectiveNames[i].title, title) == 0 ) {
4126  break;
4127  }
4128  }
4129  ShowObjective( "newObjectiveComplete" );
4130 
4131  if ( hud ) {
4132  hud->HandleNamedEvent( "newObjectiveComplete" );
4133  }
4134 }
4135 
4136 /*
4137 ===============
4138 idPlayer::GiveVideo
4139 ===============
4140 */
4141 void idPlayer::GiveVideo( const char *videoName, idDict *item ) {
4142 
4143  if ( videoName == NULL || *videoName == '\0' ) {
4144  return;
4145  }
4146 
4147  inventory.videos.AddUnique( videoName );
4148 
4149  if ( item ) {
4150  idItemInfo info;
4151  info.name = item->GetString( "inv_name" );
4152  info.icon = item->GetString( "inv_icon" );
4154  }
4155  if ( hud ) {
4156  hud->HandleNamedEvent( "videoPickup" );
4157  }
4158 }
4159 
4160 /*
4161 ===============
4162 idPlayer::GiveSecurity
4163 ===============
4164 */
4165 void idPlayer::GiveSecurity( const char *security ) {
4166  GetPDA()->SetSecurity( security );
4167  if ( hud ) {
4168  hud->SetStateString( "pda_security", "1" );
4169  hud->HandleNamedEvent( "securityPickup" );
4170  }
4171 }
4172 
4173 /*
4174 ===============
4175 idPlayer::GiveEmail
4176 ===============
4177 */
4178 void idPlayer::GiveEmail( const char *emailName ) {
4179 
4180  if ( emailName == NULL || *emailName == '\0' ) {
4181  return;
4182  }
4183 
4184  inventory.emails.AddUnique( emailName );
4185  GetPDA()->AddEmail( emailName );
4186 
4187  if ( hud ) {
4188  hud->HandleNamedEvent( "emailPickup" );
4189  }
4190 }
4191 
4192 /*
4193 ===============
4194 idPlayer::GivePDA
4195 ===============
4196 */
4197 void idPlayer::GivePDA( const char *pdaName, idDict *item )
4198 {
4199  if ( gameLocal.isMultiplayer && spectating ) {
4200  return;
4201  }
4202 
4203  if ( item ) {
4204  inventory.pdaSecurity.AddUnique( item->GetString( "inv_name" ) );
4205  }
4206 
4207  if ( pdaName == NULL || *pdaName == '\0' ) {
4208  pdaName = "personal";
4209  }
4210 
4211  const idDeclPDA *pda = static_cast< const idDeclPDA* >( declManager->FindType( DECL_PDA, pdaName ) );
4212 
4213  inventory.pdas.AddUnique( pdaName );
4214 
4215  // Copy any videos over
4216  for ( int i = 0; i < pda->GetNumVideos(); i++ ) {
4217  const idDeclVideo *video = pda->GetVideoByIndex( i );
4218  if ( video ) {
4219  inventory.videos.AddUnique( video->GetName() );
4220  }
4221  }
4222 
4223  // This is kind of a hack, but it works nicely
4224  // We don't want to display the 'you got a new pda' message during a map load
4225  if ( gameLocal.GetFrameNum() > 10 ) {
4226  if ( pda && hud ) {
4227  idStr pdaName = pda->GetPdaName();
4228  pdaName.RemoveColors();
4229  hud->SetStateString( "pda", "1" );
4230  hud->SetStateString( "pda_text", pdaName );
4231  const char *sec = pda->GetSecurity();
4232  hud->SetStateString( "pda_security", ( sec && *sec ) ? "1" : "0" );
4233  hud->HandleNamedEvent( "pdaPickup" );
4234  }
4235 
4236  if ( inventory.pdas.Num() == 1 ) {
4238  if ( !objectiveSystemOpen ) {
4239  TogglePDA();
4240  }
4241  objectiveSystem->HandleNamedEvent( "showPDATip" );
4242  //ShowTip( spawnArgs.GetString( "text_infoTitle" ), spawnArgs.GetString( "text_firstPDA" ), true );
4243  }
4244 
4245  if ( inventory.pdas.Num() > 1 && pda->GetNumVideos() > 0 && hud ) {
4246  hud->HandleNamedEvent( "videoPickup" );
4247  }
4248  }
4249 }
4250 
4251 /*
4252 ===============
4253 idPlayer::FindInventoryItem
4254 ===============
4255 */
4256 idDict *idPlayer::FindInventoryItem( const char *name ) {
4257  for ( int i = 0; i < inventory.items.Num(); i++ ) {
4258  const char *iname = inventory.items[i]->GetString( "inv_name" );
4259  if ( iname && *iname ) {
4260  if ( idStr::Icmp( name, iname ) == 0 ) {
4261  return inventory.items[i];
4262  }
4263  }
4264  }
4265  return NULL;
4266 }
4267 
4268 /*
4269 ===============
4270 idPlayer::RemoveInventoryItem
4271 ===============
4272 */
4273 void idPlayer::RemoveInventoryItem( const char *name ) {
4274  //Hack for localization
4275  if(!idStr::Icmp(name, "Pwr Cell")) {
4276  name = common->GetLanguageDict()->GetString( "#str_00101056" );
4277  }
4278  idDict *item = FindInventoryItem(name);
4279  if ( item ) {
4280  RemoveInventoryItem( item );
4281  }
4282 }
4283 
4284 /*
4285 ===============
4286 idPlayer::RemoveInventoryItem
4287 ===============
4288 */
4289 void idPlayer::RemoveInventoryItem( idDict *item ) {
4290  inventory.items.Remove( item );
4291 
4292 #ifdef _D3XP //Added to support powercells
4293  if(item->GetInt("inv_powercell") && focusUI) {
4294  //Reset the powercell count
4295  int powerCellCount = 0;
4296  for ( int j = 0; j < inventory.items.Num(); j++ ) {
4297  idDict *item = inventory.items[ j ];
4298  if(item->GetInt("inv_powercell")) {
4299  powerCellCount++;
4300  }
4301  }
4302  focusUI->SetStateInt( "powercell_count", powerCellCount );
4303  }
4304 #endif
4305 
4306  delete item;
4307 }
4308 
4309 /*
4310 ===============
4311 idPlayer::GiveItem
4312 ===============
4313 */
4314 void idPlayer::GiveItem( const char *itemname ) {
4315  idDict args;
4316 
4317  args.Set( "classname", itemname );
4318  args.Set( "owner", name.c_str() );
4319  gameLocal.SpawnEntityDef( args );
4320  if ( hud ) {
4321  hud->HandleNamedEvent( "itemPickup" );
4322  }
4323 }
4324 
4325 /*
4326 ==================
4327 idPlayer::SlotForWeapon
4328 ==================
4329 */
4330 int idPlayer::SlotForWeapon( const char *weaponName ) {
4331  int i;
4332 
4333  for( i = 0; i < MAX_WEAPONS; i++ ) {
4334  const char *weap = spawnArgs.GetString( va( "def_weapon%d", i ) );
4335  if ( !idStr::Cmp( weap, weaponName ) ) {
4336  return i;
4337  }
4338  }
4339 
4340  // not found
4341  return -1;
4342 }
4343 
4344 /*
4345 ===============
4346 idPlayer::Reload
4347 ===============
4348 */
4349 void idPlayer::Reload( void ) {
4350  if ( gameLocal.isClient ) {
4351  return;
4352  }
4353 
4355  return;
4356  }
4357 
4358  if ( weapon.GetEntity() && weapon.GetEntity()->IsLinked() ) {
4359  weapon.GetEntity()->Reload();
4360  }
4361 }
4362 
4363 /*
4364 ===============
4365 idPlayer::NextBestWeapon
4366 ===============
4367 */
4368 void idPlayer::NextBestWeapon( void ) {
4369  const char *weap;
4370  int w = MAX_WEAPONS;
4371 
4372  if ( gameLocal.isClient || !weaponEnabled ) {
4373  return;
4374  }
4375 
4376  while ( w > 0 ) {
4377  w--;
4378  weap = spawnArgs.GetString( va( "def_weapon%d", w ) );
4379 #ifdef _D3XP
4380  if ( !weap[ 0 ] || ( ( inventory.weapons & ( 1 << w ) ) == 0 ) || ( !inventory.HasAmmo( weap, true, this ) ) ) {
4381 #else
4382  if ( !weap[ 0 ] || ( ( inventory.weapons & ( 1 << w ) ) == 0 ) || ( !(inventory.HasAmmo( weap )) ) ) {
4383 #endif
4384  continue;
4385  }
4386  if ( !spawnArgs.GetBool( va( "weapon%d_best", w ) ) ) {
4387  continue;
4388  }
4389 
4390 #ifdef _D3XP
4391  //Some weapons will report having ammo but the clip is empty and
4392  //will not have enough to fill the clip (i.e. Double Barrel Shotgun with 1 round left)
4393  //We need to skip these weapons because they cannot be used
4394  if(inventory.HasEmptyClipCannotRefill(weap, this)) {
4395  continue;
4396  }
4397 #endif
4398 
4399  break;
4400  }
4401  idealWeapon = w;
4403  UpdateHudWeapon();
4404 }
4405 
4406 /*
4407 ===============
4408 idPlayer::NextWeapon
4409 ===============
4410 */
4411 void idPlayer::NextWeapon( void ) {
4412 
4413  const char *weap;
4414  int w;
4415 
4416  if ( !weaponEnabled || spectating || hiddenWeapon || gameLocal.inCinematic || gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) || health < 0 ) {
4417  return;
4418  }
4419 
4420  if ( gameLocal.isClient ) {
4421  return;
4422  }
4423 
4424  // check if we have any weapons
4425  if ( !inventory.weapons ) {
4426  return;
4427  }
4428 
4429  w = idealWeapon;
4430  while( 1 ) {
4431  w++;
4432  if ( w >= MAX_WEAPONS ) {
4433  w = 0;
4434  }
4435  weap = spawnArgs.GetString( va( "def_weapon%d", w ) );
4436  if ( !spawnArgs.GetBool( va( "weapon%d_cycle", w ) ) ) {
4437  continue;
4438  }
4439  if ( !weap[ 0 ] ) {
4440  continue;
4441  }
4442  if ( ( inventory.weapons & ( 1 << w ) ) == 0 ) {
4443  continue;
4444  }
4445 
4446 #ifdef _D3XP
4447  if ( inventory.HasAmmo( weap, true, this ) || w == weapon_bloodstone ) {
4448 #else
4449  if ( inventory.HasAmmo( weap ) ) {
4450 #endif
4451  break;
4452  }
4453  }
4454 
4455  if ( ( w != currentWeapon ) && ( w != idealWeapon ) ) {
4456  idealWeapon = w;
4458  UpdateHudWeapon();
4459  }
4460 }
4461 
4462 /*
4463 ===============
4464 idPlayer::PrevWeapon
4465 ===============
4466 */
4467 void idPlayer::PrevWeapon( void ) {
4468 
4469  const char *weap;
4470  int w;
4471 
4472  if ( !weaponEnabled || spectating || hiddenWeapon || gameLocal.inCinematic || gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) || health < 0 ) {
4473  return;
4474  }
4475 
4476  if ( gameLocal.isClient ) {
4477  return;
4478  }
4479 
4480  // check if we have any weapons
4481  if ( !inventory.weapons ) {
4482  return;
4483  }
4484 
4485  w = idealWeapon;
4486  while( 1 ) {
4487  w--;
4488  if ( w < 0 ) {
4489  w = MAX_WEAPONS - 1;
4490  }
4491  weap = spawnArgs.GetString( va( "def_weapon%d", w ) );
4492  if ( !spawnArgs.GetBool( va( "weapon%d_cycle", w ) ) ) {
4493  continue;
4494  }
4495  if ( !weap[ 0 ] ) {
4496  continue;
4497  }
4498  if ( ( inventory.weapons & ( 1 << w ) ) == 0 ) {
4499  continue;
4500  }
4501 #ifdef _D3XP
4502  if ( inventory.HasAmmo( weap, true, this ) || w == weapon_bloodstone ) {
4503 #else
4504  if ( inventory.HasAmmo( weap ) ) {
4505 #endif
4506  break;
4507  }
4508  }
4509 
4510  if ( ( w != currentWeapon ) && ( w != idealWeapon ) ) {
4511  idealWeapon = w;
4513  UpdateHudWeapon();
4514  }
4515 }
4516 
4517 /*
4518 ===============
4519 idPlayer::SelectWeapon
4520 ===============
4521 */
4522 void idPlayer::SelectWeapon( int num, bool force ) {
4523  const char *weap;
4524 
4525  if ( !weaponEnabled || spectating || gameLocal.inCinematic || health < 0 ) {
4526  return;
4527  }
4528 
4529  if ( ( num < 0 ) || ( num >= MAX_WEAPONS ) ) {
4530  return;
4531  }
4532 
4533  if ( gameLocal.isClient ) {
4534  return;
4535  }
4536 
4537  if ( ( num != weapon_pda ) && gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) ) {
4538  num = weapon_fists;
4539  hiddenWeapon ^= 1;
4540  if ( hiddenWeapon && weapon.GetEntity() ) {
4542  } else {
4544  }
4545  }
4546 
4547  weap = spawnArgs.GetString( va( "def_weapon%d", num ) );
4548  if ( !weap[ 0 ] ) {
4549  gameLocal.Printf( "Invalid weapon\n" );
4550  return;
4551  }
4552 
4553 #ifdef _D3XP
4554  //Is the weapon a toggle weapon
4555  WeaponToggle_t* weaponToggle;
4556  if(weaponToggles.Get(va("weapontoggle%d", num), &weaponToggle)) {
4557 
4558  int weaponToggleIndex = 0;
4559 
4560  //Find the current Weapon in the list
4561  int currentIndex = -1;
4562  for(int i = 0; i < weaponToggle->toggleList.Num(); i++) {
4563  if(weaponToggle->toggleList[i] == idealWeapon) {
4564  currentIndex = i;
4565  break;
4566  }
4567  }
4568  if(currentIndex == -1) {
4569  //Didn't find the current weapon so select the first item
4570  weaponToggleIndex = 0;
4571  } else {
4572  //Roll to the next available item in the list
4573  weaponToggleIndex = currentIndex;
4574  weaponToggleIndex++;
4575  if(weaponToggleIndex >= weaponToggle->toggleList.Num()) {
4576  weaponToggleIndex = 0;
4577  }
4578  }
4579 
4580  for(int i = 0; i < weaponToggle->toggleList.Num(); i++) {
4581 
4582  //Is it available
4583  if(inventory.weapons & ( 1 << weaponToggle->toggleList[weaponToggleIndex])) {
4584  break;
4585  }
4586 
4587  weaponToggleIndex++;
4588  if(weaponToggleIndex >= weaponToggle->toggleList.Num()) {
4589  weaponToggleIndex = 0;
4590  }
4591  }
4592 
4593  num = weaponToggle->toggleList[weaponToggleIndex];
4594  }
4595 #endif
4596 
4597  if ( force || ( inventory.weapons & ( 1 << num ) ) ) {
4598 #ifdef _D3XP
4599  if ( !inventory.HasAmmo( weap, true, this ) && !spawnArgs.GetBool( va( "weapon%d_allowempty", num ) ) ) {
4600 #else
4601  if ( !inventory.HasAmmo( weap ) && !spawnArgs.GetBool( va( "weapon%d_allowempty", num ) ) ) {
4602 #endif
4603  return;
4604  }
4605  if ( ( previousWeapon >= 0 ) && ( idealWeapon == num ) && ( spawnArgs.GetBool( va( "weapon%d_toggle", num ) ) ) ) {
4606  weap = spawnArgs.GetString( va( "def_weapon%d", previousWeapon ) );
4607 #ifdef _D3XP
4608  if ( !inventory.HasAmmo( weap, true, this ) && !spawnArgs.GetBool( va( "weapon%d_allowempty", previousWeapon ) ) ) {
4609 #else
4610  if ( !inventory.HasAmmo( weap ) && !spawnArgs.GetBool( va( "weapon%d_allowempty", previousWeapon ) ) ) {
4611 #endif
4612  return;
4613  }
4614  idealWeapon = previousWeapon;
4615  } else if ( ( weapon_pda >= 0 ) && ( num == weapon_pda ) && ( inventory.pdas.Num() == 0 ) ) {
4616  ShowTip( spawnArgs.GetString( "text_infoTitle" ), spawnArgs.GetString( "text_noPDA" ), true );
4617  return;
4618  } else {
4619  idealWeapon = num;
4620  }
4621  UpdateHudWeapon();
4622  }
4623 }
4624 
4625 /*
4626 =================
4627 idPlayer::DropWeapon
4628 =================
4629 */
4630 void idPlayer::DropWeapon( bool died ) {
4631  idVec3 forward, up;
4632  int inclip, ammoavailable;
4633 
4635 
4636  if ( spectating || weaponGone || weapon.GetEntity() == NULL ) {
4637  return;
4638  }
4639 
4640  if ( ( !died && !weapon.GetEntity()->IsReady() ) || weapon.GetEntity()->IsReloading() ) {
4641  return;
4642  }
4643  // ammoavailable is how many shots we can fire
4644  // inclip is which amount is in clip right now
4645  ammoavailable = weapon.GetEntity()->AmmoAvailable();
4646  inclip = weapon.GetEntity()->AmmoInClip();
4647 
4648  // don't drop a grenade if we have none left
4649  if ( !idStr::Icmp( idWeapon::GetAmmoNameForNum( weapon.GetEntity()->GetAmmoType() ), "ammo_grenades" ) && ( ammoavailable - inclip <= 0 ) ) {
4650  return;
4651  }
4652 
4653 #ifdef _D3XP
4654  ammoavailable += inclip;
4655 #endif
4656 
4657  // expect an ammo setup that makes sense before doing any dropping
4658  // ammoavailable is -1 for infinite ammo, and weapons like chainsaw
4659  // a bad ammo config usually indicates a bad weapon state, so we should not drop
4660  // used to be an assertion check, but it still happens in edge cases
4661 
4662  if ( ( ammoavailable != -1 ) && ( ammoavailable < 0 ) ) {
4663  common->DPrintf( "idPlayer::DropWeapon: bad ammo setup\n" );
4664  return;
4665  }
4666  idEntity *item = NULL;
4667  if ( died ) {
4668  // ain't gonna throw you no weapon if I'm dead
4669  item = weapon.GetEntity()->DropItem( vec3_origin, 0, WEAPON_DROP_TIME, died );
4670  } else {
4671  viewAngles.ToVectors( &forward, NULL, &up );
4672  item = weapon.GetEntity()->DropItem( 250.0f * forward + 150.0f * up, 500, WEAPON_DROP_TIME, died );
4673  }
4674  if ( !item ) {
4675  return;
4676  }
4677  // set the appropriate ammo in the dropped object
4678  const idKeyValue * keyval = item->spawnArgs.MatchPrefix( "inv_ammo_" );
4679  if ( keyval ) {
4680  item->spawnArgs.SetInt( keyval->GetKey(), ammoavailable );
4681  idStr inclipKey = keyval->GetKey();
4682  inclipKey.Insert( "inclip_", 4 );
4683 #ifdef _D3XP
4684  inclipKey.Insert( va("%.2d", currentWeapon), 11);
4685 #endif
4686  item->spawnArgs.SetInt( inclipKey, inclip );
4687  }
4688  if ( !died ) {
4689  // remove from our local inventory completely
4690  inventory.Drop( spawnArgs, item->spawnArgs.GetString( "inv_weapon" ), -1 );
4692  NextWeapon();
4694  weaponGone = true;
4695  }
4696 }
4697 
4698 /*
4699 =================
4700 idPlayer::StealWeapon
4701 steal the target player's current weapon
4702 =================
4703 */
4704 void idPlayer::StealWeapon( idPlayer *player ) {
4706 
4707  // make sure there's something to steal
4708  idWeapon *player_weapon = static_cast< idWeapon * >( player->weapon.GetEntity() );
4709  if ( !player_weapon || !player_weapon->CanDrop() || weaponGone ) {
4710  return;
4711  }
4712  // steal - we need to effectively force the other player to abandon his weapon
4713  int newweap = player->currentWeapon;
4714  if ( newweap == -1 ) {
4715  return;
4716  }
4717  // might be just dropped - check inventory
4718  if ( ! ( player->inventory.weapons & ( 1 << newweap ) ) ) {
4719  return;
4720  }
4721  const char *weapon_classname = spawnArgs.GetString( va( "def_weapon%d", newweap ) );
4722  assert( weapon_classname );
4723  int ammoavailable = player->weapon.GetEntity()->AmmoAvailable();
4724  int inclip = player->weapon.GetEntity()->AmmoInClip();
4725 
4726 #ifdef _D3XP
4727  ammoavailable += inclip;
4728 #endif
4729 
4730  if ( ( ammoavailable != -1 ) && ( ammoavailable < 0 ) ) {
4731  // see DropWeapon
4732  common->DPrintf( "idPlayer::StealWeapon: bad ammo setup\n" );
4733  // we still steal the weapon, so let's use the default ammo levels
4734  inclip = -1;
4735  const idDeclEntityDef *decl = gameLocal.FindEntityDef( weapon_classname );
4736  assert( decl );
4737  const idKeyValue *keypair = decl->dict.MatchPrefix( "inv_ammo_" );
4738  assert( keypair );
4739  ammoavailable = atoi( keypair->GetValue() );
4740  }
4741 
4742  player->weapon.GetEntity()->WeaponStolen();
4743  player->inventory.Drop( player->spawnArgs, NULL, newweap );
4744  player->SelectWeapon( weapon_fists, false );
4745  // in case the robbed player is firing rounds with a continuous fire weapon like the chaingun/plasma etc.
4746  // this will ensure the firing actually stops
4747  player->weaponGone = true;
4748 
4749  // give weapon, setup the ammo count
4750  Give( "weapon", weapon_classname );
4751  ammo_t ammo_i = player->inventory.AmmoIndexForWeaponClass( weapon_classname, NULL );
4752  idealWeapon = newweap;
4753  inventory.ammo[ ammo_i ] += ammoavailable;
4754 
4755 #ifndef _D3XP
4756  inventory.clip[ newweap ] = inclip;
4757 #endif
4758 }
4759 
4760 /*
4761 ===============
4762 idPlayer::ActiveGui
4763 ===============
4764 */
4766  if ( objectiveSystemOpen ) {
4767  return objectiveSystem;
4768  }
4769 
4770  return focusUI;
4771 }
4772 
4773 /*
4774 ===============
4775 idPlayer::Weapon_Combat
4776 ===============
4777 */
4778 void idPlayer::Weapon_Combat( void ) {
4780  return;
4781  }
4782 
4784  if ( weapon.GetEntity()->IsReloading() ) {
4785  if ( !AI_RELOAD ) {
4786  AI_RELOAD = true;
4787  SetState( "ReloadWeapon" );
4788  UpdateScript();
4789  }
4790  } else {
4791  AI_RELOAD = false;
4792  }
4793 
4794  if ( idealWeapon == weapon_soulcube && soulCubeProjectile.GetEntity() != NULL ) {
4795  idealWeapon = currentWeapon;
4796  }
4797 
4798  if ( idealWeapon != currentWeapon ) {
4799  if ( weaponCatchup ) {
4801 
4803  weaponGone = false;
4804  animPrefix = spawnArgs.GetString( va( "def_weapon%d", currentWeapon ) );
4806  animPrefix.Strip( "weapon_" );
4807 
4809  const function_t *newstate = GetScriptFunction( "NetCatchup" );
4810  if ( newstate ) {
4811  SetState( newstate );
4812  UpdateScript();
4813  }
4814  weaponCatchup = false;
4815  } else {
4816  if ( weapon.GetEntity()->IsReady() ) {
4817  weapon.GetEntity()->PutAway();
4818  }
4819 
4820  if ( weapon.GetEntity()->IsHolstered() ) {
4821  assert( idealWeapon >= 0 );
4822  assert( idealWeapon < MAX_WEAPONS );
4823 
4824  if ( currentWeapon != weapon_pda && !spawnArgs.GetBool( va( "weapon%d_toggle", currentWeapon ) ) ) {
4826  }
4828  weaponGone = false;
4829  animPrefix = spawnArgs.GetString( va( "def_weapon%d", currentWeapon ) );
4831  animPrefix.Strip( "weapon_" );
4832 
4833  weapon.GetEntity()->Raise();
4834  }
4835  }
4836  } else {
4837  weaponGone = false; // if you drop and re-get weap, you may miss the = false above
4838  if ( weapon.GetEntity()->IsHolstered() ) {
4839  if ( !weapon.GetEntity()->AmmoAvailable() ) {
4840  // weapons can switch automatically if they have no more ammo
4841  NextBestWeapon();
4842  } else {
4843  weapon.GetEntity()->Raise();
4844  state = GetScriptFunction( "RaiseWeapon" );
4845  if ( state ) {
4846  SetState( state );
4847  }
4848  }
4849  }
4850  }
4851 
4852  // check for attack
4853  AI_WEAPON_FIRED = false;
4854  if ( !influenceActive ) {
4855  if ( ( usercmd.buttons & BUTTON_ATTACK ) && !weaponGone ) {
4856  FireWeapon();
4857  } else if ( oldButtons & BUTTON_ATTACK ) {
4858  AI_ATTACK_HELD = false;
4859  weapon.GetEntity()->EndAttack();
4860  }
4861  }
4862 
4863  // update our ammo clip in our inventory
4864  if ( ( currentWeapon >= 0 ) && ( currentWeapon < MAX_WEAPONS ) ) {
4866  if ( hud && ( currentWeapon == idealWeapon ) ) {
4867  UpdateHudAmmo( hud );
4868  }
4869  }
4870 }
4871 
4872 /*
4873 ===============
4874 idPlayer::Weapon_NPC
4875 ===============
4876 */
4877 void idPlayer::Weapon_NPC( void ) {
4878  if ( idealWeapon != currentWeapon ) {
4879  Weapon_Combat();
4880  }
4881  StopFiring();
4883 
4884  if ( ( usercmd.buttons & BUTTON_ATTACK ) && !( oldButtons & BUTTON_ATTACK ) ) {
4886  focusCharacter->TalkTo( this );
4887  }
4888 }
4889 
4890 /*
4891 ===============
4892 idPlayer::LowerWeapon
4893 ===============
4894 */
4895 void idPlayer::LowerWeapon( void ) {
4896  if ( weapon.GetEntity() && !weapon.GetEntity()->IsHidden() ) {
4898  }
4899 }
4900 
4901 /*
4902 ===============
4903 idPlayer::RaiseWeapon
4904 ===============
4905 */
4906 void idPlayer::RaiseWeapon( void ) {
4907  if ( weapon.GetEntity() && weapon.GetEntity()->IsHidden() ) {
4909  }
4910 }
4911 
4912 /*
4913 ===============
4914 idPlayer::WeaponLoweringCallback
4915 ===============
4916 */
4917 void idPlayer::WeaponLoweringCallback( void ) {
4918  SetState( "LowerWeapon" );
4919  UpdateScript();
4920 }
4921 
4922 /*
4923 ===============
4924 idPlayer::WeaponRisingCallback
4925 ===============
4926 */
4927 void idPlayer::WeaponRisingCallback( void ) {
4928  SetState( "RaiseWeapon" );
4929  UpdateScript();
4930 }
4931 
4932 /*
4933 ===============
4934 idPlayer::Weapon_GUI
4935 ===============
4936 */
4937 void idPlayer::Weapon_GUI( void ) {
4938 
4939  if ( !objectiveSystemOpen ) {
4940  if ( idealWeapon != currentWeapon ) {
4941  Weapon_Combat();
4942  }
4943  StopFiring();
4945  }
4946 
4947  // disable click prediction for the GUIs. handy to check the state sync does the right thing
4949  return;
4950  }
4951 
4952  if ( ( oldButtons ^ usercmd.buttons ) & BUTTON_ATTACK ) {
4953  sysEvent_t ev;
4954  const char *command = NULL;
4955  bool updateVisuals = false;
4956 
4957  idUserInterface *ui = ActiveGui();
4958  if ( ui ) {
4959  ev = sys->GenerateMouseButtonEvent( 1, ( usercmd.buttons & BUTTON_ATTACK ) != 0 );
4960  command = ui->HandleEvent( &ev, gameLocal.time, &updateVisuals );
4961  if ( updateVisuals && focusGUIent && ui == focusUI ) {
4963  }
4964  }
4965  if ( gameLocal.isClient ) {
4966  // we predict enough, but don't want to execute commands
4967  return;
4968  }
4969  if ( focusGUIent ) {
4970  HandleGuiCommands( focusGUIent, command );
4971  } else {
4972  HandleGuiCommands( this, command );
4973  }
4974  }
4975 }
4976 
4977 /*
4978 ===============
4979 idPlayer::UpdateWeapon
4980 ===============
4981 */
4982 void idPlayer::UpdateWeapon( void ) {
4983  if ( health <= 0 ) {
4984  return;
4985  }
4986 
4987  assert( !spectating );
4988 
4989  if ( gameLocal.isClient ) {
4990  // clients need to wait till the weapon and it's world model entity
4991  // are present and synchronized ( weapon.worldModel idEntityPtr to idAnimatedEntity )
4992  if ( !weapon.GetEntity()->IsWorldModelReady() ) {
4993  return;
4994  }
4995  }
4996 
4997  // always make sure the weapon is correctly setup before accessing it
4998  if ( !weapon.GetEntity()->IsLinked() ) {
4999  if ( idealWeapon != -1 ) {
5000  animPrefix = spawnArgs.GetString( va( "def_weapon%d", idealWeapon ) );
5001  weapon.GetEntity()->GetWeaponDef( animPrefix, inventory.clip[ idealWeapon ] );
5002  assert( weapon.GetEntity()->IsLinked() );
5003  } else {
5004  return;
5005  }
5006  }
5007 
5008  if ( hiddenWeapon && tipUp && usercmd.buttons & BUTTON_ATTACK ) {
5009  HideTip();
5010  }
5011 
5012  if ( g_dragEntity.GetBool() ) {
5013  StopFiring();
5015  dragEntity.Update( this );
5016  } else if ( ActiveGui() ) {
5017  // gui handling overrides weapon use
5018  Weapon_GUI();
5019  } else if ( focusCharacter && ( focusCharacter->health > 0 ) ) {
5020  Weapon_NPC();
5021  } else {
5022  Weapon_Combat();
5023  }
5024 
5025  if ( hiddenWeapon ) {
5027  }
5028 
5029  // update weapon state, particles, dlights, etc
5031 }
5032 
5033 /*
5034 ===============
5035 idPlayer::SpectateFreeFly
5036 ===============
5037 */
5038 void idPlayer::SpectateFreeFly( bool force ) {
5039  idPlayer *player;
5040  idVec3 newOrig;
5041  idVec3 spawn_origin;
5042  idAngles spawn_angles;
5043 
5044  player = gameLocal.GetClientByNum( spectator );
5045  if ( force || gameLocal.time > lastSpectateChange ) {
5047  if ( player && player != this && !player->spectating && !player->IsInTeleport() ) {
5048  newOrig = player->GetPhysics()->GetOrigin();
5049  if ( player->physicsObj.IsCrouching() ) {
5050  newOrig[ 2 ] += pm_crouchviewheight.GetFloat();
5051  } else {
5052  newOrig[ 2 ] += pm_normalviewheight.GetFloat();
5053  }
5054  newOrig[ 2 ] += SPECTATE_RAISE;
5056  idVec3 start = player->GetPhysics()->GetOrigin();
5057  start[2] += pm_spectatebbox.GetFloat() * 0.5f;
5058  trace_t t;
5059  // assuming spectate bbox is inside stand or crouch box
5060  gameLocal.clip.TraceBounds( t, start, newOrig, b, MASK_PLAYERSOLID, player );
5061  newOrig.Lerp( start, newOrig, t.fraction );
5062  SetOrigin( newOrig );
5063  idAngles angle = player->viewAngles;
5064  angle[ 2 ] = 0;
5065  SetViewAngles( angle );
5066  } else {
5067  SelectInitialSpawnPoint( spawn_origin, spawn_angles );
5068  spawn_origin[ 2 ] += pm_normalviewheight.GetFloat();
5069  spawn_origin[ 2 ] += SPECTATE_RAISE;
5070  SetOrigin( spawn_origin );
5071  SetViewAngles( spawn_angles );
5072  }
5074  }
5075 }
5076 
5077 /*
5078 ===============
5079 idPlayer::SpectateCycle
5080 ===============
5081 */
5082 void idPlayer::SpectateCycle( void ) {
5083  idPlayer *player;
5084 
5085  if ( gameLocal.time > lastSpectateChange ) {
5086  int latchedSpectator = spectator;
5088  player = gameLocal.GetClientByNum( spectator );
5089  assert( player ); // never call here when the current spectator is wrong
5090  // ignore other spectators
5091  while ( latchedSpectator != spectator && player->spectating ) {
5093  player = gameLocal.GetClientByNum( spectator );
5094  }
5096  }
5097 }
5098 
5099 /*
5100 ===============
5101 idPlayer::UpdateSpectating
5102 ===============
5103 */
5104 void idPlayer::UpdateSpectating( void ) {
5105  assert( spectating );
5107  assert( IsHidden() );
5108  idPlayer *player;
5109  if ( !gameLocal.isMultiplayer ) {
5110  return;
5111  }
5112  player = gameLocal.GetClientByNum( spectator );
5113  if ( !player || ( player->spectating && player != this ) ) {
5114  SpectateFreeFly( true );
5115  } else if ( usercmd.upmove > 0 ) {
5116  SpectateFreeFly( false );
5117  } else if ( usercmd.buttons & BUTTON_ATTACK ) {
5118  SpectateCycle();
5119  }
5120 }
5121 
5122 /*
5123 ===============
5124 idPlayer::HandleSingleGuiCommand
5125 ===============
5126 */
5127 bool idPlayer::HandleSingleGuiCommand( idEntity *entityGui, idLexer *src ) {
5128  idToken token;
5129 
5130  if ( !src->ReadToken( &token ) ) {
5131  return false;
5132  }
5133 
5134  if ( token == ";" ) {
5135  return false;
5136  }
5137 
5138  if ( token.Icmp( "addhealth" ) == 0 ) {
5139  if ( entityGui && health < 100 ) {
5140  int _health = entityGui->spawnArgs.GetInt( "gui_parm1" );
5141  int amt = ( _health >= HEALTH_PER_DOSE ) ? HEALTH_PER_DOSE : _health;
5142  _health -= amt;
5143  entityGui->spawnArgs.SetInt( "gui_parm1", _health );
5144  if ( entityGui->GetRenderEntity() && entityGui->GetRenderEntity()->gui[ 0 ] ) {
5145  entityGui->GetRenderEntity()->gui[ 0 ]->SetStateInt( "gui_parm1", _health );
5146  }
5147  health += amt;
5148  if ( health > 100 ) {
5149  health = 100;
5150  }
5151  }
5152  return true;
5153  }
5154 
5155  if ( token.Icmp( "ready" ) == 0 ) {
5157  return true;
5158  }
5159 
5160  if ( token.Icmp( "updatepda" ) == 0 ) {
5161  UpdatePDAInfo( true );
5162  return true;
5163  }
5164 
5165  if ( token.Icmp( "updatepda2" ) == 0 ) {
5166  UpdatePDAInfo( false );
5167  return true;
5168  }
5169 
5170  if ( token.Icmp( "stoppdavideo" ) == 0 ) {
5172  StopSound( SND_CHANNEL_PDA, false );
5173  }
5174  return true;
5175  }
5176 
5177  if ( token.Icmp( "close" ) == 0 ) {
5179  TogglePDA();
5180  }
5181  }
5182 
5183  if ( token.Icmp( "playpdavideo" ) == 0 ) {
5184  if ( objectiveSystem && objectiveSystemOpen && pdaVideo.Length() > 0 ) {
5185  const idMaterial *mat = declManager->FindMaterial( pdaVideo );
5186  if ( mat ) {
5187  int c = mat->GetNumStages();
5188  for ( int i = 0; i < c; i++ ) {
5189  const shaderStage_t *stage = mat->GetStage(i);
5190  if ( stage && stage->texture.cinematic ) {
5192  }
5193  }
5194  if ( pdaVideoWave.Length() ) {
5195  const idSoundShader *shader = declManager->FindSound( pdaVideoWave );
5196  StartSoundShader( shader, SND_CHANNEL_PDA, 0, false, NULL );
5197  }
5198  }
5199  }
5200  }
5201 
5202  if ( token.Icmp( "playpdaaudio" ) == 0 ) {
5203  if ( objectiveSystem && objectiveSystemOpen && pdaAudio.Length() > 0 ) {
5204  const idSoundShader *shader = declManager->FindSound( pdaAudio );
5205  int ms;
5206  StartSoundShader( shader, SND_CHANNEL_PDA, 0, false, &ms );
5207  StartAudioLog();
5208  CancelEvents( &EV_Player_StopAudioLog );
5209  PostEventMS( &EV_Player_StopAudioLog, ms + 150 );
5210  }
5211  return true;
5212  }
5213 
5214  if ( token.Icmp( "stoppdaaudio" ) == 0 ) {
5215  if ( objectiveSystem && objectiveSystemOpen && pdaAudio.Length() > 0 ) {
5216  // idSoundShader *shader = declManager->FindSound( pdaAudio );
5217  StopAudioLog();
5218  StopSound( SND_CHANNEL_PDA, false );
5219  }
5220  return true;
5221  }
5222 
5223  src->UnreadToken( &token );
5224  return false;
5225 }
5226 
5227 /*
5228 ==============
5229 idPlayer::Collide
5230 ==============
5231 */
5232 bool idPlayer::Collide( const trace_t &collision, const idVec3 &velocity ) {
5233  idEntity *other;
5234 
5235  if ( gameLocal.isClient ) {
5236  return false;
5237  }
5238 
5239  other = gameLocal.entities[ collision.c.entityNum ];
5240  if ( other ) {
5241  other->Signal( SIG_TOUCH );
5242  if ( !spectating ) {
5243  if ( other->RespondsTo( EV_Touch ) ) {
5244  other->ProcessEvent( &EV_Touch, this, &collision );
5245  }
5246  } else {
5247  if ( other->RespondsTo( EV_SpectatorTouch ) ) {
5248  other->ProcessEvent( &EV_SpectatorTouch, this, &collision );
5249  }
5250  }
5251  }
5252  return false;
5253 }
5254 
5255 
5256 /*
5257 ================
5258 idPlayer::UpdateLocation
5259 
5260 Searches nearby locations
5261 ================
5262 */
5263 void idPlayer::UpdateLocation( void ) {
5264  if ( hud ) {
5266  if ( locationEntity ) {
5267  hud->SetStateString( "location", locationEntity->GetLocation() );
5268  } else {
5269  hud->SetStateString( "location", common->GetLanguageDict()->GetString( "#str_02911" ) );
5270  }
5271  }
5272 }
5273 
5274 /*
5275 ================
5276 idPlayer::ClearFocus
5277 
5278 Clears the focus cursor
5279 ================
5280 */
5281 void idPlayer::ClearFocus( void ) {
5282  focusCharacter = NULL;
5283  focusGUIent = NULL;
5284  focusUI = NULL;
5285  focusVehicle = NULL;
5286  talkCursor = 0;
5287 }
5288 
5289 /*
5290 ================
5291 idPlayer::UpdateFocus
5292 
5293 Searches nearby entities for interactive guis, possibly making one of them
5294 the focus and sending it a mouse move event
5295 ================
5296 */
5297 void idPlayer::UpdateFocus( void ) {
5298  idClipModel *clipModelList[ MAX_GENTITIES ];
5299  idClipModel *clip;
5300  int listedClipModels;
5301  idEntity *oldFocus;
5302  idEntity *ent;
5303  idUserInterface *oldUI;
5304  idAI *oldChar;
5305  int oldTalkCursor;
5306  idAFEntity_Vehicle *oldVehicle;
5307  int i, j;
5308  idVec3 start, end;
5309  bool allowFocus;
5310  const char *command;
5311  trace_t trace;
5312  guiPoint_t pt;
5313  const idKeyValue *kv;
5314  sysEvent_t ev;
5315  idUserInterface *ui;
5316 
5317  if ( gameLocal.inCinematic ) {
5318  return;
5319  }
5320 
5321  // only update the focus character when attack button isn't pressed so players
5322  // can still chainsaw NPC's
5323  if ( gameLocal.isMultiplayer || ( !focusCharacter && ( usercmd.buttons & BUTTON_ATTACK ) ) ) {
5324  allowFocus = false;
5325  } else {
5326  allowFocus = true;
5327  }
5328 
5329  oldFocus = focusGUIent;
5330  oldUI = focusUI;
5331  oldChar = focusCharacter;
5332  oldTalkCursor = talkCursor;
5333  oldVehicle = focusVehicle;
5334 
5335  if ( focusTime <= gameLocal.time ) {
5336  ClearFocus();
5337  }
5338 
5339  // don't let spectators interact with GUIs
5340  if ( spectating ) {
5341  return;
5342  }
5343 
5344  start = GetEyePosition();
5345  end = start + viewAngles.ToForward() * 80.0f;
5346 
5347  // player identification -> names to the hud
5349  idVec3 end = start + viewAngles.ToForward() * 768.0f;
5350  gameLocal.clip.TracePoint( trace, start, end, MASK_SHOT_BOUNDINGBOX, this );
5351  int iclient = -1;
5352  if ( ( trace.fraction < 1.0f ) && ( trace.c.entityNum < MAX_CLIENTS ) ) {
5353  iclient = trace.c.entityNum;
5354  }
5355  if ( MPAim != iclient ) {
5356  lastMPAim = MPAim;
5357  MPAim = iclient;
5359  }
5360  }
5361 
5362  idBounds bounds( start );
5363  bounds.AddPoint( end );
5364 
5365  listedClipModels = gameLocal.clip.ClipModelsTouchingBounds( bounds, -1, clipModelList, MAX_GENTITIES );
5366 
5367  // no pretense at sorting here, just assume that there will only be one active
5368  // gui within range along the trace
5369  for ( i = 0; i < listedClipModels; i++ ) {
5370  clip = clipModelList[ i ];
5371  ent = clip->GetEntity();
5372 
5373  if ( ent->IsHidden() ) {
5374  continue;
5375  }
5376 
5377  if ( allowFocus ) {
5378  if ( ent->IsType( idAFAttachment::Type ) ) {
5379  idEntity *body = static_cast<idAFAttachment *>( ent )->GetBody();
5380  if ( body && body->IsType( idAI::Type ) && ( static_cast<idAI *>( body )->GetTalkState() >= TALK_OK ) ) {
5381  gameLocal.clip.TracePoint( trace, start, end, MASK_SHOT_RENDERMODEL, this );
5382  if ( ( trace.fraction < 1.0f ) && ( trace.c.entityNum == ent->entityNumber ) ) {
5383  ClearFocus();
5384  focusCharacter = static_cast<idAI *>( body );
5385  talkCursor = 1;
5387  break;
5388  }
5389  }
5390  continue;
5391  }
5392 
5393  if ( ent->IsType( idAI::Type ) ) {
5394  if ( static_cast<idAI *>( ent )->GetTalkState() >= TALK_OK ) {
5395  gameLocal.clip.TracePoint( trace, start, end, MASK_SHOT_RENDERMODEL, this );
5396  if ( ( trace.fraction < 1.0f ) && ( trace.c.entityNum == ent->entityNumber ) ) {
5397  ClearFocus();
5398  focusCharacter = static_cast<idAI *>( ent );
5399  talkCursor = 1;
5401  break;
5402  }
5403  }
5404  continue;
5405  }
5406 
5407  if ( ent->IsType( idAFEntity_Vehicle::Type ) ) {
5408  gameLocal.clip.TracePoint( trace, start, end, MASK_SHOT_RENDERMODEL, this );
5409  if ( ( trace.fraction < 1.0f ) && ( trace.c.entityNum == ent->entityNumber ) ) {
5410  ClearFocus();
5411  focusVehicle = static_cast<idAFEntity_Vehicle *>( ent );
5413  break;
5414  }
5415  continue;
5416  }
5417  }
5418 
5419  if ( !ent->GetRenderEntity() || !ent->GetRenderEntity()->gui[ 0 ] || !ent->GetRenderEntity()->gui[ 0 ]->IsInteractive() ) {
5420  continue;
5421  }
5422 
5423  if ( ent->spawnArgs.GetBool( "inv_item" ) ) {
5424  // don't allow guis on pickup items focus
5425  continue;
5426  }
5427 
5429  if ( pt.x != -1 ) {
5430  // we have a hit
5431  renderEntity_t *focusGUIrenderEntity = ent->GetRenderEntity();
5432  if ( !focusGUIrenderEntity ) {
5433  continue;
5434  }
5435 
5436  if ( pt.guiId == 1 ) {
5437  ui = focusGUIrenderEntity->gui[ 0 ];
5438  } else if ( pt.guiId == 2 ) {
5439  ui = focusGUIrenderEntity->gui[ 1 ];
5440  } else {
5441  ui = focusGUIrenderEntity->gui[ 2 ];
5442  }
5443 
5444  if ( ui == NULL ) {
5445  continue;
5446  }
5447 
5448  ClearFocus();
5449  focusGUIent = ent;
5450  focusUI = ui;
5451 
5452  if ( oldFocus != ent ) {
5453  // new activation
5454  // going to see if we have anything in inventory a gui might be interested in
5455  // need to enumerate inventory items
5456  focusUI->SetStateInt( "inv_count", inventory.items.Num() );
5457  for ( j = 0; j < inventory.items.Num(); j++ ) {
5458  idDict *item = inventory.items[ j ];
5459  const char *iname = item->GetString( "inv_name" );
5460  const char *iicon = item->GetString( "inv_icon" );
5461  const char *itext = item->GetString( "inv_text" );
5462 
5463  focusUI->SetStateString( va( "inv_name_%i", j), iname );
5464  focusUI->SetStateString( va( "inv_icon_%i", j), iicon );
5465  focusUI->SetStateString( va( "inv_text_%i", j), itext );
5466  kv = item->MatchPrefix("inv_id", NULL);
5467  if ( kv ) {
5468  focusUI->SetStateString( va( "inv_id_%i", j ), kv->GetValue() );
5469  }
5470  focusUI->SetStateInt( iname, 1 );
5471  }
5472 
5473 
5474  for( j = 0; j < inventory.pdaSecurity.Num(); j++ ) {
5475  const char *p = inventory.pdaSecurity[ j ];
5476  if ( p && *p ) {
5477  focusUI->SetStateInt( p, 1 );
5478  }
5479  }
5480 
5481 #ifdef _D3XP //BSM: Added for powercells
5482  int powerCellCount = 0;
5483  for ( j = 0; j < inventory.items.Num(); j++ ) {
5484  idDict *item = inventory.items[ j ];
5485  if(item->GetInt("inv_powercell")) {
5486  powerCellCount++;
5487  }
5488  }
5489  focusUI->SetStateInt( "powercell_count", powerCellCount );
5490 #endif
5491 
5492  int staminapercentage = ( int )( 100.0f * stamina / pm_stamina.GetFloat() );
5493  focusUI->SetStateString( "player_health", va("%i", health ) );
5494  focusUI->SetStateString( "player_stamina", va( "%i%%", staminapercentage ) );
5495  focusUI->SetStateString( "player_armor", va( "%i%%", inventory.armor ) );
5496 
5497  kv = focusGUIent->spawnArgs.MatchPrefix( "gui_parm", NULL );
5498  while ( kv ) {
5499  focusUI->SetStateString( kv->GetKey(), kv->GetValue() );
5500  kv = focusGUIent->spawnArgs.MatchPrefix( "gui_parm", kv );
5501  }
5502  }
5503 
5504  // clamp the mouse to the corner
5505  ev = sys->GenerateMouseMoveEvent( -2000, -2000 );
5506  command = focusUI->HandleEvent( &ev, gameLocal.time );
5507  HandleGuiCommands( focusGUIent, command );
5508 
5509  // move to an absolute position
5511  command = focusUI->HandleEvent( &ev, gameLocal.time );
5512  HandleGuiCommands( focusGUIent, command );
5514  break;
5515  }
5516  }
5517 
5518  if ( focusGUIent && focusUI ) {
5519  if ( !oldFocus || oldFocus != focusGUIent ) {
5520  command = focusUI->Activate( true, gameLocal.time );
5521  HandleGuiCommands( focusGUIent, command );
5522  StartSound( "snd_guienter", SND_CHANNEL_ANY, 0, false, NULL );
5523  // HideTip();
5524  // HideObjective();
5525  }
5526  } else if ( oldFocus && oldUI ) {
5527  command = oldUI->Activate( false, gameLocal.time );
5528  HandleGuiCommands( oldFocus, command );
5529  StartSound( "snd_guiexit", SND_CHANNEL_ANY, 0, false, NULL );
5530  }
5531 
5532  if ( cursor && ( oldTalkCursor != talkCursor ) ) {
5533  cursor->SetStateInt( "talkcursor", talkCursor );
5534  }
5535 
5536  if ( oldChar != focusCharacter && hud ) {
5537  if ( focusCharacter ) {
5538  hud->SetStateString( "npc", focusCharacter->spawnArgs.GetString( "npc_name", "Joe" ) );
5539 #ifdef _D3XP
5540  //Use to code to update the npc action string to fix bug 1159
5541  hud->SetStateString( "npc_action", common->GetLanguageDict()->GetString( "#str_02036" ));
5542 #endif
5543  hud->HandleNamedEvent( "showNPC" );
5544  // HideTip();
5545  // HideObjective();
5546  } else {
5547  hud->SetStateString( "npc", "" );
5548 #ifdef _D3XP
5549  hud->SetStateString( "npc_action", "" );
5550 #endif
5551  hud->HandleNamedEvent( "hideNPC" );
5552  }
5553  }
5554 }
5555 
5556 /*
5557 =================
5558 idPlayer::CrashLand
5559 
5560 Check for hard landings that generate sound events
5561 =================
5562 */
5563 void idPlayer::CrashLand( const idVec3 &oldOrigin, const idVec3 &oldVelocity ) {
5564  idVec3 origin, velocity;
5565  idVec3 gravityVector, gravityNormal;
5566  float delta;
5567  float hardDelta, fatalDelta;
5568  float dist;
5569  float vel, acc;
5570  float t;
5571  float a, b, c, den;
5572  waterLevel_t waterLevel;
5573  bool noDamage;
5574 
5575  AI_SOFTLANDING = false;
5576  AI_HARDLANDING = false;
5577 
5578  // if the player is not on the ground
5579  if ( !physicsObj.HasGroundContacts() ) {
5580  return;
5581  }
5582 
5583  gravityNormal = physicsObj.GetGravityNormal();
5584 
5585  // if the player wasn't going down
5586  if ( ( oldVelocity * -gravityNormal ) >= 0.0f ) {
5587  return;
5588  }
5589 
5590  waterLevel = physicsObj.GetWaterLevel();
5591 
5592  // never take falling damage if completely underwater
5593  if ( waterLevel == WATERLEVEL_HEAD ) {
5594  return;
5595  }
5596 
5597  // no falling damage if touching a nodamage surface
5598  noDamage = false;
5599  for ( int i = 0; i < physicsObj.GetNumContacts(); i++ ) {
5600  const contactInfo_t &contact = physicsObj.GetContact( i );
5601  if ( contact.material->GetSurfaceFlags() & SURF_NODAMAGE ) {
5602  noDamage = true;
5603  StartSound( "snd_land_hard", SND_CHANNEL_ANY, 0, false, NULL );
5604  break;
5605  }
5606  }
5607 
5608  origin = GetPhysics()->GetOrigin();
5609  gravityVector = physicsObj.GetGravity();
5610 
5611  // calculate the exact velocity on landing
5612  dist = ( origin - oldOrigin ) * -gravityNormal;
5613  vel = oldVelocity * -gravityNormal;
5614  acc = -gravityVector.Length();
5615 
5616  a = acc / 2.0f;
5617  b = vel;
5618  c = -dist;
5619 
5620  den = b * b - 4.0f * a * c;
5621  if ( den < 0 ) {
5622  return;
5623  }
5624  t = ( -b - idMath::Sqrt( den ) ) / ( 2.0f * a );
5625 
5626  delta = vel + t * acc;
5627  delta = delta * delta * 0.0001;
5628 
5629  // reduce falling damage if there is standing water
5630  if ( waterLevel == WATERLEVEL_WAIST ) {
5631  delta *= 0.25f;
5632  }
5633  if ( waterLevel == WATERLEVEL_FEET ) {
5634  delta *= 0.5f;
5635  }
5636 
5637  if ( delta < 1.0f ) {
5638  return;
5639  }
5640 
5641  // allow falling a bit further for multiplayer
5642  if ( gameLocal.isMultiplayer ) {
5643  fatalDelta = 75.0f;
5644  hardDelta = 50.0f;
5645  } else {
5646  fatalDelta = 65.0f;
5647  hardDelta = 45.0f;
5648  }
5649 
5650  if ( delta > fatalDelta ) {
5651  AI_HARDLANDING = true;
5652  landChange = -32;
5654  if ( !noDamage ) {
5655  pain_debounce_time = gameLocal.time + pain_delay + 1; // ignore pain since we'll play our landing anim
5656  Damage( NULL, NULL, idVec3( 0, 0, -1 ), "damage_fatalfall", 1.0f, 0 );
5657  }
5658  } else if ( delta > hardDelta ) {
5659  AI_HARDLANDING = true;
5660  landChange = -24;
5662  if ( !noDamage ) {
5663  pain_debounce_time = gameLocal.time + pain_delay + 1; // ignore pain since we'll play our landing anim
5664  Damage( NULL, NULL, idVec3( 0, 0, -1 ), "damage_hardfall", 1.0f, 0 );
5665  }
5666  } else if ( delta > 30 ) {
5667  AI_HARDLANDING = true;
5668  landChange = -16;
5670  if ( !noDamage ) {
5671  pain_debounce_time = gameLocal.time + pain_delay + 1; // ignore pain since we'll play our landing anim
5672  Damage( NULL, NULL, idVec3( 0, 0, -1 ), "damage_softfall", 1.0f, 0 );
5673  }
5674  } else if ( delta > 7 ) {
5675  AI_SOFTLANDING = true;
5676  landChange = -8;
5678  } else if ( delta > 3 ) {
5679  // just walk on
5680  }
5681 }
5682 
5683 /*
5684 ===============
5685 idPlayer::BobCycle
5686 ===============
5687 */
5688 void idPlayer::BobCycle( const idVec3 &pushVelocity ) {
5689  float bobmove;
5690  int old, deltaTime;
5691  idVec3 vel, gravityDir, velocity;
5692  idMat3 viewaxis;
5693  float bob;
5694  float delta;
5695  float speed;
5696  float f;
5697 
5698  //
5699  // calculate speed and cycle to be used for
5700  // all cyclic walking effects
5701  //
5702  velocity = physicsObj.GetLinearVelocity() - pushVelocity;
5703 
5704  gravityDir = physicsObj.GetGravityNormal();
5705  vel = velocity - ( velocity * gravityDir ) * gravityDir;
5706  xyspeed = vel.LengthFast();
5707 
5708  // do not evaluate the bob for other clients
5709  // when doing a spectate follow, don't do any weapon bobbing
5711  viewBobAngles.Zero();
5712  viewBob.Zero();
5713  return;
5714  }
5715 
5717  // airborne
5718  bobCycle = 0;
5719  bobFoot = 0;
5720  bobfracsin = 0;
5721  } else if ( ( !usercmd.forwardmove && !usercmd.rightmove ) || ( xyspeed <= MIN_BOB_SPEED ) ) {
5722  // start at beginning of cycle again
5723  bobCycle = 0;
5724  bobFoot = 0;
5725  bobfracsin = 0;
5726  } else {
5727  if ( physicsObj.IsCrouching() ) {
5728  bobmove = pm_crouchbob.GetFloat();
5729  // ducked characters never play footsteps
5730  } else {
5731  // vary the bobbing based on the speed of the player
5732  bobmove = pm_walkbob.GetFloat() * ( 1.0f - bobFrac ) + pm_runbob.GetFloat() * bobFrac;
5733  }
5734 
5735  // check for footstep / splash sounds
5736  old = bobCycle;
5737  bobCycle = (int)( old + bobmove * gameLocal.msec ) & 255;
5738  bobFoot = ( bobCycle & 128 ) >> 7;
5739  bobfracsin = idMath::Fabs( sin( ( bobCycle & 127 ) / 127.0 * idMath::PI ) );
5740  }
5741 
5742  // calculate angles for view bobbing
5743  viewBobAngles.Zero();
5744 
5745  viewaxis = viewAngles.ToMat3() * physicsObj.GetGravityAxis();
5746 
5747  // add angles based on velocity
5748  delta = velocity * viewaxis[0];
5749  viewBobAngles.pitch += delta * pm_runpitch.GetFloat();
5750 
5751  delta = velocity * viewaxis[1];
5752  viewBobAngles.roll -= delta * pm_runroll.GetFloat();
5753 
5754  // add angles based on bob
5755  // make sure the bob is visible even at low speeds
5756  speed = xyspeed > 200 ? xyspeed : 200;
5757 
5758  delta = bobfracsin * pm_bobpitch.GetFloat() * speed;
5759  if ( physicsObj.IsCrouching() ) {
5760  delta *= 3; // crouching
5761  }
5762  viewBobAngles.pitch += delta;
5763  delta = bobfracsin * pm_bobroll.GetFloat() * speed;
5764  if ( physicsObj.IsCrouching() ) {
5765  delta *= 3; // crouching accentuates roll
5766  }
5767  if ( bobFoot & 1 ) {
5768  delta = -delta;
5769  }
5770  viewBobAngles.roll += delta;
5771 
5772  // calculate position for view bobbing
5773  viewBob.Zero();
5774 
5775  if ( physicsObj.HasSteppedUp() ) {
5776 
5777  // check for stepping up before a previous step is completed
5778  deltaTime = gameLocal.time - stepUpTime;
5779  if ( deltaTime < STEPUP_TIME ) {
5780  stepUpDelta = stepUpDelta * ( STEPUP_TIME - deltaTime ) / STEPUP_TIME + physicsObj.GetStepUp();
5781  } else {
5783  }
5784  if ( stepUpDelta > 2.0f * pm_stepsize.GetFloat() ) {
5785  stepUpDelta = 2.0f * pm_stepsize.GetFloat();
5786  }
5787  stepUpTime = gameLocal.time;
5788  }
5789 
5790  idVec3 gravity = physicsObj.GetGravityNormal();
5791 
5792  // if the player stepped up recently
5793  deltaTime = gameLocal.time - stepUpTime;
5794  if ( deltaTime < STEPUP_TIME ) {
5795  viewBob += gravity * ( stepUpDelta * ( STEPUP_TIME - deltaTime ) / STEPUP_TIME );
5796  }
5797 
5798  // add bob height after any movement smoothing
5799  bob = bobfracsin * xyspeed * pm_bobup.GetFloat();
5800  if ( bob > 6 ) {
5801  bob = 6;
5802  }
5803  viewBob[2] += bob;
5804 
5805  // add fall height
5806  delta = gameLocal.time - landTime;
5807  if ( delta < LAND_DEFLECT_TIME ) {
5808  f = delta / LAND_DEFLECT_TIME;
5809  viewBob -= gravity * ( landChange * f );
5810  } else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
5811  delta -= LAND_DEFLECT_TIME;
5812  f = 1.0 - ( delta / LAND_RETURN_TIME );
5813  viewBob -= gravity * ( landChange * f );
5814  }
5815 }
5816 
5817 /*
5818 ================
5819 idPlayer::UpdateDeltaViewAngles
5820 ================
5821 */
5822 void idPlayer::UpdateDeltaViewAngles( const idAngles &angles ) {
5823  // set the delta angle
5824  idAngles delta;
5825  for( int i = 0; i < 3; i++ ) {
5826  delta[ i ] = angles[ i ] - SHORT2ANGLE( usercmd.angles[ i ] );
5827  }
5828  SetDeltaViewAngles( delta );
5829 }
5830 
5831 /*
5832 ================
5833 idPlayer::SetViewAngles
5834 ================
5835 */
5836 void idPlayer::SetViewAngles( const idAngles &angles ) {
5837  UpdateDeltaViewAngles( angles );
5838  viewAngles = angles;
5839 }
5840 
5841 /*
5842 ================
5843 idPlayer::UpdateViewAngles
5844 ================
5845 */
5846 void idPlayer::UpdateViewAngles( void ) {
5847  int i;
5848  idAngles delta;
5849 
5851  // no view changes at all, but we still want to update the deltas or else when
5852  // we get out of this mode, our view will snap to a kind of random angle
5854  return;
5855  }
5856 
5857  // if dead
5858  if ( health <= 0 ) {
5859  if ( pm_thirdPersonDeath.GetBool() ) {
5860  viewAngles.roll = 0.0f;
5861  viewAngles.pitch = 30.0f;
5862  } else {
5863  viewAngles.roll = 40.0f;
5864  viewAngles.pitch = -15.0f;
5865  }
5866  return;
5867  }
5868 
5869  // circularly clamp the angles with deltas
5870  for ( i = 0; i < 3; i++ ) {
5872  if ( influenceActive == INFLUENCE_LEVEL3 ) {
5874  } else {
5876  }
5877  }
5878  if ( !centerView.IsDone( gameLocal.time ) ) {
5880  }
5881 
5882  // clamp the pitch
5883  if ( noclip ) {
5884  if ( viewAngles.pitch > 89.0f ) {
5885  // don't let the player look down more than 89 degrees while noclipping
5886  viewAngles.pitch = 89.0f;
5887  } else if ( viewAngles.pitch < -89.0f ) {
5888  // don't let the player look up more than 89 degrees while noclipping
5889  viewAngles.pitch = -89.0f;
5890  }
5891 #ifdef _D3XP
5892  } else if ( mountedObject ) {
5893  int yaw_min, yaw_max, varc;
5894 
5895  mountedObject->GetAngleRestrictions( yaw_min, yaw_max, varc );
5896 
5897  if ( yaw_min < yaw_max ) {
5898  viewAngles.yaw = idMath::ClampFloat( yaw_min, yaw_max, viewAngles.yaw );
5899  } else {
5900  if ( viewAngles.yaw < 0 ) {
5901  viewAngles.yaw = idMath::ClampFloat( -180.f, yaw_max, viewAngles.yaw );
5902  } else {
5903  viewAngles.yaw = idMath::ClampFloat( yaw_min, 180.f, viewAngles.yaw );
5904  }
5905  }
5907 #endif
5908  } else {
5910  // don't let the player look down enough to see the shadow of his (non-existant) feet
5912  } else if ( viewAngles.pitch < pm_minviewpitch.GetFloat() ) {
5913  // don't let the player look up more than 89 degrees
5915  }
5916  }
5917 
5919 
5920  // orient the model towards the direction we're looking
5921  SetAngles( idAngles( 0, viewAngles.yaw, 0 ) );
5922 
5923  // save in the log for analyzing weapon angle offsets
5924  loggedViewAngles[ gameLocal.framenum & (NUM_LOGGED_VIEW_ANGLES-1) ] = viewAngles;
5925 }
5926 
5927 /*
5928 ==============
5929 idPlayer::AdjustHeartRate
5930 
5931 Player heartrate works as follows
5932 
5933 DEF_HEARTRATE is resting heartrate
5934 
5935 Taking damage when health is above 75 adjusts heart rate by 1 beat per second
5936 Taking damage when health is below 75 adjusts heart rate by 5 beats per second
5937 Maximum heartrate from damage is MAX_HEARTRATE
5938 
5939 Firing a weapon adds 1 beat per second up to a maximum of COMBAT_HEARTRATE
5940 
5941 Being at less than 25% stamina adds 5 beats per second up to ZEROSTAMINA_HEARTRATE
5942 
5943 All heartrates are target rates.. the heart rate will start falling as soon as there have been no adjustments for 5 seconds
5944 Once it starts falling it always tries to get to DEF_HEARTRATE
5945 
5946 The exception to the above rule is upon death at which point the rate is set to DYING_HEARTRATE and starts falling
5947 immediately to zero
5948 
5949 Heart rate volumes go from zero ( -40 db for DEF_HEARTRATE to 5 db for MAX_HEARTRATE ) the volume is
5950 scaled linearly based on the actual rate
5951 
5952 Exception to the above rule is once the player is dead, the dying heart rate starts at either the current volume if
5953 it is audible or -10db and scales to 8db on the last few beats
5954 ==============
5955 */
5956 void idPlayer::AdjustHeartRate( int target, float timeInSecs, float delay, bool force ) {
5957 
5958  if ( heartInfo.GetEndValue() == target ) {
5959  return;
5960  }
5961 
5962  if ( AI_DEAD && !force ) {
5963  return;
5964  }
5965 
5967 
5968  heartInfo.Init( gameLocal.time + delay * 1000, timeInSecs * 1000, heartRate, target );
5969 }
5970 
5971 /*
5972 ==============
5973 idPlayer::GetBaseHeartRate
5974 ==============
5975 */
5976 int idPlayer::GetBaseHeartRate( void ) {
5977  int base = idMath::FtoiFast( ( BASE_HEARTRATE + LOWHEALTH_HEARTRATE_ADJ ) - ( (float)health / 100.0f ) * LOWHEALTH_HEARTRATE_ADJ );
5978  int rate = idMath::FtoiFast( base + ( ZEROSTAMINA_HEARTRATE - base ) * ( 1.0f - stamina / pm_stamina.GetFloat() ) );
5979  int diff = ( lastDmgTime ) ? gameLocal.time - lastDmgTime : 99999;
5980  rate += ( diff < 5000 ) ? ( diff < 2500 ) ? ( diff < 1000 ) ? 15 : 10 : 5 : 0;
5981  return rate;
5982 }
5983 
5984 /*
5985 ==============
5986 idPlayer::SetCurrentHeartRate
5987 ==============
5988 */
5989 void idPlayer::SetCurrentHeartRate( void ) {
5990 
5991  int base = idMath::FtoiFast( ( BASE_HEARTRATE + LOWHEALTH_HEARTRATE_ADJ ) - ( (float) health / 100.0f ) * LOWHEALTH_HEARTRATE_ADJ );
5992 
5993  if ( PowerUpActive( ADRENALINE )) {
5994  heartRate = 135;
5995  } else {
5997  int currentRate = GetBaseHeartRate();
5998  if ( health >= 0 && gameLocal.time > lastHeartAdjust + 2500 ) {
5999  AdjustHeartRate( currentRate, 2.5f, 0.0f, false );
6000  }
6001  }
6002 
6003  int bps = idMath::FtoiFast( 60.0f / heartRate * 1000.0f );
6004  if ( gameLocal.time - lastHeartBeat > bps ) {
6005  int dmgVol = DMG_VOLUME;
6006  int deathVol = DEATH_VOLUME;
6007  int zeroVol = ZERO_VOLUME;
6008  float pct = 0.0;
6009  if ( heartRate > BASE_HEARTRATE && health > 0 ) {
6010  pct = (float)(heartRate - base) / (MAX_HEARTRATE - base);
6011  pct *= ((float)dmgVol - (float)zeroVol);
6012  } else if ( health <= 0 ) {
6014  if ( pct > 1.0f ) {
6015  pct = 1.0f;
6016  } else if (pct < 0.0f) {
6017  pct = 0.0f;
6018  }
6019  pct *= ((float)deathVol - (float)zeroVol);
6020  }
6021 
6022  pct += (float)zeroVol;
6023 
6024  if ( pct != zeroVol ) {
6025  StartSound( "snd_heartbeat", SND_CHANNEL_HEART, SSF_PRIVATE_SOUND, false, NULL );
6026  // modify just this channel to a custom volume
6027  soundShaderParms_t parms;
6028  memset( &parms, 0, sizeof( parms ) );
6029  parms.volume = pct;
6031  }
6032 
6034  }
6035 }
6036 
6037 /*
6038 ==============
6039 idPlayer::UpdateAir
6040 ==============
6041 */
6042 void idPlayer::UpdateAir( void ) {
6043  if ( health <= 0 ) {
6044  return;
6045  }
6046 
6047  // see if the player is connected to the info_vacuum
6048  bool newAirless = false;
6049 
6050  if ( gameLocal.vacuumAreaNum != -1 ) {
6051  int num = GetNumPVSAreas();
6052  if ( num > 0 ) {
6053  int areaNum;
6054 
6055  // if the player box spans multiple areas, get the area from the origin point instead,
6056  // otherwise a rotating player box may poke into an outside area
6057  if ( num == 1 ) {
6058  const int *pvsAreas = GetPVSAreas();
6059  areaNum = pvsAreas[0];
6060  } else {
6061  areaNum = gameRenderWorld->PointInArea( this->GetPhysics()->GetOrigin() );
6062  }
6064  }
6065  }
6066 
6067 #ifdef _D3XP
6068  if ( PowerUpActive( ENVIROTIME ) ) {
6069  newAirless = false;
6070  }
6071 #endif
6072 
6073  if ( newAirless ) {
6074  if ( !airless ) {
6075  StartSound( "snd_decompress", SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL );
6076  StartSound( "snd_noAir", SND_CHANNEL_BODY2, 0, false, NULL );
6077  if ( hud ) {
6078  hud->HandleNamedEvent( "noAir" );
6079  }
6080  }
6081  airTics--;
6082  if ( airTics < 0 ) {
6083  airTics = 0;
6084  // check for damage
6085  const idDict *damageDef = gameLocal.FindEntityDefDict( "damage_noair", false );
6086  int dmgTiming = 1000 * ((damageDef) ? damageDef->GetFloat( "delay", "3.0" ) : 3.0f );
6087  if ( gameLocal.time > lastAirDamage + dmgTiming ) {
6088  Damage( NULL, NULL, vec3_origin, "damage_noair", 1.0f, 0 );
6090  }
6091  }
6092 
6093  } else {
6094  if ( airless ) {
6095  StartSound( "snd_recompress", SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL );
6096  StopSound( SND_CHANNEL_BODY2, false );
6097  if ( hud ) {
6098  hud->HandleNamedEvent( "Air" );
6099  }
6100  }
6101  airTics+=2; // regain twice as fast as lose
6102  if ( airTics > pm_airTics.GetInteger() ) {
6104  }
6105  }
6106 
6107  airless = newAirless;
6108 
6109  if ( hud ) {
6110  hud->SetStateInt( "player_air", 100 * airTics / pm_airTics.GetInteger() );
6111  }
6112 }
6113 
6114 void idPlayer::UpdatePowerupHud() {
6115 
6116  if ( health <= 0 ) {
6117  return;
6118  }
6119 
6120  if(lastHudPowerup != hudPowerup) {
6121 
6122  if(hudPowerup == -1) {
6123  //The powerup hud should be turned off
6124  if ( hud ) {
6125  hud->HandleNamedEvent( "noPowerup" );
6126  }
6127  } else {
6128  //Turn the pwoerup hud on
6129  if ( hud ) {
6130  hud->HandleNamedEvent( "Powerup" );
6131  }
6132  }
6133 
6134  lastHudPowerup = hudPowerup;
6135  }
6136 
6137  if(hudPowerup != -1) {
6138  if(PowerUpActive(hudPowerup)) {
6139  int remaining = inventory.powerupEndTime[ hudPowerup ] - gameLocal.time;
6140  int filledbar = idMath::ClampInt( 0, hudPowerupDuration, remaining );
6141 
6142  if ( hud ) {
6143  hud->SetStateInt( "player_powerup", 100 * filledbar / hudPowerupDuration );
6144  hud->SetStateInt( "player_poweruptime", remaining / 1000 );
6145  }
6146  }
6147  }
6148 }
6149 
6150 /*
6151 ==============
6152 idPlayer::AddGuiPDAData
6153 ==============
6154  */
6155 int idPlayer::AddGuiPDAData( const declType_t dataType, const char *listName, const idDeclPDA *src, idUserInterface *gui ) {
6156  int c, i;
6157  idStr work;
6158  if ( dataType == DECL_EMAIL ) {
6159  c = src->GetNumEmails();
6160  for ( i = 0; i < c; i++ ) {
6161  const idDeclEmail *email = src->GetEmailByIndex( i );
6162  if ( email == NULL ) {
6163  work = va( "-\tEmail %d not found\t-", i );
6164  } else {
6165  work = email->GetFrom();
6166  work += "\t";
6167  work += email->GetSubject();
6168  work += "\t";
6169  work += email->GetDate();
6170  }
6171  gui->SetStateString( va( "%s_item_%i", listName, i ), work );
6172  }
6173  return c;
6174  } else if ( dataType == DECL_AUDIO ) {
6175  c = src->GetNumAudios();
6176  for ( i = 0; i < c; i++ ) {
6177  const idDeclAudio *audio = src->GetAudioByIndex( i );
6178  if ( audio == NULL ) {
6179  work = va( "Audio Log %d not found", i );
6180  } else {
6181  work = audio->GetAudioName();
6182  }
6183  gui->SetStateString( va( "%s_item_%i", listName, i ), work );
6184  }
6185  return c;
6186  } else if ( dataType == DECL_VIDEO ) {
6187  c = inventory.videos.Num();
6188  for ( i = 0; i < c; i++ ) {
6189  const idDeclVideo *video = GetVideo( i );
6190  if ( video == NULL ) {
6191  work = va( "Video CD %s not found", inventory.videos[i].c_str() );
6192  } else {
6193  work = video->GetVideoName();
6194  }
6195  gui->SetStateString( va( "%s_item_%i", listName, i ), work );
6196  }
6197  return c;
6198  }
6199  return 0;
6200 }
6201 
6202 /*
6203 ==============
6204 idPlayer::GetPDA
6205 ==============
6206  */
6207 const idDeclPDA *idPlayer::GetPDA( void ) const {
6208  if ( inventory.pdas.Num() ) {
6209  return static_cast< const idDeclPDA* >( declManager->FindType( DECL_PDA, inventory.pdas[ 0 ] ) );
6210  } else {
6211  return NULL;
6212  }
6213 }
6214 
6215 
6216 /*
6217 ==============
6218 idPlayer::GetVideo
6219 ==============
6220 */
6221 const idDeclVideo *idPlayer::GetVideo( int index ) {
6222  if ( index >= 0 && index < inventory.videos.Num() ) {
6223  return static_cast< const idDeclVideo* >( declManager->FindType( DECL_VIDEO, inventory.videos[index], false ) );
6224  }
6225  return NULL;
6226 }
6227 
6228 
6229 /*
6230 ==============
6231 idPlayer::UpdatePDAInfo
6232 ==============
6233 */
6234 void idPlayer::UpdatePDAInfo( bool updatePDASel ) {
6235  int j, sel;
6236 
6237  if ( objectiveSystem == NULL ) {
6238  return;
6239  }
6240 
6241  assert( hud );
6242 
6243  int currentPDA = objectiveSystem->State().GetInt( "listPDA_sel_0", "0" );
6244  if ( currentPDA == -1 ) {
6245  currentPDA = 0;
6246  }
6247 
6248  if ( updatePDASel ) {
6249  objectiveSystem->SetStateInt( "listPDAVideo_sel_0", 0 );
6250  objectiveSystem->SetStateInt( "listPDAEmail_sel_0", 0 );
6251  objectiveSystem->SetStateInt( "listPDAAudio_sel_0", 0 );
6252  }
6253 
6254  if ( currentPDA > 0 ) {
6255  currentPDA = inventory.pdas.Num() - currentPDA;
6256  }
6257 
6258  // Mark in the bit array that this pda has been read
6259  if ( currentPDA < 128 ) {
6260  inventory.pdasViewed[currentPDA >> 5] |= 1 << (currentPDA & 31);
6261  }
6262 
6263  pdaAudio = "";
6264  pdaVideo = "";
6265  pdaVideoWave = "";
6266  idStr name, data, preview, info, wave;
6267  for ( j = 0; j < MAX_PDAS; j++ ) {
6268  objectiveSystem->SetStateString( va( "listPDA_item_%i", j ), "" );
6269  }
6270  for ( j = 0; j < MAX_PDA_ITEMS; j++ ) {
6271  objectiveSystem->SetStateString( va( "listPDAVideo_item_%i", j ), "" );
6272  objectiveSystem->SetStateString( va( "listPDAAudio_item_%i", j ), "" );
6273  objectiveSystem->SetStateString( va( "listPDAEmail_item_%i", j ), "" );
6274  objectiveSystem->SetStateString( va( "listPDASecurity_item_%i", j ), "" );
6275  }
6276  for ( j = 0; j < inventory.pdas.Num(); j++ ) {
6277 
6278  const idDeclPDA *pda = static_cast< const idDeclPDA* >( declManager->FindType( DECL_PDA, inventory.pdas[j], false ) );
6279 
6280  if ( pda == NULL ) {
6281  continue;
6282  }
6283 
6284  int index = inventory.pdas.Num() - j;
6285  if ( j == 0 ) {
6286  // Special case for the first PDA
6287  index = 0;
6288  }
6289 
6290  if ( j != currentPDA && j < 128 && inventory.pdasViewed[j >> 5] & (1 << (j & 31)) ) {
6291  // This pda has been read already, mark in gray
6292  objectiveSystem->SetStateString( va( "listPDA_item_%i", index), va(S_COLOR_GRAY "%s", pda->GetPdaName()) );
6293  } else {
6294  // This pda has not been read yet
6295  objectiveSystem->SetStateString( va( "listPDA_item_%i", index), pda->GetPdaName() );
6296  }
6297 
6298  const char *security = pda->GetSecurity();
6299  if ( j == currentPDA || (currentPDA == 0 && security && *security ) ) {
6300  if ( *security == '\0' ) {
6301  security = common->GetLanguageDict()->GetString( "#str_00066" );
6302  }
6303  objectiveSystem->SetStateString( "PDASecurityClearance", security );
6304  }
6305 
6306  if ( j == currentPDA ) {
6307 
6308  objectiveSystem->SetStateString( "pda_icon", pda->GetIcon() );
6309  objectiveSystem->SetStateString( "pda_id", pda->GetID() );
6310  objectiveSystem->SetStateString( "pda_title", pda->GetTitle() );
6311 
6312  if ( j == 0 ) {
6313  // Selected, personal pda
6314  // Add videos
6315  if ( updatePDASel || !inventory.pdaOpened ) {
6316  objectiveSystem->HandleNamedEvent( "playerPDAActive" );
6317  objectiveSystem->SetStateString( "pda_personal", "1" );
6318  inventory.pdaOpened = true;
6319  }
6320  objectiveSystem->SetStateString( "pda_location", hud->State().GetString("location") );
6321  objectiveSystem->SetStateString( "pda_name", cvarSystem->GetCVarString( "ui_name") );
6322  AddGuiPDAData( DECL_VIDEO, "listPDAVideo", pda, objectiveSystem );
6323  sel = objectiveSystem->State().GetInt( "listPDAVideo_sel_0", "0" );
6324  const idDeclVideo *vid = NULL;
6325  if ( sel >= 0 && sel < inventory.videos.Num() ) {
6326  vid = static_cast< const idDeclVideo * >( declManager->FindType( DECL_VIDEO, inventory.videos[ sel ], false ) );
6327  }
6328  if ( vid ) {
6329  pdaVideo = vid->GetRoq();
6330  pdaVideoWave = vid->GetWave();
6331  objectiveSystem->SetStateString( "PDAVideoTitle", vid->GetVideoName() );
6332  objectiveSystem->SetStateString( "PDAVideoVid", vid->GetRoq() );
6333  objectiveSystem->SetStateString( "PDAVideoIcon", vid->GetPreview() );
6334  objectiveSystem->SetStateString( "PDAVideoInfo", vid->GetInfo() );
6335  } else {
6336  //FIXME: need to precache these in the player def
6337  objectiveSystem->SetStateString( "PDAVideoVid", "sound/vo/video/welcome.tga" );
6338  objectiveSystem->SetStateString( "PDAVideoIcon", "sound/vo/video/welcome.tga" );
6339  objectiveSystem->SetStateString( "PDAVideoTitle", "" );
6340  objectiveSystem->SetStateString( "PDAVideoInfo", "" );
6341  }
6342  } else {
6343  // Selected, non-personal pda
6344  // Add audio logs
6345  if ( updatePDASel ) {
6346  objectiveSystem->HandleNamedEvent( "playerPDANotActive" );
6347  objectiveSystem->SetStateString( "pda_personal", "0" );
6348  inventory.pdaOpened = true;
6349  }
6350  objectiveSystem->SetStateString( "pda_location", pda->GetPost() );
6351  objectiveSystem->SetStateString( "pda_name", pda->GetFullName() );
6352  int audioCount = AddGuiPDAData( DECL_AUDIO, "listPDAAudio", pda, objectiveSystem );
6353  objectiveSystem->SetStateInt( "audioLogCount", audioCount );
6354  sel = objectiveSystem->State().GetInt( "listPDAAudio_sel_0", "0" );
6355  const idDeclAudio *aud = NULL;
6356  if ( sel >= 0 ) {
6357  aud = pda->GetAudioByIndex( sel );
6358  }
6359  if ( aud ) {
6360  pdaAudio = aud->GetWave();
6361  objectiveSystem->SetStateString( "PDAAudioTitle", aud->GetAudioName() );
6362  objectiveSystem->SetStateString( "PDAAudioIcon", aud->GetPreview() );
6363  objectiveSystem->SetStateString( "PDAAudioInfo", aud->GetInfo() );
6364  } else {
6365  objectiveSystem->SetStateString( "PDAAudioIcon", "sound/vo/video/welcome.tga" );
6366  objectiveSystem->SetStateString( "PDAAutioTitle", "" );
6367  objectiveSystem->SetStateString( "PDAAudioInfo", "" );
6368  }
6369  }
6370  // add emails
6371  name = "";
6372  data = "";
6373  int numEmails = pda->GetNumEmails();
6374  if ( numEmails > 0 ) {
6375  AddGuiPDAData( DECL_EMAIL, "listPDAEmail", pda, objectiveSystem );
6376  sel = objectiveSystem->State().GetInt( "listPDAEmail_sel_0", "-1" );
6377  if ( sel >= 0 && sel < numEmails ) {
6378  const idDeclEmail *email = pda->GetEmailByIndex( sel );
6379  name = email->GetSubject();
6380  data = email->GetBody();
6381  }
6382  }
6383  objectiveSystem->SetStateString( "PDAEmailTitle", name );
6384  objectiveSystem->SetStateString( "PDAEmailText", data );
6385  }
6386  }
6387  if ( objectiveSystem->State().GetInt( "listPDA_sel_0", "-1" ) == -1 ) {
6388  objectiveSystem->SetStateInt( "listPDA_sel_0", 0 );
6389  }
6391 }
6392 
6393 /*
6394 ==============
6395 idPlayer::TogglePDA
6396 ==============
6397 */
6398 void idPlayer::TogglePDA( void ) {
6399  if ( objectiveSystem == NULL ) {
6400  return;
6401  }
6402 
6403  if ( inventory.pdas.Num() == 0 ) {
6404  ShowTip( spawnArgs.GetString( "text_infoTitle" ), spawnArgs.GetString( "text_noPDA" ), true );
6405  return;
6406  }
6407 
6408  assert( hud );
6409 
6410  if ( !objectiveSystemOpen ) {
6411  int j, c = inventory.items.Num();
6412  objectiveSystem->SetStateInt( "inv_count", c );
6413  for ( j = 0; j < MAX_INVENTORY_ITEMS; j++ ) {
6414  objectiveSystem->SetStateString( va( "inv_name_%i", j ), "" );
6415  objectiveSystem->SetStateString( va( "inv_icon_%i", j ), "" );
6416  objectiveSystem->SetStateString( va( "inv_text_%i", j ), "" );
6417  }
6418  for ( j = 0; j < c; j++ ) {
6419  idDict *item = inventory.items[j];
6420  if ( !item->GetBool( "inv_pda" ) ) {
6421  const char *iname = item->GetString( "inv_name" );
6422  const char *iicon = item->GetString( "inv_icon" );
6423  const char *itext = item->GetString( "inv_text" );
6424  objectiveSystem->SetStateString( va( "inv_name_%i", j ), iname );
6425  objectiveSystem->SetStateString( va( "inv_icon_%i", j ), iicon );
6426  objectiveSystem->SetStateString( va( "inv_text_%i", j ), itext );
6427  const idKeyValue *kv = item->MatchPrefix( "inv_id", NULL );
6428  if ( kv ) {
6429  objectiveSystem->SetStateString( va( "inv_id_%i", j ), kv->GetValue() );
6430  }
6431  }
6432  }
6433 
6434  for ( j = 0; j < MAX_WEAPONS; j++ ) {
6435  const char *weapnum = va( "def_weapon%d", j );
6436  const char *hudWeap = va( "weapon%d", j );
6437  int weapstate = 0;
6438  if ( inventory.weapons & ( 1 << j ) ) {
6439  const char *weap = spawnArgs.GetString( weapnum );
6440  if ( weap && *weap ) {
6441  weapstate++;
6442  }
6443  }
6444  objectiveSystem->SetStateInt( hudWeap, weapstate );
6445  }
6446 
6447  objectiveSystem->SetStateInt( "listPDA_sel_0", inventory.selPDA );
6448  objectiveSystem->SetStateInt( "listPDAVideo_sel_0", inventory.selVideo );
6449  objectiveSystem->SetStateInt( "listPDAAudio_sel_0", inventory.selAudio );
6450  objectiveSystem->SetStateInt( "listPDAEmail_sel_0", inventory.selEMail );
6451  UpdatePDAInfo( false );
6454  hud->HandleNamedEvent( "pdaPickupHide" );
6455  hud->HandleNamedEvent( "videoPickupHide" );
6456  } else {
6457  inventory.selPDA = objectiveSystem->State().GetInt( "listPDA_sel_0" );
6458  inventory.selVideo = objectiveSystem->State().GetInt( "listPDAVideo_sel_0" );
6459  inventory.selAudio = objectiveSystem->State().GetInt( "listPDAAudio_sel_0" );
6460  inventory.selEMail = objectiveSystem->State().GetInt( "listPDAEmail_sel_0" );
6462  }
6463  objectiveSystemOpen ^= 1;
6464 }
6465 
6466 /*
6467 ==============
6468 idPlayer::ToggleScoreboard
6469 ==============
6470 */
6471 void idPlayer::ToggleScoreboard( void ) {
6472  scoreBoardOpen ^= 1;
6473 }
6474 
6475 /*
6476 ==============
6477 idPlayer::Spectate
6478 ==============
6479 */
6480 void idPlayer::Spectate( bool spectate ) {
6481  idBitMsg msg;
6482  byte msgBuf[MAX_EVENT_PARAM_SIZE];
6483 
6484  // track invisible player bug
6485  // all hiding and showing should be performed through Spectate calls
6486  // except for the private camera view, which is used for teleports
6487  assert( ( teleportEntity.GetEntity() != NULL ) || ( IsHidden() == spectating ) );
6488 
6489  if ( spectating == spectate ) {
6490  return;
6491  }
6492 
6493  spectating = spectate;
6494 
6495  if ( gameLocal.isServer ) {
6496  msg.Init( msgBuf, sizeof( msgBuf ) );
6497  msg.WriteBits( spectating, 1 );
6498  ServerSendEvent( EVENT_SPECTATE, &msg, false, -1 );
6499  }
6500 
6501  if ( spectating ) {
6502  // join the spectators
6503  ClearPowerUps();
6504  spectator = this->entityNumber;
6505  Init();
6506  StopRagdoll();
6507  SetPhysics( &physicsObj );
6509  Hide();
6511  if ( hud ) {
6512  hud->HandleNamedEvent( "aim_clear" );
6513  MPAimFadeTime = 0;
6514  }
6515  } else {
6516  // put everything back together again
6517  currentWeapon = -1; // to make sure the def will be loaded if necessary
6518  Show();
6520  }
6521  SetClipModel();
6522 }
6523 
6524 /*
6525 ==============
6526 idPlayer::SetClipModel
6527 ==============
6528 */
6529 void idPlayer::SetClipModel( void ) {
6530  idBounds bounds;
6531 
6532  if ( spectating ) {
6533  bounds = idBounds( vec3_origin ).Expand( pm_spectatebbox.GetFloat() * 0.5f );
6534  } else {
6535  bounds[0].Set( -pm_bboxwidth.GetFloat() * 0.5f, -pm_bboxwidth.GetFloat() * 0.5f, 0 );
6536  bounds[1].Set( pm_bboxwidth.GetFloat() * 0.5f, pm_bboxwidth.GetFloat() * 0.5f, pm_normalheight.GetFloat() );
6537  }
6538  // the origin of the clip model needs to be set before calling SetClipModel
6539  // otherwise our physics object's current origin value gets reset to 0
6540  idClipModel *newClip;
6541  if ( pm_usecylinder.GetBool() ) {
6542  newClip = new idClipModel( idTraceModel( bounds, 8 ) );
6543  newClip->Translate( physicsObj.PlayerGetOrigin() );
6544  physicsObj.SetClipModel( newClip, 1.0f );
6545  } else {
6546  newClip = new idClipModel( idTraceModel( bounds ) );
6547  newClip->Translate( physicsObj.PlayerGetOrigin() );
6548  physicsObj.SetClipModel( newClip, 1.0f );
6549  }
6550 }
6551 
6552 /*
6553 ==============
6554 idPlayer::UseVehicle
6555 ==============
6556 */
6557 void idPlayer::UseVehicle( void ) {
6558  trace_t trace;
6559  idVec3 start, end;
6560  idEntity *ent;
6561 
6562  if ( GetBindMaster() && GetBindMaster()->IsType( idAFEntity_Vehicle::Type ) ) {
6563  Show();
6564  static_cast<idAFEntity_Vehicle*>(GetBindMaster())->Use( this );
6565  } else {
6566  start = GetEyePosition();
6567  end = start + viewAngles.ToForward() * 80.0f;
6568  gameLocal.clip.TracePoint( trace, start, end, MASK_SHOT_RENDERMODEL, this );
6569  if ( trace.fraction < 1.0f ) {
6570  ent = gameLocal.entities[ trace.c.entityNum ];
6571  if ( ent && ent->IsType( idAFEntity_Vehicle::Type ) ) {
6572  Hide();
6573  static_cast<idAFEntity_Vehicle*>(ent)->Use( this );
6574  }
6575  }
6576  }
6577 }
6578 
6579 /*
6580 ==============
6581 idPlayer::PerformImpulse
6582 ==============
6583 */
6584 void idPlayer::PerformImpulse( int impulse ) {
6585 
6586  if ( gameLocal.isClient ) {
6587  idBitMsg msg;
6588  byte msgBuf[MAX_EVENT_PARAM_SIZE];
6589 
6591  msg.Init( msgBuf, sizeof( msgBuf ) );
6592  msg.BeginWriting();
6593  msg.WriteBits( impulse, 6 );
6594  ClientSendEvent( EVENT_IMPULSE, &msg );
6595  }
6596 
6597  if ( impulse >= IMPULSE_0 && impulse <= IMPULSE_12 ) {
6598  SelectWeapon( impulse, false );
6599  return;
6600  }
6601 
6602  switch( impulse ) {
6603  case IMPULSE_13: {
6604  Reload();
6605  break;
6606  }
6607  case IMPULSE_14: {
6608  NextWeapon();
6609  break;
6610  }
6611  case IMPULSE_15: {
6612  PrevWeapon();
6613  break;
6614  }
6615  case IMPULSE_17: {
6618  }
6619  break;
6620  }
6621  case IMPULSE_18: {
6623  break;
6624  }
6625  case IMPULSE_19: {
6626  // when we're not in single player, IMPULSE_19 is used for showScores
6627  // otherwise it opens the pda
6628  if ( !gameLocal.isMultiplayer ) {
6629  if ( objectiveSystemOpen ) {
6630  TogglePDA();
6631  } else if ( weapon_pda >= 0 ) {
6632  SelectWeapon( weapon_pda, true );
6633  }
6634  }
6635  break;
6636  }
6637  case IMPULSE_20: {
6640  }
6641  break;
6642  }
6643  case IMPULSE_22: {
6646  }
6647  break;
6648  }
6649 
6650  case IMPULSE_25: {
6651  if ( gameLocal.isServer && gameLocal.mpGame.IsGametypeFlagBased() && (gameLocal.serverInfo.GetInt( "si_midnight" ) == 2) ) {
6652  if ( enviroSuitLight.IsValid() ) {
6653  enviroSuitLight.GetEntity()->PostEventMS( &EV_Remove, 0 );
6654  enviroSuitLight = NULL;
6655  } else {
6656  const idDict *lightDef = gameLocal.FindEntityDefDict( "envirosuit_light", false );
6657  if ( lightDef ) {
6658  idEntity *temp = static_cast<idEntity *>(enviroSuitLight.GetEntity());
6659  idAngles lightAng = firstPersonViewAxis.ToAngles();
6660  idVec3 lightOrg = firstPersonViewOrigin;
6661 
6662  idVec3 enviroOffset = lightDef->GetVector( "enviro_offset" );
6663  idVec3 enviroAngleOffset = lightDef->GetVector( "enviro_angle_offset" );
6664 
6665  gameLocal.SpawnEntityDef( *lightDef, &temp, false );
6666  enviroSuitLight = static_cast<idLight *>(temp);
6667 
6668  enviroSuitLight.GetEntity()->fl.networkSync = true;
6669 
6670  lightOrg += (enviroOffset.x * firstPersonViewAxis[0]);
6671  lightOrg += (enviroOffset.y * firstPersonViewAxis[1]);
6672  lightOrg += (enviroOffset.z * firstPersonViewAxis[2]);
6673  lightAng.pitch += enviroAngleOffset.x;
6674  lightAng.yaw += enviroAngleOffset.y;
6675  lightAng.roll += enviroAngleOffset.z;
6676 
6677  enviroSuitLight.GetEntity()->GetPhysics()->SetOrigin( lightOrg );
6678  enviroSuitLight.GetEntity()->GetPhysics()->SetAxis( lightAng.ToMat3() );
6679 
6680  enviroSuitLight.GetEntity()->UpdateVisuals();
6681  enviroSuitLight.GetEntity()->Present();
6682  }
6683  }
6684  }
6685  break;
6686  }
6687 
6688  case IMPULSE_28: {
6691  }
6692  break;
6693  }
6694  case IMPULSE_29: {
6697  }
6698  break;
6699  }
6700  case IMPULSE_40: {
6701  UseVehicle();
6702  break;
6703  }
6704 #ifdef _D3XP
6705  //Hack so the chainsaw will work in MP
6706  case IMPULSE_27: {
6707  SelectWeapon(18, false);
6708  break;
6709  }
6710 #endif
6711  }
6712 }
6713 
6714 bool idPlayer::HandleESC( void ) {
6715  if ( gameLocal.inCinematic ) {
6716  return SkipCinematic();
6717  }
6718 
6719  if ( objectiveSystemOpen ) {
6720  TogglePDA();
6721  return true;
6722  }
6723 
6724  return false;
6725 }
6726 
6727 bool idPlayer::SkipCinematic( void ) {
6728  StartSound( "snd_skipcinematic", SND_CHANNEL_ANY, 0, false, NULL );
6729  return gameLocal.SkipCinematic();
6730 }
6731 
6732 /*
6733 ==============
6734 idPlayer::EvaluateControls
6735 ==============
6736 */
6737 void idPlayer::EvaluateControls( void ) {
6738  // check for respawning
6739  if ( health <= 0 ) {
6740  if ( ( gameLocal.time > minRespawnTime ) && ( usercmd.buttons & BUTTON_ATTACK ) ) {
6741  forceRespawn = true;
6742  } else if ( gameLocal.time > maxRespawnTime ) {
6743  forceRespawn = true;
6744  }
6745  }
6746 
6747  // in MP, idMultiplayerGame decides spawns
6749  // in single player, we let the session handle restarting the level or loading a game
6750  gameLocal.sessionCommand = "died";
6751  }
6752 
6755  }
6756 
6758 
6760 
6761  AdjustSpeed();
6762 
6763  // update the viewangles
6764  UpdateViewAngles();
6765 }
6766 
6767 /*
6768 ==============
6769 idPlayer::AdjustSpeed
6770 ==============
6771 */
6772 void idPlayer::AdjustSpeed( void ) {
6773  float speed;
6774  float rate;
6775 
6776  if ( spectating ) {
6777  speed = pm_spectatespeed.GetFloat();
6778  bobFrac = 0.0f;
6779  } else if ( noclip ) {
6780  speed = pm_noclipspeed.GetFloat();
6781  bobFrac = 0.0f;
6782  } else if ( !physicsObj.OnLadder() && ( usercmd.buttons & BUTTON_RUN ) && ( usercmd.forwardmove || usercmd.rightmove ) && ( usercmd.upmove >= 0 ) ) {
6784  stamina -= MS2SEC( gameLocal.msec );
6785  }
6786  if ( stamina < 0 ) {
6787  stamina = 0;
6788  }
6789  if ( ( !pm_stamina.GetFloat() ) || ( stamina > pm_staminathreshold.GetFloat() ) ) {
6790  bobFrac = 1.0f;
6791  } else if ( pm_staminathreshold.GetFloat() <= 0.0001f ) {
6792  bobFrac = 0.0f;
6793  } else {
6795  }
6796  speed = pm_walkspeed.GetFloat() * ( 1.0f - bobFrac ) + pm_runspeed.GetFloat() * bobFrac;
6797  } else {
6798  rate = pm_staminarate.GetFloat();
6799 
6800  // increase 25% faster when not moving
6801  if ( ( usercmd.forwardmove == 0 ) && ( usercmd.rightmove == 0 ) && ( !physicsObj.OnLadder() || ( usercmd.upmove == 0 ) ) ) {
6802  rate *= 1.25f;
6803  }
6804 
6805  stamina += rate * MS2SEC( gameLocal.msec );
6806  if ( stamina > pm_stamina.GetFloat() ) {
6808  }
6809  speed = pm_walkspeed.GetFloat();
6810  bobFrac = 0.0f;
6811  }
6812 
6813  speed *= PowerUpModifier(SPEED);
6814 
6815  if ( influenceActive == INFLUENCE_LEVEL3 ) {
6816  speed *= 0.33f;
6817  }
6818 
6820 }
6821 
6822 /*
6823 ==============
6824 idPlayer::AdjustBodyAngles
6825 ==============
6826 */
6827 void idPlayer::AdjustBodyAngles( void ) {
6828  idMat3 lookAxis;
6829  idMat3 legsAxis;
6830  bool blend;
6831  float diff;
6832  float frac;
6833  float upBlend;
6834  float forwardBlend;
6835  float downBlend;
6836 
6837  if ( health < 0 ) {
6838  return;
6839  }
6840 
6841  blend = true;
6842 
6843  if ( !physicsObj.HasGroundContacts() ) {
6844  idealLegsYaw = 0.0f;
6845  legsForward = true;
6846  } else if ( usercmd.forwardmove < 0 ) {
6848  legsForward = false;
6849  } else if ( usercmd.forwardmove > 0 ) {
6851  legsForward = true;
6852  } else if ( ( usercmd.rightmove != 0 ) && physicsObj.IsCrouching() ) {
6853  if ( !legsForward ) {
6855  } else {
6857  }
6858  } else if ( usercmd.rightmove != 0 ) {
6859  idealLegsYaw = 0.0f;
6860  legsForward = true;
6861  } else {
6862  legsForward = true;
6863  diff = idMath::Fabs( idealLegsYaw - legsYaw );
6865  if ( diff < 0.1f ) {
6867  blend = false;
6868  }
6869  }
6870 
6871  if ( !physicsObj.IsCrouching() ) {
6872  legsForward = true;
6873  }
6874 
6876 
6877  AI_TURN_LEFT = false;
6878  AI_TURN_RIGHT = false;
6879  if ( idealLegsYaw < -45.0f ) {
6880  idealLegsYaw = 0;
6881  AI_TURN_RIGHT = true;
6882  blend = true;
6883  } else if ( idealLegsYaw > 45.0f ) {
6884  idealLegsYaw = 0;
6885  AI_TURN_LEFT = true;
6886  blend = true;
6887  }
6888 
6889  if ( blend ) {
6890  legsYaw = legsYaw * 0.9f + idealLegsYaw * 0.1f;
6891  }
6892  legsAxis = idAngles( 0.0f, legsYaw, 0.0f ).ToMat3();
6894 
6895  // calculate the blending between down, straight, and up
6896  frac = viewAngles.pitch / 90.0f;
6897  if ( frac > 0.0f ) {
6898  downBlend = frac;
6899  forwardBlend = 1.0f - frac;
6900  upBlend = 0.0f;
6901  } else {
6902  downBlend = 0.0f;
6903  forwardBlend = 1.0f + frac;
6904  upBlend = -frac;
6905  }
6906 
6910 
6914 }
6915 
6916 /*
6917 ==============
6918 idPlayer::InitAASLocation
6919 ==============
6920 */
6921 void idPlayer::InitAASLocation( void ) {
6922  int i;
6923  int num;
6924  idVec3 size;
6925  idBounds bounds;
6926  idAAS *aas;
6927  idVec3 origin;
6928 
6929  GetFloorPos( 64.0f, origin );
6930 
6931  num = gameLocal.NumAAS();
6933  aasLocation.SetNum( num );
6934  for( i = 0; i < aasLocation.Num(); i++ ) {
6935  aasLocation[ i ].areaNum = 0;
6936  aasLocation[ i ].pos = origin;
6937  aas = gameLocal.GetAAS( i );
6938  if ( aas && aas->GetSettings() ) {
6939  size = aas->GetSettings()->boundingBoxes[0][1];
6940  bounds[0] = -size;
6941  size.z = 32.0f;
6942  bounds[1] = size;
6943 
6944  aasLocation[ i ].areaNum = aas->PointReachableAreaNum( origin, bounds, AREA_REACHABLE_WALK );
6945  }
6946  }
6947 }
6948 
6949 /*
6950 ==============
6951 idPlayer::SetAASLocation
6952 ==============
6953 */
6954 void idPlayer::SetAASLocation( void ) {
6955  int i;
6956  int areaNum;
6957  idVec3 size;
6958  idBounds bounds;
6959  idAAS *aas;
6960  idVec3 origin;
6961 
6962  if ( !GetFloorPos( 64.0f, origin ) ) {
6963  return;
6964  }
6965 
6966  for( i = 0; i < aasLocation.Num(); i++ ) {
6967  aas = gameLocal.GetAAS( i );
6968  if ( !aas ) {
6969  continue;
6970  }
6971 
6972  size = aas->GetSettings()->boundingBoxes[0][1];
6973  bounds[0] = -size;
6974  size.z = 32.0f;
6975  bounds[1] = size;
6976 
6977  areaNum = aas->PointReachableAreaNum( origin, bounds, AREA_REACHABLE_WALK );
6978  if ( areaNum ) {
6979  aasLocation[ i ].pos = origin;
6980  aasLocation[ i ].areaNum = areaNum;
6981  }
6982  }
6983 }
6984 
6985 /*
6986 ==============
6987 idPlayer::GetAASLocation
6988 ==============
6989 */
6990 void idPlayer::GetAASLocation( idAAS *aas, idVec3 &pos, int &areaNum ) const {
6991  int i;
6992 
6993  if ( aas != NULL ) {
6994  for( i = 0; i < aasLocation.Num(); i++ ) {
6995  if ( aas == gameLocal.GetAAS( i ) ) {
6996  areaNum = aasLocation[ i ].areaNum;
6997  pos = aasLocation[ i ].pos;
6998  return;
6999  }
7000  }
7001  }
7002 
7003  areaNum = 0;
7004  pos = physicsObj.GetOrigin();
7005 }
7006 
7007 /*
7008 ==============
7009 idPlayer::Move
7010 ==============
7011 */
7012 void idPlayer::Move( void ) {
7013  float newEyeOffset;
7014  idVec3 oldOrigin;
7015  idVec3 oldVelocity;
7016  idVec3 pushVelocity;
7017 
7018  // save old origin and velocity for crashlanding
7019  oldOrigin = physicsObj.GetOrigin();
7020  oldVelocity = physicsObj.GetLinearVelocity();
7021  pushVelocity = physicsObj.GetPushedLinearVelocity();
7022 
7023  // set physics variables
7026 
7027  if ( noclip ) {
7028  physicsObj.SetContents( 0 );
7030  } else if ( spectating ) {
7031  physicsObj.SetContents( 0 );
7033  } else if ( health <= 0 ) {
7039 #ifdef _D3XP
7040  } else if ( mountedObject ) {
7041  physicsObj.SetContents( 0 );
7043 #endif
7044  } else {
7047  }
7048 
7049  if ( spectating ) {
7051  } else if ( health <= 0 ) {
7053  } else {
7055  }
7056 
7059 
7060  // FIXME: physics gets disabled somehow
7062  RunPhysics();
7063 
7064  // update our last valid AAS location for the AI
7065  SetAASLocation();
7066 
7067  if ( spectating ) {
7068  newEyeOffset = 0.0f;
7069  } else if ( health <= 0 ) {
7070  newEyeOffset = pm_deadviewheight.GetFloat();
7071  } else if ( physicsObj.IsCrouching() ) {
7072  newEyeOffset = pm_crouchviewheight.GetFloat();
7073  } else if ( GetBindMaster() && GetBindMaster()->IsType( idAFEntity_Vehicle::Type ) ) {
7074  newEyeOffset = 0.0f;
7075  } else {
7076  newEyeOffset = pm_normalviewheight.GetFloat();
7077  }
7078 
7079  if ( EyeHeight() != newEyeOffset ) {
7080  if ( spectating ) {
7081  SetEyeHeight( newEyeOffset );
7082  } else {
7083  // smooth out duck height changes
7084  SetEyeHeight( EyeHeight() * pm_crouchrate.GetFloat() + newEyeOffset * ( 1.0f - pm_crouchrate.GetFloat() ) );
7085  }
7086  }
7087 
7089  AI_CROUCH = false;
7091  AI_ONLADDER = false;
7092  AI_JUMP = false;
7093  } else {
7098 
7099  // check if we're standing on top of a monster and give a push if we are
7100  idEntity *groundEnt = physicsObj.GetGroundEntity();
7101  if ( groundEnt && groundEnt->IsType( idAI::Type ) ) {
7103  if ( vel.ToVec2().LengthSqr() < 0.1f ) {
7104  vel.ToVec2() = physicsObj.GetOrigin().ToVec2() - groundEnt->GetPhysics()->GetAbsBounds().GetCenter().ToVec2();
7105  vel.ToVec2().NormalizeFast();
7106  vel.ToVec2() *= pm_walkspeed.GetFloat();
7107  } else {
7108  // give em a push in the direction they're going
7109  vel *= 1.1f;
7110  }
7112  }
7113  }
7114 
7115  if ( AI_JUMP ) {
7116  // bounce the view weapon
7117  loggedAccel_t *acc = &loggedAccel[currentLoggedAccel&(NUM_LOGGED_ACCELS-1)];
7119  acc->time = gameLocal.time;
7120  acc->dir[2] = 200;
7121  acc->dir[0] = acc->dir[1] = 0;
7122  }
7123 
7124  if ( AI_ONLADDER ) {
7125  int old_rung = oldOrigin.z / LADDER_RUNG_DISTANCE;
7126  int new_rung = physicsObj.GetOrigin().z / LADDER_RUNG_DISTANCE;
7127 
7128  if ( old_rung != new_rung ) {
7129  StartSound( "snd_stepladder", SND_CHANNEL_ANY, 0, false, NULL );
7130  }
7131  }
7132 
7133  BobCycle( pushVelocity );
7134  CrashLand( oldOrigin, oldVelocity );
7135 }
7136 
7137 /*
7138 ==============
7139 idPlayer::UpdateHud
7140 ==============
7141 */
7142 void idPlayer::UpdateHud( void ) {
7143  idPlayer *aimed;
7144 
7145  if ( !hud ) {
7146  return;
7147  }
7148 
7150  return;
7151  }
7152 
7153  int c = inventory.pickupItemNames.Num();
7154  if ( c > 0 ) {
7157  inventory.nextItemNum = 1;
7158  }
7159  int i;
7160 
7161 #ifdef _D3XP
7162  int count = 5;
7163  if(gameLocal.isMultiplayer) {
7164  count = 3;
7165  }
7166 #endif
7167  for ( i = 0; i < count, i < c; i++ ) { //_D3XP
7168  hud->SetStateString( va( "itemtext%i", inventory.nextItemNum ), inventory.pickupItemNames[0].name );
7169  hud->SetStateString( va( "itemicon%i", inventory.nextItemNum ), inventory.pickupItemNames[0].icon );
7170  hud->HandleNamedEvent( va( "itemPickup%i", inventory.nextItemNum++ ) );
7172  if (inventory.nextItemNum == 1 ) {
7174  } else if ( inventory.nextItemNum > count ) { //_D3XP
7175  inventory.nextItemNum = 1;
7177  } else {
7179  }
7180  }
7181  }
7182  }
7183 
7185  if ( MPAim != -1 && gameLocal.mpGame.IsGametypeTeamBased() /* CTF */
7186  && gameLocal.entities[ MPAim ] && gameLocal.entities[ MPAim ]->IsType( idPlayer::Type )
7187  && static_cast< idPlayer * >( gameLocal.entities[ MPAim ] )->team == team ) {
7188  aimed = static_cast< idPlayer * >( gameLocal.entities[ MPAim ] );
7189  hud->SetStateString( "aim_text", gameLocal.userInfo[ MPAim ].GetString( "ui_name" ) );
7190  hud->SetStateFloat( "aim_color", aimed->colorBarIndex );
7191  hud->HandleNamedEvent( "aim_flash" );
7192  MPAimHighlight = true;
7193  MPAimFadeTime = 0; // no fade till loosing focus
7194  } else if ( MPAimHighlight ) {
7195  hud->HandleNamedEvent( "aim_fade" );
7197  MPAimHighlight = false;
7198  }
7199  }
7200  if ( MPAimFadeTime ) {
7201  assert( !MPAimHighlight );
7202  if ( gameLocal.realClientTime - MPAimFadeTime > 2000 ) {
7203  MPAimFadeTime = 0;
7204  }
7205  }
7206 
7207  hud->SetStateInt( "g_showProjectilePct", g_showProjectilePct.GetInteger() );
7208  if ( numProjectilesFired ) {
7209  hud->SetStateString( "projectilepct", va( "Hit %% %.1f", ( (float) numProjectileHits / numProjectilesFired ) * 100 ) );
7210  } else {
7211  hud->SetStateString( "projectilepct", "Hit % 0.0" );
7212  }
7213 
7215  hud->SetStateString( "hudLag", "1" );
7216  } else {
7217  hud->SetStateString( "hudLag", "0" );
7218  }
7219 }
7220 
7221 /*
7222 ==============
7223 idPlayer::UpdateDeathSkin
7224 ==============
7225 */
7226 void idPlayer::UpdateDeathSkin( bool state_hitch ) {
7227  if ( !( gameLocal.isMultiplayer || g_testDeath.GetBool() ) ) {
7228  return;
7229  }
7230  if ( health <= 0 ) {
7231  if ( !doingDeathSkin ) {
7232  deathClearContentsTime = spawnArgs.GetInt( "deathSkinTime" );
7233  doingDeathSkin = true;
7234  renderEntity.noShadow = true;
7235  if ( state_hitch ) {
7237  } else {
7239  }
7240  UpdateVisuals();
7241  }
7242 
7243  // wait a bit before switching off the content
7245  SetCombatContents( false );
7247  }
7248  } else {
7249  renderEntity.noShadow = false;
7251  UpdateVisuals();
7252  doingDeathSkin = false;
7253  }
7254 }
7255 
7256 /*
7257 ==============
7258 idPlayer::StartFxOnBone
7259 ==============
7260 */
7261 void idPlayer::StartFxOnBone( const char *fx, const char *bone ) {
7262  idVec3 offset;
7263  idMat3 axis;
7264  jointHandle_t jointHandle = GetAnimator()->GetJointHandle( bone );
7265 
7266  if ( jointHandle == INVALID_JOINT ) {
7267  gameLocal.Printf( "Cannot find bone %s\n", bone );
7268  return;
7269  }
7270 
7271  if ( GetAnimator()->GetJointTransform( jointHandle, gameLocal.time, offset, axis ) ) {
7272  offset = GetPhysics()->GetOrigin() + offset * GetPhysics()->GetAxis();
7273  axis = axis * GetPhysics()->GetAxis();
7274  }
7275 
7276  idEntityFx::StartFx( fx, &offset, &axis, this, true );
7277 }
7278 
7279 /*
7280 ==============
7281 idPlayer::Think
7282 
7283 Called every tic for each player
7284 ==============
7285 */
7286 void idPlayer::Think( void ) {
7287  renderEntity_t *headRenderEnt;
7288 
7290 
7291  // latch button actions
7293 
7294  // grab out usercmd
7295  usercmd_t oldCmd = usercmd;
7299 
7301  return;
7302  }
7303 
7304  // clear the ik before we do anything else so the skeleton doesn't get updated twice
7306 
7307  // if this is the very first frame of the map, set the delta view angles
7308  // based on the usercmd angles
7309  if ( !spawnAnglesSet && ( gameLocal.GameState() != GAMESTATE_STARTUP ) ) {
7310  spawnAnglesSet = true;
7313  }
7314 
7315 #ifdef _D3XP
7316  if ( mountedObject ) {
7317  usercmd.forwardmove = 0;
7318  usercmd.rightmove = 0;
7319  usercmd.upmove = 0;
7320  }
7321 #endif
7322 
7324  if ( objectiveSystemOpen && AI_PAIN ) {
7325  TogglePDA();
7326  }
7327  usercmd.forwardmove = 0;
7328  usercmd.rightmove = 0;
7329  usercmd.upmove = 0;
7330  }
7331 
7332  // log movement changes for weapon bobbing effects
7333  if ( usercmd.forwardmove != oldCmd.forwardmove ) {
7334  loggedAccel_t *acc = &loggedAccel[currentLoggedAccel&(NUM_LOGGED_ACCELS-1)];
7336  acc->time = gameLocal.time;
7337  acc->dir[0] = usercmd.forwardmove - oldCmd.forwardmove;
7338  acc->dir[1] = acc->dir[2] = 0;
7339  }
7340 
7341  if ( usercmd.rightmove != oldCmd.rightmove ) {
7342  loggedAccel_t *acc = &loggedAccel[currentLoggedAccel&(NUM_LOGGED_ACCELS-1)];
7344  acc->time = gameLocal.time;
7345  acc->dir[1] = usercmd.rightmove - oldCmd.rightmove;
7346  acc->dir[0] = acc->dir[2] = 0;
7347  }
7348 
7349  // freelook centering
7350  if ( ( usercmd.buttons ^ oldCmd.buttons ) & BUTTON_MLOOK ) {
7352  }
7353 
7354  // zooming
7355  if ( ( usercmd.buttons ^ oldCmd.buttons ) & BUTTON_ZOOM ) {
7356  if ( ( usercmd.buttons & BUTTON_ZOOM ) && weapon.GetEntity() ) {
7357  zoomFov.Init( gameLocal.time, 200.0f, CalcFov( false ), weapon.GetEntity()->GetZoomFov() );
7358  } else {
7360  }
7361  }
7362 
7363  // if we have an active gui, we will unrotate the view angles as
7364  // we turn the mouse movements into gui events
7365  idUserInterface *gui = ActiveGui();
7366  if ( gui && gui != focusUI ) {
7367  RouteGuiMouse( gui );
7368  }
7369 
7370  // set the push velocity on the weapon before running the physics
7371  if ( weapon.GetEntity() ) {
7373  }
7374 
7375  EvaluateControls();
7376 
7377  if ( !af.IsActive() ) {
7378  AdjustBodyAngles();
7380  }
7381 
7382  Move();
7383 
7384  if ( !g_stopTime.GetBool() ) {
7385 
7386  if ( !noclip && !spectating && ( health > 0 ) && !IsHidden() ) {
7387  TouchTriggers();
7388  }
7389 
7390  // not done on clients for various reasons. don't do it on server and save the sound channel for other things
7391  if ( !gameLocal.isMultiplayer ) {
7393 #ifdef _D3XP
7394  float scale = new_g_damageScale;
7395 #else
7396  float scale = g_damageScale.GetFloat();
7397 #endif
7398  if ( g_useDynamicProtection.GetBool() && scale < 1.0f && gameLocal.time - lastDmgTime > 500 ) {
7399  if ( scale < 1.0f ) {
7400  scale += 0.05f;
7401  }
7402  if ( scale > 1.0f ) {
7403  scale = 1.0f;
7404  }
7405 #ifdef _D3XP
7406  new_g_damageScale = scale;
7407 #else
7408  g_damageScale.SetFloat( scale );
7409 #endif
7410  }
7411  }
7412 
7413  // update GUIs, Items, and character interactions
7414  UpdateFocus();
7415 
7416  UpdateLocation();
7417 
7418  // update player script
7419  UpdateScript();
7420 
7421  // service animations
7422  if ( !spectating && !af.IsActive() && !gameLocal.inCinematic ) {
7423  UpdateConditions();
7424  UpdateAnimState();
7425  CheckBlink();
7426  }
7427 
7428  // clear out our pain flag so we can tell if we recieve any damage between now and the next time we think
7429  AI_PAIN = false;
7430  }
7431 
7432  // calculate the exact bobbed view position, which is used to
7433  // position the view weapon, among other things
7435 
7436  // this may use firstPersonView, or a thirdPeroson / camera view
7438 
7440 
7441  if ( spectating ) {
7442  UpdateSpectating();
7443  } else if ( health > 0 ) {
7444  UpdateWeapon();
7445  }
7446 
7447  UpdateAir();
7448 
7449 #ifdef _D3XP
7450  UpdatePowerupHud();
7451 #endif
7452 
7453  UpdateHud();
7454 
7455  UpdatePowerUps();
7456 
7457  UpdateDeathSkin( false );
7458 
7459  if ( gameLocal.isMultiplayer ) {
7460  DrawPlayerIcons();
7461 
7462 #ifdef _D3XP
7463  if ( enviroSuitLight.IsValid() ) {
7464  idAngles lightAng = firstPersonViewAxis.ToAngles();
7465  idVec3 lightOrg = firstPersonViewOrigin;
7466  const idDict *lightDef = gameLocal.FindEntityDefDict( "envirosuit_light", false );
7467 
7468  idVec3 enviroOffset = lightDef->GetVector( "enviro_offset" );
7469  idVec3 enviroAngleOffset = lightDef->GetVector( "enviro_angle_offset" );
7470 
7471  lightOrg += (enviroOffset.x * firstPersonViewAxis[0]);
7472  lightOrg += (enviroOffset.y * firstPersonViewAxis[1]);
7473  lightOrg += (enviroOffset.z * firstPersonViewAxis[2]);
7474  lightAng.pitch += enviroAngleOffset.x;
7475  lightAng.yaw += enviroAngleOffset.y;
7476  lightAng.roll += enviroAngleOffset.z;
7477 
7478  enviroSuitLight.GetEntity()->GetPhysics()->SetOrigin( lightOrg );
7479  enviroSuitLight.GetEntity()->GetPhysics()->SetAxis( lightAng.ToMat3() );
7480  enviroSuitLight.GetEntity()->UpdateVisuals();
7481  enviroSuitLight.GetEntity()->Present();
7482  }
7483 #endif
7484  }
7485 
7486  if ( head.GetEntity() ) {
7487  headRenderEnt = head.GetEntity()->GetRenderEntity();
7488  } else {
7489  headRenderEnt = NULL;
7490  }
7491 
7492  if ( headRenderEnt ) {
7493  if ( influenceSkin ) {
7494  headRenderEnt->customSkin = influenceSkin;
7495  } else {
7496  headRenderEnt->customSkin = NULL;
7497  }
7498  }
7499 
7502  if ( headRenderEnt ) {
7503  headRenderEnt->suppressShadowInViewID = 0;
7504  }
7505  } else {
7507  if ( headRenderEnt ) {
7508  headRenderEnt->suppressShadowInViewID = entityNumber+1;
7509  }
7510  }
7511  // never cast shadows from our first-person muzzle flashes
7512  renderEntity.suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + entityNumber;
7513  if ( headRenderEnt ) {
7514  headRenderEnt->suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + entityNumber;
7515  }
7516 
7517  if ( !g_stopTime.GetBool() ) {
7518  UpdateAnimation();
7519 
7520  Present();
7521 
7523 
7524  LinkCombat();
7525 
7527  }
7528 
7529  if ( !( thinkFlags & TH_THINK ) ) {
7530  gameLocal.Printf( "player %d not thinking?\n", entityNumber );
7531  }
7532 
7533  if ( g_showEnemies.GetBool() ) {
7534  idActor *ent;
7535  int num = 0;
7536  for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
7537  gameLocal.Printf( "enemy (%d)'%s'\n", ent->entityNumber, ent->name.c_str() );
7539  num++;
7540  }
7541  gameLocal.Printf( "%d: enemies\n", num );
7542  }
7543 
7544 #ifdef _D3XP
7545  inventory.RechargeAmmo(this);
7546 
7547  if(healthRecharge) {
7548  int elapsed = gameLocal.time - lastHealthRechargeTime;
7549  if(elapsed >= rechargeSpeed) {
7550  int intervals = (gameLocal.time - lastHealthRechargeTime)/rechargeSpeed;
7551  Give("health", va("%d", intervals));
7552  lastHealthRechargeTime += intervals*rechargeSpeed;
7553  }
7554  }
7555 
7556  // determine if portal sky is in pvs
7557  gameLocal.portalSkyActive = gameLocal.pvs.CheckAreasForPortalSky( gameLocal.GetPlayerPVS(), GetPhysics()->GetOrigin() );
7558 #endif
7559 }
7560 
7561 #ifdef _D3XP
7562 /*
7563 =================
7564 idPlayer::StartHealthRecharge
7565 =================
7566 */
7567 void idPlayer::StartHealthRecharge(int speed) {
7568  lastHealthRechargeTime = gameLocal.time;
7569  healthRecharge = true;
7570  rechargeSpeed = speed;
7571 }
7572 
7573 /*
7574 =================
7575 idPlayer::StopHealthRecharge
7576 =================
7577 */
7578 void idPlayer::StopHealthRecharge() {
7579  healthRecharge = false;
7580 }
7581 
7582 /*
7583 =================
7584 idPlayer::GetCurrentWeapon
7585 =================
7586 */
7587 idStr idPlayer::GetCurrentWeapon() {
7588  const char *weapon;
7589 
7590  if ( currentWeapon >= 0 ) {
7591  weapon = spawnArgs.GetString( va( "def_weapon%d", currentWeapon ) );
7592  return weapon;
7593  } else {
7594  return "";
7595  }
7596 }
7597 
7598 /*
7599 =================
7600 idPlayer::CanGive
7601 =================
7602 */
7603 bool idPlayer::CanGive( const char *statname, const char *value ) {
7604  if ( AI_DEAD ) {
7605  return false;
7606  }
7607 
7608  if ( !idStr::Icmp( statname, "health" ) ) {
7609  if ( health >= inventory.maxHealth ) {
7610  return false;
7611  }
7612  return true;
7613  } else if ( !idStr::Icmp( statname, "stamina" ) ) {
7614  if ( stamina >= 100 ) {
7615  return false;
7616  }
7617  return true;
7618 
7619  } else if ( !idStr::Icmp( statname, "heartRate" ) ) {
7620  return true;
7621 
7622  } else if ( !idStr::Icmp( statname, "air" ) ) {
7623  if ( airTics >= pm_airTics.GetInteger() ) {
7624  return false;
7625  }
7626  return true;
7627  } else {
7628  return inventory.CanGive( this, spawnArgs, statname, value, &idealWeapon );
7629  }
7630 
7631  return false;
7632 }
7633 
7634 /*
7635 =================
7636 idPlayer::StopHelltime
7637 
7638 provides a quick non-ramping way of stopping helltime
7639 =================
7640 */
7641 void idPlayer::StopHelltime( bool quick ) {
7642  if ( !PowerUpActive( HELLTIME ) ) {
7643  return;
7644  }
7645 
7646  // take away the powerups
7647  if ( PowerUpActive( INVULNERABILITY ) ) {
7648  ClearPowerup( INVULNERABILITY );
7649  }
7650 
7651  if ( PowerUpActive( BERSERK ) ) {
7652  ClearPowerup( BERSERK );
7653  }
7654 
7655  if ( PowerUpActive( HELLTIME ) ) {
7656  ClearPowerup( HELLTIME );
7657  }
7658 
7659  // stop the looping sound
7660  StopSound( SND_CHANNEL_DEMONIC, false );
7661 
7662  // reset the game vars
7663  if ( quick ) {
7664  gameLocal.QuickSlowmoReset();
7665  }
7666 }
7667 
7668 /*
7669 =================
7670 idPlayer::Event_ToggleBloom
7671 =================
7672 */
7673 void idPlayer::Event_ToggleBloom( int on ) {
7674  if ( on ) {
7675  bloomEnabled = true;
7676  }
7677  else {
7678  bloomEnabled = false;
7679  }
7680 }
7681 
7682 /*
7683 =================
7684 idPlayer::Event_SetBloomParms
7685 =================
7686 */
7687 void idPlayer::Event_SetBloomParms( float speed, float intensity ) {
7688  bloomSpeed = speed;
7689  bloomIntensity = intensity;
7690 }
7691 
7692 /*
7693 =================
7694 idPlayer::PlayHelltimeStopSound
7695 =================
7696 */
7697 void idPlayer::PlayHelltimeStopSound() {
7698  const char* sound;
7699 
7700  if ( spawnArgs.GetString( "snd_helltime_stop", "", &sound ) ) {
7702  }
7703 }
7704 #endif
7705 
7706 /*
7707 =================
7708 idPlayer::RouteGuiMouse
7709 =================
7710 */
7712  sysEvent_t ev;
7713  const char *command;
7714 
7715  if ( usercmd.mx != oldMouseX || usercmd.my != oldMouseY ) {
7717  command = gui->HandleEvent( &ev, gameLocal.time );
7718  oldMouseX = usercmd.mx;
7719  oldMouseY = usercmd.my;
7720  }
7721 }
7722 
7723 /*
7724 ==================
7725 idPlayer::LookAtKiller
7726 ==================
7727 */
7728 void idPlayer::LookAtKiller( idEntity *inflictor, idEntity *attacker ) {
7729  idVec3 dir;
7730 
7731  if ( attacker && attacker != this ) {
7732  dir = attacker->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
7733  } else if ( inflictor && inflictor != this ) {
7734  dir = inflictor->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
7735  } else {
7736  dir = viewAxis[ 0 ];
7737  }
7738 
7739  idAngles ang( 0, dir.ToYaw(), 0 );
7740  SetViewAngles( ang );
7741 }
7742 
7743 /*
7744 ==============
7745 idPlayer::Kill
7746 ==============
7747 */
7748 void idPlayer::Kill( bool delayRespawn, bool nodamage ) {
7749  if ( spectating ) {
7750  SpectateFreeFly( false );
7751  } else if ( health > 0 ) {
7752  godmode = false;
7753  if ( nodamage ) {
7754  ServerSpectate( true );
7755  forceRespawn = true;
7756  } else {
7757  Damage( this, this, vec3_origin, "damage_suicide", 1.0f, INVALID_JOINT );
7758  if ( delayRespawn ) {
7759  forceRespawn = false;
7760  int delay = spawnArgs.GetFloat( "respawn_delay" );
7761  minRespawnTime = gameLocal.time + SEC2MS( delay );
7763  }
7764  }
7765  }
7766 }
7767 
7768 /*
7769 ==================
7770 idPlayer::Killed
7771 ==================
7772 */
7773 void idPlayer::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
7774  float delay;
7775 
7777 
7778  // stop taking knockback once dead
7779  fl.noknockback = true;
7780  if ( health < -999 ) {
7781  health = -999;
7782  }
7783 
7784  if ( AI_DEAD ) {
7785  AI_PAIN = true;
7786  return;
7787  }
7788 
7789  heartInfo.Init( 0, 0, 0, BASE_HEARTRATE );
7790  AdjustHeartRate( DEAD_HEARTRATE, 10.0f, 0.0f, true );
7791 
7792  if ( !g_testDeath.GetBool() ) {
7793  playerView.Fade( colorBlack, 12000 );
7794  }
7795 
7796  AI_DEAD = true;
7797  SetAnimState( ANIMCHANNEL_LEGS, "Legs_Death", 4 );
7798  SetAnimState( ANIMCHANNEL_TORSO, "Torso_Death", 4 );
7799  SetWaitState( "" );
7800 
7802 
7803  if ( StartRagdoll() ) {
7804  pm_modelView.SetInteger( 0 );
7807  } else {
7808  // don't allow respawn until the death anim is done
7809  // g_forcerespawn may force spawning at some later time
7810  delay = spawnArgs.GetFloat( "respawn_delay" );
7811  minRespawnTime = gameLocal.time + SEC2MS( delay );
7813  }
7814 
7816  StartSound( "snd_death", SND_CHANNEL_VOICE, 0, false, NULL );
7817  StopSound( SND_CHANNEL_BODY2, false );
7818 
7819  fl.takedamage = true; // can still be gibbed
7820 
7821  // get rid of weapon
7822  weapon.GetEntity()->OwnerDied();
7823 
7824  // drop the weapon as an item
7825  DropWeapon( true );
7826 
7827 #ifdef CTF
7828  // drop the flag if player was carrying it
7830  carryingFlag )
7831  {
7832  DropFlag();
7833  }
7834 #endif
7835 
7836  if ( !g_testDeath.GetBool() ) {
7837  LookAtKiller( inflictor, attacker );
7838  }
7839 
7841  idPlayer *killer = NULL;
7842  // no gibbing in MP. Event_Gib will early out in MP
7843  if ( attacker->IsType( idPlayer::Type ) ) {
7844  killer = static_cast<idPlayer*>(attacker);
7845  if ( health < -20 || killer->PowerUpActive( BERSERK ) ) {
7846  gibDeath = true;
7847  gibsDir = dir;
7848  gibsLaunched = false;
7849  }
7850  }
7851  gameLocal.mpGame.PlayerDeath( this, killer, isTelefragged );
7852  } else {
7854  }
7855 
7856  ClearPowerUps();
7857 
7858  UpdateVisuals();
7859 
7860  isChatting = false;
7861 }
7862 
7863 /*
7864 =====================
7865 idPlayer::GetAIAimTargets
7866 
7867 Returns positions for the AI to aim at.
7868 =====================
7869 */
7870 void idPlayer::GetAIAimTargets( const idVec3 &lastSightPos, idVec3 &headPos, idVec3 &chestPos ) {
7871  idVec3 offset;
7872  idMat3 axis;
7873  idVec3 origin;
7874 
7875  origin = lastSightPos - physicsObj.GetOrigin();
7876 
7877  GetJointWorldTransform( chestJoint, gameLocal.time, offset, axis );
7878  headPos = offset + origin;
7879 
7880  GetJointWorldTransform( headJoint, gameLocal.time, offset, axis );
7881  chestPos = offset + origin;
7882 }
7883 
7884 /*
7885 ================
7886 idPlayer::DamageFeedback
7887 
7888 callback function for when another entity received damage from this entity. damage can be adjusted and returned to the caller.
7889 ================
7890 */
7891 void idPlayer::DamageFeedback( idEntity *victim, idEntity *inflictor, int &damage ) {
7893  damage *= PowerUpModifier( BERSERK );
7894  if ( damage && ( victim != this ) && ( victim->IsType( idActor::Type ) || victim->IsType( idDamagable::Type ) ) ) {
7895 
7896  idPlayer *victimPlayer = NULL;
7897 
7898  /* No damage feedback sound for hitting friendlies in CTF */
7899  if ( victim->IsType( idPlayer::Type ) ) {
7900  victimPlayer = static_cast<idPlayer*>(victim);
7901  }
7902 
7903  if ( gameLocal.mpGame.IsGametypeFlagBased() && victimPlayer && this->team == victimPlayer->team ) {
7904  /* Do nothing ... */
7905  }
7906  else {
7908  }
7909  }
7910 }
7911 
7912 /*
7913 =================
7914 idPlayer::CalcDamagePoints
7915 
7916 Calculates how many health and armor points will be inflicted, but
7917 doesn't actually do anything with them. This is used to tell when an attack
7918 would have killed the player, possibly allowing a "saving throw"
7919 =================
7920 */
7921 void idPlayer::CalcDamagePoints( idEntity *inflictor, idEntity *attacker, const idDict *damageDef,
7922  const float damageScale, const int location, int *health, int *armor ) {
7923  int damage;
7924  int armorSave;
7925 
7926  damageDef->GetInt( "damage", "20", damage );
7927  damage = GetDamageForLocation( damage, location );
7928 
7929  idPlayer *player = attacker->IsType( idPlayer::Type ) ? static_cast<idPlayer*>(attacker) : NULL;
7930  if ( !gameLocal.isMultiplayer ) {
7931  if ( inflictor != gameLocal.world ) {
7932  switch ( g_skill.GetInteger() ) {
7933  case 0:
7934  damage *= 0.80f;
7935  if ( damage < 1 ) {
7936  damage = 1;
7937  }
7938  break;
7939  case 2:
7940  damage *= 1.70f;
7941  break;
7942  case 3:
7943  damage *= 3.5f;
7944  break;
7945  default:
7946  break;
7947  }
7948  }
7949  }
7950 
7951  damage *= damageScale;
7952 
7953  // always give half damage if hurting self
7954  if ( attacker == this ) {
7955  if ( gameLocal.isMultiplayer ) {
7956  // only do this in mp so single player plasma and rocket splash is very dangerous in close quarters
7957  damage *= damageDef->GetFloat( "selfDamageScale", "0.5" );
7958  } else {
7959  damage *= damageDef->GetFloat( "selfDamageScale", "1" );
7960  }
7961  }
7962 
7963  // check for completely getting out of the damage
7964  if ( !damageDef->GetBool( "noGod" ) ) {
7965  // check for godmode
7966  if ( godmode ) {
7967  damage = 0;
7968  }
7969 #ifdef _D3XP
7970  //Invulnerability is just like god mode
7971  if( PowerUpActive( INVULNERABILITY ) ) {
7972  damage = 0;
7973  }
7974 #endif
7975  }
7976 
7977  // inform the attacker that they hit someone
7978  attacker->DamageFeedback( this, inflictor, damage );
7979 
7980  // save some from armor
7981  if ( !damageDef->GetBool( "noArmor" ) ) {
7982  float armor_protection;
7983 
7985 
7986  armorSave = ceil( damage * armor_protection );
7987  if ( armorSave >= inventory.armor ) {
7988  armorSave = inventory.armor;
7989  }
7990 
7991  if ( !damage ) {
7992  armorSave = 0;
7993  } else if ( armorSave >= damage ) {
7994  armorSave = damage - 1;
7995  damage = 1;
7996  } else {
7997  damage -= armorSave;
7998  }
7999  } else {
8000  armorSave = 0;
8001  }
8002 
8003  // check for team damage
8004  if ( gameLocal.mpGame.IsGametypeTeamBased() /* CTF */
8005  && !gameLocal.serverInfo.GetBool( "si_teamDamage" )
8006  && !damageDef->GetBool( "noTeam" )
8007  && player
8008  && player != this // you get self damage no matter what
8009  && player->team == team ) {
8010  damage = 0;
8011  }
8012 
8013  *health = damage;
8014  *armor = armorSave;
8015 }
8016 
8017 /*
8018 ============
8019 Damage
8020 
8021 this entity that is being damaged
8022 inflictor entity that is causing the damage
8023 attacker entity that caused the inflictor to damage targ
8024  example: this=monster, inflictor=rocket, attacker=player
8025 
8026 dir direction of the attack for knockback in global space
8027 
8028 damageDef an idDict with all the options for damage effects
8029 
8030 inflictor, attacker, dir, and point can be NULL for environmental effects
8031 ============
8032 */
8033 void idPlayer::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
8034  const char *damageDefName, const float damageScale, const int location ) {
8035  idVec3 kick;
8036  int damage;
8037  int armorSave;
8038  int knockback;
8039  idVec3 damage_from;
8040  idVec3 localDamageVector;
8041  float attackerPushScale;
8042 #ifdef _D3XP
8043  SetTimeState ts( timeGroup );
8044 #endif
8045 
8046  // damage is only processed on server
8047  if ( gameLocal.isClient ) {
8048  return;
8049  }
8050 
8051  if ( !fl.takedamage || noclip || spectating || gameLocal.inCinematic ) {
8052  return;
8053  }
8054 
8055  if ( !inflictor ) {
8056  inflictor = gameLocal.world;
8057  }
8058  if ( !attacker ) {
8059  attacker = gameLocal.world;
8060  }
8061 
8062  if ( attacker->IsType( idAI::Type ) ) {
8063 #ifndef _D3XP
8064  if ( PowerUpActive( BERSERK ) ) {
8065  return;
8066  }
8067 #endif
8068  // don't take damage from monsters during influences
8069  if ( influenceActive != 0 ) {
8070  return;
8071  }
8072  }
8073 
8074  const idDeclEntityDef *damageDef = gameLocal.FindEntityDef( damageDefName, false );
8075  if ( !damageDef ) {
8076  gameLocal.Warning( "Unknown damageDef '%s'", damageDefName );
8077  return;
8078  }
8079 
8080  if ( damageDef->dict.GetBool( "ignore_player" ) ) {
8081  return;
8082  }
8083 
8084  CalcDamagePoints( inflictor, attacker, &damageDef->dict, damageScale, location, &damage, &armorSave );
8085 
8086  // determine knockback
8087  damageDef->dict.GetInt( "knockback", "20", knockback );
8088 
8089 /*#ifdef _D3XP
8090  idPlayer *player = attacker->IsType( idPlayer::Type ) ? static_cast<idPlayer*>(attacker) : NULL;
8091 
8092  if ( gameLocal.mpGame.IsGametypeTeamBased()
8093  && !gameLocal.serverInfo.GetBool( "si_teamDamage" )
8094  && !damageDef->dict.GetBool( "noTeam" )
8095  && player
8096  && player != this // you get self damage no matter what
8097  && player->team == team ) {
8098  knockback = 0;
8099  }
8100 #endif*/
8101 
8102  if ( knockback != 0 && !fl.noknockback ) {
8103  if ( attacker == this ) {
8104  damageDef->dict.GetFloat( "attackerPushScale", "0", attackerPushScale );
8105  } else {
8106  attackerPushScale = 1.0f;
8107  }
8108 
8109  kick = dir;
8110  kick.Normalize();
8111  kick *= g_knockback.GetFloat() * knockback * attackerPushScale / 200.0f;
8113 
8114  // set the timer so that the player can't cancel out the movement immediately
8115  physicsObj.SetKnockBack( idMath::ClampInt( 50, 200, knockback * 2 ) );
8116  }
8117 
8118 
8119  // give feedback on the player view and audibly when armor is helping
8120  if ( armorSave ) {
8121  inventory.armor -= armorSave;
8122 
8123  if ( gameLocal.time > lastArmorPulse + 200 ) {
8124  StartSound( "snd_hitArmor", SND_CHANNEL_ITEM, 0, false, NULL );
8125  }
8127  }
8128 
8129  if ( damageDef->dict.GetBool( "burn" ) ) {
8130  StartSound( "snd_burn", SND_CHANNEL_BODY3, 0, false, NULL );
8131  } else if ( damageDef->dict.GetBool( "no_air" ) ) {
8132  if ( !armorSave && health > 0 ) {
8133  StartSound( "snd_airGasp", SND_CHANNEL_ITEM, 0, false, NULL );
8134  }
8135  }
8136 
8137  if ( g_debugDamage.GetInteger() ) {
8138  gameLocal.Printf( "client:%i health:%i damage:%i armor:%i\n",
8139  entityNumber, health, damage, armorSave );
8140  }
8141 
8142  // move the world direction vector to local coordinates
8143  damage_from = dir;
8144  damage_from.Normalize();
8145 
8146  viewAxis.ProjectVector( damage_from, localDamageVector );
8147 
8148  // add to the damage inflicted on a player this frame
8149  // the total will be turned into screen blends and view angle kicks
8150  // at the end of the frame
8151  if ( health > 0 ) {
8152  playerView.DamageImpulse( localDamageVector, &damageDef->dict );
8153  }
8154 
8155  // do the damage
8156  if ( damage > 0 ) {
8157 
8158  if ( !gameLocal.isMultiplayer ) {
8159 #ifdef _D3XP
8160  float scale = new_g_damageScale;
8161 #else
8162  float scale = g_damageScale.GetFloat();
8163 #endif
8164  if ( g_useDynamicProtection.GetBool() && g_skill.GetInteger() < 2 ) {
8165  if ( gameLocal.time > lastDmgTime + 500 && scale > 0.25f ) {
8166  scale -= 0.05f;
8167 #ifdef _D3XP
8168  new_g_damageScale = scale;
8169 #else
8170  g_damageScale.SetFloat( scale );
8171 #endif
8172  }
8173  }
8174 
8175  if ( scale > 0.0f ) {
8176  damage *= scale;
8177  }
8178  }
8179 
8180  if ( damage < 1 ) {
8181  damage = 1;
8182  }
8183 
8184  int oldHealth = health;
8185  health -= damage;
8186 
8187  if ( health <= 0 ) {
8188 
8189  if ( health < -999 ) {
8190  health = -999;
8191  }
8192 
8193  isTelefragged = damageDef->dict.GetBool( "telefrag" );
8194 
8196  Killed( inflictor, attacker, damage, dir, location );
8197 
8198  } else {
8199  // force a blink
8200  blink_time = 0;
8201 
8202  // let the anim script know we took damage
8203  AI_PAIN = Pain( inflictor, attacker, damage, dir, location );
8204  if ( !g_testDeath.GetBool() ) {
8206  }
8207  }
8208  } else {
8209  // don't accumulate impulses
8210  if ( af.IsLoaded() ) {
8211  // clear impacts
8212  af.Rest();
8213 
8214  // physics is turned off by calling af.Rest()
8216  }
8217  }
8218 
8219  lastDamageDef = damageDef->Index();
8220  lastDamageDir = damage_from;
8222 }
8223 
8224 /*
8225 ===========
8226 idPlayer::Teleport
8227 ============
8228 */
8229 void idPlayer::Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination ) {
8230  idVec3 org;
8231 
8232  if ( weapon.GetEntity() ) {
8233  weapon.GetEntity()->LowerWeapon();
8234  }
8235 
8236  SetOrigin( origin + idVec3( 0, 0, CM_CLIP_EPSILON ) );
8237  if ( !gameLocal.isMultiplayer && GetFloorPos( 16.0f, org ) ) {
8238  SetOrigin( org );
8239  }
8240 
8241  // clear the ik heights so model doesn't appear in the wrong place
8242  walkIK.EnableAll();
8243 
8245 
8246  SetViewAngles( angles );
8247 
8248  legsYaw = 0.0f;
8249  idealLegsYaw = 0.0f;
8251 
8252  if ( gameLocal.isMultiplayer ) {
8253  playerView.Flash( colorWhite, 140 );
8254  }
8255 
8256  UpdateVisuals();
8257 
8258  teleportEntity = destination;
8259 
8260  if ( !gameLocal.isClient && !noclip ) {
8261  if ( gameLocal.isMultiplayer ) {
8262  // kill anything at the new position or mark for kill depending on immediate or delayed teleport
8263  gameLocal.KillBox( this, destination != NULL );
8264  } else {
8265  // kill anything at the new position
8266  gameLocal.KillBox( this, true );
8267  }
8268  }
8269 
8270 #ifdef _D3XP
8271  if ( PowerUpActive( HELLTIME ) ) {
8272  StopHelltime();
8273  }
8274 #endif
8275 }
8276 
8277 /*
8278 ====================
8279 idPlayer::SetPrivateCameraView
8280 ====================
8281 */
8282 void idPlayer::SetPrivateCameraView( idCamera *camView ) {
8283  privateCameraView = camView;
8284  if ( camView ) {
8285  StopFiring();
8286  Hide();
8287  } else {
8288  if ( !spectating ) {
8289  Show();
8290  }
8291  }
8292 }
8293 
8294 /*
8295 ====================
8296 idPlayer::DefaultFov
8297 
8298 Returns the base FOV
8299 ====================
8300 */
8301 float idPlayer::DefaultFov( void ) const {
8302  float fov;
8303 
8304  fov = g_fov.GetFloat();
8305  if ( gameLocal.isMultiplayer ) {
8306  if ( fov < 90.0f ) {
8307  return 90.0f;
8308  } else if ( fov > 110.0f ) {
8309  return 110.0f;
8310  }
8311  }
8312 
8313  return fov;
8314 }
8315 
8316 /*
8317 ====================
8318 idPlayer::CalcFov
8319 
8320 Fixed fov at intermissions, otherwise account for fov variable and zooms.
8321 ====================
8322 */
8323 float idPlayer::CalcFov( bool honorZoom ) {
8324  float fov;
8325 
8326  if ( fxFov ) {
8327  return DefaultFov() + 10.0f + cos( ( gameLocal.time + 2000 ) * 0.01 ) * 10.0f;
8328  }
8329 
8330  if ( influenceFov ) {
8331  return influenceFov;
8332  }
8333 
8334  if ( zoomFov.IsDone( gameLocal.time ) ) {
8335  fov = ( honorZoom && usercmd.buttons & BUTTON_ZOOM ) && weapon.GetEntity() ? weapon.GetEntity()->GetZoomFov() : DefaultFov();
8336  } else {
8338  }
8339 
8340  // bound normal viewsize
8341  if ( fov < 1 ) {
8342  fov = 1;
8343  } else if ( fov > 179 ) {
8344  fov = 179;
8345  }
8346 
8347  return fov;
8348 }
8349 
8350 /*
8351 ==============
8352 idPlayer::GunTurningOffset
8353 
8354 generate a rotational offset for the gun based on the view angle
8355 history in loggedViewAngles
8356 ==============
8357 */
8359  idAngles a;
8360 
8361  a.Zero();
8362 
8363  if ( gameLocal.framenum < NUM_LOGGED_VIEW_ANGLES ) {
8364  return a;
8365  }
8366 
8367  idAngles current = loggedViewAngles[ gameLocal.framenum & (NUM_LOGGED_VIEW_ANGLES-1) ];
8368 
8369  idAngles av, base;
8370  int weaponAngleOffsetAverages;
8371  float weaponAngleOffsetScale, weaponAngleOffsetMax;
8372 
8373  weapon.GetEntity()->GetWeaponAngleOffsets( &weaponAngleOffsetAverages, &weaponAngleOffsetScale, &weaponAngleOffsetMax );
8374 
8375  av = current;
8376 
8377  // calcualte this so the wrap arounds work properly
8378  for ( int j = 1 ; j < weaponAngleOffsetAverages ; j++ ) {
8379  idAngles a2 = loggedViewAngles[ ( gameLocal.framenum - j ) & (NUM_LOGGED_VIEW_ANGLES-1) ];
8380 
8381  idAngles delta = a2 - current;
8382 
8383  if ( delta[1] > 180 ) {
8384  delta[1] -= 360;
8385  } else if ( delta[1] < -180 ) {
8386  delta[1] += 360;
8387  }
8388 
8389  av += delta * ( 1.0f / weaponAngleOffsetAverages );
8390  }
8391 
8392  a = ( av - current ) * weaponAngleOffsetScale;
8393 
8394  for ( int i = 0 ; i < 3 ; i++ ) {
8395  if ( a[i] < -weaponAngleOffsetMax ) {
8396  a[i] = -weaponAngleOffsetMax;
8397  } else if ( a[i] > weaponAngleOffsetMax ) {
8398  a[i] = weaponAngleOffsetMax;
8399  }
8400  }
8401 
8402  return a;
8403 }
8404 
8405 /*
8406 ==============
8407 idPlayer::GunAcceleratingOffset
8408 
8409 generate a positional offset for the gun based on the movement
8410 history in loggedAccelerations
8411 ==============
8412 */
8414  idVec3 ofs;
8415 
8416  float weaponOffsetTime, weaponOffsetScale;
8417 
8418  ofs.Zero();
8419 
8420  weapon.GetEntity()->GetWeaponTimeOffsets( &weaponOffsetTime, &weaponOffsetScale );
8421 
8423  if ( stop < 0 ) {
8424  stop = 0;
8425  }
8426  for ( int i = currentLoggedAccel-1 ; i > stop ; i-- ) {
8427  loggedAccel_t *acc = &loggedAccel[i&(NUM_LOGGED_ACCELS-1)];
8428 
8429  float f;
8430  float t = gameLocal.time - acc->time;
8431  if ( t >= weaponOffsetTime ) {
8432  break; // remainder are too old to care about
8433  }
8434 
8435  f = t / weaponOffsetTime;
8436  f = ( cos( f * 2.0f * idMath::PI ) - 1.0f ) * 0.5f;
8437  ofs += f * weaponOffsetScale * acc->dir;
8438  }
8439 
8440  return ofs;
8441 }
8442 
8443 /*
8444 ==============
8445 idPlayer::CalculateViewWeaponPos
8446 
8447 Calculate the bobbing position of the view weapon
8448 ==============
8449 */
8450 void idPlayer::CalculateViewWeaponPos( idVec3 &origin, idMat3 &axis ) {
8451  float scale;
8452  float fracsin;
8453  idAngles angles;
8454  int delta;
8455 
8456  // CalculateRenderView must have been called first
8457  const idVec3 &viewOrigin = firstPersonViewOrigin;
8459 
8460  // these cvars are just for hand tweaking before moving a value to the weapon def
8462 
8463  // as the player changes direction, the gun will take a small lag
8464  idVec3 gunOfs = GunAcceleratingOffset();
8465  origin = viewOrigin + ( gunpos + gunOfs ) * viewAxis;
8466 
8467  // on odd legs, invert some angles
8468  if ( bobCycle & 128 ) {
8469  scale = -xyspeed;
8470  } else {
8471  scale = xyspeed;
8472  }
8473 
8474  // gun angles from bobbing
8475  angles.roll = scale * bobfracsin * 0.005f;
8476  angles.yaw = scale * bobfracsin * 0.01f;
8477  angles.pitch = xyspeed * bobfracsin * 0.005f;
8478 
8479  // gun angles from turning
8480  if ( gameLocal.isMultiplayer ) {
8481  idAngles offset = GunTurningOffset();
8482  offset *= g_mpWeaponAngleScale.GetFloat();
8483  angles += offset;
8484  } else {
8485  angles += GunTurningOffset();
8486  }
8487 
8488  idVec3 gravity = physicsObj.GetGravityNormal();
8489 
8490  // drop the weapon when landing after a jump / fall
8491  delta = gameLocal.time - landTime;
8492  if ( delta < LAND_DEFLECT_TIME ) {
8493  origin -= gravity * ( landChange*0.25f * delta / LAND_DEFLECT_TIME );
8494  } else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
8495  origin -= gravity * ( landChange*0.25f * (LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta) / LAND_RETURN_TIME );
8496  }
8497 
8498  // speed sensitive idle drift
8499  scale = xyspeed + 40.0f;
8500  fracsin = scale * sin( MS2SEC( gameLocal.time ) ) * 0.01f;
8501  angles.roll += fracsin;
8502  angles.yaw += fracsin;
8503  angles.pitch += fracsin;
8504 
8505  axis = angles.ToMat3() * viewAxis;
8506 }
8507 
8508 /*
8509 ===============
8510 idPlayer::OffsetThirdPersonView
8511 ===============
8512 */
8513 void idPlayer::OffsetThirdPersonView( float angle, float range, float height, bool clip ) {
8514  idVec3 view;
8515  idVec3 focusAngles;
8516  trace_t trace;
8517  idVec3 focusPoint;
8518  float focusDist;
8519  float forwardScale, sideScale;
8520  idVec3 origin;
8521  idAngles angles;
8522  idMat3 axis;
8523  idBounds bounds;
8524 
8525  angles = viewAngles;
8526  GetViewPos( origin, axis );
8527 
8528  if ( angle ) {
8529  angles.pitch = 0.0f;
8530  }
8531 
8532  if ( angles.pitch > 45.0f ) {
8533  angles.pitch = 45.0f; // don't go too far overhead
8534  }
8535 
8536  focusPoint = origin + angles.ToForward() * THIRD_PERSON_FOCUS_DISTANCE;
8537  focusPoint.z += height;
8538  view = origin;
8539  view.z += 8 + height;
8540 
8541  angles.pitch *= 0.5f;
8543 
8544  idMath::SinCos( DEG2RAD( angle ), sideScale, forwardScale );
8545  view -= range * forwardScale * renderView->viewaxis[ 0 ];
8546  view += range * sideScale * renderView->viewaxis[ 1 ];
8547 
8548  if ( clip ) {
8549  // trace a ray from the origin to the viewpoint to make sure the view isn't
8550  // in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything
8551  bounds = idBounds( idVec3( -4, -4, -4 ), idVec3( 4, 4, 4 ) );
8552  gameLocal.clip.TraceBounds( trace, origin, view, bounds, MASK_SOLID, this );
8553  if ( trace.fraction != 1.0f ) {
8554  view = trace.endpos;
8555  view.z += ( 1.0f - trace.fraction ) * 32.0f;
8556 
8557  // try another trace to this position, because a tunnel may have the ceiling
8558  // close enough that this is poking out
8559  gameLocal.clip.TraceBounds( trace, origin, view, bounds, MASK_SOLID, this );
8560  view = trace.endpos;
8561  }
8562  }
8563 
8564  // select pitch to look at focus point from vieword
8565  focusPoint -= view;
8566  focusDist = idMath::Sqrt( focusPoint[0] * focusPoint[0] + focusPoint[1] * focusPoint[1] );
8567  if ( focusDist < 1.0f ) {
8568  focusDist = 1.0f; // should never happen
8569  }
8570 
8571  angles.pitch = - RAD2DEG( atan2( focusPoint.z, focusDist ) );
8572  angles.yaw -= angle;
8573 
8574  renderView->vieworg = view;
8576  renderView->viewID = 0;
8577 }
8578 
8579 /*
8580 ===============
8581 idPlayer::GetEyePosition
8582 ===============
8583 */
8584 idVec3 idPlayer::GetEyePosition( void ) const {
8585  idVec3 org;
8586 
8587  // use the smoothed origin if spectating another player in multiplayer
8588  if ( gameLocal.isClient && entityNumber != gameLocal.localClientNum ) {
8589  org = smoothedOrigin;
8590  } else {
8591  org = GetPhysics()->GetOrigin();
8592  }
8593  return org + ( GetPhysics()->GetGravityNormal() * -eyeOffset.z );
8594 }
8595 
8596 /*
8597 ===============
8598 idPlayer::GetViewPos
8599 ===============
8600 */
8601 void idPlayer::GetViewPos( idVec3 &origin, idMat3 &axis ) const {
8602  idAngles angles;
8603 
8604  // if dead, fix the angle and don't add any kick
8605  if ( health <= 0 ) {
8606  angles.yaw = viewAngles.yaw;
8607  angles.roll = 40;
8608  angles.pitch = -15;
8609  axis = angles.ToMat3();
8610  origin = GetEyePosition();
8611  } else {
8612  origin = GetEyePosition() + viewBob;
8614 
8615  axis = angles.ToMat3() * physicsObj.GetGravityAxis();
8616 
8617  // adjust the origin based on the camera nodal distance (eye distance from neck)
8619  origin += axis[0] * g_viewNodalX.GetFloat() + axis[2] * g_viewNodalZ.GetFloat();
8620  }
8621 }
8622 
8623 /*
8624 ===============
8625 idPlayer::CalculateFirstPersonView
8626 ===============
8627 */
8629  if ( ( pm_modelView.GetInteger() == 1 ) || ( ( pm_modelView.GetInteger() == 2 ) && ( health <= 0 ) ) ) {
8630  // Displays the view from the point of view of the "camera" joint in the player model
8631 
8632  idMat3 axis;
8633  idVec3 origin;
8634  idAngles ang;
8635 
8637  ang.yaw += viewAxis[ 0 ].ToYaw();
8638 
8639  jointHandle_t joint = animator.GetJointHandle( "camera" );
8640  animator.GetJointTransform( joint, gameLocal.time, origin, axis );
8641  firstPersonViewOrigin = ( origin + modelOffset ) * ( viewAxis * physicsObj.GetGravityAxis() ) + physicsObj.GetOrigin() + viewBob;
8643  } else {
8644  // offset for local bobbing and kicks
8646 #if 0
8647  // shakefrom sound stuff only happens in first person
8649 #endif
8650  }
8651 }
8652 
8653 /*
8654 ==================
8655 idPlayer::GetRenderView
8656 
8657 Returns the renderView that was calculated for this tic
8658 ==================
8659 */
8661  return renderView;
8662 }
8663 
8664 /*
8665 ==================
8666 idPlayer::CalculateRenderView
8667 
8668 create the renderView for the current tic
8669 ==================
8670 */
8671 void idPlayer::CalculateRenderView( void ) {
8672  int i;
8673  float range;
8674 
8675  if ( !renderView ) {
8676  renderView = new renderView_t;
8677  }
8678  memset( renderView, 0, sizeof( *renderView ) );
8679 
8680  // copy global shader parms
8681  for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
8683  }
8685 
8686 #ifdef _D3XP
8687  renderView->time = gameLocal.slow.time;
8688 #endif
8689 
8690  // calculate size of 3D view
8691  renderView->x = 0;
8692  renderView->y = 0;
8695  renderView->viewID = 0;
8696 
8697  // check if we should be drawing from a camera's POV
8698  if ( !noclip && (gameLocal.GetCamera() || privateCameraView) ) {
8699  // get origin, axis, and fov
8700  if ( privateCameraView ) {
8702  } else {
8704  }
8705  } else {
8706  if ( g_stopTime.GetBool() ) {
8709 
8710  if ( !pm_thirdPerson.GetBool() ) {
8711  // set the viewID to the clientNum + 1, so we can suppress the right player bodies and
8712  // allow the right player view weapons
8713  renderView->viewID = entityNumber + 1;
8714  }
8715  } else if ( pm_thirdPerson.GetBool() ) {
8717  } else if ( pm_thirdPersonDeath.GetBool() ) {
8718  range = gameLocal.time < minRespawnTime ? ( gameLocal.time + RAGDOLL_DEATH_TIME - minRespawnTime ) * ( 120.0f / RAGDOLL_DEATH_TIME ) : 120.0f;
8719  OffsetThirdPersonView( 0.0f, 20.0f + range, 0.0f, false );
8720  } else {
8723 
8724  // set the viewID to the clientNum + 1, so we can suppress the right player bodies and
8725  // allow the right player view weapons
8726  renderView->viewID = entityNumber + 1;
8727  }
8728 
8729  // field of view
8731  }
8732 
8733  if ( renderView->fov_y == 0 ) {
8734  common->Error( "renderView->fov_y == 0" );
8735  }
8736 
8737  if ( g_showviewpos.GetBool() ) {
8739  }
8740 }
8741 
8742 /*
8743 =============
8744 idPlayer::AddAIKill
8745 =============
8746 */
8747 void idPlayer::AddAIKill( void ) {
8748 
8749 #ifndef _D3XP
8750 
8751  int max_souls;
8752  int ammo_souls;
8753 
8754  if ( ( weapon_soulcube < 0 ) || ( inventory.weapons & ( 1 << weapon_soulcube ) ) == 0 ) {
8755  return;
8756  }
8757 
8758  assert( hud );
8759 
8760 
8761  ammo_souls = idWeapon::GetAmmoNumForName( "ammo_souls" );
8762  max_souls = inventory.MaxAmmoForAmmoClass( this, "ammo_souls" );
8763  if ( inventory.ammo[ ammo_souls ] < max_souls ) {
8764  inventory.ammo[ ammo_souls ]++;
8765  if ( inventory.ammo[ ammo_souls ] >= max_souls ) {
8766  hud->HandleNamedEvent( "soulCubeReady" );
8767  StartSound( "snd_soulcube_ready", SND_CHANNEL_ANY, 0, false, NULL );
8768  }
8769  }
8770 #endif
8771 }
8772 
8773 /*
8774 =============
8775 idPlayer::SetSoulCubeProjectile
8776 =============
8777 */
8778 void idPlayer::SetSoulCubeProjectile( idProjectile *projectile ) {
8779  soulCubeProjectile = projectile;
8780 }
8781 
8782 /*
8783 =============
8784 idPlayer::AddProjectilesFired
8785 =============
8786 */
8787 void idPlayer::AddProjectilesFired( int count ) {
8789 }
8790 
8791 /*
8792 =============
8793 idPlayer::AddProjectileHites
8794 =============
8795 */
8796 void idPlayer::AddProjectileHits( int count ) {
8798 }
8799 
8800 /*
8801 =============
8802 idPlayer::SetLastHitTime
8803 =============
8804 */
8805 void idPlayer::SetLastHitTime( int time ) {
8806  idPlayer *aimed = NULL;
8807 
8808  if ( time && lastHitTime != time ) {
8809  lastHitToggle ^= 1;
8810  }
8811  lastHitTime = time;
8812  if ( !time ) {
8813  // level start and inits
8814  return;
8815  }
8816  if ( gameLocal.isMultiplayer && ( time - lastSndHitTime ) > 10 ) {
8817  lastSndHitTime = time;
8818  StartSound( "snd_hit_feedback", SND_CHANNEL_ANY, SSF_PRIVATE_SOUND, false, NULL );
8819  }
8820  if ( cursor ) {
8821  cursor->HandleNamedEvent( "hitTime" );
8822  }
8823  if ( hud ) {
8824  if ( MPAim != -1 ) {
8825  if ( gameLocal.entities[ MPAim ] && gameLocal.entities[ MPAim ]->IsType( idPlayer::Type ) ) {
8826  aimed = static_cast< idPlayer * >( gameLocal.entities[ MPAim ] );
8827  }
8828  assert( aimed );
8829  // full highlight, no fade till loosing aim
8830  hud->SetStateString( "aim_text", gameLocal.userInfo[ MPAim ].GetString( "ui_name" ) );
8831  if ( aimed ) {
8832  hud->SetStateFloat( "aim_color", aimed->colorBarIndex );
8833  }
8834  hud->HandleNamedEvent( "aim_flash" );
8835  MPAimHighlight = true;
8836  MPAimFadeTime = 0;
8837  } else if ( lastMPAim != -1 ) {
8838  if ( gameLocal.entities[ lastMPAim ] && gameLocal.entities[ lastMPAim ]->IsType( idPlayer::Type ) ) {
8839  aimed = static_cast< idPlayer * >( gameLocal.entities[ lastMPAim ] );
8840  }
8841  assert( aimed );
8842  // start fading right away
8843  hud->SetStateString( "aim_text", gameLocal.userInfo[ lastMPAim ].GetString( "ui_name" ) );
8844  if ( aimed ) {
8845  hud->SetStateFloat( "aim_color", aimed->colorBarIndex );
8846  }
8847  hud->HandleNamedEvent( "aim_flash" );
8848  hud->HandleNamedEvent( "aim_fade" );
8849  MPAimHighlight = false;
8851  }
8852  }
8853 }
8854 
8855 /*
8856 =============
8857 idPlayer::SetInfluenceLevel
8858 =============
8859 */
8860 void idPlayer::SetInfluenceLevel( int level ) {
8861  if ( level != influenceActive ) {
8862  if ( level ) {
8863  for ( idEntity *ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
8864  if ( ent->IsType( idProjectile::Type ) ) {
8865  // remove all projectiles
8866  ent->PostEventMS( &EV_Remove, 0 );
8867  }
8868  }
8869  if ( weaponEnabled && weapon.GetEntity() ) {
8870  weapon.GetEntity()->EnterCinematic();
8871  }
8872  } else {
8874  if ( weaponEnabled && weapon.GetEntity() ) {
8875  weapon.GetEntity()->ExitCinematic();
8876  }
8877  }
8879  }
8880 }
8881 
8882 /*
8883 =============
8884 idPlayer::SetInfluenceView
8885 =============
8886 */
8887 void idPlayer::SetInfluenceView( const char *mtr, const char *skinname, float radius, idEntity *ent ) {
8890  influenceSkin = NULL;
8891  if ( mtr && *mtr ) {
8893  }
8894  if ( skinname && *skinname ) {
8895  influenceSkin = declManager->FindSkin( skinname );
8896  if ( head.GetEntity() ) {
8898  }
8899  UpdateVisuals();
8900  }
8901  influenceRadius = radius;
8902  if ( radius > 0.0f ) {
8903  influenceEntity = ent;
8904  }
8905 }
8906 
8907 /*
8908 =============
8909 idPlayer::SetInfluenceFov
8910 =============
8911 */
8912 void idPlayer::SetInfluenceFov( float fov ) {
8913  influenceFov = fov;
8914 }
8915 
8916 /*
8917 ================
8918 idPlayer::OnLadder
8919 ================
8920 */
8921 bool idPlayer::OnLadder( void ) const {
8922  return physicsObj.OnLadder();
8923 }
8924 
8925 /*
8926 ==================
8927 idPlayer::Event_GetButtons
8928 ==================
8929 */
8930 void idPlayer::Event_GetButtons( void ) {
8932 }
8933 
8934 /*
8935 ==================
8936 idPlayer::Event_GetMove
8937 ==================
8938 */
8939 void idPlayer::Event_GetMove( void ) {
8941  idThread::ReturnVector( move );
8942 }
8943 
8944 /*
8945 ================
8946 idPlayer::Event_GetViewAngles
8947 ================
8948 */
8949 void idPlayer::Event_GetViewAngles( void ) {
8951 }
8952 
8953 /*
8954 ==================
8955 idPlayer::Event_StopFxFov
8956 ==================
8957 */
8958 void idPlayer::Event_StopFxFov( void ) {
8959  fxFov = false;
8960 }
8961 
8962 /*
8963 ==================
8964 idPlayer::StartFxFov
8965 ==================
8966 */
8967 void idPlayer::StartFxFov( float duration ) {
8968  fxFov = true;
8969  PostEventSec( &EV_Player_StopFxFov, duration );
8970 }
8971 
8972 /*
8973 ==================
8974 idPlayer::Event_EnableWeapon
8975 ==================
8976 */
8977 void idPlayer::Event_EnableWeapon( void ) {
8978  hiddenWeapon = gameLocal.world->spawnArgs.GetBool( "no_Weapons" );
8979  weaponEnabled = true;
8980  if ( weapon.GetEntity() ) {
8981  weapon.GetEntity()->ExitCinematic();
8982  }
8983 }
8984 
8985 /*
8986 ==================
8987 idPlayer::Event_DisableWeapon
8988 ==================
8989 */
8990 void idPlayer::Event_DisableWeapon( void ) {
8991  hiddenWeapon = gameLocal.world->spawnArgs.GetBool( "no_Weapons" );
8992  weaponEnabled = false;
8993  if ( weapon.GetEntity() ) {
8994  weapon.GetEntity()->EnterCinematic();
8995  }
8996 }
8997 
8998 #ifdef _D3XP
8999 /*
9000 ==================
9001 idPlayer::Event_GiveInventoryItem
9002 ==================
9003 */
9004 void idPlayer::Event_GiveInventoryItem( const char* name ) {
9005  GiveInventoryItem(name);
9006 }
9007 
9008 /*
9009 ==================
9010 idPlayer::Event_RemoveInventoryItem
9011 ==================
9012 */
9013 void idPlayer::Event_RemoveInventoryItem( const char* name ) {
9014  RemoveInventoryItem(name);
9015 }
9016 
9017 /*
9018 ==================
9019 idPlayer::Event_GetIdealWeapon
9020 ==================
9021 */
9022 void idPlayer::Event_GetIdealWeapon( void ) {
9023  const char *weapon;
9024 
9025  if ( idealWeapon >= 0 ) {
9026  weapon = spawnArgs.GetString( va( "def_weapon%d", idealWeapon ) );
9027  idThread::ReturnString( weapon );
9028  } else {
9029  idThread::ReturnString( "" );
9030  }
9031 }
9032 
9033 /*
9034 ==================
9035 idPlayer::Event_SetPowerupTime
9036 ==================
9037 */
9038 void idPlayer::Event_SetPowerupTime( int powerup, int time ) {
9039  if ( time > 0 ) {
9040  GivePowerUp( powerup, time );
9041  } else {
9042  ClearPowerup( powerup );
9043  }
9044 }
9045 
9046 /*
9047 ==================
9048 idPlayer::Event_IsPowerupActive
9049 ==================
9050 */
9051 void idPlayer::Event_IsPowerupActive( int powerup ) {
9052  idThread::ReturnInt(this->PowerUpActive(powerup) ? 1 : 0);
9053 }
9054 
9055 /*
9056 ==================
9057 idPlayer::Event_StartWarp
9058 ==================
9059 */
9060 void idPlayer::Event_StartWarp() {
9061  playerView.AddWarp( idVec3( 0, 0, 0 ), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 100, 1000 );
9062 }
9063 
9064 /*
9065 ==================
9066 idPlayer::Event_StopHelltime
9067 ==================
9068 */
9069 void idPlayer::Event_StopHelltime( int mode ) {
9070  if ( mode == 1 ) {
9071  StopHelltime( true );
9072  }
9073  else {
9074  StopHelltime( false );
9075  }
9076 }
9077 
9078 /*
9079 ==================
9080 idPlayer::Event_WeaponAvailable
9081 ==================
9082 */
9083 void idPlayer::Event_WeaponAvailable( const char* name ) {
9084 
9085  idThread::ReturnInt( WeaponAvailable(name) ? 1 : 0 );
9086 }
9087 
9088 bool idPlayer::WeaponAvailable( const char* name ) {
9089  for( int i = 0; i < MAX_WEAPONS; i++ ) {
9090  if ( inventory.weapons & ( 1 << i ) ) {
9091  const char *weap = spawnArgs.GetString( va( "def_weapon%d", i ) );
9092  if ( !idStr::Cmp( weap, name ) ) {
9093  return true;
9094  }
9095  }
9096  }
9097  return false;
9098 }
9099 
9100 #endif
9101 
9102 /*
9103 ==================
9104 idPlayer::Event_GetCurrentWeapon
9105 ==================
9106 */
9107 void idPlayer::Event_GetCurrentWeapon( void ) {
9108  const char *weapon;
9109 
9110  if ( currentWeapon >= 0 ) {
9111  weapon = spawnArgs.GetString( va( "def_weapon%d", currentWeapon ) );
9112  idThread::ReturnString( weapon );
9113  } else {
9114  idThread::ReturnString( "" );
9115  }
9116 }
9117 
9118 /*
9119 ==================
9120 idPlayer::Event_GetPreviousWeapon
9121 ==================
9122 */
9123 void idPlayer::Event_GetPreviousWeapon( void ) {
9124  const char *weapon;
9125 
9126  if ( previousWeapon >= 0 ) {
9127  int pw = ( gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) ) ? 0 : previousWeapon;
9128  weapon = spawnArgs.GetString( va( "def_weapon%d", pw) );
9129  idThread::ReturnString( weapon );
9130  } else {
9131  idThread::ReturnString( spawnArgs.GetString( "def_weapon0" ) );
9132  }
9133 }
9134 
9135 /*
9136 ==================
9137 idPlayer::Event_SelectWeapon
9138 ==================
9139 */
9140 void idPlayer::Event_SelectWeapon( const char *weaponName ) {
9141  int i;
9142  int weaponNum;
9143 
9144  if ( gameLocal.isClient ) {
9145  gameLocal.Warning( "Cannot switch weapons from script in multiplayer" );
9146  return;
9147  }
9148 
9149  if ( hiddenWeapon && gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) ) {
9150  idealWeapon = weapon_fists;
9151  weapon.GetEntity()->HideWeapon();
9152  return;
9153  }
9154 
9155  weaponNum = -1;
9156  for( i = 0; i < MAX_WEAPONS; i++ ) {
9157  if ( inventory.weapons & ( 1 << i ) ) {
9158  const char *weap = spawnArgs.GetString( va( "def_weapon%d", i ) );
9159  if ( !idStr::Cmp( weap, weaponName ) ) {
9160  weaponNum = i;
9161  break;
9162  }
9163  }
9164  }
9165 
9166  if ( weaponNum < 0 ) {
9167  gameLocal.Warning( "%s is not carrying weapon '%s'", name.c_str(), weaponName );
9168  return;
9169  }
9170 
9171  hiddenWeapon = false;
9172  idealWeapon = weaponNum;
9173 
9174  UpdateHudWeapon();
9175 }
9176 
9177 /*
9178 ==================
9179 idPlayer::Event_GetWeaponEntity
9180 ==================
9181 */
9182 void idPlayer::Event_GetWeaponEntity( void ) {
9183  idThread::ReturnEntity( weapon.GetEntity() );
9184 }
9185 
9186 /*
9187 ==================
9188 idPlayer::Event_OpenPDA
9189 ==================
9190 */
9191 void idPlayer::Event_OpenPDA( void ) {
9192  if ( !gameLocal.isMultiplayer ) {
9193  TogglePDA();
9194  }
9195 }
9196 
9197 /*
9198 ==================
9199 idPlayer::Event_InPDA
9200 ==================
9201 */
9202 void idPlayer::Event_InPDA( void ) {
9204 }
9205 
9206 /*
9207 ==================
9208 idPlayer::TeleportDeath
9209 ==================
9210 */
9211 void idPlayer::TeleportDeath( int killer ) {
9212  teleportKiller = killer;
9213 }
9214 
9215 /*
9216 ==================
9217 idPlayer::Event_ExitTeleporter
9218 ==================
9219 */
9220 void idPlayer::Event_ExitTeleporter( void ) {
9221  idEntity *exitEnt;
9222  float pushVel;
9223 
9224  // verify and setup
9225  exitEnt = teleportEntity.GetEntity();
9226  if ( !exitEnt ) {
9227  common->DPrintf( "Event_ExitTeleporter player %d while not being teleported\n", entityNumber );
9228  return;
9229  }
9230 
9231  pushVel = exitEnt->spawnArgs.GetFloat( "push", "300" );
9232 
9233  if ( gameLocal.isServer ) {
9235  }
9236 
9238  // setup origin and push according to the exit target
9239  SetOrigin( exitEnt->GetPhysics()->GetOrigin() + idVec3( 0, 0, CM_CLIP_EPSILON ) );
9240  SetViewAngles( exitEnt->GetPhysics()->GetAxis().ToAngles() );
9241  physicsObj.SetLinearVelocity( exitEnt->GetPhysics()->GetAxis()[ 0 ] * pushVel );
9243  // teleport fx
9244  playerView.Flash( colorWhite, 120 );
9245 
9246  // clear the ik heights so model doesn't appear in the wrong place
9247  walkIK.EnableAll();
9248 
9249  UpdateVisuals();
9250 
9251  StartSound( "snd_teleport_exit", SND_CHANNEL_ANY, 0, false, NULL );
9252 
9253  if ( teleportKiller != -1 ) {
9254  // we got killed while being teleported
9256  teleportKiller = -1;
9257  } else {
9258  // kill anything that would have waited at teleport exit
9259  gameLocal.KillBox( this );
9260  }
9261  teleportEntity = NULL;
9262 }
9263 
9264 /*
9265 ================
9266 idPlayer::ClientPredictionThink
9267 ================
9268 */
9269 void idPlayer::ClientPredictionThink( void ) {
9270  renderEntity_t *headRenderEnt;
9271 
9274 
9276 
9277  if ( entityNumber != gameLocal.localClientNum ) {
9278  // ignore attack button of other clients. that's no good for predictions
9279  usercmd.buttons &= ~BUTTON_ATTACK;
9280  }
9281 
9284 
9285 #ifdef _D3XP
9286  if ( mountedObject ) {
9287  usercmd.forwardmove = 0;
9288  usercmd.rightmove = 0;
9289  usercmd.upmove = 0;
9290  }
9291 #endif
9292 
9293  if ( objectiveSystemOpen ) {
9294  usercmd.forwardmove = 0;
9295  usercmd.rightmove = 0;
9296  usercmd.upmove = 0;
9297  }
9298 
9299  // clear the ik before we do anything else so the skeleton doesn't get updated twice
9301 
9302  if ( gameLocal.isNewFrame ) {
9305  }
9306  }
9307 
9309 
9310  AdjustSpeed();
9311 
9312  UpdateViewAngles();
9313 
9314  // update the smoothed view angles
9315  if ( gameLocal.framenum >= smoothedFrame && entityNumber != gameLocal.localClientNum ) {
9316  idAngles anglesDiff = viewAngles - smoothedAngles;
9317  anglesDiff.Normalize180();
9318  if ( idMath::Fabs( anglesDiff.yaw ) < 90.0f && idMath::Fabs( anglesDiff.pitch ) < 90.0f ) {
9319  // smoothen by pushing back to the previous angles
9320  viewAngles -= gameLocal.clientSmoothing * anglesDiff;
9322  }
9323  smoothedAngles = viewAngles;
9324  }
9325  smoothedOriginUpdated = false;
9326 
9327  if ( !af.IsActive() ) {
9328  AdjustBodyAngles();
9329  }
9330 
9331  if ( !isLagged ) {
9332  // don't allow client to move when lagged
9333  Move();
9334  }
9335 
9336  // update GUIs, Items, and character interactions
9337  UpdateFocus();
9338 
9339  // service animations
9340  if ( !spectating && !af.IsActive() ) {
9341  UpdateConditions();
9342  UpdateAnimState();
9343  CheckBlink();
9344  }
9345 
9346  // clear out our pain flag so we can tell if we recieve any damage between now and the next time we think
9347  AI_PAIN = false;
9348 
9349  // calculate the exact bobbed view position, which is used to
9350  // position the view weapon, among other things
9352 
9353  // this may use firstPersonView, or a thirdPerson / camera view
9355 
9356  if ( !gameLocal.inCinematic && weapon.GetEntity() && ( health > 0 ) && !( gameLocal.isMultiplayer && spectating ) ) {
9357  UpdateWeapon();
9358  }
9359 
9360  UpdateHud();
9361 
9362  if ( gameLocal.isNewFrame ) {
9363  UpdatePowerUps();
9364  }
9365 
9366  UpdateDeathSkin( false );
9367 
9368  if ( head.GetEntity() ) {
9369  headRenderEnt = head.GetEntity()->GetRenderEntity();
9370  } else {
9371  headRenderEnt = NULL;
9372  }
9373 
9374  if ( headRenderEnt ) {
9375  if ( influenceSkin ) {
9376  headRenderEnt->customSkin = influenceSkin;
9377  } else {
9378  headRenderEnt->customSkin = NULL;
9379  }
9380  }
9381 
9384  if ( headRenderEnt ) {
9385  headRenderEnt->suppressShadowInViewID = 0;
9386  }
9387  } else {
9388  renderEntity.suppressShadowInViewID = entityNumber+1;
9389  if ( headRenderEnt ) {
9390  headRenderEnt->suppressShadowInViewID = entityNumber+1;
9391  }
9392  }
9393  // never cast shadows from our first-person muzzle flashes
9394  renderEntity.suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + entityNumber;
9395  if ( headRenderEnt ) {
9396  headRenderEnt->suppressShadowInLightID = LIGHTID_VIEW_MUZZLE_FLASH + entityNumber;
9397  }
9398 
9399  if ( !gameLocal.inCinematic ) {
9400  UpdateAnimation();
9401  }
9402 
9403 #ifdef _D3XP
9404  if ( enviroSuitLight.IsValid() ) {
9405  idAngles lightAng = firstPersonViewAxis.ToAngles();
9406  idVec3 lightOrg = firstPersonViewOrigin;
9407  const idDict *lightDef = gameLocal.FindEntityDefDict( "envirosuit_light", false );
9408 
9409  idVec3 enviroOffset = lightDef->GetVector( "enviro_offset" );
9410  idVec3 enviroAngleOffset = lightDef->GetVector( "enviro_angle_offset" );
9411 
9412  lightOrg += (enviroOffset.x * firstPersonViewAxis[0]);
9413  lightOrg += (enviroOffset.y * firstPersonViewAxis[1]);
9414  lightOrg += (enviroOffset.z * firstPersonViewAxis[2]);
9415  lightAng.pitch += enviroAngleOffset.x;
9416  lightAng.yaw += enviroAngleOffset.y;
9417  lightAng.roll += enviroAngleOffset.z;
9418 
9419  enviroSuitLight.GetEntity()->GetPhysics()->SetOrigin( lightOrg );
9420  enviroSuitLight.GetEntity()->GetPhysics()->SetAxis( lightAng.ToMat3() );
9421  enviroSuitLight.GetEntity()->UpdateVisuals();
9422  enviroSuitLight.GetEntity()->Present();
9423  }
9424 #endif
9425 
9426  if ( gameLocal.isMultiplayer ) {
9427  DrawPlayerIcons();
9428  }
9429 
9430  Present();
9431 
9433 
9434  LinkCombat();
9435 
9436  if ( gameLocal.isNewFrame && entityNumber == gameLocal.localClientNum ) {
9438  }
9439 
9440 #ifdef _D3XP
9441  // determine if portal sky is in pvs
9443  gameLocal.portalSkyActive = gameLocal.pvs.CheckAreasForPortalSky( clientPVS, GetPhysics()->GetOrigin() );
9444  gameLocal.pvs.FreeCurrentPVS( clientPVS );
9445 #endif
9446 }
9447 
9448 /*
9449 ================
9450 idPlayer::GetPhysicsToVisualTransform
9451 ================
9452 */
9453 bool idPlayer::GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ) {
9454  if ( af.IsActive() ) {
9455  af.GetPhysicsToVisualTransform( origin, axis );
9456  return true;
9457  }
9458 
9459  // smoothen the rendered origin and angles of other clients
9460  // smooth self origin if snapshots are telling us prediction is off
9461  if ( gameLocal.isClient && gameLocal.framenum >= smoothedFrame && ( entityNumber != gameLocal.localClientNum || selfSmooth ) ) {
9462  // render origin and axis
9463  idMat3 renderAxis = viewAxis * GetPhysics()->GetAxis();
9464  idVec3 renderOrigin = GetPhysics()->GetOrigin() + modelOffset * renderAxis;
9465 
9466  // update the smoothed origin
9467  if ( !smoothedOriginUpdated ) {
9468  idVec2 originDiff = renderOrigin.ToVec2() - smoothedOrigin.ToVec2();
9469  if ( originDiff.LengthSqr() < Square( 100.0f ) ) {
9470  // smoothen by pushing back to the previous position
9471  if ( selfSmooth ) {
9472  assert( entityNumber == gameLocal.localClientNum );
9473  renderOrigin.ToVec2() -= net_clientSelfSmoothing.GetFloat() * originDiff;
9474  } else {
9475  renderOrigin.ToVec2() -= gameLocal.clientSmoothing * originDiff;
9476  }
9477  }
9478  smoothedOrigin = renderOrigin;
9479 
9481  smoothedOriginUpdated = true;
9482  }
9483 
9484  axis = idAngles( 0.0f, smoothedAngles.yaw, 0.0f ).ToMat3();
9485  origin = ( smoothedOrigin - GetPhysics()->GetOrigin() ) * axis.Transpose();
9486 
9487  } else {
9488 
9489  axis = viewAxis;
9490  origin = modelOffset;
9491  }
9492  return true;
9493 }
9494 
9495 /*
9496 ================
9497 idPlayer::GetPhysicsToSoundTransform
9498 ================
9499 */
9500 bool idPlayer::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
9501  idCamera *camera;
9502 
9503  if ( privateCameraView ) {
9504  camera = privateCameraView;
9505  } else {
9506  camera = gameLocal.GetCamera();
9507  }
9508 
9509  if ( camera ) {
9510  renderView_t view;
9511 
9512  memset( &view, 0, sizeof( view ) );
9513  camera->GetViewParms( &view );
9514  origin = view.vieworg;
9515  axis = view.viewaxis;
9516  return true;
9517  } else {
9518  return idActor::GetPhysicsToSoundTransform( origin, axis );
9519  }
9520 }
9521 
9522 /*
9523 ================
9524 idPlayer::WriteToSnapshot
9525 ================
9526 */
9527 void idPlayer::WriteToSnapshot( idBitMsgDelta &msg ) const {
9528  physicsObj.WriteToSnapshot( msg );
9529  WriteBindToSnapshot( msg );
9530  msg.WriteDeltaFloat( 0.0f, deltaViewAngles[0] );
9531  msg.WriteDeltaFloat( 0.0f, deltaViewAngles[1] );
9532  msg.WriteDeltaFloat( 0.0f, deltaViewAngles[2] );
9533  msg.WriteShort( health );
9535  msg.WriteDir( lastDamageDir, 9 );
9537  msg.WriteBits( idealWeapon, idMath::BitsForInteger( MAX_WEAPONS ) );
9538  msg.WriteBits( inventory.weapons, MAX_WEAPONS );
9539  msg.WriteBits( weapon.GetSpawnId(), 32 );
9541  msg.WriteBits( lastHitToggle, 1 );
9542  msg.WriteBits( weaponGone, 1 );
9543  msg.WriteBits( isLagged, 1 );
9544  msg.WriteBits( isChatting, 1 );
9545 #ifdef CTF
9546  /* Needed for the scoreboard */
9547  msg.WriteBits( carryingFlag, 1 );
9548 #endif
9549 #ifdef _D3XP
9550  msg.WriteBits( enviroSuitLight.GetSpawnId(), 32 );
9551 #endif
9552 }
9553 
9554 /*
9555 ================
9556 idPlayer::ReadFromSnapshot
9557 ================
9558 */
9559 void idPlayer::ReadFromSnapshot( const idBitMsgDelta &msg ) {
9560  int i, oldHealth, newIdealWeapon, weaponSpawnId;
9561  bool newHitToggle, stateHitch;
9562 
9563  if ( snapshotSequence - lastSnapshotSequence > 1 ) {
9564  stateHitch = true;
9565  } else {
9566  stateHitch = false;
9567  }
9569 
9570  oldHealth = health;
9571 
9573  ReadBindFromSnapshot( msg );
9574  deltaViewAngles[0] = msg.ReadDeltaFloat( 0.0f );
9575  deltaViewAngles[1] = msg.ReadDeltaFloat( 0.0f );
9576  deltaViewAngles[2] = msg.ReadDeltaFloat( 0.0f );
9577  health = msg.ReadShort();
9579  lastDamageDir = msg.ReadDir( 9 );
9580  lastDamageLocation = msg.ReadShort();
9581  newIdealWeapon = msg.ReadBits( idMath::BitsForInteger( MAX_WEAPONS ) );
9582  inventory.weapons = msg.ReadBits( MAX_WEAPONS );
9583  weaponSpawnId = msg.ReadBits( 32 );
9585  newHitToggle = msg.ReadBits( 1 ) != 0;
9586  weaponGone = msg.ReadBits( 1 ) != 0;
9587  isLagged = msg.ReadBits( 1 ) != 0;
9588  isChatting = msg.ReadBits( 1 ) != 0;
9589 #ifdef CTF
9590  carryingFlag = msg.ReadBits( 1 ) != 0;
9591 #endif
9592 #ifdef _D3XP
9593  int enviroSpawnId;
9594  enviroSpawnId = msg.ReadBits( 32 );
9595  enviroSuitLight.SetSpawnId( enviroSpawnId );
9596 #endif
9597 
9598  // no msg reading below this
9599 
9600  if ( weapon.SetSpawnId( weaponSpawnId ) ) {
9601  if ( weapon.GetEntity() ) {
9602  // maintain ownership locally
9603  weapon.GetEntity()->SetOwner( this );
9604  }
9605  currentWeapon = -1;
9606  }
9607  // if not a local client assume the client has all ammo types
9608  if ( entityNumber != gameLocal.localClientNum ) {
9609  for( i = 0; i < AMMO_NUMTYPES; i++ ) {
9610  inventory.ammo[ i ] = 999;
9611  }
9612  }
9613 
9614  if ( oldHealth > 0 && health <= 0 ) {
9615  if ( stateHitch ) {
9616  // so we just hide and don't show a death skin
9617  UpdateDeathSkin( true );
9618  }
9619  // die
9620  AI_DEAD = true;
9621  ClearPowerUps();
9622  SetAnimState( ANIMCHANNEL_LEGS, "Legs_Death", 4 );
9623  SetAnimState( ANIMCHANNEL_TORSO, "Torso_Death", 4 );
9624  SetWaitState( "" );
9626  if ( entityNumber == gameLocal.localClientNum ) {
9627  playerView.Fade( colorBlack, 12000 );
9628  }
9629  StartRagdoll();
9631  if ( !stateHitch ) {
9632  StartSound( "snd_death", SND_CHANNEL_VOICE, 0, false, NULL );
9633  }
9634  if ( weapon.GetEntity() ) {
9635  weapon.GetEntity()->OwnerDied();
9636  }
9637  } else if ( oldHealth <= 0 && health > 0 ) {
9638  // respawn
9639  Init();
9640  StopRagdoll();
9641  SetPhysics( &physicsObj );
9643  SetCombatContents( true );
9644  } else if ( health < oldHealth && health > 0 ) {
9645  if ( stateHitch ) {
9647  } else {
9648  // damage feedback
9649  const idDeclEntityDef *def = static_cast<const idDeclEntityDef *>( declManager->DeclByIndex( DECL_ENTITYDEF, lastDamageDef, false ) );
9650  if ( def ) {
9651  playerView.DamageImpulse( lastDamageDir * viewAxis.Transpose(), &def->dict );
9652  AI_PAIN = Pain( NULL, NULL, oldHealth - health, lastDamageDir, lastDamageLocation );
9654  } else {
9655  common->Warning( "NET: no damage def for damage feedback '%d'\n", lastDamageDef );
9656  }
9657  }
9658  } else if ( health > oldHealth && PowerUpActive( MEGAHEALTH ) && !stateHitch ) {
9659  // just pulse, for any health raise
9660  healthPulse = true;
9661  }
9662 
9663 #ifdef _D3XP
9664  // If the player is alive, restore proper physics object
9665  if ( health > 0 && IsActiveAF() ) {
9666  StopRagdoll();
9667  SetPhysics( &physicsObj );
9669  SetCombatContents( true );
9670  }
9671 #endif
9672 
9673  if ( idealWeapon != newIdealWeapon ) {
9674  if ( stateHitch ) {
9675  weaponCatchup = true;
9676  }
9677  idealWeapon = newIdealWeapon;
9678  UpdateHudWeapon();
9679  }
9680 
9681  if ( lastHitToggle != newHitToggle ) {
9683  }
9684 
9685  if ( msg.HasChanged() ) {
9686  UpdateVisuals();
9687  }
9688 }
9689 
9690 /*
9691 ================
9692 idPlayer::WritePlayerStateToSnapshot
9693 ================
9694 */
9696  int i;
9697 
9698  msg.WriteByte( bobCycle );
9699  msg.WriteLong( stepUpTime );
9700  msg.WriteFloat( stepUpDelta );
9701 #ifdef _D3XP
9702  msg.WriteLong( inventory.weapons );
9703 #else
9704  msg.WriteShort( inventory.weapons );
9705 #endif
9706  msg.WriteByte( inventory.armor );
9707 
9708  for( i = 0; i < AMMO_NUMTYPES; i++ ) {
9710  }
9711  for( i = 0; i < MAX_WEAPONS; i++ ) {
9713  }
9714 }
9715 
9716 /*
9717 ================
9718 idPlayer::ReadPlayerStateFromSnapshot
9719 ================
9720 */
9722  int i, ammo;
9723 
9724  bobCycle = msg.ReadByte();
9725  stepUpTime = msg.ReadLong();
9726  stepUpDelta = msg.ReadFloat();
9727 #ifdef _D3XP
9728  inventory.weapons = msg.ReadLong();
9729 #else
9730  inventory.weapons = msg.ReadShort();
9731 #endif
9732  inventory.armor = msg.ReadByte();
9733 
9734  for( i = 0; i < AMMO_NUMTYPES; i++ ) {
9735  ammo = msg.ReadBits( ASYNC_PLAYER_INV_AMMO_BITS );
9737  inventory.ammo[ i ] = ammo;
9738  }
9739  }
9740  for( i = 0; i < MAX_WEAPONS; i++ ) {
9742  }
9743 }
9744 
9745 /*
9746 ================
9747 idPlayer::ServerReceiveEvent
9748 ================
9749 */
9750 bool idPlayer::ServerReceiveEvent( int event, int time, const idBitMsg &msg ) {
9751 
9752  if ( idEntity::ServerReceiveEvent( event, time, msg ) ) {
9753  return true;
9754  }
9755 
9756  // client->server events
9757  switch( event ) {
9758  case EVENT_IMPULSE: {
9759  PerformImpulse( msg.ReadBits( 6 ) );
9760  return true;
9761  }
9762  default: {
9763  return false;
9764  }
9765  }
9766 }
9767 
9768 /*
9769 ================
9770 idPlayer::ClientReceiveEvent
9771 ================
9772 */
9773 bool idPlayer::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
9774  int powerup;
9775  bool start;
9776 
9777  switch ( event ) {
9778  case EVENT_EXIT_TELEPORTER:
9780  return true;
9783  return true;
9784  case EVENT_POWERUP: {
9785  powerup = msg.ReadShort();
9786  start = msg.ReadBits( 1 ) != 0;
9787  if ( start ) {
9788  GivePowerUp( powerup, 0 );
9789  } else {
9790  ClearPowerup( powerup );
9791  }
9792  return true;
9793  }
9794 #ifdef _D3XP
9795  case EVENT_PICKUPNAME: {
9796  char buf[MAX_EVENT_PARAM_SIZE];
9797  msg.ReadString(buf, MAX_EVENT_PARAM_SIZE);
9798  inventory.AddPickupName(buf, "", this); //_D3XP
9799  return true;
9800  }
9801 #endif
9802  case EVENT_SPECTATE: {
9803  bool spectate = ( msg.ReadBits( 1 ) != 0 );
9804  Spectate( spectate );
9805  return true;
9806  }
9807  case EVENT_ADD_DAMAGE_EFFECT: {
9808  if ( spectating ) {
9809  // if we're spectating, ignore
9810  // happens if the event and the spectate change are written on the server during the same frame (fraglimit)
9811  return true;
9812  }
9813  return idActor::ClientReceiveEvent( event, time, msg );
9814  }
9815  default: {
9816  return idActor::ClientReceiveEvent( event, time, msg );
9817  }
9818  }
9819  return false;
9820 }
9821 
9822 /*
9823 ================
9824 idPlayer::Hide
9825 ================
9826 */
9827 void idPlayer::Hide( void ) {
9828  idWeapon *weap;
9829 
9830  idActor::Hide();
9831  weap = weapon.GetEntity();
9832  if ( weap ) {
9833  weap->HideWorldModel();
9834  }
9835 }
9836 
9837 /*
9838 ================
9839 idPlayer::Show
9840 ================
9841 */
9842 void idPlayer::Show( void ) {
9843  idWeapon *weap;
9844 
9845  idActor::Show();
9846  weap = weapon.GetEntity();
9847  if ( weap ) {
9848  weap->ShowWorldModel();
9849  }
9850 }
9851 
9852 /*
9853 ===============
9854 idPlayer::StartAudioLog
9855 ===============
9856 */
9857 void idPlayer::StartAudioLog( void ) {
9858  if ( hud ) {
9859  hud->HandleNamedEvent( "audioLogUp" );
9860  }
9861 }
9862 
9863 /*
9864 ===============
9865 idPlayer::StopAudioLog
9866 ===============
9867 */
9868 void idPlayer::StopAudioLog( void ) {
9869  if ( hud ) {
9870  hud->HandleNamedEvent( "audioLogDown" );
9871  }
9872 }
9873 
9874 /*
9875 ===============
9876 idPlayer::ShowTip
9877 ===============
9878 */
9879 void idPlayer::ShowTip( const char *title, const char *tip, bool autoHide ) {
9880  if ( tipUp ) {
9881  return;
9882  }
9883  hud->SetStateString( "tip", tip );
9884  hud->SetStateString( "tiptitle", title );
9885  hud->HandleNamedEvent( "tipWindowUp" );
9886  if ( autoHide ) {
9887  PostEventSec( &EV_Player_HideTip, 5.0f );
9888  }
9889  tipUp = true;
9890 }
9891 
9892 /*
9893 ===============
9894 idPlayer::HideTip
9895 ===============
9896 */
9897 void idPlayer::HideTip( void ) {
9898  hud->HandleNamedEvent( "tipWindowDown" );
9899  tipUp = false;
9900 }
9901 
9902 /*
9903 ===============
9904 idPlayer::Event_HideTip
9905 ===============
9906 */
9907 void idPlayer::Event_HideTip( void ) {
9908  HideTip();
9909 }
9910 
9911 /*
9912 ===============
9913 idPlayer::ShowObjective
9914 ===============
9915 */
9916 void idPlayer::ShowObjective( const char *obj ) {
9917  hud->HandleNamedEvent( obj );
9918  objectiveUp = true;
9919 }
9920 
9921 /*
9922 ===============
9923 idPlayer::HideObjective
9924 ===============
9925 */
9926 void idPlayer::HideObjective( void ) {
9927  hud->HandleNamedEvent( "closeObjective" );
9928  objectiveUp = false;
9929 }
9930 
9931 /*
9932 ===============
9933 idPlayer::Event_StopAudioLog
9934 ===============
9935 */
9936 void idPlayer::Event_StopAudioLog( void ) {
9937  StopAudioLog();
9938 }
9939 
9940 /*
9941 ===============
9942 idPlayer::SetSpectateOrigin
9943 ===============
9944 */
9945 void idPlayer::SetSpectateOrigin( void ) {
9946  idVec3 neworig;
9947 
9948  neworig = GetPhysics()->GetOrigin();
9949  neworig[ 2 ] += EyeHeight();
9950  neworig[ 2 ] += 25;
9951  SetOrigin( neworig );
9952 }
9953 
9954 /*
9955 ===============
9956 idPlayer::RemoveWeapon
9957 ===============
9958 */
9959 void idPlayer::RemoveWeapon( const char *weap ) {
9960  if ( weap && *weap ) {
9961  inventory.Drop( spawnArgs, spawnArgs.GetString( weap ), -1 );
9962  }
9963 }
9964 
9965 /*
9966 ===============
9967 idPlayer::CanShowWeaponViewmodel
9968 ===============
9969 */
9970 bool idPlayer::CanShowWeaponViewmodel( void ) const {
9971  return showWeaponViewModel;
9972 }
9973 
9974 /*
9975 ===============
9976 idPlayer::SetLevelTrigger
9977 ===============
9978 */
9979 void idPlayer::SetLevelTrigger( const char *levelName, const char *triggerName ) {
9980  if ( levelName && *levelName && triggerName && *triggerName ) {
9981  idLevelTriggerInfo lti;
9982  lti.levelName = levelName;
9983  lti.triggerName = triggerName;
9985  }
9986 }
9987 
9988 /*
9989 ===============
9990 idPlayer::Event_LevelTrigger
9991 ===============
9992 */
9993 void idPlayer::Event_LevelTrigger( void ) {
9994  idStr mapName = gameLocal.GetMapName();
9995  mapName.StripPath();
9996  mapName.StripFileExtension();
9997  for ( int i = inventory.levelTriggers.Num() - 1; i >= 0; i-- ) {
9998  if ( idStr::Icmp( mapName, inventory.levelTriggers[i].levelName) == 0 ){
9999  idEntity *ent = gameLocal.FindEntity( inventory.levelTriggers[i].triggerName );
10000  if ( ent ) {
10001  ent->PostEventMS( &EV_Activate, 1, this );
10002  }
10003  }
10004  }
10005 }
10006 
10007 /*
10008 ===============
10009 idPlayer::Event_Gibbed
10010 ===============
10011 */
10012 void idPlayer::Event_Gibbed( void ) {
10013  // do nothing
10014 }
10015 
10016 /*
10017 ===============
10018 idPlayer::UpdatePlayerIcons
10019 ===============
10020 */
10021 void idPlayer::UpdatePlayerIcons( void ) {
10022  int time = networkSystem->ServerGetClientTimeSinceLastPacket( entityNumber );
10023  if ( time > cvarSystem->GetCVarInteger( "net_clientMaxPrediction" ) ) {
10024  isLagged = true;
10025  } else {
10026  isLagged = false;
10027  }
10028  // TODO: chatting, PDA, etc?
10029 }
10030 
10031 /*
10032 ===============
10033 idPlayer::DrawPlayerIcons
10034 ===============
10035 */
10036 void idPlayer::DrawPlayerIcons( void ) {
10037  if ( !NeedsIcon() ) {
10038  playerIcon.FreeIcon();
10039  return;
10040  }
10041 
10042 #ifdef CTF
10043  // Never draw icons for hidden players.
10044  if ( this->IsHidden() )
10045  return;
10046 #endif
10047 
10048  playerIcon.Draw( this, headJoint );
10049 }
10050 
10051 /*
10052 ===============
10053 idPlayer::HidePlayerIcons
10054 ===============
10055 */
10056 void idPlayer::HidePlayerIcons( void ) {
10057  playerIcon.FreeIcon();
10058 }
10059 
10060 /*
10061 ===============
10062 idPlayer::NeedsIcon
10063 ==============
10064 */
10065 bool idPlayer::NeedsIcon( void ) {
10066  // local clients don't render their own icons... they're only info for other clients
10067 #ifdef CTF
10068  // always draw icons in CTF games
10069  return entityNumber != gameLocal.localClientNum && ( ( g_CTFArrows.GetBool() && gameLocal.mpGame.IsGametypeFlagBased() && !IsHidden() && !AI_DEAD ) || ( isLagged || isChatting ) );
10070 #else
10071  return entityNumber != gameLocal.localClientNum && ( isLagged || isChatting );
10072 #endif
10073 }
10074 
10075 #ifdef CTF
10076 /*
10077 ===============
10078 idPlayer::DropFlag()
10079 ==============
10080 */
10081 void idPlayer::DropFlag( void ) {
10082  if ( !carryingFlag || !gameLocal.isMultiplayer || !gameLocal.mpGame.IsGametypeFlagBased() ) /* CTF */
10083  return;
10084 
10085  idEntity * entity = gameLocal.mpGame.GetTeamFlag( 1 - this->latchedTeam );
10086  if ( entity ) {
10087  idItemTeam * item = static_cast<idItemTeam*>(entity);
10088 
10089  if ( item->carried && !item->dropped ) {
10090  item->Drop( health <= 0 );
10091  carryingFlag = false;
10092  }
10093  }
10094 
10095 }
10096 
10097 void idPlayer::ReturnFlag() {
10098 
10099  if ( !carryingFlag || !gameLocal.isMultiplayer || !gameLocal.mpGame.IsGametypeFlagBased() ) /* CTF */
10100  return;
10101 
10102  idEntity * entity = gameLocal.mpGame.GetTeamFlag( 1 - this->latchedTeam );
10103  if ( entity ) {
10104  idItemTeam * item = static_cast<idItemTeam*>(entity);
10105 
10106  if ( item->carried && !item->dropped ) {
10107  item->Return();
10108  carryingFlag = false;
10109  }
10110  }
10111 }
10112 
10113 void idPlayer::FreeModelDef( void ) {
10116  playerIcon.FreeIcon();
10117 }
10118 
10119 #endif
virtual const idVec3 & GetOrigin(int id=0) const =0
void Spectate(bool spectate)
bool GuiActive(void)
Definition: Player.h:522
const idEventDef EV_ActivateTargets("activateTargets","e")
jointHandle_t
Definition: Model.h:156
const int MAX_WEAPONS
Definition: Player.h:58
void FreeSoundEmitter(bool immediate)
Definition: Entity.cpp:1787
idCVar pm_thirdPersonDeath("pm_thirdPersonDeath","0", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_BOOL,"enables third person view when player dies")
idScriptBool AI_TURN_LEFT
Definition: Player.h:286
idPhysics_Player physicsObj
Definition: Player.h:614
void TeleportDeath(int killer)
int focusTime
Definition: Player.h:680
void WriteShort(int c)
Definition: BitMsg.h:546
int ClipModelsTouchingBounds(const idBounds &bounds, int contentMask, idClipModel **clipModelList, int maxCount) const
Definition: Clip.cpp:804
idCVar g_gun_x("g_gunX","0", CVAR_GAME|CVAR_FLOAT,"")
const idVec3 & GetGravity(void) const
void Event_Gibbed(void)
idStrList pdaSecurity
Definition: Player.h:170
idEntity * GetEntity(void) const
Definition: Clip.h:178
bool TouchTriggers(void) const
Definition: Entity.cpp:3696
int vacuumAreaNum
Definition: Game_local.h:322
void AddAIKill(void)
int weapons
Definition: Player.h:140
virtual void SetSecurity(const char *sec) const
Definition: DeclPDA.cpp:256
bool noclip
Definition: Player.h:253
void HideTip(void)
renderEntity_t renderEntity
Definition: Entity.h:371
void BeginWriting(void)
Definition: BitMsg.h:265
bool TracePoint(trace_t &results, const idVec3 &start, const idVec3 &end, int contentMask, const idEntity *passEntity)
Definition: Clip.h:333
void SetClipModel(idClipModel *model, float density, int id=0, bool freeOld=true)
const char * GetPost() const
Definition: DeclPDA.h:148
idInterpolate< float > centerView
Definition: Player.h:657
idCVar pm_jumpheight("pm_jumpheight","48", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"approximate hieght the player can jump")
const int IMPULSE_19
Definition: UsercmdGen.h:73
float GetFloat(const char *key, const char *defaultString="0") const
Definition: Dict.h:248
const idEventDef EV_Player_GetPreviousWeapon("getPreviousWeapon", NULL, 's')
bool IsGametypeTeamBased(void)
bool GetJointTransform(jointHandle_t jointHandle, int currenttime, idVec3 &offset, idMat3 &axis)
int teleportKiller
Definition: Player.h:357
static const int NUM_LOGGED_ACCELS
Definition: Player.h:671
GLsizei const GLfloat * value
Definition: glext.h:3614
int ReadShort(void) const
Definition: BitMsg.h:613
const int LOWHEALTH_HEARTRATE_ADJ
Definition: Player.h:62
idCVar pm_usecylinder("pm_usecylinder","0", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_BOOL,"use a cylinder approximation instead of a bounding box for player collision detection")
short mx
Definition: UsercmdGen.h:99
void Clear()
Definition: GameEdit.cpp:140
void WriteString(const char *string)
Definition: SaveGame.cpp:231
float Normalize(void)
Definition: Vector.h:646
virtual void UpdatePlayerIcons(void)
int numProjectilesFired
Definition: Player.h:645
virtual void Hide(void)
idStr baseSkinName
Definition: Player.h:643
int GetInt(const char *key, const char *defaultString="0") const
Definition: Dict.h:252
void WeaponFireFeedback(const idDict *weaponDef)
void Clear(void)
Definition: Player.cpp:155
bool PostEventSec(const idEventDef *ev, float time)
Definition: Class.cpp:747
void WriteBindToSnapshot(idBitMsgDelta &msg) const
Definition: Entity.cpp:4756
idCVar g_fov("g_fov","90", CVAR_GAME|CVAR_INTEGER|CVAR_NOCHEAT,"")
const char * GetFrom() const
Definition: DeclPDA.h:52
bool SkipCinematic(void)
virtual void SetEnviroSuit(bool active)=0
bool weaponEnabled
Definition: Player.h:638
assert(prefInfo.fullscreenBtn)
const char * GetPdaName() const
Definition: DeclPDA.h:144
void SetOwner(idPlayer *owner)
Definition: Weapon.cpp:223
idScriptBool AI_ONLADDER
Definition: Player.h:278
void Restore(idRestoreGame *savefile)
void CacheWeapons(void)
virtual const idSoundShader * FindSound(const char *name, bool makeDefault=true)=0
bool useInitialSpawns
Definition: Player.h:346
virtual guiPoint_t GuiTrace(qhandle_t entityHandle, const idVec3 start, const idVec3 end) const =0
virtual void StateChanged(int time, bool redraw=false)=0
const idDict * FindEntityDefDict(const char *name, bool makeDefault=true) const
void ClearPowerUps(void)
Definition: Player.cpp:245
int nextHealthTake
Definition: Player.h:321
virtual const idVec3 & GetGravityNormal(void) const =0
void Restore(idRestoreGame *savefile)
Definition: Game_local.h:661
idCVar pm_deadviewheight("pm_deadviewheight","10", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"height of player's view while dead")
virtual idThread * ConstructScriptObject(void)
Definition: Actor.cpp:1290
void Present(void)
Definition: Light.cpp:737
int Cmp(const char *text) const
Definition: Str.h:652
idCVarSystem * cvarSystem
Definition: CVarSystem.cpp:487
void Weapon_Combat(void)
void LowerWeapon(void)
void SetInfluenceLevel(int level)
int selAudio
Definition: Player.h:165
void ClearFocus(void)
virtual const int GetNumVideos() const
Definition: DeclPDA.cpp:265
void TalkTo(idActor *actor)
Definition: AI.cpp:3672
bool IsActiveAF(void) const
Definition: AFEntity.h:168
idMat3 mat3_identity(idVec3(1, 0, 0), idVec3(0, 1, 0), idVec3(0, 0, 1))
const int MAX_GLOBAL_SHADER_PARMS
Definition: RenderWorld.h:44
int lastMPAim
Definition: Player.h:720
idLinkList< idActor > enemyNode
Definition: Actor.h:119
idNetworkSystem * networkSystem
idCVar g_damageScale("g_damageScale","1", CVAR_GAME|CVAR_FLOAT|CVAR_ARCHIVE,"scale final damage on player by this factor")
void Event_GetMove(void)
bool forceRespawn
Definition: Player.h:339
void ReadMaterial(const idMaterial *&material)
Definition: SaveGame.cpp:1132
void SpectateCycle(void)
void WriteObject(const idClass *obj)
Definition: SaveGame.cpp:329
idVec3 GetCenter(void) const
Definition: Bounds.h:211
bool forceScoreBoard
Definition: Player.h:338
const int LADDER_RUNG_DISTANCE
Definition: Player.cpp:44
idVec3 gibsDir
Definition: Player.h:654
void SavePersistantInfo(void)
void Event_OpenPDA(void)
void ExitCinematic(void)
Definition: Weapon.cpp:2380
bool GetFloorPos(float max_dist, idVec3 &floorpos) const
Definition: Entity.cpp:2821
idClip clip
Definition: Game_local.h:296
void Spawn(void)
const char * GetWave() const
Definition: DeclPDA.h:107
idCVar pm_thirdPersonRange("pm_thirdPersonRange","80", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"camera distance from player in 3rd person")
idVec4 colorWhite
Definition: Lib.cpp:116
idCVar pm_runbob("pm_runbob","0.4", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"bob faster when running")
void Printf(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:699
const int RAGDOLL_DEATH_TIME
Definition: Player.cpp:126
idStr title
Definition: Player.h:82
int lastSpectateChange
Definition: Player.h:715
idCVar pm_bobroll("pm_bobroll","0.002", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"")
const int FOCUS_TIME
Definition: Player.h:52
idScriptBool AI_SOFTLANDING
Definition: Player.h:283
virtual void SetStateString(const char *varName, const char *value)=0
int GetDamageForLocation(int damage, int location)
Definition: Actor.cpp:2436
idCVar g_useDynamicProtection("g_useDynamicProtection","1", CVAR_GAME|CVAR_BOOL|CVAR_ARCHIVE,"scale damage and armor dynamically to keep the player alive more often")
struct idEntity::entityFlags_s fl
void FreeCurrentPVS(pvsHandle_t handle) const
Definition: Pvs.cpp:1127
virtual void virtual void virtual const idLangDict * GetLanguageDict(void)=0
loggedAccel_t loggedAccel[NUM_LOGGED_ACCELS]
Definition: Player.h:672
const char * GetPreview() const
Definition: DeclPDA.h:109
Definition: Player.h:110
idScriptBool AI_ATTACK_HELD
Definition: Player.h:273
#define MAX_GENTITIES
Definition: Game_local.h:83
virtual int GetModelDefHandle(void)
Definition: Entity.cpp:1515
type * GetEntity(void) const
Definition: Game_local.h:695
int oldFlags
Definition: Player.h:263
const int MAX_EVENT_PARAM_SIZE
Definition: Game_local.h:132
idCVar pm_runroll("pm_runroll","0.005", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"")
bool NeedsIcon(void)
void ClearPowerup(int i)
waterLevel_t GetWaterLevel(void) const
const int HEALTHPULSE_TIME
Definition: Player.cpp:58
idCVar pm_crouchspeed("pm_crouchspeed","80", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"speed the player can move while crouched")
void SetAASLocation(void)
float GetFloat(void) const
Definition: CVarSystem.h:144
float stepUpDelta
Definition: Player.h:624
bool GiveItem(idItem *item)
const idStr & GetKey(void) const
Definition: Dict.h:52
virtual void ClientPredictionThink(void)
const int GetNumStages(void) const
Definition: Material.h:365
void SetPlayerEntity(class idPlayer *playerEnt)
Definition: PlayerView.cpp:205
void SetNum(int newnum, bool resize=true)
Definition: List.h:289
void StartAudioLog(void)
void Translate(const idVec3 &translation)
Definition: Clip.h:139
void ReadDict(idDict *dict)
Definition: SaveGame.cpp:1107
void RaiseWeapon(void)
Definition: Weapon.cpp:1581
bool SetSyncedAnimWeight(int num, float weight)
const char * ToString(int precision=2) const
Definition: Angles.cpp:238
void SetMass(float mass, int id=-1)
void TogglePDA(void)
const idEventDef EV_Activate("activate","e")
static void CacheWeapon(const char *weaponName)
Definition: Weapon.cpp:250
bool lastManPlayAgain
Definition: Player.h:359
bool isNewFrame
Definition: Game_local.h:333
idEntity * GetBindMaster(void) const
Definition: Entity.cpp:2153
GLint location
Definition: glext.h:3631
void Event_GetCurrentWeapon(void)
const idEventDef EV_Player_DisableWeapon("disableWeapon")
bool godmode
Definition: Player.h:254
void StopRagdoll(void)
Definition: Actor.cpp:1708
void SwitchToTeam(int clientNum, int oldteam, int newteam)
const int LAND_RETURN_TIME
Definition: Player.h:51
const idEventDef EV_Player_EnableWeapon("enableWeapon")
const int HEALTH_PER_DOSE
Definition: Player.cpp:47
void WriteSkin(const idDeclSkin *skin)
Definition: SaveGame.cpp:393
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:4804
idMat3 Transpose(void) const
Definition: Matrix.h:677
const int DEATH_VOLUME
Definition: Player.h:69
void SetSpectateOrigin(void)
idVec3 modelOffset
Definition: Actor.h:221
int Length(void) const
Definition: Str.h:702
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 skipCinematic
Definition: Game_local.h:314
const int IMPULSE_20
Definition: UsercmdGen.h:74
#define STRTABLE_ID
Definition: Common.h:56
bool IsType(const idTypeInfo &c) const
Definition: Class.h:337
void DropWeapon(bool died)
virtual void GetAIAimTargets(const idVec3 &lastSightPos, idVec3 &headPos, idVec3 &chestPos)
void SetCombatModel(void)
Definition: Actor.cpp:1581
idStr sessionCommand
Definition: Game_local.h:303
int heartRate
Definition: Player.h:308
bool pdaOpened
Definition: Player.h:166
const int IMPULSE_17
Definition: UsercmdGen.h:71
const int IMPULSE_28
Definition: UsercmdGen.h:82
int ClientRemapDecl(declType_t type, int index)
static const float PI
Definition: Math.h:205
idStr screenshot
Definition: Player.h:84
int LowAmmo(void) const
Definition: Weapon.cpp:2632
bool doingDeathSkin
Definition: Player.h:314
idCVar g_showHud("g_showHud","1", CVAR_GAME|CVAR_ARCHIVE|CVAR_BOOL,"")
virtual int GetCVarInteger(const char *name) const =0
const int BASE_HEARTRATE
Definition: Player.h:64
idInventory inventory
Definition: Player.h:290
void SetAngles(const idAngles &ang)
Definition: Entity.cpp:2812
idEntity * FindEntity(const char *name) const
#define CM_BOX_EPSILON
const int SCREEN_HEIGHT
Definition: RenderSystem.h:154
float oldViewYaw
Definition: Player.h:628
int lastSavingThrowTime
Definition: Player.h:267
bool IsLinked(void)
Definition: Weapon.h:415
const idEventDef EV_Player_SelectWeapon("selectWeapon","s")
float bobfracsin
Definition: Player.h:620
idLinkList< idActor > enemyList
Definition: Actor.h:120
idEntity * influenceEntity
Definition: Player.h:662
float z
Definition: Vector.h:320
bool UpdateSkin(void)
Definition: Weapon.cpp:1423
#define MASK_SOLID
Definition: Game_local.h:735
const idKeyValue * MatchPrefix(const char *prefix, const idKeyValue *lastMatch=NULL) const
Definition: Dict.cpp:523
idVec3 GetEyePosition(void) const
float influenceFov
Definition: Player.h:660
void AdjustBodyAngles(void)
case const int
Definition: Callbacks.cpp:52
void GetPersistantData(idDict &dict)
Definition: Player.cpp:258
bool ammoPulse
Definition: Player.h:174
bool ready
Definition: Player.h:712
int deathClearContentsTime
Definition: Player.h:313
void UpdateFocus(void)
virtual void DamageFeedback(idEntity *victim, idEntity *inflictor, int &damage)
Definition: Entity.cpp:3040
idAngles AngleOffset(void) const
Definition: PlayerView.cpp:435
float PowerUpModifier(int type)
static idVec3 colorBarTable[5]
Definition: Player.h:331
bool ProcessEvent(const idEventDef *ev)
Definition: Class.cpp:858
void DisableClip(void)
bool RespondsTo(const idEventDef &ev) const
Definition: Class.h:349
bool BalanceTDM(void)
void WriteBits(int value, int numBits)
Definition: BitMsg.cpp:648
const idEventDef EV_Player_ExitTeleporter("exitTeleporter")
void Strip(const char c)
Definition: Str.h:915
declType_t
Definition: DeclManager.h:65
void SetGranularity(int newgranularity)
Definition: List.h:305
jointHandle_t hipJoint
Definition: Player.h:610
idList< float > damageScale
Definition: Actor.h:230
void AddPickupName(const char *name, const char *icon, idPlayer *owner)
Definition: Player.cpp:776
idScriptBool AI_FORWARD
Definition: Player.h:269
void UpdatePDAInfo(bool updatePDASel)
static float ClampFloat(float min, float max, float value)
Definition: Math.h:893
float NormalizeFast(void)
Definition: Vector.h:180
static float AngleDelta(float angle1, float angle2)
Definition: Math.h:918
const idVec3 & GetPushedLinearVelocity(const int id=0) const
jointHandle_t GetJointHandle(const char *name) const
ammo_t AmmoIndexForAmmoClass(const char *ammo_classname) const
Definition: Player.cpp:707
bool leader
Definition: Player.h:714
void SetEyeHeight(float height)
Definition: Actor.cpp:1427
int suppressShadowInViewID
Definition: RenderWorld.h:105
void RemoveWeapon(const char *weap)
bool isClient
Definition: Game_local.h:327
unsigned int lastSnapshotSequence
Definition: Player.h:717
int GetBaseHeartRate(void)
const idEventDef EV_Player_GetWeaponEntity("getWeaponEntity", NULL, 'e')
const char * GetName(void) const
Definition: DeclManager.h:140
Definition: Vector.h:316
idInterpolate< float > heartInfo
Definition: Player.h:309
void ReadJoint(jointHandle_t &value)
Definition: SaveGame.cpp:931
case const float
Definition: Callbacks.cpp:62
void ReadBool(bool &value)
Definition: SaveGame.cpp:976
float legsYaw
Definition: Player.h:626
idAngles ang_zero(0.0f, 0.0f, 0.0f)
int nextItemPickup
Definition: Player.h:212
idScriptBool AI_RUN
Definition: Player.h:280
jointHandle_t headJoint
Definition: Player.h:612
const char * GetLocation(void) const
Definition: Misc.cpp:2147
bool isServer
Definition: Game_local.h:326
void Save(idSaveGame *savefile) const
Definition: PlayerView.cpp:91
void GivePDA(const char *pdaName, idDict *item)
const int IMPULSE_18
Definition: UsercmdGen.h:72
virtual ~idPlayer()
END_CLASS const int MAX_RESPAWN_TIME
Definition: Player.cpp:125
void WriteStaticObject(const idClass &obj)
Definition: SaveGame.cpp:348
static float Sqrt(float x)
Definition: Math.h:302
void SetInfluenceFov(float fov)
ID_INLINE T Square(T x)
Definition: Math.h:104
void Event_InPDA(void)
const char * GetFullName() const
Definition: DeclPDA.h:146
int onePickupTime
Definition: Player.h:214
virtual void HandleNamedEvent(const char *eventName)=0
int team
Definition: Actor.h:115
idCVar pm_walkspeed("pm_walkspeed","140", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"speed the player can move while walking")
idAngles & Normalize180(void)
Definition: Angles.cpp:70
idList< idLevelTriggerInfo > levelTriggers
Definition: Player.h:179
int blink_time
Definition: Actor.h:252
float idealLegsYaw
Definition: Player.h:625
virtual void SetLinearVelocity(const idVec3 &newLinearVelocity, int id=0)=0
virtual void SetCVarString(const char *name, const char *value, int flags=0)=0
virtual bool ClientReceiveEvent(int event, int time, const idBitMsg &msg)
int GetNextClientNum(int current) const
idCVar g_healthTakeLimit("g_healthTakeLimit","25", CVAR_GAME|CVAR_INTEGER|CVAR_ARCHIVE,"how low can health get taken in nightmare mode")
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
signed char impulse
Definition: UsercmdGen.h:101
idEntityPtr< idProjectile > soulCubeProjectile
Definition: Player.h:325
Definition: Token.h:71
int ReadString(char *buffer, int bufferSize) const
Definition: BitMsg.cpp:424
static void ReturnVector(idVec3 const &vec)
void EnterCinematic(void)
Definition: Weapon.cpp:2350
int entityDefBits
Definition: Game_local.h:335
void SetInfluenceView(const char *mtr, const char *skinname, float radius, idEntity *ent)
idEntityPtr< idEntity > teleportEntity
Definition: Player.h:356
int GetNumContacts(void) const
void Event_SelectWeapon(const char *weaponName)
virtual void ResetTime(int time)
Definition: Cinematic.cpp:235
int deplete_armor
Definition: Player.h:155
bool UserInfoChanged(bool canModify)
void UpdateViewAngles(void)
virtual void SetStateInt(const char *varName, const int value)=0
virtual int PointReachableAreaNum(const idVec3 &origin, const idBounds &bounds, const int areaFlags) const =0
float GetStepUp(void) const
float GetDuration(void) const
Definition: Interpolate.h:56
virtual const idMaterial * FindMaterial(const char *name, bool makeDefault=true)=0
void WriteString(const char *s, int maxLength=-1, bool make7Bit=true)
Definition: BitMsg.cpp:174
void SetPlayerInput(const usercmd_t &cmd, const idAngles &newViewAngles)
void PrevWeapon(void)
virtual void LinkCombat(void)
Definition: Actor.cpp:1613
void BobCycle(const idVec3 &pushVelocity)
void WriteFloat(float f)
Definition: BitMsg.h:558
GLuint src
Definition: glext.h:5390
int WeaponIndexForAmmoClass(const idDict &spawnArgs, const char *ammo_classname) const
Definition: Player.cpp:735
GLenum GLsizei len
Definition: glext.h:3472
void Set(const char *key, const char *value)
Definition: Dict.cpp:275
void OffsetThirdPersonView(float angle, float range, float height, bool clip)
bool ShowCrosshair(void) const
Definition: Weapon.cpp:1745
int airTics
Definition: Player.h:649
bool cinematic
Definition: Entity.h:127
int nextItemNum
Definition: Player.h:213
int ReadBits(int numBits) const
Definition: BitMsg.cpp:709
const contactInfo_t & GetContact(int num) const
virtual void DrawPlayerIcons(void)
GLhandleARB obj
Definition: glext.h:3602
bool gibDeath
Definition: Player.h:652
bool forcedReady
Definition: Player.h:343
void CopyJointsFromBodyToHead(void)
Definition: Actor.cpp:748
const int DEAD_HEARTRATE
Definition: Player.h:61
static int ClampInt(int min, int max, int value)
Definition: Math.h:883
float x
Definition: Vector.h:318
void UpdateConditions(void)
#define SHORT2ANGLE(x)
Definition: Math.h:63
jointHandle_t chestJoint
Definition: Player.h:611
idDict spawnArgs
Definition: Entity.h:122
static const char * GetAmmoPickupNameForNum(ammo_t ammonum)
Definition: Weapon.cpp:2552
void WriteDir(const idVec3 &dir, int numBits)
Definition: BitMsg.h:575
int numProjectileHits
Definition: Player.h:646
int oldMouseY
Definition: Player.h:686
idCVar pm_spectatebbox("pm_spectatebbox","32", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"size of the spectator bounding box")
idUserInterfaceManager * uiManager
void UpdateObjectiveInfo(void)
bool IsReloading(void) const
Definition: Weapon.cpp:1727
idBounds boundingBoxes[MAX_AAS_BOUNDING_BOXES]
Definition: AASFile.h:215
void ReadUsercmd(usercmd_t &usercmd)
Definition: SaveGame.cpp:1429
virtual void DamageFeedback(idEntity *victim, idEntity *inflictor, int &damage)
bool fxFov
Definition: Player.h:658
idCVar g_viewNodalZ("g_viewNodalZ","0", CVAR_GAME|CVAR_FLOAT,"")
void RouteGuiMouse(idUserInterface *gui)
int i
Definition: process.py:33
bool HasJumped(void) const
idMat3 ShakeAxis(void) const
Definition: PlayerView.cpp:424
void Event_StopAudioLog(void)
int Cmpn(const char *text, int n) const
Definition: Str.h:657
GLintptr offset
Definition: glext.h:3113
void SetLastHitTime(int time)
idList< idObjectiveInfo > objectiveNames
Definition: Player.h:216
contactInfo_t c
idScriptBool AI_TELEPORT
Definition: Player.h:285
const idDeclSkin * powerUpSkin
Definition: Player.h:642
GLuint GLuint num
Definition: glext.h:5390
bool HandleESC(void)
void ToggleScoreboard(void)
void WriteVec3(const idVec3 &vec)
Definition: SaveGame.cpp:253
bool HasChanged(void) const
Definition: BitMsg.h:534
void SetDebugLevel(bool set)
idScriptBool AI_TURN_RIGHT
Definition: Player.h:287
idAngles & Zero(void)
Definition: Angles.h:126
virtual void ClearJointMods(void)
Definition: IK.cpp:779
idMultiplayerGame::gameState_t GetGameState(void) const
idCVar pm_runspeed("pm_runspeed","220", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"speed the player can move while running")
idCVar pm_minviewpitch("pm_minviewpitch","-89", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"amount player's view can look up (negative values are up)")
const idVec3 & GetOrigin(int id=0) const
static void SinCos(float a, float &s, float &c)
Definition: Math.h:390
idCVar pm_runpitch("pm_runpitch","0.002", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"")
void SetDeltaViewAngles(const idAngles &delta)
Definition: Actor.cpp:1821
void Copy(const idDict &other)
Definition: Dict.cpp:70
void SetAnimState(int channel, const char *name, int blendFrames)
Definition: Actor.cpp:1937
idCVar g_showEnemies("g_showEnemies","0", CVAR_GAME|CVAR_BOOL,"draws boxes around monsters that have targeted the the player")
idVec3 dir
Definition: Player.h:227
virtual const char * HandleEvent(const sysEvent_t *event, int time, bool *updateVisuals=NULL)=0
GLsizei range
Definition: glext.h:4368
int Icmp(const char *text) const
Definition: Str.h:667
const idVec2 & ToVec2(void) const
Definition: Vector.h:711
idSoundWorld * gameSoundWorld
Definition: Game_local.cpp:56
void PlayerDeath(idPlayer *dead, idPlayer *killer, bool telefrag)
virtual bool IsInteractive() const =0
bool Give(const char *statname, const char *value)
void WriteMaterial(const idMaterial *material)
Definition: SaveGame.cpp:380
int bobCycle
Definition: Player.h:621
const type & GetEndValue(void) const
Definition: Interpolate.h:58
#define EVENT(event, function)
Definition: Class.h:53
void RemoveInventoryItem(idDict *item)
virtual void SetStateBool(const char *varName, const bool value)=0
idMat3 viewAxis
Definition: Actor.h:117
void SetContents(int contents, int id=-1)
void Init(byte *data, int length)
Definition: BitMsg.h:155
float fraction
int lastSndHitTime
Definition: Player.h:266
const char * GetMapName(void) const
void SetJointAxis(jointHandle_t jointnum, jointModTransform_t transform_type, const idMat3 &mat)
idVec3 endpos
virtual void Show(void)
virtual const idDeclAudio * GetAudioByIndex(int index) const
Definition: DeclPDA.cpp:304
void WriteJoint(const jointHandle_t value)
Definition: SaveGame.cpp:177
const int IMPULSE_13
Definition: UsercmdGen.h:67
const int LAND_DEFLECT_TIME
Definition: Player.h:50
int MPAim
Definition: Player.h:719
idCVar g_armorProtectionMP("g_armorProtectionMP","0.6", CVAR_GAME|CVAR_FLOAT|CVAR_ARCHIVE,"armor takes this percentage of damage in mp")
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
idStrList videos
Definition: Player.h:171
const int BUTTON_ATTACK
Definition: UsercmdGen.h:44
idLocationEntity * LocationForPoint(const idVec3 &point)
idCVar g_skill("g_skill","1", CVAR_GAME|CVAR_INTEGER,"")
void UpdateWeapon(void)
virtual void FreeModelDef(void)
Definition: AFEntity.cpp:866
virtual bool ClientReceiveEvent(int event, int time, const idBitMsg &msg)
Definition: Entity.cpp:5477
const idEventDef EV_Player_LevelTrigger("levelTrigger")
virtual void HidePlayerIcons(void)
virtual void WriteToSnapshot(idBitMsgDelta &msg) const
idStr & StripPath(void)
Definition: Str.cpp:885
void CalculateViewWeaponPos(idVec3 &origin, idMat3 &axis)
void Flash(idVec4 color, int time)
Definition: PlayerView.cpp:604
idAnimator animator
Definition: Entity.h:534
const float MIN_BOB_SPEED
Definition: Player.cpp:61
#define STRTABLE_ID_LENGTH
Definition: Common.h:57
void WriteUsercmd(const usercmd_t &usercmd)
Definition: SaveGame.cpp:653
idCVar g_gun_z("g_gunZ","0", CVAR_GAME|CVAR_FLOAT,"")
bool IsHidden(void) const
Definition: Entity.cpp:1217
bool weaponCatchup
Definition: Player.h:718
int minRespawnTime
Definition: Player.h:365
virtual void SetStateFloat(const char *varName, const float value)=0
idEntity * SpawnEntityType(const idTypeInfo &classdef, const idDict *args=NULL, bool bIsClientReadSnapshot=false)
void Event_GetWeaponEntity(void)
void UpdatePowerUps(void)
void void void Warning(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:735
int Icmpn(const char *text, int n) const
Definition: Str.h:672
void SetCurrentHeartRate(void)
void DrawHUD(idUserInterface *hud)
idStr pdaVideo
Definition: Player.h:689
idCVar pm_airTics("pm_air","1800", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_INTEGER,"how long in milliseconds the player can go without air before he starts taking damage")
virtual bool GetPhysicsToSoundTransform(idVec3 &origin, idMat3 &axis)
virtual void Killed(idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location)
bool IsWorldModelReady(void)
Definition: Weapon.h:419
idStr levelName
Definition: Player.h:88
idAFEntity_Vehicle * focusVehicle
Definition: Player.h:681
pvsHandle_t SetupCurrentPVS(const idVec3 &source, const pvsType_t type=PVS_NORMAL) const
Definition: Pvs.cpp:948
idCVar pm_stepsize("pm_stepsize","16", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"maximum height the player can step up without jumping")
int lastDmgTime
Definition: Player.h:312
idAngles deltaViewAngles
Definition: Actor.h:223
virtual const idBounds & GetBounds(int id=-1) const =0
void StartFxOnBone(const char *fx, const char *bone)
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
Definition: AI.h:87
int MPAimFadeTime
Definition: Player.h:722
void GetPhysicsToVisualTransform(idVec3 &origin, idMat3 &axis) const
Definition: AF.cpp:404
int lastHeartBeat
Definition: Player.h:311
const int MAX_HEARTRATE
Definition: Player.h:66
void KillBox(idEntity *ent, bool catch_teleport=false)
class idPlayerView playerView
Definition: Player.h:251
void ClearAllJoints(void)
waterLevel_t
bool AddPoint(const idVec3 &v)
Definition: Bounds.h:226
bool hiddenWeapon
Definition: Player.h:324
idUserInterface * focusUI
Definition: Player.h:677
static ammo_t GetAmmoNumForName(const char *ammoname)
Definition: Weapon.cpp:2445
int ServerRemapDecl(int clientNum, declType_t type, int index)
Definition: Lexer.h:137
void Reload(void)
virtual void ReadFromSnapshot(const idBitMsgDelta &msg)
void GiveHealthPool(float amt)
bool GivePowerUp(int powerup, int time)
void CalcDamagePoints(idEntity *inflictor, idEntity *attacker, const idDict *damageDef, const float damageScale, const int location, int *health, int *armor)
idScriptBool AI_STRAFE_LEFT
Definition: Player.h:271
void SetSelf(idEntity *e)
const idMaterial * material
idCVar pm_normalheight("pm_normalheight","74", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"height of player's bounding box while standing")
void SetLinearVelocity(const idVec3 &newLinearVelocity, int id=0)
bool UseAmmo(ammo_t type, int amount)
void Event_HideTip(void)
GLuint GLuint GLsizei count
Definition: glext.h:2845
void NextBestWeapon(void)
void ShutdownThreads(void)
Definition: Actor.cpp:1257
int Index(void) const
Definition: DeclManager.h:165
bool IsInTeleport(void)
Definition: Player.h:819
idCVar pm_maxviewpitch("pm_maxviewpitch","89", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"amount player's view can look down")
void Rest(void)
Definition: AF.cpp:1053
void SetMaxStepHeight(const float newMaxStepHeight)
float deplete_rate
Definition: Player.h:156
Definition: Vector.h:52
idAAS * GetAAS(int num) const
void SetClipModelAxis(void)
const char * GetID() const
Definition: DeclPDA.h:149
void RemoveOriginOffset(bool remove)
idEntityPtr< idAFAttachment > head
Definition: Actor.h:233
int landChange
Definition: Player.h:631
void RaiseWeapon(void)
float CalcFov(bool honorZoom)
idCVar pm_modelView("pm_modelView","0", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_INTEGER,"draws camera from POV of player model (1 = always, 2 = when dead)", 0, 2, idCmdSystem::ArgCompletion_Integer< 0, 2 >)
idPhysics * GetPhysics(void) const
Definition: Entity.cpp:2607
void WriteLong(int c)
Definition: BitMsg.h:554
bool IsInGame(int clientNum)
void UpdateHudWeapon(bool flashWeapon=true)
void SetSoulCubeProjectile(idProjectile *projectile)
const float THIRD_PERSON_FOCUS_DISTANCE
Definition: Player.h:49
GLuint index
Definition: glext.h:3476
void SetSkin(const idDeclSkin *skin)
Definition: Entity.cpp:1178
idAngles viewBobAngles
Definition: Player.h:629
idCVar pm_thirdPersonClip("pm_thirdPersonClip","1", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_BOOL,"clip third person view into world space")
const GLubyte * c
Definition: glext.h:4677
virtual bool HandleSingleGuiCommand(idEntity *entityGui, idLexer *src)
const char * GetString(const char *key, const char *defaultString="") const
Definition: Dict.h:240
int snapshotSequence
Definition: Entity.h:118
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
void Restore(idRestoreGame *savefile)
Definition: Player.cpp:576
bool SpawnEntityDef(const idDict &args, idEntity **ent=NULL, bool setDefaults=true)
void ReadFloat(float &value)
Definition: SaveGame.cpp:967
void AddChatLine(const char *fmt,...) id_attribute((format(printf
float ToYaw(void) const
Definition: Vector.cpp:84
float Length(void) const
Definition: Vector.h:631
const int MAX_PDAS
Definition: Player.cpp:127
bool MPAimHighlight
Definition: Player.h:723
idCVar pm_bobup("pm_bobup","0.005", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"")
idUserInterface * ActiveGui(void)
idStr & StripFileExtension(void)
Definition: Str.cpp:757
idVec3 ToForward(void) const
Definition: Angles.cpp:117
void WriteDeltaFloat(float oldValue, float newValue)
Definition: BitMsg.h:595
idWorldspawn * world
Definition: Game_local.h:280
idStr icon
Definition: Player.h:78
virtual const idDeclVideo * GetVideoByIndex(int index) const
Definition: DeclPDA.cpp:292
idCVar net_clientSelfSmoothing("net_clientSelfSmoothing","0.6", CVAR_GAME|CVAR_FLOAT,"smooth self position if network causes prediction error.", 0.0f, 0.95f)
virtual bool Collide(const trace_t &collision, const idVec3 &velocity)
virtual void AddEmail(const char *name, bool unique=true) const
Definition: DeclPDA.cpp:220
bool OnLadder(void) const
const shaderStage_t * GetStage(const int index) const
Definition: Material.h:368
type & Alloc(void)
Definition: List.h:624
idSys * sys
Definition: maya_main.cpp:48
bool StartSound(const char *soundName, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length)
Definition: Entity.cpp:1622
void GiveVideo(const char *videoName, idDict *item)
static int FtoiFast(float f)
Definition: Math.h:801
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
void CastVote(int clientNum, bool vote)
const int UCF_IMPULSE_SEQUENCE
Definition: UsercmdGen.h:87
idSoundEmitter * referenceSound
Definition: Game.h:209
bool OnLadder(void) const
int lastDamageLocation
Definition: Player.h:697
const int IMPULSE_22
Definition: UsercmdGen.h:76
idCVar g_debugDamage("g_debugDamage","0", CVAR_GAME|CVAR_BOOL,"")
virtual renderEntity_t * GetRenderEntity(void)
Definition: Entity.cpp:1506
#define vec3_zero
Definition: Vector.h:390
void SetPhysics(idPhysics *phys)
Definition: Entity.cpp:2574
virtual bool GetPhysicsToSoundTransform(idVec3 &origin, idMat3 &axis)
Definition: Actor.cpp:1234
void Raise(void)
Definition: Weapon.cpp:1528
int lastAirDamage
Definition: Player.h:650
virtual void Damage(idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location)
int weaponSwitchTime
Definition: Player.h:637
GLuint GLuint end
Definition: glext.h:2845
void SetStartTime(float time)
Definition: Interpolate.h:46
idVec3 viewBob
Definition: Player.h:630
bool smoothedOriginUpdated
Definition: Player.h:699
int powerupEndTime[MAX_POWERUPS]
Definition: Player.h:146
const function_t * state
Definition: Actor.h:237
void WriteFloat(const float value)
Definition: SaveGame.cpp:213
bool IsDone(float time) const
Definition: Interpolate.h:52
const char * GetBody() const
Definition: DeclPDA.h:53
void StopAudioLog(void)
static float Fabs(float f)
Definition: Math.h:779
idCamera * GetCamera(void) const
idStr triggerName
Definition: Player.h:89
const idVec3 & GetGravityNormal(void) const
#define MAX_CLIENTS
Definition: Game_local.h:81
void Move(void)
idCommon * common
Definition: Common.cpp:206
int GetZoomFov(void)
Definition: Weapon.cpp:2408
int currentWeapon
Definition: Player.h:634
byte flags
Definition: UsercmdGen.h:102
idStr text
Definition: Player.h:83
void UpdateSkinSetup(bool restart)
bool HandleGuiCommands(idEntity *entityGui, const char *cmds)
Definition: Entity.cpp:3428
const char * AmmoPickupNameForIndex(ammo_t ammonum) const
Definition: Player.cpp:725
bool weaponPulse
Definition: Player.h:175
bool GetBool(const char *key, const char *defaultString="0") const
Definition: Dict.h:256
idCVar g_showviewpos("g_showviewpos","0", CVAR_GAME|CVAR_BOOL,"")
Definition: Dict.h:65
idVec3 firstPersonViewOrigin
Definition: Player.h:370
int bobFoot
Definition: Player.h:618
void ResetAmmoClip(void)
Definition: Weapon.cpp:2605
virtual const int GetNumAudios() const
Definition: DeclPDA.cpp:274
void CrashLand(const idVec3 &oldOrigin, const idVec3 &oldVelocity)
#define NULL
Definition: Lib.h:88
bool objectiveSystemOpen
Definition: Player.h:295
bool armorPulse
Definition: Player.h:176
int currentLoggedAccel
Definition: Player.h:673
int weapon_pda
Definition: Player.h:298
const int WEAPON_SWITCH_DELAY
Definition: Player.cpp:53
virtual const char * GetCVarString(const char *name) const =0
ammo_t GetAmmoType(void) const
Definition: Weapon.cpp:2614
const idVec3 & GetLinearVelocity(int id=0) const
int weapon_soulcube
Definition: Player.h:297
void CalculateRenderView(void)
idAnimBlend * CurrentAnim(int channelNum)
const int IMPULSE_0
Definition: UsercmdGen.h:54
idCVar pm_spectatespeed("pm_spectatespeed","450", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"speed the player can move while spectating")
idStr pdaAudio
Definition: Player.h:688
const idDeclSkin * customSkin
Definition: RenderWorld.h:125
const int IMPULSE_27
Definition: UsercmdGen.h:81
void Clear(void)
Definition: Dict.cpp:201
bool isTelefragged
Definition: Player.h:724
void DamageImpulse(idVec3 localKickDir, const idDict *damageDef)
Definition: PlayerView.cpp:252
idEntity * focusGUIent
Definition: Player.h:676
#define MASK_PLAYERSOLID
Definition: Game_local.h:737
int deplete_ammount
Definition: Player.h:157
virtual const idDecl * FindType(declType_t type, const char *name, bool makeDefault=true)=0
idScriptBool AI_RELOAD
Definition: Player.h:284
void FreeIcon(void)
Definition: PlayerIcon.cpp:127
const idMaterial * globalMaterial
Definition: RenderWorld.h:224
const int WEAPON_DROP_TIME
Definition: Player.cpp:50
float y
Definition: Vector.h:319
idAngles cmdAngles
Definition: Player.h:259
void SetInteger(const int value)
Definition: CVarSystem.h:148
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
void SetStartValue(const type &startValue)
Definition: Interpolate.h:48
renderView_t * GetRenderView(void)
float stamina
Definition: Player.h:316
virtual void SetCVarBool(const char *name, const bool value, int flags=0)=0
int AmmoAvailable(void) const
Definition: Weapon.cpp:2583
int GetInteger(void) const
Definition: CVarSystem.h:143
idUserInterface * cursor
Definition: Player.h:682
idVec3 GetVector(const char *key, const char *defaultString=NULL) const
Definition: Dict.h:260
idVec3 smoothedOrigin
Definition: Player.h:700
void Think(void)
idScriptBool AI_JUMP
Definition: Player.h:275
void Event_DisableWeapon(void)
int oldButtons
Definition: Player.h:262
const int IMPULSE_40
Definition: UsercmdGen.h:84
const int SHADERPARM_TIME_OF_DEATH
Definition: RenderWorld.h:54
bool IsReady(void) const
Definition: Weapon.cpp:1718
virtual void Redraw(int time)=0
idStr animPrefix
Definition: Actor.h:247
signed char upmove
Definition: UsercmdGen.h:97
void ServerSendEvent(int eventId, const idBitMsg *msg, bool saveEvent, int excludeClient) const
Definition: Entity.cpp:4897
float GetStartTime(void) const
Definition: Interpolate.h:54
void WriteShort(int c)
Definition: BitMsg.h:287
const int IMPULSE_14
Definition: UsercmdGen.h:68
int smoothedFrame
Definition: Player.h:698
float influenceRadius
Definition: Player.h:664
virtual void SetOrigin(const idVec3 &newOrigin, int id=-1)=0
const int DMG_VOLUME
Definition: Player.h:68
void CancelEvents(const idEventDef *ev)
Definition: Class.cpp:619
idCVar pm_normalviewheight("pm_normalviewheight","68", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"height of player's view while standing")
virtual void Teleport(const idVec3 &origin, const idAngles &angles, idEntity *destination)
idCVar g_viewNodalX("g_viewNodalX","0", CVAR_GAME|CVAR_FLOAT,"")
int lastTeleFX
Definition: Player.h:716
idCVar g_armorProtection("g_armorProtection","0.3", CVAR_GAME|CVAR_FLOAT|CVAR_ARCHIVE,"armor takes this percentage of damage")
const idDeclSkin * influenceSkin
Definition: Player.h:665
bool PowerUpActive(int powerup) const
int ReadLong(void) const
Definition: BitMsg.h:621
const idVec3 & GetGravity(void) const
idCVar pm_crouchbob("pm_crouchbob","0.5", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"bob much faster when crouched")
static int FindText(const char *str, const char *text, bool casesensitive=true, int start=0, int end=-1)
Definition: Str.cpp:207
void Weapon_NPC(void)
virtual bool GetPhysicsToVisualTransform(idVec3 &origin, idMat3 &axis)
GLint mode
Definition: glext.h:4165
const int GetSurfaceFlags(void) const
Definition: Material.h:500
void UpdateAir(void)
void GiveEmail(const char *emailName)
int nextHealthPulse
Definition: Player.h:318
usercmd_t usercmd
Definition: Player.h:249
#define CM_CLIP_EPSILON
const char * GetString(const char *str) const
Definition: LangDict.cpp:148
idCVar g_mpWeaponAngleScale("g_mpWeaponAngleScale","0", CVAR_GAME|CVAR_FLOAT,"Control the weapon sway in MP")
void SetupWeaponEntity(void)
idScriptBool AI_CROUCH
Definition: Player.h:276
bool CanShowWeaponViewmodel(void) const
Definition: Item.h:41
void ReadUserInterface(idUserInterface *&ui)
Definition: SaveGame.cpp:1244
float roll
Definition: Angles.h:55
float clientSmoothing
Definition: Game_local.h:334
const int FOCUS_GUI_TIME
Definition: Player.h:53
int GetNumPVSAreas(void)
Definition: Entity.cpp:1363
idVec3 GunAcceleratingOffset(void)
virtual const char * Activate(bool activate, int time)=0
static int Abs(int x)
Definition: Math.h:774
const idStr & GetValue(void) const
Definition: Dict.h:53
float shaderParms[MAX_GLOBAL_SHADER_PARMS]
Definition: RenderWorld.h:223
int lastMPAimTime
Definition: Player.h:721
float ReadDeltaFloat(float oldValue) const
Definition: BitMsg.h:664
void WriteByte(int c)
Definition: BitMsg.h:542
virtual const idMat3 & GetAxis(int id=0) const =0
void Event_LevelTrigger(void)
bool healthPulse
Definition: Player.h:319
void Insert(const char a, int index)
Definition: Str.h:779
void DeleteContents(bool clear)
Definition: List.h:207
idCVar g_debugMove("g_debugMove","0", CVAR_GAME|CVAR_BOOL,"")
void UpdateHudStats(idUserInterface *hud)
int pdasViewed[4]
Definition: Player.h:160
virtual idAnimator * GetAnimator(void)
Definition: Entity.cpp:5213
idCVar g_testDeath("g_testDeath","0", CVAR_GAME|CVAR_BOOL,"")
void RestoreInventory(idPlayer *owner, const idDict &dict)
Definition: Player.cpp:354
void LookAtKiller(idEntity *inflictor, idEntity *attacker)
idUserInterface * hud
Definition: Player.h:293
int clip[MAX_WEAPONS]
Definition: Player.h:145
const char * Right(int len, idStr &result) const
Definition: Str.h:896
int powerups
Definition: Player.h:141
int Find(const char c, int start=0, int end=-1) const
Definition: Str.h:874
int ammo_t
Definition: Weapon.h:53
idAI * focusCharacter
Definition: Player.h:678
virtual void ModifySound(const s_channelType channel, const soundShaderParms_t *parms)=0
void Update(idPlayer *player)
Definition: GameEdit.cpp:167
bool SelectEntity(const idVec3 &origin, const idVec3 &dir, const idEntity *skip)
Definition: GameEdit.cpp:423
const char * GetDate() const
Definition: DeclPDA.h:55
#define MASK_SHOT_RENDERMODEL
Definition: Game_local.h:741
int maxRespawnTime
Definition: Player.h:366
idLinkList< idEntity > spawnNode
Definition: Entity.h:114
void SpawnToPoint(const idVec3 &spawn_origin, const idAngles &spawn_angles)
int talkCursor
Definition: Player.h:679
gameState_t GameState(void) const
int lastSpectateTeleport
Definition: Player.h:341
float pitch
Definition: Angles.h:53
idStr & RemoveColors(void)
Definition: Str.h:849
const char * GetIcon() const
Definition: DeclPDA.h:147
const char * GetWave() const
Definition: DeclPDA.h:81
const idMaterial * influenceMaterial
Definition: Player.h:663
idGameLocal gameLocal
Definition: Game_local.cpp:64
void SetBool(const char *key, bool val)
Definition: Dict.h:196
bool RunPhysics(void)
Definition: Entity.cpp:2616
const idEventDef EV_Player_HideTip("hideTip")
const int SHADERPARM_TIMEOFFSET
Definition: RenderWorld.h:51
void Event_GetPreviousWeapon(void)
void UnreadToken(const idToken *token)
Definition: Lexer.cpp:1159
void SetViewAngles(const idAngles &angles)
int oldMouseX
Definition: Player.h:685
idList< idItemInfo > pickupItemNames
Definition: Player.h:215
void Init(const float startTime, const float duration, const type &startValue, const type &endValue)
Definition: Interpolate.h:87
void RestorePersistantInfo(void)
#define END_CLASS
Definition: Class.h:54
void PerformImpulse(int impulse)
void Reload(void)
Definition: Weapon.cpp:1552
const idKeyValue * FindKey(const char *key) const
Definition: Dict.cpp:451
idScriptBool AI_BACKWARD
Definition: Player.h:270
GLubyte GLubyte GLubyte a
Definition: glext.h:4662
idScriptBool AI_WEAPON_FIRED
Definition: Player.h:274
int lastArmorPulse
Definition: Player.h:315
void ClientSendEvent(int eventId, const idBitMsg *msg) const
Definition: Entity.cpp:4939
idCVar g_healthTakeAmt("g_healthTakeAmt","5", CVAR_GAME|CVAR_INTEGER|CVAR_ARCHIVE,"how much health to take in nightmare mode")
#define DEG2RAD(a)
Definition: Math.h:56
int LoadMemory(const char *ptr, int length, const char *name, int startLine=1)
Definition: Lexer.cpp:1646
virtual const idDict & State() const =0
const char * GetInfo() const
Definition: DeclPDA.h:83
bool showWeaponViewModel
Definition: Player.h:639
idBounds Expand(const float d) const
Definition: Bounds.h:317
idScriptBool AI_STRAFE_RIGHT
Definition: Player.h:272
static int BitsForInteger(int i)
Definition: Math.h:727
const idEventDef EV_Player_GetViewAngles("getViewAngles", NULL, 'v')
idLinkList< idEntity > spawnedEntities
Definition: Game_local.h:281
void ExitCinematic(void)
type GetCurrentValue(float time) const
Definition: Interpolate.h:102
bool GiveInventoryItem(idDict *item)
const idVec3 & PlayerGetOrigin(void) const
idAngles loggedViewAngles[NUM_LOGGED_VIEW_ANGLES]
Definition: Player.h:670
int lastHitTime
Definition: Player.h:265
void NetCatchup(void)
Definition: Weapon.cpp:2396
int ammo[AMMO_NUMTYPES]
Definition: Player.h:144
int stepUpTime
Definition: Player.h:623
bool inCinematic
Definition: Game_local.h:313
virtual const int GetNumEmails() const
Definition: DeclPDA.cpp:283
void SetClipModel(void)
GLenum GLsizei GLsizei height
Definition: glext.h:2856
const int IMPULSE_12
Definition: UsercmdGen.h:66
const char * ToString(int precision=2) const
Definition: Vector.cpp:221
idMat3 firstPersonViewAxis
Definition: Player.h:371
void WriteInt(const int value)
Definition: SaveGame.cpp:168
int numClients
Definition: Game_local.h:271
void SetCombatContents(bool enable)
Definition: AFEntity.cpp:823
idAngles spawnAngles
Definition: Player.h:257
idCVar g_healthTakeTime("g_healthTakeTime","5", CVAR_GAME|CVAR_INTEGER|CVAR_ARCHIVE,"how often to take health in nightmare mode")
void LinkScriptVariables(void)
void ProjectVector(const idVec3 &src, idVec3 &dst) const
Definition: Matrix.h:628
const int BUTTON_ZOOM
Definition: UsercmdGen.h:46
float EyeHeight(void) const
Definition: Actor.cpp:1436
void AdjustSpeed(void)
idStrList pdas
Definition: Player.h:169
idCVar pm_noclipspeed("pm_noclipspeed","200", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"speed the player can move while in noclip")
idDeclManager * declManager
int spawnedTime
Definition: Player.h:350
const idMaterial * GetGlobalMaterial()
const char * GetSecurity() const
Definition: DeclPDA.h:145
void WriteMat3(const idMat3 &mat)
Definition: SaveGame.cpp:309
#define SEC2MS(t)
Definition: Math.h:59
void Clear(void)
Definition: Weapon.cpp:677
void WritePlayerStateToSnapshot(idBitMsgDelta &msg) const
const idEventDef EV_Player_OpenPDA("openPDA")
idDragEntity dragEntity
Definition: Player.h:373
idCVar pm_bboxwidth("pm_bboxwidth","32", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"x/y size of player's bounding box")
GLubyte GLubyte b
Definition: glext.h:4662
void ReadMat3(idMat3 &mat)
Definition: SaveGame.cpp:1064
const int IMPULSE_15
Definition: UsercmdGen.h:69
idEntity * entities[MAX_GENTITIES]
Definition: Game_local.h:275
idDict userInfo[MAX_CLIENTS]
Definition: Game_local.h:272
const int ZEROSTAMINA_HEARTRATE
Definition: Player.h:65
void WriteDict(const idDict *dict)
Definition: SaveGame.cpp:357
bool IsLoaded(void) const
Definition: AF.h:65
virtual const idDeclEmail * GetEmailByIndex(int index) const
Definition: DeclPDA.cpp:316
void EnableAll(void)
Definition: IK.cpp:802
bool Give(idPlayer *owner, const idDict &spawnArgs, const char *statname, const char *value, int *idealWeapon, bool updateHud)
void UpdateDeltaViewAngles(const idAngles &angles)
void Event_GetViewAngles(void)
idPlayer * GetClientByNum(int current) const
bool isLagged
Definition: Player.h:361
void FireWeapon(void)
int colorBarIndex
Definition: Player.h:336
const type & GetStartValue(void) const
Definition: Interpolate.h:57
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
#define MASK_DEADSOLID
Definition: Game_local.h:738
void CalcFov(float base_fov, float &fov_x, float &fov_y) const
void UpdateHudAmmo(idUserInterface *hud)
idCVar pm_walkbob("pm_walkbob","0.3", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"bob slowly when walking")
const char * Icon(void) const
Definition: Weapon.cpp:1285
int localClientNum
Definition: Game_local.h:330
void LinkTo(idScriptObject &obj, const char *name)
int health
Definition: Entity.h:134
idVec3 vieworg
Definition: RenderWorld.h:215
bool respawning
Definition: Player.h:713
void UpdateGUI(void)
Definition: Weapon.cpp:1294
virtual sysEvent_t GenerateMouseButtonEvent(int button, bool down)=0
void ReadStaticObject(idClass &obj)
Definition: SaveGame.cpp:1098
void ClearEffects(void)
Definition: PlayerView.cpp:214
const int ZERO_VOLUME
Definition: Player.h:67
idScriptBool AI_DEAD
Definition: Player.h:279
void WeaponFireFeedback(const idDict *weaponDef)
Definition: PlayerView.cpp:384
idCVar pm_staminarate("pm_staminarate","0.75", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"rate that player regains stamina. divide pm_stamina by this value to determine how long it takes to fully recharge.")
bool spawnAnglesSet
Definition: Player.h:256
int Append(const type &obj)
Definition: List.h:646
LPCSTR GetString(LPCSTR psPrompt)
Definition: GetString.cpp:87
const idEventDef EV_Player_StopAudioLog("stopAudioLog")
void Fade(idVec4 color, int time)
Definition: PlayerView.cpp:617
idDict serverInfo
Definition: Game_local.h:270
void SetInt(const char *key, int val)
Definition: Dict.h:192
int SlotForWeapon(const char *weaponName)
const int MAX_INVENTORY_ITEMS
Definition: Player.cpp:130
Definition: Player.h:94
void GiveSecurity(const char *security)
float globalShaderParms[MAX_GLOBAL_SHADER_PARMS]
Definition: Game_local.h:289
bool TraceBounds(trace_t &results, const idVec3 &start, const idVec3 &end, const idBounds &bounds, int contentMask, const idEntity *passEntity)
Definition: Clip.h:338
renderView_t * renderView
Definition: Entity.h:129
void WeaponLoweringCallback(void)
const char * Mid(int start, int len, idStr &result) const
Definition: Str.cpp:603
Definition: Matrix.h:333
void SetLevelTrigger(const char *levelName, const char *triggerName)
idCVar pm_staminathreshold("pm_staminathreshold","45", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"when stamina drops below this value, player gradually slows to a walk")
static void ReturnString(const char *text)
float bobFrac
Definition: Player.h:619
const char * GetPreview() const
Definition: DeclPDA.h:84
const int SPECTATE_RAISE
Definition: Player.cpp:56
void UpdateAnimState(void)
Definition: Actor.cpp:2058
void WriteAngles(const idAngles &angles)
Definition: SaveGame.cpp:318
const int SCREEN_WIDTH
Definition: RenderSystem.h:153
idEntity * GetGroundEntity(void) const
void SetClipMask(int mask, int id=-1)
bool airless
Definition: Player.h:648
bool CanDrop(void) const
Definition: Weapon.cpp:1754
float yaw
Definition: Angles.h:54
int HasAmmo(ammo_t type, int amount)
int influenceActive
Definition: Player.h:661
void WeaponRisingCallback(void)
int AddUnique(const type &obj)
Definition: List.h:742
float xyspeed
Definition: Player.h:622
void UpdateVisuals(void)
Definition: Entity.cpp:1310
virtual void RemoveDecals(qhandle_t entityHandle)=0
void Event_StopFxFov(void)
bool GetBool(void) const
Definition: CVarSystem.h:142
virtual const idDecl * DeclByIndex(declType_t type, int index, bool forceParse=true)=0
int tourneyLine
Definition: Player.h:349
void SetGravity(const idVec3 &newGravity)
idList< idDict * > items
Definition: Player.h:168
virtual void RemoveAddedEmailsAndVideos() const
Definition: DeclPDA.cpp:236
idCVar g_dragEntity("g_dragEntity","0", CVAR_GAME|CVAR_BOOL,"allows dragging physics objects around by placing the crosshair over them and holding the fire button")
tuple f
Definition: idal.py:89
const idDeclPDA * GetPDA(void) const
void SetWaitState(const char *_waitstate)
Definition: Actor.cpp:2049
int weapon_fists
Definition: Player.h:299
int maxarmor
Definition: Player.h:143
idCVar net_clientPredictGUI("net_clientPredictGUI","1", CVAR_GAME|CVAR_BOOL,"test guis in networking without prediction")
textureStage_t texture
Definition: Material.h:210
idAngles GunTurningOffset(void)
int AddGuiPDAData(const declType_t dataType, const char *listName, const idDeclPDA *src, idUserInterface *gui)
idAngles viewAngles
Definition: Player.h:258
void Event_ExitTeleporter(void)
Definition: Actor.h:111
bool IsGametypeFlagBased(void)
idEditEntities * editEntities
Definition: Game_local.h:308
short angles[3]
Definition: UsercmdGen.h:98
int Num(void) const
Definition: List.h:265
#define AREA_REACHABLE_WALK
Definition: AASFile.h:74
void GetAttributes(idDict &attributes)
Definition: Item.cpp:331
bool RemoveIndex(int index)
Definition: List.h:849
idMat3 ToMat3(void) const
Definition: Angles.cpp:199
unsigned char byte
Definition: Lib.h:75
virtual bool Pain(idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location)
Definition: Actor.cpp:2292
virtual const idAASSettings * GetSettings(void) const =0
signed char forwardmove
Definition: UsercmdGen.h:95
bool IsCrouching(void) const
virtual const idBounds & GetAbsBounds(int id=-1) const =0
short my
Definition: UsercmdGen.h:100
void UpdateArmor(void)
void UpdateDeathSkin(bool state_hitch)
void ShowObjective(const char *obj)
int modelDefHandle
Definition: Entity.h:372
void GivePowerUp(idPlayer *player, int powerup, int msec)
Definition: Player.cpp:207
void StartFxFov(float duration)
void SetSpeed(const float newWalkSpeed, const float newCrouchSpeed)
void StealWeapon(idPlayer *player)
const GLcharARB * name
Definition: glext.h:3629
void NextWeapon(void)
#define RAD2DEG(a)
Definition: Math.h:57
void Restore(idRestoreGame *savefile)
Definition: PlayerView.cpp:148
GLsizeiptr size
Definition: glext.h:3112
void Signal(signalNum_t signalnum)
Definition: Entity.cpp:3352
bool lastHitToggle
Definition: Player.h:342
usercmd_t usercmds[MAX_CLIENTS]
Definition: Game_local.h:273
idScriptBool AI_PAIN
Definition: Player.h:281
void ReadPlayerStateFromSnapshot(const idBitMsgDelta &msg)
idCVar pm_thirdPerson("pm_thirdPerson","0", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_BOOL,"enables third person view")
static float AngleNormalize180(float angle)
Definition: Math.h:910
bool GetJointWorldTransform(jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis)
Definition: Entity.cpp:5248
idStr pdaVideoWave
Definition: Player.h:690
idStr name
Definition: Player.h:77
idDict * GetUserInfo(void)
idVec3 eyeOffset
Definition: Actor.h:220
idCVar pm_thirdPersonAngle("pm_thirdPersonAngle","0", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"direction of camera from player in 3rd person in degrees (0 = behind player, 180 = in front)")
const char * GetTitle() const
Definition: DeclPDA.h:150
int selPDA
Definition: Player.h:162
#define CLASS_DECLARATION(nameofsuperclass, nameofclass)
Definition: Class.h:110
bool lastManOver
Definition: Player.h:358
const char * GetSubject() const
Definition: DeclPDA.h:54
Definition: Str.h:116
void AdjustHeartRate(int target, float timeInSecs, float delay, bool force)
bool healthTake
Definition: Player.h:320
void SpectateFreeFly(bool force)
idList< aasLocation_t > aasLocation
Definition: Player.h:616
int ReadByte(void) const
Definition: BitMsg.h:609
const int BUTTON_MLOOK
Definition: UsercmdGen.h:48
idInterpolate< float > zoomFov
Definition: Player.h:656
const idEventDef EV_Player_GetButtons("getButtons", NULL, 'd')
const function_t * GetScriptFunction(const char *funcname)
Definition: Actor.cpp:1328
idDict * FindInventoryItem(const char *name)
virtual bool AreasAreConnected(int areaNum1, int areaNum2, portalConnection_t connection)=0
void AddProjectileHits(int count)
int GetFrameNum() const
Definition: Game_local.h:503
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
virtual void Show(void)
Definition: Actor.cpp:1050
int suppressSurfaceInViewID
Definition: RenderWorld.h:104
float DefaultFov(void) const
idVec3 lastDamageDir
Definition: Player.h:696
static void ReturnEntity(idEntity *ent)
class idUserInterface * gui[MAX_RENDERENTITY_GUI]
Definition: RenderWorld.h:130
int selEMail
Definition: Player.h:163
void BeginAttack(void)
Definition: Weapon.cpp:1679
float LengthFast(void) const
Definition: Vector.h:639
const char * c_str(void) const
Definition: Str.h:487
void SetEndValue(const type &endValue)
Definition: Interpolate.h:49
virtual void Restart(void)
int AmmoInClip(void) const
Definition: Weapon.cpp:2596
void ClearPushedVelocity(void)
void Event_GetButtons(void)
virtual void Hide(void)
Definition: Actor.cpp:1024
void ClearPowerUps(void)
int pain_delay
Definition: Actor.h:226
void ReadAngles(idAngles &angles)
Definition: SaveGame.cpp:1073
void RestorePhysics(idPhysics *phys)
Definition: Entity.cpp:2596
const idDeclVideo * GetVideo(int index)
const idEventDef EV_SpectatorTouch("spectatorTouch","et")
bool tipUp
Definition: Player.h:692
idCVar g_gun_y("g_gunY","0", CVAR_GAME|CVAR_FLOAT,"")
void BecomeActive(int flags)
Definition: Entity.cpp:995
static const char * GetAmmoNameForNum(ammo_t ammonum)
Definition: Weapon.cpp:2498
idCVar g_stopTime("g_stopTime","0", CVAR_GAME|CVAR_BOOL,"")
const idEventDef EV_Player_StopFxFov("stopFxFov")
idCVar g_editEntityMode("g_editEntityMode","0", CVAR_GAME|CVAR_INTEGER,"0 = off\n""1 = lights\n""2 = sounds\n""3 = articulated figures\n""4 = particle systems\n""5 = monsters\n""6 = entity names\n""7 = entity models", 0, 7, idCmdSystem::ArgCompletion_Integer< 0, 7 >)
void ServerSpectate(bool spectate)
void Weapon_GUI(void)
refSound_t refSound
Definition: Entity.h:373
void StopFiring(void)
idAngles ToAngles(void) const
Definition: Matrix.cpp:147
const int ANIMCHANNEL_TORSO
Definition: Anim.h:42
const idKeyValue * GetKeyVal(int index) const
Definition: Dict.h:294
int previousWeapon
Definition: Player.h:636
idScriptBool AI_HARDLANDING
Definition: Player.h:282
const idEventDef EV_Remove("<immediateremove>", NULL)
bool selfSmooth
Definition: Player.h:728
bool wantSpectate
Definition: Player.h:344
const char * GetVideoName() const
Definition: DeclPDA.h:82
const int ASYNC_PLAYER_INV_CLIP_BITS
Definition: Player.h:74
void HideObjective(void)
const int * GetPVSAreas(void)
Definition: Entity.cpp:1375
virtual void Present(void)
Definition: AFEntity.cpp:1065
float ReadFloat(void) const
Definition: BitMsg.h:625
#define MASK_SHOT_BOUNDINGBOX
Definition: Game_local.h:742
const idEventDef EV_Gibbed("<gibbed>")
idScriptBool AI_ONGROUND
Definition: Player.h:277
float healthPool
Definition: Player.h:317
const idEventDef EV_StartSoundShader("startSoundShader","sd", 'f')
void ReadFromSnapshot(const idBitMsgDelta &msg)
virtual sysEvent_t GenerateMouseMoveEvent(int deltax, int deltay)=0
int idealWeapon
Definition: Player.h:635
void Draw(idPlayer *player, jointHandle_t joint)
Definition: PlayerIcon.cpp:68
idDict persistentPlayerInfo[MAX_CLIENTS]
Definition: Game_local.h:274
idVec3 colorBar
Definition: Player.h:335
void SetMovementType(const pmtype_t type)
virtual const idDeclSkin * FindSkin(const char *name, bool makeDefault=true)=0
const idDeclSkin * skin
Definition: Player.h:641
void CheckBlink(void)
Definition: Actor.cpp:1197
bool HasGroundContacts(void) const
const int BUTTON_SCORES
Definition: UsercmdGen.h:47
const idMat3 & GetGravityAxis(void) const
void Save(idSaveGame *savefile) const
Definition: Player.cpp:472
const int ANIMCHANNEL_LEGS
Definition: Anim.h:43
const char * GetAudioName() const
Definition: DeclPDA.h:106
int MaxAmmoForAmmoClass(idPlayer *owner, const char *ammo_classname) const
Definition: Player.cpp:716
int lastGiveTime
Definition: Player.h:177
int ClipSize(void) const
Definition: Weapon.cpp:2623
void WriteToSnapshot(idBitMsgDelta &msg) const
int realClientTime
Definition: Game_local.h:332
GLint j
Definition: qgl.h:264
int pain_debounce_time
Definition: Actor.h:225
void Lerp(const idVec3 &v1, const idVec3 &v2, const float l)
Definition: Vector.cpp:232
idCVar pm_thirdPersonHeight("pm_thirdPersonHeight","0", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"height of camera from normal view height in 3rd person")
void PresentWeapon(bool showViewModel)
Definition: Weapon.cpp:2150
Definition: Light.h:44
virtual void DebugBounds(const idVec4 &color, const idBounds &bounds, const idVec3 &org=vec3_origin, const int lifetime=0)=0
void SetPrivateCameraView(idCamera *camView)
GLint level
Definition: glext.h:2878
void WeaponStolen(void)
Definition: Weapon.cpp:1770
void ClearPain(void)
Definition: Actor.cpp:2283
virtual void Restart(void)
Definition: Actor.cpp:783
void Drop(const idDict &spawnArgs, const char *weapon_classname, int weapon_index)
idCVar pm_bobpitch("pm_bobpitch","0.002", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"")
const int ASYNC_PLAYER_INV_AMMO_BITS
Definition: Player.h:73
const int IMPULSE_25
Definition: UsercmdGen.h:79
const idDeclEntityDef * FindEntityDef(const char *name, bool makeDefault=true) const
idRenderWorld * gameRenderWorld
Definition: Game_local.cpp:55
void GetViewPos(idVec3 &origin, idMat3 &axis) const
int ammoPredictTime
Definition: Player.h:153
virtual void GetAASLocation(idAAS *aas, idVec3 &pos, int &areaNum) const
int latchedTeam
Definition: Player.h:347
char * va(const char *fmt,...)
Definition: Str.cpp:1568
int lastHeartAdjust
Definition: Player.h:310
virtual int PointInArea(const idVec3 &point) const =0
idAngles smoothedAngles
Definition: Player.h:701
void ReadBindFromSnapshot(const idBitMsgDelta &msg)
Definition: Entity.cpp:4780
static idEntityFx * StartFx(const char *fx, const idVec3 *useOrigin, const idMat3 *useAxis, idEntity *ent, bool bind)
Definition: Fx.cpp:716
void PutAway(void)
Definition: Weapon.cpp:1539
void WriteBits(int value, int numBits)
Definition: BitMsg.cpp:110
int buttonMask
Definition: Player.h:261
void UpdateSpectating(void)
void SelectWeapon(int num, bool force)
const int STEPUP_TIME
Definition: Player.cpp:129
int lastDamageDef
Definition: Player.h:695
void SetOrigin(const idVec3 &org)
Definition: Entity.cpp:2784
bool PostEventMS(const idEventDef *ev, int time)
Definition: Class.cpp:666
virtual void DPrintf(const char *fmt,...) id_attribute((format(printf
#define max(x, y)
Definition: os.h:70
const char * GetInfo() const
Definition: DeclPDA.h:108
signed char rightmove
Definition: UsercmdGen.h:96
idStrList emails
Definition: Player.h:172
idMultiplayerGame mpGame
Definition: Game_local.h:305
int selVideo
Definition: Player.h:164
bool legsForward
Definition: Player.h:627
idUserInterface * objectiveSystem
Definition: Player.h:294
const idEventDef EV_Player_GetCurrentWeapon("getCurrentWeapon", NULL, 's')
virtual void Error(const char *fmt,...) id_attribute((format(printf
int entityNumber
Definition: Entity.h:111
idVec3 ReadDir(int numBits) const
Definition: BitMsg.h:644
void HideWorldModel(void)
Definition: Weapon.cpp:1629
GLfloat GLfloat p
Definition: glext.h:4674
virtual void SetModel(const char *modelname)
Definition: Entity.cpp:5222
idPlayerIcon playerIcon
Definition: Player.h:726
void CompleteObjective(const char *title)
void ShowTip(const char *title, const char *tip, bool autoHide)
idMat3 viewaxis
Definition: RenderWorld.h:216
idCVar pm_crouchrate("pm_crouchrate","0.87", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"time it takes for player's view to change from standing to crouching")
idStr name
Definition: Entity.h:121
int tourneyRank
Definition: Player.h:348
void Event_EnableWeapon(void)
void ClearFrags(int clientNum)
void Init(void)
idCVar g_balanceTDM("g_balanceTDM","1", CVAR_GAME|CVAR_BOOL,"maintain even teams")
int thinkFlags
Definition: Entity.h:125
void CalculateFirstPersonView(void)
virtual void GetViewParms(renderView_t *view)=0
void Kill(bool delayRespawn, bool nodamage)
int nextArmorDepleteTime
Definition: Player.h:158
virtual bool ServerReceiveEvent(int event, int time, const idBitMsg &msg)
Definition: Entity.cpp:4973
void ToVectors(idVec3 *forward, idVec3 *right=NULL, idVec3 *up=NULL) const
Definition: Angles.cpp:92
const int BUTTON_RUN
Definition: UsercmdGen.h:45
void CalculateShake(void)
Definition: PlayerView.cpp:404
void SpawnFromSpawnSpot(void)
const idEventDef EV_Touch("<touch>","et")
int landTime
Definition: Player.h:632
const int IMPULSE_29
Definition: UsercmdGen.h:83
void SetMaxJumpHeight(const float newMaxJumpHeight)
idVec4 colorBlack
Definition: Lib.cpp:115
void SetFloat(const float value)
Definition: CVarSystem.h:149
bool scoreBoardOpen
Definition: Player.h:337
void InitAASLocation(void)
bool IsActive(void) const
Definition: AF.h:74
void SetDuration(float duration)
Definition: Interpolate.h:47
int GetNumKeyVals(void) const
Definition: Dict.h:290
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
idCinematic * cinematic
Definition: Material.h:160
const char * GetRoq() const
Definition: DeclPDA.h:80
const int DYING_HEARTRATE
Definition: Player.h:63
float shaderParms[MAX_ENTITY_SHADER_PARMS]
Definition: RenderWorld.h:127
bool gibsLaunched
Definition: Player.h:653
void ReadString(idStr &string)
Definition: SaveGame.cpp:985
void GiveObjective(const char *title, const char *text, const char *screenshot)
void UpdateDamageEffects(void)
Definition: Entity.cpp:5438
void SetKnockBack(const int knockBackTime)
idIK_Walk walkIK
Definition: Actor.h:245
bool Execute(void)
bool spectating
Definition: Player.h:340
static void ReturnInt(int value)
idThread * scriptThread
Definition: Actor.h:257
int ReadToken(idToken *token)
Definition: Lexer.cpp:820
void EnterCinematic(void)
gameType_t gameType
Definition: Game_local.h:324
int ReadBits(int numBits) const
Definition: BitMsg.cpp:362
idCamera * privateCameraView
Definition: Player.h:667
const idEventDef EV_Player_GetMove("getMove", NULL, 'v')
idCVar g_knockback("g_knockback","1000", CVAR_GAME|CVAR_INTEGER,"")
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
idEntityPtr< idWeapon > weapon
Definition: Player.h:292
void ReadInt(int &value)
Definition: SaveGame.cpp:922
bool HasSteppedUp(void) const
idCVar g_showProjectilePct("g_showProjectilePct","0", CVAR_GAME|CVAR_ARCHIVE|CVAR_BOOL,"enables display of player hit percentage")
const idEventDef EV_Player_InPDA("inPDA", NULL, 'd')
idCVar pm_crouchviewheight("pm_crouchviewheight","32", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"height of player's view while crouched")
struct renderView_s renderView_t
Definition: DeclParticle.h:83
byte buttons
Definition: UsercmdGen.h:94
void PrepareForRestart(void)
virtual int ServerGetClientTimeSinceLastPacket(int clientNum)
int NumAAS(void) const
void ShowWorldModel(void)
Definition: Weapon.cpp:1640
void ActivateTargets(idEntity *activator) const
Definition: Entity.cpp:3650
bool lastManPresent
Definition: Player.h:360
bool SkipCinematic(void)
GLuint start
Definition: glext.h:2845
void Save(idSaveGame *savefile) const
bool Remove(const type &obj)
Definition: List.h:878
void StopSound(const s_channelType channel, bool broadcast)
Definition: Entity.cpp:1713
void UpdateHud(void)
Definition: AI.h:253
float LengthSqr(void) const
Definition: Vector.h:166
void UpdateScript(void)
Definition: Actor.cpp:1375
idEntity * SelectInitialSpawnPoint(idPlayer *player)
int maxHealth
Definition: Player.h:139
void SetState(const function_t *newState)
Definition: Actor.cpp:1344
bool StartRagdoll(void)
Definition: Actor.cpp:1651
void WriteUserInterface(const idUserInterface *ui, bool unique)
Definition: SaveGame.cpp:477
bool IsHolstered(void) const
Definition: Weapon.cpp:1736
void EvaluateControls(void)
#define MS2SEC(t)
Definition: Math.h:60
void ReadSkin(const idDeclSkin *&skin)
Definition: SaveGame.cpp:1148
bool turkeyScore
Definition: Player.h:167
void UpdateLocation(void)
#define S_COLOR_GRAY
Definition: Str.h:103
float volume
Definition: sound.h:63
void ReadObject(idClass *&obj)
Definition: SaveGame.cpp:1083
void LowerWeapon(void)
Definition: Weapon.cpp:1563
Definition: AAS.h:75
bool isChatting
Definition: Player.h:362
bool objectiveUp
Definition: Player.h:693
void EnableClip(void)
int ReadShort(void) const
Definition: BitMsg.h:367
int armor
Definition: Player.h:142
void SelectInitialSpawnPoint(idVec3 &origin, idAngles &angles)
ammo_t AmmoIndexForWeaponClass(const char *weapon_classname, int *ammoRequired)
Definition: Player.cpp:759
bool weaponGone
Definition: Player.h:345
GLdouble GLdouble t
Definition: glext.h:2943
const int MAX_PDA_ITEMS
Definition: Player.cpp:128
void Clear(void)
Definition: List.h:184
virtual bool ServerReceiveEvent(int event, int time, const idBitMsg &msg)
void UseVehicle(void)
static const int NUM_LOGGED_VIEW_ANGLES
Definition: Player.h:669
idCVar pm_stamina("pm_stamina","24", CVAR_GAME|CVAR_NETWORKSYNC|CVAR_FLOAT,"length of time player can run")
void AddProjectilesFired(int count)