//-----------------------------------------------------------------------------
// 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 );
	}
}
示例#2
0
/*
==============
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;
}
示例#3
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 );
}
示例#4
0
//-----------------------------------------------------------------------------
// Purpose: Handles changes to the shake amplitude from an external source.
//-----------------------------------------------------------------------------
void CASWEnvShake::InputAmplitude( inputdata_t &inputdata )
{
	SetAmplitude( inputdata.value.Float() );
	ApplyShake( SHAKE_AMPLITUDE );
}
示例#5
0
//-----------------------------------------------------------------------------
// Purpose: Input handler that stops the screen shake.
//-----------------------------------------------------------------------------
void CASWEnvShake::InputStopShake( inputdata_t &inputdata )
{
	ApplyShake( SHAKE_STOP );
}
示例#6
0
//-----------------------------------------------------------------------------
// Purpose: Input handler that starts the screen shake.
//-----------------------------------------------------------------------------
void CASWEnvShake::InputStartShake( inputdata_t &inputdata )
{
	ApplyShake( SHAKE_START );
}