Beispiel #1
0
/*
* G_PointContents
* returns the CONTENTS_* value from the world at the given point.
* Quake 2 extends this to also check entities, to allow moving liquids
*/
static int GClip_PointContents( vec3_t p, int timeDelta )
{
	c4clipedict_t *clipEnt;
	int touch[MAX_EDICTS];
	int i, num;
	int contents, c2;
	struct cmodel_s	*cmodel;
	float *angles;

	// get base contents from world
	contents = trap_CM_TransformedPointContents( p, NULL, NULL, NULL );

	// or in contents from all the other entities
	num = GClip_AreaEdicts( p, p, touch, MAX_EDICTS, AREA_SOLID, timeDelta );

	for( i = 0; i < num; i++ )
	{
		clipEnt = GClip_GetClipEdictForDeltaTime( touch[i], timeDelta );

		// might intersect, so do an exact clip
		cmodel = GClip_CollisionModelForEntity( &clipEnt->s, &clipEnt->r );

		if( !ISBRUSHMODEL( clipEnt->s.modelindex ) )
			angles = vec3_origin; // boxes don't rotate
		else
			angles = clipEnt->s.angles;

		c2 = trap_CM_TransformedPointContents( p, cmodel, clipEnt->s.origin, clipEnt->s.angles );
		contents |= c2;
	}

	return contents;
}
Beispiel #2
0
void G_SplashFrac4D( int entNum, vec3_t hitpoint, float maxradius, vec3_t pushdir, float *kickFrac, float *dmgFrac, int timeDelta )
{
	c4clipedict_t *clipEnt;

	clipEnt = GClip_GetClipEdictForDeltaTime( entNum, timeDelta );
	G_SplashFrac( clipEnt->s.origin, clipEnt->r.mins, clipEnt->r.maxs, hitpoint, maxradius, pushdir, kickFrac, dmgFrac );
}
Beispiel #3
0
/*
* GClip_FindBoxInRadius
* Returns entities that have their boxes within a spherical area
*/
edict_t *GClip_FindBoxInRadius4D( edict_t *from, vec3_t org, float rad, int timeDelta )
{
	int i, j;
	c4clipedict_t *check;
	vec3_t mins, maxs;
	int fromNum;

	if( !from ) from = world;
	fromNum = ENTNUM( from ) + 1;

	for( i = fromNum; i < game.numentities; i++ )
	{
		if( !game.edicts[i].r.inuse )
			continue;

		check = GClip_GetClipEdictForDeltaTime( i, timeDelta );
		if( !check->r.inuse )
			continue;
		if( check->r.solid == SOLID_NOT )
			continue;
		// make absolute mins and maxs
		for( j = 0; j < 3; j++ )
		{
			mins[j] = check->s.origin[j] + check->r.mins[j];
			maxs[j] = check->s.origin[j] + check->r.maxs[j];
		}
		if( !BoundsAndSphereIntersect( mins, maxs, org, rad ) )
			continue;

		return &game.edicts[i]; // return realtime entity
	}

	return NULL;
}
Beispiel #4
0
/*
* GClip_ClipMoveToEntities
*/
/*static*/ void GClip_ClipMoveToEntities( moveclip_t *clip, int timeDelta )
{
	int i, num;
	c4clipedict_t *touch;
	int touchlist[MAX_EDICTS];
	trace_t	trace;
	struct cmodel_s	*cmodel;
	float *angles;

	num = GClip_AreaEdicts( clip->boxmins, clip->boxmaxs, touchlist, MAX_EDICTS, AREA_SOLID, timeDelta );

	// be careful, it is possible to have an entity in this
	// list removed before we get to it (killtriggered)
	for( i = 0; i < num; i++ )
	{
		touch = GClip_GetClipEdictForDeltaTime( touchlist[i], timeDelta );
		if( clip->passent >= 0 )
		{
			// when they are offseted in time, they can be a different pointer but be the same entity
			if( touch->s.number == clip->passent )
				continue;
			if( touch->r.owner && ( touch->r.owner->s.number == clip->passent ) )
				continue;
			if( game.edicts[clip->passent].r.owner 
				&& ( game.edicts[clip->passent].r.owner->s.number == touch->s.number ) )
				continue;

			// wsw : jal : never clipmove against SVF_PROJECTILE entities
			if( touch->r.svflags & SVF_PROJECTILE )
				continue;
		}

		if( ( touch->r.svflags & SVF_CORPSE ) && !( clip->contentmask & CONTENTS_CORPSE ) )
			continue;

		// might intersect, so do an exact clip
		cmodel = GClip_CollisionModelForEntity( &touch->s, &touch->r );

		if( ISBRUSHMODEL( touch->s.modelindex ) )
			angles = touch->s.angles;
		else
			angles = vec3_origin; // boxes don't rotate

		trap_CM_TransformedBoxTrace( &trace, clip->start, clip->end,
			clip->mins, clip->maxs, cmodel, clip->contentmask,
			touch->s.origin, angles );

		if( trace.allsolid || trace.fraction < clip->trace->fraction )
		{
			trace.ent = touch->s.number;
			*( clip->trace ) = trace;
		}
		else if( trace.startsolid )
			clip->trace->startsolid = qtrue;
		if( clip->trace->allsolid )
			return;
	}
}
Beispiel #5
0
void G_SplashFrac4D( int entNum, vec3_t hitpoint, float maxradius, vec3_t pushdir, float *kickFrac, float *dmgFrac, int timeDelta )
{
	c4clipedict_t *clipEnt;

	clipEnt = GClip_GetClipEdictForDeltaTime( entNum, timeDelta );
	// racesow - weqo
	rs_SplashFrac( clipEnt->s.origin, clipEnt->r.mins, clipEnt->r.maxs, hitpoint, maxradius, pushdir, kickFrac, dmgFrac );
	// to use default settings:
	// G_SplashFrac( clipEnt->s.origin, clipEnt->r.mins, clipEnt->r.maxs, hitpoint, maxradius, pushdir, kickFrac, dmgFrac );
	// !racesow
}
Beispiel #6
0
entity_state_t *G_GetEntityStateForDeltaTime( int entNum, int deltaTime )
{
	c4clipedict_t *clipEnt;

	if( entNum == -1 )
		return NULL;

	assert( entNum >= 0 && entNum < MAX_EDICTS );

	clipEnt = GClip_GetClipEdictForDeltaTime( entNum, deltaTime );

	return &clipEnt->s;
}
Beispiel #7
0
/*
* GClip_AreaEdicts
* fills in a table of edict ids with edicts that have bounding boxes
* that intersect the given area.  It is possible for a non-axial bmodel
* to be returned that doesn't actually intersect the area on an exact
* test.
* returns the number of pointers filled in
* ??? does this always return the world?
*/
static int GClip_AreaEdicts( vec3_t mins, vec3_t maxs, int *list, int maxcount, int areatype, int timeDelta )
{
	link_t *l, *start;
	c4clipedict_t *clipEnt;
	int stackdepth = 0, count = 0;
	areanode_t *localstack[AREA_NODES], *node = sv_areanodes;

	while( 1 )
	{
		// touch linked edicts
		if( areatype == AREA_SOLID )
			start = &node->solid_edicts;
		else
			start = &node->trigger_edicts;

		for( l = start->next; l != start; l = l->next )
		{
			clipEnt = GClip_GetClipEdictForDeltaTime( l->entNum, timeDelta );

			if( clipEnt->r.solid == SOLID_NOT )
				continue; // deactivated

			if( !BoundsIntersect( clipEnt->r.absmin, clipEnt->r.absmax, mins, maxs ) )
				continue; // not touching

			if( count == maxcount )
			{
				G_Printf( "G_AreaEdicts: MAXCOUNT\n" );
				return count;
			}
			list[count++] = l->entNum;
		}

		if( node->axis == -1 )
			goto checkstack; // terminal node

		// recurse down both sides
		if( maxs[node->axis] > node->dist )
		{
			if( mins[node->axis] < node->dist )
			{
				localstack[stackdepth++] = node->children[0];
				node = node->children[1];
				continue;
			}
			node = node->children[0];
			continue;
		}
		if( mins[node->axis] < node->dist )
		{
			node = node->children[1];
			continue;
		}

checkstack:
		if( !stackdepth )
			return count;
		node = localstack[--stackdepth];
	}

	return count;
}
Beispiel #8
0
/*
* GClip_EntitiesInBox_AreaGrid
*/
static int GClip_EntitiesInBox_AreaGrid( areagrid_t *areagrid, const vec3_t mins, const vec3_t maxs, 
	int *list, int maxcount, int areatype, int timeDelta )
{
	int numlist;
	link_t *grid;
	link_t *l;
	c4clipedict_t *clipEnt;
	vec3_t paddedmins, paddedmaxs;
	int igrid[3], igridmins[3], igridmaxs[3];

	// LordHavoc: discovered this actually causes its own bugs (dm6 teleporters 
	// being too close to info_teleport_destination)
	//VectorSet( paddedmins, mins[0] - 1.0f, mins[1] - 1.0f, mins[2] - 1.0f );
	//VectorSet( paddedmaxs, maxs[0] + 1.0f, maxs[1] + 1.0f, maxs[2] + 1.0f );
	VectorCopy( mins, paddedmins );
	VectorCopy( maxs, paddedmaxs );

	// FIXME: if areagrid_marknumber wraps, all entities need their
	// ent->priv.server->areagridmarknumber reset
	areagrid->marknumber++;

	igridmins[0] = (int) floor( (paddedmins[0] + areagrid->bias[0]) * areagrid->scale[0] );
	igridmins[1] = (int) floor( (paddedmins[1] + areagrid->bias[1]) * areagrid->scale[1] );
	//igridmins[2] = (int) ( (paddedmins[2] + areagrid->bias[2]) * areagrid->scale[2] );
	igridmaxs[0] = (int) floor( (paddedmaxs[0] + areagrid->bias[0]) * areagrid->scale[0] ) + 1;
	igridmaxs[1] = (int) floor( (paddedmaxs[1] + areagrid->bias[1]) * areagrid->scale[1] ) + 1;
	//igridmaxs[2] = (int) ( (paddedmaxs[2] + areagrid->bias[2]) * areagrid->scale[2] ) + 1;
	igridmins[0] = max( 0, igridmins[0] );
	igridmins[1] = max( 0, igridmins[1] );
	//igridmins[2] = max( 0, igridmins[2] );
	igridmaxs[0] = min( AREA_GRID, igridmaxs[0] );
	igridmaxs[1] = min( AREA_GRID, igridmaxs[1] );
	//igridmaxs[2] = min( AREA_GRID, igridmaxs[2] );

	// paranoid debugging
	//VectorSet( igridmins, 0, 0, 0 );VectorSet( igridmaxs, AREA_GRID, AREA_GRID, AREA_GRID );

	numlist = 0;

	// add entities not linked into areagrid because they are too big or
	// outside the grid bounds
	if( areagrid->outside.next )
	{
		grid = &areagrid->outside;
		for( l = grid->next; l != grid; l = l->next ) {
			clipEnt = GClip_GetClipEdictForDeltaTime( l->entNum, timeDelta );

			if( areagrid->entmarknumber[l->entNum] == areagrid->marknumber ) {
				continue;
			}
			areagrid->entmarknumber[l->entNum] = areagrid->marknumber;

			if( !clipEnt->r.inuse ) {
				continue; // deactivated
			}
			if( areatype == AREA_TRIGGERS && clipEnt->r.solid != SOLID_TRIGGER ) {
				continue;
			}
			if( areatype == AREA_SOLID && 
				( clipEnt->r.solid == SOLID_TRIGGER || clipEnt->r.solid == SOLID_NOT ) ) {
				continue;
			}

			if( BoundsIntersect( paddedmins, paddedmaxs, clipEnt->r.absmin, clipEnt->r.absmax )) {
				if( numlist < maxcount ) {
					list[numlist] = l->entNum;
				}
				numlist++;
			}
		}
	}

	// add grid linked entities
	for( igrid[1] = igridmins[1]; igrid[1] < igridmaxs[1]; igrid[1]++ ) {
		grid = areagrid->grid + igrid[1] * AREA_GRID + igridmins[0];

		for( igrid[0] = igridmins[0]; igrid[0] < igridmaxs[0]; igrid[0]++, grid++ ) {
			if( !grid->next ) {
				continue;
			}

			for( l = grid->next; l != grid; l = l->next ) {
				clipEnt = GClip_GetClipEdictForDeltaTime( l->entNum, timeDelta );

				if( areagrid->entmarknumber[l->entNum] == areagrid->marknumber ) {
					continue;
				}
				areagrid->entmarknumber[l->entNum] = areagrid->marknumber;

				if( !clipEnt->r.inuse ) {
					continue; // deactivated
				}
				if( areatype == AREA_TRIGGERS && clipEnt->r.solid != SOLID_TRIGGER ) {
					continue;
				}
				if( areatype == AREA_SOLID && 
					( clipEnt->r.solid == SOLID_TRIGGER || clipEnt->r.solid == SOLID_NOT ) ) {
					continue;
				}

				if( BoundsIntersect( paddedmins, paddedmaxs, clipEnt->r.absmin, clipEnt->r.absmax )) {
					if( numlist < maxcount ) {
						list[numlist] = l->entNum;
					}
					numlist++;
				}
			}
		}
	}

	return numlist;
}