Пример #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;
}
Пример #2
0
/*
* GClip_FindBoxInRadius
* Returns entities that have their boxes within a spherical area
*/
int GClip_FindBoxInRadius4D( vec3_t org, float rad, int *list, int maxcount, int timeDelta )
{
	int i, num;
	int listnum;
	edict_t *check;
	vec3_t mins, maxs;
	float rad_ = rad * 1.42;
	int touch[MAX_EDICTS];

	VectorSet( mins, org[0] - (rad_ + 1), org[1] - (rad_ + 1), org[2] - (rad_ + 1) );
	VectorSet( maxs, org[0] + (rad_ + 1), org[1] + (rad_ + 1), org[2] + (rad_ + 1) );

	listnum = 0;
	num = GClip_AreaEdicts( mins, maxs, touch, MAX_EDICTS, AREA_ALL, timeDelta );

	for( i = 0; i < num; i++ )
	{
		check = EDICT_NUM( touch[i] );

		// make absolute mins and maxs
		if( !BoundsAndSphereIntersect( check->r.absmin, check->r.absmax, org, rad ) )
			continue;
		if( check->s.solid == SOLID_NOT )
			continue;

		if( listnum < maxcount ) {
			list[listnum] = touch[i];
		}
		listnum++;
	}

	return listnum;
}
Пример #3
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;
	}
}
Пример #4
0
/*
* GClip_TouchTriggers
*/
void GClip_TouchTriggers( edict_t *ent )
{
	int i, num;
	edict_t	*hit;
	int touch[MAX_EDICTS];
	vec3_t mins, maxs;

	// dead things don't activate triggers!
	if( ent->r.client && G_IsDead( ent ) )
		return;

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

	// FIXME: should be s.origin + mins and s.origin + maxs because of absmin and absmax padding?
	num = GClip_AreaEdicts( ent->r.absmin, ent->r.absmax, touch, MAX_EDICTS, AREA_TRIGGERS, 0 );

	// 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++ )
	{
		if( !ent->r.inuse )
			break;

		hit = &game.edicts[touch[i]];
		if( !hit->r.inuse )
			continue;

		if( !hit->touch && !hit->asTouchFunc )
			continue;

		if( !hit->item && !GClip_EntityContact( mins, maxs, hit ) )
			continue;

		G_CallTouch( hit, ent, NULL, 0 );
	}
}
Пример #5
0
void G_PMoveTouchTriggers( pmove_t *pm )
{
	int i, num;
	edict_t	*hit;
	int touch[MAX_EDICTS];
	vec3_t mins, maxs;
	edict_t	*ent;

	if( pm->playerState->POVnum <= 0 || (int)pm->playerState->POVnum > gs.maxclients )
		return;

	ent = game.edicts + pm->playerState->POVnum;
	if( !ent->r.client || G_IsDead( ent ) )  // dead things don't activate triggers!
		return;

	// update the entity with the new position
	VectorCopy( pm->playerState->pmove.origin, ent->s.origin );
	VectorCopy( pm->playerState->pmove.velocity, ent->velocity );
	VectorCopy( pm->playerState->viewangles, ent->s.angles );
	ent->viewheight = pm->playerState->viewheight;
	VectorCopy( pm->mins, ent->r.mins );
	VectorCopy( pm->maxs, ent->r.maxs );

	ent->waterlevel = pm->waterlevel;
	ent->watertype = pm->watertype;
	if( pm->groundentity == -1 )
	{
		ent->groundentity = NULL;
	}
	else
	{
		ent->groundentity = &game.edicts[pm->groundentity];
		ent->groundentity_linkcount = ent->groundentity->r.linkcount;
	}

	GClip_LinkEntity( ent );

	VectorAdd( pm->playerState->pmove.origin, pm->mins, mins );
	VectorAdd( pm->playerState->pmove.origin, pm->maxs, maxs );

	num = GClip_AreaEdicts( mins, maxs, touch, MAX_EDICTS, AREA_TRIGGERS, 0 );

	// 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++ )
	{
		if( !ent->r.inuse )
			break;

		hit = &game.edicts[touch[i]];
		if( !hit->r.inuse )
			continue;

		if( !hit->touch && !hit->asTouchFunc )
			continue;

		if( !hit->item && !GClip_EntityContact( mins, maxs, hit ) )
			continue;

		G_CallTouch( hit, ent, NULL, 0 );
	}
}