예제 #1
0
/*
=============
SV_Physics_Toss

Toss, bounce, and fly movement.  When onground, do nothing.
=============
*/
void SV_Physics_Toss (edict_t *ent)
{
	trace_t	trace;
	vec3_t	move;
	float	backoff;

	// regular thinking
	if (!SV_RunThink (ent))
		return;

// if onground, return without moving
	if ( ((int)ent->v.flags & FL_ONGROUND) )
		return;

	SV_CheckVelocity (ent);

// add gravity
	if (ent->v.movetype != MOVETYPE_FLY
	&& ent->v.movetype != MOVETYPE_FLYMISSILE)
		SV_AddGravity (ent);

// move angles
	VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);

// move origin
	VectorScale (ent->v.velocity, host_frametime, move);
	trace = SV_PushEntity (ent, move);
	if (trace.fraction == 1)
		return;
	if (ent->free)
		return;
	
	if (ent->v.movetype == MOVETYPE_BOUNCE)
		backoff = 1.5;
	else
		backoff = 1;

	ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);

// stop if on ground
	if (trace.plane.normal[2] > 0.7)
	{
		int stop_moving = false;
		if (sv_bouncedownslopes.value)
		{
			if (DotProduct(trace.plane.normal, ent->v.velocity) < 60)
				stop_moving = true;
		}
		else
		{
			if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE)
				stop_moving = true;
		}

		if (stop_moving)
		{
			ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
			ent->v.groundentity = EDICT_TO_PROG(trace.ent);
			VectorClear (ent->v.velocity);
			VectorClear (ent->v.avelocity);
		}
	}
	
// check for in water
	SV_CheckWaterTransition (ent);
}
예제 #2
0
파일: sv_phys.c 프로젝트: THE-Swank/xash3d
/*
=============
SV_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.
=============
*/
void SV_Physics_Step( edict_t *ent )
{
	qboolean	inwater;
	qboolean	wasonground;
	qboolean	wasonmover;
	vec3_t	mins, maxs;
	vec3_t	point;
	trace_t	trace;
	int	x, y;

	SV_WaterMove( ent );
	SV_CheckVelocity( ent );

	wasonground = (ent->v.flags & FL_ONGROUND);
	wasonmover = SV_CheckMover( ent );
	inwater = SV_CheckWater( ent );

	if( ent->v.flags & FL_FLOAT && ent->v.waterlevel > 0 )
	{
		float buoyancy = SV_Submerged( ent ) * ent->v.skin * host.frametime;

		SV_AddGravity( ent );
		ent->v.velocity[2] += buoyancy;
	}

	if( !wasonground && !( ent->v.flags & FL_FLY ) && (!( ent->v.flags & FL_SWIM ) || ent->v.waterlevel <= 0 ))
	{
		if( !inwater )
			SV_AddGravity( ent );
	}

	if( !VectorIsNull( ent->v.velocity ) || !VectorIsNull( ent->v.basevelocity ))
	{
		ent->v.flags &= ~FL_ONGROUND;

		if(( wasonground || wasonmover ) && ( ent->v.health > 0 || SV_CheckBottom( ent, MOVE_NORMAL )))
		{
			float	*vel = ent->v.velocity;
			float	control, speed, newspeed;
			float	friction;

			speed = sqrt(( vel[0] * vel[0] ) + ( vel[1] * vel[1] ));	// DotProduct2D

			if( speed )
			{
				friction = sv_friction->value * ent->v.friction;	// factor
				ent->v.friction = 1.0f; // g-cont. ???
				if( wasonmover ) friction *= 0.5f; // add a little friction

				control = (speed < sv_stopspeed->value) ? sv_stopspeed->value : speed;
				newspeed = speed - (host.frametime * control * friction);
				if( newspeed < 0 ) newspeed = 0;
				newspeed /= speed;

				vel[0] = vel[0] * newspeed;
				vel[1] = vel[1] * newspeed;
			}
		}

		VectorAdd( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
		SV_CheckVelocity( ent );

		SV_FlyMove( ent, host.frametime, NULL );
		if( ent->free ) return;

		SV_CheckVelocity( ent );
		VectorSubtract( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );

		SV_CheckVelocity( ent );

		VectorAdd( ent->v.origin, ent->v.mins, mins );
		VectorAdd( ent->v.origin, ent->v.maxs, maxs );

		point[2] = mins[2] - 1.0f;

		for( x = 0; x <= 1; x++ )
		{
			if( ent->v.flags & FL_ONGROUND )
				break;

			for( y = 0; y <= 1; y++ )
			{
				point[0] = x ? maxs[0] : mins[0];
				point[1] = y ? maxs[1] : mins[1];

				trace = SV_Move( point, vec3_origin, vec3_origin, point, MOVE_NORMAL, ent );

				if( trace.startsolid )
				{
					ent->v.flags |= FL_ONGROUND;
					ent->v.groundentity = trace.ent;
					ent->v.friction = 1.0f;
					break;
				}
			}
		}

		SV_LinkEdict( ent, true );
	}
	else
	{
		if( svgame.globals->force_retouch != 0 )
		{
			trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent );

			// hentacle impact code
			if(( trace.fraction < 1.0f || trace.startsolid ) && SV_IsValidEdict( trace.ent ))
			{
				SV_Impact( ent, trace.ent, &trace );
				if( ent->free ) return;
			}
		}
	}

	if( !SV_RunThink( ent )) return;
	SV_CheckWaterTransition( ent );

}
예제 #3
0
파일: g_phys.c 프로젝트: ZwS/qudos
/*
 * ============= SV_Physics_Toss =============
 *
 * Toss, bounce, and fly movement.  When onground, do nothing.
 */
void
SV_Physics_Toss(edict_t * ent)
{
	trace_t		trace;
	vec3_t		move;
	float		backoff;
	edict_t		*slave;
	qboolean	wasinwater;
	qboolean	isinwater;
	vec3_t		old_origin;

	if (!ent)
		return;

	/* regular thinking */
	SV_RunThink(ent);

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

	if (ent->velocity[2] > 0)
		ent->groundentity = NULL;

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

	/* if onground, return without moving */
	if (ent->groundentity)
		return;

	VectorCopy(ent->s.origin, old_origin);

	SV_CheckVelocity(ent);

	/* add gravity */
	if (ent->movetype != MOVETYPE_FLY
	    && ent->movetype != MOVETYPE_FLYMISSILE)
		SV_AddGravity(ent);

	/* move angles */
	VectorMA(ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);

	/* move origin */
	VectorScale(ent->velocity, FRAMETIME, move);
	trace = SV_PushEntity(ent, move);
	if (!ent->inuse)
		return;

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

		ClipVelocity(ent->velocity, trace.plane.normal, ent->velocity, backoff);

		/* stop if on ground */
		if (trace.plane.normal[2] > 0.7) 
		{
			if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE) 
			{
				ent->groundentity = trace.ent;
				ent->groundentity_linkcount = trace.ent->linkcount;
				VectorCopy(vec3_origin, ent->velocity);
				VectorCopy(vec3_origin, ent->avelocity);
			}
		}
	}
	
	/* check for water transition */
	wasinwater = (ent->watertype & MASK_WATER);
	ent->watertype = gi.pointcontents(ent->s.origin);
	isinwater = ent->watertype & MASK_WATER;

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

	if (!wasinwater && isinwater)
		gi.positioned_sound(old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
	else if (wasinwater && !isinwater)
		gi.positioned_sound(ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);

	/* move teamslaves */
	for (slave = ent->teamchain; slave; slave = slave->teamchain) {
		VectorCopy(ent->s.origin, slave->s.origin);
		gi.linkentity(slave);
	}
}
예제 #4
0
파일: sv_phys.c 프로젝트: ACIIL/Quake
/*
=============
SV_Physics_None

Non moving objects can only think
=============
*/
void SV_Physics_None (edict_t *ent)
{
// regular thinking
	SV_RunThink (ent);
}
예제 #5
0
void SV_Physics_Step (edict_t *ent)
{
	qboolean	wasonground;
	qboolean	hitsound = false;
	float		*vel;
	float		speed, newspeed, control;
	float		friction;
	edict_t		*groundentity;
	int			mask;
	int			retval;
	vec3_t		oldpos;

	// BEGIN:	Xatrix/Ridah
	vec3_t	old_vel;
	// END:		Xatrix/Ridah

	// Joseph
	if (ent->fallerflag)
	{
		// Fix if sitting off center
		think_checkedges(ent);
	}
	
	// airborn monsters should always check for ground
	if (!ent->groundentity)
		M_CheckGround (ent);

	groundentity = ent->groundentity;

	SV_CheckVelocity (ent);

	if (groundentity)
		wasonground = true;
	else
		wasonground = false;
		
	if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2])
		SV_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[2] < sv_gravity->value*-0.1)
					hitsound = true;
// Ridah, 1-may-99, disabled this to prevent guys getting stuck in water
//				if (ent->waterlevel == 0)
					SV_AddGravity (ent);
			}
/*
	// friction for flying monsters that have been given vertical velocity
	if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0))
	{
		speed = fabs(ent->velocity[2]);
		control = speed < sv_stopspeed ? sv_stopspeed : speed;
		friction = sv_friction/3;
		newspeed = speed - (FRAMETIME * control * friction);
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		ent->velocity[2] *= newspeed;
	}
*/
	// friction for flying monsters that have been given vertical velocity
	if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0))
	{
		speed = fabs(ent->velocity[2]);
		control = speed < sv_stopspeed ? sv_stopspeed : speed;
		newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel);
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		ent->velocity[2] *= newspeed;
	}

	if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0])
	{
		// 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;
				speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
				if (speed)
				{
					friction = sv_friction;

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

					if (newspeed < 0)
						newspeed = 0;
					newspeed /= speed;

					vel[0] *= newspeed;
					vel[1] *= newspeed;
				}
			}

		// BEGIN:	Xatrix/Ridah
		// JOSEPH 26-APR-99
		if ((ent->svflags & SVF_MONSTER) || (ent->monsterprop))
		// END JOSEPH
		{
//			if (ent->cast_info.aiflags & AI_PLAYERCLIP)
				mask = MASK_PLAYERSOLID | CONTENTS_MONSTERCLIP;
//			else
//				mask = MASK_MONSTERSOLID;
		}
		else
			mask = MASK_SOLID;

		VectorCopy (ent->velocity, old_vel);
		// END:		Xatrix/Ridah

		VectorCopy (ent->s.origin, oldpos );

		retval = SV_FlyMove (ent, FRAMETIME, mask);

