Beispiel #1
0
trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
{
	edict_t	tempent, *tent;
	trace_t	trace;
	vec3_t	move, end;
	double	save_frametime;

	save_frametime = host_frametime;
	host_frametime = 0.05;

	memcpy (&tempent, ent, sizeof(edict_t));
	tent = &tempent;

	while (1)
	{
		SV_CheckVelocity (tent);
		SV_AddGravity (tent);
		VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
		VectorScale (tent->v.velocity, host_frametime, move);
		VectorAdd (tent->v.origin, move, end);
		trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);	
		VectorCopy (trace.endpos, tent->v.origin);

		if (trace.ent)
			if (trace.ent != ignore)
				break;
	}
	host_frametime = save_frametime;

	return trace;
}
Beispiel #2
0
/*
=============
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.
FIXME: is this true?
=============
*/
void SV_Physics_Step (edict_t *ent)
{
    qbool	hitsound;

// frefall if not onground
    if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
    {
        if (ent->v.velocity[2] < sv.movevars.gravity*-0.1)
            hitsound = true;
        else
            hitsound = false;

        SV_AddGravity (ent, 1.0);
        SV_CheckVelocity (ent);
        // Tonik: the check for SOLID_NOT is to fix the way dead bodies and
        // gibs behave (should not be blocked by players & monsters);
        // The SOLID_TRIGGER check is disabled lest we break frikbots
        if (ent->v.solid == SOLID_NOT /* || ent->v.solid == SOLID_TRIGGER*/)
            SV_FlyMove (ent, sv_frametime, NULL, MOVE_NOMONSTERS);
        else
            SV_FlyMove (ent, sv_frametime, NULL, MOVE_NORMAL);
        SV_LinkEdict (ent, true);

        if ( (int)ent->v.flags & FL_ONGROUND )	// just hit ground
        {
            if (hitsound)
                SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1, NULL);
        }
    }

