UTIL TraceLine

From Valve Developer Community
Jump to navigation Jump to search
English (en)Русский (ru)Translate (Translate)

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.
Note.pngNote:This is visible in HLMV under the Bones tab, by checking Highlight Bone of the first bone.
Todo: Is this accurate?
  • Weapon_ShootPosition(): Point in World Space where the player's weapon's shot originates.
Note.pngNote:Only available in the Player class
  • 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.
Note.pngNote:Only avaible in the Player class
  • 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.

Note.pngNote:This is a trace from one corner to the opposite corner of the world, assuming a cubic world.

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.
Warning.pngWarning:plane can be invalid! If the trace never leaves a solid, there will be no valid plane.
  • 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.
Tip.pngTip: Use "if ( tr.m_pEnt )" to validate it!
  • 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.
Note.pngNote:Returns strange results on the client if the entity is not predicted.
  • 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:
Tip.pngTip: 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");
    }
}
Todo: More Examples!