Ejemplo n.º 1
0
/*
====================
SV_ClipMoveToEntities

====================
*/
void SV_ClipMoveToEntities( moveclip_t *clip ) {
	int			i, num;
	int			touchlist[MAX_GENTITIES];
	sharedEntity_t *touch;
	int			passOwnerNum;
	trace_t		trace, oldTrace;
	clipHandle_t	clipHandle;
	float		*origin, *angles;
	int			thisOwnerShared = 1;

	num = SV_AreaEntities( clip->boxmins, clip->boxmaxs, touchlist, MAX_GENTITIES);

	if ( clip->passEntityNum != ENTITYNUM_NONE ) {
		passOwnerNum = ( SV_GentityNum( clip->passEntityNum ) )->r.ownerNum;
		if ( passOwnerNum == ENTITYNUM_NONE ) {
			passOwnerNum = -1;
		}
	} else {
		passOwnerNum = -1;
	}

	if ( SV_GentityNum(clip->passEntityNum)->r.svFlags & SVF_OWNERNOTSHARED )
	{
		thisOwnerShared = 0;
	}

	for ( i=0 ; i<num ; i++ ) {
		if ( clip->trace.allsolid ) {
			return;
		}
		touch = SV_GentityNum( touchlist[i] );

		// see if we should ignore this entity
		if ( clip->passEntityNum != ENTITYNUM_NONE ) {
			if ( touchlist[i] == clip->passEntityNum ) {
				continue;	// don't clip against the pass entity
			}
			if ( touch->r.ownerNum == clip->passEntityNum) {
				if (touch->r.svFlags & SVF_OWNERNOTSHARED)
				{
					if ( clip->contentmask != (MASK_SHOT | CONTENTS_LIGHTSABER) &&
						clip->contentmask != (MASK_SHOT))
					{ //it's not a laser hitting the other "missile", don't care then
						continue;
					}
				}
				else
				{
					continue;	// don't clip against own missiles
				}
			}
			if ( touch->r.ownerNum == passOwnerNum &&
				!(touch->r.svFlags & SVF_OWNERNOTSHARED) &&
				!thisOwnerShared ) {
				continue;	// don't clip against other missiles from our owner
			}
		}

		// if it doesn't have any brushes of a type we
		// are looking for, ignore it
		if ( ! ( clip->contentmask & touch->r.contents ) ) {
			continue;
		}

		if ((clip->contentmask == (MASK_SHOT|CONTENTS_LIGHTSABER) || clip->contentmask == MASK_SHOT) && (touch->r.contents > 0 && (touch->r.contents & CONTENTS_NOSHOT)))
		{
			continue;
		}

		// might intersect, so do an exact clip
		clipHandle = SV_ClipHandleForEntity (touch);

		origin = touch->r.currentOrigin;
		angles = touch->r.currentAngles;


		if ( !touch->r.bmodel ) {
			angles = vec3_origin;	// boxes don't rotate
		}

		CM_TransformedBoxTrace ( &trace, (float *)clip->start, (float *)clip->end,
			(float *)clip->mins, (float *)clip->maxs, clipHandle,  clip->contentmask,
			origin, angles, clip->capsule);

/*
Ghoul2 Insert Start
*/

		// keep these older variables around for a bit, incase we need to replace them in the Ghoul2 Collision check
		oldTrace = clip->trace;
/*
Ghoul2 Insert End
*/

		if ( trace.allsolid ) {
			clip->trace.allsolid = qtrue;
			trace.entityNum = touch->s.number;
		} else if ( trace.startsolid ) {
			clip->trace.startsolid = qtrue;
			trace.entityNum = touch->s.number;
		}

		if ( trace.fraction < clip->trace.fraction ) {
			qboolean	oldStart;

			// make sure we keep a startsolid from a previous trace
			oldStart = clip->trace.startsolid;

			trace.entityNum = touch->s.number;
			clip->trace = trace;
			clip->trace.startsolid = (qboolean)((unsigned)clip->trace.startsolid | (unsigned)oldStart);
		}
/*
Ghoul2 Insert Start
*/
#if 0
		// decide if we should do the ghoul2 collision detection right here
		if ((trace.entityNum == touch->s.number) && (clip->traceFlags))
		{
			// do we actually have a ghoul2 model here?
			if (touch->s.ghoul2)
			{
				int			oldTraceRecSize = 0;
				int			newTraceRecSize = 0;
				int			z;

				// we have to do this because sometimes you may hit a model's bounding box, but not actually penetrate the Ghoul2 Models polygons
				// this is, needless to say, not good. So we must check to see if we did actually hit the model, and if not, reset the trace stuff
				// to what it was to begin with

				// set our trace record size
				for (z=0;z<MAX_G2_COLLISIONS;z++)
				{
					if (clip->trace.G2CollisionMap[z].mEntityNum != -1)
					{
						oldTraceRecSize++;
					}
				}

				G2API_CollisionDetect(&clip->trace.G2CollisionMap[0], *((CGhoul2Info_v *)touch->s.ghoul2),
					touch->s.angles, touch->s.origin, svs.time, touch->s.number, clip->start, clip->end, touch->s.modelScale, G2VertSpaceServer, clip->traceFlags, clip->useLod);

				// set our new trace record size
 
				for (z=0;z<MAX_G2_COLLISIONS;z++)
				{
					if (clip->trace.G2CollisionMap[z].mEntityNum != -1)
					{
						newTraceRecSize++;
					}
				}

				// did we actually touch this model? If not, lets reset this ent as being hit..
				if (newTraceRecSize == oldTraceRecSize)
				{
					clip->trace = oldTrace;
				}
			}
		}
#endif
/*
Ghoul2 Insert End
*/
	}
}
Ejemplo n.º 2
0
static void SV_ClipMoveToEntities( moveclip_t *clip ) {
	static int	touchlist[MAX_GENTITIES];
	int			i, num;
	sharedEntity_t *touch;
	int			passOwnerNum;
	trace_t		trace, oldTrace= {0};
	clipHandle_t	clipHandle;
	float		*origin, *angles;
	int			thisOwnerShared = 1;

	num = SV_AreaEntities( clip->boxmins, clip->boxmaxs, touchlist, MAX_GENTITIES);

	if ( clip->passEntityNum != ENTITYNUM_NONE ) {
		passOwnerNum = ( SV_GentityNum( clip->passEntityNum ) )->r.ownerNum;
		if ( passOwnerNum == ENTITYNUM_NONE ) {
			passOwnerNum = -1;
		}
	} else {
		passOwnerNum = -1;
	}

	if ( SV_GentityNum(clip->passEntityNum)->r.svFlags & SVF_OWNERNOTSHARED )
	{
		thisOwnerShared = 0;
	}

	for ( i=0 ; i<num ; i++ ) {
		if ( clip->trace.allsolid ) {
			return;
		}
		touch = SV_GentityNum( touchlist[i] );

		// see if we should ignore this entity
		if ( clip->passEntityNum != ENTITYNUM_NONE ) {
			if ( touchlist[i] == clip->passEntityNum ) {
				continue;	// don't clip against the pass entity
			}
			if ( touch->r.ownerNum == clip->passEntityNum) {
				if (touch->r.svFlags & SVF_OWNERNOTSHARED)
				{
					if ( clip->contentmask != (MASK_SHOT | CONTENTS_LIGHTSABER) &&
						clip->contentmask != (MASK_SHOT))
					{ //it's not a laser hitting the other "missile", don't care then
						continue;
					}
				}
				else
				{
					continue;	// don't clip against own missiles
				}
			}
			if ( touch->r.ownerNum == passOwnerNum &&
				!(touch->r.svFlags & SVF_OWNERNOTSHARED) &&
				thisOwnerShared ) {
				continue;	// don't clip against other missiles from our owner
			}

			if (touch->s.eType == ET_MISSILE &&
				!(touch->r.svFlags & SVF_OWNERNOTSHARED) &&
				touch->r.ownerNum == passOwnerNum)
			{ //blah, hack
				continue;
			}
		}

		// if it doesn't have any brushes of a type we
		// are looking for, ignore it
		if ( ! ( clip->contentmask & touch->r.contents ) ) {
			continue;
		}

		if ((clip->contentmask == (MASK_SHOT|CONTENTS_LIGHTSABER) || clip->contentmask == MASK_SHOT) && (touch->r.contents > 0 && (touch->r.contents & CONTENTS_NOSHOT)))
		{
			continue;
		}

		// might intersect, so do an exact clip
		clipHandle = SV_ClipHandleForEntity (touch);

		origin = touch->r.currentOrigin;
		angles = touch->r.currentAngles;


		if ( !touch->r.bmodel ) {
			angles = vec3_origin;	// boxes don't rotate
		}

		CM_TransformedBoxTrace ( &trace, (float *)clip->start, (float *)clip->end,
			(float *)clip->mins, (float *)clip->maxs, clipHandle,  clip->contentmask,
			origin, angles, clip->capsule);


		if (clip->traceFlags & G2TRFLAG_DOGHOULTRACE)
		{ // keep these older variables around for a bit, incase we need to replace them in the Ghoul2 Collision check
			oldTrace = clip->trace;
		}

		if ( trace.allsolid ) {
			clip->trace.allsolid = qtrue;
			trace.entityNum = touch->s.number;
		} else if ( trace.startsolid ) {
			clip->trace.startsolid = qtrue;
			trace.entityNum = touch->s.number;

			//rww - added this because we want to get the number of an ent even if our trace starts inside it.
			clip->trace.entityNum = touch->s.number;
		}

		if ( trace.fraction < clip->trace.fraction ) {
			byte	oldStart;

			// make sure we keep a startsolid from a previous trace
			oldStart = clip->trace.startsolid;

			trace.entityNum = touch->s.number;
			clip->trace = trace;
			clip->trace.startsolid = (qboolean)((unsigned)clip->trace.startsolid | (unsigned)oldStart);
		}
/*
Ghoul2 Insert Start
*/
#if 0
		// decide if we should do the ghoul2 collision detection right here
		if ((trace.entityNum == touch->s.number) && (clip->traceFlags))
		{
			// do we actually have a ghoul2 model here?
			if (touch->s.ghoul2)
			{
				int			oldTraceRecSize = 0;
				int			newTraceRecSize = 0;
				int			z;

				// we have to do this because sometimes you may hit a model's bounding box, but not actually penetrate the Ghoul2 Models polygons
				// this is, needless to say, not good. So we must check to see if we did actually hit the model, and if not, reset the trace stuff
				// to what it was to begin with

				// set our trace record size
				for (z=0;z<MAX_G2_COLLISIONS;z++)
				{
					if (clip->trace.G2CollisionMap[z].mEntityNum != -1)
					{
						oldTraceRecSize++;
					}
				}

				G2API_CollisionDetect(&clip->trace.G2CollisionMap[0], *((CGhoul2Info_v *)touch->s.ghoul2),
					touch->s.angles, touch->s.origin, svs.time, touch->s.number, clip->start, clip->end, touch->s.modelScale, G2VertSpaceServer, clip->traceFlags, clip->useLod);

				// set our new trace record size

				for (z=0;z<MAX_G2_COLLISIONS;z++)
				{
					if (clip->trace.G2CollisionMap[z].mEntityNum != -1)
					{
						newTraceRecSize++;
					}
				}

				// did we actually touch this model? If not, lets reset this ent as being hit..
				if (newTraceRecSize == oldTraceRecSize)
				{
					clip->trace = oldTrace;
				}
			}
		}
#else
		//rww - since this is multiplayer and we don't have the luxury of violating networking rules in horrible ways,
		//this must be done somewhat differently.
		if ((clip->traceFlags & G2TRFLAG_DOGHOULTRACE) && trace.entityNum == touch->s.number && touch->ghoul2 && ((clip->traceFlags & G2TRFLAG_HITCORPSES) || !(touch->s.eFlags & EF_DEAD)))
		{ //standard behavior will be to ignore g2 col on dead ents, but if traceFlags is set to allow, then we'll try g2 col on EF_DEAD people too.
			static G2Trace_t G2Trace;
			vec3_t angles;
			float fRadius = 0.0f;
			int tN = 0;
			int bestTr = -1;

			if (clip->mins[0] ||
				clip->maxs[0])
			{
				fRadius=(clip->maxs[0]-clip->mins[0])/2.0f;
			}

			if (clip->traceFlags & G2TRFLAG_THICK)
			{ //if using this flag, make sure it's at least 1.0f
				if (fRadius < 1.0f)
				{
					fRadius = 1.0f;
				}
			}

			memset (&G2Trace, 0, sizeof(G2Trace));
			while (tN < MAX_G2_COLLISIONS)
			{
				G2Trace[tN].mEntityNum = -1;
				tN++;
			}

			if (touch->s.number < MAX_CLIENTS)
			{
				VectorCopy(touch->s.apos.trBase, angles);
			}
			else
			{
				VectorCopy(touch->r.currentAngles, angles);
			}
			angles[ROLL] = angles[PITCH] = 0;

			//I would think that you could trace from trace.endpos instead of clip->start, but that causes it to miss sometimes.. Not sure what it's off, but if it could be done like that, it would probably
			//be faster.
#ifndef FINAL_BUILD
			if (sv_showghoultraces->integer)
			{
				Com_Printf( "Ghoul2 trace   lod=%1d   length=%6.0f   to %s\n",clip->useLod,VectorDistance(clip->start, clip->end), re->G2API_GetModelName (*(CGhoul2Info_v *)touch->ghoul2, 0));
			}
#endif

			if (com_optvehtrace &&
				com_optvehtrace->integer &&
				touch->s.eType == ET_NPC &&
				touch->s.NPC_class == CLASS_VEHICLE &&
				touch->m_pVehicle)
			{ //for vehicles cache the transform data.
				re->G2API_CollisionDetectCache(G2Trace, *((CGhoul2Info_v *)touch->ghoul2), angles, touch->r.currentOrigin, svs.time, touch->s.number, clip->start, clip->end, touch->modelScale, G2VertSpaceServer, 0, clip->useLod, fRadius);
			}
			else
			{
				re->G2API_CollisionDetect(G2Trace, *((CGhoul2Info_v *)touch->ghoul2), angles, touch->r.currentOrigin, svs.time, touch->s.number, clip->start, clip->end, touch->modelScale, G2VertSpaceServer, 0, clip->useLod, fRadius);
			}

			tN = 0;
			while (tN < MAX_G2_COLLISIONS)
			{
				if (G2Trace[tN].mEntityNum == touch->s.number)
				{ //ok, valid
					bestTr = tN;
					break;
				}
				else if (G2Trace[tN].mEntityNum == -1)
				{ //there should not be any after the first -1
					break;
				}
				tN++;
			}

			if (bestTr == -1)
			{ //Well then, put the trace back to the old one.
				clip->trace = oldTrace;
			}
			else
			{ //Otherwise, set the endpos/normal/etc. to the model location hit instead of leaving it out in space.
				VectorCopy(G2Trace[bestTr].mCollisionPosition, clip->trace.endpos);
				VectorCopy(G2Trace[bestTr].mCollisionNormal, clip->trace.plane.normal);

				if (clip->traceFlags & G2TRFLAG_GETSURFINDEX)
				{ //we have requested that surfaceFlags be stomped over with the g2 hit surface index.
					if (clip->trace.entityNum == G2Trace[bestTr].mEntityNum)
					{
						clip->trace.surfaceFlags = G2Trace[bestTr].mSurfaceIndex;
					}
				}
			}
		}
#endif
/*
Ghoul2 Insert End
*/
	}
}