public trace_t SV_Trace(Vector3 start, Vector3 end, Vector3 mins, Vector3 maxs, int passEntityNum, int contentMask) { trace_t results; if (mins == null) mins = Vector3.Zero; if (maxs == null) maxs = Vector3.Zero; // clip to world MoveClip clip = new MoveClip(); clip.trace = ClipMap.Instance.Box_Trace(start, end, mins, maxs, 0, contentMask); clip.trace.entityNum = (clip.trace.fraction != 1.0f) ? 1022 : 1023; if (clip.trace.fraction == 0f) { return clip.trace; // blocked immediately by the world } clip.contentmask = contentMask; clip.start = start; clip.end = end; clip.mins = mins; clip.maxs = maxs; clip.passEntityNum = passEntityNum; clip.capsule = 0; // create the bounding box of the entire move // we can limit it to the part of the move not // already clipped off by the world, which can be // a significant savings for line of sight and shot traces for (int i = 0; i < 3; i++) { if (end[i] > start[i]) { clip.boxmins[i] = clip.start[i] + clip.mins[i] - 1; clip.boxmaxs[i] = clip.end[i] + clip.maxs[i] + 1; } else { clip.boxmins[i] = clip.end[i] + clip.mins[i] - 1; clip.boxmaxs[i] = clip.start[i] + clip.maxs[i] + 1; } } // clip to other solid entities ClipMoveToEntities(clip); results = clip.trace; return results; }
void ClipMoveToEntities(MoveClip clip) { AreaParams ap = AreaEntities(clip.boxmins, clip.boxmaxs, 1024); int passownernum; if (clip.passEntityNum != 1023) { passownernum = sv.gentities[clip.passEntityNum].r.ownerNum; if (passownernum == 1023) passownernum = -1; } else passownernum = -1; for (int i = 0; i < ap.count; i++) { if (clip.trace.allsolid) return; sharedEntity touch = sv.gentities[ap.list[i]]; // see if we should ignore this entity if (clip.passEntityNum != 1023) { if (ap.list[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) == 0) continue; // might intersect, so do an exact clip int clipHandle = ClipHandleForEntity(touch); Vector3 origin = touch.r.currentOrigin; Vector3 angles = touch.r.currentAngles; if (!touch.r.bmodel) angles = Vector3.Zero; trace_t trace = ClipMap.Instance.TransformedBoxTrace(clip.start, clip.end, clip.mins, clip.maxs, clipHandle, clip.contentmask, origin, angles); if (trace.allsolid) { clip.trace.allsolid = true; trace.entityNum = touch.s.number; } else if (trace.startsolid) { clip.trace.startsolid = true; trace.entityNum = touch.s.number; } if (trace.fraction < clip.trace.fraction) { bool oldstart = clip.trace.startsolid; trace.entityNum = touch.s.number; clip.trace = trace; clip.trace.startsolid |= oldstart; } } }