Beispiel #1
0
/*
=============
SV_Submerged

determine how deep the entity is
=============
*/
float SV_Submerged( edict_t *ent )
{
	vec3_t	point;
	vec3_t	halfmax;
	float	waterlevel;

	VectorAverage( ent->v.absmin, ent->v.absmax, halfmax );
	waterlevel = ent->v.absmin[2] - halfmax[2];

	switch( ent->v.waterlevel )
	{
	case 1:
		return SV_RecursiveWaterLevel( halfmax, 0.0f, waterlevel, 0 ) - waterlevel;
	case 3:
		VectorSet( point, halfmax[0], halfmax[1], ent->v.absmax[2] );
		svs.groupmask = ent->v.groupinfo;

		if( SV_PointContents( point ) == CONTENTS_WATER )
		{
			return (ent->v.maxs[2] - ent->v.mins[2]);
		}
		// intentionally fallthrough
	case 2:
		return SV_RecursiveWaterLevel( halfmax, ent->v.absmax[2] - halfmax[2], 0.0f, 0 ) - waterlevel;
	default:
		return 0.0f;
	}
}
Beispiel #2
0
/*
===============
R_TransEntityCompare

Sorting translucent entities by rendermode then by distance
===============
*/
static int R_TransEntityCompare( const cl_entity_t **a, const cl_entity_t **b )
{
	cl_entity_t	*ent1, *ent2;
	vec3_t		vecLen, org;
	float		len1, len2;

	ent1 = (cl_entity_t *)*a;
	ent2 = (cl_entity_t *)*b;

	// now sort by rendermode
	if( R_RankForRenderMode( ent1 ) > R_RankForRenderMode( ent2 ))
		return 1;
	if( R_RankForRenderMode( ent1 ) < R_RankForRenderMode( ent2 ))
		return -1;

	// then by distance
	if( ent1->model->type == mod_brush )
	{
		VectorAverage( ent1->model->mins, ent1->model->maxs, org );
		VectorAdd( ent1->origin, org, org );
		VectorSubtract( RI.vieworg, org, vecLen );
	}
	else VectorSubtract( RI.vieworg, ent1->origin, vecLen );
	len1 = VectorLength( vecLen );

	if( ent2->model->type == mod_brush )
	{
		VectorAverage( ent2->model->mins, ent2->model->maxs, org );
		VectorAdd( ent2->origin, org, org );
		VectorSubtract( RI.vieworg, org, vecLen );
	}
	else VectorSubtract( RI.vieworg, ent2->origin, vecLen );
	len2 = VectorLength( vecLen );

	if( len1 > len2 )
		return -1;
	if( len1 < len2 )
		return 1;

	return 0;
}
Beispiel #3
0
//
// sound engine implementation
//
qboolean CL_GetEntitySpatialization( int entnum, vec3_t origin, float *pradius )
{
	cl_entity_t	*ent;
	qboolean		valid_origin;

	ASSERT( origin != NULL );

	if( entnum == 0 ) return true; // static sound

	if(( entnum - 1 ) == cl.playernum )
	{
		VectorCopy( cl.frame.local.client.origin, origin );
		return true;
	}

	valid_origin = VectorIsNull( origin ) ? false : true;          
	ent = CL_GetEntityByIndex( entnum );

	// entity is not present on the client but has valid origin
	if( !ent || !ent->index ) return valid_origin;

	if( ent->curstate.messagenum == 0 )
	{
		// entity is never has updates on the client
		// so we should use static origin instead
		return valid_origin;
	}
#if 0
	// uncomment this if you want enable additional check by PVS
	if( ent->curstate.messagenum != cl.parsecount )
		return valid_origin;
#endif
	// setup origin
	VectorAverage( ent->curstate.mins, ent->curstate.maxs, origin );
	VectorAdd( origin, ent->curstate.origin, origin );

	// setup radius
	if( pradius )
	{
		if( ent->model != NULL && ent->model->radius ) *pradius = ent->model->radius;
		else *pradius = RadiusFromBounds( ent->curstate.mins, ent->curstate.maxs );
	}

	return true;
}
Beispiel #4
0
/*
===============
V_SetupOverviewState

Get initial overview values
===============
*/
void V_SetupOverviewState( void )
{
	ref_overview_t	*ov = &clgame.overView;
	float		mapAspect, screenAspect, aspect;

	ov->rotated = ( world.size[1] <= world.size[0] ) ? true : false;

	// calculate nearest aspect
	mapAspect = world.size[!ov->rotated] / world.size[ov->rotated];
	screenAspect = (float)glState.width / (float)glState.height;
	aspect = max( mapAspect, screenAspect );

	ov->zNear = world.maxs[2];
	ov->zFar = world.mins[2];
	ov->flZoom = ( 8192.0f / world.size[ov->rotated] ) / aspect;

	VectorAverage( world.mins, world.maxs, ov->origin );
}
Beispiel #5
0
/*
=================
FinishBrush

produces a final brush based on the buildBrush->sides array
and links it to the current entity
=================
*/
brush_t *FinishBrush( void )
{
	brush_t		*b;
	
	// create windings for sides and bounds for brush
	if( !CreateBrushWindings( buildBrush ))
		return NULL;

	// origin brushes are removed, but they set the rotation origin for the rest of the brushes in the entity.
	// after the entire entity is parsed, the planenums and texinfos will be adjusted for the origin brush
	if( buildBrush->compileFlags & C_ORIGIN )
	{
		char	string[32];
		vec3_t	size, movedir, origin;

		if( numEntities == 1 )
		{
			Msg( "Entity %i, Brush %i: origin brushes not allowed in world\n", mapEnt->mapEntityNum, entitySourceBrushes );
			return NULL;
		}
		
		// calcualte movedir (Xash 0.4 style)
		VectorAverage( buildBrush->mins, buildBrush->maxs, origin );
		VectorSubtract( buildBrush->maxs, buildBrush->mins, size );

		if( size[2] > size[0] && size[2] > size[1] )
            		VectorSet( movedir, 0.0f, 1.0f, 0.0f );	// x-rotate
		else if( size[1] > size[2] && size[1] > size[0] )
            		VectorSet( movedir, 1.0f, 0.0f, 0.0f );	// y-rotate
		else if( size[0] > size[2] && size[0] > size[1] )
			VectorSet( movedir, 0.0f, 0.0f, 1.0f );	// z-rotate
		else VectorClear( movedir ); // custom movedir

#if 0
		if( !VectorIsNull( movedir ))
		{
			com.snprintf( string, sizeof( string ), "%i %i %i", (int)movedir[0], (int)movedir[1], (int)movedir[2] );
			SetKeyValue( &entities[numEntities - 1], "movedir", string );
		}
#endif
		if(!VectorIsNull( origin ))
		{
			com.snprintf( string, sizeof( string ), "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2] );
			SetKeyValue( &entities[numEntities - 1], "origin", string );
			VectorCopy( origin, entities[numEntities - 1].origin );
                    }

		// don't keep this brush
		return NULL;
	}
	
	// determine if the brush is an area portal
	if( buildBrush->compileFlags & C_AREAPORTAL )
	{
		if( numEntities != 1 )
		{
			Msg( "Entity %i, Brush %i: areaportals only allowed in world\n", mapEnt->mapEntityNum, entitySourceBrushes );
			return NULL;
		}
	}
	
	AddBrushBevels();
	
	b = CopyBrush( buildBrush );
	
	b->entityNum = mapEnt->mapEntityNum;
	b->brushNum = entitySourceBrushes;
	
	b->original = b;
	
	// link opaque brushes to head of list, translucent brushes to end
	if( b->opaque || mapEnt->lastBrush == NULL )
	{
		b->next = mapEnt->brushes;
		mapEnt->brushes = b;
		if( mapEnt->lastBrush == NULL )
			mapEnt->lastBrush = b;
	}
	else
	{
		b->next = NULL;
		mapEnt->lastBrush->next = b;
		mapEnt->lastBrush = b;
	}
	
	// link colorMod volume brushes to the entity directly
	if( b->contentShader != NULL && b->contentShader->colorMod != NULL && b->contentShader->colorMod->type == CM_VOLUME )
	{
		b->nextColorModBrush = mapEnt->colorModBrushes;
		mapEnt->colorModBrushes = b;
	}
	return b;
}
Beispiel #6
0
/*
============
SV_PushRotate

============
*/
static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
{
	int		i, e, block, oldsolid;
	matrix4x4		start_l, end_l;
	vec3_t		lmove, amove;
	sv_pushed_t	*p, *pushed_p;
	vec3_t		org, org2, temp;
	edict_t		*check;

	if( svgame.globals->changelevel || VectorIsNull( pusher->v.avelocity ))
	{
		pusher->v.ltime += movetime;
		return NULL;
	}

	for( i = 0; i < 3; i++ )
		amove[i] = pusher->v.avelocity[i] * movetime;

	// create pusher initial position
	Matrix4x4_CreateFromEntity( start_l, pusher->v.angles, pusher->v.origin, 1.0f );

	pushed_p = svgame.pushed;

	// save the pusher's original position
	pushed_p->ent = pusher;
	VectorCopy( pusher->v.origin, pushed_p->origin );
	VectorCopy( pusher->v.angles, pushed_p->angles );
	pushed_p++;
	
	// move the pusher to it's final position
	SV_AngularMove( pusher, movetime, pusher->v.friction );
	SV_LinkEdict( pusher, false );
	pusher->v.ltime += movetime;
	oldsolid = pusher->v.solid;

	// non-solid pushers can't push anything
	if( pusher->v.solid == SOLID_NOT )
		return NULL;

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

	// see if any solid entities are inside the final position
	for( e = 1; e < svgame.numEntities; e++ )
	{
		check = EDICT_NUM( e );
		if( !SV_IsValidEdict( check ))
			continue;

		// filter movetypes to collide with
		if( !SV_CanPushed( check ))
			continue;

		pusher->v.solid = SOLID_NOT;
		block = SV_TestEntityPosition( check, pusher );
		pusher->v.solid = oldsolid;
		if( block ) continue;

		// if the entity is standing on the pusher, it will definately be moved
		if( !(( check->v.flags & FL_ONGROUND ) && check->v.groundentity == pusher ))
		{
			if( check->v.absmin[0] >= pusher->v.absmax[0]
			|| check->v.absmin[1] >= pusher->v.absmax[1]
			|| check->v.absmin[2] >= pusher->v.absmax[2]
			|| check->v.absmax[0] <= pusher->v.absmin[0]
			|| check->v.absmax[1] <= pusher->v.absmin[1]
			|| check->v.absmax[2] <= pusher->v.absmin[2] )
				continue;

			// see if the ent's bbox is inside the pusher's final position
			if( !SV_TestEntityPosition( check, NULL ))
				continue;
		}

		// save original position of contacted entity
		pushed_p->ent = check;
		VectorCopy( check->v.origin, pushed_p->origin );
		VectorCopy( check->v.angles, pushed_p->angles );
		pushed_p->fixangle = check->v.fixangle;
		pushed_p++;

		// calculate destination position
		if( check->v.movetype == MOVETYPE_PUSHSTEP || check->v.movetype == MOVETYPE_STEP )
			VectorAverage( check->v.absmin, check->v.absmax, org );
		else VectorCopy( check->v.origin, org );

		Matrix4x4_VectorITransform( start_l, org, temp );
		Matrix4x4_VectorTransform( end_l, temp, org2 );
		VectorSubtract( org2, org, lmove );

		// i can't clear FL_ONGROUND in all cases because many bad things may be happen
		if( check->v.movetype != MOVETYPE_WALK )
		{
			if( lmove[2] != 0.0f ) check->v.flags &= ~FL_ONGROUND;
			if( lmove[2] < 0.0f && !pusher->v.dmg )
				lmove[2] = 0.0f; // let's the free falling
		}

		// try moving the contacted entity 
		pusher->v.solid = SOLID_NOT;
		SV_PushEntity( check, lmove, amove, &block );
		pusher->v.solid = oldsolid;

		// pushed entity blocked by wall
		if( block && check->v.movetype != MOVETYPE_WALK )
			check->v.flags &= ~FL_ONGROUND;

		// if it is still inside the pusher, block
		if( SV_TestEntityPosition( check, NULL ) && block )
		{	
			if( !SV_CanBlock( check ))
				continue;

			pusher->v.ltime -= movetime;

			// move back any entities we already moved
			// go backwards, so if the same entity was pushed
			// twice, it goes back to the original position
			for( p = pushed_p - 1; p >= svgame.pushed; p-- )
			{
				VectorCopy( p->origin, p->ent->v.origin );
				VectorCopy( p->angles, p->ent->v.angles );
				SV_LinkEdict( p->ent, (p->ent == check) ? true : false );
				p->ent->v.fixangle = p->fixangle;
			}
			return check;
		}
	}

	return NULL;
}