⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 g_phys.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 3 页
字号:
Bmodel objects don't interact with each other, but
push all box objects
================
*/
void G_Physics_Pusher
	(
	Entity *ent
	)
	
	{
	Vector	move, amove;
	Entity	*part, *mv;
	Event		*ev;

	// team slaves are only moved by their captains
	if ( ent->flags & FL_TEAMSLAVE )
		{
		return;
		}

	// Check if anyone on the team is moving
	for( part = ent; part; part = part->teamchain )
		{
		if ( part->velocity != vec_zero || part->avelocity != vec_zero )
			{
			break;
			}
		}

	// make sure all team slaves can move before commiting
	// any moves or calling any think functions
	// if the move is blocked, all moved objects will be backed out
	pushed_p = pushed;
	while( part )
		{
		move = part->velocity * FRAMETIME;
		amove = part->avelocity * FRAMETIME;
		if ( !G_Push( part, move, amove ) )
			{
			// move was blocked
			break;
			}

		part = part->teamchain;
		}

	if ( part )
		{
		// the move failed, bump all movedone times
		for( mv = ent; mv; mv = mv->teamchain )
			{
			mv->PostponeEvent( EV_MoveDone, FRAMETIME );
			}

		// if the pusher has a "blocked" function, call it
		// otherwise, just stay in place until the obstacle is gone
		ev = new Event( EV_Blocked );
		ev->AddEntity( obstacle );
		part->ProcessEvent( ev );
		}
	}

//==================================================================

/*
=============
G_Physics_Noclip

A moving object that doesn't obey physics
=============
*/
void G_Physics_Noclip
	(
	Entity *ent
	)

	{
	ent->angles += ent->avelocity * FRAMETIME;
	ent->origin += ent->velocity * FRAMETIME;
	ent->link();
	}

/*
==============================================================================

TOSS / BOUNCE

==============================================================================
*/

/*
=============
G_Physics_Toss

Toss, bounce, and fly movement.  When onground, do nothing.
=============
*/
void G_Physics_Toss 
	(
	Entity *ent
	)

	{
	trace_t	trace;
	Vector	move;
	float		backoff;
	Entity	*slave;
	qboolean	wasinwater;
	qboolean	isinwater;
	Vector	old_origin;
	Vector	basevel;
	edict_t	*edict;
	qboolean onconveyor;
   const gravityaxis_t &grav = gravity_axis[ ent->gravaxis ];

	// if not a team captain, so movement will be handled elsewhere
	if ( ent->flags & FL_TEAMSLAVE )
		{
		return;
		}

	if ( ( ent->velocity[ grav.z ] * grav.sign ) > 0 )
		{
		ent->groundentity = NULL;
		}

	// check for the groundentity going away
	if ( ent->groundentity && !ent->groundentity->inuse )
		{
		ent->groundentity = NULL;
		}

	G_AddCurrents( ent, &basevel );
	onconveyor = ( basevel != vec_zero );

	// if onground, return without moving
	if ( ent->groundentity && !onconveyor && ( ent->movetype != MOVETYPE_VEHICLE ) )
		{
      if ( ent->avelocity.length() )
         {
	      // move angles
	      ent->setAngles( ent->angles + ent->avelocity * FRAMETIME );
         }
      ent->velocity = vec_zero;
		return;
		}

	old_origin = ent->origin;

	G_CheckVelocity( ent );

	// add gravity
	if ( !onconveyor && ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE )
		{
		G_AddGravity( ent );
		}

	// move angles
	ent->setAngles( ent->angles + ent->avelocity * FRAMETIME );

	// move origin
	move = ( ent->velocity + basevel ) * FRAMETIME;

	edict = ent->edict;
   if ( ent->movetype == MOVETYPE_VEHICLE )
      {
      int mask;

	   if ( ent->edict->clipmask )
		   {
		   mask = ent->edict->clipmask;
		   }
	   else
		   {
		   mask = MASK_MONSTERSOLID;
		   }
      G_FlyMove( ent, basevel, FRAMETIME, mask );
   	G_TouchTriggers( ent );
      return;
      }
   else
      {
	   trace = G_PushEntity( ent, move );
      }

   if ( (trace.fraction == 0) && (ent->movetype == MOVETYPE_SLIDE) )
      {
      // Check for slide by removing the downward velocity
      Vector slide;

      slide[ grav.x ] = move[ grav.x ] * 0.7f;
      slide[ grav.y ] = move[ grav.y ] * 0.7f;
      slide[ grav.z ] = 0;
      G_PushEntity( ent, slide );
      }

	if ( !edict->inuse )
		{
		return;
		}

	if ( trace.fraction < 1 )
		{
		if ( ent->movetype == MOVETYPE_BOUNCE )
			{
			backoff = 1.5;
			}
		else
			{
			backoff = 1;
			}

		G_ClipVelocity( ent->velocity, Vector( trace.plane.normal ), ent->velocity, backoff, ent->gravaxis );

		// stop if on ground
		if ( ( trace.plane.normal[ grav.z ] * grav.sign ) > 0.7 )
			{	
			if (( ( ent->velocity[ grav.z ] * grav.sign ) < 60 || ent->movetype != MOVETYPE_BOUNCE ) && 
            (ent->movetype != MOVETYPE_SLIDE))
            {
				ent->groundentity = trace.ent;
				ent->groundentity_linkcount = trace.ent->linkcount;
				ent->groundplane = trace.plane;
				ent->groundsurface = trace.surface;
				ent->groundcontents = trace.contents;
				ent->velocity = vec_zero;
				ent->avelocity = vec_zero;
				}
			}
		}

	if ( ( move[ grav.z ] == 0 ) && onconveyor )
		{
		// Check if we still have a ground
		ent->CheckGround();
		}

	// check for water transition
	wasinwater = ( ent->watertype & MASK_WATER );
	ent->watertype = gi.pointcontents( ent->worldorigin.vec3() );
	isinwater = ent->watertype & MASK_WATER;

	if ( isinwater )
		{
		ent->waterlevel = 1;
		}
	else
		{
		ent->waterlevel = 0;
		}

	if ( ( edict->spawntime < ( level.time - FRAMETIME ) ) && ( ent->mass > 0 ) )
		{
		if ( !wasinwater && isinwater )
			{
#ifdef SIN
         ent->RandomPositionedSound( old_origin.vec3(), "impact_watersplash" );
#else
			gi.positioned_sound( old_origin.vec3(), g_edicts, CHAN_AUTO, 
				gi.soundindex( "misc/h2ohit1.wav" ), 1, 1, 0, 1, 0, 0 );
#endif
			}
		else if ( wasinwater && !isinwater )
			{
#ifdef SIN
         ent->RandomPositionedSound( old_origin.vec3(), "impact_watersplash" );
#else
			gi.positioned_sound( old_origin.vec3(), g_edicts, CHAN_AUTO, 
				gi.soundindex( "misc/h2ohit1.wav" ), 1, 1, 0, 1, 0, 0 );
#endif
			}
		}

	// move teamslaves
	for( slave = ent->teamchain; slave; slave = slave->teamchain )
		{
		slave->origin = ent->origin;
		slave->link();
		}

	G_TouchTriggers( ent );
	}