#if 0	// leave this here for now.

		// Ridah, HACK... sometimes they get stuck, we should debug this properly when we get the time
		if (!ValidBoxAtLoc( ent->s.origin, ent->mins, ent->maxs, ent, MASK_SOLID ))
		{	// move back to old position and clear velocity
			int iter=0;

			VectorCopy (oldpos, ent->s.origin);
			VectorClear (ent->velocity);

			// find a good position
			while (!ValidBoxAtLoc( ent->s.origin, ent->mins, ent->maxs, ent, MASK_SOLID ))
			{
				VectorAdd( ent->s.origin, tv((random()-0.5) * 64, (random()-0.5) * 64, (random()-0.5) * 64), ent->s.origin );

				if (++iter > 10)
					break;
			}

//			if (iter <= 4)
//			{	// make sure they're on the ground
//				M_droptofloor( ent );
//			}

			goto exit_vel_check;		// get out of here?
		}
#endif

		// BEGIN:	Xatrix/Ridah
		if (!ent->groundentity || (ent->flags & FL_FLY))
		{
			node_t	*land_node;

			// Ridah, prevent guys getting stuck trying to jump
			if (VectorDistance( ent->s.origin, oldpos ) < 1 && !ent->groundentity && (ent->last_onground < (level.time - 2)))
			{
				ent->velocity[0] = crandom() * 300;
				ent->velocity[1] = crandom() * 300;

				if (ent->velocity[2] < -200)
					ent->velocity[2] = -200;

				ent->velocity[2] += random() * 350;

				ent->nav_data.goal_index = 0;
				ent->last_onground = level.time;
			}

			if (ent->velocity[2] > 80 && retval != 20)
			{	// while rising, maintain XY velocity
				ent->velocity[0] = old_vel[0];
				ent->velocity[1] = old_vel[1];
			}

			// see if we've gone passed the landing position
			if (	!(ent->flags & FL_FLY)
				&&	(retval == -1) && (ent->nav_data.goal_index)
				&&	(land_node = level.node_data->nodes[ent->nav_data.goal_index-1]))
//				&&	(land_node->node_type & NODE_LANDING))
			{
				vec3_t	unit_vel, goal_dir, goal_vec;
				float	vel_scale, dist;

				VectorSubtract( land_node->origin, ent->s.origin, goal_vec );
				goal_vec[2] = 0;
				dist = VectorNormalize2( goal_vec, goal_dir );

				if (dist > 16)
				{

					VectorCopy( ent->velocity, unit_vel );
					unit_vel[2] = 0;
					vel_scale = VectorNormalize( unit_vel );

					if (DotProduct( unit_vel, goal_dir ) < 0.8)
					{	// we've either gone passed, or need some correction
						vec3_t new_pos;
						float	old_z;

						if (VectorLength( goal_vec ) < 40)
						{
							new_pos[0] = land_node->origin[0];
							new_pos[1] = land_node->origin[1];
							new_pos[2] = ent->s.origin[2];

							if (ValidBoxAtLoc( new_pos, ent->mins, ent->maxs, ent, MASK_PLAYERSOLID | MASK_MONSTERSOLID ))
							{	// move there, it's safe, and clear velocity
								VectorCopy( new_pos, ent->s.origin );
								ent->velocity[0] = ent->velocity[1] = 0;

								goto exit_vel_check;
							}
						}

						// we need to adjust our velocity
						if (land_node->origin[2] < (ent->s.origin[2] - 64))
						{
							old_z = ent->velocity[2];
							VectorScale( goal_dir, vel_scale, ent->velocity );
							ent->velocity[2] = old_z;
						}
						
					}

				}
			}	

			if (	(ent->flags & FL_FLY)
				&&	((land_node = level.node_data->nodes[ent->nav_data.goal_index-1]) || ((ent->flags &= ~FL_FLY) && false))
				/*&&	(land_node->node_type & NODE_LANDING)*/)
			{	// if climbing ladder, and we're reached the landing position, stop

				// Ridah, 8-jun-99, make sure dog's don't climb ladders
				if (!ent->gender)
				{
					goto abort_climb;
				}

				if (ent->s.origin[2] > land_node->origin[2])
				{
//gi.dprintf( "-> end of climb\n" );
//					VectorSubtract( land_node->origin, ent->s.origin, ent->velocity );
					AngleVectors( ent->s.angles, ent->velocity, NULL, NULL );
					ent->velocity[2] = 0;
					VectorNormalize( ent->velocity );
					VectorScale( ent->velocity, 96, ent->velocity );

					ent->velocity[2] = 200;

					ent->flags &= ~FL_FLY;
					ent->nav_data.goal_index = 0;		// look for a new node
					ent->nav_data.cache_node = -1;

					if (ent->cast_info.move_end_climb)
						ent->cast_info.currentmove = ent->cast_info.move_end_climb;
				}
				else
				{
					trace_t tr;
					vec3_t	end, goal_vec;

					VectorSubtract( land_node->origin, ent->s.origin, goal_vec );

					ent->velocity[0] = goal_vec[0];
					ent->velocity[1] = goal_vec[1];
					ent->velocity[2] = 120;

					// if another character is above us, abort
					VectorCopy( ent->s.origin, end );
					end[2] += 128;
					tr = gi.trace( ent->s.origin, ent->mins, ent->maxs, end, ent, MASK_PLAYERSOLID | MASK_MONSTERSOLID );
					
					if ((tr.fraction < 1) && (tr.ent->svflags & SVF_MONSTER))
					{

abort_climb:

						AngleVectors( ent->s.angles, goal_vec, NULL, NULL );
						VectorScale( goal_vec, -64, ent->velocity );
						ent->flags &= ~FL_FLY;
						ent->nav_data.goal_index = 0;

						if (ent->cast_info.move_end_climb)
						{
							ent->cast_info.currentmove = ent->cast_info.move_end_climb;
						}
						else if (ent->cast_info.move_jump)
						{
							ent->cast_info.currentmove = ent->cast_info.move_jump;
						}
					}
					else if (ent->s.origin[2] > (land_node->origin[2] - 48))
					{	// we're near the top, stopping climbing anim
//gi.dprintf( "near end of climb\n" );
						if (ent->cast_info.move_end_climb)
							ent->cast_info.currentmove = ent->cast_info.move_end_climb;

						// add some forward momentum
						AngleVectors( ent->s.angles, goal_vec, NULL, NULL );
						VectorMA( ent->velocity, 64, goal_vec, ent->velocity );
					}

				}

			}
		}

exit_vel_check:

		// END:		Xatrix/Ridah

		gi.linkentity (ent);
		G_TouchTriggers (ent);

// Note to Ryan: we can't use this because we are playing specific sounds elsewhere
/*
		if (ent->groundentity)
			if (!wasonground)
				if (hitsound)
					// BEGIN:	Xatrix/Ridah/Navigator/03-apr-1998
					if (!(ent->cast_info.move_run))
					// END:		Xatrix/Ridah/Navigator/03-apr-1998
						gi.sound (ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0);
*/
	}

// regular thinking
	SV_RunThink (ent);
}
예제 #6
0
/*
=============
SV_Physics_Toss

Toss, bounce, and fly movement.  When onground, do nothing.
=============
*/
void SV_Physics_Toss (edict_t *ent)
{
	trace_t		trace;
	vec3_t		move;
	float		backoff;
	edict_t		*slave;
	qboolean	wasinwater;
	qboolean	isinwater;
	vec3_t		old_origin;

// regular thinking
	SV_RunThink (ent);

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

	if (ent->velocity[2] > 0)
		ent->groundentity = NULL;

// check for the groundentity going away
	if (ent->groundentity)
		if (!ent->groundentity->inuse)
			ent->groundentity = NULL;
// if onground, return without moving
	if ( ent->groundentity && ent->movetype != MOVETYPE_TOSS_SLIDE )
	{
		// JOSEPH 7-OCT-98
		if (ent->fallerflag)
		{
			
			// JOSEPH 22-JAN-99
			// If the object just hit the floor
			if (ent->fallingflag)
			{
				ent->fallingflag = 0;	
				if (!strcmp(ent->classname, "props_trashcanA"))
				{
					gi.sound (ent, CHAN_AUTO, gi.soundindex ("world/trash2.wav"), 1, ATTN_NORM, 0);
				}
				else if (!strcmp(ent->classname, "props_crate"))
				{
					gi.sound (ent, CHAN_AUTO, gi.soundindex ("world/crate2.wav"), 1, ATTN_NORM, 0);
				}
			}
			// END JOSEPH

			// Fix if sitting off center
			ent->movetype = MOVETYPE_STEP;
			think_checkedges(ent);
		}
		// END JOSEPH
		return;
	}

	VectorCopy (ent->s.origin, old_origin);

	SV_CheckVelocity (ent);

// add gravity
	if (ent->movetype != MOVETYPE_FLY
	&& ent->movetype != MOVETYPE_FLYMISSILE)
		SV_AddGravity (ent);

// move angles
	VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);

