/* ======================================================================================================================================= SV_PointContents ======================================================================================================================================= */ int SV_PointContents(const vec3_t p, int passEntityNum) { int touch[MAX_GENTITIES]; sharedEntity_t *hit; int i, num; int contents, c2; clipHandle_t clipHandle; float *angles; // get base contents from world contents = CM_PointContents(p, 0); // or in contents from all the other entities num = SV_AreaEntities(p, p, touch, MAX_GENTITIES); for (i = 0; i < num; i++) { if (touch[i] == passEntityNum) { continue; } hit = SV_GentityNum(touch[i]); // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity(hit); angles = hit->r.currentAngles; if (!hit->r.bmodel) { angles = vec3_origin; // boxes don't rotate } // ignore this test if the origin is at the world origin // if (!VectorCompare(hit->s.origin, vec3_origin)) { c2 = CM_TransformedPointContents(p, clipHandle, hit->r.currentOrigin, angles); contents |= c2; //} } return contents; }
/* ==================== SV_ClipToEntity ==================== */ void SV_ClipToEntity( trace_t *trace, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int entityNum, int contentmask, traceType_t type ) { sharedEntity_t *touch; clipHandle_t clipHandle; float *origin, *angles; touch = SV_GentityNum( entityNum ); Com_Memset(trace, 0, sizeof(trace_t)); // if it doesn't have any brushes of a type we // are looking for, ignore it if ( ! ( contentmask & touch->r.contents ) ) { trace->fraction = 1.0; return; } // 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 *)start, (float *)end, (float *)mins, (float *)maxs, clipHandle, contentmask, origin, angles, type); if ( trace->fraction < 1 ) { trace->entityNum = touch->s.number; } }
/* ============= SV_PointContents ============= */ int SV_PointContents( const vec3_t p, int passEntityNum ) { int touch[MAX_GENTITIES]; sharedEntity_t *hit; int i, num; int contents, c2; clipHandle_t clipHandle; // get base contents from world contents = CM_PointContents( p, 0 ); // or in contents from all the other entities num = SV_AreaEntities( p, p, touch, MAX_GENTITIES ); for ( i=0 ; i<num ; i++ ) { if ( touch[i] == passEntityNum ) { continue; } hit = SV_GentityNum( touch[i] ); // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity( hit ); c2 = CM_TransformedPointContents (p, clipHandle, hit->s.origin, hit->s.angles); contents |= c2; } return contents; }
/* ================== SV_GameAreaEntities ================== */ bool SV_EntityContact(vec3_t mins, vec3_t maxs, const sharedEntity_t * gEnt, traceType_t type) { const float *origin, *angles; clipHandle_t ch; trace_t trace; // check for exact collision origin = gEnt->r.currentOrigin; angles = gEnt->r.currentAngles; ch = SV_ClipHandleForEntity( gEnt ); CM_TransformedBoxTrace(&trace, vec3_origin, vec3_origin, mins, maxs, ch, -1, origin, angles, type); return trace.startsolid; }
/* ============= SV_PointContents ============= */ int SV_PointContents( const vec3_t p, int passEntityNum ) { int touch[ MAX_GENTITIES ]; sharedEntity_t *hit; int i, num; int contents, c2; clipHandle_t clipHandle; // float *angles; // get base contents from world contents = CM_PointContents( p, 0 ); // or in contents from all the other entities num = SV_AreaEntities( p, p, touch, MAX_GENTITIES ); for ( i = 0; i < num; i++ ) { if ( touch[ i ] == passEntityNum ) { continue; } hit = SV_GentityNum( touch[ i ] ); // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity( hit ); // ydnar: non-worldspawn entities must not use world as clip model! if ( clipHandle == 0 ) { continue; } // angles = hit->r.currentAngles; /* if(!hit->r.bmodel) { angles = vec3_origin; // boxes don't rotate } */ c2 = CM_TransformedPointContents( p, clipHandle, hit->r.currentOrigin, hit->r.currentAngles ); // Gordon: s.origin/angles is base origin/angles, need to use the current origin/angles for moving entity based water, or water locks in movement start position. // c2 = CM_TransformedPointContents (p, clipHandle, hit->s.origin, hit->s.angles); contents |= c2; } return contents; }
/* ============= SV_PointContents ============= */ int SV_PointContents( const vec3_t p, int passEntityNum ) { int touch[MAX_GENTITIES]; sharedEntity_t *hit; int i, num; int contents, c2; clipHandle_t clipHandle; float *angles; // get base contents from world contents = CM_PointContents( p, 0 ); // or in contents from all the other entities num = SV_AreaEntities( p, p, touch, MAX_GENTITIES ); for ( i=0 ; i<num ; i++ ) { if ( touch[i] == passEntityNum ) { continue; } hit = SV_GentityNum( touch[i] ); // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity( hit ); // non-worldspawn entities must not use world as clip model! if ( clipHandle == 0 ) { continue; } angles = hit->r.currentAngles; if ( !hit->s.bmodel ) { angles = vec3_origin; // boxes don't rotate } c2 = CM_TransformedPointContents (p, clipHandle, hit->r.currentOrigin, angles); contents |= c2; } return contents; }
/* * SV_ClipToEntity * */ void SV_ClipToEntity(Trace *trace, const Vec3 start, const Vec3 mins, const Vec3 maxs, const Vec3 end, int entityNum, int contentmask, int capsule) { Sharedent *touch; Cliphandle clipHandle; float *origin, *angles; touch = SV_GentityNum(entityNum); Q_Memset(trace, 0, sizeof(Trace)); /* if it doesn't have any brushes of a type we * are looking for, ignore it */ if(!(contentmask & touch->r.contents)){ trace->fraction = 1.0; return; } /* 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*)start, (float*)end, (float*)mins, (float*)maxs, clipHandle, contentmask, origin, angles, capsule); if(trace->fraction < 1) trace->entityNum = touch->s.number; }
/* * SV_PointContents */ int SV_PointContents(const Vec3 p, int passEntityNum) { int touch[MAX_GENTITIES]; Sharedent *hit; int i, num; int contents, c2; Cliphandle clipHandle; float *angles; /* get base contents from world */ contents = CM_PointContents(p, 0); /* or in contents from all the other entities */ num = SV_AreaEntities(p, p, touch, MAX_GENTITIES); for(i=0; i<num; i++){ if(touch[i] == passEntityNum) continue; hit = SV_GentityNum(touch[i]); /* might intersect, so do an exact clip */ clipHandle = SV_ClipHandleForEntity(hit); angles = hit->r.currentAngles; if(!hit->r.bmodel) angles = vec3_origin; /* boxes don't rotate */ c2 = CM_TransformedPointContents (p, clipHandle, hit->r.currentOrigin, angles); contents |= c2; } return contents; }
/* ==================== SV_ClipMoveToEntities ==================== */ static void SV_ClipMoveToEntities( moveclip_t *clip ) { int i, num; int touchlist[MAX_GENTITIES]; sharedEntity_t *touch; int passOwnerNum; trace_t trace; clipHandle_t clipHandle; float *origin, *angles; 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; } 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.svFlags & SVF_OWNERNOTSHARED) && touch->r.ownerNum == clip->passEntityNum ) { continue; // don't clip against own missiles } if ( !(touch->r.svFlags & SVF_OWNERNOTSHARED) && touch->r.ownerNum == passOwnerNum ) { 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; } // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity (touch); if ( clipHandle == 0 ) { continue; } 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 ( 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 |= oldStart; } } }
/* ======================================================================================================================================= SV_ClipMoveToEntities ======================================================================================================================================= */ void SV_ClipMoveToEntities(moveclip_t *clip) { int i, num; int touchlist[MAX_GENTITIES]; sharedEntity_t *touch; int passOwnerNum; trace_t trace; clipHandle_t clipHandle; float *origin, *angles; 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; } 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) { continue; // don't clip against own missiles } if (touch->r.ownerNum == passOwnerNum) { 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; } // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity(touch); // non-worldspawn entities must not use world as clip model! if (clipHandle == 0) { continue; } // if clipping against BBOX, set to correct contents if (clipHandle == BOX_MODEL_HANDLE) { CM_SetTempBoxModelContents(touch->r.contents); } origin = touch->r.currentOrigin; angles = touch->r.currentAngles; if (!touch->r.bmodel) { angles = vec3_origin; // boxes don't rotate } CM_TransformedBoxTrace(&trace, clip->start, clip->end, clip->mins, clip->maxs, clipHandle, clip->contentmask, origin, angles, clip->capsule); 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) { // make sure we keep a startsolid from a previous trace qboolean oldStart = clip->trace.startsolid; trace.entityNum = touch->s.number; clip->trace = trace; clip->trace.startsolid |= oldStart; } // reset contents to default if (clipHandle == BOX_MODEL_HANDLE) { CM_SetTempBoxModelContents(CONTENTS_BODY); } } }
/* ==================== 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 */ } }
__cdecl void SV_ClipMoveToEntity(moveclip_t *clip, svEntity_t *entity, trace_t *trace){ gentity_t *touch; int touchNum; float *origin, *angles; vec3_t mins, maxs; float oldfraction; clipHandle_t clipHandle; touchNum = entity - sv.svEntities; touch = SV_GentityNum( touchNum ); if( !(clip->contentmask & touch->r.contents)) return; if ( clip->passEntityNum != ENTITYNUM_NONE ) { if( touchNum == clip->passEntityNum ) return; if(touch->r.ownerNum){ if( touch->r.ownerNum - 1 == clip->passEntityNum ) return; if( touch->r.ownerNum - 1 == clip->passOwnerNum ) return; } if(!G_ShouldEntitiesClip(clip, touchNum, touch)) return; } VectorAdd(touch->r.absmin, clip->mins, mins); VectorAdd(touch->r.absmax, clip->maxs, maxs); if(CM_TraceBox(clip->extents.start, mins, maxs, trace->fraction)) return; clipHandle = SV_ClipHandleForEntity(touch); origin = touch->r.currentOrigin; angles = touch->r.currentAngles; if ( !touch->r.bmodel ) { angles = vec3_origin; // boxes don't rotate } oldfraction = trace->fraction; CM_TransformedBoxTrace( trace, clip->extents.start, clip->extents.end, clip->mins, clip->maxs, clipHandle, clip->contentmask, origin, angles ); if ( trace->fraction < oldfraction ) { trace->var_02 = qtrue; trace->entityNum = touch->s.number; } }
static void SV_ClipMoveToEntities( moveclip_t *clip ) { int i, num; int touchlist[MAX_GENTITIES]; sharedEntity_t *touch; int passOwnerNum; trace_t trace; clipHandle_t clipHandle; vector3 *origin, *angles; 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; } 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 } //QTZTODO: Missiles colliding with eachother from https://github.com/dmead/jkaq3/commit/1d1e1fefb04fab8ceb42537702d946c1a75f4812 if ( touch->r.ownerNum == clip->passEntityNum // don't clip against own missiles || touch->r.ownerNum == passOwnerNum ) // don't clip against other missiles from our owner continue; } // if it doesn't have any brushes of a type we // are looking for, ignore it if ( ! ( clip->contentmask & touch->r.contents ) ) { 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, (vector3 *)clip->start, &clip->end, (vector3 *)clip->mins, (vector3 *)clip->maxs, clipHandle, clip->contentmask, origin, angles, clip->capsule ); 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 |= oldStart; } } }
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 */ } }
/* * SV_ClipMoveToEntities * */ static void SV_ClipMoveToEntities(moveclip_t *clip) { int i, num; int touchlist[MAX_GENTITIES]; Sharedent *touch; int passOwnerNum; Trace trace; Cliphandle clipHandle; float *origin, *angles; 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; 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) continue; /* don't clip against own missiles */ if(touch->r.ownerNum == passOwnerNum) 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; /* 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(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){ qbool 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 |= oldStart; } } }