HOOZiDocs
Skip to content

math

Extends the Lua stdlib (does not override sin/cos/pi/floor/random/...); adds extra functions to the math table.


Vector Types

math.Vec2(x, y) → Vec2

math.Vec3(x, y, z) → Vec3

Note: CamelCase Vec2/Vec3, not vec2/vec3 (lowercase vec2 is a different internal type).

Vec2 / Vec3 Fields and Operators

Fields: .x / .y / .z (Vec3 only)

Supported meta-operators (work in both directions, operand order doesn't matter):

OperationBehavior
a + bPer-component addition
a - bPer-component subtraction
v * scalarScalar multiplication
v / scalarScalar division
-vNegate
tostring(v)Text form, e.g. Vec3(1.000, 2.000, 3.000)

Instance methods:

MethodReturnsDescription
v:length()numberMagnitude
v:length_2d() (Vec3 only)numberXY-plane magnitude
v:length_sq()numberSquared magnitude (avoids sqrt)
v:dot(other)numberDot product
v:cross(other) (Vec3 only)Vec3Cross product
v:dist(other)numberDistance
v:dist_2d(other) (Vec3 only)numberXY-plane distance
v:to_2d() (Vec3 only)Vec2Projects to Vec2 (x, y)
v:normalize()new VecIn-place normalize, but sol2 returns a copy of the updated value (not a self reference). Chains like v:normalize():length() do not see the original v
v:normalized()new VecCopy then normalize; original v unchanged

Scalar Operations

math.Lerp(a, b, t) → number

Linear interpolation. t is not clamped; extrapolation is legal (user's responsibility).

math.Clamp(x, lo, hi) → number

math.Smoothstep(edge0, edge1, x) → number

Hermite interpolation; input x within [edge0, edge1] smoothly transitions to [0, 1], saturating at both ends.

math.RemapVal(val, a, b, c, d) → number

Linear remap: val is mapped from [a, b] onto [c, d]. No clamping (values outside [a, b] extrapolate).

math.RemapValClamped(val, a, b, c, d) → number

Same as RemapVal, but val is saturated to [a, b] first (out-of-range inputs clamp to the endpoints).

lua
-- Map hp 0..100 to saturation 0.2..1.0
local sat = math.RemapValClamped(hp, 0, 100, 0.2, 1.0)

math.AngleNormalize(angle_deg) → number

Normalizes an arbitrary degree value into [-180, 180).


Angles / Projection

math.CalcAngle(from_pos, to_pos) → pitch, yaw

Two Vec3 → (pitch, yaw) in degrees; pitch is negative pointing up.

math.WorldToScreen(world_pos) → sx, sy, ok

Three return values; when ok=false, sx/sy are meaningless (out-of-game / off-screen / view matrix not ready).


Big-map coordinates

Built-in calibration table covers every official map (Storm Point / World's Edge / Kings Canyon / Olympus / Broken Moon ...). Scripts don't need to maintain their own scale tables.

math.WorldToMapPixel(wx, wy, disp_w, disp_h) → px, py, ok

World (wx, wy) → big-map PNG pixel position on a (disp_w, disp_h) canvas.

  • ok = false: lobby / unknown map / not in-game → (px, py) falls back to canvas center
  • Scale-independent (uses 4-corner calibration); disp scaling follows the canvas size

math.WorldRadiusToMapPixel(r_world, disp_size) → r_pixel, ok

World-inch radius → big-map pixel radius. disp_size is typically the canvas short edge (same-direction scaling avoids ellipse distortion).

  • For death rings, blast radii, marker circles, etc.
  • ok = false returns 0
lua
event.on("frame_update", function()
    -- Custom mini radar canvas: top-left 200x200
    for _, p in pairs(game.entities.players) do
        if not p.is_teammate then
            local px, py, ok = math.WorldToMapPixel(p.origin.x, p.origin.y, 200, 200)
            if ok then
                draw.circle(px, py, 3, draw.rgba(1, 0.2, 0.2, 1), { filled = true })
            end
        end
    end

    -- Death-ring radius
    local rp, ok = math.WorldRadiusToMapPixel(ring_radius_world, 200)
    if ok then
        draw.circle(100, 100, rp, draw.rgba(0.4, 0.7, 1, 0.6), { thickness = 2 })
    end
end)

Animation Curves

All ease_* take t : number (auto-clamped to [0, 1]) and return [0, 1].

FunctionCurveUse case
math.ease_in(t) slow start, fast finishFade in / starting from rest
math.ease_out(t)1-(1-t)² fast start, slow finishDeceleration to stop / popup toast
math.ease_in_out(t)cosine, bidirectionalGeneral-purpose smoothing
math.ease_in_cubic(t) more dramatic slow startHigh-contrast acceleration
math.ease_out_cubic(t)1-(1-t)³ more dramatic fast-then-slowHigh-contrast deceleration
math.ease_bounce(t)Bounces at the endElastic appearance / notification jitter

Example

lua
-- Vector arithmetic
local lp = game.localplayer
local p  = game.entities.players  -- assume targets exist
for _, enemy in pairs(p) do
    if not enemy.is_teammate then
        local delta = enemy.origin - lp.origin
        print("Enemy distance:", delta:length(), "meters")
        local angle_deg = math.CalcAngle(lp.camera_origin, enemy.head_pos)
    end
end

-- Screen projection
event.on("frame_update", function(e)
    for _, p in pairs(game.entities.players) do
        if not p.is_teammate and p.head_pos then
            local sx, sy, ok = math.WorldToScreen(p.head_pos)
            if ok then
                draw.circle(sx, sy, 3, draw.rgba(1, 0, 0, 1), { filled = true })
            end
        end
    end
end)

-- Easing animation: notify pops up 0..100% opacity over 0.5s
local start_t = time.now()
event.on("frame_update", function(e)
    local elapsed = time.now() - start_t
    local progress = math.Clamp(elapsed / 0.5, 0, 1)
    local alpha = math.ease_out_cubic(progress)
    -- Use alpha to draw the toast
end)