// move origin
	VectorScale (ent->velocity, FRAMETIME, move);
	trace = SV_PushEntity (ent, move);
	if (!ent->inuse)
		return;

	if (trace.fraction < 1)
	{
		// RAFAEL
		if (ent->movetype == MOVETYPE_WALLBOUNCE)
			backoff = 2.0;
		// RAFAEL ( else )		
		else if (ent->movetype == MOVETYPE_BOUNCE)
			backoff = 1.5;
		// Ridah, testing
		else if (ent->velocity[2] > -120)
			backoff = 1;
		else
			backoff = 1.3;

		ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff);

    	// RAFAEL
		if (ent->movetype == MOVETYPE_WALLBOUNCE)
			vectoangles (ent->velocity, ent->s.angles);

	// stop if on ground
		// RAFAEL
		if (trace.plane.normal[2] > 0.7 && ent->movetype != MOVETYPE_WALLBOUNCE && ent->movetype != MOVETYPE_TOSS_SLIDE)	// Ridah, testing
		{		
			if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE )
			{
				ent->groundentity = trace.ent;
				ent->groundentity_linkcount = trace.ent->linkcount;
				VectorCopy (vec3_origin, ent->velocity);
				VectorCopy (vec3_origin, ent->avelocity);
			}
		}

		// Ridah, testing
		if (trace.plane.normal[2] > 0.0 && ent->movetype == MOVETYPE_TOSS_SLIDE)	// Ridah, testing
		{
			VectorMA( ent->velocity, -0.07, ent->velocity, ent->velocity );	// add some friction
			ent->velocity[2] += ent->gravity * sv_gravity->value * FRAMETIME * trace.plane.normal[2];
			if (trace.fraction <= 0.1)
			{
				float	oldpitch;

				oldpitch = ent->s.angles[PITCH];
				vectoangles (ent->velocity, ent->s.angles);
				ent->s.angles[PITCH] = oldpitch;

				VectorCopy (vec3_origin, ent->avelocity);
				ent->avelocity[PITCH] = -300 * VectorLength(ent->velocity)/800;	// roll in direction we're going

				SV_Physics_Toss(ent);
				return;
			}
		}

//		if (ent->touch)
//			ent->touch (ent, trace.ent, &trace.plane, trace.surface);
	}
	
	
// check for water transition
	wasinwater = (ent->watertype & MASK_WATER);
	ent->watertype = gi.pointcontents (ent->s.origin);
	isinwater = ent->watertype & MASK_WATER;

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

	// JOSEPH 13-MAY-99
	/*if (!wasinwater && isinwater)
		gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
	else if (wasinwater && !isinwater)
		gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);*/
	// END JOSEPH

// move teamslaves
	for (slave = ent->teamchain; slave; slave = slave->teamchain)
	{
		VectorCopy (ent->s.origin, slave->s.origin);
		gi.linkentity (slave);
	}
}
예제 #7
0
파일: g_phys.c 프로젝트: wafleh/vrxcl
/*
=============
SV_Physics_Toss

Toss, bounce, and fly movement.  When onground, do nothing.
=============
*/
void SV_Physics_Toss (edict_t *ent)
{
	trace_t		trace;
	vec3_t		move;
	float		backoff;
	edict_t		*slave;
	qboolean	wasinwater;
	qboolean	isinwater;
	vec3_t		old_origin;

	qboolean	forcethrough = false;

// regular thinking
	SV_RunThink (ent);

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

	if (ent->velocity[2] > 0)
		ent->groundentity = NULL;

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



// if onground, return without moving
	if (ent->groundentity)
	{
		V_TouchSolids(ent);
		return;
	}


	VectorCopy (ent->s.origin, old_origin);

	SV_CheckVelocity (ent);

// add gravity
	if (ent->movetype != MOVETYPE_FLY
	&& ent->movetype != MOVETYPE_FLYMISSILE
	&& ent->movetype != MOVETYPE_SLIDE
	// RAFAEL
	// move type for rippergun projectile
	&& ent->movetype != MOVETYPE_WALLBOUNCE)
		SV_AddGravity (ent);

// move angles
	VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);

// move origin
	VectorScale (ent->velocity, FRAMETIME, move);


	if(ent->classname[0] == 'R' && (ent->classname[6] == 'X' || ent->classname[6] == '3'))
	{
		ent->groundentity = ent->union_ent;
		ent->groundentity_linkcount = ent->union_ent->linkcount;
		VectorCopy (ent->union_ent->velocity, ent->velocity);
		VectorCopy (ent->union_ent->avelocity, ent->avelocity);

		VectorAdd(ent->union_ent->s.origin,ent->moveinfo.dir,ent->s.origin);
	}
	trace = SV_PushEntity (ent, move);

	if (!ent->inuse)
		return;
 

	if (trace.fraction < 1 && !forcethrough)
	{
		// RAFAEL
		if (ent->movetype == MOVETYPE_WALLBOUNCE)
			backoff = 2.0;
		// RAFAEL ( else )		
		else if (ent->movetype == MOVETYPE_BOUNCE)
			backoff = 1.5;
		else
			backoff = 1;

		ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff);
				
		// spikeball never stops bouncing
		if (ent->mtype == M_SPIKEBALL)
		{
			float delta = 275 - ent->velocity[2];

			// don't get stuck on the ceiling
			if (trace.plane.normal[2] != -1.0)
				ent->velocity[2] += delta;

			// always bounce away from the wall
			VectorMA(ent->velocity, 100, trace.plane.normal, ent->velocity);
		}

		// RAFAEL
		if (ent->movetype == MOVETYPE_WALLBOUNCE)
			vectoangles (ent->velocity, ent->s.angles);

	// stop if on ground
		// RAFAEL
		//K03 Begin
		if (trace.plane.normal[2] > 0.95 && ent->movetype != MOVETYPE_WALLBOUNCE && ent->movetype != MOVETYPE_SLIDE)//was 0.7
		{
			if (ent->velocity[2] < 30/*60*/ || ent->movetype != MOVETYPE_BOUNCE )
		//K03 End
			{
				//	gi.dprintf("SV_Physics_Toss() stopped the entity\n");	
				ent->groundentity = trace.ent;
				ent->groundentity_linkcount = trace.ent->linkcount;
				VectorCopy (vec3_origin, ent->velocity);
				VectorCopy (vec3_origin, ent->avelocity);
			}
		}

	//	if (ent->touch)
	//		ent->touch (ent, trace.ent, &trace.plane, trace.surface);
	}
	
// check for water transition
	wasinwater = (ent->watertype & MASK_WATER);
	ent->watertype = gi.pointcontents (ent->s.origin);
	isinwater = ent->watertype & MASK_WATER;

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

	if (!wasinwater && isinwater)
		gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
	else if (wasinwater && !isinwater)
		gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);

// move teamslaves
	for (slave = ent->teamchain; slave; slave = slave->teamchain)
	{
		VectorCopy (ent->s.origin, slave->s.origin);
		gi.linkentity (slave);
	}
}
예제 #8
0
/*
=============
SV_Physics_Toss

Toss, bounce, and fly movement.  When onground, do nothing.
=============
*/
void SV_Physics_Toss (edict_t *ent)
{
	trace_t	trace;
	vec3_t	move;
	float	backoff;
#ifdef QUAKE2
	edict_t	*groundentity;

	groundentity = PROG_TO_EDICT(ent->v.groundentity);
	if ((int)groundentity->v.flags & FL_CONVEYOR)
		VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity);
	else
		VectorCopy(vec_origin, ent->v.basevelocity);
	SV_CheckWater (ent);
#endif
	// regular thinking
	if (!SV_RunThink (ent))
		return;

#ifdef QUAKE2
	if (ent->v.velocity[2] > 0)
		ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;

	if ( ((int)ent->v.flags & FL_ONGROUND) )
//@@
		if (VectorCompare(ent->v.basevelocity, vec_origin))
			return;

	SV_CheckVelocity (ent);

// add gravity
	if (! ((int)ent->v.flags & FL_ONGROUND)
		&& ent->v.movetype != MOVETYPE_FLY
		&& ent->v.movetype != MOVETYPE_BOUNCEMISSILE
		&& ent->v.movetype != MOVETYPE_FLYMISSILE)
			SV_AddGravity (ent);

#else
// if onground, return without moving
	if ( ((int)ent->v.flags & FL_ONGROUND) )
		return;

	SV_CheckVelocity (ent);

// add gravity
	if (ent->v.movetype != MOVETYPE_FLY
	&& ent->v.movetype != MOVETYPE_FLYMISSILE)
		SV_AddGravity (ent);
#endif

// move angles
	VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);

// move origin
#ifdef QUAKE2
	VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
#endif
	VectorScale (ent->v.velocity, host_frametime, move);
	trace = SV_PushEntity (ent, move);
#ifdef QUAKE2
	VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
#endif
	if (trace.fraction == 1)
		return;
	if (ent->free)
		return;

	if (ent->v.movetype == MOVETYPE_BOUNCE)
		backoff = 1.5;
#ifdef QUAKE2
	else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
		backoff = 2.0;
#endif
	else
		backoff = 1;

	ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);

// stop if on ground
	if (trace.plane.normal[2] > 0.7)
	{
#ifdef QUAKE2
		if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
#else
		if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE)
#endif
		{
			ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
			ent->v.groundentity = EDICT_TO_PROG(trace.ent);
			VectorCopy (vec3_origin, ent->v.velocity);
			VectorCopy (vec3_origin, ent->v.avelocity);
		}
	}

