doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Grabber.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 #include "../idlib/precompiled.h"
29 #pragma hdrstop
30 
31 #ifdef _D3XP
32 
33 #include "Game_local.h"
34 #include "Misc.h"
35 
36 #define MAX_DRAG_TRACE_DISTANCE 384.0f
37 #define TRACE_BOUNDS_SIZE 3.f
38 #define HOLD_DISTANCE 72.f
39 #define FIRING_DELAY 1000.0f
40 #define DRAG_FAIL_LEN 64.f
41 #define THROW_SCALE 1000
42 #define MAX_PICKUP_VELOCITY 1500 * 1500
43 #define MAX_PICKUP_SIZE 96
44 
45 /*
46 ===============================================================================
47 
48  Allows entities to be dragged through the world with physics.
49 
50 ===============================================================================
51 */
52 
53 CLASS_DECLARATION( idEntity, idGrabber )
55 
56 /*
57 ==============
58 idGrabber::idGrabber
59 ==============
60 */
61 idGrabber::idGrabber( void ) {
62  dragEnt = NULL;
63  owner = NULL;
64  beam = NULL;
65  beamTarget = NULL;
66  oldUcmdFlags = 0;
67  shakeForceFlip = false;
68  holdingAF = false;
69  endTime = 0;
70  lastFiredTime = -FIRING_DELAY;
71  dragFailTime = 0;
72  startDragTime = 0;
73  warpId = -1;
74  dragTraceDist = MAX_DRAG_TRACE_DISTANCE;
75 }
76 
77 /*
78 ==============
79 idGrabber::~idGrabber
80 ==============
81 */
82 idGrabber::~idGrabber( void ) {
83  StopDrag( true );
84  if ( beam ) {
85  delete beam;
86  }
87  if ( beamTarget ) {
88  delete beamTarget;
89  }
90 }
91 
92 /*
93 ==============
94 idGrabber::Save
95 ==============
96 */
97 void idGrabber::Save( idSaveGame *savefile ) const {
98 
99  dragEnt.Save( savefile );
100  savefile->WriteStaticObject( drag );
101 
102  savefile->WriteVec3( saveGravity );
103  savefile->WriteInt( id );
104 
105  savefile->WriteVec3( localPlayerPoint );
106 
107  owner.Save( savefile );
108 
109  savefile->WriteBool( holdingAF );
110  savefile->WriteBool( shakeForceFlip );
111 
112  savefile->WriteInt( endTime );
113  savefile->WriteInt( lastFiredTime );
114  savefile->WriteInt( dragFailTime );
115  savefile->WriteInt( startDragTime );
116  savefile->WriteFloat( dragTraceDist );
117  savefile->WriteInt( savedContents );
118  savefile->WriteInt( savedClipmask );
119 
120  savefile->WriteObject( beam );
121  savefile->WriteObject( beamTarget );
122 
123  savefile->WriteInt( warpId );
124 }
125 
126 /*
127 ==============
128 idGrabber::Restore
129 ==============
130 */
131 void idGrabber::Restore( idRestoreGame *savefile ) {
132  //Spawn the beams
133  Initialize();
134 
135  dragEnt.Restore( savefile );
136  savefile->ReadStaticObject( drag );
137 
138  savefile->ReadVec3( saveGravity );
139  savefile->ReadInt( id );
140 
141  // Restore the drag force's physics object
142  if ( dragEnt.IsValid() ) {
143  drag.SetPhysics( dragEnt.GetEntity()->GetPhysics(), id, dragEnt.GetEntity()->GetPhysics()->GetOrigin() );
144  }
145 
146  savefile->ReadVec3( localPlayerPoint );
147 
148  owner.Restore( savefile );
149 
150  savefile->ReadBool( holdingAF );
151  savefile->ReadBool( shakeForceFlip );
152 
153  savefile->ReadInt( endTime );
154  savefile->ReadInt( lastFiredTime );
155  savefile->ReadInt( dragFailTime );
156  savefile->ReadInt( startDragTime );
157  savefile->ReadFloat( dragTraceDist );
158  savefile->ReadInt( savedContents );
159  savefile->ReadInt( savedClipmask );
160 
161  savefile->ReadObject( reinterpret_cast<idClass *&>(beam) );
162  savefile->ReadObject( reinterpret_cast<idClass *&>(beamTarget) );
163 
164  savefile->ReadInt( warpId );
165 }
166 
167 /*
168 ==============
169 idGrabber::Initialize
170 ==============
171 */
172 void idGrabber::Initialize( void ) {
173  if ( !gameLocal.isMultiplayer ) {
174  idDict args;
175 
176  if ( !beamTarget ) {
177  args.SetVector( "origin", vec3_origin );
178  args.SetBool( "start_off", true );
179  beamTarget = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
180  }
181 
182  if ( !beam ) {
183  args.Clear();
184  args.Set( "target", beamTarget->name.c_str() );
185  args.SetVector( "origin", vec3_origin );
186  args.SetBool( "start_off", true );
187  args.Set( "width", "6" );
188  args.Set( "skin", "textures/smf/flareSizeable" );
189  args.Set( "_color", "0.0235 0.843 0.969 0.2" );
190  beam = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
191  beam->SetShaderParm( 6, 1.0f );
192  }
193 
194  endTime = 0;
195  dragTraceDist = MAX_DRAG_TRACE_DISTANCE;
196  }
197  else {
198  beam = NULL;
199  beamTarget = NULL;
200  endTime = 0;
201  dragTraceDist = MAX_DRAG_TRACE_DISTANCE;
202  };
203 }
204 
205 /*
206 ==============
207 idGrabber::SetDragDistance
208 ==============
209 */
210 void idGrabber::SetDragDistance( float dist ) {
211  dragTraceDist = dist;
212 }
213 
214 /*
215 ==============
216 idGrabber::StartDrag
217 ==============
218 */
219 void idGrabber::StartDrag( idEntity *grabEnt, int id ) {
220  int clipModelId = id;
221  idPlayer *thePlayer = owner.GetEntity();
222 
223  holdingAF = false;
224  dragFailTime = gameLocal.slow.time;
225  startDragTime = gameLocal.slow.time;
226 
227  oldUcmdFlags = thePlayer->usercmd.flags;
228 
229  // set grabbed state for networking
230  grabEnt->SetGrabbedState( true );
231 
232  // This is the new object to drag around
233  dragEnt = grabEnt;
234 
235  // Show the beams!
236  UpdateBeams();
237  if ( beam ) {
238  beam->Show();
239  }
240  if ( beamTarget ) {
241  beamTarget->Show();
242  }
243 
244  // Move the object to the fast group (helltime)
245  grabEnt->timeGroup = TIME_GROUP2;
246 
247  // Handle specific class types
248  if ( grabEnt->IsType( idProjectile::Type ) ) {
249  idProjectile* p = (idProjectile*)grabEnt;
250 
251  p->CatchProjectile( thePlayer, "_catch" );
252 
253  // Make the projectile non-solid to other projectiles/enemies (special hack for helltime hunter)
254  if ( !idStr::Cmp( grabEnt->GetEntityDefName(), "projectile_helltime_killer" ) ) {
255  savedContents = CONTENTS_PROJECTILE;
257  } else {
258  savedContents = grabEnt->GetPhysics()->GetContents();
259  savedClipmask = grabEnt->GetPhysics()->GetClipMask();
260  }
261  grabEnt->GetPhysics()->SetContents( 0 );
263 
264  } else if ( grabEnt->IsType( idExplodingBarrel::Type ) ) {
265  idExplodingBarrel *ebarrel = static_cast<idExplodingBarrel*>(grabEnt);
266 
267  ebarrel->StartBurning();
268 
269  } else if ( grabEnt->IsType( idAFEntity_Gibbable::Type ) ) {
270  holdingAF = true;
271  clipModelId = 0;
272 
273  if ( grabbableAI( grabEnt->spawnArgs.GetString( "classname" ) ) ) {
274  idAI *aiEnt = static_cast<idAI*>(grabEnt);
275 
276  aiEnt->StartRagdoll();
277  }
278  } else if ( grabEnt->IsType( idMoveableItem::Type ) ) {
279  grabEnt->PostEventMS( &EV_Touch, 250, thePlayer, 0 );
280  }
281 
282  // Get the current physics object to manipulate
283  idPhysics *phys = grabEnt->GetPhysics();
284 
285  // Turn off gravity on object
286  saveGravity = phys->GetGravity();
287  phys->SetGravity( vec3_origin );
288 
289  // hold it directly in front of player
290  localPlayerPoint = ( thePlayer->firstPersonViewAxis[0] * HOLD_DISTANCE ) * thePlayer->firstPersonViewAxis.Transpose();
291 
292  // Set the ending time for the hold
293  endTime = gameLocal.time + g_grabberHoldSeconds.GetFloat() * 1000;
294 
295  // Start up the Force_Drag to bring it in
296  drag.Init( g_grabberDamping.GetFloat() );
297  drag.SetPhysics( phys, clipModelId, thePlayer->firstPersonViewOrigin + localPlayerPoint * thePlayer->firstPersonViewAxis);
298 
299  // start the screen warp
300  warpId = thePlayer->playerView.AddWarp( phys->GetOrigin(), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 160, 2000 );
301 }
302 
303 /*
304 ==============
305 idGrabber::StopDrag
306 ==============
307 */
308 void idGrabber::StopDrag( bool dropOnly ) {
309  idPlayer *thePlayer = owner.GetEntity();
310 
311  if ( beam ) {
312  beam->Hide();
313  }
314  if ( beamTarget ) {
315  beamTarget->Hide();
316  }
317 
318  if ( dragEnt.IsValid() ) {
319  idEntity *ent = dragEnt.GetEntity();
320 
321  // set grabbed state for networking
322  ent->SetGrabbedState( false );
323 
324  // If a cinematic has started, allow dropped object to think in cinematics
325  if ( gameLocal.inCinematic ) {
326  ent->cinematic = true;
327  }
328 
329  // Restore Gravity
330  ent->GetPhysics()->SetGravity( saveGravity );
331 
332  // Move the object back to the slow group (helltime)
333  ent->timeGroup = TIME_GROUP1;
334 
335  if ( holdingAF ) {
336  idAFEntity_Gibbable *af = static_cast<idAFEntity_Gibbable *>(ent);
337  idPhysics_AF *af_Phys = static_cast<idPhysics_AF*>(af->GetPhysics());
338 
339  if ( grabbableAI( ent->spawnArgs.GetString( "classname" ) ) ) {
340  idAI *aiEnt = static_cast<idAI*>(ent);
341 
342  aiEnt->Damage( thePlayer, thePlayer, vec3_origin, "damage_suicide", 1.0f, INVALID_JOINT );
343  }
344 
345  af->SetThrown( !dropOnly );
346 
347  // Reset timers so that it isn't forcibly put to rest in mid-air
348  af_Phys->PutToRest();
349  af_Phys->Activate();
350 
351  af_Phys->SetTimeScaleRamp( MS2SEC(gameLocal.slow.time) - 1.5f, MS2SEC(gameLocal.slow.time) + 1.0f );
352  }
353 
354  // If the object isn't near its goal, just drop it in place.
355  if ( !ent->IsType( idProjectile::Type ) && ( dropOnly || drag.GetDistanceToGoal() > DRAG_FAIL_LEN ) ) {
357  thePlayer->StartSoundShader( declManager->FindSound( "grabber_maindrop" ), SND_CHANNEL_WEAPON, 0, false, NULL );
358 
359  if ( ent->IsType( idExplodingBarrel::Type ) ) {
360  idExplodingBarrel *ebarrel = static_cast<idExplodingBarrel*>(ent);
361 
362  ebarrel->SetStability( true );
363  ebarrel->StopBurning();
364  }
365  } else {
366  // Shoot the object forward
367  ent->ApplyImpulse( thePlayer, 0, ent->GetPhysics()->GetOrigin(), thePlayer->firstPersonViewAxis[0] * THROW_SCALE * ent->GetPhysics()->GetMass() );
368  thePlayer->StartSoundShader( declManager->FindSound( "grabber_release" ), SND_CHANNEL_WEAPON, 0, false, NULL );
369 
370  // Orient projectiles away from the player
371  if ( ent->IsType( idProjectile::Type ) ) {
372  idPlayer *player = owner.GetEntity();
373  idAngles ang = player->firstPersonViewAxis[0].ToAngles();
374 
375  ang.pitch += 90.f;
376  ent->GetPhysics()->SetAxis( ang.ToMat3() );
378 
379  // Restore projectile contents
380  ent->GetPhysics()->SetContents( savedContents );
381  ent->GetPhysics()->SetClipMask( savedClipmask );
382 
383  } else if ( ent->IsType( idMoveable::Type ) ) {
384  // Turn on damage for this object
385  idMoveable *obj = static_cast<idMoveable*>(ent);
386  obj->EnableDamage( true, 2.5f );
387  obj->SetAttacker( thePlayer );
388 
389  if ( ent->IsType( idExplodingBarrel::Type ) ) {
390  idExplodingBarrel *ebarrel = static_cast<idExplodingBarrel*>(ent);
391  ebarrel->SetStability( false );
392  }
393 
394  } else if ( ent->IsType( idMoveableItem::Type ) ) {
396  }
397  }
398 
399  // Remove the Force_Drag's control of the entity
400  drag.RemovePhysics( ent->GetPhysics() );
401  }
402 
403  if ( warpId != -1 ) {
404  thePlayer->playerView.FreeWarp( warpId );
405  warpId = -1;
406  }
407 
408  lastFiredTime = gameLocal.time;
409  dragEnt = NULL;
410  endTime = 0;
411 }
412 
413 /*
414 ==============
415 idGrabber::Update
416 ==============
417 */
418 int idGrabber::Update( idPlayer *player, bool hide ) {
419  trace_t trace;
420  idEntity *newEnt;
421 
422  // pause before allowing refire
423  if ( lastFiredTime + FIRING_DELAY > gameLocal.time ) {
424  return 3;
425  }
426 
427  // Dead players release the trigger
428  if ( hide || player->health <= 0 ) {
429  StopDrag( true );
430  if ( hide ) {
431  lastFiredTime = gameLocal.time - FIRING_DELAY + 250;
432  }
433  return 3;
434  }
435 
436  // Check if object being held has been removed (dead demon, projectile, etc.)
437  if ( endTime > gameLocal.time ) {
438  bool abort = !dragEnt.IsValid();
439 
440  if ( !abort && dragEnt.GetEntity()->IsType( idProjectile::Type ) ) {
441  idProjectile *proj = (idProjectile *)dragEnt.GetEntity();
442 
443  if ( proj->GetProjectileState() >= 3 ) {
444  abort = true;
445  }
446  }
447  if ( !abort && dragEnt.GetEntity()->IsHidden() ) {
448  abort = true;
449  }
450  // Not in multiplayer :: Pressing "reload" lets you carefully drop an item
451  if ( !gameLocal.isMultiplayer && !abort && (( player->usercmd.flags & UCF_IMPULSE_SEQUENCE ) != ( oldUcmdFlags & UCF_IMPULSE_SEQUENCE )) && (player->usercmd.impulse == IMPULSE_13) ) {
452  abort = true;
453  }
454 
455  if ( abort ) {
456  StopDrag( true );
457  return 3;
458  }
459  }
460 
461  owner = player;
462 
463  // if no entity selected for dragging
464  if ( !dragEnt.GetEntity() ) {
465  idBounds bounds;
466  idVec3 end = player->firstPersonViewOrigin + player->firstPersonViewAxis[0] * dragTraceDist;
467 
468  bounds.Zero();
469  bounds.ExpandSelf( TRACE_BOUNDS_SIZE );
470 
472  // If the trace hit something
473  if ( trace.fraction < 1.0f ) {
474  newEnt = gameLocal.entities[ trace.c.entityNum ];
475 
476  // if entity is already being grabbed then bypass
477  if ( gameLocal.isMultiplayer && newEnt->IsGrabbed() ) {
478  return 0;
479  }
480 
481  // Check if this is a valid entity to hold
482  if ( newEnt && ( newEnt->IsType( idMoveable::Type ) ||
483  newEnt->IsType( idMoveableItem::Type ) ||
484  newEnt->IsType( idProjectile::Type ) ||
485  newEnt->IsType( idAFEntity_Gibbable::Type ) ) &&
486  newEnt->noGrab == false &&
487  newEnt->GetPhysics()->GetBounds().GetRadius() < MAX_PICKUP_SIZE &&
488  newEnt->GetPhysics()->GetLinearVelocity().LengthSqr() < MAX_PICKUP_VELOCITY ) {
489 
490  bool validAF = true;
491 
492  if ( newEnt->IsType( idAFEntity_Gibbable::Type ) ) {
493  idAFEntity_Gibbable *afEnt = static_cast<idAFEntity_Gibbable*>(newEnt);
494 
495  if ( grabbableAI( newEnt->spawnArgs.GetString( "classname" ) ) ) {
496  // Make sure it's also active
497  if ( !afEnt->IsActive() ) {
498  validAF = false;
499  }
500  } else if ( !afEnt->IsActiveAF() ) {
501  validAF = false;
502  }
503  }
504 
505  if ( validAF && player->usercmd.buttons & BUTTON_ATTACK ) {
506  // Grab this entity and start dragging it around
507  StartDrag( newEnt, trace.c.id );
508  } else if ( validAF ) {
509  // A holdable object is ready to be grabbed
510  return 1;
511  }
512  }
513  }
514  }
515 
516  // check backwards server time in multiplayer
517  bool allow = true;
518 
519  if ( gameLocal.isMultiplayer ) {
520 
521  // if we've marched backwards
522  if ( gameLocal.slow.time < startDragTime ) {
523  allow = false;
524  }
525  }
526 
527 
528  // if there is an entity selected for dragging
529  if ( dragEnt.GetEntity() && allow ) {
530  idPhysics *entPhys = dragEnt.GetEntity()->GetPhysics();
531  idVec3 goalPos;
532 
533  // If the player lets go of attack, or time is up
534  if ( !( player->usercmd.buttons & BUTTON_ATTACK ) ) {
535  StopDrag( false );
536  return 3;
537  }
538  if ( gameLocal.time > endTime ) {
539  StopDrag( true );
540  return 3;
541  }
542 
543  // Check if the player is standing on the object
544  if ( !holdingAF ) {
545  idBounds playerBounds;
546  idBounds objectBounds = entPhys->GetAbsBounds();
547  idVec3 newPoint = player->GetPhysics()->GetOrigin();
548 
549  // create a bounds at the players feet
550  playerBounds.Clear();
551  playerBounds.AddPoint( newPoint );
552  newPoint.z -= 1.f;
553  playerBounds.AddPoint( newPoint );
554  playerBounds.ExpandSelf( 8.f );
555 
556  // If it intersects the object bounds, then drop it
557  if ( playerBounds.IntersectsBounds( objectBounds ) ) {
558  StopDrag( true );
559  return 3;
560  }
561  }
562 
563  // Shake the object at the end of the hold
564  if ( g_grabberEnableShake.GetBool() && !gameLocal.isMultiplayer ) {
565  ApplyShake();
566  }
567 
568  // Set and evaluate drag force
569  goalPos = player->firstPersonViewOrigin + localPlayerPoint * player->firstPersonViewAxis;
570 
571  drag.SetGoalPosition( goalPos );
572  drag.Evaluate( gameLocal.time );
573 
574  // If an object is flying too fast toward the player, stop it hard
575  if ( g_grabberHardStop.GetBool() ) {
576  idPlane theWall;
577  idVec3 toPlayerVelocity, objectCenter;
578  float toPlayerSpeed;
579 
580  toPlayerVelocity = -player->firstPersonViewAxis[0];
581  toPlayerSpeed = entPhys->GetLinearVelocity() * toPlayerVelocity;
582 
583  if ( toPlayerSpeed > 64.f ) {
584  objectCenter = entPhys->GetAbsBounds().GetCenter();
585 
586  theWall.SetNormal( player->firstPersonViewAxis[0] );
587  theWall.FitThroughPoint( goalPos );
588 
589  if ( theWall.Side( objectCenter, 0.1f ) == PLANESIDE_BACK ) {
590  int i, num;
591 
592  num = entPhys->GetNumClipModels();
593  for ( i=0; i<num; i++ ) {
594  entPhys->SetLinearVelocity( vec3_origin, i );
595  }
596  }
597  }
598 
599  // Make sure the object isn't spinning too fast
600  const float MAX_ROTATION_SPEED = 12.f;
601 
602  idVec3 angVel = entPhys->GetAngularVelocity();
603  float rotationSpeed = angVel.LengthFast();
604 
605  if ( rotationSpeed > MAX_ROTATION_SPEED ) {
606  angVel.NormalizeFast();
607  angVel *= MAX_ROTATION_SPEED;
608  entPhys->SetAngularVelocity( angVel );
609  }
610  }
611 
612  // Orient projectiles away from the player
613  if ( dragEnt.GetEntity()->IsType( idProjectile::Type ) ) {
614  idAngles ang = player->firstPersonViewAxis[0].ToAngles();
615  ang.pitch += 90.f;
616  entPhys->SetAxis( ang.ToMat3() );
617  }
618 
619  // Some kind of effect from gun to object?
620  UpdateBeams();
621 
622  // If the object is stuck away from its intended position for more than 500ms, let it go.
623  if ( drag.GetDistanceToGoal() > DRAG_FAIL_LEN ) {
624  if ( dragFailTime < (gameLocal.slow.time - 500) ) {
625  StopDrag( true );
626  return 3;
627  }
628  } else {
629  dragFailTime = gameLocal.slow.time;
630  }
631 
632  // Currently holding an object
633  return 2;
634  }
635 
636  // Not holding, nothing to hold
637  return 0;
638 }
639 
640 /*
641 ======================
642 idGrabber::UpdateBeams
643 ======================
644 */
645 void idGrabber::UpdateBeams( void ) {
646  jointHandle_t muzzle_joint;
647  idVec3 muzzle_origin;
648  idMat3 muzzle_axis;
649  renderEntity_t *re;
650 
651  if ( !beam ) {
652  return;
653  }
654 
655  if ( dragEnt.IsValid() ) {
656  idPlayer *thePlayer = owner.GetEntity();
657 
658  if ( beamTarget ) {
659  beamTarget->SetOrigin( dragEnt.GetEntity()->GetPhysics()->GetAbsBounds().GetCenter() );
660  }
661 
662  muzzle_joint = thePlayer->weapon.GetEntity()->GetAnimator()->GetJointHandle( "particle_upper" );
663  if ( muzzle_joint != INVALID_JOINT ) {
664  thePlayer->weapon.GetEntity()->GetJointWorldTransform( muzzle_joint, gameLocal.time, muzzle_origin, muzzle_axis );
665  } else {
666  muzzle_origin = thePlayer->GetPhysics()->GetOrigin();
667  }
668 
669  beam->SetOrigin( muzzle_origin );
670  re = beam->GetRenderEntity();
671  re->origin = muzzle_origin;
672 
673  beam->UpdateVisuals();
674  beam->Present();
675  }
676 }
677 
678 /*
679 ==============
680 idGrabber::ApplyShake
681 ==============
682 */
683 void idGrabber::ApplyShake( void ) {
684  float u = 1 - (float)( endTime - gameLocal.time ) / ( g_grabberHoldSeconds.GetFloat() * 1000 );
685 
686  if ( u >= 0.8f ) {
687  idVec3 point, impulse;
688  float shakeForceMagnitude = 450.f;
689  float mass = dragEnt.GetEntity()->GetPhysics()->GetMass();
690 
691  shakeForceFlip = !shakeForceFlip;
692 
693  // get point to rotate around
694  point = dragEnt.GetEntity()->GetPhysics()->GetOrigin();
695  point.y += 1;
696 
697  // Articulated figures get less violent shake
698  if ( holdingAF ) {
699  shakeForceMagnitude = 120.f;
700  }
701 
702  // calc impulse
703  if ( shakeForceFlip ) {
704  impulse.Set( 0, 0, shakeForceMagnitude * u * mass );
705  }
706  else {
707  impulse.Set( 0, 0, -shakeForceMagnitude * u * mass );
708  }
709 
710  dragEnt.GetEntity()->ApplyImpulse( NULL, 0, point, impulse );
711  }
712 }
713 
714 /*
715 ==============
716 idGrabber::grabbableAI
717 ==============
718 */
719 bool idGrabber::grabbableAI( const char *aiName ) {
720  // skip "monster_"
721  aiName += 8;
722 
723  if (!idStr::Cmpn( aiName, "flying_lostsoul", 15 ) ||
724  !idStr::Cmpn( aiName, "demon_trite", 11 ) ||
725  !idStr::Cmp( aiName, "flying_forgotten" ) ||
726  !idStr::Cmp( aiName, "demon_cherub" ) ||
727  !idStr::Cmp( aiName, "demon_tick" )) {
728 
729  return true;
730  }
731 
732  return false;
733 }
734 
735 #endif
virtual const idVec3 & GetOrigin(int id=0) const =0
jointHandle_t
Definition: Model.h:156
virtual void Hide(void)
virtual const idSoundShader * FindSound(const char *name, bool makeDefault=true)=0
int Cmp(const char *text) const
Definition: Str.h:652
bool IsActiveAF(void) const
Definition: AFEntity.h:168
virtual int GetClipMask(int id=-1) const =0
virtual void SetContents(int contents, int id=-1)=0
void WriteObject(const idClass *obj)
Definition: SaveGame.cpp:329
idVec3 GetCenter(void) const
Definition: Bounds.h:211
idClip clip
Definition: Game_local.h:296
void Zero(void)
Definition: Bounds.h:206
type * GetEntity(void) const
Definition: Game_local.h:695
void SetShaderParm(int parmnum, float value)
Definition: Entity.cpp:1067
idMat3 Transpose(void) const
Definition: Matrix.h:677
bool isMultiplayer
Definition: Game_local.h:325
bool IsType(const idTypeInfo &c) const
Definition: Class.h:337
void Set(const float x, const float y, const float z)
Definition: Vector.h:409
const int SCREEN_HEIGHT
Definition: RenderSystem.h:154
float z
Definition: Vector.h:320
virtual int GetNumClipModels(void) const =0
jointHandle_t GetJointHandle(const char *name) const
Definition: Vector.h:316
case const float
Definition: Callbacks.cpp:62
void ReadBool(bool &value)
Definition: SaveGame.cpp:976
virtual const idVec3 & GetLinearVelocity(int id=0) const =0
void WriteStaticObject(const idClass &obj)
Definition: SaveGame.cpp:348
virtual void SetLinearVelocity(const idVec3 &newLinearVelocity, int id=0)=0
void Clear(void)
Definition: Bounds.h:201
signed char impulse
Definition: UsercmdGen.h:101
float GetRadius(void) const
Definition: Bounds.cpp:39
void SetNormal(const idVec3 &normal)
Definition: Plane.h:233
void Set(const char *key, const char *value)
Definition: Dict.cpp:275
virtual void ApplyImpulse(idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse)
Definition: Entity.cpp:2887
bool cinematic
Definition: Entity.h:127
GLhandleARB obj
Definition: glext.h:3602
idDict spawnArgs
Definition: Entity.h:122
int i
Definition: process.py:33
#define MASK_MONSTERSOLID
Definition: Game_local.h:736
int Cmpn(const char *text, int n) const
Definition: Str.h:657
contactInfo_t c
GLuint GLuint num
Definition: glext.h:5390
void WriteVec3(const idVec3 &vec)
Definition: SaveGame.cpp:253
void Activate(void)
float fraction
const int IMPULSE_13
Definition: UsercmdGen.h:67
void WriteBool(const bool value)
Definition: SaveGame.cpp:222
const int BUTTON_ATTACK
Definition: UsercmdGen.h:44
idEntity * SpawnEntityType(const idTypeInfo &classdef, const idDict *args=NULL, bool bIsClientReadSnapshot=false)
virtual const idBounds & GetBounds(int id=-1) const =0
bool StartSoundShader(const idSoundShader *shader, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length)
Definition: Entity.cpp:1656
class idPlayerView playerView
Definition: Player.h:251
bool AddPoint(const idVec3 &v)
Definition: Bounds.h:226
void SetTimeScaleRamp(const float start, const float end)
idPhysics * GetPhysics(void) const
Definition: Entity.cpp:2607
virtual void SetGravity(const idVec3 &newGravity)=0
const char * GetString(const char *key, const char *defaultString="") const
Definition: Dict.h:240
void ReadFloat(float &value)
Definition: SaveGame.cpp:967
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
const int UCF_IMPULSE_SEQUENCE
Definition: UsercmdGen.h:87
GLuint GLuint end
Definition: glext.h:2845
void WriteFloat(const float value)
Definition: SaveGame.cpp:213
virtual float GetMass(int id=-1) const =0
byte flags
Definition: UsercmdGen.h:102
#define PLANESIDE_BACK
Definition: Plane.h:54
Definition: Dict.h:65
idVec3 firstPersonViewOrigin
Definition: Player.h:370
#define NULL
Definition: Lib.h:88
void Clear(void)
Definition: Dict.cpp:201
float y
Definition: Vector.h:319
virtual const idVec3 & GetAngularVelocity(int id=0) const =0
Definition: Plane.h:71
usercmd_t usercmd
Definition: Player.h:249
virtual idAnimator * GetAnimator(void)
Definition: Entity.cpp:5213
float NormalizeFast(void)
Definition: Vector.h:524
#define MASK_SHOT_RENDERMODEL
Definition: Game_local.h:741
float pitch
Definition: Angles.h:53
idGameLocal gameLocal
Definition: Game_local.cpp:64
void SetBool(const char *key, bool val)
Definition: Dict.h:196
float LengthSqr(void) const
Definition: Vector.h:635
#define END_CLASS
Definition: Class.h:54
bool inCinematic
Definition: Game_local.h:313
int Side(const idVec3 &v, const float epsilon=0.0f) const
Definition: Plane.h:328
idMat3 firstPersonViewAxis
Definition: Player.h:371
void WriteInt(const int value)
Definition: SaveGame.cpp:168
#define MAX_DRAG_TRACE_DISTANCE
Definition: GameEdit.cpp:110
idDeclManager * declManager
idEntity * entities[MAX_GENTITIES]
Definition: Game_local.h:275
int health
Definition: Entity.h:134
void ReadStaticObject(idClass &obj)
Definition: SaveGame.cpp:1098
bool TraceBounds(trace_t &results, const idVec3 &start, const idVec3 &end, const idBounds &bounds, int contentMask, const idEntity *passEntity)
Definition: Clip.h:338
Definition: Matrix.h:333
const int SCREEN_WIDTH
Definition: RenderSystem.h:153
GLuint id
Definition: glext.h:3103
tuple f
Definition: idal.py:89
Definition: Misc.h:513
idMat3 ToMat3(void) const
Definition: Angles.cpp:199
void PutToRest(void)
bool IntersectsBounds(const idBounds &a) const
Definition: Bounds.h:361
virtual const idBounds & GetAbsBounds(int id=-1) const =0
bool GetJointWorldTransform(jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis)
Definition: Entity.cpp:5248
virtual void Damage(idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location)
Definition: Actor.cpp:2203
#define CLASS_DECLARATION(nameofsuperclass, nameofclass)
Definition: Class.h:110
virtual void SetAngularVelocity(const idVec3 &newAngularVelocity, int id=0)=0
void ReadVec3(idVec3 &vec)
Definition: SaveGame.cpp:1011
float LengthFast(void) const
Definition: Vector.h:639
idAngles ToAngles(void) const
Definition: Matrix.cpp:147
bool IsActive(void) const
Definition: Entity.cpp:986
virtual int GetContents(int id=-1) const =0
idBounds & ExpandSelf(const float d)
Definition: Bounds.h:322
const char * GetEntityDefName(void) const
Definition: Entity.cpp:842
void SetOrigin(const idVec3 &org)
Definition: Entity.cpp:2784
bool PostEventMS(const idEventDef *ev, int time)
Definition: Class.cpp:666
GLfloat GLfloat p
Definition: glext.h:4674
void EnableDamage(bool enable, float duration)
Definition: Moveable.cpp:416
const idEventDef EV_Touch("<touch>","et")
virtual const idVec3 & GetGravity(void) const =0
idEntityPtr< idWeapon > weapon
Definition: Player.h:292
void ReadInt(int &value)
Definition: SaveGame.cpp:922
byte buttons
Definition: UsercmdGen.h:94
Definition: AI.h:253
virtual void SetClipMask(int mask, int id=-1)=0
bool StartRagdoll(void)
Definition: Actor.cpp:1651
void SetVector(const char *key, const idVec3 &val)
Definition: Dict.h:200
#define MS2SEC(t)
Definition: Math.h:60
void ReadObject(idClass *&obj)
Definition: SaveGame.cpp:1083
void FitThroughPoint(const idVec3 &p)
Definition: Plane.h:297
virtual void SetAxis(const idMat3 &newAxis, int id=-1)=0