//----------------------------------------------------------------------------- // Purpose: Input handler that starts the screen shake. //----------------------------------------------------------------------------- void CEnvShake::InputStartShake( inputdata_t &inputdata ) { if ( HasSpawnFlags( SF_SHAKE_NO_RUMBLE ) ) { ApplyShake( SHAKE_START_NORUMBLE ); } else if ( HasSpawnFlags( SF_SHAKE_NO_VIEW ) ) { ApplyShake( SHAKE_START_RUMBLEONLY ); } else { ApplyShake( SHAKE_START ); } }
/* ============== idGrabber::Update ============== */ int idGrabber::Update( idPlayer *player, bool hide ) { trace_t trace; idEntity *newEnt; // pause before allowing refire if ( lastFiredTime + FIRING_DELAY > gameLocal.time ) { return 3; } // Dead players release the trigger if ( hide || player->health <= 0 ) { StopDrag( true ); if ( hide ) { lastFiredTime = gameLocal.time - FIRING_DELAY + 250; } return 3; } // Check if object being held has been removed (dead demon, projectile, etc.) if ( endTime > gameLocal.time ) { bool abort = !dragEnt.IsValid(); if ( !abort && dragEnt.GetEntity()->IsType( idProjectile::Type ) ) { idProjectile *proj = (idProjectile *)dragEnt.GetEntity(); if ( proj->GetProjectileState() >= 3 ) { abort = true; } } if ( !abort && dragEnt.GetEntity()->IsHidden() ) { abort = true; } // Not in multiplayer :: Pressing "reload" lets you carefully drop an item if ( !gameLocal.isMultiplayer && !abort && (( player->usercmd.flags & UCF_IMPULSE_SEQUENCE ) != ( oldUcmdFlags & UCF_IMPULSE_SEQUENCE )) && (player->usercmd.impulse == IMPULSE_13) ) { abort = true; } if ( abort ) { StopDrag( true ); return 3; } } owner = player; // if no entity selected for dragging if ( !dragEnt.GetEntity() ) { idBounds bounds; idVec3 end = player->firstPersonViewOrigin + player->firstPersonViewAxis[0] * dragTraceDist; bounds.Zero(); bounds.ExpandSelf( TRACE_BOUNDS_SIZE ); gameLocal.clip.TraceBounds( trace, player->firstPersonViewOrigin, end, bounds, MASK_SHOT_RENDERMODEL|CONTENTS_PROJECTILE|CONTENTS_MOVEABLECLIP, player ); // If the trace hit something if ( trace.fraction < 1.0f ) { newEnt = gameLocal.entities[ trace.c.entityNum ]; // if entity is already being grabbed then bypass if ( gameLocal.isMultiplayer && newEnt->IsGrabbed() ) { return 0; } // Check if this is a valid entity to hold if ( newEnt && ( newEnt->IsType( idMoveable::Type ) || newEnt->IsType( idMoveableItem::Type ) || newEnt->IsType( idProjectile::Type ) || newEnt->IsType( idAFEntity_Gibbable::Type ) ) && newEnt->noGrab == false && newEnt->GetPhysics()->GetBounds().GetRadius() < MAX_PICKUP_SIZE && newEnt->GetPhysics()->GetLinearVelocity().LengthSqr() < MAX_PICKUP_VELOCITY ) { bool validAF = true; if ( newEnt->IsType( idAFEntity_Gibbable::Type ) ) { idAFEntity_Gibbable *afEnt = static_cast<idAFEntity_Gibbable*>(newEnt); if ( grabbableAI( newEnt->spawnArgs.GetString( "classname" ) ) ) { // Make sure it's also active if ( !afEnt->IsActive() ) { validAF = false; } } else if ( !afEnt->IsActiveAF() ) { validAF = false; } } if ( validAF && player->usercmd.buttons & BUTTON_ATTACK ) { // Grab this entity and start dragging it around StartDrag( newEnt, trace.c.id ); } else if ( validAF ) { // A holdable object is ready to be grabbed return 1; } } } } // check backwards server time in multiplayer bool allow = true; if ( gameLocal.isMultiplayer ) { // if we've marched backwards if ( gameLocal.slow.time < startDragTime ) { allow = false; } } // if there is an entity selected for dragging if ( dragEnt.GetEntity() && allow ) { idPhysics *entPhys = dragEnt.GetEntity()->GetPhysics(); idVec3 goalPos; // If the player lets go of attack, or time is up if ( !( player->usercmd.buttons & BUTTON_ATTACK ) ) { StopDrag( false ); return 3; } if ( gameLocal.time > endTime ) { StopDrag( true ); return 3; } // Check if the player is standing on the object if ( !holdingAF ) { idBounds playerBounds; idBounds objectBounds = entPhys->GetAbsBounds(); idVec3 newPoint = player->GetPhysics()->GetOrigin(); // create a bounds at the players feet playerBounds.Clear(); playerBounds.AddPoint( newPoint ); newPoint.z -= 1.f; playerBounds.AddPoint( newPoint ); playerBounds.ExpandSelf( 8.f ); // If it intersects the object bounds, then drop it if ( playerBounds.IntersectsBounds( objectBounds ) ) { StopDrag( true ); return 3; } } // Shake the object at the end of the hold if ( g_grabberEnableShake.GetBool() && !gameLocal.isMultiplayer ) { ApplyShake(); } // Set and evaluate drag force goalPos = player->firstPersonViewOrigin + localPlayerPoint * player->firstPersonViewAxis; drag.SetGoalPosition( goalPos ); drag.Evaluate( gameLocal.time ); // If an object is flying too fast toward the player, stop it hard if ( g_grabberHardStop.GetBool() ) { idPlane theWall; idVec3 toPlayerVelocity, objectCenter; float toPlayerSpeed; toPlayerVelocity = -player->firstPersonViewAxis[0]; toPlayerSpeed = entPhys->GetLinearVelocity() * toPlayerVelocity; if ( toPlayerSpeed > 64.f ) { objectCenter = entPhys->GetAbsBounds().GetCenter(); theWall.SetNormal( player->firstPersonViewAxis[0] ); theWall.FitThroughPoint( goalPos ); if ( theWall.Side( objectCenter, 0.1f ) == PLANESIDE_BACK ) { int i, num; num = entPhys->GetNumClipModels(); for ( i=0; i<num; i++ ) { entPhys->SetLinearVelocity( vec3_origin, i ); } } } // Make sure the object isn't spinning too fast const float MAX_ROTATION_SPEED = 12.f; idVec3 angVel = entPhys->GetAngularVelocity(); float rotationSpeed = angVel.LengthFast(); if ( rotationSpeed > MAX_ROTATION_SPEED ) { angVel.NormalizeFast(); angVel *= MAX_ROTATION_SPEED; entPhys->SetAngularVelocity( angVel ); } } // Orient projectiles away from the player if ( dragEnt.GetEntity()->IsType( idProjectile::Type ) ) { idAngles ang = player->firstPersonViewAxis[0].ToAngles(); ang.pitch += 90.f; entPhys->SetAxis( ang.ToMat3() ); } // Some kind of effect from gun to object? UpdateBeams(); // If the object is stuck away from its intended position for more than 500ms, let it go. if ( drag.GetDistanceToGoal() > DRAG_FAIL_LEN ) { if ( dragFailTime < (gameLocal.slow.time - 500) ) { StopDrag( true ); return 3; } } else { dragFailTime = gameLocal.slow.time; } // Currently holding an object return 2; } // Not holding, nothing to hold return 0; }
//----------------------------------------------------------------------------- // Purpose: Handles changes to the shake frequency from an external source. //----------------------------------------------------------------------------- void CASWEnvShake::InputFrequency( inputdata_t &inputdata ) { SetFrequency( inputdata.value.Float() ); ApplyShake( SHAKE_FREQUENCY ); }
//----------------------------------------------------------------------------- // Purpose: Handles changes to the shake amplitude from an external source. //----------------------------------------------------------------------------- void CASWEnvShake::InputAmplitude( inputdata_t &inputdata ) { SetAmplitude( inputdata.value.Float() ); ApplyShake( SHAKE_AMPLITUDE ); }
//----------------------------------------------------------------------------- // Purpose: Input handler that stops the screen shake. //----------------------------------------------------------------------------- void CASWEnvShake::InputStopShake( inputdata_t &inputdata ) { ApplyShake( SHAKE_STOP ); }
//----------------------------------------------------------------------------- // Purpose: Input handler that starts the screen shake. //----------------------------------------------------------------------------- void CASWEnvShake::InputStartShake( inputdata_t &inputdata ) { ApplyShake( SHAKE_START ); }