// check for in water
	SV_CheckWaterTransition (ent);
}
예제 #9
0
파일: g_phys.c 프로젝트: basecq/q2dos
/*
================
SV_Physics_Pusher

Bmodel objects don't interact with each other, but
push all box objects
================
*/
void SV_Physics_Pusher (edict_t *ent)
{
	vec3_t move, amove;
	edict_t *part, *mv;

	if (!ent)
	{
		return;
	}

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

	/* 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;

	for (part = ent; part; part = part->teamchain)
	{
		if (part->velocity[0] || part->velocity[1] || part->velocity[2] ||
			part->avelocity[0] || part->avelocity[1] || part->avelocity[2])
		{
			/* object is moving */
			VectorScale(part->velocity, FRAMETIME, move);
			VectorScale(part->avelocity, FRAMETIME, amove);

			if (!SV_Push(part, move, amove))
			{
				break; /* move was blocked */
			}
		}
	}

	if (pushed_p > &pushed[MAX_EDICTS-1])
	{
		gi.error("pushed_p > &pushed[MAX_EDICTS-1], memory corrupted");
	}

	if (part)
	{
		/* the move failed, bump all nextthink times and back out moves */
		for (mv = ent; mv; mv = mv->teamchain)
		{
			if (mv->nextthink > 0)
			{
				mv->nextthink += FRAMETIME;
			}
		}

		/* if the pusher has a "blocked" function, call it
		   otherwise, just stay in place until the obstacle
		   is gone */
		if (part->blocked)
		{
			part->blocked(part, obstacle);
		}
	}
	else
	{
		// the move succeeded, so call all think functions
		for (part = ent ; part ; part=part->teamchain)
		{
			SV_RunThink (part);
		}
	}
}
예제 #10
0
파일: g_phys.c 프로젝트: wafleh/vrxcl
/*
================
SV_Physics_Pusher

Bmodel objects don't interact with each other, but
push all box objects
================
*/
void SV_Physics_Pusher (edict_t *ent)
{
	vec3_t		move, amove;
	edict_t		*part, *mv;

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

	// 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
//retry:
	pushed_p = pushed;
	for (part = ent ; part ; part=part->teamchain)
	{
		if (part->velocity[0] || part->velocity[1] || part->velocity[2] ||
			part->avelocity[0] || part->avelocity[1] || part->avelocity[2]
			)
		{	// object is moving
			VectorScale (part->velocity, FRAMETIME, move);
			VectorScale (part->avelocity, FRAMETIME, amove);

			if (!SV_Push (part, move, amove))
				break;	// move was blocked
		}
	}
	if (pushed_p > &pushed[MAX_EDICTS])
		gi.error (ERR_FATAL, "pushed_p > &pushed[MAX_EDICTS], memory corrupted");

	if (part)
	{
		// the move failed, bump all nextthink times and back out moves
		for (mv = ent ; mv ; mv=mv->teamchain)
		{
			if (mv->nextthink > 0)
				mv->nextthink += FRAMETIME;
		}

		// if the pusher has a "blocked" function, call it
		// otherwise, just stay in place until the obstacle is gone
		if (part->blocked)
		{
			part->blocked (part, obstacle);
		}

#if 0
		// if the pushed entity went away and the pusher is still there
		if (!obstacle->inuse && part->inuse)
			goto retry;
#endif
	}
	else
	{
		// the move succeeded, so call all think functions
		for (part = ent ; part ; part=part->teamchain)
		{
			SV_RunThink (part);
		}
	}
}
예제 #11
0
/*
=============
SV_Physics_Toss

Toss, bounce, and fly movement.  When onground, do nothing.
=============
*/
void SV_Physics_Toss (edict_t *ent)
{
	trace_t	trace;
	vec3_t	move;
	float	backoff;

	// regular thinking
	if (!SV_RunThink (ent))
		return;

// if onground, return without moving
	if (((int)ent->v.flags & FL_ONGROUND))
		return;

	SV_CheckVelocity (ent);

// add gravity
	if (ent->v.movetype != MOVETYPE_FLY && ent->v.movetype != MOVETYPE_FLYMISSILE)
#ifdef HEXEN2_SUPPORT
		if ( (!hexen2) || (ent->v.movetype != MOVETYPE_BOUNCEMISSILE && ent->v.movetype != MOVETYPE_SWIM))
#endif
			SV_AddGravity (ent);

// move anglesy
	VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);

// move origin
	VectorScale (ent->v.velocity, host_frametime, move);
	trace = SV_PushEntity (ent, move);
	if (trace.fraction == 1)
		return;
	if (ent->free)
		return;
	
	if (ent->v.movetype == MOVETYPE_BOUNCE)
		backoff = 1.5;
#ifdef HEXEN2_SUPPORT
	else if (hexen2 && (ent->v.movetype == MOVETYPE_BOUNCEMISSILE))
	{	
		if ((ent->v.solid == SOLID_PHASE) && 
			(((int) trace.ent->v.flags & FL_MONSTER) || ((int) trace.ent->v.movetype == MOVETYPE_WALK)))
		{
			return;		// Solid phased missiles don't bounce on monsters or players
		}
		backoff = 2.0;
	}
#endif
	else
		backoff = 1;

	ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);

