/** * @brief Moves the given box volume through the world from start to end. * * The skipped edict, and edicts owned by him, are explicitly not checked. * This prevents players from clipping against their own projectiles, etc. */ cm_trace_t Sv_Trace(const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, const g_entity_t *skip, const int32_t contents) { sv_trace_t trace; memset(&trace, 0, sizeof(trace)); if (!mins) { mins = vec3_origin; } if (!maxs) { maxs = vec3_origin; } // clip to world trace.trace = Cm_BoxTrace(start, end, mins, maxs, 0, contents); if (trace.trace.fraction < 1.0) { trace.trace.ent = svs.game->entities; if (trace.trace.start_solid) { // blocked entirely return trace.trace; } } trace.start = start; trace.end = end; trace.mins = mins; trace.maxs = maxs; trace.skip = skip; trace.contents = contents; // create the bounding box of the entire move Cm_TraceBounds(start, end, mins, maxs, trace.box_mins, trace.box_maxs); // clip to other solid entities Sv_ClipTraceToEntities(&trace); return trace.trace; }
/** * @brief Client-side collision model tracing. This is the reciprocal of * Sv_Trace. * * @param skip An optional entity number for which all tests are skipped. Pass * 0 for none, because entity 0 is the world, which we always test. */ cm_trace_t Cl_Trace(const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, const uint16_t skip, const int32_t contents) { cl_trace_t trace; memset(&trace, 0, sizeof(trace)); if (!mins) { mins = vec3_origin; } if (!maxs) { maxs = vec3_origin; } // clip to world trace.trace = Cm_BoxTrace(start, end, mins, maxs, 0, contents); if (trace.trace.fraction < 1.0) { trace.trace.ent = (struct g_entity_s *) (intptr_t) - 1; if (trace.trace.start_solid) { // blocked entirely return trace.trace; } } trace.start = start; trace.end = end; trace.mins = mins; trace.maxs = maxs; trace.skip = skip; trace.contents = contents; Cm_TraceBounds(start, end, mins, maxs, trace.box_mins, trace.box_maxs); Cl_ClipTraceToEntities(&trace); return trace.trace; }