UTIL TraceLine
Трассировка - это процесс построения линии от точки A в точку B и определения первого объекта, с которым она пересекается (TraceLine). Наиболее частой областью применения трассировки являются хитскан-оружия (hitscan ). Хитскан-оружие использует трассировку для определения точки попадания и объекта, который был поражен.
(Пример использования для оружия) Линия начинается от дула оружия (точка А) и заканчивается в произвольной точке, находящейся на расстоянии не менее 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 . Поскольку это битовая маска, вы можете использовать несколько типов, и, следовательно, MASK_VISIBLE | MASK_SHOT будет считаться допустимой маской.
- *ignore является IHandleEntity или указателем на CBaseEntity. Обычно используется "this" для того, чтобы TraceLine не попал в объект, из которого вы выполняете трассировку.
- collisionGroup является типом COLLISION_, которому принадлежит TraceLine. См.: COLLISION_Types . Некоторые типы 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: Возвращает название поверхности. Нужно сделать: Что обычно возвращается (т.е. "rock" и т.д.)
- flags: Возвращает битовое поле, обычно используемое для предотвращения попадания трассировки в нежелательные типы поверхностей (например, «if (tr.surface.flags & SURF_SKY)»)
- surfaceProps: Возвращает целое число типа 'short', используемое для поиска материала поверхности, с которой столкнулась трассировка.
- name: Возвращает название поверхности.
- Совет: 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");
}
}