// stop if on ground
	if (trace.plane.normal[2] > 0.7)
	{		
#ifdef HEXEN2_SUPPORT
		if ((!hexen2) || (ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
#endif
		if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE)
		{
			ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
			ent->v.groundentity = EDICT_TO_PROG(trace.ent);
			VectorCopy (vec3_origin, ent->v.velocity);
			VectorCopy (vec3_origin, ent->v.avelocity);
		}
	}
	
// check for in water
	SV_CheckWaterTransition (ent);
}
예제 #12
0
/*
================
SV_Physics_Client

Player character actions
================
*/
void SV_Physics_Client (edict_t	*ent, int num)
{
	client_t	*cl;
	vec3_t		v;
	qboolean	was_angle_set;
	
	cl = &svs.clients[num-1];
	if (!cl->active)
		return;		// unconnected slot

// call standard client pre-think
	PR_GLOBAL(time) = sv.time;
	PR_GLOBAL(self) = EDICT_TO_PROG(ent);
	PR_ExecuteProgram (PR_GLOBAL(PlayerPreThink));
	
	// for cutscene hack (see below)
	if (isDedicated || (num != 1))
		was_angle_set = false;		// do it on local client only
	else
		was_angle_set = (ent->v.fixangle != 0);
	
// do a move
	SV_CheckVelocity (ent);

// decide which move function to call
	switch ((int)ent->v.movetype)
	{
	case MOVETYPE_NONE:
		if (!SV_RunThink(ent))
			return;
		break;

	case MOVETYPE_WALK:
		if (!SV_RunThink(ent))
			return;
		if (!SV_CheckWater(ent) && !((int)ent->v.flags & FL_WATERJUMP))
			SV_AddGravity (ent);
		SV_CheckStuck (ent);
		SV_WalkMove (ent);

		break;
		
	case MOVETYPE_TOSS:
	case MOVETYPE_BOUNCE:
		SV_Physics_Toss (ent);
		break;

	case MOVETYPE_FLY:
#ifdef HEXEN2_SUPPORT
	case MOVETYPE_SWIM:
#endif
		if (!SV_RunThink(ent))
			return;
		SV_FlyMove (ent, host_frametime, NULL);
		break;
		
	case MOVETYPE_NOCLIP:
		if (!SV_RunThink(ent))
			return;
		VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
		break;
		
	default:
		Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
	}


	// JDH: hack for cutscenes made by Darin McNeil's Cutscene Construction Kit:
	//  (note that the extra precision is noticeable only if the viewangles 
	//  are sent from server to client as 2-byte values; hence the addition 
	//  of the new svc_setpreciseangle message code)

	if (was_angle_set && (ent->v.view_ofs[2] == 0) && host_cutscenehack.value 
		&& !strcmp (pr_strings + ent->v.classname, "camera"))
	{
		// - when camera changes back to player, classname remains "camera" for
		//   1 frame, but movedir is no longer valid.  So as an  additional check, 
		//   I verify that view_ofs[2] is still 0
		// - early version(s?) of Cutscene Construction Kit don't move the camera, 
		//   so movedir is not used.  I determine the version by checking *when* 
		//   the viewangle is set: early version does it in the .think function; 
		//   later ones in PlayerPreThink.	was_angle_set will be true only if
		//   it was changed in PlayerPreThink
		
		//if (!sv_oldprotocol.value)
		{
			v[0] = ent->v.movedir[0] - ent->v.origin[0];
			v[1] = ent->v.movedir[1] - ent->v.origin[1];
			v[2] = ent->v.origin[2] - ent->v.movedir[2];
			//vectoangles (v, ent->v.angles);
			vectoangles (v, cl->cutscene_viewangles);
		}
		
		if (!cl->in_cutscene)
		{
			int i;
			edict_t *ed;
			
			// by this time, the player's viewangles have already been changed.
			// But the dummy entity spawned in place of the player has the values
			
			for (i = 1 ; i < sv.num_edicts ; i++)
			{
			// get the current server version
				ed = EDICT_NUM(i);
				if (ed->free)
					continue;

				if (!strcmp(pr_strings + ed->v.classname, "dummy"))
				{
					VectorCopy (ed->v.angles, cl->prev_viewangles);
					break;
				}
			}

			cl->in_cutscene = true;
		}
		//sv.found_cutscene = true;
	}
	else 
	{
		if (cl->in_cutscene)
		{
		// I'm not sure why, but last viewangle while in_cutscene isn't final angle
			ent->v.fixangle = 1;
			VectorCopy (cl->prev_viewangles, ent->v.angles);
			cl->in_cutscene = false;
		}
	}
	
	SV_LinkEdict (ent, true);
	
	PR_GLOBAL(time) = sv.time;
	PR_GLOBAL(self) = EDICT_TO_PROG(ent);

// JDH: another hack, this time for progs that lack CycleWeaponReverse
	if ((ent->v.impulse == 12.0) && ((sv_imp12hack.value >= 2) || (sv_imp12hack.value && !pr_handles_imp12)) && 
		!ent->v.deadflag && (ent->v.view_ofs[0] || ent->v.view_ofs[1] || ent->v.view_ofs[2]))
	{
		eval_t  *val = GETEDICTFIELD(ent, eval_attack_finished);
		if (val && (sv.time >= val->_float))
		{
			SV_CycleWeaponReverse (ent);
		}
	}

// call standard player post-think
	PR_ExecuteProgram (PR_GLOBAL(PlayerPostThink));
}
예제 #13
0
/*
================
SV_Physics

================
*/
void SV_Physics (void)
{
	int	i;
	int		entity_cap; // For sv_freezenonclients
	edict_t	*ent;

// let the progs know that a new frame has started
	pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
	pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
	pr_global_struct->time = sv.time;
	PR_ExecuteProgram (pr_global_struct->StartFrame);

//SV_CheckAllEnts ();

//
// treat each object in turn
//
	ent = sv.edicts;
	if (sv.frozen)
		entity_cap = svs.maxclients + 1; // Only run physics on clients and the world
	else
		entity_cap = sv.num_edicts;

	for (i=0 ; i<entity_cap ; i++, ent = NEXT_EDICT(ent))
//	for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
	{
		if (ent->free)
			continue;

		if (pr_global_struct->force_retouch)
		{
			SV_LinkEdict (ent, true);	// force retouch even for stationary
		}

		if (i > 0 && i <= svs.maxclients)
			SV_Physics_Client (ent, i);
		else if (ent->v.movetype == MOVETYPE_PUSH)
			SV_Physics_Pusher (ent);
		else if (ent->v.movetype == MOVETYPE_NONE)
			SV_Physics_None (ent);
		else if (ent->v.movetype == MOVETYPE_FOLLOW) // Nehahra
			SV_Physics_Follow (ent);
		else if (ent->v.movetype == MOVETYPE_NOCLIP)
			SV_Physics_Noclip (ent);
		else if (ent->v.movetype == MOVETYPE_STEP)
			SV_Physics_Step (ent);
		else if (ent->v.movetype == MOVETYPE_WALK) // Nehahra
		{
			if (!SV_RunThink (ent))
				return;
			if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
				SV_AddGravity (ent);
			SV_CheckStuck (ent);
			SV_WalkMove (ent);
		}
		else if (ent->v.movetype == MOVETYPE_TOSS 
		|| ent->v.movetype == MOVETYPE_BOUNCE
		|| ent->v.movetype == MOVETYPE_FLY
		|| ent->v.movetype == MOVETYPE_FLYMISSILE)
			SV_Physics_Toss (ent);
		else
			Host_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);			
	}
	
	if (pr_global_struct->force_retouch)
		pr_global_struct->force_retouch--;	

	if (!sv.frozen)
		sv.time += host_frametime;
}
예제 #14
0
파일: sv_phys.c 프로젝트: THE-Swank/xash3d
/*
=============
SV_PhysicsNone

Non moving objects can only think
=============
*/
void SV_Physics_None( edict_t *ent )
{
	SV_RunThink( ent );
}
예제 #15
0
파일: g_phys.c 프로젝트: wafleh/vrxcl
void SV_Physics_Step (edict_t *ent)
{
	qboolean	wasonground;
	qboolean	hitsound = false;
	float		*vel;
	float		speed, newspeed, control;
	float		friction;
	edict_t		*groundentity;
	int			mask;
//	vec3_t		dir;


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

	groundentity = ent->groundentity;

	SV_CheckVelocity (ent);

	if (groundentity)
		wasonground = true;
	else
		wasonground = false;
		
//	if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2])
//		SV_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[2] < sv_gravity->value*-0.1)
					hitsound = true;
				if (ent->waterlevel == 0)
					SV_AddGravity (ent);
			}

	// friction for flying monsters that have been given vertical velocity
	if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0))
	{
//gi.bprintf(PRINT_HIGH,"FLY!\n");
		speed = fabs(ent->velocity[2]);
		control = speed < sv_stopspeed ? sv_stopspeed : speed;
		friction = sv_friction/3;
		newspeed = speed - (FRAMETIME * control * friction);
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		ent->velocity[2] *= newspeed;
	}

	// friction for flying monsters that have been given vertical velocity
	if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0))
	{
//gi.bprintf(PRINT_HIGH,"SWIM!\n");
		//K03 Begin
		float water_friction;
		//K03 End
		speed = fabs(ent->velocity[2]);
		control = speed < sv_stopspeed ? sv_stopspeed : speed;
		//K03 Begin
		water_friction=(FRAMETIME * control * sv_waterfriction * ent->waterlevel);
		//newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel);
		if ((ent->myskills.abilities[SUPER_SPEED].current_level < 1) || (ent->myskills.abilities[SUPER_SPEED].disable))
			newspeed = speed;
		else
			newspeed = speed - water_friction;
		//K03 End
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		ent->velocity[2] *= newspeed;
	}

	if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0])
	{
		// 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)))
			{
				//K03 Begin
				float water_friction;
				//K03 End
				vel = ent->velocity;
				speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
				if (speed)
				{
					friction = sv_friction;

					control = speed < sv_stopspeed ? sv_stopspeed : speed;
					newspeed = speed - FRAMETIME*control*friction;
					//K03 Begin
					water_friction=FRAMETIME*control*friction;
					//newspeed = speed - FRAMETIME*control*friction;
					if ( ((ent->myskills.abilities[SUPER_SPEED].current_level < 1) || (ent->myskills.abilities[SUPER_SPEED].disable))
						&& !(ent->flags & FL_SWIM))
						newspeed = speed;
					else
						newspeed = speed - water_friction;
					//K03 End

					if (newspeed < 0)
						newspeed = 0;
					newspeed /= speed;

					vel[0] *= newspeed;
					vel[1] *= newspeed;
				}
			}

		if (ent->svflags & SVF_MONSTER)
		{
			if(!deathmatch->value) mask = MASK_MONSTERSOLID;
			else mask = MASK_BOTSOLIDX;//MASK_PLAYERSOLID;
		}
		else
			mask = MASK_SOLID;
		//FIXME: warning - SV_FlyMove() can cause an entity to be freed
		SV_FlyMove (ent, FRAMETIME, mask);

		gi.linkentity (ent);
//		G_TouchTriggers (ent);
	}
	else
		V_TouchSolids(ent);

