UTIL TraceLine
Tracing is the process of going from a point A towards another point B, and finding out the first thing that we "hit" on our way from A to B (TraceLine). The most common example for the use of TraceLines would be hitscan weapons. Hitscan weapons use TraceLines to determine where they hit (and if they hit someone).
The line starts from the barrel (Point A) and ends at an arbitrary spot 8000 or more units in front of it. If it hits the world (a wall, a box, something solid) the code tells it to display an effect (for example, a smoke puff coming from the wall, or sparks from metal...). If it hits a player, it'll do damage.
TraceLines
To create a simple trace, call UTIL_TraceLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, const IHandleEntity *ignore, int collisionGroup, trace_t *ptr ). Where:
- &vecAbsStart is a Vector such as GetAbsOrigin(); The "const" part of the function tells you that the function will not modify the variable.
- &vecAbsEnd is a Vector such as GetAbsOrigin() + (vecForward * 192); Tracing 192 units in front of the Absolute Origin of the caller.
- mask is a bitmask of valid MASK_ types to hit. See: MASK_Types. Since it is a bitmask, you can use multiple types and as such MASK_VISIBLE | MASK_SHOT will count as an acceptable mask.
- *ignore is a IHandleEntity, or a pointer to a CBaseEntity. It is common to use "this" as to keep the TraceLine from hitting the object you're tracing from.
- collisionGroup is a COLLISION_ type that the TraceLine is. See: COLLISION_Types. Certain COLLISION_ types will not 'collide' with each other. Use COLLISION_GROUP_NONE to have your TraceLine hit everything.
- *tr is a trace_t class. The results of the UTIL_TraceLine are written to this.
Common vecAbsStart and vecAbsEnd Methods
vecAbsStart
- GetAbsOrigin(): This returns a Vector of the entity's Origin in World Space coordinates. For Player's this is their feet, and for most entities :*it is either the center or bottom of the model.
- Weapon_ShootPosition(): Point in World Space where the player's weapon's shot originates.
- GetAttachment( int attachment, Vector &origin, QAngle &angles );: Returns the position of an attachment point. Used in conjunction with...
- LookupAttachment( char *pAttachmentName ): The name (as a char*) of the attachment point you wish to use.
vecAbsEnd
- EyeAngles(): Returns a QAngle of the angle the player is currently looking at.
- GetAbsAngles(): Returns a QAngle of the angle the player is facing at. Often does not match the z rotation of EyeAngles, as the player only turns in 15-30 degree increments to avoid jitter and increase realism.
QAngles
QAngles is a Vector of Angles -- That is to say it stores rotation in X, Y and Z. Often, we will want to turn a QAngle into a vector. To do this, we can use AngleVectors(), which takes a QAngle and can return 1 or 3 pointers to Vectors. For example:
Vector vecForward, vecRight, vecUp;
AngleVectors( EyeAngles(), &vecForward, &vecRight, &vecUp);
Will return a vector facing to the "front", a vector to the "right", and a vector to the "up" of your QAngle. You can then use vecForwards to get where EyeAngles() is looking at.
To get a point infront of your 'end' position, you can do:
Vector vecForward;
AngleVectors( pPlayer->EyeAngles(), &vecForward ) //Assign vecForward a vector facing the EyeAngles
UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + ( vecForward * MAX_TRACE_LENGTH, ...)
MAX_TRACE_LENGTH is the longest trace you can have, or ~56,754 units.
trace_t &tr
trace_t is a special class that stores the results of our TraceLine. It has the following values.
- startpos: The start of the TraceLine as a Vector.
- endpos: The end of the TraceLine as a Vector.
- plane: Struct. Contains the information about the plane you hit.
- fraction: How far the trace went before hitting something. 0-1, 1.0 means it didn't hit anything.
- allsolid: Boolean. If true, the plane is not valid. (You never left the solid you started in)
- startsolid: Boolean. If true, the initial point was in a solid area.
- hitbox: Returns the int of the hitbox hit.
- m_pEnt: The entity hit. Can be invalid.
- DidHit(): Boolean. Returns true if it hit something.
- IsPlayer(): Boolean. Returns true if the entity hit was a player.
- IsNPC(): Boolean. Returns true if the entity hit was an NPC.
- GetClassname(): Returns the name of the entity hit.
- GetTeamNumber(): Returns the team number that the entity is on. Returns UNASSIGNED for entities not on a team.
- contents: Contents on the other side of the surface it hit
- surface: Returns the surface hit by the TraceLine.
- name: Returns the name of the surface. Todo: What is normally returned (i.e. "rock" etc.)
- flags: Returns a bitflag normally used to avoid the TraceLine hitting unwanted surfacetypes (i.e. "if( tr.surface.flags & SURF_SKY )")
- surfaceProps: Returns a short integer used in finding the material of the surface hit:
- name: Returns the name of the surface.
- Tip: Use physprops->GetSurfaceData(tr.surface.surfaceProps) to return a surfacedata_t which can be used to determine the material of the surface you hit.
Examples
Trace from the player's eyes to the max trace distance.
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
if ( !pPlayer )
return; //Always validate a pointer
// Create Vector for direction
Vector vecDir;
// Take the Player's EyeAngles and turn it into a direction
AngleVectors( pPlayer->EyeAngles(), &vecDir );
// Get the Start/End
Vector vecAbsStart = pPlayer->EyePosition();
Vector vecAbsEnd = vecAbsStart + (vecDir * MAX_TRACE_LENGTH);
trace_t tr; // Create our trace_t class to hold the end result
// Do the TraceLine, and write our results to our trace_t class, tr.
UTIL_TraceLine( vecAbsStart, vecAbsEnd, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr );
// Do something with the end results
if ( tr.m_pEnt )
{
if ( tr.m_pEnt->IsNPC() )
{
Msg("TraceLine hit an NPC!\n");
}
if ( tr.m_pEnt->IsPlayer() )
{
Msg("TraceLine hit a Player!\n");
}
}