Skip to content

Traces

Questions about lines through the world: what is the first thing between two points, is the way clear, where is the floor below a point. A trace meets the map, its parts, solid models and shapes, and with bodies the players and NPCs too.

In a client script, aimed() gives the player or NPC under the crosshair, as the player’s game draws it.

On a client aimed() → Player?

Gives the player or NPC under the crosshair as the player's game draws this frame, or nil for none.

It looks along the line from the eye through the middle of the screen, against the map and the bodies drawn. Models, parts and shapes are never aimed at. A render that reads it draws again as it changes. The server checks again anything that matters, as a player’s game may lie.

Returns
Player?
mount(function()
local aimed_at = aimed()
if not aimed_at then
return nil
end
return Box { aimed_at.name or "", style = { position = "absolute", top = 560, left = 0, right = 0, textAlign = "center" } }
end)
On the server trace(from, to, { mask?, bodies?, ignore? }?) → Hit?

Gives the first thing on the line from one point to another, or nil if the line is clear.

It meets the map and its parts, solid models and shapes where they stand at the call’s tick, and with bodies the players and NPCs too. What it gives is a table: position and normal, vectors; player, the player or NPC hit; entity, the part, model or shape hit; ladder, whether the surface is a ladder’s; and mantle, whether it may be climbed over, false for a body. A line starting inside a body meets it where it starts, so put whoever traces in ignore. A body is met by its capsule, not by its limbs as a shot is.

Traces run only in handlers, timers and ticks, 1024 a call at most, is_trace_clear and ground among them.

NameTypeWhat it is
fromvectorNeeded.
tovectorNeeded.
optionstable?A table of the options below. It, and each option, may be left out.
maskMask?What of the map and its obstacles it meets; anything solid without. A table of the options below it.
mask.playersbooleandefault falseWhat stops players.
mask.npcsbooleandefault falseWhat stops NPCs.
mask.shotsbooleandefault falseWhat stops bullets: { shots = true } meets what a shot does.
mask.projectilesbooleandefault falseWhat stops thrown grenades and rockets.
bodiesbooleandefault falseMeets the players alive and the NPCs too, where they stood at the start of the call.
ignore({Player | number})?Players and NPCs whose bodies it passes through, 1088 at most.
Returns
Hit?
Fails
  • a value of the wrong type
  • an option it does not have
local eye = p.position + vector.create(0, 1.6, 0)
local hit = trace(eye, eye + angles.forward(p) * 100, { bodies = true, ignore = { p } })
if hit and hit.player then
say(`{p.name} looks at {hit.player.name}`)
end

To fire a bullet of your own, stopped by what stops shots

Section titled “To fire a bullet of your own, stopped by what stops shots”
local from = p.position + vector.create(0, 1.6, 0)
local hit = trace(from, from + angles.forward(p) * 50, { mask = { shots = true }, bodies = true, ignore = { p } })
if hit and hit.player then
hit.player:hurt(30, p, "laser", { kind = "bullet" })
end
On the server is_trace_clear(a, b, { mask? }?) → boolean

Whether the line between two points is clear: true if trace would meet nothing on it, the bodies aside.

NameTypeWhat it is
avectorNeeded.
bvectorNeeded.
optionstable?A table of the options below. It, and each option, may be left out.
maskMask?What of the map and its obstacles it meets; anything solid without. A table of the options below it.
mask.playersbooleandefault falseWhat stops players.
mask.npcsbooleandefault falseWhat stops NPCs.
mask.shotsbooleandefault falseWhat stops bullets: { shots = true } meets what a shot does.
mask.projectilesbooleandefault falseWhat stops thrown grenades and rockets.
Returns
boolean
Fails
  • a value of the wrong type
  • an option it does not have

To send each zombie that can see a player after them

Section titled “To send each zombie that can see a player after them”
local eyes = vector.create(0, 1.6, 0)
for _, zombie in players do
if zombie.npc and is_trace_clear(zombie.position + eyes, p.position + eyes) then
zombie:chase(p)
end
end
On the server ground(point) → vector?

Gives the floor below a point, the map's or a part's, a model's or a shape's, as a vector; nil if there is none.

A point resting on a floor, or a hair below it, finds that floor.

NameTypeWhat it is
pointvectorNeeded.
Returns
vector?
Fails
  • a value of the wrong type

To drop a grenade onto the floor below a player

Section titled “To drop a grenade onto the floor below a player”
local floor = ground(p.position + vector.create(0, 2, 0))
if floor then
model("grenade", { at = floor })
end