// regular thinking
	SV_RunThink (ent); 
}
예제 #16
0
/*
================
SV_Physics_Client

Player character actions
================
*/
void SV_Physics_Client (edict_t	*ent, int num)
{
	if ( ! svs.clients[num-1].active )
		return;		// unconnected slot

//
// call standard client pre-think
//
	pr_global_struct->time = sv.time;
	pr_global_struct->self = EDICT_TO_PROG(ent);
	PR_ExecuteProgram (pr_global_struct->PlayerPreThink);

//
// do a move
//
	SV_CheckVelocity (ent);

//
// decide which move function to call
//
	switch ((int)ent->v.movetype)
	{
	case MOVETYPE_NONE:
		if (!SV_RunThink (ent))
			return;
		break;

	case MOVETYPE_WALK:
		if (!SV_RunThink (ent))
			return;
		if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
			SV_AddGravity (ent);
		SV_CheckStuck (ent);
#ifdef QUAKE2
		VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
#endif
		SV_WalkMove (ent);

#ifdef QUAKE2
		VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
#endif
		break;

	case MOVETYPE_TOSS:
	case MOVETYPE_BOUNCE:
		SV_Physics_Toss (ent);
		break;

	case MOVETYPE_FLY:
		if (!SV_RunThink (ent))
			return;
		SV_FlyMove (ent, host_frametime, NULL);
		break;

	case MOVETYPE_NOCLIP:
		if (!SV_RunThink (ent))
			return;
		VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
		break;

	default:
		Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
	}

//
// call standard player post-think
//
	SV_LinkEdict (ent, true);

	pr_global_struct->time = sv.time;
	pr_global_struct->self = EDICT_TO_PROG(ent);
	PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
}
예제 #17
0
/*
===========
SV_RunCmd
===========
*/
static void SV_RunCmd (usercmd_t *ucmd)
{
	edict_t		*ent;
	int			i, n;
	int			oldmsec;

	cmd = *ucmd;

	// chop up very long commands
	if (cmd.msec > 50)
	{
		oldmsec = ucmd->msec;
		cmd.msec = oldmsec/2;
		SV_RunCmd (&cmd);
		cmd.msec = oldmsec/2;
		cmd.impulse = 0;
		SV_RunCmd (&cmd);
		return;
	}

	if (!sv_player->v.fixangle)
		VectorCopy (ucmd->angles, sv_player->v.v_angle);

	sv_player->v.button0 = ucmd->buttons & 1;
	sv_player->v.button2 = (ucmd->buttons & 2)>>1;

	if (ucmd->buttons & 4 || sv_player->v.playerclass == CLASS_DWARF) // crouched?
		sv_player->v.flags2 = ((int)sv_player->v.flags2) | FL2_CROUCHED;
	else
		sv_player->v.flags2 = ((int)sv_player->v.flags2) & (~FL2_CROUCHED);

	if (ucmd->impulse)
		sv_player->v.impulse = ucmd->impulse;

//
// angles
// show 1/3 the pitch angle and all the roll angle
	if (sv_player->v.health > 0)
	{
		if (!sv_player->v.fixangle)
		{
			sv_player->v.angles[PITCH] = -sv_player->v.v_angle[PITCH]/3;
			sv_player->v.angles[YAW] = sv_player->v.v_angle[YAW];
		}
		sv_player->v.angles[ROLL] = 
				V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;
	}

	host_frametime = ucmd->msec * 0.001;
	if (host_frametime > HX_FRAME_TIME)
		host_frametime = HX_FRAME_TIME;

	if (!host_client->spectator)
	{
		pr_global_struct->frametime = host_frametime;

		pr_global_struct->time = sv.time;
		pr_global_struct->self = EDICT_TO_PROG(sv_player);
		PR_ExecuteProgram (pr_global_struct->PlayerPreThink);

		SV_RunThink (sv_player);
	}

	for (i = 0; i < 3; i++)
		pmove.origin[i] = sv_player->v.origin[i] + (sv_player->v.mins[i] - player_mins[i]);

	VectorCopy (sv_player->v.velocity, pmove.velocity);
	VectorCopy (sv_player->v.v_angle, pmove.angles);

	pmove.spectator = host_client->spectator;
//	pmove.waterjumptime = sv_player->v.teleport_time;
	pmove.numphysent = 1;
	pmove.physents[0].model = sv.worldmodel;
	pmove.cmd = *ucmd;
	pmove.dead = sv_player->v.health <= 0;
	pmove.oldbuttons = host_client->oldbuttons;
	pmove.hasted = sv_player->v.hasted;
	pmove.movetype = sv_player->v.movetype;
	pmove.crouched = (sv_player->v.hull == HULL_CROUCH);
	pmove.teleport_time = realtime + (sv_player->v.teleport_time - sv.time);

//	movevars.entgravity = host_client->entgravity;
	movevars.entgravity = sv_player->v.gravity;
	movevars.maxspeed = host_client->maxspeed;

	for (i = 0; i < 3; i++)
	{
		pmove_mins[i] = pmove.origin[i] - 256;
		pmove_maxs[i] = pmove.origin[i] + 256;
	}
#if 1
	AddLinksToPmove ( sv_areanodes );
#else
	AddAllEntsToPmove ();
#endif

#if 0
	{
		int	before, after;

		before = PM_TestPlayerPosition (pmove.origin);
		PlayerMove ();
		after = PM_TestPlayerPosition (pmove.origin);

		if (sv_player->v.health > 0 && before && !after )
			Con_Printf ("player %s got stuck in playermove!!!!\n", host_client->name);
	}
#else
	PlayerMove ();
#endif

	host_client->oldbuttons = pmove.oldbuttons;
//	sv_player->v.teleport_time = pmove.waterjumptime;
	sv_player->v.waterlevel = waterlevel;
	sv_player->v.watertype = watertype;
	if (onground != -1)
	{
		sv_player->v.flags = (int)sv_player->v.flags | FL_ONGROUND;
		sv_player->v.groundentity = EDICT_TO_PROG(EDICT_NUM(pmove.physents[onground].info));
	}
	else
		sv_player->v.flags = (int)sv_player->v.flags & ~FL_ONGROUND;

	for (i = 0; i < 3; i++)
		sv_player->v.origin[i] = pmove.origin[i] - (sv_player->v.mins[i] - player_mins[i]);

#if 0
	// truncate velocity the same way the net protocol will
	for (i = 0; i < 3; i++)
		sv_player->v.velocity[i] = (int)pmove.velocity[i];
#else
	VectorCopy (pmove.velocity, sv_player->v.velocity);
#endif

	VectorCopy (pmove.angles, sv_player->v.v_angle);

	if (!host_client->spectator)
	{
		// link into place and touch triggers
		SV_LinkEdict (sv_player, true);

		// touch other objects
		for (i = 0; i < pmove.numtouch; i++)
		{
			n = pmove.physents[pmove.touchindex[i]].info;
			ent = EDICT_NUM(n);

		// Why not just do an SV_Impact here?
		//	SV_Impact(sv_player,ent);

			if (sv_player->v.touch)
			{
				pr_global_struct->self = EDICT_TO_PROG(sv_player);
				pr_global_struct->other = EDICT_TO_PROG(ent);
				PR_ExecuteProgram (sv_player->v.touch);
			}
			if (!ent->v.touch || (playertouch[n/8]&(1<<(n%8))))
				continue;
			pr_global_struct->self = EDICT_TO_PROG(ent);
			pr_global_struct->other = EDICT_TO_PROG(sv_player);
			PR_ExecuteProgram (ent->v.touch);
			playertouch[n/8] |= 1 << (n%8);
		}
	}
}
예제 #18
0
void SV_Physics_Step (edict_t *ent)
{
	qboolean	wasonground;
	qboolean	inwater;
	qboolean	hitsound = false;
	float		*vel;
	float		speed, newspeed, control;
	float		friction;
	edict_t		*groundentity;

	groundentity = PROG_TO_EDICT(ent->v.groundentity);
	if ((int)groundentity->v.flags & FL_CONVEYOR)
		VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity);
	else
		VectorCopy(vec_origin, ent->v.basevelocity);
//@@
	pr_global_struct->time = sv.time;
	pr_global_struct->self = EDICT_TO_PROG(ent);
	PF_WaterMove();

	SV_CheckVelocity (ent);

	wasonground = (int)ent->v.flags & FL_ONGROUND;
//	ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;

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

	if (!VectorCompare(ent->v.velocity, vec_origin) || !VectorCompare(ent->v.basevelocity, vec_origin))
	{
		ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
		// apply friction
		// let dead monsters who aren't completely onground slide
		if (wasonground)
			if (!(ent->v.health <= 0.0 && !SV_CheckBottom(ent)))
			{
				vel = ent->v.velocity;
				speed = sqrtf(vel[0]*vel[0] +vel[1]*vel[1]);
				if (speed)
				{
					friction = sv_friction.value;

					control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
					newspeed = speed - host_frametime*control*friction;

					if (newspeed < 0)
						newspeed = 0;
					newspeed /= speed;

					vel[0] = vel[0] * newspeed;
					vel[1] = vel[1] * newspeed;
				}
			}

		VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
		SV_FlyMove (ent, host_frametime, NULL);
		VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);

		// determine if it's on solid ground at all
		{
			vec3_t	mins, maxs, point;
			int		x, y;

			VectorAdd (ent->v.origin, ent->v.mins, mins);
			VectorAdd (ent->v.origin, ent->v.maxs, maxs);

			point[2] = mins[2] - 1;
			for	(x=0 ; x<=1 ; x++)
				for	(y=0 ; y<=1 ; y++)
				{
					point[0] = x ? maxs[0] : mins[0];
					point[1] = y ? maxs[1] : mins[1];
					if (SV_PointContents (point) == CONTENTS_SOLID)
					{
						ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
						break;
					}
				}

		}

		SV_LinkEdict (ent, true);

		if ((int)ent->v.flags & FL_ONGROUND)
			if (!wasonground)
				if (hitsound)
					SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
	}

// regular thinking
	SV_RunThink (ent);
	SV_CheckWaterTransition (ent);
}
예제 #19
0
void
SV_Physics_Bounce (edict_t * ent)
{
  trace_t trace;
  vec3_t move, planeVel, normalVel, temp;
  edict_t *slave;
  qboolean wasinwater;
  qboolean isinwater;
  vec3_t old_origin;
  float movetime;

// regular thinking 
  SV_RunThink (ent);
  if (!ent->inuse)
    return;

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

  if (ent->velocity[2] > 0)
    ent->groundentity = NULL;
// check for the groundentity going away 
  if (ent->groundentity)
    if (!ent->groundentity->inuse)
      ent->groundentity = NULL;
// if onground, return without moving 
  if (ent->groundentity)
    return;
  VectorCopy (ent->s.origin, old_origin);
  SV_CheckVelocity (ent);

  // move angles 
  VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);

  // add gravity 
  ent->velocity[2] -= ent->gravity * sv_gravity->value * FRAMETIME;
  movetime = FRAMETIME;
  while (movetime > 0)
    {
      // move origin 
      VectorScale (ent->velocity, movetime, move);
      // do the move (checking to see if we hit anything) 
      trace = SV_PushEntity (ent, move);
      // SV_PushEntity might have called touch() functions so its possible we disappeared 
      if (!ent->inuse)
	return;
      // we hit something so calculate rebound velocity etc. 
      if (trace.fraction < 1)
	{
	  // find component of velocity in direction of normal 
	  VectorScale (trace.plane.normal,
		       DotProduct (trace.plane.normal, ent->velocity),
		       normalVel);
	  // find component of velocity parallel to plane of impact 
	  VectorSubtract (ent->velocity, normalVel, planeVel);
	  // apply friction (lose 25% of velocity parallel to impact plane) 
	  VectorScale (planeVel, 0.75, planeVel);
	  // calculate final velocity (rebound with 60% of impact velocity) 
	  // negative since rebound causes direction reversal 
	  VectorMA (planeVel, -0.6, normalVel, ent->velocity);
	  // stop if on ground 
	  // only consider stopping if impact plane is less than 45 degrees with respect to horizontal 
	  // arccos(0.7) ~ 45 degrees 
	  if (trace.plane.normal[2] > 0.7)
	    {
	      VectorCopy (ent->velocity, temp);
	      // zero out z component (vertical) since we want to consider horizontal and vertical motion
//                              separately 
	      temp[2] = 0;
	      if ((VectorLength (temp) < 20)
		  && (ent->velocity[2] <
		      ent->gravity * sv_gravity->value * FRAMETIME * 1.5))
		{
		  ent->groundentity = trace.ent;
		  ent->groundentity_linkcount = trace.ent->linkcount;
		  VectorCopy (vec3_origin, ent->velocity);
		  VectorCopy (vec3_origin, ent->avelocity);
		  break;	// stopped, so no further simulation is necessary 
		}
	    }
	}
      // remaining amount of FRAMETIME left to simulate 
      movetime *= (1.0 - trace.fraction);
    }

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

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

  if (!wasinwater && isinwater)
    gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO,
			 gi.soundindex ("misc/h2ohit1.wav"), 1, 1, 0);
  else if (wasinwater && !isinwater)
    gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO,
			 gi.soundindex ("misc/h2ohit1.wav"), 1, 1, 0);

  // move teamslaves 
  for (slave = ent->teamchain; slave; slave = slave->teamchain)
    {
      VectorCopy (ent->s.origin, slave->s.origin);
      gi.linkentity (slave);
    }
}
예제 #20
0
/*
================
SV_Physics_Pusher

Bmodel objects don't interact with each other, but
push all box objects
================
*/
void SV_Physics_Pusher (edict_t *ent)
{
	vec3_t		move, amove;
	edict_t		*part, *mv;

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

	// 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
//retry:
	pushed_p = pushed;
	for (part = ent ; part ; part=part->teamchain)
	{
		if (part->velocity[0] || part->velocity[1] || part->velocity[2] ||
			part->avelocity[0] || part->avelocity[1] || part->avelocity[2]
			)
		{	// object is moving
			VectorScale (part->velocity, FRAMETIME, move);
			VectorScale (part->avelocity, FRAMETIME, amove);

			// JOSEPH 5-APR-99
			if (!SV_Push (part, move, amove))
				break;	// move was blocked
			// END JOSEPH
		}
	}
	if (pushed_p > &pushed[MAX_EDICTS])
		gi.error (ERR_FATAL, "pushed_p > &pushed[MAX_EDICTS], memory corrupted");

	if (part)
	{
		// the move failed, bump all nextthink times and back out moves
		for (mv = ent ; mv ; mv=mv->teamchain)
		{
			if (mv->nextthink > 0)
				mv->nextthink += FRAMETIME;
		}

		// if the pusher has a "blocked" function, call it
		// otherwise, just stay in place until the obstacle is gone
		if (part->blocked)
			part->blocked (part, obstacle);
#if 0
		// if the pushed entity went away and the pusher is still there
		if (!obstacle->inuse && part->inuse)
			goto retry;
#endif
	}
	else
	{
		// the move succeeded, so call all think functions
		for (part = ent ; part ; part=part->teamchain)
		{
			SV_RunThink (part);
		}
	}

	// JOSEPH 28-APR-99
	if (ent->classname)
	{
		if (!strcmp(ent->classname, "func_button"))
		{
			int i;
			edict_t	*e = NULL;
			
			for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++)
			{
				if ((e->classname) && (!strcmp(e->classname, "func_lift")) &&
					(e->target2) && (ent->target2) && (!strcmp(e->target2, ent->target2)))
				{
					ent->s.origin[2] = e->s.origin[2] + ent->handleflag;
				}
			}
		}
		else if	(!strcmp(ent->classname, "func_lift"))
		{
			int i;
			edict_t	*e = NULL;
			
			for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++)
			{
				if ((e->classname) && (!strcmp(e->classname, "func_button")) &&
					(e->target2) && (ent->target2) && (!strcmp(e->target2, ent->target2)))
				{
					e->s.origin[2] = ent->s.origin[2] + e->handleflag;
				}
			}
		}
	}
	// END JOSEPH
}
예제 #21
0
/*
=============
SV_Physics_Toss

Toss, bounce, and fly movement.  When onground, do nothing.
=============
*/
void
SV_Physics_Toss (edict_t * ent)
{
  trace_t trace;
  vec3_t move;
  float backoff;
  edict_t *slave;
  qboolean wasinwater;
  qboolean isinwater;
  vec3_t old_origin;

// regular thinking
  SV_RunThink (ent);

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

  if (ent->velocity[2] > 0)
    ent->groundentity = NULL;

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

// if onground, return without moving
  if (ent->groundentity)
    return;

  VectorCopy (ent->s.origin, old_origin);

  SV_CheckVelocity (ent);

// add gravity
  if (ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE)
    SV_AddGravity (ent);

// move angles
  VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);

