Value types
The vector, vector2d, vector4d, angle and color FFI value types: constructors, methods, operators, pointers, containers, 64-bit integers and angle maths.
Value type overview
| Value | Constructor | Fields |
|---|---|---|
| 3D vector | vector | x, y, z |
| 2D vector | vector2d | x, y |
| 4D vector | vector4d | x, y, z, w |
| Angle | angle | pitch, yaw, roll; aliases x, y, z |
| Colour | color | r, g, b, a |
These five LuaJIT FFI types are the only value types; their Lua type is cdata. Every API function that returns a vector, angle or colour returns a new copy of one of them, including entity fields, traces, hitboxes, render.screen_size, input.mouse_position, cmd.view_angles and console.variable:get for colours. Modifying a returned copy does not change game state. Only view.origin and view.angles return pointers into game memory.
Vector and angle components use 32-bit floats. Assigning 0.1 may read back as 0.10000000149011612; compare with a tolerance.
local b = a shares the same object. Use a constructor to copy: vector(a).
FFI value types
Constructors
vector(x?, y?, z?)
vector2d(x?, y?)
vector4d(x?, y?, z?, w?)
angle(pitch?, yaw?, roll?)
color(r?, g?, b?, a?)Missing vector and angle components default to 0. In numeric colour construction, RGB channels default to 0 and alpha to 255.
Vector constructors also accept tables and compatible values:
vector{ x = 1, y = 2, z = 3 }
vector{ 1, 2, 3 }
vector(existing_value)
color{ r = 255, g = 0, b = 0, a = 255 }
color(existing_colour)- Table components default to
0. Forcolor, this includes alpha. - The
angletable constructor acceptsx,y,z, notpitch,yaw,roll. - Copies use matching fields.
vector(v)accepts an FFI vector, a vector pointer or another value withx,y,z, including an angle. - Colour channels are not clamped by FFI construction; values outside
0..255wrap.
Methods
In the following table, vector dimensions identify the applicable types. Method arguments accept the values listed under Argument conversion, including tables.
| Method | Available on | Result |
|---|---|---|
unpack() | All value types | Components as separate returns. |
length(), lengthsqr() | Vectors and angle | Number. |
length_sqr() | 2D and 3D vectors | Alias of lengthsqr. |
length2d(), length_2d() | 3D vector | XY length. |
length2dsqr(), length_2d_sqr() | 3D vector | Squared XY length. |
dot(b) | All vectors | Dot product. |
dist(b), distsqr(b) | All vectors | Distance or squared distance. |
dist_to(b) | 3D vector | Alias of dist. |
dist2d(b), dist_to_2d(b), dist2dsqr(b) | 3D vector | XY distance or squared XY distance. |
cross(b) | All vectors | 3D vector for 3D input; number for 2D and 4D input. |
lerp(b, t) | All vectors and colour | New value of the same type; t is required. Colour channels are rounded and clamped. |
normalized() | 2D/3D vectors and angle | New normalized value; zero vectors remain zero, angle components use [-180, 180). |
normalize() | 3D vector and angle | Normalizes in place and returns the same value. |
to(b) | 3D vector | Unit vector from this point to b. |
to_angle() | 3D vector | Direction angle; pitch [-90, 90], yaw (-180, 180]. |
forward() | Angle | Forward vector. |
left_vectors() | 3D vector | Left and up vectors. |
left_vectors() | Angle | Forward, left and up vectors. |
right_vectors() | 3D vector | Right and up vectors. |
right_vectors() | Angle | Forward, right and up vectors. |
is_valid() | Vectors and angle | Whether all components are finite. |
is_zero(tolerance?) | All vectors | Whether every absolute component is below tolerance; default 0.01. |
hex() | Colour | "RRGGBBAA". |
vector4d:cross(b) returns a.x*b.y - a.y*b.x - a.z*b.z - a.w*b.w. This is compatibility behaviour, not a geometric cross product.
Operators
For FFI vectors and angles:
| Expression | Behaviour |
|---|---|
a + b, a - b | Componentwise with a compatible value, pointer or named table. A numeric operand raises. |
a * b | Componentwise, or scalar multiplication with the number on either side. |
a / b | Componentwise, or division by a number on the right. |
-a | New negated value. |
a == b | Exact component comparison, only for the same FFI kind. Other kinds return false. |
color supports only equality and string conversion. FFI value types do not provide <, # or concatenation.
String representations include vector(1.000000, 2.000000, 3.000000), vector2d(...), vector4d(...), angle(...) and color(255, 0, 0, 255).
For angles, a.pitch = 10 writes a.x. Assigning an unknown field raises 'angle' has no member named '<key>'.
FFI pointers
view.origin is a vector* into game memory. Field access, methods, string conversion and equality operate on the pointed-to value, but p + v uses C pointer arithmetic. Copy before vector arithmetic:
local origin = vector(view.origin)The C types vector, vector2d, vector4d, angle and color are declared in every script. They may be used in ffi.cast and declarations, but cannot be redefined with ffi.cdef.
Containers
Entity fields may expose live game arrays as utl_vector_bool, utl_vector_int, utl_vector_uint32_t, utl_vector_float, utl_vector_vec3_t or utl_vector_angle_t. Changes write directly into game memory.
| Operation | Behaviour |
|---|---|
#v | Element count. |
v[i] | One-based access; nil outside the valid range. |
v[i] = value | Replaces an existing element; out-of-range writes are ignored. |
v:push_back(value) | Appends and returns the new index. |
v:remove_at(i) | Removes the element and shifts later elements. |
v:clear() | Removes all elements. |
v:ipairs() | Iterator for for i, value in v:ipairs() do ... end. |
Vector and angle elements are vector and angle copies. v[1].x = 5 does not update the array; assign v[1] = vector(...) instead.
Do not confuse these one-based containers with schema array_t, which is zero-based.
64-bit integers
int64_t and uint64_t are LuaJIT cdata used for command button masks and cvar flags.
local bit = require 'bit'
local mask = bit.lshift(1ULL, 33)
local all_bits = -1LLArithmetic and comparison with Lua numbers are supported. LuaJIT has no << operator; use bit.lshift, bit.band and bit.bor with 64-bit cdata when needed. Operations on ordinary numbers use the bit library's 32-bit behaviour.
tostring(1ULL) returns "1ULL". tonumber converts to a double, with exact integer representation only up to 2^53.
Angle maths
The standard math table has no additions; angle maths is done with vector and angle methods. vector:to_angle() returns pitch in [-90, 90] and yaw in (-180, 180], with (-90, 0, 0) / (90, 0, 0) for a vector pointing straight up / down. angle:normalized() wraps every component, roll included, into [-180, 180).
local aim = (target - eye):to_angle() -- angle from eye to target
local forward, right, up = view:right_vectors() -- basis of an angle
local d = (aim - view):normalized() -- field of view between two angles
local fov = math.sqrt(d.pitch * d.pitch + d.yaw * d.yaw)