/* ================== SV_ClipMoveToEntity Handles selection or creation of a clipping hull, and offseting (and eventually rotation) of the end points ================== */ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end) { trace_t trace; vec3_t offset; vec3_t start_l, end_l; hull_t *hull; // get the clipping hull hull = SV_HullForEntity (ent, mins, maxs, offset); VectorSubtract (start, offset, start_l); VectorSubtract (end, offset, end_l); // trace a line through the apropriate clipping hull trace = CM_HullTrace (hull, start_l, end_l); // fix trace up by the offset VectorAdd (trace.endpos, offset, trace.endpos); // did we clip the move? if (trace.fraction < 1 || trace.startsolid ) trace.e.ent = ent; return trace; }
/* ============= SV_PointContents ============= */ int SV_PointContents (vec3_t p) { edict_t *touch[MAX_EDICTS], *hit; int i, num; int contents, c2; int headnode; float *angles; // get base contents from world contents = CM_PointContents (p, sv.models[1]->headnode); // or in contents from all the other entities num = SV_AreaEdicts (p, p, touch, MAX_EDICTS, AREA_SOLID); for (i=0 ; i<num ; i++) { hit = touch[i]; // might intersect, so do an exact clip headnode = SV_HullForEntity (hit); angles = hit->s.angles; if (hit->solid != SOLID_BSP) angles = vec3_origin; // boxes don't rotate c2 = CM_TransformedPointContents (p, headnode, hit->s.origin, hit->s.angles); contents |= c2; } return contents; }
/* ============= SV_PointContents ============= */ int SV_PointContents(vec3_t p) { edict_t *touch[MAX_EDICTS], *hit; int i, num; int contents; if (!sv.cm.cache) { Com_Error(ERR_DROP, "%s: no map loaded", __func__); } // get base contents from world contents = CM_PointContents(p, sv.cm.cache->nodes); // or in contents from all the other entities num = SV_AreaEdicts(p, p, touch, MAX_EDICTS, AREA_SOLID); for (i = 0; i < num; i++) { hit = touch[i]; // might intersect, so do an exact clip contents |= CM_TransformedPointContents(p, SV_HullForEntity(hit), hit->s.origin, hit->s.angles); } return contents; }
/* * ==================== SV_ClipMoveToEntities * * ==================== */ void SV_ClipMoveToEntities(moveclip_t * clip) { int i, num; edict_t *touchlist[MAX_EDICTS], *touch; trace_t trace; int headnode; float *angles; num = SV_AreaEdicts(clip->boxmins, clip->boxmaxs, touchlist ,MAX_EDICTS, AREA_SOLID); /* 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 = touchlist[i]; if (touch->solid == SOLID_NOT) continue; if (touch == clip->passedict) continue; if (clip->trace.allsolid) return; if (clip->passedict) { if (touch->owner == clip->passedict) continue; /* don't clip against own * missiles */ if (clip->passedict->owner == touch) continue; /* don't clip against owner */ } if (!(clip->contentmask & CONTENTS_DEADMONSTER) && (touch->svflags & SVF_DEADMONSTER)) continue; /* might intersect, so do an exact clip */ headnode = SV_HullForEntity(touch); angles = touch->s.angles; if (touch->solid != SOLID_BSP) angles = vec3_origin; /* boxes don't rotate */ if (touch->svflags & SVF_MONSTER) trace = CM_TransformedBoxTrace(clip->start, clip->end, clip->mins2, clip->maxs2, headnode, clip->contentmask, touch->s.origin, angles); else trace = CM_TransformedBoxTrace(clip->start, clip->end, clip->mins, clip->maxs, headnode, clip->contentmask, touch->s.origin, angles); if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction) { trace.ent = touch; if (clip->trace.startsolid) { clip->trace = trace; clip->trace.startsolid = true; } else clip->trace = trace; } else if (trace.startsolid) clip->trace.startsolid = true; } }
IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) { // Static props should never be in the trigger list Assert( !StaticPropMgr()->IsStaticProp( pHandleEntity ) ); IServerNetworkable *pNetworkable = static_cast<IServerNetworkable*>( pHandleEntity ); Assert( pNetworkable ); // Convert the IHandleEntity to an edict_t*... // Context is the thing we're testing everything against edict_t* pTouch = pNetworkable->GetEdict(); // Can't bump against itself if ( pTouch == m_pEnt ) return ITERATION_CONTINUE; IServerEntity *serverEntity = pTouch->GetIServerEntity(); if ( !serverEntity ) return ITERATION_CONTINUE; // Hmmm.. everything in this list should be a trigger.... ICollideable *pCollideable = serverEntity->GetCollideable(); Assert(pCollideable->GetSolidFlags() & FSOLID_TRIGGER ); if ( (pCollideable->GetSolidFlags() & FSOLID_TRIGGER) == 0 ) return ITERATION_CONTINUE; model_t* pModel = sv.GetModel( pCollideable->GetCollisionModelIndex() ); if ( pModel && pModel->type == mod_brush ) { int headnode = SV_HullForEntity( pTouch ); int contents; if (!m_Ray.m_IsSwept) { contents = CM_TransformedBoxContents( m_Ray.m_Start, m_mins, m_maxs, headnode, serverEntity->GetAbsOrigin(), serverEntity->GetAbsAngles() ); } else { trace_t trace; CM_TransformedBoxTrace( m_Ray, headnode, MASK_ALL, serverEntity->GetAbsOrigin(), serverEntity->GetAbsAngles(), trace ); contents = trace.contents; } if ( !(contents & MASK_SOLID) ) return ITERATION_CONTINUE; } m_TouchedEntities.AddToTail( pTouch ); return ITERATION_CONTINUE; }
/* ==================== SV_ClipMoveToEntities ==================== */ static void SV_ClipMoveToEntities(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask, trace_t *tr) { vec3_t boxmins, boxmaxs; int i, num; edict_t *touchlist[MAX_EDICTS], *touch; trace_t trace; // create the bounding box of the entire move for (i = 0; i < 3; i++) { if (end[i] > start[i]) { boxmins[i] = start[i] + mins[i] - 1; boxmaxs[i] = end[i] + maxs[i] + 1; } else { boxmins[i] = end[i] + mins[i] - 1; boxmaxs[i] = start[i] + maxs[i] + 1; } } num = SV_AreaEdicts(boxmins, boxmaxs, touchlist, MAX_EDICTS, AREA_SOLID); // 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 = touchlist[i]; if (touch->solid == SOLID_NOT) continue; if (touch == passedict) continue; if (tr->allsolid) return; if (passedict) { if (touch->owner == passedict) continue; // don't clip against own missiles if (passedict->owner == touch) continue; // don't clip against owner } if (!(contentmask & CONTENTS_DEADMONSTER) && (touch->svflags & SVF_DEADMONSTER)) continue; // might intersect, so do an exact clip CM_TransformedBoxTrace(&trace, start, end, mins, maxs, SV_HullForEntity(touch), contentmask, touch->s.origin, touch->s.angles); CM_ClipEntity(tr, &trace, touch); } }
CTriggerMoved( edict_t *pTriggerEntity ) : m_TouchedEntities( 8, 8 ) { m_headnode = -1; m_pTriggerEntity = pTriggerEntity; IServerEntity *pServerTrigger = pTriggerEntity->GetIServerEntity(); if ( !pServerTrigger ) { m_origin.Init(); m_angles.Init(); } else { model_t *pModel = sv.GetModel( pServerTrigger->GetModelIndex() ); if ( pModel && pModel->type == mod_brush ) { m_headnode = SV_HullForEntity( pTriggerEntity ); } m_origin = pServerTrigger->GetAbsOrigin(); m_angles = pServerTrigger->GetAbsAngles(); } }
/* <83e97> ../engine/r_studio.c:1015 */ hull_t *SV_HullForStudioModel(const edict_t *pEdict, const vec_t *mins, const vec_t *maxs, vec_t *offset, int *pNumHulls) { qboolean useComplexHull = FALSE; vec3_t size; float factor = 0.5; int bSkipShield = 0; size[0] = maxs[0] - mins[0]; size[1] = maxs[1] - mins[1]; size[2] = maxs[2] - mins[2]; if (VectorCompare(vec3_origin, size)) { if (!(gGlobalVariables.trace_flags & FTRACE_SIMPLEBOX)) { useComplexHull = TRUE; if (pEdict->v.flags & FL_CLIENT) { if (sv_clienttrace.value == 0.0) { useComplexHull = FALSE; } else { size[2] = 1.0f; size[1] = 1.0f; size[0] = 1.0f; factor = sv_clienttrace.value * 0.5f; } } } } if (pEdict->v.gamestate == 1 && (g_bIsTerrorStrike == 1 || g_bIsCStrike == 1 || g_bIsCZero == 1)) bSkipShield = 1; if ((g_psv.models[pEdict->v.modelindex]->flags & FL_ONGROUND) || useComplexHull == TRUE) { VectorScale(size, factor, size); offset[0] = 0; offset[1] = 0; offset[2] = 0; if (pEdict->v.flags & FL_CLIENT) { pstudiohdr = (studiohdr_t *)Mod_Extradata(g_psv.models[pEdict->v.modelindex]); mstudioseqdesc_t* pseqdesc = (mstudioseqdesc_t *)((char*)pstudiohdr + pstudiohdr->seqindex); pseqdesc += pEdict->v.sequence; vec3_t angles; angles[0] = pEdict->v.angles[0]; angles[1] = pEdict->v.angles[1]; angles[2] = pEdict->v.angles[2]; int iBlend; R_StudioPlayerBlend(pseqdesc, &iBlend, angles); unsigned char blending = (unsigned char)iBlend; unsigned char controller[4] = { 0x7F, 0x7F, 0x7F, 0x7F }; return R_StudioHull( g_psv.models[pEdict->v.modelindex], pEdict->v.frame, pEdict->v.sequence, angles, pEdict->v.origin, size, controller, &blending, pNumHulls, pEdict, bSkipShield); } else { return R_StudioHull( g_psv.models[pEdict->v.modelindex], pEdict->v.frame, pEdict->v.sequence, pEdict->v.angles, pEdict->v.origin, size, pEdict->v.controller, pEdict->v.blending, pNumHulls, pEdict, bSkipShield); } } else { *pNumHulls = 1; return SV_HullForEntity((edict_t *)pEdict, mins, maxs, offset); } }
/* DESCRIPTION: SV_ClipMoveToEntity/SV_SingleClipMoveToEntity // LOCATION: world.c // PATH: Mostly in this file. // // SV_ClipMoveToEntity is a proxy (and only access point) for the next one. // // The function seems to be related to collision detection. */ void SV_SingleClipMoveToEntity(edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t * Outgoing_Trace) { vec3_t var_c; vec3_t var_18; vec3_t var_24; hull_t * var_28; // int var_2c; int var_30; int var_34; int var_38; vec3_t forward; vec3_t right; vec3_t up; vec3_t var_68; int var_6c; trace_t var_a4; vec3_t var_bc; vec3_t var_c8; vec3_t var_d4; Q_memset(Outgoing_Trace, 0, sizeof(trace_t)); Outgoing_Trace->fraction = 1.0; Outgoing_Trace->allsolid = 1; Outgoing_Trace->endpos[0] = end[0]; Outgoing_Trace->endpos[1] = end[1]; Outgoing_Trace->endpos[2] = end[2]; if(global_sv.models[ent->v.modelindex]->modeltype == 3) { //taken: 1616, -528, 127.97 endpos var_28 = SV_HullForStudioModel(ent, mins, maxs, var_c, &var_30); } else { var_28 = SV_HullForEntity(ent, mins, maxs, var_c); var_30 = 1; //if model? } VectorSubtract(start, var_c, var_18); VectorSubtract(end, var_c, var_24); if((ent->v.solid != SOLID_BSP) || (ent->v.angles[0] == 0 && ent->v.angles[1] == 0 && ent->v.angles[2] == 0)) { //taken var_38 = 0; //rotated prob } else { var_38 = 1; } if(var_38) { //This is another function in QW. AngleVectors(ent->v.angles, forward, right, up); //v.angles is def +58. VectorCopy(var_18, var_68); var_18[0] = DotProduct(var_68, forward); var_18[1] = -DotProduct(var_68, right); var_18[2] = DotProduct(var_68, up); VectorCopy(var_24, var_68); var_24[0] = DotProduct(var_68, forward); var_24[1] = -DotProduct(var_68, right); var_24[2] = DotProduct(var_68, up); } //Curiously enough, I'm taking linear algebra right now. I hate it. //= 20 if(var_30 == 1) { SV_RecursiveHullCheck(var_28, var_28->firstclipnode, 0, 1.0, var_18, var_24, Outgoing_Trace); } else { for(var_6c = 0, var_34 = 0; var_34 < var_30; var_34++) { Q_memset(&var_a4, 0, sizeof(trace_t)); var_a4.fraction = 1.0; var_a4.allsolid = 1; VectorCopy(end, var_a4.endpos); SV_RecursiveHullCheck(&(var_28[var_34]), var_28[var_34].firstclipnode, 0, 1.0, var_18, var_24, &var_a4); if(var_34 != 0 && var_a4.startsolid == 0 && var_a4.allsolid == 0 && var_a4.fraction > Outgoing_Trace->fraction) { continue; } if(Outgoing_Trace->startsolid == 0) { Q_memcpy(Outgoing_Trace, &var_a4, sizeof(trace_t)); } else { Q_memcpy(Outgoing_Trace, &var_a4, sizeof(trace_t)); //Probably could be a bit more efficient here. Outgoing_Trace->startsolid = 1; } var_6c = var_34; } Outgoing_Trace->hitgroup = SV_HitgroupForStudioHull(var_6c); } if(Outgoing_Trace->fraction != 1.0) { if(var_38 != 0) { AngleVectorsTranspose(ent->v.angles, var_68, var_bc, var_c8); VectorCopy(Outgoing_Trace->plane.normal, var_d4); Outgoing_Trace->plane.normal[0] = DotProduct(var_d4, var_68); Outgoing_Trace->plane.normal[1] = -DotProduct(var_d4, var_bc); Outgoing_Trace->plane.normal[2] = DotProduct(var_d4, var_c8); } //Scaling, clearly. Outgoing_Trace->endpos[0] = start[0] + (Outgoing_Trace->fraction * (end[0] - start[0])); Outgoing_Trace->endpos[1] = start[1] + (Outgoing_Trace->fraction * (end[1] - start[1])); Outgoing_Trace->endpos[2] = start[2] + (Outgoing_Trace->fraction * (end[2] - start[2])); } if(Outgoing_Trace->fraction < 1.0 || Outgoing_Trace->startsolid != 0) { Outgoing_Trace->pHit = ent; } }