// move origin
  VectorScale (ent->velocity, FRAMETIME, move);
  trace = SV_PushEntity (ent, move);
  if (!ent->inuse)
    return;

  // zucc added from action to cause blood splatters
  if (trace.fraction < 1 && ent->movetype == MOVETYPE_BLOOD)
    {
      if (!ent->splatted)
	{
	  AddSplat (ent->owner, ent->s.origin, &trace);
	  ent->splatted = true;
	}

      return;
    }



  if (trace.fraction < 1)
    {
      if (ent->movetype == MOVETYPE_BOUNCE)
	backoff = 1.4;		// 1.5 is normal  -Zucc/FB
      else
	backoff = 1;

      ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity,
		    backoff);

      // stop if on ground
      if (trace.plane.normal[2] > 0.7)
	{
	  // zucc moved velocity check down from 60
	  if (ent->velocity[2] < 10 || ent->movetype != MOVETYPE_BOUNCE)
	    {
	      ent->groundentity = trace.ent;
	      ent->groundentity_linkcount = trace.ent->linkcount;
	      VectorCopy (vec3_origin, ent->velocity);
	      VectorCopy (vec3_origin, ent->avelocity);
	    }
	}

//              if (ent->touch)
//                      ent->touch (ent, trace.ent, &trace.plane, trace.surface);
    }

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

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

  if (!wasinwater && isinwater)
    gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO,
			 gi.soundindex ("misc/h2ohit1.wav"), 1, 1, 0);
  else if (wasinwater && !isinwater)
    gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO,
			 gi.soundindex ("misc/h2ohit1.wav"), 1, 1, 0);

// move teamslaves
  for (slave = ent->teamchain; slave; slave = slave->teamchain)
    {
      VectorCopy (ent->s.origin, slave->s.origin);
      gi.linkentity (slave);
    }
}
예제 #22
0
파일: g_phys.c 프로젝트: ZwS/qudos
/*
 * ================ G_RunEntity ================
 */
