CS2 Lua API

trace

Модуль trace пускает трассы движка — лучи, сферы, капсулы, коробки — и трассу пули с пробитием. Результат показывает, во что попала трасса.

Общие правила#

  • Векторные аргументы — vector.
  • Если трасса ни во что не попала, это не ошибка: fraction = 1.
  • Трассы запрещены внутри события mouse_input и внутри колбэка should_hit_entity фильтра.

trace.ray(from: vector, to: vector, filter: trace_filter)#

Линейная трасса (луч).

Параметр Тип Описание
from vector начало
to vector конец
filter trace_filter фильтр из trace.filter (обязателен)

Возвращает: trace_result.

-- Видит ли локальный игрок врага (луч от глаз до глаз)
local function is_visible(me, enemy)
    local r = trace.ray(me:eye_position(), enemy:eye_position(), trace.filter(me, __mask.shot))
    return r.fraction == 1 or r.enthit == enemy
end

events.pre_render:set(function()
    local me = entity.local_pawn()
    if not me or not me:is_alive() then return end
    for _, enemy in ipairs(entity.pawns(true)) do
        if is_visible(me, enemy) then
            -- враг на виду
        end
    end
end)

trace.sphere(from: vector, to: vector, radius: number, filter: trace_filter)#

Трасса сферой. При radius <= 0 — обычный луч.

Параметр Тип Описание
from vector начало
to vector конец
radius number радиус сферы
filter trace_filter фильтр

Возвращает: trace_result.

local me = entity.local_pawn()
if me then
    local eye = me:eye_position()
    local r = trace.sphere(eye, eye + me:eye_angles():forward() * 500, 4, trace.filter(me))
    print("Сфера прошла ", math.floor(r.fraction * 100), "%")
end

trace.capsule(from: vector, to: vector, center0: vector, center1: vector, radius: number, filter: trace_filter)#

Трасса капсулой.

Параметр Тип Описание
from vector начало
to vector конец
center0 vector центр первой полусферы капсулы
center1 vector центр второй полусферы
radius number радиус капсулы
filter trace_filter фильтр

Возвращает: trace_result.

local me = entity.local_pawn()
if me then
    local o = me:origin()
    local r = trace.capsule(o, o + vector(0, 0, -64), vector(0, 0, 0), vector(0, 0, 8), 2, trace.filter(me))
    print("Пол под ногами на расстоянии ", r.fraction * 64)
end

trace.aabb(from: vector, to: vector, mins: vector, maxs: vector, filter: trace_filter)#

Трасса коробкой (hull). Если mins == maxs, это луч, смещённый на mins.

Параметр Тип Описание
from vector начало
to vector конец
mins vector нижний угол коробки
maxs vector верхний угол коробки
filter trace_filter фильтр

Возвращает: trace_result.

-- Поместится ли игрок, если присесть на 64 юнита вперёд
local me = entity.local_pawn()
if me then
    local o = me:origin()
    local fwd = me:eye_angles():forward()
    local to = o + vector(fwd.x, fwd.y, 0) * 64
    local r = trace.aabb(o, to, vector(-16, -16, 0), vector(16, 16, 54), trace.filter(me))
    print(r.fraction == 1 and "проход свободен" or "впереди препятствие")
end

trace.convex_hull(from: vector, to: vector, points: table, filter: trace_filter)#

Трасса выпуклой фигурой из точек.

Параметр Тип Описание
from vector начало
to vector конец
points table вершины фигуры {vector, ...} относительно позиции
filter trace_filter фильтр

Возвращает: trace_result.

local me = entity.local_pawn()
if me then
    local eye = me:eye_position()
    local pts = { vector(-2, -2, 0), vector(2, -2, 0), vector(0, 2, 0), vector(0, 0, 4) }
    local r = trace.convex_hull(eye, eye + vector(0, 0, -100), pts, trace.filter(me))
    print(r.hitpos)
end

trace.filter(arg?: entity|table, mask?: number, group?: number, set_mask?: number)#

Создаёт фильтр трассы.

Параметр Тип Описание
arg entity или table сущность — игнорировать её; массив сущностей — игнорировать их; таблица-словарь — задать поля фильтра (см. ниже)
mask number или 64-битное целое с чем сталкиваться, биты __contents; по умолчанию 0x1C300B
group number группа столкновений, по умолчанию 3
set_mask number маска наборов объектов, по умолчанию 0x0F

Если arg — таблица-словарь ({interacts_with = ...}), её поля записываются в фильтр, и функция сразу возвращает его: аргументы 2–4 и умолчания не применяются. Неизвестный ключ — ошибка field not found.

Возвращает: trace_filter.

local me = entity.local_pawn()
if me then
    local f1 = trace.filter(me)                               -- игнорировать себя
    local f2 = trace.filter(me, __mask.shot)                  -- маска выстрела
    local f3 = trace.filter({ interacts_with = __mask.shot_hull }) -- только заданное поле