// regular thinking
    SV_RunThink (ent);

    SV_CheckWaterTransition (ent);
}
Beispiel #3
0
void SV_Physics_Step (edict_t *ent)
{
	qboolean	hitsound;

// freefall if not onground
	if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
	{
		if (ent->v.velocity[2] < sv_gravity.value*-0.1)
			hitsound = true;
		else
			hitsound = false;

		SV_AddGravity (ent);
		SV_CheckVelocity (ent);
		SV_FlyMove (ent, host_frametime, NULL);
		SV_LinkEdict (ent, true);

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

// regular thinking
	SV_RunThink (ent);
	
	SV_CheckWaterTransition (ent);
}
Beispiel #4
0
/*
=============
SV_Physics_Toss

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

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

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

// 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, 1.0);

// 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)
	{		
		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);
}
Beispiel #5
0
//#ifdef QUAKE2	// 2001-09-16 Quake 2 builtin functions by id/Maddes
trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
{
	edict_t	tempent, *tent;
	trace_t	trace;
	vec3_t	move;
	vec3_t	end;
	double	save_frametime;
//	extern particle_t	*active_particles, *free_particles;
//	particle_t	*p;
	int i;	// 2001-09-16 SV_Trace_Toss endless loop fix by LordHavoc

	save_frametime = host_frametime;
	host_frametime = 0.05;

	memcpy(&tempent, ent, sizeof(edict_t));
	tent = &tempent;

// 2001-09-16 SV_Trace_Toss endless loop fix by LordHavoc  start
//	while (1)
	for (i = 0;i < 200;i++)	//sanity check; never trace more than 10 seconds
// 2001-09-16 SV_Trace_Toss endless loop fix by LordHavoc  end
	{
		SV_CheckVelocity (tent);
		SV_AddGravity (tent);
		VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
		VectorScale (tent->v.velocity, host_frametime, move);
		VectorAdd (tent->v.origin, move, end);
		trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);
		VectorCopy (trace.endpos, tent->v.origin);

//		p = free_particles;
//		if (p)
//		{
//			free_particles = p->next;
//			p->next = active_particles;
//			active_particles = p;
//
//			p->die = 256;
//			p->color = 15;
//			p->type = pt_static;
//			VectorCopy (vec3_origin, p->vel);
//			VectorCopy (tent->v.origin, p->org);
//		}

		if (trace.ent)
			if (trace.ent != ignore)
				break;
	}
//	p->color = 224;
	host_frametime = save_frametime;
	
	return trace;
}
Beispiel #6
0
trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
{
	edict_t	tempent, *tent;
	trace_t	trace;
	vec3_t	move;
	vec3_t	end;
	double	save_frametime;
//	extern particle_t	*active_particles, *free_particles;
//	particle_t	*p;


	save_frametime = host_frametime;
	host_frametime = 0.05;

	memcpy(&tempent, ent, sizeof(edict_t));
	tent = &tempent;

	while (1)
	{
		SV_CheckVelocity (tent);
		SV_AddGravity (tent);
		VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
		VectorScale (tent->v.velocity, host_frametime, move);
		VectorAdd (tent->v.origin, move, end);
		trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);	
		VectorCopy (trace.endpos, tent->v.origin);

//		p = free_particles;
//		if (p)
//		{
//			free_particles = p->next;
//			p->next = active_particles;
//			active_particles = p;
//		
//			p->die = 256;
//			p->color = 15;
//			p->type = pt_static;
//			VectorCopy (vec3_origin, p->vel);
//			VectorCopy (tent->v.origin, p->org);
//		}

		if (trace.ent)
			if (trace.ent != ignore)
				break;
	}
//	p->color = 224;
	host_frametime = save_frametime;
	return trace;
}
Beispiel #7
0
/*
============
SV_AddHalfGravity

============
*/
void SV_AddHalfGravity( edict_t *ent, float timestep )
{
	float	ent_gravity;

	if( ent->v.gravity )
		ent_gravity = ent->v.gravity;
	else ent_gravity = 1.0f;

	// Add 1/2 of the total gravitational effects over this timestep
	ent->v.velocity[2] -= ( 0.5f * ent_gravity * sv_gravity->value * timestep );
	ent->v.velocity[2] += ( ent->v.basevelocity[2] * host.frametime );
	ent->v.basevelocity[2] = 0.0f;
	
	// bound velocity
	SV_CheckVelocity( ent );
}
Beispiel #8
0
/*
============
SV_AddGravity

============
*/
void SV_AddGravity( edict_t *ent )
{
	float	ent_gravity;

	if( ent->v.gravity )
		ent_gravity = ent->v.gravity;
	else ent_gravity = 1.0f;

	// add gravity incorrectly
	ent->v.velocity[2] -= ( ent_gravity * sv_gravity->value * host.frametime );
	ent->v.velocity[2] += ( ent->v.basevelocity[2] * host.frametime );
	ent->v.basevelocity[2] = 0.0f;

	// bound velocity
	SV_CheckVelocity( ent );
}
Beispiel #9
0
/*
================
SV_CheckAllEnts
================
*/
void SV_CheckAllEnts( void )
{
	edict_t	*e;
	int	i;

	if( !sv_check_errors->integer || sv.state != ss_active )
		return;

	// check edicts errors
	for( i = svgame.globals->maxClients + 1; i < svgame.numEntities; i++ )
	{
		e = EDICT_NUM( i );

		// DEBUG: check 'gamestate' for using by mods
		if( e->v.gamestate != 0 )
		{
			MsgDev( D_INFO, "Entity %s[%i] uses gamestate %i\n", SV_ClassName( e ), NUM_FOR_EDICT( e ), e->v.gamestate );
		}

		if( e->free && e->pvPrivateData != NULL )
		{
			MsgDev( D_ERROR, "Freed entity %s (%i) has private data.\n", SV_ClassName( e ), i );
			continue;
		}

		if( !SV_IsValidEdict( e ))
			continue;

		if( !e->v.pContainingEntity || e->v.pContainingEntity != e )
		{
			MsgDev( D_ERROR, "Entity %s (%i) has invalid container, fixed.\n", SV_ClassName( e ), i );
			e->v.pContainingEntity = e;
			continue;
		}

		if( !e->pvPrivateData || !Mem_IsAllocatedExt( svgame.mempool, e->pvPrivateData ))
		{
			MsgDev( D_ERROR, "Entity %s (%i) trashed private data.\n", SV_ClassName( e ), i );
			e->pvPrivateData = NULL;
			continue;
		}

		SV_CheckVelocity( e );
	}
}
Beispiel #10
0
/*
=============
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	hitsound;
	char		*snd;

// freefall if not onground
	if (!((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM)))
	{
		if (ent->v.velocity[2] < sv_gravity.value*-0.1)
			hitsound = true;
		else
			hitsound = false;

		SV_AddGravity (ent);
		SV_CheckVelocity (ent);
		SV_FlyMove (ent, host_frametime, NULL);
		SV_LinkEdict (ent, true);

		if ((int)ent->v.flags & FL_ONGROUND)	// just hit ground
#ifdef HEXEN2_SUPPORT
		if (!hexen2 || (!ent->v.flags & FL_MONSTER))
#endif
		{
			if (hitsound)
			{
			#ifdef HEXEN2_SUPPORT
				if (hexen2)
					snd = "fx/thngland.wav";
				else
			#endif
				snd = "demon/dland2.wav";
				SV_StartSound (ent, 0, snd, 255, 1);
			}
		}
	}

// regular thinking
	SV_RunThink (ent);
	
	SV_CheckWaterTransition (ent);
}
/* DESCRIPTION: SV_Trace_Toss
// LOCATION: sv_phys.c
// PATH: PF_TraceToss_Shared
//
// Say I throw a grenade.  Where will it go?  This function finds out by
// simulating ten seconds' worth of frames.
*/
trace_t * SV_Trace_Toss(trace_t * Outgoing_Trace, edict_t *tossent, edict_t *ignore) {

   int i;
   vec3_t var_378_end;
   vec3_t var_36C_move;
   trace_t var_360_trace;
   edict_t var_324_TempEdict;
   edict_t * var_328_TempEdictPtr;
   double var_380_host_frametime;

   var_380_host_frametime = host_frametime;
   host_frametime = .05;

   Q_memcpy(&var_324_TempEdict, tossent, sizeof(edict_t));

   var_328_TempEdictPtr = &var_324_TempEdict;

//   while(1) //a sanity check to avoid tracing more than ten seconds was present in QW, I think it's a good idea.  This may need to be adjusted to account for the alterable frametimes.
   for (i = 0; i < 200; i++)
   {
      SV_CheckVelocity(var_328_TempEdictPtr);
      SV_AddGravity(var_328_TempEdictPtr);
      VectorMA(var_328_TempEdictPtr->v.angles, host_frametime, var_328_TempEdictPtr->v.avelocity, var_328_TempEdictPtr->v.angles);
      VectorScale(var_328_TempEdictPtr->v.velocity, host_frametime, var_36C_move);
      VectorAdd(var_328_TempEdictPtr->v.origin, var_36C_move, var_378_end);

      var_360_trace = SV_Move(var_328_TempEdictPtr->v.origin, var_328_TempEdictPtr->v.mins, var_328_TempEdictPtr->v.maxs, var_378_end, 0, var_328_TempEdictPtr, 0);
      VectorCopy(var_360_trace.endpos, var_328_TempEdictPtr->v.origin);

      if(var_360_trace.pHit != NULL && var_360_trace.pHit != ignore) { break; }
   }

   host_frametime = var_380_host_frametime;
   Q_memcpy(Outgoing_Trace, &var_360_trace, sizeof(trace_t));
   return(Outgoing_Trace);
}
/*
=============
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->gravity > 0.0)		// PGM - gravity hack
		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);
			}
		}

//		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);
	}
}
/*
=============
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);
	}
}
Beispiel #14
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);
	}
}
Beispiel #15
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);
}
Beispiel #16
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;

	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);
	}
}
Beispiel #17
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);
    }
}
Beispiel #18
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 = ((int)EDICT_TO_PROG(trace.ent));
			VectorCopy (vec3_origin, ent->v.velocity);
			VectorCopy (vec3_origin, ent->v.avelocity);
		}
	}
	
// check for in water
	SV_CheckWaterTransition (ent);
}
Beispiel #19
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));
}
Beispiel #20
0
/*
=============
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 );

}
Beispiel #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	*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 );
}
Beispiel #22
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;

	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])
	{
		/* 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);
}
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;

	// 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->value ? sv_stopspeed->value : 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->value ? sv_stopspeed->value : 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->value ? sv_stopspeed->value : 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);

// ========
// PGM - reset this every time they move. 
//       G_touchtriggers will set it back if appropriate
		ent->gravity = 1.0;
// ========
		
		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);
	}

	if(!ent->inuse)			// PGM g_touchtrigger free problem
		return;

// regular thinking
	SV_RunThink (ent);
}
Beispiel #24
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);
}
Beispiel #25
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 = ((int)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 = ((int)EDICT_TO_PROG(ent));
	PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
}
Beispiel #26
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;
//	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); 
}
Beispiel #27
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 = sqrt(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);
}
Beispiel #28
0
/*
* SV_Physics_Toss
*
* Toss, bounce, and fly movement.  When onground, do nothing.
*
* FIXME: This function needs a serious rewrite
*/
static void SV_Physics_Toss( edict_t *ent ) {
	trace_t trace;
	vec3_t move;
	float backoff;
	edict_t *slave;
	bool wasinwater;
	bool isinwater;
	vec3_t old_origin;
	float oldSpeed;

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

	// refresh the ground entity
	if( ent->movetype == MOVETYPE_BOUNCE || ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
		if( ent->velocity[2] > 0.1f ) {
			ent->groundentity = NULL;
		}
	}

	if( ent->groundentity && ent->groundentity != world && !ent->groundentity->r.inuse ) {
		ent->groundentity = NULL;
	}

	oldSpeed = VectorLength( ent->velocity );

	if( ent->groundentity ) {
		if( !oldSpeed ) {
			return;
		}

		if( ent->movetype == MOVETYPE_TOSS ) {
			if( ent->velocity[2] >= 8 ) {
				ent->groundentity = NULL;
			} else {
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
				return;
			}
		}
	}

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

	if( ent->accel != 0 ) {
		if( ent->accel < 0 && VectorLength( ent->velocity ) < 50 ) {
			VectorClear( ent->velocity );
		} else {
			vec3_t acceldir;
			VectorNormalize2( ent->velocity, acceldir );
			VectorScale( acceldir, ent->accel * FRAMETIME, acceldir );
			VectorAdd( ent->velocity, acceldir, ent->velocity );
		}
	}

	SV_CheckVelocity( ent );

	// add gravity
	if( ent->movetype != MOVETYPE_FLY && !ent->groundentity ) {
		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->r.inuse ) {
		return;
	}

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

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

		// stop if on ground

		if( ent->movetype == MOVETYPE_BOUNCE || ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
			// stop dead on allsolid

			// LA: hopefully will fix grenades bouncing down slopes
			// method taken from Darkplaces sourcecode
			if( trace.allsolid ||
				( ISWALKABLEPLANE( &trace.plane ) &&
				  fabs( DotProduct( trace.plane.normal, ent->velocity ) ) < 40
				)
				) {
				ent->groundentity = &game.edicts[trace.ent];
				ent->groundentity_linkcount = ent->groundentity->linkcount;
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
			}
		} else {
			// in movetype_toss things stop dead when touching ground
#if 0
			G_CheckGround( ent );

			if( ent->groundentity ) {
#else

			// walkable or trapped inside solid brush
			if( trace.allsolid || ISWALKABLEPLANE( &trace.plane ) ) {
				ent->groundentity = trace.ent < 0 ? world : &game.edicts[trace.ent];
				ent->groundentity_linkcount = ent->groundentity->linkcount;
#endif
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
			}
		}
	}

	// check for water transition
	wasinwater = ( ent->watertype & MASK_WATER ) ? true : false;
	ent->watertype = G_PointContents( ent->s.origin );
	isinwater = ent->watertype & MASK_WATER ? true : false;

	// never allow items in CONTENTS_NODROP
	if( ent->item && ( ent->watertype & CONTENTS_NODROP ) ) {
		G_FreeEdict( ent );
		return;
	}

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

	if( !wasinwater && isinwater ) {
		G_PositionedSound( old_origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	} else if( wasinwater && !isinwater ) {
		G_PositionedSound( ent->s.origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	}

	// move teamslaves
	for( slave = ent->teamchain; slave; slave = slave->teamchain ) {
		VectorCopy( ent->s.origin, slave->s.origin );
		GClip_LinkEntity( slave );
	}
}

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

void SV_Physics_LinearProjectile( edict_t *ent ) {
	vec3_t start, end;
	int mask;
	float startFlyTime, endFlyTime;
	trace_t trace;
	int old_waterLevel;

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

	old_waterLevel = ent->waterlevel;

	mask = ( ent->r.clipmask ) ? ent->r.clipmask : MASK_SOLID;

	// find it's current position given the starting timeStamp
	startFlyTime = (float)( max( game.prevServerTime - ent->s.linearMovementTimeStamp, 0 ) ) * 0.001f;
	endFlyTime = (float)( game.serverTime - ent->s.linearMovementTimeStamp ) * 0.001f;

	VectorMA( ent->s.linearMovementBegin, startFlyTime, ent->s.linearMovementVelocity, start );
	VectorMA( ent->s.linearMovementBegin, endFlyTime, ent->s.linearMovementVelocity, end );

	G_Trace4D( &trace, start, ent->r.mins, ent->r.maxs, end, ent, mask, ent->timeDelta );
	VectorCopy( trace.endpos, ent->s.origin );
	GClip_LinkEntity( ent );
	SV_Impact( ent, &trace );

	if( !ent->r.inuse ) { // the projectile may be freed if touched something
		return;
	}

	// update some data required for the transmission
	//VectorCopy( ent->velocity, ent->s.linearMovementVelocity );

	GClip_TouchTriggers( ent );
	ent->groundentity = NULL; // projectiles never have ground entity
	ent->waterlevel = ( G_PointContents4D( ent->s.origin, ent->timeDelta ) & MASK_WATER ) ? true : false;

	if( !old_waterLevel && ent->waterlevel ) {
		G_PositionedSound( start, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	} else if( old_waterLevel && !ent->waterlevel ) {
		G_PositionedSound( ent->s.origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	}
}
Beispiel #29
0
void SV_Physics_Step (edict_t *ent)
{
	bool	wasonground;
	bool	hitsound = false;
	float		*vel;
	float		speed, newspeed, control;
	float		friction;
	edict_t		*groundentity;
	int			mask;

	// 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] < level.gravity*-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->r.svflags & SVF_MONSTER)
			mask = MASK_MONSTERSOLID;
		else
			mask = MASK_SOLID;
		SV_FlyMove (ent, FRAMETIME, mask);

		GClip_LinkEntity (ent);
		GClip_TouchTriggers (ent);

		if (ent->groundentity)
			if (!wasonground)
				if (hitsound)
					G_Sound (ent, 0, trap_SoundIndex( S_LAND ), ATTN_NORM);
	}
}
Beispiel #30
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;

	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)
		&& (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);
	trace = SV_PushEntity(ent, move);

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

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

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

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

		/* stop if on ground */
		if ((trace.plane.normal[2] > 0.7) &&
			(ent->movetype != MOVETYPE_WALLBOUNCE))
		{
			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);
	}
}