void
G_RunEntity(edict_t * ent)
{
	//PGM
	trace_t	trace;
	vec3_t	previous_origin;

	if(ent->movetype == MOVETYPE_STEP)
		VectorCopy(ent->s.origin, previous_origin);
	//PGM

	if (ent->prethink)
		ent->prethink(ent);

	switch ((int)ent->movetype) {
#ifdef WITH_ACEBOT
		/* ACEBOT_ADD */
		case MOVETYPE_WALK:
			SV_RunThink(ent);
			break;
		/* ACEBOT_END */
#endif
		case MOVETYPE_PUSH:
		case MOVETYPE_STOP:
			SV_Physics_Pusher(ent);
			break;
		case MOVETYPE_NONE:
			SV_Physics_None(ent);
			break;
		case MOVETYPE_NOCLIP:
			SV_Physics_Noclip(ent);
			break;
		case MOVETYPE_STEP:
			SV_Physics_Step(ent);
			break;
		case MOVETYPE_TOSS:
		case MOVETYPE_BOUNCE:
		case MOVETYPE_FLY:
		case MOVETYPE_FLYMISSILE:
			SV_Physics_Toss(ent);
			break;
		case MOVETYPE_NEWTOSS:
			SV_Physics_NewToss (ent);
			break;
		default:
			gi.error("SV_Physics: bad movetype %i", (int)ent->movetype);
	}
	
	//PGM
	if(ent->movetype == MOVETYPE_STEP)
	{
		// if we moved, check and fix origin if needed
		if (!VectorCompare(ent->s.origin, previous_origin))
		{
			trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, previous_origin, ent, MASK_MONSTERSOLID);
			if(trace.allsolid || trace.startsolid)
				VectorCopy (previous_origin, ent->s.origin);
		}
	}
	//PGM
}
예제 #23
0
파일: sv_phys.c 프로젝트: THE-Swank/xash3d
/*
=============
SV_Physics_Compound

a glue two entities together
=============
*/
void SV_Physics_Compound( edict_t *ent )
{
	edict_t	*parent;
	
	// regular thinking
	if( !SV_RunThink( ent )) return;

	parent = ent->v.aiment;

	if( !SV_IsValidEdict( parent ))
	{
		MsgDev( D_ERROR, "%s have MOVETYPE_COMPOUND with no corresponding ent!", SV_ClassName( ent ));
		ent->v.movetype = MOVETYPE_NONE;
		return;
	}

	if( ent->v.solid != SOLID_TRIGGER )
		ent->v.solid = SOLID_NOT;

	switch( parent->v.movetype )
	{
	case MOVETYPE_PUSH:
	case MOVETYPE_PUSHSTEP:
		break;
	default: return;
	}

	// not initialized ?
	if( ent->v.ltime == 0.0f )
	{
		VectorCopy( parent->v.origin, ent->v.oldorigin );
		VectorCopy( parent->v.angles, ent->v.avelocity );
		ent->v.ltime = host.frametime;
		return;
	}

	if( !VectorCompare( parent->v.origin, ent->v.oldorigin ) || !VectorCompare( parent->v.angles, ent->v.avelocity ))
	{
		matrix4x4	start_l, end_l, temp_l, child;

		// create parent old position
		Matrix4x4_CreateFromEntity( temp_l, ent->v.avelocity, ent->v.oldorigin, 1.0f );
		Matrix4x4_Invert_Simple( start_l, temp_l );

		// create parent actual position
		Matrix4x4_CreateFromEntity( end_l, parent->v.angles, parent->v.origin, 1.0f );

		// stupid quake bug!!!
		if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG ))
			ent->v.angles[PITCH] = -ent->v.angles[PITCH];

		// create child actual position
		Matrix4x4_CreateFromEntity( child, ent->v.angles, ent->v.origin, 1.0f );

		// transform child from start to end
		Matrix4x4_ConcatTransforms( temp_l, start_l, child );
		Matrix4x4_ConcatTransforms( child, end_l, temp_l );

		// create child final position
		Matrix4x4_ConvertToEntity( child, ent->v.angles, ent->v.origin );

		// stupid quake bug!!!
		if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG ))
			ent->v.angles[PITCH] = -ent->v.angles[PITCH];
	}

	// notsolid ents never touch triggers
	SV_LinkEdict( ent, (ent->v.solid == SOLID_NOT) ? false : true );

	// shuffle states
	VectorCopy( parent->v.origin, ent->v.oldorigin );
	VectorCopy( parent->v.angles, ent->v.avelocity );
}
예제 #24
0
파일: g_phys.c 프로젝트: ZwS/qudos
void
SV_Physics_Step(edict_t * ent)
{
	qboolean	wasonground;
	qboolean	hitsound = false;
	float       	*vel;
	float		speed, newspeed, control;
	float		friction;
	edict_t    	*groundentity;
	int		mask;

	if (!ent)
		return;
	
	/* airborn monsters should always check for ground */
	if (!ent->groundentity)
		M_CheckGround(ent);

	groundentity = ent->groundentity;

	SV_CheckVelocity(ent);

	if (groundentity)
		wasonground = true;
	else
		wasonground = false;

	if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2])
		SV_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[2] < sv_gravity->value * -0.1)
					hitsound = true;
				if (ent->waterlevel == 0)
					SV_AddGravity(ent);
			}

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

	/* friction for flying monsters that have been given vertical velocity */
	if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0))
	{
		speed = fabs(ent->velocity[2]);
		control = speed < sv_stopspeed ? sv_stopspeed : speed;
		newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel);
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		ent->velocity[2] *= newspeed;
	}
	if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0])
	{
		/* 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;
				speed = sqrt(vel[0] * vel[0] + vel[1] * vel[1]);
				if (speed)
				{
					friction = sv_friction;

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

					if (newspeed < 0)
						newspeed = 0;
					newspeed /= speed;

					vel[0] *= newspeed;
					vel[1] *= newspeed;
				}
			}
		if (ent->svflags & SVF_MONSTER)
			mask = MASK_MONSTERSOLID;
		else
			mask = MASK_SOLID;
		SV_FlyMove(ent, FRAMETIME, mask);

		gi.linkentity(ent);
		G_TouchTriggers(ent);
		if (!ent->inuse)
			return;

		if (ent->groundentity)
			if (!wasonground)
				if (hitsound)
					gi.sound(ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0);
	}
	/* regular thinking */
	SV_RunThink(ent);
}
예제 #25
0
파일: sv_phys.c 프로젝트: THE-Swank/xash3d
/*
=============
SV_Physics_Toss

Toss, bounce, and fly movement.  When onground, do nothing.
=============
*/
void SV_Physics_Toss( edict_t *ent )
{
	trace_t	trace;
	vec3_t	move;
	float	backoff;
	edict_t	*ground;

	SV_CheckWater( ent );

	// regular thinking
	if( !SV_RunThink( ent )) return;

	ground = ent->v.groundentity;

	if( ent->v.velocity[2] > 0.0f || !SV_IsValidEdict( ground ) || ground->v.flags & (FL_MONSTER|FL_CLIENT) || svgame.globals->changelevel )
	{
		ent->v.flags &= ~FL_ONGROUND;
	}

	// if on ground and not moving, return.
	if( ent->v.flags & FL_ONGROUND && VectorIsNull( ent->v.velocity ))
	{
		VectorClear( ent->v.avelocity );

		if( VectorIsNull( ent->v.basevelocity ))
			return;	// at rest
	}

	SV_CheckVelocity( ent );

	// add gravity
	switch( ent->v.movetype )
	{
	case MOVETYPE_FLY:
	case MOVETYPE_FLYMISSILE:
	case MOVETYPE_BOUNCEMISSILE:
		break;
	default:
		SV_AddGravity( ent );
		break;
	}

	// move angles (with friction)
	switch( ent->v.movetype )
	{
	case MOVETYPE_TOSS:
	case MOVETYPE_BOUNCE:
		SV_AngularMove( ent, host.frametime, ent->v.friction );
		break;         
	default:
		SV_AngularMove( ent, host.frametime, 0.0f );
		break;
	}

	// move origin
	// Base velocity is not properly accounted for since this entity will move again
	// after the bounce without taking it into account
	VectorAdd( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );

	SV_CheckVelocity( ent );
	VectorScale( ent->v.velocity, host.frametime, move );

	VectorSubtract( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );

	trace = SV_PushEntity( ent, move, vec3_origin, NULL );
	if( ent->free ) return;

	SV_CheckVelocity( ent );

	if( trace.allsolid )
	{
		// entity is trapped in another solid
		VectorClear( ent->v.avelocity );
		VectorClear( ent->v.velocity );
		return;
	}

	if( trace.fraction == 1.0f )
	{
		SV_CheckWaterTransition( ent );
		return;
	}

	if( ent->v.movetype == MOVETYPE_BOUNCE )
		backoff = 2.0f - ent->v.friction;
	else if( ent->v.movetype == MOVETYPE_BOUNCEMISSILE )
		backoff = 2.0f;
	else backoff = 1.0f;

	SV_ClipVelocity( ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff );

	// stop if on ground
	if( trace.plane.normal[2] > 0.7f )
	{		
		float	vel;

		VectorAdd( ent->v.velocity, ent->v.basevelocity, move );
		vel = DotProduct( move, move );

		if( ent->v.velocity[2] < sv_gravity->value * host.frametime )
		{
			// we're rolling on the ground, add static friction.
			ent->v.groundentity = trace.ent;
			ent->v.flags |= FL_ONGROUND;
			ent->v.velocity[2] = 0.0f;
		}

		if( vel < 900.0f || ( ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE ))
		{
			ent->v.flags |= FL_ONGROUND;
			ent->v.groundentity = trace.ent;
			VectorClear( ent->v.avelocity );
			VectorClear( ent->v.velocity );
		}
		else
		{
			VectorScale( ent->v.velocity, (1.0f - trace.fraction) * host.frametime * 0.9f, move );
			VectorMA( move, (1.0f - trace.fraction) * host.frametime * 0.9f, ent->v.basevelocity, move );
			trace = SV_PushEntity( ent, move, vec3_origin, NULL );
			if( ent->free ) return;
		}
	}
	
	// check for in water
	SV_CheckWaterTransition( ent );
}
예제 #26
0
/*
=============
SV_Physics_NewToss

Toss, bounce, and fly movement. When on ground and no velocity, do nothing. With velocity,
slide.
=============
*/
void SV_Physics_NewToss (edict_t *ent)
{
	trace_t		trace;
	vec3_t		move;
//	float		backoff;
	edict_t		*slave;
	qboolean	wasinwater;
	qboolean	isinwater;
	qboolean	wasonground;
	float		speed, newspeed;
	vec3_t		old_origin;
//	float		firstmove;
//	int			mask;

	// regular thinking
	SV_RunThink (ent);

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

	if (ent->groundentity)
		wasonground = true;
	else
		wasonground = false;
	
	wasinwater = ent->waterlevel;

	// find out what we're sitting on.
	VectorCopy (ent->s.origin, move);
	move[2] -= 0.25;
	trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, move, ent, ent->clipmask);
	if(ent->groundentity && ent->groundentity->inuse)
		ent->groundentity = trace.ent;
	else
		ent->groundentity = NULL;

	// if we're sitting on something flat and have no velocity of our own, return.
	if (ent->groundentity && (trace.plane.normal[2] == 1.0) && 
		!ent->velocity[0] && !ent->velocity[1] && !ent->velocity[2])
	{
		return;
	}

	// store the old origin
	VectorCopy (ent->s.origin, old_origin);

	SV_CheckVelocity (ent);

	// add gravity
	SV_AddGravity (ent);

	if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2])
		SV_AddRotationalFriction (ent);

	// add friction
	speed = VectorLength(ent->velocity);
	if(ent->waterlevel)				// friction for water movement
	{
		newspeed = speed - (sv_waterfriction * 6 * ent->waterlevel);
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		VectorScale (ent->velocity, newspeed, ent->velocity);
	}
	else if (!ent->groundentity)	// friction for air movement
	{
		newspeed = speed - ((sv_friction));
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		VectorScale (ent->velocity, newspeed, ent->velocity);
	}
	else	// use ground friction
	{
		newspeed = speed - (sv_friction * 6);
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		VectorScale (ent->velocity, newspeed, ent->velocity);
	}

	SV_FlyMove (ent, FRAMETIME, ent->clipmask);
	gi.linkentity (ent);

	G_TouchTriggers (ent);

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

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

	if (!wasinwater && isinwater)
		gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
	else if (wasinwater && !isinwater)
		gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);

// move teamslaves
	for (slave = ent->teamchain; slave; slave = slave->teamchain)
	{
		VectorCopy (ent->s.origin, slave->s.origin);
		gi.linkentity (slave);
	}
}
예제 #27
0
/*
================
SV_Physics_Client

Player character actions
================
*/
void SV_Physics_Client (edict_t	*ent, int num)
{
	if ( ! svs.clients[num-1].active )
		return;		// unconnected slot

//
// call standard client pre-think
//	
	pr_global_struct->time = sv.time;
	pr_global_struct->self = EDICT_TO_PROG(ent);
	PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
	
//
// do a move
//
	SV_CheckVelocity (ent);

//
// decide which move function to call
//
	switch ((int)ent->v.movetype)
	{
	case MOVETYPE_NONE:
		if (!SV_RunThink (ent))
			return;
		break;
		
	case MOVETYPE_WALK:
		if (!SV_RunThink (ent))
			return;
		if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
			SV_AddGravity (ent);
		SV_CheckStuck (ent);
		SV_WalkMove (ent);
		break;
		
	case MOVETYPE_TOSS:
	case MOVETYPE_BOUNCE:
		SV_Physics_Toss (ent);
		break;
		
	case MOVETYPE_FLY:
		if (!SV_RunThink (ent))
			return;
		SV_CheckWater (ent);
		SV_FlyMove (ent, host_frametime, NULL);
		break;
		
	case MOVETYPE_NOCLIP:
		if (!SV_RunThink (ent))
			return;
		ent->v.waterlevel = 0;	// Avoid annoying waterjumps in noclip
		ent->v.watertype = CONTENTS_EMPTY;	// Avoid annoying waterjumps in noclip
		VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
		break;
		
	default:
		Host_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
	}

//
// call standard player post-think
//		
	if (ent->v.movetype == MOVETYPE_NOCLIP)
		SV_LinkEdict (ent, false); // don't touch triggers in noclip
	else
		SV_LinkEdict (ent, true);

	pr_global_struct->time = sv.time;
	pr_global_struct->self = EDICT_TO_PROG(ent);
	PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
}