end

Поля trace_filter#

Поле Чтение Запись
interacts_with 64-битное целое число или 64-битное целое — с чем сталкиваться
interacts_exclude 64-битное целое что исключить
interacts_as 64-битное целое как сама трасса выглядит для объектов
collision_group number группа столкновений
object_set_mask number маска наборов объектов
ignore_entities ошибка field is write-only массив сущностей; заменяет список игнора целиком
should_hit_entity ошибка field is write-only функция fn(ent) -> boolean; не функция — снять

should_hit_entity вызывается для каждой задетой сущности, кроме игнорируемых. true — задевать; любой другой результат или ошибка внутри — не задевать.

-- Трасса, которая проходит сквозь союзников
local me = entity.local_pawn()
if me then
    local f = trace.filter(me, __mask.shot)
    f.should_hit_entity = function(ent)
        return ent:is_enemy()
    end
    local eye = me:eye_position()
    local r = trace.ray(eye, eye + me:eye_angles():forward() * 8192, f)
    print(r.enthit)
end

Поля trace_result#

Объект результата только для чтения.

Поле Тип Описание
fraction number доля пройденного пути (1 — ни во что не попала)
startpos vector начало
endpos vector конец
hitpos vector точка попадания
normal vector нормаль поверхности попадания
offset number расстояние плоскости попадания
contents 64-битное целое содержимое поверхности, биты __contents
startsolid boolean трасса началась внутри твёрдого
type number форма трассы: 0 — луч, 1 — сфера, 2 — коробка, 3 — капсула, 4 — выпуклая фигура
triangle number номер треугольника поверхности
damage number у trace.bullet — оставшийся урон; у обычных трасс −1
damage_unscaled number урон без учёта хитгруппы; у обычных трасс −1
transform CTransform преобразование задетого тела
surface declared_class или nil свойства поверхности
hitbox declared_class или nil задетый хитбокс
body lightuserdata или nil физическое тело
shape lightuserdata или nil физическая форма
enthit entity или nil задетая сущность
local me = entity.local_pawn()
if me then
    local eye = me:eye_position()
    local r = trace.ray(eye, eye + me:eye_angles():forward() * 8192, trace.filter(me))
    if bit.band(r.contents, __contents.window) ~= 0 then
        print("Смотрим на стекло")
    end
end

trace.bullet(from: vector, to: vector, pawn: entity, vdata?: declared_class, filter?: trace_filter)#

Трасса пули с пробитием (до 4 слоёв), как при выстреле.

Параметр Тип Описание
from vector точка выстрела
to vector задаёт только направление; длина равна дальности оружия
pawn entity стрелок (C_CSPlayerPawn)
vdata declared_class данные оружия; по умолчанию — активное оружие стрелка
filter trace_filter фильтр; по умолчанию trace.filter(pawn)
  • Возвращает по результату на каждое место контакта, по порядку от первого. Если контактов нет или у стрелка нет оружия — ничего не возвращает.
  • damage каждого результата — урон, оставшийся после контакта. Если контакт — игрок, урон учитывает хитгруппу.

Возвращает: trace_result, ... — несколько значений.

-- Сколько урона пройдёт сквозь стену туда, куда смотрим
local me = entity.local_pawn()
if me and me:weapon() then
    local eye = me:eye_position()
    local hits = { trace.bullet(eye, eye + me:eye_angles():forward(), me) }
    for i, r in ipairs(hits) do
        print(i, ": ", r.enthit, " урон ", math.floor(r.damage))
    end
end

Константы __contents и __mask#

Глобальные таблицы битов для масок трасс. Значения — 64-битные целые; объединяйте через bit.bor.

__contents: empty, solid, hitbox, trigger, sky, player_clip, npc_clip, block_los, ladder, pickup, block_sound, window, grate, world_geometry, touch_triggers, player, debris, physics_prop, nav_local_ignore, postprocessing_volume, carried_object, pushaway, server_entity_on_client, carried_weapon, static_level, team1, grenadeclip, moveable, monster, chicken, thrown_grenade, dropped_hostage.

__mask: all, shot, shot_brushonly, shot_hull, defaultplayersolid, npcsolid, water, opaque_and_npcs, blocklos, blocklos_and_npcs, visible, visible_and_npcs, solid_brushonly, defaultplayersolid_brushonly, npcsolid_brushonly, npcworldstatic, npcworldstatic_fluid, playersolid_brushonly, floortrace.

local me = entity.local_pawn()
if me then
    -- стрельба, но без стёкол
    local mask = bit.band(__mask.shot, bit.bnot(__contents.window))
    local f = trace.filter(me, mask)
    print(f.interacts_with)
end