Ru/UTIL TraceLine

Трассировка - это процесс построения линии от точки A в точку B и определения первого объекта, с которым она пересекается (TraceLine). Наиболее частой областью применения трассировки являются хитскан-оружия (). Хитскан-оружие использует трассировку для определения точки попадания и объекта, который был поражен.
(Пример использования для оружия)
Линия начинается от дула оружия (точка А) и заканчивается в произвольной точке, находящейся на расстоянии не менее 8000 единиц от нее. Если она попадает в какой-либо объект (например, стену, ящик, твердое тело), код сообщает игре, чтобы она отображала визуальный эффект (например, клуб дыма, выходивший из стены, или искры из металла). Если она попадает в игрока, он получает урон.
== TraceLines ==
Создаём простую трассировку, вызвав UTIL_TraceLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, const IHandleEntity *ignore, int collisionGroup, trace_t *ptr ).
Где:
:*&vecAbsStart взят Вектор например из GetAbsOrigin(); Часть "const" функции говорит вам, что функция не будет изменять переменную.
:*&vecAbsEnd взят Вектор например из GetAbsOrigin() + (vecForward * 192); Отслеживание 192 единицы перед GetAbsOrigin().
:*mask это маска допустимых типов MASK_ для попадания. См.: . Поскольку это битовая маска, вы можете использовать несколько типов, и, следовательно, MASK_VISIBLE | MASK_SHOT будет считаться допустимой маской.
:**ignore является IHandleEntity или указателем на CBaseEntity. Обычно используется "this" для того, чтобы TraceLine не попал в объект, из которого вы выполняете трассировку.
:*collisionGroup является типом COLLISION_, которому принадлежит TraceLine. См.: . Некоторые типы COLLISION_ не будут «сталкиваться» друг с другом. Используйте COLLISION_GROUP_NONE, чтобы ваш TraceLine ударял все.
:**tr является классом trace_t. Результаты UTIL_TraceLine записываются в него.
== Общие методы vecAbsStart и vecAbsEnd ==
vecAbsStart
:*GetAbsOrigin(): Это возвращает вектор положения объекта в координатах мира. Для игроков это их ноги, а для большинства объектов это либо центр, либо нижняя часть модели.
:*Weapon_ShootPosition(): Точка в Мире от куда происходит выстрел из оружия игрока.
:*GetAttachment( int attachment, Vector &origin, QAngle &angles );: Получение положения точки крепления. Используется в сочетании с...
:*LookupAttachment( char *pAttachmentName ): Имя точки крепления, которую вы хотите использовать (в виде char* ).
vecAbsEnd
:*EyeAngles(): Возвращает QAngle угла, на который в данный момент смотрит игрок.
:*GetAbsAngles(): Возвращает QAngle угла, под которым смотрит игрок. Часто не соответствует вращению по оси EyeAngles, поскольку игрок поворачивается только с шагом 15–30 градусов, чтобы избежать дрожания и повысить реалистичность.
QAngles
QAngles - это вектор углов, что означает, что он хранит вращение по осям X, Y и Z.
Часто бывает необходимо преобразовать QAngle в вектор. Для этого можно использовать функцию AngleVectors(), которая принимает QAngle и может возвращать 1 или 3 указателя на Vectors. Например, следующий код преобразует QAngle поворота игрока в вектор направления взгляда:
Vector vecForward, vecRight, vecUp;
AngleVectors( EyeAngles(), &vecForward, &vecRight, &vecUp); 
Эта функция преобразует QAngle в набор векторов, представляющих направления "вперед", "вправо" и "вверх". Затем вы можете использовать vecForwards, чтобы узнать, куда смотрит EyeAngles().
Чтобы получить точку перед вашей конечной позицией, вы можете сделать следующее:
Vector vecForward;
AngleVectors( pPlayer->EyeAngles(), &vecForward ) //Назначьте vecForward вектор, обращенный к EyeAngles.
UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + ( vecForward * MAX_TRACE_LENGTH, ...)
MAX_TRACE_LENGTH — это самая длинная трасса, которую вы можете иметь, или ~ 56 754 единицы.
== trace_t &tr ==
trace_t Это специальный класс, который хранит результаты нашего TraceLine. У него есть следующие значения:
:*startpos: Вектор начальной точки трассировки.
:*endpos: Вектор конечной точки трассировки.
:*plane: Структура. Содержит информацию о плоскости, с которой вы столкнулись.
:*fraction: Дистанция до столкновения. 0-1, 1.0 обозначают, что не куда не попало.
:*allsolid: Boolean. Если true, то плоскость недействительна. (Вы никогда не покидали место, с которого начали).
:*startsolid: Boolean. Если true, то исходная точка находилась в твердой области.
:*hitbox: Возвращает целое число попаданий в хитбокс.
:*m_pEnt: Сущность, которую ударили. Может быть недействительным.
:*DidHit(): Boolean. Возвращает true, если произошло столкновение.
:*IsPlayer(): Boolean. Возвращает true, если попало в игрока.
:*IsNPC(): Boolean. Возвращает true, если попало в NPC.
:*GetClassname(): Возвращает имя класса энтити, в которое попало.
:*GetTeamNumber(): Возвращает ID команды, в которой находится объект. Возвращает UNASSIGNED для объектов, не входящих в команду.
:*contents: Содержимое по ту сторону поверхности, в которую оно ударилось.
:*surface: Возвращает поверхность, с которой столкнулась трассировка.
::*name: Возвращает название поверхности. 
::*flags: Возвращает битовое поле, обычно используемое для предотвращения попадания трассировки в нежелательные типы поверхностей (например, «if (tr.surface.flags & SURF_SKY)»)
::*surfaceProps: Возвращает целое число типа 'short', используемое для поиска материала поверхности, с которой столкнулась трассировка.
:
== Примеры ==
Трассировка от глаз игрока до максимального расстояния трассировки.
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
if ( !pPlayer )
 return; //Всегда проверять указатель
// Создать вектор для направления
Vector vecDir;
// Возьмите углы глаз игрока и поверните их в нужном направлении.
AngleVectors( pPlayer->EyeAngles(), &vecDir );
// Получить начало и конец
Vector vecAbsStart = pPlayer->EyePosition();
Vector vecAbsEnd = vecAbsStart + (vecDir * MAX_TRACE_LENGTH);
trace_t tr; // Создайте наш класс trace_t, чтобы сохранить конечный результат.
// Выполнить трассировку и записать результаты в наш класс trace_t, tr.
UTIL_TraceLine( vecAbsStart, vecAbsEnd, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr );
// Манипуляция с конечными результатами.
if ( tr.m_pEnt )
{
 if ( tr.m_pEnt->IsNPC() )
 {
 Msg("Трасировка попала в NPC!\n");
 }
 if ( tr.m_pEnt->IsPlayer() )
 {
 Msg("Трасировка попала в игрока!\n");
 }
}