UTIL TraceLine

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

Трассировка - это процесс построения линии от точки A в точку B и определения первого объекта, с которым она пересекается (TraceLine). Наиболее частой областью применения трассировки являются хитскан-оружия (hitscan(en)). Хитскан-оружие использует трассировку для определения точки попадания и объекта, который был поражен.

(Пример использования для оружия) Линия начинается от дула оружия (точка А) и заканчивается в произвольной точке, находящейся на расстоянии не менее 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_Types(en). Поскольку это битовая маска, вы можете использовать несколько типов, и, следовательно, MASK_VISIBLE | MASK_SHOT будет считаться допустимой маской.
  • *ignore является IHandleEntity или указателем на CBaseEntity. Обычно используется "this" для того, чтобы TraceLine не попал в объект, из которого вы выполняете трассировку.
  • collisionGroup является типом COLLISION_, которому принадлежит TraceLine. См.: COLLISION_Types(en). Некоторые типы COLLISION_ не будут «сталкиваться» друг с другом. Используйте COLLISION_GROUP_NONE, чтобы ваш TraceLine ударял все.
  • *tr является классом trace_t. Результаты UTIL_TraceLine записываются в него.

Общие методы vecAbsStart и vecAbsEnd

vecAbsStart

  • GetAbsOrigin(): Это возвращает вектор положения объекта в координатах мира. Для игроков это их ноги, а для большинства объектов это либо центр, либо нижняя часть модели.
Note.pngПримечание:Это видно в HLMV(en) на вкладке Bones, если установить флажок Highlight Bone для первой кости.
Нужно сделать: Это точно?
  • Weapon_ShootPosition(): Точка в Мире от куда происходит выстрел из оружия игрока.
Note.pngПримечание:Доступно только в классе Player.
  • GetAttachment( int attachment, Vector &origin, QAngle &angles );: Получение положения точки крепления. Используется в сочетании с...
  • LookupAttachment( char *pAttachmentName ): Имя точки крепления, которую вы хотите использовать (в виде char* ).


vecAbsEnd

  • EyeAngles(): Возвращает QAngle угла, на который в данный момент смотрит игрок.
Note.pngПримечание:Доступно только в классе Player.
  • 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 единицы.

Note.pngПримечание:Это примерно от одного угла мира до другого, если бы мир был кубом.

trace_t &tr

trace_t Это специальный класс, который хранит результаты нашего TraceLine. У него есть следующие значения:

  • startpos: Вектор начальной точки трассировки.
  • endpos: Вектор конечной точки трассировки.
  • plane: Структура. Содержит информацию о плоскости, с которой вы столкнулись.
Warning.pngПредупреждение:Плоскость может быть недействительной! Если трассировка не попадает в твердое тело.
  • fraction: Дистанция до столкновения. 0-1, 1.0 обозначают, что не куда не попало.
  • allsolid: Boolean. Если true, то плоскость недействительна. (Вы никогда не покидали место, с которого начали).
  • startsolid: Boolean. Если true, то исходная точка находилась в твердой области.
  • hitbox: Возвращает целое число попаданий в хитбокс.
  • m_pEnt: Сущность, которую ударили. Может быть недействительным.
Tip.pngСовет: Используйте "if ( tr.m_pEnt )" для его проверки!
  • DidHit(): Boolean. Возвращает true, если произошло столкновение.
  • IsPlayer(): Boolean. Возвращает true, если попало в игрока.
  • IsNPC(): Boolean. Возвращает true, если попало в NPC.
  • GetClassname(): Возвращает имя класса энтити, в которое попало.
Note.pngПримечание:Возвращает странные результаты на клиенте, если сущность не прогнозируемая.
  • GetTeamNumber(): Возвращает ID команды, в которой находится объект. Возвращает UNASSIGNED для объектов, не входящих в команду.
  • contents: Содержимое по ту сторону поверхности, в которую оно ударилось.
  • surface: Возвращает поверхность, с которой столкнулась трассировка.
  • name: Возвращает название поверхности.
    Нужно сделать:  Что обычно возвращается (т.е. "rock" и т.д.)
  • flags: Возвращает битовое поле, обычно используемое для предотвращения попадания трассировки в нежелательные типы поверхностей (например, «if (tr.surface.flags & SURF_SKY)»)
  • surfaceProps: Возвращает целое число типа 'short', используемое для поиска материала поверхности, с которой столкнулась трассировка.
Tip.pngСовет: Use physprops->GetSurfaceData(tr.surface.surfaceProps) to return a surfacedata_t which can be used to determine the material of the surface you hit.

Примеры

Трассировка от глаз игрока до максимального расстояния трассировки.

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");
    }
}
Нужно сделать: Больше примеров!