/*
===============================================================================

STEPPING MOVEMENT

===============================================================================
*/

void G_AddRotationalFriction
	(
	Entity *ent
	)

	{
	int	n;
	float	adjustment;

	ent->angles += FRAMETIME * ent->avelocity;
	adjustment = FRAMETIME * sv_stopspeed->value * sv_friction->value;
	for( n = 0; n < 3; n++ )
		{
		if ( ent->avelocity[ n ] > 0)
			{
			ent->avelocity[ n ] -= adjustment;
			if ( ent->avelocity[ n ] < 0 )
				{
				ent->avelocity[ n ] = 0;
				}
			}
		else
			{
			ent->avelocity[ n ] += adjustment;
			if ( ent->avelocity[ n ] > 0 )
				{
				ent->avelocity[ n ] = 0;
				}
			}
		}
	}

/*
=============
G_CheckWater

=============
*/

void G_CheckWater
	(
   Entity *ent
	)

   {
   if ( ent->isSubclassOf( Actor ) )
      {
      ( ( Actor * )ent )->CheckWater();
      }
   else
      {
	   ent->watertype = gi.pointcontents( ent->worldorigin.vec3() );
	   if ( ent->watertype & MASK_WATER )
		   {
		   ent->waterlevel = 1;
		   }
	   else
		   {
		   ent->waterlevel = 0;
		   }
      }
   }

/*
=============
G_Physics_Step

Monsters freefall when they don't have a ground entity, otherwise
all movement is done with discrete steps.

This is also used for objects that have become still on the ground, but
will fall if the floor is pulled out from under them.
FIXME: is this true?
=============
*/

void G_Physics_Step
	(
	Entity *ent
	)

	{
	qboolean	wasonground;
	qboolean	hitsound = false;
	Vector	vel;
	float		speed, newspeed, control;
	float		friction;
	int		mask;
	Vector	basevel;

	// airborn monsters should always check for ground
	if ( !ent->groundentity )
		{
		ent->CheckGround();
		}

	if ( ent->groundentity )
		{
		wasonground = true;
		}
	else
		{
		wasonground = false;
		}

	G_CheckVelocity( ent );

	if ( ent->avelocity != vec_zero )
		{
		G_AddRotationalFriction( ent );
		}

	// add gravity except:
	//   flying monsters
	//   swimming monsters who are in the water
	if ( !wasonground )
		{
		if ( !( ent->flags & FL_FLY ) )
			{
			if ( !( ( ent->flags & FL_SWIM ) && ( ent->waterlevel > 2 ) ) )
				{
				if ( ent->velocity[ gravity_axis[ ent->gravaxis ].z ] < sv_gravity->value * ent->gravity * -0.1 *
					gravity_axis[ ent->gravaxis ].sign )
					{
					hitsound = true;
					}

            // Testing water gravity.  If this doesn't work, just restore the uncommented lines
				//if ( ent->waterlevel == 0 )
					//{
					G_AddGravity( ent );
					//}
				}
			}
		}

	// friction for flying monsters that have been given vertical velocity
	if ( ( ent->flags & FL_FLY ) && ( ent->velocity.z != 0 ) )
		{
		speed = fabs( ent->velocity.z );
		control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed;
		friction = sv_friction->value / 3;
		newspeed = speed - ( FRAMETIME * control * friction );
		if ( newspeed < 0 )
			{
			newspeed = 0;
			}
		newspeed /= speed;
		ent->velocity.z *= newspeed;
		}

	// friction for flying monsters that have been given vertical velocity
	if ( ( ent->flags & FL_SWIM ) && ( ent->velocity.z != 0 ) )
		{
		speed = fabs( ent->velocity.z );
		control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed;
		newspeed = speed - ( FRAMETIME * control * sv_waterfriction->value * ent->waterlevel );
		if ( newspeed < 0 )
			{
			newspeed = 0;
			}
		newspeed /= speed;
		ent->velocity.z *= newspeed;
		}

	if ( ent->velocity != vec_zero )
		{
		// apply friction
		// let dead monsters who aren't completely onground slide
		if ( ( wasonground ) || ( ent->flags & ( FL_SWIM | FL_FLY ) ) )
			{
			if ( !( ent->health <= 0.0 && !M_CheckBottom( ent ) ) )
				{
				vel = ent->velocity;
				vel.z = 0;
				speed = vel.length();
				if ( speed )
					{
					friction = sv_friction->value;

					control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed;
					newspeed = speed - FRAMETIME * control * friction;

					if ( newspeed < 0 )
						{
						newspeed = 0;
						}

					newspeed /= speed;

					ent->velocity.x *= newspeed;
					ent->velocity.y *= newspeed;
					}
				}
			}
		}

	G_AddCurrents( ent, &basevel );

	if ( ( basevel != vec_zero ) || ( ent->velocity != vec_zero ) || ( ent->total_delta != vec_zero ) )
		{
		if ( ent->edict->svflags & SVF_MONSTER )
			{
			mask = MASK_MONSTERSOLID;
			}
		else
			{
			mask = MASK_SOLID;
			}
	
		G_FlyMove( ent, basevel, FRAMETIME, mask );

		ent->link();

      G_CheckWater( ent );
		G_TouchTriggers( ent );

		if ( ent->groundentity && !wasonground && hitsound )
			{
			ent->RandomGlobalSound( "impact_softland", 0.5f, CHAN_BODY, 1 );
			}
		}
	}

//============================================================================
/*
================
G_RunEntity

================
*/
void G_RunEntity 
	(
	Entity *ent
	)

	{
	edict_t *edict;

	edict = ent->edict;

   if ( ent->animating && !level.intermissiontime )
		{
		ent->AnimateFrame();
		}
	
	if ( edict->inuse && ent->flags & FL_PRETHINK )
		{
		ent->Prethink();
		}

	if ( edict->inuse )
		{
		switch ( ( int )ent->movetype )
			{
			case MOVETYPE_PUSH:
			case MOVETYPE_STOP:
				G_Physics_Pusher( ent );
				break;
			case MOVETYPE_NONE:
			case MOVETYPE_WALK:
				break;
			case MOVETYPE_NOCLIP:
				G_Physics_Noclip( ent );
				break;
			case MOVETYPE_STEP:
         case MOVETYPE_HURL:
				G_Physics_Step( ent );
				break;
			case MOVETYPE_TOSS:
			case MOVETYPE_BOUNCE:
			case MOVETYPE_FLY:
			case MOVETYPE_FLYMISSILE:
         case MOVETYPE_SLIDE:
         case MOVETYPE_VEHICLE:
				G_Physics_Toss( ent );
				break;
			default:
				gi.error( "G_Physics: bad movetype %i", ( int )ent->movetype );
			}
		}

	if ( ( edict->inuse ) && ( ent->flags & FL_POSTTHINK ) )
		{
		ent->Postthink();
		}
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -